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

📄 cmd64x.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/drivers/ide/pci/cmd64x.c		Version 1.52	Dec 24, 2007 * * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. *           Due to massive hardware bugs, UltraDMA is only supported *           on the 646U2 and not on the 646U. * * Copyright (C) 1998		Eddie C. Dost  (ecd@skynet.be) * Copyright (C) 1998		David S. Miller (davem@redhat.com) * * Copyright (C) 1999-2002	Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2007		MontaVista Software, Inc. <source@mvista.com> */#include <linux/module.h>#include <linux/types.h>#include <linux/pci.h>#include <linux/delay.h>#include <linux/hdreg.h>#include <linux/ide.h>#include <linux/init.h>#include <asm/io.h>#define DISPLAY_CMD64X_TIMINGS#define CMD_DEBUG 0#if CMD_DEBUG#define cmdprintk(x...)	printk(x)#else#define cmdprintk(x...)#endif/* * CMD64x specific registers definition. */#define CFR		0x50#define   CFR_INTR_CH0		0x04#define CNTRL		0x51#define   CNTRL_ENA_1ST 	0x04#define   CNTRL_ENA_2ND 	0x08#define   CNTRL_DIS_RA0 	0x40#define   CNTRL_DIS_RA1 	0x80#define	CMDTIM		0x52#define	ARTTIM0		0x53#define	DRWTIM0		0x54#define ARTTIM1 	0x55#define DRWTIM1		0x56#define ARTTIM23	0x57#define   ARTTIM23_DIS_RA2	0x04#define   ARTTIM23_DIS_RA3	0x08#define   ARTTIM23_INTR_CH1	0x10#define DRWTIM2		0x58#define BRST		0x59#define DRWTIM3		0x5b#define BMIDECR0	0x70#define MRDMODE		0x71#define   MRDMODE_INTR_CH0	0x04#define   MRDMODE_INTR_CH1	0x08#define   MRDMODE_BLK_CH0	0x10#define   MRDMODE_BLK_CH1	0x20#define BMIDESR0	0x72#define UDIDETCR0	0x73#define DTPR0		0x74#define BMIDECR1	0x78#define BMIDECSR	0x79#define BMIDESR1	0x7A#define UDIDETCR1	0x7B#define DTPR1		0x7C#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)#include <linux/stat.h>#include <linux/proc_fs.h>static u8 cmd64x_proc = 0;#define CMD_MAX_DEVS		5static struct pci_dev *cmd_devs[CMD_MAX_DEVS];static int n_cmd_devs;static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index){	char *p = buf;	u8 reg72 = 0, reg73 = 0;			/* primary */	u8 reg7a = 0, reg7b = 0;			/* secondary */	u8 reg50 = 1, reg51 = 1, reg57 = 0, reg71 = 0;	/* extra */	p += sprintf(p, "\nController: %d\n", index);	p += sprintf(p, "PCI-%x Chipset.\n", dev->device);	(void) pci_read_config_byte(dev, CFR,       &reg50);	(void) pci_read_config_byte(dev, CNTRL,     &reg51);	(void) pci_read_config_byte(dev, ARTTIM23,  &reg57);	(void) pci_read_config_byte(dev, MRDMODE,   &reg71);	(void) pci_read_config_byte(dev, BMIDESR0,  &reg72);	(void) pci_read_config_byte(dev, UDIDETCR0, &reg73);	(void) pci_read_config_byte(dev, BMIDESR1,  &reg7a);	(void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);	/* PCI0643/6 originally didn't have the primary channel enable bit */	if ((dev->device == PCI_DEVICE_ID_CMD_643) ||	    (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 3))		reg51 |= CNTRL_ENA_1ST;	p += sprintf(p, "---------------- Primary Channel "			"---------------- Secondary Channel ------------\n");	p += sprintf(p, "                 %s                         %s\n",		 (reg51 & CNTRL_ENA_1ST) ? "enabled " : "disabled",		 (reg51 & CNTRL_ENA_2ND) ? "enabled " : "disabled");	p += sprintf(p, "---------------- drive0 --------- drive1 "			"-------- drive0 --------- drive1 ------\n");	p += sprintf(p, "DMA enabled:     %s              %s"			"             %s              %s\n",		(reg72 & 0x20) ? "yes" : "no ", (reg72 & 0x40) ? "yes" : "no ",		(reg7a & 0x20) ? "yes" : "no ", (reg7a & 0x40) ? "yes" : "no ");	p += sprintf(p, "UltraDMA mode:   %s (%c)          %s (%c)",		( reg73 & 0x01) ? " on" : "off",		((reg73 & 0x30) == 0x30) ? ((reg73 & 0x04) ? '3' : '0') :		((reg73 & 0x30) == 0x20) ? ((reg73 & 0x04) ? '3' : '1') :		((reg73 & 0x30) == 0x10) ? ((reg73 & 0x04) ? '4' : '2') :		((reg73 & 0x30) == 0x00) ? ((reg73 & 0x04) ? '5' : '2') : '?',		( reg73 & 0x02) ? " on" : "off",		((reg73 & 0xC0) == 0xC0) ? ((reg73 & 0x08) ? '3' : '0') :		((reg73 & 0xC0) == 0x80) ? ((reg73 & 0x08) ? '3' : '1') :		((reg73 & 0xC0) == 0x40) ? ((reg73 & 0x08) ? '4' : '2') :		((reg73 & 0xC0) == 0x00) ? ((reg73 & 0x08) ? '5' : '2') : '?');	p += sprintf(p, "         %s (%c)          %s (%c)\n",		( reg7b & 0x01) ? " on" : "off",		((reg7b & 0x30) == 0x30) ? ((reg7b & 0x04) ? '3' : '0') :		((reg7b & 0x30) == 0x20) ? ((reg7b & 0x04) ? '3' : '1') :		((reg7b & 0x30) == 0x10) ? ((reg7b & 0x04) ? '4' : '2') :		((reg7b & 0x30) == 0x00) ? ((reg7b & 0x04) ? '5' : '2') : '?',		( reg7b & 0x02) ? " on" : "off",		((reg7b & 0xC0) == 0xC0) ? ((reg7b & 0x08) ? '3' : '0') :		((reg7b & 0xC0) == 0x80) ? ((reg7b & 0x08) ? '3' : '1') :		((reg7b & 0xC0) == 0x40) ? ((reg7b & 0x08) ? '4' : '2') :		((reg7b & 0xC0) == 0x00) ? ((reg7b & 0x08) ? '5' : '2') : '?');	p += sprintf(p, "Interrupt:       %s, %s                 %s, %s\n",		(reg71 & MRDMODE_BLK_CH0  ) ? "blocked" : "enabled",		(reg50 & CFR_INTR_CH0	  ) ? "pending" : "clear  ",		(reg71 & MRDMODE_BLK_CH1  ) ? "blocked" : "enabled",		(reg57 & ARTTIM23_INTR_CH1) ? "pending" : "clear  ");	return (char *)p;}static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count){	char *p = buffer;	int i;	for (i = 0; i < n_cmd_devs; i++) {		struct pci_dev *dev	= cmd_devs[i];		p = print_cmd64x_get_info(p, dev, i);	}	return p-buffer;	/* => must be less than 4k! */}#endif	/* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */static u8 quantize_timing(int timing, int quant){	return (timing + quant - 1) / quant;}/* * This routine calculates active/recovery counts and then writes them into * the chipset registers. */static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time){	struct pci_dev *dev	= HWIF(drive)->pci_dev;	int clock_time		= 1000 / system_bus_clock();	u8  cycle_count, active_count, recovery_count, drwtim;	static const u8 recovery_values[] =		{15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};	static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};	cmdprintk("program_cycle_times parameters: total=%d, active=%d\n",		  cycle_time, active_time);	cycle_count	= quantize_timing( cycle_time, clock_time);	active_count	= quantize_timing(active_time, clock_time);	recovery_count	= cycle_count - active_count;	/*	 * In case we've got too long recovery phase, try to lengthen	 * the active phase	 */	if (recovery_count > 16) {		active_count += recovery_count - 16;		recovery_count = 16;	}	if (active_count > 16)		/* shouldn't actually happen... */	 	active_count = 16;	cmdprintk("Final counts: total=%d, active=%d, recovery=%d\n",		  cycle_count, active_count, recovery_count);	/*	 * Convert values to internal chipset representation	 */	recovery_count = recovery_values[recovery_count]; 	active_count  &= 0x0f;	/* Program the active/recovery counts into the DRWTIM register */	drwtim = (active_count << 4) | recovery_count;	(void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim);	cmdprintk("Write 0x%02x to reg 0x%x\n", drwtim, drwtim_regs[drive->dn]);}/* * This routine writes into the chipset registers * PIO setup/active/recovery timings. */static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	unsigned int cycle_time;	u8 setup_count, arttim = 0;	static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};	static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};	cycle_time = ide_pio_cycle_time(drive, pio);	program_cycle_times(drive, cycle_time,			    ide_pio_timings[pio].active_time);	setup_count = quantize_timing(ide_pio_timings[pio].setup_time,				      1000 / system_bus_clock());	/*	 * The primary channel has individual address setup timing registers	 * for each drive and the hardware selects the slowest timing itself.	 * The secondary channel has one common register and we have to select	 * the slowest address setup timing ourselves.	 */	if (hwif->channel) {		ide_drive_t *drives = hwif->drives;		drive->drive_data = setup_count;		setup_count = max(drives[0].drive_data, drives[1].drive_data);	}	if (setup_count > 5)		/* shouldn't actually happen... */		setup_count = 5;	cmdprintk("Final address setup count: %d\n", setup_count);	/*	 * Program the address setup clocks into the ARTTIM registers.	 * Avoid clearing the secondary channel's interrupt bit.	 */	(void) pci_read_config_byte (dev, arttim_regs[drive->dn], &arttim);	if (hwif->channel)		arttim &= ~ARTTIM23_INTR_CH1;	arttim &= ~0xc0;	arttim |= setup_values[setup_count];	(void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);	cmdprintk("Write 0x%02x to reg 0x%x\n", arttim, arttim_regs[drive->dn]);}/* * Attempts to set drive's PIO mode. * Special cases are 8: prefetch off, 9: prefetch on (both never worked) */static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio){	/*	 * Filter out the prefetch control values	 * to prevent PIO5 from being programmed	 */	if (pio == 8 || pio == 9)		return;	cmd64x_tune_pio(drive, pio);}static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	u8 unit			= drive->dn & 0x01;	u8 regU = 0, pciU	= hwif->channel ? UDIDETCR1 : UDIDETCR0;	if (speed >= XFER_SW_DMA_0) {		(void) pci_read_config_byte(dev, pciU, &regU);		regU &= ~(unit ? 0xCA : 0x35);	}	switch(speed) {	case XFER_UDMA_5:		regU |= unit ? 0x0A : 0x05;		break;	case XFER_UDMA_4:		regU |= unit ? 0x4A : 0x15;		break;	case XFER_UDMA_3:		regU |= unit ? 0x8A : 0x25;		break;	case XFER_UDMA_2:		regU |= unit ? 0x42 : 0x11;		break;	case XFER_UDMA_1:		regU |= unit ? 0x82 : 0x21;		break;	case XFER_UDMA_0:		regU |= unit ? 0xC2 : 0x31;		break;	case XFER_MW_DMA_2:		program_cycle_times(drive, 120, 70);		break;

⌨️ 快捷键说明

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