fix for corrupted graphics when manipulating config files
[open-ps2-loader.git] / modules / ps2fs / cache.c
blob11e7b55fd5fe5a2d197c1880cd02f1126efe4437
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
10 # $Id: cache.c 911 2005-03-14 21:02:17Z oopo $
11 # PFS metadata cache manipulation routines
14 #include "pfs.h"
16 pfs_cache_t *cacheBuf;
17 u32 numBuffers;
20 void cacheAdd(pfs_cache_t *clink)
22 if(clink==NULL) {
23 printf("ps2fs: Warning: NULL buffer returned\n");
24 return;
27 if(clink->nused==0){
28 printf("ps2fs: Error: Unused cache returned\n");
29 return;
32 clink->nused--;
33 if(clink->pfsMount!=NULL) {
34 if(clink->nused!=0)
35 return;
36 cacheLink(cacheBuf->prev, clink);
37 return;
39 if(clink->nused!=0) {
40 printf("ps2fs: Warning: Invalidated buffer is in use\n");
41 return;
43 cacheLink(cacheBuf, clink);
46 void cacheLink(pfs_cache_t *clink, pfs_cache_t *cnew)
48 cnew->prev=clink;
49 cnew->next=clink->next;
50 clink->next->prev=cnew;
51 clink->next=cnew;
54 pfs_cache_t *cacheUnLink(pfs_cache_t *clink)
56 clink->prev->next=clink->next;
57 clink->next->prev=clink->prev;
58 return clink;
61 pfs_cache_t *cacheUsedAdd(pfs_cache_t *clink)
63 clink->nused++;
64 return clink;
67 int cacheTransfer(pfs_cache_t* clink, int mode)
69 pfs_mount_t *pfsMount=clink->pfsMount;
70 int err;
72 if(pfsMount->lastError == 0) { // no error
73 if((err=pfsMount->blockDev->transfer(pfsMount->fd, clink->u.inode, clink->sub,
74 clink->sector << blockSize, 1 << blockSize, mode))==0) {
75 if(mode==IOCTL2_TMODE_READ) {
76 if(clink->flags & CACHE_FLAG_SEGD && ((pfs_inode *)clink->u.inode)->magic!=PFS_SEGD_MAGIC)
77 err=-EIO;
78 if(clink->flags & CACHE_FLAG_SEGI && ((pfs_inode *)clink->u.inode)->magic!=PFS_SEGI_MAGIC)
79 err=-EIO;
80 if(clink->flags & (CACHE_FLAG_SEGD|CACHE_FLAG_SEGI)) {
81 if(((pfs_inode *)clink->u.inode)->checksum!=inodeCheckSum(clink->u.inode))
82 err=-EIO;
86 if(err!=0) {
87 printf("ps2fs: Error: Disk error partition %ld, block %ld, err %d\n",
88 clink->sub, clink->sector, err);
89 pfsMount->blockDev->setPartitionError(pfsMount->fd);
90 fsckStat(pfsMount, clink->u.superblock, FSCK_STAT_WRITE_ERROR, MODE_SET_FLAG);
91 pfsMount->lastError=err;
94 clink->flags&=~CACHE_FLAG_DIRTY; // clear dirty :)
95 return pfsMount->lastError;
98 void cacheFlushAllDirty(pfs_mount_t *pfsMount)
100 u32 i;
101 int found=0;
103 for(i=1;i<numBuffers+1;i++){
104 if(cacheBuf[i].pfsMount == pfsMount &&
105 cacheBuf[i].flags & CACHE_FLAG_DIRTY)
106 found=1;
108 if(found) {
109 journalWrite(pfsMount, cacheBuf+1, numBuffers);
110 for(i=1;i<numBuffers+1;i++){
111 if(cacheBuf[i].pfsMount == pfsMount &&
112 cacheBuf[i].flags & CACHE_FLAG_DIRTY)
113 cacheTransfer(&cacheBuf[i], 1);
115 journalReset(pfsMount);
119 pfs_cache_t *cacheAlloc(pfs_mount_t *pfsMount, u16 sub, u32 scale,
120 int flags, int *result)
122 pfs_cache_t *allocated;
124 if (cacheBuf->prev==cacheBuf && cacheBuf->prev->next==cacheBuf->prev) {
125 printf("ps2fs: Error: Free buffer list is empty\n");
126 *result=-ENOMEM;
127 return NULL;
129 allocated=cacheBuf->next;
130 if (cacheBuf->next==NULL)
131 printf("ps2fs: Panic: Null pointer allocated\n");
132 if (allocated->pfsMount && (allocated->flags & CACHE_FLAG_DIRTY))
133 cacheFlushAllDirty(allocated->pfsMount);
134 allocated->flags = flags & CACHE_FLAG_MASKTYPE;
135 allocated->pfsMount = pfsMount;
136 allocated->sub = sub;
137 allocated->sector = scale;
138 allocated->nused = 1;
139 return cacheUnLink(allocated);
143 pfs_cache_t *cacheGetData(pfs_mount_t *pfsMount, u16 sub, u32 sector,
144 int flags, int *result)
146 u32 i;
147 pfs_cache_t *clink;
149 *result=0;
151 for (i=1; i < numBuffers + 1; i++)
152 if ( cacheBuf[i].pfsMount &&
153 (cacheBuf[i].pfsMount==pfsMount) &&
154 (cacheBuf[i].sector == sector))
155 if (cacheBuf[i].sub==sub){
156 cacheBuf[i].flags &= CACHE_FLAG_MASKSTATUS;
157 cacheBuf[i].flags |= flags & CACHE_FLAG_MASKTYPE;
158 if (cacheBuf[i].nused == 0)
159 cacheUnLink(&cacheBuf[i]);
160 cacheBuf[i].nused++;
161 return &cacheBuf[i];
164 clink=cacheAlloc(pfsMount, sub, sector, flags, result);
166 if (clink){
167 if (flags & CACHE_FLAG_NOLOAD)
168 return clink;
170 if ((*result=cacheTransfer(clink, IOCTL2_TMODE_READ))>=0)
171 return clink;
173 clink->pfsMount=NULL;
174 cacheAdd(clink);
176 return NULL;
179 pfs_cache_t *cacheAllocClean(int *result)
181 *result = 0;
182 return cacheAlloc(NULL, 0, 0, 0, result);
185 // checks if the cacheBuf list has some room
186 int cacheIsFull()
188 if (cacheBuf->prev != cacheBuf) return 0;
189 return cacheBuf->prev->next == cacheBuf->prev;
192 int cacheInit(u32 numBuf, u32 bufSize)
194 char *cacheData;
195 u32 i;
197 if(numBuf > 127) {
198 printf("ps2fs: Error: Number of buffers larger than 127.\n");
199 return -EINVAL;
202 cacheData = allocMem(numBuf * bufSize);
204 if(!cacheData || !(cacheBuf = allocMem((numBuf + 1) * sizeof(pfs_cache_t))))
205 return -ENOMEM;
207 numBuffers = numBuf;
208 memset(cacheBuf, 0, (numBuf + 1) * sizeof(pfs_cache_t));
210 cacheBuf->next = cacheBuf;
211 cacheBuf->prev = cacheBuf;
213 for(i = 1; i < numBuf + 1; i++)
215 cacheBuf[i].u.data = cacheData;
216 cacheLink(cacheBuf->prev, &cacheBuf[i]);
217 cacheData += bufSize;
220 return 0;
223 void cacheMarkClean(pfs_mount_t *pfsMount, u32 subpart, u32 sectorStart, u32 sectorEnd)
225 u32 i;
227 for(i=1; i< numBuffers+1;i++){
228 if(cacheBuf[i].pfsMount==pfsMount && cacheBuf[i].sub==subpart) {
229 if(cacheBuf[i].sector >= sectorStart && cacheBuf[i].sector < sectorEnd)
230 cacheBuf[i].flags&=~CACHE_FLAG_DIRTY;