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.
10 # $Id: hdd_fio.c 1511 2009-01-15 09:11:30Z radad $
11 # APA File System routines
16 hdd_file_slot_t
*fileSlots
;
19 static const char *formatPartList
[]={
20 "__net", "__system", "__sysconf", "__common", NULL
23 #define APA_NUMBER_OF_SIZES 9
24 static const char *sizeList
[APA_NUMBER_OF_SIZES
]={
25 "128M", "256M", "512M", "1G", "2G", "4G", "8G", "16G", "32G"
28 int fioPartitionSizeLookUp(char *str
)
32 for(i
=0;i
<APA_NUMBER_OF_SIZES
;i
++){
33 if(strcmp(str
, sizeList
[i
])==0)
34 return (256*1024) << i
;
36 dprintf1("ps2hdd: Error: Invalid partition size, %s.\n", str
);
40 int fioInputBreaker(char const **arg
, char *outBuf
, int maxout
)
45 if((p
=strchr(arg
[0], ','))) {
46 if(maxout
< (len
=p
-arg
[0]))
48 memcpy(outBuf
, arg
[0], len
);
50 while(arg
[0][0]==' ') arg
[0]+=1;
53 if(maxout
< (len
=strlen(arg
[0])))
55 memcpy(outBuf
, arg
[0], len
); arg
[0]+=len
;
59 // NOTE: Changed so format = partitionID,size (used to be partitionID,fpswd,rpswd,size,filesystem)
60 int fioGetInput(const char *arg
, input_param
*params
)
67 memset(params
, 0, sizeof(input_param
));
69 while(arg
[0]==' ') arg
++;
71 if(arg
[0]==0 || arg
[0]==',')
73 if((rv
=fioInputBreaker(&arg
, params
->id
, APA_IDMAX
))!=0)
75 if((params
->id
[0]==0) || (arg
[0]==0))
78 memset(szBuf
, 0, sizeof(szBuf
));
79 if((rv
=fioInputBreaker(&arg
, szBuf
, sizeof(szBuf
)))!=0)
82 if((rv
=fioPartitionSizeLookUp(szBuf
))<0)
86 // Filesystem type is fixed to PFS!
87 params
->type
= APA_TYPE_PFS
;
91 int getFileSlot(input_param
*params
, hdd_file_slot_t
**fileSlot
)
95 for(i
=0;i
<maxOpen
;i
++)
98 if(memcmp(fileSlots
[i
].id
, ¶ms
->id
, APA_IDMAX
)==0)
99 return -EBUSY
;// file is open
101 for(i
=0;i
<maxOpen
;i
++)
104 *fileSlot
=&fileSlots
[i
];
108 return -EMFILE
;// no file slots free :(
111 int fioDataTransfer(iop_file_t
*f
, void *buf
, int size
, int mode
)
113 hdd_file_slot_t
*fileSlot
=(hdd_file_slot_t
*)f
->privdata
;
117 size
>>=9; // size/512
119 if(fileSlot
->post
+size
>=0x1FF9)// no over reading
120 size
=0x1FF8-fileSlot
->post
;
126 if(atadDmaTransfer(f
->unit
, buf
, fileSlot
->post
+fileSlot
->start
+8, size
, mode
))
131 fileSlot
->post
+=size
;
138 int ioctl2Transfer(u32 device
, hdd_file_slot_t
*fileSlot
, hddIoctl2Transfer_t
*arg
)
142 if(fileSlot
->nsub
<arg
->sub
)
143 return -ENODEV
;//-EINVAL;
145 // main partitions only can read 4MB on :P
146 if(arg
->sub
==0 && (arg
->sector
< 0x2000))
148 // subs partitions only can read header on...
149 if(arg
->sub
!=0 && (arg
->sector
< 2))
152 subs
=((apa_subs
*)(&fileSlot
->start
)); // !HACK!
153 if(subs
[arg
->sub
].length
<arg
->sector
+arg
->size
)
156 if(atadDmaTransfer(device
, arg
->buffer
,
157 subs
[arg
->sub
].start
+arg
->sector
, arg
->size
, arg
->mode
))
163 void hddPowerOffHandler(void* data
)
165 printf("hdd flush cache\n");
169 int hddInit(iop_device_t
*f
)
177 fioSema
=CreateSema(&sema
);
179 AddPowerOffHandler(hddPowerOffHandler
, 0);
183 int hddDeinit(iop_device_t
*f
)
189 int hddFormat(iop_file_t
*f
, const char *dev
, const char *blockdev
, void *arg
, size_t arglen
)
200 // clear all errors on hdd
201 clink
=cacheGetFree();
202 memset(clink
->header
, 0, sizeof(apa_header
));
203 if(atadDmaTransfer(f
->unit
, clink
->header
, APA_SECTOR_SECTOR_ERROR
, 1, ATAD_MODE_WRITE
)){
207 if(atadDmaTransfer(f
->unit
, clink
->header
, APA_SECTOR_PART_ERROR
, 1, ATAD_MODE_WRITE
)){
212 for(i
=1024*8;i
<hddDeviceBuf
[f
->unit
].totalLBA
;i
+=(1024*256))
214 atadDmaTransfer(f
->unit
, clink
->header
, i
, sizeof(apa_header
)/512,
218 if((rv
=journalReset(f
->unit
))!=0)
222 if((clink
=cacheGetHeader(f
->unit
, 0, 1, &rv
))){
223 apa_header
*header
=clink
->header
;
224 memset(header
, 0, sizeof(apa_header
));
225 header
->magic
=APA_MAGIC
;
226 header
->length
=(1024*256); // 128MB
227 header
->type
=APA_TYPE_MBR
;
228 strcpy(header
->id
,"__mbr");
229 memcpy(header
->mbr
.magic
, mbrMagic
, 32);
231 header
->mbr
.version
=APA_MBR_VERSION
;
232 header
->mbr
.nsector
=0;
233 getPs2Time(&header
->created
);
234 getPs2Time(&header
->mbr
.created
);
235 header
->checksum
=apaCheckSum(header
);
236 clink
->flags
|=CACHE_FLAG_DIRTY
;
237 cacheFlushDirty(clink
);
238 atadFlushCache(f
->unit
);
240 hddDeviceBuf
[f
->unit
].status
=0;
241 hddDeviceBuf
[f
->unit
].format
=APA_MBR_VERSION
;
243 memset(&emptyBlocks
, 0, sizeof(emptyBlocks
));
244 memset(¶ms
, 0, sizeof(input_param
));
245 params
.size
=(1024*256);
246 params
.type
=APA_TYPE_PFS
;
248 // add __net, __system....
249 for(i
=0;formatPartList
[i
];i
++)
251 memset(params
.id
, 0, APA_IDMAX
);
252 strcpy(params
.id
, formatPartList
[i
]);
253 if(!(clink
=apaAddPartitionHere(f
->unit
, ¶ms
, emptyBlocks
, i
? clink
->sector
: 0, &rv
)))
258 if(hddDeviceBuf
[f
->unit
].partitionMaxSize
< params
.size
)
259 params
.size
=hddDeviceBuf
[f
->unit
].partitionMaxSize
;
264 int hddRemove(iop_file_t
*f
, const char *name
)
269 if((rv
=fioGetInput(name
, ¶ms
)) < 0)
273 apaRemove(f
->unit
, params
.id
);
274 return SignalSema(fioSema
);
277 int hddOpen(iop_file_t
*f
, const char *name
, int mode
, int other_mode
)
281 hdd_file_slot_t
*fileSlot
;
283 if(f
->unit
>= 2 || hddDeviceBuf
[f
->unit
].status
!=0)
286 if(!(f
->mode
& O_DIROPEN
))
287 if((rv
=fioGetInput(name
, ¶ms
)) < 0)
291 if((rv
=getFileSlot(¶ms
, &fileSlot
))==0) {
292 if(!(f
->mode
& O_DIROPEN
)) {
293 if((rv
=apaOpen(f
->unit
, fileSlot
, ¶ms
, mode
))==0){
295 f
->privdata
=fileSlot
;
301 f
->privdata
=fileSlot
;
308 int hddClose(iop_file_t
*f
)
311 memset(f
->privdata
, 0, sizeof(hdd_file_slot_t
));
316 int hddRead(iop_file_t
*f
, void *buf
, int size
)
318 return fioDataTransfer(f
, buf
, size
, ATAD_MODE_READ
);
321 int hddWrite(iop_file_t
*f
, void *buf
, int size
)
323 if(!(f
->mode
& O_WRONLY
))
325 return fioDataTransfer(f
, buf
, size
, ATAD_MODE_WRITE
);
328 int hddLseek(iop_file_t
*f
, unsigned long post
, int whence
)
331 hdd_file_slot_t
*fileSlot
;
333 // test input( no seeking to end point less :P )
342 fileSlot
=f
->privdata
;
345 if((fileSlot
->post
+post
) < 0 || (fileSlot
->post
+post
)>=0x1FF9)
349 fileSlot
->post
+=post
;
350 rv
=fileSlot
->post
<<9;
353 else if(whence
==SEEK_SET
)
355 if(post
< 0 || post
>=0x1FF9)
360 rv
=fileSlot
->post
<<9;
368 void fioGetStatFiller(apa_cache
*clink
, iox_stat_t
*stat
)
372 stat
->mode
=clink
->header
->type
;
373 stat
->attr
=clink
->header
->flags
;
375 u64 size
= clink
->header
->length
;
377 stat
->size
=size
& 0xFFFFFFFF;
379 stat
->hisize
=size
& 0xFFFFFFFF;
380 header
=clink
->header
;
381 memcpy(&stat
->ctime
, &clink
->header
->created
, sizeof(ps2time
));
382 memcpy(&stat
->atime
, &clink
->header
->created
, sizeof(ps2time
));
383 memcpy(&stat
->mtime
, &clink
->header
->created
, sizeof(ps2time
));
384 if(clink
->header
->flags
& APA_FLAG_SUB
)
385 stat
->private_0
=clink
->header
->number
;
387 stat
->private_0
=clink
->header
->nsub
;
392 //stat->private_5=0;// game ver
393 stat
->private_5
=clink
->header
->start
;// sony ver
396 int hddGetStat(iop_file_t
*f
, const char *name
, iox_stat_t
*stat
)
402 if((rv
=fioGetInput(name
, ¶ms
))<0)
406 if((clink
=apaFindPartition(f
->unit
, params
.id
, &rv
))){
407 if((rv
=passcmp(clink
->header
->rpwd
, NULL
))==0)
408 fioGetStatFiller(clink
, stat
);
415 int hddDopen(iop_file_t
*f
, const char *name
)
417 return hddOpen(f
, name
, 0, 0);
420 int hddDread(iop_file_t
*f
, iox_dirent_t
*dirent
)
423 hdd_file_slot_t
*fileSlot
=f
->privdata
;
426 if(!(f
->mode
& O_DIROPEN
))
429 if(fileSlot
->start
==-1)
433 if((clink
=cacheGetHeader(f
->unit
, fileSlot
->start
, 0, &rv
)) &&
434 clink
->header
->length
)
436 if(clink
->header
->flags
& APA_FLAG_SUB
) {
437 // if sub get id from main header...
438 apa_cache
*cmain
=cacheGetHeader(f
->unit
, clink
->header
->main
, 0, &rv
);
440 rv
=strlen(cmain
->header
->id
);
441 strcpy(dirent
->name
, cmain
->header
->id
);
446 rv
=strlen(clink
->header
->id
);
447 strcpy(dirent
->name
, clink
->header
->id
);
449 fioGetStatFiller(clink
, &dirent
->stat
);
450 if(clink
->header
->next
==0)
451 fileSlot
->start
=-1; // mark end
453 fileSlot
->start
=clink
->header
->next
;// set next
460 int hddReName(iop_file_t
*f
, const char *oldname
, const char *newname
)
465 char tmpBuf
[APA_IDMAX
];
467 if(f
->unit
>= 2 || hddDeviceBuf
[f
->unit
].status
!=0)
468 return -ENODEV
;// No such device
471 // look to see if can make(newname) or not...
472 memset(tmpBuf
, 0, APA_IDMAX
);
473 strncpy(tmpBuf
, newname
, APA_IDMAX
- 1);
474 tmpBuf
[APA_IDMAX
- 1] = '\0';
475 if((clink
=apaFindPartition(f
->unit
, tmpBuf
, &rv
))){
478 return -EEXIST
; // File exists
481 // look to see if open(oldname)
482 memset(tmpBuf
, 0, APA_IDMAX
);
483 strncpy(tmpBuf
, oldname
, APA_IDMAX
- 1);
484 tmpBuf
[APA_IDMAX
- 1] = '\0';
485 for(i
=0;i
<maxOpen
;i
++)
487 if(fileSlots
[i
].f
!=0)
488 if(fileSlots
[i
].f
->unit
==f
->unit
)
489 if(memcmp(fileSlots
[i
].id
, oldname
, APA_IDMAX
)==0)
497 if(!(clink
=apaFindPartition(f
->unit
, tmpBuf
, &rv
)))
503 // do the renameing :) note: subs have no names!!
504 memset(clink
->header
->id
, 0, APA_IDMAX
); // all cmp are done with memcmp!
505 strncpy(clink
->header
->id
, newname
, APA_IDMAX
- 1);
506 clink
->header
->id
[APA_IDMAX
- 1] = '\0';
508 clink
->flags
|=CACHE_FLAG_DIRTY
;
509 cacheFlushAllDirty(f
->unit
);
515 int ioctl2AddSub(hdd_file_slot_t
*fileSlot
, char *argp
)
518 u32 device
=fileSlot
->f
->unit
;
525 if(!(fileSlot
->f
->mode
& O_WRONLY
))
528 if(!(fileSlot
->nsub
< APA_MAXSUB
))
531 memset(¶ms
, 0, sizeof(input_param
));
533 if((rv
=fioPartitionSizeLookUp(argp
)) < 0)
537 params
.flags
=APA_FLAG_SUB
;
538 params
.type
=fileSlot
->type
;
539 params
.main
=fileSlot
->start
;
540 params
.number
=fileSlot
->nsub
+1;
541 if((rv
=apaCheckPartitionMax(device
, params
.size
)) < 0)
544 // walk all looking for any empty blocks
545 memset(&emptyBlocks
, 0, sizeof(emptyBlocks
));
546 clink
=cacheGetHeader(device
, 0, 0, &rv
);
548 sector
=clink
->sector
;
549 addEmptyBlock(clink
->header
, emptyBlocks
);
550 clink
=apaGetNextHeader(clink
, &rv
);
555 if(!(clink
=apaAddPartitionHere(device
, ¶ms
, emptyBlocks
, sector
, &rv
)))
558 sector
=clink
->header
->start
;
559 length
=clink
->header
->length
;
561 if(!(clink
=cacheGetHeader(device
, fileSlot
->start
, 0, &rv
)))
564 clink
->header
->subs
[clink
->header
->nsub
].start
=sector
;
565 clink
->header
->subs
[clink
->header
->nsub
].length
=length
;
566 clink
->header
->nsub
++;
568 ((apa_subs
*)(&fileSlot
->start
))[fileSlot
->nsub
].start
=sector
; // !HACK!
569 ((apa_subs
*)(&fileSlot
->start
))[fileSlot
->nsub
].length
=length
; // !HACK!
570 clink
->flags
|=CACHE_FLAG_DIRTY
;
571 cacheFlushAllDirty(device
);
576 int ioctl2DeleteLastSub(hdd_file_slot_t
*fileSlot
)
579 u32 device
=fileSlot
->f
->unit
;
583 if(!(fileSlot
->f
->mode
& O_WRONLY
))
586 if(fileSlot
->nsub
==0)
589 if(!(mainPart
=cacheGetHeader(device
, fileSlot
->start
, 0, &rv
)))
592 if((subPart
=cacheGetHeader(device
,
593 mainPart
->header
->subs
[mainPart
->header
->nsub
-1].start
, 0, &rv
))) {
595 mainPart
->header
->nsub
--;
596 mainPart
->flags
|=CACHE_FLAG_DIRTY
;
597 cacheFlushAllDirty(device
);
598 rv
=apaDelete(subPart
);
604 int hddIoctl2(iop_file_t
*f
, int req
, void *argp
, unsigned int arglen
,
605 void *bufp
, unsigned int buflen
)
608 hdd_file_slot_t
*fileSlot
=f
->privdata
;
614 case APA_IOCTL2_ADD_SUB
:
615 rv
=ioctl2AddSub(fileSlot
, (char *)argp
);
618 case APA_IOCTL2_DELETE_LAST_SUB
:
619 rv
=ioctl2DeleteLastSub(fileSlot
);
622 case APA_IOCTL2_NUMBER_OF_SUBS
:
626 case APA_IOCTL2_FLUSH_CACHE
:
627 atadFlushCache(f
->unit
);
631 case APA_IOCTL2_TRANSFER_DATA
:
632 rv
=ioctl2Transfer(f
->unit
, fileSlot
, argp
);
635 case APA_IOCTL2_GETSIZE
:
636 // rv=fileSlot->subs[*(u32 *)argp].length;
637 rv
=((apa_subs
*)(&fileSlot
->start
))[*(u32
*)argp
].length
; // !HACK!
640 case APA_IOCTL2_GETHEADER
:
641 if(atadDmaTransfer(f
->unit
, bufp
, fileSlot
->start
, sizeof(apa_header
)/512, ATAD_MODE_READ
))
643 rv
=sizeof(apa_header
);
646 case APA_IOCTL2_SET_PART_ERROR
:
647 setPartErrorSector(f
->unit
, fileSlot
->start
); rv
=0;
650 case APA_IOCTL2_GET_PART_ERROR
:
651 if((rv
=getPartErrorSector(f
->unit
, APA_SECTOR_PART_ERROR
, bufp
)) > 0) {
652 if(*(u32
*)bufp
==fileSlot
->start
) {
653 rv
=0; setPartErrorSector(f
->unit
, 0);// clear last error :)
666 int devctlSwapTemp(u32 device
, char *argp
)
670 char szBuf
[APA_IDMAX
];
675 if((rv
=fioGetInput(argp
, ¶ms
)) < 0)
678 if(*(u16
*)(params
.id
)==(u16
)0x5F5F)// test for '__' system partition
681 memset(szBuf
, 0, APA_IDMAX
);
682 strcpy(szBuf
, "_tmp");
683 if(!(partTemp
=apaFindPartition(device
, szBuf
, &rv
)))
686 if((partNew
=apaFindPartition(device
, params
.id
, &rv
))) {
687 if((rv
=passcmp(partNew
->header
->fpwd
, NULL
))==0) {
688 memcpy(partTemp
->header
->id
, partNew
->header
->id
, APA_IDMAX
);
689 memcpy(partTemp
->header
->rpwd
, partNew
->header
->rpwd
, APA_PASSMAX
);
690 memcpy(partTemp
->header
->fpwd
, partNew
->header
->fpwd
, APA_PASSMAX
);
691 //memset(partNew->header->id, 0, 8);// BUG! can make it so can not open!!
692 memset(partNew
->header
->id
, 0, APA_IDMAX
);
693 strcpy(partNew
->header
->id
, "_tmp");
694 memset(partNew
->header
->rpwd
, 0, APA_PASSMAX
);
695 memset(partNew
->header
->fpwd
, 0, APA_PASSMAX
);
696 partTemp
->flags
|=CACHE_FLAG_DIRTY
;
697 partNew
->flags
|=CACHE_FLAG_DIRTY
;
698 cacheFlushAllDirty(device
);
706 int devctlSetOsdMBR(u32 device
, hddSetOsdMBR_t
*mbrInfo
)
711 if(!(clink
=cacheGetHeader(device
, APA_SECTOR_MBR
, 0, &rv
)))
714 dprintf1("ps2hdd: mbr start: %ld\n"
715 "ps2hdd: mbr size : %ld\n", mbrInfo
->start
, mbrInfo
->size
);
716 clink
->header
->mbr
.osdStart
=mbrInfo
->start
;
717 clink
->header
->mbr
.osdSize
=mbrInfo
->size
;
718 clink
->flags
|=CACHE_FLAG_DIRTY
;
719 cacheFlushAllDirty(device
);
724 int hddDevctl(iop_file_t
*f
, const char *devname
, int cmd
, void *arg
,
725 unsigned int arglen
, void *bufp
, unsigned int buflen
)
733 case APA_DEVCTL_DEV9_SHUTDOWN
:
734 atadUpdateAttrib(f
->unit
);
738 case APA_DEVCTL_IDLE
:
739 rv
=atadIdle(f
->unit
, *(char *)arg
);
742 case APA_DEVCTL_MAX_SECTORS
:
743 rv
=hddDeviceBuf
[f
->unit
].partitionMaxSize
;
746 case APA_DEVCTL_TOTAL_SECTORS
:
747 rv
=hddDeviceBuf
[f
->unit
].totalLBA
;
750 case APA_DEVCTL_FLUSH_CACHE
:
751 if(atadFlushCache(f
->unit
))
755 case APA_DEVCTL_SWAP_TMP
:
756 rv
=devctlSwapTemp(f
->unit
, (char *)arg
);
759 case APA_DEVCTL_SMART_STAT
:
760 rv
=atadGetStatus(f
->unit
);
763 case APA_DEVCTL_STATUS
:
764 rv
=hddDeviceBuf
[f
->unit
].status
;
767 case APA_DEVCTL_FORMAT
:
768 rv
=hddDeviceBuf
[f
->unit
].format
;
771 // removed dos not work the way you like... use hddlib ;)
772 //case APA_DEVCTL_FREE_SECTORS:
773 //case APA_DEVCTL_FREE_SECTORS2:
774 // rv=apaGetFreeSectors(f->unit, bufp);
778 case APA_DEVCTL_GETTIME
:
779 rv
=getPs2Time((ps2time
*)bufp
);
782 case APA_DEVCTL_SET_OSDMBR
:
783 rv
=devctlSetOsdMBR(f
->unit
, (hddSetOsdMBR_t
*)arg
);
786 case APA_DEVCTL_GET_SECTOR_ERROR
:
787 rv
=getPartErrorSector(f
->unit
, APA_SECTOR_SECTOR_ERROR
, 0);
790 case APA_DEVCTL_GET_ERROR_PART_NAME
:
791 rv
=getPartErrorName(f
->unit
, (char *)bufp
);
794 case APA_DEVCTL_ATA_READ
:
795 rv
=atadDmaTransfer(f
->unit
, (void *)bufp
, ((hddAtaTransfer_t
*)arg
)->lba
,
796 ((hddAtaTransfer_t
*)arg
)->size
, ATAD_MODE_READ
);
799 case APA_DEVCTL_ATA_WRITE
:
800 rv
=atadDmaTransfer(f
->unit
, ((hddAtaTransfer_t
*)arg
)->data
,
801 ((hddAtaTransfer_t
*)arg
)->lba
, ((hddAtaTransfer_t
*)arg
)->size
,
805 case APA_DEVCTL_SCE_IDENTIFY_DRIVE
:
806 rv
=atadSceIdentifyDrive(f
->unit
, (u16
*)bufp
);
809 case APA_DEVCTL_IS_48BIT
:
810 rv
=atadIs48bit(f
->unit
);
813 case APA_DEVCTL_SET_TRANSFER_MODE
:
814 rv
=atadSetTransferMode(f
->unit
, ((hddAtaSetMode_t
*)arg
)->type
, ((hddAtaSetMode_t
*)arg
)->mode
);
817 case APA_DEVCTL_ATA_IOP_WRITE
:
818 rv
=atadDmaTransfer(f
->unit
, ((hddAtaIOPTransfer_t
*)arg
)->data
,
819 ((hddAtaIOPTransfer_t
*)arg
)->lba
, ((hddAtaIOPTransfer_t
*)arg
)->size
,
832 int hddUnsupported(iop_file_t
*f
){return -1;}