mirror of https://github.com/lianthony/NT4.0
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.
567 lines
13 KiB
567 lines
13 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
macndis.c
|
|
|
|
Abstract:
|
|
|
|
This is the mac ndis file for the Ungermann Bass Ethernet Controller.
|
|
This driver conforms to the NDIS 3.0 interface.
|
|
|
|
|
|
This driver currently supports three UB Network cards.
|
|
|
|
NIUpc -- Old 16-bit long cards
|
|
256k of on board memory
|
|
jumpers to set i/o base, memory window, interrupt level
|
|
Memory window size is 32k
|
|
|
|
NIUpc/EOTP -- New short 16-bit cards
|
|
512k of memory
|
|
i/o base set by jumpers
|
|
Interrupt level, memory window base and size software
|
|
configurable
|
|
Memory window size is 16k, 32k
|
|
|
|
NIUps -- Basically an MCA EOTP card.
|
|
512k of memory
|
|
i/o base, interrupt level, memory window determined
|
|
by MCA POS mechanism
|
|
Memory window size is 16k, 32k, 64k
|
|
|
|
All of the UB card are composed of an 80186 and an Intel 82586 lan
|
|
coprocessor.
|
|
|
|
The Download code that is copied to the card and run is a slightly
|
|
modified version of the down load code from UB NDIS 2.01 driver.
|
|
|
|
This download load code was basically designed to the least common
|
|
denominator of there older net cards. It only makes use of 128k
|
|
of the cards memory no matter what type of card.
|
|
|
|
The card memory is laided out as a 64k data segment and 64k code segment
|
|
The data segment is further divided into to parts. The lower 32k
|
|
of the data segment holds all of the receive buffers and receive buffer
|
|
descriptors. It also holds various statistics for ease of access.
|
|
The upper 32k is used to store various items of which the ring buffers
|
|
are of primary interest. If the Memory window size is 16k then only
|
|
the first 16k of both 32k halfs is used.
|
|
|
|
The code segment holds the all of the download code. The remainder of
|
|
the 64k (~48k) is used for the transmit buffers.
|
|
|
|
The i/o register of most interest is the map register. This register
|
|
is at offset 0 from the I/O base. The register has three functions.
|
|
1) The upper 6 bits of this register determines which section
|
|
of the cards memory is currently viewable in the memory window.
|
|
|
|
2) Bit #1 is used to enable and disable interrupts from the card.
|
|
This bit is also used to clear and interrupt from the card.
|
|
In order to clear and interrupt, the bit must be set to zero and
|
|
the set 1. This little fact is what makes things interresting
|
|
in handling interrupts. To dismiss the interrupt you must write
|
|
some value to this port, But this port also controls the window
|
|
map so you need to be careful about just what you write to this
|
|
port. On the old 16-bit card this port is not readable.
|
|
Obviously bad things would happen on an MP if one processor
|
|
set the map to one thing and second came along and set it to
|
|
something else. Spin locks will work to protect the port
|
|
for normal accesses, but they can not be used to protect it from
|
|
access from the ISR which must clear the interrupt.
|
|
|
|
I had originally planned to not do anything in the ISR and let
|
|
the DPC handle clearing the interrupt. This works fine on
|
|
the NON-MCA cards, but this one is LEVEL TRIGGERED so I need
|
|
to clear the interrupt by writing something to the port in the ISR.
|
|
|
|
The way I have currently implemented this is to only have the
|
|
reeceive window mapped in when interrupts are enabled. I do this
|
|
by disabling interrupts from the card and clearing the interrupt
|
|
in the ISR and returning. Now when the DPC runs it knows that
|
|
interrutps are disabled, and can change the map port as it wishes.
|
|
The code call by protocols to handle request does not ever
|
|
access any thing that is not in the receive page.
|
|
|
|
3) Bit #0 is used to reset the card. Setting this bit resets the card.
|
|
This bit reamins 0 except during init.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Author:
|
|
|
|
Sanjeev Katariya (sanjeevk) 03-05-92
|
|
|
|
Environment:
|
|
|
|
Kernel Mode Operating Systems : NT and other lesser OS's(dos)
|
|
|
|
Revision History:
|
|
|
|
Brian Lieuallen BrianLie 07/21/92
|
|
Made it work.
|
|
|
|
Brian Lieuallen BrianLie 12/15/93
|
|
Made it a mini-port
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#include <ndis.h>
|
|
#include <efilter.h>
|
|
|
|
#include "niudata.h"
|
|
#include "debug.h"
|
|
|
|
#include "ubhard.h"
|
|
#include "ubsoft.h"
|
|
#include "ubnei.h"
|
|
|
|
#include "map.h"
|
|
|
|
//
|
|
// This constant is used for places where NdisAllocateMemory
|
|
// needs to be called and the HighestAcceptableAddress does
|
|
// not matter.
|
|
//
|
|
|
|
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
|
|
NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
UbneiAddressChangeAction(
|
|
IN UINT NewFilterCount,
|
|
IN PUCHAR NewAddresses,
|
|
IN NDIS_HANDLE MacBindingHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when a particular filter
|
|
class is first used or last cleared.
|
|
|
|
NOTE: This routine assumes that it is called with the lock
|
|
acquired.
|
|
|
|
Arguments:
|
|
|
|
|
|
NewFilterCount - The number of addresses that should now be on the card.
|
|
|
|
NewAddresses - A list of addresses that should be put on the card.
|
|
|
|
MacBindingHandle - The context value returned by the MAC when the
|
|
adapter was opened. In reality, it is a pointer to ELNKII_OPEN.
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PUBNEI_ADAPTER pAdapt = MacBindingHandle;
|
|
|
|
|
|
//
|
|
// Holds the status that should be returned to the filtering package.
|
|
//
|
|
NDIS_STATUS StatusOfAdd;
|
|
IF_REQ_LOUD(DbgPrint("UBNEI: AddressChangeAction called\n");)
|
|
|
|
|
|
if (NIU_SET_MULTICAST_LIST(pAdapt,
|
|
ChangeAddressDPC,
|
|
(PUCHAR)NewAddresses,
|
|
(USHORT)NewFilterCount
|
|
)) {
|
|
|
|
StatusOfAdd=NDIS_STATUS_PENDING;
|
|
} else {
|
|
//
|
|
// The adapter has failed, It doesn't really matter
|
|
// what we return since the card has stopped working
|
|
//
|
|
StatusOfAdd=NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
|
|
|
|
return StatusOfAdd;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
ChangeAddressDPC(
|
|
IN NDIS_STATUS Status,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when the NIU completes a multicast or filter
|
|
change request. It in turn completes the pended request from the protocol
|
|
|
|
Arguments:
|
|
|
|
Context is actually a pointer to the an NDIS_REQUEST
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PUBNEI_ADAPTER pAdapter=Context;
|
|
|
|
IF_REQ_LOUD (DbgPrint("FilterActionDPC called\n");)
|
|
|
|
NdisMSetInformationComplete(
|
|
pAdapter->NdisAdapterHandle,
|
|
Status
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
DummyDPC(
|
|
IN NDIS_STATUS status,
|
|
IN PVOID pContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when the NIU completes a request and nothing
|
|
needs to be completed to a protocol. This routine is passed as the
|
|
callback address passed to filter functions during a close and also
|
|
used during a Reset which is restarting the adapter.
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
IF_REQ_LOUD (DbgPrint("UBNEI: DummyDPC called for filter action routine called at close\n");)
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
UbneiFilterChangeAction(
|
|
IN UINT NewFilterClasses,
|
|
IN NDIS_HANDLE MacBindingHandle
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when an address is added to
|
|
the filter that wasn't referenced by any other open binding.
|
|
|
|
NOTE: This routine assumes that it is called with the lock
|
|
acquired.
|
|
|
|
Arguments:
|
|
|
|
OldFilterClasses - A bit mask that is currently on the card telling
|
|
which packet types to accept.
|
|
|
|
NewFilterClasses - A bit mask that should be put on the card telling
|
|
which packet types to accept.
|
|
|
|
MacBindingHandle - The context value returned by the MAC when the
|
|
adapter was opened. In reality, it is a pointer to ELNKII_OPEN.
|
|
|
|
NdisRequest - The NDIS_REQUEST which submitted the filter change command.
|
|
|
|
Set - A flag telling if the command is a result of a close or not.
|
|
|
|
Return Value:
|
|
|
|
Status of the change (successful or pending).
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PUBNEI_ADAPTER pAdapt = MacBindingHandle;
|
|
USHORT NewFilter=0;
|
|
|
|
//
|
|
// Holds the status that should be returned to the filtering package.
|
|
//
|
|
NDIS_STATUS StatusOfAdd;
|
|
IF_REQ_LOUD(DbgPrint("UBNEI: FilterChangeAction called\n");)
|
|
|
|
if (NewFilterClasses & ~(NDIS_PACKET_TYPE_DIRECTED |
|
|
NDIS_PACKET_TYPE_MULTICAST |
|
|
NDIS_PACKET_TYPE_ALL_MULTICAST |
|
|
NDIS_PACKET_TYPE_BROADCAST |
|
|
NDIS_PACKET_TYPE_PROMISCUOUS )) {
|
|
|
|
IF_REQ_LOUD(DbgPrint("UBNEI: Stupid protocol set bogus filter\n");)
|
|
return NDIS_STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
if (NewFilterClasses & ( NDIS_PACKET_TYPE_DIRECTED |
|
|
NDIS_PACKET_TYPE_MULTICAST
|
|
)) {
|
|
|
|
NewFilter|=0x0001;
|
|
}
|
|
|
|
if (NewFilterClasses & NDIS_PACKET_TYPE_BROADCAST) {
|
|
NewFilter|=0x0002;
|
|
}
|
|
|
|
//
|
|
// 82586 does not support all multicast so we set to promiscuous
|
|
//
|
|
|
|
if (NewFilterClasses & NDIS_PACKET_TYPE_ALL_MULTICAST) {
|
|
NewFilter|=0x0007;
|
|
}
|
|
|
|
if (NewFilterClasses & NDIS_PACKET_TYPE_PROMISCUOUS) {
|
|
NewFilter|=0x0007;
|
|
}
|
|
|
|
|
|
|
|
pAdapt->PacketFilter=NewFilter;
|
|
|
|
|
|
if (NIU_SET_FILTER(pAdapt,
|
|
ChangeAddressDPC,
|
|
NewFilter)) {
|
|
|
|
|
|
StatusOfAdd=NDIS_STATUS_PENDING;
|
|
} else {
|
|
//
|
|
// The adapter has failed, It doesn't really matter
|
|
// what we return since the card has stopped working
|
|
//
|
|
StatusOfAdd=NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
|
|
|
|
return StatusOfAdd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
UbneiCheckForHang(
|
|
IN NDIS_HANDLE Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
DeferredContext - will be a pointer to the adapter block
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PUBNEI_ADAPTER pAdapter = ((PUBNEI_ADAPTER)Context);
|
|
|
|
PLOWNIUDATA pRcvDWindow = (PLOWNIUDATA) pAdapter->pCardRam;
|
|
|
|
UCHAR InterruptActive;
|
|
|
|
|
|
// IF_LOG('w');
|
|
|
|
if (!pAdapter->WaitingForDPC) {
|
|
//
|
|
// We are not waiting on a DPC
|
|
//
|
|
ASSERT_RECEIVE_WINDOW( pAdapter);
|
|
|
|
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&InterruptActive,&(pRcvDWindow->InterruptActive));
|
|
|
|
if (InterruptActive != 0) {
|
|
//
|
|
// The card has generated an interrupt
|
|
//
|
|
if (pAdapter->WakeUpState==0) {
|
|
//
|
|
// This is first time here
|
|
//
|
|
pAdapter->DpcHasRun=FALSE;
|
|
|
|
pAdapter->WakeUpState=1;
|
|
|
|
} else {
|
|
//
|
|
// This is the second time in here, check to see if the DPC ran
|
|
//
|
|
if (pAdapter->DpcHasRun) {
|
|
//
|
|
// The dpc has run so things must be ok
|
|
//
|
|
pAdapter->WakeUpState=0;
|
|
|
|
} else {
|
|
//
|
|
// The dpc has not run, ask the card to do it again.
|
|
//
|
|
IF_LOUD(DbgPrint("UBNEI: CheckForHang: Lost an interrupt?!?\n");)
|
|
|
|
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pRcvDWindow->InterruptActive), 0x0);
|
|
|
|
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pRcvDWindow->HostWantsInterrupt), 0xFF);
|
|
|
|
pAdapter->WakeUpState=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// The has not generated an interrupt
|
|
//
|
|
pAdapter->WakeUpState=0;
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// A dpc is pending
|
|
//
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
UbneiReset(
|
|
OUT PBOOLEAN AddressResetting,
|
|
IN NDIS_HANDLE MacBindingHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
NDIS function.
|
|
|
|
Arguments:
|
|
|
|
See NDIS 3.0 spec.
|
|
|
|
--*/
|
|
|
|
{
|
|
PUBNEI_ADAPTER pAdapter = ((PUBNEI_ADAPTER)MacBindingHandle);
|
|
|
|
IF_INIT_LOUD(DbgPrint("UbneiReset() Called\n");)
|
|
|
|
NIU_RESET_ADAPTER(
|
|
pAdapter,
|
|
ResetAdapterDPC
|
|
);
|
|
|
|
*AddressResetting=FALSE;
|
|
|
|
return NDIS_STATUS_PENDING;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
ResetAdapterDPC(
|
|
IN NDIS_STATUS status,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when the NIU completes a request and nothing
|
|
needs to be completed to a protocol. This routine is passed as the
|
|
callback address passed to filter functions during a close and also
|
|
used during a Reset which is restarting the adapter.
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PUBNEI_ADAPTER pAdapter = ((PUBNEI_ADAPTER)Context);
|
|
|
|
IF_INIT_LOUD (DbgPrint("Ubnei: ResetAdapterDpc\n");)
|
|
|
|
NdisMResetComplete(
|
|
pAdapter->NdisAdapterHandle,
|
|
NDIS_STATUS_SUCCESS,
|
|
FALSE
|
|
);
|
|
|
|
return;
|
|
|
|
}
|