]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-atapi.c
ide: add ide_check_atapi_device() helper
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-atapi.c
index adf04f99cdebb20f9d63e15c0010fa34b6db5e39..61c52fb665ca7922fab57f1459f8f18f789db811 100644 (file)
 #define debug_log(fmt, args...) do {} while (0)
 #endif
 
+/*
+ * Check whether we can support a device,
+ * based on the ATAPI IDENTIFY command results.
+ */
+int ide_check_atapi_device(ide_drive_t *drive, const char *s)
+{
+       u16 *id = drive->id;
+       u8 gcw[2], protocol, device_type, removable, drq_type, packet_size;
+
+       *((u16 *)&gcw) = id[ATA_ID_CONFIG];
+
+       protocol    = (gcw[1] & 0xC0) >> 6;
+       device_type =  gcw[1] & 0x1F;
+       removable   = (gcw[0] & 0x80) >> 7;
+       drq_type    = (gcw[0] & 0x60) >> 5;
+       packet_size =  gcw[0] & 0x03;
+
+#ifdef CONFIG_PPC
+       /* kludge for Apple PowerBook internal zip */
+       if (drive->media == ide_floppy && device_type == 5 &&
+           !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") &&
+           strstr((char *)&id[ATA_ID_PROD], "ZIP"))
+               device_type = 0;
+#endif
+
+       if (protocol != 2)
+               printk(KERN_ERR "%s: %s: protocol (0x%02x) is not ATAPI\n",
+                       s, drive->name, protocol);
+       else if ((drive->media == ide_floppy && device_type != 0) ||
+                (drive->media == ide_tape && device_type != 1))
+               printk(KERN_ERR "%s: %s: invalid device type (0x%02x)\n",
+                       s, drive->name, device_type);
+       else if (removable == 0)
+               printk(KERN_ERR "%s: %s: the removable flag is not set\n",
+                       s, drive->name);
+       else if (drive->media == ide_floppy && drq_type == 3)
+               printk(KERN_ERR "%s: %s: sorry, DRQ type (0x%02x) not "
+                       "supported\n", s, drive->name, drq_type);
+       else if (packet_size != 0)
+               printk(KERN_ERR "%s: %s: packet size (0x%02x) is not 12 "
+                       "bytes\n", s, drive->name, packet_size);
+       else
+               return 1;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ide_check_atapi_device);
+
 /* TODO: unify the code thus making some arguments go away */
 ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
        ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry,
@@ -41,7 +88,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
 
        if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
                if (hwif->dma_ops->dma_end(drive) ||
-                   (drive->media == ide_tape && !scsi && (stat & ERR_STAT))) {
+                   (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) {
                        if (drive->media == ide_floppy && !scsi)
                                printk(KERN_ERR "%s: DMA %s error\n",
                                        drive->name, rq_data_dir(pc->rq)
@@ -56,7 +103,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
        }
 
        /* No more interrupts */
-       if ((stat & DRQ_STAT) == 0) {
+       if ((stat & ATA_DRQ) == 0) {
                debug_log("Packet command completed, %d bytes transferred\n",
                          pc->xferred);
 
@@ -65,10 +112,10 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
                local_irq_enable_in_hardirq();
 
                if (drive->media == ide_tape && !scsi &&
-                   (stat & ERR_STAT) && rq->cmd[0] == REQUEST_SENSE)
-                       stat &= ~ERR_STAT;
+                   (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE)
+                       stat &= ~ATA_ERR;
 
-               if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
+               if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) {
                        /* Error detected */
                        debug_log("%s: I/O error\n", drive->name);
 
@@ -95,7 +142,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
 cmd_finished:
                pc->error = 0;
                if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
-                   (stat & SEEK_STAT) == 0) {
+                   (stat & ATA_DSC) == 0) {
                        dsc_handle(drive);
                        return ide_stopped;
                }
@@ -117,17 +164,18 @@ cmd_finished:
        /* Get the number of bytes to transfer on this interrupt. */
        ide_read_bcount_and_ireason(drive, &bcount, &ireason);
 
-       if (ireason & CD) {
+       if (ireason & ATAPI_COD) {
                printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
                return ide_do_reset(drive);
        }
 
-       if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
+       if (((ireason & ATAPI_IO) == ATAPI_IO) ==
+               !!(pc->flags & PC_FLAG_WRITING)) {
                /* Hopefully, we will never get here */
                printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
                                "to %s!\n", drive->name,
-                               (ireason & IO) ? "Write" : "Read",
-                               (ireason & IO) ? "Read" : "Write");
+                               (ireason & ATAPI_IO) ? "Write" : "Read",
+                               (ireason & ATAPI_IO) ? "Read" : "Write");
                return ide_do_reset(drive);
        }
 
@@ -205,7 +253,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
 {
        int retries = 100;
 
-       while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
+       while (retries-- && ((ireason & ATAPI_COD) == 0 ||
+               (ireason & ATAPI_IO))) {
                printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
                                "a packet command, retrying\n", drive->name);
                udelay(100);
@@ -214,8 +263,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
                        printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
                                        "a packet command, ignoring\n",
                                        drive->name);
-                       ireason |= CD;
-                       ireason &= ~IO;
+                       ireason |= ATAPI_COD;
+                       ireason &= ~ATAPI_IO;
                }
        }
 
@@ -231,7 +280,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
        ide_startstop_t startstop;
        u8 ireason;
 
-       if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
+       if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) {
                printk(KERN_ERR "%s: Strange, packet command initiated yet "
                                "DRQ isn't asserted\n", drive->name);
                return startstop;
@@ -241,7 +290,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
        if (drive->media == ide_tape && !drive->scsi)
                ireason = ide_wait_ireason(drive, ireason);
 
-       if ((ireason & CD) == 0 || (ireason & IO)) {
+       if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
                printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
                                "a packet command\n", drive->name);
                return ide_do_reset(drive);
@@ -303,7 +352,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
 
        /* Issue the packet command */
        if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
-               ide_execute_command(drive, WIN_PACKETCMD, handler,
+               ide_execute_command(drive, ATA_CMD_PACKET, handler,
                                    timeout, NULL);
                return ide_started;
        } else {