91
|
1 *******************************************
|
|
2 *** ***
|
|
3 *** COPYRIGHT 1990 BURKE & BURKE ***
|
|
4 *** ALL RIGHTS RESERVED ***
|
|
5 *** ***
|
|
6 *** COPYRIGHT 1992 BURKE & BURKE ***
|
|
7 *** ALL RIGHTS RESERVED ***
|
|
8 *** ***
|
|
9 *******************************************
|
|
10
|
|
11 *
|
|
12 * CoCo XT Hard Disk Driver Version 2.0
|
|
13 *
|
|
14 * For Western Digital WD1002-WX1 (or 27X) Controller.
|
|
15 *
|
|
16 * The controller can only handle 512 bytes per sector,
|
|
17 * so these routines must synthesize 2 logical 256 byte
|
|
18 * sectors from each physical 512 byte sector. This
|
|
19 * increases the time it takes to read or write a sector.
|
|
20 *
|
|
21 * To counteract this, the 2nd half of each "even" sector
|
|
22 * is retained during a read. If the next read accesses the
|
|
23 * "odd" half, the sector contents is read from the "verify"
|
|
24 * buffer instead of the hard disk.
|
|
25 *
|
|
26 * This version can be optimized for a single ST-225 hard disk,
|
|
27 * via conditional assembly. Several other parameters can also
|
|
28 * be controlled by conditional assembly.
|
|
29 *
|
|
30 * Conditional assembly control:
|
|
31 *
|
|
32 * Drives ;Number of drives supported (1-2)
|
|
33 *
|
|
34 * irqflg ;non-zero to mask IRQ during disk access.
|
|
35 * fmtflg ;non-zero if hard formatting supported
|
|
36 * fstflg ;non-zero if fast transfers supported
|
|
37 * cchflg ;non-zero if read cache supported
|
|
38 * vrfflg ;non-zero if write verification supported
|
|
39 * tboflg ;non-zero if jump to 2 MHz for block moves
|
|
40 * errflg ;non-zero for good error messages
|
|
41 * icdflg ;non-zero to ignore C/D status bit
|
|
42 * trsflg ;non-zero if optimized for 32 SPT, 4 hd disks
|
|
43 * sysram ;non-zero to use system RAM for verf buffer
|
|
44 * sizflg ;non-zero if drives may be different sizes
|
|
45 *
|
|
46 * XLEVEL ;Special level 2 flag -- to use L1 assembler
|
|
47 *
|
|
48 * Chris Burke Schaumburg, IL 10/14/87
|
|
49 *
|
|
50 * Modification History
|
|
51 * --------------------
|
|
52 *
|
|
53 * Date Who Description
|
|
54 * -------- --- -------------------------------------
|
|
55 * 11/20/87 CJB Fixed bug in PARK.
|
|
56 * 12/23/87 CJB Corrected table size and location
|
|
57 * equates for L2 compatibility.
|
|
58 * Deleted support for Level 1, Version
|
|
59 * 1.X OS9.
|
|
60 * 12/27/87 CJB Added code to grab parameters from
|
|
61 * device descriptor if not obtained
|
|
62 * by INIT.
|
|
63 * 01/28/88 CJB Added support for any slot.
|
|
64 * 02/07/88 CJB Changed FORMAT to reset drive parameters
|
|
65 * Added speedy read cache algorithm.
|
|
66 * Eliminated DIVA, DIVY, etc.
|
|
67 * 02/23/88 CJB Recoded for TRSFLG
|
|
68 * 03/03/88 CJB Changed module names to BBhdisk etc.
|
|
69 * 04/17/88 cjb Modified INIT to call WaitIdl before
|
|
70 * shutting off controller interrupts & DMA
|
|
71 * Fixed bugs in INIT which confused path
|
|
72 * descriptor and device descriptor pointers
|
|
73 * 04/21/88 cjb Added code to disable I/O retries after
|
|
74 * formatting hard drive.
|
|
75 * 06/12/88 cjb Changed to call WaitId2 instead of WaitIdl
|
|
76 * 07/01/88 cjb Changed revision from 2 to 3
|
|
77 * 10/10/88 cjb Modified for format error recovery
|
|
78 * 05/18/90 cjb Modified copyright
|
|
79 * Added support for up to 4 drives
|
|
80 * 07/07/91 cjb Rev 2.5 (allow disabling of recalibration)
|
|
81 * 04/15/92 cjb Rev 2.6 (speed-ups, bug fix for DBLRDD)
|
|
82 *
|
|
83
|
|
84 page
|
|
85 *
|
|
86 * Equates
|
|
87 *
|
|
88
|
|
89 ifp1
|
|
90 use defsfile
|
|
91 use wx2.equ
|
|
92 endc
|
|
93
|
|
94 * Index into device descriptor (using PD.XXX)
|
|
95
|
|
96 DD.BASE equ M$DTYP-PD.OPT
|
|
97 DD.HDSK equ $25 ;Start of extra hard disk stuff
|
|
98
|
|
99 * Multi-PAK Addresses
|
|
100 MPAK equ $FF7F
|
|
101
|
|
102 *
|
|
103 * Bogus equates for Level 2
|
|
104 *
|
|
105
|
|
106 D.DMARq2 equ $008A ;Bogus Level 2 D.DMAReq
|
|
107 D.PROC2 equ $0050 ;Bogus Level 2 D.PROC
|
|
108 DRVMEM2 equ $26 ;Level 2 drive table size
|
|
109 DRVBEG2 equ $0F ;Level 2 start of drive tables
|
|
110
|
|
111 *
|
|
112 * Bogus equates for Level 1
|
|
113 *
|
|
114
|
|
115 D.DMARq1 equ $006A ;Bogus Level 1 D.DMAReq
|
|
116 D.PROC1 equ $004B ;Bogus Level 1 D.PROC
|
|
117 DRVMEM1 equ $18 ;Level 1 drive table size
|
|
118 DRVBEG1 equ $07 ;Level 1 start of drive tables
|
|
119
|
|
120 ifne XLEVEL-1
|
|
121 DMASEM set D.DMARq2 ;Level 2 DMA stuff (multi-pak)
|
|
122 DPROC set D.PROC2 ;Level 2 process control stuff
|
|
123 XDrvBeg set DRVBEG2
|
|
124 XDrvMen set DRVMEM2
|
|
125
|
|
126 else
|
|
127 DMASEM set D.DMARq1 ;Level 1 DMA stuff (multi-pak)
|
|
128 DPROC set D.PROC1 ;Level 1 process control stuff
|
|
129 XDrvBeg set DRVBEG1
|
|
130 XDrvMen set DRVMEM1
|
|
131 endc
|
|
132
|
|
133 page
|
|
134 *
|
|
135 * Module Header
|
|
136 *
|
|
137 verson equ 2
|
|
138 mod cchend,cchnam,drivr+objct,reent+verson,JmpTbl,endmem
|
|
139 fcb DIR.+SHARE.+PEXEC.+PREAD.+PWRIT.+EXEC.+READ.+WRITE.
|
|
140
|
|
141 * Dynamic module name generation
|
|
142
|
|
143 cchnam equ *
|
|
144
|
|
145 ifeq testing
|
|
146 fcc "BB" ; (normal name)
|
|
147 else
|
|
148 fcc "BK" ; (special name)
|
|
149 endc
|
|
150
|
|
151 ifeq (XLEVEL-1) ;If level 1,
|
|
152 ifne irqflg ;If Level 1, Version 1 OS9
|
|
153 fcc /X/
|
|
154 else ;If Level 1, Version 2 OS9
|
|
155 fcc /1/
|
|
156 endc
|
|
157 endc
|
|
158
|
|
159 ifne fmtflg ;If this driver can format hard disk,
|
|
160 fcc /F/
|
|
161 endc
|
|
162
|
|
163 ifne tboflg ;If 2MHz transfers supported,
|
|
164 fcc /T/
|
|
165 endc
|
|
166
|
|
167 ifne trsflg ;If "terse" version
|
|
168 fcs /hd/ ;NOTE -- set MSB of last byte
|
|
169 else ;If "normal" version
|
|
170 fcs /hdisk/ ;NOTE -- set MSB of last byte
|
|
171 endc
|
|
172
|
|
173 fcb $06 ;revision - 2.6
|
|
174
|
|
175 * Copyright notice
|
|
176
|
|
177 fcc /COPR. 1992 BURKE & BURKE/
|
|
178
|
|
179 page
|
|
180 *
|
|
181 * Static Storage
|
|
182 *
|
|
183
|
|
184 use hdvars.src
|
|
185
|
|
186 page
|
|
187 *
|
|
188 * Jump table
|
|
189 *
|
|
190 JmpTbl lbra INIT
|
|
191 lbra READ
|
|
192 lbra WRITE
|
|
193 lbra GETSTA
|
|
194 lbra SETSTA
|
|
195 lbra TERM
|
|
196
|
|
197 ifne sizflg ;If drives may be different sizes,
|
|
198 page
|
|
199 *
|
|
200 * Post-initialization for drives.
|
|
201 *
|
|
202 * If we ever call a driver routine (other than INIT)
|
|
203 * with PARK LSN = 0, we know this drive has not been
|
|
204 * initialized.
|
|
205 *
|
|
206 * Enter w/ Reg-Y = path descriptor pointer,
|
|
207 * Reg-U = static storage
|
|
208 *
|
|
209 * Must save A and B:X as well as Y, U.
|
|
210 *
|
|
211 * Returns carry set if error initializing drive
|
|
212 *
|
|
213 PostIni pshs Y,X,D
|
|
214
|
|
215 ldb PD.DRV,Y
|
|
216 lbsr GOBPtr ;Point Y to extra variables
|
|
217 clrb ;Force no carry (success)
|
|
218 ldb (PRKLSN-OBSTART+0),Y
|
|
219 orb (PRKLSN-OBSTART+1),Y
|
|
220 bne PSTI0 ; (branch if OK)
|
|
221
|
|
222 * Perform drive info and controller intialization
|
|
223
|
|
224 ldy 4,S ;Get path pointer
|
|
225 ldy PD.DEV,Y ; get device table pointer
|
|
226 ldy V$DESC,Y ; get device descriptor pointer
|
|
227 lbsr CtlInit ;Call routine to init. controller
|
|
228
|
|
229 * Done initiailizing this drive.
|
|
230
|
|
231 PSTI0 puls D,X,Y,PC
|
|
232
|
|
233 endc
|
|
234
|
|
235 page
|
|
236 *
|
|
237 * Initialize driver routines
|
|
238 *
|
|
239 * Reg-Y points to device descriptor
|
|
240 *
|
|
241 INIT pshs y
|
|
242
|
|
243 * This section calls routines that expect a *PATH* descriptor
|
|
244 * pointer in Reg-Y
|
|
245
|
|
246 leay DD.BASE,Y ;Make Y look like path descriptor to get slot
|
|
247
|
|
248 lbsr Semfor ;Wait, then select HD controller.
|
|
249 sta >HDRSET ;Reset controller
|
|
250 lbsr WaitId2 ;Sleep -- wait for controller to reset
|
|
251 *** Extra call to give WD1004 time to reset
|
|
252 lbsr WaitId2 ;Sleep -- wait for controller to reset
|
|
253 *** ENDK
|
|
254 ldy ,S ;Restore y -> device descriptor
|
|
255
|
|
256 * Set up controller for non-interrupt, non-DMA operation
|
|
257
|
|
258 clr >HDMASK ;Turn off controller interrupts and DMA
|
|
259
|
|
260 * Set # of drives we can handle
|
|
261
|
|
262 lda #Drives
|
|
263 sta V.NDRV,U
|
|
264
|
|
265 * Set up drive switching info
|
|
266
|
|
267 ifne (Drives-1)
|
|
268 ldd #$FFFF
|
|
269 std prvdrv,u ; (set PRVDRV unknown, DRVSEM for new drive)
|
|
270 std actdrv,u ;Pointer to active drive table
|
|
271 else
|
|
272 lda #$FF
|
|
273 sta DRVSEM,U
|
|
274 endc
|
|
275
|
|
276 * Enable hardware I/O retries. These will be disabled by a FORMAT
|
|
277 * setstat, and will be re-enabled by an INIT call or a reboot.
|
|
278 * The main use of this is to disable retries during disk formatting.
|
|
279
|
|
280 clr RetryEn,U ;Enable hardware retries
|
|
281
|
|
282 * Program controller w/ drive parameters.
|
|
283 * Y points to device descriptor.
|
|
284
|
|
285 bsr CtlInit ; (also clears BFRFLG,U and changes Y)
|
|
286 bcs INIT9 ; (abort if error)
|
|
287
|
|
288 * Initialize the drive tables for all drives
|
|
289
|
|
290 ldd #(-1) ;Current track is unknown
|
|
291 stb XDrvBeg+V.TRAK,U
|
|
292 std XDrvBeg+DD.TOT,U ;Set total sectors non-zero to allow LSN0
|
|
293 ifne (Drives-1)
|
|
294 stb XDrvBeg+XDrvMen*1+V.TRAK,U ; (do all drives)
|
|
295 std XDrvBeg+XDrvMen*1+DD.TOT,U
|
|
296 ifge (Drives-3)
|
|
297 stb XDrvBeg+XDrvMen*2+V.TRAK,U ; (do all drives)
|
|
298 std XDrvBeg+XDrvMen*2+DD.TOT,U
|
|
299 endc
|
|
300 ifge (Drives-4)
|
|
301 stb XDrvBeg+XDrvMen*3+V.TRAK,U ; (do all drives)
|
|
302 std XDrvBeg+XDrvMen*3+DD.TOT,U
|
|
303 endc
|
|
304 endc
|
|
305
|
|
306 * Reg-Y points to bogus path descriptor (courtesy of CtlInit).
|
|
307 * Wait for drive to be ready.
|
|
308 *
|
|
309 * Note that WaiDrv returns Reg-B=0 and carry clear to OK,
|
|
310 * else reg-B = E$NotRdy and carry set.
|
|
311
|
|
312 bsr WaiDrv ;Note: WaiDrv requires *PATH* descriptor
|
|
313
|
|
314 * Error hook
|
|
315 INIT9 puls Y ;restore saved Y register (DD pointer)
|
|
316 bra HDXIT
|
|
317
|
|
318 * Generic error-free exit
|
|
319 OKXIT clrb
|
|
320
|
|
321 *
|
|
322 * Generic exit. Restore MULTI-PAK to
|
|
323 * slot #4 so floppy disk works, and release semaphore
|
|
324 *
|
|
325 * Preserves CC and B
|
|
326 *
|
|
327 * RELEASE also clears the V.WAKE flag.
|
|
328 *
|
|
329 HDXIT lbsr Release
|
|
330 rts
|
|
331
|
|
332 *
|
|
333 * Wait for drive ready
|
|
334 * Assumes reg-Y points to real or bogus path
|
|
335 * descriptor (for drive # and step rate)
|
|
336 *
|
|
337 WaiDrv pshs y,x,a,b
|
|
338
|
|
339 clr ,-s ;Time out
|
|
340
|
|
341 WaiDr2 lda #WX$TST ;Test drive ready
|
|
342
|
|
343 ifne (Drives-1) ;If more than 1 drive
|
|
344 ldb PD.DRV,Y ;get drive #
|
|
345 endc
|
|
346
|
|
347 lbsr DrvCmd
|
|
348 bcc WaiDr3 ; (branch if drive ready)
|
|
349
|
|
350 dec ,s ;Decrement timeout
|
|
351 beq WaiDr4 ; (branch if timeout)
|
|
352
|
|
353 lbsr Snooze ;Give drive some time
|
|
354 bra WaiDr2 ; then retry.
|
|
355
|
|
356 * Timeout
|
|
357
|
|
358 WaiDr4 comb
|
|
359 ldb #E$NotRdy ;Drive not ready
|
|
360 stb 1+1,S
|
|
361
|
|
362 * Carry clear if ready, else carry set
|
|
363
|
|
364 WaiDr3 leas 1,S ;Discard counter
|
|
365 puls a,b,x,y,pc
|
|
366
|
|
367 *
|
|
368 * Get extra bytes from this drive's descriptor.
|
|
369 * Send them to the controller.
|
|
370 *
|
|
371 * Enter w/
|
|
372 * Reg-Y = Dev Desc pointer, and
|
|
373 * Reg-U = static storage pointer.
|
|
374 *
|
|
375 * Note that if there is a 2nd drive with different
|
|
376 * parameters, they must be obtained in a different
|
|
377 * manner.
|
|
378 *
|
|
379 * Modifies Reg-Y to make it look like a bogus *PATH*
|
|
380 * descriptor
|
|
381 *
|
|
382
|
|
383 CtlInit equ *
|
|
384
|
|
385 ifne cchflg ;If read cache,
|
|
386 clr BFRFLG,U ;Buffer contents invalid
|
|
387 endc
|
|
388
|
|
389 bsr GetXtra ;Call subroutine DDPTR in Y.
|
|
390
|
|
391 * Send drive parameters to controller. Reg-Y points to device
|
|
392 * descriptor, but we adjust it to look like a path descriptor.
|
|
393
|
|
394 leay DD.BASE,Y ;Make Y look like path descriptor
|
|
395
|
|
396 lda #WX$INI ;Command to send drive parameters
|
|
397
|
|
398 ifne (Drives-1) ;If more than 1 drive
|
|
399 ldb PD.DRV,Y ;get drive #
|
|
400 endc
|
|
401
|
|
402 lbsr DrvCmd ;Set up drive parameters
|
|
403 rts
|
|
404
|
|
405 page
|
|
406 *
|
|
407 * Copy precomp cylinder and park LSN from descriptor
|
|
408 * (also gives max. tracks!)
|
|
409 *
|
|
410
|
|
411 GetXtra ldd DD.HDSK+(PCCYL-OBSTART),Y ;get prec, MSB of park LSN
|
|
412 ldx DD.HDSK+(PRKLSN+1-OBSTART),Y ;get rest of park LSN
|
|
413 ifne (Drives-1) ; If 2 drives,
|
|
414 ifne sizflg ; of different sizes,
|
|
415 pshs Y,X,D
|
|
416 ldb DD.BASE+PD.DRV,Y ;get drive #
|
|
417 lbsr GOBPtr ;get dest. pointer to Y
|
|
418 puls D,X
|
|
419 std (PCCYL-OBSTART),Y
|
|
420 stx (PRKLSN+1-OBSTART),Y
|
|
421 puls Y,PC ;Recover DD ptr and exit
|
|
422 else ; of same size,
|
|
423 std PCCYL,U
|
|
424 stx (PRKLSN+1),U ;set up both tables at once
|
|
425 std (PCCYL+OBSIZE),U
|
|
426 stx (PRKLSN+1+OBSIZE),U
|
|
427 rts
|
|
428 endc
|
|
429 else ; If 1 drive,
|
|
430 std PCCYL,U
|
|
431 stx (PRKLSN+1),U
|
|
432 rts
|
|
433 endc
|
|
434
|
|
435 page
|
|
436 *
|
|
437 * Terminate hard disk processing
|
|
438 *
|
|
439 TERM lbsr Semfor ;Wait on semaphore, select controller
|
|
440 bra OKXIT ;Clear semaphore and successful exit
|
|
441
|
|
442 *
|
|
443 * Dummy routine for GETSTA
|
|
444 *
|
|
445 GETSTA comb ;Set carry
|
|
446 ldb #E$UnkSVC
|
|
447 rts
|
|
448
|
|
449 page
|
|
450 *
|
|
451 * Read a sector from disk
|
|
452 *
|
|
453 * LSN in B:X. If it is 1+OLDLSN,
|
|
454 * and the drive # is right, and the
|
|
455 * read cache is full, don't even bother
|
|
456 * doing address computations
|
|
457 *
|
|
458 * There are always an even number of sectors
|
|
459 * per track, so if the new LSN is the old LSN
|
|
460 * with MSB set, we have a winner! We always
|
|
461 * store the old LSN with MSB set.
|
|
462 *
|
|
463
|
|
464 READ equ *
|
|
465
|
|
466 ifne cchflg ;If read cache,
|
|
467
|
|
468 pshs X,B ;Save LSN
|
|
469 lbsr SavSlt ;Save old slot #, but don't change yet
|
|
470
|
|
471 tst BFRFLG,U ;Is buffer valid?
|
|
472 beq READXX ; (branch if no luck)
|
|
473 ifne (Drives-1)
|
|
474 lda PD.DRV,Y
|
|
475 cmpa PRVDRV,U
|
|
476 bne READXX ; (branch if drive different)
|
|
477 endc
|
|
478 puls B,X
|
|
479 cmpx OLDLSN+1,U
|
|
480 bne READXY
|
|
481 cmpb OLDLSN+0,U
|
|
482 bne READXY
|
|
483
|
|
484 * Use verify buffer for sector data -- no read necessary!
|
|
485 * The OLDLSN and PRVDRV variables are already set right.
|
|
486
|
|
487 pshs u,y,x
|
|
488
|
|
489 ldb #128
|
|
490 ldx PD.BUF,Y ;Get destination pointer
|
|
491 leay vrfbuf,U ;Get source pointer
|
|
492
|
|
493 DR0 ldu ,y++
|
|
494 stu ,x++
|
|
495 decb
|
|
496 bne DR0
|
|
497
|
|
498 puls x,y,u
|
|
499 bra OKXIT3 ;Successful exit
|
|
500
|
|
501 * Not a cache read. Restore LSN
|
|
502
|
|
503 READXX puls B,X
|
|
504
|
|
505 * Save LSN in case we can do a cache read next time.
|
|
506 * We always set the LSB of the saved LSN; the BFRFLG
|
|
507 * will be set only if the actual LSB is 0!
|
|
508
|
|
509 READXY clr BFRFLG,U ;Assume future cache read invalid
|
|
510 stb OLDLSN+0,U ;Save LSN for next time
|
|
511
|
|
512 pshs B
|
|
513 tfr X,D
|
|
514 bitb #%00000001 ;If LSB is 0, cache read valid next time
|
|
515 bne READXZ
|
|
516
|
|
517 com BFRFLG,U ; (cache read next time)
|
|
518
|
|
519 READXZ orb #%00000001 ; (always set LSB in possible match)
|
|
520 std OLDLSN+1,U
|
|
521 puls B
|
|
522
|
|
523 endc
|
|
524
|
|
525 * Perform normal read -- LSN in B:X
|
|
526
|
|
527 lbsr Semfor ;Wait, select hard disk controller slot
|
|
528
|
|
529 ifne sizflg ;If drives can be different sizes,
|
|
530 lbsr PostIni
|
|
531 bcs HDXIT3
|
|
532 endc
|
|
533
|
|
534 * Check for LSN0
|
|
535
|
|
536 cmpx #0 ;Check for LSN 0 -- SPECIAL
|
|
537 bne NotLS0
|
|
538 tstb
|
|
539 bne NotLS0
|
|
540
|
|
541 ** Wants to read LSN 0.
|
|
542 ** See if LSN 0 has already been read once.
|
|
543 **
|
|
544 ** We must use PD.DTB,Y instead of ACTDRV,U because
|
|
545 ** SELDRV has not been called yet.
|
|
546 **
|
|
547 ** Actually, we still read -- we just don't update
|
|
548 ** the drive table
|
|
549 *
|
|
550 * pshs X,B ;Save LSN
|
|
551 * ifne (Drives-1) ;If 2 drives,
|
|
552 * ldx PD.DTB,Y ;Point to drive table
|
|
553 * else
|
|
554 * leax DRVTBL,U ;Point to drive table
|
|
555 * endc
|
|
556 * ldd DD.TOT,x ;Get total sectors
|
|
557 * cmpd #-1 ; -1 is a special value set by INIT routine
|
|
558 * puls B,X ;Restore LSN (always $000000)
|
|
559 * bne NotLS0 ;If not -1, LSN 0 already read; no special stuff
|
|
560
|
|
561 * Special treatment for LSN0 -- refresh drive table when done
|
|
562
|
|
563 bsr DoRead
|
|
564 bcs HDXIT3
|
|
565
|
|
566 ldx PD.BUF,y ;Get buffer address
|
|
567 pshs Y,X ;Save old buffer and device descriptor ptrs
|
|
568
|
|
569 * Note that the SELDRV routine, called by DOREAD, sets up
|
|
570 * the drive table pointer in actdrv,U if there are 2 drives.
|
|
571
|
|
572 ifne (Drives-1) ;If 2 drives,
|
|
573 ldy actdrv,u
|
|
574 else
|
|
575 leay DRVTBL,U
|
|
576 endc
|
|
577
|
|
578 ldb #DD.SIZ-1
|
|
579
|
|
580 * Update drive table from buffer
|
|
581
|
|
582 RCPY1 lda b,x
|
|
583 sta b,y
|
|
584 decb
|
|
585 bpl RCPY1
|
|
586
|
|
587 puls y,x
|
|
588 bra OKXIT3
|
|
589
|
|
590 * Read (not LSN0)
|
|
591
|
|
592 NotLS0 bsr DoRead
|
|
593 HDXIT3 lbcs HDXIT
|
|
594
|
|
595 OKXIT3 lbra OKXIT
|
|
596
|
|
597 page
|
|
598 *
|
|
599 * Utility to read a sector
|
|
600 *
|
|
601 DoRead lbsr SETUP
|
|
602 bcs DORXIT
|
|
603
|
|
604 * Entry point for VERIFY
|
|
605 VrfRdd ldx PD.BUF,Y ;Get buffer address
|
|
606
|
|
607 * General read sector
|
|
608 GetSec lda #WX$RDD ;Create "READ SINGLE SECTOR" command
|
|
609 lbsr CMEXEC
|
|
610 DORXIT rts
|
|
611
|
|
612 page
|
|
613 *
|
|
614 * Write a sector to disk.
|
|
615 *
|
|
616 * This routine must pre-read the sector in order to
|
|
617 * pack 2 logical sectors into 1 physical sector.
|
|
618 * This invalidates any data that might have been pre-read
|
|
619 * into the verify buffer.
|
|
620 *
|
|
621 WRITE lbsr Semfor ;Wait, then select HD controller
|
|
622
|
|
623 ifne sizflg ;If drives can be different sizes,
|
|
624 lbsr PostIni
|
|
625 bcs HDXIT3
|
|
626 endc
|
|
627
|
|
628 * Pre-read the "other" half of the sector to the verify buffer
|
|
629
|
|
630 pshs X,B ;Save LSN
|
|
631 lbsr SETUP ;Set up head, track, sector #'s
|
|
632 bsr flphlf ;flip LSB of SECNUM
|
|
633
|
|
634 ifne cchflg ;If read cache supported
|
|
635 clr BFRFLG,u ;2nd half of sector should not be saved
|
|
636 endc
|
|
637
|
|
638 leax vrfbuf,U ;Use verify buffer
|
|
639 bsr GetSec ; (re-use code)
|
|
640
|
|
641 puls X,B
|
|
642 bcs HDXIT3 ; branch to abort if pre-read fails
|
|
643
|
|
644 bsr flphlf ;fix up sector #
|
|
645
|
|
646 * Perform the write. The "other" half of the physical sector
|
|
647 * has been pre-read into the verify buffer.
|
|
648
|
|
649 pshs x,b ;save LSN
|
|
650 bsr DoWrit
|
|
651 puls x,b
|
|
652 bcs HDXIT3
|
|
653
|
|
654 ifne vrfflg ;If verify enabled,
|
|
655
|
|
656 tst PD.VFY,Y ;Verify writes?
|
|
657 bne OKXIT3
|
|
658
|
|
659 * Verify the write
|
|
660 bsr VERIFY
|
|
661 bcc OKXIT3
|
|
662
|
|
663 * Verify failed; carry set
|
|
664 ldb #E$Write
|
|
665 bra HDXIT3
|
|
666
|
|
667 else
|
|
668
|
|
669 bra OKXIT3
|
|
670
|
|
671 endc
|
|
672
|
|
673 *
|
|
674 * Flip LSB of SECNUM. This is used to pre-read the half of the sector
|
|
675 * that should not be changed by a write.
|
|
676 *
|
|
677 flphlf lda secnum,u
|
|
678 EORA #1
|
|
679 sta secnum,u
|
|
680 rts
|
|
681
|
|
682 page
|
|
683 *
|
|
684 * Utility to write a sector
|
|
685 *
|
|
686 DoWRIT lbsr SETUP
|
|
687 bcs DOWXIT
|
|
688
|
|
689 ldx PD.BUF,Y ;Get buffer pointer
|
|
690 lda #WX$WRT ;Create "WRITE SINGLE SECTOR" command
|
|
691 lbsr CMEXEC
|
|
692
|
|
693 DOWXIT rts
|
|
694
|
|
695 ifne vrfflg ;If verify supported,
|
|
696
|
|
697 *
|
|
698 * Verify last sector written
|
|
699 *
|
|
700 * Don't copy unused part of sector to verify buffer
|
|
701 *
|
|
702 VERIFY pshs x,b,a
|
|
703
|
|
704 ldx PD.BUF,y ;Save buffer pointer
|
|
705 pshs x
|
|
706
|
|
707 leax vrfbuf,U
|
|
708 stx PD.BUF,y ;Force dummy buffer pointer
|
|
709 ldx 4,s ;Recover LSN
|
|
710
|
|
711 lbsr setup
|
|
712 bcs VF1
|
|
713
|
|
714 ifne cchflg ;If read cache supported,
|
|
715 clr BFRFLG,u ;Mark don't save 2nd half of sector
|
|
716 endc
|
|
717
|
|
718 lbsr VrfRdd ;Actual read done here
|
|
719
|
|
720 VF1 puls x
|
|
721 stx PD.BUF,y ;Restore buffer pointer
|
|
722 bcs VRFXIT
|
|
723
|
|
724 * Look only at every 8th byte to speed up the verify
|
|
725 lda #(256/8) ;Iteration count
|
|
726 pshs u,y,a
|
|
727
|
|
728 leay vrfbuf,U ;Point at sector buffer
|
|
729 tfr x,u
|
|
730
|
|
731 * Compare the data read back to the data written
|
|
732 VRF1 ldx ,u
|
|
733 cmpx ,y
|
|
734 bne VRFERR
|
|
735
|
|
736 leau 8,u ;next byte
|
|
737 leay 8,y
|
|
738 dec ,s
|
|
739 bne VRF1
|
|
740
|
|
741 bra VRFOK
|
|
742
|
|
743 * Error exit
|
|
744 VRFERR orcc #$01
|
|
745
|
|
746 * Deallocate temporaries
|
|
747 VRFOK puls u,y,a
|
|
748
|
|
749 * Generic verify exit
|
|
750 VRFXIT puls a,b,x,PC
|
|
751
|
|
752 endc
|
|
753
|
|
754 page
|
|
755 *
|
|
756 * Set Status.
|
|
757 *
|
|
758 * Reg-Y has path descriptor, and Reg-A has status code.
|
|
759 *
|
|
760 SETSTA lbsr Semfor ;Wait, then select HD controller
|
|
761
|
|
762 ifne sizflg ;If drives can be different sizes,
|
|
763 lbsr PostIni
|
|
764 lbcs HDXIT
|
|
765 endc
|
|
766
|
|
767 lbsr SELDRV
|
|
768
|
|
769 ldx PD.RGS,y ;Point at register stack
|
|
770 ldb R$B,x ;Recover service code
|
|
771
|
|
772 cmpb #SS.Reset
|
|
773 bne SS1
|
|
774
|
|
775 lbsr SEEKT0
|
|
776 bra SSXIT
|
|
777
|
|
778 SS1 equ *
|
|
779
|
|
780 ifne fmtflg ;If hard formatting supported,
|
|
781 cmpb #SS.WTrk
|
|
782 bne SS2
|
|
783
|
|
784 bsr FmtTrk
|
|
785 bra SSXIT
|
|
786 endc
|
|
787
|
|
788 SS2 cmpb #SS.SQD
|
|
789 bne SS9
|
|
790
|
|
791 bsr PwrDwn
|
|
792 bra SSXIT
|
|
793
|
|
794 * Error - unrecognized SETSTA code
|
|
795
|
|
796 SS9 comb
|
|
797 ldb #E$UnkSvc
|
|
798
|
|
799 * Generic exit. Return error if carry set.
|
|
800
|
|
801 SSXIT lbcs HDXIT
|
|
802 lbra OKXIT
|
|
803
|
|
804 page
|
|
805 *
|
|
806 * Power-down (park) disk
|
|
807 *
|
|
808 PwrDwn equ *
|
|
809
|
|
810 * Get park LSN to B:X
|
|
811
|
|
812 ifne (Drives-1) ;If 2 drives,
|
|
813 lbsr GtPkLSN ;Call routine to get park LSN to B:X
|
|
814 else
|
|
815 ldb PRKLSN+0,U
|
|
816 ldx PRKLSN+1,U
|
|
817 endc
|
|
818
|
|
819 * Seek to this LSN
|
|
820
|
|
821 PwrDn2 lbsr SETUP
|
|
822 lbsr SEEK ;Park head at last track
|
|
823 rts
|
|
824
|
|
825 ifne fmtflg ;If hard format supported
|
|
826
|
|
827 *
|
|
828 * Format a track.
|
|
829 *
|
|
830 * Now we format one track at a time.
|
|
831 *
|
|
832 * At entry Reg-X points to the register packet,
|
|
833 * and Reg-Y points to the path descriptor
|
|
834 *
|
|
835 FmtTrk lda #$80 ;Disable hardware retries
|
|
836 sta RetryEn,U
|
|
837
|
|
838 ldd R$U,x ;Get track number -- must be zero.
|
|
839 cmpd #0
|
|
840 bne FMTXIT
|
|
841
|
|
842 ldd R$Y,x ;Check side/density -- MSB must be zero
|
|
843 cmpa #0
|
|
844 beq FMT1
|
|
845
|
|
846 * Ignore repeated calls, returning success
|
|
847 FMTXIT clrb
|
|
848 rts
|
|
849
|
|
850 * Perform the format if not write protected
|
|
851 FMT1 pshs u,y,x
|
|
852
|
|
853 * Proceed, disk not write protected
|
|
854 FMT11 equ *
|
|
855
|
|
856 * Set up reduced drive characteristics (only legal tracks)
|
|
857
|
|
858 lda #WX$XIN ;Bogus command to init. special parameters
|
|
859 lbsr CmExec
|
|
860 bcs FMTERR
|
|
861
|
|
862 * Initialize sector buffer
|
|
863
|
|
864 lda #WX$WBF
|
|
865 lbsr CmExec
|
|
866 bcs FMTERR
|
|
867
|
|
868 * Begin formatting at track 0
|
|
869
|
|
870 ldd #$C0FF ;Set initial cylinder to (-1)
|
|
871 std ERRHCYL,u
|
|
872
|
|
873 * Set up starting track for format
|
|
874
|
|
875 FMT2 ldd ERRHCYL,u ;Use last good cylinder
|
|
876 anda #%11000000
|
|
877 incb
|
|
878 bne FMT3
|
|
879 adda #%01000000
|
|
880 FMT3 std hicyl,U ; (set track number, sector 0)
|
|
881
|
|
882 * clr lowcyl,u ;Clear LOWCYL
|
|
883 * clr hicyl,u ;Clear HICYL (and sector #)
|
|
884
|
|
885 ifne (Drives-1) ;If multiple drives,
|
|
886 lda PD.DRV,Y ;Set up drive #
|
|
887 ldb #32
|
|
888 mul
|
|
889 stb sdhreg,u ;Select correct drive, clear head number
|
|
890 else
|
|
891 clr sdhreg,u
|
|
892 endc
|
|
893
|
|
894 lda PD.ILV,Y ;Set interleave factor
|
|
895 lsra ; / 2 since physical sectors are 2X
|
|
896 sta seccnt,u
|
|
897
|
|
898 lda #WX$FMT ;Command to FORMAT ENTIRE DRIVE
|
|
899 * lda #WX$FTK ;Command to FORMAT TRACK
|
|
900 lbsr CmExec
|
|
901 bcs FMT2 ;Try next track if error
|
|
902
|
|
903 * Return error code in B, C set or no error, C clear
|
|
904
|
|
905 FMTERR pshs b,cc ;Stack error status
|
|
906
|
|
907 * Set up correct drive characteristics (park track allowed)
|
|
908
|
|
909 lda #WX$INI ;Init. original parameters
|
|
910 lbsr CmExec
|
|
911
|
|
912 * Get back error status
|
|
913
|
|
914 puls cc,b
|
|
915
|
|
916 * End of format routine
|
|
917
|
|
918 FMTEND puls x,y,u,PC
|
|
919
|
|
920 endc
|
|
921
|
|
922 *
|
|
923 * End of main line of XTOS9.SRC.
|
|
924 * "USE" files follow.
|
|
925 *
|
|
926
|
|
927 page
|
|
928 *
|
|
929 * Include routines to issue command to controller
|
|
930 * and return completion status.
|
|
931 *
|
|
932
|
|
933 use hdcmd.src
|
|
934
|
|
935 page
|
|
936 *
|
|
937 * Include routines to translate LSN & drive #
|
|
938 * to a controller task file.
|
|
939 *
|
|
940
|
|
941 use hdmath.src
|
|
942
|
|
943 page
|
|
944 *
|
|
945 * Include utility routines.
|
|
946 *
|
|
947
|
|
948 use hdutil3.src
|
|
949
|
|
950 emod
|
|
951 cchend equ *
|
|
952
|
|
953 end
|