In your
Code: Select all
void irq_uhci(){
...
outportb(0x20,0x20);
outportb(0xA0,0x20);
}
code, you acknowledge the Master before the Slave. This is backwards. You should acknowledge the slave first. If not, the master might try to "fire" the slave pin while the slave is still "busy".
In your
Code: Select all
void init_uhci_port(unsigned long BAR){
uhciBAR = BAR;
printstring("UHCI: initialising port at BAR ");
...
outportw(BAR,0b0000000010000100);
...
}
you say that you are initializing the port. However, you are writing to the first register of the address space, yes? This isn't where the first port is.
In
Code: Select all
void init_uhci(unsigned long BAR,unsigned char intnum){
...
outportw(BAR,0b0000000000000010);
...
}
I send the Global Reset (bit 2) instead of the HCReset (bit 1). This makes sure that all devices attached also see a reset.
Just for your information, it is much easier to read the following:
Code: Select all
outportw(BAR,(1<<1)); // set bit 1
than
Code: Select all
outportw(BAR,0b0000000000000010);
i.e.: Using "(1<<8)" is much easier to read than "0b0000000100000000". You don't have to count bits with (1<<8).
A few more notes:
- Some controllers/devices require the schedule to be running before a port reset.
- You *must* check the "HcHalted" bit after starting/stopping the schedule. Simply setting or clearing the "Run" bit does not mean it is started/stopped. The "HcHalted" bit indicates if the schedule is running or not.
- Write your port initialize code so that sending a port index value will indicate which port you are initializing. i.e:
Code: Select all
void init_uhci_port(unsigned long BAR){
should be
Code: Select all
void init_uhci_port(const phy_address BAR, const int portnum) {
All routines that manipulate a port should have an index such as this.
("phy_address" is defined/typedef as 32-bits or 64-bits depending on the machine it is compiled for. However, for PORT I/O, this isn't must of a need. For MEM-MAPPED I/O, this is a great need.)
- Use #define's for registers. i.e.:
etc., then use
Code: Select all
outportw(BAR + UHCI_COMMAND, value);
This is so much easier to read, allowing the reader (you) to know which register you are writing to. Go a little further and use #define's for each bit as well.
Hope this helps,
Ben
-
http://www.fysnet.net/osdesign_book_series.htm