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