add simple pci driver
This commit is contained in:
parent
000c2a4b7c
commit
58d6a5c65f
@ -1,6 +1,6 @@
|
||||
#ifndef _ORANGES_MEMMAN_H_
|
||||
#define _ORANGES_MEMMAN_H_
|
||||
|
||||
#include "type.h"
|
||||
#define MEMMAN_FREES 4090 //32KB
|
||||
#define MEMMAN_ADDR 0x01ff0000 //存memman,31M960K
|
||||
#define FMIBuff 0x007ff000 //loader中getFreeMemInfo返回值存放起始地址(7M1020K)
|
||||
|
||||
51
include/pci.h
Normal file
51
include/pci.h
Normal 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
|
||||
@ -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
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#ifndef _ORANGES_PROTECT_H_
|
||||
#define _ORANGES_PROTECT_H_
|
||||
|
||||
#include "type.h"
|
||||
|
||||
/* 存储段描述符/系统段描述符 */
|
||||
typedef struct s_descriptor /* 共 8 个字节 */
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@ KERN_SRCFILES :=kernel/kernel.asm \
|
||||
kernel/protect.c \
|
||||
kernel/serialport.c \
|
||||
kernel/vga.c \
|
||||
kernel/pci.c \
|
||||
lib/klib.c \
|
||||
|
||||
|
||||
|
||||
@ -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
166
kernel/pci.c
Normal 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(); }
|
||||
@ -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)++;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user