pata_it8213: fix it8213_pre_reset() documentation
[safe/jmp/linux-2.6] / drivers / ata / pata_icside.c
index d7621a3..b663b7f 100644 (file)
@@ -45,8 +45,6 @@ static const struct portinfo pata_icside_portinfo_v6_2 = {
        .stepping       = 6,
 };
 
-#define PATA_ICSIDE_MAX_SG     128
-
 struct pata_icside_state {
        void __iomem *irq_port;
        void __iomem *ioc_base;
@@ -57,7 +55,20 @@ struct pata_icside_state {
                u8 disabled;
                unsigned int speed[ATA_MAX_DEVICES];
        } port[2];
-       struct scatterlist sg[PATA_ICSIDE_MAX_SG];
+};
+
+struct pata_icside_info {
+       struct pata_icside_state *state;
+       struct expansion_card   *ec;
+       void __iomem            *base;
+       void __iomem            *irqaddr;
+       unsigned int            irqmask;
+       const expansioncard_ops_t *irqops;
+       unsigned int            mwdma_mask;
+       unsigned int            nr_ports;
+       const struct portinfo   *port[2];
+       unsigned long           raw_base;
+       unsigned long           raw_ioc_base;
 };
 
 #define ICS_TYPE_A3IN  0
@@ -208,7 +219,6 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct pata_icside_state *state = ap->host->private_data;
-       struct scatterlist *sg, *rsg = state->sg;
        unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
 
        /*
@@ -218,24 +228,16 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
        BUG_ON(dma_channel_active(state->dma));
 
        /*
-        * Copy ATAs scattered sg list into a contiguous array of sg
-        */
-       ata_for_each_sg(sg, qc) {
-               memcpy(rsg, sg, sizeof(*sg));
-               rsg++;
-       }
-
-       /*
         * Route the DMA signals to the correct interface
         */
        writeb(state->port[ap->port_no].port_sel, state->ioc_base);
 
        set_dma_speed(state->dma, state->port[ap->port_no].speed[qc->dev->devno]);
-       set_dma_sg(state->dma, state->sg, rsg - state->sg);
+       set_dma_sg(state->dma, qc->sg, qc->n_elem);
        set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ);
 
        /* issue r/w command */
-       ap->ops->exec_command(ap, &qc->tf);
+       ap->ops->sff_exec_command(ap, &qc->tf);
 }
 
 static void pata_icside_bmdma_start(struct ata_queued_cmd *qc)
@@ -255,7 +257,7 @@ static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc)
        disable_dma(state->dma);
 
        /* see ata_bmdma_stop */
-       ata_altstatus(ap);
+       ata_sff_dma_pause(ap);
 }
 
 static u8 pata_icside_bmdma_status(struct ata_port *ap)
@@ -269,9 +271,10 @@ static u8 pata_icside_bmdma_status(struct ata_port *ap)
        return readb(irq_port) & 1 ? ATA_DMA_INTR : 0;
 }
 
-static int icside_dma_init(struct ata_probe_ent *ae, struct expansion_card *ec)
+static int icside_dma_init(struct pata_icside_info *info)
 {
-       struct pata_icside_state *state = ae->private_data;
+       struct pata_icside_state *state = info->state;
+       struct expansion_card *ec = info->ec;
        int i;
 
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
@@ -281,53 +284,26 @@ static int icside_dma_init(struct ata_probe_ent *ae, struct expansion_card *ec)
 
        if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
                state->dma = ec->dma;
-               ae->mwdma_mask = 0x07;  /* MW0..2 */
+               info->mwdma_mask = ATA_MWDMA2;
        }
 
        return 0;
 }
 
 
-static int pata_icside_port_start(struct ata_port *ap)
-{
-       /* No PRD to alloc */
-       return ata_pad_alloc(ap, ap->dev);
-}
-
 static struct scsi_host_template pata_icside_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = PATA_ICSIDE_MAX_SG,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ~0, /* no dma boundaries */
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
+       ATA_BASE_SHT(DRV_NAME),
+       .sg_tablesize           = SCSI_MAX_SG_CHAIN_SEGMENTS,
+       .dma_boundary           = IOMD_DMA_BOUNDARY,
 };
 
-/* wish this was exported from libata-core */
-static void ata_dummy_noret(struct ata_port *port)
-{
-}
-
-/*
- * We need to shut down unused ports to prevent spurious interrupts.
- * FIXME: the libata core doesn't call this function for PATA interfaces.
- */
-static void pata_icside_port_disable(struct ata_port *ap)
+static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
 {
+       struct ata_port *ap = link->ap;
        struct pata_icside_state *state = ap->host->private_data;
 
-       ata_port_printk(ap, KERN_ERR, "disabling icside port\n");
-
-       ata_port_disable(ap);
+       if (classes[0] != ATA_DEV_NONE || classes[1] != ATA_DEV_NONE)
+               return ata_sff_postreset(link, classes);
 
        state->port[ap->port_no].disabled = 1;
 
@@ -343,134 +319,93 @@ static void pata_icside_port_disable(struct ata_port *ap)
        }
 }
 
-static u8 pata_icside_irq_ack(struct ata_port *ap, unsigned int chk_drq)
-{
-       unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
-       u8 status;
-
-       status = ata_busy_wait(ap, bits, 1000);
-       if (status & bits)
-               if (ata_msg_err(ap))
-                       printk(KERN_ERR "abnormal status 0x%X\n", status);
-
-       if (ata_msg_intr(ap))
-               printk(KERN_INFO "%s: irq ack: drv_stat 0x%X\n",
-                       __FUNCTION__, status);
-
-       return status;
-}
-
 static struct ata_port_operations pata_icside_port_ops = {
-       .port_disable           = pata_icside_port_disable,
-
-       .set_dmamode            = pata_icside_set_dmamode,
-
-       .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
-       .exec_command           = ata_exec_command,
-       .check_status           = ata_check_status,
-       .dev_select             = ata_std_dev_select,
-
-       .bmdma_setup            = pata_icside_bmdma_setup,
-       .bmdma_start            = pata_icside_bmdma_start,
-
-       .data_xfer              = ata_data_xfer_noirq,
-
+       .inherits               = &ata_sff_port_ops,
        /* no need to build any PRD tables for DMA */
        .qc_prep                = ata_noop_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
-       .error_handler          = ata_bmdma_error_handler,
-       .post_internal_cmd      = pata_icside_bmdma_stop,
-
-       .irq_handler            = ata_interrupt,
-       .irq_clear              = ata_dummy_noret,
-       .irq_on                 = ata_irq_on,
-       .irq_ack                = pata_icside_irq_ack,
-
-       .port_start             = pata_icside_port_start,
-
+       .sff_data_xfer          = ata_sff_data_xfer_noirq,
+       .bmdma_setup            = pata_icside_bmdma_setup,
+       .bmdma_start            = pata_icside_bmdma_start,
        .bmdma_stop             = pata_icside_bmdma_stop,
        .bmdma_status           = pata_icside_bmdma_status,
+
+       .cable_detect           = ata_cable_40wire,
+       .set_dmamode            = pata_icside_set_dmamode,
+       .postreset              = pata_icside_postreset,
+       .post_internal_cmd      = pata_icside_bmdma_stop,
 };
 
-static void
-pata_icside_add_port(struct ata_probe_ent *ae, void __iomem *base,
-                    const struct portinfo *info)
+static void __devinit
+pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base,
+                        struct pata_icside_info *info,
+                        const struct portinfo *port)
 {
-       struct ata_ioports *ioaddr = &ae->port[ae->n_ports++];
-       void __iomem *cmd = base + info->dataoffset;
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       void __iomem *cmd = base + port->dataoffset;
 
        ioaddr->cmd_addr        = cmd;
-       ioaddr->data_addr       = cmd + (ATA_REG_DATA    << info->stepping);
-       ioaddr->error_addr      = cmd + (ATA_REG_ERR     << info->stepping);
-       ioaddr->feature_addr    = cmd + (ATA_REG_FEATURE << info->stepping);
-       ioaddr->nsect_addr      = cmd + (ATA_REG_NSECT   << info->stepping);
-       ioaddr->lbal_addr       = cmd + (ATA_REG_LBAL    << info->stepping);
-       ioaddr->lbam_addr       = cmd + (ATA_REG_LBAM    << info->stepping);
-       ioaddr->lbah_addr       = cmd + (ATA_REG_LBAH    << info->stepping);
-       ioaddr->device_addr     = cmd + (ATA_REG_DEVICE  << info->stepping);
-       ioaddr->status_addr     = cmd + (ATA_REG_STATUS  << info->stepping);
-       ioaddr->command_addr    = cmd + (ATA_REG_CMD     << info->stepping);
-
-       ioaddr->ctl_addr        = base + info->ctrloffset;
+       ioaddr->data_addr       = cmd + (ATA_REG_DATA    << port->stepping);
+       ioaddr->error_addr      = cmd + (ATA_REG_ERR     << port->stepping);
+       ioaddr->feature_addr    = cmd + (ATA_REG_FEATURE << port->stepping);
+       ioaddr->nsect_addr      = cmd + (ATA_REG_NSECT   << port->stepping);
+       ioaddr->lbal_addr       = cmd + (ATA_REG_LBAL    << port->stepping);
+       ioaddr->lbam_addr       = cmd + (ATA_REG_LBAM    << port->stepping);
+       ioaddr->lbah_addr       = cmd + (ATA_REG_LBAH    << port->stepping);
+       ioaddr->device_addr     = cmd + (ATA_REG_DEVICE  << port->stepping);
+       ioaddr->status_addr     = cmd + (ATA_REG_STATUS  << port->stepping);
+       ioaddr->command_addr    = cmd + (ATA_REG_CMD     << port->stepping);
+
+       ioaddr->ctl_addr        = base + port->ctrloffset;
        ioaddr->altstatus_addr  = ioaddr->ctl_addr;
+
+       ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
+                     info->raw_base + port->dataoffset,
+                     info->raw_base + port->ctrloffset);
+
+       if (info->raw_ioc_base)
+               ata_port_desc(ap, "iocbase 0x%lx", info->raw_ioc_base);
 }
 
-static int __init
-pata_icside_register_v5(struct ata_probe_ent *ae, struct expansion_card *ec)
+static int __devinit pata_icside_register_v5(struct pata_icside_info *info)
 {
-       struct pata_icside_state *state = ae->private_data;
+       struct pata_icside_state *state = info->state;
        void __iomem *base;
 
-       base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
-                      ecard_resource_len(ec, ECARD_RES_MEMC));
+       base = ecardm_iomap(info->ec, ECARD_RES_MEMC, 0, 0);
        if (!base)
                return -ENOMEM;
 
        state->irq_port = base;
 
-       ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
-       ec->irqmask = 1;
+       info->base = base;
+       info->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
+       info->irqmask = 1;
+       info->irqops = &pata_icside_ops_arcin_v5;
+       info->nr_ports = 1;
+       info->port[0] = &pata_icside_portinfo_v5;
 
-       ecard_setirq(ec, &pata_icside_ops_arcin_v5, state);
-
-       /*
-        * Be on the safe side - disable interrupts
-        */
-       ec->ops->irqdisable(ec, ec->irq);
-
-       pata_icside_add_port(ae, base, &pata_icside_portinfo_v5);
+       info->raw_base = ecard_resource_start(info->ec, ECARD_RES_MEMC);
 
        return 0;
 }
 
-static int __init
-pata_icside_register_v6(struct ata_probe_ent *ae, struct expansion_card *ec)
+static int __devinit pata_icside_register_v6(struct pata_icside_info *info)
 {
-       struct pata_icside_state *state = ae->private_data;
+       struct pata_icside_state *state = info->state;
+       struct expansion_card *ec = info->ec;
        void __iomem *ioc_base, *easi_base;
        unsigned int sel = 0;
-       int ret;
 
-       ioc_base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
-                          ecard_resource_len(ec, ECARD_RES_IOCFAST));
-       if (!ioc_base) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
+       if (!ioc_base)
+               return -ENOMEM;
 
        easi_base = ioc_base;
 
        if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
-               easi_base = ioremap(ecard_resource_start(ec, ECARD_RES_EASI),
-                                   ecard_resource_len(ec, ECARD_RES_EASI));
-               if (!easi_base) {
-                       ret = -ENOMEM;
-                       goto unmap_slot;
-               }
+               easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0);
+               if (!easi_base)
+                       return -ENOMEM;
 
                /*
                 * Enable access to the EASI region.
@@ -480,44 +415,68 @@ pata_icside_register_v6(struct ata_probe_ent *ae, struct expansion_card *ec)
 
        writeb(sel, ioc_base);
 
-       ecard_setirq(ec, &pata_icside_ops_arcin_v6, state);
-
        state->irq_port = easi_base;
        state->ioc_base = ioc_base;
        state->port[0].port_sel = sel;
        state->port[1].port_sel = sel | 1;
 
+       info->base = easi_base;
+       info->irqops = &pata_icside_ops_arcin_v6;
+       info->nr_ports = 2;
+       info->port[0] = &pata_icside_portinfo_v6_1;
+       info->port[1] = &pata_icside_portinfo_v6_2;
+
+       info->raw_base = ecard_resource_start(ec, ECARD_RES_EASI);
+       info->raw_ioc_base = ecard_resource_start(ec, ECARD_RES_IOCFAST);
+
+       return icside_dma_init(info);
+}
+
+static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
+{
+       struct expansion_card *ec = info->ec;
+       struct ata_host *host;
+       int i;
+
+       if (info->irqaddr) {
+               ec->irqaddr = info->irqaddr;
+               ec->irqmask = info->irqmask;
+       }
+       if (info->irqops)
+               ecard_setirq(ec, info->irqops, info->state);
+
        /*
         * Be on the safe side - disable interrupts
         */
        ec->ops->irqdisable(ec, ec->irq);
 
-       /*
-        * Find and register the interfaces.
-        */
-       pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_1);
-       pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_2);
+       host = ata_host_alloc(&ec->dev, info->nr_ports);
+       if (!host)
+               return -ENOMEM;
 
-       /*
-        * FIXME: work around libata's aversion to calling port_disable.
-        * This permanently disables interrupts on port 0 - bad luck if
-        * you have a drive on that port.
-        */
-       state->port[0].disabled = 1;
+       host->private_data = info->state;
+       host->flags = ATA_HOST_SIMPLEX;
 
-       return icside_dma_init(ae, ec);
+       for (i = 0; i < info->nr_ports; i++) {
+               struct ata_port *ap = host->ports[i];
 
- unmap_slot:
-       iounmap(ioc_base);
- out:
-       return ret;
+               ap->pio_mask = ATA_PIO4;
+               ap->mwdma_mask = info->mwdma_mask;
+               ap->flags |= ATA_FLAG_SLAVE_POSS;
+               ap->ops = &pata_icside_port_ops;
+
+               pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]);
+       }
+
+       return ata_host_activate(host, ec->irq, ata_sff_interrupt, 0,
+                                &pata_icside_sht);
 }
 
 static int __devinit
 pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        struct pata_icside_state *state;
-       struct ata_probe_ent ae;
+       struct pata_icside_info info;
        void __iomem *idmem;
        int ret;
 
@@ -525,7 +484,7 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
        if (ret)
                goto out;
 
-       state = kzalloc(sizeof(struct pata_icside_state), GFP_KERNEL);
+       state = devm_kzalloc(&ec->dev, sizeof(*state), GFP_KERNEL);
        if (!state) {
                ret = -ENOMEM;
                goto release;
@@ -534,8 +493,7 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
        state->type = ICS_TYPE_NOTYPE;
        state->dma = NO_DMA;
 
-       idmem = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
-                       ecard_resource_len(ec, ECARD_RES_IOCFAST));
+       idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
        if (idmem) {
                unsigned int type;
 
@@ -543,21 +501,14 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
                type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
                type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
                type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
-               iounmap(idmem);
+               ecardm_iounmap(ec, idmem);
 
                state->type = type;
        }
 
-       memset(&ae, 0, sizeof(ae));
-       INIT_LIST_HEAD(&ae.node);
-       ae.dev          = &ec->dev;
-       ae.port_ops     = &pata_icside_port_ops;
-       ae.sht          = &pata_icside_sht;
-       ae.pio_mask     = 0x1f;
-       ae.irq          = ec->irq;
-       ae.port_flags   = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
-       ae._host_flags  = ATA_HOST_SIMPLEX;
-       ae.private_data = state;
+       memset(&info, 0, sizeof(info));
+       info.state = state;
+       info.ec = ec;
 
        switch (state->type) {
        case ICS_TYPE_A3IN:
@@ -571,11 +522,11 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
                break;
 
        case ICS_TYPE_V5:
-               ret = pata_icside_register_v5(&ae, ec);
+               ret = pata_icside_register_v5(&info);
                break;
 
        case ICS_TYPE_V6:
-               ret = pata_icside_register_v6(&ae, ec);
+               ret = pata_icside_register_v6(&info);
                break;
 
        default:
@@ -585,12 +536,11 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
        }
 
        if (ret == 0)
-               ret = ata_device_add(&ae) == 0 ? -ENODEV : 0;
+               ret = pata_icside_add_ports(&info);
 
        if (ret == 0)
                goto out;
 
-       kfree(state);
  release:
        ecard_release_resources(ec);
  out:
@@ -638,12 +588,7 @@ static void __devexit pata_icside_remove(struct expansion_card *ec)
         */
        if (state->dma != NO_DMA)
                free_dma(state->dma);
-       if (state->ioc_base)
-               iounmap(state->ioc_base);
-       if (state->ioc_base != state->irq_port)
-               iounmap(state->irq_port);
 
-       kfree(state);
        ecard_release_resources(ec);
 }