www.pudn.com > BPSK9054.rar > BPSKDevice.cpp
// BPSKDevice.cpp // Implementation of BPSKDevice 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#include "BPSKDeviceinterface.h" #include "BPSK.h" #include "BPSKDevice.h" #include "BPSKioctl.h" #pragma hdrstop("BPSK.pch") extern KDebugOnlyTrace t; // Global driver trace object GUID BPSKDevice_Guid = BPSKDevice_CLASS_GUID; #define INTCSR 0x68 //中断控制地址 #define DMAMODE0 0x80 //DMA0通道 #define DMAPADR0 0x84 //DMA0通道PCI地址 #define DMALADR0 0x88 //DMA0通道本地地址 #define DMASIZ0 0x8C //DMA0通道传输字节计数 #define DMADPR0 0x90 //DMA0通道指针 #define DMACSR0 0xA8 //DMA(0、1)通道状态 //////////////////////////////////////////////////////////////////////// // BPSKDevice::BPSKDevice // // 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. // BPSKDevice::BPSKDevice(PDEVICE_OBJECT Pdo, ULONG Unit) : KPnpDevice(Pdo, &BPSKDevice_Guid) { t << "Entering BPSKDevice::BPSKDevice (constructor)\n"; // Check constructor status if ( ! NT_SUCCESS(m_ConstructorStatus) ) { return; } // Remember our unit number m_Unit = Unit; // Initialize the lower device m_Lower.Initialize(this, Pdo); // 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. } //////////////////////////////////////////////////////////////////////// // BPSKDevice::~BPSKDevice // // Routine Description: // This is the destructor for the Functional Device Object, or FDO. // // Parameters: // None // // Return Value: // None // // Comments: // None // BPSKDevice::~BPSKDevice() { t << "Entering BPSKDevice::~BPSKDevice() (destructor)\n"; } char *PNPMinorFunctionName(ULONG mn) { static char* minors[] = { "IRP_MN_START_DEVICE", "IRP_MN_QUERY_REMOVE_DEVICE", "IRP_MN_REMOVE_DEVICE", "IRP_MN_CANCEL_REMOVE_DEVICE", "IRP_MN_STOP_DEVICE", "IRP_MN_QUERY_STOP_DEVICE", "IRP_MN_CANCEL_STOP_DEVICE", "IRP_MN_QUERY_DEVICE_RELATIONS", "IRP_MN_QUERY_INTERFACE", "IRP_MN_QUERY_CAPABILITIES", "IRP_MN_QUERY_RESOURCES", "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", "IRP_MN_QUERY_DEVICE_TEXT", "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", " ", "IRP_MN_READ_CONFIG", "IRP_MN_WRITE_CONFIG", "IRP_MN_EJECT", "IRP_MN_SET_LOCK", "IRP_MN_QUERY_ID", "IRP_MN_QUERY_PNP_DEVICE_STATE", "IRP_MN_QUERY_BUS_INFORMATION", "IRP_MN_DEVICE_USAGE_NOTIFICATION", "IRP_MN_SURPRISE_REMOVAL" }; if (mn > IRP_MN_SURPRISE_REMOVAL) return " "; else return minors[mn]; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::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 BPSKDevice::DefaultPnp(KIrp I) { t << "Entering BPSKDevice::DefaultPnp\n" << I << EOL; I.ForceReuseOfCurrentStackLocationInCalldown(); return m_Lower.PnpCall(this, I); } //////////////////////////////////////////////////////////////////////// // BPSKDevice::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 BPSKDevice::DefaultPower(KIrp I) { t << "Entering BPSKDevice::DefaultPower\n" << I << EOL; I.IndicatePowerIrpProcessed(); I.CopyParametersDown(); return m_Lower.PnpPowerCall(this, I); } //////////////////////////////////////////////////////////////////////////////// // BPSKDevice::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 BPSKDevice::SystemControl(KIrp I) { t << "Entering BPSKDevice::SystemControl\n"; I.ForceReuseOfCurrentStackLocationInCalldown(); return m_Lower.PnpCall(this, I); } //////////////////////////////////////////////////////////////////////// // BPSKDevice::Invalidate // // Routine Description: // Calls Invalidate methods for system resources // // Parameters: // None // // Return Value: // None // // Comments: // This function is called from OnStopDevice, OnRemoveDevice and // OnStartDevice (in error conditions). It calls the Invalidate // member funcitons for each resource to free the underlying system // resource if allocated. It is safe to call Invalidate more than // once for a resource, or for an uninitialized resource. VOID BPSKDevice::Invalidate() { // It is not necessary to release the system resource for the DMA adapter // object, since NT provides no mechanism for this. //不需要释放DMA适配器对象即m_Dma; if(m_Buffer.IsValid()) m_Buffer.Invalidate();//添加 // For each memory mapped region, release the underlying system resoruce. m_MemoryRange0.Invalidate(); // For each I/O port mapped region, release the underlying system resource. m_IoPortRange0.Invalidate(); m_IoPortRange1.Invalidate(); // For the interrupt, release the underlying system resource. // m_Irq.Invalidate(); if(m_pEvent) delete m_pEvent; if(m_pEvent1) delete m_pEvent1; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::OnStartDevice // // Routine Description: // Handler for IRP_MJ_PNP subfcn IRP_MN_START_DEVICE // // Parameters: // I - Current IRP // // Return Value: // NTSTATUS - Result code // // Comments: // Initialize the physical device. Typically, the driver initializes // physical resources here. Call I.AllocatedResources() for a list // of the raw resources that the system has assigned to the device, // or I.TranslatedResources() for the translated resource list. // NTSTATUS BPSKDevice::OnStartDevice(KIrp I) { t << "Entering BPSKDevice::OnStartDevice\n"; NTSTATUS status = STATUS_SUCCESS; I.Information() = 0; // The default Pnp policy has already cleared the IRP with the lower device // Initialize the physical device object. // Get the list of raw resources from the IRP PCM_RESOURCE_LIST pResListRaw = I.AllocatedResources(); // Get the list of translated resources from the IRP PCM_RESOURCE_LIST pResListTranslated = I.TranslatedResources(); // TODO: Check to ensure that the following parameters are correct for your hardware // #define MAX_DMA_LENGTH 0x100000 // 0x100000 is 1 MB //DMA对象 // Initialize the device descriptor for the DMA object using the assigned resource DEVICE_DESCRIPTION dd; RtlZeroMemory(&dd, sizeof(dd)); dd.Version = DEVICE_DESCRIPTION_VERSION; dd.Master = TRUE; dd.ScatterGather = FALSE; dd.DemandMode = FALSE;//Indicates whether to use the system DMA controller's demand mode. Not used for busmaster DMA. dd.AutoInitialize = FALSE; dd.Dma32BitAddresses = TRUE; dd.IgnoreCount = FALSE; dd.DmaChannel = 0; dd.InterfaceType = PCIBus; dd.DmaWidth = Width32Bits; // PCI default width 32bit dd.DmaSpeed = Compatible; dd.MaximumLength = MAX_DMA_LENGTH; // Initialize the DMA adapter object m_Dma.Initialize(&dd, m_Lower.TopOfStack()); m_Buffer.Initialize(&m_Dma,1024*64);//初始化KCommonDmaBuffer类对象大小64k KPciConfiguration PciConfig(m_Lower.TopOfStack()); // For each memory mapped region, initialize the memory mapped range // using the resources provided by NT. Once initialized, each memory // range's base virtual address in system space can be obtained by calling // member Base(). Each memory range's physical address in CPU space can // obtained by calling CpuPhysicalAddress(). To access the memory mapped // range use member functions such as inb/outb, or the array element operator. status = m_MemoryRange0.Initialize( pResListTranslated, pResListRaw, PciConfig.BaseAddressIndexToOrdinal(0) ); if (!NT_SUCCESS(status)) { Invalidate(); return status; } // For each I/O port mapped region, initialize the I/O port range using // the resources provided by NT. Once initialized, use member functions such as // inb/outb, or the array element operator to access the ports range. status = m_IoPortRange0.Initialize( pResListTranslated, pResListRaw, PciConfig.BaseAddressIndexToOrdinal(1) ); if (!NT_SUCCESS(status)) { Invalidate(); return status; } status = m_IoPortRange1.Initialize( pResListTranslated, pResListRaw, PciConfig.BaseAddressIndexToOrdinal(2), TRUE ); if (!NT_SUCCESS(status)) { Invalidate(); return status; } // Initialize and connect the interrupt status = m_Irq.InitializeAndConnect( pResListTranslated, LinkTo(Isr_Irq), this ); if (!NT_SUCCESS(status)) { Invalidate(); return status; } // Setup the DPC to be used for interrupt processing m_DpcFor_Irq.Setup(LinkTo(DpcFor_Irq), this); // TODO: Add device-specific code to start your device. // The base class will handle completion return status; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::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. // Some function codes may be handled immediately, // while others may be serialized through the StartIo routine. // // The KPnpDevice class handles restricting IRP flow // if the device is stopping or being removed. // NTSTATUS BPSKDevice::DeviceControl(KIrp I) { NTSTATUS status; t << "Entering BPSKDevice::Device Control, " << I << EOL; switch (I.IoctlCode()) { case CONFIG_SYMBOL_RATE: status = CONFIG_SYMBOL_RATE_Handler(I); break; case MODULATE_MODE: status = MODULATE_MODE_Handler(I); break; case SET_IF_FRE: status = SET_IF_FRE_Handler(I); break; case CTRL_AD9851_INIT: status = CTRL_AD9851_INIT_Handler(I); break; case IOCTL_SET_NOTIFICATION_EVENT: status = IOCTL_SET_NOTIFICATION_EVENT_Handler(I); break; case START_COLLECT: status = START_COLLECT_Handler(I); break; case STOP_COLLECT: status = STOP_COLLECT_Handler(I); break; default: // Unrecognized IOCTL request status = STATUS_INVALID_PARAMETER; break; } // If the IRP was queued, or its 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); } } //////////////////////////////////////////////////////////////////////// // BPSKDevice::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 BPSKDevice::OnStopDevice(KIrp I) { NTSTATUS status = STATUS_SUCCESS; t << "Entering BPSKDevice::OnStopDevice\n"; // Device stopped, release the system resources. Invalidate(); // 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); } //////////////////////////////////////////////////////////////////////// // BPSKDevice::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 BPSKDevice::OnRemoveDevice(KIrp I) { t << "Entering BPSKDevice::OnRemoveDevice\n"; // Device removed, release the system resources. m_Irq.Disconnect(); // Device removed, release the system resources. m_Irq.Invalidate(); Invalidate(); // 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); } VOID BPSKDevice::CancelQueuedIrp(KIrp I) { KDeviceQueue dq(DeviceQueue()); // Test if the IRP is the current IRP如果请求的IRP是当前IRP就直接将他删除. if ( (PIRP)I == CurrentIrp() ) { CurrentIrp() = NULL; CancelSpinLock::Release(I.CancelIrql()); I.Information() = 0; I.Status() = STATUS_CANCELLED; PnpNextIrp(I); } // See if the IRP can be removed from the device queue,如果不是当前的但是在排队序列中就找到他然后将其删除. else if (dq.RemoveSpecificEntry(I)) { CancelSpinLock::Release(I.CancelIrql()); I.Information() = 0; I.PnpComplete(this, STATUS_CANCELLED); } //如果请求取消的IRP不在对列中,释放对IRP的请求 else { CancelSpinLock::Release(I.CancelIrql()); } } VOID BPSKDevice::StartIo(KIrp I) { if ( !I.TestAndSetCancelRoutine( LinkTo(CancelQueuedIrp), NULL, CurrentIrp()) ) { return; } switch (I.MajorFunction()) { case IRP_MJ_READ: SerialRead(I); break; case IRP_MJ_WRITE: SerialWrite(I); break; default: ASSERT(FALSE); PnpNextIrp(I); break; } } //////////////////////////////////////////////////////////////////////// // BPSKDevice::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 BPSKDevice::OnDevicePowerUp(KIrp I) { NTSTATUS status = STATUS_SUCCESS; t << "Entering BPSKDevice::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); } //////////////////////////////////////////////////////////////////////// // BPSKDevice::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 BPSKDevice::OnDeviceSleep(KIrp I) { NTSTATUS status = STATUS_SUCCESS; t << "Entering BPSKDevice::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); } //////////////////////////////////////////////////////////////////////// // BPSKDevice::Create // // Routine Description: // Handler for IRP_MJ_CREATE // // Parameters: // I - Current IRP // // Return Value: // NTSTATUS - Result code // // Comments: // NTSTATUS BPSKDevice::Create(KIrp I) { NTSTATUS status; t << "Entering BPSKDevice::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 << "BPSKDevice::Create Status " << (ULONG)status << EOL; return status; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::Close // // Routine Description: // Handler for IRP_MJ_CLOSE // // Parameters: // I - Current IRP // // Return Value: // NTSTATUS - Result code // // Comments: // NTSTATUS BPSKDevice::Close(KIrp I) { NTSTATUS status; t << "Entering BPSKDevice::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 << "BPSKDevice::Close Status " << (ULONG)status << EOL; return status; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::Cleanup // // Routine Description: // Handler for IRP_MJ_CLEANUP // // Parameters: // I - Current IRP // // Return Value: // NTSTATUS - Result code // // Comments: // NTSTATUS BPSKDevice::CleanUp(KIrp I) { t << "Entering CleanUp, " << I << EOL; // TODO: Insert your code to respond to the CLEANUP message. // This code cleans up the single Wizard created queue. If you // have created additional queues, or have any outstanding Irps // stored in some other fashion in your driver, you should clean // these up as well for the file object specified in the cleanup Irp. KDeviceQueue dq(DeviceQueue()); dq.PnpCleanUp(this, I.FileObject()); return I.PnpComplete(this, STATUS_SUCCESS); } //////////////////////////////////////////////////////////////////////// // BPSKDevice::SerialRead // // Routine Description: // Handler for serialized READ // // Parameters: // I - Current IRP // // Return Value: // None // // Comments: // This routine is called when the IRP is removed from the // STARTIO queue. This guarantees that multiple requests are // never processed simultaneously. // // This routine is called at dispatch level. // void BPSKDevice::SerialRead(KIrp I) { t << "Entering BPSKDevice::SerialRead, " << I << EOL; NTSTATUS status = STATUS_SUCCESS; //进行DMA传输 m_CurrentTransfer=new(NonPagedPool)KDmaTransfer(this,&m_Dma); if(m_CurrentTransfer==NULL) { status=STATUS_INSUFFICIENT_RESOURCES; t<<"unable to allocate transfer object:"< Initiate(I.Mdl(),(I.MajorFunction()==IRP_MJ_READ)? FromDeviceToMemory:FromMemoryToDevice, LinkTo(OnDmaReady) ); */ status=m_CurrentTransfer->Initiate(this,&m_Dma,I.Mdl(),(I.MajorFunction()==IRP_MJ_READ)? FromDeviceToMemory:FromMemoryToDevice, LinkTo(OnDmaReady),&m_Buffer ); // If the transfer cannot be initiated, complete it with an error status. if ( ! NT_SUCCESS(status) ) { t<<"unable to initiate transfer: "<< status< BytesCount;i++) { t<< "Control Word is: "< ControlWord[i]< ControlWord[i]); } BYTE TEMP=m_IoPortRange1.inb(0xf0);//0xf0:Range for PCI-to-Local Address Space 1 I.Information() = 0; return status; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::MODULATE_MODE_Handler // // Routine Description: // Handler for IO Control Code MODULATE_MODE // // Parameters: // I - IRP containing IOCTL request // // Return Value: // NTSTATUS - Status code indicating success or failure // // Comments: // This routine implements the MODULATE_MODE function. // This routine runs at passive level. // NTSTATUS BPSKDevice::MODULATE_MODE_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; t << "Entering BPSKDevice::MODULATE_MODE_Handler, " << I << EOL; // TODO: Verify that the input parameters are correct // If not, return STATUS_INVALID_PARAMETER // TODO: Handle the the MODULATE_MODE request, or // defer the processing of the IRP (i.e. by queuing) and set // status to STATUS_PENDING. // TODO: Assuming that the request was handled here. Set I.Information // to indicate how much data to copy back to the user. BYTE *ModulMode=(BYTE *)(I.IoctlBuffer()); BYTE TEMP=*ModulMode; m_IoPortRange1.outb(0x30,*ModulMode);//0x30:PCI Base Address for Local Expansion ROM I.Information() = 0; return status; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::SET_IF_FRE_Handler // // Routine Description: // Handler for IO Control Code SET_IF_FRE // // Parameters: // I - IRP containing IOCTL request // // Return Value: // NTSTATUS - Status code indicating success or failure // // Comments: // This routine implements the SET_IF_FRE function. // This routine runs at passive level. // NTSTATUS BPSKDevice::SET_IF_FRE_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; t << "Entering BPSKDevice::SET_IF_FRE_Handler, " << I << EOL; // TODO: Verify that the input parameters are correct // If not, return STATUS_INVALID_PARAMETER // TODO: Handle the the SET_IF_FRE request, or // defer the processing of the IRP (i.e. by queuing) and set // status to STATUS_PENDING. // TODO: Assuming that the request was handled here. Set I.Information // to indicate how much data to copy back to the user. IF_FRE_STRUCT *IF_FRE= (IF_FRE_STRUCT *)(I.IoctlBuffer()); for(DWORD i = 0;i < IF_FRE->BytesCount;i++) { t<< "Control Word is: "< ControlWord[i]< ControlWord[i]); } m_IoPortRange1.inb(0x60);//0x60:PCI-to-Local Doorbell Register I.Information() = 0; return status; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::CTRL_AD9851_INIT_Handler // // Routine Description: // Handler for IO Control Code CTRL_AD9851_INIT // // Parameters: // I - IRP containing IOCTL request // // Return Value: // NTSTATUS - Status code indicating success or failure // // Comments: // This routine implements the CTRL_AD9851_INIT function. // This routine runs at passive level. // NTSTATUS BPSKDevice::CTRL_AD9851_INIT_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; t << "Entering BPSKDevice::CTRL_AD9851_INIT_Handler, " << I << EOL; // TODO: Verify that the input parameters are correct // If not, return STATUS_INVALID_PARAMETER // TODO: Handle the the CTRL_AD9851_INIT request, or // defer the processing of the IRP (i.e. by queuing) and set // status to STATUS_PENDING. // TODO: Assuming that the request was handled here. Set I.Information // to indicate how much data to copy back to the user. m_IoPortRange1.inb(0x90); AD9851_CONTROL_STRUCT *AD9851_ctrl = (AD9851_CONTROL_STRUCT *)(I.IoctlBuffer()); for(DWORD i = 0;i < AD9851_ctrl->BytesCount;i++) { t<< "Control Word is: "< ControlWord[i]< ControlWord[i]); } m_IoPortRange1.inb(0x60);//0x60:PCI-to-Local Doorbell Register I.Information() = 0; return status; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::BPSK_IOCTL_804_Handler // // Routine Description: // Handler for IO Control Code BPSK_IOCTL_804 // // Parameters: // I - IRP containing IOCTL request // // Return Value: // NTSTATUS - Status code indicating success or failure // // Comments: // This routine implements the BPSK_IOCTL_804 function. // This routine runs at passive level. // NTSTATUS BPSKDevice::IOCTL_SET_NOTIFICATION_EVENT_Handler(KIrp I) { t << "Entering BPSKDevice::IOCTL_SET_NOTIFICATION_EVENT_Handler, " << I << EOL; HANDLE hEvent; NTSTATUS status; hEvent=*(HANDLE*)I.IoctlBuffer(); /* KMemory Mem(I.Mdl()); // Use the memory object to create a pointer to the caller's buffer hEvent=*(HANDLE*) Mem.MapToSystemSpaceAddress(); */ m_pEvent=new(NonPagedPool)KEvent(hEvent,OBJECT_TYPE_ALL_ACCESS); status=(m_pEvent!=NULL)?STATUS_SUCCESS:STATUS_INSUFFICIENT_RESOURCES; I.Information()=0; return status; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::DpcFor_Irq // // Routine Description: // Deferred Procedure Call (DPC) for Irq // // Parameters: // Arg1 - User-defined context variable // Arg2 - User-defined context variable // // Return Value: // None // // Comments: // This function is called for secondary processing of an interrupt. // Most code that runs at elevated IRQL should run here rather than // in the ISR, so that other interrupt handlers can continue to run. // VOID BPSKDevice::DpcFor_Irq(PVOID Arg1, PVOID Arg2) { t<<"Entering Dpc"< Continue(UseTransferSize); t<<"继续DMA传输"< Set(); } else t<<"DPC error synchronizing\n"; } } UNREFERENCED_PARAMETER(Arg1); UNREFERENCED_PARAMETER(Arg2); } BOOLEAN BPSKDevice::TestAndClearNotifyApp(PVOID p) { t<<"Entering BPSKDevice::TestAndClearNotifyApp, "<< EOL; *(BOOLEAN*)p=m_bNotifyApp; m_bNotifyApp=FALSE; return TRUE; } //////////////////////////////////////////////////////////////////////// // BPSKDevice::Isr_Irq // // Routine Description: // Interrupt Service Routine (ISR) for IRQ Irq // // Parameters: // None // // Return Value: // BOOLEAN True if this is our interrupt // // Comments: // BOOLEAN BPSKDevice::Isr_Irq(void) { t<<"Entering Isr_Irq."< BytesRemaining(); if (pXfer->BytesRemaining() == 0) { // If there are no bytes left to transfer, the callback must call // Terminate(). Then it completes the IRP with STATUS_SUCCESS. pXfer->Terminate(); I.Information() = I.ReadSize(CURRENT); I.Status() = STATUS_SUCCESS; PnpNextIrp(I); m_CurrentTransfer = NULL; // t<<"一次DMA传输结束,通知应用程序取数据"< Set(); delete pXfer; m_IoPortRange0.outd(INTCSR,0x40900);//允许本地中断 return; } // We must get the descriptor for the physical memory location for // the DMA transfer. PTRANSFER_DESCRIPTOR ptd; while (pXfer->SequenceTransferDescriptors(&ptd)) { // program the h/w using ppTD t << " Physical address 0x" << ptd->td_PhysAddr.LowPart << ". Length is 0x" << ptd->td_Length << "." << EOL; } // If this is the first time through, then start the DMA going. // We only want to do this ONCE for a given Read transfer. That // way, our data will be collected smoothly, without interruptions // or dropouts. TEMP=I.ReadSize(); if ((ULONG) pXfer->BytesRemaining() == I.ReadSize()) StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length); } NTSTATUS BPSKDevice::START_COLLECT_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; ULONG test2; t << "Entering BPSKDevice::START_COLLECT_Handler, " << I << EOL; // m_IoPortRange1.inb(0x90); m_IoPortRange1.inb(0x10);//0x10 // TODO:允许PCI中断和DMA通道0中断 m_IoPortRange0.outd(INTCSR,0x40900); test2=m_IoPortRange0.ind(INTCSR); I.Information() = 0; return status; } //////////////////////////////////////////////////////////////////////// // PCI9054Device::PCI9054_IOCTL_803_Handler // // Routine Description: // Handler for IO Control Code PCI9054_IOCTL_803 // // Parameters: // I - IRP containing IOCTL request // // Return Value: // NTSTATUS - Status code indicating success or failure // // Comments: // This routine implements the PCI9054_IOCTL_803 function. // This routine runs at passive level. // NTSTATUS BPSKDevice::STOP_COLLECT_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; t << "Entering BPSKDevice::STOP_COLLECT_Handler, " << I << EOL; m_IoPortRange1.inb(0x20);//0x20:Local Base Address for PCI Initiator-to-PCI Memory I.Information() = 0; return status; }