PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
hdd.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# Start Up routines
11*/
12
13#include <stdio.h>
14#ifdef _IOP
15#include <sysclib.h>
16#include <loadcore.h>
17#else
18#include <string.h>
19#include <stdlib.h>
20#endif
21#ifdef APA_USE_ATAD
22#include <atad.h>
23#endif
24#ifdef APA_USE_DEV9
25#include <dev9.h>
26#endif
27#include <errno.h>
28#include <irx.h>
29#include <iomanX.h>
30#include <hdd-ioctl.h>
31
32#include <libapa.h>
33#include "hdd.h"
34#include "hdd_fio.h"
35#include "hdd_blkio.h"
36
37#ifdef _IOP
38IRX_ID("hdd_driver", APA_MODVER_MAJOR, APA_MODVER_MINOR);
39#endif
40
41IOMANX_RETURN_VALUE_IMPL(EPERM);
42
43static iomanX_iop_device_ops_t hddOps={
44 &hddInit, // init
45 &hddDeinit, // deinit
46 &hddFormat, // format
47 &hddOpen, // open
48 &hddClose, // close
49 &hddRead, // read
50 &hddWrite, // write
51 &hddLseek, // lseek
52 IOMANX_RETURN_VALUE(EPERM), // ioctl
53 &hddRemove, // remove
54 IOMANX_RETURN_VALUE(EPERM), // mkdir
55 IOMANX_RETURN_VALUE(EPERM), // rmdir
56 &hddDopen, // dopen
57 &hddClose, // dclose
58 &hddDread, // dread
59 &hddGetStat, // getstat
60 IOMANX_RETURN_VALUE(EPERM), // chstat
61 &hddReName, // rename
62 IOMANX_RETURN_VALUE(EPERM), // chdir
63 IOMANX_RETURN_VALUE(EPERM), // sync
64 hddMount, // mount
65 hddUmount, // umount
66 IOMANX_RETURN_VALUE_S64(EPERM), // lseek64
67 &hddDevctl, // devctl
68 IOMANX_RETURN_VALUE(EPERM), // symlink
69 IOMANX_RETURN_VALUE(EPERM), // readlink
70 &hddIoctl2, // ioctl2
71};
72static iomanX_iop_device_t hddFioDev={
73 "hdd",
74 IOP_DT_BLOCK | IOP_DT_FSEXT,
75 1,
76 "HDD",
77 &hddOps,
78};
79#ifdef APA_SUPPORT_BHDD
80static iomanX_iop_device_t bhddFioDev={
81 "bhdd",
82 IOP_DT_BLOCK | IOP_DT_FSEXT,
83 1,
84 "HDD",
85 &hddOps,
86};
87#endif
88
89apa_device_t hddDevices[BLKIO_MAX_VOLUMES];
90
91extern int apaMaxOpen;
92extern hdd_file_slot_t *hddFileSlots;
93
94static int inputError(char *input);
95#ifdef APA_USE_ATAD
96static int unlockDrive(s32 device);
97#endif
98#ifdef APA_USE_DEV9
99static void hddShutdownCb(void);
100#endif
101static int hddInitError(void);
102
103int hddCheckPartitionMax(s32 device, u32 size)
104{
105 // TODO: In DVRP firmware, this check always succeeds
106 return (hddDevices[device].partitionMaxSize >= size) ? 0 : -EINVAL;
107}
108
109apa_cache_t *hddAddPartitionHere(s32 device, const apa_params_t *params, u32 *emptyBlocks,
110 u32 sector, int *err)
111{
112 apa_cache_t *clink_this;
113 apa_cache_t *clink_next;
114 apa_cache_t *clink_new;
115 apa_header_t *header;
116 u32 i;
117 u32 tmp, some_size, part_end;
118 u32 tempSize;
119 u32 minsize = 0x3FFFF; // 128MB
120#ifdef APA_8MB_PARTITION_SIZE
121 minsize = 0x3FFF; // 8Mb
122#endif
123
124 // walk empty blocks in case can use one :)
125 for(i=0;i< 32;i++)
126 {
127 if((u32)(1 << i) >= params->size && emptyBlocks[i]!=0)
128 return apaInsertPartition(device, params, emptyBlocks[i], err);
129 }
130 clink_this=apaCacheGetHeader(device, sector, APA_IO_MODE_READ, err);
131 header=clink_this->header;
132 part_end=header->start+header->length;
133 some_size=(part_end%params->size);
134 tmp = some_size ? params->size - some_size : 0;
135
136 if(hddDevices[device].totalLBA < (part_end + params->size + tmp)
137 //Non-SONY: when dealing with large disks, this check may overflow (therefore, check for overflows!).
138 || (part_end < sector))
139 {
140 *err=-ENOSPC;
141 apaCacheFree(clink_this);
142 return NULL;
143 }
144
145 if((clink_next=apaCacheGetHeader(device, APA_SECTOR_MBR, APA_IO_MODE_READ, err))==NULL)
146 {
147 apaCacheFree(clink_this);
148 return NULL;
149 }
150
151 while(part_end%params->size)
152 {
153 tempSize=params->size>>1;
154 while (minsize < tempSize) // 128MB
155 {
156 if(!(part_end%tempSize))
157 {
158 clink_new=apaRemovePartition(device, part_end, 0,
159 clink_this->header->start, tempSize);
160 clink_this->header->next=part_end;
161 clink_this->flags|=APA_CACHE_FLAG_DIRTY;
162 clink_next->header->prev=clink_new->header->start;
163 part_end+=tempSize;
164 clink_next->flags|=APA_CACHE_FLAG_DIRTY;
165 apaCacheFlushAllDirty(device);
166 apaCacheFree(clink_this);
167 clink_this=clink_new;
168 break;
169 }
170 tempSize>>=1;
171 }
172 }
173 if((clink_new=apaFillHeader(device, params, part_end, 0, clink_this->header->start,
174 params->size, err))!=NULL)
175 {
176 clink_this->header->next=part_end;
177 clink_this->flags|=APA_CACHE_FLAG_DIRTY;
178 clink_next->header->prev=clink_new->header->start;
179 clink_next->flags|=APA_CACHE_FLAG_DIRTY;
180 apaCacheFlushAllDirty(device);
181 }
182 apaCacheFree(clink_this);
183 apaCacheFree(clink_next);
184 return clink_new;
185}
186
187static int inputError(char *input)
188{
189 APA_PRINTF(APA_DRV_NAME": Error: Usage: %s [-o <apaMaxOpen>] [-n <maxcache>]\n", input);
190 return MODULE_NO_RESIDENT_END;
191}
192
193static void printStartup(void)
194{
195 APA_PRINTF(APA_DRV_NAME": PS2 APA Driver v%d.%d (c) 2003 Vector\n", APA_MODVER_MAJOR, APA_MODVER_MINOR);
196 return;
197}
198
199#ifdef APA_USE_ATAD
200static int unlockDrive(s32 device)
201{
202 int rv;
203 u8 id[32];
204 if((rv=apaGetIlinkID(id))==0)
205 return sceAtaSecurityUnLock(device, id);
206 return rv;
207}
208#endif
209
210#ifdef _IOP
211int APA_ENTRYPOINT(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
212#else
213int APA_ENTRYPOINT(int argc, char *argv[])
214#endif
215{
216 int i, ret;
217 char *input;
218 int cacheSize=3;
219 apa_ps2time_t tm;
220#ifdef APA_USE_ATAD
221 ata_devinfo_t *hddInfo;
222#endif
223
224#ifdef _IOP
225 (void)startaddr;
226 if (argc < 0)
227 {
228 for ( i = 0; i < apaMaxOpen; i += 1 )
229 {
230 if ( hddFileSlots[i].f )
231 {
232 APA_PRINTF(APA_DRV_NAME": error: can't stop module(fd busy)\n");
233 return MODULE_REMOVABLE_END;
234 }
235 }
236#ifdef APA_USE_DEV9
237 Dev9RegisterPowerOffHandler(0, NULL);
238#endif
239 iomanX_DelDrv(hddFioDev.name);
240#ifdef APA_SUPPORT_BHDD
241 iomanX_DelDrv(bhddFioDev.name);
242#endif
243 if (hddFileSlots)
244 {
245 apaFreeMem(hddFileSlots);
246 }
247 apaCacheDeinit();
248 APA_PRINTF(APA_DRV_NAME": stopped module\n");
249 return MODULE_NO_RESIDENT_END;
250 }
251#endif
252
253 printStartup();
254
255 if((input=strrchr(argv[0], '/')))
256 input++;
257 else
258 input=argv[0];
259
260 argc--; argv++;
261 while(argc)
262 {
263 if(argv[0][0] != '-')
264 break;
265 if(strcmp("-o", argv[0])==0)
266 {
267 argc--; argv++;
268 if(!argc)
269 return inputError(input);
270 i=strtol(argv[0], 0, 10);
271 if(i-1<32)
272 apaMaxOpen=i;
273 }
274 else if(strcmp("-n", argv[0])==0)
275 {
276 argc--; argv++;
277 if(!argc)
278 return inputError(input);
279 i=strtol(*argv, 0, 10);
280 if(cacheSize<i)
281 cacheSize=i;
282 }
283 argc--; argv++;
284 }
285
286 APA_PRINTF(APA_DRV_NAME": max open = %d, %d buffers\n", apaMaxOpen, cacheSize);
287#ifdef APA_USE_DEV9
288 if(Dev9RegisterPowerOffHandler(0, &hddShutdownCb) != 0)
289 {
290 APA_PRINTF(APA_DRV_NAME": error: dev9 may not be resident.\n");
291 return hddInitError();
292 }
293#endif
294
295 if(apaGetTime(&tm) != 0)
296 {
297 APA_PRINTF(APA_DRV_NAME": error: could not get date.\n");
298 return hddInitError();
299 }
300
301 APA_PRINTF(APA_DRV_NAME": %02d:%02d:%02d %02d/%02d/%d\n",
302 tm.hour, tm.min, tm.sec, tm.month, tm.day, tm.year);
303 memset(&hddDevices, 0, sizeof(hddDevices));
304 for(i = 0; i < BLKIO_MAX_VOLUMES; i++)
305 {
306 hddDevices[i].status = 3;
307#ifdef APA_USE_ATAD
308 if(!(hddInfo=sceAtaInit(i)))
309 {
310 APA_PRINTF(APA_DRV_NAME": Error: ata initialization failed.\n");
311 return hddInitError();
312 }
313 if(hddInfo->exists!=0 && hddInfo->has_packet==0)
314 {
315 hddDevices[i].status--;
316 hddDevices[i].totalLBA=hddInfo->total_sectors;
317 hddDevices[i].partitionMaxSize=apaGetPartitionMax(hddInfo->total_sectors);
318 if(unlockDrive(i)==0)
319 hddDevices[i].status--;
320 APA_PRINTF(APA_DRV_NAME": disk%d: 0x%08lx sectors, max 0x%08lx\n", i,
321 hddDevices[i].totalLBA, hddDevices[i].partitionMaxSize);
322 }
323#endif
324 }
325 hddFileSlots=apaAllocMem(apaMaxOpen*sizeof(hdd_file_slot_t));
326 ret = (hddFileSlots == NULL) ? -ENOMEM : 0;
327 if(ret != 0)
328 {
329 APA_PRINTF(APA_DRV_NAME": error: file descriptor initialization failed.\n");
330 return hddInitError();
331 }
332
333 memset(hddFileSlots, 0, apaMaxOpen*sizeof(hdd_file_slot_t));
334
335 if(apaCacheInit(cacheSize) != 0)
336 {
337 APA_PRINTF(APA_DRV_NAME": error: cache buffer initialization failed.\n");
338 return hddInitError();
339 }
340
341#ifdef APA_USE_ATAD
342 for(i=0;i < BLKIO_MAX_VOLUMES;i++)
343 {
344 if(hddDevices[i].status<2)
345 {
346 if((hddDevices[i].status != 1) && apaJournalRestore(i) != 0)
347 {
348 APA_PRINTF(APA_DRV_NAME": error: log check failed.\n");
349 return hddInitError();
350 }
351 if(apaGetFormat(i, &hddDevices[i].format))
352 hddDevices[i].status--;
353 APA_PRINTF(APA_DRV_NAME": drive status %d, format version %08x\n",
354 hddDevices[i].status, hddDevices[i].format);
355 }
356 }
357#endif
358 blkIoInit();
359 iomanX_DelDrv(hddFioDev.name);
360 if(iomanX_AddDrv(&hddFioDev) == 0)
361 {
362#ifdef APA_SUPPORT_BHDD
363 iomanX_DelDrv(bhddFioDev.name);
364 if(iomanX_AddDrv(&bhddFioDev) == 0)
365#endif
366 {
367#if defined(APA_XOSD_VER)
368 APA_PRINTF(APA_DRV_NAME": version %04x driver start. This is XOSD LBA48 VERSION !!!!!!!!!!!\n", IRX_VER(APA_MODVER_MAJOR, APA_MODVER_MINOR));
369#elif defined(APA_OSD_VER)
370 APA_PRINTF(APA_DRV_NAME": version %04x driver start. This is OSD version!\n", IRX_VER(APA_MODVER_MAJOR, APA_MODVER_MINOR));
371#else
372 APA_PRINTF(APA_DRV_NAME": version %04x driver start.\n", IRX_VER(APA_MODVER_MAJOR, APA_MODVER_MINOR));
373#endif
374#ifdef _IOP
375 if (mi && ((mi->newflags & 2) != 0))
376 mi->newflags |= 0x10;
377#endif
378 return MODULE_RESIDENT_END;
379 }
380 }
381 {
382 APA_PRINTF(APA_DRV_NAME": error: add device failed.\n");
383 return hddInitError();
384 }
385}
386
387#ifdef APA_USE_DEV9
388static void hddShutdownCb(void)
389{
390 int i;
391
392 for(i = 0; i < BLKIO_MAX_VOLUMES; i++)
393 {
394 if(hddDevices[i].status == 0)
395 blkIoSmartSaveAttr(i);
396 }
397}
398#endif
399
400static int hddInitError(void)
401{
402#ifdef APA_USE_DEV9
403 Dev9RegisterPowerOffHandler(0, NULL);
404#endif
405 return MODULE_NO_RESIDENT_END;
406}
s32 exists
Definition atad.h:29
u32 total_sectors
Definition atad.h:33
s32 has_packet
Definition atad.h:31
#define ENOSPC
Definition errno.h:75
#define EINVAL
Definition errno.h:63
#define ENOMEM
Definition errno.h:43
#define EPERM
Definition errno.h:21
#define IOP_DT_FSEXT
Definition iomanX.h:66
u16 newflags
Definition loadcore.h:36