pata_hpt366.c revision 1c5afdf7a629d2e77de8dd043b97a33dcd7e6dfa
1669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
2669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Libata driver for the highpoint 366 and 368 UDMA66 ATA controllers.
3669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
4669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * This driver is heavily based upon:
5669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
6669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * linux/drivers/ide/pci/hpt366.c		Version 0.36	April 25, 2003
7669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
8669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
9669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
10669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Portions Copyright (C) 2003		Red Hat Inc
11669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
12669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
13669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * TODO
14d817898c2fc73e6ea33b58498c87a43d7e9fcd7aSergei Shtylyov *	Look into engine reset on timeout errors. Should not be required.
15669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
16669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
17669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
18669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/kernel.h>
19669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/module.h>
20669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/pci.h>
21669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/init.h>
22669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/blkdev.h>
23669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/delay.h>
24669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <scsi/scsi_host.h>
25669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/libata.h>
26669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
27669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#define DRV_NAME	"pata_hpt366"
28859faa875ed6760fcdfaf6f1fec1155a7e43dc21Sergei Shtylyov#define DRV_VERSION	"0.6.8"
29669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
30669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstruct hpt_clock {
316ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	u8	xfer_mode;
32669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32	timing;
33669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
34669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
35669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* key for bus clock timings
36669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * bit
3782beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 0:3    data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
3882beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov *        cycles = value + 1
3982beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 4:7    data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
4082beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov *        cycles = value + 1
4182beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 8:11   cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
42669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        register access.
4382beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 12:15  cmd_low_time. Active time of DIOW_/DIOR_ during task file
44669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        register access.
4582beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 16:18  udma_cycle_time. Clock cycles for UDMA xfer?
4682beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 19:21  pre_high_time. Time to initialize 1st cycle for PIO and MW DMA xfer.
4782beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 22:24  cmd_pre_high_time. Time to initialize 1st PIO cycle for task file
48669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        register access.
4982beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 28     UDMA enable.
5082beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 29     DMA  enable.
5182beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 30     PIO_MST enable. If set, the chip is in bus master mode during
5282beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov *        PIO xfer.
53669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 31     FIFO enable.
54669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
55669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
56669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const struct hpt_clock hpt366_40[] = {
57669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_4,	0x900fd943	},
58669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_3,	0x900ad943	},
59669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_2,	0x900bd943	},
60669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_1,	0x9008d943	},
61669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_0,	0x9008d943	},
62669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
63669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_2,	0xa008d943	},
64669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_1,	0xa010d955	},
65669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_0,	0xa010d9fc	},
66669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
67669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_4,	0xc008d963	},
68669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_3,	0xc010d974	},
69669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_2,	0xc010d997	},
70669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_1,	0xc010d9c7	},
71669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_0,	0xc018d9d9	},
72669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	0,		0x0120d9d9	}
73669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
74669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
75669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const struct hpt_clock hpt366_33[] = {
76669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_4,	0x90c9a731	},
77669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_3,	0x90cfa731	},
78669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_2,	0x90caa731	},
79669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_1,	0x90cba731	},
80669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_0,	0x90c8a731	},
81669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
82669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_2,	0xa0c8a731	},
83669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_1,	0xa0c8a732	},	/* 0xa0c8a733 */
84669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_0,	0xa0c8a797	},
85669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
86669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_4,	0xc0c8a731	},
87669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_3,	0xc0c8a742	},
88669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_2,	0xc0d0a753	},
89669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_1,	0xc0d0a7a3	},	/* 0xc0d0a793 */
90669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_0,	0xc0d0a7aa	},	/* 0xc0d0a7a7 */
91669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	0,		0x0120a7a7	}
92669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
93669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
94669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const struct hpt_clock hpt366_25[] = {
95669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_4,	0x90c98521	},
96669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_3,	0x90cf8521	},
97669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_2,	0x90cf8521	},
98669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_1,	0x90cb8521	},
99669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_0,	0x90cb8521	},
100669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
101669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_2,	0xa0ca8521	},
102669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_1,	0xa0ca8532	},
103669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_0,	0xa0ca8575	},
104669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
105669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_4,	0xc0ca8521	},
106669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_3,	0xc0ca8532	},
107669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_2,	0xc0ca8542	},
108669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_1,	0xc0d08572	},
109669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_0,	0xc0d08585	},
110669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	0,		0x01208585	}
111669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
112669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
113669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const char *bad_ata33[] = {
114669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
115669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
116669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
117669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 90510D4",
118669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
119669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
120669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
121669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	NULL
122669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
123669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
124669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const char *bad_ata66_4[] = {
125669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307075",
126669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307060",
127669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307045",
128669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307030",
129669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307020",
130669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307015",
131669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-305040",
132669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-305030",
133669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-305020",
134669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L010AVER07-0",
135669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L020AVER07-0",
136669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L030AVER07-0",
137669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L040AVER07-0",
138669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L060AVER07-0",
139669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"WDC AC310200R",
140669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	NULL
141669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
142669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
143669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const char *bad_ata66_3[] = {
144669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"WDC AC310200R",
145669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	NULL
146669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
147669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
148669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[])
149669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
1508bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo	unsigned char model_num[ATA_ID_PROD_LEN + 1];
151669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int i = 0;
152669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1538bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
154669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1558bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo	while (list[i] != NULL) {
1568bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo		if (!strcmp(list[i], model_num)) {
15785cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik			printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
158669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				modestr, list[i]);
159669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			return 1;
160669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		}
161669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		i++;
162669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
163669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return 0;
164669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
165669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
166669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
167669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt366_filter	-	mode selection filter
168669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: ATA device
169669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
170669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Block UDMA on devices that cause trouble with this controller.
171669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
17285cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
173a76b62ca70662cd0ca98edf366c6637009a95f7dAlan Coxstatic unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask)
174669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
175669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (adev->class == ATA_DEV_ATA) {
176669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (hpt_dma_blacklisted(adev, "UDMA",  bad_ata33))
177669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			mask &= ~ATA_MASK_UDMA;
178669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3))
1796ddd68615ae9b21096545d7d6ab0f04113ae8b42Alan Cox			mask &= ~(0xF8 << ATA_SHIFT_UDMA);
180669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
1816ddd68615ae9b21096545d7d6ab0f04113ae8b42Alan Cox			mask &= ~(0xF0 << ATA_SHIFT_UDMA);
1823ee89f177e3cef0b5b024bcb6df683a3fa7d795fTejun Heo	} else if (adev->class == ATA_DEV_ATAPI)
1833ee89f177e3cef0b5b024bcb6df683a3fa7d795fTejun Heo		mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
1843ee89f177e3cef0b5b024bcb6df683a3fa7d795fTejun Heo
185c7087652e1890a3feef35b30ee1d4be68e1932cdTejun Heo	return mask;
186669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
187669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
188fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Coxstatic int hpt36x_cable_detect(struct ata_port *ap)
189fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox{
190fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
191bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	u8 ata66;
192fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox
193bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	/*
194bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	 * Each channel of pata_hpt366 occupies separate PCI function
195bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	 * as the primary channel and bit1 indicates the cable type.
196bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	 */
197fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	pci_read_config_byte(pdev, 0x5A, &ata66);
198bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	if (ata66 & 2)
199fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox		return ATA_CBL_PATA40;
200fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	return ATA_CBL_PATA80;
201fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox}
202fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox
2036ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heostatic void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
2046ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo			    u8 mode)
205669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
2066ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	struct hpt_clock *clocks = ap->host->private_data;
207669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
208859faa875ed6760fcdfaf6f1fec1155a7e43dc21Sergei Shtylyov	u32 addr = 0x40 + 4 * adev->devno;
2096ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	u32 mask, reg;
21085cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
2116ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	/* determine timing mask and find matching clock entry */
2126ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	if (mode < XFER_MW_DMA_0)
2136ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo		mask = 0xc1f8ffff;
2146ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	else if (mode < XFER_UDMA_0)
2156ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo		mask = 0x303800ff;
2166ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	else
2176ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo		mask = 0x30070000;
2186ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo
2196ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	while (clocks->xfer_mode) {
2206ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo		if (clocks->xfer_mode == mode)
2216ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo			break;
2226ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo		clocks++;
2236ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	}
2246ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	if (!clocks->xfer_mode)
2256ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo		BUG();
2266ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo
2276ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	/*
2286ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	 * Combine new mode bits with old config bits and disable
2296ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	 * on-chip PIO FIFO/buffer (and PIO MST mode as well) to avoid
2306ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	 * problems handling I/O errors later.
2316ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	 */
232859faa875ed6760fcdfaf6f1fec1155a7e43dc21Sergei Shtylyov	pci_read_config_dword(pdev, addr, &reg);
2336ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	reg = ((reg & ~mask) | (clocks->timing & mask)) & ~0xc0000000;
234859faa875ed6760fcdfaf6f1fec1155a7e43dc21Sergei Shtylyov	pci_write_config_dword(pdev, addr, reg);
2356ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo}
2366ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo
2376ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo/**
2386ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo *	hpt366_set_piomode		-	PIO setup
2396ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo *	@ap: ATA interface
2406ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo *	@adev: device on the interface
2416ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo *
2426ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo *	Perform PIO mode setup.
2436ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo */
2446ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo
2456ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heostatic void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
2466ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo{
2476ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	hpt366_set_mode(ap, adev, adev->pio_mode);
248669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
249669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
250669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
251669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt366_set_dmamode		-	DMA timing setup
252669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA interface
253669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: Device being configured
254669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
255669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Set up the channel for MWDMA or UDMA modes. Much the same as with
256669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	PIO, load the mode number and then set MWDMA or UDMA flag.
257669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
25885cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
259669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
260669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
2616ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	hpt366_set_mode(ap, adev, adev->dma_mode);
262669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
263669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
264669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct scsi_host_template hpt36x_sht = {
26568d1d07b510bb57a504588adc2bd2758adea0965Tejun Heo	ATA_BMDMA_SHT(DRV_NAME),
266669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
267669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
268669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
269669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Configuration for HPT366/68
270669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
27185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
272669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations hpt366_port_ops = {
273029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &ata_bmdma_port_ops,
274029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.cable_detect	= hpt36x_cable_detect,
275029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.mode_filter	= hpt366_filter,
276669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_piomode	= hpt366_set_piomode,
277669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_dmamode	= hpt366_set_dmamode,
27885cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik};
279669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
280669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
281aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	hpt36x_init_chipset	-	common chip setup
282aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	@dev: PCI device
283aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *
284aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	Perform the chip setup work that must be done at both init and
285aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	resume time
286aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox */
287aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
288aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Coxstatic void hpt36x_init_chipset(struct pci_dev *dev)
289aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox{
290aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	u8 drive_fast;
291aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
292aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
293aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
294aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
295aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
296aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_read_config_byte(dev, 0x51, &drive_fast);
297aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	if (drive_fast & 0x80)
298aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox		pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
299aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox}
300aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
301aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox/**
302669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt36x_init_one		-	Initialise an HPT366/368
303669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@dev: PCI device
304669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@id: Entry in match table
305669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
306669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Initialise an HPT36x device. There are some interesting complications
307669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	here. Firstly the chip may report 366 and be one of several variants.
308669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Secondly all the timings depend on the clock for the chip which we must
309669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	detect and look up
310669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
311669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	This is the known chip mappings. It may be missing a couple of later
312669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	releases.
313669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
314669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Chip version		PCI		Rev	Notes
315669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT366			4 (HPT366)	0	UDMA66
316669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT366			4 (HPT366)	1	UDMA66
317669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT368			4 (HPT366)	2	UDMA66
318669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT37x/30x		4 (HPT366)	3+	Other driver
319669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
320669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
32185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
322669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
323669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
3241626aeb881236c8cb022b5e4ca594146a951d669Tejun Heo	static const struct ata_port_info info_hpt366 = {
3251d2808fd3d2d5d2c0483796a0f443d1cb3f11367Jeff Garzik		.flags = ATA_FLAG_SLAVE_POSS,
32614bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø		.pio_mask = ATA_PIO4,
32714bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø		.mwdma_mask = ATA_MWDMA2,
328bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask = ATA_UDMA4,
329669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		.port_ops = &hpt366_port_ops
330669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	};
331887125e3740283be25564bfc6fb5d24974b651abTejun Heo	const struct ata_port_info *ppi[] = { &info_hpt366, NULL };
332669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
333887125e3740283be25564bfc6fb5d24974b651abTejun Heo	void *hpriv = NULL;
334669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 reg1;
335f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	int rc;
336f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo
337f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	rc = pcim_enable_device(dev);
338f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	if (rc)
339f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo		return rc;
340669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
341669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* May be a later chip in disguise. Check */
342669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Newer chips are not in the HPT36x driver. Ignore them */
34389d3b3603bfb648e0113d8682d4f84dd18a776bdSergei Shtylyov	if (dev->revision > 2)
34489d3b3603bfb648e0113d8682d4f84dd18a776bdSergei Shtylyov		return -ENODEV;
345669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
346aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	hpt36x_init_chipset(dev);
347669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
348669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_dword(dev, 0x40,  &reg1);
34985cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
350669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* PCI clocking determines the ATA timing values to use */
351669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* info_hpt366 is safe against re-entry so we can scribble on it */
3522c136efcf6f58d07512c4df83eb494597fe0d229OGAWA Hirofumi	switch((reg1 & 0x700) >> 8) {
3532456eb819be7aa2cac73359c2855dfa30e46d75aTejun Heo		case 9:
354887125e3740283be25564bfc6fb5d24974b651abTejun Heo			hpriv = &hpt366_40;
355669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			break;
3562456eb819be7aa2cac73359c2855dfa30e46d75aTejun Heo		case 5:
357887125e3740283be25564bfc6fb5d24974b651abTejun Heo			hpriv = &hpt366_25;
358669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			break;
359669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		default:
360887125e3740283be25564bfc6fb5d24974b651abTejun Heo			hpriv = &hpt366_33;
361669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			break;
362669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
363669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Now kick off ATA set up */
3641c5afdf7a629d2e77de8dd043b97a33dcd7e6dfaTejun Heo	return ata_pci_bmdma_init_one(dev, ppi, &hpt36x_sht, hpriv, 0);
365669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
366669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
367438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#ifdef CONFIG_PM
368aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Coxstatic int hpt36x_reinit_one(struct pci_dev *dev)
369aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox{
370f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	struct ata_host *host = dev_get_drvdata(&dev->dev);
371f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	int rc;
372f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo
373f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	rc = ata_pci_device_do_resume(dev);
374f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	if (rc)
375f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo		return rc;
376aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	hpt36x_init_chipset(dev);
377f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	ata_host_resume(host);
378f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	return 0;
379aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox}
380438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#endif
381aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
3822d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzikstatic const struct pci_device_id hpt36x[] = {
3832d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), },
3842d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ },
385669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
386669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
387669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct pci_driver hpt36x_pci_driver = {
3882d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	.name 		= DRV_NAME,
389669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.id_table	= hpt36x,
390669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.probe 		= hpt36x_init_one,
391aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.remove		= ata_pci_remove_one,
392438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#ifdef CONFIG_PM
393aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.suspend	= ata_pci_device_suspend,
394aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.resume		= hpt36x_reinit_one,
395438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#endif
396669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
397669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
398669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int __init hpt36x_init(void)
399669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
400669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return pci_register_driver(&hpt36x_pci_driver);
401669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
402669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
403669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void __exit hpt36x_exit(void)
404669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
405669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_unregister_driver(&hpt36x_pci_driver);
406669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
407669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
408669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_AUTHOR("Alan Cox");
409669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368");
410669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_LICENSE("GPL");
411669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DEVICE_TABLE(pci, hpt36x);
412669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_VERSION(DRV_VERSION);
413669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
414669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_init(hpt36x_init);
415669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_exit(hpt36x_exit);
416