📄 ide_ata.c
字号:
OS_MsgQSend(msgQID, (char *)&msg, sizeof(msg), OS_WAIT_FOREVER, OS_MSG_PRI_NORMAL);
// Wait for the semaphore to be released
OS_SemTake(msg.cmd.ideCmd.semID, OS_WAIT_FOREVER);
OS_SemGive(msg.cmd.ideCmd.semID);
// modify for flash card hot plug
return hdd_scheduler_get_cmd_ret(driveno);
//return SUCCESS;
}
#else
return ide_exec(driveno, sector, buffer, count, reading, FALSE);
#endif
}
//------------------------------------------------------------------------
int ide_exec(
Uint8 driveno,
Uint32 sector,
void *buffer,
Uint16 count,
Uint8 reading,
Boolean use_cache
)
{
Uint32 ltemp;
Uint16 phys_disk;
Uint8 ret_val = 0;
setATAError(0);
DEBUG_OUT("ide_exec: diskno: %d driveno[%d] drv_start[0x%x]\n", driveDesc[driveno].phys_disk, driveno, driveDesc[driveno].drv_start);
if (!count) /* Must have a count */
{
TRACE_ERROR("ide_exec fail 1\n");
return SUCCESS;
}
if (!driveDesc[driveno].open_count)
{
TRACE_ERROR("ide_exec fail 2\n");
return IDE_BADDRIVE;
}
phys_disk = driveDesc[driveno].phys_disk; // 0 to NDISKS
TRACE_48BIT("ide_exec driveno: %d phys_disk: %d\n", driveno, phys_disk);
sector += driveDesc[driveno].drv_start; /* Add in the start of partition */
ltemp = sector + count - 1;
/* Check the partition end.*/
if (ltemp > driveDesc[driveno].drv_end)
{
TRACE_ERROR("ide_exec fail 3\n");
return IDE_BADPARM;
}
if (reading)
{
/*
if ( diskDesc[phys_disk].IsRemovableMediaDevice )
{
int i;
for ( i = 0; i < count; i++ )
ret_val = ide_command_read_sectors((Uint8 *) buffer + (512 *i), phys_disk, sector + i, 1, use_cache);
}
else
*/
{
ret_val = ide_command_read_sectors((Uint8 *)buffer, phys_disk, sector, count, use_cache);
}
}
else
{
if ( diskDesc[phys_disk].IsRemovableMediaDevice )
{
int i;
for ( i = 0; i < count; i++ )
ret_val = ide_command_write_sectors((Uint8 *)buffer + (512 *i), phys_disk, sector + i, 1, use_cache);
}
else
{
ret_val = ide_command_write_sectors((Uint8 *)buffer, phys_disk, sector, count, use_cache);
}
}
setATAError(ret_val);
return (ret_val);
}
//-----------------------------------------------------------------------------
// Function: ide_command_read_sectors
//
// Description:
//
// Called by ide_io and ide_open
//
//-----------------------------------------------------------------------------
#if 1
static Int32 ide_command_read_sectors(
Uint8 *address, // Destination address for the data
Uint16 disk, // Drive number
Uint32 blockno, // Block number to read
Uint16 nblocks, // Number of blocks (legal range: 1-256)
Boolean use_cache
)
{
IDE_Cmd cmd;
int ret = 0, begin, end;
/* Check against max_blocks. this is 256 for IDE. In real mode 80xx we limit
it to 128 to eliminate segment wrap. */
if (nblocks > MAX_BLOCKS)
{
ErrPrint(" IDE_INTERNAL nblocks=%d\n",nblocks);
return IDE_INTERNAL;
}
if ( !diskDesc[disk].MediaDeviceBrand == MEDIADEVICE_BRAND_SAIN )
if (!(diskDesc[disk].maxLBA)) /* Should be non zeroe if the disk was initialized */
{
ErrPrint(" IDE_INTERNAL diskDesc[%d].maxLBA=%d\n",disk,diskDesc[disk].maxLBA);
return IDE_INTERNAL;
}
begin = 0;
end = nblocks;
if ((use_cache == TRUE) && (address != NULL))
{
Uint32 index = 0;
Boolean used_io = FALSE;
if (nblocks > 1)
{
TRACE_CACHE("!!!!!!!!!!!!!! nblocks: %d\n", nblocks);
}
while (begin < end)
{
// Try to get a continuous stretch from the beginning in the cache
for (index = begin; index < end; index++)
{
ret = readFromCache(&ide_cache[disk], blockno + index, address + (index * HD_SECTOR_SIZE));
if (ret == -1)
break;
}
begin = index;
if (begin < end)
{
Uint8 *buf;
// We did not find everything in the cache
// Now we must bulk load from the smallest needed sector
// The first sector that we don't have is blockno + begin
// We always want to load up the maximum available
Uint32 cache_load_size;
Int32 ret;
used_io = TRUE;
cache_load_size = getCacheSize(&ide_cache[disk]);
if (diskDesc[disk].currentMultipleTransfer == 0)
{
cache_load_size = 1;
}
/*else
{
if (cache_load_size > diskDesc[disk].currentMultipleTransfer)
cache_load_size = diskDesc[disk].currentMultipleTransfer;
}*/
TRACE_CACHE("!!!!!!!!!!!!!!! Bulk loading to cache starting sector: %d size: %d\n", (blockno + begin), cache_load_size);
ret = bulkLoadToCache(&ide_cache[disk], (blockno + begin), cache_load_size, &buf);
soft_assert(ret == 0);
if (diskDesc[disk].supports48bitAddFeatureSet)
{
cmd.ext_cmd = TRUE;
if (cache_load_size == 1)
cmd.cmdCode = IDE_CMD_READS_EXT;
else
cmd.cmdCode = IDE_CMD_READM_EXT;
}
else
{
cmd.ext_cmd = FALSE;
if (cache_load_size == 1)
cmd.cmdCode = IDE_CMD_READS;
else
cmd.cmdCode = IDE_CMD_READM;
}
//Due to the size of sectorCntReg(Uint8), if (nblocks - i) == 256, sectorCntReg will be 0
cmd.sectorCntReg = cache_load_size;
cmd.lba = blockno + begin;
cmd.driveID = disk;
if ((diskDesc[disk].IsRemovableMediaDevice ) && (diskDesc[disk].MediaDeviceBrand == MEDIADEVICE_BRAND_SAIN))
cmd.featureReg = 1;
else
cmd.featureReg = 0;
cmd.pktCmd = NULL;
cmd.pktCmdSize = 0;
cmd.data = buf;
cmd.deviceReg = LBA_MODE;
cmd.readWrite = IDE_CMD_READ;
cmd.maxDataSize = HD_SECTOR_SIZE * cache_load_size;
TRACE_READ(" block %x sectorCntReg: %d driveID: %d data: 0x%x maxDataSize: %d\n",
cmd.lba, cmd.sectorCntReg, cmd.driveID, cmd.data, cmd.maxDataSize);
return (IDE_SendCmd(&cmd));
}
}
if (used_io == FALSE)
{
//TRACE_CACHE("!!!!!!!!!!!!!! Loaded completely from cache starting sector: %d size: %d\n", blockno, nblocks);
}
}
else
{
if (diskDesc[disk].supports48bitAddFeatureSet)
{
cmd.ext_cmd = TRUE;
if ((end - begin) == 1)
cmd.cmdCode = IDE_CMD_READS_EXT;
else
cmd.cmdCode = IDE_CMD_READM_EXT;
}
else
{
cmd.ext_cmd = FALSE;
if (((end - begin) == 1) || (diskDesc[disk].currentMultipleTransfer <= 1))
cmd.cmdCode = IDE_CMD_READS;
else
cmd.cmdCode = IDE_CMD_READM;
}
//Due to the size of sectorCntReg(Uint8), if (nblocks - i) == 256, sectorCntReg will be 0
cmd.sectorCntReg = end - begin;
cmd.lba = blockno + begin;
cmd.driveID = disk;
if ((diskDesc[disk].IsRemovableMediaDevice ) && (diskDesc[disk].MediaDeviceBrand == MEDIADEVICE_BRAND_SAIN))
cmd.featureReg = 1;
else
cmd.featureReg = 0;
cmd.pktCmd = NULL;
cmd.pktCmdSize = 0;
cmd.data = address + (begin * HD_SECTOR_SIZE);
cmd.deviceReg = LBA_MODE;
cmd.readWrite = IDE_CMD_READ;
cmd.maxDataSize = HD_SECTOR_SIZE * (end - begin);
TRACE_READ(" block %x sectorCntReg: %d driveID: %d data: 0x%x maxDataSize: %d\n",
cmd.lba, cmd.sectorCntReg, cmd.driveID, cmd.data, cmd.maxDataSize);
return (IDE_SendCmd(&cmd));
}
return SUCCESS;
}
#else
static Int32 ide_command_read_sectors (
Uint8 * address, // Destination address for the data
Uint16 disk, // Drive number
Uint32 blockno, // Block number to read
Uint16 nblocks, // Number of blocks (legal range: 1-256)
Boolean use_cache
)
{
IDE_Cmd cmd;
int ret=0, begin, end, j;
/* Check against max_blocks. this is 256 for IDE. In real mode 80xx we limit
it to 128 to eliminate segment wrap. */
if (nblocks > MAX_BLOCKS)
{
ErrPrint(" IDE_INTERNAL \n");
return IDE_INTERNAL;
}
if (!(diskDesc[disk].maxLBA)) /* Should be non zeroe if the disk was initialized */
{
ErrPrint(" IDE_INTERNAL \n");
return IDE_INTERNAL;
}
begin = 0;
if (use_cache == TRUE)
{
// Try to get a continuous stretch from the beginning in the cache
for (begin=0; begin<nblocks; begin++) {
ret = readFromCache(&ide_cache[disk], blockno+begin, address + (begin*HD_SECTOR_SIZE));
if (ret == -1)
break;
}
}
end = nblocks;
if (begin < nblocks)
{
if (use_cache == TRUE)
{
// We did not find everything in the cache
// Try to get a continous stretch from the end in the cache
for (end=nblocks-1; end>begin; end--)
{
ret = readFromCache(&ide_cache[disk], blockno+end, address + (end*HD_SECTOR_SIZE));
if (ret == -1)
break;
}
end++;
}
if ((end - begin) == 1)
cmd.cmdCode = IDE_CMD_READS;
else
cmd.cmdCode = IDE_CMD_READM;
//Due to the size of sectorCntReg(Uint8), if (nblocks - i) == 256, sectorCntReg will be 0
cmd.sectorCntReg = end - begin;
cmd.lba = blockno + begin;
cmd.driveID = diskDesc[disk].driveID;
cmd.featureReg = 0;
cmd.pktCmd = NULL;
cmd.pktCmdSize = 0;
cmd.data = address + (begin*HD_SECTOR_SIZE);
cmd.deviceReg = LBA_MODE;
cmd.readWrite = IDE_CMD_READ;
cmd.maxDataSize = HD_SECTOR_SIZE * (end-begin);
TRACE_READ(" block %x \n", cmd.lba);
ret = IDE_SendCmd(&cmd);
if (use_cache == TRUE)
{
for (j=begin; j<end; j++)
{
Int32 cache_ret;
//DEBUG_OUT("read sectors after failed cache write on sector: %d disk: %d\n", (blockno + j), disk);
cache_ret = loadToCache(&ide_cache[disk], blockno+j, address + (j*HD_SECTOR_SIZE));
soft_assert(cache_ret == 0);
// Since this is a write through cache no page will ever get dirty
// since we are always writing straight to the HDD anyway
// This operation must succeed
}
}
if (ret)
{
return ( ATA_ReadRegister(diskDesc[disk].driveID, ATA_REG_ERROR) & 0xFF);
}
else
{
return SUCCESS;
}
}
return SUCCESS;
}
#endif
//-----------------------------------------------------------------------------
// Function: ide_command_write_sectors
//
// Description:
//
// Called by ide_do_block
//
// This routine is portable
//
//-----------------------------------------------------------------------------
Int32 ide_command_write_sectors(
Uint8 * address, // Source address for the data
Uint16 disk, // Disk number (0 or 1)
Uint32 blockno, // Block number to read
Uint16 nblocks, // Number of blocks (legal range: 1-256)
Boolean use_cache
)
{
IDE_Cmd cmd;
int i;
//TRACE_WRITE("write sectors called\n");
/* Check against max_blocks. this is 256 for IDE. In real mode 80xx we limit
it to 128 to eliminate segment wrap. */
if (nblocks > MAX_BLOCKS)
{
TRACE_ERROR("write sectors fail 1\n");
return IDE_INTERNAL;
}
if (!(diskDesc[disk].maxLBA) && !diskDesc[disk].IsRemovableMediaDevice) /* Should be non zeroe if the disk was initialized */
{
TRACE_ERROR("write sectors fail 2\n");
return IDE_INTERNAL;
}
/* write through cache */
for (i = 0; i < nblocks; i++)
{
//DEBUG_OUT("write sectors writing to cache to sectors: %d\n", (blockno+i));
//writeToCache(&ide_cache[disk], blockno+i, address + (i*HD_SECTOR_SIZE));
//updateCache(&ide_cache[disk], blockno+i, address + (i*HD_SECTOR_SIZE));
invalidateCache(&ide_cache[disk], blockno + i);
}
/* Call the CMD processing routine! */
if (address == NULL)
{
if (diskDesc[disk].supports48bitAddFeatureSet)
{
cmd.ext_cmd = TRUE;
#ifdef RIO_PIO_MODE
if (nblocks == 1)
cmd.cmdCode = IDE_CMD_WRITES_EXT;
else
cmd.cmdCode = IDE_CMD_WRITEM_EXT;
#else
cmd.cmdCode = IDE_CMD_WRITEDMA_EXT;
cmd.ext_cmd = TRUE;
#endif
}
else
{
#ifdef RIO_PIO_MODE
if (nblocks == 1)
cmd.cmdCode = IDE_CMD_WRITES;
else
cmd.cmdCode = IDE_CMD_WRITEM;
#else
cmd.cmdCode = IDE_CMD_WRITEDMA;
cmd.ext_cmd = FALSE;
#endif
}
}
else
{
if (diskDesc[disk].supports48bitAddFeatureSet)
{
cmd.ext_cmd = TRUE;
if (nblocks == 1)
cmd.cmdCode = IDE_CMD_WRITES_EXT;
else
cmd.cmdCode = IDE_CMD_WRITEM_EXT;
}
else
{
cmd.ext_cmd = FALSE;
if (nblocks == 1)
cmd.cmdCode = IDE_CMD_WRITES;
else
cmd.cmdCode = IDE_CMD_WRITEM;
}
}
//Due to the size of sectorCntReg(Uint8), if nblocks == 256, sectorCntReg will be 0
cmd.sectorCntReg = nblocks;
cmd.lba = blockno;
cmd.driveID = disk;
cmd.featureReg = 0;
cmd.pktCmd = NULL;
cmd.pktCmdSize = 0;
cmd.data = address;
cmd.deviceReg = LBA_MODE;
cmd.readWrite = IDE_CMD_WRITE;
cmd.maxDataSize = 512 * nblocks;
return (IDE_SendCmd(&cmd));
}
Int32 writeMBR(Uint8 diskno, Uint32 addr, Uint32 disk_lba_size)
{
PTABLE ppart;
Uint8 end_sec;
Uint16 end_cyl;
Uint8 *buf;
Uint8 bootLoaderCode[0x1be] = {
0x33, 0xC0, 0x8E, 0xD0, 0xBC, 0x00, 0x7C, 0xFB, 0x50, 0x07, 0x50, 0x1F, 0xFC, 0xBE, 0x1B, 0x7C,
0xBF, 0x1B, 0x06, 0x50, 0x57, 0xB9, 0xE5, 0x01, 0xF3, 0xA4, 0xCB, 0xBD, 0xBE, 0x07, 0xB1, 0x04,
0x38, 0x6E, 0x00, 0x7C, 0x09, 0x75, 0x13, 0x83, 0xC5, 0x10, 0xE2, 0xF4, 0xCD, 0x18, 0x8B, 0xF5,
0x83, 0xC6, 0x10, 0x49, 0x74, 0x19, 0x3
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -