⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1004.ide.patch

📁 sm86xx内核源包括补丁( GPL )的
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+	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 + -