OSDev.org
https://forum.osdev.org/

UHCI can find usb on emulators but not on real hardware
https://forum.osdev.org/viewtopic.php?f=1&t=33343
Page 1 of 1

Author:  SanderR [ Wed Nov 28, 2018 11:34 am ]
Post subject:  UHCI can find usb on emulators but not on real hardware

So im working on a UHCI driver. I initialised the controller and I want to see which ports are connected. On qemu and bochs this goes well. On real hardware it keeps rising interrupts and saying there is nothing in the ports. This is my code: https://github.com/AdeRegt/SanderOSUSB/ ... CI?files=1

Author:  BenLunt [ Wed Nov 28, 2018 2:00 pm ]
Post subject:  Re: UHCI can find usb on emulators but not on real hardware

I haven't had a chance to look over your code yet, but I plan on it soon.

One of the biggest things to recognize when it works on emulators, whom are horrible at absolute timing, and real hardware, which is excellent at real timing, is, well you guessed it, timing.

You must allow the hardware to actually do what it is asked to do. On an emulator, the emulation is already there. i.e.: as soon as you request the data, the data is already there waiting to be sent. On real hardware, this is not necessarily the case.

Also, the reset of the device has a lot of differences between emulators and hardware. On an emulator, it simply is the setting and clearing of the reset bit. Done. On real hardware, it is the timing between the time the reset bit is set, then cleared, as well as which other bits are set or cleared at the same time. If my memory serves, one of the bits in the Ports register *must* be cleared before or at the same time you clear the reset bit or a device will not reset.

Welcome to the art of real hardware testing. I will tell you, a hardware analyzer, such as the Beagle I got, is a wonderful piece of hardware to help with this stuff, if you can afford the expense.

When I get a chance, I will have a look at your code. In the meantime, check your reset timing and other timing code.

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

Author:  BenLunt [ Wed Nov 28, 2018 3:45 pm ]
Post subject:  Re: UHCI can find usb on emulators but not on real hardware

In your
Code:
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:
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:
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:
   outportw(BAR,(1<<1));   // set bit 1
than
Code:
   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:
void init_uhci_port(unsigned long BAR){
should be
Code:
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.:
Code:
#define UHCI_COMMAND 0x0000
etc., then use
Code:
  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

Author:  SanderR [ Wed Nov 28, 2018 5:02 pm ]
Post subject:  Re: UHCI can find usb on emulators but not on real hardware

Thank you very much for the fast answer.
I tried to add the things you have said.
I uploaded the new code to GitHub.

When I change the code to
Code:
   outportw(BAR,0b0000000000000000);
   resetTicks(); // 1 tick is on real hardware one second
   while(1){
      if(getTicks()==10){
         break;
      }
   }
   outportw(BAR,0b0000000000000100);
   while(1){
      volatile unsigned short duringreset = inportw(BAR+USBCMD);
      if((duringreset & 0b0000000000000110)==0){
         break;
      }
   }
   printstring("UHCI: reset completed!\n");

it keeps hanging in there "forever" and shows this (emulator snapshot) :
Code:
-elcome to the Sanderslando Kernel!!
Loading core components...
=> Global Description Table...
=> Interrupt Description Table...
Loading utilities...
=> Programmable Interrupt Timer...
=> PS2...
PS2: data for controller
PS2: port1 interrupt enabled
PS2: port2 clock enabled
PS2: porttranslation enabled
PS2: keyboard
PS2: keyboard enabled!
PS2: mouse disabled!
=> PCI...
PCI: detecting devices....
PCI: device detected, bridge device:  host bridge
PCI: device detected, bridge device:  ISA bridge
PCI: device detected, mass storage device:  IDE controller
PCI: device detected, serial buss controller:  USB controller, UHCI [USB 1]
UHCI: Initialising UHCI
UHCI: using I/O port c020 and irq 9
UHCI: USBCMD register before reset: 0
UHCI: USBSTS register before reset: 20


Also, must I set the runbit in order to detect the devices? since I have no commands for my queue.

Thank you.

Author:  BenLunt [ Wed Nov 28, 2018 5:18 pm ]
Post subject:  Re: UHCI can find usb on emulators but not on real hardware

SanderR wrote:
When I change the code to
Code:
   outportw(BAR,0b0000000000000000);
   resetTicks(); // 1 tick is on real hardware one second
   while(1){
      if(getTicks()==10){
         break;
      }
   }
   outportw(BAR,0b0000000000000100);
   while(1){
      volatile unsigned short duringreset = inportw(BAR+USBCMD);
      if((duringreset & 0b0000000000000110)==0){
         break;
      }
   }
   printstring("UHCI: reset completed!\n");

it keeps hanging in there "forever" and shows this (emulator snapshot) :
Because the controller will not clear bit 2 when it is done. You must clear it after 10ms. Please note that this is 10 milliseconds, not 10 seconds. Your code suggests that you are waiting one (1) second per tick. This is way too long. Also, after the reset, clearing the bit, you need to delay again for USB_TRSTRCY milliseconds. This is the recovery wait.

All of this is explained in the UHCI specification sheet. A quick search for "UHCI specs" will bring it up. (Hint, this is the first)

SanderR wrote:
Also, must I set the run bit in order to detect the devices? since I have no commands for my queue.
Thank you.
You shouldn't have to, per the specification, but I have found that if the run bit is not set, some controllers don't perform as advertised. I have seen comments to this in other code/documentation as well.

Ben

Author:  BenLunt [ Mon Dec 03, 2018 4:22 pm ]
Post subject:  Re: UHCI can find usb on emulators but not on real hardware

Just curious to see if you made any progress on this?

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

Author:  SanderR [ Mon Feb 11, 2019 4:21 pm ]
Post subject:  Re: UHCI can find usb on emulators but not on real hardware

No, I have not made any progress.
I had a small pause and then started again with hope this time it would go better.
Still, on the emulators (BOCHS and QEMU) it is working while on real hardware it is still refusing.
I am currently working on a way to make the queue work and maybe it is detected that way.
The system is booted from USB, but LEGACY says it is 0xFFFF so probably it will not change the outcome of my code.

https://github.com/AdeRegt/SanderOSUSB/tree/uhci_2 is the newest link

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/