Leaked source code of windows server 2003
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.
 
 
 
 
 
 

571 lines
16 KiB

/*++
Copyright (c) Microsoft Corporation. All rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Module Name:
INIT.C
Abstract:
This module contains initialization helper routines called during
MiniportInitialize.
Revision History:
Notes:
--*/
#include "miniport.h"
#pragma NDIS_PAGEABLE_FUNCTION(NICAllocAdapter)
#pragma NDIS_PAGEABLE_FUNCTION(NICFreeAdapter)
#pragma NDIS_PAGEABLE_FUNCTION(NICInitializeAdapter)
#pragma NDIS_PAGEABLE_FUNCTION(NICReadRegParameters)
NDIS_STATUS NICAllocAdapter(
PMP_ADAPTER *pAdapter)
{
PMP_ADAPTER Adapter = NULL;
PNDIS_PACKET Packet;
PNDIS_BUFFER Buffer;
PUCHAR pTCBMem;
PTCB pTCB;
NDIS_STATUS Status;
LONG index;
DEBUGP(MP_TRACE, ("--> NICAllocAdapter\n"));
*pAdapter = NULL;
do
{
//
// Allocate memory for adapter context
//
Status = NdisAllocateMemoryWithTag(
&Adapter,
sizeof(MP_ADAPTER),
NIC_TAG);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("Failed to allocate memory for adapter context\n"));
break;
}
//
// Zero the memory block
//
NdisZeroMemory(Adapter, sizeof(MP_ADAPTER));
NdisInitializeListHead(&Adapter->List);
//
// Initialize Send & Recv listheads and corresponding
// spinlocks.
//
NdisInitializeListHead(&Adapter->RecvWaitList);
NdisInitializeListHead(&Adapter->SendWaitList);
NdisInitializeListHead(&Adapter->SendFreeList);
NdisAllocateSpinLock(&Adapter->SendLock);
NdisInitializeListHead(&Adapter->RecvFreeList);
NdisAllocateSpinLock(&Adapter->RecvLock);
//
// Allocate lookside list for Receive Control blocks.
//
NdisInitializeNPagedLookasideList(
&Adapter->RecvLookaside,
NULL, // No Allocate function
NULL, // No Free function
0, // Reserved for system use
sizeof(RCB),
NIC_TAG,
0); // Reserved for system use
MP_SET_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE);
//
// Allocate packet pool for receive indications
//
NdisAllocatePacketPool(
&Status,
&Adapter->RecvPacketPoolHandle,
NIC_MAX_BUSY_RECVS,
PROTOCOL_RESERVED_SIZE_IN_PACKET);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("NdisAllocatePacketPool failed\n"));
break;
}
//
// Initialize receive packets
//
for(index=0; index < NIC_MAX_BUSY_RECVS; index++)
{
//
// Allocate a packet descriptor for receive packets
// from a preallocated pool.
//
NdisAllocatePacket(
&Status,
&Packet,
Adapter->RecvPacketPoolHandle);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("NdisAllocatePacket failed\n"));
break;
}
NDIS_SET_PACKET_HEADER_SIZE(Packet, ETH_HEADER_SIZE);
//
// Insert it into the list of free receive packets.
//
NdisInterlockedInsertTailList(
&Adapter->RecvFreeList,
(PLIST_ENTRY)&Packet->MiniportReserved[0],
&Adapter->RecvLock);
}
//
// Allocate a huge block of memory for all TCB's
//
Status = NdisAllocateMemoryWithTag(
&pTCBMem,
sizeof(TCB) * NIC_MAX_BUSY_SENDS,
NIC_TAG);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("Failed to allocate memory for TCB's\n"));
break;
}
NdisZeroMemory(pTCBMem, sizeof(TCB) * NIC_MAX_BUSY_SENDS);
Adapter->TCBMem = pTCBMem;
//
// Allocate a buffer pool for send buffers.
//
NdisAllocateBufferPool(
&Status,
&Adapter->SendBufferPoolHandle,
NIC_MAX_BUSY_SENDS);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("NdisAllocateBufferPool for send buffer failed\n"));
break;
}
//
// Divide the TCBMem blob into TCBs and create a buffer
// descriptor for the Data portion of the TCBs.
//
for(index=0; index < NIC_MAX_BUSY_SENDS; index++)
{
pTCB = (PTCB) pTCBMem;
//
// Create a buffer descriptor for the Data portion of the TCBs.
// Buffer descriptors are nothing but MDLs on NT systems.
//
NdisAllocateBuffer(
&Status,
&Buffer,
Adapter->SendBufferPoolHandle,
(PVOID)&pTCB->Data[0],
NIC_BUFFER_SIZE);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("NdisAllocateBuffer failed\n"));
break;
}
//
// Initialize the TCB structure.
//
pTCB->Buffer = Buffer;
pTCB->pData = (PUCHAR) &pTCB->Data[0];
pTCB->Adapter = Adapter;
NdisInterlockedInsertTailList(
&Adapter->SendFreeList,
&pTCB->List,
&Adapter->SendLock);
pTCBMem = pTCBMem + sizeof(TCB);
}
} while(FALSE);
*pAdapter = Adapter;
//
// In the failure case, the caller of this routine will end up
// calling NICFreeAdapter to free all the successfully allocated
// resources.
//
DEBUGP(MP_TRACE, ("<-- NICAllocAdapter\n"));
return(Status);
}
void NICFreeAdapter(
PMP_ADAPTER Adapter)
{
NDIS_STATUS Status;
PNDIS_PACKET Packet;
PNDIS_BUFFER Buffer;
PUCHAR pMem;
PTCB pTCB;
PLIST_ENTRY pEntry;
DEBUGP(MP_TRACE, ("--> NICFreeAdapter\n"));
ASSERT(Adapter);
ASSERT(!Adapter->RefCount);
//
// Free all the resources we allocated for send.
//
while(!IsListEmpty(&Adapter->SendFreeList))
{
pTCB = (PTCB) NdisInterlockedRemoveHeadList(
&Adapter->SendFreeList,
&Adapter->SendLock);
if(!pTCB)
{
break;
}
if(pTCB->Buffer)
{
NdisFreeBuffer(pTCB->Buffer);
}
}
if(Adapter->SendBufferPoolHandle)
{
NdisFreeBufferPool(Adapter->SendBufferPoolHandle);
}
NdisFreeMemory(Adapter->TCBMem, sizeof(TCB) * NIC_MAX_BUSY_SENDS, 0);
ASSERT(IsListEmpty(&Adapter->SendFreeList));
ASSERT(IsListEmpty(&Adapter->RecvWaitList));
ASSERT(IsListEmpty(&Adapter->SendWaitList));
NdisFreeSpinLock(&Adapter->SendLock);
//
// Free all the resources we allocated for receive.
//
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE))
{
NdisDeleteNPagedLookasideList(&Adapter->RecvLookaside);
MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE);
}
while(!IsListEmpty(&Adapter->RecvFreeList))
{
pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
&Adapter->RecvFreeList,
&Adapter->RecvLock);
if(pEntry)
{
Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
NdisFreePacket(Packet);
}
}
if(Adapter->RecvPacketPoolHandle)
{
NdisFreePacketPool(Adapter->RecvPacketPoolHandle);
}
ASSERT(IsListEmpty(&Adapter->RecvFreeList));
NdisFreeSpinLock(&Adapter->RecvLock);
//
// Finally free the memory for adapter context.
//
NdisFreeMemory(Adapter, sizeof(MP_ADAPTER), 0);
DEBUGP(MP_TRACE, ("<-- NICFreeAdapter\n"));
}
void NICAttachAdapter(PMP_ADAPTER Adapter)
{
DEBUGP(MP_TRACE, ("--> NICAttachAdapter\n"));
NdisInterlockedInsertTailList(
&GlobalData.AdapterList,
&Adapter->List,
&GlobalData.Lock);
DEBUGP(MP_TRACE, ("<-- NICAttachAdapter\n"));
}
void NICDetachAdapter(PMP_ADAPTER Adapter)
{
DEBUGP(MP_TRACE, ("--> NICDetachAdapter\n"));
NdisAcquireSpinLock(&GlobalData.Lock);
RemoveEntryList(&Adapter->List);
NdisReleaseSpinLock(&GlobalData.Lock);
DEBUGP(MP_TRACE, ("<-- NICDetachAdapter\n"));
}
NDIS_STATUS
NICReadRegParameters(
PMP_ADAPTER Adapter,
NDIS_HANDLE WrapperConfigurationContext)
/*++
Routine Description:
Read device configuration parameters from the registry
Arguments:
Adapter Pointer to our adapter
WrapperConfigurationContext For use by NdisOpenConfiguration
Should be called at IRQL = PASSIVE_LEVEL.
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_FAILURE
NDIS_STATUS_RESOURCES
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
NDIS_HANDLE ConfigurationHandle;
PUCHAR NetworkAddress;
UINT Length;
PUCHAR pAddr;
static ULONG g_ulAddress = 0;
DEBUGP(MP_TRACE, ("--> NICReadRegParameters\n"));
//
// Open the registry for this adapter to read advanced
// configuration parameters stored by the INF file.
//
NdisOpenConfiguration(
&Status,
&ConfigurationHandle,
WrapperConfigurationContext);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("NdisOpenConfiguration failed\n"));
return NDIS_STATUS_FAILURE;
}
//
// Read all of our configuration parameters using NdisReadConfiguration
// and parse the value.
//
//
// Just for testing purposes, let us make up a dummy mac address.
// In order to avoid conflicts with MAC addresses, it is usually a good
// idea to check the IEEE OUI list (e.g. at
// http://standards.ieee.org/regauth/oui/oui.txt). According to that
// list 00-50-F2 is owned by Microsoft.
//
// An important rule to "generating" MAC addresses is to have the
// "locally administered bit" set in the address, which is bit 0x02 for
// LSB-type networks like Ethernet. Also make sure to never set the
// multicast bit in any MAC address: bit 0x01 in LSB networks.
//
pAddr = (PUCHAR) &g_ulAddress;
++g_ulAddress;
Adapter->PermanentAddress[0] = 0x02;
Adapter->PermanentAddress[1] = 0x50;
Adapter->PermanentAddress[2] = 0xF2;
Adapter->PermanentAddress[3] = 0x00;
Adapter->PermanentAddress[4] = 0x00;
Adapter->PermanentAddress[5] = pAddr[0];
//
// Read NetworkAddress registry value and use it as the current address
// if there is a software configurable NetworkAddress specified in
// the registry.
//
NdisReadNetworkAddress(
&Status,
&NetworkAddress,
&Length,
ConfigurationHandle);
if((Status == NDIS_STATUS_SUCCESS) && (Length == ETH_LENGTH_OF_ADDRESS))
{
ETH_COPY_NETWORK_ADDRESS(
Adapter->CurrentAddress,
NetworkAddress);
} else {
ETH_COPY_NETWORK_ADDRESS(
Adapter->CurrentAddress,
Adapter->PermanentAddress);
}
DEBUGP(MP_LOUD, ("Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
Adapter->PermanentAddress[0],
Adapter->PermanentAddress[1],
Adapter->PermanentAddress[2],
Adapter->PermanentAddress[3],
Adapter->PermanentAddress[4],
Adapter->PermanentAddress[5]));
DEBUGP(MP_LOUD, ("Current Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
Adapter->CurrentAddress[0],
Adapter->CurrentAddress[1],
Adapter->CurrentAddress[2],
Adapter->CurrentAddress[3],
Adapter->CurrentAddress[4],
Adapter->CurrentAddress[5]));
Adapter->ulLinkSpeed = NIC_LINK_SPEED;
//
// Close the configuration registry
//
NdisCloseConfiguration(ConfigurationHandle);
DEBUGP(MP_TRACE, ("<-- NICReadRegParameters\n"));
return NDIS_STATUS_SUCCESS;
}
NDIS_STATUS NICInitializeAdapter(
IN PMP_ADAPTER Adapter,
IN NDIS_HANDLE WrapperConfigurationContext
)
/*++
Routine Description:
Query assigned resources and initialize the adapter.
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_ADAPTER_NOT_FOUND
--*/
{
NDIS_STATUS Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
UCHAR resBuf[NIC_RESOURCE_BUF_SIZE];
PNDIS_RESOURCE_LIST resList = (PNDIS_RESOURCE_LIST)resBuf;
UINT bufSize = NIC_RESOURCE_BUF_SIZE;
PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDesc;
ULONG index;
DEBUGP(MP_TRACE, ("---> InitializeAdapter\n"));
do
{
//
// Get the resources assigned by the PNP manager. NDIS gets
// these resources in IRP_MN_START_DEVICE request.
//
NdisMQueryAdapterResources(
&Status,
WrapperConfigurationContext,
resList,
&bufSize);
if (Status == NDIS_STATUS_SUCCESS)
{
for (index=0; index < resList->Count; index++)
{
pResDesc = &resList->PartialDescriptors[index];
switch(pResDesc->Type)
{
case CmResourceTypePort:
DEBUGP(MP_INFO, ("IoBaseAddress = 0x%x\n",
NdisGetPhysicalAddressLow(pResDesc->u.Port.Start)));
DEBUGP(MP_INFO, ("IoRange = x%x\n",
pResDesc->u.Port.Length));
break;
case CmResourceTypeInterrupt:
DEBUGP(MP_INFO, ("InterruptLevel = x%x\n",
pResDesc->u.Interrupt.Level));
break;
case CmResourceTypeMemory:
DEBUGP(MP_INFO, ("MemPhysAddress(Low) = 0x%0x\n",
NdisGetPhysicalAddressLow(pResDesc->u.Memory.Start)));
DEBUGP(MP_INFO, ("MemPhysAddress(High) = 0x%0x\n",
NdisGetPhysicalAddressHigh(pResDesc->u.Memory.Start)));
break;
}
}
}
Status = NDIS_STATUS_SUCCESS;
//
// Map bus-relative IO range to system IO space using
// NdisMRegisterIoPortRange
//
//
// Map bus-relative registers to virtual system-space
// using NdisMMapIoSpace
//
//
// Disable interrupts here as soon as possible
//
//
// Register the interrupt using NdisMRegisterInterrupt
//
//
// Initialize the hardware with mapped resources
//
#ifdef NDIS50_MINIPORT
//
// Register a shutdown handler for NDIS50 or earlier miniports
// For NDIS51 miniports, set AdapterShutdownHandler.
//
NdisMRegisterAdapterShutdownHandler(
Adapter->AdapterHandle,
(PVOID) Adapter,
(ADAPTER_SHUTDOWN_HANDLER) MPShutdown);
#endif
//
// Enable the interrupt
//
} while (FALSE);
DEBUGP(MP_TRACE, ("<--- InitializeAdapter, Status=%x\n", Status));
return Status;
}