* 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:
Salvatore Benedetto
2008-01-17 18:02:26 +00:00
parent 19b468ea24
commit 4cfc1fee3e
2 changed files with 34 additions and 5 deletions
+26 -3
View File
@@ -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)