aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sata_via.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sata_via.c')
-rw-r--r--drivers/scsi/sata_via.c387
1 files changed, 387 insertions, 0 deletions
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
new file mode 100644
index 000000000000..3a7830667277
--- /dev/null
+++ b/drivers/scsi/sata_via.c
@@ -0,0 +1,387 @@
1/*
2 sata_via.c - VIA Serial ATA controllers
3
4 Maintained by: Jeff Garzik <jgarzik@pobox.com>
5 Please ALWAYS copy linux-ide@vger.kernel.org
6 on emails.
7
8 Copyright 2003-2004 Red Hat, Inc. All rights reserved.
9 Copyright 2003-2004 Jeff Garzik
10
11 The contents of this file are subject to the Open
12 Software License version 1.1 that can be found at
13 http://www.opensource.org/licenses/osl-1.1.txt and is included herein
14 by reference.
15
16 Alternatively, the contents of this file may be used under the terms
17 of the GNU General Public License version 2 (the "GPL") as distributed
18 in the kernel source COPYING file, in which case the provisions of
19 the GPL are applicable instead of the above. If you wish to allow
20 the use of your version of this file only under the terms of the
21 GPL and not to allow others to use your version of this file under
22 the OSL, indicate your decision by deleting the provisions above and
23 replace them with the notice and other provisions required by the GPL.
24 If you do not delete the provisions above, a recipient may use your
25 version of this file under either the OSL or the GPL.
26
27 ----------------------------------------------------------------------
28
29 To-do list:
30 * VT6421 PATA support
31
32 */
33
34#include <linux/kernel.h>
35#include <linux/module.h>
36#include <linux/pci.h>
37#include <linux/init.h>
38#include <linux/blkdev.h>
39#include <linux/delay.h>
40#include "scsi.h"
41#include <scsi/scsi_host.h>
42#include <linux/libata.h>
43#include <asm/io.h>
44
45#define DRV_NAME "sata_via"
46#define DRV_VERSION "1.1"
47
48enum board_ids_enum {
49 vt6420,
50 vt6421,
51};
52
53enum {
54 SATA_CHAN_ENAB = 0x40, /* SATA channel enable */
55 SATA_INT_GATE = 0x41, /* SATA interrupt gating */
56 SATA_NATIVE_MODE = 0x42, /* Native mode enable */
57 SATA_PATA_SHARING = 0x49, /* PATA/SATA sharing func ctrl */
58
59 PORT0 = (1 << 1),
60 PORT1 = (1 << 0),
61 ALL_PORTS = PORT0 | PORT1,
62 N_PORTS = 2,
63
64 NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
65
66 SATA_EXT_PHY = (1 << 6), /* 0==use PATA, 1==ext phy */
67 SATA_2DEV = (1 << 5), /* SATA is master/slave */
68};
69
70static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
71static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
72static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
73
74static struct pci_device_id svia_pci_tbl[] = {
75 { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
76 { 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 },
77
78 { } /* terminate list */
79};
80
81static struct pci_driver svia_pci_driver = {
82 .name = DRV_NAME,
83 .id_table = svia_pci_tbl,
84 .probe = svia_init_one,
85 .remove = ata_pci_remove_one,
86};
87
88static Scsi_Host_Template svia_sht = {
89 .module = THIS_MODULE,
90 .name = DRV_NAME,
91 .ioctl = ata_scsi_ioctl,
92 .queuecommand = ata_scsi_queuecmd,
93 .eh_strategy_handler = ata_scsi_error,
94 .can_queue = ATA_DEF_QUEUE,
95 .this_id = ATA_SHT_THIS_ID,
96 .sg_tablesize = LIBATA_MAX_PRD,
97 .max_sectors = ATA_MAX_SECTORS,
98 .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
99 .emulated = ATA_SHT_EMULATED,
100 .use_clustering = ATA_SHT_USE_CLUSTERING,
101 .proc_name = DRV_NAME,
102 .dma_boundary = ATA_DMA_BOUNDARY,
103 .slave_configure = ata_scsi_slave_config,
104 .bios_param = ata_std_bios_param,
105 .ordered_flush = 1,
106};
107
108static struct ata_port_operations svia_sata_ops = {
109 .port_disable = ata_port_disable,
110
111 .tf_load = ata_tf_load,
112 .tf_read = ata_tf_read,
113 .check_status = ata_check_status,
114 .exec_command = ata_exec_command,
115 .dev_select = ata_std_dev_select,
116
117 .phy_reset = sata_phy_reset,
118
119 .bmdma_setup = ata_bmdma_setup,
120 .bmdma_start = ata_bmdma_start,
121 .bmdma_stop = ata_bmdma_stop,
122 .bmdma_status = ata_bmdma_status,
123
124 .qc_prep = ata_qc_prep,
125 .qc_issue = ata_qc_issue_prot,
126
127 .eng_timeout = ata_eng_timeout,
128
129 .irq_handler = ata_interrupt,
130 .irq_clear = ata_bmdma_irq_clear,
131
132 .scr_read = svia_scr_read,
133 .scr_write = svia_scr_write,
134
135 .port_start = ata_port_start,
136 .port_stop = ata_port_stop,
137};
138
139static struct ata_port_info svia_port_info = {
140 .sht = &svia_sht,
141 .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY,
142 .pio_mask = 0x1f,
143 .mwdma_mask = 0x07,
144 .udma_mask = 0x7f,
145 .port_ops = &svia_sata_ops,
146};
147
148MODULE_AUTHOR("Jeff Garzik");
149MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
150MODULE_LICENSE("GPL");
151MODULE_DEVICE_TABLE(pci, svia_pci_tbl);
152MODULE_VERSION(DRV_VERSION);
153
154static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg)
155{
156 if (sc_reg > SCR_CONTROL)
157 return 0xffffffffU;
158 return inl(ap->ioaddr.scr_addr + (4 * sc_reg));
159}
160
161static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
162{
163 if (sc_reg > SCR_CONTROL)
164 return;
165 outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
166}
167
168static const unsigned int svia_bar_sizes[] = {
169 8, 4, 8, 4, 16, 256
170};
171
172static const unsigned int vt6421_bar_sizes[] = {
173 16, 16, 16, 16, 32, 128
174};
175
176static unsigned long svia_scr_addr(unsigned long addr, unsigned int port)
177{
178 return addr + (port * 128);
179}
180
181static unsigned long vt6421_scr_addr(unsigned long addr, unsigned int port)
182{
183 return addr + (port * 64);
184}
185
186static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
187 struct pci_dev *pdev,
188 unsigned int port)
189{
190 unsigned long reg_addr = pci_resource_start(pdev, port);
191 unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (port * 8);
192 unsigned long scr_addr;
193
194 probe_ent->port[port].cmd_addr = reg_addr;
195 probe_ent->port[port].altstatus_addr =
196 probe_ent->port[port].ctl_addr = (reg_addr + 8) | ATA_PCI_CTL_OFS;
197 probe_ent->port[port].bmdma_addr = bmdma_addr;
198
199 scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port);
200 probe_ent->port[port].scr_addr = scr_addr;
201
202 ata_std_ports(&probe_ent->port[port]);
203}
204
205static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
206{
207 struct ata_probe_ent *probe_ent;
208 struct ata_port_info *ppi = &svia_port_info;
209
210 probe_ent = ata_pci_init_native_mode(pdev, &ppi);
211 if (!probe_ent)
212 return NULL;
213
214 probe_ent->port[0].scr_addr =
215 svia_scr_addr(pci_resource_start(pdev, 5), 0);
216 probe_ent->port[1].scr_addr =
217 svia_scr_addr(pci_resource_start(pdev, 5), 1);
218
219 return probe_ent;
220}
221
222static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
223{
224 struct ata_probe_ent *probe_ent;
225 unsigned int i;
226
227 probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
228 if (!probe_ent)
229 return NULL;
230
231 memset(probe_ent, 0, sizeof(*probe_ent));
232 probe_ent->dev = pci_dev_to_dev(pdev);
233 INIT_LIST_HEAD(&probe_ent->node);
234
235 probe_ent->sht = &svia_sht;
236 probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
237 ATA_FLAG_NO_LEGACY;
238 probe_ent->port_ops = &svia_sata_ops;
239 probe_ent->n_ports = N_PORTS;
240 probe_ent->irq = pdev->irq;
241 probe_ent->irq_flags = SA_SHIRQ;
242 probe_ent->pio_mask = 0x1f;
243 probe_ent->mwdma_mask = 0x07;
244 probe_ent->udma_mask = 0x7f;
245
246 for (i = 0; i < N_PORTS; i++)
247 vt6421_init_addrs(probe_ent, pdev, i);
248
249 return probe_ent;
250}
251
252static void svia_configure(struct pci_dev *pdev)
253{
254 u8 tmp8;
255
256 pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
257 printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n",
258 pci_name(pdev),
259 (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
260
261 /* make sure SATA channels are enabled */
262 pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
263 if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
264 printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n",
265 pci_name(pdev), (int) tmp8);
266 tmp8 |= ALL_PORTS;
267 pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
268 }
269
270 /* make sure interrupts for each channel sent to us */
271 pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
272 if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
273 printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n",
274 pci_name(pdev), (int) tmp8);
275 tmp8 |= ALL_PORTS;
276 pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
277 }
278
279 /* make sure native mode is enabled */
280 pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
281 if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
282 printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n",
283 pci_name(pdev), (int) tmp8);
284 tmp8 |= NATIVE_MODE_ALL;
285 pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
286 }
287}
288
289static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
290{
291 static int printed_version;
292 unsigned int i;
293 int rc;
294 struct ata_probe_ent *probe_ent;
295 int board_id = (int) ent->driver_data;
296 const int *bar_sizes;
297 int pci_dev_busy = 0;
298 u8 tmp8;
299
300 if (!printed_version++)
301 printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
302
303 rc = pci_enable_device(pdev);
304 if (rc)
305 return rc;
306
307 rc = pci_request_regions(pdev, DRV_NAME);
308 if (rc) {
309 pci_dev_busy = 1;
310 goto err_out;
311 }
312
313 if (board_id == vt6420) {
314 pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
315 if (tmp8 & SATA_2DEV) {
316 printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n",
317 pci_name(pdev), (int) tmp8);
318 rc = -EIO;
319 goto err_out_regions;
320 }
321
322 bar_sizes = &svia_bar_sizes[0];
323 } else {
324 bar_sizes = &vt6421_bar_sizes[0];
325 }
326
327 for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
328 if ((pci_resource_start(pdev, i) == 0) ||
329 (pci_resource_len(pdev, i) < bar_sizes[i])) {
330 printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n",
331 pci_name(pdev), i,
332 pci_resource_start(pdev, i),
333 pci_resource_len(pdev, i));
334 rc = -ENODEV;
335 goto err_out_regions;
336 }
337
338 rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
339 if (rc)
340 goto err_out_regions;
341 rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
342 if (rc)
343 goto err_out_regions;
344
345 if (board_id == vt6420)
346 probe_ent = vt6420_init_probe_ent(pdev);
347 else
348 probe_ent = vt6421_init_probe_ent(pdev);
349
350 if (!probe_ent) {
351 printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
352 pci_name(pdev));
353 rc = -ENOMEM;
354 goto err_out_regions;
355 }
356
357 svia_configure(pdev);
358
359 pci_set_master(pdev);
360
361 /* FIXME: check ata_device_add return value */
362 ata_device_add(probe_ent);
363 kfree(probe_ent);
364
365 return 0;
366
367err_out_regions:
368 pci_release_regions(pdev);
369err_out:
370 if (!pci_dev_busy)
371 pci_disable_device(pdev);
372 return rc;
373}
374
375static int __init svia_init(void)
376{
377 return pci_module_init(&svia_pci_driver);
378}
379
380static void __exit svia_exit(void)
381{
382 pci_unregister_driver(&svia_pci_driver);
383}
384
385module_init(svia_init);
386module_exit(svia_exit);
387