* Added hash function and related data in order to find the virtual address
of the descriptor from its physical address returned by the controller. NOTE: As stated in the commented code, when the controller has finished processing some descriptors, it returns the first element physical address of an heterogeneous list (general + isochronous) and there is not way to tell the descriptor type. This solution, which implementes two hash tables (one for generic descriptors and one for isochronous) is the one adopted from *BSD. If somebody has better idea, please let me know. :) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23589 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -48,6 +48,17 @@ typedef struct hcd_soft_itransfer
|
||||
|
||||
#define OHCI_NUMBER_OF_ENDPOINTS (2 * OHCI_NUMBER_OF_INTERRUPTS - 1)
|
||||
|
||||
// Note: the controller returns only the physical
|
||||
// address of the first processed descriptor of
|
||||
// an heterogeneous list (isochronous + generic). Unfortunately
|
||||
// we don't have a way to know whether the descriptor is
|
||||
// generic or isochronous, either way to translate the address back to
|
||||
// kernel address. The physical address is used as the hash value.
|
||||
// (Kindly borrowed from *BSD)
|
||||
|
||||
#define OHCI_HASH_SIZE 128
|
||||
#define HASH(x) (((x) >> 4) % OHCI_HASH_SIZE)
|
||||
|
||||
|
||||
class OHCI : public BusManager
|
||||
{
|
||||
@@ -128,9 +139,21 @@ static int32 _FinishThread(void *data);
|
||||
iovec *vector,
|
||||
size_t vectorCount);
|
||||
|
||||
// OHCI needs this function
|
||||
addr_t _LogicalAddress(addr_t physical);
|
||||
bool _IsIsochronous(addr_t logical);
|
||||
// Hash tables related methods
|
||||
void _AddDescriptorToHash(
|
||||
ohci_general_td *descriptor);
|
||||
void _RemoveDescriptorFromHash(
|
||||
addr_t physicalAddress);
|
||||
ohci_general_td *_FindDescriptorInHash(
|
||||
addr_t physicalAddress);
|
||||
|
||||
void _AddIsoDescriptorToHash(
|
||||
ohci_isochronous_td *descriptor);
|
||||
void _RemoveIsoDescriptorFromHash(
|
||||
addr_t physicalAddress);
|
||||
ohci_isochronous_td *_FindIsoDescriptorInHash(
|
||||
addr_t physicalAddress);
|
||||
|
||||
|
||||
// Register functions
|
||||
inline void _WriteReg(uint32 reg, uint32 value);
|
||||
|
||||
@@ -335,16 +335,19 @@ typedef struct ohci_endpoint_descriptor
|
||||
|
||||
typedef struct ohci_general_td
|
||||
{
|
||||
// Hardware part
|
||||
// Hardware part 16 bytes
|
||||
uint32 flags; // Flags field
|
||||
uint32 buffer_physical; // Physical buffer pointer
|
||||
uint32 next_physical_descriptor; // Physical pointer next descriptor
|
||||
uint32 last_physical_byte_address; // Physical pointer to buffer end
|
||||
// Software part
|
||||
addr_t physical_address; // Physical pointer to this address
|
||||
addr_t physical_address; // Physical address of this descriptor
|
||||
void *buffer_logical; // Logical pointer to the buffer
|
||||
void *next_logical_descriptor; // Logical pointer next descriptor
|
||||
size_t buffer_size; // Size of the buffer
|
||||
void *endpoint; // Necessary when there is an error
|
||||
void *transfer; // Pointer to the transfer
|
||||
bool is_last; // Last descriptor of the transfer
|
||||
};
|
||||
|
||||
#define OHCI_BUFFER_ROUNDING 0x00040000
|
||||
@@ -373,11 +376,14 @@ typedef struct ohci_general_td
|
||||
#define OHCI_ITD_NOFFSET 8
|
||||
typedef struct ohci_isochronous_td
|
||||
{
|
||||
// Hardware part 32 byte
|
||||
uint32 flags;
|
||||
uint32 buffer_page_byte_0; // Physical page number of byte 0
|
||||
uint32 next_physical_descriptor; // Next isochronous transfer descriptor
|
||||
uint32 last_byte_address; // Physical buffer end
|
||||
uint16 offset[OHCI_ITD_NOFFSET]; // Buffer offsets
|
||||
// Software part
|
||||
addr_t physical_address; // Physical address of this descriptor
|
||||
};
|
||||
|
||||
#define OHCI_ITD_GET_STARTING_FRAME(x) ((x) & 0x0000ffff)
|
||||
|
||||
Reference in New Issue
Block a user