895 lines
22 KiB
C
895 lines
22 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
pccardc.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the C code to set up PcCard (pcmcia, cardbus)
|
|||
|
configuration data.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Neil Sandlin (neilsa) 16-Dec-1998
|
|||
|
(DetectIRQMap, ToggleIRQLine were copied from win9x)
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "hwdetect.h"
|
|||
|
#include "pccard.h"
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
extern UCHAR DisablePccardIrqScan;
|
|||
|
extern BOOLEAN SystemHas8259;
|
|||
|
extern BOOLEAN SystemHas8253;
|
|||
|
|
|||
|
CARDBUS_BRIDGE_DEVTYPE CBTable[] = {
|
|||
|
{0x11101013, DEVTYPE_CL_PD6832},
|
|||
|
{0x11121013, DEVTYPE_CL_PD6834},
|
|||
|
{0x11111013, DEVTYPE_CL_PD6833},
|
|||
|
{0xAC12104C, DEVTYPE_TI_PCI1130},
|
|||
|
{0xAC15104C, DEVTYPE_TI_PCI1131},
|
|||
|
{0xAC13104C, DEVTYPE_TI_PCI1031},
|
|||
|
{0,0}};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
FPFWCONFIGURATION_COMPONENT_DATA ControllerList = NULL;
|
|||
|
|
|||
|
#define LEGACY_BASE_LIST_SIZE 10
|
|||
|
USHORT LegacyBaseList[LEGACY_BASE_LIST_SIZE] = {0};
|
|||
|
USHORT LegacyBaseListCount = 0;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SetPcCardConfigurationData(
|
|||
|
PPCCARD_INFORMATION PcCardInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine creates a structure containing the result of the
|
|||
|
irq detection, and links it onto our running list. This list
|
|||
|
eventually will show up in the registry under hardware
|
|||
|
descriptions.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
PcCardInfo - Structure containing the results of detection
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry;
|
|||
|
static FPFWCONFIGURATION_COMPONENT_DATA PreviousEntry = NULL;
|
|||
|
FPFWCONFIGURATION_COMPONENT Component;
|
|||
|
FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
|
|||
|
CHAR Identifier[32];
|
|||
|
FPCHAR IdentifierString;
|
|||
|
USHORT Length;
|
|||
|
CM_PCCARD_DEVICE_DATA far *PcCardData;
|
|||
|
|
|||
|
CurrentEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
|
|||
|
sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
|
|||
|
if (!ControllerList) {
|
|||
|
ControllerList = CurrentEntry;
|
|||
|
}
|
|||
|
Component = &CurrentEntry->ComponentEntry;
|
|||
|
|
|||
|
Component->Class = ControllerClass;
|
|||
|
Component->Type = OtherController;
|
|||
|
|
|||
|
strcpy (Identifier, "PcCardController");
|
|||
|
Length = strlen(Identifier) + 1;
|
|||
|
IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
|
|||
|
_fstrcpy(IdentifierString, Identifier);
|
|||
|
|
|||
|
Component->IdentifierLength = Length;
|
|||
|
Component->Identifier = IdentifierString;
|
|||
|
|
|||
|
Length = sizeof(HWRESOURCE_DESCRIPTOR_LIST) + sizeof(CM_PCCARD_DEVICE_DATA);
|
|||
|
DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)HwAllocateHeap(
|
|||
|
Length,
|
|||
|
TRUE);
|
|||
|
|
|||
|
CurrentEntry->ConfigurationData = DescriptorList;
|
|||
|
Component->ConfigurationDataLength = Length;
|
|||
|
|
|||
|
DescriptorList->Count = 1;
|
|||
|
DescriptorList->PartialDescriptors[0].Type = RESOURCE_DEVICE_DATA;
|
|||
|
DescriptorList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
|
|||
|
sizeof(CM_PCCARD_DEVICE_DATA);
|
|||
|
|
|||
|
PcCardData = (CM_PCCARD_DEVICE_DATA far *)(DescriptorList + 1);
|
|||
|
PcCardData->Flags = PcCardInfo->Flags;
|
|||
|
PcCardData->ErrorCode = PcCardInfo->ErrorCode;
|
|||
|
PcCardData->DeviceId = PcCardInfo->DeviceId;
|
|||
|
PcCardData->LegacyBaseAddress = (ULONG) PcCardInfo->IoBase;
|
|||
|
|
|||
|
if (PcCardInfo->Flags & PCCARD_DEVICE_PCI) {
|
|||
|
PcCardData->BusData = PcCardInfo->PciCfg1.u.bits.BusNumber |
|
|||
|
PcCardInfo->PciCfg1.u.bits.DeviceNumber << 8 |
|
|||
|
PcCardInfo->PciCfg1.u.bits.FunctionNumber << 16;
|
|||
|
}
|
|||
|
|
|||
|
_fmemcpy(PcCardData->IRQMap, PcCardInfo->abIRQMap, 16);
|
|||
|
|
|||
|
if (PreviousEntry) {
|
|||
|
PreviousEntry->Sibling = CurrentEntry;
|
|||
|
}
|
|||
|
PreviousEntry = CurrentEntry;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
IsOnLegacyBaseList(
|
|||
|
USHORT IoBase
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine runs our list of legacy base addresses to see if we
|
|||
|
have looked at the address before.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IoBase = base address to map
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
TRUE if the base address is already on the list
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
USHORT i;
|
|||
|
|
|||
|
for (i = 0; i<LegacyBaseListCount; i++) {
|
|||
|
if (IoBase == LegacyBaseList[i]) {
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SetLegacyBaseList(
|
|||
|
USHORT IoBase
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine remembers the legacy base addresses that we have looked
|
|||
|
at so far so we don't keep mapping the same address.
|
|||
|
|
|||
|
NOTE: We are using a DUMB mechanism that only builds the list in a
|
|||
|
fixed array. We could write some generic code which creates
|
|||
|
a linked list, but since the heap routines in ntdetect are also
|
|||
|
dumb, it makes it not possible to free the list. It's just not worth
|
|||
|
it.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IoBase = base address to map
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
TRUE if the base address is unique to this point
|
|||
|
FALSE if the base address already exists on the list
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
if (IsOnLegacyBaseList(IoBase)) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (LegacyBaseListCount < LEGACY_BASE_LIST_SIZE) {
|
|||
|
LegacyBaseList[LegacyBaseListCount++] = IoBase;
|
|||
|
}
|
|||
|
// note, we return true even if we overflow the list
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
MapPcCardController(
|
|||
|
PPCCARD_INFORMATION PcCardInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is the entry for doing ISA IRQ detection for PcCard
|
|||
|
controllers.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
PcCardInfo - Structure defining the device to run detection on
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
USHORT wDetected;
|
|||
|
USHORT i;
|
|||
|
|
|||
|
PcCardInfo->ErrorCode = 0;
|
|||
|
for (i=0; i<16; i++) {
|
|||
|
PcCardInfo->abIRQMap[i]=0;
|
|||
|
}
|
|||
|
|
|||
|
if (!PcCardInfo->IoBase) {
|
|||
|
|
|||
|
PcCardInfo->Flags |= PCCARD_MAP_ERROR;
|
|||
|
PcCardInfo->ErrorCode = PCCARD_NO_LEGACY_BASE;
|
|||
|
|
|||
|
} else if (!SetLegacyBaseList(PcCardInfo->IoBase)) {
|
|||
|
|
|||
|
PcCardInfo->Flags |= PCCARD_MAP_ERROR;
|
|||
|
PcCardInfo->ErrorCode = PCCARD_DUP_LEGACY_BASE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (!(PcCardInfo->Flags & PCCARD_MAP_ERROR)) {
|
|||
|
PcCardInfo->wValidIRQs = PCCARD_POSSIBLE_IRQS;
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("Going to detect...\n");
|
|||
|
#endif
|
|||
|
//
|
|||
|
// Do the IRQ detection
|
|||
|
//
|
|||
|
wDetected = DetectIRQMap(PcCardInfo);
|
|||
|
#if DBG
|
|||
|
BlPrint("Detect IRQ Map returns %x on iobase %x\n", wDetected, PcCardInfo->IoBase);
|
|||
|
#endif
|
|||
|
|
|||
|
if (!wDetected) {
|
|||
|
PcCardInfo->ErrorCode = PCCARD_MAP_ZERO;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (PcCardInfo->Flags & PCCARD_MAP_ERROR) {
|
|||
|
BlPrint("Error mapping device, code=%x\n", PcCardInfo->ErrorCode);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Report the results
|
|||
|
//
|
|||
|
SetPcCardConfigurationData(PcCardInfo);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
LookForPciCardBusBridges(
|
|||
|
USHORT BusStart,
|
|||
|
USHORT BusEnd,
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is the entry for doing ISA IRQ detection for PCI-based
|
|||
|
cardbus controllers.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Bus = PCI Bus number to scan
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCCARD_INFORMATION PcCardInfo = {0};
|
|||
|
USHORT Device, Function;
|
|||
|
UCHAR HeaderType;
|
|||
|
UCHAR SecBus, SubBus;
|
|||
|
USHORT VendorId;
|
|||
|
USHORT DeviceId;
|
|||
|
ULONG LegacyBaseAddress;
|
|||
|
USHORT i;
|
|||
|
USHORT Bus;
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("LookForPciCardBusBridges %x-%x\n", BusStart, BusEnd);
|
|||
|
#endif
|
|||
|
|
|||
|
for (Bus = BusStart; Bus <= BusEnd; Bus++) {
|
|||
|
|
|||
|
PcCardInfo.PciCfg1.u.AsULONG = 0;
|
|||
|
PcCardInfo.PciCfg1.u.bits.BusNumber = Bus;
|
|||
|
PcCardInfo.PciCfg1.u.bits.Enable = TRUE;
|
|||
|
|
|||
|
for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
|
|||
|
PcCardInfo.PciCfg1.u.bits.DeviceNumber = Device;
|
|||
|
|
|||
|
for (Function = 0; Function < PCI_MAX_FUNCTION; Function++) {
|
|||
|
PcCardInfo.PciCfg1.u.bits.FunctionNumber = Function;
|
|||
|
|
|||
|
VendorId = 0xffff;
|
|||
|
GetPciConfigSpace(&PcCardInfo, CFGSPACE_VENDOR_ID, &VendorId, sizeof(VendorId));
|
|||
|
|
|||
|
if ((VendorId == 0xffff) || (VendorId == 0)) {
|
|||
|
if (Function == 0) {
|
|||
|
break;
|
|||
|
} else {
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
GetPciConfigSpace(&PcCardInfo, CFGSPACE_DEVICE_ID, &DeviceId, sizeof(DeviceId));
|
|||
|
GetPciConfigSpace(&PcCardInfo, CFGSPACE_HEADER_TYPE, &HeaderType, sizeof(HeaderType));
|
|||
|
|
|||
|
switch(HeaderType & 0x7f) {
|
|||
|
case PCI_CARDBUS_BRIDGE_TYPE:
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("%x.%x.%x : DeviceID = %lx (CardBus Bridge)\n", Bus, Device, Function, DeviceId);
|
|||
|
#endif
|
|||
|
PcCardInfo.DeviceId = (ULONG) (VendorId << 16) | DeviceId;
|
|||
|
PcCardInfo.Flags = PCCARD_DEVICE_PCI;
|
|||
|
//
|
|||
|
// See if this is a special cased controller
|
|||
|
//
|
|||
|
PcCardInfo.bDevType = DEVTYPE_GENERIC_CARDBUS;
|
|||
|
i = 0;
|
|||
|
while (CBTable[i].DeviceId != 0) {
|
|||
|
if (DeviceId == CBTable[i].DeviceId) {
|
|||
|
PcCardInfo.bDevType = CBTable[i].bDevType;
|
|||
|
break;
|
|||
|
}
|
|||
|
i++;
|
|||
|
}
|
|||
|
|
|||
|
GetPciConfigSpace(&PcCardInfo, CFGSPACE_LEGACY_MODE_BASE_ADDR, &LegacyBaseAddress, 4);
|
|||
|
PcCardInfo.IoBase = (USHORT) (LegacyBaseAddress & ~1);
|
|||
|
|
|||
|
MapPcCardController(&PcCardInfo);
|
|||
|
break;
|
|||
|
|
|||
|
case PCI_BRIDGE_TYPE:
|
|||
|
#if DBG
|
|||
|
BlPrint("%x.%x.%x : DeviceID = %lx (Pci-Pci Bridge)\n", Bus, Device, Function, DeviceId);
|
|||
|
#endif
|
|||
|
GetPciConfigSpace(&PcCardInfo, CFGSPACE_SECONDARY_BUS, &SecBus, sizeof(SecBus));
|
|||
|
GetPciConfigSpace(&PcCardInfo, CFGSPACE_SUBORDINATE_BUS, &SubBus, sizeof(SubBus));
|
|||
|
|
|||
|
if ((SecBus <= Bus) || (SubBus <= Bus) || (SubBus < SecBus)) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Be conservative on stack space, only look one level deep
|
|||
|
//
|
|||
|
if (Bus > 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
LookForPciCardBusBridges(SecBus, SubBus);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
LookForPcicControllers(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is the entry for doing ISA IRQ detection for PCIC
|
|||
|
controllers.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCCARD_INFORMATION PcCardInfo = {0};
|
|||
|
USHORT IoBase;
|
|||
|
UCHAR id;
|
|||
|
|
|||
|
for (IoBase = 0x3e0; IoBase < 0x3e6; IoBase+=2) {
|
|||
|
if (IsOnLegacyBaseList(IoBase)) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
PcCardInfo.Flags = 0;
|
|||
|
PcCardInfo.IoBase = IoBase;
|
|||
|
PcCardInfo.bDevType = DEVTYPE_GENERIC_PCIC;
|
|||
|
|
|||
|
id = PcicReadSocket(&PcCardInfo, EXCAREG_IDREV);
|
|||
|
switch (id) {
|
|||
|
case PCIC_REVISION:
|
|||
|
case PCIC_REVISION2:
|
|||
|
case PCIC_REVISION3:
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("Pcic Controller at base %x, rev(%x)\n", IoBase, id);
|
|||
|
#endif
|
|||
|
MapPcCardController(&PcCardInfo);
|
|||
|
break;
|
|||
|
#if DBG
|
|||
|
default:
|
|||
|
BlPrint("Not mapping base %x, return is (%x)\n", IoBase, id);
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
FPFWCONFIGURATION_COMPONENT_DATA
|
|||
|
GetPcCardInformation(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is the entry for doing ISA IRQ detection for PcCard
|
|||
|
controllers.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
A pointer to a pccard component structure, if IRQ's were properly detected.
|
|||
|
Otherwise a NULL pointer is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCCARD_INFORMATION PcCardInfo = {0};
|
|||
|
UCHAR ErrorCode = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Check for things which would prevent us from attempting
|
|||
|
// the irq detection
|
|||
|
//
|
|||
|
|
|||
|
if (DisablePccardIrqScan == 1) {
|
|||
|
ErrorCode = PCCARD_SCAN_DISABLED;
|
|||
|
|
|||
|
} else if (!SystemHas8259) {
|
|||
|
ErrorCode = PCCARD_NO_PIC;
|
|||
|
|
|||
|
} else if (!SystemHas8253) {
|
|||
|
ErrorCode = PCCARD_NO_TIMER;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If things look ok so far, do the detection
|
|||
|
//
|
|||
|
if (!ErrorCode) {
|
|||
|
#if DBG
|
|||
|
BlPrint("press any key to continue...\n");
|
|||
|
while ( !HwGetKey() ) ; // wait until key pressed to continue
|
|||
|
clrscrn();
|
|||
|
BlPrint("Looking for PcCard Controllers...\n");
|
|||
|
#endif
|
|||
|
//
|
|||
|
// Look first for cardbus
|
|||
|
//
|
|||
|
LookForPciCardBusBridges(0,0);
|
|||
|
//
|
|||
|
// Now check for regular pcic devices
|
|||
|
//
|
|||
|
LookForPcicControllers();
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("press any key to continue...\n");
|
|||
|
while ( !HwGetKey() ) ; // wait until key pressed to continue
|
|||
|
#endif
|
|||
|
|
|||
|
if (!ControllerList) {
|
|||
|
ErrorCode = PCCARD_NO_CONTROLLERS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (ErrorCode) {
|
|||
|
//
|
|||
|
// Something when wrong, so write a single entry to
|
|||
|
// allow someone to see what the error was
|
|||
|
//
|
|||
|
PcCardInfo.Flags |= PCCARD_MAP_ERROR;
|
|||
|
PcCardInfo.ErrorCode = ErrorCode;
|
|||
|
SetPcCardConfigurationData(&PcCardInfo);
|
|||
|
}
|
|||
|
|
|||
|
return ControllerList;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
USHORT
|
|||
|
DetectIRQMap(
|
|||
|
PPCCARD_INFORMATION pa
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine detects the IRQ mapping of the specified cardbus controller.
|
|||
|
Note that the controller is in PCIC mode.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pa -> ADAPTER structure
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
returns detected IRQ bit mask
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
USHORT wRealIRQMask = 0;
|
|||
|
USHORT wData;
|
|||
|
UCHAR bData;
|
|||
|
|
|||
|
BOOLEAN fTINMIBug = FALSE;
|
|||
|
|
|||
|
UCHAR i;
|
|||
|
USHORT wIRQMask, wRealIRQ, w;
|
|||
|
|
|||
|
if (pa->bDevType == DEVTYPE_CL_PD6832)
|
|||
|
{
|
|||
|
//enable CSC IRQ routing just for IRQ detection
|
|||
|
GetPciConfigSpace(pa, CFGSPACE_BRIDGE_CTRL, &wData, sizeof(wData));
|
|||
|
wData |= BCTRL_CL_CSCIRQROUTING_ENABLE;
|
|||
|
SetPciConfigSpace(pa, CFGSPACE_BRIDGE_CTRL, &wData, sizeof(wData));
|
|||
|
}
|
|||
|
else if ((pa->bDevType == DEVTYPE_CL_PD6834) ||
|
|||
|
(pa->bDevType == DEVTYPE_CL_PD6833))
|
|||
|
{
|
|||
|
//enable CSC IRQ routing just for IRQ detection
|
|||
|
GetPciConfigSpace(pa, CFGSPACE_CL_CFGMISC1, &bData, sizeof(bData));
|
|||
|
bData |= CL_CFGMISC1_ISACSC;
|
|||
|
SetPciConfigSpace(pa, CFGSPACE_CL_CFGMISC1, &bData, sizeof(bData));
|
|||
|
}
|
|||
|
else if ((pa->bDevType == DEVTYPE_TI_PCI1130) ||
|
|||
|
(pa->bDevType == DEVTYPE_TI_PCI1131) ||
|
|||
|
(pa->bDevType == DEVTYPE_TI_PCI1031))
|
|||
|
{
|
|||
|
GetPciConfigSpace(pa, CFGSPACE_TI_DEV_CTRL, &wData, sizeof(wData));
|
|||
|
if ((wData & DEVCTRL_INTMODE_MASK) == DEVCTRL_INTMODE_COMPAQ)
|
|||
|
{
|
|||
|
//
|
|||
|
// There is an errata on TI 1130, 1131 and 1031 in which if
|
|||
|
// the chip is programmed to use serial IRQ mode (i.e. COMPAQ
|
|||
|
// mode) and the SERIRQ pin is not pull up with a 1K resistor,
|
|||
|
// the SERIRQ line will rise too slowly after IRQ 15 is
|
|||
|
// deasserted so that it looks like NMI should be asserted.
|
|||
|
// This caused spurious NMI. This is a hardware problem.
|
|||
|
// Unfortunately, there are a large number of machines with
|
|||
|
// this problem on the street already, so CBSS has to work
|
|||
|
// around the problem by temporarily disabling NMI before
|
|||
|
// doing ISA IRQ detection.
|
|||
|
//
|
|||
|
fTINMIBug = TRUE;
|
|||
|
_asm in al,SYSCTRL_B
|
|||
|
_asm and al,0x0f
|
|||
|
_asm push ax
|
|||
|
//
|
|||
|
// Mask NMI
|
|||
|
//
|
|||
|
_asm or al,0x08
|
|||
|
_asm out SYSCTRL_B,al
|
|||
|
}
|
|||
|
}
|
|||
|
_asm pushf
|
|||
|
_asm cli //disable interrupt
|
|||
|
_asm in al,PIC2_IMR //save old IMRs
|
|||
|
_asm mov ah,al
|
|||
|
_asm in al,PIC1_IMR
|
|||
|
_asm push ax
|
|||
|
|
|||
|
_asm mov al,0xff //mask all interrupt
|
|||
|
_asm out PIC2_IMR,al
|
|||
|
_asm out PIC1_IMR,al
|
|||
|
|
|||
|
for (i = 0; i < 16; ++i)
|
|||
|
{
|
|||
|
w = (USHORT)(1 << i);
|
|||
|
if ((pa->wValidIRQs & w) &&
|
|||
|
((wIRQMask = ToggleIRQLine(pa, i)) != 0))
|
|||
|
{
|
|||
|
_asm mov dx, wIRQMask
|
|||
|
_asm _emit 0x66
|
|||
|
_asm _emit 0x0f
|
|||
|
_asm _emit 0xbc
|
|||
|
_asm _emit 0xc2
|
|||
|
_asm mov wRealIRQ,ax
|
|||
|
pa->abIRQMap[wRealIRQ] = i;
|
|||
|
wRealIRQMask |= (USHORT)(1 << wRealIRQ);
|
|||
|
}
|
|||
|
}
|
|||
|
Clear_IR_Bits(wRealIRQMask);
|
|||
|
|
|||
|
_asm pop ax
|
|||
|
_asm out PIC1_IMR,al
|
|||
|
_asm mov al,ah
|
|||
|
_asm out PIC2_IMR,al
|
|||
|
_asm popf
|
|||
|
|
|||
|
if (fTINMIBug)
|
|||
|
{
|
|||
|
//
|
|||
|
// Restore NMI mask
|
|||
|
//
|
|||
|
_asm pop ax
|
|||
|
_asm out SYSCTRL_B,al
|
|||
|
}
|
|||
|
|
|||
|
if (pa->bDevType == DEVTYPE_CL_PD6832)
|
|||
|
{
|
|||
|
//disable CSC IRQ routing (use PCI interrupt for CSC)
|
|||
|
GetPciConfigSpace(pa, CFGSPACE_BRIDGE_CTRL, &wData, sizeof(wData));
|
|||
|
wData &= ~BCTRL_CL_CSCIRQROUTING_ENABLE;
|
|||
|
SetPciConfigSpace(pa, CFGSPACE_BRIDGE_CTRL, &wData, sizeof(wData));
|
|||
|
}
|
|||
|
else if ((pa->bDevType == DEVTYPE_CL_PD6834) ||
|
|||
|
(pa->bDevType == DEVTYPE_CL_PD6833))
|
|||
|
{
|
|||
|
//disable CSC IRQ routing (use PCI interrupt for CSC)
|
|||
|
GetPciConfigSpace(pa, CFGSPACE_CL_CFGMISC1, &bData, sizeof(bData));
|
|||
|
bData &= ~CL_CFGMISC1_ISACSC;
|
|||
|
SetPciConfigSpace(pa, CFGSPACE_CL_CFGMISC1, &bData, sizeof(bData));
|
|||
|
}
|
|||
|
|
|||
|
return wRealIRQMask;
|
|||
|
} //DetectIRQMap
|
|||
|
|
|||
|
|
|||
|
|
|||
|
USHORT
|
|||
|
ToggleIRQLine(
|
|||
|
PPCCARD_INFORMATION pa,
|
|||
|
UCHAR bIRQ
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine toggles the specified IRQ line from the adapter.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pa -> ADAPTER structure
|
|||
|
bIRQ - IRQ line to toggle
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
returns the IRR mask from PIC
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UCHAR bOldIntCtrl, bOldIntCfg, bData;
|
|||
|
USHORT rc = 0, irr1, irr2, irr3;
|
|||
|
|
|||
|
bOldIntCfg = PcicReadSocket(pa, EXCAREG_CSC_CFG);
|
|||
|
bOldIntCtrl = PcicReadSocket(pa, EXCAREG_INT_GENCTRL);
|
|||
|
|
|||
|
//Set to a known state
|
|||
|
PcicWriteSocket(pa, EXCAREG_INT_GENCTRL, IGC_PCCARD_RESETLO);
|
|||
|
|
|||
|
//Set irq number in interrupt control register and enable irq
|
|||
|
PcicWriteSocket(pa, EXCAREG_CSC_CFG, (UCHAR)((bIRQ << 4) | CSCFG_CD_ENABLE));
|
|||
|
|
|||
|
//clear all pending interrupts
|
|||
|
bData = PcicReadSocket(pa, EXCAREG_CARD_STATUS);
|
|||
|
irr1 = GetPICIRR();
|
|||
|
|
|||
|
if (PcicReadSocket(pa, EXCAREG_IDREV) != 0x82)
|
|||
|
{
|
|||
|
//This is not an A stepping part, try the undocumented interrupt
|
|||
|
//register. If this fails the other routine will be tried.
|
|||
|
PcicWriteSocket(pa, EXCAREG_CARDDET_GENCTRL, CDGC_SW_DET_INT);
|
|||
|
irr2 = GetPICIRR();
|
|||
|
|
|||
|
//reset pending interrupt
|
|||
|
bData = PcicReadSocket(pa, EXCAREG_CARD_STATUS);
|
|||
|
irr3 = GetPICIRR();
|
|||
|
rc = (USHORT)((irr1 ^ irr2) & (irr2 ^ irr3));
|
|||
|
}
|
|||
|
|
|||
|
if (rc == 0)
|
|||
|
{
|
|||
|
//Generate interrupt by de-asserting IRQ line so the PIC can pull it
|
|||
|
//high
|
|||
|
PcicWriteSocket(pa, EXCAREG_CSC_CFG, 0);
|
|||
|
//if (pa->dwfAdapter & AF_TI_SERIALIRQ)
|
|||
|
// TIReleaseSerialIRQ(pa, bIRQ);
|
|||
|
irr2 = GetPICIRR();
|
|||
|
|
|||
|
//re-assert IRQ line
|
|||
|
PcicWriteSocket(pa, EXCAREG_CSC_CFG, (UCHAR)((bIRQ << 4) | CSCFG_CD_ENABLE));
|
|||
|
|
|||
|
//reset pending interrupt
|
|||
|
bData = PcicReadSocket(pa, EXCAREG_CARD_STATUS);
|
|||
|
irr3 = GetPICIRR();
|
|||
|
rc = (USHORT)((irr1 ^ irr2) & (irr2 ^ irr3));
|
|||
|
}
|
|||
|
|
|||
|
PcicWriteSocket(pa, EXCAREG_CSC_CFG, bOldIntCfg);
|
|||
|
PcicWriteSocket(pa, EXCAREG_INT_GENCTRL, bOldIntCtrl);
|
|||
|
|
|||
|
return rc;
|
|||
|
} //ToggleIRQLine
|
|||
|
|
|||
|
|
|||
|
/***LP GetPICIRR - Read PIC IRR
|
|||
|
*
|
|||
|
* ENTRY
|
|||
|
* None
|
|||
|
*
|
|||
|
* EXIT
|
|||
|
* returns the IRR mask from PIC
|
|||
|
*/
|
|||
|
|
|||
|
USHORT GetPICIRR(VOID)
|
|||
|
{
|
|||
|
USHORT wData;
|
|||
|
|
|||
|
//
|
|||
|
// Delay 2 usec before reading PIC because serial IRQ may be a bit slow.
|
|||
|
//
|
|||
|
TimeOut(4);
|
|||
|
|
|||
|
_asm mov al,PIC_RD_IR
|
|||
|
_asm out PIC2_OCW3,al
|
|||
|
_asm in al,PIC2_OCW3
|
|||
|
_asm mov ah,al
|
|||
|
|
|||
|
_asm mov al,PIC_RD_IR
|
|||
|
_asm out PIC1_OCW3,al
|
|||
|
_asm in al,PIC1_OCW3
|
|||
|
|
|||
|
_asm mov wData,ax
|
|||
|
|
|||
|
return wData;
|
|||
|
} //GetPICIRR
|
|||
|
|
|||
|
|
|||
|
|
|||
|
UCHAR
|
|||
|
PcicReadSocket(
|
|||
|
PPCCARD_INFORMATION pa,
|
|||
|
USHORT Reg
|
|||
|
)
|
|||
|
{
|
|||
|
USHORT IoBase = pa->IoBase;
|
|||
|
UCHAR value;
|
|||
|
_asm {
|
|||
|
mov dx, IoBase
|
|||
|
mov ax, Reg
|
|||
|
out dx, al
|
|||
|
inc dx
|
|||
|
in al, dx
|
|||
|
mov value, al
|
|||
|
}
|
|||
|
return value;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
PcicWriteSocket(
|
|||
|
PPCCARD_INFORMATION pa,
|
|||
|
USHORT Reg,
|
|||
|
UCHAR value
|
|||
|
)
|
|||
|
{
|
|||
|
USHORT IoBase = pa->IoBase;
|
|||
|
_asm {
|
|||
|
mov dx, IoBase
|
|||
|
mov ax, Reg
|
|||
|
out dx, al
|
|||
|
inc dx
|
|||
|
mov al, value
|
|||
|
out dx, al
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UCHAR PCIDeref[4][4] = { {4,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
|
|||
|
|
|||
|
VOID
|
|||
|
SetPciConfigSpace(
|
|||
|
PPCCARD_INFORMATION pa,
|
|||
|
USHORT Offset,
|
|||
|
PVOID pvBuffer,
|
|||
|
USHORT Length
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
USHORT IoSize;
|
|||
|
PUCHAR Buffer = (PUCHAR) pvBuffer;
|
|||
|
//
|
|||
|
// Read it
|
|||
|
//
|
|||
|
while (Length) {
|
|||
|
pa->PciCfg1.u.bits.RegisterNumber = Offset / sizeof(ULONG);
|
|||
|
|
|||
|
IoSize = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
|
|||
|
|
|||
|
SetPCIType1Data (pa->PciCfg1.u.AsULONG,
|
|||
|
(Offset % sizeof(ULONG)),
|
|||
|
Buffer,
|
|||
|
IoSize);
|
|||
|
|
|||
|
Offset += IoSize;
|
|||
|
Buffer += IoSize;
|
|||
|
Length -= IoSize;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
GetPciConfigSpace(
|
|||
|
PPCCARD_INFORMATION pa,
|
|||
|
USHORT Offset,
|
|||
|
PVOID pvBuffer,
|
|||
|
USHORT Length
|
|||
|
)
|
|||
|
{
|
|||
|
USHORT IoSize;
|
|||
|
USHORT i;
|
|||
|
PUCHAR Buffer = (PUCHAR) pvBuffer;
|
|||
|
|
|||
|
//
|
|||
|
// Zap input buffer
|
|||
|
//
|
|||
|
|
|||
|
for (i=0; i < Length; i++) {
|
|||
|
Buffer[i] = 0xff;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Read it
|
|||
|
//
|
|||
|
while (Length) {
|
|||
|
pa->PciCfg1.u.bits.RegisterNumber = Offset / sizeof(ULONG);
|
|||
|
|
|||
|
IoSize = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
|
|||
|
|
|||
|
GetPCIType1Data (pa->PciCfg1.u.AsULONG,
|
|||
|
(Offset % sizeof(ULONG)),
|
|||
|
Buffer,
|
|||
|
IoSize);
|
|||
|
|
|||
|
Offset += IoSize;
|
|||
|
Buffer += IoSize;
|
|||
|
Length -= IoSize;
|
|||
|
}
|
|||
|
}
|
|||
|
|