📄 diskio.c
字号:
if (pDisk->d_f16Bit) {
if (nextbyte != 0xFFFF) {
// Update the first byte.
*pBuf++ = (BYTE) nextbyte;
i--;
nextbyte = 0xFFFF;
}
if ((DWORD)pBuf & 1) {
//
// If the user's buffer is not 16 bit aligned then use the
// 16 bit aligned buffer to read the sector from the card.
//
while (i > 1) {
unisc.us = ATA_READ_USHORT(pDisk->d_Flags, (PUSHORT)pData16);
*pBuf++= unisc.uc[0];
*pBuf++= unisc.uc[1];
i -= 2;
}
} else {
while (i > 1) {
*(WORD *)pBuf = ATA_READ_USHORT(pDisk->d_Flags, (PUSHORT)pData16);
i -= 2;
pBuf +=2;
}
}
if (i == 1) {
unisc.us = ATA_READ_USHORT(pDisk->d_Flags, (PUSHORT)pData16);
*pBuf++= unisc.uc[0];
nextbyte = (WORD)unisc.uc[1]; // Save byte for the next SG if
}
} else {
while (i) {
*pBuf++ = ATA_READ_UCHAR(pDisk->d_Flags, (PUCHAR)pData);
i--;
}
}
} except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
DEBUGMSG(ZONE_IO|ZONE_ERROR, (TEXT("ATADISK:ATARead - exception 2\r\n")));
error = ERROR_READ_FAULT;
}
if (error != ERROR_SUCCESS) {
return error;
}
if (bytes_this_int == 0) {
if (sectno < endsect) {
continue; // next sector
}
}
//
// Use the next scatter/gather buffer
//
num_sg--;
if (num_sg == 0) {
break;
}
pSg++;
// Map address and check for security violation
pBuf = (LPBYTE)MapCallerPtr((LPVOID)pSg->sb_buf, pSg->sb_len);
if (pSg->sb_buf != NULL && pBuf == NULL) {
// Security violation
DEBUGMSG(ZONE_ERROR, (TEXT(
"ATARead>Failed to map pointer to caller\r\n"
)));
return ERROR_ACCESS_DENIED;
}
bytes_this_sg = pSg->sb_len;
if (bytes_this_int) {
goto ar_continue_sector;
}
} // while
return 0;
} // ATARead
//
// ATAWrite
//
DWORD
ATAWrite(
PDISK pDisk,
PSG_REQ pSgr
)
{
DWORD i;
DWORD num_sg;
DWORD bytes_this_int;
DWORD bytes_this_sg;
PSG_BUF pSg;
volatile USHORT *pData16;
PUCHAR pBuf;
volatile UCHAR *pData;
DWORD sectno;
DWORD nextsec;
DWORD endsect;
DWORD error;
WORD nextbyte=0xFFFF;
union {
WORD us;
BYTE uc[2];
}unisc;
num_sg = pSgr->sr_num_sg;
pSg = &(pSgr->sr_sglist[0]);
bytes_this_sg = pSg->sb_len;
bytes_this_int = pDisk->d_DiskInfo.di_bytes_per_sect;
// Map address and check for security violation
pBuf = (LPBYTE)MapCallerPtr((LPVOID)pSg->sb_buf, pSg->sb_len);
if (pSg->sb_buf != NULL && pBuf == NULL) {
// Security violation
DEBUGMSG(ZONE_ERROR, (TEXT(
"ATAWrite>Failed to map pointer to caller\r\n"
)));
return ERROR_ACCESS_DENIED;
}
pData = (volatile UCHAR*)pData16 = pDisk->d_pATAReg;
sectno = pSgr->sr_start;
endsect = sectno + pSgr->sr_num_sec;
error = ERROR_SUCCESS;
nextsec = 0;
//
// This loop writes data from multiple scatter/gather buffers to multiple
// sectors.
//
while (num_sg) {
DEBUGMSG(ZONE_IO,
(TEXT("ATADISK:ATAWrite - writing sector %d\r\n"), sectno));
if (!nextsec) {
nextsec = MIN(MAX_SECT_CNT, endsect - sectno);
try {
error = ATASetSector(pDisk, sectno, nextsec, ATA_CMD_WRITE);
} except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
DEBUGMSG(ZONE_IO|ZONE_ERROR, (TEXT("ATADISK:ATAWrite - exception 1\r\n")));
error = ERROR_WRITE_FAULT;
}
if (error != ERROR_SUCCESS) {
return error;
}
}
error = ATAWaitForDisk(pDisk, WAIT_TIME_NORMAL, WAIT_TYPE_DRQ_NOERR);
if (error != ERROR_SUCCESS) {
return error;
}
sectno++;
nextsec--;
bytes_this_int = pDisk->d_DiskInfo.di_bytes_per_sect;
aw_continue_sector:
i = (bytes_this_sg < bytes_this_int) ? bytes_this_sg : bytes_this_int;
bytes_this_sg -= i;
bytes_this_int -= i;
try {
if (pDisk->d_f16Bit) {
if (nextbyte != 0xFFFF) {
// Update the first byte
unisc.uc[0] = (BYTE) nextbyte;
unisc.uc[1] = *pBuf++;
i--;
nextbyte = 0xFFFF;
ATA_WRITE_USHORT(pDisk->d_Flags, (PUSHORT)pData16, unisc.us);
}
if ((DWORD)pBuf & 1) {
//
// If the user's buffer is not 16 bit aligned then use the
// 16 bit aligned buffer to write the sector to the card.
//
while (i > 1) {
unisc.uc[0] = *pBuf++;
unisc.uc[1] = *pBuf++;
ATA_WRITE_USHORT(pDisk->d_Flags, (PUSHORT)pData16, unisc.us);
i -= 2;
}
} else {
while (i > 1) {
ATA_WRITE_USHORT(pDisk->d_Flags, (PUSHORT)pData16, *(WORD *)pBuf);
i -= 2;
pBuf +=2;
}
}
if (i == 1) {
nextbyte = *(WORD *)pBuf; // Save byte for the next SG if
pBuf += 2;
}
} else {
while (i) {
ATA_WRITE_UCHAR(pDisk->d_Flags, (PUCHAR)pData, *pBuf);
i--;
pBuf++;
}
}
} except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
DEBUGMSG(ZONE_IO|ZONE_ERROR, (TEXT("ATADISK:ATAWrite - exception 2\r\n")));
error = ERROR_WRITE_FAULT;
}
if (error != ERROR_SUCCESS) {
return error;
}
if (bytes_this_int == 0) {
if (sectno < endsect) {
continue; // next sector
}
}
//
// Use the next scatter/gather buffer
//
num_sg--;
if (num_sg == 0) {
break;
}
pSg++;
// Map address and check for security violation
pBuf = (LPBYTE)MapCallerPtr((LPVOID)pSg->sb_buf, pSg->sb_len);
if (pSg->sb_buf != NULL && pBuf == NULL) {
// Security violation
DEBUGMSG(ZONE_ERROR, (TEXT(
"ATAWrite>Failed to map pointer to caller\r\n"
)));
return ERROR_ACCESS_DENIED;
}
bytes_this_sg = pSg->sb_len;
if (bytes_this_int) {
goto aw_continue_sector;
}
} // while
//
// Finish writing to last sector if the last buffer was not a sector multiple.
//
if (pDisk->d_f16Bit) {
bytes_this_int = (bytes_this_int + 1) /2;
while (bytes_this_int) {
ATA_WRITE_USHORT(pDisk->d_Flags, (PUSHORT)pData16, 0xDDDD);
//*pData16 = 0xDDDD;
bytes_this_int--;
}
} else {
while (bytes_this_int) {
ATA_WRITE_UCHAR(pDisk->d_Flags, (PUCHAR)pData, 0xDD);
//*pData = 0xDD;
bytes_this_int--;
}
}
return ATAWaitForDisk(pDisk, WAIT_TIME_NORMAL, WAIT_TYPE_READY);
} // ATAWrite
//
// DoDiskIO - fulfill I/O requests
//
DWORD
DoDiskIO(
PDISK pDisk,
DWORD Opcode,
PSG_REQ pSgr
)
{
DWORD status;
unsigned int i;
DEBUGMSG(ZONE_IO, (TEXT("ATDISK:DoDiskIO entered\r\n")));
pSgr->sr_status = ERROR_IO_PENDING;
if (pSgr->sr_num_sg > MAX_SG_BUF || pSgr->sr_num_sg <= 0) {
status = ERROR_INVALID_PARAMETER;
goto ddi_exit;
}
for (i = 0; i < pSgr->sr_num_sg; i++) {
if (pSgr->sr_sglist[i].sb_len <= 0 ||
pSgr->sr_sglist[i].sb_buf == NULL) {
status = ERROR_INVALID_PARAMETER;
goto ddi_exit;
}
}
//
// Make sure request doesn't exceed the disk size or ask for 0 sectors.
//
if (pSgr->sr_num_sec == 0) {
status = ERROR_INVALID_PARAMETER;
goto ddi_exit;
}
if ((pSgr->sr_start + pSgr->sr_num_sec) > pDisk->d_DiskInfo.di_total_sectors) {
status = ERROR_SECTOR_NOT_FOUND;
goto ddi_exit;
}
EnterCriticalSection(&pDisk->d_DiskCardCrit);
while(pDisk->lPwrOff) {
HANDLE hEvent = pDisk->hPwrEvent;
LeaveCriticalSection(&pDisk->d_DiskCardCrit);
WaitForSingleObject( pDisk->hPwrEvent, INFINITE);
if (pDisk->lPwrOff == -1) {
goto ddi_exit;
}
EnterCriticalSection(&pDisk->d_DiskCardCrit);
ATAInitController(pDisk);
}
DEBUGMSG(ZONE_IO,
(TEXT("ATADISK:DoDiskIO - working on request @ 0x%x from sector %d to %d\r\n"),
pSgr, pSgr->sr_start, pSgr->sr_start + pSgr->sr_num_sec - 1));
if (Opcode == DISK_IOCTL_READ) {
status = ATARead(pDisk, pSgr);
} else {
status = ATAWrite(pDisk, pSgr);
}
LeaveCriticalSection(&(pDisk->d_DiskCardCrit));
ddi_exit:
DEBUGMSG(ZONE_IO, (TEXT("ATDISK:DoDiskIO done - status=%d\r\n"), status));
if (pDisk->lPwrOff == -1) {
status = ERROR_DEVICE_NOT_AVAILABLE;
}
pSgr->sr_status = status;
return status;
} // DoDiskIO
VOID
PcmciaIntr(
DWORD Context
)
{
DWORD error;
UCHAR ATAStatus;
UCHAR AltStatus;
#ifdef DEBUG
TCHAR szStatus[70];
#endif
PDISK pDisk = (PDISK)Context;
if (IsValidDisk(pDisk) == FALSE) {
DEBUGMSG(ZONE_IO|ZONE_PCMCIA,
(TEXT("ATADISK: PcmciaIntr - Invalid PDISK\r\n")));
return;
}
error = ERROR_SUCCESS;
ATAStatus = AltStatus = 0;
//
// Acknowledge the interrupt by reading the status register
//
try {
ATAStatus = ATA_READ_UCHAR(pDisk->d_Flags, (UCHAR*)pDisk->d_pATAReg + ATA_REG_STATUS);
AltStatus = ATA_READ_UCHAR(pDisk->d_Flags, (UCHAR*)pDisk->d_pATARegAlt + ATA_REG_ALT_STATUS);
} except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
DEBUGMSG(ZONE_IO|ZONE_ERROR, (TEXT("ATADISK:PcmciaIntr - exception!\r\n")));
error = ERROR_GEN_FAILURE;
}
if (error != ERROR_SUCCESS) {
return;
}
if (ATAStatus != AltStatus) {
DEBUGMSG(ZONE_IO|ZONE_PCMCIA,
(TEXT("ATADISK:PcmciaIntr - ATAStatus(0x%x) != AltStatus(0x%x)\r\n"),
ATAStatus, AltStatus));
}
if (ATAStatus != pDisk->d_DiskStatus) {
pDisk->d_DiskStatus = ATAStatus;
#ifdef DEBUG
if (ZONE_IO) {
szStatus[0] = 0;
//
// Display ATA status register
//
if (ATAStatus & ATA_STATUS_ERROR) {
_tcscat(szStatus, TEXT("ERROR "));
}
if (ATAStatus & ATA_STATUS_CORRECTED_ERROR) {
_tcscat(szStatus, TEXT("CORRECTED_ERROR "));
}
if (ATAStatus & ATA_STATUS_DATA_REQ) {
_tcscat(szStatus, TEXT("DATA_REQ "));
}
if (ATAStatus & ATA_STATUS_SEEK_DONE) {
_tcscat(szStatus, TEXT("SEEK_DONE "));
}
if (ATAStatus & ATA_STATUS_WRITE_FAULT) {
_tcscat(szStatus, TEXT("WRITE_FAULT "));
}
if (ATAStatus & ATA_STATUS_READY) {
_tcscat(szStatus, TEXT("READY "));
}
if (ATAStatus & ATA_STATUS_BUSY) {
_tcscat(szStatus, TEXT("BUSY "));
}
DEBUGMSG(ZONE_IO, (TEXT("ATADISK:PcmciaIntr - ATA Status = %s\r\n"),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -