summaryrefslogtreecommitdiffstats
path: root/drivers/block/ide.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-17 13:25:08 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-17 13:25:08 +0000
commit59223edaa18759982db0a8aced0e77457d10c68e (patch)
tree89354903b01fa0a447bffeefe00df3044495db2e /drivers/block/ide.c
parentdb7d4daea91e105e3859cf461d7e53b9b77454b2 (diff)
Merge with Linux 2.3.6. Sorry, this isn't tested on silicon, I don't
have a MIPS box at hand.
Diffstat (limited to 'drivers/block/ide.c')
-rw-r--r--drivers/block/ide.c470
1 files changed, 419 insertions, 51 deletions
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 2e703455d..2d6eebd24 100644
--- a/drivers/block/ide.c
+++ b/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 */
@@ -114,9 +122,11 @@
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
+#include <linux/blkpg.h>
#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 +134,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 +202,18 @@ static inline void set_recovery_timer (ide_hwif_t *hwif)
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)
@@ -219,6 +238,7 @@ static void init_hwif_data (unsigned int index)
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 @@ static void init_ide_data (void)
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;
}
@@ -271,8 +295,9 @@ int drive_is_flashcard (ide_drive_t *drive)
if (drive->removable && id != NULL) {
if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */
- || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
- || !strncmp(id->model, "SunDisk SDCFB", 13)) /* SunDisk */
+ || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
+ || !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */
+ || !strncmp(id->model, "HAGIWARA HPC", 12)) /* Hagiwara */
{
return 1; /* yes, it is a flash memory card */
}
@@ -652,6 +677,10 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
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 +886,8 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
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);
}
@@ -926,6 +956,7 @@ static inline void do_special (ide_drive_t *drive)
int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout)
{
byte stat;
+ int i;
unsigned long flags;
udelay(1); /* spec allows drive 400ns to assert "BUSY" */
@@ -942,9 +973,18 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou
}
__restore_flags(flags); /* local CPU only */
}
- udelay(1); /* allow status to settle, then read it again */
- if (OK_STAT((stat = GET_STAT()), good, bad))
- return 0;
+ /*
+ * Allow status to settle, then read it again.
+ * A few rare drives vastly violate the 400ns spec here,
+ * so we'll wait up to 10usec for a "good" status
+ * rather than expensively fail things immediately.
+ * This fix courtesy of Matthew Faupel & Niccolo Rigacci.
+ */
+ for (i = 0; i < 10; i++) {
+ udelay(1);
+ if (OK_STAT((stat = GET_STAT()), good, bad))
+ return 0;
+ }
ide_error(drive, "status error", stat);
return 1;
}
@@ -1253,6 +1293,20 @@ void do_ide5_request (void)
}
#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 +1424,12 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
__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 +1451,6 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
* 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 +1462,6 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
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,10 +1548,12 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
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)
+#ifdef CONFIG_BLK_DEV_PDC4030
+ if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)
return -ENOSYS; /* special drive cmds not supported */
+#endif
rq->errors = 0;
rq->rq_status = RQ_ACTIVE;
rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS);
@@ -1696,6 +1756,7 @@ void ide_unregister (unsigned int index)
ide_hwgroup_t *hwgroup;
int irq_count = 0, unit, i;
unsigned long flags;
+ unsigned int p, minor;
if (index >= MAX_HWIFS)
return;
@@ -1714,6 +1775,26 @@ void ide_unregister (unsigned int index)
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];
+ if (!drive->present)
+ continue;
+ 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 +1815,8 @@ void ide_unregister (unsigned int index)
* 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 +1880,58 @@ abort:
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 +1943,33 @@ found:
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 +2194,24 @@ int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int secto
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;
@@ -2095,17 +2247,6 @@ static int ide_ioctl (struct inode *inode, struct file *file,
(unsigned long *) &loc->start)) return -EFAULT;
return 0;
}
- case BLKSSZGET:
- /* Block size of media */
- return put_user(blksize_size[HWIF(drive)->major]
- [minor&PARTN_MASK],
- (int *)arg);
-
- case BLKFLSBUF:
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- fsync_dev(inode->i_rdev);
- invalidate_buffers(inode->i_rdev);
- return 0;
case BLKGETSIZE: /* Return device size */
return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (long *) arg);
@@ -2147,7 +2288,68 @@ static int ide_ioctl (struct inode *inode, struct file *file,
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)
@@ -2185,7 +2387,12 @@ static int ide_ioctl (struct inode *inode, struct file *file,
drive->nice1 = (arg >> IDE_NICE_1) & 1;
return 0;
- RO_IOCTLS(inode->i_rdev, arg);
+ case BLKROSET:
+ case BLKROGET:
+ case BLKFLSBUF:
+ case BLKSSZGET:
+ case BLKPG:
+ return blk_ioctl(inode->i_rdev, cmd, arg);
default:
if (drive->driver != NULL)
@@ -2233,6 +2440,32 @@ void ide_fixstring (byte *s, const int bytecount, const int byteswap)
}
/*
+ *
+ */
+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 +2584,22 @@ __initfunc(static int match_parm (char *s, const char *keywords[], int vals[], i
* "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 +2609,7 @@ __initfunc(static int match_parm (char *s, const char *keywords[], int vals[], i
* "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 +2621,17 @@ __initfunc(void ide_setup (char *s))
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 +2695,58 @@ __initfunc(void ide_setup (char *s))
}
}
+#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 +2780,9 @@ __initfunc(void ide_setup (char *s))
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");
}
@@ -2479,8 +2791,8 @@ __initfunc(void ide_setup (char *s))
#ifdef CONFIG_BLK_DEV_PDC4030
case -14: /* "dc4030" */
{
- extern void setup_pdc4030(ide_hwif_t *);
- setup_pdc4030(hwif);
+ extern void init_pdc4030(void);
+ init_pdc4030();
goto done;
}
#endif /* CONFIG_BLK_DEV_PDC4030 */
@@ -2574,8 +2886,9 @@ __initfunc(void ide_setup (char *s))
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 +2925,11 @@ done:
* an IDE disk drive, or if a geometry was "forced" on the commandline.
* Returns 1 if the geometry translation was successful.
*/
+
int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
{
ide_drive_t *drive;
+
static const byte head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
const byte *heads = head_vals;
unsigned long tracks;
@@ -2689,14 +3004,15 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
printk("[remap +63] ");
}
}
+
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;
}
@@ -2729,8 +3045,8 @@ __initfunc(static void probe_for_hwifs (void))
#endif /* CONFIG_BLK_DEV_CMD640 */
#ifdef CONFIG_BLK_DEV_PDC4030
{
- extern int init_pdc4030(void);
- (void) init_pdc4030();
+ extern int ide_probe_for_pdc4030(void);
+ (void) ide_probe_for_pdc4030();
}
#endif /* CONFIG_BLK_DEV_PDC4030 */
#ifdef CONFIG_BLK_DEV_IDE_PMAC
@@ -2739,6 +3055,42 @@ __initfunc(static void probe_for_hwifs (void))
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 +3365,12 @@ EXPORT_SYMBOL(do_ide4_request);
#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 +3395,7 @@ EXPORT_SYMBOL(ide_end_request);
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 +3405,23 @@ EXPORT_SYMBOL(proc_ide_read_geometry);
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;