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

📄 ide.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  linux/drivers/ide/ide.c		Version 7.00beta2	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 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. * * ... * *  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 */#define	REVISION	"Revision: 7.00alpha2"#define	VERSION		"Id: ide.c 7.00a2 20020906"#define _IDE_C			/* Tell ide.h it's really us */#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/completion.h>#include <linux/reboot.h>#include <linux/cdrom.h>#include <linux/seq_file.h>#include <linux/device.h>#include <linux/bitops.h>#include <asm/byteorder.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.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 */DEFINE_MUTEX(ide_cfg_mtx); __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);#ifdef CONFIG_IDEPCI_PCIBUS_ORDERstatic int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */#endifint noautodma = 0;#ifdef CONFIG_BLK_DEV_IDEACPIint ide_noacpi = 0;int ide_noacpitfs = 1;int ide_noacpionboot = 1;#endif/* * 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);/* * Do not even *think* about calling this! */static void init_hwif_data(ide_hwif_t *hwif, unsigned int index){	unsigned int unit;	/* 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->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;	init_completion(&hwif->gendev_rel_comp);	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->vdma			= 0;		INIT_LIST_HEAD(&drive->list);		init_completion(&drive->gendev_rel_comp);	}}static void init_hwif_default(ide_hwif_t *hwif, unsigned int index){	hw_regs_t hw;	memset(&hw, 0, sizeof(hw_regs_t));	ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);	memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));	hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];#ifdef CONFIG_BLK_DEV_HD	if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)		hwif->noprobe = 1;	/* may be overridden by ide_setup() */#endif}extern void ide_arm_init(void);/* * 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){	ide_hwif_t *hwif;	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) {		hwif = &ide_hwifs[index];		init_hwif_data(hwif, index);		init_hwif_default(hwif, index);#if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI)		hwif->irq =			ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);#endif	}#ifdef CONFIG_IDE_ARM	ide_arm_init();#endif}/** *	ide_system_bus_speed	-	guess bus speed * *	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. Drivers should only use this as a last resort. * *	Returns a guessed speed in MHz. */static int ide_system_bus_speed(void){#ifdef CONFIG_PCI	static struct pci_device_id pci_default[] = {		{ PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID) },		{ }	};#else#define pci_default 0#endif /* CONFIG_PCI */	if (!system_bus_speed) {		if (idebus_parameter) {			/* user supplied value */			system_bus_speed = idebus_parameter;		} else if (pci_dev_present(pci_default)) {			/* 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;}ide_hwif_t * ide_find_port(unsigned long base){	ide_hwif_t *hwif;	int i;	for (i = 0; i < MAX_HWIFS; i++) {		hwif = &ide_hwifs[i];		if (hwif->io_ports[IDE_DATA_OFFSET] == base)			goto found;	}	for (i = 0; i < MAX_HWIFS; i++) {		hwif = &ide_hwifs[i];		if (hwif->io_ports[IDE_DATA_OFFSET] == 0)			goto found;	}	hwif = NULL;found:	return hwif;}EXPORT_SYMBOL_GPL(ide_find_port);static struct resource* hwif_request_region(ide_hwif_t *hwif,					    unsigned long addr, int num){	struct resource *res = request_region(addr, num, hwif->name);	if (!res)		printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",				hwif->name, addr, addr+num-1);	return res;}/** *	ide_hwif_request_regions - request resources for IDE *	@hwif: interface to use * *	Requests all the needed resources for an interface. *	Right now core IDE code does this work which is deeply wrong. *	MMIO leaves it to the controller driver, *	PIO will migrate this way over time. */int ide_hwif_request_regions(ide_hwif_t *hwif){	unsigned long addr;	unsigned int i;	if (hwif->mmio)		return 0;	addr = hwif->io_ports[IDE_CONTROL_OFFSET];	if (addr && !hwif_request_region(hwif, addr, 1))		goto control_region_busy;	hwif->straight8 = 0;	addr = hwif->io_ports[IDE_DATA_OFFSET];	if ((addr | 7) == hwif->io_ports[IDE_STATUS_OFFSET]) {		if (!hwif_request_region(hwif, addr, 8))			goto data_region_busy;		hwif->straight8 = 1;		return 0;	}	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {		addr = hwif->io_ports[i];		if (!hwif_request_region(hwif, addr, 1)) {			while (--i)				release_region(addr, 1);			goto data_region_busy;		}	}	return 0;data_region_busy:	addr = hwif->io_ports[IDE_CONTROL_OFFSET];	if (addr)		release_region(addr, 1);control_region_busy:	/* If any errors are return, we drop the hwif interface. */	return -EBUSY;}/** *	ide_hwif_release_regions - free IDE resources * *	Note that we only release the standard ports, *	and do not even try to handle any extra ports *	allocated for weird IDE interface chipsets. * *	Note also that we don't yet handle mmio resources here. More *	importantly our caller should be doing this so we need to  *	restructure this as a helper function for drivers. */void ide_hwif_release_regions(ide_hwif_t *hwif){	u32 i = 0;	if (hwif->mmio)		return;	if (hwif->io_ports[IDE_CONTROL_OFFSET])		release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);	if (hwif->straight8) {		release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);		return;	}	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)		if (hwif->io_ports[i])			release_region(hwif->io_ports[i], 1);}/** *	ide_hwif_restore	-	restore hwif to template *	@hwif: hwif to update *	@tmp_hwif: template * *	Restore hwif to a previous state by copying most settings *	from the template. */static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif){	hwif->hwgroup			= tmp_hwif->hwgroup;	hwif->gendev.parent		= tmp_hwif->gendev.parent;	hwif->proc			= tmp_hwif->proc;	hwif->major			= tmp_hwif->major;	hwif->straight8			= tmp_hwif->straight8;	hwif->bus_state			= tmp_hwif->bus_state;	hwif->host_flags		= tmp_hwif->host_flags;	hwif->pio_mask			= tmp_hwif->pio_mask;	hwif->ultra_mask		= tmp_hwif->ultra_mask;	hwif->mwdma_mask		= tmp_hwif->mwdma_mask;	hwif->swdma_mask		= tmp_hwif->swdma_mask;	hwif->cbl			= tmp_hwif->cbl;	hwif->chipset			= tmp_hwif->chipset;	hwif->hold			= tmp_hwif->hold;#ifdef CONFIG_BLK_DEV_IDEPCI	hwif->pci_dev			= tmp_hwif->pci_dev;	hwif->cds			= tmp_hwif->cds;#endif	hwif->fixup			= tmp_hwif->fixup;	hwif->set_pio_mode		= tmp_hwif->set_pio_mode;	hwif->set_dma_mode		= tmp_hwif->set_dma_mode;	hwif->mdma_filter		= tmp_hwif->mdma_filter;	hwif->udma_filter		= tmp_hwif->udma_filter;	hwif->selectproc		= tmp_hwif->selectproc;	hwif->reset_poll		= tmp_hwif->reset_poll;	hwif->pre_reset			= tmp_hwif->pre_reset;	hwif->resetproc			= tmp_hwif->resetproc;	hwif->intrproc			= tmp_hwif->intrproc;	hwif->maskproc			= tmp_hwif->maskproc;	hwif->quirkproc			= tmp_hwif->quirkproc;	hwif->busproc			= tmp_hwif->busproc;	hwif->ata_input_data		= tmp_hwif->ata_input_data;	hwif->ata_output_data		= tmp_hwif->ata_output_data;	hwif->atapi_input_bytes		= tmp_hwif->atapi_input_bytes;	hwif->atapi_output_bytes	= tmp_hwif->atapi_output_bytes;	hwif->dma_setup			= tmp_hwif->dma_setup;	hwif->dma_exec_cmd		= tmp_hwif->dma_exec_cmd;	hwif->dma_start			= tmp_hwif->dma_start;	hwif->ide_dma_end		= tmp_hwif->ide_dma_end;	hwif->ide_dma_on		= tmp_hwif->ide_dma_on;	hwif->dma_off_quietly		= tmp_hwif->dma_off_quietly;	hwif->ide_dma_test_irq		= tmp_hwif->ide_dma_test_irq;	hwif->ide_dma_clear_irq		= tmp_hwif->ide_dma_clear_irq;	hwif->dma_host_on		= tmp_hwif->dma_host_on;	hwif->dma_host_off		= tmp_hwif->dma_host_off;	hwif->dma_lost_irq		= tmp_hwif->dma_lost_irq;	hwif->dma_timeout		= tmp_hwif->dma_timeout;	hwif->OUTB			= tmp_hwif->OUTB;	hwif->OUTBSYNC			= tmp_hwif->OUTBSYNC;	hwif->OUTW			= tmp_hwif->OUTW;	hwif->OUTSW			= tmp_hwif->OUTSW;	hwif->OUTSL			= tmp_hwif->OUTSL;	hwif->INB			= tmp_hwif->INB;	hwif->INW			= tmp_hwif->INW;	hwif->INSW			= tmp_hwif->INSW;	hwif->INSL			= tmp_hwif->INSL;	hwif->sg_max_nents		= tmp_hwif->sg_max_nents;	hwif->mmio			= tmp_hwif->mmio;	hwif->rqsize			= tmp_hwif->rqsize;

⌨️ 快捷键说明

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