blob: 9fd50801d3822e0cd8a2bdbfa186d48be4c76d95 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003
3 *
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
65 * - disable UltraATA/133 for HPT372 by default (50 MHz DPLL clock do not
66 * allow for this speed anyway)
67 * - 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 Shtylyov836c0062006-12-13 00:35:47 -080079 * <source@mvista.com>
80 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 */
82
83
Linus Torvalds1da177e2005-04-16 15:20:36 -070084#include <linux/types.h>
85#include <linux/module.h>
86#include <linux/kernel.h>
87#include <linux/delay.h>
88#include <linux/timer.h>
89#include <linux/mm.h>
90#include <linux/ioport.h>
91#include <linux/blkdev.h>
92#include <linux/hdreg.h>
93
94#include <linux/interrupt.h>
95#include <linux/pci.h>
96#include <linux/init.h>
97#include <linux/ide.h>
98
99#include <asm/uaccess.h>
100#include <asm/io.h>
101#include <asm/irq.h>
102
103/* various tuning parameters */
104#define HPT_RESET_STATE_ENGINE
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800105#undef HPT_DELAY_INTERRUPT
106#define HPT_SERIALIZE_IO 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107
108static const char *quirk_drives[] = {
109 "QUANTUM FIREBALLlct08 08",
110 "QUANTUM FIREBALLP KA6.4",
111 "QUANTUM FIREBALLP LM20.4",
112 "QUANTUM FIREBALLP LM20.5",
113 NULL
114};
115
116static const char *bad_ata100_5[] = {
117 "IBM-DTLA-307075",
118 "IBM-DTLA-307060",
119 "IBM-DTLA-307045",
120 "IBM-DTLA-307030",
121 "IBM-DTLA-307020",
122 "IBM-DTLA-307015",
123 "IBM-DTLA-305040",
124 "IBM-DTLA-305030",
125 "IBM-DTLA-305020",
126 "IC35L010AVER07-0",
127 "IC35L020AVER07-0",
128 "IC35L030AVER07-0",
129 "IC35L040AVER07-0",
130 "IC35L060AVER07-0",
131 "WDC AC310200R",
132 NULL
133};
134
135static const char *bad_ata66_4[] = {
136 "IBM-DTLA-307075",
137 "IBM-DTLA-307060",
138 "IBM-DTLA-307045",
139 "IBM-DTLA-307030",
140 "IBM-DTLA-307020",
141 "IBM-DTLA-307015",
142 "IBM-DTLA-305040",
143 "IBM-DTLA-305030",
144 "IBM-DTLA-305020",
145 "IC35L010AVER07-0",
146 "IC35L020AVER07-0",
147 "IC35L030AVER07-0",
148 "IC35L040AVER07-0",
149 "IC35L060AVER07-0",
150 "WDC AC310200R",
151 NULL
152};
153
154static const char *bad_ata66_3[] = {
155 "WDC AC310200R",
156 NULL
157};
158
159static const char *bad_ata33[] = {
160 "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
161 "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
162 "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
163 "Maxtor 90510D4",
164 "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
165 "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
166 "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
167 NULL
168};
169
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800170static u8 xfer_speeds[] = {
171 XFER_UDMA_6,
172 XFER_UDMA_5,
173 XFER_UDMA_4,
174 XFER_UDMA_3,
175 XFER_UDMA_2,
176 XFER_UDMA_1,
177 XFER_UDMA_0,
178
179 XFER_MW_DMA_2,
180 XFER_MW_DMA_1,
181 XFER_MW_DMA_0,
182
183 XFER_PIO_4,
184 XFER_PIO_3,
185 XFER_PIO_2,
186 XFER_PIO_1,
187 XFER_PIO_0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188};
189
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800190/* Key for bus clock timings
191 * 36x 37x
192 * bits bits
193 * 0:3 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
194 * cycles = value + 1
195 * 4:7 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
196 * cycles = value + 1
197 * 8:11 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
198 * register access.
199 * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file
200 * register access.
201 * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer.
202 * - 21 CLK frequency: 0=ATA clock, 1=dual ATA clock.
203 * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and
204 * MW DMA xfer.
205 * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for
206 * task file register access.
207 * 28 28 UDMA enable.
208 * 29 29 DMA enable.
209 * 30 30 PIO MST enable. If set, the chip is in bus master mode during
210 * PIO xfer.
211 * 31 31 FIFO enable.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800214static u32 forty_base_hpt36x[] = {
215 /* XFER_UDMA_6 */ 0x900fd943,
216 /* XFER_UDMA_5 */ 0x900fd943,
217 /* XFER_UDMA_4 */ 0x900fd943,
218 /* XFER_UDMA_3 */ 0x900ad943,
219 /* XFER_UDMA_2 */ 0x900bd943,
220 /* XFER_UDMA_1 */ 0x9008d943,
221 /* XFER_UDMA_0 */ 0x9008d943,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800223 /* XFER_MW_DMA_2 */ 0xa008d943,
224 /* XFER_MW_DMA_1 */ 0xa010d955,
225 /* XFER_MW_DMA_0 */ 0xa010d9fc,
226
227 /* XFER_PIO_4 */ 0xc008d963,
228 /* XFER_PIO_3 */ 0xc010d974,
229 /* XFER_PIO_2 */ 0xc010d997,
230 /* XFER_PIO_1 */ 0xc010d9c7,
231 /* XFER_PIO_0 */ 0xc018d9d9
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232};
233
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800234static u32 thirty_three_base_hpt36x[] = {
235 /* XFER_UDMA_6 */ 0x90c9a731,
236 /* XFER_UDMA_5 */ 0x90c9a731,
237 /* XFER_UDMA_4 */ 0x90c9a731,
238 /* XFER_UDMA_3 */ 0x90cfa731,
239 /* XFER_UDMA_2 */ 0x90caa731,
240 /* XFER_UDMA_1 */ 0x90cba731,
241 /* XFER_UDMA_0 */ 0x90c8a731,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800243 /* XFER_MW_DMA_2 */ 0xa0c8a731,
244 /* XFER_MW_DMA_1 */ 0xa0c8a732, /* 0xa0c8a733 */
245 /* XFER_MW_DMA_0 */ 0xa0c8a797,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800247 /* XFER_PIO_4 */ 0xc0c8a731,
248 /* XFER_PIO_3 */ 0xc0c8a742,
249 /* XFER_PIO_2 */ 0xc0d0a753,
250 /* XFER_PIO_1 */ 0xc0d0a7a3, /* 0xc0d0a793 */
251 /* XFER_PIO_0 */ 0xc0d0a7aa /* 0xc0d0a7a7 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252};
253
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800254static u32 twenty_five_base_hpt36x[] = {
255 /* XFER_UDMA_6 */ 0x90c98521,
256 /* XFER_UDMA_5 */ 0x90c98521,
257 /* XFER_UDMA_4 */ 0x90c98521,
258 /* XFER_UDMA_3 */ 0x90cf8521,
259 /* XFER_UDMA_2 */ 0x90cf8521,
260 /* XFER_UDMA_1 */ 0x90cb8521,
261 /* XFER_UDMA_0 */ 0x90cb8521,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800263 /* XFER_MW_DMA_2 */ 0xa0ca8521,
264 /* XFER_MW_DMA_1 */ 0xa0ca8532,
265 /* XFER_MW_DMA_0 */ 0xa0ca8575,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800267 /* XFER_PIO_4 */ 0xc0ca8521,
268 /* XFER_PIO_3 */ 0xc0ca8532,
269 /* XFER_PIO_2 */ 0xc0ca8542,
270 /* XFER_PIO_1 */ 0xc0d08572,
271 /* XFER_PIO_0 */ 0xc0d08585
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272};
273
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800274static u32 thirty_three_base_hpt37x[] = {
275 /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */
276 /* XFER_UDMA_5 */ 0x12446231,
277 /* XFER_UDMA_4 */ 0x12446231,
278 /* XFER_UDMA_3 */ 0x126c6231,
279 /* XFER_UDMA_2 */ 0x12486231,
280 /* XFER_UDMA_1 */ 0x124c6233,
281 /* XFER_UDMA_0 */ 0x12506297,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800283 /* XFER_MW_DMA_2 */ 0x22406c31,
284 /* XFER_MW_DMA_1 */ 0x22406c33,
285 /* XFER_MW_DMA_0 */ 0x22406c97,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800287 /* XFER_PIO_4 */ 0x06414e31,
288 /* XFER_PIO_3 */ 0x06414e42,
289 /* XFER_PIO_2 */ 0x06414e53,
290 /* XFER_PIO_1 */ 0x06814e93,
291 /* XFER_PIO_0 */ 0x06814ea7
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292};
293
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800294static u32 fifty_base_hpt37x[] = {
295 /* XFER_UDMA_6 */ 0x12848242,
296 /* XFER_UDMA_5 */ 0x12848242,
297 /* XFER_UDMA_4 */ 0x12ac8242,
298 /* XFER_UDMA_3 */ 0x128c8242,
299 /* XFER_UDMA_2 */ 0x120c8242,
300 /* XFER_UDMA_1 */ 0x12148254,
301 /* XFER_UDMA_0 */ 0x121882ea,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800303 /* XFER_MW_DMA_2 */ 0x22808242,
304 /* XFER_MW_DMA_1 */ 0x22808254,
305 /* XFER_MW_DMA_0 */ 0x228082ea,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800307 /* XFER_PIO_4 */ 0x0a81f442,
308 /* XFER_PIO_3 */ 0x0a81f443,
309 /* XFER_PIO_2 */ 0x0a81f454,
310 /* XFER_PIO_1 */ 0x0ac1f465,
311 /* XFER_PIO_0 */ 0x0ac1f48a
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312};
313
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800314static u32 sixty_six_base_hpt37x[] = {
315 /* XFER_UDMA_6 */ 0x1c869c62,
316 /* XFER_UDMA_5 */ 0x1cae9c62, /* 0x1c8a9c62 */
317 /* XFER_UDMA_4 */ 0x1c8a9c62,
318 /* XFER_UDMA_3 */ 0x1c8e9c62,
319 /* XFER_UDMA_2 */ 0x1c929c62,
320 /* XFER_UDMA_1 */ 0x1c9a9c62,
321 /* XFER_UDMA_0 */ 0x1c829c62,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800323 /* XFER_MW_DMA_2 */ 0x2c829c62,
324 /* XFER_MW_DMA_1 */ 0x2c829c66,
325 /* XFER_MW_DMA_0 */ 0x2c829d2e,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800327 /* XFER_PIO_4 */ 0x0c829c62,
328 /* XFER_PIO_3 */ 0x0c829c84,
329 /* XFER_PIO_2 */ 0x0c829ca6,
330 /* XFER_PIO_1 */ 0x0d029d26,
331 /* XFER_PIO_0 */ 0x0d029d5e
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332};
333
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334#define HPT366_DEBUG_DRIVE_INFO 0
335#define HPT374_ALLOW_ATA133_6 0
336#define HPT371_ALLOW_ATA133_6 0
337#define HPT302_ALLOW_ATA133_6 0
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800338#define HPT372_ALLOW_ATA133_6 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339#define HPT370_ALLOW_ATA100_5 1
340#define HPT366_ALLOW_ATA66_4 1
341#define HPT366_ALLOW_ATA66_3 1
342#define HPT366_MAX_DEVS 8
343
344#define F_LOW_PCI_33 0x23
345#define F_LOW_PCI_40 0x29
346#define F_LOW_PCI_50 0x2d
347#define F_LOW_PCI_66 0x42
348
Alan Coxb39b01f2005-06-27 15:24:27 -0700349/*
350 * Hold all the highpoint quirks and revision information in one
351 * place.
352 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
Alan Coxb39b01f2005-06-27 15:24:27 -0700354struct hpt_info
355{
356 u8 max_mode; /* Speeds allowed */
357 int revision; /* Chipset revision */
358 int flags; /* Chipset properties */
359#define PLL_MODE 1
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800360#define IS_3xxN 2
361#define PCI_66MHZ 4
Alan Coxb39b01f2005-06-27 15:24:27 -0700362 /* Speed table */
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800363 u32 *speed;
Alan Coxb39b01f2005-06-27 15:24:27 -0700364};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
Alan Coxb39b01f2005-06-27 15:24:27 -0700366/*
367 * This wants fixing so that we do everything not by classrev
368 * (which breaks on the newest chips) but by creating an
369 * enumeration of chip variants and using that
370 */
371
372static __devinit u32 hpt_revision (struct pci_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
374 u32 class_rev;
375 pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
376 class_rev &= 0xff;
377
378 switch(dev->device) {
379 /* Remap new 372N onto 372 */
380 case PCI_DEVICE_ID_TTI_HPT372N:
381 class_rev = PCI_DEVICE_ID_TTI_HPT372; break;
382 case PCI_DEVICE_ID_TTI_HPT374:
383 class_rev = PCI_DEVICE_ID_TTI_HPT374; break;
384 case PCI_DEVICE_ID_TTI_HPT371:
385 class_rev = PCI_DEVICE_ID_TTI_HPT371; break;
386 case PCI_DEVICE_ID_TTI_HPT302:
387 class_rev = PCI_DEVICE_ID_TTI_HPT302; break;
388 case PCI_DEVICE_ID_TTI_HPT372:
389 class_rev = PCI_DEVICE_ID_TTI_HPT372; break;
390 default:
391 break;
392 }
393 return class_rev;
394}
395
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396static int check_in_drive_lists(ide_drive_t *drive, const char **list);
397
398static u8 hpt3xx_ratemask (ide_drive_t *drive)
399{
Alan Coxb39b01f2005-06-27 15:24:27 -0700400 ide_hwif_t *hwif = drive->hwif;
401 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 u8 mode = 0;
403
Alan Coxb39b01f2005-06-27 15:24:27 -0700404 /* FIXME: TODO - move this to set info->mode once at boot */
405
406 if (info->revision >= 8) { /* HPT374 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3;
Alan Coxb39b01f2005-06-27 15:24:27 -0700408 } else if (info->revision >= 7) { /* HPT371 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3;
Alan Coxb39b01f2005-06-27 15:24:27 -0700410 } else if (info->revision >= 6) { /* HPT302 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3;
Alan Coxb39b01f2005-06-27 15:24:27 -0700412 } else if (info->revision >= 5) { /* HPT372 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3;
Alan Coxb39b01f2005-06-27 15:24:27 -0700414 } else if (info->revision >= 4) { /* HPT370A */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
Alan Coxb39b01f2005-06-27 15:24:27 -0700416 } else if (info->revision >= 3) { /* HPT370 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
418 mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode;
419 } else { /* HPT366 and HPT368 */
420 mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2;
421 }
Alan Coxb39b01f2005-06-27 15:24:27 -0700422 if (!eighty_ninty_three(drive) && mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 mode = min(mode, (u8)1);
424 return mode;
425}
426
427/*
428 * Note for the future; the SATA hpt37x we must set
429 * either PIO or UDMA modes 0,4,5
430 */
431
432static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
433{
Alan Coxb39b01f2005-06-27 15:24:27 -0700434 ide_hwif_t *hwif = drive->hwif;
435 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 u8 mode = hpt3xx_ratemask(drive);
437
438 if (drive->media != ide_disk)
439 return min(speed, (u8)XFER_PIO_4);
440
441 switch(mode) {
442 case 0x04:
443 speed = min(speed, (u8)XFER_UDMA_6);
444 break;
445 case 0x03:
446 speed = min(speed, (u8)XFER_UDMA_5);
Alan Coxb39b01f2005-06-27 15:24:27 -0700447 if (info->revision >= 5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 break;
449 if (check_in_drive_lists(drive, bad_ata100_5))
450 speed = min(speed, (u8)XFER_UDMA_4);
451 break;
452 case 0x02:
453 speed = min(speed, (u8)XFER_UDMA_4);
454 /*
455 * CHECK ME, Does this need to be set to 5 ??
456 */
Alan Coxb39b01f2005-06-27 15:24:27 -0700457 if (info->revision >= 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 break;
459 if ((check_in_drive_lists(drive, bad_ata66_4)) ||
460 (!(HPT366_ALLOW_ATA66_4)))
461 speed = min(speed, (u8)XFER_UDMA_3);
462 if ((check_in_drive_lists(drive, bad_ata66_3)) ||
463 (!(HPT366_ALLOW_ATA66_3)))
464 speed = min(speed, (u8)XFER_UDMA_2);
465 break;
466 case 0x01:
467 speed = min(speed, (u8)XFER_UDMA_2);
468 /*
469 * CHECK ME, Does this need to be set to 5 ??
470 */
Alan Coxb39b01f2005-06-27 15:24:27 -0700471 if (info->revision >= 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 break;
473 if (check_in_drive_lists(drive, bad_ata33))
474 speed = min(speed, (u8)XFER_MW_DMA_2);
475 break;
476 case 0x00:
477 default:
478 speed = min(speed, (u8)XFER_MW_DMA_2);
479 break;
480 }
481 return speed;
482}
483
484static int check_in_drive_lists (ide_drive_t *drive, const char **list)
485{
486 struct hd_driveid *id = drive->id;
487
488 if (quirk_drives == list) {
489 while (*list)
490 if (strstr(id->model, *list++))
491 return 1;
492 } else {
493 while (*list)
494 if (!strcmp(*list++,id->model))
495 return 1;
496 }
497 return 0;
498}
499
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800500static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501{
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800502 int i;
503
504 /*
505 * Lookup the transfer mode table to get the index into
506 * the timing table.
507 *
508 * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.
509 */
510 for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
511 if (xfer_speeds[i] == speed)
512 break;
513 return chipset_table[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514}
515
516static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
517{
Alan Coxb39b01f2005-06-27 15:24:27 -0700518 ide_hwif_t *hwif = drive->hwif;
519 struct pci_dev *dev = hwif->pci_dev;
520 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 u8 speed = hpt3xx_ratefilter(drive, xferspeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
Alan Coxb39b01f2005-06-27 15:24:27 -0700523 u8 regfast = (hwif->channel) ? 0x55 : 0x51;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 u8 drive_fast = 0;
525 u32 reg1 = 0, reg2 = 0;
526
527 /*
528 * Disable the "fast interrupt" prediction.
529 */
530 pci_read_config_byte(dev, regfast, &drive_fast);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 if (drive_fast & 0x80)
532 pci_write_config_byte(dev, regfast, drive_fast & ~0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
Alan Coxb39b01f2005-06-27 15:24:27 -0700534 reg2 = pci_bus_clock_list(speed, info->speed);
535
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 /*
537 * Disable on-chip PIO FIFO/buffer
538 * (to avoid problems handling I/O errors later)
539 */
540 pci_read_config_dword(dev, regtime, &reg1);
541 if (speed >= XFER_MW_DMA_0) {
542 reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000);
543 } else {
544 reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000);
545 }
546 reg2 &= ~0x80000000;
547
548 pci_write_config_dword(dev, regtime, reg2);
549
550 return ide_config_drive_speed(drive, speed);
551}
552
553static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
554{
Alan Coxb39b01f2005-06-27 15:24:27 -0700555 ide_hwif_t *hwif = drive->hwif;
556 struct pci_dev *dev = hwif->pci_dev;
557 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 u8 speed = hpt3xx_ratefilter(drive, xferspeed);
Alan Coxb39b01f2005-06-27 15:24:27 -0700559 u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 u8 drive_pci = 0x40 + (drive->dn * 4);
561 u8 new_fast = 0, drive_fast = 0;
562 u32 list_conf = 0, drive_conf = 0;
563 u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
564
565 /*
566 * Disable the "fast interrupt" prediction.
567 * don't holdoff on interrupts. (== 0x01 despite what the docs say)
568 */
569 pci_read_config_byte(dev, regfast, &drive_fast);
570 new_fast = drive_fast;
571 if (new_fast & 0x02)
572 new_fast &= ~0x02;
573
574#ifdef HPT_DELAY_INTERRUPT
575 if (new_fast & 0x01)
576 new_fast &= ~0x01;
577#else
578 if ((new_fast & 0x01) == 0)
579 new_fast |= 0x01;
580#endif
581 if (new_fast != drive_fast)
582 pci_write_config_byte(dev, regfast, new_fast);
583
Alan Coxb39b01f2005-06-27 15:24:27 -0700584 list_conf = pci_bus_clock_list(speed, info->speed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
586 pci_read_config_dword(dev, drive_pci, &drive_conf);
587 list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
588
Alan Coxb39b01f2005-06-27 15:24:27 -0700589 if (speed < XFER_MW_DMA_0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 pci_write_config_dword(dev, drive_pci, list_conf);
592
593 return ide_config_drive_speed(drive, speed);
594}
595
596static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
597{
Alan Coxb39b01f2005-06-27 15:24:27 -0700598 ide_hwif_t *hwif = drive->hwif;
599 struct pci_dev *dev = hwif->pci_dev;
600 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 u8 speed = hpt3xx_ratefilter(drive, xferspeed);
Alan Coxb39b01f2005-06-27 15:24:27 -0700602 u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4);
604 u32 list_conf = 0, drive_conf = 0;
605 u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
606
607 /*
608 * Disable the "fast interrupt" prediction.
609 * don't holdoff on interrupts. (== 0x01 despite what the docs say)
610 */
611 pci_read_config_byte(dev, regfast, &drive_fast);
612 drive_fast &= ~0x07;
613 pci_write_config_byte(dev, regfast, drive_fast);
Alan Coxb39b01f2005-06-27 15:24:27 -0700614
615 list_conf = pci_bus_clock_list(speed, info->speed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 pci_read_config_dword(dev, drive_pci, &drive_conf);
617 list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
618 if (speed < XFER_MW_DMA_0)
619 list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
620 pci_write_config_dword(dev, drive_pci, list_conf);
621
622 return ide_config_drive_speed(drive, speed);
623}
624
625static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed)
626{
Alan Coxb39b01f2005-06-27 15:24:27 -0700627 ide_hwif_t *hwif = drive->hwif;
628 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
Alan Coxb39b01f2005-06-27 15:24:27 -0700630 if (info->revision >= 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 return hpt372_tune_chipset(drive, speed); /* not a typo */
Alan Coxb39b01f2005-06-27 15:24:27 -0700632 else if (info->revision >= 5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 return hpt372_tune_chipset(drive, speed);
Alan Coxb39b01f2005-06-27 15:24:27 -0700634 else if (info->revision >= 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 return hpt370_tune_chipset(drive, speed);
636 else /* hpt368: hpt_minimum_revision(dev, 2) */
637 return hpt36x_tune_chipset(drive, speed);
638}
639
640static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio)
641{
642 pio = ide_get_best_pio_mode(drive, 255, pio, NULL);
643 (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio));
644}
645
646/*
647 * This allows the configuration of ide_pci chipset registers
648 * for cards that learn about the drive's UDMA, DMA, PIO capabilities
649 * after the drive is reported by the OS. Initially for designed for
650 * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc.
651 *
652 * check_in_drive_lists(drive, bad_ata66_4)
653 * check_in_drive_lists(drive, bad_ata66_3)
654 * check_in_drive_lists(drive, bad_ata33)
655 *
656 */
657static int config_chipset_for_dma (ide_drive_t *drive)
658{
659 u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive));
Alan Coxb39b01f2005-06-27 15:24:27 -0700660 ide_hwif_t *hwif = drive->hwif;
661 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
Alan Coxb39b01f2005-06-27 15:24:27 -0700663 if (!speed)
664 return 0;
665
666 /* If we don't have any timings we can't do a lot */
667 if (info->speed == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 return 0;
669
670 (void) hpt3xx_tune_chipset(drive, speed);
671 return ide_dma_enable(drive);
672}
673
674static int hpt3xx_quirkproc (ide_drive_t *drive)
675{
676 return ((int) check_in_drive_lists(drive, quirk_drives));
677}
678
679static void hpt3xx_intrproc (ide_drive_t *drive)
680{
Alan Coxb39b01f2005-06-27 15:24:27 -0700681 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
683 if (drive->quirk_list)
684 return;
685 /* drives in the quirk_list may not like intr setups/cleanups */
686 hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);
687}
688
689static void hpt3xx_maskproc (ide_drive_t *drive, int mask)
690{
Alan Coxb39b01f2005-06-27 15:24:27 -0700691 ide_hwif_t *hwif = drive->hwif;
692 struct hpt_info *info = ide_get_hwifdata(hwif);
693 struct pci_dev *dev = hwif->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694
695 if (drive->quirk_list) {
Alan Coxb39b01f2005-06-27 15:24:27 -0700696 if (info->revision >= 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 u8 reg5a = 0;
698 pci_read_config_byte(dev, 0x5a, &reg5a);
699 if (((reg5a & 0x10) >> 4) != mask)
700 pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
701 } else {
702 if (mask) {
Alan Coxb39b01f2005-06-27 15:24:27 -0700703 disable_irq(hwif->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 } else {
Alan Coxb39b01f2005-06-27 15:24:27 -0700705 enable_irq(hwif->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 }
707 }
708 } else {
709 if (IDE_CONTROL_REG)
Alan Coxb39b01f2005-06-27 15:24:27 -0700710 hwif->OUTB(mask ? (drive->ctl | 2) :
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 (drive->ctl & ~2),
712 IDE_CONTROL_REG);
713 }
714}
715
716static int hpt366_config_drive_xfer_rate (ide_drive_t *drive)
717{
Alan Coxb39b01f2005-06-27 15:24:27 -0700718 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 struct hd_driveid *id = drive->id;
720
721 drive->init_speed = 0;
722
Alan Coxb39b01f2005-06-27 15:24:27 -0700723 if ((id->capability & 1) && drive->autodma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725 if (ide_use_dma(drive)) {
726 if (config_chipset_for_dma(drive))
727 return hwif->ide_dma_on(drive);
728 }
729
730 goto fast_ata_pio;
731
732 } else if ((id->capability & 8) || (id->field_valid & 2)) {
733fast_ata_pio:
734 hpt3xx_tune_drive(drive, 5);
735 return hwif->ide_dma_off_quietly(drive);
736 }
737 /* IORDY not supported */
738 return 0;
739}
740
741/*
742 * This is specific to the HPT366 UDMA bios chipset
743 * by HighPoint|Triones Technologies, Inc.
744 */
745static int hpt366_ide_dma_lostirq (ide_drive_t *drive)
746{
747 struct pci_dev *dev = HWIF(drive)->pci_dev;
748 u8 reg50h = 0, reg52h = 0, reg5ah = 0;
749
750 pci_read_config_byte(dev, 0x50, &reg50h);
751 pci_read_config_byte(dev, 0x52, &reg52h);
752 pci_read_config_byte(dev, 0x5a, &reg5ah);
753 printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",
754 drive->name, __FUNCTION__, reg50h, reg52h, reg5ah);
755 if (reg5ah & 0x10)
756 pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 return __ide_dma_lostirq(drive);
758}
759
760static void hpt370_clear_engine (ide_drive_t *drive)
761{
762 u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50;
763 pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37);
764 udelay(10);
765}
766
767static void hpt370_ide_dma_start(ide_drive_t *drive)
768{
769#ifdef HPT_RESET_STATE_ENGINE
770 hpt370_clear_engine(drive);
771#endif
772 ide_dma_start(drive);
773}
774
775static int hpt370_ide_dma_end (ide_drive_t *drive)
776{
777 ide_hwif_t *hwif = HWIF(drive);
778 u8 dma_stat = hwif->INB(hwif->dma_status);
779
780 if (dma_stat & 0x01) {
781 /* wait a little */
782 udelay(20);
783 dma_stat = hwif->INB(hwif->dma_status);
784 }
785 if ((dma_stat & 0x01) != 0)
786 /* fallthrough */
787 (void) HWIF(drive)->ide_dma_timeout(drive);
788
789 return __ide_dma_end(drive);
790}
791
792static void hpt370_lostirq_timeout (ide_drive_t *drive)
793{
794 ide_hwif_t *hwif = HWIF(drive);
795 u8 bfifo = 0, reginfo = hwif->channel ? 0x56 : 0x52;
796 u8 dma_stat = 0, dma_cmd = 0;
797
798 pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo);
Alan Coxb39b01f2005-06-27 15:24:27 -0700799 printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 hpt370_clear_engine(drive);
801 /* get dma command mode */
802 dma_cmd = hwif->INB(hwif->dma_command);
803 /* stop dma */
804 hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command);
805 dma_stat = hwif->INB(hwif->dma_status);
806 /* clear errors */
807 hwif->OUTB(dma_stat | 0x6, hwif->dma_status);
808}
809
810static int hpt370_ide_dma_timeout (ide_drive_t *drive)
811{
812 hpt370_lostirq_timeout(drive);
813 hpt370_clear_engine(drive);
814 return __ide_dma_timeout(drive);
815}
816
817static int hpt370_ide_dma_lostirq (ide_drive_t *drive)
818{
819 hpt370_lostirq_timeout(drive);
820 hpt370_clear_engine(drive);
821 return __ide_dma_lostirq(drive);
822}
823
824/* returns 1 if DMA IRQ issued, 0 otherwise */
825static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
826{
827 ide_hwif_t *hwif = HWIF(drive);
828 u16 bfifo = 0;
829 u8 reginfo = hwif->channel ? 0x56 : 0x52;
830 u8 dma_stat;
831
832 pci_read_config_word(hwif->pci_dev, reginfo, &bfifo);
833 if (bfifo & 0x1FF) {
834// printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
835 return 0;
836 }
837
838 dma_stat = hwif->INB(hwif->dma_status);
839 /* return 1 if INTR asserted */
840 if ((dma_stat & 4) == 4)
841 return 1;
842
843 if (!drive->waiting_for_dma)
844 printk(KERN_WARNING "%s: (%s) called while not waiting\n",
845 drive->name, __FUNCTION__);
846 return 0;
847}
848
849static int hpt374_ide_dma_end (ide_drive_t *drive)
850{
851 struct pci_dev *dev = HWIF(drive)->pci_dev;
852 ide_hwif_t *hwif = HWIF(drive);
853 u8 msc_stat = 0, mscreg = hwif->channel ? 0x54 : 0x50;
854 u8 bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01;
855
856 pci_read_config_byte(dev, 0x6a, &bwsr_stat);
857 pci_read_config_byte(dev, mscreg, &msc_stat);
858 if ((bwsr_stat & bwsr_mask) == bwsr_mask)
859 pci_write_config_byte(dev, mscreg, msc_stat|0x30);
860 return __ide_dma_end(drive);
861}
862
863/**
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800864 * hpt3xxn_set_clock - perform clock switching dance
865 * @hwif: hwif to switch
866 * @mode: clocking mode (0x21 for write, 0x23 otherwise)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 *
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800868 * Switch the DPLL clock on the HPT3xxN devices. This is a right mess.
869 * NOTE: avoid touching the disabled primary channel on HPT371N -- it
870 * doesn't physically exist anyway...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800872
873static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874{
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800875 u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b);
876
877 if ((scr2 & 0x7f) == mode)
878 return;
879
880 /* MISC. control register 1 has the channel enable bit... */
881 mcr1 = hwif->INB(hwif->dma_master + 0x70);
882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 /* Tristate the bus */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800884 if (mcr1 & 0x04)
885 hwif->OUTB(0x80, hwif->dma_master + 0x73);
886 hwif->OUTB(0x80, hwif->dma_master + 0x77);
887
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 /* Switch clock and reset channels */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800889 hwif->OUTB(mode, hwif->dma_master + 0x7b);
890 hwif->OUTB(0xc0, hwif->dma_master + 0x79);
891
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 /* Reset state machines */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800893 if (mcr1 & 0x04)
894 hwif->OUTB(0x37, hwif->dma_master + 0x70);
895 hwif->OUTB(0x37, hwif->dma_master + 0x74);
896
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 /* Complete reset */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800898 hwif->OUTB(0x00, hwif->dma_master + 0x79);
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 /* Reconnect channels to bus */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800901 if (mcr1 & 0x04)
902 hwif->OUTB(0x00, hwif->dma_master + 0x73);
903 hwif->OUTB(0x00, hwif->dma_master + 0x77);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904}
905
906/**
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800907 * hpt3xxn_rw_disk - prepare for I/O
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 * @drive: drive for command
909 * @rq: block request structure
910 *
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800911 * This is called when a disk I/O is issued to HPT3xxN.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 * We need it because of the clock switching.
913 */
914
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800915static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916{
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800917 ide_hwif_t *hwif = HWIF(drive);
918 u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800920 hpt3xxn_set_clock(hwif, wantclock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921}
922
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923/*
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800924 * Set/get power state for a drive.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 *
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800926 * When we turn the power back on, we need to re-initialize things.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 */
928#define TRISTATE_BIT 0x8000
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800929
930static int hpt3xx_busproc(ide_drive_t *drive, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931{
Alan Coxb39b01f2005-06-27 15:24:27 -0700932 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 struct pci_dev *dev = hwif->pci_dev;
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800934 u8 tristate, resetmask, bus_reg = 0;
935 u16 tri_reg = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936
937 hwif->bus_state = state;
938
939 if (hwif->channel) {
940 /* secondary channel */
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800941 tristate = 0x56;
942 resetmask = 0x80;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 } else {
944 /* primary channel */
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800945 tristate = 0x52;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 resetmask = 0x40;
947 }
948
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800949 /* Grab the status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 pci_read_config_word(dev, tristate, &tri_reg);
951 pci_read_config_byte(dev, 0x59, &bus_reg);
952
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800953 /*
954 * Set the state. We don't set it if we don't need to do so.
955 * Make sure that the drive knows that it has failed if it's off.
956 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 switch (state) {
958 case BUSSTATE_ON:
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800959 if (!(bus_reg & resetmask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 return 0;
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800961 hwif->drives[0].failures = hwif->drives[1].failures = 0;
962
963 pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask);
964 pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT);
965 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 case BUSSTATE_OFF:
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800967 if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 return 0;
969 tri_reg &= ~TRISTATE_BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 break;
971 case BUSSTATE_TRISTATE:
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800972 if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 return 0;
974 tri_reg |= TRISTATE_BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 break;
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800976 default:
977 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800980 hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
981 hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
982
983 pci_write_config_word(dev, tristate, tri_reg);
984 pci_write_config_byte(dev, 0x59, bus_reg | resetmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 return 0;
986}
987
Alan Coxb39b01f2005-06-27 15:24:27 -0700988static void __devinit hpt366_clocking(ide_hwif_t *hwif)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989{
Alan Coxb39b01f2005-06-27 15:24:27 -0700990 u32 reg1 = 0;
991 struct hpt_info *info = ide_get_hwifdata(hwif);
992
993 pci_read_config_dword(hwif->pci_dev, 0x40, &reg1);
994
995 /* detect bus speed by looking at control reg timing: */
996 switch((reg1 >> 8) & 7) {
997 case 5:
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800998 info->speed = forty_base_hpt36x;
Alan Coxb39b01f2005-06-27 15:24:27 -0700999 break;
1000 case 9:
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001001 info->speed = twenty_five_base_hpt36x;
Alan Coxb39b01f2005-06-27 15:24:27 -07001002 break;
1003 case 7:
1004 default:
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001005 info->speed = thirty_three_base_hpt36x;
Alan Coxb39b01f2005-06-27 15:24:27 -07001006 break;
1007 }
1008}
1009
1010static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
1011{
1012 struct hpt_info *info = ide_get_hwifdata(hwif);
1013 struct pci_dev *dev = hwif->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 int adjust, i;
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001015 u16 freq = 0;
1016 u32 pll, temp = 0;
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001017 u8 reg5bh = 0, mcr1 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 /*
1020 * default to pci clock. make sure MA15/16 are set to output
Alan Coxb39b01f2005-06-27 15:24:27 -07001021 * to prevent drives having problems with 40-pin cables. Needed
1022 * for some drives such as IBM-DTLA which will not enter ready
1023 * state on reset when PDIAG is a input.
1024 *
1025 * ToDo: should we set 0x21 when using PLL mode ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 */
1027 pci_write_config_byte(dev, 0x5b, 0x23);
1028
1029 /*
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001030 * We'll have to read f_CNT value in order to determine
1031 * the PCI clock frequency according to the following ratio:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 *
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001033 * f_CNT = Fpci * 192 / Fdpll
1034 *
1035 * First try reading the register in which the HighPoint BIOS
1036 * saves f_CNT value before reprogramming the DPLL from its
1037 * default setting (which differs for the various chips).
1038 * In case the signature check fails, we'll have to resort to
1039 * reading the f_CNT register itself in hopes that nobody has
1040 * touched the DPLL yet...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 */
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001042 pci_read_config_dword(dev, 0x70, &temp);
1043 if ((temp & 0xFFFFF000) != 0xABCDE000) {
1044 int i;
1045
1046 printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n");
1047
1048 /* Calculate the average value of f_CNT */
1049 for (temp = i = 0; i < 128; i++) {
1050 pci_read_config_word(dev, 0x78, &freq);
1051 temp += freq & 0x1ff;
1052 mdelay(1);
1053 }
1054 freq = temp / 128;
1055 } else
1056 freq = temp & 0x1ff;
1057
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 /*
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001059 * HPT3xxN chips use different PCI clock information.
1060 * Currently we always set up the PLL for them.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 */
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001062
1063 if (info->flags & IS_3xxN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 if(freq < 0x55)
1065 pll = F_LOW_PCI_33;
1066 else if(freq < 0x70)
1067 pll = F_LOW_PCI_40;
1068 else if(freq < 0x7F)
1069 pll = F_LOW_PCI_50;
1070 else
1071 pll = F_LOW_PCI_66;
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001072
1073 printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 }
1075 else
1076 {
1077 if(freq < 0x9C)
1078 pll = F_LOW_PCI_33;
1079 else if(freq < 0xb0)
1080 pll = F_LOW_PCI_40;
1081 else if(freq <0xc8)
1082 pll = F_LOW_PCI_50;
1083 else
1084 pll = F_LOW_PCI_66;
1085
1086 if (pll == F_LOW_PCI_33) {
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001087 info->speed = thirty_three_base_hpt37x;
Alan Coxb39b01f2005-06-27 15:24:27 -07001088 printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 } else if (pll == F_LOW_PCI_40) {
1090 /* Unsupported */
1091 } else if (pll == F_LOW_PCI_50) {
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001092 info->speed = fifty_base_hpt37x;
Alan Coxb39b01f2005-06-27 15:24:27 -07001093 printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 } else {
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001095 info->speed = sixty_six_base_hpt37x;
1096 printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 }
1098 }
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001099
1100 if (pll == F_LOW_PCI_66)
1101 info->flags |= PCI_66MHZ;
1102
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 /*
1104 * only try the pll if we don't have a table for the clock
1105 * speed that we're running at. NOTE: the internal PLL will
1106 * result in slow reads when using a 33MHz PCI clock. we also
1107 * don't like to use the PLL because it will cause glitches
1108 * on PRST/SRST when the HPT state engine gets reset.
Alan Coxb39b01f2005-06-27 15:24:27 -07001109 *
1110 * ToDo: Use 66MHz PLL when ATA133 devices are present on a
1111 * 372 device so we can get ATA133 support
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 */
Alan Coxb39b01f2005-06-27 15:24:27 -07001113 if (info->speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 goto init_hpt37X_done;
Alan Coxb39b01f2005-06-27 15:24:27 -07001115
1116 info->flags |= PLL_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
1118 /*
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001119 * Adjust the PLL based upon the PCI clock, enable it, and
1120 * wait for stabilization...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 */
1122 adjust = 0;
1123 freq = (pll < F_LOW_PCI_50) ? 2 : 4;
1124 while (adjust++ < 6) {
1125 pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 |
1126 pll | 0x100);
1127
1128 /* wait for clock stabilization */
1129 for (i = 0; i < 0x50000; i++) {
1130 pci_read_config_byte(dev, 0x5b, &reg5bh);
1131 if (reg5bh & 0x80) {
1132 /* spin looking for the clock to destabilize */
1133 for (i = 0; i < 0x1000; ++i) {
1134 pci_read_config_byte(dev, 0x5b,
1135 &reg5bh);
1136 if ((reg5bh & 0x80) == 0)
1137 goto pll_recal;
1138 }
1139 pci_read_config_dword(dev, 0x5c, &pll);
1140 pci_write_config_dword(dev, 0x5c,
1141 pll & ~0x100);
1142 pci_write_config_byte(dev, 0x5b, 0x21);
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001143
1144 info->speed = fifty_base_hpt37x;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 printk("HPT37X: using 50MHz internal PLL\n");
1146 goto init_hpt37X_done;
1147 }
1148 }
1149pll_recal:
1150 if (adjust & 1)
1151 pll -= (adjust >> 1);
1152 else
1153 pll += (adjust >> 1);
1154 }
1155
1156init_hpt37X_done:
Alan Coxb39b01f2005-06-27 15:24:27 -07001157 if (!info->speed)
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001158 printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n",
1159 (info->flags & IS_3xxN) ? "N" : "", pll, freq);
1160 /*
1161 * Reset the state engines.
1162 * NOTE: avoid accidentally enabling the primary channel on HPT371N.
1163 */
1164 pci_read_config_byte(dev, 0x50, &mcr1);
1165 if (mcr1 & 0x04)
1166 pci_write_config_byte(dev, 0x50, 0x37);
1167 pci_write_config_byte(dev, 0x54, 0x37);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 udelay(100);
Alan Coxb39b01f2005-06-27 15:24:27 -07001169}
1170
1171static int __devinit init_hpt37x(struct pci_dev *dev)
1172{
1173 u8 reg5ah;
1174
1175 pci_read_config_byte(dev, 0x5a, &reg5ah);
1176 /* interrupt force enable */
1177 pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 return 0;
1179}
1180
1181static int __devinit init_hpt366(struct pci_dev *dev)
1182{
1183 u32 reg1 = 0;
1184 u8 drive_fast = 0;
1185
1186 /*
1187 * Disable the "fast interrupt" prediction.
1188 */
1189 pci_read_config_byte(dev, 0x51, &drive_fast);
1190 if (drive_fast & 0x80)
1191 pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
1192 pci_read_config_dword(dev, 0x40, &reg1);
1193
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 return 0;
1195}
1196
1197static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
1198{
1199 int ret = 0;
Linus Torvalds9ec4ff42005-09-11 09:22:50 -07001200
1201 /*
1202 * FIXME: Not portable. Also, why do we enable the ROM in the first place?
1203 * We don't seem to be using it.
1204 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 if (dev->resource[PCI_ROM_RESOURCE].start)
Linus Torvalds9ec4ff42005-09-11 09:22:50 -07001206 pci_write_config_dword(dev, PCI_ROM_ADDRESS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
1208
Alan Coxb39b01f2005-06-27 15:24:27 -07001209 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
1210 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
1211 pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
1212 pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
Alan Coxb39b01f2005-06-27 15:24:27 -07001214 if (hpt_revision(dev) >= 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 ret = init_hpt37x(dev);
Alan Coxb39b01f2005-06-27 15:24:27 -07001216 else
1217 ret = init_hpt366(dev);
1218
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 if (ret)
1220 return ret;
1221
1222 return dev->irq;
1223}
1224
1225static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
1226{
1227 struct pci_dev *dev = hwif->pci_dev;
Alan Coxb39b01f2005-06-27 15:24:27 -07001228 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02;
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001230 int serialize = HPT_SERIALIZE_IO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 hwif->tuneproc = &hpt3xx_tune_drive;
1233 hwif->speedproc = &hpt3xx_tune_chipset;
1234 hwif->quirkproc = &hpt3xx_quirkproc;
1235 hwif->intrproc = &hpt3xx_intrproc;
1236 hwif->maskproc = &hpt3xx_maskproc;
1237
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001238 /*
1239 * HPT3xxN chips have some complications:
1240 *
1241 * - on 33 MHz PCI we must clock switch
1242 * - on 66 MHz PCI we must NOT use the PCI clock
1243 */
1244 if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) {
1245 /*
1246 * Clock is shared between the channels,
1247 * so we'll have to serialize them... :-(
1248 */
1249 serialize = 1;
1250 hwif->rw_disk = &hpt3xxn_rw_disk;
1251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
1253 /*
1254 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
1255 * address lines to access an external eeprom. To read valid
1256 * cable detect state the pins must be enabled as inputs.
1257 */
Alan Coxb39b01f2005-06-27 15:24:27 -07001258 if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 /*
1260 * HPT374 PCI function 1
1261 * - set bit 15 of reg 0x52 to enable TCBLID as input
1262 * - set bit 15 of reg 0x56 to enable FCBLID as input
1263 */
1264 u16 mcr3, mcr6;
1265 pci_read_config_word(dev, 0x52, &mcr3);
1266 pci_read_config_word(dev, 0x56, &mcr6);
1267 pci_write_config_word(dev, 0x52, mcr3 | 0x8000);
1268 pci_write_config_word(dev, 0x56, mcr6 | 0x8000);
1269 /* now read cable id register */
1270 pci_read_config_byte(dev, 0x5a, &ata66);
1271 pci_write_config_word(dev, 0x52, mcr3);
1272 pci_write_config_word(dev, 0x56, mcr6);
Alan Coxb39b01f2005-06-27 15:24:27 -07001273 } else if (info->revision >= 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 /*
1275 * HPT370/372 and 374 pcifn 0
1276 * - clear bit 0 of 0x5b to enable P/SCBLID as inputs
1277 */
1278 u8 scr2;
1279 pci_read_config_byte(dev, 0x5b, &scr2);
1280 pci_write_config_byte(dev, 0x5b, scr2 & ~1);
1281 /* now read cable id register */
1282 pci_read_config_byte(dev, 0x5a, &ata66);
1283 pci_write_config_byte(dev, 0x5b, scr2);
1284 } else {
1285 pci_read_config_byte(dev, 0x5a, &ata66);
1286 }
1287
1288#ifdef DEBUG
1289 printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n",
1290 ata66, (ata66 & regmask) ? "33" : "66",
1291 PCI_FUNC(hwif->pci_dev->devfn));
1292#endif /* DEBUG */
1293
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001294 /* Serialize access to this device */
1295 if (serialize && hwif->mate)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 hwif->serialized = hwif->mate->serialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297
Sergei Shtylyov33b18a62006-12-13 00:35:50 -08001298 /*
1299 * Set up ioctl for power status.
1300 * NOTE: power affects both drives on each channel.
1301 */
1302 hwif->busproc = &hpt3xx_busproc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
1304 if (!hwif->dma_base) {
1305 hwif->drives[0].autotune = 1;
1306 hwif->drives[1].autotune = 1;
1307 return;
1308 }
1309
1310 hwif->ultra_mask = 0x7f;
1311 hwif->mwdma_mask = 0x07;
1312
1313 if (!(hwif->udma_four))
1314 hwif->udma_four = ((ata66 & regmask) ? 0 : 1);
1315 hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
1316
Alan Coxb39b01f2005-06-27 15:24:27 -07001317 if (info->revision >= 8) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
1319 hwif->ide_dma_end = &hpt374_ide_dma_end;
Alan Coxb39b01f2005-06-27 15:24:27 -07001320 } else if (info->revision >= 5) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
1322 hwif->ide_dma_end = &hpt374_ide_dma_end;
Alan Coxb39b01f2005-06-27 15:24:27 -07001323 } else if (info->revision >= 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 hwif->dma_start = &hpt370_ide_dma_start;
1325 hwif->ide_dma_end = &hpt370_ide_dma_end;
1326 hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
1327 hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq;
Alan Coxb39b01f2005-06-27 15:24:27 -07001328 } else if (info->revision >= 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
1330 else
1331 hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
1332
1333 if (!noautodma)
1334 hwif->autodma = 1;
1335 hwif->drives[0].autodma = hwif->autodma;
1336 hwif->drives[1].autodma = hwif->autodma;
1337}
1338
1339static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
1340{
Alan Coxb39b01f2005-06-27 15:24:27 -07001341 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 u8 masterdma = 0, slavedma = 0;
1343 u8 dma_new = 0, dma_old = 0;
1344 u8 primary = hwif->channel ? 0x4b : 0x43;
1345 u8 secondary = hwif->channel ? 0x4f : 0x47;
1346 unsigned long flags;
1347
1348 if (!dmabase)
1349 return;
1350
Alan Coxb39b01f2005-06-27 15:24:27 -07001351 if(info->speed == NULL) {
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001352 printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 return;
1354 }
1355
1356 dma_old = hwif->INB(dmabase+2);
1357
1358 local_irq_save(flags);
1359
1360 dma_new = dma_old;
1361 pci_read_config_byte(hwif->pci_dev, primary, &masterdma);
1362 pci_read_config_byte(hwif->pci_dev, secondary, &slavedma);
1363
1364 if (masterdma & 0x30) dma_new |= 0x20;
1365 if (slavedma & 0x30) dma_new |= 0x40;
1366 if (dma_new != dma_old)
1367 hwif->OUTB(dma_new, dmabase+2);
1368
1369 local_irq_restore(flags);
1370
1371 ide_setup_dma(hwif, dmabase, 8);
1372}
1373
Alan Coxb39b01f2005-06-27 15:24:27 -07001374/*
1375 * We "borrow" this hook in order to set the data structures
1376 * up early enough before dma or init_hwif calls are made.
1377 */
1378
1379static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
1380{
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001381 struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
1382 struct pci_dev *dev = hwif->pci_dev;
1383 u16 did = dev->device;
1384 u8 rid = 0;
Alan Coxb39b01f2005-06-27 15:24:27 -07001385
1386 if(info == NULL) {
1387 printk(KERN_WARNING "hpt366: out of memory.\n");
1388 return;
1389 }
Alan Coxb39b01f2005-06-27 15:24:27 -07001390 ide_set_hwifdata(hwif, info);
1391
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001392 /* Avoid doing the same thing twice. */
1393 if (hwif->channel && hwif->mate) {
1394 memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info));
1395 return;
Alan Coxb39b01f2005-06-27 15:24:27 -07001396 }
1397
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001398 pci_read_config_byte(dev, PCI_CLASS_REVISION, &rid);
1399
1400 if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) ||
1401 ((did == PCI_DEVICE_ID_TTI_HPT372 ||
1402 did == PCI_DEVICE_ID_TTI_HPT302 ||
1403 did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) ||
1404 did == PCI_DEVICE_ID_TTI_HPT372N)
1405 info->flags |= IS_3xxN;
1406
1407 info->revision = hpt_revision(dev);
Alan Coxb39b01f2005-06-27 15:24:27 -07001408
1409 if (info->revision >= 3)
1410 hpt37x_clocking(hwif);
1411 else
1412 hpt366_clocking(hwif);
1413}
1414
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d)
1416{
1417 struct pci_dev *findev = NULL;
1418
1419 if (PCI_FUNC(dev->devfn) & 1)
1420 return -ENODEV;
1421
1422 while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
1423 if ((findev->vendor == dev->vendor) &&
1424 (findev->device == dev->device) &&
1425 ((findev->devfn - dev->devfn) == 1) &&
1426 (PCI_FUNC(findev->devfn) & 1)) {
1427 if (findev->irq != dev->irq) {
1428 /* FIXME: we need a core pci_set_interrupt() */
1429 findev->irq = dev->irq;
1430 printk(KERN_WARNING "%s: pci-config space interrupt "
1431 "fixed.\n", d->name);
1432 }
1433 return ide_setup_pci_devices(dev, findev, d);
1434 }
1435 }
1436 return ide_setup_pci_device(dev, d);
1437}
1438
1439static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d)
1440{
1441 return ide_setup_pci_device(dev, d);
1442}
1443
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001444static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
1445{
1446 u8 mcr1 = 0;
1447
1448 /*
1449 * HPT371 chips physically have only one channel, the secondary one,
1450 * but the primary channel registers do exist! Go figure...
1451 * So, we manually disable the non-existing channel here
1452 * (if the BIOS hasn't done this already).
1453 */
1454 pci_read_config_byte(dev, 0x50, &mcr1);
1455 if (mcr1 & 0x04)
1456 pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04));
1457
1458 return ide_setup_pci_device(dev, d);
1459}
1460
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
1462{
1463 struct pci_dev *findev = NULL;
1464 u8 pin1 = 0, pin2 = 0;
1465 unsigned int class_rev;
1466 char *chipset_names[] = {"HPT366", "HPT366", "HPT368",
1467 "HPT370", "HPT370A", "HPT372",
1468 "HPT372N" };
1469
1470 if (PCI_FUNC(dev->devfn) & 1)
1471 return -ENODEV;
1472
1473 pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
1474 class_rev &= 0xff;
1475
1476 if(dev->device == PCI_DEVICE_ID_TTI_HPT372N)
1477 class_rev = 6;
1478
1479 if(class_rev <= 6)
1480 d->name = chipset_names[class_rev];
1481
1482 switch(class_rev) {
1483 case 6:
1484 case 5:
1485 case 4:
1486 case 3:
1487 goto init_single;
1488 default:
1489 break;
1490 }
1491
1492 d->channels = 1;
1493
1494 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
1495 while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
1496 if ((findev->vendor == dev->vendor) &&
1497 (findev->device == dev->device) &&
1498 ((findev->devfn - dev->devfn) == 1) &&
1499 (PCI_FUNC(findev->devfn) & 1)) {
1500 pci_read_config_byte(findev, PCI_INTERRUPT_PIN, &pin2);
1501 if ((pin1 != pin2) && (dev->irq == findev->irq)) {
1502 d->bootable = ON_BOARD;
1503 printk("%s: onboard version of chipset, "
1504 "pin1=%d pin2=%d\n", d->name,
1505 pin1, pin2);
1506 }
1507 return ide_setup_pci_devices(dev, findev, d);
1508 }
1509 }
1510init_single:
1511 return ide_setup_pci_device(dev, d);
1512}
1513
1514static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
1515 { /* 0 */
1516 .name = "HPT366",
1517 .init_setup = init_setup_hpt366,
1518 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001519 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 .init_hwif = init_hwif_hpt366,
1521 .init_dma = init_dma_hpt366,
1522 .channels = 2,
1523 .autodma = AUTODMA,
1524 .bootable = OFF_BOARD,
1525 .extra = 240
1526 },{ /* 1 */
1527 .name = "HPT372A",
1528 .init_setup = init_setup_hpt37x,
1529 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001530 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 .init_hwif = init_hwif_hpt366,
1532 .init_dma = init_dma_hpt366,
1533 .channels = 2,
1534 .autodma = AUTODMA,
1535 .bootable = OFF_BOARD,
1536 },{ /* 2 */
1537 .name = "HPT302",
1538 .init_setup = init_setup_hpt37x,
1539 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001540 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 .init_hwif = init_hwif_hpt366,
1542 .init_dma = init_dma_hpt366,
1543 .channels = 2,
1544 .autodma = AUTODMA,
1545 .bootable = OFF_BOARD,
1546 },{ /* 3 */
1547 .name = "HPT371",
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001548 .init_setup = init_setup_hpt371,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001550 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 .init_hwif = init_hwif_hpt366,
1552 .init_dma = init_dma_hpt366,
1553 .channels = 2,
1554 .autodma = AUTODMA,
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001555 .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 .bootable = OFF_BOARD,
1557 },{ /* 4 */
1558 .name = "HPT374",
1559 .init_setup = init_setup_hpt374,
1560 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001561 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 .init_hwif = init_hwif_hpt366,
1563 .init_dma = init_dma_hpt366,
1564 .channels = 2, /* 4 */
1565 .autodma = AUTODMA,
1566 .bootable = OFF_BOARD,
1567 },{ /* 5 */
1568 .name = "HPT372N",
1569 .init_setup = init_setup_hpt37x,
1570 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001571 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 .init_hwif = init_hwif_hpt366,
1573 .init_dma = init_dma_hpt366,
1574 .channels = 2, /* 4 */
1575 .autodma = AUTODMA,
1576 .bootable = OFF_BOARD,
1577 }
1578};
1579
1580/**
1581 * hpt366_init_one - called when an HPT366 is found
1582 * @dev: the hpt366 device
1583 * @id: the matching pci id
1584 *
1585 * Called when the PCI registration layer (or the IDE initialization)
1586 * finds a device matching our IDE device tables.
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -08001587 *
1588 * NOTE: since we'll have to modify some fields of the ide_pci_device_t
1589 * structure depending on the chip's revision, we'd better pass a local
1590 * copy down the call chain...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
1593{
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -08001594 ide_pci_device_t d = hpt366_chipsets[id->driver_data];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -08001596 return d.init_setup(dev, &d);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597}
1598
1599static struct pci_device_id hpt366_pci_tbl[] = {
1600 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
1601 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
1602 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
1603 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
1604 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
1605 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
1606 { 0, },
1607};
1608MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
1609
1610static struct pci_driver driver = {
1611 .name = "HPT366_IDE",
1612 .id_table = hpt366_pci_tbl,
1613 .probe = hpt366_init_one,
1614};
1615
1616static int hpt366_ide_init(void)
1617{
1618 return ide_pci_register_driver(&driver);
1619}
1620
1621module_init(hpt366_ide_init);
1622
1623MODULE_AUTHOR("Andre Hedrick");
1624MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
1625MODULE_LICENSE("GPL");