2 * linux/drivers/block/ns87415.c Version 1.00 December 7, 1997
4 * Copyright (C) 1997-1998 Mark Lord
5 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
7 * Inspired by an earlier effort from David S. Miller (davem@caipfs.rutgers.edu)
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/timer.h>
14 #include <linux/ioport.h>
15 #include <linux/interrupt.h>
16 #include <linux/blkdev.h>
17 #include <linux/hdreg.h>
18 #include <linux/pci.h>
19 #include <linux/delay.h>
20 #include <linux/ide.h>
24 static unsigned int ns87415_count
= 0, ns87415_control
[MAX_HWIFS
] = { 0 };
27 * This routine either enables/disables (according to drive->present)
28 * the IRQ associated with the port (HWIF(drive)),
29 * and selects either PIO or DMA handshaking for the next I/O operation.
31 static void ns87415_prepare_drive (ide_drive_t
*drive
, unsigned int use_dma
)
33 ide_hwif_t
*hwif
= HWIF(drive
);
34 unsigned int bit
, other
, new, *old
= (unsigned int *) hwif
->select_data
;
35 struct pci_dev
*dev
= hwif
->pci_dev
;
38 __save_flags(flags
); /* local CPU only */
39 __cli(); /* local CPU only */
42 /* Adjust IRQ enable bit */
43 bit
= 1 << (8 + hwif
->channel
);
44 new = drive
->present
? (new & ~bit
) : (new | bit
);
46 /* Select PIO or DMA, DMA may only be selected for one drive/channel. */
47 bit
= 1 << (20 + drive
->select
.b
.unit
+ (hwif
->channel
<< 1));
48 other
= 1 << (20 + (1 - drive
->select
.b
.unit
) + (hwif
->channel
<< 1));
49 new = use_dma
? ((new & ~other
) | bit
) : (new & ~bit
);
55 * Don't change DMA engine settings while Write Buffers
58 (void) pci_read_config_byte(dev
, 0x43, &stat
);
61 (void) pci_read_config_byte(dev
, 0x43, &stat
);
65 (void) pci_write_config_dword(dev
, 0x40, new);
68 * And let things settle...
73 __restore_flags(flags
); /* local CPU only */
76 static void ns87415_selectproc (ide_drive_t
*drive
)
78 ns87415_prepare_drive (drive
, drive
->using_dma
);
81 static int ns87415_dmaproc(ide_dma_action_t func
, ide_drive_t
*drive
)
83 ide_hwif_t
*hwif
= HWIF(drive
);
87 case ide_dma_end
: /* returns 1 on error, 0 otherwise */
88 drive
->waiting_for_dma
= 0;
89 dma_stat
= inb(hwif
->dma_base
+2);
90 outb(inb(hwif
->dma_base
)&~1, hwif
->dma_base
); /* stop DMA */
91 outb(inb(hwif
->dma_base
)|6, hwif
->dma_base
); /* from ERRATA: clear the INTR & ERROR bits */
92 return (dma_stat
& 7) != 4; /* verify good DMA status */
95 ns87415_prepare_drive(drive
, 1); /* select DMA xfer */
96 if (!ide_dmaproc(func
, drive
)) /* use standard DMA stuff */
98 ns87415_prepare_drive(drive
, 0); /* DMA failed: select PIO xfer */
101 return ide_dmaproc(func
, drive
); /* use standard DMA stuff */
105 void __init
ide_init_ns87415 (ide_hwif_t
*hwif
)
107 struct pci_dev
*dev
= hwif
->pci_dev
;
108 unsigned int ctrl
, using_inta
;
115 /* Set a good latency timer and cache line size value. */
116 (void) pci_write_config_byte(dev
, PCI_LATENCY_TIMER
, 64);
118 (void) pci_write_config_byte(dev
, PCI_CACHE_LINE_SIZE
, 0x10);
122 * We cannot probe for IRQ: both ports share common IRQ on INTA.
123 * Also, leave IRQ masked during drive probing, to prevent infinite
124 * interrupts from a potentially floating INTA..
126 * IRQs get unmasked in selectproc when drive is first used.
128 (void) pci_read_config_dword(dev
, 0x40, &ctrl
);
129 (void) pci_read_config_byte(dev
, 0x09, &progif
);
130 /* is irq in "native" mode? */
131 using_inta
= progif
& (1 << (hwif
->channel
<< 1));
133 using_inta
= ctrl
& (1 << (4 + hwif
->channel
));
135 hwif
->select_data
= hwif
->mate
->select_data
;
137 hwif
->select_data
= (unsigned long)
138 &ns87415_control
[ns87415_count
++];
139 ctrl
|= (1 << 8) | (1 << 9); /* mask both IRQs */
141 ctrl
&= ~(1 << 6); /* unmask INTA */
142 *((unsigned int *)hwif
->select_data
) = ctrl
;
143 (void) pci_write_config_dword(dev
, 0x40, ctrl
);
146 * Set prefetch size to 512 bytes for both ports,
147 * but don't turn on/off prefetching here.
149 pci_write_config_byte(dev
, 0x55, 0xee);
153 * XXX: Reset the device, if we don't it will not respond
154 * to SELECT_DRIVE() properly during first probe_hwif().
157 outb(12, hwif
->io_ports
[IDE_CONTROL_OFFSET
]);
159 outb(8, hwif
->io_ports
[IDE_CONTROL_OFFSET
]);
162 stat
= inb(hwif
->io_ports
[IDE_STATUS_OFFSET
]);
165 } while ((stat
& BUSY_STAT
) && --timeout
);
170 outb(0x60, hwif
->dma_base
+ 2);
173 hwif
->irq
= hwif
->channel
? 15 : 14; /* legacy mode */
174 else if (!hwif
->irq
&& hwif
->mate
&& hwif
->mate
->irq
)
175 hwif
->irq
= hwif
->mate
->irq
; /* share IRQ with mate */
178 hwif
->dmaproc
= &ns87415_dmaproc
;
179 hwif
->selectproc
= &ns87415_selectproc
;