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

📄 ide-probe.c

📁 em85xx的大硬盘修正代码包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/drivers/ide/ide-probe.c	Version 1.07	March 18, 2001 * *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below) *//* *  Mostly written by Mark Lord <mlord@pobox.com> *                and Gadi Oxman <gadio@netvision.net.il> *                and Andre Hedrick <andre@linux-ide.org> * *  See linux/MAINTAINERS for address of current maintainer. * * This is the IDE probe module, as evolved from hd.c and ide.c. * * Version 1.00		move drive probing code from ide.c to ide-probe.c * Version 1.01		fix compilation problem for m68k * Version 1.02		increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot *			 by Andrea Arcangeli * Version 1.03		fix for (hwif->chipset == ide_4drives) * Version 1.04		fixed buggy treatments of known flash memory cards * * Version 1.05		fix for (hwif->chipset == ide_pdc4030) *			added ide6/7/8/9 *			allowed for secondary flash card to be detectable *			 with new flag : drive->ata_flash : 1; * Version 1.06		stream line request queue and prep for cascade project. * Version 1.07		max_sect <= 255; slower disks would get behind and * 			then fall over when they get to 256.	Paul G. */#undef REALLY_SLOW_IO		/* most systems can safely undef this */#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/major.h>#include <linux/errno.h>#include <linux/genhd.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/ide.h>#include <linux/spinlock.h>#include <asm/byteorder.h>#include <asm/dma.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>static inline void do_identify (ide_drive_t *drive, byte cmd){	int bswap = 1;	struct hd_driveid *id;	id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC);	/* called with interrupts disabled! */	ide_input_data(drive, id, SECTOR_WORDS);		/* read 512 bytes of id info */	ide__sti();	/* local CPU only */	ide_fix_driveid(id);	if (id->word156 == 0x4d42) {		printk("%s: drive->id->word156 == 0x%04x \n", drive->name, drive->id->word156);	}	if (!drive->forced_lun)		drive->last_lun = id->last_lun & 0x7;#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)	/*	 * EATA SCSI controllers do a hardware ATA emulation:	 * Ignore them if there is a driver for them available.	 */	if ((id->model[0] == 'P' && id->model[1] == 'M')	 || (id->model[0] == 'S' && id->model[1] == 'K')) {		printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);		drive->present = 0;		return;	}#endif /* CONFIG_SCSI_EATA_DMA || CONFIG_SCSI_EATA_PIO */	/*	 *  WIN_IDENTIFY returns little-endian info,	 *  WIN_PIDENTIFY *usually* returns little-endian info.	 */	if (cmd == WIN_PIDENTIFY) {		if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */		 || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */		 || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */			bswap ^= 1;	/* Vertos drives may still be weird */	}	ide_fixstring (id->model,     sizeof(id->model),     bswap);	ide_fixstring (id->fw_rev,    sizeof(id->fw_rev),    bswap);	ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap);	if (strstr(id->model, "E X A B Y T E N E S T"))		return;	id->model[sizeof(id->model)-1] = '\0';	/* we depend on this a lot! */	printk("%s: %s, ", drive->name, id->model);	drive->present = 1;	/*	 * Check for an ATAPI device	 */	if (cmd == WIN_PIDENTIFY) {		byte type = (id->config >> 8) & 0x1f;		printk("ATAPI ");#ifdef CONFIG_BLK_DEV_PDC4030		if (HWIF(drive)->channel == 1 && HWIF(drive)->chipset == ide_pdc4030) {			printk(" -- not supported on 2nd Promise port\n");			drive->present = 0;			return;		}#endif /* CONFIG_BLK_DEV_PDC4030 */		switch (type) {			case ide_floppy:				if (!strstr(id->model, "CD-ROM")) {					if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP"))						printk("cdrom or floppy?, assuming ");					if (drive->media != ide_cdrom) {						printk ("FLOPPY");						break;					}				}				type = ide_cdrom;	/* Early cdrom models used zero */			case ide_cdrom:				drive->removable = 1;#ifdef CONFIG_PPC				/* kludge for Apple PowerBook internal zip */				if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) {					printk ("FLOPPY");					type = ide_floppy;					break;				}#endif				printk ("CD/DVD-ROM");				break;			case ide_tape:				printk ("TAPE");				break;			case ide_optical:				printk ("OPTICAL");				drive->removable = 1;				break;			default:				printk("UNKNOWN (type %d)", type);				break;		}		printk (" drive\n");		drive->media = type;		return;	}	/*	 * Not an ATAPI device: looks like a "regular" hard disk	 */	if (id->config & (1<<7))		drive->removable = 1;	/*	 * Prevent long system lockup probing later for non-existant	 * slave drive if the hwif is actually a flash memory card of some variety:	 */	if (drive_is_flashcard(drive)) {		ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit];		if (!mate->ata_flash) {			mate->present = 0;			mate->noprobe = 1;		}	}	drive->media = ide_disk;	printk("ATA DISK drive\n");	QUIRK_LIST(HWIF(drive),drive);	return;}/* * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive * and waits for a response.  It also monitors irqs while this is * happening, in hope of automatically determining which one is * being used by the interface. * * Returns:	0  device was identified *		1  device timed-out (no response to identify request) *		2  device aborted the command (refused to identify itself) */static int actual_try_to_identify (ide_drive_t *drive, byte cmd){	int rc;	ide_ioreg_t hd_status;	unsigned long timeout;	byte s, a;//	int i;	if (IDE_CONTROL_REG) {		/* take a deep breath */		ide_delay_50ms();		a = IN_BYTE(IDE_ALTSTATUS_REG);		s = IN_BYTE(IDE_STATUS_REG);		if ((a ^ s) & ~INDEX_STAT) {			printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a);			hd_status = IDE_STATUS_REG;	/* ancient Seagate drives, broken interfaces */		} else {			hd_status = IDE_ALTSTATUS_REG;	/* use non-intrusive polling */		}	} else {		ide_delay_50ms();		hd_status = IDE_STATUS_REG;	}/*	for(i=0; i<10; i++)*/		ide_delay_50ms();	/* set features register for atapi identify command to be sure of reply */	if ((cmd == WIN_PIDENTIFY))		OUT_BYTE(0,IDE_FEATURE_REG);	/* disable dma & overlap *//*	for(i=0; i<10; i++)*/		ide_delay_50ms();#if CONFIG_BLK_DEV_PDC4030	if (HWIF(drive)->chipset == ide_pdc4030) {		/* DC4030 hosted drives need their own identify... */		extern int pdc4030_identify(ide_drive_t *);		if (pdc4030_identify(drive)) {			return 1;		}	} else#endif /* CONFIG_BLK_DEV_PDC4030 */		OUT_BYTE(cmd,IDE_COMMAND_REG);		/* ask drive for ID *///	for(i=0; i<10; i++)		ide_delay_50ms();	timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;	timeout += jiffies;	do {		if (0 < (signed long)(jiffies - timeout)) {			return 1;	/* drive timed-out */		}		ide_delay_50ms();		/* give drive a breather */	} while (IN_BYTE(hd_status) & BUSY_STAT);	ide_delay_50ms();		/* wait for IRQ and DRQ_STAT */	if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {		unsigned long flags;		__save_flags(flags);	/* local CPU only */		__cli();		/* local CPU only; some systems need this */		do_identify(drive, cmd); /* drive returned ID */		rc = 0;			/* drive responded with ID */		(void) GET_STAT();	/* clear drive IRQ */		__restore_flags(flags);	/* local CPU only */	} else		rc = 2;			/* drive refused ID */	return rc;}static int try_to_identify (ide_drive_t *drive, byte cmd){	int retval;	int autoprobe = 0;	unsigned long cookie = 0;	if (IDE_CONTROL_REG && !HWIF(drive)->hw.irq) {		autoprobe = 1;		cookie = probe_irq_on();		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* enable device irq */	}	retval = actual_try_to_identify(drive, cmd);	if (autoprobe) {		int irq;		OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG);	/* mask device irq */		(void) GET_STAT();			/* clear drive IRQ */		udelay(5);		irq = probe_irq_off(cookie);		if (!HWIF(drive)->hw.irq) {			if (irq > 0) {				HWIF(drive)->hw.irq = irq;			} else {	/* Mmmm.. multiple IRQs.. don't know which was ours */				printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie);#ifdef CONFIG_BLK_DEV_CMD640#ifdef CMD640_DUMP_REGS				if (HWIF(drive)->chipset == ide_cmd640) {					printk("%s: Hmmm.. probably a driver problem.\n", drive->name);					CMD640_DUMP_REGS;				}#endif /* CMD640_DUMP_REGS */#endif /* CONFIG_BLK_DEV_CMD640 */			}		}	}	return retval;}/* * do_probe() has the difficult job of finding a drive if it exists, * without getting hung up if it doesn't exist, without trampling on * ethernet cards, and without leaving any IRQs dangling to haunt us later. * * If a drive is "known" to exist (from CMOS or kernel parameters), * but does not respond right away, the probe will "hang in there" * for the maximum wait time (about 30 seconds), otherwise it will * exit much more quickly. * * Returns:	0  device was identified *		1  device timed-out (no response to identify request) *		2  device aborted the command (refused to identify itself) *		3  bad status from device (possible for ATAPI drives) *		4  probe was not attempted because failure was obvious */static int do_probe (ide_drive_t *drive, byte cmd){	int rc;	ide_hwif_t *hwif = HWIF(drive);	if (drive->present) {	/* avoid waiting for inappropriate probes */		if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY))			return 4;	}#ifdef DEBUG	printk("probing for %s: present=%d, media=%d, probetype=%s\n",		drive->name, drive->present, drive->media,		(cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");#endif	ide_delay_50ms();	/* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */	SELECT_DRIVE(hwif,drive);	ide_delay_50ms();#ifdef CONFIG_COLDFIRE	    /*		 *  ColdFire platforms boot up so quick that most hard drives		 *  have not completed there own self tests. Pause here for		 *  a couple of seconds if it looks like there is a drive		 *  present...		 */	    if (IN_BYTE(IDE_SELECT_REG) != drive->select.all) {			printk("IDE: waiting for drives to settle...\n");			for (rc = 0; (rc < 400); rc++) {				SELECT_DRIVE(hwif,drive);				ide_delay_50ms();				if (IN_BYTE(IDE_SELECT_REG) == drive->select.all)					break;			}		}#endif	if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) {		if (drive->select.b.unit != 0) {			SELECT_DRIVE(hwif,&hwif->drives[0]);	/* exit with drive0 selected */			ide_delay_50ms();		/* allow BUSY_STAT to assert & clear */		}		return 3;    /* no i/f present: mmm.. this should be a 4 -ml */	}	if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT)	 || drive->present || cmd == WIN_PIDENTIFY)	{		if ((rc = try_to_identify(drive,cmd)))   /* send cmd and wait */			rc = try_to_identify(drive,cmd); /* failed: try again */		if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) {			unsigned long timeout;			printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT());			ide_delay_50ms();			OUT_BYTE (drive->select.all, IDE_SELECT_REG);			ide_delay_50ms();			OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);			timeout = jiffies;			while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE))				ide_delay_50ms();			rc = try_to_identify(drive, cmd);		}		if (rc == 1)			printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT());		(void) GET_STAT();		/* ensure drive irq is clear */	} else {		rc = 3;				/* not present or maybe ATAPI */	}	if (drive->select.b.unit != 0) {		SELECT_DRIVE(hwif,&hwif->drives[0]);	/* exit with drive0 selected */		ide_delay_50ms();		(void) GET_STAT();		/* ensure drive irq is clear */	}	return rc;}/* * */static void enable_nest (ide_drive_t *drive){	unsigned long timeout;	printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model);	SELECT_DRIVE(HWIF(drive), drive);	ide_delay_50ms();	OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);	timeout = jiffies + WAIT_WORSTCASE;	do {		if (jiffies > timeout) {			printk("failed (timeout)\n");			return;		}		ide_delay_50ms();	} while (GET_STAT() & BUSY_STAT);	ide_delay_50ms();	if (!OK_STAT(GET_STAT(), 0, BAD_STAT))		printk("failed (status = 0x%02x)\n", GET_STAT());	else		printk("success\n");	if (do_probe(drive, WIN_IDENTIFY) >= 2) {	/* if !(success||timed-out) */		(void) do_probe(drive, WIN_PIDENTIFY);	/* look for ATAPI device */	}}/* * probe_for_drive() tests for existence of a given drive using do_probe(). * * Returns:	0  no device was found *		1  device was found (note: drive->present might still be 0) */static inline byte probe_for_drive (ide_drive_t *drive){	if (drive->noprobe)			/* skip probing? */		return drive->present;	if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */		(void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */	}	if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T"))		enable_nest(drive);	if (!drive->present)		return 0;			/* drive not found */	if (drive->id == NULL) {		/* identification failed? */		if (drive->media == ide_disk) {			printk ("%s: non-IDE drive, CHS=%d/%d/%d\n",			 drive->name, drive->cyl, drive->head, drive->sect);		} else if (drive->media == ide_cdrom) {			printk("%s: ATAPI cdrom (?)\n", drive->name);		} else {			drive->present = 0;	/* nuke it */		}	}	return 1;	/* drive was found */}/* * Calculate the region that this interface occupies, * handling interfaces where the registers may not be * ordered sanely.  We deal with the CONTROL register * separately. */static int hwif_check_regions (ide_hwif_t *hwif){	int region_errors = 0;	hwif->straight8 = 0;	region_errors  = ide_check_region(hwif->hw.io_ports[IDE_DATA_OFFSET], 1);	region_errors += ide_check_region(hwif->hw.io_ports[IDE_ERROR_OFFSET], 1);	region_errors += ide_check_region(hwif->hw.io_ports[IDE_NSECTOR_OFFSET], 1);	region_errors += ide_check_region(hwif->hw.io_ports[IDE_SECTOR_OFFSET], 1);	region_errors += ide_check_region(hwif->hw.io_ports[IDE_LCYL_OFFSET], 1);	region_errors += ide_check_region(hwif->hw.io_ports[IDE_HCYL_OFFSET], 1);	region_errors += ide_check_region(hwif->hw.io_ports[IDE_SELECT_OFFSET], 1);	region_errors += ide_check_region(hwif->hw.io_ports[IDE_STATUS_OFFSET], 1);	if (hwif->hw.io_ports[IDE_CONTROL_OFFSET])		region_errors += ide_check_region(hwif->hw.io_ports[IDE_CONTROL_OFFSET], 1);#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)	if (hwif->hw.io_ports[IDE_IRQ_OFFSET])		region_errors += ide_check_region(hwif->hw.io_ports[IDE_IRQ_OFFSET], 1);#endif	/*	 * If any errors are return, we drop the hwif interface.	 */	return(region_errors);}static void hwif_register (ide_hwif_t *hwif){	if (((unsigned long)hwif->hw.io_ports[IDE_DATA_OFFSET] | 7) ==	    ((unsigned long)hwif->hw.io_ports[IDE_STATUS_OFFSET])) {

⌨️ 快捷键说明

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