PS2SDK
PS2 Homebrew Libraries
hdd_blkio.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 <iomanX.h>
12 
13 #include <libapa.h>
14 #include "hdd.h"
15 #include "hdd_blkio.h"
16 
17 #ifdef APA_USE_BDM
18 
19 #ifdef _IOP
20 #include <sysclib.h>
21 #else
22 #include <string.h>
23 #endif
24 #include <thbase.h>
25 #include <thsemap.h>
26 
27 #include <bdm.h>
28 
29 typedef struct hdd_blkio_fs_driver_mount_info_
30 {
31  struct block_device *mounted_bd;
32 } hdd_blkio_fs_driver_mount_info;
33 
34 extern apa_device_t hddDevices[]; // defined in hdd.c
35 static hdd_blkio_fs_driver_mount_info fs_driver_mount_info[BLKIO_MAX_VOLUMES];
36 
37 #define HDD_BLKIO_FS_DRIVER_MOUNT_INFO_MAX ((int)(sizeof(fs_driver_mount_info) / sizeof(fs_driver_mount_info[0])))
38 
39 static int _fs_lock_sema_id = -1;
40 
41 static int _fs_init_lock(void)
42 {
43  iop_sema_t sp;
44 
45  sp.initial = 1;
46  sp.max = 1;
47  sp.option = 0;
48  sp.attr = 0;
49  if ((_fs_lock_sema_id = CreateSema(&sp)) < 0) {
50  return (-1);
51  }
52 
53  return (0);
54 }
55 
56 static void _fs_lock(void)
57 {
58  WaitSema(_fs_lock_sema_id);
59 }
60 
61 static void _fs_unlock(void)
62 {
63  SignalSema(_fs_lock_sema_id);
64 }
65 
66 static void fs_reset(void)
67 {
68  if (_fs_lock_sema_id >= 0)
69  DeleteSema(_fs_lock_sema_id);
70 
71  _fs_init_lock();
72 }
73 
74 static void hdd_blkio_fs_driver_initialize_all_mount_info(void)
75 {
76  int i;
77  for (i = 0; i < HDD_BLKIO_FS_DRIVER_MOUNT_INFO_MAX; i += 1) {
78  fs_driver_mount_info[i].mounted_bd = NULL;
79  }
80 }
81 
82 static int hdd_blkio_fs_driver_find_mount_info_index_from_block_device(const struct block_device *bd)
83 {
84  int i;
85  for (i = 0; i < HDD_BLKIO_FS_DRIVER_MOUNT_INFO_MAX; i += 1) {
86  if (fs_driver_mount_info[i].mounted_bd == bd) {
87  return i;
88  }
89  }
90  return -1;
91 }
92 
93 static int hdd_blkio_fs_driver_find_mount_info_index_free(void)
94 {
95  return hdd_blkio_fs_driver_find_mount_info_index_from_block_device(NULL);
96 }
97 
98 static struct block_device *hdd_blkio_fs_driver_get_mounted_bd_from_index(int mount_info_index)
99 {
100  struct block_device *mounted_bd;
101  if (mount_info_index >= HDD_BLKIO_FS_DRIVER_MOUNT_INFO_MAX) {
102  return NULL;
103  }
104  mounted_bd = fs_driver_mount_info[mount_info_index].mounted_bd;
105  return mounted_bd;
106 }
107 
108 static int hdd_blkio_fs_driver_mount_bd(int mount_info_index, struct block_device *bd)
109 {
110  fs_driver_mount_info[mount_info_index].mounted_bd = bd;
111  hddDevices[mount_info_index].status = 3;
112  // 512 sector size only supported
113  if (bd->sectorSize != 512)
114  {
115  fs_driver_mount_info[mount_info_index].mounted_bd = NULL;
116  return -1;
117  }
118  hddDevices[mount_info_index].status -= 1; // assume drive exists
119  hddDevices[mount_info_index].totalLBA = bd->sectorCount;
120  hddDevices[mount_info_index].partitionMaxSize = apaGetPartitionMax(hddDevices[mount_info_index].totalLBA);
121  hddDevices[mount_info_index].status -= 1; // assume drive unlocked
122  if (apaJournalRestore(mount_info_index) != 0)
123  {
124  fs_driver_mount_info[mount_info_index].mounted_bd = NULL;
125  return -1;
126  }
127  // Check if drive is formatted in APA
128  if (apaGetFormat(mount_info_index, &hddDevices[mount_info_index].format) != 0)
129  {
130  hddDevices[mount_info_index].status -= 1;
131  }
132  if (hddDevices[mount_info_index].status != 0)
133  {
134  fs_driver_mount_info[mount_info_index].mounted_bd = NULL;
135  return -1;
136  }
137  return 0;
138 }
139 
140 static void hdd_blkio_fs_driver_unmount_bd(int mount_info_index)
141 {
142  fs_driver_mount_info[mount_info_index].mounted_bd = NULL;
143  hddDevices[mount_info_index].status = 3;
144 }
145 
146 static int hdd_blkio_connect_bd(struct block_device *bd)
147 {
148  int mount_info_index;
149 
150  _fs_lock();
151  mount_info_index = hdd_blkio_fs_driver_find_mount_info_index_free();
152  if (mount_info_index != -1) {
153  if (hdd_blkio_fs_driver_mount_bd(mount_info_index, bd) == 0) {
154  _fs_unlock();
155  return 0;
156  }
157  }
158  _fs_unlock();
159  return -1;
160 }
161 
162 static void hdd_blkio_disconnect_bd(struct block_device *bd)
163 {
164  int mount_info_index;
165 
166  _fs_lock();
167  mount_info_index = hdd_blkio_fs_driver_find_mount_info_index_from_block_device(bd);
168  if (mount_info_index != -1) {
169  hdd_blkio_fs_driver_unmount_bd(mount_info_index);
170  }
171  _fs_unlock();
172 }
173 
174 static struct file_system g_fs = {
175  .priv = NULL,
176  .name = "ps2hdd",
177  .connect_bd = hdd_blkio_connect_bd,
178  .disconnect_bd = hdd_blkio_disconnect_bd,
179 };
180 #endif
181 
182 #ifdef APA_USE_IOMANX
183 
184 #ifdef _IOP
185 #include <sysclib.h>
186 #else
187 #include <string.h>
188 #endif
189 #include <errno.h>
190 
191 typedef struct vhdd_diskinfo_
192 {
193  int fd;
194  int sectorcount;
195 } vhdd_diskinfo_t;
196 
197 extern apa_device_t hddDevices[]; // defined in hdd.c
198 static vhdd_diskinfo_t hdd_blkio_vhdd_diskinfo[BLKIO_MAX_VOLUMES];
199 
200 static void hdd_blkio_vhdd_clear_slot(int slot)
201 {
202  vhdd_diskinfo_t *diskinfo;
203  diskinfo = &hdd_blkio_vhdd_diskinfo[slot];
204  if (diskinfo->fd >= 0) {
205  iomanX_close(diskinfo->fd);
206  }
207  memset(diskinfo, 0, sizeof(vhdd_diskinfo_t));
208  diskinfo->fd = -1;
209 }
210 
211 static int hdd_blkio_vhdd_validate(int slot, int check_mounted)
212 {
213  vhdd_diskinfo_t *diskinfo;
214 
215  if (slot > BLKIO_MAX_VOLUMES) {
216  return -EOVERFLOW;
217  }
218 
219  diskinfo = &hdd_blkio_vhdd_diskinfo[slot];
220 
221  if (check_mounted) {
222  if (diskinfo->fd < 0) {
223  return -ENXIO;
224  }
225  }
226  return 0;
227 }
228 
229 int hdd_blkio_vhdd_mount(int slot, const char *filename)
230 {
231  int fd;
232  s64 disksize;
233  int r;
234  vhdd_diskinfo_t *diskinfo;
235 
236  r = hdd_blkio_vhdd_validate(slot, 0);
237  if (r < 0) {
238  goto cleanup;
239  }
240 
241  diskinfo = &hdd_blkio_vhdd_diskinfo[slot];
242 
243  fd = iomanX_open(filename, FIO_O_RDWR, 0);
244  if (fd < 0) {
245  // Propogate open error
246  r = fd;
247  goto cleanup;
248  }
249  diskinfo->fd = fd;
250 
251  disksize = iomanX_lseek64(fd, 0, FIO_SEEK_END);
252  diskinfo->sectorcount = disksize >> 9; // divide by 512
253  iomanX_lseek64(fd, 0, FIO_SEEK_SET);
254 
255  // Check if image is formatted
256  {
257  hddDevices[slot].status = 3;
258  hddDevices[slot].status -= 1; // assume drive exists
259  hddDevices[slot].totalLBA = diskinfo->sectorcount;
260  hddDevices[slot].partitionMaxSize = apaGetPartitionMax(hddDevices[slot].totalLBA);
261  hddDevices[slot].status -= 1; // assume drive unlocked
262  if (apaJournalRestore(slot) != 0)
263  {
264  r = -EIO;
265  goto cleanup;
266  }
267  // Check if drive is formatted in APA
268  if (apaGetFormat(slot, &hddDevices[slot].format) != 0)
269  {
270  hddDevices[slot].status -= 1;
271  }
272  if (hddDevices[slot].status != 0)
273  {
274  r = -EIO;
275  goto cleanup;
276  }
277  r = 0; // Success
278  }
279 cleanup:
280  if (r < 0) {
281  hdd_blkio_vhdd_clear_slot(slot);
282  }
283  return r;
284 }
285 
286 int hdd_blkio_vhdd_umount(int slot)
287 {
288  int r;
289 
290  r = hdd_blkio_vhdd_validate(slot, 1);
291  if (r < 0) {
292  goto cleanup;
293  }
294 
295  hdd_blkio_vhdd_clear_slot(slot);
296 
297 cleanup:
298  return r;
299 }
300 #endif
301 
302 #ifndef APA_USE_ATAD
303 int blkIoInit(void)
304 {
305 #ifdef APA_USE_BDM
306  fs_reset();
307  hdd_blkio_fs_driver_initialize_all_mount_info();
308  bdm_connect_fs(&g_fs);
309 #endif
310  return 0;
311 }
312 
313 int blkIoDmaTransfer(int device, void *buf, u32 lba, u32 nsectors, int dir)
314 {
315 #ifdef APA_USE_BDM
316  struct block_device *mounted_bd;
317 
318  mounted_bd = hdd_blkio_fs_driver_get_mounted_bd_from_index(device);
319 
320  if (mounted_bd == NULL)
321  {
322  return -1;
323  }
324 
325  if (dir == BLKIO_DIR_READ)
326  {
327  return (mounted_bd->read(mounted_bd, lba, buf, nsectors) == nsectors) ? 0 : -1;
328  }
329  else if (dir == BLKIO_DIR_WRITE)
330  {
331  return (mounted_bd->write(mounted_bd, lba, buf, nsectors) == nsectors) ? 0 : -1;
332  }
333 #elif defined(APA_USE_IOMANX)
334  {
335  int r;
336  vhdd_diskinfo_t *diskinfo;
337 
338  r = hdd_blkio_vhdd_validate(device, 1);
339  if (r < 0) {
340  return -1;
341  }
342  diskinfo = &hdd_blkio_vhdd_diskinfo[device];
343 
344  if (buf != NULL) {
345  int sector_to_byte_count;
346  sector_to_byte_count = nsectors * 512;
347  iomanX_lseek64(diskinfo->fd, (s64)lba * (s64)512, FIO_SEEK_SET);
348  if (dir == BLKIO_DIR_READ)
349  {
350  return (iomanX_read(diskinfo->fd, buf, sector_to_byte_count) == sector_to_byte_count) ? 0 : -1;
351  }
352  else if (dir == BLKIO_DIR_WRITE)
353  {
354  return (iomanX_write(diskinfo->fd, buf, sector_to_byte_count) == sector_to_byte_count) ? 0 : -1;
355  }
356  }
357  }
358 #else
359  (void)device;
360  (void)buf;
361  (void)lba;
362  (void)nsectors;
363  (void)dir;
364 #endif
365  return -1;
366 }
367 
368 int blkIoIdle(int device, int period)
369 {
370  (void)device;
371  (void)period;
372  return 0;
373 }
374 
375 int blkIoGetSceId(int device, void *data)
376 {
377  (void)device;
378  (void)data;
379  return 0;
380 }
381 
382 int blkIoSmartReturnStatus(int device)
383 {
384  (void)device;
385  return 0;
386 }
387 
388 int blkIoSmartSaveAttr(int device)
389 {
390 #ifdef APA_USE_BDM
391  struct block_device *mounted_bd;
392 
393  mounted_bd = hdd_blkio_fs_driver_get_mounted_bd_from_index(device);
394 
395  if (mounted_bd == NULL)
396  {
397  return 0;
398  }
399 
400  mounted_bd->stop(mounted_bd);
401 #else
402  (void)device;
403 #endif
404  return 0;
405 }
406 
407 int blkIoFlushCache(int device)
408 {
409 #ifdef APA_USE_BDM
410  struct block_device *mounted_bd;
411 
412  mounted_bd = hdd_blkio_fs_driver_get_mounted_bd_from_index(device);
413 
414  if (mounted_bd == NULL)
415  {
416  return 0;
417  }
418 
419  mounted_bd->flush(mounted_bd);
420 #else
421  (void)device;
422 #endif
423  return 0;
424 }
425 
426 int blkIoIdleImmediate(int device)
427 {
428  (void)device;
429  return 0;
430 }
431 #endif
iomanX.h
bdm.h
EOVERFLOW
#define EOVERFLOW
Definition: errno.h:269
thbase.h
iop_sema_t
Definition: thsemap.h:38
sysclib.h
ENXIO
#define ENXIO
Definition: errno.h:31
EIO
#define EIO
Definition: errno.h:29
thsemap.h
apa_device_t
Definition: libapa.h:209
block_device
Definition: bdm.h:21
file_system
Definition: bdm.h:50
errno.h