qemu/hw/usb/dev-uas.c
<<
>>
Prefs
   1/*
   2 * UAS (USB Attached SCSI) emulation
   3 *
   4 * Copyright Red Hat, Inc. 2012
   5 *
   6 * Author: Gerd Hoffmann <kraxel@redhat.com>
   7 *
   8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
   9 * See the COPYING file in the top-level directory.
  10 */
  11
  12#include "qemu-common.h"
  13#include "qemu/option.h"
  14#include "qemu/config-file.h"
  15#include "trace.h"
  16
  17#include "hw/usb.h"
  18#include "hw/usb/desc.h"
  19#include "hw/scsi/scsi.h"
  20#include "block/scsi.h"
  21
  22/* --------------------------------------------------------------------- */
  23
  24#define UAS_UI_COMMAND              0x01
  25#define UAS_UI_SENSE                0x03
  26#define UAS_UI_RESPONSE             0x04
  27#define UAS_UI_TASK_MGMT            0x05
  28#define UAS_UI_READ_READY           0x06
  29#define UAS_UI_WRITE_READY          0x07
  30
  31#define UAS_RC_TMF_COMPLETE         0x00
  32#define UAS_RC_INVALID_INFO_UNIT    0x02
  33#define UAS_RC_TMF_NOT_SUPPORTED    0x04
  34#define UAS_RC_TMF_FAILED           0x05
  35#define UAS_RC_TMF_SUCCEEDED        0x08
  36#define UAS_RC_INCORRECT_LUN        0x09
  37#define UAS_RC_OVERLAPPED_TAG       0x0a
  38
  39#define UAS_TMF_ABORT_TASK          0x01
  40#define UAS_TMF_ABORT_TASK_SET      0x02
  41#define UAS_TMF_CLEAR_TASK_SET      0x04
  42#define UAS_TMF_LOGICAL_UNIT_RESET  0x08
  43#define UAS_TMF_I_T_NEXUS_RESET     0x10
  44#define UAS_TMF_CLEAR_ACA           0x40
  45#define UAS_TMF_QUERY_TASK          0x80
  46#define UAS_TMF_QUERY_TASK_SET      0x81
  47#define UAS_TMF_QUERY_ASYNC_EVENT   0x82
  48
  49#define UAS_PIPE_ID_COMMAND         0x01
  50#define UAS_PIPE_ID_STATUS          0x02
  51#define UAS_PIPE_ID_DATA_IN         0x03
  52#define UAS_PIPE_ID_DATA_OUT        0x04
  53
  54typedef struct {
  55    uint8_t    id;
  56    uint8_t    reserved;
  57    uint16_t   tag;
  58} QEMU_PACKED  uas_ui_header;
  59
  60typedef struct {
  61    uint8_t    prio_taskattr;   /* 6:3 priority, 2:0 task attribute   */
  62    uint8_t    reserved_1;
  63    uint8_t    add_cdb_length;  /* 7:2 additional adb length (dwords) */
  64    uint8_t    reserved_2;
  65    uint64_t   lun;
  66    uint8_t    cdb[16];
  67    uint8_t    add_cdb[];
  68} QEMU_PACKED  uas_ui_command;
  69
  70typedef struct {
  71    uint16_t   status_qualifier;
  72    uint8_t    status;
  73    uint8_t    reserved[7];
  74    uint16_t   sense_length;
  75    uint8_t    sense_data[18];
  76} QEMU_PACKED  uas_ui_sense;
  77
  78typedef struct {
  79    uint16_t   add_response_info;
  80    uint8_t    response_code;
  81} QEMU_PACKED  uas_ui_response;
  82
  83typedef struct {
  84    uint8_t    function;
  85    uint8_t    reserved;
  86    uint16_t   task_tag;
  87    uint64_t   lun;
  88} QEMU_PACKED  uas_ui_task_mgmt;
  89
  90typedef struct {
  91    uas_ui_header  hdr;
  92    union {
  93        uas_ui_command   command;
  94        uas_ui_sense     sense;
  95        uas_ui_task_mgmt task;
  96        uas_ui_response  response;
  97    };
  98} QEMU_PACKED  uas_ui;
  99
 100/* --------------------------------------------------------------------- */
 101
 102#define UAS_STREAM_BM_ATTR  4
 103#define UAS_MAX_STREAMS     (1 << UAS_STREAM_BM_ATTR)
 104
 105typedef struct UASDevice UASDevice;
 106typedef struct UASRequest UASRequest;
 107typedef struct UASStatus UASStatus;
 108
 109struct UASDevice {
 110    USBDevice                 dev;
 111    SCSIBus                   bus;
 112    QEMUBH                    *status_bh;
 113    QTAILQ_HEAD(, UASStatus)  results;
 114    QTAILQ_HEAD(, UASRequest) requests;
 115
 116    /* usb 2.0 only */
 117    USBPacket                 *status2;
 118    UASRequest                *datain2;
 119    UASRequest                *dataout2;
 120
 121    /* usb 3.0 only */
 122    USBPacket                 *data3[UAS_MAX_STREAMS];
 123    USBPacket                 *status3[UAS_MAX_STREAMS];
 124};
 125
 126struct UASRequest {
 127    uint16_t     tag;
 128    uint64_t     lun;
 129    UASDevice    *uas;
 130    SCSIDevice   *dev;
 131    SCSIRequest  *req;
 132    USBPacket    *data;
 133    bool         data_async;
 134    bool         active;
 135    bool         complete;
 136    uint32_t     buf_off;
 137    uint32_t     buf_size;
 138    uint32_t     data_off;
 139    uint32_t     data_size;
 140    QTAILQ_ENTRY(UASRequest)  next;
 141};
 142
 143struct UASStatus {
 144    uint32_t                  stream;
 145    uas_ui                    status;
 146    uint32_t                  length;
 147    QTAILQ_ENTRY(UASStatus)   next;
 148};
 149
 150/* --------------------------------------------------------------------- */
 151
 152enum {
 153    STR_MANUFACTURER = 1,
 154    STR_PRODUCT,
 155    STR_SERIALNUMBER,
 156    STR_CONFIG_HIGH,
 157    STR_CONFIG_SUPER,
 158};
 159
 160static const USBDescStrings desc_strings = {
 161    [STR_MANUFACTURER] = "QEMU",
 162    [STR_PRODUCT]      = "USB Attached SCSI HBA",
 163    [STR_SERIALNUMBER] = "27842",
 164    [STR_CONFIG_HIGH]  = "High speed config (usb 2.0)",
 165    [STR_CONFIG_SUPER] = "Super speed config (usb 3.0)",
 166};
 167
 168static const USBDescIface desc_iface_high = {
 169    .bInterfaceNumber              = 0,
 170    .bNumEndpoints                 = 4,
 171    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
 172    .bInterfaceSubClass            = 0x06, /* SCSI */
 173    .bInterfaceProtocol            = 0x62, /* UAS  */
 174    .eps = (USBDescEndpoint[]) {
 175        {
 176            .bEndpointAddress      = USB_DIR_OUT | UAS_PIPE_ID_COMMAND,
 177            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 178            .wMaxPacketSize        = 512,
 179            .extra = (uint8_t[]) {
 180                0x04,  /*  u8  bLength */
 181                0x24,  /*  u8  bDescriptorType */
 182                UAS_PIPE_ID_COMMAND,
 183                0x00,  /*  u8  bReserved */
 184            },
 185        },{
 186            .bEndpointAddress      = USB_DIR_IN | UAS_PIPE_ID_STATUS,
 187            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 188            .wMaxPacketSize        = 512,
 189            .extra = (uint8_t[]) {
 190                0x04,  /*  u8  bLength */
 191                0x24,  /*  u8  bDescriptorType */
 192                UAS_PIPE_ID_STATUS,
 193                0x00,  /*  u8  bReserved */
 194            },
 195        },{
 196            .bEndpointAddress      = USB_DIR_IN | UAS_PIPE_ID_DATA_IN,
 197            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 198            .wMaxPacketSize        = 512,
 199            .extra = (uint8_t[]) {
 200                0x04,  /*  u8  bLength */
 201                0x24,  /*  u8  bDescriptorType */
 202                UAS_PIPE_ID_DATA_IN,
 203                0x00,  /*  u8  bReserved */
 204            },
 205        },{
 206            .bEndpointAddress      = USB_DIR_OUT | UAS_PIPE_ID_DATA_OUT,
 207            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 208            .wMaxPacketSize        = 512,
 209            .extra = (uint8_t[]) {
 210                0x04,  /*  u8  bLength */
 211                0x24,  /*  u8  bDescriptorType */
 212                UAS_PIPE_ID_DATA_OUT,
 213                0x00,  /*  u8  bReserved */
 214            },
 215        },
 216    }
 217};
 218
 219static const USBDescIface desc_iface_super = {
 220    .bInterfaceNumber              = 0,
 221    .bNumEndpoints                 = 4,
 222    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
 223    .bInterfaceSubClass            = 0x06, /* SCSI */
 224    .bInterfaceProtocol            = 0x62, /* UAS  */
 225    .eps = (USBDescEndpoint[]) {
 226        {
 227            .bEndpointAddress      = USB_DIR_OUT | UAS_PIPE_ID_COMMAND,
 228            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 229            .wMaxPacketSize        = 1024,
 230            .bMaxBurst             = 15,
 231            .extra = (uint8_t[]) {
 232                0x04,  /*  u8  bLength */
 233                0x24,  /*  u8  bDescriptorType */
 234                UAS_PIPE_ID_COMMAND,
 235                0x00,  /*  u8  bReserved */
 236            },
 237        },{
 238            .bEndpointAddress      = USB_DIR_IN | UAS_PIPE_ID_STATUS,
 239            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 240            .wMaxPacketSize        = 1024,
 241            .bMaxBurst             = 15,
 242            .bmAttributes_super    = UAS_STREAM_BM_ATTR,
 243            .extra = (uint8_t[]) {
 244                0x04,  /*  u8  bLength */
 245                0x24,  /*  u8  bDescriptorType */
 246                UAS_PIPE_ID_STATUS,
 247                0x00,  /*  u8  bReserved */
 248            },
 249        },{
 250            .bEndpointAddress      = USB_DIR_IN | UAS_PIPE_ID_DATA_IN,
 251            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 252            .wMaxPacketSize        = 1024,
 253            .bMaxBurst             = 15,
 254            .bmAttributes_super    = UAS_STREAM_BM_ATTR,
 255            .extra = (uint8_t[]) {
 256                0x04,  /*  u8  bLength */
 257                0x24,  /*  u8  bDescriptorType */
 258                UAS_PIPE_ID_DATA_IN,
 259                0x00,  /*  u8  bReserved */
 260            },
 261        },{
 262            .bEndpointAddress      = USB_DIR_OUT | UAS_PIPE_ID_DATA_OUT,
 263            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 264            .wMaxPacketSize        = 1024,
 265            .bMaxBurst             = 15,
 266            .bmAttributes_super    = UAS_STREAM_BM_ATTR,
 267            .extra = (uint8_t[]) {
 268                0x04,  /*  u8  bLength */
 269                0x24,  /*  u8  bDescriptorType */
 270                UAS_PIPE_ID_DATA_OUT,
 271                0x00,  /*  u8  bReserved */
 272            },
 273        },
 274    }
 275};
 276
 277static const USBDescDevice desc_device_high = {
 278    .bcdUSB                        = 0x0200,
 279    .bMaxPacketSize0               = 64,
 280    .bNumConfigurations            = 1,
 281    .confs = (USBDescConfig[]) {
 282        {
 283            .bNumInterfaces        = 1,
 284            .bConfigurationValue   = 1,
 285            .iConfiguration        = STR_CONFIG_HIGH,
 286            .bmAttributes          = 0xc0,
 287            .nif = 1,
 288            .ifs = &desc_iface_high,
 289        },
 290    },
 291};
 292
 293static const USBDescDevice desc_device_super = {
 294    .bcdUSB                        = 0x0300,
 295    .bMaxPacketSize0               = 64,
 296    .bNumConfigurations            = 1,
 297    .confs = (USBDescConfig[]) {
 298        {
 299            .bNumInterfaces        = 1,
 300            .bConfigurationValue   = 1,
 301            .iConfiguration        = STR_CONFIG_SUPER,
 302            .bmAttributes          = 0xc0,
 303            .nif = 1,
 304            .ifs = &desc_iface_super,
 305        },
 306    },
 307};
 308
 309static const USBDesc desc = {
 310    .id = {
 311        .idVendor          = 0x46f4, /* CRC16() of "QEMU" */
 312        .idProduct         = 0x0003,
 313        .bcdDevice         = 0,
 314        .iManufacturer     = STR_MANUFACTURER,
 315        .iProduct          = STR_PRODUCT,
 316        .iSerialNumber     = STR_SERIALNUMBER,
 317    },
 318    .high  = &desc_device_high,
 319    .super = &desc_device_super,
 320    .str   = desc_strings,
 321};
 322
 323/* --------------------------------------------------------------------- */
 324
 325static bool uas_using_streams(UASDevice *uas)
 326{
 327    return uas->dev.speed == USB_SPEED_SUPER;
 328}
 329
 330/* --------------------------------------------------------------------- */
 331
 332static UASStatus *usb_uas_alloc_status(UASDevice *uas, uint8_t id, uint16_t tag)
 333{
 334    UASStatus *st = g_new0(UASStatus, 1);
 335
 336    st->status.hdr.id = id;
 337    st->status.hdr.tag = cpu_to_be16(tag);
 338    st->length = sizeof(uas_ui_header);
 339    if (uas_using_streams(uas)) {
 340        st->stream = tag;
 341    }
 342    return st;
 343}
 344
 345static void usb_uas_send_status_bh(void *opaque)
 346{
 347    UASDevice *uas = opaque;
 348    UASStatus *st;
 349    USBPacket *p;
 350
 351    while ((st = QTAILQ_FIRST(&uas->results)) != NULL) {
 352        if (uas_using_streams(uas)) {
 353            p = uas->status3[st->stream];
 354            uas->status3[st->stream] = NULL;
 355        } else {
 356            p = uas->status2;
 357            uas->status2 = NULL;
 358        }
 359        if (p == NULL) {
 360            break;
 361        }
 362
 363        usb_packet_copy(p, &st->status, st->length);
 364        QTAILQ_REMOVE(&uas->results, st, next);
 365        g_free(st);
 366
 367        p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
 368        usb_packet_complete(&uas->dev, p);
 369    }
 370}
 371
 372static void usb_uas_queue_status(UASDevice *uas, UASStatus *st, int length)
 373{
 374    USBPacket *p = uas_using_streams(uas) ?
 375        uas->status3[st->stream] : uas->status2;
 376
 377    st->length += length;
 378    QTAILQ_INSERT_TAIL(&uas->results, st, next);
 379    if (p) {
 380        /*
 381         * Just schedule bh make sure any in-flight data transaction
 382         * is finished before completing (sending) the status packet.
 383         */
 384        qemu_bh_schedule(uas->status_bh);
 385    } else {
 386        USBEndpoint *ep = usb_ep_get(&uas->dev, USB_TOKEN_IN,
 387                                     UAS_PIPE_ID_STATUS);
 388        usb_wakeup(ep, st->stream);
 389    }
 390}
 391
 392static void usb_uas_queue_response(UASDevice *uas, uint16_t tag,
 393                                   uint8_t code, uint16_t add_info)
 394{
 395    UASStatus *st = usb_uas_alloc_status(uas, UAS_UI_RESPONSE, tag);
 396
 397    trace_usb_uas_response(uas->dev.addr, tag, code);
 398    st->status.response.response_code = code;
 399    st->status.response.add_response_info = cpu_to_be16(add_info);
 400    usb_uas_queue_status(uas, st, sizeof(uas_ui_response));
 401}
 402
 403static void usb_uas_queue_sense(UASRequest *req, uint8_t status)
 404{
 405    UASStatus *st = usb_uas_alloc_status(req->uas, UAS_UI_SENSE, req->tag);
 406    int len, slen = 0;
 407
 408    trace_usb_uas_sense(req->uas->dev.addr, req->tag, status);
 409    st->status.sense.status = status;
 410    st->status.sense.status_qualifier = cpu_to_be16(0);
 411    if (status != GOOD) {
 412        slen = scsi_req_get_sense(req->req, st->status.sense.sense_data,
 413                                  sizeof(st->status.sense.sense_data));
 414        st->status.sense.sense_length = cpu_to_be16(slen);
 415    }
 416    len = sizeof(uas_ui_sense) - sizeof(st->status.sense.sense_data) + slen;
 417    usb_uas_queue_status(req->uas, st, len);
 418}
 419
 420static void usb_uas_queue_read_ready(UASRequest *req)
 421{
 422    UASStatus *st = usb_uas_alloc_status(req->uas, UAS_UI_READ_READY,
 423                                         req->tag);
 424
 425    trace_usb_uas_read_ready(req->uas->dev.addr, req->tag);
 426    usb_uas_queue_status(req->uas, st, 0);
 427}
 428
 429static void usb_uas_queue_write_ready(UASRequest *req)
 430{
 431    UASStatus *st = usb_uas_alloc_status(req->uas, UAS_UI_WRITE_READY,
 432                                         req->tag);
 433
 434    trace_usb_uas_write_ready(req->uas->dev.addr, req->tag);
 435    usb_uas_queue_status(req->uas, st, 0);
 436}
 437
 438/* --------------------------------------------------------------------- */
 439
 440static int usb_uas_get_lun(uint64_t lun64)
 441{
 442    return (lun64 >> 48) & 0xff;
 443}
 444
 445static SCSIDevice *usb_uas_get_dev(UASDevice *uas, uint64_t lun64)
 446{
 447    if ((lun64 >> 56) != 0x00) {
 448        return NULL;
 449    }
 450    return scsi_device_find(&uas->bus, 0, 0, usb_uas_get_lun(lun64));
 451}
 452
 453static void usb_uas_complete_data_packet(UASRequest *req)
 454{
 455    USBPacket *p;
 456
 457    if (!req->data_async) {
 458        return;
 459    }
 460    p = req->data;
 461    req->data = NULL;
 462    req->data_async = false;
 463    p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
 464    usb_packet_complete(&req->uas->dev, p);
 465}
 466
 467static void usb_uas_copy_data(UASRequest *req)
 468{
 469    uint32_t length;
 470
 471    length = MIN(req->buf_size - req->buf_off,
 472                 req->data->iov.size - req->data->actual_length);
 473    trace_usb_uas_xfer_data(req->uas->dev.addr, req->tag, length,
 474                            req->data->actual_length, req->data->iov.size,
 475                            req->buf_off, req->buf_size);
 476    usb_packet_copy(req->data, scsi_req_get_buf(req->req) + req->buf_off,
 477                    length);
 478    req->buf_off += length;
 479    req->data_off += length;
 480
 481    if (req->data->actual_length == req->data->iov.size) {
 482        usb_uas_complete_data_packet(req);
 483    }
 484    if (req->buf_size && req->buf_off == req->buf_size) {
 485        req->buf_off = 0;
 486        req->buf_size = 0;
 487        scsi_req_continue(req->req);
 488    }
 489}
 490
 491static void usb_uas_start_next_transfer(UASDevice *uas)
 492{
 493    UASRequest *req;
 494
 495    if (uas_using_streams(uas)) {
 496        return;
 497    }
 498
 499    QTAILQ_FOREACH(req, &uas->requests, next) {
 500        if (req->active || req->complete) {
 501            continue;
 502        }
 503        if (req->req->cmd.mode == SCSI_XFER_FROM_DEV && uas->datain2 == NULL) {
 504            uas->datain2 = req;
 505            usb_uas_queue_read_ready(req);
 506            req->active = true;
 507            return;
 508        }
 509        if (req->req->cmd.mode == SCSI_XFER_TO_DEV && uas->dataout2 == NULL) {
 510            uas->dataout2 = req;
 511            usb_uas_queue_write_ready(req);
 512            req->active = true;
 513            return;
 514        }
 515    }
 516}
 517
 518static UASRequest *usb_uas_alloc_request(UASDevice *uas, uas_ui *ui)
 519{
 520    UASRequest *req;
 521
 522    req = g_new0(UASRequest, 1);
 523    req->uas = uas;
 524    req->tag = be16_to_cpu(ui->hdr.tag);
 525    req->lun = be64_to_cpu(ui->command.lun);
 526    req->dev = usb_uas_get_dev(req->uas, req->lun);
 527    return req;
 528}
 529
 530static void usb_uas_scsi_free_request(SCSIBus *bus, void *priv)
 531{
 532    UASRequest *req = priv;
 533    UASDevice *uas = req->uas;
 534
 535    if (req == uas->datain2) {
 536        uas->datain2 = NULL;
 537    }
 538    if (req == uas->dataout2) {
 539        uas->dataout2 = NULL;
 540    }
 541    QTAILQ_REMOVE(&uas->requests, req, next);
 542    g_free(req);
 543    usb_uas_start_next_transfer(uas);
 544}
 545
 546static UASRequest *usb_uas_find_request(UASDevice *uas, uint16_t tag)
 547{
 548    UASRequest *req;
 549
 550    QTAILQ_FOREACH(req, &uas->requests, next) {
 551        if (req->tag == tag) {
 552            return req;
 553        }
 554    }
 555    return NULL;
 556}
 557
 558static void usb_uas_scsi_transfer_data(SCSIRequest *r, uint32_t len)
 559{
 560    UASRequest *req = r->hba_private;
 561
 562    trace_usb_uas_scsi_data(req->uas->dev.addr, req->tag, len);
 563    req->buf_off = 0;
 564    req->buf_size = len;
 565    if (req->data) {
 566        usb_uas_copy_data(req);
 567    } else {
 568        usb_uas_start_next_transfer(req->uas);
 569    }
 570}
 571
 572static void usb_uas_scsi_command_complete(SCSIRequest *r,
 573                                          uint32_t status, size_t resid)
 574{
 575    UASRequest *req = r->hba_private;
 576
 577    trace_usb_uas_scsi_complete(req->uas->dev.addr, req->tag, status, resid);
 578    req->complete = true;
 579    if (req->data) {
 580        usb_uas_complete_data_packet(req);
 581    }
 582    usb_uas_queue_sense(req, status);
 583    scsi_req_unref(req->req);
 584}
 585
 586static void usb_uas_scsi_request_cancelled(SCSIRequest *r)
 587{
 588    UASRequest *req = r->hba_private;
 589
 590    /* FIXME: queue notification to status pipe? */
 591    scsi_req_unref(req->req);
 592}
 593
 594static const struct SCSIBusInfo usb_uas_scsi_info = {
 595    .tcq = true,
 596    .max_target = 0,
 597    .max_lun = 255,
 598
 599    .transfer_data = usb_uas_scsi_transfer_data,
 600    .complete = usb_uas_scsi_command_complete,
 601    .cancel = usb_uas_scsi_request_cancelled,
 602    .free_request = usb_uas_scsi_free_request,
 603};
 604
 605/* --------------------------------------------------------------------- */
 606
 607static void usb_uas_handle_reset(USBDevice *dev)
 608{
 609    UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
 610    UASRequest *req, *nreq;
 611    UASStatus *st, *nst;
 612
 613    trace_usb_uas_reset(dev->addr);
 614    QTAILQ_FOREACH_SAFE(req, &uas->requests, next, nreq) {
 615        scsi_req_cancel(req->req);
 616    }
 617    QTAILQ_FOREACH_SAFE(st, &uas->results, next, nst) {
 618        QTAILQ_REMOVE(&uas->results, st, next);
 619        g_free(st);
 620    }
 621}
 622
 623static void usb_uas_handle_control(USBDevice *dev, USBPacket *p,
 624               int request, int value, int index, int length, uint8_t *data)
 625{
 626    int ret;
 627
 628    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
 629    if (ret >= 0) {
 630        return;
 631    }
 632    fprintf(stderr, "%s: unhandled control request\n", __func__);
 633    p->status = USB_RET_STALL;
 634}
 635
 636static void usb_uas_cancel_io(USBDevice *dev, USBPacket *p)
 637{
 638    UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
 639    UASRequest *req, *nreq;
 640    int i;
 641
 642    if (uas->status2 == p) {
 643        uas->status2 = NULL;
 644        qemu_bh_cancel(uas->status_bh);
 645        return;
 646    }
 647    if (uas_using_streams(uas)) {
 648        for (i = 0; i < UAS_MAX_STREAMS; i++) {
 649            if (uas->status3[i] == p) {
 650                uas->status3[i] = NULL;
 651                return;
 652            }
 653            if (uas->data3[i] == p) {
 654                uas->data3[i] = NULL;
 655                return;
 656            }
 657        }
 658    }
 659    QTAILQ_FOREACH_SAFE(req, &uas->requests, next, nreq) {
 660        if (req->data == p) {
 661            req->data = NULL;
 662            return;
 663        }
 664    }
 665    assert(!"canceled usb packet not found");
 666}
 667
 668static void usb_uas_command(UASDevice *uas, uas_ui *ui)
 669{
 670    UASRequest *req;
 671    uint32_t len;
 672
 673    req = usb_uas_find_request(uas, be16_to_cpu(ui->hdr.tag));
 674    if (req) {
 675        goto overlapped_tag;
 676    }
 677    req = usb_uas_alloc_request(uas, ui);
 678    if (req->dev == NULL) {
 679        goto bad_target;
 680    }
 681
 682    trace_usb_uas_command(uas->dev.addr, req->tag,
 683                          usb_uas_get_lun(req->lun),
 684                          req->lun >> 32, req->lun & 0xffffffff);
 685    QTAILQ_INSERT_TAIL(&uas->requests, req, next);
 686    if (uas_using_streams(uas) && uas->data3[req->tag] != NULL) {
 687        req->data = uas->data3[req->tag];
 688        req->data_async = true;
 689        uas->data3[req->tag] = NULL;
 690    }
 691
 692    req->req = scsi_req_new(req->dev, req->tag,
 693                            usb_uas_get_lun(req->lun),
 694                            ui->command.cdb, req);
 695#if 1
 696    scsi_req_print(req->req);
 697#endif
 698    len = scsi_req_enqueue(req->req);
 699    if (len) {
 700        req->data_size = len;
 701        scsi_req_continue(req->req);
 702    }
 703    return;
 704
 705overlapped_tag:
 706    usb_uas_queue_response(uas, req->tag, UAS_RC_OVERLAPPED_TAG, 0);
 707    return;
 708
 709bad_target:
 710    /*
 711     * FIXME: Seems to upset linux, is this wrong?
 712     * NOTE: Happens only with no scsi devices at the bus, not sure
 713     *       this is a valid UAS setup in the first place.
 714     */
 715    usb_uas_queue_response(uas, req->tag, UAS_RC_INVALID_INFO_UNIT, 0);
 716    g_free(req);
 717}
 718
 719static void usb_uas_task(UASDevice *uas, uas_ui *ui)
 720{
 721    uint16_t tag = be16_to_cpu(ui->hdr.tag);
 722    uint64_t lun64 = be64_to_cpu(ui->task.lun);
 723    SCSIDevice *dev = usb_uas_get_dev(uas, lun64);
 724    int lun = usb_uas_get_lun(lun64);
 725    UASRequest *req;
 726    uint16_t task_tag;
 727
 728    req = usb_uas_find_request(uas, be16_to_cpu(ui->hdr.tag));
 729    if (req) {
 730        goto overlapped_tag;
 731    }
 732
 733    switch (ui->task.function) {
 734    case UAS_TMF_ABORT_TASK:
 735        task_tag = be16_to_cpu(ui->task.task_tag);
 736        trace_usb_uas_tmf_abort_task(uas->dev.addr, tag, task_tag);
 737        if (dev == NULL) {
 738            goto bad_target;
 739        }
 740        if (dev->lun != lun) {
 741            goto incorrect_lun;
 742        }
 743        req = usb_uas_find_request(uas, task_tag);
 744        if (req && req->dev == dev) {
 745            scsi_req_cancel(req->req);
 746        }
 747        usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE, 0);
 748        break;
 749
 750    case UAS_TMF_LOGICAL_UNIT_RESET:
 751        trace_usb_uas_tmf_logical_unit_reset(uas->dev.addr, tag, lun);
 752        if (dev == NULL) {
 753            goto bad_target;
 754        }
 755        if (dev->lun != lun) {
 756            goto incorrect_lun;
 757        }
 758        qdev_reset_all(&dev->qdev);
 759        usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE, 0);
 760        break;
 761
 762    default:
 763        trace_usb_uas_tmf_unsupported(uas->dev.addr, tag, ui->task.function);
 764        usb_uas_queue_response(uas, tag, UAS_RC_TMF_NOT_SUPPORTED, 0);
 765        break;
 766    }
 767    return;
 768
 769overlapped_tag:
 770    usb_uas_queue_response(uas, req->tag, UAS_RC_OVERLAPPED_TAG, 0);
 771    return;
 772
 773bad_target:
 774    /* FIXME: correct?  [see long comment in usb_uas_command()] */
 775    usb_uas_queue_response(uas, tag, UAS_RC_INVALID_INFO_UNIT, 0);
 776    return;
 777
 778incorrect_lun:
 779    usb_uas_queue_response(uas, tag, UAS_RC_INCORRECT_LUN, 0);
 780}
 781
 782static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
 783{
 784    UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
 785    uas_ui ui;
 786    UASStatus *st;
 787    UASRequest *req;
 788    int length;
 789
 790    switch (p->ep->nr) {
 791    case UAS_PIPE_ID_COMMAND:
 792        length = MIN(sizeof(ui), p->iov.size);
 793        usb_packet_copy(p, &ui, length);
 794        switch (ui.hdr.id) {
 795        case UAS_UI_COMMAND:
 796            usb_uas_command(uas, &ui);
 797            break;
 798        case UAS_UI_TASK_MGMT:
 799            usb_uas_task(uas, &ui);
 800            break;
 801        default:
 802            fprintf(stderr, "%s: unknown command ui: id 0x%x\n",
 803                    __func__, ui.hdr.id);
 804            p->status = USB_RET_STALL;
 805            break;
 806        }
 807        break;
 808    case UAS_PIPE_ID_STATUS:
 809        if (p->stream) {
 810            QTAILQ_FOREACH(st, &uas->results, next) {
 811                if (st->stream == p->stream) {
 812                    break;
 813                }
 814            }
 815            if (st == NULL) {
 816                assert(uas->status3[p->stream] == NULL);
 817                uas->status3[p->stream] = p;
 818                p->status = USB_RET_ASYNC;
 819                break;
 820            }
 821        } else {
 822            st = QTAILQ_FIRST(&uas->results);
 823            if (st == NULL) {
 824                assert(uas->status2 == NULL);
 825                uas->status2 = p;
 826                p->status = USB_RET_ASYNC;
 827                break;
 828            }
 829        }
 830        usb_packet_copy(p, &st->status, st->length);
 831        QTAILQ_REMOVE(&uas->results, st, next);
 832        g_free(st);
 833        break;
 834    case UAS_PIPE_ID_DATA_IN:
 835    case UAS_PIPE_ID_DATA_OUT:
 836        if (p->stream) {
 837            req = usb_uas_find_request(uas, p->stream);
 838        } else {
 839            req = (p->ep->nr == UAS_PIPE_ID_DATA_IN)
 840                ? uas->datain2 : uas->dataout2;
 841        }
 842        if (req == NULL) {
 843            if (p->stream) {
 844                assert(uas->data3[p->stream] == NULL);
 845                uas->data3[p->stream] = p;
 846                p->status = USB_RET_ASYNC;
 847                break;
 848            } else {
 849                fprintf(stderr, "%s: no inflight request\n", __func__);
 850                p->status = USB_RET_STALL;
 851                break;
 852            }
 853        }
 854        scsi_req_ref(req->req);
 855        req->data = p;
 856        usb_uas_copy_data(req);
 857        if (p->actual_length == p->iov.size || req->complete) {
 858            req->data = NULL;
 859        } else {
 860            req->data_async = true;
 861            p->status = USB_RET_ASYNC;
 862        }
 863        scsi_req_unref(req->req);
 864        usb_uas_start_next_transfer(uas);
 865        break;
 866    default:
 867        fprintf(stderr, "%s: invalid endpoint %d\n", __func__, p->ep->nr);
 868        p->status = USB_RET_STALL;
 869        break;
 870    }
 871}
 872
 873static void usb_uas_handle_destroy(USBDevice *dev)
 874{
 875    UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
 876
 877    qemu_bh_delete(uas->status_bh);
 878}
 879
 880static int usb_uas_init(USBDevice *dev)
 881{
 882    UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
 883
 884    usb_desc_create_serial(dev);
 885    usb_desc_init(dev);
 886
 887    QTAILQ_INIT(&uas->results);
 888    QTAILQ_INIT(&uas->requests);
 889    uas->status_bh = qemu_bh_new(usb_uas_send_status_bh, uas);
 890
 891    scsi_bus_new(&uas->bus, &uas->dev.qdev, &usb_uas_scsi_info, NULL);
 892
 893    return 0;
 894}
 895
 896static const VMStateDescription vmstate_usb_uas = {
 897    .name = "usb-uas",
 898    .unmigratable = 1,
 899    .fields = (VMStateField[]) {
 900        VMSTATE_USB_DEVICE(dev, UASDevice),
 901        VMSTATE_END_OF_LIST()
 902    }
 903};
 904
 905static void usb_uas_class_initfn(ObjectClass *klass, void *data)
 906{
 907    DeviceClass *dc = DEVICE_CLASS(klass);
 908    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 909
 910    uc->init           = usb_uas_init;
 911    uc->product_desc   = desc_strings[STR_PRODUCT];
 912    uc->usb_desc       = &desc;
 913    uc->cancel_packet  = usb_uas_cancel_io;
 914    uc->handle_attach  = usb_desc_attach;
 915    uc->handle_reset   = usb_uas_handle_reset;
 916    uc->handle_control = usb_uas_handle_control;
 917    uc->handle_data    = usb_uas_handle_data;
 918    uc->handle_destroy = usb_uas_handle_destroy;
 919    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 920    dc->fw_name = "storage";
 921    dc->vmsd = &vmstate_usb_uas;
 922}
 923
 924static const TypeInfo uas_info = {
 925    .name          = "usb-uas",
 926    .parent        = TYPE_USB_DEVICE,
 927    .instance_size = sizeof(UASDevice),
 928    .class_init    = usb_uas_class_initfn,
 929};
 930
 931static void usb_uas_register_types(void)
 932{
 933    type_register_static(&uas_info);
 934}
 935
 936type_init(usb_uas_register_types)
 937