OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Jul 23, 2018 9:32 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: EHCI didn't works at real PC and VirtualBox!
PostPosted: Sat Jul 07, 2018 4:11 pm 
Offline
Member
Member

Joined: Sat Sep 24, 2016 12:06 am
Posts: 28
Hi all, i'm write EHCI driver for my own OS. Sorry for my english, firstly.
On QEMU my driver successfully works, but on VirtualBox and real hardware -no.
On QEMU:
Image
On Virtual box:
Image
Frame index rolls over 1024x8 micro frames and didn't processing the all types of queues.
My initialization code here:
Code:
    // Base I/O Address
    PciBar bar;
    PciGetBar(&bar, id, 0);
    if (bar.flags & PCI_BAR_IO)
    {
        // Only Memory Mapped I/O supported
        return;
    }

    // Controller initialization
    EhciController *hc = VMAlloc(sizeof(EhciController));
    hc->capRegs = (EhciCapRegs *)bar.u.address;
    hc->opRegs = (EhciOpRegs *)(bar.u.address + hc->capRegs->capLength);
    hc->frameList = (u32 *)VMAlloc(1024 * sizeof(u32) + 8292);
   hc->frameList = ((int)hc->frameList/4096)*4096 + 4096;
    hc->qhPool = (EhciQH *)VMAlloc(sizeof(EhciQH) * MAX_QH + 8292);
   hc->qhPool =((int)hc->qhPool/4096)*4096 + 4096;
    hc->tdPool = (EhciTD *)VMAlloc(sizeof(EhciTD) * MAX_TD + 8292);
   hc->tdPool =((int)hc->tdPool/4096)*4096 + 4096;

    memset(hc->qhPool, 0, sizeof(EhciQH) * MAX_QH);
    memset(hc->tdPool, 0, sizeof(EhciTD) * MAX_TD);

    // Asynchronous queue setup
    EhciQH *qh = EhciAllocQH(hc);
    qh->qhlp = (u32)qh | PTR_QH;
    qh->ch = QH_CH_H;
    qh->caps = 0;
    qh->curLink = 0;
    qh->nextLink = PTR_TERMINATE;
    qh->altLink = 0;
    qh->token = 1<<6;
    for (uint i = 0; i < 5; ++i)
    {
        qh->buffer[i] = 0;
        qh->extBuffer[i] = 0;
    }
    qh->transfer = 0;
    qh->qhLink.prev = &qh->qhLink;
    qh->qhLink.next = &qh->qhLink;

    hc->asyncQH = qh;

    // Periodic list queue setup
    qh = EhciAllocQH(hc);
    qh->qhlp = PTR_TERMINATE;
    qh->ch = 0;
    qh->caps = 0;
    qh->curLink = 0;
    qh->nextLink = PTR_TERMINATE;
    qh->altLink = 0;
    qh->token = 1<<6;
    for (uint i = 0; i < 5; ++i)
    {
        qh->buffer[i] = 0;
        qh->extBuffer[i] = 0;
    }
    qh->transfer = 0;
    qh->qhLink.prev = &qh->qhLink;
    qh->qhLink.next = &qh->qhLink;

    hc->periodicQH = qh;
    for (uint i = 0; i < 1024; ++i)
    {
        hc->frameList[i] = 2 | (u32)qh;
    }

    // Check extended capabilities
    uint eecp = (hc->capRegs->hccParams & HCCPARAMS_EECP_MASK) >> HCCPARAMS_EECP_SHIFT;
    if (eecp >= 0x40)
    {
        // Disable BIOS legacy support
        uint legsup = PciRead32(id, eecp + USBLEGSUP);

        if (legsup & USBLEGSUP_HC_BIOS)
        {
            PciWrite32(id, eecp + USBLEGSUP, legsup | USBLEGSUP_HC_OS);
            for (;;)
            {
                legsup = PciRead32(id, eecp + USBLEGSUP);
                if (~legsup & USBLEGSUP_HC_BIOS && legsup & USBLEGSUP_HC_OS)
                {
                    break;
                }
            }
        }
    }

    // Disable interrupts
    hc->opRegs->usbIntr = 0;

    // Setup frame list
    hc->opRegs->frameIndex = 0;
    hc->opRegs->periodicListBase = (u32)hc->frameList;
    hc->opRegs->asyncListAddr = (u32)hc->asyncQH;
    hc->opRegs->ctrlDsSegment = 0;

    // Clear status
    hc->opRegs->usbSts = 0xffff;

    // Enable controller
    hc->opRegs->usbCmd = (0x8 << CMD_ITC_SHIFT) | CMD_PSE | CMD_ASE | CMD_RS;
    while (hc->opRegs->usbSts & STS_HCHALTED) // TODO - remove after dynamic port detection
        ;
kprintf("In");
    // Configure all devices to be managed by the EHCI
    hc->opRegs->configFlag = 1;
    PitWait(5);    // TODO - remove after dynamic port detection

    // Probe devices
    EhciProbe(hc);

    // Register controller
    UsbController *controller = (UsbController *)VMAlloc(sizeof(UsbController));
    controller->next = g_usbControllerList;
    controller->hc = hc;
    controller->poll = EhciControllerPoll;

    g_usbControllerList = controller;

Please, try to help me! I'm troubleshooting that about a month, and no one knows, why my driver didn't works!
With best regards,
Aleksandr


Top
 Profile  
 
 Post subject: Re: EHCI didn't works at real PC and VirtualBox!
PostPosted: Sun Jul 08, 2018 2:38 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 394
Location: USA
Hi,

Looking over your code, nothing wrong jumps out at me, though I didn't look extremely close.

However, one thing I noticed a few times is that with QEMU, compared to other emulators, all memory is initialized to zero. i.e.: any unused register or a register's initial state is zero instead of undefined. Therefore, if a 64-bit register (or memory operand) is used and only the bottom 32-bits are initialized, the implementation still works fine. However, on other emulators and real hardware, this is not the case. The upper 32 bits of the 64-bit field/register/etc is undefined and could be anything.

Make sure that all your 64-bit registers, memory pointers, etc are zero when using a 64-bit controller.

Ben
- http://www.fysnet.net/the_universal_serial_bus.htm


Top
 Profile  
 
 Post subject: Re: EHCI didn't works at real PC and VirtualBox!
PostPosted: Mon Jul 09, 2018 3:35 am 
Offline
Member
Member

Joined: Sat Sep 24, 2016 12:06 am
Posts: 28
Ben, i'm working in protected mode. i'm set some memory fragment to zero:
Code:
EhciController *hc = VMAlloc(sizeof(EhciController));//That's from last code, that are at top
    hc->capRegs = (EhciCapRegs *)bar.u.address;//That's from last code, that are at top
    hc->opRegs = (EhciOpRegs *)(bar.u.address + hc->capRegs->capLength);//That's from last code, that are at top
   memset(hc->capRegs, 0, hc->capRegs->capLength + 160);

There are in my malloc realization memset all bytes of malloced region to zero. I'm don't know what to do, or u can help with code to set all registers to zero at start? What i'm need to do?


Top
 Profile  
 
 Post subject: Re: EHCI didn't works at real PC and VirtualBox!
PostPosted: Mon Jul 09, 2018 2:29 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 394
Location: USA
I am talking about all of the 64-bit address that may pertain to the card.

1) What are the bottom four bits of the Base IO address at BAR0 (0x10)? Do they indicate that the address can be anywhere in the 64-bit address range? If so, you have to get the next BAR address as well, using it as the top 32 bits of the 64-bit address.

2) The CTRLDSSEGMENT register (Opregs + 0x10) is used for 64-bit addresses. If the card is a 64-bit capable card, you must have all addresses within a 4-gig range and use this register as the top 32 bits of all other (memory access) registers. For example, on 64-bit machines, the PeriodicListBase register (offset 0x14) will be combined with the CTRLDSSegment register to create a 64-bit address:

Code:
  Physical address =  ((CTRLDSSegment << 32) | PeriodicListBase);

Same goes for all other registers that access memory. (only one other at the moment :-))
Code:
  Physical address =  ((CTRLDSSegment << 32) | AsyncListAddr);

3) Appendix B shows the format of a 64-bit Data Structure. If you are assuming 32-bit structures and place another 32-bit structure 96 bytes after the last one, on a 64-bit card, it will take the "undefined" data from the second structure as the Extended Buffer Pointer Page[x] address members. It looks like in your code you account for the Extended Buffer entries, but do you make sure that the second one doesn't overlap the first one?

Another thing to look at. You say that the controller rolled over the frame list in QEMU but not real hardware. QEMU will have a 1024-entry frame. Real hardware may have a frame with fewer entries. Real hardware may have 1024-, 512-, 256-, and in some cases, a 128-entry frame list. Check the capabilities flag to see how many. Don't assume 1024.

Also, please explain in more detail, "it doesn't work!". What isn't working?

Ben


Top
 Profile  
 
 Post subject: Re: EHCI didn't works at real PC and VirtualBox!
PostPosted: Wed Jul 11, 2018 1:42 am 
Offline
Member
Member

Joined: Sat Sep 24, 2016 12:06 am
Posts: 28
Ben, thanks to u, but i'm sayed, that frame index rolls over 1024 frames on Virtual Box, on QEMU all working ok. "It doesn't work" - i'm sayed, that host controller didn't process the queue.


Top
 Profile  
 
 Post subject: Re: EHCI didn't works at real PC and VirtualBox!
PostPosted: Thu Jul 12, 2018 12:20 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 394
Location: USA
So you are saying that as far as you know, the controller (one real hardware) did not process the queue.

There are a few things that you can do.

1) If the Queue was actually not processed, then it will still be identical to what you created. i.e.: There will not be any status update. This means that you don't have a valid pointer to the Queue, or haven't started the Queue, or many other reasons. The point is, now you have an idea where to look.

2) If the Queue was actually processed, the status will be updated. Look at the status to see what is going on.

Start with a small list of things to check, then check each one until you find that something is wrong at that point. Process of elimination.

Do you use or know how to use Bochs? Bochs has a much better and detailed reporting mechanism. If you tell it to print all debug (BXDEBUG) strings, it will give you an idea of what is happening.

Ben
- http://www.fysnet.net/the_universal_serial_bus.htm


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: JAAman and 11 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group