==============================================================================
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 |
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 9030 Chip | CIF PCI cards with PLX 9030 Chip | |||
---|---|---|---|---|
PCI Identifier | Value | Description | Value | Description |
VENDOR_ID | 0x10B5 | PLX technology | 0x10B5 | PLX technology |
DEVICE_ID | 0x9050 | PLX-PCI chip | 0x9030 | PLX-PCI chip |
SUBVENDOR_ID | 0x10B5 | PLX-PCI chip | 0x10B5 | PLX-PCI chip |
SUBSYSTEM_ID | 0x1080 | Defines a HILSCHER CIF PCI board | 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 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 |
==============================================================================
PCI-Register Definition
- CIF50/80 (PLX 9050-Chip and PLX 9030-Chip)
- CIF52/54 (PLX 9030-Chip)
==============================================================================
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 |
----------------------------------------------------------------+
Dword10 = CardBus CIS Pointer |
----------------------------------------------------------------+
Dword11 = Subsystem ID | Subsystem Vendor ID |
----------------------------------------------------------------+
Dword12 = Expansion ROM Base Address |
----------------------------------------------------------------+
Dword13 = Reserved |
----------------------------------------------------------------+
Dword14 = Reserved |
----------------------------------------------------------------+
Dword15 = Max_Lat| Min_Grant | Interrupt Pin | Interrupt Line|
----------------------------------------------------------------+
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);