int journalResetore(u32 device) { // copys apa headers from apal to apa system int i; u32 sector; apa_cache *clink; dprintf1("ps2hdd: checking log...\n"); if(atadDmaTransfer(device, &journalBuf, APA_SECTOR_APAL, sizeof(apa_journal_t)/512, ATAD_MODE_READ)){ journalReset(device); return -EIO; } if(journalBuf.magic==APAL_MAGIC) { if(journalBuf.num==0) return 0; clink=cacheGetFree(); for(i=0, sector=APA_SECTOR_APAL_HEADERS;i<journalBuf.num;i++, sector+=2) { if(atadDmaTransfer(device, clink->header, sector, 2, ATAD_MODE_READ)) break; if(atadDmaTransfer(device, clink->header, journalBuf.sectors[i], 2, ATAD_MODE_WRITE)) break; } cacheAdd(clink); return journalReset(device);// only do if journal.. } memset(&journalBuf, 0, sizeof(apa_journal_t));// safe e journalBuf.magic=APAL_MAGIC; return 0;//-EINVAL; }
int apaOpen(u32 device, hdd_file_slot_t *fileSlot, input_param *params, int mode) { int rv=0; u32 emptyBlocks[32]; apa_cache *clink; apa_cache *clink2; u32 sector=0; // walk all looking for any empty blocks & look for partition clink=cacheGetHeader(device, 0, 0, &rv); memset(&emptyBlocks, 0, sizeof(emptyBlocks)); while(clink) { sector=clink->sector; if(!(clink->header->flags & APA_FLAG_SUB)) { if(memcmp(clink->header->id, params->id, APA_IDMAX) == 0) break; // found :) } addEmptyBlock(clink->header, emptyBlocks); clink=apaGetNextHeader(clink, &rv); } if(rv!=0) return rv; rv=-ENOENT; if(clink==NULL && (mode & O_CREAT)) { if((rv=apaCheckPartitionMax(device, params->size))>=0) { if((clink=apaAddPartitionHere(device, params, emptyBlocks, sector, &rv))!=NULL) { sector=clink->header->start; clink2=cacheGetFree(); memset(clink2->header, 0, sizeof(apa_header)); atadDmaTransfer(device, clink2->header, sector+8 , 2, ATAD_MODE_WRITE); atadDmaTransfer(device, clink2->header, sector+0x2000, 2, ATAD_MODE_WRITE); cacheAdd(clink2); } } } if(clink==NULL) return rv; fileSlot->start=clink->header->start; fileSlot->length=clink->header->length; memcpy(&fileSlot->subs, &clink->header->subs, APA_MAXSUB*sizeof(apa_subs)); fileSlot->type=clink->header->type; fileSlot->nsub=clink->header->nsub; memcpy(&fileSlot->id, &clink->header->id, APA_IDMAX); cacheAdd(clink); rv=0; if(passcmp(clink->header->fpwd, NULL)!=0) rv=-EACCES; return rv; }
int apaGetFormat(u32 device, int *format) { apa_cache *clink; int rv=0;// u32 rv=0; u32 *pDW; int i; clink=cacheGetFree(); *format=0; if((rv=apaReadHeader(device, clink->header, 0))==0) { *format=clink->header->mbr.version; if(atadDmaTransfer(device, clink->header, APA_SECTOR_SECTOR_ERROR, 2, ATAD_MODE_READ)) rv=-EIO; // return -EIO; if(rv==0){ pDW=(u32 *)clink->header; for(i=0;i < 256; i++) { if((i & 0x7F) && pDW[i]!=0) rv=1; } } } cacheAdd(clink); return rv==0; }
void apaSaveError(u32 device, void *buffer, u32 lba, u32 err_lba) { memset(buffer, 0, 512); *(u32 *)buffer=err_lba; atadDmaTransfer(device, buffer, lba, 1, ATAD_MODE_WRITE); atadFlushCache(device); }
int fioDataTransfer(iop_file_t *f, void *buf, int size, int mode) { hdd_file_slot_t *fileSlot=(hdd_file_slot_t *)f->privdata; if((size & 0x1FF)) return -EINVAL; size>>=9; // size/512 if(fileSlot->post+size>=0x1FF9)// no over reading size=0x1FF8-fileSlot->post; if(size!=0) { int rv=0; WaitSema(fioSema); if(atadDmaTransfer(f->unit, buf, fileSlot->post+fileSlot->start+8, size, mode)) rv=-EIO; SignalSema(fioSema); if(rv==0) { fileSlot->post+=size; return size<<9; } } return 0; }
int journalWrite(apa_cache *clink) { clink->header->checksum=journalCheckSum(clink->header); if(atadDmaTransfer(clink->device, clink->header, (journalBuf.num << 1)+APA_SECTOR_APAL_HEADERS, 2, ATAD_MODE_WRITE)) return -EIO; journalBuf.sectors[journalBuf.num]=clink->sector; journalBuf.num++; return 0; }
int journalFlush(u32 device) {// this write any thing that in are journal buffer :) if(atadFlushCache(device)) return -EIO; if(atadDmaTransfer(device, &journalBuf, APA_SECTOR_APAL, 1, ATAD_MODE_WRITE)) return -EIO; if(atadFlushCache(device)) return -EIO; return 0; }
int apaReadHeader(u32 device, apa_header *header, u32 lba) { if(atadDmaTransfer(device, header, lba, 2, ATAD_MODE_READ)!=0) return -EIO; if(header->magic!=APA_MAGIC) return -EIO; if(apaCheckSum(header)!=header->checksum) return -EIO; if(lba==APA_SECTOR_MBR) { if(strncmp(header->mbr.magic, mbrMagic, 0x20)==0) return 0; dprintf1("ps2hdd: Error: invalid partition table or version newer than I know.\n"); return -EIO; } return 0; }
int getPartErrorSector(u32 device, u32 lba, int *lba_out) { apa_cache *clink; int rv=0; if(!(clink=cacheGetFree())) return -ENOMEM; if(atadDmaTransfer(device, clink->header, lba, 1, ATAD_MODE_READ)) return -EIO; if(lba_out) *lba_out=((u32 *)(clink->header))[0]; if(((u32 *)(clink->header))[0]) rv=1;// error is set ;) cacheAdd(clink); return rv; }
int ioctl2Transfer(u32 device, hdd_file_slot_t *fileSlot, hddIoctl2Transfer_t *arg) { apa_subs *subs; if(fileSlot->nsub<arg->sub) return -ENODEV;//-EINVAL; // main partitions only can read 4MB on :P if(arg->sub==0 && (arg->sector < 0x2000)) return -EINVAL; // subs partitions only can read header on... if(arg->sub!=0 && (arg->sector < 2)) return -EINVAL; subs=((apa_subs *)(&fileSlot->start)); // !HACK! if(subs[arg->sub].length<arg->sector+arg->size) return -ENXIO; if(atadDmaTransfer(device, arg->buffer, subs[arg->sub].start+arg->sector, arg->size, arg->mode)) return -EIO; return 0; }
int apaWriteHeader(u32 device, apa_header *header, u32 lba) { if(atadDmaTransfer(device, header, lba, 2, ATAD_MODE_WRITE)) return -EIO; return 0; }
int hddDevctl(iop_file_t *f, const char *devname, int cmd, void *arg, unsigned int arglen, void *bufp, unsigned int buflen) { int rv=0; WaitSema(fioSema); switch(cmd) { // cmd set 1 case APA_DEVCTL_DEV9_SHUTDOWN: atadUpdateAttrib(f->unit); dev9Shutdown(); break; case APA_DEVCTL_IDLE: rv=atadIdle(f->unit, *(char *)arg); break; case APA_DEVCTL_MAX_SECTORS: rv=hddDeviceBuf[f->unit].partitionMaxSize; break; case APA_DEVCTL_TOTAL_SECTORS: rv=hddDeviceBuf[f->unit].totalLBA; break; case APA_DEVCTL_FLUSH_CACHE: if(atadFlushCache(f->unit)) rv=-EIO; break; case APA_DEVCTL_SWAP_TMP: rv=devctlSwapTemp(f->unit, (char *)arg); break; case APA_DEVCTL_SMART_STAT: rv=atadGetStatus(f->unit); break; case APA_DEVCTL_STATUS: rv=hddDeviceBuf[f->unit].status; break; case APA_DEVCTL_FORMAT: rv=hddDeviceBuf[f->unit].format; break; // removed dos not work the way you like... use hddlib ;) //case APA_DEVCTL_FREE_SECTORS: //case APA_DEVCTL_FREE_SECTORS2: // rv=apaGetFreeSectors(f->unit, bufp); // break; // cmd set 2 :) case APA_DEVCTL_GETTIME: rv=getPs2Time((ps2time *)bufp); break; case APA_DEVCTL_SET_OSDMBR: rv=devctlSetOsdMBR(f->unit, (hddSetOsdMBR_t *)arg); break; case APA_DEVCTL_GET_SECTOR_ERROR: rv=getPartErrorSector(f->unit, APA_SECTOR_SECTOR_ERROR, 0); break; case APA_DEVCTL_GET_ERROR_PART_NAME: rv=getPartErrorName(f->unit, (char *)bufp); break; case APA_DEVCTL_ATA_READ: rv=atadDmaTransfer(f->unit, (void *)bufp, ((hddAtaTransfer_t *)arg)->lba, ((hddAtaTransfer_t *)arg)->size, ATAD_MODE_READ); break; case APA_DEVCTL_ATA_WRITE: rv=atadDmaTransfer(f->unit, ((hddAtaTransfer_t *)arg)->data, ((hddAtaTransfer_t *)arg)->lba, ((hddAtaTransfer_t *)arg)->size, ATAD_MODE_WRITE); break; case APA_DEVCTL_SCE_IDENTIFY_DRIVE: rv=atadSceIdentifyDrive(f->unit, (u16 *)bufp); break; case APA_DEVCTL_IS_48BIT: rv=atadIs48bit(f->unit); break; case APA_DEVCTL_SET_TRANSFER_MODE: rv=atadSetTransferMode(f->unit, ((hddAtaSetMode_t *)arg)->type, ((hddAtaSetMode_t *)arg)->mode); break; case APA_DEVCTL_ATA_IOP_WRITE: rv=atadDmaTransfer(f->unit, ((hddAtaIOPTransfer_t *)arg)->data, ((hddAtaIOPTransfer_t *)arg)->lba, ((hddAtaIOPTransfer_t *)arg)->size, ATAD_MODE_WRITE); break; default: rv=-EINVAL; break; } SignalSema(fioSema); return rv; }
int hddIoctl2(iop_file_t *f, int req, void *argp, unsigned int arglen, void *bufp, unsigned int buflen) { u32 rv=0; hdd_file_slot_t *fileSlot=f->privdata; WaitSema(fioSema); switch(req) { // cmd set 1 case APA_IOCTL2_ADD_SUB: rv=ioctl2AddSub(fileSlot, (char *)argp); break; case APA_IOCTL2_DELETE_LAST_SUB: rv=ioctl2DeleteLastSub(fileSlot); break; case APA_IOCTL2_NUMBER_OF_SUBS: rv=fileSlot->nsub; break; case APA_IOCTL2_FLUSH_CACHE: atadFlushCache(f->unit); break; // cmd set 2 case APA_IOCTL2_TRANSFER_DATA: rv=ioctl2Transfer(f->unit, fileSlot, argp); break; case APA_IOCTL2_GETSIZE: // rv=fileSlot->subs[*(u32 *)argp].length; rv=((apa_subs *)(&fileSlot->start))[*(u32 *)argp].length; // !HACK! break; case APA_IOCTL2_GETHEADER: if(atadDmaTransfer(f->unit, bufp, fileSlot->start, sizeof(apa_header)/512, ATAD_MODE_READ)) rv=-EIO; rv=sizeof(apa_header); break; case APA_IOCTL2_SET_PART_ERROR: setPartErrorSector(f->unit, fileSlot->start); rv=0; break; case APA_IOCTL2_GET_PART_ERROR: if((rv=getPartErrorSector(f->unit, APA_SECTOR_PART_ERROR, bufp)) > 0) { if(*(u32 *)bufp==fileSlot->start) { rv=0; setPartErrorSector(f->unit, 0);// clear last error :) } } break; default: rv=-EINVAL; break; } SignalSema(fioSema); return rv; }
int hddFormat(iop_file_t *f, const char *dev, const char *blockdev, void *arg, size_t arglen) { int rv=0; apa_cache *clink; int i; input_param params; u32 emptyBlocks[32]; if(f->unit >= 2) return -ENXIO; // clear all errors on hdd clink=cacheGetFree(); memset(clink->header, 0, sizeof(apa_header)); if(atadDmaTransfer(f->unit, clink->header, APA_SECTOR_SECTOR_ERROR, 1, ATAD_MODE_WRITE)){ cacheAdd(clink); return -EIO; } if(atadDmaTransfer(f->unit, clink->header, APA_SECTOR_PART_ERROR, 1, ATAD_MODE_WRITE)){ cacheAdd(clink); return -EIO; } // clear apa headers for(i=1024*8;i<hddDeviceBuf[f->unit].totalLBA;i+=(1024*256)) { atadDmaTransfer(f->unit, clink->header, i, sizeof(apa_header)/512, ATAD_MODE_WRITE); } cacheAdd(clink); if((rv=journalReset(f->unit))!=0) return rv; // set up mbr :) if((clink=cacheGetHeader(f->unit, 0, 1, &rv))){ apa_header *header=clink->header; memset(header, 0, sizeof(apa_header)); header->magic=APA_MAGIC; header->length=(1024*256); // 128MB header->type=APA_TYPE_MBR; strcpy(header->id,"__mbr"); memcpy(header->mbr.magic, mbrMagic, 32); header->mbr.version=APA_MBR_VERSION; header->mbr.nsector=0; getPs2Time(&header->created); getPs2Time(&header->mbr.created); header->checksum=apaCheckSum(header); clink->flags|=CACHE_FLAG_DIRTY; cacheFlushDirty(clink); atadFlushCache(f->unit); cacheAdd(clink); hddDeviceBuf[f->unit].status=0; hddDeviceBuf[f->unit].format=APA_MBR_VERSION; } memset(&emptyBlocks, 0, sizeof(emptyBlocks)); memset(¶ms, 0, sizeof(input_param)); params.size=(1024*256); params.type=APA_TYPE_PFS; // add __net, __system.... for(i=0;formatPartList[i];i++) { memset(params.id, 0, APA_IDMAX); strcpy(params.id, formatPartList[i]); if(!(clink=apaAddPartitionHere(f->unit, ¶ms, emptyBlocks, i ? clink->sector : 0, &rv))) return rv; cacheAdd(clink); params.size<<=1; if(hddDeviceBuf[f->unit].partitionMaxSize < params.size) params.size=hddDeviceBuf[f->unit].partitionMaxSize; } return rv; }