
Applied Micro Circuits Corporation
6195 Lusk Blvd., San Diego, CA 92121 (619) 450-9333
15-57
PCI CONTROLLER
S5933
Code Segment 2 determines the interrupt vector from
a PCI device and installs an interrupt handler which
calls the previous interrupt handler.
First it defines an interrupt handler. This handler
only calls the previous interrupt handler. A method
for determining if a shared interrupt is to be ser-
viced by this interrupt handler is not defined by
PCI. AMCC suggests the use of an Operation Reg-
ister — Interrupt Control/Status Register to deter-
mine if the device has an interrupt pending.
The main routine assumes that the bus and
device_and_function variables are determined as de-
scribed in a previous section. It then reads the Inter-
rupt Line Configuration Space register and converts
the interrupt line into a software interrupt vector. The
current interrupt vector routine is then determined by
the Borland C/C++ getvect() function and the new
interrupt handler installed with the setvect() function.
Obtaining Base Addresses
The six Base Address Registers in the Configuration
Space contain the hardware memory or I/O addresses
assigned to the device by the host computer. The first
Base Address (0) on a S5933 is dedicated to the Op-
eration Registers. The remaining five base address
registers are available for use by the PCI device.
The six Base Address DWORD Registers are located
in the Configuration Space at addresses: 10h, 14h,
18h, 1Ch, 20h and 24h. Each Base Address may
describe either a Memory or I/O Base Address. The
Memory Base Address is indicated by bit zero
cleared and I/O indicated by bit zero set. To deter-
mine the actual base address, bits 3-0 on a Memory
address must be masked off and bits 1-0 on an I/O
address must be masked off. These bits indicate vari-
ous information about the memory that is generally
not important for this discussion. See the PCI LO-
CAL BUS SPECIFICATION (or Section 3.1.11 of this
manual).
Code Segment 2
void interrupt ( *oldhandler)(void);
void interrupt handler(void)
{
/* Must determine if PCI device needs servicing */
/* call the old routine */
oldhandler();
}
main()
{
byte bus;
/* Bus number of device */
byte device_and_function;
/* Device Number bits 7-3, Function bits 2-0 */
byte interrupt_line;
/* Interrupt assigned to PCI device */
byte interrupt_vector;
/* Software interrupt vector */
/* Must Determine bus and device_and_function of device first */
if (read_configuration_byte(bus, device_and_function,
PCI_CS_INTERRUPT_LINE, &interrupt_line) == SUCCESSFUL) {
if (interrupt_line != 0xff) {
if (interrupt_line < 8) {
interrupt_vector = 0x08 + interrupt_line;
}
else {
interrupt_vector = 0x70 + (interrupt_line - 8);
}
/* save the old interrupt vector */
oldhandler = getvect(interrupt_vector);
/* install the new interrupt handler */
setvect(interrupt_vector, handler);
}