diff options
Diffstat (limited to 'drivers/block/ide.c')
-rw-r--r-- | drivers/block/ide.c | 118 |
1 files changed, 80 insertions, 38 deletions
diff --git a/drivers/block/ide.c b/drivers/block/ide.c index 5bdb1d477..873f57cc9 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide.c Version 6.21 November 9, 1999 + * linux/drivers/block/ide.c Version 6.30 Dec 28, 1999 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -108,6 +108,7 @@ * Specifically Promise's PDC20262 chipset. * Version 6.21 Fixing/Fixed SMP spinlock issue with insight from an old * hat that clarified original low level driver design. + * Version 6.30 Added SMP support; fixed multmode issues. -ml * * Some additional driver compile-time options are in ./include/linux/ide.h * @@ -116,8 +117,8 @@ * */ -#define REVISION "Revision: 6.21" -#define VERSION "Id: ide.c 6.21 1999/11/10" +#define REVISION "Revision: 6.30" +#define VERSION "Id: ide.c 6.30 1999/12/28" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -169,6 +170,10 @@ static int idebus_parameter; /* holds the "idebus=" parameter */ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ static int initializing; /* set while initializing built-in drivers */ +#ifdef CONFIG_BLK_DEV_IDEPCI +static int ide_scan_direction = 0; /* HELLO, comment me!! */ +#endif /* CONFIG_BLK_DEV_IDEPCI */ + #if defined(__mc68000__) || defined(CONFIG_APUS) /* * ide_lock is used by the Atari code to obtain access to the IDE interrupt, @@ -542,22 +547,28 @@ unsigned long current_capacity (ide_drive_t *drive) return 0; } +extern struct block_device_operations ide_fops[]; /* - * ide_geninit() is called exactly *once* for each major, from genhd.c, - * at the beginning of the initial partition check for the drives. + * ide_geninit() is called exactly *once* for each interface. */ -void ide_geninit (struct gendisk *gd) +void ide_geninit (ide_hwif_t *hwif) { unsigned int unit; - ide_hwif_t *hwif = gd->real_devices; + struct gendisk *gd = hwif->gd; - for (unit = 0; unit < gd->nr_real; ++unit) { + for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; - drive->part[0].nr_sects = current_capacity(drive); - if (!drive->present || (drive->media != ide_disk && drive->media != ide_floppy) || - drive->driver == NULL || !drive->part[0].nr_sects) - drive->part[0].start_sect = -1; /* skip partition check */ + if (!drive->present) + continue; + if (drive->media!=ide_disk && drive->media!=ide_floppy) + continue; + register_disk(gd,MKDEV(hwif->major,unit<<PARTN_BITS), +#ifdef CONFIG_BLK_DEV_ISAPNP + (drive->forced_geom && drive->noprobe) ? 1 : +#endif /* CONFIG_BLK_DEV_ISAPNP */ + 1<<PARTN_BITS, ide_fops, + current_capacity(drive)); } } @@ -669,7 +680,7 @@ static void pre_reset (ide_drive_t *drive) * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, * we set a timer to poll at 50ms intervals. */ -static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) +static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) { unsigned int unit; unsigned long flags; @@ -1213,7 +1224,7 @@ repeat: * the driver. This makes the driver much more friendlier to shared IRQs * than previous designs, while remaining 100% (?) SMP safe and capable. */ -static void ide_do_request (ide_hwgroup_t *hwgroup) +static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) { struct blk_dev_struct *bdev; ide_drive_t *drive; @@ -1272,14 +1283,25 @@ static void ide_do_request (ide_hwgroup_t *hwgroup) drive->service_start = jiffies; bdev = &blk_dev[hwif->major]; - if( bdev->request_queue.plugged ) /* FIXME: paranoia */ + if ( bdev->request_queue.plugged ) /* FIXME: paranoia */ printk("%s: Huh? nuking plugged queue\n", drive->name); bdev->request_queue.current_request = hwgroup->rq = drive->queue.current_request; + /* + * Some systems have trouble with IDE IRQs arriving while + * the driver is still setting things up. So, here we disable + * the IRQ used by this interface while the request is being started. + * This may look bad at first, but pretty much the same thing + * happens anyway when any interrupt comes in, IDE or otherwise + * -- the kernel masks the IRQ while it is being handled. + */ + if (hwif->irq != masked_irq) + disable_irq_nosync(hwif->irq); spin_unlock(&io_request_lock); - if (!hwif->serialized) /* play it safe with buggy hardware */ - ide__sti(); + ide__sti(); /* allow other IRQs while we start this request */ startstop = start_request(drive); spin_lock_irq(&io_request_lock); + if (hwif->irq != masked_irq) + enable_irq(hwif->irq); if (startstop == ide_stopped) hwgroup->busy = 0; } @@ -1297,69 +1319,69 @@ request_queue_t *ide_get_queue (kdev_t dev) void do_ide0_request (request_queue_t *q) { - ide_do_request (ide_hwifs[0].hwgroup); + ide_do_request (ide_hwifs[0].hwgroup, 0); } #if MAX_HWIFS > 1 void do_ide1_request (request_queue_t *q) { - ide_do_request (ide_hwifs[1].hwgroup); + ide_do_request (ide_hwifs[1].hwgroup, 0); } #endif /* MAX_HWIFS > 1 */ #if MAX_HWIFS > 2 void do_ide2_request (request_queue_t *q) { - ide_do_request (ide_hwifs[2].hwgroup); + ide_do_request (ide_hwifs[2].hwgroup, 0); } #endif /* MAX_HWIFS > 2 */ #if MAX_HWIFS > 3 void do_ide3_request (request_queue_t *q) { - ide_do_request (ide_hwifs[3].hwgroup); + ide_do_request (ide_hwifs[3].hwgroup, 0); } #endif /* MAX_HWIFS > 3 */ #if MAX_HWIFS > 4 void do_ide4_request (request_queue_t *q) { - ide_do_request (ide_hwifs[4].hwgroup); + ide_do_request (ide_hwifs[4].hwgroup, 0); } #endif /* MAX_HWIFS > 4 */ #if MAX_HWIFS > 5 void do_ide5_request (request_queue_t *q) { - ide_do_request (ide_hwifs[5].hwgroup); + ide_do_request (ide_hwifs[5].hwgroup, 0); } #endif /* MAX_HWIFS > 5 */ #if MAX_HWIFS > 6 void do_ide6_request (request_queue_t *q) { - ide_do_request (ide_hwifs[6].hwgroup); + ide_do_request (ide_hwifs[6].hwgroup, 0); } #endif /* MAX_HWIFS > 6 */ #if MAX_HWIFS > 7 void do_ide7_request (request_queue_t *q) { - ide_do_request (ide_hwifs[7].hwgroup); + ide_do_request (ide_hwifs[7].hwgroup, 0); } #endif /* MAX_HWIFS > 7 */ #if MAX_HWIFS > 8 void do_ide8_request (request_queue_t *q) { - ide_do_request (ide_hwifs[8].hwgroup); + ide_do_request (ide_hwifs[8].hwgroup, 0); } #endif /* MAX_HWIFS > 8 */ #if MAX_HWIFS > 9 void do_ide9_request (request_queue_t *q) { - ide_do_request (ide_hwifs[9].hwgroup); + ide_do_request (ide_hwifs[9].hwgroup, 0); } #endif /* MAX_HWIFS > 9 */ @@ -1445,7 +1467,7 @@ void ide_timer_expiry (unsigned long data) hwgroup->busy = 0; } } - ide_do_request(hwgroup); + ide_do_request(hwgroup, 0); spin_unlock_irqrestore(&io_request_lock, flags); } @@ -1593,7 +1615,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs) if (startstop == ide_stopped) { if (hwgroup->handler == NULL) { /* paranoia */ hwgroup->busy = 0; - ide_do_request(hwgroup); + ide_do_request(hwgroup, hwif->irq); } else { printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name); } @@ -1608,6 +1630,9 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs) ide_drive_t *get_info_ptr (kdev_t i_rdev) { int major = MAJOR(i_rdev); +#if 0 + int minor = MINOR(i_rdev) & PARTN_MASK; +#endif unsigned int h; for (h = 0; h < MAX_HWIFS; ++h) { @@ -1616,7 +1641,11 @@ ide_drive_t *get_info_ptr (kdev_t i_rdev) unsigned unit = DEVICE_NR(i_rdev); if (unit < MAX_DRIVES) { ide_drive_t *drive = &hwif->drives[unit]; +#if 0 + if ((drive->present) && (drive->part[minor].nr_sects)) +#else if (drive->present) +#endif return drive; } break; @@ -1698,7 +1727,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio rq->next = cur_rq->next; cur_rq->next = rq; } - ide_do_request(hwgroup); + ide_do_request(hwgroup, 0); spin_unlock_irqrestore(&io_request_lock, flags); if (action == ide_wait) { down(&sem); /* wait for it to be serviced */ @@ -1751,11 +1780,10 @@ int ide_revalidate_disk (kdev_t i_rdev) drive->part[p].nr_sects = 0; }; - drive->part[0].nr_sects = current_capacity(drive); - if ((drive->media != ide_disk && drive->media != ide_floppy) || - drive->driver == NULL || !drive->part[0].nr_sects) - drive->part[0].start_sect = -1; - resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit); + grok_partitions(HWIF(drive)->gd, drive->select.b.unit, + (drive->media != ide_disk && + drive->media != ide_floppy) ? 1 : 1<<PARTN_BITS, + current_capacity(drive)); drive->busy = 0; wake_up(&drive->wqueue); @@ -1846,7 +1874,6 @@ static int ide_release (struct inode * inode, struct file * file) ide_drive_t *drive; if ((drive = get_info_ptr(inode->i_rdev)) != NULL) { - fsync_dev(inode->i_rdev); drive->usage--; if (drive->driver != NULL) DRIVER(drive)->release(inode, file, drive); @@ -2678,6 +2705,7 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m * for chipsets that are ATA-66 capable, but * the ablity to bit test for detection is * currently unknown. + * "ide=reverse" : Formerly called to pci sub-system, but now local. * * "splitfifo=betweenChan" * : FIFO Configuration of VIA 82c586(<nothing>,"A"or"B"). @@ -2728,6 +2756,14 @@ int __init ide_setup (char *s) } #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ +#ifdef CONFIG_BLK_DEV_IDEPCI + if (!strcmp(s, "ide=reverse")) { + ide_scan_direction = 1; + printk("ide: Enabled support for IDE inverse scan order.\n"); + return 0; + } +#endif /* CONFIG_BLK_DEV_IDEPCI */ + init_ide_data (); /* @@ -3061,7 +3097,7 @@ static void __init probe_for_hwifs (void) if (pci_present()) { #ifdef CONFIG_BLK_DEV_IDEPCI - ide_scan_pcibus(); + ide_scan_pcibus(ide_scan_direction); #else #ifdef CONFIG_BLK_DEV_RZ1000 { @@ -3367,7 +3403,6 @@ EXPORT_SYMBOL(ide_spin_wait_hwgroup); EXPORT_SYMBOL(drive_is_flashcard); EXPORT_SYMBOL(ide_timer_expiry); EXPORT_SYMBOL(ide_intr); -EXPORT_SYMBOL(ide_geninit); EXPORT_SYMBOL(ide_fops); EXPORT_SYMBOL(ide_get_queue); EXPORT_SYMBOL(do_ide0_request); @@ -3449,6 +3484,7 @@ EXPORT_SYMBOL(current_capacity); int __init ide_init (void) { static char banner_printed = 0; + int i; if (!banner_printed) { printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); @@ -3461,6 +3497,12 @@ int __init ide_init (void) ide_init_builtin_drivers(); initializing = 0; + for (i = 0; i < MAX_HWIFS; ++i) { + ide_hwif_t *hwif = &ide_hwifs[i]; + if (hwif->present) + ide_geninit(hwif); + } + return 0; } |