📄 ide.c
字号:
printk("ide: failed opcode was %x\n", opcode); }out: local_irq_restore(flags); return err;}EXPORT_SYMBOL(ide_dump_status);static int ide_open (struct inode * inode, struct file * filp){ return -ENXIO;}/* * drives_lock protects the list of drives, drivers_lock the * list of drivers. Currently nobody takes both at once. */static spinlock_t drives_lock = SPIN_LOCK_UNLOCKED;static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;static LIST_HEAD(drivers);/* Iterator for the driver list. */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_FSstruct 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 }};#endifstatic 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 == 2) return 0; BUG_ON(hwif->mmio == 1); 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 == 2) 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 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->identify = tmp_hwif->identify; 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->ide_dma_read = tmp_hwif->ide_dma_read; hwif->ide_dma_write = tmp_hwif->ide_dma_write; hwif->ide_dma_begin = tmp_hwif->ide_dma_begin; 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_verbose = tmp_hwif->ide_dma_verbose; 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->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 * @index: index of interface (will change soon to a pointer) * * 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 interfce will not be reopened (present/vanishing locking * isnt 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){ 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; BUG_ON(index >= MAX_HWIFS); BUG_ON(in_interrupt()); BUG_ON(irqs_disabled()); down(&ide_cfg_sem); 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; if (drive->usage || DRIVER(drive)->busy) goto abort; drive->dead = 1; } 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 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); spin_lock_irq(&ide_lock); /* * Note that we only release the standard ports, * and do not even try to handle any extra ports * allocated for weird IDE interface chipsets. */ ide_hwif_release_regions(hwif); /* * 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); } else { /* There is another interface in hwgroup. * Unlink us, and set hwgroup->drive and ->hwif to * something sane. */ 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); } /* More messed up locking ... */ spin_unlock_irq(&ide_lock); device_unregister(&hwif->gendev); down(&hwif->gendev_rel_sem); /* * Remove us from the kernel's knowledge */ blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS); for (i = 0; i < MAX_DRIVES; i++) { struct gendisk *disk = hwif->drives[i].disk; hwif->drives[i].disk = NULL; put_disk(disk); } 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_master = 0; hwif->dma_command = 0; hwif->dma_vendor1 = 0; hwif->dma_status = 0; hwif->dma_vendor3 = 0; hwif->dma_prdtable = 0; } /* copy original settings */ tmp_hwif = *hwif; /* restore hwif data to pristine status */ init_hwif_data(hwif, index); init_hwif_default(hwif, index); ide_hwif_restore(hwif, &tmp_hwif);abort: spin_unlock_irq(&ide_lock); up(&ide_cfg_sem);}EXPORT_SYMBOL(ide_unregister);/** * ide_setup_ports - set up IDE interface ports * @hw: register descriptions * @base: base register * @offsets: table of register offsets * @ctrl: control register * @ack_irq: IRQ ack * @irq: interrupt lie * * Setup hw_regs_t structure described by parameters. You * may set up the hw structure yourself OR use this routine to * do it for you. This is basically a helper * */ void ide_setup_ports ( hw_regs_t *hw, unsigned long base, int *offsets, unsigned long ctrl, unsigned long intr, ide_ack_intr_t *ack_intr,/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -