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

📄 alim15x3.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/drivers/ide/pci/alim15x3.c		Version 0.17	2003/03/05 * *  Copyright (C) 1998-2000 Michel Aubry, Maintainer *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer *  Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer * *  Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) *  May be copied or modified under the terms of the GNU General Public License *  Copyright (C) 2002 Alan Cox <alan@redhat.com> * *  Changes for ALi 156x ported from RH 8.0 driver changes by *			Clear Zang * *  (U)DMA capable version of ali 1533/1543(C), 1535(D) * ********************************************************************** *  9/7/99 --Parts from the above author are included and need to be *  converted into standard interface, once I finish the thought. * *  Recent changes *	Don't use LBA48 mode on ALi <= 0xC4 *	Don't poke 0x79 with a non ALi northbridge *	Don't flip undefined bits on newer chipsets (fix Fujitsu laptop hang) * *  Documentation *	Chipset documentation available under NDA only * */#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.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>#include "ide_modes.h"#include "alim15x3.h"/* *	ALi devices are not plug in. Otherwise these static values would *	need to go. They ought to go away anyway */ static u8 m5229_revision;static u8 chip_is_1543c_e;static struct pci_dev *isa_dev;#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)#include <linux/stat.h>#include <linux/proc_fs.h>static u8 ali_proc = 0;static struct pci_dev *bmide_dev;static char *fifo[4] = {	"FIFO Off",	"FIFO On ",	"DMA mode",	"PIO mode" };static char *udmaT[8] = {	"1.5T",	"  2T",	"2.5T",	"  3T",	"3.5T",	"  4T",	"  6T",	"  8T"};static char *channel_status[8] = {	"OK            ",	"busy          ",	"DRQ           ",	"DRQ busy      ",	"error         ",	"error busy    ",	"error DRQ     ",	"error DRQ busy"};/** *	ali_get_info		-	generate proc file for ALi IDE *	@buffer: buffer to fill *	@addr: address of user start in buffer *	@offset: offset into 'file' *	@count: buffer count * *	Walks the Ali devices and outputs summary data on the tuning and *	anything else that will help with debugging */ static int ali_get_info (char *buffer, char **addr, off_t offset, int count){	unsigned long bibma;	u8 reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1, c0, c1, rev, tmp;	char *q, *p = buffer;	/* fetch rev. */	pci_read_config_byte(bmide_dev, 0x08, &rev);	if (rev >= 0xc1)	/* M1543C or newer */		udmaT[7] = " ???";	else		fifo[3]  = "   ???  ";	/* first fetch bibma: */		bibma = pci_resource_start(bmide_dev, 4);	/*	 * at that point bibma+0x2 et bibma+0xa are byte	 * registers to investigate:	 */	c0 = inb(bibma + 0x02);	c1 = inb(bibma + 0x0a);	p += sprintf(p,		"\n                                Ali M15x3 Chipset.\n");	p += sprintf(p,		"                                ------------------\n");	pci_read_config_byte(bmide_dev, 0x78, &reg53h);	p += sprintf(p, "PCI Clock: %d.\n", reg53h);	pci_read_config_byte(bmide_dev, 0x53, &reg53h);	p += sprintf(p,		"CD_ROM FIFO:%s, CD_ROM DMA:%s\n",		(reg53h & 0x02) ? "Yes" : "No ",		(reg53h & 0x01) ? "Yes" : "No " );	pci_read_config_byte(bmide_dev, 0x74, &reg53h);	p += sprintf(p,		"FIFO Status: contains %d Words, runs%s%s\n\n",		(reg53h & 0x3f),		(reg53h & 0x40) ? " OVERWR" : "",		(reg53h & 0x80) ? " OVERRD." : "." );	p += sprintf(p,		"-------------------primary channel"		"-------------------secondary channel"		"---------\n\n");	pci_read_config_byte(bmide_dev, 0x09, &reg53h);	p += sprintf(p,		"channel status:       %s"		"                               %s\n",		(reg53h & 0x20) ? "On " : "Off",		(reg53h & 0x10) ? "On " : "Off" );	p += sprintf(p,		"both channels togth:  %s"		"                               %s\n",		(c0&0x80) ? "No " : "Yes",		(c1&0x80) ? "No " : "Yes" );	pci_read_config_byte(bmide_dev, 0x76, &reg53h);	p += sprintf(p,		"Channel state:        %s                    %s\n",		channel_status[reg53h & 0x07],		channel_status[(reg53h & 0x70) >> 4] );	pci_read_config_byte(bmide_dev, 0x58, &reg5xh);	pci_read_config_byte(bmide_dev, 0x5c, &reg5yh);	p += sprintf(p,		"Add. Setup Timing:    %dT"		"                                %dT\n",		(reg5xh & 0x07) ? (reg5xh & 0x07) : 8,		(reg5yh & 0x07) ? (reg5yh & 0x07) : 8 );	pci_read_config_byte(bmide_dev, 0x59, &reg5xh);	pci_read_config_byte(bmide_dev, 0x5d, &reg5yh);	p += sprintf(p,		"Command Act. Count:   %dT"		"                                %dT\n"		"Command Rec. Count:   %dT"		"                               %dT\n\n",		(reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,		(reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, 		(reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,		(reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 );	p += sprintf(p,		"----------------drive0-----------drive1"		"------------drive0-----------drive1------\n\n");	p += sprintf(p,		"DMA enabled:      %s              %s"		"               %s              %s\n",		(c0&0x20) ? "Yes" : "No ",		(c0&0x40) ? "Yes" : "No ",		(c1&0x20) ? "Yes" : "No ",		(c1&0x40) ? "Yes" : "No " );	pci_read_config_byte(bmide_dev, 0x54, &reg5xh);	pci_read_config_byte(bmide_dev, 0x55, &reg5yh);	q = "FIFO threshold:   %2d Words         %2d Words"		"          %2d Words         %2d Words\n";	if (rev < 0xc1) {		if ((rev == 0x20) &&		    (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) {			p += sprintf(p, q, 8, 8, 8, 8);		} else {			p += sprintf(p, q,				(reg5xh & 0x03) + 12,				((reg5xh & 0x30)>>4) + 12,				(reg5yh & 0x03) + 12,				((reg5yh & 0x30)>>4) + 12 );		}	} else {		int t1 = (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4;		int t2 = (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4;		int t3 = (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4;		int t4 = (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4;		p += sprintf(p, q, t1, t2, t3, t4);	}#if 0	p += sprintf(p, 		"FIFO threshold:   %2d Words         %2d Words"		"          %2d Words         %2d Words\n",		(reg5xh & 0x03) + 12,		((reg5xh & 0x30)>>4) + 12,		(reg5yh & 0x03) + 12,		((reg5yh & 0x30)>>4) + 12 );#endif	p += sprintf(p,		"FIFO mode:        %s         %s          %s         %s\n",		fifo[((reg5xh & 0x0c) >> 2)],		fifo[((reg5xh & 0xc0) >> 6)],		fifo[((reg5yh & 0x0c) >> 2)],		fifo[((reg5yh & 0xc0) >> 6)] );	pci_read_config_byte(bmide_dev, 0x5a, &reg5xh);	pci_read_config_byte(bmide_dev, 0x5b, &reg5xh1);	pci_read_config_byte(bmide_dev, 0x5e, &reg5yh);	pci_read_config_byte(bmide_dev, 0x5f, &reg5yh1);	p += sprintf(p,/*		"------------------drive0-----------drive1"		"------------drive0-----------drive1------\n")*/		"Dt RW act. Cnt    %2dT              %2dT"		"               %2dT              %2dT\n"		"Dt RW rec. Cnt    %2dT              %2dT"		"               %2dT              %2dT\n\n",		(reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,		(reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8,		(reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,		(reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8,		(reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,		(reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16,		(reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16,		(reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 );	p += sprintf(p,		"-----------------------------------UDMA Timings"		"--------------------------------\n\n");	pci_read_config_byte(bmide_dev, 0x56, &reg5xh);	pci_read_config_byte(bmide_dev, 0x57, &reg5yh);	p += sprintf(p,		"UDMA:             %s               %s"		"                %s               %s\n"		"UDMA timings:     %s             %s"		"              %s             %s\n\n",		(reg5xh & 0x08) ? "OK" : "No",		(reg5xh & 0x80) ? "OK" : "No",		(reg5yh & 0x08) ? "OK" : "No",		(reg5yh & 0x80) ? "OK" : "No",		udmaT[(reg5xh & 0x07)],		udmaT[(reg5xh & 0x70) >> 4],		udmaT[reg5yh & 0x07],		udmaT[(reg5yh & 0x70) >> 4] );	return p-buffer; /* => must be less than 4k! */}#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) *//** *	ali15x3_tune_drive	-	set up a drive *	@drive: drive to tune *	@pio: unused * *	Select the best PIO timing for the drive in question. Then *	program the controller for this drive set up */ static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio){	ide_pio_data_t d;	ide_hwif_t *hwif = HWIF(drive);	struct pci_dev *dev = hwif->pci_dev;	int s_time, a_time, c_time;	u8 s_clc, a_clc, r_clc;	unsigned long flags;	int bus_speed = system_bus_clock();	int port = hwif->channel ? 0x5c : 0x58;	int portFIFO = hwif->channel ? 0x55 : 0x54;	u8 cd_dma_fifo = 0;	int unit = drive->select.b.unit & 1;	pio = ide_get_best_pio_mode(drive, pio, 5, &d);	s_time = ide_pio_timings[pio].setup_time;	a_time = ide_pio_timings[pio].active_time;	if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)		s_clc = 0;	if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)		a_clc = 0;	c_time = ide_pio_timings[pio].cycle_time;#if 0	if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16)		r_clc = 0;#endif	if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {		r_clc = 1;	} else {		if (r_clc >= 16)			r_clc = 0;	}	local_irq_save(flags);		/* 	 * PIO mode => ATA FIFO on, ATAPI FIFO off	 */	pci_read_config_byte(dev, portFIFO, &cd_dma_fifo);	if (drive->media==ide_disk) {		if (unit) {			pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50);		} else {			pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05);		}	} else {		if (unit) {			pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F);		} else {			pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0);		}	}		pci_write_config_byte(dev, port, s_clc);	pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc);	local_irq_restore(flags);	/*	 * setup   active  rec	 * { 70,   165,    365 },   PIO Mode 0	 * { 50,   125,    208 },   PIO Mode 1	 * { 30,   100,    110 },   PIO Mode 2	 * { 30,   80,     70  },   PIO Mode 3 with IORDY	 * { 25,   70,     25  },   PIO Mode 4 with IORDY  ns	 * { 20,   50,     30  }    PIO Mode 5 with IORDY (nonstandard)	 */}/** *	ali15x3_can_ultra	-	check for ultra DMA support *	@drive: drive to do the check * *	Check the drive and controller revisions. Return 0 if UDMA is *	not available, or 1 if UDMA can be used. The actual rules for *	the ALi are *		No UDMA on revisions <= 0xC1 *		Disk only for revisions < 0xC2 *		Not WDC drives for revisions < 0xC2 * *	FIXME: WDC ifdef needs to die */ static u8 ali15x3_can_ultra (ide_drive_t *drive){#ifndef CONFIG_WDC_ALI15X3	struct hd_driveid *id	= drive->id;#endif /* CONFIG_WDC_ALI15X3 */	if (m5229_revision < 0xC1) {	/* According to ALi */		return 0;	} else if ((m5229_revision < 0xC2) &&#ifndef CONFIG_WDC_ALI15X3		   ((chip_is_1543c_e && strstr(id->model, "WDC ")) ||		    (drive->media!=ide_disk))) {#else /* CONFIG_WDC_ALI15X3 */		   (drive->media!=ide_disk)) {#endif /* CONFIG_WDC_ALI15X3 */		return 0;	} else {		return 1;	}}/** *	ali15x3_ratemask	-	generate DMA mode list *	@drive: drive to compute against * *	Generate a list of the available DMA modes for the drive.  *	FIXME: this function contains lots of bogus masking we can dump * *	Return the highest available mode (UDMA33, UDMA66, UDMA100,..) */ static u8 ali15x3_ratemask (ide_drive_t *drive){	u8 mode = 0, can_ultra	= ali15x3_can_ultra(drive);	if (m5229_revision >= 0xC4 && can_ultra) {		mode = 4;	} else if (m5229_revision >= 0xC2 && can_ultra) {		mode = 2;	} else if (can_ultra) {		return 1;	} else {		return 0;	}	/*	 *	If the drive sees no suitable cable then UDMA 33	 *	is the highest permitted mode	 */	 	if (!eighty_ninty_three(drive))		mode = min(mode, (u8)1);	return mode;}/** *	ali15x3_tune_chipset	-	set up chiset for new speed *	@drive: drive to configure for *	@xferspeed: desired speed * *	Configure the hardware for the desired IDE transfer mode. *	We also do the needed drive configuration through helpers */ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	u8 speed		= ide_rate_filter(ali15x3_ratemask(drive), xferspeed);	u8 speed1		= speed;	u8 unit			= (drive->select.b.unit & 0x01);	u8 tmpbyte		= 0x00;	int m5229_udma		= (hwif->channel) ? 0x57 : 0x56;	if (speed == XFER_UDMA_6)	{		speed1 = 0x47;		if(m5229_revision == 0xC4)			speed1 --;	}	if (speed < XFER_UDMA_0) {		u8 ultra_enable	= (unit) ? 0x7f : 0xf7;

⌨️ 快捷键说明

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