PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
cache.c
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.
9#
10# APA cache manipulation routines
11*/
12
13#include <errno.h>
14#include <iomanX.h>
15#ifdef _IOP
16#include <sysclib.h>
17#else
18#include <string.h>
19#endif
20#include <stdio.h>
21#include <hdd-ioctl.h>
22
23#include "libapa.h"
24
25// Globals
26static apa_cache_t *cacheBuf;
27static int cacheSize;
28
29int apaCacheInit(u32 size)
30{
31 apa_header_t *header;
32 unsigned int i;
33
34 cacheSize=size; // save size ;)
35 if((header=(apa_header_t *)apaAllocMem(size*sizeof(apa_header_t)))){
36 cacheBuf=apaAllocMem((size+1)*sizeof(apa_cache_t));
37 if(cacheBuf==NULL)
38 return -ENOMEM;
39 }
40 else
41 return -ENOMEM;
42 // setup cache header...
43 memset(cacheBuf, 0, (size+1)*sizeof(apa_cache_t));
44 cacheBuf->next=cacheBuf;
45 cacheBuf->tail=cacheBuf;
46 for(i=1; i<size+1;i++, header++){
47 cacheBuf[i].header=header;
48 cacheBuf[i].device=-1;
49 apaCacheLink(cacheBuf->tail, &cacheBuf[i]);
50 }
51 return 0;
52}
53
54int apaCacheDeinit(void)
55{
56#if 0
57 unsigned int i;
58
59 for(i=1; i<cacheSize+1;i++){
60 // !!! This code performs multiple frees
61 apaFreeMem(cacheBuf[i].header);
62 }
63#else
64 // Unofficial: Free once at the head of the list
65 if (cacheSize > 1)
66 {
67 apaFreeMem(cacheBuf[1].header);
68 }
69#endif
70 apaFreeMem(cacheBuf);
71 return 0;
72}
73
74void apaCacheLink(apa_cache_t *clink, apa_cache_t *cnew)
75{
76 cnew->tail=clink;
77 cnew->next=clink->next;
78 clink->next->tail=cnew;
79 clink->next=cnew;
80}
81
82apa_cache_t *apaCacheUnLink(apa_cache_t *clink)
83{
84 clink->tail->next=clink->next;
85 clink->next->tail=clink->tail;
86 return clink;
87}
88
89int apaCacheTransfer(apa_cache_t *clink, int type)
90{
91 int err;
92 if(type)
93 err=apaWriteHeader(clink->device, clink->header, clink->sector);
94 else// 0
95 err=apaReadHeader(clink->device, clink->header, clink->sector);
96
97 if(err)
98 {
99 APA_PRINTF(APA_DRV_NAME": error: disk err %d on device %ld, sector %ld, type %d\n",
100 err, clink->device, clink->sector, type);
101 if(type==0)// save any read error's..
102 apaSaveError(clink->device, clink->header, APA_SECTOR_SECTOR_ERROR, clink->sector);
103 }
104 clink->flags&=~APA_CACHE_FLAG_DIRTY;
105 return err;
106}
107
108void apaCacheFlushDirty(apa_cache_t *clink)
109{
110 if(clink->flags&APA_CACHE_FLAG_DIRTY)
111 apaCacheTransfer(clink, APA_IO_MODE_WRITE);
112}
113
114int apaCacheFlushAllDirty(s32 device)
115{
116 int i;
117 // flush apal
118 for(i=1;i<cacheSize+1;i++){
119 if((cacheBuf[i].flags & APA_CACHE_FLAG_DIRTY) && cacheBuf[i].device==device)
120 apaJournalWrite(&cacheBuf[i]);
121 }
122 apaJournalFlush(device);
123 // flush apa
124 for(i=1;i<cacheSize+1;i++){
125 if((cacheBuf[i].flags & APA_CACHE_FLAG_DIRTY) && cacheBuf[i].device==device)
126 apaCacheTransfer(&cacheBuf[i], APA_IO_MODE_WRITE);
127 }
128 return apaJournalReset(device);
129}
130
131apa_cache_t *apaCacheGetHeader(s32 device, u32 sector, u32 mode, int *result)
132{
133 apa_cache_t *clink=NULL;
134 int i;
135
136 *result=0;
137 for(i=1;i<cacheSize+1;i++){
138 if(cacheBuf[i].sector==sector &&
139 cacheBuf[i].device==device){
140 clink=&cacheBuf[i];
141 break;
142 }
143 }
144 if(clink!=NULL) {
145 // cached ver was found :)
146 if(clink->nused==0)
147 clink=apaCacheUnLink(clink);
148 clink->nused++;
149 return clink;
150 }
151 if((cacheBuf->tail==cacheBuf) &&
152 (cacheBuf->tail==cacheBuf->tail->next)){
153 APA_PRINTF(APA_DRV_NAME": error: free buffer empty\n");
154 }
155 else
156 {
157 clink=cacheBuf->next;
158 if(clink->flags & APA_CACHE_FLAG_DIRTY)
159 APA_PRINTF(APA_DRV_NAME": error: dirty buffer allocated\n");
160 clink->flags=0;
161 clink->nused=1;
162 clink->device=device;
163 clink->sector=sector;
164 clink=apaCacheUnLink(clink);
165 }
166 if(clink==NULL)
167 {
168 *result=-ENOMEM;
169 return NULL;
170 }
171 if(!mode)
172 {
173 if((*result=apaCacheTransfer(clink, APA_IO_MODE_READ))<0){
174 clink->nused=0;
175 clink->device=-1;
176 apaCacheLink(cacheBuf, clink);
177 clink=NULL;
178 }
179 }
180 return clink;
181}
182
183void apaCacheFree(apa_cache_t *clink)
184{
185 if(clink==NULL){
186 APA_PRINTF(APA_DRV_NAME": error: null buffer returned\n");
187 return;
188 }
189 if(clink->nused==0){
190 APA_PRINTF(APA_DRV_NAME": error: unused cache returned\n");
191 return;
192 }
193 if(clink->flags & APA_CACHE_FLAG_DIRTY)
194 APA_PRINTF(APA_DRV_NAME": error: dirty buffer returned\n");
195 clink->nused--;
196 if(clink->nused==0)
197 apaCacheLink(cacheBuf->tail, clink);
198 return;
199}
200
201apa_cache_t *apaCacheAlloc(void)
202{
203 apa_cache_t *cnext;
204
205 if((cacheBuf->tail==cacheBuf) &&
206 (cacheBuf->tail==cacheBuf->tail->next)){
207 APA_PRINTF(APA_DRV_NAME": error: free buffer empty\n");
208 return NULL;
209 }
210 cnext=cacheBuf->next;
211 if(cnext->flags & APA_CACHE_FLAG_DIRTY)
212 APA_PRINTF(APA_DRV_NAME": error: dirty buffer allocated\n");
213 cnext->nused=1;
214 cnext->flags=0;
215 cnext->device=-1;
216 cnext->sector=-1;
217 return apaCacheUnLink(cnext);
218}
#define ENOMEM
Definition errno.h:43