📄 pciiomaplib.c
字号:
size = (~base + 1); /* Allocate some (aligned) memory space */ base = pciAllocateMemSpace (size); /* * Let the device see it, but don't enable accesses. * This is because, according to the specification, * the device may share an address decoder between * the Expansion ROM base and other base address * registers. In other words, any device driver wishing * to access the ROM must set the enable bit (bit 0) before * proceeding and clear it afterwards. */ pciConfigOutLong (bus, slot, func, PCI_ROM_BAR, base); /* ROM gets added to PCI memory, so allow accesses */ barFlag |= PCI_CMD_MEM_ENABLE; } /* Enable PCI IO and memory accesses as found by scan, with MASTER */ barFlag |= PCI_CMD_MASTER_ENABLE; pciConfigOutWord (bus, slot, func, PCI_CFG_COMMAND, barFlag); pciConfigOutByte (bus, slot, func, PCI_CFG_LATENCY_TIMER, 0xFF); }/********************************************************************************* pciMakeConfigAddress - make a Daconfiguration address()** This routine will generate a platform dependent configuration address.** To generate the appropriate PCI configuration cycles in the PCI* configuration address space, you present the V3 with the following pattern* (which is very nearly a type 1 (except that the lower two bits are 00 and* not 01). In order for this mapping to work you need to set up one of* the local to PCI aperatures to 16Mbytes in length translating to* PCI configuration space starting at 0x0000.0000.** PCI configuration cycles look like this:** Type 0:** 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1* 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+** 31:11 Device select bit.* 10:8 Function number* 7:2 Register number** Type 1:** 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1* 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+** 31:24 reserved* 23:16 bus number (8 bits = 128 possible buses)* 15:11 Device number (5 bits)* 10:8 function number* 7:2 register number** RETURNS: configuration address on the PCI bus*/UINT32 pciMakeConfigAddress ( int bus, /* bus number */ int slot, /* slot number */ int function, /* function number */ int offset /* offset into the configuration space */ ) { UINT32 address, devicebit; UINT16 mapaddress; if (bus == 0) { /* * local bus segment so need a type 0 config cycle * build the PCI configuration "address" with one-hot in A31-A11 */ address = CPU_PCI_CNFG_ADRS; address |= ((function & 0x07) << 8); address |= offset & 0xFF; /* 101=>config cycle, 0=>A1=A0=0 */ mapaddress = 0x000A; devicebit = (1 << (slot + 11)); if ((devicebit & 0xFF000000) != 0) { /* high order bits are handled by the MAP register */ mapaddress |= (devicebit >> 16); } else { /* low order bits handled directly in the address */ address |= devicebit; } } else { /* -- bus !=0 -- * * not the local bus segment so need a type 1 config cycle * A31-A24 are don't care (so clear to 0) */ mapaddress = 0x000B; /* 101=>config cycle, 1=>A1&A0 from PCI_CFG */ address = CPU_PCI_CNFG_ADRS; address |= ((bus & 0xFF) << 16); /* bits 23..16 = bus number */ address |= ((slot & 0x1F) << 11); /* bits 15..11 = slot number */ address |= ((function & 0x07) << 8); /* bits 10..8 = function num */ address |= offset & 0xFF; /* bits 7..0 = register num */ } V3_WRITE16 (V3_LB_MAP1, mapaddress); return address; }/********************************************************************************* pciConfigInByte - read a byte from PCI config register.** This routine reads a byte from the given PCI config register.*** RETURNS: the data value read.*/STATUS pciConfigInByte ( int bus, /* bus number */ int slot, /* slot number */ int function, /* function number */ int offset, /* offset into the configuration space */ char *data /* data read from the offset */ ) { char *pAddress; int key; /* mutual exclusion start */ key = intLock (); /* open the (closed) configuration window from local bus memory */ v3OpenConfigWindow(); /* generate the address of correct configuration space */ pAddress = (char *)pciMakeConfigAddress(bus, slot, function, offset); /* now that we have valid params, go read the config space data */ *data = *pAddress; /* close the window */ v3CloseConfigWindow(); /* end of mutual exclusion */ intUnlock (key); return (OK); }/********************************************************************************* pciConfigInWord - read a word from PCI config register.** This routine reads a word from the given PCI config register.** RETURNS: the data value read.*/STATUS pciConfigInWord ( int bus, /* bus number */ int slot, /* slot number */ int function, /* function number */ int offset, /* offset into the configuration space */ short *data /* data read from the offset */ ) { short * pAddress; int key; /* mutual exclusion start */ key = intLock (); /* open the (closed) configuration window from local bus memory */ v3OpenConfigWindow(); /* generate the address of correct configuration space */ pAddress = (short *)pciMakeConfigAddress(bus, slot, function, offset); /* now that we have valid params, go read the config space data */ *data = *pAddress; /* close the window */ v3CloseConfigWindow(); /* end of mutual exclusion */ intUnlock (key); return (OK); }/********************************************************************************* pciConfigInLong - read a long from PCI config register.** This routine reads a long from the given PCI config register.** RETURNS: the data value read.*/STATUS pciConfigInLong ( int bus, /* bus number */ int slot, /* slot number */ int function, /* function number */ int offset, /* offset into the configuration space */ int *data /* data read from the offset */ ) { int * pAddress; int key; /* mutual exclusion start */ key = intLock(); /* open the (closed) configuration window from local bus memory */ v3OpenConfigWindow(); /* generate the address of correct configuration space */ pAddress = (int *)pciMakeConfigAddress(bus, slot, function, offset); /* now that we have valid params, go read the config space data */ *data = *pAddress; /* close the window */ v3CloseConfigWindow(); /* mutual exclusion stop */ intUnlock(key); return (OK); }/********************************************************************************* pciConfigOutByte - write a byte to configuration space** This routine writes a byte value to the given PCI config register.** RETURNS: N/A*/STATUS pciConfigOutByte ( int bus, /* bus number */ int slot, /* slot number */ int function, /* function number */ int offset, /* offset into the configuration space */ char data /* data written to the offset */ ) { char *pAddress; int key; /* mutual exclusion start */ key = intLock(); /* open the (closed) configuration window from local bus memory */ v3OpenConfigWindow(); if (bus != 0) { /* workaround for problem with type 0 write */ pAddress = (UINT8 *)CPU_PCI_CNFG_ADRS; *pAddress = data; } else { /* generate the address of correct configuration space */ pAddress = (char *)pciMakeConfigAddress(bus, slot, function, offset); /* now that we have valid params, go write the config space data */ *pAddress = data; } /* close the window */ v3CloseConfigWindow(); /* mutual exclusion stop */ intUnlock(key); return OK; }/********************************************************************************* pciConfigOutWord - write a word to configuration space** This routine writes a word value to the given PCI config register.** RETURNS: N/A*/STATUS pciConfigOutWord ( int bus, /* bus number */ int slot, /* slot number */ int function, /* function number */ int offset, /* offset into the configuration space */ short data /* data written to the offset */ ) { short * pAddress; int key; /* mutual exclusion start */ key = intLock(); /* open the (closed) configuration window from local bus memory */ v3OpenConfigWindow(); if (bus != 0) { /* workaround for problem with type 0 write */ pAddress = (short *)CPU_PCI_CNFG_ADRS; *pAddress = data; } else { /* generate the address of correct configuration space */ pAddress = (short *)pciMakeConfigAddress(bus, slot, function, offset); /* now that we have valid params, go write the config space data */ *pAddress = data; } /* close the window */ v3CloseConfigWindow(); /* mutual exclusion stop */ intUnlock(key); return OK; }/********************************************************************************* pciConfigOutLong - write a long to configuration space** This routine writes a long value to the given PCI config register.** RETURNS: N/A*/STATUS pciConfigOutLong ( int bus, /* bus number */ int slot, /* slot number */ int function, /* function number */ int offset, /* offset into the configuration space */ int data /* data written to the offset */ ) { int * pAddress; int key; /* mutual exclusion start */ key = intLock(); /* open the (closed) configuration window from local bus memory */ v3OpenConfigWindow(); if (bus != 0) { /* workaround for problem with type 0 write */ pAddress = (int *)CPU_PCI_CNFG_ADRS; *pAddress = data; } else { /* generate the address of correct configuration space */ pAddress = (int *)pciMakeConfigAddress(bus, slot, function, offset); /* now that we have valid params, go write the config space data */ *pAddress = data; } /* close the window */ v3CloseConfigWindow(); /* mutual exclusion stop */ intUnlock(key); return OK; }/********************************************************************************* pciIomapLibInit - initialize the configuration access-method and addresses** This routine initializes the configuration access-method and addresses.** Configuration mechanism one utilizes two 32-bit IO ports located at addresses* 0x0cf8 and 0x0cfc. These two ports are:* - 32-bit configuration address port, at 0x0cf8* - 32-bit configuration data port, at 0x0cfc* Accessing a PCI function's configuration port is two step process.* - Write the bus number, physical device number, function number and* register number to the configuration address port.* - Perform an IO read from or an write to the configuration data port.** Configuration mechanism two uses following two single-byte IO ports.* - Configuration space enable, or CSE, register, at 0x0cf8* - Forward register, at 0x0cfa* To generate a PCI configuration transaction, the following actions are* performed.* - Write the target bus number into the forward register.* - Write a one byte value to the CSE register at 0x0cf8. The bit* pattern written to this register has three effects: disables the* generation of special cycles; enables the generation of configuration* transactions; specifies the target PCI functional device.* - Perform a one, two or four byte IO read or write transaction within* the IO range 0xc000 through 0xcfff.** Configuration mechanism three is for non-PC/PowerPC environments* where an area of address space produces PCI configuration* transactions. No support for special cycles is included.** RETURNS: OK or ERROR if a mechanism is not 1, 2 or 3.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -