add simple pci driver

This commit is contained in:
catfood 2023-01-08 21:03:48 +08:00
parent 000c2a4b7c
commit 58d6a5c65f
10 changed files with 256 additions and 7 deletions

View File

@ -1,6 +1,6 @@
#ifndef _ORANGES_MEMMAN_H_
#define _ORANGES_MEMMAN_H_
#include "type.h"
#define MEMMAN_FREES 4090 //32KB
#define MEMMAN_ADDR 0x01ff0000 //存memman31M960K
#define FMIBuff 0x007ff000 //loader中getFreeMemInfo返回值存放起始地址(7M1020K)

51
include/pci.h Normal file
View File

@ -0,0 +1,51 @@
/*
** Copyright 2002-2003, Michael Noisternig. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#ifndef _PCI_H_
#define _PCI_H_
#include "type.h"
typedef struct {
char prefetchable;
uint32_t address;
uint8_t type;
} bar_t;
#define INPUT_OUTPUT 0
#define MEMORY_MAPPED 1
struct device_desc_pci {
uint8_t bus;
uint8_t device;
uint8_t function;
uint16_t vendor_id;
uint16_t device_id;
uint8_t class_id;
uint8_t subclass_id;
uint8_t interface_id;
uint8_t revision_id;
uint32_t interrupt;
uint32_t port_base;
uint32_t type;
};
typedef struct device_desc_pci pci_dev_t;
enum DEVICES_TYPE {
DEVICE_STORAGE = (1 << 0),
DEVICE_SOUND = (1 << 1),
DEVICE_INPUT_SYSTEMS = (1 << 2),
DEVICE_NETWORK = (1 << 3),
DEVICE_DISPLAY = (1 << 4),
DEVICE_BUS_CONTROLLER = (1 << 5),
DEVICE_BRIDGE = (1 << 6),
DEVICE_CHAR = (1 << 7),
DEVICE_RTC = (1 << 8),
DEVICE_UNKNOWN = (1 << 9),
};
uint32_t pci_read(uint16_t bus, uint16_t device, uint16_t function, uint32_t offset);
void pci_write(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t data);
pci_dev_t pci_get_device_desriptor(uint8_t bus, uint8_t device, uint8_t function);
#define NR_PCI_DEV 8
#endif

View File

@ -15,6 +15,8 @@
* below instead.
* added by xw, 17/12/11
*/
#pragma once
#include "protect.h"
#define INIT_STACK_SIZE 1024 * 8 //new kernel stack is 8kB
#define P_STACKBASE 0
#define GSREG 0

View File

@ -7,7 +7,7 @@
#ifndef _ORANGES_PROTECT_H_
#define _ORANGES_PROTECT_H_
#include "type.h"
/* 存储段描述符/系统段描述符 */
typedef struct s_descriptor /* 共 8 个字节 */

View File

@ -4,6 +4,11 @@
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Forrest Yu, 2005
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#ifndef _PROTO_H_
#define _PROTO_H_
#include "type.h"
#include "tty.h"
// added by zcr
void disable_irq(int irq);
@ -130,3 +135,8 @@ void write_page_pte(u32 TblPhyAddr, u32 AddrLin, u32 PhyAddr, u32 Attribute);
u32 vmalloc(u32 size);
int lin_mapping_phy(u32 AddrLin, u32 phy_addr, u32 pid, u32 pde_Attribute, u32 pte_Attribute); // edit by visual 2016.5.19
void clear_kernel_pagepte_low(); // add by visual 2016.5.12
/* add by catfood */
void init_pci();
#endif

View File

@ -24,6 +24,24 @@ typedef unsigned short u16;
typedef char i8;
typedef unsigned char u8;
typedef long long int64;
typedef unsigned long long uint64;
typedef int int32;
typedef unsigned int uint32;
typedef short int16;
typedef unsigned short uint16;
typedef char int8;
typedef unsigned char uint8;
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef char int8_t;
typedef unsigned char uint8_t;
typedef i32 intptr_t;
typedef u32 uintptr_t;

View File

@ -32,6 +32,7 @@ KERN_SRCFILES :=kernel/kernel.asm \
kernel/protect.c \
kernel/serialport.c \
kernel/vga.c \
kernel/pci.c \
lib/klib.c \

View File

@ -32,9 +32,10 @@ static int initialize_cpus(); // added by xw, 18/6/2
*======================================================================*/
int kernel_main()
{
clear_kernel_pagepte_low();
init_serial();
init_pci();
clear_kernel_pagepte_low();
while(1);
int error;
disp_pos = 0;

166
kernel/pci.c Normal file
View File

@ -0,0 +1,166 @@
#include "type.h"
#include "assert.h"
#include "console.h"
#include "const.h"
#include "keyboard.h"
#include "memman.h"
#include "proc.h"
#include "protect.h"
#include "proto.h"
#include "stdio.h"
#include "string.h"
#include "x86.h"
#include "global.h"
#include "tty.h"
#include "pci.h"
/*
* Copyright (C) 2020-2022 The opuntiaOS Project Authors.
* + Contributed by Nikita Melekhin <nimelehin@gmail.com>
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#define DEBUG_PCI
pci_dev_t pci_devs[NR_PCI_DEV];
static uint32_t _pci_do_read_bar(uint8_t bus, uint8_t device, uint8_t function,
uint8_t bar_id) {
uint32_t header_type = pci_read(bus, device, function, 0x0e) & 0x7f;
uint8_t max_bars = 6 - (header_type * 4);
if (bar_id >= max_bars) return 0;
uint32_t bar_val = pci_read(bus, device, function, 0x10 + 4 * bar_id);
return bar_val;
}
static bar_t _pci_get_bar(uint8_t bus, uint8_t device, uint8_t function,
uint8_t bar_id) {
bar_t result;
uint32_t bar_val = _pci_do_read_bar(bus, device, function, bar_id);
result.type = (bar_val & 0x1) ? INPUT_OUTPUT : MEMORY_MAPPED;
if (result.type == MEMORY_MAPPED) {
} else {
result.address = (uint32_t)((bar_val >> 2) << 2);
result.prefetchable = 0;
}
return result;
}
uint32_t pci_read(uint16_t bus, uint16_t device, uint16_t function,
uint32_t offset) {
uint32_t id = (0x1 << 31) | ((bus & 0xFF) << 16) | ((device & 0x1F) << 11) |
((function & 0x07) << 8) | (offset & 0xFC);
outl(0xCF8, id);
uint32_t tmp = (uint32_t)(inl(0xCFC) >> (8 * (offset % 4)));
return tmp;
}
void pci_write(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset,
uint32_t data) {
uint32_t bus32 = bus;
uint32_t device32 = device;
uint16_t function16 = function;
uint32_t address = (1 << 31) | (bus32 << 16) | (device32 << 11) |
(function16 << 8) | (offset & 0xFC);
outl(0xCF8, address);
outl(0xCFC, data);
}
static int dev_type_by_class(pci_dev_t* dd) {
switch (dd->class_id) {
case 0x1:
switch (dd->subclass_id) {
case 0x1:
case 0x3:
case 0x4:
return DEVICE_BUS_CONTROLLER;
default:
return DEVICE_STORAGE;
}
case 0x2:
return DEVICE_NETWORK;
case 0x3:
return DEVICE_DISPLAY;
case 0x6:
return DEVICE_BRIDGE;
default:
#ifdef DEBUG_PCI
kprintf("PCI: DEVICE_UNKNOWN: Class %d subclass %d", dd->class_id,
dd->subclass_id);
#endif
return DEVICE_UNKNOWN;
}
}
static char pci_has_device_functions(uint8_t bus, uint8_t device) {
return pci_read(bus, device, 0, 0x0e) & (1 << 7);
}
int pci_find_devices() {
#ifdef DEBUG_PCI
kprintf("PCI: scanning\n");
#endif
uint8_t bus, device, function;
int count = 0;
for (bus = 0; bus < 8; bus++) {
for (device = 0; device < 32; device++) {
uint8_t functions_count =
pci_has_device_functions(bus, device) == 0 ? 8 : 1;
for (function = 0; function < functions_count; function++) {
pci_dev_t dev =
pci_get_device_desriptor(bus, device, function);
if (dev.vendor_id == 0x0000 || dev.vendor_id == 0xffff) {
continue;
}
for (uint8_t bar_id = 0; bar_id < 6; bar_id++) {
bar_t bar = _pci_get_bar(bus, device, function, bar_id);
if (bar.address && (bar.type == INPUT_OUTPUT)) {
dev.port_base = (uint32_t)bar.address;
}
}
dev.type = dev_type_by_class(&dev);
pci_devs[count ++] = dev;
#ifdef DEBUG_PCI
kprintf("PCI: Vendor %x, devID %x, cl %x scl %x\n",
dev.vendor_id, dev.device_id, dev.class_id,
dev.subclass_id);
#endif
}
}
}
return 0;
}
pci_dev_t pci_get_device_desriptor(uint8_t bus, uint8_t device,
uint8_t function) {
pci_dev_t new_device = {0};
new_device.bus = bus;
new_device.device = device;
new_device.function = function;
new_device.vendor_id = pci_read(bus, device, function, 0x00);
new_device.device_id = pci_read(bus, device, function, 0x02);
new_device.class_id = pci_read(bus, device, function, 0x0b);
new_device.subclass_id = pci_read(bus, device, function, 0x0a);
new_device.interface_id = pci_read(bus, device, function, 0x09);
new_device.revision_id = pci_read(bus, device, function, 0x08);
new_device.interrupt = pci_read(bus, device, function, 0x3c);
return new_device;
}
uint32_t pci_read_bar(pci_dev_t* pci_dev, int bar_id) {
return _pci_do_read_bar(pci_dev->bus, pci_dev->device, pci_dev->function,
bar_id);
}
void init_pci() { pci_find_devices(); }

View File

@ -8,9 +8,9 @@
static void kprintfputch(int ch, int *cnt)
{
// write_serial(ch);
char _ch = ch;
tty_write(cur_ntty, &_ch, 1);
write_serial(ch);
// char _ch = ch;
// tty_write(cur_ntty, &_ch, 1);
(*cnt)++;
}