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

📄 ide-probe.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	blk_queue_max_phys_segments(q, max_sg_entries);	/* assign drive queue */	drive->queue = q;	/* needs drive->queue to be set */	ide_toggle_bounce(drive, 1);	return 0;}/* * This routine sets up the irq for an ide interface, and creates a new * hwgroup for the irq/hwif if none was previously assigned. * * Much of the code is for correctly detecting/handling irq sharing * and irq serialization situations.  This is somewhat complex because * it handles static as well as dynamic (PCMCIA) IDE interfaces. * * The IRQF_DISABLED in sa_flags means ide_intr() is always entered with * interrupts completely disabled.  This can be bad for interrupt latency, * but anything else has led to problems on some machines.  We re-enable * interrupts as much as we can safely do in most places. */static int init_irq (ide_hwif_t *hwif){	unsigned int index;	ide_hwgroup_t *hwgroup;	ide_hwif_t *match = NULL;	BUG_ON(in_interrupt());	BUG_ON(irqs_disabled());		BUG_ON(hwif == NULL);	mutex_lock(&ide_cfg_mtx);	hwif->hwgroup = NULL;#if MAX_HWIFS > 1	/*	 * Group up with any other hwifs that share our irq(s).	 */	for (index = 0; index < MAX_HWIFS; index++) {		ide_hwif_t *h = &ide_hwifs[index];		if (h->hwgroup) {  /* scan only initialized hwif's */			if (hwif->irq == h->irq) {				hwif->sharing_irq = h->sharing_irq = 1;				if (hwif->chipset != ide_pci ||				    h->chipset != ide_pci) {					save_match(hwif, h, &match);				}			}			if (hwif->serialized) {				if (hwif->mate && hwif->mate->irq == h->irq)					save_match(hwif, h, &match);			}			if (h->serialized) {				if (h->mate && hwif->irq == h->mate->irq)					save_match(hwif, h, &match);			}		}	}#endif /* MAX_HWIFS > 1 */	/*	 * If we are still without a hwgroup, then form a new one	 */	if (match) {		hwgroup = match->hwgroup;		hwif->hwgroup = hwgroup;		/*		 * Link us into the hwgroup.		 * This must be done early, do ensure that unexpected_intr		 * can find the hwif and prevent irq storms.		 * No drives are attached to the new hwif, choose_drive		 * can't do anything stupid (yet).		 * Add ourself as the 2nd entry to the hwgroup->hwif		 * linked list, the first entry is the hwif that owns		 * hwgroup->handler - do not change that.		 */		spin_lock_irq(&ide_lock);		hwif->next = hwgroup->hwif->next;		hwgroup->hwif->next = hwif;		spin_unlock_irq(&ide_lock);	} else {		hwgroup = kmalloc_node(sizeof(ide_hwgroup_t),					GFP_KERNEL | __GFP_ZERO,					hwif_to_node(hwif->drives[0].hwif));		if (!hwgroup)	       		goto out_up;		hwif->hwgroup = hwgroup;		hwgroup->hwif     = hwif->next = hwif;		hwgroup->rq       = NULL;		hwgroup->handler  = NULL;		hwgroup->drive    = NULL;		hwgroup->busy     = 0;		init_timer(&hwgroup->timer);		hwgroup->timer.function = &ide_timer_expiry;		hwgroup->timer.data = (unsigned long) hwgroup;	}	/*	 * Allocate the irq, if not already obtained for another hwif	 */	if (!match || match->irq != hwif->irq) {		int sa = IRQF_DISABLED;#if defined(__mc68000__) || defined(CONFIG_APUS)		sa = IRQF_SHARED;#endif /* __mc68000__ || CONFIG_APUS */		if (IDE_CHIPSET_IS_PCI(hwif->chipset)) {			sa = IRQF_SHARED;#ifndef CONFIG_IDEPCI_SHARE_IRQ			sa |= IRQF_DISABLED;#endif /* CONFIG_IDEPCI_SHARE_IRQ */		}		if (hwif->io_ports[IDE_CONTROL_OFFSET])			/* clear nIEN */			hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]);		if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))	       		goto out_unlink;	}	/*	 * For any present drive:	 * - allocate the block device queue	 * - link drive into the hwgroup	 */	for (index = 0; index < MAX_DRIVES; ++index) {		ide_drive_t *drive = &hwif->drives[index];		if (!drive->present)			continue;		if (ide_init_queue(drive)) {			printk(KERN_ERR "ide: failed to init %s\n",drive->name);			continue;		}		spin_lock_irq(&ide_lock);		if (!hwgroup->drive) {			/* first drive for hwgroup. */			drive->next = drive;			hwgroup->drive = drive;			hwgroup->hwif = HWIF(hwgroup->drive);		} else {			drive->next = hwgroup->drive->next;			hwgroup->drive->next = drive;		}		spin_unlock_irq(&ide_lock);	}#if !defined(__mc68000__) && !defined(CONFIG_APUS)	printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,		hwif->io_ports[IDE_DATA_OFFSET],		hwif->io_ports[IDE_DATA_OFFSET]+7,		hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);#else	printk("%s at 0x%08lx on irq %d", hwif->name,		hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);#endif /* __mc68000__ && CONFIG_APUS */	if (match)		printk(" (%sed with %s)",			hwif->sharing_irq ? "shar" : "serializ", match->name);	printk("\n");	mutex_unlock(&ide_cfg_mtx);	return 0;out_unlink:	spin_lock_irq(&ide_lock);	if (hwif->next == hwif) {		BUG_ON(match);		BUG_ON(hwgroup->hwif != hwif);		kfree(hwgroup);	} else {		ide_hwif_t *g;		g = hwgroup->hwif;		while (g->next != hwif)			g = g->next;		g->next = hwif->next;		if (hwgroup->hwif == hwif) {			/* Impossible. */			printk(KERN_ERR "Duh. Uninitialized hwif listed as active hwif.\n");			hwgroup->hwif = g;		}		BUG_ON(hwgroup->hwif == hwif);	}	spin_unlock_irq(&ide_lock);out_up:	mutex_unlock(&ide_cfg_mtx);	return 1;}static int ata_lock(dev_t dev, void *data){	/* FIXME: we want to pin hwif down */	return 0;}static struct kobject *ata_probe(dev_t dev, int *part, void *data){	ide_hwif_t *hwif = data;	int unit = *part >> PARTN_BITS;	ide_drive_t *drive = &hwif->drives[unit];	if (!drive->present)		return NULL;	if (drive->media == ide_disk)		request_module("ide-disk");	if (drive->scsi)		request_module("ide-scsi");	if (drive->media == ide_cdrom || drive->media == ide_optical)		request_module("ide-cd");	if (drive->media == ide_tape)		request_module("ide-tape");	if (drive->media == ide_floppy)		request_module("ide-floppy");	return NULL;}static struct kobject *exact_match(dev_t dev, int *part, void *data){	struct gendisk *p = data;	*part &= (1 << PARTN_BITS) - 1;	return &p->kobj;}static int exact_lock(dev_t dev, void *data){	struct gendisk *p = data;	if (!get_disk(p))		return -1;	return 0;}void ide_register_region(struct gendisk *disk){	blk_register_region(MKDEV(disk->major, disk->first_minor),			    disk->minors, NULL, exact_match, exact_lock, disk);}EXPORT_SYMBOL_GPL(ide_register_region);void ide_unregister_region(struct gendisk *disk){	blk_unregister_region(MKDEV(disk->major, disk->first_minor),			      disk->minors);}EXPORT_SYMBOL_GPL(ide_unregister_region);void ide_init_disk(struct gendisk *disk, ide_drive_t *drive){	ide_hwif_t *hwif = drive->hwif;	unsigned int unit = (drive->select.all >> 4) & 1;	disk->major = hwif->major;	disk->first_minor = unit << PARTN_BITS;	sprintf(disk->disk_name, "hd%c", 'a' + hwif->index * MAX_DRIVES + unit);	disk->queue = drive->queue;}EXPORT_SYMBOL_GPL(ide_init_disk);static void ide_remove_drive_from_hwgroup(ide_drive_t *drive){	ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;	if (drive == drive->next) {		/* special case: last drive from hwgroup. */		BUG_ON(hwgroup->drive != drive);		hwgroup->drive = NULL;	} else {		ide_drive_t *walk;		walk = hwgroup->drive;		while (walk->next != drive)			walk = walk->next;		walk->next = drive->next;		if (hwgroup->drive == drive) {			hwgroup->drive = drive->next;			hwgroup->hwif = hwgroup->drive->hwif;		}	}	BUG_ON(hwgroup->drive == drive);}static void drive_release_dev (struct device *dev){	ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);	spin_lock_irq(&ide_lock);	ide_remove_drive_from_hwgroup(drive);	kfree(drive->id);	drive->id = NULL;	drive->present = 0;	/* Messed up locking ... */	spin_unlock_irq(&ide_lock);	blk_cleanup_queue(drive->queue);	spin_lock_irq(&ide_lock);	drive->queue = NULL;	spin_unlock_irq(&ide_lock);	complete(&drive->gendev_rel_comp);}/* * init_gendisk() (as opposed to ide_geninit) is called for each major device, * after probing for drives, to allocate partition tables and other data * structures needed for the routines in genhd.c.  ide_geninit() gets called * somewhat later, during the partition check. */static void init_gendisk (ide_hwif_t *hwif){	unsigned int unit;	for (unit = 0; unit < MAX_DRIVES; ++unit) {		ide_drive_t * drive = &hwif->drives[unit];		ide_add_generic_settings(drive);		snprintf(drive->gendev.bus_id,BUS_ID_SIZE,"%u.%u",			 hwif->index,unit);		drive->gendev.parent = &hwif->gendev;		drive->gendev.bus = &ide_bus_type;		drive->gendev.driver_data = drive;		drive->gendev.release = drive_release_dev;	}	blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,			THIS_MODULE, ata_probe, ata_lock, hwif);}static int hwif_init(ide_hwif_t *hwif){	int old_irq;	/* Return success if no device is connected */	if (!hwif->present)		return 1;	if (!hwif->irq) {		if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))		{			printk("%s: DISABLED, NO IRQ\n", hwif->name);			return (hwif->present = 0);		}	}#ifdef CONFIG_BLK_DEV_HD	if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) {		printk("%s: CANNOT SHARE IRQ WITH OLD "			"HARDDISK DRIVER (hd.c)\n", hwif->name);		return (hwif->present = 0);	}#endif /* CONFIG_BLK_DEV_HD */	/* we set it back to 1 if all is ok below */		hwif->present = 0;	if (register_blkdev(hwif->major, hwif->name))		return 0;	if (!hwif->sg_max_nents)		hwif->sg_max_nents = PRD_ENTRIES;	hwif->sg_table = kmalloc(sizeof(struct scatterlist)*hwif->sg_max_nents,				 GFP_KERNEL);	if (!hwif->sg_table) {		printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name);		goto out;	}	sg_init_table(hwif->sg_table, hwif->sg_max_nents);		if (init_irq(hwif) == 0)		goto done;	old_irq = hwif->irq;	/*	 *	It failed to initialise. Find the default IRQ for 	 *	this port and try that.	 */	if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {		printk("%s: Disabled unable to get IRQ %d.\n",			hwif->name, old_irq);		goto out;	}	if (init_irq(hwif)) {		printk("%s: probed IRQ %d and default IRQ %d failed.\n",			hwif->name, old_irq, hwif->irq);		goto out;	}	printk("%s: probed IRQ %d failed, using default.\n",		hwif->name, hwif->irq);done:	init_gendisk(hwif);	ide_acpi_init(hwif);	hwif->present = 1;	/* success */	return 1;out:	unregister_blkdev(hwif->major, hwif->name);	return 0;}static void hwif_register_devices(ide_hwif_t *hwif){	unsigned int i;	for (i = 0; i < MAX_DRIVES; i++) {		ide_drive_t *drive = &hwif->drives[i];		if (drive->present) {			int ret = device_register(&drive->gendev);			if (ret < 0)				printk(KERN_WARNING "IDE: %s: "					"device_register error: %d\n",					__FUNCTION__, ret);		}	}}int ideprobe_init (void){	unsigned int index;	int probe[MAX_HWIFS];	memset(probe, 0, MAX_HWIFS * sizeof(int));	for (index = 0; index < MAX_HWIFS; ++index)		probe[index] = !ide_hwifs[index].present;	for (index = 0; index < MAX_HWIFS; ++index)		if (probe[index])			probe_hwif(&ide_hwifs[index]);	for (index = 0; index < MAX_HWIFS; ++index)		if (probe[index])			hwif_init(&ide_hwifs[index]);	for (index = 0; index < MAX_HWIFS; ++index) {		if (probe[index]) {			ide_hwif_t *hwif = &ide_hwifs[index];			if (!hwif->present)				continue;			if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced)				hwif->chipset = ide_generic;			hwif_register_devices(hwif);		}	}	for (index = 0; index < MAX_HWIFS; ++index)		if (probe[index])			ide_proc_register_port(&ide_hwifs[index]);	return 0;}EXPORT_SYMBOL_GPL(ideprobe_init);int ide_device_add(u8 idx[4]){	int i, rc = 0;	for (i = 0; i < 4; i++) {		if (idx[i] != 0xff)			rc |= probe_hwif_init(&ide_hwifs[idx[i]]);	}	for (i = 0; i < 4; i++) {		if (idx[i] != 0xff)			ide_proc_register_port(&ide_hwifs[idx[i]]);	}	return rc;}EXPORT_SYMBOL_GPL(ide_device_add);

⌨️ 快捷键说明

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