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

📄 hpt366.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	{	0,		0x06814ea7	}};#endif#define HPT366_DEBUG_DRIVE_INFO		0#define HPT374_ALLOW_ATA133_6		0#define HPT371_ALLOW_ATA133_6		0#define HPT302_ALLOW_ATA133_6		0#define HPT372_ALLOW_ATA133_6		1#define HPT370_ALLOW_ATA100_5		1#define HPT366_ALLOW_ATA66_4		1#define HPT366_ALLOW_ATA66_3		1#define HPT366_MAX_DEVS			8#define F_LOW_PCI_33	0x23#define F_LOW_PCI_40	0x29#define F_LOW_PCI_50	0x2d#define F_LOW_PCI_66	0x42/* *	Hold all the highpoint quirks and revision information in one *	place. */struct hpt_info{	u8 max_mode;		/* Speeds allowed */	int revision;		/* Chipset revision */	int flags;		/* Chipset properties */#define PLL_MODE	1#define IS_372N		2				/* Speed table */	struct chipset_bus_clock_list_entry *speed;};/* *	This wants fixing so that we do everything not by classrev *	(which breaks on the newest chips) but by creating an *	enumeration of chip variants and using that */static __devinit u32 hpt_revision (struct pci_dev *dev){	u32 class_rev;	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);	class_rev &= 0xff;	switch(dev->device) {		/* Remap new 372N onto 372 */		case PCI_DEVICE_ID_TTI_HPT372N:			class_rev = PCI_DEVICE_ID_TTI_HPT372; break;		case PCI_DEVICE_ID_TTI_HPT374:			class_rev = PCI_DEVICE_ID_TTI_HPT374; break;		case PCI_DEVICE_ID_TTI_HPT371:			class_rev = PCI_DEVICE_ID_TTI_HPT371; break;		case PCI_DEVICE_ID_TTI_HPT302:			class_rev = PCI_DEVICE_ID_TTI_HPT302; break;		case PCI_DEVICE_ID_TTI_HPT372:			class_rev = PCI_DEVICE_ID_TTI_HPT372; break;		default:			break;	}	return class_rev;}static int check_in_drive_lists(ide_drive_t *drive, const char **list);static u8 hpt3xx_ratemask (ide_drive_t *drive){	ide_hwif_t *hwif	= drive->hwif;	struct hpt_info *info	= ide_get_hwifdata(hwif);	u8 mode			= 0;	/* FIXME: TODO - move this to set info->mode once at boot */	if (info->revision >= 8) {		/* HPT374 */		mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3;	} else if (info->revision >= 7) {	/* HPT371 */		mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3;	} else if (info->revision >= 6) {	/* HPT302 */		mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3;	} else if (info->revision >= 5) {	/* HPT372 */		mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3;	} else if (info->revision >= 4) {	/* HPT370A */		mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;	} else if (info->revision >= 3) {	/* HPT370 */		mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;		mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode;	} else {				/* HPT366 and HPT368 */		mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2;	}	if (!eighty_ninty_three(drive) && mode)		mode = min(mode, (u8)1);	return mode;}/* *	Note for the future; the SATA hpt37x we must set *	either PIO or UDMA modes 0,4,5 */ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed){	ide_hwif_t *hwif	= drive->hwif;	struct hpt_info *info	= ide_get_hwifdata(hwif);	u8 mode			= hpt3xx_ratemask(drive);	if (drive->media != ide_disk)		return min(speed, (u8)XFER_PIO_4);	switch(mode) {		case 0x04:			speed = min(speed, (u8)XFER_UDMA_6);			break;		case 0x03:			speed = min(speed, (u8)XFER_UDMA_5);			if (info->revision >= 5)				break;			if (check_in_drive_lists(drive, bad_ata100_5))				speed = min(speed, (u8)XFER_UDMA_4);			break;		case 0x02:			speed = min(speed, (u8)XFER_UDMA_4);	/*	 * CHECK ME, Does this need to be set to 5 ??	 */			if (info->revision >= 3)				break;			if ((check_in_drive_lists(drive, bad_ata66_4)) ||			    (!(HPT366_ALLOW_ATA66_4)))				speed = min(speed, (u8)XFER_UDMA_3);			if ((check_in_drive_lists(drive, bad_ata66_3)) ||			    (!(HPT366_ALLOW_ATA66_3)))				speed = min(speed, (u8)XFER_UDMA_2);			break;		case 0x01:			speed = min(speed, (u8)XFER_UDMA_2);	/*	 * CHECK ME, Does this need to be set to 5 ??	 */			if (info->revision >= 3)				break;			if (check_in_drive_lists(drive, bad_ata33))				speed = min(speed, (u8)XFER_MW_DMA_2);			break;		case 0x00:		default:			speed = min(speed, (u8)XFER_MW_DMA_2);			break;	}	return speed;}static int check_in_drive_lists (ide_drive_t *drive, const char **list){	struct hd_driveid *id = drive->id;	if (quirk_drives == list) {		while (*list)			if (strstr(id->model, *list++))				return 1;	} else {		while (*list)			if (!strcmp(*list++,id->model))				return 1;	}	return 0;}static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_entry * chipset_table){	for ( ; chipset_table->xfer_speed ; chipset_table++)		if (chipset_table->xfer_speed == speed)			return chipset_table->chipset_settings;	return chipset_table->chipset_settings;}static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed){	ide_hwif_t *hwif	= drive->hwif;	struct pci_dev *dev	= hwif->pci_dev;	struct hpt_info	*info	= ide_get_hwifdata(hwif);	u8 speed		= hpt3xx_ratefilter(drive, xferspeed);	u8 regtime		= (drive->select.b.unit & 0x01) ? 0x44 : 0x40;	u8 regfast		= (hwif->channel) ? 0x55 : 0x51;	u8 drive_fast		= 0;	u32 reg1 = 0, reg2	= 0;	/*	 * Disable the "fast interrupt" prediction.	 */	pci_read_config_byte(dev, regfast, &drive_fast);	if (drive_fast & 0x80)		pci_write_config_byte(dev, regfast, drive_fast & ~0x80);	reg2 = pci_bus_clock_list(speed, info->speed);	/*	 * Disable on-chip PIO FIFO/buffer	 *  (to avoid problems handling I/O errors later)	 */	pci_read_config_dword(dev, regtime, &reg1);	if (speed >= XFER_MW_DMA_0) {		reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000);	} else {		reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000);	}		reg2 &= ~0x80000000;	pci_write_config_dword(dev, regtime, reg2);	return ide_config_drive_speed(drive, speed);}static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed){	ide_hwif_t *hwif	= drive->hwif;	struct pci_dev *dev = hwif->pci_dev;	struct hpt_info	*info	= ide_get_hwifdata(hwif);	u8 speed	= hpt3xx_ratefilter(drive, xferspeed);	u8 regfast	= (drive->hwif->channel) ? 0x55 : 0x51;	u8 drive_pci	= 0x40 + (drive->dn * 4);	u8 new_fast	= 0, drive_fast = 0;	u32 list_conf	= 0, drive_conf = 0;	u32 conf_mask	= (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;	/*	 * Disable the "fast interrupt" prediction.	 * don't holdoff on interrupts. (== 0x01 despite what the docs say) 	 */	pci_read_config_byte(dev, regfast, &drive_fast);	new_fast = drive_fast;	if (new_fast & 0x02)		new_fast &= ~0x02;#ifdef HPT_DELAY_INTERRUPT	if (new_fast & 0x01)		new_fast &= ~0x01;#else	if ((new_fast & 0x01) == 0)		new_fast |= 0x01;#endif	if (new_fast != drive_fast)		pci_write_config_byte(dev, regfast, new_fast);	list_conf = pci_bus_clock_list(speed, info->speed);	pci_read_config_dword(dev, drive_pci, &drive_conf);	list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);		if (speed < XFER_MW_DMA_0)		list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */	pci_write_config_dword(dev, drive_pci, list_conf);	return ide_config_drive_speed(drive, speed);}static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed){	ide_hwif_t *hwif	= drive->hwif;	struct pci_dev *dev	= hwif->pci_dev;	struct hpt_info	*info	= ide_get_hwifdata(hwif);	u8 speed	= hpt3xx_ratefilter(drive, xferspeed);	u8 regfast	= (drive->hwif->channel) ? 0x55 : 0x51;	u8 drive_fast	= 0, drive_pci = 0x40 + (drive->dn * 4);	u32 list_conf	= 0, drive_conf = 0;	u32 conf_mask	= (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;	/*	 * Disable the "fast interrupt" prediction.	 * don't holdoff on interrupts. (== 0x01 despite what the docs say)	 */	pci_read_config_byte(dev, regfast, &drive_fast);	drive_fast &= ~0x07;	pci_write_config_byte(dev, regfast, drive_fast);	list_conf = pci_bus_clock_list(speed, info->speed);	pci_read_config_dword(dev, drive_pci, &drive_conf);	list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);	if (speed < XFER_MW_DMA_0)		list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */	pci_write_config_dword(dev, drive_pci, list_conf);	return ide_config_drive_speed(drive, speed);}static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed){	ide_hwif_t *hwif	= drive->hwif;	struct hpt_info	*info	= ide_get_hwifdata(hwif);	if (info->revision >= 8)		return hpt372_tune_chipset(drive, speed); /* not a typo */	else if (info->revision >= 5)		return hpt372_tune_chipset(drive, speed);	else if (info->revision >= 3)		return hpt370_tune_chipset(drive, speed);	else	/* hpt368: hpt_minimum_revision(dev, 2) */		return hpt36x_tune_chipset(drive, speed);}static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio){	pio = ide_get_best_pio_mode(drive, 255, pio, NULL);	(void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio));}/* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities * after the drive is reported by the OS.  Initially for designed for * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. * * check_in_drive_lists(drive, bad_ata66_4) * check_in_drive_lists(drive, bad_ata66_3) * check_in_drive_lists(drive, bad_ata33) * */static int config_chipset_for_dma (ide_drive_t *drive){	u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive));	ide_hwif_t *hwif = drive->hwif;	struct hpt_info	*info	= ide_get_hwifdata(hwif);	if (!speed)		return 0;	/* If we don't have any timings we can't do a lot */	if (info->speed == NULL)		return 0;	(void) hpt3xx_tune_chipset(drive, speed);	return ide_dma_enable(drive);}static int hpt3xx_quirkproc (ide_drive_t *drive){	return ((int) check_in_drive_lists(drive, quirk_drives));}static void hpt3xx_intrproc (ide_drive_t *drive){	ide_hwif_t *hwif = drive->hwif;	if (drive->quirk_list)		return;	/* drives in the quirk_list may not like intr setups/cleanups */	hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);}static void hpt3xx_maskproc (ide_drive_t *drive, int mask){	ide_hwif_t *hwif = drive->hwif;	struct hpt_info *info = ide_get_hwifdata(hwif);	struct pci_dev *dev = hwif->pci_dev;	if (drive->quirk_list) {		if (info->revision >= 3) {			u8 reg5a = 0;			pci_read_config_byte(dev, 0x5a, &reg5a);			if (((reg5a & 0x10) >> 4) != mask)				pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));		} else {			if (mask) {				disable_irq(hwif->irq);			} else {				enable_irq(hwif->irq);			}		}	} else {		if (IDE_CONTROL_REG)			hwif->OUTB(mask ? (drive->ctl | 2) :						 (drive->ctl & ~2),						 IDE_CONTROL_REG);	}}static int hpt366_config_drive_xfer_rate (ide_drive_t *drive){	ide_hwif_t *hwif	= drive->hwif;	struct hd_driveid *id	= drive->id;	drive->init_speed = 0;	if ((id->capability & 1) && 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:		hpt3xx_tune_drive(drive, 5);		return hwif->ide_dma_off_quietly(drive);	}	/* IORDY not supported */	return 0;}/* * This is specific to the HPT366 UDMA bios chipset * by HighPoint|Triones Technologies, Inc. */static int hpt366_ide_dma_lostirq (ide_drive_t *drive){	struct pci_dev *dev	= HWIF(drive)->pci_dev;	u8 reg50h = 0, reg52h = 0, reg5ah = 0;	pci_read_config_byte(dev, 0x50, &reg50h);	pci_read_config_byte(dev, 0x52, &reg52h);	pci_read_config_byte(dev, 0x5a, &reg5ah);	printk("%s: (%s)  reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",		drive->name, __FUNCTION__, reg50h, reg52h, reg5ah);	if (reg5ah & 0x10)		pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);	return __ide_dma_lostirq(drive);}static void hpt370_clear_engine (ide_drive_t *drive){	u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50;	pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37);	udelay(10);}static void hpt370_ide_dma_start(ide_drive_t *drive){#ifdef HPT_RESET_STATE_ENGINE	hpt370_clear_engine(drive);#endif	ide_dma_start(drive);

⌨️ 快捷键说明

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