Mercurial > hg > Members > kono > nitros9-code
comparison level1/modules/rbsuper.asm @ 2590:17d43fd29ee2
Integration of SuperDriver
author | boisy |
---|---|
date | Thu, 22 Dec 2011 18:23:47 +0000 |
parents | |
children | ebf319736e9c |
comparison
equal
deleted
inserted
replaced
2589:e134044fd755 | 2590:17d43fd29ee2 |
---|---|
1 ******************************************************************** | |
2 * rbsuper - RBF Super Caching Device Driver | |
3 * | |
4 * $Id$ | |
5 * | |
6 * (C) 2004 Boisy G. Pitre - Licensed to Cloud-9 | |
7 * | |
8 * RBSuper is the framework for a new type of RBF device driver -- one | |
9 * that fetches native-size, or PHYSICAL sectors. A physical sector is | |
10 * a sector that is sized to its device. For example, all IDE drives and | |
11 * pretty much all SCSI drives have 512 byte sectors; CD-ROMs have 2048 | |
12 * byte sectors. | |
13 * | |
14 * As a high-level driver, this module is responsible for managing | |
15 * the cache, verifying writes, etc. | |
16 * | |
17 * The actual reading and writing of sectors is performed by the | |
18 * low-level driver, which can be designed for any device. | |
19 * | |
20 * Conditionals: | |
21 * H6309 - if set, assembles for 6309 | |
22 * USECS - if set, uses critical section code (slows down driver) | |
23 * HDBDOS - if set, adds code to handle HDB-DOS partitions | |
24 * | |
25 * Edt/Rev YYYY/MM/DD Modified by | |
26 * Comment | |
27 * ------------------------------------------------------------------ | |
28 * 2004/04/10 Boisy G. Pitre | |
29 * Created due to Mark's constant harping about a NitrOS-9 driver for | |
30 * the SuperIDE Interface. Here ya go, Marlette. | |
31 * | |
32 * 2005/12/12 Boisy G. Pitre | |
33 * The SS.VarSect call has been moved from the low level driver to rbsuper | |
34 * for efficiency. Also it no longer calls SS.DSize every time it is called. | |
35 * Instead, it only calls it the first time, then caches the sector size value | |
36 * and returns that value on subsequent calls. | |
37 * | |
38 * 2005/12/13 Boisy G. Pitre | |
39 * Employed a trick to "shift" the idea of where the driver's static | |
40 * data starts at the start of each entry point. This saves about 200 | |
41 * bytes of memory. | |
42 * | |
43 * 1 2006/08/20 Boisy G. Pitre | |
44 * Fixed bug where linking to a non-existent module in Init would cause a crash | |
45 * because IOMan calls the Term routine when Init returns an error. Added a simple | |
46 * one line test in Term to see if a value was non-zero which would indicate if Init | |
47 * | |
48 * 2 2008/02/05 Boisy G. Pitre | |
49 * Fixed bug where DNS HDB flag was being pulled from PD.TYP byte instead of PD.DNS. | |
50 * | |
51 * 3 2011/12/22 Boisy G. Pitre | |
52 * Made a "fast path" for 256 byte sector devices to read/write directly into PD.BUF | |
53 * instead of using the cache, for performance reasons. | |
54 * Conditionalized critical section code since it may not be needed, and affects performance. | |
55 | |
56 NAM rbsuper | |
57 TTL RBF Super Caching Device Driver | |
58 | |
59 IFP1 | |
60 USE defsfile | |
61 USE rbsuper.d | |
62 ENDC | |
63 | |
64 tylg SET Drivr+Objct | |
65 atrv SET ReEnt+rev | |
66 rev SET 0 | |
67 edition SET 2 | |
68 | |
69 MOD eom,name,tylg,atrv,start,V.RBSuper | |
70 | |
71 FCB DIR.+SHARE.+PEXEC.+PREAD.+PWRIT.+EXEC.+UPDAT. | |
72 | |
73 name FCS /RBSuper/ | |
74 FCB edition | |
75 | |
76 start lbra Init | |
77 bra Read | |
78 nop | |
79 lbra Write | |
80 lbra GetStat | |
81 lbra SetStat | |
82 | |
83 * | |
84 * Term | |
85 * | |
86 * Entry: | |
87 * U = address of device memory area | |
88 * | |
89 * Exit: | |
90 * CC = carry set on error | |
91 * B = error code | |
92 * | |
93 Term leau UOFFSET,u | |
94 * Free memory allocated for cache | |
95 lda V.CchSize,u get cache size into A | |
96 * Note, the next line fixes a bug where the system would crash when F$Link in Init failed. | |
97 * If it fails, V.CchSize will never get set, and since it is set to 0 initally, we assume | |
98 * that init failed if V.CchSize is 0 and thus we simply return. | |
99 beq ret@ | |
100 tfr u,x move statics ptr into X for safety | |
101 ldu V.CchAddr,u and load U with cache address | |
102 beq nofree@ | |
103 os9 F$SRtMem return cache memory to system | |
104 nofree@ tfr x,u and restore statics ptr | |
105 * Call low-level driver term | |
106 ldx V.LLTerm,u | |
107 lbsr LLCall | |
108 * Unlink low-level driver | |
109 IFGT Level-1 | |
110 ldx D.Proc get curr proc ptr | |
111 ldd D.SysPrc get system process desc ptr | |
112 std D.Proc and make current proc | |
113 ENDC | |
114 ldu V.LLAddr,u get the address of the low-level module | |
115 os9 F$Unlink unlink it | |
116 IFGT Level-1 | |
117 stx D.Proc restore | |
118 ENDC | |
119 ret@ rts return | |
120 | |
121 * | |
122 * Read | |
123 * | |
124 * Entry: | |
125 * B = MSB of the disk's LSN | |
126 * X = LSB of the disk's LSN | |
127 * Y = address of path descriptor | |
128 * U = address of device memory area | |
129 * | |
130 * Exit: | |
131 * CC = carry set on error | |
132 * B = error code | |
133 * | |
134 Read leau UOFFSET,u | |
135 cmpx #$0000 LSN 0? | |
136 bne ReadSect branch if not | |
137 tstb LSN 0? | |
138 bne ReadSect branch if not | |
139 bsr ReadSect else read LSN0 | |
140 bcs bye if error, return | |
141 * Code to deal with copying LSN0 | |
142 leax DRVBEG-UOFFSET,u point X to start of drive table | |
143 ldb PD.DRV,y get drive number | |
144 lsn@ beq CopyLSN0 branch if zero | |
145 leax DRVMEM,x else increase X by drive table size | |
146 decb decrement drive number | |
147 bra lsn@ branch to loop | |
148 | |
149 * X = drive table pointer for PD.DRV | |
150 * Copy DD.SIZ bytes (LSN0) from buffer to drive table | |
151 CopyLSN0 EQU * | |
152 ldu PD.BUF,y | |
153 IFNE H6309 | |
154 ldw #DD.SIZ | |
155 tfm u+,x+ | |
156 ELSE | |
157 ldb #DD.SIZ | |
158 CpyLSNLp pulu a one cycle less than lda ,u+ | |
159 sta ,x+ | |
160 decb | |
161 bne CpyLSNLp | |
162 ENDC | |
163 rret rts | |
164 | |
165 IFNE HDBDOS | |
166 * For HDB-DOS, we must add in drive number | |
167 * First, multiply drive number in descriptor by $276 (630 sectors), | |
168 * then, add the product to the PSect | |
169 ComputeHDB | |
170 IFNE H6309 | |
171 clra | |
172 ldb V.HDBDrive,u | |
173 muld #$0276 | |
174 addw V.PhysSect+1,u | |
175 stw V.PhysSect+1,u | |
176 adcb V.PhysSect,u | |
177 stb V.PhysSect,u | |
178 ELSE | |
179 leas -4,s make a stack to store product of $276 * DriveNum | |
180 lda V.HDBDrive,u get drive number | |
181 ldb #$76 | |
182 mul | |
183 std 2,s | |
184 lda V.HDBDrive,u | |
185 ldb #$02 | |
186 mul | |
187 std ,s | |
188 clrb | |
189 lda 1,s | |
190 addd 2,s | |
191 std 2,s | |
192 bcc f@ | |
193 inc ,s | |
194 f@ lda ,s | |
195 sta 1,s | |
196 ldd 2,s | |
197 addd V.PhysSect+1,u | |
198 std V.PhysSect+1,u | |
199 lda 1,s | |
200 adca V.PhysSect,u | |
201 sta V.PhysSect,u | |
202 leas 4,s | |
203 ENDC | |
204 ENDC | |
205 bye rts | |
206 | |
207 * 256 byte sector device: setup for low level driver to put 256 byte sector directly into PD.BUF | |
208 Read256 | |
209 lbsr Log2Phys | |
210 * We may not have to do this (and disturb the cache as a result) | |
211 * lda PD.DRV,y get current drive number | |
212 * sta V.LastDrv,u and make this the current drive | |
213 lda #1 | |
214 sta V.SectCnt,u | |
215 ldx PD.BUF,y put address of PD.BUF directly into cache spot | |
216 stx V.CchPSpot,u | |
217 * Call low-level driver read | |
218 ldx V.LLRead,u | |
219 lbra LLCall | |
220 | |
221 * Read Sector | |
222 * | |
223 * The sector will be read from either the cache or the controller. | |
224 * A cache "hit" is verified by two methods: | |
225 * 1. Comparing the drive number of the drive for the current path to | |
226 * the drive number of the last path -- if they match, we *MAY* | |
227 * have a cache hit. If not, we fill the cache | |
228 * 2. If #1 matches, then we know the current drive and the last drive | |
229 * are the same. We then check the logical sector to see if it is | |
230 * in the cache. | |
231 * | |
232 * Entry: | |
233 * Y = address of path descriptor | |
234 * U = address of device memory area | |
235 * B = Sector bits 23-16 | |
236 * X = Sector bits 15-0 | |
237 * | |
238 ReadSect bsr PreXfr to pre-transfer stuff | |
239 bcs bye branch if error | |
240 IFNE HDBDOS | |
241 tst V.HDBPart,u HDB-DOS partition? | |
242 beq NotHDB | |
243 * This is the HDB-DOS partition "read" code path. | |
244 * As an HDB-DOS partition, we are interested ONLY in reading the first 256 bytes | |
245 * regardless of the size of the cache. | |
246 lda V.SectSize,u get sector size (0=256,1=512,2=1024,etc) | |
247 leax SCTTBL,pcr | |
248 lda a,x | |
249 sta V.Log2Phys,u set logical sectors per phys | |
250 lda #$01 get sector count | |
251 sta V.SectCnt,u and store it | |
252 sta V.CchDirty,u the cache will ALWAYS be dirty in HDB-DOS mode | |
253 lda V.LogSect,u get logical sector stored earlier | |
254 sta V.PhysSect,u save off logical sector as physical one | |
255 ldd V.LogSect+1,u get logical sector stored earlier | |
256 std V.PhysSect+1,u save off logical sector as physical sector | |
257 lbsr AddSectorOffset add in partition offset and HDB-DOS drive | |
258 bsr ComputeHDB and compute HDB-DOS offset | |
259 * Set up the pointer to the buffer | |
260 ldx V.CchAddr,u get address of cache | |
261 stx V.CchPSpot,u save in current sector pointer | |
262 * Call low-level driver | |
263 ldx V.LLRead,u | |
264 lbsr LLCall | |
265 bcs bye | |
266 ldx V.CchAddr,u get cache pointer which holds HDB-DOS sector | |
267 bra CopyXToPDBUF | |
268 ENDC | |
269 NotHDB | |
270 * New: Dec 20, 2011 | |
271 * Fast path opportunity: if sector size is 256 bytes, call LLRead right into PD.BUF | |
272 tst V.SectSize,u (0=256 byte sector device) | |
273 beq Read256 | |
274 bsr ValidateCache | |
275 bcs ex@ | |
276 * Copy appropriate 256 byte sector from V.CchAddr to PD.BUF,y | |
277 lda V.CchSize,u get hi byte of cache size | |
278 deca | |
279 anda V.LogSect+2,u | |
280 clrb | |
281 ldx V.CchAddr,u | |
282 leax d,x | |
283 CopyXToPDBUF pshs y | |
284 ldy PD.BUF,y | |
285 IFNE H6309 | |
286 ldw #256 | |
287 tfm x+,y+ | |
288 clrb | |
289 puls y,pc | |
290 ELSE | |
291 clr ,-s | |
292 next@ ldd ,x++ | |
293 std ,y++ | |
294 inc ,s | |
295 bpl next@ | |
296 clrb | |
297 puls a,y,pc | |
298 ENDC | |
299 ex@ rts | |
300 | |
301 * ValidateCache | |
302 * | |
303 * Check if the cache is coherent (i.e. contains requested sector). | |
304 * If the cache is NOT coherent, it calls 'FillCache' to fill it. | |
305 ValidateCache | |
306 * We must determine if the currently requested sector is already in cache. | |
307 * First, is this drive the same as the last drive that accessed the cache? | |
308 * If not, then we need to fill the cache with sectors from the current drive. | |
309 tst V.CchDirty,u has cache been initialized? | |
310 bne nomatch branch if not | |
311 lda PD.DRV,y get current drive | |
312 cmpa V.LastDrv,u save as last drive to access cache? | |
313 bne nomatch if not, fill cache | |
314 * Same drive as last access... is this sector in cache? | |
315 ldb V.LogSect,u save off logical sector | |
316 cmpb V.CchBase,u compare bits 23-16 | |
317 bne nomatch branch if not the same | |
318 lda V.LogSect+1,u save off logical sector | |
319 ldb V.CchSize,u get hi byte of cache size | |
320 decb decrement (e.g. 8=7,4=3,2=1,1=0) | |
321 comb invert (e.g. 7=$F8,3=$FC,1=$FE,0=$FF) | |
322 andb V.LogSect+2,u mask out cached sectors | |
323 cmpd V.CchBase+1,u same as what's in cache? | |
324 beq exok@ YES, WE HAVE A CACHE HIT!!! | |
325 nomatch bra FillCache no, we must fil the cache | |
326 * | |
327 * PreXfr | |
328 * | |
329 * Called at read/write to gather info from path descriptor and | |
330 * device descriptor. | |
331 PreXfr stb V.LogSect,u save off logical sector | |
332 stx V.LogSect+1,u save off logical sector | |
333 lda PD.STP,y get possible HDB-DOS drive number | |
334 sta V.HDBDrive,u save off in our statics | |
335 lda PD.TYP,y | |
336 anda #TYPH.SSM lob off all but sector size bits | |
337 * SmartCache - check if our current cache can accommodate this sector size | |
338 cmpa V.SectSize,u do we need to expand? | |
339 bls no@ branch if not | |
340 * Yes, we need to free our current cache mem and alloc more | |
341 pshs a,u save regs | |
342 ldd V.CchSize,u get current cache size | |
343 ldu V.CchAddr,u and cache pointer | |
344 beq nofree@ | |
345 os9 F$SRtMem return that memory | |
346 nofree@ puls a,u restore regs | |
347 lbsr ExpandCache go expand cache | |
348 bcs ex@ and branch if error | |
349 sta V.SectSize,u save new sector size | |
350 no@ | |
351 lda PD.DNS,y get DNS byte | |
352 anda #DNS.HDB isolate HDB-DOS flag | |
353 sta V.HDBPart,u and save state | |
354 exok@ clrb clear carry | |
355 rts return | |
356 ex@ clr V.SectSize,u clear sector size to force realloc | |
357 orcc #Carry set carry (indicates error) | |
358 rts return | |
359 | |
360 * FillCache | |
361 * | |
362 * Fill the cache with sectors from the device. | |
363 * | |
364 * Destroys: A, B, X | |
365 FillCache | |
366 lda V.LogSect,u get logical sector bits 23-16 | |
367 sta V.CchBase,u save as cached base | |
368 lda V.LogSect+1,u save off logical sector | |
369 ldb V.CchSize,u get hi byte of cache size (1, 2, 4 or 8) | |
370 decb decrement (e.g. 8=7,4=3,2=1,1=0) | |
371 comb invert (e.g. 7=$F8,3=$FC,1=$FE,0=$FF) | |
372 andb V.LogSect+2,u mask out cached sectors | |
373 std V.CchBase+1,u save as cached base | |
374 lbsr Log2Phys convert logical sectors to physical | |
375 lda PD.DRV,y get current drive number | |
376 sta V.LastDrv,u and make this the currently cached drive | |
377 * Set up the transfer | |
378 ldb V.CchSize,u get upper 8 bits of cache size | |
379 lda V.SectSize,u get sector size (0=256,1=512,2=1024,etc) | |
380 leax SCTTBL,pcr | |
381 lda a,x | |
382 sta V.Log2Phys,u | |
383 lda V.SectSize,u get sector size (0=256,1=512,2=1024,etc) | |
384 beq ok@ | |
385 lsr@ lsrb divide by 2 | |
386 deca decrement | |
387 bne lsr@ else divide again | |
388 ok@ stb V.SectCnt,u save sector count | |
389 decb | |
390 comb | |
391 andb V.PhysSect+2,u | |
392 stb V.PhysSect+2,u | |
393 * Set up the pointer to the buffer | |
394 ldx V.CchAddr,u get pointer to big buffer | |
395 stx V.CchPSpot,u save in current sector pointer | |
396 * Call low-level driver read | |
397 ldx V.LLRead,u | |
398 bsr LLCall | |
399 bcs ex@ | |
400 clr V.CchDirty,u cache is no longer dirty | |
401 clrb | |
402 rts | |
403 ex@ stb V.CchDirty,u store error code as dirty flag | |
404 rts | |
405 | |
406 | |
407 SCTTBL FCB 256/256 | |
408 FCB 512/256 | |
409 FCB 1024/256 | |
410 FCB 2048/256 | |
411 | |
412 * GetStat/SetStat | |
413 * | |
414 * Entry: | |
415 * R$B = function code | |
416 * Y = address of path descriptor | |
417 * U = address of device memory area | |
418 * | |
419 * Exit: | |
420 * CC = carry set on error | |
421 * B = error code | |
422 * | |
423 SetStat leau UOFFSET,u | |
424 ldx V.LLStSt,u | |
425 bra LLCall | |
426 | |
427 SSVarSect ldb PD.DRV,y get drive number | |
428 leax V.SSCache,u point to sector size cache table | |
429 abx | |
430 lda ,x get sector size | |
431 bne go2@ if not zero, use that value | |
432 pshs x | |
433 ldx PD.RGS,y | |
434 pshs x | |
435 leas -R$Size,s | |
436 sts PD.RGS,y | |
437 lda #SS.DSize | |
438 sta R$B,s | |
439 bsr gs2 make a call to low level driver's SS.DSize | |
440 * Be sure that no instructions from here to the bcs modify carry | |
441 lda R$A,s | |
442 leas R$Size,s | |
443 puls x | |
444 stx PD.RGS,y | |
445 puls x | |
446 bcs ex@ | |
447 cmpa #8 2048 byte sector? | |
448 beq go@ | |
449 lsra else shift right | |
450 FCB $8C skip next two bytes (cmpx...) | |
451 go@ lda #3 | |
452 sta ,x save newly acquired value off into cached size table | |
453 go2@ pshs a | |
454 lda PD.TYP,y | |
455 anda #^TYPH.SSM | |
456 ora ,s+ | |
457 * Boisy's Notes 3/27/06: | |
458 * Notice that we save the true sector size of the device in the PD.TYP byte of | |
459 * the path descriptor EACH TIME SS.VarSect is called. This is important, | |
460 * because it alleviates the user from having to set this value in the device | |
461 * descriptor in a situation where the device being accessed has a larger sector | |
462 * size than what is in the device descriptor. | |
463 * | |
464 * Note that the value in the device descriptor IS used to initially determine | |
465 * the size of the cache at INIT time since we haven't even talked to the | |
466 * controller at that time yet to query it for its size. | |
467 * sta PD.TYP,y and in path descriptor | |
468 clrb | |
469 ex@ rts | |
470 | |
471 | |
472 GetStat leau UOFFSET,u | |
473 ldx PD.RGS,y get registers | |
474 ldb R$B,x get caller's B | |
475 cmpb #SS.VarSect | |
476 beq SSVarSect | |
477 | |
478 gs2 ldx V.LLGtSt,u | |
479 | |
480 * Entry: Y = path desc ptr | |
481 * U = statics ptr | |
482 * X = address of routine to call | |
483 LLCall | |
484 IFEQ USECS-1 | |
485 pshs a preserve A for duration of csacq_wait | |
486 lda #255 wait the maximum number of counts | |
487 bsr csacq_wait acquire the critical section | |
488 tsta test A for zero | |
489 puls a restore A | |
490 beq cserr return if A was zero (semaphore wasn't acquired) | |
491 ENDC | |
492 pshs u,y save U and Y | |
493 jsr ,x call low level routine | |
494 puls y,u restore U and Y | |
495 | |
496 IFEQ USECS-1 | |
497 * Critical Section Release - clear the critial section to zero, allowing others to use it | |
498 csrel pshs cc preserve CC | |
499 clr V.LLSema,u clear critical section | |
500 puls cc,pc restore CC and return | |
501 cserr comb set the carry | |
502 ldb #111 and load B with error indicating a semaphore timeout | |
503 ENDC | |
504 rts | |
505 | |
506 IFEQ USECS-1 | |
507 * Critical Section Acquire With Wait | |
508 * | |
509 * Entry: | |
510 * A = number of times to check before giving up | |
511 * | |
512 * Exit: | |
513 * A = status (>0 = Critical section acquired, 0 = Critical section not acquired) | |
514 * | |
515 csacq_wait pshs cc save CC on stack | |
516 orcc #IntMasks mask interrupts | |
517 tst V.LLSema,u does someone already have the critical section? | |
518 bne w@ if so, then branch | |
519 inc V.LLSema,u else claim critical section (0->1) | |
520 e@ puls cc,pc restore CC and return | |
521 w@ deca decrement our timeout counter | |
522 beq e@ if zero, we've timed out, return | |
523 puls cc give interrupts a chance to breathe | |
524 IFGT Level-1 | |
525 * Give up timeslice unless this is the system | |
526 pshs x | |
527 ldx D.Proc get proc descriptor | |
528 cmpx D.SysPrc system? | |
529 beq wd@ yep, system cannot sleep | |
530 * ldx D.AProcQ get active proc queue | |
531 * beq wd@ if empty, return | |
532 ldx #$0001 | |
533 os9 F$Sleep give up timeslice | |
534 wd@ puls x return to caller | |
535 ENDC | |
536 bra csacq_wait and try again | |
537 ENDC | |
538 | |
539 | |
540 * Log2Phys - Convert logical sector to physical sector | |
541 * | |
542 * Stores V.PhysSect,u from V.LogSect,u based on V.SectSize,u | |
543 * Also adds IT.SOFF1-IT.SOFF3 to V.PhysSect,u for partitioning. | |
544 * Results are placed in V.PhysSect,u | |
545 Log2Phys lda V.LogSect,u | |
546 sta V.PhysSect,u | |
547 ldd V.LogSect+1,u | |
548 std V.PhysSect+1,u | |
549 lda V.SectSize,u | |
550 beq AddSectorOffset | |
551 DivBy2 lsr V.PhysSect,u | |
552 ror V.PhysSect+1,u | |
553 ror V.PhysSect+2,u | |
554 deca | |
555 bne DivBy2 | |
556 * This routine adds the 3 byte sector offset in the | |
557 * device descriptor to the physical sector. | |
558 AddSectorOffset | |
559 ldx PD.DEV,y | |
560 ldx V$DESC,x | |
561 ldd IT.SOFF2,x | |
562 addd V.PhysSect+1,u | |
563 std V.PhysSect+1,u | |
564 lda IT.SOFF1,x | |
565 adca V.PhysSect,u | |
566 sta V.PhysSect,u | |
567 logex rts | |
568 | |
569 | |
570 * 256 byte sector device: setup for low level driver to put 256 byte sector directly into PD.BUF | |
571 Write256 | |
572 bsr Log2Phys | |
573 * We may not have to do this (and disturb the cache as a result) | |
574 * lda PD.DRV,y get current drive number | |
575 * sta V.LastDrv,u and make this the current drive | |
576 lda #1 | |
577 sta V.SectCnt,u | |
578 ldx PD.BUF,y put address of PD.BUF directly into cache spot | |
579 stx V.CchPSpot,u | |
580 * Call low-level driver read | |
581 ldx V.LLWrite,u | |
582 bra LLCall | |
583 | |
584 * Write | |
585 * | |
586 * Entry: | |
587 * B = MSB of the disk's LSN | |
588 * X = LSB of the disk's LSN | |
589 * Y = address of path descriptor | |
590 * U = address of device memory area | |
591 * | |
592 * Exit: | |
593 * CC = carry set on error | |
594 * B = error code | |
595 * | |
596 Write leau UOFFSET,u | |
597 lbsr PreXfr to pre-transfer stuff | |
598 bcs logex branch if error | |
599 IFNE HDBDOS | |
600 lda V.HDBPart,u HDB-DOS partition? | |
601 beq h@ | |
602 * HDB-DOS partition code path | |
603 sta V.CchDirty,u cache is dirty | |
604 lda V.SectSize,u get sector size (0=256,1=512,2=1024,3=2048) | |
605 leax SCTTBL,pcr | |
606 lda a,x | |
607 sta V.Log2Phys,u set logical sectors per phys | |
608 lda V.LogSect,u | |
609 sta V.PhysSect,u | |
610 ldd V.LogSect+1,u | |
611 std V.PhysSect+1,u | |
612 bsr AddSectorOffset add in partition offset and HDB-DOS drive | |
613 lbsr ComputeHDB and compute HDB-DOS offset | |
614 ldx PD.BUF,y get path desc buffer | |
615 stx V.CchPSpot,u we write directly from PD.BUF | |
616 bra writeit | |
617 ENDC | |
618 * New: Dec 20, 2011 | |
619 * Fast path opportunity: if sector size is 256 bytes, call LLRead right into PD.BUF | |
620 h@ | |
621 tst V.SectSize,u (0=256 byte sector device) | |
622 beq Write256 | |
623 lbsr ValidateCache | |
624 bcs logex | |
625 * Copy appropriate 256 byte sector from PD.BUF,y to V.CchAddr,u | |
626 * Determine where in the cache we copy this 256 byte sector | |
627 bsr Log2Phys compute physical sector from logical sector | |
628 lda V.CchSize,u get hi byte of cache size | |
629 deca | |
630 anda V.LogSect+2,u | |
631 clrb | |
632 ldx V.CchAddr,u | |
633 leax d,x | |
634 stx V.CchLSpot,u save for possible verify later | |
635 pshs y save path desc for now | |
636 ldy PD.BUF,y | |
637 IFNE H6309 | |
638 ldw #256 | |
639 tfm y+,x+ | |
640 puls y | |
641 ELSE | |
642 clr ,-s | |
643 loop@ ldd ,y++ | |
644 std ,x++ | |
645 inc ,s | |
646 bpl loop@ | |
647 puls a,y | |
648 ENDC | |
649 * Now that sector is copied, determine where in cache we start | |
650 lda V.LogSect+2,u get logical sector bits 7-0 | |
651 leax MASKTBL,pcr point to base of cache | |
652 ldb V.SectSize,u get sector size in B | |
653 anda b,x | |
654 pshs a | |
655 lda V.CchSize,u get upper 8 bits of cache size | |
656 deca | |
657 anda ,s+ | |
658 clrb | |
659 ldx V.CchAddr,u point to base of cache | |
660 leax d,x | |
661 stx V.CchPSpot,u | |
662 * Call low-level driver write routine | |
663 writeit lda #$01 | |
664 sta V.SectCnt,u | |
665 ldx V.LLWrite,u | |
666 lbsr LLCall | |
667 * If verify flag is on, read back and compare | |
668 tst PD.VFY,y verify flag set? | |
669 bne ex@ if so, we don't verify -- just exit | |
670 * Read back physical sector into cache | |
671 tst V.HDBPart,u HDB-DOS partition? | |
672 beq o@ | |
673 * If in HDB-DOS mode, we simply place the base address of the cache into | |
674 * V.CchPSpot... and V.CchLSpot for later verify | |
675 ldx V.CchAddr,u | |
676 stx V.CchPSpot,u | |
677 stx V.CchLSpot,u | |
678 o@ lda #$01 | |
679 sta V.SectCnt,u | |
680 ldx V.LLRead,u | |
681 lbsr LLCall | |
682 * Now compare PD.BUF to sector in cache just re-read | |
683 ldx V.CchLSpot,u get spot in cache where 256 byte sector is. | |
684 ldy PD.BUF,y get pointer to buffer | |
685 clra | |
686 a@ ldb ,x+ get byte in cache | |
687 cmpb ,y+ compare against byte in PD.BUF | |
688 bne err@ | |
689 deca | |
690 bne a@ | |
691 ex@ clrb | |
692 rts | |
693 err@ comb | |
694 ldb #E$Write | |
695 stb V.CchDirty,u make cache dirty due to error | |
696 rts | |
697 | |
698 * | |
699 * Init | |
700 * | |
701 * Entry: | |
702 * Y = address of device descriptor | |
703 * U = address of device memory area | |
704 * | |
705 * Exit: | |
706 * CC = carry set on error | |
707 * B = error code | |
708 * | |
709 Init pshs y save device descriptor ptr on stack | |
710 ldb #DrvCount get maximum drives supported | |
711 stb V.NDRV,u save in our device memory | |
712 leax DRVBEG,u point X to the drive tables | |
713 lda #$FF | |
714 * Invalidate V.NDRV drive tables | |
715 drvx sta DD.TOT,x | |
716 sta DD.TOT+1,x | |
717 sta DD.TOT+2,x | |
718 leax DRVMEM,x point to next drive table | |
719 decb decrement counter | |
720 bne drvx if not zero, continue | |
721 * Link to low-level driver | |
722 ldd IT.LLDRV,y point to name in descriptor | |
723 leax d,y point to name in descriptor | |
724 pshs u | |
725 IFGT Level-1 | |
726 ldd D.Proc get curr proc ptr | |
727 pshs d save on stack | |
728 ldd D.SysPrc get system process desc ptr | |
729 std D.Proc and make current proc | |
730 ENDC | |
731 lda #Sbrtn+Objct | |
732 os9 F$Link link to it | |
733 IFGT Level-1 | |
734 puls x get curr proc ptr | |
735 stx D.Proc restore | |
736 ENDC | |
737 tfr u,x transfer module address to X | |
738 puls u restore U | |
739 leau UOFFSET,u | |
740 bcs ret@ | |
741 stx V.LLAddr,u else save module address | |
742 * setup entry points to low-level module | |
743 leax V.LLInit,u | |
744 lda #6 number of entry points | |
745 l@ sty ,x++ | |
746 leay 3,y | |
747 deca | |
748 bne l@ | |
749 * Call low-level driver init | |
750 ldy ,s grab path desc ptr | |
751 ldx V.LLInit,u | |
752 lbsr LLCall | |
753 bcc r@ | |
754 ret@ puls y,pc | |
755 * Allocate cache memory | |
756 r@ lda IT.TYP,y get type byte | |
757 anda #TYPH.SSM mask out all but sector size | |
758 * Added Dec 20, 2011: save off to V.SectSize (never got initialized until now!) | |
759 sta V.SectSize,u clear out V.SectSize | |
760 puls y | |
761 * Fall through to ExpandCache | |
762 | |
763 * Entry: A = cache size to expand to (1 = 512, 2 = 1024, 3 = 2048) | |
764 * Exit: D is destroyed | |
765 * Note: any previously allocated cache memory must have been | |
766 * freed before this call! | |
767 * | |
768 ExpandCache | |
769 pshs a,x | |
770 leax CCHTBL,pcr | |
771 lda a,x get 1, 2, 4 or 8 | |
772 sta V.CchDirty,u make cache dirty since we will expand it | |
773 clrb | |
774 std V.CchSize,u save cache size (256, 512, 1024 or 2048) | |
775 tfr u,x | |
776 os9 F$SRqMem allocate cache memory | |
777 stu V.CchAddr,x save cache ptr | |
778 tfr x,u restore mem pointer | |
779 ex@ puls a,x,pc | |
780 | |
781 | |
782 CCHTBL FCB 256/256 | |
783 FCB 512/256 | |
784 FCB 1024/256 | |
785 FCB 2048/256 | |
786 | |
787 MASKTBL FCB $07,$06,$04,$00 | |
788 | |
789 EMOD | |
790 eom EQU * | |
791 END |