Improvements for usb3 bulk stream (usb core, xhci).
Bugfixes for uas emulation.
 Add remote wakeup support for ehci.
 Add suspend support for xhci.
 Misc minor tweaks and fixes.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJSmEXxAAoJEEy22O7T6HE47t0QALonQORRj0IUAH0cOdfAhlQ3
 tGMQksBCYevBatKt4iZQgkw6H0jwse6QfsgsG2dfznEO+ZWsrt9cxe1UrqxbK2PN
 2PY/I9Ke1iP6tjcf9ftjqt+mZcAg/FHrbua5hb8zXRQnqu2jr0y3Cp7k2Jax4j4d
 Zl2FJ+sd4lGNR3Qpb85Muxtii8XERmMqvAit72VN4VAW4iE+SQAFSOgzBC512b55
 wLVc6DrbnM8I4AVJQ8RH2pMQau0/aBHFbU8By2RKbymkJmIG2nFqLH6eSJ19QgzY
 CmX8yGDJM5LGAGRZCeDSeuilxFU/WCSoTtkL8cPcYUv4cSTm+forzxhVz+CVOeVu
 JJsWNkaIxu4mxfRyADjUKkWoKX7ACro3ErfAWHdv8hwuhZ4uD6cf2++nXVDK9dq4
 yLL2nR4YG0NTOdQNKrsUbltf9gC5cWqNRgVMJ5VfqIBGtjXdTbpGpcUEFuDDegjk
 GhfN8lcpqgnFj0U4fAGLxHYXHvJRpNeWzEEANPuEYnWr2tSrgBWKkYLaooTDHt5r
 FUE6lmKL+BzQYnXfWWqh1fZoiBzzrMaT3OkHc2vx/SrGLuO/rVWTzXsFQI+NGPHp
 XxuyocFoKZA2yGr9h6eBBp9mtd5y0oOVxBR0WbkgvmbyxkX7Zq9r2PSoDOm26oE3
 5kmApAnSij83aT06Qe8P
 =2yvC
 -----END PGP SIGNATURE-----
Merge remote-tracking branch 'kraxel/tags/pull-usb-1' into staging
Improvements for usb3 bulk stream (usb core, xhci).
Bugfixes for uas emulation.
Add remote wakeup support for ehci.
Add suspend support for xhci.
Misc minor tweaks and fixes.
# gpg: Signature made Thu 28 Nov 2013 11:44:49 PM PST using RSA key ID D3E87138
# gpg: Can't check signature: public key not found
# By Hans de Goede (11) and others
# Via Gerd Hoffmann
* kraxel/tags/pull-usb-1:
  usb: move usb_{hi,lo} helpers to header file.
  usb: add vendor request defines
  trace-events: Clean up after removal of old usb-host code
  Revert "usb-tablet: Don't claim wakeup capability for USB-2 version"
  ehci: implement port wakeup
  xhci: Call usb_device_alloc/free_streams
  usb: Add usb_device_alloc/free_streams
  usb: Add max_streams attribute to endpoint info
  uas: s/ui/iu/
  uas: Fix response iu struct definition
  uas: Bounds check tags when using streams
  uas: Streams are numbered 1-y, rather then 0-x
  uas: Fix / cleanup usb_uas_task error handling
  uas: Only use report iu-s for task_mgmt status reporting
  scsi: Add 2 new sense codes needed by uas
  xhci: add support for suspend/resume
  xhci: Add a few missing checks for disconnected devices
Message-id: 1385712381-30918-1-git-send-email-kraxel@redhat.com
Signed-off-by: Anthony Liguori <aliguori@amazon.com>
			
			
This commit is contained in:
		
						commit
						e679f05248
					
				| @ -1293,6 +1293,11 @@ const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = { | ||||
|     .key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x02 | ||||
| }; | ||||
| 
 | ||||
| /* Illegal request, Invalid Transfer Tag */ | ||||
| const struct SCSISense sense_code_INVALID_TAG = { | ||||
|     .key = ILLEGAL_REQUEST, .asc = 0x4b, .ascq = 0x01 | ||||
| }; | ||||
| 
 | ||||
| /* Command aborted, I/O process terminated */ | ||||
| const struct SCSISense sense_code_IO_ERROR = { | ||||
|     .key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06 | ||||
| @ -1308,6 +1313,11 @@ const struct SCSISense sense_code_LUN_FAILURE = { | ||||
|     .key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01 | ||||
| }; | ||||
| 
 | ||||
| /* Command aborted, Overlapped Commands Attempted */ | ||||
| const struct SCSISense sense_code_OVERLAPPED_COMMANDS = { | ||||
|     .key = ABORTED_COMMAND, .asc = 0x4e, .ascq = 0x00 | ||||
| }; | ||||
| 
 | ||||
| /* Unit attention, Capacity data has changed */ | ||||
| const struct SCSISense sense_code_CAPACITY_CHANGED = { | ||||
|     .key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09 | ||||
|  | ||||
							
								
								
									
										18
									
								
								hw/usb/bus.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								hw/usb/bus.c
									
									
									
									
									
								
							| @ -203,6 +203,24 @@ void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps, | ||||
|                              int streams) | ||||
| { | ||||
|     USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); | ||||
|     if (klass->alloc_streams) { | ||||
|         return klass->alloc_streams(dev, eps, nr_eps, streams); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps) | ||||
| { | ||||
|     USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); | ||||
|     if (klass->free_streams) { | ||||
|         klass->free_streams(dev, eps, nr_eps); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static int usb_qdev_init(DeviceState *qdev) | ||||
| { | ||||
|     USBDevice *dev = USB_DEVICE(qdev); | ||||
|  | ||||
| @ -623,6 +623,7 @@ void usb_ep_reset(USBDevice *dev) | ||||
|     dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL; | ||||
|     dev->ep_ctl.ifnum = 0; | ||||
|     dev->ep_ctl.max_packet_size = 64; | ||||
|     dev->ep_ctl.max_streams = 0; | ||||
|     dev->ep_ctl.dev = dev; | ||||
|     dev->ep_ctl.pipeline = false; | ||||
|     for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) { | ||||
| @ -636,6 +637,8 @@ void usb_ep_reset(USBDevice *dev) | ||||
|         dev->ep_out[ep].ifnum = USB_INTERFACE_INVALID; | ||||
|         dev->ep_in[ep].max_packet_size = 0; | ||||
|         dev->ep_out[ep].max_packet_size = 0; | ||||
|         dev->ep_in[ep].max_streams = 0; | ||||
|         dev->ep_out[ep].max_streams = 0; | ||||
|         dev->ep_in[ep].dev = dev; | ||||
|         dev->ep_out[ep].dev = dev; | ||||
|         dev->ep_in[ep].pipeline = false; | ||||
| @ -764,6 +767,25 @@ int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep) | ||||
|     return uep->max_packet_size; | ||||
| } | ||||
| 
 | ||||
| void usb_ep_set_max_streams(USBDevice *dev, int pid, int ep, uint8_t raw) | ||||
| { | ||||
|     struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); | ||||
|     int MaxStreams; | ||||
| 
 | ||||
|     MaxStreams = raw & 0x1f; | ||||
|     if (MaxStreams) { | ||||
|         uep->max_streams = 1 << MaxStreams; | ||||
|     } else { | ||||
|         uep->max_streams = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int usb_ep_get_max_streams(USBDevice *dev, int pid, int ep) | ||||
| { | ||||
|     struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); | ||||
|     return uep->max_streams; | ||||
| } | ||||
| 
 | ||||
| void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled) | ||||
| { | ||||
|     struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); | ||||
|  | ||||
| @ -6,16 +6,6 @@ | ||||
| 
 | ||||
| /* ------------------------------------------------------------------ */ | ||||
| 
 | ||||
| static uint8_t usb_lo(uint16_t val) | ||||
| { | ||||
|     return val & 0xff; | ||||
| } | ||||
| 
 | ||||
| static uint8_t usb_hi(uint16_t val) | ||||
| { | ||||
|     return (val >> 8) & 0xff; | ||||
| } | ||||
| 
 | ||||
| int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, | ||||
|                     uint8_t *dest, size_t len) | ||||
| { | ||||
| @ -385,6 +375,8 @@ static void usb_desc_ep_init(USBDevice *dev) | ||||
|             usb_ep_set_ifnum(dev, pid, ep, iface->bInterfaceNumber); | ||||
|             usb_ep_set_max_packet_size(dev, pid, ep, | ||||
|                                        iface->eps[e].wMaxPacketSize); | ||||
|             usb_ep_set_max_streams(dev, pid, ep, | ||||
|                                    iface->eps[e].bmAttributes_super); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -194,6 +194,17 @@ struct USBDesc { | ||||
| 
 | ||||
| #define USB_DESC_FLAG_SUPER (1 << 1) | ||||
| 
 | ||||
| /* little helpers */ | ||||
| static inline uint8_t usb_lo(uint16_t val) | ||||
| { | ||||
|     return val & 0xff; | ||||
| } | ||||
| 
 | ||||
| static inline uint8_t usb_hi(uint16_t val) | ||||
| { | ||||
|     return (val >> 8) & 0xff; | ||||
| } | ||||
| 
 | ||||
| /* generate usb packages from structs */ | ||||
| int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, | ||||
|                     uint8_t *dest, size_t len); | ||||
|  | ||||
| @ -236,7 +236,7 @@ static const USBDescDevice desc_device_tablet2 = { | ||||
|             .bNumInterfaces        = 1, | ||||
|             .bConfigurationValue   = 1, | ||||
|             .iConfiguration        = STR_CONFIG_TABLET, | ||||
|             .bmAttributes          = 0x80, | ||||
|             .bmAttributes          = 0xa0, | ||||
|             .bMaxPower             = 50, | ||||
|             .nif = 1, | ||||
|             .ifs = &desc_iface_tablet2, | ||||
|  | ||||
							
								
								
									
										156
									
								
								hw/usb/dev-uas.c
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								hw/usb/dev-uas.c
									
									
									
									
									
								
							| @ -55,7 +55,7 @@ typedef struct { | ||||
|     uint8_t    id; | ||||
|     uint8_t    reserved; | ||||
|     uint16_t   tag; | ||||
| } QEMU_PACKED  uas_ui_header; | ||||
| } QEMU_PACKED  uas_iu_header; | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint8_t    prio_taskattr;   /* 6:3 priority, 2:0 task attribute   */ | ||||
| @ -65,7 +65,7 @@ typedef struct { | ||||
|     uint64_t   lun; | ||||
|     uint8_t    cdb[16]; | ||||
|     uint8_t    add_cdb[]; | ||||
| } QEMU_PACKED  uas_ui_command; | ||||
| } QEMU_PACKED  uas_iu_command; | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint16_t   status_qualifier; | ||||
| @ -73,29 +73,29 @@ typedef struct { | ||||
|     uint8_t    reserved[7]; | ||||
|     uint16_t   sense_length; | ||||
|     uint8_t    sense_data[18]; | ||||
| } QEMU_PACKED  uas_ui_sense; | ||||
| } QEMU_PACKED  uas_iu_sense; | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint16_t   add_response_info; | ||||
|     uint8_t    add_response_info[3]; | ||||
|     uint8_t    response_code; | ||||
| } QEMU_PACKED  uas_ui_response; | ||||
| } QEMU_PACKED  uas_iu_response; | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint8_t    function; | ||||
|     uint8_t    reserved; | ||||
|     uint16_t   task_tag; | ||||
|     uint64_t   lun; | ||||
| } QEMU_PACKED  uas_ui_task_mgmt; | ||||
| } QEMU_PACKED  uas_iu_task_mgmt; | ||||
| 
 | ||||
| typedef struct { | ||||
|     uas_ui_header  hdr; | ||||
|     uas_iu_header  hdr; | ||||
|     union { | ||||
|         uas_ui_command   command; | ||||
|         uas_ui_sense     sense; | ||||
|         uas_ui_task_mgmt task; | ||||
|         uas_ui_response  response; | ||||
|         uas_iu_command   command; | ||||
|         uas_iu_sense     sense; | ||||
|         uas_iu_task_mgmt task; | ||||
|         uas_iu_response  response; | ||||
|     }; | ||||
| } QEMU_PACKED  uas_ui; | ||||
| } QEMU_PACKED  uas_iu; | ||||
| 
 | ||||
| /* --------------------------------------------------------------------- */ | ||||
| 
 | ||||
| @ -122,8 +122,8 @@ struct UASDevice { | ||||
|     UASRequest                *dataout2; | ||||
| 
 | ||||
|     /* usb 3.0 only */ | ||||
|     USBPacket                 *data3[UAS_MAX_STREAMS]; | ||||
|     USBPacket                 *status3[UAS_MAX_STREAMS]; | ||||
|     USBPacket                 *data3[UAS_MAX_STREAMS + 1]; | ||||
|     USBPacket                 *status3[UAS_MAX_STREAMS + 1]; | ||||
| }; | ||||
| 
 | ||||
| struct UASRequest { | ||||
| @ -145,7 +145,7 @@ struct UASRequest { | ||||
| 
 | ||||
| struct UASStatus { | ||||
|     uint32_t                  stream; | ||||
|     uas_ui                    status; | ||||
|     uas_iu                    status; | ||||
|     uint32_t                  length; | ||||
|     QTAILQ_ENTRY(UASStatus)   next; | ||||
| }; | ||||
| @ -338,7 +338,7 @@ static UASStatus *usb_uas_alloc_status(UASDevice *uas, uint8_t id, uint16_t tag) | ||||
| 
 | ||||
|     st->status.hdr.id = id; | ||||
|     st->status.hdr.tag = cpu_to_be16(tag); | ||||
|     st->length = sizeof(uas_ui_header); | ||||
|     st->length = sizeof(uas_iu_header); | ||||
|     if (uas_using_streams(uas)) { | ||||
|         st->stream = tag; | ||||
|     } | ||||
| @ -392,15 +392,13 @@ static void usb_uas_queue_status(UASDevice *uas, UASStatus *st, int length) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void usb_uas_queue_response(UASDevice *uas, uint16_t tag, | ||||
|                                    uint8_t code, uint16_t add_info) | ||||
| static void usb_uas_queue_response(UASDevice *uas, uint16_t tag, uint8_t code) | ||||
| { | ||||
|     UASStatus *st = usb_uas_alloc_status(uas, UAS_UI_RESPONSE, tag); | ||||
| 
 | ||||
|     trace_usb_uas_response(uas->dev.addr, tag, code); | ||||
|     st->status.response.response_code = code; | ||||
|     st->status.response.add_response_info = cpu_to_be16(add_info); | ||||
|     usb_uas_queue_status(uas, st, sizeof(uas_ui_response)); | ||||
|     usb_uas_queue_status(uas, st, sizeof(uas_iu_response)); | ||||
| } | ||||
| 
 | ||||
| static void usb_uas_queue_sense(UASRequest *req, uint8_t status) | ||||
| @ -416,10 +414,28 @@ static void usb_uas_queue_sense(UASRequest *req, uint8_t status) | ||||
|                                   sizeof(st->status.sense.sense_data)); | ||||
|         st->status.sense.sense_length = cpu_to_be16(slen); | ||||
|     } | ||||
|     len = sizeof(uas_ui_sense) - sizeof(st->status.sense.sense_data) + slen; | ||||
|     len = sizeof(uas_iu_sense) - sizeof(st->status.sense.sense_data) + slen; | ||||
|     usb_uas_queue_status(req->uas, st, len); | ||||
| } | ||||
| 
 | ||||
| static void usb_uas_queue_fake_sense(UASDevice *uas, uint16_t tag, | ||||
|                                      struct SCSISense sense) | ||||
| { | ||||
|     UASStatus *st = usb_uas_alloc_status(uas, UAS_UI_SENSE, tag); | ||||
|     int len, slen = 0; | ||||
| 
 | ||||
|     st->status.sense.status = CHECK_CONDITION; | ||||
|     st->status.sense.status_qualifier = cpu_to_be16(0); | ||||
|     st->status.sense.sense_data[0] = 0x70; | ||||
|     st->status.sense.sense_data[2] = sense.key; | ||||
|     st->status.sense.sense_data[7] = 10; | ||||
|     st->status.sense.sense_data[12] = sense.asc; | ||||
|     st->status.sense.sense_data[13] = sense.ascq; | ||||
|     slen = 18; | ||||
|     len = sizeof(uas_iu_sense) - sizeof(st->status.sense.sense_data) + slen; | ||||
|     usb_uas_queue_status(uas, st, len); | ||||
| } | ||||
| 
 | ||||
| static void usb_uas_queue_read_ready(UASRequest *req) | ||||
| { | ||||
|     UASStatus *st = usb_uas_alloc_status(req->uas, UAS_UI_READ_READY, | ||||
| @ -518,14 +534,14 @@ static void usb_uas_start_next_transfer(UASDevice *uas) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static UASRequest *usb_uas_alloc_request(UASDevice *uas, uas_ui *ui) | ||||
| static UASRequest *usb_uas_alloc_request(UASDevice *uas, uas_iu *iu) | ||||
| { | ||||
|     UASRequest *req; | ||||
| 
 | ||||
|     req = g_new0(UASRequest, 1); | ||||
|     req->uas = uas; | ||||
|     req->tag = be16_to_cpu(ui->hdr.tag); | ||||
|     req->lun = be64_to_cpu(ui->command.lun); | ||||
|     req->tag = be16_to_cpu(iu->hdr.tag); | ||||
|     req->lun = be64_to_cpu(iu->command.lun); | ||||
|     req->dev = usb_uas_get_dev(req->uas, req->lun); | ||||
|     return req; | ||||
| } | ||||
| @ -648,7 +664,7 @@ static void usb_uas_cancel_io(USBDevice *dev, USBPacket *p) | ||||
|         return; | ||||
|     } | ||||
|     if (uas_using_streams(uas)) { | ||||
|         for (i = 0; i < UAS_MAX_STREAMS; i++) { | ||||
|         for (i = 0; i <= UAS_MAX_STREAMS; i++) { | ||||
|             if (uas->status3[i] == p) { | ||||
|                 uas->status3[i] = NULL; | ||||
|                 return; | ||||
| @ -668,16 +684,20 @@ static void usb_uas_cancel_io(USBDevice *dev, USBPacket *p) | ||||
|     assert(!"canceled usb packet not found"); | ||||
| } | ||||
| 
 | ||||
| static void usb_uas_command(UASDevice *uas, uas_ui *ui) | ||||
| static void usb_uas_command(UASDevice *uas, uas_iu *iu) | ||||
| { | ||||
|     UASRequest *req; | ||||
|     uint32_t len; | ||||
|     uint16_t tag = be16_to_cpu(iu->hdr.tag); | ||||
| 
 | ||||
|     req = usb_uas_find_request(uas, be16_to_cpu(ui->hdr.tag)); | ||||
|     if (uas_using_streams(uas) && tag > UAS_MAX_STREAMS) { | ||||
|         goto invalid_tag; | ||||
|     } | ||||
|     req = usb_uas_find_request(uas, tag); | ||||
|     if (req) { | ||||
|         goto overlapped_tag; | ||||
|     } | ||||
|     req = usb_uas_alloc_request(uas, ui); | ||||
|     req = usb_uas_alloc_request(uas, iu); | ||||
|     if (req->dev == NULL) { | ||||
|         goto bad_target; | ||||
|     } | ||||
| @ -694,7 +714,7 @@ static void usb_uas_command(UASDevice *uas, uas_ui *ui) | ||||
| 
 | ||||
|     req->req = scsi_req_new(req->dev, req->tag, | ||||
|                             usb_uas_get_lun(req->lun), | ||||
|                             ui->command.cdb, req); | ||||
|                             iu->command.cdb, req); | ||||
|     if (uas->requestlog) { | ||||
|         scsi_req_print(req->req); | ||||
|     } | ||||
| @ -705,105 +725,97 @@ static void usb_uas_command(UASDevice *uas, uas_ui *ui) | ||||
|     } | ||||
|     return; | ||||
| 
 | ||||
| invalid_tag: | ||||
|     usb_uas_queue_fake_sense(uas, tag, sense_code_INVALID_TAG); | ||||
|     return; | ||||
| 
 | ||||
| overlapped_tag: | ||||
|     usb_uas_queue_response(uas, req->tag, UAS_RC_OVERLAPPED_TAG, 0); | ||||
|     usb_uas_queue_fake_sense(uas, tag, sense_code_OVERLAPPED_COMMANDS); | ||||
|     return; | ||||
| 
 | ||||
| bad_target: | ||||
|     /*
 | ||||
|      * FIXME: Seems to upset linux, is this wrong? | ||||
|      * NOTE: Happens only with no scsi devices at the bus, not sure | ||||
|      *       this is a valid UAS setup in the first place. | ||||
|      */ | ||||
|     usb_uas_queue_response(uas, req->tag, UAS_RC_INVALID_INFO_UNIT, 0); | ||||
|     usb_uas_queue_fake_sense(uas, tag, sense_code_LUN_NOT_SUPPORTED); | ||||
|     g_free(req); | ||||
| } | ||||
| 
 | ||||
| static void usb_uas_task(UASDevice *uas, uas_ui *ui) | ||||
| static void usb_uas_task(UASDevice *uas, uas_iu *iu) | ||||
| { | ||||
|     uint16_t tag = be16_to_cpu(ui->hdr.tag); | ||||
|     uint64_t lun64 = be64_to_cpu(ui->task.lun); | ||||
|     uint16_t tag = be16_to_cpu(iu->hdr.tag); | ||||
|     uint64_t lun64 = be64_to_cpu(iu->task.lun); | ||||
|     SCSIDevice *dev = usb_uas_get_dev(uas, lun64); | ||||
|     int lun = usb_uas_get_lun(lun64); | ||||
|     UASRequest *req; | ||||
|     uint16_t task_tag; | ||||
| 
 | ||||
|     req = usb_uas_find_request(uas, be16_to_cpu(ui->hdr.tag)); | ||||
|     if (uas_using_streams(uas) && tag > UAS_MAX_STREAMS) { | ||||
|         goto invalid_tag; | ||||
|     } | ||||
|     req = usb_uas_find_request(uas, be16_to_cpu(iu->hdr.tag)); | ||||
|     if (req) { | ||||
|         goto overlapped_tag; | ||||
|     } | ||||
|     if (dev == NULL) { | ||||
|         goto incorrect_lun; | ||||
|     } | ||||
| 
 | ||||
|     switch (ui->task.function) { | ||||
|     switch (iu->task.function) { | ||||
|     case UAS_TMF_ABORT_TASK: | ||||
|         task_tag = be16_to_cpu(ui->task.task_tag); | ||||
|         task_tag = be16_to_cpu(iu->task.task_tag); | ||||
|         trace_usb_uas_tmf_abort_task(uas->dev.addr, tag, task_tag); | ||||
|         if (dev == NULL) { | ||||
|             goto bad_target; | ||||
|         } | ||||
|         if (dev->lun != lun) { | ||||
|             goto incorrect_lun; | ||||
|         } | ||||
|         req = usb_uas_find_request(uas, task_tag); | ||||
|         if (req && req->dev == dev) { | ||||
|             scsi_req_cancel(req->req); | ||||
|         } | ||||
|         usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE, 0); | ||||
|         usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE); | ||||
|         break; | ||||
| 
 | ||||
|     case UAS_TMF_LOGICAL_UNIT_RESET: | ||||
|         trace_usb_uas_tmf_logical_unit_reset(uas->dev.addr, tag, lun); | ||||
|         if (dev == NULL) { | ||||
|             goto bad_target; | ||||
|         } | ||||
|         if (dev->lun != lun) { | ||||
|             goto incorrect_lun; | ||||
|         } | ||||
|         qdev_reset_all(&dev->qdev); | ||||
|         usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE, 0); | ||||
|         usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         trace_usb_uas_tmf_unsupported(uas->dev.addr, tag, ui->task.function); | ||||
|         usb_uas_queue_response(uas, tag, UAS_RC_TMF_NOT_SUPPORTED, 0); | ||||
|         trace_usb_uas_tmf_unsupported(uas->dev.addr, tag, iu->task.function); | ||||
|         usb_uas_queue_response(uas, tag, UAS_RC_TMF_NOT_SUPPORTED); | ||||
|         break; | ||||
|     } | ||||
|     return; | ||||
| 
 | ||||
| overlapped_tag: | ||||
|     usb_uas_queue_response(uas, req->tag, UAS_RC_OVERLAPPED_TAG, 0); | ||||
| invalid_tag: | ||||
|     usb_uas_queue_response(uas, tag, UAS_RC_INVALID_INFO_UNIT); | ||||
|     return; | ||||
| 
 | ||||
| bad_target: | ||||
|     /* FIXME: correct?  [see long comment in usb_uas_command()] */ | ||||
|     usb_uas_queue_response(uas, tag, UAS_RC_INVALID_INFO_UNIT, 0); | ||||
| overlapped_tag: | ||||
|     usb_uas_queue_response(uas, req->tag, UAS_RC_OVERLAPPED_TAG); | ||||
|     return; | ||||
| 
 | ||||
| incorrect_lun: | ||||
|     usb_uas_queue_response(uas, tag, UAS_RC_INCORRECT_LUN, 0); | ||||
|     usb_uas_queue_response(uas, tag, UAS_RC_INCORRECT_LUN); | ||||
| } | ||||
| 
 | ||||
| static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) | ||||
| { | ||||
|     UASDevice *uas = DO_UPCAST(UASDevice, dev, dev); | ||||
|     uas_ui ui; | ||||
|     uas_iu iu; | ||||
|     UASStatus *st; | ||||
|     UASRequest *req; | ||||
|     int length; | ||||
| 
 | ||||
|     switch (p->ep->nr) { | ||||
|     case UAS_PIPE_ID_COMMAND: | ||||
|         length = MIN(sizeof(ui), p->iov.size); | ||||
|         usb_packet_copy(p, &ui, length); | ||||
|         switch (ui.hdr.id) { | ||||
|         length = MIN(sizeof(iu), p->iov.size); | ||||
|         usb_packet_copy(p, &iu, length); | ||||
|         switch (iu.hdr.id) { | ||||
|         case UAS_UI_COMMAND: | ||||
|             usb_uas_command(uas, &ui); | ||||
|             usb_uas_command(uas, &iu); | ||||
|             break; | ||||
|         case UAS_UI_TASK_MGMT: | ||||
|             usb_uas_task(uas, &ui); | ||||
|             usb_uas_task(uas, &iu); | ||||
|             break; | ||||
|         default: | ||||
|             fprintf(stderr, "%s: unknown command ui: id 0x%x\n", | ||||
|                     __func__, ui.hdr.id); | ||||
|             fprintf(stderr, "%s: unknown command iu: id 0x%x\n", | ||||
|                     __func__, iu.hdr.id); | ||||
|             p->status = USB_RET_STALL; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
| @ -827,9 +827,9 @@ static void ehci_child_detach(USBPort *port, USBDevice *child) | ||||
| static void ehci_wakeup(USBPort *port) | ||||
| { | ||||
|     EHCIState *s = port->opaque; | ||||
|     uint32_t portsc = s->portsc[port->index]; | ||||
|     uint32_t *portsc = &s->portsc[port->index]; | ||||
| 
 | ||||
|     if (portsc & PORTSC_POWNER) { | ||||
|     if (*portsc & PORTSC_POWNER) { | ||||
|         USBPort *companion = s->companion_ports[port->index]; | ||||
|         if (companion->ops->wakeup) { | ||||
|             companion->ops->wakeup(companion); | ||||
| @ -837,6 +837,12 @@ static void ehci_wakeup(USBPort *port) | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (*portsc & PORTSC_SUSPEND) { | ||||
|         trace_usb_ehci_port_wakeup(port->index); | ||||
|         *portsc |= PORTSC_FPRES; | ||||
|         ehci_raise_irq(s, USBSTS_PCD); | ||||
|     } | ||||
| 
 | ||||
|     qemu_bh_schedule(s->async_bh); | ||||
| } | ||||
| 
 | ||||
| @ -1068,6 +1074,14 @@ static void ehci_port_write(void *ptr, hwaddr addr, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if ((val & PORTSC_SUSPEND) && !(*portsc & PORTSC_SUSPEND)) { | ||||
|         trace_usb_ehci_port_suspend(port); | ||||
|     } | ||||
|     if (!(val & PORTSC_FPRES) && (*portsc & PORTSC_FPRES)) { | ||||
|         trace_usb_ehci_port_resume(port); | ||||
|         val &= ~PORTSC_SUSPEND; | ||||
|     } | ||||
| 
 | ||||
|     *portsc &= ~PORTSC_RO_MASK; | ||||
|     *portsc |= val; | ||||
|     trace_usb_ehci_portsc_change(addr + s->portscbase, addr >> 2, *portsc, old); | ||||
|  | ||||
| @ -1150,6 +1150,111 @@ static void xhci_free_streams(XHCIEPContext *epctx) | ||||
|     epctx->nr_pstreams = 0; | ||||
| } | ||||
| 
 | ||||
| static int xhci_epmask_to_eps_with_streams(XHCIState *xhci, | ||||
|                                            unsigned int slotid, | ||||
|                                            uint32_t epmask, | ||||
|                                            XHCIEPContext **epctxs, | ||||
|                                            USBEndpoint **eps) | ||||
| { | ||||
|     XHCISlot *slot; | ||||
|     XHCIEPContext *epctx; | ||||
|     USBEndpoint *ep; | ||||
|     int i, j; | ||||
| 
 | ||||
|     assert(slotid >= 1 && slotid <= xhci->numslots); | ||||
| 
 | ||||
|     slot = &xhci->slots[slotid - 1]; | ||||
| 
 | ||||
|     for (i = 2, j = 0; i <= 31; i++) { | ||||
|         if (!(epmask & (1 << i))) { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         epctx = slot->eps[i - 1]; | ||||
|         ep = xhci_epid_to_usbep(xhci, slotid, i); | ||||
|         if (!epctx || !epctx->nr_pstreams || !ep) { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         if (epctxs) { | ||||
|             epctxs[j] = epctx; | ||||
|         } | ||||
|         eps[j++] = ep; | ||||
|     } | ||||
|     return j; | ||||
| } | ||||
| 
 | ||||
| static void xhci_free_device_streams(XHCIState *xhci, unsigned int slotid, | ||||
|                                      uint32_t epmask) | ||||
| { | ||||
|     USBEndpoint *eps[30]; | ||||
|     int nr_eps; | ||||
| 
 | ||||
|     nr_eps = xhci_epmask_to_eps_with_streams(xhci, slotid, epmask, NULL, eps); | ||||
|     if (nr_eps) { | ||||
|         usb_device_free_streams(eps[0]->dev, eps, nr_eps); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static TRBCCode xhci_alloc_device_streams(XHCIState *xhci, unsigned int slotid, | ||||
|                                           uint32_t epmask) | ||||
| { | ||||
|     XHCIEPContext *epctxs[30]; | ||||
|     USBEndpoint *eps[30]; | ||||
|     int i, r, nr_eps, req_nr_streams, dev_max_streams; | ||||
| 
 | ||||
|     nr_eps = xhci_epmask_to_eps_with_streams(xhci, slotid, epmask, epctxs, | ||||
|                                              eps); | ||||
|     if (nr_eps == 0) { | ||||
|         return CC_SUCCESS; | ||||
|     } | ||||
| 
 | ||||
|     req_nr_streams = epctxs[0]->nr_pstreams; | ||||
|     dev_max_streams = eps[0]->max_streams; | ||||
| 
 | ||||
|     for (i = 1; i < nr_eps; i++) { | ||||
|         /*
 | ||||
|          * HdG: I don't expect these to ever trigger, but if they do we need | ||||
|          * to come up with another solution, ie group identical endpoints | ||||
|          * together and make an usb_device_alloc_streams call per group. | ||||
|          */ | ||||
|         if (epctxs[i]->nr_pstreams != req_nr_streams) { | ||||
|             FIXME("guest streams config not identical for all eps"); | ||||
|             return CC_RESOURCE_ERROR; | ||||
|         } | ||||
|         if (eps[i]->max_streams != dev_max_streams) { | ||||
|             FIXME("device streams config not identical for all eps"); | ||||
|             return CC_RESOURCE_ERROR; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /*
 | ||||
|      * max-streams in both the device descriptor and in the controller is a | ||||
|      * power of 2. But stream id 0 is reserved, so if a device can do up to 4 | ||||
|      * streams the guest will ask for 5 rounded up to the next power of 2 which | ||||
|      * becomes 8. For emulated devices usb_device_alloc_streams is a nop. | ||||
|      * | ||||
|      * For redirected devices however this is an issue, as there we must ask | ||||
|      * the real xhci controller to alloc streams, and the host driver for the | ||||
|      * real xhci controller will likely disallow allocating more streams then | ||||
|      * the device can handle. | ||||
|      * | ||||
|      * So we limit the requested nr_streams to the maximum number the device | ||||
|      * can handle. | ||||
|      */ | ||||
|     if (req_nr_streams > dev_max_streams) { | ||||
|         req_nr_streams = dev_max_streams; | ||||
|     } | ||||
| 
 | ||||
|     r = usb_device_alloc_streams(eps[0]->dev, eps, nr_eps, req_nr_streams); | ||||
|     if (r != 0) { | ||||
|         fprintf(stderr, "xhci: alloc streams failed\n"); | ||||
|         return CC_RESOURCE_ERROR; | ||||
|     } | ||||
| 
 | ||||
|     return CC_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx, | ||||
|                                            unsigned int streamid, | ||||
|                                            uint32_t *cc_error) | ||||
| @ -1495,7 +1600,8 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid, | ||||
|     } | ||||
| 
 | ||||
|     if (!xhci->slots[slotid-1].uport || | ||||
|         !xhci->slots[slotid-1].uport->dev) { | ||||
|         !xhci->slots[slotid-1].uport->dev || | ||||
|         !xhci->slots[slotid-1].uport->dev->attached) { | ||||
|         return CC_USB_TRANSACTION_ERROR; | ||||
|     } | ||||
| 
 | ||||
| @ -1982,6 +2088,14 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     /* If the device has been detached, but the guest has not noticed this
 | ||||
|        yet the 2 above checks will succeed, but we must NOT continue */ | ||||
|     if (!xhci->slots[slotid - 1].uport || | ||||
|         !xhci->slots[slotid - 1].uport->dev || | ||||
|         !xhci->slots[slotid - 1].uport->dev->attached) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (epctx->retry) { | ||||
|         XHCITransfer *xfer = epctx->retry; | ||||
| 
 | ||||
| @ -2206,7 +2320,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, | ||||
|     trace_usb_xhci_slot_address(slotid, uport->path); | ||||
| 
 | ||||
|     dev = uport->dev; | ||||
|     if (!dev) { | ||||
|     if (!dev || !dev->attached) { | ||||
|         fprintf(stderr, "xhci: port %s not connected\n", uport->path); | ||||
|         return CC_USB_TRANSACTION_ERROR; | ||||
|     } | ||||
| @ -2313,6 +2427,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, | ||||
|         return CC_CONTEXT_STATE_ERROR; | ||||
|     } | ||||
| 
 | ||||
|     xhci_free_device_streams(xhci, slotid, ictl_ctx[0] | ictl_ctx[1]); | ||||
| 
 | ||||
|     for (i = 2; i <= 31; i++) { | ||||
|         if (ictl_ctx[0] & (1<<i)) { | ||||
|             xhci_disable_ep(xhci, slotid, i); | ||||
| @ -2334,6 +2450,16 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     res = xhci_alloc_device_streams(xhci, slotid, ictl_ctx[1]); | ||||
|     if (res != CC_SUCCESS) { | ||||
|         for (i = 2; i <= 31; i++) { | ||||
|             if (ictl_ctx[1] & (1 << i)) { | ||||
|                 xhci_disable_ep(xhci, slotid, i); | ||||
|             } | ||||
|         } | ||||
|         return res; | ||||
|     } | ||||
| 
 | ||||
|     slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT); | ||||
|     slot_ctx[3] |= SLOT_CONFIGURED << SLOT_STATE_SHIFT; | ||||
|     slot_ctx[0] &= ~(SLOT_CONTEXT_ENTRIES_MASK << SLOT_CONTEXT_ENTRIES_SHIFT); | ||||
| @ -3016,6 +3142,14 @@ static void xhci_oper_write(void *ptr, hwaddr reg, | ||||
|         } else if (!(val & USBCMD_RS) && (xhci->usbcmd & USBCMD_RS)) { | ||||
|             xhci_stop(xhci); | ||||
|         } | ||||
|         if (val & USBCMD_CSS) { | ||||
|             /* save state */ | ||||
|             xhci->usbsts &= ~USBSTS_SRE; | ||||
|         } | ||||
|         if (val & USBCMD_CRS) { | ||||
|             /* restore state */ | ||||
|             xhci->usbsts |= USBSTS_SRE; | ||||
|         } | ||||
|         xhci->usbcmd = val & 0xc0f; | ||||
|         xhci_mfwrap_update(xhci); | ||||
|         if (val & USBCMD_HCRST) { | ||||
|  | ||||
| @ -199,12 +199,16 @@ extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED; | ||||
| extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT; | ||||
| /* Illegal request, medium removal prevented */ | ||||
| extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED; | ||||
| /* Illegal request, Invalid Transfer Tag */ | ||||
| extern const struct SCSISense sense_code_INVALID_TAG; | ||||
| /* Command aborted, I/O process terminated */ | ||||
| extern const struct SCSISense sense_code_IO_ERROR; | ||||
| /* Command aborted, I_T Nexus loss occurred */ | ||||
| extern const struct SCSISense sense_code_I_T_NEXUS_LOSS; | ||||
| /* Command aborted, Logical Unit failure */ | ||||
| extern const struct SCSISense sense_code_LUN_FAILURE; | ||||
| /* Command aborted, Overlapped Commands Attempted */ | ||||
| extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS; | ||||
| /* LUN not ready, Capacity data has changed */ | ||||
| extern const struct SCSISense sense_code_CAPACITY_CHANGED; | ||||
| /* LUN not ready, Medium not present */ | ||||
|  | ||||
| @ -102,17 +102,26 @@ | ||||
| 
 | ||||
| #define DeviceRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) | ||||
| #define DeviceOutRequest ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) | ||||
| #define InterfaceRequest \ | ||||
| #define VendorDeviceRequest ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) | ||||
| #define VendorDeviceOutRequest \ | ||||
|         ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) | ||||
| 
 | ||||
| #define InterfaceRequest                                        \ | ||||
|         ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) | ||||
| #define InterfaceOutRequest \ | ||||
|         ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) | ||||
| #define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) | ||||
| #define EndpointOutRequest \ | ||||
|         ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) | ||||
| #define ClassInterfaceRequest \ | ||||
|         ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) | ||||
| #define ClassInterfaceOutRequest \ | ||||
|         ((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) | ||||
| #define VendorInterfaceRequest \ | ||||
|         ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8) | ||||
| #define VendorInterfaceOutRequest \ | ||||
|         ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8) | ||||
| 
 | ||||
| #define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) | ||||
| #define EndpointOutRequest \ | ||||
|         ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) | ||||
| 
 | ||||
| #define USB_REQ_GET_STATUS		0x00 | ||||
| #define USB_REQ_CLEAR_FEATURE		0x01 | ||||
| @ -189,6 +198,7 @@ struct USBEndpoint { | ||||
|     uint8_t type; | ||||
|     uint8_t ifnum; | ||||
|     int max_packet_size; | ||||
|     int max_streams; | ||||
|     bool pipeline; | ||||
|     bool halted; | ||||
|     USBDevice *dev; | ||||
| @ -314,6 +324,14 @@ typedef struct USBDeviceClass { | ||||
|      */ | ||||
|     void (*ep_stopped)(USBDevice *dev, USBEndpoint *ep); | ||||
| 
 | ||||
|     /*
 | ||||
|      * Called by the hcd to alloc / free streams on a bulk endpoint. | ||||
|      * Optional may be NULL. | ||||
|      */ | ||||
|     int (*alloc_streams)(USBDevice *dev, USBEndpoint **eps, int nr_eps, | ||||
|                          int streams); | ||||
|     void (*free_streams)(USBDevice *dev, USBEndpoint **eps, int nr_eps); | ||||
| 
 | ||||
|     const char *product_desc; | ||||
|     const USBDesc *usb_desc; | ||||
| } USBDeviceClass; | ||||
| @ -421,6 +439,8 @@ void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum); | ||||
| void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep, | ||||
|                                 uint16_t raw); | ||||
| int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep); | ||||
| void usb_ep_set_max_streams(USBDevice *dev, int pid, int ep, uint8_t raw); | ||||
| int usb_ep_get_max_streams(USBDevice *dev, int pid, int ep); | ||||
| void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled); | ||||
| void usb_ep_set_halted(USBDevice *dev, int pid, int ep, bool halted); | ||||
| USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep, | ||||
| @ -550,6 +570,10 @@ void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep); | ||||
| 
 | ||||
| void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep); | ||||
| 
 | ||||
| int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps, | ||||
|                              int streams); | ||||
| void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps); | ||||
| 
 | ||||
| const char *usb_device_get_product_desc(USBDevice *dev); | ||||
| 
 | ||||
| const USBDesc *usb_device_get_usb_desc(USBDevice *dev); | ||||
|  | ||||
							
								
								
									
										16
									
								
								trace-events
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								trace-events
									
									
									
									
									
								
							| @ -309,6 +309,9 @@ usb_ehci_sitd(uint32_t addr, uint32_t nxt, uint32_t active) "ITD @ %08x: next %0 | ||||
| usb_ehci_port_attach(uint32_t port, const char *owner, const char *device) "attach port #%d, owner %s, device %s" | ||||
| usb_ehci_port_detach(uint32_t port, const char *owner) "detach port #%d, owner %s" | ||||
| usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d" | ||||
| usb_ehci_port_suspend(uint32_t port) "port #%d" | ||||
| usb_ehci_port_wakeup(uint32_t port) "port #%d" | ||||
| usb_ehci_port_resume(uint32_t port) "port #%d" | ||||
| usb_ehci_queue_action(void *q, const char *action) "q %p: %s" | ||||
| usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s" | ||||
| usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) "level %d, frindex 0x%04x, sts 0x%x, mask 0x%x" | ||||
| @ -427,45 +430,32 @@ usb_uas_tmf_abort_task(int addr, uint16_t tag, uint16_t task_tag) "dev %d, tag 0 | ||||
| usb_uas_tmf_logical_unit_reset(int addr, uint16_t tag, int lun) "dev %d, tag 0x%x, lun %d" | ||||
| usb_uas_tmf_unsupported(int addr, uint16_t tag, uint32_t function) "dev %d, tag 0x%x, function 0x%x" | ||||
| 
 | ||||
| # hw/usb/host-linux.c | ||||
| # hw/usb/host-libusb.c | ||||
| usb_host_open_started(int bus, int addr) "dev %d:%d" | ||||
| usb_host_open_success(int bus, int addr) "dev %d:%d" | ||||
| usb_host_open_failure(int bus, int addr) "dev %d:%d" | ||||
| usb_host_disconnect(int bus, int addr) "dev %d:%d" | ||||
| usb_host_close(int bus, int addr) "dev %d:%d" | ||||
| usb_host_attach_kernel(int bus, int addr, int interface) "dev %d:%d, if %d" | ||||
| usb_host_detach_kernel(int bus, int addr, int interface) "dev %d:%d, if %d" | ||||
| usb_host_set_address(int bus, int addr, int config) "dev %d:%d, address %d" | ||||
| usb_host_set_config(int bus, int addr, int config) "dev %d:%d, config %d" | ||||
| usb_host_set_interface(int bus, int addr, int interface, int alt) "dev %d:%d, interface %d, alt %d" | ||||
| usb_host_claim_interfaces(int bus, int addr, int config, int nif) "dev %d:%d, config %d, nif %d" | ||||
| usb_host_claim_interface(int bus, int addr, int config, int interface) "dev %d:%d, config %d, if %d" | ||||
| usb_host_release_interfaces(int bus, int addr) "dev %d:%d" | ||||
| usb_host_release_interface(int bus, int addr, int interface) "dev %d:%d, if %d" | ||||
| usb_host_req_control(int bus, int addr, void *p, int req, int value, int index) "dev %d:%d, packet %p, req 0x%x, value %d, index %d" | ||||
| usb_host_req_data(int bus, int addr, void *p, int in, int ep, int size) "dev %d:%d, packet %p, in %d, ep %d, size %d" | ||||
| usb_host_req_complete(int bus, int addr, void *p, int status, int length) "dev %d:%d, packet %p, status %d, length %d" | ||||
| usb_host_req_emulated(int bus, int addr, void *p, int status) "dev %d:%d, packet %p, status %d" | ||||
| usb_host_req_canceled(int bus, int addr, void *p) "dev %d:%d, packet %p" | ||||
| usb_host_urb_submit(int bus, int addr, void *aurb, int length, int more) "dev %d:%d, aurb %p, length %d, more %d" | ||||
| usb_host_urb_complete(int bus, int addr, void *aurb, int status, int length, int more) "dev %d:%d, aurb %p, status %d, length %d, more %d" | ||||
| usb_host_urb_canceled(int bus, int addr, void *aurb) "dev %d:%d, aurb %p" | ||||
| usb_host_ep_set_halt(int bus, int addr, int ep) "dev %d:%d, ep %d" | ||||
| usb_host_ep_clear_halt(int bus, int addr, int ep) "dev %d:%d, ep %d" | ||||
| usb_host_iso_start(int bus, int addr, int ep) "dev %d:%d, ep %d" | ||||
| usb_host_iso_stop(int bus, int addr, int ep) "dev %d:%d, ep %d" | ||||
| usb_host_iso_out_of_bufs(int bus, int addr, int ep) "dev %d:%d, ep %d" | ||||
| usb_host_iso_many_urbs(int bus, int addr, int count) "dev %d:%d, count %d" | ||||
| usb_host_reset(int bus, int addr) "dev %d:%d" | ||||
| usb_host_auto_scan_enabled(void) | ||||
| usb_host_auto_scan_disabled(void) | ||||
| usb_host_claim_port(int bus, int hub, int port) "bus %d, hub addr %d, port %d" | ||||
| usb_host_parse_device(int bus, int addr, int vendor, int product) "dev %d:%d, id %04x:%04x" | ||||
| usb_host_parse_config(int bus, int addr, int value, int active) "dev %d:%d, value %d, active %d" | ||||
| usb_host_parse_interface(int bus, int addr, int num, int alt, int active) "dev %d:%d, num %d, alt %d, active %d" | ||||
| usb_host_parse_endpoint(int bus, int addr, int ep, const char *dir, const char *type, int active) "dev %d:%d, ep %d, %s, %s, active %d" | ||||
| usb_host_parse_unknown(int bus, int addr, int len, int type) "dev %d:%d, len %d, type %d" | ||||
| usb_host_parse_error(int bus, int addr, const char *errmsg) "dev %d:%d, msg %s" | ||||
| 
 | ||||
| # hw/scsi/scsi-bus.c | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Anthony Liguori
						Anthony Liguori