📄 usbnicadap.cpp
字号:
// Copy partial packet buffer to Transfer buffer
memcpy(Context->Buffer+count,Buffer,Size);
count += Size;
buf = buf.GetNext();
}
// Store the packet size in the Frame at the first word
*((short *)Context->Buffer) = (short)count-2;
pUrb = m_SendPipe.BuildBulkTransfer(
Context->Buffer,
count,
FALSE,
NULL,
TRUE
);
if (pUrb == NULL)
{
delete Context;
m_TxIrpPool.Free(I);
return NDIS_STATUS_RESOURCES;
}
else
{
Context->m_pUrb = pUrb;
}
// Pass down the URB to the bus driver
status = m_SendPipe.SubmitUrb (
I,
pUrb,
WdmCompletionTxRoutine(this),
Context
);
return status;
}
////////////////////////////////////////////////////////////////////
// USBNICAdapter::ReturnPacket
//
// This method is called when NDIS returns a packet previuosly
// indicated by IndicateReceive() back to the miniport
//
// Parameters:
// Packet
// Points to a packet descriptor specifying the packet
// IRQL:
// DISPATCH_LEVEL
// Return Mode:
// n/a
// NOTE:
// The packet returns to the "free list" in the Rx area.
// Reclaim() does the necessary reset of the chained buffer
// and OOB data if any.
VOID USBNICAdapter::ReturnPacket(IN PNDIS_PACKET Packet)
{
//TRACE("USBNICAdapter::ReturnPacket() Entered Packet=%p\n", Packet);
// declare for convenience
m_pRxArea->Reclaim(Packet);
}
////////////////////////////////////////////////////////////////////
// USBNICAdapter::CheckForHang
// Optional function that reports the state of the NIC or monitors
// the responsiveness of an underlying device driver.
// Parameters:
// none
// IRQL:
// IRQL DISPATCH_LEVEL
// Return Mode:
// Synchronous
// NOTE:
// By default, the NDIS library calls MiniportCheckForHang
// approximately every two seconds. If MiniportCheckForHang returns
// TRUE, NDIS then calls the driver's MiniportReset function.
BOOLEAN USBNICAdapter::CheckForHang()
{
return FALSE;
}
///////////////////////////////////////////////////////////////////////
// USBNICAdapter::CompletionRxRoutine
//
// Parameters:
// pIrp - irp being completed
// Context - context passed when the irp had been submitted
// IRQL:
// IRQL DISPATCH_LEVEL
// Returns:
// Usually, STATUS_MORE_PROCESSING_REQUIRED
// Comments:
// Processes asynchronous "receive" IRP completions: this is a "HandleInterrupt()"
// thing for NDIS WDM drivers. So, the logic is similar to HandleInterrupt():
// If a new received packet arrived indicate it to NDIS. Handle status indications, too.
// The important point is that if the the irps are be recycled back to the pools they
// came from, STATUS_MORE_PROCESSING_REQUIRED should be returned to the system.
// NOTE: Under Win9X, NDIS packet and status indications must NOT be made from
// the completion routine context. Instead, the NDIS WDM driver should use the
// KNdisWdm9XIndication class which is used to schedule the indication on
// a timer.
NTSTATUS USBNICAdapter::CompletionRxRoutine(PIRP pIrp, IRP_CONTEXT *Context)
{
PWDM_RFD pContext = (PWDM_RFD)Context;
KIrp I(pIrp);
NTSTATUS status = I.Status();
//TRACE("USBNICAdapter::CompletionRxRoutine() Entered\n");
if(status)
TRACE("IRP RX completion status = %08X\n",ULONG(I.Status()));
if (m_HaltFlag)
{
--m_RxIrpsOutstanding;
TRACE("IRP RX Outstanding Count--= %08X\n",(ULONG)m_RxIrpsOutstanding);
if (!m_RxIrpsOutstanding)
{
TRACE("IRP RX Idle Event being set!");
m_RxIdleEvent.Set();
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
if (status != NDIS_STATUS_SUCCESS)
{
if ((status == STATUS_DEVICE_DATA_ERROR) ||
(status == STATUS_CANCELLED) ||
(status == STATUS_DEVICE_NOT_CONNECTED))
{
// This error usually occurs when the device is malfunctioning
// or it has been disconnected. Halt() cancels all outstanding Irps
// Note: The OutStanding Rx Irp count must be decrimented because we got
// here prior to the m_HaltFlag being set
// TODO: add code to handle you case
--m_RxIrpsOutstanding;
TRACE("IRP RX Outstanding Count--= %08X\n",(ULONG)m_RxIrpsOutstanding);
if (!m_RxIrpsOutstanding)
{
TRACE("IRP RX Idle Event being set!");
m_RxIdleEvent.Set();
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
else
{
//TODO: Handle the case were the Irp did not complete successfully
// In this example we simply are resending the URB back to the
// bus driver.
ReSubmitRfd(pContext);
return STATUS_MORE_PROCESSING_REQUIRED;
}
}
// Retrieve the Packet descriptor that matches this HwRfd
KNdisPacket Packet(m_pRxArea->GetPacket(pContext));
ASSERT( Packet.IsValid() );
// Extract the first available buffer
KNdisBuffer buf = Packet.QueryFirstBuffer();
ASSERT( buf.IsValid() );
// Copy the Rx Packet data to the Packet
short ActualSize = *((short *)pContext->m_RfdBuffer);
if(0 == ActualSize)
{
ReSubmitRfd(pContext);
return STATUS_MORE_PROCESSING_REQUIRED;
}
// Remove the Packet from the Rfd list
m_pRxArea->Complete(pContext);
// Make sure that the Packet to be indicated has the correct length
buf.AdjustLength(ActualSize);
Packet.STATUS(NDIS_STATUS_SUCCESS);
#if BINARY_COMPATIBLE
m_PacketIndicate.ScheduleReceiveIndicate(Packet);
#else
// Indicate the Packet to NDIS
IndicateReceive(Packet);
#endif
// Update the transmit stats
m_GenStats->rcv_ok++;
return STATUS_MORE_PROCESSING_REQUIRED;
}
#if BINARY_COMPATIBLE
///////////////////////////////////////////////////////////////////////
// USBNIC::ProcessReceiveIndicate
//
// Parameters:
// Packet - Packet to indicate
// Context - Anything you wish to carry forward that is not
// resident in the packet.
// IRQL:
// = DISPATCH_LEVEL
// Returns:
// None
// Comments:
// This routine is used to perform the actual indication when the timer
// has expired.
//
VOID USBNICAdapter::ProcessReceiveIndicate(PNDIS_PACKET Packet)
{
// Indicate the Packet to NDIS
IndicateReceive(Packet);
}
#endif
////////////////////////////////////////////////////////////////////
// USBNICAdapter::CompletionCntrlRoutine()
//
//
// Parameters:
// Irp - IRP to be completed
// Context - Associated context for the Irp
// IRQL:
// IRQL DISPATCH_LEVEL
//
// Return Mode:
//
NTSTATUS USBNICAdapter::CompletionCntrlRoutine(KIrp Irp, IRP_CONTEXT* Context)
{
TRACE("USBNICAdapter::CompletionCntrlRoutineLINK() Entered\n");
TRACE("IRP Control completion status = %08X\n",ULONG(Irp->IoStatus.Information));
// Free the associated Irp
Context->Adapter->m_CntrlIrpPool.Free(Irp);
// Destroy the associated Urb
delete Context->m_pUrb;
// Destroy the Context
delete Context;
return STATUS_MORE_PROCESSING_REQUIRED;
}
////////////////////////////////////////////////////////////////////
// USBNICAdapter::ReadConfiguration()
//
// When this routine returns success, then it is
// accepted that the device configuration was successfull.
//
// Parameters:
// pEthConfig - pointer to a Ethernet_Configuration
//
// IRQL:
// PASSIVE_LEVEL
//
// Return Mode:
//
NTSTATUS USBNICAdapter::ReadConfiguration(Ethernet_Configuration *pEthConfig)
{
NTSTATUS status = STATUS_SUCCESS;
status = ControlCommand (
USBNIC_COMMAND_GET_ETHERNET_DESC,
USBD_TRANSFER_DIRECTION_IN,
0,
0,
(PUCHAR)pEthConfig,
sizeof(Ethernet_Configuration),
TIMEOUT);
return status;
}
////////////////////////////////////////////////////////////////////
// USBNICAdapter::DownLoadFirmware()
//
// This routine is used to supply the Firmware Buffers to
// the device.
//
// Parameters:
//
// data - data to be downloaded
// length - length of data buffer
// interrupt - firmware specific params
// type - firmware specific params
//
// IRQL:
// PASSIVE_LEVEL
//
// Return Mode:
// SYNCHRONOUS
NTSTATUS USBNICAdapter::DownLoadFirmware(PUCHAR data, USHORT length, UCHAR interrupt, UCHAR type)
{
NTSTATUS status = STATUS_SUCCESS;
if (length > BUF_SIZE)
status = STATUS_UNSUCCESSFUL;
else
{
memcpy((PUCHAR)FirmwareBuffer, data,length);
status = ControlCommand (
USBNIC_COMMAND_SCAN,
USBD_TRANSFER_DIRECTION_OUT,
type,
interrupt,
(PUCHAR)FirmwareBuffer,
length,
TIMEOUT);
}
return status;
}
////////////////////////////////////////////////////////////////////
// USBNICAdapter::TriggerFirmware()
//
// This routine fires off the hardware to that it starts
// performing as a NIC.
//
// Parameters:
// None
// IRQL:
// PASSIVE_LEVEL
//
// Return Mode:
// SYNCHRONOUS
NTSTATUS USBNICAdapter::TriggerFirmware()
{
NTSTATUS status = STATUS_SUCCESS;
status = ControlCommand (
USBNIC_COMMAND_SCAN,
USBD_TRANSFER_DIRECTION_OUT,
0,
0,
(PUCHAR)trigger_code,
trigger_code_size,
TIMEOUT);
return status;
}
////////////////////////////////////////////////////////////////////
// USBNICAdapter::SetURBSize()
//
// This routine is used to set the size of the URBs that the
// adapter will accept. These URBs will contains bothe packet data
// and configuration parameters.
//
// Parameters:
// urb_size - size for the URB to be accepted by the
// hardware.
//
// IRQL:
// PASSIVE_LEVEL
//
// Return Mode:
// SYNCHRONOUS
NTSTATUS USBNICAdapter::SetURBSize(short urb_size)
{
NTSTATUS status = STATUS_SUCCESS;
status = ControlCommand (
USBNIC_COMMAND_SET_URB_SIZE,
USBD_TRANSFER_DIRECTION_OUT,
urb_size,
0,
NULL,
0,
TIMEOUT);
return status;
}
////////////////////////////////////////////////////////////////////
// USBNICAdapter::SetSOFSWait()
//
// This routine sets the SOFS for the device.
//
// Parameters:
// sofs_wait - specific value to the SOFS
// IRQL:
// PASSIVE_LEVEL
//
// Return Mode:
// SYNCHRONOUS
NTSTATUS USBNICAdapter::SetSOFSWait(short sofs_wait)
{
NTSTATUS status = STATUS_SUCCESS;
status = ControlCommand (
USBNIC_COMMAND_SET_SOFS_WAIT,
USBD_TRANSFER_DIRECTION_OUT,
sofs_wait,
0,
NULL,
0,
TIMEOUT);
return status;
}
////////////////////////////////////////////////////////////////////
// USBNICAdapter::SetReceiveFilter()
//
// This routine converts the NDIS Rx filter values to the
// device specific values.
//
// Parameters:
// Rxfilters - NDIS Rx Filter values
//
// IRQL:
// PASSIVE_LEVEL or DISPATCH_LEVEL
//
// Return Mode:
// SYNCHRONOUS(for PASSIVE) or ASYNCHRONOUS(for DISPATCH)
// Comments:
// During the setOID_GEN_CURRENT_PACKET_FILTER this routine runs
// at DISPATCH_LEVEL. During device configuration this routine runs
// at PASSIVE_LEVEL.
//
NTSTATUS USBNICAdapter::SetReceiveFilter(ULONG Rxfilters)
{
KIRQL kIrql;
NTSTATUS status = STATUS_SUCCESS;
short receive_filters = 0;
if (Rxfilters & NDIS_PACKET_TYPE_FUNCTIONAL)
receive_filters = USBNIC_PACKET_FILTER_DIRECTED |
USBNIC_PACKET_FILTER_BROADCAST |
USBNIC_PACKET_FILTER_MULTICAST |
USBNIC_PACKET_FILTER_PROMISCUOUS |
USBNIC_PACKET_FILTER_ALL_MULTICAST
;
else
{
receive_filters |= Rxfilters & NDIS_PACKET_TYPE_DIRECTED ? USBNIC_PACKET_FILTER_DIRECTED : 0;
receive_filters |= Rxfilters & NDIS_PACKET_TYPE_BROADCAST ? USBNIC_PACKET_FILTER_BROADCAST : 0;
receive_filters |= Rxfilters & NDIS_PACKET_TYPE_MULTICAST ? USBNIC_PACKET_FILTER_MULTICAST : 0;
receive_filters |= Rxfilters & NDIS_PACKET_TYPE_PROMISCUOUS ? USBNIC_PACKET_FILTER_PROMISCUOUS : 0;
receive_filters |= Rxfilters & NDIS_PACKET_TYPE_ALL_MULTICAST ? USBNIC_PACKET_FILTER_ALL_MULTICAST : 0;
}
kIrql = KeGetCurrentIrql();
if (kIrql < DISPATCH_LEVEL)
{
// Pass the URB to the bus driver at PASSIVE level
status = ControlCommand (
USBNIC_COMMAND_SET_PACKET_FILTER,
USBD_TRANSFER_DIRECTION_OUT,
receive_filters,
0,
NULL,
0,
TIMEOUT);
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -