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

📄 ide-probe.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/drivers/ide/ide-probe.c	Version 1.11	Mar 05, 2003 * *  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. * Version 1.10		Update set for new IDE. drive->id is now always *			valid after probe time even with noprobe */#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 <linux/pci.h>#include <linux/kmod.h>#include <asm/byteorder.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>/** *	generic_id		-	add a generic drive id *	@drive:	drive to make an ID block for *	 *	Add a fake id field to the drive we are passed. This allows *	use to skip a ton of NULL checks (which people always miss)  *	and make drive properties unconditional outside of this file */ static void generic_id(ide_drive_t *drive){	drive->id->cyls = drive->cyl;	drive->id->heads = drive->head;	drive->id->sectors = drive->sect;	drive->id->cur_cyls = drive->cyl;	drive->id->cur_heads = drive->head;	drive->id->cur_sectors = drive->sect;}		/** *	drive_is_flashcard	-	check for compact flash *	@drive: drive to check * *	CompactFlash cards and their brethern pretend to be removable *	hard disks, except: * 		(1) they never have a slave unit, and *		(2) they don't have doorlock mechanisms. *	This test catches them, and is invoked elsewhere when setting *	appropriate config bits. * *	FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) *	devices, so in linux 2.3.x we should change this to just treat all *	PCMCIA  drives this way, and get rid of the model-name tests below *	(too big of an interface change for 2.4.x). *	At that time, we might also consider parameterizing the timeouts and *	retries, since these are MUCH faster than mechanical drives. -M.Lord */ static inline int drive_is_flashcard (ide_drive_t *drive){	struct hd_driveid *id = drive->id;	if (drive->removable && id != NULL) {		if (id->config == 0x848a) return 1;	/* CompactFlash */		if (!strncmp(id->model, "KODAK ATA_FLASH", 15)	/* Kodak */		 || !strncmp(id->model, "Hitachi CV", 10)	/* Hitachi */		 || !strncmp(id->model, "SunDisk SDCFB", 13)	/* SunDisk */		 || !strncmp(id->model, "HAGIWARA HPC", 12)	/* Hagiwara */		 || !strncmp(id->model, "LEXAR ATA_FLASH", 15)	/* Lexar */		 || !strncmp(id->model, "ATA_FLASH", 9))	/* Simple Tech */		{			return 1;	/* yes, it is a flash memory card */		}	}	return 0;	/* no, it is not a flash memory card */}/** *	do_identify	-	identify a drive *	@drive: drive to identify  *	@cmd: command used * *	Called when we have issued a drive identify command to *	read and parse the results. This function is run with *	interrupts disabled.  */ static inline void do_identify (ide_drive_t *drive, u8 cmd){	ide_hwif_t *hwif = HWIF(drive);	int bswap = 1;	struct hd_driveid *id;	/* called with interrupts disabled! */	id = drive->id;	/* read 512 bytes of id info */	hwif->ata_input_data(drive, id, SECTOR_WORDS);	drive->id_read = 1;	local_irq_enable();		ide_fix_driveid(id);	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);		goto err_misc;	}#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 */			/* Vertos drives may still be weird */			bswap ^= 1;		}	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"))		goto err_misc;	/* we depend on this a lot! */	id->model[sizeof(id->model)-1] = '\0';	printk("%s: %s, ", drive->name, id->model);	drive->present = 1;	drive->dead = 0;	/*	 * Check for an ATAPI device	 */	if (cmd == WIN_PIDENTIFY) {		u8 type = (id->config >> 8) & 0x1f;		printk("ATAPI ");#ifdef CONFIG_BLK_DEV_PDC4030		if (hwif->channel == 1 && hwif->chipset == ide_pdc4030) {			printk(" -- not supported on 2nd Promise port\n");			goto err_misc;		}#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");						drive->removable = 1;						break;					}				}				/* Early cdrom models used zero */				type = ide_cdrom;			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:	 */	drive->is_flash = 0;	if (drive_is_flashcard(drive)) {#if 0		/* The new IDE adapter widgets don't follow this heuristic		   so we must nowdays just bite the bullet and take the		   probe hit */			ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit];				if (!mate->ata_flash) {			mate->present = 0;			mate->noprobe = 1;		}#endif				drive->is_flash = 1;	}	drive->media = ide_disk;	printk("%s DISK drive\n", (drive->is_flash) ? "CFA" : "ATA" );	QUIRK_LIST(drive);	return;err_misc:	kfree(id);	drive->present = 0;	return;}/** *	actual_try_to_identify	-	send ata/atapi identify *	@drive: drive to identify *	@cmd: comamnd to use * *	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, u8 cmd){	ide_hwif_t *hwif = HWIF(drive);	int rc;	ide_ioreg_t hd_status;	unsigned long timeout;	u8 s = 0, a = 0;	if (IDE_CONTROL_REG) {		/* take a deep breath */		ide_delay_50ms();		a = hwif->INB(IDE_ALTSTATUS_REG);		s = hwif->INB(IDE_STATUS_REG);		if ((a ^ s) & ~INDEX_STAT) {			printk(KERN_INFO "%s: probing with STATUS(0x%02x) instead of "				"ALTSTATUS(0x%02x)\n", drive->name, s, a);			/* ancient Seagate drives, broken interfaces */			hd_status = IDE_STATUS_REG;		} else {			/* use non-intrusive polling */			hd_status = IDE_ALTSTATUS_REG;		}	} else {		ide_delay_50ms();		hd_status = IDE_STATUS_REG;	}	/* set features register for atapi	 * identify command to be sure of reply	 */	if ((cmd == WIN_PIDENTIFY))		/* disable dma & overlap */		hwif->OUTB(0, IDE_FEATURE_REG);	if (hwif->identify != NULL) {		if (hwif->identify(drive))			return 1;	} else {		/* ask drive for ID */		hwif->OUTB(cmd, IDE_COMMAND_REG);	}	timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;	timeout += jiffies;	do {		if (time_after(jiffies, timeout)) {			/* drive timed-out */			return 1;		}		/* give drive a breather */		ide_delay_50ms();	} while ((hwif->INB(hd_status)) & BUSY_STAT);	/* wait for IRQ and DRQ_STAT */	ide_delay_50ms();	if (OK_STAT((hwif->INB(IDE_STATUS_REG)), DRQ_STAT, BAD_R_STAT)) {		unsigned long flags;		/* local CPU only; some systems need this */		local_irq_save(flags);		/* drive returned ID */		do_identify(drive, cmd);		/* drive responded with ID */		rc = 0;		/* clear drive IRQ */		(void) hwif->INB(IDE_STATUS_REG);		local_irq_restore(flags);	} else {		/* drive refused ID */		rc = 2;	}	return rc;}/** *	try_to_identify	-	try to identify a drive *	@drive: drive to probe *	@cmd: comamnd to use * *	Issue the identify command and then do IRQ probing to *	complete the identification when needed by finding the *	IRQ the drive is attached to */ static int try_to_identify (ide_drive_t *drive, u8 cmd){	ide_hwif_t *hwif = HWIF(drive);	int retval;	int autoprobe = 0;	unsigned long cookie = 0;	if (IDE_CONTROL_REG && !hwif->irq) {		autoprobe = 1;		cookie = probe_irq_on();		/* enable device irq */		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);	}	retval = actual_try_to_identify(drive, cmd);	if (autoprobe) {		int irq;		/* mask device irq */		hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);		/* clear drive IRQ */		(void) hwif->INB(IDE_STATUS_REG);		udelay(5);		irq = probe_irq_off(cookie);		if (!hwif->irq) {			if (irq > 0) {				hwif->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->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		-	probe an IDE device *	@drive: drive to probe *	@cmd: command to use * *	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, u8 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	/* needed for some systems	 * (e.g. crw9624 as drive0 with disk as slave)	 */	ide_delay_50ms();	SELECT_DRIVE(drive);	ide_delay_50ms();	if (hwif->INB(IDE_SELECT_REG) != drive->select.all && !drive->present) {		if (drive->select.b.unit != 0) {			/* exit with drive0 selected */			SELECT_DRIVE(&hwif->drives[0]);			/* allow BUSY_STAT to assert & clear */			ide_delay_50ms();		}		/* no i/f present: mmm.. this should be a 4 -ml */		return 3;	}	if (OK_STAT((hwif->INB(IDE_STATUS_REG)), READY_STAT, BUSY_STAT) ||	    drive->present || cmd == WIN_PIDENTIFY) {		/* send cmd and wait */		if ((rc = try_to_identify(drive, cmd))) {			/* failed: try again */			rc = try_to_identify(drive,cmd);		}

⌨️ 快捷键说明

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