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

📄 hpt366.c

📁 at91rm9200处理器ide接口驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		{			u8 c2, c3;			/* older revs don't have these registers mapped 			 * into io space */			pci_read_config_byte(dev, 0x43, &c0);			pci_read_config_byte(dev, 0x47, &c1);			pci_read_config_byte(dev, 0x4b, &c2);			pci_read_config_byte(dev, 0x4f, &c3);			p += sprintf(p, "Mode:           %s             %s"					"           %s              %s\n",				(c0 & 0x10) ? "UDMA" : (c0 & 0x20) ? "DMA " : 					(c0 & 0x80) ? "PIO " : "off ",				(c1 & 0x10) ? "UDMA" : (c1 & 0x20) ? "DMA " :					(c1 & 0x80) ? "PIO " : "off ",				(c2 & 0x10) ? "UDMA" : (c2 & 0x20) ? "DMA " :					(c2 & 0x80) ? "PIO " : "off ",				(c3 & 0x10) ? "UDMA" : (c3 & 0x20) ? "DMA " :					(c3 & 0x80) ? "PIO " : "off ");		}	}	p += sprintf(p, "\n");		return p-buffer;/* => must be less than 4k! */}#endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */static unsigned int pci_rev_check_hpt3xx (struct pci_dev *dev){	unsigned int class_rev;	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);	class_rev &= 0xff;	return ((int) (class_rev > 0x02) ? 1 : 0);}static unsigned int pci_rev2_check_hpt3xx (struct pci_dev *dev){	unsigned int class_rev;	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);	class_rev &= 0xff;	return ((int) (class_rev > 0x01) ? 1 : 0);}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 (byte 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 void hpt366_tune_chipset (ide_drive_t *drive, byte speed){	byte regtime		= (drive->select.b.unit & 0x01) ? 0x44 : 0x40;	byte regfast		= (HWIF(drive)->channel) ? 0x55 : 0x51;			/*			 * since the channel is always 0 it does not matter.			 */	unsigned int reg1	= 0;	unsigned int reg2	= 0;	byte drive_fast		= 0;	/*	 * Disable the "fast interrupt" prediction. 	 */	pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast);	if (drive_fast & 0x02)		pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x20);	pci_read_config_dword(HWIF(drive)->pci_dev, regtime, &reg1);	/* detect bus speed by looking at control reg timing: */	switch((reg1 >> 8) & 7) {		case 5:			reg2 = pci_bus_clock_list(speed, forty_base);			break;		case 9:			reg2 = pci_bus_clock_list(speed, twenty_five_base);			break;		default:		case 7:			reg2 = pci_bus_clock_list(speed, thirty_three_base);			break;	}#if 0	/* this is a nice idea ... */	list_conf = pci_bus_clock_list(speed,				       (struct chipset_bus_clock_list_entry *)				       dev->sysdata);#endif	/*	 * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later)	 */	if (speed >= XFER_MW_DMA_0) {		reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000);	} else {		reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000);	}		reg2 &= ~0x80000000;	pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2);}static void hpt370_tune_chipset (ide_drive_t *drive, byte speed){	byte regfast		= (HWIF(drive)->channel) ? 0x55 : 0x51;	unsigned int list_conf	= 0;	unsigned int drive_conf = 0;	unsigned int conf_mask	= (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;	byte drive_pci		= 0x40 + (drive->dn * 4);	byte new_fast, drive_fast		= 0;	struct pci_dev *dev 	= HWIF(drive)->pci_dev;	/*	 * 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(HWIF(drive)->pci_dev, regfast, new_fast);	list_conf = pci_bus_clock_list(speed, 				       (struct chipset_bus_clock_list_entry *)				       dev->sysdata);	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);}static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed){	if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))		return -1;	if (!drive->init_speed)		drive->init_speed = speed;	if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) {		hpt370_tune_chipset(drive, speed);        } else {                hpt366_tune_chipset(drive, speed);        }	drive->current_speed = speed;	return ((int) ide_config_drive_speed(drive, speed));}static void config_chipset_for_pio (ide_drive_t *drive){	unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};	unsigned short xfer_pio = drive->id->eide_pio_modes;	byte	timing, speed, pio;	pio = ide_get_best_pio_mode(drive, 255, 5, NULL);	if (xfer_pio> 4)		xfer_pio = 0;	if (drive->id->eide_pio_iordy > 0) {		for (xfer_pio = 5;			xfer_pio>0 &&			drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];			xfer_pio--);	} else {		xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :			   (drive->id->eide_pio_modes & 2) ? 0x04 :			   (drive->id->eide_pio_modes & 1) ? 0x03 :			   (drive->id->tPIO & 2) ? 0x02 :			   (drive->id->tPIO & 1) ? 0x01 : xfer_pio;	}	timing = (xfer_pio >= pio) ? xfer_pio : pio;	switch(timing) {		case 4: speed = XFER_PIO_4;break;		case 3: speed = XFER_PIO_3;break;		case 2: speed = XFER_PIO_2;break;		case 1: speed = XFER_PIO_1;break;		default:			speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;			break;	}	(void) hpt3xx_tune_chipset(drive, speed);}static void hpt3xx_tune_drive (ide_drive_t *drive, byte pio){	byte speed;	switch(pio) {		case 4:		speed = XFER_PIO_4;break;		case 3:		speed = XFER_PIO_3;break;		case 2:		speed = XFER_PIO_2;break;		case 1:		speed = XFER_PIO_1;break;		default:	speed = XFER_PIO_0;break;	}	(void) hpt3xx_tune_chipset(drive, speed);}#ifdef CONFIG_BLK_DEV_IDEDMA/* * 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.  Initally 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){	struct hd_driveid *id	= drive->id;	byte speed		= 0x00;	byte ultra66		= eighty_ninty_three(drive);	int  rval;	if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))		return ((int) ide_dma_off_quietly);	if ((id->dma_ultra & 0x0020) &&	    (!check_in_drive_lists(drive, bad_ata100_5)) &&	    (HPT370_ALLOW_ATA100_5) &&	    (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) &&	    (ultra66)) {		speed = XFER_UDMA_5;	} else if ((id->dma_ultra & 0x0010) &&		   (!check_in_drive_lists(drive, bad_ata66_4)) &&		   (HPT366_ALLOW_ATA66_4) &&		   (ultra66)) {		speed = XFER_UDMA_4;	} else if ((id->dma_ultra & 0x0008) &&		   (!check_in_drive_lists(drive, bad_ata66_3)) &&		   (HPT366_ALLOW_ATA66_3) &&		   (ultra66)) {		speed = XFER_UDMA_3;	} else if (id->dma_ultra && (!check_in_drive_lists(drive, bad_ata33))) {		if (id->dma_ultra & 0x0004) {			speed = XFER_UDMA_2;		} else if (id->dma_ultra & 0x0002) {			speed = XFER_UDMA_1;		} else if (id->dma_ultra & 0x0001) {			speed = XFER_UDMA_0;		}	} else if (id->dma_mword & 0x0004) {		speed = XFER_MW_DMA_2;	} else if (id->dma_mword & 0x0002) {		speed = XFER_MW_DMA_1;	} else if (id->dma_mword & 0x0001) {		speed = XFER_MW_DMA_0;	} else {		return ((int) ide_dma_off_quietly);	}	(void) hpt3xx_tune_chipset(drive, speed);	rval = (int)(	((id->dma_ultra >> 11) & 7) ? ide_dma_on :			((id->dma_ultra >> 8) & 7) ? ide_dma_on :			((id->dma_mword >> 8) & 7) ? ide_dma_on :						     ide_dma_off_quietly);	return rval;}int hpt3xx_quirkproc (ide_drive_t *drive){	return ((int) check_in_drive_lists(drive, quirk_drives));}void hpt3xx_intrproc (ide_drive_t *drive){	if (drive->quirk_list) {		/* drives in the quirk_list may not like intr setups/cleanups */	} else {		OUT_BYTE((drive)->ctl|2, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);	}}void hpt3xx_maskproc (ide_drive_t *drive, int mask){	if (drive->quirk_list) {		if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) {			byte reg5a = 0;			pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, &reg5a);			if (((reg5a & 0x10) >> 4) != mask)				pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));		} else {			if (mask) {				disable_irq(HWIF(drive)->irq);			} else {				enable_irq(HWIF(drive)->irq);			}		}	} else {		if (IDE_CONTROL_REG)			OUT_BYTE(mask ? (drive->ctl | 2) : (drive->ctl & ~2), IDE_CONTROL_REG);	}}static int config_drive_xfer_rate (ide_drive_t *drive){	struct hd_driveid *id = drive->id;	ide_dma_action_t dma_func = ide_dma_on;	if (id && (id->capability & 1) && HWIF(drive)->autodma) {		/* Consult the list of known "bad" drives */		if (ide_dmaproc(ide_dma_bad_drive, drive)) {			dma_func = ide_dma_off;			goto fast_ata_pio;		}		dma_func = ide_dma_off_quietly;		if (id->field_valid & 4) {			if (id->dma_ultra & 0x002F) {				/* Force if Capable UltraDMA */				dma_func = config_chipset_for_dma(drive);				if ((id->field_valid & 2) &&				    (dma_func != ide_dma_on))					goto try_dma_modes;			}		} else if (id->field_valid & 2) {try_dma_modes:			if (id->dma_mword & 0x0007) {				/* Force if Capable regular DMA modes */				dma_func = config_chipset_for_dma(drive);				if (dma_func != ide_dma_on)					goto no_dma_set;			}		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {			if (id->eide_dma_time > 150) {				goto no_dma_set;			}			/* Consult the list of known "good" drives */			dma_func = config_chipset_for_dma(drive);			if (dma_func != ide_dma_on)				goto no_dma_set;		} else {			goto fast_ata_pio;		}	} else if ((id->capability & 8) || (id->field_valid & 2)) {fast_ata_pio:		dma_func = ide_dma_off_quietly;no_dma_set:		config_chipset_for_pio(drive);	}	return HWIF(drive)->dmaproc(dma_func, drive);}/* * hpt366_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. * * This is specific to the HPT366 UDMA bios chipset * by HighPoint|Triones Technologies, Inc. */int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive){	byte reg50h = 0, reg52h = 0, reg5ah = 0, dma_stat = 0;	unsigned long dma_base = HWIF(drive)->dma_base;	switch (func) {		case ide_dma_check:			return config_drive_xfer_rate(drive);		case ide_dma_test_irq:	/* returns 1 if dma irq issued, 0 otherwise */			dma_stat = inb(dma_base+2);			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */		case ide_dma_lostirq:			pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);			pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);			pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, &reg5ah);			printk("%s: (%s)  reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",				drive->name,				ide_dmafunc_verbose(func),				reg50h, reg52h, reg5ah);			if (reg5ah & 0x10)				pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, reg5ah & ~0x10);			/* fall through to a reset */

⌨️ 快捷键说明

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