X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fide%2Fide.c;h=3fdab563fec25f405a7903b8c13002206d47d45e;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=4e2b9934b7a47cd45de96d7ab93a68ed65a53d81;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 4e2b9934b..3fdab563f 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -153,12 +153,12 @@ #include #include #include +#include #include #include #include #include -#include /* default maximum number of failures */ @@ -175,7 +175,7 @@ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ static int initializing; /* set while initializing built-in drivers */ DECLARE_MUTEX(ide_cfg_sem); -spinlock_t ide_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; + __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock); #ifdef CONFIG_BLK_DEV_IDEPCI static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ @@ -188,7 +188,6 @@ int noautodma = 1; #endif EXPORT_SYMBOL(noautodma); -EXPORT_SYMBOL(ide_bus_type); /* * This is declared extern in ide.h, for access by other IDE modules: @@ -197,9 +196,6 @@ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ EXPORT_SYMBOL(ide_hwifs); -extern ide_driver_t idedefault_driver; -static void setup_driver_defaults(ide_driver_t *driver); - /* * Do not even *think* about calling this! */ @@ -226,7 +222,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) hwif->mwdma_mask = 0x80; /* disable all mwdma */ hwif->swdma_mask = 0x80; /* disable all swdma */ - sema_init(&hwif->gendev_rel_sem, 0); + init_completion(&hwif->gendev_rel_comp); default_hwif_iops(hwif); default_hwif_transport(hwif); @@ -246,11 +242,9 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) 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; drive->vdma = 0; INIT_LIST_HEAD(&drive->list); - sema_init(&drive->gendev_rel_sem, 0); + init_completion(&drive->gendev_rel_comp); } } @@ -272,6 +266,8 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index) #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. @@ -300,8 +296,6 @@ static void __init init_ide_data (void) return; /* already initialized */ magic_cookie = 0; - setup_driver_defaults(&idedefault_driver); - /* Initialise all interface structures */ for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; @@ -312,30 +306,42 @@ static void __init init_ide_data (void) ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]); #endif } - -/* OBSOLETE: still needed on arm26 and arm */ -#ifdef CONFIG_ARM - /* Add default hw interfaces */ +#ifdef CONFIG_IDE_ARM initializing = 1; - ide_init_default_hwifs(); + ide_arm_init(); initializing = 0; #endif } -/* - * 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. +/** + * 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. */ -int ide_system_bus_speed (void) + +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_find_device(PCI_ANY_ID, PCI_ANY_ID, NULL) != NULL) { + } else if (pci_dev_present(pci_default)) { /* safe default value for PCI */ system_bus_speed = 33; } else { @@ -349,152 +355,8 @@ int ide_system_bus_speed (void) return system_bus_speed; } -/* - * current_capacity() returns the capacity (in sectors) of a drive - * according to its current geometry/LBA settings. - */ -sector_t current_capacity (ide_drive_t *drive) -{ - if (!drive->present) - return 0; - return DRIVER(drive)->capacity(drive); -} - -EXPORT_SYMBOL(current_capacity); - -/* - * 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 = ide_read_24(drive); - hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); - high = ide_read_24(drive); - - sectors = ((u64)high << 24) | low; - printk(", LBAsect=%llu, high=%d, low=%d", - (long long) 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=%llu", (unsigned long long)HWGROUP(drive)->rq->sector); - } - } -#endif /* FANCY_STATUS_DUMPS */ - printk("\n"); - } - local_irq_restore(flags); - return err; -} - -EXPORT_SYMBOL(ide_dump_status); - -static int ide_open (struct inode * inode, struct file * filp) -{ - return -ENXIO; -} - -static spinlock_t drives_lock = SPIN_LOCK_UNLOCKED; -static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED; -static LIST_HEAD(drivers); - -/* Iterator */ -static void *m_start(struct seq_file *m, loff_t *pos) -{ - struct list_head *p; - loff_t l = *pos; - spin_lock(&drivers_lock); - list_for_each(p, &drivers) - if (!l--) - return list_entry(p, ide_driver_t, drivers); - return NULL; -} -static void *m_next(struct seq_file *m, void *v, loff_t *pos) -{ - struct list_head *p = ((ide_driver_t *)v)->drivers.next; - (*pos)++; - return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers); -} -static void m_stop(struct seq_file *m, void *v) -{ - spin_unlock(&drivers_lock); -} -static int show_driver(struct seq_file *m, void *v) -{ - ide_driver_t *driver = v; - seq_printf(m, "%s version %s\n", driver->name, driver->version); - return 0; -} -struct seq_operations ide_drivers_op = { - .start = m_start, - .next = m_next, - .stop = m_stop, - .show = show_driver -}; - #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_ide_root; - -ide_proc_entry_t generic_subdriver_entries[] = { - { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, - { NULL, 0, NULL, NULL } -}; #endif static struct resource* hwif_request_region(ide_hwif_t *hwif, @@ -517,6 +379,7 @@ static struct resource* hwif_request_region(ide_hwif_t *hwif, * 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; @@ -555,8 +418,6 @@ control_region_busy: return -EBUSY; } -EXPORT_SYMBOL(ide_hwif_request_regions); - /** * ide_hwif_release_regions - free IDE resources * @@ -568,6 +429,7 @@ EXPORT_SYMBOL(ide_hwif_request_regions); * 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; @@ -585,7 +447,109 @@ void ide_hwif_release_regions(ide_hwif_t *hwif) release_region(hwif->io_ports[i], 1); } -EXPORT_SYMBOL(ide_hwif_release_regions); +/** + * ide_hwif_restore - restore hwif to template + * @hwif: hwif to update + * @tmp_hwif: template + * + * Restore hwif to a previous state by copying most settngs + * 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->atapi_dma = tmp_hwif->atapi_dma; + hwif->ultra_mask = tmp_hwif->ultra_mask; + hwif->mwdma_mask = tmp_hwif->mwdma_mask; + hwif->swdma_mask = tmp_hwif->swdma_mask; + + 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->tuneproc = tmp_hwif->tuneproc; + hwif->speedproc = tmp_hwif->speedproc; + 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_check = tmp_hwif->ide_dma_check; + hwif->ide_dma_on = tmp_hwif->ide_dma_on; + hwif->ide_dma_off_quietly = tmp_hwif->ide_dma_off_quietly; + hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq; + hwif->ide_dma_host_on = tmp_hwif->ide_dma_host_on; + hwif->ide_dma_host_off = tmp_hwif->ide_dma_host_off; + hwif->ide_dma_lostirq = tmp_hwif->ide_dma_lostirq; + hwif->ide_dma_timeout = tmp_hwif->ide_dma_timeout; + + hwif->OUTB = tmp_hwif->OUTB; + hwif->OUTBSYNC = tmp_hwif->OUTBSYNC; + hwif->OUTW = tmp_hwif->OUTW; + hwif->OUTL = tmp_hwif->OUTL; + hwif->OUTSW = tmp_hwif->OUTSW; + hwif->OUTSL = tmp_hwif->OUTSL; + + hwif->INB = tmp_hwif->INB; + hwif->INW = tmp_hwif->INW; + hwif->INL = tmp_hwif->INL; + 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; + hwif->no_lba48 = tmp_hwif->no_lba48; + +#ifndef CONFIG_BLK_DEV_IDECS + hwif->irq = tmp_hwif->irq; +#endif + + hwif->dma_base = tmp_hwif->dma_base; + hwif->dma_master = tmp_hwif->dma_master; + hwif->dma_command = tmp_hwif->dma_command; + hwif->dma_vendor1 = tmp_hwif->dma_vendor1; + hwif->dma_status = tmp_hwif->dma_status; + hwif->dma_vendor3 = tmp_hwif->dma_vendor3; + hwif->dma_prdtable = tmp_hwif->dma_prdtable; + + hwif->dma_extra = tmp_hwif->dma_extra; + hwif->config_data = tmp_hwif->config_data; + hwif->select_data = tmp_hwif->select_data; + hwif->autodma = tmp_hwif->autodma; + hwif->udma_four = tmp_hwif->udma_four; + hwif->no_dsc = tmp_hwif->no_dsc; + + hwif->hwif_data = tmp_hwif->hwif_data; +} /** * ide_unregister - free an ide interface @@ -608,18 +572,17 @@ EXPORT_SYMBOL(ide_hwif_release_regions); * Unregister restores the hwif structures to the default state. * This is raving bonkers. */ - -void ide_unregister (unsigned int index) + +void ide_unregister(unsigned int index) { ide_drive_t *drive; ide_hwif_t *hwif, *g; + static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */ ide_hwgroup_t *hwgroup; - int irq_count = 0, unit, i; - ide_hwif_t old_hwif; + int irq_count = 0, unit; + + BUG_ON(index >= MAX_HWIFS); - if (index >= MAX_HWIFS) - BUG(); - BUG_ON(in_interrupt()); BUG_ON(irqs_disabled()); down(&ide_cfg_sem); @@ -629,26 +592,23 @@ void ide_unregister (unsigned int index) goto abort; for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &hwif->drives[unit]; - if (!drive->present) + if (!drive->present) { + if (drive->devfs_name[0] != '\0') { + devfs_remove(drive->devfs_name); + drive->devfs_name[0] = '\0'; + } continue; - if (drive->usage || DRIVER(drive)->busy) - goto abort; - drive->dead = 1; + } + 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); - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &hwif->drives[unit]; - if (!drive->present) - continue; - DRIVER(drive)->cleanup(drive); - } - -#ifdef CONFIG_PROC_FS - destroy_proc_ide_drives(hwif); -#endif + destroy_proc_ide_interface(hwif); hwgroup = hwif->hwgroup; /* @@ -675,44 +635,6 @@ void ide_unregister (unsigned int index) * Remove us from the hwgroup, and free * the hwgroup if we were the only member */ - for (i = 0; i < MAX_DRIVES; ++i) { - drive = &hwif->drives[i]; - if (drive->devfs_name[0] != '\0') { - devfs_remove(drive->devfs_name); - drive->devfs_name[0] = '\0'; - } - if (!drive->present) - continue; - 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 = HWIF(hwgroup->drive); - } - } - BUG_ON(hwgroup->drive == drive); - if (drive->id != NULL) { - kfree(drive->id); - drive->id = NULL; - } - drive->present = 0; - /* Messed up locking ... */ - spin_unlock_irq(&ide_lock); - blk_cleanup_queue(drive->queue); - device_unregister(&drive->gendev); - down(&drive->gendev_rel_sem); - spin_lock_irq(&ide_lock); - drive->queue = NULL; - } if (hwif->next == hwif) { BUG_ON(hwgroup->hwif != hwif); kfree(hwgroup); @@ -739,17 +661,13 @@ void ide_unregister (unsigned int index) /* More messed up locking ... */ spin_unlock_irq(&ide_lock); device_unregister(&hwif->gendev); - down(&hwif->gendev_rel_sem); + wait_for_completion(&hwif->gendev_rel_comp); /* * Remove us from the kernel's knowledge */ blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<drives[i].disk; - hwif->drives[i].disk = NULL; - put_disk(disk); - } + kfree(hwif->sg_table); unregister_blkdev(hwif->major, hwif->name); spin_lock_irq(&ide_lock); @@ -765,119 +683,15 @@ void ide_unregister (unsigned int index) hwif->dma_prdtable = 0; } - old_hwif = *hwif; + /* copy original settings */ + tmp_hwif = *hwif; - init_hwif_data(hwif, index); /* restore hwif data to pristine status */ + /* restore hwif data to pristine status */ + init_hwif_data(hwif, index); init_hwif_default(hwif, index); - hwif->hwgroup = old_hwif.hwgroup; - - hwif->gendev.parent = old_hwif.gendev.parent; - - hwif->proc = old_hwif.proc; + ide_hwif_restore(hwif, &tmp_hwif); - hwif->major = old_hwif.major; -// hwif->index = old_hwif.index; -// hwif->channel = old_hwif.channel; - hwif->straight8 = old_hwif.straight8; - hwif->bus_state = old_hwif.bus_state; - - hwif->atapi_dma = old_hwif.atapi_dma; - hwif->ultra_mask = old_hwif.ultra_mask; - hwif->mwdma_mask = old_hwif.mwdma_mask; - hwif->swdma_mask = old_hwif.swdma_mask; - - hwif->chipset = old_hwif.chipset; - hwif->hold = old_hwif.hold; - -#ifdef CONFIG_BLK_DEV_IDEPCI - hwif->pci_dev = old_hwif.pci_dev; - hwif->cds = old_hwif.cds; -#endif /* CONFIG_BLK_DEV_IDEPCI */ - -#if 0 - hwif->hwifops = old_hwif.hwifops; -#else - hwif->identify = old_hwif.identify; - hwif->tuneproc = old_hwif.tuneproc; - hwif->speedproc = old_hwif.speedproc; - hwif->selectproc = old_hwif.selectproc; - hwif->reset_poll = old_hwif.reset_poll; - hwif->pre_reset = old_hwif.pre_reset; - hwif->resetproc = old_hwif.resetproc; - hwif->intrproc = old_hwif.intrproc; - hwif->maskproc = old_hwif.maskproc; - hwif->quirkproc = old_hwif.quirkproc; - hwif->busproc = old_hwif.busproc; -#endif - -#if 0 - hwif->pioops = old_hwif.pioops; -#else - hwif->ata_input_data = old_hwif.ata_input_data; - hwif->ata_output_data = old_hwif.ata_output_data; - hwif->atapi_input_bytes = old_hwif.atapi_input_bytes; - hwif->atapi_output_bytes = old_hwif.atapi_output_bytes; -#endif - -#if 0 - hwif->dmaops = old_hwif.dmaops; -#else - hwif->ide_dma_read = old_hwif.ide_dma_read; - hwif->ide_dma_write = old_hwif.ide_dma_write; - hwif->ide_dma_begin = old_hwif.ide_dma_begin; - hwif->ide_dma_end = old_hwif.ide_dma_end; - hwif->ide_dma_check = old_hwif.ide_dma_check; - hwif->ide_dma_on = old_hwif.ide_dma_on; - hwif->ide_dma_off_quietly = old_hwif.ide_dma_off_quietly; - hwif->ide_dma_test_irq = old_hwif.ide_dma_test_irq; - hwif->ide_dma_host_on = old_hwif.ide_dma_host_on; - hwif->ide_dma_host_off = old_hwif.ide_dma_host_off; - hwif->ide_dma_verbose = old_hwif.ide_dma_verbose; - hwif->ide_dma_lostirq = old_hwif.ide_dma_lostirq; - hwif->ide_dma_timeout = old_hwif.ide_dma_timeout; -#endif - -#if 0 - hwif->iops = old_hwif.iops; -#else - hwif->OUTB = old_hwif.OUTB; - hwif->OUTBSYNC = old_hwif.OUTBSYNC; - hwif->OUTW = old_hwif.OUTW; - hwif->OUTL = old_hwif.OUTL; - hwif->OUTSW = old_hwif.OUTSW; - hwif->OUTSL = old_hwif.OUTSL; - - hwif->INB = old_hwif.INB; - hwif->INW = old_hwif.INW; - hwif->INL = old_hwif.INL; - hwif->INSW = old_hwif.INSW; - hwif->INSL = old_hwif.INSL; -#endif - - hwif->mmio = old_hwif.mmio; - hwif->rqsize = old_hwif.rqsize; - hwif->no_lba48 = old_hwif.no_lba48; -#ifndef CONFIG_BLK_DEV_IDECS - hwif->irq = old_hwif.irq; -#endif /* CONFIG_BLK_DEV_IDECS */ - - hwif->dma_base = old_hwif.dma_base; - hwif->dma_master = old_hwif.dma_master; - hwif->dma_command = old_hwif.dma_command; - hwif->dma_vendor1 = old_hwif.dma_vendor1; - hwif->dma_status = old_hwif.dma_status; - hwif->dma_vendor3 = old_hwif.dma_vendor3; - hwif->dma_prdtable = old_hwif.dma_prdtable; - - hwif->dma_extra = old_hwif.dma_extra; - hwif->config_data = old_hwif.config_data; - hwif->select_data = old_hwif.select_data; - hwif->autodma = old_hwif.autodma; - hwif->udma_four = old_hwif.udma_four; - hwif->no_dsc = old_hwif.no_dsc; - - hwif->hwif_data = old_hwif.hwif_data; abort: spin_unlock_irq(&ide_lock); up(&ide_cfg_sem); @@ -939,13 +753,19 @@ void ide_setup_ports ( hw_regs_t *hw, */ } -EXPORT_SYMBOL(ide_setup_ports); - -/* - * Register an IDE interface, specifying exactly the registers etc - * Set init=1 iff calling before probes have taken place. +/** + * ide_register_hw_with_fixup - register IDE interface + * @hw: hardware registers + * @hwifp: pointer to returned hwif + * @fixup: fixup function + * + * Register an IDE interface, specifying exactly the registers etc. + * Set init=1 iff calling before probes have taken place. + * + * Returns -1 on error. */ -int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp) + +int ide_register_hw_with_fixup(hw_regs_t *hw, ide_hwif_t **hwifp, void(*fixup)(ide_hwif_t *hwif)) { int index, retry = 1; ide_hwif_t *hwif; @@ -982,9 +802,10 @@ found: hwif->irq = hw->irq; hwif->noprobe = 0; hwif->chipset = hw->chipset; + hwif->gendev.parent = hw->dev; if (!initializing) { - probe_hwif_init(hwif); + probe_hwif_init_with_fixup(hwif, fixup); create_proc_ide_interfaces(); } @@ -994,6 +815,13 @@ found: return (initializing || hwif->present) ? index : -1; } +EXPORT_SYMBOL(ide_register_hw_with_fixup); + +int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp) +{ + return ide_register_hw_with_fixup(hw, hwifp, NULL); +} + EXPORT_SYMBOL(ide_register_hw); /* @@ -1001,10 +829,9 @@ EXPORT_SYMBOL(ide_register_hw); */ DECLARE_MUTEX(ide_setting_sem); -EXPORT_SYMBOL(ide_setting_sem); /** - * ide_add_setting - add an ide setting option + * __ide_add_setting - add an ide setting option * @drive: drive to use * @name: setting name * @rw: true if the function is read write @@ -1017,6 +844,7 @@ EXPORT_SYMBOL(ide_setting_sem); * @div_factor: divison scale * @data: private data field * @set: setting + * @auto_remove: setting auto removal flag * * Removes the setting named from the device if it is present. * The function takes the settings_lock to protect against @@ -1028,17 +856,16 @@ EXPORT_SYMBOL(ide_setting_sem); * a driver is attached we assume the driver settings are auto * remove. */ - -int ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) + +static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; down(&ide_setting_sem); while ((*p) && strcmp((*p)->name, name) < 0) p = &((*p)->next); - if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL) + if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) goto abort; - memset(setting, 0, sizeof(*setting)); if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) goto abort; strcpy(setting->name, name); @@ -1054,18 +881,22 @@ int ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioct setting->set = set; setting->next = *p; - if (drive->driver != &idedefault_driver) + if (auto_remove) setting->auto_remove = 1; *p = setting; up(&ide_setting_sem); return 0; abort: up(&ide_setting_sem); - if (setting) - kfree(setting); + kfree(setting); return -1; } +int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) +{ + return __ide_add_setting(drive, name, rw, read_ioctl, write_ioctl, data_type, min, max, mul_factor, div_factor, data, set, 1); +} + EXPORT_SYMBOL(ide_add_setting); /** @@ -1094,26 +925,6 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name) kfree(setting); } -/** - * ide_remove_setting - remove an ide setting option - * @drive: drive to use - * @name: setting name - * - * Removes the setting named from the device if it is present. - * The function takes the settings_lock to protect against - * parallel changes. This function must not be called from IRQ - * context. - */ - -void ide_remove_setting (ide_drive_t *drive, char *name) -{ - down(&ide_setting_sem); - __ide_remove_setting(drive, name); - up(&ide_setting_sem); -} - -EXPORT_SYMBOL(ide_remove_setting); - /** * ide_find_setting_by_ioctl - find a drive specific ioctl * @drive: drive to scan @@ -1219,6 +1030,15 @@ int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) return val; } +/** + * ide_spin_wait_hwgroup - wait for group + * @drive: drive in the group + * + * Wait for an IDE device group to go non busy and then return + * holding the ide_lock which guards the hwgroup->busy status + * and right to use it. + */ + int ide_spin_wait_hwgroup (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); @@ -1260,6 +1080,7 @@ EXPORT_SYMBOL(ide_spin_wait_hwgroup); * to the driver to change settings, and then wait on a sema for completion. * The current scheme of polling is kludgy, though safe enough. */ + int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) { int i; @@ -1295,8 +1116,6 @@ int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) return 0; } -EXPORT_SYMBOL(ide_write_setting); - static int set_io_32bit(ide_drive_t *drive, int arg) { drive->io_32bit = arg; @@ -1355,60 +1174,37 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) return err; } -int ide_atapi_to_scsi (ide_drive_t *drive, int arg) -{ - if (drive->media == ide_disk) { - drive->scsi = 0; - return 0; - } - - if (DRIVER(drive)->cleanup(drive)) { - drive->scsi = 0; - return 0; - } - - drive->scsi = (u8) arg; - ata_attach(drive); - return 0; -} +/** + * ide_add_generic_settings - generic ide settings + * @drive: drive being configured + * + * Add the generic parts of the system settings to the /proc files and + * ioctls for this IDE device. The caller must not be holding the + * ide_setting_sem. + */ void ide_add_generic_settings (ide_drive_t *drive) { /* - * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function + * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit); - ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL); - ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL); - ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode); - ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL); - ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma); - ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL); - ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate); - ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL); - if (drive->media != ide_disk) - ide_add_setting(drive, "ide-scsi", SETTING_RW, -1, HDIO_SET_IDE_SCSI, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, ide_atapi_to_scsi); + __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); + __ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); + __ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); + __ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); + __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); + __ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); + __ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); + __ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); + __ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); } -/* - * Delay for *at least* 50ms. As we don't know how much time is left - * until the next tick occurs, we wait an extra tick to be safe. - * This is used only during the probing/polling for drives at boot time. +/** + * system_bus_clock - clock guess * - * However, its usefullness may be needed in other places, thus we export it now. - * The future may change this to a millisecond setable delay. + * External version of the bus clock guess used by very old IDE drivers + * for things like VLB timings. Should not be used. */ -void ide_delay_50ms (void) -{ -#ifndef CONFIG_BLK_DEV_IDECS - mdelay(50); -#else - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1+HZ/20); -#endif /* CONFIG_BLK_DEV_IDECS */ -} - -EXPORT_SYMBOL(ide_delay_50ms); int system_bus_clock (void) { @@ -1417,62 +1213,7 @@ int system_bus_clock (void) EXPORT_SYMBOL(system_bus_clock); -/* - * Locking is badly broken here - since way back. That sucker is - * root-only, but that's not an excuse... The real question is what - * exclusion rules do we want here. - */ -int ide_replace_subdriver (ide_drive_t *drive, const char *driver) -{ - if (!drive->present || drive->usage || drive->dead) - goto abort; - if (DRIVER(drive)->cleanup(drive)) - goto abort; - strlcpy(drive->driver_req, driver, sizeof(drive->driver_req)); - if (ata_attach(drive)) { - spin_lock(&drives_lock); - list_del_init(&drive->list); - spin_unlock(&drives_lock); - drive->driver_req[0] = 0; - ata_attach(drive); - } else { - drive->driver_req[0] = 0; - } - if (DRIVER(drive)!= &idedefault_driver && !strcmp(DRIVER(drive)->name, driver)) - return 0; -abort: - return 1; -} - -EXPORT_SYMBOL(ide_replace_subdriver); - -int ata_attach(ide_drive_t *drive) -{ - struct list_head *p; - spin_lock(&drivers_lock); - list_for_each(p, &drivers) { - ide_driver_t *driver = list_entry(p, ide_driver_t, drivers); - if (!try_module_get(driver->owner)) - continue; - spin_unlock(&drivers_lock); - if (driver->attach(drive) == 0) { - module_put(driver->owner); - drive->gendev.driver = &driver->gen_driver; - return 0; - } - spin_lock(&drivers_lock); - module_put(driver->owner); - } - drive->gendev.driver = &idedefault_driver.gen_driver; - spin_unlock(&drivers_lock); - if(idedefault_driver.attach(drive) != 0) - panic("ide: default attach failed"); - return 1; -} - -EXPORT_SYMBOL(ata_attach); - -static int generic_ide_suspend(struct device *dev, u32 state) +static int generic_ide_suspend(struct device *dev, pm_message_t state) { ide_drive_t *drive = dev->driver_data; struct request rq; @@ -1486,7 +1227,7 @@ static int generic_ide_suspend(struct device *dev, u32 state) rq.special = &args; rq.pm = &rqpm; rqpm.pm_step = ide_pm_state_start_suspend; - rqpm.pm_state = state; + rqpm.pm_state = state.event; return ide_do_drive_cmd(drive, &rq, ide_wait); } @@ -1505,24 +1246,25 @@ static int generic_ide_resume(struct device *dev) rq.special = &args; rq.pm = &rqpm; rqpm.pm_step = ide_pm_state_start_resume; - rqpm.pm_state = 0; + rqpm.pm_state = PM_EVENT_ON; return ide_do_drive_cmd(drive, &rq, ide_head_wait); } -int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd, - unsigned long arg) +int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, + unsigned int cmd, unsigned long arg) { - ide_drive_t *drive = bdev->bd_disk->private_data; ide_settings_t *setting; + ide_driver_t *drv; int err = 0; + void __user *p = (void __user *)arg; down(&ide_setting_sem); if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) { if (cmd == setting->read_ioctl) { err = ide_read_setting(drive, setting); up(&ide_setting_sem); - return err >= 0 ? put_user(err, (long *) arg) : err; + return err >= 0 ? put_user(err, (long __user *)arg) : err; } else { if (bdev != bdev->bd_contains) err = -EINVAL; @@ -1535,26 +1277,13 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd, up(&ide_setting_sem); switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry *loc = (struct hd_geometry *) arg; - u16 bios_cyl = drive->bios_cyl; /* truncate */ - if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; - if (put_user(drive->bios_head, (u8 *) &loc->heads)) return -EFAULT; - if (put_user(drive->bios_sect, (u8 *) &loc->sectors)) return -EFAULT; - if (put_user(bios_cyl, (u16 *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)get_start_sect(bdev), - (unsigned long *) &loc->start)) return -EFAULT; - return 0; - } - case HDIO_OBSOLETE_IDENTITY: case HDIO_GET_IDENTITY: if (bdev != bdev->bd_contains) return -EINVAL; if (drive->id_read == 0) return -ENOMSG; - if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142)) + if (copy_to_user(p, drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142)) return -EFAULT; return 0; @@ -1564,7 +1293,7 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd, drive->nice0 << IDE_NICE_0 | drive->nice1 << IDE_NICE_1 | drive->nice2 << IDE_NICE_2, - (long *) arg); + (long __user *) arg); #ifdef CONFIG_IDE_TASK_IOCTL case HDIO_DRIVE_TASKFILE: @@ -1593,7 +1322,7 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd, hw_regs_t hw; int args[3]; if (!capable(CAP_SYS_RAWIO)) return -EACCES; - if (copy_from_user(args, (void *)arg, 3 * sizeof(int))) + if (copy_from_user(args, p, 3 * sizeof(int))) return -EFAULT; memset(&hw, 0, sizeof(hw)); ide_init_hwif_ports(&hw, (unsigned long) args[0], @@ -1613,7 +1342,8 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd, if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) return -EPERM; drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; - if (drive->dsc_overlap && !DRIVER(drive)->supports_dsc_overlap) { + drv = *(ide_driver_t **)bdev->bd_disk->private_data; + if (drive->dsc_overlap && !drv->supports_dsc_overlap) { drive->dsc_overlap = 0; return -EPERM; } @@ -1633,8 +1363,9 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd, */ spin_lock_irqsave(&ide_lock, flags); - - DRIVER(drive)->abort(drive, "drive reset"); + + ide_abort(drive, "drive reset"); + if(HWGROUP(drive)->handler) BUG(); @@ -1644,29 +1375,18 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd, HWGROUP(drive)->busy = 1; spin_unlock_irqrestore(&ide_lock, flags); (void) ide_do_reset(drive); - if (drive->suspend_reset) { -/* - * APM WAKE UP todo !! - * int nogoodpower = 1; - * while(nogoodpower) { - * check_power1() or check_power2() - * nogoodpower = 0; - * } - * HWIF(drive)->multiproc(drive); - */ - return ioctl_by_bdev(bdev, BLKRRPART, 0); - } + return 0; } case CDROMEJECT: case CDROMCLOSETRAY: - return scsi_cmd_ioctl(bdev->bd_disk, cmd, arg); + return scsi_cmd_ioctl(file, bdev->bd_disk, cmd, p); case HDIO_GET_BUSSTATE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (put_user(HWIF(drive)->bus_state, (long *)arg)) + if (put_user(HWIF(drive)->bus_state, (long __user *)arg)) return -EFAULT; return 0; @@ -1747,9 +1467,6 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m return 0; /* zero = nothing matched */ } -#ifdef CONFIG_BLK_DEV_PDC4030 -static int __initdata probe_pdc4030; -#endif #ifdef CONFIG_BLK_DEV_ALI14XX static int __initdata probe_ali14xx; extern int ali14xx_init(void); @@ -1779,7 +1496,7 @@ static int __initdata is_chipset_set[MAX_HWIFS]; * * Remember to update Documentation/ide.txt if you change something here. */ -int __init ide_setup (char *s) +static int __init ide_setup(char *s) { int i, vals[3]; ide_hwif_t *hwif; @@ -1809,7 +1526,7 @@ int __init ide_setup (char *s) #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ if (!strcmp(s, "ide=nodma")) { - printk("IDE: Prevented DMA\n"); + printk(" : Prevented DMA\n"); noautodma = 1; return 1; } @@ -1851,6 +1568,8 @@ int __init ide_setup (char *s) case -4: /* "cdrom" */ drive->present = 1; drive->media = ide_cdrom; + /* an ATAPI device ignores DRDY */ + drive->ready_stat = 0; hwif->noprobe = 0; goto done; case -5: /* "serialize" */ @@ -1858,10 +1577,10 @@ int __init ide_setup (char *s) goto do_serialize; case -6: /* "autotune" */ drive->autotune = IDE_TUNE_AUTO; - goto done; + goto obsolete_option; case -7: /* "noautotune" */ drive->autotune = IDE_TUNE_NOAUTO; - goto done; + goto obsolete_option; case -9: /* "swapdata" */ case -10: /* "bswap" */ drive->bswap = 1; @@ -1877,6 +1596,7 @@ int __init ide_setup (char *s) goto done; case 3: /* cyl,head,sect */ drive->media = ide_disk; + drive->ready_stat = READY_STAT; drive->cyl = drive->bios_cyl = vals[0]; drive->head = drive->bios_head = vals[1]; drive->sect = drive->bios_sect = vals[2]; @@ -1915,7 +1635,7 @@ int __init ide_setup (char *s) "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", - "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; + "dtc2278", "umc8672", "ali14xx", NULL }; hw = s[3] - '0'; hwif = &ide_hwifs[hw]; i = match_parm(&s[4], ide_words, vals, 3); @@ -1941,11 +1661,6 @@ int __init ide_setup (char *s) } switch (i) { -#ifdef CONFIG_BLK_DEV_PDC4030 - case -18: /* "dc4030" */ - probe_pdc4030 = 1; - goto done; -#endif #ifdef CONFIG_BLK_DEV_ALI14XX case -17: /* "ali14xx" */ probe_ali14xx = 1; @@ -1998,30 +1713,30 @@ int __init ide_setup (char *s) case -7: /* ata66 */ #ifdef CONFIG_BLK_DEV_IDEPCI hwif->udma_four = 1; - goto done; + goto obsolete_option; #else goto bad_hwif; #endif case -6: /* dma */ hwif->autodma = 1; - goto done; + goto obsolete_option; case -5: /* "reset" */ hwif->reset = 1; - goto done; + goto obsolete_option; case -4: /* "noautotune" */ hwif->drives[0].autotune = IDE_TUNE_NOAUTO; hwif->drives[1].autotune = IDE_TUNE_NOAUTO; - goto done; + goto obsolete_option; case -3: /* "autotune" */ hwif->drives[0].autotune = IDE_TUNE_AUTO; hwif->drives[1].autotune = IDE_TUNE_AUTO; - goto done; + goto obsolete_option; case -2: /* "serialize" */ do_serialize: hwif->mate = &ide_hwifs[hw^1]; hwif->mate->mate = hwif; hwif->serialized = hwif->mate->serialized = 1; - goto done; + goto obsolete_option; case -1: /* "noprobe" */ hwif->noprobe = 1; @@ -2038,7 +1753,7 @@ int __init ide_setup (char *s) hwif->irq = vals[2]; hwif->noprobe = 0; hwif->chipset = ide_forced; - goto done; + goto obsolete_option; case 0: goto bad_option; default: @@ -2049,6 +1764,9 @@ int __init ide_setup (char *s) bad_option: printk(" -- BAD OPTION\n"); return 1; +obsolete_option: + printk(" -- OBSOLETE OPTION, WILL BE REMOVED SOON!\n"); + return 1; bad_hwif: printk("-- NOT SUPPORTED ON ide%d", hw); done: @@ -2056,6 +1774,9 @@ done: return 1; } +extern void pnpide_init(void); +extern void h8300_ide_init(void); + /* * probe_for_hwifs() finds/initializes "known" IDE interfaces */ @@ -2077,25 +1798,12 @@ static void __init probe_for_hwifs (void) ide_probe_for_cmd640x(); } #endif /* CONFIG_BLK_DEV_CMD640 */ -#ifdef CONFIG_BLK_DEV_PDC4030 - { - extern int pdc4030_init(void); - if (probe_pdc4030) - (void)pdc4030_init(); - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ #ifdef CONFIG_BLK_DEV_IDE_PMAC { extern void pmac_ide_probe(void); pmac_ide_probe(); } #endif /* CONFIG_BLK_DEV_IDE_PMAC */ -#ifdef CONFIG_BLK_DEV_IDE_SWARM - { - extern void swarm_ide_probe(void); - swarm_ide_probe(); - } -#endif /* CONFIG_BLK_DEV_IDE_SWARM */ #ifdef CONFIG_BLK_DEV_GAYLE { extern void gayle_init(void); @@ -2126,249 +1834,166 @@ static void __init probe_for_hwifs (void) buddha_init(); } #endif /* CONFIG_BLK_DEV_BUDDHA */ -#if defined(CONFIG_BLK_DEV_IDEPNP) && defined(CONFIG_PNP) - { - extern void pnpide_init(int enable); - pnpide_init(1); - } -#endif /* CONFIG_BLK_DEV_IDEPNP */ -} - -/* - * Actually unregister the subdriver. Called with the - * request lock dropped. - */ - -static int default_cleanup (ide_drive_t *drive) -{ - return ide_unregister_subdriver(drive); -} - -static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, sector_t block) -{ - ide_end_request(drive, 0, 0); - return ide_stopped; +#ifdef CONFIG_BLK_DEV_IDEPNP + pnpide_init(); +#endif +#ifdef CONFIG_H8300 + h8300_ide_init(); +#endif } -static int default_end_request (ide_drive_t *drive, int uptodate, int nr_sects) +void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) { - return ide_end_request(drive, uptodate, nr_sects); +#ifdef CONFIG_PROC_FS + ide_add_proc_entries(drive->proc, driver->proc, drive); +#endif } -static u8 default_sense (ide_drive_t *drive, const char *msg, u8 stat) -{ - return ide_dump_status(drive, msg, stat); -} +EXPORT_SYMBOL(ide_register_subdriver); -static ide_startstop_t default_error (ide_drive_t *drive, const char *msg, u8 stat) -{ - return ide_error(drive, msg, stat); -} +/** + * ide_unregister_subdriver - disconnect drive from driver + * @drive: drive to unplug + * @driver: driver + * + * Disconnect a drive from the driver it was attached to and then + * clean up the various proc files and other objects attached to it. + * + * Takes ide_setting_sem and ide_lock. + * Caller must hold none of the locks. + */ -static void default_pre_reset (ide_drive_t *drive) +void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver) { + unsigned long flags; + + down(&ide_setting_sem); + spin_lock_irqsave(&ide_lock, flags); +#ifdef CONFIG_PROC_FS + ide_remove_proc_entries(drive->proc, driver->proc); +#endif + auto_remove_settings(drive); + spin_unlock_irqrestore(&ide_lock, flags); + up(&ide_setting_sem); } -static sector_t default_capacity (ide_drive_t *drive) -{ - return 0x7fffffff; -} +EXPORT_SYMBOL(ide_unregister_subdriver); -static ide_startstop_t default_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; +/* + * Probe module + */ - s->all = 0; - drive->mult_req = 0; - return ide_stopped; -} +EXPORT_SYMBOL(ide_lock); -static int default_attach (ide_drive_t *drive) +static int ide_bus_match(struct device *dev, struct device_driver *drv) { - printk(KERN_ERR "%s: does not support hotswap of device class !\n", - drive->name); - - return 0; + return 1; } -static ide_startstop_t default_abort (ide_drive_t *drive, const char *msg) +static char *media_string(ide_drive_t *drive) { - return ide_abort(drive, msg); + switch (drive->media) { + case ide_disk: + return "disk"; + case ide_cdrom: + return "cdrom"; + case ide_tape: + return "tape"; + case ide_floppy: + return "floppy"; + default: + return "UNKNOWN"; + } } -static ide_startstop_t default_start_power_step(ide_drive_t *drive, - struct request *rq) +static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf) { - rq->pm->pm_step = ide_pm_state_completed; - return ide_stopped; + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", media_string(drive)); } -static void setup_driver_defaults (ide_driver_t *d) +static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf) { - if (d->cleanup == NULL) d->cleanup = default_cleanup; - if (d->do_request == NULL) d->do_request = default_do_request; - if (d->end_request == NULL) d->end_request = default_end_request; - if (d->sense == NULL) d->sense = default_sense; - if (d->error == NULL) d->error = default_error; - if (d->abort == NULL) d->abort = default_abort; - if (d->pre_reset == NULL) d->pre_reset = default_pre_reset; - if (d->capacity == NULL) d->capacity = default_capacity; - if (d->special == NULL) d->special = default_special; - if (d->attach == NULL) d->attach = default_attach; - if (d->start_power_step == NULL) - d->start_power_step = default_start_power_step; + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->name); } -int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { - unsigned long flags; - - BUG_ON(!drive->driver); - - spin_lock_irqsave(&ide_lock, flags); - if (!drive->present || drive->driver != &idedefault_driver || - drive->usage || drive->dead) { - spin_unlock_irqrestore(&ide_lock, flags); - return 1; - } - drive->driver = driver; - spin_unlock_irqrestore(&ide_lock, flags); - spin_lock(&drives_lock); - list_add_tail(&drive->list, &driver->drives); - spin_unlock(&drives_lock); -// printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name); - if ((drive->autotune == IDE_TUNE_DEFAULT) || - (drive->autotune == IDE_TUNE_AUTO)) { - /* DMA timings and setup moved to ide-probe.c */ - drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap); - drive->nice1 = 1; - } - drive->suspend_reset = 0; -#ifdef CONFIG_PROC_FS - if (drive->driver != &idedefault_driver) { - ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); - ide_add_proc_entries(drive->proc, driver->proc, drive); - } -#endif - return 0; + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "ide:m-%s\n", media_string(drive)); } -EXPORT_SYMBOL(ide_register_subdriver); +static struct device_attribute ide_dev_attrs[] = { + __ATTR_RO(media), + __ATTR_RO(drivename), + __ATTR_RO(modalias), + __ATTR_NULL +}; -int ide_unregister_subdriver (ide_drive_t *drive) +static int ide_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) { - unsigned long flags; - - down(&ide_setting_sem); - spin_lock_irqsave(&ide_lock, flags); - if (drive->usage || drive->driver == &idedefault_driver || DRIVER(drive)->busy) { - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); - return 1; - } -#if defined(CONFIG_BLK_DEV_IDEPNP) && defined(CONFIG_PNP) && defined(MODULE) - pnpide_init(0); -#endif /* CONFIG_BLK_DEV_IDEPNP */ -#ifdef CONFIG_PROC_FS - ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc); - ide_remove_proc_entries(drive->proc, generic_subdriver_entries); -#endif - auto_remove_settings(drive); - drive->driver = &idedefault_driver; - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); - spin_lock(&drives_lock); - list_del_init(&drive->list); - spin_unlock(&drives_lock); - /* drive will be added to &idedefault_driver->drives in ata_attach() */ - return 0; -} + ide_drive_t *drive = to_ide_device(dev); + int i = 0; + int length = 0; -EXPORT_SYMBOL(ide_unregister_subdriver); - -static int ide_drive_remove(struct device * dev) -{ - ide_drive_t * drive = container_of(dev,ide_drive_t,gendev); - DRIVER(drive)->cleanup(drive); + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "MEDIA=%s", media_string(drive)); + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "DRIVENAME=%s", drive->name); + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "MODALIAS=ide:m-%s", media_string(drive)); + envp[i] = NULL; return 0; } -int ide_register_driver(ide_driver_t *driver) +static int generic_ide_probe(struct device *dev) { - struct list_head list; - struct list_head *list_loop; - struct list_head *tmp_storage; - - setup_driver_defaults(driver); - - spin_lock(&drivers_lock); - list_add(&driver->drivers, &drivers); - spin_unlock(&drivers_lock); - - INIT_LIST_HEAD(&list); - spin_lock(&drives_lock); - list_splice_init(&idedefault_driver.drives, &list); - spin_unlock(&drives_lock); - - list_for_each_safe(list_loop, tmp_storage, &list) { - ide_drive_t *drive = container_of(list_loop, ide_drive_t, list); - list_del_init(&drive->list); - if (drive->present) - ata_attach(drive); - } - driver->gen_driver.name = (char *) driver->name; - driver->gen_driver.bus = &ide_bus_type; - driver->gen_driver.remove = ide_drive_remove; - return driver_register(&driver->gen_driver); -} + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); -EXPORT_SYMBOL(ide_register_driver); + return drv->probe ? drv->probe(drive) : -ENODEV; +} -void ide_unregister_driver(ide_driver_t *driver) +static int generic_ide_remove(struct device *dev) { - ide_drive_t *drive; - - spin_lock(&drivers_lock); - list_del(&driver->drivers); - spin_unlock(&drivers_lock); + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); - driver_unregister(&driver->gen_driver); + if (drv->remove) + drv->remove(drive); - while(!list_empty(&driver->drives)) { - drive = list_entry(driver->drives.next, ide_drive_t, list); - if (driver->cleanup(drive)) { - printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); - BUG(); - } - ata_attach(drive); - } + return 0; } -EXPORT_SYMBOL(ide_unregister_driver); - -struct block_device_operations ide_fops[] = {{ - .owner = THIS_MODULE, - .open = ide_open, -}}; - -EXPORT_SYMBOL(ide_fops); - -/* - * Probe module - */ +static void generic_ide_shutdown(struct device *dev) +{ + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); -EXPORT_SYMBOL(ide_lock); + if (dev->driver && drv->shutdown) + drv->shutdown(drive); +} struct bus_type ide_bus_type = { .name = "ide", + .match = ide_bus_match, + .uevent = ide_uevent, + .probe = generic_ide_probe, + .remove = generic_ide_remove, + .shutdown = generic_ide_shutdown, + .dev_attrs = ide_dev_attrs, .suspend = generic_ide_suspend, .resume = generic_ide_resume, }; +EXPORT_SYMBOL_GPL(ide_bus_type); + /* * This is gets invoked once during initialization, to set *everything* up */ -int __init ide_init (void) +static int __init ide_init(void) { printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); devfs_mk_dir("ide"); @@ -2379,7 +2004,7 @@ int __init ide_init (void) init_ide_data(); #ifdef CONFIG_PROC_FS - proc_ide_root = proc_mkdir("ide", 0); + proc_ide_root = proc_mkdir("ide", NULL); #endif #ifdef CONFIG_BLK_DEV_ALI14XX @@ -2415,8 +2040,8 @@ int __init ide_init (void) } #ifdef MODULE -char *options = NULL; -MODULE_PARM(options,"s"); +static char *options = NULL; +module_param(options, charp, 0); MODULE_LICENSE("GPL"); static void __init parse_options (char *line) @@ -2433,7 +2058,7 @@ static void __init parse_options (char *line) } } -int init_module (void) +int __init init_module (void) { parse_options(options); return ide_init(); @@ -2443,11 +2068,8 @@ void cleanup_module (void) { int index; - for (index = 0; index < MAX_HWIFS; ++index) { + for (index = 0; index < MAX_HWIFS; ++index) ide_unregister(index); - if (ide_hwifs[index].dma_base) - (void) ide_release_dma(&ide_hwifs[index]); - } #ifdef CONFIG_PROC_FS proc_ide_destroy();