📄 pcicommon.c
字号:
/***************************************** Copyright (c) 2003-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the EM86XX boot loader *//* * pcicommon.c * * by Ho Lee 02/05/2003 */#include "config.h"#include "uart.h"#include "util.h"#include "hardware.h"#include "io.h"#include "irqs.h"#include "pcicommon.h"//// global variables//struct my_pci_op *g_pciop = NULL;//// Initialization//int pci_init(struct my_pci_op *pop, int verbose){ if (pop) { g_pciop = pop; g_pciop->init(verbose); return 0; } else return 1;}//// Basic//int pci_info(void){ if (g_pciop && g_pciop->info) return g_pciop->info(); return 1;}unsigned int pci_select(int idsel){ if (g_pciop && g_pciop->select) return g_pciop->select(idsel); return 0;}//// Bus address translation//unsigned int virt_to_bus(unsigned int virt){ return (g_pciop && g_pciop->virt_to_bus) ? g_pciop->virt_to_bus(virt) : virt;}unsigned int bus_to_virt(unsigned int bus){ return (g_pciop && g_pciop->bus_to_virt) ? g_pciop->bus_to_virt(bus) : bus;}//// primitive PCI configuration I/O//#define PCI_READ_CONFIG_X(x, type, name) \ int pci_read_config_##name(unsigned int addr, unsigned type *data) \ { \ return (g_pciop && g_pciop->read_config_##name) ? g_pciop->read_config_##name(addr, data) : 1; \ } #define PCI_WRITE_CONFIG_X(x, type, name) \ int pci_write_config_##name(unsigned int addr, unsigned int data) \ { \ return (g_pciop && g_pciop->write_config_##name) ? g_pciop->write_config_##name(addr, data) : 1; \ }PCI_READ_CONFIG_X(b, char, byte)PCI_READ_CONFIG_X(w, short, word)PCI_READ_CONFIG_X(l, int, dword)PCI_WRITE_CONFIG_X(b, char, byte)PCI_WRITE_CONFIG_X(w, short, word)PCI_WRITE_CONFIG_X(l, int, dword)//// primitive PCI I/O Access// #define PCI_IN_X(x, type, name) \ unsigned type pci_in##x(unsigned int addr) \ { \ return (g_pciop && g_pciop->in_##name) ? g_pciop->in_##name(addr) : (unsigned type) -1; \ } #define PCI_OUT_X(x, type, name) \ void pci_out##x(unsigned int data, unsigned int addr) \ { \ if (g_pciop && g_pciop->out_##name) \ g_pciop->out_##name(data, addr); \ }PCI_IN_X(b, char, byte)PCI_IN_X(w, short, word)PCI_IN_X(l, int, dword)PCI_OUT_X(b, char, byte)PCI_OUT_X(w, short, word)PCI_OUT_X(l, int, dword)//// primitive PCI Memory Access// #define PCI_READ_X(x, type, name) \ unsigned type pci_read##x(unsigned int addr) \ { \ return (g_pciop && g_pciop->read_##name) ? g_pciop->read_##name(addr) : (unsigned type) -1; \ } #define PCI_WRITE_X(x, type, name) \ void pci_write##x(unsigned int data, unsigned int addr) \ { \ if (g_pciop && g_pciop->write_##name) \ g_pciop->write_##name(data, addr); \ }PCI_READ_X(b, char, byte)PCI_READ_X(w, short, word)PCI_READ_X(l, int, dword)PCI_WRITE_X(b, char, byte)PCI_WRITE_X(w, short, word)PCI_WRITE_X(l, int, dword)//// PCI bus scan & dump// // restriction : This code does not support multi-function device//// scan every devices on the bus, and display the information of each deviceint pci_scan(void){ int i; if (g_pciop == NULL) return -1; // Agent detection for (i = g_pciop->idsel_start; i <= g_pciop->idsel_end; ++i) { if (pci_select(i) != 0) pci_dump_idsel(i, 0); } return 0;}struct my_pci_dev *pci_get_info(struct my_pci_dev *pdev, int readonly){ int i; unsigned char hdr_type, latency, cacheline, irqpin, irqline; unsigned short cmd, status; unsigned int vendor_id, device_id, class, rev, romaddr, baseaddr, buses; if (g_pciop == NULL) return NULL; g_pciop->read_config_byte(PCI_HEADER_TYPE, &hdr_type); g_pciop->read_config_dword(PCI_VENDOR_ID, &vendor_id); if (vendor_id == 0xffffffff || vendor_id == 0x00000000 || vendor_id == 0x0000ffff) return NULL; pdev->is_normal = ((hdr_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) ? 1 : 0; pdev->is_bridge = ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) ? 1 : 0; pdev->is_cardbus = ((hdr_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS) ? 1 : 0; device_id = (vendor_id >> 16) & 0xffff; vendor_id &= 0xffff; g_pciop->read_config_word(PCI_COMMAND, &cmd); g_pciop->read_config_word(PCI_STATUS, &status); g_pciop->read_config_dword(PCI_CLASS_REVISION, &class); rev = class & 0xff; class >>= 8; g_pciop->read_config_byte(PCI_LATENCY_TIMER, &latency); g_pciop->read_config_byte(PCI_CACHE_LINE_SIZE, &cacheline); g_pciop->read_config_byte(PCI_INTERRUPT_PIN, &irqpin); g_pciop->read_config_byte(PCI_INTERRUPT_LINE, &irqline); g_pciop->read_config_dword(PCI_ROM_ADDRESS, &romaddr); g_pciop->read_config_dword(PCI_PRIMARY_BUS, &buses); pdev->vendor_id = vendor_id; pdev->device_id = device_id; pdev->cmd = cmd; pdev->status = status; pdev->class = class; pdev->progIF = class & 0xff; pdev->subclass = (class >> 8) & 0xff; pdev->classcode = (class >> 16) & 0xff; pdev->rev = rev; pdev->hdr_type = hdr_type; pdev->latency = latency; pdev->cacheline = cacheline; pdev->irqpin = irqpin; pdev->irqline = irqline; pdev->romaddr = romaddr; pdev->buses = buses; pdev->primary_bus = buses & 0xff; pdev->secondary_bus = (buses >> 8) & 0xff; pdev->subordinate_bus = (buses >> 16) & 0xff; for (i = 0; i < 6; ++i) { g_pciop->read_config_dword(PCI_BASE_ADDRESS_0 + 4 * i, &baseaddr); pdev->resource[i].isio = -1; pdev->resource[i].start = pdev->base_addr[i] = baseaddr; pdev->resource[i].size = 0; if (baseaddr != 0) { pdev->resource[i].isio = baseaddr & PCI_BASE_ADDRESS_SPACE_IO; pdev->resource[i].start = baseaddr & (pdev->resource[i].isio ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK); } if (!readonly) { g_pciop->write_config_dword(PCI_BASE_ADDRESS_0 + 4 * i, 0xffffffff); g_pciop->read_config_dword(PCI_BASE_ADDRESS_0 + 4 * i, &baseaddr); if (baseaddr != 0) { baseaddr &= (pdev->resource[i].isio ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK); pdev->resource[i].size = ~baseaddr + 1; } g_pciop->write_config_dword(PCI_BASE_ADDRESS_0 + 4 * i, pdev->base_addr[i]); } } if ((pdev->class >> 8) != PCI_CLASS_BRIDGE_PCI) pdev->is_bridge = 0; return pdev;}static char *s_strType[] = { "Normal", "Brdige", "Cardbus" };static char *s_strCmd[] = { "IO Enable", "Memory Enable", "Master", "Special", "Invalidate", "VGA Palette", "Parity", "Wait", "SERR", "Fast Back" };static char *s_strStatus[] = { "", "", "", "", "CAP List", "66MHz", "UDF", "Fast Back" };static char *s_strClassCode[] = { "Reserved", "Disk", "Network", "Display", "Multimedia", "Memory", "Bridge", "Communication", "System Peripheral", "Input", "Docking station", "CPU", "Serial Bus" };static char *s_strIoType[] = { "Memory", "I/O" };static char *s_strMemType[] = { "32 bit", "below 1M", "64 bit" };static char *s_strPrefetch[] = { "Nonprefetchable", "Prefetchable" };#define INFOSTR(strarray, idx) ((idx < (sizeof strarray / sizeof strarray[0])) ? strarray[idx] : "Unknown")#define INFOSTRBIT(strarray, data, max) \ for (i = 0, count = 0; data > 0 && (max <= 0 || i < max); ++i, data >>= 1) { \ if (data & 1) { \ if (count > 0) \ uart_printf(", "); \ uart_printf("%s", INFOSTR(strarray, i)); \ ++count; \ } \ } void pci_dump(struct my_pci_dev *pdev){ int i, count, basecount; unsigned int iotype, memtype, prefetch; if (g_pciop == NULL) return; uart_printf("PCI ID select %d:\n", pdev->idsel); // Vendor ID & Device ID uart_printf(" Vendor ID = %04x, Device ID = %04x, Type = %02x (%s)\n", pdev->vendor_id, pdev->device_id, pdev->hdr_type, INFOSTR(s_strType, pdev->hdr_type)); // Command & Status uart_printf(" Command = %04x (", pdev->cmd); INFOSTRBIT(s_strCmd, pdev->cmd, 0); uart_printf(")\n"); uart_printf(" Status = %04x (", pdev->status); INFOSTRBIT(s_strStatus, pdev->status, 8); uart_printf(")\n"); // Class uart_printf(" Class = %06x (", pdev->class); uart_printf("Class = %s)\n", INFOSTR(s_strClassCode, pdev->classcode)); // Revision, Latency Timer, Cache Line Size uart_printf(" Revision = %02x, Latency Timer = %02x, Cache Line Size = %02x\n", pdev->rev, pdev->latency, pdev->cacheline); // Interrupt if (pdev->is_normal) uart_printf(" Interrupt Line = %02x, Interrupt Pin = %02x\n", pdev->irqline, pdev->irqpin); // Base address switch (pdev->hdr_type) { case PCI_HEADER_TYPE_NORMAL : basecount = 6; break; case PCI_HEADER_TYPE_BRIDGE : basecount = 2; break; case PCI_HEADER_TYPE_CARDBUS : basecount = 1; break; default : basecount = 6; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -