Blame view

drivers/ide/hpt366.c 42.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
   * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
   * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
   * Portions Copyright (C) 2003		Red Hat Inc
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
5
   * Portions Copyright (C) 2007		Bartlomiej Zolnierkiewicz
59c8d04f5   Sergei Shtylyov   hpt366: use ATA_D...
6
   * Portions Copyright (C) 2005-2009	MontaVista Software, Inc.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
   *
   * Thanks to HighPoint Technologies for their assistance, and hardware.
   * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
   * donation of an ABit BP6 mainboard, processor, and memory acellerated
   * development and support.
   *
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
13
   *
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
14
   * HighPoint has its own drivers (open source except for the RAID part)
631dd1a88   Justin P. Mattock   Update broken web...
15
   * available from http://www.highpoint-tech.com/USA_new/service_support.htm 
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
16
17
18
   * This may be useful to anyone wanting to work on this driver, however  do not
   * trust  them too much since the code tends to become less and less meaningful
   * as the time passes... :-/
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
19
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
   * Note that final HPT370 support was done by force extraction of GPL.
   *
   * - add function for getting/setting power status of drive
   * - the HPT370's state machine can get confused. reset it before each dma 
   *   xfer to prevent that from happening.
   * - reset state engine whenever we get an error.
   * - check for busmaster state at end of dma. 
   * - use new highpoint timings.
   * - detect bus speed using highpoint register.
   * - use pll if we don't have a clock table. added a 66MHz table that's
   *   just 2x the 33MHz table.
   * - removed turnaround. NOTE: we never want to switch between pll and
   *   pci clocks as the chip can glitch in those cases. the highpoint
   *   approved workaround slows everything down too much to be useful. in
   *   addition, we would have to serialize access to each chip.
   * 	Adrian Sun <a.sun@sun.com>
   *
   * add drive timings for 66MHz PCI bus,
   * fix ATA Cable signal detection, fix incorrect /proc info
   * add /proc display for per-drive PIO/DMA/UDMA mode and
   * per-channel ATA-33/66 Cable detect.
   * 	Duncan Laurie <void@sun.com>
   *
   * fixup /proc output for multiple controllers
   *	Tim Hockin <thockin@sun.com>
   *
   * On hpt366: 
   * Reset the hpt366 on error, reset on dma
   * Fix disabling Fast Interrupt hpt366.
   * 	Mike Waychison <crlf@sun.com>
   *
   * Added support for 372N clocking and clock switching. The 372N needs
   * different clocks on read/write. This requires overloading rw_disk and
   * other deeply crazy things. Thanks to <http://www.hoerstreich.de> for
   * keeping me sane. 
ccd32e221   Alan Cox   ide: Switch to a ...
55
   *		Alan Cox <alan@lxorguk.ukuu.org.uk>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
   *
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
57
58
59
60
61
   * - fix the clock turnaround code: it was writing to the wrong ports when
   *   called for the secondary channel, caching the current clock mode per-
   *   channel caused the cached register value to get out of sync with the
   *   actual one, the channels weren't serialized, the turnaround shouldn't
   *   be done on 66 MHz PCI bus
7b73ee05d   Sergei Shtylyov   hpt366: init code...
62
63
64
65
   * - disable UltraATA/100 for HPT370 by default as the 33 MHz clock being used
   *   does not allow for this speed anyway
   * - avoid touching disabled channels (e.g. HPT371/N are single channel chips,
   *   their primary channel is kind of virtual, it isn't tied to any pins)
471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
66
67
68
   * - fix/remove bad/unused timing tables and use one set of tables for the whole
   *   HPT37x chip family; save space by introducing the separate transfer mode
   *   table in which the mode lookup is done
26c068daf   Sergei Shtylyov   [PATCH] ide: HPT3...
69
   * - use f_CNT value saved by  the HighPoint BIOS as reading it directly gives
729313681   Sergei Shtylyov   hpt366: fix PCI c...
70
71
   *   the wrong PCI frequency since DPLL has already been calibrated by BIOS;
   *   read it only from the function 0 of HPT374 chips
33b18a602   Sergei Shtylyov   [PATCH] ide: fix ...
72
73
   * - fix the hotswap code:  it caused RESET- to glitch when tristating the bus,
   *   and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
73d1dd93c   Sergei Shtylyov   [PATCH] ide: fix ...
74
75
   * - pass to init_chipset() handlers a copy of the IDE PCI device structure as
   *   they tamper with its fields
7b73ee05d   Sergei Shtylyov   hpt366: init code...
76
77
   * - pass  to the init_setup handlers a copy of the ide_pci_device_t structure
   *   since they may tamper with its fields
90778574c   Sergei Shtylyov   hpt366: print the...
78
79
   * - prefix the driver startup messages with the real chip name
   * - claim the extra 240 bytes of I/O space for all chips
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
80
   * - optimize the UltraDMA filtering and the drive list lookup code
b4586715d   Sergei Shtylyov   hpt366: switch to...
81
   * - use pci_get_slot() to get to the function 1 of HPT36x/374
7b73ee05d   Sergei Shtylyov   hpt366: init code...
82
83
84
85
   * - cache offset of the channel's misc. control registers (MCRs) being used
   *   throughout the driver
   * - only touch the relevant MCR when detecting the cable type on HPT374's
   *   function 1
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
86
   * - rename all the register related variables consistently
7b73ee05d   Sergei Shtylyov   hpt366: init code...
87
88
   * - move all the interrupt twiddling code from the speedproc handlers into
   *   init_hwif_hpt366(), also grouping all the DMA related code together there
866664d79   Sergei Shtylyov   hpt366: merge set...
89
   * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and
7b73ee05d   Sergei Shtylyov   hpt366: init code...
90
91
92
93
   *   separate the UltraDMA and MWDMA masks there to avoid changing PIO timings
   *   when setting an UltraDMA mode
   * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select
   *   the best possible one
4bf63de27   Sergei Shtylyov   hpt366: clean up ...
94
   * - clean up DMA timeout handling for HPT370
7b73ee05d   Sergei Shtylyov   hpt366: init code...
95
96
97
98
99
100
101
   * - switch to using the enumeration type to differ between the numerous chip
   *   variants, matching PCI device/revision ID with the chip type early, at the
   *   init_setup stage
   * - extend the hpt_info structure to hold the DPLL and PCI clock frequencies,
   *   stop duplicating it for each channel by storing the pointer in the pci_dev
   *   structure: first, at the init_setup stage, point it to a static "template"
   *   with only the chip type and its specific base DPLL frequency, the highest
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
102
103
104
   *   UltraDMA mode, and the chip settings table pointer filled,  then, at the
   *   init_chipset stage, allocate per-chip instance  and fill it with the rest
   *   of the necessary information
7b73ee05d   Sergei Shtylyov   hpt366: init code...
105
106
107
108
   * - get rid of the constant thresholds in the HPT37x PCI clock detection code,
   *   switch  to calculating  PCI clock frequency based on the chip's base DPLL
   *   frequency
   * - switch to using the  DPLL clock and enable UltraATA/133 mode by default on
278978e95   Sergei Shtylyov   hpt366: disallow ...
109
110
   *   anything  newer than HPT370/A (except HPT374 that is not capable of this
   *   mode according to the manual)
6273d26a5   Sergei Shtylyov   hpt366: HPT36x PC...
111
112
   * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(),
   *   also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
113
114
   *   unify HPT36x/37x timing setup code and the speedproc handlers by joining
   *   the register setting lists into the table indexed by the clock selected
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
115
   * - set the correct hwif->ultra_mask for each individual chip
b4e44369a   Sergei Shtylyov   hpt366: MWDMA fil...
116
   * - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards
c018f1ee5   Sergei Shtylyov   hpt366: fix HPT37...
117
118
   * - stop resetting HPT370's state machine before each DMA transfer as that has
   *   caused more harm than good
7b73ee05d   Sergei Shtylyov   hpt366: init code...
119
   *	Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
  #include <linux/types.h>
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/delay.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  #include <linux/blkdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
  #include <linux/interrupt.h>
  #include <linux/pci.h>
  #include <linux/init.h>
  #include <linux/ide.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
130
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
  
  #include <asm/uaccess.h>
  #include <asm/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134

ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
135
  #define DRV_NAME "hpt366"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  /* various tuning parameters */
c018f1ee5   Sergei Shtylyov   hpt366: fix HPT37...
137
  #undef	HPT_RESET_STATE_ENGINE
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
138
  #undef	HPT_DELAY_INTERRUPT
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
  static const char *bad_ata100_5[] = {
  	"IBM-DTLA-307075",
  	"IBM-DTLA-307060",
  	"IBM-DTLA-307045",
  	"IBM-DTLA-307030",
  	"IBM-DTLA-307020",
  	"IBM-DTLA-307015",
  	"IBM-DTLA-305040",
  	"IBM-DTLA-305030",
  	"IBM-DTLA-305020",
  	"IC35L010AVER07-0",
  	"IC35L020AVER07-0",
  	"IC35L030AVER07-0",
  	"IC35L040AVER07-0",
  	"IC35L060AVER07-0",
  	"WDC AC310200R",
  	NULL
  };
  
  static const char *bad_ata66_4[] = {
  	"IBM-DTLA-307075",
  	"IBM-DTLA-307060",
  	"IBM-DTLA-307045",
  	"IBM-DTLA-307030",
  	"IBM-DTLA-307020",
  	"IBM-DTLA-307015",
  	"IBM-DTLA-305040",
  	"IBM-DTLA-305030",
  	"IBM-DTLA-305020",
  	"IC35L010AVER07-0",
  	"IC35L020AVER07-0",
  	"IC35L030AVER07-0",
  	"IC35L040AVER07-0",
  	"IC35L060AVER07-0",
  	"WDC AC310200R",
783353b1d   Sergei Shtylyov   hpt366: blacklist...
175
  	"MAXTOR STM3320620A",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  	NULL
  };
  
  static const char *bad_ata66_3[] = {
  	"WDC AC310200R",
  	NULL
  };
  
  static const char *bad_ata33[] = {
  	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
  	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
  	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
  	"Maxtor 90510D4",
  	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
  	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
  	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
  	NULL
  };
471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  static u8 xfer_speeds[] = {
  	XFER_UDMA_6,
  	XFER_UDMA_5,
  	XFER_UDMA_4,
  	XFER_UDMA_3,
  	XFER_UDMA_2,
  	XFER_UDMA_1,
  	XFER_UDMA_0,
  
  	XFER_MW_DMA_2,
  	XFER_MW_DMA_1,
  	XFER_MW_DMA_0,
  
  	XFER_PIO_4,
  	XFER_PIO_3,
  	XFER_PIO_2,
  	XFER_PIO_1,
  	XFER_PIO_0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  };
471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  /* Key for bus clock timings
   * 36x   37x
   * bits  bits
   * 0:3	 0:3	data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
   *		cycles = value + 1
   * 4:7	 4:8	data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
   *		cycles = value + 1
   * 8:11  9:12	cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
   *		register access.
   * 12:15 13:17	cmd_low_time. Active time of DIOW_/DIOR_ during task file
   *		register access.
   * 16:18 18:20	udma_cycle_time. Clock cycles for UDMA xfer.
   * -	 21	CLK frequency: 0=ATA clock, 1=dual ATA clock.
   * 19:21 22:24	pre_high_time. Time to initialize the 1st cycle for PIO and
   *		MW DMA xfer.
   * 22:24 25:27	cmd_pre_high_time. Time to initialize the 1st PIO cycle for
   *		task file register access.
   * 28	 28	UDMA enable.
   * 29	 29	DMA  enable.
   * 30	 30	PIO MST enable. If set, the chip is in bus master mode during
   *		PIO xfer.
   * 31	 31	FIFO enable.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236

471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  static u32 forty_base_hpt36x[] = {
  	/* XFER_UDMA_6 */	0x900fd943,
  	/* XFER_UDMA_5 */	0x900fd943,
  	/* XFER_UDMA_4 */	0x900fd943,
  	/* XFER_UDMA_3 */	0x900ad943,
  	/* XFER_UDMA_2 */	0x900bd943,
  	/* XFER_UDMA_1 */	0x9008d943,
  	/* XFER_UDMA_0 */	0x9008d943,
  
  	/* XFER_MW_DMA_2 */	0xa008d943,
  	/* XFER_MW_DMA_1 */	0xa010d955,
  	/* XFER_MW_DMA_0 */	0xa010d9fc,
  
  	/* XFER_PIO_4 */	0xc008d963,
  	/* XFER_PIO_3 */	0xc010d974,
  	/* XFER_PIO_2 */	0xc010d997,
  	/* XFER_PIO_1 */	0xc010d9c7,
  	/* XFER_PIO_0 */	0xc018d9d9
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  };
471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  static u32 thirty_three_base_hpt36x[] = {
  	/* XFER_UDMA_6 */	0x90c9a731,
  	/* XFER_UDMA_5 */	0x90c9a731,
  	/* XFER_UDMA_4 */	0x90c9a731,
  	/* XFER_UDMA_3 */	0x90cfa731,
  	/* XFER_UDMA_2 */	0x90caa731,
  	/* XFER_UDMA_1 */	0x90cba731,
  	/* XFER_UDMA_0 */	0x90c8a731,
  
  	/* XFER_MW_DMA_2 */	0xa0c8a731,
  	/* XFER_MW_DMA_1 */	0xa0c8a732,	/* 0xa0c8a733 */
  	/* XFER_MW_DMA_0 */	0xa0c8a797,
  
  	/* XFER_PIO_4 */	0xc0c8a731,
  	/* XFER_PIO_3 */	0xc0c8a742,
  	/* XFER_PIO_2 */	0xc0d0a753,
  	/* XFER_PIO_1 */	0xc0d0a7a3,	/* 0xc0d0a793 */
  	/* XFER_PIO_0 */	0xc0d0a7aa	/* 0xc0d0a7a7 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  };
471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  static u32 twenty_five_base_hpt36x[] = {
  	/* XFER_UDMA_6 */	0x90c98521,
  	/* XFER_UDMA_5 */	0x90c98521,
  	/* XFER_UDMA_4 */	0x90c98521,
  	/* XFER_UDMA_3 */	0x90cf8521,
  	/* XFER_UDMA_2 */	0x90cf8521,
  	/* XFER_UDMA_1 */	0x90cb8521,
  	/* XFER_UDMA_0 */	0x90cb8521,
  
  	/* XFER_MW_DMA_2 */	0xa0ca8521,
  	/* XFER_MW_DMA_1 */	0xa0ca8532,
  	/* XFER_MW_DMA_0 */	0xa0ca8575,
  
  	/* XFER_PIO_4 */	0xc0ca8521,
  	/* XFER_PIO_3 */	0xc0ca8532,
  	/* XFER_PIO_2 */	0xc0ca8542,
  	/* XFER_PIO_1 */	0xc0d08572,
  	/* XFER_PIO_0 */	0xc0d08585
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  };
809b53c4e   Sergei Shtylyov   hpt366: fix HPT37...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  /*
   * The following are the new timing tables with PIO mode data/taskfile transfer
   * overclocking fixed...
   */
  
  /* This table is taken from the HPT370 data manual rev. 1.02 */
  static u32 thirty_three_base_hpt37x[] = {
  	/* XFER_UDMA_6 */	0x16455031,	/* 0x16655031 ?? */
  	/* XFER_UDMA_5 */	0x16455031,
  	/* XFER_UDMA_4 */	0x16455031,
  	/* XFER_UDMA_3 */	0x166d5031,
  	/* XFER_UDMA_2 */	0x16495031,
  	/* XFER_UDMA_1 */	0x164d5033,
  	/* XFER_UDMA_0 */	0x16515097,
  
  	/* XFER_MW_DMA_2 */	0x26515031,
  	/* XFER_MW_DMA_1 */	0x26515033,
  	/* XFER_MW_DMA_0 */	0x26515097,
  
  	/* XFER_PIO_4 */	0x06515021,
  	/* XFER_PIO_3 */	0x06515022,
  	/* XFER_PIO_2 */	0x06515033,
  	/* XFER_PIO_1 */	0x06915065,
  	/* XFER_PIO_0 */	0x06d1508a
  };
  
  static u32 fifty_base_hpt37x[] = {
  	/* XFER_UDMA_6 */	0x1a861842,
  	/* XFER_UDMA_5 */	0x1a861842,
  	/* XFER_UDMA_4 */	0x1aae1842,
  	/* XFER_UDMA_3 */	0x1a8e1842,
  	/* XFER_UDMA_2 */	0x1a0e1842,
  	/* XFER_UDMA_1 */	0x1a161854,
  	/* XFER_UDMA_0 */	0x1a1a18ea,
  
  	/* XFER_MW_DMA_2 */	0x2a821842,
  	/* XFER_MW_DMA_1 */	0x2a821854,
  	/* XFER_MW_DMA_0 */	0x2a8218ea,
  
  	/* XFER_PIO_4 */	0x0a821842,
  	/* XFER_PIO_3 */	0x0a821843,
  	/* XFER_PIO_2 */	0x0a821855,
  	/* XFER_PIO_1 */	0x0ac218a8,
  	/* XFER_PIO_0 */	0x0b02190c
  };
  
  static u32 sixty_six_base_hpt37x[] = {
  	/* XFER_UDMA_6 */	0x1c86fe62,
  	/* XFER_UDMA_5 */	0x1caefe62,	/* 0x1c8afe62 */
  	/* XFER_UDMA_4 */	0x1c8afe62,
  	/* XFER_UDMA_3 */	0x1c8efe62,
  	/* XFER_UDMA_2 */	0x1c92fe62,
  	/* XFER_UDMA_1 */	0x1c9afe62,
  	/* XFER_UDMA_0 */	0x1c82fe62,
  
  	/* XFER_MW_DMA_2 */	0x2c82fe62,
  	/* XFER_MW_DMA_1 */	0x2c82fe66,
  	/* XFER_MW_DMA_0 */	0x2c82ff2e,
  
  	/* XFER_PIO_4 */	0x0c82fe62,
  	/* XFER_PIO_3 */	0x0c82fe84,
  	/* XFER_PIO_2 */	0x0c82fea6,
  	/* XFER_PIO_1 */	0x0d02ff26,
  	/* XFER_PIO_0 */	0x0d42ff7f
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359

7b73ee05d   Sergei Shtylyov   hpt366: init code...
360
361
362
  #define HPT371_ALLOW_ATA133_6		1
  #define HPT302_ALLOW_ATA133_6		1
  #define HPT372_ALLOW_ATA133_6		1
e139b0b02   Sergei Shtylyov   hpt366: rework ra...
363
  #define HPT370_ALLOW_ATA100_5		0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
  #define HPT366_ALLOW_ATA66_4		1
  #define HPT366_ALLOW_ATA66_3		1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366

7b73ee05d   Sergei Shtylyov   hpt366: init code...
367
368
369
370
371
372
373
374
375
  /* Supported ATA clock frequencies */
  enum ata_clock {
  	ATA_CLOCK_25MHZ,
  	ATA_CLOCK_33MHZ,
  	ATA_CLOCK_40MHZ,
  	ATA_CLOCK_50MHZ,
  	ATA_CLOCK_66MHZ,
  	NUM_ATA_CLOCKS
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376

866664d79   Sergei Shtylyov   hpt366: merge set...
377
378
379
380
381
382
  struct hpt_timings {
  	u32 pio_mask;
  	u32 dma_mask;
  	u32 ultra_mask;
  	u32 *clock_table[NUM_ATA_CLOCKS];
  };
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
383
  /*
7b73ee05d   Sergei Shtylyov   hpt366: init code...
384
   *	Hold all the HighPoint chip information in one place.
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
385
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386

7b73ee05d   Sergei Shtylyov   hpt366: init code...
387
  struct hpt_info {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
388
  	char *chip_name;	/* Chip name */
7b73ee05d   Sergei Shtylyov   hpt366: init code...
389
  	u8 chip_type;		/* Chip type */
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
390
  	u8 udma_mask;		/* Allowed UltraDMA modes mask. */
7b73ee05d   Sergei Shtylyov   hpt366: init code...
391
392
  	u8 dpll_clk;		/* DPLL clock in MHz */
  	u8 pci_clk;		/* PCI  clock in MHz */
866664d79   Sergei Shtylyov   hpt366: merge set...
393
394
  	struct hpt_timings *timings; /* Chipset timing data */
  	u8 clock;		/* ATA clock selected */
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
395
  };
7b73ee05d   Sergei Shtylyov   hpt366: init code...
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  /* Supported HighPoint chips */
  enum {
  	HPT36x,
  	HPT370,
  	HPT370A,
  	HPT374,
  	HPT372,
  	HPT372A,
  	HPT302,
  	HPT371,
  	HPT372N,
  	HPT302N,
  	HPT371N
  };
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
410

866664d79   Sergei Shtylyov   hpt366: merge set...
411
412
413
414
415
416
417
418
419
420
421
  static struct hpt_timings hpt36x_timings = {
  	.pio_mask	= 0xc1f8ffff,
  	.dma_mask	= 0x303800ff,
  	.ultra_mask	= 0x30070000,
  	.clock_table	= {
  		[ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x,
  		[ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x,
  		[ATA_CLOCK_40MHZ] = forty_base_hpt36x,
  		[ATA_CLOCK_50MHZ] = NULL,
  		[ATA_CLOCK_66MHZ] = NULL
  	}
7b73ee05d   Sergei Shtylyov   hpt366: init code...
422
  };
e139b0b02   Sergei Shtylyov   hpt366: rework ra...
423

866664d79   Sergei Shtylyov   hpt366: merge set...
424
425
426
427
428
429
430
431
432
433
434
  static struct hpt_timings hpt37x_timings = {
  	.pio_mask	= 0xcfc3ffff,
  	.dma_mask	= 0x31c001ff,
  	.ultra_mask	= 0x303c0000,
  	.clock_table	= {
  		[ATA_CLOCK_25MHZ] = NULL,
  		[ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x,
  		[ATA_CLOCK_40MHZ] = NULL,
  		[ATA_CLOCK_50MHZ] = fifty_base_hpt37x,
  		[ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x
  	}
7b73ee05d   Sergei Shtylyov   hpt366: init code...
435
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436

282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
437
  static const struct hpt_info hpt36x __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
438
  	.chip_name	= "HPT36x",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
439
  	.chip_type	= HPT36x,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
440
  	.udma_mask	= HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
441
  	.dpll_clk	= 0,	/* no DPLL */
866664d79   Sergei Shtylyov   hpt366: merge set...
442
  	.timings	= &hpt36x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
443
  };
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
444
  static const struct hpt_info hpt370 __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
445
  	.chip_name	= "HPT370",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
446
  	.chip_type	= HPT370,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
447
  	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
448
  	.dpll_clk	= 48,
866664d79   Sergei Shtylyov   hpt366: merge set...
449
  	.timings	= &hpt37x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
450
  };
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
451
  static const struct hpt_info hpt370a __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
452
  	.chip_name	= "HPT370A",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
453
  	.chip_type	= HPT370A,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
454
  	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
455
  	.dpll_clk	= 48,
866664d79   Sergei Shtylyov   hpt366: merge set...
456
  	.timings	= &hpt37x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
457
  };
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
458
  static const struct hpt_info hpt374 __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
459
  	.chip_name	= "HPT374",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
460
  	.chip_type	= HPT374,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
461
  	.udma_mask	= ATA_UDMA5,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
462
  	.dpll_clk	= 48,
866664d79   Sergei Shtylyov   hpt366: merge set...
463
  	.timings	= &hpt37x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
464
  };
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
465
  static const struct hpt_info hpt372 __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
466
  	.chip_name	= "HPT372",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
467
  	.chip_type	= HPT372,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
468
  	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
469
  	.dpll_clk	= 55,
866664d79   Sergei Shtylyov   hpt366: merge set...
470
  	.timings	= &hpt37x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
471
  };
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
472
  static const struct hpt_info hpt372a __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
473
  	.chip_name	= "HPT372A",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
474
  	.chip_type	= HPT372A,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
475
  	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
476
  	.dpll_clk	= 66,
866664d79   Sergei Shtylyov   hpt366: merge set...
477
  	.timings	= &hpt37x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
478
  };
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
479
  static const struct hpt_info hpt302 __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
480
  	.chip_name	= "HPT302",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
481
  	.chip_type	= HPT302,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
482
  	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
483
  	.dpll_clk	= 66,
866664d79   Sergei Shtylyov   hpt366: merge set...
484
  	.timings	= &hpt37x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
485
  };
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
486
  static const struct hpt_info hpt371 __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
487
  	.chip_name	= "HPT371",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
488
  	.chip_type	= HPT371,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
489
  	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
490
  	.dpll_clk	= 66,
866664d79   Sergei Shtylyov   hpt366: merge set...
491
  	.timings	= &hpt37x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
492
  };
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
493
  static const struct hpt_info hpt372n __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
494
  	.chip_name	= "HPT372N",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
495
  	.chip_type	= HPT372N,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
496
  	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
497
  	.dpll_clk	= 77,
866664d79   Sergei Shtylyov   hpt366: merge set...
498
  	.timings	= &hpt37x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
499
  };
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
500
  static const struct hpt_info hpt302n __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
501
  	.chip_name	= "HPT302N",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
502
  	.chip_type	= HPT302N,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
503
  	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
504
  	.dpll_clk	= 77,
866664d79   Sergei Shtylyov   hpt366: merge set...
505
  	.timings	= &hpt37x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
506
  };
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
507
  static const struct hpt_info hpt371n __devinitdata = {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
508
  	.chip_name	= "HPT371N",
7b73ee05d   Sergei Shtylyov   hpt366: init code...
509
  	.chip_type	= HPT371N,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
510
  	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
511
  	.dpll_clk	= 77,
866664d79   Sergei Shtylyov   hpt366: merge set...
512
  	.timings	= &hpt37x_timings
7b73ee05d   Sergei Shtylyov   hpt366: init code...
513
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514

e139b0b02   Sergei Shtylyov   hpt366: rework ra...
515
516
  static int check_in_drive_list(ide_drive_t *drive, const char **list)
  {
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
517
  	char *m = (char *)&drive->id[ATA_ID_PROD];
e139b0b02   Sergei Shtylyov   hpt366: rework ra...
518
519
  
  	while (*list)
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
520
  		if (!strcmp(*list++, m))
e139b0b02   Sergei Shtylyov   hpt366: rework ra...
521
522
523
  			return 1;
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524

62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
525
526
527
528
529
530
531
  static struct hpt_info *hpt3xx_get_info(struct device *dev)
  {
  	struct ide_host *host	= dev_get_drvdata(dev);
  	struct hpt_info *info	= (struct hpt_info *)host->host_priv;
  
  	return dev == host->dev[1] ? info + 1 : info;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
  /*
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
533
534
   * The Marvell bridge chips used on the HighPoint SATA cards do not seem
   * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
   */
2d5eaa6dd   Bartlomiej Zolnierkiewicz   ide: rework the c...
536
537
  
  static u8 hpt3xx_udma_filter(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
539
  	ide_hwif_t *hwif	= drive->hwif;
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
540
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
541
  	u8 mask 		= hwif->ultra_mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542

2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
543
  	switch (info->chip_type) {
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
544
545
546
  	case HPT36x:
  		if (!HPT366_ALLOW_ATA66_4 ||
  		    check_in_drive_list(drive, bad_ata66_4))
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
547
  			mask = ATA_UDMA3;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
548

2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
549
550
  		if (!HPT366_ALLOW_ATA66_3 ||
  		    check_in_drive_list(drive, bad_ata66_3))
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
551
  			mask = ATA_UDMA2;
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
552
  		break;
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
553
554
555
556
557
558
559
560
561
562
563
564
565
  	case HPT370:
  		if (!HPT370_ALLOW_ATA100_5 ||
  		    check_in_drive_list(drive, bad_ata100_5))
  			mask = ATA_UDMA4;
  		break;
  	case HPT370A:
  		if (!HPT370_ALLOW_ATA100_5 ||
  		    check_in_drive_list(drive, bad_ata100_5))
  			return ATA_UDMA4;
  	case HPT372 :
  	case HPT372A:
  	case HPT372N:
  	case HPT374 :
367d7e78d   Bartlomiej Zolnierkiewicz   ide: ide_dev_is_s...
566
  		if (ata_id_is_sata(drive->id))
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
567
568
  			mask &= ~0x0e;
  		/* Fall thru */
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
569
  	default:
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
570
  		return mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
  	}
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
572
573
  
  	return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
  }
b4e44369a   Sergei Shtylyov   hpt366: MWDMA fil...
575
576
  static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
577
  	ide_hwif_t *hwif	= drive->hwif;
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
578
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
b4e44369a   Sergei Shtylyov   hpt366: MWDMA fil...
579
580
581
582
583
584
  
  	switch (info->chip_type) {
  	case HPT372 :
  	case HPT372A:
  	case HPT372N:
  	case HPT374 :
367d7e78d   Bartlomiej Zolnierkiewicz   ide: ide_dev_is_s...
585
  		if (ata_id_is_sata(drive->id))
b4e44369a   Sergei Shtylyov   hpt366: MWDMA fil...
586
587
588
589
590
591
  			return 0x00;
  		/* Fall thru */
  	default:
  		return 0x07;
  	}
  }
7b73ee05d   Sergei Shtylyov   hpt366: init code...
592
  static u32 get_speed_setting(u8 speed, struct hpt_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
  {
471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
594
595
596
597
598
599
600
601
602
603
604
  	int i;
  
  	/*
  	 * Lookup the transfer mode table to get the index into
  	 * the timing table.
  	 *
  	 * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.
  	 */
  	for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
  		if (xfer_speeds[i] == speed)
  			break;
866664d79   Sergei Shtylyov   hpt366: merge set...
605
606
  
  	return info->timings->clock_table[info->clock][i];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
  }
8776168ca   Bartlomiej Zolnierkiewicz   ide: change ->set...
608
  static void hpt3xx_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  {
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
610
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
611
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
866664d79   Sergei Shtylyov   hpt366: merge set...
612
613
  	struct hpt_timings *t	= info->timings;
  	u8  itr_addr		= 0x40 + (drive->dn * 4);
26ccb802e   Sergei Shtylyov   hpt366: merge HPT...
614
  	u32 old_itr		= 0;
8776168ca   Bartlomiej Zolnierkiewicz   ide: change ->set...
615
  	const u8 speed		= drive->dma_mode;
ceb1b2c58   Sergei Shtylyov   hpt366: change ti...
616
  	u32 new_itr		= get_speed_setting(speed, info);
866664d79   Sergei Shtylyov   hpt366: merge set...
617
618
619
  	u32 itr_mask		= speed < XFER_MW_DMA_0 ? t->pio_mask :
  				 (speed < XFER_UDMA_0   ? t->dma_mask :
  							  t->ultra_mask);
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
620

ceb1b2c58   Sergei Shtylyov   hpt366: change ti...
621
622
  	pci_read_config_dword(dev, itr_addr, &old_itr);
  	new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
  	/*
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
624
625
  	 * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
  	 * to avoid problems handling I/O errors later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
  	 */
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
627
  	new_itr &= ~0xc0000000;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628

abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
629
  	pci_write_config_dword(dev, itr_addr, new_itr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
  }
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
631
  static void hpt3xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  {
8776168ca   Bartlomiej Zolnierkiewicz   ide: change ->set...
633
634
  	drive->dma_mode = drive->pio_mode;
  	hpt3xx_set_mode(hwif, drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
  }
26ccb802e   Sergei Shtylyov   hpt366: merge HPT...
636
  static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
638
  	ide_hwif_t *hwif	= drive->hwif;
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
639
  	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
640
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641

734affdca   Bartlomiej Zolnierkiewicz   ide: add IDE_DFLA...
642
  	if ((drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0)
ea2ac5a3b   Sergei Shtylyov   hpt366: cleanup m...
643
644
645
646
647
648
649
  		return;
  
  	if (info->chip_type >= HPT370) {
  		u8 scr1 = 0;
  
  		pci_read_config_byte(dev, 0x5a, &scr1);
  		if (((scr1 & 0x10) >> 4) != mask) {
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
650
  			if (mask)
ea2ac5a3b   Sergei Shtylyov   hpt366: cleanup m...
651
  				scr1 |=  0x10;
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
652
  			else
ea2ac5a3b   Sergei Shtylyov   hpt366: cleanup m...
653
654
  				scr1 &= ~0x10;
  			pci_write_config_byte(dev, 0x5a, scr1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
  		}
ea2ac5a3b   Sergei Shtylyov   hpt366: cleanup m...
656
657
658
659
  	} else if (mask)
  		disable_irq(hwif->irq);
  	else
  		enable_irq(hwif->irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
  /*
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
662
   * This is specific to the HPT366 UDMA chipset
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
664
   * by HighPoint|Triones Technologies, Inc.
   */
841d2a9bf   Sergei Shtylyov   ide: make void an...
665
  static void hpt366_dma_lost_irq(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
  {
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
667
  	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
668
669
670
671
672
673
674
  	u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
  
  	pci_read_config_byte(dev, 0x50, &mcr1);
  	pci_read_config_byte(dev, 0x52, &mcr3);
  	pci_read_config_byte(dev, 0x5a, &scr1);
  	printk("%s: (%s)  mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x
  ",
eb63963a5   Harvey Harrison   ide: replace rema...
675
  		drive->name, __func__, mcr1, mcr3, scr1);
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
676
677
  	if (scr1 & 0x10)
  		pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
841d2a9bf   Sergei Shtylyov   ide: make void an...
678
  	ide_dma_lost_irq(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
  }
4bf63de27   Sergei Shtylyov   hpt366: clean up ...
680
  static void hpt370_clear_engine(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
682
  	ide_hwif_t *hwif = drive->hwif;
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
683
  	struct pci_dev *dev = to_pci_dev(hwif->dev);
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
684

36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
685
  	pci_write_config_byte(dev, hwif->select_data, 0x37);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
  	udelay(10);
  }
4bf63de27   Sergei Shtylyov   hpt366: clean up ...
688
689
  static void hpt370_irq_timeout(ide_drive_t *drive)
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
690
  	ide_hwif_t *hwif	= drive->hwif;
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
691
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
4bf63de27   Sergei Shtylyov   hpt366: clean up ...
692
693
  	u16 bfifo		= 0;
  	u8  dma_cmd;
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
694
  	pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
4bf63de27   Sergei Shtylyov   hpt366: clean up ...
695
696
697
698
  	printk(KERN_DEBUG "%s: %d bytes in FIFO
  ", drive->name, bfifo & 0x1ff);
  
  	/* get DMA command mode */
cab7f8eda   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
699
  	dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
4bf63de27   Sergei Shtylyov   hpt366: clean up ...
700
  	/* stop DMA */
59c8d04f5   Sergei Shtylyov   hpt366: use ATA_D...
701
  	outb(dma_cmd & ~ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD);
4bf63de27   Sergei Shtylyov   hpt366: clean up ...
702
703
  	hpt370_clear_engine(drive);
  }
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
704
  static void hpt370_dma_start(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
707
708
709
710
  {
  #ifdef HPT_RESET_STATE_ENGINE
  	hpt370_clear_engine(drive);
  #endif
  	ide_dma_start(drive);
  }
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
711
  static int hpt370_dma_end(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
712
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
713
  	ide_hwif_t *hwif	= drive->hwif;
cab7f8eda   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
714
  	u8  dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715

59c8d04f5   Sergei Shtylyov   hpt366: use ATA_D...
716
  	if (dma_stat & ATA_DMA_ACTIVE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
718
  		/* wait a little */
  		udelay(20);
cab7f8eda   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
719
  		dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
59c8d04f5   Sergei Shtylyov   hpt366: use ATA_D...
720
  		if (dma_stat & ATA_DMA_ACTIVE)
4bf63de27   Sergei Shtylyov   hpt366: clean up ...
721
  			hpt370_irq_timeout(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
  	}
653bcf529   Bartlomiej Zolnierkiewicz   ide: __ide_dma_en...
723
  	return ide_dma_end(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725
  /* returns 1 if DMA IRQ issued, 0 otherwise */
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
726
  static int hpt374_dma_test_irq(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
728
  	ide_hwif_t *hwif	= drive->hwif;
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
729
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
  	u16 bfifo		= 0;
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
731
  	u8  dma_stat;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732

36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
733
  	pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
738
  	if (bfifo & 0x1FF) {
  //		printk("%s: %d bytes in FIFO
  ", drive->name, bfifo);
  		return 0;
  	}
cab7f8eda   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
739
  	dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
  	/* return 1 if INTR asserted */
59c8d04f5   Sergei Shtylyov   hpt366: use ATA_D...
741
  	if (dma_stat & ATA_DMA_INTR)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
  	return 0;
  }
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
745
  static int hpt374_dma_end(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
747
  	ide_hwif_t *hwif	= drive->hwif;
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
748
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
749
750
751
752
753
754
755
  	u8 mcr	= 0, mcr_addr	= hwif->select_data;
  	u8 bwsr = 0, mask	= hwif->channel ? 0x02 : 0x01;
  
  	pci_read_config_byte(dev, 0x6a, &bwsr);
  	pci_read_config_byte(dev, mcr_addr, &mcr);
  	if (bwsr & mask)
  		pci_write_config_byte(dev, mcr_addr, mcr | 0x30);
653bcf529   Bartlomiej Zolnierkiewicz   ide: __ide_dma_en...
756
  	return ide_dma_end(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
759
  }
  
  /**
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
760
761
762
   *	hpt3xxn_set_clock	-	perform clock switching dance
   *	@hwif: hwif to switch
   *	@mode: clocking mode (0x21 for write, 0x23 otherwise)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
   *
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
764
   *	Switch the DPLL clock on the HPT3xxN devices. This is a	right mess.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
   */
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
766
767
  
  static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
  {
1c029fd65   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
769
770
  	unsigned long base = hwif->extra_base;
  	u8 scr2 = inb(base + 0x6b);
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
771
772
773
  
  	if ((scr2 & 0x7f) == mode)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
  	/* Tristate the bus */
1c029fd65   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
775
776
  	outb(0x80, base + 0x63);
  	outb(0x80, base + 0x67);
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
777

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
  	/* Switch clock and reset channels */
1c029fd65   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
779
780
  	outb(mode, base + 0x6b);
  	outb(0xc0, base + 0x69);
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
781

7b73ee05d   Sergei Shtylyov   hpt366: init code...
782
783
784
785
  	/*
  	 * Reset the state machines.
  	 * NOTE: avoid accidentally enabling the disabled channels.
  	 */
1c029fd65   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
786
787
  	outb(inb(base + 0x60) | 0x32, base + 0x60);
  	outb(inb(base + 0x64) | 0x32, base + 0x64);
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
788

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  	/* Complete reset */
1c029fd65   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
790
  	outb(0x00, base + 0x69);
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
791

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
  	/* Reconnect channels to bus */
1c029fd65   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
793
794
  	outb(0x00, base + 0x63);
  	outb(0x00, base + 0x67);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
796
797
  }
  
  /**
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
798
   *	hpt3xxn_rw_disk		-	prepare for I/O
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
800
801
   *	@drive: drive for command
   *	@rq: block request structure
   *
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
802
   *	This is called when a disk I/O is issued to HPT3xxN.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
804
   *	We need it because of the clock switching.
   */
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
805
  static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
  {
bbe54d78c   Sergei Shtylyov   hpt366: fix clock...
807
  	hpt3xxn_set_clock(drive->hwif, rq_data_dir(rq) ? 0x21 : 0x23);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
  }
7b73ee05d   Sergei Shtylyov   hpt366: init code...
809
810
811
812
813
814
815
  /**
   *	hpt37x_calibrate_dpll	-	calibrate the DPLL
   *	@dev: PCI device
   *
   *	Perform a calibration cycle on the DPLL.
   *	Returns 1 if this succeeds
   */
feb22b7f8   Bartlomiej Zolnierkiewicz   ide: add proper P...
816
  static int hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
  {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
818
819
820
  	u32 dpll = (f_high << 16) | f_low | 0x100;
  	u8  scr2;
  	int i;
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
821

7b73ee05d   Sergei Shtylyov   hpt366: init code...
822
  	pci_write_config_dword(dev, 0x5c, dpll);
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
823

7b73ee05d   Sergei Shtylyov   hpt366: init code...
824
825
826
827
828
  	/* Wait for oscillator ready */
  	for(i = 0; i < 0x5000; ++i) {
  		udelay(50);
  		pci_read_config_byte(dev, 0x5b, &scr2);
  		if (scr2 & 0x80)
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
829
830
  			break;
  	}
7b73ee05d   Sergei Shtylyov   hpt366: init code...
831
832
833
834
835
836
837
838
839
840
841
  	/* See if it stays ready (we'll just bail out if it's not yet) */
  	for(i = 0; i < 0x1000; ++i) {
  		pci_read_config_byte(dev, 0x5b, &scr2);
  		/* DPLL destabilized? */
  		if(!(scr2 & 0x80))
  			return 0;
  	}
  	/* Turn off tuning, we have the DPLL set */
  	pci_read_config_dword (dev, 0x5c, &dpll);
  	pci_write_config_dword(dev, 0x5c, (dpll & ~0x100));
  	return 1;
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
842
  }
feb22b7f8   Bartlomiej Zolnierkiewicz   ide: add proper P...
843
  static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr)
1785192b5   Bartlomiej Zolnierkiewicz   hpt366: add hpt3x...
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
  {
  	struct ide_host *host	= pci_get_drvdata(dev);
  	struct hpt_info *info	= host->host_priv + (&dev->dev == host->dev[1]);
  	u8  chip_type		= info->chip_type;
  	u8  new_mcr, old_mcr	= 0;
  
  	/*
  	 * Disable the "fast interrupt" prediction.  Don't hold off
  	 * on interrupts. (== 0x01 despite what the docs say)
  	 */
  	pci_read_config_byte(dev, mcr_addr + 1, &old_mcr);
  
  	if (chip_type >= HPT374)
  		new_mcr = old_mcr & ~0x07;
  	else if (chip_type >= HPT370) {
  		new_mcr = old_mcr;
  		new_mcr &= ~0x02;
  #ifdef HPT_DELAY_INTERRUPT
  		new_mcr &= ~0x01;
  #else
  		new_mcr |=  0x01;
  #endif
  	} else					/* HPT366 and HPT368  */
  		new_mcr = old_mcr & ~0x80;
  
  	if (new_mcr != old_mcr)
  		pci_write_config_byte(dev, mcr_addr + 1, new_mcr);
  }
2ed0ef543   Bartlomiej Zolnierkiewicz   ide: fix ->init_c...
872
  static int init_chipset_hpt366(struct pci_dev *dev)
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
873
  {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
874
  	unsigned long io_base	= pci_resource_start(dev, 4);
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
875
  	struct hpt_info *info	= hpt3xx_get_info(&dev->dev);
a326b02b0   Bartlomiej Zolnierkiewicz   ide: drop 'name' ...
876
  	const char *name	= DRV_NAME;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
877
  	u8 pci_clk,  dpll_clk	= 0;	/* PCI and DPLL clock in MHz */
729313681   Sergei Shtylyov   hpt366: fix PCI c...
878
  	u8 chip_type;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
879
  	enum ata_clock	clock;
729313681   Sergei Shtylyov   hpt366: fix PCI c...
880
  	chip_type = info->chip_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881

7b73ee05d   Sergei Shtylyov   hpt366: init code...
882
883
884
885
  	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
  	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
  	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
  	pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
26c068daf   Sergei Shtylyov   [PATCH] ide: HPT3...
886

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
887
  	/*
7b73ee05d   Sergei Shtylyov   hpt366: init code...
888
  	 * First, try to estimate the PCI clock frequency...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
  	 */
729313681   Sergei Shtylyov   hpt366: fix PCI c...
890
  	if (chip_type >= HPT370) {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
891
892
893
894
895
896
897
898
899
900
901
902
903
  		u8  scr1  = 0;
  		u16 f_cnt = 0;
  		u32 temp  = 0;
  
  		/* Interrupt force enable. */
  		pci_read_config_byte(dev, 0x5a, &scr1);
  		if (scr1 & 0x10)
  			pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
  
  		/*
  		 * HighPoint does this for HPT372A.
  		 * NOTE: This register is only writeable via I/O space.
  		 */
729313681   Sergei Shtylyov   hpt366: fix PCI c...
904
  		if (chip_type == HPT372A)
7b73ee05d   Sergei Shtylyov   hpt366: init code...
905
906
907
908
909
910
911
  			outb(0x0e, io_base + 0x9c);
  
  		/*
  		 * Default to PCI clock. Make sure MA15/16 are set to output
  		 * to prevent drives having problems with 40-pin cables.
  		 */
  		pci_write_config_byte(dev, 0x5b, 0x23);
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
912

7b73ee05d   Sergei Shtylyov   hpt366: init code...
913
914
915
916
917
918
919
920
921
  		/*
  		 * We'll have to read f_CNT value in order to determine
  		 * the PCI clock frequency according to the following ratio:
  		 *
  		 * f_CNT = Fpci * 192 / Fdpll
  		 *
  		 * First try reading the register in which the HighPoint BIOS
  		 * saves f_CNT value before  reprogramming the DPLL from its
  		 * default setting (which differs for the various chips).
7b73ee05d   Sergei Shtylyov   hpt366: init code...
922
  		 *
729313681   Sergei Shtylyov   hpt366: fix PCI c...
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
  		 * NOTE: This register is only accessible via I/O space;
  		 * HPT374 BIOS only saves it for the function 0, so we have to
  		 * always read it from there -- no need to check the result of
  		 * pci_get_slot() for the function 0 as the whole device has
  		 * been already "pinned" (via function 1) in init_setup_hpt374()
  		 */
  		if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
  			struct pci_dev	*dev1 = pci_get_slot(dev->bus,
  							     dev->devfn - 1);
  			unsigned long io_base = pci_resource_start(dev1, 4);
  
  			temp =	inl(io_base + 0x90);
  			pci_dev_put(dev1);
  		} else
  			temp =	inl(io_base + 0x90);
  
  		/*
  		 * In case the signature check fails, we'll have to
  		 * resort to reading the f_CNT register itself in hopes
  		 * that nobody has touched the DPLL yet...
7b73ee05d   Sergei Shtylyov   hpt366: init code...
943
  		 */
7b73ee05d   Sergei Shtylyov   hpt366: init code...
944
945
  		if ((temp & 0xFFFFF000) != 0xABCDE000) {
  			int i;
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
946
947
948
  			printk(KERN_WARNING "%s %s: no clock data saved by "
  				"BIOS
  ", name, pci_name(dev));
7b73ee05d   Sergei Shtylyov   hpt366: init code...
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
  
  			/* Calculate the average value of f_CNT. */
  			for (temp = i = 0; i < 128; i++) {
  				pci_read_config_word(dev, 0x78, &f_cnt);
  				temp += f_cnt & 0x1ff;
  				mdelay(1);
  			}
  			f_cnt = temp / 128;
  		} else
  			f_cnt = temp & 0x1ff;
  
  		dpll_clk = info->dpll_clk;
  		pci_clk  = (f_cnt * dpll_clk) / 192;
  
  		/* Clamp PCI clock to bands. */
  		if (pci_clk < 40)
  			pci_clk = 33;
  		else if(pci_clk < 45)
  			pci_clk = 40;
  		else if(pci_clk < 55)
  			pci_clk = 50;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
  		else
7b73ee05d   Sergei Shtylyov   hpt366: init code...
971
  			pci_clk = 66;
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
972

28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
973
974
975
976
  		printk(KERN_INFO "%s %s: DPLL base: %d MHz, f_CNT: %d, "
  			"assuming %d MHz PCI
  ", name, pci_name(dev),
  			dpll_clk, f_cnt, pci_clk);
90778574c   Sergei Shtylyov   hpt366: print the...
977
  	} else {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
978
979
980
981
982
983
984
985
  		u32 itr1 = 0;
  
  		pci_read_config_dword(dev, 0x40, &itr1);
  
  		/* Detect PCI clock by looking at cmd_high_time. */
  		switch((itr1 >> 8) & 0x07) {
  			case 0x09:
  				pci_clk = 40;
6273d26a5   Sergei Shtylyov   hpt366: HPT36x PC...
986
  				break;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
987
988
  			case 0x05:
  				pci_clk = 25;
6273d26a5   Sergei Shtylyov   hpt366: HPT36x PC...
989
  				break;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
990
991
992
  			case 0x07:
  			default:
  				pci_clk = 33;
6273d26a5   Sergei Shtylyov   hpt366: HPT36x PC...
993
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
995
  		}
  	}
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
996

7b73ee05d   Sergei Shtylyov   hpt366: init code...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
  	/* Let's assume we'll use PCI clock for the ATA clock... */
  	switch (pci_clk) {
  		case 25:
  			clock = ATA_CLOCK_25MHZ;
  			break;
  		case 33:
  		default:
  			clock = ATA_CLOCK_33MHZ;
  			break;
  		case 40:
  			clock = ATA_CLOCK_40MHZ;
  			break;
  		case 50:
  			clock = ATA_CLOCK_50MHZ;
  			break;
  		case 66:
  			clock = ATA_CLOCK_66MHZ;
  			break;
  	}
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1016

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
  	/*
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1018
1019
  	 * Only try the DPLL if we don't have a table for the PCI clock that
  	 * we are running at for HPT370/A, always use it  for anything newer...
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
1020
  	 *
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1021
1022
1023
  	 * NOTE: Using the internal DPLL results in slow reads on 33 MHz PCI.
  	 * We also  don't like using  the DPLL because this causes glitches
  	 * on PRST-/SRST- when the state engine gets reset...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024
  	 */
866664d79   Sergei Shtylyov   hpt366: merge set...
1025
  	if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1026
1027
1028
1029
1030
1031
1032
  		u16 f_low, delta = pci_clk < 50 ? 2 : 4;
  		int adjust;
  
  		 /*
  		  * Select 66 MHz DPLL clock only if UltraATA/133 mode is
  		  * supported/enabled, use 50 MHz DPLL clock otherwise...
  		  */
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1033
  		if (info->udma_mask == ATA_UDMA6) {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1034
1035
1036
1037
1038
1039
  			dpll_clk = 66;
  			clock = ATA_CLOCK_66MHZ;
  		} else if (dpll_clk) {	/* HPT36x chips don't have DPLL */
  			dpll_clk = 50;
  			clock = ATA_CLOCK_50MHZ;
  		}
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
1040

866664d79   Sergei Shtylyov   hpt366: merge set...
1041
  		if (info->timings->clock_table[clock] == NULL) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1042
1043
1044
  			printk(KERN_ERR "%s %s: unknown bus timing!
  ",
  				name, pci_name(dev));
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1045
  			return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1046
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047

7b73ee05d   Sergei Shtylyov   hpt366: init code...
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
  		/* Select the DPLL clock. */
  		pci_write_config_byte(dev, 0x5b, 0x21);
  
  		/*
  		 * Adjust the DPLL based upon PCI clock, enable it,
  		 * and wait for stabilization...
  		 */
  		f_low = (pci_clk * 48) / dpll_clk;
  
  		for (adjust = 0; adjust < 8; adjust++) {
  			if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta))
  				break;
  
  			/*
  			 * See if it'll settle at a fractionally different clock
  			 */
  			if (adjust & 1)
  				f_low -= adjust >> 1;
  			else
  				f_low += adjust >> 1;
  		}
  		if (adjust == 8) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1070
1071
1072
  			printk(KERN_ERR "%s %s: DPLL did not stabilize!
  ",
  				name, pci_name(dev));
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1073
1074
  			return -EIO;
  		}
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1075
1076
1077
  		printk(KERN_INFO "%s %s: using %d MHz DPLL clock
  ",
  			name, pci_name(dev), dpll_clk);
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1078
1079
1080
  	} else {
  		/* Mark the fact that we're not using the DPLL. */
  		dpll_clk = 0;
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1081
1082
1083
  		printk(KERN_INFO "%s %s: using %d MHz PCI clock
  ",
  			name, pci_name(dev), pci_clk);
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1084
  	}
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
1085

7b73ee05d   Sergei Shtylyov   hpt366: init code...
1086
1087
1088
  	/* Store the clock frequencies. */
  	info->dpll_clk	= dpll_clk;
  	info->pci_clk	= pci_clk;
866664d79   Sergei Shtylyov   hpt366: merge set...
1089
  	info->clock	= clock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1090

729313681   Sergei Shtylyov   hpt366: fix PCI c...
1091
  	if (chip_type >= HPT370) {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
  		u8  mcr1, mcr4;
  
  		/*
  		 * Reset the state engines.
  		 * NOTE: Avoid accidentally enabling the disabled channels.
  		 */
  		pci_read_config_byte (dev, 0x50, &mcr1);
  		pci_read_config_byte (dev, 0x54, &mcr4);
  		pci_write_config_byte(dev, 0x50, (mcr1 | 0x32));
  		pci_write_config_byte(dev, 0x54, (mcr4 | 0x32));
  		udelay(100);
26ccb802e   Sergei Shtylyov   hpt366: merge HPT...
1103
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1104

7b73ee05d   Sergei Shtylyov   hpt366: init code...
1105
1106
1107
1108
1109
  	/*
  	 * On  HPT371N, if ATA clock is 66 MHz we must set bit 2 in
  	 * the MISC. register to stretch the UltraDMA Tss timing.
  	 * NOTE: This register is only writeable via I/O space.
  	 */
729313681   Sergei Shtylyov   hpt366: fix PCI c...
1110
  	if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ)
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1111
  		outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c);
1785192b5   Bartlomiej Zolnierkiewicz   hpt366: add hpt3x...
1112
1113
  	hpt3xx_disable_fast_irq(dev, 0x50);
  	hpt3xx_disable_fast_irq(dev, 0x54);
2ed0ef543   Bartlomiej Zolnierkiewicz   ide: fix ->init_c...
1114
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
  }
f454cbe8c   Bartlomiej Zolnierkiewicz   ide: ->cable_dete...
1116
  static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
bfa14b42a   Bartlomiej Zolnierkiewicz   ide: add ->cable_...
1117
1118
  {
  	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
1119
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
bfa14b42a   Bartlomiej Zolnierkiewicz   ide: add ->cable_...
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
  	u8 chip_type		= info->chip_type;
  	u8 scr1 = 0, ata66	= hwif->channel ? 0x01 : 0x02;
  
  	/*
  	 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
  	 * address lines to access an external EEPROM.  To read valid
  	 * cable detect state the pins must be enabled as inputs.
  	 */
  	if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
  		/*
  		 * HPT374 PCI function 1
  		 * - set bit 15 of reg 0x52 to enable TCBLID as input
  		 * - set bit 15 of reg 0x56 to enable FCBLID as input
  		 */
  		u8  mcr_addr = hwif->select_data + 2;
  		u16 mcr;
  
  		pci_read_config_word(dev, mcr_addr, &mcr);
5d3f1a493   Sergei Shtylyov   hpt366: add debou...
1138
1139
1140
  		pci_write_config_word(dev, mcr_addr, mcr | 0x8000);
  		/* Debounce, then read cable ID register */
  		udelay(10);
bfa14b42a   Bartlomiej Zolnierkiewicz   ide: add ->cable_...
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
  		pci_read_config_byte(dev, 0x5a, &scr1);
  		pci_write_config_word(dev, mcr_addr, mcr);
  	} else if (chip_type >= HPT370) {
  		/*
  		 * HPT370/372 and 374 pcifn 0
  		 * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
  		 */
  		u8 scr2 = 0;
  
  		pci_read_config_byte(dev, 0x5b, &scr2);
5d3f1a493   Sergei Shtylyov   hpt366: add debou...
1151
1152
1153
  		pci_write_config_byte(dev, 0x5b, scr2 & ~1);
  		/* Debounce, then read cable ID register */
  		udelay(10);
bfa14b42a   Bartlomiej Zolnierkiewicz   ide: add ->cable_...
1154
  		pci_read_config_byte(dev, 0x5a, &scr1);
5d3f1a493   Sergei Shtylyov   hpt366: add debou...
1155
  		pci_write_config_byte(dev, 0x5b, scr2);
bfa14b42a   Bartlomiej Zolnierkiewicz   ide: add ->cable_...
1156
1157
1158
1159
1160
  	} else
  		pci_read_config_byte(dev, 0x5a, &scr1);
  
  	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161
1162
  static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
  {
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
1163
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
1164
  	u8  chip_type		= info->chip_type;
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
1165
1166
  
  	/* Cache the channel's MISC. control registers' offset */
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
1167
  	hwif->select_data	= hwif->channel ? 0x54 : 0x50;
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
1168

836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1169
1170
1171
1172
1173
1174
  	/*
  	 * HPT3xxN chips have some complications:
  	 *
  	 * - on 33 MHz PCI we must clock switch
  	 * - on 66 MHz PCI we must NOT use the PCI clock
  	 */
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1175
  	if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) {
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1176
1177
1178
1179
  		/*
  		 * Clock is shared between the channels,
  		 * so we'll have to serialize them... :-(
  		 */
702c026be   Bartlomiej Zolnierkiewicz   ide: rework handl...
1180
  		hwif->host->host_flags |= IDE_HFLAG_SERIALIZE;
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1181
1182
  		hwif->rw_disk = &hpt3xxn_rw_disk;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
  }
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
1184
1185
  static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
  				     const struct ide_port_info *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
  {
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
1187
  	struct pci_dev *dev = to_pci_dev(hwif->dev);
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
1188
1189
  	unsigned long flags, base = ide_pci_dma_base(hwif, d);
  	u8 dma_old, dma_new, masterdma = 0, slavedma = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190

ebb00fb55   Bartlomiej Zolnierkiewicz   ide: factor out s...
1191
1192
1193
1194
1195
1196
1197
1198
1199
  	if (base == 0)
  		return -1;
  
  	hwif->dma_base = base;
  
  	if (ide_pci_check_simplex(hwif, d) < 0)
  		return -1;
  
  	if (ide_pci_set_master(dev, d->name) < 0)
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
1200
1201
1202
  		return -1;
  
  	dma_old = inb(base + 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1203
1204
1205
1206
  
  	local_irq_save(flags);
  
  	dma_new = dma_old;
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
1207
1208
  	pci_read_config_byte(dev, hwif->channel ? 0x4b : 0x43, &masterdma);
  	pci_read_config_byte(dev, hwif->channel ? 0x4f : 0x47,  &slavedma);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
1210
  
  	if (masterdma & 0x30)	dma_new |= 0x20;
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
1211
  	if ( slavedma & 0x30)	dma_new |= 0x40;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1212
  	if (dma_new != dma_old)
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
1213
  		outb(dma_new, base + 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
1215
  
  	local_irq_restore(flags);
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
1216
1217
1218
1219
1220
1221
1222
1223
1224
  
  	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx
  ",
  			 hwif->name, base, base + 7);
  
  	hwif->extra_base = base + (hwif->channel ? 8 : 16);
  
  	if (ide_allocate_dma_engine(hwif))
  		return -1;
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
1225
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
  }
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1227
  static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
  {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1229
1230
1231
  	if (dev2->irq != dev->irq) {
  		/* FIXME: we need a core pci_set_interrupt() */
  		dev2->irq = dev->irq;
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
1232
  		printk(KERN_INFO DRV_NAME " %s: PCI config space interrupt "
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1233
1234
  			"fixed
  ", pci_name(dev2));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
  }
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1237
  static void __devinit hpt371_init(struct pci_dev *dev)
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1238
  {
44c10138f   Auke Kok   PCI: Change all d...
1239
  	u8 mcr1 = 0;
90778574c   Sergei Shtylyov   hpt366: print the...
1240

836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1241
1242
1243
1244
1245
1246
1247
1248
  	/*
  	 * HPT371 chips physically have only one channel, the secondary one,
  	 * but the primary channel registers do exist!  Go figure...
  	 * So,  we manually disable the non-existing channel here
  	 * (if the BIOS hasn't done this already).
  	 */
  	pci_read_config_byte(dev, 0x50, &mcr1);
  	if (mcr1 & 0x04)
90778574c   Sergei Shtylyov   hpt366: print the...
1249
  		pci_write_config_byte(dev, 0x50, mcr1 & ~0x04);
90778574c   Sergei Shtylyov   hpt366: print the...
1250
  }
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1251
  static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
90778574c   Sergei Shtylyov   hpt366: print the...
1252
  {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1253
  	u8 mcr1 = 0, pin1 = 0, pin2 = 0;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1254

fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1255
1256
1257
1258
1259
1260
1261
  	/*
  	 * Now we'll have to force both channels enabled if
  	 * at least one of them has been enabled by BIOS...
  	 */
  	pci_read_config_byte(dev, 0x50, &mcr1);
  	if (mcr1 & 0x30)
  		pci_write_config_byte(dev, 0x50, mcr1 | 0x30);
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1262

fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1263
1264
  	pci_read_config_byte(dev,  PCI_INTERRUPT_PIN, &pin1);
  	pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1265

fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1266
  	if (pin1 != pin2 && dev->irq == dev2->irq) {
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
1267
  		printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, "
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1268
1269
  			"pin1=%d pin2=%d
  ", pci_name(dev), pin1, pin2);
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1270
  		return 1;
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
1271
  	}
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1272
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
  }
4db90a145   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
1274
1275
  #define IDE_HFLAGS_HPT3XX \
  	(IDE_HFLAG_NO_ATAPI_DMA | \
4db90a145   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
1276
  	 IDE_HFLAG_OFF_BOARD)
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
1277
1278
1279
  static const struct ide_port_ops hpt3xx_port_ops = {
  	.set_pio_mode		= hpt3xx_set_pio_mode,
  	.set_dma_mode		= hpt3xx_set_mode,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
1280
1281
1282
1283
1284
  	.maskproc		= hpt3xx_maskproc,
  	.mdma_filter		= hpt3xx_mdma_filter,
  	.udma_filter		= hpt3xx_udma_filter,
  	.cable_detect		= hpt3xx_cable_detect,
  };
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1285
1286
1287
  static const struct ide_dma_ops hpt37x_dma_ops = {
  	.dma_host_set		= ide_dma_host_set,
  	.dma_setup		= ide_dma_setup,
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1288
  	.dma_start		= ide_dma_start,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1289
1290
  	.dma_end		= hpt374_dma_end,
  	.dma_test_irq		= hpt374_dma_test_irq,
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1291
  	.dma_lost_irq		= ide_dma_lost_irq,
22117d6ea   Bartlomiej Zolnierkiewicz   ide: add ->dma_ti...
1292
  	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
592b53152   Sergei Shtylyov   ide: move read_sf...
1293
  	.dma_sff_read_status	= ide_dma_sff_read_status,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1294
  };
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1295
1296
1297
  static const struct ide_dma_ops hpt370_dma_ops = {
  	.dma_host_set		= ide_dma_host_set,
  	.dma_setup		= ide_dma_setup,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1298
1299
  	.dma_start		= hpt370_dma_start,
  	.dma_end		= hpt370_dma_end,
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1300
1301
  	.dma_test_irq		= ide_dma_test_irq,
  	.dma_lost_irq		= ide_dma_lost_irq,
22117d6ea   Bartlomiej Zolnierkiewicz   ide: add ->dma_ti...
1302
  	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
35c9b4daf   Bartlomiej Zolnierkiewicz   ide: add ->dma_cl...
1303
  	.dma_clear		= hpt370_irq_timeout,
592b53152   Sergei Shtylyov   ide: move read_sf...
1304
  	.dma_sff_read_status	= ide_dma_sff_read_status,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1305
  };
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1306
1307
1308
  static const struct ide_dma_ops hpt36x_dma_ops = {
  	.dma_host_set		= ide_dma_host_set,
  	.dma_setup		= ide_dma_setup,
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1309
  	.dma_start		= ide_dma_start,
653bcf529   Bartlomiej Zolnierkiewicz   ide: __ide_dma_en...
1310
  	.dma_end		= ide_dma_end,
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1311
  	.dma_test_irq		= ide_dma_test_irq,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1312
  	.dma_lost_irq		= hpt366_dma_lost_irq,
22117d6ea   Bartlomiej Zolnierkiewicz   ide: add ->dma_ti...
1313
  	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
592b53152   Sergei Shtylyov   ide: move read_sf...
1314
  	.dma_sff_read_status	= ide_dma_sff_read_status,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1315
  };
856204360   Bartlomiej Zolnierkiewicz   ide: constify str...
1316
  static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
1317
1318
  	{	/* 0: HPT36x */
  		.name		= DRV_NAME,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319
1320
1321
  		.init_chipset	= init_chipset_hpt366,
  		.init_hwif	= init_hwif_hpt366,
  		.init_dma	= init_dma_hpt366,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1322
1323
1324
1325
1326
1327
1328
  		/*
  		 * HPT36x chips have one channel per function and have
  		 * both channel enable bits located differently and visible
  		 * to both functions -- really stupid design decision... :-(
  		 * Bit 4 is for the primary channel, bit 5 for the secondary.
  		 */
  		.enablebits	= {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
1329
  		.port_ops	= &hpt3xx_port_ops,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1330
  		.dma_ops	= &hpt36x_dma_ops,
4db90a145   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
1331
  		.host_flags	= IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
4099d1432   Bartlomiej Zolnierkiewicz   ide: add PIO masks
1332
  		.pio_mask	= ATA_PIO4,
5f8b6c348   Bartlomiej Zolnierkiewicz   ide: add ->mwdma_...
1333
  		.mwdma_mask	= ATA_MWDMA2,
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
1334
1335
1336
  	},
  	{	/* 1: HPT3xx */
  		.name		= DRV_NAME,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337
1338
1339
  		.init_chipset	= init_chipset_hpt366,
  		.init_hwif	= init_hwif_hpt366,
  		.init_dma	= init_dma_hpt366,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1340
  		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
1341
  		.port_ops	= &hpt3xx_port_ops,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1342
  		.dma_ops	= &hpt37x_dma_ops,
4db90a145   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
1343
  		.host_flags	= IDE_HFLAGS_HPT3XX,
4099d1432   Bartlomiej Zolnierkiewicz   ide: add PIO masks
1344
  		.pio_mask	= ATA_PIO4,
5f8b6c348   Bartlomiej Zolnierkiewicz   ide: add ->mwdma_...
1345
  		.mwdma_mask	= ATA_MWDMA2,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
  	}
  };
  
  /**
   *	hpt366_init_one	-	called when an HPT366 is found
   *	@dev: the hpt366 device
   *	@id: the matching pci id
   *
   *	Called when the PCI registration layer (or the IDE initialization)
   *	finds a device matching our IDE device tables.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1357
1358
  static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
  {
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
1359
  	const struct hpt_info *info = NULL;
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1360
  	struct hpt_info *dyn_info;
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1361
  	struct pci_dev *dev2 = NULL;
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
1362
  	struct ide_port_info d;
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1363
1364
  	u8 idx = id->driver_data;
  	u8 rev = dev->revision;
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1365
  	int ret;
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1366
1367
1368
1369
1370
1371
1372
1373
1374
  
  	if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1))
  		return -ENODEV;
  
  	switch (idx) {
  	case 0:
  		if (rev < 3)
  			info = &hpt36x;
  		else {
b66cae767   Sam Ravnborg   hpt366: fix secti...
1375
1376
1377
1378
1379
1380
  			switch (min_t(u8, rev, 6)) {
  			case 3: info = &hpt370;  break;
  			case 4: info = &hpt370a; break;
  			case 5: info = &hpt372;  break;
  			case 6: info = &hpt372n; break;
  			}
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
  			idx++;
  		}
  		break;
  	case 1:
  		info = (rev > 1) ? &hpt372n : &hpt372a;
  		break;
  	case 2:
  		info = (rev > 1) ? &hpt302n : &hpt302;
  		break;
  	case 3:
  		hpt371_init(dev);
  		info = (rev > 1) ? &hpt371n : &hpt371;
  		break;
  	case 4:
  		info = &hpt374;
  		break;
  	case 5:
  		info = &hpt372n;
  		break;
  	}
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
1401
1402
1403
1404
  	printk(KERN_INFO DRV_NAME ": %s chipset detected
  ", info->chip_name);
  
  	d = hpt366_chipsets[min_t(u8, idx, 1)];
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1405

fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1406
  	d.udma_mask = info->udma_mask;
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1407
1408
1409
  	/* fixup ->dma_ops for HPT370/HPT370A */
  	if (info == &hpt370 || info == &hpt370a)
  		d.dma_ops = &hpt370_dma_ops;
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1410
1411
  	if (info == &hpt36x || info == &hpt374)
  		dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1412
1413
  	dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL);
  	if (dyn_info == NULL) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1414
1415
1416
  		printk(KERN_ERR "%s %s: out of memory!
  ",
  			d.name, pci_name(dev));
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1417
1418
1419
1420
1421
1422
1423
1424
1425
  		pci_dev_put(dev2);
  		return -ENOMEM;
  	}
  
  	/*
  	 * Copy everything from a static "template" structure
  	 * to just allocated per-chip hpt_info structure.
  	 */
  	memcpy(dyn_info, info, sizeof(*dyn_info));
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1426

74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1427
1428
  	if (dev2) {
  		memcpy(dyn_info + 1, info, sizeof(*dyn_info));
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1429
1430
1431
1432
1433
  
  		if (info == &hpt374)
  			hpt374_init(dev, dev2);
  		else {
  			if (hpt36x_init(dev, dev2))
5e71d9c5a   Bartlomiej Zolnierkiewicz   ide: IDE_HFLAG_BO...
1434
  				d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1435
  		}
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1436
1437
  		ret = ide_pci_init_two(dev, dev2, &d, dyn_info);
  		if (ret < 0) {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1438
  			pci_dev_put(dev2);
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1439
1440
  			kfree(dyn_info);
  		}
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1441
1442
  		return ret;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443

74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1444
1445
1446
1447
1448
  	ret = ide_pci_init_one(dev, &d, dyn_info);
  	if (ret < 0)
  		kfree(dyn_info);
  
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449
  }
a6c43a2be   Bartlomiej Zolnierkiewicz   hpt366: add ->rem...
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
  static void __devexit hpt366_remove(struct pci_dev *dev)
  {
  	struct ide_host *host = pci_get_drvdata(dev);
  	struct ide_info *info = host->host_priv;
  	struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
  
  	ide_pci_remove(dev);
  	pci_dev_put(dev2);
  	kfree(info);
  }
b66cae767   Sam Ravnborg   hpt366: fix secti...
1460
  static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
9cbcc5e3c   Bartlomiej Zolnierkiewicz   ide: use PCI_VDEV...
1461
1462
1463
1464
1465
1466
  	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366),  0 },
  	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372),  1 },
  	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302),  2 },
  	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371),  3 },
  	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374),  4 },
  	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), 5 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467
1468
1469
  	{ 0, },
  };
  MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
1470
  static struct pci_driver hpt366_pci_driver = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1471
1472
1473
  	.name		= "HPT366_IDE",
  	.id_table	= hpt366_pci_tbl,
  	.probe		= hpt366_init_one,
a69999e28   Adrian Bunk   drivers/ide/pci/:...
1474
  	.remove		= __devexit_p(hpt366_remove),
feb22b7f8   Bartlomiej Zolnierkiewicz   ide: add proper P...
1475
1476
  	.suspend	= ide_pci_suspend,
  	.resume		= ide_pci_resume,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1477
  };
82ab1eece   Bartlomiej Zolnierkiewicz   ide: add missing ...
1478
  static int __init hpt366_ide_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479
  {
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
1480
  	return ide_pci_register_driver(&hpt366_pci_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
  }
a6c43a2be   Bartlomiej Zolnierkiewicz   hpt366: add ->rem...
1482
1483
  static void __exit hpt366_ide_exit(void)
  {
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
1484
  	pci_unregister_driver(&hpt366_pci_driver);
a6c43a2be   Bartlomiej Zolnierkiewicz   hpt366: add ->rem...
1485
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1486
  module_init(hpt366_ide_init);
a6c43a2be   Bartlomiej Zolnierkiewicz   hpt366: add ->rem...
1487
  module_exit(hpt366_ide_exit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1488
1489
1490
1491
  
  MODULE_AUTHOR("Andre Hedrick");
  MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
  MODULE_LICENSE("GPL");