diff options
Diffstat (limited to 'drivers/ide/setup-pci.c')
| -rw-r--r-- | drivers/ide/setup-pci.c | 109 |
1 files changed, 60 insertions, 49 deletions
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 65fc08b6b6d0..b15cad58dc81 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c | |||
| @@ -73,15 +73,12 @@ static void ide_pci_clear_simplex(unsigned long dma_base, const char *name) | |||
| 73 | * @d: IDE port info | 73 | * @d: IDE port info |
| 74 | * | 74 | * |
| 75 | * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space. | 75 | * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space. |
| 76 | * Where a device has a partner that is already in DMA mode we check | ||
| 77 | * and enforce IDE simplex rules. | ||
| 78 | */ | 76 | */ |
| 79 | 77 | ||
| 80 | unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d) | 78 | unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d) |
| 81 | { | 79 | { |
| 82 | struct pci_dev *dev = to_pci_dev(hwif->dev); | 80 | struct pci_dev *dev = to_pci_dev(hwif->dev); |
| 83 | unsigned long dma_base = 0; | 81 | unsigned long dma_base = 0; |
| 84 | u8 dma_stat = 0; | ||
| 85 | 82 | ||
| 86 | if (hwif->host_flags & IDE_HFLAG_MMIO) | 83 | if (hwif->host_flags & IDE_HFLAG_MMIO) |
| 87 | return hwif->dma_base; | 84 | return hwif->dma_base; |
| @@ -102,11 +99,19 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d) | |||
| 102 | if (hwif->channel) | 99 | if (hwif->channel) |
| 103 | dma_base += 8; | 100 | dma_base += 8; |
| 104 | 101 | ||
| 105 | if (d->host_flags & IDE_HFLAG_CS5520) | 102 | return dma_base; |
| 103 | } | ||
| 104 | EXPORT_SYMBOL_GPL(ide_pci_dma_base); | ||
| 105 | |||
| 106 | int ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d) | ||
| 107 | { | ||
| 108 | u8 dma_stat; | ||
| 109 | |||
| 110 | if (d->host_flags & (IDE_HFLAG_MMIO | IDE_HFLAG_CS5520)) | ||
| 106 | goto out; | 111 | goto out; |
| 107 | 112 | ||
| 108 | if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) { | 113 | if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) { |
| 109 | ide_pci_clear_simplex(dma_base, d->name); | 114 | ide_pci_clear_simplex(hwif->dma_base, d->name); |
| 110 | goto out; | 115 | goto out; |
| 111 | } | 116 | } |
| 112 | 117 | ||
| @@ -120,15 +125,15 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d) | |||
| 120 | * we tune the drive then try to grab DMA ownership if we want to be | 125 | * we tune the drive then try to grab DMA ownership if we want to be |
| 121 | * the DMA end. This has to be become dynamic to handle hot-plug. | 126 | * the DMA end. This has to be become dynamic to handle hot-plug. |
| 122 | */ | 127 | */ |
| 123 | dma_stat = hwif->INB(dma_base + 2); | 128 | dma_stat = hwif->tp_ops->read_sff_dma_status(hwif); |
| 124 | if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) { | 129 | if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) { |
| 125 | printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name); | 130 | printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name); |
| 126 | dma_base = 0; | 131 | return -1; |
| 127 | } | 132 | } |
| 128 | out: | 133 | out: |
| 129 | return dma_base; | 134 | return 0; |
| 130 | } | 135 | } |
| 131 | EXPORT_SYMBOL_GPL(ide_pci_dma_base); | 136 | EXPORT_SYMBOL_GPL(ide_pci_check_simplex); |
| 132 | 137 | ||
| 133 | /* | 138 | /* |
| 134 | * Set up BM-DMA capability (PnP BIOS should have done this) | 139 | * Set up BM-DMA capability (PnP BIOS should have done this) |
| @@ -284,33 +289,31 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * | |||
| 284 | } | 289 | } |
| 285 | 290 | ||
| 286 | /** | 291 | /** |
| 287 | * ide_hwif_configure - configure an IDE interface | 292 | * ide_hw_configure - configure a hw_regs_t instance |
| 288 | * @dev: PCI device holding interface | 293 | * @dev: PCI device holding interface |
| 289 | * @d: IDE port info | 294 | * @d: IDE port info |
| 290 | * @port: port number | 295 | * @port: port number |
| 291 | * @irq: PCI IRQ | 296 | * @irq: PCI IRQ |
| 297 | * @hw: hw_regs_t instance corresponding to this port | ||
| 292 | * | 298 | * |
| 293 | * Perform the initial set up for the hardware interface structure. This | 299 | * Perform the initial set up for the hardware interface structure. This |
| 294 | * is done per interface port rather than per PCI device. There may be | 300 | * is done per interface port rather than per PCI device. There may be |
| 295 | * more than one port per device. | 301 | * more than one port per device. |
| 296 | * | 302 | * |
| 297 | * Returns the new hardware interface structure, or NULL on a failure | 303 | * Returns zero on success or an error code. |
| 298 | */ | 304 | */ |
| 299 | 305 | ||
| 300 | static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, | 306 | static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, |
| 301 | const struct ide_port_info *d, | 307 | unsigned int port, int irq, hw_regs_t *hw) |
| 302 | unsigned int port, int irq) | ||
| 303 | { | 308 | { |
| 304 | unsigned long ctl = 0, base = 0; | 309 | unsigned long ctl = 0, base = 0; |
| 305 | ide_hwif_t *hwif; | ||
| 306 | struct hw_regs_s hw; | ||
| 307 | 310 | ||
| 308 | if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) { | 311 | if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) { |
| 309 | if (ide_pci_check_iomem(dev, d, 2 * port) || | 312 | if (ide_pci_check_iomem(dev, d, 2 * port) || |
| 310 | ide_pci_check_iomem(dev, d, 2 * port + 1)) { | 313 | ide_pci_check_iomem(dev, d, 2 * port + 1)) { |
| 311 | printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported " | 314 | printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported " |
| 312 | "as MEM for port %d!\n", d->name, port); | 315 | "as MEM for port %d!\n", d->name, port); |
| 313 | return NULL; | 316 | return -EINVAL; |
| 314 | } | 317 | } |
| 315 | 318 | ||
| 316 | ctl = pci_resource_start(dev, 2*port+1); | 319 | ctl = pci_resource_start(dev, 2*port+1); |
| @@ -324,22 +327,16 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, | |||
| 324 | if (!base || !ctl) { | 327 | if (!base || !ctl) { |
| 325 | printk(KERN_ERR "%s: bad PCI BARs for port %d, skipping\n", | 328 | printk(KERN_ERR "%s: bad PCI BARs for port %d, skipping\n", |
| 326 | d->name, port); | 329 | d->name, port); |
| 327 | return NULL; | 330 | return -EINVAL; |
| 328 | } | 331 | } |
| 329 | 332 | ||
| 330 | hwif = ide_find_port_slot(d); | 333 | memset(hw, 0, sizeof(*hw)); |
| 331 | if (hwif == NULL) | 334 | hw->irq = irq; |
| 332 | return NULL; | 335 | hw->dev = &dev->dev; |
| 333 | 336 | hw->chipset = d->chipset ? d->chipset : ide_pci; | |
| 334 | memset(&hw, 0, sizeof(hw)); | 337 | ide_std_init_ports(hw, base, ctl | 2); |
| 335 | hw.irq = irq; | ||
| 336 | hw.dev = &dev->dev; | ||
| 337 | hw.chipset = d->chipset ? d->chipset : ide_pci; | ||
| 338 | ide_std_init_ports(&hw, base, ctl | 2); | ||
| 339 | |||
| 340 | ide_init_port_hw(hwif, &hw); | ||
| 341 | 338 | ||
| 342 | return hwif; | 339 | return 0; |
| 343 | } | 340 | } |
| 344 | 341 | ||
| 345 | #ifdef CONFIG_BLK_DEV_IDEDMA_PCI | 342 | #ifdef CONFIG_BLK_DEV_IDEDMA_PCI |
| @@ -362,7 +359,15 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) | |||
| 362 | (dev->class & 0x80))) { | 359 | (dev->class & 0x80))) { |
| 363 | unsigned long base = ide_pci_dma_base(hwif, d); | 360 | unsigned long base = ide_pci_dma_base(hwif, d); |
| 364 | 361 | ||
| 365 | if (base == 0 || ide_pci_set_master(dev, d->name) < 0) | 362 | if (base == 0) |
| 363 | return -1; | ||
| 364 | |||
| 365 | hwif->dma_base = base; | ||
| 366 | |||
| 367 | if (ide_pci_check_simplex(hwif, d) < 0) | ||
| 368 | return -1; | ||
| 369 | |||
| 370 | if (ide_pci_set_master(dev, d->name) < 0) | ||
| 366 | return -1; | 371 | return -1; |
| 367 | 372 | ||
| 368 | if (hwif->host_flags & IDE_HFLAG_MMIO) | 373 | if (hwif->host_flags & IDE_HFLAG_MMIO) |
| @@ -376,7 +381,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) | |||
| 376 | if (ide_allocate_dma_engine(hwif)) | 381 | if (ide_allocate_dma_engine(hwif)) |
| 377 | return -1; | 382 | return -1; |
| 378 | 383 | ||
| 379 | ide_setup_dma(hwif, base); | 384 | hwif->dma_ops = &sff_dma_ops; |
| 380 | } | 385 | } |
| 381 | 386 | ||
| 382 | return 0; | 387 | return 0; |
| @@ -429,7 +434,8 @@ out: | |||
| 429 | * @dev: PCI device | 434 | * @dev: PCI device |
| 430 | * @d: IDE port info | 435 | * @d: IDE port info |
| 431 | * @pciirq: IRQ line | 436 | * @pciirq: IRQ line |
| 432 | * @idx: ATA index table to update | 437 | * @hw: hw_regs_t instances corresponding to this PCI IDE device |
| 438 | * @hws: hw_regs_t pointers table to update | ||
| 433 | * | 439 | * |
| 434 | * Scan the interfaces attached to this device and do any | 440 | * Scan the interfaces attached to this device and do any |
| 435 | * necessary per port setup. Attach the devices and ask the | 441 | * necessary per port setup. Attach the devices and ask the |
| @@ -440,10 +446,10 @@ out: | |||
| 440 | * where the chipset setup is not the default PCI IDE one. | 446 | * where the chipset setup is not the default PCI IDE one. |
| 441 | */ | 447 | */ |
| 442 | 448 | ||
| 443 | void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx) | 449 | void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, |
| 450 | int pciirq, hw_regs_t *hw, hw_regs_t **hws) | ||
| 444 | { | 451 | { |
| 445 | int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; | 452 | int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; |
| 446 | ide_hwif_t *hwif; | ||
| 447 | u8 tmp; | 453 | u8 tmp; |
| 448 | 454 | ||
| 449 | /* | 455 | /* |
| @@ -459,11 +465,10 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int | |||
| 459 | continue; /* port not enabled */ | 465 | continue; /* port not enabled */ |
| 460 | } | 466 | } |
| 461 | 467 | ||
| 462 | hwif = ide_hwif_configure(dev, d, port, pciirq); | 468 | if (ide_hw_configure(dev, d, port, pciirq, hw + port)) |
| 463 | if (hwif == NULL) | ||
| 464 | continue; | 469 | continue; |
| 465 | 470 | ||
| 466 | *(idx + port) = hwif->index; | 471 | *(hws + port) = hw + port; |
| 467 | } | 472 | } |
| 468 | } | 473 | } |
| 469 | EXPORT_SYMBOL_GPL(ide_pci_setup_ports); | 474 | EXPORT_SYMBOL_GPL(ide_pci_setup_ports); |
| @@ -480,7 +485,7 @@ EXPORT_SYMBOL_GPL(ide_pci_setup_ports); | |||
| 480 | */ | 485 | */ |
| 481 | static int do_ide_setup_pci_device(struct pci_dev *dev, | 486 | static int do_ide_setup_pci_device(struct pci_dev *dev, |
| 482 | const struct ide_port_info *d, | 487 | const struct ide_port_info *d, |
| 483 | u8 *idx, u8 noisy) | 488 | u8 noisy) |
| 484 | { | 489 | { |
| 485 | int tried_config = 0; | 490 | int tried_config = 0; |
| 486 | int pciirq, ret; | 491 | int pciirq, ret; |
| @@ -529,22 +534,24 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, | |||
| 529 | d->name, pciirq); | 534 | d->name, pciirq); |
| 530 | } | 535 | } |
| 531 | 536 | ||
| 532 | /* FIXME: silent failure can happen */ | 537 | ret = pciirq; |
| 533 | |||
| 534 | ide_pci_setup_ports(dev, d, pciirq, idx); | ||
| 535 | out: | 538 | out: |
| 536 | return ret; | 539 | return ret; |
| 537 | } | 540 | } |
| 538 | 541 | ||
| 539 | int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) | 542 | int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) |
| 540 | { | 543 | { |
| 541 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; | 544 | hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; |
| 542 | int ret; | 545 | int ret; |
| 543 | 546 | ||
| 544 | ret = do_ide_setup_pci_device(dev, d, &idx[0], 1); | 547 | ret = do_ide_setup_pci_device(dev, d, 1); |
| 548 | |||
| 549 | if (ret >= 0) { | ||
| 550 | /* FIXME: silent failure can happen */ | ||
| 551 | ide_pci_setup_ports(dev, d, ret, &hw[0], &hws[0]); | ||
| 545 | 552 | ||
| 546 | if (ret >= 0) | 553 | ret = ide_host_add(d, hws, NULL); |
| 547 | ide_device_add(idx, d); | 554 | } |
| 548 | 555 | ||
| 549 | return ret; | 556 | return ret; |
| 550 | } | 557 | } |
| @@ -555,19 +562,23 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, | |||
| 555 | { | 562 | { |
| 556 | struct pci_dev *pdev[] = { dev1, dev2 }; | 563 | struct pci_dev *pdev[] = { dev1, dev2 }; |
| 557 | int ret, i; | 564 | int ret, i; |
| 558 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; | 565 | hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; |
| 559 | 566 | ||
| 560 | for (i = 0; i < 2; i++) { | 567 | for (i = 0; i < 2; i++) { |
| 561 | ret = do_ide_setup_pci_device(pdev[i], d, &idx[i*2], !i); | 568 | ret = do_ide_setup_pci_device(pdev[i], d, !i); |
| 569 | |||
| 562 | /* | 570 | /* |
| 563 | * FIXME: Mom, mom, they stole me the helper function to undo | 571 | * FIXME: Mom, mom, they stole me the helper function to undo |
| 564 | * do_ide_setup_pci_device() on the first device! | 572 | * do_ide_setup_pci_device() on the first device! |
| 565 | */ | 573 | */ |
| 566 | if (ret < 0) | 574 | if (ret < 0) |
| 567 | goto out; | 575 | goto out; |
| 576 | |||
| 577 | /* FIXME: silent failure can happen */ | ||
| 578 | ide_pci_setup_ports(pdev[i], d, ret, &hw[i*2], &hws[i*2]); | ||
| 568 | } | 579 | } |
| 569 | 580 | ||
| 570 | ide_device_add(idx, d); | 581 | ret = ide_host_add(d, hws, NULL); |
| 571 | out: | 582 | out: |
| 572 | return ret; | 583 | return ret; |
| 573 | } | 584 | } |
