//------------------------------------------------------------------------------
//
//  Function:  InitKitlNIC
//
//  Finds a supported PCI NIC, matching against g_NicSupported
//  If nothing is found it will return attempt to use dwDfltType with the input params, dwIrq and dwIoBase.
//  If that failes too, it will return NULL
//
PCKITL_NIC_INFO InitKitlNIC(
                            DWORD dwIrq, 
                            DWORD dwIoBase, 
                            DWORD dwDfltType
                            )
{
    PCI_COMMON_CONFIG   pciConfig;
    int                 funcType, bus, device, function;
    PCSUPPORTED_NIC     pNicFound;
    int                 length = 0;
    enum {
        FIND_BY_VENDOR, // 0
        FIND_BY_TYPE    // 1
    };

    // InitKitlNIC returns a pointer to this
    static KTIL_NIC_INFO KitlNic;

    KITLOutputDebugString("InitKitlNIC: Searching for PCI Ethernet NIC (dwIrq = %x, dwIoBase = %x, dwDfltType = %x) ...\r\n",
        dwIrq, dwIoBase, dwDfltType);

    // Pass 1: iterate searching for vendor (this is the best match)
    // Pass 2: iterate searching for matching type
    for (funcType = FIND_BY_VENDOR; funcType <= FIND_BY_TYPE; funcType++)
    {
        // iterate through buses
        for (bus = 0; bus < PCI_MAX_BUS; bus++) 
        {
            // iterate through devices
            for (device = 0; device < PCI_MAX_DEVICES; device++) 
            {
                // iterate through functions
                for (function = 0; function < PCI_MAX_FUNCTION; function++) 
                {
                    // read PCI config data
                    OAL_PCI_LOCATION pciLoc;
                    pciLoc.logicalLoc = bus << 16 | device << 8 | function;

                    length = OALPCICfgRead(0,
                        pciLoc,
                        0,
                        (sizeof(pciConfig) - sizeof(pciConfig.DeviceSpecific)),
                        &pciConfig);

                    if (length == 0 || (pciConfig.VendorID == 0xFFFF))
                        break;

                    // network controller or USB?
                    if (    (  (pciConfig.BaseClass == PCI_CLASS_NETWORK_CTLR)
                            && (pciConfig.SubClass  == PCI_SUBCLASS_NET_ETHERNET_CTLR)) // Network device.
                        ||  (  (pciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
                            && (pciConfig.SubClass  == PCI_SUBCLASS_BR_OTHER))) 
                    {    
                        // Other Unknown Special Devices
                        DWORD dwFoundBase = pciConfig.u.type0.BaseAddresses[0] & 0xFFFFFFFC;
                        DWORD dwFoundIrq  = pciConfig.u.type0.InterruptLine;
                    
                        if (dwFoundIrq && dwFoundBase) 
                        {
                            if (   (!dwIrq && !dwIoBase)                                    // IRQ && IoBase not specified -- use 1st found
                                || (dwIrq == OAL_KITL_IRQ_INVALID)                          // Undefined IRQ = Poll mode -- use first found    
                                || (!dwIoBase && (dwIrq == dwFoundIrq))                     // IRQ match, no IO base specified
                                || (dwIoBase == dwFoundBase))                               // IOBase match
                            {
                                if(funcType == FIND_BY_VENDOR) 
                                {
                                    pNicFound = FindNICByVendor (&pciConfig);
                                }
                                else if(funcType == FIND_BY_TYPE) 
                                {
                                    pNicFound = FindNICByType ((UCHAR) dwDfltType);
                                }

                                if (pNicFound) 
                                {
                                    // found NIC card
                                    KitlNic.dwIoBase   = dwFoundBase;
                                    KitlNic.dwIrq      = dwFoundIrq;
                                    KitlNic.dwBus      = bus;
                                    KitlNic.dwDevice   = device;
                                    KitlNic.dwFunction = function;
                                    KitlNic.pDriver    = pNicFound->pDriver;
                                    KitlNic.dwType     = pNicFound->Type;
                                    memcpy (&KitlNic.pciConfig, &pciConfig, sizeof(pciConfig));

                                    KITLOutputDebugString ("InitKitlNIC: Found PCI Ethernet NIC (type = %x, IRQ=%d, IOBase=0x%x).\r\n",
                                        pNicFound->Type, dwFoundIrq, dwFoundBase);

                                    return &KitlNic;
                                }
                                else
                                {
                                    KITLOutputDebugString ("InitKitlNIC: skipping unknown PCI Ethernet NIC: (subclass=%x, Vendor=%x, Device=%x)\r\n", 
                                                            pciConfig.SubClass, pciConfig.VendorID, pciConfig.DeviceID);
                                }
                            }
                            else
                            {
                                // found a NIC, but it didn't match what the bootloader was using
                                KITLOutputDebugString ("InitKitlNIC: skipping PCI Ethernet NIC: (subclass = %x, IRQ=%d, IOBase=0x%x).\r\n",
                                                        pciConfig.SubClass, dwFoundIrq, dwFoundBase);
                            }
                        }
                    }
                
                    if (function == 0 && !(pciConfig.HeaderType & 0x80)) 
                        break;
                }
                if (length == 0)
                    break;
            }

            if (length == 0 && device == 0)
                break;
        }

    }

    // can't find it on PCI bus, if IRQ and IoBase are specified, use it
    if (dwIrq && dwIoBase && (pNicFound = FindNICByType ((UCHAR) dwDfltType))) 
    {
        KitlNic.dwIoBase   = dwIoBase;
        KitlNic.dwIrq      = dwIrq;
        KitlNic.pDriver    = pNicFound->pDriver;
        KitlNic.dwType     = dwDfltType;

        // Signal that we're using a device but it's not on the PCI bus
        memset(&KitlNic.pciConfig, LEGACY_KITL_DEVICE_BYTEPATTERN, sizeof(pciConfig));

        KITLOutputDebugString ("InitKitlNIC: Can't find PCI Ethernet NIC, use specified data (type = %x, IRQ=%d, IOBase=0x%x).\r\n",
            pNicFound->Type, dwIrq, dwIoBase);
        return &KitlNic;
    }
    
    return NULL;
}
Esempio n. 2
0
//------------------------------------------------------------------------------
//
//  Function:  OALPCIInit
//
BOOL OALPCIInit()
{
    VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA);
    M1535_CFG_REGS *pM1535Regs = OALPAtoUA(BSP_REG_PA_M1535_CFG);
    OAL_PCI_LOCATION pciLoc;
    UINT32 u32;

    //----------------------------------------------------------------------
    // External PCI
    //----------------------------------------------------------------------

    // Cold reset
    OUTREG32(&pVRC5477Regs->PCICTL0H, PCI_CTRL_CRST);
    OALStall(100000);
    OUTREG32(&pVRC5477Regs->PCICTL0H, 0);
    OALStall(100000);
    
    // Setup windows
    OUTREG32(&pVRC5477Regs->PCIINIT00, BSP_PCI_INIT00);
    OUTREG32(&pVRC5477Regs->PCIW0, BSP_PCI_W0);
    OUTREG32(&pVRC5477Regs->PCIINIT10, BSP_PCI_INIT10);
    OUTREG32(&pVRC5477Regs->PCIW1, BSP_PCI_W1);

    // Setup control & arbiter registers
    OUTREG32(&pVRC5477Regs->PCICTL0L, BSP_PCI_CTL0L);
    OUTREG32(&pVRC5477Regs->PCICTL0H, BSP_PCI_CTL0H);
    OUTREG32(&pVRC5477Regs->PCIARB0L, BSP_PCI_ARB0L);
    OUTREG32(&pVRC5477Regs->PCIARB0H, BSP_PCI_ARB0H);
        
    // Setup configuration space
    OUTREG16(&pVRC5477Regs->PCICMD0, BSP_PCI_CMD0);
    OUTREG8(&pVRC5477Regs->MLTIM0, BSP_PCI_MLTIM0);
    OUTREG32(&pVRC5477Regs->BARC0, BSP_PCI_BARC0);
    OUTREG32(&pVRC5477Regs->BARM010, BSP_PCI_BARM010);
    OUTREG32(&pVRC5477Regs->BARM230, BSP_PCI_BARM230);
    OUTREG32(&pVRC5477Regs->BAR00, BSP_PCI_BAR00);
    OUTREG32(&pVRC5477Regs->BAR10, BSP_PCI_BAR10);
    OUTREG32(&pVRC5477Regs->BAR20, BSP_PCI_BAR20);
    OUTREG32(&pVRC5477Regs->BARB0, BSP_PCI_BARB0);
    OUTREG32(&pVRC5477Regs->BARP00, BSP_PCI_BARP00);
    OUTREG32(&pVRC5477Regs->BARP10, BSP_PCI_BARP10);

    //----------------------------------------------------------------------
    // Internal PCI
    //----------------------------------------------------------------------

    OUTREG32(&pVRC5477Regs->PCICTL1H, PCI_CTRL_CRST);
    OALStall(100000);
    OUTREG32(&pVRC5477Regs->PCICTL1H, 0);
    OALStall(100000);

    // Setup internal PCI windows
    OUTREG32(&pVRC5477Regs->PCIINIT01, BSP_PCI_INIT01);
    OUTREG32(&pVRC5477Regs->IOPCIW0, BSP_IOPCI_W0);
    OUTREG32(&pVRC5477Regs->PCIINIT11, BSP_PCI_INIT11);
    OUTREG32(&pVRC5477Regs->IOPCIW1, BSP_IOPCI_W1);

    // Setup control & arbiter registers
    OUTREG32(&pVRC5477Regs->PCICTL1L, BSP_PCI_CTL1L);
    OUTREG32(&pVRC5477Regs->PCICTL1H, BSP_PCI_CTL1H);
    OUTREG32(&pVRC5477Regs->PCIARB1L, BSP_PCI_ARB1L);
    OUTREG32(&pVRC5477Regs->PCIARB1H, BSP_PCI_ARB1H);
    
    // Setup configuration space
    OUTREG16(&pVRC5477Regs->PCICMD1, BSP_PCI_CMD1);
    OUTREG8(&pVRC5477Regs->MLTIM1, BSP_PCI_MLTIM1);
    OUTREG32(&pVRC5477Regs->BARC1, BSP_PCI_BARC1);
    OUTREG32(&pVRC5477Regs->BARM011, BSP_PCI_BARM011);
    OUTREG32(&pVRC5477Regs->BARM231, BSP_PCI_BARM231);
    OUTREG32(&pVRC5477Regs->BAR01, BSP_PCI_BAR01);
    OUTREG32(&pVRC5477Regs->BAR11, BSP_PCI_BAR11);
    OUTREG32(&pVRC5477Regs->BAR21, BSP_PCI_BAR21);
    OUTREG32(&pVRC5477Regs->BARB1, BSP_PCI_BARB1);
    OUTREG32(&pVRC5477Regs->BARP01, BSP_PCI_BARP01);
    OUTREG32(&pVRC5477Regs->BARP11, BSP_PCI_BARP11);

    OALStall(10000);

    //----------------------------------------------------------------------
    // ALI M1535+ South Bridge
    //----------------------------------------------------------------------
    // Is there ALI M1535+ bridge = CPU board is inserted to SG2 mother board,
    // in such case we must do some initialization --- default config address
    // lines for some ALI M1535+ internal devices colide with PCI slot config
    // address lines.
    pciLoc.bus = 0;
    pciLoc.dev = 8;
    pciLoc.fnc = 0;
    OALPCICfgRead(0, pciLoc, 0, sizeof(u32), &u32);
    if (u32 != 0x153310B9) goto cleanUp;

    //----------------------------------------------------------------------
    // PCI-ISA bridge initialize
    //----------------------------------------------------------------------

    OALLog(L"INFO: OALPCIInit: ALI M1535+ Bridge detected\r\n");

    u32 = 0x0000C119;   // I/O control, select PS2 keyboad/mouse
    OALPCICfgWrite(0, pciLoc, 0x40, sizeof(u32), &u32);
    u32 = 0x0000025D;   // Primary IDE IRQ14
    OALPCICfgWrite(0, pciLoc, 0x44, sizeof(u32), &u32);
    u32 = 0x70000009;   // Audio->IRQ6, PCI INTC->IRQ11
    OALPCICfgWrite(0, pciLoc, 0x48, sizeof(u32), &u32);
    u32 = 0x00000000;   // USB1 enable
    OALPCICfgWrite(0, pciLoc, 0x50, sizeof(u32), &u32);
    u32 = 0x00000000;   // PCSJ
    OALPCICfgWrite(0, pciLoc, 0x54, sizeof(u32), &u32);
    u32 = 0x0000007C;   // IDE IDSEL(AD15), INTR
    OALPCICfgWrite(0, pciLoc, 0x58, sizeof(u32), &u32);
    u32 = 0x00004000;   // Document recommend???
    OALPCICfgWrite(0, pciLoc, 0x6C, sizeof(u32), &u32);
    u32 = 0x002600D2;   // PMU IDSEL(AD14), USB IDSEL(AD13)
    OALPCICfgWrite(0, pciLoc, 0x70, sizeof(u32), &u32);
    u32 = 0x40801F01;   // No modem, USB INTR(IRQ09), 2nd IDE IRQ15, AC97 IDSEL(AD17)
    OALPCICfgWrite(0, pciLoc, 0x74, sizeof(u32), &u32);
    u32 = 0x00000000;   // USB2 disable
    OALPCICfgWrite(0, pciLoc, 0x7C, sizeof(u32), &u32);

    //---------------------------
    // Configure super I/O chip
    //---------------------------
    
    OUTPORT8(&pM1535Regs->config, 0x51);    // Enter config mode
    OUTPORT8(&pM1535Regs->config, 0x23);    
    
    // Enable parallel port
    OUTPORT8(&pM1535Regs->index, 0x07);
    OUTPORT8(&pM1535Regs->data,  0x03);     // Select logical device 3
    OUTPORT8(&pM1535Regs->index, 0x30);
    OUTPORT8(&pM1535Regs->data,  0x01);     // Enable device
    OUTPORT8(&pM1535Regs->index, 0x60);
    OUTPORT8(&pM1535Regs->data,  0x03);     // I/O address: 378h
    OUTPORT8(&pM1535Regs->index, 0x61);
    OUTPORT8(&pM1535Regs->data,  0x78);     // I/O address: 378h
    OUTPORT8(&pM1535Regs->index, 0x70);
    OUTPORT8(&pM1535Regs->data,  0x07);     // Irq: 7
    
    // Enable UART1
    OUTPORT8(&pM1535Regs->index, 0x07);
    OUTPORT8(&pM1535Regs->data,  0x04);     // Select logical device 4
    OUTPORT8(&pM1535Regs->index, 0x30);
    OUTPORT8(&pM1535Regs->data,  0x01);     // Enable device
    OUTPORT8(&pM1535Regs->index, 0x60);
    OUTPORT8(&pM1535Regs->data,  0x03);     // I/O address: 3F8h
    OUTPORT8(&pM1535Regs->index, 0x61);
    OUTPORT8(&pM1535Regs->data,  0xF8);     // I/O address: 3F8h
    OUTPORT8(&pM1535Regs->index, 0x70);
    OUTPORT8(&pM1535Regs->data,  0x04);     // Irq: 4
    
    // Enable UART2/INFRA
    OUTPORT8(&pM1535Regs->index, 0x07);
    OUTPORT8(&pM1535Regs->data,  0x05);     // Select logical device 5
    OUTPORT8(&pM1535Regs->index, 0x30);
    OUTPORT8(&pM1535Regs->data,  0x01);     // Enable device
    OUTPORT8(&pM1535Regs->index, 0x60);
    OUTPORT8(&pM1535Regs->data,  0x03);     // I/O address: 3E8h
    OUTPORT8(&pM1535Regs->index, 0x61);
    OUTPORT8(&pM1535Regs->data,  0xE8);     // I/O address: 3E8h
    OUTPORT8(&pM1535Regs->index, 0x70);
    OUTPORT8(&pM1535Regs->data,  0x05);     // Irq: 5
    
    // Enable PS/2 controller
    OUTPORT8(&pM1535Regs->index, 0x07);
    OUTPORT8(&pM1535Regs->data,  0x07);     // Select logical device 7.
    OUTPORT8(&pM1535Regs->index, 0x30);
    OUTPORT8(&pM1535Regs->data,  0x01);     // Enable device
    OUTPORT8(&pM1535Regs->index, 0x70);
    OUTPORT8(&pM1535Regs->data,  0x01);     // Irq: 1 - keyboard
    OUTPORT8(&pM1535Regs->index, 0x72);
    OUTPORT8(&pM1535Regs->data,  0x0C);     // Irq: 12 - mouse
    
    // Enable UART3
    OUTPORT8(&pM1535Regs->index, 0x07);
    OUTPORT8(&pM1535Regs->data,  0x0B);     // Select logical device 11
    OUTPORT8(&pM1535Regs->index, 0x30);
    OUTPORT8(&pM1535Regs->data,  0x01);     // Enable device
    OUTPORT8(&pM1535Regs->index, 0x60);
    OUTPORT8(&pM1535Regs->data,  0x02);     // I/O address: 2F8h
    OUTPORT8(&pM1535Regs->index, 0x61);
    OUTPORT8(&pM1535Regs->data,  0xF8);     // I/O address: 2F8h
    OUTPORT8(&pM1535Regs->index, 0x70);
    OUTPORT8(&pM1535Regs->data,  0x03);     // Irq: 3
    
    // Exit config mode
    OUTPORT8(&pM1535Regs->config, 0xBB);
  
cleanUp:
    return TRUE;
}