diff options
author | Tejun Heo <htejun@gmail.com> | 2007-04-17 10:44:07 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-28 14:16:03 -0400 |
commit | eca25dca17630ae354f4b1df559ed90578b794fe (patch) | |
tree | e1c0864264a227bf3302480c8a5290d542acbf71 /drivers/ata/sata_via.c | |
parent | 21b0ad4fb8306ac2bf5a249ffc978b1b8924c7d0 (diff) |
libata: convert drivers with combined SATA/PATA ports to new init model
Convert sata_via and sata_promise to new init model. Both controllers
can have combined configuration (SATA + PATA) and used twisted
initialization method (modifying port in ->port_start) to overcome
probe_ent limitations.
This patch converts both drivers to new init model in which such
configuration is natively supported.
* promise: Combined pata port now uses separate port_info entry right
after the sata counterpart entry.
* promise: Controller configuration is discerned using ap->flags.
This simplifies init path and makes it look more like other LLDs.
* via: Both SATA and PATA ports in vt6421 are represented in their
own port_info structure.
Tested on PDC20375 (SATA150 TX2plus) [105a:3375] and PDC40775 (SATA
300 TX2plus) [105a:3d73]. Couldn't test via cuz my c3 won't boot the
current kernel.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/sata_via.c')
-rw-r--r-- | drivers/ata/sata_via.c | 182 |
1 files changed, 80 insertions, 102 deletions
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 842ccf601224..1d855f55f5f7 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c | |||
@@ -64,8 +64,6 @@ enum { | |||
64 | PORT0 = (1 << 1), | 64 | PORT0 = (1 << 1), |
65 | PORT1 = (1 << 0), | 65 | PORT1 = (1 << 0), |
66 | ALL_PORTS = PORT0 | PORT1, | 66 | ALL_PORTS = PORT0 | PORT1, |
67 | PATA_PORT = 2, /* PATA is port 2 */ | ||
68 | N_PORTS = 3, | ||
69 | 67 | ||
70 | NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), | 68 | NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), |
71 | 69 | ||
@@ -81,7 +79,6 @@ static void vt6420_error_handler(struct ata_port *ap); | |||
81 | static int vt6421_pata_cable_detect(struct ata_port *ap); | 79 | static int vt6421_pata_cable_detect(struct ata_port *ap); |
82 | static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev); | 80 | static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev); |
83 | static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); | 81 | static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); |
84 | static int vt6421_port_start(struct ata_port *ap); | ||
85 | 82 | ||
86 | static const struct pci_device_id svia_pci_tbl[] = { | 83 | static const struct pci_device_id svia_pci_tbl[] = { |
87 | { PCI_VDEVICE(VIA, 0x5337), vt6420 }, | 84 | { PCI_VDEVICE(VIA, 0x5337), vt6420 }, |
@@ -140,7 +137,6 @@ static const struct ata_port_operations vt6420_sata_ops = { | |||
140 | .error_handler = vt6420_error_handler, | 137 | .error_handler = vt6420_error_handler, |
141 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 138 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
142 | 139 | ||
143 | .irq_handler = ata_interrupt, | ||
144 | .irq_clear = ata_bmdma_irq_clear, | 140 | .irq_clear = ata_bmdma_irq_clear, |
145 | .irq_on = ata_irq_on, | 141 | .irq_on = ata_irq_on, |
146 | .irq_ack = ata_irq_ack, | 142 | .irq_ack = ata_irq_ack, |
@@ -175,12 +171,11 @@ static const struct ata_port_operations vt6421_pata_ops = { | |||
175 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 171 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
176 | .cable_detect = vt6421_pata_cable_detect, | 172 | .cable_detect = vt6421_pata_cable_detect, |
177 | 173 | ||
178 | .irq_handler = ata_interrupt, | ||
179 | .irq_clear = ata_bmdma_irq_clear, | 174 | .irq_clear = ata_bmdma_irq_clear, |
180 | .irq_on = ata_irq_on, | 175 | .irq_on = ata_irq_on, |
181 | .irq_ack = ata_irq_ack, | 176 | .irq_ack = ata_irq_ack, |
182 | 177 | ||
183 | .port_start = vt6421_port_start, | 178 | .port_start = ata_port_start, |
184 | }; | 179 | }; |
185 | 180 | ||
186 | static const struct ata_port_operations vt6421_sata_ops = { | 181 | static const struct ata_port_operations vt6421_sata_ops = { |
@@ -207,7 +202,6 @@ static const struct ata_port_operations vt6421_sata_ops = { | |||
207 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 202 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
208 | .cable_detect = ata_cable_sata, | 203 | .cable_detect = ata_cable_sata, |
209 | 204 | ||
210 | .irq_handler = ata_interrupt, | ||
211 | .irq_clear = ata_bmdma_irq_clear, | 205 | .irq_clear = ata_bmdma_irq_clear, |
212 | .irq_on = ata_irq_on, | 206 | .irq_on = ata_irq_on, |
213 | .irq_ack = ata_irq_ack, | 207 | .irq_ack = ata_irq_ack, |
@@ -215,11 +209,10 @@ static const struct ata_port_operations vt6421_sata_ops = { | |||
215 | .scr_read = svia_scr_read, | 209 | .scr_read = svia_scr_read, |
216 | .scr_write = svia_scr_write, | 210 | .scr_write = svia_scr_write, |
217 | 211 | ||
218 | .port_start = vt6421_port_start, | 212 | .port_start = ata_port_start, |
219 | }; | 213 | }; |
220 | 214 | ||
221 | static struct ata_port_info vt6420_port_info = { | 215 | static const struct ata_port_info vt6420_port_info = { |
222 | .sht = &svia_sht, | ||
223 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, | 216 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, |
224 | .pio_mask = 0x1f, | 217 | .pio_mask = 0x1f, |
225 | .mwdma_mask = 0x07, | 218 | .mwdma_mask = 0x07, |
@@ -227,6 +220,22 @@ static struct ata_port_info vt6420_port_info = { | |||
227 | .port_ops = &vt6420_sata_ops, | 220 | .port_ops = &vt6420_sata_ops, |
228 | }; | 221 | }; |
229 | 222 | ||
223 | static struct ata_port_info vt6421_sport_info = { | ||
224 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, | ||
225 | .pio_mask = 0x1f, | ||
226 | .mwdma_mask = 0x07, | ||
227 | .udma_mask = 0x7f, | ||
228 | .port_ops = &vt6421_sata_ops, | ||
229 | }; | ||
230 | |||
231 | static struct ata_port_info vt6421_pport_info = { | ||
232 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY, | ||
233 | .pio_mask = 0x1f, | ||
234 | .mwdma_mask = 0, | ||
235 | .udma_mask = 0x7f, | ||
236 | .port_ops = &vt6421_pata_ops, | ||
237 | }; | ||
238 | |||
230 | MODULE_AUTHOR("Jeff Garzik"); | 239 | MODULE_AUTHOR("Jeff Garzik"); |
231 | MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); | 240 | MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); |
232 | MODULE_LICENSE("GPL"); | 241 | MODULE_LICENSE("GPL"); |
@@ -356,16 +365,6 @@ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev) | |||
356 | pci_write_config_byte(pdev, PATA_UDMA_TIMING, udma_bits[adev->pio_mode - XFER_UDMA_0]); | 365 | pci_write_config_byte(pdev, PATA_UDMA_TIMING, udma_bits[adev->pio_mode - XFER_UDMA_0]); |
357 | } | 366 | } |
358 | 367 | ||
359 | static int vt6421_port_start(struct ata_port *ap) | ||
360 | { | ||
361 | if (ap->port_no == PATA_PORT) { | ||
362 | ap->ops = &vt6421_pata_ops; | ||
363 | ap->mwdma_mask = 0; | ||
364 | ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST; | ||
365 | } | ||
366 | return ata_port_start(ap); | ||
367 | } | ||
368 | |||
369 | static const unsigned int svia_bar_sizes[] = { | 368 | static const unsigned int svia_bar_sizes[] = { |
370 | 8, 4, 8, 4, 16, 256 | 369 | 8, 4, 8, 4, 16, 256 |
371 | }; | 370 | }; |
@@ -384,79 +383,78 @@ static void __iomem * vt6421_scr_addr(void __iomem *addr, unsigned int port) | |||
384 | return addr + (port * 64); | 383 | return addr + (port * 64); |
385 | } | 384 | } |
386 | 385 | ||
387 | static void vt6421_init_addrs(struct ata_probe_ent *probe_ent, | 386 | static void vt6421_init_addrs(struct ata_port *ap) |
388 | void __iomem * const *iomap, unsigned int port) | ||
389 | { | 387 | { |
390 | void __iomem *reg_addr = iomap[port]; | 388 | void __iomem * const * iomap = ap->host->iomap; |
391 | void __iomem *bmdma_addr = iomap[4] + (port * 8); | 389 | void __iomem *reg_addr = iomap[ap->port_no]; |
392 | 390 | void __iomem *bmdma_addr = iomap[4] + (ap->port_no * 8); | |
393 | probe_ent->port[port].cmd_addr = reg_addr; | 391 | struct ata_ioports *ioaddr = &ap->ioaddr; |
394 | probe_ent->port[port].altstatus_addr = | 392 | |
395 | probe_ent->port[port].ctl_addr = (void __iomem *) | 393 | ioaddr->cmd_addr = reg_addr; |
394 | ioaddr->altstatus_addr = | ||
395 | ioaddr->ctl_addr = (void __iomem *) | ||
396 | ((unsigned long)(reg_addr + 8) | ATA_PCI_CTL_OFS); | 396 | ((unsigned long)(reg_addr + 8) | ATA_PCI_CTL_OFS); |
397 | probe_ent->port[port].bmdma_addr = bmdma_addr; | 397 | ioaddr->bmdma_addr = bmdma_addr; |
398 | probe_ent->port[port].scr_addr = vt6421_scr_addr(iomap[5], port); | 398 | ioaddr->scr_addr = vt6421_scr_addr(iomap[5], ap->port_no); |
399 | 399 | ||
400 | ata_std_ports(&probe_ent->port[port]); | 400 | ata_std_ports(ioaddr); |
401 | } | 401 | } |
402 | 402 | ||
403 | static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev) | 403 | static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) |
404 | { | 404 | { |
405 | struct ata_probe_ent *probe_ent; | 405 | const struct ata_port_info *ppi[] = { &vt6420_port_info, NULL }; |
406 | struct ata_port_info *ppi[2]; | 406 | struct ata_host *host; |
407 | void __iomem *bar5; | 407 | int rc; |
408 | 408 | ||
409 | ppi[0] = ppi[1] = &vt6420_port_info; | 409 | rc = ata_pci_prepare_native_host(pdev, ppi, 2, &host); |
410 | probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); | 410 | if (rc) |
411 | if (!probe_ent) | 411 | return rc; |
412 | return NULL; | 412 | *r_host = host; |
413 | 413 | ||
414 | bar5 = pcim_iomap(pdev, 5, 0); | 414 | rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME); |
415 | if (!bar5) { | 415 | if (rc) { |
416 | dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n"); | 416 | dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n"); |
417 | return NULL; | 417 | return rc; |
418 | } | 418 | } |
419 | 419 | ||
420 | probe_ent->port[0].scr_addr = svia_scr_addr(bar5, 0); | 420 | host->ports[0]->ioaddr.scr_addr = svia_scr_addr(host->iomap[5], 0); |
421 | probe_ent->port[1].scr_addr = svia_scr_addr(bar5, 1); | 421 | host->ports[1]->ioaddr.scr_addr = svia_scr_addr(host->iomap[5], 1); |
422 | 422 | ||
423 | return probe_ent; | 423 | return 0; |
424 | } | 424 | } |
425 | 425 | ||
426 | static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev) | 426 | static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) |
427 | { | 427 | { |
428 | struct ata_probe_ent *probe_ent; | 428 | const struct ata_port_info *ppi[] = |
429 | unsigned int i; | 429 | { &vt6421_sport_info, &vt6421_sport_info, &vt6421_pport_info }; |
430 | struct ata_host *host; | ||
431 | int i, rc; | ||
432 | |||
433 | *r_host = host = ata_host_alloc_pinfo(&pdev->dev, ppi, ARRAY_SIZE(ppi)); | ||
434 | if (!host) { | ||
435 | dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n"); | ||
436 | return -ENOMEM; | ||
437 | } | ||
430 | 438 | ||
431 | probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL); | 439 | rc = pcim_iomap_regions(pdev, 0x1f, DRV_NAME); |
432 | if (!probe_ent) | 440 | if (rc) { |
433 | return NULL; | 441 | dev_printk(KERN_ERR, &pdev->dev, "failed to request/iomap " |
434 | 442 | "PCI BARs (errno=%d)\n", rc); | |
435 | memset(probe_ent, 0, sizeof(*probe_ent)); | 443 | return rc; |
436 | probe_ent->dev = pci_dev_to_dev(pdev); | 444 | } |
437 | INIT_LIST_HEAD(&probe_ent->node); | 445 | host->iomap = pcim_iomap_table(pdev); |
438 | |||
439 | probe_ent->sht = &svia_sht; | ||
440 | probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY; | ||
441 | probe_ent->port_ops = &vt6421_sata_ops; | ||
442 | probe_ent->n_ports = N_PORTS; | ||
443 | probe_ent->irq = pdev->irq; | ||
444 | probe_ent->irq_flags = IRQF_SHARED; | ||
445 | probe_ent->pio_mask = 0x1f; | ||
446 | probe_ent->mwdma_mask = 0x07; | ||
447 | probe_ent->udma_mask = 0x7f; | ||
448 | |||
449 | for (i = 0; i < 6; i++) | ||
450 | if (!pcim_iomap(pdev, i, 0)) { | ||
451 | dev_printk(KERN_ERR, &pdev->dev, | ||
452 | "failed to iomap PCI BAR %d\n", i); | ||
453 | return NULL; | ||
454 | } | ||
455 | 446 | ||
456 | for (i = 0; i < N_PORTS; i++) | 447 | for (i = 0; i < host->n_ports; i++) |
457 | vt6421_init_addrs(probe_ent, pcim_iomap_table(pdev), i); | 448 | vt6421_init_addrs(host->ports[i]); |
458 | 449 | ||
459 | return probe_ent; | 450 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); |
451 | if (rc) | ||
452 | return rc; | ||
453 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | ||
454 | if (rc) | ||
455 | return rc; | ||
456 | |||
457 | return 0; | ||
460 | } | 458 | } |
461 | 459 | ||
462 | static void svia_configure(struct pci_dev *pdev) | 460 | static void svia_configure(struct pci_dev *pdev) |
@@ -503,7 +501,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
503 | static int printed_version; | 501 | static int printed_version; |
504 | unsigned int i; | 502 | unsigned int i; |
505 | int rc; | 503 | int rc; |
506 | struct ata_probe_ent *probe_ent; | 504 | struct ata_host *host; |
507 | int board_id = (int) ent->driver_data; | 505 | int board_id = (int) ent->driver_data; |
508 | const int *bar_sizes; | 506 | const int *bar_sizes; |
509 | u8 tmp8; | 507 | u8 tmp8; |
@@ -515,12 +513,6 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
515 | if (rc) | 513 | if (rc) |
516 | return rc; | 514 | return rc; |
517 | 515 | ||
518 | rc = pci_request_regions(pdev, DRV_NAME); | ||
519 | if (rc) { | ||
520 | pcim_pin_device(pdev); | ||
521 | return rc; | ||
522 | } | ||
523 | |||
524 | if (board_id == vt6420) { | 516 | if (board_id == vt6420) { |
525 | pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8); | 517 | pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8); |
526 | if (tmp8 & SATA_2DEV) { | 518 | if (tmp8 & SATA_2DEV) { |
@@ -546,32 +538,18 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
546 | return -ENODEV; | 538 | return -ENODEV; |
547 | } | 539 | } |
548 | 540 | ||
549 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); | ||
550 | if (rc) | ||
551 | return rc; | ||
552 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | ||
553 | if (rc) | ||
554 | return rc; | ||
555 | |||
556 | if (board_id == vt6420) | 541 | if (board_id == vt6420) |
557 | probe_ent = vt6420_init_probe_ent(pdev); | 542 | rc = vt6420_prepare_host(pdev, &host); |
558 | else | 543 | else |
559 | probe_ent = vt6421_init_probe_ent(pdev); | 544 | rc = vt6421_prepare_host(pdev, &host); |
560 | 545 | if (rc) | |
561 | if (!probe_ent) { | 546 | return rc; |
562 | dev_printk(KERN_ERR, &pdev->dev, "out of memory\n"); | ||
563 | return -ENOMEM; | ||
564 | } | ||
565 | 547 | ||
566 | svia_configure(pdev); | 548 | svia_configure(pdev); |
567 | 549 | ||
568 | pci_set_master(pdev); | 550 | pci_set_master(pdev); |
569 | 551 | return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED, | |
570 | if (!ata_device_add(probe_ent)) | 552 | &svia_sht); |
571 | return -ENODEV; | ||
572 | |||
573 | devm_kfree(&pdev->dev, probe_ent); | ||
574 | return 0; | ||
575 | } | 553 | } |
576 | 554 | ||
577 | static int __init svia_init(void) | 555 | static int __init svia_init(void) |