1669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
2669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *   pata-legacy.c - Legacy port PATA/SATA controller driver.
3ab77163008c596aad9624ceab190d840c0143fa8Alan Cox *   Copyright 2005/2006 Red Hat, all rights reserved.
4669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
5669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  This program is free software; you can redistribute it and/or modify
6669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  it under the terms of the GNU General Public License as published by
7669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  the Free Software Foundation; either version 2, or (at your option)
8669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  any later version.
9669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
10669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  This program is distributed in the hope that it will be useful,
11669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  GNU General Public License for more details.
14669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
15669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  You should have received a copy of the GNU General Public License
16669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  along with this program; see the file COPYING.  If not, write to
17669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
19669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *   An ATA driver for the legacy ATA ports.
20669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
21669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *   Data Sources:
22669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Opti 82C465/82C611 support: Data sheets at opti-inc.com
23669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HT6560 series:
24669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Promise 20230/20620:
25669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *		http://www.ryston.cz/petr/vlb/pdc20230b.html
26669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *		http://www.ryston.cz/petr/vlb/pdc20230c.html
27669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *		http://www.ryston.cz/petr/vlb/pdc20630.html
289c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz *	QDI65x0:
299c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz *		http://www.ryston.cz/petr/vlb/qd6500.html
309c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz *		http://www.ryston.cz/petr/vlb/qd6580.html
319c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz *
329c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz *	QDI65x0 probe code based on drivers/ide/legacy/qd65xx.c
339c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz *	Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
349c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz *	Samuel Thibault <samuel.thibault@ens-lyon.org>
35669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
36669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  Unsupported but docs exist:
37669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Appian/Adaptec AIC25VL01/Cirrus Logic PD7220
38669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
39669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  This driver handles legacy (that is "ISA/VLB side") IDE ports found
40669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  on PC class systems. There are three hybrid devices that are exceptions
41669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  The Cyrix 5510/5520 where a pre SFF ATA device is on the bridge and
42669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  the MPIIX where the tuning is PCI side but the IDE is "ISA side".
43669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
44669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  Specific support is included for the ht6560a/ht6560b/opti82c611a/
459c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz *  opti82c465mv/promise 20230c/20630/qdi65x0/winbond83759A
46669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
476d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz *  Support for the Winbond 83759A when operating in advanced mode.
486d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz *  Multichip mode is not currently supported.
496d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz *
50669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  Use the autospeed and pio_mask options with:
51669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Appian ADI/2 aka CLPD7220 or AIC25VL01.
52669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  Use the jumpers, autospeed and set pio_mask to the mode on the jumpers with
53669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Goldstar GM82C711, PIC-1288A-125, UMC 82C871F, Winbond W83759,
54669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Winbond W83759A, Promise PDC20230-B
55669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
56669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  For now use autospeed and pio_mask as above with the W83759A. This may
57669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *  change.
58669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
59669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
60669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
6145bc955bb1324a46c9539550cc615994e6d0a43dJames Bottomley#include <linux/async.h>
62669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/kernel.h>
63669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/module.h>
64669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/pci.h>
65669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/init.h>
66669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/blkdev.h>
67669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/delay.h>
68669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <scsi/scsi_host.h>
69669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/ata.h>
70669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/libata.h>
71669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/platform_device.h>
72669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
73669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#define DRV_NAME "pata_legacy"
74b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox#define DRV_VERSION "0.6.5"
75669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
76669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#define NR_HOST 6
77669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
78defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int all;
79defc9cd826e4a99f550504a744f9407b518828aeAlan Coxmodule_param(all, int, 0444);
80defc9cd826e4a99f550504a744f9407b518828aeAlan CoxMODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)");
81669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
82defc9cd826e4a99f550504a744f9407b518828aeAlan Coxenum controller {
83defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	BIOS = 0,
84defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	SNOOP = 1,
85defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	PDC20230 = 2,
86defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	HT6560A = 3,
87defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	HT6560B = 4,
88defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	OPTI611A = 5,
89defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	OPTI46X = 6,
90defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	QDI6500 = 7,
91defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	QDI6580 = 8,
92defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	QDI6580DP = 9,		/* Dual channel mode is different */
93b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	W83759A = 10,
94defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
95defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	UNKNOWN = -1
96defc9cd826e4a99f550504a744f9407b518828aeAlan Cox};
97defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
988c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewiczstruct legacy_data {
998c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	unsigned long timing;
1008c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	u8 clock[2];
1018c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	u8 last;
1028c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	int fast;
1038c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	enum controller type;
1048c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	struct platform_device *platform_dev;
1058c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz};
106defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
107defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstruct legacy_probe {
108defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	unsigned char *name;
109defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	unsigned long port;
110defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	unsigned int irq;
111defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	unsigned int slot;
112defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	enum controller type;
113defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	unsigned long private;
114defc9cd826e4a99f550504a744f9407b518828aeAlan Cox};
115defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
116defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstruct legacy_controller {
117defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	const char *name;
118defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct ata_port_operations *ops;
119defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	unsigned int pio_mask;
120defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	unsigned int flags;
121e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox	unsigned int pflags;
122b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	int (*setup)(struct platform_device *, struct legacy_probe *probe,
123b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		struct legacy_data *data);
124defc9cd826e4a99f550504a744f9407b518828aeAlan Cox};
125defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
126defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
127defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
128defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic struct legacy_probe probe_list[NR_HOST];
129669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct legacy_data legacy_data[NR_HOST];
130669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_host *legacy_host[NR_HOST];
131669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int nr_legacy_host;
132669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
133669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
134defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int probe_all;		/* Set to check all ISA port ranges */
135defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int ht6560a;		/* HT 6560A on primary 1, second 2, both 3 */
136defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int ht6560b;		/* HT 6560A on primary 1, second 2, both 3 */
137defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int opti82c611a;		/* Opti82c611A on primary 1, sec 2, both 3 */
138defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int opti82c46x;		/* Opti 82c465MV present(pri/sec autodetect) */
139defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int autospeed;		/* Chip present which snoops speed changes */
14014bdef982caeda19afe34010482867c18217c641Erik Inge Bolsøstatic int pio_mask = ATA_PIO4;	/* PIO range for autospeed devices */
141f834e49f1a09414e9618ff0c9cd83c2114032bb6Alan Coxstatic int iordy_mask = 0xFFFFFFFF;	/* Use iordy if available */
142669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1430dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewicz/* Set to probe QDI controllers */
1440dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewicz#ifdef CONFIG_PATA_QDI_MODULE
1450dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewiczstatic int qdi = 1;
1460dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewicz#else
1470dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewiczstatic int qdi;
1480dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewicz#endif
1490dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewicz
150f60215a1302f03ad435f8365c0dd85bdb022cac3Tejun Heo#ifdef CONFIG_PATA_WINBOND_VLB_MODULE
1516d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewiczstatic int winbond = 1;		/* Set to probe Winbond controllers,
1526d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz					give I/O port if non standard */
1536d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz#else
1546d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewiczstatic int winbond;		/* Set to probe Winbond controllers,
1556d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz					give I/O port if non standard */
1566d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz#endif
1576d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz
158669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
159defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	legacy_probe_add	-	Add interface to probe list
160defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	@port: Controller port
161defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	@irq: IRQ number
162defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	@type: Controller type
163defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	@private: Controller specific info
164defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *
165defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	Add an entry into the probe list for ATA controllers. This is used
166defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	to add the default ISA slots and then to build up the table
167defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	further according to other ISA/VLB/Weird device scans
168defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *
169defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	An I/O port list is used to keep ordering stable and sane, as we
170defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	don't have any good way to talk about ordering otherwise
171defc9cd826e4a99f550504a744f9407b518828aeAlan Cox */
172defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
173defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int legacy_probe_add(unsigned long port, unsigned int irq,
174defc9cd826e4a99f550504a744f9407b518828aeAlan Cox				enum controller type, unsigned long private)
175defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{
176defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct legacy_probe *lp = &probe_list[0];
177defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	int i;
178defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct legacy_probe *free = NULL;
179defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
180defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	for (i = 0; i < NR_HOST; i++) {
181defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (lp->port == 0 && free == NULL)
182defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			free = lp;
183defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		/* Matching port, or the correct slot for ordering */
184defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (lp->port == port || legacy_port[i] == port) {
185defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			free = lp;
186defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			break;
187defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		}
188defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		lp++;
189defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	}
190defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (free == NULL) {
191defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		printk(KERN_ERR "pata_legacy: Too many interfaces.\n");
192defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		return -1;
193defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	}
194defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	/* Fill in the entry for later probing */
195defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	free->port = port;
196defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	free->irq = irq;
197defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	free->type = type;
198defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	free->private = private;
199defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	return 0;
200defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}
201defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
202defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
203defc9cd826e4a99f550504a744f9407b518828aeAlan Cox/**
204669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	legacy_set_mode		-	mode setting
2050260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo *	@link: IDE link
206b229a7b0aed808f2ef6a5e9dbf78b0f17cefb4d0Alan Cox *	@unused: Device that failed when error is returned
207669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
208669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Use a non standard set_mode function. We don't want to be tuned.
209669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
210669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	The BIOS configured everything. Our job is not to fiddle. Just use
211669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	whatever PIO the hardware is using and leave it at that. When we
212669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	get some kind of nice user driven API for control then we can
213669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	expand on this as per hdparm in the base kernel.
214669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
215669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
2160260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heostatic int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
217669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
218f58229f8060055b08b34008ea08f31de1e2f003cTejun Heo	struct ata_device *dev;
219669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
2201eca4365be25c540650693e941bc06a66cf38f94Tejun Heo	ata_for_each_dev(dev, link, ENABLED) {
221a9a79dfec239568bdbf778242f8fcd10bcc5b9e2Joe Perches		ata_dev_info(dev, "configured for PIO\n");
2221eca4365be25c540650693e941bc06a66cf38f94Tejun Heo		dev->pio_mode = XFER_PIO_0;
2231eca4365be25c540650693e941bc06a66cf38f94Tejun Heo		dev->xfer_mode = XFER_PIO_0;
2241eca4365be25c540650693e941bc06a66cf38f94Tejun Heo		dev->xfer_shift = ATA_SHIFT_PIO;
2251eca4365be25c540650693e941bc06a66cf38f94Tejun Heo		dev->flags |= ATA_DFLAG_PIO;
226669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
227b229a7b0aed808f2ef6a5e9dbf78b0f17cefb4d0Alan Cox	return 0;
228669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
229669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
230669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct scsi_host_template legacy_sht = {
23168d1d07b510bb57a504588adc2bd2758adea0965Tejun Heo	ATA_PIO_SHT(DRV_NAME),
232669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
233669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
234029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heostatic const struct ata_port_operations legacy_base_port_ops = {
235029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &ata_sff_port_ops,
236029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.cable_detect	= ata_cable_40wire,
237029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo};
238029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo
239669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
240669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	These ops are used if the user indicates the hardware
241669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	snoops the commands to decide on the mode and handles the
242669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	mode selection "magically" itself. Several legacy controllers
243669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	do this. The mode range can be set if it is not 0x1F by setting
244669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	pio_mask as well.
245669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
246669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
247669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations simple_port_ops = {
248029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
2495682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo	.sff_data_xfer	= ata_sff_data_xfer_noirq,
250669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
251669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
252669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations legacy_port_ops = {
253029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
2545682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo	.sff_data_xfer	= ata_sff_data_xfer_noirq,
255029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.set_mode	= legacy_set_mode,
256669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
257669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
258669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
259669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Promise 20230C and 20620 support
260669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
261defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	This controller supports PIO0 to PIO2. We set PIO timings
262defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	conservatively to allow for 50MHz Vesa Local Bus. The 20620 DMA
263defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	support is weird being DMA to controller and PIO'd to the host
264defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	and not supported.
265669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
266669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
267669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
268669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
269669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int tries = 5;
270669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int pio = adev->pio_mode - XFER_PIO_0;
271669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 rt;
272669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	unsigned long flags;
27385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
274669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Safe as UP only. Force I/Os to occur together */
27585cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
276669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	local_irq_save(flags);
27785cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
278669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Unlock the control interface */
279defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	do {
280669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x1F5);
281669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		outb(inb(0x1F2) | 0x80, 0x1F2);
282669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x1F2);
283669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x3F6);
284669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x3F6);
285669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x1F2);
286669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x1F2);
287669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
288defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	while ((inb(0x1F2) & 0x80) && --tries);
289669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
290669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	local_irq_restore(flags);
29185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
292669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	outb(inb(0x1F4) & 0x07, 0x1F4);
293669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
294669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rt = inb(0x1F3);
295669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rt &= 0x07 << (3 * adev->devno);
296669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (pio)
297669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		rt |= (1 + 3 * pio) << (3 * adev->devno);
298669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
299669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	udelay(100);
300669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	outb(inb(0x1F2) | 0x01, 0x1F2);
301669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	udelay(100);
302669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	inb(0x1F5);
303669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
304669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
305669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
30655dba3120fbcbea6800f9a18503d25f73212a347Tejun Heostatic unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
307defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			unsigned char *buf, unsigned int buflen, int rw)
308669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
309c55af1f5abf606118b32e3ce9c3b1bbce5236e7eAlan Cox	int slop = buflen & 3;
31016e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu	struct ata_port *ap = dev->link->ap;
31116e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu
312c55af1f5abf606118b32e3ce9c3b1bbce5236e7eAlan Cox	/* 32bit I/O capable *and* we need to write a whole number of dwords */
313e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox	if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)
314e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox					&& (ap->pflags & ATA_PFLAG_PIO32)) {
31555dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo		unsigned long flags;
31655dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo
317669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		local_irq_save(flags);
318669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
319669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		/* Perform the 32bit I/O synchronization sequence */
3200d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		ioread8(ap->ioaddr.nsect_addr);
3210d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		ioread8(ap->ioaddr.nsect_addr);
3220d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		ioread8(ap->ioaddr.nsect_addr);
323669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
324669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		/* Now the data */
32555dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo		if (rw == READ)
3260d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
32755dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo		else
32855dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
329669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
330669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (unlikely(slop)) {
3316ad67403da47e833d9e418caf7f28295c9472e11Harvey Harrison			__le32 pad;
33255dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo			if (rw == READ) {
333b50e56d81e0df964e9b28001d792021b109cf4f1Al Viro				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
334669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				memcpy(buf + buflen - slop, &pad, slop);
33555dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo			} else {
33655dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo				memcpy(&pad, buf + buflen - slop, slop);
33755dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
338669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			}
33955dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo			buflen += 4 - slop;
340669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		}
341669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		local_irq_restore(flags);
34255dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo	} else
3439363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo		buflen = ata_sff_data_xfer_noirq(dev, buf, buflen, rw);
34455dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo
34555dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo	return buflen;
346669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
347669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
348669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations pdc20230_port_ops = {
349029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
350669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_piomode	= pdc20230_set_piomode,
3515682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo	.sff_data_xfer	= pdc_data_xfer_vlb,
352669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
353669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
354669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
355669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Holtek 6560A support
356669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
357defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	This controller supports PIO0 to PIO2 (no IORDY even though higher
358defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	timings can be loaded).
359669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
360669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
361669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
362669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
363669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 active, recover;
364669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_timing t;
365669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
366669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Get the timing data in cycles. For now play safe at 50Mhz */
367669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
368669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
36907633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	active = clamp_val(t.active, 2, 15);
37007633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	recover = clamp_val(t.recover, 4, 15);
371669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
372669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	inb(0x3E6);
373669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	inb(0x3E6);
374669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	inb(0x3E6);
375669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	inb(0x3E6);
376669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
3770d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(recover << 4 | active, ap->ioaddr.device_addr);
3780d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	ioread8(ap->ioaddr.status_addr);
379669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
380669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
381669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations ht6560a_port_ops = {
382029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
383669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_piomode	= ht6560a_set_piomode,
384669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
385669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
386669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
387669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Holtek 6560B support
388669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
389defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO
390defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	setting unless we see an ATAPI device in which case we force it off.
391669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
392669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	FIXME: need to implement 2nd channel support.
393669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
394669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
395669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
396669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
397669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 active, recover;
398669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_timing t;
399669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
400669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Get the timing data in cycles. For now play safe at 50Mhz */
401669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
402669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
40307633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	active = clamp_val(t.active, 2, 15);
4049716387311c790de381214c03e7f1b72b91a8189Sergei Shtylyov	recover = clamp_val(t.recover, 2, 16) & 0x0F;
405669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
406669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	inb(0x3E6);
407669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	inb(0x3E6);
408669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	inb(0x3E6);
409669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	inb(0x3E6);
410669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
4110d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(recover << 4 | active, ap->ioaddr.device_addr);
412669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
413669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (adev->class != ATA_DEV_ATA) {
414669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		u8 rconf = inb(0x3E6);
415669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (rconf & 0x24) {
416defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			rconf &= ~0x24;
417669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			outb(rconf, 0x3E6);
418669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		}
419669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
4200d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	ioread8(ap->ioaddr.status_addr);
421669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
422669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
423669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations ht6560b_port_ops = {
424029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
425669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_piomode	= ht6560b_set_piomode,
426669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
427669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
428669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
429669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Opti core chipset helpers
430669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
43185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
432669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
433669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	opti_syscfg	-	read OPTI chipset configuration
434669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@reg: Configuration register to read
435669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
436669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Returns the value of an OPTI system board configuration register.
437669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
438669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
439669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic u8 opti_syscfg(u8 reg)
440669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
441669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	unsigned long flags;
442669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 r;
44385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
444669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Uniprocessor chipset and must force cycles adjancent */
445669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	local_irq_save(flags);
446669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	outb(reg, 0x22);
447669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	r = inb(0x24);
448669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	local_irq_restore(flags);
449669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return r;
450669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
451669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
452669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
453669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Opti 82C611A
454669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
455669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	This controller supports PIO0 to PIO3.
456669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
457669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
458defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic void opti82c611a_set_piomode(struct ata_port *ap,
459defc9cd826e4a99f550504a744f9407b518828aeAlan Cox						struct ata_device *adev)
460669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
461669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 active, recover, setup;
462669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_timing t;
463669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_device *pair = ata_dev_pair(adev);
464669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int clock;
465669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int khz[4] = { 50000, 40000, 33000, 25000 };
466669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 rc;
467669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
468669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Enter configuration mode */
4690d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	ioread16(ap->ioaddr.error_addr);
4700d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	ioread16(ap->ioaddr.error_addr);
4710d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(3, ap->ioaddr.nsect_addr);
472669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
473669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Read VLB clock strapping */
4740d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	clock = 1000000000 / khz[ioread8(ap->ioaddr.lbah_addr) & 0x03];
475669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
476669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Get the timing data in cycles */
477669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	ata_timing_compute(adev, adev->pio_mode, &t, clock, 1000);
478669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
479669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Setup timing is shared */
480669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (pair) {
481669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		struct ata_timing tp;
482669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		ata_timing_compute(pair, pair->pio_mode, &tp, clock, 1000);
483669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
484669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP);
485669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
486669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
48707633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	active = clamp_val(t.active, 2, 17) - 2;
48807633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	recover = clamp_val(t.recover, 1, 16) - 1;
48907633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	setup = clamp_val(t.setup, 1, 4) - 1;
490669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
491669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Select the right timing bank for write timing */
4920d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = ioread8(ap->ioaddr.lbal_addr);
493669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc &= 0x7F;
494669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc |= (adev->devno << 7);
4950d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(rc, ap->ioaddr.lbal_addr);
496669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
497669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Write the timings */
4980d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(active << 4 | recover, ap->ioaddr.error_addr);
499669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
500669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Select the right bank for read timings, also
501669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	   load the shared timings for address */
5020d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = ioread8(ap->ioaddr.device_addr);
503669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc &= 0xC0;
504669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc |= adev->devno;	/* Index select */
505669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc |= (setup << 4) | 0x04;
5060d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(rc, ap->ioaddr.device_addr);
507669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
508669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Load the read timings */
5090d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(active << 4 | recover, ap->ioaddr.data_addr);
510669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
511669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Ensure the timing register mode is right */
5120d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = ioread8(ap->ioaddr.lbal_addr);
513669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc &= 0x73;
514669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc |= 0x84;
5150d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(rc, ap->ioaddr.lbal_addr);
516669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
517669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Exit command mode */
5180d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(0x83,  ap->ioaddr.nsect_addr);
519669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
520669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
521669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
522669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations opti82c611a_port_ops = {
523029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
524669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_piomode	= opti82c611a_set_piomode,
525669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
526669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
527669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
528669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Opti 82C465MV
529669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
530669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	This controller supports PIO0 to PIO3. Unlike the 611A the MVB
531669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	version is dual channel but doesn't have a lot of unique registers.
532669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
533669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
534669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
535669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
536669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 active, recover, setup;
537669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_timing t;
538669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_device *pair = ata_dev_pair(adev);
539669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int clock;
540669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int khz[4] = { 50000, 40000, 33000, 25000 };
541669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 rc;
542669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 sysclk;
543669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
544669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Get the clock */
545669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	sysclk = opti_syscfg(0xAC) & 0xC0;	/* BIOS set */
546669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
547669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Enter configuration mode */
5480d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	ioread16(ap->ioaddr.error_addr);
5490d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	ioread16(ap->ioaddr.error_addr);
5500d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(3, ap->ioaddr.nsect_addr);
551669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
552669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Read VLB clock strapping */
553669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	clock = 1000000000 / khz[sysclk];
554669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
555669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Get the timing data in cycles */
556669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	ata_timing_compute(adev, adev->pio_mode, &t, clock, 1000);
557669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
558669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Setup timing is shared */
559669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (pair) {
560669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		struct ata_timing tp;
561669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		ata_timing_compute(pair, pair->pio_mode, &tp, clock, 1000);
562669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
563669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP);
564669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
565669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
56607633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	active = clamp_val(t.active, 2, 17) - 2;
56707633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	recover = clamp_val(t.recover, 1, 16) - 1;
56807633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	setup = clamp_val(t.setup, 1, 4) - 1;
569669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
570669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Select the right timing bank for write timing */
5710d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = ioread8(ap->ioaddr.lbal_addr);
572669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc &= 0x7F;
573669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc |= (adev->devno << 7);
5740d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(rc, ap->ioaddr.lbal_addr);
575669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
576669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Write the timings */
5770d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(active << 4 | recover, ap->ioaddr.error_addr);
578669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
579669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Select the right bank for read timings, also
580669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	   load the shared timings for address */
5810d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = ioread8(ap->ioaddr.device_addr);
582669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc &= 0xC0;
583669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc |= adev->devno;	/* Index select */
584669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc |= (setup << 4) | 0x04;
5850d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(rc, ap->ioaddr.device_addr);
586669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
587669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Load the read timings */
5880d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(active << 4 | recover, ap->ioaddr.data_addr);
589669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
590669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Ensure the timing register mode is right */
5910d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = ioread8(ap->ioaddr.lbal_addr);
592669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc &= 0x73;
593669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	rc |= 0x84;
5940d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(rc, ap->ioaddr.lbal_addr);
595669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
596669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Exit command mode */
5970d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(0x83,  ap->ioaddr.nsect_addr);
598669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
599669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* We need to know this for quad device on the MVB */
600669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	ap->host->private_data = ap;
601669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
602669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
603669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
6049363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo *	opt82c465mv_qc_issue		-	command issue
605669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@qc: command pending
606669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
607669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Called when the libata layer is about to issue a command. We wrap
608669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	this interface so that we can load the correct ATA timings. The
609669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	MVB has a single set of timing registers and these are shared
610669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	across channels. As there are two registers we really ought to
611669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	track the last two used values as a sort of register window. For
612669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	now we just reload on a channel switch. On the single channel
613669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	setup this condition never fires so we do nothing extra.
614669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
615669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	FIXME: dual channel needs ->serialize support
616669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
617669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
6189363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heostatic unsigned int opti82c46x_qc_issue(struct ata_queued_cmd *qc)
619669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
620669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_port *ap = qc->ap;
621669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_device *adev = qc->dev;
622669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
623669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* If timings are set and for the wrong channel (2nd test is
624669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	   due to a libata shortcoming and will eventually go I hope) */
625669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (ap->host->private_data != ap->host
626669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	    && ap->host->private_data != NULL)
627669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		opti82c46x_set_piomode(ap, adev);
628669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
6299363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo	return ata_sff_qc_issue(qc);
630669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
631669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
632669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations opti82c46x_port_ops = {
633029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
634669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_piomode	= opti82c46x_set_piomode,
6359363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo	.qc_issue	= opti82c46x_qc_issue,
636669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
637669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
638669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
6398c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz *	qdi65x0_set_piomode		-	PIO setup for QDI65x0
640defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	@ap: Port
641defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	@adev: Device
642669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
6438c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz *	In single channel mode the 6580 has one clock per device and we can
6448c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz *	avoid the requirement to clock switch. We also have to load the timing
6458c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz *	into the right clock according to whether we are master or slave.
6468c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz *
647defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	In dual channel mode the 6580 has one clock per channel and we have
6489363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo *	to software clockswitch in qc_issue.
649669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
650669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
6518c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewiczstatic void qdi65x0_set_piomode(struct ata_port *ap, struct ata_device *adev)
652669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
653defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct ata_timing t;
654cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison	struct legacy_data *ld_qdi = ap->host->private_data;
655defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	int active, recovery;
656defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	u8 timing;
657669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
658defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	/* Get the timing data in cycles */
659defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
660defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
661cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison	if (ld_qdi->fast) {
66207633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison		active = 8 - clamp_val(t.active, 1, 8);
66307633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison		recovery = 18 - clamp_val(t.recover, 3, 18);
664defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	} else {
66507633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison		active = 9 - clamp_val(t.active, 2, 9);
66607633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison		recovery = 15 - clamp_val(t.recover, 0, 15);
667defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	}
668defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	timing = (recovery << 4) | active | 0x08;
669cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison	ld_qdi->clock[adev->devno] = timing;
670669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
6718c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	if (ld_qdi->type == QDI6580)
6728c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz		outb(timing, ld_qdi->timing + 2 * adev->devno);
6738c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	else
6748c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz		outb(timing, ld_qdi->timing + 2 * ap->port_no);
675defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
676defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	/* Clear the FIFO */
6778c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	if (ld_qdi->type != QDI6500 && adev->class != ATA_DEV_ATA)
6786809e7301fba4f9fa446ead5167faed115690fc4Bartlomiej Zolnierkiewicz		outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3);
679defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}
680defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
681defc9cd826e4a99f550504a744f9407b518828aeAlan Cox/**
6829363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo *	qdi_qc_issue		-	command issue
683defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	@qc: command pending
684defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *
685defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	Called when the libata layer is about to issue a command. We wrap
686defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	this interface so that we can load the correct ATA timings.
687defc9cd826e4a99f550504a744f9407b518828aeAlan Cox */
688defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
6899363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heostatic unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
690defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{
691defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct ata_port *ap = qc->ap;
692defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct ata_device *adev = qc->dev;
693cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison	struct legacy_data *ld_qdi = ap->host->private_data;
694defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
695cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison	if (ld_qdi->clock[adev->devno] != ld_qdi->last) {
696defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (adev->pio_mode) {
697cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison			ld_qdi->last = ld_qdi->clock[adev->devno];
698cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison			outb(ld_qdi->clock[adev->devno], ld_qdi->timing +
699defc9cd826e4a99f550504a744f9407b518828aeAlan Cox							2 * ap->port_no);
700defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		}
701669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
7029363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo	return ata_sff_qc_issue(qc);
703defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}
704669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
705b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
706defc9cd826e4a99f550504a744f9407b518828aeAlan Cox					unsigned int buflen, int rw)
707defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{
708defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct ata_port *ap = adev->link->ap;
709defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	int slop = buflen & 3;
710669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
711e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox	if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3)
712e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox					&& (ap->pflags & ATA_PFLAG_PIO32)) {
713defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (rw == WRITE)
714defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
715defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		else
716defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
717669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
718defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (unlikely(slop)) {
7196ad67403da47e833d9e418caf7f28295c9472e11Harvey Harrison			__le32 pad;
720defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			if (rw == WRITE) {
721defc9cd826e4a99f550504a744f9407b518828aeAlan Cox				memcpy(&pad, buf + buflen - slop, slop);
7226ad67403da47e833d9e418caf7f28295c9472e11Harvey Harrison				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
723defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			} else {
7246ad67403da47e833d9e418caf7f28295c9472e11Harvey Harrison				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
725defc9cd826e4a99f550504a744f9407b518828aeAlan Cox				memcpy(buf + buflen - slop, &pad, slop);
726defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			}
727defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		}
728defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		return (buflen + 3) & ~3;
729defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	} else
7309363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo		return ata_sff_data_xfer(adev, buf, buflen, rw);
731defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}
732defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
733b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic int qdi_port(struct platform_device *dev,
734b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox			struct legacy_probe *lp, struct legacy_data *ld)
735b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox{
736b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	if (devm_request_region(&dev->dev, lp->private, 4, "qdi") == NULL)
737b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		return -EBUSY;
738b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	ld->timing = lp->private;
739b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	return 0;
740b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox}
741b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
742defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic struct ata_port_operations qdi6500_port_ops = {
743029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
7448c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	.set_piomode	= qdi65x0_set_piomode,
7459363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo	.qc_issue	= qdi_qc_issue,
7465682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo	.sff_data_xfer	= vlb32_data_xfer,
747defc9cd826e4a99f550504a744f9407b518828aeAlan Cox};
748defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
749defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic struct ata_port_operations qdi6580_port_ops = {
750029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
7518c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	.set_piomode	= qdi65x0_set_piomode,
7525682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo	.sff_data_xfer	= vlb32_data_xfer,
753defc9cd826e4a99f550504a744f9407b518828aeAlan Cox};
754defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
755defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic struct ata_port_operations qdi6580dp_port_ops = {
756029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
7578c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	.set_piomode	= qdi65x0_set_piomode,
75843c7d17ee7e03433c57dc4ce457d34110108455aBartlomiej Zolnierkiewicz	.qc_issue	= qdi_qc_issue,
7595682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo	.sff_data_xfer	= vlb32_data_xfer,
760defc9cd826e4a99f550504a744f9407b518828aeAlan Cox};
761defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
762b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic DEFINE_SPINLOCK(winbond_lock);
763b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
764b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic void winbond_writecfg(unsigned long port, u8 reg, u8 val)
765b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox{
766b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	unsigned long flags;
767b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	spin_lock_irqsave(&winbond_lock, flags);
768b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	outb(reg, port + 0x01);
769b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	outb(val, port + 0x02);
770b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	spin_unlock_irqrestore(&winbond_lock, flags);
771b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox}
772b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
773b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic u8 winbond_readcfg(unsigned long port, u8 reg)
774b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox{
775b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	u8 val;
776b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
777b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	unsigned long flags;
778b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	spin_lock_irqsave(&winbond_lock, flags);
779b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	outb(reg, port + 0x01);
780b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	val = inb(port + 0x02);
781b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	spin_unlock_irqrestore(&winbond_lock, flags);
782b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
783b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	return val;
784b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox}
785b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
786b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
787b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox{
788b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	struct ata_timing t;
789cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison	struct legacy_data *ld_winbond = ap->host->private_data;
790b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	int active, recovery;
791b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	u8 reg;
792b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2);
793b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
794cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison	reg = winbond_readcfg(ld_winbond->timing, 0x81);
795b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
796b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	/* Get the timing data in cycles */
797b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	if (reg & 0x40)		/* Fast VLB bus, assume 50MHz */
798b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
799b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	else
800b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
801b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
80207633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	active = (clamp_val(t.active, 3, 17) - 1) & 0x0F;
80307633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	recovery = (clamp_val(t.recover, 1, 15) + 1) & 0x0F;
804b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	timing = (active << 4) | recovery;
805cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison	winbond_writecfg(ld_winbond->timing, timing, reg);
806b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
807b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	/* Load the setup timing */
808b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
809b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	reg = 0x35;
810b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	if (adev->class != ATA_DEV_ATA)
811b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		reg |= 0x08;	/* FIFO off */
812b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	if (!ata_pio_need_iordy(adev))
813b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		reg |= 0x02;	/* IORDY off */
81407633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison	reg |= (clamp_val(t.setup, 0, 3) << 6);
815cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison	winbond_writecfg(ld_winbond->timing, timing + 1, reg);
816b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox}
817b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
818b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic int winbond_port(struct platform_device *dev,
819b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox			struct legacy_probe *lp, struct legacy_data *ld)
820b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox{
821b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	if (devm_request_region(&dev->dev, lp->private, 4, "winbond") == NULL)
822b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		return -EBUSY;
823b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	ld->timing = lp->private;
824b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	return 0;
825b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox}
826b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
827b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic struct ata_port_operations winbond_port_ops = {
828029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &legacy_base_port_ops,
829b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	.set_piomode	= winbond_set_piomode,
8305682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo	.sff_data_xfer	= vlb32_data_xfer,
831b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox};
832b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
833defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic struct legacy_controller controllers[] = {
834b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"BIOS",	&legacy_port_ops, 	ATA_PIO4,
835e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox			ATA_FLAG_NO_IORDY,	0,			NULL },
836b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"Snooping", 	&simple_port_ops, 	ATA_PIO4,
837e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox			0,			0,			NULL },
838b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"PDC20230",	&pdc20230_port_ops,	ATA_PIO2,
839e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox			ATA_FLAG_NO_IORDY,
84016e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu			ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,	NULL },
841b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"HT6560A",	&ht6560a_port_ops,	ATA_PIO2,
842e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox			ATA_FLAG_NO_IORDY,	0,			NULL },
843b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"HT6560B",	&ht6560b_port_ops,	ATA_PIO4,
844e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox			ATA_FLAG_NO_IORDY,	0,			NULL },
845b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"OPTI82C611A",	&opti82c611a_port_ops,	ATA_PIO3,
846e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox			0,			0,			NULL },
847b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"OPTI82C46X",	&opti82c46x_port_ops,	ATA_PIO3,
848e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox			0,			0,			NULL },
849b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"QDI6500",	&qdi6500_port_ops,	ATA_PIO2,
850e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox			ATA_FLAG_NO_IORDY,
85116e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu			ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,    qdi_port },
852b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"QDI6580",	&qdi6580_port_ops,	ATA_PIO4,
85316e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
854b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"QDI6580DP",	&qdi6580dp_port_ops,	ATA_PIO4,
85516e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
856b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz	{"W83759A",	&winbond_port_ops,	ATA_PIO4,
85716e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,
858e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox								winbond_port }
859defc9cd826e4a99f550504a744f9407b518828aeAlan Cox};
860defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
861defc9cd826e4a99f550504a744f9407b518828aeAlan Cox/**
862defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	probe_chip_type		-	Discover controller
863defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	@probe: Probe entry to check
864defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *
865defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	Probe an ATA port and identify the type of controller. We don't
866defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	check if the controller appears to be driveless at this point.
867defc9cd826e4a99f550504a744f9407b518828aeAlan Cox */
868defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
869b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic __init int probe_chip_type(struct legacy_probe *probe)
870defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{
871defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	int mask = 1 << probe->slot;
872defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
873b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	if (winbond && (probe->port == 0x1F0 || probe->port == 0x170)) {
874b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		u8 reg = winbond_readcfg(winbond, 0x81);
875b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		reg |= 0x80;	/* jumpered mode off */
876b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		winbond_writecfg(winbond, 0x81, reg);
877b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		reg = winbond_readcfg(winbond, 0x83);
878b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		reg |= 0xF0;	/* local control */
879b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		winbond_writecfg(winbond, 0x83, reg);
880b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		reg = winbond_readcfg(winbond, 0x85);
881b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		reg |= 0xF0;	/* programmable timing */
882b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		winbond_writecfg(winbond, 0x85, reg);
883b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
884b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		reg = winbond_readcfg(winbond, 0x81);
885b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
886b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		if (reg & mask)
887b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox			return W83759A;
888b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	}
889defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (probe->port == 0x1F0) {
890defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		unsigned long flags;
891defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		local_irq_save(flags);
892669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		/* Probes */
893669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		outb(inb(0x1F2) | 0x80, 0x1F2);
894defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		inb(0x1F5);
895669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x1F2);
896669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x3F6);
897669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x3F6);
898669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x1F2);
899669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		inb(0x1F2);
900669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
901669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if ((inb(0x1F2) & 0x80) == 0) {
902669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			/* PDC20230c or 20630 ? */
903defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			printk(KERN_INFO  "PDC20230-C/20630 VLB ATA controller"
904defc9cd826e4a99f550504a744f9407b518828aeAlan Cox							" detected.\n");
905669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			udelay(100);
906669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			inb(0x1F5);
907defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			local_irq_restore(flags);
908defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			return PDC20230;
909669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		} else {
910669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			outb(0x55, 0x1F2);
911669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			inb(0x1F2);
912669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			inb(0x1F2);
913defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			if (inb(0x1F2) == 0x00)
914defc9cd826e4a99f550504a744f9407b518828aeAlan Cox				printk(KERN_INFO "PDC20230-B VLB ATA "
915defc9cd826e4a99f550504a744f9407b518828aeAlan Cox						     "controller detected.\n");
916defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			local_irq_restore(flags);
917defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			return BIOS;
918669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		}
919669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		local_irq_restore(flags);
920669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
921669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
922defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (ht6560a & mask)
923defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		return HT6560A;
924defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (ht6560b & mask)
925defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		return HT6560B;
926defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (opti82c611a & mask)
927defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		return OPTI611A;
928defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (opti82c46x & mask)
929defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		return OPTI46X;
930defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (autospeed & mask)
931defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		return SNOOP;
932defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	return BIOS;
933defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}
934defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
935defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
936defc9cd826e4a99f550504a744f9407b518828aeAlan Cox/**
937defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	legacy_init_one		-	attach a legacy interface
938defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	@pl: probe record
939defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *
940defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	Register an ISA bus IDE interface. Such interfaces are PIO and we
941defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	assume do not support IRQ sharing.
942defc9cd826e4a99f550504a744f9407b518828aeAlan Cox */
943defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
944defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic __init int legacy_init_one(struct legacy_probe *probe)
945defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{
946defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct legacy_controller *controller = &controllers[probe->type];
947defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	int pio_modes = controller->pio_mask;
948defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	unsigned long io = probe->port;
949defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	u32 mask = (1 << probe->slot);
950defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct ata_port_operations *ops = controller->ops;
951defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct legacy_data *ld = &legacy_data[probe->slot];
952defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct ata_host *host = NULL;
953defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct ata_port *ap;
954defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct platform_device *pdev;
955defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct ata_device *dev;
956defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	void __iomem *io_addr, *ctrl_addr;
957defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
958defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	int ret;
959defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
960defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	iordy |= controller->flags;
961defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
962defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	pdev = platform_device_register_simple(DRV_NAME, probe->slot, NULL, 0);
963defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (IS_ERR(pdev))
964defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		return PTR_ERR(pdev);
965669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
966defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	ret = -EBUSY;
967defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL ||
968defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	    devm_request_region(&pdev->dev, io + 0x0206, 1,
969defc9cd826e4a99f550504a744f9407b518828aeAlan Cox							"pata_legacy") == NULL)
970defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		goto fail;
971f834e49f1a09414e9618ff0c9cd83c2114032bb6Alan Cox
9725d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ret = -ENOMEM;
973defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	io_addr = devm_ioport_map(&pdev->dev, io, 8);
974defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	ctrl_addr = devm_ioport_map(&pdev->dev, io + 0x0206, 1);
975defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (!io_addr || !ctrl_addr)
976defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		goto fail;
9778c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz	ld->type = probe->type;
978defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (controller->setup)
979b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		if (controller->setup(pdev, probe, ld) < 0)
980defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			goto fail;
9815d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	host = ata_host_alloc(&pdev->dev, 1);
9825d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	if (!host)
9835d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		goto fail;
9845d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ap = host->ports[0];
9855d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
9865d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ap->ops = ops;
9875d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ap->pio_mask = pio_modes;
9885d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ap->flags |= ATA_FLAG_SLAVE_POSS | iordy;
989e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox	ap->pflags |= controller->pflags;
9905d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ap->ioaddr.cmd_addr = io_addr;
9915d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ap->ioaddr.altstatus_addr = ctrl_addr;
9925d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ap->ioaddr.ctl_addr = ctrl_addr;
9939363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo	ata_sff_std_ports(&ap->ioaddr);
994b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	ap->host->private_data = ld;
9955d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
996defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, io + 0x0206);
997cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
9989363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo	ret = ata_host_activate(host, probe->irq, ata_sff_interrupt, 0,
9999363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo				&legacy_sht);
10005d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	if (ret)
1001669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		goto fail;
100245bc955bb1324a46c9539550cc615994e6d0a43dJames Bottomley	async_synchronize_full();
1003669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	ld->platform_dev = pdev;
1004669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1005defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	/* Nothing found means we drop the port as its probably not there */
1006defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1007defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	ret = -ENODEV;
10081eca4365be25c540650693e941bc06a66cf38f94Tejun Heo	ata_for_each_dev(dev, &ap->link, ALL) {
1009defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (!ata_dev_absent(dev)) {
1010defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			legacy_host[probe->slot] = host;
1011defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			ld->platform_dev = pdev;
1012defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			return 0;
1013defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		}
1014defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	}
101520cbf5f8c0fe3df2ddbde1f334993b4dda18a651Tejun Heo	ata_host_detach(host);
1016669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikfail:
1017669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	platform_device_unregister(pdev);
1018669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return ret;
1019669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
1020669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1021669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
1022669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	legacy_check_special_cases	-	ATA special cases
1023669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@p: PCI device to check
1024669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@master: set this if we find an ATA master
1025669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@master: set this if we find an ATA secondary
1026669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
1027defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	A small number of vendors implemented early PCI ATA interfaces
1028defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	on bridge logic without the ATA interface being PCI visible.
1029defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	Where we have a matching PCI driver we must skip the relevant
1030defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	device here. If we don't know about it then the legacy driver
1031defc9cd826e4a99f550504a744f9407b518828aeAlan Cox *	is the right driver anyway.
1032669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
1033669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1034b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic void __init legacy_check_special_cases(struct pci_dev *p, int *primary,
1035defc9cd826e4a99f550504a744f9407b518828aeAlan Cox								int *secondary)
1036669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
1037669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Cyrix CS5510 pre SFF MWDMA ATA on the bridge */
1038669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (p->vendor == 0x1078 && p->device == 0x0000) {
1039669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		*primary = *secondary = 1;
1040669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		return;
1041669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
1042669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Cyrix CS5520 pre SFF MWDMA ATA on the bridge */
1043669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (p->vendor == 0x1078 && p->device == 0x0002) {
1044669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		*primary = *secondary = 1;
1045669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		return;
1046669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
1047669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Intel MPIIX - PIO ATA on non PCI side of bridge */
1048669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (p->vendor == 0x8086 && p->device == 0x1234) {
1049669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		u16 r;
1050669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		pci_read_config_word(p, 0x6C, &r);
1051defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (r & 0x8000) {
1052defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			/* ATA port enabled */
1053669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			if (r & 0x4000)
1054669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				*secondary = 1;
1055669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			else
1056669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				*primary = 1;
1057669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		}
1058669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		return;
1059669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
1060669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
1061669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1062defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic __init void probe_opti_vlb(void)
1063defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{
1064defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	/* If an OPTI 82C46X is present find out where the channels are */
1065defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	static const char *optis[4] = {
1066defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		"3/463MV", "5MV",
1067defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		"5MVA", "5MVB"
1068defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	};
1069defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	u8 chans = 1;
1070defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6;
1071defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1072defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	opti82c46x = 3;	/* Assume master and slave first */
1073defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n",
1074defc9cd826e4a99f550504a744f9407b518828aeAlan Cox								optis[ctrl]);
1075defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (ctrl == 3)
1076defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1;
1077defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	ctrl = opti_syscfg(0xAC);
1078defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	/* Check enabled and this port is the 465MV port. On the
1079defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	   MVB we may have two channels */
1080defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (ctrl & 8) {
1081defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (chans == 2) {
1082defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			legacy_probe_add(0x1F0, 14, OPTI46X, 0);
1083defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			legacy_probe_add(0x170, 15, OPTI46X, 0);
1084defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		}
1085defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (ctrl & 4)
1086defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			legacy_probe_add(0x170, 15, OPTI46X, 0);
1087defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		else
1088defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			legacy_probe_add(0x1F0, 14, OPTI46X, 0);
1089defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	} else
1090defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		legacy_probe_add(0x1F0, 14, OPTI46X, 0);
1091defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}
1092defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1093defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic __init void qdi65_identify_port(u8 r, u8 res, unsigned long port)
1094defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{
1095defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	static const unsigned long ide_port[2] = { 0x170, 0x1F0 };
1096defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	/* Check card type */
1097defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if ((r & 0xF0) == 0xC0) {
1098defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		/* QD6500: single channel */
1099b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		if (r & 8)
1100defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			/* Disabled ? */
1101defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			return;
1102defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01),
1103defc9cd826e4a99f550504a744f9407b518828aeAlan Cox								QDI6500, port);
1104defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	}
1105defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) {
1106defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		/* QD6580: dual channel */
1107defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (!request_region(port + 2 , 2, "pata_qdi")) {
1108defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			release_region(port, 2);
1109defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			return;
1110defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		}
1111defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		res = inb(port + 3);
1112defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		/* Single channel mode ? */
1113defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (res & 1)
1114defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01),
1115defc9cd826e4a99f550504a744f9407b518828aeAlan Cox								QDI6580, port);
1116defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		else { /* Dual channel mode */
1117defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			legacy_probe_add(0x1F0, 14, QDI6580DP, port);
1118defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			/* port + 0x02, r & 0x04 */
1119defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			legacy_probe_add(0x170, 15, QDI6580DP, port + 2);
1120defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		}
1121b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		release_region(port + 2, 2);
1122defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	}
1123defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}
1124defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1125defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic __init void probe_qdi_vlb(void)
1126defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{
1127defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	unsigned long flags;
1128defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	static const unsigned long qd_port[2] = { 0x30, 0xB0 };
1129defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	int i;
1130defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1131defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	/*
1132defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	 *	Check each possible QD65xx base address
1133defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	 */
1134defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1135defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	for (i = 0; i < 2; i++) {
1136defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		unsigned long port = qd_port[i];
1137defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		u8 r, res;
1138defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1139defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1140defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (request_region(port, 2, "pata_qdi")) {
1141defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			/* Check for a card */
1142defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			local_irq_save(flags);
1143defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			/* I have no h/w that needs this delay but it
1144defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			   is present in the historic code */
1145defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			r = inb(port);
1146defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			udelay(1);
1147defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			outb(0x19, port);
1148defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			udelay(1);
1149defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			res = inb(port);
1150defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			udelay(1);
1151defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			outb(r, port);
1152defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			udelay(1);
1153defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			local_irq_restore(flags);
1154defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1155defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			/* Fail */
1156defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			if (res == 0x19) {
1157defc9cd826e4a99f550504a744f9407b518828aeAlan Cox				release_region(port, 2);
1158defc9cd826e4a99f550504a744f9407b518828aeAlan Cox				continue;
1159defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			}
1160defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			/* Passes the presence test */
1161defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			r = inb(port + 1);
1162defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			udelay(1);
1163defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			/* Check port agrees with port set */
1164b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox			if ((r & 2) >> 1 == i)
1165b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox				qdi65_identify_port(r, res, port);
1166b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox			release_region(port, 2);
1167defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		}
1168defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	}
1169defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}
1170669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1171669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
1172669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	legacy_init		-	attach legacy interfaces
1173669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
1174669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Attach legacy IDE interfaces by scanning the usual IRQ/port suspects.
1175669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Right now we do not scan the ide0 and ide1 address but should do so
1176669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	for non PCI systems or systems with no PCI IDE legacy mode devices.
1177669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	If you fix that note there are special cases to consider like VLB
1178669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	drivers and CS5510/20.
1179669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
1180669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1181669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic __init int legacy_init(void)
1182669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
1183669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int i;
1184669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int ct = 0;
1185669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int primary = 0;
1186669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int secondary = 0;
1187defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	int pci_present = 0;
1188defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	struct legacy_probe *pl = &probe_list[0];
1189defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	int slot = 0;
1190669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1191669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct pci_dev *p = NULL;
1192669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1193669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	for_each_pci_dev(p) {
1194669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		int r;
1195defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		/* Check for any overlap of the system ATA mappings. Native
1196defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		   mode controllers stuck on these addresses or some devices
1197defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		   in 'raid' mode won't be found by the storage class test */
1198669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		for (r = 0; r < 6; r++) {
1199669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			if (pci_resource_start(p, r) == 0x1f0)
1200669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				primary = 1;
1201669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			if (pci_resource_start(p, r) == 0x170)
1202669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				secondary = 1;
1203669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		}
1204669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		/* Check for special cases */
1205669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		legacy_check_special_cases(p, &primary, &secondary);
1206669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1207defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		/* If PCI bus is present then don't probe for tertiary
1208defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		   legacy ports */
1209defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		pci_present = 1;
1210669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
1211669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1212b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox	if (winbond == 1)
1213b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox		winbond = 0x130;	/* Default port, alt is 1B0 */
1214b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox
1215defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (primary == 0 || all)
1216defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		legacy_probe_add(0x1F0, 14, UNKNOWN, 0);
1217defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (secondary == 0 || all)
1218defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		legacy_probe_add(0x170, 15, UNKNOWN, 0);
1219defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1220defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (probe_all || !pci_present) {
1221defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		/* ISA/VLB extra ports */
1222defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		legacy_probe_add(0x1E8, 11, UNKNOWN, 0);
1223defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		legacy_probe_add(0x168, 10, UNKNOWN, 0);
1224defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		legacy_probe_add(0x1E0, 8, UNKNOWN, 0);
1225defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		legacy_probe_add(0x160, 12, UNKNOWN, 0);
1226669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
1227669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1228defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (opti82c46x)
1229defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		probe_opti_vlb();
1230defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	if (qdi)
1231defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		probe_qdi_vlb();
1232defc9cd826e4a99f550504a744f9407b518828aeAlan Cox
1233defc9cd826e4a99f550504a744f9407b518828aeAlan Cox	for (i = 0; i < NR_HOST; i++, pl++) {
1234defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (pl->port == 0)
1235669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			continue;
1236defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (pl->type == UNKNOWN)
1237defc9cd826e4a99f550504a744f9407b518828aeAlan Cox			pl->type = probe_chip_type(pl);
1238defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		pl->slot = slot++;
1239defc9cd826e4a99f550504a744f9407b518828aeAlan Cox		if (legacy_init_one(pl) == 0)
1240669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			ct++;
1241669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
1242669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (ct != 0)
1243669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		return 0;
1244669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return -ENODEV;
1245669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
1246669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1247669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic __exit void legacy_exit(void)
1248669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
1249669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int i;
1250669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1251669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	for (i = 0; i < nr_legacy_host; i++) {
1252669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		struct legacy_data *ld = &legacy_data[i];
125324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		ata_host_detach(legacy_host[i]);
1254669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		platform_device_unregister(ld->platform_dev);
1255669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
1256669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
1257669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1258669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_AUTHOR("Alan Cox");
1259669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DESCRIPTION("low-level driver for legacy ATA");
1260669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_LICENSE("GPL");
1261669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_VERSION(DRV_VERSION);
12620dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej ZolnierkiewiczMODULE_ALIAS("pata_qdi");
12636d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej ZolnierkiewiczMODULE_ALIAS("pata_winbond");
1264669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1265669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(probe_all, int, 0);
1266669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(autospeed, int, 0);
1267669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(ht6560a, int, 0);
1268669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(ht6560b, int, 0);
1269669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(opti82c611a, int, 0);
1270669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(opti82c46x, int, 0);
1271defc9cd826e4a99f550504a744f9407b518828aeAlan Coxmodule_param(qdi, int, 0);
12726d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewiczmodule_param(winbond, int, 0);
1273669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(pio_mask, int, 0);
1274f834e49f1a09414e9618ff0c9cd83c2114032bb6Alan Coxmodule_param(iordy_mask, int, 0);
1275669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1276669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_init(legacy_init);
1277669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_exit(legacy_exit);
1278