============================================================================== 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 |
---|
Byte | 3 | 2 | 1 | 0 |
---|
Dword 0 | Device ID
| Vendor ID
| Dword 1 | Status Register
| Command Register
| Dword 2 | Class Code | Revision ID | Dword 3 | BIST
| Header Type | Latency
| 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 | CIFX50 / CIFX70 / CIFX90 etc.
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
CIF PCI cards with PLX 9050 Chip
|
---|
| | | | | | | | PCI Identifier | Value | Description | | | | | |
---|
VENDOR_ID | 0x15CF | Hilscher GmbH0x10B5 | PLX technology | | | | | | DEVICE_ID | 0x0000 | CIFX | 0x9050 | PLX-PCI chip | | | | | | SUBVENDOR_ID | 0x0000 | none | 0x10B5 | PLX-PCI chip | | | | | | SUBSYSTEM_ID | 0x0000 | none | 0x1080 | Defines 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 ----------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------- /* ------------------------------------------------------------------------------------ */ /* 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 Identifier | Value | Description |
---|
VENDOR_ID | 0x15CF | Hilscher GmbH | DEVICE_ID | 0x0000 | CIFX | SUBVENDOR_ID | 0x0000 | none | SUBSYSTEM_ID | 0x0000 | none |
netPLC |
---|
PCI Identifier | Value RAM based | Value FLASH based | Description |
---|
VENDOR_ID | 0x15CF | 0x15CF | Hilscher GmbH | DEVCE_ID | 0x0010 | 0x0010 | netPLC | SUBVENDOR_ID | 0x15CF | 0x15CF | Hilscher GmbH | SUBSYSTEM_ID | 0x0000 | 0x0001 | RAM/FLASH based |
netJACK |
---|
PCI Identifier | Value RAM based | Value FLASH based | Description |
---|
VENDOR_ID | 0x15CF | 0x15CF | Hilscher GmbH | DEVCE_ID | 0x0020 | 0x0020 | netJACK | SUBVENDOR_ID | 0x15CF | 0x15CF | Hilscher GmbH | SUBSYSTEM_ID | 0x0000 | 0x0001 | RAM/FLASH based |
|