PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
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
29typedef struct hdd_blkio_fs_driver_mount_info_
30{
31 struct block_device *mounted_bd;
32} hdd_blkio_fs_driver_mount_info;
33
34extern apa_device_t hddDevices[]; // defined in hdd.c
35static 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
39static int _fs_lock_sema_id = -1;
40
41static 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
56static void _fs_lock(void)
57{
58 WaitSema(_fs_lock_sema_id);
59}
60
61static void _fs_unlock(void)
62{
63 SignalSema(_fs_lock_sema_id);
64}
65
66static 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
74static 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
82static 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
93static 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
98static 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
108static 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
140static 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
146static 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
162static 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
174static 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
191typedef struct vhdd_diskinfo_
192{
193 int fd;
194 int sectorcount;
195} vhdd_diskinfo_t;
196
197extern apa_device_t hddDevices[]; // defined in hdd.c
198static vhdd_diskinfo_t hdd_blkio_vhdd_diskinfo[BLKIO_MAX_VOLUMES];
199
200static 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
211static 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
229int 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 }
279cleanup:
280 if (r < 0) {
281 hdd_blkio_vhdd_clear_slot(slot);
282 }
283 return r;
284}
285
286int 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
297cleanup:
298 return r;
299}
300#endif
301
302#ifndef APA_USE_ATAD
303int 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
313int 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
368int blkIoIdle(int device, int period)
369{
370 (void)device;
371 (void)period;
372 return 0;
373}
374
375int blkIoGetSceId(int device, void *data)
376{
377 (void)device;
378 (void)data;
379 return 0;
380}
381
382int blkIoSmartReturnStatus(int device)
383{
384 (void)device;
385 return 0;
386}
387
388int 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
407int 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
426int blkIoIdleImmediate(int device)
427{
428 (void)device;
429 return 0;
430}
431#endif
#define ENXIO
Definition errno.h:31
#define EIO
Definition errno.h:29
#define EOVERFLOW
Definition errno.h:269