source: branches /fat32-0.9 /src /ifscache.c @ 70

Last change on this file since 70 was 70, checked in by KO Myung-Hun, 17 years ago

Fix the crash when removing USB removable media without 'eject'

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 46.8 KB
Line
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<stdarg.h>
4 #include<string.h>
5 #include<stddef.h>
6 #include<time.h>
7 #include<dos.h>
8
9 #define INCL_DOS
10 #define INCL_DOSDEVIOCTL
11 #define INCL_DOSDEVICES
12 #define INCL_DOSERRORS
13
14 #include"os2.h"
15 #include"portable.h"
16 #include"fat32ifs.h"
17
18
19 #define NOT_USED 0xFFFFFFFF
20 #define MAX_SECTORS 4096
21 #define PAGE_SIZE 4096
22 #define MAX_SLOTS 0x4000
23 #define FREE_SLOT 0xFFFF
24
25 PRIVATEvolatileUSHORTusOldestEntry=0xFFFF;
26 PRIVATEvolatileUSHORTusNewestEntry=0xFFFF;
27 PRIVATEvolatileUSHORTusWaitCount=0;
28 PRIVATEvolatileUSHORTusRQInUse=0;
29 PRIVATEULONGLinCacheAddr=0;
30 PRIVATESELrgCacheSel[(MAX_SECTORS/128)+1]={0};
31 PRIVATEUSHORTusSelCount=1;
32 PRIVATEUSHORTusPhysCount=0;
33 PRIVATEUSHORTusRQCount=MAX_RQS;
34
35 PRIVATECACHEBASEpCacheBase[MAX_SECTORS]={0};
36 PRIVATECACHEBASE2pCacheBase2[MAX_SECTORS]={0};
37 PRIVATEBOOLrgfDirty[MAX_SECTORS]={0};
38 PRIVATEUSHORTrgSlot[MAX_SLOTS]={0};
39 PRIVATERQLISTrgRQ[MAX_RQS]={0};
40
41 PRIVATEBOOLIsSectorInCache(PVOLINFOpVolInfo,ULONGulSector,PBYTEbSector);
42 PRIVATEBOOLfStoreSector(PVOLINFOpVolInfo,ULONGulSector,PBYTEpbSector,BOOLfDirty);
43 PRIVATEPVOIDGetAddress(ULONGulEntry);
44 PRIVATEPVOIDGetPhysAddr(PRQLISTpRQ,ULONGulEntry);
45 PRIVATEBOOLfFindSector(ULONGulSector,BYTEbDrive,PUSHORTpusIndex);
46 PRIVATEUSHORTWriteCacheSector(PVOLINFOpVolInfo,USHORTusCBIndex,BOOLfSetTime);
47 PRIVATEVOIDUpdateChain(USHORTusCBIndex);
48 PRIVATEVOIDvGetSectorFromCache(USHORTusCBIndex,PBYTEpbSector);
49 PRIVATEVOIDvReplaceSectorInCache(USHORTusCBIndex,PBYTEpbSector,BOOLfDirty);
50 PRIVATEVOIDLockBuffer(PCACHEBASEpBase);
51 PRIVATEVOIDUnlockBuffer(PCACHEBASEpBase);
52 PRIVATEPRQLISTGetRequestList(PVOLINFOpVolInfo,BOOLfWait);
53 PRIVATEBOOLfAddToRLH(PRQLISTpRQ,USHORTusCBIndex,BYTEbPriority);
54 PRIVATEVOIDvCallStrategy(PVOLINFOpVolInfo,PRQLISTpRQ);
55 PRIVATEVOIDrlhNotify(VOID);
56 PRIVATEVOIDrhNotify(VOID);
57 PRIVATEVOIDvCheckRequest(PREQUESTpRequest);
58 PRIVATEUSHORTusEmergencyFlush(VOID);
59
60 /******************************************************************
61 *
62 ******************************************************************/
63 BOOLInitCache(ULONGulSectors)
64 {
65 staticBOOLfInitDone=FALSE;
66 ULONGulLinCacheAddr;
67 PCACHEBASEpBase;
68 PCACHEBASE2pBase2;
69 USHORTrc;
70 USHORTusIndex;
71 ULONGulSize;
72 PVOIDp;
73 PAGELISTPageList;
74 ULONGlinPageList;
75
76 if(fInitDone)
77 returnFALSE;
78 fInitDone=TRUE;
79
80 if(!ulSectors||f32Parms.usCacheSize)
81 returnFALSE;
82
83 if(ulSectors>MAX_SECTORS)
84 ulSectors=MAX_SECTORS;
85 Message("Allocating cache space for %ld sectors",ulSectors);
86
87 f32Parms.usCacheSize=0L;
88
89
90 /* Allocate enough selectors */
91
92 usSelCount=(USHORT)(ulSectors/128+(ulSectors%128?1:0));
93
94 rc=DevHelp_AllocGDTSelector(rgCacheSel,usSelCount);
95 if(rc)
96 {
97 FatalMessage("FAT32: AllocGDTSelector failed, rc = %d",rc);
98 returnFALSE;
99 }
100
101 /* Allocate lineair memory */
102
103 ulSize=ulSectors*(ULONG)sizeof(CACHE);
104 ulLinCacheAddr=linalloc(ulSize,f32Parms.fHighMem,f32Parms.fHighMem);
105 if(ulLinCacheAddr==0xFFFFFFFF)
106 {
107 /* If tried to use high memory, try to use low memory */
108 if(f32Parms.fHighMem)
109 {
110 f32Parms.fHighMem=FALSE;
111 ulLinCacheAddr=linalloc(ulSize,f32Parms.fHighMem,f32Parms.fHighMem);
112 }
113
114 if(ulLinCacheAddr==0xFFFFFFFF)
115 returnFALSE;
116 }
117
118 /* Fill the selectors */
119
120 LinCacheAddr=ulLinCacheAddr;
121 for(usIndex=0;usIndex<usSelCount;usIndex++)
122 {
123 ULONGulBlockSize=0x10000;
124 if(ulBlockSize>ulSize)
125 ulBlockSize=ulSize;
126 rc=DevHelp_LinToGDTSelector(rgCacheSel[usIndex],
127 LinCacheAddr+(ULONG)usIndex*0x10000,ulBlockSize);
128 if(rc)
129 {
130 FatalMessage("FAT32: LinToGDTSelector (%d) failed, rc = %d",usIndex,rc);
131 returnFALSE;
132 }
133 ulSize-=0x10000;
134 }
135
136
137 f32Parms.usCacheSize=(USHORT)ulSectors;
138 f32Parms.usDirtyTreshold=
139 f32Parms.usCacheSize-(f32Parms.usCacheSize/20);
140
141 /* initiate request lists */
142
143 p=&PageList;
144 rc=DevHelp_VirtToLin(SELECTOROF(p),OFFSETOF(p),&linPageList);
145 if(rc)
146 FatalMessage("FAT32:VirtToLin for pagelist failed, rc = %d",rc);
147
148 usRQCount=(USHORT)((ULONG)MAX_RQS*ulSectors/MAX_SECTORS);
149 if(usRQCount<MAX_RQS)
150 usRQCount++;
151 for(usIndex=0;usIndex<usRQCount;usIndex++)
152 {
153 USHORTusIndex2;
154
155 rgRQ[usIndex].usNr=usIndex;
156
157 /* 65535 bytes */
158 ulSize=MAXRQENTRIES*512L;
159
160 rc=DevHelp_AllocGDTSelector(&rgRQ[usIndex].Sel,1);
161 if(rc)
162 {
163 FatalMessage("FAT32: AllocGDTSelector for RLH failed, rc = %d",rc);
164 returnFALSE;
165 }
166
167 rgRQ[usIndex].ulLin=linalloc(ulSize,f32Parms.fHighMem,f32Parms.fHighMem);
168 if(rgRQ[usIndex].ulLin==0xFFFFFFFF)
169 {
170 /* If tried to use high memory, try to use low memory */
171 if(f32Parms.fHighMem)
172 {
173 f32Parms.fHighMem=FALSE;
174 rgRQ[usIndex].ulLin=linalloc(ulSize,f32Parms.fHighMem,f32Parms.fHighMem);
175 }
176
177 if(rgRQ[usIndex].ulLin==0xFFFFFFFF)
178 {
179 FatalMessage("FAT32: linAlloc for RLH failed");
180 returnFALSE;
181 }
182 }
183
184 rc=DevHelp_LinToGDTSelector(rgRQ[usIndex].Sel,
185 rgRQ[usIndex].ulLin,ulSize);
186 if(rc)
187 {
188 FatalMessage("FAT32: LinToGDTSelector for RLH failed, rc = %d",rc);
189 returnFALSE;
190 }
191
192 usPhysCount=(USHORT)(ulSize/PAGE_SIZE)+(ulSize%PAGE_SIZE?1:0);
193
194 for(usIndex2=0;usIndex2<usPhysCount;usIndex2++)
195 {
196 ULONGulBlockSize=PAGE_SIZE;
197 if(ulBlockSize>ulSize)
198 ulBlockSize=ulSize;
199
200 rc=DevHelp_LinToPageList(rgRQ[usIndex].ulLin+(ULONG)usIndex2*PAGE_SIZE,
201 ulBlockSize,
202 linPageList,
203 &ulBlockSize);
204 if(rc)
205 {
206 FatalMessage("FAT32: LinToPageList for RLH (%d) failed, rc = %d",usIndex2,rc);
207 returnFALSE;
208 }
209 if(ulBlockSize!=1)
210 {
211 FatalMessage("FAT32: LinToPageList for RLH (%d) did not fill 1 entry",rc);
212 returnFALSE;
213 }
214
215 rgRQ[usIndex].rgPhys[usIndex2]=PageList.PhysAddr;
216 ulSize-=PAGE_SIZE;
217 }
218 }
219
220 pBase=pCacheBase;
221 pBase2=pCacheBase2;
222 for(usIndex=0;usIndex<f32Parms.usCacheSize;usIndex++)
223 {
224 pBase->ulSector=NOT_USED;
225 pBase->bDrive=0xFF;
226 pBase2->usOlder=0xFFFF;
227 pBase2->usNewer=0xFFFF;
228 if(usIndex+1<f32Parms.usCacheSize)
229 pBase->usNext=usIndex+1;
230 else
231 pBase->usNext=FREE_SLOT;
232 pBase++;
233 pBase2++;
234 }
235 memset(rgSlot,0xFF,sizeofrgSlot);
236 memset(rgfDirty,FALSE,sizeofrgfDirty);
237
238 f32Parms.usCacheUsed=0L;
239
240 /*
241 Making sure all segments are available during interrupts
242 */
243 p=(PVOID)InitCache;
244 rc=FSH_FORCENOSWAP(SELECTOROF(p));
245 if(rc)
246 FatalMessage("FAT32: FSH_FORCENOSWAP on CODE Segment failed, rc=%u",rc);
247
248 p=(PVOID)pCacheBase;
249 rc=FSH_FORCENOSWAP(SELECTOROF(p));
250 if(rc)
251 FatalMessage("FAT32:FSH_FORCENOSWAP on pCacheBase Segment failed, rc=%u",rc);
252
253 p=(PVOID)&LinCacheAddr;
254 rc=FSH_FORCENOSWAP(SELECTOROF(p));
255 if(rc)
256 FatalMessage("FAT32:FSH_FORCENOSWAP on DATA Segment failed, rc=%u",rc);
257
258 p=(PVOID)rgRQ;
259 rc=FSH_FORCENOSWAP(SELECTOROF(p));
260 if(rc)
261 FatalMessage("FAT32:FSH_FORCENOSWAP on rgRQ Segment failed, rc=%u",rc);
262
263
264 returnTRUE;
265 }
266
267
268 #define Cluster2Sector( ulCluster ) (( ULONG )( pVolInfo->ulStartOfData + \
269 (( ULONG )( ulCluster ) - 2) * pVolInfo->BootSect.bpb.SectorsPerCluster ))
270
271 #define Sector2Cluster( ulSector ) (( ULONG )((( ULONG )( ulSector ) - pVolInfo->ulStartOfData ) / \
272 pVolInfo->BootSect.bpb.SectorsPerCluster + 2 ))
273
274 /******************************************************************
275 *
276 ******************************************************************/
277 USHORTReadSector(PVOLINFOpVolInfo,ULONGulSector,USHORTnSectors,PCHARpbData,USHORTusIOMode)
278 {
279 INTrc;
280 USHORTusSectors;
281 PSZp;
282 USHORTusIndex;
283 PBYTEpbSectors;
284 BOOLfFromCache;
285 BOOLfSectorInCache;
286 USHORTusCBIndex;
287
288 if(ulSector+nSectors-1>=pVolInfo->BootSect.bpb.BigTotalSectors)
289 {
290 FatalMessage("FAT32: ERROR: Sector %ld does not exist on disk %c:",
291 ulSector+nSectors-1,pVolInfo->bDrive+'A');
292 returnERROR_SECTOR_NOT_FOUND;
293 }
294
295 f32Parms.ulTotalReads+=nSectors;
296
297 /*
298 See if all sectors are in cache
299 */
300 fFromCache=TRUE;
301 p=pbData;
302 for(usIndex=0;usIndex<nSectors;usIndex++)
303 {
304 if(!IsSectorInCache(pVolInfo,ulSector+usIndex,p))
305 {
306 fFromCache=FALSE;
307 break;
308 }
309 p+=SECTOR_SIZE;
310 }
311 /*
312 if all sectors were found in cache, we are done
313 */
314 if(fFromCache)
315 return0;
316
317 #if 0
318 if (f32Parms.fMessageActive & LOG_CACHE)
319 {
320 if (ulSector > pVolInfo->ulStartOfData)
321 Message("Cluster %lu not found in cache!",
322 (ulSector - pVolInfo->ulStartOfData) / pVolInfo->BootSect.bpb.SectorsPerCluster + 2);
323 }
324 #endif
325 pbSectors=NULL;
326 if((ulSector>=pVolInfo->ulStartOfData)&&
327 !(usIOMode&DVIO_OPNCACHE)&&nSectors<pVolInfo->usRASectors)
328 {
329 usSectors=pVolInfo->usRASectors;
330 if(ulSector+usSectors>pVolInfo->BootSect.bpb.BigTotalSectors)
331 usSectors=(USHORT)(pVolInfo->BootSect.bpb.BigTotalSectors-ulSector);
332 pbSectors=malloc(usSectors*512);
333 }
334 if(!pbSectors)
335 {
336 pbSectors=pbData;
337 usSectors=nSectors;
338 }
339
340 /* check bad cluster */
341 if(ulSector>=pVolInfo->ulStartOfData)
342 {
343 ULONGulStartCluster=Sector2Cluster(ulSector);
344 ULONGulEndCluster=Sector2Cluster(ulSector+usSectors-1);
345 ULONGulNextCluster=0;
346 ULONGulCluster;
347
348 for(ulCluster=ulStartCluster;ulCluster<=ulEndCluster;ulCluster++)
349 {
350 ulNextCluster=GetNextCluster(pVolInfo,ulCluster);
351 if(ulNextCluster==FAT_BAD_CLUSTER)
352 break;
353 }
354
355 if(ulNextCluster==FAT_BAD_CLUSTER)
356 {
357 usSectors=(ulStartCluster!=ulCluster)?
358 (min((USHORT)(Cluster2Sector(ulCluster)-ulSector),usSectors)):0;
359 }
360 }
361
362 usIOMode&=~DVIO_OPWRITE;
363 pVolInfo->ulLastDiskTime=GetCurTime();
364 usWaitCount++;
365 rc=FSH_DOVOLIO(DVIO_OPREAD|usIOMode,DVIO_ALLACK,pVolInfo->hVBP,pbSectors,&usSectors,ulSector);
366 usWaitCount--;
367 if(rc)
368 {
369 CritMessage("FAT32: ReadSector of sector %ld (%d sectors) failed, rc = %u",
370 ulSector,usSectors,rc);
371 Message("ERROR: ReadSector of sector %ld (%d sectors) failed, rc = %u",
372 ulSector,usSectors,rc);
373 }
374
375 /*
376 Store sector only in cache if we should
377 */
378 if(!rc)
379 {
380 p=pbSectors;
381 for(usIndex=0;usIndex<usSectors;usIndex++)
382 {
383 /*
384 Was sector already in cache?
385 */
386 fSectorInCache=fFindSector(ulSector+usIndex,
387 pVolInfo->bDrive,
388 &usCBIndex);
389
390 switch(fSectorInCache)
391 {
392 /*
393 No, it wasn't. Store it if needed.
394 */
395 caseFALSE:
396 if(!(usIOMode&DVIO_OPNCACHE))
397 fStoreSector(pVolInfo,ulSector+usIndex,p,FALSE);
398 break;
399 caseTRUE:
400 /*
401 Yes it was. Get it if it was dirty since then it is different
402 from version on disk.
403 */
404 if(rgfDirty[usCBIndex])
405 vGetSectorFromCache(usCBIndex,p);
406 UnlockBuffer(pCacheBase+usCBIndex);
407 break;
408 }
409 p+=SECTOR_SIZE;
410 }
411 }
412
413 if(!rc&&pbSectors!=pbData)
414 {
415 f32Parms.ulTotalRA+=usSectors>nSectors?(usSectors-nSectors):0;
416 memcpy(pbData,pbSectors,min(usSectors,nSectors)*512);
417 }
418 if(pbSectors!=pbData)
419 free(pbSectors);
420
421 returnrc;
422 }
423
424 /******************************************************************
425 *
426 ******************************************************************/
427 USHORTWriteSector(PVOLINFOpVolInfo,ULONGulSector,USHORTnSectors,PCHARpbData,USHORTusIOMode)
428 {
429 INTrc;
430 USHORTusSectors=nSectors;
431 PSZp;
432 USHORTusIndex;
433 BOOLfDirty;
434 BOOLfSectorInCache;
435 USHORTusCBIndex;
436
437 if(pVolInfo->fWriteProtected)
438 returnERROR_WRITE_PROTECT;
439
440 if(pVolInfo->fDiskClean)
441 MarkDiskStatus(pVolInfo,FALSE);
442
443 if(ulSector+nSectors-1>=pVolInfo->BootSect.bpb.BigTotalSectors)
444 {
445 FatalMessage("FAT32: ERROR: Sector %ld does not exist on disk %c:",
446 ulSector+nSectors-1,pVolInfo->bDrive+'A');
447 returnERROR_SECTOR_NOT_FOUND;
448 }
449
450 fDirty=TRUE;
451 rc=0;
452 if(!f32Parms.fLW||(usIOMode&DVIO_OPWRTHRU)||(usIOMode&DVIO_OPNCACHE))
453 {
454 if(f32Parms.fLW&&f32Parms.fMessageActive&LOG_CACHE)
455 Message("WriteSector: Writing sector thru");
456 pVolInfo->ulLastDiskTime=GetCurTime();
457 usWaitCount++;
458 rc=FSH_DOVOLIO(DVIO_OPWRITE|usIOMode,DVIO_ALLACK,pVolInfo->hVBP,pbData,&usSectors,ulSector);
459 usWaitCount--;
460 if(rc&&rc!=ERROR_WRITE_PROTECT)
461 CritMessage("FAT32: ERROR: WriteSector sector %ld (%d sectors) failed, rc = %u",
462 ulSector,nSectors,rc);
463 fDirty=FALSE;
464 }
465
466
467 if(!rc)
468 {
469 p=pbData;
470 for(usIndex=0;usIndex<nSectors;usIndex++)
471 {
472 fSectorInCache=
473 fFindSector(ulSector+usIndex,pVolInfo->bDrive,&usCBIndex);
474 switch(fSectorInCache)
475 {
476 caseFALSE:
477 if(!(usIOMode&DVIO_OPNCACHE))
478 fStoreSector(pVolInfo,ulSector+usIndex,p,fDirty);
479 break;
480 caseTRUE:
481 {
482 BOOLfIdent=FALSE;
483
484 if(fDirty)
485 {
486 PCACHEpCache;
487
488 pCache=GetAddress(usCBIndex);
489 fIdent=memcmp(p,pCache->bSector,SECTOR_SIZE)==0;
490 }
491
492 if(!fIdent)
493 vReplaceSectorInCache(usCBIndex,p,fDirty);
494 UnlockBuffer(pCacheBase+usCBIndex);
495 break;
496 }
497 }
498 p+=SECTOR_SIZE;
499 }
500 }
501
502 returnrc;
503 }
504
505
506
507 /******************************************************************
508 *
509 ******************************************************************/
510 BOOLIsSectorInCache(PVOLINFOpVolInfo,ULONGulSector,PBYTEpbSector)
511 {
512 USHORTusIndex;
513
514 if(!fFindSector(ulSector,pVolInfo->bDrive,&usIndex))
515 returnFALSE;
516 f32Parms.ulTotalHits++;
517 vGetSectorFromCache(usIndex,pbSector);
518 UnlockBuffer(pCacheBase+usIndex);
519 returnTRUE;
520 }
521
522 /******************************************************************
523 *
524 ******************************************************************/
525 VOIDvGetSectorFromCache(USHORTusCBIndex,PBYTEpbSector)
526 {
527 PCACHEBASEpBase;
528 PCACHEpCache;
529
530 pBase=pCacheBase+usCBIndex;
531
532 pCache=GetAddress(usCBIndex);
533 memcpy(pbSector,pCache->bSector,512);
534
535 pBase->ulAccessTime=GetCurTime();
536 UpdateChain(usCBIndex);
537
538 return;
539 }
540
541 /******************************************************************
542 *
543 ******************************************************************/
544 VOIDUpdateChain(USHORTusCBIndex)
545 {
546 PCACHEBASE2pBase2;
547
548 /*
549 Is entry already the newest ?
550 */
551 if(usNewestEntry==usCBIndex)
552 return;
553
554 pBase2=pCacheBase2+usCBIndex;
555 /*
556 Remove entry from current position in chain
557 */
558 if(pBase2->usOlder!=0xFFFF)
559 pCacheBase2[pBase2->usOlder].usNewer=pBase2->usNewer;
560 if(pBase2->usNewer!=0xFFFF)
561 pCacheBase2[pBase2->usNewer].usOlder=pBase2->usOlder;
562
563 /*
564 Update the oldest if this entry was the oldest
565 */
566
567 if(usOldestEntry==0xFFFF)
568 usOldestEntry=usCBIndex;
569 elseif(usOldestEntry==usCBIndex)
570 usOldestEntry=pBase2->usNewer;
571
572 /*
573 Update base itself
574 */
575 pBase2->usOlder=usNewestEntry;
576 if(usNewestEntry!=0xFFFF)
577 pCacheBase2[usNewestEntry].usNewer=usCBIndex;
578 usNewestEntry=usCBIndex;
579 pBase2->usNewer=0xFFFF;
580 }
581
582 #if 1
583 #define WAIT_THRESHOLD
584 #endif
585 /******************************************************************
586 *
587 ******************************************************************/
588 BOOLfStoreSector(PVOLINFOpVolInfo,ULONGulSector,PBYTEpbSector,BOOLfDirty)
589 {
590 USHORTusSlot;
591 USHORTusCBIndex;
592 PCACHEBASEpBase;
593 PCACHEBASE2pBase2;
594 USHORTusCount;
595
596 if(!f32Parms.usCacheSize)
597 returnFALSE;
598
599 pBase=NULL;
600 if(f32Parms.usCacheUsed<f32Parms.usCacheSize)
601 {
602 usCBIndex=f32Parms.usCacheUsed;
603 f32Parms.usCacheUsed++;
604
605 pBase=pCacheBase+usCBIndex;
606 LockBuffer(pBase);
607
608 usSlot=(USHORT)(ulSector%MAX_SLOTS);
609 pBase->usNext=rgSlot[usSlot];
610 rgSlot[usSlot]=usCBIndex;
611
612 pBase->ulSector=ulSector;
613 pBase->bDrive=pVolInfo->bDrive;
614
615 vReplaceSectorInCache(usCBIndex,pbSector,fDirty);
616 UnlockBuffer(pBase);
617 }
618 else
619 {
620 PCACHEBASEpWork;
621 USHORTusIndex;
622
623 if(usOldestEntry==0xFFFF)
624 FatalMessage("FAT32: No Oldest entry found!");
625
626 if(usRQInUse<usRQCount&&
627 #ifdef WAIT_THRESHOLD
628 f32Parms.usDirtySectors>=f32Parms.usDirtyTreshold)
629 #else
630 f32Parms.usDirtySectors-f32Parms.usPendingFlush>f32Parms.usDirtyTreshold)
631 #endif
632 {
633 if(f32Parms.fMessageActive&LOG_CACHE||
634 f32Parms.fMessageActive&LOG_WAIT)
635 Message("ProcRun on EmergencyFlush");
636
637 usWaitCount++;
638 DevHelp_ProcRun((ULONG)DoEmergencyFlush,&usCount);
639 DevHelp_TCYield();
640 usWaitCount--;
641
642 if(f32Parms.fMessageActive&LOG_CACHE||
643 f32Parms.fMessageActive&LOG_WAIT)
644 Message("continuing after ProcRun...");
645
646 #ifdef WAIT_THRESHOLD
647 if(f32Parms.fMessageActive&LOG_CACHE||
648 f32Parms.fMessageActive&LOG_WAIT)
649 Message("waiting for dirty sectors to be less than threshold...");
650
651 _disable();
652 while(f32Parms.usDirtySectors>=f32Parms.usDirtyTreshold)
653 {
654 DevHelp_ProcBlock((ULONG)&f32Parms.usDirtySectors,1000L,1);
655 _disable();
656 }
657 _enable();
658 #endif
659 }
660
661 /*
662 find the oldest non dirty, not locked, not pending sector in cache
663 */
664
665 fStoreRetry:
666
667 usCBIndex=0xFFFF;
668 if(f32Parms.usDirtySectors<f32Parms.usCacheSize)
669 {
670 usCBIndex=usOldestEntry;
671 while(usCBIndex!=0xFFFF)
672 {
673 if(!rgfDirty[usCBIndex])
674 {
675 pBase=pCacheBase+usCBIndex;
676 if(!pBase->fLocked)
677 {
678 LockBuffer(pBase);
679 if(!rgfDirty[usCBIndex])
680 break;
681 UnlockBuffer(pBase);
682 }
683 }
684 pBase2=pCacheBase2+usCBIndex;
685 usCBIndex=pBase2->usNewer;
686 }
687 }
688
689 /*
690 no available sectors and at least one pending requestlist
691 lets wait for at least one requestlist to finish
692 */
693 if(usCBIndex==0xFFFF&&usRQInUse)
694 {
695 USHORTusInUse=usRQInUse;
696 if(f32Parms.fMessageActive&LOG_CACHE||
697 f32Parms.fMessageActive&LOG_WAIT)
698 Message("All Sectors Dirty, waiting for a requestlist for finish (%u pending flush)",f32Parms.usPendingFlush);
699
700 usWaitCount++;
701 _disable();
702 while(usRQInUse==usInUse)
703 {
704 DevHelp_ProcBlock((ULONG)GetRequestList,1000L,1);
705 _disable();
706 }
707 _enable();
708 usWaitCount--;
709
710 if(f32Parms.fMessageActive&LOG_CACHE||
711 f32Parms.fMessageActive&LOG_WAIT)
712 Message("Done waiting, still %u lists in use",usRQInUse);
713
714 gotofStoreRetry;
715 }
716
717 if(usCBIndex==0xFFFF)
718 {
719 /*
720 No non-dirty sector was found, thus:
721 find oldest not locked, not pending entry
722 */
723 usCBIndex=usOldestEntry;
724 usCount=0;
725 while(usCBIndex!=0xFFFF)
726 {
727 pBase=pCacheBase+usCBIndex;
728 if(pBase->fLocked)
729 usCount++;
730 if(!pBase->fLocked)
731 {
732 LockBuffer(pBase);
733 break;
734 }
735 pBase2=pCacheBase2+usCBIndex;
736 usCBIndex=pBase2->usNewer;
737 }
738 }
739
740 if(usCBIndex==0xFFFF)
741 {
742 BOOLfMsg=f32Parms.fMessageActive;
743 CritMessage("FAT32:No free sectors in cache! (run MONITOR now!)");
744 Message("ERROR: fStoreSector - No sectors available!");
745 Message(" %u sectors are locked",usCount);
746 Message(" %u sectors are pending flush",f32Parms.usPendingFlush);
747 Message(" %u sectors are dirty",f32Parms.usDirtySectors);
748 f32Parms.fMessageActive=fMsg;
749 Yield();
750 gotofStoreRetry;
751 }
752
753 /*
754 Write old entry if needed
755 */
756
757 if(rgfDirty[usCBIndex])
758 {
759 if(f32Parms.fMessageActive&LOG_CACHE||
760 f32Parms.fMessageActive&LOG_WAIT)
761 Message("fStoreSector: PROBLEM: Oldest is dirty! (%u, %u)",
762 f32Parms.usDirtySectors,f32Parms.usPendingFlush);
763 WriteCacheSector(NULL,usCBIndex,TRUE);
764 }
765
766 /*
767 Remove entry from slot chain
768 */
769
770 usSlot=(USHORT)(pBase->ulSector%MAX_SLOTS);
771 usIndex=rgSlot[usSlot];
772 if(usIndex==usCBIndex)
773 rgSlot[usSlot]=pBase->usNext;
774 else
775 {
776 pWork=NULL;
777 while(usIndex!=FREE_SLOT)
778 {
779 pWork=pCacheBase+usIndex;
780 if(pWork->usNext==usCBIndex)
781 break;
782 usIndex=pWork->usNext;
783 }
784 if(usIndex==FREE_SLOT)
785 FatalMessage("FAT32: Store: Oldest entry not found in slot chain!");
786 pWork->usNext=pBase->usNext;
787 }
788
789 usSlot=(USHORT)(ulSector%MAX_SLOTS);
790 pBase->usNext=rgSlot[usSlot];
791 rgSlot[usSlot]=usCBIndex;
792
793 pBase->ulSector=ulSector;
794 pBase->bDrive=pVolInfo->bDrive;
795 vReplaceSectorInCache(usCBIndex,pbSector,fDirty);
796 UnlockBuffer(pBase);
797 }
798
799 returnTRUE;
800 }
801
802 /******************************************************************
803 *
804 ******************************************************************/
805 VOIDvReplaceSectorInCache(USHORTusCBIndex,PBYTEpbSector,BOOLfDirty)
806 {
807 PCACHEBASEpBase;
808 PCACHEpCache;
809 #ifdef WAIT_THRESHOLD
810 USHORTusCount;
811 #endif
812
813 pBase=pCacheBase+usCBIndex;
814
815 if(!rgfDirty[usCBIndex]&&fDirty)
816 {
817 f32Parms.usDirtySectors++;
818 pBase->ulCreateTime=GetCurTime();
819 }
820 elseif(rgfDirty[usCBIndex]&&!fDirty)
821 {
822 f32Parms.usDirtySectors--;
823 #ifdef WAIT_THRESHOLD
824 DevHelp_ProcRun((ULONG)&f32Parms.usDirtySectors,&usCount);
825 #endif
826 }
827 rgfDirty[usCBIndex]=fDirty;
828 pCache=GetAddress(usCBIndex);
829 memcpy(pCache->bSector,pbSector,SECTOR_SIZE);
830 pBase->ulAccessTime=GetCurTime();
831 UpdateChain(usCBIndex);
832 return;
833 }
834 /******************************************************************
835 *
836 ******************************************************************/
837 PVOIDGetAddress(ULONGulEntry)
838 {
839 ULONGulOffset;
840 USHORTusSel;
841
842 ulOffset=ulEntry*sizeof(CACHE);
843 usSel=(USHORT)(ulOffset/0x10000);
844
845 ulOffset=ulOffset%0x10000;
846
847 return(PVOID)MAKEP(rgCacheSel[usSel],(USHORT)ulOffset);
848 }
849
850 /******************************************************************
851 *
852 ******************************************************************/
853 PVOIDGetPhysAddr(PRQLISTpRQ,ULONGulEntry)
854 {
855 ULONGulOffset;
856 USHORTusEntry;
857
858 ulOffset=ulEntry*sizeof(CACHE);
859 usEntry=(USHORT)(ulOffset/PAGE_SIZE);
860
861 ulOffset=ulOffset%PAGE_SIZE;
862
863 return(PVOID)(pRQ->rgPhys[usEntry]+ulOffset);
864 }
865
866 /******************************************************************
867 *
868 ******************************************************************/
869 BOOLfFindSector(ULONGulSector,BYTEbDrive,PUSHORTpusIndex)
870 {
871 PCACHEBASEpBase;
872 USHORTusCBIndex;
873
874 if(!f32Parms.usCacheUsed)
875 returnFALSE;
876
877 usCBIndex=rgSlot[(USHORT)(ulSector%MAX_SLOTS)];
878 while(usCBIndex!=FREE_SLOT)
879 {
880 pBase=pCacheBase+usCBIndex;
881 if(pBase->ulSector==ulSector&&pBase->bDrive==bDrive)
882 {
883 LockBuffer(pBase);
884 if(pBase->ulSector==ulSector&&pBase->bDrive==bDrive)
885 {
886 *pusIndex=usCBIndex;
887 returnTRUE;
888 }
889 UnlockBuffer(pBase);
890 usCBIndex=rgSlot[(USHORT)(ulSector%MAX_SLOTS)];
891 continue;
892 }
893 usCBIndex=pBase->usNext;
894 }
895 returnFALSE;
896 }
897
898
899 /******************************************************************
900 *
901 ******************************************************************/
902 USHORTWriteCacheSector(PVOLINFOpVolInfo,USHORTusCBIndex,BOOLfSetTime)
903 {
904 staticBOOLfLocked=FALSE;
905 staticBYTEbSector[512]="";
906 PCACHEBASEpBase;
907 USHORTrc;
908 USHORTusSectors;
909 USHORTusCount;
910 PCACHEpCache;
911
912 pBase=pCacheBase+usCBIndex;
913 if(!rgfDirty[usCBIndex])
914 {
915 if(pBase->fDiscard)
916 {
917 pBase->bDrive=0xFF;
918 pBase->fDiscard=OFF;
919 }
920
921 return0;
922 }
923
924 if(!pVolInfo)
925 pVolInfo=pGlobVolInfo;
926
927 while(pVolInfo)
928 {
929 if(pVolInfo->bDrive==(BYTE)pBase->bDrive)
930 {
931 pCache=GetAddress(usCBIndex);
932 usSectors=1;
933 usWaitCount++;
934
935 _disable();
936 while(fLocked)
937 {
938 if(f32Parms.fMessageActive&LOG_WAIT)
939 Message("Waiting for WriteCacheSector!");
940 DevHelp_ProcBlock((ULONG)WriteCacheSector,1000,1);
941 _disable();
942 }
943 _enable();
944
945 usWaitCount--;
946 fLocked=TRUE;
947
948 memcpy(bSector,pCache->bSector,512);
949 rc=FSH_DOVOLIO(DVIO_OPWRITE,DVIO_ALLACK,
950 pVolInfo->hVBP,bSector,&usSectors,pBase->ulSector);
951
952 fLocked=FALSE;
953 DevHelp_ProcRun((ULONG)WriteCacheSector,&usCount);
954
955 if(!rc||rc==ERROR_WRITE_PROTECT)
956 {
957 if(pBase->fDiscard)
958 {
959 pBase->bDrive=0xFF;
960 pBase->fDiscard=OFF;
961 }
962
963 rgfDirty[usCBIndex]=FALSE;
964 f32Parms.usDirtySectors--;
965 #ifdef WAIT_THRESHOLD
966 DevHelp_ProcRun((ULONG)&f32Parms.usDirtySectors,&usCount);
967 #endif
968
969 if(fSetTime)
970 pVolInfo->ulLastDiskTime=GetCurTime();
971 }
972 else
973 CritMessage("FAT32: Error %u in WriteCacheSector",rc);
974 returnrc;
975 }
976 pVolInfo=(PVOLINFO)pVolInfo->pNextVolInfo;
977 }
978
979 FatalMessage("FAT32: WriteCacheSector: VOLINFO not found!");
980 return1;
981 }
982
983
984 /******************************************************************
985 *
986 ******************************************************************/
987 VOIDDoEmergencyFlush(PLWOPTSpOptions)
988 {
989 #if 0
990 USHORT usIndex;
991 #endif
992 USHORTrc;
993
994 while(!f32Parms.fInShutDown&&!pOptions->fTerminate)
995 {
996 _disable();
997 rc=WAIT_TIMED_OUT;
998 while(!f32Parms.fInShutDown&&!pOptions->fTerminate&&
999 rc==WAIT_TIMED_OUT)
1000 /* f32Parms.usDirtySectors - f32Parms.usPendingFlush <= f32Parms.usDirtyTreshold */
1001 {
1002 rc=DevHelp_ProcBlock((ULONG)DoEmergencyFlush,5000L,1);
1003 _disable();
1004 }
1005 _enable();
1006 if(f32Parms.fInShutDown||pOptions->fTerminate)
1007 break;
1008 #if 0
1009 for (usIndex = 0; usIndex < usRQCount; usIndex++)
1010 {
1011 if (!rgRQ[usIndex].fBusy)
1012 break;
1013 }
1014 if (usIndex == usRQCount)
1015 continue;
1016 #endif
1017
1018 usEmergencyFlush();
1019 FSH_IOBOOST();
1020 }
1021 }
1022
1023 /******************************************************************
1024 *
1025 ******************************************************************/
1026 USHORTusFlushAll(VOID)
1027 {
1028 PVOLINFOpVolInfo=pGlobVolInfo;
1029 USHORTrc;
1030
1031 while(pVolInfo)
1032 {
1033 rc=usFlushVolume(pVolInfo,FLUSH_DISCARD,TRUE,PRIO_URGENT);
1034 pVolInfo=(PVOLINFO)pVolInfo->pNextVolInfo;
1035 }
1036 return0;
1037 }
1038
1039 /******************************************************************
1040 *
1041 ******************************************************************/
1042 VOIDDoLW(PVOLINFOpVolInfo,PLWOPTSpOptions)
1043 {
1044 BYTEbPriority;
1045 LONGlWait;
1046
1047 Message("DoLW started");
1048
1049 lWait=f32Parms.ulDiskIdle;
1050 _disable();
1051 while(!f32Parms.fInShutDown&&!pOptions->fTerminate)
1052 {
1053 DevHelp_ProcBlock((ULONG)DoLW,lWait,1);
1054 Yield();
1055 if((f32Parms.usDirtySectors==f32Parms.usPendingFlush)||usWaitCount)
1056 {
1057 lWait=f32Parms.ulDiskIdle;
1058 _disable();
1059 continue;
1060 }
1061 lWait=5;
1062
1063 if(f32Parms.fLW)
1064 {
1065 switch(pOptions->bLWPrio)
1066 {
1067 case1:
1068 bPriority=PRIO_LAZY_WRITE;
1069 break;
1070
1071 case2:
1072 bPriority=PRIO_BACKGROUND_USER;
1073 break;
1074
1075 case3:
1076 bPriority=PRIO_FOREGROUND_USER;
1077 break;
1078
1079 default:
1080 bPriority=PRIO_PAGER_HIGH;
1081 break;
1082 }
1083
1084 pVolInfo=pGlobVolInfo;
1085 while(pVolInfo)
1086 {
1087 ULONGulTime=GetCurTime();
1088
1089 if(ulTime<pVolInfo->ulLastDiskTime||
1090 pVolInfo->ulLastDiskTime+f32Parms.ulDiskIdle<=ulTime)
1091
1092 usFlushVolume(pVolInfo,FLUSH_RETAIN,FALSE,bPriority);
1093 pVolInfo=(PVOLINFO)pVolInfo->pNextVolInfo;
1094 }
1095 }
1096 _disable();
1097 }
1098 _enable();
1099
1100 f32Parms.fLW=FALSE;
1101 usFlushAll();
1102 Message("DoLW Stopped, Lazy writing also");
1103 }
1104
1105 #if 0
1106 #define WAIT_PENDINGFLUSH
1107 #endif
1108
1109 /******************************************************************
1110 *
1111 ******************************************************************/
1112 USHORTusFlushVolume(PVOLINFOpVolInfo,USHORTusFlag,BOOLfFlushAll,BYTEbPriority)
1113 {
1114 USHORTusCBIndex=0;
1115 PCACHEBASEpBase;
1116 PCACHEBASE2pBase2;
1117 USHORTusCount;
1118 ULONGulCurTime=GetCurTime();
1119 PRQLISTpRQ;
1120
1121 if(!f32Parms.usCacheUsed)
1122 return0;
1123
1124 if(usFlag==FLUSH_DISCARD)
1125 {
1126 /* Wait to flush pending dirty sectors completely */
1127 #ifndef WAIT_PENDINGFLUSH
1128 _disable();
1129 while(usRQInUse)
1130 {
1131 DevHelp_ProcBlock((ULONG)GetRequestList,1000L,1);
1132 _disable();
1133 }
1134 _enable();
1135 #else
1136 _disable();
1137 while(f32Parms.usPendingFlush)
1138 {
1139 DevHelp_ProcBlock((ULONG)&f32Parms.usPendingFlush,1000L,1);
1140 _disable();
1141 }
1142 _enable();
1143 #endif
1144 }
1145 elseif(f32Parms.usDirtySectors==f32Parms.usPendingFlush)
1146 return0;
1147
1148 usCount=0;
1149
1150 if(!fFlushAll)
1151 {
1152 pRQ=NULL;
1153 usCBIndex=usOldestEntry;
1154 while(usCBIndex!=0xFFFF&&!usWaitCount)
1155 {
1156 if(pRQ&&pRQ->rlh.Count>=MAXRQENTRIES)
1157 break;
1158
1159 pBase2=pCacheBase2+usCBIndex;
1160 pBase=pCacheBase+usCBIndex;
1161
1162 if(pBase->bDrive==pVolInfo->bDrive&&
1163 (ulCurTime-pBase->ulCreateTime>=f32Parms.ulMaxAge||
1164 ulCurTime-pBase->ulAccessTime>=f32Parms.ulBufferIdle))
1165 {
1166 if(rgfDirty[usCBIndex])
1167 {
1168 if(!pBase->fLocked&&!pBase->fFlushPending)
1169 {
1170 if(!pRQ)
1171 pRQ=GetRequestList(pVolInfo,TRUE);
1172
1173 LockBuffer(pBase);
1174 if(usFlag==FLUSH_DISCARD)
1175 pBase->fDiscard=SET;
1176 if(!pRQ||!fAddToRLH(pRQ,usCBIndex,bPriority))
1177 {
1178 WriteCacheSector(pVolInfo,usCBIndex,FALSE);
1179 UnlockBuffer(pBase);
1180 }
1181 usCount++;
1182 }
1183 }
1184 elseif(usFlag==FLUSH_DISCARD)
1185 {
1186 LockBuffer(pBase);
1187 pBase->bDrive=0xFF;
1188 pBase->fDiscard=OFF;
1189 UnlockBuffer(pBase);
1190 }
1191 }
1192
1193 usCBIndex=pBase2->usNewer;
1194 }
1195 if(f32Parms.fMessageActive&LOG_CACHE&&usCount>0)
1196 Message("%u sectors LAZY flushed, still %u dirty",usCount,f32Parms.usDirtySectors);
1197
1198 if(pRQ)
1199 vCallStrategy(pVolInfo,pRQ);
1200 return0;
1201 }
1202
1203 if(f32Parms.fMessageActive&LOG_CACHE)
1204 Message("usFlushVolume ALL");
1205
1206 pRQ=GetRequestList(pVolInfo,TRUE);
1207 usCBIndex=0;
1208 for(usCBIndex=0;(f32Parms.usDirtySectors||usFlag==FLUSH_DISCARD)&&
1209 usCBIndex<f32Parms.usCacheUsed;usCBIndex++)
1210 {
1211 pBase=pCacheBase+usCBIndex;
1212 if(pVolInfo->bDrive==(BYTE)pBase->bDrive)
1213 {
1214 if(rgfDirty[usCBIndex])
1215 {
1216 if(pRQ&&pRQ->rlh.Count>=MAXRQENTRIES)
1217 {
1218 vCallStrategy(pVolInfo,pRQ);
1219 pRQ=GetRequestList(pVolInfo,TRUE);
1220 }
1221
1222 LockBuffer(pBase);
1223 if(usFlag==FLUSH_DISCARD)
1224 pBase->fDiscard=SET;
1225 if(!pRQ||!fAddToRLH(pRQ,usCBIndex,PRIO_URGENT))
1226 {
1227 WriteCacheSector(pVolInfo,usCBIndex,FALSE);
1228 UnlockBuffer(pBase);
1229 }
1230 usCount++;
1231 }
1232 elseif(usFlag==FLUSH_DISCARD)
1233 {
1234 LockBuffer(pBase);
1235 pBase->bDrive=0xFF;
1236 pBase->fDiscard=OFF;
1237 UnlockBuffer(pBase);
1238 }
1239 }
1240 }
1241 vCallStrategy(pVolInfo,pRQ);
1242
1243 if(f32Parms.fMessageActive&LOG_CACHE)
1244 Message("%u sectors flushed, still %u dirty",usCount,f32Parms.usDirtySectors);
1245 return0;
1246 }
1247
1248 /******************************************************************
1249 *
1250 ******************************************************************/
1251 USHORTusEmergencyFlush(VOID)
1252 {
1253 USHORTusCBIndex=0;
1254 PCACHEBASEpBase;
1255 PCACHEBASE2pBase2;
1256 USHORTusCount;
1257 PVOLINFOpVolInfo;
1258 PRQLISTpRQ;
1259
1260 if(!f32Parms.usCacheUsed||(f32Parms.usDirtySectors==f32Parms.usPendingFlush))
1261 return0;
1262
1263 /*
1264 find the volinfo for the oldest entry
1265 */
1266 pVolInfo=NULL;
1267 usCBIndex=usOldestEntry;
1268 while(usCBIndex!=0xFFFF)
1269 {
1270 pBase2=pCacheBase2+usCBIndex;
1271 pBase=pCacheBase+usCBIndex;
1272 if(rgfDirty[usCBIndex]&&!pBase->fFlushPending)
1273 {
1274 pVolInfo=pGlobVolInfo;
1275 while(pVolInfo)
1276 {
1277 if((BYTE)pBase->bDrive==pVolInfo->bDrive)
1278 break;
1279 pVolInfo=(PVOLINFO)(pVolInfo->pNextVolInfo);
1280 }
1281 if(!pVolInfo)
1282 FatalMessage("FAT32: Drive not found in emergency flush!");
1283 break;
1284 }
1285 usCBIndex=pBase2->usNewer;
1286 }
1287
1288 if(usCBIndex==0xFFFF)
1289 return0;
1290
1291 if(!pVolInfo)
1292 return0;
1293
1294 pRQ=GetRequestList(pVolInfo,TRUE);
1295 if(!pRQ)
1296 return0;
1297
1298 usCount=0;
1299 while(usCBIndex!=0xFFFF&&usCount<MAXRQENTRIES)
1300 {
1301 pBase2=pCacheBase2+usCBIndex;
1302 pBase=pCacheBase+usCBIndex;
1303 if(rgfDirty[usCBIndex]&&
1304 pVolInfo->bDrive==(BYTE)pBase->bDrive&&
1305 !pBase->fLocked&&!pBase->fFlushPending)
1306 {
1307 LockBuffer(pBase);
1308 fAddToRLH(pRQ,usCBIndex,PRIO_URGENT);
1309 usCount++;
1310 }
1311 usCBIndex=pBase2->usNewer;
1312 }
1313
1314 pVolInfo->ulLastDiskTime=GetCurTime();
1315
1316 if(f32Parms.fMessageActive&LOG_CACHE)
1317 Message("usEmergencyFlush: %u sectors flushed, still %u dirty",usCount,f32Parms.usDirtySectors);
1318
1319 vCallStrategy(pVolInfo,pRQ);
1320
1321 return0;
1322 }
1323
1324 /******************************************************************
1325 *
1326 ******************************************************************/
1327 VOIDLockBuffer(PCACHEBASEpBase)
1328 {
1329 _disable();
1330 usWaitCount++;
1331 while(pBase->fLocked)
1332 {
1333 if(f32Parms.fMessageActive&LOG_WAIT)
1334 Message("Waiting on locked buffer...");
1335 DevHelp_ProcBlock((ULONG)pBase,1000,1);
1336 _disable();
1337 if(!pBase->fLocked&&f32Parms.fMessageActive&LOG_WAIT)
1338 Message("Continuing after wait for locked buffer");
1339 }
1340 usWaitCount--;
1341 pBase->fLocked=SET;
1342 _enable();
1343 }
1344
1345 /******************************************************************
1346 *
1347 ******************************************************************/
1348 VOIDUnlockBuffer(PCACHEBASEpBase)
1349 {
1350 USHORTusCount;
1351
1352 pBase->fLocked=OFF;
1353 DevHelp_ProcRun((ULONG)pBase,&usCount);
1354 }
1355
1356 /******************************************************************
1357 *
1358 ******************************************************************/
1359 PRQLISTGetRequestList(PVOLINFOpVolInfo,BOOLfWait)
1360 {
1361 PRQLISTpRQ;
1362 USHORTusIndex;
1363
1364 if(!pVolInfo->pfnStrategy)
1365 returnNULL;
1366
1367 pRQ=NULL;
1368
1369 usWaitCount++;
1370 _disable();
1371 while(!pRQ)
1372 {
1373 for(usIndex=0;usIndex<usRQCount;usIndex++)
1374 {
1375 if(!rgRQ[usIndex].fBusy)
1376 {
1377 pRQ=&rgRQ[usIndex];
1378 pRQ->usNr=usIndex;
1379 break;
1380 }
1381 }
1382
1383 if(!pRQ)
1384 {
1385 if(fWait)
1386 {
1387 if(f32Parms.fMessageActive&LOG_WAIT)
1388 Message("Waiting for a requestlist to become available");
1389 DevHelp_ProcBlock((ULONG)GetRequestList,1000L,1);
1390 _disable();
1391 }
1392 else
1393 {
1394 _enable();
1395 if(f32Parms.fMessageActive&LOG_CACHE)
1396 Message("No RQ Buffers free!");
1397 returnNULL;
1398 }
1399 }
1400 }
1401 _enable();
1402 usWaitCount--;
1403
1404 memset(&pRQ->rlh,0,sizeofpRQ->rlh);
1405 memset(pRQ->rgReq,0,sizeofpRQ->rgReq);
1406 pRQ->fBusy=TRUE;
1407 usRQInUse++;
1408 pRQ->rlh.Count=0;
1409 pRQ->rlh.Notify_Address=(PVOID)rlhNotify;
1410 pRQ->rlh.Request_Control=RLH_Notify_Done;
1411 pRQ->rlh.Block_Dev_Unit=pVolInfo->bUnit;
1412 returnpRQ;
1413 }
1414
1415 /******************************************************************
1416 *
1417 ******************************************************************/
1418 BOOLfAddToRLH(PRQLISTpRQin,USHORTusCBIndex,BYTEbPriority)
1419 {
1420 _segmentrqBase;
1421 RQLIST_based(rqBase)*pRQ;
1422 RLH_based(rqBase)*pRLH;
1423 PB_based(rqBase)*pPB;
1424 SG_based(rqBase)*pSG;
1425 PCACHEBASEpBase;
1426 USHORTusEntry;
1427 PBYTEpTar;
1428 PCACHEpCache;
1429
1430 if(!pRQin||pRQin->rlh.Count>=MAXRQENTRIES)
1431 returnFALSE;
1432 rqBase=SELECTOROF(pRQin);
1433 pRQ=(RQLIST_based(rqBase)*)OFFSETOF(pRQin);
1434
1435 pBase=pCacheBase+usCBIndex;
1436
1437 #ifdef SORT_RLH
1438 for(usEntry=0;usEntry<(USHORT)pRQ->rlh.Count;usEntry++)
1439 {
1440 pPB=&pRQ->rgReq[usEntry].pb;
1441 if(pBase->ulSector<pPB->Start_Block)
1442 break;
1443 }
1444 if(usEntry<(USHORT)pRQ->rlh.Count)
1445 {
1446 memmove(&pRQ->rgReq[usEntry+1],
1447 &pRQ->rgReq[usEntry],
1448 ((USHORT)pRQ->rlh.Count-usEntry)*sizeof(REQUEST));
1449 }
1450 #else
1451 usEntry=(USHORT)pRQ->rlh.Count;
1452 #endif
1453
1454 pRLH=&pRQ->rlh;
1455 pPB=&pRQ->rgReq[usEntry].pb;
1456 pSG=&pRQ->rgReq[usEntry].sg;
1457
1458 pRQ->rgReq[usEntry].usCBIndex=usCBIndex;
1459
1460 pPB->RqHdr.Length=RH_LAST_REQ;
1461 pPB->RqHdr.Old_Command=PB_REQ_LIST;
1462 pPB->RqHdr.Command_Code=PB_WRITE_X;
1463 pPB->RqHdr.Head_Offset=0;
1464 /* pPB->RqHdr.Req_Control = RH_NOTIFY_ERROR | RH_NOTIFY_DONE; */
1465 pPB->RqHdr.Req_Control=RH_NOTIFY_ERROR;
1466 pPB->RqHdr.Priority=bPriority;
1467 pPB->RqHdr.Status=RH_NOT_QUEUED;
1468 pPB->RqHdr.Error_Code=0;
1469 pPB->RqHdr.Notify_Address=(PVOID)rhNotify;
1470 pPB->RqHdr.Hint_Pointer=0xFFFFFFFF;
1471
1472 pPB->Start_Block=pBase->ulSector;
1473 pPB->Block_Count=1;
1474 pPB->Blocks_Xferred=0;
1475 pPB->RW_Flags=RW_Cache_Req;
1476 pPB->SG_Desc_Count=1;
1477
1478 pSG->BufferPtr=GetPhysAddr(pRQ,pRQ->rlh.Count);
1479 pSG->BufferSize=SECTOR_SIZE;
1480
1481 pTar=MAKEP(pRQ->Sel,usEntry*SECTOR_SIZE);
1482 pCache=GetAddress(usCBIndex);
1483 memcpy(pTar,pCache->bSector,SECTOR_SIZE);
1484
1485 /*
1486 rgfDirty[usCBIndex] = FALSE;
1487 f32Parms.usDirtySectors--;
1488 */
1489
1490 pBase->fFlushPending=SET;
1491 f32Parms.usPendingFlush++;
1492
1493 UnlockBuffer(pBase);
1494
1495 pRQ->rlh.Count++;
1496
1497 returnTRUE;
1498 }
1499
1500 #pragma optimize("g", off)
1501 /******************************************************************
1502 *
1503 ******************************************************************/
1504 VOIDvCallStrategy(PVOLINFOpVolInfo,PRQLISTpRQin)
1505 {
1506 STRATFUNCpfnStrategy;
1507 USHORTusSeg;
1508 USHORTusOff;
1509 ULONGulIndex;
1510
1511 _segmentrqBase;
1512 RQLIST_based(rqBase)*pRQ;
1513 RLH_based(rqBase)*pRLH;
1514 PB_based(rqBase)*pPB;
1515
1516 if(!pRQin)
1517 return;
1518
1519 rqBase=SELECTOROF(pRQin);
1520 pRQ=(RQLIST_based(rqBase)*)OFFSETOF(pRQin);
1521
1522 if(f32Parms.fMessageActive&LOG_CACHE&&pRQ->rlh.Count)
1523 Message("vCallStrategy drive %c:, %lu sectors, RQ %u",
1524 pRQ->rlh.Block_Dev_Unit+'A',
1525 pRQ->rlh.Count,
1526 pRQ->usNr);
1527
1528 if(!pRQ->rlh.Count)
1529 {
1530 USHORTusCount;
1531
1532 pRQ->fBusy=FALSE;
1533 usRQInUse--;
1534 DevHelp_ProcRun((ULONG)GetRequestList,&usCount);
1535 return;
1536 }
1537
1538 pRLH=&pRQ->rlh;
1539 if(pRQ->rlh.Count==1)
1540 pRQ->rlh.Lst_Status|=RLH_Single_Req;
1541
1542
1543 for(ulIndex=0;ulIndex<pRQ->rlh.Count;ulIndex++)
1544 {
1545 pPB=&pRQ->rgReq[ulIndex].pb;
1546
1547 if(ulIndex+1<pRQ->rlh.Count)
1548 pPB->RqHdr.Length=sizeof(REQUEST);
1549 pPB->RqHdr.Head_Offset=(USHORT)pPB-(USHORT)pRLH;
1550 }
1551
1552 usSeg=rqBase;
1553 usOff=(USHORT)pRQ+offsetof(RQLIST,rlh);
1554
1555 pfnStrategy=pVolInfo->pfnStrategy;
1556 _asmmoves,usSeg;
1557 _asmmovbx,usOff;
1558 (*pfnStrategy)();
1559 }
1560
1561 /******************************************************************
1562 *
1563 ******************************************************************/
1564 VOIDrlhNotify(VOID)
1565 {
1566 PRQLISTpRQ;
1567 USHORTusCount;
1568 WORDESReg,BXReg;
1569 INTiStatus,iErrorStatus;
1570 ULONGulIndex;
1571 PREQUESTpRequest;
1572
1573
1574 _asmmovESReg,es
1575 _asmmovBXReg,bx
1576
1577 pRQ=MAKEP(ESReg,BXReg-offsetof(RQLIST,rlh));
1578
1579 iStatus=pRQ->rlh.Lst_Status&0x0F;
1580 iErrorStatus=pRQ->rlh.Lst_Status&0xF0;
1581
1582 if(iStatus==RLH_All_Req_Done)
1583 {
1584 switch(iErrorStatus)
1585 {
1586 caseRLH_No_Error:
1587 caseRLH_Rec_Error:
1588 pRequest=pRQ->rgReq;
1589 for(ulIndex=0;ulIndex<pRQ->rlh.Count;ulIndex++)
1590 {
1591 PCACHEBASEpBase=pCacheBase+pRequest->usCBIndex;
1592
1593 if(pRequest->pb.RqHdr.Status&0x0F!=RH_DONE)
1594 FatalMessage("FAT32: rlhNotify received with not all sectors being done!");
1595
1596 if(pBase->ulSector==pRequest->pb.Start_Block)
1597 {
1598 if(rgfDirty[pRequest->usCBIndex])
1599 {
1600 if(pBase->fDiscard)
1601 {
1602 pBase->bDrive=0xFF;
1603 pBase->fDiscard=OFF;
1604 }
1605
1606 rgfDirty[pRequest->usCBIndex]=FALSE;
1607 f32Parms.usDirtySectors--;
1608 #ifdef WAIT_THRESHOLD
1609 DevHelp_ProcRun((ULONG)&f32Parms.usDirtySectors,&usCount);
1610 #endif
1611 }
1612 if(pBase->fFlushPending)
1613 {
1614 f32Parms.usPendingFlush--;
1615 #ifdef WAIT_PENDINGFLUSH
1616 DevHelp_ProcRun((ULONG)&f32Parms.usPendingFlush,&usCount);
1617 #endif
1618 pBase->fFlushPending=OFF;
1619 }
1620 }
1621 pRequest++;
1622 }
1623 break;
1624
1625 default:
1626 CritMessage("FAT32: Fatal WRITE Error %X in rlhNotify!",iErrorStatus);
1627 break;
1628 }
1629
1630 pRQ->fBusy=FALSE;
1631 usRQInUse--;
1632 DevHelp_ProcRun((ULONG)GetRequestList,&usCount);
1633 return;
1634 }
1635
1636 switch(iErrorStatus)
1637 {
1638 caseRLH_No_Error:
1639 caseRLH_Rec_Error:
1640 return;
1641
1642 default:
1643 CritMessage("FAT32: Fatal WRITE Error %X in rlhNotify!",iErrorStatus);
1644 pRQ->fBusy=FALSE;
1645 usRQInUse--;
1646 DevHelp_ProcRun((ULONG)GetRequestList,&usCount);
1647 break;
1648 }
1649
1650 return;
1651 }
1652
1653
1654 /******************************************************************
1655 *
1656 ******************************************************************/
1657 VOIDrhNotify(VOID)
1658 {
1659 WORDESReg,BXReg;
1660
1661 _asmmovESReg,es
1662 _asmmovBXReg,bx
1663
1664 vCheckRequest(MAKEP(ESReg,BXReg));
1665 }
1666 #pragma optimize("", on)
1667
1668 /******************************************************************
1669 *
1670 ******************************************************************/
1671 VOIDvCheckRequest(PREQUESTpRequest)
1672 {
1673 PCACHEBASEpBase;
1674 INTstatus;
1675 INTerr_status;
1676 INTerr_code;
1677 #ifdef WAIT_THRESHOLD
1678 USHORTusCount;
1679 #endif
1680
1681 if(pRequest->usCBIndex>f32Parms.usCacheUsed)
1682 InternalError("FAT32: usCBIndex is wrong in vCheckRequest!");
1683
1684 pBase=pCacheBase+pRequest->usCBIndex;
1685
1686 if(pBase->ulSector!=pRequest->pb.Start_Block)
1687 {
1688 CritMessage("FAT32: Sectors do not match in rhNotify!");
1689 return;
1690 }
1691
1692 status=pRequest->pb.RqHdr.Status&0x0F;
1693 err_status=pRequest->pb.RqHdr.Status&0xF0;
1694 err_code=pRequest->pb.RqHdr.Error_Code;
1695
1696 if(status==RH_DONE)
1697 {
1698 switch(err_status)
1699 {
1700 caseRH_NO_ERROR:
1701 caseRH_RECOV_ERROR:
1702 if(pBase->fDiscard)
1703 {
1704 pBase->bDrive=0xFF;
1705 pBase->fDiscard=OFF;
1706 }
1707
1708 rgfDirty[pRequest->usCBIndex]=FALSE;
1709 f32Parms.usDirtySectors--;
1710 #ifdef WAIT_THRESHOLD
1711 DevHelp_ProcRun((ULONG)&f32Parms.usDirtySectors,&usCount);
1712 #endif
1713 break;
1714 default:
1715 CritMessage("FAT32: Error %X in rhNotify!",err_code);
1716 break;
1717 }
1718
1719 if(pBase->fFlushPending)
1720 {
1721 f32Parms.usPendingFlush--;
1722 #ifdef WAIT_PENDINGFLUSH
1723 DevHelp_ProcRun((ULONG)&f32Parms.usPendingFlush,&usCount);
1724 #endif
1725 pBase->fFlushPending=OFF;
1726 }
1727 return;
1728 }
1729
1730 switch(err_status)
1731 {
1732 /*
1733 In this case we should be notified later of the real status of the request.
1734 */
1735 caseRH_NO_ERROR:
1736 caseRH_RECOV_ERROR:
1737 return;
1738 /*
1739 In this case there is no more chance ...
1740 */
1741 default:
1742 if(pBase->fFlushPending)
1743 {
1744 f32Parms.usPendingFlush--;
1745 #ifdef WAIT_PENDINGFLUSH
1746 DevHelp_ProcRun((ULONG)&f32Parms.usPendingFlush,&usCount);
1747 #endif
1748 pBase->fFlushPending=OFF;
1749 }
1750
1751 CritMessage("FAT32: Error %X in rhNotify!",err_code);
1752 break;
1753 }
1754 return;
1755 }
Note: See TracBrowser for help on using the repository browser.

AltStyle によって変換されたページ (->オリジナル) /