www.pudn.com > usbboot-v1.2.rar.zip > Usb_Boot_Driver_Device.cpp, change:2007-09-05,size:43975b


// Jz4740_usbDevice.cpp 
// Implementation of Jz4740_usbDevice device class 
// 
// Generated by DriverWizard version DriverStudio 3.1.0 (Build 1722) 
// Requires Compuware's DriverWorks classes 
// 
 
#pragma warning(disable:4065) // Allow switch statement with no cases 
		   
#include <vdw.h> 
#include <kusb.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include "Usb_Boot_Interface.h" 
 #include "Usb_Boot_Driver.h" 
#include "Usb_Boot_Driver_Device.h" 
#include "Usb_Boot_Ioctl.h" 
  
#pragma hdrstop("Usb_Boot_Driver.pch") 
 
extern KDebugOnlyTrace t;	// Global driver trace object	 
 
UCHAR Jz4740_usbDevice::dev_n = 0; 
 
GUID Jz4740_usbDevice_Guid = Jz4740_usbDevice_CLASS_GUID; 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::Jz4740_usbDevice 
// 
//	Routine Description: 
//		This is the constructor for the Functional Device Object, or FDO. 
//		It is derived from KPnpDevice, which builds in automatic 
//	    dispatching of subfunctions of IRP_MJ_POWER and IRP_MJ_PNP to 
//		virtual member functions. 
// 
//	Parameters: 
//		Pdo - Physical Device Object - this is a pointer to a system 
//			device object that represents the physical device. 
// 
//		Unit - Unit number. This is a number to append to the device's 
//			base device name to form the Logical Device Object's name 
// 
//	Return Value: 
//		None    
// 
//	Comments: 
//		The object being constructed contains a data member (m_Lower) of type 
//		KPnpLowerDevice. By initializing it, the driver binds the FDO to the 
//		PDO and creates an interface to the upper edge of the system class driver. 
// 
Jz4740_usbDevice::Jz4740_usbDevice(PDEVICE_OBJECT Pdo, ULONG Unit) : 
	KPnpDevice(Pdo, &Jz4740_usbDevice_Guid) 
{ 
	t << "Entering Jz4740_usbDevice::Jz4740_usbDevice (constructor)\n"; 
 
	// Check constructor status 
    if ( ! NT_SUCCESS(m_ConstructorStatus) ) 
	{ 
	    return; 
	} 
 
	// Remember our unit number 
	m_Unit = Unit; 
	if (dev_n<16) dev_n ++; 
	// Initialize the lower device 
	m_Lower.Initialize(this, Pdo); 
 
	// Initialize the interface object.  The wizard generates code  
	// to support a single interface.  You may create and add additional  
	// interfaces.  By default, the wizard uses InterfaceNumber 0 (the  
	// first interface descriptor), ConfigurationValue 1 (the first 
	// configuration descriptor), and initial interface alternate 
	// setting of 0.  If your device has multiple interfaces or alternate 
	// settings for an interface, you can add additional KUsbInterface 
	// objects or adjust the parameters passed to this function. 
	m_Interface.Initialize( 
					m_Lower, //KUsbLowerDevice 
					0,		 //InterfaceNumber 
					1,		 //ConfigurationValue  
					0		 //Initial Interface Alternate Setting 
					);  
 
	// Initialize each Pipe object 
	//m_Endpoint1OUT.Initialize(m_Lower, 0x1, 1048576);  
	//m_Endpoint1IN.Initialize(m_Lower, 0x81, 1048576);  
	m_Endpoint1OUT.Initialize(m_Lower, 0x1, 0x400000);  
	m_Endpoint1IN.Initialize(m_Lower, 0x81, 0x400000);  
 
    // Inform the base class of the lower edge device object 
	SetLowerDevice(&m_Lower); 
 
	// Initialize the PnP Policy settings to the "standard" policy 
	SetPnpPolicy(); 
 
// TODO:	Customize the PnP Policy for this device by setting 
//			flags in m_Policies. 
 
	// Initialize the Power Policy settings to the "standard" policy 
	SetPowerPolicy(); 
 
// TODO:	Customize the Power Policy for this device by setting 
//			flags in m_PowerPolicies. 
 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::~Jz4740_usbDevice 
// 
//	Routine Description: 
//		This is the destructor for the Functional Device Object, or FDO. 
// 
//	Parameters: 
//		None 
// 
//	Return Value: 
//		None 
// 
//	Comments: 
//		None 
// 
 
Jz4740_usbDevice::~Jz4740_usbDevice() 
{ 
	t << "Entering Jz4740_usbDevice::~Jz4740_usbDevice() (destructor)\n"; 
	if (dev_n>0) Jz4740_usbDevice::dev_n -- ; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::DefaultPnp 
// 
//	Routine Description: 
//		Default handler for IRP_MJ_PNP 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result returned from lower device 
// 
//	Comments: 
//		This routine just passes the IRP through to the lower device. It is  
//		the default handler for IRP_MJ_PNP. IRPs that correspond to 
//		any virtual members of KpnpDevice that handle minor functions of 
//		IRP_MJ_PNP and that are not overridden get passed to this routine. 
// 
 
NTSTATUS Jz4740_usbDevice::DefaultPnp(KIrp I)  
{ 
	ULONG Fun; 
	PIO_STACK_LOCATION IS; 
	t << "Entering Jz4740_usbDevice::DefaultPnp\n" << I << EOL; 
 
	I.ForceReuseOfCurrentStackLocationInCalldown(); 
	IS = IoGetCurrentIrpStackLocation(I); 
	Fun = IS->MajorFunction; 
 
	switch (Fun) 
	{ 
	case IRP_MN_REMOVE_DEVICE: 
	case IRP_MN_SURPRISE_REMOVAL: 
		return this->OnRemoveDevice(I); 
		//case IRP_ 
		break; 
	default: 
		return m_Lower.PnpCall(this, I); 
	} 
	return m_Lower.PnpCall(this, I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::DefaultPower 
// 
//	Routine Description: 
//		Default handler for IRP_MJ_POWER  
//   
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result returned from lower device 
// 
//	Comments: 
//		This routine just passes the IRP through to the lower device. It is  
//		the default handler for IRP_MJ_POWER. 
// 
 
NTSTATUS Jz4740_usbDevice::DefaultPower(KIrp I)  
{ 
	t << "Entering Jz4740_usbDevice::DefaultPower\n" << I << EOL; 
 
	I.IndicatePowerIrpProcessed(); 
	I.CopyParametersDown(); 
	return m_Lower.PnpPowerCall(this, I); 
} 
 
//////////////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::SystemControl 
// 
//	Routine Description: 
//		Default handler for IRP_MJ_SYSTEM_CONTROL 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result returned from lower device 
// 
//	Comments: 
//		This routine just passes the IRP through to the next device since this driver 
//		is not a WMI provider. 
// 
 
NTSTATUS Jz4740_usbDevice::SystemControl(KIrp I)  
{ 
	t << "Entering Jz4740_usbDevice::SystemControl\n"; 
 
	I.ForceReuseOfCurrentStackLocationInCalldown(); 
	return m_Lower.PnpCall(this, I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::OnStartDevice 
// 
//	Routine Description: 
//		Handler for IRP_MJ_PNP subfcn IRP_MN_START_DEVICE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
//		Typically, the driver sends a SET CONFIGURATION request for the 
//		USB device by using KUsbLowerDevice::ActivateConfiguration with 
//		the ConfigurationValue to activate.  The wizard generates code to  
//		support a single configuration.  You may create and add additional  
//		configurations.  
// 
 
NTSTATUS Jz4740_usbDevice::OnStartDevice(KIrp I) 
{ 
	t << "Entering Jz4740_usbDevice::OnStartDevice\n"; 
 
	NTSTATUS status = STATUS_UNSUCCESSFUL; 
 
	AC_STATUS acStatus = AC_SUCCESS; 
 
	I.Information() = 0; 
 
	// The default Pnp policy has already cleared the IRP with the lower device 
 
	//By default, the wizard passes a ConfigurationValue of 1 to  
	//ActivateConfiguration().  This corresponds to the first configuration  
	//that the device reports in its configuration descriptor.  If the device  
	//supports multiple configurations, pass the appropriate 
	//ConfigurationValue of the configuration to activate here. 
	acStatus = m_Lower.ActivateConfiguration( 
		1	// ConfigurationValue 1 (the first configuration) 
		); 
 
	switch (acStatus) 
	{ 
		case AC_SUCCESS: 
			t << "USB Configuration OK\n"; 
			status = STATUS_SUCCESS; 
			break; 
 
		case AC_COULD_NOT_LOCATE_INTERFACE: 
			t << "Could not locate interface\n"; 
			break; 
 
		case AC_COULD_NOT_PRECONFIGURE_INTERFACE: 
			t << "Could not get configuration descriptor\n"; 
			break; 
 
		case AC_CONFIGURATION_REQUEST_FAILED: 
			t << "Board did not accept configuration URB\n"; 
			break; 
 
		case AC_FAILED_TO_INITIALIZE_INTERFACE_OBJECT: 
			t << "Failed to initialize interface object\n"; 
			break; 
 
		case AC_FAILED_TO_GET_DESCRIPTOR: 
			t << "Failed to get device descriptor\n"; 
			break; 
 
		case AC_FAILED_TO_OPEN_PIPE_OBJECT: 
			//NOTE: this may not be an error.  It could mean that 
			//the device has an endpoint for which a KUsbPipe object has 
			//not been instanced.  If the intention is to not use this endpoint, 
			//then it's likely not a problem.   
			status = STATUS_SUCCESS; 
			t << "Failed to open pipe object\n"; 
			break; 
 
		default: 
			t << "Unexpected error activating USB configuration\n"; 
			break; 
	} 
 
   return status;  // base class completes the IRP 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::OnStopDevice 
// 
//	Routine Description: 
//		Handler for IRP_MJ_PNP subfcn IRP_MN_STOP_DEVICE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
//		The system calls this when the device is stopped. 
//		The driver should release any hardware resources 
//		in this routine. 
// 
//		The base class passes the irp to the lower device. 
// 
 
NTSTATUS Jz4740_usbDevice::OnStopDevice(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
 
	t << "Entering Jz4740_usbDevice::OnStopDevice\n"; 
	//if (dev_n>0) Jz4740_usbDevice::dev_n -- ; 
 
	m_Lower.DeActivateConfiguration(); 
 
 
// TODO:	Add device-specific code to stop your device    
 
	return status; 
	 
	// The following macro simply allows compilation at Warning Level 4 
	// If you reference this parameter in the function simply remove the macro. 
	UNREFERENCED_PARAMETER(I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::OnRemoveDevice 
// 
//	Routine Description: 
//		Handler for IRP_MJ_PNP subfcn IRP_MN_REMOVE_DEVICE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
//		The system calls this when the device is removed. 
//		Our PnP policy will take care of  
//			(1) giving the IRP to the lower device 
//			(2) detaching the PDO 
//			(3) deleting the device object 
// 
 
NTSTATUS Jz4740_usbDevice::OnRemoveDevice(KIrp I) 
{ 
	t << "Entering Jz4740_usbDevice::OnRemoveDevice\n"; 
	if (dev_n>0) Jz4740_usbDevice::dev_n -- ; 
	// Device removed, release the system resources used by the USB lower device. 
	m_Lower.ReleaseResources(); 
 
 
// TODO:	Add device-specific code to remove your device    
 
	return STATUS_SUCCESS; 
 
	// The following macro simply allows compilation at Warning Level 4 
	// If you reference this parameter in the function simply remove the macro. 
	UNREFERENCED_PARAMETER(I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::OnDevicePowerUp 
// 
//	Routine Description: 
//		Handler for IRP_MJ_POWER with minor function IRP_MN_SET_POWER 
//		for a request to go to power on state from low power state 
// 
//	Parameters: 
//		I - IRP containing POWER request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the OnDevicePowerUp function. 
//		This function was called by the framework from the completion 
//		routine of the IRP_MJ_POWER dispatch handler in KPnpDevice. 
//		The bus driver has completed the IRP and this driver can now 
//		access the hardware device.   
//		This routine runs at dispatch level. 
//	 
 
NTSTATUS Jz4740_usbDevice::OnDevicePowerUp(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
 
	t << "Entering Jz4740_usbDevice::OnDevicePowerUp\n"; 
 
// TODO:	Service the device. 
//			Restore any context to the hardware device that 
//			was saved during the handling of a power down request. 
//			See the OnDeviceSleep function. 
//			Do NOT complete this IRP. 
// 
	return status; 
 
	// The following macro simply allows compilation at Warning Level 4 
	// If you reference this parameter in the function simply remove the macro. 
	UNREFERENCED_PARAMETER(I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::OnDeviceSleep 
// 
//	Routine Description: 
//		Handler for IRP_MJ_POWER with minor function IRP_MN_SET_POWER 
//		for a request to go to a low power state from a high power state 
// 
//	Parameters: 
//		I - IRP containing POWER request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the OnDeviceSleep function. 
//		This function was called by the framework from the IRP_MJ_POWER  
//		dispatch handler in KPnpDevice prior to forwarding to the PDO. 
//		The hardware has yet to be powered down and this driver can now 
//		access the hardware device.   
//		This routine runs at passive level. 
//	 
 
NTSTATUS Jz4740_usbDevice::OnDeviceSleep(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
 
	t << "Entering Jz4740_usbDevice::OnDeviceSleep\n"; 
 
// TODO:	Service the device. 
//			Save any context to the hardware device that will be required  
//			during a power up request. See the OnDevicePowerUp function. 
//			Do NOT complete this IRP.  The base class handles forwarding 
//			this IRP to the PDO. 
// 
	return status; 
 
	// The following macro simply allows compilation at Warning Level 4 
	// If you reference this parameter in the function simply remove the macro. 
	UNREFERENCED_PARAMETER(I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::Create 
// 
//	Routine Description: 
//		Handler for IRP_MJ_CREATE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
// 
 
NTSTATUS Jz4740_usbDevice::Create(KIrp I) 
{ 
	NTSTATUS status; 
 
	t << "Entering Jz4740_usbDevice::Create, " << I << EOL; 
 
// TODO: Add driver specific create handling code here 
 
	// Generally a create IRP is targeted at our FDO, so we don't need 
	// to pass it down to the PDO.  We have found for some devices, the 
	// PDO is not expecting this Irp and returns an error code. 
	// The default wizard code, therefore completes the Irp here using 
	// PnpComplete().  The following commented code could be used instead 
	// of PnpComplete() to pass the Irp to the PDO, which would complete it. 
	// 
//	I.ForceReuseOfCurrentStackLocationInCalldown(); 
//	status = m_Lower.PnpCall(this, I); 
 
	status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT); 
 
	t << "Jz4740_usbDevice::Create Status " << (ULONG)status << EOL; 
 
	return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::Close 
// 
//	Routine Description: 
//		Handler for IRP_MJ_CLOSE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
// 
 
NTSTATUS Jz4740_usbDevice::Close(KIrp I) 
{ 
	NTSTATUS status; 
 
	t << "Entering Jz4740_usbDevice::Close, " << I << EOL; 
 
// TODO: Add driver specific close handling code here 
 
	// Generally a close IRP is targeted at our FDO, so we don't need 
	// to pass it down to the PDO.  We have found for some devices, the 
	// PDO is not expecting this Irp and returns an error code. 
	// The default wizard code, therefore completes the Irp here using 
	// PnpComplete().  The following commented code could be used instead 
	// of PnpComplete() to pass the Irp to the PDO, which would complete it. 
	// 
//	I.ForceReuseOfCurrentStackLocationInCalldown(); 
//	status = m_Lower.PnpCall(this, I); 
 
	status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT); 
 
	t << "Jz4740_usbDevice::Close Status " << (ULONG)status << EOL; 
 
    return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::Cleanup 
// 
//	Routine Description: 
//		Handler for IRP_MJ_CLEANUP	 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
// 
 
NTSTATUS Jz4740_usbDevice::CleanUp(KIrp I) 
{ 
	t << "Entering CleanUp, " << I << EOL; 
 
// TODO:	Insert your code to respond to the CLEANUP message. 
	return I.PnpComplete(this, STATUS_SUCCESS); 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::Read 
// 
//	Routine Description: 
//		Handler for IRP_MJ_READ 
// 
//	Parameters: 
//		I			Current IRP 
// 
//	Return Value: 
//		NTSTATUS	Result code 
// 
//	Comments: 
//		This routine handles read requests. 
// 
//		The KPnpDevice class handles restricting IRP flow 
//		if the device is stopping or being removed. 
// 
 
NTSTATUS Jz4740_usbDevice::Read(KIrp I)  
{ 
	t << "Entering Jz4740_usbDevice::Read, " << I << EOL; 
// TODO:	Check the incoming request.  Replace "FALSE" in the following 
//			line with a check that returns TRUE if the request is not valid. 
 
    if (FALSE)		// If (Request is invalid) 
	{ 
		// Invalid parameter in the Read request 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_INVALID_PARAMETER); 
	} 
 
	// Always ok to read 0 elements. 
	if (I.ReadSize() == 0) 
	{ 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_SUCCESS); 
	} 
 
	// Declare a memory object 
	KMemory Mem(I.Mdl()); 
 
    ULONG dwTotalSize = I.ReadSize(CURRENT); 
	ULONG dwMaxSize = m_Endpoint1IN.MaximumTransferSize(); 
 
	// If the total requested read size is greater than the Maximum Transfer 
	// Size for the Pipe, request to read only the Maximum Transfer Size since 
	// the bus driver will fail an URB with a TransferBufferLength of greater 
	// than the Maximum Transfer Size.  
	if (dwTotalSize > dwMaxSize) 
	{ 
		ASSERT(dwMaxSize); 
		dwTotalSize = dwMaxSize; 
	} 
 
	// Allocate a new context structure for Irp completion 
	USB_COMPLETION_INFO* pCompInfo = new (NonPagedPool) USB_COMPLETION_INFO; 
	if (pCompInfo == NULL) 
	{ 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_INSUFFICIENT_RESOURCES); 
	} 
 
// TODO:	Select the correct pipe to read from 
 
	// Create an URB to do actual Bulk read from the pipe 
	PURB pUrb = m_Endpoint1IN.BuildBulkTransfer( 
			    	Mem,      		// Where is data coming from? 
					dwTotalSize,  	// How much data to read? 
					TRUE,         	// direction (TRUE = IN) 
					NULL,			// Link to next URB 
					TRUE			// Allow a short transfer 
					);        		 
 
	if (pUrb == NULL) 
	{ 
		delete pCompInfo; 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_INSUFFICIENT_RESOURCES); 
	} 
 
	// Initialize context structure 
	pCompInfo->m_pClass = this; 
	pCompInfo->m_pUrb = pUrb; 
 
    // Submit the URB to our USB device 
	NTSTATUS status; 
	status = m_Endpoint1IN.SubmitUrb(I, pUrb, LinkTo(ReadComplete), pCompInfo, 0); 
	return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::ReadComplete 
// 
//	Routine Description: 
//		Completion Handler for IRP_MJ_READ 
// 
//	Parameters: 
//		I - IRP just completed by USB 
//		pContext - Context structure containing pointer to Urb 
// 
//	Parameters: 
//		NTSTATUS - STATUS_SUCCESS 
// 
//	Comments: 
//		This routine is called when USBD completes the read request 
// 
 
NTSTATUS Jz4740_usbDevice::ReadComplete(KIrp I, USB_COMPLETION_INFO* pContext) 
{ 
	// Normal completion routine code to propagate pending flag 
 
	if (I->PendingReturned)  
	{ 
		I.MarkPending(); 
	} 
	 
	NTSTATUS status = I.Status(); 
	PURB pUrb = pContext->m_pUrb; 
	ULONG nBytesRead = 0; 
 
	if ( NT_SUCCESS(status) )  
	{ 
		nBytesRead = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength; 
		if (nBytesRead > 0)  
			t << "Read() got " << nBytesRead<< " bytes from USB\n"; 
    } 
 
	// Deallocate Urb and context structure 
	delete pUrb; 
	delete pContext; 
 
	// set returned count 
	I.Information() = nBytesRead; 
	 
	// Plug and Play accounting 
	DecrementOutstandingRequestCount(); 
 
	// allow IRP completion processing 
	return STATUS_SUCCESS; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::Write 
// 
//	Routine Description: 
//		Handler for IRP_MJ_WRITE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
//		This routine handles write requests. 
// 
//		The KPnpDevice class handles restricting IRP flow 
//		if the device is stopping or being removed. 
// 
 
NTSTATUS Jz4740_usbDevice::Write(KIrp I)  
{ 
	t << "Entering Jz4740_usbDevice::Write, " << I << EOL; 
// TODO:	Check the incoming request.  Replace "FALSE" in the following 
//			line with a check that returns TRUE if the request is not valid. 
    if (FALSE) 
	{ 
		// Invalid parameter in the Write request 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_INVALID_PARAMETER); 
	} 
 
	// Always ok to write 0 elements. 
	if (I.WriteSize() == 0) 
	{ 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_SUCCESS); 
	} 
	ULONG dwTotalSize = I.WriteSize(CURRENT); 
	ULONG dwMaxSize = m_Endpoint1OUT.MaximumTransferSize(); 
 
	// If the total requested read size is greater than the Maximum Transfer 
	// Size for the Pipe, request to read only the Maximum Transfer Size since 
	// the bus driver will fail an URB with a TransferBufferLength of greater 
	// than the Maximum Transfer Size.  
	if (dwTotalSize > dwMaxSize) 
	{ 
		ASSERT(dwMaxSize); 
		dwTotalSize = dwMaxSize; 
	} 
 
	// Declare a memory object 
	KMemory Mem(I.Mdl()); 
 
	// Allocate a new context structure for Irp completion 
	USB_COMPLETION_INFO* pCompInfo = new (NonPagedPool) USB_COMPLETION_INFO; 
	if (pCompInfo == NULL) 
	{ 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_INSUFFICIENT_RESOURCES); 
	} 
 
// TODO:	Select the correct pipe to write to 
 
	// Create an URB to do actual Bulk write to the pipe 
	PURB pUrb = m_Endpoint1OUT.BuildBulkTransfer( 
					Mem,          // Where is data coming from? 
					dwTotalSize,  // How much data to read? 
					FALSE,        // direction (FALSE = OUT) 
					NULL		  // Link to next URB 
					);	         
 
	if (pUrb == NULL) 
	{ 
		delete pCompInfo; 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_INSUFFICIENT_RESOURCES); 
	} 
 
	// Initialize context structure 
	pCompInfo->m_pClass = this; 
	pCompInfo->m_pUrb = pUrb; 
 
    // Submit the URB to our USB device 
	NTSTATUS status; 
	status = m_Endpoint1OUT.SubmitUrb(I, pUrb, LinkTo(WriteComplete), pCompInfo, 0); 
	return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::WriteComplete 
// 
//	Routine Description: 
//		Completion Handler for IRP_MJ_WRITE 
// 
//	Parameters: 
//		I - IRP just completed by USB 
//		pContext - Context structure containing pointer to Urb 
// 
//	Return Value: 
//		NTSTATUS	STATUS_SUCCESS 
// 
//	Comments: 
//		This routine is called when USBD completes the write request 
// 
 
NTSTATUS Jz4740_usbDevice::WriteComplete(KIrp I, USB_COMPLETION_INFO* pContext) 
{ 
	// Normal completion routine code to propagate pending flag 
 
	if (I->PendingReturned)  
	{ 
		I.MarkPending(); 
	} 
	 
	NTSTATUS status = I.Status(); 
	PURB pUrb = pContext->m_pUrb; 
	ULONG nBytesWritten = 0; 
 
	if ( NT_SUCCESS(status) )  
	{ 
		nBytesWritten = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength; 
		if (nBytesWritten > 0)  
			t << "Wrote " << nBytesWritten	<< " bytes to USB\n"; 
    } 
 
	// Deallocate Urb and context structure 
	delete pUrb; 
	delete pContext; 
 
	// set returned count 
	I.Information() = nBytesWritten; 
	 
	// Plug and Play accounting 
	DecrementOutstandingRequestCount(); 
 
	// allow IRP completion processing 
	return STATUS_SUCCESS; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::DeviceControl 
// 
//	Routine Description: 
//		Handler for IRP_MJ_DEVICE_CONTROL 
// 
//	Parameters: 
//		I - Current IRP 
//  
//	Return Value: 
//		None 
// 
//	Comments: 
//		This routine is the first handler for Device Control requests. 
//		The KPnpDevice class handles restricting IRP flow 
//		if the device is stopping or being removed. 
// 
 
NTSTATUS Jz4740_usbDevice::DeviceControl(KIrp I)  
{ 
	NTSTATUS status; 
 
	t << "Entering Jz4740_usbDevice::Device Control, " << I << EOL; 
	switch (I.IoctlCode()) 
	{ 
		case JZ4740_USB_IOCTL_GET_CPU_INFO: 
			status = JZ4740_USB_IOCTL_GET_CPU_INFO_Handler(I); 
			break; 
 
		case JZ4740_USB_IOCTL_SET_DATA_ADDRESS: 
			status = JZ4740_USB_IOCTL_SET_DATA_ADDRESS_Handler(I); 
			break; 
 
		case JZ4740_USB_IOCTL_SET_DATA_LENGTH: 
			status = JZ4740_USB_IOCTL_SET_DATA_LENGTH_Handler(I); 
			break; 
 
		case JZ4740_USB_IOCTL_FLUSH_CACHES: 
			status = JZ4740_USB_IOCTL_FLUSH_CACHES_Handler(I); 
			break; 
 
		case JZ4740_USB_IOCTL_PROG_START1: 
			status = JZ4740_USB_IOCTL_PROG_START1_Handler(I); 
			break; 
 
		case JZ4740_USB_IOCTL_PROG_START2: 
			status = JZ4740_USB_IOCTL_PROG_START2_Handler(I); 
			break; 
 
		case JZ4740_USB_IOCTL_NOR_OPS: 
			status = JZ4740_USB_IOCTL_NOR_OPS_Handler(I); 
			break; 
 
		case JZ4740_USB_IOCTL_NAND_OPS: 
			status = JZ4740_USB_IOCTL_NAND_OPS_Handler(I); 
			break; 
 
		case JZ4740_USB_IOCTL_CONFIGRATION: 
			status = JZ4740_USB_IOCTL_CONFIGRATION_Handler(I); 
			break; 
		case JZ4740_USB_IOCTL_GET_NUM: 
			status = JZ4740_USB_IOCTL_GET_NUM_Handler(I); 
			break; 
		case JZ4740_USB_IOCTL_SDRAM_OPS: 
			status = JZ4740_USB_IOCTL_SDRAM_OPS_Handler(I); 
			break; 
		default: 
			// Unrecognized IOCTL request 
			status = STATUS_INVALID_PARAMETER; 
			break; 
	} 
 
	// If the IRP's IOCTL handler deferred processing using some driver 
	// specific scheme, the status variable is set to STATUS_PENDING. 
	// In this case we simply return that status, and the IRP will be 
	// completed later.  Otherwise, complete the IRP using the status 
	// returned by the IOCTL handler. 
	if (status == STATUS_PENDING) 
	{ 
		return status; 
	} 
	else 
	{ 
		return I.PnpComplete(this, status); 
	} 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::JZ4740_USB_IOCTL_GET_CPU_INFO_Handler 
// 
//	Routine Description: 
//		Handler for IO Control Code JZ4740_USB_IOCTL_GET_CPU_INFO 
// 
//	Parameters: 
//		I - IRP containing IOCTL request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the JZ4740_USB_IOCTL_GET_CPU_INFO function. 
//		This routine runs at passive level. 
// 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_GET_CPU_INFO_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
	PVOID pBuffer = I.IoctlBuffer(); 
	ULONG dwOutputBufferSize = I.IoctlOutputBufferSize(); 
	PUCHAR OutputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	ULONG ret; 
 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_GET_CPU_INFO_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_GET_CPU_INFO request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
	PURB pUrb = m_Lower.BuildVendorRequest( 
							OutputBuf,					//TransferBuffer 
							8,							//TransferBufferLength 
							0,							//RequestTypeReservedBits 
							JZ4740_VR_GET_CPU_INFO,		//Request 
							0,							//Value 
							TRUE,						//bIn 
							FALSE,						//bShortOk 
							NULL,						//Link 
							0,							//Index 
							URB_FUNCTION_VENDOR_DEVICE	//Function 
							); 
 
	if (pUrb == NULL) 
        return STATUS_NO_MEMORY; 
  
	status = m_Lower.SubmitUrb(pUrb); 
 
	delete pUrb; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 8; 
 
	return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::JZ4740_USB_IOCTL_SET_DATA_ADDRESS_Handler 
// 
//	Routine Description: 
//		Handler for IO Control Code JZ4740_USB_IOCTL_SET_DATA_ADDRESS 
// 
//	Parameters: 
//		I - IRP containing IOCTL request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the JZ4740_USB_IOCTL_SET_DATA_ADDRESS function. 
//		This routine runs at passive level. 
// 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_SET_DATA_ADDRESS_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
	PVOID pBuffer = I.IoctlBuffer(); 
	ULONG dwInputBufferSize = I.IoctlInputBufferSize();	 
	PUCHAR InputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	ULONG ret; 
	unsigned int addr; 
 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_SET_DATA_ADDRESS_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
	t << "InputBufferSize: " << dwInputBufferSize << EOL; 
	t << "InputBuf: " << InputBuf[0] << InputBuf[1] << InputBuf[2] << InputBuf[3] << EOL; 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_SET_DATA_ADDRESS request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
 
	addr = *(unsigned int *)InputBuf; 
	t << "ADDR: " << addr << EOL; 
 
	PURB pUrb = m_Lower.BuildVendorRequest( 
					0,							//TransferBuffer 
					0,							//TransferBufferLength 
					0,							//RequestTypeReservedBits 
					JZ4740_VR_SET_DATA_ADDRESS,	//Request 
					addr >> 16,					//Value 
					FALSE,						//bIn 
					FALSE,						//bShortOk 
					NULL,						//Link 
					addr & 0xffff,				//Index 
					URB_FUNCTION_VENDOR_DEVICE	//Function 
					); 
 
	if (pUrb == NULL) 
		return STATUS_NO_MEMORY; 
 
	status = m_Lower.SubmitUrb(pUrb); 
 
	delete pUrb; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 0; 
 
	return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::JZ4740_USB_IOCTL_SET_DATA_LENGTH_Handler 
// 
//	Routine Description: 
//		Handler for IO Control Code JZ4740_USB_IOCTL_SET_DATA_LENGTH 
// 
//	Parameters: 
//		I - IRP containing IOCTL request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the JZ4740_USB_IOCTL_SET_DATA_LENGTH function. 
//		This routine runs at passive level. 
// 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_SET_DATA_LENGTH_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
	PVOID pBuffer = I.IoctlBuffer(); 
	ULONG dwInputBufferSize = I.IoctlInputBufferSize();	 
	PUCHAR InputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	ULONG ret; 
	unsigned int len; 
 
 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_SET_DATA_LENGTH_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
	t << "InputBufferSize: " << dwInputBufferSize << EOL; 
	t << "InputBuf: " << InputBuf[0] << InputBuf[1] << InputBuf[2] << InputBuf[3] << EOL; 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_SET_DATA_LENGTH request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
	len = *(unsigned int *)InputBuf; 
	t << "LEN: " << len << EOL; 
 
	PURB pUrb = m_Lower.BuildVendorRequest( 
					0,							//TransferBuffer 
					0,							//TransferBufferLength 
					0,							//RequestTypeReservedBits 
					JZ4740_VR_SET_DATA_LENGTH,	//Request 
					len >> 16,					//Value 
					FALSE,						//bIn 
					FALSE,						//bShortOk 
					NULL,						//Link 
					len & 0xffff,				//Index 
					URB_FUNCTION_VENDOR_DEVICE	//Function 
					); 
 
	if (pUrb == NULL) 
		return STATUS_NO_MEMORY; 
 
	status = m_Lower.SubmitUrb(pUrb); 
 
	delete pUrb; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 0; 
 
	return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::JZ4740_USB_IOCTL_FLUSH_CACHES_Handler 
// 
//	Routine Description: 
//		Handler for IO Control Code JZ4740_USB_IOCTL_FLUSH_CACHES 
// 
//	Parameters: 
//		I - IRP containing IOCTL request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the JZ4740_USB_IOCTL_FLUSH_CACHES function. 
//		This routine runs at passive level. 
// 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_FLUSH_CACHES_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_FLUSH_CACHES_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_FLUSH_CACHES request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
 
	PURB pUrb = m_Lower.BuildVendorRequest( 
							0,							//TransferBuffer 
							0,							//TransferBufferLength 
							0,							//RequestTypeReservedBits 
							JZ4740_VR_FLUSH_CACHES,		//Request 
							0,							//Value 
							FALSE,						//bIn 
							FALSE,						//bShortOk 
							NULL,						//Link 
							0,							//Index 
							URB_FUNCTION_VENDOR_DEVICE	//Function 
							); 
 
	if (pUrb == NULL) 
        return STATUS_NO_MEMORY; 
 
	status = m_Lower.SubmitUrb(pUrb); 
 
	delete pUrb; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 0; 
 
	return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::JZ4740_USB_IOCTL_PROG_START1_Handler 
// 
//	Routine Description: 
//		Handler for IO Control Code JZ4740_USB_IOCTL_PROG_START1 
// 
//	Parameters: 
//		I - IRP containing IOCTL request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the JZ4740_USB_IOCTL_PROG_START1 function. 
//		This routine runs at passive level. 
// 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_PROG_START1_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
	PVOID pBuffer = I.IoctlBuffer(); 
	ULONG dwInputBufferSize = I.IoctlInputBufferSize();	 
	PUCHAR InputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	ULONG ret; 
	unsigned int addr; 
 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_PROG_START1_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_PROG_START1 request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
	addr= *(unsigned int *)InputBuf; 
	PURB pUrb = m_Lower.BuildVendorRequest( 
							0,							//TransferBuffer 
							0,							//TransferBufferLength 
							0,							//RequestTypeReservedBits 
							JZ4740_VR_PROG_START1,		//Request 
							addr>>16,						//Value 
							FALSE,						//bIn 
							FALSE,						//bShortOk 
							NULL,						//Link 
							addr,							//Index 
							URB_FUNCTION_VENDOR_DEVICE	//Function 
							); 
 
	if (pUrb == NULL) 
        return STATUS_NO_MEMORY; 
 
	status = m_Lower.SubmitUrb(pUrb); 
 
	delete pUrb; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 0; 
 
	return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Jz4740_usbDevice::JZ4740_USB_IOCTL_PROG_START2_Handler 
// 
//	Routine Description: 
//		Handler for IO Control Code JZ4740_USB_IOCTL_PROG_START2 
// 
//	Parameters: 
//		I - IRP containing IOCTL request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the JZ4740_USB_IOCTL_PROG_START2 function. 
//		This routine runs at passive level. 
// 
 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_PROG_START2_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
	PVOID pBuffer = I.IoctlBuffer(); 
	ULONG dwInputBufferSize = I.IoctlInputBufferSize();	 
	PUCHAR InputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	ULONG ret; 
	unsigned int addr; 
 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_PROG_START2_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_PROG_START2 request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
	addr= *(unsigned int *)InputBuf; 
 
	PURB pUrb = m_Lower.BuildVendorRequest( 
							0,							//TransferBuffer 
							0,							//TransferBufferLength 
							0,							//RequestTypeReservedBits 
							JZ4740_VR_PROG_START2,		//Request 
							addr>>16,						//Value 
							FALSE,						//bIn 
							FALSE,						//bShortOk 
							NULL,						//Link 
							addr,							//Index 
							URB_FUNCTION_VENDOR_DEVICE	//Function 
							); 
 
	if (pUrb == NULL) 
        return STATUS_NO_MEMORY; 
 
	status = m_Lower.SubmitUrb(pUrb); 
 
	delete pUrb; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 0; 
 
	return status; 
} 
 
 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_NOR_OPS_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
	PVOID pBuffer = I.IoctlBuffer(); 
	ULONG dwInputBufferSize = I.IoctlInputBufferSize();	 
	PUCHAR InputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	PUCHAR OutputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	unsigned int ops; 
 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_NOR_OPS_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_PROG_START2 request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
	ops = *(unsigned int *)InputBuf; 
 
	PURB pUrb = m_Lower.BuildVendorRequest( 
							0,					//TransferBuffer 
							0,							//TransferBufferLength 
							0,							//RequestTypeReservedBits 
							JZ4740_VR_NOR_OPS,			//Request 
							ops,						//Value 
							FALSE,						//bIn 
							FALSE,						//bShortOk 
							NULL,						//Link 
							0,							//Index 
							URB_FUNCTION_VENDOR_DEVICE	//Function 
							); 
 
	if (pUrb == NULL) 
        return STATUS_NO_MEMORY; 
 
	status = m_Lower.SubmitUrb(pUrb); 
 
	delete pUrb; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 0; 
 
	return status; 
} 
 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_NAND_OPS_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
	PVOID pBuffer = I.IoctlBuffer(); 
	ULONG dwInputBufferSize = I.IoctlInputBufferSize();	 
	PUCHAR InputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	PUCHAR OutputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	unsigned int ops; 
 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_NAND_OPS_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_PROG_START2 request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
	ops = *(unsigned int *)InputBuf; 
 
	PURB pUrb = m_Lower.BuildVendorRequest( 
							0,					//TransferBuffer 
							0,							//TransferBufferLength 
							0,							//RequestTypeReservedBits 
							JZ4740_VR_NAND_OPS,			//Request 
							ops&0xffff,					//Value 
							FALSE,						//bIn 
							FALSE,						//bShortOk 
							NULL,						//Link 
							0,							//Index 
							URB_FUNCTION_VENDOR_DEVICE	//Function 
							); 
	//printf("\n HERE!!"); 
	if (pUrb == NULL) 
        return STATUS_NO_MEMORY; 
 
	status = m_Lower.SubmitUrb(pUrb); 
 
	delete pUrb; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 0; 
 
	return status; 
} 
 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_CONFIGRATION_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
	PVOID pBuffer = I.IoctlBuffer(); 
	ULONG dwInputBufferSize = I.IoctlInputBufferSize();	 
	PUCHAR InputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	PUCHAR OutputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	unsigned int ops; 
 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_CONFIGRATION_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_PROG_START2 request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
	ops = *(unsigned int *)InputBuf; 
 
	PURB pUrb = m_Lower.BuildVendorRequest( 
							0,					//TransferBuffer 
							0,							//TransferBufferLength 
							0,							//RequestTypeReservedBits 
							JZ4740_VR_CONFIGRATION,		//Request 
							ops,						//Value 
							FALSE,						//bIn 
							FALSE,						//bShortOk 
							NULL,						//Link 
							0,							//Index 
							URB_FUNCTION_VENDOR_DEVICE	//Function 
							); 
 
	if (pUrb == NULL) 
        return STATUS_NO_MEMORY; 
 
	status = m_Lower.SubmitUrb(pUrb); 
 
	delete pUrb; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 0; 
 
	return status; 
} 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_GET_NUM_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
	PVOID pBuffer = I.IoctlBuffer(); 
	ULONG dwOutputBufferSize = I.IoctlOutputBufferSize(); 
	PUCHAR OutputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_GET_CPU_INFO_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_GET_CPU_INFO request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
	OutputBuf[0] = Jz4740_usbDevice::dev_n; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 1; 
	return status; 
} 
 
NTSTATUS Jz4740_usbDevice::JZ4740_USB_IOCTL_SDRAM_OPS_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
	PVOID pBuffer = I.IoctlBuffer(); 
	ULONG dwOutputBufferSize = I.IoctlOutputBufferSize(); 
	PUCHAR InputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
	PUCHAR OutputBuf = reinterpret_cast<PUCHAR>(pBuffer); 
 
	unsigned int ops; 
	t << "Entering Jz4740_usbDevice::JZ4740_USB_IOCTL_GET_CPU_INFO_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
// TODO:	Handle the the JZ4740_USB_IOCTL_GET_CPU_INFO request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
	ops = *(unsigned int *)InputBuf; 
	PURB pUrb = m_Lower.BuildVendorRequest( 
							0,							//TransferBuffer 
							0,							//TransferBufferLength 
							0,							//RequestTypeReservedBits 
							JZ4740_VR_SDRAM_OPS,			//Request 
							ops&0xffff,					//Value 
							FALSE,						//bIn 
							FALSE,						//bShortOk 
							NULL,						//Link 
							0,							//Index 
							URB_FUNCTION_VENDOR_DEVICE	//Function 
							); 
	//printf("\n HERE!!"); 
	if (pUrb == NULL) 
        return STATUS_NO_MEMORY; 
	status = m_Lower.SubmitUrb(pUrb); 
	delete pUrb; 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 0; 
	return status; 
}