xref: /openbmc/linux/drivers/ata/pata_ali.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1669a5db4SJeff Garzik /*
2669a5db4SJeff Garzik  * pata_ali.c 	- ALI 15x3 PATA for new ATA layer
3669a5db4SJeff Garzik  *			  (C) 2005 Red Hat Inc
4669a5db4SJeff Garzik  *
5669a5db4SJeff Garzik  * based in part upon
6669a5db4SJeff Garzik  * linux/drivers/ide/pci/alim15x3.c		Version 0.17	2003/01/02
7669a5db4SJeff Garzik  *
8669a5db4SJeff Garzik  *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
9669a5db4SJeff Garzik  *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
10669a5db4SJeff Garzik  *  Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer
11669a5db4SJeff Garzik  *
12669a5db4SJeff Garzik  *  Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org)
13669a5db4SJeff Garzik  *  May be copied or modified under the terms of the GNU General Public License
14669a5db4SJeff Garzik  *  Copyright (C) 2002 Alan Cox <alan@redhat.com>
15669a5db4SJeff Garzik  *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
16669a5db4SJeff Garzik  *
17669a5db4SJeff Garzik  *  Documentation
18669a5db4SJeff Garzik  *	Chipset documentation available under NDA only
19669a5db4SJeff Garzik  *
20669a5db4SJeff Garzik  *  TODO/CHECK
21669a5db4SJeff Garzik  *	Cannot have ATAPI on both master & slave for rev < c2 (???) but
221b2c357cSAlan Cox  *	otherwise should do atapi DMA (For now for old we do PIO only for
231b2c357cSAlan Cox  *	ATAPI)
241b2c357cSAlan Cox  *	Review Sunblade workaround.
25669a5db4SJeff Garzik  */
26669a5db4SJeff Garzik 
27669a5db4SJeff Garzik #include <linux/kernel.h>
28669a5db4SJeff Garzik #include <linux/module.h>
29669a5db4SJeff Garzik #include <linux/pci.h>
30669a5db4SJeff Garzik #include <linux/init.h>
31669a5db4SJeff Garzik #include <linux/blkdev.h>
32669a5db4SJeff Garzik #include <linux/delay.h>
33669a5db4SJeff Garzik #include <scsi/scsi_host.h>
34669a5db4SJeff Garzik #include <linux/libata.h>
35669a5db4SJeff Garzik #include <linux/dmi.h>
36669a5db4SJeff Garzik 
37669a5db4SJeff Garzik #define DRV_NAME "pata_ali"
38fc80902fSAlan Cox #define DRV_VERSION "0.7.8"
39669a5db4SJeff Garzik 
4049737f26SJason Wang static int ali_atapi_dma;
418243e636STejun Heo module_param_named(atapi_dma, ali_atapi_dma, int, 0644);
428243e636STejun Heo MODULE_PARM_DESC(atapi_dma, "Enable ATAPI DMA (0=disable, 1=enable)");
438243e636STejun Heo 
44bc42b24eSAndrew Morton static struct pci_dev *ali_isa_bridge;
451b2c357cSAlan Cox 
46669a5db4SJeff Garzik /*
47669a5db4SJeff Garzik  *	Cable special cases
48669a5db4SJeff Garzik  */
49669a5db4SJeff Garzik 
501855256cSJeff Garzik static const struct dmi_system_id cable_dmi_table[] = {
51669a5db4SJeff Garzik 	{
52669a5db4SJeff Garzik 		.ident = "HP Pavilion N5430",
53669a5db4SJeff Garzik 		.matches = {
54669a5db4SJeff Garzik 			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
555c8d5201SAlan Cox 			DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
56669a5db4SJeff Garzik 		},
57669a5db4SJeff Garzik 	},
5803e6f489SDaniel Exner 	{
59802872e7SBartlomiej Zolnierkiewicz 		.ident = "Toshiba Satellite S1800-814",
6003e6f489SDaniel Exner 		.matches = {
6103e6f489SDaniel Exner 			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
6203e6f489SDaniel Exner 			DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"),
6303e6f489SDaniel Exner 		},
6403e6f489SDaniel Exner 	},
65669a5db4SJeff Garzik 	{ }
66669a5db4SJeff Garzik };
67669a5db4SJeff Garzik 
ali_cable_override(struct pci_dev * pdev)68669a5db4SJeff Garzik static int ali_cable_override(struct pci_dev *pdev)
69669a5db4SJeff Garzik {
70669a5db4SJeff Garzik 	/* Fujitsu P2000 */
71669a5db4SJeff Garzik 	if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF)
72669a5db4SJeff Garzik 	   	return 1;
738f59a13aSAlan Cox 	/* Mitac 8317 (Winbook-A) and relatives */
748f59a13aSAlan Cox 	if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317)
758f59a13aSAlan Cox 		return 1;
76669a5db4SJeff Garzik 	/* Systems by DMI */
77669a5db4SJeff Garzik 	if (dmi_check_system(cable_dmi_table))
78669a5db4SJeff Garzik 		return 1;
79669a5db4SJeff Garzik 	return 0;
80669a5db4SJeff Garzik }
81669a5db4SJeff Garzik 
82669a5db4SJeff Garzik /**
83669a5db4SJeff Garzik  *	ali_c2_cable_detect	-	cable detection
84669a5db4SJeff Garzik  *	@ap: ATA port
85669a5db4SJeff Garzik  *
86669a5db4SJeff Garzik  *	Perform cable detection for C2 and later revisions
87669a5db4SJeff Garzik  */
88669a5db4SJeff Garzik 
ali_c2_cable_detect(struct ata_port * ap)89669a5db4SJeff Garzik static int ali_c2_cable_detect(struct ata_port *ap)
90669a5db4SJeff Garzik {
91669a5db4SJeff Garzik 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
92669a5db4SJeff Garzik 	u8 ata66;
93669a5db4SJeff Garzik 
94669a5db4SJeff Garzik 	/* Certain laptops use short but suitable cables and don't
95669a5db4SJeff Garzik 	   implement the detect logic */
96669a5db4SJeff Garzik 
97669a5db4SJeff Garzik 	if (ali_cable_override(pdev))
98fc085150SAlan Cox 		return ATA_CBL_PATA40_SHORT;
99669a5db4SJeff Garzik 
100669a5db4SJeff Garzik 	/* Host view cable detect 0x4A bit 0 primary bit 1 secondary
101669a5db4SJeff Garzik 	   Bit set for 40 pin */
102669a5db4SJeff Garzik 	pci_read_config_byte(pdev, 0x4A, &ata66);
103669a5db4SJeff Garzik 	if (ata66 & (1 << ap->port_no))
104669a5db4SJeff Garzik 		return ATA_CBL_PATA40;
105669a5db4SJeff Garzik 	else
106669a5db4SJeff Garzik 		return ATA_CBL_PATA80;
107669a5db4SJeff Garzik }
108669a5db4SJeff Garzik 
109669a5db4SJeff Garzik /**
110669a5db4SJeff Garzik  *	ali_20_filter		-	filter for earlier ALI DMA
111325fe208SLee Jones  *	@adev: ATA device
112764e3bc4SLee Jones  *	@mask: received mask to manipulate and pass back
113669a5db4SJeff Garzik  *
114669a5db4SJeff Garzik  *	Ensure that we do not do DMA on CD devices. We may be able to
115669a5db4SJeff Garzik  *	fix that later on. Also ensure we do not do UDMA on WDC drives
116669a5db4SJeff Garzik  */
117669a5db4SJeff Garzik 
ali_20_filter(struct ata_device * adev,unsigned int mask)118f0a6d77bSSergey Shtylyov static unsigned int ali_20_filter(struct ata_device *adev, unsigned int mask)
119669a5db4SJeff Garzik {
1208bfa79fcSTejun Heo 	char model_num[ATA_ID_PROD_LEN + 1];
121669a5db4SJeff Garzik 	/* No DMA on anything but a disk for now */
122669a5db4SJeff Garzik 	if (adev->class != ATA_DEV_ATA)
123669a5db4SJeff Garzik 		mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
1248bfa79fcSTejun Heo 	ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
125669a5db4SJeff Garzik 	if (strstr(model_num, "WDC"))
126237fe888SColin Ian King 		mask &= ~ATA_MASK_UDMA;
127c7087652STejun Heo 	return mask;
128669a5db4SJeff Garzik }
129669a5db4SJeff Garzik 
130669a5db4SJeff Garzik /**
131669a5db4SJeff Garzik  *	ali_fifo_control	-	FIFO manager
132669a5db4SJeff Garzik  *	@ap: ALi channel to control
133669a5db4SJeff Garzik  *	@adev: device for FIFO control
134669a5db4SJeff Garzik  *	@on: 0 for off 1 for on
135669a5db4SJeff Garzik  *
136669a5db4SJeff Garzik  *	Enable or disable the FIFO on a given device. Because of the way the
137669a5db4SJeff Garzik  *	ALi FIFO works it provides a boost on ATA disk but can be confused by
138669a5db4SJeff Garzik  *	ATAPI and we must therefore manage it.
139669a5db4SJeff Garzik  */
140669a5db4SJeff Garzik 
ali_fifo_control(struct ata_port * ap,struct ata_device * adev,int on)141669a5db4SJeff Garzik static void ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int on)
142669a5db4SJeff Garzik {
143669a5db4SJeff Garzik 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
144669a5db4SJeff Garzik 	int pio_fifo = 0x54 + ap->port_no;
145669a5db4SJeff Garzik 	u8 fifo;
146669a5db4SJeff Garzik 	int shift = 4 * adev->devno;
147669a5db4SJeff Garzik 
148669a5db4SJeff Garzik 	/* ATA - FIFO on set nibble to 0x05, ATAPI - FIFO off, set nibble to
149669a5db4SJeff Garzik 	   0x00. Not all the docs agree but the behaviour we now use is the
150669a5db4SJeff Garzik 	   one stated in the BIOS Programming Guide */
151669a5db4SJeff Garzik 
152669a5db4SJeff Garzik 	pci_read_config_byte(pdev, pio_fifo, &fifo);
153669a5db4SJeff Garzik 	fifo &= ~(0x0F << shift);
154669a5db4SJeff Garzik 	fifo |= (on << shift);
155669a5db4SJeff Garzik 	pci_write_config_byte(pdev, pio_fifo, fifo);
156669a5db4SJeff Garzik }
157669a5db4SJeff Garzik 
158669a5db4SJeff Garzik /**
159669a5db4SJeff Garzik  *	ali_program_modes	-	load mode registers
160669a5db4SJeff Garzik  *	@ap: ALi channel to load
161669a5db4SJeff Garzik  *	@adev: Device the timing is for
162d8b3d8cfSBartlomiej Zolnierkiewicz  *	@t: timing data
163669a5db4SJeff Garzik  *	@ultra: UDMA timing or zero for off
164669a5db4SJeff Garzik  *
165669a5db4SJeff Garzik  *	Loads the timing registers for cmd/data and disable UDMA if
166669a5db4SJeff Garzik  *	ultra is zero. If ultra is set then load and enable the UDMA
167669a5db4SJeff Garzik  *	timing but do not touch the command/data timing.
168669a5db4SJeff Garzik  */
169669a5db4SJeff Garzik 
ali_program_modes(struct ata_port * ap,struct ata_device * adev,struct ata_timing * t,u8 ultra)170669a5db4SJeff Garzik static void ali_program_modes(struct ata_port *ap, struct ata_device *adev, struct ata_timing *t, u8 ultra)
171669a5db4SJeff Garzik {
172669a5db4SJeff Garzik 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
173669a5db4SJeff Garzik 	int cas = 0x58 + 4 * ap->port_no;	/* Command timing */
174669a5db4SJeff Garzik 	int cbt = 0x59 + 4 * ap->port_no;	/* Command timing */
175669a5db4SJeff Garzik 	int drwt = 0x5A + 4 * ap->port_no + adev->devno; /* R/W timing */
176669a5db4SJeff Garzik 	int udmat = 0x56 + ap->port_no;	/* UDMA timing */
177669a5db4SJeff Garzik 	int shift = 4 * adev->devno;
178669a5db4SJeff Garzik 	u8 udma;
179669a5db4SJeff Garzik 
180669a5db4SJeff Garzik 	if (t != NULL) {
18107633b5dSHarvey Harrison 		t->setup = clamp_val(t->setup, 1, 8) & 7;
18207633b5dSHarvey Harrison 		t->act8b = clamp_val(t->act8b, 1, 8) & 7;
18307633b5dSHarvey Harrison 		t->rec8b = clamp_val(t->rec8b, 1, 16) & 15;
18407633b5dSHarvey Harrison 		t->active = clamp_val(t->active, 1, 8) & 7;
18507633b5dSHarvey Harrison 		t->recover = clamp_val(t->recover, 1, 16) & 15;
186669a5db4SJeff Garzik 
187669a5db4SJeff Garzik 		pci_write_config_byte(pdev, cas, t->setup);
188669a5db4SJeff Garzik 		pci_write_config_byte(pdev, cbt, (t->act8b << 4) | t->rec8b);
189669a5db4SJeff Garzik 		pci_write_config_byte(pdev, drwt, (t->active << 4) | t->recover);
190669a5db4SJeff Garzik 	}
191669a5db4SJeff Garzik 
192669a5db4SJeff Garzik 	/* Set up the UDMA enable */
193669a5db4SJeff Garzik 	pci_read_config_byte(pdev, udmat, &udma);
194669a5db4SJeff Garzik 	udma &= ~(0x0F << shift);
195669a5db4SJeff Garzik 	udma |= ultra << shift;
196669a5db4SJeff Garzik 	pci_write_config_byte(pdev, udmat, udma);
197669a5db4SJeff Garzik }
198669a5db4SJeff Garzik 
199669a5db4SJeff Garzik /**
200669a5db4SJeff Garzik  *	ali_set_piomode	-	set initial PIO mode data
201669a5db4SJeff Garzik  *	@ap: ATA interface
202669a5db4SJeff Garzik  *	@adev: ATA device
203669a5db4SJeff Garzik  *
204d8b3d8cfSBartlomiej Zolnierkiewicz  *	Program the ALi registers for PIO mode.
205669a5db4SJeff Garzik  */
206669a5db4SJeff Garzik 
ali_set_piomode(struct ata_port * ap,struct ata_device * adev)207669a5db4SJeff Garzik static void ali_set_piomode(struct ata_port *ap, struct ata_device *adev)
208669a5db4SJeff Garzik {
209669a5db4SJeff Garzik 	struct ata_device *pair = ata_dev_pair(adev);
210669a5db4SJeff Garzik 	struct ata_timing t;
211669a5db4SJeff Garzik 	unsigned long T =  1000000000 / 33333;	/* PCI clock based */
212669a5db4SJeff Garzik 
213669a5db4SJeff Garzik 	ata_timing_compute(adev, adev->pio_mode, &t, T, 1);
214669a5db4SJeff Garzik 	if (pair) {
215669a5db4SJeff Garzik 		struct ata_timing p;
216669a5db4SJeff Garzik 		ata_timing_compute(pair, pair->pio_mode, &p, T, 1);
217669a5db4SJeff Garzik 		ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
21847b32049SReimar Döffinger 		if (ata_dma_enabled(pair)) {
219669a5db4SJeff Garzik 			ata_timing_compute(pair, pair->dma_mode, &p, T, 1);
220669a5db4SJeff Garzik 			ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
221669a5db4SJeff Garzik 		}
222669a5db4SJeff Garzik 	}
223669a5db4SJeff Garzik 
224669a5db4SJeff Garzik 	/* PIO FIFO is only permitted on ATA disk */
225669a5db4SJeff Garzik 	if (adev->class != ATA_DEV_ATA)
226669a5db4SJeff Garzik 		ali_fifo_control(ap, adev, 0x00);
227669a5db4SJeff Garzik 	ali_program_modes(ap, adev, &t, 0);
228669a5db4SJeff Garzik 	if (adev->class == ATA_DEV_ATA)
229669a5db4SJeff Garzik 		ali_fifo_control(ap, adev, 0x05);
230669a5db4SJeff Garzik 
231669a5db4SJeff Garzik }
232669a5db4SJeff Garzik 
233669a5db4SJeff Garzik /**
234669a5db4SJeff Garzik  *	ali_set_dmamode	-	set initial DMA mode data
235669a5db4SJeff Garzik  *	@ap: ATA interface
236669a5db4SJeff Garzik  *	@adev: ATA device
237669a5db4SJeff Garzik  *
238d8b3d8cfSBartlomiej Zolnierkiewicz  *	Program the ALi registers for DMA mode.
239669a5db4SJeff Garzik  */
240669a5db4SJeff Garzik 
ali_set_dmamode(struct ata_port * ap,struct ata_device * adev)241669a5db4SJeff Garzik static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev)
242669a5db4SJeff Garzik {
243669a5db4SJeff Garzik 	static u8 udma_timing[7] = { 0xC, 0xB, 0xA, 0x9, 0x8, 0xF, 0xD };
244669a5db4SJeff Garzik 	struct ata_device *pair = ata_dev_pair(adev);
245669a5db4SJeff Garzik 	struct ata_timing t;
246669a5db4SJeff Garzik 	unsigned long T =  1000000000 / 33333;	/* PCI clock based */
247669a5db4SJeff Garzik 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
248669a5db4SJeff Garzik 
249669a5db4SJeff Garzik 
250669a5db4SJeff Garzik 	if (adev->class == ATA_DEV_ATA)
251669a5db4SJeff Garzik 		ali_fifo_control(ap, adev, 0x08);
252669a5db4SJeff Garzik 
253669a5db4SJeff Garzik 	if (adev->dma_mode >= XFER_UDMA_0) {
254669a5db4SJeff Garzik 		ali_program_modes(ap, adev, NULL, udma_timing[adev->dma_mode - XFER_UDMA_0]);
255669a5db4SJeff Garzik 		if (adev->dma_mode >= XFER_UDMA_3) {
256669a5db4SJeff Garzik 			u8 reg4b;
257669a5db4SJeff Garzik 			pci_read_config_byte(pdev, 0x4B, &reg4b);
258669a5db4SJeff Garzik 			reg4b |= 1;
259669a5db4SJeff Garzik 			pci_write_config_byte(pdev, 0x4B, reg4b);
260669a5db4SJeff Garzik 		}
261669a5db4SJeff Garzik 	} else {
262669a5db4SJeff Garzik 		ata_timing_compute(adev, adev->dma_mode, &t, T, 1);
263669a5db4SJeff Garzik 		if (pair) {
264669a5db4SJeff Garzik 			struct ata_timing p;
265669a5db4SJeff Garzik 			ata_timing_compute(pair, pair->pio_mode, &p, T, 1);
266669a5db4SJeff Garzik 			ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
26747b32049SReimar Döffinger 			if (ata_dma_enabled(pair)) {
268669a5db4SJeff Garzik 				ata_timing_compute(pair, pair->dma_mode, &p, T, 1);
269669a5db4SJeff Garzik 				ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
270669a5db4SJeff Garzik 			}
271669a5db4SJeff Garzik 		}
272669a5db4SJeff Garzik 		ali_program_modes(ap, adev, &t, 0);
273669a5db4SJeff Garzik 	}
274669a5db4SJeff Garzik }
275669a5db4SJeff Garzik 
276669a5db4SJeff Garzik /**
2778243e636STejun Heo  *	ali_warn_atapi_dma	-	Warn about ATAPI DMA disablement
2788243e636STejun Heo  *	@adev: Device
2798243e636STejun Heo  *
2808243e636STejun Heo  *	Whine about ATAPI DMA disablement if @adev is an ATAPI device.
2818243e636STejun Heo  *	Can be used as ->dev_config.
2828243e636STejun Heo  */
2838243e636STejun Heo 
ali_warn_atapi_dma(struct ata_device * adev)2848243e636STejun Heo static void ali_warn_atapi_dma(struct ata_device *adev)
2858243e636STejun Heo {
2868243e636STejun Heo 	struct ata_eh_context *ehc = &adev->link->eh_context;
2878243e636STejun Heo 	int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
2888243e636STejun Heo 
2898243e636STejun Heo 	if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
290a9a79dfeSJoe Perches 		ata_dev_warn(adev,
291c21c8066SDirk Hohndel 			     "WARNING: ATAPI DMA disabled for reliability issues.  It can be enabled\n");
292a9a79dfeSJoe Perches 		ata_dev_warn(adev,
2938243e636STejun Heo 			     "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
2948243e636STejun Heo 	}
2958243e636STejun Heo }
2968243e636STejun Heo 
2978243e636STejun Heo /**
298669a5db4SJeff Garzik  *	ali_lock_sectors	-	Keep older devices to 255 sector mode
299669a5db4SJeff Garzik  *	@adev: Device
300669a5db4SJeff Garzik  *
301669a5db4SJeff Garzik  *	Called during the bus probe for each device that is found. We use
302669a5db4SJeff Garzik  *	this call to lock the sector count of the device to 255 or less on
303669a5db4SJeff Garzik  *	older ALi controllers. If we didn't do this then large I/O's would
304669a5db4SJeff Garzik  *	require LBA48 commands which the older ALi requires are issued by
305669a5db4SJeff Garzik  *	slower PIO methods
306669a5db4SJeff Garzik  */
307669a5db4SJeff Garzik 
ali_lock_sectors(struct ata_device * adev)308cd0d3bbcSAlan static void ali_lock_sectors(struct ata_device *adev)
309669a5db4SJeff Garzik {
310669a5db4SJeff Garzik 	adev->max_sectors = 255;
3118243e636STejun Heo 	ali_warn_atapi_dma(adev);
312669a5db4SJeff Garzik }
313669a5db4SJeff Garzik 
314498222f3SAlan Cox /**
315498222f3SAlan Cox  *	ali_check_atapi_dma	-	DMA check for most ALi controllers
316325fe208SLee Jones  *	@qc: Command to complete
317498222f3SAlan Cox  *
318498222f3SAlan Cox  *	Called to decide whether commands should be sent by DMA or PIO
319498222f3SAlan Cox  */
320498222f3SAlan Cox 
ali_check_atapi_dma(struct ata_queued_cmd * qc)321498222f3SAlan Cox static int ali_check_atapi_dma(struct ata_queued_cmd *qc)
322498222f3SAlan Cox {
3238243e636STejun Heo 	if (!ali_atapi_dma) {
3248243e636STejun Heo 		/* FIXME: pata_ali can't do ATAPI DMA reliably but the
3258243e636STejun Heo 		 * IDE alim15x3 driver can.  I tried lots of things
3268243e636STejun Heo 		 * but couldn't find what the actual difference was.
3278243e636STejun Heo 		 * If you got an idea, please write it to
3288243e636STejun Heo 		 * linux-ide@vger.kernel.org and cc htejun@gmail.com.
3298243e636STejun Heo 		 *
3308243e636STejun Heo 		 * Disable ATAPI DMA for now.
3318243e636STejun Heo 		 */
3328243e636STejun Heo 		return -EOPNOTSUPP;
3338243e636STejun Heo 	}
3348243e636STejun Heo 
335498222f3SAlan Cox 	/* If its not a media command, its not worth it */
3364a38e733STejun Heo 	if (atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC)
337498222f3SAlan Cox 		return -EOPNOTSUPP;
338498222f3SAlan Cox 	return 0;
339498222f3SAlan Cox }
340498222f3SAlan Cox 
ali_c2_c3_postreset(struct ata_link * link,unsigned int * classes)341fc80902fSAlan Cox static void ali_c2_c3_postreset(struct ata_link *link, unsigned int *classes)
342fc80902fSAlan Cox {
343fc80902fSAlan Cox 	u8 r;
344fc80902fSAlan Cox 	int port_bit = 4 << link->ap->port_no;
345fc80902fSAlan Cox 
346fc80902fSAlan Cox 	/* If our bridge is an ALI 1533 then do the extra work */
347bc42b24eSAndrew Morton 	if (ali_isa_bridge) {
348fc80902fSAlan Cox 		/* Tristate and re-enable the bus signals */
349bc42b24eSAndrew Morton 		pci_read_config_byte(ali_isa_bridge, 0x58, &r);
350fc80902fSAlan Cox 		r &= ~port_bit;
351bc42b24eSAndrew Morton 		pci_write_config_byte(ali_isa_bridge, 0x58, r);
352fc80902fSAlan Cox 		r |= port_bit;
353bc42b24eSAndrew Morton 		pci_write_config_byte(ali_isa_bridge, 0x58, r);
354fc80902fSAlan Cox 	}
355fc80902fSAlan Cox 	ata_sff_postreset(link, classes);
356fc80902fSAlan Cox }
357fc80902fSAlan Cox 
358*25df73d9SBart Van Assche static const struct scsi_host_template ali_sht = {
35968d1d07bSTejun Heo 	ATA_BMDMA_SHT(DRV_NAME),
360669a5db4SJeff Garzik };
361669a5db4SJeff Garzik 
362669a5db4SJeff Garzik /*
363669a5db4SJeff Garzik  *	Port operations for PIO only ALi
364669a5db4SJeff Garzik  */
365669a5db4SJeff Garzik 
366669a5db4SJeff Garzik static struct ata_port_operations ali_early_port_ops = {
367029cfd6bSTejun Heo 	.inherits	= &ata_sff_port_ops,
368b723d144SAlan Cox 	.cable_detect	= ata_cable_40wire,
369029cfd6bSTejun Heo 	.set_piomode	= ali_set_piomode,
370871af121SAlan Cox 	.sff_data_xfer  = ata_sff_data_xfer32,
371029cfd6bSTejun Heo };
372669a5db4SJeff Garzik 
373029cfd6bSTejun Heo static const struct ata_port_operations ali_dma_base_ops = {
374871af121SAlan Cox 	.inherits	= &ata_bmdma32_port_ops,
375029cfd6bSTejun Heo 	.set_piomode	= ali_set_piomode,
376029cfd6bSTejun Heo 	.set_dmamode	= ali_set_dmamode,
377669a5db4SJeff Garzik };
378669a5db4SJeff Garzik 
379669a5db4SJeff Garzik /*
380669a5db4SJeff Garzik  *	Port operations for DMA capable ALi without cable
381669a5db4SJeff Garzik  *	detect
382669a5db4SJeff Garzik  */
383669a5db4SJeff Garzik static struct ata_port_operations ali_20_port_ops = {
384029cfd6bSTejun Heo 	.inherits	= &ali_dma_base_ops,
385b723d144SAlan Cox 	.cable_detect	= ata_cable_40wire,
386029cfd6bSTejun Heo 	.mode_filter	= ali_20_filter,
387029cfd6bSTejun Heo 	.check_atapi_dma = ali_check_atapi_dma,
388029cfd6bSTejun Heo 	.dev_config	= ali_lock_sectors,
389669a5db4SJeff Garzik };
390669a5db4SJeff Garzik 
391669a5db4SJeff Garzik /*
392669a5db4SJeff Garzik  *	Port operations for DMA capable ALi with cable detect
393669a5db4SJeff Garzik  */
394669a5db4SJeff Garzik static struct ata_port_operations ali_c2_port_ops = {
395029cfd6bSTejun Heo 	.inherits	= &ali_dma_base_ops,
396498222f3SAlan Cox 	.check_atapi_dma = ali_check_atapi_dma,
397b723d144SAlan Cox 	.cable_detect	= ali_c2_cable_detect,
398029cfd6bSTejun Heo 	.dev_config	= ali_lock_sectors,
399fc80902fSAlan Cox 	.postreset	= ali_c2_c3_postreset,
400fc80902fSAlan Cox };
401fc80902fSAlan Cox 
402fc80902fSAlan Cox /*
403fc80902fSAlan Cox  *	Port operations for DMA capable ALi with cable detect
404fc80902fSAlan Cox  */
405fc80902fSAlan Cox static struct ata_port_operations ali_c4_port_ops = {
406fc80902fSAlan Cox 	.inherits	= &ali_dma_base_ops,
407fc80902fSAlan Cox 	.check_atapi_dma = ali_check_atapi_dma,
408fc80902fSAlan Cox 	.cable_detect	= ali_c2_cable_detect,
409fc80902fSAlan Cox 	.dev_config	= ali_lock_sectors,
410669a5db4SJeff Garzik };
411669a5db4SJeff Garzik 
412669a5db4SJeff Garzik /*
413669a5db4SJeff Garzik  *	Port operations for DMA capable ALi with cable detect and LBA48
414669a5db4SJeff Garzik  */
415669a5db4SJeff Garzik static struct ata_port_operations ali_c5_port_ops = {
416029cfd6bSTejun Heo 	.inherits	= &ali_dma_base_ops,
417498222f3SAlan Cox 	.check_atapi_dma = ali_check_atapi_dma,
4188243e636STejun Heo 	.dev_config	= ali_warn_atapi_dma,
419b723d144SAlan Cox 	.cable_detect	= ali_c2_cable_detect,
420669a5db4SJeff Garzik };
421669a5db4SJeff Garzik 
42234d8dfb1SAlan 
42334d8dfb1SAlan /**
42434d8dfb1SAlan  *	ali_init_chipset	-	chip setup function
42534d8dfb1SAlan  *	@pdev: PCI device of ATA controller
42634d8dfb1SAlan  *
42734d8dfb1SAlan  *	Perform the setup on the device that must be done both at boot
42834d8dfb1SAlan  *	and at resume time.
42934d8dfb1SAlan  */
43034d8dfb1SAlan 
ali_init_chipset(struct pci_dev * pdev)43134d8dfb1SAlan static void ali_init_chipset(struct pci_dev *pdev)
43234d8dfb1SAlan {
43344c10138SAuke Kok 	u8 tmp;
4341b2c357cSAlan Cox 	struct pci_dev *north;
43534d8dfb1SAlan 
43634d8dfb1SAlan 	/*
43734d8dfb1SAlan 	 * The chipset revision selects the driver operations and
43834d8dfb1SAlan 	 * mode data.
43934d8dfb1SAlan 	 */
44034d8dfb1SAlan 
4411b2c357cSAlan Cox 	if (pdev->revision <= 0x20) {
4421b2c357cSAlan Cox 		pci_read_config_byte(pdev, 0x53, &tmp);
4431b2c357cSAlan Cox 		tmp |= 0x03;
4441b2c357cSAlan Cox 		pci_write_config_byte(pdev, 0x53, tmp);
4451b2c357cSAlan Cox 	} else {
4461b2c357cSAlan Cox 		pci_read_config_byte(pdev, 0x4a, &tmp);
4471b2c357cSAlan Cox 		pci_write_config_byte(pdev, 0x4a, tmp | 0x20);
44834d8dfb1SAlan 		pci_read_config_byte(pdev, 0x4B, &tmp);
4491b2c357cSAlan Cox 		if (pdev->revision < 0xC2)
4501b2c357cSAlan Cox 			/* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
45134d8dfb1SAlan 			/* Clear CD-ROM DMA write bit */
45234d8dfb1SAlan 			tmp &= 0x7F;
4531b2c357cSAlan Cox 		/* Cable and UDMA */
454d6250a03SAlan Cox 		if (pdev->revision >= 0xc2)
455d6250a03SAlan Cox 			tmp |= 0x01;
456d6250a03SAlan Cox 		pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
4571b2c357cSAlan Cox 		/*
4581b2c357cSAlan Cox 		 * CD_ROM DMA on (0x53 bit 0). Enable this even if we want
4591b2c357cSAlan Cox 		 * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
4601b2c357cSAlan Cox 		 * via 0x54/55.
4611b2c357cSAlan Cox 		 */
4621b2c357cSAlan Cox 		pci_read_config_byte(pdev, 0x53, &tmp);
4631b2c357cSAlan Cox 		if (pdev->revision >= 0xc7)
4641b2c357cSAlan Cox 			tmp |= 0x03;
4651b2c357cSAlan Cox 		else
4661b2c357cSAlan Cox 			tmp |= 0x01;	/* CD_ROM enable for DMA */
4671b2c357cSAlan Cox 		pci_write_config_byte(pdev, 0x53, tmp);
46834d8dfb1SAlan 	}
46978a6b8d8SSinan Kaya 	north = pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), 0,
47078a6b8d8SSinan Kaya 					    PCI_DEVFN(0, 0));
471bc42b24eSAndrew Morton 	if (north && north->vendor == PCI_VENDOR_ID_AL && ali_isa_bridge) {
47234d8dfb1SAlan 		/* Configure the ALi bridge logic. For non ALi rely on BIOS.
47334d8dfb1SAlan 		   Set the south bridge enable bit */
474bc42b24eSAndrew Morton 		pci_read_config_byte(ali_isa_bridge, 0x79, &tmp);
47544c10138SAuke Kok 		if (pdev->revision == 0xC2)
476bc42b24eSAndrew Morton 			pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x04);
47744c10138SAuke Kok 		else if (pdev->revision > 0xC2 && pdev->revision < 0xC5)
478bc42b24eSAndrew Morton 			pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x02);
47934d8dfb1SAlan 	}
48034d8dfb1SAlan 	pci_dev_put(north);
4819363c382STejun Heo 	ata_pci_bmdma_clear_simplex(pdev);
48234d8dfb1SAlan }
483669a5db4SJeff Garzik /**
484669a5db4SJeff Garzik  *	ali_init_one		-	discovery callback
485669a5db4SJeff Garzik  *	@pdev: PCI device ID
486669a5db4SJeff Garzik  *	@id: PCI table info
487669a5db4SJeff Garzik  *
488669a5db4SJeff Garzik  *	An ALi IDE interface has been discovered. Figure out what revision
489669a5db4SJeff Garzik  *	and perform configuration work before handing it to the ATA layer
490669a5db4SJeff Garzik  */
491669a5db4SJeff Garzik 
ali_init_one(struct pci_dev * pdev,const struct pci_device_id * id)492669a5db4SJeff Garzik static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
493669a5db4SJeff Garzik {
4941626aeb8STejun Heo 	static const struct ata_port_info info_early = {
4951d2808fdSJeff Garzik 		.flags = ATA_FLAG_SLAVE_POSS,
49614bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
497669a5db4SJeff Garzik 		.port_ops = &ali_early_port_ops
498669a5db4SJeff Garzik 	};
499669a5db4SJeff Garzik 	/* Revision 0x20 added DMA */
5001626aeb8STejun Heo 	static const struct ata_port_info info_20 = {
501a3cb900cSAlan Cox 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
502a3cb900cSAlan Cox 							ATA_FLAG_IGN_SIMPLEX,
50314bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
50414bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
505669a5db4SJeff Garzik 		.port_ops = &ali_20_port_ops
506669a5db4SJeff Garzik 	};
507669a5db4SJeff Garzik 	/* Revision 0x20 with support logic added UDMA */
5081626aeb8STejun Heo 	static const struct ata_port_info info_20_udma = {
509a3cb900cSAlan Cox 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
510a3cb900cSAlan Cox 							ATA_FLAG_IGN_SIMPLEX,
51114bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
51214bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
51314bdef98SErik Inge Bolsø 		.udma_mask = ATA_UDMA2,
514669a5db4SJeff Garzik 		.port_ops = &ali_20_port_ops
515669a5db4SJeff Garzik 	};
516669a5db4SJeff Garzik 	/* Revision 0xC2 adds UDMA66 */
5171626aeb8STejun Heo 	static const struct ata_port_info info_c2 = {
518a3cb900cSAlan Cox 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
519a3cb900cSAlan Cox 							ATA_FLAG_IGN_SIMPLEX,
52014bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
52114bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
522bf6263a8SJeff Garzik 		.udma_mask = ATA_UDMA4,
523669a5db4SJeff Garzik 		.port_ops = &ali_c2_port_ops
524669a5db4SJeff Garzik 	};
525ee581502SChuck Ebbert 	/* Revision 0xC3 is UDMA66 for now */
5261626aeb8STejun Heo 	static const struct ata_port_info info_c3 = {
527a3cb900cSAlan Cox 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
528a3cb900cSAlan Cox 							ATA_FLAG_IGN_SIMPLEX,
52914bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
53014bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
531bf6263a8SJeff Garzik 		.udma_mask = ATA_UDMA4,
532669a5db4SJeff Garzik 		.port_ops = &ali_c2_port_ops
533669a5db4SJeff Garzik 	};
534ee581502SChuck Ebbert 	/* Revision 0xC4 is UDMA100 */
5351626aeb8STejun Heo 	static const struct ata_port_info info_c4 = {
536a3cb900cSAlan Cox 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
537a3cb900cSAlan Cox 							ATA_FLAG_IGN_SIMPLEX,
53814bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
53914bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
540bf6263a8SJeff Garzik 		.udma_mask = ATA_UDMA5,
541fc80902fSAlan Cox 		.port_ops = &ali_c4_port_ops
542669a5db4SJeff Garzik 	};
543669a5db4SJeff Garzik 	/* Revision 0xC5 is UDMA133 with LBA48 DMA */
5441626aeb8STejun Heo 	static const struct ata_port_info info_c5 = {
545a3cb900cSAlan Cox 		.flags = ATA_FLAG_SLAVE_POSS | 	ATA_FLAG_IGN_SIMPLEX,
54614bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
54714bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
548bf6263a8SJeff Garzik 		.udma_mask = ATA_UDMA6,
549669a5db4SJeff Garzik 		.port_ops = &ali_c5_port_ops
550669a5db4SJeff Garzik 	};
551669a5db4SJeff Garzik 
5521626aeb8STejun Heo 	const struct ata_port_info *ppi[] = { NULL, NULL };
55344c10138SAuke Kok 	u8 tmp;
554f08048e9STejun Heo 	int rc;
555f08048e9STejun Heo 
556f08048e9STejun Heo 	rc = pcim_enable_device(pdev);
557f08048e9STejun Heo 	if (rc)
558f08048e9STejun Heo 		return rc;
559669a5db4SJeff Garzik 
560669a5db4SJeff Garzik 	/*
561669a5db4SJeff Garzik 	 * The chipset revision selects the driver operations and
562669a5db4SJeff Garzik 	 * mode data.
563669a5db4SJeff Garzik 	 */
564669a5db4SJeff Garzik 
56544c10138SAuke Kok 	if (pdev->revision < 0x20) {
5661626aeb8STejun Heo 		ppi[0] = &info_early;
56744c10138SAuke Kok 	} else if (pdev->revision < 0xC2) {
5681626aeb8STejun Heo         	ppi[0] = &info_20;
56944c10138SAuke Kok 	} else if (pdev->revision == 0xC2) {
5701626aeb8STejun Heo         	ppi[0] = &info_c2;
57144c10138SAuke Kok 	} else if (pdev->revision == 0xC3) {
5721626aeb8STejun Heo         	ppi[0] = &info_c3;
57344c10138SAuke Kok 	} else if (pdev->revision == 0xC4) {
5741626aeb8STejun Heo         	ppi[0] = &info_c4;
575669a5db4SJeff Garzik 	} else
5761626aeb8STejun Heo         	ppi[0] = &info_c5;
577669a5db4SJeff Garzik 
57834d8dfb1SAlan 	ali_init_chipset(pdev);
579669a5db4SJeff Garzik 
580bc42b24eSAndrew Morton 	if (ali_isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
581669a5db4SJeff Garzik 		/* Are we paired with a UDMA capable chip */
582bc42b24eSAndrew Morton 		pci_read_config_byte(ali_isa_bridge, 0x5E, &tmp);
583669a5db4SJeff Garzik 		if ((tmp & 0x1E) == 0x12)
5841626aeb8STejun Heo 	        	ppi[0] = &info_20_udma;
58534d8dfb1SAlan 	}
586e8389f0cSBen Dooks 
5871c5afdf7STejun Heo 	if (!ppi[0]->mwdma_mask && !ppi[0]->udma_mask)
58816ea0fc9SAlan Cox 		return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL, 0);
5891c5afdf7STejun Heo 	else
5901c5afdf7STejun Heo 		return ata_pci_bmdma_init_one(pdev, ppi, &ali_sht, NULL, 0);
591669a5db4SJeff Garzik }
592669a5db4SJeff Garzik 
59358eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
ali_reinit_one(struct pci_dev * pdev)59434d8dfb1SAlan static int ali_reinit_one(struct pci_dev *pdev)
59534d8dfb1SAlan {
5960a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
597f08048e9STejun Heo 	int rc;
598f08048e9STejun Heo 
599f08048e9STejun Heo 	rc = ata_pci_device_do_resume(pdev);
600f08048e9STejun Heo 	if (rc)
601f08048e9STejun Heo 		return rc;
60234d8dfb1SAlan 	ali_init_chipset(pdev);
603f08048e9STejun Heo 	ata_host_resume(host);
604f08048e9STejun Heo 	return 0;
60534d8dfb1SAlan }
606438ac6d5STejun Heo #endif
60734d8dfb1SAlan 
6082d2744fcSJeff Garzik static const struct pci_device_id ali[] = {
6092d2744fcSJeff Garzik 	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), },
6102d2744fcSJeff Garzik 	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), },
6112d2744fcSJeff Garzik 
6122d2744fcSJeff Garzik 	{ },
613669a5db4SJeff Garzik };
614669a5db4SJeff Garzik 
615669a5db4SJeff Garzik static struct pci_driver ali_pci_driver = {
616669a5db4SJeff Garzik 	.name 		= DRV_NAME,
617669a5db4SJeff Garzik 	.id_table	= ali,
618669a5db4SJeff Garzik 	.probe 		= ali_init_one,
61934d8dfb1SAlan 	.remove		= ata_pci_remove_one,
62058eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
62134d8dfb1SAlan 	.suspend	= ata_pci_device_suspend,
62234d8dfb1SAlan 	.resume		= ali_reinit_one,
623438ac6d5STejun Heo #endif
624669a5db4SJeff Garzik };
625669a5db4SJeff Garzik 
ali_init(void)626669a5db4SJeff Garzik static int __init ali_init(void)
627669a5db4SJeff Garzik {
6281b2c357cSAlan Cox 	int ret;
629bc42b24eSAndrew Morton 	ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
6301b2c357cSAlan Cox 
6311b2c357cSAlan Cox 	ret = pci_register_driver(&ali_pci_driver);
6321b2c357cSAlan Cox 	if (ret < 0)
633bc42b24eSAndrew Morton 		pci_dev_put(ali_isa_bridge);
6341b2c357cSAlan Cox 	return ret;
635669a5db4SJeff Garzik }
636669a5db4SJeff Garzik 
637669a5db4SJeff Garzik 
ali_exit(void)638669a5db4SJeff Garzik static void __exit ali_exit(void)
639669a5db4SJeff Garzik {
640669a5db4SJeff Garzik 	pci_unregister_driver(&ali_pci_driver);
641bc42b24eSAndrew Morton 	pci_dev_put(ali_isa_bridge);
642669a5db4SJeff Garzik }
643669a5db4SJeff Garzik 
644669a5db4SJeff Garzik 
645669a5db4SJeff Garzik MODULE_AUTHOR("Alan Cox");
646669a5db4SJeff Garzik MODULE_DESCRIPTION("low-level driver for ALi PATA");
647669a5db4SJeff Garzik MODULE_LICENSE("GPL");
648669a5db4SJeff Garzik MODULE_DEVICE_TABLE(pci, ali);
649669a5db4SJeff Garzik MODULE_VERSION(DRV_VERSION);
650669a5db4SJeff Garzik 
651669a5db4SJeff Garzik module_init(ali_init);
652669a5db4SJeff Garzik module_exit(ali_exit);
653