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

📄 hpt366.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * linux/drivers/ide/pci/hpt366.c		Version 0.34	Sept 17, 2002 * * Copyright (C) 1999-2002		Andre Hedrick <andre@linux-ide.org> * Portions Copyright (C) 2001	        Sun Microsystems, Inc. * * Thanks to HighPoint Technologies for their assistance, and hardware. * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his * donation of an ABit BP6 mainboard, processor, and memory acellerated * development and support. * * Note that final HPT370 support was done by force extraction of GPL. * * - add function for getting/setting power status of drive * - the HPT370's state machine can get confused. reset it before each dma  *   xfer to prevent that from happening. * - reset state engine whenever we get an error. * - check for busmaster state at end of dma.  * - use new highpoint timings. * - detect bus speed using highpoint register. * - use pll if we don't have a clock table. added a 66MHz table that's *   just 2x the 33MHz table. * - removed turnaround. NOTE: we never want to switch between pll and *   pci clocks as the chip can glitch in those cases. the highpoint *   approved workaround slows everything down too much to be useful. in *   addition, we would have to serialize access to each chip. * 	Adrian Sun <a.sun@sun.com> * * add drive timings for 66MHz PCI bus, * fix ATA Cable signal detection, fix incorrect /proc info * add /proc display for per-drive PIO/DMA/UDMA mode and * per-channel ATA-33/66 Cable detect. * 	Duncan Laurie <void@sun.com> * * fixup /proc output for multiple controllers *	Tim Hockin <thockin@sun.com> * * On hpt366:  * Reset the hpt366 on error, reset on dma * Fix disabling Fast Interrupt hpt366. * 	Mike Waychison <crlf@sun.com> */#include <linux/config.h>#include <linux/types.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/blkdev.h>#include <linux/hdreg.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/ide.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/irq.h>#include "ide_modes.h"#include "hpt366.h"#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)#include <linux/stat.h>#include <linux/proc_fs.h>#endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */static unsigned int hpt_revision(struct pci_dev *dev);static unsigned int hpt_minimum_revision(struct pci_dev *dev, int revision);#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)static u8 hpt366_proc = 0;static struct pci_dev *hpt_devs[HPT366_MAX_DEVS];static int n_hpt_devs;static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count){	char *p	= buffer;	char *chipset_nums[] = {"366", "366",  "368",				"370", "370A", "372",				"302", "371",  "374" };	int i;	p += sprintf(p, "\n                             "		"HighPoint HPT366/368/370/372/374\n");	for (i = 0; i < n_hpt_devs; i++) {		struct pci_dev *dev = hpt_devs[i];		unsigned long iobase = dev->resource[4].start;		u32 class_rev = hpt_revision(dev);		u8 c0, c1;		p += sprintf(p, "\nController: %d\n", i);		p += sprintf(p, "Chipset: HPT%s\n", chipset_nums[class_rev]);		p += sprintf(p, "--------------- Primary Channel "				"--------------- Secondary Channel "				"--------------\n");		/* get the bus master status registers */		c0 = inb(iobase + 0x2);		c1 = inb(iobase + 0xa);		p += sprintf(p, "Enabled:        %s"				"                             %s\n",			(c0 & 0x80) ? "no" : "yes",			(c1 & 0x80) ? "no" : "yes");		if (hpt_minimum_revision(dev, 3)) {			u8 cbl;			cbl = inb(iobase + 0x7b);			outb(cbl | 1, iobase + 0x7b);			outb(cbl & ~1, iobase + 0x7b);			cbl = inb(iobase + 0x7a);			p += sprintf(p, "Cable:          ATA-%d"					"                          ATA-%d\n",				(cbl & 0x02) ? 33 : 66,				(cbl & 0x01) ? 33 : 66);			p += sprintf(p, "\n");		}		p += sprintf(p, "--------------- drive0 --------- drive1 "				"------- drive0 ---------- drive1 -------\n");		p += sprintf(p, "DMA capable:    %s              %s" 				"            %s               %s\n",			(c0 & 0x20) ? "yes" : "no ", 			(c0 & 0x40) ? "yes" : "no ",			(c1 & 0x20) ? "yes" : "no ", 			(c1 & 0x40) ? "yes" : "no ");		{			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 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) {		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 u32 hpt_minimum_revision (struct pci_dev *dev, int revision){	unsigned int class_rev = hpt_revision(dev);	revision--;	return ((int) (class_rev > revision) ? 1 : 0);}static int check_in_drive_lists(ide_drive_t *drive, const char **list);static u8 hpt3xx_ratemask (ide_drive_t *drive){	struct pci_dev *dev	= HWIF(drive)->pci_dev;	u8 mode			= 0;	if (hpt_minimum_revision(dev, 8)) {		/* HPT374 */		mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3;	} else if (hpt_minimum_revision(dev, 7)) {	/* HPT371 */		mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3;	} else if (hpt_minimum_revision(dev, 6)) {	/* HPT302 */		mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3;	} else if (hpt_minimum_revision(dev, 5)) {	/* HPT372 */		mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3;	} else if (hpt_minimum_revision(dev, 4)) {	/* HPT370A */		mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;	} else if (hpt_minimum_revision(dev, 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;}static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed){	struct pci_dev *dev	= HWIF(drive)->pci_dev;	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 (hpt_minimum_revision(dev, 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 (hpt_minimum_revision(dev, 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 (hpt_minimum_revision(dev, 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 void hpt366_tune_chipset (ide_drive_t *drive, u8 xferspeed){	struct pci_dev *dev	= HWIF(drive)->pci_dev;	u8 speed		= hpt3xx_ratefilter(drive, xferspeed);//	u8 speed		= ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);	u8 regtime		= (drive->select.b.unit & 0x01) ? 0x44 : 0x40;	u8 regfast		= (HWIF(drive)->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 0	if (drive_fast & 0x02)		pci_write_config_byte(dev, regfast, drive_fast & ~0x20);#else	if (drive_fast & 0x80)		pci_write_config_byte(dev, regfast, drive_fast & ~0x80);#endif	reg2 = pci_bus_clock_list(speed,		(struct chipset_bus_clock_list_entry *) pci_get_drvdata(dev));	/*	 * 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);}static void hpt368_tune_chipset (ide_drive_t *drive, u8 speed){	hpt366_tune_chipset(drive, speed);}static void hpt370_tune_chipset (ide_drive_t *drive, u8 xferspeed){	struct pci_dev *dev = HWIF(drive)->pci_dev;	u8 speed	= hpt3xx_ratefilter(drive, xferspeed);//	u8 speed	= ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);	u8 regfast	= (HWIF(drive)->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, 				       (struct chipset_bus_clock_list_entry *)				       pci_get_drvdata(dev));	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 void hpt372_tune_chipset (ide_drive_t *drive, u8 xferspeed){	struct pci_dev *dev	= HWIF(drive)->pci_dev;	u8 speed	= hpt3xx_ratefilter(drive, xferspeed);//	u8 speed	= ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);	u8 regfast	= (HWIF(drive)->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,			(struct chipset_bus_clock_list_entry *)					pci_get_drvdata(dev));	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 void hpt374_tune_chipset (ide_drive_t *drive, u8 speed){

⌨️ 快捷键说明

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