⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 driverwi.c

📁 profibus-dp主站源代码
💻 C
字号:
//-----------------------------------------------------------------------------
// $Id: driverwinnt.c,v 1.0.0                                       2004/01/13
//-----------------------------------------------------------------------------
//
//      ProfiM - PROFIBUS MASTER DRIVER FOR WINDOWS NT/2000
//
// Author:  
//      Pavel Trnka, CTU FEE
//      trnkap@seznam.cz
// With help and advices from:
//      Ing. Petr Smolik, CTU FEE
//      Ing. Pavel Pisa, CTU FEE
//      Ing. Pavel Burget, CTU FEE
//
//-----------------------------------------------------------------------------
//
// Popis:
// ------
//   Cast ovladace, ktera je do projektu vkladana pokud ovladac neni prekladan
// s podporou PnP - falesne makro PnP (vardef.h) neni nadefinovano. Prelozeny
// ovladac je tak urcen do prostredi Windows NT.
//   Zajistuje start ovladace vytvorenim vstupni bodu DriverEntry a ukoncovani
// jeho cinnosti (UnloadDriver).
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------






//---------------------------------------------------------------------------
// DriverEntry
//
// Description:
//  NT device Driver Entry point
//
// Arguments:
//      DriverObject    - Pointer to this device's driver object
//      RegistryPath    - Pointer to the Unicode regsitry path name
//
// Return Value:
//      NTSTATUS
//
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject,
                      IN PUNICODE_STRING RegistryPath )
{
  PDEVICE_OBJECT            deviceObject  = NULL;
  NTSTATUS                  status, ioConnectStatus;
  UNICODE_STRING            uniNtNameString;
  UNICODE_STRING            uniWin32NameString;
  KIRQL                     irql          = DEF_IRQ_LINE;
  KAFFINITY                 Affinity;
  ULONG                     MappedVector, AddressSpace = 1;
  PPROFIM_DEVICE_EXTENSION  extension;
  BOOLEAN                   ResourceConflict;
  PHYSICAL_ADDRESS          InPortAddr, OutPortAddr;


  RS_DbgPrint( "ProfiM: Enter the driver!\n" );
  DbgPrint ("ProfiM: Version 0.025 (%s  %s)\n",__TIME__,__DATE__);

  //
  // Create counted string version of our device name.
  //

  RtlInitUnicodeString( &uniNtNameString, NT_DEVICE_NAME );

  //
  // Create the device object, single-thread access (TRUE)
  //

  status = IoCreateDevice( DriverObject,
                           sizeof( PROFIM_DEVICE_EXTENSION ),
                           &uniNtNameString,
                           FILE_DEVICE_UNKNOWN,
                           0,
                           TRUE,
                           &deviceObject );

  if ( !NT_SUCCESS( status ) )
  {
    RS_DbgPrint( "ProfiM: IoCreateDevice failed\n" );
    return status;
  }

  extension = ( PPROFIM_DEVICE_EXTENSION ) deviceObject->DeviceExtension;
    
  //
  // Initialize structure control identificator
  //
  extension->magic = PROFIM_MAGIC;
  extension->PB.AllInitialized = FALSE;
  extension->ContinueFrame = FALSE;  
    
  //
  // Set the FLAGS field
  //
  deviceObject->Flags |= DO_BUFFERED_IO;

  //
  // Get the configuration information from the Registry
  //

  status = GetConfiguration( deviceObject->DeviceExtension, RegistryPath );

  if ( !NT_SUCCESS( status ) )
  {
    RS_DbgPrint( "ProfiM: GetConfiguration failed\n" );
    return status;
  }

  //
  // This call will map our IRQ to a system vector. It will also fill
  // in the IRQL (the kernel-defined level at which our ISR will run),
  // and affinity mask (which processors our ISR can run on).
  //
  // We need to do this so that when we connect to the interrupt, we
  // can supply the kernel with this information.
  //
  MappedVector = HalGetInterruptVector( Isa,        // Interface type
            0,          // Bus number
            extension->IRQLine, extension->IRQLine, &irql,      // IRQ level
 & Affinity   // Affinity mask
  );

  //
  // A little known Windows NT fact,
  // If MappedVector==0, then HalGetInterruptVector failed.
  //

  if ( MappedVector == 0 )
  {
    RS_DbgPrint( "ProfiM: HalGetInterruptVector failed\n" );
    return ( STATUS_INVALID_PARAMETER );
  }

  //
  // Save off the Irql
  //

  extension->Irql = irql;

  //
  // Translate the base port address to a system mapped address.
  // This will be saved in the device extension after IoCreateDevice,
  // because we use the translated port address to access the ports.
  //

  InPortAddr.LowPart = ( ULONG ) extension->PortAddress;
  InPortAddr.HighPart = 0;
  if ( !HalTranslateBusAddress( Isa,
                                0,
                                InPortAddr,
                                &AddressSpace,
                                &OutPortAddr ) )
  {
    RS_DbgPrint( "ProfiM: HalTranslateBusAddress failed\n" );
    return STATUS_SOME_NOT_MAPPED;
  }


  if ( NT_SUCCESS( status ) )
  {
    //
    // Create dispatch points for create/open, close, unload, and ioctl
    //

    DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchRoutine;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchRoutine;
    DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRoutine;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchRoutine;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchRoutine;
    DriverObject->DriverUnload = UnloadDriver;

    //
    // check if resources (ports and interrupt) are available
    //
    ReportUsage( DriverObject, deviceObject, OutPortAddr, &ResourceConflict );

    if ( ResourceConflict )
    {
      RS_DbgPrint( "ProfiM: Couldn't get resources\n" );
      IoDeleteDevice( deviceObject );
      return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // fill in the device extension
    //
    extension = ( PPROFIM_DEVICE_EXTENSION ) deviceObject->DeviceExtension;
    extension->DeviceObject = deviceObject;
    extension->PortAddress = ( PVOID ) OutPortAddr.LowPart;
    
    
    KeInitializeDpc(&extension->CompleteDPC, ProfiM_CompleteDPC, extension);
    
    KeInitializeSpinLock( &(extension->InterruptSpinLock) );    
    

    //
    // connect the device driver to the IRQ
    //
    ioConnectStatus = IoConnectInterrupt( &extension->InterruptObject,
                                          ProfiM_Isr,
                                          extension->DeviceObject,
                                          &(extension->InterruptSpinLock),
                                          MappedVector,
                                          irql,
                                          irql,
                                          Latched,
                                          FALSE,
                                          Affinity,
                                          FALSE );

    if ( !NT_SUCCESS( ioConnectStatus ) )
    {
      RS_DbgPrint( "ProfiM: Couldn't connect interrupt\n" );
      IoDeleteDevice( deviceObject );
      return ioConnectStatus;
    }

    RS_DbgPrint( "ProfiM: just about ready!\n" );

    //
    // Create counted string version of our Win32 device name.
    //

    RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );

    //
    // Create a link from our device name to a name in the Win32 namespace.
    //

    status = IoCreateSymbolicLink( &uniWin32NameString, &uniNtNameString );

    if ( !NT_SUCCESS( status ) )
    {
      RS_DbgPrint( "ProfiM: Couldn't create the symbolic link\n" );
      IoDeleteDevice( DriverObject->DeviceObject );
    }
    else
    {
      //
      // Setup the Dpc for ISR routine
      //

      IoInitializeDpcRequest( DriverObject->DeviceObject, ProfiM_Dpc_Routine );
            

      //
      // Initialize the device (enable IRQ's, hit the hardware)
      //

      Initialize_ProfiM( extension, 0 );

      /// Nastaveni priznaku vysilani                        
      extension->Sending = FALSE;  
      // priznak k vymazani vsech casovacich znaku ze zacatku vysilaci fronty                   
      extension->FlushTCH = FALSE;
      
      // umozni rozbeh ovladace nez se aktivuje hlidaci rutina watchdogu
      extension->WatchDogTrigger = 0;
      

      extension->HIDCounter = 1;

#ifdef PISA_IO            
      extension->ModemInterruptState = MI_Disabled;
#endif

      RS_DbgPrint( "ProfiM: All initialized!\n" );

      PB_Init( &( extension->PB ), extension, RegistryPath );
    }
  }
  else
  {
    RS_DbgPrint( "ProfiM: Couldn't create the device\n" );
  }
  return status;
}




//---------------------------------------------------------------------------
// UnloadDriver
//
// Description:
//     Free all the allocated resources, etc.
//
// Arguments:
//     DriverObject - pointer to a driver object
// 
// Return Value:
//      None
// 
VOID UnloadDriver( IN PDRIVER_OBJECT DriverObject )
{
  WCHAR                     deviceLinkBuffer[]  = L"\\DosDevices\\ProfiM";
  UNICODE_STRING            deviceLinkUnicodeString;
  PPROFIM_DEVICE_EXTENSION  extension;

  extension = DriverObject->DeviceObject->DeviceExtension;

  PB_Close( &( extension->PB ) );

  //
  // Deactivate all of the MCR interrupt sources.
  //

  WRITE_PORT_UCHAR( extension->ComPort.MCR, MCR_DEACTIVATE_ALL );

  //
  // Free any resources
  //

  IoDisconnectInterrupt( extension->InterruptObject );

  //
  // Delete the symbolic link
  //

  RtlInitUnicodeString( &deviceLinkUnicodeString, deviceLinkBuffer );

  IoDeleteSymbolicLink( &deviceLinkUnicodeString );

  //
  // Delete the device object
  //

  IoDeleteDevice( DriverObject->DeviceObject );

  RS_DbgPrint( "ProfiM: Unloaded\n" );
  return;
}




//---------------------------------------------------------------------------
// ReportUsage
//
// Description:
//  This routine registers (reports) the I/O and IRQ usage for this driver.
//
// Arguments:
//      DriverObject    - Pointer to the driver object
//      DeviceObject    - Pointer to the Device object
//      PortAddress     - Address of I/O port used
//      ConflictDetected - TRUE if a resource conflict was detected.
//
// Return Value:
//      TRUE    - If a Resource conflict was detected
//      FALSE   - If no conflict was detected
//
BOOLEAN ReportUsage( IN PDRIVER_OBJECT DriverObject,
                     IN PDEVICE_OBJECT DeviceObject,
                     IN PHYSICAL_ADDRESS PortAddress,
                     IN BOOLEAN *ConflictDetected )
{
  PPROFIM_DEVICE_EXTENSION        extension;

  ULONG                           sizeOfResourceList;
  PCM_RESOURCE_LIST               resourceList;
  PCM_FULL_RESOURCE_DESCRIPTOR    nextFrd;
  PCM_PARTIAL_RESOURCE_DESCRIPTOR partial;

  extension = ( PPROFIM_DEVICE_EXTENSION ) DeviceObject->DeviceExtension;

  //
  // The size of the resource list is going to be one full descriptor
  // which already has one partial descriptor included, plus another
  // partial descriptor. One partial descriptor will be for the
  // interrupt, and the other for the port addresses.
  //

  sizeOfResourceList = sizeof( CM_FULL_RESOURCE_DESCRIPTOR );

  //
  // The full resource descriptor already contains one
  // partial. Make room for one more.
  //
  // It will hold the irq "prd", and the port "prd".
  //    ("prd" = partial resource descriptor)
  //

  sizeOfResourceList += sizeof( CM_PARTIAL_RESOURCE_DESCRIPTOR );

  //
  // Now we increment the length of the resource list by field offset
  // of the first frd.   This will give us the length of what preceeds
  // the first frd in the resource list.
  //   (frd = full resource descriptor)
  //

  sizeOfResourceList += FIELD_OFFSET( CM_RESOURCE_LIST, List[0] );

  resourceList = ExAllocatePool( PagedPool, sizeOfResourceList );

  if ( !resourceList )
  {
    return FALSE;
  }

  //
  // Zero out the list
  //

  RtlZeroMemory( resourceList, sizeOfResourceList );

  resourceList->Count = 1;
  nextFrd = &resourceList->List[0];

  nextFrd->InterfaceType = Isa;
  nextFrd->BusNumber = 0;

  //
  // We are going to report port addresses and interrupt
  //

  nextFrd->PartialResourceList.Count = 2;

  //
  // Now fill in the port data.  We don't wish to share
  // this port range with anyone.
  //
  // Note: the port address we pass in is the one we got
  // back from HalTranslateBusAddress.
  //

  partial = &nextFrd->PartialResourceList.PartialDescriptors[0];

  partial->Type = CmResourceTypePort;
  partial->ShareDisposition = CmResourceShareDriverExclusive;
  partial->Flags = CM_RESOURCE_PORT_IO;
  partial->u.Port.Start = PortAddress;
  partial->u.Port.Length = DEF_PORT_RANGE;

  partial++;

  //
  // Now fill in the irq stuff.
  //
  // Note: for IoReportResourceUsage, the Interrupt.Level and
  // Interrupt.Vector are bus-specific level and vector, just
  // as we passed in to HalGetInterruptVector, not the mapped
  // system vector we got back from HalGetInterruptVector.
  //

  partial->Type = CmResourceTypeInterrupt;
  partial->u.Interrupt.Level = extension->IRQLine;
  partial->u.Interrupt.Vector = extension->IRQLine;
  partial->ShareDisposition = CmResourceShareDriverExclusive;
  partial->Flags = CM_RESOURCE_INTERRUPT_LATCHED;

  IoReportResourceUsage( NULL,
                         DriverObject,
                         resourceList,
                         sizeOfResourceList,
                         NULL,
                         NULL,
                         0,
                         FALSE,
                         ConflictDetected );

  //
  // The above routine sets the BOOLEAN parameter ConflictDetected
  // to TRUE if a conflict was detected.
  //

  ExFreePool( resourceList );

  return ( *ConflictDetected );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -