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:
Akshay Jaggi
2014-07-11 22:14:05 +02:00
committed by Jérôme Duval
parent 8674959175
commit 17aa359b5d
9 changed files with 334 additions and 83 deletions
+2 -2
View File
@@ -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
; ;
+1
View File
@@ -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
+2 -2
View File
@@ -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,
+220 -63
View File
@@ -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,37 +201,69 @@ 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) {
TRACE_ALWAYS("the host controller is bios owned, claiming"
" ownership\n");
WriteCapReg32(eecp, eec | XHCI_LEGSUP_OSOWNED);
for (int32 i = 0; i < 20; i++) {
eec = ReadCapReg32(eecp);
if ((eec & XHCI_LEGSUP_BIOSOWNED) == 0)
break;
TRACE_ALWAYS("controller is still bios owned, waiting\n");
snooze(50000);
}
if (eec & XHCI_LEGSUP_BIOSOWNED) { if (eec & XHCI_LEGSUP_BIOSOWNED) {
TRACE_ERROR("bios won't give up control over the host " TRACE_ALWAYS("the host controller is bios owned, claiming"
"controller (ignoring)\n"); " ownership\n");
} else if (eec & XHCI_LEGSUP_OSOWNED) { WriteCapReg32(eecp, eec | XHCI_LEGSUP_OSOWNED);
TRACE_ALWAYS("successfully took ownership of the host "
"controller\n"); for (int32 i = 0; i < 20; i++) {
eec = ReadCapReg32(eecp);
if ((eec & XHCI_LEGSUP_BIOSOWNED) == 0)
break;
TRACE_ALWAYS("controller is still bios owned, waiting\n");
snooze(50000);
}
if (eec & XHCI_LEGSUP_BIOSOWNED) {
TRACE_ERROR("bios won't give up control over the host "
"controller (ignoring)\n");
} else if (eec & XHCI_LEGSUP_OSOWNED) {
TRACE_ALWAYS("successfully took ownership of the host "
"controller\n");
}
// Force off the BIOS owned flag, and clear all SMIs. Some BIOSes
// do indicate a successful handover but do not remove their SMIs
// and then freeze the system when interrupts are generated.
WriteCapReg32(eecp, eec & ~XHCI_LEGSUP_BIOSOWNED);
} }
break;
// Force off the BIOS owned flag, and clear all SMIs. Some BIOSes }
// do indicate a successful handover but do not remove their SMIs uint32 legctlsts = ReadCapReg32(eecp + XHCI_LEGCTLSTS);
// and then freeze the system when interrupts are generated. legctlsts &= XHCI_LEGCTLSTS_DISABLE_SMI;
WriteCapReg32(eecp, eec & ~XHCI_LEGSUP_BIOSOWNED); 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);
} }
WriteCapReg32(eecp + XHCI_LEGCTLSTS, XHCI_LEGCTLSTS_DISABLE_SMI);
// halt the host controller // halt the host controller
if (ControllerHalt() < B_OK) { if (ControllerHalt() < B_OK) {
@@ -337,8 +371,7 @@ 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) {
deviceDescriptor, device->address + 1, speed, false, device); TRACE("creating new Hub\n");
if (!deviceObject) { 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);
} 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) {
: transfer->DataLength(); case COMP_SHORT_PACKET:
TRACE("finishing transfer td %p\n", td); case COMP_SUCCESS:
if (directionIn && actualLength > 0) { callbackStatus = B_OK;
if (requestData) { break;
TRACE("copying in data %d bytes\n", requestData->Length); case COMP_DATA_BUFFER:
memcpy((uint8 *)transfer->Vector()[0].iov_base, callbackStatus = directionIn ? B_DEV_DATA_OVERRUN
td->buffer_log[0], requestData->Length); : B_DEV_DATA_UNDERRUN;
} else { break;
TRACE("copying in iov count %ld\n", transfer->VectorCount()); case COMP_BABBLE:
ReadDescriptorChain(td, transfer->Vector(), callbackStatus = directionIn ? B_DEV_FIFO_OVERRUN
transfer->VectorCount()); : 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();
if (td->trb_completion_code == COMP_SHORT_PACKET)
actualLength -= td->trb_left;
if (directionIn && actualLength > 0) {
if (requestData) {
TRACE("copying in data %d bytes\n", requestData->Length);
transfer->PrepareKernelAccess();
memcpy((uint8 *)transfer->Vector()[0].iov_base,
td->buffer_log[0], requestData->Length);
} else {
TRACE("copying in iov count %ld\n", transfer->VectorCount());
transfer->PrepareKernelAccess();
ReadDescriptorChain(td, transfer->Vector(),
transfer->VectorCount());
}
} }
} }
transfer->Finished(callbackStatus, actualLength); transfer->Finished(callbackStatus, actualLength);
delete transfer;
FreeDescriptor(td); FreeDescriptor(td);
Lock(); Lock();
} }
+2
View File
@@ -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)));
+19 -5
View File
@@ -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},