📄 btpci.c
字号:
/****************************************************************************//* Copyright 2000 Compaq Computer Corporation. *//* . *//* Copying or modifying this code for any purpose is permitted, *//* provided that this copyright notice is preserved in its entirety *//* in all copies or modifications. COMPAQ COMPUTER CORPORATION *//* MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, AS TO THE USEFULNESS *//* OR CORRECTNESS OF THIS CODE OR ITS FITNESS FOR ANY PARTICULAR *//* PURPOSE. *//****************************************************************************//* * btpci.c - Firmware configuration of PCI for Compaq Personal Server */#include "bootldr.h"#include "btpci.h"/* some typedefs required by pcireg.h */typedef dword u_int32_t;typedef word u_int16_t;typedef byte u_int8_t;#include "pcireg.h"#define readInt8(a,o) (*(volatile byte*)(((char*)(a))+o))#define readInt16(a,o) (*(volatile word*)(((char*)(a))+o))#define readInt32(a,o) (*(volatile dword*)(((char*)(a))+o))#define writeInt8(a,o,v) (*(volatile byte*)(((char*)(a))+o) = (v))#define writeInt16(a,o,v) (*(volatile word*)(((char*)(a))+o) = (v))#define writeInt32(a,o,v) (*(volatile dword*)(((char*)(a))+o) = (v))static void bset8(volatile char *addr, u_int32_t offset, u_int8_t mask){ u_int32_t temp; temp = readInt8(addr, offset); temp |= mask; writeInt8(addr, offset, temp);}static void bclr8(volatile char *addr, u_int32_t offset, u_int8_t mask){ u_int32_t temp; temp = readInt8(addr, offset); temp &= ~mask; writeInt8(addr, offset, temp);}static void bset16(volatile char *addr, u_int32_t offset, u_int16_t mask){ u_int32_t temp; temp = readInt16(addr, offset); temp |= mask; writeInt16(addr, offset, temp);}static void bclr16(volatile char *addr, u_int32_t offset, u_int16_t mask){ u_int32_t temp; temp = readInt16(addr, offset); temp &= ~mask; writeInt16(addr, offset, temp);}static void bset32(volatile char *addr, u_int32_t offset, u_int32_t mask){ u_int32_t temp; temp = readInt32(addr, offset); temp |= mask; writeInt32(addr, offset, temp);}static void bclr32(volatile char *addr, u_int32_t offset, u_int32_t mask){ u_int32_t temp; temp = readInt32(addr, offset); temp &= ~mask; writeInt32(addr, offset, temp);}#define makePCIConfigurationAddress(dev_, fcn_, offset_) ((char*)(0x7b000000L | (3<<22) | ((dev_)<<11) | ((fcn_)<<8) | (offset_)))#if 0#define STANDARD_COMMAND (PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE|PCI_COMMAND_INVALIDATE_ENABLE|PCI_COMMAND_PARITY_ENABLE|PCI_COMMAND_SERR_ENABLE|PCI_COMMAND_BACKTOBACK_ENABLE)#else#define STANDARD_COMMAND (PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE|PCI_COMMAND_INVALIDATE_ENABLE|PCI_COMMAND_PARITY_ENABLE|PCI_COMMAND_SERR_ENABLE|PCI_COMMAND_BACKTOBACK_ENABLE)#endif#define USB_DELAY 1000000/* * Command and status register. */struct PciConfigurationValues { const char *name; int pciDevice; /* which PCI device this info is for */ int pciFunction; /* which PCI function in a multifunction device this info is for */ dword interruptPin; /* which interrupt pin on the chip to use */ dword interruptLine; /* which interrupt line on 21285 it's tied to -- 0x40 + 21285.IRQEnable.bitnum * -- the 0x40 is so that we can use netbsd interrupt steering unmodified. */ dword BAR0; /* base address register 0 */ dword BAR1; /* base address register 1 */ dword commandEnables; /* these bits get OR'd into the command CSR of the device */ void (*handleQuirks)(struct PciConfigurationValues *); };static void handleCirrusCardbusBridgeQuirks(struct PciConfigurationValues *);static void handleOptiUSBControllerQuirks(struct PciConfigurationValues *);static void handlePCNetQuirks(struct PciConfigurationValues *);#define CARDBUS_DEVICE_NUMBER 0#define OHCI_DEVICE_NUMBER 1#define PCNET_DEVICE_NUMBER 2struct PciConfigurationValues pciConfigurationValues [] = { { "Cardbus Socket1", CARDBUS_DEVICE_NUMBER, 0, PCI_INTERRUPT_PIN_A, 0x40 + IRQ_INTA_BITNUM, CARDBUS_SOCKET1_MEMORY_BASE, 0, STANDARD_COMMAND, handleCirrusCardbusBridgeQuirks }, { "Cardbus Socket2", CARDBUS_DEVICE_NUMBER, 1, PCI_INTERRUPT_PIN_B, 0x40 + IRQ_INTB_BITNUM, CARDBUS_SOCKET2_MEMORY_BASE, 0, STANDARD_COMMAND, handleCirrusCardbusBridgeQuirks }, { "USB Controller", OHCI_DEVICE_NUMBER, 0, PCI_INTERRUPT_PIN_A, 0x40 + IRQ_INTC_BITNUM, /* PCI_INTERRUPT_PIN_A on OPTi is wired to 21285's PCI_INTERRUPT_PIN_C */ USB_MEMORY_BASE, /* first block of PCI memory space */ 0, STANDARD_COMMAND, handleOptiUSBControllerQuirks }, { "Ethernet Controller", PCNET_DEVICE_NUMBER, 0, PCI_INTERRUPT_PIN_A, 0x40 + IRQ_INTD_BITNUM, /* PCI_INTERRUPT_PIN_A on Ethernet chip is wired to 21285's PCI_INTERRUPT_PIN_D */ ETHERNET_IO_BASE, 0, /* was ETHERNET_MEMORY_BASE, for memory mapped IO, but seems to be hardwired in driver to expect an IO and not a Memory address */ STANDARD_COMMAND, handlePCNetQuirks }, { NULL, 0, 0, 0, 0, 0, 0, 0, NULL }};/* * ad[1:0] * ad[7:2] configuration doubleword * ad[10:8] fcn number * ad[15:11] device * ad[23:16] bus number */void formatCardbusPresentState(long reg){ }typedef struct RegDescr { short size; short offset; const char *name; void (*format)(long value);} RegDescr;RegDescr pciConfigRegDescrs[] = { { 4, 0x00, "ID", NULL }, { 4, 0x04, "StatusCommand", NULL }, { 4, 0x08, "ClassCode:Revision", NULL }, { 4, 0x0c, "BIST:Header:Latency:CLS", NULL }, { 4, 0x10, "MemBAR", NULL }, { 4, 0x14, "CardbusStatus", NULL }, { 4, 0x18, "=LatTimr:SubBusNum:CardbusNum:PCINum", NULL }, { 4, 0x1c, "MemBase0", NULL }, { 4, 0x20, "MemLimit0", NULL }, { 4, 0x24, "MemBase1", NULL }, { 4, 0x28, "MemLimit1", NULL }, { 4, 0x2c, "IOBase0", NULL }, { 4, 0x30, "IOLimit0", NULL }, { 4, 0x34, "IOBase1", NULL }, { 4, 0x38, "IOLimit1", NULL }, { 4, 0x3c, "BridgeCtl:IntPin:IntLine", NULL }, { 4, 0x40, "SubsystemID", NULL }, { 4, 0x44, "LegacyBAR", NULL }, { 4, 0x48, "DMASlaveReg", NULL }, { 4, 0x4c, "SocketNumber", NULL }, { 4, 0x80, "PowerManagement", NULL }, { 4, 0x90, "DMASlaveConfig", NULL }, { 4, 0x94, "SocketNumber", NULL }, { 4, 0x98, "MiscConfig1", NULL }, { 0, 0, "", NULL } };RegDescr cardbusRegDescrs[] = { { 4, 0x0, "StatusEvent", NULL }, { 4, 0x4, "StatusMask", NULL }, { 4, 0x8, "PresentState", formatCardbusPresentState }, { 4, 0xc, "EventForce", NULL }, { 4, 0x10, "Control", NULL }, { 0, 0, ", NULL" }};RegDescr excaRegDescrs[] = { { 1, 0x00, "0x800 ChipRev", NULL }, { 1, 0x01, "=>InterfaceStatus", NULL }, { 1, 0x02, "=>PowerCtl", NULL }, { 1, 0x03, "IntGenCtl", NULL }, { 1, 0x04, "CardStatusChange", NULL }, { 1, 0x05, "MgmtIntCfg", NULL }, { 1, 0x06, "MappingEnable", NULL }, { 1, 0x07, "IOWindowCtl", NULL }, { 1, 0x16, "=>MiscCtl1", NULL }, { 1, 0x1e, "MiscCtl2", NULL }, { 1, 0x125, "=>MiscCtl3(0xf)", NULL }, { 1, 0x12f, "MiscCtl4", NULL }, { 1, 0x130, "MiscCtl5", NULL }, { 1, 0x131, "MiscCtl6", NULL }, { 1, 0x126, "=>SMB Socket Power Control Addr", NULL }, { 1, 0x17, "FIFO Ctl", NULL }, { 1, 0x1f, "ChipInfo", NULL }, { 1, 0x26, "ATA Ctl", NULL }, { 1, 0x27, "Scratch", NULL }, { 2, 0x10, "GenMap0 StartAddr", NULL }, { 2, 0x12, "GenMap0 EndAddr", NULL }, { 1, 0x40, "GenMap0 UpperAddr", NULL }, { 2, 0x14, "GenMap0 OffsetAddr", NULL }, { 2, 0x18, "GenMap1 StartAddr", NULL }, { 2, 0x1a, "GenMap1 EndAddr", NULL }, { 1, 0x41, "GenMap1 UpperAddr", NULL }, { 2, 0x1c, "GenMap1 OffsetAddr", NULL }, { 2, 0x20, "GenMap2 StartAddr", NULL }, { 2, 0x22, "GenMap2 EndAddr", NULL }, { 1, 0x42, "GenMap2 UpperAddr", NULL }, { 2, 0x24, "GenMap2 OffsetAddr", NULL }, { 2, 0x20, "GenMap3 StartAddr", NULL }, { 2, 0x22, "GenMap3 EndAddr", NULL }, { 1, 0x43, "GenMap3 UpperAddr", NULL }, { 2, 0x24, "GenMap3 OffsetAddr", NULL }, { 2, 0x30, "GenMap4 StartAddr", NULL }, { 2, 0x32, "GenMap4 EndAddr", NULL }, { 1, 0x44, "GenMap4 UpperAddr", NULL }, { 2, 0x34, "GenMap4 OffsetAddr", NULL }, { 2, 0x08, "GenMap5 StartAddr", NULL }, { 2, 0x0a, "GenMap5 EndAddr", NULL }, { 1, 0x45, "GenMap5 UpperAddr", NULL }, { 2, 0x36, "GenMap5 OffsetAddr", NULL }, { 2, 0x0c, "GenMap6 StartAddr", NULL }, { 2, 0x0e, "GenMap6 EndAddr", NULL }, { 1, 0x46, "GenMap6 UpperAddr", NULL }, { 2, 0x38, "GenMap6 OffsetAddr", NULL }, { 1, 0x3a, "SetupTiming0", NULL }, { 1, 0x3b, "CommandTiming0", NULL }, { 1, 0x3c, "RecoveryTiming0", NULL }, { 1, 0x3d, "SetupTiming1", NULL }, { 1, 0x3e, "CommandTiming1", NULL }, { 1, 0x3f, "RecoveryTiming1", NULL }, { 1, 0x103, "ExtensionCtl1", NULL }, { 1, 0x10a, "ExternalData", NULL }, { 1, 0x10b, "ExtensionCtl2", NULL }, { 1, 0x122, "PCI Space Ctl", NULL }, { 1, 0x123, "PC Card Space Ctl", NULL }, { 1, 0x124, "WindowTypeSelect", NULL }, { 1, 0x127, "GenMap0 ExtraCtl", NULL }, { 1, 0x128, "GenMap1 ExtraCtl", NULL }, { 1, 0x129, "GenMap2 ExtraCtl", NULL }, { 1, 0x12a, "GenMap3 ExtraCtl", NULL }, { 1, 0x12b, "GenMap4 ExtraCtl", NULL }, { 1, 0x12c, "GenMap5 ExtraCtl", NULL }, { 1, 0x12d, "GenMap6 ExtraCtl", NULL }, { 1, 0x12e, "ExtCardStatusChange", NULL }, { 1, 0x134, "MaskRevision", NULL }, { 1, 0x135, "ProdID", NULL }, { 2, 0x136, "DevCapA", NULL }, { 4, 0x138, "=>DevImpl", NULL }, { 0, 0, ", NULL" }};static void showRegs(const char *regClass, volatile dword *regs, RegDescr *regDescrs){ long lregs = (long)regs; int i = 0; RegDescr *regDescr = ®Descrs[i]; while (regDescr->size != 0) { int offset = regDescr->offset; int reg = 0; putstr(regClass); putstr("\t"); putHexInt32(lregs+offset); putstr(": "); switch (regDescr->size) { case 1: reg = readInt8(regs, offset); putHexInt8(reg); break; case 2: reg = readInt16(regs, offset); putHexInt16(reg); break; case 4: reg = readInt32(regs, offset); putHexInt32(reg); break; } putstr("\t"); putstr(regDescr->name); if (regDescr->format != NULL) { putstr("\t"); (regDescr->format)(reg); } putstr("\r\n"); i++; regDescr = ®Descrs[i]; }}enum { CCB_CONFIGURE, CCB_REGS, CCB_RESET_CARD, CCB_ENABLE_CARD, CCB_DISABLE_CARD, CCB_CONFIGURATION_READ, CCB_CONFIGURATION_WRITE, CCB_POWER, CCB_NUM};static struct { char *name; int tag;} cardbusSubcommands[] = { { "configure", CCB_CONFIGURE }, { "config", CCB_CONFIGURE }, { "regs", CCB_REGS }, { "reset", CCB_RESET_CARD }, { "enable", CCB_ENABLE_CARD }, { "disable", CCB_DISABLE_CARD }, { "read", CCB_CONFIGURATION_READ }, { "write", CCB_CONFIGURATION_WRITE }, { "power", CCB_POWER }, { NULL, CCB_NUM },};#if 0void testCirrusCardbusBridge(char *args){ struct PciConfigurationValues *pcv = &pciConfigurationValues[0]; volatile char *socketConfig = (volatile char *)makePCIConfigurationAddress(pcv->pciDevice, pcv->pciFunction, 0); long socketOperationPCIAddr = (long)readInt32(socketConfig,PCI_MAPREG_START); volatile byte *socketOperationPhysAddr = (volatile byte *)(((long)socketOperationPCIAddr)|0x80000000L); int socketNumber = readInt32(socketConfig, 0x4c); long cardPCIAddr = readInt32(socketConfig, 0x1c); long cardPCIEndAddr = readInt32(socketConfig, 0x20); long cardOffset = 0; char *cardPhysAddr = (char *)(cardPCIAddr | 0x80000000L); int i; for (i = 0; i < CCB_NUM; i++) { if (strncmp(args, cardbusSubcommands[i].name, strlen( cardbusSubcommands[i].name)) == 0) { break; } } putstr("args="); putstr(args); putstr("\r\n"); putstr("cmd="); putstr(cardbusSubcommands[i].name); putstr("\r\n"); putstr("tag="); putHexInt8(cardbusSubcommands[i].tag); putstr("\r\n"); if (cardbusSubcommands[i].tag == CCB_NUM) return; switch (cardbusSubcommands[i].tag) { case CCB_CONFIGURE: { /* disable write posting */ bclr8(socketConfig, 0x3f, 4); /* set up card configuration memory space */ /* start addr */ writeInt8(socketOperationPhysAddr, 0x810, ((cardPCIAddr >> 12) & 0xff)); writeInt8(socketOperationPhysAddr, 0x811, ((cardPCIAddr >> 20) & 0x0f) | 0x80); writeInt8(socketOperationPhysAddr, 0x840, ((cardPCIAddr >> 24) & 0xff)); /* end addr */ writeInt8(socketOperationPhysAddr, 0x812, ((cardPCIEndAddr >> 12) & 0xff)); writeInt8(socketOperationPhysAddr, 0x813, ((cardPCIEndAddr >> 20) & 0x0f) | 0x0); /* cardmem offset */ writeInt8(socketOperationPhysAddr, 0x814, ((cardOffset >> 12) & 0xff)); writeInt8(socketOperationPhysAddr, 0x815, ((cardOffset >> 20) & 0x3f) | 0x40); writeInt8(socketOperationPhysAddr, 0x817, 0x70); /* enable window */ bset8(socketOperationPhysAddr, 0x806, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -