📄 ide-ep93xx.c
字号:
*/ if (g_errors[i] == FAILURES_BEFORE_BACKOFF) { /* * Drop down to the next lowest transfer rate, or PIO * 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. */ return 1; } else /* * Success, so reset the consecutive error counter. */ g_errors[i] = 0; /* * Success. */ return 0;}/***************************************************************************** * * 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 intep93xx_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 intep93xx_ide_dma_count(ide_drive_t *drive){ DPRINTK("%s: ep93xx_ide_dma_count\n", drive->name); return 0;}/***************************************************************************** * * ep93xx_ide_dma_verbose() * ****************************************************************************/static intep93xx_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 intep93xx_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 intep93xx_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 voidep93xx_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 voidep93xx_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 charep93xx_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 voidep93xx_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 u16ep93xx_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 voidep93xx_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 voidep93xx_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 voidep93xx_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 voidep93xx_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 voidep93xx_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 voidep93xx_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. * ****************************************************************************/voidep93xx_ide_init(void){ hw_regs_t hw; struct hwif_s *hwif; unsigned int uiTemp; DPRINTK("ep93xx_ide_init\n"); //hzh /* * 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 ); /* * 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", hwif->name); return; } /* * Allocate memory for the scatterlist structures. */ hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, GFP_KERNEL); /* * Check if we allocated the memory we expected to. */ if (hwif->sg_table == NULL) { /* * Fail, so clean up. */ kfree(g_dma_table_base); printk("%s: SG-DMA disabled, UNABLE TO ALLOCATE DMA TABLES\n", hwif->name); return; } /* * Init the dma handle to 0. This field is used to hold a * handle to the dma instance. */ hwif->hw.dma = 0; /* * Open an instance of the ep93xx dma interface. */ if (ep93xx_dma_request(&hwif->hw.dma, hwif->name, DMA_IDE) != 0) { /* * Fail, so clean up. */ kfree(g_dma_table_base); kfree(hwif->sg_table); printk("%s: SG-DMA disabled, unable to allocate DMA channel.\n", hwif->name); return; } /* * Now that we've got a dma channel allocated, set up the rest * of the dma specific stuff. */ DPRINTK("\n ide init- dma channel allocated: %d \n", hwif->hw.dma); /* * Enable dma support for atapi devices. */ hwif->atapi_dma = 1; hwif->ultra_mask = 0x07; hwif->mwdma_mask = 0x00; hwif->swdma_mask = 0x00; hwif->speedproc = NULL; hwif->autodma = 1; hwif->ide_dma_check = ep93xx_ide_dma_check; hwif->ide_dma_host_off = ep93xx_ide_dma_host_off; hwif->ide_dma_off_quietly = ep93xx_ide_dma_off_quietly; hwif->ide_dma_off = ep93xx_ide_dma_off; hwif->ide_dma_host_on = ep93xx_ide_dma_host_on; hwif->ide_dma_on = ep93xx_ide_dma_on; hwif->ide_dma_read = ep93xx_ide_dma_first_read; hwif->ide_dma_write = ep93xx_ide_dma_write; hwif->ide_dma_count = ep93xx_ide_dma_count; hwif->ide_dma_begin = ep93xx_ide_dma_begin; hwif->ide_dma_end = ep93xx_ide_dma_end; hwif->ide_dma_test_irq = ep93xx_ide_dma_test_irq; hwif->ide_dma_verbose = ep93xx_ide_dma_verbose; hwif->ide_dma_timeout = ep93xx_ide_dma_timeout; hwif->ide_dma_lostirq = ep93xx_ide_dma_lostirq; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -