DiskATA.CC refactor

This commit is contained in:
Void NV 2020-05-05 01:47:34 -05:00
parent 48f9e4c7d6
commit 948532f39e
4 changed files with 530 additions and 408 deletions

View File

@ -20,5 +20,7 @@ StartOS.CC
ZBlkDev/
Mount.CC
/Kernel/
BlkDev/
DiskATA.CC
$FG,7$-Tom$FG,0$

View File

@ -1,8 +1,20 @@
#define ATAPI_FORMAT_UNIT EndianU16(0x04)
#define ATAPI_START_STOP_UNIT EndianU16(0x1B)
#define ATAPI_READ_CAPACITY EndianU16(0x25)
#define ATAPI_SEEK EndianU16(0x2B)
#define ATAPI_SYNC_CACHE EndianU16(0x35)
#define ATAPI_READ_TRACK_INFO EndianU16(0x52)
#define ATAPI_CLOSE_TRACK_SESSION EndianU16(0x5B)
#define ATAPI_READ EndianU16(0xA8)
#define ATAPI_WRITE EndianU16(0xAA)
#define ATAPI_SET_CD_SPEED EndianU16(0xBB)
U0 ATABlkSel(CBlkDev *bd, I64 blk, I64 count)
{
if (bd->type != BDT_ATAPI && bd->base1)
OutU8(bd->base1 + ATAR1_CTRL, 0x8);
if (bd->flags & BDF_EXT_SIZE) { //48 Bit LBA?
if (bd->flags & BDF_EXT_SIZE)
{ //48 Bit LBA?
OutU8(bd->base0 + ATAR0_NSECT, count.u8[1]);
OutU8(bd->base0 + ATAR0_SECT, blk.u8[3]);
OutU8(bd->base0 + ATAR0_LCYL, blk.u8[4]);
@ -12,7 +24,9 @@ U0 ATABlkSel(CBlkDev *bd,I64 blk,I64 count)
OutU8(bd->base0 + ATAR0_LCYL, blk.u8[1]);
OutU8(bd->base0 + ATAR0_HCYL, blk.u8[2]);
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
} else { //28 Bit LBA
}
else
{ //28 Bit LBA
OutU8(bd->base0 + ATAR0_NSECT, count);
OutU8(bd->base0 + ATAR0_SECT, blk);
OutU8(bd->base0 + ATAR0_LCYL, blk.u8[1]);
@ -24,24 +38,28 @@ U0 ATABlkSel(CBlkDev *bd,I64 blk,I64 count)
Bool ATAWaitNotBUSY(CBlkDev *bd, F64 timeout)
{
I64 i;
do {
do
{
for (i = 0; i < 3; i++)
if (!(InU8(bd->base0 + ATAR0_STAT) & ATAS_BSY))
return TRUE;
Yield;
} while (!(0<timeout<tS));
}
while (!(0 < timeout < tS));
return FALSE;
}
Bool ATAWaitDRQ(CBlkDev *bd, F64 timeout)
{
I64 i;
do {
do
{
for (i = 0; i < 3; i++)
if (InU8(bd->base0 + ATAR0_STAT) & ATAS_DRQ)
return TRUE;
Yield;
} while (!(0<timeout<tS));
}
while (!(0 < timeout < tS));
return FALSE;
}
@ -51,6 +69,7 @@ Bool ATANop(CBlkDev *bd,F64 timeout)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_FEAT, 0);
OutU8(bd->base0 + ATAR0_CMD, ATA_NOP);
return ATAWaitNotBUSY(bd, timeout);
@ -64,32 +83,38 @@ U0 ATACmd(CBlkDev *bd,U8 cmd)
PortNop;
}
Bool ATAGetRes(CBlkDev *bd,F64 timeout,U8 *buf,I64 count,
I64 _avail,Bool one_read)
Bool ATAGetRes(CBlkDev *bd, F64 timeout, U8 *buf, I64 count, I64 _avail, Bool one_read)
{
I64 avail, overflow;
bd->flags &= ~BDF_LAST_WAS_WRITE;
MemSet(buf, 0, count);
while (count>0) {
while (count > 0)
{
if (!ATAWaitDRQ(bd, timeout))
return FALSE;
if (_avail)
avail = _avail;
else
avail = InU8(bd->base0 + ATAR0_HCYL) << 8 + InU8(bd->base0 + ATAR0_LCYL);
if (avail) {
if (avail>count) {
if (avail)
{
if (avail > count)
{
overflow = avail - count;
avail = count;
} else
}
else
overflow = 0;
if (avail & 2)
RepInU16(buf, avail >> 1, bd->base0 + ATAR0_DATA);
else
RepInU32(buf, avail >> 2, bd->base0 + ATAR0_DATA);
count -= avail;
buf += avail;
while (overflow>0) {
while (overflow > 0)
{
InU16(bd->base0 + ATAR0_DATA);
overflow -= 2;
if (0 < timeout < tS)
@ -97,7 +122,8 @@ Bool ATAGetRes(CBlkDev *bd,F64 timeout,U8 *buf,I64 count,
}
if (one_read)
break;
} else
}
else
Yield;
}
return ATAWaitNotBUSY(bd, timeout);
@ -106,9 +132,11 @@ Bool ATAGetRes(CBlkDev *bd,F64 timeout,U8 *buf,I64 count,
Bool ATAPIWritePacketWord(CBlkDev *bd, F64 timeout, ...)
{
I64 i;
for (i=0;i<argc;i++) {
for (i = 0; i < argc; i++)
{
if (!ATAWaitDRQ(bd, timeout))
return FALSE;
OutU16(bd->base0 + ATAR0_DATA, EndianU16(argv[i]));
bd->last_time = tS;
}
@ -121,10 +149,12 @@ Bool ATAPISetMaxSpeed(CBlkDev *bd)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, 0);
OutU8(bd->base0 + ATAR0_HCYL, 0);
ATACmd(bd, ATA_PACKET);
ATAPIWritePacketWord(bd,0,0xBB00,0xFFFF,0xFFFF,0,0,0);
ATAPIWritePacketWord(bd, 0, ATAPI_SET_CD_SPEED, 0xFFFF, 0xFFFF, 0, 0, 0);
return ATAWaitNotBUSY(bd, 0);
}
@ -134,10 +164,12 @@ Bool ATAPISeek(CBlkDev *bd,I64 native_blk)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, 0);
OutU8(bd->base0 + ATAR0_HCYL, 0);
ATACmd(bd, ATA_PACKET);
ATAPIWritePacketWord(bd,0,0x2B00,native_blk>>16,native_blk,0,0,0);
ATAPIWritePacketWord(bd, 0, ATAPI_SEEK, native_blk >> 16, native_blk, 0, 0, 0);
return ATAWaitNotBUSY(bd, 0);
}
@ -152,9 +184,10 @@ Bool ATAPIStartStop(CBlkDev *bd,F64 timeout,Bool start)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
ATACmd(bd, ATA_PACKET);
//Start/Stop
if (ATAPIWritePacketWord(bd,timeout,0x1B00,0,i,0,0,0))
if (ATAPIWritePacketWord(bd, timeout, ATAPI_START_STOP_UNIT, 0, i, 0, 0, 0))
return ATAWaitNotBUSY(bd, timeout);
else
return FALSE;
@ -164,27 +197,33 @@ I64 ATAGetDevId(CBlkDev *bd,F64 timeout,Bool keep_id_record)
{
I64 res = BDT_NULL;
U16 *id_record = NULL;
if (bd->type != BDT_ATAPI && bd->base1)
OutU8(bd->base1 + ATAR1_CTRL, 0x8);
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
ATACmd(bd, ATA_IDENTIFY);
if (ATAWaitNotBUSY(bd,timeout)) {
if (ATAWaitNotBUSY(bd, timeout))
{
if (InU8(bd->base0 + ATAR0_STAT) & ATAS_ERR)
res = BDT_ATAPI;
else {
else
{
id_record = ZCAlloc(512);
if (ATAGetRes(bd, timeout, id_record, 512, 512, FALSE))
res = BDT_ATA;
else {
else
{
Free(id_record);
id_record = NULL;
}
}
}
if (keep_id_record) {
if (keep_id_record)
{
Free(bd->dev_id_record);
bd->dev_id_record = id_record;
}
@ -195,16 +234,21 @@ I64 ATAReadNativeMax(CBlkDev *bd,F64 timeout)
{//Returns zero on error
I64 res = 0;
Bool okay = TRUE;
if (bd->type==BDT_ATAPI) {
if (bd->type == BDT_ATAPI)
{
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
ATACmd(bd, ATA_DEV_RST);
if (!ATAWaitNotBUSY(bd, 0))
okay = FALSE;
} else {
while (InU8(bd->base0+ATAR0_STAT) & ATAS_BSY) {
}
else
{
while (InU8(bd->base0 + ATAR0_STAT) & ATAS_BSY)
{
if (bd->flags & BDF_LAST_WAS_WRITE)
OutU16(bd->base0 + ATAR0_DATA, 0);
else
@ -218,12 +262,16 @@ I64 ATAReadNativeMax(CBlkDev *bd,F64 timeout)
else
BEqual(&bd->flags, BDf_EXT_SIZE, Bt(&bd->dev_id_record[86], 10));
}
if (okay) {
if (bd->flags & BDF_EXT_SIZE && bd->base1) {
if (okay)
{
if (bd->flags & BDF_EXT_SIZE && bd->base1)
{
OutU8(bd->base1 + ATAR1_CTRL, 0x8);
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
ATACmd(bd, ATA_READ_NATIVE_MAX_EXT);
if (ATAWaitNotBUSY(bd,timeout)) {
if (ATAWaitNotBUSY(bd, timeout))
{
res.u8[0] = InU8(bd->base0 + ATAR0_SECT);
res.u8[1] = InU8(bd->base0 + ATAR0_LCYL);
res.u8[2] = InU8(bd->base0 + ATAR0_HCYL);
@ -233,17 +281,21 @@ I64 ATAReadNativeMax(CBlkDev *bd,F64 timeout)
res.u8[4] = InU8(bd->base0 + ATAR0_LCYL);
res.u8[5] = InU8(bd->base0 + ATAR0_HCYL);
if (res>>24==res&0xFFFFFF) {//Kludge to make QEMU work
if (res >> 24 == res & 0xFFFFFF)
{//Kludge to make QEMU work
bd->flags &= ~BDF_EXT_SIZE;
res &= 0xFFFFFF;
}
}
} else {
}
else
{
if (bd->type != BDT_ATAPI && bd->base1)
OutU8(bd->base1 + ATAR1_CTRL, 0x8);
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
ATACmd(bd, ATA_READ_NATIVE_MAX);
if (ATAWaitNotBUSY(bd,timeout)) {
if (ATAWaitNotBUSY(bd, timeout))
{
res.u8[0] = InU8(bd->base0 + ATAR0_SECT);
res.u8[1] = InU8(bd->base0 + ATAR0_LCYL);
res.u8[2] = InU8(bd->base0 + ATAR0_HCYL);
@ -259,22 +311,29 @@ I64 ATAPIReadCapacity(CBlkDev *bd,I64 *_blk_size=NULL)
//Error might just be for music.
Bool unlock = BlkDevLock(bd);
U32 buf[2];
if (ATAWaitNotBUSY(bd,0)) {
if (ATAWaitNotBUSY(bd, 0))
{
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, 8);
OutU8(bd->base0 + ATAR0_HCYL, 0);
ATACmd(bd, ATA_PACKET);
ATAPIWritePacketWord(bd,0,0x2500,0,0,0,0,0);
ATAPIWritePacketWord(bd, 0, ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0);
if (!ATAGetRes(bd, 0, buf, 8, 0, TRUE))
buf[0] = buf[1] = 0;
} else
}
else
buf[0] = buf[1] = 0;
if (unlock) BlkDevUnlock(bd);
if (_blk_size) *_blk_size=EndianU32(buf[1]);
if (unlock)
BlkDevUnlock(bd);
if (_blk_size)
*_blk_size = EndianU32(buf[1]);
return EndianU32(buf[0]);
}
@ -282,25 +341,39 @@ CATAPITrack *ATAPIReadTrackInfo(CBlkDev *bd,I64 blk)
{
CATAPITrack *res = CAlloc(sizeof(CATAPITrack));
Bool unlock = BlkDevLock(bd);
if (ATAWaitNotBUSY(bd,0)) {
if (ATAWaitNotBUSY(bd, 0))
{
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, sizeof(CATAPITrack) & 0xFF);
OutU8(bd->base0 + ATAR0_HCYL, sizeof(CATAPITrack) >> 8);
ATACmd(bd, ATA_PACKET);
ATAPIWritePacketWord(bd,0,0x5200,blk.u16[1],blk.u16[0],
(sizeof(CATAPITrack)&0xFF00)>>8,(sizeof(CATAPITrack)&0x00FF)<<8,0);
if (!ATAGetRes(bd,0,res,sizeof(CATAPITrack),0,TRUE)) {
ATAPIWritePacketWord(bd,
0,
ATAPI_READ_TRACK_INFO,
blk.u16[1],
blk.u16[0],
(sizeof(CATAPITrack) & 0xFF00) >> 8,
(sizeof(CATAPITrack) & 0x00FF) << 8,
0);
if (!ATAGetRes(bd, 0, res, sizeof(CATAPITrack), 0, TRUE))
{
Free(res);
res = NULL;
}
} else {
}
else
{
Free(res);
res = NULL;
}
if (unlock) BlkDevUnlock(bd);
if (unlock)
BlkDevUnlock(bd);
return res;
}
@ -313,40 +386,47 @@ Bool ATAInit(CBlkDev *bd)
else
bd->flags |= BDF_EXT_SIZE;
if (ATAReadNativeMax(bd,tS+0.1)) {
if (ATAReadNativeMax(bd, tS + 0.1))
{
ATABlkSel(bd, bd->max_blk, 0);
if (bd->flags & BDF_EXT_SIZE)
ATACmd(bd, ATA_SET_MAX_EXT);
else
ATACmd(bd, ATA_SET_MAX);
if (ATAWaitNotBUSY(bd,0)) {
if (ATAWaitNotBUSY(bd, 0))
{
okay = TRUE;
if (bd->type==BDT_ATAPI) {
if (ATAPIStartStop(bd,0,TRUE)) {
if (bd->type == BDT_ATAPI)
{
if (ATAPIStartStop(bd, 0, TRUE))
{
if(!ATAPISetMaxSpeed(bd))
okay = FALSE;
} else
}
else
okay = FALSE;
}
}
}
if (unlock) BlkDevUnlock(bd);
if (unlock)
BlkDevUnlock(bd);
return okay;
}
Bool ATAPIWaitReady(CBlkDev *bd, F64 timeout)
{
do {
if (!ATAWaitNotBUSY(bd,timeout) ||
!ATANop(bd,timeout) ||
!ATAPIStartStop(bd,timeout,TRUE))
do
{
if (!ATAWaitNotBUSY(bd, timeout) || !ATANop(bd, timeout) || !ATAPIStartStop(bd, timeout, TRUE))
return FALSE;
if (InU8(bd->base0+ATAR0_STAT) & ATAS_DRDY &&
!InU8(bd->base0+ATAR0_FEAT));
if (InU8(bd->base0 + ATAR0_STAT) & ATAS_DRDY && !InU8(bd->base0 + ATAR0_FEAT));
return TRUE;
ATAInit(bd);
Yield;
} while (!(0<timeout<tS));
}
while (!(0 < timeout < tS));
return FALSE;
}
@ -361,16 +441,22 @@ U0 ATAReadBlks(CBlkDev *bd,U8 *buf, I64 blk, I64 count)
ATACmd(bd, ATA_READ_MULTI_EXT);
else
ATACmd(bd, ATA_READ_MULTI);
if (!ATAGetRes(bd,tS+1.0,buf,count*bd->blk_size,BLK_SIZE,FALSE)) {
if (retries--) {
if (!ATAGetRes(bd, tS + 1.0, buf, count * bd->blk_size, BLK_SIZE, FALSE))
{
if (retries--)
{
ATAWaitNotBUSY(bd, 0);
goto retry;
} else
}
else
throw('BlkDev');
}
blkdev.read_count += (count * bd->blk_size) >> BLK_SIZE_BITS;
if (unlock) BlkDevUnlock(bd);
if (unlock)
BlkDevUnlock(bd);
}
I64 ATAProbe(I64 base0, I64 base1, I64 unit)
@ -382,50 +468,57 @@ I64 ATAProbe(I64 base0,I64 base1,I64 unit)
bd.base1 = base1;
bd.unit = unit;
bd.blk_size = DVD_BLK_SIZE;
return ATAGetDevId(&bd, tS + 0.1, FALSE);
}
Bool ATAPIReadBlks2(CBlkDev *bd,F64 timeout,U8 *buf,
I64 native_blk, I64 count,Bool lock)
Bool ATAPIReadBlks2(CBlkDev *bd, F64 timeout, U8 *buf, I64 native_blk, I64 count, Bool lock)
{
Bool res = FALSE, unlock;
if (count <= 0)
return FALSE;
if (lock)
unlock = BlkDevLock(bd);
if (ATAPIWaitReady(bd,timeout)) {
if (ATAPIWaitReady(bd, timeout))
{
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, bd->blk_size);
OutU8(bd->base0 + ATAR0_HCYL, bd->blk_size.u8[1]);
ATACmd(bd, ATA_PACKET);
if (ATAPIWritePacketWord(bd,timeout,0xA800,
native_blk.u16[1],native_blk,count.u16[1],count,0) &&
ATAGetRes(bd,timeout,buf,count*bd->blk_size,0,FALSE)) {
if (ATAPIWritePacketWord(bd, timeout, ATAPI_READ, native_blk.u16[1], native_blk, count.u16[1], count, 0) &&
ATAGetRes(bd, timeout, buf, count * bd->blk_size, 0, FALSE))
{
blkdev.read_count += (count * bd->blk_size) >> BLK_SIZE_BITS;
res = TRUE;
}
}
// ATAPIStartStop(bd, 0, FALSE);
if (lock && unlock) BlkDevUnlock(bd);
if (lock && unlock)
BlkDevUnlock(bd);
return res;
}
U0 ATAPIReadBlks(CBlkDev *bd, U8 *buf, I64 blk, I64 count)
{
CDrive *drive = Letter2Drive(bd->first_drive_let);
I64 retry,spc=bd->blk_size>>BLK_SIZE_BITS,n,blk2,
l2=bd->max_reads<<1+spc<<1;
I64 retry,spc = bd->blk_size >> BLK_SIZE_BITS, n, blk2, l2 = bd->max_reads << 1 + spc << 1;
U8 *dvd_buf = MAlloc(l2 << BLK_SIZE_BITS);
if (count>0) {
if (count > 0)
{
if (blk <= bd->max_reads)
blk2 = 0;
else
blk2 = FloorU64(blk-bd->max_reads, spc);
if (blk2 + l2 > drive->size + drive->drv_offset)
l2 = drive->size + drive->drv_offset - blk2;
n = (l2 + spc - 1) / spc;
retry = 4;
@ -437,6 +530,7 @@ U0 ATAPIReadBlks(CBlkDev *bd,U8 *buf, I64 blk, I64 count)
ATAPIReadBlks2(bd, 0, dvd_buf, blk2 / spc, n, TRUE);
if (bd->flags & BDF_READ_CACHE)
DiskCacheAdd(drive, dvd_buf, blk2, n * spc);
MemCopy(buf, dvd_buf + (blk - blk2) << BLK_SIZE_BITS, count << BLK_SIZE_BITS);
}
Free(dvd_buf);
@ -446,14 +540,17 @@ Bool ATARBlks(CDrive *drive,U8 *buf, I64 blk, I64 count)
{
I64 n;
CBlkDev *bd = drive->bd;
while (count>0) {
while (count > 0)
{
n = count;
if (n > bd->max_reads)
n = bd->max_reads;
if (bd->type == BDT_ATAPI)
ATAPIReadBlks(bd, buf, blk, n);
else
ATAReadBlks(bd, buf, blk, n);
buf += n << BLK_SIZE_BITS;
blk += n;
count -= n;
@ -473,20 +570,28 @@ retry:
ATACmd(bd, ATA_WRITE_MULTI_EXT);
else
ATACmd(bd, ATA_WRITE_MULTI);
bd->flags |= BDF_LAST_WAS_WRITE;
while (count>0) {
while (count > 0)
{
timeout = tS + 1.0;
while (TRUE) {
while (TRUE)
{
i = InU8(bd->base0 + ATAR0_STAT);
if (!(i & ATAS_DRDY)||!(i & ATAS_DRQ)) {
if (!(i & ATAS_DRDY) || !(i & ATAS_DRQ))
{
Yield;
} else
}
else
break;
if (/* i&ATAS_ERR||*/ tS>timeout) {
if (retries--) {
if (/* i&ATAS_ERR||*/ tS > timeout)
{
if (retries--)
{
ATAWaitNotBUSY(bd, 0);
goto retry;
} else
}
else
throw('BlkDev');
}
}
@ -498,7 +603,8 @@ retry:
retries = 3;
}
ATAWaitNotBUSY(bd, 0);
if (unlock) BlkDevUnlock(bd);
if (unlock)
BlkDevUnlock(bd);
}
Bool ATAPISync(CBlkDev *bd)
@ -506,15 +612,18 @@ Bool ATAPISync(CBlkDev *bd)
Bool okay = TRUE;
if (!ATAWaitNotBUSY(bd, 0))
okay = FALSE;
else {
else
{
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, 0);
OutU8(bd->base0 + ATAR0_HCYL, 0);
ATACmd(bd, ATA_PACKET);
ATAPIWritePacketWord(bd,0,0x3500,0,0,0,0,0);
ATAPIWritePacketWord(bd, 0, ATAPI_SYNC_CACHE, 0, 0, 0, 0, 0);
if (!ATAWaitNotBUSY(bd, 0))
okay = FALSE;
}
@ -528,10 +637,12 @@ U0 ATAPIClose(CBlkDev *bd,I64 close_field=0x200,I64 track=0)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, 0);
OutU8(bd->base0 + ATAR0_HCYL, 0);
ATACmd(bd, ATA_PACKET);
ATAPIWritePacketWord(bd,0,0x5B00,close_field,track,0,0,0);
ATAPIWritePacketWord(bd, 0, ATAPI_CLOSE_TRACK_SESSION, close_field, track, 0, 0, 0);
ATAWaitNotBUSY(bd, 0);
}
@ -545,32 +656,39 @@ U0 ATAPIWriteBlks(CBlkDev *bd,U8 *buf, I64 native_blk, I64 count)
OutU8(bd->base0 + ATAR0_FEAT, 0);
OutU8(bd->base0 + ATAR0_LCYL, bd->blk_size);
OutU8(bd->base0 + ATAR0_HCYL, bd->blk_size.u8[1]);
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0+ATAR0_CMD,ATA_PACKET);
ATAPIWritePacketWord(bd,0,0x0400,native_blk.u16[1],native_blk,count.u16[1],count,0);
bd->flags|=BDF_LAST_WAS_WRITE;
ATAWaitNotBUSY(bd,0);
OutU8(bd->base0 + ATAR0_CMD, ATA_PACKET);
ATAPIWritePacketWord(bd, 0, ATAPI_FORMAT_UNIT, native_blk.u16[1], native_blk, count.u16[1], count, 0);
bd->flags |= BDF_LAST_WAS_WRITE;
ATAWaitNotBUSY(bd, 0);
ATAPISeek(bd, native_blk);
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, bd->blk_size);
OutU8(bd->base0 + ATAR0_HCYL, bd->blk_size.u8[1]);
ATACmd(bd, ATA_PACKET);
ATAPIWritePacketWord(bd,0,0xAA00,native_blk.u16[1],native_blk,count.u16[1],count,0);
ATAPIWritePacketWord(bd, 0, ATAPI_WRITE, native_blk.u16[1], native_blk, count.u16[1], count, 0);
buf2 = buf + bd->blk_size * count;
while (buf<buf2) {
while (buf < buf2)
{
ATAWaitDRQ(bd, 0);
U32s_avail = (InU8(bd->base0 + ATAR0_HCYL) << 8 + InU8(bd->base0 + ATAR0_LCYL)) >> 2;
if (buf + U32s_avail << 2 > buf2)
U32s_avail = (buf2-buf) >> 2;
if (U32s_avail) {
if (U32s_avail)
{
RepOutU32(buf, U32s_avail, bd->base0 + ATAR0_DATA);
buf += U32s_avail << 2;
blkdev.write_count += U32s_avail >> (BLK_SIZE_BITS - 2);
@ -585,27 +703,33 @@ Bool ATAWBlks(CDrive *drive,U8 *buf, I64 blk, I64 count)
CBlkDev *bd = drive->bd;
Bool unlock;
spc = bd->blk_size >> BLK_SIZE_BITS;
if (bd->type==BDT_ATAPI) {
if (bd->type == BDT_ATAPI)
{
unlock = BlkDevLock(bd);
ATAPIWaitReady(bd, 0);
}
while (count>0) {
while (count > 0)
{
n = count;
if (n > bd->max_writes)
n = bd->max_writes;
if (bd->type == BDT_ATAPI)
ATAPIWriteBlks(bd, buf, blk / spc, (n + spc - 1) / spc);
else
ATAWriteBlks(bd, buf, blk, n);
buf += n << BLK_SIZE_BITS;
blk += n;
count -= n;
blkdev.write_count += n;
}
if (bd->type==BDT_ATAPI) {
if (bd->type == BDT_ATAPI)
{
ATAPISync(bd);
// ATAPIStartStop(bd,0,FALSE);
if (unlock) BlkDevUnlock(bd);
if (unlock)
BlkDevUnlock(bd);
}
return TRUE;
}

View File

@ -17,9 +17,9 @@ public _intern IC_LBTR Bool LBtr(U8 *bit_field,I64 bit); //Locked bit test and r
public _intern IC_LBTS Bool LBts(U8 *bit_field,I64 bit); //Locked bit test and set to one.
public _intern IC_POPCNT I64 PopCount(I64 bit_field_val); //Count number of set bits in number.
public _extern _BEQUAL Bool BEqual(U8 *bit_field,I64 bit,Bool val);//Set bit equ to val.
public _extern _LBEQUAL Bool LBEqual(U8 *bit_field,I64 bit,Bool val); //Locked Set bit equ to val.
public _extern _BIT_FIELD_EXT_U32 U32 BFieldExtU32(U8 *bit_field,I64 bit,I64 size); //Extract U32 from bit field.
public _extern _BIT_FIELD_OR_U32 U0 BFieldOrU32(U8 *bit_field,I64 bit,U32 pattern); //Or U32 into bit field.
public _extern _LBEQUAL Bool LBEqual(U8 *bit_field,I64 bit,Bool val); //Locked Set bit equ to val.
#help_index "Boot"
_extern MEM_BOOT_BASE U32 mem_boot_base;
@ -30,17 +30,13 @@ _extern SYS_RUN_LEVEL U32 sys_run_level;
#help_index "Call"
public _extern _CALL I64 Call(U8 *machine_code); //Call addr with no args.
public _extern _CALLEXTSTR I64 CallExtStr(
/*argpop*/ U8 *name,...); //Search sym table for fun and pass it args.
public _extern _CALLEXTSTR I64 CallExtStr(/*argpop*/ U8 *name,...); //Search sym table for fun and pass it args.
//Can have any fixed number of arguments.
public _extern _CALL_IND I64 CallInd(
/*argpop*/I64 (*fp_addr)(...),...); //Call with fixed number of args.
public _extern _CALL_IND I64 CallInd(/*argpop*/I64 (*fp_addr)(...),...); //Call with fixed number of args.
#help_index "Call/System Extern Num"
public _extern SYS_EXTERN_TABLE /*argpop*/
I64 (**ext)(...); //Array of fun ptrs. See $LK,"Extern Num Definitions",A="MN:EXT_EXTS_NUM"$
public _extern _CALLEXTNUM
I64 CallExtNum(I64 num,...); //Call ext num with fixed number of args.
public _extern SYS_EXTERN_TABLE /*argpop*/I64 (**ext)(...); //Array of fun ptrs. See $LK,"Extern Num Definitions",A="MN:EXT_EXTS_NUM"$
public _extern _CALLEXTNUM I64 CallExtNum(I64 num,...); //Call ext num with fixed number of args.
#help_index "Char/Conversion"
public _intern IC_TOUPPER I64 ToUpper(U8 ch); //Convert char to upper case.