📄 ezloader.c
字号:
//////////////////////////////////////////////////////////////////////
//
// File: ezloader.c
// $Archive: /USB/Drivers/ezloader/ezloader.c $
//
// Purpose:
// driver for downloading firmware to pre-renumerated ezusb devices.
//
// Note:
// derived from ezusbsys.c ver 15
// Environment:
// kernel mode
//
// $Author: Mdn $
//
// $History: ezloader.c $
//
// ***************** Version 2 *****************
// User: Mdn Date: 7/19/01 Time: 10:32a
// Updated in $/USB/Drivers/ezloader
// added support for FX2 - specifically, modified the 8051 reset code so
// it will work with both EZ-USB and FX2
//
// ***************** Version 1 *****************
// User: Tpm Date: 6/09/00 Time: 6:30p
// Created in $/USB/Drivers/ezloader
//
// ***************** Version 7 *****************
// User: Markm Date: 4/12/99 Time: 1:17p
// Updated in $/EzUsb/Drivers/ezloader
//
// ***************** Version 6 *****************
// User: Markm Date: 4/12/99 Time: 1:16p
// Updated in $/EzUsb/Drivers/ezloader
//
// ***************** Version 5 *****************
// User: Markm Date: 4/12/99 Time: 1:00p
// Updated in $/EzUsb/Drivers/ezloader
// minor changes to get rid of compiler warnings.
//
// ***************** Version 4 *****************
// User: Markm Date: 3/26/99 Time: 2:59p
// Updated in $/EzUsb/Drivers/ezloader
// Fixed a bug in the surprise removal code I just added. I was returning
// from the PnP dispatch function without unlocking the device object.
//
// ***************** Version 3 *****************
// User: Markm Date: 3/25/99 Time: 2:05p
// Updated in $/EzUsb/Drivers/ezloader
// Added code to allow unplugs (surprise removal) under NT5 without
// notifying the user.
//
// ***************** Version 2 *****************
// User: Markm Date: 4/10/98 Time: 2:06p
// Updated in $/EZUSB/ezloader
// modified to download intel hex records and to download the loader
// firmware for downloading to external RAM
//
// ***************** Version 1 *****************
// User: Markm Date: 2/24/98 Time: 5:26p
// Created in $/EZUSB/ezloader
//
//
// Copyright (c) 1997 Anchor Chips, Inc. May not be reproduced without
// permission. See the license agreement for more details.
//
//////////////////////////////////////////////////////////////////////
//
// Include files needed for WDM driver support
//
#include <wdm.h>
#include "stdarg.h"
#include "stdio.h"
//
// Include files needed for USB support
//
#include "usbdi.h"
#include "usbdlib.h"
//
// Include file for the Ezusb Device
//
#include "ezloader.h"
//
// this file contains an image of the device firmware
//
extern INTEL_HEX_RECORD firmware[];
extern INTEL_HEX_RECORD loader[];
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Arguments:
DriverObject - pointer to the driver object
RegistryPath - pointer to a unicode string representing the path
to driver-specific key in the registry
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
Ezusb_KdPrint (("entering (Ezusb) DriverEntry (Build: %s/%s\n",__DATE__,__TIME__));
DriverObject->DriverUnload = Ezusb_Unload;
//
// POWER and PNP IRPs go to the same dispatch function. Under
// Win95, there is just a single IRP for both, called
// IRP_MJ_PNP_POWER. This is assigned the same value as
// IRP_MJ_PNP has under Win98 and NT5. I'm only concerned
// with basic PNP stuff, like START and REMOVE. All other
// PNP and POWER IRPs will simply be passed down the driver
// stack. This driver won't be around like enough to worry
// about POWER IRPs. That is, as soon as code is downloaded
// to the device, the device will remove itself and the driver
// will go away.
//
DriverObject->MajorFunction[IRP_MJ_PNP] =
DriverObject->MajorFunction[IRP_MJ_POWER] = Ezusb_DispatchPnp;
DriverObject->DriverExtension->AddDevice = Ezusb_PnPAddDevice;
Ezusb_KdPrint (("exiting (Ezusb) DriverEntry (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
Ezusb_DefaultPnpHandler(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
{
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(pdx->StackDeviceObject, Irp);
}
///////////////////////////////////////////////////////////////////////////////
// @func Handle completion of a request by a lower-level driver
// @parm Functional device object
// @parm I/O request which has completed
// @parm Context argument supplied to IoSetCompletionRoutine, namely address of
// KEVENT object on which ForwardAndWait is waiting
// @comm This is the completion routine used for requests forwarded by ForwardAndWait. It
// sets the event object and thereby awakens ForwardAndWait.
// @comm Note that it's *not* necessary for this particular completion routine to test
// the PendingReturned flag in the IRP and then call IoMarkIrpPending. You do that in many
// completion routines because the dispatch routine can't know soon enough that the
// lower layer has returned STATUS_PENDING. In our case, we're never going to pass a
// STATUS_PENDING back up the driver chain, so we don't need to worry about this.
NTSTATUS
OnRequestComplete(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PKEVENT pev
)
/*++
Routine Description:
Handle completion of a request by a lower-level driver
Arguments:
DriverObject - Functional device object
Irp - I/O request which has completed
pev - Context argument supplied to IoSetCompletionRoutine, namely address of
KEVENT object on which ForwardAndWait is waiting
Return Value:
STATUS_MORE_PROCESSING_REQUIRED
--*/
{
KeSetEvent(pev, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
ForwardAndWait(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
/*++
Routine Description:
Forward request to lower level and await completion
The only purpose of this routine in this particular driver is to pass down
IRP_MN_START_DEVICE requests and wait for the PDO to handle them.
The processor must be at PASSIVE IRQL because this function initializes
and waits for non-zero time on a kernel event object.
Arguments:
fdo - pointer to a device object
Irp - pointer to an I/O Request Packet
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
KEVENT event;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
NTSTATUS ntStatus;
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
//
// Initialize a kernel event object to use in waiting for the lower-level
// driver to finish processing the object.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete,
(PVOID) &event, TRUE, TRUE, TRUE);
ntStatus = IoCallDriver(pdx->StackDeviceObject, Irp);
if (ntStatus == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
ntStatus = Irp->IoStatus.Status;
}
return ntStatus;
}
NTSTATUS
CompleteRequest(
IN PIRP Irp,
IN NTSTATUS status,
IN ULONG info
)
/*++
Routine Description:
Mark I/O request complete
Arguments:
Irp - I/O request in question
status - Standard status code
info Additional information related to status code
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
Ezusb_DispatchPnp(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
/*++
Routine Description:
Process Plug and Play IRPs sent to this device.
Arguments:
fdo - pointer to a device object
Irp - pointer to an I/O Request Packet
Return Value:
NTSTATUS
--*/
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION pdx = fdo->DeviceExtension;
ULONG fcn;
NTSTATUS ntStatus;
Ezusb_KdPrint (("Enter Ezusb_DispatchPnp\n"));
if (!LockDevice(fdo))
return CompleteRequest(Irp, STATUS_DELETE_PENDING, 0);
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
fcn = irpStack->MinorFunction;
switch (fcn)
{
case IRP_MN_START_DEVICE:
Ezusb_KdPrint (("IRP_MN_START_DEVICE\n"));
ntStatus = Ezusb_HandleStartDevice(fdo,Irp);
break; //IRP_MN_START_DEVICE
case IRP_MN_REMOVE_DEVICE:
Ezusb_KdPrint (("IRP_MN_REMOVE_DEVICE\n"))
ntStatus = Ezusb_HandleRemoveDevice(fdo,Irp);
break; //IRP_MN_REMOVE_DEVICE
case IRP_MN_QUERY_CAPABILITIES:
{
//
// This code swiped from Walter Oney. Please buy his book!!
//
PDEVICE_CAPABILITIES pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
Ezusb_KdPrint (("IRP_MN_QUERY_CAPABILITIES\n"))
// Check to besure we know how to handle this version of the capabilities structure
if (pdc->Version < 1)
{
ntStatus = Ezusb_DefaultPnpHandler(fdo, Irp);
break;
}
ntStatus = ForwardAndWait(fdo, Irp);
if (NT_SUCCESS(ntStatus))
{ // IRP succeeded
pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
// setting this field prevents NT5 from notifying the user when the
// device is removed.
pdc->SurpriseRemovalOK = TRUE;
} // IRP succeeded
ntStatus = CompleteRequest(Irp, ntStatus, Irp->IoStatus.Information);
}
break; //IRP_MN_QUERY_CAPABILITIES
//
// All other PNP IRP's are just passed down the stack by the default handler
//
default:
Ezusb_KdPrint (("Passing down unhandled PnP IOCTL MJ=0x%x MN=0x%x\n",
irpStack->MajorFunction, irpStack->MinorFunction));
ntStatus = Ezusb_DefaultPnpHandler(fdo, Irp);
} // switch MinorFunction
if (fcn != IRP_MN_REMOVE_DEVICE)
UnlockDevice(fdo);
Ezusb_KdPrint (("Exit Ezusb_DispatchPnp %x\n", ntStatus));
return ntStatus;
}//Ezusb_Dispatch
VOID
Ezusb_Unload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Free all the allocated resources, etc.
TODO: This is a placeholder for driver writer to add code on unload
Arguments:
DriverObject - pointer to a driver object
Return Value:
None
--*/
{
Ezusb_KdPrint (("enter Ezusb_Unload\n"));
/*
// TODO: Free any global resources allocated in DriverEntry
*/
Ezusb_KdPrint (("exit Ezusb_Unload\n"));
}
NTSTATUS
Ezusb_HandleRemoveDevice(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
{
NTSTATUS ntStatus;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
pdx->removing = TRUE;
UnlockDevice(fdo); // once for LockDevice at start of dispatch
UnlockDevice(fdo); // once for initialization during AddDevice
KeWaitForSingleObject(&pdx->evRemove, Executive, KernelMode, FALSE, NULL);
// Let lower-level drivers handle this request. Ignore whatever
// result eventuates.
// ntStatus = Ezusb_DefaultPnpHandler(fdo, Irp);
// Ezusb_Cleanup(fdo);
// Remove the device object
Ezusb_RemoveDevice(fdo);
ntStatus = Ezusb_DefaultPnpHandler(fdo, Irp);
return ntStatus; // lower-level completed IoStatus already
}
NTSTATUS
Ezusb_HandleStartDevice(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
{
NTSTATUS ntStatus;
//
// First let all lower-level drivers handle this request.
//
ntStatus = ForwardAndWait(fdo, Irp);
if (!NT_SUCCESS(ntStatus))
return CompleteRequest(Irp, ntStatus, Irp->IoStatus.Information);
//
// now do whatever we need to do to start the device
//
ntStatus = Ezusb_StartDevice(fdo);
return CompleteRequest(Irp, ntStatus, 0);
}
NTSTATUS
Ezusb_StartDevice(
IN PDEVICE_OBJECT fdo
)
/*++
Routine Description:
Initializes a given instance of the Ezusb Device on the USB.
Arguments:
fdo - pointer to the device object for this instance of a
Ezusb Device
Return Value:
NT status code
--*/
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -