📄 biosial.c
字号:
if((lowLBAAddress + ax.parts.lval) >
sataAdapter.channelsInfo[channelIndex].diskSize[PMPort])
{
#ifdef DEBUG_IAL
printHexSingle ("LBA OOR Lo",(lowLBAAddress) & 0xffff);
printHexSingle ("LBA OOR Hi",((lowLBAAddress)>>16) & 0xffff);
#endif
flags |= 0x1;
ax.parts.lval = 0x4;
break;
}
#ifdef DEBUG_IAL
if(printAll == MV_TRUE)
{
printHexSingle ("LBA Low",lowLBAAddress);
printHexSingle ("LBA Hi",lowLBAAddress >> 16);
printHexSingle ("Sec Count", ax.parts.lval);
printHexSingle ("Buff Seg",es);
printHexSingle ("Buff off",bx.val);
}
#endif
/*
* If SP < 0x200, then probably when calling requestIO it's going
* to overflow. Add 0x200 to stack pointer and bp and substitute
* 0x20 from the stack segment. This is the same from the int13
* handler point of view, but when going back with iret the
* stack pointer, bp and stack segment must be returned to it's
* previous value.
*/
if(sp.val < 0x200)
{
incrementSP = MV_TRUE;
_asm {
push si
add sp, 0x200
add bp, 0x200
mov si, ss
sub si, 0x20
mov ss, si
pop si
}
#ifdef DEBUG_IAL
printHexSingle ("Stack WO",sp.val);
#endif
}
ax.parts.hval = requestIO (channelIndex, PMPort,
lowLBAAddress, 0,
ax.parts.lval,
(ax.parts.hval == 0x2) ? MV_UDMA_TYPE_READ : MV_UDMA_TYPE_WRITE,
es, bx.val);
/* Revert sp, bp and ss to it's previous value */
if(incrementSP == MV_TRUE)
{
_asm {
push si
sub sp, 0x200
sub bp, 0x200
mov si, ss
add si, 0x20
mov ss, si
pop si
}
#ifdef DEBUG_IAL
printHexSingle ("StackB",sp.val);
#endif
}
if(ax.parts.hval != 0x0)
{
#ifdef DEBUG_IAL
printAll = MV_TRUE;
printHexSingle ("UDMA comp Err",ax.parts.hval);
#endif
if(mvStorageDevATASoftResetDevice(&sataAdapter.mvSataAdapter,
channelIndex, PMPort, 0) ==
MV_FALSE)
{
#ifdef DEBUG_IAL
printHexSingle ("Softrst Err",ax.parts.hval);
#endif
}
flags |= 0x1;
}
/*
* Revert the Request Queue hi base address to it's value that is
* set in initializeDriver
*/
if((channelIndex == 0) && (useIoBar == MV_FALSE))
{
mvSataWriteReg(&sataAdapter.mvSataAdapter, 0x22010, mvSataBarOffset);
}
break;
}
case 0x00: /* Reset disk system */
case 0x0d: /* Alternate Fixed Disk Reset */
if(mvStorageDevATASoftResetDevice(&sataAdapter.mvSataAdapter,
channelIndex, PMPort, 0) == MV_FALSE)
{
flags |= 0x1;
ax.parts.hval = 0x5; /* fixed disk reset failed */
#ifdef DEBUG_IAL
printHexSingle ("Softrst Err",ax.parts.hval);
#endif
} else
{
ax.parts.hval = 0x0; /* All went good */
}
break;
case 0x04: /* Verify Sectors */
{
MV_U32 lowLBAAddress;
unsigned long track, head;
unsigned char sector;
MV_BOOLEAN returnStatus;
MV_U8 ATAStatus, ATAError;
MV_U16 timerBase, timerChanges;
sector = (unsigned short) (cx.parts.lval & 0x3f);
track = (((unsigned short)(cx.parts.lval & 0xc0) << 2) | cx.parts.hval);
head = (unsigned short) dx.parts.hval;
lowLBAAddress =
(unsigned long) track * HEADS * SECTORS +
(unsigned long) head * SECTORS +
(unsigned long) (sector - 1) ;
cx.val = 0xf9; 0000 0000 1111 1001
dx.val = 0xc97e; 1100 1001 0111 1110
/* Check if sector count is more than 128 or equals 0 */
if((ax.parts.lval > 128) || (ax.parts.lval == 0))
{
#ifdef DEBUG_IAL
printHexSingle ("Sect Cnt Err",readSegmentOffset16bit(ds,si.val+2));
#endif
flags |= 0x1;
ax.parts.lval = 0xa;
break;
}
if((lowLBAAddress + ax.parts.lval) >
sataAdapter.channelsInfo[channelIndex].diskSize[PMPort])
{
#ifdef DEBUG_IAL
printHexSingle ("LBA OOR Lo",(lowLBAAddress) & 0xffff);
printHexSingle ("LBA OOR Hi",((lowLBAAddress)>>16) & 0xffff);
#endif
flags |= 0x1;
ax.parts.lval = 0x4;
break;
}
#ifdef DEBUG_IAL
if(printAll == MV_TRUE)
{
printHexSingle ("V LBA Low",lowLBAAddress);
printHexSingle ("V LBA Hi",lowLBAAddress >> 16);
printHexSingle ("V Sec Count", ax.parts.lval);
}
#endif
returnStatus = MV_TRUE;
/*
* Since in this function the LBA address translation from CHS
* can't be LBA48, then send only LBA 28 command.
*/
mvSataWriteReg (&sataAdapter.mvSataAdapter,
getEdmaRegOffset (channelIndex) + MV_ATA_DEVICE_FEATURES_REG_OFFSET,
0);
mvSataWriteReg (&sataAdapter.mvSataAdapter,
getEdmaRegOffset (channelIndex) + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET,
ax.parts.lval);
mvSataWriteReg (&sataAdapter.mvSataAdapter,
getEdmaRegOffset (channelIndex) + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET,
(MV_U32)(lowLBAAddress & 0xffUL));
mvSataWriteReg (&sataAdapter.mvSataAdapter,
getEdmaRegOffset (channelIndex) + MV_ATA_DEVICE_LBA_MID_REG_OFFSET,
(MV_U32)((lowLBAAddress & 0xff00UL) >> 8));
mvSataWriteReg (&sataAdapter.mvSataAdapter,
getEdmaRegOffset (channelIndex) + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET,
(MV_U32)((lowLBAAddress & 0xff0000UL) >> 16));
mvSataWriteReg (&sataAdapter.mvSataAdapter,
getEdmaRegOffset (channelIndex) + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET,
(MV_U32)((MV_BIT6) |
((lowLBAAddress & 0x0f000000UL) >> 24)));
mvSataWriteReg (&sataAdapter.mvSataAdapter,
getEdmaRegOffset (channelIndex) + MV_ATA_DEVICE_COMMAND_REG_OFFSET,
MV_ATA_COMMAND_READ_VERIFY_SECTORS);
/* Command is out - wait for 10 seconds for completion */
timerChanges = 0;
timerBase = readSystemClockTimer();
while(1)
{
MV_U16 timerCurrent;
timerCurrent = readSystemClockTimer();
ATAStatus = mvSataReadReg (&sataAdapter.mvSataAdapter,
getEdmaRegOffset (channelIndex) +
MV_ATA_DEVICE_STATUS_REG_OFFSET);
/* Is BSY bit '0' ? */
if(!(ATAStatus & MV_BIT7))
{
break;
}
/*
* For measuring the time, the driver is waiting for changes on the
* system timer and count these changes.
*/
if(timerCurrent != timerBase)
{
timerChanges ++;
timerBase = timerCurrent;
}
/*
* Check if reached 10 seconds timeout. The 18*10 is because the system
* timer is ~18Hz, and the required timeout is 10seconds
*/
if(timerChanges == (18*10))
{
#ifdef DEBUG_IAL
printHexSingle ("Timeout !!!",0);
#endif
returnStatus = MV_FALSE;
break;
}
}
/* If function returned MV_TRUE, check ATA Status */
if(returnStatus == MV_TRUE)
{
/* Is err bit set ? */
if(ATAStatus & MV_BIT0)
{
ATAError = mvSataReadReg (&sataAdapter.mvSataAdapter,
getEdmaRegOffset (channelIndex) +
MV_ATA_DEVICE_ERROR_REG_OFFSET);
#ifdef DEBUG_IAL
printHexSingle ("VER ERR",ATAStatus);
printHexSingle ("VER ERR",ATAError);
#endif
/* Check UNC */
if(ATAStatus & MV_BIT6)
{
/* Medium error */
ax.parts.hval = 0x2;
flags |= 0x1;
} else
{
/* HDD Error */
ax.parts.hval = 0xbb;
flags |= 0x1;
}
}
} else
{
#ifdef DEBUG_IAL
printHexSingle ("TimeOut",ATAStatus);
#endif
/* Return not ready / timeout */
ax.parts.hval = 0x80;
flags |= 0x1;
}
break;
}
case 0x05: /* Format Cylinder */
case 0x09: /* Initialize Drive Parameters */
case 0x0c: /* Seek to Cylinder */
case 0x11: /* Recalibrate Drive */
case 0x12: /* Controller Ram Diagnostic */
case 0x13: /* Controller Driver Diagnositc */
case 0x14: /* Controller Internal Diagnostic */
case 0x44: /* Extended verify sectors */
case 0x18: /* Set Media Type For Format */
{
ax.parts.hval = 0x0; /* Fake the command as if it has passed */
break;
}
case 0x47: /* Extended seek */
{
ax.parts.hval = 0; /* lie and say it all worked */
break;
}
case 0x08: /* Read Drive Parameters */
{
ax.val = 0;
cx.val = 0xfeff;
cx.parts.lval = ((CYLINDER & 0x300) >> 2) | SECTORS;
cx.parts.hval = (CYLINDER & 0xff);
dx.parts.hval = HEADS - 1;
dx.parts.lval = getCurrentInstalledDrives();
break;
}
case 0x10: /* Test for Drive Ready */
{
ax.parts.hval = 0;
break;
}
case 0x15: /* Read Fixed Disk Type */
{
cx.val = 0xf9;
dx.val = 0xc97e;
ax.val = 0x0300;
break;
}
/* Extended commands */
case 0x41:
{
ax.parts.hval = 0x21; /* Major revision number */
bx.val = 0xaa55;
cx.val = 0x5 ; /* Device access using the packet structure */
break;
}
case 0x42: /* Extended READ */
case 0x43: /* Extended WRITE */
{
unsigned short blknumLo, blknumHi;
MV_U32 lowLBAAddress;
unsigned short sectorCount;
unsigned short segment, offset;
/* Check that packet is at least 16 bytes */
if(((unsigned char)readSegmentOffset16bit(ds,si.val)) < 0x10)
{
#ifdef DEBUG_IAL
printHexSingle ("Length err",readSegmentOffset16bit(ds,si.val));
printAll = MV_TRUE;
#endif
flags |= 0x1;
ax.parts.lval = 0x1;
break;
}
/* Meantime, support only 32 bits of address */
blknumLo = readSegmentOffset16bit(ds,si.val+8);
blknumHi = readSegmentOffset16bit(ds,si.val+10);
lowLBAAddress = (MV_U32) ((((MV_U32)blknumHi) << 16) |
(((MV_U32)blknumLo) & 0x0000ffff));
sectorCount = (unsigned char) (readSegmentOffset16bit(ds,si.val+2) & 0xff);
/* Check if sector count is more than 128 or equals 0 */
if((sectorCount > 128) || (sectorCount == 0))
{
#ifdef DEBUG_IAL
printHexSingle ("Sect Cnt Err",readSegmentOffset16bit(ds,si.val+2));
#endif
flags |= 0x1;
ax.parts.lval = 0xa;
break;
}
if((lowLBAAddress + sectorCount) >
sataAdapter.channelsInfo[channelIndex].diskSize[PMPort])
{
#ifdef DEBUG_IAL
printHexSingle ("LBA OOR Lo",(lowLBAAddress) & 0xffff);
printHexSingle ("LBA OOR Hi",((lowLBAAddress)>>16) & 0xffff);
#endif
flags |= 0x1;
ax.parts.lval = 0x4;
break;
}
segment = readSegmentOffset16bit(ds,si.val + 6);
offset = readSegmentOffset16bit(ds,si.val + 4);
#ifdef DEBUG_IAL
if(printAll == MV_TRUE)
{
printHexSingle ("LBA Low",blknumLo);
printHexSingle ("LBA Hi",blknumHi);
printHexSingle ("LBA Low",lowLBAAddress);
printHexSingle ("LBA Hi",lowLBAAddress>>16);
printHexSingle ("Sec Count",sectorCount);
printHexSingle ("Buff seg",segment);
printHexSingle ("Buff off",offset);
printHexSingle ("Buff Lo",generate32Addr (segment, offset));
printHexSingle ("Buff Hi",generate32Addr (segment, offset)>>16);
printHexSingle ("R/W",ax.parts.hval);
}
#endif
/*
* If SP < 0x200, then probably when calling requestIO it's going
* to overflow. Add 0x200 to stack pointer and bp and substitute
* 0x20 from the stack segment. This is the same from the int13
* handler point of view, but when going back with iret the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -