#include <linux/pci.h>
#include <linux/init.h>
#include <linux/list.h>
-#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/spinlock.h>
#include <linux/blkdev.h>
}
/**
- * ata_check_status_pio - Read device status reg & clear interrupt
+ * ata_check_status - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
return ata_check_status_pio(ap);
}
-u8 ata_altstatus(struct ata_port *ap)
-{
- if (ap->ops->check_altstatus)
- return ap->ops->check_altstatus(ap);
-
- if (ap->flags & ATA_FLAG_MMIO)
- return readb((void __iomem *)ap->ioaddr.altstatus_addr);
- return inb(ap->ioaddr.altstatus_addr);
-}
-
-u8 ata_chk_err(struct ata_port *ap)
-{
- if (ap->ops->check_err)
- return ap->ops->check_err(ap);
-
- if (ap->flags & ATA_FLAG_MMIO) {
- return readb((void __iomem *) ap->ioaddr.error_addr);
- }
- return inb(ap->ioaddr.error_addr);
-}
-
/**
* ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
* @tf: Taskfile to convert
printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
ap->id, device);
err_out:
+ ata_irq_on(ap); /* re-enable interrupts */
dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */
DPRINTK("EXIT, err\n");
}
ata_dev_try_classify(ap, 1);
/* re-enable interrupts */
- if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
- ata_irq_on(ap);
+ ata_irq_on(ap);
/* is double-select really necessary? */
if (ap->device[1].class != ATA_DEV_NONE)
DPRINTK("EXIT\n");
}
-static void ata_pr_blacklisted(struct ata_port *ap, struct ata_device *dev)
-{
- printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n",
- ap->id, dev->devno);
-}
-
-static const char * ata_dma_blacklist [] = {
- "WDC AC11000H",
- "WDC AC22100H",
- "WDC AC32500H",
- "WDC AC33100H",
- "WDC AC31600H",
- "WDC AC32100H",
- "WDC AC23200L",
- "Compaq CRD-8241B",
- "CRD-8400B",
- "CRD-8480B",
- "CRD-8482B",
- "CRD-84",
- "SanDisk SDP3B",
- "SanDisk SDP3B-64",
- "SANYO CD-ROM CRD",
- "HITACHI CDR-8",
- "HITACHI CDR-8335",
- "HITACHI CDR-8435",
- "Toshiba CD-ROM XM-6202B",
- "CD-532E-A",
- "E-IDE CD-ROM CR-840",
- "CD-ROM Drive/F5A",
- "WPI CDD-820",
- "SAMSUNG CD-ROM SC-148C",
- "SAMSUNG CD-ROM SC",
- "SanDisk SDP3B-64",
- "SAMSUNG CD-ROM SN-124",
- "ATAPI CD-ROM DRIVE 40X MAXIMUM",
- "_NEC DV5800A",
-};
-
-static int ata_dma_blacklisted(struct ata_port *ap, struct ata_device *dev)
-{
- unsigned char model_num[40];
- char *s;
- unsigned int len;
- int i;
-
- ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
- sizeof(model_num));
- s = &model_num[0];
- len = strnlen(s, sizeof(model_num));
-
- /* ATAPI specifies that empty space is blank-filled; remove blanks */
- while ((len > 0) && (s[len - 1] == ' ')) {
- len--;
- s[len] = 0;
- }
-
- for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++)
- if (!strncmp(ata_dma_blacklist[i], s, len))
- return 1;
-
- return 0;
-}
-
static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
{
struct ata_device *master, *slave;
if (shift == ATA_SHIFT_UDMA) {
mask = ap->udma_mask;
- if (ata_dev_present(master)) {
+ if (ata_dev_present(master))
mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
- if (ata_dma_blacklisted(ap, master)) {
- mask = 0;
- ata_pr_blacklisted(ap, master);
- }
- }
- if (ata_dev_present(slave)) {
+ if (ata_dev_present(slave))
mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
- if (ata_dma_blacklisted(ap, slave)) {
- mask = 0;
- ata_pr_blacklisted(ap, slave);
- }
- }
}
else if (shift == ATA_SHIFT_MWDMA) {
mask = ap->mwdma_mask;
- if (ata_dev_present(master)) {
+ if (ata_dev_present(master))
mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
- if (ata_dma_blacklisted(ap, master)) {
- mask = 0;
- ata_pr_blacklisted(ap, master);
- }
- }
- if (ata_dev_present(slave)) {
+ if (ata_dev_present(slave))
mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
- if (ata_dma_blacklisted(ap, slave)) {
- mask = 0;
- ata_pr_blacklisted(ap, slave);
- }
- }
}
else if (shift == ATA_SHIFT_PIO) {
mask = ap->pio_mask;
case ATA_PROT_DMA:
case ATA_PROT_ATAPI_DMA:
- host_stat = ap->ops->bmdma_status(ap);
+ host_stat = ata_bmdma_status(ap);
/* before we do anything else, clear DMA-Start bit */
- ap->ops->bmdma_stop(ap);
+ ata_bmdma_stop(ap);
/* fall through */
drv_stat = ata_chk_status(ap);
/* ack bmdma irq events */
- ap->ops->irq_clear(ap);
+ ata_bmdma_ack_irq(ap);
printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
ap->id, qc->tf.command, drv_stat, host_stat);
clear_bit(tag, &ap->qactive);
}
-/**
- * ata_qc_free - free unused ata_queued_cmd
- * @qc: Command to complete
- *
- * Designed to free unused ata_queued_cmd object
- * in case something prevents using it.
- *
- * LOCKING:
- *
- */
-void ata_qc_free(struct ata_queued_cmd *qc)
-{
- assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
- assert(qc->waiting == NULL); /* nothing should be waiting */
-
- __ata_qc_complete(qc);
-}
-
/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
return 1;
/* fall through */
-
+
default:
return 0;
}
void ata_bmdma_irq_clear(struct ata_port *ap)
{
- if (ap->flags & ATA_FLAG_MMIO) {
- void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
- writeb(readb(mmio), mmio);
- } else {
- unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
- outb(inb(addr), addr);
- }
-
-}
-
-u8 ata_bmdma_status(struct ata_port *ap)
-{
- u8 host_stat;
- if (ap->flags & ATA_FLAG_MMIO) {
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
- host_stat = readb(mmio + ATA_DMA_STATUS);
- } else
- host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
- return host_stat;
-}
-
-void ata_bmdma_stop(struct ata_port *ap)
-{
- if (ap->flags & ATA_FLAG_MMIO) {
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-
- /* clear start/stop bit */
- writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
- mmio + ATA_DMA_CMD);
- } else {
- /* clear start/stop bit */
- outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
- ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- }
-
- /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
- ata_altstatus(ap); /* dummy read */
+ ata_bmdma_ack_irq(ap);
}
/**
case ATA_PROT_ATAPI_DMA:
case ATA_PROT_ATAPI:
/* check status of DMA engine */
- host_stat = ap->ops->bmdma_status(ap);
+ host_stat = ata_bmdma_status(ap);
VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
/* if it's not our irq... */
goto idle_irq;
/* before we do anything else, clear DMA-Start bit */
- ap->ops->bmdma_stop(ap);
+ ata_bmdma_stop(ap);
/* fall through */
ap->id, qc->tf.protocol, status);
/* ack bmdma irq events */
- ap->ops->irq_clear(ap);
+ ata_bmdma_ack_irq(ap);
/* complete taskfile transaction */
ata_qc_complete(qc, status);
}
static struct ata_probe_ent *
-ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
+ata_probe_ent_alloc(int n, struct device *dev, struct ata_port_info **port)
{
struct ata_probe_ent *probe_ent;
+ int i;
- probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+ probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL);
if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
kobject_name(&(dev->kobj)));
return NULL;
}
- memset(probe_ent, 0, sizeof(*probe_ent));
+ memset(probe_ent, 0, sizeof(*probe_ent) * n);
+
+ for (i = 0; i < n; i++) {
+ INIT_LIST_HEAD(&probe_ent[i].node);
+ probe_ent[i].dev = dev;
- INIT_LIST_HEAD(&probe_ent->node);
- probe_ent->dev = dev;
+ probe_ent[i].sht = port[i]->sht;
+ probe_ent[i].host_flags = port[i]->host_flags;
+ probe_ent[i].pio_mask = port[i]->pio_mask;
+ probe_ent[i].mwdma_mask = port[i]->mwdma_mask;
+ probe_ent[i].udma_mask = port[i]->udma_mask;
+ probe_ent[i].port_ops = port[i]->port_ops;
- probe_ent->sht = port->sht;
- probe_ent->host_flags = port->host_flags;
- probe_ent->pio_mask = port->pio_mask;
- probe_ent->mwdma_mask = port->mwdma_mask;
- probe_ent->udma_mask = port->udma_mask;
- probe_ent->port_ops = port->port_ops;
+ }
return probe_ent;
}
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
{
struct ata_probe_ent *probe_ent =
- ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+ ata_probe_ent_alloc(1, pci_dev_to_dev(pdev), port);
if (!probe_ent)
return NULL;
return probe_ent;
}
-static struct ata_probe_ent *
-ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
- struct ata_probe_ent **ppe2)
+struct ata_probe_ent *
+ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port)
{
- struct ata_probe_ent *probe_ent, *probe_ent2;
-
- probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+ struct ata_probe_ent *probe_ent =
+ ata_probe_ent_alloc(2, pci_dev_to_dev(pdev), port);
if (!probe_ent)
return NULL;
- probe_ent2 = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[1]);
- if (!probe_ent2) {
- kfree(probe_ent);
- return NULL;
- }
- probe_ent->n_ports = 1;
- probe_ent->irq = 14;
+ probe_ent[0].n_ports = 1;
+ probe_ent[0].irq = 14;
- probe_ent->hard_port_no = 0;
- probe_ent->legacy_mode = 1;
+ probe_ent[0].hard_port_no = 0;
+ probe_ent[0].legacy_mode = 1;
- probe_ent2->n_ports = 1;
- probe_ent2->irq = 15;
+ probe_ent[1].n_ports = 1;
+ probe_ent[1].irq = 15;
- probe_ent2->hard_port_no = 1;
- probe_ent2->legacy_mode = 1;
+ probe_ent[1].hard_port_no = 1;
+ probe_ent[1].legacy_mode = 1;
- probe_ent->port[0].cmd_addr = 0x1f0;
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr = 0x3f6;
- probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+ probe_ent[0].port[0].cmd_addr = 0x1f0;
+ probe_ent[0].port[0].altstatus_addr =
+ probe_ent[0].port[0].ctl_addr = 0x3f6;
+ probe_ent[0].port[0].bmdma_addr = pci_resource_start(pdev, 4);
- probe_ent2->port[0].cmd_addr = 0x170;
- probe_ent2->port[0].altstatus_addr =
- probe_ent2->port[0].ctl_addr = 0x376;
- probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
+ probe_ent[1].port[0].cmd_addr = 0x170;
+ probe_ent[1].port[0].altstatus_addr =
+ probe_ent[1].port[0].ctl_addr = 0x376;
+ probe_ent[1].port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
- ata_std_ports(&probe_ent->port[0]);
- ata_std_ports(&probe_ent2->port[0]);
+ ata_std_ports(&probe_ent[0].port[0]);
+ ata_std_ports(&probe_ent[1].port[0]);
- *ppe2 = probe_ent2;
return probe_ent;
}
struct ata_port_info *port[2];
u8 tmp8, mask;
unsigned int legacy_mode = 0;
- int disable_dev_on_err = 1;
int rc;
DPRINTK("ENTER\n");
else
port[1] = port[0];
- if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
- && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
+ if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
/* TODO: support transitioning to native mode? */
pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
mask = (1 << 2) | (1 << 0);
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc) {
- disable_dev_on_err = 0;
+ if (rc)
goto err_out;
- }
if (legacy_mode) {
if (!request_region(0x1f0, 8, "libata")) {
conflict = ____request_resource(&ioport_resource, &res);
if (!strcmp(conflict->name, "libata"))
legacy_mode |= (1 << 0);
- else {
- disable_dev_on_err = 0;
+ else
printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
- }
} else
legacy_mode |= (1 << 0);
conflict = ____request_resource(&ioport_resource, &res);
if (!strcmp(conflict->name, "libata"))
legacy_mode |= (1 << 1);
- else {
- disable_dev_on_err = 0;
+ else
printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
- }
} else
legacy_mode |= (1 << 1);
}
goto err_out_regions;
if (legacy_mode) {
- probe_ent = ata_pci_init_legacy_mode(pdev, port, &probe_ent2);
+ probe_ent = ata_pci_init_legacy_mode(pdev, port);
+ if (probe_ent)
+ probe_ent2 = &probe_ent[1];
} else
probe_ent = ata_pci_init_native_mode(pdev, port);
if (!probe_ent) {
ata_device_add(probe_ent);
if (legacy_mode & (1 << 1))
ata_device_add(probe_ent2);
- } else
+ } else {
ata_device_add(probe_ent);
-
+ }
kfree(probe_ent);
- kfree(probe_ent2);
return 0;
release_region(0x170, 8);
pci_release_regions(pdev);
err_out:
- if (disable_dev_on_err)
- pci_disable_device(pdev);
+ pci_disable_device(pdev);
return rc;
}
EXPORT_SYMBOL_GPL(ata_tf_to_fis);
EXPORT_SYMBOL_GPL(ata_tf_from_fis);
EXPORT_SYMBOL_GPL(ata_check_status);
-EXPORT_SYMBOL_GPL(ata_altstatus);
-EXPORT_SYMBOL_GPL(ata_chk_err);
EXPORT_SYMBOL_GPL(ata_exec_command);
EXPORT_SYMBOL_GPL(ata_port_start);
EXPORT_SYMBOL_GPL(ata_port_stop);
EXPORT_SYMBOL_GPL(ata_bmdma_setup);
EXPORT_SYMBOL_GPL(ata_bmdma_start);
EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
-EXPORT_SYMBOL_GPL(ata_bmdma_status);
-EXPORT_SYMBOL_GPL(ata_bmdma_stop);
EXPORT_SYMBOL_GPL(ata_port_probe);
EXPORT_SYMBOL_GPL(sata_phy_reset);
EXPORT_SYMBOL_GPL(__sata_phy_reset);
#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
+EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);