libata: implement drain buffers
[safe/jmp/linux-2.6] / drivers / ata / pata_it821x.c
index e8afd48..109ddd4 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * ata-it821x.c        - IT821x PATA for new ATA layer
+ * pata_it821x.c       - IT821x PATA for new ATA layer
  *                       (C) 2005 Red Hat Inc
  *                       Alan Cox <alan@redhat.com>
+ *                       (C) 2007 Bartlomiej Zolnierkiewicz
  *
  * based upon
  *
@@ -65,7 +66,6 @@
  *
  *  TODO
  *     -       ATAPI and other speed filtering
- *     -       Command filter in smart mode
  *     -       RAID configuration ioctls
  */
 
@@ -80,7 +80,7 @@
 
 
 #define DRV_NAME "pata_it821x"
-#define DRV_VERSION "0.3.3"
+#define DRV_VERSION "0.3.8"
 
 struct it821x_dev
 {
@@ -105,7 +105,7 @@ struct it821x_dev
 
 /*
  *     We allow users to force the card into non raid mode without
- *     flashing the alternative BIOS. This is also neccessary right now
+ *     flashing the alternative BIOS. This is also necessary right now
  *     for embedded platforms that cannot run a PC BIOS but are using this
  *     device.
  */
@@ -113,31 +113,6 @@ struct it821x_dev
 static int it8212_noraid;
 
 /**
- *     it821x_pre_reset        -       probe
- *     @ap: ATA port
- *
- *     Set the cable type
- */
-
-static int it821x_pre_reset(struct ata_port *ap)
-{
-       ap->cbl = ATA_CBL_PATA80;
-       return ata_std_prereset(ap);
-}
-
-/**
- *     it821x_error_handler    -       probe/reset
- *     @ap: ATA port
- *
- *     Set the cable type and trigger a probe
- */
-
-static void it821x_error_handler(struct ata_port *ap)
-{
-       return ata_bmdma_drive_eh(ap, it821x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
-/**
  *     it821x_program  -       program the PIO/MWDMA registers
  *     @ap: ATA port
  *     @adev: Device to program
@@ -408,7 +383,7 @@ static void it821x_passthru_bmdma_stop(struct ata_queued_cmd *qc)
  *     @ap: ATA port
  *     @device: Device number (not pointer)
  *
- *     Device selection hook. If neccessary perform clock switching
+ *     Device selection hook. If necessary perform clock switching
  */
 
 static void it821x_passthru_dev_select(struct ata_port *ap,
@@ -416,7 +391,7 @@ static void it821x_passthru_dev_select(struct ata_port *ap,
 {
        struct it821x_dev *itdev = ap->private_data;
        if (itdev && device != itdev->last_device) {
-               struct ata_device *adev = &ap->device[device];
+               struct ata_device *adev = &ap->link.device[device];
                it821x_program(ap, adev, itdev->pio[adev->devno]);
                itdev->last_device = device;
        }
@@ -455,7 +430,7 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
                        return ata_qc_issue_prot(qc);
        }
        printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
-       return AC_ERR_INVALID;
+       return AC_ERR_DEV;
 }
 
 /**
@@ -475,7 +450,7 @@ static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
 
 /**
  *     it821x_smart_set_mode   -       mode setting
- *     @ap: interface to set up
+ *     @link: interface to set up
  *     @unused: device that failed (error only)
  *
  *     Use a non standard set_mode function. We don't want to be tuned.
@@ -484,29 +459,24 @@ static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
  *     and respect them.
  */
 
-static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused)
+static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unused)
 {
-       int dma_enabled = 0;
-       int i;
-
-       /* Bits 5 and 6 indicate if DMA is active on master/slave */
-       /* It is possible that BMDMA isn't allocated */
-       if (ap->ioaddr.bmdma_addr)
-               dma_enabled = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+       struct ata_device *dev;
 
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               struct ata_device *dev = &ap->device[i];
+       ata_link_for_each_dev(dev, link) {
                if (ata_dev_enabled(dev)) {
                        /* We don't really care */
                        dev->pio_mode = XFER_PIO_0;
                        dev->dma_mode = XFER_MW_DMA_0;
                        /* We do need the right mode information for DMA or PIO
                           and this comes from the current configuration flags */
-                       if (dma_enabled & (1 << (5 + i))) {
+                       if (ata_id_has_dma(dev->id)) {
+                               ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
                                dev->xfer_mode = XFER_MW_DMA_0;
                                dev->xfer_shift = ATA_SHIFT_MWDMA;
                                dev->flags &= ~ATA_DFLAG_PIO;
                        } else {
+                               ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
                                dev->xfer_mode = XFER_PIO_0;
                                dev->xfer_shift = ATA_SHIFT_PIO;
                                dev->flags |= ATA_DFLAG_PIO;
@@ -518,7 +488,6 @@ static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused
 
 /**
  *     it821x_dev_config       -       Called each device identify
- *     @ap: ATA port
  *     @adev: Device that has just been identified
  *
  *     Perform the initial setup needed for each device that is chip
@@ -529,25 +498,11 @@ static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused
  *     basically we need to filter commands for this chip.
  */
 
-static void it821x_dev_config(struct ata_port *ap, struct ata_device *adev)
+static void it821x_dev_config(struct ata_device *adev)
 {
-       unsigned char model_num[40];
-       char *s;
-       unsigned int len;
-
-       /* This block ought to be a library routine as it is in several
-          drivers now */
-
-       ata_id_string(adev->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;
-       }
+       unsigned char model_num[ATA_ID_PROD_LEN + 1];
+
+       ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
        if (adev->max_sectors > 255)
                adev->max_sectors = 255;
@@ -561,6 +516,37 @@ static void it821x_dev_config(struct ata_port *ap, struct ata_device *adev)
                        printk("(%dK stripe)", adev->id[146]);
                printk(".\n");
        }
+       /* This is a controller firmware triggered funny, don't
+          report the drive faulty! */
+       adev->horkage &= ~ATA_HORKAGE_DIAGNOSTIC;
+}
+
+/**
+ *     it821x_ident_hack       -       Hack identify data up
+ *     @ap: Port
+ *
+ *     Walk the devices on this firmware driven port and slightly
+ *     mash the identify data to stop us and common tools trying to
+ *     use features not firmware supported. The firmware itself does
+ *     some masking (eg SMART) but not enough.
+ *
+ *     This is a bit of an abuse of the cable method, but it is the
+ *     only method called at the right time. We could modify the libata
+ *     core specifically for ident hacking but while we have one offender
+ *     it seems better to keep the fallout localised.
+ */
+
+static int it821x_ident_hack(struct ata_port *ap)
+{
+       struct ata_device *adev;
+       ata_link_for_each_dev(adev, &ap->link) {
+               if (ata_dev_enabled(adev)) {
+                       adev->id[84] &= ~(1 << 6);      /* No FUA */
+                       adev->id[85] &= ~(1 << 10);     /* No HPA */
+                       adev->id[76] = 0;               /* No NCQ/AN etc */
+               }
+       }
+       return ata_cable_unknown(ap);
 }
 
 
@@ -577,6 +563,10 @@ static int it821x_check_atapi_dma(struct ata_queued_cmd *qc)
        struct ata_port *ap = qc->ap;
        struct it821x_dev *itdev = ap->private_data;
 
+       /* Only use dma for transfers to/from the media. */
+       if (qc->nbytes < 2048)
+               return -EOPNOTSUPP;
+
        /* No ATAPI DMA in smart mode */
        if (itdev->smart)
                return -EOPNOTSUPP;
@@ -604,18 +594,14 @@ static int it821x_port_start(struct ata_port *ap)
        struct it821x_dev *itdev;
        u8 conf;
 
-       int ret = ata_port_start(ap);
+       int ret = ata_sff_port_start(ap);
        if (ret < 0)
                return ret;
 
-       ap->private_data = kmalloc(sizeof(struct it821x_dev), GFP_KERNEL);
-       if (ap->private_data == NULL) {
-               ata_port_stop(ap);
+       itdev = devm_kzalloc(&pdev->dev, sizeof(struct it821x_dev), GFP_KERNEL);
+       if (itdev == NULL)
                return -ENOMEM;
-       }
-
-       itdev = ap->private_data;
-       memset(itdev, 0, sizeof(struct it821x_dev));
+       ap->private_data = itdev;
 
        pci_read_config_byte(pdev, 0x50, &conf);
 
@@ -635,8 +621,7 @@ static int it821x_port_start(struct ata_port *ap)
        itdev->want[1][1] = ATA_ANY;
        itdev->last_device = -1;
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &conf);
-       if (conf == 0x10) {
+       if (pdev->revision == 0x10) {
                itdev->timing10 = 1;
                /* Need to disable ATAPI DMA for this case */
                if (!itdev->smart)
@@ -646,20 +631,6 @@ static int it821x_port_start(struct ata_port *ap)
        return 0;
 }
 
-/**
- *     it821x_port_stop        -       port shutdown
- *     @ap: ATA port being removed
- *
- *     Release the private objects we added in it821x_port_start
- */
-
-static void it821x_port_stop(struct ata_port *ap) {
-       kfree(ap->private_data);
-       ap->private_data = NULL;        /* We want an OOPS if we reuse this
-                                          too late! */
-       ata_port_stop(ap);
-}
-
 static struct scsi_host_template it821x_sht = {
        .module                 = THIS_MODULE,
        .name                   = DRV_NAME,
@@ -676,13 +647,10 @@ static struct scsi_host_template it821x_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
-       .resume                 = ata_scsi_device_resume,
-       .suspend                = ata_scsi_device_suspend,
 };
 
 static struct ata_port_operations it821x_smart_port_ops = {
        .set_mode       = it821x_smart_set_mode,
-       .port_disable   = ata_port_disable,
        .tf_load        = ata_tf_load,
        .tf_read        = ata_tf_read,
        .mode_filter    = ata_pci_default_filter,
@@ -695,8 +663,9 @@ static struct ata_port_operations it821x_smart_port_ops = {
 
        .freeze         = ata_bmdma_freeze,
        .thaw           = ata_bmdma_thaw,
-       .error_handler  = it821x_error_handler,
+       .error_handler  = ata_bmdma_error_handler,
        .post_internal_cmd = ata_bmdma_post_internal_cmd,
+       .cable_detect   = it821x_ident_hack,
 
        .bmdma_setup    = ata_bmdma_setup,
        .bmdma_start    = ata_bmdma_start,
@@ -706,18 +675,16 @@ static struct ata_port_operations it821x_smart_port_ops = {
        .qc_prep        = ata_qc_prep,
        .qc_issue       = it821x_smart_qc_issue_prot,
 
-       .data_xfer      = ata_pio_data_xfer,
+       .data_xfer      = ata_data_xfer,
 
        .irq_handler    = ata_interrupt,
        .irq_clear      = ata_bmdma_irq_clear,
+       .irq_on         = ata_irq_on,
 
        .port_start     = it821x_port_start,
-       .port_stop      = it821x_port_stop,
-       .host_stop      = ata_host_stop
 };
 
 static struct ata_port_operations it821x_passthru_port_ops = {
-       .port_disable   = ata_port_disable,
        .set_piomode    = it821x_passthru_set_piomode,
        .set_dmamode    = it821x_passthru_set_dmamode,
        .mode_filter    = ata_pci_default_filter,
@@ -731,8 +698,9 @@ static struct ata_port_operations it821x_passthru_port_ops = {
 
        .freeze         = ata_bmdma_freeze,
        .thaw           = ata_bmdma_thaw,
-       .error_handler  = it821x_error_handler,
+       .error_handler  = ata_bmdma_error_handler,
        .post_internal_cmd = ata_bmdma_post_internal_cmd,
+       .cable_detect   = ata_cable_unknown,
 
        .bmdma_setup    = ata_bmdma_setup,
        .bmdma_start    = it821x_passthru_bmdma_start,
@@ -742,17 +710,16 @@ static struct ata_port_operations it821x_passthru_port_ops = {
        .qc_prep        = ata_qc_prep,
        .qc_issue       = it821x_passthru_qc_issue_prot,
 
-       .data_xfer      = ata_pio_data_xfer,
+       .data_xfer      = ata_data_xfer,
 
        .irq_clear      = ata_bmdma_irq_clear,
        .irq_handler    = ata_interrupt,
+       .irq_on         = ata_irq_on,
 
        .port_start     = it821x_port_start,
-       .port_stop      = it821x_port_stop,
-       .host_stop      = ata_host_stop
 };
 
-static void __devinit it821x_disable_raid(struct pci_dev *pdev)
+static void it821x_disable_raid(struct pci_dev *pdev)
 {
        /* Reset local CPU, and set BIOS not ready */
        pci_write_config_byte(pdev, 0x5E, 0x01);
@@ -774,23 +741,23 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        u8 conf;
 
-       static struct ata_port_info info_smart = {
+       static const struct ata_port_info info_smart = {
                .sht = &it821x_sht,
-               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+               .flags = ATA_FLAG_SLAVE_POSS,
                .pio_mask = 0x1f,
                .mwdma_mask = 0x07,
                .port_ops = &it821x_smart_port_ops
        };
-       static struct ata_port_info info_passthru = {
+       static const struct ata_port_info info_passthru = {
                .sht = &it821x_sht,
-               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+               .flags = ATA_FLAG_SLAVE_POSS,
                .pio_mask = 0x1f,
                .mwdma_mask = 0x07,
-               .udma_mask = 0x7f,
+               .udma_mask = ATA_UDMA6,
                .port_ops = &it821x_passthru_port_ops
        };
-       static struct ata_port_info *port_info[2];
 
+       const struct ata_port_info *ppi[] = { NULL, NULL };
        static char *mode[2] = { "pass through", "smart" };
 
        /* Force the card into bypass mode if so requested */
@@ -803,13 +770,14 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        printk(KERN_INFO DRV_NAME ": controller in %s mode.\n", mode[conf]);
        if (conf == 0)
-               port_info[0] = port_info[1] = &info_passthru;
+               ppi[0] = &info_passthru;
        else
-               port_info[0] = port_info[1] = &info_smart;
+               ppi[0] = &info_smart;
 
-       return ata_pci_init_one(pdev, port_info, 2);
+       return ata_pci_init_one(pdev, ppi);
 }
 
+#ifdef CONFIG_PM
 static int it821x_reinit_one(struct pci_dev *pdev)
 {
        /* Resume - turn raid back off if need be */
@@ -817,6 +785,7 @@ static int it821x_reinit_one(struct pci_dev *pdev)
                it821x_disable_raid(pdev);
        return ata_pci_device_resume(pdev);
 }
+#endif
 
 static const struct pci_device_id it821x[] = {
        { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), },
@@ -830,8 +799,10 @@ static struct pci_driver it821x_pci_driver = {
        .id_table       = it821x,
        .probe          = it821x_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = it821x_reinit_one,
+#endif
 };
 
 static int __init it821x_init(void)
@@ -852,7 +823,7 @@ MODULE_VERSION(DRV_VERSION);
 
 
 module_param_named(noraid, it8212_noraid, int, S_IRUGO);
-MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode");
+MODULE_PARM_DESC(noraid, "Force card into bypass mode");
 
 module_init(it821x_init);
 module_exit(it821x_exit);