blob: 49ae9f6d21837cbd1bb3125bf090240be3228818 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01002 * linux/drivers/ide/pci/hpt366.c Version 0.43 May 17, 2006
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
5 * Portions Copyright (C) 2001 Sun Microsystems, Inc.
6 * Portions Copyright (C) 2003 Red Hat Inc
Sergei Shtylyov836c0062006-12-13 00:35:47 -08007 * Portions Copyright (C) 2005-2006 MontaVista Software, Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * Thanks to HighPoint Technologies for their assistance, and hardware.
10 * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
11 * donation of an ABit BP6 mainboard, processor, and memory acellerated
12 * development and support.
13 *
Alan Coxb39b01f2005-06-27 15:24:27 -070014 *
Sergei Shtylyov836c0062006-12-13 00:35:47 -080015 * HighPoint has its own drivers (open source except for the RAID part)
16 * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/.
17 * This may be useful to anyone wanting to work on this driver, however do not
18 * trust them too much since the code tends to become less and less meaningful
19 * as the time passes... :-/
Alan Coxb39b01f2005-06-27 15:24:27 -070020 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 * Note that final HPT370 support was done by force extraction of GPL.
22 *
23 * - add function for getting/setting power status of drive
24 * - the HPT370's state machine can get confused. reset it before each dma
25 * xfer to prevent that from happening.
26 * - reset state engine whenever we get an error.
27 * - check for busmaster state at end of dma.
28 * - use new highpoint timings.
29 * - detect bus speed using highpoint register.
30 * - use pll if we don't have a clock table. added a 66MHz table that's
31 * just 2x the 33MHz table.
32 * - removed turnaround. NOTE: we never want to switch between pll and
33 * pci clocks as the chip can glitch in those cases. the highpoint
34 * approved workaround slows everything down too much to be useful. in
35 * addition, we would have to serialize access to each chip.
36 * Adrian Sun <a.sun@sun.com>
37 *
38 * add drive timings for 66MHz PCI bus,
39 * fix ATA Cable signal detection, fix incorrect /proc info
40 * add /proc display for per-drive PIO/DMA/UDMA mode and
41 * per-channel ATA-33/66 Cable detect.
42 * Duncan Laurie <void@sun.com>
43 *
44 * fixup /proc output for multiple controllers
45 * Tim Hockin <thockin@sun.com>
46 *
47 * On hpt366:
48 * Reset the hpt366 on error, reset on dma
49 * Fix disabling Fast Interrupt hpt366.
50 * Mike Waychison <crlf@sun.com>
51 *
52 * Added support for 372N clocking and clock switching. The 372N needs
53 * different clocks on read/write. This requires overloading rw_disk and
54 * other deeply crazy things. Thanks to <http://www.hoerstreich.de> for
55 * keeping me sane.
56 * Alan Cox <alan@redhat.com>
57 *
Sergei Shtylyov836c0062006-12-13 00:35:47 -080058 * - fix the clock turnaround code: it was writing to the wrong ports when
59 * called for the secondary channel, caching the current clock mode per-
60 * channel caused the cached register value to get out of sync with the
61 * actual one, the channels weren't serialized, the turnaround shouldn't
62 * be done on 66 MHz PCI bus
63 * - avoid calibrating PLL twice as the second time results in a wrong PCI
64 * frequency and thus in the wrong timings for the secondary channel
Sergei Shtylyove139b0b2007-02-07 18:17:37 +010065 * - disable UltraATA/133 for HPT372 and UltraATA/100 for HPT370 by default
66 * as the ATA clock being used does not allow for this speed anyway
Sergei Shtylyov836c0062006-12-13 00:35:47 -080067 * - add support for HPT302N and HPT371N clocking (the same as for HPT372N)
68 * - HPT371/N are single channel chips, so avoid touching the primary channel
69 * which exists only virtually (there's no pins for it)
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -080070 * - fix/remove bad/unused timing tables and use one set of tables for the whole
71 * HPT37x chip family; save space by introducing the separate transfer mode
72 * table in which the mode lookup is done
Sergei Shtylyov26c068d2006-12-13 00:35:52 -080073 * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives
74 * the wrong PCI frequency since DPLL has already been calibrated by BIOS
Sergei Shtylyov33b18a62006-12-13 00:35:50 -080075 * - fix the hotswap code: it caused RESET- to glitch when tristating the bus,
76 * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -080077 * - pass to init_chipset() handlers a copy of the IDE PCI device structure as
78 * they tamper with its fields
Sergei Shtylyove139b0b2007-02-07 18:17:37 +010079 * - optimize the rate masking/filtering and the drive list lookup code
Sergei Shtylyov836c0062006-12-13 00:35:47 -080080 * <source@mvista.com>
81 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 */
83
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085#include <linux/types.h>
86#include <linux/module.h>
87#include <linux/kernel.h>
88#include <linux/delay.h>
89#include <linux/timer.h>
90#include <linux/mm.h>
91#include <linux/ioport.h>
92#include <linux/blkdev.h>
93#include <linux/hdreg.h>
94
95#include <linux/interrupt.h>
96#include <linux/pci.h>
97#include <linux/init.h>
98#include <linux/ide.h>
99
100#include <asm/uaccess.h>
101#include <asm/io.h>
102#include <asm/irq.h>
103
104/* various tuning parameters */
105#define HPT_RESET_STATE_ENGINE
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800106#undef HPT_DELAY_INTERRUPT
107#define HPT_SERIALIZE_IO 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109static const char *quirk_drives[] = {
110 "QUANTUM FIREBALLlct08 08",
111 "QUANTUM FIREBALLP KA6.4",
112 "QUANTUM FIREBALLP LM20.4",
113 "QUANTUM FIREBALLP LM20.5",
114 NULL
115};
116
117static const char *bad_ata100_5[] = {
118 "IBM-DTLA-307075",
119 "IBM-DTLA-307060",
120 "IBM-DTLA-307045",
121 "IBM-DTLA-307030",
122 "IBM-DTLA-307020",
123 "IBM-DTLA-307015",
124 "IBM-DTLA-305040",
125 "IBM-DTLA-305030",
126 "IBM-DTLA-305020",
127 "IC35L010AVER07-0",
128 "IC35L020AVER07-0",
129 "IC35L030AVER07-0",
130 "IC35L040AVER07-0",
131 "IC35L060AVER07-0",
132 "WDC AC310200R",
133 NULL
134};
135
136static const char *bad_ata66_4[] = {
137 "IBM-DTLA-307075",
138 "IBM-DTLA-307060",
139 "IBM-DTLA-307045",
140 "IBM-DTLA-307030",
141 "IBM-DTLA-307020",
142 "IBM-DTLA-307015",
143 "IBM-DTLA-305040",
144 "IBM-DTLA-305030",
145 "IBM-DTLA-305020",
146 "IC35L010AVER07-0",
147 "IC35L020AVER07-0",
148 "IC35L030AVER07-0",
149 "IC35L040AVER07-0",
150 "IC35L060AVER07-0",
151 "WDC AC310200R",
152 NULL
153};
154
155static const char *bad_ata66_3[] = {
156 "WDC AC310200R",
157 NULL
158};
159
160static const char *bad_ata33[] = {
161 "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
162 "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
163 "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
164 "Maxtor 90510D4",
165 "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
166 "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
167 "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
168 NULL
169};
170
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800171static u8 xfer_speeds[] = {
172 XFER_UDMA_6,
173 XFER_UDMA_5,
174 XFER_UDMA_4,
175 XFER_UDMA_3,
176 XFER_UDMA_2,
177 XFER_UDMA_1,
178 XFER_UDMA_0,
179
180 XFER_MW_DMA_2,
181 XFER_MW_DMA_1,
182 XFER_MW_DMA_0,
183
184 XFER_PIO_4,
185 XFER_PIO_3,
186 XFER_PIO_2,
187 XFER_PIO_1,
188 XFER_PIO_0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189};
190
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800191/* Key for bus clock timings
192 * 36x 37x
193 * bits bits
194 * 0:3 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
195 * cycles = value + 1
196 * 4:7 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
197 * cycles = value + 1
198 * 8:11 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
199 * register access.
200 * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file
201 * register access.
202 * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer.
203 * - 21 CLK frequency: 0=ATA clock, 1=dual ATA clock.
204 * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and
205 * MW DMA xfer.
206 * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for
207 * task file register access.
208 * 28 28 UDMA enable.
209 * 29 29 DMA enable.
210 * 30 30 PIO MST enable. If set, the chip is in bus master mode during
211 * PIO xfer.
212 * 31 31 FIFO enable.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800215static u32 forty_base_hpt36x[] = {
216 /* XFER_UDMA_6 */ 0x900fd943,
217 /* XFER_UDMA_5 */ 0x900fd943,
218 /* XFER_UDMA_4 */ 0x900fd943,
219 /* XFER_UDMA_3 */ 0x900ad943,
220 /* XFER_UDMA_2 */ 0x900bd943,
221 /* XFER_UDMA_1 */ 0x9008d943,
222 /* XFER_UDMA_0 */ 0x9008d943,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800224 /* XFER_MW_DMA_2 */ 0xa008d943,
225 /* XFER_MW_DMA_1 */ 0xa010d955,
226 /* XFER_MW_DMA_0 */ 0xa010d9fc,
227
228 /* XFER_PIO_4 */ 0xc008d963,
229 /* XFER_PIO_3 */ 0xc010d974,
230 /* XFER_PIO_2 */ 0xc010d997,
231 /* XFER_PIO_1 */ 0xc010d9c7,
232 /* XFER_PIO_0 */ 0xc018d9d9
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233};
234
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800235static u32 thirty_three_base_hpt36x[] = {
236 /* XFER_UDMA_6 */ 0x90c9a731,
237 /* XFER_UDMA_5 */ 0x90c9a731,
238 /* XFER_UDMA_4 */ 0x90c9a731,
239 /* XFER_UDMA_3 */ 0x90cfa731,
240 /* XFER_UDMA_2 */ 0x90caa731,
241 /* XFER_UDMA_1 */ 0x90cba731,
242 /* XFER_UDMA_0 */ 0x90c8a731,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800244 /* XFER_MW_DMA_2 */ 0xa0c8a731,
245 /* XFER_MW_DMA_1 */ 0xa0c8a732, /* 0xa0c8a733 */
246 /* XFER_MW_DMA_0 */ 0xa0c8a797,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800248 /* XFER_PIO_4 */ 0xc0c8a731,
249 /* XFER_PIO_3 */ 0xc0c8a742,
250 /* XFER_PIO_2 */ 0xc0d0a753,
251 /* XFER_PIO_1 */ 0xc0d0a7a3, /* 0xc0d0a793 */
252 /* XFER_PIO_0 */ 0xc0d0a7aa /* 0xc0d0a7a7 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253};
254
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800255static u32 twenty_five_base_hpt36x[] = {
256 /* XFER_UDMA_6 */ 0x90c98521,
257 /* XFER_UDMA_5 */ 0x90c98521,
258 /* XFER_UDMA_4 */ 0x90c98521,
259 /* XFER_UDMA_3 */ 0x90cf8521,
260 /* XFER_UDMA_2 */ 0x90cf8521,
261 /* XFER_UDMA_1 */ 0x90cb8521,
262 /* XFER_UDMA_0 */ 0x90cb8521,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800264 /* XFER_MW_DMA_2 */ 0xa0ca8521,
265 /* XFER_MW_DMA_1 */ 0xa0ca8532,
266 /* XFER_MW_DMA_0 */ 0xa0ca8575,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800268 /* XFER_PIO_4 */ 0xc0ca8521,
269 /* XFER_PIO_3 */ 0xc0ca8532,
270 /* XFER_PIO_2 */ 0xc0ca8542,
271 /* XFER_PIO_1 */ 0xc0d08572,
272 /* XFER_PIO_0 */ 0xc0d08585
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273};
274
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800275static u32 thirty_three_base_hpt37x[] = {
276 /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */
277 /* XFER_UDMA_5 */ 0x12446231,
278 /* XFER_UDMA_4 */ 0x12446231,
279 /* XFER_UDMA_3 */ 0x126c6231,
280 /* XFER_UDMA_2 */ 0x12486231,
281 /* XFER_UDMA_1 */ 0x124c6233,
282 /* XFER_UDMA_0 */ 0x12506297,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800284 /* XFER_MW_DMA_2 */ 0x22406c31,
285 /* XFER_MW_DMA_1 */ 0x22406c33,
286 /* XFER_MW_DMA_0 */ 0x22406c97,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800288 /* XFER_PIO_4 */ 0x06414e31,
289 /* XFER_PIO_3 */ 0x06414e42,
290 /* XFER_PIO_2 */ 0x06414e53,
291 /* XFER_PIO_1 */ 0x06814e93,
292 /* XFER_PIO_0 */ 0x06814ea7
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293};
294
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800295static u32 fifty_base_hpt37x[] = {
296 /* XFER_UDMA_6 */ 0x12848242,
297 /* XFER_UDMA_5 */ 0x12848242,
298 /* XFER_UDMA_4 */ 0x12ac8242,
299 /* XFER_UDMA_3 */ 0x128c8242,
300 /* XFER_UDMA_2 */ 0x120c8242,
301 /* XFER_UDMA_1 */ 0x12148254,
302 /* XFER_UDMA_0 */ 0x121882ea,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800304 /* XFER_MW_DMA_2 */ 0x22808242,
305 /* XFER_MW_DMA_1 */ 0x22808254,
306 /* XFER_MW_DMA_0 */ 0x228082ea,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800308 /* XFER_PIO_4 */ 0x0a81f442,
309 /* XFER_PIO_3 */ 0x0a81f443,
310 /* XFER_PIO_2 */ 0x0a81f454,
311 /* XFER_PIO_1 */ 0x0ac1f465,
312 /* XFER_PIO_0 */ 0x0ac1f48a
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313};
314
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800315static u32 sixty_six_base_hpt37x[] = {
316 /* XFER_UDMA_6 */ 0x1c869c62,
317 /* XFER_UDMA_5 */ 0x1cae9c62, /* 0x1c8a9c62 */
318 /* XFER_UDMA_4 */ 0x1c8a9c62,
319 /* XFER_UDMA_3 */ 0x1c8e9c62,
320 /* XFER_UDMA_2 */ 0x1c929c62,
321 /* XFER_UDMA_1 */ 0x1c9a9c62,
322 /* XFER_UDMA_0 */ 0x1c829c62,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800324 /* XFER_MW_DMA_2 */ 0x2c829c62,
325 /* XFER_MW_DMA_1 */ 0x2c829c66,
326 /* XFER_MW_DMA_0 */ 0x2c829d2e,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800328 /* XFER_PIO_4 */ 0x0c829c62,
329 /* XFER_PIO_3 */ 0x0c829c84,
330 /* XFER_PIO_2 */ 0x0c829ca6,
331 /* XFER_PIO_1 */ 0x0d029d26,
332 /* XFER_PIO_0 */ 0x0d029d5e
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333};
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335#define HPT366_DEBUG_DRIVE_INFO 0
336#define HPT374_ALLOW_ATA133_6 0
337#define HPT371_ALLOW_ATA133_6 0
338#define HPT302_ALLOW_ATA133_6 0
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800339#define HPT372_ALLOW_ATA133_6 0
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100340#define HPT370_ALLOW_ATA100_5 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341#define HPT366_ALLOW_ATA66_4 1
342#define HPT366_ALLOW_ATA66_3 1
343#define HPT366_MAX_DEVS 8
344
345#define F_LOW_PCI_33 0x23
346#define F_LOW_PCI_40 0x29
347#define F_LOW_PCI_50 0x2d
348#define F_LOW_PCI_66 0x42
349
Alan Coxb39b01f2005-06-27 15:24:27 -0700350/*
351 * Hold all the highpoint quirks and revision information in one
352 * place.
353 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
Alan Coxb39b01f2005-06-27 15:24:27 -0700355struct hpt_info
356{
357 u8 max_mode; /* Speeds allowed */
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100358 u8 revision; /* Chipset revision */
359 u8 flags; /* Chipset properties */
Alan Coxb39b01f2005-06-27 15:24:27 -0700360#define PLL_MODE 1
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800361#define IS_3xxN 2
362#define PCI_66MHZ 4
Alan Coxb39b01f2005-06-27 15:24:27 -0700363 /* Speed table */
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800364 u32 *speed;
Alan Coxb39b01f2005-06-27 15:24:27 -0700365};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Alan Coxb39b01f2005-06-27 15:24:27 -0700367/*
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100368 * This wants fixing so that we do everything not by revision
Alan Coxb39b01f2005-06-27 15:24:27 -0700369 * (which breaks on the newest chips) but by creating an
370 * enumeration of chip variants and using that
371 */
372
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100373static __devinit u8 hpt_revision(struct pci_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374{
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100375 u8 rev = 0;
376
377 pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 switch(dev->device) {
380 /* Remap new 372N onto 372 */
381 case PCI_DEVICE_ID_TTI_HPT372N:
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100382 rev = PCI_DEVICE_ID_TTI_HPT372; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 case PCI_DEVICE_ID_TTI_HPT374:
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100384 rev = PCI_DEVICE_ID_TTI_HPT374; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 case PCI_DEVICE_ID_TTI_HPT371:
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100386 rev = PCI_DEVICE_ID_TTI_HPT371; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 case PCI_DEVICE_ID_TTI_HPT302:
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100388 rev = PCI_DEVICE_ID_TTI_HPT302; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 case PCI_DEVICE_ID_TTI_HPT372:
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100390 rev = PCI_DEVICE_ID_TTI_HPT372; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 default:
392 break;
393 }
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100394 return rev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395}
396
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100397static int check_in_drive_list(ide_drive_t *drive, const char **list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398{
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100399 struct hd_driveid *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100401 while (*list)
402 if (!strcmp(*list++,id->model))
403 return 1;
404 return 0;
405}
Alan Coxb39b01f2005-06-27 15:24:27 -0700406
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100407static u8 hpt3xx_ratemask(ide_drive_t *drive)
408{
409 struct hpt_info *info = ide_get_hwifdata(HWIF(drive));
410 u8 mode = info->max_mode;
411
Alan Coxb39b01f2005-06-27 15:24:27 -0700412 if (!eighty_ninty_three(drive) && mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 mode = min(mode, (u8)1);
414 return mode;
415}
416
417/*
418 * Note for the future; the SATA hpt37x we must set
419 * either PIO or UDMA modes 0,4,5
420 */
421
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100422static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100424 struct hpt_info *info = ide_get_hwifdata(HWIF(drive));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 u8 mode = hpt3xx_ratemask(drive);
426
427 if (drive->media != ide_disk)
428 return min(speed, (u8)XFER_PIO_4);
429
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100430 switch (mode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 case 0x04:
432 speed = min(speed, (u8)XFER_UDMA_6);
433 break;
434 case 0x03:
435 speed = min(speed, (u8)XFER_UDMA_5);
Alan Coxb39b01f2005-06-27 15:24:27 -0700436 if (info->revision >= 5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 break;
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100438 if (!check_in_drive_list(drive, bad_ata100_5))
439 goto check_bad_ata33;
440 /* fall thru */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 case 0x02:
442 speed = min(speed, (u8)XFER_UDMA_4);
443 /*
444 * CHECK ME, Does this need to be set to 5 ??
445 */
Alan Coxb39b01f2005-06-27 15:24:27 -0700446 if (info->revision >= 3)
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100447 goto check_bad_ata33;
448 if (HPT366_ALLOW_ATA66_4 &&
449 !check_in_drive_list(drive, bad_ata66_4))
450 goto check_bad_ata33;
451
452 speed = min(speed, (u8)XFER_UDMA_3);
453 if (HPT366_ALLOW_ATA66_3 &&
454 !check_in_drive_list(drive, bad_ata66_3))
455 goto check_bad_ata33;
456 /* fall thru */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 case 0x01:
458 speed = min(speed, (u8)XFER_UDMA_2);
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100459
460 check_bad_ata33:
461 if (info->revision >= 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 break;
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100463 if (!check_in_drive_list(drive, bad_ata33))
464 break;
465 /* fall thru */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 case 0x00:
467 default:
468 speed = min(speed, (u8)XFER_MW_DMA_2);
469 break;
470 }
471 return speed;
472}
473
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800474static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475{
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800476 int i;
477
478 /*
479 * Lookup the transfer mode table to get the index into
480 * the timing table.
481 *
482 * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.
483 */
484 for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
485 if (xfer_speeds[i] == speed)
486 break;
487 return chipset_table[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488}
489
490static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
491{
Alan Coxb39b01f2005-06-27 15:24:27 -0700492 ide_hwif_t *hwif = drive->hwif;
493 struct pci_dev *dev = hwif->pci_dev;
494 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 u8 speed = hpt3xx_ratefilter(drive, xferspeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
Alan Coxb39b01f2005-06-27 15:24:27 -0700497 u8 regfast = (hwif->channel) ? 0x55 : 0x51;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 u8 drive_fast = 0;
499 u32 reg1 = 0, reg2 = 0;
500
501 /*
502 * Disable the "fast interrupt" prediction.
503 */
504 pci_read_config_byte(dev, regfast, &drive_fast);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 if (drive_fast & 0x80)
506 pci_write_config_byte(dev, regfast, drive_fast & ~0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
Alan Coxb39b01f2005-06-27 15:24:27 -0700508 reg2 = pci_bus_clock_list(speed, info->speed);
509
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 /*
511 * Disable on-chip PIO FIFO/buffer
512 * (to avoid problems handling I/O errors later)
513 */
514 pci_read_config_dword(dev, regtime, &reg1);
515 if (speed >= XFER_MW_DMA_0) {
516 reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000);
517 } else {
518 reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000);
519 }
520 reg2 &= ~0x80000000;
521
522 pci_write_config_dword(dev, regtime, reg2);
523
524 return ide_config_drive_speed(drive, speed);
525}
526
527static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
528{
Alan Coxb39b01f2005-06-27 15:24:27 -0700529 ide_hwif_t *hwif = drive->hwif;
530 struct pci_dev *dev = hwif->pci_dev;
531 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 u8 speed = hpt3xx_ratefilter(drive, xferspeed);
Alan Coxb39b01f2005-06-27 15:24:27 -0700533 u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 u8 drive_pci = 0x40 + (drive->dn * 4);
535 u8 new_fast = 0, drive_fast = 0;
536 u32 list_conf = 0, drive_conf = 0;
537 u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
538
539 /*
540 * Disable the "fast interrupt" prediction.
541 * don't holdoff on interrupts. (== 0x01 despite what the docs say)
542 */
543 pci_read_config_byte(dev, regfast, &drive_fast);
544 new_fast = drive_fast;
545 if (new_fast & 0x02)
546 new_fast &= ~0x02;
547
548#ifdef HPT_DELAY_INTERRUPT
549 if (new_fast & 0x01)
550 new_fast &= ~0x01;
551#else
552 if ((new_fast & 0x01) == 0)
553 new_fast |= 0x01;
554#endif
555 if (new_fast != drive_fast)
556 pci_write_config_byte(dev, regfast, new_fast);
557
Alan Coxb39b01f2005-06-27 15:24:27 -0700558 list_conf = pci_bus_clock_list(speed, info->speed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
560 pci_read_config_dword(dev, drive_pci, &drive_conf);
561 list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
562
Alan Coxb39b01f2005-06-27 15:24:27 -0700563 if (speed < XFER_MW_DMA_0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 pci_write_config_dword(dev, drive_pci, list_conf);
566
567 return ide_config_drive_speed(drive, speed);
568}
569
570static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
571{
Alan Coxb39b01f2005-06-27 15:24:27 -0700572 ide_hwif_t *hwif = drive->hwif;
573 struct pci_dev *dev = hwif->pci_dev;
574 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 u8 speed = hpt3xx_ratefilter(drive, xferspeed);
Alan Coxb39b01f2005-06-27 15:24:27 -0700576 u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4);
578 u32 list_conf = 0, drive_conf = 0;
579 u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
580
581 /*
582 * Disable the "fast interrupt" prediction.
583 * don't holdoff on interrupts. (== 0x01 despite what the docs say)
584 */
585 pci_read_config_byte(dev, regfast, &drive_fast);
586 drive_fast &= ~0x07;
587 pci_write_config_byte(dev, regfast, drive_fast);
Alan Coxb39b01f2005-06-27 15:24:27 -0700588
589 list_conf = pci_bus_clock_list(speed, info->speed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 pci_read_config_dword(dev, drive_pci, &drive_conf);
591 list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
592 if (speed < XFER_MW_DMA_0)
593 list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
594 pci_write_config_dword(dev, drive_pci, list_conf);
595
596 return ide_config_drive_speed(drive, speed);
597}
598
599static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed)
600{
Alan Coxb39b01f2005-06-27 15:24:27 -0700601 ide_hwif_t *hwif = drive->hwif;
602 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
Alan Coxb39b01f2005-06-27 15:24:27 -0700604 if (info->revision >= 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 return hpt372_tune_chipset(drive, speed); /* not a typo */
Alan Coxb39b01f2005-06-27 15:24:27 -0700606 else if (info->revision >= 5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 return hpt372_tune_chipset(drive, speed);
Alan Coxb39b01f2005-06-27 15:24:27 -0700608 else if (info->revision >= 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 return hpt370_tune_chipset(drive, speed);
610 else /* hpt368: hpt_minimum_revision(dev, 2) */
611 return hpt36x_tune_chipset(drive, speed);
612}
613
614static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio)
615{
616 pio = ide_get_best_pio_mode(drive, 255, pio, NULL);
617 (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio));
618}
619
620/*
621 * This allows the configuration of ide_pci chipset registers
622 * for cards that learn about the drive's UDMA, DMA, PIO capabilities
623 * after the drive is reported by the OS. Initially for designed for
624 * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc.
625 *
626 * check_in_drive_lists(drive, bad_ata66_4)
627 * check_in_drive_lists(drive, bad_ata66_3)
628 * check_in_drive_lists(drive, bad_ata33)
629 *
630 */
631static int config_chipset_for_dma (ide_drive_t *drive)
632{
633 u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive));
Alan Coxb39b01f2005-06-27 15:24:27 -0700634 ide_hwif_t *hwif = drive->hwif;
635 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
Alan Coxb39b01f2005-06-27 15:24:27 -0700637 if (!speed)
638 return 0;
639
640 /* If we don't have any timings we can't do a lot */
641 if (info->speed == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 return 0;
643
644 (void) hpt3xx_tune_chipset(drive, speed);
645 return ide_dma_enable(drive);
646}
647
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100648static int hpt3xx_quirkproc(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649{
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100650 struct hd_driveid *id = drive->id;
651 const char **list = quirk_drives;
652
653 while (*list)
654 if (strstr(id->model, *list++))
655 return 1;
656 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657}
658
659static void hpt3xx_intrproc (ide_drive_t *drive)
660{
Alan Coxb39b01f2005-06-27 15:24:27 -0700661 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
663 if (drive->quirk_list)
664 return;
665 /* drives in the quirk_list may not like intr setups/cleanups */
666 hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);
667}
668
669static void hpt3xx_maskproc (ide_drive_t *drive, int mask)
670{
Alan Coxb39b01f2005-06-27 15:24:27 -0700671 ide_hwif_t *hwif = drive->hwif;
672 struct hpt_info *info = ide_get_hwifdata(hwif);
673 struct pci_dev *dev = hwif->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
675 if (drive->quirk_list) {
Alan Coxb39b01f2005-06-27 15:24:27 -0700676 if (info->revision >= 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 u8 reg5a = 0;
678 pci_read_config_byte(dev, 0x5a, &reg5a);
679 if (((reg5a & 0x10) >> 4) != mask)
680 pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
681 } else {
682 if (mask) {
Alan Coxb39b01f2005-06-27 15:24:27 -0700683 disable_irq(hwif->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 } else {
Alan Coxb39b01f2005-06-27 15:24:27 -0700685 enable_irq(hwif->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 }
687 }
688 } else {
689 if (IDE_CONTROL_REG)
Alan Coxb39b01f2005-06-27 15:24:27 -0700690 hwif->OUTB(mask ? (drive->ctl | 2) :
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 (drive->ctl & ~2),
692 IDE_CONTROL_REG);
693 }
694}
695
696static int hpt366_config_drive_xfer_rate (ide_drive_t *drive)
697{
Alan Coxb39b01f2005-06-27 15:24:27 -0700698 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 struct hd_driveid *id = drive->id;
700
701 drive->init_speed = 0;
702
Alan Coxb39b01f2005-06-27 15:24:27 -0700703 if ((id->capability & 1) && drive->autodma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
705 if (ide_use_dma(drive)) {
706 if (config_chipset_for_dma(drive))
707 return hwif->ide_dma_on(drive);
708 }
709
710 goto fast_ata_pio;
711
712 } else if ((id->capability & 8) || (id->field_valid & 2)) {
713fast_ata_pio:
714 hpt3xx_tune_drive(drive, 5);
715 return hwif->ide_dma_off_quietly(drive);
716 }
717 /* IORDY not supported */
718 return 0;
719}
720
721/*
722 * This is specific to the HPT366 UDMA bios chipset
723 * by HighPoint|Triones Technologies, Inc.
724 */
725static int hpt366_ide_dma_lostirq (ide_drive_t *drive)
726{
727 struct pci_dev *dev = HWIF(drive)->pci_dev;
728 u8 reg50h = 0, reg52h = 0, reg5ah = 0;
729
730 pci_read_config_byte(dev, 0x50, &reg50h);
731 pci_read_config_byte(dev, 0x52, &reg52h);
732 pci_read_config_byte(dev, 0x5a, &reg5ah);
733 printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",
734 drive->name, __FUNCTION__, reg50h, reg52h, reg5ah);
735 if (reg5ah & 0x10)
736 pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 return __ide_dma_lostirq(drive);
738}
739
740static void hpt370_clear_engine (ide_drive_t *drive)
741{
742 u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50;
743 pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37);
744 udelay(10);
745}
746
747static void hpt370_ide_dma_start(ide_drive_t *drive)
748{
749#ifdef HPT_RESET_STATE_ENGINE
750 hpt370_clear_engine(drive);
751#endif
752 ide_dma_start(drive);
753}
754
755static int hpt370_ide_dma_end (ide_drive_t *drive)
756{
757 ide_hwif_t *hwif = HWIF(drive);
758 u8 dma_stat = hwif->INB(hwif->dma_status);
759
760 if (dma_stat & 0x01) {
761 /* wait a little */
762 udelay(20);
763 dma_stat = hwif->INB(hwif->dma_status);
764 }
765 if ((dma_stat & 0x01) != 0)
766 /* fallthrough */
767 (void) HWIF(drive)->ide_dma_timeout(drive);
768
769 return __ide_dma_end(drive);
770}
771
772static void hpt370_lostirq_timeout (ide_drive_t *drive)
773{
774 ide_hwif_t *hwif = HWIF(drive);
775 u8 bfifo = 0, reginfo = hwif->channel ? 0x56 : 0x52;
776 u8 dma_stat = 0, dma_cmd = 0;
777
778 pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo);
Alan Coxb39b01f2005-06-27 15:24:27 -0700779 printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 hpt370_clear_engine(drive);
781 /* get dma command mode */
782 dma_cmd = hwif->INB(hwif->dma_command);
783 /* stop dma */
784 hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command);
785 dma_stat = hwif->INB(hwif->dma_status);
786 /* clear errors */
787 hwif->OUTB(dma_stat | 0x6, hwif->dma_status);
788}
789
790static int hpt370_ide_dma_timeout (ide_drive_t *drive)
791{
792 hpt370_lostirq_timeout(drive);
793 hpt370_clear_engine(drive);
794 return __ide_dma_timeout(drive);
795}
796
797static int hpt370_ide_dma_lostirq (ide_drive_t *drive)
798{
799 hpt370_lostirq_timeout(drive);
800 hpt370_clear_engine(drive);
801 return __ide_dma_lostirq(drive);
802}
803
804/* returns 1 if DMA IRQ issued, 0 otherwise */
805static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
806{
807 ide_hwif_t *hwif = HWIF(drive);
808 u16 bfifo = 0;
809 u8 reginfo = hwif->channel ? 0x56 : 0x52;
810 u8 dma_stat;
811
812 pci_read_config_word(hwif->pci_dev, reginfo, &bfifo);
813 if (bfifo & 0x1FF) {
814// printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
815 return 0;
816 }
817
818 dma_stat = hwif->INB(hwif->dma_status);
819 /* return 1 if INTR asserted */
820 if ((dma_stat & 4) == 4)
821 return 1;
822
823 if (!drive->waiting_for_dma)
824 printk(KERN_WARNING "%s: (%s) called while not waiting\n",
825 drive->name, __FUNCTION__);
826 return 0;
827}
828
829static int hpt374_ide_dma_end (ide_drive_t *drive)
830{
831 struct pci_dev *dev = HWIF(drive)->pci_dev;
832 ide_hwif_t *hwif = HWIF(drive);
833 u8 msc_stat = 0, mscreg = hwif->channel ? 0x54 : 0x50;
834 u8 bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01;
835
836 pci_read_config_byte(dev, 0x6a, &bwsr_stat);
837 pci_read_config_byte(dev, mscreg, &msc_stat);
838 if ((bwsr_stat & bwsr_mask) == bwsr_mask)
839 pci_write_config_byte(dev, mscreg, msc_stat|0x30);
840 return __ide_dma_end(drive);
841}
842
843/**
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800844 * hpt3xxn_set_clock - perform clock switching dance
845 * @hwif: hwif to switch
846 * @mode: clocking mode (0x21 for write, 0x23 otherwise)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 *
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800848 * Switch the DPLL clock on the HPT3xxN devices. This is a right mess.
849 * NOTE: avoid touching the disabled primary channel on HPT371N -- it
850 * doesn't physically exist anyway...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800852
853static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854{
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800855 u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b);
856
857 if ((scr2 & 0x7f) == mode)
858 return;
859
860 /* MISC. control register 1 has the channel enable bit... */
861 mcr1 = hwif->INB(hwif->dma_master + 0x70);
862
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 /* Tristate the bus */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800864 if (mcr1 & 0x04)
865 hwif->OUTB(0x80, hwif->dma_master + 0x73);
866 hwif->OUTB(0x80, hwif->dma_master + 0x77);
867
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 /* Switch clock and reset channels */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800869 hwif->OUTB(mode, hwif->dma_master + 0x7b);
870 hwif->OUTB(0xc0, hwif->dma_master + 0x79);
871
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 /* Reset state machines */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800873 if (mcr1 & 0x04)
874 hwif->OUTB(0x37, hwif->dma_master + 0x70);
875 hwif->OUTB(0x37, hwif->dma_master + 0x74);
876
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 /* Complete reset */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800878 hwif->OUTB(0x00, hwif->dma_master + 0x79);
879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 /* Reconnect channels to bus */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800881 if (mcr1 & 0x04)
882 hwif->OUTB(0x00, hwif->dma_master + 0x73);
883 hwif->OUTB(0x00, hwif->dma_master + 0x77);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884}
885
886/**
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800887 * hpt3xxn_rw_disk - prepare for I/O
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 * @drive: drive for command
889 * @rq: block request structure
890 *
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800891 * This is called when a disk I/O is issued to HPT3xxN.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 * We need it because of the clock switching.
893 */
894
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800895static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896{
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800897 ide_hwif_t *hwif = HWIF(drive);
898 u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800900 hpt3xxn_set_clock(hwif, wantclock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901}
902
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903/*
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800904 * Set/get power state for a drive.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 *
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800906 * When we turn the power back on, we need to re-initialize things.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 */
908#define TRISTATE_BIT 0x8000
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800909
910static int hpt3xx_busproc(ide_drive_t *drive, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911{
Alan Coxb39b01f2005-06-27 15:24:27 -0700912 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 struct pci_dev *dev = hwif->pci_dev;
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800914 u8 tristate, resetmask, bus_reg = 0;
915 u16 tri_reg = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916
917 hwif->bus_state = state;
918
919 if (hwif->channel) {
920 /* secondary channel */
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800921 tristate = 0x56;
922 resetmask = 0x80;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 } else {
924 /* primary channel */
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800925 tristate = 0x52;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 resetmask = 0x40;
927 }
928
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800929 /* Grab the status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 pci_read_config_word(dev, tristate, &tri_reg);
931 pci_read_config_byte(dev, 0x59, &bus_reg);
932
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800933 /*
934 * Set the state. We don't set it if we don't need to do so.
935 * Make sure that the drive knows that it has failed if it's off.
936 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 switch (state) {
938 case BUSSTATE_ON:
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800939 if (!(bus_reg & resetmask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 return 0;
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800941 hwif->drives[0].failures = hwif->drives[1].failures = 0;
942
943 pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask);
944 pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT);
945 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 case BUSSTATE_OFF:
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800947 if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 return 0;
949 tri_reg &= ~TRISTATE_BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 break;
951 case BUSSTATE_TRISTATE:
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800952 if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return 0;
954 tri_reg |= TRISTATE_BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 break;
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800956 default:
957 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800960 hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
961 hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
962
963 pci_write_config_word(dev, tristate, tri_reg);
964 pci_write_config_byte(dev, 0x59, bus_reg | resetmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 return 0;
966}
967
Alan Coxb39b01f2005-06-27 15:24:27 -0700968static void __devinit hpt366_clocking(ide_hwif_t *hwif)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969{
Alan Coxb39b01f2005-06-27 15:24:27 -0700970 u32 reg1 = 0;
971 struct hpt_info *info = ide_get_hwifdata(hwif);
972
973 pci_read_config_dword(hwif->pci_dev, 0x40, &reg1);
974
975 /* detect bus speed by looking at control reg timing: */
976 switch((reg1 >> 8) & 7) {
977 case 5:
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800978 info->speed = forty_base_hpt36x;
Alan Coxb39b01f2005-06-27 15:24:27 -0700979 break;
980 case 9:
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800981 info->speed = twenty_five_base_hpt36x;
Alan Coxb39b01f2005-06-27 15:24:27 -0700982 break;
983 case 7:
984 default:
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800985 info->speed = thirty_three_base_hpt36x;
Alan Coxb39b01f2005-06-27 15:24:27 -0700986 break;
987 }
988}
989
990static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
991{
992 struct hpt_info *info = ide_get_hwifdata(hwif);
993 struct pci_dev *dev = hwif->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 int adjust, i;
Sergei Shtylyov26c068d2006-12-13 00:35:52 -0800995 u16 freq = 0;
996 u32 pll, temp = 0;
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800997 u8 reg5bh = 0, mcr1 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 /*
1000 * default to pci clock. make sure MA15/16 are set to output
Alan Coxb39b01f2005-06-27 15:24:27 -07001001 * to prevent drives having problems with 40-pin cables. Needed
1002 * for some drives such as IBM-DTLA which will not enter ready
1003 * state on reset when PDIAG is a input.
1004 *
1005 * ToDo: should we set 0x21 when using PLL mode ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 */
1007 pci_write_config_byte(dev, 0x5b, 0x23);
1008
1009 /*
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001010 * We'll have to read f_CNT value in order to determine
1011 * the PCI clock frequency according to the following ratio:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 *
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001013 * f_CNT = Fpci * 192 / Fdpll
1014 *
1015 * First try reading the register in which the HighPoint BIOS
1016 * saves f_CNT value before reprogramming the DPLL from its
1017 * default setting (which differs for the various chips).
Sergei Shtylyovf13c15262006-12-13 00:35:53 -08001018 * NOTE: This register is only accessible via I/O space.
1019 *
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001020 * In case the signature check fails, we'll have to resort to
1021 * reading the f_CNT register itself in hopes that nobody has
1022 * touched the DPLL yet...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 */
Sergei Shtylyovf13c15262006-12-13 00:35:53 -08001024 temp = inl(pci_resource_start(dev, 4) + 0x90);
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001025 if ((temp & 0xFFFFF000) != 0xABCDE000) {
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001026 printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n");
1027
1028 /* Calculate the average value of f_CNT */
1029 for (temp = i = 0; i < 128; i++) {
1030 pci_read_config_word(dev, 0x78, &freq);
1031 temp += freq & 0x1ff;
1032 mdelay(1);
1033 }
1034 freq = temp / 128;
1035 } else
1036 freq = temp & 0x1ff;
1037
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 /*
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001039 * HPT3xxN chips use different PCI clock information.
1040 * Currently we always set up the PLL for them.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 */
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001042
1043 if (info->flags & IS_3xxN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 if(freq < 0x55)
1045 pll = F_LOW_PCI_33;
1046 else if(freq < 0x70)
1047 pll = F_LOW_PCI_40;
1048 else if(freq < 0x7F)
1049 pll = F_LOW_PCI_50;
1050 else
1051 pll = F_LOW_PCI_66;
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001052
1053 printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 }
1055 else
1056 {
1057 if(freq < 0x9C)
1058 pll = F_LOW_PCI_33;
1059 else if(freq < 0xb0)
1060 pll = F_LOW_PCI_40;
1061 else if(freq <0xc8)
1062 pll = F_LOW_PCI_50;
1063 else
1064 pll = F_LOW_PCI_66;
1065
1066 if (pll == F_LOW_PCI_33) {
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001067 info->speed = thirty_three_base_hpt37x;
Alan Coxb39b01f2005-06-27 15:24:27 -07001068 printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 } else if (pll == F_LOW_PCI_40) {
1070 /* Unsupported */
1071 } else if (pll == F_LOW_PCI_50) {
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001072 info->speed = fifty_base_hpt37x;
Alan Coxb39b01f2005-06-27 15:24:27 -07001073 printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 } else {
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001075 info->speed = sixty_six_base_hpt37x;
1076 printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 }
1078 }
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001079
1080 if (pll == F_LOW_PCI_66)
1081 info->flags |= PCI_66MHZ;
1082
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 /*
1084 * only try the pll if we don't have a table for the clock
1085 * speed that we're running at. NOTE: the internal PLL will
1086 * result in slow reads when using a 33MHz PCI clock. we also
1087 * don't like to use the PLL because it will cause glitches
1088 * on PRST/SRST when the HPT state engine gets reset.
Alan Coxb39b01f2005-06-27 15:24:27 -07001089 *
1090 * ToDo: Use 66MHz PLL when ATA133 devices are present on a
1091 * 372 device so we can get ATA133 support
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 */
Alan Coxb39b01f2005-06-27 15:24:27 -07001093 if (info->speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 goto init_hpt37X_done;
Alan Coxb39b01f2005-06-27 15:24:27 -07001095
1096 info->flags |= PLL_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
1098 /*
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001099 * Adjust the PLL based upon the PCI clock, enable it, and
1100 * wait for stabilization...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 */
1102 adjust = 0;
1103 freq = (pll < F_LOW_PCI_50) ? 2 : 4;
1104 while (adjust++ < 6) {
1105 pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 |
1106 pll | 0x100);
1107
1108 /* wait for clock stabilization */
1109 for (i = 0; i < 0x50000; i++) {
1110 pci_read_config_byte(dev, 0x5b, &reg5bh);
1111 if (reg5bh & 0x80) {
1112 /* spin looking for the clock to destabilize */
1113 for (i = 0; i < 0x1000; ++i) {
1114 pci_read_config_byte(dev, 0x5b,
1115 &reg5bh);
1116 if ((reg5bh & 0x80) == 0)
1117 goto pll_recal;
1118 }
1119 pci_read_config_dword(dev, 0x5c, &pll);
1120 pci_write_config_dword(dev, 0x5c,
1121 pll & ~0x100);
1122 pci_write_config_byte(dev, 0x5b, 0x21);
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001123
1124 info->speed = fifty_base_hpt37x;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 printk("HPT37X: using 50MHz internal PLL\n");
1126 goto init_hpt37X_done;
1127 }
1128 }
1129pll_recal:
1130 if (adjust & 1)
1131 pll -= (adjust >> 1);
1132 else
1133 pll += (adjust >> 1);
1134 }
1135
1136init_hpt37X_done:
Alan Coxb39b01f2005-06-27 15:24:27 -07001137 if (!info->speed)
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001138 printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n",
1139 (info->flags & IS_3xxN) ? "N" : "", pll, freq);
1140 /*
1141 * Reset the state engines.
1142 * NOTE: avoid accidentally enabling the primary channel on HPT371N.
1143 */
1144 pci_read_config_byte(dev, 0x50, &mcr1);
1145 if (mcr1 & 0x04)
1146 pci_write_config_byte(dev, 0x50, 0x37);
1147 pci_write_config_byte(dev, 0x54, 0x37);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 udelay(100);
Alan Coxb39b01f2005-06-27 15:24:27 -07001149}
1150
1151static int __devinit init_hpt37x(struct pci_dev *dev)
1152{
1153 u8 reg5ah;
1154
1155 pci_read_config_byte(dev, 0x5a, &reg5ah);
1156 /* interrupt force enable */
1157 pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 return 0;
1159}
1160
1161static int __devinit init_hpt366(struct pci_dev *dev)
1162{
1163 u32 reg1 = 0;
1164 u8 drive_fast = 0;
1165
1166 /*
1167 * Disable the "fast interrupt" prediction.
1168 */
1169 pci_read_config_byte(dev, 0x51, &drive_fast);
1170 if (drive_fast & 0x80)
1171 pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
1172 pci_read_config_dword(dev, 0x40, &reg1);
1173
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 return 0;
1175}
1176
1177static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
1178{
1179 int ret = 0;
Linus Torvalds9ec4ff42005-09-11 09:22:50 -07001180
1181 /*
1182 * FIXME: Not portable. Also, why do we enable the ROM in the first place?
1183 * We don't seem to be using it.
1184 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 if (dev->resource[PCI_ROM_RESOURCE].start)
Linus Torvalds9ec4ff42005-09-11 09:22:50 -07001186 pci_write_config_dword(dev, PCI_ROM_ADDRESS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
1188
Alan Coxb39b01f2005-06-27 15:24:27 -07001189 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
1190 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
1191 pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
1192 pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
Alan Coxb39b01f2005-06-27 15:24:27 -07001194 if (hpt_revision(dev) >= 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 ret = init_hpt37x(dev);
Alan Coxb39b01f2005-06-27 15:24:27 -07001196 else
1197 ret = init_hpt366(dev);
1198
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 if (ret)
1200 return ret;
1201
1202 return dev->irq;
1203}
1204
1205static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
1206{
1207 struct pci_dev *dev = hwif->pci_dev;
Alan Coxb39b01f2005-06-27 15:24:27 -07001208 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02;
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001210 int serialize = HPT_SERIALIZE_IO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 hwif->tuneproc = &hpt3xx_tune_drive;
1213 hwif->speedproc = &hpt3xx_tune_chipset;
1214 hwif->quirkproc = &hpt3xx_quirkproc;
1215 hwif->intrproc = &hpt3xx_intrproc;
1216 hwif->maskproc = &hpt3xx_maskproc;
1217
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001218 /*
1219 * HPT3xxN chips have some complications:
1220 *
1221 * - on 33 MHz PCI we must clock switch
1222 * - on 66 MHz PCI we must NOT use the PCI clock
1223 */
1224 if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) {
1225 /*
1226 * Clock is shared between the channels,
1227 * so we'll have to serialize them... :-(
1228 */
1229 serialize = 1;
1230 hwif->rw_disk = &hpt3xxn_rw_disk;
1231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
1233 /*
1234 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
1235 * address lines to access an external eeprom. To read valid
1236 * cable detect state the pins must be enabled as inputs.
1237 */
Alan Coxb39b01f2005-06-27 15:24:27 -07001238 if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 /*
1240 * HPT374 PCI function 1
1241 * - set bit 15 of reg 0x52 to enable TCBLID as input
1242 * - set bit 15 of reg 0x56 to enable FCBLID as input
1243 */
1244 u16 mcr3, mcr6;
1245 pci_read_config_word(dev, 0x52, &mcr3);
1246 pci_read_config_word(dev, 0x56, &mcr6);
1247 pci_write_config_word(dev, 0x52, mcr3 | 0x8000);
1248 pci_write_config_word(dev, 0x56, mcr6 | 0x8000);
1249 /* now read cable id register */
1250 pci_read_config_byte(dev, 0x5a, &ata66);
1251 pci_write_config_word(dev, 0x52, mcr3);
1252 pci_write_config_word(dev, 0x56, mcr6);
Alan Coxb39b01f2005-06-27 15:24:27 -07001253 } else if (info->revision >= 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 /*
1255 * HPT370/372 and 374 pcifn 0
1256 * - clear bit 0 of 0x5b to enable P/SCBLID as inputs
1257 */
1258 u8 scr2;
1259 pci_read_config_byte(dev, 0x5b, &scr2);
1260 pci_write_config_byte(dev, 0x5b, scr2 & ~1);
1261 /* now read cable id register */
1262 pci_read_config_byte(dev, 0x5a, &ata66);
1263 pci_write_config_byte(dev, 0x5b, scr2);
1264 } else {
1265 pci_read_config_byte(dev, 0x5a, &ata66);
1266 }
1267
1268#ifdef DEBUG
1269 printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n",
1270 ata66, (ata66 & regmask) ? "33" : "66",
1271 PCI_FUNC(hwif->pci_dev->devfn));
1272#endif /* DEBUG */
1273
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001274 /* Serialize access to this device */
1275 if (serialize && hwif->mate)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 hwif->serialized = hwif->mate->serialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Sergei Shtylyov33b18a62006-12-13 00:35:50 -08001278 /*
1279 * Set up ioctl for power status.
1280 * NOTE: power affects both drives on each channel.
1281 */
1282 hwif->busproc = &hpt3xx_busproc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
1284 if (!hwif->dma_base) {
1285 hwif->drives[0].autotune = 1;
1286 hwif->drives[1].autotune = 1;
1287 return;
1288 }
1289
1290 hwif->ultra_mask = 0x7f;
1291 hwif->mwdma_mask = 0x07;
1292
1293 if (!(hwif->udma_four))
1294 hwif->udma_four = ((ata66 & regmask) ? 0 : 1);
1295 hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
1296
Alan Coxb39b01f2005-06-27 15:24:27 -07001297 if (info->revision >= 8) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
1299 hwif->ide_dma_end = &hpt374_ide_dma_end;
Alan Coxb39b01f2005-06-27 15:24:27 -07001300 } else if (info->revision >= 5) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
1302 hwif->ide_dma_end = &hpt374_ide_dma_end;
Alan Coxb39b01f2005-06-27 15:24:27 -07001303 } else if (info->revision >= 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 hwif->dma_start = &hpt370_ide_dma_start;
1305 hwif->ide_dma_end = &hpt370_ide_dma_end;
1306 hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
1307 hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq;
Alan Coxb39b01f2005-06-27 15:24:27 -07001308 } else if (info->revision >= 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
1310 else
1311 hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
1312
1313 if (!noautodma)
1314 hwif->autodma = 1;
1315 hwif->drives[0].autodma = hwif->autodma;
1316 hwif->drives[1].autodma = hwif->autodma;
1317}
1318
1319static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
1320{
Alan Coxb39b01f2005-06-27 15:24:27 -07001321 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 u8 masterdma = 0, slavedma = 0;
1323 u8 dma_new = 0, dma_old = 0;
1324 u8 primary = hwif->channel ? 0x4b : 0x43;
1325 u8 secondary = hwif->channel ? 0x4f : 0x47;
1326 unsigned long flags;
1327
1328 if (!dmabase)
1329 return;
1330
Alan Coxb39b01f2005-06-27 15:24:27 -07001331 if(info->speed == NULL) {
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001332 printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 return;
1334 }
1335
1336 dma_old = hwif->INB(dmabase+2);
1337
1338 local_irq_save(flags);
1339
1340 dma_new = dma_old;
1341 pci_read_config_byte(hwif->pci_dev, primary, &masterdma);
1342 pci_read_config_byte(hwif->pci_dev, secondary, &slavedma);
1343
1344 if (masterdma & 0x30) dma_new |= 0x20;
1345 if (slavedma & 0x30) dma_new |= 0x40;
1346 if (dma_new != dma_old)
1347 hwif->OUTB(dma_new, dmabase+2);
1348
1349 local_irq_restore(flags);
1350
1351 ide_setup_dma(hwif, dmabase, 8);
1352}
1353
Alan Coxb39b01f2005-06-27 15:24:27 -07001354/*
1355 * We "borrow" this hook in order to set the data structures
1356 * up early enough before dma or init_hwif calls are made.
1357 */
1358
1359static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
1360{
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001361 struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
1362 struct pci_dev *dev = hwif->pci_dev;
1363 u16 did = dev->device;
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001364 u8 mode, rid = 0;
Alan Coxb39b01f2005-06-27 15:24:27 -07001365
1366 if(info == NULL) {
1367 printk(KERN_WARNING "hpt366: out of memory.\n");
1368 return;
1369 }
Alan Coxb39b01f2005-06-27 15:24:27 -07001370 ide_set_hwifdata(hwif, info);
1371
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001372 /* Avoid doing the same thing twice. */
1373 if (hwif->channel && hwif->mate) {
1374 memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info));
1375 return;
Alan Coxb39b01f2005-06-27 15:24:27 -07001376 }
1377
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001378 pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001379
1380 if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) ||
1381 ((did == PCI_DEVICE_ID_TTI_HPT372 ||
1382 did == PCI_DEVICE_ID_TTI_HPT302 ||
1383 did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) ||
1384 did == PCI_DEVICE_ID_TTI_HPT372N)
1385 info->flags |= IS_3xxN;
1386
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001387 rid = info->revision = hpt_revision(dev);
1388 if (rid >= 8) /* HPT374 */
1389 mode = HPT374_ALLOW_ATA133_6 ? 4 : 3;
1390 else if (rid >= 7) /* HPT371 and HPT371N */
1391 mode = HPT371_ALLOW_ATA133_6 ? 4 : 3;
1392 else if (rid >= 6) /* HPT302 and HPT302N */
1393 mode = HPT302_ALLOW_ATA133_6 ? 4 : 3;
1394 else if (rid >= 5) /* HPT372, HPT372A, and HPT372N */
1395 mode = HPT372_ALLOW_ATA133_6 ? 4 : 3;
1396 else if (rid >= 3) /* HPT370 and HPT370A */
1397 mode = HPT370_ALLOW_ATA100_5 ? 3 : 2;
1398 else /* HPT366 and HPT368 */
1399 mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1;
1400 info->max_mode = mode;
Alan Coxb39b01f2005-06-27 15:24:27 -07001401
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001402 if (rid >= 3)
Alan Coxb39b01f2005-06-27 15:24:27 -07001403 hpt37x_clocking(hwif);
1404 else
1405 hpt366_clocking(hwif);
1406}
1407
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d)
1409{
1410 struct pci_dev *findev = NULL;
1411
1412 if (PCI_FUNC(dev->devfn) & 1)
1413 return -ENODEV;
1414
1415 while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
1416 if ((findev->vendor == dev->vendor) &&
1417 (findev->device == dev->device) &&
1418 ((findev->devfn - dev->devfn) == 1) &&
1419 (PCI_FUNC(findev->devfn) & 1)) {
1420 if (findev->irq != dev->irq) {
1421 /* FIXME: we need a core pci_set_interrupt() */
1422 findev->irq = dev->irq;
1423 printk(KERN_WARNING "%s: pci-config space interrupt "
1424 "fixed.\n", d->name);
1425 }
1426 return ide_setup_pci_devices(dev, findev, d);
1427 }
1428 }
1429 return ide_setup_pci_device(dev, d);
1430}
1431
1432static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d)
1433{
1434 return ide_setup_pci_device(dev, d);
1435}
1436
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001437static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
1438{
1439 u8 mcr1 = 0;
1440
1441 /*
1442 * HPT371 chips physically have only one channel, the secondary one,
1443 * but the primary channel registers do exist! Go figure...
1444 * So, we manually disable the non-existing channel here
1445 * (if the BIOS hasn't done this already).
1446 */
1447 pci_read_config_byte(dev, 0x50, &mcr1);
1448 if (mcr1 & 0x04)
1449 pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04));
1450
1451 return ide_setup_pci_device(dev, d);
1452}
1453
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
1455{
1456 struct pci_dev *findev = NULL;
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001457 u8 rev = 0, pin1 = 0, pin2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 char *chipset_names[] = {"HPT366", "HPT366", "HPT368",
1459 "HPT370", "HPT370A", "HPT372",
1460 "HPT372N" };
1461
1462 if (PCI_FUNC(dev->devfn) & 1)
1463 return -ENODEV;
1464
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001465 pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 if(dev->device == PCI_DEVICE_ID_TTI_HPT372N)
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001468 rev = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001470 if(rev <= 6)
1471 d->name = chipset_names[rev];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001473 switch(rev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 case 6:
1475 case 5:
1476 case 4:
1477 case 3:
1478 goto init_single;
1479 default:
1480 break;
1481 }
1482
1483 d->channels = 1;
1484
1485 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
1486 while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
1487 if ((findev->vendor == dev->vendor) &&
1488 (findev->device == dev->device) &&
1489 ((findev->devfn - dev->devfn) == 1) &&
1490 (PCI_FUNC(findev->devfn) & 1)) {
1491 pci_read_config_byte(findev, PCI_INTERRUPT_PIN, &pin2);
1492 if ((pin1 != pin2) && (dev->irq == findev->irq)) {
1493 d->bootable = ON_BOARD;
1494 printk("%s: onboard version of chipset, "
1495 "pin1=%d pin2=%d\n", d->name,
1496 pin1, pin2);
1497 }
1498 return ide_setup_pci_devices(dev, findev, d);
1499 }
1500 }
1501init_single:
1502 return ide_setup_pci_device(dev, d);
1503}
1504
1505static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
1506 { /* 0 */
1507 .name = "HPT366",
1508 .init_setup = init_setup_hpt366,
1509 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001510 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 .init_hwif = init_hwif_hpt366,
1512 .init_dma = init_dma_hpt366,
1513 .channels = 2,
1514 .autodma = AUTODMA,
1515 .bootable = OFF_BOARD,
1516 .extra = 240
1517 },{ /* 1 */
1518 .name = "HPT372A",
1519 .init_setup = init_setup_hpt37x,
1520 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001521 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 .init_hwif = init_hwif_hpt366,
1523 .init_dma = init_dma_hpt366,
1524 .channels = 2,
1525 .autodma = AUTODMA,
1526 .bootable = OFF_BOARD,
1527 },{ /* 2 */
1528 .name = "HPT302",
1529 .init_setup = init_setup_hpt37x,
1530 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001531 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 .init_hwif = init_hwif_hpt366,
1533 .init_dma = init_dma_hpt366,
1534 .channels = 2,
1535 .autodma = AUTODMA,
1536 .bootable = OFF_BOARD,
1537 },{ /* 3 */
1538 .name = "HPT371",
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001539 .init_setup = init_setup_hpt371,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001541 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 .init_hwif = init_hwif_hpt366,
1543 .init_dma = init_dma_hpt366,
1544 .channels = 2,
1545 .autodma = AUTODMA,
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001546 .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 .bootable = OFF_BOARD,
1548 },{ /* 4 */
1549 .name = "HPT374",
1550 .init_setup = init_setup_hpt374,
1551 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001552 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 .init_hwif = init_hwif_hpt366,
1554 .init_dma = init_dma_hpt366,
1555 .channels = 2, /* 4 */
1556 .autodma = AUTODMA,
1557 .bootable = OFF_BOARD,
1558 },{ /* 5 */
1559 .name = "HPT372N",
1560 .init_setup = init_setup_hpt37x,
1561 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001562 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 .init_hwif = init_hwif_hpt366,
1564 .init_dma = init_dma_hpt366,
1565 .channels = 2, /* 4 */
1566 .autodma = AUTODMA,
1567 .bootable = OFF_BOARD,
1568 }
1569};
1570
1571/**
1572 * hpt366_init_one - called when an HPT366 is found
1573 * @dev: the hpt366 device
1574 * @id: the matching pci id
1575 *
1576 * Called when the PCI registration layer (or the IDE initialization)
1577 * finds a device matching our IDE device tables.
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -08001578 *
1579 * NOTE: since we'll have to modify some fields of the ide_pci_device_t
1580 * structure depending on the chip's revision, we'd better pass a local
1581 * copy down the call chain...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
1584{
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -08001585 ide_pci_device_t d = hpt366_chipsets[id->driver_data];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -08001587 return d.init_setup(dev, &d);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588}
1589
1590static struct pci_device_id hpt366_pci_tbl[] = {
1591 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
1592 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
1593 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
1594 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
1595 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
1596 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
1597 { 0, },
1598};
1599MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
1600
1601static struct pci_driver driver = {
1602 .name = "HPT366_IDE",
1603 .id_table = hpt366_pci_tbl,
1604 .probe = hpt366_init_one,
1605};
1606
Bartlomiej Zolnierkiewicz82ab1ee2007-01-27 13:46:56 +01001607static int __init hpt366_ide_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608{
1609 return ide_pci_register_driver(&driver);
1610}
1611
1612module_init(hpt366_ide_init);
1613
1614MODULE_AUTHOR("Andre Hedrick");
1615MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
1616MODULE_LICENSE("GPL");