📄 ide-probe.c
字号:
ide_request_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1, hwif->name); if (hwif->io_ports[IDE_SECTOR_OFFSET]) ide_request_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1, hwif->name); if (hwif->io_ports[IDE_LCYL_OFFSET]) ide_request_region(hwif->io_ports[IDE_LCYL_OFFSET], 1, hwif->name); if (hwif->io_ports[IDE_HCYL_OFFSET]) ide_request_region(hwif->io_ports[IDE_HCYL_OFFSET], 1, hwif->name); if (hwif->io_ports[IDE_SELECT_OFFSET]) ide_request_region(hwif->io_ports[IDE_SELECT_OFFSET], 1, hwif->name); if (hwif->io_ports[IDE_STATUS_OFFSET]) ide_request_region(hwif->io_ports[IDE_STATUS_OFFSET], 1, hwif->name);jump_straight8: if (hwif->io_ports[IDE_CONTROL_OFFSET]) ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name);#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) if (hwif->io_ports[IDE_IRQ_OFFSET]) ide_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name);#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */}/* * This routine only knows how to look for drive units 0 and 1 * on an interface, so any setting of MAX_DRIVES > 2 won't work here. */static void probe_hwif (ide_hwif_t *hwif){ unsigned int unit; unsigned long flags; if (hwif->noprobe) return;#ifdef CONFIG_BLK_DEV_IDE if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) { extern void probe_cmos_for_drives(ide_hwif_t *); probe_cmos_for_drives (hwif); }#endif if ((hwif->chipset != ide_4drives || !hwif->mate->present) &&#if CONFIG_BLK_DEV_PDC4030 (hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&#endif /* CONFIG_BLK_DEV_PDC4030 */ (hwif_check_regions(hwif))) { int msgout = 0; for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; if (drive->present) { drive->present = 0; printk("%s: ERROR, PORTS ALREADY IN USE\n", drive->name); msgout = 1; } } if (!msgout) printk("%s: ports already in use, skipping probe\n", hwif->name); return; } __save_flags(flags); /* local CPU only */ __sti(); /* local CPU only; needed for jiffies and irq probing */ /* * Second drive should only exist if first drive was found, * but a lot of cdrom drives are configured as single slaves. */ for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; (void) probe_for_drive (drive); if (drive->present && !hwif->present) { hwif->present = 1; if (hwif->chipset != ide_4drives || !hwif->mate->present) { hwif_register(hwif); } } } if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) { unsigned long timeout = jiffies + WAIT_WORSTCASE; byte stat; printk("%s: reset\n", hwif->name); OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]); udelay(10); OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]); do { ide_delay_50ms(); stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); } while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies)); } __restore_flags(flags); /* local CPU only */ for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; if (drive->present) { ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; if (tuneproc != NULL && drive->autotune == 1) tuneproc(drive, 255); /* auto-tune PIO mode */ } }}#if MAX_HWIFS > 1/* * save_match() is used to simplify logic in init_irq() below. * * A loophole here is that we may not know about a particular * hwif's irq until after that hwif is actually probed/initialized.. * This could be a problem for the case where an hwif is on a * dual interface that requires serialization (eg. cmd640) and another * hwif using one of the same irqs is initialized beforehand. * * This routine detects and reports such situations, but does not fix them. */static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match){ ide_hwif_t *m = *match; if (m && m->hwgroup && m->hwgroup != new->hwgroup) { if (!new->hwgroup) return; printk("%s: potential irq problem with %s and %s\n", hwif->name, new->name, m->name); } if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ *match = new;}#endif /* MAX_HWIFS > 1 *//* * init request queue */static void ide_init_queue(ide_drive_t *drive){ request_queue_t *q = &drive->queue; q->queuedata = HWGROUP(drive); blk_init_queue(q, do_ide_request);}/* * This routine sets up the irq for an ide interface, and creates a new * hwgroup for the irq/hwif if none was previously assigned. * * Much of the code is for correctly detecting/handling irq sharing * and irq serialization situations. This is somewhat complex because * it handles static as well as dynamic (PCMCIA) IDE interfaces. * * The SA_INTERRUPT in sa_flags means ide_intr() is always entered with * interrupts completely disabled. This can be bad for interrupt latency, * but anything else has led to problems on some machines. We re-enable * interrupts as much as we can safely do in most places. */static int init_irq (ide_hwif_t *hwif){ unsigned long flags; unsigned int index; ide_hwgroup_t *hwgroup, *new_hwgroup; ide_hwif_t *match = NULL; /* Allocate the buffer and potentially sleep first */ new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL); save_flags(flags); /* all CPUs */ cli(); /* all CPUs */ hwif->hwgroup = NULL;#if MAX_HWIFS > 1 /* * Group up with any other hwifs that share our irq(s). */ for (index = 0; index < MAX_HWIFS; index++) { ide_hwif_t *h = &ide_hwifs[index]; if (h->hwgroup) { /* scan only initialized hwif's */ if (hwif->irq == h->irq) { hwif->sharing_irq = h->sharing_irq = 1; if (hwif->chipset != ide_pci || h->chipset != ide_pci) { save_match(hwif, h, &match); } } if (hwif->serialized) { if (hwif->mate && hwif->mate->irq == h->irq) save_match(hwif, h, &match); } if (h->serialized) { if (h->mate && hwif->irq == h->mate->irq) save_match(hwif, h, &match); } } }#endif /* MAX_HWIFS > 1 */ /* * If we are still without a hwgroup, then form a new one */ if (match) { hwgroup = match->hwgroup; if(new_hwgroup) kfree(new_hwgroup); } else { hwgroup = new_hwgroup; if (!hwgroup) { restore_flags(flags); /* all CPUs */ return 1; } memset(hwgroup, 0, sizeof(ide_hwgroup_t)); hwgroup->hwif = hwif->next = hwif; hwgroup->rq = NULL; hwgroup->handler = NULL; hwgroup->drive = NULL; hwgroup->busy = 0; init_timer(&hwgroup->timer); hwgroup->timer.function = &ide_timer_expiry; hwgroup->timer.data = (unsigned long) hwgroup; } /* * Allocate the irq, if not already obtained for another hwif */ if (!match || match->irq != hwif->irq) {#ifdef CONFIG_IDEPCI_SHARE_IRQ int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_SHIRQ : SA_INTERRUPT;#else /* !CONFIG_IDEPCI_SHARE_IRQ */ int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;#endif /* CONFIG_IDEPCI_SHARE_IRQ */ if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) { if (!match) kfree(hwgroup); restore_flags(flags); /* all CPUs */ return 1; } } /* * Everything is okay, so link us into the hwgroup */ hwif->hwgroup = hwgroup; hwif->next = hwgroup->hwif->next; hwgroup->hwif->next = hwif; for (index = 0; index < MAX_DRIVES; ++index) { ide_drive_t *drive = &hwif->drives[index]; if (!drive->present) continue; if (!hwgroup->drive) hwgroup->drive = drive; drive->next = hwgroup->drive->next; hwgroup->drive->next = drive; ide_init_queue(drive); } if (!hwgroup->hwif) { hwgroup->hwif = HWIF(hwgroup->drive);#ifdef DEBUG printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name);#endif } restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->io_ports[IDE_DATA_OFFSET]+7, hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);#elif defined(__sparc__) printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->io_ports[IDE_DATA_OFFSET]+7, hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq));#else printk("%s at %p on irq 0x%08x", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);#endif /* __mc68000__ && CONFIG_APUS */ if (match) printk(" (%sed with %s)", hwif->sharing_irq ? "shar" : "serializ", match->name); printk("\n"); return 0;}/* * init_gendisk() (as opposed to ide_geninit) is called for each major device, * after probing for drives, to allocate partition tables and other data * structures needed for the routines in genhd.c. ide_geninit() gets called * somewhat later, during the partition check. */static void init_gendisk (ide_hwif_t *hwif){ struct gendisk *gd; unsigned int unit, units, minors; int *bs, *max_sect, *max_ra; extern devfs_handle_t ide_devfs_handle; /* figure out maximum drive number on the interface */ for (units = MAX_DRIVES; units > 0; --units) { if (hwif->drives[units-1].present) break; } minors = units * (1<<PARTN_BITS); gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL); gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL); gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL); bs = kmalloc (minors*sizeof(int), GFP_KERNEL); max_sect = kmalloc (minors*sizeof(int), GFP_KERNEL); max_ra = kmalloc (minors*sizeof(int), GFP_KERNEL); memset(gd->part, 0, minors * sizeof(struct hd_struct)); /* cdroms and msdos f/s are examples of non-1024 blocksizes */ blksize_size[hwif->major] = bs; max_sectors[hwif->major] = max_sect; max_readahead[hwif->major] = max_ra; for (unit = 0; unit < minors; ++unit) { *bs++ = BLOCK_SIZE;#ifdef CONFIG_BLK_DEV_PDC4030 *max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : 255);#else /* IDE can do up to 128K per request. */ *max_sect++ = 255;#endif *max_ra++ = vm_max_readahead; } for (unit = 0; unit < units; ++unit) hwif->drives[unit].part = &gd->part[unit << PARTN_BITS]; gd->major = hwif->major; /* our major device number */ gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */ gd->minor_shift = PARTN_BITS; /* num bits for partitions */ gd->max_p = 1<<PARTN_BITS; /* 1 + max partitions / drive */ gd->nr_real = units; /* current num real drives */ gd->real_devices= hwif; /* ptr to internal data */ gd->next = NULL; /* linked list of major devs */ gd->fops = ide_fops; /* file operations */ gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL); gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL); if (gd->de_arr) memset (gd->de_arr, 0, sizeof *gd->de_arr * units); if (gd->flags) memset (gd->flags, 0, sizeof *gd->flags * units); hwif->gd = gd; add_gendisk(gd); for (unit = 0; unit < units; ++unit) { if (hwif->drives[unit].present) { char name[64]; ide_add_generic_settings(hwif->drives + unit); hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); sprintf (name, "host%d/bus%d/target%d/lun%d", (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, hwif->channel, unit, hwif->drives[unit].lun); hwif->drives[unit].de = devfs_mk_dir (ide_devfs_handle, name, NULL); } }}static int hwif_init (ide_hwif_t *hwif){ if (!hwif->present) return 0; if (!hwif->irq) { if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { printk("%s: DISABLED, NO IRQ\n", hwif->name); return (hwif->present = 0); } }#ifdef CONFIG_BLK_DEV_HD if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) { printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name); return (hwif->present = 0); }#endif /* CONFIG_BLK_DEV_HD */ hwif->present = 0; /* we set it back to 1 if all is ok below */ if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) { printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major); return (hwif->present = 0); } if (init_irq(hwif)) { int i = hwif->irq; /* * It failed to initialise. Find the default IRQ for * this port and try that. */ if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i); (void) unregister_blkdev (hwif->major, hwif->name); return (hwif->present = 0); } if (init_irq(hwif)) { printk("%s: probed IRQ %d and default IRQ %d failed.\n", hwif->name, i, hwif->irq); (void) unregister_blkdev (hwif->major, hwif->name); return (hwif->present = 0); } printk("%s: probed IRQ %d failed, using default.\n", hwif->name, hwif->irq); } init_gendisk(hwif); blk_dev[hwif->major].data = hwif; blk_dev[hwif->major].queue = ide_get_queue; read_ahead[hwif->major] = 8; /* (4kB) */ hwif->present = 1; /* success */#if (DEBUG_SPINLOCK > 0){ static int done = 0; if (!done++) printk("io_request_lock is %p\n", &io_request_lock); /* FIXME */}#endif return hwif->present;}int ideprobe_init (void);static ide_module_t ideprobe_module = { IDE_PROBE_MODULE, ideprobe_init, NULL};int ideprobe_init (void){ unsigned int index; int probe[MAX_HWIFS]; MOD_INC_USE_COUNT; memset(probe, 0, MAX_HWIFS * sizeof(int)); for (index = 0; index < MAX_HWIFS; ++index) probe[index] = !ide_hwifs[index].present; /* * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports */ for (index = 0; index < MAX_HWIFS; ++index) if (probe[index]) probe_hwif(&ide_hwifs[index]); for (index = 0; index < MAX_HWIFS; ++index) if (probe[index]) hwif_init(&ide_hwifs[index]); if (!ide_probe) ide_probe = &ideprobe_module; MOD_DEC_USE_COUNT; return 0;}#ifdef MODULEint init_module (void){ unsigned int index; for (index = 0; index < MAX_HWIFS; ++index) ide_unregister(index); ideprobe_init(); create_proc_ide_interfaces(); return 0;}void cleanup_module (void){ ide_probe = NULL;}MODULE_LICENSE("GPL");#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -