it821x.c

来自「linux 内核源代码」· C语言 代码 · 共 686 行 · 第 1/2 页

C
686
字号
		conf &= ~ (1 << (3 + 2 * channel + unit));	pci_write_config_byte(hwif->pci_dev, 0x50, conf);	it821x_clock_strategy(drive);	it821x_program_udma(drive, itdev->udma[unit]);}/** *	it821x_dma_read	-	DMA hook *	@drive: drive for DMA * *	The IT821x has a single timing register for MWDMA and for PIO *	operations. As we flip back and forth we have to reload the *	clock. In addition the rev 0x10 device only works if the same *	timing value is loaded into the master and slave UDMA clock * 	so we must also reload that. * *	FIXME: we could figure out in advance if we need to do reloads */static void it821x_dma_start(ide_drive_t *drive){	ide_hwif_t *hwif = drive->hwif;	struct it821x_dev *itdev = ide_get_hwifdata(hwif);	int unit = drive->select.b.unit;	if(itdev->mwdma[unit] != MWDMA_OFF)		it821x_program(drive, itdev->mwdma[unit]);	else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10)		it821x_program_udma(drive, itdev->udma[unit]);	ide_dma_start(drive);}/** *	it821x_dma_write	-	DMA hook *	@drive: drive for DMA stop * *	The IT821x has a single timing register for MWDMA and for PIO *	operations. As we flip back and forth we have to reload the *	clock. */static int it821x_dma_end(ide_drive_t *drive){	ide_hwif_t *hwif = drive->hwif;	int unit = drive->select.b.unit;	struct it821x_dev *itdev = ide_get_hwifdata(hwif);	int ret = __ide_dma_end(drive);	if(itdev->mwdma[unit] != MWDMA_OFF)		it821x_program(drive, itdev->pio[unit]);	return ret;}/** *	it821x_set_dma_mode	-	set host controller for DMA mode *	@drive: drive *	@speed: DMA mode * *	Tune the ITE chipset for the desired DMA mode. */static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed){	/*	 * MWDMA tuning is really hard because our MWDMA and PIO	 * timings are kept in the same place.  We can switch in the	 * host dma on/off callbacks.	 */	if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_6)		it821x_tune_udma(drive, speed - XFER_UDMA_0);	else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)		it821x_tune_mwdma(drive, speed - XFER_MW_DMA_0);}/** *	ata66_it821x	-	check for 80 pin cable *	@hwif: interface to check * *	Check for the presence of an ATA66 capable cable on the *	interface. Problematic as it seems some cards don't have *	the needed logic onboard. */static u8 __devinit ata66_it821x(ide_hwif_t *hwif){	/* The reference driver also only does disk side */	return ATA_CBL_PATA80;}/** *	it821x_fixup	-	post init callback *	@hwif: interface * *	This callback is run after the drives have been probed but *	before anything gets attached. It allows drivers to do any *	final tuning that is needed, or fixups to work around bugs. */static void __devinit it821x_fixups(ide_hwif_t *hwif){	struct it821x_dev *itdev = ide_get_hwifdata(hwif);	int i;	if(!itdev->smart) {		/*		 *	If we are in pass through mode then not much		 *	needs to be done, but we do bother to clear the		 *	IRQ mask as we may well be in PIO (eg rev 0x10)		 *	for now and we know unmasking is safe on this chipset.		 */		for (i = 0; i < 2; i++) {			ide_drive_t *drive = &hwif->drives[i];			if(drive->present)				drive->unmask = 1;		}		return;	}	/*	 *	Perform fixups on smart mode. We need to "lose" some	 *	capabilities the firmware lacks but does not filter, and	 *	also patch up some capability bits that it forgets to set	 *	in RAID mode.	 */	for(i = 0; i < 2; i++) {		ide_drive_t *drive = &hwif->drives[i];		struct hd_driveid *id;		u16 *idbits;		if(!drive->present)			continue;		id = drive->id;		idbits = (u16 *)drive->id;		/* Check for RAID v native */		if(strstr(id->model, "Integrated Technology Express")) {			/* In raid mode the ident block is slightly buggy			   We need to set the bits so that the IDE layer knows			   LBA28. LBA48 and DMA ar valid */			id->capability |= 3;		/* LBA28, DMA */			id->command_set_2 |= 0x0400;	/* LBA48 valid */			id->cfs_enable_2 |= 0x0400;	/* LBA48 on */			/* Reporting logic */			printk(KERN_INFO "%s: IT8212 %sRAID %d volume",				drive->name,				idbits[147] ? "Bootable ":"",				idbits[129]);				if(idbits[129] != 1)					printk("(%dK stripe)", idbits[146]);				printk(".\n");		} else {			/* Non RAID volume. Fixups to stop the core code			   doing unsupported things */			id->field_valid &= 3;			id->queue_depth = 0;			id->command_set_1 = 0;			id->command_set_2 &= 0xC400;			id->cfsse &= 0xC000;			id->cfs_enable_1 = 0;			id->cfs_enable_2 &= 0xC400;			id->csf_default &= 0xC000;			id->word127 = 0;			id->dlf = 0;			id->csfo = 0;			id->cfa_power = 0;			printk(KERN_INFO "%s: Performing identify fixups.\n",				drive->name);		}		/*		 * Set MWDMA0 mode as enabled/support - just to tell		 * IDE core that DMA is supported (it821x hardware		 * takes care of DMA mode programming).		 */		if (id->capability & 1) {			id->dma_mword |= 0x0101;			drive->current_speed = XFER_MW_DMA_0;		}	}}/** *	init_hwif_it821x	-	set up hwif structs *	@hwif: interface to set up * *	We do the basic set up of the interface structure. The IT8212 *	requires several custom handlers so we override the default *	ide DMA handlers appropriately */static void __devinit init_hwif_it821x(ide_hwif_t *hwif){	struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);	u8 conf;	if (idev == NULL) {		printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");		return;	}	ide_set_hwifdata(hwif, idev);	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);	if (conf & 1) {		idev->smart = 1;		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;		/* Long I/O's although allowed in LBA48 space cause the		   onboard firmware to enter the twighlight zone */		hwif->rqsize = 256;	}	/* Pull the current clocks from 0x50 also */	if (conf & (1 << (1 + hwif->channel)))		idev->clock_mode = ATA_50;	else		idev->clock_mode = ATA_66;	idev->want[0][1] = ATA_ANY;	idev->want[1][1] = ATA_ANY;	/*	 *	Not in the docs but according to the reference driver	 *	this is necessary.	 */	pci_read_config_byte(hwif->pci_dev, 0x08, &conf);	if (conf == 0x10) {		idev->timing10 = 1;		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;		if (idev->smart == 0)			printk(KERN_WARNING "it821x: Revision 0x10, workarounds activated.\n");	}	if (idev->smart == 0) {		hwif->set_pio_mode = &it821x_set_pio_mode;		hwif->set_dma_mode = &it821x_set_dma_mode;		/* MWDMA/PIO clock switching for pass through mode */		hwif->dma_start = &it821x_dma_start;		hwif->ide_dma_end = &it821x_dma_end;	} else		hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;	if (hwif->dma_base == 0)		return;	hwif->ultra_mask = ATA_UDMA6;	hwif->mwdma_mask = ATA_MWDMA2;	if (hwif->cbl != ATA_CBL_PATA40_SHORT)		hwif->cbl = ata66_it821x(hwif);}static void __devinit it8212_disable_raid(struct pci_dev *dev){	/* Reset local CPU, and set BIOS not ready */	pci_write_config_byte(dev, 0x5E, 0x01);	/* Set to bypass mode, and reset PCI bus */	pci_write_config_byte(dev, 0x50, 0x00);	pci_write_config_word(dev, PCI_COMMAND,			      PCI_COMMAND_PARITY | PCI_COMMAND_IO |			      PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);	pci_write_config_word(dev, 0x40, 0xA0F3);	pci_write_config_dword(dev,0x4C, 0x02040204);	pci_write_config_byte(dev, 0x42, 0x36);	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);}static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name){	u8 conf;	static char *mode[2] = { "pass through", "smart" };	/* Force the card into bypass mode if so requested */	if (it8212_noraid) {		printk(KERN_INFO "it8212: forcing bypass mode.\n");		it8212_disable_raid(dev);	}	pci_read_config_byte(dev, 0x50, &conf);	printk(KERN_INFO "it821x: controller in %s mode.\n", mode[conf & 1]);	return 0;}#define DECLARE_ITE_DEV(name_str)			\	{						\		.name		= name_str,		\		.init_chipset	= init_chipset_it821x,	\		.init_hwif	= init_hwif_it821x,	\		.fixup	 	= it821x_fixups,	\		.host_flags	= IDE_HFLAG_BOOTABLE,	\		.pio_mask	= ATA_PIO4,		\	}static const struct ide_port_info it821x_chipsets[] __devinitdata = {	/* 0 */ DECLARE_ITE_DEV("IT8212"),};/** *	it821x_init_one	-	pci layer discovery entry *	@dev: PCI device *	@id: ident table entry * *	Called by the PCI code when it finds an ITE821x controller. *	We then use the IDE PCI generic helper to do most of the work. */static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id){	return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);}static const struct pci_device_id it821x_pci_tbl[] = {	{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 },	{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 },	{ 0, },};MODULE_DEVICE_TABLE(pci, it821x_pci_tbl);static struct pci_driver driver = {	.name		= "ITE821x IDE",	.id_table	= it821x_pci_tbl,	.probe		= it821x_init_one,};static int __init it821x_ide_init(void){	return ide_pci_register_driver(&driver);}module_init(it821x_ide_init);module_param_named(noraid, it8212_noraid, int, S_IRUGO);MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode");MODULE_AUTHOR("Alan Cox");MODULE_DESCRIPTION("PCI driver module for the ITE 821x");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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