Commit | Line | Data |
---|---|---|
1fdffbce JG |
1 | /* |
2 | * libata-bmdma.c - helper library for PCI IDE BMDMA | |
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-2006 Red Hat, Inc. All rights reserved. | |
9 | * Copyright 2003-2006 Jeff Garzik | |
10 | * | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU General Public License as published by | |
14 | * the Free Software Foundation; either version 2, or (at your option) | |
15 | * any later version. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License | |
23 | * along with this program; see the file COPYING. If not, write to | |
24 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
25 | * | |
26 | * | |
27 | * libata documentation is available via 'make {ps|pdf}docs', | |
28 | * as Documentation/DocBook/libata.* | |
29 | * | |
30 | * Hardware documentation available from http://www.t13.org/ and | |
31 | * http://www.sata-io.org/ | |
32 | * | |
33 | */ | |
34 | ||
35 | #include <linux/config.h> | |
36 | #include <linux/kernel.h> | |
37 | #include <linux/pci.h> | |
38 | #include <linux/libata.h> | |
39 | ||
40 | #include "libata.h" | |
41 | ||
42 | /** | |
43 | * ata_tf_load_pio - send taskfile registers to host controller | |
44 | * @ap: Port to which output is sent | |
45 | * @tf: ATA taskfile register set | |
46 | * | |
47 | * Outputs ATA taskfile to standard ATA host controller. | |
48 | * | |
49 | * LOCKING: | |
50 | * Inherited from caller. | |
51 | */ | |
52 | ||
53 | static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf) | |
54 | { | |
55 | struct ata_ioports *ioaddr = &ap->ioaddr; | |
56 | unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; | |
57 | ||
58 | if (tf->ctl != ap->last_ctl) { | |
59 | outb(tf->ctl, ioaddr->ctl_addr); | |
60 | ap->last_ctl = tf->ctl; | |
61 | ata_wait_idle(ap); | |
62 | } | |
63 | ||
64 | if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { | |
65 | outb(tf->hob_feature, ioaddr->feature_addr); | |
66 | outb(tf->hob_nsect, ioaddr->nsect_addr); | |
67 | outb(tf->hob_lbal, ioaddr->lbal_addr); | |
68 | outb(tf->hob_lbam, ioaddr->lbam_addr); | |
69 | outb(tf->hob_lbah, ioaddr->lbah_addr); | |
70 | VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", | |
71 | tf->hob_feature, | |
72 | tf->hob_nsect, | |
73 | tf->hob_lbal, | |
74 | tf->hob_lbam, | |
75 | tf->hob_lbah); | |
76 | } | |
77 | ||
78 | if (is_addr) { | |
79 | outb(tf->feature, ioaddr->feature_addr); | |
80 | outb(tf->nsect, ioaddr->nsect_addr); | |
81 | outb(tf->lbal, ioaddr->lbal_addr); | |
82 | outb(tf->lbam, ioaddr->lbam_addr); | |
83 | outb(tf->lbah, ioaddr->lbah_addr); | |
84 | VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", | |
85 | tf->feature, | |
86 | tf->nsect, | |
87 | tf->lbal, | |
88 | tf->lbam, | |
89 | tf->lbah); | |
90 | } | |
91 | ||
92 | if (tf->flags & ATA_TFLAG_DEVICE) { | |
93 | outb(tf->device, ioaddr->device_addr); | |
94 | VPRINTK("device 0x%X\n", tf->device); | |
95 | } | |
96 | ||
97 | ata_wait_idle(ap); | |
98 | } | |
99 | ||
100 | /** | |
101 | * ata_tf_load_mmio - send taskfile registers to host controller | |
102 | * @ap: Port to which output is sent | |
103 | * @tf: ATA taskfile register set | |
104 | * | |
105 | * Outputs ATA taskfile to standard ATA host controller using MMIO. | |
106 | * | |
107 | * LOCKING: | |
108 | * Inherited from caller. | |
109 | */ | |
110 | ||
111 | static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) | |
112 | { | |
113 | struct ata_ioports *ioaddr = &ap->ioaddr; | |
114 | unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; | |
115 | ||
116 | if (tf->ctl != ap->last_ctl) { | |
117 | writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr); | |
118 | ap->last_ctl = tf->ctl; | |
119 | ata_wait_idle(ap); | |
120 | } | |
121 | ||
122 | if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { | |
123 | writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr); | |
124 | writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr); | |
125 | writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr); | |
126 | writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr); | |
127 | writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr); | |
128 | VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", | |
129 | tf->hob_feature, | |
130 | tf->hob_nsect, | |
131 | tf->hob_lbal, | |
132 | tf->hob_lbam, | |
133 | tf->hob_lbah); | |
134 | } | |
135 | ||
136 | if (is_addr) { | |
137 | writeb(tf->feature, (void __iomem *) ioaddr->feature_addr); | |
138 | writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr); | |
139 | writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr); | |
140 | writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr); | |
141 | writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr); | |
142 | VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", | |
143 | tf->feature, | |
144 | tf->nsect, | |
145 | tf->lbal, | |
146 | tf->lbam, | |
147 | tf->lbah); | |
148 | } | |
149 | ||
150 | if (tf->flags & ATA_TFLAG_DEVICE) { | |
151 | writeb(tf->device, (void __iomem *) ioaddr->device_addr); | |
152 | VPRINTK("device 0x%X\n", tf->device); | |
153 | } | |
154 | ||
155 | ata_wait_idle(ap); | |
156 | } | |
157 | ||
158 | ||
159 | /** | |
160 | * ata_tf_load - send taskfile registers to host controller | |
161 | * @ap: Port to which output is sent | |
162 | * @tf: ATA taskfile register set | |
163 | * | |
164 | * Outputs ATA taskfile to standard ATA host controller using MMIO | |
165 | * or PIO as indicated by the ATA_FLAG_MMIO flag. | |
166 | * Writes the control, feature, nsect, lbal, lbam, and lbah registers. | |
167 | * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect, | |
168 | * hob_lbal, hob_lbam, and hob_lbah. | |
169 | * | |
170 | * This function waits for idle (!BUSY and !DRQ) after writing | |
171 | * registers. If the control register has a new value, this | |
172 | * function also waits for idle after writing control and before | |
173 | * writing the remaining registers. | |
174 | * | |
175 | * May be used as the tf_load() entry in ata_port_operations. | |
176 | * | |
177 | * LOCKING: | |
178 | * Inherited from caller. | |
179 | */ | |
180 | void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) | |
181 | { | |
182 | if (ap->flags & ATA_FLAG_MMIO) | |
183 | ata_tf_load_mmio(ap, tf); | |
184 | else | |
185 | ata_tf_load_pio(ap, tf); | |
186 | } | |
187 | ||
188 | /** | |
189 | * ata_exec_command_pio - issue ATA command to host controller | |
190 | * @ap: port to which command is being issued | |
191 | * @tf: ATA taskfile register set | |
192 | * | |
193 | * Issues PIO write to ATA command register, with proper | |
194 | * synchronization with interrupt handler / other threads. | |
195 | * | |
196 | * LOCKING: | |
197 | * spin_lock_irqsave(host_set lock) | |
198 | */ | |
199 | ||
200 | static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf) | |
201 | { | |
202 | DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); | |
203 | ||
204 | outb(tf->command, ap->ioaddr.command_addr); | |
205 | ata_pause(ap); | |
206 | } | |
207 | ||
208 | ||
209 | /** | |
210 | * ata_exec_command_mmio - issue ATA command to host controller | |
211 | * @ap: port to which command is being issued | |
212 | * @tf: ATA taskfile register set | |
213 | * | |
214 | * Issues MMIO write to ATA command register, with proper | |
215 | * synchronization with interrupt handler / other threads. | |
216 | * | |
217 | * LOCKING: | |
218 | * spin_lock_irqsave(host_set lock) | |
219 | */ | |
220 | ||
221 | static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf) | |
222 | { | |
223 | DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); | |
224 | ||
225 | writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr); | |
226 | ata_pause(ap); | |
227 | } | |
228 | ||
229 | ||
230 | /** | |
231 | * ata_exec_command - issue ATA command to host controller | |
232 | * @ap: port to which command is being issued | |
233 | * @tf: ATA taskfile register set | |
234 | * | |
235 | * Issues PIO/MMIO write to ATA command register, with proper | |
236 | * synchronization with interrupt handler / other threads. | |
237 | * | |
238 | * LOCKING: | |
239 | * spin_lock_irqsave(host_set lock) | |
240 | */ | |
241 | void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) | |
242 | { | |
243 | if (ap->flags & ATA_FLAG_MMIO) | |
244 | ata_exec_command_mmio(ap, tf); | |
245 | else | |
246 | ata_exec_command_pio(ap, tf); | |
247 | } | |
248 | ||
249 | /** | |
250 | * ata_tf_read_pio - input device's ATA taskfile shadow registers | |
251 | * @ap: Port from which input is read | |
252 | * @tf: ATA taskfile register set for storing input | |
253 | * | |
254 | * Reads ATA taskfile registers for currently-selected device | |
255 | * into @tf. | |
256 | * | |
257 | * LOCKING: | |
258 | * Inherited from caller. | |
259 | */ | |
260 | ||
261 | static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf) | |
262 | { | |
263 | struct ata_ioports *ioaddr = &ap->ioaddr; | |
264 | ||
265 | tf->command = ata_check_status(ap); | |
266 | tf->feature = inb(ioaddr->error_addr); | |
267 | tf->nsect = inb(ioaddr->nsect_addr); | |
268 | tf->lbal = inb(ioaddr->lbal_addr); | |
269 | tf->lbam = inb(ioaddr->lbam_addr); | |
270 | tf->lbah = inb(ioaddr->lbah_addr); | |
271 | tf->device = inb(ioaddr->device_addr); | |
272 | ||
273 | if (tf->flags & ATA_TFLAG_LBA48) { | |
274 | outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr); | |
275 | tf->hob_feature = inb(ioaddr->error_addr); | |
276 | tf->hob_nsect = inb(ioaddr->nsect_addr); | |
277 | tf->hob_lbal = inb(ioaddr->lbal_addr); | |
278 | tf->hob_lbam = inb(ioaddr->lbam_addr); | |
279 | tf->hob_lbah = inb(ioaddr->lbah_addr); | |
280 | } | |
281 | } | |
282 | ||
283 | /** | |
284 | * ata_tf_read_mmio - input device's ATA taskfile shadow registers | |
285 | * @ap: Port from which input is read | |
286 | * @tf: ATA taskfile register set for storing input | |
287 | * | |
288 | * Reads ATA taskfile registers for currently-selected device | |
289 | * into @tf via MMIO. | |
290 | * | |
291 | * LOCKING: | |
292 | * Inherited from caller. | |
293 | */ | |
294 | ||
295 | static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf) | |
296 | { | |
297 | struct ata_ioports *ioaddr = &ap->ioaddr; | |
298 | ||
299 | tf->command = ata_check_status(ap); | |
300 | tf->feature = readb((void __iomem *)ioaddr->error_addr); | |
301 | tf->nsect = readb((void __iomem *)ioaddr->nsect_addr); | |
302 | tf->lbal = readb((void __iomem *)ioaddr->lbal_addr); | |
303 | tf->lbam = readb((void __iomem *)ioaddr->lbam_addr); | |
304 | tf->lbah = readb((void __iomem *)ioaddr->lbah_addr); | |
305 | tf->device = readb((void __iomem *)ioaddr->device_addr); | |
306 | ||
307 | if (tf->flags & ATA_TFLAG_LBA48) { | |
308 | writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr); | |
309 | tf->hob_feature = readb((void __iomem *)ioaddr->error_addr); | |
310 | tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr); | |
311 | tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr); | |
312 | tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr); | |
313 | tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr); | |
314 | } | |
315 | } | |
316 | ||
317 | ||
318 | /** | |
319 | * ata_tf_read - input device's ATA taskfile shadow registers | |
320 | * @ap: Port from which input is read | |
321 | * @tf: ATA taskfile register set for storing input | |
322 | * | |
323 | * Reads ATA taskfile registers for currently-selected device | |
324 | * into @tf. | |
325 | * | |
326 | * Reads nsect, lbal, lbam, lbah, and device. If ATA_TFLAG_LBA48 | |
327 | * is set, also reads the hob registers. | |
328 | * | |
329 | * May be used as the tf_read() entry in ata_port_operations. | |
330 | * | |
331 | * LOCKING: | |
332 | * Inherited from caller. | |
333 | */ | |
334 | void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) | |
335 | { | |
336 | if (ap->flags & ATA_FLAG_MMIO) | |
337 | ata_tf_read_mmio(ap, tf); | |
338 | else | |
339 | ata_tf_read_pio(ap, tf); | |
340 | } | |
341 | ||
342 | /** | |
343 | * ata_check_status_pio - Read device status reg & clear interrupt | |
344 | * @ap: port where the device is | |
345 | * | |
346 | * Reads ATA taskfile status register for currently-selected device | |
347 | * and return its value. This also clears pending interrupts | |
348 | * from this device | |
349 | * | |
350 | * LOCKING: | |
351 | * Inherited from caller. | |
352 | */ | |
353 | static u8 ata_check_status_pio(struct ata_port *ap) | |
354 | { | |
355 | return inb(ap->ioaddr.status_addr); | |
356 | } | |
357 | ||
358 | /** | |
359 | * ata_check_status_mmio - Read device status reg & clear interrupt | |
360 | * @ap: port where the device is | |
361 | * | |
362 | * Reads ATA taskfile status register for currently-selected device | |
363 | * via MMIO and return its value. This also clears pending interrupts | |
364 | * from this device | |
365 | * | |
366 | * LOCKING: | |
367 | * Inherited from caller. | |
368 | */ | |
369 | static u8 ata_check_status_mmio(struct ata_port *ap) | |
370 | { | |
371 | return readb((void __iomem *) ap->ioaddr.status_addr); | |
372 | } | |
373 | ||
374 | ||
375 | /** | |
376 | * ata_check_status - Read device status reg & clear interrupt | |
377 | * @ap: port where the device is | |
378 | * | |
379 | * Reads ATA taskfile status register for currently-selected device | |
380 | * and return its value. This also clears pending interrupts | |
381 | * from this device | |
382 | * | |
383 | * May be used as the check_status() entry in ata_port_operations. | |
384 | * | |
385 | * LOCKING: | |
386 | * Inherited from caller. | |
387 | */ | |
388 | u8 ata_check_status(struct ata_port *ap) | |
389 | { | |
390 | if (ap->flags & ATA_FLAG_MMIO) | |
391 | return ata_check_status_mmio(ap); | |
392 | return ata_check_status_pio(ap); | |
393 | } | |
394 | ||
395 | ||
396 | /** | |
397 | * ata_altstatus - Read device alternate status reg | |
398 | * @ap: port where the device is | |
399 | * | |
400 | * Reads ATA taskfile alternate status register for | |
401 | * currently-selected device and return its value. | |
402 | * | |
403 | * Note: may NOT be used as the check_altstatus() entry in | |
404 | * ata_port_operations. | |
405 | * | |
406 | * LOCKING: | |
407 | * Inherited from caller. | |
408 | */ | |
409 | u8 ata_altstatus(struct ata_port *ap) | |
410 | { | |
411 | if (ap->ops->check_altstatus) | |
412 | return ap->ops->check_altstatus(ap); | |
413 | ||
414 | if (ap->flags & ATA_FLAG_MMIO) | |
415 | return readb((void __iomem *)ap->ioaddr.altstatus_addr); | |
416 | return inb(ap->ioaddr.altstatus_addr); | |
417 | } | |
418 | ||
419 | #ifdef CONFIG_PCI | |
420 | static struct ata_probe_ent * | |
421 | ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) | |
422 | { | |
423 | struct ata_probe_ent *probe_ent; | |
424 | ||
425 | probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); | |
426 | if (!probe_ent) { | |
427 | printk(KERN_ERR DRV_NAME "(%s): out of memory\n", | |
428 | kobject_name(&(dev->kobj))); | |
429 | return NULL; | |
430 | } | |
431 | ||
432 | INIT_LIST_HEAD(&probe_ent->node); | |
433 | probe_ent->dev = dev; | |
434 | ||
435 | probe_ent->sht = port->sht; | |
436 | probe_ent->host_flags = port->host_flags; | |
437 | probe_ent->pio_mask = port->pio_mask; | |
438 | probe_ent->mwdma_mask = port->mwdma_mask; | |
439 | probe_ent->udma_mask = port->udma_mask; | |
440 | probe_ent->port_ops = port->port_ops; | |
441 | ||
442 | return probe_ent; | |
443 | } | |
444 | ||
445 | ||
446 | /** | |
447 | * ata_pci_init_native_mode - Initialize native-mode driver | |
448 | * @pdev: pci device to be initialized | |
449 | * @port: array[2] of pointers to port info structures. | |
450 | * @ports: bitmap of ports present | |
451 | * | |
452 | * Utility function which allocates and initializes an | |
453 | * ata_probe_ent structure for a standard dual-port | |
454 | * PIO-based IDE controller. The returned ata_probe_ent | |
455 | * structure can be passed to ata_device_add(). The returned | |
456 | * ata_probe_ent structure should then be freed with kfree(). | |
457 | * | |
458 | * The caller need only pass the address of the primary port, the | |
459 | * secondary will be deduced automatically. If the device has non | |
460 | * standard secondary port mappings this function can be called twice, | |
461 | * once for each interface. | |
462 | */ | |
463 | ||
464 | struct ata_probe_ent * | |
465 | ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports) | |
466 | { | |
467 | struct ata_probe_ent *probe_ent = | |
468 | ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); | |
469 | int p = 0; | |
470 | ||
471 | if (!probe_ent) | |
472 | return NULL; | |
473 | ||
474 | probe_ent->irq = pdev->irq; | |
475 | probe_ent->irq_flags = SA_SHIRQ; | |
476 | probe_ent->private_data = port[0]->private_data; | |
477 | ||
478 | if (ports & ATA_PORT_PRIMARY) { | |
479 | probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0); | |
480 | probe_ent->port[p].altstatus_addr = | |
481 | probe_ent->port[p].ctl_addr = | |
482 | pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; | |
483 | probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4); | |
484 | ata_std_ports(&probe_ent->port[p]); | |
485 | p++; | |
486 | } | |
487 | ||
488 | if (ports & ATA_PORT_SECONDARY) { | |
489 | probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2); | |
490 | probe_ent->port[p].altstatus_addr = | |
491 | probe_ent->port[p].ctl_addr = | |
492 | pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; | |
493 | probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8; | |
494 | ata_std_ports(&probe_ent->port[p]); | |
495 | p++; | |
496 | } | |
497 | ||
498 | probe_ent->n_ports = p; | |
499 | return probe_ent; | |
500 | } | |
501 | ||
502 | ||
503 | static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, | |
504 | struct ata_port_info *port, int port_num) | |
505 | { | |
506 | struct ata_probe_ent *probe_ent; | |
507 | ||
508 | probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); | |
509 | if (!probe_ent) | |
510 | return NULL; | |
511 | ||
512 | probe_ent->legacy_mode = 1; | |
513 | probe_ent->n_ports = 1; | |
514 | probe_ent->hard_port_no = port_num; | |
515 | probe_ent->private_data = port->private_data; | |
516 | ||
517 | switch(port_num) | |
518 | { | |
519 | case 0: | |
520 | probe_ent->irq = 14; | |
521 | probe_ent->port[0].cmd_addr = 0x1f0; | |
522 | probe_ent->port[0].altstatus_addr = | |
523 | probe_ent->port[0].ctl_addr = 0x3f6; | |
524 | break; | |
525 | case 1: | |
526 | probe_ent->irq = 15; | |
527 | probe_ent->port[0].cmd_addr = 0x170; | |
528 | probe_ent->port[0].altstatus_addr = | |
529 | probe_ent->port[0].ctl_addr = 0x376; | |
530 | break; | |
531 | } | |
532 | ||
533 | probe_ent->port[0].bmdma_addr = | |
534 | pci_resource_start(pdev, 4) + 8 * port_num; | |
535 | ata_std_ports(&probe_ent->port[0]); | |
536 | ||
537 | return probe_ent; | |
538 | } | |
539 | ||
540 | ||
541 | /** | |
542 | * ata_pci_init_one - Initialize/register PCI IDE host controller | |
543 | * @pdev: Controller to be initialized | |
544 | * @port_info: Information from low-level host driver | |
545 | * @n_ports: Number of ports attached to host controller | |
546 | * | |
547 | * This is a helper function which can be called from a driver's | |
548 | * xxx_init_one() probe function if the hardware uses traditional | |
549 | * IDE taskfile registers. | |
550 | * | |
551 | * This function calls pci_enable_device(), reserves its register | |
552 | * regions, sets the dma mask, enables bus master mode, and calls | |
553 | * ata_device_add() | |
554 | * | |
555 | * LOCKING: | |
556 | * Inherited from PCI layer (may sleep). | |
557 | * | |
558 | * RETURNS: | |
559 | * Zero on success, negative on errno-based value on error. | |
560 | */ | |
561 | ||
562 | int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, | |
563 | unsigned int n_ports) | |
564 | { | |
565 | struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL; | |
566 | struct ata_port_info *port[2]; | |
567 | u8 tmp8, mask; | |
568 | unsigned int legacy_mode = 0; | |
569 | int disable_dev_on_err = 1; | |
570 | int rc; | |
571 | ||
572 | DPRINTK("ENTER\n"); | |
573 | ||
574 | port[0] = port_info[0]; | |
575 | if (n_ports > 1) | |
576 | port[1] = port_info[1]; | |
577 | else | |
578 | port[1] = port[0]; | |
579 | ||
580 | if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0 | |
581 | && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { | |
582 | /* TODO: What if one channel is in native mode ... */ | |
583 | pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); | |
584 | mask = (1 << 2) | (1 << 0); | |
585 | if ((tmp8 & mask) != mask) | |
586 | legacy_mode = (1 << 3); | |
587 | } | |
588 | ||
589 | /* FIXME... */ | |
590 | if ((!legacy_mode) && (n_ports > 2)) { | |
591 | printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n"); | |
592 | n_ports = 2; | |
593 | /* For now */ | |
594 | } | |
595 | ||
596 | /* FIXME: Really for ATA it isn't safe because the device may be | |
597 | multi-purpose and we want to leave it alone if it was already | |
598 | enabled. Secondly for shared use as Arjan says we want refcounting | |
599 | ||
600 | Checking dev->is_enabled is insufficient as this is not set at | |
601 | boot for the primary video which is BIOS enabled | |
602 | */ | |
603 | ||
604 | rc = pci_enable_device(pdev); | |
605 | if (rc) | |
606 | return rc; | |
607 | ||
608 | rc = pci_request_regions(pdev, DRV_NAME); | |
609 | if (rc) { | |
610 | disable_dev_on_err = 0; | |
611 | goto err_out; | |
612 | } | |
613 | ||
614 | /* FIXME: Should use platform specific mappers for legacy port ranges */ | |
615 | if (legacy_mode) { | |
616 | if (!request_region(0x1f0, 8, "libata")) { | |
617 | struct resource *conflict, res; | |
618 | res.start = 0x1f0; | |
619 | res.end = 0x1f0 + 8 - 1; | |
620 | conflict = ____request_resource(&ioport_resource, &res); | |
621 | if (!strcmp(conflict->name, "libata")) | |
622 | legacy_mode |= (1 << 0); | |
623 | else { | |
624 | disable_dev_on_err = 0; | |
625 | printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n"); | |
626 | } | |
627 | } else | |
628 | legacy_mode |= (1 << 0); | |
629 | ||
630 | if (!request_region(0x170, 8, "libata")) { | |
631 | struct resource *conflict, res; | |
632 | res.start = 0x170; | |
633 | res.end = 0x170 + 8 - 1; | |
634 | conflict = ____request_resource(&ioport_resource, &res); | |
635 | if (!strcmp(conflict->name, "libata")) | |
636 | legacy_mode |= (1 << 1); | |
637 | else { | |
638 | disable_dev_on_err = 0; | |
639 | printk(KERN_WARNING "ata: 0x170 IDE port busy\n"); | |
640 | } | |
641 | } else | |
642 | legacy_mode |= (1 << 1); | |
643 | } | |
644 | ||
645 | /* we have legacy mode, but all ports are unavailable */ | |
646 | if (legacy_mode == (1 << 3)) { | |
647 | rc = -EBUSY; | |
648 | goto err_out_regions; | |
649 | } | |
650 | ||
651 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); | |
652 | if (rc) | |
653 | goto err_out_regions; | |
654 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | |
655 | if (rc) | |
656 | goto err_out_regions; | |
657 | ||
658 | if (legacy_mode) { | |
659 | if (legacy_mode & (1 << 0)) | |
660 | probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0); | |
661 | if (legacy_mode & (1 << 1)) | |
662 | probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1); | |
663 | } else { | |
664 | if (n_ports == 2) | |
665 | probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); | |
666 | else | |
667 | probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY); | |
668 | } | |
669 | if (!probe_ent && !probe_ent2) { | |
670 | rc = -ENOMEM; | |
671 | goto err_out_regions; | |
672 | } | |
673 | ||
674 | pci_set_master(pdev); | |
675 | ||
676 | /* FIXME: check ata_device_add return */ | |
677 | if (legacy_mode) { | |
678 | if (legacy_mode & (1 << 0)) | |
679 | ata_device_add(probe_ent); | |
680 | if (legacy_mode & (1 << 1)) | |
681 | ata_device_add(probe_ent2); | |
682 | } else | |
683 | ata_device_add(probe_ent); | |
684 | ||
685 | kfree(probe_ent); | |
686 | kfree(probe_ent2); | |
687 | ||
688 | return 0; | |
689 | ||
690 | err_out_regions: | |
691 | if (legacy_mode & (1 << 0)) | |
692 | release_region(0x1f0, 8); | |
693 | if (legacy_mode & (1 << 1)) | |
694 | release_region(0x170, 8); | |
695 | pci_release_regions(pdev); | |
696 | err_out: | |
697 | if (disable_dev_on_err) | |
698 | pci_disable_device(pdev); | |
699 | return rc; | |
700 | } | |
701 | ||
702 | #endif /* CONFIG_PCI */ | |
703 |