📄 ide.c
字号:
* If we are revalidating a disk because of a media change, then we * enter with usage == 0. If we are using an ioctl, we automatically have * usage == 1 (we need an open channel to use an ioctl :-), so this * is our limit. */int ide_revalidate_disk (kdev_t i_rdev){ ide_drive_t *drive; ide_hwgroup_t *hwgroup; unsigned int p, major, minor; unsigned long flags; if ((drive = get_info_ptr(i_rdev)) == NULL) return -ENODEV; major = MAJOR(i_rdev); minor = drive->select.b.unit << PARTN_BITS; hwgroup = HWGROUP(drive); spin_lock_irqsave(&io_request_lock, flags); if (drive->busy || (drive->usage > 1)) { spin_unlock_irqrestore(&io_request_lock, flags); return -EBUSY; }; drive->busy = 1; MOD_INC_USE_COUNT; spin_unlock_irqrestore(&io_request_lock, flags); for (p = 0; p < (1<<PARTN_BITS); ++p) { if (drive->part[p].nr_sects > 0) { kdev_t devp = MKDEV(major, minor+p); invalidate_device(devp, 1); } drive->part[p].start_sect = 0; drive->part[p].nr_sects = 0; }; if (DRIVER(drive)->revalidate) DRIVER(drive)->revalidate(drive); drive->busy = 0; wake_up(&drive->wqueue); MOD_DEC_USE_COUNT; return 0;}EXPORT_SYMBOL(ide_revalidate_disk);static void revalidate_drives (int revaldiate){ ide_hwif_t *hwif; ide_drive_t *drive; int index, unit; for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &ide_hwifs[index].drives[unit]; if (drive->revalidate) { drive->revalidate = 0; if ((!initializing) && (revaldiate)) (void) ide_revalidate_disk(MKDEV(hwif->major, unit<<PARTN_BITS)); } } }}void ide_probe_module (int revaldiate){ if (!ide_probe) {#if defined(CONFIG_BLK_DEV_IDE_MODULE) (void) request_module("ide-probe-mod");#endif } else { (void) ide_probe->init(); } revalidate_drives(revaldiate);}EXPORT_SYMBOL(ide_probe_module);void ide_driver_module (int revaldiate){ int index; ide_module_t *module = ide_modules; for (index = 0; index < MAX_HWIFS; ++index) if (ide_hwifs[index].present) goto search; ide_probe_module(revaldiate);search: while (module) { (void) module->init(); module = module->next; } revalidate_drives(revaldiate);}EXPORT_SYMBOL(ide_driver_module);static int ide_open (struct inode * inode, struct file * filp){ ide_drive_t *drive; if ((drive = get_info_ptr(inode->i_rdev)) == NULL) return -ENXIO; if (drive->driver == &idedefault_driver) ide_driver_module(1); if (drive->driver == &idedefault_driver) { if (drive->media == ide_disk) (void) request_module("ide-disk"); if (drive->scsi) (void) request_module("ide-scsi"); if (drive->media == ide_cdrom) (void) request_module("ide-cd"); if (drive->media == ide_tape) (void) request_module("ide-tape"); if (drive->media == ide_floppy) (void) request_module("ide-floppy"); } /* The locking here isnt enough, but this is hard to fix in the 2.4 cases */ while (drive->busy) sleep_on(&drive->wqueue); drive->usage++; if (!drive->dead) return DRIVER(drive)->open(inode, filp, drive); printk(KERN_WARNING "%s: driver not present\n", drive->name); drive->usage--; return -ENXIO;}/* * Releasing a block device means we sync() it, so that it can safely * be forgotten about... */static int ide_release (struct inode * inode, struct file * file){ ide_drive_t *drive; if ((drive = get_info_ptr(inode->i_rdev)) != NULL) { drive->usage--; DRIVER(drive)->release(inode, file, drive); } return 0;}#ifdef CONFIG_PROC_FSide_proc_entry_t generic_subdriver_entries[] = { { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, { NULL, 0, NULL, NULL }};#endif#define hwif_release_region(addr, num) \ ((hwif->mmio) ? release_mem_region((addr),(num)) : release_region((addr),(num)))/* * Note that we only release the standard ports, * and do not even try to handle any extra ports * allocated for weird IDE interface chipsets. */void hwif_unregister (ide_hwif_t *hwif){ u32 i = 0; if (hwif->mmio == 2) return; if (hwif->io_ports[IDE_CONTROL_OFFSET]) hwif_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) if (hwif->io_ports[IDE_IRQ_OFFSET]) hwif_release_region(hwif->io_ports[IDE_IRQ_OFFSET], 1);#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ if (hwif->straight8) { hwif_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]) { hwif_release_region(hwif->io_ports[i], 1); } }}EXPORT_SYMBOL(hwif_unregister);extern void init_hwif_data(unsigned int index);int ide_unregister (unsigned int index){ struct gendisk *gd; ide_drive_t *drive, *d; ide_hwif_t *hwif, *g; ide_hwgroup_t *hwgroup; int irq_count = 0, unit, i; unsigned long flags; unsigned int p, minor; ide_hwif_t old_hwif; if (index >= MAX_HWIFS) BUG(); spin_lock_irqsave(&io_request_lock, flags); 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->busy || drive->usage) goto abort; if (DRIVER(drive)->shutdown(drive)) goto abort; } hwif->present = 0; /* * All clear? Then blow away the buffer cache */ spin_unlock_irqrestore(&io_request_lock, flags); for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &hwif->drives[unit]; if (!drive->present) continue; DRIVER(drive)->cleanup(drive); minor = drive->select.b.unit << PARTN_BITS; for (p = 0; p < (1<<PARTN_BITS); ++p) { if (drive->part[p].nr_sects > 0) { kdev_t devp = MKDEV(hwif->major, minor+p); invalidate_device(devp, 0); } }#ifdef CONFIG_PROC_FS destroy_proc_ide_drives(hwif);#endif } spin_lock_irqsave(&io_request_lock, flags); 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); /* * Note that we only release the standard ports, * and do not even try to handle any extra ports * allocated for weird IDE interface chipsets. */ hwif_unregister(hwif); /* * Remove us from the hwgroup, and free * the hwgroup if we were the only member */ d = hwgroup->drive; for (i = 0; i < MAX_DRIVES; ++i) { drive = &hwif->drives[i]; if (drive->de) { devfs_unregister(drive->de); drive->de = NULL; } if (!drive->present) continue; while (hwgroup->drive->next != drive) hwgroup->drive = hwgroup->drive->next; hwgroup->drive->next = drive->next; if (hwgroup->drive == drive) hwgroup->drive = NULL; if (drive->id != NULL) { kfree(drive->id); drive->id = NULL; } drive->present = 0; blk_cleanup_queue(&drive->queue); } if (d->present) hwgroup->drive = d; while (hwgroup->hwif->next != hwif) hwgroup->hwif = hwgroup->hwif->next; hwgroup->hwif->next = hwif->next; if (hwgroup->hwif == hwif) kfree(hwgroup); else hwgroup->hwif = HWIF(hwgroup->drive);#if !defined(CONFIG_DMA_NONPCI) 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; }#endif /* !(CONFIG_DMA_NONPCI) */ /* * Remove us from the kernel's knowledge */ unregister_blkdev(hwif->major, hwif->name); kfree(blksize_size[hwif->major]); kfree(max_sectors[hwif->major]); kfree(max_readahead[hwif->major]); blk_dev[hwif->major].data = NULL; blk_dev[hwif->major].queue = NULL; blksize_size[hwif->major] = NULL; gd = hwif->gd; if (gd) { del_gendisk(gd); kfree(gd->sizes); kfree(gd->part); if (gd->de_arr) kfree(gd->de_arr); if (gd->flags) kfree(gd->flags); kfree(gd); hwif->gd = NULL; } old_hwif = *hwif; init_hwif_data(index); /* restore hwif data to pristine status */ hwif->hwgroup = old_hwif.hwgroup; hwif->proc = old_hwif.proc; 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;#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 = old_hwif.ide_dma_off; 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_bad_drive = old_hwif.ide_dma_bad_drive; hwif->ide_dma_good_drive = old_hwif.ide_dma_good_drive; hwif->ide_dma_count = old_hwif.ide_dma_count; hwif->ide_dma_verbose = old_hwif.ide_dma_verbose; hwif->ide_dma_retune = old_hwif.ide_dma_retune; 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->addressing = old_hwif.addressing;#ifndef CONFIG_BLK_DEV_IDECS hwif->irq = old_hwif.irq;#endif /* CONFIG_BLK_DEV_IDECS */ hwif->initializing = old_hwif.initializing; 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; spin_unlock_irqrestore(&io_request_lock, flags); return 0;abort: spin_unlock_irqrestore(&io_request_lock, flags); return 1; }EXPORT_SYMBOL(ide_unregister);/* * 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -