changeset 2308:b5f0c5326e7e

Changes made to move ISR to dw3
author boisy
date Sun, 03 Jan 2010 14:35:04 +0000
parents 2f90c1624ab4
children f3e79ee2ffef
files level1/modules/clock2_dw3.asm level1/modules/dw3.asm level1/modules/scdwp.asm level1/modules/scdwt.asm
diffstat 4 files changed, 381 insertions(+), 436 deletions(-) [+]
line wrap: on
line diff
--- a/level1/modules/clock2_dw3.asm	Sun Jan 03 14:29:29 2010 +0000
+++ b/level1/modules/clock2_dw3.asm	Sun Jan 03 14:35:04 2010 +0000
@@ -8,6 +8,9 @@
 * ------------------------------------------------------------------
 *   1      2004/08/18  Boisy G. Pitre
 * Separated clock2 modules for source clarity.
+*
+*   2      2010/01/02  Boisy G. Pitre
+* Saved some bytes by optimizing
 
          nam   Clock2
          ttl   DriveWire 3 RTC Driver
@@ -19,7 +22,7 @@
 tylg     set   Sbrtn+Objct
 atrv     set   ReEnt+rev
 rev      set   $00
-edition  set   1
+edition  set   2
 
 
 RTC.Base equ   $0000     
@@ -42,22 +45,28 @@
          nop
 ex       rts			RTC Set Time
 
-GetTime  pshs  u,y,x
+GetTime  pshs  u,y,x,b
          lda   #'#        Time packet
-	 pshs  a
+	 sta   ,s
 	 leax  ,s
 	 ldy   #$0001
+         IFGT  Level-1
+         ldu   <D.DWSubAddr
+         ELSE
          ldu   >D.DWSubAddr
+         ENDC
+         beq   UpdLeave      in case we failed to link it, just exit
 	 jsr   6,u
-         puls  a        
 * Consider the following optimization
          ldx   #D.Year
 	 ldy   #$0005
          jsr   3,u
-UpdLeave puls  x,y,u,pc
+UpdLeave puls  b,x,y,u,pc
 
 
 Init     
+* We do not bother checking if D.DWSubAddr is $0000 because it will always be since
+* we are the first module to use the subroutine module.
          IFGT    Level-1
          ldx     <D.Proc
          pshs    x
@@ -70,14 +79,13 @@
          IFGT    Level-1
          puls    x
          stx     <D.Proc
-         bcs     InitEx
+         bcs     ex
          sty     <D.DWSubAddr
          ELSE
          bcs     ex
          sty     >D.DWSubAddr
          ENDC
-         jsr     ,y			call initialization routine
-InitEx   rts
+         jmp     ,y			call initialization routine
 
          emod          
 eom      equ   *         
--- a/level1/modules/dw3.asm	Sun Jan 03 14:29:29 2010 +0000
+++ b/level1/modules/dw3.asm	Sun Jan 03 14:35:04 2010 +0000
@@ -17,19 +17,24 @@
          use   dwdefs.d
          endc
 
-tylg     set   Sbrtn+Objct   
-atrv     set   ReEnt+rev
-rev      set   $01
+tylg      set   Sbrtn+Objct   
+atrv      set   ReEnt+rev
+rev       set   $01
+
+          mod   eom,name,tylg,atrv,start,0
 
-         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   dtb
 
-name     fcs   /dw3/
+name      fcs   /dw3/
 
 * DriveWire subroutine entry table
-start    lbra   Init
-         bra    Read
-	 nop
-         lbra   Write
+start     lbra   Init
+          bra    Read
+          nop
+          lbra   Write
 
 * Term
 *
@@ -41,32 +46,8 @@
 *    B  = error code
 *
 Term
-         clrb				clear Carry
-         rts
-
-* 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  cc,x			then push CC on stack
-         orcc  #IntMasks
-         ldx   #PIA1Base		$FF20
-         clr   1,x			clear CD
-         lda   #%11111110
-         sta   ,x
-         lda   #%00110100
-         sta   1,x
-         lda   ,x
-         puls  cc,x,pc
+          clrb				clear Carry
+          rts
 
 * Read
 *
@@ -81,13 +62,307 @@
 *    CC.CARRY IS SET IF A FRAMING ERROR WAS DETECTED
 *
 Read  
-       use  dwread.asm
+          use  dwread.asm
          
 * Write
 *
 * Entry:
 Write    
-         use   dwwrite.asm
+          use   dwwrite.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
+          orcc  #IntMasks
+          ldx   #PIA1Base		$FF20
+          clr   1,x			clear CD
+          lda   #%11111110
+          sta   ,x
+          lda   #%00110100
+          sta   1,x
+          lda   ,x
+
+; 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@
+
+* install ISR
+InstIRQ
+          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
+          ldd     #$0003                  ;lets try every 6 ticks (0.1 seconds) -- testing 3, gives better response in interactive things
+          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    #$1F		; mask first 5 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     6,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     3,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
+          
+          bra     CkSuspnd
+          
+IRQMulti			
+          ; 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
+          bne		CkSuspnd
+          bra		IRQExit
+          
+
+; **** 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     6,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     3,u    		; call DWRead
+          beq     IRQSvc2		; branch if no error
+          leas    2,s     	; error, cleanup stack 2
+          bra		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)
+          beq   	IRQExit  	; branch if D = 0 (nothing to do)
+
+; save back D on stack and build our U
+          pshs    d
+          anda    #$1F		; mask first 5 bits, a is now port #+1
+          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
+          bra     IRQExit
+IRQCont
+          clrb
+          tfr     d,u
+
+          ldd     ,s++     	; pull returned status byte into A,data into B (set Z if zero, N if multiread)
+
+          bmi		IRQMulti	; branch for multiread
+
+; put byte B in port As buffer - optimization help from Darren Atkinson       
+IRQPutCh   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
+
+
+          ; 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   *
--- a/level1/modules/scdwp.asm	Sun Jan 03 14:29:29 2010 +0000
+++ b/level1/modules/scdwp.asm	Sun Jan 03 14:35:04 2010 +0000
@@ -124,7 +124,11 @@
          pshs  d
          leax  ,s
          ldy   #$0002
+         IFGT  Level-1
+         ldu   <D.DWSubAddr
+         ELSE
          ldu   >D.DWSubAddr
+         ENDC
          jsr   6,u
          puls  d,pc
 
@@ -183,11 +187,14 @@
          pshs  a
          ldy   #$0001
          leax  ,s
+         IFGT  Level-1
+         ldu   <D.DWSubAddr
+         ELSE
          ldu   >D.DWSubAddr
+         ENDC
          jsr   6,u
          puls  a,pc
 
-
 Read     comb  
          ldb   #E$BMode
          rts
--- a/level1/modules/scdwt.asm	Sun Jan 03 14:29:29 2010 +0000
+++ b/level1/modules/scdwt.asm	Sun Jan 03 14:35:04 2010 +0000
@@ -30,35 +30,14 @@
 rev      	set   	$00
 edition  	set   	1
 
-* Device memory area: offset from U
-         	org   	V.SCF      	;V.SCF: free memory for driver to use
-
-* input buffer redesign to support multiball, used per instance
-* heavily borrowed from sc6551
-RxDatLen	rmb		1              ;current length of data in Rx buffer
-RxBufSiz	rmb		1              ;Rx buffer size
-RxBufEnd	rmb		2              ;end of Rx buffer
-RxBufGet	rmb		2              ;Rx buffer output pointer
-RxBufPut	rmb		2              ;Rx buffer input pointer
-RxGrab		rmb		1              ;bytes to grab in multiread
-RxBufPtr	rmb		2              ;pointer to Rx buffer
-RxBufDSz	equ		256-.          ;default Rx buffer gets remainder of page...
-RxBuff		rmb		RxBufDSz       ;default Rx buffer
-
-memsize     equ   	.
-
-         	mod   	eom,name,tylg,atrv,start,memsize
+* Note: driver memory defined in dwdefs.d
+         	mod   	eom,name,tylg,atrv,start,SCFDrvMemSz
 
 * module info         	
          	fcb   	READ.+WRITE.	;driver access modes
 name     	fcs   	/scdwt/		;driver name
          	fcb   	edition   	;driver edition 
 
-
-* irq         	
-IRQPckt   	fcb  	$00,$01,$0A 	;IRQ packet Flip(1),Mask(1),Priority(1) bytes
-
-            
 * dispatch calls            
 start    	equ   	*
          	lbra  	Init
@@ -113,85 +92,18 @@
 			beq     nosub		
     		jsr     6,u      	; call DWrite
 
+nosub
             puls    u
 			
     		leas	2,s			; clean 3 DWsub args from stack 
 			
-; check if we need to clean up IRQ
-			bsr     CheckStats
-    		beq		DumpVIRQ	;no more ports, lets bail
     		clrb
 			rts
 
-nosub
 			puls	u
 			leas	2,s
-			bsr		ReleaseMem
 			rts  			
 
-; no more ports open... tear down ISR
-DumpVIRQ   	
-			IFGT    Level-1
-			ldy   	<D.DWStat
-			ELSE
-			ldy   	>D.DWStat
-			ENDC
-			leay    DW.VIRQPkt,y
-         	ldx   	#$0000		;code to delete VIRQ entry
-         	os9   	F$VIRQ		;remove from VIRQ polling
-
-DumpIRQ
-			IFGT    Level-1
-			ldx   	<D.DWStat
-			ELSE
-			ldx   	>D.DWStat
-			ENDC
-			leax    DW.VIRQPkt,x
-			tfr     x,u
-         	leax  	Vi.Stat,x	;fake VIRQ status register
-         	tfr   	x,d			;copy address...
-         	ldx   	#$0000		;code to remove IRQ entry
-         	leay  	IRQSvc,pc	;IRQ service routine
-         	os9   	F$IRQ
-
-ReleaseMem
-			IFGT    Level-1
-			ldu     <D.DWStat
-			ELSE
-			ldu     >D.DWStat
-			ENDC
-			beq     Term.Err
-			ldd     #$0100
-			os9     F$SRtMem
-			ldd     #$0000
-			IFGT    Level-1
-			std   	<D.DWStat
-			ELSE
-			std   	>D.DWStat
-			ENDC
-Term.Err    rts
-
-
-***********************************************************************
-* CheckStats - Check if the D.DWStat table is empty
-* Entry: None
-* Exit:  B=0, stat table is empty; B!=0, stat table is not empty
-CheckStats
-         	pshs  	x
-			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
-			ldb     #7
-CheckLoop   tst     ,x+
-			bne     CheckExit
-			decb
-			bne     CheckLoop
-CheckExit   puls    x,pc
-         	
 ***********************************************************************
 * Init
 *
@@ -237,7 +149,7 @@
          	puls  	x
          	stx   	<D.Proc
          	ENDC
-         	lbcs   	InitEx2
+         	bcs   	InitEx2
          	IFGT  	Level-1
          	sty   	<D.DWSubAddr
          	ELSE
@@ -248,82 +160,6 @@
 			puls	u				; restore u
       	
 already
-; load stat address
-			IFGT    Level-1
-			ldx     <D.DWStat
-			ELSE
-			ldx     >D.DWStat
-			ENDC
-			bne     IRQok			; if non-zero, already been allocated
-
-; allocate DW statics page
-			pshs    u
-			ldd     #$0100
-			os9     F$SRqMem
-			tfr     u,x
-			puls    u
-			bcs		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@
-        	
-; if here, we must install IRQ/VIRQ entry
-InstIRQ
-			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
-         	ldd   	#$0003     		;lets try every 6 ticks (0.1 seconds) -- testing 3, gives better response in interactive things
-			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
-	
 ; set up local buffer
 			ldb   	#RxBufDSz      	; default Rx buffer size
 			leax  	RxBuff,u       	; default Rx buffer address
@@ -360,208 +196,6 @@
 dw3name  	fcs  	/dw3/
 
 
-
-; ***********************************************************************
-; Interrupt handler  - Much help from Darren Atkinson
-			
-IRQMulti3   anda    #$1F		; mask first 5 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     6,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     3,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
-			
-			bra     CkSuspnd
-			
-IRQMulti			
-           	; 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
-  			bne		CkSuspnd
-  			bra		IRQExit
-  			
-
-; **** 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     6,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     3,u    		; call DWRead
-			beq     IRQSvc2		; branch if no error
-			leas    2,s     	; error, cleanup stack 2
-			bra		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)
-  			beq   	IRQExit  	; branch if D = 0 (nothing to do)
-
-; save back D on stack and build our U
-            pshs    d
-  			anda    #$1F		; mask first 5 bits, a is now port #+1
-  			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
-			bra     IRQExit
-IRQCont
-			clrb
-			tfr     d,u
-
-     		ldd     ,s++     	; pull returned status byte into A,data into B (set Z if zero, N if multiread)
-  			
-  			bmi		IRQMulti	; branch for multiread
-  			
-; put byte B in port As buffer - optimization help from Darren Atkinson       
-IRQPutCh   	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
-
-
-  			; 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
-         
-
-			
 *****************************************************************************
 * Write
 *
@@ -788,25 +422,46 @@
 *    B  = error code 
 *
 SetStat  
-			ldb		#OP_SERSETSTAT
-			bsr		SendStat
-			cmpa	#SS.ComSt
-			bne		donebad
-			leax	PD.OPT,y
-			ldy		#OPTCNT
-			IFGT	LEVEL-1
-			ldu		<D.DWSubAddr
-			ELSE
-			ldu		>D.DWSubAddr
-			ENDC
-			jsr		6,u
-done
-			clrb
-			rts
+		ldb	#OP_SERSETSTAT
+		bsr	SendStat
+		cmpa	#SS.ComSt
+		bne	donebad
+		leax	PD.OPT,y
+		ldy	#OPTCNT
+		IFGT	LEVEL-1
+		ldu	<D.DWSubAddr
+		ELSE
+		ldu	>D.DWSubAddr
+		ENDC
+		jsr	6,u
+                clrb
+		rts
+
+SetPortSig      cmpa   #SS.PortSig
+                bne    SetPortRel
+                lda    PD.CPR,y       current process ID
+                ldb    R$X+1,x        LSB of [X] is signal code
+                std    <PortSigPID
+                clrb
+                rts
+SetPortRel      cmpa   #SS.PortRel
+                bne    donebad
+                leax   PortSigPID,u
+                bsr    ReleaSig
+                clrb
+                rts
 donebad		comb
-			ldb		#E$UnkSVc
-			rts
+		ldb	#E$UnkSVc
+		rts
           
-			emod
-eom			equ		*
-			end
+ReleaSig        pshs    cc             save IRQ enable status
+                orcc    #IntMasks      disable IRQs while releasing signal
+                lda     PD.CPR,y       get current process ID
+                suba    ,x             same as signal process ID?
+                bne     NoReleas       no, go return...
+                sta     ,x             clear this signal's process ID
+NoReleas        puls    cc,pc          restore IRQ enable status, return
+
+		emod
+eom		equ		*
+		end