/* * Prepare a MMC request. Essentially, this means passing the * preparation off to the media driver. The media driver will * create a mmc_io_request in req->special. */ static int mmc_prep_request(struct request_queue *q, struct request *req) { struct mmc_queue *mq = q->queuedata; int ret = BLKPREP_KILL; if (blk_special_request(req)) { /* * Special commands already have the command * blocks already setup in req->special. */ BUG_ON(!req->special); ret = BLKPREP_OK; } else if (blk_fs_request(req) || blk_pc_request(req)) { /* * Block I/O requests need translating according * to the protocol. */ ret = mq->prep_fn(mq, req); } else { /* * Everything else is invalid. */ blk_dump_rq_flags(req, "MMC bad request"); } if (ret == BLKPREP_OK) req->cmd_flags |= REQ_DONTPREP; return ret; }
static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); struct request *rq = HWGROUP(drive)->rq; struct ide_atapi_pc *pc = (struct ide_atapi_pc *) rq->special; int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); struct Scsi_Host *host; int errors = rq->errors; unsigned long flags; if (!blk_special_request(rq) && !blk_sense_request(rq)) { ide_end_request(drive, uptodate, nrsecs); return 0; } ide_end_drive_cmd (drive, 0, 0); if (blk_sense_request(rq)) { struct ide_atapi_pc *opc = (struct ide_atapi_pc *) rq->buffer; if (log) { printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number); ide_scsi_hex_dump(pc->buf, 16); } memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buf, SCSI_SENSE_BUFFERSIZE); kfree(pc->buf); kfree(pc); blk_put_request(rq); pc = opc; rq = pc->rq; pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (((pc->flags & PC_FLAG_TIMEDOUT) ? DID_TIME_OUT : DID_OK) << 16); } else if (pc->flags & PC_FLAG_TIMEDOUT) { if (log) printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n", drive->name, pc->scsi_cmd->serial_number); pc->scsi_cmd->result = DID_TIME_OUT << 16; } else if (errors >= ERROR_MAX) { pc->scsi_cmd->result = DID_ERROR << 16; if (log) printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number); } else if (errors) { if (log) printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number); if (!idescsi_check_condition(drive, rq)) /* we started a request sense, so we'll be back, exit for now */ return 0; pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); } else { pc->scsi_cmd->result = DID_OK << 16; } host = pc->scsi_cmd->device->host; spin_lock_irqsave(host->host_lock, flags); pc->done(pc->scsi_cmd); spin_unlock_irqrestore(host->host_lock, flags); kfree(pc); blk_put_request(rq); scsi->pc = NULL; return 0; }
void ide_kill_rq(ide_drive_t *drive, struct request *rq) { u8 drv_req = blk_special_request(rq) && rq->rq_disk; u8 media = drive->media; drive->failed_pc = NULL; if ((media == ide_floppy || media == ide_tape) && drv_req) { rq->errors = 0; } else { if (media == ide_tape) rq->errors = IDE_DRV_ERROR_GENERAL; else if (blk_fs_request(rq) == 0 && rq->errors == 0) rq->errors = -EIO; } ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); }
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; }
/* * idescsi_do_request is our request handling function. */ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, sector_t block) { debug_log("dev: %s, cmd: %x, errors: %d\n", rq->rq_disk->disk_name, rq->cmd[0], rq->errors); debug_log("sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n", rq->sector, rq->nr_sectors, rq->current_nr_sectors); if (blk_sense_request(rq) || blk_special_request(rq)) { struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special; if (drive->using_dma && !idescsi_map_sg(drive, pc)) pc->flags |= PC_FLAG_DMA_OK; return idescsi_issue_pc(drive, pc); } blk_dump_rq_flags(rq, "ide-scsi: unsup command"); idescsi_end_request (drive, 0, 0); return ide_stopped; }
static int card_prep_request(struct request_queue *q, struct request *req) { struct card_queue *cq = q->queuedata; int ret = BLKPREP_KILL; if (!cq) { //printk(KERN_ERR "[card_prep_request] %s: killing request - no device/host\n", req->rq_disk->disk_name); return BLKPREP_KILL; } if (blk_special_request(req)) { /* * Special commands already have the command * blocks already setup in req->special. */ BUG_ON(!req->special); ret = BLKPREP_OK; } else if (blk_fs_request(req) || blk_pc_request(req)) { /* * Block I/O requests need translating according * to the protocol. */ ret = cq->prep_fn(cq, req); } else { /* * Everything else is invalid. */ blk_dump_rq_flags(req, "CARD bad request"); } if (ret == BLKPREP_OK) req->cmd_flags |= REQ_DONTPREP; return ret; }
static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; BUG_ON(!blk_rq_started(rq)); #ifdef DEBUG printk("%s: start_request: current=0x%08lx\n", drive->hwif->name, (unsigned long) rq); #endif /* bail early if we've exceeded max_failures */ if (drive->max_failures && (drive->failures > drive->max_failures)) { rq->cmd_flags |= REQ_FAILED; goto kill_rq; } if (blk_pm_request(rq)) ide_check_pm_state(drive, rq); SELECT_DRIVE(drive); if (ide_wait_stat(&startstop, drive, drive->ready_stat, ATA_BUSY | ATA_DRQ, WAIT_READY)) { printk(KERN_ERR "%s: drive not ready for command\n", drive->name); return startstop; } if (!drive->special.all) { struct ide_driver *drv; /* * We reset the drive so we need to issue a SETFEATURES. * Do it _after_ do_special() restored device parameters. */ if (drive->current_speed == 0xff) ide_config_drive_speed(drive, drive->desired_speed); if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) return execute_drive_cmd(drive, rq); else if (blk_pm_request(rq)) { struct request_pm_state *pm = rq->data; #ifdef DEBUG_PM printk("%s: start_power_step(step: %d)\n", drive->name, pm->pm_step); #endif startstop = ide_start_power_step(drive, rq); if (startstop == ide_stopped && pm->pm_step == IDE_PM_COMPLETED) ide_complete_pm_request(drive, rq); return startstop; } else if (!rq->rq_disk && blk_special_request(rq)) /* * TODO: Once all ULDs have been modified to * check for specific op codes rather than * blindly accepting any special request, the * check for ->rq_disk above may be replaced * by a more suitable mechanism or even * dropped entirely. */ return ide_special_rq(drive, rq); drv = *(struct ide_driver **)rq->rq_disk->private_data; return drv->do_request(drive, rq, rq->sector); } return do_special(drive); kill_rq: ide_kill_rq(drive, rq); return ide_stopped; }
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; }