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

📄 cmd64x.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		(void) pci_write_config_byte(dev, pciU, regU);		(void) pci_read_config_byte(dev, pciD, &regD);		(void) pci_read_config_byte(dev, pciU, &regU);	}	switch(speed) {		case XFER_UDMA_5:	regU |= (unit ? 0x0A : 0x05); break;		case XFER_UDMA_4:	regU |= (unit ? 0x4A : 0x15); break;		case XFER_UDMA_3:	regU |= (unit ? 0x8A : 0x25); break;		case XFER_UDMA_2:	regU |= (unit ? 0x42 : 0x11); break;		case XFER_UDMA_1:	regU |= (unit ? 0x82 : 0x21); break;		case XFER_UDMA_0:	regU |= (unit ? 0xC2 : 0x31); break;		case XFER_MW_DMA_2:	regD |= (unit ? 0x40 : 0x10); break;		case XFER_MW_DMA_1:	regD |= (unit ? 0x80 : 0x20); break;		case XFER_MW_DMA_0:	regD |= (unit ? 0xC0 : 0x30); break;		case XFER_SW_DMA_2:	regD |= (unit ? 0x40 : 0x10); break;		case XFER_SW_DMA_1:	regD |= (unit ? 0x80 : 0x20); break;		case XFER_SW_DMA_0:	regD |= (unit ? 0xC0 : 0x30); break;		case XFER_PIO_4:	cmd64x_tuneproc(drive, 4); break;		case XFER_PIO_3:	cmd64x_tuneproc(drive, 3); break;		case XFER_PIO_2:	cmd64x_tuneproc(drive, 2); break;		case XFER_PIO_1:	cmd64x_tuneproc(drive, 1); break;		case XFER_PIO_0:	cmd64x_tuneproc(drive, 0); break;		default:			return 1;	}	if (speed > XFER_PIO_4) {		(void) pci_write_config_byte(dev, pciU, regU);		regD |= (unit ? 0x40 : 0x20);		(void) pci_write_config_byte(dev, pciD, regD);	}	return (ide_config_drive_speed(drive, speed));}static int config_chipset_for_dma (ide_drive_t *drive){	u8 speed	= ide_dma_speed(drive, cmd64x_ratemask(drive));	config_chipset_for_pio(drive, !speed);	if (!speed)		return 0;	if(ide_set_xfer_rate(drive, speed))		return 0; 	if (!drive->init_speed)		drive->init_speed = speed;	return ide_dma_enable(drive);}static int cmd64x_config_drive_for_dma (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	struct hd_driveid *id	= drive->id;	if ((id->capability & 1) != 0 && drive->autodma) {		/* Consult the list of known "bad" drives */		if (hwif->ide_dma_bad_drive(drive))			goto fast_ata_pio;		if ((id->field_valid & 4) && cmd64x_ratemask(drive)) {			if (id->dma_ultra & hwif->ultra_mask) {				/* Force if Capable UltraDMA */				int dma = config_chipset_for_dma(drive);				if ((id->field_valid & 2) && !dma)					goto try_dma_modes;			}		} else if (id->field_valid & 2) {try_dma_modes:			if ((id->dma_mword & hwif->mwdma_mask) ||			    (id->dma_1word & hwif->swdma_mask)) {				/* Force if Capable regular DMA modes */				if (!config_chipset_for_dma(drive))					goto no_dma_set;			}		} else if (hwif->ide_dma_good_drive(drive) &&			   (id->eide_dma_time < 150)) {			/* Consult the list of known "good" drives */			if (!config_chipset_for_dma(drive))				goto no_dma_set;		} else {			goto fast_ata_pio;		}	} else if ((id->capability & 8) || (id->field_valid & 2)) {fast_ata_pio:no_dma_set:		config_chipset_for_pio(drive, 1);		return hwif->ide_dma_off_quietly(drive);	}	return hwif->ide_dma_on(drive);}static int cmd64x_alt_dma_status (struct pci_dev *dev){	switch(dev->device) {		case PCI_DEVICE_ID_CMD_648:		case PCI_DEVICE_ID_CMD_649:			return 1;		default:			break;	}	return 0;}static int cmd64x_ide_dma_end (ide_drive_t *drive){	u8 dma_stat = 0, dma_cmd = 0;	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	drive->waiting_for_dma = 0;	/* read DMA command state */	dma_cmd = hwif->INB(hwif->dma_command);	/* stop DMA */	hwif->OUTB((dma_cmd & ~1), hwif->dma_command);	/* get DMA status */	dma_stat = hwif->INB(hwif->dma_status);	/* clear the INTR & ERROR bits */	hwif->OUTB(dma_stat|6, hwif->dma_status);	if (cmd64x_alt_dma_status(dev)) {		u8 dma_intr	= 0;		u8 dma_mask	= (hwif->channel) ? ARTTIM23_INTR_CH1 :						    CFR_INTR_CH0;		u8 dma_reg	= (hwif->channel) ? ARTTIM2 : CFR;		(void) pci_read_config_byte(dev, dma_reg, &dma_intr);		/* clear the INTR bit */		(void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask);	}	/* purge DMA mappings */	ide_destroy_dmatable(drive);	/* verify good DMA status */	return (dma_stat & 7) != 4;}static int cmd64x_ide_dma_test_irq (ide_drive_t *drive){	ide_hwif_t *hwif		= HWIF(drive);	struct pci_dev *dev		= hwif->pci_dev;        u8 dma_alt_stat = 0, mask	= (hwif->channel) ? MRDMODE_INTR_CH1 :							    MRDMODE_INTR_CH0;	u8 dma_stat = hwif->INB(hwif->dma_status);	(void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat);#ifdef DEBUG	printk("%s: dma_stat: 0x%02x dma_alt_stat: "		"0x%02x mask: 0x%02x\n", drive->name,		dma_stat, dma_alt_stat, mask);#endif	if (!(dma_alt_stat & mask))		return 0;	/* return 1 if INTR asserted */	if ((dma_stat & 4) == 4)		return 1;	return 0;}/* * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old * event order for DMA transfers. */static int cmd646_1_ide_dma_end (ide_drive_t *drive){	ide_hwif_t *hwif = HWIF(drive);	u8 dma_stat = 0, dma_cmd = 0;	drive->waiting_for_dma = 0;	/* get DMA status */	dma_stat = hwif->INB(hwif->dma_status);	/* read DMA command state */	dma_cmd = hwif->INB(hwif->dma_command);	/* stop DMA */	hwif->OUTB((dma_cmd & ~1), hwif->dma_command);	/* clear the INTR & ERROR bits */	hwif->OUTB(dma_stat|6, hwif->dma_status);	/* and free any DMA resources */	ide_destroy_dmatable(drive);	/* verify good DMA status */	return (dma_stat & 7) != 4;}static unsigned int __init init_chipset_cmd64x (struct pci_dev *dev, const char *name){	u32 class_rev = 0;	u8 mrdmode = 0;	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);	class_rev &= 0xff;#ifdef __i386__	if (dev->resource[PCI_ROM_RESOURCE].start) {		pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);		printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);	}#endif	switch(dev->device) {		case PCI_DEVICE_ID_CMD_643:			break;		case PCI_DEVICE_ID_CMD_646:			printk(KERN_INFO "%s: chipset revision 0x%02X, ", name, class_rev);			switch(class_rev) {				case 0x07:				case 0x05:					printk("UltraDMA Capable");					break;				case 0x03:					printk("MultiWord DMA Force Limited");					break;				case 0x01:				default:					printk("MultiWord DMA Limited, IRQ workaround enabled");					break;				}			printk("\n");                        break;		case PCI_DEVICE_ID_CMD_648:		case PCI_DEVICE_ID_CMD_649:			break;		default:			break;	}	/* Set a good latency timer and cache line size value. */	(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);#ifdef __sparc_v9__	(void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10);#endif	/* Setup interrupts. */	(void) pci_read_config_byte(dev, MRDMODE, &mrdmode);	mrdmode &= ~(0x30);	(void) pci_write_config_byte(dev, MRDMODE, mrdmode);	/* Use MEMORY READ LINE for reads.	 * NOTE: Although not mentioned in the PCI0646U specs,	 *       these bits are write only and won't be read	 *       back as set or not.  The PCI0646U2 specs clarify	 *       this point.	 */	(void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02);	/* Set reasonable active/recovery/address-setup values. */	(void) pci_write_config_byte(dev, ARTTIM0,  0x40);	(void) pci_write_config_byte(dev, DRWTIM0,  0x3f);	(void) pci_write_config_byte(dev, ARTTIM1,  0x40);	(void) pci_write_config_byte(dev, DRWTIM1,  0x3f);#ifdef __i386__	(void) pci_write_config_byte(dev, ARTTIM23, 0x1c);#else	(void) pci_write_config_byte(dev, ARTTIM23, 0x5c);#endif	(void) pci_write_config_byte(dev, DRWTIM23, 0x3f);	(void) pci_write_config_byte(dev, DRWTIM3,  0x3f);#ifdef CONFIG_PPC	(void) pci_write_config_byte(dev, UDIDETCR0, 0xf0);#endif /* CONFIG_PPC */#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS)	cmd_devs[n_cmd_devs++] = dev;	if (!cmd64x_proc) {		cmd64x_proc = 1;		ide_pci_register_host_proc(&cmd64x_procs[0]);	}#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */	return 0;}static unsigned int __init ata66_cmd64x (ide_hwif_t *hwif){	u8 ata66 = 0, mask = (hwif->channel) ? 0x02 : 0x01;	switch(hwif->pci_dev->device) {		case PCI_DEVICE_ID_CMD_643:		case PCI_DEVICE_ID_CMD_646:			return ata66;		default:			break;	}	pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66);	return (ata66 & mask) ? 1 : 0;}static void __init init_hwif_cmd64x (ide_hwif_t *hwif){	struct pci_dev *dev	= hwif->pci_dev;	unsigned int class_rev;	hwif->autodma = 0;	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);	class_rev &= 0xff;	hwif->tuneproc  = &cmd64x_tuneproc;	hwif->speedproc = &cmd64x_tune_chipset;	if (!hwif->dma_base) {		hwif->drives[0].autotune = 1;		hwif->drives[1].autotune = 1;		return;	}	hwif->atapi_dma = 1;	hwif->ultra_mask = 0x3f;	hwif->mwdma_mask = 0x07;	hwif->swdma_mask = 0x07;	if (dev->device == PCI_DEVICE_ID_CMD_643)		hwif->ultra_mask = 0x80;	if (dev->device == PCI_DEVICE_ID_CMD_646)		hwif->ultra_mask = (class_rev > 0x04) ? 0x07 : 0x80;	if (dev->device == PCI_DEVICE_ID_CMD_648)		hwif->ultra_mask = 0x1f;	hwif->ide_dma_check = &cmd64x_config_drive_for_dma;	if (!(hwif->udma_four))		hwif->udma_four = ata66_cmd64x(hwif);	if (dev->device == PCI_DEVICE_ID_CMD_646) {		hwif->chipset = ide_cmd646;		if (class_rev == 0x01) {			hwif->ide_dma_end = &cmd646_1_ide_dma_end;		} else {			hwif->ide_dma_end = &cmd64x_ide_dma_end;			hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq;		}	} else {		hwif->ide_dma_end = &cmd64x_ide_dma_end;		hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq;	}	if (!noautodma)		hwif->autodma = 1;	hwif->drives[0].autodma = hwif->autodma;	hwif->drives[1].autodma = hwif->autodma;}static void __init init_dma_cmd64x (ide_hwif_t *hwif, unsigned long dmabase){	ide_setup_dma(hwif, dmabase, 8);}extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id){	ide_pci_device_t *d = &cmd64x_chipsets[id->driver_data];	if (dev->device != d->device)		BUG();	ide_setup_pci_device(dev, d);	MOD_INC_USE_COUNT;	return 0;}static struct pci_device_id cmd64x_pci_tbl[] __devinitdata = {	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},	{ 0, },};static struct pci_driver driver = {	.name		= "CMD64x IDE",	.id_table	= cmd64x_pci_tbl,	.probe		= cmd64x_init_one,};static int cmd64x_ide_init(void){	return ide_pci_register_driver(&driver);}static void cmd64x_ide_exit(void){	ide_pci_unregister_driver(&driver);}module_init(cmd64x_ide_init);module_exit(cmd64x_ide_exit);MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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