blob: 6541993db5c4173581cf0df1dccf124492bad9bb [file]
/*
* b2ether driver -- derived from DDK packet driver sample
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* Windows platform specific code copyright (C) Lauri Pesonen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"
#include "b2ether.h"
#undef DBG
#define DBG 0
#include "debug.h"
static UINT Medium;
static NDIS_MEDIUM MediumArray=NdisMedium802_3;
NTSTATUS PacketOpen( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
/*
This is the dispatch routine for create/open and close requests.
These requests complete successfully.
*/
{
PDEVICE_EXTENSION DeviceExtension;
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
NDIS_STATUS Status;
NDIS_STATUS ErrorStatus;
UINT i;
IF_LOUD(DbgPrint("Packet: OpenAdapter\n");)
DeviceExtension = DeviceObject->DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open = ExAllocatePool(NonPagedPool,sizeof(OPEN_INSTANCE));
if (Open==NULL) {
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory( Open, sizeof(OPEN_INSTANCE) );
// Save or open here
IrpSp->FileObject->FsContext = Open;
Open->DeviceExtension = DeviceExtension;
Open->OpenCloseIrp = Irp;
// Allocate a packet pool for our xmit and receive packets
NdisAllocatePacketPool(
&Status,
&Open->PacketPool,
TRANSMIT_PACKETS,
sizeof(PACKET_RESERVED));
if (Status != NDIS_STATUS_SUCCESS) {
IF_LOUD(DbgPrint("Packet: Failed to allocate packet pool\n");)
ExFreePool(Open);
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
// list to hold irp's want to reset the adapter
InitializeListHead(&Open->ResetIrpList);
// Initialize list for holding pending read requests
KeInitializeSpinLock(&Open->RcvQSpinLock);
InitializeListHead(&Open->RcvList);
// Initialize the request list
KeInitializeSpinLock(&Open->RequestSpinLock);
InitializeListHead(&Open->RequestList);
// link up the request stored in our open block
for ( i=0; i<MAX_REQUESTS; i++ ) {
ExInterlockedInsertTailList(
&Open->RequestList,
&Open->Requests[i].ListElement,
&Open->RequestSpinLock);
}
IoMarkIrpPending(Irp);
Irp->IoStatus.Status = STATUS_PENDING;
// Try to open the MAC
NdisOpenAdapter(
&Status,
&ErrorStatus,
&Open->AdapterHandle,
&Medium,
&MediumArray,
1,
DeviceExtension->NdisProtocolHandle,
Open,
&DeviceExtension->AdapterName,
0,
NULL);
if (Status != NDIS_STATUS_PENDING) {
PacketOpenAdapterComplete( Open, Status, NDIS_STATUS_SUCCESS );
}
return(STATUS_PENDING);
}
VOID PacketOpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
)
{
PIRP Irp;
POPEN_INSTANCE Open;
IF_LOUD(DbgPrint("Packet: OpenAdapterComplete\n");)
Open = (POPEN_INSTANCE)ProtocolBindingContext;
Irp = Open->OpenCloseIrp;
if (Status != NDIS_STATUS_SUCCESS) {
IF_LOUD(DbgPrint("Packet: OpenAdapterComplete-FAILURE\n");)
NdisFreePacketPool(Open->PacketPool);
ExFreePool(Open);
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return;
}
NTSTATUS PacketClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
POPEN_INSTANCE Open;
NDIS_STATUS Status;
PIO_STACK_LOCATION IrpSp;
IF_LOUD(DbgPrint("Packet: CloseAdapter\n");)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open = IrpSp->FileObject->FsContext;
Open->OpenCloseIrp =Irp;
IoMarkIrpPending(Irp);
Irp->IoStatus.Status = STATUS_PENDING;
NdisCloseAdapter( &Status, Open->AdapterHandle );
if (Status != NDIS_STATUS_PENDING) {
PacketCloseAdapterComplete( Open, Status );
}
return(STATUS_PENDING);
}
VOID PacketCloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
POPEN_INSTANCE Open;
PIRP Irp;
IF_LOUD(DbgPrint("Packet: CloseAdapterComplete\n");)
Open = (POPEN_INSTANCE)ProtocolBindingContext;
Irp = Open->OpenCloseIrp;
NdisFreePacketPool(Open->PacketPool);
ExFreePool(Open);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
NTSTATUS PacketCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP FlushIrp
)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PLIST_ENTRY PacketListEntry;
PNDIS_PACKET pPacket;
NDIS_STATUS Status;
IF_LOUD(DbgPrint("Packet: Cleanup\n");)
IrpSp = IoGetCurrentIrpStackLocation(FlushIrp);
Open=IrpSp->FileObject->FsContext;
IoMarkIrpPending(FlushIrp);
FlushIrp->IoStatus.Status = STATUS_PENDING;
//
// The open instance of the device is about to close
// We need to complete all pending Irp's
// First we complete any pending read requests
//
while ((PacketListEntry=ExInterlockedRemoveHeadList(
&Open->RcvList,
&Open->RcvQSpinLock
)) != NULL) {
IF_LOUD(DbgPrint("Packet: CleanUp - Completeing read\n");)
pPacket=CONTAINING_RECORD(PacketListEntry,NDIS_PACKET,ProtocolReserved);
// complete normally
PacketTransferDataComplete(
Open,
pPacket,
NDIS_STATUS_SUCCESS,
0
);
}
// IoMarkIrpPending(FlushIrp);
// FlushIrp->IoStatus.Status = STATUS_PENDING;
// We now place the Irp on the Reset list
ExInterlockedInsertTailList(
&Open->ResetIrpList,
&FlushIrp->Tail.Overlay.ListEntry,
&Open->RequestSpinLock);
// Now reset the adapter, the mac driver will complete any
// pending requests we have made to it.
NdisReset( &Status, Open->AdapterHandle );
if (Status != NDIS_STATUS_PENDING) {
IF_LOUD(DbgPrint("Packet: Cleanup - ResetComplte being called\n");)
PacketResetComplete( Open, Status );
}
return(STATUS_PENDING);
}
VOID PacketResetComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
POPEN_INSTANCE Open;
PIRP Irp;
PLIST_ENTRY ResetListEntry;
IF_LOUD(DbgPrint("Packet: PacketResetComplte\n");)
Open = (POPEN_INSTANCE)ProtocolBindingContext;
// remove the reset IRP from the list
ResetListEntry=ExInterlockedRemoveHeadList(
&Open->ResetIrpList,
&Open->RequestSpinLock
);
#if DBG
if (ResetListEntry == NULL) {
DbgBreakPoint();
return;
}
#endif
Irp = CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IF_LOUD(DbgPrint("Packet: PacketResetComplte exit\n");)
}