]> err.no Git - linux-2.6/blobdiff - drivers/ide/pci/scc_pata.c
ide: add IDE_HFLAG_SERIALIZE_DMA host flag
[linux-2.6] / drivers / ide / pci / scc_pata.c
index 7694969b02ce1097ce730e74833a84cce06a537f..c30b0c44c705870a58db50c080d2efb4fd9e1100 100644 (file)
@@ -65,7 +65,7 @@
 
 static struct scc_ports {
        unsigned long ctl, dma;
-       unsigned char hwif_id;  /* for removing hwif from system */
+       ide_hwif_t *hwif;  /* for removing port from system */
 } scc_ports[MAX_HWIFS];
 
 /* PIO transfer mode  table */
@@ -334,7 +334,8 @@ static int scc_ide_dma_end(ide_drive_t * drive)
 
        /* errata A308 workaround: Step5 (check data loss) */
        /* We don't check non ide_disk because it is limited to UDMA4 */
-       if (!(in_be32((void __iomem *)IDE_ALTSTATUS_REG) & ERR_STAT) &&
+       if (!(in_be32((void __iomem *)hwif->io_ports[IDE_ALTSTATUS_OFFSET])
+             & ERR_STAT) &&
            drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) {
                reg = in_be32((void __iomem *)intsts_port);
                if (!(reg & INTSTS_ACTEINT)) {
@@ -437,7 +438,8 @@ static int scc_dma_test_irq(ide_drive_t *drive)
        u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014);
 
        /* SCC errata A252,A308 workaround: Step4 */
-       if ((in_be32((void __iomem *)IDE_ALTSTATUS_REG) & ERR_STAT) &&
+       if ((in_be32((void __iomem *)hwif->io_ports[IDE_ALTSTATUS_OFFSET])
+            & ERR_STAT) &&
            (int_stat & INTSTS_INTRQ))
                return 1;
 
@@ -447,7 +449,7 @@ static int scc_dma_test_irq(ide_drive_t *drive)
 
        if (!drive->waiting_for_dma)
                printk(KERN_WARNING "%s: (%s) called while not waiting\n",
-                       drive->name, __FUNCTION__);
+                       drive->name, __func__);
        return 0;
 }
 
@@ -481,7 +483,7 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
        unsigned long dma_size = pci_resource_len(dev, 1);
        void __iomem *ctl_addr;
        void __iomem *dma_addr;
-       int i;
+       int i, ret;
 
        for (i = 0; i < MAX_HWIFS; i++) {
                if (scc_ports[i].ctl == 0)
@@ -490,21 +492,17 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
        if (i >= MAX_HWIFS)
                return -ENOMEM;
 
-       if (!request_mem_region(ctl_base, ctl_size, name)) {
-               printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
-               goto fail_0;
-       }
-
-       if (!request_mem_region(dma_base, dma_size, name)) {
-               printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
-               goto fail_1;
+       ret = pci_request_selected_regions(dev, (1 << 2) - 1, name);
+       if (ret < 0) {
+               printk(KERN_ERR "%s: can't reserve resources\n", name);
+               return ret;
        }
 
        if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL)
-               goto fail_2;
+               goto fail_0;
 
        if ((dma_addr = ioremap(dma_base, dma_size)) == NULL)
-               goto fail_3;
+               goto fail_1;
 
        pci_set_master(dev);
        scc_ports[i].ctl = (unsigned long)ctl_addr;
@@ -513,16 +511,44 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
 
        return 1;
 
- fail_3:
-       iounmap(ctl_addr);
- fail_2:
-       release_mem_region(dma_base, dma_size);
  fail_1:
-       release_mem_region(ctl_base, ctl_size);
+       iounmap(ctl_addr);
  fail_0:
        return -ENOMEM;
 }
 
+static int scc_ide_setup_pci_device(struct pci_dev *dev,
+                                   const struct ide_port_info *d)
+{
+       struct scc_ports *ports = pci_get_drvdata(dev);
+       ide_hwif_t *hwif = NULL;
+       hw_regs_t hw;
+       u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+       int i;
+
+       hwif = ide_find_port();
+       if (hwif == NULL) {
+               printk(KERN_ERR "%s: too many IDE interfaces, "
+                               "no room in table\n", SCC_PATA_NAME);
+               return -ENOMEM;
+       }
+
+       memset(&hw, 0, sizeof(hw));
+       for (i = IDE_DATA_OFFSET; i <= IDE_CONTROL_OFFSET; i++)
+               hw.io_ports[i] = ports->dma + 0x20 + i * 4;
+       hw.irq = dev->irq;
+       hw.dev = &dev->dev;
+       hw.chipset = ide_pci;
+       ide_init_port_hw(hwif, &hw);
+       hwif->dev = &dev->dev;
+
+       idx[0] = hwif->index;
+
+       ide_device_add(idx, d);
+
+       return 0;
+}
+
 /**
  *     init_setup_scc  -       set up an SCC PATA Controller
  *     @dev: PCI device
@@ -545,10 +571,13 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
        struct scc_ports *ports;
        int rc;
 
+       rc = pci_enable_device(dev);
+       if (rc)
+               goto end;
+
        rc = setup_mmio_scc(dev, d->name);
-       if (rc < 0) {
-               return rc;
-       }
+       if (rc < 0)
+               goto end;
 
        ports = pci_get_drvdata(dev);
        ctl_base = ports->ctl;
@@ -583,7 +612,10 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
        out_be32((void*)mode_port, MODE_JCUSFEN);
        out_be32((void*)intmask_port, INTMASK_MSK);
 
-       return ide_setup_pci_device(dev, d);
+       rc = scc_ide_setup_pci_device(dev, d);
+
+ end:
+       return rc;
 }
 
 /**
@@ -610,17 +642,6 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
        hwif->OUTSW = scc_ide_outsw;
        hwif->OUTSL = scc_ide_outsl;
 
-       hwif->io_ports[IDE_DATA_OFFSET] = dma_base + 0x20;
-       hwif->io_ports[IDE_ERROR_OFFSET] = dma_base + 0x24;
-       hwif->io_ports[IDE_NSECTOR_OFFSET] = dma_base + 0x28;
-       hwif->io_ports[IDE_SECTOR_OFFSET] = dma_base + 0x2c;
-       hwif->io_ports[IDE_LCYL_OFFSET] = dma_base + 0x30;
-       hwif->io_ports[IDE_HCYL_OFFSET] = dma_base + 0x34;
-       hwif->io_ports[IDE_SELECT_OFFSET] = dma_base + 0x38;
-       hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c;
-       hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40;
-
-       hwif->irq = dev->irq;
        hwif->dma_base = dma_base;
        hwif->config_data = ports->ctl;
        hwif->mmio = 1;
@@ -644,6 +665,11 @@ static void __devinit init_iops_scc(ide_hwif_t *hwif)
        init_mmio_iops_scc(hwif);
 }
 
+static u8 __devinit scc_cable_detect(ide_hwif_t *hwif)
+{
+       return ATA_CBL_PATA80;
+}
+
 /**
  *     init_hwif_scc   -       set up hwif
  *     @hwif: interface to set up
@@ -657,7 +683,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
 {
        struct scc_ports *ports = ide_get_hwifdata(hwif);
 
-       ports->hwif_id = hwif->index;
+       ports->hwif = hwif;
 
        hwif->dma_command = hwif->dma_base;
        hwif->dma_status = hwif->dma_base + 0x04;
@@ -668,27 +694,28 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
 
        hwif->dma_setup = scc_dma_setup;
        hwif->ide_dma_end = scc_ide_dma_end;
-       hwif->set_pio_mode = scc_set_pio_mode;
-       hwif->set_dma_mode = scc_set_dma_mode;
        hwif->ide_dma_test_irq = scc_dma_test_irq;
-       hwif->udma_filter = scc_udma_filter;
 
        if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN)
                hwif->ultra_mask = ATA_UDMA6; /* 133MHz */
        else
                hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
-
-       /* we support 80c cable only. */
-       hwif->cbl = ATA_CBL_PATA80;
 }
 
+static const struct ide_port_ops scc_port_ops = {
+       .set_pio_mode           = scc_set_pio_mode,
+       .set_dma_mode           = scc_set_dma_mode,
+       .udma_filter            = scc_udma_filter,
+       .cable_detect           = scc_cable_detect,
+};
+
 #define DECLARE_SCC_DEV(name_str)                      \
   {                                                    \
       .name            = name_str,                     \
       .init_iops       = init_iops_scc,                \
       .init_hwif       = init_hwif_scc,                \
-      .host_flags      = IDE_HFLAG_SINGLE |            \
-                         IDE_HFLAG_BOOTABLE,           \
+      .port_ops                = &scc_port_ops,                \
+      .host_flags      = IDE_HFLAG_SINGLE,             \
       .pio_mask                = ATA_PIO4,                     \
   }
 
@@ -720,11 +747,7 @@ static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_i
 static void __devexit scc_remove(struct pci_dev *dev)
 {
        struct scc_ports *ports = pci_get_drvdata(dev);
-       ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id];
-       unsigned long ctl_base = pci_resource_start(dev, 0);
-       unsigned long dma_base = pci_resource_start(dev, 1);
-       unsigned long ctl_size = pci_resource_len(dev, 0);
-       unsigned long dma_size = pci_resource_len(dev, 1);
+       ide_hwif_t *hwif = ports->hwif;
 
        if (hwif->dmatable_cpu) {
                pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
@@ -737,8 +760,7 @@ static void __devexit scc_remove(struct pci_dev *dev)
        hwif->chipset = ide_unknown;
        iounmap((void*)ports->dma);
        iounmap((void*)ports->ctl);
-       release_mem_region(dma_base, dma_size);
-       release_mem_region(ctl_base, ctl_size);
+       pci_release_selected_regions(dev, (1 << 2) - 1);
        memset(ports, 0, sizeof(*ports));
 }