-static 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 };
-
-DEFINE_MUTEX(ide_cfg_mtx);
-
-__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
-EXPORT_SYMBOL(ide_lock);
-
-ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
-
-static void ide_port_init_devices_data(ide_hwif_t *);
-
-/*
- * Do not even *think* about calling this!
- */
-void ide_init_port_data(ide_hwif_t *hwif, unsigned int 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->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);
-
- ide_port_init_devices_data(hwif);
-}
-EXPORT_SYMBOL_GPL(ide_init_port_data);
-
-static void ide_port_init_devices_data(ide_hwif_t *hwif)
-{
- int unit;
-
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- u8 j = (hwif->index * MAX_DRIVES) + unit;
-
- memset(drive, 0, sizeof(*drive));
-
- drive->media = ide_disk;
- drive->select.all = (unit<<4)|0xa0;
- drive->hwif = hwif;
- 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' + j;
- drive->max_failures = IDE_DEFAULT_MAX_FAILURES;
-
- INIT_LIST_HEAD(&drive->list);
- init_completion(&drive->gendev_rel_comp);
- }
-}
-
-static void __init init_ide_data (void)
-{
- unsigned int index;
-
- /* Initialise all interface structures */
- for (index = 0; index < MAX_HWIFS; ++index) {
- ide_hwif_t *hwif = &ide_hwifs[index];
-
- ide_init_port_data(hwif, index);
- }
-}
-
-void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
-{
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
-
- spin_lock_irq(&ide_lock);
- /*
- * Remove us from the hwgroup, and free
- * the hwgroup if we were the only member
- */
- if (hwif->next == hwif) {
- BUG_ON(hwgroup->hwif != hwif);
- kfree(hwgroup);
- } else {
- /* There is another interface in hwgroup.
- * Unlink us, and set hwgroup->drive and ->hwif to
- * something sane.
- */
- ide_hwif_t *g = hwgroup->hwif;
-
- while (g->next != hwif)
- g = g->next;
- g->next = hwif->next;
- if (hwgroup->hwif == hwif) {
- /* Chose a random hwif for hwgroup->hwif.
- * It's guaranteed that there are no drives
- * left in the hwgroup.
- */
- BUG_ON(hwgroup->drive != NULL);
- hwgroup->hwif = g;
- }
- BUG_ON(hwgroup->hwif == hwif);
- }
- spin_unlock_irq(&ide_lock);
-}
-
-/* Called with ide_lock held. */
-static void __ide_port_unregister_devices(ide_hwif_t *hwif)
-{
- int i;
-
- for (i = 0; i < MAX_DRIVES; i++) {
- ide_drive_t *drive = &hwif->drives[i];
-
- if (drive->present) {
- spin_unlock_irq(&ide_lock);
- device_unregister(&drive->gendev);
- wait_for_completion(&drive->gendev_rel_comp);
- spin_lock_irq(&ide_lock);
- }
- }
-}
-
-void ide_port_unregister_devices(ide_hwif_t *hwif)
-{
- mutex_lock(&ide_cfg_mtx);
- spin_lock_irq(&ide_lock);
- __ide_port_unregister_devices(hwif);
- hwif->present = 0;
- ide_port_init_devices_data(hwif);
- spin_unlock_irq(&ide_lock);
- mutex_unlock(&ide_cfg_mtx);
-}
-EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
-
-/**
- * ide_unregister - free an IDE interface
- * @hwif: IDE interface
- *
- * 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(ide_hwif_t *hwif)
-{
- ide_hwif_t *g;
- ide_hwgroup_t *hwgroup;
- int irq_count = 0;
-
- BUG_ON(in_interrupt());
- BUG_ON(irqs_disabled());
-
- mutex_lock(&ide_cfg_mtx);
-
- spin_lock_irq(&ide_lock);
- if (hwif->present) {
- __ide_port_unregister_devices(hwif);
- 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->portdev);
- 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);
-
- if (hwif->dma_base)
- ide_release_dma_engine(hwif);
-
- spin_lock_irq(&ide_lock);
- /* restore hwif data to pristine status */
- ide_init_port_data(hwif, hwif->index);
- spin_unlock_irq(&ide_lock);
-
- mutex_unlock(&ide_cfg_mtx);
-}
-
-EXPORT_SYMBOL(ide_unregister);
-
-void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
-{
- memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
- hwif->irq = hw->irq;
- hwif->chipset = hw->chipset;
- hwif->gendev.parent = hw->dev;
- hwif->ack_intr = hw->ack_intr;
-}
-EXPORT_SYMBOL_GPL(ide_init_port_hw);
-