📄 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 + -