windows-nt/Source/XPSP1/NT/net/irda/samples/nscirda/request.c
2020-09-26 16:20:57 +08:00

423 lines
12 KiB
C

/*
************************************************************************
*
* REQUEST.c
*
*
* (C) Copyright 1996 National Semiconductor Corp.
* (C) Copyright 1996 Microsoft Corp.
*
*
* (ep)
*
*************************************************************************
*/
#include "nsc.h"
#include "newdong.h"
const NDIS_OID NSCGlobalSupportedOids[] = {
OID_GEN_SUPPORTED_LIST,
OID_GEN_HARDWARE_STATUS,
OID_GEN_MEDIA_SUPPORTED,
OID_GEN_MEDIA_IN_USE,
OID_GEN_MAXIMUM_LOOKAHEAD,
OID_GEN_MAXIMUM_FRAME_SIZE,
OID_GEN_MAXIMUM_SEND_PACKETS,
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_MAC_OPTIONS,
OID_GEN_PROTOCOL_OPTIONS,
OID_GEN_LINK_SPEED,
OID_GEN_TRANSMIT_BUFFER_SPACE,
OID_GEN_RECEIVE_BUFFER_SPACE,
OID_GEN_TRANSMIT_BLOCK_SIZE,
OID_GEN_RECEIVE_BLOCK_SIZE,
OID_GEN_VENDOR_DESCRIPTION,
OID_GEN_VENDOR_DRIVER_VERSION,
OID_GEN_DRIVER_VERSION,
OID_GEN_CURRENT_PACKET_FILTER,
OID_GEN_CURRENT_LOOKAHEAD,
OID_GEN_MEDIA_CONNECT_STATUS,
OID_IRDA_RECEIVING,
OID_IRDA_SUPPORTED_SPEEDS,
OID_IRDA_LINK_SPEED,
OID_IRDA_MEDIA_BUSY,
OID_IRDA_TURNAROUND_TIME,
OID_IRDA_MAX_RECEIVE_WINDOW_SIZE,
OID_IRDA_EXTRA_RCV_BOFS,
OID_IRDA_MAX_SEND_WINDOW_SIZE
};
//////////////////////////////////////////////////////////////////////////
// //
// Function: MiniportQueryInformation //
// //
// Description: //
// Query the capabilities and status of the miniport driver. //
// //
//////////////////////////////////////////////////////////////////////////
NDIS_STATUS MiniportQueryInformation (
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWritten,
OUT PULONG BytesNeeded)
{
NDIS_STATUS result = NDIS_STATUS_SUCCESS;
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
INT i, speeds, speedSupported;
UINT *infoPtr;
NDIS_MEDIUM Medium = NdisMediumIrda;
ULONG GenericUlong;
PVOID SourceBuffer = (PVOID) (&GenericUlong);
ULONG SourceLength = sizeof(ULONG);
ULONG BaudRateTable[NUM_BAUDRATES];
switch (Oid){
case OID_GEN_SUPPORTED_LIST:
SourceBuffer = (PVOID) (NSCGlobalSupportedOids);
SourceLength = sizeof(NSCGlobalSupportedOids);
break;
case OID_GEN_HARDWARE_STATUS:
GenericUlong = thisDev->hardwareStatus;
break;
case OID_GEN_MEDIA_SUPPORTED:
case OID_GEN_MEDIA_IN_USE:
SourceBuffer = (PVOID) (&Medium);
SourceLength = sizeof(NDIS_MEDIUM);
break;
case OID_IRDA_RECEIVING:
DBGOUT(("MiniportQueryInformation(OID_IRDA_RECEIVING)"));
GenericUlong = (ULONG)thisDev->nowReceiving;
break;
case OID_IRDA_SUPPORTED_SPEEDS:
DBGOUT(("MiniportQueryInformation(OID_IRDA_SUPPORTED_SPEEDS)"));
speeds = thisDev->portInfo.hwCaps.supportedSpeedsMask &
thisDev->AllowedSpeedMask &
ALL_IRDA_SPEEDS;
for (i = 0, infoPtr = (PUINT)BaudRateTable, SourceLength=0;
(i < NUM_BAUDRATES) && speeds;
i++){
if (supportedBaudRateTable[i].ndisCode & speeds){
*infoPtr++ = supportedBaudRateTable[i].bitsPerSec;
SourceLength += sizeof(UINT);
speeds &= ~supportedBaudRateTable[i].ndisCode;
DBGOUT((" - supporting speed %d bps", supportedBaudRateTable[i].bitsPerSec));
}
}
SourceBuffer = (PVOID) BaudRateTable;
break;
case OID_GEN_LINK_SPEED:
// The maximum speed of NIC is 4Mbps
GenericUlong = 40000; // 100bps increments
break;
case OID_IRDA_LINK_SPEED:
DBGOUT(("MiniportQueryInformation(OID_IRDA_LINK_SPEED)"));
if (thisDev->linkSpeedInfo){
GenericUlong = (ULONG)thisDev->linkSpeedInfo->bitsPerSec;
}
else {
GenericUlong = DEFAULT_BAUD_RATE;
}
break;
case OID_IRDA_MEDIA_BUSY:
DBGOUT(("MiniportQueryInformation(OID_IRDA_MEDIA_BUSY)"));
GenericUlong = (UINT)thisDev->mediaBusy;
break;
case OID_GEN_CURRENT_LOOKAHEAD:
case OID_GEN_MAXIMUM_LOOKAHEAD:
DBGOUT(("MiniportQueryInformation(OID_GEN_MAXIMUM_LOOKAHEAD)"));
GenericUlong = MAX_I_DATA_SIZE;
break;
case OID_GEN_MAXIMUM_TOTAL_SIZE:
case OID_GEN_TRANSMIT_BLOCK_SIZE:
case OID_GEN_RECEIVE_BLOCK_SIZE:
case OID_GEN_MAXIMUM_FRAME_SIZE:
DBGOUT(("MiniportQueryInformation(OID_GEN_MAXIMUM_LOOKAHEAD)"));
// Normally there's some difference in these values, based on the
// MAC header, but IrDA doesn't have one.
GenericUlong = MAX_I_DATA_SIZE;
break;
case OID_GEN_RECEIVE_BUFFER_SPACE:
case OID_GEN_TRANSMIT_BUFFER_SPACE:
GenericUlong = (ULONG) (MAX_IRDA_DATA_SIZE * 8);
break;
case OID_GEN_MAC_OPTIONS:
DBGOUT(("MiniportQueryInformation(OID_GEN_MAC_OPTIONS)"));
GenericUlong = 0;
break;
case OID_GEN_MAXIMUM_SEND_PACKETS:
DBGOUT(("MiniportQueryInformation(OID_GEN_MAXIMUM_SEND_PACKETS)"));
GenericUlong = 16;
break;
case OID_IRDA_TURNAROUND_TIME:
// Indicate the amount of time that the transceiver needs
// to recuperate after a send.
DBGOUT(("MiniportQueryInformation(OID_IRDA_TURNAROUND_TIME)"));
GenericUlong =
(ULONG)thisDev->portInfo.hwCaps.turnAroundTime_usec;
break;
case OID_IRDA_EXTRA_RCV_BOFS:
// Pass back the number of _extra_ BOFs to be prepended
// to packets sent to this unit at 115.2 baud, the
// maximum Slow IR speed. This will be scaled for other
// speed according to the table in the
// Infrared Extensions to NDIS' spec.
DBGOUT(("MiniportQueryInformation(OID_IRDA_EXTRA_RCV_BOFS)"));
GenericUlong = (ULONG)thisDev->portInfo.hwCaps.extraBOFsRequired;
break;
case OID_GEN_CURRENT_PACKET_FILTER:
DBGOUT(("MiniportQueryInformation(OID_GEN_CURRENT_PACKET_FILTER)"));
GenericUlong = NDIS_PACKET_TYPE_PROMISCUOUS;
break;
case OID_IRDA_MAX_RECEIVE_WINDOW_SIZE:
DBGOUT(("MiniportQueryInformation(OID_IRDA_MAX_RECEIVE_WINDOW_SIZE)"));
GenericUlong = MAX_RX_PACKETS;
//GenericUlong = 1;
break;
case OID_GEN_VENDOR_DESCRIPTION:
SourceBuffer = (PVOID)"NSC Infrared Port";
SourceLength = 18;
break;
case OID_GEN_VENDOR_DRIVER_VERSION:
// This value is used to know whether to update driver.
GenericUlong = (NSC_MAJOR_VERSION << 16) +
(NSC_MINOR_VERSION << 8) +
NSC_LETTER_VERSION;
break;
case OID_GEN_DRIVER_VERSION:
GenericUlong = (NDIS_MAJOR_VERSION << 8) + NDIS_MINOR_VERSION;
SourceLength = 2;
break;
case OID_IRDA_MAX_SEND_WINDOW_SIZE:
GenericUlong = 7;
break;
case OID_GEN_MEDIA_CONNECT_STATUS:
GenericUlong = (ULONG) NdisMediaStateConnected;
break;
default:
DBGERR(("MiniportQueryInformation(%d=0x%x), unsupported OID", Oid, Oid));
result = NDIS_STATUS_NOT_SUPPORTED;
break;
}
if (result == NDIS_STATUS_SUCCESS) {
if (SourceLength > InformationBufferLength) {
*BytesNeeded = SourceLength;
result = NDIS_STATUS_INVALID_LENGTH;
}
else {
*BytesNeeded = 0;
*BytesWritten = SourceLength;
NdisMoveMemory(InformationBuffer, SourceBuffer, SourceLength);
}
}
DBGOUT(("MiniportQueryInformation succeeded (info <- %d)", *(UINT *)InformationBuffer));
return result;
}
//////////////////////////////////////////////////////////////////////////
// //
// Function: MiniportSetInformation //
// //
// Description: //
// Allow other layers of the network software (e.g., a transport //
// driver) to control the miniport driver by changing information that //
// the miniport driver maintains in its OIDs, such as the packet //
// or multicast addresses. //
// //
//////////////////////////////////////////////////////////////////////////
NDIS_STATUS MiniportSetInformation (
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded)
{
NDIS_STATUS result = NDIS_STATUS_SUCCESS;
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
UINT i,speedSupported;
const baudRateInfo * CurrentLinkSpeed;
if (InformationBufferLength >= sizeof(UINT)){
UINT info = *(UINT *)InformationBuffer;
*BytesRead = sizeof(UINT);
*BytesNeeded = 0;
switch (Oid){
case OID_IRDA_LINK_SPEED:
DBGOUT(("MiniportSetInformation(OID_IRDA_LINK_SPEED, %xh)",
info));
result = NDIS_STATUS_INVALID_DATA;
CurrentLinkSpeed=thisDev->linkSpeedInfo;
// Find the appropriate speed and set it
speedSupported = NUM_BAUDRATES;
for (i = 0; i < speedSupported; i++){
if (supportedBaudRateTable[i].bitsPerSec == info){
thisDev->linkSpeedInfo = &supportedBaudRateTable[i];
result = NDIS_STATUS_SUCCESS;
break;
}
}
if (result == NDIS_STATUS_SUCCESS){
if (CurrentLinkSpeed != thisDev->linkSpeedInfo) {
//
// different from the current
//
BOOLEAN DoItNow=TRUE;
NdisAcquireSpinLock(&thisDev->QueueLock);
if (!IsListEmpty(&thisDev->SendQueue)){
//
// packets queued, change after this one
//
thisDev->lastPacketAtOldSpeed = CONTAINING_RECORD(thisDev->SendQueue.Blink,
NDIS_PACKET,
MiniportReserved);
DBGOUT(("delaying set-speed because send pkts queued"));
DoItNow=FALSE;
} else {
//
// no packets in the queue
//
if (thisDev->CurrentPacket != NULL) {
//
// the current packet is the only one
//
thisDev->lastPacketAtOldSpeed=thisDev->CurrentPacket;
thisDev->setSpeedAfterCurrentSendPacket = TRUE;
DBGOUT(("delaying set-speed because send pkts queued"));
DoItNow=FALSE;
}
}
if (DoItNow) {
if (!SetSpeed(thisDev)){
result = NDIS_STATUS_FAILURE;
}
thisDev->TransmitIsIdle=FALSE;
}
NdisReleaseSpinLock(&thisDev->QueueLock);
if (DoItNow) {
ProcessSendQueue(thisDev);
}
}
}
else {
*BytesRead = 0;
*BytesNeeded = 0;
}
break;
case OID_IRDA_MEDIA_BUSY:
DBGOUT(("MiniportSetInformation(OID_IRDA_MEDIA_BUSY, %xh)",
info));
// The protocol can use this OID to reset the busy field
// in order to check it later for intervening activity.
//
thisDev->mediaBusy = (BOOLEAN)info;
InterlockedExchange(&thisDev->RxInterrupts,0);
result = NDIS_STATUS_SUCCESS;
break;
case OID_GEN_CURRENT_PACKET_FILTER:
DBGOUT(
("MiniportSetInformation(OID_GEN_CURRENT_PACKET_FILTER, %xh)",
info));
result = NDIS_STATUS_SUCCESS;
break;
case OID_GEN_CURRENT_LOOKAHEAD:
result = (info<=MAX_I_DATA_SIZE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_INVALID_LENGTH;
break;
// We don't support these
//
case OID_IRDA_RATE_SNIFF:
case OID_IRDA_UNICAST_LIST:
// These are query-only parameters.
//
case OID_IRDA_SUPPORTED_SPEEDS:
case OID_IRDA_MAX_UNICAST_LIST_SIZE:
case OID_IRDA_TURNAROUND_TIME:
default:
DBGERR(("MiniportSetInformation(OID=%d=0x%x, value=%xh) - unsupported OID", Oid, Oid, info));
*BytesRead = 0;
*BytesNeeded = 0;
result = NDIS_STATUS_NOT_SUPPORTED;
break;
}
}
else {
*BytesRead = 0;
*BytesNeeded = sizeof(UINT);
result = NDIS_STATUS_INVALID_LENGTH;
}
DBGOUT(("MiniportSetInformation succeeded"));
return result;
}