ide-ep93xx.c
来自「一个2.4.21版本的嵌入式linux内核」· C语言 代码 · 共 2,386 行 · 第 1/5 页
C
2,386 行
* if already at the bottom.
*/
switch (drive->current_speed) {
case XFER_UDMA_4:
ide_config_drive_speed(drive, XFER_UDMA_3);
break;
case XFER_UDMA_3:
ide_config_drive_speed(drive, XFER_UDMA_2);
break;
case XFER_UDMA_2:
ide_config_drive_speed(drive, XFER_UDMA_1);
break;
case XFER_UDMA_1:
ide_config_drive_speed(drive, XFER_UDMA_0);
break;
case XFER_UDMA_0:
HWIF(drive)->ide_dma_off(drive);
break;
case XFER_MW_DMA_2:
ide_config_drive_speed(drive, XFER_MW_DMA_1);
break;
case XFER_MW_DMA_1:
ide_config_drive_speed(drive, XFER_MW_DMA_0);
break;
case XFER_MW_DMA_0:
HWIF(drive)->ide_dma_off(drive);
break;
}
/*
* Reset the consecutive error counters for this drive.
*/
g_errors[i] = 0;
g_errors[i ^ 1] = 0;
}
/*
* Fail the transfer.
*/
rv = DMA_END_FAIL;
goto end;
} else
/*
* Success, so reset the consecutive error counter.
*/
g_errors[i] = 0;
/*
* Success.
*/
end:
if(drive->ep93xx_if_test & TEST_FOR_WRITE)
{
if(failcode == DMA_FAIL_CODE_BUFFER_BUSY_WRITE)
{
while(1);
}
if(failcode == DMA_FAIL_CODE_FIFO_STATUS_WRITE)
{
while(1);
}
}
if(drive->ep93xx_if_test & TEST_FOR_READ)
{
if(failcode == DMA_FAIL_CODE_FIFO_STATUS_READ)
{
while(1);
}
if(failcode == DMA_FAIL_CODE_BUFFER_BUSY_READ)
{
while(1);
}
}
if(drive->ep93xx_if_test & HALT_ON_CRC_ERROR)
{
if(failcode == DMA_FAIL_CODE_CRC_READ)
{
while(1);
}
if(failcode == DMA_FAIL_CODE_CRC_WRITE)
{
while(1);
}
}
return rv;
}
#endif
/*****************************************************************************
*
* ep93xx_ide_dma_test_irq()
*
* This function checks if the IDE interrupt is asserted and returns a
* 1 if it is, and 0 otherwise..
*
****************************************************************************/
static int
ep93xx_ide_dma_test_irq(ide_drive_t *drive)
{
DPRINTK("%s: ep93xx_ide_dma_test_irq\n", drive->name);
if (!drive->waiting_for_dma)
printk(KERN_WARNING "%s: %s called while not waiting\n",
drive->name, __FUNCTION__);
/*
* Return the value of the IDE interrupt bit.
*/
return inl(IDECR) & IDECtrl_INTRQ;
}
/*****************************************************************************
*
* ep93xx_ide_dma_count()
*
****************************************************************************/
static int
ep93xx_ide_dma_count(ide_drive_t *drive)
{
DPRINTK("%s: ep93xx_ide_dma_count\n", drive->name);
return 0;
}
/*****************************************************************************
*
* ep93xx_ide_dma_verbose()
*
****************************************************************************/
static int
ep93xx_ide_dma_verbose(ide_drive_t *drive)
{
DPRINTK("%s: ep93xx_ide_dma_verbose\n", drive->name);
printk(", %s ", ide_xfer_verbose(drive->current_speed));
return 1;
}
/*****************************************************************************
*
* ep93xx_ide_dma_bad_timeout()
*
****************************************************************************/
static int
ep93xx_ide_dma_timeout(ide_drive_t *drive)
{
DPRINTK("%s: ep93xx_ide_dma_timeout\n", drive->name);
if (HWIF(drive)->ide_dma_test_irq(drive))
return 0;
return HWIF(drive)->ide_dma_end(drive);
}
/*****************************************************************************
*
* ep93xx_ide_dma_lostirq()
*
****************************************************************************/
static int
ep93xx_ide_dma_lostirq(ide_drive_t *drive)
{
DPRINTK("%s: ep93xx_ide_dma_lostirq\n", drive->name);
printk("%s: DMA interrupt recovery\n", drive->name);
return 1;
}
/*****************************************************************************
*
* functions to set up the IDE control register and data register to read
* or write a byte of data to/from the specified IDE device register.
*
****************************************************************************/
static void
ep93xx_ide_outb(u8 b, unsigned long addr)
{
unsigned int uiIDECR;
/*
* Write the address out.
*/
uiIDECR = IDECtrl_DIORn | IDECtrl_DIOWn | ((addr & 7) << 2) |
(addr >> 10);
outl(uiIDECR, IDECR);
/*
* Write the data out.
*/
outl(b, IDEDATAOUT);
/*
* Toggle the write signal.
*/
outl(uiIDECR & ~IDECtrl_DIOWn, IDECR);
outl(uiIDECR, IDECR);
}
static void
ep93xx_ide_outbsync(ide_drive_t *drive, u8 b, unsigned long addr)
{
unsigned int uiIDECR;
/*
* Write the address out.
*/
uiIDECR = IDECtrl_DIORn | IDECtrl_DIOWn | ((addr & 7) << 2) |
(addr >> 10);
outl(uiIDECR, IDECR);
/*
* Write the data out.
*/
outl(b, IDEDATAOUT);
/*
* Toggle the write signal.
*/
outl(uiIDECR & ~IDECtrl_DIOWn, IDECR);
outl(uiIDECR, IDECR);
}
static unsigned char
ep93xx_ide_inb(unsigned long addr)
{
unsigned int uiIDECR;
/*
* Write the address out.
*/
uiIDECR = IDECtrl_DIORn | IDECtrl_DIOWn | ((addr & 7) << 2) |
(addr >> 10);
outl(uiIDECR, IDECR);
/*
* Toggle the read signal.
*/
outl(uiIDECR & ~IDECtrl_DIORn, IDECR);
outl(uiIDECR, IDECR);
/*
* Read the data in.
*/
return(inl(IDEDATAIN) & 0xff);
}
/*****************************************************************************
*
* functions to set up the IDE control register and data restister to read
* or write 16 bits of data to/from the specified IDE device register.
* These functions should only be used when reading/writing data to/from
* the data register.
*
****************************************************************************/
static void
ep93xx_ide_outw(u16 w, unsigned long addr)
{
unsigned int uiIDECR;
/*
* Write the address out.
*/
uiIDECR = IDECtrl_DIORn | IDECtrl_DIOWn | ((addr & 7) << 2) |
(addr >> 10);
outl(uiIDECR, IDECR);
/*
* Write the data out.
*/
outl(w, IDEDATAOUT);
/*
* Toggle the write signal.
*/
outl(uiIDECR & ~IDECtrl_DIOWn, IDECR);
outl(uiIDECR, IDECR);
}
static u16
ep93xx_ide_inw(unsigned long addr)
{
unsigned int uiIDECR;
/*
* Write the address out.
*/
uiIDECR = IDECtrl_DIORn | IDECtrl_DIOWn | ((addr & 7) << 2) |
(addr >> 10);
outl(uiIDECR, IDECR);
/*
* Toggle the read signal.
*/
outl(uiIDECR & ~IDECtrl_DIORn, IDECR);
outl(uiIDECR, IDECR);
/*
* Read the data in.
*/
return(inl(IDEDATAIN) & 0xffff);
}
/*****************************************************************************
*
* functions to read/write a block of data to/from the ide device using
* PIO mode.
*
****************************************************************************/
static void
ep93xx_ide_insw(unsigned long addr, void *buf, u32 count)
{
unsigned short *data = (unsigned short *)buf;
/*
* Read in data from the data register 16 bits at a time.
*/
for (; count; count--)
*data++ = ep93xx_ide_inw(addr);
}
static void
ep93xx_ide_outsw(unsigned long addr, void *buf, u32 count)
{
unsigned short *data = (unsigned short *)buf;
/*
* Write out data to the data register 16 bits at a time.
*/
for (; count; count--)
ep93xx_ide_outw(*data++, addr);
}
static void
ep93xx_ata_input_data(ide_drive_t *drive, void *buffer, u32 count)
{
/*
* Read in the specified number of half words from the ide interface.
*/
ep93xx_ide_insw(IDE_DATA_REG, buffer, count << 1);
}
static void
ep93xx_ata_output_data(ide_drive_t *drive, void *buffer, u32 count)
{
/*
* write the specified number of half words from the ide interface
* to the ide device.
*/
ep93xx_ide_outsw(IDE_DATA_REG, buffer, count << 1);
}
static void
ep93xx_atapi_input_bytes(ide_drive_t *drive, void *buffer, u32 count)
{
/*
* read in the specified number of bytes from the ide interface.
*/
ep93xx_ide_insw(IDE_DATA_REG, buffer, (count >> 1) + (count & 1));
}
static void
ep93xx_atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 count)
{
/*
* Write the specified number of bytes from the ide interface
* to the ide device.
*/
ep93xx_ide_outsw(IDE_DATA_REG, buffer, (count >> 1) + (count & 1));
}
/*****************************************************************************
*
* ep93xx_ide_init()
*
* This function sets up a pointer to the ep93xx specific ideproc funciton.
*
****************************************************************************/
void
ep93xx_ide_init(void)
{
DPRINTK("ep93xx_ide_init\n");
hw_regs_t hw;
struct hwif_s *hwif;
unsigned int uiTemp;
/*
* Make sure the GPIO on IDE bits in the DEVCFG register are not set.
*/
uiTemp = inl(SYSCON_DEVCFG) & ~(SYSCON_DEVCFG_EonIDE |
SYSCON_DEVCFG_GonIDE |
SYSCON_DEVCFG_HonIDE);
SysconSetLocked( SYSCON_DEVCFG, uiTemp );
/*
* Insure that neither device is selected.
*/
// if (MODE_SWITCH_FIX)
outl(inl(IDECR) | (IDECtrl_CS0n | IDECtrl_CS1n), IDECR);
/*
* Make sure that MWDMA and UDMA are disabled.
*/
outl(0, IDEMDMAOP);
outl(0, IDEUDMAOP);
/*
* Set up the IDE interface for PIO transfers, using the default PIO
* mode.
*/
outl(IDECfg_IDEEN | IDECfg_PIO | (4 << IDECfg_MODE_SHIFT) |
(1 << IDECfg_WST_SHIFT), IDECFG);
/*
* Setup the ports.
*/
ide_init_hwif_ports(&hw, 0x800, 0x406, NULL);
/*
* Get the interrupt.
*/
hw.irq = IRQ_EIDE;
/*
* This is the dma channel number assigned to this IDE interface. Until
* dma is enabled for this interface, we set it to NO_DMA.
*/
hw.dma = NO_DMA;
/*
* Register the IDE interface, an ide_hwif_t pointer is passed in,
* which will get filled in with the hwif pointer for this interface.
*/
ide_register_hw(&hw, &hwif);
/*
* Set up the HW interface function pointers with the ep93xx specific
* function.
*/
hwif->ata_input_data = ep93xx_ata_input_data;
hwif->ata_output_data = ep93xx_ata_output_data;
hwif->atapi_input_bytes = ep93xx_atapi_input_bytes;
hwif->atapi_output_bytes = ep93xx_atapi_output_bytes;
hwif->OUTB = ep93xx_ide_outb;
hwif->OUTBSYNC = ep93xx_ide_outbsync;
hwif->OUTW = ep93xx_ide_outw;
hwif->OUTSW = ep93xx_ide_outsw;
hwif->INB = ep93xx_ide_inb;
hwif->INW = ep93xx_ide_inw;
hwif->INSW = ep93xx_ide_insw;
/*
* Only enable IDE DMA on rev D1 and later chips.
*/
if ((inl(SYSCON_CHIPID) >> 28) > 3) {
DPRINTK("ep93xx_ide_init- dma enabled \n");
/*
* Allocate memory for the DMA table.
*/
g_dma_table_base = kmalloc(PRD_ENTRIES * PRD_BYTES,
GFP_KERNEL);
/*
* Check if we allocated memory for dma
*/
if (g_dma_table_base == NULL) {
printk("%s: SG-DMA disabled, UNABLE TO ALLOCATE DMA TABLES\n"
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?