diskmain.cpp
来自「6410BSP3」· C++ 代码 · 共 1,948 行 · 第 1/5 页
CPP
1,948 行
if (pIOReq->dwCode == IOCTL_POWER_CAPABILITIES) {
// instantiate DiskPower object on first use, if necessary
if (m_pDiskPower == NULL) {
CDiskPower *pDiskPower = GetDiskPowerInterface();
if (pDiskPower == NULL) {
DEBUGMSG(ZONE_WARNING, (_T(
"Atapi!CDisk::PerformIoctl> Failed to create power management object\r\n"
)));
}
else if (!pDiskPower->Init(this)) {
DEBUGMSG(ZONE_WARNING, (_T(
"Atapi!CDisk::PerformIoctl> Failed to initialize power management\r\n"
)));
delete pDiskPower;
}
else {
m_pDiskPower = pDiskPower;
}
}
}
if (m_pDiskPower != NULL) {
// is this a power IOCTL? if an exception occurs, then we'll catch
// it below
dwError = m_pDiskPower->DiskPowerIoctl(pIOReq);
if (dwError != ERROR_NOT_SUPPORTED) {
goto done;
}
// request that the disk spin up (if it's not up already)
if (!m_pDiskPower->RequestDevice()) {
// the disk is powered down
dwError = ERROR_RESOURCE_DISABLED;
goto done;
}
}
// call the driver
dwError = MainIoctl(pIOReq);
// indicate we're done with the disk
if (m_pDiskPower != NULL) {
m_pDiskPower->ReleaseDevice();
}
done:;
} __except(EXCEPTION_EXECUTE_HANDLER) {
dwError = ERROR_GEN_FAILURE;
}
if (ZONE_CELOG) CeLogData(TRUE, CELID_ATAPI_COMPLETEIOCTL, &dwError, sizeof(dwError), 0, CELZONE_ALWAYSON, 0, FALSE);
m_pPort->ReleaseCS();
ReleaseCS();
if (dwError != ERROR_SUCCESS) {
SetLastError(dwError);
}
return (ERROR_SUCCESS == dwError);
}
// ----------------------------------------------------------------------------
// Function: PostInit
// This function facilitates backward compatibility
//
// Parameters:
// pPostInitBuf -
// ----------------------------------------------------------------------------
BOOL
CDisk::PostInit(
PPOST_INIT_BUF pPostInitBuf
)
{
DWORD dwError = ERROR_SUCCESS;
DEBUGMSG(ZONEID_INIT, (TEXT("Atapi!CDisk::PostInit> device(%d)\r\n"), m_dwDeviceId));
m_hDevice = pPostInitBuf->p_hDevice;
return (dwError == ERROR_SUCCESS);
}
// ----------------------------------------------------------------------------
// Function: GetDiskInfo
// Implement IOCTL_DISK_GETINFO
//
// Parameters:
// pIOReq -
// ----------------------------------------------------------------------------
DWORD
CDisk::GetDiskInfo(
PIOREQ pIOReq
)
{
DWORD dwError = ERROR_SUCCESS;
DISK_INFO *pInfo = NULL;
// for B/C, this call has three forms; only pInBuf, only pOutBuf, or both
// if both, then use pOutBuf
if (pIOReq->pInBuf) {
if (pIOReq->dwInBufSize != sizeof(DISK_INFO)) {
return ERROR_INVALID_PARAMETER;
}
pInfo = (DISK_INFO *)pIOReq->pInBuf;
}
if (pIOReq->pOutBuf) {
if (pIOReq->dwOutBufSize!= sizeof(DISK_INFO)) {
return ERROR_INVALID_PARAMETER;
}
pInfo = (DISK_INFO *)pIOReq->pOutBuf;
}
if (!pInfo) {
DEBUGMSG(ZONE_ERROR|ZONE_IOCTL, (_T(
"Atapi!CDisk::GetDiskInfo> bad argument; pInBuf/pOutBuf null\r\n")));
return ERROR_INVALID_PARAMETER;
}
// TODO: if device is ATAPI, call AtapiGetDiskInfo
if (ERROR_SUCCESS == dwError) {
__try {
memcpy(pInfo, &m_DiskInfo, sizeof(DISK_INFO));
pInfo->di_flags |= DISK_INFO_FLAG_PAGEABLE;
pInfo->di_flags &= ~DISK_INFO_FLAG_UNFORMATTED;
if (pIOReq->pBytesReturned){
*(pIOReq->pBytesReturned) = sizeof(DISK_INFO);
}
} __except(EXCEPTION_EXECUTE_HANDLER) {
dwError = ERROR_INVALID_PARAMETER;
}
}
return dwError;
}
// ----------------------------------------------------------------------------
// Function: SetDiskInfo
// Implement IOCTL_DISK_SETINFO
//
// Parameters:
// pSgReq -
// InBufLen -
// ----------------------------------------------------------------------------
DWORD
CDisk::SetDiskInfo(
PIOREQ pIOReq
)
{
DWORD dwError = ERROR_SUCCESS;
DISK_INFO *pInfo = (DISK_INFO *)pIOReq->pInBuf;
if ((pIOReq->pInBuf == NULL) || (pIOReq->dwInBufSize != sizeof(DISK_INFO))) {
return ERROR_INVALID_PARAMETER;
}
memcpy(&m_DiskInfo, pInfo, sizeof(DISK_INFO));
return dwError;
}
// ----------------------------------------------------------------------------
// Function: GetDeviceInfo
// IOCTL_DISK_DEVICE_INFO
//
// Parameters:
// pIOReq -
// ----------------------------------------------------------------------------
DWORD
CDisk::GetDeviceInfo(
PIOREQ pIOReq
)
{
if ((pIOReq->dwInBufSize == 0) || (pIOReq->pInBuf == NULL)) {
return ERROR_INVALID_PARAMETER;
}
if (pIOReq->dwInBufSize < sizeof(STORAGEDEVICEINFO)) {
return ERROR_INSUFFICIENT_BUFFER;
}
ASSERT(m_storagedeviceinfo.cbSize == sizeof(STORAGEDEVICEINFO));
PSTORAGEDEVICEINFO psdi = (PSTORAGEDEVICEINFO)pIOReq->pInBuf;
*psdi = m_storagedeviceinfo;
if (pIOReq->pBytesReturned) {
*(pIOReq->pBytesReturned) = sizeof(STORAGEDEVICEINFO);
}
return ERROR_SUCCESS;
}
// ----------------------------------------------------------------------------
// Function: GetDeviceInfo
// IOCTL_DISK_DEVICE_INFO
// This function queries the registry and must be called only in the INIT
// routines to prevent deadlocks, as this method will end up acquiring
// the registry lock. Otherwise the registry lock, mapped file sections
// global lock and block driver lock can possibly deadlock. Ideally mapped file
// sections shouldn't have a global lock. m_szDeviceKey must be set before this
// method is called
//
// Parameters:
// PSTORAGEDEVICEINFO -
// ----------------------------------------------------------------------------
DWORD
CDisk::GetDeviceInfo(
PSTORAGEDEVICEINFO psdi
)
{
HKEY hKey;
psdi->dwDeviceClass = 0;
psdi->dwDeviceType = 0;
psdi->dwDeviceFlags = 0;
PTSTR szProfile = psdi->szProfile;
wcscpy(szProfile, L"Default");
if (ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, m_szDeviceKey, 0, 0, &hKey)) {
hKey = NULL;
}
if (IsAtapiDevice() && IsCDRomDevice()) {
psdi->dwDeviceClass = STORAGE_DEVICE_CLASS_MULTIMEDIA;
psdi->dwDeviceType |= STORAGE_DEVICE_TYPE_REMOVABLE_MEDIA;
psdi->dwDeviceType |= STORAGE_DEVICE_TYPE_ATAPI;
psdi->dwDeviceType |= STORAGE_DEVICE_TYPE_PCIIDE;
psdi->dwDeviceFlags |= STORAGE_DEVICE_FLAG_MEDIASENSE;
psdi->dwDeviceFlags |= STORAGE_DEVICE_FLAG_READONLY;
if (!hKey || !AtaGetRegistryString(hKey, REG_VALUE_CDPROFILE, &szProfile, sizeof(psdi->szProfile))) {
wcscpy(psdi->szProfile, REG_VALUE_CDPROFILE);
}
}
else {
psdi->dwDeviceClass = STORAGE_DEVICE_CLASS_BLOCK;
psdi->dwDeviceType |= STORAGE_DEVICE_TYPE_PCIIDE;
psdi->dwDeviceType |= STORAGE_DEVICE_TYPE_ATA;
psdi->dwDeviceFlags |= STORAGE_DEVICE_FLAG_READWRITE;
if (!hKey || !AtaGetRegistryString(hKey, REG_VALUE_6410_CFPROFILE, &szProfile, sizeof(psdi->szProfile))) {
wcscpy(psdi->szProfile, REG_VALUE_6410_CFPROFILE);
}
}
psdi->cbSize = sizeof(STORAGEDEVICEINFO);
return ERROR_SUCCESS;
}
// ----------------------------------------------------------------------------
// Function: GetDiskName
// Implement IOCTL_DISK_GETNAME
//
// Parameters:
// pIOReq -
// ----------------------------------------------------------------------------
DWORD
CDisk::GetDiskName(
PIOREQ pIOReq
)
{
static PTCHAR szDefaultDiscDrive = (_T("External Volume"));
PTCHAR szDiskName = NULL;
DWORD dwSize;
DEBUGMSG(ZONE_IOCTL, (_T("Atapi!GeDisktName\r\n")));
if ((pIOReq->pBytesReturned == NULL) || (pIOReq->dwOutBufSize == 0) || (pIOReq->pOutBuf == NULL)) {
return ERROR_INVALID_PARAMETER;
}
*(pIOReq->pBytesReturned) = 0;
if (m_szDiskName) {
if (wcslen(m_szDiskName)) {
szDiskName = m_szDiskName;
}
else {
return ERROR_NOT_SUPPORTED;
}
}
else {
szDiskName = szDefaultDiscDrive;
}
dwSize = (wcslen(szDiskName) + 1) * sizeof(TCHAR);
if (pIOReq->dwOutBufSize < dwSize) {
return ERROR_INSUFFICIENT_BUFFER;
}
wcscpy((PTCHAR) pIOReq->pOutBuf, szDiskName);
*(pIOReq->pBytesReturned) = dwSize;
return ERROR_SUCCESS;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
BOOL CDisk::DoRead(CSgReq* pSgReqWrapper, DWORD dwStartingSector, DWORD dwNumberOfSectors, PDWORD pdwBytesRead)
{
DWORD dwBytesRead = 0;
BYTE bStatus;
DWORD dwByteInDrqDataBlock = 0;
BYTE bData = 0;
WORD wData = 0;
if (NULL == pSgReqWrapper) {
ASSERT(NULL != pSgReqWrapper);
return FALSE;
}
// Host_Idle
// ---------
// Issue the appropriate command.
if (FALSE == SendIOCommand(dwStartingSector, dwNumberOfSectors, m_bReadCommand)) {
DEBUGMSG(ZONE_ERROR, (_T("Atapi!CDisk::DoRead> Failed to issue read/write command\r\n")));
return FALSE;
}
// INTRQ_Wait
// ----------
// Wait for interrupt if nIEN=0 (i.e., if interrupt enabled).
HPIOI_INTRQ_Wait:;
if (m_fInterruptSupported) {
if (FALSE == WaitForInterrupt(m_dwDiskIoTimeOut) || (ATA_INTR_ERROR == CheckIntrState())) {
DEBUGMSG(ZONE_ERROR, (_T("Atapi!CDisk::DoRead> Failed to wait for interrupt (m_dwDeviceId=%d)\r\n"), m_dwDeviceId));
return FALSE;
}
}
// Check_Status
// ------------
// If BSY=0 and DRQ=0, transition to Host_Idle.
// If BSY=1, re-enter this state.
// If BSY=0 and DRQ=1, transition to Transfer_Data.
HPIOI_Check_Status:;
// Read the Status register.
bStatus = GetAltStatus();
// Test for BSY=0 and DRQ=0.
if ((!(bStatus & 0x80)) && (!(bStatus & 0x08))) {
ASSERT(0 == dwNumberOfSectors);
*pdwBytesRead = dwBytesRead;
return TRUE;
}
// Test for BSY=1.
if (bStatus & 0x80) {
goto HPIOI_Check_Status;
}
// Test for BSY=0, DRQ=1.
if ((!(bStatus & 0x80)) && (bStatus & 0x08)) {
goto HPIOI_Transfer_Data_Setup;
}
// Illegal status.
ASSERT(FALSE);
return FALSE;
// Transfer_Data
// -------------
// If read Data register, DRQ data block transfer not complete, re-enter
// this state.
// If read Data register, all data for command transferred, transition to
// Host_Idle.
// If read Data register, DRQ data block transferred, all data for c
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?