📄 ide_ata.c
字号:
/************************************************************************
// ide_ata.c
//
// Modification History:
// $Id: ide_ata.c,v 1.18 2005/10/05 09:38:06 raphael Exp $
// $Log: ide_ata.c,v $
// Revision 1.18 2005/10/05 09:38:06 raphael
// Merge SONATA2_7_8 into Sonata2Customer head.
//
// Revision 1.66.4.2 2005/08/17 08:16:27 hwxiao
// modify HDD sleep mode. add idle Immediate command.
//
// Revision 1.66.4.1 2005/07/25 04:04:23 shu
// Synchronize core to SONATA2_6_RC_BRANCH
//
// Revision 1.65.6.2 2005/07/22 10:35:00 hwxiao
// fix bug 37512 Card Reader : show firmware version
//
// Revision 1.65.6.1 2005/06/24 03:06:00 hwxiao
// fix 37584, add timeout and modify polling module
//
// Revision 1.65 2005/04/19 21:56:15 rinllow
// reorganize card reader state machine
//
// Revision 1.64 2005/04/11 02:09:07 hwxiao
// fix bug 34912,add parameter for hdd_scheduler_get_cmd_ret
//
// Revision 1.63 2005/03/23 08:34:45 hwxiao
// fix bug 32478, if hdd not found, return IDE_IO_ERROR
//
// Revision 1.62 2005/03/16 09:57:31 hwxiao
// fix bug 34173,modify invalidate function
//
// Revision 1.61 2005/02/17 07:19:08 hwxiao
// fix Bug 33582, clear soft assert if there is Extended MS-DOS Partition
// on media for flash card
//
// Revision 1.60 2005/02/17 02:10:23 hwxiao
// if card reader is disconnected, media thread exit.
//
// Revision 1.59 2005/02/15 03:06:37 mahashin
// fix for bug 33566
// Added ide driver first initialization to ide_open in addition to existing in ide_init_drive to
// prevent assert on unitialized variable in ide_open.
//
// Revision 1.58 2005/02/13 22:52:31 mahashin
// Port of fixes from 2.4.8 branch.
//
// Revision 1.57 2005/02/10 01:02:52 jsu
// [30992] added PIO mode to Rio->HDD transfer
//
// Revision 1.56 2005/02/06 05:31:00 rinllow
// [32711] fix memory card reader issues
//
// Revision 1.55 2005/02/02 07:29:28 hwxiao
// 1) fix bug 31418,31479, modify for flash card hot plug
// 2) if card reader is disconnected, error register is 0,return FAIL
//
// Revision 1.54 2005/01/14 18:24:08 mahashin
// Added log header
//
//
*************************************************************************/
#include "nucleus.h"
#include "basetype.h"
#include "osapi.h"
#include "apitypes.h"
#include "eromdbg.h"
#include "chips.h"
#include "host.h"
#include "ide.h"
#include "apiconfig.h"
#include "hdcache.h"
#ifdef STREAM_ENABLE
#include "hdd_scheduler.h"
#endif
#include "ata.h"
#include "assert.h"
#include "bsp_io.h"
#include "string.h"
#undef FORCE_FORMAT
//#define FORCE_FORMAT
#define DEBUG_WINDOW 3
#define TRACE_48BIT(fmt, args...) //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_BIG(fmt, args...) //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_DEBUG(fmt, args...) //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_STDBY(fmt, args...) //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_ID(fmt, args...) //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define DEBUG_OUT(fmt, args...) //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_CACHE(fmt, args...) //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_ERROR(fmt, args...) {ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_WRITE(fmt, args...) //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_READ(fmt, args...) //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define LOG_DIAG_ERROR(fmt, args...) //{if (ide_diag_mode == TRUE) ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
//-----------------------------------------------------------------------------
// Local definitions
//-----------------------------------------------------------------------------
#define MAX_BLOCKS 256
#define HD_WAIT_TIMEOUT 240
#define CSWAP16(x) (((Uint16)(x) << 8) | \
((Uint16)(x) >> 8))
#define CSWAP32(x) ((((Uint32)(x) >> 24) & 0x000000ff) | \
(((Uint32)(x) >> 8) & 0x0000ff00) | \
(((Uint32)(x) << 8) & 0x00ff0000) | \
(((Uint32)(x) << 24) & 0xff000000))
#define DRIVE_SELECT(driveID) ((driveID & 1) ? 0xB0 : 0xA0)
/*==========================================================================*/
ide_drive_desc diskDesc[NDISKS];
logical_drive_desc driveDesc[NDRIVES * NDISKS];
//-----------------------------------------------------------------------------
// Local functions
//-----------------------------------------------------------------------------
static Int32 ide_command_diags (Uint8 driveID);
static Int32 ide_command_read_sectors (Uint8 * address, Uint16 disk, Uint32 blockno, Uint16 nblocks, Boolean use_cache);
Int32 ide_command_write_sectors(Uint8 * address, Uint16 disk, Uint32 blockno, Uint16 nblocks, Boolean use_cache);
static Int32 ide_controller_init(ide_drive_desc* desc);
//-----------------------------------------------------------------------------
// External declarations
//-----------------------------------------------------------------------------
extern NU_SEMAPHORE* HstBusSem;
//-----------------------------------------------------------------------------
// Local variables
//-----------------------------------------------------------------------------
/* The control structure - without too much difficulty we could go to
** multiple controllers!
*/
static Uint8 ide_initialized = FALSE;
Boolean ide_diag_mode = FALSE;
/* Logical open count per partition.
** We also increment this on raw opens! */
static cachingSystem ide_cache[NDISKS];
void UtilSwap16(Uint16 *to, Uint16 *from)
{
Uint8 *fptr;
Uint8 *tptr;
fptr = (Uint8 *)from;
tptr = (Uint8 *)to;
*tptr = *(fptr + 1);
*(tptr + 1) = *(fptr);
}
void UtilSwap32(Uint32 *to, Uint32 *from)
{
Uint8 *fptr;
Uint8 *tptr;
fptr = (Uint8 *)from;
tptr = (Uint8 *)to;
*tptr = *(fptr + 3);
*(tptr + 1) = *(fptr + 2);
*(tptr + 2) = *(fptr + 1);
*(tptr + 3) = *(fptr);
}
void UtilThrough16(Uint16 *to, Uint16 *from)
{
Uint8 *fptr;
Uint8 *tptr;
fptr = (Uint8 *)from;
tptr = (Uint8 *)to;
*tptr = *fptr;
*(tptr + 1) = *(fptr + 1);
}
void UtilThrough32(Uint32 *to, Uint32 *from)
{
Uint8 *fptr;
Uint8 *tptr;
fptr = (Uint8 *)from;
tptr = (Uint8 *)to;
*tptr = *fptr;
*(tptr + 1) = *(fptr + 1);
*(tptr + 2) = *(fptr + 2);
*(tptr + 3) = *(fptr + 3);
}
Int32 ide_device_version(Uint8 driveID, char **firmware_version)
{
*firmware_version = diskDesc[driveID].firmware;
TRACE_ID("ide_device_version: 0x%x[%s]\n", firmware_version, firmware_version);
return SUCCESS;
}
Uint32 ide_set_multiple(Uint8 driveID, Uint32 multiple)
{
IDE_Cmd cmd;
if ( diskDesc[driveID].MediaDeviceBrand== MEDIADEVICE_BRAND_SAIN)
{
return SUCCESS;
}
cmd.driveID = driveID;
cmd.cmdCode = IDE_CMD_SETM;
cmd.sectorCntReg = multiple;
cmd.lba = 0;
cmd.featureReg = 0;
cmd.pktCmd = NULL;
cmd.pktCmdSize = 0;
cmd.data = 0;
cmd.deviceReg = LBA_MODE;
cmd.readWrite = 0;
cmd.maxDataSize = 0;
cmd.ext_cmd = FALSE;
DEBUG_OUT("set multiple to: %d %d\n", cmd.sectorCntReg, driveID);
if (IDE_SendCmd(&cmd))
{
return IDE_IO_ERROR;
}
else
{
return SUCCESS;
}
}
//-----------------------------------------------------------------------------
Uint32 IDE_SendCmd(IDE_Cmd *cmd)
{
Uint32 res;
// fixme tango look
ATA_LockBus(cmd->driveID);
ATA_LockDevice(cmd->driveID);
res = IDE_Send(cmd);
switch (cmd->cmdCode)
{
case IDE_CMD_MSNS:
case IDE_CMD_MEDIA:
if (res)
{
res = ATA_ReadRegister(cmd->driveID, ATA_REG_ERROR) & 0xFF;
}
else
{
//ErrPrint(" MI %x \n", ATA_ReadRegister(cmd->driveID, ATA_REG_SECTOR_NUM));
}
break;
case IDE_CMD_READS_EXT:
case IDE_CMD_READM_EXT:
case IDE_CMD_READS:
case IDE_CMD_READM:
case IDE_CMD_WRITEDMA_EXT:
case IDE_CMD_WRITEDMA:
case IDE_CMD_WRITES_EXT:
case IDE_CMD_WRITEM_EXT:
case IDE_CMD_WRITES:
case IDE_CMD_WRITEM:
case IDE_CMD_IDLE_IMMEDIATE:
if (res)
{
res = ATA_ReadRegister(cmd->driveID, ATA_REG_ERROR) & 0xFF;
ErrPrint("IDE_SendCmd error: driveID[%d] cmd[0x%x] err[0x%x]\n", cmd->driveID, cmd->cmdCode, res);
}
break;
case IDE_CMD_MEDIA_TYPE:
if (res)
{
res = ATA_ReadRegister(cmd->driveID, ATA_REG_ERROR) & 0xFF;
ErrPrint("IDE_SendCmd error: driveID[%d] cmd[0x%x] err[0x%x]\n", cmd->driveID, cmd->cmdCode, res);
res = 0;
}else
{
res = ATA_ReadRegister(cmd->driveID, ATA_REG_SECTOR_NUM) & 0xFF;
}
break;
default:
break;
}
// fixme tango look
ATA_ReleaseDevice(cmd->driveID);
ATA_ReleaseBus(cmd->driveID);
return res;
}
//-----------------------------------------------------------------------------
Uint32 IDE_Send(IDE_Cmd *cmd)
{
unsigned int byteCnt, byteTx = 0;
unsigned char *buf = cmd->data;
Uint32 error;
Uint32 status = 0;
unsigned int i;
unsigned int maxTransfer, totalSecNum;
ATA_Error_t retval;
Uint32 feature;
Uint32 hd_cmd;
if ((cmd->pktCmdSize != 0) && (cmd->pktCmdSize != 12))
{
TRACE_ERROR("Warning, sending IDE_Cmd %x with pktCmdSize %x\n", cmd->cmdCode, cmd->pktCmdSize);
LOG_DIAG_ERROR("Warning, sending IDE_Cmd %x with pktCmdSize %x\n", cmd->cmdCode, cmd->pktCmdSize);
}
//if (ATA_WaitNotBusy(cmd->driveID, HD_WAIT_TIMEOUT) == ATA_FAIL)
//{
// TRACE_ERROR("Timeout Waiting For Drive Not Busy 1\n");
// LOG_DIAG_ERROR("Timeout Waiting For Drive Not Busy 1\n");
// return (IDE_ERRORCODE_TIMEOUT);
//}
ATA_WriteRegister(cmd->driveID, ATA_REG_DRIVE_SEL, DRIVE_SELECT(cmd->driveID) |
(LBA_MODE & 0x40));
//if (ATA_WaitNotBusy(cmd->driveID, HD_WAIT_TIMEOUT) == ATA_FAIL)
//{
// TRACE_ERROR("Timeout Waiting For Drive Not Busy 2\n");
// LOG_DIAG_ERROR("Timeout Waiting For Drive Not Busy 2\n");
// return (IDE_ERRORCODE_TIMEOUT);
//}
if (ATA_WaitDriveDRdy(cmd->driveID, HD_WAIT_TIMEOUT) == ATA_FAIL)
{
TRACE_ERROR("Timeout Waiting For Drive Drdy 3 driveID = %d cmd = 0x%x\n", cmd->driveID, cmd->cmdCode);
LOG_DIAG_ERROR("Timeout Waiting For Drive Drdy 3\n");
return (IDE_ERRORCODE_TIMEOUT);
}
feature = cmd->featureReg;
hd_cmd = cmd->cmdCode;
#ifdef RIO_PIO_MODE
if (hd_cmd == IDE_CMD_WRITEDMA)
hd_cmd = IDE_CMD_WRITEM;
#endif
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_FEATURE, feature);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 4: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 4: 0x%x\n", retval);
}
// Writing the adress differes on 48bit feature set or not
if (diskDesc[cmd->driveID].supports48bitAddFeatureSet && cmd->ext_cmd)
//if (diskDesc[cmd->driveID].supports48bitAddFeatureSet == TRUE)
{
Uint32 sector_cnt_7_0;
Uint32 sector_cnt_15_8;
Uint32 lba_7_0;
Uint32 lba_15_8;
Uint32 lba_23_16;
Uint32 lba_31_24;
Uint32 lba_39_32;
Uint32 lba_47_40;
Uint32 device;
sector_cnt_7_0 = cmd->sectorCntReg & 0xFF;
sector_cnt_15_8 = (cmd->sectorCntReg >> 8) & 0xFF;
lba_7_0 = cmd->lba & 0xFF;
lba_15_8 = (cmd->lba >> 8) & 0xFF;
lba_23_16 = (cmd->lba >> 16) & 0xFF;
lba_31_24 = (cmd->lba >> 24) & 0xFF;
lba_39_32 = 0;
lba_47_40 = 0;
// The 48-bit Address feature set operates in LBA only.
device = LBA_MODE | DRIVE_SELECT(cmd->driveID);
//TRACE_48BIT("IDE_Send - doing 48bit addressing\n");
// sector cnt
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_SECTOR_CNT, sector_cnt_15_8);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 5: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 5: 0x%x\n", retval);
}
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_SECTOR_CNT, sector_cnt_7_0);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 5: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 5: 0x%x\n", retval);
}
// lba low
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_LOW, lba_31_24);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 6: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 6: 0x%x\n", retval);
}
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_LOW, lba_7_0);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 6: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 6: 0x%x\n", retval);
}
// lba mid
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_MID, lba_39_32);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 7: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 7: 0x%x\n", retval);
}
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_MID, lba_15_8);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 7: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 7: 0x%x\n", retval);
}
// lba high
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_HIGH, lba_47_40);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 8: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 8: 0x%x\n", retval);
}
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_HIGH, lba_23_16);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 8: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 8: 0x%x\n", retval);
}
// device
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_DRIVE_SEL, device);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 9: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 9: 0x%x\n", retval);
}
}
else
{
Uint32 sector_cnt;
Uint32 lba_low;
Uint32 lba_mid;
Uint32 lba_high;
Uint32 device;
sector_cnt = cmd->sectorCntReg;
lba_low = cmd->lba & 0xFF;
lba_mid = (cmd->lba >> 8) & 0xFF;
lba_high = (cmd->lba >> 16) & 0xFF;
device =
DRIVE_SELECT(cmd->driveID) |
(cmd->deviceReg & LBA_MODE) |
((cmd->lba >> 24) & 0x0F);
//TRACE_48BIT("IDE_Send - doing regular addressing\n");
// sector cnt
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_SECTOR_CNT, sector_cnt);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -