patch-2.0.31 linux/drivers/block/ide.c
Next file: linux/drivers/block/ide.h
Previous file: linux/drivers/block/ide-floppy.c
Back to the patch index
Back to the overall index
- Lines: 485
- Date:
Mon Aug 4 11:45:55 1997
- Orig file:
v2.0.30/linux/drivers/block/ide.c
- Orig date:
Tue Nov 19 06:21:06 1996
diff -u --recursive --new-file v2.0.30/linux/drivers/block/ide.c linux/drivers/block/ide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide.c Version 5.52 Sep 24, 1996
+ * linux/drivers/block/ide.c Version 5.53 Jun 24, 1997
*
* Copyright (C) 1994-1996 Linus Torvalds & authors (see below)
*/
@@ -261,6 +261,17 @@
* change delay_10ms() to delay_50ms() to fix problems
* Version 5.52 fix incorrect invalidation of removable devices
* add "hdx=slow" command line option
+ * Version 5.53 add ATAPI floppy drive support
+ * change default media for type 0 to floppy
+ * add support for Exabyte Nest
+ * add missing set_blocksize() in revalidate_disk()
+ * handle bad status bit sequencing in ide_wait_stat()
+ * support partition table translations with 255 heads
+ * probe all interfaces by default
+ * add probe for the i82371AB chipset
+ * acknowledge media change on removable drives
+ * add work-around for BMI drives
+ * remove "LBA" from boot messages
*
* Some additional driver compile-time options are in ide.h
*
@@ -367,7 +378,6 @@
/* fill in any non-zero initial values */
hwif->index = index;
- hwif->noprobe = (index > 1);
hwif->io_base = default_io_base[index];
hwif->ctl_port = hwif->io_base ? hwif->io_base+0x206 : 0x000;
#ifdef CONFIG_BLK_DEV_HD
@@ -536,6 +546,29 @@
}
/*
+ * The following routines are mainly used by the ATAPI drivers.
+ *
+ * These routines will round up any request for an odd number of bytes,
+ * so if an odd bytecount is specified, be sure that there's at least one
+ * extra byte allocated for the buffer.
+ */
+void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
+{
+ ++bytecount;
+ ide_input_data (drive, buffer, bytecount / 4);
+ if ((bytecount & 0x03) >= 2)
+ insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
+}
+
+void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
+{
+ ++bytecount;
+ ide_output_data (drive, buffer, bytecount / 4);
+ if ((bytecount & 0x03) >= 2)
+ outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
+}
+
+/*
* This should get invoked any time we exit the driver to
* wait for an interrupt response from a drive. handler() points
* at the appropriate code to handle the next interrupt, and a
@@ -593,6 +626,10 @@
if (!drive->present)
return 0;
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+ if (drive->media == ide_floppy)
+ return idefloppy_capacity(drive);
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
if (drive->media != ide_disk)
return 0x7fffffff; /* cdrom or tape */
drive->select.b.lba = 0;
@@ -625,8 +662,13 @@
if (drive->present && drive->media == ide_tape)
idetape_setup(drive);
#endif /* CONFIG_BLK_DEV_IDETAPE */
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+ if (drive->present && drive->media == ide_floppy)
+ idefloppy_setup(drive);
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
drive->part[0].nr_sects = current_capacity(drive);
- if (!drive->present || drive->media != ide_disk) {
+ if (!drive->present || (drive->media != ide_disk && drive->media != ide_floppy) ||
+ !drive->part[0].nr_sects) {
drive->part[0].start_sect = -1; /* skip partition check */
}
}
@@ -1005,6 +1047,8 @@
rq->errors = ERROR_MAX;
else if (err & TRK0_ERR) /* help it find track zero */
rq->errors |= ERROR_RECAL;
+ else if (err & MC_ERR)
+ drive->special.b.mc = 1;
}
if ((stat & DRQ_STAT) && rq->cmd != WRITE)
try_to_flush_leftover_data(drive);
@@ -1017,9 +1061,20 @@
if (drive->media == ide_tape) {
rq->errors = 0;
idetape_end_request(0, HWGROUP(drive));
- }
- else
+ } else
#endif /* CONFIG_BLK_DEV_IDETAPE */
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+ if (drive->media == ide_floppy) {
+ rq->errors = 0;
+ idefloppy_end_request(0, HWGROUP(drive));
+ } else
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
+#ifdef CONFIG_BLK_DEV_IDESCSI
+ if (drive->media == ide_scsi) {
+ rq->errors = 0;
+ idescsi_end_request(0, HWGROUP(drive));
+ } else
+#endif /* CONFIG_BLK_DEV_IDESCSI */
ide_end_request(0, HWGROUP(drive));
}
else {
@@ -1230,6 +1285,19 @@
}
/*
+ * mc_intr() is invoked on completion of a WIN_ACKMC cmd.
+ */
+static void mc_intr (ide_drive_t *drive)
+{
+ byte stat = GET_STAT();
+
+ sti();
+ if (!OK_STAT(stat,READY_STAT,BAD_STAT))
+ ide_error(drive, "mc_intr", stat);
+ drive->special.b.mc = 0;
+}
+
+/*
* drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
*/
static void drive_cmd_intr (ide_drive_t *drive)
@@ -1265,7 +1333,7 @@
#endif
if (s->b.set_geometry) {
s->b.set_geometry = 0;
- if (drive->media == ide_disk) {
+ if (drive->media == ide_disk && !drive->no_geom) {
OUT_BYTE(drive->sect,IDE_SECTOR_REG);
OUT_BYTE(drive->cyl,IDE_LCYL_REG);
OUT_BYTE(drive->cyl>>8,IDE_HCYL_REG);
@@ -1291,6 +1359,10 @@
ide_cmd(drive, WIN_SETMULT, drive->mult_req, &set_multmode_intr);
} else
drive->mult_req = 0;
+ } else if (s->b.mc) {
+ s->b.mc = 0;
+ if (drive->media == ide_disk && !IS_PROMISE_DRIVE)
+ ide_cmd(drive, WIN_ACKMC, drive->sect, &mc_intr);
} else if (s->all) {
int special = s->all;
s->all = 0;
@@ -1314,27 +1386,24 @@
byte stat;
unsigned long flags;
-test:
- udelay(1); /* spec allows drive 400ns to change "BUSY" */
- if (OK_STAT((stat = GET_STAT()), good, bad))
- return 0; /* fast exit for most frequent case */
- if (!(stat & BUSY_STAT)) {
- ide_error(drive, "status error", stat);
- return 1;
- }
-
- save_flags(flags);
- sti();
- timeout += jiffies;
- do {
- if (!((stat = GET_STAT()) & BUSY_STAT)) {
- restore_flags(flags);
- goto test;
+ udelay(1); /* spec allows drive 400ns to assert "BUSY" */
+ if ((stat = GET_STAT()) & BUSY_STAT) {
+ save_flags(flags);
+ sti();
+ timeout += jiffies;
+ while ((stat = GET_STAT()) & BUSY_STAT) {
+ if (jiffies > timeout) {
+ restore_flags(flags);
+ ide_error(drive, "status timeout", stat);
+ return 1;
+ }
}
- } while (jiffies <= timeout);
-
- restore_flags(flags);
- ide_error(drive, "status timeout", GET_STAT());
+ restore_flags(flags);
+ }
+ udelay(1); /* allow status to settle, then read it again */
+ if (OK_STAT((stat = GET_STAT()), good, bad))
+ return 0;
+ ide_error(drive, "status error", stat);
return 1;
}
@@ -1532,6 +1601,16 @@
idetape_do_request (drive, rq, block);
return;
#endif /* CONFIG_BLK_DEV_IDETAPE */
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+ case ide_floppy:
+ idefloppy_do_request (drive, rq, block);
+ return;
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
+#ifdef CONFIG_BLK_DEV_IDESCSI
+ case ide_scsi:
+ idescsi_do_request (drive, rq, block);
+ return;
+#endif /* CONFIG_BLK_DEV_IDESCSI */
default:
printk("%s: media type %d not supported\n",
@@ -1588,6 +1667,7 @@
if (rq != NULL && rq->rq_status != RQ_INACTIVE)
goto got_rq;
} while ((hwif = hwif->next) != hwgroup->next_hwif);
+ hwgroup->active = 0;
return; /* no work left for this hwgroup */
}
got_rq:
@@ -1612,6 +1692,7 @@
if (hwgroup->handler == NULL) {
ide_hwif_t *hgif = hwgroup->hwif;
ide_hwif_t *hwif = hgif;
+ hwgroup->active = 1;
do {
disable_irq(hwif->irq);
} while ((hwif = hwif->next) != hgif);
@@ -1859,13 +1940,8 @@
if (cur_rq == NULL || action == ide_preempt) {
rq->next = cur_rq;
bdev->current_request = rq;
- if (action == ide_preempt) {
+ if (action == ide_preempt)
HWGROUP(drive)->rq = NULL;
- } else
- if (HWGROUP(drive)->rq == NULL) { /* is this necessary (?) */
- bdev->request_fn();
- cli();
- }
} else {
if (action == ide_wait || action == ide_end) {
while (cur_rq->next != NULL) /* find end of list */
@@ -1874,6 +1950,10 @@
rq->next = cur_rq->next;
cur_rq->next = rq;
}
+ if (!HWGROUP(drive)->active) {
+ do_hwgroup_request(HWGROUP(drive));
+ cli();
+ }
if (action == ide_wait && rq->rq_status != RQ_INACTIVE)
down(&sem); /* wait for it to be serviced */
restore_flags(flags);
@@ -1901,6 +1981,14 @@
if (drive->media == ide_tape)
return idetape_blkdev_open (inode, filp, drive);
#endif /* CONFIG_BLK_DEV_IDETAPE */
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+ if (drive->media == ide_floppy)
+ return idefloppy_open (inode, filp, drive);
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
+#ifdef CONFIG_BLK_DEV_IDESCSI
+ if (drive->media == ide_scsi)
+ return idescsi_open (inode, filp, drive);
+#endif /* CONFIG_BLK_DEV_IDESCSI */
if (drive->removable && drive->usage == 1) {
byte door_lock[] = {WIN_DOORLOCK,0,0,0};
struct request rq;
@@ -1940,6 +2028,18 @@
return;
}
#endif /* CONFIG_BLK_DEV_IDETAPE */
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+ if (drive->media == ide_floppy) {
+ idefloppy_release (inode, file, drive);
+ return;
+ }
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
+#ifdef CONFIG_BLK_DEV_IDESCSI
+ if (drive->media == ide_scsi) {
+ idescsi_ide_release (inode, file, drive);
+ return;
+ }
+#endif /* CONFIG_BLK_DEV_IDESCSI */
if (drive->removable && !drive->usage) {
byte door_unlock[] = {WIN_DOORUNLOCK,0,0,0};
struct request rq;
@@ -1985,13 +2085,14 @@
fsync_dev (devp);
invalidate_inodes (devp);
invalidate_buffers (devp);
+ set_blocksize(devp, 1024);
}
drive->part[p].start_sect = 0;
drive->part[p].nr_sects = 0;
};
drive->part[0].nr_sects = current_capacity(drive);
- if (drive->media != ide_disk)
+ if ((drive->media != ide_disk && drive->media != ide_floppy) || !drive->part[0].nr_sects)
drive->part[0].start_sect = -1;
resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit);
@@ -2029,7 +2130,7 @@
case HDIO_GETGEO:
{
struct hd_geometry *loc = (struct hd_geometry *) arg;
- if (!loc || drive->media != ide_disk) return -EINVAL;
+ if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;
err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
if (err) return err;
put_user(drive->bios_head, (byte *) &loc->heads);
@@ -2223,6 +2324,14 @@
if (drive->media == ide_tape)
return idetape_blkdev_ioctl(drive, inode, file, cmd, arg);
#endif /* CONFIG_BLK_DEV_IDETAPE */
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+ if (drive->media == ide_floppy)
+ return idefloppy_ioctl(drive, inode, file, cmd, arg);
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
+#ifdef CONFIG_BLK_DEV_IDESCSI
+ if (drive->media == ide_scsi)
+ return idescsi_ioctl(drive, inode, file, cmd, arg);
+#endif /* CONFIG_BLK_DEV_IDESCSI */
return -EPERM;
}
}
@@ -2237,6 +2346,10 @@
if (drive->media == ide_cdrom)
return ide_cdrom_check_media_change (drive);
#endif /* CONFIG_BLK_DEV_IDECD */
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+ if (drive->media == ide_floppy)
+ return idefloppy_media_change (drive);
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
if (drive->removable) /* for disks */
return 1; /* always assume it was changed */
return 0;
@@ -2307,6 +2420,9 @@
ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap);
ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap);
+ if (strstr(id->model, "E X A B Y T E N E S T"))
+ return;
+
#ifdef CONFIG_BLK_DEV_IDEATAPI
/*
* Check for an ATAPI device
@@ -2322,7 +2438,22 @@
}
#endif /* CONFIG_BLK_DEV_PROMISE */
switch (type) {
- case 0: /* Early cdrom models used zero */
+ case 0:
+ if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP"))
+ printk("cdrom or floppy?, assuming ");
+ if (drive->media != ide_cdrom) {
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+ printk("FLOPPY drive\n");
+ drive->media = ide_floppy;
+ if (idefloppy_identify_device(drive, id))
+ drive->present = 1;
+ return;
+#else
+ printk("FLOPPY ");
+ break;
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
+ }
+ /* Early cdrom models used zero */
case 5:
#ifdef CONFIG_BLK_DEV_IDECD
printk ("CDROM drive\n");
@@ -2361,8 +2492,15 @@
printk("Type %d - Unknown device\n", type);
return;
}
+#ifdef CONFIG_BLK_DEV_IDESCSI
+ printk("drive - enabling SCSI emulation\n");
+ drive->media = ide_scsi;
+ drive->present = 1;
+ idescsi_setup(drive);
+#else
drive->present = 0;
printk("- not supported by this kernel\n");
+#endif /* CONFIG_BLK_DEV_IDESCSI */
return;
}
#endif /* CONFIG_BLK_DEV_IDEATAPI */
@@ -2381,7 +2519,7 @@
return;
}
}
-
+
drive->media = ide_disk;
/* Extract geometry if we did not already have one for the drive */
if (!drive->present) {
@@ -2431,9 +2569,13 @@
(void) current_capacity (drive); /* initialize LBA selection */
- printk ("%s: %.40s, %ldMB w/%dkB Cache, %sCHS=%d/%d/%d",
+ if (!strncmp(id->model, "BMI ", 4) &&
+ strstr(id->model, " ENHANCED IDE ") &&
+ drive->select.b.lba)
+ drive->no_geom = 1;
+
+ printk ("%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d",
drive->name, id->model, current_capacity(drive)/2048L, id->buf_size/2,
- drive->select.b.lba ? "LBA, " : "",
drive->bios_cyl, drive->bios_head, drive->bios_sect);
drive->mult_count = 0;
@@ -2607,6 +2749,34 @@
return rc;
}
+static void enable_nest (ide_drive_t *drive)
+{
+ unsigned long timeout;
+
+ printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model);
+ SELECT_DRIVE(HWIF(drive), drive);
+ delay_50ms();
+ OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
+ timeout = jiffies + WAIT_WORSTCASE;
+ do {
+ if (jiffies > timeout) {
+ printk("failed (timeout)\n");
+ return;
+ }
+ delay_50ms();
+ } while (GET_STAT() & BUSY_STAT);
+ delay_50ms();
+ if (!OK_STAT(GET_STAT(), 0, BAD_STAT))
+ printk("failed (status = 0x%02x)\n", GET_STAT());
+ else
+ printk("success\n");
+ if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */
+#ifdef CONFIG_BLK_DEV_IDEATAPI
+ (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */
+#endif /* CONFIG_BLK_DEV_IDEATAPI */
+ }
+}
+
/*
* probe_for_drive() tests for existence of a given drive using do_probe().
*
@@ -2622,6 +2792,8 @@
(void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */
#endif /* CONFIG_BLK_DEV_IDEATAPI */
}
+ if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T"))
+ enable_nest(drive);
if (!drive->present)
return 0; /* drive not found */
if (drive->id == NULL) { /* identification failed? */
@@ -3250,6 +3422,7 @@
else
hwgroup->drive = &hwif->drives[1];
hwgroup->poll_timeout = 0;
+ hwgroup->active = 0;
init_timer(&hwgroup->timer);
hwgroup->timer.function = &timer_expiry;
hwgroup->timer.data = (unsigned long) hwgroup;
@@ -3353,6 +3526,7 @@
*/
ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371_0, &ide_init_triton, 1);
ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, &ide_init_triton, 0);
+ ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, &ide_init_triton, 0);
#endif /* CONFIG_BLK_DEV_TRITON */
}
#endif /* CONFIG_PCI */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov