⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcilib.c

📁 AT91RM9200的完整启动代码:包括loader, boot及U-boot三部分均已编译通过!欢迎下载使用!
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************                   SciTech OS Portability Manager Library**  ========================================================================**    The contents of this file are subject to the SciTech MGL Public*    License Version 1.0 (the "License"); you may not use this file*    except in compliance with the License. You may obtain a copy of*    the License at http://www.scitechsoft.com/mgl-license.txt**    Software distributed under the License is distributed on an*    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or*    implied. See the License for the specific language governing*    rights and limitations under the License.**    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.**    The Initial Developer of the Original Code is SciTech Software, Inc.*    All Rights Reserved.**  ========================================================================** Language:     ANSI C* Environment:  Any** Description:  Module for interfacing to the PCI bus and configuration*               space registers.*****************************************************************************/#include "pmapi.h"#include "pcilib.h"#if !defined(__WIN32_VXD__) && !defined(__NT_DRIVER__)#include <string.h>#endif/*---------------------- Macros and type definitions ----------------------*/#pragma pack(1)/* Length of the memory mapping for the PCI BIOS */#define BIOS_LIMIT          (128 * 1024L - 1)/* Macros for accessing the PCI BIOS functions from 32-bit protected mode */#define BIOS32_SIGNATURE    (((ulong)'_' << 0) + ((ulong)'3' << 8) + ((ulong)'2' << 16) + ((ulong)'_' << 24))#define PCI_SIGNATURE       (((ulong)'P' << 0) + ((ulong)'C' << 8) + ((ulong)'I' << 16) + ((ulong)' ' << 24))#define PCI_SERVICE         (((ulong)'$' << 0) + ((ulong)'P' << 8) + ((ulong)'C' << 16) + ((ulong)'I' << 24))#define PCI_BIOS_PRESENT    0xB101#define FIND_PCI_DEVICE     0xB102#define FIND_PCI_CLASS      0xB103#define GENERATE_SPECIAL    0xB106#define READ_CONFIG_BYTE    0xB108#define READ_CONFIG_WORD    0xB109#define READ_CONFIG_DWORD   0xB10A#define WRITE_CONFIG_BYTE   0xB10B#define WRITE_CONFIG_WORD   0xB10C#define WRITE_CONFIG_DWORD  0xB10D#define GET_IRQ_ROUTING_OPT 0xB10E#define SET_PCI_IRQ         0xB10F/* This is the standard structure used to identify the entry point to the * BIOS32 Service Directory, as documented in PCI 2.1 BIOS Specicition. */typedef union {    struct {        ulong signature;        /* _32_                                 */        ulong entry;            /* 32 bit physical address              */        uchar revision;         /* Revision level, 0                    */        uchar length;           /* Length in paragraphs should be 01    */        uchar checksum;         /* All bytes must add up to zero        */        uchar reserved[5];      /* Must be zero                         */        } fields;    char chars[16];    } PCI_bios32;/* Structure for a far pointer to call the PCI BIOS services with */typedef struct {    ulong   address;    ushort  segment;    } PCIBIOS_entry;/* Macros to copy a structure that includes dwSize members */#define COPY_STRUCTURE(d,s) memcpy(d,s,MIN((s)->dwSize,(d)->dwSize))#pragma pack()/*--------------------------- Global variables ----------------------------*/static uchar            *BIOSImage = NULL;  /* BIOS image mapping       */static int              PCIBIOSVersion = -1;/* PCI BIOS version         */static PCIBIOS_entry    PCIEntry;           /* PCI services entry point */static ulong            PCIPhysEntry = 0;   /* Physical address         *//*----------------------------- Implementation ----------------------------*//* External assembler helper functions */uchar   _ASMAPI _BIOS32_service(ulong service,ulong function,ulong *physBase,ulong *length,ulong *serviceOffset,PCIBIOS_entry entry);ushort  _ASMAPI _PCIBIOS_isPresent(ulong i_eax,ulong *o_edx,ushort *o_ax,uchar *o_cl,PCIBIOS_entry entry);ulong   _ASMAPI _PCIBIOS_service(ulong r_eax,ulong r_ebx,ulong r_edi,ulong r_ecx,PCIBIOS_entry entry);int     _ASMAPI _PCIBIOS_getRouting(PCIRoutingOptionsBuffer *buf,PCIBIOS_entry entry);ibool   _ASMAPI _PCIBIOS_setIRQ(int busDev,int intPin,int IRQ,PCIBIOS_entry entry);ulong   _ASMAPI _PCIBIOS_specialCycle(int bus,ulong data,PCIBIOS_entry entry);ushort  _ASMAPI _PCI_getCS(void);/****************************************************************************REMARKS:This functions returns the physical address of the PCI BIOS entry point.****************************************************************************/ulong _ASMAPI PCIBIOS_getEntry(void){ return PCIPhysEntry; }/****************************************************************************PARAMETERS:hwType  - Place to store the PCI hardware access mechanism flagslastBus - Place to store the index of the last PCI bus in the systemRETURNS:Version number of the PCI BIOS found.REMARKS:This function determines if the PCI BIOS is present in the system, and ifso returns the information returned by the PCI BIOS detect function.****************************************************************************/static int PCIBIOS_detect(    uchar *hwType,    uchar *lastBus){    ulong   signature;    ushort  stat,version;#ifndef __16BIT__    PCIBIOS_entry   BIOSEntry = {0};    uchar           *BIOSEnd;    PCI_bios32      *BIOSDir;    ulong           physBase,length,offset;    /* Bail if we have already detected no BIOS is present */    if (PCIBIOSVersion == 0)        return 0;    /* First scan the memory from 0xE0000 to 0xFFFFF looking for the     * BIOS32 service directory, so we can determine if we can call it     * from 32-bit protected mode.     */    if (PCIBIOSVersion == -1) {        PCIBIOSVersion = 0;        BIOSImage = PM_mapPhysicalAddr(0xE0000,BIOS_LIMIT,false);        if (!BIOSImage)            return 0;        BIOSEnd = BIOSImage + 0x20000;        for (BIOSDir = (PCI_bios32*)BIOSImage; BIOSDir < (PCI_bios32*)BIOSEnd; BIOSDir++) {            uchar   sum;            int     i,length;            if (BIOSDir->fields.signature != BIOS32_SIGNATURE)                continue;            length = BIOSDir->fields.length * 16;            if (!length)                continue;            for (sum = i = 0; i < length ; i++)                sum += BIOSDir->chars[i];            if (sum != 0)                continue;            BIOSEntry.address = (ulong)BIOSImage + (BIOSDir->fields.entry - 0xE0000);            BIOSEntry.segment = _PCI_getCS();            break;            }        /* If we found the BIOS32 directory, call it to get the address of the         * PCI services.         */        if (BIOSEntry.address == 0)            return 0;        if (_BIOS32_service(PCI_SERVICE,0,&physBase,&length,&offset,BIOSEntry) != 0)            return 0;        PCIPhysEntry = physBase + offset;        PCIEntry.address = (ulong)BIOSImage + (PCIPhysEntry - 0xE0000);        PCIEntry.segment = _PCI_getCS();        }#endif    /* We found the BIOS entry, so now do the version check */    version = _PCIBIOS_isPresent(PCI_BIOS_PRESENT,&signature,&stat,lastBus,PCIEntry);    if (version > 0 && ((stat >> 8) == 0) && signature == PCI_SIGNATURE) {        *hwType = stat & 0xFF;        return PCIBIOSVersion = version;        }    return 0;}/****************************************************************************PARAMETERS:info    - Array of PCIDeviceInfo structures to check againstindex   - Index of the current device to checkRETURNS:True if the device is a duplicate, false if not.REMARKS:This function goes through the list of all devices preceeding the newlyfound device in the info structure, and checks that the device is not aduplicate of a previous device. Some devices incorrectly enumeratethemselves at different function addresses so we check here to excludethose cases.****************************************************************************/static ibool CheckDuplicate(    PCIDeviceInfo *info,    PCIDeviceInfo *prev){    /* Ignore devices with a vendor ID of 0 */    if (info->VendorID == 0)        return true;    /* NOTE: We only check against the current device on     *       the bus to ensure that we do not exclude     *       multiple controllers of the same device ID.     */    if (info->slot.p.Bus == prev->slot.p.Bus &&        info->slot.p.Device == prev->slot.p.Device &&        info->DeviceID == prev->DeviceID)        return true;    return false;}/****************************************************************************PARAMETERS:info        - Array of PCIDeviceInfo structures to fill inmaxDevices  - Maximum number of of devices to enumerate into arrayRETURNS:Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.REMARKS:Function to enumerate all available devices on the PCI bus into an arrayof configuration information blocks.****************************************************************************/static int PCI_enumerateMech1(    PCIDeviceInfo info[]){    int             bus,device,function,i,numFound = 0;    ulong           *lp,tmp;    PCIslot         slot = {{0,0,0,0,0,0,1}};    PCIDeviceInfo   pci,prev = {0};    /* Try PCI access mechanism 1 */    PM_outpb(0xCFB,0x01);    tmp = PM_inpd(0xCF8);    PM_outpd(0xCF8,slot.i);    if ((PM_inpd(0xCF8) == slot.i) && (PM_inpd(0xCFC) != 0xFFFFFFFFUL)) {        /* PCI access mechanism 1 - the preferred mechanism */        for (bus = 0; bus < 8; bus++) {            slot.p.Bus = bus;            for (device = 0; device < 32; device++) {                slot.p.Device = device;                for (function = 0; function < 8; function++) {                    slot.p.Function = function;                    slot.p.Register = 0;                    PM_outpd(0xCF8,slot.i);                    if (PM_inpd(0xCFC) != 0xFFFFFFFFUL) {                        memset(&pci,0,sizeof(pci));                        pci.dwSize = sizeof(pci);                        pci.mech1 = 1;                        pci.slot = slot;                        lp = (ulong*)&(pci.VendorID);                        for (i = 0; i < NUM_PCI_REG; i++, lp++) {                            slot.p.Register = i;                            PM_outpd(0xCF8,slot.i);                            *lp = PM_inpd(0xCFC);                            }                        if (!CheckDuplicate(&pci,&prev)) {                            if (info)                                COPY_STRUCTURE(&info[numFound],&pci);                            ++numFound;                            }                        prev = pci;                        }                    }                }            }        /* Disable PCI config cycle on exit */        PM_outpd(0xCF8,0);        return numFound;        }    PM_outpd(0xCF8,tmp);    /* No hardware access mechanism 1 found */    return 0;}/****************************************************************************PARAMETERS:info        - Array of PCIDeviceInfo structures to fill inmaxDevices  - Maximum number of of devices to enumerate into arrayRETURNS:Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.REMARKS:Function to enumerate all available devices on the PCI bus into an arrayof configuration information blocks.****************************************************************************/static int PCI_enumerateMech2(    PCIDeviceInfo info[]){    int             bus,device,function,i,numFound = 0;    ushort          deviceIO;    ulong           *lp;    PCIslot         slot = {{0,0,0,0,0,0,1}};    PCIDeviceInfo   pci,prev = {0};    /* Try PCI access mechanism 2 */    PM_outpb(0xCFB,0x00);    PM_outpb(0xCF8,0x00);    PM_outpb(0xCFA,0x00);    if (PM_inpb(0xCF8) == 0x00 && PM_inpb(0xCFB) == 0x00) {        /* PCI access mechanism 2 - the older mechanism for legacy busses */        for (bus = 0; bus < 2; bus++) {            slot.p.Bus = bus;            PM_outpb(0xCFA,(uchar)bus);            for (device = 0; device < 16; device++) {                slot.p.Device = device;                deviceIO = 0xC000 + (device << 8);                for (function = 0; function < 8; function++) {                    slot.p.Function = function;                    slot.p.Register = 0;                    PM_outpb(0xCF8,(uchar)((function << 1) | 0x10));                    if (PM_inpd(deviceIO) != 0xFFFFFFFFUL) {                        memset(&pci,0,sizeof(pci));                        pci.dwSize = sizeof(pci);                        pci.mech1 = 0;                        pci.slot = slot;                        lp = (ulong*)&(pci.VendorID);                        for (i = 0; i < NUM_PCI_REG; i++, lp++) {                            slot.p.Register = i;                            *lp = PM_inpd(deviceIO + (i << 2));                            }                        if (!CheckDuplicate(&pci,&prev)) {                            if (info)                                COPY_STRUCTURE(&info[numFound],&pci);                            ++numFound;                            }                        prev = pci;                        }                    }                }            }        /* Disable PCI config cycle on exit */        PM_outpb(0xCF8,0);        return numFound;        }    /* No hardware access mechanism 2 found */    return 0;}/****************************************************************************REMARKS:This functions reads a configuration dword via the PCI BIOS.****************************************************************************/static ulong PCIBIOS_readDWORD(    int index,    ulong slot){    return (ulong)_PCIBIOS_service(READ_CONFIG_DWORD,slot >> 8,index,0,PCIEntry);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -