Blame view

drivers/ata/pata_ali.c 17.5 KB
669a5db41   Jeff Garzik   [libata] Add a bu...
1
2
3
  /*
   * pata_ali.c 	- ALI 15x3 PATA for new ATA layer
   *			  (C) 2005 Red Hat Inc
669a5db41   Jeff Garzik   [libata] Add a bu...
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
   *
   * based in part upon
   * linux/drivers/ide/pci/alim15x3.c		Version 0.17	2003/01/02
   *
   *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
   *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
   *  Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer
   *
   *  Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org)
   *  May be copied or modified under the terms of the GNU General Public License
   *  Copyright (C) 2002 Alan Cox <alan@redhat.com>
   *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
   *
   *  Documentation
   *	Chipset documentation available under NDA only
   *
   *  TODO/CHECK
   *	Cannot have ATAPI on both master & slave for rev < c2 (???) but
1b2c357c3   Alan Cox   pata_ali: force i...
22
23
24
   *	otherwise should do atapi DMA (For now for old we do PIO only for
   *	ATAPI)
   *	Review Sunblade workaround.
669a5db41   Jeff Garzik   [libata] Add a bu...
25
26
27
28
29
30
31
32
33
34
35
36
37
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/pci.h>
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <linux/delay.h>
  #include <scsi/scsi_host.h>
  #include <linux/libata.h>
  #include <linux/dmi.h>
  
  #define DRV_NAME "pata_ali"
fc80902fd   Alan Cox   pata_ali: Fix and...
38
  #define DRV_VERSION "0.7.8"
669a5db41   Jeff Garzik   [libata] Add a bu...
39

1892225f7   Adrian Bunk   [libata] make ali...
40
  static int ali_atapi_dma = 0;
8243e636c   Tejun Heo   pata_ali: disable...
41
42
  module_param_named(atapi_dma, ali_atapi_dma, int, 0644);
  MODULE_PARM_DESC(atapi_dma, "Enable ATAPI DMA (0=disable, 1=enable)");
bc42b24e6   Andrew Morton   drivers/ata/pata_...
43
  static struct pci_dev *ali_isa_bridge;
1b2c357c3   Alan Cox   pata_ali: force i...
44

669a5db41   Jeff Garzik   [libata] Add a bu...
45
46
47
  /*
   *	Cable special cases
   */
1855256c4   Jeff Garzik   drivers/firmware:...
48
  static const struct dmi_system_id cable_dmi_table[] = {
669a5db41   Jeff Garzik   [libata] Add a bu...
49
50
51
52
  	{
  		.ident = "HP Pavilion N5430",
  		.matches = {
  			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
5c8d52015   Alan Cox   pata_ali: Correct...
53
  			DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
669a5db41   Jeff Garzik   [libata] Add a bu...
54
55
  		},
  	},
03e6f489b   Daniel Exner   pata_ali/alim15x3...
56
  	{
802872e7d   Bartlomiej Zolnierkiewicz   pata_ali: fix "Sa...
57
  		.ident = "Toshiba Satellite S1800-814",
03e6f489b   Daniel Exner   pata_ali/alim15x3...
58
59
60
61
62
  		.matches = {
  			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  			DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"),
  		},
  	},
669a5db41   Jeff Garzik   [libata] Add a bu...
63
64
65
66
67
68
69
70
  	{ }
  };
  
  static int ali_cable_override(struct pci_dev *pdev)
  {
  	/* Fujitsu P2000 */
  	if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF)
  	   	return 1;
8f59a13ac   Alan Cox   pata_ali: Add Mit...
71
  	/* Mitac 8317 (Winbook-A) and relatives */
11b7becca   Jeff Garzik   libata: checkpatc...
72
  	if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317)
8f59a13ac   Alan Cox   pata_ali: Add Mit...
73
  		return 1;
669a5db41   Jeff Garzik   [libata] Add a bu...
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  	/* Systems by DMI */
  	if (dmi_check_system(cable_dmi_table))
  		return 1;
  	return 0;
  }
  
  /**
   *	ali_c2_cable_detect	-	cable detection
   *	@ap: ATA port
   *
   *	Perform cable detection for C2 and later revisions
   */
  
  static int ali_c2_cable_detect(struct ata_port *ap)
  {
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
  	u8 ata66;
  
  	/* Certain laptops use short but suitable cables and don't
  	   implement the detect logic */
  
  	if (ali_cable_override(pdev))
fc085150b   Alan Cox   [PATCH] libata: a...
96
  		return ATA_CBL_PATA40_SHORT;
669a5db41   Jeff Garzik   [libata] Add a bu...
97
98
99
100
101
102
103
104
105
106
107
  
  	/* Host view cable detect 0x4A bit 0 primary bit 1 secondary
  	   Bit set for 40 pin */
  	pci_read_config_byte(pdev, 0x4A, &ata66);
  	if (ata66 & (1 << ap->port_no))
  		return ATA_CBL_PATA40;
  	else
  		return ATA_CBL_PATA80;
  }
  
  /**
669a5db41   Jeff Garzik   [libata] Add a bu...
108
109
110
111
112
113
114
   *	ali_20_filter		-	filter for earlier ALI DMA
   *	@ap: ALi ATA port
   *	@adev: attached device
   *
   *	Ensure that we do not do DMA on CD devices. We may be able to
   *	fix that later on. Also ensure we do not do UDMA on WDC drives
   */
a76b62ca7   Alan Cox   libata: Change pr...
115
  static unsigned long ali_20_filter(struct ata_device *adev, unsigned long mask)
669a5db41   Jeff Garzik   [libata] Add a bu...
116
  {
8bfa79fcb   Tejun Heo   libata: use ata_i...
117
  	char model_num[ATA_ID_PROD_LEN + 1];
669a5db41   Jeff Garzik   [libata] Add a bu...
118
119
120
  	/* No DMA on anything but a disk for now */
  	if (adev->class != ATA_DEV_ATA)
  		mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
8bfa79fcb   Tejun Heo   libata: use ata_i...
121
  	ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
669a5db41   Jeff Garzik   [libata] Add a bu...
122
123
  	if (strstr(model_num, "WDC"))
  		return mask &= ~ATA_MASK_UDMA;
c7087652e   Tejun Heo   libata-sff: clean...
124
  	return mask;
669a5db41   Jeff Garzik   [libata] Add a bu...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  }
  
  /**
   *	ali_fifo_control	-	FIFO manager
   *	@ap: ALi channel to control
   *	@adev: device for FIFO control
   *	@on: 0 for off 1 for on
   *
   *	Enable or disable the FIFO on a given device. Because of the way the
   *	ALi FIFO works it provides a boost on ATA disk but can be confused by
   *	ATAPI and we must therefore manage it.
   */
  
  static void ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int on)
  {
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
  	int pio_fifo = 0x54 + ap->port_no;
  	u8 fifo;
  	int shift = 4 * adev->devno;
  
  	/* ATA - FIFO on set nibble to 0x05, ATAPI - FIFO off, set nibble to
  	   0x00. Not all the docs agree but the behaviour we now use is the
  	   one stated in the BIOS Programming Guide */
85cd7251b   Jeff Garzik   [libata #pata-dri...
148

669a5db41   Jeff Garzik   [libata] Add a bu...
149
150
  	pci_read_config_byte(pdev, pio_fifo, &fifo);
  	fifo &= ~(0x0F << shift);
871af1210   Alan Cox   libata: Add 32bit...
151
  	fifo |= (on << shift);
669a5db41   Jeff Garzik   [libata] Add a bu...
152
153
154
155
156
157
158
  	pci_write_config_byte(pdev, pio_fifo, fifo);
  }
  
  /**
   *	ali_program_modes	-	load mode registers
   *	@ap: ALi channel to load
   *	@adev: Device the timing is for
d8b3d8cfe   Bartlomiej Zolnierkiewicz   pata_ali: documen...
159
   *	@t: timing data
669a5db41   Jeff Garzik   [libata] Add a bu...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
   *	@ultra: UDMA timing or zero for off
   *
   *	Loads the timing registers for cmd/data and disable UDMA if
   *	ultra is zero. If ultra is set then load and enable the UDMA
   *	timing but do not touch the command/data timing.
   */
  
  static void ali_program_modes(struct ata_port *ap, struct ata_device *adev, struct ata_timing *t, u8 ultra)
  {
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
  	int cas = 0x58 + 4 * ap->port_no;	/* Command timing */
  	int cbt = 0x59 + 4 * ap->port_no;	/* Command timing */
  	int drwt = 0x5A + 4 * ap->port_no + adev->devno; /* R/W timing */
  	int udmat = 0x56 + ap->port_no;	/* UDMA timing */
  	int shift = 4 * adev->devno;
  	u8 udma;
  
  	if (t != NULL) {
07633b5d0   Harvey Harrison   ata: remove FIT()...
178
179
180
181
182
  		t->setup = clamp_val(t->setup, 1, 8) & 7;
  		t->act8b = clamp_val(t->act8b, 1, 8) & 7;
  		t->rec8b = clamp_val(t->rec8b, 1, 16) & 15;
  		t->active = clamp_val(t->active, 1, 8) & 7;
  		t->recover = clamp_val(t->recover, 1, 16) & 15;
669a5db41   Jeff Garzik   [libata] Add a bu...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
  
  		pci_write_config_byte(pdev, cas, t->setup);
  		pci_write_config_byte(pdev, cbt, (t->act8b << 4) | t->rec8b);
  		pci_write_config_byte(pdev, drwt, (t->active << 4) | t->recover);
  	}
  
  	/* Set up the UDMA enable */
  	pci_read_config_byte(pdev, udmat, &udma);
  	udma &= ~(0x0F << shift);
  	udma |= ultra << shift;
  	pci_write_config_byte(pdev, udmat, udma);
  }
  
  /**
   *	ali_set_piomode	-	set initial PIO mode data
   *	@ap: ATA interface
   *	@adev: ATA device
   *
d8b3d8cfe   Bartlomiej Zolnierkiewicz   pata_ali: documen...
201
   *	Program the ALi registers for PIO mode.
669a5db41   Jeff Garzik   [libata] Add a bu...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
   */
  
  static void ali_set_piomode(struct ata_port *ap, struct ata_device *adev)
  {
  	struct ata_device *pair = ata_dev_pair(adev);
  	struct ata_timing t;
  	unsigned long T =  1000000000 / 33333;	/* PCI clock based */
  
  	ata_timing_compute(adev, adev->pio_mode, &t, T, 1);
  	if (pair) {
  		struct ata_timing p;
  		ata_timing_compute(pair, pair->pio_mode, &p, T, 1);
  		ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
  		if (pair->dma_mode) {
  			ata_timing_compute(pair, pair->dma_mode, &p, T, 1);
  			ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
  		}
  	}
  
  	/* PIO FIFO is only permitted on ATA disk */
  	if (adev->class != ATA_DEV_ATA)
  		ali_fifo_control(ap, adev, 0x00);
  	ali_program_modes(ap, adev, &t, 0);
  	if (adev->class == ATA_DEV_ATA)
  		ali_fifo_control(ap, adev, 0x05);
  
  }
  
  /**
   *	ali_set_dmamode	-	set initial DMA mode data
   *	@ap: ATA interface
   *	@adev: ATA device
   *
d8b3d8cfe   Bartlomiej Zolnierkiewicz   pata_ali: documen...
235
   *	Program the ALi registers for DMA mode.
669a5db41   Jeff Garzik   [libata] Add a bu...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
   */
  
  static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev)
  {
  	static u8 udma_timing[7] = { 0xC, 0xB, 0xA, 0x9, 0x8, 0xF, 0xD };
  	struct ata_device *pair = ata_dev_pair(adev);
  	struct ata_timing t;
  	unsigned long T =  1000000000 / 33333;	/* PCI clock based */
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
  
  
  	if (adev->class == ATA_DEV_ATA)
  		ali_fifo_control(ap, adev, 0x08);
  
  	if (adev->dma_mode >= XFER_UDMA_0) {
  		ali_program_modes(ap, adev, NULL, udma_timing[adev->dma_mode - XFER_UDMA_0]);
  		if (adev->dma_mode >= XFER_UDMA_3) {
  			u8 reg4b;
  			pci_read_config_byte(pdev, 0x4B, &reg4b);
  			reg4b |= 1;
  			pci_write_config_byte(pdev, 0x4B, reg4b);
  		}
  	} else {
  		ata_timing_compute(adev, adev->dma_mode, &t, T, 1);
  		if (pair) {
  			struct ata_timing p;
  			ata_timing_compute(pair, pair->pio_mode, &p, T, 1);
  			ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
  			if (pair->dma_mode) {
  				ata_timing_compute(pair, pair->dma_mode, &p, T, 1);
  				ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
  			}
  		}
  		ali_program_modes(ap, adev, &t, 0);
  	}
  }
  
  /**
8243e636c   Tejun Heo   pata_ali: disable...
274
275
276
277
278
279
280
281
282
283
284
285
286
   *	ali_warn_atapi_dma	-	Warn about ATAPI DMA disablement
   *	@adev: Device
   *
   *	Whine about ATAPI DMA disablement if @adev is an ATAPI device.
   *	Can be used as ->dev_config.
   */
  
  static void ali_warn_atapi_dma(struct ata_device *adev)
  {
  	struct ata_eh_context *ehc = &adev->link->eh_context;
  	int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
  
  	if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
a9a79dfec   Joe Perches   ata: Convert ata_...
287
288
289
290
291
292
  		ata_dev_warn(adev,
  			     "WARNING: ATAPI DMA disabled for reliability issues.  It can be enabled
  ");
  		ata_dev_warn(adev,
  			     "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.
  ");
8243e636c   Tejun Heo   pata_ali: disable...
293
294
295
296
  	}
  }
  
  /**
669a5db41   Jeff Garzik   [libata] Add a bu...
297
   *	ali_lock_sectors	-	Keep older devices to 255 sector mode
669a5db41   Jeff Garzik   [libata] Add a bu...
298
299
300
301
302
303
304
305
   *	@adev: Device
   *
   *	Called during the bus probe for each device that is found. We use
   *	this call to lock the sector count of the device to 255 or less on
   *	older ALi controllers. If we didn't do this then large I/O's would
   *	require LBA48 commands which the older ALi requires are issued by
   *	slower PIO methods
   */
cd0d3bbcd   Alan Cox   libata: dev_confi...
306
  static void ali_lock_sectors(struct ata_device *adev)
669a5db41   Jeff Garzik   [libata] Add a bu...
307
308
  {
  	adev->max_sectors = 255;
8243e636c   Tejun Heo   pata_ali: disable...
309
  	ali_warn_atapi_dma(adev);
669a5db41   Jeff Garzik   [libata] Add a bu...
310
  }
498222f32   Alan Cox   pata_ali: Lots of...
311
312
313
314
315
316
  /**
   *	ali_check_atapi_dma	-	DMA check for most ALi controllers
   *	@adev: Device
   *
   *	Called to decide whether commands should be sent by DMA or PIO
   */
2541d0ca7   Jeff Garzik   pata_ali: trim tr...
317

498222f32   Alan Cox   pata_ali: Lots of...
318
319
  static int ali_check_atapi_dma(struct ata_queued_cmd *qc)
  {
8243e636c   Tejun Heo   pata_ali: disable...
320
321
322
323
324
325
326
327
328
329
330
  	if (!ali_atapi_dma) {
  		/* FIXME: pata_ali can't do ATAPI DMA reliably but the
  		 * IDE alim15x3 driver can.  I tried lots of things
  		 * but couldn't find what the actual difference was.
  		 * If you got an idea, please write it to
  		 * linux-ide@vger.kernel.org and cc htejun@gmail.com.
  		 *
  		 * Disable ATAPI DMA for now.
  		 */
  		return -EOPNOTSUPP;
  	}
498222f32   Alan Cox   pata_ali: Lots of...
331
  	/* If its not a media command, its not worth it */
4a38e733a   Tejun Heo   pata_ali: use ata...
332
  	if (atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC)
498222f32   Alan Cox   pata_ali: Lots of...
333
334
335
  		return -EOPNOTSUPP;
  	return 0;
  }
fc80902fd   Alan Cox   pata_ali: Fix and...
336
337
338
339
340
341
  static void ali_c2_c3_postreset(struct ata_link *link, unsigned int *classes)
  {
  	u8 r;
  	int port_bit = 4 << link->ap->port_no;
  
  	/* If our bridge is an ALI 1533 then do the extra work */
bc42b24e6   Andrew Morton   drivers/ata/pata_...
342
  	if (ali_isa_bridge) {
fc80902fd   Alan Cox   pata_ali: Fix and...
343
  		/* Tristate and re-enable the bus signals */
bc42b24e6   Andrew Morton   drivers/ata/pata_...
344
  		pci_read_config_byte(ali_isa_bridge, 0x58, &r);
fc80902fd   Alan Cox   pata_ali: Fix and...
345
  		r &= ~port_bit;
bc42b24e6   Andrew Morton   drivers/ata/pata_...
346
  		pci_write_config_byte(ali_isa_bridge, 0x58, r);
fc80902fd   Alan Cox   pata_ali: Fix and...
347
  		r |= port_bit;
bc42b24e6   Andrew Morton   drivers/ata/pata_...
348
  		pci_write_config_byte(ali_isa_bridge, 0x58, r);
fc80902fd   Alan Cox   pata_ali: Fix and...
349
350
351
  	}
  	ata_sff_postreset(link, classes);
  }
669a5db41   Jeff Garzik   [libata] Add a bu...
352
  static struct scsi_host_template ali_sht = {
68d1d07b5   Tejun Heo   libata: implement...
353
  	ATA_BMDMA_SHT(DRV_NAME),
669a5db41   Jeff Garzik   [libata] Add a bu...
354
355
356
357
358
359
360
  };
  
  /*
   *	Port operations for PIO only ALi
   */
  
  static struct ata_port_operations ali_early_port_ops = {
029cfd6b7   Tejun Heo   libata: implement...
361
  	.inherits	= &ata_sff_port_ops,
b723d1448   Alan Cox   pata_ali: remove ...
362
  	.cable_detect	= ata_cable_40wire,
029cfd6b7   Tejun Heo   libata: implement...
363
  	.set_piomode	= ali_set_piomode,
871af1210   Alan Cox   libata: Add 32bit...
364
  	.sff_data_xfer  = ata_sff_data_xfer32,
029cfd6b7   Tejun Heo   libata: implement...
365
  };
669a5db41   Jeff Garzik   [libata] Add a bu...
366

029cfd6b7   Tejun Heo   libata: implement...
367
  static const struct ata_port_operations ali_dma_base_ops = {
871af1210   Alan Cox   libata: Add 32bit...
368
  	.inherits	= &ata_bmdma32_port_ops,
029cfd6b7   Tejun Heo   libata: implement...
369
370
  	.set_piomode	= ali_set_piomode,
  	.set_dmamode	= ali_set_dmamode,
669a5db41   Jeff Garzik   [libata] Add a bu...
371
372
373
374
375
376
377
  };
  
  /*
   *	Port operations for DMA capable ALi without cable
   *	detect
   */
  static struct ata_port_operations ali_20_port_ops = {
029cfd6b7   Tejun Heo   libata: implement...
378
379
  	.inherits	= &ali_dma_base_ops,
  	.cable_detect	= ata_cable_40wire,
669a5db41   Jeff Garzik   [libata] Add a bu...
380
  	.mode_filter	= ali_20_filter,
8243e636c   Tejun Heo   pata_ali: disable...
381
  	.check_atapi_dma = ali_check_atapi_dma,
669a5db41   Jeff Garzik   [libata] Add a bu...
382
  	.dev_config	= ali_lock_sectors,
669a5db41   Jeff Garzik   [libata] Add a bu...
383
384
385
386
387
388
  };
  
  /*
   *	Port operations for DMA capable ALi with cable detect
   */
  static struct ata_port_operations ali_c2_port_ops = {
029cfd6b7   Tejun Heo   libata: implement...
389
  	.inherits	= &ali_dma_base_ops,
498222f32   Alan Cox   pata_ali: Lots of...
390
  	.check_atapi_dma = ali_check_atapi_dma,
b723d1448   Alan Cox   pata_ali: remove ...
391
  	.cable_detect	= ali_c2_cable_detect,
029cfd6b7   Tejun Heo   libata: implement...
392
  	.dev_config	= ali_lock_sectors,
fc80902fd   Alan Cox   pata_ali: Fix and...
393
394
395
396
397
398
399
400
401
402
403
  	.postreset	= ali_c2_c3_postreset,
  };
  
  /*
   *	Port operations for DMA capable ALi with cable detect
   */
  static struct ata_port_operations ali_c4_port_ops = {
  	.inherits	= &ali_dma_base_ops,
  	.check_atapi_dma = ali_check_atapi_dma,
  	.cable_detect	= ali_c2_cable_detect,
  	.dev_config	= ali_lock_sectors,
669a5db41   Jeff Garzik   [libata] Add a bu...
404
405
406
407
408
409
  };
  
  /*
   *	Port operations for DMA capable ALi with cable detect and LBA48
   */
  static struct ata_port_operations ali_c5_port_ops = {
029cfd6b7   Tejun Heo   libata: implement...
410
  	.inherits	= &ali_dma_base_ops,
498222f32   Alan Cox   pata_ali: Lots of...
411
  	.check_atapi_dma = ali_check_atapi_dma,
8243e636c   Tejun Heo   pata_ali: disable...
412
  	.dev_config	= ali_warn_atapi_dma,
b723d1448   Alan Cox   pata_ali: remove ...
413
  	.cable_detect	= ali_c2_cable_detect,
669a5db41   Jeff Garzik   [libata] Add a bu...
414
  };
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
415
416
417
418
419
420
421
422
  
  /**
   *	ali_init_chipset	-	chip setup function
   *	@pdev: PCI device of ATA controller
   *
   *	Perform the setup on the device that must be done both at boot
   *	and at resume time.
   */
f20b16ff7   Jeff Garzik   [libata] trim tra...
423

34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
424
425
  static void ali_init_chipset(struct pci_dev *pdev)
  {
44c10138f   Auke Kok   PCI: Change all d...
426
  	u8 tmp;
1b2c357c3   Alan Cox   pata_ali: force i...
427
  	struct pci_dev *north;
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
428

34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
429
430
431
432
  	/*
  	 * The chipset revision selects the driver operations and
  	 * mode data.
  	 */
1b2c357c3   Alan Cox   pata_ali: force i...
433
434
435
436
437
438
439
  	if (pdev->revision <= 0x20) {
  		pci_read_config_byte(pdev, 0x53, &tmp);
  		tmp |= 0x03;
  		pci_write_config_byte(pdev, 0x53, tmp);
  	} else {
  		pci_read_config_byte(pdev, 0x4a, &tmp);
  		pci_write_config_byte(pdev, 0x4a, tmp | 0x20);
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
440
  		pci_read_config_byte(pdev, 0x4B, &tmp);
1b2c357c3   Alan Cox   pata_ali: force i...
441
442
443
444
445
  		if (pdev->revision < 0xC2)
  			/* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
  			/* Clear CD-ROM DMA write bit */
  			tmp &= 0x7F;
  		/* Cable and UDMA */
d6250a03f   Alan Cox   pata_ali: Fix reg...
446
447
448
  		if (pdev->revision >= 0xc2)
  			tmp |= 0x01;
  		pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
449
450
451
452
453
454
  		/*
  		 * CD_ROM DMA on (0x53 bit 0). Enable this even if we want
  		 * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
  		 * via 0x54/55.
  		 */
  		pci_read_config_byte(pdev, 0x53, &tmp);
44c10138f   Auke Kok   PCI: Change all d...
455
  		if (pdev->revision >= 0xc7)
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
456
457
458
459
460
  			tmp |= 0x03;
  		else
  			tmp |= 0x01;	/* CD_ROM enable for DMA */
  		pci_write_config_byte(pdev, 0x53, tmp);
  	}
1b2c357c3   Alan Cox   pata_ali: force i...
461
  	north = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
bc42b24e6   Andrew Morton   drivers/ata/pata_...
462
  	if (north && north->vendor == PCI_VENDOR_ID_AL && ali_isa_bridge) {
1b2c357c3   Alan Cox   pata_ali: force i...
463
464
  		/* Configure the ALi bridge logic. For non ALi rely on BIOS.
  		   Set the south bridge enable bit */
bc42b24e6   Andrew Morton   drivers/ata/pata_...
465
  		pci_read_config_byte(ali_isa_bridge, 0x79, &tmp);
1b2c357c3   Alan Cox   pata_ali: force i...
466
  		if (pdev->revision == 0xC2)
bc42b24e6   Andrew Morton   drivers/ata/pata_...
467
  			pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x04);
1b2c357c3   Alan Cox   pata_ali: force i...
468
  		else if (pdev->revision > 0xC2 && pdev->revision < 0xC5)
bc42b24e6   Andrew Morton   drivers/ata/pata_...
469
  			pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x02);
1b2c357c3   Alan Cox   pata_ali: force i...
470
  	}
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
471
  	pci_dev_put(north);
9363c3825   Tejun Heo   libata: rename SF...
472
  	ata_pci_bmdma_clear_simplex(pdev);
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
473
  }
669a5db41   Jeff Garzik   [libata] Add a bu...
474
475
476
477
478
479
480
481
482
483
484
  /**
   *	ali_init_one		-	discovery callback
   *	@pdev: PCI device ID
   *	@id: PCI table info
   *
   *	An ALi IDE interface has been discovered. Figure out what revision
   *	and perform configuration work before handing it to the ATA layer
   */
  
  static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
  {
1626aeb88   Tejun Heo   libata: clean up ...
485
  	static const struct ata_port_info info_early = {
1d2808fd3   Jeff Garzik   [libata] PATA dri...
486
  		.flags = ATA_FLAG_SLAVE_POSS,
14bdef982   Erik Inge Bolsø   [libata] convert ...
487
  		.pio_mask = ATA_PIO4,
669a5db41   Jeff Garzik   [libata] Add a bu...
488
489
490
  		.port_ops = &ali_early_port_ops
  	};
  	/* Revision 0x20 added DMA */
1626aeb88   Tejun Heo   libata: clean up ...
491
  	static const struct ata_port_info info_20 = {
a3cb900cc   Alan Cox   [libata] pata_ali...
492
493
  		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
  							ATA_FLAG_IGN_SIMPLEX,
14bdef982   Erik Inge Bolsø   [libata] convert ...
494
495
  		.pio_mask = ATA_PIO4,
  		.mwdma_mask = ATA_MWDMA2,
669a5db41   Jeff Garzik   [libata] Add a bu...
496
497
498
  		.port_ops = &ali_20_port_ops
  	};
  	/* Revision 0x20 with support logic added UDMA */
1626aeb88   Tejun Heo   libata: clean up ...
499
  	static const struct ata_port_info info_20_udma = {
a3cb900cc   Alan Cox   [libata] pata_ali...
500
501
  		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
  							ATA_FLAG_IGN_SIMPLEX,
14bdef982   Erik Inge Bolsø   [libata] convert ...
502
503
504
  		.pio_mask = ATA_PIO4,
  		.mwdma_mask = ATA_MWDMA2,
  		.udma_mask = ATA_UDMA2,
669a5db41   Jeff Garzik   [libata] Add a bu...
505
506
507
  		.port_ops = &ali_20_port_ops
  	};
  	/* Revision 0xC2 adds UDMA66 */
1626aeb88   Tejun Heo   libata: clean up ...
508
  	static const struct ata_port_info info_c2 = {
a3cb900cc   Alan Cox   [libata] pata_ali...
509
510
  		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
  							ATA_FLAG_IGN_SIMPLEX,
14bdef982   Erik Inge Bolsø   [libata] convert ...
511
512
  		.pio_mask = ATA_PIO4,
  		.mwdma_mask = ATA_MWDMA2,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
513
  		.udma_mask = ATA_UDMA4,
669a5db41   Jeff Garzik   [libata] Add a bu...
514
515
  		.port_ops = &ali_c2_port_ops
  	};
ee5815023   Chuck Ebbert   pata_ali: fix UDM...
516
  	/* Revision 0xC3 is UDMA66 for now */
1626aeb88   Tejun Heo   libata: clean up ...
517
  	static const struct ata_port_info info_c3 = {
a3cb900cc   Alan Cox   [libata] pata_ali...
518
519
  		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
  							ATA_FLAG_IGN_SIMPLEX,
14bdef982   Erik Inge Bolsø   [libata] convert ...
520
521
  		.pio_mask = ATA_PIO4,
  		.mwdma_mask = ATA_MWDMA2,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
522
  		.udma_mask = ATA_UDMA4,
669a5db41   Jeff Garzik   [libata] Add a bu...
523
524
  		.port_ops = &ali_c2_port_ops
  	};
ee5815023   Chuck Ebbert   pata_ali: fix UDM...
525
  	/* Revision 0xC4 is UDMA100 */
1626aeb88   Tejun Heo   libata: clean up ...
526
  	static const struct ata_port_info info_c4 = {
a3cb900cc   Alan Cox   [libata] pata_ali...
527
528
  		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
  							ATA_FLAG_IGN_SIMPLEX,
14bdef982   Erik Inge Bolsø   [libata] convert ...
529
530
  		.pio_mask = ATA_PIO4,
  		.mwdma_mask = ATA_MWDMA2,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
531
  		.udma_mask = ATA_UDMA5,
fc80902fd   Alan Cox   pata_ali: Fix and...
532
  		.port_ops = &ali_c4_port_ops
669a5db41   Jeff Garzik   [libata] Add a bu...
533
534
  	};
  	/* Revision 0xC5 is UDMA133 with LBA48 DMA */
1626aeb88   Tejun Heo   libata: clean up ...
535
  	static const struct ata_port_info info_c5 = {
a3cb900cc   Alan Cox   [libata] pata_ali...
536
  		.flags = ATA_FLAG_SLAVE_POSS | 	ATA_FLAG_IGN_SIMPLEX,
14bdef982   Erik Inge Bolsø   [libata] convert ...
537
538
  		.pio_mask = ATA_PIO4,
  		.mwdma_mask = ATA_MWDMA2,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
539
  		.udma_mask = ATA_UDMA6,
669a5db41   Jeff Garzik   [libata] Add a bu...
540
541
  		.port_ops = &ali_c5_port_ops
  	};
1626aeb88   Tejun Heo   libata: clean up ...
542
  	const struct ata_port_info *ppi[] = { NULL, NULL };
44c10138f   Auke Kok   PCI: Change all d...
543
  	u8 tmp;
f08048e94   Tejun Heo   libata: PCI devic...
544
545
546
547
548
  	int rc;
  
  	rc = pcim_enable_device(pdev);
  	if (rc)
  		return rc;
669a5db41   Jeff Garzik   [libata] Add a bu...
549

669a5db41   Jeff Garzik   [libata] Add a bu...
550
551
552
553
  	/*
  	 * The chipset revision selects the driver operations and
  	 * mode data.
  	 */
44c10138f   Auke Kok   PCI: Change all d...
554
  	if (pdev->revision < 0x20) {
1626aeb88   Tejun Heo   libata: clean up ...
555
  		ppi[0] = &info_early;
44c10138f   Auke Kok   PCI: Change all d...
556
  	} else if (pdev->revision < 0xC2) {
1626aeb88   Tejun Heo   libata: clean up ...
557
          	ppi[0] = &info_20;
44c10138f   Auke Kok   PCI: Change all d...
558
  	} else if (pdev->revision == 0xC2) {
1626aeb88   Tejun Heo   libata: clean up ...
559
          	ppi[0] = &info_c2;
44c10138f   Auke Kok   PCI: Change all d...
560
  	} else if (pdev->revision == 0xC3) {
1626aeb88   Tejun Heo   libata: clean up ...
561
          	ppi[0] = &info_c3;
44c10138f   Auke Kok   PCI: Change all d...
562
  	} else if (pdev->revision == 0xC4) {
1626aeb88   Tejun Heo   libata: clean up ...
563
          	ppi[0] = &info_c4;
669a5db41   Jeff Garzik   [libata] Add a bu...
564
  	} else
1626aeb88   Tejun Heo   libata: clean up ...
565
          	ppi[0] = &info_c5;
669a5db41   Jeff Garzik   [libata] Add a bu...
566

34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
567
  	ali_init_chipset(pdev);
f20b16ff7   Jeff Garzik   [libata] trim tra...
568

bc42b24e6   Andrew Morton   drivers/ata/pata_...
569
  	if (ali_isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
570
  		/* Are we paired with a UDMA capable chip */
bc42b24e6   Andrew Morton   drivers/ata/pata_...
571
  		pci_read_config_byte(ali_isa_bridge, 0x5E, &tmp);
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
572
  		if ((tmp & 0x1E) == 0x12)
1626aeb88   Tejun Heo   libata: clean up ...
573
  	        	ppi[0] = &info_20_udma;
669a5db41   Jeff Garzik   [libata] Add a bu...
574
  	}
e8389f0c4   Ben Dooks   pata_ali: misplac...
575

1c5afdf7a   Tejun Heo   libata-sff: separ...
576
577
578
579
  	if (!ppi[0]->mwdma_mask && !ppi[0]->udma_mask)
  		return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL, 0);
  	else
  		return ata_pci_bmdma_init_one(pdev, ppi, &ali_sht, NULL, 0);
669a5db41   Jeff Garzik   [libata] Add a bu...
580
  }
438ac6d5e   Tejun Heo   libata: add missi...
581
  #ifdef CONFIG_PM
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
582
583
  static int ali_reinit_one(struct pci_dev *pdev)
  {
f08048e94   Tejun Heo   libata: PCI devic...
584
585
586
587
588
589
  	struct ata_host *host = dev_get_drvdata(&pdev->dev);
  	int rc;
  
  	rc = ata_pci_device_do_resume(pdev);
  	if (rc)
  		return rc;
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
590
  	ali_init_chipset(pdev);
f08048e94   Tejun Heo   libata: PCI devic...
591
592
  	ata_host_resume(host);
  	return 0;
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
593
  }
438ac6d5e   Tejun Heo   libata: add missi...
594
  #endif
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
595

2d2744fc8   Jeff Garzik   [libata] PCI ID t...
596
597
598
599
600
  static const struct pci_device_id ali[] = {
  	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), },
  	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), },
  
  	{ },
669a5db41   Jeff Garzik   [libata] Add a bu...
601
602
603
604
605
606
  };
  
  static struct pci_driver ali_pci_driver = {
  	.name 		= DRV_NAME,
  	.id_table	= ali,
  	.probe 		= ali_init_one,
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
607
  	.remove		= ata_pci_remove_one,
438ac6d5e   Tejun Heo   libata: add missi...
608
  #ifdef CONFIG_PM
34d8dfb1e   Alan Cox   [PATCH] pata_ali:...
609
610
  	.suspend	= ata_pci_device_suspend,
  	.resume		= ali_reinit_one,
438ac6d5e   Tejun Heo   libata: add missi...
611
  #endif
669a5db41   Jeff Garzik   [libata] Add a bu...
612
613
614
615
  };
  
  static int __init ali_init(void)
  {
1b2c357c3   Alan Cox   pata_ali: force i...
616
  	int ret;
bc42b24e6   Andrew Morton   drivers/ata/pata_...
617
  	ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
1b2c357c3   Alan Cox   pata_ali: force i...
618
619
620
  
  	ret = pci_register_driver(&ali_pci_driver);
  	if (ret < 0)
bc42b24e6   Andrew Morton   drivers/ata/pata_...
621
  		pci_dev_put(ali_isa_bridge);
1b2c357c3   Alan Cox   pata_ali: force i...
622
  	return ret;
669a5db41   Jeff Garzik   [libata] Add a bu...
623
624
625
626
627
628
  }
  
  
  static void __exit ali_exit(void)
  {
  	pci_unregister_driver(&ali_pci_driver);
bc42b24e6   Andrew Morton   drivers/ata/pata_...
629
  	pci_dev_put(ali_isa_bridge);
669a5db41   Jeff Garzik   [libata] Add a bu...
630
631
632
633
634
635
636
637
638
639
640
  }
  
  
  MODULE_AUTHOR("Alan Cox");
  MODULE_DESCRIPTION("low-level driver for ALi PATA");
  MODULE_LICENSE("GPL");
  MODULE_DEVICE_TABLE(pci, ali);
  MODULE_VERSION(DRV_VERSION);
  
  module_init(ali_init);
  module_exit(ali_exit);