PS2SDK
PS2 Homebrew Libraries
sim.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 
11 #include <stdio.h>
12 #include <sysclib.h>
13 #include <hdd-ioctl.h>
14 
15 #include "libapa.h"
16 #include "hdsk-devctl.h"
17 #include "hdsk.h"
18 #include "sim.h"
19 
20 extern u32 TotalCopied;
21 extern struct hdskBitmap hdskBitmap[];
22 
23 void hdskSimGetFreeSectors(s32 device, struct hdskStat *stat, apa_device_t *deviceinfo)
24 {
25  u32 sectors, partMax;
26  int i;
27 
28  sectors = 0;
29  stat->free = 0;
30  u32 maxsize = 0x1FFFFF; // 1GB
31  u32 minsize = 0x3FFFF; // 128MB
32 #ifdef APA_8MB_PARTITION_SIZE
33  minsize = 0x3FFF; // 8MB
34 #endif
35  for (i = 0; hdskBitmap[i].next != hdskBitmap; sectors += hdskBitmap[i].length, i++) {
36  if (hdskBitmap[i].type == 0) {
37  if ((maxsize < hdskBitmap[i].length) || ((stat->free & hdskBitmap[i].length) == 0)) {
38  stat->free += hdskBitmap[i].length;
39  }
40  sectors += hdskBitmap[i].length;
41  }
42  }
43 
44  for (partMax = deviceinfo[device].partitionMaxSize; minsize < partMax; partMax = deviceinfo[device].partitionMaxSize) { // As weird as it looks, this was how it was done in the original HDD.IRX.
45  for (; minsize < partMax; partMax /= 2) {
46  // Non-SONY: Perform 64-bit arithmetic here to avoid overflows when dealing with large disks.
47  if ((sectors % partMax == 0) && ((u64)sectors + partMax < deviceinfo[device].totalLBA)) {
48  if ((maxsize < partMax) || (stat->free & partMax) == 0) {
49  stat->free += partMax;
50  }
51  sectors += partMax;
52  break;
53  }
54  }
55 
56  if (minsize >= partMax) {
57  break;
58  }
59  }
60 
61  APA_PRINTF(APA_DRV_NAME ": total = %08lx sectors, installable = %08lx sectors.\n", sectors, stat->free);
62 }
63 
64 static void hdskSimClearHeader(struct hdskBitmap *header)
65 {
66  memset(header, 0, sizeof(struct hdskBitmap));
67 }
68 
69 static struct hdskBitmap *hdskSimDeleteFixPrev(struct hdskBitmap *part)
70 {
71  struct hdskBitmap *prev;
72  u32 length;
73 
74  while (hdskBitmap[0].next != part) {
75  prev = part->prev;
76  if (prev->type == 0) {
77  length = prev->length + part->length;
78  if (prev->start % length != 0) {
79  break;
80  }
81 
82  if ((length & (length - 1)) == 0) {
83  prev->length = length;
84  hdskSimClearHeader((struct hdskBitmap *)apaCacheUnLink((apa_cache_t *)part));
85  } else {
86  break;
87  }
88  } else {
89  break;
90  }
91 
92  part = prev;
93  }
94 
95  return part;
96 }
97 
98 static struct hdskBitmap *hdskSimDeleteFixNext(struct hdskBitmap *part)
99 {
100  struct hdskBitmap *next;
101  u32 length;
102 
103  while (hdskBitmap[0].prev != part) {
104  next = part->next;
105  if (next->type == 0) {
106  length = next->length + part->length;
107  if (part->start % length != 0) {
108  break;
109  }
110 
111  if ((length & (length - 1)) == 0) {
112  part->length = length;
113  part->type = 0;
114  hdskSimClearHeader((struct hdskBitmap *)apaCacheUnLink((apa_cache_t *)part));
115  } else {
116  break;
117  }
118  } else {
119  break;
120  }
121  }
122 
123  return part;
124 }
125 
126 static void hdskSimSwapPartition(struct hdskBitmap *start)
127 {
128  u32 OrigStart, OrigLen;
129  struct hdskBitmap *part;
130 
131  part = hdskBitmap[0].prev;
132  if (start == part) {
133  do {
134  hdskSimClearHeader((struct hdskBitmap *)apaCacheUnLink((apa_cache_t *)part));
135  part = hdskBitmap[0].prev;
136  if (part == NULL) {
137  break;
138  }
139  } while (part->type != 0);
140  } else {
141  int i;
142 
143  OrigStart = start->start;
144  OrigLen = start->length;
145  for (i = 0; i < 2; i++) {
146  start = hdskSimDeleteFixNext(hdskSimDeleteFixPrev(start));
147  }
148 
149  if (start->start == OrigStart && start->length == OrigLen) {
150  start->type = 0;
151  }
152  }
153 }
154 
155 void hdskSimMovePartition(struct hdskBitmap *dest, struct hdskBitmap *start)
156 {
157  APA_PRINTF("MovePartition: %08lx to %08lx. sector count = %08lx.\n", start->start, dest->start, start->length);
158 
159  TotalCopied += start->length;
160  APA_PRINTF("swap partition start...");
161 
162  dest->type = start->type;
163  hdskSimSwapPartition(start);
164 
165  printf("done\n");
166  APA_PRINTF("MovePartition: done\n");
167 }
168 
169 struct hdskBitmap *hdskSimFindEmptyPartition(u32 size)
170 {
171  struct hdskBitmap *part;
172 
173  for (part = hdskBitmap; part->next != hdskBitmap; part = part->next) {
174  if (part->length == size && part->type == 0) {
175  APA_PRINTF("sim: found empty partition at %08lx, size %08lx.\n", part->start, part->length);
176  return part;
177  }
178  }
179 
180  return NULL;
181 }
182 
183 static int hdskCheckIfPrevPartEmpty(struct hdskBitmap *part, u32 size)
184 {
185  return ((part->prev->length == size) && (part->prev->type == 0));
186 }
187 
188 static int hdskCheckIfNextPartEmpty(struct hdskBitmap *part, u32 size)
189 {
190  return ((part->next->length == size) && (part->next->type == 0));
191 }
192 
193 struct hdskBitmap *hdskSimFindLastUsedPartition(u32 size, u32 start, int mode)
194 {
195  u32 SliceSize;
196  struct hdskBitmap *part;
197 
198  SliceSize = size * 2;
199  for (part = hdskBitmap[0].prev; start < part->start && part != hdskBitmap; part = part->prev) {
200  if (part->length == size && part->type != 0) {
201  if (mode != 0) {
202  if (part->start % SliceSize != 0) {
203  if (hdskCheckIfPrevPartEmpty(part, size) != 0) {
204  return part;
205  }
206  } else {
207  if (part == hdskBitmap[0].prev || hdskCheckIfNextPartEmpty(part, size) != 0) {
208  return part;
209  }
210  }
211  } else {
212  return part;
213  }
214  }
215  }
216 
217  return NULL;
218 }
219 
220 static int hdskCheckIsLastPart(struct hdskBitmap *part, u32 size, int mode)
221 {
222  struct hdskBitmap *CurrPart;
223  u32 PartSize;
224 
225  for (CurrPart = part, PartSize = part->length; (PartSize < size) && (CurrPart != hdskBitmap); PartSize += CurrPart->length) {
226  CurrPart = CurrPart->next;
227  if (CurrPart->type == 0) {
228  break;
229  }
230  }
231 
232  if (PartSize == size) {
233  if (mode != 0) {
234  if (part->start % (size * 2) != 0) {
235  return (hdskCheckIfPrevPartEmpty(part, size) == 0 ? 0 : 1);
236  } else {
237  return (CurrPart != hdskBitmap[0].prev ? (hdskCheckIfNextPartEmpty(CurrPart, size) != 0) : 1);
238  }
239  } else {
240  return 1;
241  }
242  }
243 
244  return 0;
245 }
246 
247 struct hdskBitmap *hdskSimFindLastUsedBlock(u32 size, u32 start, int mode)
248 {
249  struct hdskBitmap *part;
250 
251  for (part = hdskBitmap[0].prev; start < part->start && part != hdskBitmap; part = part->prev) {
252  if ((part->start % size == 0) && (part->length < size) && (part->type != 0)) {
253  if (hdskCheckIsLastPart(part, size, mode) != 0) {
254  return part;
255  }
256  }
257  }
258 
259  return NULL;
260 }
261 
262 static struct hdskBitmap *hdskBitmapAlloc(void)
263 {
264  struct hdskBitmap *part;
265  unsigned int i;
266 
267  for (part = &hdskBitmap[1], i = 1; i < HDSK_BITMAP_SIZE; i++, part++) {
268  if (part->length == 0) {
269  return part;
270  }
271  }
272 
273  return NULL;
274 }
275 
276 static void hdskSimSplitEmptyPartition(struct hdskBitmap *part, u32 length)
277 {
278  APA_PRINTF("split empty partition.\n");
279  while (part->length != length) {
280  struct hdskBitmap *end;
281 
282  end = hdskBitmapAlloc();
283  part->length /= 2;
284  end->start = part->start + part->length;
285  end->type = 0;
286  end->length = part->length;
287  apaCacheLink((apa_cache_t *)part, (apa_cache_t *)end);
288  }
289 }
290 
291 void hdskSimMovePartitionsBlock(struct hdskBitmap *dest, struct hdskBitmap *src)
292 {
293  u32 size;
294 
295  size = dest->length;
296  APA_PRINTF("MovePartitionsBlock: %08lx to %08lx. sector count = %08lx.\n", src->start, dest->start, dest->length);
297  do {
298  hdskSimSplitEmptyPartition(dest, src->length);
299  if (src->next == hdskBitmap) {
300  break;
301  }
302 
303  hdskSimMovePartition(dest, src);
304  dest = dest->next;
305  size -= dest->length;
306  if (size == 0) {
307  break;
308  }
309 
310  src = src->next;
311  } while (dest != hdskBitmap);
312 
313  APA_PRINTF("MovePartitionsBlock: done\n");
314 }
sysclib.h
sapa_cache
Definition: libapa.h:120
hdd-ioctl.h
hdskStat
Definition: hdsk-devctl.h:25
stdio.h
hdskBitmap
Definition: fssk.h:22
apa_device_t
Definition: libapa.h:209