📄 ide-cd.c
字号:
sprintf(buf, "Diagnostic failure on component 0x%02x", sense->ascq); 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 semaphore *sem, 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->sem = sem; (void) ide_do_drive_cmd(drive, rq, ide_preempt);}static void cdrom_end_request (int uptodate, ide_drive_t *drive){ 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 (rq->cmd == READ || rq->cmd == WRITE) if (!rq->current_nr_sectors) uptodate = 1; ide_end_request (uptodate, HWGROUP(drive));}/* 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 = GET_STAT(); *stat_ret = stat; if (OK_STAT (stat, good_stat, BAD_R_STAT)) return 0; /* Get the IDE error register. */ err = GET_ERR(); 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 (1, drive); *startstop = ide_error (drive, "request sense failure", stat); return 1; } else if (rq->cmd == PACKET_COMMAND) { /* All other functions, except for READ. */ struct semaphore *sem = 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) { sem = rq->sem; rq->sem = NULL; } pc->stat = 1; cdrom_end_request (1, drive); if ((stat & ERR_STAT) != 0) cdrom_queue_request_sense(drive, sem, pc->sense, pc); } else { /* Handle errors from READ and WRITE requests. */ 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 (0, drive); } 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 (0, drive); } 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 (0, drive); } else if ((err & ~ABRT_ERR) != 0) { /* Go to the default handler for other errors. */ *startstop = ide_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 (0, drive); } /* 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){ struct request *rq = HWGROUP(drive)->rq; struct packet_command *pc = (struct packet_command *) rq->buffer; unsigned long wait = 0; /* * Some commands are *slow* and normally take a long time to * complete. Usually we can use the ATAPI "disconnect" to bypass * this, but not all commands/drives support that. Let * ide_timer_expiry keep polling us for these. */ switch (pc->c[0]) { case GPCMD_BLANK: case GPCMD_FORMAT_UNIT: case GPCMD_RESERVE_RZONE_TRACK: wait = WAIT_CMD; break; default: wait = 0; break; } return wait;}/* Set up the device registers for transferring a packet command on DEV, expecting to later transfer XFERLEN bytes. HANDLER is the routine which actually transfers the command to the drive. If this is a drq_interrupt device, this routine will arrange for HANDLER to be called when the interrupt from the drive arrives. Otherwise, HANDLER will be called immediately after the drive is prepared for the transfer. */static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, int xferlen, ide_handler_t *handler){ ide_startstop_t startstop; struct cdrom_info *info = drive->driver_data; /* Wait for the controller to be idle. */ if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) return startstop; if (info->dma) { if (info->cmd == READ) { info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); } else if (info->cmd == WRITE) { info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive); } else { printk("ide-cd: DMA set, but not allowed\n"); } } /* Set up the controller registers. */ OUT_BYTE (info->dma, IDE_FEATURE_REG); OUT_BYTE (0, IDE_NSECTOR_REG); OUT_BYTE (0, IDE_SECTOR_REG); OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG); OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG); if (IDE_CONTROL_REG) OUT_BYTE (drive->ctl, IDE_CONTROL_REG); if (info->dma) (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ return ide_started; } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ return (*handler) (drive); }}/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN. The device registers must have already been prepared by cdrom_start_packet_command. HANDLER is the interrupt handler to call when the command completes or there's data ready. *//* * changed 5 parameters to 3 for dvd-ram * struct packet_command *pc; now packet_command_t *pc; */#undef CLASSIC_PACKET_STRUCTstatic ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, struct packet_command *pc, ide_handler_t *handler){#ifdef CLASSIC_PACKET_STRUCT unsigned char *cmd_buf = pc->c; int cmd_len = sizeof(pc->c); unsigned int timeout = pc->timeout;#endif ide_startstop_t startstop; if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { /* Here we should have been called after receiving an interrupt from the device. DRQ should how be set. */ int stat_dum; /* Check for errors. */ if (cdrom_decode_status (&startstop, drive, DRQ_STAT, &stat_dum)) return startstop; } else { /* Otherwise, we must wait for DRQ to get set. */ if (ide_wait_stat (&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) return startstop; } /* Arm the interrupt handler. */#ifdef CLASSIC_PACKET_STRUCT /* Arm the interrupt handler. */ ide_set_handler (drive, handler, timeout, cdrom_timer_expiry); /* Send the command to the device. */ atapi_output_bytes (drive, cmd_buf, cmd_len);#else /* !CLASSIC_PACKET_STRUCT */ /* Arm the interrupt handler. */// ide_set_handler (drive, handler, (unsigned int) pc->timeout, cdrom_timer_expiry); ide_set_handler (drive, handler, pc->timeout, cdrom_timer_expiry); /* Send the command to the device. */// atapi_output_bytes (drive, (void *)pc->c, (unsigned int) sizeof(pc->c)); atapi_output_bytes (drive, pc->c, sizeof(pc->c));#endif /* CLASSIC_PACKET_STRUCT */ return ide_started;}/**************************************************************************** * Block read functions. *//* * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector * buffer. Once the first sector is added, any subsequent sectors are * assumed to be continuous (until the buffer is cleared). For the first * sector added, SECTOR is its sector number. (SECTOR is then ignored until
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -