diff options
Diffstat (limited to 'drivers/ata/pata_hpt3x3.c')
-rw-r--r-- | drivers/ata/pata_hpt3x3.c | 93 |
1 files changed, 80 insertions, 13 deletions
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index d928c9105034..be0f05efac6d 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 |
@@ -52,6 +52,7 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
52 | pci_write_config_dword(pdev, 0x48, r2); | 52 | pci_write_config_dword(pdev, 0x48, r2); |
53 | } | 53 | } |
54 | 54 | ||
55 | #if defined(CONFIG_PATA_HPT3X3_DMA) | ||
55 | /** | 56 | /** |
56 | * hpt3x3_set_dmamode - DMA timing setup | 57 | * hpt3x3_set_dmamode - DMA timing setup |
57 | * @ap: ATA interface | 58 | * @ap: ATA interface |
@@ -59,6 +60,9 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
59 | * | 60 | * |
60 | * Set up the channel for MWDMA or UDMA modes. Much the same as with | 61 | * 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. | 62 | * PIO, load the mode number and then set MWDMA or UDMA flag. |
63 | * | ||
64 | * 0x44 : bit 0-2 master mode, 3-5 slave mode, etc | ||
65 | * 0x48 : bit 4/0 DMA/UDMA bit 5/1 for slave etc | ||
62 | */ | 66 | */ |
63 | 67 | ||
64 | static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) | 68 | static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) |
@@ -76,13 +80,26 @@ static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
76 | r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ | 80 | r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ |
77 | 81 | ||
78 | if (adev->dma_mode >= XFER_UDMA_0) | 82 | if (adev->dma_mode >= XFER_UDMA_0) |
79 | r2 |= 0x01 << dn; /* Ultra mode */ | 83 | r2 |= (0x10 << dn); /* Ultra mode */ |
80 | else | 84 | else |
81 | r2 |= 0x10 << dn; /* MWDMA */ | 85 | r2 |= (0x01 << dn); /* MWDMA */ |
82 | 86 | ||
83 | pci_write_config_dword(pdev, 0x44, r1); | 87 | pci_write_config_dword(pdev, 0x44, r1); |
84 | pci_write_config_dword(pdev, 0x48, r2); | 88 | pci_write_config_dword(pdev, 0x48, r2); |
85 | } | 89 | } |
90 | #endif /* CONFIG_PATA_HPT3X3_DMA */ | ||
91 | |||
92 | /** | ||
93 | * hpt3x3_atapi_dma - ATAPI DMA check | ||
94 | * @qc: Queued command | ||
95 | * | ||
96 | * Just say no - we don't do ATAPI DMA | ||
97 | */ | ||
98 | |||
99 | static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc) | ||
100 | { | ||
101 | return 1; | ||
102 | } | ||
86 | 103 | ||
87 | static struct scsi_host_template hpt3x3_sht = { | 104 | static struct scsi_host_template hpt3x3_sht = { |
88 | .module = THIS_MODULE, | 105 | .module = THIS_MODULE, |
@@ -105,7 +122,9 @@ static struct scsi_host_template hpt3x3_sht = { | |||
105 | static struct ata_port_operations hpt3x3_port_ops = { | 122 | static struct ata_port_operations hpt3x3_port_ops = { |
106 | .port_disable = ata_port_disable, | 123 | .port_disable = ata_port_disable, |
107 | .set_piomode = hpt3x3_set_piomode, | 124 | .set_piomode = hpt3x3_set_piomode, |
125 | #if defined(CONFIG_PATA_HPT3X3_DMA) | ||
108 | .set_dmamode = hpt3x3_set_dmamode, | 126 | .set_dmamode = hpt3x3_set_dmamode, |
127 | #endif | ||
109 | .mode_filter = ata_pci_default_filter, | 128 | .mode_filter = ata_pci_default_filter, |
110 | 129 | ||
111 | .tf_load = ata_tf_load, | 130 | .tf_load = ata_tf_load, |
@@ -124,6 +143,7 @@ static struct ata_port_operations hpt3x3_port_ops = { | |||
124 | .bmdma_start = ata_bmdma_start, | 143 | .bmdma_start = ata_bmdma_start, |
125 | .bmdma_stop = ata_bmdma_stop, | 144 | .bmdma_stop = ata_bmdma_stop, |
126 | .bmdma_status = ata_bmdma_status, | 145 | .bmdma_status = ata_bmdma_status, |
146 | .check_atapi_dma= hpt3x3_atapi_dma, | ||
127 | 147 | ||
128 | .qc_prep = ata_qc_prep, | 148 | .qc_prep = ata_qc_prep, |
129 | .qc_issue = ata_qc_issue_prot, | 149 | .qc_issue = ata_qc_issue_prot, |
@@ -158,32 +178,79 @@ static void hpt3x3_init_chipset(struct pci_dev *dev) | |||
158 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); | 178 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); |
159 | } | 179 | } |
160 | 180 | ||
161 | |||
162 | /** | 181 | /** |
163 | * hpt3x3_init_one - Initialise an HPT343/363 | 182 | * hpt3x3_init_one - Initialise an HPT343/363 |
164 | * @dev: PCI device | 183 | * @pdev: PCI device |
165 | * @id: Entry in match table | 184 | * @id: Entry in match table |
166 | * | 185 | * |
167 | * Perform basic initialisation. The chip has a quirk that it won't | 186 | * 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 | 187 | * ports via BAR4. This is neccessary to work around errata. |
169 | * but we leave it for pci quirks to do properly. | ||
170 | */ | 188 | */ |
171 | 189 | ||
172 | static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) | 190 | static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
173 | { | 191 | { |
192 | static int printed_version; | ||
174 | static const struct ata_port_info info = { | 193 | static const struct ata_port_info info = { |
175 | .sht = &hpt3x3_sht, | 194 | .sht = &hpt3x3_sht, |
176 | .flags = ATA_FLAG_SLAVE_POSS, | 195 | .flags = ATA_FLAG_SLAVE_POSS, |
177 | .pio_mask = 0x1f, | 196 | .pio_mask = 0x1f, |
197 | #if defined(CONFIG_PATA_HPT3X3_DMA) | ||
198 | /* Further debug needed */ | ||
178 | .mwdma_mask = 0x07, | 199 | .mwdma_mask = 0x07, |
179 | .udma_mask = 0x07, | 200 | .udma_mask = 0x07, |
201 | #endif | ||
180 | .port_ops = &hpt3x3_port_ops | 202 | .port_ops = &hpt3x3_port_ops |
181 | }; | 203 | }; |
204 | /* Register offsets of taskfiles in BAR4 area */ | ||
205 | static const u8 offset_cmd[2] = { 0x20, 0x28 }; | ||
206 | static const u8 offset_ctl[2] = { 0x36, 0x3E }; | ||
182 | const struct ata_port_info *ppi[] = { &info, NULL }; | 207 | const struct ata_port_info *ppi[] = { &info, NULL }; |
183 | 208 | struct ata_host *host; | |
184 | hpt3x3_init_chipset(dev); | 209 | int i, rc; |
185 | /* Now kick off ATA set up */ | 210 | void __iomem *base; |
186 | return ata_pci_init_one(dev, ppi); | 211 | |
212 | hpt3x3_init_chipset(pdev); | ||
213 | |||
214 | if (!printed_version++) | ||
215 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | ||
216 | |||
217 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); | ||
218 | if (!host) | ||
219 | return -ENOMEM; | ||
220 | /* acquire resources and fill host */ | ||
221 | rc = pcim_enable_device(pdev); | ||
222 | if (rc) | ||
223 | return rc; | ||
224 | |||
225 | /* Everything is relative to BAR4 if we set up this way */ | ||
226 | rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME); | ||
227 | if (rc == -EBUSY) | ||
228 | pcim_pin_device(pdev); | ||
229 | if (rc) | ||
230 | return rc; | ||
231 | host->iomap = pcim_iomap_table(pdev); | ||
232 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); | ||
233 | if (rc) | ||
234 | return rc; | ||
235 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | ||
236 | if (rc) | ||
237 | return rc; | ||
238 | |||
239 | base = host->iomap[4]; /* Bus mastering base */ | ||
240 | |||
241 | for (i = 0; i < host->n_ports; i++) { | ||
242 | struct ata_ioports *ioaddr = &host->ports[i]->ioaddr; | ||
243 | |||
244 | ioaddr->cmd_addr = base + offset_cmd[i]; | ||
245 | ioaddr->altstatus_addr = | ||
246 | ioaddr->ctl_addr = base + offset_ctl[i]; | ||
247 | ioaddr->scr_addr = NULL; | ||
248 | ata_std_ports(ioaddr); | ||
249 | ioaddr->bmdma_addr = base + 8 * i; | ||
250 | } | ||
251 | pci_set_master(pdev); | ||
252 | return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED, | ||
253 | &hpt3x3_sht); | ||
187 | } | 254 | } |
188 | 255 | ||
189 | #ifdef CONFIG_PM | 256 | #ifdef CONFIG_PM |