diff --git a/sys/dev/virtio/scsi/virtio_scsi.h b/sys/dev/virtio/scsi/virtio_scsi.h --- a/sys/dev/virtio/scsi/virtio_scsi.h +++ b/sys/dev/virtio/scsi/virtio_scsi.h @@ -31,13 +31,7 @@ #ifndef _VIRTIO_SCSI_H #define _VIRTIO_SCSI_H -/* Feature bits */ -#define VIRTIO_SCSI_F_INOUT 0x0001 /* Single request can contain both - * read and write buffers */ -#define VIRTIO_SCSI_F_HOTPLUG 0x0002 /* Host should enable hot plug/unplug - * of new LUNs and targets. - */ - +/* Default values of the CDB and sense data size configuration fields */ #define VIRTIO_SCSI_CDB_SIZE 32 #define VIRTIO_SCSI_SENSE_SIZE 96 @@ -46,8 +40,20 @@ uint8_t lun[8]; /* Logical Unit Number */ uint64_t tag; /* Command identifier */ uint8_t task_attr; /* Task attribute */ - uint8_t prio; + uint8_t prio; /* SAM command priority field */ + uint8_t crn; + uint8_t cdb[VIRTIO_SCSI_CDB_SIZE]; +} __packed; + +/* SCSI command request, followed by protection information */ +struct virtio_scsi_cmd_req_pi { + uint8_t lun[8]; /* Logical Unit Number */ + uint64_t tag; /* Command identifier */ + uint8_t task_attr; /* Task attribute */ + uint8_t prio; /* SAM command priority field */ uint8_t crn; + uint32_t pi_bytesout; /* DataOUT PI Number of bytes */ + uint32_t pi_bytesin; /* DataIN PI Number of bytes */ uint8_t cdb[VIRTIO_SCSI_CDB_SIZE]; } __packed; @@ -104,6 +110,22 @@ uint32_t max_lun; } __packed; +/* Feature bits */ +#define VIRTIO_SCSI_F_INOUT 0x0001 /* Single request can contain both + * read and write buffers. + */ +#define VIRTIO_SCSI_F_HOTPLUG 0x0002 /* Host should enable hot plug/unplug + * of new LUNs and targets. + */ +#define VIRTIO_SCSI_F_CHANGE 0x0004 /* Host will report changes to LUN + * parameters via a + * VIRTIO_SCSI_T_PARAM_CHANGE event. + */ +#define VIRTIO_SCSI_F_T10_PI 0x0008 /* Extended fields for T10 protection + * information (DIF/DIX) are included + * in the SCSI request header. + */ + /* Response codes */ #define VIRTIO_SCSI_S_OK 0 #define VIRTIO_SCSI_S_FUNCTION_COMPLETE 0 @@ -140,6 +162,7 @@ #define VIRTIO_SCSI_T_NO_EVENT 0 #define VIRTIO_SCSI_T_TRANSPORT_RESET 1 #define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 +#define VIRTIO_SCSI_T_PARAM_CHANGE 3 /* Reasons of transport reset event */ #define VIRTIO_SCSI_EVT_RESET_HARD 0 diff --git a/sys/dev/virtio/scsi/virtio_scsi.c b/sys/dev/virtio/scsi/virtio_scsi.c --- a/sys/dev/virtio/scsi/virtio_scsi.c +++ b/sys/dev/virtio/scsi/virtio_scsi.c @@ -135,10 +135,10 @@ static void vtscsi_get_request_lun(uint8_t [], target_id_t *, lun_id_t *); static void vtscsi_set_request_lun(struct ccb_hdr *, uint8_t []); -static void vtscsi_init_scsi_cmd_req(struct ccb_scsiio *, - struct virtio_scsi_cmd_req *); -static void vtscsi_init_ctrl_tmf_req(struct ccb_hdr *, uint32_t, - uintptr_t, struct virtio_scsi_ctrl_tmf_req *); +static void vtscsi_init_scsi_cmd_req(struct vtscsi_softc *, + struct ccb_scsiio *, struct virtio_scsi_cmd_req *); +static void vtscsi_init_ctrl_tmf_req(struct vtscsi_softc *, struct ccb_hdr *, + uint32_t, uintptr_t, struct virtio_scsi_ctrl_tmf_req *); static void vtscsi_freeze_simq(struct vtscsi_softc *, int); static int vtscsi_thaw_simq(struct vtscsi_softc *, int); @@ -189,6 +189,14 @@ static void vtscsi_printf_req(struct vtscsi_request *, const char *, const char *, ...); +#define vtscsi_modern(_sc) (((_sc)->vtscsi_features & VIRTIO_F_VERSION_1) != 0) +#define vtscsi_htog16(_sc, _val) virtio_htog16(vtscsi_modern(_sc), _val) +#define vtscsi_htog32(_sc, _val) virtio_htog32(vtscsi_modern(_sc), _val) +#define vtscsi_htog64(_sc, _val) virtio_htog64(vtscsi_modern(_sc), _val) +#define vtscsi_gtoh16(_sc, _val) virtio_gtoh16(vtscsi_modern(_sc), _val) +#define vtscsi_gtoh32(_sc, _val) virtio_gtoh32(vtscsi_modern(_sc), _val) +#define vtscsi_gtoh64(_sc, _val) virtio_gtoh64(vtscsi_modern(_sc), _val) + /* Global tunables. */ /* * The current QEMU VirtIO SCSI implementation does not cancel in-flight @@ -206,6 +214,9 @@ static struct virtio_feature_desc vtscsi_feature_desc[] = { { VIRTIO_SCSI_F_INOUT, "InOut" }, { VIRTIO_SCSI_F_HOTPLUG, "Hotplug" }, + { VIRTIO_SCSI_F_CHANGE, "ChangeEvent" }, + { VIRTIO_SCSI_F_T10_PI, "T10PI" }, + { 0, NULL } }; @@ -409,8 +420,10 @@ uint64_t features; dev = sc->vtscsi_dev; - features = virtio_negotiate_features(dev, VTSCSI_FEATURES); - sc->vtscsi_features = features; + features = VTSCSI_FEATURES; + + sc->vtscsi_features = virtio_negotiate_features(dev, features); + virtio_finalize_features(dev); } #define VTSCSI_GET_CONFIG(_dev, _field, _cfg) \ @@ -530,8 +543,8 @@ error = virtio_reinit(dev, sc->vtscsi_features); if (error == 0) { vtscsi_write_device_config(sc); - vtscsi_reinit_event_vq(sc); virtio_reinit_complete(dev); + vtscsi_reinit_event_vq(sc); vtscsi_enable_vqs_intr(sc); } @@ -1085,7 +1098,7 @@ cmd_req = &req->vsr_cmd_req; cmd_resp = &req->vsr_cmd_resp; - vtscsi_init_scsi_cmd_req(csio, cmd_req); + vtscsi_init_scsi_cmd_req(sc, csio, cmd_req); error = vtscsi_fill_scsi_cmd_sglist(sc, req, &readable, &writable); if (error) @@ -1205,7 +1218,7 @@ tmf_req = &req->vsr_tmf_req; tmf_resp = &req->vsr_tmf_resp; - vtscsi_init_ctrl_tmf_req(to_ccbh, VIRTIO_SCSI_T_TMF_ABORT_TASK, + vtscsi_init_ctrl_tmf_req(sc, to_ccbh, VIRTIO_SCSI_T_TMF_ABORT_TASK, (uintptr_t) to_ccbh, tmf_req); sglist_reset(sg); @@ -1313,22 +1326,24 @@ vtscsi_complete_scsi_cmd_response(struct vtscsi_softc *sc, struct ccb_scsiio *csio, struct virtio_scsi_cmd_resp *cmd_resp) { + uint32_t resp_sense_length; cam_status status; csio->scsi_status = cmd_resp->status; - csio->resid = cmd_resp->resid; + csio->resid = vtscsi_htog32(sc, cmd_resp->resid); if (csio->scsi_status == SCSI_STATUS_OK) status = CAM_REQ_CMP; else status = CAM_SCSI_STATUS_ERROR; - if (cmd_resp->sense_len > 0) { + resp_sense_length = vtscsi_htog32(sc, cmd_resp->sense_len); + + if (resp_sense_length > 0) { status |= CAM_AUTOSNS_VALID; - if (cmd_resp->sense_len < csio->sense_len) - csio->sense_resid = csio->sense_len - - cmd_resp->sense_len; + if (resp_sense_length < csio->sense_len) + csio->sense_resid = csio->sense_len - resp_sense_length; else csio->sense_resid = 0; @@ -1493,7 +1508,7 @@ if (abort_req->vsr_flags & VTSCSI_REQ_FLAG_TIMEOUT_SET) callout_stop(&abort_req->vsr_callout); - vtscsi_init_ctrl_tmf_req(ccbh, VIRTIO_SCSI_T_TMF_ABORT_TASK, + vtscsi_init_ctrl_tmf_req(sc, ccbh, VIRTIO_SCSI_T_TMF_ABORT_TASK, (uintptr_t) abort_ccbh, tmf_req); sglist_reset(sg); @@ -1562,7 +1577,7 @@ else subtype = VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET; - vtscsi_init_ctrl_tmf_req(ccbh, subtype, 0, tmf_req); + vtscsi_init_ctrl_tmf_req(sc, ccbh, subtype, 0, tmf_req); sglist_reset(sg); sglist_append(sg, tmf_req, sizeof(struct virtio_scsi_ctrl_tmf_req)); @@ -1599,7 +1614,7 @@ } static void -vtscsi_init_scsi_cmd_req(struct ccb_scsiio *csio, +vtscsi_init_scsi_cmd_req(struct vtscsi_softc *sc, struct ccb_scsiio *csio, struct virtio_scsi_cmd_req *cmd_req) { uint8_t attr; @@ -1620,7 +1635,7 @@ } vtscsi_set_request_lun(&csio->ccb_h, cmd_req->lun); - cmd_req->tag = (uintptr_t) csio; + cmd_req->tag = vtscsi_gtoh64(sc, (uintptr_t) csio); cmd_req->task_attr = attr; memcpy(cmd_req->cdb, @@ -1630,15 +1645,15 @@ } static void -vtscsi_init_ctrl_tmf_req(struct ccb_hdr *ccbh, uint32_t subtype, - uintptr_t tag, struct virtio_scsi_ctrl_tmf_req *tmf_req) +vtscsi_init_ctrl_tmf_req(struct vtscsi_softc *sc, struct ccb_hdr *ccbh, + uint32_t subtype, uintptr_t tag, struct virtio_scsi_ctrl_tmf_req *tmf_req) { vtscsi_set_request_lun(ccbh, tmf_req->lun); - tmf_req->type = VIRTIO_SCSI_T_TMF; - tmf_req->subtype = subtype; - tmf_req->tag = tag; + tmf_req->type = vtscsi_gtoh32(sc, VIRTIO_SCSI_T_TMF); + tmf_req->subtype = vtscsi_gtoh32(sc, subtype); + tmf_req->tag = vtscsi_gtoh64(sc, tag); } static void