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

📄 ide.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  linux/drivers/ide/ide.c		Version 7.00beta3	Apr 22 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 multiple IDE interface driver, as evolved from hd.c. * It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs *   (usually 14 & 15). * There can be up to two drives per interface, as per the ATA-2 spec. * * Primary:    ide0, port 0x1f0; major=3;  hda is minor=0; hdb is minor=64 * Secondary:  ide1, port 0x170; major=22; hdc is minor=0; hdd is minor=64 * Tertiary:   ide2, port 0x???; major=33; hde is minor=0; hdf is minor=64 * Quaternary: ide3, port 0x???; major=34; hdg is minor=0; hdh is minor=64 * ... * *  From hd.c: *  | *  | It traverses the request-list, using interrupts to jump between functions. *  | As nearly all functions can be called within interrupts, we may not sleep. *  | Special care is recommended.  Have Fun! *  | *  | modified by Drew Eckhardt to check nr of hd's from the CMOS. *  | *  | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug *  | in the early extended-partition checks and added DM partitions. *  | *  | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI). *  | *  | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", *  | and general streamlining by Mark Lord (mlord@pobox.com). * *  October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by: * *	Mark Lord	(mlord@pobox.com)		(IDE Perf.Pkg) *	Delman Lee	(delman@ieee.org)		("Mr. atdisk2") *	Scott Snyder	(snyder@fnald0.fnal.gov)	(ATAPI IDE cd-rom) * *  This was a rewrite of just about everything from hd.c, though some original *  code is still sprinkled about.  Think of it as a major evolution, with *  inspiration from lots of linux users, esp.  hamish@zot.apana.org.au * *  Version 1.0 ALPHA	initial code, primary i/f working okay *  Version 1.3 BETA	dual i/f on shared irq tested & working! *  Version 1.4 BETA	added auto probing for irq(s) *  Version 1.5 BETA	added ALPHA (untested) support for IDE cd-roms, *  ... * Version 5.50		allow values as small as 20 for idebus= * Version 5.51		force non io_32bit in drive_cmd_intr() *			change delay_10ms() to delay_50ms() to fix problems * Version 5.52		fix incorrect invalidation of removable devices *			add "hdx=slow" command line option * Version 5.60		start to modularize the driver; the disk and ATAPI *			 drivers can be compiled as loadable modules. *			move IDE probe code to ide-probe.c *			move IDE disk code to ide-disk.c *			add support for generic IDE device subdrivers *			add m68k code from Geert Uytterhoeven *			probe all interfaces by default *			add ioctl to (re)probe an interface * Version 6.00		use per device request queues *			attempt to optimize shared hwgroup performance *			add ioctl to manually adjust bandwidth algorithms *			add kerneld support for the probe module *			fix bug in ide_error() *			fix bug in the first ide_get_lock() call for Atari *			don't flush leftover data for ATAPI devices * Version 6.01		clear hwgroup->active while the hwgroup sleeps *			support HDIO_GETGEO for floppies * Version 6.02		fix ide_ack_intr() call *			check partition table on floppies * Version 6.03		handle bad status bit sequencing in ide_wait_stat() * Version 6.10		deleted old entries from this list of updates *			replaced triton.c with ide-dma.c generic PCI DMA *			added support for BIOS-enabled UltraDMA *			rename all "promise" things to "pdc4030" *			fix EZ-DRIVE handling on small disks * Version 6.11		fix probe error in ide_scan_devices() *			fix ancient "jiffies" polling bugs *			mask all hwgroup interrupts on each irq entry * Version 6.12		integrate ioctl and proc interfaces *			fix parsing of "idex=" command line parameter * Version 6.13		add support for ide4/ide5 courtesy rjones@orchestream.com * Version 6.14		fixed IRQ sharing among PCI devices * Version 6.15		added SMP awareness to IDE drivers * Version 6.16		fixed various bugs; even more SMP friendly * Version 6.17		fix for newest EZ-Drive problem * Version 6.18		default unpartitioned-disk translation now "BIOS LBA" * Version 6.19		Re-design for a UNIFORM driver for all platforms, *			  model based on suggestions from Russell King and *			  Geert Uytterhoeven *			Promise DC4030VL now supported. *			add support for ide6/ide7 *			delay_50ms() changed to ide_delay_50ms() and exported. * Version 6.20		Added/Fixed Generic ATA-66 support and hwif detection. *			Added hdx=flash to allow for second flash disk *			  detection w/o the hang loop. *			Added support for ide8/ide9 *			Added idex=ata66 for the quirky chipsets that are *			  ATA-66 compliant, but have yet to determine a method *			  of verification of the 80c cable presence. *			  Specifically Promise's PDC20262 chipset. * Version 6.21		Fixing/Fixed SMP spinlock issue with insight from an old *			  hat that clarified original low level driver design. * Version 6.30		Added SMP support; fixed multmode issues.  -ml * Version 6.31		Debug Share INTR's and request queue streaming *			Native ATA-100 support *			Prep for Cascades Project * Version 7.00alpha	First named revision of ide rearrange * Version 7.00beta	(2.4 backport) * *  Some additional driver compile-time options are in ./include/linux/ide.h * */#define	REVISION	"Revision: 7.00beta4-2.4"#define	VERSION		"Id: ide.c 7.00b4 20030520"#undef REALLY_SLOW_IO		/* most systems can safely undef this */#define _IDE_C			/* Tell ide.h it's really us */#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/blkpg.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/delay.h>#include <linux/ide.h>#include <linux/devfs_fs_kernel.h>#include <linux/completion.h>#include <linux/reboot.h>#include <asm/byteorder.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/bitops.h>#include "ide_modes.h"#include <linux/kmod.h>/* default maximum number of failures */#define IDE_DEFAULT_MAX_FAILURES 	1static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,					IDE2_MAJOR, IDE3_MAJOR,					IDE4_MAJOR, IDE5_MAJOR,					IDE6_MAJOR, IDE7_MAJOR,					IDE8_MAJOR, IDE9_MAJOR };static int idebus_parameter;	/* holds the "idebus=" parameter */static int system_bus_speed;	/* holds what we think is VESA/PCI bus speed */static int initializing;	/* set while initializing built-in drivers */static int ide_scan_direction;	/* THIS was formerly 2.2.x pci=reverse */#ifdef CONFIG_IDEDMA_AUTOint noautodma = 0;#elseint noautodma = 1;#endifEXPORT_SYMBOL(noautodma);/* * ide_modules keeps track of the available IDE chipset/probe/driver modules. */ide_module_t *ide_chipsets;ide_module_t *ide_modules;ide_module_t *ide_probe;/* * This is declared extern in ide.h, for access by other IDE modules: */ide_hwif_t ide_hwifs[MAX_HWIFS];	/* master data repository */EXPORT_SYMBOL(ide_hwifs);ide_devices_t *idedisk;ide_devices_t *idecd;ide_devices_t *idefloppy;ide_devices_t *idetape;ide_devices_t *idescsi;EXPORT_SYMBOL(idedisk);EXPORT_SYMBOL(idecd);EXPORT_SYMBOL(idefloppy);EXPORT_SYMBOL(idetape);EXPORT_SYMBOL(idescsi);extern ide_driver_t idedefault_driver;static void setup_driver_defaults (ide_drive_t *drive);/* * Do not even *think* about calling this! */static void init_hwif_data (unsigned int index){	unsigned int unit;	ide_hwif_t *hwif = &ide_hwifs[index];	/* bulk initialize hwif & drive info with zeros */	memset(hwif, 0, sizeof(ide_hwif_t));	/* fill in any non-zero initial values */	hwif->index     = index;	hwif->noprobe	= 1;	hwif->major	= ide_hwif_to_major[index];	hwif->name[0]	= 'i';	hwif->name[1]	= 'd';	hwif->name[2]	= 'e';	hwif->name[3]	= '0' + index;	hwif->bus_state = BUSSTATE_ON;	hwif->reset_poll= NULL;	hwif->pre_reset = NULL;	hwif->atapi_dma = 0;		/* disable all atapi dma */ 	hwif->ultra_mask = 0x80;	/* disable all ultra */	hwif->mwdma_mask = 0x80;	/* disable all mwdma */	hwif->swdma_mask = 0x80;	/* disable all swdma */	default_hwif_iops(hwif);	default_hwif_transport(hwif);	for (unit = 0; unit < MAX_DRIVES; ++unit) {		ide_drive_t *drive = &hwif->drives[unit];		drive->media			= ide_disk;		drive->select.all		= (unit<<4)|0xa0;		drive->hwif			= hwif;		drive->ctl			= 0x08;		drive->ready_stat		= READY_STAT;		drive->bad_wstat		= BAD_W_STAT;		drive->special.b.recalibrate	= 1;		drive->special.b.set_geometry	= 1;		drive->name[0]			= 'h';		drive->name[1]			= 'd';		drive->name[2]			= 'a' + (index * MAX_DRIVES) + unit;		drive->max_failures		= IDE_DEFAULT_MAX_FAILURES;		drive->using_dma		= 0;		drive->is_flash			= 0;		drive->driver			= &idedefault_driver;		setup_driver_defaults(drive);		init_waitqueue_head(&drive->wqueue);	}}/* * Old compatability function - initialise ports using ide_default_io_base */static void ide_old_init_default_hwifs(void){	unsigned int index;	ide_ioreg_t base;	ide_hwif_t *hwif;	for (index = 0; index < MAX_HWIFS; index++) {		hwif = &ide_hwifs[index];		base = ide_default_io_base(index);		if (base) {			ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->hw.irq);			memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));			hwif->noprobe = 0;		}	}}/* * init_ide_data() sets reasonable default values into all fields * of all instances of the hwifs and drives, but only on the first call. * Subsequent calls have no effect (they don't wipe out anything). * * This routine is normally called at driver initialization time, * but may also be called MUCH earlier during kernel "command-line" * parameter processing.  As such, we cannot depend on any other parts * of the kernel (such as memory allocation) to be functioning yet. * * This is too bad, as otherwise we could dynamically allocate the * ide_drive_t structs as needed, rather than always consuming memory * for the max possible number (MAX_HWIFS * MAX_DRIVES) of them. * * FIXME: We should stuff the setup data into __init and copy the * relevant hwifs/allocate them properly during boot. */#define MAGIC_COOKIE 0x12345678static void __init init_ide_data (void){	unsigned int index;	static unsigned long magic_cookie = MAGIC_COOKIE;	if (magic_cookie != MAGIC_COOKIE)		return;		/* already initialized */	magic_cookie = 0;	/* Initialise all interface structures */	for (index = 0; index < MAX_HWIFS; ++index)		init_hwif_data(index);	/* Add default hw interfaces */	ide_old_init_default_hwifs();	ide_init_default_hwifs();	idebus_parameter = 0;	system_bus_speed = 0;}/* * ide_system_bus_speed() returns what we think is the system VESA/PCI * bus speed (in MHz).  This is used for calculating interface PIO timings. * The default is 40 for known PCI systems, 50 otherwise. * The "idebus=xx" parameter can be used to override this value. * The actual value to be used is computed/displayed the first time through. */int ide_system_bus_speed (void){	if (!system_bus_speed) {		if (idebus_parameter) {			/* user supplied value */			system_bus_speed = idebus_parameter;		} else if (pci_present()) {			/* safe default value for PCI */			system_bus_speed = 33;		} else {			/* safe default value for VESA and PCI */			system_bus_speed = 50;		}		printk(KERN_INFO "ide: Assuming %dMHz system bus speed "			"for PIO modes%s\n", system_bus_speed,			idebus_parameter ? "" : "; override with idebus=xx");	}	return system_bus_speed;}/* * current_capacity() returns the capacity (in sectors) of a drive * according to its current geometry/LBA settings. */unsigned long current_capacity (ide_drive_t *drive){	if (!drive->present)		return 0;	return DRIVER(drive)->capacity(drive);}EXPORT_SYMBOL(current_capacity);static inline u32 read_24 (ide_drive_t *drive){	return  (HWIF(drive)->INB(IDE_HCYL_REG)<<16) |		(HWIF(drive)->INB(IDE_LCYL_REG)<<8) |		 HWIF(drive)->INB(IDE_SECTOR_REG);}/* * Error reporting, in human readable form (luxurious, but a memory hog). */u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat){	ide_hwif_t *hwif = HWIF(drive);	unsigned long flags;	u8 err = 0;	local_irq_set(flags);	printk(KERN_WARNING "%s: %s: status=0x%02x", drive->name, msg, stat);#if FANCY_STATUS_DUMPS	printk(" { ");	if (stat & BUSY_STAT) {		printk("Busy ");	} else {		if (stat & READY_STAT)	printk("DriveReady ");		if (stat & WRERR_STAT)	printk("DeviceFault ");		if (stat & SEEK_STAT)	printk("SeekComplete ");		if (stat & DRQ_STAT)	printk("DataRequest ");		if (stat & ECC_STAT)	printk("CorrectedError ");		if (stat & INDEX_STAT)	printk("Index ");		if (stat & ERR_STAT)	printk("Error ");	}	printk("}");#endif	/* FANCY_STATUS_DUMPS */	printk("\n");	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {		err = hwif->INB(IDE_ERROR_REG);		printk("%s: %s: error=0x%02x", drive->name, msg, err);#if FANCY_STATUS_DUMPS		if (drive->media == ide_disk) {			printk(" { ");			if (err & ABRT_ERR)	printk("DriveStatusError ");			if (err & ICRC_ERR)	printk("Bad%s ", (err & ABRT_ERR) ? "CRC" : "Sector");			if (err & ECC_ERR)	printk("UncorrectableError ");			if (err & ID_ERR)	printk("SectorIdNotFound ");			if (err & TRK0_ERR)	printk("TrackZeroNotFound ");			if (err & MARK_ERR)	printk("AddrMarkNotFound ");			printk("}");			if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) {				if ((drive->id->command_set_2 & 0x0400) &&				    (drive->id->cfs_enable_2 & 0x0400) &&				    (drive->addressing == 1)) {					u64 sectors = 0;					u32 high = 0;					u32 low = read_24(drive);					hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);					high = read_24(drive);					sectors = ((u64)high << 24) | low;					printk(", LBAsect=%llu, high=%d, low=%d",					       (u64) sectors,					       high, low);				} else {					u8 cur = hwif->INB(IDE_SELECT_REG);					if (cur & 0x40) {	/* using LBA? */						printk(", LBAsect=%ld", (unsigned long)						 ((cur&0xf)<<24)						 |(hwif->INB(IDE_HCYL_REG)<<16)						 |(hwif->INB(IDE_LCYL_REG)<<8)						 | hwif->INB(IDE_SECTOR_REG));					} else {						printk(", CHS=%d/%d/%d",						 (hwif->INB(IDE_HCYL_REG)<<8) +						  hwif->INB(IDE_LCYL_REG),						  cur & 0xf,						  hwif->INB(IDE_SECTOR_REG));					}				}				if (HWGROUP(drive) && HWGROUP(drive)->rq)					printk(", sector=%ld", HWGROUP(drive)->rq->sector);			}		}#endif	/* FANCY_STATUS_DUMPS */		printk("\n");	}	local_irq_restore(flags);	return err;}EXPORT_SYMBOL(ide_dump_status);/* * This routine is called to flush all partitions and partition tables * for a changed disk, and then re-read the new partition table.

⌨️ 快捷键说明

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