Blame view

drivers/ata/sata_via.c 17.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
af36d7f0d   Jeff Garzik   [libata] license ...
2
3
4
5
   *  sata_via.c - VIA Serial ATA controllers
   *
   *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
   * 		   Please ALWAYS copy linux-ide@vger.kernel.org
5796d1c4c   Jeff Garzik   [libata] Address ...
6
   *		   on emails.
af36d7f0d   Jeff Garzik   [libata] license ...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
   *
   *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
   *  Copyright 2003-2004 Jeff Garzik
   *
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2, or (at your option)
   *  any later version.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program; see the file COPYING.  If not, write to
   *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   *
   *
   *  libata documentation is available via 'make {ps|pdf}docs',
   *  as Documentation/DocBook/libata.*
   *
   *  Hardware documentation available under NDA.
   *
   *
af36d7f0d   Jeff Garzik   [libata] license ...
33
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
39
40
41
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/pci.h>
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <linux/delay.h>
a9524a76f   Jeff Garzik   [libata] use dev_...
42
  #include <linux/device.h>
a55ab496e   Bart Hartgers   sata_via: Delay o...
43
44
  #include <scsi/scsi.h>
  #include <scsi/scsi_cmnd.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
  #include <scsi/scsi_host.h>
  #include <linux/libata.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
  
  #define DRV_NAME	"sata_via"
a55ab496e   Bart Hartgers   sata_via: Delay o...
49
  #define DRV_VERSION	"2.6"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50

b9d5b89b4   Tejun Heo   sata_via: fix sup...
51
52
53
54
  /*
   * vt8251 is different from other sata controllers of VIA.  It has two
   * channels, each channel has both Master and Slave slot.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
  enum board_ids_enum {
  	vt6420,
  	vt6421,
b9d5b89b4   Tejun Heo   sata_via: fix sup...
58
  	vt8251,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
64
  };
  
  enum {
  	SATA_CHAN_ENAB		= 0x40, /* SATA channel enable */
  	SATA_INT_GATE		= 0x41, /* SATA interrupt gating */
  	SATA_NATIVE_MODE	= 0x42, /* Native mode enable */
d73f30e1c   Alan Cox   sata_via: PATA su...
65
66
  	PATA_UDMA_TIMING	= 0xB3, /* PATA timing for DMA/ cable detect */
  	PATA_PIO_TIMING		= 0xAB, /* PATA timing register */
a84471fe2   Jeff Garzik   [libata] Trim tra...
67

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
  	PORT0			= (1 << 1),
  	PORT1			= (1 << 0),
  	ALL_PORTS		= PORT0 | PORT1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
74
  
  	NATIVE_MODE_ALL		= (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
  
  	SATA_EXT_PHY		= (1 << 6), /* 0==use PATA, 1==ext phy */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  };
5796d1c4c   Jeff Garzik   [libata] Address ...
76
  static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
82ef04fb4   Tejun Heo   libata: make SCR ...
77
78
  static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
  static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
b9d5b89b4   Tejun Heo   sata_via: fix sup...
79
80
  static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val);
  static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val);
b78152e9d   Tejun Heo   sata_via: load DE...
81
  static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
17234246e   Tejun Heo   sata_via: don't d...
82
  static void svia_noop_freeze(struct ata_port *ap);
a1efdaba2   Tejun Heo   libata: make rese...
83
  static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
a55ab496e   Bart Hartgers   sata_via: Delay o...
84
  static void vt6420_bmdma_start(struct ata_queued_cmd *qc);
a0fcdc025   Jeff Garzik   [libata] Update s...
85
  static int vt6421_pata_cable_detect(struct ata_port *ap);
d73f30e1c   Alan Cox   sata_via: PATA su...
86
87
  static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev);
  static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88

3b7d697df   Jeff Garzik   [libata] constify...
89
  static const struct pci_device_id svia_pci_tbl[] = {
96bc103f4   Luca Pedrielli   sata_via: add PCI...
90
  	{ PCI_VDEVICE(VIA, 0x5337), vt6420 },
b9d5b89b4   Tejun Heo   sata_via: fix sup...
91
92
93
  	{ PCI_VDEVICE(VIA, 0x0591), vt6420 }, /* 2 sata chnls (Master) */
  	{ PCI_VDEVICE(VIA, 0x3149), vt6420 }, /* 2 sata chnls (Master) */
  	{ PCI_VDEVICE(VIA, 0x3249), vt6421 }, /* 2 sata chnls, 1 pata chnl */
52df0ee07   Jeff Garzik   [libata] sata_via...
94
95
  	{ PCI_VDEVICE(VIA, 0x5372), vt6420 },
  	{ PCI_VDEVICE(VIA, 0x7372), vt6420 },
b9d5b89b4   Tejun Heo   sata_via: fix sup...
96
  	{ PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */
681395202   JosephChan@via.com.tw   sata_via: Add VT8...
97
  	{ PCI_VDEVICE(VIA, 0x9000), vt8251 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
102
103
104
105
  
  	{ }	/* terminate list */
  };
  
  static struct pci_driver svia_pci_driver = {
  	.name			= DRV_NAME,
  	.id_table		= svia_pci_tbl,
  	.probe			= svia_init_one,
e1e143cf9   Tejun Heo   sata_via: add mis...
106
107
108
109
  #ifdef CONFIG_PM
  	.suspend		= ata_pci_device_suspend,
  	.resume			= ata_pci_device_resume,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
  	.remove			= ata_pci_remove_one,
  };
193515d51   Jeff Garzik   [libata] eliminat...
112
  static struct scsi_host_template svia_sht = {
68d1d07b5   Tejun Heo   libata: implement...
113
  	ATA_BMDMA_SHT(DRV_NAME),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  };
b78152e9d   Tejun Heo   sata_via: load DE...
115
  static struct ata_port_operations svia_base_ops = {
029cfd6b7   Tejun Heo   libata: implement...
116
  	.inherits		= &ata_bmdma_port_ops,
b78152e9d   Tejun Heo   sata_via: load DE...
117
118
119
120
121
  	.sff_tf_load		= svia_tf_load,
  };
  
  static struct ata_port_operations vt6420_sata_ops = {
  	.inherits		= &svia_base_ops,
17234246e   Tejun Heo   sata_via: don't d...
122
  	.freeze			= svia_noop_freeze,
a1efdaba2   Tejun Heo   libata: make rese...
123
  	.prereset		= vt6420_prereset,
a55ab496e   Bart Hartgers   sata_via: Delay o...
124
  	.bmdma_start		= vt6420_bmdma_start,
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
125
  };
029cfd6b7   Tejun Heo   libata: implement...
126
  static struct ata_port_operations vt6421_pata_ops = {
b78152e9d   Tejun Heo   sata_via: load DE...
127
  	.inherits		= &svia_base_ops,
029cfd6b7   Tejun Heo   libata: implement...
128
  	.cable_detect		= vt6421_pata_cable_detect,
d73f30e1c   Alan Cox   sata_via: PATA su...
129
130
  	.set_piomode		= vt6421_set_pio_mode,
  	.set_dmamode		= vt6421_set_dma_mode,
d73f30e1c   Alan Cox   sata_via: PATA su...
131
  };
029cfd6b7   Tejun Heo   libata: implement...
132
  static struct ata_port_operations vt6421_sata_ops = {
b78152e9d   Tejun Heo   sata_via: load DE...
133
  	.inherits		= &svia_base_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  	.scr_read		= svia_scr_read,
  	.scr_write		= svia_scr_write,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  };
b9d5b89b4   Tejun Heo   sata_via: fix sup...
137
138
139
140
141
142
  static struct ata_port_operations vt8251_ops = {
  	.inherits		= &svia_base_ops,
  	.hardreset		= sata_std_hardreset,
  	.scr_read		= vt8251_scr_read,
  	.scr_write		= vt8251_scr_write,
  };
eca25dca1   Tejun Heo   libata: convert d...
143
  static const struct ata_port_info vt6420_port_info = {
9cbe056f6   Sergei Shtylyov   libata: remove AT...
144
  	.flags		= ATA_FLAG_SATA,
14bdef982   Erik Inge Bolsø   [libata] convert ...
145
146
  	.pio_mask	= ATA_PIO4,
  	.mwdma_mask	= ATA_MWDMA2,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
147
  	.udma_mask	= ATA_UDMA6,
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
148
  	.port_ops	= &vt6420_sata_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  };
eca25dca1   Tejun Heo   libata: convert d...
150
  static struct ata_port_info vt6421_sport_info = {
9cbe056f6   Sergei Shtylyov   libata: remove AT...
151
  	.flags		= ATA_FLAG_SATA,
14bdef982   Erik Inge Bolsø   [libata] convert ...
152
153
  	.pio_mask	= ATA_PIO4,
  	.mwdma_mask	= ATA_MWDMA2,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
154
  	.udma_mask	= ATA_UDMA6,
eca25dca1   Tejun Heo   libata: convert d...
155
156
157
158
  	.port_ops	= &vt6421_sata_ops,
  };
  
  static struct ata_port_info vt6421_pport_info = {
9cbe056f6   Sergei Shtylyov   libata: remove AT...
159
  	.flags		= ATA_FLAG_SLAVE_POSS,
14bdef982   Erik Inge Bolsø   [libata] convert ...
160
161
  	.pio_mask	= ATA_PIO4,
  	/* No MWDMA */
bf6263a85   Jeff Garzik   [libata] Use ATA_...
162
  	.udma_mask	= ATA_UDMA6,
eca25dca1   Tejun Heo   libata: convert d...
163
164
  	.port_ops	= &vt6421_pata_ops,
  };
b9d5b89b4   Tejun Heo   sata_via: fix sup...
165
  static struct ata_port_info vt8251_port_info = {
9cbe056f6   Sergei Shtylyov   libata: remove AT...
166
  	.flags		= ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS,
14bdef982   Erik Inge Bolsø   [libata] convert ...
167
168
  	.pio_mask	= ATA_PIO4,
  	.mwdma_mask	= ATA_MWDMA2,
b9d5b89b4   Tejun Heo   sata_via: fix sup...
169
170
171
  	.udma_mask	= ATA_UDMA6,
  	.port_ops	= &vt8251_ops,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
175
176
  MODULE_AUTHOR("Jeff Garzik");
  MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
  MODULE_LICENSE("GPL");
  MODULE_DEVICE_TABLE(pci, svia_pci_tbl);
  MODULE_VERSION(DRV_VERSION);
82ef04fb4   Tejun Heo   libata: make SCR ...
177
  static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
  {
  	if (sc_reg > SCR_CONTROL)
da3dbb17a   Tejun Heo   libata: make ->sc...
180
  		return -EINVAL;
82ef04fb4   Tejun Heo   libata: make SCR ...
181
  	*val = ioread32(link->ap->ioaddr.scr_addr + (4 * sc_reg));
da3dbb17a   Tejun Heo   libata: make ->sc...
182
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  }
82ef04fb4   Tejun Heo   libata: make SCR ...
184
  static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
  {
  	if (sc_reg > SCR_CONTROL)
da3dbb17a   Tejun Heo   libata: make ->sc...
187
  		return -EINVAL;
82ef04fb4   Tejun Heo   libata: make SCR ...
188
  	iowrite32(val, link->ap->ioaddr.scr_addr + (4 * sc_reg));
da3dbb17a   Tejun Heo   libata: make ->sc...
189
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  }
b9d5b89b4   Tejun Heo   sata_via: fix sup...
191
192
193
194
195
196
197
198
199
200
201
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
235
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
  static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
  {
  	static const u8 ipm_tbl[] = { 1, 2, 6, 0 };
  	struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
  	int slot = 2 * link->ap->port_no + link->pmp;
  	u32 v = 0;
  	u8 raw;
  
  	switch (scr) {
  	case SCR_STATUS:
  		pci_read_config_byte(pdev, 0xA0 + slot, &raw);
  
  		/* read the DET field, bit0 and 1 of the config byte */
  		v |= raw & 0x03;
  
  		/* read the SPD field, bit4 of the configure byte */
  		if (raw & (1 << 4))
  			v |= 0x02 << 4;
  		else
  			v |= 0x01 << 4;
  
  		/* read the IPM field, bit2 and 3 of the config byte */
  		v |= ipm_tbl[(raw >> 2) & 0x3];
  		break;
  
  	case SCR_ERROR:
  		/* devices other than 5287 uses 0xA8 as base */
  		WARN_ON(pdev->device != 0x5287);
  		pci_read_config_dword(pdev, 0xB0 + slot * 4, &v);
  		break;
  
  	case SCR_CONTROL:
  		pci_read_config_byte(pdev, 0xA4 + slot, &raw);
  
  		/* read the DET field, bit0 and bit1 */
  		v |= ((raw & 0x02) << 1) | (raw & 0x01);
  
  		/* read the IPM field, bit2 and bit3 */
  		v |= ((raw >> 2) & 0x03) << 8;
  		break;
  
  	default:
  		return -EINVAL;
  	}
  
  	*val = v;
  	return 0;
  }
  
  static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val)
  {
  	struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
  	int slot = 2 * link->ap->port_no + link->pmp;
  	u32 v = 0;
  
  	switch (scr) {
  	case SCR_ERROR:
  		/* devices other than 5287 uses 0xA8 as base */
  		WARN_ON(pdev->device != 0x5287);
  		pci_write_config_dword(pdev, 0xB0 + slot * 4, val);
  		return 0;
  
  	case SCR_CONTROL:
  		/* set the DET field */
  		v |= ((val & 0x4) >> 1) | (val & 0x1);
  
  		/* set the IPM field */
  		v |= ((val >> 8) & 0x3) << 2;
  
  		pci_write_config_byte(pdev, 0xA4 + slot, v);
  		return 0;
  
  	default:
  		return -EINVAL;
  	}
  }
b78152e9d   Tejun Heo   sata_via: load DE...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  /**
   *	svia_tf_load - send taskfile registers to host controller
   *	@ap: Port to which output is sent
   *	@tf: ATA taskfile register set
   *
   *	Outputs ATA taskfile to standard ATA host controller.
   *
   *	This is to fix the internal bug of via chipsets, which will
   *	reset the device register after changing the IEN bit on ctl
   *	register.
   */
  static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
  {
  	struct ata_taskfile ttf;
  
  	if (tf->ctl != ap->last_ctl)  {
  		ttf = *tf;
  		ttf.flags |= ATA_TFLAG_DEVICE;
  		tf = &ttf;
  	}
  	ata_sff_tf_load(ap, tf);
  }
17234246e   Tejun Heo   sata_via: don't d...
289
290
291
292
293
  static void svia_noop_freeze(struct ata_port *ap)
  {
  	/* Some VIA controllers choke if ATA_NIEN is manipulated in
  	 * certain way.  Leave it alone and just clear pending IRQ.
  	 */
5682ed33a   Tejun Heo   libata: rename SF...
294
  	ap->ops->sff_check_status(ap);
37f65b8bc   Tejun Heo   libata-sff: ata_s...
295
  	ata_bmdma_irq_clear(ap);
17234246e   Tejun Heo   sata_via: don't d...
296
  }
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
297
298
  /**
   *	vt6420_prereset - prereset for vt6420
cc0680a58   Tejun Heo   libata-link: link...
299
   *	@link: target ATA link
d4b2bab4f   Tejun Heo   libata: add deadl...
300
   *	@deadline: deadline jiffies for the operation
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
   *
   *	SCR registers on vt6420 are pieces of shit and may hang the
   *	whole machine completely if accessed with the wrong timing.
   *	To avoid such catastrophe, vt6420 doesn't provide generic SCR
   *	access operations, but uses SStatus and SControl only during
   *	boot probing in controlled way.
   *
   *	As the old (pre EH update) probing code is proven to work, we
   *	strictly follow the access pattern.
   *
   *	LOCKING:
   *	Kernel thread context (may sleep)
   *
   *	RETURNS:
   *	0 on success, -errno otherwise.
   */
cc0680a58   Tejun Heo   libata-link: link...
317
  static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
318
  {
cc0680a58   Tejun Heo   libata-link: link...
319
  	struct ata_port *ap = link->ap;
9af5c9c97   Tejun Heo   libata-link: intr...
320
  	struct ata_eh_context *ehc = &ap->link.eh_context;
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
321
322
323
324
325
  	unsigned long timeout = jiffies + (HZ * 5);
  	u32 sstatus, scontrol;
  	int online;
  
  	/* don't do any SCR stuff if we're not loading */
68ff6e8e0   Jeff Garzik   [libata] sata_via...
326
  	if (!(ap->pflags & ATA_PFLAG_LOADING))
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
327
  		goto skip_scr;
a09060ffe   Jeff Garzik   [libata] sata_sx4...
328
  	/* Resume phy.  This is the old SATA resume sequence */
82ef04fb4   Tejun Heo   libata: make SCR ...
329
330
  	svia_scr_write(link, SCR_CONTROL, 0x300);
  	svia_scr_read(link, SCR_CONTROL, &scontrol); /* flush */
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
331
332
333
  
  	/* wait for phy to become ready, if necessary */
  	do {
97750cebb   Tejun Heo   libata: add @ap t...
334
  		ata_msleep(link->ap, 200);
82ef04fb4   Tejun Heo   libata: make SCR ...
335
  		svia_scr_read(link, SCR_STATUS, &sstatus);
da3dbb17a   Tejun Heo   libata: make ->sc...
336
  		if ((sstatus & 0xf) != 1)
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
337
338
339
340
  			break;
  	} while (time_before(jiffies, timeout));
  
  	/* open code sata_print_link_status() */
82ef04fb4   Tejun Heo   libata: make SCR ...
341
342
  	svia_scr_read(link, SCR_STATUS, &sstatus);
  	svia_scr_read(link, SCR_CONTROL, &scontrol);
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
343
344
  
  	online = (sstatus & 0xf) == 0x3;
a9a79dfec   Joe Perches   ata: Convert ata_...
345
346
347
348
  	ata_port_info(ap,
  		      "SATA link %s 1.5 Gbps (SStatus %X SControl %X)
  ",
  		      online ? "up" : "down", sstatus, scontrol);
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
349
350
  
  	/* SStatus is read one more time */
82ef04fb4   Tejun Heo   libata: make SCR ...
351
  	svia_scr_read(link, SCR_STATUS, &sstatus);
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
352
353
354
  
  	if (!online) {
  		/* tell EH to bail */
cf4806265   Tejun Heo   libata: prefer ha...
355
  		ehc->i.action &= ~ATA_EH_RESET;
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
356
357
358
359
360
  		return 0;
  	}
  
   skip_scr:
  	/* wait for !BSY */
705e76beb   Tejun Heo   libata: restructu...
361
  	ata_sff_wait_ready(link, deadline);
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
362
363
364
  
  	return 0;
  }
a55ab496e   Bart Hartgers   sata_via: Delay o...
365
366
367
368
369
370
371
372
373
374
  static void vt6420_bmdma_start(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
  	if ((qc->tf.command == ATA_CMD_PACKET) &&
  	    (qc->scsicmd->sc_data_direction == DMA_TO_DEVICE)) {
  		/* Prevents corruption on some ATAPI burners */
  		ata_sff_pause(ap);
  	}
  	ata_bmdma_start(qc);
  }
a0fcdc025   Jeff Garzik   [libata] Update s...
375
  static int vt6421_pata_cable_detect(struct ata_port *ap)
d73f30e1c   Alan Cox   sata_via: PATA su...
376
377
378
379
380
381
  {
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
  	u8 tmp;
  
  	pci_read_config_byte(pdev, PATA_UDMA_TIMING, &tmp);
  	if (tmp & 0x10)
a0fcdc025   Jeff Garzik   [libata] Update s...
382
383
  		return ATA_CBL_PATA40;
  	return ATA_CBL_PATA80;
d73f30e1c   Alan Cox   sata_via: PATA su...
384
385
386
387
388
389
  }
  
  static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev)
  {
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
  	static const u8 pio_bits[] = { 0xA8, 0x65, 0x65, 0x31, 0x20 };
02d1d6160   Bart Hartgers   sata_via: Correct...
390
391
  	pci_write_config_byte(pdev, PATA_PIO_TIMING - adev->devno,
  			      pio_bits[adev->pio_mode - XFER_PIO_0]);
d73f30e1c   Alan Cox   sata_via: PATA su...
392
393
394
395
396
397
  }
  
  static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev)
  {
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
  	static const u8 udma_bits[] = { 0xEE, 0xE8, 0xE6, 0xE4, 0xE2, 0xE1, 0xE0, 0xE0 };
02d1d6160   Bart Hartgers   sata_via: Correct...
398
399
  	pci_write_config_byte(pdev, PATA_UDMA_TIMING - adev->devno,
  			      udma_bits[adev->dma_mode - XFER_UDMA_0]);
d73f30e1c   Alan Cox   sata_via: PATA su...
400
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
403
404
405
406
407
  static const unsigned int svia_bar_sizes[] = {
  	8, 4, 8, 4, 16, 256
  };
  
  static const unsigned int vt6421_bar_sizes[] = {
  	16, 16, 16, 16, 32, 128
  };
5796d1c4c   Jeff Garzik   [libata] Address ...
408
  static void __iomem *svia_scr_addr(void __iomem *addr, unsigned int port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
411
  {
  	return addr + (port * 128);
  }
5796d1c4c   Jeff Garzik   [libata] Address ...
412
  static void __iomem *vt6421_scr_addr(void __iomem *addr, unsigned int port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
  {
  	return addr + (port * 64);
  }
eca25dca1   Tejun Heo   libata: convert d...
416
  static void vt6421_init_addrs(struct ata_port *ap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  {
eca25dca1   Tejun Heo   libata: convert d...
418
419
420
421
422
423
424
425
  	void __iomem * const * iomap = ap->host->iomap;
  	void __iomem *reg_addr = iomap[ap->port_no];
  	void __iomem *bmdma_addr = iomap[4] + (ap->port_no * 8);
  	struct ata_ioports *ioaddr = &ap->ioaddr;
  
  	ioaddr->cmd_addr = reg_addr;
  	ioaddr->altstatus_addr =
  	ioaddr->ctl_addr = (void __iomem *)
0d5ff5667   Tejun Heo   libata: convert t...
426
  		((unsigned long)(reg_addr + 8) | ATA_PCI_CTL_OFS);
eca25dca1   Tejun Heo   libata: convert d...
427
428
  	ioaddr->bmdma_addr = bmdma_addr;
  	ioaddr->scr_addr = vt6421_scr_addr(iomap[5], ap->port_no);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429

9363c3825   Tejun Heo   libata: rename SF...
430
  	ata_sff_std_ports(ioaddr);
cbcdd8759   Tejun Heo   libata: implement...
431
432
433
  
  	ata_port_pbar_desc(ap, ap->port_no, -1, "port");
  	ata_port_pbar_desc(ap, 4, ap->port_no * 8, "bmdma");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  }
eca25dca1   Tejun Heo   libata: convert d...
435
  static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
  {
eca25dca1   Tejun Heo   libata: convert d...
437
438
439
  	const struct ata_port_info *ppi[] = { &vt6420_port_info, NULL };
  	struct ata_host *host;
  	int rc;
f20b16ff7   Jeff Garzik   [libata] trim tra...
440

1c5afdf7a   Tejun Heo   libata-sff: separ...
441
  	rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
eca25dca1   Tejun Heo   libata: convert d...
442
443
444
  	if (rc)
  		return rc;
  	*r_host = host;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445

eca25dca1   Tejun Heo   libata: convert d...
446
447
  	rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
  	if (rc) {
a44fec1fc   Joe Perches   ata: Convert dev_...
448
449
  		dev_err(&pdev->dev, "failed to iomap PCI BAR 5
  ");
eca25dca1   Tejun Heo   libata: convert d...
450
  		return rc;
e1be5d73e   Tejun Heo   sata_via: fix res...
451
  	}
eca25dca1   Tejun Heo   libata: convert d...
452
453
  	host->ports[0]->ioaddr.scr_addr = svia_scr_addr(host->iomap[5], 0);
  	host->ports[1]->ioaddr.scr_addr = svia_scr_addr(host->iomap[5], 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454

eca25dca1   Tejun Heo   libata: convert d...
455
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
  }
eca25dca1   Tejun Heo   libata: convert d...
457
  static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
  {
eca25dca1   Tejun Heo   libata: convert d...
459
460
461
462
463
464
465
  	const struct ata_port_info *ppi[] =
  		{ &vt6421_sport_info, &vt6421_sport_info, &vt6421_pport_info };
  	struct ata_host *host;
  	int i, rc;
  
  	*r_host = host = ata_host_alloc_pinfo(&pdev->dev, ppi, ARRAY_SIZE(ppi));
  	if (!host) {
a44fec1fc   Joe Perches   ata: Convert dev_...
466
467
  		dev_err(&pdev->dev, "failed to allocate host
  ");
eca25dca1   Tejun Heo   libata: convert d...
468
469
  		return -ENOMEM;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470

8fd7d1b16   Tejun Heo   sata_via: pcim_io...
471
  	rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);
eca25dca1   Tejun Heo   libata: convert d...
472
  	if (rc) {
a44fec1fc   Joe Perches   ata: Convert dev_...
473
474
475
  		dev_err(&pdev->dev, "failed to request/iomap PCI BARs (errno=%d)
  ",
  			rc);
eca25dca1   Tejun Heo   libata: convert d...
476
477
478
  		return rc;
  	}
  	host->iomap = pcim_iomap_table(pdev);
e1be5d73e   Tejun Heo   sata_via: fix res...
479

eca25dca1   Tejun Heo   libata: convert d...
480
481
  	for (i = 0; i < host->n_ports; i++)
  		vt6421_init_addrs(host->ports[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482

eca25dca1   Tejun Heo   libata: convert d...
483
484
485
486
487
488
489
490
  	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
  	if (rc)
  		return rc;
  	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
  	if (rc)
  		return rc;
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
  }
b9d5b89b4   Tejun Heo   sata_via: fix sup...
492
493
494
495
496
  static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
  {
  	const struct ata_port_info *ppi[] = { &vt8251_port_info, NULL };
  	struct ata_host *host;
  	int i, rc;
1c5afdf7a   Tejun Heo   libata-sff: separ...
497
  	rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
b9d5b89b4   Tejun Heo   sata_via: fix sup...
498
499
500
501
502
503
  	if (rc)
  		return rc;
  	*r_host = host;
  
  	rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
  	if (rc) {
a44fec1fc   Joe Perches   ata: Convert dev_...
504
505
  		dev_err(&pdev->dev, "failed to iomap PCI BAR 5
  ");
b9d5b89b4   Tejun Heo   sata_via: fix sup...
506
507
508
509
510
511
512
513
514
  		return rc;
  	}
  
  	/* 8251 hosts four sata ports as M/S of the two channels */
  	for (i = 0; i < host->n_ports; i++)
  		ata_slave_link_init(host->ports[i]);
  
  	return 0;
  }
b1353e4f4   Tejun Heo   sata_via: apply m...
515
  static void svia_configure(struct pci_dev *pdev, int board_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
519
  {
  	u8 tmp8;
  
  	pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
a44fec1fc   Joe Perches   ata: Convert dev_...
520
521
522
  	dev_info(&pdev->dev, "routed to hard irq line %d
  ",
  		 (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
525
526
  
  	/* make sure SATA channels are enabled */
  	pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
  	if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
5b933e634   Joe Perches   ata: sata_via: Us...
527
528
529
  		dev_dbg(&pdev->dev, "enabling SATA channels (0x%x)
  ",
  			(int)tmp8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
532
533
534
535
536
  		tmp8 |= ALL_PORTS;
  		pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
  	}
  
  	/* make sure interrupts for each channel sent to us */
  	pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
  	if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
5b933e634   Joe Perches   ata: sata_via: Us...
537
538
539
  		dev_dbg(&pdev->dev, "enabling SATA channel interrupts (0x%x)
  ",
  			(int) tmp8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
543
544
545
546
  		tmp8 |= ALL_PORTS;
  		pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
  	}
  
  	/* make sure native mode is enabled */
  	pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
  	if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
5b933e634   Joe Perches   ata: sata_via: Us...
547
548
549
550
  		dev_dbg(&pdev->dev,
  			"enabling SATA channel native mode (0x%x)
  ",
  			(int) tmp8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
  		tmp8 |= NATIVE_MODE_ALL;
  		pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
  	}
8b27ff4cf   Tejun Heo   sata_via: magic v...
554
555
  
  	/*
b1353e4f4   Tejun Heo   sata_via: apply m...
556
  	 * vt6420/1 has problems talking to some drives.  The following
b475a3b83   Tejun Heo   sata_via: explain...
557
558
559
560
561
  	 * is the fix from Joseph Chan <JosephChan@via.com.tw>.
  	 *
  	 * When host issues HOLD, device may send up to 20DW of data
  	 * before acknowledging it with HOLDA and the host should be
  	 * able to buffer them in FIFO.  Unfortunately, some WD drives
25985edce   Lucas De Marchi   Fix common misspe...
562
  	 * send up to 40DW before acknowledging HOLD and, in the
b475a3b83   Tejun Heo   sata_via: explain...
563
564
565
566
567
568
569
570
571
  	 * default configuration, this ends up overflowing vt6421's
  	 * FIFO, making the controller abort the transaction with
  	 * R_ERR.
  	 *
  	 * Rx52[2] is the internal 128DW FIFO Flow control watermark
  	 * adjusting mechanism enable bit and the default value 0
  	 * means host will issue HOLD to device when the left FIFO
  	 * size goes below 32DW.  Setting it to 1 makes the watermark
  	 * 64DW.
8b27ff4cf   Tejun Heo   sata_via: magic v...
572
573
  	 *
  	 * https://bugzilla.kernel.org/show_bug.cgi?id=15173
b475a3b83   Tejun Heo   sata_via: explain...
574
  	 * http://article.gmane.org/gmane.linux.ide/46352
b1353e4f4   Tejun Heo   sata_via: apply m...
575
  	 * http://thread.gmane.org/gmane.linux.kernel/1062139
8b27ff4cf   Tejun Heo   sata_via: magic v...
576
  	 */
b1353e4f4   Tejun Heo   sata_via: apply m...
577
  	if (board_id == vt6420 || board_id == vt6421) {
8b27ff4cf   Tejun Heo   sata_via: magic v...
578
579
580
581
  		pci_read_config_byte(pdev, 0x52, &tmp8);
  		tmp8 |= 1 << 2;
  		pci_write_config_byte(pdev, 0x52, tmp8);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  }
5796d1c4c   Jeff Garzik   [libata] Address ...
583
  static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
  	unsigned int i;
  	int rc;
f1c22943e   Jeff Garzik   [libata] sata_via...
587
  	struct ata_host *host = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
  	int board_id = (int) ent->driver_data;
b4482a4b2   Al Viro   more trivial sign...
589
  	const unsigned *bar_sizes;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590

06296a1e6   Joe Perches   ata: Add and use ...
591
  	ata_print_version_once(&pdev->dev, DRV_VERSION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592

24dc5f33e   Tejun Heo   libata: update li...
593
  	rc = pcim_enable_device(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
  	if (rc)
  		return rc;
b9d5b89b4   Tejun Heo   sata_via: fix sup...
596
  	if (board_id == vt6421)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
  		bar_sizes = &vt6421_bar_sizes[0];
b9d5b89b4   Tejun Heo   sata_via: fix sup...
598
599
  	else
  		bar_sizes = &svia_bar_sizes[0];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
601
602
603
  
  	for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
  		if ((pci_resource_start(pdev, i) == 0) ||
  		    (pci_resource_len(pdev, i) < bar_sizes[i])) {
a44fec1fc   Joe Perches   ata: Convert dev_...
604
  			dev_err(&pdev->dev,
e29419fff   Greg Kroah-Hartman   [PATCH] 64bit res...
605
606
607
  				"invalid PCI BAR %u (sz 0x%llx, val 0x%llx)
  ",
  				i,
5796d1c4c   Jeff Garzik   [libata] Address ...
608
609
  				(unsigned long long)pci_resource_start(pdev, i),
  				(unsigned long long)pci_resource_len(pdev, i));
24dc5f33e   Tejun Heo   libata: update li...
610
  			return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
  		}
b9d5b89b4   Tejun Heo   sata_via: fix sup...
612
613
  	switch (board_id) {
  	case vt6420:
eca25dca1   Tejun Heo   libata: convert d...
614
  		rc = vt6420_prepare_host(pdev, &host);
b9d5b89b4   Tejun Heo   sata_via: fix sup...
615
616
  		break;
  	case vt6421:
eca25dca1   Tejun Heo   libata: convert d...
617
  		rc = vt6421_prepare_host(pdev, &host);
b9d5b89b4   Tejun Heo   sata_via: fix sup...
618
619
620
621
622
  		break;
  	case vt8251:
  		rc = vt8251_prepare_host(pdev, &host);
  		break;
  	default:
554d491de   Marcin Slusarz   sata_via: restore...
623
  		rc = -EINVAL;
b9d5b89b4   Tejun Heo   sata_via: fix sup...
624
  	}
554d491de   Marcin Slusarz   sata_via: restore...
625
626
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627

b1353e4f4   Tejun Heo   sata_via: apply m...
628
  	svia_configure(pdev, board_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
630
  
  	pci_set_master(pdev);
c3b288942   Tejun Heo   libata-sff: separ...
631
  	return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
9363c3825   Tejun Heo   libata: rename SF...
632
  				 IRQF_SHARED, &svia_sht);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
634
635
636
  }
  
  static int __init svia_init(void)
  {
b7887196e   Pavel Roskin   [PATCH] libata: r...
637
  	return pci_register_driver(&svia_pci_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
641
642
643
644
645
646
  }
  
  static void __exit svia_exit(void)
  {
  	pci_unregister_driver(&svia_pci_driver);
  }
  
  module_init(svia_init);
  module_exit(svia_exit);