1746
|
1 ********************************************************************
|
|
2 * rb1773 - Western Digital 1773 Disk Controller Driver
|
|
3 *
|
|
4 * $Id$
|
|
5 *
|
|
6 * This driver has been tested with the following controllers:
|
|
7 * - Tandy FD-502 "shortie" disk controller
|
|
8 * - Disto Super Controller I
|
|
9 * - Disto Super Controller II
|
|
10 *
|
|
11 * This driver can also be assembled to support the no-halt feature of
|
|
12 * the Disto Super Controller II.
|
|
13 *
|
|
14 *
|
|
15 * A lot of references to **.CYL or <u00B6 using 16 bit registers can be
|
|
16 * changed to 8 bit registers with a +1 offset, since track #'s >255 are
|
|
17 * ignored
|
|
18 *
|
|
19 * NOTE: 512 bytes is reserved as a physical sector buffer. Any reads/
|
|
20 * writes are done from this buffer to the controller. Copies of the 256
|
|
21 * byte chunk needed are done by a block memory move
|
|
22 *
|
|
23 *
|
|
24 ********** DISTO SUPER CONTROLLER II NOTES **********
|
|
25 *
|
|
26 * SCII 0=standard controller 1=Disto Super Controller II
|
|
27 * SCIIALT 0=Normal I/O register 1=Alternative registers; See below
|
|
28 *
|
|
29 * Disto Super Controller II Registers:
|
|
30 *
|
|
31 * $FF74 RW.Dat --- R/W Buffer data #1
|
|
32 * $FF75 mirror of $FF74
|
|
33 * $FF76 RW.Ctrl --- Write D0 = 0 FDC Write Op #2
|
|
34 * = 1 FDC Read Op #2
|
|
35 * D1 = 0 Normal Mode
|
|
36 * = 1 Buffered I/O Mode
|
|
37 * D2 = 0 Normal NMI
|
|
38 * = 1 Masked NMI
|
|
39 * D3 = 0 No FIRQ (Masked)
|
|
40 * = 1 Enabled FIRQ
|
|
41 * Read D7 = FDC INT Status (Inverted)
|
|
42 * $FF77 mirror of $FF76
|
|
43 * #1: any write to $FF76-$FF77 clears Buffer counter
|
|
44 * #2: in buffered mode only
|
|
45 *
|
|
46 * Alternate port is at $FF58-$FF5B in case of hardware conflicts.
|
|
47 *
|
|
48 * Edt/Rev YYYY/MM/DD Modified by
|
|
49 * Comment
|
|
50 * ------------------------------------------------------------------
|
|
51 * 11 1993/05/12 ???
|
|
52 * Special opts for TC9 to slow controller reads and writes TFM's
|
|
53 * between sector buffers & in drive table init/copies.
|
|
54 * Changed software timing loop (drive spin-up) to F$Sleep for 32 ticks
|
|
55 * Shrunk (slowed slightly) error returns
|
|
56 * Added blobstop code
|
|
57 *
|
|
58 * 11r1 2003/09/03 Boisy G. Pitre
|
|
59 * Added code to sense if HW is present or not and return error if not.
|
|
60 *
|
|
61 * 1r0 2004/05/20 Boisy G. Pitre
|
|
62 * Restarted edition due to name change; backported to Level 1
|
|
63 *
|
|
64 * 2004/06/01 Robert Gault
|
|
65 * Added code to obtain an SCII driver, at least for the Sleep mode. It
|
|
66 * would be quite difficult and probably not worth the effort to permit
|
|
67 * selection of both Sleep and IRQ SCII drivers. However, both normal
|
|
68 * and Alt SCII I/O registers are supported.
|
|
69 *
|
|
70 * Cleaned up some errors in the last version of rb1773.
|
|
71 *
|
|
72 * 2004/07/11 Robert Gault
|
|
73 * Corrected the error handling code for read & write to separate SCII errors
|
|
74 * from OS-9 errors. Changed drive test from compare #4 to compare #N.Drives to
|
|
75 * permit up to 6 drives using alternate table.
|
|
76 *
|
|
77 * 2005/01/27 Robert Gault
|
|
78 * Separated the sector write and format write loops so that the CPU clock
|
|
79 * can be slowed down during formats. This "corrects" problems some hardware
|
|
80 * have with the current NitrOS-9 during formats.
|
1785
|
81 *
|
|
82 * 1r1 2005/04/07 Boisy G. Pitre
|
|
83 * We now save the contents of D.NMI (Level 2) or D.XNMI (Level 1) before
|
|
84 * overwriting them, and then restore the original values at term time.
|
1746
|
85
|
|
86 nam rb1773
|
|
87 ttl Western Digital 1773 Disk Controller Driver
|
|
88
|
|
89 * These lines needed if assembling with on a Color computer.
|
|
90 *SCII set 1 * 0=not present 1=present
|
|
91 *SCIIALT set 1 * 0=normal address 1=alternate
|
|
92 SCIIHACK set 0 * 0=stock model 1=512 byte buffer
|
|
93 *H6309 set 1
|
|
94 *LEVEL set 2
|
|
95 * These lines needed if not using latest os9def files.
|
|
96 *TkPerSec set 60
|
|
97 *DPort set $FF40
|
|
98
|
|
99 * This should be changed for NitrOS9 project to "use defsfile"
|
|
100 IFP1
|
|
101 use defsfile
|
|
102 ENDC
|
|
103
|
|
104 tylg set Drivr+Objct
|
|
105 atrv set ReEnt+rev
|
1785
|
106 rev set $01
|
1746
|
107 edition set 1
|
|
108
|
|
109 * Configuration Settings
|
|
110 N.Drives equ 4 number of drives to support
|
|
111 TC9 equ 0 Set to 1 for TC9 special slowdowns
|
|
112 PRECOMP equ 0 Set to 1 to turn on write precompensation
|
|
113
|
|
114 * Disto Super Controller defs
|
|
115 IFEQ SCIIALT
|
|
116 RW.Dat equ $FF74
|
|
117 RW.Ctrl equ $FF76
|
|
118 ELSE
|
|
119 RW.Dat equ $FF58
|
|
120 RW.Ctrl equ $FF5A
|
|
121 ENDC
|
|
122
|
|
123
|
|
124 * WD-17X3 Definitions
|
|
125 CtrlReg equ $00 Control register for Tandy controllers; not part of WD
|
|
126 WD_Cmd equ $08
|
|
127 WD_Stat equ WD_Cmd
|
|
128 WD_Trak equ $09
|
|
129 WD_Sect equ $0A
|
|
130 WD_Data equ $0B
|
|
131
|
|
132 * WD-17X3 Commands
|
|
133 S$Read equ $80 Read sector
|
|
134 S$Format equ $A0 Format track
|
|
135 S$FrcInt equ $D0 Force interrupt
|
|
136
|
|
137 * Control Register Definitions
|
|
138 C_HALT equ %10000000 Halt line to CPU is active when set
|
|
139 C_SIDSEL equ %01000000 Side select (0 = front side, 1 = back side)
|
|
140 C_DBLDNS equ %00100000 Density (0 = single, 1 = double)
|
|
141 C_WPRCMP equ %00010000 Write precompensation (0 = off, 1 = on)
|
|
142 C_MOTOR equ %00001000 Drive motor (0 = off, 1 = on)
|
|
143 C_DRV2 equ %00000100 Drive 2 selected when set
|
|
144 C_DRV1 equ %00000010 Drive 1 selected when set
|
|
145 C_DRV0 equ %00000001 Drive 0 selected when set
|
|
146
|
|
147 mod eom,name,tylg,atrv,start,size
|
|
148
|
|
149 u0000 rmb DRVBEG+(DRVMEM*N.Drives)
|
|
150 lastdrv rmb 2 Last drive table accessed (ptr)
|
|
151 ctlimg rmb 1 Bit mask for control reg (drive #, side,etc)
|
|
152 u00AA rmb 1 drive change flag
|
|
153 sectbuf rmb 2 Ptr to 512 byte sector buffer
|
|
154 currside rmb 1 head flag; 0=front 1 = back
|
|
155 u00AE rmb 1 LSB of LSN
|
|
156 IFGT Level-1
|
|
157 FBlock rmb 2 block number for format
|
|
158 FTask rmb 1 task number for format
|
1785
|
159 NMISave rmb 2
|
|
160 ELSE
|
|
161 NMISave rmb 2
|
1746
|
162 ENDC
|
|
163 VIRQPak rmb 2 Vi.Cnt word for VIRQ
|
|
164 u00B3 rmb 2 Vi.Rst word for VIRQ
|
|
165 u00B5 rmb 1 Vi.Stat byte for VIRQ (drive motor timeout)
|
|
166 loglsn rmb 2 OS9's logical sector #
|
|
167 * Removed next line and added two new ones. RG
|
|
168 * PCDOS does not ask driver for any info.
|
|
169 * physlsn rmb 2 PCDOS (512 byte sector) #
|
|
170 flag512 rmb 1 PCDOS (512 byte sector) 0=no, 1=yes
|
|
171 flagform rmb 1 SCII format flag
|
|
172 size equ .
|
|
173
|
|
174 fcb DIR.+SHARE.+PEXEC.+PWRIT.+PREAD.+EXEC.+UPDAT.
|
|
175
|
|
176 name fcs /rb1773/
|
|
177 fcb edition
|
|
178
|
|
179 VIRQCnt fdb TkPerSec*4 Initial count for VIRQ (4 seconds)
|
|
180
|
|
181 IRQPkt fcb $00 Normal bits (flip byte)
|
|
182 fcb $01 Bit 1 is interrupt request flag (Mask byte)
|
|
183 fcb 10 Priority byte
|
|
184
|
|
185 * Init
|
|
186 *
|
|
187 * Entry:
|
|
188 * Y = address of device descriptor
|
|
189 * U = address of device memory area
|
|
190 *
|
|
191 * Exit:
|
|
192 * CC = carry set on error
|
|
193 * B = error code
|
|
194 *
|
|
195 * New code added 09/03/2003 by Boisy G. Pitre
|
|
196 * Write a pattern to $FF4B and read it back to verify that the hardware
|
|
197 * does exist.
|
|
198 Init equ *
|
|
199 * Two new lines for SCII. RG
|
|
200 IFNE SCII
|
|
201 clr RW.Ctrl clear SCII control register
|
|
202 clr flagform,u clear SCII format flag
|
|
203 ENDC
|
|
204 ldx V.PORT,u get Base port address
|
|
205 lda WD_Data,x get byte at FDC Data register
|
|
206 coma complement it to modify it
|
|
207 sta WD_Data,x write it
|
|
208 clrb
|
|
209 Init2 decb delay a bit...
|
|
210 bmi Init2
|
|
211 suba WD_Data,x read it back
|
|
212 lbne NoHW if not zero, we didn't read what we wrote
|
|
213 **
|
|
214 IFEQ Level-1
|
|
215 clr >D.DskTmr flag drive motor as not running
|
|
216 ELSE
|
|
217 clr <D.MotOn flag drive motor as not running
|
|
218 ENDC
|
|
219 leax WD_Stat,x point to Status/Command register
|
|
220 lda #S$FrcInt "Force Interrupt" command
|
|
221 sta ,x send to FDC
|
|
222 lbsr FDCDelay time delay for ~ 108 cycles
|
|
223 lda ,x eat status register
|
|
224 ldd #$FF*256+N.Drives 'invalid' value & # of drives
|
|
225 leax DRVBEG,u point to start of drive tables
|
|
226 l1 sta ,x DD.TOT MSB to bogus value
|
|
227 sta <V.TRAK,x init current track # to bogus value
|
|
228 leax <DRVMEM,x point to next drive table
|
|
229 decb done all drives yet?
|
|
230 bne l1 no, init them all
|
1785
|
231 *** Fix on 04/06/2005: we now save the contents of D.NMI (Level 2)
|
|
232 *** or D.XNMI (Level 1) before overwriting them.
|
1746
|
233 IFGT Level-1
|
1785
|
234 ldx >D.NMI
|
|
235 stx NMISave,u
|
|
236 leax >NMISvc,pc point to NMI service routine
|
|
237 stx >D.NMI install as system NMI
|
1746
|
238 ELSE
|
1785
|
239 ldx >D.XNMI
|
|
240 stx NMISave,u
|
|
241 lda >D.XNMI+2
|
|
242 sta NMISave+2,u
|
|
243 leax >NMISvc,pc point to NMI service routine
|
1746
|
244 stx >D.XNMI+1 NMI jump vector operand
|
|
245 lda #$7E JMP code
|
|
246 sta >D.XNMI NMI jump vector opcode
|
|
247 ENDC
|
|
248 pshs y save device dsc. ptr
|
|
249 leay >u00B5,u point to Vi.Stat in VIRQ packet
|
|
250 tfr y,d make it the status register ptr for IRQ
|
|
251 leay >IRQSvc,pc point to IRQ service routine
|
|
252 leax >IRQPkt,pc point to IRQ packet
|
|
253 os9 F$IRQ install IRQ
|
|
254 puls y Get back device dsc. ptr
|
|
255 bcs Return If we can't install IRQ, exit
|
|
256 ldd #512 Request 512 byte sector buffer
|
|
257 pshs u Preserve device mem ptr
|
|
258 os9 F$SRqMem Request sector buffer
|
|
259 tfr u,x Move ptr to sector buffer to x
|
|
260 puls u Restore device mem ptr
|
|
261 bcs Return If error, exit with it
|
|
262 stx >sectbuf,u Save ptr to sector buffer
|
|
263
|
|
264 * GetStat
|
|
265 *
|
|
266 * Entry:
|
|
267 * A = function code
|
|
268 * Y = address of path descriptor
|
|
269 * U = address of device memory area
|
|
270 *
|
|
271 * Exit:
|
|
272 * CC = carry set on error
|
|
273 * B = error code
|
|
274 *
|
|
275 GetStat clrb no GetStt calls - return, no error, ignore
|
|
276 Return rts
|
|
277
|
|
278 * Term
|
|
279 *
|
|
280 * Entry:
|
|
281 * U = address of device memory area
|
|
282 *
|
|
283 * Exit:
|
|
284 * CC = carry set on error
|
|
285 * B = error code
|
|
286 *
|
|
287 Term leay >VIRQPak,u Point to VIRQ packet
|
|
288 IFNE H6309
|
|
289 tfr 0,x "remove"
|
|
290 ELSE
|
|
291 ldx #$0000
|
|
292 ENDC
|
|
293 os9 F$VIRQ Remove VIRQ
|
|
294 IFNE H6309
|
|
295 tfr 0,x "remove"
|
|
296 ELSE
|
|
297 ldx #$0000
|
|
298 ENDC
|
|
299 leay >IRQSvc,pc point to IRQ service routine
|
|
300 os9 F$IRQ Remove IRQ
|
1785
|
301 *** Fix: we now restore original D.NMI (Level 2) or D.XNMI (Level 1)
|
|
302 *** before overwriting them.
|
|
303 IFGT Level-1
|
|
304 ldx NMISave,u
|
|
305 stx >D.NMI
|
|
306 ELSE
|
|
307 ldx NMISave,u
|
|
308 stx >D.XNMI
|
|
309 lda NMISave+2,u
|
|
310 sta >D.XNMI+2
|
|
311 ENDC
|
|
312 ***
|
1746
|
313 pshs u Save device mem ptr
|
|
314 ldu >sectbuf,u Get pointer to sector buffer
|
|
315 ldd #512 Return sector buffer memory
|
|
316 os9 F$SRtMem
|
|
317 puls u Restore device mem ptr
|
|
318 clr >DPort+CtrlReg shut off drive motors
|
|
319 IFEQ Level-1
|
|
320 clr >D.DskTmr Clear out drive motor timeout flag
|
|
321 ELSE
|
|
322 clr <D.MotOn Clear out drive motor timeout flag
|
|
323 ENDC
|
|
324 ex rts return
|
|
325
|
|
326 * Check if 512 byte sector conversion needed
|
|
327 * Entry: B:X=LSN
|
|
328 * U=Static mem ptr
|
|
329 * Y=Path dsc. ptr
|
|
330 * Exit: X=New LSN (same as original for 256 byte sectors, 1/2 of original
|
|
331 * for 512 byte sectors
|
|
332 * regD changed
|
|
333 Chk512 equ *
|
|
334 clr flag512,u set to 256 byte sector
|
|
335 stx >loglsn,u save OS9 LSN
|
|
336 lda <PD.TYP,y get device type from path dsc.
|
|
337 anda #%00000100 mask out all but 512 byte sector flag
|
|
338 bne Log2Phys 512 byte sectors, go process
|
|
339 rts RG
|
|
340
|
|
341 * 512 byte sector processing goes here
|
|
342 * regB should be saved and not just cleared at end because there is
|
|
343 * a subsequent tst for the msb of lsn. The test is pointless if B
|
|
344 * is changed.
|
|
345 Log2Phys pshs b save MSB of LSN; new RG
|
|
346 * Minor inefficiencies here that I have changed, RG
|
|
347 tfr x,d
|
|
348 IFNE H6309
|
|
349 lsrd
|
|
350 ELSE
|
|
351 lsra
|
|
352 rorb
|
|
353 ENDC
|
|
354 tfr d,x move new LSN back to regX
|
|
355 * New line for stock SCII controller with 256 max no-halt.
|
|
356 inc flag512,u set to 512 byte sector
|
|
357 puls b,pc regB will be tested later for >0
|
|
358
|
|
359 start lbra Init
|
|
360 bra Read
|
|
361 nop
|
|
362 lbra Write
|
|
363 bra GetStat
|
|
364 nop
|
|
365 lbra SetStat
|
|
366 bra Term
|
|
367 nop
|
|
368
|
|
369 * Read
|
|
370 *
|
|
371 * Entry:
|
|
372 * B = MSB of LSN
|
|
373 * X = LSB of LSN
|
|
374 * Y = address of path descriptor
|
|
375 * U = address of device memory area
|
|
376 *
|
|
377 * Exit:
|
|
378 * CC = carry set on error
|
|
379 * B = error code
|
|
380 *
|
|
381 Read bsr Chk512 go check for 512 byte sector/adjust if needed
|
|
382 lda #%10010001 error flags (see Disto SCII source)
|
|
383 pshs x preserve sector #
|
|
384 lbsr ReadWithRetry go read the sector
|
|
385 puls x restore sector #
|
|
386 bcs ex if error, exit
|
|
387 pshs y,x save path dsc ptr & LSN
|
|
388 leax ,x LSN0?, ie. tstx
|
|
389 bne L012D no, go calculate normally
|
|
390 puls y,x yes, restore path dsc ptr & LSN
|
|
391 lda <PD.TYP,y get type from path dsc.
|
|
392 bita #TYP.NSF standard OS-9 format?
|
|
393 beq L00F0 yes, skip ahead
|
|
394 lbsr MakeDTEntry else make a drive table entry
|
|
395 pshs y,x save path dsc ptr
|
|
396 bra L012D
|
|
397
|
|
398 * LSN0, standard OS-9 format - copy part of LSN0 into drive table
|
|
399 L00F0 ldx >sectbuf,u Get ptr to sector buffer
|
|
400 pshs y,x Preserve path dsc. ptr & sector buffer ptr
|
|
401 ldy >lastdrv,u Get last drive table accessed ptr
|
|
402 IFNE H6309
|
|
403 ldw #DD.SIZ # bytes to copy from new LSN0 to drive table
|
|
404 tfm x+,y+ Copy them
|
|
405 ELSE
|
|
406 ldb #DD.SIZ
|
|
407 L00F0Lp lda ,x+
|
|
408 sta ,y+
|
|
409 decb
|
|
410 bne L00F0Lp
|
|
411 ENDC
|
|
412 ldy >lastdrv,u Get drive table ptr back
|
|
413 lda <DD.FMT,y Get format for disk in drive
|
|
414 ldy 2,s restore path descriptor pointer
|
|
415 ldb <PD.DNS,y Get path's density settings
|
|
416 bita #FMT.DNS Disk in drive double density?
|
|
417 beq L0115 No, all drives can read single, skip ahead
|
|
418 bitb #DNS.MFM Can our path dsc. handle double density?
|
|
419 beq erbtyp No, illegal
|
|
420 L0115 bita #FMT.TDNS Is new disk 96/135 tpi?
|
|
421 beq L011D No, all drives handle 48 tpi, so skip ahead
|
|
422 bitb #DNS.DTD Can path dsc. handle 96/135 tpi?
|
|
423 beq erbtyp No, illegal
|
|
424 L011D bita #FMT.SIDE Is new disk double sided?
|
|
425 beq L0128 No, all drives handle single sided, we're done
|
|
426 lda <PD.SID,y Get # sides path dsc. can handle
|
|
427 suba #2 sides higher or equal to 2?
|
|
428 blo erbtyp Yes, exit with illegal type error
|
|
429 L0128 clrb No error
|
|
430 * LSN's other than 0 come straight here
|
|
431 L012D ldy 2,s Get path dsc. ptr back??
|
|
432 ldx PD.BUF,y Get path dsc. buffer ptr
|
|
433 * lda <PD.TYP,y Get path dsc. disk type, RG
|
|
434 ldy >sectbuf,u Get ptr to sector buffer
|
|
435 IFNE H6309
|
|
436 ldw #256 OS9 sector size (even if physical was 512)
|
|
437 ENDC
|
|
438 * anda #%00000100 Mask out all but 512 byte sector flag, RG
|
|
439 * Next replaces the two lines removed, RG
|
|
440 tst flag512,u Is it a 512 byte sector?
|
|
441 beq L014B If normal sector, just copy it
|
|
442 ldd >loglsn,u Get OS9's LSN (twice of the 'real' 512 sector)
|
|
443 andb #$01 Mask out all but odd/even sector indicator
|
|
444 beq L014B Even, use 1st half of 512 byte sector
|
|
445 IFNE H6309
|
|
446 addr w,y Odd, bump sector buffer ptr to 2nd half
|
|
447 ELSE
|
|
448 leay 256,y
|
|
449 ENDC
|
|
450 L014B equ *
|
|
451 IFNE H6309
|
|
452 tfm y+,x+ Copy from physical sector buffer to PD buffer
|
|
453 puls pc,y,x restore path dsc & sector buffer ptrs & return
|
|
454 ELSE
|
|
455 pshs d
|
|
456 clrb
|
|
457 L014BLp lda ,y+
|
|
458 sta ,x+
|
|
459 decb
|
|
460 bne L014BLp
|
|
461 puls pc,y,x,d restore path dsc & sector buffer ptrs & return
|
|
462 ENDC
|
|
463
|
|
464 erbtyp comb
|
|
465 ldb #E$BTyp Error - wrong type error
|
|
466 puls pc,y,x
|
|
467
|
|
468 **********************
|
|
469 * Read error - retry handler
|
|
470 Retry
|
|
471 bcc ReadWithRetry Normal retry, try reading again
|
|
472 pshs x,d Preserve regs
|
|
473 lbsr sktrk0 Seek to track 0 (attempt to recalibrate)
|
|
474 puls x,d Restore regs & try reading again
|
|
475
|
|
476
|
|
477 * Read With Retry: Do read with retries
|
|
478 *
|
|
479 * ENTER reg B,X=working lsn on disk
|
|
480 * Y=path descriptor
|
|
481 * U=driver data
|
|
482 * A=retry sequence mix of read & seek track 0
|
|
483 * EXIT X,Y,U preserved; D,CC changed
|
|
484 * B=error if any
|
|
485 * CC=error flag
|
|
486 ReadWithRetry
|
|
487 pshs x,d Preserve regs
|
|
488 bsr ReadSector Go read sector
|
|
489 puls x,d Restore regs (A=retry flags)
|
|
490 lbcc L01D7 No error, return
|
|
491 lsra Shift retry flags
|
|
492 bne Retry Still more retries allowed, go do them
|
|
493 * otherwise, final try before we give up
|
|
494 ReadSector
|
|
495 lbsr L02AC Do double-step/precomp etc. if needed, seek
|
|
496 lbcs L01D7 Error somewhere, exit with it
|
|
497 L0176 ldx >sectbuf,u Get physical sector buffer ptr
|
|
498 ldb #S$Read Read sector command
|
|
499 IFNE SCII
|
|
500 * If SCII not hacked for 512 byte no-halt, must use halt for 512b sectors RG
|
|
501 IFEQ SCIIHACK
|
|
502 clra SCII normal mode, normal NMI
|
|
503 tst flag512,u SCII must use halt mode for 512 byte sectors
|
|
504 bne L0176B
|
|
505 ENDC
|
|
506 lda #7 SCII read, buffered mode, masked NMI
|
|
507 bsr L01A1B send commands and wait
|
|
508 * New lines needed because the SCII has error other than OS-9 errors. RG
|
|
509 bcs ngood
|
|
510 * This now becomes a subroutine call. RG
|
|
511 * lbcs L03AF get the errors
|
|
512 lbsr L03AF get the errors
|
|
513 bcc good
|
|
514 ngood rts
|
|
515
|
|
516 good pshs y
|
|
517 IFNE H6309
|
|
518 ldw #256 set counter
|
|
519 ldy #RW.DAT source of data
|
|
520 IFNE SCIIHACK
|
|
521 tst flag512,u
|
|
522 beq sc2rlp
|
|
523 ldw #512 bump up counter to 512 byte sector
|
|
524 ENDC
|
|
525 * Don't use tfm if no halt important else need orcc #$50 for tfm
|
|
526 * If an interrupt occurs during a tfm transfer, the SCII counter
|
|
527 * will update but the tfm will repeat a byte and lose track.
|
|
528 * If orcc #$50 used, then key presses may be lost even with no-halt
|
|
529 * mode.
|
|
530 sc2rlp lda ,y read byte from SCII
|
|
531 sta ,x+ transfer byte to system buffer
|
|
532 decw update counter
|
|
533 bne sc2rlp
|
|
534 ELSE
|
|
535 ldy #256
|
|
536 IFNE SCIIHACK
|
|
537 tst flag512,u
|
|
538 beq sc2rlp
|
|
539 ldy #512
|
|
540 ENDC
|
|
541 sc2rlp lda >RW.DAT
|
|
542 sta ,x+
|
|
543 leay -1,y
|
|
544 bne sc2rlp
|
|
545 ENDC
|
|
546 clrb no errors
|
|
547 puls y,pc
|
|
548 ENDC
|
|
549
|
|
550 L0176B bsr L01A1 Send to controller & time delay to let it settle
|
|
551 *** Next few lines are commented out for blobstop patches
|
|
552 *L0180 bita >DPort+WD_Stat check status register
|
|
553 * bne L0197 eat it & start reading sector
|
|
554 * leay -1,y bump timeout timer down
|
|
555 * bne L0180 keep trying until it reaches 0 or sector read
|
|
556 * lda >ctlimg,u get current drive settings
|
|
557 * ora #C_MOTOR turn drive motor on
|
|
558 * sta >DPort+CtrlReg send to controller
|
|
559 * puls y,cc restore regs
|
|
560 * lbra L03E0 exit with Read Error
|
|
561 *** Blobstop fixes
|
|
562 stb >DPort+CtrlReg send B to control register
|
|
563 nop allow HALT to take effect
|
|
564 nop
|
|
565 bra L0197 and a bit more time
|
|
566 * Read loop - exited with NMI
|
|
567 * Entry: X=ptr to sector buffer
|
|
568 * B=Control register settings
|
|
569 L0197 lda >DPort+WD_Data get byte from controller
|
|
570 sta ,x+ store into sector buffer
|
|
571 * stb >DPort+CtrlReg drive info
|
|
572 nop -- blobstop fix
|
|
573 bra L0197 Keep reading until sector done
|
|
574
|
|
575 L01A1 orcc #IntMasks Shut off IRQ & FIRQ
|
|
576 * No-halt mode must enter here, skipping IRQ shutoff.
|
|
577 L01A1B stb >DPort+WD_Cmd Send command
|
|
578 IFNE SCII
|
|
579 sta >RW.Ctrl tell SCII what to do
|
|
580 ENDC
|
|
581 L01A1C ldb #C_DBLDNS+C_MOTOR Double density & motor on
|
|
582 orb >ctlimg,u Merge with current drive settings
|
|
583 stb >DPort+CtrlReg Send to control register
|
|
584 IFNE SCII
|
|
585 tst flagform,u Format uses halt mode
|
|
586 bne s512
|
|
587 IFEQ SCIIHACK
|
|
588 tst flag512,u SCII uses halt with 512 byte sectors
|
|
589 beq s256
|
|
590 ELSE
|
|
591 bra s256
|
|
592 ENDC
|
|
593 ENDC
|
|
594 s512 ldb #C_HALT+C_DBLDNS+C_MOTOR Enable halt, double density & motor on
|
|
595 orb >ctlimg,u Merge that with current drive settings
|
|
596 lbra FDCDelay Time delay to wait for command to settle
|
|
597 IFNE SCII
|
|
598 s256 ldb #4 normal mode, NMI masked
|
|
599 lda #255 time out slices
|
|
600 pshs a,x
|
|
601 SC2tmr1 ldx #1
|
|
602 lbsr Delay sleep or timer
|
|
603 dec ,s count
|
|
604 beq tmout
|
|
605 tst >RW.Ctrl check status
|
|
606 bmi SC2tmr1 loop on not ready
|
|
607 stb RW.Ctrl clear SCII but don't generate NMI
|
|
608 clrb
|
|
609 puls a,x,pc
|
|
610 tmout stb RW.Ctrl clear SCII buffer counter
|
|
611 lda #$D0 force interrupt
|
|
612 sta DPort+WD_Cmd
|
|
613 comb set carry
|
|
614 puls a,x,pc
|
|
615 ENDC
|
|
616
|
|
617 * Delay for some number of ticks (1 tick = 1/60 second).
|
|
618 * For a hard delay, we need to delay for 14833 cycles at .89MHz or
|
|
619 * 29666 cycles at 1.78MHz
|
|
620 * Entry: X = number of ticks to delay
|
|
621 Delay
|
|
622 pshs d [5+] [4+]
|
|
623 IFGT Level-1
|
|
624 ldd <D.Proc [6] [5] process pointer
|
|
625 cmpd <D.SysPrc [is it the system?
|
|
626 beq hardloop [3] [3]
|
|
627 os9 F$Sleep if not system then sleep
|
|
628 puls d,pc [5+] [4+]
|
|
629 ENDC
|
|
630 hardloop tfr x,d we want X in A,B
|
|
631 l1@ equ *
|
|
632 IFEQ Level-1
|
|
633 ldx #1482/2 [3] [3]
|
|
634 ELSE
|
|
635 IFNE H6309
|
|
636 ldx #1854 [3] [3]
|
|
637 ELSE
|
|
638 ldx #1482 [3] [3]
|
|
639 ENDC
|
|
640 ENDC
|
|
641 l2@ nop [2] [1]
|
|
642 nop [2] [1]
|
|
643 nop [2] [1]
|
|
644 leax -1,x [4+] [4+]
|
|
645 bne l2@ [3] [3]
|
|
646 subd #$0001 [4] [3]
|
|
647 bne l1@ [3] [3]
|
|
648 puls d,pc [5+] [4+]
|
|
649
|
|
650 * Write
|
|
651 * Entry:
|
|
652 * B = MSB of LSN
|
|
653 * X = LSB of LSN
|
|
654 * Y = address of path descriptor
|
|
655 * U = address of device memory area
|
|
656 *
|
|
657 * Exit:
|
|
658 * CC = carry set on error
|
|
659 * B = error code
|
|
660 *
|
|
661 Write lbsr Chk512 go adjust LSN for 512 byte sector if needed
|
|
662 * Next line was lda #%1001001 which was an error RG
|
|
663 lda #%10010001 retry flags for I/O errors (see Disto SCII source)
|
|
664 L01C4 pshs x,d preserve LSN, retries
|
|
665 bsr L01E8 go write the sector
|
|
666 puls x,d restore LSN, retries
|
|
667 bcs L01D8 error writing, go to write retry handler
|
|
668 tst <PD.VFY,y no error, do we want physical verify?
|
|
669 bne L01D6 no, exit without error
|
|
670 lbsr verify go re-read & verify 64 out of 256 bytes
|
|
671 bcs L01D8 error on verify, go to write retry handler
|
|
672 L01D6 clrb no error & return
|
|
673 L01D7 rts
|
|
674
|
|
675 * Write error retry handler
|
|
676 L01D8 lsra Shift retry flags
|
|
677 lbeq L03AF Too many retries, exit with error
|
|
678 bcc L01C4 Normal retry, attemp to re-write sector
|
|
679 pshs x,d Preserve flags & sector #
|
|
680 lbsr sktrk0 Seek to track 0 (attempt to recalibrate)
|
|
681 puls x,d Restore flags & sector #
|
|
682 bra L01C4 Try re-writing now
|
|
683
|
|
684 * 512 byte sector write here
|
|
685 L01E8 lbsr L02AC Go do double-step/write precomp if needed
|
|
686 bcs L01D7 Error, exit with it
|
|
687 pshs y,d Preserve path dsc. ptr & LSN
|
|
688 * Since I have modified chk512 the next two lines are replaced. RG
|
|
689 * lda <PD.TYP,y Get device type
|
|
690 * anda #%00000100 512 byte sector?
|
|
691 tst flag512,u go if 256 byte sectors
|
|
692 beq L020D Not 512 then skip ahead
|
|
693 lbsr L0176 Go read the sector in
|
|
694 ldd >loglsn,u Get OS9 LSN
|
|
695 andb #$01 Even or odd?
|
|
696 beq L020D Even, skip ahead
|
|
697 ldx >sectbuf,u Get physical sector buffer ptr
|
|
698 leax >$0100,x Point to 2nd half
|
|
699 bra L0211 Copy caller's buffer to 2nd half of sector
|
|
700
|
|
701 L020D ldx >sectbuf,u Get physical sector buffer ptr
|
|
702
|
|
703 L0211 ldy PD.BUF,y Get path dsc. buffer ptr
|
|
704 IFNE H6309
|
|
705 ldw #256 Copy write buffer to sector buffer
|
|
706 tfm y+,x+
|
|
707 ELSE
|
|
708 clrb
|
|
709 L0211Lp lda ,y+
|
|
710 sta ,x+
|
|
711 decb
|
|
712 bne L0211Lp
|
|
713 ENDC
|
|
714 puls y,d Get path dsc. ptr & LSN back
|
|
715 ldx >sectbuf,u Get physical sector buffer ptr again
|
|
716 * See read routine for explanation of SCII code. RG
|
|
717 IFNE SCII
|
|
718 IFEQ SCIIHACK
|
|
719 clra SCII write, normal mode & NMI
|
|
720 tst flag512,u
|
|
721 bne wr512
|
|
722 ENDC
|
|
723 lda #4 SCII normal mode, masked NMI
|
|
724 sta RW.Ctrl tell SCII
|
|
725 pshs y
|
|
726 ldy #RW.Dat Send data to SCII RAM buffer
|
|
727 IFNE H6309
|
|
728 ldw #256
|
|
729 tst flag512,u
|
|
730 beq wrbuf
|
|
731 ldw #512
|
|
732 wrbuf lda ,x+
|
|
733 sta ,y
|
|
734 decw
|
|
735 bne wrbuf
|
|
736 ELSE
|
|
737 ldy #256
|
|
738 tst flag512,u
|
|
739 beq wrbuf
|
|
740 ldy #512
|
|
741 wrbuf lda ,x+
|
|
742 sta >RW.DAT
|
|
743 leay -1,y
|
|
744 bne wrbuf
|
|
745 ENDC
|
|
746 puls y
|
|
747 ldb #$A0 Write sector command
|
|
748 lda #6 SCII masked NMI, buffered mode, write
|
|
749 * See Read section for explanation of error changes below. RG
|
|
750 * lbra L01A1B send command to controller
|
|
751 lbsr L01A1B send command to controller
|
|
752 bcs wngood SCII error, then go
|
|
753 lbra L03AF check for OS-9 errors
|
|
754 wngood rts
|
|
755 ENDC
|
|
756 wr512 ldb #S$Format
|
|
757
|
|
758 * Format track comes here with B=$F0 (write track)
|
|
759 * as does write sector with B=$A0
|
|
760 *WrTrk pshs y,cc Preserve path dsc. ptr & CC
|
|
761 WrTrk lbsr L01A1 Send command to controller (including delay)
|
|
762 *** Commented out for blobstop fixes
|
|
763 *L0229 bita >DPort+WD_Stat Controller done yet?
|
|
764 * bne L0240 Yes, go write sector out
|
|
765 * leay -$01,y No, bump wait counter
|
|
766 * bne L0229 Still more tries, continue
|
|
767 * lda >ctlimg,u Get current drive control register settings
|
|
768 * ora #C_MOTOR Drive motor on (but drive select off)
|
|
769 * sta >DPort+CtrlReg Send to controller
|
|
770 * puls y,cc Restore regs
|
|
771 * lbra L03AF Check for errors from status register
|
|
772
|
|
773 *** added blobstop
|
|
774 IFGT Level-1
|
|
775 lda FBlock+1,u get the block number for format
|
|
776 beq L0230 if not format, don't do anything
|
|
777 sta >$FFA1 otherwise map the block in
|
|
778 * added delay for for MMU line settling. RG 2005/1/23
|
|
779 nop
|
|
780 nop
|
|
781 ENDC
|
|
782 L0230 stb >DPort+CtrlReg send data to control register
|
|
783 * These lines converted to separate sector writes from format. RG
|
|
784 * nop
|
|
785 * nop
|
|
786 cmpb #$F0 if format, then
|
|
787 beq L0240b go to special loop
|
|
788 bra L0240 wait a bit for HALT to enable
|
|
789
|
|
790 * Write sector routine (Entry: B= drive/side select) (NMI will break out)
|
|
791 * Part of timing change mentioned above. RG
|
|
792 *L0240 nop --- wait a bit more
|
|
793 L0240 lda ,x+ Get byte from write buffer
|
|
794 sta >DPort+WD_Data Save to FDC's data register
|
|
795 * EAT 2 CYCLES: TC9 ONLY (TRY 1 CYCLE AND SEE HOW IT WORKS)
|
|
796 IFEQ TC9-1
|
|
797 nop
|
|
798 nop
|
|
799 ELSE
|
|
800 * See above. RG
|
|
801 nop
|
|
802 ENDC
|
|
803 * stb >DPort+CtrlReg Set up to read next byte
|
|
804 bra L0240 Go read it
|
|
805 * Special loop for format slows CPU clock. RG
|
|
806 L0240b sta >$FFD8
|
|
807 L0240c lda ,x+
|
|
808 sta >DPort+WD_Data
|
|
809 bra L0240b
|
|
810 * NMI routine
|
|
811 NMISvc leas R$Size,s Eat register stack
|
|
812 * Added to compensate above change in format loop. RG
|
|
813 sta >$FFD9
|
|
814 IFGT Level-1
|
|
815 ldx <D.SysDAT get pointer to system DAT image
|
|
816 lda 3,x get block number 1
|
|
817 sta >$FFA1 map it back into memory
|
|
818 ENDC
|
|
819 andcc #^IntMasks turn IRQ's on again
|
|
820 ldb >DPort+WD_Stat Get status register
|
|
821 IFNE SCII
|
|
822 clr RW.Ctrl Clear SCII command register
|
|
823 ENDC
|
|
824 bitb #%00000100 Did we lose data in the transfer?
|
|
825 lbeq L03B2 Otherwise, check for drive errors
|
|
826 comb -- blobstop error code
|
|
827 ldb #E$DevBsy -- device busy
|
|
828 rts -- and exit
|
|
829
|
|
830 verify pshs x,d
|
|
831 * Removed unneeded code. Data never sent to PD.BUF anyway so there is
|
|
832 * no need to redirect the PD.BUF pointer. RG
|
|
833 * ldx PD.BUF,y Get write buffer ptr
|
|
834 * pshs x Preserve it
|
|
835 * ldx >sectbuf,u Get sector buffer ptr
|
|
836 * stx PD.BUF,y Save as write buffer ptr
|
|
837 * ldx 4,s
|
|
838 lbsr ReadSector Go read sector we just wrote
|
|
839 * puls x Get original write buffer ptr
|
|
840 * stx PD.BUF,y Restore path dsc. version
|
|
841 bcs L02A3 If error reading, exit with it
|
|
842 ldx PD.BUF,y Get system buffer ptr
|
|
843 pshs u,y Preserve device mem, path dsc. ptrs
|
|
844 * See change in chk512 routine. RG
|
|
845 * ldb <PD.TYP,y Get type from path dsc.
|
|
846 ldy >sectbuf,u Get sector buffer ptr
|
|
847 * andb #%00000100 512 byte sector?
|
|
848 tst flag512,u 512 byte sector?
|
|
849 beq L028D No, skip ahead
|
|
850 ldd >loglsn,u Get OS9's sector #
|
|
851 andb #$01 Odd/even sector?
|
|
852 beq L028D Even; compare first half
|
|
853 leay >$0100,y Odd, compare second half
|
|
854 L028D tfr x,u Move PD.BUF ptr to U (since cmpx is faster)
|
|
855 clra check all 256 bytes
|
|
856 L028F ldx ,u++ Get 2 bytes from original write buffer
|
|
857 cmpx ,y++ Same as corresponding bytes in re-read sector?
|
|
858 bne vfybad No, error & return
|
|
859 inca
|
|
860 bpl L028F No, continue
|
|
861 bra L02A1 carry is clear by virtue of last cmpx
|
|
862 vfybad comb set carry
|
|
863 L02A1 puls u,y
|
|
864 L02A3 puls pc,x,d
|
|
865
|
|
866 L02A5 pshs a Save Caller's track #
|
|
867 ldb <V.TRAK,x Get track # drive is currently on
|
|
868 bra L02E9 Go save it to controller & continue
|
|
869
|
|
870 L02AC lbsr L0376 Go set up controller for drive, spin motor up
|
|
871 bsr L032B Get track/sector # (A=Trk, B=Sector)
|
|
872 pshs a Save track #
|
|
873 lda >currside,u Get side 1/2 flag
|
|
874 beq L02C4 Side 1, skip ahead
|
|
875 lda >ctlimg,u Get control register settings
|
|
876 ora #C_SIDSEL Set side 2 (drive 3) select
|
|
877 sta >ctlimg,u Save it back
|
|
878 L02C4 lda <PD.TYP,y Get drive type settings
|
|
879 bita #%00000010 ??? (Base 0/1 for sector #?)
|
|
880 bne L02CC Skip ahead
|
|
881 incb Bump sector # up by 1
|
|
882 L02CC stb >DPort+WD_Sect Save into Sector register
|
|
883 ldx >lastdrv,u Get last drive table accessed
|
|
884 ldb <V.TRAK,x Get current track # on device
|
|
885 lda <DD.FMT,x Get drive format specs
|
|
886 lsra Shift track & bit densities to match PD
|
|
887 eora <PD.DNS,y Check for differences with path densities
|
|
888 anda #%00000010 Keep only 48 vs. 96/135 tpi differences
|
|
889 pshs a Save differences
|
|
890 lda 1,s Get track # back
|
|
891 tst ,s+ Are tpi's different?
|
|
892 beq L02E9 No, continue normally
|
|
893 lsla Yes, multiply track # by 2 ('double-step')
|
|
894 lslb Multiply current track # by 2 ('double-step')
|
|
895 L02E9 stb >DPort+WD_Trak Save current track # onto controller
|
|
896
|
|
897 * From here to the line before L0307 is for write precomp, but is not used.
|
|
898 * Unless write precomp is needed, all of this is useless
|
|
899 * I think most (if not all) drives do NOT need precomp
|
|
900 IFEQ PRECOMP-1
|
|
901 ldb #21 Pre-comp track #
|
|
902 pshs b Save it
|
|
903 ldb <PD.DNS,y Get current density settings
|
|
904 andb #%00000010 Just want to check track density
|
|
905 beq L02F9 48 tpi, skip ahead
|
|
906 lsl ,s Multiply pre-comp value by 2 ('double-step')
|
|
907 L02F9 cmpa ,s+ Is track # high enough to warrant precomp?
|
|
908 bls L0307 No, continue normally
|
|
909 ldb >ctlimg,u
|
|
910 orb #C.WRPCMP Turn on Write precomp
|
|
911 stb >ctlimg,u
|
|
912 ENDC
|
|
913
|
|
914 L0307 tst >u00AA,u ??? Get flag (same drive flag?)
|
|
915 bne L0314 no, skip ahead
|
|
916 ldb ,s get track #
|
|
917 cmpb <V.TRAK,x same as current track on this drive?
|
|
918 beq L0321 yes, skip ahead
|
|
919 L0314 sta >DPort+WD_Data save track # to data register
|
|
920 ldb <PD.STP,y get stepping rate
|
|
921 andb #%00000011 just keep usable settings (6-30 ms)
|
|
922 eorb #%00011011 set proper bits for controller
|
|
923 lbsr L03E4 send command to controller & time delay
|
|
924 L0321 puls a get track # back
|
|
925 sta <V.TRAK,x save as current track #
|
|
926 sta >DPort+WD_Trak save to controller
|
|
927 clrb no error & return
|
|
928 rts
|
|
929
|
|
930 * Entry: B:X LSN
|
|
931 * Exit: A=Track #
|
|
932 * B=Sector #
|
|
933 * <currside=00 = Head 1 , $FF = Head 2
|
|
934 L032B tstb Sector # > 65535?
|
|
935 bne L033F Yes, illegal for floppy
|
|
936 tfr x,d Move sector # to D
|
|
937 leax ,x LSN 0? ie. "tstx"
|
|
938 beq L0371 Yes, exit this routine
|
|
939 ldx >lastdrv,u Get previous drive table ptr
|
|
940 cmpd DD.TOT+1,x Within range of drive spec?
|
|
941 blo L0343 Yes, go calculate track/sector #'s
|
|
942 L033F comb Exit with Bad sector # error
|
|
943 ldb #E$Sect
|
|
944 rts
|
|
945
|
|
946 * Calculate track/sector #'s?
|
|
947 * These two sections could be combined into one with a final
|
|
948 * test of DD.FMT. Then currside can be set and regA can be lsra
|
|
949 * as needed. RG
|
|
950 L0343 stb >u00AE,u Save LSB of LSN
|
|
951 clr ,-s Clear track # on stack
|
|
952 ldb <DD.FMT,x Get drive format
|
|
953 lsrb Shift out # sides into carry
|
|
954 ldb >u00AE,u Get LSB of LSN again
|
|
955 bcc L0367 Single sided drive, skip ahead
|
|
956 bra L035D Double sided drive, skip ahead
|
|
957 * Double sided drive handling here
|
|
958 L0355 com >currside,u Odd/even sector track flag
|
|
959 bne L035D Odd, so don't bump track # up
|
|
960 inc ,s Bump up track #
|
|
961
|
|
962 * Changed this to more effient code. RG
|
|
963 *L035D subb DD.TKS,x Subtract # sectors/track
|
|
964 * sbca #$00
|
|
965 L035D subd DD.SPT,x
|
|
966 bcc L0355 Still more sectors left, continue
|
|
967 bra L036D Wrapped, skip ahead
|
|
968 * Single sided drive handling here
|
|
969 L0365 inc ,s Bump track # up
|
|
970
|
|
971 * See above. RG
|
|
972 *L0367 subb DD.TKS,x Subtract # sectors/track
|
|
973 * sbca #$00
|
|
974 L0367 subd DD.SPT,x
|
|
975 bcc L0365 Still more, go bump the track up
|
|
976 * Next possible because upper limit is 256 sectors/track. RG
|
|
977 L036D addb DD.TKS,x Bump sector # back up from negative value
|
|
978 puls a Get the track #
|
|
979 L0371 rts A=track #, B=Sector #, <currside=Odd
|
|
980
|
|
981 * Drive control register bit mask table
|
|
982 * May want an option here for double sided SDDD disks ex. RG
|
|
983 * fcb $1 drive0
|
|
984 * fcb $2 drive1
|
|
985 * fcb $41 drive2
|
|
986 * fcb $42 drive3
|
|
987 * fcb $4 drive4
|
|
988 * fcb $44 drive5
|
|
989
|
|
990 L0372 fcb $01 Drive 0
|
|
991 fcb $02 Drive 1
|
|
992 fcb $04 Drive 2
|
|
993 fcb $40 Drive 3 / Side select
|
|
994
|
|
995 * Changes regD; X,Y,U preserved
|
|
996 L0376 clr >u00AA,u clear drive change flag
|
|
997 chkdrv lda <PD.DRV,y Get drive # requested
|
|
998 * It is possible to have more than 4 drive # so the change below. RG
|
|
999 * cmpa #4 Drive 0-3?
|
|
1000 cmpa #N.Drives Drive 0-6 if alternate table used?
|
|
1001 blo L0385 Yes, continue normally
|
|
1002 NoHW comb Illegal drive # error
|
|
1003 ldb #E$Unit
|
|
1004 rts
|
|
1005
|
|
1006 * Entry: A=drive #, X=LSN (Physical, not OS9 logical if PCDOS disk)
|
|
1007 L0385 pshs x,d Save sector #, drive # & B???
|
|
1008 leax >L0372,pc Point to drive bit mask table
|
|
1009 ldb a,x Get bit mask for drive # we want
|
|
1010 stb >ctlimg,u Save mask
|
|
1011 leax DRVBEG,u Point to beginning of drive tables
|
|
1012 ldb #DRVMEM Get size of each drive table
|
|
1013 mul Calculate offset to drive table we want
|
|
1014 leax d,x Point to it
|
|
1015 cmpx >lastdrv,u Same as Last drive table accessed?
|
|
1016 beq L03A6 Yes, skip ahead
|
|
1017 stx >lastdrv,u Save new drive table ptr
|
|
1018 com >u00AA,u Set drive change flag
|
|
1019 L03A6 clr >currside,u Set side (head) flag to side 1
|
|
1020 lbsr L04B3 Go set up VIRQ to wait for drive motor
|
|
1021 puls pc,x,d Restore sector #,drive #,B & return
|
|
1022
|
|
1023 L03AF ldb >DPort+WD_Stat Get status register from FDC
|
|
1024 * This line needed when returning to Disk Basic but probably
|
|
1025 * not needed for OS-9. RG
|
|
1026 IFNE SCII
|
|
1027 clr RW.Ctrl return SCII to halt mode
|
|
1028 ENDC
|
|
1029 L03B2 bitb #%11111000 any of the error bits set?
|
|
1030 beq L03CA No, exit without error
|
|
1031 aslb Drive not ready?
|
|
1032 bcs L03CC Yes, use that error code
|
|
1033 aslb Write protect error?
|
|
1034 bcs L03D0 Yes, use that error code
|
|
1035 aslb Write fault error?
|
|
1036 bcs L03D4 Yes, use that error code
|
|
1037 aslb Sector not found?
|
|
1038 bcs L03D8 Yes, use Seek error code
|
|
1039 aslb CRC error?
|
|
1040 bcs L03DC Yes, use that error code
|
|
1041 L03CA clrb No error & return
|
|
1042 rts
|
|
1043
|
|
1044 L03CC ldb #E$NotRdy not ready
|
|
1045 fcb $8C skip 2 bytes
|
|
1046
|
|
1047 L03D0 ldb #E$WP write protect
|
|
1048 fcb $8C skip 2 bytes
|
|
1049
|
|
1050 L03D4 ldb #E$Write write error
|
|
1051 fcb $8C
|
|
1052
|
|
1053 L03D8 ldb #E$Seek seek error
|
|
1054 fcb $8C
|
|
1055
|
|
1056 L03DC ldb #E$CRC CRC error
|
|
1057 * fcb $8C
|
|
1058
|
|
1059 *L03E0 ldb #E$Read Read error
|
|
1060 orcc #Carry set carry
|
|
1061 rts
|
|
1062
|
|
1063 L03E4 bsr L0404 Send command to controller & waste some time
|
|
1064 L03E6 ldb >DPort+WD_Stat Check FDC status register
|
|
1065 bitb #$01 Is controller still busy?
|
|
1066 beq L0403 No, exit
|
|
1067 ldd >VIRQCnt,pc Get initial count value for drive motor speed
|
|
1068 std >VIRQPak,u Save it
|
|
1069 * Again, I'm trying to match Kevin Darling code. It may not be needed. RG
|
|
1070 pshs x
|
|
1071 ldx #1 Sleep remainder of slice
|
|
1072 lbsr Delay
|
|
1073 puls x
|
|
1074 bra L03E6 Wait for controller to finish previous command
|
|
1075
|
|
1076 * Send command to FDC
|
|
1077 L03F7 lda #C_MOTOR
|
|
1078 * lda #%00001000 Mask in Drive motor on bit
|
|
1079 ora >ctlimg,u Merge in drive/side selects
|
|
1080 sta >DPort+CtrlReg Turn the drive motor on & select drive
|
|
1081 stb >DPort+WD_Cmd Save command & return
|
|
1082 L0403 rts
|
|
1083
|
|
1084 L0404 bsr L03F7 Go send command to controller
|
|
1085
|
|
1086 * This loop has been changed from nested LBSRs to timing loop.
|
|
1087 * People with crystal upgrades should modify the loop counter
|
|
1088 * to get a 58+ us delay time. MINIMUM 58us.
|
|
1089 FDCDelay
|
|
1090 pshs a 14 cycles, plus 3*loop counter
|
|
1091 IFEQ Level-1
|
|
1092 lda #18 (only do about a 100 cycle delay for now)
|
|
1093 ELSE
|
|
1094 lda #29 (only do about a 100 cycle delay for now)
|
|
1095 ENDC
|
|
1096 L0409 deca for total ~63 us delay (123 cycles max.)
|
|
1097 bne L0409
|
|
1098 puls a,pc restore register and exit
|
|
1099
|
|
1100 * SetStat
|
|
1101 *
|
|
1102 * Entry:
|
|
1103 * A = function code
|
|
1104 * Y = address of path descriptor
|
|
1105 * U = address of device memory area
|
|
1106 *
|
|
1107 * Exit:
|
|
1108 * CC = carry set on error
|
|
1109 * B = error code
|
|
1110 *
|
|
1111 SetStat ldx PD.RGS,y Get caller's register stack ptr
|
|
1112 ldb R$B,x Get function code
|
|
1113 cmpb #SS.WTrk Write track?
|
|
1114 beq SSWTrk Yes, go do it
|
|
1115 cmpb #SS.Reset Restore head to track 0?
|
|
1116 lbeq sktrk0 Yes, go do it --- beq
|
|
1117 comb set carry for error
|
|
1118 ldb #E$UnkSvc return illegal service request error
|
|
1119 rts
|
|
1120
|
|
1121 SSWTrk pshs u,y preserve register stack & descriptor
|
|
1122
|
|
1123 * Level 2 Code
|
|
1124 IFGT Level-1
|
|
1125
|
|
1126 *--- new code
|
|
1127 ldb #1 1 block to allocate
|
|
1128 os9 F$AllRAM allocate some RAM
|
|
1129 lbcs L0489 error out if at all
|
|
1130 leax >FBlock,u point to 'my' DAT image
|
|
1131 std ,x save a copy of the block
|
|
1132 os9 F$ResTsk reserve a task number for the copy
|
|
1133 bcs FError error out
|
|
1134 stb 2,x save temporary task number in FTask,u
|
|
1135 lslb 2 bytes per entry
|
|
1136 ldu <D.TskIPt get task image table pointer
|
|
1137 stx b,u save pointer to the task's DAT image
|
|
1138 lsrb get the right number again
|
|
1139 IFNE H6309
|
|
1140 tfr 0,u destination is address 0
|
|
1141 ELSE
|
|
1142 ldu #$0000
|
|
1143 ENDC
|
|
1144 *--- end new code
|
|
1145
|
|
1146 ldx 2,s get pointer to descriptor
|
|
1147 * stu >FBlock,x
|
|
1148 ldx <D.Proc Get current process ptr
|
|
1149 lda P$Task,x Get task # for current process
|
|
1150 * ldb <D.SysTsk Get system task #
|
|
1151 ldy ,s
|
|
1152 ldx PD.RGS,y Get register stack ptr
|
|
1153 ldx R$X,x Get ptr to caller's track buffer
|
|
1154 ldy #$1A00 Size of track buffer
|
|
1155 os9 F$Move Copy from caller to temporary task
|
|
1156 bcs L0479 Error copying, exit
|
|
1157 puls u,y
|
|
1158 pshs u,y
|
|
1159
|
|
1160 ENDC
|
|
1161 * End of Level 2 Code
|
|
1162
|
|
1163 lbsr L0376 Go check drive #/wait for it to spin up
|
|
1164 ldx PD.RGS,y Get caller's register stack ptr
|
|
1165 ldb R$Y+1,x Get caller's side/density
|
|
1166 bitb #$01 Check side
|
|
1167 beq L0465 Side 1, skip ahead
|
|
1168 * I think this next line is not needed. RG
|
|
1169 com >currside,u * Why? This is normally used with
|
|
1170 * calculate track. RG
|
|
1171 ldb >ctlimg,u Get current control register settings
|
|
1172 * orb #%01000000 Mask in side 2
|
|
1173 orb #C_SIDSEL Mask in side 2
|
|
1174 stb >ctlimg,u Save updated control register
|
|
1175 L0465 lda R$U+1,x Get caller's track #
|
|
1176 ldx >lastdrv,u Get current drive table ptr
|
|
1177 lbsr L02A5
|
|
1178 bcs L0489
|
|
1179 ldb #$F0 Write track command
|
|
1180 *---
|
|
1181 IFEQ Level-1
|
|
1182 ldx PD.RGS,y
|
|
1183 ldx R$X,x
|
|
1184 ELSE
|
|
1185 ldx #$2000 start writing from block 1
|
|
1186 ENDC
|
|
1187
|
|
1188 IFNE SCII
|
|
1189 lda #1 normal unbuffered write
|
|
1190 * Next line prevents WrTrk from switching to SCII buffered mode. RG
|
|
1191 sta flagform,u
|
|
1192 ENDC
|
|
1193 lbsr WrTrk Go write the track
|
|
1194 IFNE SCII
|
|
1195 clr flagform,u permit no-halt mode RG
|
|
1196 ENDC
|
|
1197
|
|
1198 IFGT Level-1
|
|
1199 L0479 ldu 2,s
|
|
1200 pshs b,cc Preserve error
|
|
1201 ldb >FTask,u point to task
|
|
1202 os9 F$RelTsk release the task
|
|
1203 fcb $8C skip 2 bytes
|
|
1204
|
|
1205 * format comes here when block allocation passes, but task allocation
|
|
1206 * gives error. So er de-allocate the block.
|
|
1207 FError
|
|
1208 pshs b,cc save error code, cc
|
|
1209 ldx >FBlock,u point to block
|
|
1210 ldb #1 1 block to return
|
|
1211 os9 F$DelRAM de-allocate image RAM blocks
|
|
1212 clr FBlock+1,u ensure that the block # in FBlock is zero.
|
|
1213 puls b,cc Restore error
|
|
1214 ENDC
|
|
1215
|
|
1216 L0489 puls pc,u,y Restore regs & return
|
|
1217
|
|
1218 * seek the head to track 0
|
|
1219 sktrk0 lbsr chkdrv
|
|
1220 ldx >lastdrv,u
|
|
1221 clr <$15,x
|
|
1222 lda #1 was 5 but that causes head banging
|
|
1223 L0497 ldb <PD.STP,y
|
|
1224 andb #%00000011 Just keep usable settings (6-30 ms)
|
|
1225 eorb #%01001011 Set proper bits for controller
|
|
1226 pshs a
|
|
1227 lbsr L03E4
|
|
1228 puls a
|
|
1229 deca
|
|
1230 bne L0497
|
|
1231 ldb <PD.STP,y
|
|
1232 andb #%00000011 Just keep usable settings (6-30 ms)
|
|
1233 eorb #%00001011 Set proper bits for controller
|
|
1234 lbra L03E4
|
|
1235
|
|
1236 L04B3 pshs y,x,d Preserve regs
|
|
1237 ldd >VIRQCnt,pc Get VIRQ initial count value
|
|
1238 std >VIRQPak,u Save it
|
|
1239 lda >ctlimg,u ?Get drive?
|
|
1240 ora #C_MOTOR Turn drive motor on for that drive
|
|
1241 * ora #%00001000 Turn drive motor on for that drive
|
|
1242 sta >DPort+CtrlReg Send drive motor on command to FDC
|
|
1243 IFEQ Level-1
|
|
1244 lda >D.DskTmr Get VIRQ flag
|
|
1245 ELSE
|
|
1246 lda <D.MotOn Get VIRQ flag
|
|
1247 ENDC
|
|
1248 bmi L04DE Not installed yet, try installing it
|
|
1249 bne L04E0 Drive already up to speed, exit without error
|
|
1250
|
|
1251 * Drive motor speed timing loop (could be F$Sleep call now) (was over .5 sec)
|
|
1252 * 32 was not sufficient for one of my drives. RG
|
|
1253 ldx #50 wait for 32 ticks; increased it RG
|
|
1254 lbsr Delay
|
|
1255
|
|
1256 L04DE bsr InsVIRQ Install VIRQ to wait for drive motors
|
|
1257 L04E0 clrb No error & return
|
|
1258 puls pc,y,x,d
|
|
1259
|
|
1260 InsVIRQ lda #$01 Flag drive motor is up to speed
|
|
1261 IFEQ Level-1
|
|
1262 sta >D.DskTmr
|
|
1263 ELSE
|
|
1264 sta <D.MotOn
|
|
1265 ENDC
|
|
1266 ldx #$0001 Install VIRQ entry
|
|
1267 leay >VIRQPak,u Point to packet
|
|
1268 clr Vi.Stat,y Reset Status byte
|
|
1269 ldd >VIRQCnt,pc Get initial VIRQ count value
|
|
1270 os9 F$VIRQ Install VIRQ
|
|
1271 bcc VIRQOut No error, exit
|
|
1272 lda #$80 Flag that VIRQ wasn't installed
|
|
1273 IFEQ Level-1
|
|
1274 sta >D.DskTmr
|
|
1275 ELSE
|
|
1276 sta <D.MotOn
|
|
1277 ENDC
|
|
1278 VIRQOut clra
|
|
1279 rts
|
|
1280
|
|
1281 * IRQ service routine for VIRQ (drive motor time)
|
|
1282 * Entry: U=Ptr to VIRQ memory area
|
|
1283 IRQSvc pshs a
|
|
1284 lda <D.DMAReq
|
|
1285 beq L0509
|
|
1286 bsr InsVIRQ
|
|
1287 bra IRQOut
|
|
1288 L0509 sta >DPort+CtrlReg
|
|
1289 * I changed this to a clear. Don't see the point of an AND. RG
|
|
1290 * IFNE H6309
|
|
1291 * aim #$FE,>u00B5,u
|
|
1292 * ELSE
|
|
1293 * lda u00B5,u
|
|
1294 * anda #$FE
|
|
1295 * sta u00B5,u
|
|
1296 * ENDC
|
|
1297 * fdb u00B5 --- so changes in data size won't affect anything
|
|
1298 clr u00B5,u
|
|
1299 IFEQ Level-1
|
|
1300 clr >D.DskTmr
|
|
1301 ELSE
|
|
1302 clr <D.MotOn
|
|
1303 ENDC
|
|
1304 IRQOut puls pc,a
|
|
1305
|
|
1306 * Non-OS9 formatted floppies need a drive table entry constructed
|
|
1307 * by hand since there is no RBF LSN0.
|
|
1308 *
|
|
1309 * Entry: X=LSN
|
|
1310 * Y=Path dsc. ptr
|
|
1311 * U=Device mem ptr
|
|
1312 MakeDTEntry
|
|
1313 pshs x Preserve Logical sector #
|
|
1314 ldx >lastdrv,u Get last drive table accessed ptr
|
|
1315 clra
|
|
1316 pshs x,a Save ptr & NUL byte
|
|
1317 IFNE H6309
|
|
1318 ldw #20 Clear 20 bytes
|
|
1319 tfm s,x+
|
|
1320 ELSE
|
|
1321 ldb #20
|
|
1322 L051ALp clr ,x+
|
|
1323 decb
|
|
1324 bne L051ALp
|
|
1325 ENDC
|
|
1326 puls x,a Eat NUL & get back drive table ptr
|
|
1327 ldb <PD.CYL+1,y Get # cylinders on drive (ignores high byte)
|
|
1328 lda <PD.SID,y Get # sides
|
|
1329 mul Calculate # tracks on drive (1 per head)
|
|
1330 IFNE H6309
|
|
1331 decd Adjust to ignore track 0
|
|
1332 ELSE
|
|
1333 subd #$0001
|
|
1334 ENDC
|
|
1335 lda <PD.SCT+1,y Get # sectors/track
|
|
1336 sta DD.TKS,x Save in drive table
|
|
1337 sta <DD.SPT+1,x Save in other copy in drive table
|
|
1338 mul Calculate # sectors on drive (minus track 0)
|
|
1339 pshs x Preserve drive table ptr
|
|
1340 tfr d,x Move # sectors on drive to X
|
|
1341 lda <PD.T0S+1,y Get # sectors on track 0
|
|
1342 leax a,x Add that many sectors to total
|
|
1343 lda <PD.TYP,y Get device type settings
|
|
1344 anda #%00000100 Mask out all but 512 byte sector flag
|
|
1345 beq L0550 Not 512 byte sector, skip ahead
|
|
1346 IFNE H6309
|
|
1347 addr x,x Multiply by 2 (convert to 256 byte OS9 sectors)
|
|
1348 ELSE
|
|
1349 tfr x,d
|
|
1350 leax d,x
|
|
1351 ENDC
|
|
1352 L0550 tfr x,d Move # sectors to D
|
|
1353 puls x Get back drive table ptr
|
|
1354 std DD.TOT+1,x Save # sectors allowed on drive
|
|
1355 lda #UPDAT.+EXEC. Owner's read/write/exec attributes
|
|
1356 sta DD.ATT,x Set attributes for disk
|
|
1357 lda <PD.DNS,y Get density settings
|
|
1358 lsla Shift for DD.FMT
|
|
1359 pshs a Preserve it a sec
|
|
1360 lda <PD.SID,y Get # sides
|
|
1361 deca Adjust to base 0
|
|
1362 ora ,s+ Merge with density settings
|
|
1363 sta <DD.FMT,x Save in device table
|
|
1364 clrb No error?
|
|
1365 puls pc,x Restore original LSN & return
|
|
1366
|
|
1367 emod
|
|
1368 eom equ *
|
|
1369 end
|
|
1370
|