?? ide-cd.c
字號:
s = buf; } else { int lo = 0, mid, hi = ARY_LEN(sense_data_texts); unsigned long key = (sense->sense_key << 16); key |= (sense->asc << 8); if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd)) key |= sense->ascq; s = NULL; while (hi > lo) { mid = (lo + hi) / 2; if (sense_data_texts[mid].asc_ascq == key || sense_data_texts[mid].asc_ascq == (0xff0000|key)) { s = sense_data_texts[mid].text; break; } else if (sense_data_texts[mid].asc_ascq > key) hi = mid; else lo = mid+1; } } if (s == NULL) { if (sense->asc > 0x80) s = "(vendor-specific error)"; else s = "(reserved error code)"; } printk(" %s -- (asc=0x%02x, ascq=0x%02x)\n", s, sense->asc, sense->ascq); if (failed_command != NULL) { int lo=0, mid, hi= ARY_LEN (packet_command_texts); s = NULL; while (hi > lo) { mid = (lo + hi) / 2; if (packet_command_texts[mid].packet_command == failed_command->c[0]) { s = packet_command_texts[mid].text; break; } if (packet_command_texts[mid].packet_command > failed_command->c[0]) hi = mid; else lo = mid+1; } printk (" The failed \"%s\" packet command was: \n \"", s); for (i=0; i<sizeof (failed_command->c); i++) printk ("%02x ", failed_command->c[i]); printk ("\"\n"); } /* The SKSV bit specifies validity of the sense_key_specific * in the next two commands. It is bit 7 of the first byte. * In the case of NOT_READY, if SKSV is set the drive can * give us nice ETA readings. */ if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) { int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100; printk(" Command is %02d%% complete\n", progress / 0xffff); } if (sense->sense_key == ILLEGAL_REQUEST && (sense->sks[0] & 0x80) != 0) { printk(" Error in %s byte %d", (sense->sks[0] & 0x40) != 0 ? "command packet" : "command data", (sense->sks[1] << 8) + sense->sks[2]); if ((sense->sks[0] & 0x40) != 0) printk (" bit %d", sense->sks[0] & 0x07); printk ("\n"); } }#else /* not VERBOSE_IDE_CD_ERRORS */ /* Suppress printing unit attention and `in progress of becoming ready' errors when we're not being verbose. */ if (sense->sense_key == UNIT_ATTENTION || (sense->sense_key == NOT_READY && (sense->asc == 4 || sense->asc == 0x3a))) return; printk("%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n", drive->name, sense->error_code, sense->sense_key, sense->asc, sense->ascq);#endif /* not VERBOSE_IDE_CD_ERRORS */}static void cdrom_queue_request_sense(ide_drive_t *drive, struct completion *wait, struct request_sense *sense, struct packet_command *failed_command){ struct cdrom_info *info = drive->driver_data; struct packet_command *pc = &info->request_sense_pc; struct request *rq; if (sense == NULL) sense = &info->sense_data; memset(pc, 0, sizeof(struct packet_command)); pc->c[0] = GPCMD_REQUEST_SENSE; pc->c[4] = pc->buflen = 18; pc->buffer = (char *) sense; pc->sense = (struct request_sense *) failed_command; /* stuff the sense request in front of our current request */ rq = &info->request_sense_request; ide_init_drive_cmd(rq); rq->cmd = REQUEST_SENSE_COMMAND; rq->buffer = (char *) pc; rq->waiting = wait; (void) ide_do_drive_cmd(drive, rq, ide_preempt);}/* * This is our end_request replacement function. */static int ide_cdrom_end_request (ide_drive_t *drive, int uptodate){ struct request *rq; unsigned long flags; int ret = 1; spin_lock_irqsave(&io_request_lock, flags); rq = HWGROUP(drive)->rq; /* * decide whether to reenable DMA -- 3 is a random magic for now, * if we DMA timeout more than 3 times, just stay in PIO */ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { drive->state = 0; HWGROUP(drive)->hwif->ide_dma_on(drive); } if (!end_that_request_first(rq, uptodate, drive->name)) { add_blkdev_randomness(MAJOR(rq->rq_dev)); blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; end_that_request_last(rq); ret = 0; } spin_unlock_irqrestore(&io_request_lock, flags); return ret;}/* * Error reporting, in human readable form (luxurious, but a memory hog). */byte ide_cdrom_dump_status (ide_drive_t *drive, const char *msg, byte stat){ unsigned long flags; atapi_status_t status; atapi_error_t error; status.all = stat; local_irq_set(flags); printk("%s: %s: status=0x%02x", drive->name, msg, stat);#if FANCY_STATUS_DUMPS printk(" { "); if (status.b.bsy) printk("Busy "); else { if (status.b.drdy) printk("DriveReady "); if (status.b.df) printk("DeviceFault "); if (status.b.dsc) printk("SeekComplete "); if (status.b.drq) printk("DataRequest "); if (status.b.corr) printk("CorrectedError "); if (status.b.idx) printk("Index "); if (status.b.check) printk("Error "); } printk("}");#endif /* FANCY_STATUS_DUMPS */ printk("\n"); if ((status.all & (status.b.bsy|status.b.check)) == status.b.check) { error.all = HWIF(drive)->INB(IDE_ERROR_REG); printk("%s: %s: error=0x%02x", drive->name, msg, error.all);#if FANCY_STATUS_DUMPS if (error.b.ili) printk("IllegalLengthIndication "); if (error.b.eom) printk("EndOfMedia "); if (error.b.abrt) printk("Aborted Command "); if (error.b.mcr) printk("MediaChangeRequested "); if (error.b.sense_key) printk("LastFailedSense 0x%02x ", error.b.sense_key);#endif /* FANCY_STATUS_DUMPS */ printk("\n"); } local_irq_restore(flags); return error.all;}/* * ide_error() takes action based on the error returned by the drive. */ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat){ struct request *rq; byte err; err = ide_cdrom_dump_status(drive, msg, stat); if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) return ide_stopped; /* retry only "normal" I/O: */ if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { rq->errors = 1; ide_end_drive_cmd(drive, stat, err); return ide_stopped; } if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ rq->errors |= ERROR_RESET; } else { /* add decoding error stuff */ } if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) /* force an abort */ HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); if (rq->errors >= ERROR_MAX) { DRIVER(drive)->end_request(drive, 0); } else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; return ide_do_reset(drive); } ++rq->errors; } return ide_stopped;}ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg){ struct request *rq; if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) return ide_stopped; /* retry only "normal" I/O: */ if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { rq->errors = 1; ide_end_drive_cmd(drive, BUSY_STAT, 0); return ide_stopped; } rq->errors |= ERROR_RESET; DRIVER(drive)->end_request(drive, 0); return ide_stopped;}static void cdrom_end_request (ide_drive_t *drive, int uptodate){ struct request *rq = HWGROUP(drive)->rq; if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate) { struct packet_command *pc = (struct packet_command *) rq->buffer; cdrom_analyze_sense_data(drive, (struct packet_command *) pc->sense, (struct request_sense *) (pc->buffer - pc->c[4])); } if (blk_fs_request(rq) && !rq->current_nr_sectors) uptodate = 1; ide_cdrom_end_request(drive, uptodate);}/* Returns 0 if the request should be continued. Returns 1 if the request was ended. */static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, int good_stat, int *stat_ret){ struct request *rq = HWGROUP(drive)->rq; int stat, err, sense_key; struct packet_command *pc; /* Check for errors. */ *stat_ret = stat = HWIF(drive)->INB(IDE_STATUS_REG); if (OK_STAT (stat, good_stat, BAD_R_STAT)) return 0; /* Get the IDE error register. */ err = HWIF(drive)->INB(IDE_ERROR_REG); sense_key = err >> 4; if (rq == NULL) { printk("%s: missing rq in cdrom_decode_status\n", drive->name); *startstop = ide_stopped; return 1; } if (rq->cmd == REQUEST_SENSE_COMMAND) { /* We got an error trying to get sense info from the drive (probably while trying to recover from a former error). Just give up. */ pc = (struct packet_command *) rq->buffer; pc->stat = 1; cdrom_end_request(drive, 1); *startstop = DRIVER(drive)->error(drive, "request sense failure", stat); return 1; } else if (rq->cmd == PACKET_COMMAND) { /* All other functions, except for READ. */ struct completion *wait = NULL; pc = (struct packet_command *) rq->buffer; /* Check for tray open. */ if (sense_key == NOT_READY) { cdrom_saw_media_change (drive); } else if (sense_key == UNIT_ATTENTION) { /* Check for media change. */ cdrom_saw_media_change (drive); /*printk("%s: media changed\n",drive->name);*/ return 0; } else if (!pc->quiet) { /* Otherwise, print an error. */ ide_dump_status(drive, "packet command error", stat); } /* Set the error flag and complete the request. Then, if we have a CHECK CONDITION status, queue a request sense command. We must be careful, though: we don't want the thread in cdrom_queue_packet_command to wake up until the request sense has completed. We do this by transferring the semaphore from the packet command request to the request sense request. */ if ((stat & ERR_STAT) != 0) { wait = rq->waiting; rq->waiting = NULL; } pc->stat = 1; cdrom_end_request(drive, 1); if ((stat & ERR_STAT) != 0) cdrom_queue_request_sense(drive, wait, pc->sense, pc); } else if (blk_fs_request(rq)) { /* Handle errors from READ and WRITE requests. */ int do_end_request = 0; if (sense_key == NOT_READY) { /* Tray open. */ cdrom_saw_media_change (drive); /* Fail the request. */ printk ("%s: tray open\n", drive->name); //cdrom_end_request(drive, 0); do_end_request = 1; } else if (sense_key == UNIT_ATTENTION) { /* Media change. */ cdrom_saw_media_change (drive); /* Arrange to retry the request. But be sure to give up if we've retried too many times. */ if (++rq->errors > ERROR_MAX) //cdrom_end_request(drive, 0); do_end_request = 1; } else if (sense_key == ILLEGAL_REQUEST || sense_key == DATA_PROTECT) { /* No point in retrying after an illegal request or data protect error.*/ ide_dump_status (drive, "command error", stat); //cdrom_end_request(drive, 0); do_end_request = 1; } else if (sense_key == MEDIUM_ERROR) { /* No point in re-trying a zillion times on a bad sector... * If we got here the error is not correctable. */ ide_dump_status (drive, "media error (bad sector)", stat); do_end_request = 1; } else if ((err & ~ABRT_ERR) != 0) { /* Go to the default handler for other errors. */ *startstop = DRIVER(drive)->error(drive, "cdrom_decode_status", stat); return 1; } else if ((++rq->errors > ERROR_MAX)) { /* We've racked up too many retries. Abort. */ //cdrom_end_request(drive, 0); do_end_request = 1; } if(do_end_request) cdrom_end_request(drive, 0); /* If we got a CHECK_CONDITION status, queue a request sense command. */ if ((stat & ERR_STAT) != 0) cdrom_queue_request_sense(drive, NULL, NULL, NULL); } /* Retry, or handle the next request. */ *startstop = ide_stopped; return 1;}static int cdrom_timer_expiry(ide_drive_t *drive)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -