diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 05:15:27 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 05:15:27 -0500 |
commit | 1fdffbce0332b3e00993d741e76935e7f4f0d40f (patch) | |
tree | d6d5063c7f2f1dfcdaa9868260b3b812e4feca7e /drivers/scsi/libata-bmdma.c | |
parent | 389984cb75a5d26aa6ee9724c343bbd130cb3eec (diff) |
[libata] Move PCI IDE BMDMA-related code to new file libata-bmdma.c.
Diffstat (limited to 'drivers/scsi/libata-bmdma.c')
-rw-r--r-- | drivers/scsi/libata-bmdma.c | 703 |
1 files changed, 703 insertions, 0 deletions
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c new file mode 100644 index 000000000000..a93336adcd23 --- /dev/null +++ b/drivers/scsi/libata-bmdma.c | |||
@@ -0,0 +1,703 @@ | |||
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 | |||