changeset 2249:8cbd8013fe24

rel: now we clear $00-$1F (direct page) in Level 2 scdwt: changes made to driver by Boisy Pitre
author boisy
date Thu, 24 Dec 2009 16:37:49 +0000
parents 02aaa1cde1e4
children 8f641411c2fa
files level1/modules/dwdefs.d level1/modules/rel.asm level1/modules/scdwt.asm
diffstat 3 files changed, 115 insertions(+), 171 deletions(-) [+]
line wrap: on
line diff
--- a/level1/modules/dwdefs.d	Thu Dec 24 16:37:07 2009 +0000
+++ b/level1/modules/dwdefs.d	Thu Dec 24 16:37:49 2009 +0000
@@ -50,5 +50,9 @@
 OP_WIREBUG_WRITEMEM   equ  'm	Write the CoCo's memory
 OP_WIREBUG_GO         equ  'G	Tell CoCo to get out of WireBug mode and continue execution
 
+* VPort opcodes (CoCo-initiated)
+OP_VPORT_READ         equ  'V
+OP_VPORT_WRITE        equ  'v
+
 * Error definitions
 E_CRC      equ   $F3            Same as NitrOS-9 E$CRC
--- a/level1/modules/rel.asm	Thu Dec 24 16:37:07 2009 +0000
+++ b/level1/modules/rel.asm	Thu Dec 24 16:37:49 2009 +0000
@@ -112,7 +112,9 @@
 * This is done so I can tell what went on in the direct page if there's
 * a crash. 0(crash) 1(reset) -1(startup)
          beq   Cont       --don't clear out direct page if it's a crash
-         ldb   #$20       start out at $20
+* BGP 12/24/2009: clear out ALL of direct page (even $00-$1F)
+*         ldb   #$20       start out at $20
+         clrb
          tfr   d,x        here, too
 L0072    sta   ,x+        clear out the direct page
          incb             Boot won't be using any of it!
--- a/level1/modules/scdwt.asm	Thu Dec 24 16:37:07 2009 +0000
+++ b/level1/modules/scdwt.asm	Thu Dec 24 16:37:49 2009 +0000
@@ -29,13 +29,9 @@
 DWTAdr		rmb		2			;pointer to instance with irq handler       
 
 * these are only used in the primary instance
-IRQPorts	rmb		1			;# ports active  
-Instnces	rmb		14			;pointers to each instance of the driver
-RxWaiter	rmb		7			;need to know who to wake per port..
-DWErrors	rmb		1			;number of errors talking to DW server
 
 * For ISR
-VIRQPckt 	rmb   	5			;VIRQ packet Counter(2),Reset(2),Status(1) bytes
+*VIRQPckt 	rmb   	5			;VIRQ packet Counter(2),Reset(2),Status(1) bytes
 
 * port status variables...
 * none yet
@@ -50,7 +46,7 @@
 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
+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...
 *RxBufDSz	equ		20
@@ -78,7 +74,7 @@
          	lbra  	GetStt
          	lbra  	SetStt
 	 	
-         	
+
 ***********************************************************************
 * Term
 *
@@ -94,32 +90,23 @@
 *    B  = error code   
 * NEEDS WORK
 Term     	equ   	*
-			ldy		DWTAdr,u		;main instance base addr
-			* decrement port count
-			*lda		IRQPorts,y		;# ports open
-			*deca	
-			*sta		IRQPorts,y
-			*pshs	a			; save remaining port #
-			pshs	u			; for after dwsub call
-			
-			* remove any waiter table entry
+
 			lda		<V.PORT+1,u		;get our port #
-			leax	RxWaiter,y		;get waiter table base
-			clr		a,x				; clear our entry
+
 			* put setstat args on stack for later
 			ldb		#255
 			pshs 	d				;port #, 255 (term) on stack
-			* remove instance table entry
-			asla					; a*2 
-			leax	Instnces,y		;base of instance table
-			clr		a,x+			;clear 1st byte, inc x
-			clr		a,x				;clear 2nd byte
+			* clear statics table entry
+			ldx   	#D.DWSTATS
+			clr		a,x				;clear out
 			* tell server
 			lda     #OP_SERSETSTAT ; load command
 			pshs   	a      		; command store on stack
 			leax    ,s     		; point X to stack 
 			ldy     #3          ; 3 bytes to send 
     
+            pshs    u
+
 			IFGT  Level-1
 			ldu   	<D.DWSUB
 			ELSE
@@ -127,36 +114,48 @@
 			ENDC
 			
     		jsr     6,u      	; call DWrite
+
+            puls    u
+			
     		leas	3,s			; clean 3 DWsub args from stack 
 			
-    		puls 	u
-    		*lda		,s+			; remaining ports
-    		lda		lportct,pcr
-    		deca
-    		sta		lportct,pcr
+* Check if we need to clean up IRQ
+			bsr     CheckStats
     		beq		DumpVIRQ	;no more ports, lets bail
     		clrb
 			rts
 			
-			* no more ports open.. are we the primary instance?
-DumpVIRQ   	cmpu	DWTAdr,u
-			bne		Term.Err	;we are not.. hmmm
-		 	leay  	VIRQPckt,u	;VIRQ software registers
+* no more ports open.. are we the primary instance?
+DumpVIRQ   	
+			ldy     #D.DWVIRQPkt
          	ldx   	#$0000		;code to delete VIRQ entry
          	os9   	F$VIRQ		;remove from VIRQ polling
          	bcs   	Term.Err	;go report error...
-DumpIRQ  	leax  	VIRQPckt+Vi.Stat,u	;fake VIRQ status register
+DumpIRQ
+			ldx     #D.DWVIRQPkt
+         	leax  	Vi.Stat,x	;fake VIRQ status register
          	tfr   	x,d			;copy address...
          	ldx   	#$0000		;code to remove IRQ entry
+			ldu     #D.DWSTATS  ;ISR doesn't use static storage, so set to $0000
          	leay  	IRQSvc,pc	;IRQ service routine
          	os9   	F$IRQ
 Term.Err    rts
 
 
-*** byte in code to store port count... is this acceptable?
-lportct		fcb		0
-
-
+***********************************************************************
+* CheckStats - Check if the D.DWSTATS table is empty
+* Entry: None
+* Exit:  B=0, stat table is empty; B!=0, stat table is not empty
+CheckStats
+         	pshs  	x
+			ldx     #D.DWSTATS
+			ldb     #7
+CheckLoop   tst     ,x+
+			bne     CheckExit
+			decb
+			bne     CheckLoop
+CheckExit   puls    x,pc
+         	
 ***********************************************************************
 * Init
 *
@@ -172,15 +171,7 @@
 Init		equ		*
 			pshs  cc        save IRQ/Carry status
 
-* Check if D.DWSUB already holds a valid subroutine module pointer
-         	IFGT  	Level-1
-         	ldx   	<D.DWSUB
-         	ELSE
-         	ldx   	>D.DWSUB
-         	ENDC
-         	bne   	DWSetOk
-
-* If here, D.DWSUB is 0, so we must link to subroutine module
+* link to subroutine module
          	pshs	u				;preserve u since os9 link is coming up
 
 			IFGT  	Level-1
@@ -212,65 +203,42 @@
          	* the value seems to remain in memory through a reset, so see if any ports active
          	* should be >0 only if the IRQ is installed
          	* trying local byte..
-         	lda		lportct,pcr
-         	bne		DWTAdrOk
+         	bsr     CheckStats
+         	bne		IRQok
          	
-         	
-* If here, ports is 0, so we must install ISR and set D.DWTAdr
+* If here, we must install ISR
      
 
 * Install the IRQ/VIRQ entry 
-
-InstIRQ		leax  	VIRQPckt+Vi.Stat,u 	;fake VIRQ status register
+InstIRQ
+			ldx     #D.DWVIRQPkt
+		    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
+            pshs    u
+			ldu     #D.DWSTATS
          	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
-         	std   	VIRQPckt+Vi.Rst,u 	;reset count
+			ldx     #D.DWVIRQPkt
+         	std   	Vi.Rst,x		;reset count
+			tfr     x,y             ;move VIRQ software packet to Y
          	ldx   	#$0001     		;code to install new VIRQ
-         	leay  	VIRQPckt,u 		;VIRQ software registers
          	os9   	F$VIRQ			;install
          	bcc   	IRQok1st   		;no error, continue
 *         	bsr   	DumpIRQ    		;go remove from IRQ polling - is this necessary? according to OS9 dev ref, if I return an error it calls Term for me?  vrn.asm does this though
          	puls  	cc,pc			;recover error info and exit
          	
-IRQok1st	lda		#1				;first port opening
-			sta		lportct,pcr		;store
-			pshs	a				;for dwsub call
-			
-			* Set D.DWTAdr
-			IFGT  	Level-1
-         	stu   	<D.DWTAdr
-         	ELSE
-         	stu   	>D.DWTAdr
-         	ENDC
-         	
-         	stu		DWTAdr,u		;local DWTAdr pointer
-         	tfr		u,x				;x is used below
-			bra		IRQok
-			
-			* value of exisiting DWTAdr in X 
-DWTAdrOk	inca					;otherwise, note +1 ports
-			sta		lportct,pcr		;store it
-			pshs	a				; for dwsub call
-			
-			* save our pointer to ISR instance
-			IFGT  	Level-1
-         	ldx   	<D.DWTAdr
-         	ELSE
-         	ldx   	>D.DWTAdr
-         	ENDC
-			stx		DWTAdr,u				
-
-			* add our address to main instance's pointer table
-IRQok  		lda		<V.PORT+1,u		;get our port #
-			asla					; *2 
-			leax	Instnces,x		;base of instance table
-			stu		a,x				;store in table
+IRQok1st	
+IRQok
+         	ldx   	#D.DWSTATS
+			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
@@ -284,6 +252,7 @@
 
 			* tell DW we've got a new port opening
 			ldb		<V.PORT+1,u		; get our port #			
+			pshs    b
 			lda     #OP_SERSETSTAT 	; command 
 			pshs   	d      			; command + port # on stack
 			leax    ,s     			; point X to stack 
@@ -312,7 +281,8 @@
 * Interrupt handler  - Much help from Darren Atkinson
 
 			
-IRQMulti3	cmpb	RxGrab,u	;compare room in buffer to server's byte
+IRQMulti3   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
@@ -327,7 +297,7 @@
 			stb		RxGrab,u	;else set grab to room left
 			
 			* send multiread req
-IRQM03		lda		4,s			;port # is on stack behind our U and the PC from bsr call in multi2		
+IRQM03		puls    a			;port # is on stack
 			ldb		RxGrab,u
 
 			pshs	u
@@ -375,15 +345,9 @@
 			addb	RxGrab,u
 			stb		RxDatLen,u	;store new value
 			
-			puls	u
 			rts
 			
-IRQMulti	pshs	u			;save local u
-			
- 			leax    Instnces,u	;base of instance pointer table
-           	asla           		;a*2 bytes per instance address
-           	ldu     a,x     	;U = pointer to instance data from table, now buffervar,u points to this port's buffer, etc	
-  			
+IRQMulti			
            	* initial grab bytes
            	stb		RxGrab,u	
            	
@@ -392,32 +356,25 @@
            	subb	RxDatLen,u	;current bytes in buffer
            	bne		IRQMulti3	;continue, we have some space in buffer
   			* no room in buffer
-  			puls	u
-  			rts
-           	
-IRQMulti2	anda    #$07		;mask first 5 bits, a is now port #+1
-  			deca				;we pass +1 to use 0 for no data
-  			pshs	a			;save port # for serreadm call and return to cksuspnd
-  			bsr		IRQMulti
-  			cmpb	#0
+  			tstb
   			bne		CkSuspnd
-  			leas	1,s
   			bra		IRQExit
   			
+
+**** IRQ ENTRY POINT
 IRQSvc		equ		*
 			pshs  	cc,dp 		;save system cc,DP
 			orcc	#$50		;mask interrupts
 			
 			* mark VIRQ handled
-			lda   	VIRQPckt+Vi.Stat,u	;VIRQ status register
+			ldx     #D.DWVIRQPkt
+			lda   	Vi.Stat,x	;VIRQ status register
 			anda  	#^Vi.IFlag 	;clear flag in VIRQ status register
-			sta   	VIRQPckt+Vi.Stat,u	;save it...
+			sta   	Vi.Stat,x	;save it...
 			
 			* poll server for incoming serial data
-			
+ 			
 			* send request
-			pshs 	u			;see U later
-			
 			lda     #OP_SERREAD ; load command
 			pshs   	a      		; command store on stack
 			leax    ,s     		; point X to stack 
@@ -437,35 +394,51 @@
 			jsr     3,u    		; call DWRead
 			beq     IRQSvc2		; branch if no error
 			leas    2,s     	; error, cleanup stack 2
-			puls	u			; get U back
-			lda		DWErrors,u	; current error count	 
-			inca
-			* TODO - At some point, decide to bail out
-			sta		DWErrors,u	; store new error count
 			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)
-
-  			puls	u			; get local u back - stack should be clean except initial save of cc and dp
-
+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)
-  			
-  			bmi		IRQMulti2	; branch for multiread
-  			
-  			* get port # (last 3 bits of status byte (a)
+
+* save back D on stack and build our U
+            pshs    d
   			anda    #$07		;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
+			ldx     #D.DWSTATS
+			lda     a,x
+			tfr     a,dp		;put in DP
+			clrb
+			tfr     d,u
+
+     		ldd     ,s++     	; pull returned status byte into A,data into B (set Z if zero, N if multiread)
   			
-  			pshs	a			;save port #
-  			bsr		IRQPutCh	;put one character into buffer
+  			bmi		IRQMulti	; branch for multiread
+  			
+* put byte B in port A's buffer - optimization help from Darren Atkinson       
+IRQPutCh   	ldx     RxBufPut,u	;point X to the data buffer
+        
+			* sc6551 now does lots of things with flow control, we might want some of this
+			* but implemented differently.. for now.. skip it
+		   
+			* store our data byte
+			stb    	,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   	puls	b			;stack has port #
-			leax	RxWaiter,u	;waiter table
-			lda   	b,x       	;waiter?
+CkSuspnd   	lda   	<V.WAKE,u   	;V.WAKE?
 			beq   	IRQExit   	;no
-			clr 	b,x			;clear waiter
+			clr 	<V.WAKE,u		;clear V.WAKE
 			
 			* wake up waiter for read
 			IFEQ  	Level-1
@@ -479,38 +452,10 @@
 			sta   	P$State,x      ;save state flags
 			ENDC
 
-IRQExit		clr		DWErrors,u	;reset DW error count	           
-IRQExit2  	puls  	cc,dp		;restore interrupts cc,dp
-			rts					;return
+IRQExit
+IRQExit2  	puls  	cc,dp,pc		;restore interrupts cc,dp, return
          
 
-* put byte B in port A's buffer - optimization help from Darren Atkinson       
-IRQPutCh    pshs    u,b     	;save u and our data byte
-           	leax    Instnces,u	;base of instance pointer table
-           	asla           		;a*2 bytes per instance address
-           	ldu     a,x     	;U = pointer to instance data from table
-           	ldx     RxBufPut,u	;point X to the data buffer
-        
-			* sc6551 now does lots of things with flow control, we might want some of this
-			* but implemented differently.. for now.. skip it
-		   
-			* store our data byte
-			puls	a			;retrieve 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
-			lda		RxDatLen,u
-			inca	
-			sta		RxDatLen,u
-
-			puls	u,pc		;restore u, rts
-	
 			
 *****************************************************************************
 * Write
@@ -570,17 +515,13 @@
 
 ReadSlp		equ		*
 
-			ldy		DWTAdr,u	;offset to main instance
-			leax	RxWaiter,y	; X = waiter table address
-			ldb		V.PORT+1,u	;port number into B
-			
            	IFEQ  	Level-1
-ReadSlp2   	lda   	<V.BUSY
-           	sta   	b,x			;store process id in this port's entry in the waiter table
+ReadSlp2   	lda   	<V.BUSY,u
+           	sta   	<V.WAKE,u		;store process id in this port's entry in the waiter table
            	lbsr  	Sleep0     	;sleep level 1 style
            	ELSE
 ReadSlp2   	lda   	>D.Proc    	;process descriptor address MSB
-           	sta   	b,x        	;save MSB in waiter table
+           	sta   	<V.WAKE,u        	;save MSB in V.WAKE
            	clrb
            	tfr		d,x			;process descriptor address
            	IFNE  	H6309
@@ -613,10 +554,7 @@
            	bne   	PrAbtErr 	;yes, go do it...
            	
            	* check that our waiter byte was cleared by ISR instance
-           	ldy		DWTAdr,u	;offset to main instance
-			leax	RxWaiter,y	; X = waiter address for this port
-			ldb		V.PORT+1,u	;port number into B
-			lda		b,x			;our waiter byte
+			lda		<V.WAKE,u		;our waiter byte
 			beq		ReadChr		;0 = its our turn, go get a character 
            	bra   	ReadSlp		;false alarm, go back to sleep