Add start of a PCI driver
This commit is contained in:
parent
0bd3fe70cb
commit
1b1c3026ba
9
Makefile
9
Makefile
@ -30,7 +30,7 @@ debug: os.iso kernel/kernel.elf
|
||||
@$(GDB)
|
||||
#gdbgui -g i386-elf-gdb --project $(CWD)
|
||||
|
||||
os.iso: kernel/kernel.elf init vfs devfs initrd vga_drv
|
||||
os.iso: kernel/kernel.elf init vfs devfs initrd vga_drv pci
|
||||
@cp kernel/kernel.elf sysroot/boot
|
||||
@cd initrd; tar -f ../sysroot/boot/initrd.tar -c *
|
||||
@grub-mkrescue -o $@ sysroot >/dev/null 2>/dev/null
|
||||
@ -50,6 +50,9 @@ devfs: crts libc
|
||||
@cd $@ && make
|
||||
@cp $@/$@ initrd/$@
|
||||
|
||||
pci: crts libc
|
||||
@cd $@ && make
|
||||
@cp $@/$@ initrd/$@
|
||||
|
||||
vga_drv: crts libc
|
||||
@cd $@ && make
|
||||
@ -58,6 +61,8 @@ vga_drv: crts libc
|
||||
kernel/kernel.elf: $(OBJ) $(ASM_OBJ) $(S_ASM_OBJ) sysroot/usr/lib/libc.a
|
||||
@$(CC) -z max-page-size=4096 -Xlinker -n -T kernel/cpu/$(PLAT)/linker.ld -o $@ $(CFLAGS) -nostdlib $^ -lgcc
|
||||
|
||||
libc: sysroot/usr/lib/libc.a
|
||||
|
||||
sysroot/usr/lib/libc.a: $(LIBC_OBJ)
|
||||
@$(AR) rcs $@ $^
|
||||
|
||||
@ -65,7 +70,7 @@ sysroot/usr/lib/libc.a: $(LIBC_OBJ)
|
||||
@$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
%.o: %.asm
|
||||
@$(NASM) $< -o $@
|
||||
$(NASM) $< -o $@
|
||||
|
||||
%.o: %.s
|
||||
@$(AS) $< -o $@
|
||||
|
@ -105,7 +105,6 @@ int main() {
|
||||
yieldToPID(3);
|
||||
datapos=find_loc("vga_drv",initrd);
|
||||
load_task(datapos,initrd);
|
||||
free(initrd);
|
||||
yieldToPID(4);
|
||||
mount("","devfs","/dev/");
|
||||
FILE* file;
|
||||
@ -115,6 +114,10 @@ int main() {
|
||||
do {
|
||||
file=fopen("/dev/vga","w");
|
||||
} while(file==NULL);
|
||||
datapos=find_loc("pci",initrd);
|
||||
load_task(datapos,initrd);
|
||||
free(initrd);
|
||||
yieldToPID(4);
|
||||
fputs("FPUTS String\n",file);
|
||||
char str[3]={0,0,0};
|
||||
fgets(str,2,stdin);
|
||||
|
0
initrd_drv/Makefile
Normal file
0
initrd_drv/Makefile
Normal file
13
pci/Makefile
Normal file
13
pci/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
C_SOURCES = $(wildcard *.c)
|
||||
OBJ = $(C_SOURCES:.c=.o )
|
||||
CFLAGS = -Wall -g
|
||||
CC = i386-myos-gcc
|
||||
|
||||
pci: $(OBJ) ../libc/*
|
||||
@$(CC) -o $@ $(CFLAGS) $(OBJ)
|
||||
|
||||
%.o: %.c
|
||||
@$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
@rm -rf *.o pci
|
13
pci/main.c
Normal file
13
pci/main.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include <stdio.h>
|
||||
#include "pci.h"
|
||||
int main() {
|
||||
FILE* file;
|
||||
do {
|
||||
file=fopen("/dev/vga","w");
|
||||
} while(file==NULL);
|
||||
do {
|
||||
file=fopen("/dev/vga","w");
|
||||
} while(file==NULL);
|
||||
yield();
|
||||
pci_init();
|
||||
}
|
121
pci/pci.c
Normal file
121
pci/pci.c
Normal file
@ -0,0 +1,121 @@
|
||||
#include <stdint.h>
|
||||
#include "ports.h"
|
||||
#include "pci.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
pci_dev_common_info** pci_devs;
|
||||
static uint32_t max_devs;
|
||||
uint32_t pci_num_devs;
|
||||
|
||||
static uint32_t read_config(uint8_t bus,uint8_t device,uint8_t func,uint8_t offset) {
|
||||
uint32_t address;
|
||||
uint32_t lbus=(uint32_t)bus;
|
||||
uint32_t ldev=(uint32_t)device;
|
||||
uint32_t lfunc=(uint32_t)func;
|
||||
address=(uint32_t)((lbus << 16)|(ldev << 11)|(lfunc<<8)|(offset&0xfc)|((uint32_t)0x80000000));
|
||||
port_long_out(PCI_CONFIG_ADDRESS,address);
|
||||
uint32_t data=port_long_in(PCI_CONFIG_DATA);
|
||||
return data;
|
||||
}
|
||||
|
||||
static void write_config(uint8_t bus,uint8_t device,uint8_t func,uint8_t offset,uint32_t data) {
|
||||
uint32_t address;
|
||||
uint32_t lbus=(uint32_t)bus;
|
||||
uint32_t ldev=(uint32_t)device;
|
||||
uint32_t lfunc=(uint32_t)func;
|
||||
address=(uint32_t)((lbus << 16)|(ldev << 11)|(lfunc<<8)|(offset&0xfc)|((uint32_t)0x80000000));
|
||||
port_long_out(PCI_CONFIG_ADDRESS,address);
|
||||
port_long_out(PCI_CONFIG_DATA,data);
|
||||
}
|
||||
|
||||
pci_dev_common_info* pci_get_dev_info(uint8_t bus,uint8_t device,uint8_t func) {
|
||||
uint32_t* info=malloc(sizeof(uint32_t)*5);
|
||||
info[0]=read_config(bus,device,func,0);
|
||||
info[1]=read_config(bus,device,func,4);
|
||||
info[2]=read_config(bus,device,func,8);
|
||||
info[3]=read_config(bus,device,func,0xC);
|
||||
pci_dev_common_info* pci_info=(pci_dev_common_info*)info;
|
||||
pci_info->bus=bus;
|
||||
pci_info->device=device;
|
||||
pci_info->func=func;
|
||||
return pci_info;
|
||||
}
|
||||
|
||||
void pci_set_dev_info(pci_dev_common_info* inf) {
|
||||
uint32_t* info=(uint32_t*)inf;
|
||||
write_config(inf->bus,inf->device,inf->func,0,info[0]);
|
||||
write_config(inf->bus,inf->device,inf->func,4,info[1]);
|
||||
write_config(inf->bus,inf->device,inf->func,8,info[2]);
|
||||
write_config(inf->bus,inf->device,inf->func,0xC,info[3]);
|
||||
}
|
||||
|
||||
static void checkFunction(pci_dev_common_info* info);
|
||||
|
||||
static void checkDevice(uint8_t bus, uint8_t device) {
|
||||
pci_dev_common_info* info=pci_get_dev_info(bus,device,0);
|
||||
if(info->vend_id==0xFFFF||info->class_code==0xFF) {
|
||||
return;
|
||||
}
|
||||
checkFunction(info);
|
||||
if((info->header_type&0x80)!=0) {
|
||||
for(uint8_t function=1;function<8;function++) {
|
||||
pci_dev_common_info* info=pci_get_dev_info(bus,device,function);
|
||||
if(info->vend_id!=0xFFFF&&info->class_code!=0xFF) {
|
||||
checkFunction(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void printBAR(pci_dev_common_info* info,uint32_t bar,int num) {
|
||||
if (bar!=0) {
|
||||
if (bar&0x1) {
|
||||
printf("[INFO] IO BAR%d:%x\n",num,bar&0xFFFFFFFC);
|
||||
} else {
|
||||
printf("[INFO] MEM BAR%d:%x\n",num,bar&0xFFFFFFF0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void checkFunction(pci_dev_common_info* info) {
|
||||
if (pci_num_devs==max_devs) {
|
||||
max_devs+=32;
|
||||
pci_devs=malloc(sizeof(pci_dev_common_info)*max_devs);
|
||||
}
|
||||
pci_devs[pci_num_devs]=info;
|
||||
if ((info->header_type&0x7f)==0) {
|
||||
pci_dev_type0* dev=realloc(info,sizeof(pci_dev_type0));
|
||||
uint32_t* dev_word_array=(uint32_t*)dev;
|
||||
for (int i=5;i<17;i++) {
|
||||
dev_word_array[i]=read_config(info->bus,info->device,info->func,i*4);
|
||||
}
|
||||
pci_devs[pci_num_devs]=(pci_dev_common_info*)dev;
|
||||
}
|
||||
pci_num_devs++;
|
||||
}
|
||||
|
||||
void pci_init() {
|
||||
pci_devs=malloc(sizeof(pci_dev_common_info)*32);
|
||||
max_devs=32;
|
||||
pci_num_devs=0;
|
||||
for(uint16_t bus=0;bus<1; bus++) {
|
||||
for(uint8_t device=0;device<32; device++) {
|
||||
checkDevice(bus, device);
|
||||
}
|
||||
}
|
||||
for (int i=0;i<pci_num_devs;i++) {
|
||||
pci_dev_common_info* info=pci_devs[i];
|
||||
printf("[INFO] Found PCI device. Class code:%x, Subclass:%x Prog IF:%x\n",info->class_code,info->subclass,info->prog_if);
|
||||
printf("[INFO] Vendor ID:%x, Device ID:%x\n",info->vend_id,info->dev_id);
|
||||
if ((info->header_type&0x7f)==0) {
|
||||
pci_dev_type0* dev=(pci_dev_type0*)info;
|
||||
printBAR(info,dev->bar0,0);
|
||||
printBAR(info,dev->bar1,1);
|
||||
printBAR(info,dev->bar2,2);
|
||||
printBAR(info,dev->bar3,3);
|
||||
printBAR(info,dev->bar4,4);
|
||||
printBAR(info,dev->bar5,5);
|
||||
}
|
||||
}
|
||||
}
|
76
pci/pci.h
Normal file
76
pci/pci.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef PCI_H
|
||||
#define PCI_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PCI_CONFIG_ADDRESS 0xCF8
|
||||
#define PCI_CONFIG_DATA 0xCFC
|
||||
|
||||
typedef struct {
|
||||
uint16_t vend_id;
|
||||
uint16_t dev_id;
|
||||
uint16_t command;
|
||||
uint16_t status;
|
||||
uint8_t rev_id;
|
||||
uint8_t prog_if;
|
||||
uint8_t subclass;
|
||||
uint8_t class_code;
|
||||
uint8_t cache_line_size;
|
||||
uint8_t lat_timer;
|
||||
uint8_t header_type;
|
||||
uint8_t bist;
|
||||
uint16_t bus;
|
||||
uint8_t device;
|
||||
uint8_t func;
|
||||
} __attribute__((packed)) pci_dev_common_info;
|
||||
|
||||
typedef struct {
|
||||
pci_dev_common_info common;
|
||||
uint32_t bar0;
|
||||
uint32_t bar1;
|
||||
uint32_t bar2;
|
||||
uint32_t bar3;
|
||||
uint32_t bar4;
|
||||
uint32_t bar5;
|
||||
uint32_t cis_ptr;
|
||||
uint16_t sub_vend_id;
|
||||
uint16_t sub_id;
|
||||
uint32_t exp_rom_addr;
|
||||
uint16_t cap_ptr;
|
||||
uint16_t reserved1;
|
||||
uint32_t reserved2;
|
||||
uint8_t int_line;
|
||||
uint8_t int_pin;
|
||||
uint8_t min_grnt;
|
||||
uint8_t max_latency;
|
||||
} __attribute__((packed)) pci_dev_type0;
|
||||
|
||||
typedef enum {
|
||||
PCI_CLASS_UNCLASSIFIED=0x0,
|
||||
PCI_CLASS_STORAGE=0x1,
|
||||
PCI_CLASS_NETWORK=0x2,
|
||||
PCI_CLASS_DISPLAY=0x3,
|
||||
PCI_CLASS_MULTIMEDIA=0x4,
|
||||
PCI_CLASS_MEMORY=0x5,
|
||||
PCI_CLASS_BRIDGE=0x6,
|
||||
PCI_CLASS_SIMPCOM=0x7,
|
||||
PCI_CLASS_BASEPERIPH=0x8,
|
||||
PCI_CLASS_INPDEV=0x9,
|
||||
PCI_CLASS_DOCK=0xa,
|
||||
PCI_CLASS_CPU=0xb,
|
||||
PCI_CLASS_SERBUS=0xc,
|
||||
PCI_CLASS_WIRELESS=0xd,
|
||||
PCI_CLASS_INTELLIGENT=0xe,
|
||||
PCI_CLASS_SATELLITE=0xf,
|
||||
PCI_CLASS_ENCRYPTION=0x10,
|
||||
PCI_CLASS_SIGPROCESS=0x11,
|
||||
} pci_class;
|
||||
|
||||
extern pci_dev_common_info** pci_devs;
|
||||
extern uint32_t pci_num_devs;
|
||||
|
||||
pci_dev_common_info* pci_get_dev_info(uint8_t bus,uint8_t device,uint8_t func);
|
||||
void pci_set_dev_info(pci_dev_common_info* inf);
|
||||
void pci_init();
|
||||
|
||||
#endif
|
31
pci/ports.c
Normal file
31
pci/ports.c
Normal file
@ -0,0 +1,31 @@
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t port_byte_in(uint16_t port) {
|
||||
uint8_t result;
|
||||
asm("in %%dx, %%al":"=a"(result):"d"(port));
|
||||
return result;
|
||||
}
|
||||
|
||||
void port_byte_out(uint16_t port,uint8_t data) {
|
||||
asm("out %%al, %%dx":: "a"(data),"d"(port));
|
||||
}
|
||||
|
||||
uint16_t port_word_in(uint16_t port) {
|
||||
uint16_t result;
|
||||
asm("in %%dx, %%ax":"=a"(result):"d"(port));
|
||||
return result;
|
||||
}
|
||||
|
||||
void port_word_out(uint16_t port,uint16_t data) {
|
||||
asm("out %%ax, %%dx":: "a" (data), "d" (port));
|
||||
}
|
||||
|
||||
uint32_t port_long_in(uint16_t port) {
|
||||
uint32_t result;
|
||||
asm("inl %%dx, %%eax":"=a"(result):"d"(port));
|
||||
return result;
|
||||
}
|
||||
|
||||
void port_long_out(uint16_t port,uint32_t data) {
|
||||
asm("outl %%eax, %%dx":: "a" (data), "d" (port));
|
||||
}
|
12
pci/ports.h
Normal file
12
pci/ports.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef PORTS_H
|
||||
#define PORTS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t port_byte_in(uint16_t port);
|
||||
void port_byte_out(uint16_t port,uint8_t data);
|
||||
uint16_t port_word_in(uint16_t port);
|
||||
void port_word_out(uint16_t port,uint16_t data);
|
||||
uint32_t port_long_in(uint16_t port);
|
||||
void port_long_out(uint16_t port,uint32_t data);
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user