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

📄 1004.ide.patch

📁 sm86xx内核源包括补丁( GPL )的
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
++static void tangox_pbide_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, &ide_dma_intr, (2 * WAIT_CMD), NULL);+}++static void tangox_pbide_dma_start(ide_drive_t *drive)+{+	return;+}++static int tangox_pbide_dma_lostirq(ide_drive_t *drive)+{+	return 0;+}++static int tangox_pbide_dma_timeout(ide_drive_t *drive)+{+	return 0;+}++static int tangox_pbide_dma_host_on(ide_drive_t *drive)+{+	return 0;+}++static int tangox_pbide_dma_host_off(ide_drive_t *drive)+{+	return 0;+}++static int tangox_pbide_dma_on(ide_drive_t *drive)+{+        ide_hwif_t *hwif = HWIF(drive);++        if (hwif->ide_dma_host_on)+                hwif->ide_dma_host_on(drive);++        printk("IDE: DMA enabled for %s%s\n",+                drive->media == ide_disk ? "ATA DISK " :+                (drive->media == ide_cdrom ? "ATAPI CDROM " : ""),+                drive->name);+        drive->using_dma = 1;+        return 0;+}++/*+ * Calculate the peripheral bus timing needed for the register used by IDE+ * devices.+ */++/* + * The tables bellows use indices as Multi-word DMA 2, Multi-word DMA 1,+ * Multi-word DMA 0, PIO 4, PIO 3, PIO 2, PIO 1, and PIO 0 (From 0 to 7, + * respectively).+ */++/* For storing value pair */+typedef struct {+	unsigned char x;+	unsigned char y;+} value_pair;++/* Table used for calculate Ta and Tb */+static const value_pair tab_values[] = {+	{3,0}, {5,0}, {7,2}, {3,0}, {5,0}, {5,0}, {7,2}, {10,4}+};++/* Table used for calculate Tc */+static const value_pair tc_values[] = {+	{13,8}, {19,11}, {60,41}, {10,5}, {12,6}, {14,8}, {17,11}, {23,15}+};++/* Table used for calculate Td */+static const value_pair td_values[] = {+	{1,100}, {1,100}, {3,200}, {1,100}, {1,100}, {1,100}, {3,200}, {5,250}+};++/* + * Calculate the required timing for setting up peripheral bus timing register.+ *+ * Input: sysclk = system clock rate (in MHz)+ *        mode = IDE mode (0-2: Multiword DMA mode 2-0, 3-7: PIO mode 4-0)+ * Return: 0 = Error+ *         else = value for setting up the timing register+ */+static unsigned long get_pb_ide_timing(unsigned int sysclk, int mode)+{+	unsigned char ta = 0;+	unsigned char tb = 0;+	unsigned char tc = 0;+	unsigned char td = 0;+	long temp = 0;+	const value_pair *val_ptr = (const value_pair *)0;++	/* The formula is only effective between 100-240MHz */+	if ((sysclk < 100) && (sysclk > 240))+		return(0);+	else if ((mode < 0) && (mode > 7)) /* Mode index is 0-7 only */+		return(0);++	/* (x, y) = tab_values[mode] */+	/* (Ta + Tb) = Temp = (ceiling((sysclk - 100) * x / 140) + y) */+	/* Ta = ceiling(Temp / 2) */+	/* Tb = (Temp / 2) */+	val_ptr = &tab_values[mode];+	temp = ((sysclk - 100) * val_ptr->x) / 140;+	if ((temp * 140) < ((sysclk - 100) * val_ptr->x))+		temp++;+	temp += val_ptr->y;+	tb = ta = (unsigned char)((temp >> 1) & 0xff);+	if (temp & 0x1)+		ta++;++	/* (x, y) = tc_values[mode] */+	/* Tc = (ceiling((sysclk - 100) * x / 140) + y) */+	val_ptr = &tc_values[mode];+	tc = (unsigned char)(((sysclk - 100) * val_ptr->x) / 140) & 0xff;+	if ((tc * 140) < ((sysclk - 100) * val_ptr->x))+		tc++;+	tc += val_ptr->y;++	/* (x, y) = td_values[mode] */+	/* Td = ceiling(sysclk + y - 400) * x / y) */+	val_ptr = &td_values[mode];+	if ((temp = (sysclk + val_ptr->y) - 400) < 0)+		td = 0; /* It's possible that Td < 0, so we set it to 0 */+	else {+		td = (unsigned char)(((temp * val_ptr->x) / val_ptr->y) & 0xff);+		if ((td * val_ptr->y) < (temp * val_ptr->x))+			td++;+	}+	return((td << 24) | (tc << 16) | (tb << 8) | ta);+}++ide_startstop_t tangox_pbide_dma_intr(ide_drive_t *drive)+{+	ide_hwif_t *hwif = HWIF(drive);+	struct request *rq = HWGROUP(drive)->rq;++	hwif->ide_dma_end(drive);++	ide_end_request(drive, 1,rq->nr_sectors);++	return ide_stopped;+}++static int tangox_pbide_rwdma(ide_drive_t *drive, int read, struct request *rq)+{+	unsigned long size = 0;+	unsigned long addr = 0;++        ide_hwif_t *hwif = HWIF(drive);+        struct scatterlist *sg = hwif->sg_table;++        dma_map_sg(&hwif->gendev, sg, hwif->sg_nents, hwif->sg_dma_direction);++	if (hwif->sg_nents > 2) { /* this shouldn't happen since we limited rqsize=16 for now*/+      		printk("cannot handle multiple transfer yet. sg_nents=0x%x\n", hwif->sg_nents);+                dma_unmap_sg(&hwif->gendev, sg, hwif->sg_nents, hwif->sg_dma_direction);+	        return 1;+	}++	// setup switchbox and wait for its readiness+        if (em86xx_mbus_alloc_dma(SBOX_IDEFLASH,  1, &g_regbase_read, NULL)) {+                printk("fail to alloc read dma, fallback to pio.\n");+		return 1;+        }++        /* try to setup dma write channel */+        if (em86xx_mbus_alloc_dma(SBOX_IDEFLASH,  0, &g_regbase_write, NULL)) {+                printk("fail to alloc write dma, fallback to pio.\n");+		em86xx_mbus_free_dma(g_regbase_read, SBOX_IDEFLASH);+		return 1;+        }++	// setup handler+	if (drive->media == ide_disk)+		ide_set_handler(drive, &tangox_pbide_dma_intr, 2 * WAIT_CMD, NULL);++        addr = sg_dma_address(sg);+       	size = sg_dma_len(sg);++	if (hwif->sg_nents == 1) {++		/* perform a single (linear/rectangle) transfer */++	        // setup PB automode registers+	        gbus_writel(REG_BASE_host_interface + PB_automode_start_address, 0);+	        gbus_writel(REG_BASE_host_interface + PB_automode_control,+				0x00140000 | ((read ? 1 : 0) << 16) | (size >> 1));++	        if (read)+        	        dma_cache_inv((unsigned int)phys_to_virt(addr), size);+	        else+	                dma_cache_wback_inv((unsigned int)phys_to_virt(addr), size);++        	em86xx_mbus_setup_dma(read ? g_regbase_read : g_regbase_write,+                		addr, size, NULL, NULL);+	}+	else { +		/* perform a double transfer */+		unsigned int addr1 = 0;+		unsigned int size1 = 0;++		sg = &hwif->sg_table[1];++	        addr1 = sg_dma_address(sg);+	       	size1 = sg_dma_len(sg);++	        // setup PB automode registers+	        gbus_writel(REG_BASE_host_interface + PB_automode_start_address, 0);+	        gbus_writel(REG_BASE_host_interface + PB_automode_control,+				0x00140000 | ((read ? 1 : 0) << 16) | ((size+size1) >> 1));++                if (read) {+                        dma_cache_inv((unsigned int)phys_to_virt(addr), size);+                        dma_cache_inv((unsigned int)phys_to_virt(addr1), size1);+		} else {+                        dma_cache_wback_inv((unsigned int)phys_to_virt(addr), size);+                        dma_cache_wback_inv((unsigned int)phys_to_virt(addr1), size1);+		}++                mbus_setup_dma_double(read ? g_regbase_read : g_regbase_write, +				addr, size, addr1, size1);+	}++	if (drive->media == ide_disk) {+		// send IDE command+		HWIF(drive)->OUTB(read ? (drive->addressing ? WIN_READDMA_EXT : WIN_READDMA) : +			(drive->addressing ? WIN_WRITEDMA_EXT : WIN_WRITEDMA), IDE_COMMAND_REG);+	}++	return 0;+}++static int tangox_pbide_dma_setup(ide_drive_t *drive)+{+        ide_hwif_t *hwif = HWIF(drive);+        struct request *rq;+        int iswrite;++        drive->waiting_for_dma = 1;+        rq = HWGROUP(drive)->rq;+        iswrite = (rq_data_dir(rq) == WRITE);+        hwif->sg_dma_direction = iswrite ? DMA_TO_DEVICE : DMA_FROM_DEVICE;+	+	// this will do the merge+	ide_map_sg(drive, rq);++        return tangox_pbide_rwdma(drive, !iswrite, rq);+}++static int tangox_ide_config_drive_for_dma(ide_drive_t *drive, int mode)+{+        ide_hwif_t *hwif = HWIF(drive);+        int config_allows_dma = 0;+        struct hd_driveid *id = drive->id;+        int speed;++        // enable DMA for CDROM by default+        if (drive->media == ide_disk || drive->media == ide_cdrom)+                config_allows_dma = 1;++        if (id && (id->capability & 1) && hwif->autodma && config_allows_dma) {+                speed = ide_dma_speed(drive, mode);++                /* For CDROM, we do the max. MDMA mode 2 */+		//if ((speed > XFER_MW_DMA_2) && (drive->media == ide_cdrom))+		//	speed = XFER_MW_DMA_2;++                if (speed >= XFER_MW_DMA_0) {+                        if (hwif->speedproc)+                                hwif->speedproc(drive, speed);+                        ide_config_drive_speed(drive, speed);+                        return hwif->ide_dma_on(drive);+                }+        }++        return hwif->ide_dma_off_quietly(drive);+}++static int tangox_pbide_dma_check(ide_drive_t *drive)+{+	return tangox_ide_config_drive_for_dma(drive, 0);+}++static void tangox_pbide_tune_chipset_drive(int drive, int speed, int verbose)+{+	extern unsigned long tangox_get_sysclock(void);+	int mode = speed & 0x0f;+	unsigned int timing;+	+	if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4)+		mode -= 8;+	else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)+		mode += 5;+	else+		return;	++	// get_pb_ide_timing() receives mode in reversed order+	//   PIO : 7-3+	//   Multi-word DMA : 2-0+	mode = 7 - mode;+	timing = get_pb_ide_timing(tangox_get_sysclock() * 11 / (10*1000000), mode);+	gbus_writel(REG_BASE_host_interface + PB_timing_slot(tangox_isaide_timing_slot()), timing);+}++static int tangox_pbide_tune_chipset(ide_drive_t *drive, u8 speed)+{+	tangox_pbide_tune_chipset_drive(drive->select.b.unit, speed, 1);++	return ide_config_drive_speed(drive, speed);+}++static int tangox_pbide_dma_end_io(ide_drive_t *drive)+{+	ide_hwif_t *hwif = HWIF(drive);+	struct scatterlist *sg = hwif->sg_table;+	struct request *rq = HWGROUP(drive)->rq;++	int stat = em86xx_mbus_wait(rq->cmd == READ ? g_regbase_read : +					g_regbase_write, SBOX_IDEFLASH);++	dma_unmap_sg(&hwif->gendev, sg, hwif->sg_nents, hwif->sg_dma_direction);++	/* Free up MBUS channel */+	em86xx_mbus_free_dma(g_regbase_read, SBOX_IDEFLASH);+	em86xx_mbus_free_dma(g_regbase_write, SBOX_IDEFLASH);+	return((stat != 0) ? 1 : 0);+}++static int tangox_pbide_dma_end(ide_drive_t *drive)+{+	int status;++	drive->waiting_for_dma = 0;+	status = tangox_pbide_dma_end_io(drive);+	return(status);+}+#endif++//+// initialize IDE driver+//+int __init tangox_pbide_init(void)+{+	int index, i;+	ide_hwif_t *hwif;+	hw_regs_t hw;+#ifdef MODULE+        ide_drive_t *drive = NULL;+#endif++	if (tangox_isaide_enabled() == 0)+		return 0;+	else+		tangox_pbide_init_hwif_ports(&hw, +			REG_BASE_host_interface_ISAIDE(tangox_isaide_cs_select()), 0, &hw.irq);++       	index = ide_register_hw(&hw, &hwif);+	printk("%s: SMP863x/SMP865x PB IDE controller.\n", hwif->name);++	// initialize ide_hwifs data structure+	// supports only one interface+	for (i = index; i < index + 1; ++i) {+		// register DMA handler+		hwif = &ide_hwifs[i];++	        /* set up local I/O function entry points */+	        hwif->INB = tangox_pbide_inb;+	        hwif->INW = tangox_pbide_inw;+	        hwif->INSW = tangox_pbide_insw;+	        hwif->OUTB = tangox_pbide_outb;+	        hwif->OUTW = tangox_pbide_outw;+	        hwif->OUTBSYNC = tangox_pbide_outbsync;+	        hwif->OUTSW = tangox_pbide_outsw;++		hwif->rqsize = 16; ++	    if (!noautodma) {+#ifdef CONFIG_BLK_DEV_PBIDE_TANGOX_DMA +		hwif->autodma = 1;+		hwif->atapi_dma = 1;+		hwif->ultra_mask = 0x00;	// dpbble all Ultra DMA+		hwif->mwdma_mask = 0x07;	// enable all Multi-word DMA+		hwif->swdma_mask = 0x80;	// dpbble all Single-word DMA++	        hwif->dma_setup = tangox_pbide_dma_setup;+	        hwif->dma_exec_cmd = tangox_pbide_dma_exec_cmd;+	        hwif->dma_start = tangox_pbide_dma_start;+		hwif->ide_dma_end = tangox_pbide_dma_end;++		hwif->ide_dma_check = tangox_pbide_dma_check;+		hwif->ide_dma_on = tangox_pbide_dma_on;+		hwif->ide_dma_off_quietly = tangox_pbide_dma_off_quietly;+		hwif->ide_dma_test_irq = tangox_pbide_dma_test_irq;+		hwif->ide_dma_host_on = tangox_pbide_dma_host_on;+		hwif->ide_dma_host_off = tangox_pbide_dma_host_off;+		hwif->ide_dma_lostirq = tangox_pbide_dma_lostirq;+		hwif->ide_dma_timeout = tangox_pbide_dma_time

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -