Blame view

drivers/ata/sata_via.c 16.6 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>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
  #include <scsi/scsi_host.h>
  #include <linux/libata.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
  
  #define DRV_NAME	"sata_via"
b9d5b89b4   Tejun Heo   sata_via: fix sup...
47
  #define DRV_VERSION	"2.4"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48

b9d5b89b4   Tejun Heo   sata_via: fix sup...
49
50
51
52
  /*
   * 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
53
54
55
  enum board_ids_enum {
  	vt6420,
  	vt6421,
b9d5b89b4   Tejun Heo   sata_via: fix sup...
56
  	vt8251,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
60
61
62
  };
  
  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...
63
64
  	PATA_UDMA_TIMING	= 0xB3, /* PATA timing for DMA/ cable detect */
  	PATA_PIO_TIMING		= 0xAB, /* PATA timing register */
a84471fe2   Jeff Garzik   [libata] Trim tra...
65

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
  	PORT0			= (1 << 1),
  	PORT1			= (1 << 0),
  	ALL_PORTS		= PORT0 | PORT1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
  
  	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
73
  };
5796d1c4c   Jeff Garzik   [libata] Address ...
74
  static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
82ef04fb4   Tejun Heo   libata: make SCR ...
75
76
  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...
77
78
  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...
79
  static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
17234246e   Tejun Heo   sata_via: don't d...
80
  static void svia_noop_freeze(struct ata_port *ap);
a1efdaba2   Tejun Heo   libata: make rese...
81
  static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
a0fcdc025   Jeff Garzik   [libata] Update s...
82
  static int vt6421_pata_cable_detect(struct ata_port *ap);
d73f30e1c   Alan Cox   sata_via: PATA su...
83
84
  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
85

3b7d697df   Jeff Garzik   [libata] constify...
86
  static const struct pci_device_id svia_pci_tbl[] = {
96bc103f4   Luca Pedrielli   sata_via: add PCI...
87
  	{ PCI_VDEVICE(VIA, 0x5337), vt6420 },
b9d5b89b4   Tejun Heo   sata_via: fix sup...
88
89
90
  	{ 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...
91
92
  	{ PCI_VDEVICE(VIA, 0x5372), vt6420 },
  	{ PCI_VDEVICE(VIA, 0x7372), vt6420 },
b9d5b89b4   Tejun Heo   sata_via: fix sup...
93
  	{ PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */
681395202   JosephChan@via.com.tw   sata_via: Add VT8...
94
95
  	{ PCI_VDEVICE(VIA, 0x9000), vt8251 },
  	{ PCI_VDEVICE(VIA, 0x9040), vt8251 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
99
100
101
102
103
  
  	{ }	/* 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...
104
105
106
107
  #ifdef CONFIG_PM
  	.suspend		= ata_pci_device_suspend,
  	.resume			= ata_pci_device_resume,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
  	.remove			= ata_pci_remove_one,
  };
193515d51   Jeff Garzik   [libata] eliminat...
110
  static struct scsi_host_template svia_sht = {
68d1d07b5   Tejun Heo   libata: implement...
111
  	ATA_BMDMA_SHT(DRV_NAME),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  };
b78152e9d   Tejun Heo   sata_via: load DE...
113
  static struct ata_port_operations svia_base_ops = {
029cfd6b7   Tejun Heo   libata: implement...
114
  	.inherits		= &ata_bmdma_port_ops,
b78152e9d   Tejun Heo   sata_via: load DE...
115
116
117
118
119
  	.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...
120
  	.freeze			= svia_noop_freeze,
a1efdaba2   Tejun Heo   libata: make rese...
121
  	.prereset		= vt6420_prereset,
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
122
  };
029cfd6b7   Tejun Heo   libata: implement...
123
  static struct ata_port_operations vt6421_pata_ops = {
b78152e9d   Tejun Heo   sata_via: load DE...
124
  	.inherits		= &svia_base_ops,
029cfd6b7   Tejun Heo   libata: implement...
125
  	.cable_detect		= vt6421_pata_cable_detect,
d73f30e1c   Alan Cox   sata_via: PATA su...
126
127
  	.set_piomode		= vt6421_set_pio_mode,
  	.set_dmamode		= vt6421_set_dma_mode,
d73f30e1c   Alan Cox   sata_via: PATA su...
128
  };
029cfd6b7   Tejun Heo   libata: implement...
129
  static struct ata_port_operations vt6421_sata_ops = {
b78152e9d   Tejun Heo   sata_via: load DE...
130
  	.inherits		= &svia_base_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
  	.scr_read		= svia_scr_read,
  	.scr_write		= svia_scr_write,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
  };
b9d5b89b4   Tejun Heo   sata_via: fix sup...
134
135
136
137
138
139
  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...
140
  static const struct ata_port_info vt6420_port_info = {
cca3974e4   Jeff Garzik   libata: Grand ren...
141
  	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
14bdef982   Erik Inge Bolsø   [libata] convert ...
142
143
  	.pio_mask	= ATA_PIO4,
  	.mwdma_mask	= ATA_MWDMA2,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
144
  	.udma_mask	= ATA_UDMA6,
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
145
  	.port_ops	= &vt6420_sata_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  };
eca25dca1   Tejun Heo   libata: convert d...
147
148
  static struct ata_port_info vt6421_sport_info = {
  	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
14bdef982   Erik Inge Bolsø   [libata] convert ...
149
150
  	.pio_mask	= ATA_PIO4,
  	.mwdma_mask	= ATA_MWDMA2,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
151
  	.udma_mask	= ATA_UDMA6,
eca25dca1   Tejun Heo   libata: convert d...
152
153
154
155
156
  	.port_ops	= &vt6421_sata_ops,
  };
  
  static struct ata_port_info vt6421_pport_info = {
  	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY,
14bdef982   Erik Inge Bolsø   [libata] convert ...
157
158
  	.pio_mask	= ATA_PIO4,
  	/* No MWDMA */
bf6263a85   Jeff Garzik   [libata] Use ATA_...
159
  	.udma_mask	= ATA_UDMA6,
eca25dca1   Tejun Heo   libata: convert d...
160
161
  	.port_ops	= &vt6421_pata_ops,
  };
b9d5b89b4   Tejun Heo   sata_via: fix sup...
162
163
164
  static struct ata_port_info vt8251_port_info = {
  	.flags		= ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS |
  			  ATA_FLAG_NO_LEGACY,
14bdef982   Erik Inge Bolsø   [libata] convert ...
165
166
  	.pio_mask	= ATA_PIO4,
  	.mwdma_mask	= ATA_MWDMA2,
b9d5b89b4   Tejun Heo   sata_via: fix sup...
167
168
169
  	.udma_mask	= ATA_UDMA6,
  	.port_ops	= &vt8251_ops,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
174
  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 ...
175
  static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
  {
  	if (sc_reg > SCR_CONTROL)
da3dbb17a   Tejun Heo   libata: make ->sc...
178
  		return -EINVAL;
82ef04fb4   Tejun Heo   libata: make SCR ...
179
  	*val = ioread32(link->ap->ioaddr.scr_addr + (4 * sc_reg));
da3dbb17a   Tejun Heo   libata: make ->sc...
180
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  }
82ef04fb4   Tejun Heo   libata: make SCR ...
182
  static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
  {
  	if (sc_reg > SCR_CONTROL)
da3dbb17a   Tejun Heo   libata: make ->sc...
185
  		return -EINVAL;
82ef04fb4   Tejun Heo   libata: make SCR ...
186
  	iowrite32(val, link->ap->ioaddr.scr_addr + (4 * sc_reg));
da3dbb17a   Tejun Heo   libata: make ->sc...
187
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  }
b9d5b89b4   Tejun Heo   sata_via: fix sup...
189
190
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
  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...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
  /**
   *	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...
287
288
289
290
291
  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...
292
  	ap->ops->sff_check_status(ap);
9363c3825   Tejun Heo   libata: rename SF...
293
  	ata_sff_irq_clear(ap);
17234246e   Tejun Heo   sata_via: don't d...
294
  }
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
295
296
  /**
   *	vt6420_prereset - prereset for vt6420
cc0680a58   Tejun Heo   libata-link: link...
297
   *	@link: target ATA link
d4b2bab4f   Tejun Heo   libata: add deadl...
298
   *	@deadline: deadline jiffies for the operation
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
   *
   *	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...
315
  static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
316
  {
cc0680a58   Tejun Heo   libata-link: link...
317
  	struct ata_port *ap = link->ap;
9af5c9c97   Tejun Heo   libata-link: intr...
318
  	struct ata_eh_context *ehc = &ap->link.eh_context;
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
319
320
321
322
323
  	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...
324
  	if (!(ap->pflags & ATA_PFLAG_LOADING))
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
325
  		goto skip_scr;
a09060ffe   Jeff Garzik   [libata] sata_sx4...
326
  	/* Resume phy.  This is the old SATA resume sequence */
82ef04fb4   Tejun Heo   libata: make SCR ...
327
328
  	svia_scr_write(link, SCR_CONTROL, 0x300);
  	svia_scr_read(link, SCR_CONTROL, &scontrol); /* flush */
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
329
330
331
332
  
  	/* wait for phy to become ready, if necessary */
  	do {
  		msleep(200);
82ef04fb4   Tejun Heo   libata: make SCR ...
333
  		svia_scr_read(link, SCR_STATUS, &sstatus);
da3dbb17a   Tejun Heo   libata: make ->sc...
334
  		if ((sstatus & 0xf) != 1)
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
335
336
337
338
  			break;
  	} while (time_before(jiffies, timeout));
  
  	/* open code sata_print_link_status() */
82ef04fb4   Tejun Heo   libata: make SCR ...
339
340
  	svia_scr_read(link, SCR_STATUS, &sstatus);
  	svia_scr_read(link, SCR_CONTROL, &scontrol);
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
341
342
343
344
345
346
347
348
349
  
  	online = (sstatus & 0xf) == 0x3;
  
  	ata_port_printk(ap, KERN_INFO,
  			"SATA link %s 1.5 Gbps (SStatus %X SControl %X)
  ",
  			online ? "up" : "down", sstatus, scontrol);
  
  	/* SStatus is read one more time */
82ef04fb4   Tejun Heo   libata: make SCR ...
350
  	svia_scr_read(link, SCR_STATUS, &sstatus);
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
351
352
353
  
  	if (!online) {
  		/* tell EH to bail */
cf4806265   Tejun Heo   libata: prefer ha...
354
  		ehc->i.action &= ~ATA_EH_RESET;
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
355
356
357
358
359
  		return 0;
  	}
  
   skip_scr:
  	/* wait for !BSY */
705e76beb   Tejun Heo   libata: restructu...
360
  	ata_sff_wait_ready(link, deadline);
ac2164d5e   Tejun Heo   [PATCH] sata_via:...
361
362
363
  
  	return 0;
  }
a0fcdc025   Jeff Garzik   [libata] Update s...
364
  static int vt6421_pata_cable_detect(struct ata_port *ap)
d73f30e1c   Alan Cox   sata_via: PATA su...
365
366
367
368
369
370
  {
  	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...
371
372
  		return ATA_CBL_PATA40;
  	return ATA_CBL_PATA80;
d73f30e1c   Alan Cox   sata_via: PATA su...
373
374
375
376
377
378
379
380
381
382
383
384
385
  }
  
  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 };
  	pci_write_config_byte(pdev, PATA_PIO_TIMING, pio_bits[adev->pio_mode - XFER_PIO_0]);
  }
  
  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 };
b4154d4a0   Ondrej Zary   Fix sata_via writ...
386
  	pci_write_config_byte(pdev, PATA_UDMA_TIMING, udma_bits[adev->dma_mode - XFER_UDMA_0]);
d73f30e1c   Alan Cox   sata_via: PATA su...
387
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
390
391
392
393
394
  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 ...
395
  static void __iomem *svia_scr_addr(void __iomem *addr, unsigned int port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
  {
  	return addr + (port * 128);
  }
5796d1c4c   Jeff Garzik   [libata] Address ...
399
  static void __iomem *vt6421_scr_addr(void __iomem *addr, unsigned int port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
402
  {
  	return addr + (port * 64);
  }
eca25dca1   Tejun Heo   libata: convert d...
403
  static void vt6421_init_addrs(struct ata_port *ap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  {
eca25dca1   Tejun Heo   libata: convert d...
405
406
407
408
409
410
411
412
  	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...
413
  		((unsigned long)(reg_addr + 8) | ATA_PCI_CTL_OFS);
eca25dca1   Tejun Heo   libata: convert d...
414
415
  	ioaddr->bmdma_addr = bmdma_addr;
  	ioaddr->scr_addr = vt6421_scr_addr(iomap[5], ap->port_no);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416

9363c3825   Tejun Heo   libata: rename SF...
417
  	ata_sff_std_ports(ioaddr);
cbcdd8759   Tejun Heo   libata: implement...
418
419
420
  
  	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
421
  }
eca25dca1   Tejun Heo   libata: convert d...
422
  static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
  {
eca25dca1   Tejun Heo   libata: convert d...
424
425
426
  	const struct ata_port_info *ppi[] = { &vt6420_port_info, NULL };
  	struct ata_host *host;
  	int rc;
f20b16ff7   Jeff Garzik   [libata] trim tra...
427

9363c3825   Tejun Heo   libata: rename SF...
428
  	rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
eca25dca1   Tejun Heo   libata: convert d...
429
430
431
  	if (rc)
  		return rc;
  	*r_host = host;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432

eca25dca1   Tejun Heo   libata: convert d...
433
434
  	rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
  	if (rc) {
e1be5d73e   Tejun Heo   sata_via: fix res...
435
436
  		dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5
  ");
eca25dca1   Tejun Heo   libata: convert d...
437
  		return rc;
e1be5d73e   Tejun Heo   sata_via: fix res...
438
  	}
eca25dca1   Tejun Heo   libata: convert d...
439
440
  	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
441

eca25dca1   Tejun Heo   libata: convert d...
442
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
  }
eca25dca1   Tejun Heo   libata: convert d...
444
  static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
  {
eca25dca1   Tejun Heo   libata: convert d...
446
447
448
449
450
451
452
453
454
455
456
  	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) {
  		dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host
  ");
  		return -ENOMEM;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457

8fd7d1b16   Tejun Heo   sata_via: pcim_io...
458
  	rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);
eca25dca1   Tejun Heo   libata: convert d...
459
460
461
462
463
464
465
  	if (rc) {
  		dev_printk(KERN_ERR, &pdev->dev, "failed to request/iomap "
  			   "PCI BARs (errno=%d)
  ", rc);
  		return rc;
  	}
  	host->iomap = pcim_iomap_table(pdev);
e1be5d73e   Tejun Heo   sata_via: fix res...
466

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

eca25dca1   Tejun Heo   libata: convert d...
470
471
472
473
474
475
476
477
  	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
478
  }
b9d5b89b4   Tejun Heo   sata_via: fix sup...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
  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;
  
  	rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
  	if (rc)
  		return rc;
  	*r_host = host;
  
  	rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
  	if (rc) {
  		dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5
  ");
  		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;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
505
506
507
  static void svia_configure(struct pci_dev *pdev)
  {
  	u8 tmp8;
  
  	pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
a9524a76f   Jeff Garzik   [libata] use dev_...
508
509
  	dev_printk(KERN_INFO, &pdev->dev, "routed to hard irq line %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
512
513
514
  	       (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
  
  	/* make sure SATA channels are enabled */
  	pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
  	if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
a9524a76f   Jeff Garzik   [libata] use dev_...
515
516
517
  		dev_printk(KERN_DEBUG, &pdev->dev,
  			   "enabling SATA channels (0x%x)
  ",
5796d1c4c   Jeff Garzik   [libata] Address ...
518
  			   (int) tmp8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
520
521
522
523
524
525
  		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) {
a9524a76f   Jeff Garzik   [libata] use dev_...
526
527
528
  		dev_printk(KERN_DEBUG, &pdev->dev,
  			   "enabling SATA channel interrupts (0x%x)
  ",
5796d1c4c   Jeff Garzik   [libata] Address ...
529
  			   (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_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) {
a9524a76f   Jeff Garzik   [libata] use dev_...
537
538
539
  		dev_printk(KERN_DEBUG, &pdev->dev,
  			   "enabling SATA channel native mode (0x%x)
  ",
5796d1c4c   Jeff Garzik   [libata] Address ...
540
  			   (int) tmp8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
  		tmp8 |= NATIVE_MODE_ALL;
  		pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
  	}
  }
5796d1c4c   Jeff Garzik   [libata] Address ...
545
  static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
548
549
  {
  	static int printed_version;
  	unsigned int i;
  	int rc;
f1c22943e   Jeff Garzik   [libata] sata_via...
550
  	struct ata_host *host = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
  	int board_id = (int) ent->driver_data;
b4482a4b2   Al Viro   more trivial sign...
552
  	const unsigned *bar_sizes;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
554
  
  	if (!printed_version++)
a9524a76f   Jeff Garzik   [libata] use dev_...
555
556
  		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557

24dc5f33e   Tejun Heo   libata: update li...
558
  	rc = pcim_enable_device(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
  	if (rc)
  		return rc;
b9d5b89b4   Tejun Heo   sata_via: fix sup...
561
  	if (board_id == vt6421)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  		bar_sizes = &vt6421_bar_sizes[0];
b9d5b89b4   Tejun Heo   sata_via: fix sup...
563
564
  	else
  		bar_sizes = &svia_bar_sizes[0];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
566
567
568
  
  	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])) {
a9524a76f   Jeff Garzik   [libata] use dev_...
569
  			dev_printk(KERN_ERR, &pdev->dev,
e29419fff   Greg Kroah-Hartman   [PATCH] 64bit res...
570
571
572
  				"invalid PCI BAR %u (sz 0x%llx, val 0x%llx)
  ",
  				i,
5796d1c4c   Jeff Garzik   [libata] Address ...
573
574
  				(unsigned long long)pci_resource_start(pdev, i),
  				(unsigned long long)pci_resource_len(pdev, i));
24dc5f33e   Tejun Heo   libata: update li...
575
  			return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  		}
b9d5b89b4   Tejun Heo   sata_via: fix sup...
577
578
  	switch (board_id) {
  	case vt6420:
eca25dca1   Tejun Heo   libata: convert d...
579
  		rc = vt6420_prepare_host(pdev, &host);
b9d5b89b4   Tejun Heo   sata_via: fix sup...
580
581
  		break;
  	case vt6421:
eca25dca1   Tejun Heo   libata: convert d...
582
  		rc = vt6421_prepare_host(pdev, &host);
b9d5b89b4   Tejun Heo   sata_via: fix sup...
583
584
585
586
587
  		break;
  	case vt8251:
  		rc = vt8251_prepare_host(pdev, &host);
  		break;
  	default:
554d491de   Marcin Slusarz   sata_via: restore...
588
  		rc = -EINVAL;
b9d5b89b4   Tejun Heo   sata_via: fix sup...
589
  	}
554d491de   Marcin Slusarz   sata_via: restore...
590
591
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
594
595
  
  	svia_configure(pdev);
  
  	pci_set_master(pdev);
9363c3825   Tejun Heo   libata: rename SF...
596
597
  	return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
  				 IRQF_SHARED, &svia_sht);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
599
600
601
  }
  
  static int __init svia_init(void)
  {
b7887196e   Pavel Roskin   [PATCH] libata: r...
602
  	return pci_register_driver(&svia_pci_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
606
607
608
609
610
611
  }
  
  static void __exit svia_exit(void)
  {
  	pci_unregister_driver(&svia_pci_driver);
  }
  
  module_init(svia_init);
  module_exit(svia_exit);