📄 profim.c
字号:
//-----------------------------------------------------------------------------
// $Id: ProfiM.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:
// ------
// Nejnizsi vrstva ProfiMu. Zajistuje start ovladace (DriverEntry) a jeho
// rozhrani pro spolupraci se systemem. Pro vyssi vrstvy ProfiMu umoznuje vy-
// silani ramcu na sbernici a predevsim zajisteni rychleho casovani, ktere je
// nezbytne pro dodrzeni casovych intervalu specifikace Profibusu.
// Nastavenim falesneho makra "PnP" v headru vardef.h je ovladac prelozen
// s podporou Plug and Play a muze tak byt pouzivan v systemu Windows 2000.
// Jinak je ovladac prelozen pro system Windows NT.
//
// Funkce volane z vnejsku:
// ------------------------
//
// DriverEntry - pozadavek systemu na spusteni ovladace
// ProfiM_Isr - obsluha preruseni
// DispatchRoutine - komunikace s aplikacni vrstvou
//
// ProfiM_SendOut - pozadavek vyssi vrstvy na vysilani (casovacich,
// synchronizacnich nebo datovych znaku)
// ProfiM_ClearTimingChars - zastavi odpocet time-outu
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
// Include files
//
#include "NTDDK.H"
#include "COM8250.H"
#include "Profibus.h"
#include "PROFIM.H"
#include "ProfiMIOC.H"
//---------------------------------------------------------------------------
//
// Define the driver names
//
#define NT_DEVICE_NAME L"\\Device\\ProfiM"
#define DOS_DEVICE_NAME L"\\DosDevices\\ProfiM"
//-----------------------------------------------------------------------------
//
// Declare forward function references
//
NTSTATUS DispatchRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID UnloadDriver( IN PDRIVER_OBJECT DriverObject );
BOOLEAN ReportUsage( IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject,
IN PHYSICAL_ADDRESS PortAddress,
IN BOOLEAN *ConflictDetected );
BOOLEAN ProfiM_Isr( IN PKINTERRUPT Interrupt, IN OUT PVOID Context );
VOID ProfiM_CompleteDPC( IN PKDPC Dpc, IN PVOID DeferredContext,
IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
BOOLEAN ProfiM_CompleteDPC_Synch( IN PPROFIM_DEVICE_EXTENSION DeviceExtension );
VOID ProfiM_Dpc_Routine( IN PKDPC Dpc,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context );
NTSTATUS GetConfiguration( IN PPROFIM_DEVICE_EXTENSION DeviceExtension,
IN PUNICODE_STRING RegistryPath );
NTSTATUS GetPnPConfiguration( IN PPROFIM_DEVICE_EXTENSION DeviceExtension);
NTSTATUS Initialize_ProfiM( IN PPROFIM_DEVICE_EXTENSION DeviceExtension,
int chip_options );
/*NTSTATUS ProfiM_Write( IN PPROFIM_DEVICE_EXTENSION DeviceExtension,
IN PIRP Irp );*/
BOOLEAN ProfiM_Write( IN PPROFIM_DEVICE_EXTENSION DeviceExtension );
/*NTSTATUS ProfiM_Read( IN PPROFIM_DEVICE_EXTENSION deviceExtension,
IN PIRP Irp );*/
BOOLEAN ProfiM_Read( IN PPROFIM_DEVICE_EXTENSION DeviceExtension );
void FillTxBuffer( PPROFIM_DEVICE_EXTENSION DeviceExtension );
void Jam_First_Out( PPROFIM_DEVICE_EXTENSION DeviceExtension );
BOOLEAN AllSent( PPROFIM_DEVICE_EXTENSION DeviceExtension );
BOOLEAN LastOfSameType( PPROFIM_DEVICE_EXTENSION DeviceExtension );
BOOLEAN LastToSend( PPROFIM_DEVICE_EXTENSION DeviceExtension );
void ProfiM_IrpCancel( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
BOOLEAN ProfiM_WatchDog_Synch( IN PPROFIM_DEVICE_EXTENSION DeviceExtension );
//---------------------------------------------------------------------------
//
// Begin FUNCTIONS
//
//---------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
// 16950 SUPPORT
/////////////////////////////////////////////////////////////////////////////
#include "16950pci.c"
/////////////////////////////////////////////////////////////////////////////
// Pri prekladu pro Windows NT neobsahuje ovladac podporu PnP
#ifndef PnP
#include "DriverWinNT.c"
#endif
// Podpora PnP pri prekladu ovladace pro systemy Windows 2000 ev. Windows XP
#ifdef PnP
#include "DriverPnP.c"
#endif
//***************************************************************************
// ProfiM_Isr
//
// Description:
// This is our 'C' Isr routine to handle transmit and recieve
//
// Arguments:
// Interrupt - Pointer to our interrupt object
// Context - Pointer to our device object
//
// Return Value:
// TRUE - If this was our ISR
//
//***************************************************************************
BOOLEAN ProfiM_Isr( IN PKINTERRUPT Interrupt, IN OUT PVOID Context )
{
PDEVICE_OBJECT DeviceObject;
PPROFIM_DEVICE_EXTENSION DeviceExtension;
UCHAR ch;
int cit;
int pom; /*DEBUG*/
if ( !Context )
{
DbgPrint( "ProfiM: ISR Error - Context is NULL!" );
return FALSE;
}
//
// Get the Device Object and obtain our Extension
//
DeviceObject = Context;
DeviceExtension = DeviceObject->DeviceExtension;
//
// Check DeviceExtension
//
if ( !DeviceExtension )
{
DbgPrint( "ProfiM: ISR Error - DeviceExtension is NULL!" );
return FALSE;
}
if ( DeviceExtension->magic != PROFIM_MAGIC )
{
DbgPrint( "ProfiM: ISR Error - Device Extension MAGIC is invalid!" );
return FALSE;
}
//
// Bump the interrupt count
//
//DeviceExtension->InterruptCount++;
//
// Shozeni priznaku pro WatchDog
//
DeviceExtension->WatchDogTrigger = 0;
//*******************************************************
// ISR for 16PCI954
//*******************************************************
if ( CHIP950 )
{
ch = u950pci_inb( DeviceExtension->port, UART_IIR );
//
// Je preruseni pro nas?
//
if ( ch & UART_IIR_NO_INT )
return FALSE;
if ( ! DeviceExtension->PB.AllInitialized )
return TRUE;
//
// Probiha-li ukladani dat do vystupniho Tx FIFO je preruseni ignorovano
//
if (DeviceExtension->Buffering)
{
//DbgPrint(" ISR: Buffering !!!");
return TRUE;
}
/*DEBUG*/
//u950pci_outb( DeviceExtension->port, UART_IER, 0 ); /* disable interrupts */
if (DeviceExtension->InterruptRunning) /*DEBUG*/
{
DeviceExtension->SecondInterrupt = TRUE;
DbgPrint( "ProfiM: Dve preruseni najednou!!!" );
/*
DbgPrint( "ProfiM: Dve preruseni najednou (LastIIR=%d IIR=%d) !?!?!", DeviceExtension->LastIIR, ch);
DbgPrint( " LastMasterState = %d MasterState = %d", DeviceExtension->PB.MasterState, DeviceExtension->PB.LastState );
DbgPrint( " XmitFirst = %d XmitLast = %d", DeviceExtension->XmitFirst, DeviceExtension->XmitLast );
pom=DeviceExtension->XmitFirst--;
if ( pom<0 ) pom = DeviceExtension->BufferSize - 1;
DbgPrint( " Last Transmit Type = %x Last Transmit Byte = %x", DeviceExtension->XmitTypeBuffer[pom], DeviceExtension->XmitBuffer[pom] );
*/
return TRUE; //nebo radsi TRUE jako ze preruseni bylo nase???
}
DeviceExtension->InterruptRunning = TRUE;
DeviceExtension->LastIIR = ch;
//DbgPrint ("ProfiM: ISR( IIR = %d ) !\n",ch);
while ( ! ( ch & UART_IIR_NO_INT ) )
{
switch ( ch & UART_IIR_ID )
{
//*********************************************************************
// Receiver - line status interrupt - receive error
//*********************************************************************
case UART_IIR_RLSI:
DbgPrint( "ProfiM: Receiver ERROR !" );
break;
//*********************************************************************
// Receiver - data time-out
//*********************************************************************
case UART_IIR_TIMEOUT:
#ifdef USE_RX_FIFO
DbgPrint( "ProfiM: ISR TIME-OUT!" );
while ( u950pci_RxDataReady( DeviceExtension ) )
{
ch = u950pci_inb( DeviceExtension->port, UART_RX );
PB_RxByte( &( DeviceExtension->PB ), ch );
}
DeviceExtension->ContinueFrame = FALSE;
#ifndef AUTOMATIC_RX
u950pci_RxTreshold( DeviceExtension , 1 );
#endif
#endif
break;
//*********************************************************************
// Receiver - data interrupt
//*********************************************************************
case UART_IIR_RDI:
// automatic receive (direction switching) with full FIFO support
#ifdef AUTOMATIC_RX
cit=300;
//DbgPrint("ProfiM: Rx INT");
while ( u950pci_RxDataReady( DeviceExtension ) && cit>0 )
{
cit--;
ch = u950pci_inb( DeviceExtension->port, UART_RX );
PB_RxByte( &( DeviceExtension->PB ), ch );
}
if (cit<=0) DbgPrint("ProfiM: RxData - deadlock avoided!!!");
break;
#endif
#ifdef USE_RX_FIFO // *************************************
if ( ! DeviceExtension->ContinueFrame )
{
switch ( DeviceExtension->RTL ) // Receiver Interrupt Trigger Level
{
case 1:
ch = u950pci_inb( DeviceExtension->port, UART_RX );
PB_RxByte( &( DeviceExtension->PB ), ch );
if ( IsStartDelimiterSDx( ch ) )
{
DeviceExtension->FrameHeader[0] = ch;
u950pci_RxTreshold( DeviceExtension, 2 );
}
return TRUE;
break;
case 3:
ch = u950pci_inb( DeviceExtension->port, UART_RX );
PB_RxByte( &( DeviceExtension->PB ), ch );
DeviceExtension->FrameHeader[0] = ch;
if ( ch == DelimiterSC )
{
//
// DelimiterSC je jednoznakovy a tudiz preruseni
// nastava time-outem
//
return TRUE;
}
// zamerne zde chybi break
case 2:
ch = u950pci_inb( DeviceExtension->port, UART_RX );
PB_RxByte( &( DeviceExtension->PB ), ch );
DeviceExtension->FrameHeader[1] = ch;
ch = u950pci_inb( DeviceExtension->port, UART_RX );
PB_RxByte( &( DeviceExtension->PB ), ch );
DeviceExtension->FrameHeader[2] = ch;
break;
}
switch ( DeviceExtension->FrameHeader[0] )
{
case DelimiterSD1: // Frame of fixed Length with no Data Field
DeviceExtension->RTL = 3;
DeviceExtension->ContinueFrame = TRUE;
break;
case DelimiterSD2: // Frame with variable Data Field Length
if ( DeviceExtension->FrameHeader[1] ==
DeviceExtension->FrameHeader[2] )
{
DeviceExtension->RTL = DeviceExtension->FrameHeader[1] + 3;
DeviceExtension->ContinueFrame = TRUE;
}
else
{
DeviceExtension->RTL = 1;
DeviceExtension->ContinueFrame = FALSE;
}
break;
case DelimiterSD3: // Frame of fixed Length with Data Field
DeviceExtension->RTL = 11;
DeviceExtension->ContinueFrame = TRUE;
break;
case DelimiterSD4: // Token Frame
DeviceExtension->RTL = 3;
DeviceExtension->ContinueFrame = FALSE;
break;
default:
DeviceExtension->RTL = 1;
DeviceExtension->ContinueFrame = FALSE;
break;
}
}
if ( DeviceExtension->ContinueFrame )
{
while ( DeviceExtension->RTL && u950pci_RxDataReady( DeviceExtension ) )
{
ch = u950pci_inb( DeviceExtension->port, UART_RX );
PB_RxByte( &( DeviceExtension->PB ), ch );
DeviceExtension->RTL--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -