diff --git a/devicemodel/hw/pci/xhci.c b/devicemodel/hw/pci/xhci.c index 6b72da09c..b4e453f25 100644 --- a/devicemodel/hw/pci/xhci.c +++ b/devicemodel/hw/pci/xhci.c @@ -2572,44 +2572,73 @@ pci_xhci_complete_commands(struct pci_xhci_vdev *xdev) case XHCI_TRB_TYPE_DISABLE_SLOT: /* 0x0A */ slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); - cmderr = pci_xhci_cmd_disable_slot(xdev, slot); + /* + * From spec 4.5.3.2 The only command that software is + * allowed to issue for the slot in disabled state + * is Enable Slot Command. + * */ + if (xdev->slot_allocated[slot]) + cmderr = pci_xhci_cmd_disable_slot(xdev, slot); + else + cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; break; case XHCI_TRB_TYPE_ADDRESS_DEVICE: /* 0x0B */ slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); - cmderr = pci_xhci_cmd_address_device(xdev, slot, trb); + if (xdev->slot_allocated[slot]) + cmderr = pci_xhci_cmd_address_device(xdev, slot, trb); + else + cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; break; case XHCI_TRB_TYPE_CONFIGURE_EP: /* 0x0C */ slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); - cmderr = pci_xhci_cmd_config_ep(xdev, slot, trb); + if (xdev->slot_allocated[slot]) + cmderr = pci_xhci_cmd_config_ep(xdev, slot, trb); + else + cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; break; case XHCI_TRB_TYPE_EVALUATE_CTX: /* 0x0D */ slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); - cmderr = pci_xhci_cmd_eval_ctx(xdev, slot, trb); + if (xdev->slot_allocated[slot]) + cmderr = pci_xhci_cmd_eval_ctx(xdev, slot, trb); + else + cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; break; case XHCI_TRB_TYPE_RESET_EP: /* 0x0E */ UPRINTF(LDBG, "Reset Endpoint on slot %d\r\n", slot); slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); - cmderr = pci_xhci_cmd_reset_ep(xdev, slot, trb); + if (xdev->slot_allocated[slot]) + cmderr = pci_xhci_cmd_reset_ep(xdev, slot, trb); + else + cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; break; case XHCI_TRB_TYPE_STOP_EP: /* 0x0F */ UPRINTF(LDBG, "Stop Endpoint on slot %d\r\n", slot); slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); - cmderr = pci_xhci_cmd_reset_ep(xdev, slot, trb); + if (xdev->slot_allocated[slot]) + cmderr = pci_xhci_cmd_reset_ep(xdev, slot, trb); + else + cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; break; case XHCI_TRB_TYPE_SET_TR_DEQUEUE: /* 0x10 */ slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); - cmderr = pci_xhci_cmd_set_tr(xdev, slot, trb); + if (xdev->slot_allocated[slot]) + cmderr = pci_xhci_cmd_set_tr(xdev, slot, trb); + else + cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; break; case XHCI_TRB_TYPE_RESET_DEVICE: /* 0x11 */ slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); - cmderr = pci_xhci_cmd_reset_device(xdev, slot); + if (xdev->slot_allocated[slot]) + cmderr = pci_xhci_cmd_reset_device(xdev, slot); + else + cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; break; case XHCI_TRB_TYPE_FORCE_EVENT: /* 0x12 */