hpt366.c

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

C
1,677
字号
static u32 sixty_six_base_hpt37x[] = {	/* XFER_UDMA_6 */	0x1c86fe62,	/* XFER_UDMA_5 */	0x1caefe62,	/* 0x1c8afe62 */	/* XFER_UDMA_4 */	0x1c8afe62,	/* XFER_UDMA_3 */	0x1c8efe62,	/* XFER_UDMA_2 */	0x1c92fe62,	/* XFER_UDMA_1 */	0x1c9afe62,	/* XFER_UDMA_0 */	0x1c82fe62,	/* XFER_MW_DMA_2 */	0x2c82fe62,	/* XFER_MW_DMA_1 */	0x2c82fe66,	/* XFER_MW_DMA_0 */	0x2c82ff2e,	/* XFER_PIO_4 */	0x0c82fe62,	/* XFER_PIO_3 */	0x0c82fe84,	/* XFER_PIO_2 */	0x0c82fea6,	/* XFER_PIO_1 */	0x0d02ff26,	/* XFER_PIO_0 */	0x0d42ff7f};#endif#define HPT366_DEBUG_DRIVE_INFO		0#define HPT371_ALLOW_ATA133_6		1#define HPT302_ALLOW_ATA133_6		1#define HPT372_ALLOW_ATA133_6		1#define HPT370_ALLOW_ATA100_5		0#define HPT366_ALLOW_ATA66_4		1#define HPT366_ALLOW_ATA66_3		1#define HPT366_MAX_DEVS			8/* Supported ATA clock frequencies */enum ata_clock {	ATA_CLOCK_25MHZ,	ATA_CLOCK_33MHZ,	ATA_CLOCK_40MHZ,	ATA_CLOCK_50MHZ,	ATA_CLOCK_66MHZ,	NUM_ATA_CLOCKS};/* *	Hold all the HighPoint chip information in one place. */struct hpt_info {	char *chip_name;	/* Chip name */	u8 chip_type;		/* Chip type */	u8 udma_mask;		/* Allowed UltraDMA modes mask. */	u8 dpll_clk;		/* DPLL clock in MHz */	u8 pci_clk;		/* PCI  clock in MHz */	u32 **settings; 	/* Chipset settings table */};/* Supported HighPoint chips */enum {	HPT36x,	HPT370,	HPT370A,	HPT374,	HPT372,	HPT372A,	HPT302,	HPT371,	HPT372N,	HPT302N,	HPT371N};static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = {	twenty_five_base_hpt36x,	thirty_three_base_hpt36x,	forty_base_hpt36x,	NULL,	NULL};static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {	NULL,	thirty_three_base_hpt37x,	NULL,	fifty_base_hpt37x,	sixty_six_base_hpt37x};static const struct hpt_info hpt36x __devinitdata = {	.chip_name	= "HPT36x",	.chip_type	= HPT36x,	.udma_mask	= HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,	.dpll_clk	= 0,	/* no DPLL */	.settings	= hpt36x_settings};static const struct hpt_info hpt370 __devinitdata = {	.chip_name	= "HPT370",	.chip_type	= HPT370,	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,	.dpll_clk	= 48,	.settings	= hpt37x_settings};static const struct hpt_info hpt370a __devinitdata = {	.chip_name	= "HPT370A",	.chip_type	= HPT370A,	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,	.dpll_clk	= 48,	.settings	= hpt37x_settings};static const struct hpt_info hpt374 __devinitdata = {	.chip_name	= "HPT374",	.chip_type	= HPT374,	.udma_mask	= ATA_UDMA5,	.dpll_clk	= 48,	.settings	= hpt37x_settings};static const struct hpt_info hpt372 __devinitdata = {	.chip_name	= "HPT372",	.chip_type	= HPT372,	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,	.dpll_clk	= 55,	.settings	= hpt37x_settings};static const struct hpt_info hpt372a __devinitdata = {	.chip_name	= "HPT372A",	.chip_type	= HPT372A,	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,	.dpll_clk	= 66,	.settings	= hpt37x_settings};static const struct hpt_info hpt302 __devinitdata = {	.chip_name	= "HPT302",	.chip_type	= HPT302,	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,	.dpll_clk	= 66,	.settings	= hpt37x_settings};static const struct hpt_info hpt371 __devinitdata = {	.chip_name	= "HPT371",	.chip_type	= HPT371,	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,	.dpll_clk	= 66,	.settings	= hpt37x_settings};static const struct hpt_info hpt372n __devinitdata = {	.chip_name	= "HPT372N",	.chip_type	= HPT372N,	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,	.dpll_clk	= 77,	.settings	= hpt37x_settings};static const struct hpt_info hpt302n __devinitdata = {	.chip_name	= "HPT302N",	.chip_type	= HPT302N,	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,	.dpll_clk	= 77,	.settings	= hpt37x_settings};static const struct hpt_info hpt371n __devinitdata = {	.chip_name	= "HPT371N",	.chip_type	= HPT371N,	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,	.dpll_clk	= 77,	.settings	= hpt37x_settings};static int check_in_drive_list(ide_drive_t *drive, const char **list){	struct hd_driveid *id = drive->id;	while (*list)		if (!strcmp(*list++,id->model))			return 1;	return 0;}/* * The Marvell bridge chips used on the HighPoint SATA cards do not seem * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes... */static u8 hpt3xx_udma_filter(ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	struct hpt_info *info	= pci_get_drvdata(hwif->pci_dev);	u8 mask 		= hwif->ultra_mask;	switch (info->chip_type) {	case HPT36x:		if (!HPT366_ALLOW_ATA66_4 ||		    check_in_drive_list(drive, bad_ata66_4))			mask = ATA_UDMA3;		if (!HPT366_ALLOW_ATA66_3 ||		    check_in_drive_list(drive, bad_ata66_3))			mask = ATA_UDMA2;		break;	case HPT370:		if (!HPT370_ALLOW_ATA100_5 ||		    check_in_drive_list(drive, bad_ata100_5))			mask = ATA_UDMA4;		break;	case HPT370A:		if (!HPT370_ALLOW_ATA100_5 ||		    check_in_drive_list(drive, bad_ata100_5))			return ATA_UDMA4;	case HPT372 :	case HPT372A:	case HPT372N:	case HPT374 :		if (ide_dev_is_sata(drive->id))			mask &= ~0x0e;		/* Fall thru */	default:		return mask;	}	return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;}static u8 hpt3xx_mdma_filter(ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	struct hpt_info *info	= pci_get_drvdata(hwif->pci_dev);	switch (info->chip_type) {	case HPT372 :	case HPT372A:	case HPT372N:	case HPT374 :		if (ide_dev_is_sata(drive->id))			return 0x00;		/* Fall thru */	default:		return 0x07;	}}static u32 get_speed_setting(u8 speed, struct hpt_info *info){	int i;	/*	 * Lookup the transfer mode table to get the index into	 * the timing table.	 *	 * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.	 */	for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)		if (xfer_speeds[i] == speed)			break;	/*	 * NOTE: info->settings only points to the pointer	 * to the list of the actual register values	 */	return (*info->settings)[i];}static void hpt36x_set_mode(ide_drive_t *drive, const u8 speed){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev  *dev	= hwif->pci_dev;	struct hpt_info	*info	= pci_get_drvdata(dev);	u8  itr_addr		= drive->dn ? 0x44 : 0x40;	u32 old_itr		= 0;	u32 itr_mask, new_itr;	itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 :		  (speed < XFER_UDMA_0   ? 0xc0070000 : 0xc03800ff);	new_itr = get_speed_setting(speed, info);	/*	 * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)	 * to avoid problems handling I/O errors later	 */	pci_read_config_dword(dev, itr_addr, &old_itr);	new_itr  = (new_itr & ~itr_mask) | (old_itr & itr_mask);	new_itr &= ~0xc0000000;	pci_write_config_dword(dev, itr_addr, new_itr);}static void hpt37x_set_mode(ide_drive_t *drive, const u8 speed){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev  *dev	= hwif->pci_dev;	struct hpt_info	*info	= pci_get_drvdata(dev);	u8  itr_addr		= 0x40 + (drive->dn * 4);	u32 old_itr		= 0;	u32 itr_mask, new_itr;	itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 :		  (speed < XFER_UDMA_0   ? 0xc03c0000 : 0xc1c001ff);	new_itr = get_speed_setting(speed, info);	pci_read_config_dword(dev, itr_addr, &old_itr);	new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);		if (speed < XFER_MW_DMA_0)		new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */	pci_write_config_dword(dev, itr_addr, new_itr);}static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed){	ide_hwif_t *hwif	= HWIF(drive);	struct hpt_info	*info	= pci_get_drvdata(hwif->pci_dev);	if (info->chip_type >= HPT370)		hpt37x_set_mode(drive, speed);	else	/* hpt368: hpt_minimum_revision(dev, 2) */		hpt36x_set_mode(drive, speed);}static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio){	hpt3xx_set_mode(drive, XFER_PIO_0 + pio);}static int hpt3xx_quirkproc(ide_drive_t *drive){	struct hd_driveid *id	= drive->id;	const  char **list	= quirk_drives;	while (*list)		if (strstr(id->model, *list++))			return 1;	return 0;}static void hpt3xx_intrproc(ide_drive_t *drive){	if (drive->quirk_list)		return;	/* drives in the quirk_list may not like intr setups/cleanups */	outb(drive->ctl | 2, IDE_CONTROL_REG);}static void hpt3xx_maskproc(ide_drive_t *drive, int mask){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev	*dev	= hwif->pci_dev;	struct hpt_info *info	= pci_get_drvdata(dev);	if (drive->quirk_list) {		if (info->chip_type >= HPT370) {			u8 scr1 = 0;			pci_read_config_byte(dev, 0x5a, &scr1);			if (((scr1 & 0x10) >> 4) != mask) {				if (mask)					scr1 |=  0x10;				else					scr1 &= ~0x10;				pci_write_config_byte(dev, 0x5a, scr1);			}		} else {			if (mask)				disable_irq(hwif->irq);			else				enable_irq (hwif->irq);		}	} else		outb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),		     IDE_CONTROL_REG);}/* * This is specific to the HPT366 UDMA chipset * by HighPoint|Triones Technologies, Inc. */static void hpt366_dma_lost_irq(ide_drive_t *drive){	struct pci_dev *dev = HWIF(drive)->pci_dev;	u8 mcr1 = 0, mcr3 = 0, scr1 = 0;	pci_read_config_byte(dev, 0x50, &mcr1);	pci_read_config_byte(dev, 0x52, &mcr3);	pci_read_config_byte(dev, 0x5a, &scr1);	printk("%s: (%s)  mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n",		drive->name, __FUNCTION__, mcr1, mcr3, scr1);	if (scr1 & 0x10)		pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);	ide_dma_lost_irq(drive);}static void hpt370_clear_engine(ide_drive_t *drive){	ide_hwif_t *hwif = HWIF(drive);	pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37);	udelay(10);}static void hpt370_irq_timeout(ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	u16 bfifo		= 0;	u8  dma_cmd;	pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);	printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);	/* get DMA command mode */	dma_cmd = inb(hwif->dma_command);	/* stop DMA */	outb(dma_cmd & ~0x1, hwif->dma_command);	hpt370_clear_engine(drive);}static void hpt370_ide_dma_start(ide_drive_t *drive)

⌨️ 快捷键说明

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