static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, struct request *failed_command) { struct cdrom_info *info = drive->driver_data; struct request *rq = &drive->request_sense_rq; ide_debug_log(IDE_DBG_SENSE, "enter"); if (sense == NULL) sense = &info->sense_data; /* stuff the sense request in front of our current request */ blk_rq_init(NULL, rq); rq->cmd_type = REQ_TYPE_ATA_PC; rq->rq_disk = info->disk; rq->data = sense; rq->cmd[0] = GPCMD_REQUEST_SENSE; rq->cmd[4] = 18; rq->data_len = 18; rq->cmd_type = REQ_TYPE_SENSE; rq->cmd_flags |= REQ_PREEMPT; /* NOTE! Save the failed command in "rq->buffer" */ rq->buffer = (void *) failed_command; if (failed_command) ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x", failed_command->cmd[0]); drive->hwif->rq = NULL; elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); }
static void idefloppy_create_rw_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc, struct request *rq, unsigned long sector) { struct ide_disk_obj *floppy = drive->driver_data; int block = sector / floppy->bs_factor; int blocks = rq->nr_sectors / floppy->bs_factor; int cmd = rq_data_dir(rq); ide_debug_log(IDE_DBG_FUNC, "block: %d, blocks: %d", block, blocks); ide_init_pc(pc); pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10; put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]); put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]); memcpy(rq->cmd, pc->c, 12); pc->rq = rq; if (rq->cmd_flags & REQ_RW) pc->flags |= PC_FLAG_WRITING; pc->buf = NULL; pc->req_xfer = pc->buf_size = blocks * floppy->block_size; pc->flags |= PC_FLAG_DMA_OK; }
static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd, struct ide_atapi_pc *pc) { struct ide_disk_obj *floppy = drive->driver_data; if (drive->failed_pc == NULL && pc->c[0] != GPCMD_REQUEST_SENSE) drive->failed_pc = pc; drive->pc = pc; if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) { unsigned int done = blk_rq_bytes(drive->hwif->rq); if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) ide_floppy_report_error(floppy, pc); pc->error = IDE_DRV_ERROR_GENERAL; drive->failed_pc = NULL; drive->pc_callback(drive, 0); ide_complete_rq(drive, -EIO, done); return ide_stopped; } ide_debug_log(IDE_DBG_FUNC, "retry #%d", pc->retries); pc->retries++; return ide_issue_pc(drive, cmd); }
static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd, struct ide_atapi_pc *pc) { struct ide_disk_obj *floppy = drive->driver_data; if (drive->failed_pc == NULL && pc->c[0] != GPCMD_REQUEST_SENSE) drive->failed_pc = pc; /* Set the current packet command */ drive->pc = pc; if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) { if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) ide_floppy_report_error(floppy, pc); /* Giving up */ pc->error = IDE_DRV_ERROR_GENERAL; drive->failed_pc = NULL; drive->pc_callback(drive, 0); return ide_stopped; } ide_debug_log(IDE_DBG_FUNC, "retry #%d", pc->retries); pc->retries++; return ide_issue_pc(drive, cmd); }
static int ide_gd_open(struct block_device *bdev, fmode_t mode) { struct gendisk *disk = bdev->bd_disk; struct ide_disk_obj *idkp; ide_drive_t *drive; int ret = 0; idkp = ide_disk_get(disk); if (idkp == NULL) return -ENXIO; drive = idkp->drive; ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); idkp->openers++; if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; /* Just in case */ ret = drive->disk_ops->init_media(drive, disk); /* * Allow O_NDELAY to open a drive without a disk, or with an * unreadable disk, so that we can get the format capacity * of the drive or begin the format - Sam */ if (ret && (mode & FMODE_NDELAY) == 0) { ret = -EIO; goto out_put_idkp; } if ((drive->dev_flags & IDE_DFLAG_WP) && (mode & FMODE_WRITE)) { ret = -EROFS; goto out_put_idkp; } /* * Ignore the return code from door_lock, * since the open() has already succeeded, * and the door_lock is irrelevant at this point. */ drive->disk_ops->set_doorlock(drive, disk, 1); drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; check_disk_change(bdev); } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) { ret = -EBUSY; goto out_put_idkp; } return 0; out_put_idkp: idkp->openers--; ide_disk_put(idkp); return ret; }
static int ide_floppy_callback(ide_drive_t *drive, int dsc) { struct ide_disk_obj *floppy = drive->driver_data; struct ide_atapi_pc *pc = drive->pc; struct request *rq = pc->rq; int uptodate = pc->error ? 0 : 1; ide_debug_log(IDE_DBG_FUNC, "enter"); if (drive->failed_pc == pc) drive->failed_pc = NULL; if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 || (rq && blk_pc_request(rq))) uptodate = 1; else if (pc->c[0] == GPCMD_REQUEST_SENSE) { u8 *buf = bio_data(rq->bio); if (!pc->error) { floppy->sense_key = buf[2] & 0x0F; floppy->asc = buf[12]; floppy->ascq = buf[13]; floppy->progress_indication = buf[15] & 0x80 ? (u16)get_unaligned((u16 *)&buf[16]) : 0x10000; if (drive->failed_pc) ide_debug_log(IDE_DBG_PC, "pc = %x", drive->failed_pc->c[0]); ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x," "ascq = %x", floppy->sense_key, floppy->asc, floppy->ascq); } else printk(KERN_ERR PFX "Error in REQUEST SENSE itself - " "Aborting request!\n"); } if (blk_special_request(rq)) rq->errors = uptodate ? 0 : IDE_DRV_ERROR_GENERAL; return uptodate; }
static int ide_gd_open(struct block_device *bdev, fmode_t mode) { struct gendisk *disk = bdev->bd_disk; struct ide_disk_obj *idkp; ide_drive_t *drive; int ret = 0; idkp = ide_disk_get(disk); if (idkp == NULL) return -ENXIO; drive = idkp->drive; ide_debug_log(IDE_DBG_FUNC, "enter"); idkp->openers++; if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; ret = drive->disk_ops->init_media(drive, disk); if (ret && (mode & FMODE_NDELAY) == 0) { ret = -EIO; goto out_put_idkp; } if ((drive->dev_flags & IDE_DFLAG_WP) && (mode & FMODE_WRITE)) { ret = -EROFS; goto out_put_idkp; } drive->disk_ops->set_doorlock(drive, disk, 1); drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; check_disk_change(bdev); } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) { ret = -EBUSY; goto out_put_idkp; } return 0; out_put_idkp: idkp->openers--; ide_disk_put(idkp); return ret; }
static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, struct request_sense *sense) { int log = 0; ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key); if (!sense || !rq || (rq->cmd_flags & REQ_QUIET)) return 0; switch (sense->sense_key) { case NO_SENSE: case RECOVERED_ERROR: break; case NOT_READY: /* * don't care about tray state messages for e.g. capacity * commands or in-progress or becoming ready */ if (sense->asc == 0x3a || sense->asc == 0x04) break; log = 1; break; case ILLEGAL_REQUEST: /* * don't log START_STOP unit with LoEj set, since we cannot * reliably check if drive can auto-close */ if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24) break; log = 1; break; case UNIT_ATTENTION: /* * Make good and sure we've seen this potential media change. * Some drives (i.e. Creative) fail to present the correct sense * key in the error register. */ cdrom_saw_media_change(drive); break; default: log = 1; break; } return log; }
static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd) { struct request *rq = cmd->rq; ide_debug_log(IDE_DBG_FUNC, "rq->cmd[0]: 0x%x", rq->cmd[0]); /* * Some of the trailing request sense fields are optional, * and some drives don't send them. Sigh. */ if (rq->cmd[0] == GPCMD_REQUEST_SENSE && cmd->nleft > 0 && cmd->nleft <= 5) { unsigned int ofs = cmd->nbytes - cmd->nleft; while (cmd->nleft > 0) { *((u8 *)rq->data + ofs++) = 0; cmd->nleft--; } } }
static int ide_gd_release(struct gendisk *disk, fmode_t mode) { struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); ide_drive_t *drive = idkp->drive; ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); if (idkp->openers == 1) drive->disk_ops->flush(drive); if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { drive->disk_ops->set_doorlock(drive, disk, 0); drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; } idkp->openers--; ide_disk_put(idkp); return 0; }
/* * Check the contents of the interrupt reason register from the cdrom * and attempt to recover if there are problems. Returns 0 if everything's * ok; nonzero if the request has been terminated. */ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq, int len, int ireason, int rw) { ide_hwif_t *hwif = drive->hwif; ide_debug_log(IDE_DBG_FUNC, "ireason: 0x%x, rw: 0x%x", ireason, rw); /* * ireason == 0: the drive wants to receive data from us * ireason == 2: the drive is expecting to transfer data to us */ if (ireason == (!rw << 1)) return 0; else if (ireason == (rw << 1)) { /* whoops... */ printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n", drive->name, __func__); ide_pad_transfer(drive, rw, len); } else if (rw == 0 && ireason == 1) { /* * Some drives (ASUS) seem to tell us that status info is * available. Just get it and ignore. */ (void)hwif->tp_ops->read_status(hwif); return 0; } else { /* drive wants a command packet, or invalid ireason... */ printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n", drive->name, __func__, ireason); } if (rq->cmd_type == REQ_TYPE_ATA_PC) rq->cmd_flags |= REQ_FAILED; return -1; }
static int ide_floppy_get_capacity(ide_drive_t *drive) { struct ide_disk_obj *floppy = drive->driver_data; struct gendisk *disk = floppy->disk; struct ide_atapi_pc pc; u8 *cap_desc; u8 pc_buf[256], header_len, desc_cnt; int i, rc = 1, blocks, length; ide_debug_log(IDE_DBG_FUNC, "enter"); drive->bios_cyl = 0; drive->bios_head = drive->bios_sect = 0; floppy->blocks = 0; floppy->bs_factor = 1; drive->capacity64 = 0; ide_floppy_create_read_capacity_cmd(&pc); if (ide_queue_pc_tail(drive, disk, &pc, pc_buf, pc.req_xfer)) { printk(KERN_ERR PFX "Can't get floppy parameters\n"); return 1; } header_len = pc_buf[3]; cap_desc = &pc_buf[4]; desc_cnt = header_len / 8; for (i = 0; i < desc_cnt; i++) { unsigned int desc_start = 4 + i*8; blocks = be32_to_cpup((__be32 *)&pc_buf[desc_start]); length = be16_to_cpup((__be16 *)&pc_buf[desc_start + 6]); ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, " "%d sector size", i, blocks * length / 1024, blocks, length); if (i) continue; switch (pc_buf[desc_start + 4] & 0x03) { case CAPACITY_UNFORMATTED: if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) break; case CAPACITY_CURRENT: if (memcmp(cap_desc, &floppy->cap_desc, 8)) printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d " "sector size\n", drive->name, blocks * length / 1024, blocks, length); memcpy(&floppy->cap_desc, cap_desc, 8); if (!length || length % 512) { printk(KERN_NOTICE PFX "%s: %d bytes block size" " not supported\n", drive->name, length); } else { floppy->blocks = blocks; floppy->block_size = length; floppy->bs_factor = length / 512; if (floppy->bs_factor != 1) printk(KERN_NOTICE PFX "%s: Warning: " "non 512 bytes block size not " "fully supported\n", drive->name); drive->capacity64 = floppy->blocks * floppy->bs_factor; rc = 0; } break; case CAPACITY_NO_CARTRIDGE: printk(KERN_ERR PFX "%s: No disk in drive\n", drive->name); break; case CAPACITY_INVALID: printk(KERN_ERR PFX "%s: Invalid capacity for disk " "in drive\n", drive->name); break; } ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d", pc_buf[desc_start + 4] & 0x03); } if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) (void) ide_floppy_get_flexible_disk_page(drive, &pc); return rc; }
static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, struct request *rq, sector_t block) { struct ide_disk_obj *floppy = drive->driver_data; struct ide_cmd cmd; struct ide_atapi_pc *pc; ide_debug_log(IDE_DBG_FUNC, "enter, cmd: 0x%x\n", rq->cmd[0]); if (drive->debug_mask & IDE_DBG_RQ) blk_dump_rq_flags(rq, (rq->rq_disk ? rq->rq_disk->disk_name : "dev?")); if (rq->errors >= ERROR_MAX) { if (drive->failed_pc) { ide_floppy_report_error(floppy, drive->failed_pc); drive->failed_pc = NULL; } else printk(KERN_ERR PFX "%s: I/O error\n", drive->name); if (blk_special_request(rq)) { rq->errors = 0; ide_complete_rq(drive, 0, blk_rq_bytes(rq)); return ide_stopped; } else goto out_end; } if (blk_fs_request(rq)) { if (((long)blk_rq_pos(rq) % floppy->bs_factor) || (blk_rq_sectors(rq) % floppy->bs_factor)) { printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", drive->name); goto out_end; } pc = &floppy->queued_pc; idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); } else if (blk_special_request(rq) || blk_sense_request(rq)) { pc = (struct ide_atapi_pc *)rq->special; } else if (blk_pc_request(rq)) { pc = &floppy->queued_pc; idefloppy_blockpc_cmd(floppy, pc, rq); } else BUG(); ide_prep_sense(drive, rq); memset(&cmd, 0, sizeof(cmd)); if (rq_data_dir(rq)) cmd.tf_flags |= IDE_TFLAG_WRITE; cmd.rq = rq; if (blk_fs_request(rq) || blk_rq_bytes(rq)) { ide_init_sg_cmd(&cmd, blk_rq_bytes(rq)); ide_map_sg(drive, &cmd); } pc->rq = rq; return ide_floppy_issue_pc(drive, &cmd, pc); out_end: drive->failed_pc = NULL; if (blk_fs_request(rq) == 0 && rq->errors == 0) rq->errors = -EIO; ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); return ide_stopped; }
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; struct ide_cmd *cmd = &hwif->cmd; struct request *rq = hwif->rq; ide_expiry_t *expiry = NULL; int dma_error = 0, dma, stat, thislen, uptodate = 0; int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc, nsectors; int sense = blk_sense_request(rq); unsigned int timeout; u16 len; u8 ireason; ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x", rq->cmd[0], write); /* check for errors */ dma = drive->dma; if (dma) { drive->dma = 0; drive->waiting_for_dma = 0; dma_error = hwif->dma_ops->dma_end(drive); ide_dma_unmap_sg(drive, cmd); if (dma_error) { printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name, write ? "write" : "read"); ide_dma_off(drive); } } rc = cdrom_decode_status(drive, 0, &stat); if (rc) { if (rc == 2) goto out_end; return ide_stopped; } /* using dma, transfer is complete now */ if (dma) { if (dma_error) return ide_error(drive, "dma error", stat); uptodate = 1; goto out_end; } ide_read_bcount_and_ireason(drive, &len, &ireason); thislen = blk_fs_request(rq) ? len : cmd->nleft; if (thislen > len) thislen = len; ide_debug_log(IDE_DBG_PC, "DRQ: stat: 0x%x, thislen: %d", stat, thislen); /* If DRQ is clear, the command has completed. */ if ((stat & ATA_DRQ) == 0) { if (blk_fs_request(rq)) { /* * If we're not done reading/writing, complain. * Otherwise, complete the command normally. */ uptodate = 1; if (cmd->nleft > 0) { printk(KERN_ERR PFX "%s: %s: data underrun " "(%u bytes)\n", drive->name, __func__, cmd->nleft); if (!write) rq->cmd_flags |= REQ_FAILED; uptodate = 0; } } else if (!blk_pc_request(rq)) { ide_cd_request_sense_fixup(drive, cmd); /* complain if we still have data left to transfer */ uptodate = cmd->nleft ? 0 : 1; if (uptodate == 0) rq->cmd_flags |= REQ_FAILED; } goto out_end; } /* check which way to transfer data */ rc = ide_cd_check_ireason(drive, rq, len, ireason, write); if (rc) goto out_end; cmd->last_xfer_len = 0; ide_debug_log(IDE_DBG_PC, "data transfer, rq->cmd_type: 0x%x, " "ireason: 0x%x", rq->cmd_type, ireason); /* transfer data */ while (thislen > 0) { int blen = min_t(int, thislen, cmd->nleft); if (cmd->nleft == 0) break; ide_pio_bytes(drive, cmd, write, blen); cmd->last_xfer_len += blen; thislen -= blen; len -= blen; if (sense && write == 0) rq->sense_len += blen; } /* pad, if necessary */ if (len > 0) { if (blk_fs_request(rq) == 0 || write == 0) ide_pad_transfer(drive, write, len); else { printk(KERN_ERR PFX "%s: confused, missing data\n", drive->name); blk_dump_rq_flags(rq, "cdrom_newpc_intr"); } } if (blk_pc_request(rq)) { timeout = rq->timeout; } else { timeout = ATAPI_WAIT_PC; if (!blk_fs_request(rq)) expiry = ide_cd_expiry; } hwif->expiry = expiry; ide_set_handler(drive, cdrom_newpc_intr, timeout); return ide_started; out_end: if (blk_pc_request(rq) && rc == 0) { unsigned int dlen = rq->data_len; rq->data_len = 0; if (blk_end_request(rq, 0, dlen)) BUG(); hwif->rq = NULL; } else { if (sense && uptodate) ide_cd_complete_failed_rq(drive, rq); if (blk_fs_request(rq)) { if (cmd->nleft == 0) uptodate = 1; } else { if (uptodate <= 0 && rq->errors == 0) rq->errors = -EIO; } if (uptodate == 0) ide_cd_error_cmd(drive, cmd); /* make sure it's fully ended */ if (blk_pc_request(rq)) nsectors = (rq->data_len + 511) >> 9; else nsectors = rq->hard_nr_sectors; if (nsectors == 0) nsectors = 1; if (blk_fs_request(rq) == 0) { rq->data_len -= (cmd->nbytes - cmd->nleft); if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE)) rq->data_len += cmd->last_xfer_len; } ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9); if (sense && rc == 2) ide_error(drive, "request sense failure", stat); }
int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, int write, void *buffer, unsigned *bufflen, struct request_sense *sense, int timeout, unsigned int cmd_flags) { struct cdrom_info *info = drive->driver_data; struct request_sense local_sense; int retries = 10; unsigned int flags = 0; if (!sense) sense = &local_sense; ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x, timeout: %d, " "cmd_flags: 0x%x", cmd[0], write, timeout, cmd_flags); /* start of retry loop */ do { struct request *rq; int error; rq = blk_get_request(drive->queue, write, __GFP_WAIT); memcpy(rq->cmd, cmd, BLK_MAX_CDB); rq->cmd_type = REQ_TYPE_ATA_PC; rq->sense = sense; rq->cmd_flags |= cmd_flags; rq->timeout = timeout; if (buffer) { rq->data = buffer; rq->data_len = *bufflen; } error = blk_execute_rq(drive->queue, info->disk, rq, 0); if (buffer) *bufflen = rq->data_len; flags = rq->cmd_flags; blk_put_request(rq); /* * FIXME: we should probably abort/retry or something in case of * failure. */ if (flags & REQ_FAILED) { /* * The request failed. Retry if it was due to a unit * attention status (usually means media was changed). */ struct request_sense *reqbuf = sense; if (reqbuf->sense_key == UNIT_ATTENTION) cdrom_saw_media_change(drive); else if (reqbuf->sense_key == NOT_READY && reqbuf->asc == 4 && reqbuf->ascq != 4) { /* * The drive is in the process of loading * a disk. Retry, but wait a little to give * the drive time to complete the load. */ ssleep(2); } else { /* otherwise, don't retry */ retries = 0; } --retries; } /* end of retry loop */ } while ((flags & REQ_FAILED) && retries >= 0); /* return an error if the command failed */ return (flags & REQ_FAILED) ? -EIO : 0; }
/* * Returns: * 0: if the request should be continued. * 1: if the request will be going through error recovery. * 2: if the request should be ended. */ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) { ide_hwif_t *hwif = drive->hwif; struct request *rq = hwif->rq; int stat, err, sense_key; /* check for errors */ stat = hwif->tp_ops->read_status(hwif); if (stat_ret) *stat_ret = stat; if (OK_STAT(stat, good_stat, BAD_R_STAT)) return 0; /* get the IDE error register */ err = ide_read_error(drive); sense_key = err >> 4; ide_debug_log(IDE_DBG_RQ, "stat: 0x%x, good_stat: 0x%x, cmd[0]: 0x%x, " "rq->cmd_type: 0x%x, err: 0x%x", stat, good_stat, rq->cmd[0], rq->cmd_type, err); if (blk_sense_request(rq)) { /* * We got an error trying to get sense info from the drive * (probably while trying to recover from a former error). * Just give up. */ rq->cmd_flags |= REQ_FAILED; return 2; } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) { /* All other functions, except for READ. */ /* * if we have an error, pass back CHECK_CONDITION as the * scsi status byte */ if (blk_pc_request(rq) && !rq->errors) rq->errors = SAM_STAT_CHECK_CONDITION; /* 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); return 0; } else if (sense_key == ILLEGAL_REQUEST && rq->cmd[0] == GPCMD_START_STOP_UNIT) { /* * Don't print error message for this condition-- * SFF8090i indicates that 5/24/00 is the correct * response to a request to close the tray if the * drive doesn't have that capability. * cdrom_log_sense() knows this! */ } else if (!(rq->cmd_flags & REQ_QUIET)) { /* otherwise, print an error */ ide_dump_status(drive, "packet command error", stat); } rq->cmd_flags |= REQ_FAILED; /* * instead of playing games with moving completions around, * remove failed request completely and end it when the * request sense has completed */ goto end_request; } else if (blk_fs_request(rq)) { int do_end_request = 0; /* handle errors from READ and WRITE requests */ if (blk_noretry_request(rq)) do_end_request = 1; if (sense_key == NOT_READY) { /* tray open */ if (rq_data_dir(rq) == READ) { cdrom_saw_media_change(drive); /* fail the request */ printk(KERN_ERR PFX "%s: tray open\n", drive->name); do_end_request = 1; } else { struct cdrom_info *info = drive->driver_data; /* * Allow the drive 5 seconds to recover, some * devices will return this error while flushing * data from cache. */ if (!rq->errors) info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY; rq->errors = 1; if (time_after(jiffies, info->write_timeout)) do_end_request = 1; else { struct request_queue *q = drive->queue; unsigned long flags; /* * take a breather relying on the unplug * timer to kick us again */ spin_lock_irqsave(q->queue_lock, flags); blk_plug_device(q); spin_unlock_irqrestore(q->queue_lock, flags); return 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) 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); 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 (sense_key == BLANK_CHECK) { /* disk appears blank ?? */ ide_dump_status(drive, "media error (blank)", stat); do_end_request = 1; } else if ((err & ~ATA_ABORTED) != 0) { /* go to the default handler for other errors */ ide_error(drive, "cdrom_decode_status", stat); return 1; } else if ((++rq->errors > ERROR_MAX)) { /* we've racked up too many retries, abort */ do_end_request = 1; } /* * End a request through request sense analysis when we have * sense data. We need this in order to perform end of media * processing. */ if (do_end_request) goto end_request; /* * If we got a CHECK_CONDITION status, queue * a request sense command. */ if (stat & ATA_ERR) cdrom_queue_request_sense(drive, NULL, NULL); return 1; } else { blk_dump_rq_flags(rq, PFX "bad rq"); return 2; } end_request: if (stat & ATA_ERR) { struct request_queue *q = drive->queue; unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); blkdev_dequeue_request(rq); spin_unlock_irqrestore(q->queue_lock, flags); hwif->rq = NULL; cdrom_queue_request_sense(drive, rq->sense, rq); return 1; } else return 2; }
/* * Determine if a media is present in the floppy drive, and if so, its LBA * capacity. */ static int ide_floppy_get_capacity(ide_drive_t *drive) { struct ide_disk_obj *floppy = drive->driver_data; struct gendisk *disk = floppy->disk; struct ide_atapi_pc pc; u8 *cap_desc; u8 pc_buf[256], header_len, desc_cnt; int i, rc = 1, blocks, length; pax_track_stack(); ide_debug_log(IDE_DBG_FUNC, "enter"); drive->bios_cyl = 0; drive->bios_head = drive->bios_sect = 0; floppy->blocks = 0; floppy->bs_factor = 1; drive->capacity64 = 0; ide_floppy_create_read_capacity_cmd(&pc); if (ide_queue_pc_tail(drive, disk, &pc, pc_buf, pc.req_xfer)) { printk(KERN_ERR PFX "Can't get floppy parameters\n"); return 1; } header_len = pc_buf[3]; cap_desc = &pc_buf[4]; desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ for (i = 0; i < desc_cnt; i++) { unsigned int desc_start = 4 + i*8; blocks = be32_to_cpup((__be32 *)&pc_buf[desc_start]); length = be16_to_cpup((__be16 *)&pc_buf[desc_start + 6]); ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, " "%d sector size", i, blocks * length / 1024, blocks, length); if (i) continue; /* * the code below is valid only for the 1st descriptor, ie i=0 */ switch (pc_buf[desc_start + 4] & 0x03) { /* Clik! drive returns this instead of CAPACITY_CURRENT */ case CAPACITY_UNFORMATTED: if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) /* * If it is not a clik drive, break out * (maintains previous driver behaviour) */ break; case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */ if (memcmp(cap_desc, &floppy->cap_desc, 8)) printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d " "sector size\n", drive->name, blocks * length / 1024, blocks, length); memcpy(&floppy->cap_desc, cap_desc, 8); if (!length || length % 512) { printk(KERN_NOTICE PFX "%s: %d bytes block size" " not supported\n", drive->name, length); } else { floppy->blocks = blocks; floppy->block_size = length; floppy->bs_factor = length / 512; if (floppy->bs_factor != 1) printk(KERN_NOTICE PFX "%s: Warning: " "non 512 bytes block size not " "fully supported\n", drive->name); drive->capacity64 = floppy->blocks * floppy->bs_factor; rc = 0; } break; case CAPACITY_NO_CARTRIDGE: /* * This is a KERN_ERR so it appears on screen * for the user to see */ printk(KERN_ERR PFX "%s: No disk in drive\n", drive->name); break; case CAPACITY_INVALID: printk(KERN_ERR PFX "%s: Invalid capacity for disk " "in drive\n", drive->name); break; } ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d", pc_buf[desc_start + 4] & 0x03); } /* Clik! disk does not support get_flexible_disk_page */ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) (void) ide_floppy_get_flexible_disk_page(drive, &pc); return rc; }
static void cdrom_analyze_sense_data(ide_drive_t *drive, struct request *failed_command, struct request_sense *sense) { unsigned long sector; unsigned long bio_sectors; struct cdrom_info *info = drive->driver_data; ide_debug_log(IDE_DBG_SENSE, "error_code: 0x%x, sense_key: 0x%x", sense->error_code, sense->sense_key); if (failed_command) ide_debug_log(IDE_DBG_SENSE, "failed cmd: 0x%x", failed_command->cmd[0]); if (!cdrom_log_sense(drive, failed_command, sense)) return; /* * If a read toc is executed for a CD-R or CD-RW medium where the first * toc has not been recorded yet, it will fail with 05/24/00 (which is a * confusing error) */ if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP) if (sense->sense_key == 0x05 && sense->asc == 0x24) return; /* current error */ if (sense->error_code == 0x70) { switch (sense->sense_key) { case MEDIUM_ERROR: case VOLUME_OVERFLOW: case ILLEGAL_REQUEST: if (!sense->valid) break; if (failed_command == NULL || !blk_fs_request(failed_command)) break; sector = (sense->information[0] << 24) | (sense->information[1] << 16) | (sense->information[2] << 8) | (sense->information[3]); if (drive->queue->hardsect_size == 2048) /* device sector size is 2K */ sector <<= 2; bio_sectors = max(bio_sectors(failed_command->bio), 4U); sector &= ~(bio_sectors - 1); /* * The SCSI specification allows for the value * returned by READ CAPACITY to be up to 75 2K * sectors past the last readable block. * Therefore, if we hit a medium error within the * last 75 2K sectors, we decrease the saved size * value. */ if (sector < get_capacity(info->disk) && drive->probed_capacity - sector < 4 * 75) set_capacity(info->disk, sector); } } ide_cd_log_error(drive->name, failed_command, sense); }