ide: add struct ide_tp_ops (take 2)
[firefly-linux-kernel-4.4.55.git] / drivers / ide / pci / ns87415.c
index bf0d3b2931f1c3202259fa40c444642cb93f07c6..5cd2b32ff0ef000d61a06047bddb19f9a911c342 100644 (file)
  */
 #include <asm/superio.h>
 
-static unsigned long superio_ide_status[2];
-static unsigned long superio_ide_select[2];
-static unsigned long superio_ide_dma_status[2];
-
 #define SUPERIO_IDE_MAX_RETRIES 25
 
 /* Because of a defect in Super I/O, all reads of the PCI DMA status 
@@ -40,57 +36,100 @@ static unsigned long superio_ide_dma_status[2];
  */
 static u8 superio_ide_inb (unsigned long port)
 {
-       if (port == superio_ide_status[0] ||
-           port == superio_ide_status[1] ||
-           port == superio_ide_select[0] ||
-           port == superio_ide_select[1] ||
-           port == superio_ide_dma_status[0] ||
-           port == superio_ide_dma_status[1]) {
-               u8 tmp;
-               int retries = SUPERIO_IDE_MAX_RETRIES;
+       u8 tmp;
+       int retries = SUPERIO_IDE_MAX_RETRIES;
 
-               /* printk(" [ reading port 0x%x with retry ] ", port); */
+       /* printk(" [ reading port 0x%x with retry ] ", port); */
 
-               do {
-                       tmp = inb(port);
-                       if (tmp == 0)
-                               udelay(50);
-               } while (tmp == 0 && retries-- > 0);
+       do {
+               tmp = inb(port);
+               if (tmp == 0)
+                       udelay(50);
+       } while (tmp == 0 && retries-- > 0);
 
-               return tmp;
-       }
+       return tmp;
+}
 
-       return inb(port);
+static u8 superio_read_status(ide_hwif_t *hwif)
+{
+       return superio_ide_inb(hwif->io_ports.status_addr);
 }
 
-static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
+static u8 superio_read_sff_dma_status(ide_hwif_t *hwif)
 {
-       struct pci_dev *pdev = to_pci_dev(hwif->dev);
-       u32 base, dmabase;
-       u8 port = hwif->channel, tmp;
+       return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS);
+}
 
-       base = pci_resource_start(pdev, port * 2) & ~3;
-       dmabase = pci_resource_start(pdev, 4) & ~3;
+static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
+{
+       struct ide_io_ports *io_ports = &drive->hwif->io_ports;
+       struct ide_taskfile *tf = &task->tf;
 
-       superio_ide_status[port] = base + IDE_STATUS_OFFSET;
-       superio_ide_select[port] = base + IDE_SELECT_OFFSET;
-       superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa);
+       if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+               u16 data = inw(io_ports->data_addr);
 
-       /* Clear error/interrupt, enable dma */
-       tmp = superio_ide_inb(superio_ide_dma_status[port]);
-       outb(tmp | 0x66, superio_ide_dma_status[port]);
+               tf->data = data & 0xff;
+               tf->hob_data = (data >> 8) & 0xff;
+       }
 
-       /* We need to override inb to workaround a SuperIO errata */
-       hwif->INB = superio_ide_inb;
+       /* be sure we're looking at the low order bits */
+       outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+
+       if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+               tf->feature = inb(io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+               tf->nsect  = inb(io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+               tf->lbal   = inb(io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+               tf->lbam   = inb(io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+               tf->lbah   = inb(io_ports->lbah_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+               tf->device = superio_ide_inb(io_ports->device_addr);
+
+       if (task->tf_flags & IDE_TFLAG_LBA48) {
+               outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
+
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+                       tf->hob_feature = inb(io_ports->feature_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+                       tf->hob_nsect   = inb(io_ports->nsect_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+                       tf->hob_lbal    = inb(io_ports->lbal_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+                       tf->hob_lbam    = inb(io_ports->lbam_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+                       tf->hob_lbah    = inb(io_ports->lbah_addr);
+       }
 }
 
-static void __devinit init_iops_ns87415(ide_hwif_t *hwif)
+static const struct ide_tp_ops superio_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = superio_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = superio_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = superio_tf_read,
+
+       .input_data             = ide_input_data,
+       .output_data            = ide_output_data,
+};
+
+static void __devinit superio_init_iops(struct hwif_s *hwif)
 {
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+       u32 dma_stat;
+       u8 port = hwif->channel, tmp;
 
-       if (PCI_SLOT(dev->devfn) == 0xE)
-               /* Built-in - assume it's under superio. */
-               superio_ide_init_iops(hwif);
+       dma_stat = (pci_resource_start(pdev, 4) & ~3) + (!port ? 2 : 0xa);
+
+       /* Clear error/interrupt, enable dma */
+       tmp = superio_ide_inb(dma_stat);
+       outb(tmp | 0x66, dma_stat);
 }
 #endif
 
@@ -150,27 +189,27 @@ static void ns87415_selectproc (ide_drive_t *drive)
        ns87415_prepare_drive (drive, drive->using_dma);
 }
 
-static int ns87415_ide_dma_end (ide_drive_t *drive)
+static int ns87415_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t      *hwif = HWIF(drive);
        u8 dma_stat = 0, dma_cmd = 0;
 
        drive->waiting_for_dma = 0;
-       dma_stat = hwif->INB(hwif->dma_status);
-       /* get dma command mode */
-       dma_cmd = hwif->INB(hwif->dma_command);
+       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+       /* get DMA command mode */
+       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
        /* stop DMA */
-       outb(dma_cmd & ~1, hwif->dma_command);
+       outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
        /* from ERRATA: clear the INTR & ERROR bits */
-       dma_cmd = hwif->INB(hwif->dma_command);
-       outb(dma_cmd | 6, hwif->dma_command);
+       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+       outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD);
        /* and free any DMA resources */
        ide_destroy_dmatable(drive);
        /* verify good DMA status */
        return (dma_stat & 7) != 4;
 }
 
-static int ns87415_ide_dma_setup(ide_drive_t *drive)
+static int ns87415_dma_setup(ide_drive_t *drive)
 {
        /* select DMA xfer */
        ns87415_prepare_drive(drive, 1);
@@ -191,8 +230,6 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
        u8 stat;
 #endif
 
-       hwif->selectproc = &ns87415_selectproc;
-
        /*
         * We cannot probe for IRQ: both ports share common IRQ on INTA.
         * Also, leave IRQ masked during drive probing, to prevent infinite
@@ -229,12 +266,12 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
                 *      SELECT_DRIVE() properly during first ide_probe_port().
                 */
                timeout = 10000;
-               outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+               outb(12, hwif->io_ports.ctl_addr);
                udelay(10);
-               outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+               outb(8, hwif->io_ports.ctl_addr);
                do {
                        udelay(50);
-                       stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+                       stat = hwif->tp_ops->read_status(hwif);
                        if (stat == 0xff)
                                break;
                } while ((stat & BUSY_STAT) && --timeout);
@@ -242,32 +279,52 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
        }
 
        if (!using_inta)
-               hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
+               hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
        else if (!hwif->irq && hwif->mate && hwif->mate->irq)
                hwif->irq = hwif->mate->irq;    /* share IRQ with mate */
 
        if (!hwif->dma_base)
                return;
 
-       outb(0x60, hwif->dma_status);
-       hwif->dma_setup = &ns87415_ide_dma_setup;
-       hwif->ide_dma_end = &ns87415_ide_dma_end;
+       outb(0x60, hwif->dma_base + ATA_DMA_STATUS);
 }
 
+static const struct ide_port_ops ns87415_port_ops = {
+       .selectproc             = ns87415_selectproc,
+};
+
+static const struct ide_dma_ops ns87415_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ns87415_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = ns87415_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
 static const struct ide_port_info ns87415_chipset __devinitdata = {
        .name           = "NS87415",
-#ifdef CONFIG_SUPERIO
-       .init_iops      = init_iops_ns87415,
-#endif
        .init_hwif      = init_hwif_ns87415,
+       .port_ops       = &ns87415_port_ops,
+       .dma_ops        = &ns87415_dma_ops,
        .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                         IDE_HFLAG_NO_ATAPI_DMA |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_NO_ATAPI_DMA,
 };
 
 static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &ns87415_chipset);
+       struct ide_port_info d = ns87415_chipset;
+
+#ifdef CONFIG_SUPERIO
+       if (PCI_SLOT(dev->devfn) == 0xE) {
+               /* Built-in - assume it's under superio. */
+               d.init_iops = superio_init_iops;
+               d.tp_ops = &superio_tp_ops;
+       }
+#endif
+       return ide_setup_pci_device(dev, &d);
 }
 
 static const struct pci_device_id ns87415_pci_tbl[] = {