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

📄 pdc4030.c

📁 em85xx的大硬盘修正代码包
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  -*- linux-c -*- *  linux/drivers/ide/pdc4030.c		Version 0.90  May 27, 1999 * *  Copyright (C) 1995-1999  Linus Torvalds & authors (see below) *//* *  Principal Author/Maintainer:  peterd@pnd-pc.demon.co.uk * *  This file provides support for the second port and cache of Promise *  IDE interfaces, e.g. DC4030VL, DC4030VL-1 and DC4030VL-2. * *  Thanks are due to Mark Lord for advice and patiently answering stupid *  questions, and all those mugs^H^H^H^Hbrave souls who've tested this, *  especially Andre Hedrick. * *  Version 0.01	Initial version, #include'd in ide.c rather than *                      compiled separately. *                      Reads use Promise commands, writes as before. Drives *                      on second channel are read-only. *  Version 0.02        Writes working on second channel, reads on both *                      channels. Writes fail under high load. Suspect *			transfers of >127 sectors don't work. *  Version 0.03        Brought into line with ide.c version 5.27. *                      Other minor changes. *  Version 0.04        Updated for ide.c version 5.30 *                      Changed initialization strategy *  Version 0.05	Kernel integration.  -ml *  Version 0.06	Ooops. Add hwgroup to direct call of ide_intr() -ml *  Version 0.07	Added support for DC4030 variants *			Secondary interface autodetection *  Version 0.08	Renamed to pdc4030.c *  Version 0.09	Obsolete - never released - did manual write request *			splitting before max_sectors[major][minor] available. *  Version 0.10	Updated for 2.1 series of kernels *  Version 0.11	Updated for 2.3 series of kernels *			Autodetection code added. * *  Version 0.90	Transition to BETA code. No lost/unexpected interrupts *//* * Once you've compiled it in, you'll have to also enable the interface * setup routine from the kernel command line, as in  * *	'linux ide0=dc4030' or 'linux ide1=dc4030' * * It should now work as a second controller also ('ide1=dc4030') but only * if you DON'T have BIOS V4.44, which has a bug. If you have this version * and EPROM programming facilities, you need to fix 4 bytes: * 	2496:	81	81 *	2497:	3E	3E *	2498:	22	98	* *	2499:	06	05	* *	249A:	F0	F0 *	249B:	01	01 *	... *	24A7:	81	81 *	24A8:	3E	3E *	24A9:	22	98	* *	24AA:	06	05	* *	24AB:	70	70 *	24AC:	01	01 * * As of January 1999, Promise Technology Inc. have finally supplied me with * some technical information which has shed a glimmer of light on some of the * problems I was having, especially with writes.  * * There are still problems with the robustness and efficiency of this driver * because I still don't understand what the card is doing with interrupts. */#define DEBUG_READ#define DEBUG_WRITE#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/ide.h>#include <linux/init.h>#include <asm/io.h>#include <asm/irq.h>#include "pdc4030.h"/* * promise_selectproc() is invoked by ide.c * in preparation for access to the specified drive. */static void promise_selectproc (ide_drive_t *drive){	unsigned int number;	number = (HWIF(drive)->channel << 1) + drive->select.b.unit;	OUT_BYTE(number,IDE_FEATURE_REG);}/* * pdc4030_cmd handles the set of vendor specific commands that are initiated * by command F0. They all have the same success/failure notification - * 'P' (=0x50) on success, 'p' (=0x70) on failure. */int pdc4030_cmd(ide_drive_t *drive, byte cmd){	unsigned long timeout, timer;	byte status_val;	promise_selectproc(drive);	/* redundant? */	OUT_BYTE(0xF3,IDE_SECTOR_REG);	OUT_BYTE(cmd,IDE_SELECT_REG);	OUT_BYTE(PROMISE_EXTENDED_COMMAND,IDE_COMMAND_REG);	timeout = HZ * 10;	timeout += jiffies;	do {		if(time_after(jiffies, timeout)) {			return 2; /* device timed out */		}		/* This is out of delay_10ms() */		/* Delays at least 10ms to give interface a chance */		timer = jiffies + (HZ + 99)/100 + 1;		while (time_after(timer, jiffies));		status_val = IN_BYTE(IDE_SECTOR_REG);	} while (status_val != 0x50 && status_val != 0x70);	if(status_val == 0x50)		return 0; /* device returned success */	else		return 1; /* device returned failure */}/* * pdc4030_identify sends a vendor-specific IDENTIFY command to the drive */int pdc4030_identify(ide_drive_t *drive){	return pdc4030_cmd(drive, PROMISE_IDENTIFY);}int enable_promise_support = 0;void __init init_pdc4030 (void){	enable_promise_support = 1;}/* * setup_pdc4030() * Completes the setup of a Promise DC4030 controller card, once found. */int __init setup_pdc4030 (ide_hwif_t *hwif){        ide_drive_t *drive;	ide_hwif_t *hwif2;	struct dc_ident ident;	int i;	ide_startstop_t startstop;		if (!hwif) return 0;	drive = &hwif->drives[0];	hwif2 = &ide_hwifs[hwif->index+1];	if (hwif->chipset == ide_pdc4030) /* we've already been found ! */		return 1;	if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF) {		return 0;	}	if (IDE_CONTROL_REG)		OUT_BYTE(0x08,IDE_CONTROL_REG);	if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) {		return 0;	}	if (ide_wait_stat(&startstop, drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) {		printk(KERN_INFO			"%s: Failed Promise read config!\n",hwif->name);		return 0;	}	ide_input_data(drive,&ident,SECTOR_WORDS);	if (ident.id[1] != 'P' || ident.id[0] != 'T') {		return 0;	}	printk(KERN_INFO "%s: Promise caching controller, ",hwif->name);	switch(ident.type) {		case 0x43:	printk("DC4030VL-2, "); break;		case 0x41:	printk("DC4030VL-1, "); break;		case 0x40:	printk("DC4030VL, "); break;		default:			printk("unknown - type 0x%02x - please report!\n"			       ,ident.type);			printk("Please e-mail the following data to "			       "promise@pnd-pc.demon.co.uk along with\n"			       "a description of your card and drives:\n");			for (i=0; i < 0x90; i++) {				printk("%02x ", ((unsigned char *)&ident)[i]);				if ((i & 0x0f) == 0x0f) printk("\n");			}			return 0;	}	printk("%dKB cache, ",(int)ident.cache_mem);	switch(ident.irq) {            case 0x00: hwif->irq = 14; break;            case 0x01: hwif->irq = 12; break;            default:   hwif->irq = 15; break;	}	printk("on IRQ %d\n",hwif->irq);	/*	 * Once found and identified, we set up the next hwif in the array	 * (hwif2 = ide_hwifs[hwif->index+1]) with the same io ports, irq	 * and other settings as the main hwif. This gives us two "mated"	 * hwifs pointing to the Promise card.	 *	 * We also have to shift the default values for the remaining	 * interfaces "up by one" to make room for the second interface on the	 * same set of values.	 */	hwif->chipset	= hwif2->chipset = ide_pdc4030;	hwif->mate	= hwif2;	hwif2->mate	= hwif;	hwif2->channel	= 1;	hwif->selectproc = hwif2->selectproc = &promise_selectproc;	hwif->serialized = hwif2->serialized = 1;/* Shift the remaining interfaces down by one */	for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) {		ide_hwif_t *h = &ide_hwifs[i];#ifdef DEBUG		printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i);#endif		ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL);		memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports));		h->noprobe = (h-1)->noprobe;	}	ide_init_hwif_ports(&hwif2->hw, hwif->io_ports[IDE_DATA_OFFSET], 0, NULL);	memcpy(hwif2->io_ports, hwif->hw.io_ports, sizeof(hwif2->io_ports));	hwif2->irq = hwif->irq;	hwif2->hw.irq = hwif->hw.irq = hwif->irq;	for (i=0; i<2 ; i++) {		hwif->drives[i].io_32bit = 3;		hwif2->drives[i].io_32bit = 3;		hwif->drives[i].keep_settings = 1;		hwif2->drives[i].keep_settings = 1;		if (!ident.current_tm[i].cyl)			hwif->drives[i].noprobe = 1;		if (!ident.current_tm[i+2].cyl)			hwif2->drives[i].noprobe = 1;	}        return 1;}/* * detect_pdc4030() * Tests for the presence of a DC4030 Promise card on this interface * Returns: 1 if found, 0 if not found */int __init detect_pdc4030(ide_hwif_t *hwif){	ide_drive_t *drive = &hwif->drives[0];	if (IDE_DATA_REG == 0) { /* Skip test for non-existent interface */		return 0;	}	OUT_BYTE(0xF3, IDE_SECTOR_REG);	OUT_BYTE(0x14, IDE_SELECT_REG);	OUT_BYTE(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG);		ide_delay_50ms();	if (IN_BYTE(IDE_ERROR_REG) == 'P' &&

⌨️ 快捷键说明

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