mgh: fix for default HDD DMA mode, that wasn't correctly set
[open-ps2-loader.git] / modules / usb / usbhdfsd / scache.c
blob04d32ff7f875f5e1df8300aac4632d2a685fa2bd
1 //---------------------------------------------------------------------------
2 //File name: scache.c
3 //---------------------------------------------------------------------------
4 /*
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)
10 * Sector cache
12 * See the file LICENSE included with this distribution for licensing terms.
14 //---------------------------------------------------------------------------
15 #include <stdio.h>
17 #ifdef WIN32
18 #include <malloc.h>
19 #include <memory.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #else
23 #include <tamtypes.h>
24 #include <sysmem.h>
25 #define malloc(a) AllocSysMemory(0,(a), NULL)
26 #define free(a) FreeSysMemory((a))
27 #endif
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)
43 #ifdef LIGHT_MEM
44 #define CACHE_SIZE 6
45 #else
46 #ifdef INGAME_DRIVER
47 #define CACHE_SIZE 16
48 #else
49 #define CACHE_SIZE 32
50 #endif
51 #endif
53 //when the flushCounter reaches FLUSH_TRIGGER then flushSectors is called
54 //#define FLUSH_TRIGGER 16
56 typedef struct _cache_record
58 unsigned int sector;
59 int tax;
60 char writeDirty;
61 } cache_record;
63 struct _cache_set
65 mass_dev* dev;
66 int sectorSize;
67 int indexLimit;
68 unsigned char* sectorBuf; // = NULL; //sector content - the cache buffer
69 cache_record rec[CACHE_SIZE]; //cache info record
71 //statistical infos
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)
83 int i;
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;
92 cache->writeFlag = 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) {
101 int i;
103 for (i = 0; i < CACHE_SIZE; i++) {
104 if (sector >= cache->rec[i].sector && sector < (cache->rec[i].sector + cache->indexLimit)) {
105 return i;
108 return -1;
112 //---------------------------------------------------------------------------
113 /* search cache records for the sector number stored in cache */
114 int getIndexRead(cache_set* cache, unsigned int sector) {
115 int i;
116 int index =-1;
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;
122 index = i;
124 cache->rec[i].tax--; //apply tax penalty
126 if (index < 0)
127 return index;
128 else
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) {
135 int i;
136 int minTax = 0x0FFFFFFF;
137 int index = 0;
139 for (i = 0; i < CACHE_SIZE; i++) {
140 if (cache->rec[i].tax < minTax) {
141 index = i;
142 minTax = cache->rec[i].tax;
146 #ifdef WRITE_SUPPORT
147 int ret;
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
154 if (ret < 0) {
155 printf("scache: ERROR writing sector to disk! sector=%d\n", sector);
159 #endif
161 cache->rec[index].tax +=2;
162 cache->rec[index].sector = sector;
164 return index * cache->indexLimit;
169 //---------------------------------------------------------------------------
171 flush dirty sectors
173 int scache_flushSectors(cache_set* cache) {
174 int counter = 0;
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) {
183 return 0;
186 #ifdef WRITE_SUPPORT
187 int i,ret;
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
194 if (ret < 0) {
195 printf("scache: ERROR writing sector to disk! sector=%d\n", cache->rec[i].sector);
196 return ret;
198 counter ++;
201 #endif
203 cache->writeFlag = 0;
204 return counter;
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
210 int ret;
211 unsigned int alignedSector;
213 XPRINTF("cache: readSector devId = %i %X sector = %i \n", cache->dev->devId, (int) cache, sector);
214 if (cache == NULL) {
215 printf("cache: devId cache not created = %i \n", cache->dev->devId);
216 return -1;
219 cache->cacheAccess ++;
220 index = getIndexRead(cache, sector);
221 XPRINTF("cache: indexRead=%i \n", index);
222 if (index >= 0) { //sector found in cache
223 cache->cacheHits ++;
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);
236 if (ret < 0) {
237 printf("scache: ERROR reading sector from disk! sector=%d\n", alignedSector);
238 return ret;
240 *buf = cache->sectorBuf + (index * cache->sectorSize) + ((sector%cache->indexLimit) * cache->sectorSize);
241 XPRINTF("cache: done reading physical sector \n");
243 //write precaution
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
256 //int ret;
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
282 //int ret;
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");
289 return -1;
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;
296 //set dirty status
297 cache->rec[index].writeDirty = 1;
298 cache->writeFlag++;
300 XPRINTF("cache: done soft writing sector \n");
302 //write precaution
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)
314 cache_set* cache;
315 XPRINTF("cache: init devId = %i sectSize = %i \n", dev->devId, sectSize);
317 cache = malloc(sizeof(cache_set));
318 if (cache == NULL) {
319 printf("scache init! Sector cache: can't alloate cache!\n");
320 return NULL;
323 XPRINTF("scache init! \n");
324 cache->dev = dev;
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);
330 free(cache);
331 return NULL;
333 XPRINTF("Sector cache: allocated memory at:%p of size:%d \n", cache->sectorBuf, BLOCK_SIZE * CACHE_SIZE);
335 //added by Hermes
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;
340 initRecords(cache);
341 return cache;
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;
359 free(cache);
361 //---------------------------------------------------------------------------
362 void scache_close(cache_set* cache)
364 XPRINTF("cache: close devId = %i \n", cache->dev->devId);
365 scache_flushSectors(cache);
366 scache_kill(cache);
368 //---------------------------------------------------------------------------
369 //End of file: scache.c
370 //---------------------------------------------------------------------------