Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

889 lines
22 KiB

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
pc586sft.h
Abstract:
The main header for a PC586 (Local Area Network Controller
Intel pc586) MAC driver.
Author:
Weldon Washburn (o-weldo) creation-date 10-29-90 adapted from...
Anthony V. Ercolano (tonye) creation-date 19-Jun-1990
Environment:
This driver is expected to work in DOS, OS2 and NT at the equivalent
of kernal mode.
Notes:
optional-notes
Revision History:
--*/
#ifndef _PC586SFT_
#define _PC586SFT_
#define PC586_NDIS_MAJOR_VERSION 3
#define PC586_NDIS_MINOR_VERSION 0
//
// ZZZ These macros are peculiar to NT.
//
#define PC586_ALLOC_PHYS(s) ExAllocatePool(NonPagedPool,(s))
#define PC586_FREE_PHYS(s) ExFreePool((s))
#define PC586_MOVE_MEMORY(Destination,Source,Length) RtlMoveMemory(Destination,Source,Length)
#define PC586_ZERO_MEMORY(Destination,Length) RtlZeroMemory(Destination,Length)
// = 6 bytes src addr, 6 dest, 2 length and RCVBUFSIZE (Rbd->RbdSize) data
#define LOOKAHEADBUFFERSIZE (RCVBUFSIZE + 6 + 6 + 2) / 2
//
// This record type is inserted into the MacReserved portion
// of the packet header when the packet is going through the
// staged allocation of buffer space prior to the actual send.
//
typedef struct _PC586_RESERVED {
//
// Points to the next packet in the chain of queued packets
// being allocated, loopbacked, or waiting for the finish
// of transmission.
//
// The packet will either be on the stage list for allocation,
// the loopback list for loopback processing, on an adapter
// wide doubly linked list (see below) for post transmission
// processing.
//
// We always keep the packet on a list so that in case the
// the adapter is closing down or resetting, all the packets
// can easily be located and "canceled".
//
PNDIS_PACKET Next;
//
// This field holds the binding handle of the open binding
// that submitted this packet for send.
//
NDIS_HANDLE MacBindingHandle;
//
// The particular request handle for the send of this packet.
//
NDIS_HANDLE RequestHandle;
//
// The following union elements are adjusted at each stage
// of the allocation. Each union element should only be accessed
// during it's own stage.
//
union _STAGE {
UINT ClearStage;
struct _STAGE1 {
//
// A value of zero indicates that the packet needs
// no adjustment.
//
// A value of 1 means it only requires a small packet.
//
// A value of 2 means it only requires a medium packet.
//
// A value of 3 means it must use a large packet.
//
UINT MinimumBufferRequirements:2;
//
// The number of ndis buffers to copy into the buffer.
//
UINT NdisBuffersToMove:14;
} STAGE1;
struct _STAGE2 {
//
// If TRUE then the packet caused an adapter buffer to
// be allocated.
//
UINT UsedPc586Buffer:1;
//
// If the previous field was TRUE then this gives the
// index into the array of adapter buffer descriptors that
// contains the old packet information.
//
UINT Pc586BuffersIndex:15;
//
// If UsedPc586Buffer is true then this field contains the
// number of *physical* ndis buffers contained in the adapter
// buffer.
//
UINT PhysicalBuffersContained:16;
} STAGE2;
struct _STAGE3 {
//
// If TRUE then the packet caused an adapter buffer to
// be allocated.
//
UINT UsedPc586Buffer:1;
//
// If the previous field was TRUE then this gives the
// index into the array of adapter buffer descriptors that
// contains the old packet information.
//
UINT Pc586BuffersIndex:15;
//
// Gives the index into the ring to packet structure as well
// as the ring descriptors.
//
UINT RingIndex:16;
} STAGE3;
//
// When the packet is submitted to the hardware and/or
// placed on the loopback queue these two fields of the
// union are used.
//
// It is always desired to keep the packet linked on
// one list.
//
// Here's how the fields are used.
//
// If the packet is just going on the hardware transmit
// or it is just going on the loopback then the ReadyToComplete
// flag will be set TRUE immediately. If it is just going on the
// loopback it also sets the status field in stage4 to successful.
//
// In the above situations, if the packet just went on the
// loopback queue, when the packet was finished with loopback
// the code would see that it was ready to complete. It would
// also know that it is in loopback processing. Since the packet
// can only be on one queue at a time it could simply remove
// the packet from the loopback queue and indicate the send
// as complete.
//
// If the packet not going on the loopback queue it would
// be placed on an adapter wide queue. It would use as a
// forward pointer the Next field. As a backward pointer it
// would overlay the stage 4 field with the backward pointer.
// Note that this is safe since no PNDIS_PACKET is ever odd
// byte aligned, and therefore the low bit would always be clear.
//
// We put the packet on a doubly linked list since we could
// never be quite sure of the order that we would remove packets
// from this list. (This will be clear shortly.)
//
// If the packet needs to be transmitted as well as loopbacked
// then the following occurs.
//
// The packets buffers are relinquished to the hardware. At the
// same time the packet is placed on the loopback queue. The
// stage4 field ReadyToComplete is set to false.
//
// If the packet finishes transmission and the ReadyToComplete
// flag is false that means it still hasn't finished loopback
// and therefore is still on the loopback list. The code
// simply sets ReadyToComplete to true and the status of the
// operation to true or false (depending on the result.)
// When that packet does finish loopback it notes that the
// ready to complete is true. It recovers that status from stage
// 4. It can then remove the packet from the loopback list and
// signal completion for that packet.
//
// If the packet finishes transmission and ReadyToComplete is true
// it simply removes it from the doubly linked adapter wide queue
// and signals its completion with the status that has been
// determined in the trasmission complete code.
//
// If the loopback code finishes processing the packet and it finds
// the ReadyToComplete TRUE it simply removes it from the loopback
// list and signals with the saved status in STAGE4.
//
// If the loopback code finishes processing the packet and it finds
// the ReadyToComplete FALSE it simply puts the packet on the adapter
// wide doubly linked list with ReadyToComplete set to TRUE.
//
// The main reason this is a doubly linked list is that there is no
// real way to predict when a packet will finish loopback and no
// real way to predict whether a packet even will be loopbacked.
// With this lack of knowledge, and the fact that the above packets
// may end up on the same list, the packet at the front of that
// list may not be the first packet to complete first. With
// a doubly linked list it is much easier to pull a packet out of
// the middle of that list.
//
struct _STAGE4 {
//
// Under the protection of the transmit queue lock
// this value will be examined by both the loopback
// completion code and the hardware send completion
// code. If either of them find the value to be true
// they will send the transmit complete.
//
// Note that if the packet didn't have to be loopbacked
// or if the packet didn't need to go out on the wire
// the this value will be initialized to true. Otherwise
// this value will be set to false just before it is
// relinquished to the hardware and to the loopback queue.
//
UINT ReadyToComplete:1;
//
// When the hardware send is done this will record whether
// the send was successful or not. It is only used if
// ReadyToComplete is FALSE.
//
// By definition loopback can never fail.
//
UINT SuccessfulTransmit:1;
} STAGE4;
//
// Used as a back pointer in a doubly linked list if the
// packet needs to go on an adapter wide queue to finish
// processing.
//
PNDIS_PACKET BackPointer;
} STAGE;
} PC586_RESERVED,*PPC586_RESERVED;
//
// This macro will return a pointer to the pc586 reserved portion
// of a packet given a pointer to a packet.
//
#define PPC586_RESERVED_FROM_PACKET(Packet) \
((PPC586_RESERVED)((PVOID)(&(Packet)->MacReserved)))
typedef struct _PC586_ADAPTER {
//
// OS Dependant fields of the adapter.
//
//
// Holds the interrupt object for this adapter.
//
KINTERRUPT Interrupt;
//
// Normal processing DPC.
//
KDPC InterruptDPC;
//
// Non OS fields of the adapter.
//
//
// Zero terminated string that holds the name of the particular device
// adapter. This is set at initialization.
//
PSZ DeviceName;
//
// This boolean is used as a gate to ensure that only one thread
// of execution is actually processing interrupts or some other
// source of deferred processing.
//
BOOLEAN DoingProcessing;
//
// The network address from the hardware.
//
UCHAR NetworkAddress[MAC_LENGTH_OF_ADDRESS];
//
// Keeps a reference count on the current number of uses of
// this adapter block. Uses is defined to be the number of
// routines currently within the "external" interface.
//
UINT References;
//
// List head for all open bindings for this adapter.
//
LIST_ENTRY OpenBindings;
//
// List head for all opens that had outstanding references
// when an attempt was made to close them.
//
LIST_ENTRY CloseList;
//
// Spinlock to protect fields in this structure..
//
NDIS_SPIN_LOCK Lock;
//
// Handle given by NDIS when the MAC registered itself.
//
NDIS_HANDLE NdisMacHandle;
//
// Handle given by NDIS when the adapter was registered.
//
NDIS_HANDLE NdisAdapterHandle;
//
// Pointer to the filter database for the MAC.
//
PMAC_FILTER FilterDB;
//
// Pointer to the first packet on the loopback list.
//
// Can only be accessed when the adapter lock
// is held.
//
PNDIS_PACKET FirstLoopBack;
//
// Pointer to the last packet on the loopback list.
//
// Can only be accessed when the adapter lock
// is held.
//
PNDIS_PACKET LastLoopBack;
//
// Pointer to the first transmitting packet that is actually
// sending, or done with the living on the loopback queue.
//
// Can only be accessed when the adapter lock
// is held.
//
PNDIS_PACKET FirstFinishTransmit;
//
// Pointer to the last transmitting packet that is actually
// sending, or done with the living on the loopback queue.
//
// Can only be accessed when the adapter lock
// is held.
//
PNDIS_PACKET LastFinishTransmit;
//
// These fields let the send allocation code know that it's
// futile to even try to move a packet along to that stage.
//
// Stage2 and Stage3 Open would be set to false in StagedAllocation
// and set to true by the interrupt processing code.
//
// Stage4Open could be set to false by any number of routines
// if they wish to close down the sending of packets. It
// would be set to true to turn back sending of packets.
//
// All of the stages would be closed to close a binding
// or to reset the adapter.
//
// These variables can only be accessed when the adapter
// lock is held.
//
BOOLEAN Stage4Open;
BOOLEAN Stage3Open;
BOOLEAN Stage2Open;
BOOLEAN Stage1Open;
//
// These AlreadyProcessingStageX variables are set up to keep
// more than one thread from accessing a particular thread
// a one time.
//
// These variables can only be accessed when the adapter
// lock is held.
//
BOOLEAN AlreadyProcessingStage4;
BOOLEAN AlreadyProcessingStage3;
BOOLEAN AlreadyProcessingStage2;
//
// Pointers to the first and last packets at a particular stage
// of allocation. All packets in transmit are linked
// via there next field.
//
// Can only be accessed when the adapter lock
// is held.
//
PNDIS_PACKET FirstStage1Packet;
PNDIS_PACKET LastStage1Packet;
PNDIS_PACKET FirstStage2Packet;
PNDIS_PACKET LastStage2Packet;
PNDIS_PACKET FirstStage3Packet;
PNDIS_PACKET LastStage3Packet;
//
// Flag that when enabled lets routines know that a reset
// is in progress.
//
BOOLEAN ResetInProgress;
//
// Pointer to the binding that initiated the reset. This
// will be null if the reset is initiated by the MAC itself.
//
struct _PC586_OPEN *ResettingOpen;
//
// RequestHandle of the request that initiated the reset. This
// value is undefined if the reset is initiated by the MAC itself.
//
NDIS_HANDLE ResetRequestHandle;
//
// The type of the request that caused the adapter to reset.
//
NDIS_REQUEST_TYPE ResetRequestType;
USHORT LookaheadBufferNdis [LOOKAHEADBUFFERSIZE];
// The transmit packet that currently "owns" the 586 xmt cmd block
PNDIS_PACKET OwningPacket;
//
// 82586 specific part of PC586_ADAPTER
//
// pointers used in receiveing a packet
PFD BeginFd, EndFd;
PRBD BeginRbd, EndRbd;
// pointers to 82586 control structures
PSCP Scp;
PISCP Iscp;
PSCB Scb;
PCMD Cb;
PTBD Tbd;
PUSHORT CommandBuffer;
//
// pc586 netcard specific part of PC586_ADAPTER
//
PUSHORT CAAddr;
PUSHORT IntAddr;
PUCHAR StaticRam, CmdProm;
} PC586_ADAPTER,*PPC586_ADAPTER;
//
// Given a MacBindingHandle this macro returns a pointer to the
// PC586_ADAPTER.
//
#define PPC586_ADAPTER_FROM_BINDING_HANDLE(Handle) \
(((PPC586_OPEN)((PVOID)(Handle)))->OwningPc586)
//
// Given a MacContextHandle return the PPC586_ADAPTER
// it represents.
//
#define PPC586_ADAPTER_FROM_CONTEXT_HANDLE(Handle) \
((PPC586_ADAPTER)((PVOID)(Handle)))
//
// Given a pointer to a PC586_ADAPTER return the
// proper MacContextHandle.
//
#define CONTEXT_HANDLE_FROM_PPC586_ADAPTER(Ptr) \
((NDIS_HANDLE)((PVOID)(Ptr)))
//
// One of these structures is created on each MacOpenAdapter.
//
typedef struct _PC586_OPEN {
//
// Linking structure for all of the open bindings of a particular
// adapter.
//
LIST_ENTRY OpenList;
//
// The Adapter that requested this open binding.
//
PPC586_ADAPTER OwningPc586;
//
// Index of this adapter in the filter database.
//
UINT FilterIndex;
//
// Given by NDIS when the adapter was opened.
//
NDIS_HANDLE NdisBindingContext;
//
// Counter of all the different reasons that a open binding
// couldn't be closed. This would be incremented each time
// for:
//
// While a particular interface routine is accessing this open
//
// During an indication.
//
// When the open causes a reset.
//
// A packet currently being sent.
//
// (Basically the above two mean any time the open has left
// some processing around to be accomplished later.)
//
// This field should only be accessed when the adapter lock is held.
//
UINT References;
//
// A flag indicating that this binding is in the process of closing.
//
BOOLEAN BindingShuttingDown;
//
// Request handle of the close request for this binding.
//
NDIS_HANDLE CloseHandle;
} PC586_OPEN,*PPC586_OPEN;
//
// This macro returns a pointer to a PPC586_OPEN given a MacBindingHandle.
//
#define PPC586_OPEN_FROM_BINDING_HANDLE(Handle) \
((PPC586_OPEN)((PVOID)Handle))
//
// This macro returns a NDIS_HANDLE from a PPC586_OPEN
//
#define BINDING_HANDLE_FROM_PPC586_OPEN(Open) \
((NDIS_HANDLE)((PVOID)Open))
//
// This macro will act a "epilogue" to every routine in the
// *interface*. It will check whether there any requests needed
// to defer there processing. It will also decrement the reference
// count on the adapter. If the reference count is zero and there
// is deferred work to do it will insert the interrupt processing
// routine in the DPC queue.
//
// Note that we don't need to include checking for blocked receives
// since blocked receives imply that there will eventually be an
// interrupt.
//
// NOTE: This macro assumes that it is called with the lock acquired.
//
// ZZZ This routine is NT specific.
//
#define PC586_DO_DEFERRED(Adapter) \
{ \
PPC586_ADAPTER _A = (Adapter); \
_A->References--; \
if ((!_A->References) && \
(_A->ResetInProgress || \
_A->FirstLoopBack || \
(!IsListEmpty(&_A->CloseList)))) { \
NdisReleaseSpinLock(&_A->Lock); \
KeInsertQueueDpc( \
&_A->InterruptDPC, \
NULL, \
NULL \
); \
} else { \
NdisReleaseSpinLock(&_A->Lock); \
} \
}
//
// This structure is passed as context from the receive interrupt
// processor. Eventually it will be used as a parameter to
// Pc586TransferData. Pc586TransferData can get two kinds of
// context. It will receive either an ndis packet or it will
// receive a PC586_RECEIVE_CONTEXT. It will be able to tell
// the difference since the PC586_RECEIVE_CONTEXT will have
// its low bit set. No pointer to an ndis packet can have its low
// bit set.
//
typedef struct { union {
UINT WholeThing;
UINT FrameDescriptor; } a;
} PC586_RECEIVE_CONTEXT,*PPC586_RECEIVE_CONTEXT;
//
// We define the external interfaces to the pc586 driver.
// These routines are only external to permit separate
// compilation. Given a truely fast compiler they could
// all reside in a single file and be static.
//
extern
NDIS_STATUS
Pc586TransferData(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle,
IN NDIS_HANDLE MacReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer,
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred
);
extern
NDIS_STATUS
Pc586Send(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle,
IN PNDIS_PACKET Packet
);
extern
BOOLEAN
Pc586StartAdapters(
IN NDIS_HANDLE NdisMacHandle
);
extern
VOID
Pc586StagedAllocation(
IN PPC586_ADAPTER Adapter
);
extern
VOID
Pc586CopyFromPacketToBuffer(
IN PNDIS_PACKET Packet,
IN UINT Offset,
IN UINT BytesToCopy,
OUT PCHAR Buffer,
OUT PUINT BytesCopied
);
extern
VOID
Pc586CopyFromPacketToPacket(
IN PNDIS_PACKET Destination,
IN UINT DestinationOffset,
IN UINT BytesToCopy,
IN PNDIS_PACKET Source,
IN UINT SourceOffset,
OUT PUINT BytesCopied
);
extern
VOID
Pc586ProcessLoopback(
IN PPC586_ADAPTER Adapter
);
extern
VOID
Pc586RemovePacketFromLoopBack(
IN PPC586_ADAPTER Adapter
);
extern
VOID
Pc586PutPacketOnLoopBack(
IN PPC586_ADAPTER Adapter,
IN PNDIS_PACKET Packet,
IN BOOLEAN ReadyToComplete
);
extern
VOID
Pc586RemovePacketOnFinishTrans(
IN PPC586_ADAPTER Adapter,
IN PNDIS_PACKET Packet
);
extern
VOID
Pc586PutPacketOnFinishTrans(
IN PPC586_ADAPTER Adapter,
IN PNDIS_PACKET Packet
);
extern
VOID
Pc586HardwareDetails(
IN PPC586_ADAPTER Adapter,
IN PVOID Specific
);
extern
VOID
Pc586StopChip(
IN PPC586_ADAPTER Adapter
);
extern
BOOLEAN
Pc586RegisterAdapter(
IN NDIS_HANDLE NdisMacHandle,
IN PSZ DeviceName,
IN PVOID Pc586BaseHardwareMemoryAddress,
IN CCHAR Pc586InterruptVector,
IN KIRQL Pc586InterruptIrql,
IN UINT MaximumMulticastAddresses,
IN UINT MaximumOpenAdapters,
);
#endif // _PC586SFT_
static
VOID
ReQFd(
IN PPC586_ADAPTER Adapter,
IN PFD Fd
);
static
VOID
RuStart(
IN PPC586_ADAPTER Adapter
);
static
VOID
ShuvWord(
IN PUSHORT VirtAddr,
IN USHORT Value
);
static
USHORT
PullWord(
IN PUSHORT VirtAddr
);
static
VOID
BuildCu(
IN PPC586_ADAPTER Adapter
);
static
VOID
BuildRu(
IN PPC586_ADAPTER Adapter
);
static
BOOLEAN
Diagnose586(
IN PPC586_ADAPTER Adapter
);
static
BOOLEAN
Config586(
IN PPC586_ADAPTER Adapter
);
static
USHORT
PromAddr(
IN PPC586_ADAPTER Adapter,
IN ULONG Index
);
static
VOID
ChanAttn(
IN PPC586_ADAPTER Adapter
);
static
VOID
WaitScb(
IN PPC586_ADAPTER Adapter
);
static
USHORT
VirtToPc586(
IN PPC586_ADAPTER Adapter,
IN PUCHAR KernelVirtAddr
);
static
PUCHAR
Pc586ToVirt(
IN PPC586_ADAPTER Adapter,
IN USHORT Addr586
);
static
VOID
PutPacket(
IN PPC586_ADAPTER Adapter,
IN PFD Fd,
IN UINT PacketLength
);
static
VOID
Pc586IntOn(
IN PPC586_ADAPTER Adapter
);
static
VOID
Pc586IntOff(
IN PPC586_ADAPTER Adapter
);
static
Pc586TimeOut(
IN PDEVICE_OBJECT DeviceObject,
IN PLONG TimerCounter
);
static
VOID
Pc586MoveToHost(
IN PVOID DestinationVirtualAddress,
IN PVOID SourceVirtualAddress,
IN UINT AmountToMove
);
static
VOID
Pc586MoveToAdapter(
IN PVOID DestinationVirtualAddress,
IN PVOID SourceVirtualAddress,
IN UINT AmountToMove
);