91
|
1 * COPYRIGHT BURKE & BURKE 1990
|
|
2 * ALL RIGHTS RESERVED
|
|
3 *
|
|
4 * COCO XT LSN / DRIVE -> TASK FILE CONVERSION
|
|
5 *
|
|
6 * Version 2.0
|
|
7 *
|
|
8 * Date Who Description
|
|
9 * -------- --- --------------------------
|
|
10 * 01-08-88 CJB Coded from version 1.0
|
|
11 * Added GOBPtr routine and support for 2
|
|
12 * drives with different characteristics.
|
|
13 * Changed ST-225 support to work with any
|
|
14 * drive having 32 SPT and 4 heads (e.g.
|
|
15 * ST-238 w/ RLL & W9 in).
|
|
16 * 01/28/88 CJB Changed LSN bounds check in XSETUP --
|
|
17 * compare to park LSN!
|
|
18 * 02/06/88 CJB Fixed bug that caused loss of LSN MSbyte
|
|
19 * when supporting 2 drives.
|
|
20 * Eliminated need for DIVA and DIVY parameters
|
|
21 * 05/18/88 Added CNV99 to check for seek errors
|
|
22 * 12/12/88 cjb Fixed bug in 1-drive XSETUP for park track
|
|
23 * 05/18/90 cjb Added support for drives in multiple slots
|
|
24 *
|
|
25
|
|
26 *
|
|
27 * Get ready to read or write a sector
|
|
28 *
|
|
29 SETUP lbsr SELDRV
|
|
30 bcs SETXIT
|
|
31
|
|
32 bsr XSETUP
|
|
33
|
|
34 SETXIT rts
|
|
35
|
|
36 ifeq trsflg ;If not optimized for 4 heads, 32 SPT
|
|
37
|
|
38 *
|
|
39 * General setup for read or write.
|
|
40 * Drive is already selected.
|
|
41 *
|
|
42 XSETUP pshs y,x,b
|
|
43
|
|
44 ifne (Drives-1)
|
|
45 ldb PD.DRV,Y
|
|
46 lbsr GOBPTR ;Point Y to park LSN area
|
|
47
|
|
48 ldb ,S ;Recover MSByte of LSN
|
|
49 cmpb (PRKLSN-OBSTART+0),Y
|
|
50 lbhi BADSEC
|
|
51 bcs XSET2 ;Branch if OK
|
|
52
|
|
53 cmpx (PRKLSN-OBSTART+1),Y
|
|
54 lbhi BADSEC
|
|
55
|
|
56 * LSN is OK. Still in B:X
|
|
57
|
|
58 XSET2 ldy 3,S ;Recover PD pointer
|
|
59
|
|
60 else
|
|
61 cmpb PRKLSN+0,U
|
|
62 lbhi BADSEC
|
|
63 bcs XSET2
|
|
64
|
|
65 cmpx PRKLSN+1,U
|
|
66 lbhi BADSEC
|
|
67
|
|
68 * LSN is OK. Still in B:X
|
|
69
|
|
70 XSET2 equ *
|
|
71
|
|
72 endc
|
|
73
|
|
74 *
|
|
75 * Convert LSN to cylinder, sector, head #'s
|
|
76 * Save head.sector in TEMP
|
|
77 *
|
|
78 CNVLSN equ *
|
|
79
|
|
80 bsr LSNDIV ;track -> X, Head -> A, sector ->B
|
|
81 std temp,u ;save head & sector for later
|
|
82
|
|
83 clrb ; (clear carry for ROR)
|
|
84 tfr x,d ;Cylinder number
|
|
85 RORA
|
|
86 RORA ;get cylinder MSB's to top of byte
|
|
87 RORA
|
|
88 std hicyl,u
|
|
89
|
|
90 ldb temp+1,U ;Process sector #
|
|
91 andb #%00111111 ; (0-31 normal, 0-47 RLL)
|
|
92 stb secnum,u ;Save logical sector number
|
|
93 lsrb ; / 2 to get physical sector #
|
|
94 orb hicyl,U ; OR in the physical sector number
|
|
95 stb hicyl,U
|
|
96
|
|
97 lda sdhreg,U ;save drive #; OR in head
|
|
98 anda #%00100000
|
|
99 ora temp+0,U
|
|
100 sta sdhreg,U
|
|
101
|
|
102 lda #1 ;read only 1 sector
|
|
103 sta seccnt,U
|
|
104
|
|
105 tst drvsem,u ;is drive ready?
|
|
106 beq CNVOK
|
|
107
|
|
108 *
|
|
109 * Drive is not ready.
|
|
110 *
|
|
111 CNV7 clr drvsem,U
|
|
112
|
|
113 ifne (Drives-1) ;If multiple drives,
|
|
114 * ldy actdrv,u
|
|
115 * lda V.TRAK,y
|
|
116 ldy 3,s ;Restore PD pointer
|
|
117 * cmpa #$FF
|
|
118 * bne CNVOK ;Implicit seek if current track known
|
|
119 lbsr Seek ;Explicit seek
|
|
120 else
|
|
121 lda DRVTBL+V.TRAK,U
|
|
122 cmpa #$FF
|
|
123 bne CNVOK ;Implicit seek if current track known
|
|
124 lbsr SEEKT0 ;Else seek to track 0
|
|
125 endc
|
|
126 bcs CNV99 ; report error if any encountered
|
|
127
|
|
128 * Generic exit w/o error from conversion
|
|
129
|
|
130 CNVOK clrb
|
|
131
|
|
132 CNV9 bcc CNVXIT
|
|
133
|
|
134 CNV99 stb ,s ;Set error code
|
|
135
|
|
136 CNVXIT puls b,x,y,PC
|
|
137
|
|
138 * Return bad sector error
|
|
139
|
|
140 BADSEC puls b
|
|
141 comb
|
|
142 ldb #E$Sect
|
|
143 puls x,y,PC
|
|
144
|
|
145 page
|
|
146 *
|
|
147 * Convert LSN in B:X to track # in X
|
|
148 * and head.sector (remainder) in D. Enter with
|
|
149 * Reg-U -> static storage and Reg-Y -> path descriptor.
|
|
150 *
|
|
151 * Routine assumes that MSB of LSN is 0, and that
|
|
152 * MSB of H*S is 0.
|
|
153 *
|
|
154 * Start by dividing LSN by SPT*heads. The quotient
|
|
155 * is the track number. Then divide the remainder by
|
|
156 * SPT; the quotient is the head, and the remainder
|
|
157 * is the sector.
|
|
158 *
|
|
159 LSNDIV pshs Y,X,B ;Save Y, stack LSN for division
|
|
160
|
|
161 * Calculate SPT * heads
|
|
162
|
|
163 lda PD.SID,Y ;Get sides
|
|
164 ldb (PD.SCT+1),Y ;Get reg-B = SPT
|
|
165 mul
|
|
166
|
|
167 pshs D
|
|
168 clr ,-S ;Now stack = heads*spt
|
|
169
|
|
170 * Calculate track # to X
|
|
171
|
|
172 bsr div24 ;divide, X=quotient, D=remainder
|
|
173 leas 6,S ; discard temps
|
|
174
|
|
175 pshs X ;Save track to return
|
|
176
|
|
177 * Now divide heads*SPT by SPT -- quickly
|
|
178
|
|
179 clr ,-s
|
|
180 com ,s
|
|
181
|
|
182 LDV000 inc ,s
|
|
183 subb (PD.SCT+1),Y
|
|
184 sbca #0
|
|
185 bhs LDV000
|
|
186
|
|
187 addb (PD.SCT+1),Y ;Get sector # to B
|
|
188
|
|
189 puls A,X,Y,PC ;Get head to A, sector to B, track X
|
|
190
|
|
191 *
|
|
192 * Divide 24 bit 'M' by 24 bit 'N'. Return 16 bit quotient
|
|
193 * in Reg-X, 16 bit remainder in Reg-D. Destroys M, N; leaves
|
|
194 * carcasses on stack. Preserves U, Y.
|
|
195 *
|
|
196 * Entry:
|
|
197 * M.l
|
|
198 * M.m
|
|
199 * M.h
|
|
200 * N.l
|
|
201 * N.m
|
|
202 * N.h
|
|
203 * P.l
|
|
204 * SP->P.h
|
|
205 *
|
|
206
|
|
207 div24 pshs Y
|
|
208
|
|
209 * Push special division guys
|
|
210
|
|
211 ldd #1
|
|
212 pshs D
|
|
213 pshs A ;24 bit "1" flag
|
|
214
|
|
215 clrb
|
|
216 pshs D
|
|
217 pshs A ;24 bits of 0's (result)
|
|
218
|
|
219 * Lotsa good stuff on stack. Find biggest multiple of heads*spt
|
|
220 * smaller than or = LSN
|
|
221
|
|
222 LDV001 ldd (8+2+3+0),S
|
|
223 cmpd (8+2+0+0),S
|
|
224 bne LDV002 ;carry set w/ which is more
|
|
225
|
|
226 lda (8+2+3+2),S
|
|
227 cmpa (8+2+0+2),S
|
|
228
|
|
229 * Now CC set for LSN-HS
|
|
230 LDV002 bcs LDV005 ;branch if HS > LSN
|
|
231
|
|
232 * Get to multiply HS etc by 2
|
|
233
|
|
234 asl (3+2),S ;bit flag * 2
|
|
235 rol (3+1),S
|
|
236 rol (3+0),S
|
|
237
|
|
238 asl (8+2+0+2),S ;HS * 2
|
|
239 rol (8+2+0+1),S
|
|
240 rol (8+2+0+0),S
|
|
241
|
|
242 bra LDV001
|
|
243
|
|
244 * Now HS is bigger than LSN. Start dividing.
|
|
245
|
|
246 LDV005 lsr (8+2+0+0),S ;HS / 2
|
|
247 ror (8+2+0+1),S
|
|
248 ror (8+2+0+2),S
|
|
249
|
|
250 lsr (3+0),S ;bit flag / 2
|
|
251 ror (3+1),S
|
|
252 ror (3+2),S
|
|
253 bcs LDV008 ; (branch if ready for remainder)
|
|
254
|
|
255 ldd (8+2+3+1),S ;LSN - HS.scaled
|
|
256 subd (8+2+0+1),S
|
|
257 std (8+2+3+1),S
|
|
258 lda (8+2+3+0),S
|
|
259 sbca (8+2+0+0),S
|
|
260 sta (8+2+3+0),S
|
|
261
|
|
262 bcc LDV007
|
|
263
|
|
264 * No good. Restore LSN
|
|
265
|
|
266 leay (8+2+3),S
|
|
267 leax (8+2+0),S
|
|
268 bsr addxtoy ;LSN + HS.scaled
|
|
269 bra LDV005
|
|
270
|
|
271 * Good. Add bit to result
|
|
272
|
|
273 LDV007 leay 0,S ;Quotient + bit
|
|
274 leax 3,S
|
|
275 bsr addxtoy
|
|
276 bra LDV005
|
|
277
|
|
278 * Now we've checked for all multiples of HS.
|
|
279 * Quotient is at 0-2,S; remainder is where dividend was.
|
|
280 * Quotient and remainder are known to be < 65536
|
|
281
|
|
282 LDV008 ldx (0+1),S ;get 16 bit quotient
|
|
283 leas 6,S ;Deallocate quotient & temps
|
|
284 ldd (4+3+1),S ;get 16 bit remainder
|
|
285
|
|
286 puls Y,PC
|
|
287
|
|
288 *
|
|
289 * Add 24 bits @X to 24 bits @Y
|
|
290 *
|
|
291 addxtoy ldd 1,Y
|
|
292 addd 1,X
|
|
293 std 1,Y
|
|
294 lda 0,Y
|
|
295 adca 0,X
|
|
296 sta 0,Y
|
|
297 rts
|
|
298
|
|
299 else
|
|
300
|
|
301 *
|
|
302 * General setup for read or write.
|
|
303 * Drive is already selected.
|
|
304 *
|
|
305 * Optimized for drives such as ST-225, with
|
|
306 * 32 double-sectors / track. This version
|
|
307 * works only with 4 heads.
|
|
308 *
|
|
309 * Reg-Y points to path descriptor.
|
|
310 * Drive # already set up in SDHREG,U
|
|
311 *
|
|
312 XSETUP pshs y,x,b
|
|
313
|
|
314 ifne (Drives-1)
|
|
315 ldy actdrv,u ;Verify legal LSN (fetch drive table pointer)
|
|
316
|
|
317 cmpb DD.TOT,y
|
|
318 lbhi BADSEC
|
|
319 bcs XSET2 ;Branch if OK
|
|
320
|
|
321 cmpx DD.TOT+1,y
|
|
322 lbcc BADSEC
|
|
323
|
|
324 * LSN is OK. Still in B:X
|
|
325
|
|
326 XSET2 ldy 3,S ;Recover PD pointer
|
|
327
|
|
328 else
|
|
329 cmpb DRVTBL+DD.TOT,U
|
|
330 lbhi BADSEC
|
|
331 bcs XSET2
|
|
332
|
|
333 cmpx DRVTBL+DD.TOT+1,U
|
|
334 lbcc BADSEC
|
|
335
|
|
336 * LSN is OK. Still in B:X
|
|
337
|
|
338 XSET2 equ *
|
|
339
|
|
340 endc
|
|
341
|
|
342 *
|
|
343 * These drives have 4 heads, 32 sectors / track.
|
|
344 * The LSN is known to be in range.
|
|
345 *
|
|
346
|
|
347 pshs x,b ;Calculate track = LSN / (32*4); format for controller
|
|
348 ldd ,s
|
|
349 addd ,s ;double MS word of LSN; /128 is like *2 / 256.
|
|
350 tst 2,s ; (there's never a carry from ADDD)
|
|
351 bpl XSET3
|
|
352
|
|
353 incb ;add in MSB of LS byte if needed -- never a carry
|
|
354
|
|
355 * NOTE -- carry must be clear here.
|
|
356
|
|
357 XSET3 rora ;Controller likes 2 MS bits of cylinder in MS bits of A
|
|
358 rora
|
|
359 rora
|
|
360 std hicyl,U ; (don't need to format Reg-B)
|
|
361
|
|
362 ldb 2,s ;Calculate logical sector and physical sector
|
|
363 andb #%00011111 ; (0-31 ALWAYS -- W9 in for RLL)
|
|
364 stb secnum,u
|
|
365 lsrb ; (physical sector is 1/2 logical -- 0-15)
|
|
366 orb hicyl,u
|
|
367 stb hicyl,u ;format correctly
|
|
368
|
|
369 ldb 2,s ;Calculate head number = LSN / 32
|
|
370 lda #8
|
|
371 mul ; now head number is in Reg-A
|
|
372 anda #%00000011
|
|
373 pshs a
|
|
374 lda sdhreg,u
|
|
375 anda #%00100000 ; (save only the drive # from SELDRV)
|
|
376 ora ,s+
|
|
377 sta sdhreg,u ; format for controller and save
|
|
378
|
|
379 lda #1 ;Set up sector count
|
|
380 sta seccnt,u
|
|
381
|
|
382 leas 3,s ;Discard stack stuff
|
|
383
|
|
384 * Done with task file.
|
|
385 tst drvsem,u ;Is drive ready?
|
|
386 beq CNVOK
|
|
387
|
|
388 * Drive not ready; perform seek
|
|
389 CNV7 clr drvsem,u
|
|
390
|
|
391 ifne (Drives-1) ;If multiple drives,
|
|
392 * ldy actdrv,u
|
|
393 * lda V.TRAK,y
|
|
394 ldy 3,s ;Restore PD pointer
|
|
395 * cmpa #$FF
|
|
396 * bne CNVOK ;Implicit seek if current track known
|
|
397 lbsr Seek ;Explicit seek
|
|
398 else
|
|
399 lda DRVTBL+V.TRAK,U
|
|
400 cmpa #$FF
|
|
401 bne CNVOK ;Implicit seek if current track known
|
|
402 lbsr SEEKT0 ;Else seek to track 0
|
|
403 endc
|
|
404 bcs CNV99
|
|
405
|
|
406 * Generic conversion exit with no error
|
|
407 CNVOK clrb
|
|
408
|
|
409 CNV9 bcc CNVXIT
|
|
410
|
|
411 CNV99 stb ,s
|
|
412
|
|
413 CNVXIT puls b,x,y,PC
|
|
414
|
|
415 * Return bad sector error
|
|
416 BADSEC puls b
|
|
417 comb
|
|
418 ldb #E$Sect
|
|
419 puls x,y,PC
|
|
420
|
|
421 endc
|
|
422
|
|
423 *
|
|
424 * Perform drive selection calculations
|
|
425 *
|
|
426 SELDRV equ *
|
|
427
|
|
428 ifne (Drives-1) ;If multiple drives supported,
|
|
429
|
|
430 lda PD.DRV,Y
|
|
431 cmpa #Drives ;Is drive # OK?
|
|
432 bcs SD0
|
|
433
|
|
434 * Illegal drive error
|
|
435 comb
|
|
436 ldb #E$Unit
|
|
437
|
|
438 SD.XIT rts
|
|
439
|
|
440 * Drive # in A is OK. Set semaphore based on
|
|
441 * current and prev. drive;
|
|
442
|
|
443 SD0 clr drvsem,U ;Assume same drive.
|
|
444 cmpa prvdrv,U ;Same as previous?
|
|
445 beq SD1 ; (if so, we're already set up)
|
|
446
|
|
447 * Set flag to indicate new drive, and wait for drive ready
|
|
448
|
|
449 sta prvdrv,U
|
|
450 dec drvsem,U
|
|
451 lbsr WaiDrv ;Wait -- preserve D,X,Y,U
|
|
452 bcs SD.XIT ; (abort if drive not ready)
|
|
453 ifne cchflg ;If cache supported,
|
|
454 clr BfrFlg,U ;Mark cache data invalid
|
|
455 endc
|
|
456
|
|
457 * Convert drive # to controller's format
|
|
458
|
|
459 SD1 anda #$01 ;2 drives / controller, but allow slots
|
|
460 asla
|
|
461 asla
|
|
462 asla
|
|
463 asla
|
|
464 asla
|
|
465 pshs a
|
|
466 lda sdhreg,U ;get old value
|
|
467 anda #%00001111 ; (save head #)
|
|
468 ora ,s+
|
|
469 sta sdhreg,U
|
|
470
|
|
471 pshs x
|
|
472 ldx PD.DTB,Y ;get pointer to drive table
|
|
473 stx ACTDRV,U
|
|
474 puls x
|
|
475
|
|
476 else
|
|
477
|
|
478 lda sdhreg,U ;get old value
|
|
479 anda #%00001111 ; save head #, force drive # to 0
|
|
480 sta sdhreg,U
|
|
481
|
|
482 endc
|
|
483
|
|
484 * Carry clear unless error
|
|
485 SDXIT rts
|
|
486
|
|
487 ifne (Drives-1) ;For 2 drive systems,
|
|
488
|
|
489 page
|
|
490 *
|
|
491 * Calculate pointer to drive PCCYL, DIVA, DIVY, and PRKTRK
|
|
492 * parameters, based on drive # in Reg-B. Return ptr in Y.
|
|
493 *
|
|
494 * Assumes U->static storage
|
|
495 *
|
|
496 GOBPtr pshs D
|
|
497 lda #OBSIZE ;(size of option packet for each drive)
|
|
498 mul
|
|
499 leay OBSTART,U
|
|
500 leay D,Y ;Point to options for correct drive
|
|
501 puls D,PC
|
|
502
|
|
503 endc
|
|
504
|
|
505 *
|
|
506 * end of hdmath.src
|
|
507 *
|
|
508
|