xref: /openbmc/linux/drivers/ata/pata_hpt37x.c (revision 1c5afdf7)
1669a5db4SJeff Garzik /*
2669a5db4SJeff Garzik  * Libata driver for the highpoint 37x and 30x UDMA66 ATA controllers.
3669a5db4SJeff Garzik  *
4669a5db4SJeff Garzik  * This driver is heavily based upon:
5669a5db4SJeff Garzik  *
6669a5db4SJeff Garzik  * linux/drivers/ide/pci/hpt366.c		Version 0.36	April 25, 2003
7669a5db4SJeff Garzik  *
8669a5db4SJeff Garzik  * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
9669a5db4SJeff Garzik  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
10669a5db4SJeff Garzik  * Portions Copyright (C) 2003		Red Hat Inc
11265b7215SSergei Shtylyov  * Portions Copyright (C) 2005-2009	MontaVista Software, Inc.
12669a5db4SJeff Garzik  *
13669a5db4SJeff Garzik  * TODO
14d44a65f7SSergei Shtylyov  *	Look into engine reset on timeout errors. Should not be	required.
15669a5db4SJeff Garzik  */
16669a5db4SJeff Garzik 
17669a5db4SJeff Garzik #include <linux/kernel.h>
18669a5db4SJeff Garzik #include <linux/module.h>
19669a5db4SJeff Garzik #include <linux/pci.h>
20669a5db4SJeff Garzik #include <linux/init.h>
21669a5db4SJeff Garzik #include <linux/blkdev.h>
22669a5db4SJeff Garzik #include <linux/delay.h>
23669a5db4SJeff Garzik #include <scsi/scsi_host.h>
24669a5db4SJeff Garzik #include <linux/libata.h>
25669a5db4SJeff Garzik 
26669a5db4SJeff Garzik #define DRV_NAME	"pata_hpt37x"
271a1b172bSSergei Shtylyov #define DRV_VERSION	"0.6.15"
28669a5db4SJeff Garzik 
29669a5db4SJeff Garzik struct hpt_clock {
30669a5db4SJeff Garzik 	u8	xfer_speed;
31669a5db4SJeff Garzik 	u32	timing;
32669a5db4SJeff Garzik };
33669a5db4SJeff Garzik 
34669a5db4SJeff Garzik struct hpt_chip {
35669a5db4SJeff Garzik 	const char *name;
36669a5db4SJeff Garzik 	unsigned int base;
37669a5db4SJeff Garzik 	struct hpt_clock const *clocks[4];
38669a5db4SJeff Garzik };
39669a5db4SJeff Garzik 
40669a5db4SJeff Garzik /* key for bus clock timings
41669a5db4SJeff Garzik  * bit
42fd5e62e2SSergei Shtylyov  * 0:3    data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
43fd5e62e2SSergei Shtylyov  *        cycles = value + 1
44fd5e62e2SSergei Shtylyov  * 4:8    data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
45fd5e62e2SSergei Shtylyov  *        cycles = value + 1
46fd5e62e2SSergei Shtylyov  * 9:12   cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
47669a5db4SJeff Garzik  *        register access.
48fd5e62e2SSergei Shtylyov  * 13:17  cmd_low_time. Active time of DIOW_/DIOR_ during task file
49669a5db4SJeff Garzik  *        register access.
50fd5e62e2SSergei Shtylyov  * 18:20  udma_cycle_time. Clock cycles for UDMA xfer.
51fd5e62e2SSergei Shtylyov  * 21     CLK frequency for UDMA: 0=ATA clock, 1=dual ATA clock.
52fd5e62e2SSergei Shtylyov  * 22:24  pre_high_time. Time to initialize 1st cycle for PIO and MW DMA xfer.
53fd5e62e2SSergei Shtylyov  * 25:27  cmd_pre_high_time. Time to initialize 1st PIO cycle for task file
54669a5db4SJeff Garzik  *        register access.
55fd5e62e2SSergei Shtylyov  * 28     UDMA enable.
56fd5e62e2SSergei Shtylyov  * 29     DMA  enable.
57fd5e62e2SSergei Shtylyov  * 30     PIO_MST enable. If set, the chip is in bus master mode during
58fd5e62e2SSergei Shtylyov  *        PIO xfer.
59fd5e62e2SSergei Shtylyov  * 31     FIFO enable. Only for PIO.
60669a5db4SJeff Garzik  */
61669a5db4SJeff Garzik 
62fcc2f69aSAlan Cox static struct hpt_clock hpt37x_timings_33[] = {
63fcc2f69aSAlan Cox 	{ XFER_UDMA_6,		0x12446231 },	/* 0x12646231 ?? */
64669a5db4SJeff Garzik 	{ XFER_UDMA_5,		0x12446231 },
65669a5db4SJeff Garzik 	{ XFER_UDMA_4,		0x12446231 },
66669a5db4SJeff Garzik 	{ XFER_UDMA_3,		0x126c6231 },
67669a5db4SJeff Garzik 	{ XFER_UDMA_2,		0x12486231 },
68669a5db4SJeff Garzik 	{ XFER_UDMA_1,		0x124c6233 },
69669a5db4SJeff Garzik 	{ XFER_UDMA_0,		0x12506297 },
70669a5db4SJeff Garzik 
71669a5db4SJeff Garzik 	{ XFER_MW_DMA_2,	0x22406c31 },
72669a5db4SJeff Garzik 	{ XFER_MW_DMA_1,	0x22406c33 },
73669a5db4SJeff Garzik 	{ XFER_MW_DMA_0,	0x22406c97 },
74669a5db4SJeff Garzik 
75669a5db4SJeff Garzik 	{ XFER_PIO_4,		0x06414e31 },
76669a5db4SJeff Garzik 	{ XFER_PIO_3,		0x06414e42 },
77669a5db4SJeff Garzik 	{ XFER_PIO_2,		0x06414e53 },
78669a5db4SJeff Garzik 	{ XFER_PIO_1,		0x06814e93 },
79fcc2f69aSAlan Cox 	{ XFER_PIO_0,		0x06814ea7 }
80669a5db4SJeff Garzik };
81669a5db4SJeff Garzik 
82fcc2f69aSAlan Cox static struct hpt_clock hpt37x_timings_50[] = {
83fcc2f69aSAlan Cox 	{ XFER_UDMA_6,		0x12848242 },
84669a5db4SJeff Garzik 	{ XFER_UDMA_5,		0x12848242 },
85669a5db4SJeff Garzik 	{ XFER_UDMA_4,		0x12ac8242 },
86669a5db4SJeff Garzik 	{ XFER_UDMA_3,		0x128c8242 },
87669a5db4SJeff Garzik 	{ XFER_UDMA_2,		0x120c8242 },
88669a5db4SJeff Garzik 	{ XFER_UDMA_1,		0x12148254 },
89669a5db4SJeff Garzik 	{ XFER_UDMA_0,		0x121882ea },
90669a5db4SJeff Garzik 
91669a5db4SJeff Garzik 	{ XFER_MW_DMA_2,	0x22808242 },
92669a5db4SJeff Garzik 	{ XFER_MW_DMA_1,	0x22808254 },
93669a5db4SJeff Garzik 	{ XFER_MW_DMA_0,	0x228082ea },
94669a5db4SJeff Garzik 
95669a5db4SJeff Garzik 	{ XFER_PIO_4,		0x0a81f442 },
96669a5db4SJeff Garzik 	{ XFER_PIO_3,		0x0a81f443 },
97669a5db4SJeff Garzik 	{ XFER_PIO_2,		0x0a81f454 },
98669a5db4SJeff Garzik 	{ XFER_PIO_1,		0x0ac1f465 },
99fcc2f69aSAlan Cox 	{ XFER_PIO_0,		0x0ac1f48a }
100669a5db4SJeff Garzik };
101669a5db4SJeff Garzik 
102fcc2f69aSAlan Cox static struct hpt_clock hpt37x_timings_66[] = {
103669a5db4SJeff Garzik 	{ XFER_UDMA_6,		0x1c869c62 },
104fcc2f69aSAlan Cox 	{ XFER_UDMA_5,		0x1cae9c62 },	/* 0x1c8a9c62 */
105669a5db4SJeff Garzik 	{ XFER_UDMA_4,		0x1c8a9c62 },
106669a5db4SJeff Garzik 	{ XFER_UDMA_3,		0x1c8e9c62 },
107669a5db4SJeff Garzik 	{ XFER_UDMA_2,		0x1c929c62 },
108669a5db4SJeff Garzik 	{ XFER_UDMA_1,		0x1c9a9c62 },
109669a5db4SJeff Garzik 	{ XFER_UDMA_0,		0x1c829c62 },
110669a5db4SJeff Garzik 
111669a5db4SJeff Garzik 	{ XFER_MW_DMA_2,	0x2c829c62 },
112669a5db4SJeff Garzik 	{ XFER_MW_DMA_1,	0x2c829c66 },
113669a5db4SJeff Garzik 	{ XFER_MW_DMA_0,	0x2c829d2e },
114669a5db4SJeff Garzik 
115669a5db4SJeff Garzik 	{ XFER_PIO_4,		0x0c829c62 },
116669a5db4SJeff Garzik 	{ XFER_PIO_3,		0x0c829c84 },
117669a5db4SJeff Garzik 	{ XFER_PIO_2,		0x0c829ca6 },
118669a5db4SJeff Garzik 	{ XFER_PIO_1,		0x0d029d26 },
119fcc2f69aSAlan Cox 	{ XFER_PIO_0,		0x0d029d5e }
120669a5db4SJeff Garzik };
121669a5db4SJeff Garzik 
122669a5db4SJeff Garzik 
123669a5db4SJeff Garzik static const struct hpt_chip hpt370 = {
124669a5db4SJeff Garzik 	"HPT370",
125669a5db4SJeff Garzik 	48,
126669a5db4SJeff Garzik 	{
127fcc2f69aSAlan Cox 		hpt37x_timings_33,
128669a5db4SJeff Garzik 		NULL,
129669a5db4SJeff Garzik 		NULL,
130a4734468SAlan Cox 		NULL
131669a5db4SJeff Garzik 	}
132669a5db4SJeff Garzik };
133669a5db4SJeff Garzik 
134669a5db4SJeff Garzik static const struct hpt_chip hpt370a = {
135669a5db4SJeff Garzik 	"HPT370A",
136669a5db4SJeff Garzik 	48,
137669a5db4SJeff Garzik 	{
138fcc2f69aSAlan Cox 		hpt37x_timings_33,
139669a5db4SJeff Garzik 		NULL,
140fcc2f69aSAlan Cox 		hpt37x_timings_50,
141a4734468SAlan Cox 		NULL
142669a5db4SJeff Garzik 	}
143669a5db4SJeff Garzik };
144669a5db4SJeff Garzik 
145669a5db4SJeff Garzik static const struct hpt_chip hpt372 = {
146669a5db4SJeff Garzik 	"HPT372",
147669a5db4SJeff Garzik 	55,
148669a5db4SJeff Garzik 	{
149fcc2f69aSAlan Cox 		hpt37x_timings_33,
150669a5db4SJeff Garzik 		NULL,
151fcc2f69aSAlan Cox 		hpt37x_timings_50,
152fcc2f69aSAlan Cox 		hpt37x_timings_66
153669a5db4SJeff Garzik 	}
154669a5db4SJeff Garzik };
155669a5db4SJeff Garzik 
156669a5db4SJeff Garzik static const struct hpt_chip hpt302 = {
157669a5db4SJeff Garzik 	"HPT302",
158669a5db4SJeff Garzik 	66,
159669a5db4SJeff Garzik 	{
160fcc2f69aSAlan Cox 		hpt37x_timings_33,
161669a5db4SJeff Garzik 		NULL,
162fcc2f69aSAlan Cox 		hpt37x_timings_50,
163fcc2f69aSAlan Cox 		hpt37x_timings_66
164669a5db4SJeff Garzik 	}
165669a5db4SJeff Garzik };
166669a5db4SJeff Garzik 
167669a5db4SJeff Garzik static const struct hpt_chip hpt371 = {
168669a5db4SJeff Garzik 	"HPT371",
169669a5db4SJeff Garzik 	66,
170669a5db4SJeff Garzik 	{
171fcc2f69aSAlan Cox 		hpt37x_timings_33,
172669a5db4SJeff Garzik 		NULL,
173fcc2f69aSAlan Cox 		hpt37x_timings_50,
174fcc2f69aSAlan Cox 		hpt37x_timings_66
175669a5db4SJeff Garzik 	}
176669a5db4SJeff Garzik };
177669a5db4SJeff Garzik 
178669a5db4SJeff Garzik static const struct hpt_chip hpt372a = {
179669a5db4SJeff Garzik 	"HPT372A",
180669a5db4SJeff Garzik 	66,
181669a5db4SJeff Garzik 	{
182fcc2f69aSAlan Cox 		hpt37x_timings_33,
183669a5db4SJeff Garzik 		NULL,
184fcc2f69aSAlan Cox 		hpt37x_timings_50,
185fcc2f69aSAlan Cox 		hpt37x_timings_66
186669a5db4SJeff Garzik 	}
187669a5db4SJeff Garzik };
188669a5db4SJeff Garzik 
189669a5db4SJeff Garzik static const struct hpt_chip hpt374 = {
190669a5db4SJeff Garzik 	"HPT374",
191669a5db4SJeff Garzik 	48,
192669a5db4SJeff Garzik 	{
193fcc2f69aSAlan Cox 		hpt37x_timings_33,
194669a5db4SJeff Garzik 		NULL,
195669a5db4SJeff Garzik 		NULL,
196669a5db4SJeff Garzik 		NULL
197669a5db4SJeff Garzik 	}
198669a5db4SJeff Garzik };
199669a5db4SJeff Garzik 
200669a5db4SJeff Garzik /**
201669a5db4SJeff Garzik  *	hpt37x_find_mode	-	reset the hpt37x bus
202669a5db4SJeff Garzik  *	@ap: ATA port
203669a5db4SJeff Garzik  *	@speed: transfer mode
204669a5db4SJeff Garzik  *
205669a5db4SJeff Garzik  *	Return the 32bit register programming information for this channel
206669a5db4SJeff Garzik  *	that matches the speed provided.
207669a5db4SJeff Garzik  */
208669a5db4SJeff Garzik 
209669a5db4SJeff Garzik static u32 hpt37x_find_mode(struct ata_port *ap, int speed)
210669a5db4SJeff Garzik {
211669a5db4SJeff Garzik 	struct hpt_clock *clocks = ap->host->private_data;
212669a5db4SJeff Garzik 
213669a5db4SJeff Garzik 	while(clocks->xfer_speed) {
214669a5db4SJeff Garzik 		if (clocks->xfer_speed == speed)
215669a5db4SJeff Garzik 			return clocks->timing;
216669a5db4SJeff Garzik 		clocks++;
217669a5db4SJeff Garzik 	}
218669a5db4SJeff Garzik 	BUG();
219669a5db4SJeff Garzik 	return 0xffffffffU;	/* silence compiler warning */
220669a5db4SJeff Garzik }
221669a5db4SJeff Garzik 
222669a5db4SJeff Garzik static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[])
223669a5db4SJeff Garzik {
2248bfa79fcSTejun Heo 	unsigned char model_num[ATA_ID_PROD_LEN + 1];
225669a5db4SJeff Garzik 	int i = 0;
226669a5db4SJeff Garzik 
2278bfa79fcSTejun Heo 	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
228669a5db4SJeff Garzik 
229669a5db4SJeff Garzik 	while (list[i] != NULL) {
2308bfa79fcSTejun Heo 		if (!strcmp(list[i], model_num)) {
231669a5db4SJeff Garzik 			printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
232669a5db4SJeff Garzik 				modestr, list[i]);
233669a5db4SJeff Garzik 			return 1;
234669a5db4SJeff Garzik 		}
235669a5db4SJeff Garzik 		i++;
236669a5db4SJeff Garzik 	}
237669a5db4SJeff Garzik 	return 0;
238669a5db4SJeff Garzik }
239669a5db4SJeff Garzik 
240669a5db4SJeff Garzik static const char *bad_ata33[] = {
241669a5db4SJeff Garzik 	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
242669a5db4SJeff Garzik 	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
243669a5db4SJeff Garzik 	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
244669a5db4SJeff Garzik 	"Maxtor 90510D4",
245669a5db4SJeff Garzik 	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
246669a5db4SJeff Garzik 	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
247669a5db4SJeff Garzik 	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
248669a5db4SJeff Garzik 	NULL
249669a5db4SJeff Garzik };
250669a5db4SJeff Garzik 
251669a5db4SJeff Garzik static const char *bad_ata100_5[] = {
252669a5db4SJeff Garzik 	"IBM-DTLA-307075",
253669a5db4SJeff Garzik 	"IBM-DTLA-307060",
254669a5db4SJeff Garzik 	"IBM-DTLA-307045",
255669a5db4SJeff Garzik 	"IBM-DTLA-307030",
256669a5db4SJeff Garzik 	"IBM-DTLA-307020",
257669a5db4SJeff Garzik 	"IBM-DTLA-307015",
258669a5db4SJeff Garzik 	"IBM-DTLA-305040",
259669a5db4SJeff Garzik 	"IBM-DTLA-305030",
260669a5db4SJeff Garzik 	"IBM-DTLA-305020",
261669a5db4SJeff Garzik 	"IC35L010AVER07-0",
262669a5db4SJeff Garzik 	"IC35L020AVER07-0",
263669a5db4SJeff Garzik 	"IC35L030AVER07-0",
264669a5db4SJeff Garzik 	"IC35L040AVER07-0",
265669a5db4SJeff Garzik 	"IC35L060AVER07-0",
266669a5db4SJeff Garzik 	"WDC AC310200R",
267669a5db4SJeff Garzik 	NULL
268669a5db4SJeff Garzik };
269669a5db4SJeff Garzik 
270669a5db4SJeff Garzik /**
271669a5db4SJeff Garzik  *	hpt370_filter	-	mode selection filter
272669a5db4SJeff Garzik  *	@adev: ATA device
273669a5db4SJeff Garzik  *
274669a5db4SJeff Garzik  *	Block UDMA on devices that cause trouble with this controller.
275669a5db4SJeff Garzik  */
276669a5db4SJeff Garzik 
277a76b62caSAlan Cox static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask)
278669a5db4SJeff Garzik {
2796929da44SAlan 	if (adev->class == ATA_DEV_ATA) {
280669a5db4SJeff Garzik 		if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33))
281669a5db4SJeff Garzik 			mask &= ~ATA_MASK_UDMA;
282669a5db4SJeff Garzik 		if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
2836ddd6861SAlan Cox 			mask &= ~(0xE0 << ATA_SHIFT_UDMA);
284669a5db4SJeff Garzik 	}
285c7087652STejun Heo 	return mask;
286669a5db4SJeff Garzik }
287669a5db4SJeff Garzik 
288669a5db4SJeff Garzik /**
289669a5db4SJeff Garzik  *	hpt370a_filter	-	mode selection filter
290669a5db4SJeff Garzik  *	@adev: ATA device
291669a5db4SJeff Garzik  *
292669a5db4SJeff Garzik  *	Block UDMA on devices that cause trouble with this controller.
293669a5db4SJeff Garzik  */
294669a5db4SJeff Garzik 
295a76b62caSAlan Cox static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
296669a5db4SJeff Garzik {
29773946f9fSAlan Cox 	if (adev->class == ATA_DEV_ATA) {
298669a5db4SJeff Garzik 		if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
2996ddd6861SAlan Cox 			mask &= ~(0xE0 << ATA_SHIFT_UDMA);
300669a5db4SJeff Garzik 	}
301c7087652STejun Heo 	return mask;
302669a5db4SJeff Garzik }
303669a5db4SJeff Garzik 
304669a5db4SJeff Garzik /**
3059e87be9eSBartlomiej Zolnierkiewicz  *	hpt37x_cable_detect	-	Detect the cable type
3069e87be9eSBartlomiej Zolnierkiewicz  *	@ap: ATA port to detect on
307669a5db4SJeff Garzik  *
3089e87be9eSBartlomiej Zolnierkiewicz  *	Return the cable type attached to this port
309669a5db4SJeff Garzik  */
310669a5db4SJeff Garzik 
3119e87be9eSBartlomiej Zolnierkiewicz static int hpt37x_cable_detect(struct ata_port *ap)
312669a5db4SJeff Garzik {
313669a5db4SJeff Garzik 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
3149e87be9eSBartlomiej Zolnierkiewicz 	u8 scr2, ata66;
315669a5db4SJeff Garzik 
316669a5db4SJeff Garzik 	pci_read_config_byte(pdev, 0x5B, &scr2);
317669a5db4SJeff Garzik 	pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01);
31810a9c969SBartlomiej Zolnierkiewicz 
31910a9c969SBartlomiej Zolnierkiewicz 	udelay(10); /* debounce */
32010a9c969SBartlomiej Zolnierkiewicz 
321669a5db4SJeff Garzik 	/* Cable register now active */
322669a5db4SJeff Garzik 	pci_read_config_byte(pdev, 0x5A, &ata66);
323669a5db4SJeff Garzik 	/* Restore state */
324669a5db4SJeff Garzik 	pci_write_config_byte(pdev, 0x5B, scr2);
325669a5db4SJeff Garzik 
32622d5c760SAlan Cox 	if (ata66 & (2 >> ap->port_no))
3279e87be9eSBartlomiej Zolnierkiewicz 		return ATA_CBL_PATA40;
328669a5db4SJeff Garzik 	else
3299e87be9eSBartlomiej Zolnierkiewicz 		return ATA_CBL_PATA80;
3309e87be9eSBartlomiej Zolnierkiewicz }
3319e87be9eSBartlomiej Zolnierkiewicz 
3329e87be9eSBartlomiej Zolnierkiewicz /**
3339e87be9eSBartlomiej Zolnierkiewicz  *	hpt374_fn1_cable_detect	-	Detect the cable type
3349e87be9eSBartlomiej Zolnierkiewicz  *	@ap: ATA port to detect on
3359e87be9eSBartlomiej Zolnierkiewicz  *
3369e87be9eSBartlomiej Zolnierkiewicz  *	Return the cable type attached to this port
3379e87be9eSBartlomiej Zolnierkiewicz  */
3389e87be9eSBartlomiej Zolnierkiewicz 
3399e87be9eSBartlomiej Zolnierkiewicz static int hpt374_fn1_cable_detect(struct ata_port *ap)
3409e87be9eSBartlomiej Zolnierkiewicz {
3419e87be9eSBartlomiej Zolnierkiewicz 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
3429e87be9eSBartlomiej Zolnierkiewicz 	unsigned int mcrbase = 0x50 + 4 * ap->port_no;
3439e87be9eSBartlomiej Zolnierkiewicz 	u16 mcr3;
3449e87be9eSBartlomiej Zolnierkiewicz 	u8 ata66;
3459e87be9eSBartlomiej Zolnierkiewicz 
3469e87be9eSBartlomiej Zolnierkiewicz 	/* Do the extra channel work */
3479e87be9eSBartlomiej Zolnierkiewicz 	pci_read_config_word(pdev, mcrbase + 2, &mcr3);
3489e87be9eSBartlomiej Zolnierkiewicz 	/* Set bit 15 of 0x52 to enable TCBLID as input */
3499e87be9eSBartlomiej Zolnierkiewicz 	pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000);
3509e87be9eSBartlomiej Zolnierkiewicz 	pci_read_config_byte(pdev, 0x5A, &ata66);
3519e87be9eSBartlomiej Zolnierkiewicz 	/* Reset TCBLID/FCBLID to output */
3529e87be9eSBartlomiej Zolnierkiewicz 	pci_write_config_word(pdev, mcrbase + 2, mcr3);
3539e87be9eSBartlomiej Zolnierkiewicz 
3549e87be9eSBartlomiej Zolnierkiewicz 	if (ata66 & (2 >> ap->port_no))
3559e87be9eSBartlomiej Zolnierkiewicz 		return ATA_CBL_PATA40;
3569e87be9eSBartlomiej Zolnierkiewicz 	else
3579e87be9eSBartlomiej Zolnierkiewicz 		return ATA_CBL_PATA80;
3589e87be9eSBartlomiej Zolnierkiewicz }
3599e87be9eSBartlomiej Zolnierkiewicz 
3609e87be9eSBartlomiej Zolnierkiewicz /**
3619e87be9eSBartlomiej Zolnierkiewicz  *	hpt37x_pre_reset	-	reset the hpt37x bus
3629e87be9eSBartlomiej Zolnierkiewicz  *	@link: ATA link to reset
3639e87be9eSBartlomiej Zolnierkiewicz  *	@deadline: deadline jiffies for the operation
3649e87be9eSBartlomiej Zolnierkiewicz  *
365ab81a505SBartlomiej Zolnierkiewicz  *	Perform the initial reset handling for the HPT37x.
3669e87be9eSBartlomiej Zolnierkiewicz  */
3679e87be9eSBartlomiej Zolnierkiewicz 
3689e87be9eSBartlomiej Zolnierkiewicz static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)
3699e87be9eSBartlomiej Zolnierkiewicz {
3709e87be9eSBartlomiej Zolnierkiewicz 	struct ata_port *ap = link->ap;
3719e87be9eSBartlomiej Zolnierkiewicz 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
3729e87be9eSBartlomiej Zolnierkiewicz 	static const struct pci_bits hpt37x_enable_bits[] = {
3739e87be9eSBartlomiej Zolnierkiewicz 		{ 0x50, 1, 0x04, 0x04 },
3749e87be9eSBartlomiej Zolnierkiewicz 		{ 0x54, 1, 0x04, 0x04 }
3759e87be9eSBartlomiej Zolnierkiewicz 	};
3769e87be9eSBartlomiej Zolnierkiewicz 	if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
3779e87be9eSBartlomiej Zolnierkiewicz 		return -ENOENT;
378669a5db4SJeff Garzik 
379669a5db4SJeff Garzik 	/* Reset the state machine */
380fcc2f69aSAlan Cox 	pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
381669a5db4SJeff Garzik 	udelay(100);
382669a5db4SJeff Garzik 
3839363c382STejun Heo 	return ata_sff_prereset(link, deadline);
384669a5db4SJeff Garzik }
385669a5db4SJeff Garzik 
3861a1b172bSSergei Shtylyov static void hpt370_set_mode(struct ata_port *ap, struct ata_device *adev,
3871a1b172bSSergei Shtylyov 			    u8 mode)
3881a1b172bSSergei Shtylyov {
3891a1b172bSSergei Shtylyov 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
3901a1b172bSSergei Shtylyov 	u32 addr1, addr2;
3911a1b172bSSergei Shtylyov 	u32 reg, timing, mask;
3921a1b172bSSergei Shtylyov 	u8 fast;
3931a1b172bSSergei Shtylyov 
3941a1b172bSSergei Shtylyov 	addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
3951a1b172bSSergei Shtylyov 	addr2 = 0x51 + 4 * ap->port_no;
3961a1b172bSSergei Shtylyov 
3971a1b172bSSergei Shtylyov 	/* Fast interrupt prediction disable, hold off interrupt disable */
3981a1b172bSSergei Shtylyov 	pci_read_config_byte(pdev, addr2, &fast);
3991a1b172bSSergei Shtylyov 	fast &= ~0x02;
4001a1b172bSSergei Shtylyov 	fast |= 0x01;
4011a1b172bSSergei Shtylyov 	pci_write_config_byte(pdev, addr2, fast);
4021a1b172bSSergei Shtylyov 
4031a1b172bSSergei Shtylyov 	/* Determine timing mask and find matching mode entry */
4041a1b172bSSergei Shtylyov 	if (mode < XFER_MW_DMA_0)
4051a1b172bSSergei Shtylyov 		mask = 0xcfc3ffff;
4061a1b172bSSergei Shtylyov 	else if (mode < XFER_UDMA_0)
4071a1b172bSSergei Shtylyov 		mask = 0x31c001ff;
4081a1b172bSSergei Shtylyov 	else
4091a1b172bSSergei Shtylyov 		mask = 0x303c0000;
4101a1b172bSSergei Shtylyov 
4111a1b172bSSergei Shtylyov 	timing = hpt37x_find_mode(ap, mode);
4121a1b172bSSergei Shtylyov 
4131a1b172bSSergei Shtylyov 	pci_read_config_dword(pdev, addr1, &reg);
4141a1b172bSSergei Shtylyov 	reg = (reg & ~mask) | (timing & mask);
4151a1b172bSSergei Shtylyov 	pci_write_config_dword(pdev, addr1, reg);
4161a1b172bSSergei Shtylyov }
417669a5db4SJeff Garzik /**
418669a5db4SJeff Garzik  *	hpt370_set_piomode		-	PIO setup
419669a5db4SJeff Garzik  *	@ap: ATA interface
420669a5db4SJeff Garzik  *	@adev: device on the interface
421669a5db4SJeff Garzik  *
422669a5db4SJeff Garzik  *	Perform PIO mode setup.
423669a5db4SJeff Garzik  */
424669a5db4SJeff Garzik 
425669a5db4SJeff Garzik static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev)
426669a5db4SJeff Garzik {
4271a1b172bSSergei Shtylyov 	hpt370_set_mode(ap, adev, adev->pio_mode);
428669a5db4SJeff Garzik }
429669a5db4SJeff Garzik 
430669a5db4SJeff Garzik /**
431669a5db4SJeff Garzik  *	hpt370_set_dmamode		-	DMA timing setup
432669a5db4SJeff Garzik  *	@ap: ATA interface
433669a5db4SJeff Garzik  *	@adev: Device being configured
434669a5db4SJeff Garzik  *
4351a1b172bSSergei Shtylyov  *	Set up the channel for MWDMA or UDMA modes.
436669a5db4SJeff Garzik  */
437669a5db4SJeff Garzik 
438669a5db4SJeff Garzik static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev)
439669a5db4SJeff Garzik {
4401a1b172bSSergei Shtylyov 	hpt370_set_mode(ap, adev, adev->dma_mode);
441669a5db4SJeff Garzik }
442669a5db4SJeff Garzik 
443669a5db4SJeff Garzik /**
444669a5db4SJeff Garzik  *	hpt370_bmdma_end		-	DMA engine stop
445669a5db4SJeff Garzik  *	@qc: ATA command
446669a5db4SJeff Garzik  *
447669a5db4SJeff Garzik  *	Work around the HPT370 DMA engine.
448669a5db4SJeff Garzik  */
449669a5db4SJeff Garzik 
450669a5db4SJeff Garzik static void hpt370_bmdma_stop(struct ata_queued_cmd *qc)
451669a5db4SJeff Garzik {
452669a5db4SJeff Garzik 	struct ata_port *ap = qc->ap;
453669a5db4SJeff Garzik 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
4540d5ff566STejun Heo 	void __iomem *bmdma = ap->ioaddr.bmdma_addr;
45556f46f8cSSergei Shtylyov 	u8 dma_stat = ioread8(bmdma + ATA_DMA_STATUS);
45656f46f8cSSergei Shtylyov 	u8 dma_cmd;
457669a5db4SJeff Garzik 
45856f46f8cSSergei Shtylyov 	if (dma_stat & ATA_DMA_ACTIVE) {
459669a5db4SJeff Garzik 		udelay(20);
46056f46f8cSSergei Shtylyov 		dma_stat = ioread8(bmdma + ATA_DMA_STATUS);
461669a5db4SJeff Garzik 	}
46256f46f8cSSergei Shtylyov 	if (dma_stat & ATA_DMA_ACTIVE) {
463669a5db4SJeff Garzik 		/* Clear the engine */
464669a5db4SJeff Garzik 		pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
465669a5db4SJeff Garzik 		udelay(10);
466669a5db4SJeff Garzik 		/* Stop DMA */
46756f46f8cSSergei Shtylyov 		dma_cmd = ioread8(bmdma + ATA_DMA_CMD);
46856f46f8cSSergei Shtylyov 		iowrite8(dma_cmd & ~ATA_DMA_START, bmdma + ATA_DMA_CMD);
469669a5db4SJeff Garzik 		/* Clear Error */
47056f46f8cSSergei Shtylyov 		dma_stat = ioread8(bmdma + ATA_DMA_STATUS);
47156f46f8cSSergei Shtylyov 		iowrite8(dma_stat | ATA_DMA_INTR | ATA_DMA_ERR,
47256f46f8cSSergei Shtylyov 			 bmdma + ATA_DMA_STATUS);
473669a5db4SJeff Garzik 		/* Clear the engine */
474669a5db4SJeff Garzik 		pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
475669a5db4SJeff Garzik 		udelay(10);
476669a5db4SJeff Garzik 	}
477669a5db4SJeff Garzik 	ata_bmdma_stop(qc);
478669a5db4SJeff Garzik }
479669a5db4SJeff Garzik 
4801a1b172bSSergei Shtylyov static void hpt372_set_mode(struct ata_port *ap, struct ata_device *adev,
4811a1b172bSSergei Shtylyov 			    u8 mode)
4821a1b172bSSergei Shtylyov {
4831a1b172bSSergei Shtylyov 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
4841a1b172bSSergei Shtylyov 	u32 addr1, addr2;
4851a1b172bSSergei Shtylyov 	u32 reg, timing, mask;
4861a1b172bSSergei Shtylyov 	u8 fast;
4871a1b172bSSergei Shtylyov 
4881a1b172bSSergei Shtylyov 	addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
4891a1b172bSSergei Shtylyov 	addr2 = 0x51 + 4 * ap->port_no;
4901a1b172bSSergei Shtylyov 
4911a1b172bSSergei Shtylyov 	/* Fast interrupt prediction disable, hold off interrupt disable */
4921a1b172bSSergei Shtylyov 	pci_read_config_byte(pdev, addr2, &fast);
4931a1b172bSSergei Shtylyov 	fast &= ~0x07;
4941a1b172bSSergei Shtylyov 	pci_write_config_byte(pdev, addr2, fast);
4951a1b172bSSergei Shtylyov 
4961a1b172bSSergei Shtylyov 	/* Determine timing mask and find matching mode entry */
4971a1b172bSSergei Shtylyov 	if (mode < XFER_MW_DMA_0)
4981a1b172bSSergei Shtylyov 		mask = 0xcfc3ffff;
4991a1b172bSSergei Shtylyov 	else if (mode < XFER_UDMA_0)
5001a1b172bSSergei Shtylyov 		mask = 0x31c001ff;
5011a1b172bSSergei Shtylyov 	else
5021a1b172bSSergei Shtylyov 		mask = 0x303c0000;
5031a1b172bSSergei Shtylyov 
5041a1b172bSSergei Shtylyov 	timing = hpt37x_find_mode(ap, mode);
5051a1b172bSSergei Shtylyov 
5061a1b172bSSergei Shtylyov 	pci_read_config_dword(pdev, addr1, &reg);
5071a1b172bSSergei Shtylyov 	reg = (reg & ~mask) | (timing & mask);
5081a1b172bSSergei Shtylyov 	pci_write_config_dword(pdev, addr1, reg);
5091a1b172bSSergei Shtylyov }
5101a1b172bSSergei Shtylyov 
511669a5db4SJeff Garzik /**
512669a5db4SJeff Garzik  *	hpt372_set_piomode		-	PIO setup
513669a5db4SJeff Garzik  *	@ap: ATA interface
514669a5db4SJeff Garzik  *	@adev: device on the interface
515669a5db4SJeff Garzik  *
516669a5db4SJeff Garzik  *	Perform PIO mode setup.
517669a5db4SJeff Garzik  */
518669a5db4SJeff Garzik 
519669a5db4SJeff Garzik static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev)
520669a5db4SJeff Garzik {
5211a1b172bSSergei Shtylyov 	hpt372_set_mode(ap, adev, adev->pio_mode);
522669a5db4SJeff Garzik }
523669a5db4SJeff Garzik 
524669a5db4SJeff Garzik /**
525669a5db4SJeff Garzik  *	hpt372_set_dmamode		-	DMA timing setup
526669a5db4SJeff Garzik  *	@ap: ATA interface
527669a5db4SJeff Garzik  *	@adev: Device being configured
528669a5db4SJeff Garzik  *
5291a1b172bSSergei Shtylyov  *	Set up the channel for MWDMA or UDMA modes.
530669a5db4SJeff Garzik  */
531669a5db4SJeff Garzik 
532669a5db4SJeff Garzik static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev)
533669a5db4SJeff Garzik {
5341a1b172bSSergei Shtylyov 	hpt372_set_mode(ap, adev, adev->dma_mode);
535669a5db4SJeff Garzik }
536669a5db4SJeff Garzik 
537669a5db4SJeff Garzik /**
538669a5db4SJeff Garzik  *	hpt37x_bmdma_end		-	DMA engine stop
539669a5db4SJeff Garzik  *	@qc: ATA command
540669a5db4SJeff Garzik  *
541669a5db4SJeff Garzik  *	Clean up after the HPT372 and later DMA engine
542669a5db4SJeff Garzik  */
543669a5db4SJeff Garzik 
544669a5db4SJeff Garzik static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc)
545669a5db4SJeff Garzik {
546669a5db4SJeff Garzik 	struct ata_port *ap = qc->ap;
547669a5db4SJeff Garzik 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
5486929da44SAlan 	int mscreg = 0x50 + 4 * ap->port_no;
549669a5db4SJeff Garzik 	u8 bwsr_stat, msc_stat;
550669a5db4SJeff Garzik 
551669a5db4SJeff Garzik 	pci_read_config_byte(pdev, 0x6A, &bwsr_stat);
552669a5db4SJeff Garzik 	pci_read_config_byte(pdev, mscreg, &msc_stat);
553669a5db4SJeff Garzik 	if (bwsr_stat & (1 << ap->port_no))
554669a5db4SJeff Garzik 		pci_write_config_byte(pdev, mscreg, msc_stat | 0x30);
555669a5db4SJeff Garzik 	ata_bmdma_stop(qc);
556669a5db4SJeff Garzik }
557669a5db4SJeff Garzik 
558669a5db4SJeff Garzik 
559669a5db4SJeff Garzik static struct scsi_host_template hpt37x_sht = {
56068d1d07bSTejun Heo 	ATA_BMDMA_SHT(DRV_NAME),
561669a5db4SJeff Garzik };
562669a5db4SJeff Garzik 
563669a5db4SJeff Garzik /*
564669a5db4SJeff Garzik  *	Configuration for HPT370
565669a5db4SJeff Garzik  */
566669a5db4SJeff Garzik 
567669a5db4SJeff Garzik static struct ata_port_operations hpt370_port_ops = {
568029cfd6bSTejun Heo 	.inherits	= &ata_bmdma_port_ops,
569669a5db4SJeff Garzik 
570669a5db4SJeff Garzik 	.bmdma_stop	= hpt370_bmdma_stop,
571669a5db4SJeff Garzik 
572029cfd6bSTejun Heo 	.mode_filter	= hpt370_filter,
5739e87be9eSBartlomiej Zolnierkiewicz 	.cable_detect	= hpt37x_cable_detect,
574029cfd6bSTejun Heo 	.set_piomode	= hpt370_set_piomode,
575029cfd6bSTejun Heo 	.set_dmamode	= hpt370_set_dmamode,
576a1efdabaSTejun Heo 	.prereset	= hpt37x_pre_reset,
577669a5db4SJeff Garzik };
578669a5db4SJeff Garzik 
579669a5db4SJeff Garzik /*
580669a5db4SJeff Garzik  *	Configuration for HPT370A. Close to 370 but less filters
581669a5db4SJeff Garzik  */
582669a5db4SJeff Garzik 
583669a5db4SJeff Garzik static struct ata_port_operations hpt370a_port_ops = {
584029cfd6bSTejun Heo 	.inherits	= &hpt370_port_ops,
585669a5db4SJeff Garzik 	.mode_filter	= hpt370a_filter,
586669a5db4SJeff Garzik };
587669a5db4SJeff Garzik 
588669a5db4SJeff Garzik /*
589669a5db4SJeff Garzik  *	Configuration for HPT372, HPT371, HPT302. Slightly different PIO
590669a5db4SJeff Garzik  *	and DMA mode setting functionality.
591669a5db4SJeff Garzik  */
592669a5db4SJeff Garzik 
593669a5db4SJeff Garzik static struct ata_port_operations hpt372_port_ops = {
594029cfd6bSTejun Heo 	.inherits	= &ata_bmdma_port_ops,
595029cfd6bSTejun Heo 
596029cfd6bSTejun Heo 	.bmdma_stop	= hpt37x_bmdma_stop,
597029cfd6bSTejun Heo 
5989e87be9eSBartlomiej Zolnierkiewicz 	.cable_detect	= hpt37x_cable_detect,
599669a5db4SJeff Garzik 	.set_piomode	= hpt372_set_piomode,
600669a5db4SJeff Garzik 	.set_dmamode	= hpt372_set_dmamode,
601a1efdabaSTejun Heo 	.prereset	= hpt37x_pre_reset,
602669a5db4SJeff Garzik };
603669a5db4SJeff Garzik 
604669a5db4SJeff Garzik /*
605669a5db4SJeff Garzik  *	Configuration for HPT374. Mode setting works like 372 and friends
606a1efdabaSTejun Heo  *	but we have a different cable detection procedure for function 1.
607669a5db4SJeff Garzik  */
608669a5db4SJeff Garzik 
609a1efdabaSTejun Heo static struct ata_port_operations hpt374_fn1_port_ops = {
610029cfd6bSTejun Heo 	.inherits	= &hpt372_port_ops,
6119e87be9eSBartlomiej Zolnierkiewicz 	.cable_detect	= hpt374_fn1_cable_detect,
612ab81a505SBartlomiej Zolnierkiewicz 	.prereset	= hpt37x_pre_reset,
613669a5db4SJeff Garzik };
614669a5db4SJeff Garzik 
615669a5db4SJeff Garzik /**
616ad452d64SKrzysztof Halasa  *	hpt37x_clock_slot	-	Turn timing to PC clock entry
617669a5db4SJeff Garzik  *	@freq: Reported frequency timing
618669a5db4SJeff Garzik  *	@base: Base timing
619669a5db4SJeff Garzik  *
620669a5db4SJeff Garzik  *	Turn the timing data intoa clock slot (0 for 33, 1 for 40, 2 for 50
621669a5db4SJeff Garzik  *	and 3 for 66Mhz)
622669a5db4SJeff Garzik  */
623669a5db4SJeff Garzik 
624669a5db4SJeff Garzik static int hpt37x_clock_slot(unsigned int freq, unsigned int base)
625669a5db4SJeff Garzik {
626669a5db4SJeff Garzik 	unsigned int f = (base * freq) / 192;	/* Mhz */
627669a5db4SJeff Garzik 	if (f < 40)
628669a5db4SJeff Garzik 		return 0;	/* 33Mhz slot */
629669a5db4SJeff Garzik 	if (f < 45)
630669a5db4SJeff Garzik 		return 1;	/* 40Mhz slot */
631669a5db4SJeff Garzik 	if (f < 55)
632669a5db4SJeff Garzik 		return 2;	/* 50Mhz slot */
633669a5db4SJeff Garzik 	return 3;		/* 60Mhz slot */
634669a5db4SJeff Garzik }
635669a5db4SJeff Garzik 
636669a5db4SJeff Garzik /**
637669a5db4SJeff Garzik  *	hpt37x_calibrate_dpll		-	Calibrate the DPLL loop
638669a5db4SJeff Garzik  *	@dev: PCI device
639669a5db4SJeff Garzik  *
640669a5db4SJeff Garzik  *	Perform a calibration cycle on the HPT37x DPLL. Returns 1 if this
641669a5db4SJeff Garzik  *	succeeds
642669a5db4SJeff Garzik  */
643669a5db4SJeff Garzik 
644669a5db4SJeff Garzik static int hpt37x_calibrate_dpll(struct pci_dev *dev)
645669a5db4SJeff Garzik {
646669a5db4SJeff Garzik 	u8 reg5b;
647669a5db4SJeff Garzik 	u32 reg5c;
648669a5db4SJeff Garzik 	int tries;
649669a5db4SJeff Garzik 
650669a5db4SJeff Garzik 	for(tries = 0; tries < 0x5000; tries++) {
651669a5db4SJeff Garzik 		udelay(50);
652669a5db4SJeff Garzik 		pci_read_config_byte(dev, 0x5b, &reg5b);
653669a5db4SJeff Garzik 		if (reg5b & 0x80) {
654669a5db4SJeff Garzik 			/* See if it stays set */
655669a5db4SJeff Garzik 			for(tries = 0; tries < 0x1000; tries ++) {
656669a5db4SJeff Garzik 				pci_read_config_byte(dev, 0x5b, &reg5b);
657669a5db4SJeff Garzik 				/* Failed ? */
658669a5db4SJeff Garzik 				if ((reg5b & 0x80) == 0)
659669a5db4SJeff Garzik 					return 0;
660669a5db4SJeff Garzik 			}
661669a5db4SJeff Garzik 			/* Turn off tuning, we have the DPLL set */
662669a5db4SJeff Garzik 			pci_read_config_dword(dev, 0x5c, &reg5c);
663669a5db4SJeff Garzik 			pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100);
664669a5db4SJeff Garzik 			return 1;
665669a5db4SJeff Garzik 		}
666669a5db4SJeff Garzik 	}
667669a5db4SJeff Garzik 	/* Never went stable */
668669a5db4SJeff Garzik 	return 0;
669669a5db4SJeff Garzik }
67073946f9fSAlan Cox 
67173946f9fSAlan Cox static u32 hpt374_read_freq(struct pci_dev *pdev)
67273946f9fSAlan Cox {
67373946f9fSAlan Cox 	u32 freq;
67473946f9fSAlan Cox 	unsigned long io_base = pci_resource_start(pdev, 4);
67573946f9fSAlan Cox 	if (PCI_FUNC(pdev->devfn) & 1) {
67640f46f17SAndrew Morton 		struct pci_dev *pdev_0;
67740f46f17SAndrew Morton 
67840f46f17SAndrew Morton 		pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
67973946f9fSAlan Cox 		/* Someone hot plugged the controller on us ? */
68073946f9fSAlan Cox 		if (pdev_0 == NULL)
68173946f9fSAlan Cox 			return 0;
68273946f9fSAlan Cox 		io_base = pci_resource_start(pdev_0, 4);
68373946f9fSAlan Cox 		freq = inl(io_base + 0x90);
68473946f9fSAlan Cox 		pci_dev_put(pdev_0);
68540f46f17SAndrew Morton 	} else
68673946f9fSAlan Cox 		freq = inl(io_base + 0x90);
68773946f9fSAlan Cox 	return freq;
68873946f9fSAlan Cox }
68973946f9fSAlan Cox 
690669a5db4SJeff Garzik /**
691669a5db4SJeff Garzik  *	hpt37x_init_one		-	Initialise an HPT37X/302
692669a5db4SJeff Garzik  *	@dev: PCI device
693669a5db4SJeff Garzik  *	@id: Entry in match table
694669a5db4SJeff Garzik  *
695669a5db4SJeff Garzik  *	Initialise an HPT37x device. There are some interesting complications
696669a5db4SJeff Garzik  *	here. Firstly the chip may report 366 and be one of several variants.
697669a5db4SJeff Garzik  *	Secondly all the timings depend on the clock for the chip which we must
698669a5db4SJeff Garzik  *	detect and look up
699669a5db4SJeff Garzik  *
700669a5db4SJeff Garzik  *	This is the known chip mappings. It may be missing a couple of later
701669a5db4SJeff Garzik  *	releases.
702669a5db4SJeff Garzik  *
703669a5db4SJeff Garzik  *	Chip version		PCI		Rev	Notes
704669a5db4SJeff Garzik  *	HPT366			4 (HPT366)	0	Other driver
705669a5db4SJeff Garzik  *	HPT366			4 (HPT366)	1	Other driver
706669a5db4SJeff Garzik  *	HPT368			4 (HPT366)	2	Other driver
707669a5db4SJeff Garzik  *	HPT370			4 (HPT366)	3	UDMA100
708669a5db4SJeff Garzik  *	HPT370A			4 (HPT366)	4	UDMA100
709669a5db4SJeff Garzik  *	HPT372			4 (HPT366)	5	UDMA133 (1)
710669a5db4SJeff Garzik  *	HPT372N			4 (HPT366)	6	Other driver
711669a5db4SJeff Garzik  *	HPT372A			5 (HPT372)	1	UDMA133 (1)
712669a5db4SJeff Garzik  *	HPT372N			5 (HPT372)	2	Other driver
713669a5db4SJeff Garzik  *	HPT302			6 (HPT302)	1	UDMA133
714669a5db4SJeff Garzik  *	HPT302N			6 (HPT302)	2	Other driver
715669a5db4SJeff Garzik  *	HPT371			7 (HPT371)	*	UDMA133
716669a5db4SJeff Garzik  *	HPT374			8 (HPT374)	*	UDMA133 4 channel
717669a5db4SJeff Garzik  *	HPT372N			9 (HPT372N)	*	Other driver
718669a5db4SJeff Garzik  *
719669a5db4SJeff Garzik  *	(1) UDMA133 support depends on the bus clock
720669a5db4SJeff Garzik  */
721669a5db4SJeff Garzik 
722669a5db4SJeff Garzik static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
723669a5db4SJeff Garzik {
724669a5db4SJeff Garzik 	/* HPT370 - UDMA100 */
7251626aeb8STejun Heo 	static const struct ata_port_info info_hpt370 = {
7261d2808fdSJeff Garzik 		.flags = ATA_FLAG_SLAVE_POSS,
72714bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
72814bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
729bf6263a8SJeff Garzik 		.udma_mask = ATA_UDMA5,
730669a5db4SJeff Garzik 		.port_ops = &hpt370_port_ops
731669a5db4SJeff Garzik 	};
732669a5db4SJeff Garzik 	/* HPT370A - UDMA100 */
7331626aeb8STejun Heo 	static const struct ata_port_info info_hpt370a = {
7341d2808fdSJeff Garzik 		.flags = ATA_FLAG_SLAVE_POSS,
73514bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
73614bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
737bf6263a8SJeff Garzik 		.udma_mask = ATA_UDMA5,
738669a5db4SJeff Garzik 		.port_ops = &hpt370a_port_ops
739669a5db4SJeff Garzik 	};
740fcc2f69aSAlan Cox 	/* HPT370 - UDMA100 */
7411626aeb8STejun Heo 	static const struct ata_port_info info_hpt370_33 = {
7421d2808fdSJeff Garzik 		.flags = ATA_FLAG_SLAVE_POSS,
74314bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
74414bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
74573946f9fSAlan Cox 		.udma_mask = ATA_UDMA5,
746fcc2f69aSAlan Cox 		.port_ops = &hpt370_port_ops
747fcc2f69aSAlan Cox 	};
748fcc2f69aSAlan Cox 	/* HPT370A - UDMA100 */
7491626aeb8STejun Heo 	static const struct ata_port_info info_hpt370a_33 = {
7501d2808fdSJeff Garzik 		.flags = ATA_FLAG_SLAVE_POSS,
75114bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
75214bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
75373946f9fSAlan Cox 		.udma_mask = ATA_UDMA5,
754fcc2f69aSAlan Cox 		.port_ops = &hpt370a_port_ops
755fcc2f69aSAlan Cox 	};
756669a5db4SJeff Garzik 	/* HPT371, 372 and friends - UDMA133 */
7571626aeb8STejun Heo 	static const struct ata_port_info info_hpt372 = {
7581d2808fdSJeff Garzik 		.flags = ATA_FLAG_SLAVE_POSS,
75914bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
76014bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
761bf6263a8SJeff Garzik 		.udma_mask = ATA_UDMA6,
762669a5db4SJeff Garzik 		.port_ops = &hpt372_port_ops
763669a5db4SJeff Garzik 	};
764a1efdabaSTejun Heo 	/* HPT374 - UDMA100, function 1 uses different prereset method */
765a1efdabaSTejun Heo 	static const struct ata_port_info info_hpt374_fn0 = {
7661d2808fdSJeff Garzik 		.flags = ATA_FLAG_SLAVE_POSS,
76714bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
76814bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
769bf6263a8SJeff Garzik 		.udma_mask = ATA_UDMA5,
770a1efdabaSTejun Heo 		.port_ops = &hpt372_port_ops
771a1efdabaSTejun Heo 	};
772a1efdabaSTejun Heo 	static const struct ata_port_info info_hpt374_fn1 = {
773a1efdabaSTejun Heo 		.flags = ATA_FLAG_SLAVE_POSS,
77414bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
77514bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
776a1efdabaSTejun Heo 		.udma_mask = ATA_UDMA5,
777a1efdabaSTejun Heo 		.port_ops = &hpt374_fn1_port_ops
778669a5db4SJeff Garzik 	};
779669a5db4SJeff Garzik 
780669a5db4SJeff Garzik 	static const int MHz[4] = { 33, 40, 50, 66 };
7811626aeb8STejun Heo 	void *private_data = NULL;
782887125e3STejun Heo 	const struct ata_port_info *ppi[] = { NULL, NULL };
78389d3b360SSergei Shtylyov 	u8 rev = dev->revision;
784669a5db4SJeff Garzik 	u8 irqmask;
785fcc2f69aSAlan Cox 	u8 mcr1;
786669a5db4SJeff Garzik 	u32 freq;
787fcc2f69aSAlan Cox 	int prefer_dpll = 1;
788fcc2f69aSAlan Cox 
789fcc2f69aSAlan Cox 	unsigned long iobase = pci_resource_start(dev, 4);
790669a5db4SJeff Garzik 
791669a5db4SJeff Garzik 	const struct hpt_chip *chip_table;
792669a5db4SJeff Garzik 	int clock_slot;
793f08048e9STejun Heo 	int rc;
794f08048e9STejun Heo 
795f08048e9STejun Heo 	rc = pcim_enable_device(dev);
796f08048e9STejun Heo 	if (rc)
797f08048e9STejun Heo 		return rc;
798669a5db4SJeff Garzik 
799669a5db4SJeff Garzik 	if (dev->device == PCI_DEVICE_ID_TTI_HPT366) {
800669a5db4SJeff Garzik 		/* May be a later chip in disguise. Check */
801669a5db4SJeff Garzik 		/* Older chips are in the HPT366 driver. Ignore them */
80289d3b360SSergei Shtylyov 		if (rev < 3)
803669a5db4SJeff Garzik 			return -ENODEV;
804669a5db4SJeff Garzik 		/* N series chips have their own driver. Ignore */
80589d3b360SSergei Shtylyov 		if (rev == 6)
806669a5db4SJeff Garzik 			return -ENODEV;
807669a5db4SJeff Garzik 
80889d3b360SSergei Shtylyov 		switch(rev) {
809669a5db4SJeff Garzik 			case 3:
810887125e3STejun Heo 				ppi[0] = &info_hpt370;
811669a5db4SJeff Garzik 				chip_table = &hpt370;
812fcc2f69aSAlan Cox 				prefer_dpll = 0;
813669a5db4SJeff Garzik 				break;
814669a5db4SJeff Garzik 			case 4:
815887125e3STejun Heo 				ppi[0] = &info_hpt370a;
816669a5db4SJeff Garzik 				chip_table = &hpt370a;
817fcc2f69aSAlan Cox 				prefer_dpll = 0;
818669a5db4SJeff Garzik 				break;
819669a5db4SJeff Garzik 			case 5:
820887125e3STejun Heo 				ppi[0] = &info_hpt372;
821669a5db4SJeff Garzik 				chip_table = &hpt372;
822669a5db4SJeff Garzik 				break;
823669a5db4SJeff Garzik 			default:
82489d3b360SSergei Shtylyov 				printk(KERN_ERR "pata_hpt37x: Unknown HPT366 "
82589d3b360SSergei Shtylyov 				       "subtype, please report (%d).\n", rev);
826669a5db4SJeff Garzik 				return -ENODEV;
827669a5db4SJeff Garzik 		}
828669a5db4SJeff Garzik 	} else {
829669a5db4SJeff Garzik 		switch(dev->device) {
830669a5db4SJeff Garzik 			case PCI_DEVICE_ID_TTI_HPT372:
831669a5db4SJeff Garzik 				/* 372N if rev >= 2*/
83289d3b360SSergei Shtylyov 				if (rev >= 2)
833669a5db4SJeff Garzik 					return -ENODEV;
834887125e3STejun Heo 				ppi[0] = &info_hpt372;
835669a5db4SJeff Garzik 				chip_table = &hpt372a;
836669a5db4SJeff Garzik 				break;
837669a5db4SJeff Garzik 			case PCI_DEVICE_ID_TTI_HPT302:
838669a5db4SJeff Garzik 				/* 302N if rev > 1 */
83989d3b360SSergei Shtylyov 				if (rev > 1)
840669a5db4SJeff Garzik 					return -ENODEV;
841887125e3STejun Heo 				ppi[0] = &info_hpt372;
842669a5db4SJeff Garzik 				/* Check this */
843669a5db4SJeff Garzik 				chip_table = &hpt302;
844669a5db4SJeff Garzik 				break;
845669a5db4SJeff Garzik 			case PCI_DEVICE_ID_TTI_HPT371:
84689d3b360SSergei Shtylyov 				if (rev > 1)
847fcc2f69aSAlan Cox 					return -ENODEV;
848887125e3STejun Heo 				ppi[0] = &info_hpt372;
849669a5db4SJeff Garzik 				chip_table = &hpt371;
850a4734468SAlan Cox 				/* Single channel device, master is not present
851a4734468SAlan Cox 				   but the BIOS (or us for non x86) must mark it
852fcc2f69aSAlan Cox 				   absent */
853fcc2f69aSAlan Cox 				pci_read_config_byte(dev, 0x50, &mcr1);
854fcc2f69aSAlan Cox 				mcr1 &= ~0x04;
855fcc2f69aSAlan Cox 				pci_write_config_byte(dev, 0x50, mcr1);
856669a5db4SJeff Garzik 				break;
857669a5db4SJeff Garzik 			case PCI_DEVICE_ID_TTI_HPT374:
858669a5db4SJeff Garzik 				chip_table = &hpt374;
859a1efdabaSTejun Heo 				if (!(PCI_FUNC(dev->devfn) & 1))
860a1efdabaSTejun Heo 					*ppi = &info_hpt374_fn0;
861a1efdabaSTejun Heo 				else
862a1efdabaSTejun Heo 					*ppi = &info_hpt374_fn1;
863669a5db4SJeff Garzik 				break;
864669a5db4SJeff Garzik 			default:
865669a5db4SJeff Garzik 				printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device);
866669a5db4SJeff Garzik 				return -ENODEV;
867669a5db4SJeff Garzik 		}
868669a5db4SJeff Garzik 	}
869669a5db4SJeff Garzik 	/* Ok so this is a chip we support */
870669a5db4SJeff Garzik 
871669a5db4SJeff Garzik 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
872669a5db4SJeff Garzik 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
873669a5db4SJeff Garzik 	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
874669a5db4SJeff Garzik 	pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
875669a5db4SJeff Garzik 
876669a5db4SJeff Garzik 	pci_read_config_byte(dev, 0x5A, &irqmask);
877669a5db4SJeff Garzik 	irqmask &= ~0x10;
878669a5db4SJeff Garzik 	pci_write_config_byte(dev, 0x5a, irqmask);
879669a5db4SJeff Garzik 
880669a5db4SJeff Garzik 	/*
881669a5db4SJeff Garzik 	 * default to pci clock. make sure MA15/16 are set to output
882669a5db4SJeff Garzik 	 * to prevent drives having problems with 40-pin cables. Needed
883669a5db4SJeff Garzik 	 * for some drives such as IBM-DTLA which will not enter ready
884669a5db4SJeff Garzik 	 * state on reset when PDIAG is a input.
885669a5db4SJeff Garzik 	 */
886669a5db4SJeff Garzik 
887669a5db4SJeff Garzik 	pci_write_config_byte(dev, 0x5b, 0x23);
888669a5db4SJeff Garzik 
889fcc2f69aSAlan Cox 	/*
890fcc2f69aSAlan Cox 	 * HighPoint does this for HPT372A.
891fcc2f69aSAlan Cox 	 * NOTE: This register is only writeable via I/O space.
892fcc2f69aSAlan Cox 	 */
893fcc2f69aSAlan Cox 	if (chip_table == &hpt372a)
894fcc2f69aSAlan Cox 		outb(0x0e, iobase + 0x9c);
895fcc2f69aSAlan Cox 
896fcc2f69aSAlan Cox 	/* Some devices do not let this value be accessed via PCI space
89773946f9fSAlan Cox 	   according to the old driver. In addition we must use the value
89873946f9fSAlan Cox 	   from FN 0 on the HPT374 */
899fcc2f69aSAlan Cox 
90073946f9fSAlan Cox 	if (chip_table == &hpt374) {
90173946f9fSAlan Cox 		freq = hpt374_read_freq(dev);
90273946f9fSAlan Cox 		if (freq == 0)
90373946f9fSAlan Cox 			return -ENODEV;
90473946f9fSAlan Cox 	} else
905fcc2f69aSAlan Cox 		freq = inl(iobase + 0x90);
90673946f9fSAlan Cox 
907669a5db4SJeff Garzik 	if ((freq >> 12) != 0xABCDE) {
908669a5db4SJeff Garzik 		int i;
909669a5db4SJeff Garzik 		u8 sr;
910669a5db4SJeff Garzik 		u32 total = 0;
911669a5db4SJeff Garzik 
912669a5db4SJeff Garzik 		printk(KERN_WARNING "pata_hpt37x: BIOS has not set timing clocks.\n");
913669a5db4SJeff Garzik 
914669a5db4SJeff Garzik 		/* This is the process the HPT371 BIOS is reported to use */
915669a5db4SJeff Garzik 		for(i = 0; i < 128; i++) {
916669a5db4SJeff Garzik 			pci_read_config_byte(dev, 0x78, &sr);
917fcc2f69aSAlan Cox 			total += sr & 0x1FF;
918669a5db4SJeff Garzik 			udelay(15);
919669a5db4SJeff Garzik 		}
920669a5db4SJeff Garzik 		freq = total / 128;
921669a5db4SJeff Garzik 	}
922669a5db4SJeff Garzik 	freq &= 0x1FF;
923669a5db4SJeff Garzik 
924669a5db4SJeff Garzik 	/*
925669a5db4SJeff Garzik 	 *	Turn the frequency check into a band and then find a timing
926669a5db4SJeff Garzik 	 *	table to match it.
927669a5db4SJeff Garzik 	 */
928669a5db4SJeff Garzik 
929669a5db4SJeff Garzik 	clock_slot = hpt37x_clock_slot(freq, chip_table->base);
930fcc2f69aSAlan Cox 	if (chip_table->clocks[clock_slot] == NULL || prefer_dpll) {
931669a5db4SJeff Garzik 		/*
932669a5db4SJeff Garzik 		 *	We need to try PLL mode instead
933fcc2f69aSAlan Cox 		 *
934fcc2f69aSAlan Cox 		 *	For non UDMA133 capable devices we should
935fcc2f69aSAlan Cox 		 *	use a 50MHz DPLL by choice
936669a5db4SJeff Garzik 		 */
937fcc2f69aSAlan Cox 		unsigned int f_low, f_high;
938960c8a10SAlan Cox 		int dpll, adjust;
939669a5db4SJeff Garzik 
940960c8a10SAlan Cox 		/* Compute DPLL */
941887125e3STejun Heo 		dpll = (ppi[0]->udma_mask & 0xC0) ? 3 : 2;
942fcc2f69aSAlan Cox 
943960c8a10SAlan Cox 		f_low = (MHz[clock_slot] * 48) / MHz[dpll];
944fcc2f69aSAlan Cox 		f_high = f_low + 2;
945960c8a10SAlan Cox 		if (clock_slot > 1)
946960c8a10SAlan Cox 			f_high += 2;
947fcc2f69aSAlan Cox 
948fcc2f69aSAlan Cox 		/* Select the DPLL clock. */
949fcc2f69aSAlan Cox 		pci_write_config_byte(dev, 0x5b, 0x21);
95064a81709SAlan Cox 		pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100);
951fcc2f69aSAlan Cox 
952669a5db4SJeff Garzik 		for(adjust = 0; adjust < 8; adjust++) {
953669a5db4SJeff Garzik 			if (hpt37x_calibrate_dpll(dev))
954669a5db4SJeff Garzik 				break;
955669a5db4SJeff Garzik 			/* See if it'll settle at a fractionally different clock */
95664a81709SAlan Cox 			if (adjust & 1)
95764a81709SAlan Cox 				f_low -= adjust >> 1;
95864a81709SAlan Cox 			else
95964a81709SAlan Cox 				f_high += adjust >> 1;
96064a81709SAlan Cox 			pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100);
961669a5db4SJeff Garzik 		}
962669a5db4SJeff Garzik 		if (adjust == 8) {
96380b8987cSSergei Shtylyov 			printk(KERN_ERR "pata_hpt37x: DPLL did not stabilize!\n");
964669a5db4SJeff Garzik 			return -ENODEV;
965669a5db4SJeff Garzik 		}
966960c8a10SAlan Cox 		if (dpll == 3)
9671626aeb8STejun Heo 			private_data = (void *)hpt37x_timings_66;
968fcc2f69aSAlan Cox 		else
9691626aeb8STejun Heo 			private_data = (void *)hpt37x_timings_50;
970669a5db4SJeff Garzik 
97180b8987cSSergei Shtylyov 		printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using %dMHz DPLL.\n",
97280b8987cSSergei Shtylyov 		       MHz[clock_slot], MHz[dpll]);
973669a5db4SJeff Garzik 	} else {
9741626aeb8STejun Heo 		private_data = (void *)chip_table->clocks[clock_slot];
975669a5db4SJeff Garzik 		/*
976a4734468SAlan Cox 		 *	Perform a final fixup. Note that we will have used the
977a4734468SAlan Cox 		 *	DPLL on the HPT372 which means we don't have to worry
978a4734468SAlan Cox 		 *	about lack of UDMA133 support on lower clocks
979669a5db4SJeff Garzik  		 */
980669a5db4SJeff Garzik 
981887125e3STejun Heo 		if (clock_slot < 2 && ppi[0] == &info_hpt370)
982887125e3STejun Heo 			ppi[0] = &info_hpt370_33;
983887125e3STejun Heo 		if (clock_slot < 2 && ppi[0] == &info_hpt370a)
984887125e3STejun Heo 			ppi[0] = &info_hpt370a_33;
98580b8987cSSergei Shtylyov 		printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n",
98680b8987cSSergei Shtylyov 		       chip_table->name, MHz[clock_slot]);
987669a5db4SJeff Garzik 	}
988fcc2f69aSAlan Cox 
989669a5db4SJeff Garzik 	/* Now kick off ATA set up */
9901c5afdf7STejun Heo 	return ata_pci_bmdma_init_one(dev, ppi, &hpt37x_sht, private_data, 0);
991669a5db4SJeff Garzik }
992669a5db4SJeff Garzik 
9932d2744fcSJeff Garzik static const struct pci_device_id hpt37x[] = {
9942d2744fcSJeff Garzik 	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), },
9952d2744fcSJeff Garzik 	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), },
9962d2744fcSJeff Garzik 	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), },
9972d2744fcSJeff Garzik 	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374), },
9982d2744fcSJeff Garzik 	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), },
9992d2744fcSJeff Garzik 
10002d2744fcSJeff Garzik 	{ },
1001669a5db4SJeff Garzik };
1002669a5db4SJeff Garzik 
1003669a5db4SJeff Garzik static struct pci_driver hpt37x_pci_driver = {
1004669a5db4SJeff Garzik 	.name 		= DRV_NAME,
1005669a5db4SJeff Garzik 	.id_table	= hpt37x,
1006669a5db4SJeff Garzik 	.probe 		= hpt37x_init_one,
1007669a5db4SJeff Garzik 	.remove		= ata_pci_remove_one
1008669a5db4SJeff Garzik };
1009669a5db4SJeff Garzik 
1010669a5db4SJeff Garzik static int __init hpt37x_init(void)
1011669a5db4SJeff Garzik {
1012669a5db4SJeff Garzik 	return pci_register_driver(&hpt37x_pci_driver);
1013669a5db4SJeff Garzik }
1014669a5db4SJeff Garzik 
1015669a5db4SJeff Garzik static void __exit hpt37x_exit(void)
1016669a5db4SJeff Garzik {
1017669a5db4SJeff Garzik 	pci_unregister_driver(&hpt37x_pci_driver);
1018669a5db4SJeff Garzik }
1019669a5db4SJeff Garzik 
1020669a5db4SJeff Garzik MODULE_AUTHOR("Alan Cox");
1021669a5db4SJeff Garzik MODULE_DESCRIPTION("low-level driver for the Highpoint HPT37x/30x");
1022669a5db4SJeff Garzik MODULE_LICENSE("GPL");
1023669a5db4SJeff Garzik MODULE_DEVICE_TABLE(pci, hpt37x);
1024669a5db4SJeff Garzik MODULE_VERSION(DRV_VERSION);
1025669a5db4SJeff Garzik 
1026669a5db4SJeff Garzik module_init(hpt37x_init);
1027669a5db4SJeff Garzik module_exit(hpt37x_exit);
1028