changeset 1966:4de571b41659

Added lots of comments should now compile and work.
author afra
date Wed, 04 Jan 2006 14:25:28 +0000
parents 7d14b2ce38c4
children 1cb1a5c389cc
files level1/modules/sc6551dragon.asm
diffstat 1 files changed, 657 insertions(+), 371 deletions(-) [+]
line wrap: on
line diff
--- a/level1/modules/sc6551dragon.asm	Wed Jan 04 14:24:43 2006 +0000
+++ b/level1/modules/sc6551dragon.asm	Wed Jan 04 14:25:28 2006 +0000
@@ -1,384 +1,670 @@
-********************************************************************
-* ACIA51 - Serial port device driver
+*
+* Dragon 64/Alpha 6551 serial port driver 
+*
+* Disassembled 2005/04/25 00:12:02 by Disasm v1.5 (C) 1988 by RML
+*
+* The Dragon 64 and Dragon Alpha have a hardware serial port driven
+* by a Rockwell 6551, mapped from $FF04-$FF07.
 *
-* $Id$
+* Communication between the read/write routines and the ACIA, is buffered
+* using a pair of ring buffers, when disassembling labels have been assigned
+* so that bytes are placed into the Rx/Tx queue Tail, and removed from the 
+* head. When the queues become full the calling process is put to sleep
+* while it awiaits Rx/Tx from the remote device.
+*
+* 2005-05-01, P.Harvey-Smith.
+*	Initial disassembly.
+*
+* 2005-10-24, P.Harvey-Smith.
+*	Code clean up/commenting.
 *
-* Edt/Rev  YYYY/MM/DD  Modified by
-* Comment
-* ------------------------------------------------------------------
-*   4      1985/??/??
-* From Dragon OS-9 Level One VR 02.00.00
+
+	nam   ACIA51
+        ttl   os9 device driver    
+
+        ifp1
+        use   	defsfile.dragon
+	endc
+		
+* Following definitions borrowed from sc6551.asm	
+
+* Status bit definitions
+Stat.IRQ	equ   %10000000      IRQ occurred
+Stat.DSR	equ   %01000000      DSR level (clear = active)
+Stat.DCD	equ   %00100000      DCD level (clear = active)
+Stat.TxE   	equ   %00010000      Tx data register Empty
+Stat.RxF   	equ   %00001000      Rx data register Full
+Stat.Ovr   	equ   %00000100      Rx data Overrun error
+Stat.Frm   	equ   %00000010      Rx data Framing error
+Stat.Par   	equ   %00000001      Rx data Parity error
+
+Stat.Err   	equ   Stat.Ovr!Stat.Frm!Stat.Par Status error bits
+Stat.Flp   	equ   $00            all Status bits active when set
+Stat.Msk   	equ   Stat.IRQ!Stat.RxF active IRQs
+
+* Control bit definitions
+Ctl.Stop   	equ   %10000000      stop bits (set=two, clear=one)
+Ctl.DBit   	equ   %01100000      see data bit table below
+Ctl.RxCS   	equ   %00010000      Rx clock source (set=baud rate, clear=external)
+Ctl.Baud   	equ   %00001111      see baud rate table below
+
+* data bit table
+DB.8       	equ   %00000000      eight data bits per character
+DB.7       	equ   %00100000      seven data bits per character
+DB.6       	equ   %01000000      six data bits per character
+DB.5       	equ   %01100000      five data bits per character
+
+* baud rate table
+		org   $00
+BR.ExClk   	rmb   1              16x external clock (not supported)
+		org   $11
+BR.00050   	rmb   1              50 baud (not supported)
+BR.00075   	rmb   1              75 baud (not supported)
+BR.00110   	rmb   1              109.92 baud
+BR.00135   	rmb   1              134.58 baud (not supported)
+BR.00150   	rmb   1              150 baud (not supported)
+BR.00300   	rmb   1              300 baud
+BR.00600   	rmb   1              600 baud
+BR.01200   	rmb   1              1200 baud
+BR.01800   	rmb   1              1800 baud (not supported)
+BR.02400   	rmb   1              2400 baud
+BR.03600   	rmb   1              3600 baud (not supported)
+BR.04800   	rmb   1              4800 baud
+BR.07200   	rmb   1              7200 baud (not supported)
+BR.09600   	rmb   1              9600 baud
+BR.19200   	rmb   1              19200 baud
 
-         nam   ACIA51
-         ttl   Serial port device driver    
+* Command bit definitions
+Cmd.Par    	equ   %11100000      see parity table below
+Cmd.Echo   	equ   %00010000      local echo (set=activated)
+Cmd.TIRB   	equ   %00001100      see Tx IRQ/RTS/Break table below
+Cmd.RxI    	equ   %00000010      Rx IRQ (set=disabled)
+Cmd.DTR    	equ   %00000001      DTR output (set=enabled)
+
+* parity table
+Par.None   	equ   %00000000
+Par.Odd    	equ   %00100000
+Par.Even   	equ   %01100000
+Par.Mark   	equ   %10100000
+Par.Spac   	equ   %11100000
 
-* Disassembled 02/04/21 22:37:41 by Disasm v1.6 (C) 1988 by RML
+* Tx IRQ/RTS/Break table
+TIRB.Off   	equ   %00000000      RTS & Tx IRQs disabled
+TIRB.On    	equ   %00000100      RTS & Tx IRQs enabled
+TIRB.RTS   	equ   %00001000      RTS enabled, Tx IRQs disabled
+TIRB.Brk   	equ   %00001100      RTS enabled, Tx IRQs disabled, Tx line Break
+
+* V.ERR bit definitions
+DCDLstEr   	equ   %00100000      DCD lost error
+OvrFloEr   	equ   %00000100      Rx data overrun or Rx buffer overflow error
+FrmingEr   	equ   %00000010      Rx data framing error
+ParityEr   	equ   %00000001      Rx data parity error
+
+* FloCtlRx bit definitions
+FCRxSend   	equ   %10000000      send flow control character
+FCRxSent   	equ   %00010000      Rx disabled due to XOFF sent
+FCRxDTR    	equ   %00000010      Rx disabled due to DTR
+FCRxRTS    	equ   %00000001      Rx disabled due to RTS
+
+* FloCtlTx bit definitions
+FCTxXOff   	equ   %10000000      due to XOFF received
+FCTxBrk    	equ   %00000010      due to currently transmitting Break
 
-         IFP1
-         use   defsfile
-         ENDC
+* Wrk.Type bit definitions
+Parity     	equ   %11100000      parity bits
+MdmKill    	equ   %00010000      modem kill option
+RxSwFlow   	equ   %00001000      Rx data software (XON/XOFF) flow control
+TxSwFlow   	equ   %00000100      Tx data software (XON/XOFF) flow control
+RTSFlow    	equ   %00000010      CTS/RTS hardware flow control
+DSRFlow    	equ   %00000001      DSR/DTR hardware flow control
+
+* Wrk.Baud bit definitions
+StopBits   	equ   %10000000      number of stop bits code
+WordLen    	equ   %01100000      word length code
+BaudRate   	equ   %00001111      baud rate code
+
+* Wrk.XTyp bit definitions
+SwpDCDSR   	equ   %10000000      swap DCD+DSR bits (valid for 6551 only)
+ForceDTR   	equ   %01000000      don't drop DTR in term routine
+RxBufPag   	equ   %00001111      input buffer page count
+	
+* End of borrowed stuff :)
+	
+tylg    set   	Drivr+Objct   
+atrv    set   	ReEnt+rev
+rev     set   	$01
+        mod   	eom,name,tylg,atrv,start,size
 
-tylg     set   Drivr+Objct   
-atrv     set   ReEnt+rev
-rev      set   $00
-edition  set   $04
+RxQueueTailOffset	rmb   	1		; Tail of Rx queue, Rx inturrupt inserts here
+RxQueueHeadOffset   	rmb	1		; Head of Rx queue, read call fetches from here
+u001F   rmb   	1
+TxQueueTailOffset   	rmb   	1		; Tail of Tx queue, write call inserts here
+TxQueueHeadOffset   	rmb   	1		; Head of Tx queue, Tx inturrupt fetches here
+u0022   rmb   	1
+u0023   rmb   	1		; something to do with XON/XOFF
+u0024   rmb   	2
+SavedDSRDCD   		rmb   	1		; Saved DSR and DCD ststus
+RxQueue 		rmb   	80		; Rx Queue
+RxQueueLen		EQU	*-RxQueue	; Rx queue length
+	
+TxQueue 		rmb   	140		; Tx Queue
+TxQueueLen		EQU	*-TxQueue	; Tx Queue length
 
-         mod   eom,name,tylg,atrv,start,size
+size    equ   	.
+
+        fcb   	$03 
+	
+name    equ   	*
+        fcs   	/ACIA51/
+        fcb   	$04 
+
+start   equ   	*
 
-u0000    rmb   1
-u0001    rmb   2
-u0003    rmb   1
-u0004    rmb   1
-u0005    rmb   1
-u0006    rmb   3
-u0009    rmb   2
-u000B    rmb   1
-u000C    rmb   1
-u000D    rmb   1
-u000E    rmb   1
-u000F    rmb   1
-u0010    rmb   13
-u001D    rmb   1
-u001E    rmb   1
-u001F    rmb   1
-u0020    rmb   1
-u0021    rmb   1
-u0022    rmb   1
-u0023    rmb   1
-u0024    rmb   2
-u0026    rmb   1
-u0027    rmb   36
-u004B    rmb   44
-u0077    rmb   9
-u0080    rmb   46
-u00AE    rmb   85
-size     equ   .
+        lbra  	Init
+        lbra  	Read
+        lbra  	Write
+        lbra  	GetSta
+        lbra  	SetSta
+        lbra  	Term
+
+IRQPkt 
+	FCB	$00		; Normal bits (flip byte)
+	FCB	$80		; Bit 1 is interrupt request flag (Mask byte)
+	FCB	$0A		; Priority byte
+	
+
+* Init
+*
+* Entry:
+*    Y  = address of device descriptor
+*    U  = address of device memory area
+*
+* Exit:
+*    CC = carry set on error
+*    B  = error code
+*
+
+Init	LDX	V.PORT,U		; 1,U Get port address $FF04
+        stb   	AciaStat,x		; Write to status reg, this resets ACIA
+        ldb   	#$02
+        stb   	<u0022,u
+        ldd   	<IT.PAR,y		; Get parity & baud rate <$26,y
+        
+	andb  	#$0F			
+        leax  	<BaudRateTable,pcr	; Calculate baud rate values for Acia
+        ldb   	b,x
+	
+        anda  	#$F0
+        sta   	V.TYPE,u		; Save parity bits for later use
+        ldx   	V.PORT,u		; Get port address $FF04
+        std   	AciaCmd,x		; Setup Command (A), Control (B,Baud rates).
+        lda   	,x			
+        lda   	,x
+        tst   	AciaStat,x		; Get status
+        lbmi  	ErrorExit		; Error if int occoured
+	
+        clra  				; Init some static storage
+        clrb  
+        std   	<RxQueueTailOffset,u	; Init Rx queue
+        std   	<TxQueueTailOffset,u	; Init Tx queue
+        sta   	<u0023,u
+        sta   	<u001F,u
+        std   	<u0024,u
+
+        ldd   	V.PORT,u		; Get port address $FF04
+        addd  	#$0001			; Setup V$IRQ on status reg changes
+        leax  	>IRQPkt,pcr		; Point to packet
+        leay  	>IRQService,pcr		; Point to handler
+        os9   	F$IRQ    		; Install it !
+        bcs   	InitExit		; Error : Exit
+	
+        ldx   	V.PORT,u		; Get port address $FF04
+        ldb   	V.TYPE,u		; Get device parity settings
+        orb   	#Cmd.DTR		; SET DTR, flag us as ready
+        stb   	AciaCmd,x
+        clrb  				; Flag no error
+InitExit   
+	rts   
+
+;
+; Baud rate table, all baud rates use external clock.
+;
+
+BaudRateTable   
+	fcb	Ctl.RxCS+BR.00110
+	fcb	Ctl.RxCS+BR.00300
+	fcb	Ctl.RxCS+BR.00600
+	fcb	Ctl.RxCS+BR.01200
+	fcb	Ctl.RxCS+BR.02400
+	fcb	Ctl.RxCS+BR.04800
+	fcb	Ctl.RxCS+BR.09600
+	fcb	Ctl.RxCS+BR.19200
 
-         fcb   UPDAT.
+PutProcToSleep   
+	bsr   	DoPutProcToSleep
+
+*
+* Input	U = Address of device static data storage
+*	Y = Address of path descriptor module
+*
+* Output
+*	A = Character read
+*	CC = carry set on error, clear on none
+*	B = error code if CC.C set.
+*
+
+
+Read    lda   	<u0023,u
+        ble   	L00A1
+	
+        ldb   	<u001F,u
+        cmpb  	#$0A
+        bhi   	L00A1
+        
+	ldb   	V.XON,u
+        orb   	#$80
+        stb   	<u0023,u
+	
+        ldb   	V.TYPE,u		; Get prity settings
+        orb   	#TIRB.On+Cmd.DTR	; Enable tranmitter inturrupt & DTR ($05)
+        ldx   	V.PORT,u		; Get port address $FF04
+        stb   	AciaCmd,x		; Write to ACIA
+	
+L00A1   tst   	<u0024,u
+        bne   	ErrorExit
+
+        ldb   	<RxQueueHeadOffset,u	; Get queue head ptr
+        leax  	<RxQueue,u		; Get Rx Queue address
 
-name     fcs   /ACIA51/
-         fcb   edition
+        orcc  	#$50			; Disable Inturrupts
+        cmpb  	<RxQueueTailOffset,u	; Is Head=Tail, and therefore queue empty ?
+        beq   	PutProcToSleep		; Yes : sleep and await input from remote device
+	
+        abx   				; Calculate pos in queue for next char
+        lda   	,x			; Get byte from read queue 
+        dec   	<u001F,u
+        incb  
+        cmpb  	#RxQueueLen-1		; Reached end of queue area ?
+        bls   	L00BF			; no : continue
+	
+        clrb  				; Wrap tail pointer to the beginning of queue space
+L00BF   stb   	<RxQueueHeadOffset,u	; save new queue pointer
+        clrb  
+        ldb   	V.ERR,u
+        beq   	L00CF			; No error : exit
+	
+        stb   	<$3A,y
+        clr   	V.ERR,u
+        comb  				; Flag and return error
+        ldb   	#$F4		
+L00CF   andcc 	#$AF			; Enable inturrupts
+        rts
+	
+ErrorExit   
+	comb  				; Flag error & return
+        ldb   	#$F6
+        rts   
+	
+;
+; Put calling process to sleep while we await input or output from remote device.
+;
+	
+DoPutProcToSleep   
+	pshs  	x,b,a
+        lda   	V.BUSY,u		; Get busy process
+        sta   	V.WAKE,u		; Store in proc to wake
+        andcc 	#$AF			; Enable inturrupts
+        ldx  	#$0000			; Sleep indefinatly
+        os9   	F$Sleep			; Put caller to sleep
+  
+        ldx   	<D.Proc			; Get current proces descriptor addr
+        ldb   	<P$Signal,x		; Get signal code of proc
+        beq   	L00EF
+	
+        cmpb  	#$03
+        bls   	L00F8
 
-start    equ   *
-         lbra  L002A
-         lbra  L0086
-         lbra  L00FE
-         lbra  L012F
-         lbra  L0146
-         lbra  L0173
-L0027    neg   <u0080
-         dec   <u00AE
-         fcb   $41 A
-         stb   $01,x
-         ldb   #$02
-         stb   <u0022,u
-         ldd   <$26,y
-         andb  #$0F
-         leax  <L007C,pcr
-         ldb   b,x
-         anda  #$F0
-         sta   u0006,u
-         ldx   u0001,u
-         std   $02,x
-         lda   ,x
-         lda   ,x
-         tst   $01,x
-         lbmi  L00D2
-         clra  
-         clrb  
-         std   <u001D,u
-         std   <u0020,u
-         sta   <u0023,u
-         sta   <u001F,u
-         std   <u0024,u
-         ldd   u0001,u
-         addd  #$0001
-         leax  >L0027,pcr
-         leay  >L0194,pcr
-         os9   F$IRQ    
-         bcs   L007B
-         ldx   u0001,u
-         ldb   u0006,u
-         orb   #$01
-         stb   $02,x
-         clrb  
-L007B    rts   
-L007C    sync  
-         lbra  L1798
-         orcc  #$1C
-         exg   x,f
-L0084    bsr   L00D6
-L0086    lda   <u0023,u
-         ble   L00A1
-         ldb   <u001F,u
-         cmpb  #$0A
-         bhi   L00A1
-         ldb   u000F,u
-         orb   #$80
-         stb   <u0023,u
-         ldb   u0006,u
-         orb   #$05
-         ldx   u0001,u
-         stb   $02,x
-L00A1    tst   <u0024,u
-         bne   L00D2
-         ldb   <u001E,u
-         leax  <u0027,u
-         orcc  #$50
-         cmpb  <u001D,u
-         beq   L0084
-         abx   
-         lda   ,x
-         dec   <u001F,u
-         incb  
-         cmpb  #$4F
-         bls   L00BF
-         clrb  
-L00BF    stb   <u001E,u
-         clrb  
-         ldb   u000E,u
-         beq   L00CF
-         stb   <$3A,y
-         clr   u000E,u
-         comb  
-         ldb   #$F4
-L00CF    andcc #$AF
-         rts   
-L00D2    comb  
-         ldb   #$F6
-         rts   
-L00D6    pshs  x,b,a
-         lda   u0004,u
-         sta   u0005,u
-         andcc #$AF
-         ldx   #$0000
-         os9   F$Sleep  
-         ldx   <u004B
-         ldb   <$36,x
-         beq   L00EF
-         cmpb  #$03
-         bls   L00F8
-L00EF    clra  
-         lda   $0D,x
-         bita  #$02
-         bne   L00F8
-         puls  pc,x,b,a
-L00F8    leas  $06,s
-         coma  
-         rts   
-L00FC    bsr   L00D6
-L00FE    leax  <u0077,u
-         ldb   <u0020,u
-         abx   
-         sta   ,x
-         incb  
-         cmpb  #$8B
-         bls   L010D
-         clrb  
-L010D    orcc  #$50
-         cmpb  <u0021,u
-         beq   L00FC
-         stb   <u0020,u
-         lda   <u0022,u
-         beq   L012B
-         anda  #$FD
-         sta   <u0022,u
-         bne   L012B
-         lda   u0006,u
-         ora   #$05
-         ldx   u0001,u
-         sta   $02,x
-L012B    andcc #$AF
-L012D    clrb  
-         rts   
-L012F    cmpa  #$01
-         bne   L013E
-         ldb   <u001F,u
-         beq   L00D2
-         ldx   $06,y
-         stb   $02,x
-L013C    clrb  
-         rts   
-L013E    cmpa  #$06
-         beq   L012D
-L0142    comb  
-         ldb   #$D0
-         rts   
-L0146    cmpa  #$1A
-         bne   L0161
-         lda   $05,y
-         ldx   $06,y
-         ldb   $05,x
-         orcc  #$50
-         tst   <u001F,u
-         bne   L015C
-         std   <u0024,u
-         bra   L012B
-L015C    andcc #$AF
-         lbra  L01F8
-L0161    cmpa  #$1B
-         bne   L0142
-         lda   $05,y
-         cmpa  <u0024,u
-         bne   L013C
-         clr   <u0024,u
-         rts   
-L0170    lbsr  L00D6
-L0173    ldx   <u004B
-         lda   ,x
-         sta   u0004,u
-         sta   u0003,u
-         ldb   <u0020,u
-         orcc  #$50
-         cmpb  <u0021,u
-         bne   L0170
-         lda   u0006,u
-         ldx   u0001,u
-         sta   $02,x
-         andcc #$AF
-         ldx   #$0000
-         os9   F$IRQ    
-         rts   
-L0194    ldx   u0001,u
-         tfr   a,b
-         andb  #$60
-         cmpb  <u0026,u
-         beq   L01AB
-         stb   <u0026,u
-         bitb  #$60
-         lbne  L02AE
-         lbra  L029C
-L01AB    bita  #$08
-         bne   L01FD
-         lda   <u0023,u
-         bpl   L01C4
-         anda  #$7F
-         sta   ,x
-         eora  u000F,u
-         sta   <u0023,u
-         lda   <u0022,u
-         bne   L01EA
-         clrb  
-         rts   
-L01C4    leay  <u0077,u
-         ldb   <u0021,u
-         cmpb  <u0020,u
-         beq   L01E2
-         clra  
-         lda   d,y
-         incb  
-         cmpb  #$8B
-         bls   L01D8
-         clrb  
-L01D8    stb   <u0021,u
-         sta   ,x
-         cmpb  <u0020,u
-         bne   L01F0
-L01E2    lda   <u0022,u
-         ora   #$02
-         sta   <u0022,u
-L01EA    ldb   u0006,u
-         orb   #$01
-         stb   $02,x
-L01F0    ldb   #$01
-         lda   u0005,u
-L01F4    beq   L01FB
-         clr   u0005,u
-L01F8    os9   F$Send   
-L01FB    clrb  
-         rts   
-L01FD    bita  #$07
-         beq   L0213
-         tfr   a,b
-         tst   ,x
-         anda  #$07
-         ora   u000E,u
-         sta   u000E,u
-         lda   $02,x
-         sta   $01,x
-         sta   $02,x
-         bra   L01FB
-L0213    lda   ,x
-         beq   L022E
-         cmpa  u000B,u
-         beq   L028B
-         cmpa  u000C,u
-         beq   L028F
-         cmpa  u000D,u
-         beq   L0283
-         cmpa  u000F,u
-         beq   L029C
-         cmpa  <u0010,u
-         lbeq  L02AE
-L022E    leax  <u0027,u
-         ldb   <u001D,u
-         abx   
-         sta   ,x
-         incb  
-         cmpb  #$4F
-         bls   L023D
-         clrb  
-L023D    cmpb  <u001E,u
-         bne   L024A
-         ldb   #$04
-         orb   u000E,u
-         stb   u000E,u
-         bra   L01F0
-L024A    stb   <u001D,u
-         inc   <u001F,u
-         tst   <u0024,u
-         beq   L025D
-         ldd   <u0024,u
-         clr   <u0024,u
-         bra   L01F8
-L025D    lda   <u0010,u
-         beq   L01F0
-         ldb   <u001F,u
-         cmpb  #$46
-         bcs   L01F0
-         ldb   <u0023,u
-         bne   L01F0
-         anda  #$7F
-         sta   <u0010,u
-         ora   #$80
-         sta   <u0023,u
-         ldb   u0006,u
-         orb   #$05
-         ldx   u0001,u
-         stb   $02,x
-         lbra  L01F0
-L0283    ldx   u0009,u
-         beq   L022E
-         sta   $08,x
-         bra   L022E
-L028B    ldb   #$03
-         bra   L0291
-L028F    ldb   #$02
-L0291    pshs  a
-         lda   u0003,u
-         lbsr  L01F4
-         puls  a
-         bra   L022E
-L029C    lda   <u0022,u
-         anda  #$FE
-         sta   <u0022,u
-         bne   L02AC
-         lda   u0006,u
-         ora   #$05
-         sta   $02,x
-L02AC    clrb  
-         rts   
-L02AE    lda   <u0022,u
-         bne   L02B9
-         ldb   u0006,u
-         orb   #$01
-         stb   $02,x
-L02B9    ora   #$01
-         sta   <u0022,u
-         clrb  
-         rts   
+L00EF   clra  
+        lda   	P$State,x		; Get process state
+        bita  	#Condem			; Process condemed ? (being killed ?)
+        bne   	L00F8			; yes : error, exit
+	
+        puls  	pc,x,b,a		; Return
+	
+L00F8   leas  	$06,s
+        coma  
+        rts   
+
+L00FC   bsr   	DoPutProcToSleep
+
+*
+* Input	U = Address of device static data storage
+*	Y = Address of path descriptor module
+*	A = Character to write
+*
+* Output
+*	CC = carry set on error, clear on none
+*	B = error code if CC.C set.
+*
+
+Write   leax  	<TxQueue,u		; Get pointer to transmit queue
+        ldb   	<TxQueueTailOffset,u	; Get offset of end of TX queue
+        abx   				; Calculate next free queue slot
+        sta   	,x			; Put byte to transmit in queue
+        incb  				; Increment queue tail ptr
+        cmpb  	#TxQueueLen-1		; End of Queue area ?
+        bls   	L010D			; no, continue
+        clrb  				; Point at begining of queue area
+	
+L010D   orcc  	#$50			; Disable inturrupts
+        cmpb  	<TxQueueHeadOffset,u	; is Head=Tail therefore queue full ?
+        beq   	L00FC			; Yes : sleep process until room in queue
+	
+        stb   	<TxQueueTailOffset,u	; Re-save tail pointer
+        lda   	<u0022,u
+        beq   	L012B
+        
+	anda  	#$FD
+        sta   	<u0022,u
+        bne   	L012B
+	
+        lda   	V.TYPE,u		; Get parity bits
+        ora   	#TIRB.On+Cmd.DTR	; Enable tranmitter inturrupt & DTR ($05)
+        ldx   	V.PORT,u		; Get port address $FF04
+        sta   	AciaCmd,x		; Write to ACIA
+	
+L012B   andcc 	#$AF			; Enable Inturrupts
+L012D   clrb  				; Flag no error
+        rts
+	
+*
+* Input	U = Address of device static data storage
+*	Y = Address of path descriptor module
+*	A = Status code
+*
+* Output
+*	Depends on status code.
+*
+	
+GetSta  cmpa  	#SS.Ready		; Device ready ? ($01)
+        bne   	L013E
+        
+	ldb   	<u001F,u
+        beq   	ErrorExit
+        
+	ldx   	$06,y
+        stb   	$02,x
+L013C   clrb  
+        rts
+	
+L013E   cmpa  	#SS.EOF			; EOF ? ($06)
+        beq   	L012D
+	
+L0142   comb  				; Flag error
+        ldb   	#$D0
+        rts   
+
+*
+* Input	U = Address of device static data storage
+*	Y = Address of path descriptor module
+*	A = Status code
+*
+* Output
+*	Depends on status code.
+*
+
+SetSta  cmpa  	#SS.SSig		; Send signal on data ready ? ($1A)
+        bne   	L0161
+	
+        lda   	PD.CPR,y		; Get caller's process id
+        ldx   	PD.RGS,y		; Get caller's Regs
+        ldb   	$05,x			; Get lower half of X ????
+	
+        orcc  	#$50			; Disable inturrupts
+        tst   	<u001F,u		
+        bne   	L015C
+	
+        std   	<u0024,u
+        bra   	L012B
+	
+L015C   andcc 	#$AF
+        lbra  	L01F8
+	
+L0161   cmpa  	#SS.Relea		; Release device ? ($1B)
+        bne   	L0142
+	
+        lda   	PD.CPR,y		; Get calling process ID
+        cmpa  	<u0024,u		; Same process ?
+        bne   	L013C			; no !
+        
+	clr   	<u0024,u		; Yes : release 
+        rts 
+	
+L0170   lbsr  	DoPutProcToSleep
+
+*
+* Input	U = Address of device static data storage
+*
+* Output
+*	CC = carry set on error, clear on none
+*	B = error code if CC.C set.
+*
+
+Term   	ldx   	<D.Proc			; Get current process descriptor addr
+        lda   	P$ID,x			; Get process ID
+        sta   	V.BUSY,u		; Save it in busy and last processs
+        sta   	V.LPRC,u
+	
+        ldb   	<TxQueueTailOffset,u	; Check we have sent all bytes ?
+        orcc  	#$50
+        cmpb  	<TxQueueHeadOffset,u
+        bne   	L0170			; Still bytes left to send, wait to send them
+        
+	lda   	V.TYPE,u		; Get Parity settings
+        ldx   	V.PORT,u		; Get port address $FF04
+        sta   	AciaCmd,x		; Set parity in ACIA
+        andcc 	#$AF			; Enable inturrupts
+	
+        ldx   	#$0000			; Remove IRQ handler
+        os9   	F$IRQ    
+        rts   				
+
+*
+* F$IRQ handler,
+*
+* Input :
+*	A	= Status byte XOR flip
+*	U	= our data area
+*
+* In this case, since flip byte is zero, and any value XOR zero
+* remains uncahanged, A contains the contents of the ACIA status
+* register ($FF05)
+*
+
+IRQService
+	ldx   	V.PORT,u		; Get port address $FF04
+        tfr   	a,b			; Take a copy of status
+        andb  	#Stat.DSR+Stat.DCD	; Mask all but DSR & DCD ($60)
+        cmpb  	<SavedDSRDCD,u		; Compare to saved
+        beq   	L01AB			; not changed, check other bits
+	
+        stb   	<SavedDSRDCD,u		; Save DSR & DCD values
+        bitb  	#$60			; Was either set ???
+        lbne  	L02AE			; yes 
+        lbra  	L029C
 
-         emod
-eom      equ   *
-         end
+L01AB   bita  	#Stat.RxF		; Rx register full ? ($08)
+        bne   	L01FD			; yes 
+	
+        lda   	<u0023,u
+        bpl   	L01C4
+
+        anda  	#$7F			
+        sta   	,x
+        eora  	V.XON,u
+        sta   	<u0023,u
+        lda   	<u0022,u
+        bne   	L01EA
+
+        clrb  
+        rts   
+
+L01C4   leay  	<TxQueue,u		; Point to transmit queue
+        ldb   	<TxQueueHeadOffset,u	; Check that there are bytes to transmit
+        cmpb  	<TxQueueTailOffset,u
+        beq   	L01E2			; no : skip
+
+        clra  
+        lda   	d,y			; Get byte to transmit
+        incb  				; Increment head offset ptr
+        cmpb  	#TxQueueLen-1		; Head at end of Queue area ?
+        bls   	L01D8
+
+        clrb  				; Yes : point it at beginning
+L01D8   stb   	<TxQueueHeadOffset,u	; Save it
+        sta   	AciaData,x	; Transmit byte
+        cmpb  	<TxQueueTailOffset,u	; Head=Tail therefore Tx queue empty ?
+        bne   	L01F0			; no : skip ahead
+	
+L01E2   lda   	<u0022,u
+        ora   	#$02
+        sta   	<u0022,u
+	
+L01EA   ldb   	V.TYPE,u		; Get parity settings
+        orb   	#Cmd.DTR		; Enable DTR, ready
+        stb   	AciaCmd,x		; Write to ACIA
+	
+L01F0   ldb   	#S$Wake			; Wake up calling process
+        lda   	V.WAKE,u		; Get proc ID to wake
+L01F4   beq   	L01FB
+
+        clr   	V.WAKE,u		; Clear saved wake proc ID
+L01F8   os9   	F$Send   		; send wakeup signal
+L01FB   clrb  				; Flag no error
+        rts   
+
+L01FD   bita  	#Stat.Par+Stat.Frm+Stat.Ovr	; Check for Parity/Framing/Overrun errors ($07)
+        beq   	L0213			; No Error detected, do read
+
+        tfr   	a,b			; Copy status
+        tst   	,x			
+        anda  	#$07
+        ora   	V.ERR,u
+        sta   	V.ERR,u
+        lda   	$02,x
+        sta   	$01,x
+        sta   	$02,x
+        bra   	L01FB
+	
+L0213   lda   	,x			; Read byte from ACIA
+        beq   	L022E			; zero, branch ahead
+
+        cmpa  	V.INTR,u		; Inturrupt char ?
+        beq   	L028B
+
+        cmpa  	V.QUIT,u		; Quit char ?
+        beq   	L028F
+
+        cmpa  	V.PCHR,u		; Pause char ?
+        beq   	L0283
+
+        cmpa  	V.XON,u			; Xon char ?
+        beq   	L029C
+
+        cmpa  	<V.XOFF,u		; Xoff char ?
+        lbeq  	L02AE
+
+;
+; If we reach here, char is nothing special, so just put it in queue
+;
 
+L022E   leax  	<RxQueue,u		; Point to receive queue
+        ldb   	<RxQueueTailOffset,u	; Get tail offset
+        abx   				; Calculate address
+        sta   	,x			; Put char in queue
+        incb  				; increment tail ptr
+        cmpb  	#RxQueueLen-1		; End of queue area ?
+        bls   	L023D			; no : continue
+
+        clrb  				; point to begining of Rx queue area
+L023D   cmpb  	<RxQueueHeadOffset,u	; Same as head of queue ?
+        bne   	L024A			; no : 
+
+        ldb   	#$04
+        orb   	V.ERR,u			; accumulated errors
+        stb   	V.ERR,u
+        bra   	L01F0
+
+L024A   stb   	<RxQueueTailOffset,u	; Save tail ptr
+        inc   	<u001F,u
+        tst   	<u0024,u
+        beq   	L025D
+
+        ldd   	<u0024,u
+        clr   	<u0024,u
+        bra   	L01F8
+
+L025D   lda   	<V.XOFF,u
+        beq   	L01F0
+
+        ldb   	<u001F,u
+        cmpb  	#$46
+        bcs   	L01F0
+
+        ldb   	<u0023,u
+        bne   	L01F0
+
+        anda  	#$7F
+        sta   	<V.XOFF,u
+        ora   	#$80
+        sta   	<u0023,u
+        
+	ldb   	V.TYPE,u		; Get parity settings
+        orb   	#TIRB.On+Cmd.DTR	; Enable tranmitter inturrupt & DTR ($05)
+        ldx   	V.PORT,u		; Get port address $FF04
+        stb   	AciaCmd,x		; Write to acia
+	
+        lbra  	L01F0
+L0283   ldx   	V.DEV2,u
+        beq   	L022E
+	
+        sta   	$08,x
+        bra   	L022E
+
+L028B   ldb   	#$03
+        bra   	L0291
+
+L028F   ldb   	#$02
+L0291   pshs  	a
+
+        lda   	V.LPRC,u		; Get last active proc ID
+        lbsr  	L01F4			; Wake process
+        puls  	a
+        bra   	L022E
+	
+L029C   lda   	<u0022,u
+        anda  	#$FE
+        sta   	<u0022,u
+        bne   	L02AC
+	
+        lda   	V.TYPE,u		; Get parity settings
+        ora   	#TIRB.On+Cmd.DTR	; Enable tranmitter inturrupt & DTR ($05)
+        sta   	AciaCmd,x		; Write to ACIA
+L02AC   clrb  				; Flag no error
+        rts   
+
+L02AE   lda   	<u0022,u
+        bne   	L02B9
+	
+        ldb   	V.TYPE,u		; Get parity settings
+        orb   	#Cmd.DTR		; Enable DTR 
+        stb   	AciaCmd,x		; Write to ACIA
+	
+L02B9   ora   	#$01
+        sta   	<u0022,u
+        clrb  
+        rts   
+
+	emod
+eom     equ   	*
+        end