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,