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

📄 pdc202xx_new.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Promise TX2/TX4/TX2000/133 IDE driver * *  This program is free software; you can redistribute it and/or *  modify it under the terms of the GNU General Public License *  as published by the Free Software Foundation; either version *  2 of the License, or (at your option) any later version. * *  Split from: *  linux/drivers/ide/pdc202xx.c	Version 0.35	Mar. 30, 2002 *  Copyright (C) 1998-2002		Andre Hedrick <andre@linux-ide.org> *  Portions Copyright (C) 1999 Promise Technology, Inc. *  Author: Frank Tiernan (frankt@promise.com) *  Released under terms of General Public License */#include <linux/config.h>#include <linux/module.h>#include <linux/types.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/io.h>#include <asm/irq.h>#include "ide_modes.h"#include "pdc202xx_new.h"#define PDC202_DEBUG_CABLE	0#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)#include <linux/stat.h>#include <linux/proc_fs.h>static u8 pdcnew_proc = 0;#define PDC202_MAX_DEVS		5static struct pci_dev *pdc202_devs[PDC202_MAX_DEVS];static int n_pdc202_devs;static char * pdcnew_info(char *buf, struct pci_dev *dev){	char *p = buf;	p += sprintf(p, "\n                                ");	switch(dev->device) {		case PCI_DEVICE_ID_PROMISE_20277:			p += sprintf(p, "SBFastTrak 133 Lite"); break;		case PCI_DEVICE_ID_PROMISE_20276:			p += sprintf(p, "MBFastTrak 133 Lite"); break;		case PCI_DEVICE_ID_PROMISE_20275:			p += sprintf(p, "MBUltra133"); break;		case PCI_DEVICE_ID_PROMISE_20271:			p += sprintf(p, "FastTrak TX2000"); break;		case PCI_DEVICE_ID_PROMISE_20270:			p += sprintf(p, "FastTrak LP/TX2/TX4"); break;		case PCI_DEVICE_ID_PROMISE_20269:			p += sprintf(p, "Ultra133 TX2"); break;		case PCI_DEVICE_ID_PROMISE_20268:			p += sprintf(p, "Ultra100 TX2"); break;		default:			p += sprintf(p, "Ultra series"); break;			break;	}	p += sprintf(p, " Chipset.\n");	return (char *)p;}static int pdcnew_get_info (char *buffer, char **addr, off_t offset, int count){	char *p = buffer;	int i, len;	for (i = 0; i < n_pdc202_devs; i++) {		struct pci_dev *dev	= pdc202_devs[i];		p = pdcnew_info(buffer, dev);	}	/* p - buffer must be less than 4k! */	len = (p - buffer) - offset;	*addr = buffer + offset;		return len > count ? count : len;}#endif  /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */static u8 pdcnew_ratemask (ide_drive_t *drive){	u8 mode;	switch(HWIF(drive)->pci_dev->device) {		case PCI_DEVICE_ID_PROMISE_20277:		case PCI_DEVICE_ID_PROMISE_20276:		case PCI_DEVICE_ID_PROMISE_20275:		case PCI_DEVICE_ID_PROMISE_20271:		case PCI_DEVICE_ID_PROMISE_20269:			mode = 4;			break;		case PCI_DEVICE_ID_PROMISE_20270:		case PCI_DEVICE_ID_PROMISE_20268:			mode = 3;			break;		default:			return 0;	}	if (!eighty_ninty_three(drive))		mode = min(mode, (u8)1);	return mode;}static int check_in_drive_lists (ide_drive_t *drive, const char **list){	struct hd_driveid *id = drive->id;	if (pdc_quirk_drives == list) {		while (*list) {			if (strstr(id->model, *list++)) {				return 2;			}		}	} else {		while (*list) {			if (!strcmp(*list++,id->model)) {				return 1;			}		}	}	return 0;}static int pdcnew_tune_chipset (ide_drive_t *drive, u8 xferspeed){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	u8 drive_pci		= 0x60 + (drive->dn << 2);	u8 speed	= ide_rate_filter(pdcnew_ratemask(drive), xferspeed);	u32			drive_conf;	u8			AP, BP, CP, DP;	u8			TA = 0, TB = 0, TC = 0;	if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))		return -1;	pci_read_config_dword(dev, drive_pci, &drive_conf);	pci_read_config_byte(dev, (drive_pci), &AP);	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);	pci_read_config_byte(dev, (drive_pci)|0x03, &DP);	if (speed < XFER_SW_DMA_0) {		if ((AP & 0x0F) || (BP & 0x07)) {			/* clear PIO modes of lower 8421 bits of A Register */			pci_write_config_byte(dev, (drive_pci), AP &~0x0F);			pci_read_config_byte(dev, (drive_pci), &AP);			/* clear PIO modes of lower 421 bits of B Register */			pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0x07);			pci_read_config_byte(dev, (drive_pci)|0x01, &BP);			pci_read_config_byte(dev, (drive_pci), &AP);			pci_read_config_byte(dev, (drive_pci)|0x01, &BP);		}	} else {		if ((BP & 0xF0) && (CP & 0x0F)) {			/* clear DMA modes of upper 842 bits of B Register */			/* clear PIO forced mode upper 1 bit of B Register */			pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0xF0);			pci_read_config_byte(dev, (drive_pci)|0x01, &BP);			/* clear DMA modes of lower 8421 bits of C Register */			pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F);			pci_read_config_byte(dev, (drive_pci)|0x02, &CP);		}	}	pci_read_config_byte(dev, (drive_pci), &AP);	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);	switch(speed) {		case XFER_UDMA_6:	speed = XFER_UDMA_5;		case XFER_UDMA_5:		case XFER_UDMA_4:	TB = 0x20; TC = 0x01; break;		case XFER_UDMA_2:	TB = 0x20; TC = 0x01; break;		case XFER_UDMA_3:		case XFER_UDMA_1:	TB = 0x40; TC = 0x02; break;		case XFER_UDMA_0:		case XFER_MW_DMA_2:	TB = 0x60; TC = 0x03; break;		case XFER_MW_DMA_1:	TB = 0x60; TC = 0x04; break;		case XFER_MW_DMA_0:		case XFER_SW_DMA_2:	TB = 0x60; TC = 0x05; break;		case XFER_SW_DMA_1:	TB = 0x80; TC = 0x06; break;		case XFER_SW_DMA_0:	TB = 0xC0; TC = 0x0B; break;		case XFER_PIO_4:	TA = 0x01; TB = 0x04; break;		case XFER_PIO_3:	TA = 0x02; TB = 0x06; break;		case XFER_PIO_2:	TA = 0x03; TB = 0x08; break;		case XFER_PIO_1:	TA = 0x05; TB = 0x0C; break;		case XFER_PIO_0:		default:		TA = 0x09; TB = 0x13; break;	}	if (speed < XFER_SW_DMA_0) {		pci_write_config_byte(dev, (drive_pci), AP|TA);		pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);	} else {		pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);		pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);	}#if PDC202XX_DECODE_REGISTER_INFO	pci_read_config_byte(dev, (drive_pci), &AP);	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);	pci_read_config_byte(dev, (drive_pci)|0x03, &DP);	decode_registers(REG_A, AP);	decode_registers(REG_B, BP);	decode_registers(REG_C, CP);	decode_registers(REG_D, DP);#endif /* PDC202XX_DECODE_REGISTER_INFO */#if PDC202XX_DEBUG_DRIVE_INFO	printk(KERN_DEBUG "%s: %s drive%d 0x%08x ",		drive->name, ide_xfer_verbose(speed),		drive->dn, drive_conf);		pci_read_config_dword(dev, drive_pci, &drive_conf);	printk("0x%08x\n", drive_conf);#endif /* PDC202XX_DEBUG_DRIVE_INFO */	return (ide_config_drive_speed(drive, speed));}static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed){	ide_hwif_t *hwif	= HWIF(drive);	unsigned long indexreg	= hwif->dma_vendor1;	unsigned long datareg	= hwif->dma_vendor3;	u8 thold		= 0x10;	u8 adj			= (drive->dn%2) ? 0x08 : 0x00;	u8 speed		= ide_rate_filter(pdcnew_ratemask(drive), xferspeed);	if (speed == XFER_UDMA_2) {		hwif->OUTB((thold + adj), indexreg);		hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg);	}	switch (speed) {		case XFER_UDMA_7:			speed = XFER_UDMA_6;		case XFER_UDMA_6:	set_ultra(0x1a, 0x01, 0xcb); break;		case XFER_UDMA_5:	set_ultra(0x1a, 0x02, 0xcb); break;		case XFER_UDMA_4:	set_ultra(0x1a, 0x03, 0xcd); break;		case XFER_UDMA_3:	set_ultra(0x1a, 0x05, 0xcd); break;		case XFER_UDMA_2:	set_ultra(0x2a, 0x07, 0xcd); break;		case XFER_UDMA_1:	set_ultra(0x3a, 0x0a, 0xd0); break;		case XFER_UDMA_0:	set_ultra(0x4a, 0x0f, 0xd5); break;		case XFER_MW_DMA_2:	set_ata2(0x69, 0x25); break;		case XFER_MW_DMA_1:	set_ata2(0x6b, 0x27); break;		case XFER_MW_DMA_0:	set_ata2(0xdf, 0x5f); break;		case XFER_PIO_4:	set_pio(0x23, 0x09, 0x25); break;		case XFER_PIO_3:	set_pio(0x27, 0x0d, 0x35); break;		case XFER_PIO_2:	set_pio(0x23, 0x26, 0x64); break;		case XFER_PIO_1:	set_pio(0x46, 0x29, 0xa4); break;		case XFER_PIO_0:	set_pio(0xfb, 0x2b, 0xac); break;		default:			;	}	return (ide_config_drive_speed(drive, speed));}/*   0    1    2    3    4    5    6   7   8 * 960, 480, 390, 300, 240, 180, 120, 90, 60 *           180, 150, 120,  90,  60 * DMA_Speed * 180, 120,  90,  90,  90,  60,  30 *  11,   5,   4,   3,   2,   1,   0 */static int config_chipset_for_pio (ide_drive_t *drive, u8 pio){	u8 speed = 0;	if (pio == 5) pio = 4;	speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);        	return ((int) pdcnew_tune_chipset(drive, speed));}static void pdcnew_tune_drive (ide_drive_t *drive, u8 pio){	(void) config_chipset_for_pio(drive, pio);}static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif){	hwif->OUTB(0x0b, hwif->dma_vendor1);	return ((u8)((hwif->INB(hwif->dma_vendor3) & 0x04)));}static int config_chipset_for_dma (ide_drive_t *drive){	struct hd_driveid *id	= drive->id;	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	u8 speed		= -1;	u8 cable		= 0;	u8 ultra_66		= ((id->dma_ultra & 0x0010) ||				   (id->dma_ultra & 0x0008)) ? 1 : 0;	switch(dev->device) {		case PCI_DEVICE_ID_PROMISE_20277:		case PCI_DEVICE_ID_PROMISE_20276:		case PCI_DEVICE_ID_PROMISE_20275:		case PCI_DEVICE_ID_PROMISE_20271:		case PCI_DEVICE_ID_PROMISE_20269:		case PCI_DEVICE_ID_PROMISE_20270:		case PCI_DEVICE_ID_PROMISE_20268:			cable = pdcnew_new_cable_detect(hwif);#if PDC202_DEBUG_CABLE			printk(KERN_DEBUG "%s: %s-pin cable, %s-pin cable, %d\n",				hwif->name, hwif->udma_four ? "80" : "40",				cable ? "40" : "80", cable);#endif /* PDC202_DEBUG_CABLE */			break;		default:			/* If it's not one we know we should never			   arrive here.. */			BUG();	}	/*	 * Set the control register to use the 66Mhz system	 * clock for UDMA 3/4 mode operation. If one drive on

⌨️ 快捷键说明

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