Blame view

drivers/ide/hpt366.c 41.9 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
   * 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 ->...
6
   * Portions Copyright (C) 2007		Bartlomiej Zolnierkiewicz
59c8d04f5   Sergei Shtylyov   hpt366: use ATA_D...
7
   * Portions Copyright (C) 2005-2009	MontaVista Software, Inc.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
   *
   * 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 ...
14
   *
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
15
   * HighPoint has its own drivers (open source except for the RAID part)
631dd1a88   Justin P. Mattock   Update broken web...
16
   * available from http://www.highpoint-tech.com/USA_new/service_support.htm 
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
17
18
19
   * 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 ...
20
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
55
   * 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 ...
56
   *		Alan Cox <alan@lxorguk.ukuu.org.uk>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
   *
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
58
59
60
61
62
   * - 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...
63
64
65
66
   * - 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...
67
68
69
   * - 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...
70
   * - use f_CNT value saved by  the HighPoint BIOS as reading it directly gives
729313681   Sergei Shtylyov   hpt366: fix PCI c...
71
72
   *   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 ...
73
74
   * - 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 ...
75
76
   * - 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...
77
78
   * - 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...
79
80
   * - 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 ...
81
   * - optimize the UltraDMA filtering and the drive list lookup code
b4586715d   Sergei Shtylyov   hpt366: switch to...
82
   * - use pci_get_slot() to get to the function 1 of HPT36x/374
7b73ee05d   Sergei Shtylyov   hpt366: init code...
83
84
85
86
   * - 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...
87
   * - rename all the register related variables consistently
7b73ee05d   Sergei Shtylyov   hpt366: init code...
88
89
   * - 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...
90
   * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and
7b73ee05d   Sergei Shtylyov   hpt366: init code...
91
92
93
94
   *   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 ...
95
   * - clean up DMA timeout handling for HPT370
7b73ee05d   Sergei Shtylyov   hpt366: init code...
96
97
98
99
100
101
102
   * - 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 ...
103
104
105
   *   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...
106
107
108
109
   * - 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 ...
110
111
   *   anything  newer than HPT370/A (except HPT374 that is not capable of this
   *   mode according to the manual)
6273d26a5   Sergei Shtylyov   hpt366: HPT36x PC...
112
113
   * - 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...
114
115
   *   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 ...
116
   * - set the correct hwif->ultra_mask for each individual chip
b4e44369a   Sergei Shtylyov   hpt366: MWDMA fil...
117
   * - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards
c018f1ee5   Sergei Shtylyov   hpt366: fix HPT37...
118
119
   * - stop resetting HPT370's state machine before each DMA transfer as that has
   *   caused more harm than good
7b73ee05d   Sergei Shtylyov   hpt366: init code...
120
   *	Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
  #include <linux/types.h>
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/delay.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  #include <linux/blkdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
130
  #include <linux/interrupt.h>
  #include <linux/pci.h>
  #include <linux/init.h>
  #include <linux/ide.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
131
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
133
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  #include <asm/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
175
  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...
176
  	"MAXTOR STM3320620A",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  	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...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
  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
213
  };
471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  /* 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
236
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237

471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
  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
256
  };
471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  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
275
  };
471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
  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
294
  };
809b53c4e   Sergei Shtylyov   hpt366: fix HPT37...
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
359
  /*
   * 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
360

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

7b73ee05d   Sergei Shtylyov   hpt366: init code...
368
369
370
371
372
373
374
375
376
  /* 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
377

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

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

866664d79   Sergei Shtylyov   hpt366: merge set...
412
413
414
415
416
417
418
419
420
421
422
  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...
423
  };
e139b0b02   Sergei Shtylyov   hpt366: rework ra...
424

866664d79   Sergei Shtylyov   hpt366: merge set...
425
426
427
428
429
430
431
432
433
434
435
  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...
436
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437

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

9adb9254f   Andy Shevchenko   ide: hpt366: conv...
516
  static bool check_in_drive_list(ide_drive_t *drive, const char **list)
e139b0b02   Sergei Shtylyov   hpt366: rework ra...
517
  {
9adb9254f   Andy Shevchenko   ide: hpt366: conv...
518
  	return match_string(list, -1, (char *)&drive->id[ATA_ID_PROD]) >= 0;
e139b0b02   Sergei Shtylyov   hpt366: rework ra...
519
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520

62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
521
522
523
524
525
526
527
  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
528
  /*
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
529
530
   * 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
531
   */
2d5eaa6dd   Bartlomiej Zolnierkiewicz   ide: rework the c...
532
533
  
  static u8 hpt3xx_udma_filter(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
535
  	ide_hwif_t *hwif	= drive->hwif;
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
536
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
537
  	u8 mask 		= hwif->ultra_mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538

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

2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
545
546
  		if (!HPT366_ALLOW_ATA66_3 ||
  		    check_in_drive_list(drive, bad_ata66_3))
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
547
  			mask = ATA_UDMA2;
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
548
  		break;
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
549
550
551
552
553
554
555
556
557
  	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;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
558
  		fallthrough;
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
559
560
561
562
  	case HPT372 :
  	case HPT372A:
  	case HPT372N:
  	case HPT374 :
367d7e78d   Bartlomiej Zolnierkiewicz   ide: ide_dev_is_s...
563
  		if (ata_id_is_sata(drive->id))
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
564
  			mask &= ~0x0e;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
565
  		fallthrough;
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
566
  	default:
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
567
  		return mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
  	}
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
569
570
  
  	return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
  }
b4e44369a   Sergei Shtylyov   hpt366: MWDMA fil...
572
573
  static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
574
  	ide_hwif_t *hwif	= drive->hwif;
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
575
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
b4e44369a   Sergei Shtylyov   hpt366: MWDMA fil...
576
577
578
579
580
581
  
  	switch (info->chip_type) {
  	case HPT372 :
  	case HPT372A:
  	case HPT372N:
  	case HPT374 :
367d7e78d   Bartlomiej Zolnierkiewicz   ide: ide_dev_is_s...
582
  		if (ata_id_is_sata(drive->id))
b4e44369a   Sergei Shtylyov   hpt366: MWDMA fil...
583
  			return 0x00;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
584
  		fallthrough;
b4e44369a   Sergei Shtylyov   hpt366: MWDMA fil...
585
586
587
588
  	default:
  		return 0x07;
  	}
  }
7b73ee05d   Sergei Shtylyov   hpt366: init code...
589
  static u32 get_speed_setting(u8 speed, struct hpt_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
  {
471a0bda5   Sergei Shtylyov   [PATCH] ide: opti...
591
592
593
594
595
596
597
598
599
600
601
  	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...
602
603
  
  	return info->timings->clock_table[info->clock][i];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
  }
8776168ca   Bartlomiej Zolnierkiewicz   ide: change ->set...
605
  static void hpt3xx_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
  {
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
607
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
608
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
866664d79   Sergei Shtylyov   hpt366: merge set...
609
610
  	struct hpt_timings *t	= info->timings;
  	u8  itr_addr		= 0x40 + (drive->dn * 4);
26ccb802e   Sergei Shtylyov   hpt366: merge HPT...
611
  	u32 old_itr		= 0;
8776168ca   Bartlomiej Zolnierkiewicz   ide: change ->set...
612
  	const u8 speed		= drive->dma_mode;
ceb1b2c58   Sergei Shtylyov   hpt366: change ti...
613
  	u32 new_itr		= get_speed_setting(speed, info);
866664d79   Sergei Shtylyov   hpt366: merge set...
614
615
616
  	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 ...
617

ceb1b2c58   Sergei Shtylyov   hpt366: change ti...
618
619
  	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
620
  	/*
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
621
622
  	 * 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
623
  	 */
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
624
  	new_itr &= ~0xc0000000;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625

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

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

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

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

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

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

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

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

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

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

7b73ee05d   Sergei Shtylyov   hpt366: init code...
821
822
823
824
825
  	/* 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 ...
826
827
  			break;
  	}
7b73ee05d   Sergei Shtylyov   hpt366: init code...
828
829
830
831
832
833
834
835
836
837
838
  	/* 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 ...
839
  }
feb22b7f8   Bartlomiej Zolnierkiewicz   ide: add proper P...
840
  static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr)
1785192b5   Bartlomiej Zolnierkiewicz   hpt366: add hpt3x...
841
842
843
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
  {
  	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...
869
  static int init_chipset_hpt366(struct pci_dev *dev)
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
870
  {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
871
  	unsigned long io_base	= pci_resource_start(dev, 4);
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
872
  	struct hpt_info *info	= hpt3xx_get_info(&dev->dev);
a326b02b0   Bartlomiej Zolnierkiewicz   ide: drop 'name' ...
873
  	const char *name	= DRV_NAME;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
874
  	u8 pci_clk,  dpll_clk	= 0;	/* PCI and DPLL clock in MHz */
729313681   Sergei Shtylyov   hpt366: fix PCI c...
875
  	u8 chip_type;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
876
  	enum ata_clock	clock;
729313681   Sergei Shtylyov   hpt366: fix PCI c...
877
  	chip_type = info->chip_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878

7b73ee05d   Sergei Shtylyov   hpt366: init code...
879
880
881
882
  	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...
883

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
  	/*
7b73ee05d   Sergei Shtylyov   hpt366: init code...
885
  	 * First, try to estimate the PCI clock frequency...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
  	 */
729313681   Sergei Shtylyov   hpt366: fix PCI c...
887
  	if (chip_type >= HPT370) {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
888
889
890
891
892
893
894
895
896
897
898
899
900
  		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...
901
  		if (chip_type == HPT372A)
7b73ee05d   Sergei Shtylyov   hpt366: init code...
902
903
904
905
906
907
908
  			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...
909

7b73ee05d   Sergei Shtylyov   hpt366: init code...
910
911
912
913
914
915
916
917
918
  		/*
  		 * 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...
919
  		 *
729313681   Sergei Shtylyov   hpt366: fix PCI c...
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
  		 * 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...
940
  		 */
7b73ee05d   Sergei Shtylyov   hpt366: init code...
941
942
  		if ((temp & 0xFFFFF000) != 0xABCDE000) {
  			int i;
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
943
944
945
  			printk(KERN_WARNING "%s %s: no clock data saved by "
  				"BIOS
  ", name, pci_name(dev));
7b73ee05d   Sergei Shtylyov   hpt366: init code...
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
  
  			/* 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
967
  		else
7b73ee05d   Sergei Shtylyov   hpt366: init code...
968
  			pci_clk = 66;
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
969

28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
970
971
972
973
  		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...
974
  	} else {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
975
976
977
978
979
  		u32 itr1 = 0;
  
  		pci_read_config_dword(dev, 0x40, &itr1);
  
  		/* Detect PCI clock by looking at cmd_high_time. */
45969e16f   Colin Ian King   ide: hpt366: fix ...
980
  		switch ((itr1 >> 8) & 0x0f) {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
981
982
  			case 0x09:
  				pci_clk = 40;
6273d26a5   Sergei Shtylyov   hpt366: HPT36x PC...
983
  				break;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
984
985
  			case 0x05:
  				pci_clk = 25;
6273d26a5   Sergei Shtylyov   hpt366: HPT36x PC...
986
  				break;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
987
988
989
  			case 0x07:
  			default:
  				pci_clk = 33;
6273d26a5   Sergei Shtylyov   hpt366: HPT36x PC...
990
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
991
992
  		}
  	}
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
993

7b73ee05d   Sergei Shtylyov   hpt366: init code...
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
  	/* 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...
1013

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
  	/*
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1015
1016
  	 * 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 ...
1017
  	 *
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1018
1019
1020
  	 * 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
1021
  	 */
866664d79   Sergei Shtylyov   hpt366: merge set...
1022
  	if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1023
1024
1025
1026
1027
1028
1029
  		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 ->...
1030
  		if (info->udma_mask == ATA_UDMA6) {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1031
1032
1033
1034
1035
1036
  			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 ...
1037

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

7b73ee05d   Sergei Shtylyov   hpt366: init code...
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
  		/* 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 ...
1067
1068
1069
  			printk(KERN_ERR "%s %s: DPLL did not stabilize!
  ",
  				name, pci_name(dev));
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1070
1071
  			return -EIO;
  		}
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1072
1073
1074
  		printk(KERN_INFO "%s %s: using %d MHz DPLL clock
  ",
  			name, pci_name(dev), dpll_clk);
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1075
1076
1077
  	} else {
  		/* Mark the fact that we're not using the DPLL. */
  		dpll_clk = 0;
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1078
1079
1080
  		printk(KERN_INFO "%s %s: using %d MHz PCI clock
  ",
  			name, pci_name(dev), pci_clk);
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1081
  	}
b39b01ffb   Alan Cox   [PATCH] ide: fix ...
1082

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

729313681   Sergei Shtylyov   hpt366: fix PCI c...
1088
  	if (chip_type >= HPT370) {
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  		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...
1100
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101

7b73ee05d   Sergei Shtylyov   hpt366: init code...
1102
1103
1104
1105
1106
  	/*
  	 * 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...
1107
  	if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ)
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1108
  		outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c);
1785192b5   Bartlomiej Zolnierkiewicz   hpt366: add hpt3x...
1109
1110
  	hpt3xx_disable_fast_irq(dev, 0x50);
  	hpt3xx_disable_fast_irq(dev, 0x54);
2ed0ef543   Bartlomiej Zolnierkiewicz   ide: fix ->init_c...
1111
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
  }
f454cbe8c   Bartlomiej Zolnierkiewicz   ide: ->cable_dete...
1113
  static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
bfa14b42a   Bartlomiej Zolnierkiewicz   ide: add ->cable_...
1114
1115
  {
  	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
1116
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
bfa14b42a   Bartlomiej Zolnierkiewicz   ide: add ->cable_...
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
  	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...
1135
1136
1137
  		pci_write_config_word(dev, mcr_addr, mcr | 0x8000);
  		/* Debounce, then read cable ID register */
  		udelay(10);
bfa14b42a   Bartlomiej Zolnierkiewicz   ide: add ->cable_...
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
  		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...
1148
1149
1150
  		pci_write_config_byte(dev, 0x5b, scr2 & ~1);
  		/* Debounce, then read cable ID register */
  		udelay(10);
bfa14b42a   Bartlomiej Zolnierkiewicz   ide: add ->cable_...
1151
  		pci_read_config_byte(dev, 0x5a, &scr1);
5d3f1a493   Sergei Shtylyov   hpt366: add debou...
1152
  		pci_write_config_byte(dev, 0x5b, scr2);
bfa14b42a   Bartlomiej Zolnierkiewicz   ide: add ->cable_...
1153
1154
1155
1156
1157
  	} else
  		pci_read_config_byte(dev, 0x5a, &scr1);
  
  	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
  }
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
1158
  static void init_hwif_hpt366(ide_hwif_t *hwif)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
  {
62ff2ecf7   Masoud Sharbiani   ide: Fix pointer ...
1160
  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
1161
  	u8  chip_type		= info->chip_type;
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
1162
1163
  
  	/* Cache the channel's MISC. control registers' offset */
2808b0a96   Sergei Shtylyov   hpt366: UltraDMA ...
1164
  	hwif->select_data	= hwif->channel ? 0x54 : 0x50;
abc4ad4c6   Sergei Shtylyov   hpt366: cache cha...
1165

836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1166
1167
1168
1169
1170
1171
  	/*
  	 * 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...
1172
  	if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) {
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1173
1174
1175
1176
  		/*
  		 * Clock is shared between the channels,
  		 * so we'll have to serialize them... :-(
  		 */
702c026be   Bartlomiej Zolnierkiewicz   ide: rework handl...
1177
  		hwif->host->host_flags |= IDE_HFLAG_SERIALIZE;
836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1178
1179
  		hwif->rw_disk = &hpt3xxn_rw_disk;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
  }
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
1181
  static int init_dma_hpt366(ide_hwif_t *hwif,
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
1182
  				     const struct ide_port_info *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
  {
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
1184
  	struct pci_dev *dev = to_pci_dev(hwif->dev);
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
1185
1186
  	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
1187

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

836c0063c   Sergei Shtylyov   [PATCH] ide: HPT3...
1238
1239
1240
1241
1242
1243
1244
1245
  	/*
  	 * 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...
1246
  		pci_write_config_byte(dev, 0x50, mcr1 & ~0x04);
90778574c   Sergei Shtylyov   hpt366: print the...
1247
  }
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
1248
  static int hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
90778574c   Sergei Shtylyov   hpt366: print the...
1249
  {
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1250
  	u8 mcr1 = 0, pin1 = 0, pin2 = 0;
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1251

fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1252
1253
1254
1255
1256
1257
1258
  	/*
  	 * 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...
1259

fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1260
1261
  	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
1262

fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1263
  	if (pin1 != pin2 && dev->irq == dev2->irq) {
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
1264
  		printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, "
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1265
1266
  			"pin1=%d pin2=%d
  ", pci_name(dev), pin1, pin2);
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1267
  		return 1;
2648e5d9a   Sergei Shtylyov   hpt366: simplify ...
1268
  	}
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1269
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
  }
4db90a145   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
1271
1272
  #define IDE_HFLAGS_HPT3XX \
  	(IDE_HFLAG_NO_ATAPI_DMA | \
4db90a145   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
1273
  	 IDE_HFLAG_OFF_BOARD)
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
1274
1275
1276
  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...
1277
1278
1279
1280
1281
  	.maskproc		= hpt3xx_maskproc,
  	.mdma_filter		= hpt3xx_mdma_filter,
  	.udma_filter		= hpt3xx_udma_filter,
  	.cable_detect		= hpt3xx_cable_detect,
  };
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1282
1283
1284
  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...
1285
  	.dma_start		= ide_dma_start,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1286
1287
  	.dma_end		= hpt374_dma_end,
  	.dma_test_irq		= hpt374_dma_test_irq,
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1288
  	.dma_lost_irq		= ide_dma_lost_irq,
22117d6ea   Bartlomiej Zolnierkiewicz   ide: add ->dma_ti...
1289
  	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
592b53152   Sergei Shtylyov   ide: move read_sf...
1290
  	.dma_sff_read_status	= ide_dma_sff_read_status,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1291
  };
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1292
1293
1294
  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...
1295
1296
  	.dma_start		= hpt370_dma_start,
  	.dma_end		= hpt370_dma_end,
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1297
1298
  	.dma_test_irq		= ide_dma_test_irq,
  	.dma_lost_irq		= ide_dma_lost_irq,
22117d6ea   Bartlomiej Zolnierkiewicz   ide: add ->dma_ti...
1299
  	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
35c9b4daf   Bartlomiej Zolnierkiewicz   ide: add ->dma_cl...
1300
  	.dma_clear		= hpt370_irq_timeout,
592b53152   Sergei Shtylyov   ide: move read_sf...
1301
  	.dma_sff_read_status	= ide_dma_sff_read_status,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1302
  };
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1303
1304
1305
  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...
1306
  	.dma_start		= ide_dma_start,
653bcf529   Bartlomiej Zolnierkiewicz   ide: __ide_dma_en...
1307
  	.dma_end		= ide_dma_end,
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
1308
  	.dma_test_irq		= ide_dma_test_irq,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1309
  	.dma_lost_irq		= hpt366_dma_lost_irq,
22117d6ea   Bartlomiej Zolnierkiewicz   ide: add ->dma_ti...
1310
  	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
592b53152   Sergei Shtylyov   ide: move read_sf...
1311
  	.dma_sff_read_status	= ide_dma_sff_read_status,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1312
  };
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
1313
  static const struct ide_port_info hpt366_chipsets[] = {
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
1314
1315
  	{	/* 0: HPT36x */
  		.name		= DRV_NAME,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
1317
1318
  		.init_chipset	= init_chipset_hpt366,
  		.init_hwif	= init_hwif_hpt366,
  		.init_dma	= init_dma_hpt366,
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1319
1320
1321
1322
1323
1324
1325
  		/*
  		 * 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...
1326
  		.port_ops	= &hpt3xx_port_ops,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1327
  		.dma_ops	= &hpt36x_dma_ops,
4db90a145   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
1328
  		.host_flags	= IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
4099d1432   Bartlomiej Zolnierkiewicz   ide: add PIO masks
1329
  		.pio_mask	= ATA_PIO4,
5f8b6c348   Bartlomiej Zolnierkiewicz   ide: add ->mwdma_...
1330
  		.mwdma_mask	= ATA_MWDMA2,
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
1331
1332
1333
  	},
  	{	/* 1: HPT3xx */
  		.name		= DRV_NAME,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334
1335
1336
  		.init_chipset	= init_chipset_hpt366,
  		.init_hwif	= init_hwif_hpt366,
  		.init_dma	= init_dma_hpt366,
7b73ee05d   Sergei Shtylyov   hpt366: init code...
1337
  		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
1338
  		.port_ops	= &hpt3xx_port_ops,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1339
  		.dma_ops	= &hpt37x_dma_ops,
4db90a145   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
1340
  		.host_flags	= IDE_HFLAGS_HPT3XX,
4099d1432   Bartlomiej Zolnierkiewicz   ide: add PIO masks
1341
  		.pio_mask	= ATA_PIO4,
5f8b6c348   Bartlomiej Zolnierkiewicz   ide: add ->mwdma_...
1342
  		.mwdma_mask	= ATA_MWDMA2,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
  	}
  };
  
  /**
   *	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.
   */
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
1354
  static int hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1355
  {
282037f17   Bartlomiej Zolnierkiewicz   hpt366: fix build...
1356
  	const struct hpt_info *info = NULL;
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1357
  	struct hpt_info *dyn_info;
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1358
  	struct pci_dev *dev2 = NULL;
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
1359
  	struct ide_port_info d;
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1360
1361
  	u8 idx = id->driver_data;
  	u8 rev = dev->revision;
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1362
  	int ret;
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1363
1364
1365
1366
1367
1368
1369
1370
1371
  
  	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...
1372
1373
1374
1375
1376
1377
  			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 ->...
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
  			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...
1398
1399
1400
1401
  	printk(KERN_INFO DRV_NAME ": %s chipset detected
  ", info->chip_name);
  
  	d = hpt366_chipsets[min_t(u8, idx, 1)];
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1402

fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1403
  	d.udma_mask = info->udma_mask;
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
1404
1405
1406
  	/* fixup ->dma_ops for HPT370/HPT370A */
  	if (info == &hpt370 || info == &hpt370a)
  		d.dma_ops = &hpt370_dma_ops;
fbf47840f   Bartlomiej Zolnierkiewicz   hpt366: remove ->...
1407
1408
  	if (info == &hpt36x || info == &hpt374)
  		dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
6396bb221   Kees Cook   treewide: kzalloc...
1409
  	dyn_info = kcalloc(dev2 ? 2 : 1, sizeof(*dyn_info), GFP_KERNEL);
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1410
  	if (dyn_info == NULL) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
1411
1412
1413
  		printk(KERN_ERR "%s %s: out of memory!
  ",
  			d.name, pci_name(dev));
74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1414
1415
1416
1417
1418
1419
1420
1421
1422
  		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 ->...
1423

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

74811f355   Bartlomiej Zolnierkiewicz   hpt366: convert t...
1441
1442
1443
1444
1445
  	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
1446
  }
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
1447
  static void hpt366_remove(struct pci_dev *dev)
a6c43a2be   Bartlomiej Zolnierkiewicz   hpt366: add ->rem...
1448
1449
1450
1451
1452
1453
1454
1455
1456
  {
  	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);
  }
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
1457
  static const struct pci_device_id hpt366_pci_tbl[] = {
9cbcc5e3c   Bartlomiej Zolnierkiewicz   ide: use PCI_VDEV...
1458
1459
1460
1461
1462
1463
  	{ 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
1464
1465
1466
  	{ 0, },
  };
  MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
1467
  static struct pci_driver hpt366_pci_driver = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1468
1469
1470
  	.name		= "HPT366_IDE",
  	.id_table	= hpt366_pci_tbl,
  	.probe		= hpt366_init_one,
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
1471
  	.remove		= hpt366_remove,
feb22b7f8   Bartlomiej Zolnierkiewicz   ide: add proper P...
1472
1473
  	.suspend	= ide_pci_suspend,
  	.resume		= ide_pci_resume,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
  };
82ab1eece   Bartlomiej Zolnierkiewicz   ide: add missing ...
1475
  static int __init hpt366_ide_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
  {
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
1477
  	return ide_pci_register_driver(&hpt366_pci_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
  }
a6c43a2be   Bartlomiej Zolnierkiewicz   hpt366: add ->rem...
1479
1480
  static void __exit hpt366_ide_exit(void)
  {
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
1481
  	pci_unregister_driver(&hpt366_pci_driver);
a6c43a2be   Bartlomiej Zolnierkiewicz   hpt366: add ->rem...
1482
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
  module_init(hpt366_ide_init);
a6c43a2be   Bartlomiej Zolnierkiewicz   hpt366: add ->rem...
1484
  module_exit(hpt366_ide_exit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1485
1486
1487
1488
  
  MODULE_AUTHOR("Andre Hedrick");
  MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
  MODULE_LICENSE("GPL");