I've been working on my operating system for a year or more.
Until now, I've been able to get pretty far with just the wiki and forum posts.
I've gotten terminal output, GDT, paging, interrupts, PS/2 keyboard and mouse support, FAT12/16 support, an AHCI driver, and program loading and usermode.
I've started working on USB support (right now I just want to get a mouse working), so I'm working on an UHCI driver since I think it's the simplest (also it's the first one mentioned in Benjamin Lunt's book). I've also read most of the UHCI spec (which is the most understandable spec I've seen from Intel).
I understand how the I/O ports work, queues, transfer descriptors, etc. I have mostly figured out how the different packets work, but I'll get there once I figure this out.
I had a working implementation of the Get Device Descriptor function and the Set Address function before, but since it was basically just merging Ben's code into my OS, I decided to scrap that code and rewrite it. However I (foolishly) did not save a copy of that code. I've rewritten it to be much easier to integrate into the system later and I'm trying to get multiple queues that run at 2^n intervals (as described in Ben's book). However, I've put that on hold for a bit because I can't seem to get what I have to work.
The first problem:
I try to get 8 bytes of the device descriptor, attempt to set the address, and then read all the bytes of the descriptor.
However, when I run my code as it is (see below for links), It succeeds in getting the descriptor the first time, "says" it succeeded with setting the address, and then fails to get the descriptor the second time (times out).
I've determined that the Set Address function fails, and therefore the Get Device Descriptor function is trying to request something from a nonexistent device (I've tested this theory by disabling the Set Address function and getting the descriptor from device address 0, which "works" (see below)).
I've dumped the I/O registers before and after each function, but they always turn up like this:
Code: Select all
USBCMD: 0x00C1
USBSTS: 0x0002
USBINTR: 0x0000
FRNUM: (varies)
FLBASEADD: 0x00833000
PORTSC1: 0x0085
PORTSC2: 0x0080 (shouldn't worry about this register since the device is on port 0 (PORTSC1)
The second problem:
If I try to get the device descriptor without setting the address, it "works." However, it doesn't seem right:
Code: Select all
Length: 18
Descriptor type: 0x01
USB Version (BCD): 0x0200
Device Class: 0x00
Device Subclass: 0x00
Device Protocol: 0x00
Max Packet Size: 8
VendorID: 0x0106
ProductID: 0x0000
Code: Select all
qemu-system-i386 -m 512M -cdrom myos.iso -s -serial stdio -usb -device usb-mouse
Code: Select all
VendorID: 0x0627
ProductID: 0x0001
It's most likely a stupid mistake like a bit not set in a TD or a virtual instead of physical address, but whatever it is I can't figure it out.
Code Links
Main UHCI code: https://github.com/foliagecanine/tritiu ... 386/uhci.c
UHCI Header: https://github.com/foliagecanine/tritiu ... usb/uhci.h
USB Header: https://github.com/foliagecanine/tritiu ... /usb/usb.h
Full repository: https://github.com/foliagecanine/tritium-os
If you want to build it, see the read-me in the repository.
How to test
Download the ISO file.
Run
Code: Select all
qemu-system-i386 -m 512M -cdrom myos.iso -s -serial stdio -usb -device usb-mouse
It will boot and then say "No valid drive found"
Press shift to get to the debug console.
Type "usb" and press enter.
Thanks ahead of time.