;;; -*- Mode: Common-Lisp; Package: System-internals; Base: 10.; Patch-File: T -*-

;;; Reason: Recompile the serial code to fix a build problem.

;;;                           RESTRICTED RIGHTS LEGEND
;;;
;;; Use, duplication, or disclosure by the Government is subject to
;;; restrictions as set forth in subdivision (c)(1)(ii) of the Rights in
;;; Technical Data and Computer Software clause at 52.227-7013.
;;;
;;;   TEXAS INSTRUMENTS INCORPORATED      
;;;   P.O. BOX 2909, M/S 2151             
;;;   AUSTIN, TEXAS 78769                 
;;;
;;; Copyright (C) 1989 Texas Instruments Incorporated.
;;; All rights reserved.

;;; Written 07/11/89 14:44:24 by jones,
;;; while running on HOBBS from band p616
;;; With SYSTEM 6.10, GC 6.3, VIRTUAL-MEMORY 6.1, MICRONET 6.0, MICRONET-COMM 6.1,
;;;  DISK-IO 6.0, DISK-LABEL 6.0, BASIC-PATHNAME 6.1, MAC-PATHNAME 6.0, NETWORK-SUPPORT-COLD 6.0,
;;;  BASIC-NAMESPACE 6.1, BASIC-FILE 6.2, RPC 6.1, NFS 6.0, EH 6.3, MAKE-SYSTEM 6.0,
;;;  MEMORY-AUX 6.0, COMPILER 6.7, TV 6.12, NVRAM 6.1, UCL 6.0, INPUT-EDITOR 6.0,
;;;  Inconsistent MACTOOLBOX 2.4, METER 6.1, ZWEI 6.3, DEBUG-TOOLS 6.3, WINDOW-MX 6.5,
;;;  PRINTER 6.3, MAC-PRINTER-TYPES 6.1, Inconsistent CLIPBOARD 6.1, NETWORK-PATHNAME 6.0,
;;;  NETWORK-NAMESPACE 6.0, DATALINK 6.0, CHAOSNET 6.0, NETWORK-SUPPORT 6.0, NETWORK-SERVICE 6.1,
;;;  DATALINK-DISPLAYS 6.0, MX-DATALINK 6.1, NAMESPACE-EDITOR 6.0, IP 3.47, NFS-SERVER 6.0,
;;;  MX-SERIAL 6.0, PRINTER-TYPES 6.1, IMAGEN 6.0, MAIL-DAEMON 6.2, MAIL-READER 6.1,
;;;  TELNET 6.0, VT100 6.0, STREAMER-TAPE 6.4, DECNET 1.69, VISIDOC 6.2, PROFILE 6.1,
;;;  TI-CLOS 6.11, CLEH 6.4, Experimental CLX 6.2, CLUE 6.9, Experimental BUG 11.10,
;;;  Experimental ACTION 2.0, Experimental KERMIT 1.0,  microcode 138, Band Name: p616*2


#!C
; From file MX-SERIAL-STREAM.LISP#> SERIAL; MR-X:
#10R SYSTEM#:
(COMPILER-LET ((*PACKAGE* (FIND-PACKAGE "SYSTEM"))
                          (SI:*LISP-MODE* :Common-lisp)
                          (*READTABLE* Common-lisp-readtable)
                          (SI:*READER-SYMBOL-SUBSTITUTIONS* *common-lisp-symbol-substitutions*))
  (COMPILER#:PATCH-SOURCE-FILE "SYS: SERIAL; MX-SERIAL-STREAM.#"



;;; Originally the serial-stream flavor for the EXPLORER; this code is being
;;; modified for the Micro-Explorer by Hank Ivy on 9/28/88
;;; for the serial modem port, aka. port A,
;;; and the serial printer port, aka. port B
;;; NOTE: MAC driver       driver name      reference number, aka refNum
;;;  Modem Port Input      .AIn                -6
;;;  Modem Port Output     .AOut               -7
;;;  Printer Port Input    .BIn                -8
;;;  Printer Port Output   .BOut               -9

(comment explorer code
	 ;;; Stream support for the explorer RS232.
	 ;;; This code uses the following system variables:
	 ;;;   *Serial-Port*          - The device descriptor for the serial port
	 ;;;   *Serial-Input-Buffer*  - the input buffer where microcode places incomming characters
	 ;;;   *Serial-Output-Buffer* - the output buffer where the microcode gets characters to go out
	 )
(defparameter *SERIAL-PORT-A-OWNER* ()
  "normally the stream that is currently active on the port A.")

(defparameter *SERIAL-PORT-B-OWNER* ()
  "normally the stream that is currently active on the port B.")

(defparameter *MICRO-EXPLORER-SERIAL-PORT-ALIST*
	      '(("A" ".AIn" -6 ".AOut" -7 *serial-port-a-owner*)
		("B" ".BIn" -8 ".BOut" -9 *serial-port-b-owner*)
		)
  "This a-list can be used to map the port letter to MACintosh driver names and reference numbers."
  )

(defparameter *SERIAL-MAC-BAUD-LIST*
	      '((300. 380.) (600. 189.) (1200. 94.) (1800. 62.)
		(2400. 46.) (3600. 30.) (4800. 22.) (7200. 14.)
		(9600. 10.) (19200. 4.) (57600. 0.))
  "This is a list of the valid baud rates
   and the integer value to use in resetting the serial port on the MAC.")

(defparameter *SERIAL-MAC-STOP-BITS-LIST*
	      '((1 16384.) (3/2 -32768.) (2 -16384))
  "This is a list of the valid stop bit values
   and the integer value to use in resetting the serial port on the MAC.")

(defparameter *SERIAL-MAC-PARITY-LIST*
	      '((() 0) (:none 0) (:even 12288.) (:odd 4096.))
  "This is a list of the valid parity values [nil is treated as :none]
   and the integer value to use in resetting the serial port on the MAC.")

(defparameter *SERIAL-MAC-DATA-BITS-LIST*
	      '((5 0) (6 2048.) (7 1024.) (8 3072.))
  "This is a list of the valid number of data bits and the integer value to use in resetting the serial port on the MAC.")

(defun GET-PORT-OWNER-SYMBOL (port-chr)
  "given a port-chr as a single letter or keyword, returns the port owner symbol in the Explorer."
  (let ((port-data-list (find port-chr *micro-explorer-serial-port-alist* :test #'string-equal :key #'car)))
    (sixth port-data-list)
    )
  )

(defun GET-PORT-OWNER (port-chr)
  "given a port-chr as a single letter or keyword, returns the port owner in the Explorer."
  (eval (get-port-owner-symbol port-chr))
  )

(defconstant EOT-CHARACTER #o4)     ;need a good place for these constants !

(comment explorer code
	 (defparameter xon-character #o21) 
	 )


(defun MAKE-SERIAL-STREAM (&rest keywords)
  "Make a stream that talks over a Micro-explorer serial port A or B.
Keywords are:
:FLAVOR                 -- flavor name to make this stream an instance of
:ASCII-CHARACTERS       -- T enables translation between Ascii and Lisp machine character sets
:XON-XOFF-PROTOCOL      -- T enables XONXOFF (^S^Q) control of output
:EOT-ENABLE             -- T enables special processing of the EOT (04) character (NIL by default)
:INPUT-BUFFER-SIZE      -- default buffer size is 256. words (1 page)
:OUTPUT-BUFFER-SIZE
:FORCE-OUTPUT           -- NIL means you must :FORCE-OUTPUT to cause transmission,
                           NIL (the default) means an automatic :FORCE-OUTPUT occurs after :TYO
                           It is recommended that :FORCE-OUTPUT be T with the TI855 printer.
:NUMBER-OF-DATA-BITS    -- 5, 7, 6, or 8 (default 8)
:NUMBER-OF-RX-DATA-BITS -- Use :NUMBER-OF-DATA-BITS  -  the Z8530 chip allows you to do these seperately
:NUMBER-OF-TX-DATA-BITS -- Use :NUMBER-OF-DATA-BITS  -  this is not recommended
:NUMBER-OF-STOP-BITS    -- default 2,  (1 and 1.5 are also supported ??? what values?)
:PARITY                 -- init keywords are ':none ':even ':odd (default is ':none)
:BAUD                   -- baud rate (default 4800.)
                        -- (also 300, 600, 1200, 1800, 2400, 3600, 4800, 7200,
                        --       9600, 19200, 57600)

:DATA-TERMINAL-READY    -- (unknown support) NIL disables DTR output - default is true
:REQUEST-TO-SEND        -- (unknown support) NIL disables RTS output - default is true

:CHECK-FRAMING-ERRORS   -- (unknown support) NIL disables error if break received
:CHECK-OVER-RUN-ERRORS  -- (unknown support) NIL disables error if input characters lost in UART
:CHECK-PARITY-ERRORS    -- (unknown support) NIL disables error if wrong parity

:PORT                   -- may be single character, character string, symbol, or keyword; :A or :B

"
  (declare
    (arglist &key &optional flavor ascii-characters xon-xoff-protocol force-output eot-enable
	     number-of-data-bits number-of-rx-data-bits number-of-tx-data-bits
	     number-of-stop-bits parity baud data-terminal-ready request-to-send
	     input-buffer-size output-buffer-size check-framing-errors check-over-run-errors
	     check-parity-errors port))
  (if (get-port-owner (getf keywords :port))	       ;somebody already has the port ?
      (progn
	(cerror "Close Existing Stream and Open New Stream"
		"Attempt to open a Serial Stream on Port already in use by: ~a "
		(get-port-owner (getf keywords :port)))
	;; user wants to proceed - close the old stream and start the new one
	(send (get-port-owner (getf keywords :port)) :close)))
  (instantiate-flavor
    (or (getf keywords :flavor)			       ;user specified flavor or ...
	(if (getf keywords :ascii-characters)
	    'serial-ascii-stream
	    'serial-stream))
    (locf keywords) t)) 

;;; Flavor definitions
;;; This used to use the basic-buffered-output-stream flavor but it did a 
;;; lot of stuff we don't really need so I took it out. -- JSL


(defflavor SERIAL-STREAM-MIXIN
	   (
	    (tb:*application-channel* 8) ; Bind this so that all toolbox calls will be handled in the mx driver.
	    ;; integer for serial driver control  computed from baud, stop-bits, parity, and data bits.
	    (serial-configuration-int 0)
	    ;; MAC input dev driver name ".AIn"  typical value see *micro-explorer-serial-port-alist*
	    input-mac-driver-name      
	    ;; MAC output dev driver name ".AOut" typical value see *micro-explorer-serial-port-alist*
	    output-mac-driver-name     
	    ;; MAC input dev reference number -6 typical value see *micro-explorer-serial-port-alist*
	    input-mac-reference-number 
	    ;; MAC output dev reference number -7 typical value see *micro-explorer-serial-port-alist*
	    output-mac-reference-number
	    (force-output nil)
	    (eot-enable nil)
	    (serial-error-mask 7)		       ;error checking on as default
	    (serial-untyi-ch nil)
	    (parity :none)
	    (baud 300.)
	    (port :a)				       ; default to modem port A
	    (serial-port-eot-received-p nil)
	    (number-of-stop-bits 2)
	    (xon-xoff-protocol nil)
	    (check-framing-errors t)
	    (check-over-run-errors t)
	    (check-parity-errors t)
	    (number-of-data-bits 8)
	    (number-of-tx-data-bits 8)
	    (number-of-rx-data-bits 8)
	    mx-heap-zone
	    
	    mac-driver-input-buffer		       ; The buffer that the mac serial driver uses 
	    
	    (input-buffer-size page-size)
	    stream-input-buffer
	    (stream-input-index 0)
	    (stream-input-limit 0)
	    parm-block-in

	    backup-input-buffer
	    
	    (stream-output-limit page-size)
	    stream-output-buffer
	    (stream-output-index 0)
	    parm-block-out
	    
	    serial-status-record
	    (read-issued-p)
	    (closed-p t))			       ;signal stream is not open for I/O
	   ()
  (:special-instance-variables tb:*application-channel*)
  (:required-flavors bidirectional-stream character-stream)
  (:initable-instance-variables serial-untyi-ch force-output eot-enable input-buffer-size
				stream-output-limit number-of-data-bits parity number-of-stop-bits port)
  (:init-keywords :ascii-characters :force-output :eot-enable
		  :request-to-send :data-terminal-ready :receive-enable :transmit-enable
		  :input-buffer-size :output-buffer-size :flavor :baud
		  :xon-xoff-protocol :ascii-characters :force-output :eot-enable
		  :number-of-data-bits :number-of-tx-data-bits :number-of-rx-data-bits :number-of-stop-bits
		  :parity :baud :request-to-send :data-terminal-ready :receive-enable :transmit-enable
		  :input-buffer-size :output-buffer-size :check-framing-errors :check-over-run-errors
		  :check-parity-errors :flavor)
  (:documentation :mixin "The guts of RS232 Serial I/O Streams")) 


(defflavor SERIAL-STREAM
	   ()
	   (serial-stream-mixin
	    bidirectional-stream
	    character-stream
	    buffered-line-input-stream)
  (:documentation :combination "RS232 Serial I/O Stream, no character-set translation")) 


(defflavor SERIAL-CHARACTER-STREAM
	   ()
	   (serial-ascii-stream))		       ;compatibility


(defflavor SERIAL-ASCII-STREAM
	   ((suppress-output-mapping)
	    (suppress-input-mapping ))
	   (serial-stream)
  (:documentation :combination "RS232 Serial I/O Stream, Ascii character translation")) 


;;; The ascii-translating-input-stream-mixin expects the return character to be sent as a <CR><LF> 
;;; combination, a throw back to the TELNET protocol.  Host systems using serial streams
;;; are not required to send <CR><LF>.  Thus the standard input ascii translating can
;;; hang a serial stream by waiting for the <LF> character which never is sent. 

;;; The Ascii to Explorer mapping table only does the following translation :
;;;	ASCII-BS  -->   #\BACKSPACE
;;;	ASCII-TAB -->   #\TAB
;;;     ASCII-LF  -->   #\LINEFEED
;;;     ASCII-CR  -->   #\NEWLINE
;;;	ASCII-FF  -->   #\PAGE
;;;	ASCII-DEL -->   #\RUBOUT
(DEFPARAMETER *Ascii-to-Explorer-char-map*
	      (MAKE-ARRAY
		256. :area  permanent-storage-area
		:initial-contents
;;;             0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
	(LIST #x00 #x01 #x02 #x03 #x04 #x05 #x06 #x07 #x88 #x89 #x8a #x0B #x8C #x8D #x0E #x0F   ;0
	      #x10 #x11 #x12 #x13 #x14 #x15 #x16 #x17 #x18 #x19 #x1A #x1B #x1C #x1D #x1E #x1F   ;1
	      #x20 #x21 #x22 #x23 #x24 #x25 #x26 #x27 #x28 #x29 #x2A #x2B #x2C #x2D #x2E #x2F   ;2
	      #x30 #x31 #x32 #x33 #x34 #x35 #x36 #x37 #x38 #x39 #x3A #x3B #x3C #x3D #x3E #x3F   ;3
	      #x40 #x41 #x42 #x43 #x44 #x45 #x46 #x47 #x48 #x49 #x4A #x4B #x4C #x4D #x4E #x4F   ;4
	      #x50 #x51 #x52 #x53 #x54 #x55 #x56 #x57 #x58 #x59 #x5A #x5B #x5C #x5D #x5E #x5F   ;5
	      #x60 #x61 #x62 #x63 #x64 #x65 #x66 #x67 #x68 #x69 #x6A #x6B #x6C #x6D #x6E #x6F   ;6
	      #x70 #x71 #x72 #x73 #x74 #x75 #x76 #x77 #x78 #x79 #x7A #x7B #x7C #x7D #x7E #x87   ;7
	      #x80 #x81 #x82 #x83 #x84 #x85 #x86 #x7F #x08 #x09 #x0A #x8B #x0C #x0A #x8E #x8F   ;8
	      #x90 #x91 #x92 #x93 #x94 #x95 #x96 #x97 #x98 #x99 #x9A #x9B #x9C #x9D #x9E #x9F   ;9
	      #xA0 #xA1 #xA2 #xA3 #xA4 #xA5 #xA6 #xA7 #xA8 #xA9 #xAA #xAB #xAC #xAD #xAE #xAF   ;A
	      #xB0 #xB1 #xB2 #xB3 #xB4 #xB5 #xB6 #xB7 #xB8 #xB9 #xBA #xBB #xBC #xBD #xBE #xBF   ;B
	      #xC0 #xC1 #xC2 #xC3 #xC4 #xC5 #xC6 #xC7 #xC8 #xC9 #xCA #xCB #xCC #xCD #xCE #xCF   ;C
	      #xD0 #xD1 #xD2 #xD3 #xD4 #xD5 #xD6 #xD7 #xD8 #xD9 #xDA #xDB #xDC #xDD #xDE #xDF   ;D
	      #xE0 #xE1 #xE2 #xE3 #xE4 #xE5 #xE6 #xE7 #xE8 #xE9 #xEA #xEB #xEC #xED #xEE #xEF   ;E
	      #xF0 #xF1 #xF2 #xF3 #xF4 #xF5 #xF6 #xF7 #xF8 #xF9 #xFA #xFB #xFC #xFD #xFE #xFF)) ;F
  )

;;; The Explorer to Ascii mapping table only does the following translation :
;;;        #\RETURN      -->    ASCII-LF   
;;;	#\TAB          -->    ASCII-TAB  
;;;	#\PAGE         -->    ASCII-FF   
;;;	#\LINEFEED   -->    ASCII-LF
;;;	#\BACKSPACE  -->    ASCII-BS
;;;	#\RUBOUT      -->    ASCII-DEL   
(DEFPARAMETER *Explorer-to-Ascii-char-map*
	      (MAKE-ARRAY
		256. :area  permanent-storage-area
		:initial-contents
;;;             0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
	(LIST #x00 #x01 #x02 #x03 #x04 #x05 #x06 #x07 #x88 #x89 #x8D #x0B #x8C #x8D #x0E #x0F   ;0
	      #x10 #x11 #x12 #x13 #x14 #x15 #x16 #x17 #x18 #x19 #x1A #x1B #x1C #x1D #x1E #x1F   ;1
	      #x20 #x21 #x22 #x23 #x24 #x25 #x26 #x27 #x28 #x29 #x2A #x2B #x2C #x2D #x2E #x2F   ;2
	      #x30 #x31 #x32 #x33 #x34 #x35 #x36 #x37 #x38 #x39 #x3A #x3B #x3C #x3D #x3E #x3F   ;3
	      #x40 #x41 #x42 #x43 #x44 #x45 #x46 #x47 #x48 #x49 #x4A #x4B #x4C #x4D #x4E #x4F   ;4
	      #x50 #x51 #x52 #x53 #x54 #x55 #x56 #x57 #x58 #x59 #x5A #x5B #x5C #x5D #x5E #x5F   ;5
	      #x60 #x61 #x62 #x63 #x64 #x65 #x66 #x67 #x68 #x69 #x6A #x6B #x6C #x6D #x6E #x6F   ;6
	      #x70 #x71 #x72 #x73 #x74 #x75 #x76 #x77 #x78 #x79 #x7A #x7B #x7C #x7D #x7E #x87   ;7
	      #x80 #x81 #x82 #x83 #x84 #x85 #x86 #x7F #x08 #x09 #x0A #x8B #x0C #x0D #x8E #x8F   ;8
	      #x90 #x91 #x92 #x93 #x94 #x95 #x96 #x97 #x98 #x99 #x9A #x9B #x9C #x9D #x9E #x9F   ;9
	      #xA0 #xA1 #xA2 #xA3 #xA4 #xA5 #xA6 #xA7 #xA8 #xA9 #xAA #xAB #xAC #xAD #xAE #xAF   ;A
	      #xB0 #xB1 #xB2 #xB3 #xB4 #xB5 #xB6 #xB7 #xB8 #xB9 #xBA #xBB #xBC #xBD #xBE #xBF   ;B
	      #xC0 #xC1 #xC2 #xC3 #xC4 #xC5 #xC6 #xC7 #xC8 #xC9 #xCA #xCB #xCC #xCD #xCE #xCF   ;C
	      #xD0 #xD1 #xD2 #xD3 #xD4 #xD5 #xD6 #xD7 #xD8 #xD9 #xDA #xDB #xDC #xDD #xDE #xDF   ;D
	      #xE0 #xE1 #xE2 #xE3 #xE4 #xE5 #xE6 #xE7 #xE8 #xE9 #xEA #xEB #xEC #xED #xEE #xEF   ;E
	      #xF0 #xF1 #xF2 #xF3 #xF4 #xF5 #xF6 #xF7 #xF8 #xF9 #xFA #xFB #xFC #xFD #xFE #xFF)) ;F
)

(defmethod (serial-ascii-stream :ascii-to-exp) ()
  "Translate the current input buffer to the Explorer character set."
  (unless suppress-input-mapping
    (without-interrupts
      (si:%buffer-char-map stream-input-buffer stream-input-index stream-input-limit
			   stream-input-buffer stream-input-index stream-input-limit
			   *Ascii-to-Explorer-char-map* #xff 0))))

(defmethod (serial-ascii-stream :exp-to-ascii) ()
  "Translate the current output buffer to ASCII."
  (unless suppress-output-mapping
    (without-interrupts
      (si:%buffer-char-map stream-output-buffer stream-output-index stream-output-limit
			   stream-output-buffer stream-output-index stream-output-limit
			   *Explorer-to-Ascii-char-map* #xff 0))))

(defmethod (serial-ascii-stream :suppress-output-mapping) ()
  "Temporarily turn off character mapping on output."
  (send self :force-output)
  (setf suppress-output-mapping t))

(defmethod (serial-ascii-stream :restart-output-mapping) ()
  "Turn character mapping back on for output."
  (send self :force-output)
  (setf suppress-output-mapping nil))

(defmethod (serial-ascii-stream :suppress-input-mapping) ()
  "Temporarily turn off character mapping on input."
  (without-interrupts
      (si:%buffer-char-map stream-input-buffer stream-input-index stream-input-limit
			   stream-input-buffer stream-input-index stream-input-limit
			   *Explorer-to-Ascii-char-map* #xff 0))
  (setf suppress-output-mapping t))

(defmethod (serial-ascii-stream :restart-input-mapping) ()
  "Turn character mapping back on for input."
  (without-interrupts
      (si:%buffer-char-map stream-input-buffer stream-input-index stream-input-limit
			   stream-input-buffer stream-input-index stream-input-limit
			   *Ascii-to-Explorer-char-map* #xff 0))
  (setf suppress-input-mapping nil))
	   

;;; Housekeeping methods


(defmethod (SERIAL-STREAM-MIXIN :INIT) (init-plist)
  (let ((port-owner (get-port-owner port)))
    
    (when (and port-owner			       ;somebody already has the port ?
	       (not (eq port-owner self)))	       ;and its not us
      (cerror "Close Existing Stream and Initialize New Stream"
	      "Attempt to Initialize Serial Stream: ~a on Serial Port already in use by: ~a "
	      self port-owner)
      ;; user wants to proceed - close the old stream and start the new one
      (send port-owner :close))
    
    (loop for (kwd val) on (cdr init-plist) by 'cddr unless
	  (member kwd '(:flavor :ascii-characters) :test #'eq) do
	  (errset (send self :put kwd val) ()))
    (send self :reset))) 

(defmacro WITH-PARM-BLOCK ((parm-block asyncp) &body body)
  (cond (asyncp
	 
	 `(progn
	    (without-interrupts
	      (when (eql (send ,parm-block :ioresult) 1)
		(process-wait "Wait For Input Block"
			      #'(lambda (parm-block)
				  (not (eql (send parm-block :ioresult) 1)))
			      ,parm-block))
	      (setf (send ,parm-block :ioresult) 1))
	    ,@body))
	(t
	 `(unwind-protect
	      (progn
		(without-interrupts
		  (when (eql (send ,parm-block :ioresult) 1)
		    (process-wait "Wait For Input Block"
				  #'(lambda (parm-block)
				      (not (eql (send parm-block :ioresult) 1)))
				  ,parm-block))
		  (setf (send ,parm-block :ioresult) 1))
		,@body)
	    (setf (send ,parm-block :ioresult) 0)))))


(defmethod (SERIAL-STREAM-MIXIN :HEAP-ZONE-SIZE) ()
  (+ stream-output-limit
     input-buffer-size
     (get 'tb:SerStaRec 'tb:obsize)
     (* 2 (+ (get 'tb:ioparam 'tb:obsize) 4))
     (get 'tb:sershk 'tb:obsize) 4))

(defmethod (SERIAL-STREAM-MIXIN :RESET) (&optional (abort-output ':abort))
  "This method verifies the parameters in self,
   Opens the serial port on the MAC side using the Expertelligence Toolbox,
   and resets the hardware."
  ;;; verify the parameters in self.
  (let ((baud-entry (find baud *serial-mac-baud-list* :key #'car :test #'equalp))
	(stop-bit-entry (find number-of-stop-bits *serial-mac-stop-bits-list* :key #'car :test #'equalp))
	(parity-entry (find parity *serial-mac-parity-list* :key #'car :test #'equalp))
	(data-bits-entry (find number-of-data-bits *serial-mac-data-bits-list* :key #'car :test #'equalp))
	(port-entry (find port *micro-explorer-serial-port-alist* :key #'car :test #'string-equal))
	(port-owner (get-port-owner port))
	mysershk)
    
    (unless baud-entry
      (ferror nil "Baud rate ~a is invalid" baud))
    
    (unless stop-bit-entry
      (ferror nil "Number of stop bits ~a is invalid" number-of-stop-bits))
    
    (unless parity-entry
      (ferror nil "Parity ~a is invalid" parity))
    
    (unless port-entry
      (ferror nil "Port ~a is invalid" port))
    
    (unless (= number-of-data-bits number-of-tx-data-bits number-of-rx-data-bits)
      (ferror nil "The MAC does not support a different number of receive ~a and transmit ~a data bits."
	      number-of-rx-data-bits number-of-tx-data-bits))
    
    (unless data-bits-entry
      (ferror nil "The number of data bits ~a is not valid." number-of-data-bits))
    
    ;; can only reset the current holder of the port
    (when (and port-owner			       ;somebody already has the port ?
	       (not (eq port-owner self)))	       ;and its not us
      (cerror "Close Existing Stream and Initialize New Stream"
	      "Attempt to Initialize Serial Stream: ~a on Serial Port already in use by: ~a "
	      self port-owner)
      ;; user wants to proceed - close the old stream and start the new one
      (send port-owner :close))
    
    (setf input-mac-driver-name (second port-entry)
	  input-mac-reference-number (third port-entry)
	  output-mac-driver-name (fourth port-entry)
	  output-mac-reference-number (fifth port-entry))
    
    (unless (eq port-owner self)
      (send self :close abort-output))		       ;Forget about any remaining output characters
    
    
    (setf mx-heap-zone (tb:make-mx-heap-zone (send self :heap-zone-size)))
    
    ;; Open the input driver
    (tb:with-heap-zone (mx-heap-zone)
      (setf parm-block-in (make-instance 'tb:ioparam))
      
      ;; This record is passed to serial read to return serial errors in.
      (setf serial-status-record (make-instance 'tb:serstarec))
      (setf (send parm-block-in :iomisc) (tb:deref serial-status-record))
      
      (setf (send parm-block-in :iorefnum) input-mac-reference-number)
      (setf (send parm-block-in :ioresult) 0)
      (setf (send parm-block-in :iopermssn) 0)
      
      (tb:!ramsdopen (if (eq port :a) 0 1))
      
      ;; Open the output driver.
      (setf parm-block-out (make-instance 'tb:ioparam))
      (setf (send parm-block-out :iorefnum) output-mac-reference-number)    
      (setf (send parm-block-out :ioresult) 0)
      (setf (send parm-block-out :iopermssn) 0)
      
      ;;;  now reset it.
      ;;;  compute the serial configuration integer.
      (setq serial-configuration-int
	    (+ (second baud-entry) (second stop-bit-entry)
	       (second parity-entry) (second data-bits-entry)))
      ;;  reset and initialize the serial port on the MACintosh.
      (send self :reset-hardware)
      
      ;; Create the output data buffer
      (let ((ptr (tb:!NewPtr stream-output-limit)))
	(setf stream-output-buffer (make-array stream-output-limit
					       :type 'art-8b
					       :displaced-to-physical-address (send (tb:ptr24to32 ptr) :pointer)))	
	(setf (send parm-block-out :iobuffer) ptr)
	
	;; Create the input data buffer.
	(setf ptr (tb:!NewPtr input-buffer-size))	
	(setf stream-input-buffer (make-array input-buffer-size
					      :type 'art-8b
					      :leader-list (list ptr)
					      :displaced-to-physical-address (send (tb:ptr24to32 ptr) :pointer)))
	
	
	;; Create the input data buffer.
	(setf ptr (tb:!NewPtr input-buffer-size))
	(setf backup-input-buffer (make-array input-buffer-size
					      :type 'art-8b
					      :leader-list (list ptr)
					      :displaced-to-physical-address (send (tb:ptr24to32 ptr) :pointer))))
      
      ;; Setup driver parameters.
      (setf mysershk (make-instance 'tb:sershk))
      (setf (send mysershk :fxon) (if xon-xoff-protocol 1 0))
      (setf (send mysershk :finx) (if xon-xoff-protocol 1 0))
      (setf (send mysershk :xon)  (int-char #x11))
      (setf (send mysershk :xoff) (int-char #x13))
      (setf (send mysershk :errs) (+ (if check-parity-errors 16. 0)
				     (if check-framing-errors 64. 0)
				     (if check-over-run-errors 32. 0)))
      (setf (send mysershk :evts) 0)
      
      (tb:!serhshake output-mac-reference-number mysershk)
      
      (tb:!serclrbrk output-mac-reference-number))
    
    ;; Allocate an input buffer of the appropriate size. This replaces the 64 char default. Note that this is in
    ;; Mac memory. We don't want the serial driver writing into MX memory every time a character is received.
    (setf mac-driver-input-buffer (tb:!newptr 2048))
    (tb:!sersetbuf input-mac-reference-number mac-driver-input-buffer 2048)
    
    (setq closed-p ())			       ;stream is open now
    (set (get-port-owner-symbol port) self)))

(defmethod (SERIAL-STREAM-MIXIN :RESET-HARDWARE) ()    ;stage 1 - modes and constants
  "This method uses the values validated and computed by the :reset method,
    and should not be called without calling the :reset method first."
  (tb:!serreset output-mac-reference-number serial-configuration-int)
  (tb:!serreset input-mac-reference-number serial-configuration-int))


(defmethod (SERIAL-STREAM-MIXIN :CLOSE) (&optional abort-p)
  ;; deallocate the serial buffers
  (when (equal self (get-port-owner port))	       ;can only close the real owner of the port
    (unless abort-p
      (send self :finish))
    (with-parm-block (parm-block-in t)
      (tb:!killio_async parm-block-in))
    
    (with-parm-block (parm-block-out t)
      (tb:!killio_async parm-block-out))
    
    ;; Remove the allocated driver input buffer.
    (tb:!sersetbuf input-mac-reference-number (make-instance 'tb:mac-pointer :pointer 0) 0)
    (tb:!disposptr mac-driver-input-buffer)
    (setf mac-driver-input-buffer nil)
    
    (tb:!ramsdclose (if (eq port :a) 0 1))
    
    (setq closed-p t)				       ;stream is closed -- any I/O method use could crash the system
    (set (get-port-owner-symbol port) nil)
    (tb:remove-mx-heap-zone mx-heap-zone)))

(defmethod (SERIAL-STREAM-MIXIN :FINISH) ()
  ;; get things started if they aren't already
  (send self :force-output)
  (process-wait "Serial finish" #'(lambda (parm-block)
				    (not (eql (send parm-block :ioresult) 1)))
		parm-block-out))

(defmethod (SERIAL-STREAM-MIXIN :CLEAR-INPUT) ()
  (unless closed-p
    (setf serial-untyi-ch nil)
    (setf stream-input-limit 0)
    (setf stream-input-index 0)
    
    (with-parm-block (parm-block-in t)
      (tb:!killio_async parm-block-in))))


(defmethod (SERIAL-STREAM-MIXIN :CLEAR-OUTPUT) ()
  (unless closed-p    
    ;;(FLUSH-SERIAL-BUFFER *SERIAL-OUTPUT-BUFFER*)
    ;; We are going to clear the output by killing the IO on the output reference number.
    (with-parm-block (parm-block-out t)
      (tb:!killio_async parm-block-out))
    (setf stream-output-index 0))) 



(defmethod (SERIAL-STREAM-MIXIN :STATUS) ()
  "Print out the status of the serial i/o interface."
  (let (myserstatus status xoffsent rdpend wrpend ctshold xoffhold (status-stream t))
    (select (get-port-owner port)
      ;; If we own the port then Write the status report.
      (self
       (format status-stream "~%The Owner of the port is: ~a" self)
       (send self :describe)
       (format status-stream "~%The number of characters in the input buffer is ~d."
	       (tb:!sergetbuf input-mac-reference-number))
       (setq myserstatus (tb:!serstatus output-mac-reference-number))
       (if (numberp myserstatus)
	   (format status-stream "~&!SerStatus returned ~d" myserstatus)
	   (setq status (send myserstatus :cumerrs))
	   (format status-stream "~%The Serial Status Record is:")
	   (format status-stream "~%Software Overrun error has ~:[not ~;~]occurred."
		   (logtest 1 status))
	   (format status-stream "~%Parity error has ~:[not ~;~]occurred."
		   (logtest 16. status))
	   (format status-stream "~%Hardware Overrun error has ~:[not ~;~]occurred."
		   (logtest 32. status))
	   (format status-stream "~%Framing error has ~:[not ~;~]occurred."
		   (logtest 64. status))
	   (setq xoffsent (send myserstatus :xoffsent))
	   (format status-stream "~%An XOff character has ~:[not ~;~]been sent."
		   (logtest #x80 xoffsent))
	   (setq rdpend (send myserstatus :rdpend))
	   (format status-stream "~%A read is ~:[~;not ~]pending." (= 0 rdpend))
	   (setq wrpend (send myserstatus :wrpend))
	   (format status-stream "~%A write is ~:[~;not ~]pending." (= 0 wrpend))
	   (setq ctshold (send myserstatus :ctshold))
	   (format status-stream "~%A write is ~:[~;not ~]waiting for CTS to come high." (= 0 ctshold))
	   (setq xoffhold (send myserstatus :xoffhold))
	   (format status-stream "~%A write is ~:[~;not ~]waiting for an X-On character to be sent.~%"
		   (= 0 xoffhold)
		   )
	   (tb:!disposhandle myserstatus)
	   )
       (format status-stream "~2%")
       )
; If there is no owner then either the port is not open or not valid.
      (nil (if (get-port-owner-symbol port)
	       (format status-stream "~%The port ~a is not opened." port)
	       (format status-stream "~%The port ~a is not valid." port)))
; Send the owner of the open port the request to get the status.
      (otherwise (format status-stream "~%~a is not the owner of the port" self)
		 (send (get-port-owner port) :status)))
    )
  )

;;; Get the current RS232 parameters

(defmethod (SERIAL-STREAM-MIXIN :GET) (prop)
  (let ()
    (case prop
      (:request-to-send t)
      (:data-terminal-ready t)
      (:data-carrier-detect t)
      (:clear-to-send
       (let (myserstatus ctshold)
	 (setq myserstatus (tb:!serstatus output-mac-reference-number))
	 (setq ctshold (send myserstatus :ctshold))
	 (zerop ctshold)
	 ))
      (:tx-buffer-empty t)
      (:rx-char-available (tb:!sergetbuf input-mac-reference-number))
      (:number-of-stop-bits number-of-stop-bits)
      (:parity parity)
      (:number-of-data-bits number-of-data-bits)
      (:number-of-rx-data-bits number-of-data-bits)
      (:number-of-tx-data-bits number-of-data-bits)
      (:baud baud)
      (:receive-enable (not closed-p))
      (:transmit-enable (not closed-p))
      (:wr3 0)
      (:wr4 0)
      (:wr5 0)
      (:wr12 0)
      (:wr13 0)
      (:input-buffer-size input-buffer-size)
      (:output-buffer-size stream-output-limit)
      (:force-output force-output)
      (:eot-enable eot-enable)
      (:xon-xoff-protocol xon-xoff-protocol)
      (:otherwise (ferror () "~S not a valid property name" prop))))) 

;;; Modify RS232 parameters


(defmethod (SERIAL-STREAM-MIXIN :PUT) (prop val)
  "Change various properties of the stream.  The serial stream should be :reset for certain new values to 
take effect."
  (case prop
    (:number-of-tx-data-bits
     (loop until (find val *serial-mac-data-bits-list* :key #'car :test #'equalp)
	   do (setq val
		    (cerror :argument-value nil 'sys:wrong-type-argument
			    "The new number of transmit data bits ~a is not valid. The valid values are ~:{~a ~}."
			    val *serial-mac-data-bits-list*))
	   finally (setq number-of-tx-data-bits val))
     (setq number-of-data-bits (or number-of-data-bits number-of-tx-data-bits)
	   number-of-rx-data-bits (or number-of-rx-data-bits number-of-tx-data-bits)))
    (:number-of-rx-data-bits
     (loop until (find val *serial-mac-data-bits-list* :key #'car :test #'equalp)
	   do (setq val
		    (cerror :argument-value nil 'sys:wrong-type-argument
			    "The new number of receive data bits ~a is not valid. The valid values are ~:{~a ~}."
			    val *serial-mac-data-bits-list*))
	   finally (setq number-of-rx-data-bits val))
     (setq number-of-data-bits (or number-of-data-bits number-of-rx-data-bits)
	   number-of-tx-data-bits (or number-of-tx-data-bits number-of-rx-data-bits)))
    (:number-of-data-bits
     (loop until (find val *serial-mac-data-bits-list* :key #'car :test #'equalp)
	   do (setq val
		    (cerror :argument-value nil 'sys:wrong-type-argument
			    "The new number of data bits ~a is not valid. The valid values are ~:{~a ~}."
			    val *serial-mac-data-bits-list*))
	   finally (setq number-of-data-bits val
			 number-of-rx-data-bits val
			 number-of-tx-data-bits val)))
    (:parity
     (loop until (find val *serial-mac-parity-list* :key #'car :test #'equalp)
	   do (setq val
		    (cerror :argument-value nil 'sys:wrong-type-argument
			    "The new parity ~a is not valid. The valid values are ~:{~a ~}."
			    val *serial-mac-parity-list*))
	   finally (setq parity val)))
    (:number-of-stop-bits
     (loop until (find val *serial-mac-stop-bits-list* :key #'car :test #'equalp)
	   do (setq val
		    (cerror :argument-value nil 'sys:wrong-type-argument
			    "The new number of stop bits ~a is not valid. The valid values are ~:{~a ~}."
			    val *serial-mac-stop-bits-list*))
	   finally (setq number-of-stop-bits val)))
    (:baud
     (loop until (find val *serial-mac-baud-list* :key #'car :test #'equalp)
	   do (setq val
		    (cerror :argument-value nil 'sys:wrong-type-argument
			    "The new baud rate ~a is not valid. The valid values are ~:{~a ~}."
			    val *serial-mac-baud-list*))
	   finally (setq baud val)))
    (:receive-enable )				       ; This value is ignored.
    (:transmit-enable )				       ; This value is ignored.
    (:request-to-send )				       ; This value is ignored.
    (:data-terminal-ready )			       ; This value is ignored.
    (:input-buffer-size (setq input-buffer-size val))
    (:output-buffer-size (setq stream-output-limit val))
    (:force-output (setq force-output (if val t ())))
    (:eot-enable (setq eot-enable (if val t ())))
    (:xon-xoff-protocol (setq xon-xoff-protocol (if val t ())))
    (:check-parity-errors (setq check-parity-errors (if val t ())))
    (:check-over-run-errors (setq check-over-run-errors (if val t ())))
    (:check-framing-errors (setq check-framing-errors (if val t ())))
    (:otherwise (ferror () "~S not a valid property name" prop))))



;;; Stream Input Protocol

(defvar *serial-input-buffer-threshold* 5. "When the current input buffer gets this low we will issue another call.")

(defmethod (SERIAL-STREAM-MIXIN :INPUT-CHARS-AVAILABLE-P) ()
  "This method will return T or NIL. T implies that one or more characters is available to read.
 NIL implies that there are not any characters known to read about."
  (cond
    (closed-p nil)				       ;If closed, don't do anything & return nil
    (serial-untyi-ch t)				       ;If character that was :UNTYIed, then we have one character there.
    ((< stream-input-index stream-input-limit)

     ;; Issue a read ahead call.
     (when (and (not read-issued-p) (< (- stream-input-limit stream-input-index) *serial-input-buffer-threshold*))
       (send self :issue-read-call))
     t)
    
    ;; Check the MAC device driver's input buffer for characters.
    ;; Status issued, we just poll the param block
    (read-issued-p
     
     (let ((result (send parm-block-in :ioresult)))
       
       (cond
	 
	 ;; Read still pending. Return nil.
	 ((= result 1)
	  nil)
	 
	 ;; Call Finished, got an error. Signal it
	 ((not (zerop result))
	  (setf read-issued-p nil)
	  (tb:signal-oserr result 'tb:serial-read)
	  nil)
	 
	 ;; Call finished, got at least one character. Return that value.
	 ((not (zerop (send parm-block-in :ioactcount)))

	  ;; Swap out the buffers.
	  (psetf stream-input-buffer backup-input-buffer backup-input-buffer stream-input-buffer)
	  
	  (setf stream-input-limit (send parm-block-in :ioactcount))
	  (setf stream-input-index 0)

	  (send self :send-if-handles :ascii-to-exp)
	  
	  ;; Need to look at serial errors here!!! They are kept in a buffer pointed to by ioMisc.
	  (let ((errors (send serial-status-record :cumerrs)))
	    (when (logtest (+ 1 16. 32. 64.) errors)
	      (error "Serial input ~:[software over-run ~]~:[framing ~]~:[hardware over-run ~]~:[parity ~]error: ~O"
		     (zerop (logand 1 errors))
		     (zerop (logand 64. errors))
		     (zerop (logand 32. errors))
		     (zerop (logand 16. errors)))))
	  
	  (setf read-issued-p nil)
	  t)
	 
	 ;; Call Finished, There were no characters.
	 (t
	  (setf read-issued-p nil)
	  nil))))
    
    ;; Issue a status call and return nil. It will complete on some other call to this function.
    (t
     (send self :issue-read-call)
     nil
     )))
;;
;; As the code is written right now these two methods are not used but are required by one
;; of the mixin flavors.
(defmethod (serial-stream-mixin :next-input-buffer) ()
  (process-wait "Serial Input" #'(lambda (str) (send str :input-characters-available-p)) self))

(defmethod (serial-stream-mixin :discard-input-buffer) (buffer)
  (declare (ignore buffer)))

(defmethod (serial-stream-mixin :issue-read-call) ()
  (unless read-issued-p
    (with-parm-block (parm-block-in t)
      (setf (send parm-block-in :IoBuffer) (array-leader backup-input-buffer 0))
      (setf (send parm-block-in :ioreqcount) input-buffer-size) 
      (tb:serial-read (tb:deref parm-block-in)))       
    (setf read-issued-p t)))

(defmethod (SERIAL-STREAM-MIXIN :TYI) (&optional ignore)
  (without-interrupts
    (let (ch)
      
      (when closed-p
	(cerror "Reset (Open) Serial Stream ~a and Retry" "Attempt to initiate IO on closed Serial Stream: ~a " self)
	(send self :reset))
      
      ;; Wait until there is something to return.
      (unless (send self :input-chars-available-p)
	(process-wait "serial input" #'(lambda (stream) (send stream :input-chars-available-p)) self))
      
      ;; stream should be open at this point
      (cond
	
	;;; Handle the case of returning a character that has been :UNTYIed.
	(serial-untyi-ch (setq ch (prog1 serial-untyi-ch (setq serial-untyi-ch ()))))
	
	;; Handle the case of returning a character from the input buffer on the LISP side.
	(t
	 
	 (prog1
	   (setf ch (aref stream-input-buffer stream-input-index))
	   (incf stream-input-index))))
      
      (cond ((and eot-enable (= ch eot-character))
	     (setq serial-port-eot-received-p t)
	     nil)
	    
	    ((and eot-enable ch)
	     (setq serial-port-eot-received-p nil)
	     ch)
	    
	    (t
	     ch)))))

(defmethod (SERIAL-STREAM-MIXIN :UNTYI) (char)
  (setq serial-untyi-ch char)) 


(defmethod (SERIAL-STREAM-MIXIN :LISTEN) ()
  (cond (serial-untyi-ch)
	((< stream-input-index stream-input-limit)
	 (aref stream-input-buffer (send self :stream-input-index)))
	((send self :input-chars-available-p)
	 (aref stream-input-buffer stream-input-index))))

(defmethod (SERIAL-STREAM-MIXIN :TYI-NO-HANG) (&optional ignore)
  (when (send self :input-chars-available-p)
    (send self :tyi))) 

(DEFMETHOD (SERIAL-STREAM-MIXIN :TYI-WITH-TIMEOUT) (INTERVAL-IN-60THS)
  (IF (PROCESS-WAIT-WITH-TIMEOUT
	   "Serial Waiting"
	   INTERVAL-IN-60THS
	   (FUNCTION (LAMBDA (STREAM) (SEND STREAM :INPUT-CHARS-AVAILABLE-P)))
	   SELF)
	 (SEND SELF :TYI)))

(DEFMETHOD (serial-stream-mixin :STRING-IN) (EOF STRING &OPTIONAL (START 0.) END)
  (declare (ignore eof))
  (unless END
    (SETf END (ARRAY-TOTAL-SIZE STRING)))
  
  (loop with index = start
	with chunk-length = 0
	while (< index end)
	unless (send self :input-chars-available-p)
	do (process-wait "serial input" #'(lambda (str) (send str :input-chars-available-p)) self)
	
	do
	(setf chunk-length (min (- stream-input-limit stream-input-index) (- end index)))
	(copy-array-portion stream-input-buffer stream-input-index (+ index chunk-length) string index (+ index chunk-length))
	(incf stream-input-index chunk-length)
	(incf index chunk-length)
	
	finally (progn (when (array-has-leader-p string)
			 (setf (array-leader string 0) index))
		       (return (values index nil)))))


(defmethod (serial-stream-mixin :line-in) (&optional leader)
  (declare (special *new-line-delimiter* ))	       ;01-27-88 DAB
      
    (loop

      with string-index = 0
      with new-string-index
      with new-buffer-index
      with cr-index = nil
      with read-string

      when cr-index
      return read-string
      
      unless (send self :input-chars-available-p)
      do (process-wait "serial input" #'(lambda (str) (send str :input-chars-available-p)) self)
      
      do
      (setf cr-index (string-search-set *new-line-delimiter*   ;01-27-88 DAB
					stream-input-buffer
					stream-input-index
					stream-input-limit))
      
      (cond (cr-index
	     (setf new-buffer-index (1+ cr-index))
	     (setf new-string-index (+ string-index (- cr-index stream-input-index))))
	    (t
	     (setf new-buffer-index stream-input-limit)
	     (setf new-string-index (+ string-index (- stream-input-limit stream-input-index)))))

      (cond ((null read-string)
	     (setf read-string (make-array new-string-index :element-type 'string-char :leader-length (or leader 0))))
	    ((> new-string-index (array-total-size read-string))
	     (adjust-array read-string new-string-index)))
      
      (copy-array-portion stream-input-buffer stream-input-index new-buffer-index
			  read-string string-index new-string-index)
      
      (setf stream-input-index new-buffer-index)
      (setf string-index new-string-index)
      
      (when (array-has-fill-pointer-p read-string)
	(setf (fill-pointer read-string) string-index))))


;;; Serial stream output protocoll
;;; If the buffer is full, we want to do an automatic :FORCE-OUTPUT


(defmethod (SERIAL-STREAM-MIXIN :TYO) (ch)
  (when closed-p
    (cerror "Reset Stream ~a and Retry" "Attempt to Type Out on closed Serial Stream: ~a "
	    self)
    (send self :reset))
  
  (when (>= stream-output-index stream-output-limit)
    (send self :force-output))
  (with-parm-block (parm-block-out nil)
    (setf (aref stream-output-buffer stream-output-index) ch)
    (incf stream-output-index))
  
  (when force-output
    (send self :force-output)))

(defmethod (SERIAL-STREAM-MIXIN :STRING-OUT) (string &optional (start 0.) (end (length string)))
  (loop with index = start
	with chunk-length = 0
	do (with-parm-block (parm-block-out nil)
	     (setf chunk-length (min (- stream-output-limit stream-output-index) (- end index)))
	     (copy-array-portion string index (+ index chunk-length) stream-output-buffer stream-output-index stream-output-limit)
	     (incf stream-output-index chunk-length)
	     (incf index chunk-length))
	(cond ((< index end)
	       (send self :force-output))
	      (t
	       (return))))

  (when force-output
    (send self :force-output)))

(defmethod (SERIAL-STREAM-MIXIN :LINE-OUT) (line &optional (start 0.) (end (length line)))
  (send self :string-out line start end)
  (send self :tyo #\newline))

(defmethod (SERIAL-STREAM-MIXIN :FORCE-OUTPUT) ()
  (with-parm-block (parm-block-out t)
    (send self :send-if-handles :exp-to-ascii)
    (setf (send parm-block-out :ioreqcount) stream-output-index)
    (tb:!write_async parm-block-out)
    (setf stream-output-index 0)))

(DEFMETHOD (SERIAL-STREAM-MIXIN :NETWORK-TYPE) () :SERIAL)

(defmethod (serial-stream-mixin :SEND-LONG-BREAK) ()
 "Transmits a space condition for 3.5 seconds (long break)."
  (cerror "Resume" "Long Breaks are not supported."))


(defmethod (serial-stream-mixin :SEND-SHORT-BREAK) ()
 "Transmits a space condition for .275 seconds (short break)."
  (cerror "Resume" "Short Breaks are not supported."))  

(DEFMETHOD (SERIAL-STREAM-MIXIN :NETWORK-TYPE) () :SERIAL)

(compile-flavor-methods serial-stream serial-ascii-stream) 




))
