comparison level1/modules/dw3.asm @ 2308:b5f0c5326e7e

Changes made to move ISR to dw3
author boisy
date Sun, 03 Jan 2010 14:35:04 +0000
parents 660cc987e18d
children b2bc1ad04163
comparison
equal deleted inserted replaced
2307:2f90c1624ab4 2308:b5f0c5326e7e
15 ifp1 15 ifp1
16 use defsfile 16 use defsfile
17 use dwdefs.d 17 use dwdefs.d
18 endc 18 endc
19 19
20 tylg set Sbrtn+Objct 20 tylg set Sbrtn+Objct
21 atrv set ReEnt+rev 21 atrv set ReEnt+rev
22 rev set $01 22 rev set $01
23 23
24 mod eom,name,tylg,atrv,start,0 24 mod eom,name,tylg,atrv,start,0
25 25
26 name fcs /dw3/ 26 * irq
27 IRQPckt fcb $00,$01,$0A ;IRQ packet Flip(1),Mask(1),Priority(1) bytes
28 * Default time packet
29 DefTime dtb
30
31 name fcs /dw3/
27 32
28 * DriveWire subroutine entry table 33 * DriveWire subroutine entry table
29 start lbra Init 34 start lbra Init
30 bra Read 35 bra Read
31 nop 36 nop
32 lbra Write 37 lbra Write
33 38
34 * Term 39 * Term
35 * 40 *
36 * Entry: 41 * Entry:
37 * U = address of device memory area 42 * U = address of device memory area
39 * Exit: 44 * Exit:
40 * CC = carry set on error 45 * CC = carry set on error
41 * B = error code 46 * B = error code
42 * 47 *
43 Term 48 Term
44 clrb clear Carry 49 clrb clear Carry
45 rts 50 rts
46
47 * Init
48 *
49 * Entry:
50 * Y = address of device descriptor
51 * U = address of device memory area
52 *
53 * Exit:
54 * CC = carry set on error
55 * B = error code
56 *
57 * Initialize the serial device
58 Init
59 clrb clear Carry
60 pshs cc,x then push CC on stack
61 orcc #IntMasks
62 ldx #PIA1Base $FF20
63 clr 1,x clear CD
64 lda #%11111110
65 sta ,x
66 lda #%00110100
67 sta 1,x
68 lda ,x
69 puls cc,x,pc
70 51
71 * Read 52 * Read
72 * 53 *
73 * ON ENTRY: 54 * ON ENTRY:
74 * X = ADDRESS OF THE RECEIVE BUFFER 55 * X = ADDRESS OF THE RECEIVE BUFFER
79 * D = ACTUAL NUMBER OF BYTES RECEIVED 60 * D = ACTUAL NUMBER OF BYTES RECEIVED
80 * X AND U ARE PRESERVED 61 * X AND U ARE PRESERVED
81 * CC.CARRY IS SET IF A FRAMING ERROR WAS DETECTED 62 * CC.CARRY IS SET IF A FRAMING ERROR WAS DETECTED
82 * 63 *
83 Read 64 Read
84 use dwread.asm 65 use dwread.asm
85 66
86 * Write 67 * Write
87 * 68 *
88 * Entry: 69 * Entry:
89 Write 70 Write
90 use dwwrite.asm 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
91 366
92 emod 367 emod
93 eom equ * 368 eom equ *
94 end 369 end