diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2007-07-09 14:46:22 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-10 21:30:33 -0400 |
commit | 66e7da4e34610e84bdb1bf726031d6c4c88cbbf9 (patch) | |
tree | d781e713327712cfc8ec79b7a76eee514036ddb8 /drivers/ata/pata_hpt3x3.c | |
parent | 75683fe7153c3817bb4fd4491e2a5913af6c463e (diff) |
pata_hpt3x3: major reworking and testing
The HPT343/345 (aka 363) is a bit of a warped device. For many setups you
need to access the other registers via BAR4 offsets. PIO is now rock
solid, DMA isn't. Unfortunately the drivers/ide hpt34x driver is
completely broken so doesn't help further debug.
Signed-off-by: Alan Cox <alan@redhat.com>
Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/pata_hpt3x3.c')
-rw-r--r-- | drivers/ata/pata_hpt3x3.c | 90 |
1 files changed, 76 insertions, 14 deletions
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index d928c9105034..a66e2c3a221b 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.4.3" | 26 | #define DRV_VERSION "0.5.3" |
27 | 27 | ||
28 | /** | 28 | /** |
29 | * hpt3x3_set_piomode - PIO setup | 29 | * hpt3x3_set_piomode - PIO setup |
@@ -59,6 +59,9 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
59 | * | 59 | * |
60 | * Set up the channel for MWDMA or UDMA modes. Much the same as with | 60 | * Set up the channel for MWDMA or UDMA modes. Much the same as with |
61 | * PIO, load the mode number and then set MWDMA or UDMA flag. | 61 | * PIO, load the mode number and then set MWDMA or UDMA flag. |
62 | * | ||
63 | * 0x44 : bit 0-2 master mode, 3-5 slave mode, etc | ||
64 | * 0x48 : bit 4/0 DMA/UDMA bit 5/1 for slave etc | ||
62 | */ | 65 | */ |
63 | 66 | ||
64 | static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) | 67 | static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) |
@@ -76,14 +79,26 @@ static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
76 | r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ | 79 | r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ |
77 | 80 | ||
78 | if (adev->dma_mode >= XFER_UDMA_0) | 81 | if (adev->dma_mode >= XFER_UDMA_0) |
79 | r2 |= 0x01 << dn; /* Ultra mode */ | 82 | r2 |= (0x10 << dn); /* Ultra mode */ |
80 | else | 83 | else |
81 | r2 |= 0x10 << dn; /* MWDMA */ | 84 | r2 |= (0x01 << dn); /* MWDMA */ |
82 | 85 | ||
83 | pci_write_config_dword(pdev, 0x44, r1); | 86 | pci_write_config_dword(pdev, 0x44, r1); |
84 | pci_write_config_dword(pdev, 0x48, r2); | 87 | pci_write_config_dword(pdev, 0x48, r2); |
85 | } | 88 | } |
86 | 89 | ||
90 | /** | ||
91 | * hpt3x3_atapi_dma - ATAPI DMA check | ||
92 | * @qc: Queued command | ||
93 | * | ||
94 | * Just say no - we don't do ATAPI DMA | ||
95 | */ | ||
96 | |||
97 | static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc) | ||
98 | { | ||
99 | return 1; | ||
100 | } | ||
101 | |||
87 | static struct scsi_host_template hpt3x3_sht = { | 102 | static struct scsi_host_template hpt3x3_sht = { |
88 | .module = THIS_MODULE, | 103 | .module = THIS_MODULE, |
89 | .name = DRV_NAME, | 104 | .name = DRV_NAME, |
@@ -105,7 +120,6 @@ static struct scsi_host_template hpt3x3_sht = { | |||
105 | static struct ata_port_operations hpt3x3_port_ops = { | 120 | static struct ata_port_operations hpt3x3_port_ops = { |
106 | .port_disable = ata_port_disable, | 121 | .port_disable = ata_port_disable, |
107 | .set_piomode = hpt3x3_set_piomode, | 122 | .set_piomode = hpt3x3_set_piomode, |
108 | .set_dmamode = hpt3x3_set_dmamode, | ||
109 | .mode_filter = ata_pci_default_filter, | 123 | .mode_filter = ata_pci_default_filter, |
110 | 124 | ||
111 | .tf_load = ata_tf_load, | 125 | .tf_load = ata_tf_load, |
@@ -124,6 +138,7 @@ static struct ata_port_operations hpt3x3_port_ops = { | |||
124 | .bmdma_start = ata_bmdma_start, | 138 | .bmdma_start = ata_bmdma_start, |
125 | .bmdma_stop = ata_bmdma_stop, | 139 | .bmdma_stop = ata_bmdma_stop, |
126 | .bmdma_status = ata_bmdma_status, | 140 | .bmdma_status = ata_bmdma_status, |
141 | .check_atapi_dma= hpt3x3_atapi_dma, | ||
127 | 142 | ||
128 | .qc_prep = ata_qc_prep, | 143 | .qc_prep = ata_qc_prep, |
129 | .qc_issue = ata_qc_issue_prot, | 144 | .qc_issue = ata_qc_issue_prot, |
@@ -158,32 +173,79 @@ static void hpt3x3_init_chipset(struct pci_dev *dev) | |||
158 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); | 173 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); |
159 | } | 174 | } |
160 | 175 | ||
161 | |||
162 | /** | 176 | /** |
163 | * hpt3x3_init_one - Initialise an HPT343/363 | 177 | * hpt3x3_init_one - Initialise an HPT343/363 |
164 | * @dev: PCI device | 178 | * @pdev: PCI device |
165 | * @id: Entry in match table | 179 | * @id: Entry in match table |
166 | * | 180 | * |
167 | * Perform basic initialisation. The chip has a quirk that it won't | 181 | * Perform basic initialisation. We set the device up so we access all |
168 | * function unless it is at XX00. The old ATA driver touched this up | 182 | * ports via BAR4. This is neccessary to work around errata. |
169 | * but we leave it for pci quirks to do properly. | ||
170 | */ | 183 | */ |
171 | 184 | ||
172 | static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) | 185 | static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
173 | { | 186 | { |
187 | static int printed_version; | ||
174 | static const struct ata_port_info info = { | 188 | static const struct ata_port_info info = { |
175 | .sht = &hpt3x3_sht, | 189 | .sht = &hpt3x3_sht, |
176 | .flags = ATA_FLAG_SLAVE_POSS, | 190 | .flags = ATA_FLAG_SLAVE_POSS, |
177 | .pio_mask = 0x1f, | 191 | .pio_mask = 0x1f, |
192 | #if defined(CONFIG_PATA_HPT3X3_DMA) | ||
193 | /* Further debug needed */ | ||
178 | .mwdma_mask = 0x07, | 194 | .mwdma_mask = 0x07, |
179 | .udma_mask = 0x07, | 195 | .udma_mask = 0x07, |
196 | #endif | ||
180 | .port_ops = &hpt3x3_port_ops | 197 | .port_ops = &hpt3x3_port_ops |
181 | }; | 198 | }; |
199 | /* Register offsets of taskfiles in BAR4 area */ | ||
200 | static const u8 offset_cmd[2] = { 0x20, 0x28 }; | ||
201 | static const u8 offset_ctl[2] = { 0x36, 0x3E }; | ||
182 | const struct ata_port_info *ppi[] = { &info, NULL }; | 202 | const struct ata_port_info *ppi[] = { &info, NULL }; |
183 | 203 | struct ata_host *host; | |
184 | hpt3x3_init_chipset(dev); | 204 | int i, rc; |
185 | /* Now kick off ATA set up */ | 205 | void __iomem *base; |
186 | return ata_pci_init_one(dev, ppi); | 206 | |
207 | hpt3x3_init_chipset(pdev); | ||
208 | |||
209 | if (!printed_version++) | ||
210 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | ||
211 | |||
212 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); | ||
213 | if (!host) | ||
214 | return -ENOMEM; | ||
215 | /* acquire resources and fill host */ | ||
216 | rc = pcim_enable_device(pdev); | ||
217 | if (rc) | ||
218 | return rc; | ||
219 | |||
220 | /* Everything is relative to BAR4 if we set up this way */ | ||
221 | rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME); | ||
222 | if (rc == -EBUSY) | ||
223 | pcim_pin_device(pdev); | ||
224 | if (rc) | ||
225 | return rc; | ||
226 | host->iomap = pcim_iomap_table(pdev); | ||
227 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); | ||
228 | if (rc) | ||
229 | return rc; | ||
230 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | ||
231 | if (rc) | ||
232 | return rc; | ||
233 | |||
234 | base = host->iomap[4]; /* Bus mastering base */ | ||
235 | |||
236 | for (i = 0; i < host->n_ports; i++) { | ||
237 | struct ata_ioports *ioaddr = &host->ports[i]->ioaddr; | ||
238 | |||
239 | ioaddr->cmd_addr = base + offset_cmd[i]; | ||
240 | ioaddr->altstatus_addr = | ||
241 | ioaddr->ctl_addr = base + offset_ctl[i]; | ||
242 | ioaddr->scr_addr = NULL; | ||
243 | ata_std_ports(ioaddr); | ||
244 | ioaddr->bmdma_addr = base + 8 * i; | ||
245 | } | ||
246 | pci_set_master(pdev); | ||
247 | return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED, | ||
248 | &hpt3x3_sht); | ||
187 | } | 249 | } |
188 | 250 | ||
189 | #ifdef CONFIG_PM | 251 | #ifdef CONFIG_PM |