diff options
| author | Alan Cox <alan@redhat.com> | 2009-01-05 09:12:51 -0500 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2009-01-08 16:08:56 -0500 |
| commit | 978ff6db23279422046c1b3f89fe2045c234dc91 (patch) | |
| tree | 69da222db791998823afcc68160dab4d7458ea92 | |
| parent | 85da1fb545e5fe51c35e0576f71780cc557f4277 (diff) | |
pata_hpt3x3: Workarounds for chipset
Correct the DMA bit flags (UDMA and MWDMA were swapped)
Add workarounds so that we clear ERR and INTR bits before issuing a DMA
Add workarounds so that we stop a live DMA before touching the CTL register
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
| -rw-r--r-- | drivers/ata/pata_hpt3x3.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index f11a320337c0..1c9016edf87a 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include <linux/libata.h> | 23 | #include <linux/libata.h> |
| 24 | 24 | ||
| 25 | #define DRV_NAME "pata_hpt3x3" | 25 | #define DRV_NAME "pata_hpt3x3" |
| 26 | #define DRV_VERSION "0.5.3" | 26 | #define DRV_VERSION "0.6.1" |
| 27 | 27 | ||
| 28 | /** | 28 | /** |
| 29 | * hpt3x3_set_piomode - PIO setup | 29 | * hpt3x3_set_piomode - PIO setup |
| @@ -80,14 +80,48 @@ static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
| 80 | r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ | 80 | r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ |
| 81 | 81 | ||
| 82 | if (adev->dma_mode >= XFER_UDMA_0) | 82 | if (adev->dma_mode >= XFER_UDMA_0) |
| 83 | r2 |= (0x10 << dn); /* Ultra mode */ | 83 | r2 |= (0x01 << dn); /* Ultra mode */ |
| 84 | else | 84 | else |
| 85 | r2 |= (0x01 << dn); /* MWDMA */ | 85 | r2 |= (0x10 << dn); /* MWDMA */ |
| 86 | 86 | ||
| 87 | pci_write_config_dword(pdev, 0x44, r1); | 87 | pci_write_config_dword(pdev, 0x44, r1); |
| 88 | pci_write_config_dword(pdev, 0x48, r2); | 88 | pci_write_config_dword(pdev, 0x48, r2); |
| 89 | } | 89 | } |
| 90 | #endif /* CONFIG_PATA_HPT3X3_DMA */ | 90 | |
| 91 | /** | ||
| 92 | * hpt3x3_freeze - DMA workaround | ||
| 93 | * @ap: port to freeze | ||
| 94 | * | ||
| 95 | * When freezing an HPT3x3 we must stop any pending DMA before | ||
| 96 | * writing to the control register or the chip will hang | ||
| 97 | */ | ||
| 98 | |||
| 99 | static int hpt3x3_freeze(struct ata_port *ap) | ||
| 100 | { | ||
| 101 | void __iomem *mmio = ap->ioaddr.bmdma_addr; | ||
| 102 | |||
| 103 | iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ ATA_DMA_START, | ||
| 104 | mmio + ATA_DMA_CMD); | ||
| 105 | ata_sff_dma_pause(ap); | ||
| 106 | ata_sff_freeze(ap); | ||
| 107 | } | ||
| 108 | |||
| 109 | /** | ||
| 110 | * hpt3x3_bmdma_setup - DMA workaround | ||
| 111 | * @qc: Queued command | ||
| 112 | * | ||
| 113 | * When issuing BMDMA we must clean up the error/active bits in | ||
| 114 | * software on this device | ||
| 115 | */ | ||
| 116 | |||
| 117 | static void hpt3x3_bmdma_setup(struct ata_queued_cmd *qc) | ||
| 118 | { | ||
| 119 | struct ata_port *ap = qc->ap; | ||
| 120 | u8 r = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
| 121 | r |= ATA_DMA_INTR | ATA_DMA_ERR; | ||
| 122 | iowrite8(r, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
| 123 | return ata_bmdma_setup(qc); | ||
| 124 | } | ||
| 91 | 125 | ||
| 92 | /** | 126 | /** |
| 93 | * hpt3x3_atapi_dma - ATAPI DMA check | 127 | * hpt3x3_atapi_dma - ATAPI DMA check |
| @@ -101,18 +135,23 @@ static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc) | |||
| 101 | return 1; | 135 | return 1; |
| 102 | } | 136 | } |
| 103 | 137 | ||
| 138 | #endif /* CONFIG_PATA_HPT3X3_DMA */ | ||
| 139 | |||
| 104 | static struct scsi_host_template hpt3x3_sht = { | 140 | static struct scsi_host_template hpt3x3_sht = { |
| 105 | ATA_BMDMA_SHT(DRV_NAME), | 141 | ATA_BMDMA_SHT(DRV_NAME), |
| 106 | }; | 142 | }; |
| 107 | 143 | ||
| 108 | static struct ata_port_operations hpt3x3_port_ops = { | 144 | static struct ata_port_operations hpt3x3_port_ops = { |
| 109 | .inherits = &ata_bmdma_port_ops, | 145 | .inherits = &ata_bmdma_port_ops, |
| 110 | .check_atapi_dma= hpt3x3_atapi_dma, | ||
| 111 | .cable_detect = ata_cable_40wire, | 146 | .cable_detect = ata_cable_40wire, |
| 112 | .set_piomode = hpt3x3_set_piomode, | 147 | .set_piomode = hpt3x3_set_piomode, |
| 113 | #if defined(CONFIG_PATA_HPT3X3_DMA) | 148 | #if defined(CONFIG_PATA_HPT3X3_DMA) |
| 114 | .set_dmamode = hpt3x3_set_dmamode, | 149 | .set_dmamode = hpt3x3_set_dmamode, |
| 150 | .bmdma_setup = hpt3x3_bmdma_setup, | ||
| 151 | .check_atapi_dma= hpt3x3_atapi_dma, | ||
| 152 | .freeze = hpt3x3_freeze, | ||
| 115 | #endif | 153 | #endif |
| 154 | |||
| 116 | }; | 155 | }; |
| 117 | 156 | ||
| 118 | /** | 157 | /** |
| @@ -257,4 +296,4 @@ MODULE_DEVICE_TABLE(pci, hpt3x3); | |||
| 257 | MODULE_VERSION(DRV_VERSION); | 296 | MODULE_VERSION(DRV_VERSION); |
| 258 | 297 | ||
| 259 | module_init(hpt3x3_init); | 298 | module_init(hpt3x3_init); |
| 260 | module_exit(hpt3x3_exit); | 299 | module_exit(hpt3x3_exit); \ No newline at end of file |
