1 //---------------------------------------------------------------------------
3 //---------------------------------------------------------------------------
5 * scache.c - USB Mass storage driver for PS2
7 * (C) 2004, Marek Olejnik (ole00@post.cz)
8 * (C) 2004 Hermes (support for sector sizes from 512 to 4096 bytes)
12 * See the file LICENSE included with this distribution for licensing terms.
14 //---------------------------------------------------------------------------
25 #define malloc(a) AllocSysMemory(0,(a), NULL)
26 #define free(a) FreeSysMemory((a))
29 #include "usbhd_common.h"
30 #include "mass_stor.h"
32 //---------------------------------------------------------------------------
33 #define READ_SECTOR mass_stor_readSector
34 #define WRITE_SECTOR mass_stor_writeSector
36 //#define DEBUG //comment out this line when not debugging
38 #include "mass_debug.h"
40 #define BLOCK_SIZE 4096
42 //number of cache slots (1 slot = block)
53 //when the flushCounter reaches FLUSH_TRIGGER then flushSectors is called
54 //#define FLUSH_TRIGGER 16
56 typedef struct _cache_record
68 unsigned char* sectorBuf
; // = NULL; //sector content - the cache buffer
69 cache_record rec
[CACHE_SIZE
]; //cache info record
72 unsigned int cacheAccess
;
73 unsigned int cacheHits
;
74 unsigned int writeFlag
;
75 //unsigned int flushCounter;
77 //unsigned int cacheDumpCounter = 0;
80 //---------------------------------------------------------------------------
81 void initRecords(cache_set
* cache
)
85 for (i
= 0; i
< CACHE_SIZE
; i
++)
87 cache
->rec
[i
].sector
= 0xFFFFFFF0;
88 cache
->rec
[i
].tax
= 0;
89 cache
->rec
[i
].writeDirty
= 0;
93 //cache->flushCounter = 0;
96 //---------------------------------------------------------------------------
97 /* search cache records for the sector number stored in cache
98 returns cache record (slot) number
100 int getSlot(cache_set
* cache
, unsigned int sector
) {
103 for (i
= 0; i
< CACHE_SIZE
; i
++) {
104 if (sector
>= cache
->rec
[i
].sector
&& sector
< (cache
->rec
[i
].sector
+ cache
->indexLimit
)) {
112 //---------------------------------------------------------------------------
113 /* search cache records for the sector number stored in cache */
114 int getIndexRead(cache_set
* cache
, unsigned int sector
) {
118 for (i
= 0; i
< CACHE_SIZE
; i
++) {
119 if (sector
>= cache
->rec
[i
].sector
&& sector
< (cache
->rec
[i
].sector
+ cache
->indexLimit
)) {
120 if (cache
->rec
[i
].tax
< 0) cache
->rec
[i
].tax
= 0;
121 cache
->rec
[i
].tax
+=2;
124 cache
->rec
[i
].tax
--; //apply tax penalty
129 return ((index
* cache
->indexLimit
) + (sector
- cache
->rec
[index
].sector
));
132 //---------------------------------------------------------------------------
133 /* select the best record where to store new sector */
134 int getIndexWrite(cache_set
* cache
, unsigned int sector
) {
136 int minTax
= 0x0FFFFFFF;
139 for (i
= 0; i
< CACHE_SIZE
; i
++) {
140 if (cache
->rec
[i
].tax
< minTax
) {
142 minTax
= cache
->rec
[i
].tax
;
148 //this sector is dirty - we need to flush it first
149 if (cache
->rec
[index
].writeDirty
) {
150 XPRINTF("scache: getIndexWrite: sector is dirty : %d index=%d \n", cache
->rec
[index
].sector
, index
);
151 ret
= WRITE_SECTOR(cache
->dev
, cache
->rec
[index
].sector
, cache
->sectorBuf
+ (index
* BLOCK_SIZE
), BLOCK_SIZE
);
152 cache
->rec
[index
].writeDirty
= 0;
153 //TODO - error handling
155 printf("scache: ERROR writing sector to disk! sector=%d\n", sector
);
161 cache
->rec
[index
].tax
+=2;
162 cache
->rec
[index
].sector
= sector
;
164 return index
* cache
->indexLimit
;
169 //---------------------------------------------------------------------------
173 int scache_flushSectors(cache_set
* cache
) {
176 XPRINTF("cache: flushSectors devId = %i \n", cache
->dev
->devId
);
178 //cache->flushCounter = 0;
180 XPRINTF("scache: flushSectors writeFlag=%d\n", cache
->writeFlag
);
181 //no write operation occured since last flush
182 if (cache
->writeFlag
==0) {
188 for (i
= 0; i
< CACHE_SIZE
; i
++) {
189 if (cache
->rec
[i
].writeDirty
) {
190 XPRINTF("scache: flushSectors dirty index=%d sector=%d \n", i
, cache
->rec
[i
].sector
);
191 ret
= WRITE_SECTOR(cache
->dev
, cache
->rec
[i
].sector
, cache
->sectorBuf
+ (i
* BLOCK_SIZE
), BLOCK_SIZE
);
192 cache
->rec
[i
].writeDirty
= 0;
193 //TODO - error handling
195 printf("scache: ERROR writing sector to disk! sector=%d\n", cache
->rec
[i
].sector
);
203 cache
->writeFlag
= 0;
207 //---------------------------------------------------------------------------
208 int scache_readSector(cache_set
* cache
, unsigned int sector
, void** buf
) {
209 int index
; //index is given in single sectors not octal sectors
211 unsigned int alignedSector
;
213 XPRINTF("cache: readSector devId = %i %X sector = %i \n", cache
->dev
->devId
, (int) cache
, sector
);
215 printf("cache: devId cache not created = %i \n", cache
->dev
->devId
);
219 cache
->cacheAccess
++;
220 index
= getIndexRead(cache
, sector
);
221 XPRINTF("cache: indexRead=%i \n", index
);
222 if (index
>= 0) { //sector found in cache
224 *buf
= cache
->sectorBuf
+ (index
* cache
->sectorSize
);
225 XPRINTF("cache: hit and done reading sector \n");
227 return cache
->sectorSize
;
230 //compute alignedSector - to prevent storage of duplicit sectors in slots
231 alignedSector
= (sector
/cache
->indexLimit
)*cache
->indexLimit
;
232 index
= getIndexWrite(cache
, alignedSector
);
233 XPRINTF("cache: indexWrite=%i slot=%d alignedSector=%i\n", index
, index
/ cache
->indexLimit
, alignedSector
);
234 ret
= READ_SECTOR(cache
->dev
, alignedSector
, cache
->sectorBuf
+ (index
* cache
->sectorSize
), BLOCK_SIZE
);
237 printf("scache: ERROR reading sector from disk! sector=%d\n", alignedSector
);
240 *buf
= cache
->sectorBuf
+ (index
* cache
->sectorSize
) + ((sector
%cache
->indexLimit
) * cache
->sectorSize
);
241 XPRINTF("cache: done reading physical sector \n");
244 //cache->flushCounter++;
245 //if (cache->flushCounter == FLUSH_TRIGGER) {
246 //scache_flushSectors(cache);
249 return cache
->sectorSize
;
253 //---------------------------------------------------------------------------
254 int scache_allocSector(cache_set
* cache
, unsigned int sector
, void** buf
) {
255 int index
; //index is given in single sectors not octal sectors
257 unsigned int alignedSector
;
259 XPRINTF("cache: allocSector devId = %i sector = %i \n", cache
->dev
->devId
, sector
);
261 index
= getIndexRead(cache
, sector
);
262 XPRINTF("cache: indexRead=%i \n", index
);
263 if (index
>= 0) { //sector found in cache
264 *buf
= cache
->sectorBuf
+ (index
* cache
->sectorSize
);
265 XPRINTF("cache: hit and done allocating sector \n");
266 return cache
->sectorSize
;
269 //compute alignedSector - to prevent storage of duplicit sectors in slots
270 alignedSector
= (sector
/cache
->indexLimit
)*cache
->indexLimit
;
271 index
= getIndexWrite(cache
, alignedSector
);
272 XPRINTF("cache: indexWrite=%i \n", index
);
273 *buf
= cache
->sectorBuf
+ (index
* cache
->sectorSize
) + ((sector
%cache
->indexLimit
) * cache
->sectorSize
);
274 XPRINTF("cache: done allocating sector\n");
275 return cache
->sectorSize
;
279 //---------------------------------------------------------------------------
280 int scache_writeSector(cache_set
* cache
, unsigned int sector
) {
281 int index
; //index is given in single sectors not octal sectors
284 XPRINTF("cache: writeSector devId = %i sector = %i \n", cache
->dev
->devId
, sector
);
286 index
= getSlot(cache
, sector
);
287 if (index
< 0) { //sector not found in cache
288 printf("cache: writeSector: ERROR! the sector is not allocated! \n");
291 XPRINTF("cache: slotFound=%i \n", index
);
293 //prefere written sectors to stay in cache longer than read sectors
294 cache
->rec
[index
].tax
+= 2;
297 cache
->rec
[index
].writeDirty
= 1;
300 XPRINTF("cache: done soft writing sector \n");
303 //cache->flushCounter++;
304 //if (cache->flushCounter == FLUSH_TRIGGER) {
305 //scache_flushSectors(devId);
308 return cache
->sectorSize
;
311 //---------------------------------------------------------------------------
312 cache_set
* scache_init(mass_dev
* dev
, int sectSize
)
315 XPRINTF("cache: init devId = %i sectSize = %i \n", dev
->devId
, sectSize
);
317 cache
= malloc(sizeof(cache_set
));
319 printf("scache init! Sector cache: can't alloate cache!\n");
323 XPRINTF("scache init! \n");
326 XPRINTF("sectorSize: 0x%x\n", cache
->sectorSize
);
327 cache
->sectorBuf
= (unsigned char*) malloc(BLOCK_SIZE
* CACHE_SIZE
);
328 if (cache
->sectorBuf
== NULL
) {
329 printf("Sector cache: can't alloate memory of size:%d \n", BLOCK_SIZE
* CACHE_SIZE
);
333 XPRINTF("Sector cache: allocated memory at:%p of size:%d \n", cache
->sectorBuf
, BLOCK_SIZE
* CACHE_SIZE
);
336 cache
->sectorSize
= sectSize
;
337 cache
->indexLimit
= BLOCK_SIZE
/cache
->sectorSize
; //number of sectors per 1 cache slot
338 cache
->cacheAccess
= 0;
339 cache
->cacheHits
= 0;
344 //---------------------------------------------------------------------------
345 void scache_getStat(cache_set
* cache
, unsigned int* access
, unsigned int* hits
) {
346 *access
= cache
->cacheAccess
;
347 *hits
= cache
->cacheHits
;
350 //---------------------------------------------------------------------------
351 void scache_kill(cache_set
* cache
) //dlanor: added for disconnection events (flush impossible)
353 XPRINTF("cache: kill devId = %i \n", cache
->dev
->devId
);
354 if(cache
->sectorBuf
!= NULL
)
356 free(cache
->sectorBuf
);
357 cache
->sectorBuf
= NULL
;
361 //---------------------------------------------------------------------------
362 void scache_close(cache_set
* cache
)
364 XPRINTF("cache: close devId = %i \n", cache
->dev
->devId
);
365 scache_flushSectors(cache
);
368 //---------------------------------------------------------------------------
369 //End of file: scache.c
370 //---------------------------------------------------------------------------