XHCI USB: Fixes.
* Add support for hubs in AllocateDevice(). * Prevent page fault in FinishTransfers(). * Set fCapabilityLength * Correct in BIOS ownership code * Fix context errors in _InsertEndpointForPipe(). * Update constants according to latest Specification (v1.1) * Fix SMI code (reference http://lkml.iu.edu/hypermail/linux/kernel/1204.2/02460.html). * Fix Memory/Device-Slot leaks. * Fix area allocation for TRBs. * Fix for Intel Lynx Point and Panther Point chipsets. Also move init of xhci before ehci, to switch USB 2.0 ports before the ehci module discovers them. Signed-off-by: Jérôme Duval <[email protected]>
This commit is contained in:
committed by
Jérôme Duval
parent
8674959175
commit
17aa359b5d
@@ -38,7 +38,7 @@ if $(HAIKU_ATA_STACK) = 1 {
|
|||||||
|
|
||||||
AddFilesToPackage add-ons kernel busses random : virtio_rng ;
|
AddFilesToPackage add-ons kernel busses random : virtio_rng ;
|
||||||
AddFilesToPackage add-ons kernel busses scsi : ahci virtio_scsi ;
|
AddFilesToPackage add-ons kernel busses scsi : ahci virtio_scsi ;
|
||||||
AddFilesToPackage add-ons kernel busses usb : <usb>uhci <usb>ohci <usb>ehci ;
|
AddFilesToPackage add-ons kernel busses usb : <usb>uhci <usb>ohci <usb>ehci <usb>xhci ;
|
||||||
AddFilesToPackage add-ons kernel busses virtio : virtio_pci ;
|
AddFilesToPackage add-ons kernel busses virtio : virtio_pci ;
|
||||||
AddFilesToPackage add-ons kernel console : vga_text ;
|
AddFilesToPackage add-ons kernel console : vga_text ;
|
||||||
AddFilesToPackage add-ons kernel debugger
|
AddFilesToPackage add-ons kernel debugger
|
||||||
@@ -206,7 +206,7 @@ AddBootModuleSymlinksToPackage
|
|||||||
openpic@ppc
|
openpic@ppc
|
||||||
packagefs pci
|
packagefs pci
|
||||||
scsi scsi_cd scsi_disk scsi_periph silicon_image_3112
|
scsi scsi_cd scsi_disk scsi_periph silicon_image_3112
|
||||||
usb usb_disk <usb>ehci <usb>ohci <usb>uhci
|
usb usb_disk <usb>ehci <usb>ohci <usb>uhci <usb>xhci
|
||||||
virtio virtio_block virtio_pci virtio_scsi
|
virtio virtio_block virtio_pci virtio_scsi
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ typedef uint32_t in_addr_t;
|
|||||||
#define IPPROTO_NONE 59 /* 59, IPv6 no next header */
|
#define IPPROTO_NONE 59 /* 59, IPv6 no next header */
|
||||||
#define IPPROTO_DSTOPTS 60 /* 60, IPv6 destination option */
|
#define IPPROTO_DSTOPTS 60 /* 60, IPv6 destination option */
|
||||||
#define IPPROTO_ETHERIP 97 /* 97, Ethernet in IPv4 */
|
#define IPPROTO_ETHERIP 97 /* 97, Ethernet in IPv4 */
|
||||||
|
#define IPPROTO_UDPLITE 136 /* 136, UDPLite */
|
||||||
#define IPPROTO_RAW 255 /* 255 */
|
#define IPPROTO_RAW 255 /* 255 */
|
||||||
|
|
||||||
#define IPPROTO_MAX 256
|
#define IPPROTO_MAX 256
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
|
|
||||||
Hub::Hub(Object *parent, int8 hubAddress, uint8 hubPort,
|
Hub::Hub(Object *parent, int8 hubAddress, uint8 hubPort,
|
||||||
usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed,
|
usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed,
|
||||||
bool isRootHub)
|
bool isRootHub, void *controllerCookie)
|
||||||
: Device(parent, hubAddress, hubPort, desc, deviceAddress, speed,
|
: Device(parent, hubAddress, hubPort, desc, deviceAddress, speed,
|
||||||
isRootHub),
|
isRootHub, controllerCookie),
|
||||||
fInterruptPipe(NULL)
|
fInterruptPipe(NULL)
|
||||||
{
|
{
|
||||||
TRACE("creating hub\n");
|
TRACE("creating hub\n");
|
||||||
|
|||||||
@@ -60,11 +60,14 @@ Stack::Stack()
|
|||||||
// companion host controllers (per the EHCI specs) and it would therefore
|
// companion host controllers (per the EHCI specs) and it would therefore
|
||||||
// be enumerated as the last item. As this does not apply to us we have to
|
// be enumerated as the last item. As this does not apply to us we have to
|
||||||
// ensure ordering using another method.
|
// ensure ordering using another method.
|
||||||
|
// Intel Lynx Point and Panther Point chipsets have ports shared between
|
||||||
|
// EHCI and XHCI, defaulting to EHCI. The XHCI module will switch USB 2.0
|
||||||
|
// ports before the EHCI module discovers them.
|
||||||
const char *moduleNames[] = {
|
const char *moduleNames[] = {
|
||||||
|
"busses/usb/xhci",
|
||||||
"busses/usb/uhci",
|
"busses/usb/uhci",
|
||||||
"busses/usb/ohci",
|
"busses/usb/ohci",
|
||||||
"busses/usb/ehci",
|
"busses/usb/ehci",
|
||||||
"busses/usb/xhci",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -579,7 +579,8 @@ public:
|
|||||||
uint8 hubPort,
|
uint8 hubPort,
|
||||||
usb_device_descriptor &desc,
|
usb_device_descriptor &desc,
|
||||||
int8 deviceAddress,
|
int8 deviceAddress,
|
||||||
usb_speed speed, bool isRootHub);
|
usb_speed speed, bool isRootHub,
|
||||||
|
void *controllerCookie = NULL);
|
||||||
virtual ~Hub();
|
virtual ~Hub();
|
||||||
|
|
||||||
virtual status_t Changed(change_item **changeList,
|
virtual status_t Changed(change_item **changeList,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2012, Haiku Inc. All rights reserved.
|
* Copyright 2006-2014, Haiku Inc. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Some code borrowed from the Haiku EHCI driver
|
* Some code borrowed from the Haiku EHCI driver
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
* Michael Lotz <[email protected]>
|
* Michael Lotz <[email protected]>
|
||||||
* Jian Chiang <[email protected]>
|
* Jian Chiang <[email protected]>
|
||||||
* Jérôme Duval <[email protected]>
|
* Jérôme Duval <[email protected]>
|
||||||
|
* Akshay Jaggi <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -174,8 +175,9 @@ XHCI::XHCI(pci_info *info, Stack *stack)
|
|||||||
|
|
||||||
uint32 hciCapLength = ReadCapReg32(XHCI_HCI_CAPLENGTH);
|
uint32 hciCapLength = ReadCapReg32(XHCI_HCI_CAPLENGTH);
|
||||||
fCapabilityRegisters += offset;
|
fCapabilityRegisters += offset;
|
||||||
|
fCapabilityLength = HCI_CAPLENGTH(hciCapLength);
|
||||||
TRACE("mapped capability length: 0x%" B_PRIx32 "\n", fCapabilityLength);
|
TRACE("mapped capability length: 0x%" B_PRIx32 "\n", fCapabilityLength);
|
||||||
fOperationalRegisters = fCapabilityRegisters + HCI_CAPLENGTH(hciCapLength);
|
fOperationalRegisters = fCapabilityRegisters + fCapabilityLength;
|
||||||
fRuntimeRegisters = fCapabilityRegisters + ReadCapReg32(XHCI_RTSOFF);
|
fRuntimeRegisters = fCapabilityRegisters + ReadCapReg32(XHCI_RTSOFF);
|
||||||
fDoorbellRegisters = fCapabilityRegisters + ReadCapReg32(XHCI_DBOFF);
|
fDoorbellRegisters = fCapabilityRegisters + ReadCapReg32(XHCI_DBOFF);
|
||||||
TRACE("mapped capability registers: 0x%p\n", fCapabilityRegisters);
|
TRACE("mapped capability registers: 0x%p\n", fCapabilityRegisters);
|
||||||
@@ -199,8 +201,8 @@ XHCI::XHCI(pci_info *info, Stack *stack)
|
|||||||
eec = ReadCapReg32(eecp);
|
eec = ReadCapReg32(eecp);
|
||||||
if (XECP_ID(eec) != XHCI_LEGSUP_CAPID)
|
if (XECP_ID(eec) != XHCI_LEGSUP_CAPID)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
TRACE("eecp register: 0x%04" B_PRIx32 "\n", eecp);
|
TRACE("eecp register: 0x%08" B_PRIx32 "\n", eecp);
|
||||||
if (eec & XHCI_LEGSUP_BIOSOWNED) {
|
if (eec & XHCI_LEGSUP_BIOSOWNED) {
|
||||||
TRACE_ALWAYS("the host controller is bios owned, claiming"
|
TRACE_ALWAYS("the host controller is bios owned, claiming"
|
||||||
" ownership\n");
|
" ownership\n");
|
||||||
@@ -229,7 +231,39 @@ XHCI::XHCI(pci_info *info, Stack *stack)
|
|||||||
// and then freeze the system when interrupts are generated.
|
// and then freeze the system when interrupts are generated.
|
||||||
WriteCapReg32(eecp, eec & ~XHCI_LEGSUP_BIOSOWNED);
|
WriteCapReg32(eecp, eec & ~XHCI_LEGSUP_BIOSOWNED);
|
||||||
}
|
}
|
||||||
WriteCapReg32(eecp + XHCI_LEGCTLSTS, XHCI_LEGCTLSTS_DISABLE_SMI);
|
break;
|
||||||
|
}
|
||||||
|
uint32 legctlsts = ReadCapReg32(eecp + XHCI_LEGCTLSTS);
|
||||||
|
legctlsts &= XHCI_LEGCTLSTS_DISABLE_SMI;
|
||||||
|
legctlsts |= XHCI_LEGCTLSTS_EVENTS_SMI;
|
||||||
|
WriteCapReg32(eecp + XHCI_LEGCTLSTS, legctlsts);
|
||||||
|
|
||||||
|
// On Intel's Panther Point and Lynx Point Chipset taking ownership
|
||||||
|
// of EHCI owned ports, is what we do here.
|
||||||
|
if (fPCIInfo->vendor_id == PCI_VENDOR_INTEL
|
||||||
|
&& (fPCIInfo->device_id == PCI_DEVICE_INTEL_PANTHER_POINT_XHCI
|
||||||
|
|| fPCIInfo->device_id == PCI_DEVICE_INTEL_LYNX_POINT_XHCI
|
||||||
|
|| fPCIInfo->device_id == PCI_DEVICE_INTEL_LYNX_POINT_LP_XHCI)) {
|
||||||
|
|
||||||
|
TRACE("Intel xHC Controller\n");
|
||||||
|
TRACE("Looking for EHCI owned ports\n");
|
||||||
|
uint32 ports = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||||
|
fPCIInfo->device, fPCIInfo->function, XHCI_INTEL_USB3PRM, 4);
|
||||||
|
TRACE("Superspeed Ports: 0x%" B_PRIx32 "\n", ports);
|
||||||
|
sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
|
||||||
|
fPCIInfo->function, XHCI_INTEL_USB3_PSSEN, 4, ports);
|
||||||
|
ports = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||||
|
fPCIInfo->device, fPCIInfo->function, XHCI_INTEL_USB3_PSSEN, 4);
|
||||||
|
TRACE("Superspeed ports now under XHCI : 0x%" B_PRIx32 "\n", ports);
|
||||||
|
ports = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||||
|
fPCIInfo->device, fPCIInfo->function, XHCI_INTEL_USB2PRM, 4);
|
||||||
|
TRACE("USB 2.0 Ports : 0x%" B_PRIx32 "\n", ports);
|
||||||
|
sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
|
||||||
|
fPCIInfo->function, XHCI_INTEL_XUSB2PR, 4, ports);
|
||||||
|
ports = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||||
|
fPCIInfo->device, fPCIInfo->function, XHCI_INTEL_XUSB2PR, 4);
|
||||||
|
TRACE("USB 2.0 ports now under XHCI: 0x%" B_PRIx32 "\n", ports);
|
||||||
|
}
|
||||||
|
|
||||||
// halt the host controller
|
// halt the host controller
|
||||||
if (ControllerHalt() < B_OK) {
|
if (ControllerHalt() < B_OK) {
|
||||||
@@ -338,7 +372,6 @@ XHCI::Start()
|
|||||||
|
|
||||||
// read port count from capability register
|
// read port count from capability register
|
||||||
uint32 capabilities = ReadCapReg32(XHCI_HCSPARAMS1);
|
uint32 capabilities = ReadCapReg32(XHCI_HCSPARAMS1);
|
||||||
|
|
||||||
fPortCount = HCS_MAX_PORTS(capabilities);
|
fPortCount = HCS_MAX_PORTS(capabilities);
|
||||||
if (fPortCount == 0) {
|
if (fPortCount == 0) {
|
||||||
TRACE_ERROR("Invalid number of ports: %u\n", fPortCount);
|
TRACE_ERROR("Invalid number of ports: %u\n", fPortCount);
|
||||||
@@ -573,15 +606,25 @@ XHCI::SubmitControlRequest(Transfer *transfer)
|
|||||||
|
|
||||||
xhci_endpoint *endpoint = (xhci_endpoint *)pipe->ControllerCookie();
|
xhci_endpoint *endpoint = (xhci_endpoint *)pipe->ControllerCookie();
|
||||||
uint8 id = XHCI_ENDPOINT_ID(pipe);
|
uint8 id = XHCI_ENDPOINT_ID(pipe);
|
||||||
if (id >= XHCI_MAX_ENDPOINTS)
|
if (id >= XHCI_MAX_ENDPOINTS) {
|
||||||
|
TRACE_ERROR("Invalid Endpoint");
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
setupDescriptor->transfer = transfer;
|
setupDescriptor->transfer = transfer;
|
||||||
|
transfer->InitKernelAccess();
|
||||||
_LinkDescriptorForPipe(setupDescriptor, endpoint);
|
_LinkDescriptorForPipe(setupDescriptor, endpoint);
|
||||||
|
|
||||||
TRACE("SubmitControlRequest() request linked\n");
|
TRACE("SubmitControlRequest() request linked\n");
|
||||||
|
|
||||||
|
TRACE("Endpoint status 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx64 "\n",
|
||||||
|
endpoint->device->device_ctx->endpoints[id-1].dwendpoint0,
|
||||||
|
endpoint->device->device_ctx->endpoints[id-1].dwendpoint1,
|
||||||
|
endpoint->device->device_ctx->endpoints[id-1].qwendpoint2);
|
||||||
Ring(endpoint->device->slot, id);
|
Ring(endpoint->device->slot, id);
|
||||||
|
TRACE("Endpoint status 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx64 "\n",
|
||||||
|
endpoint->device->device_ctx->endpoints[id-1].dwendpoint0,
|
||||||
|
endpoint->device->device_ctx->endpoints[id-1].dwendpoint1,
|
||||||
|
endpoint->device->device_ctx->endpoints[id-1].qwendpoint2);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,11 +668,20 @@ XHCI::SubmitNormalRequest(Transfer *transfer)
|
|||||||
|
|
||||||
xhci_endpoint *endpoint = (xhci_endpoint *)pipe->ControllerCookie();
|
xhci_endpoint *endpoint = (xhci_endpoint *)pipe->ControllerCookie();
|
||||||
descriptor->transfer = transfer;
|
descriptor->transfer = transfer;
|
||||||
|
transfer->InitKernelAccess();
|
||||||
_LinkDescriptorForPipe(descriptor, endpoint);
|
_LinkDescriptorForPipe(descriptor, endpoint);
|
||||||
|
|
||||||
TRACE("SubmitNormalRequest() request linked\n");
|
TRACE("SubmitNormalRequest() request linked\n");
|
||||||
|
|
||||||
|
TRACE("Endpoint status 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx64 "\n",
|
||||||
|
endpoint->device->device_ctx->endpoints[id - 1].dwendpoint0,
|
||||||
|
endpoint->device->device_ctx->endpoints[id - 1].dwendpoint1,
|
||||||
|
endpoint->device->device_ctx->endpoints[id - 1].qwendpoint2);
|
||||||
Ring(endpoint->device->slot, id);
|
Ring(endpoint->device->slot, id);
|
||||||
|
TRACE("Endpoint status 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx64 "\n",
|
||||||
|
endpoint->device->device_ctx->endpoints[id - 1].dwendpoint0,
|
||||||
|
endpoint->device->device_ctx->endpoints[id - 1].dwendpoint1,
|
||||||
|
endpoint->device->device_ctx->endpoints[id - 1].qwendpoint2);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -994,6 +1046,7 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
|||||||
"XHCI input context");
|
"XHCI input context");
|
||||||
if (device->input_ctx_area < B_OK) {
|
if (device->input_ctx_area < B_OK) {
|
||||||
TRACE_ERROR("unable to create a input context area\n");
|
TRACE_ERROR("unable to create a input context area\n");
|
||||||
|
device->state = XHCI_STATE_DISABLED;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1003,7 +1056,7 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
|||||||
|
|
||||||
uint32 route = 0;
|
uint32 route = 0;
|
||||||
uint8 routePort = hubPort;
|
uint8 routePort = hubPort;
|
||||||
uint8 rhPort = 0;
|
uint8 rhPort = hubPort;
|
||||||
for (Device *hubDevice = parent; hubDevice != RootObject();
|
for (Device *hubDevice = parent; hubDevice != RootObject();
|
||||||
hubDevice = (Device *)hubDevice->Parent()) {
|
hubDevice = (Device *)hubDevice->Parent()) {
|
||||||
|
|
||||||
@@ -1020,8 +1073,6 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
|||||||
}
|
}
|
||||||
|
|
||||||
device->input_ctx->slot.dwslot0 = SLOT_0_NUM_ENTRIES(1) | SLOT_0_ROUTE(route);
|
device->input_ctx->slot.dwslot0 = SLOT_0_NUM_ENTRIES(1) | SLOT_0_ROUTE(route);
|
||||||
//device->input_ctx->slot.dwslot0 =
|
|
||||||
// SLOT_0_NUM_ENTRIES(XHCI_MAX_ENDPOINTS - 1) | SLOT_0_ROUTE(route);
|
|
||||||
|
|
||||||
// add the speed
|
// add the speed
|
||||||
switch (speed) {
|
switch (speed) {
|
||||||
@@ -1059,15 +1110,18 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
|||||||
"XHCI device context");
|
"XHCI device context");
|
||||||
if (device->device_ctx_area < B_OK) {
|
if (device->device_ctx_area < B_OK) {
|
||||||
TRACE_ERROR("unable to create a device context area\n");
|
TRACE_ERROR("unable to create a device context area\n");
|
||||||
|
device->state = XHCI_STATE_DISABLED;
|
||||||
delete_area(device->input_ctx_area);
|
delete_area(device->input_ctx_area);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(device->device_ctx, 0, sizeof(*device->device_ctx));
|
memset(device->device_ctx, 0, sizeof(*device->device_ctx));
|
||||||
|
|
||||||
device->trb_area = fStack->AllocateArea((void **)&device->trbs,
|
device->trb_area = fStack->AllocateArea((void **)&device->trbs,
|
||||||
&device->trb_addr, sizeof(*device->trbs), "XHCI endpoint trbs");
|
&device->trb_addr, sizeof(*device->trbs) * (XHCI_MAX_ENDPOINTS - 1)
|
||||||
|
* XHCI_MAX_TRANSFERS, "XHCI endpoint trbs");
|
||||||
if (device->trb_area < B_OK) {
|
if (device->trb_area < B_OK) {
|
||||||
TRACE_ERROR("unable to create a device trbs area\n");
|
TRACE_ERROR("unable to create a device trbs area\n");
|
||||||
|
device->state = XHCI_STATE_DISABLED;
|
||||||
delete_area(device->input_ctx_area);
|
delete_area(device->input_ctx_area);
|
||||||
delete_area(device->device_ctx_area);
|
delete_area(device->device_ctx_area);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1102,6 +1156,10 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
|||||||
if (ConfigureEndpoint(slot, 0, 4, device->trb_addr, 0, 1, 1, 0,
|
if (ConfigureEndpoint(slot, 0, 4, device->trb_addr, 0, 1, 1, 0,
|
||||||
maxPacketSize, maxPacketSize, speed) != B_OK) {
|
maxPacketSize, maxPacketSize, speed) != B_OK) {
|
||||||
TRACE_ERROR("unable to configure default control endpoint\n");
|
TRACE_ERROR("unable to configure default control endpoint\n");
|
||||||
|
device->state = XHCI_STATE_DISABLED;
|
||||||
|
delete_area(device->input_ctx_area);
|
||||||
|
delete_area(device->device_ctx_area);
|
||||||
|
delete_area(device->trb_area);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1116,6 +1174,10 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
|||||||
// device should get to addressed state (bsr = 0)
|
// device should get to addressed state (bsr = 0)
|
||||||
if (SetAddress(device->input_ctx_addr, false, slot) != B_OK) {
|
if (SetAddress(device->input_ctx_addr, false, slot) != B_OK) {
|
||||||
TRACE_ERROR("unable to set address\n");
|
TRACE_ERROR("unable to set address\n");
|
||||||
|
device->state = XHCI_STATE_DISABLED;
|
||||||
|
delete_area(device->input_ctx_area);
|
||||||
|
delete_area(device->device_ctx_area);
|
||||||
|
delete_area(device->trb_area);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1154,6 +1216,10 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
|||||||
|
|
||||||
if (actualLength != 8) {
|
if (actualLength != 8) {
|
||||||
TRACE_ERROR("error while getting the device descriptor\n");
|
TRACE_ERROR("error while getting the device descriptor\n");
|
||||||
|
device->state = XHCI_STATE_DISABLED;
|
||||||
|
delete_area(device->input_ctx_area);
|
||||||
|
delete_area(device->device_ctx_area);
|
||||||
|
delete_area(device->trb_area);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1161,11 +1227,51 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
|||||||
deviceDescriptor.device_class, deviceDescriptor.device_subclass,
|
deviceDescriptor.device_class, deviceDescriptor.device_subclass,
|
||||||
deviceDescriptor.device_protocol);
|
deviceDescriptor.device_protocol);
|
||||||
|
|
||||||
TRACE("creating new device\n");
|
Device *deviceObject = NULL;
|
||||||
Device *deviceObject = new(std::nothrow) Device(parent, hubAddress, hubPort,
|
if (deviceDescriptor.device_class == 0x09) {
|
||||||
|
TRACE("creating new Hub\n");
|
||||||
|
TRACE("getting the hub descriptor\n");
|
||||||
|
size_t actualLength = 0;
|
||||||
|
usb_hub_descriptor hubDescriptor;
|
||||||
|
pipe.SendRequest(
|
||||||
|
USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type
|
||||||
|
USB_REQUEST_GET_DESCRIPTOR, // request
|
||||||
|
USB_DESCRIPTOR_HUB << 8, // value
|
||||||
|
0, // index
|
||||||
|
sizeof(usb_hub_descriptor), // length
|
||||||
|
(void *)&hubDescriptor, // buffer
|
||||||
|
sizeof(usb_hub_descriptor), // buffer length
|
||||||
|
&actualLength);
|
||||||
|
|
||||||
|
if (actualLength != sizeof(usb_hub_descriptor)) {
|
||||||
|
TRACE_ERROR("error while getting the hub descriptor\n");
|
||||||
|
device->state = XHCI_STATE_DISABLED;
|
||||||
|
delete_area(device->input_ctx_area);
|
||||||
|
delete_area(device->device_ctx_area);
|
||||||
|
delete_area(device->trb_area);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
device->input_ctx->slot.dwslot0 |= SLOT_0_HUB_BIT;
|
||||||
|
device->input_ctx->slot.dwslot1 |= SLOT_1_NUM_PORTS(hubDescriptor.num_ports);
|
||||||
|
if (speed == USB_SPEED_HIGHSPEED) {
|
||||||
|
device->input_ctx->slot.dwslot2 |=
|
||||||
|
SLOT_2_TT_TIME(HUB_TTT_GET(hubDescriptor.characteristics));
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceObject = new(std::nothrow) Hub(parent, hubAddress, hubPort,
|
||||||
deviceDescriptor, device->address + 1, speed, false, device);
|
deviceDescriptor, device->address + 1, speed, false, device);
|
||||||
if (!deviceObject) {
|
} else {
|
||||||
|
TRACE("creating new device\n");
|
||||||
|
deviceObject = new(std::nothrow) Device(parent, hubAddress, hubPort,
|
||||||
|
deviceDescriptor, device->address + 1, speed, false, device);
|
||||||
|
}
|
||||||
|
if (deviceObject == NULL) {
|
||||||
TRACE_ERROR("no memory to allocate device\n");
|
TRACE_ERROR("no memory to allocate device\n");
|
||||||
|
device->state = XHCI_STATE_DISABLED;
|
||||||
|
delete_area(device->input_ctx_area);
|
||||||
|
delete_area(device->device_ctx_area);
|
||||||
|
delete_area(device->trb_area);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
fPortSlots[hubPort] = slot;
|
fPortSlots[hubPort] = slot;
|
||||||
@@ -1193,6 +1299,8 @@ XHCI::FreeDevice(Device *device)
|
|||||||
status_t
|
status_t
|
||||||
XHCI::_InsertEndpointForPipe(Pipe *pipe)
|
XHCI::_InsertEndpointForPipe(Pipe *pipe)
|
||||||
{
|
{
|
||||||
|
TRACE("_InsertEndpointForPipe endpoint address %" B_PRId8 "\n",
|
||||||
|
pipe->EndpointAddress());
|
||||||
if (pipe->ControllerCookie() != NULL
|
if (pipe->ControllerCookie() != NULL
|
||||||
|| pipe->Parent()->Type() != USB_OBJECT_DEVICE) {
|
|| pipe->Parent()->Type() != USB_OBJECT_DEVICE) {
|
||||||
// default pipe is already referenced
|
// default pipe is already referenced
|
||||||
@@ -1303,8 +1411,10 @@ XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
|
|||||||
{
|
{
|
||||||
TRACE("_LinkDescriptorForPipe\n");
|
TRACE("_LinkDescriptorForPipe\n");
|
||||||
MutexLocker endpointLocker(endpoint->lock);
|
MutexLocker endpointLocker(endpoint->lock);
|
||||||
if (endpoint->used >= XHCI_MAX_TRANSFERS)
|
if (endpoint->used >= XHCI_MAX_TRANSFERS) {
|
||||||
|
TRACE_ERROR("_LinkDescriptorForPipe max transfers count exceeded\n");
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
endpoint->used++;
|
endpoint->used++;
|
||||||
if (endpoint->td_head == NULL)
|
if (endpoint->td_head == NULL)
|
||||||
@@ -1468,7 +1578,7 @@ XHCI::GetPortStatus(uint8 index, usb_port_status *status)
|
|||||||
|
|
||||||
status->status = status->change = 0;
|
status->status = status->change = 0;
|
||||||
uint32 portStatus = ReadOpReg(XHCI_PORTSC(index));
|
uint32 portStatus = ReadOpReg(XHCI_PORTSC(index));
|
||||||
//TRACE("port status=0x%08lx\n", portStatus);
|
TRACE("port %" B_PRId8 " status=0x%08" B_PRIx32 "\n", index, portStatus);
|
||||||
|
|
||||||
// build the status
|
// build the status
|
||||||
switch (PS_SPEED_GET(portStatus)) {
|
switch (PS_SPEED_GET(portStatus)) {
|
||||||
@@ -1767,8 +1877,8 @@ XHCI::HandleTransferComplete(xhci_trb *trb)
|
|||||||
{
|
{
|
||||||
TRACE("HandleTransferComplete trb %p\n", trb);
|
TRACE("HandleTransferComplete trb %p\n", trb);
|
||||||
addr_t source = trb->qwtrb0;
|
addr_t source = trb->qwtrb0;
|
||||||
//uint8 completionCode = TRB_2_COMP_CODE_GET(trb->dwtrb2);
|
uint8 completionCode = TRB_2_COMP_CODE_GET(trb->dwtrb2);
|
||||||
//uint32 remainder = TRB_2_REM_GET(trb->dwtrb2);
|
uint32 remainder = TRB_2_REM_GET(trb->dwtrb2);
|
||||||
uint8 endpointNumber = TRB_3_ENDPOINT_GET(trb->dwtrb3);
|
uint8 endpointNumber = TRB_3_ENDPOINT_GET(trb->dwtrb3);
|
||||||
uint8 slot = TRB_3_SLOT_GET(trb->dwtrb3);
|
uint8 slot = TRB_3_SLOT_GET(trb->dwtrb3);
|
||||||
|
|
||||||
@@ -1785,7 +1895,8 @@ XHCI::HandleTransferComplete(xhci_trb *trb)
|
|||||||
offset);
|
offset);
|
||||||
(void)offset;
|
(void)offset;
|
||||||
_UnlinkDescriptorForPipe(td, endpoint);
|
_UnlinkDescriptorForPipe(td, endpoint);
|
||||||
|
td->trb_completion_code = completionCode;
|
||||||
|
td->trb_left = remainder;
|
||||||
// add descriptor to finished list (to be processed and freed)
|
// add descriptor to finished list (to be processed and freed)
|
||||||
Lock();
|
Lock();
|
||||||
td->next = fFinishedHead;
|
td->next = fFinishedHead;
|
||||||
@@ -1838,6 +1949,7 @@ XHCI::DoCommand(xhci_trb *trb)
|
|||||||
status_t
|
status_t
|
||||||
XHCI::Noop()
|
XHCI::Noop()
|
||||||
{
|
{
|
||||||
|
TRACE("Noop\n");
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.qwtrb0 = 0;
|
trb.qwtrb0 = 0;
|
||||||
trb.dwtrb2 = 0;
|
trb.dwtrb2 = 0;
|
||||||
@@ -1850,6 +1962,7 @@ XHCI::Noop()
|
|||||||
status_t
|
status_t
|
||||||
XHCI::EnableSlot(uint8 *slot)
|
XHCI::EnableSlot(uint8 *slot)
|
||||||
{
|
{
|
||||||
|
TRACE("Enable Slot\n");
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.qwtrb0 = 0;
|
trb.qwtrb0 = 0;
|
||||||
trb.dwtrb2 = 0;
|
trb.dwtrb2 = 0;
|
||||||
@@ -1867,6 +1980,7 @@ XHCI::EnableSlot(uint8 *slot)
|
|||||||
status_t
|
status_t
|
||||||
XHCI::DisableSlot(uint8 slot)
|
XHCI::DisableSlot(uint8 slot)
|
||||||
{
|
{
|
||||||
|
TRACE("Disable Slot\n");
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.qwtrb0 = 0;
|
trb.qwtrb0 = 0;
|
||||||
trb.dwtrb2 = 0;
|
trb.dwtrb2 = 0;
|
||||||
@@ -1879,6 +1993,7 @@ XHCI::DisableSlot(uint8 slot)
|
|||||||
status_t
|
status_t
|
||||||
XHCI::SetAddress(uint64 inputContext, bool bsr, uint8 slot)
|
XHCI::SetAddress(uint64 inputContext, bool bsr, uint8 slot)
|
||||||
{
|
{
|
||||||
|
TRACE("Set Address\n");
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.qwtrb0 = inputContext;
|
trb.qwtrb0 = inputContext;
|
||||||
trb.dwtrb2 = 0;
|
trb.dwtrb2 = 0;
|
||||||
@@ -1894,6 +2009,7 @@ XHCI::SetAddress(uint64 inputContext, bool bsr, uint8 slot)
|
|||||||
status_t
|
status_t
|
||||||
XHCI::ConfigureEndpoint(uint64 inputContext, bool deconfigure, uint8 slot)
|
XHCI::ConfigureEndpoint(uint64 inputContext, bool deconfigure, uint8 slot)
|
||||||
{
|
{
|
||||||
|
TRACE("Configure Endpoint\n");
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.qwtrb0 = inputContext;
|
trb.qwtrb0 = inputContext;
|
||||||
trb.dwtrb2 = 0;
|
trb.dwtrb2 = 0;
|
||||||
@@ -1909,6 +2025,7 @@ XHCI::ConfigureEndpoint(uint64 inputContext, bool deconfigure, uint8 slot)
|
|||||||
status_t
|
status_t
|
||||||
XHCI::EvaluateContext(uint64 inputContext, uint8 slot)
|
XHCI::EvaluateContext(uint64 inputContext, uint8 slot)
|
||||||
{
|
{
|
||||||
|
TRACE("Evaluate Context\n");
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.qwtrb0 = inputContext;
|
trb.qwtrb0 = inputContext;
|
||||||
trb.dwtrb2 = 0;
|
trb.dwtrb2 = 0;
|
||||||
@@ -1921,6 +2038,7 @@ XHCI::EvaluateContext(uint64 inputContext, uint8 slot)
|
|||||||
status_t
|
status_t
|
||||||
XHCI::ResetEndpoint(bool preserve, uint8 endpoint, uint8 slot)
|
XHCI::ResetEndpoint(bool preserve, uint8 endpoint, uint8 slot)
|
||||||
{
|
{
|
||||||
|
TRACE("Reset Endpoint\n");
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.qwtrb0 = 0;
|
trb.qwtrb0 = 0;
|
||||||
trb.dwtrb2 = 0;
|
trb.dwtrb2 = 0;
|
||||||
@@ -1936,6 +2054,7 @@ XHCI::ResetEndpoint(bool preserve, uint8 endpoint, uint8 slot)
|
|||||||
status_t
|
status_t
|
||||||
XHCI::StopEndpoint(bool suspend, uint8 endpoint, uint8 slot)
|
XHCI::StopEndpoint(bool suspend, uint8 endpoint, uint8 slot)
|
||||||
{
|
{
|
||||||
|
TRACE("Stop Endpoint\n");
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.qwtrb0 = 0;
|
trb.qwtrb0 = 0;
|
||||||
trb.dwtrb2 = 0;
|
trb.dwtrb2 = 0;
|
||||||
@@ -1951,6 +2070,7 @@ XHCI::StopEndpoint(bool suspend, uint8 endpoint, uint8 slot)
|
|||||||
status_t
|
status_t
|
||||||
XHCI::SetTRDequeue(uint64 dequeue, uint16 stream, uint8 endpoint, uint8 slot)
|
XHCI::SetTRDequeue(uint64 dequeue, uint16 stream, uint8 endpoint, uint8 slot)
|
||||||
{
|
{
|
||||||
|
TRACE("Set TR Dequeue\n");
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.qwtrb0 = dequeue;
|
trb.qwtrb0 = dequeue;
|
||||||
trb.dwtrb2 = TRB_2_STREAM(stream);
|
trb.dwtrb2 = TRB_2_STREAM(stream);
|
||||||
@@ -1964,6 +2084,7 @@ XHCI::SetTRDequeue(uint64 dequeue, uint16 stream, uint8 endpoint, uint8 slot)
|
|||||||
status_t
|
status_t
|
||||||
XHCI::ResetDevice(uint8 slot)
|
XHCI::ResetDevice(uint8 slot)
|
||||||
{
|
{
|
||||||
|
TRACE("Reset Device\n");
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.qwtrb0 = 0;
|
trb.qwtrb0 = 0;
|
||||||
trb.dwtrb2 = 0;
|
trb.dwtrb2 = 0;
|
||||||
@@ -2000,6 +2121,9 @@ XHCI::CompleteEvents()
|
|||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
uint32 temp = fEventRing[i].dwtrb3;
|
uint32 temp = fEventRing[i].dwtrb3;
|
||||||
|
TRACE_ALWAYS("event[%u] = %u (0x%016" B_PRIx64 " 0x%08" B_PRIx32 " 0x%08"
|
||||||
|
B_PRIx32 ")\n", i, (uint8)TRB_3_TYPE_GET(temp), fEventRing[i].qwtrb0,
|
||||||
|
fEventRing[i].dwtrb2, fEventRing[i].dwtrb3);
|
||||||
uint8 k = (temp & TRB_3_CYCLE_BIT) ? 1 : 0;
|
uint8 k = (temp & TRB_3_CYCLE_BIT) ? 1 : 0;
|
||||||
if (j != k)
|
if (j != k)
|
||||||
break;
|
break;
|
||||||
@@ -2073,28 +2197,61 @@ XHCI::FinishTransfers()
|
|||||||
td->next = NULL;
|
td->next = NULL;
|
||||||
Unlock();
|
Unlock();
|
||||||
|
|
||||||
|
TRACE("finishing transfer td %p\n", td);
|
||||||
|
|
||||||
Transfer* transfer = td->transfer;
|
Transfer* transfer = td->transfer;
|
||||||
bool directionIn = (transfer->TransferPipe()->Direction() != Pipe::Out);
|
bool directionIn = (transfer->TransferPipe()->Direction() != Pipe::Out);
|
||||||
usb_request_data *requestData = transfer->RequestData();
|
usb_request_data *requestData = transfer->RequestData();
|
||||||
|
|
||||||
// TODO check event
|
|
||||||
status_t callbackStatus = B_OK;
|
status_t callbackStatus = B_OK;
|
||||||
size_t actualLength = requestData ? requestData->Length
|
switch (td->trb_completion_code) {
|
||||||
|
case COMP_SHORT_PACKET:
|
||||||
|
case COMP_SUCCESS:
|
||||||
|
callbackStatus = B_OK;
|
||||||
|
break;
|
||||||
|
case COMP_DATA_BUFFER:
|
||||||
|
callbackStatus = directionIn ? B_DEV_DATA_OVERRUN
|
||||||
|
: B_DEV_DATA_UNDERRUN;
|
||||||
|
break;
|
||||||
|
case COMP_BABBLE:
|
||||||
|
callbackStatus = directionIn ? B_DEV_FIFO_OVERRUN
|
||||||
|
: B_DEV_FIFO_UNDERRUN;
|
||||||
|
break;
|
||||||
|
case COMP_USB_TRANSACTION:
|
||||||
|
callbackStatus = B_DEV_CRC_ERROR;
|
||||||
|
break;
|
||||||
|
case COMP_STALL:
|
||||||
|
callbackStatus = B_DEV_STALLED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
callbackStatus = B_DEV_STALLED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t actualLength = 0;
|
||||||
|
if (callbackStatus == B_OK) {
|
||||||
|
actualLength = requestData ? requestData->Length
|
||||||
: transfer->DataLength();
|
: transfer->DataLength();
|
||||||
TRACE("finishing transfer td %p\n", td);
|
|
||||||
|
if (td->trb_completion_code == COMP_SHORT_PACKET)
|
||||||
|
actualLength -= td->trb_left;
|
||||||
|
|
||||||
if (directionIn && actualLength > 0) {
|
if (directionIn && actualLength > 0) {
|
||||||
if (requestData) {
|
if (requestData) {
|
||||||
TRACE("copying in data %d bytes\n", requestData->Length);
|
TRACE("copying in data %d bytes\n", requestData->Length);
|
||||||
|
transfer->PrepareKernelAccess();
|
||||||
memcpy((uint8 *)transfer->Vector()[0].iov_base,
|
memcpy((uint8 *)transfer->Vector()[0].iov_base,
|
||||||
td->buffer_log[0], requestData->Length);
|
td->buffer_log[0], requestData->Length);
|
||||||
} else {
|
} else {
|
||||||
TRACE("copying in iov count %ld\n", transfer->VectorCount());
|
TRACE("copying in iov count %ld\n", transfer->VectorCount());
|
||||||
|
transfer->PrepareKernelAccess();
|
||||||
ReadDescriptorChain(td, transfer->Vector(),
|
ReadDescriptorChain(td, transfer->Vector(),
|
||||||
transfer->VectorCount());
|
transfer->VectorCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
transfer->Finished(callbackStatus, actualLength);
|
transfer->Finished(callbackStatus, actualLength);
|
||||||
|
delete transfer;
|
||||||
FreeDescriptor(td);
|
FreeDescriptor(td);
|
||||||
Lock();
|
Lock();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ typedef struct xhci_td {
|
|||||||
struct xhci_td *next;
|
struct xhci_td *next;
|
||||||
Transfer *transfer;
|
Transfer *transfer;
|
||||||
uint8 trb_count;
|
uint8 trb_count;
|
||||||
|
uint8 trb_completion_code;
|
||||||
|
uint32 trb_left;
|
||||||
} xhci_td __attribute__((__aligned__(16)));
|
} xhci_td __attribute__((__aligned__(16)));
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,22 @@
|
|||||||
* Authors:
|
* Authors:
|
||||||
* Jian Chiang <j.jian.chiang@gmail.com>
|
* Jian Chiang <j.jian.chiang@gmail.com>
|
||||||
* Jérôme Duval <jerome.duval@gmail.com>
|
* Jérôme Duval <jerome.duval@gmail.com>
|
||||||
|
* Akshay Jaggi <akshay1994.leo@gmail.com>
|
||||||
*/
|
*/
|
||||||
#ifndef XHCI_HARDWARE_H
|
#ifndef XHCI_HARDWARE_H
|
||||||
#define XHCI_HARDWARE_H
|
#define XHCI_HARDWARE_H
|
||||||
|
|
||||||
|
// PCI IDs
|
||||||
|
#define PCI_VENDOR_INTEL 0x8086
|
||||||
|
#define PCI_DEVICE_INTEL_PANTHER_POINT_XHCI 0x1e31
|
||||||
|
#define PCI_DEVICE_INTEL_LYNX_POINT_XHCI 0x8c31
|
||||||
|
#define PCI_DEVICE_INTEL_LYNX_POINT_LP_XHCI 0x9c31
|
||||||
|
|
||||||
|
// Intel quirks registers in PCI config
|
||||||
|
#define XHCI_INTEL_USB3PRM 0xdc // USB 3.0 Port Routing Mask
|
||||||
|
#define XHCI_INTEL_USB3_PSSEN 0xd8 // USB 3.0 Port SuperSpeed Enable
|
||||||
|
#define XHCI_INTEL_USB2PRM 0xd4 // USB 2.0 Port Routing Mask
|
||||||
|
#define XHCI_INTEL_XUSB2PR 0xd0 // USB 2.0 Port Routing
|
||||||
|
|
||||||
// Host Controller Capability Registers
|
// Host Controller Capability Registers
|
||||||
#define XHCI_HCI_CAPLENGTH 0x00 // HCI Capability Register Length
|
#define XHCI_HCI_CAPLENGTH 0x00 // HCI Capability Register Length
|
||||||
@@ -17,12 +29,12 @@
|
|||||||
#define XHCI_HCSPARAMS1 0x04 // Structural Parameters 1
|
#define XHCI_HCSPARAMS1 0x04 // Structural Parameters 1
|
||||||
// HCSPARAMS1
|
// HCSPARAMS1
|
||||||
#define HCS_MAX_SLOTS(p) (((p) >> 0) & 0xff)
|
#define HCS_MAX_SLOTS(p) (((p) >> 0) & 0xff)
|
||||||
#define HCS_MAX_PORTS(p) (((p) >> 24) & 0x7f)
|
#define HCS_MAX_PORTS(p) (((p) >> 24) & 0xff)
|
||||||
#define XHCI_HCSPARAMS2 0x08 // Structural Parameters 2
|
#define XHCI_HCSPARAMS2 0x08 // Structural Parameters 2
|
||||||
#define HCS_IST(p) (((p) >> 0) & 0xf)
|
#define HCS_IST(p) (((p) >> 0) & 0xf)
|
||||||
#define HCS_ERST_MAX(p) (((p) >> 4) & 0xf)
|
#define HCS_ERST_MAX(p) (((p) >> 4) & 0xf)
|
||||||
#define HCS_SPR(p) (((p) >> 26) & 0x1)
|
#define HCS_SPR(p) (((p) >> 26) & 0x1)
|
||||||
#define HCS_MAX_SC_BUFFERS(p) (((p) >> 27) & 0x1f)
|
#define HCS_MAX_SC_BUFFERS(p) (((((p) >> 21) & 0x1f)<<5)|(((p) >> 27) & 0x1f))
|
||||||
#define XHCI_HCSPARAMS3 0x0C // Structural Parameters 3
|
#define XHCI_HCSPARAMS3 0x0C // Structural Parameters 3
|
||||||
#define HCS_U1_DEVICE_LATENCY(p) (((p) >> 0) & 0xff)
|
#define HCS_U1_DEVICE_LATENCY(p) (((p) >> 0) & 0xff)
|
||||||
#define HCS_U2_DEVICE_LATENCY(p) (((p) >> 16) & 0xffff)
|
#define HCS_U2_DEVICE_LATENCY(p) (((p) >> 16) & 0xffff)
|
||||||
@@ -98,7 +110,8 @@
|
|||||||
#define XHCI_LEGSUP_BIOSOWNED (1 << 16) // BIOS Owned Semaphore
|
#define XHCI_LEGSUP_BIOSOWNED (1 << 16) // BIOS Owned Semaphore
|
||||||
|
|
||||||
#define XHCI_LEGCTLSTS 0x04
|
#define XHCI_LEGCTLSTS 0x04
|
||||||
#define XHCI_LEGCTLSTS_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17))
|
#define XHCI_LEGCTLSTS_DISABLE_SMI ((0x7 << 1) + (0xff << 5) + (0x7 << 17))
|
||||||
|
#define XHCI_LEGCTLSTS_EVENTS_SMI (0x7 << 29)
|
||||||
|
|
||||||
#define XHCI_SUPPORTED_PROTOCOLS_CAPID 0x02
|
#define XHCI_SUPPORTED_PROTOCOLS_CAPID 0x02
|
||||||
#define XHCI_SUPPORTED_PROTOCOLS_0_MINOR(x) (((x) >> 16) & 0xff)
|
#define XHCI_SUPPORTED_PROTOCOLS_0_MINOR(x) (((x) >> 16) & 0xff)
|
||||||
@@ -336,14 +349,15 @@ struct xhci_slot_ctx {
|
|||||||
#define SLOT_2_PORT_NUM_GET(x) (((x) >> 8) & 0xFF)
|
#define SLOT_2_PORT_NUM_GET(x) (((x) >> 8) & 0xFF)
|
||||||
#define SLOT_2_TT_TIME(x) (((x) & 0x3) << 16)
|
#define SLOT_2_TT_TIME(x) (((x) & 0x3) << 16)
|
||||||
#define SLOT_2_TT_TIME_GET(x) (((x) >> 16) & 0x3)
|
#define SLOT_2_TT_TIME_GET(x) (((x) >> 16) & 0x3)
|
||||||
#define SLOT_2_IRQ_TARGET(x) (((x) & 0x1F) << 27)
|
#define SLOT_2_IRQ_TARGET(x) (((x) & 0x7F) << 22)
|
||||||
#define SLOT_2_IRQ_TARGET_GET(x) (((x) >> 27) & 0x1f)
|
#define SLOT_2_IRQ_TARGET_GET(x) (((x) >> 22) & 0x7F)
|
||||||
|
|
||||||
#define SLOT_3_DEVICE_ADDRESS(x) ((x) & 0xFF)
|
#define SLOT_3_DEVICE_ADDRESS(x) ((x) & 0xFF)
|
||||||
#define SLOT_3_DEVICE_ADDRESS_GET(x) ((x) & 0xFF)
|
#define SLOT_3_DEVICE_ADDRESS_GET(x) ((x) & 0xFF)
|
||||||
#define SLOT_3_SLOT_STATE(x) (((x) & 0x1F) << 27)
|
#define SLOT_3_SLOT_STATE(x) (((x) & 0x1F) << 27)
|
||||||
#define SLOT_3_SLOT_STATE_GET(x) (((x) >> 27) & 0x1F)
|
#define SLOT_3_SLOT_STATE_GET(x) (((x) >> 27) & 0x1F)
|
||||||
|
|
||||||
|
#define HUB_TTT_GET(x) (((x) >> 5) & 0x3)
|
||||||
|
|
||||||
struct xhci_endpoint_ctx {
|
struct xhci_endpoint_ctx {
|
||||||
uint32 dwendpoint0;
|
uint32 dwendpoint0;
|
||||||
|
|||||||
@@ -223,10 +223,12 @@ public:
|
|||||||
|
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
|
|
||||||
status_t ReceiveData(net_buffer* buffer);
|
status_t ReceiveData(net_buffer* buffer,
|
||||||
|
bool isUDPLite = false);
|
||||||
status_t ReceiveError(status_t error,
|
status_t ReceiveError(status_t error,
|
||||||
net_buffer* buffer);
|
net_buffer* buffer);
|
||||||
status_t Deframe(net_buffer* buffer);
|
status_t Deframe(net_buffer* buffer,
|
||||||
|
bool isUDPLite = false);
|
||||||
|
|
||||||
UdpDomainSupport* OpenEndpoint(UdpEndpoint* endpoint);
|
UdpDomainSupport* OpenEndpoint(UdpEndpoint* endpoint);
|
||||||
status_t FreeEndpoint(UdpDomainSupport* domain);
|
status_t FreeEndpoint(UdpDomainSupport* domain);
|
||||||
@@ -692,7 +694,7 @@ UdpEndpointManager::DumpEndpoints(int argc, char *argv[])
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
UdpEndpointManager::ReceiveData(net_buffer *buffer)
|
UdpEndpointManager::ReceiveData(net_buffer *buffer, bool isUDPLite)
|
||||||
{
|
{
|
||||||
TRACE_EPM("ReceiveData(%p [%" B_PRIu32 " bytes])", buffer, buffer->size);
|
TRACE_EPM("ReceiveData(%p [%" B_PRIu32 " bytes])", buffer, buffer->size);
|
||||||
|
|
||||||
@@ -703,7 +705,7 @@ UdpEndpointManager::ReceiveData(net_buffer *buffer)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t status = Deframe(buffer);
|
status_t status = Deframe(buffer, isUDPLite);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -759,7 +761,7 @@ UdpEndpointManager::ReceiveError(status_t error, net_buffer* buffer)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
UdpEndpointManager::Deframe(net_buffer* buffer)
|
UdpEndpointManager::Deframe(net_buffer* buffer, bool isUDPLite)
|
||||||
{
|
{
|
||||||
TRACE_EPM("Deframe(%p [%ld bytes])", buffer, buffer->size);
|
TRACE_EPM("Deframe(%p [%ld bytes])", buffer, buffer->size);
|
||||||
|
|
||||||
@@ -786,26 +788,33 @@ UdpEndpointManager::Deframe(net_buffer* buffer)
|
|||||||
TRACE_EPM(" Deframe(): data from %s to %s", source.AsString(true).Data(),
|
TRACE_EPM(" Deframe(): data from %s to %s", source.AsString(true).Data(),
|
||||||
destination.AsString(true).Data());
|
destination.AsString(true).Data());
|
||||||
|
|
||||||
|
bool liteCheck = isUDPLite;
|
||||||
uint16 udpLength = ntohs(header.udp_length);
|
uint16 udpLength = ntohs(header.udp_length);
|
||||||
|
if (isUDPLite && udpLength == 0) {
|
||||||
|
udpLength = buffer->size;
|
||||||
|
liteCheck = false;
|
||||||
|
}
|
||||||
if (udpLength > buffer->size) {
|
if (udpLength > buffer->size) {
|
||||||
TRACE_EPM(" Deframe(): buffer is too short, expected %hu.",
|
TRACE_EPM(" Deframe(): buffer is too short, expected %hu.",
|
||||||
udpLength);
|
udpLength);
|
||||||
return B_MISMATCHED_VALUES;
|
return B_MISMATCHED_VALUES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer->size > udpLength)
|
if (!isUDPLite && buffer->size > udpLength)
|
||||||
gBufferModule->trim(buffer, udpLength);
|
gBufferModule->trim(buffer, udpLength);
|
||||||
|
|
||||||
if (header.udp_checksum != 0) {
|
if (header.udp_checksum != 0) {
|
||||||
// check UDP-checksum (simulating a so-called "pseudo-header"):
|
// check UDP-checksum (simulating a so-called "pseudo-header"):
|
||||||
uint16 sum = Checksum::PseudoHeader(addressModule, gBufferModule,
|
uint16 sum = Checksum::PseudoHeader(addressModule, gBufferModule,
|
||||||
buffer, IPPROTO_UDP);
|
buffer, isUDPLite ? IPPROTO_UDPLITE : IPPROTO_UDP);
|
||||||
if (sum != 0) {
|
if (sum != 0) {
|
||||||
TRACE_EPM(" Deframe(): bad checksum 0x%hx.", sum);
|
TRACE_EPM(" Deframe(): bad checksum 0x%hx.", sum);
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO check for udpLength < configured min length
|
||||||
|
|
||||||
bufferHeader.Remove();
|
bufferHeader.Remove();
|
||||||
// remove UDP-header from buffer before passing it on
|
// remove UDP-header from buffer before passing it on
|
||||||
|
|
||||||
@@ -991,7 +1000,7 @@ UdpEndpoint::SendRoutedData(net_buffer *buffer, net_route *route)
|
|||||||
if (buffer->size > (0xffff - sizeof(udp_header)))
|
if (buffer->size > (0xffff - sizeof(udp_header)))
|
||||||
return EMSGSIZE;
|
return EMSGSIZE;
|
||||||
|
|
||||||
buffer->protocol = IPPROTO_UDP;
|
buffer->protocol = Socket()->protocol;
|
||||||
|
|
||||||
// add and fill UDP-specific header:
|
// add and fill UDP-specific header:
|
||||||
NetBufferPrepend<udp_header> header(buffer);
|
NetBufferPrepend<udp_header> header(buffer);
|
||||||
@@ -1071,7 +1080,7 @@ UdpEndpoint::DeliverData(net_buffer *_buffer)
|
|||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t status = sUdpEndpointManager->Deframe(buffer);
|
status_t status = sUdpEndpointManager->Deframe(buffer, Socket()->protocol);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
gBufferModule->free(buffer);
|
gBufferModule->free(buffer);
|
||||||
return status;
|
return status;
|
||||||
@@ -1111,6 +1120,21 @@ udp_init_protocol(net_socket *socket)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
net_protocol *
|
||||||
|
udplite_init_protocol(net_socket *socket)
|
||||||
|
{
|
||||||
|
UdpEndpoint *endpoint = new (std::nothrow) UdpEndpoint(socket);
|
||||||
|
if (endpoint == NULL || endpoint->InitCheck() < B_OK) {
|
||||||
|
delete endpoint;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket->protocol = IPPROTO_UDPLITE;
|
||||||
|
|
||||||
|
return endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
udp_uninit_protocol(net_protocol *protocol)
|
udp_uninit_protocol(net_protocol *protocol)
|
||||||
{
|
{
|
||||||
@@ -1267,6 +1291,13 @@ udp_receive_data(net_buffer *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
udplite_receive_data(net_buffer *buffer)
|
||||||
|
{
|
||||||
|
return sUdpEndpointManager->ReceiveData(buffer, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
udp_deliver_data(net_protocol *protocol, net_buffer *buffer)
|
udp_deliver_data(net_protocol *protocol, net_buffer *buffer)
|
||||||
{
|
{
|
||||||
@@ -1465,6 +1496,48 @@ net_protocol_module_info sUDPModule = {
|
|||||||
NULL // read_data_no_buffer()
|
NULL // read_data_no_buffer()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
net_protocol_module_info sUDPLiteModule = {
|
||||||
|
{
|
||||||
|
"network/protocols/udplite/v1",
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
NET_PROTOCOL_ATOMIC_MESSAGES,
|
||||||
|
|
||||||
|
udplite_init_protocol,
|
||||||
|
udp_uninit_protocol,
|
||||||
|
udp_open,
|
||||||
|
udp_close,
|
||||||
|
udp_free,
|
||||||
|
udp_connect,
|
||||||
|
udp_accept,
|
||||||
|
udp_control,
|
||||||
|
udp_getsockopt,
|
||||||
|
udp_setsockopt,
|
||||||
|
udp_bind,
|
||||||
|
udp_unbind,
|
||||||
|
udp_listen,
|
||||||
|
udp_shutdown,
|
||||||
|
udp_send_data,
|
||||||
|
udp_send_routed_data,
|
||||||
|
udp_send_avail,
|
||||||
|
udp_read_data,
|
||||||
|
udp_read_avail,
|
||||||
|
udp_get_domain,
|
||||||
|
udp_get_mtu,
|
||||||
|
udplite_receive_data,
|
||||||
|
udp_deliver_data,
|
||||||
|
udp_error_received,
|
||||||
|
udp_error_reply,
|
||||||
|
NULL, // add_ancillary_data()
|
||||||
|
NULL, // process_ancillary_data()
|
||||||
|
udp_process_ancillary_data_no_container,
|
||||||
|
NULL, // send_data_no_buffer()
|
||||||
|
NULL // read_data_no_buffer()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
module_dependency module_dependencies[] = {
|
module_dependency module_dependencies[] = {
|
||||||
{NET_STACK_MODULE_NAME, (module_info **)&gStackModule},
|
{NET_STACK_MODULE_NAME, (module_info **)&gStackModule},
|
||||||
{NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule},
|
{NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule},
|
||||||
|
|||||||
Reference in New Issue
Block a user