diff options
Diffstat (limited to 'drivers/ata/pata_mpiix.c')
-rw-r--r-- | drivers/ata/pata_mpiix.c | 113 |
1 files changed, 48 insertions, 65 deletions
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index 4ccca938675e..ca8c965179b1 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <linux/libata.h> | 35 | #include <linux/libata.h> |
36 | 36 | ||
37 | #define DRV_NAME "pata_mpiix" | 37 | #define DRV_NAME "pata_mpiix" |
38 | #define DRV_VERSION "0.7.3" | 38 | #define DRV_VERSION "0.7.5" |
39 | 39 | ||
40 | enum { | 40 | enum { |
41 | IDETIM = 0x6C, /* IDE control register */ | 41 | IDETIM = 0x6C, /* IDE control register */ |
@@ -49,12 +49,9 @@ enum { | |||
49 | static int mpiix_pre_reset(struct ata_port *ap) | 49 | static int mpiix_pre_reset(struct ata_port *ap) |
50 | { | 50 | { |
51 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 51 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
52 | static const struct pci_bits mpiix_enable_bits[] = { | 52 | static const struct pci_bits mpiix_enable_bits = { 0x6D, 1, 0x80, 0x80 }; |
53 | { 0x6D, 1, 0x80, 0x80 }, | ||
54 | { 0x6F, 1, 0x80, 0x80 } | ||
55 | }; | ||
56 | 53 | ||
57 | if (!pci_test_config_bits(pdev, &mpiix_enable_bits[ap->port_no])) | 54 | if (!pci_test_config_bits(pdev, &mpiix_enable_bits)) |
58 | return -ENOENT; | 55 | return -ENOENT; |
59 | ap->cbl = ATA_CBL_PATA40; | 56 | ap->cbl = ATA_CBL_PATA40; |
60 | return ata_std_prereset(ap); | 57 | return ata_std_prereset(ap); |
@@ -80,8 +77,8 @@ static void mpiix_error_handler(struct ata_port *ap) | |||
80 | * @adev: ATA device | 77 | * @adev: ATA device |
81 | * | 78 | * |
82 | * Called to do the PIO mode setup. The MPIIX allows us to program the | 79 | * Called to do the PIO mode setup. The MPIIX allows us to program the |
83 | * IORDY sample point (2-5 clocks), recovery 1-4 clocks and whether | 80 | * IORDY sample point (2-5 clocks), recovery (1-4 clocks) and whether |
84 | * prefetching or iordy are used. | 81 | * prefetching or IORDY are used. |
85 | * | 82 | * |
86 | * This would get very ugly because we can only program timing for one | 83 | * This would get very ugly because we can only program timing for one |
87 | * device at a time, the other gets PIO0. Fortunately libata calls | 84 | * device at a time, the other gets PIO0. Fortunately libata calls |
@@ -103,18 +100,19 @@ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
103 | { 2, 3 }, }; | 100 | { 2, 3 }, }; |
104 | 101 | ||
105 | pci_read_config_word(pdev, IDETIM, &idetim); | 102 | pci_read_config_word(pdev, IDETIM, &idetim); |
106 | /* Mask the IORDY/TIME/PPE0 bank for this device */ | 103 | |
104 | /* Mask the IORDY/TIME/PPE for this device */ | ||
107 | if (adev->class == ATA_DEV_ATA) | 105 | if (adev->class == ATA_DEV_ATA) |
108 | control |= PPE; /* PPE enable for disk */ | 106 | control |= PPE; /* Enable prefetch/posting for disk */ |
109 | if (ata_pio_need_iordy(adev)) | 107 | if (ata_pio_need_iordy(adev)) |
110 | control |= IORDY; /* IORDY */ | 108 | control |= IORDY; |
111 | if (pio > 0) | 109 | if (pio > 1) |
112 | control |= FTIM; /* This drive is on the fast timing bank */ | 110 | control |= FTIM; /* This drive is on the fast timing bank */ |
113 | 111 | ||
114 | /* Mask out timing and clear both TIME bank selects */ | 112 | /* Mask out timing and clear both TIME bank selects */ |
115 | idetim &= 0xCCEE; | 113 | idetim &= 0xCCEE; |
116 | idetim &= ~(0x07 << (2 * adev->devno)); | 114 | idetim &= ~(0x07 << (4 * adev->devno)); |
117 | idetim |= (control << (2 * adev->devno)); | 115 | idetim |= control << (4 * adev->devno); |
118 | 116 | ||
119 | idetim |= (timings[pio][0] << 12) | (timings[pio][1] << 8); | 117 | idetim |= (timings[pio][0] << 12) | (timings[pio][1] << 8); |
120 | pci_write_config_word(pdev, IDETIM, idetim); | 118 | pci_write_config_word(pdev, IDETIM, idetim); |
@@ -188,23 +186,24 @@ static struct ata_port_operations mpiix_port_ops = { | |||
188 | 186 | ||
189 | .qc_prep = ata_qc_prep, | 187 | .qc_prep = ata_qc_prep, |
190 | .qc_issue = mpiix_qc_issue_prot, | 188 | .qc_issue = mpiix_qc_issue_prot, |
191 | .data_xfer = ata_pio_data_xfer, | 189 | .data_xfer = ata_data_xfer, |
192 | 190 | ||
193 | .irq_handler = ata_interrupt, | 191 | .irq_handler = ata_interrupt, |
194 | .irq_clear = ata_bmdma_irq_clear, | 192 | .irq_clear = ata_bmdma_irq_clear, |
193 | .irq_on = ata_irq_on, | ||
194 | .irq_ack = ata_irq_ack, | ||
195 | 195 | ||
196 | .port_start = ata_port_start, | 196 | .port_start = ata_port_start, |
197 | .port_stop = ata_port_stop, | ||
198 | .host_stop = ata_host_stop | ||
199 | }; | 197 | }; |
200 | 198 | ||
201 | static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id) | 199 | static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id) |
202 | { | 200 | { |
203 | /* Single threaded by the PCI probe logic */ | 201 | /* Single threaded by the PCI probe logic */ |
204 | static struct ata_probe_ent probe[2]; | 202 | static struct ata_probe_ent probe; |
205 | static int printed_version; | 203 | static int printed_version; |
204 | void __iomem *cmd_addr, *ctl_addr; | ||
206 | u16 idetim; | 205 | u16 idetim; |
207 | int enabled; | 206 | int irq; |
208 | 207 | ||
209 | if (!printed_version++) | 208 | if (!printed_version++) |
210 | dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); | 209 | dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); |
@@ -217,65 +216,49 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
217 | if (!(idetim & ENABLED)) | 216 | if (!(idetim & ENABLED)) |
218 | return -ENODEV; | 217 | return -ENODEV; |
219 | 218 | ||
219 | /* See if it's primary or secondary channel... */ | ||
220 | if (!(idetim & SECONDARY)) { | ||
221 | irq = 14; | ||
222 | cmd_addr = devm_ioport_map(&dev->dev, 0x1F0, 8); | ||
223 | ctl_addr = devm_ioport_map(&dev->dev, 0x3F6, 1); | ||
224 | } else { | ||
225 | irq = 15; | ||
226 | cmd_addr = devm_ioport_map(&dev->dev, 0x170, 8); | ||
227 | ctl_addr = devm_ioport_map(&dev->dev, 0x376, 1); | ||
228 | } | ||
229 | |||
230 | if (!cmd_addr || !ctl_addr) | ||
231 | return -ENOMEM; | ||
232 | |||
220 | /* We do our own plumbing to avoid leaking special cases for whacko | 233 | /* We do our own plumbing to avoid leaking special cases for whacko |
221 | ancient hardware into the core code. There are two issues to | 234 | ancient hardware into the core code. There are two issues to |
222 | worry about. #1 The chip is a bridge so if in legacy mode and | 235 | worry about. #1 The chip is a bridge so if in legacy mode and |
223 | without BARs set fools the setup. #2 If you pci_disable_device | 236 | without BARs set fools the setup. #2 If you pci_disable_device |
224 | the MPIIX your box goes castors up */ | 237 | the MPIIX your box goes castors up */ |
225 | 238 | ||
226 | INIT_LIST_HEAD(&probe[0].node); | 239 | INIT_LIST_HEAD(&probe.node); |
227 | probe[0].dev = pci_dev_to_dev(dev); | 240 | probe.dev = pci_dev_to_dev(dev); |
228 | probe[0].port_ops = &mpiix_port_ops; | 241 | probe.port_ops = &mpiix_port_ops; |
229 | probe[0].sht = &mpiix_sht; | 242 | probe.sht = &mpiix_sht; |
230 | probe[0].pio_mask = 0x1F; | 243 | probe.pio_mask = 0x1F; |
231 | probe[0].irq = 14; | 244 | probe.irq_flags = SA_SHIRQ; |
232 | probe[0].irq_flags = SA_SHIRQ; | 245 | probe.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; |
233 | probe[0].port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; | 246 | probe.n_ports = 1; |
234 | probe[0].n_ports = 1; | 247 | |
235 | probe[0].port[0].cmd_addr = 0x1F0; | 248 | probe.irq = irq; |
236 | probe[0].port[0].ctl_addr = 0x3F6; | 249 | probe.port[0].cmd_addr = cmd_addr; |
237 | probe[0].port[0].altstatus_addr = 0x3F6; | 250 | probe.port[0].ctl_addr = ctl_addr; |
238 | 251 | probe.port[0].altstatus_addr = ctl_addr; | |
239 | /* The secondary lurks at different addresses but is otherwise | ||
240 | the same beastie */ | ||
241 | |||
242 | INIT_LIST_HEAD(&probe[1].node); | ||
243 | probe[1] = probe[0]; | ||
244 | probe[1].irq = 15; | ||
245 | probe[1].port[0].cmd_addr = 0x170; | ||
246 | probe[1].port[0].ctl_addr = 0x376; | ||
247 | probe[1].port[0].altstatus_addr = 0x376; | ||
248 | 252 | ||
249 | /* Let libata fill in the port details */ | 253 | /* Let libata fill in the port details */ |
250 | ata_std_ports(&probe[0].port[0]); | 254 | ata_std_ports(&probe.port[0]); |
251 | ata_std_ports(&probe[1].port[0]); | ||
252 | 255 | ||
253 | /* Now add the port that is active */ | 256 | /* Now add the port that is active */ |
254 | enabled = (idetim & SECONDARY) ? 1 : 0; | 257 | if (ata_device_add(&probe)) |
255 | |||
256 | if (ata_device_add(&probe[enabled])) | ||
257 | return 0; | 258 | return 0; |
258 | return -ENODEV; | 259 | return -ENODEV; |
259 | } | 260 | } |
260 | 261 | ||
261 | /** | ||
262 | * mpiix_remove_one - device unload | ||
263 | * @pdev: PCI device being removed | ||
264 | * | ||
265 | * Handle an unplug/unload event for a PCI device. Unload the | ||
266 | * PCI driver but do not use the default handler as we *MUST NOT* | ||
267 | * disable the device as it has other functions. | ||
268 | */ | ||
269 | |||
270 | static void __devexit mpiix_remove_one(struct pci_dev *pdev) | ||
271 | { | ||
272 | struct device *dev = pci_dev_to_dev(pdev); | ||
273 | struct ata_host *host = dev_get_drvdata(dev); | ||
274 | |||
275 | ata_host_remove(host); | ||
276 | dev_set_drvdata(dev, NULL); | ||
277 | } | ||
278 | |||
279 | static const struct pci_device_id mpiix[] = { | 262 | static const struct pci_device_id mpiix[] = { |
280 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), }, | 263 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), }, |
281 | 264 | ||
@@ -286,7 +269,7 @@ static struct pci_driver mpiix_pci_driver = { | |||
286 | .name = DRV_NAME, | 269 | .name = DRV_NAME, |
287 | .id_table = mpiix, | 270 | .id_table = mpiix, |
288 | .probe = mpiix_init_one, | 271 | .probe = mpiix_init_one, |
289 | .remove = mpiix_remove_one, | 272 | .remove = ata_pci_remove_one, |
290 | .suspend = ata_pci_device_suspend, | 273 | .suspend = ata_pci_device_suspend, |
291 | .resume = ata_pci_device_resume, | 274 | .resume = ata_pci_device_resume, |
292 | }; | 275 | }; |