📄 1004.ide.patch
字号:
+ ide_hwif_t *hwif = HWIF(drive);++ if (hwif->ide_dma_host_on)+ hwif->ide_dma_host_on(drive);++ if (drive->using_dma)+ return 0;++ printk("%s: DMA enabled for %s%s\n", hwif->name,+ drive->media == ide_disk ? "ATA DISK " :+ (drive->media == ide_cdrom ? "ATAPI CDROM " : ""),+ drive->name);+ drive->using_dma = 1;++ return 0;+}++int tangox_bmide_dma_off_quietly(ide_drive_t *drive)+{+ drive->using_dma = 0;+ return 0;+}++/*+ * dma operations+ */+static unsigned long g_mbus_reg = 0;+static unsigned int g_next_sg = 0;++static ide_startstop_t tangox_dma_intr(ide_drive_t *drive)+{+ ide_hwif_t *hwif = HWIF(drive);+ u8 dma_stat, stat;+ struct request *rq;++ dma_stat = hwif->ide_dma_end(drive);+ stat = HWIF(drive)->INB(IDE_STATUS_REG);++ if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {+ if (!(dma_stat & 1)) {+ rq = HWGROUP(drive)->rq;+ ide_end_request(drive, 1, rq->nr_sectors);+ return ide_stopped;+ }+ printk(KERN_ERR PFX "%s: bad DMA status (dma_stat=%x)\n",+ drive->name, dma_stat);+ }++ return ide_error(drive, "dma_intr", 0);+}++static void tangox_mbus_intr(int irq, void *arg)+{+ ide_drive_t *drive = (ide_drive_t *)arg;+ ide_hwif_t *hwif = HWIF(drive);+ struct scatterlist *sg;++ if (drive->using_dma == 0) {+ printk(KERN_ERR PFX "bug: tangox_mbus_intr called while "+ "using_dma == 0\n");+ return;+ }++ em86xx_mbus_wait(g_mbus_reg, SBOX_IDEDVD);++ /*+ * setup a new mbus transfer+ */+ sg = &hwif->sg_table[g_next_sg];+ g_next_sg++;++ if (em86xx_mbus_setup_dma(g_mbus_reg, sg_dma_address(sg),+ sg_dma_len(sg),+ (g_next_sg == hwif->sg_nents) ? NULL :+ tangox_mbus_intr, drive)) {+ printk(KERN_ERR PFX "fail to resetup dma, wait "+ "for timeout...\n");+ }+}++static void tangox_dma_exec_cmd(ide_drive_t *drive, u8 command)+{+ /* issue cmd to drive, and register interrupt handler for+ * command completion */+ ide_execute_command(drive, command, &tangox_dma_intr, (2 * WAIT_CMD),+ NULL);+}++/* Get the I/O size of given request */+static inline int get_request_size(struct request *rq)+{+ unsigned int rq_size;+ struct bio *bio;+ + for (rq_size = 0, bio = rq->bio; bio != NULL; bio = bio->bi_next)+ rq_size += bio->bi_size;+ + return rq_size;+}++static void tangox_dma_start(ide_drive_t *drive)+{+ ide_hwif_t *hwif = HWIF(drive);+ struct request *rq;+ unsigned long val, len;++ rq = HWGROUP(drive)->rq;+ len = get_request_size(rq);++ /* setup IDE DMA transfer len */+ gbus_writel(REG_BASE_host_interface + IDECTRL_ide_dmalen, len);++ /* enable bus mastering */+ val = 0x05;+ if (hwif->sg_dma_direction == DMA_FROM_DEVICE)+ val |= 0x8;++ gbus_writel(REG_BASE_host_interface + IDECTRL_bmic, val);+}++static int tangox_dma_setup(ide_drive_t *drive)+{+ ide_hwif_t *hwif = HWIF(drive);+ struct request *rq;+ int iswrite;+ struct scatterlist *sg = hwif->sg_table;++ rq = HWGROUP(drive)->rq;++ iswrite = (rq_data_dir(rq) == WRITE);+ hwif->sg_dma_direction = iswrite ? DMA_TO_DEVICE : DMA_FROM_DEVICE;++ /*+ * ide_map_sg will merge contiguous memory zone for us+ */+ ide_map_sg(drive, rq);++ /* try to setup dma channel */+ if (em86xx_mbus_alloc_dma(SBOX_IDEDVD, iswrite ? 0 : 1, &g_mbus_reg,+ NULL)) {+ printk(KERN_ERR PFX "fail to alloc dma, fallback to pio\n");+ goto fallback_pio;+ }++ /*+ * map and transfer first segment+ */+ dma_map_sg(&hwif->gendev, sg, hwif->sg_nents, hwif->sg_dma_direction);+ g_next_sg = 1;++ /*+ * setup mbus dma for this address. we want an mbus interrupt+ * only if this is not the last sg element, so we can refeed+ * mbus.+ */+ if (em86xx_mbus_setup_dma(g_mbus_reg, sg_dma_address(sg),+ sg_dma_len(sg),+ (hwif->sg_nents == 1) ? NULL :+ tangox_mbus_intr, drive)) {+ printk(KERN_ERR PFX "fail to setup dma, fallback to pio\n");+ dma_unmap_sg(&hwif->gendev, sg, hwif->sg_nents,+ hwif->sg_dma_direction);+ em86xx_mbus_free_dma(g_mbus_reg, SBOX_IDEDVD);+ goto fallback_pio;+ }++ drive->waiting_for_dma = 1;+ return 0;++fallback_pio:+ ide_map_sg(drive, rq);+ return 1;+}++static int tangox_bmide_dma_end(ide_drive_t *drive)+{+ ide_hwif_t *hwif = HWIF(drive);+ u8 dma_stat;+ int mbus_stat;+ struct scatterlist *sg = hwif->sg_table;++ dma_stat = hwif->INB(hwif->dma_status);++ /*+ * make sure DMA is not in progress+ */+ if ((dma_stat & 0x7) == 1) {+ printk(KERN_ERR PFX "huh ? dma_end called while dma still "+ "in progress...\n");+ }++ /* clear the INTR & ERROR bits */+ hwif->OUTB(dma_stat | 6, hwif->dma_status);++ /*+ * confirm whether MBUS transfer is done due to the memory+ * arbitration, IDE device thinks the DMA transfer is done,+ * but the data might be held in MBUS FIFO+ */+ mbus_stat = em86xx_mbus_wait(g_mbus_reg, SBOX_IDEDVD);++ /* release mbus */+ em86xx_mbus_free_dma(g_mbus_reg, SBOX_IDEDVD);++ /* stop bus mastering */+ hwif->OUTB(0x4, hwif->dma_command);++ dma_unmap_sg(&hwif->gendev, sg, hwif->sg_nents,+ hwif->sg_dma_direction);+ drive->waiting_for_dma = 0;++ /* fake dma error in case of mbus timeout, else return+ * dma_status error bit */+ return (mbus_stat == 0) ? (dma_stat & 1) : 0x1;+}++static int tangox_bmide_dma_test_irq(ide_drive_t *drive)+{+ ide_hwif_t *hwif = HWIF(drive);+ u8 dma_stat;++ dma_stat = hwif->INB(hwif->dma_status);+ if ((dma_stat & 0x4))+ return 1;+ return 0;+}++static int tangox_bmide_dma_lostirq(ide_drive_t *drive)+{+ return 0;+}++static int tangox_bmide_dma_timeout(ide_drive_t *drive)+{+ return 0;+}+#endif++#ifndef CONFIG_RUNTIME_CLK_CALC+/*+ * timing values for each ide mode+ */+static const unsigned int s_pio_tim[] = {+ 0xff230ee6, 0xd41b0fa4, 0xb4150f63, 0xa7110f62, 0x9a0f0552+};++static const unsigned int s_dma_tim[] = {+ 0xf33333b4, 0xa3130b73, 0x9c100552+};+static const unsigned int s_udma_tim1[] = {+ 0x35440b08, 0x35440a06, 0x35440804+};+static const unsigned int s_udma_tim2[] = {+ 0x00000208, 0x00000206, 0x00000204+};++static const unsigned int s_udma_tim1_alt[] = {+ 0x44442418, 0x44441c10, 0x4444160b, 0x44441608,+ 0x44441605, 0x44441303, 0x44441302, 0x44441302+};+static const unsigned int s_udma_tim2_alt[] = {+ 0x0000010f, 0x0000010a, 0x00000106, 0x00000104,+ 0x00000101, 0x00000202, 0x00000202, 0x00000202+};+#endif /* !CONFIG_RUNTIME_CLK_CALC */+++/*+ * tangox_bmide_tune_drive+ */+static void tangox_bmide_tune_drive(ide_drive_t *drive, u8 pio)+{+ ide_hwif_t *hwif = HWIF(drive);++ if (pio == 255)+ pio = ide_get_best_pio_mode(drive, pio, 4, NULL);+ hwif->speedproc(drive, pio + XFER_PIO_0);+}++/*+ * tangox_bmide_tune_chipset+ */+static int tangox_bmide_tune_chipset(ide_drive_t *drive, u8 xferspeed)+{+ int didx;+ unsigned int ctrlreg, newflag;+ unsigned long flags;+ u8 mode, pio;++#ifdef CONFIG_RUNTIME_CLK_CALC+#define TIMING_MARGIN(x) (((x) * 105) / 100) /* add 5% margin */+//#define TIMING_MARGIN(x) (x) /* no margin added */+ extern unsigned long tangox_get_sysclock(void);+ unsigned int ide_clock = TIMING_MARGIN(tangox_get_sysclock() / 1000000); /* in MHz */+#endif+ + didx = drive->select.b.unit;+ newflag = 0;++ spin_lock_irqsave(&bmide_tune_chipset_spin_lock, flags);++ if (xferspeed >= XFER_PIO_0 && xferspeed <= XFER_PIO_4) {+ /*+ * setup timing for PIO mode+ */+ mode = xferspeed - XFER_PIO_0;+ printk("%s: set to PIO mode %d\n", drive->name, mode);++ /* fast timing for PIO */+ newflag = 0x01;++#ifdef CONFIG_RUNTIME_CLK_CALC+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0tim : IDECTRL_pri_drv1tim), + CalcRegValTiming_PIO_DMA(&(j2_pio_timings[mode]), ide_clock));+#else+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0tim : IDECTRL_pri_drv1tim), + s_pio_tim[mode]);+#endif++ }+#ifdef CONFIG_BLK_DEV_BMIDE_TANGOX_DMA+ else if (xferspeed >= XFER_MW_DMA_0 && xferspeed <= XFER_MW_DMA_2) {+ /*+ * setup timing for Multi-word DMA+ */+ mode = xferspeed - XFER_MW_DMA_0;+ printk("%s: set to Multi-word DMA mode %d\n", drive->name,+ mode);++ /* fast timing for PIO, prefetch enable */+ newflag = 0x05;++#ifdef CONFIG_RUNTIME_CLK_CALC+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0tim : IDECTRL_pri_drv1tim), + CalcRegValTiming_PIO_DMA(&(j2_dma_timings[mode]), ide_clock));+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0udmatim1 : IDECTRL_pri_drv1udmatim1), + CalcRegValTiming1_UDMA(&(j2_udma_timings[mode]), ide_clock));+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0udmatim2 : IDECTRL_pri_drv1udmatim2), + CalcRegValTiming2_UDMA(&(j2_udma_timings[mode]), ide_clock));+#else+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0tim : IDECTRL_pri_drv1tim), + s_dma_tim[mode]);+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0udmatim1 : IDECTRL_pri_drv1udmatim1), + s_udma_tim1[mode]);+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0udmatim2 : IDECTRL_pri_drv1udmatim2), + s_udma_tim2[mode]);+#endif++ } +#endif+#ifdef CONFIG_BLK_DEV_BMIDE_TANGOX_UDMA+ else if (xferspeed >= XFER_UDMA_0 && xferspeed <= XFER_UDMA_7) {+ unsigned int val;++ /*+ * setup timing for Ultra DMA+ */+ mode = xferspeed - XFER_UDMA_0;+ printk("%s: set to Ultra DMA mode %d\n", drive->name, mode);++ newflag = 0x00;++ /* enable Ultra DMA */+ val = gbus_readl(REG_BASE_host_interface + IDECTRL_udmactl);+ val |= (didx == 0) ? 0x01 : 0x02;+ gbus_writel(REG_BASE_host_interface + IDECTRL_udmactl, val);++#ifdef CONFIG_RUNTIME_CLK_CALC+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0udmatim1 : IDECTRL_pri_drv1udmatim1), + CalcRegValTiming1_UDMA(&(j2_udma_timings[mode]), ide_clock));+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0udmatim2 : IDECTRL_pri_drv1udmatim2), + CalcRegValTiming2_UDMA(&(j2_udma_timings[mode]), ide_clock));+#else+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0udmatim1 : IDECTRL_pri_drv1udmatim1), + s_udma_tim1_alt[mode]);+ gbus_writel(REG_BASE_host_interface ++ ((didx == 0) ? IDECTRL_pri_drv0udmatim2 : IDECTRL_pri_drv1udmatim2), + s_udma_tim2_alt[mode]);+#endif+ }+#endif+ else {+ printk("%s: unknown speed to be set %d\n", drive->name, xferspeed);+ }++ ctrlreg = gbus_readl(REG_BASE_host_interface + IDECTRL_pri_idectl);+ ctrlreg &= ~(didx == 0 ? 0xf : 0xf0);+ ctrlreg |= newflag << (didx * 4);+ gbus_writel(REG_BASE_host_interface + IDECTRL_pri_idectl, ctrlreg);++ spin_unlock_irqrestore(&bmide_tune_chipset_spin_lock, flags);++#ifdef CONFIG_BLK_DEV_BMIDE_TANGOX_DMA+ if (xferspeed >= XFER_SW_DMA_0)+ pio = dma_2_pio(xferspeed);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -