changeset 2875:3231faca9642

Rename dw.asm to dwio.asm
author Tormod Volden <debian.tormod@gmail.com>
date Sun, 24 Nov 2013 15:28:44 +0100
parents 89cb16c2a83c
children 1ca5c484c7a7
files level1/coco/modules/makefile level1/modules/dw.asm level1/modules/dwio.asm level2/coco3/modules/makefile
diffstat 4 files changed, 583 insertions(+), 583 deletions(-) [+]
line wrap: on
line diff
--- a/level1/coco/modules/makefile	Sun Nov 24 13:27:24 2013 +0100
+++ b/level1/coco/modules/makefile	Sun Nov 24 15:28:44 2013 +0100
@@ -93,10 +93,10 @@
 boot_dw_becker: boot_dw.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) -aBECKER=1
 
-dw_coco1.sb: dw.asm
+dw_coco1.sb: dwio.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) -aBAUD38400=1
 
-dwio_becker.sb: dw.asm
+dwio_becker.sb: dwio.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) -aBECKER=1
 
 boot_1773_6ms:	boot_1773.asm
--- a/level1/modules/dw.asm	Sun Nov 24 13:27:24 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,580 +0,0 @@
-********************************************************************
-* DW3 - DriveWire 3 Low Level Subroutine Module
-*
-* $Id$
-*
-* Edt/Rev  YYYY/MM/DD  Modified by
-* Comment
-* ------------------------------------------------------------------
-*   1      2008/01/26  Boisy G. Pitre
-* Started as a segregated subroutine module.
-*
-*   2      2010/01/20  Boisy G. Pitre
-* Added support for DWNet
-*
-*   3      2010/01/23  Aaron A. Wolfe
-* Added dynamic polling frequency
-*
-               nam       DW3
-               ttl       DriveWire 3 Low Level Subroutine Module
-
-               ifp1      
-               use       defsfile
-               use       drivewire.d
-               endc      
-
-tylg           set       Sbrtn+Objct
-atrv           set       ReEnt+rev
-rev            set       $01
-
-               mod       eom,name,tylg,atrv,start,0
-
-* irq
-IRQPckt        fcb       $00,$01,$0A         ;IRQ packet Flip(1),Mask(1),Priority(1) bytes
-* Default time packet
-DefTime        fcb       109,12,31,23,59,59
-
-* for dynamic poll frequency, number of ticks between firing poller - should we move to dwdefs?
-* speed 1 = interactive (typing)
-PollSpd1       fcb       3
-* speed 2 = bulk transfer (depending on how much processing needs to be done to incoming stream, 5-8 seems good)
-PollSpd2       fcb       6
-* speed 3 = idle 
-PollSpd3       fcb       40
-* X pollidle -> drop to next slower rate
-PollIdle       fcb       60
-
-
-name           fcs       /dw3/
-
-* DriveWire subroutine entry table
-start          lbra      Init
-               bra       Read
-               nop       
-               lbra      Write
-
-* Term
-*
-* Entry:
-*    U  = address of device memory area
-*
-* Exit:
-*    CC = carry set on error
-*    B  = error code
-*
-Term                     
-               clrb                          clear Carry
-               rts       
-
-Read                     
-               use       dwread.asm
-
-Write                    
-               use       dwwrite.asm
-
-
-			use		dwinit.asm
-			
-* Init
-*
-* Entry:
-*    Y  = address of device descriptor
-*    U  = address of device memory area
-*
-* Exit:
-*    CC = carry set on error
-*    B  = error code
-*
-* Initialize the serial device
-Init                     
-               clrb                          clear Carry
-               pshs      y,x,cc              then push CC on stack
-               bsr		DWInit
-
-; allocate DW statics page
-               pshs      u
-               ldd       #$0100
-               os9       F$SRqMem
-               tfr       u,x
-               puls      u
-               lbcs      InitEx
-               ifgt      Level-1
-               stx       <D.DWStat
-               else      
-               stx       >D.DWStat
-               endc      
-; clear out 256 byte page at X
-               clrb      
-loop@          clr       ,x+
-               decb      
-               bne       loop@
-
-* send OP_DWINIT
-         ; setup DWsub command
-               pshs      u
-               ldb		 #1					 ; DRIVER VERSION
-               lda       #OP_DWINIT          ; load command
-               pshs      d                   ; command store on stack
-               leax      ,s                  ; point X to stack 
-               ldy       #2                  ; 1 byte to send
-               ifgt      Level-1
-               ldu       <D.DWSubAddr
-               else      
-               ldu       >D.DWSubAddr
-               endc      
-               jsr       DW$Write,u                 ; call DWrite
-               leas      1,s                 ; leave one byte on stack for response 
-               
-               ; read protocol version response, 1 byte
-               leax      ,s                  ; point X to stack head
-               ldy       #1                  ; 1 byte to retrieve
-               jsr       DW$Read,u                 ; call DWRead
-               IFNE      atari-1
-               beq       InstIRQ             ; branch if no error
-               ENDC
-               leas      3,s                 ; error, cleanup stack (u and 1 byte from read) 
-               lbra      InitEx            	 ; don't install IRQ handler
-
-* install ISR
-InstIRQ                  
-			   puls      a,u		; a has proto version from server.. not used yet
-
-			   ifgt      Level-1
-               ldx       <D.DWStat
-               else      
-               ldx       >D.DWStat
-               endc      
-               leax      DW.VIRQPkt,x
-               pshs      u
-               tfr       x,u
-               leax      Vi.Stat,x           ;fake VIRQ status register
-               lda       #$80                ;VIRQ flag clear, repeated VIRQs
-               sta       ,x                  ;set it while we're here...
-               tfr       x,d                 ;copy fake VIRQ status register address
-               leax      IRQPckt,pcr         ;IRQ polling packet
-               leay      IRQSvc,pcr          ;IRQ service entry
-               os9       F$IRQ               ;install
-               puls      u
-               bcs       InitEx              ;exit with error
-               clra      
-               ldb       PollSpd3,pcr        ; start at idle
-               ifgt      Level-1
-               ldx       <D.DWStat
-               else      
-               ldx       >D.DWStat
-               endc      
-               leax      DW.VIRQPkt,x
-               std       Vi.Rst,x            ; reset count
-               tfr       x,y                 ; move VIRQ software packet to Y
-tryagain                 
-               ldx       #$0001              ; code to install new VIRQ
-               os9       F$VIRQ              ; install
-               bcc       IRQok               ; no error, continue
-               cmpb      #E$UnkSvc
-               bne       InitEx
-; if we get an E$UnkSvc error, then clock has not been initialized, so do it here
-               leax      DefTime,pcr
-               os9       F$STime
-               bra       tryagain            ; note: this has the slim potential of looping forever
-IRQok                    
-               ifgt      Level-1
-               ldx       <D.DWStat
-               else      
-               ldx       >D.DWStat
-               endc      
-; cheat: we know DW.StatTbl is at offset $00 from D.DWStat, do not bother with leax
-               leax      DW.StatTbl,x
-               tfr       u,d
-               ldb       <V.PORT+1,u         ; get our port #
-               sta       b,x                 ; store in table
-
-InitEx                   
-               puls      cc,x,y,pc
-
-
-; ***********************************************************************
-; Interrupt handler  - Much help from Darren Atkinson
-
-IRQMulti3      anda      #$0F                ; mask first 4 bits, a is now port #+1
-               deca                          ; we pass +1 to use 0 for no data
-               pshs      a                   ; save port #
-               cmpb      RxGrab,u            ; compare room in buffer to server's byte
-               bhs       IRQM06              ; room left >= server's bytes, no problem
-
-               stb       RxGrab,u            ; else replace with room left in our buffer
-
-          ; also limit to end of buffer
-IRQM06         ldd       RxBufEnd,u          ; end addr of buffer
-               subd      RxBufPut,u          ; subtract current write pointer, result is # bytes left going forward in buff.
-
-IRQM05         cmpb      RxGrab,u            ; compare b (room left) to grab bytes  
-               bhs       IRQM03              ; branch if we have room for grab bytes
-
-               stb       RxGrab,u            ; else set grab to room left
-
-          ; send multiread req
-IRQM03         puls      a                   ; port # is on stack
-               ldb       RxGrab,u
-
-               pshs      u
-
-          ; setup DWsub command
-               pshs      d                   ; (a port, b bytes)
-               lda       #OP_SERREADM        ; load command
-               pshs      a                   ; command store on stack
-               leax      ,s                  ; point X to stack 
-               ldy       #3                  ; 3 bytes to send
-
-               ifgt      Level-1
-               ldu       <D.DWSubAddr
-               else      
-               ldu       >D.DWSubAddr
-               endc      
-               jsr       DW$Write,u                 ; call DWrite
-
-               leas      3,s                 ; clean 3 DWsub args from stack 
-
-               ldx       ,s                  ; pointer to this port's area (from U prior), leave it on stack
-               ldb       RxGrab,x            ; set B to grab bytes
-               clra                          ; 0 in high byte		
-               tfr       d,y                 ; set # bytes for DW
-
-               ldx       RxBufPut,x          ; point X to insert position in this port's buffer
-          ; receive response
-               jsr       DW$Read,u                 ; call DWRead
-          ; handle errors?
-
-
-               puls      u
-               ldb       RxGrab,u            ; our grab bytes
-
-          ; set new RxBufPut
-               ldx       RxBufPut,u          ; current write pointer
-               abx                           ; add b (# bytes) to RxBufPut
-               cmpx      RxBufEnd,u          ; end of Rx buffer?
-               blo       IRQM04              ; no, go keep laydown pointer
-               ldx       RxBufPtr,u          ; get Rx buffer start address
-IRQM04         stx       RxBufPut,u          ; set new Rx data laydown pointer
-
-          ; set new RxDatLen
-               ldb       RxDatLen,u
-               addb      RxGrab,u
-               stb       RxDatLen,u          ; store new value
-
-               lbra      CkSSig              ; had to lbra
-
-IRQMulti                 
-		  ; set IRQ freq for bulk
-               pshs      a
-               lda       PollSpd2,pcr
-               lbsr      IRQsetFRQ
-               puls      a
-
-          ; initial grab bytes
-               stb       RxGrab,u
-
-          ; limit server bytes to bufsize - datlen
-               ldb       RxBufSiz,u          ; size of buffer
-               subb      RxDatLen,u          ; current bytes in buffer
-               bne       IRQMulti3           ; continue, we have some space in buffer
-          ; no room in buffer
-               tstb      
-               lbne      CkSSig              ;had to lbra
-               lbra      IRQExit             ;had to lbra
-
-
-; **** IRQ ENTRY POINT
-IRQSvc         equ       *
-               pshs      cc,dp               ; save system cc,DP
-               orcc      #IntMasks           ; mask interrupts
-
-          ; mark VIRQ handled (note U is pointer to our VIRQ packet in DP)
-               lda       Vi.Stat,u           ; VIRQ status register
-               anda      #^Vi.IFlag          ; clear flag in VIRQ status register
-               sta       Vi.Stat,u           ; save it...
-
-          ; poll server for incoming serial data
-
-          ; send request
-               lda       #OP_SERREAD         ; load command
-               pshs      a                   ; command store on stack
-               leax      ,s                  ; point X to stack 
-               ldy       #1                  ; 1 byte to send
-
-               ifgt      Level-1
-               ldu       <D.DWSubAddr
-               else      
-               ldu       >D.DWSubAddr
-               endc      
-               jsr       DW$Write,u                 ; call DWrite
-
-          ; receive response
-               leas      -1,s                ; one more byte to fit response
-               leax      ,s                  ; point X to stack head
-               ldy       #2                  ; 2 bytes to retrieve
-               jsr       DW$Read,u                 ; call DWRead
-               beq       IRQSvc2             ; branch if no error
-               leas      2,s                 ; error, cleanup stack 2
-               lbra      IRQExit2            ; don't reset error count on the way out
-
-          ; process response	
-IRQSvc2                  
-               ldd       ,s++                ; pull returned status byte into A,data into B (set Z if zero, N if multiread)
-               bne       IRQGotOp            ; branch if D != 0 (something to do)
-* this is a NOP response.. do we need to reschedule
-               ifgt      Level-1
-               ldx       <D.DWStat
-               else      
-               ldx       >D.DWStat
-               endc      
-               lda       DW.VIRQPkt+Vi.Rst+1,x
-               cmpa      PollSpd3,pcr
-               lbeq      IRQExit             ;we are already at idle speed
-
-               lda       DW.VIRQNOP,x
-               inca      
-               cmpa      PollIdle,pcr
-               beq       FRQdown
-
-               sta       DW.VIRQNOP,x        ;inc NOP count, exit
-               lbra      IRQExit
-
-FRQdown        lda       DW.VIRQPkt+Vi.Rst+1,x
-               cmpa      PollSpd1,pcr
-               beq       FRQd1
-               lda       PollSpd3,pcr
-FRQd2                    
-               sta       DW.VIRQPkt+Vi.Rst+1,x
-               clr       DW.VIRQNOP,x
-               lbra      IRQExit
-FRQd1          lda       PollSpd2,pcr
-               bra       FRQd2
-
-; save back D on stack and build our U
-IRQGotOp       pshs      d
-          * mode switch on bits 7+6 of A: 00 = vserial, 01 = vwindow, 10 = wirebug?, 11 = ?							
-               anda      #$C0                ; mask last 6 bits
-               beq       mode00              ; virtual serial mode
-          					; future - handle other modes
-               cmpa      #%01000000          ; vwindow?
-               beq       mode01
-               lbra      IRQExit             ; for now, bail
-
-* Virtual Window Handler
-mode01
-               lda       ,s
-               anda      #%00110000
-               beq       key
-               lbra      IRQExit
-
-key
-               lda       ,s
-               anda      #$0F
-               ora       #$10
-               ifgt      Level-1
-               ldx       <D.DWStat
-               else      
-               ldx       >D.DWStat
-               endc      
-; cheat: we know DW.StatTbl is at offset $00 from D.DWStat, do not bother with leax
-;			leax    DW.StatTbl,x
-               lda       a,x
-               clrb      
-               tfr       d,u
-               puls      d
-               lbra      IRQPutch
-
-               
-* Virtual Serial Handler
-mode00         lda       ,s                  ; restore A		  
-               anda      #$0F                ; mask first 4 bits, a is now port #+1
-               beq       IRQCont             ; if we're here with 0 in the port, its not really a port # (can we jump straight to status?)
-               deca                          ; we pass +1 to use 0 for no data
-; here we set U to the static storage area of the device we are working with
-               ifgt      Level-1
-               ldx       <D.DWStat
-               else      
-               ldx       >D.DWStat
-               endc      
-; cheat: we know DW.StatTbl is at offset $00 from D.DWStat, do not bother with leax
-;			leax    DW.StatTbl,x
-               lda       a,x
-               bne       IRQCont             ; if A is 0, then this device is not active, so exit
-               puls      d
-               lbra      IRQExit
-IRQCont                  
-               clrb      
-               tfr       d,u
-
-               puls      d
-
-          * multiread/status flag is in bit 4 of A
-               bita      #$10
-               beq       IRQPutch            ; branch for read1 if multiread not set
-
-          * all 0s in port means status, anything else is multiread
-
-               bita      #$0F                ;mask bit 7-4
-               beq       dostat              ;port # all 0, this is a status response
-               lbra      IRQMulti            ;its not all 0, this is a multiread
-
-
-		 * in status events, databyte is split, 4bits status, 4bits port #          
-dostat         bitb      #$F0                ;mask low bits
-               lbne      IRQExit             ;we only implement code 0000, term
-			* set u to port #
-               ifgt      Level-1
-               ldx       <D.DWStat
-               else      
-               ldx       >D.DWStat
-               endc      
-               lda       b,x
-               bne       statcont            ; if A is 0, then this device is not active, so exit
-               lbra      IRQExit
-
-* IRQ set freq routine
-* sets freq and clears NOP counter
-* a = desired IRQ freq
-IRQsetFRQ      pshs      x                   ; preserve
-               ifgt      Level-1
-               ldx       <D.DWStat
-               else      
-               ldx       >D.DWStat
-               endc      
-               sta       DW.VIRQPkt+Vi.Rst+1,x
-* +++ BGP +++ added following line so that the counter (which was copied by
-* clock before calling us) gets reset to the same value the reset value. Without
-* this line, we get called again with the PRIOR Vi.Rst value.
-               sta       DW.VIRQPkt+Vi.Cnt+1,x
-               clr       DW.VIRQNOP,x
-               puls      x
-               rts       
-
-
-* This routine roots through process descriptors in a queue and
-* checks to see if the process has a path that is open to the device
-* represented by the static storage pointer in U. if so, the S$HUP
-* signal is sent to that process
-*
-* Entry: X = process descriptor to evaluate
-*        U = static storage of device we want to check against
-RootThrough              
-               ldb       #NumPaths
-               leay      P$Path,x
-               pshs      x
-loop           decb      
-               bmi       out
-               lda       ,y+
-               beq       loop
-               pshs      y
-               ifgt      Level-1
-               ldx       <D.PthDBT
-               else      
-               ldx       >D.PthDBT
-               endc      
-               os9       F$Find64
-               ldx       PD.DEV,y
-               leax      V$STAT,x
-               puls      y
-               bcs       out
-
-               cmpu      ,x
-               bne       loop
-
-               ldx       ,s
-               lda       P$ID,x
-               ldb       #S$HUP
-               os9       F$Send
-
-out            puls      x
-               ldx       P$Queue,x
-               bne       RootThrough
-               rts       
-
-statcont       clrb      
-               tfr       d,u
-* NEW: root through all process descriptors. if any has a path open to this
-* device, send then S$HUP
-               ldx       <D.AProcQ
-               beq       dowaitq
-               bsr       RootThrough
-dowaitq        ldx       <D.WProcQ
-               beq       dosleepq
-               bsr       RootThrough
-dosleepq       ldx       <D.SProcQ
-               beq       CkLPRC
-               bsr       RootThrough
-
-CkLPRC                   
-               lda       <V.LPRC,u
-               beq       IRQExit             ; no last process, bail
-               ldb       #S$HUP
-               os9       F$Send              ; send signal, don't think we can do anything about an error result anyway.. so
-               bra       CkSuspnd            ; do we need to go check suspend?
-
-; put byte B in port As buffer - optimization help from Darren Atkinson       
-IRQPutCh                 
-		  ; set IRQ freq for bulk
-               lda       PollSpd1,pcr
-               lbsr      IRQsetFRQ
-               ldx       RxBufPut,u          ; point X to the data buffer
-
-; process interrupt/quit characters here
-; note we will have to do this in the multiread (ugh)
-               tfr       b,a                 ; put byte in A
-               ldb       #S$Intrpt
-               cmpa      V.INTR,u
-               beq       send@
-               ldb       #S$Abort
-               cmpa      V.QUIT,u
-               bne       store
-send@          lda       V.LPRC,u
-               beq       IRQExit
-               os9       F$Send
-               bra       IRQExit
-
-store                    
-          ; store our data byte
-               sta       ,x+                 ; store and increment buffer pointer
-
-          ; adjust RxBufPut	
-               cmpx      RxBufEnd,u          ; end of Rx buffer?
-               blo       IRQSkip1            ; no, go keep laydown pointer
-               ldx       RxBufPtr,u          ; get Rx buffer start address
-IRQSkip1       stx       RxBufPut,u          ; set new Rx data laydown pointer
-
-          ; increment RxDatLen
-               inc       RxDatLen,u
-
-CkSSig                   
-               lda       <SSigID,u           ; send signal on data ready?
-               beq       CkSuspnd
-               ldb       <SSigSg,u           ; else get signal code
-               os9       F$Send
-               clr       <SSigID,u
-               bra       IRQExit
-
-          ; check if we have a process waiting for data	
-CkSuspnd                 
-               lda       <V.WAKE,u           ; V.WAKE?
-               beq       IRQExit             ; no
-               clr       <V.WAKE,u           ; clear V.WAKE
-
-          ; wake up waiter for read
-               ifeq      Level-1
-               ldb       #S$Wake
-               os9       F$Send
-               else      
-               clrb      
-               tfr       d,x                 ; copy process descriptor pointer
-               lda       P$State,x           ; get state flags
-               anda      #^Suspend           ; clear suspend state
-               sta       P$State,x           ; save state flags
-               endc      
-
-IRQExit                  
-IRQExit2       puls      cc,dp,pc            ; restore interrupts cc,dp, return
-
-               emod      
-eom            equ       *
-               end       
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/level1/modules/dwio.asm	Sun Nov 24 15:28:44 2013 +0100
@@ -0,0 +1,580 @@
+********************************************************************
+* DW3 - DriveWire 3 Low Level Subroutine Module
+*
+* $Id$
+*
+* Edt/Rev  YYYY/MM/DD  Modified by
+* Comment
+* ------------------------------------------------------------------
+*   1      2008/01/26  Boisy G. Pitre
+* Started as a segregated subroutine module.
+*
+*   2      2010/01/20  Boisy G. Pitre
+* Added support for DWNet
+*
+*   3      2010/01/23  Aaron A. Wolfe
+* Added dynamic polling frequency
+*
+               nam       DW3
+               ttl       DriveWire 3 Low Level Subroutine Module
+
+               ifp1      
+               use       defsfile
+               use       drivewire.d
+               endc      
+
+tylg           set       Sbrtn+Objct
+atrv           set       ReEnt+rev
+rev            set       $01
+
+               mod       eom,name,tylg,atrv,start,0
+
+* irq
+IRQPckt        fcb       $00,$01,$0A         ;IRQ packet Flip(1),Mask(1),Priority(1) bytes
+* Default time packet
+DefTime        fcb       109,12,31,23,59,59
+
+* for dynamic poll frequency, number of ticks between firing poller - should we move to dwdefs?
+* speed 1 = interactive (typing)
+PollSpd1       fcb       3
+* speed 2 = bulk transfer (depending on how much processing needs to be done to incoming stream, 5-8 seems good)
+PollSpd2       fcb       6
+* speed 3 = idle 
+PollSpd3       fcb       40
+* X pollidle -> drop to next slower rate
+PollIdle       fcb       60
+
+
+name           fcs       /dw3/
+
+* DriveWire subroutine entry table
+start          lbra      Init
+               bra       Read
+               nop       
+               lbra      Write
+
+* Term
+*
+* Entry:
+*    U  = address of device memory area
+*
+* Exit:
+*    CC = carry set on error
+*    B  = error code
+*
+Term                     
+               clrb                          clear Carry
+               rts       
+
+Read                     
+               use       dwread.asm
+
+Write                    
+               use       dwwrite.asm
+
+
+			use		dwinit.asm
+			
+* Init
+*
+* Entry:
+*    Y  = address of device descriptor
+*    U  = address of device memory area
+*
+* Exit:
+*    CC = carry set on error
+*    B  = error code
+*
+* Initialize the serial device
+Init                     
+               clrb                          clear Carry
+               pshs      y,x,cc              then push CC on stack
+               bsr		DWInit
+
+; allocate DW statics page
+               pshs      u
+               ldd       #$0100
+               os9       F$SRqMem
+               tfr       u,x
+               puls      u
+               lbcs      InitEx
+               ifgt      Level-1
+               stx       <D.DWStat
+               else      
+               stx       >D.DWStat
+               endc      
+; clear out 256 byte page at X
+               clrb      
+loop@          clr       ,x+
+               decb      
+               bne       loop@
+
+* send OP_DWINIT
+         ; setup DWsub command
+               pshs      u
+               ldb		 #1					 ; DRIVER VERSION
+               lda       #OP_DWINIT          ; load command
+               pshs      d                   ; command store on stack
+               leax      ,s                  ; point X to stack 
+               ldy       #2                  ; 1 byte to send
+               ifgt      Level-1
+               ldu       <D.DWSubAddr
+               else      
+               ldu       >D.DWSubAddr
+               endc      
+               jsr       DW$Write,u                 ; call DWrite
+               leas      1,s                 ; leave one byte on stack for response 
+               
+               ; read protocol version response, 1 byte
+               leax      ,s                  ; point X to stack head
+               ldy       #1                  ; 1 byte to retrieve
+               jsr       DW$Read,u                 ; call DWRead
+               IFNE      atari-1
+               beq       InstIRQ             ; branch if no error
+               ENDC
+               leas      3,s                 ; error, cleanup stack (u and 1 byte from read) 
+               lbra      InitEx            	 ; don't install IRQ handler
+
+* install ISR
+InstIRQ                  
+			   puls      a,u		; a has proto version from server.. not used yet
+
+			   ifgt      Level-1
+               ldx       <D.DWStat
+               else      
+               ldx       >D.DWStat
+               endc      
+               leax      DW.VIRQPkt,x
+               pshs      u
+               tfr       x,u
+               leax      Vi.Stat,x           ;fake VIRQ status register
+               lda       #$80                ;VIRQ flag clear, repeated VIRQs
+               sta       ,x                  ;set it while we're here...
+               tfr       x,d                 ;copy fake VIRQ status register address
+               leax      IRQPckt,pcr         ;IRQ polling packet
+               leay      IRQSvc,pcr          ;IRQ service entry
+               os9       F$IRQ               ;install
+               puls      u
+               bcs       InitEx              ;exit with error
+               clra      
+               ldb       PollSpd3,pcr        ; start at idle
+               ifgt      Level-1
+               ldx       <D.DWStat
+               else      
+               ldx       >D.DWStat
+               endc      
+               leax      DW.VIRQPkt,x
+               std       Vi.Rst,x            ; reset count
+               tfr       x,y                 ; move VIRQ software packet to Y
+tryagain                 
+               ldx       #$0001              ; code to install new VIRQ
+               os9       F$VIRQ              ; install
+               bcc       IRQok               ; no error, continue
+               cmpb      #E$UnkSvc
+               bne       InitEx
+; if we get an E$UnkSvc error, then clock has not been initialized, so do it here
+               leax      DefTime,pcr
+               os9       F$STime
+               bra       tryagain            ; note: this has the slim potential of looping forever
+IRQok                    
+               ifgt      Level-1
+               ldx       <D.DWStat
+               else      
+               ldx       >D.DWStat
+               endc      
+; cheat: we know DW.StatTbl is at offset $00 from D.DWStat, do not bother with leax
+               leax      DW.StatTbl,x
+               tfr       u,d
+               ldb       <V.PORT+1,u         ; get our port #
+               sta       b,x                 ; store in table
+
+InitEx                   
+               puls      cc,x,y,pc
+
+
+; ***********************************************************************
+; Interrupt handler  - Much help from Darren Atkinson
+
+IRQMulti3      anda      #$0F                ; mask first 4 bits, a is now port #+1
+               deca                          ; we pass +1 to use 0 for no data
+               pshs      a                   ; save port #
+               cmpb      RxGrab,u            ; compare room in buffer to server's byte
+               bhs       IRQM06              ; room left >= server's bytes, no problem
+
+               stb       RxGrab,u            ; else replace with room left in our buffer
+
+          ; also limit to end of buffer
+IRQM06         ldd       RxBufEnd,u          ; end addr of buffer
+               subd      RxBufPut,u          ; subtract current write pointer, result is # bytes left going forward in buff.
+
+IRQM05         cmpb      RxGrab,u            ; compare b (room left) to grab bytes  
+               bhs       IRQM03              ; branch if we have room for grab bytes
+
+               stb       RxGrab,u            ; else set grab to room left
+
+          ; send multiread req
+IRQM03         puls      a                   ; port # is on stack
+               ldb       RxGrab,u
+
+               pshs      u
+
+          ; setup DWsub command
+               pshs      d                   ; (a port, b bytes)
+               lda       #OP_SERREADM        ; load command
+               pshs      a                   ; command store on stack
+               leax      ,s                  ; point X to stack 
+               ldy       #3                  ; 3 bytes to send
+
+               ifgt      Level-1
+               ldu       <D.DWSubAddr
+               else      
+               ldu       >D.DWSubAddr
+               endc      
+               jsr       DW$Write,u                 ; call DWrite
+
+               leas      3,s                 ; clean 3 DWsub args from stack 
+
+               ldx       ,s                  ; pointer to this port's area (from U prior), leave it on stack
+               ldb       RxGrab,x            ; set B to grab bytes
+               clra                          ; 0 in high byte		
+               tfr       d,y                 ; set # bytes for DW
+
+               ldx       RxBufPut,x          ; point X to insert position in this port's buffer
+          ; receive response
+               jsr       DW$Read,u                 ; call DWRead
+          ; handle errors?
+
+
+               puls      u
+               ldb       RxGrab,u            ; our grab bytes
+
+          ; set new RxBufPut
+               ldx       RxBufPut,u          ; current write pointer
+               abx                           ; add b (# bytes) to RxBufPut
+               cmpx      RxBufEnd,u          ; end of Rx buffer?
+               blo       IRQM04              ; no, go keep laydown pointer
+               ldx       RxBufPtr,u          ; get Rx buffer start address
+IRQM04         stx       RxBufPut,u          ; set new Rx data laydown pointer
+
+          ; set new RxDatLen
+               ldb       RxDatLen,u
+               addb      RxGrab,u
+               stb       RxDatLen,u          ; store new value
+
+               lbra      CkSSig              ; had to lbra
+
+IRQMulti                 
+		  ; set IRQ freq for bulk
+               pshs      a
+               lda       PollSpd2,pcr
+               lbsr      IRQsetFRQ
+               puls      a
+
+          ; initial grab bytes
+               stb       RxGrab,u
+
+          ; limit server bytes to bufsize - datlen
+               ldb       RxBufSiz,u          ; size of buffer
+               subb      RxDatLen,u          ; current bytes in buffer
+               bne       IRQMulti3           ; continue, we have some space in buffer
+          ; no room in buffer
+               tstb      
+               lbne      CkSSig              ;had to lbra
+               lbra      IRQExit             ;had to lbra
+
+
+; **** IRQ ENTRY POINT
+IRQSvc         equ       *
+               pshs      cc,dp               ; save system cc,DP
+               orcc      #IntMasks           ; mask interrupts
+
+          ; mark VIRQ handled (note U is pointer to our VIRQ packet in DP)
+               lda       Vi.Stat,u           ; VIRQ status register
+               anda      #^Vi.IFlag          ; clear flag in VIRQ status register
+               sta       Vi.Stat,u           ; save it...
+
+          ; poll server for incoming serial data
+
+          ; send request
+               lda       #OP_SERREAD         ; load command
+               pshs      a                   ; command store on stack
+               leax      ,s                  ; point X to stack 
+               ldy       #1                  ; 1 byte to send
+
+               ifgt      Level-1
+               ldu       <D.DWSubAddr
+               else      
+               ldu       >D.DWSubAddr
+               endc      
+               jsr       DW$Write,u                 ; call DWrite
+
+          ; receive response
+               leas      -1,s                ; one more byte to fit response
+               leax      ,s                  ; point X to stack head
+               ldy       #2                  ; 2 bytes to retrieve
+               jsr       DW$Read,u                 ; call DWRead
+               beq       IRQSvc2             ; branch if no error
+               leas      2,s                 ; error, cleanup stack 2
+               lbra      IRQExit2            ; don't reset error count on the way out
+
+          ; process response	
+IRQSvc2                  
+               ldd       ,s++                ; pull returned status byte into A,data into B (set Z if zero, N if multiread)
+               bne       IRQGotOp            ; branch if D != 0 (something to do)
+* this is a NOP response.. do we need to reschedule
+               ifgt      Level-1
+               ldx       <D.DWStat
+               else      
+               ldx       >D.DWStat
+               endc      
+               lda       DW.VIRQPkt+Vi.Rst+1,x
+               cmpa      PollSpd3,pcr
+               lbeq      IRQExit             ;we are already at idle speed
+
+               lda       DW.VIRQNOP,x
+               inca      
+               cmpa      PollIdle,pcr
+               beq       FRQdown
+
+               sta       DW.VIRQNOP,x        ;inc NOP count, exit
+               lbra      IRQExit
+
+FRQdown        lda       DW.VIRQPkt+Vi.Rst+1,x
+               cmpa      PollSpd1,pcr
+               beq       FRQd1
+               lda       PollSpd3,pcr
+FRQd2                    
+               sta       DW.VIRQPkt+Vi.Rst+1,x
+               clr       DW.VIRQNOP,x
+               lbra      IRQExit
+FRQd1          lda       PollSpd2,pcr
+               bra       FRQd2
+
+; save back D on stack and build our U
+IRQGotOp       pshs      d
+          * mode switch on bits 7+6 of A: 00 = vserial, 01 = vwindow, 10 = wirebug?, 11 = ?							
+               anda      #$C0                ; mask last 6 bits
+               beq       mode00              ; virtual serial mode
+          					; future - handle other modes
+               cmpa      #%01000000          ; vwindow?
+               beq       mode01
+               lbra      IRQExit             ; for now, bail
+
+* Virtual Window Handler
+mode01
+               lda       ,s
+               anda      #%00110000
+               beq       key
+               lbra      IRQExit
+
+key
+               lda       ,s
+               anda      #$0F
+               ora       #$10
+               ifgt      Level-1
+               ldx       <D.DWStat
+               else      
+               ldx       >D.DWStat
+               endc      
+; cheat: we know DW.StatTbl is at offset $00 from D.DWStat, do not bother with leax
+;			leax    DW.StatTbl,x
+               lda       a,x
+               clrb      
+               tfr       d,u
+               puls      d
+               lbra      IRQPutch
+
+               
+* Virtual Serial Handler
+mode00         lda       ,s                  ; restore A		  
+               anda      #$0F                ; mask first 4 bits, a is now port #+1
+               beq       IRQCont             ; if we're here with 0 in the port, its not really a port # (can we jump straight to status?)
+               deca                          ; we pass +1 to use 0 for no data
+; here we set U to the static storage area of the device we are working with
+               ifgt      Level-1
+               ldx       <D.DWStat
+               else      
+               ldx       >D.DWStat
+               endc      
+; cheat: we know DW.StatTbl is at offset $00 from D.DWStat, do not bother with leax
+;			leax    DW.StatTbl,x
+               lda       a,x
+               bne       IRQCont             ; if A is 0, then this device is not active, so exit
+               puls      d
+               lbra      IRQExit
+IRQCont                  
+               clrb      
+               tfr       d,u
+
+               puls      d
+
+          * multiread/status flag is in bit 4 of A
+               bita      #$10
+               beq       IRQPutch            ; branch for read1 if multiread not set
+
+          * all 0s in port means status, anything else is multiread
+
+               bita      #$0F                ;mask bit 7-4
+               beq       dostat              ;port # all 0, this is a status response
+               lbra      IRQMulti            ;its not all 0, this is a multiread
+
+
+		 * in status events, databyte is split, 4bits status, 4bits port #          
+dostat         bitb      #$F0                ;mask low bits
+               lbne      IRQExit             ;we only implement code 0000, term
+			* set u to port #
+               ifgt      Level-1
+               ldx       <D.DWStat
+               else      
+               ldx       >D.DWStat
+               endc      
+               lda       b,x
+               bne       statcont            ; if A is 0, then this device is not active, so exit
+               lbra      IRQExit
+
+* IRQ set freq routine
+* sets freq and clears NOP counter
+* a = desired IRQ freq
+IRQsetFRQ      pshs      x                   ; preserve
+               ifgt      Level-1
+               ldx       <D.DWStat
+               else      
+               ldx       >D.DWStat
+               endc      
+               sta       DW.VIRQPkt+Vi.Rst+1,x
+* +++ BGP +++ added following line so that the counter (which was copied by
+* clock before calling us) gets reset to the same value the reset value. Without
+* this line, we get called again with the PRIOR Vi.Rst value.
+               sta       DW.VIRQPkt+Vi.Cnt+1,x
+               clr       DW.VIRQNOP,x
+               puls      x
+               rts       
+
+
+* This routine roots through process descriptors in a queue and
+* checks to see if the process has a path that is open to the device
+* represented by the static storage pointer in U. if so, the S$HUP
+* signal is sent to that process
+*
+* Entry: X = process descriptor to evaluate
+*        U = static storage of device we want to check against
+RootThrough              
+               ldb       #NumPaths
+               leay      P$Path,x
+               pshs      x
+loop           decb      
+               bmi       out
+               lda       ,y+
+               beq       loop
+               pshs      y
+               ifgt      Level-1
+               ldx       <D.PthDBT
+               else      
+               ldx       >D.PthDBT
+               endc      
+               os9       F$Find64
+               ldx       PD.DEV,y
+               leax      V$STAT,x
+               puls      y
+               bcs       out
+
+               cmpu      ,x
+               bne       loop
+
+               ldx       ,s
+               lda       P$ID,x
+               ldb       #S$HUP
+               os9       F$Send
+
+out            puls      x
+               ldx       P$Queue,x
+               bne       RootThrough
+               rts       
+
+statcont       clrb      
+               tfr       d,u
+* NEW: root through all process descriptors. if any has a path open to this
+* device, send then S$HUP
+               ldx       <D.AProcQ
+               beq       dowaitq
+               bsr       RootThrough
+dowaitq        ldx       <D.WProcQ
+               beq       dosleepq
+               bsr       RootThrough
+dosleepq       ldx       <D.SProcQ
+               beq       CkLPRC
+               bsr       RootThrough
+
+CkLPRC                   
+               lda       <V.LPRC,u
+               beq       IRQExit             ; no last process, bail
+               ldb       #S$HUP
+               os9       F$Send              ; send signal, don't think we can do anything about an error result anyway.. so
+               bra       CkSuspnd            ; do we need to go check suspend?
+
+; put byte B in port As buffer - optimization help from Darren Atkinson       
+IRQPutCh                 
+		  ; set IRQ freq for bulk
+               lda       PollSpd1,pcr
+               lbsr      IRQsetFRQ
+               ldx       RxBufPut,u          ; point X to the data buffer
+
+; process interrupt/quit characters here
+; note we will have to do this in the multiread (ugh)
+               tfr       b,a                 ; put byte in A
+               ldb       #S$Intrpt
+               cmpa      V.INTR,u
+               beq       send@
+               ldb       #S$Abort
+               cmpa      V.QUIT,u
+               bne       store
+send@          lda       V.LPRC,u
+               beq       IRQExit
+               os9       F$Send
+               bra       IRQExit
+
+store                    
+          ; store our data byte
+               sta       ,x+                 ; store and increment buffer pointer
+
+          ; adjust RxBufPut	
+               cmpx      RxBufEnd,u          ; end of Rx buffer?
+               blo       IRQSkip1            ; no, go keep laydown pointer
+               ldx       RxBufPtr,u          ; get Rx buffer start address
+IRQSkip1       stx       RxBufPut,u          ; set new Rx data laydown pointer
+
+          ; increment RxDatLen
+               inc       RxDatLen,u
+
+CkSSig                   
+               lda       <SSigID,u           ; send signal on data ready?
+               beq       CkSuspnd
+               ldb       <SSigSg,u           ; else get signal code
+               os9       F$Send
+               clr       <SSigID,u
+               bra       IRQExit
+
+          ; check if we have a process waiting for data	
+CkSuspnd                 
+               lda       <V.WAKE,u           ; V.WAKE?
+               beq       IRQExit             ; no
+               clr       <V.WAKE,u           ; clear V.WAKE
+
+          ; wake up waiter for read
+               ifeq      Level-1
+               ldb       #S$Wake
+               os9       F$Send
+               else      
+               clrb      
+               tfr       d,x                 ; copy process descriptor pointer
+               lda       P$State,x           ; get state flags
+               anda      #^Suspend           ; clear suspend state
+               sta       P$State,x           ; save state flags
+               endc      
+
+IRQExit                  
+IRQExit2       puls      cc,dp,pc            ; restore interrupts cc,dp, return
+
+               emod      
+eom            equ       *
+               end       
--- a/level2/coco3/modules/makefile	Sun Nov 24 13:27:24 2013 +0100
+++ b/level2/coco3/modules/makefile	Sun Nov 24 15:28:44 2013 +0100
@@ -119,7 +119,7 @@
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) -aBECKER=1
 
 # DriveWire 3 Becker Submodule
-dwio_becker.sb: dw.asm
+dwio_becker.sb: dwio.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) -aBECKER=1
 
 # CoGrf/CoVDG Modules