Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Panel
titleHilscher CIF - PCI Vendor and Device IDs

==============================================================================
PCI-Register Definition
- CIF50/80 (PLX 9050-Chip and PLX 9030-Chip)
- CIF52/54 (PLX 9030-Chip)
==============================================================================

PCI-Configuration Register Block

PCI-Configuration Register Block
Byte3210
Dword 0 Device ID
Vendor ID
Dword 1 Status Register
Command Register
Dword 2 Class CodeRevision ID
Dword 3 BIST
Header TypeLatency
Cache Line
Dword 4 Base Address 0
Dword 5 Base Address 1
Dword 6 Base Address 2
Dword 7 Base Address 3
Dword 8 Base Address 4
Dword 9 Base Address 5
Dword 10 CardBus CIS Pointer
Dword 11 Subsystem ID
Subsystem Vendor ID
Dword 12 Expansion ROM Base Address
Dword 13 Reserved
Dword 14 Reserved
Dword 15 Max_Lat Min_Grant
Interrupt Pin Interrupt Line

Base Address 0     = Memory Mapped Runtime PCI register
Base Address 1     = I/O Mapped PCI register
Base Address 2     = CIF 50/80 dual ported memory
Base Address 3     = Second dual ported memory on CIF 52/54

Interrupt Pin          = Interrupt enabled / disabled state
Interrupt Line        = Physical interrupt line


9050
 CIF PCI cards with PLX 9030 Chip
        
CIF PCI cards with PLX 9030 Chip
PCI IdentifierValueDescription     ValueDescription
VENDOR_ID0x10B5PLX technology 0x10B5    PLX technology

DEVICE_ID

0x9050PLX-PCI chip     0x9030PLX-PCI chip
SUBVENDOR_ID0x10B5PLX-PCI chip     0x10B5PLX-PCI chip
SUBSYSTEM_ID0x1080Defines a HILSCHER CIF PCI board     
VENDOR_ID       =>         /* PLX technology                           */
DEVICE_ID    =>         /* PLX-PCI chip                             */
SUBVENDOR_ID    =>         /* PLX-PCI chip                             */
SUBSYSTEM_ID    =>         /* Defines a HILSCHER CIF PCI board         */
Base Address 0     = Memory Mapped Runtime PCI register
Base Address 1     = I/O Mapped PCI register
Base Address 2     = CIF 50/80 dual ported memory
Base Address 3     = Second dual ported memory on CIF 52/54
Interrupt Pin      = Interrupt enabled / disabled state
Interrupt Line     = Physical interrupt line
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
EXAMPLE: PCI-Scan function for Windows NT
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
0x2695          Defines a HILSCHER CIF PCI board


/* CIF52 and CIF54 are working with two independend */
/* DPM memory areas.                                */
/****************************************************/
/* These are the entries of the CIF52 2Channel cards using the PLX 9030 Chip */
VENDOR_ID_3         0x10B5          /* PLX technology                           */
DEVICE_ID_3         0x9030          /* PLX-PCI chip                             */
SUBVENDOR_ID_3      0x10B5          /* PLX technology                           */
SUBSYSTEM_ID_3      0x3060          /* Defines a HILSCHER CIF 52 PCI board      */

/* These are the entries of the CIF54 4Channel cards using the PLX 9030 Chip */
VENDOR_ID_4         0x10B5          /* PLX technology                           */
DEVICE_ID_4         0x9030          /* PLX-PCI chip                             */
SUBVENDOR_ID_4      0x10B5          /* PLX technology                           */
SUBSYSTEM_ID_4      0x2833          /* Defines a HILSCHER CIF 54 PCI board      */


/* ------------------------------------------------------------------------------------ */
/* PCI card definitions                                                                 */
/* ------------------------------------------------------------------------------------ */

/* These are the entries of the CIF50 cards using the PLX 9050 Chip */
#define VENDOR_ID           0x10B5          /* PLX technology                           */
#define DEVICE_ID           0x9050          /* PLX-PCI chip                             */

#define SUBVENDOR_ID        0x10B5          /* PLX technology                           */
#define SUBSYSTEM_ID        0x1080          /* Defines a HILSCHER CIF 50 PCI board      */

/* These are the entries of the CIF50/80 cards using the PLX 9030 Chip */
#define VENDOR_ID_2         0x10B5          /* PLX technology                           */
#define DEVICE_ID_2         0x9030          /* PLX-PCI chip                             */

#define SUBVENDOR_ID_2      0x10B5          /* PLX technology                           */
#define SUBSYSTEM_ID_2      0x2695          /* Defines a HILSCHER CIF 50/80 PCI board   */


/****************************************************/
/* ATTENTION!!!!!!!!!                               */
/* CIF52 and CIF54 are working with two independend */
/* DPM memory areas.                                */
/****************************************************/
/* These are the entries of the CIF52 2Channel cards using the PLX 9030 Chip */
#define VENDOR_ID_3         0x10B5          /* PLX technology                           */
#define DEVICE_ID_3         0x9030          /* PLX-PCI chip                             */

#define SUBVENDOR_ID_3      0x10B5          /* PLX technology                           */
#define SUBSYSTEM_ID_3      0x3060          /* Defines a HILSCHER CIF 52 PCI board      */

/* These are the entries of the CIF54 4Channel cards using the PLX 9030 Chip */
#define VENDOR_ID_4         0x10B5          /* PLX technology                           */
#define DEVICE_ID_4         0x9030          /* PLX-PCI chip                             */

#define SUBVENDOR_ID_4      0x10B5          /* PLX technology                           */
#define SUBSYSTEM_ID_4      0x2833          /* Defines a HILSCHER CIF 54 PCI board      */


/* Local Control Register Offsets */
#define PCI_INTCTRLSTS_REG  0x4C

/* Data structures for PCI cards */
typedef struct tagPCI_DATA{
  unsigned long     ulSlotNumber;           // PCI slot number
  unsigned long     ulIOLocalRegAddress;    // PCI IO Address of the LCR registers
  unsigned long     ulBoardAddress;         // physical memory address
  unsigned long     ulDPMSize;              // DPM size of the DEV
  unsigned long     ulDPMByteSize;          // DPM size of the DEV in bytes
  unsigned short    usBoardIrq;             // Interrupt number of the DEV
  short             sError;                 // PCI device error
} PCI_DATA;

/* Data structures for PCMCIA cards */
typedef struct tagPCMCIA_DATA{
  unsigned long     ulBoardAddress;         // physical memory address
  unsigned long     ulDPMSize;              // DPM size of the DEV
  unsigned long     ulDPMByteSize;          // DPM size of the DEV in bytes
  unsigned short    usBoardIrq;             // Interrupt number of the DEV
  short             sError;                 // PCMCIA device error
} PCMCIA_DATA;

/* <ST> =================================================================================

  Function: DriverScanPCIDevices
            Read PCI devices CIF50 / CIF80 ONLY

  ---------------------------------------------------------------------------------------

  Input   : DeviceObject -

  Output  : -

  Return  : -

  ================================================================================= <En> */

void DriverScanPCIDevices( void)
{
  PCI_COMMON_CONFIG   tPciCommonConfig;
  PCI_SLOT_NUMBER     tPciSlotNumber;
  ULONG               ulRegisterSave;
  ULONG               ulState           = 0;
  ULONG               ulBusNumber       = 0L;
  ULONG               ulLength          = 0;
  BOOLEAN             bFound            = FALSE;
  unsigned short      usIdx             = 0;

  /*-----------------------------*/
  /* Find PCI device             */
  /*-----------------------------*/
  tPciSlotNumber.u.AsULONG = 0;   // Start with PCI slot number 0
  while ( bFound == FALSE) {

    ulState = HalGetBusData (PCIConfiguration,        /* BusDataType */
                             ulBusNumber,             /* Bus number */
                         tPciSlotNumber.u.AsULONG,/* PCI slot number */
                         &tPciCommonConfig,       /* Configuration data */
                         sizeof(PCI_COMMON_CONFIG));

    if ( ulState == 0) {

      // No PCI device found
      break;

    } else if ( ulState == 2) {

      // No Device at this slot number
      // Next Slot nmumber
      tPciSlotNumber.u.bits.FunctionNumber = PCI_MAX_FUNCTION-1;
     
    } else if ( ulState != sizeof(PCI_COMMON_CONFIG)) {

      // Size error in PCI_COMMON_CONFIG
      break;

    //--------------------------------------
    // PCI card found, check if its our card   
    //--------------------------------------   
    } else if ( ((VENDOR_ID == tPciCommonConfig.VendorID) &&
                 (DEVICE_ID == tPciCommonConfig.DeviceID)  )      ||
                ((VENDOR_ID_2 == tPciCommonConfig.VendorID) &&
                 (DEVICE_ID_2 == tPciCommonConfig.DeviceID)  )  )  {
 
      // Found a PLX device, check for Hilscher card
      if ( ( ((SUBVENDOR_ID == tPciCommonConfig.u.type0.SubVendorID)  &&
              (SUBSYSTEM_ID == tPciCommonConfig.u.type0.SubSystemID))   ||
             ((SUBVENDOR_ID_2 == tPciCommonConfig.u.type0.SubVendorID)&&
              (SUBSYSTEM_ID_2 == tPciCommonConfig.u.type0.SubSystemID))) &&
           (ulPciDataCnt < MAX_DEV_BOARDS)                         ) {

        // Hilscher card found

        /*-----------------------*/
        /* Check for DPM length  */
        /*-----------------------*/

        // Save actual register entry
        ulRegisterSave = tPciCommonConfig.u.type0.BaseAddresses[2];

        // Writing Data Address Register for Memory Access to Local Address Space 0
        tPciCommonConfig.u.type0.BaseAddresses[2] = 0xFFFFFFFF;
        if ( (ulState = HalSetBusDataByOffset(PCIConfiguration,
                                                  ulBusNumber,
                                                  tPciSlotNumber.u.AsULONG,
                                                  &tPciCommonConfig.u.type0.BaseAddresses[2], // Value
                                                  0x00000018,                                 // Offset
                                                  sizeof(ULONG))) == 0) {
          // Error by writing config mode
          tPciData[ulPciDataCnt].sError = DRV_PCI_SET_CONFIG_MODE;

        /*--------------------------*/
        /* Read DPM length,         */
        /* read configuration again */
        /*--------------------------*/
        } else if ( (ulState = HalGetBusData( PCIConfiguration,        /* BusDataType */
                                              ulBusNumber,             /* Bus number */
                                              tPciSlotNumber.u.AsULONG,/* PCI slot number */
                                              &tPciCommonConfig,       /* Configuration data */
                                              sizeof(PCI_COMMON_CONFIG))) == 0) {
          // Error by reading DPM size
          tPciData[ulPciDataCnt].sError = DRV_PCI_READ_DPM_LENGTH;

        } else {

          //------------------------------------------------------
          // Insert all datas for this board into driver structure
          //------------------------------------------------------
          // Set PCI Slot number
          tPciData[ulPciDataCnt].ulSlotNumber         = tPciSlotNumber.u.AsULONG,
          // Store LCR IO address
          tPciData[ulPciDataCnt].ulIOLocalRegAddress  = (tPciCommonConfig.u.type0.BaseAddresses[1] & 0xFFFFFFFE);
          // Set DPM address
          tPciData[ulPciDataCnt].ulBoardAddress       = (ulRegisterSave & 0xFFFFFFF0);
          // Set DPM size in bytes
          tPciData[ulPciDataCnt].ulDPMByteSize        = ~(tPciCommonConfig.u.type0.BaseAddresses[2] & 0xFFFFFFF0) + 1;
          // Calculate DPM size in KBytes
          tPciData[ulPciDataCnt].ulDPMSize            = tPciData[ulPciDataCnt].ulDPMByteSize / 1024;
          // Set interrupt number
          tPciData[ulPciDataCnt].usBoardIrq           = 0;
          // Check interrupt configuration
          if ( tPciCommonConfig.u.type0.InterruptPin != 0) {
            // PCI interrupt assigned
            if ( (tPciCommonConfig.u.type0.InterruptLine < 16)    &&
                 (tPciCommonConfig.u.type0.InterruptLine != 0xFF)  ) {
              // Valid interrupt value found
              tPciData[ulPciDataCnt].usBoardIrq = tPciCommonConfig.u.type0.InterruptLine;

            }
          }

          //------------------------------------------------------
          // Write back orignal value for Local Address Space 0
          //------------------------------------------------------
          tPciCommonConfig.u.type0.BaseAddresses[2] = ulRegisterSave;
          if ( (ulState = HalSetBusDataByOffset(PCIConfiguration,
                                                    ulBusNumber,
                                                    tPciSlotNumber.u.AsULONG,
                                                    &tPciCommonConfig.u.type0.BaseAddresses[2], // Value
                                                    0x00000018,                                 // Offset
                                                    sizeof(ULONG))) == 0) {
            // Error by writing original values back to device
            #ifdef KRNLDBG
              DbgPrint("DriverGetPCIDevices: Error by SetBusData (%ld)\n", ulState);
            #endif
            tPciData[ulPciDataCnt].sError = DRV_PCI_SET_RUN_MODE;

          } else {
            //-----------------------------------------------------
            // All work done for this board, increment board number
            //-----------------------------------------------------
            ulPciDataCnt++;

          }
        }
      }
    }

    /*----------------------*/
    /* Search next PCI card */
    /*----------------------*/
    // Count Function number from 0..7     
    if ( tPciSlotNumber.u.bits.FunctionNumber < (PCI_MAX_FUNCTION - 1) ) {
      // Try the next function number
      tPciSlotNumber.u.bits.FunctionNumber++;
    } else if ( tPciSlotNumber.u.bits.DeviceNumber < (PCI_MAX_DEVICES - 1)) {
      tPciSlotNumber.u.bits.DeviceNumber++;
      tPciSlotNumber.u.bits.FunctionNumber = 0;
    } else if ( ulBusNumber < MaximumBusDataType) {
      // Search next BUS
      ulBusNumber++; 
      tPciSlotNumber.u.AsULONG = 0;          
    } else {
      break;
    }
  }
}


-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
EXAMPLE: INTERRUPT-HANDLING
     CIF50 / CIF80 ONLY
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
Desciption:

The PCI-Chip of the CIF 50/80 always request an interrupt resource from the system,
but the physical interrupt generation is disabled.
The reason is to prevent an interrupt generation, by the hardware, before an interrupt service function
is installed. Otherwise the PCI bus can be blocked by an unserviced interrupt, wich will result in an
blocked system (e.g. DOS).

The interrupt will be enabled by writing into a specific area of the PCI register.
This can be done either by writing to a memory location or into an IO port address, depending where the
PCI registers are mapped. Both ways are supported by CIF 50.


The information where the registers are located can be taken from the PCI Configuration Information structure.

Here is an example, how to generate the real physical address from the PCI Configuration structure
by using "Base Address 1" to access the PCI registers via I/O port addresses.

- Generate the physical address from the PCI Configuration structure
  ulIOLocalRegAddress  = (BaseAddress1 & 0xFFFFFFFE);

- Enable or disable the physical hardware interrupt

//--------------------------------------------------------------
// DriverSetInterruptState
// Enable /Disable PCI Interrupt for CIF50/80
//--------------------------------------------------------------
#define HW_INTERRUPT_DISABLE     0x00
#define HW_INTERRUPT_ENABLE      0x01
/* Local Control Register Offsets */
#define PCI_INTCTRLSTS_REG       0x4C

  unsigned char bData;

  bData = _inp ( ulIOLocalRegAddress + PCI_INTCTRLSTS_REG);

  if ( usIntState == HW_INTERRUPT_ENABLE) {
    // Enable Interrupt (LCR-Registers)
    bData = (unsigned char)(bData | HW_INTERRUPT_ENABLE);
  } else {
    // Disable PCI Interrupt (LCR-Registers)
    bData = (unsigned char)(bData & ~HW_INTERRUPT_ENABLE);
  }
  // Write new data to port
  _outp ( (ulIOLocalRegAddress + PCI_INTCTRLSTS_REG), bData);



-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
INFORMATION for CIF52 /CIF54
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
Desciption:

The CIF 52 and CIF 54 containing two independent CIFs on the local side and handled as
two independent cards.

The second DPM can be found in the PCI "Base Address 3".

Also the interrupt handling is different. While the CIF54 uses only one Interrupt for both DPMs, the
CIF52 uses two independent local interrupt for each interface.
Like on the CIF50/80, the PCI-Chip of the CIF 52/54 always request an interrupt resource from the system,
but the physical interrupt generation is disabled (see CIF50/80).

Interrupt enable on the CIF54 works like on the CIF50/80. The CIF52 needs to enable two local interrupts
The interrupt will be enabled by writing into a specific area of the PCI register (memory mapped or I/O mapped).

Enable interrupt on CIF54 (see CIF50/80).
Enable interrupt on CIF52 needs a second interrupt enable bit set.

//--------------------------------------------------------------
// DriverSetInterruptState
// Enable /Disable PCI Interrupt for CIF52
//--------------------------------------------------------------
#define HW_INTERRUPT_DISABLE         0x00
#define HW_INTERRUPT_ENABLE_CIF52    0x09

/* Local Control Register Offsets */
#define PCI_INTCTRLSTS_REG       0x4C

  unsigned char bData;

  bData = _inp ( ulIOLocalRegAddress + PCI_INTCTRLSTS_REG);

  if ( usIntState == HW_INTERRUPT_ENABLE_CIF52) {
    // Enable Interrupt (LCR-Registers)
    bData = (unsigned char)(bData | HW_INTERRUPT_ENABLE_CIF52);
  } else {
    // Disable PCI Interrupt (LCR-Registers)
    bData = (unsigned char)(bData & ~HW_INTERRUPT_ENABLE_CIF52);
  }
  // Write new data to port
  _outp ( (ulIOLocalRegAddress + PCI_INTCTRLSTS_REG), bData);





Attention: The SUBSYSTEM_ID is used to determine if the hardware is a RAM based or FLASH based hardware

  • RAM based
    Firmware and configuration is not stored on the hardware
  • FLASH based
    Firmware and configuration is stored on the hardware.  Depending on the functionality the start-up behaviour of the hardware is different!

 

CIFX50 / CIFX70 / CIFX90 etc.
PCI IdentifierValueDescription
VENDOR_ID0x15CFHilscher GmbH

DEVICE_ID

0x0000CIFX
SUBVENDOR_ID0x0000none
SUBSYSTEM_ID0x0000none
netPLC
PCI Identifier

Value

RAM based

Value

FLASH based

Description
VENDOR_ID0x15CF0x15CFHilscher GmbH
DEVCE_ID0x00100x0010netPLC
SUBVENDOR_ID0x15CF0x15CFHilscher GmbH
SUBSYSTEM_ID0x00000x0001RAM/FLASH based
netJACK
PCI IdentifierValue
RAM based
Value
FLASH based
Description
VENDOR_ID0x15CF0x15CFHilscher GmbH
DEVCE_ID0x00200x0020netJACK
SUBVENDOR_ID0x15CF0x15CFHilscher GmbH
SUBSYSTEM_ID0x00000x0001RAM/FLASH based

...