Lines Matching +full:- +full:- +full:-
9 * See the COPYING file in the top-level directory.
14 #include "qemu/config-file.h"
16 #include "qemu/error-report.h"
17 #include "qemu/main-loop.h"
24 #include "hw/qdev-properties.h"
29 /* --------------------------------------------------------------------- */
107 /* --------------------------------------------------------------------- */
136 #define TYPE_USB_UAS "usb-uas"
163 /* --------------------------------------------------------------------- */
336 /* --------------------------------------------------------------------- */
340 return uas->dev.speed == USB_SPEED_SUPER; in uas_using_streams()
343 /* --------------------------------------------------------------------- */
349 st->status.hdr.id = id; in usb_uas_alloc_status()
350 st->status.hdr.tag = cpu_to_be16(tag); in usb_uas_alloc_status()
351 st->length = sizeof(uas_iu_header); in usb_uas_alloc_status()
353 st->stream = tag; in usb_uas_alloc_status()
364 while ((st = QTAILQ_FIRST(&uas->results)) != NULL) { in usb_uas_send_status_bh()
366 p = uas->status3[st->stream]; in usb_uas_send_status_bh()
367 uas->status3[st->stream] = NULL; in usb_uas_send_status_bh()
369 p = uas->status2; in usb_uas_send_status_bh()
370 uas->status2 = NULL; in usb_uas_send_status_bh()
376 usb_packet_copy(p, &st->status, st->length); in usb_uas_send_status_bh()
377 QTAILQ_REMOVE(&uas->results, st, next); in usb_uas_send_status_bh()
380 p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */ in usb_uas_send_status_bh()
381 usb_packet_complete(&uas->dev, p); in usb_uas_send_status_bh()
388 uas->status3[st->stream] : uas->status2; in usb_uas_queue_status()
390 st->length += length; in usb_uas_queue_status()
391 QTAILQ_INSERT_TAIL(&uas->results, st, next); in usb_uas_queue_status()
394 * Just schedule bh make sure any in-flight data transaction in usb_uas_queue_status()
397 qemu_bh_schedule(uas->status_bh); in usb_uas_queue_status()
399 USBEndpoint *ep = usb_ep_get(&uas->dev, USB_TOKEN_IN, in usb_uas_queue_status()
401 usb_wakeup(ep, st->stream); in usb_uas_queue_status()
409 trace_usb_uas_response(uas->dev.addr, tag, code); in usb_uas_queue_response()
410 st->status.response.response_code = code; in usb_uas_queue_response()
416 UASStatus *st = usb_uas_alloc_status(req->uas, UAS_UI_SENSE, req->tag); in usb_uas_queue_sense()
419 trace_usb_uas_sense(req->uas->dev.addr, req->tag, status); in usb_uas_queue_sense()
420 st->status.sense.status = status; in usb_uas_queue_sense()
421 st->status.sense.status_qualifier = cpu_to_be16(0); in usb_uas_queue_sense()
423 slen = scsi_req_get_sense(req->req, st->status.sense.sense_data, in usb_uas_queue_sense()
424 sizeof(st->status.sense.sense_data)); in usb_uas_queue_sense()
425 st->status.sense.sense_length = cpu_to_be16(slen); in usb_uas_queue_sense()
427 len = sizeof(uas_iu_sense) - sizeof(st->status.sense.sense_data) + slen; in usb_uas_queue_sense()
428 usb_uas_queue_status(req->uas, st, len); in usb_uas_queue_sense()
437 st->status.sense.status = CHECK_CONDITION; in usb_uas_queue_fake_sense()
438 st->status.sense.status_qualifier = cpu_to_be16(0); in usb_uas_queue_fake_sense()
439 st->status.sense.sense_data[0] = 0x70; in usb_uas_queue_fake_sense()
440 st->status.sense.sense_data[2] = sense.key; in usb_uas_queue_fake_sense()
441 st->status.sense.sense_data[7] = 10; in usb_uas_queue_fake_sense()
442 st->status.sense.sense_data[12] = sense.asc; in usb_uas_queue_fake_sense()
443 st->status.sense.sense_data[13] = sense.ascq; in usb_uas_queue_fake_sense()
445 len = sizeof(uas_iu_sense) - sizeof(st->status.sense.sense_data) + slen; in usb_uas_queue_fake_sense()
451 UASStatus *st = usb_uas_alloc_status(req->uas, UAS_UI_READ_READY, in usb_uas_queue_read_ready()
452 req->tag); in usb_uas_queue_read_ready()
454 trace_usb_uas_read_ready(req->uas->dev.addr, req->tag); in usb_uas_queue_read_ready()
455 usb_uas_queue_status(req->uas, st, 0); in usb_uas_queue_read_ready()
460 UASStatus *st = usb_uas_alloc_status(req->uas, UAS_UI_WRITE_READY, in usb_uas_queue_write_ready()
461 req->tag); in usb_uas_queue_write_ready()
463 trace_usb_uas_write_ready(req->uas->dev.addr, req->tag); in usb_uas_queue_write_ready()
464 usb_uas_queue_status(req->uas, st, 0); in usb_uas_queue_write_ready()
467 /* --------------------------------------------------------------------- */
479 return scsi_device_find(&uas->bus, 0, 0, usb_uas_get_lun(lun64)); in usb_uas_get_dev()
486 if (!req->data_async) { in usb_uas_complete_data_packet()
489 p = req->data; in usb_uas_complete_data_packet()
490 req->data = NULL; in usb_uas_complete_data_packet()
491 req->data_async = false; in usb_uas_complete_data_packet()
492 p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */ in usb_uas_complete_data_packet()
493 usb_packet_complete(&req->uas->dev, p); in usb_uas_complete_data_packet()
500 length = MIN(req->buf_size - req->buf_off, in usb_uas_copy_data()
501 req->data->iov.size - req->data->actual_length); in usb_uas_copy_data()
502 trace_usb_uas_xfer_data(req->uas->dev.addr, req->tag, length, in usb_uas_copy_data()
503 req->data->actual_length, req->data->iov.size, in usb_uas_copy_data()
504 req->buf_off, req->buf_size); in usb_uas_copy_data()
505 usb_packet_copy(req->data, scsi_req_get_buf(req->req) + req->buf_off, in usb_uas_copy_data()
507 req->buf_off += length; in usb_uas_copy_data()
508 req->data_off += length; in usb_uas_copy_data()
510 if (req->data->actual_length == req->data->iov.size) { in usb_uas_copy_data()
513 if (req->buf_size && req->buf_off == req->buf_size) { in usb_uas_copy_data()
514 req->buf_off = 0; in usb_uas_copy_data()
515 req->buf_size = 0; in usb_uas_copy_data()
516 scsi_req_continue(req->req); in usb_uas_copy_data()
528 QTAILQ_FOREACH(req, &uas->requests, next) { in usb_uas_start_next_transfer()
529 if (req->active || req->complete) { in usb_uas_start_next_transfer()
532 if (req->req->cmd.mode == SCSI_XFER_FROM_DEV && uas->datain2 == NULL) { in usb_uas_start_next_transfer()
533 uas->datain2 = req; in usb_uas_start_next_transfer()
535 req->active = true; in usb_uas_start_next_transfer()
538 if (req->req->cmd.mode == SCSI_XFER_TO_DEV && uas->dataout2 == NULL) { in usb_uas_start_next_transfer()
539 uas->dataout2 = req; in usb_uas_start_next_transfer()
541 req->active = true; in usb_uas_start_next_transfer()
552 req->uas = uas; in usb_uas_alloc_request()
553 req->tag = be16_to_cpu(iu->hdr.tag); in usb_uas_alloc_request()
554 req->lun = be64_to_cpu(iu->command.lun); in usb_uas_alloc_request()
555 req->dev = usb_uas_get_dev(req->uas, req->lun); in usb_uas_alloc_request()
562 UASDevice *uas = req->uas; in usb_uas_scsi_free_request()
564 if (req == uas->datain2) { in usb_uas_scsi_free_request()
565 uas->datain2 = NULL; in usb_uas_scsi_free_request()
567 if (req == uas->dataout2) { in usb_uas_scsi_free_request()
568 uas->dataout2 = NULL; in usb_uas_scsi_free_request()
570 QTAILQ_REMOVE(&uas->requests, req, next); in usb_uas_scsi_free_request()
579 QTAILQ_FOREACH(req, &uas->requests, next) { in usb_uas_find_request()
580 if (req->tag == tag) { in usb_uas_find_request()
589 UASRequest *req = r->hba_private; in usb_uas_scsi_transfer_data()
591 trace_usb_uas_scsi_data(req->uas->dev.addr, req->tag, len); in usb_uas_scsi_transfer_data()
592 req->buf_off = 0; in usb_uas_scsi_transfer_data()
593 req->buf_size = len; in usb_uas_scsi_transfer_data()
594 if (req->data) { in usb_uas_scsi_transfer_data()
597 usb_uas_start_next_transfer(req->uas); in usb_uas_scsi_transfer_data()
603 UASRequest *req = r->hba_private; in usb_uas_scsi_command_complete()
605 trace_usb_uas_scsi_complete(req->uas->dev.addr, req->tag, r->status, resid); in usb_uas_scsi_command_complete()
606 req->complete = true; in usb_uas_scsi_command_complete()
607 if (req->data) { in usb_uas_scsi_command_complete()
610 usb_uas_queue_sense(req, r->status); in usb_uas_scsi_command_complete()
611 scsi_req_unref(req->req); in usb_uas_scsi_command_complete()
616 UASRequest *req = r->hba_private; in usb_uas_scsi_request_cancelled()
619 scsi_req_unref(req->req); in usb_uas_scsi_request_cancelled()
633 /* --------------------------------------------------------------------- */
641 trace_usb_uas_reset(dev->addr); in usb_uas_handle_reset()
642 QTAILQ_FOREACH_SAFE(req, &uas->requests, next, nreq) { in usb_uas_handle_reset()
643 scsi_req_cancel(req->req); in usb_uas_handle_reset()
645 QTAILQ_FOREACH_SAFE(st, &uas->results, next, nst) { in usb_uas_handle_reset()
646 QTAILQ_REMOVE(&uas->results, st, next); in usb_uas_handle_reset()
662 p->status = USB_RET_STALL; in usb_uas_handle_control()
671 if (uas->status2 == p) { in usb_uas_cancel_io()
672 uas->status2 = NULL; in usb_uas_cancel_io()
673 qemu_bh_cancel(uas->status_bh); in usb_uas_cancel_io()
678 if (uas->status3[i] == p) { in usb_uas_cancel_io()
679 uas->status3[i] = NULL; in usb_uas_cancel_io()
682 if (uas->data3[i] == p) { in usb_uas_cancel_io()
683 uas->data3[i] = NULL; in usb_uas_cancel_io()
688 QTAILQ_FOREACH_SAFE(req, &uas->requests, next, nreq) { in usb_uas_cancel_io()
689 if (req->data == p) { in usb_uas_cancel_io()
690 req->data = NULL; in usb_uas_cancel_io()
701 uint16_t tag = be16_to_cpu(iu->hdr.tag); in usb_uas_command()
702 size_t cdb_len = sizeof(iu->command.cdb) + iu->command.add_cdb_length; in usb_uas_command()
704 if (iu->command.add_cdb_length > 0) { in usb_uas_command()
717 if (req->dev == NULL) { in usb_uas_command()
721 trace_usb_uas_command(uas->dev.addr, req->tag, in usb_uas_command()
722 usb_uas_get_lun(req->lun), in usb_uas_command()
723 req->lun >> 32, req->lun & 0xffffffff); in usb_uas_command()
724 QTAILQ_INSERT_TAIL(&uas->requests, req, next); in usb_uas_command()
725 if (uas_using_streams(uas) && uas->data3[req->tag] != NULL) { in usb_uas_command()
726 req->data = uas->data3[req->tag]; in usb_uas_command()
727 req->data_async = true; in usb_uas_command()
728 uas->data3[req->tag] = NULL; in usb_uas_command()
731 req->req = scsi_req_new(req->dev, req->tag, in usb_uas_command()
732 usb_uas_get_lun(req->lun), in usb_uas_command()
733 iu->command.cdb, cdb_len, req); in usb_uas_command()
734 if (uas->requestlog) { in usb_uas_command()
735 scsi_req_print(req->req); in usb_uas_command()
737 len = scsi_req_enqueue(req->req); in usb_uas_command()
739 req->data_size = len; in usb_uas_command()
740 scsi_req_continue(req->req); in usb_uas_command()
763 uint16_t tag = be16_to_cpu(iu->hdr.tag); in usb_uas_task()
764 uint64_t lun64 = be64_to_cpu(iu->task.lun); in usb_uas_task()
773 req = usb_uas_find_request(uas, be16_to_cpu(iu->hdr.tag)); in usb_uas_task()
781 switch (iu->task.function) { in usb_uas_task()
783 task_tag = be16_to_cpu(iu->task.task_tag); in usb_uas_task()
784 trace_usb_uas_tmf_abort_task(uas->dev.addr, tag, task_tag); in usb_uas_task()
786 if (req && req->dev == dev) { in usb_uas_task()
787 scsi_req_cancel(req->req); in usb_uas_task()
793 trace_usb_uas_tmf_logical_unit_reset(uas->dev.addr, tag, lun); in usb_uas_task()
794 device_cold_reset(&dev->qdev); in usb_uas_task()
799 trace_usb_uas_tmf_unsupported(uas->dev.addr, tag, iu->task.function); in usb_uas_task()
810 usb_uas_queue_response(uas, req->tag, UAS_RC_OVERLAPPED_TAG); in usb_uas_task()
825 switch (p->ep->nr) { in usb_uas_handle_data()
827 length = MIN(sizeof(iu), p->iov.size); in usb_uas_handle_data()
839 p->status = USB_RET_STALL; in usb_uas_handle_data()
844 if (p->stream > UAS_MAX_STREAMS) { in usb_uas_handle_data()
847 if (p->stream) { in usb_uas_handle_data()
848 QTAILQ_FOREACH(st, &uas->results, next) { in usb_uas_handle_data()
849 if (st->stream == p->stream) { in usb_uas_handle_data()
854 assert(uas->status3[p->stream] == NULL); in usb_uas_handle_data()
855 uas->status3[p->stream] = p; in usb_uas_handle_data()
856 p->status = USB_RET_ASYNC; in usb_uas_handle_data()
860 st = QTAILQ_FIRST(&uas->results); in usb_uas_handle_data()
862 assert(uas->status2 == NULL); in usb_uas_handle_data()
863 uas->status2 = p; in usb_uas_handle_data()
864 p->status = USB_RET_ASYNC; in usb_uas_handle_data()
868 usb_packet_copy(p, &st->status, st->length); in usb_uas_handle_data()
869 QTAILQ_REMOVE(&uas->results, st, next); in usb_uas_handle_data()
874 if (p->stream > UAS_MAX_STREAMS) { in usb_uas_handle_data()
877 if (p->stream) { in usb_uas_handle_data()
878 req = usb_uas_find_request(uas, p->stream); in usb_uas_handle_data()
880 req = (p->ep->nr == UAS_PIPE_ID_DATA_IN) in usb_uas_handle_data()
881 ? uas->datain2 : uas->dataout2; in usb_uas_handle_data()
884 if (p->stream) { in usb_uas_handle_data()
885 assert(uas->data3[p->stream] == NULL); in usb_uas_handle_data()
886 uas->data3[p->stream] = p; in usb_uas_handle_data()
887 p->status = USB_RET_ASYNC; in usb_uas_handle_data()
891 p->status = USB_RET_STALL; in usb_uas_handle_data()
895 scsi_req_ref(req->req); in usb_uas_handle_data()
896 req->data = p; in usb_uas_handle_data()
898 if (p->actual_length == p->iov.size || req->complete) { in usb_uas_handle_data()
899 req->data = NULL; in usb_uas_handle_data()
901 req->data_async = true; in usb_uas_handle_data()
902 p->status = USB_RET_ASYNC; in usb_uas_handle_data()
904 scsi_req_unref(req->req); in usb_uas_handle_data()
908 error_report("%s: invalid endpoint %d", __func__, p->ep->nr); in usb_uas_handle_data()
909 p->status = USB_RET_STALL; in usb_uas_handle_data()
915 error_report("%s: invalid stream %d", __func__, p->stream); in usb_uas_handle_data()
916 p->status = USB_RET_STALL; in usb_uas_handle_data()
923 qemu_bh_delete(uas->status_bh); in usb_uas_unrealize()
933 if (d->hotplugged) { in usb_uas_realize()
934 uas->dev.auto_attach = 0; in usb_uas_realize()
937 QTAILQ_INIT(&uas->results); in usb_uas_realize()
938 QTAILQ_INIT(&uas->requests); in usb_uas_realize()
939 uas->status_bh = qemu_bh_new_guarded(usb_uas_send_status_bh, uas, in usb_uas_realize()
940 &d->mem_reentrancy_guard); in usb_uas_realize()
942 dev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE); in usb_uas_realize()
943 scsi_bus_init(&uas->bus, sizeof(uas->bus), DEVICE(dev), &usb_uas_scsi_info); in usb_uas_realize()
947 .name = "usb-uas",
956 DEFINE_PROP_UINT32("log-scsi-req", UASDevice, requestlog, 0),
964 uc->realize = usb_uas_realize; in usb_uas_class_initfn()
965 uc->product_desc = desc_strings[STR_PRODUCT]; in usb_uas_class_initfn()
966 uc->usb_desc = &desc; in usb_uas_class_initfn()
967 uc->cancel_packet = usb_uas_cancel_io; in usb_uas_class_initfn()
968 uc->handle_attach = usb_desc_attach; in usb_uas_class_initfn()
969 uc->handle_reset = usb_uas_handle_reset; in usb_uas_class_initfn()
970 uc->handle_control = usb_uas_handle_control; in usb_uas_class_initfn()
971 uc->handle_data = usb_uas_handle_data; in usb_uas_class_initfn()
972 uc->unrealize = usb_uas_unrealize; in usb_uas_class_initfn()
973 uc->attached_settable = true; in usb_uas_class_initfn()
974 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); in usb_uas_class_initfn()
975 dc->fw_name = "storage"; in usb_uas_class_initfn()
976 dc->vmsd = &vmstate_usb_uas; in usb_uas_class_initfn()