Mercurial > hg > Members > kono > nitros9-code
annotate level1/modules/dw3.asm @ 2375:707480b7f0b0
Updated
author | boisy |
---|---|
date | Thu, 21 Jan 2010 13:07:03 +0000 |
parents | 895dec31461a |
children | b399116a3b5f |
rev | line source |
---|---|
2180 | 1 ******************************************************************** |
2 * DW3 - DriveWire 3 Low Level Subroutine Module | |
3 * | |
4 * $Id$ | |
5 * | |
6 * Edt/Rev YYYY/MM/DD Modified by | |
7 * Comment | |
8 * ------------------------------------------------------------------ | |
9 * 1 2008/01/26 Boisy G. Pitre | |
10 * Started as a segregated subroutine module. | |
2374 | 11 * |
12 * 2 2010/01/20 Boisy G. Pitre | |
13 * Added support for DWNet | |
2180 | 14 |
2374 | 15 nam DW3 |
16 ttl DriveWire 3 Low Level Subroutine Module | |
2180 | 17 |
2374 | 18 ifp1 |
19 use defsfile | |
20 use dwdefs.d | |
21 endc | |
2180 | 22 |
2374 | 23 tylg set Sbrtn+Objct |
24 atrv set ReEnt+rev | |
25 rev set $01 | |
2308 | 26 |
2374 | 27 mod eom,name,tylg,atrv,start,0 |
2180 | 28 |
2308 | 29 * irq |
2374 | 30 IRQPckt fcb $00,$01,$0A ;IRQ packet Flip(1),Mask(1),Priority(1) bytes |
2308 | 31 * Default time packet |
2374 | 32 DefTime fcb 109,12,31,23,59,59 |
2180 | 33 |
2374 | 34 name fcs /dw3/ |
2180 | 35 |
36 * DriveWire subroutine entry table | |
2374 | 37 start lbra Init |
38 bra Read | |
39 nop | |
40 lbra Write | |
2180 | 41 |
42 * Term | |
43 * | |
44 * Entry: | |
45 * U = address of device memory area | |
46 * | |
47 * Exit: | |
48 * CC = carry set on error | |
49 * B = error code | |
50 * | |
2374 | 51 Term |
52 clrb clear Carry | |
53 rts | |
2180 | 54 |
55 * Read | |
56 * | |
57 * ON ENTRY: | |
58 * X = ADDRESS OF THE RECEIVE BUFFER | |
59 * A = TIMEOUT VALUE (182 = APPROX ONE SECOND @ 0.89 MHz) | |
60 * | |
61 * ON EXIT: | |
62 * Y = DATA CHECKSUM | |
63 * D = ACTUAL NUMBER OF BYTES RECEIVED | |
64 * X AND U ARE PRESERVED | |
65 * CC.CARRY IS SET IF A FRAMING ERROR WAS DETECTED | |
66 * | |
2374 | 67 Read |
68 use dwread.asm | |
69 | |
2180 | 70 * Write |
71 * | |
72 * Entry: | |
2374 | 73 Write |
74 use dwwrite.asm | |
2308 | 75 |
76 * Init | |
77 * | |
78 * Entry: | |
79 * Y = address of device descriptor | |
80 * U = address of device memory area | |
81 * | |
82 * Exit: | |
83 * CC = carry set on error | |
84 * B = error code | |
85 * | |
86 * Initialize the serial device | |
2374 | 87 Init |
88 clrb clear Carry | |
89 pshs y,x,cc then push CC on stack | |
90 orcc #IntMasks | |
91 ldx #PIA1Base $FF20 | |
92 clr 1,x clear CD | |
93 lda #%11111110 | |
94 sta ,x | |
95 lda #%00110100 | |
96 sta 1,x | |
97 lda ,x | |
2308 | 98 |
99 ; allocate DW statics page | |
2374 | 100 pshs u |
101 ldd #$0100 | |
102 os9 F$SRqMem | |
103 tfr u,x | |
104 puls u | |
105 lbcs InitEx | |
106 ifgt Level-1 | |
107 stx <D.DWStat | |
108 else | |
109 stx >D.DWStat | |
110 endc | |
2308 | 111 ; clear out 256 byte page at X |
2374 | 112 clrb |
113 loop@ clr ,x+ | |
114 decb | |
115 bne loop@ | |
2308 | 116 |
2321
6a5ada3e2666
added DWINIT op code, dw3 now sends on init just before installing VIRQ
aaronwolfe
parents:
2316
diff
changeset
|
117 * send OP_DWINIT |
6a5ada3e2666
added DWINIT op code, dw3 now sends on init just before installing VIRQ
aaronwolfe
parents:
2316
diff
changeset
|
118 ; setup DWsub command |
2374 | 119 pshs u |
120 lda #OP_DWINIT ; load command | |
121 pshs a ; command store on stack | |
122 leax ,s ; point X to stack | |
123 ldy #1 ; 1 byte to send | |
124 ifgt Level-1 | |
125 ldu <D.DWSubAddr | |
126 else | |
127 ldu >D.DWSubAddr | |
128 endc | |
129 jsr 6,u ; call DWrite | |
130 leas 1,s ; clean 1 DWsub arg from stack | |
131 puls u | |
132 | |
2308 | 133 * install ISR |
2374 | 134 InstIRQ |
135 ifgt Level-1 | |
136 ldx <D.DWStat | |
137 else | |
138 ldx >D.DWStat | |
139 endc | |
140 leax DW.VIRQPkt,x | |
141 pshs u | |
142 tfr x,u | |
143 leax Vi.Stat,x ;fake VIRQ status register | |
144 lda #$80 ;VIRQ flag clear, repeated VIRQs | |
145 sta ,x ;set it while we're here... | |
146 tfr x,d ;copy fake VIRQ status register address | |
147 leax IRQPckt,pcr ;IRQ polling packet | |
148 leay IRQSvc,pcr ;IRQ service entry | |
149 os9 F$IRQ ;install | |
150 puls u | |
151 bcs InitEx ;exit with error | |
152 ldd #$0003 ;lets try every 6 ticks (0.1 seconds) -- testing 3, gives better response in interactive things | |
153 ifgt Level-1 | |
154 ldx <D.DWStat | |
155 else | |
156 ldx >D.DWStat | |
157 endc | |
158 leax DW.VIRQPkt,x | |
159 std Vi.Rst,x ; reset count | |
160 tfr x,y ; move VIRQ software packet to Y | |
161 tryagain | |
162 ldx #$0001 ; code to install new VIRQ | |
163 os9 F$VIRQ ; install | |
164 bcc IRQok ; no error, continue | |
165 cmpb #E$UnkSvc | |
166 bne InitEx | |
2308 | 167 ; if we get an E$UnkSvc error, then clock has not been initialized, so do it here |
2374 | 168 leax DefTime,pcr |
169 os9 F$STime | |
170 bra tryagain ; note: this has the slim potential of looping forever | |
171 IRQok | |
172 ifgt Level-1 | |
173 ldx <D.DWStat | |
174 else | |
175 ldx >D.DWStat | |
176 endc | |
2308 | 177 ; cheat: we know DW.StatTbl is at offset $00 from D.DWStat, do not bother with leax |
2374 | 178 leax DW.StatTbl,x |
179 tfr u,d | |
180 ldb <V.PORT+1,u ; get our port # | |
181 sta b,x ; store in table | |
2308 | 182 |
2374 | 183 InitEx |
184 puls cc,x,y,pc | |
2308 | 185 |
186 | |
187 ; *********************************************************************** | |
188 ; Interrupt handler - Much help from Darren Atkinson | |
2374 | 189 |
190 IRQMulti3 anda #$0F ; mask first 4 bits, a is now port #+1 | |
191 deca ; we pass +1 to use 0 for no data | |
192 pshs a ; save port # | |
193 cmpb RxGrab,u ; compare room in buffer to server's byte | |
194 bhs IRQM06 ; room left >= server's bytes, no problem | |
195 | |
196 stb RxGrab,u ; else replace with room left in our buffer | |
2308 | 197 |
198 ; also limit to end of buffer | |
2374 | 199 IRQM06 ldd RxBufEnd,u ; end addr of buffer |
200 subd RxBufPut,u ; subtract current write pointer, result is # bytes left going forward in buff. | |
201 | |
202 IRQM05 cmpb RxGrab,u ; compare b (room left) to grab bytes | |
203 bhs IRQM03 ; branch if we have room for grab bytes | |
2308 | 204 |
2374 | 205 stb RxGrab,u ; else set grab to room left |
206 | |
2308 | 207 ; send multiread req |
2374 | 208 IRQM03 puls a ; port # is on stack |
209 ldb RxGrab,u | |
2308 | 210 |
2374 | 211 pshs u |
212 | |
2308 | 213 ; setup DWsub command |
2374 | 214 pshs d ; (a port, b bytes) |
215 lda #OP_SERREADM ; load command | |
216 pshs a ; command store on stack | |
217 leax ,s ; point X to stack | |
218 ldy #3 ; 3 bytes to send | |
2308 | 219 |
2374 | 220 ifgt Level-1 |
221 ldu <D.DWSubAddr | |
222 else | |
223 ldu >D.DWSubAddr | |
224 endc | |
225 jsr 6,u ; call DWrite | |
2308 | 226 |
2374 | 227 leas 3,s ; clean 3 DWsub args from stack |
2308 | 228 |
2374 | 229 ldx ,s ; pointer to this port's area (from U prior), leave it on stack |
230 ldb RxGrab,x ; set B to grab bytes | |
231 clra ; 0 in high byte | |
232 tfr d,y ; set # bytes for DW | |
2308 | 233 |
2374 | 234 ldx RxBufPut,x ; point X to insert position in this port's buffer |
2308 | 235 ; receive response |
2374 | 236 jsr 3,u ; call DWRead |
2308 | 237 ; handle errors? |
238 | |
239 | |
2374 | 240 puls u |
241 ldb RxGrab,u ; our grab bytes | |
2308 | 242 |
243 ; set new RxBufPut | |
2374 | 244 ldx RxBufPut,u ; current write pointer |
245 abx ; add b (# bytes) to RxBufPut | |
246 cmpx RxBufEnd,u ; end of Rx buffer? | |
247 blo IRQM04 ; no, go keep laydown pointer | |
248 ldx RxBufPtr,u ; get Rx buffer start address | |
249 IRQM04 stx RxBufPut,u ; set new Rx data laydown pointer | |
2308 | 250 |
251 ; set new RxDatLen | |
2374 | 252 ldb RxDatLen,u |
253 addb RxGrab,u | |
254 stb RxDatLen,u ; store new value | |
255 | |
256 lbra CkSSig ; had to lbra | |
257 | |
258 IRQMulti | |
2308 | 259 ; initial grab bytes |
2374 | 260 stb RxGrab,u |
261 | |
2308 | 262 ; limit server bytes to bufsize - datlen |
2374 | 263 ldb RxBufSiz,u ; size of buffer |
264 subb RxDatLen,u ; current bytes in buffer | |
265 bne IRQMulti3 ; continue, we have some space in buffer | |
2308 | 266 ; no room in buffer |
2374 | 267 tstb |
268 lbne CkSSig ;had to lbra | |
269 lbra IRQExit ;had to lbra | |
270 | |
2308 | 271 |
272 ; **** IRQ ENTRY POINT | |
2374 | 273 IRQSvc equ * |
274 pshs cc,dp ; save system cc,DP | |
275 orcc #IntMasks ; mask interrupts | |
2308 | 276 |
277 ; mark VIRQ handled (note U is pointer to our VIRQ packet in DP) | |
2374 | 278 lda Vi.Stat,u ; VIRQ status register |
279 anda #^Vi.IFlag ; clear flag in VIRQ status register | |
280 sta Vi.Stat,u ; save it... | |
2308 | 281 |
282 ; poll server for incoming serial data | |
283 | |
284 ; send request | |
2374 | 285 lda #OP_SERREAD ; load command |
286 pshs a ; command store on stack | |
287 leax ,s ; point X to stack | |
288 ldy #1 ; 1 byte to send | |
2308 | 289 |
2374 | 290 ifgt Level-1 |
291 ldu <D.DWSubAddr | |
292 else | |
293 ldu >D.DWSubAddr | |
294 endc | |
295 jsr 6,u ; call DWrite | |
2308 | 296 |
297 ; receive response | |
2374 | 298 leas -1,s ; one more byte to fit response |
299 leax ,s ; point X to stack head | |
300 ldy #2 ; 2 bytes to retrieve | |
301 jsr 3,u ; call DWRead | |
302 beq IRQSvc2 ; branch if no error | |
303 leas 2,s ; error, cleanup stack 2 | |
304 lbra IRQExit2 ; don't reset error count on the way out | |
2308 | 305 |
306 ; process response | |
2374 | 307 IRQSvc2 |
308 ldd ,s++ ; pull returned status byte into A,data into B (set Z if zero, N if multiread) | |
309 lbeq IRQExit ; branch if D = 0 (nothing to do) | |
2311 | 310 ; future - handle backing off on polling interval |
2308 | 311 |
2374 | 312 |
2308 | 313 ; save back D on stack and build our U |
2374 | 314 pshs d |
2311 | 315 * mode switch on bits 7+6 of A: 00 = vserial, 01 = system, 10 = wirebug?, 11 = ? |
2374 | 316 anda #$C0 ; mask last 6 bits |
317 beq mode00 ; virtual serial mode | |
2311 | 318 ; future - handle other modes |
2374 | 319 lbra IRQExit ; for now, bail |
320 | |
321 mode00 lda ,s ; restore A | |
322 anda #$0F ; mask first 4 bits, a is now port #+1 | |
323 beq IRQCont ; if we're here with 0 in the port, its not really a port # (can we jump straight to status?) | |
324 deca ; we pass +1 to use 0 for no data | |
2308 | 325 ; here we set U to the static storage area of the device we are working with |
2374 | 326 ifgt Level-1 |
327 ldx <D.DWStat | |
328 else | |
329 ldx >D.DWStat | |
330 endc | |
2308 | 331 ; cheat: we know DW.StatTbl is at offset $00 from D.DWStat, do not bother with leax |
332 ; leax DW.StatTbl,x | |
2374 | 333 lda a,x |
334 bne IRQCont ; if A is 0, then this device is not active, so exit | |
335 puls d | |
336 lbra IRQExit | |
337 IRQCont | |
338 clrb | |
339 tfr d,u | |
340 | |
341 puls d | |
2308 | 342 |
2311 | 343 * multiread/status flag is in bit 4 of A |
2374 | 344 bita #$10 |
345 beq IRQPutch ; branch if multiread not set | |
346 | |
2311 | 347 * all 0s in port means status, anything else is multiread |
2374 | 348 |
349 bita #$0F ;mask bit 7-4 | |
350 beq dostat ;port # all 0, this is a status response | |
351 bra IRQMulti ;its not all 0, this is a multiread | |
2308 | 352 |
2314
5f76d1a611f6
term signal sending for serread port status responses
aaronwolfe
parents:
2313
diff
changeset
|
353 |
5f76d1a611f6
term signal sending for serread port status responses
aaronwolfe
parents:
2313
diff
changeset
|
354 * in status events, databyte is split, 4bits status, 4bits port # |
2374 | 355 dostat bitb #$F0 ;mask low bits |
356 lbne IRQExit ;we only implement code 0000, term | |
2314
5f76d1a611f6
term signal sending for serread port status responses
aaronwolfe
parents:
2313
diff
changeset
|
357 * set u to port # |
2374 | 358 ifgt Level-1 |
359 ldx <D.DWStat | |
360 else | |
361 ldx >D.DWStat | |
362 endc | |
363 lda b,x | |
364 bne statcont ; if A is 0, then this device is not active, so exit | |
365 lbra IRQExit | |
2372 | 366 |
367 * This routine roots through process descriptors in a queue and | |
368 * checks to see if the process has a path that is open to the device | |
369 * represented by the static storage pointer in U. if so, the S$HUP | |
370 * signal is sent to that process | |
371 * | |
372 * Entry: X = process descriptor to evaluate | |
373 * U = static storage of device we want to check against | |
2374 | 374 RootThrough |
375 ldb #NumPaths | |
376 leay P$Path,x | |
377 pshs x | |
378 loop decb | |
379 bmi out | |
380 lda ,y+ | |
381 beq loop | |
382 pshs y | |
383 ifgt Level-1 | |
384 ldx <D.PthDBT | |
385 else | |
386 ldx >D.PthDBT | |
387 endc | |
388 os9 F$Find64 | |
389 ldx PD.DEV,y | |
390 leax V$STAT,x | |
391 puls y | |
392 bcs out | |
2372 | 393 |
2374 | 394 cmpu ,x |
395 bne loop | |
396 | |
397 ldx ,s | |
398 lda P$ID,x | |
399 ldb #S$HUP | |
400 os9 F$Send | |
2372 | 401 |
2374 | 402 out puls x |
403 ldx P$Queue,x | |
404 bne RootThrough | |
405 rts | |
406 | |
407 statcont clrb | |
408 tfr d,u | |
2372 | 409 * NEW: root through all process descriptors. if any has a path open to this |
410 * device, send then S$HUP | |
2374 | 411 ldx <D.AProcQ |
412 beq dowait | |
413 bsr RootThrough | |
414 dowait ldx <D.WProcQ | |
415 beq dosleep | |
416 bsr RootThrough | |
417 dosleep ldx <D.SProcQ | |
2375 | 418 beq CkLPRC |
2374 | 419 bsr RootThrough |
2372 | 420 |
2375 | 421 CkLPRC |
2374 | 422 lda <V.LPRC,u |
423 beq IRQExit ; no last process, bail | |
424 ldb #S$HUP | |
425 os9 F$Send ; send signal, don't think we can do anything about an error result anyway.. so | |
426 bra CkSuspnd ; do we need to go check suspend? | |
2314
5f76d1a611f6
term signal sending for serread port status responses
aaronwolfe
parents:
2313
diff
changeset
|
427 |
2308 | 428 ; put byte B in port As buffer - optimization help from Darren Atkinson |
2374 | 429 IRQPutCh ldx RxBufPut,u ; point X to the data buffer |
430 | |
2308 | 431 ; process interrupt/quit characters here |
432 ; note we will have to do this in the multiread (ugh) | |
2374 | 433 tfr b,a ; put byte in A |
434 ldb #S$Intrpt | |
435 cmpa V.INTR,u | |
436 beq send@ | |
437 ldb #S$Abort | |
438 cmpa V.QUIT,u | |
439 bne store | |
440 send@ lda V.LPRC,u | |
441 beq IRQExit | |
442 os9 F$Send | |
443 bra IRQExit | |
2308 | 444 |
2374 | 445 store |
2308 | 446 ; store our data byte |
2374 | 447 sta ,x+ ; store and increment buffer pointer |
448 | |
2308 | 449 ; adjust RxBufPut |
2374 | 450 cmpx RxBufEnd,u ; end of Rx buffer? |
451 blo IRQSkip1 ; no, go keep laydown pointer | |
452 ldx RxBufPtr,u ; get Rx buffer start address | |
453 IRQSkip1 stx RxBufPut,u ; set new Rx data laydown pointer | |
2308 | 454 |
455 ; increment RxDatLen | |
2374 | 456 inc RxDatLen,u |
2308 | 457 |
2374 | 458 CkSSig |
459 lda <SSigID,u ; send signal on data ready? | |
460 beq CkSuspnd | |
461 ldb <SSigSg,u ; else get signal code | |
462 os9 F$Send | |
463 clr <SSigID,u | |
464 bra IRQExit | |
2308 | 465 |
466 ; check if we have a process waiting for data | |
2374 | 467 CkSuspnd |
468 lda <V.WAKE,u ; V.WAKE? | |
469 beq IRQExit ; no | |
470 clr <V.WAKE,u ; clear V.WAKE | |
471 | |
2308 | 472 ; wake up waiter for read |
2374 | 473 ifeq Level-1 |
474 ldb #S$Wake | |
475 os9 F$Send | |
476 else | |
477 clrb | |
478 tfr d,x ; copy process descriptor pointer | |
479 lda P$State,x ; get state flags | |
480 anda #^Suspend ; clear suspend state | |
481 sta P$State,x ; save state flags | |
482 endc | |
2308 | 483 |
2374 | 484 IRQExit |
485 IRQExit2 puls cc,dp,pc ; restore interrupts cc,dp, return | |
2180 | 486 |
2374 | 487 emod |
488 eom equ * | |
489 end |