You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
7.0 KiB
296 lines
7.0 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cmnbuf.c
|
|
|
|
Abstract:
|
|
|
|
Code to manage common buffer -- hardware addressable memory
|
|
|
|
a common buffer block looks like this
|
|
|
|
start ------------ <- address returned from the hal
|
|
padding
|
|
------------ <- address returned to the miniport
|
|
mp data
|
|
------------ <- ptr to header
|
|
header
|
|
end ------------
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
Revision History:
|
|
|
|
6-20-99 : created
|
|
|
|
--*/
|
|
|
|
#include "common.h"
|
|
|
|
// paged functions
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, USBPORT_HalAllocateCommonBuffer)
|
|
#endif
|
|
|
|
// non paged functions
|
|
|
|
|
|
PUSBPORT_COMMON_BUFFER
|
|
USBPORT_HalAllocateCommonBuffer(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
ULONG NumberOfBytes
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocates common buffer directly from the hal.
|
|
The common buffer is passed to the miniport, we
|
|
always allocate a multiple of PAGE_SIZE so the
|
|
always starts on a page_boundry. This ensures
|
|
proper alignement of the TDs used by the miniport
|
|
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - DeviceObject of the controller to stop
|
|
|
|
Return Value:
|
|
|
|
returns Virtual Address of common buffer or NULL if
|
|
unsuccessful.
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION devExt;
|
|
PUSBPORT_COMMON_BUFFER header;
|
|
PUCHAR virtualAddress, mpBuffer, baseVa;
|
|
PHYSICAL_ADDRESS logicalAddress;
|
|
ULONG headerLength;
|
|
ULONG n, basePhys, mpBufferPhys, pageCount, extra;
|
|
|
|
PAGED_CODE();
|
|
|
|
LOGENTRY(NULL, FdoDeviceObject, LOG_XFERS, 'acm>', 0, 0, NumberOfBytes);
|
|
|
|
GET_DEVICE_EXT(devExt, FdoDeviceObject);
|
|
ASSERT_FDOEXT(devExt);
|
|
|
|
// NULL initialize the return value in case the allocation fails
|
|
//
|
|
header = NULL;
|
|
|
|
headerLength = sizeof(USBPORT_COMMON_BUFFER);
|
|
|
|
// compute number min of pages we will need to satisfy
|
|
// the request
|
|
|
|
n = NumberOfBytes+headerLength;
|
|
pageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, n);
|
|
|
|
#if DBG
|
|
{
|
|
ULONG pc;
|
|
// compute number of pages we will need
|
|
pc = n / PAGE_SIZE;
|
|
if ((n % PAGE_SIZE)) {
|
|
pc++;
|
|
}
|
|
USBPORT_ASSERT(pc == pageCount);
|
|
}
|
|
#endif
|
|
|
|
extra = (pageCount*PAGE_SIZE)-n;
|
|
n = (pageCount*PAGE_SIZE);
|
|
|
|
USBPORT_KdPrint((1,"'ALLOC(%d) extra %d bytes\n", n, extra));
|
|
|
|
virtualAddress =
|
|
HalAllocateCommonBuffer(devExt->Fdo.AdapterObject,
|
|
n,
|
|
&logicalAddress,
|
|
TRUE);
|
|
#if DBG
|
|
if (virtualAddress == NULL) {
|
|
USBPORT_KdPrint((0,"'HalAllocateCommonBuffer failed\n"));
|
|
USBPORT_KdPrint((0,"'alloced bytes %d\n"));
|
|
DEBUG_BREAK();
|
|
}
|
|
#endif
|
|
|
|
if (virtualAddress != NULL) {
|
|
|
|
devExt->Fdo.StatCommonBufferBytes += n;
|
|
|
|
basePhys = logicalAddress.LowPart & ~(PAGE_SIZE-1);
|
|
baseVa = PAGE_ALIGN(virtualAddress);
|
|
// hal should have given us a page aligned address since
|
|
// we asked for a multiple of PAGE_SIZE,
|
|
// i trust NT but not Win9x
|
|
USBPORT_ASSERT(virtualAddress == baseVa);
|
|
|
|
// client ptrs
|
|
mpBuffer = baseVa;
|
|
mpBufferPhys = basePhys;
|
|
|
|
header = (PUSBPORT_COMMON_BUFFER) (mpBuffer+NumberOfBytes+extra);
|
|
USBPORT_ASSERT(n == NumberOfBytes+extra+headerLength);
|
|
// USB controllers only support 32 bit phys addresses
|
|
// for control structures
|
|
USBPORT_ASSERT(logicalAddress.HighPart == 0);
|
|
|
|
#if DBG
|
|
RtlFillMemory(virtualAddress, n, 'x');
|
|
#endif
|
|
// init the header
|
|
header->Sig = SIG_CMNBUF;
|
|
header->Flags = 0;
|
|
header->TotalLength = n;
|
|
header->LogicalAddress = logicalAddress;
|
|
header->VirtualAddress = virtualAddress;
|
|
header->BaseVa = baseVa;
|
|
header->BasePhys = basePhys;
|
|
|
|
header->MiniportLength = NumberOfBytes+extra;
|
|
header->MiniportVa = mpBuffer;
|
|
header->MiniportPhys = mpBufferPhys;
|
|
// zero the client part
|
|
RtlZeroMemory(header->MiniportVa, header->MiniportLength);
|
|
|
|
}
|
|
|
|
LOGENTRY(NULL, FdoDeviceObject, LOG_XFERS, 'acm<', mpBuffer, mpBufferPhys, header);
|
|
|
|
return header;
|
|
}
|
|
|
|
|
|
VOID
|
|
USBPORT_HalFreeCommonBuffer(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PUSBPORT_COMMON_BUFFER CommonBuffer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free a common buffer for the miniport
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
returns Virtual Address of common buffer or NULL if
|
|
unsuccessful.
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION devExt;
|
|
|
|
GET_DEVICE_EXT(devExt, FdoDeviceObject);
|
|
ASSERT_FDOEXT(devExt);
|
|
|
|
USBPORT_ASSERT(CommonBuffer != NULL);
|
|
ASSERT_COMMON_BUFFER(CommonBuffer);
|
|
|
|
LOGENTRY(NULL, FdoDeviceObject, LOG_XFERS, 'hFCB',
|
|
CommonBuffer, CommonBuffer->TotalLength,
|
|
CommonBuffer->MiniportVa);
|
|
|
|
devExt->Fdo.StatCommonBufferBytes -=
|
|
CommonBuffer->TotalLength;
|
|
|
|
HalFreeCommonBuffer(devExt->Fdo.AdapterObject,
|
|
CommonBuffer->TotalLength,
|
|
CommonBuffer->LogicalAddress,
|
|
CommonBuffer->MiniportVa,
|
|
TRUE);
|
|
}
|
|
|
|
|
|
PUCHAR
|
|
USBPORTSVC_MapHwPhysicalToVirtual(
|
|
HW_32BIT_PHYSICAL_ADDRESS HwPhysicalAddress,
|
|
PDEVICE_DATA DeviceData,
|
|
PENDPOINT_DATA EndpointData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
given a physical address return the corresponding
|
|
virtual address.
|
|
|
|
Arguments:
|
|
|
|
if the phys address is associated with an endpoint
|
|
the endpoint is passed in.
|
|
|
|
Return Value:
|
|
|
|
Virtual Address, NULL if not found
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION devExt;
|
|
PUCHAR virtualAddress;
|
|
PHCD_ENDPOINT endpoint;
|
|
ULONG offset;
|
|
PDEVICE_OBJECT fdoDeviceObject;
|
|
|
|
DEVEXT_FROM_DEVDATA(devExt, DeviceData);
|
|
ASSERT_FDOEXT(devExt);
|
|
|
|
fdoDeviceObject = devExt->HcFdoDeviceObject;
|
|
|
|
LOGENTRY(NULL, fdoDeviceObject, LOG_XFERS, 'mapP', HwPhysicalAddress, 0,
|
|
EndpointData);
|
|
|
|
if (EndpointData == NULL) {
|
|
TEST_TRAP();
|
|
} else {
|
|
PUSBPORT_COMMON_BUFFER cb;
|
|
|
|
ENDPOINT_FROM_EPDATA(endpoint, EndpointData);
|
|
ASSERT_ENDPOINT(endpoint);
|
|
|
|
cb = endpoint->CommonBuffer;
|
|
|
|
// mask off base physical address
|
|
offset = HwPhysicalAddress - cb->BasePhys;
|
|
virtualAddress = cb->BaseVa+offset;
|
|
|
|
LOGENTRY(NULL, fdoDeviceObject, LOG_XFERS, 'mpPV', HwPhysicalAddress, offset,
|
|
cb->BaseVa);
|
|
|
|
USBPORT_ASSERT(HwPhysicalAddress >= cb->BasePhys &&
|
|
HwPhysicalAddress < cb->BasePhys+cb->MiniportLength);
|
|
|
|
LOGENTRY(NULL, fdoDeviceObject, LOG_XFERS, 'mapV', HwPhysicalAddress, 0,
|
|
virtualAddress);
|
|
|
|
return virtualAddress;
|
|
}
|
|
|
|
|
|
// probably a bug in the miniport
|
|
DEBUG_BREAK();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|