diff options
Diffstat (limited to 'drivers/ide/pci/ns87415.c')
-rw-r--r-- | drivers/ide/pci/ns87415.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index e1b0c9a9ab9c..fec4955f449b 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c | |||
@@ -63,6 +63,48 @@ static u8 superio_ide_inb (unsigned long port) | |||
63 | return inb(port); | 63 | return inb(port); |
64 | } | 64 | } |
65 | 65 | ||
66 | static void superio_tf_read(ide_drive_t *drive, ide_task_t *task) | ||
67 | { | ||
68 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; | ||
69 | struct ide_taskfile *tf = &task->tf; | ||
70 | |||
71 | if (task->tf_flags & IDE_TFLAG_IN_DATA) { | ||
72 | u16 data = inw(io_ports->data_addr); | ||
73 | |||
74 | tf->data = data & 0xff; | ||
75 | tf->hob_data = (data >> 8) & 0xff; | ||
76 | } | ||
77 | |||
78 | /* be sure we're looking at the low order bits */ | ||
79 | outb(drive->ctl & ~0x80, io_ports->ctl_addr); | ||
80 | |||
81 | if (task->tf_flags & IDE_TFLAG_IN_NSECT) | ||
82 | tf->nsect = inb(io_ports->nsect_addr); | ||
83 | if (task->tf_flags & IDE_TFLAG_IN_LBAL) | ||
84 | tf->lbal = inb(io_ports->lbal_addr); | ||
85 | if (task->tf_flags & IDE_TFLAG_IN_LBAM) | ||
86 | tf->lbam = inb(io_ports->lbam_addr); | ||
87 | if (task->tf_flags & IDE_TFLAG_IN_LBAH) | ||
88 | tf->lbah = inb(io_ports->lbah_addr); | ||
89 | if (task->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
90 | tf->device = superio_ide_inb(io_ports->device_addr); | ||
91 | |||
92 | if (task->tf_flags & IDE_TFLAG_LBA48) { | ||
93 | outb(drive->ctl | 0x80, io_ports->ctl_addr); | ||
94 | |||
95 | if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | ||
96 | tf->hob_feature = inb(io_ports->feature_addr); | ||
97 | if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
98 | tf->hob_nsect = inb(io_ports->nsect_addr); | ||
99 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
100 | tf->hob_lbal = inb(io_ports->lbal_addr); | ||
101 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
102 | tf->hob_lbam = inb(io_ports->lbam_addr); | ||
103 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
104 | tf->hob_lbah = inb(io_ports->lbah_addr); | ||
105 | } | ||
106 | } | ||
107 | |||
66 | static void __devinit superio_ide_init_iops (struct hwif_s *hwif) | 108 | static void __devinit superio_ide_init_iops (struct hwif_s *hwif) |
67 | { | 109 | { |
68 | struct pci_dev *pdev = to_pci_dev(hwif->dev); | 110 | struct pci_dev *pdev = to_pci_dev(hwif->dev); |
@@ -72,14 +114,16 @@ static void __devinit superio_ide_init_iops (struct hwif_s *hwif) | |||
72 | base = pci_resource_start(pdev, port * 2) & ~3; | 114 | base = pci_resource_start(pdev, port * 2) & ~3; |
73 | dmabase = pci_resource_start(pdev, 4) & ~3; | 115 | dmabase = pci_resource_start(pdev, 4) & ~3; |
74 | 116 | ||
75 | superio_ide_status[port] = base + IDE_STATUS_OFFSET; | 117 | superio_ide_status[port] = base + 7; |
76 | superio_ide_select[port] = base + IDE_SELECT_OFFSET; | 118 | superio_ide_select[port] = base + 6; |
77 | superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa); | 119 | superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa); |
78 | 120 | ||
79 | /* Clear error/interrupt, enable dma */ | 121 | /* Clear error/interrupt, enable dma */ |
80 | tmp = superio_ide_inb(superio_ide_dma_status[port]); | 122 | tmp = superio_ide_inb(superio_ide_dma_status[port]); |
81 | outb(tmp | 0x66, superio_ide_dma_status[port]); | 123 | outb(tmp | 0x66, superio_ide_dma_status[port]); |
82 | 124 | ||
125 | hwif->tf_read = superio_tf_read; | ||
126 | |||
83 | /* We need to override inb to workaround a SuperIO errata */ | 127 | /* We need to override inb to workaround a SuperIO errata */ |
84 | hwif->INB = superio_ide_inb; | 128 | hwif->INB = superio_ide_inb; |
85 | } | 129 | } |
@@ -231,12 +275,12 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) | |||
231 | * SELECT_DRIVE() properly during first ide_probe_port(). | 275 | * SELECT_DRIVE() properly during first ide_probe_port(). |
232 | */ | 276 | */ |
233 | timeout = 10000; | 277 | timeout = 10000; |
234 | outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]); | 278 | outb(12, hwif->io_ports.ctl_addr); |
235 | udelay(10); | 279 | udelay(10); |
236 | outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]); | 280 | outb(8, hwif->io_ports.ctl_addr); |
237 | do { | 281 | do { |
238 | udelay(50); | 282 | udelay(50); |
239 | stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); | 283 | stat = hwif->INB(hwif->io_ports.status_addr); |
240 | if (stat == 0xff) | 284 | if (stat == 0xff) |
241 | break; | 285 | break; |
242 | } while ((stat & BUSY_STAT) && --timeout); | 286 | } while ((stat & BUSY_STAT) && --timeout); |
@@ -244,7 +288,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) | |||
244 | } | 288 | } |
245 | 289 | ||
246 | if (!using_inta) | 290 | if (!using_inta) |
247 | hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]); | 291 | hwif->irq = ide_default_irq(hwif->io_ports.data_addr); |
248 | else if (!hwif->irq && hwif->mate && hwif->mate->irq) | 292 | else if (!hwif->irq && hwif->mate && hwif->mate->irq) |
249 | hwif->irq = hwif->mate->irq; /* share IRQ with mate */ | 293 | hwif->irq = hwif->mate->irq; /* share IRQ with mate */ |
250 | 294 | ||