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.
|
|
11
|
|
12 nam DW3
|
|
13 ttl DriveWire 3 Low Level Subroutine Module
|
|
14
|
|
15 ifp1
|
|
16 use defsfile
|
|
17 use dwdefs.d
|
|
18 endc
|
|
19
|
2308
|
20 tylg set Sbrtn+Objct
|
|
21 atrv set ReEnt+rev
|
|
22 rev set $01
|
|
23
|
|
24 mod eom,name,tylg,atrv,start,0
|
2180
|
25
|
2308
|
26 * irq
|
|
27 IRQPckt fcb $00,$01,$0A ;IRQ packet Flip(1),Mask(1),Priority(1) bytes
|
|
28 * Default time packet
|
|
29 DefTime dtb
|
2180
|
30
|
2308
|
31 name fcs /dw3/
|
2180
|
32
|
|
33 * DriveWire subroutine entry table
|
2308
|
34 start lbra Init
|
|
35 bra Read
|
|
36 nop
|
|
37 lbra Write
|
2180
|
38
|
|
39 * Term
|
|
40 *
|
|
41 * Entry:
|
|
42 * U = address of device memory area
|
|
43 *
|
|
44 * Exit:
|
|
45 * CC = carry set on error
|
|
46 * B = error code
|
|
47 *
|
|
48 Term
|
2308
|
49 clrb clear Carry
|
|
50 rts
|
2180
|
51
|
|
52 * Read
|
|
53 *
|
|
54 * ON ENTRY:
|
|
55 * X = ADDRESS OF THE RECEIVE BUFFER
|
|
56 * A = TIMEOUT VALUE (182 = APPROX ONE SECOND @ 0.89 MHz)
|
|
57 *
|
|
58 * ON EXIT:
|
|
59 * Y = DATA CHECKSUM
|
|
60 * D = ACTUAL NUMBER OF BYTES RECEIVED
|
|
61 * X AND U ARE PRESERVED
|
|
62 * CC.CARRY IS SET IF A FRAMING ERROR WAS DETECTED
|
|
63 *
|
|
64 Read
|
2308
|
65 use dwread.asm
|
2180
|
66
|
|
67 * Write
|
|
68 *
|
|
69 * Entry:
|
|
70 Write
|
2308
|
71 use dwwrite.asm
|
|
72
|
|
73 * Init
|
|
74 *
|
|
75 * Entry:
|
|
76 * Y = address of device descriptor
|
|
77 * U = address of device memory area
|
|
78 *
|
|
79 * Exit:
|
|
80 * CC = carry set on error
|
|
81 * B = error code
|
|
82 *
|
|
83 * Initialize the serial device
|
|
84 Init
|
|
85 clrb clear Carry
|
|
86 pshs y,x,cc then push CC on stack
|
|
87 orcc #IntMasks
|
|
88 ldx #PIA1Base $FF20
|
|
89 clr 1,x clear CD
|
|
90 lda #%11111110
|
|
91 sta ,x
|
|
92 lda #%00110100
|
|
93 sta 1,x
|
|
94 lda ,x
|
|
95
|
|
96 ; allocate DW statics page
|
|
97 pshs u
|
|
98 ldd #$0100
|
|
99 os9 F$SRqMem
|
|
100 tfr u,x
|
|
101 puls u
|
|
102 lbcs InitEx
|
|
103 IFGT Level-1
|
|
104 stx <D.DWStat
|
|
105 ELSE
|
|
106 stx >D.DWStat
|
|
107 ENDC
|
|
108 ; clear out 256 byte page at X
|
|
109 clrb
|
|
110 loop@ clr ,x+
|
|
111 decb
|
|
112 bne loop@
|
|
113
|
|
114 * install ISR
|
|
115 InstIRQ
|
|
116 IFGT Level-1
|
|
117 ldx <D.DWStat
|
|
118 ELSE
|
|
119 ldx >D.DWStat
|
|
120 ENDC
|
|
121 leax DW.VIRQPkt,x
|
|
122 pshs u
|
|
123 tfr x,u
|
|
124 leax Vi.Stat,x ;fake VIRQ status register
|
|
125 lda #$80 ;VIRQ flag clear, repeated VIRQs
|
|
126 sta ,x ;set it while we're here...
|
|
127 tfr x,d ;copy fake VIRQ status register address
|
|
128 leax IRQPckt,pcr ;IRQ polling packet
|
|
129 leay IRQSvc,pcr ;IRQ service entry
|
|
130 os9 F$IRQ ;install
|
|
131 puls u
|
|
132 bcs InitEx ;exit with error
|
|
133 ldd #$0003 ;lets try every 6 ticks (0.1 seconds) -- testing 3, gives better response in interactive things
|
|
134 IFGT Level-1
|
|
135 ldx <D.DWStat
|
|
136 ELSE
|
|
137 ldx >D.DWStat
|
|
138 ENDC
|
|
139 leax DW.VIRQPkt,x
|
|
140 std Vi.Rst,x ; reset count
|
|
141 tfr x,y ; move VIRQ software packet to Y
|
|
142 tryagain
|
|
143 ldx #$0001 ; code to install new VIRQ
|
|
144 os9 F$VIRQ ; install
|
|
145 bcc IRQok ; no error, continue
|
|
146 cmpb #E$UnkSvc
|
|
147 bne InitEx
|
|
148 ; if we get an E$UnkSvc error, then clock has not been initialized, so do it here
|
|
149 leax DefTime,pcr
|
|
150 os9 F$STime
|
|
151 bra tryagain ; note: this has the slim potential of looping forever
|
|
152 IRQok
|
|
153 IFGT Level-1
|
|
154 ldx <D.DWStat
|
|
155 ELSE
|
|
156 ldx >D.DWStat
|
|
157 ENDC
|
|
158 ; cheat: we know DW.StatTbl is at offset $00 from D.DWStat, do not bother with leax
|
|
159 leax DW.StatTbl,x
|
|
160 tfr u,d
|
|
161 ldb <V.PORT+1,u ; get our port #
|
|
162 sta b,x ; store in table
|
|
163
|
|
164 InitEx
|
|
165 puls cc,x,y,pc
|
|
166
|
|
167
|
|
168 ; ***********************************************************************
|
|
169 ; Interrupt handler - Much help from Darren Atkinson
|
|
170
|
|
171 IRQMulti3 anda #$1F ; mask first 5 bits, a is now port #+1
|
|
172 deca ; we pass +1 to use 0 for no data
|
|
173 pshs a ; save port #
|
|
174 cmpb RxGrab,u ; compare room in buffer to server's byte
|
|
175 bhs IRQM06 ; room left >= server's bytes, no problem
|
|
176
|
|
177 stb RxGrab,u ; else replace with room left in our buffer
|
|
178
|
|
179 ; also limit to end of buffer
|
|
180 IRQM06 ldd RxBufEnd,u ; end addr of buffer
|
|
181 subd RxBufPut,u ; subtract current write pointer, result is # bytes left going forward in buff.
|
|
182
|
|
183 IRQM05 cmpb RxGrab,u ; compare b (room left) to grab bytes
|
|
184 bhs IRQM03 ; branch if we have room for grab bytes
|
|
185
|
|
186 stb RxGrab,u ; else set grab to room left
|
|
187
|
|
188 ; send multiread req
|
|
189 IRQM03 puls a ; port # is on stack
|
|
190 ldb RxGrab,u
|
|
191
|
|
192 pshs u
|
|
193
|
|
194 ; setup DWsub command
|
|
195 pshs d ; (a port, b bytes)
|
|
196 lda #OP_SERREADM ; load command
|
|
197 pshs a ; command store on stack
|
|
198 leax ,s ; point X to stack
|
|
199 ldy #3 ; 3 bytes to send
|
|
200
|
|
201 IFGT Level-1
|
|
202 ldu <D.DWSubAddr
|
|
203 ELSE
|
|
204 ldu >D.DWSubAddr
|
|
205 ENDC
|
|
206 jsr 6,u ; call DWrite
|
|
207
|
|
208 leas 3,s ; clean 3 DWsub args from stack
|
|
209
|
|
210 ldx ,s ; pointer to this port's area (from U prior), leave it on stack
|
|
211 ldb RxGrab,x ; set B to grab bytes
|
|
212 clra ; 0 in high byte
|
|
213 tfr d,y ; set # bytes for DW
|
|
214
|
|
215 ldx RxBufPut,x ; point X to insert position in this port's buffer
|
|
216 ; receive response
|
|
217 jsr 3,u ; call DWRead
|
|
218 ; handle errors?
|
|
219
|
|
220
|
|
221 puls u
|
|
222 ldb RxGrab,u ; our grab bytes
|
|
223
|
|
224 ; set new RxBufPut
|
|
225 ldx RxBufPut,u ; current write pointer
|
|
226 abx ; add b (# bytes) to RxBufPut
|
|
227 cmpx RxBufEnd,u ; end of Rx buffer?
|
|
228 blo IRQM04 ; no, go keep laydown pointer
|
|
229 ldx RxBufPtr,u ; get Rx buffer start address
|
|
230 IRQM04 stx RxBufPut,u ; set new Rx data laydown pointer
|
|
231
|
|
232 ; set new RxDatLen
|
|
233 ldb RxDatLen,u
|
|
234 addb RxGrab,u
|
|
235 stb RxDatLen,u ; store new value
|
|
236
|
|
237 bra CkSuspnd
|
|
238
|
|
239 IRQMulti
|
|
240 ; initial grab bytes
|
|
241 stb RxGrab,u
|
|
242
|
|
243 ; limit server bytes to bufsize - datlen
|
|
244 ldb RxBufSiz,u ; size of buffer
|
|
245 subb RxDatLen,u ; current bytes in buffer
|
|
246 bne IRQMulti3 ; continue, we have some space in buffer
|
|
247 ; no room in buffer
|
|
248 tstb
|
|
249 bne CkSuspnd
|
|
250 bra IRQExit
|
|
251
|
|
252
|
|
253 ; **** IRQ ENTRY POINT
|
|
254 IRQSvc equ *
|
|
255 pshs cc,dp ; save system cc,DP
|
|
256 orcc #IntMasks ; mask interrupts
|
|
257
|
|
258 ; mark VIRQ handled (note U is pointer to our VIRQ packet in DP)
|
|
259 lda Vi.Stat,u ; VIRQ status register
|
|
260 anda #^Vi.IFlag ; clear flag in VIRQ status register
|
|
261 sta Vi.Stat,u ; save it...
|
|
262
|
|
263 ; poll server for incoming serial data
|
|
264
|
|
265 ; send request
|
|
266 lda #OP_SERREAD ; load command
|
|
267 pshs a ; command store on stack
|
|
268 leax ,s ; point X to stack
|
|
269 ldy #1 ; 1 byte to send
|
|
270
|
|
271 IFGT Level-1
|
|
272 ldu <D.DWSubAddr
|
|
273 ELSE
|
|
274 ldu >D.DWSubAddr
|
|
275 ENDC
|
|
276 jsr 6,u ; call DWrite
|
|
277
|
|
278 ; receive response
|
|
279 leas -1,s ; one more byte to fit response
|
|
280 leax ,s ; point X to stack head
|
|
281 ldy #2 ; 2 bytes to retrieve
|
|
282 jsr 3,u ; call DWRead
|
|
283 beq IRQSvc2 ; branch if no error
|
|
284 leas 2,s ; error, cleanup stack 2
|
|
285 bra IRQExit2 ; don't reset error count on the way out
|
|
286
|
|
287 ; process response
|
|
288 IRQSvc2
|
|
289 ldd ,s++ ; pull returned status byte into A,data into B (set Z if zero, N if multiread)
|
|
290 beq IRQExit ; branch if D = 0 (nothing to do)
|
|
291
|
|
292 ; save back D on stack and build our U
|
|
293 pshs d
|
|
294 anda #$1F ; mask first 5 bits, a is now port #+1
|
|
295 deca ; we pass +1 to use 0 for no data
|
|
296 ; here we set U to the static storage area of the device we are working with
|
|
297 IFGT Level-1
|
|
298 ldx <D.DWStat
|
|
299 ELSE
|
|
300 ldx >D.DWStat
|
|
301 ENDC
|
|
302 ; cheat: we know DW.StatTbl is at offset $00 from D.DWStat, do not bother with leax
|
|
303 ; leax DW.StatTbl,x
|
|
304 lda a,x
|
|
305 bne IRQCont ; if A is 0, then this device is not active, so exit
|
|
306 puls d
|
|
307 bra IRQExit
|
|
308 IRQCont
|
|
309 clrb
|
|
310 tfr d,u
|
|
311
|
|
312 ldd ,s++ ; pull returned status byte into A,data into B (set Z if zero, N if multiread)
|
|
313
|
|
314 bmi IRQMulti ; branch for multiread
|
|
315
|
|
316 ; put byte B in port As buffer - optimization help from Darren Atkinson
|
|
317 IRQPutCh ldx RxBufPut,u ; point X to the data buffer
|
|
318
|
|
319 ; process interrupt/quit characters here
|
|
320 ; note we will have to do this in the multiread (ugh)
|
|
321 tfr b,a ; put byte in A
|
|
322 ldb #S$Intrpt
|
|
323 cmpa V.INTR,u
|
|
324 beq send@
|
|
325 ldb #S$Abort
|
|
326 cmpa V.QUIT,u
|
|
327 bne store
|
|
328 send@ lda V.LPRC,u
|
|
329 beq IRQExit
|
|
330 os9 F$Send
|
|
331 bra IRQExit
|
|
332
|
|
333 store
|
|
334 ; store our data byte
|
|
335 sta ,x+ ; store and increment buffer pointer
|
|
336
|
|
337 ; adjust RxBufPut
|
|
338 cmpx RxBufEnd,u ; end of Rx buffer?
|
|
339 blo IRQSkip1 ; no, go keep laydown pointer
|
|
340 ldx RxBufPtr,u ; get Rx buffer start address
|
|
341 IRQSkip1 stx RxBufPut,u ; set new Rx data laydown pointer
|
|
342
|
|
343 ; increment RxDatLen
|
|
344 inc RxDatLen,u
|
|
345
|
|
346
|
|
347 ; check if we have a process waiting for data
|
|
348 CkSuspnd lda <V.WAKE,u ; V.WAKE?
|
|
349 beq IRQExit ; no
|
|
350 clr <V.WAKE,u ; clear V.WAKE
|
|
351
|
|
352 ; wake up waiter for read
|
|
353 IFEQ Level-1
|
|
354 ldb #S$Wake
|
|
355 os9 F$Send
|
|
356 ELSE
|
|
357 clrb
|
|
358 tfr d,x ; copy process descriptor pointer
|
|
359 lda P$State,x ; get state flags
|
|
360 anda #^Suspend ; clear suspend state
|
|
361 sta P$State,x ; save state flags
|
|
362 ENDC
|
|
363
|
|
364 IRQExit
|
|
365 IRQExit2 puls cc,dp,pc ; restore interrupts cc,dp, return
|
2180
|
366
|
|
367 emod
|
|
368 eom equ *
|
|
369 end
|