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 | } |