📄 pci_serv.c
字号:
{
printf("Error reading Region 0 Base\n");
return;
}
printf("PCI Region 0 Base = 0x%08X\n",long_data);
/* get Region 1 Base Address */
offset = REGION1_BASE_OFFSET;
if (sys_read_config_dword (busno,devno,function,offset,&long_data)
== ERROR)
{
printf("Error reading Region 1 Base\n");
return;
}
printf("PCI Region 1 Base = 0x%08X\n",long_data);
/* get Expansion ROM Base Address */
offset = TYPE1_EXP_ROM_OFFSET;
if (sys_read_config_dword (busno,devno,function,offset,&long_data)
== ERROR)
{
printf("Error reading Expansion ROM Base\n");
return;
}
printf("Expansion ROM Base = 0x%08X\n",long_data);
} /* end type 1 header */
}
}
/* check if host of backplane */
int isHost()
{
if (*BACKPLANE_DET_REG & BP_HOST_BIT)
return TRUE;
else
return FALSE;
}
/*****************************************************************************
* sys_pci_device_initialization - initialize PCI I/O devices
*
* This function is responsible for initializing all PCI I/O devices for proper
* PCI operation. All I/O devices are mapped into appropriate locations in the
* PCI address space (based on size and alignment requirements). This function
* must ensure that no bus conflicts exist. This function is also responsible
* for initializing cache line size, latency timer, DEVSEL# timing, and parity
* error response. This function fills out the data structure which is passed
* in to it. This function will return SUCCESSFUL if at least one I/O
* controller can be successfully configured. This function will return ERROR
* if no I/O controllers can be initialized.
*
*/
void sys_pci_device_initialization (PCI_DATA* pci_data)
{
volatile int i;
bus0_lastbus = PRIMARY_BUS_NUM; /* last bus number behind bus 0 (primary bus ) */
bus1_lastbus = SECONDARY_BUS_NUM; /* last bus number behind bus 1 (secondary bus) */
pci_data->num_devices = 0; /* total number of devices configured */
pci_data->num_functions = 0; /* total number of functions configured */
init_312_pci(); /* initialize the ATU, MU and bridge on the 80312 */
if (isHost())
{
/* If the IQ80310 board is connected to the backplane it has to initialize the Primary PCI bus */
/* set PCI base addresses for primary bus */
memspace_ptr[PRIMARY_BUS_NUM] = PRIMARY_MEM_BASE;
memspace_limit[PRIMARY_BUS_NUM] = PRIMARY_MEM_LIMIT;
iospace_ptr[PRIMARY_BUS_NUM] = PRIMARY_IO_BASE;
iospace_limit[PRIMARY_BUS_NUM] = PRIMARY_IO_LIMIT;
PRINT_OFF();
/* Initialize Primary PCI bus */
sys_pci_bus_init (PRIMARY_BUS_NUM, PRIMARY_BUS_NUM, pci_data);
}
/* Initialization of the Secondary PCI bus */
/* set PCI base addresses for secondary bus */
memspace_ptr[SECONDARY_BUS_NUM] = SECONDARY_MEM_BASE;
memspace_limit[SECONDARY_BUS_NUM] = SECONDARY_MEM_LIMIT;
iospace_ptr[SECONDARY_BUS_NUM] = SECONDARY_IO_BASE;
iospace_limit[SECONDARY_BUS_NUM] = SECONDARY_IO_LIMIT;
PRINT_OFF();
/* Initialize Secondary PCI bus */
sys_pci_bus_init (SECONDARY_BUS_NUM, SECONDARY_BUS_NUM, pci_data);
/* Set absolute last secondary bus */
if (bus0_lastbus > bus1_lastbus)
lastbus = bus0_lastbus;
else
lastbus = bus1_lastbus;
PRINT_OFF();
/* before exiting, configure and enable FIQ and IRQ interrupts */
_enableFiqIrq(); /* enable FIQ and IRQ interrupts in CP13 */
config_ints(); /* configure interrupts */
/* wait a while to clear out any unwanted NMI interrupts */
for (i = 0; i < 100000; i++)
;
PRINT_ON();
/* enable ECC single bit correction and multi-bit reporting
- initialization code only enables correction */
*(volatile unsigned long *)ECCR_ADDR = 0x6;
}
/*****************************************************************************
* sys_pci_bus_init - initialize PCI I/O devices
*
* This function is responsible for initializing all PCI I/O devices for proper
* PCI operation. All I/O devices are mapped into appropriate locations in the
* PCI address space (based on size and alignment requirements). This function
* must ensure that no bus conflicts exist. This function is also responsible
* for initializing cache line size, latency timer, DEVSEL# timing, and parity
* error response. This function fills out the data structure which is passed
* in to it. This function will return SUCCESSFUL if at least one I/O
* controller can be successfully configured. This function will return ERROR
* if no I/O controllers can be initialized.
*/
static void sys_pci_bus_init(UINT bus, UINT root_bus, PCI_DATA* pci_data)
{
UINT device, function;
USHORT vendor, device_id;
UINT regno;
ULONG regvalue;
USHORT regshort;
UCHAR regchar;
UCHAR intpin, intline;
UINT line;
UCHAR header_type;
ULONG rom_enabled;
UINT base_addr_reg_start;
UINT base_addr_reg_end;
UINT exp_rom_baseaddr;
int multifunction;
/* bridge initialization variables */
ULONG class_code;
UINT secondary_bus_number;
UCHAR iospace_type;
UCHAR data_byte;
USHORT data_word;
ULONG membase, iobase;
ULONG memlimit, iolimit;
int no_memory, no_io;
#ifdef DEBUG_PCI
printf ("Configuring PCI Bus %d.\n", bus);
printf ("PCI Root Bus %d.\n", root_bus);
PRINT_OFF();
#endif
for (device = 0; device <= MAX_DEVICE_NUMBER; device++)
{
#ifdef DEBUG_PCI
printf ("\nConfiguring device %d.\n\n", device);
#endif
/* assume non-multifunction device at start */
multifunction = FALSE;
for (function = 0; function < MAX_FUNCTION_NUMBER; function ++)
{
#ifdef DEBUG_PCI
printf ("Configuring function %d.\n", function);
#endif
/* To determine whether a device is installed in a particular slot, */
/* we attempt to read the vendor ID from that slot. If there's */
/* nothing there, the bridge should return 0xffff (and signal a */
/* master abort). Otherwise, there is something there and we need */
/* to configure it. */
if ((sys_read_config_word(bus, device, function, VENDOR_ID_OFFSET, &vendor) == ERROR) || (vendor == 0xffff))
{
/* This means no device found */
#ifdef DEBUG_PCI
printf ("\nNo device.\n");
#endif
break; /* Go on to the next device */
}
/* We'll only get here if we got a real device/function */
/* Count the number of devices */
if (function == 0) (pci_data->num_devices)++;
/* Count the number of functions */
(pci_data->num_functions)++;
#ifdef DEBUG_PCI
printf ("Vendor: %x\n", vendor);
#endif
/* Read the Device ID */
sys_read_config_word (bus,device,function,DEVICE_ID_OFFSET,&device_id);
#ifdef DEBUG_PCI
printf("\n");
printf("Configuring PCI Bus : %d\n", bus);
printf(" PCI Device: %d\n", device);
printf(" Vendor Id : 0x%08X\n", vendor);
printf(" Device Id : 0x%08X\n", device_id);
#endif
/* Read the Configuration Header Type to determine configuration */
if (sys_read_config_byte (bus,device,function,HEADER_TYPE_OFFSET,&header_type)== ERROR) continue;
/* determine if multifunction device */
if ((header_type & MULTIFUNCTION_DEVICE) && (function == 0))
{
#ifdef DEBUG_PCI
printf ("Multifunction Device Found...\n");
#endif
multifunction = TRUE;
}
/* strip off multifunction device indicator bit */
header_type &= 0x7f;
switch (header_type)
{
case STANDARD_HEADER:
base_addr_reg_start = 0x10; /* Base Address Reg. Start Offset */
base_addr_reg_end = 0x24; /* Base Address Reg. End Offset */
exp_rom_baseaddr = 0x30; /* Expansion ROM Base Addr. Reg Offset */
break;
case PCITOPCI_HEADER:
base_addr_reg_start = 0x10; /* Base Address Reg. Start Offset */
base_addr_reg_end = 0x14; /* Base Address Reg. End Offset */
exp_rom_baseaddr = 0x38; /* Expansion ROM Base Addr. Reg Offset */
break;
default:
printf ("Header Type Not Supported, 0x%02X\n", header_type);
continue; /* skip over device */
break;
}
/* We cycle through the base registers, first writing out all */
/* ones to the register, then reading it back to determine the */
/* requested size in either I/O or memory space. Then we */
/* align the top of memory or i/o space pointer, write it to */
/* the register, and increment it. I say we so you won't feel */
/* excluded. */
for (regno = base_addr_reg_start; regno <= base_addr_reg_end; regno += 4)
{
/* Write out all 1's to the base register, then read it back */
regvalue = 0xffffffff;
sys_write_config_dword(bus,device,function,regno,(UINT32*)®value);
sys_read_config_dword (bus,device,function,regno,(UINT32*)®value);
/* Some number of the lower bits of regvalue will be clear */
/* indicating a don't care position. The more clear bits, */
/* the larger the requested mapping space. */
if (regvalue == 0) /* ...this reg not used. */
;
/*---------------------------------------------------------*/
/* I/O space mapping */
/*---------------------------------------------------------*/
else if ((regvalue & 3) == 1) /* ...this is I/O space */
{
ULONG requested_size;
/* Align iospace_ptr for the requested size. All bit */
/* positions clear in regvalue must be clear in */
/* iospace_ptr. */
requested_size = ~(regvalue & 0xfffffffe);
#ifdef DEBUG_PCI
printf ("Configuration for I/O space...\n");
printf ("Size request: %x; ", requested_size);
printf ("IOspace_ptr: %x\n", iospace_ptr[root_bus]);
#endif
/* check to make sure that there is enought iospace left to grant */
if ((iospace_ptr[root_bus] + requested_size) > iospace_limit[root_bus])
{
printf ("\nPCI Configuration ERROR: Out of I/O Space on Bus %d!\n", bus);
printf (" No I/O Space Allocated to Device %d, Function %d.\n", device, function);
return;
}
/* Align the space pointer if necessary */
if (iospace_ptr[root_bus] & requested_size)
{
iospace_ptr[root_bus] &= ~requested_size;
iospace_ptr[root_bus] += requested_size + 1;
}
#ifdef DEBUG_PCI
printf("Adjusted I/O Space Ptr: %x\n", iospace_ptr[root_bus]);
printf(" I/O Space Size : 0x%08X\n", requested_size);
printf(" I/O Space Base : 0x%08X\n", iospace_ptr[root_bus]);
#endif /* Write out the adjusted iospace pointer. */
sys_write_config_dword (bus,device,function,regno,(UINT32*)&iospace_ptr[root_bus]);
/* Update space pointer */
iospace_ptr[root_bus] += requested_size + 1;
}
/*---------------------------------------------------------*/
/* Memory space mapping */
/*---------------------------------------------------------*/
else if ((regvalue & 1) == 0) /* ...this is memory space */
{
ULONG requested_size;
/* Type is encoded in bits 1 and 2 */
/* 64 bit space (10) is an error for the moment, as is */
/* the reserved value, 11. */
if (regvalue & 0x4)
{
printf ("Type error in base register.\n");
break;
}
/* Align memspace_ptr for the requested size. All bit */
/* positions clear in regvalue must be clear in */
/* memspace_ptr. */
requested_size = ~(regvalue & 0xfffffff0);
#ifdef DEBUG_PCI
printf ("Configuration for memory space.\n");
printf ("Size request: %x; ", requested_size);
printf ("Membase_ptr: %x\n", memspace_ptr[root_bus]);
#endif
/* check to make sure that there is enough memspace left to grant */
if ((memspace_ptr[root_bus] + requested_size) > memspace_limit[root_bus])
{
printf ("\nPCI Configuration ERROR: Out of Memory Space on Bus %d!\n", bus);
printf (" No Memory Space Allocated to Device %d, Function %d.\n", device, function);
printf ("Root Bus = %d, Memory Ptr = 0x%08X, Requested Size = 0x%08X, Memory Limit = 0x%08X\n",
root_bus, memspace_ptr[root_bus], requested_size, memspace_limit[root_bus]);
return;
}
if (memspace_ptr[root_bus] & requested_size)
{
memspace_ptr[root_bus] &= ~requested_size;
memspace_ptr[root_bus] += requested_size + 1;
}
#ifdef DEBUG_PCI
printf ("Adjusted Membase_ptr: %x\n", memspace_ptr[root_bus]);
printf(" Memory Space Size : 0x%08X\n", requested_size);
printf(" Memory Space Base : 0x%08X\n", memspace_ptr[root_bus]);
#endif
/* Write out the adjusted memory pointer */
sys_write_config_dword (bus,device,function,regno,(UINT32*)&memspace_ptr[root_bus]);
memspace_ptr[root_bus] += requested_size + 1;
}
}
/*-------------------------------------------------------------*/
/* Expansion ROM mapping */
/* The expansion ROM is handled in the same way as the other */
/* PCI base registers. If the lowest bit in this register is */
/* set, memory-mapped accesses are not possible, since the ROM */
/* is active. (Only one decoder). */
/*-------------------------------------------------------------*/
/* Store the state of the ROM enabled bit so we can restore it */
sys_read_confi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -