550 lines
12 KiB
C
550 lines
12 KiB
C
/*++
|
|
|
|
Copyright (c) 1990-1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
pciirqmp.c
|
|
|
|
Abstract:
|
|
|
|
This is the PCI IRQ Miniport library.
|
|
|
|
Author:
|
|
|
|
Santosh Jodh (santoshj) 09-June-1998
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "local.h"
|
|
|
|
//
|
|
// Macro to declare a table of function pointers for the chipset
|
|
// module.
|
|
//
|
|
|
|
#define DECLARE_CHIPSET(x) \
|
|
{ DECLARE_MINIPORT_FUNCTION(x, ValidateTable), \
|
|
DECLARE_MINIPORT_FUNCTION(x, GetIRQ), \
|
|
DECLARE_MINIPORT_FUNCTION(x, SetIRQ), \
|
|
DECLARE_MINIPORT_FUNCTION(x, GetTrigger), \
|
|
DECLARE_MINIPORT_FUNCTION(x, SetTrigger) \
|
|
}
|
|
|
|
//
|
|
// Macro to declare a table of function pointers for EISA
|
|
// compatible chipset module.
|
|
//
|
|
|
|
#define DECLARE_EISA_CHIPSET(x) \
|
|
{ DECLARE_MINIPORT_FUNCTION(x, ValidateTable), \
|
|
DECLARE_MINIPORT_FUNCTION(x, GetIRQ), \
|
|
DECLARE_MINIPORT_FUNCTION(x, SetIRQ), \
|
|
EisaGetTrigger, \
|
|
EisaSetTrigger \
|
|
}
|
|
|
|
//
|
|
// Macro to declare the functions to be provided by the chipset
|
|
// module.
|
|
//
|
|
|
|
#define DECLARE_IRQ_MINIPORT(x) \
|
|
NTSTATUS \
|
|
DECLARE_MINIPORT_FUNCTION(x, ValidateTable) ( \
|
|
IN PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable, \
|
|
IN ULONG Flags \
|
|
); \
|
|
NTSTATUS \
|
|
DECLARE_MINIPORT_FUNCTION(x, GetIRQ) ( \
|
|
OUT PUCHAR Irq, \
|
|
IN UCHAR Link \
|
|
); \
|
|
NTSTATUS \
|
|
DECLARE_MINIPORT_FUNCTION( x, SetIRQ) ( \
|
|
IN UCHAR Irq, \
|
|
IN UCHAR Link \
|
|
); \
|
|
NTSTATUS \
|
|
DECLARE_MINIPORT_FUNCTION(x, GetTrigger) ( \
|
|
OUT PULONG Trigger \
|
|
); \
|
|
NTSTATUS \
|
|
DECLARE_MINIPORT_FUNCTION(x, SetTrigger) ( \
|
|
IN ULONG Trigger \
|
|
);
|
|
|
|
//
|
|
// Macro to declare the functions to be provided by the EISA
|
|
// compatible chipset.
|
|
//
|
|
|
|
#define DECLARE_EISA_IRQ_MINIPORT(x) \
|
|
NTSTATUS \
|
|
DECLARE_MINIPORT_FUNCTION(x, ValidateTable) ( \
|
|
IN PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable, \
|
|
IN ULONG Flags \
|
|
); \
|
|
NTSTATUS \
|
|
DECLARE_MINIPORT_FUNCTION(x, GetIRQ) ( \
|
|
OUT PUCHAR Irq, \
|
|
IN UCHAR Link \
|
|
); \
|
|
NTSTATUS \
|
|
DECLARE_MINIPORT_FUNCTION( x, SetIRQ) ( \
|
|
IN UCHAR Irq, \
|
|
IN UCHAR Link \
|
|
);
|
|
|
|
//
|
|
// Function prototypes for functions that every chipset module
|
|
// has to provide.
|
|
//
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PIRQMINI_VALIDATE_TABLE) (
|
|
PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable,
|
|
ULONG Flags
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PIRQMINI_GET_IRQ) (
|
|
OUT PUCHAR Irq,
|
|
IN UCHAR Link
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PIRQMINI_SET_IRQ) (
|
|
IN UCHAR Irq,
|
|
IN UCHAR Link
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PIRQMINI_GET_TRIGGER) (
|
|
OUT PULONG Trigger
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PIRQMINI_SET_TRIGGER) (
|
|
IN ULONG Trigger
|
|
);
|
|
|
|
//
|
|
// Chipset specific data contains a table of function pointers
|
|
// to program the chipset.
|
|
//
|
|
|
|
typedef struct _CHIPSET_DATA {
|
|
PIRQMINI_VALIDATE_TABLE ValidateTable;
|
|
PIRQMINI_GET_IRQ GetIrq;
|
|
PIRQMINI_SET_IRQ SetIrq;
|
|
PIRQMINI_GET_TRIGGER GetTrigger;
|
|
PIRQMINI_SET_TRIGGER SetTrigger;
|
|
} CHIPSET_DATA, *PCHIPSET_DATA;
|
|
|
|
|
|
//
|
|
// Declare all miniports here.
|
|
//
|
|
|
|
DECLARE_EISA_IRQ_MINIPORT(Mercury)
|
|
DECLARE_EISA_IRQ_MINIPORT(Triton)
|
|
DECLARE_IRQ_MINIPORT(VLSI)
|
|
DECLARE_IRQ_MINIPORT(OptiViper)
|
|
DECLARE_EISA_IRQ_MINIPORT(SiS5503)
|
|
DECLARE_IRQ_MINIPORT(VLSIEagle)
|
|
DECLARE_EISA_IRQ_MINIPORT(M1523)
|
|
DECLARE_IRQ_MINIPORT(NS87560)
|
|
DECLARE_EISA_IRQ_MINIPORT(Compaq3)
|
|
DECLARE_EISA_IRQ_MINIPORT(M1533)
|
|
DECLARE_IRQ_MINIPORT(OptiFireStar)
|
|
DECLARE_EISA_IRQ_MINIPORT(VT586)
|
|
DECLARE_EISA_IRQ_MINIPORT(CPQOSB)
|
|
DECLARE_EISA_IRQ_MINIPORT(CPQ1000)
|
|
DECLARE_EISA_IRQ_MINIPORT(Cx5520)
|
|
DECLARE_IRQ_MINIPORT(Toshiba)
|
|
DECLARE_IRQ_MINIPORT(NEC)
|
|
DECLARE_IRQ_MINIPORT(VESUVIUS)
|
|
|
|
//
|
|
// Table of chipset drivers.
|
|
//
|
|
|
|
const CHIPSET_DATA rgChipData[] = {
|
|
DECLARE_EISA_CHIPSET(Mercury), // Intel 82374EB\SB (80860482)
|
|
DECLARE_EISA_CHIPSET(Triton), // Intel 82430FX (8086122E)
|
|
DECLARE_CHIPSET(VLSI), // VLSI VL82C596/7
|
|
DECLARE_CHIPSET(OptiViper), // OPTi Viper-M
|
|
DECLARE_EISA_CHIPSET(SiS5503), // SIS P54C
|
|
DECLARE_CHIPSET(VLSIEagle), // VLSI VL82C534
|
|
DECLARE_EISA_CHIPSET(M1523), // ALi M1523
|
|
DECLARE_CHIPSET(NS87560), // Nat Semi NS87560
|
|
DECLARE_EISA_CHIPSET(Compaq3), // Compaq MISC 3
|
|
DECLARE_EISA_CHIPSET(M1533), // ALi M1533
|
|
DECLARE_CHIPSET(OptiFireStar), // OPTI FIRESTAR
|
|
DECLARE_EISA_CHIPSET(VT586), // VIATECH 82C586B
|
|
DECLARE_EISA_CHIPSET(CPQOSB), // Conpaq OSB
|
|
DECLARE_EISA_CHIPSET(CPQ1000), // Conpaq 1000
|
|
DECLARE_EISA_CHIPSET(Cx5520), // Cyrix 5520
|
|
DECLARE_CHIPSET(Toshiba), // Toshiba
|
|
DECLARE_CHIPSET(NEC), // NEC PC9800
|
|
DECLARE_CHIPSET(VESUVIUS) //
|
|
};
|
|
|
|
#define NUMBER_OF_CHIPSETS (sizeof(rgChipData) / sizeof(CHIPSET_DATA))
|
|
|
|
//
|
|
// Global variables shared by all modules.
|
|
//
|
|
|
|
ULONG bBusPIC = -1;
|
|
ULONG bDevFuncPIC = -1;
|
|
CHIPSET_DATA const* rgChipSet = NULL;
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, PciirqmpInit)
|
|
#pragma alloc_text(PAGE, PciirqmpExit)
|
|
#pragma alloc_text(PAGE, PciirqmpValidateTable)
|
|
#endif //ALLOC_PRAGMA
|
|
|
|
NTSTATUS
|
|
PciirqmpInit (
|
|
ULONG Instance,
|
|
ULONG RouterBus,
|
|
ULONG RouterDevFunc
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes calls the individual chipset handler
|
|
to validate the Pci Irq Routing Table.
|
|
|
|
Parameters:
|
|
|
|
PciIrqRoutingTable - Pci Irq Routing Table.
|
|
|
|
Flags - Flags specifying source of the Pci Irq Routing Table.
|
|
|
|
Return Value:
|
|
|
|
Standard Pci Irq Miniport return value.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Check to make sure that we are not already initialized.
|
|
//
|
|
|
|
if (rgChipSet != NULL)
|
|
{
|
|
PCIIRQMPPRINT(("IRQ miniport already initialized!"));
|
|
return (PCIIRQMP_STATUS_ALREADY_INITIALIZED);
|
|
}
|
|
|
|
//
|
|
// Check for invalid instance.
|
|
//
|
|
|
|
if (Instance >= NUMBER_OF_CHIPSETS)
|
|
{
|
|
PCIIRQMPPRINT(("Invalid IRQ miniport instance %08X", Instance));
|
|
return (PCIIRQMP_STATUS_INVALID_INSTANCE);
|
|
}
|
|
|
|
//
|
|
// Save our global data.
|
|
//
|
|
|
|
rgChipSet = &rgChipData[Instance];
|
|
bBusPIC = RouterBus;
|
|
bDevFuncPIC = RouterDevFunc;
|
|
|
|
return (PCIMP_SUCCESS);
|
|
}
|
|
|
|
NTSTATUS
|
|
PciirqmpExit (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine cleans up after the Pci Irq Routing miniport library.
|
|
|
|
Parameters:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Standard Pci Irq Miniport return value.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Were we ever initialized?
|
|
//
|
|
|
|
if (rgChipSet == NULL)
|
|
{
|
|
PCIIRQMPPRINT(("Cannot exit without having been initialized!"));
|
|
return (PCIIRQMP_STATUS_NOT_INITIALIZED);
|
|
}
|
|
|
|
//
|
|
// Clean up.
|
|
//
|
|
|
|
rgChipSet = NULL;
|
|
bBusPIC = -1;
|
|
bDevFuncPIC = -1;
|
|
|
|
return (PCIMP_SUCCESS);
|
|
}
|
|
|
|
NTSTATUS
|
|
PciirqmpValidateTable (
|
|
IN PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable,
|
|
IN ULONG Flags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine normalizes calls the individual chipset handler
|
|
to validate the Pci Irq Routing Table.
|
|
|
|
Parameters:
|
|
|
|
PciIrqRoutingTable - Pci Irq Routing Table.
|
|
|
|
Flags - Flags specifying source of the Pci Irq Routing Table.
|
|
|
|
Return Value:
|
|
|
|
Standard Pci Irq Miniport return value.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Were we ever initialized?
|
|
//
|
|
|
|
if (rgChipSet == NULL)
|
|
{
|
|
PCIIRQMPPRINT(("Not initialized yet!"));
|
|
return (PCIIRQMP_STATUS_NOT_INITIALIZED);
|
|
}
|
|
|
|
//
|
|
// Call the chipset handler.
|
|
//
|
|
|
|
return (rgChipSet->ValidateTable(PciIrqRoutingTable, Flags));
|
|
}
|
|
|
|
NTSTATUS
|
|
PciirqmpGetIrq (
|
|
OUT PUCHAR Irq,
|
|
IN UCHAR Link
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine calls the individual chipset handler
|
|
to set the link to the specified Irq.
|
|
|
|
Parameters:
|
|
|
|
Irq - Variable that receives the Irq.
|
|
|
|
Link - Link to be read.
|
|
|
|
Return Value:
|
|
|
|
Standard Pci Irq Miniport return value.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Were we ever initialized?
|
|
//
|
|
|
|
if (rgChipSet == NULL)
|
|
{
|
|
PCIIRQMPPRINT(("Not initialized yet!"));
|
|
return (PCIIRQMP_STATUS_NOT_INITIALIZED);
|
|
}
|
|
|
|
//
|
|
// Call the chipset handler.
|
|
//
|
|
|
|
return (rgChipSet->GetIrq(Irq, Link));
|
|
}
|
|
|
|
NTSTATUS
|
|
PciirqmpSetIrq (
|
|
IN UCHAR Irq,
|
|
IN UCHAR Link
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine calls the individual chipset handler
|
|
to set the link to the specified Irq.
|
|
|
|
Parameters:
|
|
|
|
Irq - Irq to be set.
|
|
|
|
Link - Link to be programmed.
|
|
|
|
Return Value:
|
|
|
|
Standard Pci Irq Miniport return value.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Were we ever initialized?
|
|
//
|
|
|
|
if (rgChipSet == NULL)
|
|
{
|
|
PCIIRQMPPRINT(("Not initialized yet!"));
|
|
return (PCIIRQMP_STATUS_NOT_INITIALIZED);
|
|
}
|
|
|
|
//
|
|
// Call the chipset handler.
|
|
//
|
|
|
|
return (rgChipSet->SetIrq(Irq, Link));
|
|
}
|
|
|
|
NTSTATUS
|
|
PciirqmpGetTrigger (
|
|
OUT PULONG Trigger
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine calls the individual chipset handler
|
|
to get the interrupt edge\level mask.
|
|
|
|
Parameters:
|
|
|
|
Trigger - Variable that receives edge\level mask.
|
|
|
|
Return Value:
|
|
|
|
Standard Pci Irq Miniport return value.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Were we ever initialized?
|
|
//
|
|
|
|
if (rgChipSet == NULL)
|
|
{
|
|
PCIIRQMPPRINT(("Not initialized yet!"));
|
|
return (PCIIRQMP_STATUS_NOT_INITIALIZED);
|
|
}
|
|
|
|
//
|
|
// Call the chipset handler.
|
|
//
|
|
|
|
return (rgChipSet->GetTrigger(Trigger));
|
|
}
|
|
|
|
NTSTATUS
|
|
PciirqmpSetTrigger (
|
|
IN ULONG Trigger
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine calls the individual chipset handler
|
|
to set the interrupt edge\level mask.
|
|
|
|
Parameters:
|
|
|
|
Trigger - Edge\level mask to be set.
|
|
|
|
Return Value:
|
|
|
|
Standard Pci Irq Miniport return value.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Were we ever initialized?
|
|
//
|
|
|
|
if (rgChipSet == NULL)
|
|
{
|
|
PCIIRQMPPRINT(("Not initialized yet!"));
|
|
return (PCIIRQMP_STATUS_NOT_INITIALIZED);
|
|
}
|
|
|
|
//
|
|
// Call the chipset handler and return the result.
|
|
//
|
|
|
|
return (rgChipSet->SetTrigger(Trigger));
|
|
}
|