/*
- * linux/drivers/ide/ide.c Version 7.00beta2 Mar 05 2003
- *
- * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
+ * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
+ * Copyrifht (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
*/
/*
*/
#define REVISION "Revision: 7.00alpha2"
-#define VERSION "Id: ide.c 7.00a2 20020906"
#define _IDE_C /* Tell ide.h it's really us */
__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
-static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
+int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
#endif
int noautodma = 0;
/*
* Do not even *think* about calling this!
*/
-static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
+void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
{
unsigned int unit;
init_completion(&drive->gendev_rel_comp);
}
}
+EXPORT_SYMBOL_GPL(ide_init_port_data);
static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
{
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];
#endif
}
-extern void ide_arm_init(void);
-
/*
* init_ide_data() sets reasonable default values into all fields
* of all instances of the hwifs and drives, but only on the first call.
/* Initialise all interface structures */
for (index = 0; index < MAX_HWIFS; ++index) {
hwif = &ide_hwifs[index];
- init_hwif_data(hwif, index);
+ ide_init_port_data(hwif, index);
init_hwif_default(hwif, index);
#if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI)
- hwif->irq = hwif->hw.irq =
+ hwif->irq =
ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
#endif
}
-#ifdef CONFIG_IDE_ARM
- ide_arm_init();
-#endif
}
/**
#define pci_default 0
#endif /* CONFIG_PCI */
- if (!system_bus_speed) {
- if (idebus_parameter) {
- /* user supplied value */
- system_bus_speed = idebus_parameter;
- } else if (pci_dev_present(pci_default)) {
- /* safe default value for PCI */
- system_bus_speed = 33;
- } else {
- /* safe default value for VESA and PCI */
- system_bus_speed = 50;
- }
- printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
- "for PIO modes%s\n", system_bus_speed,
- idebus_parameter ? "" : "; override with idebus=xx");
+ /* user supplied value */
+ if (idebus_parameter)
+ return idebus_parameter;
+
+ /* safe default value for PCI or VESA and PCI*/
+ return pci_dev_present(pci_default) ? 33 : 50;
+}
+
+ide_hwif_t * ide_find_port(unsigned long base)
+{
+ ide_hwif_t *hwif;
+ int i;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ hwif = &ide_hwifs[i];
+ if (hwif->io_ports[IDE_DATA_OFFSET] == base)
+ goto found;
}
- return system_bus_speed;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ hwif = &ide_hwifs[i];
+ if (hwif->io_ports[IDE_DATA_OFFSET] == 0)
+ goto found;
+ }
+
+ hwif = NULL;
+found:
+ return hwif;
}
+EXPORT_SYMBOL_GPL(ide_find_port);
+
static struct resource* hwif_request_region(ide_hwif_t *hwif,
unsigned long addr, int num)
{
hwif->chipset = tmp_hwif->chipset;
hwif->hold = tmp_hwif->hold;
+ hwif->dev = tmp_hwif->dev;
+
#ifdef CONFIG_BLK_DEV_IDEPCI
- hwif->pci_dev = tmp_hwif->pci_dev;
hwif->cds = tmp_hwif->cds;
#endif
hwif->reset_poll = tmp_hwif->reset_poll;
hwif->pre_reset = tmp_hwif->pre_reset;
hwif->resetproc = tmp_hwif->resetproc;
- hwif->intrproc = tmp_hwif->intrproc;
hwif->maskproc = tmp_hwif->maskproc;
hwif->quirkproc = tmp_hwif->quirkproc;
hwif->busproc = tmp_hwif->busproc;
hwif->atapi_input_bytes = tmp_hwif->atapi_input_bytes;
hwif->atapi_output_bytes = tmp_hwif->atapi_output_bytes;
+ hwif->dma_host_set = tmp_hwif->dma_host_set;
hwif->dma_setup = tmp_hwif->dma_setup;
hwif->dma_exec_cmd = tmp_hwif->dma_exec_cmd;
hwif->dma_start = tmp_hwif->dma_start;
hwif->ide_dma_end = tmp_hwif->ide_dma_end;
- hwif->ide_dma_on = tmp_hwif->ide_dma_on;
- hwif->dma_off_quietly = tmp_hwif->dma_off_quietly;
hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq;
hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq;
- hwif->dma_host_on = tmp_hwif->dma_host_on;
- hwif->dma_host_off = tmp_hwif->dma_host_off;
hwif->dma_lost_irq = tmp_hwif->dma_lost_irq;
hwif->dma_timeout = tmp_hwif->dma_timeout;
#endif
hwif->dma_base = tmp_hwif->dma_base;
- hwif->dma_master = tmp_hwif->dma_master;
hwif->dma_command = tmp_hwif->dma_command;
hwif->dma_vendor1 = tmp_hwif->dma_vendor1;
hwif->dma_status = tmp_hwif->dma_status;
hwif->hwif_data = tmp_hwif->hwif_data;
}
+void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+{
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
+
+ spin_lock_irq(&ide_lock);
+ /*
+ * Remove us from the hwgroup, and free
+ * the hwgroup if we were the only member
+ */
+ if (hwif->next == hwif) {
+ BUG_ON(hwgroup->hwif != hwif);
+ kfree(hwgroup);
+ } else {
+ /* There is another interface in hwgroup.
+ * Unlink us, and set hwgroup->drive and ->hwif to
+ * something sane.
+ */
+ ide_hwif_t *g = hwgroup->hwif;
+
+ while (g->next != hwif)
+ g = g->next;
+ g->next = hwif->next;
+ if (hwgroup->hwif == hwif) {
+ /* Chose a random hwif for hwgroup->hwif.
+ * It's guaranteed that there are no drives
+ * left in the hwgroup.
+ */
+ BUG_ON(hwgroup->drive != NULL);
+ hwgroup->hwif = g;
+ }
+ BUG_ON(hwgroup->hwif == hwif);
+ }
+ spin_unlock_irq(&ide_lock);
+}
+
/**
* ide_unregister - free an IDE interface
* @index: index of interface (will change soon to a pointer)
if (irq_count == 1)
free_irq(hwif->irq, hwgroup);
- spin_lock_irq(&ide_lock);
- /*
- * Note that we only release the standard ports,
- * and do not even try to handle any extra ports
- * allocated for weird IDE interface chipsets.
- */
- ide_hwif_release_regions(hwif);
+ ide_remove_port_from_hwgroup(hwif);
- /*
- * Remove us from the hwgroup, and free
- * the hwgroup if we were the only member
- */
- if (hwif->next == hwif) {
- BUG_ON(hwgroup->hwif != hwif);
- kfree(hwgroup);
- } else {
- /* There is another interface in hwgroup.
- * Unlink us, and set hwgroup->drive and ->hwif to
- * something sane.
- */
- g = hwgroup->hwif;
- while (g->next != hwif)
- g = g->next;
- g->next = hwif->next;
- if (hwgroup->hwif == hwif) {
- /* Chose a random hwif for hwgroup->hwif.
- * It's guaranteed that there are no drives
- * left in the hwgroup.
- */
- BUG_ON(hwgroup->drive != NULL);
- hwgroup->hwif = g;
- }
- BUG_ON(hwgroup->hwif == hwif);
- }
-
- /* More messed up locking ... */
- spin_unlock_irq(&ide_lock);
device_unregister(&hwif->gendev);
wait_for_completion(&hwif->gendev_rel_comp);
(void) ide_release_dma(hwif);
hwif->dma_base = 0;
- hwif->dma_master = 0;
hwif->dma_command = 0;
hwif->dma_vendor1 = 0;
hwif->dma_status = 0;
hwif->extra_ports = 0;
}
+ /*
+ * Note that we only release the standard ports,
+ * and do not even try to handle any extra ports
+ * allocated for weird IDE interface chipsets.
+ */
+ ide_hwif_release_regions(hwif);
+
/* copy original settings */
tmp_hwif = *hwif;
/* restore hwif data to pristine status */
- init_hwif_data(hwif, index);
+ ide_init_port_data(hwif, index);
init_hwif_default(hwif, index);
ide_hwif_restore(hwif, &tmp_hwif);
}
}
hw->irq = irq;
- hw->dma = NO_DMA;
hw->ack_intr = ack_intr;
/*
* hw->iops = iops;
*/
}
+void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
+{
+ memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
+ hwif->irq = hw->irq;
+ hwif->noprobe = 0;
+ hwif->chipset = hw->chipset;
+ hwif->gendev.parent = hw->dev;
+ hwif->ack_intr = hw->ack_intr;
+}
+EXPORT_SYMBOL_GPL(ide_init_port_hw);
+
/**
- * ide_register_hw_with_fixup - register IDE interface
+ * ide_register_hw - register IDE interface
* @hw: hardware registers
- * @initializing: set while initializing built-in drivers
+ * @quirkproc: quirkproc function
* @hwifp: pointer to returned hwif
- * @fixup: fixup function
*
* Register an IDE interface, specifying exactly the registers etc.
- * Set init=1 iff calling before probes have taken place.
*
* Returns -1 on error.
*/
-int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing,
- ide_hwif_t **hwifp,
- void(*fixup)(ide_hwif_t *hwif))
+int ide_register_hw(hw_regs_t *hw, void (*quirkproc)(ide_drive_t *),
+ ide_hwif_t **hwifp)
{
int index, retry = 1;
ide_hwif_t *hwif;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
do {
for (index = 0; index < MAX_HWIFS; ++index) {
hwif = &ide_hwifs[index];
- if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
+ if (hwif->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->hold)
continue;
- if ((!hwif->present && !hwif->mate && !initializing) ||
- (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
+ if (!hwif->present && hwif->mate == NULL)
goto found;
}
for (index = 0; index < MAX_HWIFS; index++)
if (hwif->present)
ide_unregister(index);
else if (!hwif->hold) {
- init_hwif_data(hwif, index);
+ ide_init_port_data(hwif, index);
init_hwif_default(hwif, index);
}
- if (hwif->present)
- return -1;
- 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;
- hwif->chipset = hw->chipset;
- hwif->gendev.parent = hw->dev;
- if (!initializing) {
- probe_hwif_init_with_fixup(hwif, fixup);
- ide_proc_register_port(hwif);
- }
+ ide_init_port_hw(hwif, hw);
+ hwif->quirkproc = quirkproc;
- if (hwifp)
- *hwifp = hwif;
+ idx[0] = index;
- return (initializing || hwif->present) ? index : -1;
-}
+ ide_device_add(idx, NULL);
-EXPORT_SYMBOL(ide_register_hw_with_fixup);
+ if (hwifp)
+ *hwifp = hwif;
-int ide_register_hw(hw_regs_t *hw, int initializing, ide_hwif_t **hwifp)
-{
- return ide_register_hw_with_fixup(hw, initializing, hwifp, NULL);
+ return hwif->present ? index : -1;
}
EXPORT_SYMBOL(ide_register_hw);
if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
return -EINVAL;
+ if (ide_spin_wait_hwgroup(drive))
+ return -EBUSY;
+
drive->io_32bit = arg;
-#ifdef CONFIG_BLK_DEV_DTC2278
- if (HWIF(drive)->chipset == ide_dtc2278)
- HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
-#endif /* CONFIG_BLK_DEV_DTC2278 */
+
+ spin_unlock_irq(&ide_lock);
+
return 0;
}
if (!drive->id || !(drive->id->capability & 1))
goto out;
- if (hwif->ide_dma_on == NULL)
+ if (hwif->dma_host_set == NULL)
goto out;
err = -EBUSY;
err = 0;
if (arg) {
- hwif->dma_off_quietly(drive);
- if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
+ if (ide_set_dma(drive))
err = -EIO;
} else
ide_dma_off(drive);
if (drive->special.b.set_tune)
return -EBUSY;
+
ide_init_drive_cmd(&rq);
+ rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+
drive->tune_req = (u8) arg;
drive->special.b.set_tune = 1;
(void) ide_do_drive_cmd(drive, &rq, ide_wait);
int system_bus_clock (void)
{
- return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
+ return system_bus_speed;
}
EXPORT_SYMBOL(system_bus_clock);
ide_init_hwif_ports(&hw, (unsigned long) args[0],
(unsigned long) args[1], NULL);
hw.irq = args[2];
- if (ide_register_hw(&hw, 0, NULL) == -1)
+ if (ide_register_hw(&hw, NULL, NULL) == -1)
return -EIO;
return 0;
}
return 0; /* zero = nothing matched */
}
-#ifdef CONFIG_BLK_DEV_ALI14XX
extern int probe_ali14xx;
-extern int ali14xx_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_UMC8672
extern int probe_umc8672;
-extern int umc8672_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_DTC2278
extern int probe_dtc2278;
-extern int dtc2278_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_HT6560B
extern int probe_ht6560b;
-extern int ht6560b_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_QD65XX
extern int probe_qd65xx;
-extern int qd65xx_init(void);
-#endif
+extern int cmd640_vlb;
static int __initdata is_chipset_set[MAX_HWIFS];
if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
const char *hd_words[] = {
"none", "noprobe", "nowerr", "cdrom", "nodma",
- "autotune", "noautotune", "minus8", "swapdata", "bswap",
+ "autotune", "noautotune", "-8", "-9", "-10",
"noflush", "remap", "remap63", "scsi", NULL };
unit = s[2] - 'a';
hw = unit / MAX_DRIVES;
case -7: /* "noautotune" */
drive->autotune = IDE_TUNE_NOAUTO;
goto obsolete_option;
- case -9: /* "swapdata" */
- case -10: /* "bswap" */
- drive->bswap = 1;
- goto done;
case -11: /* noflush */
drive->noflush = 1;
goto done;
"reset", "minus6", "ata66", "minus8", "minus9",
"minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb",
"dtc2278", "umc8672", "ali14xx", NULL };
+
+ hw_regs_t hwregs;
+
hw = s[3] - '0';
hwif = &ide_hwifs[hw];
i = match_parm(&s[4], ide_words, vals, 3);
#endif
#ifdef CONFIG_BLK_DEV_CMD640
case -14: /* "cmd640_vlb" */
- {
- extern int cmd640_vlb; /* flag for cmd640.c */
cmd640_vlb = 1;
goto done;
- }
#endif
#ifdef CONFIG_BLK_DEV_HT6560B
case -13: /* "ht6560b" */
case 2: /* base,ctl */
vals[2] = 0; /* default irq = probe for it */
case 3: /* base,ctl,irq */
- hwif->hw.irq = vals[2];
- ide_init_hwif_ports(&hwif->hw, (unsigned long) vals[0], (unsigned long) vals[1], &hwif->irq);
- memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+ memset(&hwregs, 0, sizeof(hwregs));
+ ide_init_hwif_ports(&hwregs, vals[0], vals[1], &hwif->irq);
+ memcpy(hwif->io_ports, hwregs.io_ports, sizeof(hwif->io_ports));
hwif->irq = vals[2];
hwif->noprobe = 0;
hwif->chipset = ide_forced;
return 1;
}
-extern void __init pnpide_init(void);
-extern void __exit pnpide_exit(void);
-extern void __init h8300_ide_init(void);
-
-/*
- * probe_for_hwifs() finds/initializes "known" IDE interfaces
- */
-static void __init probe_for_hwifs (void)
-{
-#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
- ide_scan_pcibus(ide_scan_direction);
-#endif
-
-#ifdef CONFIG_ETRAX_IDE
- {
- extern void init_e100_ide(void);
- init_e100_ide();
- }
-#endif /* CONFIG_ETRAX_IDE */
-#ifdef CONFIG_BLK_DEV_CMD640
- {
- extern void ide_probe_for_cmd640x(void);
- ide_probe_for_cmd640x();
- }
-#endif /* CONFIG_BLK_DEV_CMD640 */
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
- {
- extern int pmac_ide_probe(void);
- (void)pmac_ide_probe();
- }
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#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_Q40IDE
- {
- extern void q40ide_init(void);
- q40ide_init();
- }
-#endif /* CONFIG_BLK_DEV_Q40IDE */
-#ifdef CONFIG_BLK_DEV_BUDDHA
- {
- extern void buddha_init(void);
- buddha_init();
- }
-#endif /* CONFIG_BLK_DEV_BUDDHA */
-#ifdef CONFIG_BLK_DEV_IDEPNP
- pnpide_init();
-#endif
-#ifdef CONFIG_H8300
- h8300_ide_init();
-#endif
-}
-
-/*
- * Probe module
- */
-
EXPORT_SYMBOL(ide_lock);
static int ide_bus_match(struct device *dev, struct device_driver *drv)
return sprintf(buf, "ide:m-%s\n", media_string(drive));
}
+static ssize_t model_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->id->model);
+}
+
+static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->id->fw_rev);
+}
+
+static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->id->serial_no);
+}
+
static struct device_attribute ide_dev_attrs[] = {
__ATTR_RO(media),
__ATTR_RO(drivename),
__ATTR_RO(modalias),
+ __ATTR_RO(model),
+ __ATTR_RO(firmware),
+ __ATTR(serial, 0400, serial_show, NULL),
__ATTR_NULL
};
printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
system_bus_speed = ide_system_bus_speed();
+ printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
+ "for PIO modes%s\n", system_bus_speed,
+ idebus_parameter ? "" : "; override with idebus=xx");
+
ret = bus_register(&ide_bus_type);
if (ret < 0) {
printk(KERN_WARNING "IDE: bus_register error: %d\n", ret);
proc_ide_create();
-#ifdef CONFIG_BLK_DEV_ALI14XX
- if (probe_ali14xx)
- (void)ali14xx_init();
-#endif
-#ifdef CONFIG_BLK_DEV_UMC8672
- if (probe_umc8672)
- (void)umc8672_init();
-#endif
-#ifdef CONFIG_BLK_DEV_DTC2278
- if (probe_dtc2278)
- (void)dtc2278_init();
-#endif
-#ifdef CONFIG_BLK_DEV_HT6560B
- if (probe_ht6560b)
- (void)ht6560b_init();
-#endif
-#ifdef CONFIG_BLK_DEV_QD65XX
- if (probe_qd65xx)
- (void)qd65xx_init();
-#endif
-
- /* Probe for special PCI and other "known" interface chipsets. */
- probe_for_hwifs();
-
return 0;
}
for (index = 0; index < MAX_HWIFS; ++index)
ide_unregister(index);
-#ifdef CONFIG_BLK_DEV_IDEPNP
- pnpide_exit();
-#endif
-
proc_ide_destroy();
bus_unregister(&ide_bus_type);