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

📄 1006.ide.patch

📁 sm86xx内核源包括补丁( GPL )的
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+	// initialize ide_hwifs data structure+	// supports only one interface+	for (i = index; i < index + 1; ++i) {+		// register DMA handler+		hwif = &ide_hwifs[i];+		hwif->OUTB = em86xx_ide_OUTB;+		hwif->OUTW = em86xx_ide_OUTW;+		hwif->OUTBSYNC = em86xx_ide_OUTBSYNC;+		hwif->INB = em86xx_ide_INB;+		hwif->INW = em86xx_ide_INW;+		hwif->INSW = em86xx_ide_INSW;+		hwif->OUTSW = em86xx_ide_OUTSW;+                // MBUS can transfer two separate chunks of data blocks+                // but kernel usually allocate 4KB for each buffer cache,+                // which can hold 8 sectors, and usually they are not continous+                // So TANGO2X IDE interface can handle 16 sectors in best performance+                // If the request queue is bigger than this, driver need to use+                // bounce buffer+		hwif->rqsize = 16;+	    if (!noautodma) {+#ifdef CONFIG_BLK_DEV_TANGO2_BMIDEDMA+		hwif->autodma = 1;+		hwif->atapi_dma = 1;+#ifdef CONFIG_BLK_DEV_TANGO2_BMIDEUDMA+		hwif->ultra_mask = 0x7f;        // enable all Ultra DMA	+#else+		hwif->ultra_mask = 0x00;		// disable all Ultra DMA+#endif+		hwif->udma_four = 1;+		hwif->mwdma_mask = 0x07;		// enable all Multi-word DMA (0/1/2)+		hwif->swdma_mask = 0x80;		// disable all Single-word DMA++		// registers+		hwif->dma_command = REG_BASE_host_interface + IDECTRL_bmic;+		hwif->dma_status = REG_BASE_host_interface + IDECTRL_bmis;+		hwif->dma_prdtable = REG_BASE_host_interface + IDECTRL_bmidtp;++		// handlers+		hwif->ide_dma_read = em86xx_bmide_dma_read;+		hwif->ide_dma_write = em86xx_bmide_dma_write;+		hwif->ide_dma_begin = em86xx_bmide_dma_begin;+		hwif->ide_dma_end = em86xx_bmide_dma_end;+		hwif->ide_dma_check = em86xx_bmide_dma_check;+		hwif->ide_dma_on = em86xx_ide_dma_on;+		hwif->ide_dma_off = em86xx_ide_dma_off;+		hwif->ide_dma_off_quietly = em86xx_ide_dma_off_quietly;+		hwif->ide_dma_test_irq = em86xx_ide_dma_test_irq;+		hwif->ide_dma_host_on = em86xx_bmide_dma_host_on;+		hwif->ide_dma_host_off = em86xx_bmide_dma_host_off;+		hwif->ide_dma_bad_drive = em86xx_ide_dma_bad_drive;+		hwif->ide_dma_good_drive = em86xx_ide_dma_good_drive;+		hwif->ide_dma_count = em86xx_ide_dma_count;+		hwif->ide_dma_verbose = em86xx_ide_dma_verbose;+		hwif->ide_dma_retune = em86xx_ide_dma_retune;+		hwif->ide_dma_lostirq = em86xx_bmide_dma_lostirq;+		hwif->ide_dma_timeout = em86xx_bmide_dma_timeout;+		hwif->speedproc = em86xx_bmide_tune_chipset;+#endif+	    }+	}++	// set to maximum PIO mode+	for (i = 0; i < MAX_DRIVES; ++i)+		em86xx_bmide_tune_chipset_drive(i, XFER_PIO_4, 0);++	if (!noautodma) {+#ifdef CONFIG_BLK_DEV_TANGO2_BMIDEDMA+	if ((g_bounce_buf = (unsigned char *)__get_free_pages(GFP_KERNEL, DMA_BOUNCE_BUF_ORDER)) == NULL)+		printk("IDE: Can not allocate buffer for IDE transfer\n");++#ifdef EM86XX_BOUNCE_BUFFER_NOCACHE+	g_bounce_buf = (unsigned char *)KSEG1ADDR((unsigned long)g_bounce_buf);+	printk("Bounce buffer starts at 0x%08lx\n", (unsigned long)g_bounce_buf);+#endif++#endif	// EM86XX_BMIDEDMA+	}+	return 0;+}++#ifdef CONFIG_BLK_DEV_TANGO2_BMIDEDMA++//+// IDE DMA handlers+//++int em86xx_bmide_dma_read(ide_drive_t *drive)+{+	struct request *rq;++	drive->waiting_for_dma = 1;+	rq = HWGROUP(drive)->rq;+	// printk("em86xx_bmide_dma_read : nsect = %ld\n", rq->nr_sectors);+	return em86xx_bmide_rwdma(drive, 1, rq);+}++int em86xx_bmide_dma_write(ide_drive_t *drive)+{+	struct request *rq;++	drive->waiting_for_dma = 1;+	rq = HWGROUP(drive)->rq;+	// printk("em86xx_bmide_dma_write : sector = %ld, nsect = %ld\n", rq->sector, rq->nr_sectors);+	return em86xx_bmide_rwdma(drive, 0, rq);+}++int em86xx_bmide_dma_begin(ide_drive_t *drive)+{+	return(0);+}++int em86xx_bmide_dma_end(ide_drive_t *drive)+{+	int status;++	drive->waiting_for_dma = 0;+	status = em86xx_bmide_dma_end_io(drive);+	return(status);+}++int em86xx_bmide_dma_lostirq(ide_drive_t *drive)+{+	struct request *rq = HWGROUP(drive)->rq;+	unsigned int regbase = ((rq->cmd == READ) ? g_regbase_read : g_regbase_write);++	if (em86xx_mbus_inuse(regbase) != 0) +		em86xx_mbus_reset(regbase, SBOX_IDEDVD);+	return 0;+}++int em86xx_bmide_dma_timeout(ide_drive_t *drive)+{+	struct request *rq = HWGROUP(drive)->rq;+	unsigned int regbase = ((rq->cmd == READ) ? g_regbase_read : g_regbase_write);++	if (em86xx_mbus_inuse(regbase) != 0) +		em86xx_mbus_reset(regbase, SBOX_IDEDVD);+	return 0;+}++int em86xx_bmide_dma_check(ide_drive_t *drive)+{+	int mode;++#ifdef CONFIG_BLK_DEV_TANGO2_BMIDEUDMA+	if ((gbus_read_uint32(pGBus, REG_BASE_host_interface + IDECTRL_idestatus) & 0x02) == 0x02)+        	mode = 1;   // 40 donductor cable (UDMA33) : Mode 0/1/2+	else +		mode = 4;   // 80 conductor cable : Mode 0/1/2/3/4/5/6+#else+	mode = 0;       // MW DMA mode 2+#endif++	return em86xx_ide_config_drive_for_dma(drive, mode);+}++int em86xx_bmide_dma_host_on(ide_drive_t *drive)+{+	if (drive->using_dma) {+		ide_hwif_t *hwif = HWIF(drive);+		u8 unit = (drive->select.b.unit & 0x01);+		u8 dma_stat = hwif->INB(hwif->dma_status);++		hwif->OUTB((dma_stat | (1 << (5 + unit))), hwif->dma_status);+		return 0;+	}+	return 1;+}++int em86xx_bmide_dma_host_off(ide_drive_t *drive)+{+	ide_hwif_t *hwif = HWIF(drive);+	u8 unit = (drive->select.b.unit & 0x01);+	u8 dma_stat = hwif->INB(hwif->dma_status);++	hwif->OUTB((dma_stat & ~(1 << (5 + unit))), hwif->dma_status);++	return 0;+}++int em86xx_bmide_tune_chipset(ide_drive_t *drive, u8 speed)+{+	em86xx_bmide_tune_chipset_drive(drive->select.b.unit, speed, 1);++	return ide_config_drive_speed(drive, speed);+}++//+// helper functions+//++#ifdef EM86XX_BMIDE_DMA_MERGE_BH+#define MBUS_LINEAR_MAX 	(0x2000 - 1)+#endif++/* Get the I/O size of given request */+static inline int get_request_size(struct request *rq)+{+	unsigned int rq_size;+	struct buffer_head *bh;++	for (rq_size = 0, bh = rq->bh; bh != NULL; bh = bh->b_reqnext) +		rq_size += bh->b_size;++	return(rq_size);+}++#ifdef CONFIG_BLK_DEV_TANGO2_BMIDEDMA+// return the number of fragmented blocks+static __inline__ int em86xx_bmide_request_fragment(struct request *rq)+{+	int ntransfer = 0;+	struct buffer_head *bh = rq->bh;++#ifdef EM86XX_BMIDE_DMA_MERGE_BH+	unsigned long addr;+	unsigned int size;+	unsigned int sector;++	if (rq == crq)+		return(crq_ntransfer);++	/* Try to merge multiple BH if possible -- deal with one fragment only */+	for (ntransfer = 0, bh = rq->bh;;) {+		if (bh == NULL)+			break;+		else {+			if (++ntransfer > 1) /* More than one fragment found */+				break; +		}+		addr = (unsigned long)bh->b_data;+		size = bh->b_size;+		sector = bh->b_rsector;+		for (bh = bh->b_reqnext; bh != NULL; bh = bh->b_reqnext) {+			if ((addr + size) != (unsigned long)bh->b_data)+				break;	/* data is not contiguous */+			else {	/* Merge the next BH */+				size += bh->b_size;+			}+		}	+	}+	if (ntransfer < 2) /* This can be done with one fragment (linear or rectangular) */+		goto done;++	/* Try to merge multiple BH if possible -- deal with two fragments or more */+	for (ntransfer = 0, bh = rq->bh;;) {+		if (bh == NULL)+			break;+		else+			++ntransfer;+		addr = (unsigned long)bh->b_data;+		size = bh->b_size;+		sector = bh->b_rsector;+		for (bh = bh->b_reqnext; bh != NULL; bh = bh->b_reqnext) {+			if ((addr + size) != (unsigned long)bh->b_data)+				break;	/* data is not contiguous */+			else if ((size + bh->b_size) > MBUS_LINEAR_MAX)+				break;	/* Size too large */+			else {	/* Merge the next BH */+				size += bh->b_size;+			}+		}	+	}+#else+	if (rq == crq)+		return(crq_ntransfer);++	do {+		++ntransfer;+	} while ((bh = bh->b_reqnext) != NULL);+#endif++done:+	return ntransfer;+}++// prepare MBUS for DMA transfer+// stop_if_fragment must be non-zero+static struct buffer_head *em86xx_bmide_dma_setup(int read, struct request *rq, int stop_if_fragment)+{+	struct buffer_head *bh = rq->bh;++	// scans buffer head and calculate the requested transfer size+	// MBUS can't transfer to more than two separate regions. +	// So if the buffer head is too fragmented, return non-NULL value+#ifdef EM86XX_BMIDE_DMA_MERGE_BH+	struct {+		unsigned long addr;+		unsigned int size;+		unsigned int sector;+	} transfer[2], *ptransfer;+	unsigned int ntransfer;++	crq = rq;++	/* Try to merge multiple BH if possible -- one fragment only */+	for (ntransfer = 0, ptransfer = &transfer[0], bh = rq->bh;; ptransfer++) {+		if (bh == NULL)+			break;+		else if (++ntransfer > 1)+			break;++		ptransfer->addr = (unsigned long)bh->b_data;+		ptransfer->size = bh->b_size;+		ptransfer->sector = bh->b_rsector;+		for (bh = bh->b_reqnext; bh != NULL; bh = bh->b_reqnext) {+			if ((ptransfer->addr + ptransfer->size) != (unsigned long)bh->b_data)+				break;	/* data is not contiguous */+			else {	/* Merge the next BH */+				ptransfer->size += bh->b_size;+			}+		}	+	}+	if (ntransfer < 2) /* This can be done with one fragment (linear or rectangular) */+		goto start_transfer;++	/* Try to merge multiple BH if possible */+	for (ntransfer = 0, ptransfer = &transfer[0], bh = rq->bh;; ptransfer++) {+		if (bh == NULL)+			break;+		else if (++ntransfer > 2)+			break;++		ptransfer->addr = (unsigned long)bh->b_data;+		ptransfer->size = bh->b_size;+		ptransfer->sector = bh->b_rsector;+		for (bh = bh->b_reqnext; bh != NULL; bh = bh->b_reqnext) {+			if ((ptransfer->addr + ptransfer->size) != (unsigned long)bh->b_data)+				break;	/* data is not contiguous */+			else if ((ptransfer->size + bh->b_size) > MBUS_LINEAR_MAX)+				break;	/* Size too large */+			else {	/* Merge the next BH */+				ptransfer->size += bh->b_size;+			}+		}	+	}++	if ((ntransfer > 2) && (stop_if_fragment != 0)) {+		crq_ntransfer = ntransfer;+		return bh;+	}+#else+	struct buffer_head *prevbh;++	struct {+		unsigned long addr;+		unsigned int size;+	} transfer[2], *ptransfer;+	unsigned int ntransfer, size;++	crq = rq;++	for (prevbh = NULL, ntransfer = 0, ptransfer = transfer, size = 0; bh != NULL; prevbh = bh, bh = bh->b_reqnext) {+		if (++ntransfer > 2) {+			if (stop_if_fragment) {+				crq_ntransfer = ntransfer;+				return bh;+			}+			break;+		}+		ptransfer->addr = (unsigned long) bh->b_data;+		ptransfer->size = bh->b_size;+		// printk("MBUS : bh = %p, bh->next = %p, %08x, %08x\n", bh, bh->b_reqnext, ptransfer->addr, ptransfer->size);+		++ptransfer;+		size += bh->b_size;+	}+#endif++start_transfer:++	crq_ntransfer = ntransfer;++	// setup MBUS+	if (ntransfer == 1) {+#ifdef CONFIG_NONCOHERENT_IO+		if (!is_physical(transfer[0].addr)) {+			if (read) +				dma_cache_inv(transfer[0].addr, transfer[0].size);+			else+				dma_cache_wback_inv(transfer[0].addr, transfer[0].size);+		}+#endif+		if (transfer[0].size <= MBUS_LINEAR_MAX) {+			/* Do linear transfer */+

⌨️ 快捷键说明

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