diff options
Diffstat (limited to 'drivers/ide/pci/sgiioc4.c')
-rw-r--r-- | drivers/ide/pci/sgiioc4.c | 65 |
1 files changed, 39 insertions, 26 deletions
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index c79ff5b41088..42eef19a18f1 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c | |||
@@ -127,7 +127,7 @@ sgiioc4_checkirq(ide_hwif_t * hwif) | |||
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | 129 | ||
130 | static u8 sgiioc4_INB(unsigned long); | 130 | static u8 sgiioc4_read_status(ide_hwif_t *); |
131 | 131 | ||
132 | static int | 132 | static int |
133 | sgiioc4_clearirq(ide_drive_t * drive) | 133 | sgiioc4_clearirq(ide_drive_t * drive) |
@@ -141,18 +141,19 @@ sgiioc4_clearirq(ide_drive_t * drive) | |||
141 | intr_reg = readl((void __iomem *)other_ir); | 141 | intr_reg = readl((void __iomem *)other_ir); |
142 | if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */ | 142 | if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */ |
143 | /* | 143 | /* |
144 | * Using sgiioc4_INB to read the Status register has a side | 144 | * Using sgiioc4_read_status to read the Status register has a |
145 | * effect of clearing the interrupt. The first read should | 145 | * side effect of clearing the interrupt. The first read should |
146 | * clear it if it is set. The second read should return | 146 | * clear it if it is set. The second read should return |
147 | * a "clear" status if it got cleared. If not, then spin | 147 | * a "clear" status if it got cleared. If not, then spin |
148 | * for a bit trying to clear it. | 148 | * for a bit trying to clear it. |
149 | */ | 149 | */ |
150 | u8 stat = sgiioc4_INB(io_ports->status_addr); | 150 | u8 stat = sgiioc4_read_status(hwif); |
151 | int count = 0; | 151 | int count = 0; |
152 | stat = sgiioc4_INB(io_ports->status_addr); | 152 | |
153 | stat = sgiioc4_read_status(hwif); | ||
153 | while ((stat & 0x80) && (count++ < 100)) { | 154 | while ((stat & 0x80) && (count++ < 100)) { |
154 | udelay(1); | 155 | udelay(1); |
155 | stat = sgiioc4_INB(io_ports->status_addr); | 156 | stat = sgiioc4_read_status(hwif); |
156 | } | 157 | } |
157 | 158 | ||
158 | if (intr_reg & 0x02) { | 159 | if (intr_reg & 0x02) { |
@@ -304,9 +305,9 @@ sgiioc4_dma_lost_irq(ide_drive_t * drive) | |||
304 | ide_dma_lost_irq(drive); | 305 | ide_dma_lost_irq(drive); |
305 | } | 306 | } |
306 | 307 | ||
307 | static u8 | 308 | static u8 sgiioc4_read_status(ide_hwif_t *hwif) |
308 | sgiioc4_INB(unsigned long port) | ||
309 | { | 309 | { |
310 | unsigned long port = hwif->io_ports.status_addr; | ||
310 | u8 reg = (u8) readb((void __iomem *) port); | 311 | u8 reg = (u8) readb((void __iomem *) port); |
311 | 312 | ||
312 | if ((port & 0xFFF) == 0x11C) { /* Status register of IOC4 */ | 313 | if ((port & 0xFFF) == 0x11C) { /* Status register of IOC4 */ |
@@ -549,6 +550,21 @@ static int sgiioc4_dma_setup(ide_drive_t *drive) | |||
549 | return 0; | 550 | return 0; |
550 | } | 551 | } |
551 | 552 | ||
553 | static const struct ide_tp_ops sgiioc4_tp_ops = { | ||
554 | .exec_command = ide_exec_command, | ||
555 | .read_status = sgiioc4_read_status, | ||
556 | .read_altstatus = ide_read_altstatus, | ||
557 | .read_sff_dma_status = ide_read_sff_dma_status, | ||
558 | |||
559 | .set_irq = ide_set_irq, | ||
560 | |||
561 | .tf_load = ide_tf_load, | ||
562 | .tf_read = ide_tf_read, | ||
563 | |||
564 | .input_data = ide_input_data, | ||
565 | .output_data = ide_output_data, | ||
566 | }; | ||
567 | |||
552 | static const struct ide_port_ops sgiioc4_port_ops = { | 568 | static const struct ide_port_ops sgiioc4_port_ops = { |
553 | .set_dma_mode = sgiioc4_set_dma_mode, | 569 | .set_dma_mode = sgiioc4_set_dma_mode, |
554 | /* reset DMA engine, clear IRQs */ | 570 | /* reset DMA engine, clear IRQs */ |
@@ -571,6 +587,7 @@ static const struct ide_port_info sgiioc4_port_info __devinitdata = { | |||
571 | .name = DRV_NAME, | 587 | .name = DRV_NAME, |
572 | .chipset = ide_pci, | 588 | .chipset = ide_pci, |
573 | .init_dma = ide_dma_sgiioc4, | 589 | .init_dma = ide_dma_sgiioc4, |
590 | .tp_ops = &sgiioc4_tp_ops, | ||
574 | .port_ops = &sgiioc4_port_ops, | 591 | .port_ops = &sgiioc4_port_ops, |
575 | .dma_ops = &sgiioc4_dma_ops, | 592 | .dma_ops = &sgiioc4_dma_ops, |
576 | .host_flags = IDE_HFLAG_MMIO, | 593 | .host_flags = IDE_HFLAG_MMIO, |
@@ -583,10 +600,10 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) | |||
583 | unsigned long cmd_base, irqport; | 600 | unsigned long cmd_base, irqport; |
584 | unsigned long bar0, cmd_phys_base, ctl; | 601 | unsigned long bar0, cmd_phys_base, ctl; |
585 | void __iomem *virt_base; | 602 | void __iomem *virt_base; |
586 | ide_hwif_t *hwif; | 603 | struct ide_host *host; |
587 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; | 604 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; |
588 | hw_regs_t hw; | ||
589 | struct ide_port_info d = sgiioc4_port_info; | 605 | struct ide_port_info d = sgiioc4_port_info; |
606 | int rc; | ||
590 | 607 | ||
591 | /* Get the CmdBlk and CtrlBlk Base Registers */ | 608 | /* Get the CmdBlk and CtrlBlk Base Registers */ |
592 | bar0 = pci_resource_start(dev, 0); | 609 | bar0 = pci_resource_start(dev, 0); |
@@ -618,30 +635,26 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) | |||
618 | hw.chipset = ide_pci; | 635 | hw.chipset = ide_pci; |
619 | hw.dev = &dev->dev; | 636 | hw.dev = &dev->dev; |
620 | 637 | ||
621 | hwif = ide_find_port_slot(&d); | ||
622 | if (hwif == NULL) | ||
623 | goto err; | ||
624 | |||
625 | ide_init_port_hw(hwif, &hw); | ||
626 | |||
627 | /* The IOC4 uses MMIO rather than Port IO. */ | ||
628 | default_hwif_mmiops(hwif); | ||
629 | |||
630 | /* Initializing chipset IRQ Registers */ | 638 | /* Initializing chipset IRQ Registers */ |
631 | writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); | 639 | writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); |
632 | 640 | ||
633 | hwif->INB = &sgiioc4_INB; | 641 | host = ide_host_alloc(&d, hws); |
634 | 642 | if (host == NULL) { | |
635 | idx[0] = hwif->index; | 643 | rc = -ENOMEM; |
644 | goto err; | ||
645 | } | ||
636 | 646 | ||
637 | if (ide_device_add(idx, &d)) | 647 | rc = ide_host_register(host, &d, hws); |
638 | return -EIO; | 648 | if (rc) |
649 | goto err_free; | ||
639 | 650 | ||
640 | return 0; | 651 | return 0; |
652 | err_free: | ||
653 | ide_host_free(host); | ||
641 | err: | 654 | err: |
642 | release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE); | 655 | release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE); |
643 | iounmap(virt_base); | 656 | iounmap(virt_base); |
644 | return -ENOMEM; | 657 | return rc; |
645 | } | 658 | } |
646 | 659 | ||
647 | static unsigned int __devinit | 660 | static unsigned int __devinit |