SparrowOSTS_121127.ISO
This commit is contained in:
1 parent
0e9364ff4c
commit
e57428affb
1218 files changed
+247142
-165507
No files matched your search
@@ -0,0 +1,655 @@
|
||||
U0 ATABlkSelect(CBlkDev *bdev,I64 blk,I64 cnt)
|
||||
{
|
||||
if (bdev->type!=BDT_ATAPI && bdev->base1)
|
||||
OutU8(bdev->base1+ATAR1_CTRL,0x8);
|
||||
if (bdev->flags & BDF_EXT_SIZE) {
|
||||
OutU8(bdev->base0+ATAR0_NSECT,cnt.u8[1]);
|
||||
OutU8(bdev->base0+ATAR0_SECT,blk.u8[3]);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[4]);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[5]);
|
||||
OutU8(bdev->base0+ATAR0_NSECT,cnt);
|
||||
OutU8(bdev->base0+ATAR0_SECT,blk);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[1]);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[2]);
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
} else {
|
||||
OutU8(bdev->base0+ATAR0_NSECT,cnt);
|
||||
OutU8(bdev->base0+ATAR0_SECT,blk);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[1]);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[2]);
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4|blk.u8[3]);
|
||||
}
|
||||
}
|
||||
|
||||
Bool ATAWaitNotBUSY(CBlkDev *bdev,F64 timeout)
|
||||
{
|
||||
while (TRUE) {
|
||||
if (timeout && tS>timeout)
|
||||
return FALSE;
|
||||
if (InU8(bdev->base0+ATAR0_STAT)&ATAS_BSY)
|
||||
Yield;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Bool ATAWaitDRQ(CBlkDev *bdev,F64 timeout)
|
||||
{
|
||||
while (TRUE) {
|
||||
if (timeout && tS>timeout)
|
||||
return FALSE;
|
||||
if (!(InU8(bdev->base0+ATAR0_STAT)&ATAS_DRQ))
|
||||
Yield;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Bool ATANop(CBlkDev *bdev,F64 timeout)
|
||||
{
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
OutU8(bdev->base0+ATAR0_FEAT,0);
|
||||
OutU8(bdev->base0+ATAR0_CMD,ATA_NOP);
|
||||
return ATAWaitNotBUSY(bdev,timeout);
|
||||
}
|
||||
|
||||
U0 ATACmd(CBlkDev *bdev,U8 cmd)
|
||||
{
|
||||
OutU8(bdev->base0+ATAR0_FEAT,0);
|
||||
OutU8(bdev->base0+ATAR0_CMD,cmd);
|
||||
bdev->last_time=tS;
|
||||
PortNop;
|
||||
}
|
||||
|
||||
Bool ATAGetResult(CBlkDev *bdev,U8 *buf,I64 cnt,I64 _avail,Bool one_read,F64 timeout=0)
|
||||
{
|
||||
I64 avail,overflow;
|
||||
bdev->flags&=~BDF_LAST_WAS_WRITE;
|
||||
MemSet(buf,0,cnt);
|
||||
while (cnt>0) {
|
||||
if (!ATAWaitDRQ(bdev,timeout))
|
||||
return FALSE;
|
||||
if (_avail)
|
||||
avail=_avail;
|
||||
else
|
||||
avail=InU8(bdev->base0+ATAR0_HCYL)<<8+InU8(bdev->base0+ATAR0_LCYL);
|
||||
if (avail) {
|
||||
if (avail>cnt) {
|
||||
overflow=avail-cnt;
|
||||
avail=cnt;
|
||||
} else
|
||||
overflow=0;
|
||||
if (avail&2)
|
||||
RepInU16(buf,avail>>1,bdev->base0+ATAR0_DATA);
|
||||
else
|
||||
RepInU32(buf,avail>>2,bdev->base0+ATAR0_DATA);
|
||||
cnt-=avail;
|
||||
buf+=avail;
|
||||
while (overflow>0) {
|
||||
if (timeout && tS>timeout)
|
||||
return FALSE;
|
||||
InU16(bdev->base0+ATAR0_DATA);
|
||||
overflow-=2;
|
||||
}
|
||||
if (one_read)
|
||||
break;
|
||||
} else
|
||||
Yield;
|
||||
}
|
||||
return ATAWaitNotBUSY(bdev,timeout);
|
||||
}
|
||||
|
||||
Bool ATAPIWritePktWord(CBlkDev *bdev,U16 w,F64 timeout=0)
|
||||
{
|
||||
if (!ATAWaitDRQ(bdev,timeout))
|
||||
return FALSE;
|
||||
OutU16(bdev->base0+ATAR0_DATA,EndianU16(w));
|
||||
bdev->last_time=tS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool ATAPISetMaxSpeed(CBlkDev *bdev)
|
||||
{
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,0);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,0);
|
||||
ATACmd(bdev,ATA_PACKET);
|
||||
ATAPIWritePktWord(bdev,0xBB00); //Set speed
|
||||
ATAPIWritePktWord(bdev,0xFFFF); //read at max
|
||||
ATAPIWritePktWord(bdev,0xFFFF); //write at max
|
||||
ATAPIWritePktWord(bdev,0);
|
||||
ATAPIWritePktWord(bdev,0);
|
||||
ATAPIWritePktWord(bdev,0);
|
||||
return ATAWaitNotBUSY(bdev,0);
|
||||
}
|
||||
|
||||
|
||||
Bool ATAPISeek(CBlkDev *bdev,I64 native_blk)
|
||||
{
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,0);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,0);
|
||||
ATACmd(bdev,ATA_PACKET);
|
||||
ATAPIWritePktWord(bdev,0x2B00); //Seek
|
||||
ATAPIWritePktWord(bdev,native_blk>>16);
|
||||
ATAPIWritePktWord(bdev,native_blk);
|
||||
ATAPIWritePktWord(bdev,0);
|
||||
ATAPIWritePktWord(bdev,0);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
return ATAWaitNotBUSY(bdev,0);
|
||||
}
|
||||
|
||||
Bool ATAPIStartStop(CBlkDev *bdev,Bool start,F64 timeout)
|
||||
{
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
ATACmd(bdev,ATA_PACKET);
|
||||
|
||||
//Start/Stop
|
||||
if (!ATAPIWritePktWord(bdev,0x1B00,timeout)) return FALSE;
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
|
||||
if (start) {
|
||||
if (!ATAPIWritePktWord(bdev,0x0100,timeout)) return FALSE;
|
||||
} else {
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
|
||||
}
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
|
||||
return ATAWaitNotBUSY(bdev,timeout);
|
||||
}
|
||||
|
||||
I64 ATAGetDevId(CBlkDev *bdev,U16 **_id_record,F64 timeout)
|
||||
{
|
||||
U16 *id_record;
|
||||
if (_id_record) *_id_record=NULL;
|
||||
if (bdev->type!=BDT_ATAPI && bdev->base1)
|
||||
OutU8(bdev->base1+ATAR1_CTRL,0x8);
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
ATACmd(bdev,ATA_ID_DEV);
|
||||
if (!ATAWaitNotBUSY(bdev,timeout))
|
||||
return BDT_NULL;
|
||||
if (InU8(bdev->base0+ATAR0_STAT)&ATAS_ERR)
|
||||
return BDT_ATAPI;
|
||||
id_record=ACAlloc(512);
|
||||
if (!ATAGetResult(bdev,id_record,512,512,FALSE,timeout)) {
|
||||
Free(id_record);
|
||||
return BDT_NULL;
|
||||
}
|
||||
if (_id_record) *_id_record=id_record;
|
||||
return BDT_ATA;
|
||||
}
|
||||
|
||||
I64 ATAReadNativeMax(CBlkDev *bdev)
|
||||
{ //returns zero on err
|
||||
I64 blk=0;
|
||||
Bool okay=TRUE;
|
||||
|
||||
if (bdev->type==BDT_ATAPI) {
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
ATACmd(bdev,ATA_DEV_RST);
|
||||
if (!ATAWaitNotBUSY(bdev,0))
|
||||
okay=FALSE;
|
||||
} else {
|
||||
while (InU8(bdev->base0+ATAR0_STAT) & ATAS_BSY) {
|
||||
if (bdev->flags&BDF_LAST_WAS_WRITE)
|
||||
OutU16(bdev->base0+ATAR0_DATA,0);
|
||||
else
|
||||
InU16(bdev->base0+ATAR0_DATA);
|
||||
Yield;
|
||||
}
|
||||
|
||||
Free(bdev->dev_id_record);
|
||||
if (ATAGetDevId(bdev,&bdev->dev_id_record,0)==BDT_NULL)
|
||||
okay=FALSE;
|
||||
else
|
||||
BEqu(&bdev->flags,BDf_EXT_SIZE,Bt(&bdev->dev_id_record[86],10));
|
||||
}
|
||||
if (okay) {
|
||||
if (bdev->flags & BDF_EXT_SIZE && bdev->base1) {
|
||||
OutU8(bdev->base1+ATAR1_CTRL,0x8);
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
ATACmd(bdev,ATA_READ_NATIVE_MAX_EXT);
|
||||
if (ATAWaitNotBUSY(bdev,0)) {
|
||||
blk.u8[0]=InU8(bdev->base0+ATAR0_SECT);
|
||||
blk.u8[1]=InU8(bdev->base0+ATAR0_LCYL);
|
||||
blk.u8[2]=InU8(bdev->base0+ATAR0_HCYL);
|
||||
|
||||
OutU8(bdev->base1+ATAR1_CTRL,0x80);
|
||||
blk.u8[3]=InU8(bdev->base0+ATAR0_SECT);
|
||||
blk.u8[4]=InU8(bdev->base0+ATAR0_LCYL);
|
||||
blk.u8[5]=InU8(bdev->base0+ATAR0_HCYL);
|
||||
|
||||
if (blk>>24==blk&0xFFFFFF) {//Kludge to make qemu-kvm work
|
||||
Btr(&bdev->flags,BDf_EXT_SIZE);
|
||||
blk&=0xFFFFFF;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (bdev->type!=BDT_ATAPI && bdev->base1)
|
||||
OutU8(bdev->base1+ATAR1_CTRL,0x8);
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
ATACmd(bdev,ATA_READ_NATIVE_MAX);
|
||||
if (ATAWaitNotBUSY(bdev,0)) {
|
||||
blk.u8[0]=InU8(bdev->base0+ATAR0_SECT);
|
||||
blk.u8[1]=InU8(bdev->base0+ATAR0_LCYL);
|
||||
blk.u8[2]=InU8(bdev->base0+ATAR0_HCYL);
|
||||
blk.u8[3]=InU8(bdev->base0+ATAR0_SELECT) & 0xF;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bdev->max_blk=blk;
|
||||
}
|
||||
|
||||
I64 ATAPIReadCapacity(CBlkDev *bdev,I64 *_blk_size=NULL)
|
||||
{ //Supposedly this can return a result +/- 75 sects.
|
||||
//Error might just be for music.
|
||||
Bool unlock=BlkDevLock(bdev);
|
||||
U32 buf[2];
|
||||
if (ATAWaitNotBUSY(bdev,0)) {
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,8);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,0);
|
||||
ATACmd(bdev,ATA_PACKET);
|
||||
ATAPIWritePktWord(bdev,0x2500); //Read Capacity
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
if (!ATAGetResult(bdev,buf,8,0,TRUE))
|
||||
buf[0]=buf[1]=0;
|
||||
} else
|
||||
buf[0]=buf[1]=0;
|
||||
|
||||
if (unlock) BlkDevUnlock(bdev);
|
||||
if (_blk_size) *_blk_size=EndianU32(buf[1]);
|
||||
return EndianU32(buf[0]);
|
||||
}
|
||||
|
||||
CATAPITrack *ATAPIReadTrackInfo(CBlkDev *bdev,I64 blk)
|
||||
{
|
||||
CATAPITrack *result=CAlloc(sizeof(CATAPITrack));
|
||||
Bool unlock=BlkDevLock(bdev);
|
||||
if (ATAWaitNotBUSY(bdev,0)) {
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,sizeof(CATAPITrack)&0xFF);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,sizeof(CATAPITrack)>>8);
|
||||
ATACmd(bdev,ATA_PACKET);
|
||||
ATAPIWritePktWord(bdev,0x5200); //Read Track Info
|
||||
ATAPIWritePktWord(bdev,blk.u16[1]);
|
||||
ATAPIWritePktWord(bdev,blk.u16[0]);
|
||||
ATAPIWritePktWord(bdev,(sizeof(CATAPITrack)&0xFF00)>>8);
|
||||
ATAPIWritePktWord(bdev,(sizeof(CATAPITrack)&0x00FF)<<8);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
if (!ATAGetResult(bdev,result,sizeof(CATAPITrack),0,TRUE)) {
|
||||
Free(result);
|
||||
result=NULL;
|
||||
}
|
||||
} else {
|
||||
Free(result);
|
||||
result=NULL;
|
||||
}
|
||||
if (unlock) BlkDevUnlock(bdev);
|
||||
return result;
|
||||
}
|
||||
|
||||
Bool ATAInit(CBlkDev *bdev)
|
||||
{
|
||||
Bool unlock=BlkDevLock(bdev),okay=FALSE;
|
||||
|
||||
if (bdev->type==BDT_ATAPI)
|
||||
bdev->flags&=~BDF_EXT_SIZE;
|
||||
else
|
||||
bdev->flags|=BDF_EXT_SIZE;
|
||||
|
||||
if (ATAReadNativeMax(bdev)) {
|
||||
|
||||
ATABlkSelect(bdev,bdev->max_blk,0);
|
||||
if (bdev->flags&BDF_EXT_SIZE)
|
||||
ATACmd(bdev,ATA_SET_MAX_EXT);
|
||||
else
|
||||
ATACmd(bdev,ATA_SET_MAX);
|
||||
if (ATAWaitNotBUSY(bdev,0)) {
|
||||
okay=TRUE;
|
||||
if (bdev->type==BDT_ATAPI) {
|
||||
if (ATAPIStartStop(bdev,TRUE,0)) {
|
||||
if(!ATAPISetMaxSpeed(bdev))
|
||||
okay=FALSE;
|
||||
} else
|
||||
okay=FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unlock) BlkDevUnlock(bdev);
|
||||
return okay;
|
||||
}
|
||||
|
||||
Bool ATAPIWaitReady(CBlkDev *bdev,F64 timeout)
|
||||
{
|
||||
while (TRUE) {
|
||||
if (!ATAWaitNotBUSY(bdev,timeout) ||
|
||||
!ATANop(bdev,timeout) ||
|
||||
!ATAPIStartStop(bdev,TRUE,timeout))
|
||||
return FALSE;
|
||||
if (InU8(bdev->base0+ATAR0_STAT) & ATAS_DRDY &&
|
||||
!InU8(bdev->base0+ATAR0_FEAT));
|
||||
return TRUE;
|
||||
if (timeout && tS>timeout)
|
||||
return FALSE;
|
||||
ATAInit(bdev);
|
||||
Yield;
|
||||
}
|
||||
}
|
||||
|
||||
U0 ATAReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
|
||||
{
|
||||
I64 retries=3;
|
||||
Bool unlock=BlkDevLock(bdev);
|
||||
|
||||
retry:
|
||||
ATABlkSelect(bdev,blk,cnt);
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
ATACmd(bdev,ATA_READ_MULTI_EXT);
|
||||
else
|
||||
ATACmd(bdev,ATA_READ_MULTI);
|
||||
if (!ATAGetResult(bdev,buf,cnt*bdev->blk_size,BLK_SIZE,FALSE,tS+1.0)) {
|
||||
if (retries--) {
|
||||
ATAWaitNotBUSY(bdev,0);
|
||||
goto retry;
|
||||
} else
|
||||
throw(EXCEPT_BLKDEV,6);
|
||||
}
|
||||
|
||||
sys_dsk_reads+=(cnt*bdev->blk_size)>>BLK_SIZE_BITS;
|
||||
if (unlock) BlkDevUnlock(bdev);
|
||||
}
|
||||
|
||||
I64 ATAProbe(I64 base0,I64 base1,I64 unit)
|
||||
{
|
||||
CBlkDev bdev;
|
||||
MemSet(&bdev,0,sizeof(CBlkDev));
|
||||
bdev.type=BDT_ATAPI;
|
||||
bdev.base0=base0;
|
||||
bdev.base1=base1;
|
||||
bdev.unit=unit;
|
||||
bdev.blk_size=CD_BLK_SIZE;
|
||||
return ATAGetDevId(&bdev,NULL,tS+0.1);
|
||||
}
|
||||
|
||||
Bool ATAPIReadBlks2(CBlkDev *bdev,U8 *buf, I64 native_blk, I64 cnt,Bool lock,F64 timeout)
|
||||
{
|
||||
Bool result,unlock;
|
||||
if (cnt<=0)
|
||||
return FALSE;
|
||||
if (lock)
|
||||
unlock=BlkDevLock(bdev);
|
||||
if (!ATAPIWaitReady(bdev,timeout)) goto arb_false_done;
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
|
||||
ATACmd(bdev,ATA_PACKET);
|
||||
if (!ATAPIWritePktWord(bdev,0xA800,timeout)) goto arb_false_done;
|
||||
if (!ATAPIWritePktWord(bdev,native_blk.u16[1],timeout)) goto arb_false_done;
|
||||
if (!ATAPIWritePktWord(bdev,native_blk,timeout)) goto arb_false_done;
|
||||
if (!ATAPIWritePktWord(bdev,cnt.u16[1],timeout)) goto arb_false_done;
|
||||
if (!ATAPIWritePktWord(bdev,cnt,timeout)) goto arb_false_done;
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) goto arb_false_done;
|
||||
if (!ATAGetResult(bdev,buf,cnt*bdev->blk_size,0,FALSE,timeout)) {
|
||||
arb_false_done:
|
||||
result=FALSE;
|
||||
} else {
|
||||
sys_dsk_reads+=(cnt*bdev->blk_size)>>BLK_SIZE_BITS;
|
||||
result=TRUE;
|
||||
}
|
||||
// ATAPIStartStop(bdev,FALSE,0);
|
||||
if (lock && unlock) BlkDevUnlock(bdev);
|
||||
return result;
|
||||
}
|
||||
|
||||
U0 ATAPIReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
|
||||
{
|
||||
CPrt *p=Drv2Prt(bdev->drv_let_base);
|
||||
I64 retry,spc=bdev->blk_size>>BLK_SIZE_BITS,n,blk2,
|
||||
l2=bdev->max_reads<<1+spc<<1;
|
||||
U8 *cd_buf=MAlloc(l2<<BLK_SIZE_BITS);
|
||||
if (cnt>0) {
|
||||
if (blk<=bdev->max_reads)
|
||||
blk2=0;
|
||||
else
|
||||
blk2=FloorU64(blk-bdev->max_reads,spc);
|
||||
if (blk2+l2>p->size)
|
||||
l2=p->size-blk2;
|
||||
n=(l2+spc-1)/spc;
|
||||
|
||||
retry=4;
|
||||
while (--retry)
|
||||
if (ATAPIReadBlks2(bdev,cd_buf,blk2/spc,n,TRUE,
|
||||
//n is 0x800 if max_reads. Up to 8 additional seconds
|
||||
tS+7.0+0.004*n))
|
||||
break;
|
||||
if (!retry)
|
||||
ATAPIReadBlks2(bdev,cd_buf,blk2/spc,n,TRUE,0);
|
||||
if (bdev->flags & BDF_READ_CACHE)
|
||||
DskCacheAdd(p,cd_buf,blk2,n*spc);
|
||||
MemCpy(buf,cd_buf+(blk-blk2)<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
|
||||
}
|
||||
Free(cd_buf);
|
||||
}
|
||||
|
||||
U0 ATARBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
|
||||
{
|
||||
I64 n;
|
||||
CBlkDev *bdev=p->bdev;
|
||||
BlkDevChk(bdev);
|
||||
while (cnt>0) {
|
||||
n=cnt;
|
||||
if (n>bdev->max_reads)
|
||||
n=bdev->max_reads;
|
||||
if (bdev->type==BDT_ATAPI)
|
||||
ATAPIReadBlks(bdev,buf,blk,n);
|
||||
else
|
||||
ATAReadBlks(bdev,buf,blk,n);
|
||||
buf+=n<<BLK_SIZE_BITS;
|
||||
blk+=n;
|
||||
cnt-=n;
|
||||
}
|
||||
}
|
||||
|
||||
//This is for low level disk access
|
||||
//Call WBlks() instead
|
||||
U0 ATAWriteBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
|
||||
{
|
||||
I64 i,U32s_avail,sects_avail,retries=3;
|
||||
F64 timeout;
|
||||
Bool unlock=BlkDevLock(bdev);
|
||||
retry:
|
||||
ATABlkSelect(bdev,blk,cnt);
|
||||
if (bdev->flags&BDF_EXT_SIZE)
|
||||
ATACmd(bdev,ATA_WRITE_MULTI_EXT);
|
||||
else
|
||||
ATACmd(bdev,ATA_WRITE_MULTI);
|
||||
bdev->flags|=BDF_LAST_WAS_WRITE;
|
||||
while (cnt>0) {
|
||||
timeout=tS+1.0;
|
||||
while (TRUE) {
|
||||
i=InU8(bdev->base0+ATAR0_STAT);
|
||||
if (!(i & ATAS_DRDY)||!(i & ATAS_DRQ)) {
|
||||
Yield;
|
||||
} else
|
||||
break;
|
||||
if (/* i&ATAS_ERR||*/ tS>timeout) {
|
||||
if (retries--) {
|
||||
ATAWaitNotBUSY(bdev,0);
|
||||
goto retry;
|
||||
} else
|
||||
throw(EXCEPT_BLKDEV,7);
|
||||
}
|
||||
}
|
||||
sects_avail=1;
|
||||
U32s_avail=sects_avail<<BLK_SIZE_BITS>>2;
|
||||
RepOutU32(buf,U32s_avail,bdev->base0+ATAR0_DATA);
|
||||
buf+=U32s_avail<<2;
|
||||
cnt-=sects_avail;
|
||||
retries=3;
|
||||
}
|
||||
ATAWaitNotBUSY(bdev,0);
|
||||
if (unlock) BlkDevUnlock(bdev);
|
||||
}
|
||||
|
||||
Bool ATAPISync(CBlkDev *bdev)
|
||||
{
|
||||
Bool okay=TRUE;
|
||||
if (!ATAWaitNotBUSY(bdev,0))
|
||||
okay=FALSE;
|
||||
else {
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,0);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,0);
|
||||
ATACmd(bdev,ATA_PACKET);
|
||||
ATAPIWritePktWord(bdev,0x3500); //Sync
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
if (!ATAWaitNotBUSY(bdev,0))
|
||||
okay=FALSE;
|
||||
}
|
||||
return okay;
|
||||
}
|
||||
|
||||
U0 ATAPIClose(CBlkDev *bdev,I64 close_field=0x200,I64 track=0)
|
||||
{
|
||||
//0x200 CD/DVD part 1
|
||||
//0x300 DVD part 2
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,0);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,0);
|
||||
ATACmd(bdev,ATA_PACKET);
|
||||
ATAPIWritePktWord(bdev,0x5B00); //Close
|
||||
ATAPIWritePktWord(bdev,close_field);
|
||||
ATAPIWritePktWord(bdev,track);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAWaitNotBUSY(bdev,0);
|
||||
}
|
||||
|
||||
U0 ATAPIWriteBlks(CBlkDev *bdev,U8 *buf, I64 native_blk, I64 cnt)
|
||||
{
|
||||
I64 U32s_avail;
|
||||
U8 *buf2;
|
||||
ATAWaitNotBUSY(bdev,0);
|
||||
ATAPISeek(bdev,native_blk);
|
||||
|
||||
OutU8(bdev->base0+ATAR0_FEAT,0);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
OutU8(bdev->base0+ATAR0_CMD,ATA_PACKET);
|
||||
ATAPIWritePktWord(bdev,0x0400); //FMT
|
||||
ATAPIWritePktWord(bdev,native_blk.u16[1]);
|
||||
ATAPIWritePktWord(bdev,native_blk);
|
||||
ATAPIWritePktWord(bdev,cnt.u16[1]);
|
||||
ATAPIWritePktWord(bdev,cnt);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
bdev->flags|=BDF_LAST_WAS_WRITE;
|
||||
ATAWaitNotBUSY(bdev,0);
|
||||
|
||||
ATAPISeek(bdev,native_blk);
|
||||
|
||||
if (bdev->flags & BDF_EXT_SIZE)
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
|
||||
else
|
||||
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
|
||||
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
|
||||
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
|
||||
ATACmd(bdev,ATA_PACKET);
|
||||
ATAPIWritePktWord(bdev,0xAA00); //Write
|
||||
ATAPIWritePktWord(bdev,native_blk.u16[1]);
|
||||
ATAPIWritePktWord(bdev,native_blk);
|
||||
ATAPIWritePktWord(bdev,cnt.u16[1]);
|
||||
ATAPIWritePktWord(bdev,cnt);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
buf2=buf+bdev->blk_size*cnt;
|
||||
while (buf<buf2) {
|
||||
ATAWaitDRQ(bdev,0);
|
||||
U32s_avail=(InU8(bdev->base0+ATAR0_HCYL)<<8+InU8(bdev->base0+ATAR0_LCYL))>>2;
|
||||
if (buf+U32s_avail<<2>buf2)
|
||||
U32s_avail=(buf2-buf)>>2;
|
||||
if (U32s_avail) {
|
||||
RepOutU32(buf,U32s_avail,bdev->base0+ATAR0_DATA);
|
||||
buf+=U32s_avail<<2;
|
||||
sys_dsk_writes+=U32s_avail>>(BLK_SIZE_BITS-2);
|
||||
}
|
||||
}
|
||||
ATAWaitNotBUSY(bdev,0);
|
||||
}
|
||||
|
||||
U0 ATAWBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
|
||||
{
|
||||
I64 n,spc;
|
||||
CBlkDev *bdev=p->bdev;
|
||||
Bool unlock;
|
||||
BlkDevChk(bdev);
|
||||
spc=bdev->blk_size>>BLK_SIZE_BITS;
|
||||
if (bdev->type==BDT_ATAPI) {
|
||||
unlock=BlkDevLock(bdev);
|
||||
ATAPIWaitReady(bdev,0);
|
||||
}
|
||||
while (cnt>0) {
|
||||
n=cnt;
|
||||
if (n>bdev->max_writes)
|
||||
n=bdev->max_writes;
|
||||
if (bdev->type==BDT_ATAPI)
|
||||
ATAPIWriteBlks(bdev,buf,blk/spc,(n+spc-1)/spc);
|
||||
else
|
||||
ATAWriteBlks(bdev,buf,blk,n);
|
||||
buf+=n<<BLK_SIZE_BITS;
|
||||
blk+=n;
|
||||
cnt-=n;
|
||||
sys_dsk_writes+=n;
|
||||
}
|
||||
if (bdev->type==BDT_ATAPI) {
|
||||
ATAPISync(bdev);
|
||||
// ATAPIStartStop(bdev,FALSE,0);
|
||||
if (unlock) BlkDevUnlock(bdev);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user