1570
|
1 ********************************************************************
|
|
2 * rb1773 - Western Digital 1773 Disk Controller Driver
|
|
3 *
|
|
4 * A lot of references to **.CYL or <u00B6 using 16 bit registers can be
|
|
5 * changed to 8 bit registers with a +1 offset, since track #'s >255 are
|
|
6 * ignored
|
|
7 *
|
|
8 * NOTE: 512 bytes is reserved as a physical sector buffer. Any reads/
|
|
9 * writes are done from this buffer to the controller. Copies of the 256
|
|
10 * byte chunk needed are done by a block memory move
|
|
11
|
|
12 * $Id$
|
|
13 *
|
|
14 * Edt/Rev YYYY/MM/DD Modified by
|
|
15 * Comment
|
|
16 * ------------------------------------------------------------------
|
|
17 * 11 1993/05/12 ???
|
|
18 * Special opts for TC9 to slow controller reads and writes TFM's
|
|
19 * between sector buffers & in drive table init/copies.
|
|
20 * Changed software timing loop (drive spin-up) to F$Sleep for 32 ticks
|
|
21 * Shrunk (slowed slightly) error returns
|
|
22 * Added blobstop code
|
|
23 *
|
|
24 * 11r1 2003/09/03 Boisy G. Pitre
|
|
25 * Added code to sense if HW is present or not and return error if not.
|
|
26
|
|
27 nam rb1773
|
|
28 ttl Western Digital 1773 Disk Controller Driver
|
|
29
|
|
30 IFP1
|
|
31 use defsfile
|
|
32 ENDC
|
|
33
|
|
34 tylg set Drivr+Objct
|
|
35 atrv set ReEnt+rev
|
|
36 rev set $01
|
|
37 edition set 11
|
|
38
|
|
39 * Configuration Settings
|
|
40 N.Drives equ 4 number of drives to support
|
|
41 TC9 equ 0 Set to 1 for TC9 special slowdowns
|
|
42 PRECOMP equ 0 Set to 1 to turn on write precompensation
|
|
43
|
|
44 * WD-17X3 Definitions
|
|
45 WD_Cmd equ $08
|
|
46 WD_Stat equ WD_Cmd
|
|
47 WD_Trak equ $09
|
|
48 WD_Sect equ $0A
|
|
49 WD_Data equ $0B
|
|
50
|
|
51 mod eom,name,tylg,atrv,start,size
|
|
52
|
|
53 u0000 rmb DRVBEG+(DRVMEM*N.Drives)
|
|
54 u00A7 rmb 2 Last drive table accessed (ptr)
|
|
55 u00A9 rmb 1 Bit mask for control reg (drive #, side,etc)
|
|
56 u00AA rmb 1
|
|
57 sectbuf rmb 2 Ptr to 512 byte sector buffer
|
|
58 u00AD rmb 1
|
|
59 u00AE rmb 1
|
|
60 FBlock rmb 2 block number for format
|
|
61 IFGT Level-1
|
|
62 FTask rmb 1 task number for format
|
|
63 ENDC
|
|
64 u00B1 rmb 2 Vi.Cnt word for VIRQ
|
|
65 u00B3 rmb 2 Vi.Rst word for VIRQ
|
|
66 u00B5 rmb 1 Vi.Stat byte for VIRQ (drive motor timeout)
|
|
67 u00B6 rmb 2 OS9's logical sector #
|
|
68 u00B8 rmb 1 PCDOS (512 byte sector) sector #
|
|
69 size equ .
|
|
70
|
|
71 fcb DIR.+SHARE.+PEXEC.+PWRIT.+PREAD.+EXEC.+UPDAT.
|
|
72
|
1574
|
73 name fcs /rb1773/
|
1570
|
74 fcb edition
|
|
75
|
|
76 VIRQCnt fdb $00F0 Initial count for VIRQ (240)
|
|
77
|
|
78 IRQPkt fcb $00 Normal bits (flip byte)
|
|
79 fcb $01 Bit 1 is interrupt request flag (Mask byte)
|
|
80 fcb 10 Priority byte
|
|
81
|
|
82 * Init
|
|
83 *
|
|
84 * Entry:
|
|
85 * Y = address of device descriptor
|
|
86 * U = address of device memory area
|
|
87 *
|
|
88 * Exit:
|
|
89 * CC = carry set on error
|
|
90 * B = error code
|
|
91 *
|
|
92 * New code added 09/03/2003 by Boisy G. Pitre
|
|
93 * Write a pattern to $FF4B and read it back to verify that the hardware
|
|
94 * does exist.
|
|
95 Init ldx V.PORT,u get Base port address
|
|
96 lda WD_Data,x get byte at FDC Data register
|
|
97 coma complement it to modify it
|
|
98 sta WD_Data,x write it
|
|
99 clrb
|
|
100 Init2 decb delay a bit...
|
|
101 bmi Init2
|
|
102 suba WD_Data,x read it back
|
|
103 lbne NoHW if not zero, we didn't read what we wrote
|
|
104 **
|
|
105 IFEQ Level-1
|
|
106 clr >D.DskTmr flag drive motor as not running
|
|
107 ELSE
|
|
108 clr <D.MotOn flag drive motor as not running
|
|
109 ENDC
|
|
110 leax WD_Stat,x point to Status/Command register
|
|
111 lda #$D0 force Interrupt command
|
|
112 sta ,x send to FDC
|
|
113 lbsr L0406 time delay for ~ 108 cycles
|
|
114 lda ,x eat status register
|
|
115 ldd #$FF*256+N.Drives 'invalid' value & # of drives
|
|
116 sta >u00B8,u set 512 byte sector # to bogus value
|
|
117 sta >u00B8+1,u
|
|
118 leax DRVBEG,u point to start of drive tables
|
|
119 L004B sta ,x DD.TOT MSB to bogus value
|
|
120 sta <V.TRAK,x init current track # to bogus value
|
|
121 leax <DRVMEM,x point to next drive table
|
|
122 decb done all 4 drives yet?
|
|
123 bne L004B no, init them all
|
|
124 leax >NMISvc,pc point to NMI service routine
|
|
125 IFGT Level-1
|
|
126 stx <D.NMI install as system NMI
|
|
127 ELSE
|
|
128 stx >D.XNMI+1 NMI jump vector operand
|
|
129 lda #$7E JMP code
|
|
130 sta >D.XNMI NMI jump vector opcode
|
|
131 ENDC
|
|
132 pshs y save device dsc. ptr
|
|
133 leay >u00B5,u point to Vi.Stat in VIRQ packet
|
|
134 tfr y,d make it the status register ptr for IRQ
|
|
135 leay >IRQSvc,pc point to IRQ service routine
|
|
136 leax >IRQPkt,pc point to IRQ packet
|
|
137 os9 F$IRQ install IRQ
|
|
138 puls y Get back device dsc. ptr
|
|
139 bcs Return If we can't install IRQ, exit
|
|
140 ldd #512 Request 512 byte sector buffer
|
|
141 pshs u Preserve device mem ptr
|
|
142 os9 F$SRqMem Request sector buffer
|
|
143 tfr u,x Move ptr to sector buffer to x
|
|
144 puls u Restore device mem ptr
|
|
145 bcs Return If error, exit with it
|
|
146 stx >sectbuf,u Save ptr to sector buffer
|
|
147
|
|
148 * GetStat
|
|
149 *
|
|
150 * Entry:
|
|
151 * A = function code
|
|
152 * Y = address of path descriptor
|
|
153 * U = address of device memory area
|
|
154 *
|
|
155 * Exit:
|
|
156 * CC = carry set on error
|
|
157 * B = error code
|
|
158 *
|
|
159 GetStat clrb no GetStt calls - return, no error, ignore
|
|
160 Return rts
|
|
161
|
|
162 * Term
|
|
163 *
|
|
164 * Entry:
|
|
165 * U = address of device memory area
|
|
166 *
|
|
167 * Exit:
|
|
168 * CC = carry set on error
|
|
169 * B = error code
|
|
170 *
|
|
171 Term leay >u00B1,u Point to VIRQ packet
|
|
172 IFNE H6309
|
|
173 tfr 0,x "remove"
|
|
174 ELSE
|
|
175 ldx #$0000
|
|
176 ENDC
|
|
177 os9 F$VIRQ Remove VIRQ
|
|
178 IFNE H6309
|
|
179 tfr 0,x "remove"
|
|
180 ELSE
|
|
181 ldx #$0000
|
|
182 ENDC
|
|
183 os9 F$IRQ Remove IRQ
|
|
184 pshs u Save device mem ptr
|
|
185 ldu >sectbuf,u Get pointer to sector buffer
|
|
186 ldd #512 Return sector buffer memory
|
|
187 os9 F$SRtMem
|
|
188 puls u Restore device mem ptr
|
|
189 clr >DPort shut off drive motors
|
|
190 IFEQ Level-1
|
|
191 clr >D.DskTmr Clear out drive motor timeout flag
|
|
192 ELSE
|
|
193 clr <D.MotOn Clear out drive motor timeout flag
|
|
194 ENDC
|
|
195 L00AB rts return
|
|
196
|
|
197 * Check if 512 byte sector conversion needed
|
|
198 * Entry: B:X=LSN
|
|
199 * U=Static mem ptr
|
|
200 * Y=Path dsc. ptr
|
|
201 * Exit: X=New LSN (same as original for 256 byte sectors, 1/2 of original
|
|
202 * for 512 byte sectors
|
|
203 L00AC pshs x,b Save LSN
|
|
204 stx >u00B6,u Save OS9 LSN
|
|
205 lda <PD.TYP,y Get device type from path dsc.
|
|
206 anda #%00000100 Mask out all but 512 byte sector flag
|
|
207 bne L00BB 512 byte sectors, go process
|
|
208 L00CA puls pc,x,b Restore LSN & return
|
|
209
|
|
210 * 512 byte sector processing goes here
|
|
211 L00BB puls x,b Get back LSN
|
|
212 clrb Clear carry for rotate (also high byte of LSN)
|
|
213 tfr x,d Move to mathable register
|
|
214 IFNE H6309
|
|
215 rord Divide LSN by 2
|
|
216 ELSE
|
|
217 rora
|
|
218 rorb
|
|
219 ENDC
|
|
220 tfr d,x Move new LSN back to X
|
|
221 stx >u00B8,u Save 'physical' LSN (for controller)
|
|
222 clrb No error & return
|
|
223 rts
|
|
224
|
|
225 start lbra Init
|
|
226 bra Read
|
|
227 nop
|
|
228 lbra Write
|
|
229 bra GetStat
|
|
230 nop
|
|
231 lbra SetStat
|
|
232 bra Term
|
|
233 nop
|
|
234
|
|
235 * Read
|
|
236 *
|
|
237 * Entry:
|
|
238 * B = MSB of LSN
|
|
239 * X = LSB of LSN
|
|
240 * Y = address of path descriptor
|
|
241 * U = address of device memory area
|
|
242 *
|
|
243 * Exit:
|
|
244 * CC = carry set on error
|
|
245 * B = error code
|
|
246 *
|
|
247 Read bsr L00AC Go check for 512 byte sector/adjust if needed
|
|
248 lda #%10010001 Error flags (see Disto SCII source)
|
|
249 pshs x Preserve sector #
|
|
250 lbsr L0162 Go read the sector
|
|
251 puls x Restore sector #
|
|
252 bcs L00AB If error, exit
|
|
253 pshs y,x Save path dsc ptr & LSN
|
|
254 leax ,x LSN0?
|
|
255 bne L012D No, go calculate normally
|
|
256 puls y,x Yes, restore path dsc ptr & LSN
|
|
257 lda <PD.TYP,y Get type from path dsc.
|
|
258 bita #TYP.NSF Standard OS-9 format?
|
|
259 beq L00F0 Yes, skip ahead
|
|
260 lbsr L051A
|
|
261 pshs y,x save path dsc ptr
|
|
262 bra L012D
|
|
263
|
|
264 * LSN0, standard OS-9 format
|
|
265 L00F0 ldx >sectbuf,u Get ptr to sector buffer
|
|
266 pshs y,x Preserve path dsc. ptr & sector buffer ptr
|
|
267 ldy >u00A7,u Get last drive table accessed ptr
|
|
268 IFNE H6309
|
|
269 ldw #DD.SIZ # bytes to copy from new LSN0 to drive table
|
|
270 tfm x+,y+ Copy them
|
|
271 ELSE
|
|
272 ldb #DD.SIZ
|
|
273 L00F0Lp lda ,x+
|
|
274 sta ,y+
|
|
275 decb
|
|
276 bne L00F0Lp
|
|
277 ENDC
|
|
278 ldy >u00A7,u Get drive table ptr back
|
|
279 lda <DD.FMT,y Get format for disk in drive
|
|
280 ldy 2,s restore path descriptor pointer
|
|
281 ldb <PD.DNS,y Get path's density settings
|
|
282 bita #FMT.DNS Disk in drive double density?
|
|
283 beq L0115 No, all drives can read single, skip ahead
|
|
284 bitb #DNS.MFM Can our path dsc. handle double density?
|
|
285 beq erbtyp No, illegal
|
|
286 L0115 bita #FMT.TDNS Is new disk 96 tpi?
|
|
287 beq L011D No, all drives handle 48 tpi, so skip ahead
|
|
288 bitb #DNS.DTD Can path dsc. handle 96 tpi?
|
|
289 beq erbtyp No, illegal
|
|
290 L011D bita #FMT.SIDE Is new disk double sided?
|
|
291 beq L0128 No, all drives handle single sided, we're done
|
|
292 lda <PD.SID,y Get # sides path dsc. can handle
|
|
293 suba #2 sides higher or equal to 2?
|
|
294 blo erbtyp Yes, exit with illegal type error
|
|
295 L0128 clrb No error
|
|
296 * puls y,x ??? 2 USELESS LINES?
|
|
297 * pshs y,x
|
|
298 * LSN's other than 0 come straight here
|
|
299 L012D ldy 2,s Get path dsc. ptr back??
|
|
300 ldx PD.BUF,y Get path dsc. buffer ptr
|
|
301 lda <PD.TYP,y Get path dsc. disk type
|
|
302 ldy >sectbuf,u Get ptr to sector buffer
|
|
303 IFNE H6309
|
|
304 ldw #256 OS9 sector size (even if physical was 512)
|
|
305 ENDC
|
|
306 anda #%00000100 Mask out all but 512 byte sector flag
|
|
307 beq L014B If normal sector, just copy it
|
|
308 ldd >u00B6,u Get OS9's LSN (twice of the 'real' 512 sector)
|
|
309 andb #$01 Mask out all but odd/even sector indicator
|
|
310 beq L014B Even, use 1st half of 512 byte sector
|
|
311 IFNE H6309
|
|
312 addr w,y Odd, bump sector buffer ptr to 2nd half
|
|
313 ELSE
|
|
314 leay 256,y
|
|
315 ENDC
|
|
316 L014B equ *
|
|
317 IFNE H6309
|
|
318 tfm y+,x+ Copy from physical sector buffer to PD buffer
|
|
319 puls pc,y,x restore path dsc & sector buffer ptrs & return
|
|
320 ELSE
|
|
321 pshs d
|
|
322 clrb
|
|
323 L014BLp lda ,y+
|
|
324 sta ,x+
|
|
325 decb
|
|
326 bne L014BLp
|
|
327 puls pc,y,x,d restore path dsc & sector buffer ptrs & return
|
|
328 ENDC
|
|
329
|
|
330 erbtyp comb
|
|
331 ldb #E$BTyp Error - wrong type error
|
|
332 puls pc,y,x
|
|
333
|
|
334 * Read error - retry handler
|
|
335 L0159 bcc L0162 Normal retry, try reading again
|
|
336 pshs x,d Preserve regs
|
|
337 lbsr sktrk0 Seek to track 0 (attempt to recalibrate)
|
|
338 puls x,d Restore regs & try reading again
|
|
339
|
|
340 L0162 pshs x,d Preserve regs
|
|
341 bsr L016F Go read sector
|
|
342 puls x,d Restore regs (A=retry flags)
|
|
343 bcc L01D7 No error, return
|
|
344 lsra Shift retry flags
|
|
345 bne L0159 Still more retries allowed, go do them
|
|
346 * otherwise, final try before we give up
|
|
347 L016F lbsr L02AC Do double-step/precomp etc. if needed, seek
|
|
348 bcs L01D7 Error somewhere, exit with it
|
|
349 L0176 ldx >sectbuf,u Get physical sector buffer ptr
|
|
350 * pshs y,cc Preserve timeout timer & CC
|
|
351 ldb #$80 Read sector command
|
|
352 bsr L01A1 Send to controller & time delay to let it settle
|
|
353 *** Next few lines are commented out for blobstop patches
|
|
354 *L0180 bita >DPort+WD_Stat check status register
|
|
355 * bne L0197 eat it & start reading sector
|
|
356 * leay -1,y bump timeout timer down
|
|
357 * bne L0180 keep trying until it reaches 0 or sector read
|
|
358 * lda >u00A9,u get current drive settings
|
|
359 * ora #%00001000 turn drive motor on
|
|
360 * sta >DPort send to controller
|
|
361 * puls y,cc restore regs
|
|
362 * lbra L03E0 exit with Read Error
|
|
363 *** Blobstop fixes
|
|
364 stb >DPort send command to FDC
|
|
365 nop allow HALT to take effect
|
|
366 nop
|
|
367 bra L0197 and a bit more time
|
|
368 * Read loop - exited with NMI
|
|
369 * Entry: X=ptr to sector buffer
|
|
370 * B=Control register settings
|
|
371 L0197 lda >DPort+WD_Data get byte from controller
|
|
372 sta ,x+ store into sector buffer
|
|
373 * stb >DPort drive info
|
|
374 nop -- blobstop fix
|
|
375 bra L0197 Keep reading until sector done
|
|
376
|
|
377 L01A1 orcc #IntMasks Shut off IRQ & FIRQ
|
|
378 stb >DPort+WD_Cmd Send command
|
|
379 * ldy #$FFFF
|
|
380 ldb #%00101000 Double density & motor on
|
|
381 orb >u00A9,u Merge with current drive settings
|
|
382 stb >DPort Send to control register
|
|
383 ldb #%10101000 Enable halt, double density & motor on
|
|
384 orb >u00A9,u Merge that with current drive settings
|
|
385 lbra L0406 Time delay to wait for command to settle
|
|
386 * lda #$02
|
|
387 *L01BE rts
|
|
388
|
|
389 * Write
|
|
390 *
|
|
391 * Entry:
|
|
392 * B = MSB of LSN
|
|
393 * X = LSB of LSN
|
|
394 * Y = address of path descriptor
|
|
395 * U = address of device memory area
|
|
396 *
|
|
397 * Exit:
|
|
398 * CC = carry set on error
|
|
399 * B = error code
|
|
400 *
|
|
401 Write lbsr L00AC Go adjust LSN for 512 byte sector if needed
|
|
402 lda #%1001001 Retry flags for I/O errors (see Disto SCII source)
|
|
403 L01C4 pshs x,d Preserve LSN, retries
|
|
404 bsr L01E8 Go write the sector
|
|
405 puls x,d Restore LSN, retries
|
|
406 bcs L01D8 Error writing, go to write retry handler
|
|
407 tst <PD.VFY,y No error, do we want physical verify?
|
|
408 bne L01D6 No, exit without error
|
|
409 lbsr verify Go re-read & verify 32 out of 256 bytes
|
|
410 bcs L01D8 Error on verify, go to write retry handler
|
|
411 L01D6 clrb No error & return
|
|
412 L01D7 rts
|
|
413
|
|
414 * Write error retry handler
|
|
415 L01D8 lsra Shift retry flags
|
|
416 lbeq L03AF Too many retries, exit with error
|
|
417 bcc L01C4 Normal retry, attemp to re-write sector
|
|
418 pshs x,d Preserve flags & sector #
|
|
419 lbsr sktrk0 Seek to track 0 (attempt to recalibrate)
|
|
420 puls x,d Restore flags & sector #
|
|
421 bra L01C4 Try re-writing now
|
|
422
|
|
423 * 512 byte sector write here
|
|
424 L01E8 lbsr L02AC Go do double-step/write precomp if needed
|
|
425 bcs L01D7 Error, exit with it
|
|
426 pshs y,d Preserve path dsc. ptr & LSN
|
|
427 lda <PD.TYP,y Get device type
|
|
428 anda #%00000100 512 byte sector?
|
|
429 beq L020D No, skip ahead
|
|
430 lda #$91 ??? appears to be useless
|
|
431 lbsr L0176 Go read the sector in
|
|
432 ldd >u00B6,u Get OS9 LSN
|
|
433 andb #$01 Even or odd?
|
|
434 beq L020D Even, skip ahead
|
|
435 ldx >sectbuf,u Get physical sector buffer ptr
|
|
436 leax >$0100,x Point to 2nd half
|
|
437 bra L0211 Copy caller's buffer to 2nd half of sector
|
|
438
|
|
439 L020D ldx >sectbuf,u Get physical sector buffer ptr
|
|
440
|
|
441 L0211 ldy PD.BUF,y Get path dsc. buffer ptr
|
|
442 IFNE H6309
|
|
443 ldw #256 Copy write buffer to sector buffer
|
|
444 tfm y+,x+
|
|
445 ELSE
|
|
446 clrb
|
|
447 L0211Lp lda ,y+
|
|
448 sta ,x+
|
|
449 decb
|
|
450 bne L0211Lp
|
|
451 ENDC
|
|
452 puls y,d Get path dsc. ptr & LSN back
|
|
453 ldx >sectbuf,u Get physical sector buffer ptr again
|
|
454 ldb #$A0 Write sector command
|
|
455
|
|
456 * Format track comes here with B=$F0 (write track)
|
|
457 *L0224 pshs y,cc Preserve path dsc. ptr & CC
|
|
458 L0224 lbsr L01A1 Send command to controller (including delay)
|
|
459 *** Commented out for blobstop fixes
|
|
460 *L0229 bita >DPort+WD_Stat Controller done yet?
|
|
461 * bne L0240 Yes, go write sector out
|
|
462 * leay -$01,y No, bump wait counter
|
|
463 * bne L0229 Still more tries, continue
|
|
464 * lda >u00A9,u Get current drive control register settings
|
|
465 * ora #%00001000 Drive motor on (but drive select off)
|
|
466 * sta >DPort Send to controller
|
|
467 * puls y,cc Restore regs
|
|
468 * lbra L03AF Check for errors from status register
|
|
469
|
|
470 IFGT Level-1
|
|
471 *** added blobstop
|
|
472 lda FBlock+1,u get the block number for format
|
|
473 beq L0230 if not format, don't do anything
|
|
474 sta >$FFA1 otherwise map the block in
|
|
475 ENDC
|
|
476
|
|
477 L0230 stb >DPort send command to FDC
|
|
478 bra L0240 wait a bit for HALT to enable
|
|
479 * Write sector routine (Entry: B= drive/side select) (NMI will break out)
|
|
480 L0240 nop --- wait a bit more
|
|
481 lda ,x+ Get byte from write buffer
|
|
482 sta >DPort+WD_Data Save to FDC's data register
|
|
483 * EAT 2 CYCLES: TC9 ONLY (TRY 1 CYCLE AND SEE HOW IT WORKS)
|
|
484 IFEQ TC9-1
|
|
485 nop
|
|
486 nop
|
|
487 ENDC
|
|
488 * stb >DPort Set up to read next byte
|
|
489 bra L0240 Go read it
|
|
490
|
|
491 * NMI routine
|
|
492 NMISvc leas R$Size,s Eat register stack
|
|
493 * puls y,cc Get path dsc. ptr & CC
|
|
494 IFGT Level-1
|
|
495 ldx <D.SysDAT get pointer to system DAT image
|
|
496 lda 3,x get block number 1
|
|
497 sta >$FFA1 map it back into memory
|
|
498 andcc #^IntMasks turn IRQ's on again
|
|
499 ELSE
|
|
500 * puls y,cc Get path dsc. ptr & CC
|
|
501 ENDC
|
|
502 ldb >DPort+WD_Stat Get status register
|
|
503 bitb #%00000100 Did we lose data in the transfer?
|
|
504 * lbne L03E0 Yes, exit with Read Error
|
|
505 lbeq L03B2 Otherwise, check for drive errors
|
|
506 comb -- blobstop error code
|
|
507 ldb #E$DevBsy -- device busy
|
|
508 rts -- and exit
|
|
509
|
|
510 verify pshs x,d
|
|
511 ldx PD.BUF,y Get write buffer ptr
|
|
512 pshs x Preserve it
|
|
513 ldx >sectbuf,u Get sector buffer ptr
|
|
514 stx PD.BUF,y Save as write buffer ptr
|
|
515 ldx 4,s
|
|
516 lbsr L016F Go read sector we just wrote
|
|
517 puls x Get original write buffer ptr
|
|
518 stx PD.BUF,y Restore path dsc. version
|
|
519 bcs L02A3 If error reading, exit with it
|
|
520 pshs u,y Preserve device mem, path dsc. ptrs
|
|
521 ldb <PD.TYP,y Get type from path dsc.
|
|
522 ldy >sectbuf,u Get sector buffer ptr
|
|
523 andb #%00000100 512 byte sector?
|
|
524 beq L028D No, skip ahead
|
|
525 ldd >u00B6,u Get OS9's sector #
|
|
526 andb #$01 Odd/even sector?
|
|
527 beq L028D Even; compare first half
|
|
528 leay >$0100,y Odd, compare second half
|
|
529 L028D tfr x,u Move PD.BUF ptr to U (since cmpx is faster)
|
|
530 lda #32 # of 'spotty' checks to do
|
|
531 L028F ldx ,u Get 2 bytes from original write buffer
|
|
532 cmpx ,y Same as corresponding bytes in re-read sector?
|
|
533 bne L029F No, error & return
|
|
534 leau 8,u Skip next 6 bytes
|
|
535 leay 8,y
|
|
536 deca Done our 'spotty' check?
|
|
537 bne L028F No, continue
|
|
538 fcb $8C skip the next 2 bytes
|
|
539
|
|
540 L029F orcc #Carry
|
|
541 L02A1 puls u,y
|
|
542 L02A3 puls pc,x,d
|
|
543
|
|
544 L02A5 pshs a Save Caller's track #
|
|
545 ldb <V.TRAK,x Get track # drive is currently on
|
|
546 bra L02E9 Go save it to controller & continue
|
|
547
|
|
548 L02AC lbsr L0376 Go set up controller for drive, spin motor up
|
|
549 bsr L032B Get track/sector # (A=Trk, B=Sector)
|
|
550 pshs a Save track #
|
|
551 lda >u00AD,u Get side 1/2 flag
|
|
552 beq L02C4 Side 1, skip ahead
|
|
553 lda >u00A9,u Get control register settings
|
|
554 ora #%01000000 Set side 2 (drive 3) select
|
|
555 sta >u00A9,u Save it back
|
|
556 L02C4 lda <PD.TYP,y Get drive type settings
|
|
557 bita #%00000010 ??? (Base 0/1 for sector #?)
|
|
558 bne L02CC Skip ahead
|
|
559 incb Bump sector # up by 1
|
|
560 L02CC stb >DPort+WD_Sect Save into Sector register
|
|
561 ldx >u00A7,u Get last drive table accessed
|
|
562 ldb <V.TRAK,x Get current track # on device
|
|
563 lda <DD.FMT,x Get drive format specs
|
|
564 lsra Shift track & bit densities to match PD
|
|
565 eora <PD.DNS,y Check for differences with path densities
|
|
566 anda #%00000010 Keep only 48/96 tpi differences
|
|
567 pshs a Save differences
|
|
568 lda 1,s Get track # back
|
|
569 tst ,s+ Are tpi's different?
|
|
570 beq L02E9 No, continue normally
|
|
571 lsla Yes, multiply track # by 2 ('double-step')
|
|
572 lslb Multiply current track # by 2 ('double-step')
|
|
573 L02E9 stb >DPort+WD_Trak Save current track # onto controller
|
|
574
|
|
575 * From here to the line before L0307 is for write precomp, but is not used.
|
|
576 * Unless write precomp is needed, all of this is useless
|
|
577 * I think most (if not all) drives do NOT need precomp
|
|
578 IFEQ PRECOMP-1
|
|
579 ldb #21 Pre-comp track #
|
|
580 pshs b Save it
|
|
581 ldb <PD.DNS,y Get current density settings
|
|
582 andb #%00000010 Just want to check track density
|
|
583 beq L02F9 48 tpi, skip ahead
|
|
584 lsl ,s Multiply pre-comp value by 2 ('double-step')
|
|
585 L02F9 cmpa ,s+ Is track # high enough to warrant precomp?
|
|
586 bls L0307 No, continue normally
|
|
587 ldb >u00A9,u
|
|
588 orb #%00010000 Turn on Write precomp
|
|
589 stb >u00A9,u
|
|
590 ENDC
|
|
591
|
|
592 L0307 ldb >u00AA,u ??? Get flag (same drive flag?)
|
|
593 bne L0314 no, skip ahead
|
|
594 ldb ,s get track #
|
|
595 cmpb <V.TRAK,x same as current track on this drive?
|
|
596 beq L0321 yes, skip ahead
|
|
597 L0314 sta >DPort+WD_Data save track # to data register
|
|
598 ldb <PD.STP,y get stepping rate
|
|
599 andb #%00000011 just keep usable settings (6-30 ms)
|
|
600 eorb #%00011011 set proper bits for controller
|
|
601 lbsr L03E4 send command to controller & time delay
|
|
602 L0321 puls a get track # back
|
|
603 sta <V.TRAK,x save as current track #
|
|
604 sta >DPort+WD_Trak save to controller
|
|
605 clrb no error & return
|
|
606 rts
|
|
607
|
|
608 * Entry: B:X LSN
|
|
609 * Exit: A=Track #
|
|
610 * B=Sector #
|
|
611 * <u00AD=00 = Head 1 , $FF = Head 2
|
|
612 L032B tstb Sector # > 65535?
|
|
613 bne L033F Yes, illegal for floppy
|
|
614 tfr x,d Move sector # to D
|
|
615 leax ,x LSN 0?
|
|
616 beq L0371 Yes, exit this routine
|
|
617 ldx >u00A7,u Get previous drive table ptr
|
|
618 cmpd DD.TOT+1,x Within range of drive spec?
|
|
619 blo L0343 Yes, go calculate track/sector #'s
|
|
620 L033F comb Exit with Bad sector # error
|
|
621 ldb #E$Sect
|
|
622 rts
|
|
623
|
|
624 * Calculate track/sector #'s?
|
|
625 L0343 stb >u00AE,u Save LSB of LSN
|
|
626 clr ,-s Clear track # on stack
|
|
627 ldb <DD.FMT,x Get drive format
|
|
628 lsrb Shift out # sides into carry
|
|
629 ldb >u00AE,u Get LSB of LSN again
|
|
630 bcc L0367 Single sided drive, skip ahead
|
|
631 bra L035D Double sided drive, skip ahead
|
|
632 * Double sided drive handling here
|
|
633 L0355 com >u00AD,u ???? Odd/even sector track flag?
|
|
634 bne L035D Odd, so don't bump track # up
|
|
635 inc ,s Bump up track #
|
|
636
|
|
637 L035D subb DD.TKS,x Subtract # sectors/track
|
|
638 sbca #$00
|
|
639 bcc L0355 Still more sectors left, continue
|
|
640 bra L036D Wrapped, skip ahead
|
|
641 * Single sided drive handling here
|
|
642 L0365 inc ,s Bump track # up
|
|
643
|
|
644 L0367 subb DD.TKS,x Subtract # sectors/track
|
|
645 sbca #$00
|
|
646 bcc L0365 Still more, go bump the track up
|
|
647 L036D addb $03,x Bump sector # back up from negative value
|
|
648 puls a Get the track #
|
|
649 L0371 rts A=track #, B=Sector #, <u00AD=Odd
|
|
650
|
|
651 * Drive control register bit mask table
|
|
652 L0372 fcb $01 Drive 0
|
|
653 fcb $02 Drive 1
|
|
654 fcb $04 Drive 2
|
|
655 fcb $40 Drive 3 / Side select
|
|
656
|
|
657 L0376 clr >u00AA,u ???
|
|
658
|
|
659 chkdrv lda <PD.DRV,y Get drive # requested
|
|
660 cmpa #4 Drive 0-3?
|
|
661 blo L0385 Yes, continue normally
|
|
662 NoHW comb Illegal drive # error
|
|
663 ldb #E$Unit
|
|
664 rts
|
|
665
|
|
666 * Entry: A=drive #, X=LSN (Physical, not OS9 logical if PCDOS disk)
|
|
667 L0385 pshs x,d Save sector #, drive # & B???
|
|
668 leax >L0372,pc Point to drive bit mask table
|
|
669 ldb a,x Get bit mask for drive # we want
|
|
670 stb >u00A9,u Save mask
|
|
671 leax DRVBEG,u Point to beginning of drive tables
|
|
672 ldb #DRVMEM Get size of each drive table
|
|
673 mul Calculate offset to drive table we want
|
|
674 leax d,x Point to it
|
|
675 cmpx >u00A7,u Same as Last drive table accessed?
|
|
676 beq L03A6 Yes, skip ahead
|
|
677 stx >u00A7,u Save new drive table ptr
|
|
678 com >u00AA,u ??? Set flag
|
|
679 L03A6 clr >u00AD,u Set side (head) flag to side 1
|
|
680 lbsr L04B3 Go set up VIRQ to wait for drive motor
|
|
681 puls pc,x,d Restore sector #,drive #,B & return
|
|
682
|
|
683 L03AF ldb >DPort+WD_Stat Get status register from FDC
|
|
684 L03B2 bitb #%11111000 Any of the error bits set?
|
|
685 beq L03CA No, exit without error
|
|
686 aslb Drive not ready?
|
|
687 bcs L03CC Yes, use that error code
|
|
688 aslb Write protect error?
|
|
689 bcs L03D0 Yes, use that error code
|
|
690 aslb Write fault error?
|
|
691 bcs L03D4 Yes, use that error code
|
|
692 aslb Sector not found?
|
|
693 bcs L03D8 Yes, use Seek error code
|
|
694 aslb CRC error?
|
|
695 bcs L03DC Yes, use that error code
|
|
696 L03CA clrb No error & return
|
|
697 rts
|
|
698
|
|
699 L03CC ldb #E$NotRdy not ready
|
|
700 fcb $8C skip 2 bytes
|
|
701
|
|
702 L03D0 ldb #E$WP write protect
|
|
703 fcb $8C skip 2 bytes
|
|
704
|
|
705 L03D4 ldb #E$Write write error
|
|
706 fcb $8C
|
|
707
|
|
708 L03D8 ldb #E$Seek seek error
|
|
709 fcb $8C
|
|
710
|
|
711 L03DC ldb #E$CRC CRC error
|
|
712 * fcb $8C
|
|
713
|
|
714 *L03E0 ldb #E$Read Read error
|
|
715 orcc #Carry set carry
|
|
716 rts
|
|
717
|
|
718 L03E4 bsr L0404 Send command to controller & waste some time
|
|
719 L03E6 ldb >DPort+WD_Stat Check FDC status register
|
|
720 bitb #$01 Is controller still busy?
|
|
721 beq L0403 No, exit
|
|
722 ldd >VIRQCnt,pc Get initial count value for drive motor speed
|
|
723 std >u00B1,u Save it
|
|
724 bra L03E6 Wait for controller to finish previous command
|
|
725
|
|
726 * Send command to FDC
|
|
727 L03F7 lda #%00001000 Mask in Drive motor on bit
|
|
728 ora >u00A9,u Merge in drive/side selects
|
|
729 sta >DPort Turn the drive motor on & select drive
|
|
730 stb >DPort+WD_Cmd Save command & return
|
|
731 L0403 rts
|
|
732
|
|
733 L0404 bsr L03F7 Go send command to controller
|
|
734
|
|
735 * This loop has been changed from nested LBSRs to timing loop.
|
|
736 * People with crystal upgrades should modify the loop counter
|
|
737 * to get a 58+ us delay time. MINIMUM 58us.
|
|
738 L0406 pshs a 14 cycles, plus 3*loop counter
|
|
739 lda #29 (only do about a 100 cycle delay for now)
|
|
740 L0409 deca for total ~63 us delay (123 cycles max.)
|
|
741 bne L0409
|
|
742 puls a,pc restore register and exit
|
|
743
|
|
744 * SetStat
|
|
745 *
|
|
746 * Entry:
|
|
747 * A = function code
|
|
748 * Y = address of path descriptor
|
|
749 * U = address of device memory area
|
|
750 *
|
|
751 * Exit:
|
|
752 * CC = carry set on error
|
|
753 * B = error code
|
|
754 *
|
|
755 SetStat ldx PD.RGS,y Get caller's register stack ptr
|
|
756 ldb R$B,x Get function code
|
|
757 cmpb #SS.WTrk Write track?
|
|
758 beq SSWTrk Yes, go do it
|
|
759 cmpb #SS.Reset Restore head to track 0?
|
|
760 lbeq sktrk0 Yes, go do it --- beq
|
|
761 comb set carry for error
|
|
762 ldb #E$UnkSvc return illegal service request error
|
|
763 rts
|
|
764
|
|
765 SSWTrk pshs u,y preserve register stack & descriptor
|
|
766
|
|
767 IFEQ Level-1
|
|
768
|
|
769 ldd #$1A00 Size of buffer to hold entire track image
|
|
770 os9 F$SRqMem Request memory from system
|
|
771 bcs L0489 Error requesting, exit with it
|
|
772 stu >FBlock,x
|
|
773
|
|
774 ELSE
|
|
775
|
|
776 *--- new code
|
|
777 ldb #1 1 block to allocate
|
|
778 os9 F$AllRAM allocate some RAM
|
|
779 bcs L0489 error out if at all
|
|
780 leax >FBlock,u point to 'my' DAT image
|
|
781 std ,x save a copy of the block
|
|
782 os9 F$ResTsk reserve a task number for the copy
|
|
783 bcs FError error out
|
|
784 stb 2,x save temporary task number in FTask,u
|
|
785 lslb 2 bytes per entry
|
|
786 ldu <D.TskIPt get task image table pointer
|
|
787 stx b,u save pointer to the task's DAT image
|
|
788 lsrb get the right number again
|
|
789 IFNE H6309
|
|
790 tfr 0,u destination is address 0
|
|
791 ELSE
|
|
792 ldu #$0000
|
|
793 ENDC
|
|
794 *--- end new code
|
|
795
|
|
796 ldx 2,s get pointer to descriptor
|
|
797 * stu >FBlock,x
|
|
798 ldx <D.Proc Get current process ptr
|
|
799 lda P$Task,x Get task # for current process
|
|
800 * ldb <D.SysTsk Get system task #
|
|
801 ldy ,s
|
|
802 ldx PD.RGS,y Get register stack ptr
|
|
803 ldx R$X,x Get ptr to caller's track buffer
|
|
804 ldy #$1A00 Size of track buffer
|
|
805 os9 F$Move Copy from caller to temporary task
|
|
806 bcs L0479 Error copying, exit
|
|
807
|
|
808 ENDC
|
|
809
|
|
810 puls u,y
|
|
811 pshs u,y
|
|
812 lbsr L0376 Go check drive #/wait for it to spin up
|
|
813 ldx PD.RGS,y Get caller's register stack ptr
|
|
814 ldb R$Y+1,x Get caller's side/density
|
|
815 bitb #$01 Check side
|
|
816 beq L0465 Side 1, skip ahead
|
|
817 com >u00AD,u
|
|
818 ldb >u00A9,u Get current control register settings
|
|
819 orb #%01000000 Mask in side 2
|
|
820 stb >u00A9,u Save updated control register
|
|
821 L0465 lda R$U+1,x Get caller's track #
|
|
822 ldx >u00A7,u Get current drive table ptr
|
|
823 lbsr L02A5
|
|
824 bcs L0489
|
|
825 ldb #$F0 Write track command?
|
|
826 *---
|
|
827 IFEQ Level-1
|
|
828 ldx >FBlock,u
|
|
829 ELSE
|
|
830 ldx #$2000 start writing from block 1
|
|
831 ENDC
|
|
832
|
|
833 lbsr L0224 Go write the track
|
|
834 L0479 ldu 2,s
|
|
835 pshs b,cc Preserve error
|
|
836
|
|
837 IFEQ Level-1
|
|
838
|
|
839 ldu >FBlock,u Get ptr to track buffer
|
|
840 ldd #$1A00 Return track buffer
|
|
841 os9 F$SRtMem
|
|
842
|
|
843 ELSE
|
|
844
|
|
845 ldb >FTask,u point to task
|
|
846 os9 F$RelTsk release the task
|
|
847 fcb $8C skip 2 bytes
|
|
848
|
|
849 ENDC
|
|
850
|
|
851 * format comes here when block allocation passes, but task allocation
|
|
852 * gives error. So er de-allocate the block.
|
|
853 FError
|
|
854 IFGT Level-1
|
|
855 pshs b,cc save error code, cc
|
|
856 ldx >FBlock,u point to block
|
|
857 ldb #1 1 block to return
|
|
858 os9 F$DelRAM de-allocate image RAM blocks
|
|
859 clr FBlock+1,u ensure that the block # in FBlock is zero.
|
|
860 puls b,cc Restore error
|
|
861 ENDC
|
|
862
|
|
863 L0489 puls pc,u,y Restore regs & return
|
|
864
|
|
865 * seek the head to track 0
|
|
866 sktrk0 lbsr chkdrv
|
|
867 ldx >u00A7,u
|
|
868 clr <$15,x
|
|
869 lda #$05
|
|
870 L0497 ldb <PD.STP,y
|
|
871 andb #%00000011 Just keep usable settings (6-30 ms)
|
|
872 eorb #%01001011 Set proper bits for controller
|
|
873 pshs a
|
|
874 lbsr L03E4
|
|
875 puls a
|
|
876 deca
|
|
877 bne L0497
|
|
878 ldb <PD.STP,y
|
|
879 andb #%00000011 Just keep usable settings (6-30 ms)
|
|
880 eorb #%00001011 Set proper bits for controller
|
|
881 lbra L03E4
|
|
882
|
|
883 L04B3 pshs y,x,d Preserve regs
|
|
884 ldd >VIRQCnt,pc Get VIRQ initial count value
|
|
885 std >u00B1,u Save it
|
|
886 lda >u00A9,u ?Get drive?
|
|
887 ora #%00001000 Turn drive motor on for that drive
|
|
888 sta >DPort Send drive motor on command to FDC
|
|
889 IFEQ Level-1
|
|
890 lda >D.DskTmr Get VIRQ flag
|
|
891 ELSE
|
|
892 lda <D.MotOn Get VIRQ flag
|
|
893 ENDC
|
|
894 bmi L04DE Not installed yet, try installing it
|
|
895 bne L04E0 Drive already up to speed, exit without error
|
|
896
|
|
897 * Drive motor speed timing loop (could be F$Sleep call now) (was over .5 sec)
|
|
898 ldx #32 wait for 32 ticks
|
|
899 os9 F$Sleep
|
|
900
|
|
901 L04DE bsr InsVIRQ Install VIRQ to wait for drive motors
|
|
902 L04E0 clrb No error & return
|
|
903 puls pc,y,x,d
|
|
904
|
|
905 InsVIRQ lda #$01 Flag drive motor is up to speed
|
|
906 IFEQ Level-1
|
|
907 sta >D.DskTmr
|
|
908 ELSE
|
|
909 sta <D.MotOn
|
|
910 ENDC
|
|
911 ldx #$0001 Install VIRQ entry
|
|
912 leay >u00B1,u Point to packet
|
|
913 clr Vi.Stat,y Reset Status byte
|
|
914 ldd >VIRQCnt,pc Get initial VIRQ count value
|
|
915 os9 F$VIRQ Install VIRQ
|
|
916 bcc VIRQOut No error, exit
|
|
917 lda #$80 Flag that VIRQ wasn't installed
|
|
918 IFEQ Level-1
|
|
919 sta >D.DskTmr
|
|
920 ELSE
|
|
921 sta <D.MotOn
|
|
922 ENDC
|
|
923 VIRQOut clra
|
|
924 rts
|
|
925
|
|
926 * IRQ service routine for VIRQ (drive motor time)
|
|
927 * Entry: U=Ptr to VIRQ memory area
|
|
928 IRQSvc pshs a
|
|
929 lda <D.DMAReq
|
|
930 beq L0509
|
|
931 bsr InsVIRQ
|
|
932 bra IRQOut
|
|
933 L0509 sta >DPort
|
|
934 IFNE H6309
|
|
935 aim #$FE,>u00B5,u
|
|
936 ELSE
|
|
937 lda u00B5,u
|
|
938 anda #$FE
|
|
939 sta u00B5,u
|
|
940 ENDC
|
|
941 * fdb u00B5 --- so changes in data size won't affect anything
|
|
942 IFEQ Level-1
|
|
943 clr >D.DskTmr
|
|
944 ELSE
|
|
945 clr <D.MotOn
|
|
946 ENDC
|
|
947 IRQOut puls pc,a
|
|
948
|
|
949 * Non-OS9 format goes here
|
|
950 * Entry: X=LSN
|
|
951 * Y=Path dsc. ptr
|
|
952 * U=Device mem ptr
|
|
953 L051A pshs x Preserve Logical sector #
|
|
954 ldx >u00A7,u Get last drive table accessed ptr
|
|
955 clra
|
|
956 pshs x,a Save ptr & NUL byte
|
|
957 IFNE H6309
|
|
958 ldw #$14 Clear 20 bytes
|
|
959 tfm s,x+
|
|
960 ELSE
|
|
961 ldb #$14
|
|
962 L051ALp clr ,x+
|
|
963 decb
|
|
964 bne L051ALp
|
|
965 ENDC
|
|
966 puls x,a Eat NUL & get back drive table ptr
|
|
967 ldb <PD.CYL+1,y Get # cylinders on drive (ignores high byte)
|
|
968 lda <PD.SID,y Get # sides
|
|
969 mul Calculate # tracks on drive (1 per head)
|
|
970 IFNE H6309
|
|
971 decd Adjust to ignore track 0
|
|
972 ELSE
|
|
973 subd #$0001
|
|
974 ENDC
|
|
975 lda <PD.SCT+1,y Get # sectors/track
|
|
976 sta DD.TKS,x Save in drive table
|
|
977 sta <DD.SPT+1,x Save in other copy in drive table
|
|
978 mul Calculate # sectors on drive (minus track 0)
|
|
979 pshs x Preserve drive table ptr
|
|
980 tfr d,x Move # sectors on drive to X
|
|
981 lda <PD.T0S+1,y Get # sectors on track 0
|
|
982 leax a,x Add that many sectors to total
|
|
983 lda <PD.TYP,y Get device type settings
|
|
984 anda #%00000100 Mask out all but 512 byte sector flag
|
|
985 beq L0550 Not 512 byte sector, skip ahead
|
|
986 IFNE H6309
|
|
987 addr x,x Multiply by 2 (convert to 256 byte OS9 sectors)
|
|
988 ELSE
|
|
989 tfr x,d
|
|
990 leax d,x
|
|
991 ENDC
|
|
992 L0550 tfr x,d Move # sectors to D
|
|
993 puls x Get back drive table ptr
|
|
994 std DD.TOT+1,x Save # sectors allowed on drive
|
|
995 lda #UPDAT.+EXEC. Owner's read/write/exec attributes
|
|
996 sta DD.ATT,x Set attributes for disk
|
|
997 lda <PD.DNS,y Get density settings
|
|
998 lsla Shift for DD.FMT
|
|
999 pshs a Preserve it a sec
|
|
1000 lda <PD.SID,y Get # sides
|
|
1001 deca Adjust to base 0
|
|
1002 ora ,s+ Merge with density settings
|
|
1003 sta <DD.FMT,x Save in device table
|
|
1004 clrb No error?
|
|
1005 puls pc,x Restore original LSN & return
|
|
1006
|
|
1007 emod
|
|
1008 eom equ *
|
|
1009 end
|