diff options
Diffstat (limited to 'drivers/ata/pata_opti.c')
-rw-r--r-- | drivers/ata/pata_opti.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c new file mode 100644 index 000000000000..c3d01325e0e2 --- /dev/null +++ b/drivers/ata/pata_opti.c | |||
@@ -0,0 +1,292 @@ | |||
1 | /* | ||
2 | * pata_opti.c - ATI PATA for new ATA layer | ||
3 | * (C) 2005 Red Hat Inc | ||
4 | * Alan Cox <alan@redhat.com> | ||
5 | * | ||
6 | * Based on | ||
7 | * linux/drivers/ide/pci/opti621.c Version 0.7 Sept 10, 2002 | ||
8 | * | ||
9 | * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) | ||
10 | * | ||
11 | * Authors: | ||
12 | * Jaromir Koutek <miri@punknet.cz>, | ||
13 | * Jan Harkes <jaharkes@cwi.nl>, | ||
14 | * Mark Lord <mlord@pobox.com> | ||
15 | * Some parts of code are from ali14xx.c and from rz1000.c. | ||
16 | * | ||
17 | * Also consulted the FreeBSD prototype driver by Kevin Day to try | ||
18 | * and resolve some confusions. Further documentation can be found in | ||
19 | * Ralf Brown's interrupt list | ||
20 | * | ||
21 | * If you have other variants of the Opti range (Viper/Vendetta) please | ||
22 | * try this driver with those PCI idents and report back. For the later | ||
23 | * chips see the pata_optidma driver | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/pci.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/blkdev.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <scsi/scsi_host.h> | ||
34 | #include <linux/libata.h> | ||
35 | |||
36 | #define DRV_NAME "pata_opti" | ||
37 | #define DRV_VERSION "0.2.4" | ||
38 | |||
39 | enum { | ||
40 | READ_REG = 0, /* index of Read cycle timing register */ | ||
41 | WRITE_REG = 1, /* index of Write cycle timing register */ | ||
42 | CNTRL_REG = 3, /* index of Control register */ | ||
43 | STRAP_REG = 5, /* index of Strap register */ | ||
44 | MISC_REG = 6 /* index of Miscellaneous register */ | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * opti_pre_reset - probe begin | ||
49 | * @ap: ATA port | ||
50 | * | ||
51 | * Set up cable type and use generic probe init | ||
52 | */ | ||
53 | |||
54 | static int opti_pre_reset(struct ata_port *ap) | ||
55 | { | ||
56 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
57 | static const struct pci_bits opti_enable_bits[] = { | ||
58 | { 0x45, 1, 0x80, 0x00 }, | ||
59 | { 0x40, 1, 0x08, 0x00 } | ||
60 | }; | ||
61 | |||
62 | if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no])) { | ||
63 | ata_port_disable(ap); | ||
64 | printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); | ||
65 | return 0; | ||
66 | } | ||
67 | ap->cbl = ATA_CBL_PATA40; | ||
68 | return ata_std_prereset(ap); | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * opti_probe_reset - probe reset | ||
73 | * @ap: ATA port | ||
74 | * | ||
75 | * Perform the ATA probe and bus reset sequence plus specific handling | ||
76 | * for this hardware. The Opti needs little handling - we have no UDMA66 | ||
77 | * capability that needs cable detection. All we must do is check the port | ||
78 | * is enabled. | ||
79 | */ | ||
80 | |||
81 | static void opti_error_handler(struct ata_port *ap) | ||
82 | { | ||
83 | ata_bmdma_drive_eh(ap, opti_pre_reset, ata_std_softreset, NULL, ata_std_postreset); | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * opti_write_reg - control register setup | ||
88 | * @ap: ATA port | ||
89 | * @value: value | ||
90 | * @reg: control register number | ||
91 | * | ||
92 | * The Opti uses magic 'trapdoor' register accesses to do configuration | ||
93 | * rather than using PCI space as other controllers do. The double inw | ||
94 | * on the error register activates configuration mode. We can then write | ||
95 | * the control register | ||
96 | */ | ||
97 | |||
98 | static void opti_write_reg(struct ata_port *ap, u8 val, int reg) | ||
99 | { | ||
100 | unsigned long regio = ap->ioaddr.cmd_addr; | ||
101 | |||
102 | /* These 3 unlock the control register access */ | ||
103 | inw(regio + 1); | ||
104 | inw(regio + 1); | ||
105 | outb(3, regio + 2); | ||
106 | |||
107 | /* Do the I/O */ | ||
108 | outb(val, regio + reg); | ||
109 | |||
110 | /* Relock */ | ||
111 | outb(0x83, regio + 2); | ||
112 | } | ||
113 | |||
114 | #if 0 | ||
115 | /** | ||
116 | * opti_read_reg - control register read | ||
117 | * @ap: ATA port | ||
118 | * @reg: control register number | ||
119 | * | ||
120 | * The Opti uses magic 'trapdoor' register accesses to do configuration | ||
121 | * rather than using PCI space as other controllers do. The double inw | ||
122 | * on the error register activates configuration mode. We can then read | ||
123 | * the control register | ||
124 | */ | ||
125 | |||
126 | static u8 opti_read_reg(struct ata_port *ap, int reg) | ||
127 | { | ||
128 | unsigned long regio = ap->ioaddr.cmd_addr; | ||
129 | u8 ret; | ||
130 | inw(regio + 1); | ||
131 | inw(regio + 1); | ||
132 | outb(3, regio + 2); | ||
133 | ret = inb(regio + reg); | ||
134 | outb(0x83, regio + 2); | ||
135 | } | ||
136 | #endif | ||
137 | |||
138 | /** | ||
139 | * opti_set_piomode - set initial PIO mode data | ||
140 | * @ap: ATA interface | ||
141 | * @adev: ATA device | ||
142 | * | ||
143 | * Called to do the PIO mode setup. Timing numbers are taken from | ||
144 | * the FreeBSD driver then pre computed to keep the code clean. There | ||
145 | * are two tables depending on the hardware clock speed. | ||
146 | */ | ||
147 | |||
148 | static void opti_set_piomode(struct ata_port *ap, struct ata_device *adev) | ||
149 | { | ||
150 | struct ata_device *pair = ata_dev_pair(adev); | ||
151 | int clock; | ||
152 | int pio = adev->pio_mode - XFER_PIO_0; | ||
153 | unsigned long regio = ap->ioaddr.cmd_addr; | ||
154 | u8 addr; | ||
155 | |||
156 | /* Address table precomputed with prefetch off and a DCLK of 2 */ | ||
157 | static const u8 addr_timing[2][5] = { | ||
158 | { 0x30, 0x20, 0x20, 0x10, 0x10 }, | ||
159 | { 0x20, 0x20, 0x10, 0x10, 0x10 } | ||
160 | }; | ||
161 | static const u8 data_rec_timing[2][5] = { | ||
162 | { 0x6B, 0x56, 0x42, 0x32, 0x31 }, | ||
163 | { 0x58, 0x44, 0x32, 0x22, 0x21 } | ||
164 | }; | ||
165 | |||
166 | outb(0xff, regio + 5); | ||
167 | clock = inw(regio + 5) & 1; | ||
168 | |||
169 | /* | ||
170 | * As with many controllers the address setup time is shared | ||
171 | * and must suit both devices if present. | ||
172 | */ | ||
173 | |||
174 | addr = addr_timing[clock][pio]; | ||
175 | if (pair) { | ||
176 | /* Hardware constraint */ | ||
177 | u8 pair_addr = addr_timing[clock][pair->pio_mode - XFER_PIO_0]; | ||
178 | if (pair_addr > addr) | ||
179 | addr = pair_addr; | ||
180 | } | ||
181 | |||
182 | /* Commence primary programming sequence */ | ||
183 | opti_write_reg(ap, adev->devno, MISC_REG); | ||
184 | opti_write_reg(ap, data_rec_timing[clock][pio], READ_REG); | ||
185 | opti_write_reg(ap, data_rec_timing[clock][pio], WRITE_REG); | ||
186 | opti_write_reg(ap, addr, MISC_REG); | ||
187 | |||
188 | /* Programming sequence complete, override strapping */ | ||
189 | opti_write_reg(ap, 0x85, CNTRL_REG); | ||
190 | } | ||
191 | |||
192 | static struct scsi_host_template opti_sht = { | ||
193 | .module = THIS_MODULE, | ||
194 | .name = DRV_NAME, | ||
195 | .ioctl = ata_scsi_ioctl, | ||
196 | .queuecommand = ata_scsi_queuecmd, | ||
197 | .can_queue = ATA_DEF_QUEUE, | ||
198 | .this_id = ATA_SHT_THIS_ID, | ||
199 | .sg_tablesize = LIBATA_MAX_PRD, | ||
200 | .max_sectors = ATA_MAX_SECTORS, | ||
201 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | ||
202 | .emulated = ATA_SHT_EMULATED, | ||
203 | .use_clustering = ATA_SHT_USE_CLUSTERING, | ||
204 | .proc_name = DRV_NAME, | ||
205 | .dma_boundary = ATA_DMA_BOUNDARY, | ||
206 | .slave_configure = ata_scsi_slave_config, | ||
207 | .bios_param = ata_std_bios_param, | ||
208 | }; | ||
209 | |||
210 | static struct ata_port_operations opti_port_ops = { | ||
211 | .port_disable = ata_port_disable, | ||
212 | .set_piomode = opti_set_piomode, | ||
213 | /* .set_dmamode = opti_set_dmamode, */ | ||
214 | .tf_load = ata_tf_load, | ||
215 | .tf_read = ata_tf_read, | ||
216 | .check_status = ata_check_status, | ||
217 | .exec_command = ata_exec_command, | ||
218 | .dev_select = ata_std_dev_select, | ||
219 | |||
220 | .freeze = ata_bmdma_freeze, | ||
221 | .thaw = ata_bmdma_thaw, | ||
222 | .error_handler = opti_error_handler, | ||
223 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
224 | |||
225 | .bmdma_setup = ata_bmdma_setup, | ||
226 | .bmdma_start = ata_bmdma_start, | ||
227 | .bmdma_stop = ata_bmdma_stop, | ||
228 | .bmdma_status = ata_bmdma_status, | ||
229 | |||
230 | .qc_prep = ata_qc_prep, | ||
231 | .qc_issue = ata_qc_issue_prot, | ||
232 | .eng_timeout = ata_eng_timeout, | ||
233 | .data_xfer = ata_pio_data_xfer, | ||
234 | |||
235 | .irq_handler = ata_interrupt, | ||
236 | .irq_clear = ata_bmdma_irq_clear, | ||
237 | |||
238 | .port_start = ata_port_start, | ||
239 | .port_stop = ata_port_stop, | ||
240 | .host_stop = ata_host_stop | ||
241 | }; | ||
242 | |||
243 | static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id) | ||
244 | { | ||
245 | static struct ata_port_info info = { | ||
246 | .sht = &opti_sht, | ||
247 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | ||
248 | .pio_mask = 0x1f, | ||
249 | .port_ops = &opti_port_ops | ||
250 | }; | ||
251 | static struct ata_port_info *port_info[2] = { &info, &info }; | ||
252 | static int printed_version; | ||
253 | |||
254 | if (!printed_version++) | ||
255 | dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); | ||
256 | |||
257 | return ata_pci_init_one(dev, port_info, 2); | ||
258 | } | ||
259 | |||
260 | static const struct pci_device_id opti[] = { | ||
261 | { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
262 | { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, | ||
263 | { 0, }, | ||
264 | }; | ||
265 | |||
266 | static struct pci_driver opti_pci_driver = { | ||
267 | .name = DRV_NAME, | ||
268 | .id_table = opti, | ||
269 | .probe = opti_init_one, | ||
270 | .remove = ata_pci_remove_one | ||
271 | }; | ||
272 | |||
273 | static int __init opti_init(void) | ||
274 | { | ||
275 | return pci_register_driver(&opti_pci_driver); | ||
276 | } | ||
277 | |||
278 | |||
279 | static void __exit opti_exit(void) | ||
280 | { | ||
281 | pci_unregister_driver(&opti_pci_driver); | ||
282 | } | ||
283 | |||
284 | |||
285 | MODULE_AUTHOR("Alan Cox"); | ||
286 | MODULE_DESCRIPTION("low-level driver for Opti 621/621X"); | ||
287 | MODULE_LICENSE("GPL"); | ||
288 | MODULE_DEVICE_TABLE(pci, opti); | ||
289 | MODULE_VERSION(DRV_VERSION); | ||
290 | |||
291 | module_init(opti_init); | ||
292 | module_exit(opti_exit); | ||