/*++ Copyright (c) 1990 Microsoft Corporation Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file contains copyrighted material. Use of this file is restricted by the provisions of a Motorola Software License Agreement. Copyright (c) 1995-96 International Business Machines Corporation Module Name: pxmemctl.c Abstract: The module initializes any planar registers. This module also implements machince check parity error handling. Author: Jim Wooldridge (jimw@austin.vnet.ibm.com) Revision History: --*/ #include "halp.h" #include "pci.h" #include "pcip.h" extern PVOID HalpPciConfigBase; #define PCI_INTERRUPT_ROUTING_OTHER 15 //IBMCPK: should we really have seperate scsi int?? #define PCI_INTERRUPT_ROUTING_SCSI PCI_INTERRUPT_ROUTING_OTHER #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE,HalpGetPCIIrq) #endif ULONG HalpPciMaxSlots = PCI_MAX_DEVICES; ULONG HalpTranslatePciSlotNumber ( ULONG BusNumber, ULONG SlotNumber ) /*++ Routine Description: This routine translate a PCI slot number to a PCI device number. This is a sandalfoot memory map implementation. Arguments: None. Return Value: Returns length of data written. --*/ { // // Sandalfoot only has 1 PCI bus so bus number is unused // PCI_TYPE1_CFG_BITS PciConfig; PCI_SLOT_NUMBER PciSlotNumber; PciSlotNumber.u.AsULONG = SlotNumber; PciConfig.u.AsULONG = 0; PciConfig.u.bits.DeviceNumber = PciSlotNumber.u.bits.DeviceNumber; PciConfig.u.bits.FunctionNumber = PciSlotNumber.u.bits.FunctionNumber; PciConfig.u.bits.BusNumber = BusNumber; PciConfig.u.bits.Enable = TRUE; return (PciConfig.u.AsULONG); } ULONG HalpPhase0SetPciDataByOffset ( ULONG BusNumber, ULONG SlotNumber, PUCHAR Buffer, ULONG Offset, ULONG Length ) /*++ Routine Description: This routine writes to PCI configuration space prior to bus handler installation. Arguments: None. Return Value: Returns length of data written. --*/ { ULONG to; PUCHAR from; ULONG tmpLength; ULONG i; if (SlotNumber < HalpPciMaxSlots) { to = (ULONG) HalpPciConfigBase + (SlotNumber << 11); to += Offset; from = Buffer; tmpLength = Length; while (tmpLength > 0) { WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, to ); i = to % sizeof(ULONG); WRITE_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i,*from); to++; from++; tmpLength--; } return(Length); } else { return (0); } } ULONG HalpPhase0GetPciDataByOffset ( ULONG BusNumber, ULONG SlotNumber, PUCHAR Buffer, ULONG Offset, ULONG Length ) /*++ Routine Description: This routine reads PCI config space prior to bus handlder installation. Arguments: None. Return Value: Amount of data read. --*/ { PUCHAR to; ULONG from; ULONG tmpLength; ULONG i; if (SlotNumber < HalpPciMaxSlots) { from = (ULONG) HalpPciConfigBase + (SlotNumber << 11); from += Offset; to = Buffer; tmpLength = Length; while (tmpLength > 0) { WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, from); i = from % sizeof(ULONG); *((PUCHAR) to) = READ_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i); to++; from++; tmpLength--; } return(Length); } else { return (0); } } NTSTATUS HalpGetPCIIrq ( IN PBUS_HANDLER BusHandler, IN PBUS_HANDLER RootHandler, IN PCI_SLOT_NUMBER PciSlot, OUT PSUPPORTED_RANGE *Interrupt ) { ULONG buffer[PCI_COMMON_HDR_LENGTH/sizeof(ULONG)]; PPCI_COMMON_CONFIG PciData; #define PCI_VENDOR_NCR 0x1000 PciData = (PPCI_COMMON_CONFIG) buffer; HalGetBusData ( PCIConfiguration, BusHandler->BusNumber, PciSlot.u.AsULONG, PciData, PCI_COMMON_HDR_LENGTH ); if (PciData->VendorID == PCI_INVALID_VENDORID || PCI_CONFIG_TYPE (PciData) != 0) { return STATUS_UNSUCCESSFUL; } *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE)); if (!*Interrupt) { return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE)); if (PciSlot.u.bits.DeviceNumber == 2) { (*Interrupt)->Base = PCI_INTERRUPT_ROUTING_SCSI; (*Interrupt)->Limit = PCI_INTERRUPT_ROUTING_SCSI; } else { (*Interrupt)->Base = PCI_INTERRUPT_ROUTING_OTHER; (*Interrupt)->Limit = PCI_INTERRUPT_ROUTING_OTHER; } #if defined(SOFT_HDD_LAMP) if ( (PciData->BaseClass == 1) || ( (PciData->VendorID == PCI_VENDOR_NCR) && (PciData->DeviceID == 1) ) ) { // // This device is a Mass Storage Controller, set flag to // turn on the HDD Lamp when interrupts come in on this // vector. // // N.B. We recognize NCR 810 controllers as they were implemented // before class codes. // extern ULONG HalpMassStorageControllerVectors; HalpMassStorageControllerVectors |= 1 << (*Interrupt)->Base; } #endif return STATUS_SUCCESS; } VOID HalpMapPlugInPciBridges( UCHAR NoBuses ) /*++ Routine Description: Looks for any unexpected (plug-in) PCI-PCI bridges so that interrupts can be mapped from these buses back into the interrupt controller. Arguments: NoBuses -- This is the number of buses that HalpGetPciBridgeConfig found Return Value: none --*/ { // Carolina supports some plug-in PCI busses, but this // HAL doesn't need to build the map because all Carolina PCI // interrupts are routed to the same IRQ. Hence the // map reduces to nothing. return; }