patch-2.3.1 linux/drivers/block/ide.c
Next file: linux/drivers/block/ide.h
Previous file: linux/drivers/block/ide-tape.c
Back to the patch index
Back to the overall index
- Lines: 838
- Date:
Thu May 13 11:31:31 1999
- Orig file:
v2.3.0/linux/drivers/block/ide.c
- Orig date:
Mon May 3 09:34:51 1999
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide.c linux/drivers/block/ide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide.c Version 6.18 August 16, 1998
+ * linux/drivers/block/ide.c Version 6.19 January 29, 1999
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
@@ -92,6 +92,11 @@
* Version 6.16 fixed various bugs; even more SMP friendly
* Version 6.17 fix for newest EZ-Drive problem
* Version 6.18 default unpartitioned-disk translation now "BIOS LBA"
+ * Version 6.19 Re-design for a UNIFORM driver for all platforms,
+ * model based on suggestions from Russell King and
+ * Geert Uytterhoeven
+ * Promise DC4030VL now supported.
+ * delay_50ms() changed to ide_delay_50ms() and exported.
*
* Some additional driver compile-time options are in ide.h
*
@@ -99,6 +104,9 @@
* - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
*/
+#define REVISION "Revision: 6.19"
+#define VERSION "Id: ide.c 6.19 1999/01/29"
+
#undef REALLY_SLOW_IO /* most systems can safely undef this */
#define _IDE_C /* Tell ide.h it's really us */
@@ -117,6 +125,7 @@
#include <linux/malloc.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/ide.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -124,24 +133,29 @@
#include <asm/io.h>
#include <asm/bitops.h>
-#include "ide.h"
#include "ide_modes.h"
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif /* CONFIG_KMOD */
-static const byte ide_hwif_to_major[] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR };
+#ifdef CONFIG_BLK_DEV_VIA82C586
+extern byte fifoconfig; /* defined in via82c586.c used by ide_setup()*/
+#endif
+
+static const byte ide_hwif_to_major[] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR };
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 */
+#if defined(__mc68000__) || defined(CONFIG_APUS)
/*
* ide_lock is used by the Atari code to obtain access to the IDE interrupt,
* which is shared between several drivers.
*/
static int ide_lock = 0;
+#endif /* __mc68000__ || CONFIG_APUS */
/*
* ide_modules keeps track of the available IDE chipset/probe/driver modules.
@@ -187,14 +201,18 @@
static void init_hwif_data (unsigned int index)
{
unsigned int unit;
+ hw_regs_t hw;
ide_hwif_t *hwif = &ide_hwifs[index];
/* bulk initialize hwif & drive info with zeros */
memset(hwif, 0, sizeof(ide_hwif_t));
+ memset(&hw, 0, sizeof(hw_regs_t));
/* fill in any non-zero initial values */
hwif->index = index;
- ide_init_hwif_ports(hwif->io_ports, ide_default_io_base(index), &hwif->irq);
+ ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
+ memcpy(&hwif->hw, &hw, sizeof(hw));
+ memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
#ifdef CONFIG_BLK_DEV_HD
if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
@@ -211,6 +229,7 @@
drive->media = ide_disk;
drive->select.all = (unit<<4)|0xa0;
drive->hwif = hwif;
+ init_waitqueue_head(&drive->wqueue);
drive->ctl = 0x08;
drive->ready_stat = READY_STAT;
drive->bad_wstat = BAD_W_STAT;
@@ -219,6 +238,7 @@
drive->name[0] = 'h';
drive->name[1] = 'd';
drive->name[2] = 'a' + (index * MAX_DRIVES) + unit;
+ init_waitqueue_head(&drive->wqueue);
}
}
@@ -246,9 +266,13 @@
return; /* already initialized */
magic_cookie = 0;
+ /* Initialise all interface structures */
for (index = 0; index < MAX_HWIFS; ++index)
init_hwif_data(index);
+ /* Add default hw interfaces */
+ ide_init_default_hwifs();
+
idebus_parameter = 0;
system_bus_speed = 0;
}
@@ -652,6 +676,10 @@
pre_reset(&hwif->drives[unit]);
#if OK_TO_RESET_CONTROLLER
+ if (!IDE_CONTROL_REG) {
+ __restore_flags(flags);
+ return;
+ }
/*
* Note that we also set nIEN while resetting the device,
* to mask unwanted interrupts from the interface during the reset.
@@ -857,7 +885,8 @@
void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
{
ide_set_handler (drive, handler, WAIT_CMD);
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
+ if (IDE_CONTROL_REG)
+ OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
OUT_BYTE(nsect,IDE_NSECTOR_REG);
OUT_BYTE(cmd,IDE_COMMAND_REG);
}
@@ -1253,6 +1282,20 @@
}
#endif /* MAX_HWIFS > 5 */
+#if MAX_HWIFS > 6
+void do_ide6_request (void)
+{
+ unlock_do_hwgroup_request (ide_hwifs[6].hwgroup);
+}
+#endif /* MAX_HWIFS > 6 */
+
+#if MAX_HWIFS > 7
+void do_ide7_request (void)
+{
+ unlock_do_hwgroup_request (ide_hwifs[7].hwgroup);
+}
+#endif /* MAX_HWIFS > 7 */
+
static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq)
{
unsigned long flags;
@@ -1370,6 +1413,12 @@
__cli(); /* local CPU only */
spin_lock_irqsave(&hwgroup->spinlock, flags);
hwif = hwgroup->hwif;
+
+ if (!ide_ack_intr(hwif)) {
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+ return;
+ }
+
if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
/*
* Not expecting an interrupt from this drive.
@@ -1391,7 +1440,6 @@
* Probably not a shared PCI interrupt,
* so we can safely try to do something about it:
*/
- (void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
unexpected_intr(irq, hwgroup);
}
spin_unlock_irqrestore(&hwgroup->spinlock, flags);
@@ -1403,7 +1451,6 @@
return;
}
hwgroup->handler = NULL;
- (void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
del_timer(&(hwgroup->timer));
spin_unlock_irqrestore(&hwgroup->spinlock, flags);
if (drive->unmask)
@@ -1490,7 +1537,7 @@
ide_hwgroup_t *hwgroup = HWGROUP(drive);
unsigned int major = HWIF(drive)->major;
struct request *cur_rq;
- struct semaphore sem = MUTEX_LOCKED;
+ DECLARE_MUTEX_LOCKED(sem);
if (IS_PDC4030_DRIVE && rq->buffer != NULL)
return -ENOSYS; /* special drive cmds not supported */
@@ -1696,6 +1743,7 @@
ide_hwgroup_t *hwgroup;
int irq_count = 0, unit, i;
unsigned long flags;
+ unsigned int p, minor;
if (index >= MAX_HWIFS)
return;
@@ -1714,6 +1762,24 @@
goto abort;
}
hwif->present = 0;
+
+ /*
+ * All clear? Then blow away the buffer cache
+ */
+ sti();
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ drive = &hwif->drives[unit];
+ 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);
+ struct super_block * sb = get_super(devp);
+ if (sb) invalidate_inodes(sb);
+ invalidate_buffers (devp);
+ }
+ }
+ }
+ cli();
hwgroup = hwif->hwgroup;
/*
@@ -1734,7 +1800,8 @@
* allocated for weird IDE interface chipsets.
*/
ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
- ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
+ if (hwif->io_ports[IDE_CONTROL_OFFSET])
+ ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
/*
* Remove us from the hwgroup, and free
@@ -1798,21 +1865,58 @@
restore_flags(flags); /* all CPUs */
}
-int ide_register (int arg1, int arg2, int irq)
+/*
+ * 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.
+ */
+void ide_setup_ports ( hw_regs_t *hw,
+ ide_ioreg_t base, int *offsets,
+ ide_ioreg_t ctrl, ide_ioreg_t intr,
+ ide_ack_intr_t *ack_intr, int irq)
+{
+ int i;
+
+ for (i = 0; i < IDE_NR_PORTS; i++) {
+ if (offsets[i] == -1) {
+ switch(i) {
+ case IDE_CONTROL_OFFSET:
+ hw->io_ports[i] = ctrl;
+ break;
+ case IDE_IRQ_OFFSET:
+ hw->io_ports[i] = intr;
+ break;
+ default:
+ hw->io_ports[i] = 0;
+ break;
+ }
+ } else {
+ hw->io_ports[i] = base + offsets[i];
+ }
+ }
+ hw->irq = irq;
+ hw->ack_intr = ack_intr;
+}
+
+/*
+ * Register an IDE interface, specifing exactly the registers etc
+ * Set init=1 iff calling before probes have taken place.
+ */
+int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp)
{
int index, retry = 1;
ide_hwif_t *hwif;
- ide_ioreg_t data_port = (ide_ioreg_t) arg1, ctl_port = (ide_ioreg_t) arg2;
do {
for (index = 0; index < MAX_HWIFS; ++index) {
hwif = &ide_hwifs[index];
- if (hwif->io_ports[IDE_DATA_OFFSET] == data_port)
+ if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
goto found;
}
for (index = 0; index < MAX_HWIFS; ++index) {
hwif = &ide_hwifs[index];
- if (!hwif->present)
+ if ((!hwif->present && !initializing) ||
+ (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
goto found;
}
for (index = 0; index < MAX_HWIFS; index++)
@@ -1824,14 +1928,33 @@
ide_unregister(index);
if (hwif->present)
return -1;
- ide_init_hwif_ports(hwif->io_ports, data_port, &hwif->irq);
- if (ctl_port)
- hwif->io_ports[IDE_CONTROL_OFFSET] = ctl_port;
- hwif->irq = irq;
+ memcpy(&hwif->hw, hw, sizeof(*hw));
+ memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
+ hwif->irq = hw->irq;
hwif->noprobe = 0;
- ide_init_module(IDE_PROBE_MODULE);
- ide_init_module(IDE_DRIVER_MODULE);
- return hwif->present ? index : -1;
+
+ if (!initializing) {
+ ide_init_module(IDE_PROBE_MODULE);
+ ide_init_module(IDE_DRIVER_MODULE);
+ }
+
+ if (hwifp)
+ *hwifp = hwif;
+
+ return (initializing || hwif->present) ? index : -1;
+}
+
+/*
+ * Compatability function with existing drivers. If you want
+ * something different, use the function above.
+ */
+int ide_register (int arg1, int arg2, int irq)
+{
+ hw_regs_t hw;
+
+ ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL);
+ hw.irq = irq;
+ return ide_register_hw(&hw, NULL);
}
void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
@@ -2056,10 +2179,24 @@
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
+/*
+ * Delay for *at least* 50ms. As we don't know how much time is left
+ * until the next tick occurs, we wait an extra tick to be safe.
+ * This is used only during the probing/polling for drives at boot time.
+ *
+ * However, its usefullness may be needed in other places, thus we export it now.
+ * The future may change this to a millisecond setable delay.
+ */
+void ide_delay_50ms (void)
+{
+ unsigned long timeout = jiffies + ((HZ + 19)/20) + 1;
+ while (0 < (signed long)(timeout - jiffies));
+}
+
static int ide_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- int err, major, minor;
+ int err = 0, major, minor;
ide_drive_t *drive;
struct request rq;
kdev_t dev;
@@ -2147,7 +2284,68 @@
return -ENOMEM;
memcpy(argbuf, args, 4);
}
+ if ((((byte *)arg)[0] == WIN_SETFEATURES) &&
+ (((byte *)arg)[1] > 66) &&
+ (((byte *)arg)[2] == 3) &&
+ ((drive->id->word93 & 0x2000) == 0)) {
+ printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name);
+ goto abort;
+ }
err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
+ if (!err &&
+ (((byte *)arg)[0] == WIN_SETFEATURES) &&
+ (((byte *)arg)[1] >= 16) &&
+ (((byte *)arg)[2] == 3) &&
+ (drive->id->dma_ultra ||
+ drive->id->dma_mword ||
+ drive->id->dma_1word)) {
+
+ /*
+ * Re-read drive->id for possible DMA mode
+ * change (copied from ide-probe.c)
+ */
+ struct hd_driveid *id;
+ unsigned long timeout, irqs, flags;
+
+ probe_irq_off(probe_irq_on());
+ irqs = probe_irq_on();
+ if (IDE_CONTROL_REG)
+ OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+ ide_delay_50ms();
+ OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG);
+ timeout = jiffies + WAIT_WORSTCASE;
+ do {
+ if (0 < (signed long)(jiffies - timeout)) {
+ if (irqs)
+ (void) probe_irq_off(irqs);
+ goto abort; /* drive timed-out */
+ }
+ ide_delay_50ms(); /* give drive a breather */
+ } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT);
+ ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */
+ if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT))
+ goto abort;
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only; some systems need this */
+ id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
+ ide_input_data(drive, id, SECTOR_WORDS);
+ (void) GET_STAT(); /* clear drive IRQ */
+ ide__sti(); /* local CPU only */
+ __restore_flags(flags); /* local CPU only */
+ ide_fix_driveid(id);
+ if (id && id->cyls) {
+ drive->id->dma_ultra = id->dma_ultra;
+ drive->id->dma_mword = id->dma_mword;
+ drive->id->dma_1word = id->dma_1word;
+ /* anything more ? */
+#ifdef DEBUG
+ printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n",
+ drive->name, id->dma_ultra, id->dma_mword, id->dma_1word);
+#endif
+ kfree(id);
+ }
+ }
+ abort:
if (copy_to_user((void *)arg, argbuf, argsize))
err = -EFAULT;
if (argsize > 4)
@@ -2233,6 +2431,32 @@
}
/*
+ *
+ */
+char *ide_xfer_verbose (byte xfer_rate) {
+ switch(xfer_rate) {
+ case XFER_UDMA_4: return("UDMA 4");
+ case XFER_UDMA_3: return("UDMA 3");
+ case XFER_UDMA_2: return("UDMA 2");
+ case XFER_UDMA_1: return("UDMA 1");
+ case XFER_UDMA_0: return("UDMA 0");
+ case XFER_MW_DMA_2: return("MW DMA 2");
+ case XFER_MW_DMA_1: return("MW DMA 1");
+ case XFER_MW_DMA_0: return("MW DMA 0");
+ case XFER_SW_DMA_2: return("SW DMA 2");
+ case XFER_SW_DMA_1: return("SW DMA 1");
+ case XFER_SW_DMA_0: return("SW DMA 0");
+ case XFER_PIO_4: return("PIO 4");
+ case XFER_PIO_3: return("PIO 3");
+ case XFER_PIO_2: return("PIO 2");
+ case XFER_PIO_1: return("PIO 1");
+ case XFER_PIO_0: return("PIO 0");
+ case XFER_PIO_SLOW: return("PIO SLOW");
+ default: return("XFER ERROR");
+ }
+}
+
+/*
* stridx() returns the offset of c within s,
* or -1 if c is '\0' or not found within s.
*/
@@ -2351,7 +2575,22 @@
* "idex=reset" : reset interface before first use
* "idex=dma" : enable DMA by default on both drives if possible
*
- * The following are valid ONLY on ide0,
+ * "splitfifo=betweenChan"
+ * : FIFO Configuration of VIA 82c586(<nothing>,"A"or"B").
+ * --see what follows...
+ * "splitfifo=betweenChan,thresholdprim,thresholdsec"
+ * : FIFO Configuration of VIA 82c586(<nothing>,"A" or "B").
+ * betweenChan = 1(all FIFO's to primary channel)
+ * , 2(all FIFO's to secondary channel)
+ * , 3 or 4(evenly shared between them).
+ * note: without FIFO, a channel is (u)dma disabled!
+ * thresholdprim = 4, 3, 2 or 1
+ * (standing for 1, 3/4, 1/2, 1/4).
+ * Sets the threshold of FIFO to begin dma
+ * transfer on the primary channel.
+ * thresholdsec = cf upper, but for secondary channel.
+ *
+ * The following are valid ONLY on ide0, (except dc4030)
* and the defaults for the base,ctl ports must not be altered.
*
* "ide0=dtc2278" : probe/support DTC2278 interface
@@ -2361,6 +2600,7 @@
* "ide0=qd6580" : probe/support qd6580 interface
* "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445)
* "ide0=umc8672" : probe/support umc8672 chipsets
+ * "idex=dc4030" : probe/support Promise DC4030VL interface
*/
__initfunc(void ide_setup (char *s))
{
@@ -2372,6 +2612,17 @@
const char max_hwif = '0' + (MAX_HWIFS - 1);
printk("ide_setup: %s", s);
+
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+ if (!strcmp(s, "ide=doubler")) {
+ extern int ide_doubler;
+
+ printk("ide: Enabled support for IDE doublers\n");
+ ide_doubler = 1;
+ return;
+ }
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
init_ide_data ();
/*
@@ -2435,6 +2686,58 @@
}
}
+#if defined(CONFIG_BLK_DEV_VIA82C586)
+ /*
+ * Look for drive option "splitfifo=..."
+ */
+
+ if (s[0] == 's' && s[1] == 'p' && s[2] == 'l' &&
+ s[3] == 'i' && s[4] == 't' && s[5] == 'f' &&
+ s[6] == 'i' && s[7] == 'f' && s[8] == 'o') {
+ byte tmp = 0x3a; /* default config byte */
+
+ i = match_parm(&s[9], NULL, vals, 3);
+ switch(i) {
+ case 3:
+ tmp &= 0xf0;
+ if ((vals[1] > 0) && (vals[1] < 5)) {
+ /* sets threshold for primary Channel: */
+ byte x = 4 - vals[1];
+ tmp |= (x << 2);
+ }
+ else
+ goto bad_option;
+ if ((vals[2] > 0) && (vals[2] < 5)) {
+ /* sets threshold for secondary Channel: */
+ byte x = 4 - vals[2];
+ tmp |= x;
+ }
+ else
+ goto bad_option;
+ case 1:
+ /* set the FIFO config between channels to 0: */
+ tmp &= 0x9f;
+ /* set the needed FIFO config between channels: */
+ if (vals[0] == 1) /* primary fifo only */
+ tmp |= 0x10;
+ else if (vals[0] == 2) /* secondary fifo only */
+ tmp |= 0x70;
+ else if (vals[0] == 4) /* other shared fifo config */
+ tmp |= 0x50;
+ else if (vals[0] == 3) /* default config */
+ tmp |= 0x30;
+ else
+ goto bad_option;
+ break;
+ default:
+ goto bad_option;
+ }
+ /* set the found option in fifoconfig */
+ fifoconfig = tmp;
+ goto done;
+ }
+#endif /* defined(CONFIG_BLK_DEV_VIA82C586) */
+
if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e')
goto bad_option;
/*
@@ -2468,9 +2771,9 @@
if (i > 0 || i <= -7) { /* is parameter a chipset name? */
if (hwif->chipset != ide_unknown)
goto bad_option; /* chipset already specified */
- if (i <= -7 && hw != 0)
+ if (i <= -7 && i != -14 && hw != 0)
goto bad_hwif; /* chipset drivers are for "ide0=" only */
- if (i <= -7 && ide_hwifs[hw^1].chipset != ide_unknown)
+ if (i <= -7 && i != -14 && ide_hwifs[hw+1].chipset != ide_unknown)
goto bad_option; /* chipset for 2nd port already specified */
printk("\n");
}
@@ -2574,8 +2877,9 @@
case 2: /* base,ctl */
vals[2] = 0; /* default irq = probe for it */
case 3: /* base,ctl,irq */
- ide_init_hwif_ports(hwif->io_ports, (ide_ioreg_t) vals[0], &hwif->irq);
- hwif->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) vals[1];
+ hwif->hw.irq = vals[2];
+ ide_init_hwif_ports(&hwif->hw, (ide_ioreg_t) vals[0], (ide_ioreg_t) vals[1], &hwif->irq);
+ memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
hwif->irq = vals[2];
hwif->noprobe = 0;
hwif->chipset = ide_generic;
@@ -2612,9 +2916,122 @@
* an IDE disk drive, or if a geometry was "forced" on the commandline.
* Returns 1 if the geometry translation was successful.
*/
+
+#define ANDRIES_GEOMETRY 0
+
int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
{
ide_drive_t *drive;
+
+#if ANDRIES_GEOMETRY
+ /*
+ * This is the documented list of values (some version of)
+ * OnTrack DM uses.
+ */
+
+ static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
+
+ /*
+ * This is a pure phantasy list - known to be incorrect.
+ *
+ * In fact it seems that EZD does not do anything to the CHS
+ * values in the partition table, so whether EZD is present
+ * or not should probably not influence the geometry.
+ */
+
+ static const byte ez_head_vals[] = {4, 8, 16, 32, 64, 128, 240, 255, 0}; const byte *heads;
+ unsigned long tracks;
+
+ drive = get_info_ptr(i_rdev);
+ if (!drive)
+ return 0;
+
+ if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) {
+ /*
+ * Update the current 3D drive values.
+ */
+ drive->id->cur_cyls = drive->bios_cyl;
+ drive->id->cur_heads = drive->bios_head;
+ drive->id->cur_sectors = drive->bios_sect;
+ return 0; /* we already have a translation */
+ }
+
+ if (xparm == -1) {
+ int ret = 0;
+#if FAKE_FDISK_FOR_EZDRIVE
+ if (drive->remap_0_to_1 == 0) {
+ drive->remap_0_to_1 = 1;
+ printk("%s [remap 0->1]", msg);
+ msg = NULL;
+ ret = 1;
+ }
+ if (drive->bios_head > 16)
+#endif /* FAKE_FDISK_FOR_EZDRIVE */
+ {
+ /*
+ * Update the current 3D drive values.
+ */
+ drive->id->cur_cyls = drive->bios_cyl;
+ drive->id->cur_heads = drive->bios_head;
+ drive->id->cur_sectors = drive->bios_sect;
+ return ret; /* we already have a translation */
+ }
+ }
+
+ if (msg)
+ printk("%s ", msg);
+
+ if (drive->forced_geom) {
+ /*
+ * Update the current 3D drive values.
+ */
+ drive->id->cur_cyls = drive->bios_cyl;
+ drive->id->cur_heads = drive->bios_head;
+ drive->id->cur_sectors = drive->bios_sect;
+ return 0;
+ }
+
+#if 1
+ /* There used to be code here that assigned drive->id->CHS
+ to drive->CHS and that to drive->bios_CHS. However,
+ some disks have id->C/H/S = 4092/16/63 but are larger than 2.1 GB.
+ In such cases that code was wrong. Moreover,
+ there seems to be no reason to do any of these things. */
+#else
+ if (drive->id) {
+ drive->cyl = drive->id->cyls;
+ drive->head = drive->id->heads;
+ drive->sect = drive->id->sectors;
+ }
+ drive->bios_cyl = drive->cyl;
+ drive->bios_head = drive->head;
+ drive->bios_sect = drive->sect;
+ drive->special.b.set_geometry = 1;
+
+#endif
+
+ tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
+ drive->bios_sect = 63;
+ if (xparm > 1) {
+ drive->bios_head = xparm;
+ drive->bios_cyl = tracks / drive->bios_head;
+ } else {
+ heads = (xparm == -1) ? ez_head_vals : dm_head_vals;
+ while (drive->bios_cyl >= 1024) {
+ drive->bios_head = *heads;
+ drive->bios_cyl = tracks / drive->bios_head;
+ if (0 == *++heads)
+ break;
+ }
+ if (xparm == 1) {
+ drive->sect0 = 63;
+ drive->bios_cyl = (tracks - 1) / drive->bios_head;
+ printk("[remap +63] ");
+ }
+ }
+
+#else /* ANDRIES_GEOMETRY */
+
static const byte head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
const byte *heads = head_vals;
unsigned long tracks;
@@ -2689,14 +3106,16 @@
printk("[remap +63] ");
}
}
+#endif /* ANDRIES_GEOMETRY */
+
drive->part[0].nr_sects = current_capacity(drive);
printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect);
/*
* Update the current 3D drive values.
*/
- drive->id->cur_cyls = drive->bios_cyl;
- drive->id->cur_heads = drive->bios_head;
- drive->id->cur_sectors = drive->bios_sect;
+ drive->id->cur_cyls = drive->bios_cyl;
+ drive->id->cur_heads = drive->bios_head;
+ drive->id->cur_sectors = drive->bios_sect;
return 1;
}
@@ -2739,6 +3158,42 @@
pmac_ide_probe();
}
#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
+ {
+ extern void icside_init(void);
+ icside_init();
+ }
+#endif /* CONFIG_BLK_DEV_IDE_ICSIDE */
+#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
+ {
+ extern void rapide_init(void);
+ rapide_init();
+ }
+#endif /* CONFIG_BLK_DEV_IDE_RAPIDE */
+#ifdef CONFIG_BLK_DEV_GAYLE
+ {
+ extern void gayle_init(void);
+ gayle_init();
+ }
+#endif /* CONFIG_BLK_DEV_GAYLE */
+#ifdef CONFIG_BLK_DEV_FALCON_IDE
+ {
+ extern void falconide_init(void);
+ falconide_init();
+ }
+#endif /* CONFIG_BLK_DEV_FALCON_IDE */
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+ {
+ extern void macide_init(void);
+ macide_init();
+ }
+#endif /* CONFIG_BLK_DEV_MAC_IDE */
+#ifdef CONFIG_BLK_DEV_BUDDHA
+ {
+ extern void buddha_init(void);
+ buddha_init();
+ }
+#endif /* CONFIG_BLK_DEV_BUDDHA */
}
__initfunc(void ide_init_builtin_drivers (void))
@@ -3013,6 +3468,12 @@
#if MAX_HWIFS > 5
EXPORT_SYMBOL(do_ide5_request);
#endif /* MAX_HWIFS > 5 */
+#if MAX_HWIFS > 6
+EXPORT_SYMBOL(do_ide6_request);
+#endif /* MAX_HWIFS > 6 */
+#if MAX_HWIFS > 7
+EXPORT_SYMBOL(do_ide7_request);
+#endif /* MAX_HWIFS > 7 */
/*
* Driver module
@@ -3037,6 +3498,7 @@
EXPORT_SYMBOL(ide_revalidate_disk);
EXPORT_SYMBOL(ide_cmd);
EXPORT_SYMBOL(ide_wait_cmd);
+EXPORT_SYMBOL(ide_delay_50ms);
EXPORT_SYMBOL(ide_stall_queue);
#ifdef CONFIG_PROC_FS
EXPORT_SYMBOL(ide_add_proc_entries);
@@ -3046,14 +3508,23 @@
EXPORT_SYMBOL(ide_add_setting);
EXPORT_SYMBOL(ide_remove_setting);
+EXPORT_SYMBOL(ide_register_hw);
EXPORT_SYMBOL(ide_register);
EXPORT_SYMBOL(ide_unregister);
+EXPORT_SYMBOL(ide_setup_ports);
/*
* This is gets invoked once during initialization, to set *everything* up
*/
__initfunc(int ide_init (void))
{
+ static char banner_printed = 0;
+
+ if (!banner_printed) {
+ printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
+ banner_printed = 1;
+ }
+
init_ide_data ();
initializing = 1;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)