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
120 // walk empty blocks in case can use one :)
121 for(i=0;i< 32;i++)
122 {
123 if((u32)(1 << i) >= params->size && emptyBlocks[i]!=0)
124 return apaInsertPartition(device, params, emptyBlocks[i], err);
125 }
126 clink_this=apaCacheGetHeader(device, sector, APA_IO_MODE_READ, err);
127 header=clink_this->header;
128 part_end=header->start+header->length;
129 some_size=(part_end%params->size);
130 tmp = some_size ? params->size - some_size : 0;
131
132 if(hddDevices[device].totalLBA < (part_end + params->size + tmp)
133 //Non-SONY: when dealing with large disks, this check may overflow (therefore, check for overflows!).
134 || (part_end < sector))
135 {
136 *err=-ENOSPC;
137 apaCacheFree(clink_this);
138 return NULL;
139 }
140
141 if((clink_next=apaCacheGetHeader(device, APA_SECTOR_MBR, APA_IO_MODE_READ, err))==NULL)
142 {
143 apaCacheFree(clink_this);
144 return NULL;
145 }
146
147 while(part_end%params->size)
148 {
149 tempSize=params->size>>1;
150 while(0x3FFFF<tempSize)
151 {
152 if(!(part_end%tempSize))
153 {
154 clink_new=apaRemovePartition(device, part_end, 0,
155 clink_this->header->start, tempSize);
156 clink_this->header->next=part_end;
157 clink_this->flags|=APA_CACHE_FLAG_DIRTY;
158 clink_next->header->prev=clink_new->header->start;
159 part_end+=tempSize;
160 clink_next->flags|=APA_CACHE_FLAG_DIRTY;
161 apaCacheFlushAllDirty(device);
162 apaCacheFree(clink_this);
163 clink_this=clink_new;
164 break;
165 }
166 tempSize>>=1;
167 }
168 }
169 if((clink_new=apaFillHeader(device, params, part_end, 0, clink_this->header->start,
170 params->size, err))!=NULL)
171 {
172 clink_this->header->next=part_end;
173 clink_this->flags|=APA_CACHE_FLAG_DIRTY;
174 clink_next->header->prev=clink_new->header->start;
175 clink_next->flags|=APA_CACHE_FLAG_DIRTY;
176 apaCacheFlushAllDirty(device);
177 }
178 apaCacheFree(clink_this);
179 apaCacheFree(clink_next);
180 return clink_new;
181}
182
183static int inputError(char *input)
184{
185 APA_PRINTF(APA_DRV_NAME": Error: Usage: %s [-o <apaMaxOpen>] [-n <maxcache>]\n", input);
186 return MODULE_NO_RESIDENT_END;
187}
188
189static void printStartup(void)
190{
191 APA_PRINTF(APA_DRV_NAME": PS2 APA Driver v%d.%d (c) 2003 Vector\n", APA_MODVER_MAJOR, APA_MODVER_MINOR);
192 return;
193}
194
195#ifdef APA_USE_ATAD
196static int unlockDrive(s32 device)
197{
198 int rv;
199 u8 id[32];
200 if((rv=apaGetIlinkID(id))==0)
201 return sceAtaSecurityUnLock(device, id);
202 return rv;
203}
204#endif
205
206#ifdef _IOP
207int APA_ENTRYPOINT(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
208#else
209int APA_ENTRYPOINT(int argc, char *argv[])
210#endif
211{
212 int i, ret;
213 char *input;
214 int cacheSize=3;
215 apa_ps2time_t tm;
216#ifdef APA_USE_ATAD
217 ata_devinfo_t *hddInfo;
218#endif
219
220#ifdef _IOP
221 (void)startaddr;
222 if (argc < 0)
223 {
224 for ( i = 0; i < apaMaxOpen; i += 1 )
225 {
226 if ( hddFileSlots[i].f )
227 {
228 APA_PRINTF(APA_DRV_NAME": error: can't stop module(fd busy)\n");
229 return MODULE_REMOVABLE_END;
230 }
231 }
232#ifdef APA_USE_DEV9
233 Dev9RegisterPowerOffHandler(0, NULL);
234#endif
235 iomanX_DelDrv(hddFioDev.name);
236#ifdef APA_SUPPORT_BHDD
237 iomanX_DelDrv(bhddFioDev.name);
238#endif
239 if (hddFileSlots)
240 {
241 apaFreeMem(hddFileSlots);
242 }
243 apaCacheDeinit();
244 APA_PRINTF(APA_DRV_NAME": stopped module\n");
245 return MODULE_NO_RESIDENT_END;
246 }
247#endif
248
249 printStartup();
250
251 if((input=strrchr(argv[0], '/')))
252 input++;
253 else
254 input=argv[0];
255
256 argc--; argv++;
257 while(argc)
258 {
259 if(argv[0][0] != '-')
260 break;
261 if(strcmp("-o", argv[0])==0)
262 {
263 argc--; argv++;
264 if(!argc)
265 return inputError(input);
266 i=strtol(argv[0], 0, 10);
267 if(i-1<32)
268 apaMaxOpen=i;
269 }
270 else if(strcmp("-n", argv[0])==0)
271 {
272 argc--; argv++;
273 if(!argc)
274 return inputError(input);
275 i=strtol(*argv, 0, 10);
276 if(cacheSize<i)
277 cacheSize=i;
278 }
279 argc--; argv++;
280 }
281
282 APA_PRINTF(APA_DRV_NAME": max open = %d, %d buffers\n", apaMaxOpen, cacheSize);
283#ifdef APA_USE_DEV9
284 if(Dev9RegisterPowerOffHandler(0, &hddShutdownCb) != 0)
285 {
286 APA_PRINTF(APA_DRV_NAME": error: dev9 may not be resident.\n");
287 return hddInitError();
288 }
289#endif
290
291 if(apaGetTime(&tm) != 0)
292 {
293 APA_PRINTF(APA_DRV_NAME": error: could not get date.\n");
294 return hddInitError();
295 }
296
297 APA_PRINTF(APA_DRV_NAME": %02d:%02d:%02d %02d/%02d/%d\n",
298 tm.hour, tm.min, tm.sec, tm.month, tm.day, tm.year);
299 memset(&hddDevices, 0, sizeof(hddDevices));
300 for(i = 0; i < BLKIO_MAX_VOLUMES; i++)
301 {
302 hddDevices[i].status = 3;
303#ifdef APA_USE_ATAD
304 if(!(hddInfo=sceAtaInit(i)))
305 {
306 APA_PRINTF(APA_DRV_NAME": Error: ata initialization failed.\n");
307 return hddInitError();
308 }
309 if(hddInfo->exists!=0 && hddInfo->has_packet==0)
310 {
311 hddDevices[i].status--;
312 hddDevices[i].totalLBA=hddInfo->total_sectors;
313 hddDevices[i].partitionMaxSize=apaGetPartitionMax(hddInfo->total_sectors);
314 if(unlockDrive(i)==0)
315 hddDevices[i].status--;
316 APA_PRINTF(APA_DRV_NAME": disk%d: 0x%08lx sectors, max 0x%08lx\n", i,
317 hddDevices[i].totalLBA, hddDevices[i].partitionMaxSize);
318 }
319#endif
320 }
321 hddFileSlots=apaAllocMem(apaMaxOpen*sizeof(hdd_file_slot_t));
322 ret = (hddFileSlots == NULL) ? -ENOMEM : 0;
323 if(ret != 0)
324 {
325 APA_PRINTF(APA_DRV_NAME": error: file descriptor initialization failed.\n");
326 return hddInitError();
327 }
328
329 memset(hddFileSlots, 0, apaMaxOpen*sizeof(hdd_file_slot_t));
330
331 if(apaCacheInit(cacheSize) != 0)
332 {
333 APA_PRINTF(APA_DRV_NAME": error: cache buffer initialization failed.\n");
334 return hddInitError();
335 }
336
337#ifdef APA_USE_ATAD
338 for(i=0;i < BLKIO_MAX_VOLUMES;i++)
339 {
340 if(hddDevices[i].status<2)
341 {
342 if((hddDevices[i].status != 1) && apaJournalRestore(i) != 0)
343 {
344 APA_PRINTF(APA_DRV_NAME": error: log check failed.\n");
345 return hddInitError();
346 }
347 if(apaGetFormat(i, &hddDevices[i].format))
348 hddDevices[i].status--;
349 APA_PRINTF(APA_DRV_NAME": drive status %d, format version %08x\n",
350 hddDevices[i].status, hddDevices[i].format);
351 }
352 }
353#endif
354 blkIoInit();
355 iomanX_DelDrv(hddFioDev.name);
356 if(iomanX_AddDrv(&hddFioDev) == 0)
357 {
358#ifdef APA_SUPPORT_BHDD
359 iomanX_DelDrv(bhddFioDev.name);
360 if(iomanX_AddDrv(&bhddFioDev) == 0)
361#endif
362 {
363#if defined(APA_XOSD_VER)
364 APA_PRINTF(APA_DRV_NAME": version %04x driver start. This is XOSD LBA48 VERSION !!!!!!!!!!!\n", IRX_VER(APA_MODVER_MAJOR, APA_MODVER_MINOR));
365#elif defined(APA_OSD_VER)
366 APA_PRINTF(APA_DRV_NAME": version %04x driver start. This is OSD version!\n", IRX_VER(APA_MODVER_MAJOR, APA_MODVER_MINOR));
367#else
368 APA_PRINTF(APA_DRV_NAME": version %04x driver start.\n", IRX_VER(APA_MODVER_MAJOR, APA_MODVER_MINOR));
369#endif
370#ifdef _IOP
371 if (mi && ((mi->newflags & 2) != 0))
372 mi->newflags |= 0x10;
373#endif
374 return MODULE_RESIDENT_END;
375 }
376 }
377 {
378 APA_PRINTF(APA_DRV_NAME": error: add device failed.\n");
379 return hddInitError();
380 }
381}
382
383#ifdef APA_USE_DEV9
384static void hddShutdownCb(void)
385{
386 int i;
387
388 for(i = 0; i < BLKIO_MAX_VOLUMES; i++)
389 {
390 if(hddDevices[i].status == 0)
391 blkIoSmartSaveAttr(i);
392 }
393}
394#endif
395
396static int hddInitError(void)
397{
398#ifdef APA_USE_DEV9
399 Dev9RegisterPowerOffHandler(0, NULL);
400#endif
401 return MODULE_NO_RESIDENT_END;
402}
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