Mercurial > hg > Members > kono > nitros9-code
view level1/modules/dw3.asm @ 2313:9e3038c39b01
clock2_dw3 now gets seconds (6 byte time packet)
dw3.asm uses hard coded date instead of dtb so CRC won't go wild
scdwt.asm no longer has date in since it's not needed
author | boisy |
---|---|
date | Sun, 03 Jan 2010 20:29:41 +0000 |
parents | ad5f60988a60 |
children | 5f76d1a611f6 |
line wrap: on
line source
******************************************************************** * 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. nam DW3 ttl DriveWire 3 Low Level Subroutine Module ifp1 use defsfile use dwdefs.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 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 * * ON ENTRY: * X = ADDRESS OF THE RECEIVE BUFFER * A = TIMEOUT VALUE (182 = APPROX ONE SECOND @ 0.89 MHz) * * ON EXIT: * Y = DATA CHECKSUM * D = ACTUAL NUMBER OF BYTES RECEIVED * X AND U ARE PRESERVED * CC.CARRY IS SET IF A FRAMING ERROR WAS DETECTED * Read use dwread.asm * Write * * Entry: Write 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 #$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 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 lbra CkSuspnd ; had to lbra 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 lbne CkSuspnd ;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 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) ; future - handle backing off on polling interval ; save back D on stack and build our U pshs d * mode switch on bits 7+6 of A: 00 = vserial, 01 = system, 10 = wirebug?, 11 = ? anda #$C0 ; mask last 6 bits beq mode00 ; virtual serial mode ; future - handle other modes bra IRQExit ; for now, bail 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 bra IRQExit IRQCont clrb tfr d,u puls d * multiread/status flag is in bit 4 of A bita #$10 beq IRQPutch ; branch 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 bra IRQMulti ;its not all 0, this is a multiread dostat bra IRQExit ; not implemented yet ; 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 * end