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

📄 cmd64x.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	config_cmd64x_chipset_for_pio(drive, set_speed);}static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	u8 unit			= (drive->select.b.unit & 0x01);	u8 regU = 0, pciU	= (hwif->channel) ? UDIDETCR1 : UDIDETCR0;	u8 regD = 0, pciD	= (hwif->channel) ? BMIDESR1 : BMIDESR0;	u8 speed	= ide_rate_filter(cmd64x_ratemask(drive), xferspeed);	if (speed > XFER_PIO_4) {		(void) pci_read_config_byte(dev, pciD, &regD);		(void) pci_read_config_byte(dev, pciU, &regU);		regD &= ~(unit ? 0x40 : 0x20);		regU &= ~(unit ? 0xCA : 0x35);		(void) pci_write_config_byte(dev, pciD, regD);		(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 != NULL) && ((id->capability & 1) != 0) && drive->autodma) {		if (ide_use_dma(drive)) {			if (config_chipset_for_dma(drive))				return hwif->ide_dma_on(drive);		}		goto fast_ata_pio;	} else if ((id->capability & 8) || (id->field_valid & 2)) {fast_ata_pio:		config_chipset_for_pio(drive, 1);		return hwif->ide_dma_off_quietly(drive);	}	/* IORDY not supported */	return 0;}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 __devinit 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_dword(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);	/* FIXME: pci_set_master() to ensure a good latency timer value */	/* 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_create_host_proc("cmd64x", cmd64x_get_info);	}#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */	return 0;}static unsigned int __devinit 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 __devinit 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 ide_pci_device_t cmd64x_chipsets[] __devinitdata = {	{	/* 0 */		.name		= "CMD643",		.init_chipset	= init_chipset_cmd64x,		.init_hwif	= init_hwif_cmd64x,		.channels	= 2,		.autodma	= AUTODMA,		.bootable	= ON_BOARD,	},{	/* 1 */		.name		= "CMD646",		.init_chipset	= init_chipset_cmd64x,		.init_hwif	= init_hwif_cmd64x,		.channels	= 2,		.autodma	= AUTODMA,		.enablebits	= {{0x00,0x00,0x00}, {0x51,0x80,0x80}},		.bootable	= ON_BOARD,	},{	/* 2 */		.name		= "CMD648",		.init_chipset	= init_chipset_cmd64x,		.init_hwif	= init_hwif_cmd64x,		.channels	= 2,		.autodma	= AUTODMA,		.bootable	= ON_BOARD,	},{	/* 3 */		.name		= "CMD649",		.init_chipset	= init_chipset_cmd64x,		.init_hwif	= init_hwif_cmd64x,		.channels	= 2,		.autodma	= AUTODMA,		.bootable	= ON_BOARD,	}};static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id){	return ide_setup_pci_device(dev, &cmd64x_chipsets[id->driver_data]);}static struct pci_device_id cmd64x_pci_tbl[] = {	{ 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, },};MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);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);}module_init(cmd64x_ide_init);MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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