PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
mciomanx_backing.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright (c) 2009 jimmikaelkael
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <mcman.h>
12#include "mcman-internal.h"
13
14#if defined(BUILDING_VMCMAN)
15typedef struct vmc_cardinfo_
16{
17 int mounted;
18 int has_ecc;
19 int fd;
20 s16 pagesize;
21 u16 blocksize;
22 int cardsize;
23 u8 flags;
24} vmc_cardinfo_t;
25
26static vmc_cardinfo_t mcman_vmc_cardinfo[MCMAN_MAXSLOT];
27
28static void mcman_iomanx_backing_clear_slot(int slot)
29{
30 vmc_cardinfo_t *cardinfo;
31 cardinfo = &mcman_vmc_cardinfo[slot];
32 if (cardinfo->fd >= 0) {
33 iomanX_close(cardinfo->fd);
34 }
35 memset(cardinfo, 0, sizeof(vmc_cardinfo_t));
36 cardinfo->fd = -1;
37
38 // Just to clear any cached information
39 mcman_probePS2Card(0, slot);
40}
41
42static int mcman_iomanx_backing_validate(int slot, int check_mounted)
43{
44 vmc_cardinfo_t *cardinfo;
45
46 if (slot > MCMAN_MAXSLOT) {
47 return -EOVERFLOW;
48 }
49
50 cardinfo = &mcman_vmc_cardinfo[slot];
51
52 if (check_mounted) {
53 if (cardinfo->mounted == 0) {
54 return -ENXIO;
55 }
56 }
57 return 0;
58}
59
60int mcman_iomanx_backing_mount(int port, int slot, const char *filename)
61{
62 int fd;
63 int cardsize;
64 int r;
65 vmc_cardinfo_t *cardinfo;
66
67 (void)port;
68
69 r = mcman_iomanx_backing_validate(slot, 0);
70 if (r < 0) {
71 goto cleanup;
72 }
73
74 r = -EINVAL;
75
76 cardinfo = &mcman_vmc_cardinfo[slot];
77
78 fd = iomanX_open(filename, FIO_O_RDWR, 0);
79 if (fd < 0) {
80 // Propogate open error
81 r = fd;
82 goto cleanup;
83 }
84 cardinfo->fd = fd;
85
86 cardsize = iomanX_lseek(fd, 0, FIO_SEEK_END);
87 cardinfo->cardsize = cardsize;
88 iomanX_lseek(fd, 0, FIO_SEEK_SET);
89
90 // Check superblock for correct parameters
91 {
92 MCDevInfo superblock;
93 int read_result;
94 int total_pages;
95
96 read_result = iomanX_read(fd, &superblock, sizeof(superblock));
97 if (read_result != sizeof(superblock)) {
98 if (read_result >= 0) {
99 r = -EINVAL;
100 }
101 else {
102 r = read_result;
103 }
104 goto cleanup;
105 }
106 // Check magic
107 if (strncmp(superblock.magic, SUPERBLOCK_MAGIC, 28) != 0) {
108 r = -EINVAL;
109 goto cleanup;
110 }
111 // Check card type
112 if (superblock.cardtype != sceMcTypePS2) {
113 r = -EINVAL;
114 goto cleanup;
115 }
116 total_pages = superblock.pages_per_cluster * superblock.blocksize;
117 // Check card ECC
118 if (cardsize == ((superblock.pagesize + 0x10) * total_pages)) {
119 cardinfo->has_ecc = 1;
120 }
121 else if (cardsize == ((superblock.pagesize) * total_pages)) {
122 cardinfo->has_ecc = 0;
123 }
124 else {
125 // size is invalid
126 r = -EINVAL;
127 goto cleanup;
128 }
129 // Check page size
130 if (superblock.pagesize != 512 && superblock.pagesize != 528) {
131 // Not a tested page size
132 r = -EINVAL;
133 goto cleanup;
134 }
135
136 // Retrieve rest of info
137 cardinfo->pagesize = superblock.pagesize;
138 cardinfo->blocksize = superblock.blocksize;
139 cardinfo->flags = superblock.cardflags;
140 }
141
142 mcman_probePS2Card(port, slot);
143 if (McGetFormat(port, slot) > 0) {
144 r = 0; // Success
145 goto cleanup;
146 }
147 if (McGetFormat(port, slot) < 0) {
148 r = -EIO;
149 goto cleanup;
150 }
151
152cleanup:
153 if (r < 0) {
154 mcman_iomanx_backing_clear_slot(slot);
155 }
156 return r;
157}
158
159int mcman_iomanx_backing_umount(int port, int slot)
160{
161 int r;
162
163 (void)port;
164
165 r = mcman_iomanx_backing_validate(slot, 1);
166 if (r < 0) {
167 goto cleanup;
168 }
169
170 mcman_iomanx_backing_clear_slot(slot);
171
172cleanup:
173 return r;
174}
175
176int mcman_iomanx_backing_getcardspec(int port, int slot, s16 *pagesize, u16 *blocksize, int *cardsize, u8 *flags)
177{
178 int r;
179 vmc_cardinfo_t *cardinfo;
180
181 (void)port;
182
183 r = mcman_iomanx_backing_validate(slot, 1);
184 if (r < 0) {
185 return 1;
186 }
187
188 cardinfo = &mcman_vmc_cardinfo[slot];
189
190 if (pagesize) {
191 *pagesize = cardinfo->pagesize;
192 }
193
194 if (blocksize) {
195 *blocksize = cardinfo->blocksize;
196 }
197
198 if (cardsize) {
199 *cardsize = cardinfo->cardsize;
200 }
201
202 if (flags) {
203 *flags = cardinfo->flags;
204 }
205
206 return 0;
207}
208
209int mcman_iomanx_backing_erase(int port, int slot, int page)
210{
211 int r;
212 vmc_cardinfo_t *cardinfo;
213
214 (void)port;
215
216 r = mcman_iomanx_backing_validate(slot, 1);
217 if (r < 0) {
218 return 1;
219 }
220
221 cardinfo = &mcman_vmc_cardinfo[slot];
222
223 {
224 char buf[528];
225 int effective_page_size;
226
227 memset(buf, ((cardinfo->flags & CF_ERASE_ZEROES) != 0) ? 0x0 : 0xFF, sizeof(buf));
228 effective_page_size = (cardinfo->pagesize + (cardinfo->has_ecc ? 0x10 : 0));
229 iomanX_lseek(cardinfo->fd, page * effective_page_size, FIO_SEEK_SET);
230 iomanX_write(cardinfo->fd, buf, effective_page_size);
231 }
232
233 return 0;
234}
235
236int mcman_iomanx_backing_write(int port, int slot, int page, void *pagebuf, void *eccbuf)
237{
238 int r;
239 vmc_cardinfo_t *cardinfo;
240
241 (void)port;
242
243 r = mcman_iomanx_backing_validate(slot, 1);
244 if (r < 0) {
245 return 1;
246 }
247
248 cardinfo = &mcman_vmc_cardinfo[slot];
249
250 {
251 int effective_page_size;
252
253 effective_page_size = (cardinfo->pagesize + (cardinfo->has_ecc ? 0x10 : 0));
254 iomanX_lseek(cardinfo->fd, page * effective_page_size, FIO_SEEK_SET);
255 if (pagebuf != NULL) {
256 iomanX_write(cardinfo->fd, pagebuf, 512);
257 }
258 else {
259 iomanX_lseek(cardinfo->fd, 512, FIO_SEEK_CUR);
260 }
261
262 if (cardinfo->has_ecc) {
263 if (eccbuf != NULL) {
264 iomanX_write(cardinfo->fd, eccbuf, 16);
265 }
266 else {
267 iomanX_lseek(cardinfo->fd, 16, FIO_SEEK_CUR);
268 }
269 }
270 }
271
272 // FIXME: implement
273
274 return 0;
275}
276
277int mcman_iomanx_backing_read(int port, int slot, int page, void *pagebuf, void *eccbuf)
278{
279 int r;
280 vmc_cardinfo_t *cardinfo;
281
282 (void)port;
283
284 r = mcman_iomanx_backing_validate(slot, 1);
285 if (r < 0) {
286 return 1;
287 }
288
289 cardinfo = &mcman_vmc_cardinfo[slot];
290
291 {
292 int pagesize;
293 int effective_page_size;
294
295 pagesize = cardinfo->pagesize;
296
297 effective_page_size = (cardinfo->pagesize + (cardinfo->has_ecc ? 0x10 : 0));
298 iomanX_lseek(cardinfo->fd, page * effective_page_size, FIO_SEEK_SET);
299 if (pagebuf != NULL) {
300 iomanX_read(cardinfo->fd, pagebuf, 512);
301 }
302 else {
303 iomanX_lseek(cardinfo->fd, 512, FIO_SEEK_CUR);
304 }
305
306 if (cardinfo->has_ecc) {
307 if (eccbuf != NULL) {
308 iomanX_read(cardinfo->fd, eccbuf, 16);
309 }
310 else {
311 iomanX_lseek(cardinfo->fd, 16, FIO_SEEK_CUR);
312 }
313 } else if (pagebuf != NULL && eccbuf != NULL) {
314 int i;
315 int ecc_count;
316 u8 *p_page, *p_ecc;
317
318 // Make our own ECC
319
320 memset(eccbuf, ((cardinfo->flags & CF_ERASE_ZEROES) != 0) ? 0x0 : 0xFF, 16);
321 p_page = pagebuf;
322 p_ecc = eccbuf;
323
324 i = 0; //s1
325 do {
326 if (pagesize < 0)
327 ecc_count = (pagesize + 0x7f) >> 7;
328 else
329 ecc_count = pagesize >> 7;
330
331 if (i >= ecc_count)
332 break;
333
334 McDataChecksum(p_page, p_ecc);
335
336 p_ecc = (void *)((u8 *)p_ecc + 3);
337 p_page = (void *)((u8 *)p_page + 128);
338 i++;
339 } while (1);
340 }
341 }
342
343 return 0;
344}
345#endif
#define ENXIO
Definition errno.h:31
#define EINVAL
Definition errno.h:63
#define EIO
Definition errno.h:29
#define EOVERFLOW
Definition errno.h:269