OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Aug 20, 2019 3:17 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: EHCI initialization issue to get control from legacy BIOS
PostPosted: Thu Apr 18, 2019 2:05 am 
Offline

Joined: Wed Feb 06, 2019 10:41 am
Posts: 17
Hi.
I am trying to initialize the EHCI controller after finding it on PCI.
The bus mastering bit is set, bar 0 had been obtained, memory mapped space (and not IO ports) is set, and extended capabilities value is getting as following:
Code:
unsigned int eecp = (hccparams >> 8) & 0xFF;

since the value of eecp in my OS is 0x68 (i.e. >= 0x40), it means the EHCI controller is under BIOS control and I need to get the control from BIOS and give it to the OS as following:
Code:

    #define LEGSUP 0x00
    #define LEGSUP_HC_BIOS 0x00010000
    #define LEGSUP_HC_OS 0x01000000

    if (eecp >= 0x40) {
        // Disable BIOS legacy support
        unsigned int leg_sup = PCI_Read(id, eecp + LEGSUP);
        if (leg_sup & LEGSUP_HC_BIOS) {
            PCI_Write(id, eecp + LEGSUP, leg_sup | LEGSUP_HC_OS);
            while(1) {
                leg_sup = PCI_Read(id, eecp + LEGSUP);
                if (~leg_sup & LEGSUP_HC_BIOS && leg_sup & LEGSUP_HC_OS)
                    break;
            }
        }
    }

The problem is that the infinite loop never breaks, meaning that the leg_sup never changed after PCI_Write.
I also chcked leg_sup right after PCI_Write call and after every PCI_Read in the while loop, but it shows no change at all.

I am wondering what might be the source of the issue. Just to be clear, the both PCI_Read and PCI_Write calls, manipulates two 32 bits data and command ports
and the id value have been constructed based on the bus, slot, and function values after pci enumerations. Besides all these pci methods work flawlessly with other hardwares attached.

Thanks.


Top
 Profile  
 
 Post subject: Re: EHCI initialization issue to get control from legacy BIO
PostPosted: Thu Apr 18, 2019 1:42 pm 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1065
Since I don't have the Order of Operations memorized, I would put in explicit parentheses and " != 0 " statements in that last if statement, just to make sure that your order of operations are correct.

EDIT: Also, that negate (~) looks wrong. I think that last line should just be:

Code:
if ((leg_sup & LEGSUP_HC_BIOS) == 0)
                    break;

_________________
Project: OZone
Source: GitHub
Current Task: DOSBox Compatibility
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott


Top
 Profile  
 
 Post subject: Re: EHCI initialization issue to get control from legacy BIO
PostPosted: Thu Apr 18, 2019 3:04 pm 
Offline
Member
Member
User avatar

Joined: Fri Feb 17, 2017 4:01 pm
Posts: 383
Location: Ukraine, Bachmut
Is it really meant to be that leg_sup should have set both LEGSUP_HC_BIOS and LEGSUP_HC_OS? Because your loop breaks only if that condition is true. ~ has priority over &. Also, you OR both flags when writing them into register. I can't say about EHCI, this is Ben Lunt, who can say for sure, but looks like you messed up the code hard. If you need to preserve the content of all other bits but LEGSUP_HC_BIOS and also set the LEGSUP_HC_OS bit, you need to do something like that:
Code:
    if (eecp >= 0x40) {
        // Disable BIOS legacy support
        unsigned int leg_sup = PCI_Read(id, eecp + LEGSUP);
        if (leg_sup & LEGSUP_HC_BIOS) {
            leg_sup =  leg_sup ^ LEGSUP_HC_BIOS | LEGSUP_HC_OS;
            PCI_Write(id, eecp + LEGSUP, leg_sup);
            while(1) {
                leg_sup = PCI_Read(id, eecp + LEGSUP);
                if (~(leg_sup & LEGSUP_HC_BIOS) && leg_sup & LEGSUP_HC_OS)
                    break;
            }
        }
    }

_________________
future big goal: ANT - NT-like OS for mips, arm and x86.
current smaller goal: efify - UEFI for a couple of boards (mips and arm).


Top
 Profile  
 
 Post subject: Re: EHCI initialization issue to get control from legacy BIO
PostPosted: Thu Apr 18, 2019 7:04 pm 
Offline
Member
Member
User avatar

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

Sorry, I haven't had much time to "play" lately, darn it. However, I do watch for specific topics such as this.

As others have suggested, parentheses are suggested.

Also, if I remember correctly, and I would have to look over my notes to be sure, you don't need to preserve the other bits. Simply write a 1 to bit 24, then wait for it to be set *and* bit 16 to be clear. I strongly suggest a timeout test too. You don't want to be stuck there forever.

Two other quick points:

1) If you have an Intel ICH5 mobo (vendor:device 0x24DD8086), there is another Legacy register you have to use. I would have to look at my notes to describe how.

2) Some mobo/controllers must have all EHCI controllers switched from BIOS to OS *before* you read anything from any other EHCI controller. i.e.: If you switch the first EHCI controller from BIOS to OS and then start to initialize it while another EHCI is still in legacy mode (BIOS owned), that second ECHI controller will never come out of Legacy mode.

During your PCI enumeration and before you start your EHCI controller drivers, make sure all EHCI controllers are out of legacy mode first.

If you still can't get it to work, post here again and I will pull out my notes and look over your stuff.

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


Top
 Profile  
 
 Post subject: Re: EHCI initialization issue to get control from legacy BIO
PostPosted: Fri Apr 19, 2019 2:38 am 
Offline

Joined: Wed Feb 06, 2019 10:41 am
Posts: 17
Dear SpyderTL, zaval, and Ben.

I looked more carefully into my code based on what you suggested.
Finally I figured out that the main issue came from my buggy PCI_Write method and I fixed it and it works now.

But I would like to reply to all your suggestions and what I found:
Quote:
EDIT: Also, that negate (~) looks wrong. I think that last line should just be:

Code:
Code:
if ((leg_sup & LEGSUP_HC_BIOS) == 0)
                    break;

It makes here more sense to me to have like what you proposed (cleaner and less ambiguous).
Quote:
Is it really meant to be that leg_sup should have set both LEGSUP_HC_BIOS and LEGSUP_HC_OS?

I think not necessarily, but I was not careful before your mentioning. Now I fixed it. I had even a look at the Standalone EHCI usb debug driver in linux EHCI implementation https://github.com/torvalds/linux/blob/master/drivers/usb/early/ehci-dbgp.c and I guess it is not needed to keep all the bits set.

Quote:
If you have an Intel ICH5 mobo (vendor:device 0x24DD8086), there is another Legacy register you have to use

I checked my hardware and could not find it.
Quote:
If you switch the first EHCI controller from BIOS to OS and then start to initialize it while another EHCI is still in legacy mode (BIOS owned), that second ECHI controller will never come out of Legacy mode

Indeed I have two EHCI controller on my PCI. In the beginning, after seeing your reply to my post and apart from caring about being mobo or not, I tried to get the BIOS control passed to the OS alternatively but both cases failed until I figured out my PCI_Write problem.

Thanks for all of your instructive comments.
Iman.


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: BaconWraith, Bing [Bot] and 6 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