void ata_timeout(struct ata_request *request) { struct ata_channel *ch; ch = device_get_softc(request->parent); //request->flags |= ATA_R_DEBUG; ATA_DEBUG_RQ(request, "timeout"); /* * If we have an ATA_ACTIVE request running, we flag the request * ATA_R_TIMEOUT so ata_cam_end_transaction() will handle it correctly. * Also, NULL out the running request so we wont loose the race with * an eventual interrupt arriving late. */ if (ch->state == ATA_ACTIVE) { request->flags |= ATA_R_TIMEOUT; if (ch->dma.unload) ch->dma.unload(request); ch->running = NULL; ch->state = ATA_IDLE; ata_cam_end_transaction(ch->dev, request); } mtx_unlock(&ch->state_mtx); }
static void ata_interrupt_locked(void *data) { struct ata_channel *ch = (struct ata_channel *)data; struct ata_request *request; /* ignore interrupt if its not for us */ if (ch->hw.status && !ch->hw.status(ch->dev)) return; /* do we have a running request */ if (!(request = ch->running)) return; ATA_DEBUG_RQ(request, "interrupt"); /* safetycheck for the right state */ if (ch->state == ATA_IDLE) { device_printf(request->dev, "interrupt on idle channel ignored\n"); return; } /* * we have the HW locks, so end the transaction for this request * if it finishes immediately otherwise wait for next interrupt */ if (ch->hw.end_transaction(request) == ATA_OP_FINISHED) { ch->running = NULL; if (ch->state == ATA_ACTIVE) ch->state = ATA_IDLE; ata_cam_end_transaction(ch->dev, request); return; } }
static void ata_cam_request_sense(device_t dev, struct ata_request *request) { struct ata_channel *ch = device_get_softc(dev); union ccb *ccb = request->ccb; ch->requestsense = 1; bzero(request, sizeof(*request)); request->dev = NULL; request->parent = dev; request->unit = ccb->ccb_h.target_id; request->data = (void *)&ccb->csio.sense_data; request->bytecount = ccb->csio.sense_len; request->u.atapi.ccb[0] = ATAPI_REQUEST_SENSE; request->u.atapi.ccb[4] = ccb->csio.sense_len; request->flags |= ATA_R_ATAPI; if (ch->curr[ccb->ccb_h.target_id].atapi == 16) request->flags |= ATA_R_ATAPI16; if (ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA) request->flags |= ATA_R_DMA; request->flags |= ATA_R_READ; request->transfersize = min(request->bytecount, ch->curr[ccb->ccb_h.target_id].bytecount); request->retries = 0; request->timeout = (ccb->ccb_h.timeout + 999) / 1000; callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED); request->ccb = ccb; ch->running = request; ch->state = ATA_ACTIVE; if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) { ch->running = NULL; ch->state = ATA_IDLE; ata_cam_end_transaction(dev, request); return; } }
int ata_reinit(device_t dev) { struct ata_channel *ch = device_get_softc(dev); struct ata_request *request; xpt_freeze_simq(ch->sim, 1); if ((request = ch->running)) { ch->running = NULL; if (ch->state == ATA_ACTIVE) ch->state = ATA_IDLE; callout_stop(&request->callout); if (ch->dma.unload) ch->dma.unload(request); request->result = ERESTART; ata_cam_end_transaction(dev, request); } /* reset the controller HW, the channel and device(s) */ ATA_RESET(dev); /* Tell the XPT about the event */ xpt_async(AC_BUS_RESET, ch->path, NULL); xpt_release_simq(ch->sim, TRUE); return(0); }
static void ata_cam_begin_transaction(device_t dev, union ccb *ccb) { struct ata_channel *ch = device_get_softc(dev); struct ata_request *request; if (!(request = ata_alloc_request())) { device_printf(dev, "FAILURE - out of memory in start\n"); ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); return; } bzero(request, sizeof(*request)); /* setup request */ request->dev = NULL; request->parent = dev; request->unit = ccb->ccb_h.target_id; if (ccb->ccb_h.func_code == XPT_ATA_IO) { request->data = ccb->ataio.data_ptr; request->bytecount = ccb->ataio.dxfer_len; request->u.ata.command = ccb->ataio.cmd.command; request->u.ata.feature = ((uint16_t)ccb->ataio.cmd.features_exp << 8) | (uint16_t)ccb->ataio.cmd.features; request->u.ata.count = ((uint16_t)ccb->ataio.cmd.sector_count_exp << 8) | (uint16_t)ccb->ataio.cmd.sector_count; if (ccb->ataio.cmd.flags & CAM_ATAIO_48BIT) { request->flags |= ATA_R_48BIT; request->u.ata.lba = ((uint64_t)ccb->ataio.cmd.lba_high_exp << 40) | ((uint64_t)ccb->ataio.cmd.lba_mid_exp << 32) | ((uint64_t)ccb->ataio.cmd.lba_low_exp << 24); } else { request->u.ata.lba = ((uint64_t)(ccb->ataio.cmd.device & 0x0f) << 24); } request->u.ata.lba |= ((uint64_t)ccb->ataio.cmd.lba_high << 16) | ((uint64_t)ccb->ataio.cmd.lba_mid << 8) | (uint64_t)ccb->ataio.cmd.lba_low; if (ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT) request->flags |= ATA_R_NEEDRESULT; if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE && ccb->ataio.cmd.flags & CAM_ATAIO_DMA) request->flags |= ATA_R_DMA; if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) request->flags |= ATA_R_READ; if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) request->flags |= ATA_R_WRITE; if (ccb->ataio.cmd.command == ATA_READ_MUL || ccb->ataio.cmd.command == ATA_READ_MUL48 || ccb->ataio.cmd.command == ATA_WRITE_MUL || ccb->ataio.cmd.command == ATA_WRITE_MUL48) { request->transfersize = min(request->bytecount, ch->curr[ccb->ccb_h.target_id].bytecount); } else request->transfersize = min(request->bytecount, 512); } else { request->data = ccb->csio.data_ptr; request->bytecount = ccb->csio.dxfer_len; bcopy((ccb->ccb_h.flags & CAM_CDB_POINTER) ? ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes, request->u.atapi.ccb, ccb->csio.cdb_len); request->flags |= ATA_R_ATAPI; if (ch->curr[ccb->ccb_h.target_id].atapi == 16) request->flags |= ATA_R_ATAPI16; if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE && ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA) request->flags |= ATA_R_DMA; if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) request->flags |= ATA_R_READ; if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) request->flags |= ATA_R_WRITE; request->transfersize = min(request->bytecount, ch->curr[ccb->ccb_h.target_id].bytecount); } request->retries = 0; request->timeout = (ccb->ccb_h.timeout + 999) / 1000; callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED); request->ccb = ccb; request->flags |= ATA_R_DATA_IN_CCB; ch->running = request; ch->state = ATA_ACTIVE; if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) { ch->running = NULL; ch->state = ATA_IDLE; ata_cam_end_transaction(dev, request); return; } }