diff options
Diffstat (limited to 'drivers/ide/ide-atapi.c')
-rw-r--r-- | drivers/ide/ide-atapi.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c new file mode 100644 index 000000000000..25939bc60402 --- /dev/null +++ b/drivers/ide/ide-atapi.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * ATAPI support. | ||
3 | */ | ||
4 | |||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/delay.h> | ||
7 | #include <linux/ide.h> | ||
8 | |||
9 | static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) | ||
10 | { | ||
11 | ide_hwif_t *hwif = drive->hwif; | ||
12 | int retries = 100; | ||
13 | |||
14 | while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) { | ||
15 | printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " | ||
16 | "a packet command, retrying\n", drive->name); | ||
17 | udelay(100); | ||
18 | ireason = hwif->INB(hwif->io_ports.nsect_addr); | ||
19 | if (retries == 0) { | ||
20 | printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " | ||
21 | "a packet command, ignoring\n", | ||
22 | drive->name); | ||
23 | ireason |= CD; | ||
24 | ireason &= ~IO; | ||
25 | } | ||
26 | } | ||
27 | |||
28 | return ireason; | ||
29 | } | ||
30 | |||
31 | ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc, | ||
32 | ide_handler_t *handler, unsigned int timeout, | ||
33 | ide_expiry_t *expiry) | ||
34 | { | ||
35 | ide_hwif_t *hwif = drive->hwif; | ||
36 | ide_startstop_t startstop; | ||
37 | u8 ireason; | ||
38 | |||
39 | if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) { | ||
40 | printk(KERN_ERR "%s: Strange, packet command initiated yet " | ||
41 | "DRQ isn't asserted\n", drive->name); | ||
42 | return startstop; | ||
43 | } | ||
44 | |||
45 | ireason = hwif->INB(hwif->io_ports.nsect_addr); | ||
46 | if (drive->media == ide_tape && !drive->scsi) | ||
47 | ireason = ide_wait_ireason(drive, ireason); | ||
48 | |||
49 | if ((ireason & CD) == 0 || (ireason & IO)) { | ||
50 | printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " | ||
51 | "a packet command\n", drive->name); | ||
52 | return ide_do_reset(drive); | ||
53 | } | ||
54 | |||
55 | /* Set the interrupt routine */ | ||
56 | ide_set_handler(drive, handler, timeout, expiry); | ||
57 | |||
58 | /* Begin DMA, if necessary */ | ||
59 | if (pc->flags & PC_FLAG_DMA_OK) { | ||
60 | pc->flags |= PC_FLAG_DMA_IN_PROGRESS; | ||
61 | hwif->dma_ops->dma_start(drive); | ||
62 | } | ||
63 | |||
64 | /* Send the actual packet */ | ||
65 | if ((pc->flags & PC_FLAG_ZIP_DRIVE) == 0) | ||
66 | hwif->output_data(drive, NULL, pc->c, 12); | ||
67 | |||
68 | return ide_started; | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(ide_transfer_pc); | ||