Implemented endpoint creation for Pipes.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18986 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -363,6 +363,9 @@ OHCI::~OHCI()
|
||||
status_t
|
||||
OHCI::Start()
|
||||
{
|
||||
if (InitCheck())
|
||||
return B_ERROR;
|
||||
|
||||
if (!(ReadReg(OHCI_CONTROL) & OHCI_HCFS_OPERATIONAL)) {
|
||||
TRACE(("USB OHCI::Start(): Controller not started. TODO: find out what happens.\n"));
|
||||
return B_ERROR;
|
||||
@@ -397,6 +400,25 @@ status_t OHCI::SubmitTransfer( Transfer *t )
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t
|
||||
OHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
|
||||
{
|
||||
if (InitCheck())
|
||||
return B_ERROR;
|
||||
|
||||
switch (change) {
|
||||
case USB_CHANGE_CREATED:
|
||||
return InsertEndpointForPipe(pipe);
|
||||
case USB_CHANGE_DESTROYED:
|
||||
// Do something
|
||||
return B_ERROR;
|
||||
case USB_CHANGE_PIPE_POLICY_CHANGED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return B_ERROR; //We should never go here
|
||||
}
|
||||
|
||||
status_t
|
||||
OHCI::GetPortStatus(uint8 index, usb_port_status *status)
|
||||
{
|
||||
@@ -481,7 +503,8 @@ OHCI::ClearPortFeature(uint8 index, uint16 feature)
|
||||
Endpoint *
|
||||
OHCI::AllocateEndpoint()
|
||||
{
|
||||
Endpoint *endpoint = new Endpoint;
|
||||
//Allocate memory chunk
|
||||
Endpoint *endpoint = new(std::nothrow) Endpoint;
|
||||
void *phy;
|
||||
if (fStack->AllocateChunk((void **)&endpoint->ed, &phy, sizeof(ohci_endpoint_descriptor)) != B_OK) {
|
||||
TRACE(("OHCI::AllocateEndpoint(): Error Allocating Endpoint\n"));
|
||||
@@ -489,8 +512,15 @@ OHCI::AllocateEndpoint()
|
||||
}
|
||||
endpoint->physicaladdress = (addr_t)phy;
|
||||
|
||||
//Initialize the physical part
|
||||
memset((void *)endpoint->ed, 0, sizeof(ohci_endpoint_descriptor));
|
||||
endpoint->ed->ed_flags = OHCI_ED_SKIP;
|
||||
endpoint->ed->flags = OHCI_ENDPOINT_SKIP;
|
||||
|
||||
//Add a NULL list by creating one TransferDescriptor
|
||||
TransferDescriptor *trans = new(std::nothrow) TransferDescriptor;
|
||||
endpoint->head = endpoint->tail = trans;
|
||||
endpoint->ed->headp = endpoint->ed->tailp = trans->physicaladdress;
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
@@ -501,6 +531,122 @@ OHCI::FreeEndpoint(Endpoint *end)
|
||||
delete end;
|
||||
}
|
||||
|
||||
TransferDescriptor *
|
||||
OHCI::AllocateTransfer()
|
||||
{
|
||||
TransferDescriptor *transfer = new TransferDescriptor;
|
||||
void *phy;
|
||||
if (fStack->AllocateChunk((void **)&transfer->td, &phy, sizeof(ohci_transfer_descriptor)) != B_OK) {
|
||||
TRACE(("OHCI::AllocateTransfer(): Error Allocating Transfer\n"));
|
||||
return 0;
|
||||
}
|
||||
transfer->physicaladdress = (addr_t)phy;
|
||||
memset((void *)transfer->td, 0, sizeof(ohci_transfer_descriptor));
|
||||
return transfer;
|
||||
}
|
||||
|
||||
void
|
||||
OHCI::FreeTransfer(TransferDescriptor *trans)
|
||||
{
|
||||
fStack->FreeChunk((void *)trans->td, (void *) trans->physicaladdress, sizeof(ohci_transfer_descriptor));
|
||||
delete trans;
|
||||
}
|
||||
|
||||
status_t
|
||||
OHCI::InsertEndpointForPipe(Pipe *p)
|
||||
{
|
||||
TRACE(("OHCI: Inserting Endpoint for device %u function %u\n", p->DeviceAddress(), p->EndpointAddress()));
|
||||
|
||||
if (InitCheck())
|
||||
return B_ERROR;
|
||||
|
||||
Endpoint *endpoint = AllocateEndpoint();
|
||||
if (!endpoint)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
//Set up properties of the endpoint
|
||||
//TODO: does this need its own utility function?
|
||||
{
|
||||
uint32 properties = 0;
|
||||
|
||||
//Set the device address
|
||||
properties |= OHCI_ENDPOINT_SET_FA(p->DeviceAddress());
|
||||
|
||||
//Set the endpoint number
|
||||
properties |= OHCI_ENDPOINT_SET_EN(p->EndpointAddress());
|
||||
|
||||
//Set the direction
|
||||
switch (p->Direction()) {
|
||||
case Pipe::In:
|
||||
properties |= OHCI_ENDPOINT_DIR_IN;
|
||||
break;
|
||||
case Pipe::Out:
|
||||
properties |= OHCI_ENDPOINT_DIR_OUT;
|
||||
break;
|
||||
case Pipe::Default:
|
||||
properties |= OHCI_ENDPOINT_DIR_TD;
|
||||
break;
|
||||
default:
|
||||
//TODO: error
|
||||
break;
|
||||
}
|
||||
|
||||
//Set the speed
|
||||
switch (p->Speed()) {
|
||||
case USB_SPEED_LOWSPEED:
|
||||
//the bit is 0
|
||||
break;
|
||||
case USB_SPEED_FULLSPEED:
|
||||
properties |= OHCI_ENDPOINT_SPEED;
|
||||
break;
|
||||
case USB_SPEED_HIGHSPEED:
|
||||
default:
|
||||
//TODO: error
|
||||
break;
|
||||
}
|
||||
|
||||
//Assign the format. Isochronous endpoints require this switch
|
||||
if (p->Type() & USB_OBJECT_ISO_PIPE)
|
||||
properties |= OHCI_ENDPOINT_FORMAT_ISO;
|
||||
|
||||
//Set the maximum packet size
|
||||
properties |= OHCI_ENDPOINT_SET_MAXP(p->MaxPacketSize());
|
||||
|
||||
endpoint->ed->flags = properties;
|
||||
}
|
||||
|
||||
//Check which list we need to add the endpoint in
|
||||
Endpoint *listhead;
|
||||
switch (p->Type()) {
|
||||
case USB_OBJECT_CONTROL_PIPE:
|
||||
listhead = fDummyControl;
|
||||
break;
|
||||
case USB_OBJECT_BULK_PIPE:
|
||||
listhead = fDummyBulk;
|
||||
break;
|
||||
case USB_OBJECT_ISO_PIPE:
|
||||
listhead = fDummyIsochronous;
|
||||
break;
|
||||
default:
|
||||
FreeEndpoint(endpoint);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
//Add the endpoint to the queues
|
||||
if (p->Type() != USB_OBJECT_ISO_PIPE) {
|
||||
//Link the endpoint into the head of the list
|
||||
endpoint->SetNext(listhead->next);
|
||||
listhead->SetNext(endpoint);
|
||||
} else {
|
||||
//Link the endpoint into the tail of the list
|
||||
Endpoint *tail = listhead;
|
||||
while (tail->next != 0)
|
||||
tail = tail->next;
|
||||
tail->SetNext(endpoint);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
pci_module_info *OHCI::pci_module = 0;
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
struct pci_info;
|
||||
struct pci_module_info;
|
||||
class OHCIRootHub;
|
||||
class Endpoint;
|
||||
struct Endpoint;
|
||||
struct TransferDescriptor;
|
||||
|
||||
// --------------------------------
|
||||
// OHCI: The OHCI class derived
|
||||
@@ -50,6 +51,9 @@ public:
|
||||
~OHCI();
|
||||
status_t Start();
|
||||
status_t SubmitTransfer(Transfer *t); //Override from BusManager.
|
||||
status_t NotifyPipeChange(Pipe *pipe, //Override from BusManager.
|
||||
usb_change change);
|
||||
|
||||
static pci_module_info *pci_module; // Global data for the module.
|
||||
|
||||
status_t GetPortStatus(uint8 index, usb_port_status *status);
|
||||
@@ -81,7 +85,11 @@ private:
|
||||
uint8 fNumPorts; // the number of ports
|
||||
// functions
|
||||
Endpoint *AllocateEndpoint(); // allocate memory for an endpoint
|
||||
void FreeEndpoint(Endpoint *end); //Free endpoint
|
||||
void FreeEndpoint(Endpoint *end); // Free endpoint
|
||||
TransferDescriptor *AllocateTransfer(); // create a NULL transfer
|
||||
void FreeTransfer(TransferDescriptor *trans); // Free transfer
|
||||
|
||||
status_t InsertEndpointForPipe(Pipe *p);
|
||||
};
|
||||
|
||||
// --------------------------------
|
||||
@@ -106,12 +114,25 @@ struct Endpoint
|
||||
addr_t physicaladdress;//Point to the physical address
|
||||
ohci_endpoint_descriptor *ed; //Logical 'endpoint'
|
||||
Endpoint *next; //Pointer to the 'next' endpoint
|
||||
TransferDescriptor *head, *tail; //Pointers to the 'head' and 'tail' transfer descriptors
|
||||
|
||||
//Utility functions
|
||||
void SetNext(Endpoint *end) {
|
||||
next = end;
|
||||
ed->next_endpoint = end->physicaladdress;
|
||||
if (end == 0)
|
||||
ed->next_endpoint = 0;
|
||||
else
|
||||
ed->next_endpoint = end->physicaladdress;
|
||||
};
|
||||
|
||||
//Constructor (or better: initialiser)
|
||||
Endpoint() : physicaladdress(0), ed(0), next(0), head(0), tail(0) {};
|
||||
};
|
||||
|
||||
struct TransferDescriptor
|
||||
{
|
||||
addr_t physicaladdress;
|
||||
ohci_transfer_descriptor *td;
|
||||
};
|
||||
|
||||
#endif // OHCI_H
|
||||
|
||||
@@ -296,42 +296,41 @@ struct ohci_hcca
|
||||
|
||||
typedef struct ohci_endpoint_descriptor
|
||||
{
|
||||
uint32 ed_flags;
|
||||
addr_t ed_qtailp; // Queue tail pointer
|
||||
addr_t ed_qheadp; // Queue head pointer
|
||||
uint32 flags;
|
||||
addr_t tailp; // Queue tail pointer
|
||||
addr_t headp; // Queue head pointer
|
||||
addr_t next_endpoint; // Next endpoint in the list
|
||||
};
|
||||
|
||||
#define OHCI_ED_GET_FA(s) ((s) & 0x7f)
|
||||
#define OHCI_ED_ADDRMASK 0x0000007f
|
||||
#define OHCI_ED_SET_FA(s) (s)
|
||||
#define OHCI_ED_GET_EN(s) (((s) >> 7) & 0xf)
|
||||
#define OHCI_ED_SET_EN(s) ((s) << 7)
|
||||
#define OHCI_ED_DIR_MASK 0x00001800
|
||||
#define OHCI_ED_DIR_TD 0x00000000
|
||||
#define OHCI_ED_DIR_OUT 0x00000800
|
||||
#define OHCI_ED_DIR_IN 0x00001000
|
||||
#define OHCI_ED_SPEED 0x00002000
|
||||
#define OHCI_ED_SKIP 0x00004000
|
||||
#define OHCI_ED_FORMAT_GEN 0x00000000
|
||||
#define OHCI_ED_FORMAT_ISO 0x00008000
|
||||
#define OHCI_ED_GET_MAXP(s) (((s) >> 16) & 0x07ff)
|
||||
#define OHCI_ED_SET_MAXP(s) ((s) << 16)
|
||||
#define OHCI_ED_MAXPMASK (0x7ff << 16)
|
||||
#define OHCI_ENDPOINT_GET_FA(s) ((s) & 0x7f)
|
||||
#define OHCI_ENDPOINT_ADDRMASK 0x0000007f
|
||||
#define OHCI_ENDPOINT_SET_FA(s) (s)
|
||||
#define OHCI_ENDPOINT_GET_EN(s) (((s) >> 7) & 0xf)
|
||||
#define OHCI_ENDPOINT_SET_EN(s) ((s) << 7)
|
||||
#define OHCI_ENDPOINT_DIR_MASK 0x00001800
|
||||
#define OHCI_ENDPOINT_DIR_TD 0x00000000
|
||||
#define OHCI_ENDPOINT_DIR_OUT 0x00000800
|
||||
#define OHCI_ENDPOINT_DIR_IN 0x00001000
|
||||
#define OHCI_ENDPOINT_SPEED 0x00002000
|
||||
#define OHCI_ENDPOINT_SKIP 0x00004000
|
||||
#define OHCI_ENDPOINT_FORMAT_GEN 0x00000000
|
||||
#define OHCI_ENDPOINT_FORMAT_ISO 0x00008000
|
||||
#define OHCI_ENDPOINT_GET_MAXP(s) (((s) >> 16) & 0x07ff)
|
||||
#define OHCI_ENDPOINT_SET_MAXP(s) ((s) << 16)
|
||||
#define OHCI_ENDPOINT_MAXPMASK (0x7ff << 16)
|
||||
|
||||
#define OHCI_HALTED 0x00000001
|
||||
#define OHCI_TOGGLECARRY 0x00000002
|
||||
#define OHCI_HEADMASK 0xfffffffc
|
||||
|
||||
#define OHCI_ED_ALIGN 16
|
||||
|
||||
// --------------------------------
|
||||
// General transfer descriptor structure (section 4.3.1)
|
||||
// --------------------------------
|
||||
|
||||
typedef struct hc_transfer_descriptor
|
||||
typedef struct ohci_transfer_descriptor
|
||||
{
|
||||
uint32 td_flags;
|
||||
uint32 flags;
|
||||
addr_t td_cbp; // Current Buffer Pointer
|
||||
addr_t td_nexttd; // Next Transfer Descriptor
|
||||
addr_t td_be; // Buffer End
|
||||
|
||||
@@ -32,28 +32,6 @@
|
||||
#include "ohci_hardware.h"
|
||||
|
||||
|
||||
// ------------------------------------
|
||||
// OHCI:: Software general
|
||||
// transfer descriptor
|
||||
// ------------------------------------
|
||||
|
||||
typedef struct hcd_soft_transfer
|
||||
{
|
||||
hc_transfer_descriptor td;
|
||||
struct hcd_soft_transfer *nexttd; // mirrors nexttd in TD
|
||||
struct hcd_soft_trasfer *dnext; // next in done list
|
||||
addr_t physaddr; // physical address to the host controller transfer
|
||||
//LIST_ENTRY(hcd_soft_transfer) hnext;
|
||||
uint16 len; // the lenght
|
||||
uint16 flags; // flags
|
||||
}hcd_soft_transfer;
|
||||
|
||||
#define OHCI_CALL_DONE 0x0001
|
||||
#define OHCI_ADD_LEN 0x0002
|
||||
|
||||
#define OHCI_STD_SIZE ((sizeof (struct hcd_soft_transfer) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN)
|
||||
#define OHCI_STD_CHUNK 128
|
||||
|
||||
// --------------------------------------
|
||||
// OHCI:: Software isonchronous
|
||||
// transfer descriptor
|
||||
@@ -80,10 +58,5 @@ typedef struct hcd_soft_itransfer
|
||||
|
||||
#define OHCI_NO_EDS (2*OHCI_NO_INTRS-1)
|
||||
|
||||
// --------------------------
|
||||
// OHCI:: Hash size for the
|
||||
// --------------------------
|
||||
|
||||
#define OHCI_HASH_SIZE 128
|
||||
|
||||
#endif // OHCI_SOFT
|
||||
|
||||
Reference in New Issue
Block a user