sis5513.c

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

C
632
字号
		case XFER_UDMA_4:		case XFER_UDMA_3:		case XFER_UDMA_2:		case XFER_UDMA_1:		case XFER_UDMA_0:			if (chipset_family >= ATA_133) {				u32 regdw = 0;				u8 drive_pci = sis_ata133_get_base(drive);				pci_read_config_dword(dev, drive_pci, &regdw);				regdw |= 0x04;				regdw &= 0xfffff00f;				/* check if ATA133 enable */				if (regdw & 0x08) {					regdw |= (unsigned long)cycle_time_value[ATA_133][speed-XFER_UDMA_0] << 4;					regdw |= (unsigned long)cvs_time_value[ATA_133][speed-XFER_UDMA_0] << 8;				} else {					regdw |= (unsigned long)cycle_time_value[ATA_100][speed-XFER_UDMA_0] << 4;					regdw |= (unsigned long)cvs_time_value[ATA_100][speed-XFER_UDMA_0] << 8;				}				pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);			} else {				u8 drive_pci = 0x40 + drive->dn * 2, reg = 0;				pci_read_config_byte(dev, drive_pci+1, &reg);				/* Force the UDMA bit on if we want to use UDMA */				reg |= 0x80;				/* clean reg cycle time bits */				reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))					 << cycle_time_offset[chipset_family]);				/* set reg cycle time bits */				reg |= cycle_time_value[chipset_family][speed-XFER_UDMA_0]					<< cycle_time_offset[chipset_family];				pci_write_config_byte(dev, drive_pci+1, reg);			}			break;		case XFER_MW_DMA_2:		case XFER_MW_DMA_1:		case XFER_MW_DMA_0:			sis_program_timings(drive, speed);			break;		default:			break;	}}static u8 sis5513_ata133_udma_filter(ide_drive_t *drive){	struct pci_dev *dev = drive->hwif->pci_dev;	u32 regdw = 0;	u8 drive_pci = sis_ata133_get_base(drive);	pci_read_config_dword(dev, drive_pci, &regdw);	/* if ATA133 disable, we should not set speed above UDMA5 */	return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;}/* Chip detection and general config */static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name){	struct pci_dev *host;	int i = 0;	chipset_family = 0;	for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) {		host = pci_get_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL);		if (!host)			continue;		chipset_family = SiSHostChipInfo[i].chipset_family;		/* Special case for SiS630 : 630S/ET is ATA_100a */		if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) {			if (host->revision >= 0x30)				chipset_family = ATA_100a;		}		pci_dev_put(host);			printk(KERN_INFO "SIS5513: %s %s controller\n",			 SiSHostChipInfo[i].name, chipset_capability[chipset_family]);	}	if (!chipset_family) { /* Belongs to pci-quirks */			u32 idemisc;			u16 trueid;			/* Disable ID masking and register remapping */			pci_read_config_dword(dev, 0x54, &idemisc);			pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff));			pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);			pci_write_config_dword(dev, 0x54, idemisc);			if (trueid == 0x5518) {				printk(KERN_INFO "SIS5513: SiS 962/963 MuTIOL IDE UDMA133 controller\n");				chipset_family = ATA_133;				/* Check for 5513 compability mapping				 * We must use this, else the port enabled code will fail,				 * as it expects the enablebits at 0x4a.				 */				if ((idemisc & 0x40000000) == 0) {					pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);					printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");				}			}	}	if (!chipset_family) { /* Belongs to pci-quirks */			struct pci_dev *lpc_bridge;			u16 trueid;			u8 prefctl;			u8 idecfg;			pci_read_config_byte(dev, 0x4a, &idecfg);			pci_write_config_byte(dev, 0x4a, idecfg | 0x10);			pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);			pci_write_config_byte(dev, 0x4a, idecfg);			if (trueid == 0x5517) { /* SiS 961/961B */				lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */				pci_read_config_byte(dev, 0x49, &prefctl);				pci_dev_put(lpc_bridge);				if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {					printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");					chipset_family = ATA_133a;				} else {					printk(KERN_INFO "SIS5513: SiS 961 MuTIOL IDE UDMA100 controller\n");					chipset_family = ATA_100;				}			}	}	if (!chipset_family)		return -1;	/* Make general config ops here	   1/ tell IDE channels to operate in Compatibility mode only	   2/ tell old chips to allow per drive IDE timings */	{		u8 reg;		u16 regw;		switch(chipset_family) {			case ATA_133:				/* SiS962 operation mode */				pci_read_config_word(dev, 0x50, &regw);				if (regw & 0x08)					pci_write_config_word(dev, 0x50, regw&0xfff7);				pci_read_config_word(dev, 0x52, &regw);				if (regw & 0x08)					pci_write_config_word(dev, 0x52, regw&0xfff7);				break;			case ATA_133a:			case ATA_100:				/* Fixup latency */				pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);				/* Set compatibility bit */				pci_read_config_byte(dev, 0x49, &reg);				if (!(reg & 0x01)) {					pci_write_config_byte(dev, 0x49, reg|0x01);				}				break;			case ATA_100a:			case ATA_66:				/* Fixup latency */				pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);				/* On ATA_66 chips the bit was elsewhere */				pci_read_config_byte(dev, 0x52, &reg);				if (!(reg & 0x04)) {					pci_write_config_byte(dev, 0x52, reg|0x04);				}				break;			case ATA_33:				/* On ATA_33 we didn't have a single bit to set */				pci_read_config_byte(dev, 0x09, &reg);				if ((reg & 0x0f) != 0x00) {					pci_write_config_byte(dev, 0x09, reg&0xf0);				}			case ATA_16:				/* force per drive recovery and active timings				   needed on ATA_33 and below chips */				pci_read_config_byte(dev, 0x52, &reg);				if (!(reg & 0x08)) {					pci_write_config_byte(dev, 0x52, reg|0x08);				}				break;		}	}	return 0;}struct sis_laptop {	u16 device;	u16 subvendor;	u16 subdevice;};static const struct sis_laptop sis_laptop[] = {	/* devid, subvendor, subdev */	{ 0x5513, 0x1043, 0x1107 },	/* ASUS A6K */	{ 0x5513, 0x1734, 0x105f },	/* FSC Amilo A1630 */	{ 0x5513, 0x1071, 0x8640 },     /* EasyNote K5305 */	/* end marker */	{ 0, }};static u8 __devinit ata66_sis5513(ide_hwif_t *hwif){	struct pci_dev *pdev = hwif->pci_dev;	const struct sis_laptop *lap = &sis_laptop[0];	u8 ata66 = 0;	while (lap->device) {		if (lap->device == pdev->device &&		    lap->subvendor == pdev->subsystem_vendor &&		    lap->subdevice == pdev->subsystem_device)			return ATA_CBL_PATA40_SHORT;		lap++;	}	if (chipset_family >= ATA_133) {		u16 regw = 0;		u16 reg_addr = hwif->channel ? 0x52: 0x50;		pci_read_config_word(hwif->pci_dev, reg_addr, &regw);		ata66 = (regw & 0x8000) ? 0 : 1;	} else if (chipset_family >= ATA_66) {		u8 reg48h = 0;		u8 mask = hwif->channel ? 0x20 : 0x10;		pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);		ata66 = (reg48h & mask) ? 0 : 1;	}	return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;}static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif){	u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };	hwif->set_pio_mode = &sis_set_pio_mode;	hwif->set_dma_mode = &sis_set_dma_mode;	if (chipset_family >= ATA_133)		hwif->udma_filter = sis5513_ata133_udma_filter;	if (hwif->dma_base == 0)		return;	hwif->ultra_mask = udma_rates[chipset_family];	if (hwif->cbl != ATA_CBL_PATA40_SHORT)		hwif->cbl = ata66_sis5513(hwif);}static const struct ide_port_info sis5513_chipset __devinitdata = {	.name		= "SIS5513",	.init_chipset	= init_chipset_sis5513,	.init_hwif	= init_hwif_sis5513,	.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},	.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA |			  IDE_HFLAG_BOOTABLE,	.pio_mask	= ATA_PIO4,	.mwdma_mask	= ATA_MWDMA2,};static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id){	return ide_setup_pci_device(dev, &sis5513_chipset);}static const struct pci_device_id sis5513_pci_tbl[] = {	{ PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5513), 0 },	{ PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5518), 0 },	{ PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_1180), 0 },	{ 0, },};MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);static struct pci_driver driver = {	.name		= "SIS_IDE",	.id_table	= sis5513_pci_tbl,	.probe		= sis5513_init_one,};static int __init sis5513_ide_init(void){	return ide_pci_register_driver(&driver);}module_init(sis5513_ide_init);MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik");MODULE_DESCRIPTION("PCI driver module for SIS IDE");MODULE_LICENSE("GPL");/* * TODO: *	- CLEANUP *	- Use drivers/ide/ide-timing.h ! *	- More checks in the config registers (force values instead of *	  relying on the BIOS setting them correctly). *	- Further optimisations ? *	  . for example ATA66+ regs 0x48 & 0x4A */

⌨️ 快捷键说明

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