patch-2.3.40 linux/drivers/block/ide.c

Next file: linux/drivers/block/loop.c
Previous file: linux/drivers/block/ide-tape.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide.c linux/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	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 @@
 	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 @@
  * (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 @@
  * 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 @@
 		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 @@
 
 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 @@
 				hwgroup->busy = 0;
 		}
 	}
-	ide_do_request(hwgroup);
+	ide_do_request(hwgroup, 0);
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
@@ -1593,7 +1615,7 @@
 	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 @@
 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 @@
 			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 @@
 		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 @@
 		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);
@@ -2677,6 +2705,7 @@
  *				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").
@@ -2727,6 +2756,14 @@
 	}
 #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 ();
 
 	/*
@@ -3060,7 +3097,7 @@
 	if (pci_present())
 	{
 #ifdef CONFIG_BLK_DEV_IDEPCI
-		ide_scan_pcibus();
+		ide_scan_pcibus(ide_scan_direction);
 #else
 #ifdef CONFIG_BLK_DEV_RZ1000
 		{
@@ -3366,7 +3403,6 @@
 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);
@@ -3448,6 +3484,7 @@
 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");
@@ -3459,6 +3496,12 @@
 	initializing = 1;
 	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;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)