|
/* * Mostly written by Mark Lord <[EMAIL PROTECTED]> * and Gadi Oxman <[EMAIL PROTECTED]> * and Andre Hedrick <[EMAIL PROTECTED]> * * 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, [EMAIL PROTECTED], who found a bug * | in the early extended-partition checks and added DM partitions. * | * | Early work on error handling by Mika Liljeberg ([EMAIL PROTECTED]). * | * | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", * | and general streamlining by Mark Lord ([EMAIL PROTECTED]). * * October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by: * * Mark Lord ([EMAIL PROTECTED]) (IDE Perf.Pkg) * Delman Lee ([EMAIL PROTECTED]) ("Mr. atdisk2") * Scott Snyder ([EMAIL PROTECTED]) (ATAPI IDE cd-rom) * /** * ide_unregister - free an IDE interface * @index: index of interface (will change soon to a pointer) * @init_default: init default hwif flag * @restore: restore hwif flag * * Perform the final unregister of an IDE interface. At the moment * we don't refcount interfaces so this will also get split up. * * Locking: * The caller must not hold the IDE locks * The drive present/vanishing is not yet properly locked * Take care with the callbacks. These have been split to avoid * deadlocking the IDE layer. The shutdown callback is called * before we take the lock and free resources. It is up to the * caller to be sure there is no pending I/O here, and that * the interface will not be reopened (present/vanishing locking * isn't yet done BTW). After we commit to the final kill we * call the cleanup callback with the ide locks held. * * Unregister restores the hwif structures to the default state. * This is raving bonkers. */ void ide_unregister(unsigned int index, int init_default, int restore) { ide_drive_t *drive; ide_hwif_t *hwif, *g; static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */ ide_hwgroup_t *hwgroup; int irq_count = 0, unit; BUG_ON(index >= MAX_HWIFS); BUG_ON(in_interrupt()); BUG_ON(irqs_disabled()); mutex_lock(&ide_cfg_mtx); spin_lock_irq(&ide_lock); hwif = &ide_hwifs[index]; if (!hwif->present) goto abort; for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &hwif->drives[unit]; if (!drive->present) continue; spin_unlock_irq(&ide_lock); device_unregister(&drive->gendev); wait_for_completion(&drive->gendev_rel_comp); spin_lock_irq(&ide_lock); } hwif->present = 0; spin_unlock_irq(&ide_lock); ide_proc_unregister_port(hwif); hwgroup = hwif->hwgroup; /* * free the irq if we were the only hwif using it */ g = hwgroup->hwif; do { if (g->irq == hwif->irq) ++irq_count; g = g->next; } while (g != hwgroup->hwif); if (irq_count == 1) free_irq(hwif->irq, hwgroup); ide_remove_port_from_hwgroup(hwif); device_unregister(&hwif->gendev); wait_for_completion(&hwif->gendev_rel_comp); /* * Remove us from the kernel's knowledge */ blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS); kfree(hwif->sg_table); unregister_blkdev(hwif->major, hwif->name); spin_lock_irq(&ide_lock); if (hwif->dma_base) { (void) ide_release_dma(hwif); hwif->dma_base = 0; hwif->dma_command = 0; hwif->dma_vendor1 = 0; hwif->dma_status = 0; hwif->dma_vendor3 = 0; hwif->dma_prdtable = 0; hwif->extra_base = 0; hwif->extra_ports = 0; } ide_hwif_release_regions(hwif); /* copy original settings */ tmp_hwif = *hwif; /* restore hwif data to pristine status */ ide_init_port_data(hwif, index); if (init_default) init_hwif_default(hwif, index); if (restore) ide_hwif_restore(hwif, &tmp_hwif); abort: spin_unlock_irq(&ide_lock); mutex_unlock(&ide_cfg_mtx); } EXPORT_SYMBOL(ide_unregister); |
