Keep browsing

Blog post by emitrax on Wed, 2007-04-18 17:33

I've been reading some more code and I'm getting more confident with it.

Basically data transfer is done with memcpy.

In the ehci controller, registers are mapped every time a controller is found. This is done in the controller constructor.

As the ehci specs says:
Register Space. Implementation-specific parameters and capabilities, plus operational control and
status registers. This space, normally referred to as I/O space, must be implemented as memory-mapped
I/O space.

So...

EHCI::EHCI(pci_info *info, Stack *stack)
...
 // map the registers
 fRegisterArea = map_physical_memory("EHCI memory mapped registers",
                (void *)physicalAddress, mapSize, B_ANY_KERNEL_BLOCK_ADDRESS,
                B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA,
                (void **)&fCapabilityRegisters);
...
 fCapabilityRegisters += offset;
 fOperationalRegisters = fCapabilityRegisters + ReadCapReg8(EHCI_CAPLENGTH);
...

fCapabilityRegisters and fOperationRegisters will be used to access the registers. Capability and Operation register functions are available to make things easier. Good.

In the UHCI controllor, things are a little bit different.

The specs says:
USB Host Controller I/O Registers. This block of Control and Status registers is I/O mapped into PCI I/O
space and controls the various operations of the USB (Table 2). The Base portion of the address location is set
via a PCI configuration register.

UHCI::UHCI(pci_info *info, Stack *stack)
...
     fRegisterBase = sPCIModule->read_pci_config(fPCIInfo->bus,
                fPCIInfo->device, fPCIInfo->function, PCI_memory_base, 4);
        fRegisterBase &= PCI_address_io_mask;
....

A pci_module_info struct is used to access the registers by using fRegisterBase. Like with the ehci controller class, functions to access registers are also provided.

I guess I'll go with the uhci controller first, even though I'm still far from start coding.

Both class controllers (ehci and uhci) have a static method AddTo which is called to look for controllers. They both have very similar code

EHCI::AddTo
...
 for (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
                if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
                        && item->class_api == PCI_usb_ehci) {
...
}
...
                        EHCI *bus = new(std::nothrow) EHCI(item, stack);
...

What I haven't figure out yet is who and when is calling this methods.

host_controller_info ehci_module = {
        {
                "busses/usb/ehci",
                0,
                ehci_std_ops
        },
        NULL,
        EHCI::AddTo
};

I guess I'll find my answer in the BeBook, or perhaps some of you can save me some time?! :)

Comments

Re: Keep browsing

The USB Bus Manager does it at startup (Stack object constructor). For each usb bus controller module he could find, he load them and pass itself to the "add_to" function they should exports via their host_controller_info module interface. That the way the USB bus manager ask each host controller module if they should be added to the global USB bus topology. Or not.

Check USB Manager's Stack::Stack() code at http://svn.berlios.de/viewcvs/haiku/haiku/trunk/src/add-ons/kernel/bus_m....

UHCI and EHCI USB controllers modules don't have any "add_to" function indeed, but, as you've found, set their class's AddTo() static method in their host_controller_info module interface.
The current OHCI module exports an ohci_add_to() function. Following a similar way in all three controllers modules will be better, IMHO.

BTW, guys, calling the USB bus controller interface just "host_controller_info" could create conflict in the future, as the term "host controller" is widely used since controllers hardware interfaces are more and more standardized/cloned for each bus type. In both FireWire and AHCI field, you'll encounter the same term used to designate the bus controller, too.
Could be confusing.

May I suggest that we rename this one to make it clear that the USB host controller module interface is defined by usb_host_controller_info struct, to avoid conflict with other *_host_controller_info definitions?

----
Philippe Houdoin, occasional OpenGL & Networking team leader ;-)

no close_module_list()

I agree, we need to prevent naming conflicts.

Hmm, the constructor (Stack::Stack()) calls open_module_list(), but not close_module_list(). Looks like a memory leak.

Re: no close_module_list()

Quote:

Stack::Stack()) calls open_module_list(), but not close_module_list(). Looks like a memory leak.

Good catch!

Re: Keep browsing

Thanks to both of you.