158 lines
6.0 KiB
C
158 lines
6.0 KiB
C
#include "../include/pci.h"
|
|
#include "../include/memory.h"
|
|
#include "../include/io.h"
|
|
#include "../include/printf.h"
|
|
|
|
unsigned int PCI_ADDR_BASE;
|
|
|
|
uint8_t pci_get_drive_irq(uint8_t bus, uint8_t slot, uint8_t func) {
|
|
return (uint8_t)read_pci(bus, slot, func, 0x3c);
|
|
}
|
|
|
|
uint32_t pci_get_port_base(uint8_t bus, uint8_t slot, uint8_t func) {
|
|
uint32_t io_port = 0;
|
|
for(int i = 0;i<6;i++) {
|
|
base_address_register bar = get_base_address_register(bus,slot,func,i);
|
|
if(bar.type == input_output) {
|
|
io_port = (uint32_t)bar.address;
|
|
}
|
|
}
|
|
return io_port;
|
|
}
|
|
|
|
void PCI_GET_DEVICE(uint16_t vendor_id, uint16_t device_id, uint8_t* bus, uint8_t* slot, uint8_t* func) {
|
|
unsigned char* pci_drive = PCI_ADDR_BASE;
|
|
for (;; pci_drive += 0x110 + 4) {
|
|
if (pci_drive[0] == 0xff) {
|
|
struct pci_config_space_public* pci_config_space_puclic;
|
|
pci_config_space_puclic =
|
|
(struct pci_config_space_public*)(pci_drive + 0x0c);
|
|
if (pci_config_space_puclic->VendorID == vendor_id &&
|
|
pci_config_space_puclic->DeviceID == device_id) {
|
|
*bus = pci_drive[1];
|
|
*slot = pci_drive[2];
|
|
*func = pci_drive[3];
|
|
return;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t read_bar_n(uint8_t bus, uint8_t device, uint8_t function, uint8_t bar_n) {
|
|
uint32_t bar_offset = 0x10 + 4 * bar_n;
|
|
return read_pci(bus, device, function, bar_offset);
|
|
}
|
|
|
|
void write_pci(uint8_t bus, uint8_t device, uint8_t function, uint8_t registeroffset, uint32_t value) {
|
|
uint32_t id = 1 << 31 | ((bus & 0xff) << 16) | ((device & 0x1f) << 11) |
|
|
((function & 0x07) << 8) | (registeroffset & 0xfc);
|
|
io_out32(PCI_COMMAND_PORT, id);
|
|
io_out32(PCI_DATA_PORT, value);
|
|
}
|
|
|
|
uint32_t pci_read_command_status(uint8_t bus, uint8_t slot, uint8_t func) {
|
|
return read_pci(bus, slot, func, 0x04);
|
|
}
|
|
|
|
void pci_write_command_status(uint8_t bus, uint8_t slot, uint8_t func, uint32_t value) {
|
|
write_pci(bus, slot, func, 0x04, value);
|
|
}
|
|
|
|
uint32_t read_pci(uint8_t bus, uint8_t device, uint8_t function, uint8_t registeroffset) {
|
|
uint32_t id = 1 << 31 | ((bus & 0xff) << 16) | ((device & 0x1f) << 11) |
|
|
((function & 0x07) << 8) | (registeroffset & 0xfc);
|
|
io_out32(PCI_COMMAND_PORT, id);
|
|
uint32_t result = io_in32(PCI_DATA_PORT);
|
|
return result >> (8 * (registeroffset % 4));
|
|
}
|
|
|
|
base_address_register get_base_address_register(uint8_t bus, uint8_t device, uint8_t function, uint8_t bar) {
|
|
base_address_register result;
|
|
|
|
uint32_t headertype = read_pci(bus, device, function, 0x0e) & 0x7e;
|
|
int max_bars = 6 - 4 * headertype;
|
|
if (bar >= max_bars)
|
|
return result;
|
|
|
|
uint32_t bar_value = read_pci(bus, device, function, 0x10 + 4 * bar);
|
|
result.type = (bar_value & 1) ? input_output : mem_mapping;
|
|
|
|
if (result.type == mem_mapping) {
|
|
switch ((bar_value >> 1) & 0x3) {
|
|
case 0: // 32
|
|
case 1: // 20
|
|
case 2: // 64
|
|
break;
|
|
}
|
|
result.address = (uint8_t*)(bar_value & ~0x3);
|
|
result.prefetchable = 0;
|
|
} else {
|
|
result.address = (uint8_t*)(bar_value & ~0x3);
|
|
result.prefetchable = 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void pci_config(unsigned int bus, unsigned int f, unsigned int equipment, unsigned int adder) {
|
|
unsigned int cmd = 0;
|
|
cmd = 0x80000000 + (unsigned int)adder + ((unsigned int)f << 8) +
|
|
((unsigned int)equipment << 11) + ((unsigned int)bus << 16);
|
|
// cmd = cmd | 0x01;
|
|
io_out32(PCI_COMMAND_PORT, cmd);
|
|
}
|
|
|
|
void init_pci(){
|
|
printf("[\035kernel\036]: Loading pci device...\n");
|
|
|
|
PCI_ADDR_BASE = kmalloc(1 * 1024 * 1024);
|
|
unsigned int i, BUS, Equipment, F, ADDER, *i1;
|
|
unsigned char *PCI_DATA = PCI_ADDR_BASE, *PCI_DATA1;
|
|
|
|
for (BUS = 0; BUS < 256; BUS++) { //查询总线
|
|
for (Equipment = 0; Equipment < 32; Equipment++) { //查询设备
|
|
for (F = 0; F < 8; F++) { //查询功能
|
|
pci_config(BUS, F, Equipment, 0);
|
|
if (io_in32(PCI_DATA_PORT) != 0xFFFFFFFF) {
|
|
//当前插槽有设备
|
|
//把当前设备信息映射到PCI数据区
|
|
int key = 1;
|
|
while (key) {
|
|
PCI_DATA1 = PCI_DATA;
|
|
*PCI_DATA1 = 0xFF; //表占用标志
|
|
PCI_DATA1++;
|
|
*PCI_DATA1 = BUS; //总线号
|
|
PCI_DATA1++;
|
|
*PCI_DATA1 = Equipment; //设备号
|
|
PCI_DATA1++;
|
|
*PCI_DATA1 = F; //功能号
|
|
PCI_DATA1++;
|
|
PCI_DATA1 = PCI_DATA1 + 8;
|
|
for (ADDER = 0; ADDER < 256; ADDER = ADDER + 4) {
|
|
pci_config(BUS, F, Equipment, ADDER);
|
|
i = io_in32(PCI_DATA_PORT);
|
|
i1 = i;
|
|
//*i1 = PCI_DATA1;
|
|
memcpy(PCI_DATA1, &i, 4);
|
|
PCI_DATA1 = PCI_DATA1 + 4;
|
|
}
|
|
for (uint8_t barNum = 0; barNum < 6; barNum++) {
|
|
base_address_register bar =
|
|
get_base_address_register(BUS, Equipment, F, barNum);
|
|
if (bar.address && (bar.type == input_output)) {
|
|
PCI_DATA1 += 4;
|
|
int i = ((uint32_t)(bar.address));
|
|
memcpy(PCI_DATA1, &i, 4);
|
|
printf("[pci]: Device Address: %08x Size: %d\n",bar.address,bar.size);
|
|
}
|
|
}
|
|
PCI_DATA = PCI_DATA + 0x110 + 4;
|
|
key = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|