📄 ata_cmds.c
字号:
DOCH_SimSocket* simSocket = getSimSocket();
if((items & CHECK_PARTITION) == CHECK_PARTITION)
{
if(simDev->partitions[partNum].wActive == 0)
{
DBG_PRINT_FLOW_PRM(FLZONE_MTD, (FLTXT("Partition #%d not formatted\r\n"),partNum));
rc |= CHECK_PARTITION;
}
}
if((items & CHECK_SIZE) == CHECK_SIZE)
{
if( ((FLDword)requiredSize) > /*(partNum==DOCH_IPL_PARTITION?simDev->dwXIPMaxSize : */simDev->partitions[partNum].dwSize/*)*/)
{
DBG_PRINT_FLOW_PRM(FLZONE_MTD, (FLTXT("Not enough space...\r\n")));
rc |= CHECK_SIZE;
}
}
if((items & CHECK_LIMITS) == CHECK_LIMITS)
{
if( ((FLDword)endSector) > simDev->partitions[partNum].dwSize)
{
DBG_PRINT_FLOW_PRM(FLZONE_MTD, (FLTXT("Request overflows partition limits\r\n")));
rc |= CHECK_LIMITS;
}
}
if((items & CHECK_AUTHENTICATION) == CHECK_AUTHENTICATION)
{
if(!simDev->partitions[partNum].wAuthenticated)
{
DBG_PRINT_FLOW_PRM(FLZONE_MTD, (FLTXT("Partition NOT authenticated\r\n")));
rc |= CHECK_AUTHENTICATION;
}
}
if((items & CHECK_READ_ACCESS) == CHECK_READ_ACCESS)
{
if((!simDev->partitions[partNum].wAuthenticated) &&
(((simDev->partitions[partNum].info.partitionAttributes2 & DOCH_PA2B_GUEST_MODE) >> DOCH_PA2O_GUEST_MODE)
== DOCH_PART_ACCESS_MODE_NONE))
{
DBG_PRINT_FLOW_PRM(FLZONE_MTD, (FLTXT("No Read Access\r\n")));
rc |= CHECK_READ_ACCESS;
}
}
if((items & CHECK_WRITE_ACCESS) == CHECK_WRITE_ACCESS)
{
if((!simDev->partitions[partNum].wAuthenticated) &&
(((simDev->partitions[partNum].info.partitionAttributes2 & DOCH_PA2B_GUEST_MODE) >> DOCH_PA2O_GUEST_MODE)
!= DOCH_PART_ACCESS_MODE_FULL))
{
DBG_PRINT_FLOW_PRM(FLZONE_MTD, (FLTXT("No Write Access\r\n")));
rc |= CHECK_WRITE_ACCESS;
}
}
if((items & CHECK_OTP) == CHECK_OTP)
{
if((simDev->partitions[partNum].info.dwCommandFlagsOrStatuses & DOCH_CFSB_PERM_LOCKED) == DOCH_CFSB_PERM_LOCKED)
{
DBG_PRINT_FLOW_PRM(FLZONE_MTD, (FLTXT("OTP Bit Active!\r\n")));
rc |= CHECK_OTP;
}
}
if((items & CHECK_SLOCK) == CHECK_SLOCK)
{
if((simSocket->config_regs.wSWLock & 0x1) == 0x01)
{
DBG_PRINT_FLOW_PRM(FLZONE_MTD, (FLTXT("SLock active!\r\n")));
rc |= CHECK_SLOCK;
}
}
if(rc != 0)
{
simSocket->out_regs.bStatusCommand |= DOCH_ERROR;
if((rc & CHECK_PARTITION) == CHECK_PARTITION)
{
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT);
return (simATANotFormatted);
}
else if((rc & CHECK_SIZE) == CHECK_SIZE)
{
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT | DOCH_ATA_ERROR_WRITE_PROTECTED);
return (simATANoSpace);
}
else if((rc & CHECK_LIMITS) == CHECK_LIMITS)
{
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT | DOCH_ATA_ERROR_ID_NOT_FOUND);
return (simATAExcLimit);
}
else if((rc & CHECK_AUTHENTICATION) == CHECK_AUTHENTICATION)
{
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT | DOCH_ATA_ERROR_TRACK_0_NOT_FOUND);
return (simATANotAuth);
}
else if((rc & CHECK_READ_ACCESS) == CHECK_READ_ACCESS)
{
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT | DOCH_ATA_ERROR_TRACK_0_NOT_FOUND);
return (simATANoReadAccess);
}
else if((rc & CHECK_WRITE_ACCESS) == CHECK_WRITE_ACCESS)
{
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT | DOCH_ATA_ERROR_TRACK_0_NOT_FOUND);
return (simATANoWriteAccess);
}
else if((rc & CHECK_OTP) == CHECK_OTP)
{
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT | DOCH_ATA_ERROR_TRACK_0_NOT_FOUND);
return (simATANoWriteAccess);
}
else if((rc & CHECK_SLOCK) == CHECK_SLOCK)
{
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT | DOCH_ATA_ERROR_TRACK_0_NOT_FOUND);
return (simATASlockActive);
}
}
return rc;
}
/*Simulation static routines implementations*/
/*==========================================*/
static FLSNative simReadPartition(DOCH_SimDevice* simDev)
{
FLSNative rc = 0;
DOCH_SimSocket* simSocket = getSimSocket();
FLNative requiredSize = simSocket->in_regs.bSectorCount;
FLNative startSector;
FLNative endSector;
if(requiredSize == 0)
requiredSize = 0x100;
startSector = simSocket->in_regs.bLBALow + (simSocket->in_regs.bLBAMid << 8) + (simSocket->in_regs.bLBAHigh << 16);
endSector = startSector + requiredSize;
simSocket->out_regs.bStatusCommand |= DOCH_BUSY;
simSocket->out_regs.bStatusCommand &= ~(DOCH_READY | DOCH_DRQ | DOCH_ERROR);
/*Sanity checks*/
rc = sanityCheck(simDev,
CHECK_PARTITION | CHECK_SIZE | CHECK_LIMITS | CHECK_READ_ACCESS,
simSocket->in_regs.bErrorFeature,
requiredSize,
startSector,
endSector);
if(rc != 0)
{
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return rc;
}
#ifdef DOCH_MEMMAP_FILE
if(simFileIO(simSocket, SIM_ITEM_STORAGE, simSocket->selDevNum, FALSE, NULL))
{
simSocket->out_regs.bStatusCommand |= DOCH_ERROR;
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return -1;
}
#endif /*DOCH_MEMMAP_FILE*/
simSocket->cmdBuffer.sbBuffer = choosePartition(simSocket, simSocket->in_regs.bErrorFeature);
simSocket->cmdBuffer.nBufferLen = requiredSize * DOCH_SECTOR_SIZE;
simSocket->cmdBuffer.sbCurrentPosition = simSocket->cmdBuffer.sbBuffer + (startSector * DOCH_SECTOR_SIZE);
simSocket->cmdBuffer.sbPositionToReach = (simSocket->cmdBuffer.sbCurrentPosition + simSocket->cmdBuffer.nBufferLen);
simSocket->cmdBuffer.nDirection = SIM_READ;
/* Now that data is ready, set DRQ and clear BSY*/
simSocket->out_regs.bStatusCommand |= (DOCH_DRQ | DOCH_READY);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return rc;
}
static FLSNative simWritePartition(DOCH_SimDevice* simDev)
{
FLSNative rc = 0;
DOCH_SimSocket* simSocket = getSimSocket();
FLNative requiredSize = simSocket->in_regs.bSectorCount;
FLNative startSector;
FLNative endSector;
if(requiredSize == 0)
requiredSize = 0x100;
startSector = simSocket->in_regs.bLBALow + (simSocket->in_regs.bLBAMid << 8) + (simSocket->in_regs.bLBAHigh << 16);
endSector = startSector + requiredSize;
simSocket->out_regs.bStatusCommand |= DOCH_BUSY;
simSocket->out_regs.bStatusCommand &= ~(DOCH_READY | DOCH_DRQ | DOCH_ERROR);
/*Sanity checks*/
rc = sanityCheck(simDev,
CHECK_PARTITION | CHECK_SIZE | CHECK_LIMITS | CHECK_WRITE_ACCESS | CHECK_OTP,
simSocket->in_regs.bErrorFeature,
requiredSize,
startSector,
endSector);
if(rc != 0)
{
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return rc;
}
#ifdef DOCH_MEMMAP_FILE
if(simFileIO(simSocket, SIM_ITEM_STORAGE, simSocket->selDevNum, FALSE, NULL))
{
simSocket->out_regs.bStatusCommand |= DOCH_ERROR;
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return -1;
}
#endif /*DOCH_MEMMAP_FILE*/
simSocket->cmdBuffer.sbBuffer = choosePartition(simSocket, simSocket->in_regs.bErrorFeature);
simSocket->cmdBuffer.nBufferLen = requiredSize * DOCH_SECTOR_SIZE;
simSocket->cmdBuffer.sbCurrentPosition = simSocket->cmdBuffer.sbBuffer + (startSector * DOCH_SECTOR_SIZE);
simSocket->cmdBuffer.sbPositionToReach = (simSocket->cmdBuffer.sbCurrentPosition + simSocket->cmdBuffer.nBufferLen);
simSocket->cmdBuffer.nDirection = SIM_WRITE;
/* Now that data is ready, set DRQ and clear BSY*/
simSocket->out_regs.bStatusCommand |= (DOCH_DRQ | DOCH_READY);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
#if 0
if( simSocket->in_regs.bErrorFeature == DOCH_IPL_PARTITION )
{
if( ((FLDword)endSector)==simDev->dwXIPMaxSize )
{
simDev->partitions[DOCH_IPL_PARTITION].dwSize = simDev->dwXIPMaxSize; /* update the IPL partition size, when last sector written */
simDev->partitions[DOCH_IPL_PARTITION].dwRequestedSize = simDev->dwXIPMaxSize; /* update the IPL partition size, when last sector written */
simDev->partitions[DOCH_IPL_PARTITION].info.nPartitionSize = simDev->dwXIPMaxSize; /* update the IPL partition size, when last sector written */
}
}
#endif /*0*/
return rc;
}
static FLSNative simWriteFlexi(DOCH_SimDevice* simDev)
{
/*TBD*/
return 0;
}
static FLSNative simErasePartition(DOCH_SimDevice* simDev)
{
FLSNative rc = 0;
FLNative i;
DOCH_SimSocket* simSocket = getSimSocket();
FLNative requiredSize = simSocket->in_regs.bSectorCount;
FLNative startSector = simSocket->in_regs.bLBALow + (simSocket->in_regs.bLBAMid << 8) + (simSocket->in_regs.bLBAHigh << 16);
FLNative endSector = startSector + requiredSize;
simSocket->out_regs.bStatusCommand |= DOCH_BUSY;
simSocket->out_regs.bStatusCommand &= ~(DOCH_READY | DOCH_ERROR);
/*Sanity checks*/
rc = sanityCheck(simDev,
CHECK_PARTITION | CHECK_SIZE | CHECK_LIMITS | CHECK_WRITE_ACCESS | CHECK_OTP,
simSocket->in_regs.bErrorFeature,
requiredSize,
startSector,
endSector);
if(rc != 0)
{
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return rc;
}
#ifdef DOCH_MEMMAP_FILE
{
FLWord writeLen = 0;
FLByte dummy[DOCH_SECTOR_SIZE];
if(simFileIO(simSocket, SIM_ITEM_STORAGE, simSocket->selDevNum, FALSE, NULL))
{
simSocket->out_regs.bStatusCommand |= DOCH_ERROR;
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return -1;
}
for(i=0; i<requiredSize; i++)
{
/* Fill partition with "0" */
writeLen = fwrite( (void*)&(dummy), 1,
DOCH_SECTOR_SIZE, simSocket->pSimFile );
if( writeLen != DOCH_SECTOR_SIZE )
{
simSocket->out_regs.bStatusCommand |= DOCH_ERROR;
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return -1;
}
}
}
#else /*DOCH_MEMMAP_FILE*/
simSocket->cmdBuffer.sbBuffer = choosePartition(simSocket, simSocket->in_regs.bErrorFeature);
simSocket->cmdBuffer.nBufferLen = 0;
for(i=0; i<(requiredSize * DOCH_SECTOR_SIZE); i++)
{
simSocket->cmdBuffer.sbBuffer[(startSector * DOCH_SECTOR_SIZE) + i] = 0;
}
#endif /*DOCH_MEMMAP_FILE*/
/* Now that data is ready, clear BSY*/
simSocket->out_regs.bStatusCommand |= (DOCH_READY);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return rc;
}
static FLSNative simSecureErase(DOCH_SimDevice* simDev)
{
DOCH_SimSocket* simSocket = getSimSocket();
simSocket->out_regs.bStatusCommand |= DOCH_BUSY;
simSocket->out_regs.bStatusCommand &= ~(DOCH_READY | DOCH_DRQ | DOCH_ERROR);
simSocket->cmdBuffer.sbBuffer = getSandBox();
simSocket->cmdBuffer.nBufferLen = (simSocket->in_regs.bLBALow<<DOCH_SECTOR_SIZE_BITS);
simSocket->cmdBuffer.sbCurrentPosition = simSocket->cmdBuffer.sbBuffer;
simSocket->cmdBuffer.sbPositionToReach = (simSocket->cmdBuffer.sbCurrentPosition + simSocket->cmdBuffer.nBufferLen);
simSocket->cmdBuffer.nDirection = SIM_READ;
/* Now that data is ready, clear BSY*/
simSocket->out_regs.bStatusCommand |= (DOCH_DRQ | DOCH_READY);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return 0;
}
static FLSNative simDeletePartitions(DOCH_SimDevice* simDev)
{
register FLSNative i = 0;
DOCH_SimSocket* simSocket = getSimSocket();
DOCH_DeviceInfo* diskOnChipDeviceInfo = (DOCH_DeviceInfo*)getDiskOnChipDeviceInfo(simSocket->selDevNum);
FLByte firstPartToRemove = simSocket->in_regs.bSectorCount;
FLByte lastPartToRemove = TFFSMIN(simSocket->in_regs.bLBALow, (diskOnChipDeviceInfo->wTotalNumOfPartitions-1));
simSocket->out_regs.bStatusCommand |= DOCH_BUSY;
simSocket->out_regs.bStatusCommand &= ~(DOCH_READY | DOCH_ERROR);
/* (lastPartToRemove + 1) must be >= last partition number */
if((lastPartToRemove+1) < diskOnChipDeviceInfo->wTotalNumOfPartitions)
{
simSocket->out_regs.bStatusCommand |= DOCH_ERROR;
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return -1;
}
/* (firstPartToRemove+1) must be <= total number of partitions */
if( ((firstPartToRemove+1) > diskOnChipDeviceInfo->wTotalNumOfPartitions) &&
(diskOnChipDeviceInfo->wTotalNumOfPartitions != 0))
{
simSocket->out_regs.bStatusCommand |= DOCH_ERROR;
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return -1;
}
/* If no partition exist - FAIL */
if((diskOnChipDeviceInfo->wTotalNumOfPartitions == 0) &&
(! ((firstPartToRemove == 0) && (lastPartToRemove == 0xFF))) )
{
simSocket->out_regs.bStatusCommand |= DOCH_ERROR;
simSocket->out_regs.bErrorFeature = (DOCH_ATA_ERROR_ABORT | DOCH_ATA_ERROR_WRITE_PROTECTED);
simSocket->out_regs.bStatusCommand &= ~DOCH_BUSY;
return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -