xHCI: Got Completion Code 0x11(context parameter error) when perfroming Address Command

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Oython
Posts: 15
Joined: Wed Aug 03, 2022 8:17 pm
Libera.chat IRC: no

xHCI: Got Completion Code 0x11(context parameter error) when perfroming Address Command

Post by Oython »

These days I try to implement a xHCI driver on x86_64 platform.But I met various problem, espescially when it comes to the Device Initialization.
My current problem is that when I try to perform Address Command with BSR=0, it return Completion Code 0x11 (context parameter error), but I can't find out the mistake.
The structure of my code:
1.Detect USB Device Attachment and reset the port(for USB2)
2.Enable the slot
3.Initialite the input context
4.Perform Address Command with BSR=1
5.Perform Address Command with BSR=0
...
When I try to delete step 4, the controller returns the code 0x4 (USB Transaction Error)
And I have tried hundreds of methods to sovle the problem, but I failed.
Here is my code:

Code: Select all

struct xHCI_EXTRA *xHCI_extra = du->spe.xhci.xhci_extra;
    struct Message_reader *mr = get_currunt_process_message_addr();
    char num_64_msg[] = "xxxxxxxxxxxxxxxx";
    // print(0xffffffff, 0xff000000, a);

    if ((xHCIportinf[portID] & 0xff) < 0x30)
    {
        // USB2 PORT
        xHCI_extra->opr->PRS[portID].PORTSC |= 1 << 4; // reset
        while ((xHCI_extra->opr->PRS[portID].PORTSC & (1 << 4)) || (xHCI_extra->opr->PRS[portID].PORTSC & 0x1e0))
        {
            /* code */
        }
        
        // m = (*wait_for_message_p)(mr, &m, 0b111);
        // (*print_p)(INF (*long_longToChar16_p)(portID, num_64_msg));
        if (xHCI_extra->opr->PRS[portID].PORTSC & 0x200000)
        {
            xHCI_extra->opr->PRS[portID].PORTSC = xHCI_extra->opr->PRS[portID].PORTSC;
        }
        char usb2_msg[] = "USB2 Port Attachment\n";
        print(INF usb2_msg);
        // break; // error
    }
    else
    {
        // USB3 PORT
        while (((xHCI_extra->opr->PRS[portID].PORTSC >> 5) & 0xf) != 0)
        {
            // active_switch();
        }
        char usb3_msg[] = "USB3 Port Attachment\n";
        print(INF usb3_msg);
    }

    struct xHCIEnableSlotCommandTRB cmd_es = {0};
    // cmd_es.SlotType = (xHCI_port_usb_type[portID] >> 8) & 0xff;
    cmd_es.SlotType = portID;
    cmd_es.TRBType = 9;
    xHCI_place_trb(&du->spe.xhci.xhci_extra->crcr, &cmd_es);
    xHCI_extra->db[0] = 0;
    struct Message escmd_m = { 
        .message_type = MSG_TYPE_XHCI,
        .message_content = 9, // Enable Slot Command
        .message_status = 0
    };

    escmd_m = wait_for_message(mr, &escmd_m, 0b1110); 
    char msg_cmd[] = "[PDD] Enabled Slot!\n";
    print(0xffffffff, 0xff000000, msg_cmd);
    print(INF long_longToChar16(escmd_m.message_content, num_64_msg));
    struct xHCICommandCompletionEventTRB t_event = *((struct xHCICommandCompletionEventTRB *) escmd_m.extra);

    struct xHCILinkTRB *TRDequeuePointer = alloc_ring(1);
    
    
    void *input_context_addr = kernelMalloc(_4KB, WB);
    unsigned int MaxPacketSize = xHCIget_MaxPacketSize_byPortID(du, portID);
    MaxPacketSize = 16;
    
    
    if (xHCI_extra->cap->HCCPARAMS1 & 4)
    {
        // 64 Byte
        struct xHCIInputContext64 *input_context = input_context_addr;
        input_context->InputControlContext.A |= 0b11;
        input_context->DeviceContext.SlotContext.RootHubPortNumber = portID + 1;
        input_context->DeviceContext.SlotContext.ContextEntries = 1;
        input_context->DeviceContext.EPContext0BiDir.EPType = 4;
        input_context->DeviceContext.SlotContext.Speed = (xHCI_extra->opr->PRS[portID].PORTSC >> 10) & 0xf;
        input_context->DeviceContext.EPContext0BiDir.MaxPacketSize = MaxPacketSize;
        input_context->DeviceContext.SlotContext.SlotState = 1;
        input_context->DeviceContext.EPContext0BiDir.TRDequeuePointer = ((unsigned long long) GetPaddr(TRDequeuePointer)) | 1;
        input_context->DeviceContext.EPContext0BiDir.CErr = 3;
        input_context->DeviceContext.EPContext0BiDir.AverageTRBLength = 8;
        xHCI_extra->DCBAAP[t_event.SlotID] = GetPaddr(input_context) + (((unsigned long long) &input_context->DeviceContext) & 0xfff);
        
    } 
    else
    {
        // 32 Byte
        input_context_addr += 32; // To Ensure Boundary
        struct xHCIInputContext32 *input_context = input_context_addr;
        input_context->InputControlContext.A |= 0b11;
        input_context->DeviceContext.SlotContext.RootHubPortNumber = portID + 1;
        input_context->DeviceContext.SlotContext.ContextEntries = 1;
        input_context->DeviceContext.EPContext0BiDir.EPType = 4;
        input_context->DeviceContext.SlotContext.Speed = (xHCI_extra->opr->PRS[portID].PORTSC >> 10) & 0xf;
        input_context->DeviceContext.SlotContext.SlotState = 1;
        input_context->DeviceContext.EPContext0BiDir.MaxPacketSize = MaxPacketSize;
        input_context->DeviceContext.EPContext0BiDir.TRDequeuePointer = ((unsigned long long) GetPaddr(TRDequeuePointer)) | 1;
        input_context->DeviceContext.EPContext0BiDir.CErr = 3; 
        input_context->DeviceContext.EPContext0BiDir.AverageTRBLength = 8;
        xHCI_extra->DCBAAP[t_event.SlotID] = GetPaddr(input_context) + (((unsigned long long) &input_context->DeviceContext) & 0xfff);
    }
    struct xHCIAddressDeviceCommandTRB cmd_ad = {0};
    cmd_ad.InputContextPointer = GetPaddr(input_context_addr) + (((unsigned long long) input_context_addr) & 0xfff);
    cmd_ad.SlotID = t_event.SlotID;
    cmd_ad.TRBType = 11;
    cmd_ad.BSR = 1;
    xHCI_place_trb(&du->spe.xhci.xhci_extra->crcr, &cmd_ad);
    xHCI_extra->db[0] = 0;
    struct Message adcmd_m = {
        .message_type = MSG_TYPE_XHCI,
        .message_content = 11,
        .message_status = 0
    }; 
    wait_for_message(mr, &adcmd_m, 0b1110);
    if (xHCI_extra->cap->HCCPARAMS1 & 4)
    {
        struct xHCIInputContext64 *input_context = input_context_addr;
        input_context->DeviceContext.SlotContext.USBDeviceAddress = 0;
    } 
    else
    {
        struct xHCIInputContext32 *input_context = input_context_addr;
        input_context->DeviceContext.SlotContext.USBDeviceAddress = 0;
    }
    
    cmd_ad.BSR = 0;
    xHCI_place_trb(&du->spe.xhci.xhci_extra->crcr, &cmd_ad);
    xHCI_extra->db[0] = 0;
......
I would appreciate it if you could solve my problem! :)
Oython
Posts: 15
Joined: Wed Aug 03, 2022 8:17 pm
Libera.chat IRC: no

Re: xHCI: Got Completion Code 0x11(context parameter error) when perfroming Address Command

Post by Oython »

In addition, it's ok on VmWare, but goes wrong on real hardware.On bochs, my driver can't work at all, I am confused.Who can help me??!
User avatar
BenLunt
Member
Member
Posts: 1029
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: xHCI: Got Completion Code 0x11(context parameter error) when perfroming Address Command

Post by BenLunt »

Oython wrote: Thu Aug 28, 2025 7:45 am On bochs, my driver can't work at all
Did you set Bochs to use the debug output and/or the actual USB Debugger?

First, the debug output will give you a lot of information and you can see what is working or not working. Second, if you use the USB Debugger, it will show you each TRB as it is being processed, before and after it being processed.

Have a look at a recent post for information on how to do this: viewtopic.php?p=352649#p352649

Ben
- https://www.fysnet.net/the_universal_serial_bus.htm
Oython
Posts: 15
Joined: Wed Aug 03, 2022 8:17 pm
Libera.chat IRC: no

Re: xHCI: Got Completion Code 0x11(context parameter error) when perfroming Address Command

Post by Oython »

BenLunt wrote: Thu Aug 28, 2025 9:12 am
Oython wrote: Thu Aug 28, 2025 7:45 am On bochs, my driver can't work at all
Did you set Bochs to use the debug output and/or the actual USB Debugger?

First, the debug output will give you a lot of information and you can see what is working or not working. Second, if you use the USB Debugger, it will show you each TRB as it is being processed, before and after it being processed.

Have a look at a recent post for information on how to do this: viewtopic.php?p=352649#p352649

Ben
- https://www.fysnet.net/the_universal_serial_bus.htm
I am glad that you can give me these suggestions.
In fact, I have tried to use Bochs and usb debugger as well, but it seems that my system is stuck and don't receive any interrupt.What's more, the event ring produces two Port Status Change Event TRB, but both the Port Status Registers are 0xFFFF_FFFF.
My configure is:

Code: Select all

usb_xhci: enabled=1, model=uPD720202, n_ports=4, port1=none, options1=none, port2=none, options2=none, port3=mouse, options3="speed:low", port4=keyboard, options4="speed:low", port5=none, options5=none, port6=none, options6=none, port7=none, options7=none, port8=none, options8=none, port9=none, options9=none, port10=none, options10="==none"
usb_debug: type=xhci, reset=false, enable=true, start_frame=0, doorbell=true, data=false, event=true, non_exist=false
User avatar
BenLunt
Member
Member
Posts: 1029
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: xHCI: Got Completion Code 0x11(context parameter error) when perfroming Address Command

Post by BenLunt »

Oython wrote: Thu Aug 28, 2025 10:33 pm What's more, the event ring produces two Port Status Change Event TRB, but both the Port Status Registers are 0xFFFF_FFFF.
When this happens, I first go to the fact that you might not have enabled Mem IO in the CONFIG register of the device's PCI Config Space. However, if you were able to setup the Event Ring to see the Event TRB's, this might not be the case.

Did you check the Protocol Capabilities of the controller and with that information are you reading the correct port register set. For example, if the controller has 4 sockets, it might have 8 register sets. A normal setup will use port 0 as the first socket when a super-speed device is attached and port 4 when a high/full/low-speed device is attached. However, this is not to be relied upon. The Protocol Capabilities must be parsed to evaluate which port register set goes with which socket and which speed.

With this example setup, the controller will report 8 port register sets, 4 for the super-speed and 4 for the lower speeds. However, if any of the sockets are high-speed only (which includes full- and low-speed), the count of ports will be less since there will not be a corresponding super-speed port register set.

With Bochs, did you enable the debug out for the log file and look through this log to see what worked and then see at what point it doesn't work anymore?

For us to help you out, we need more than just a few of lines of code. Can you post the relevant part of the log file? Can you upload your disk image and bochsrc.txt file somewhere?

Ben
- https://www.fysnet.net/osdesign_book_series.htm
Oython
Posts: 15
Joined: Wed Aug 03, 2022 8:17 pm
Libera.chat IRC: no

Re: xHCI: Got Completion Code 0x11(context parameter error) when perfroming Address Command

Post by Oython »

Alright, maybe I found the solution.I just mixed the input context and the output device context by mistake.That means I set the entry of device context array to the device context address in input context, which should be alloced again.
But now, I met a new problem similar to this: viewtopic.php?t=57621.
It seems that I can just copy his solution but I found it doesn't work.
Oython
Posts: 15
Joined: Wed Aug 03, 2022 8:17 pm
Libera.chat IRC: no

Re: xHCI: Got Completion Code 0x11(context parameter error) when perfroming Address Command

Post by Oython »

BenLunt wrote: Fri Aug 29, 2025 9:06 am
Oython wrote: Thu Aug 28, 2025 10:33 pm What's more, the event ring produces two Port Status Change Event TRB, but both the Port Status Registers are 0xFFFF_FFFF.
For us to help you out, we need more than just a few of lines of code. Can you post the relevant part of the log file? Can you upload your disk image and bochsrc.txt file somewhere?
The only three lines about xHCI in the log:

Code: Select all

01057818606i[XHCI  ] Reset port #1, type=0
01057818606i[XHCI  ] Reset port #2, type=0
01057818628e[XHCI  ] Write to one or more Read-only bits in Status Register
Post Reply