更新PCI驱动
This commit is contained in:
parent
52000ef135
commit
9a851018f7
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,4 +6,6 @@ cmake-build-debug/
|
||||
|
||||
isodir/
|
||||
|
||||
OSMain/
|
||||
|
||||
crashpowerdos-x86-nodesktop-rebuild-0.2.0.iso
|
13
build.py
13
build.py
@ -1,4 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
gcc = '/i686_elf_tools/bin/i686-elf-gcc.exe -std=gnu99 -I include/ -std=gnu99 -ffreestanding -O2 -c -Wincompatible-pointer-types'
|
||||
asm = '/i686_elf_tools/bin/i686-elf-as.exe'
|
||||
@ -6,11 +7,15 @@ nasm = "nasm -f elf32"
|
||||
ld = '/i686_elf_tools/bin/i686-elf-ld.exe'
|
||||
cd = os.getcwd() # 获取当前执行目录 'D:\CrashPowerDOS-main\'
|
||||
out = "target"
|
||||
|
||||
|
||||
def clean():
|
||||
print("Clean target folder")
|
||||
for file in os.listdir(cd + "\\target"): # 遍历指定文件夹下所有文件
|
||||
os.remove(cd + "\\target\\" + file)
|
||||
return 0
|
||||
|
||||
|
||||
def build_boot(): # 构建引导程序
|
||||
print("Building boot source code...")
|
||||
status = True
|
||||
@ -95,4 +100,10 @@ a = linker()
|
||||
if a != 0:
|
||||
exit(-1)
|
||||
print("Launching i386 vm...")
|
||||
os.system("qemu-system-i386 -vga std -kernel isodir\\sys\\kernel.elf -drive format=qcow2,file=cpos.qcow2")
|
||||
|
||||
if len(sys.argv) == 0 or sys.argv[1] == 'vga':
|
||||
print("Graphics MODE [VGA]")
|
||||
os.system("qemu-system-i386 -net nic,model=pcnet -net user -kernel isodir\\sys\\kernel.elf -drive format=qcow2,file=cpos.qcow2")
|
||||
elif sys.argv[1] == 'vbe':
|
||||
print("Graphics MODE [VBE]")
|
||||
os.system("qemu-system-i386 -vga std -net nic,model=pcnet -net user -kernel isodir\\sys\\kernel.elf -drive format=qcow2,file=cpos.qcow2")
|
@ -170,14 +170,18 @@ static int AcpiPowerHandler(registers_t *irq) {
|
||||
}
|
||||
|
||||
static void AcpiPowerInit() {
|
||||
uint32_t len = facp->PM1_EVT_LEN / 2;
|
||||
if(!facp) return;
|
||||
|
||||
uint8_t len = facp->PM1_EVT_LEN / 2;
|
||||
uint32_t *PM1a_ENABLE_REG = facp->PM1a_EVT_BLK + len;
|
||||
uint32_t *PM1b_ENABLE_REG = facp->PM1b_EVT_BLK + len;
|
||||
|
||||
if (!facp)
|
||||
return;
|
||||
if(PM1b_ENABLE_REG == len)
|
||||
PM1b_ENABLE_REG = 0;
|
||||
|
||||
io_out16((uint16_t)PM1a_ENABLE_REG, (uint8_t)(1 << 8));
|
||||
printf("[acpi]: Setting Power event listener...\n");
|
||||
|
||||
io_out16(PM1a_ENABLE_REG, (1 << 8));
|
||||
if (PM1b_ENABLE_REG) {
|
||||
io_out16((uint16_t)PM1b_ENABLE_REG, (uint8_t)(1 << 8));
|
||||
}
|
||||
|
157
driver/pci.c
Normal file
157
driver/pci.c
Normal file
@ -0,0 +1,157 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
227
driver/pcnet.c
Normal file
227
driver/pcnet.c
Normal file
@ -0,0 +1,227 @@
|
||||
#include "../include/pcnet.h"
|
||||
#include "../include/io.h"
|
||||
#include "../include/description_table.h"
|
||||
#include "../include/pci.h"
|
||||
#include "../include/timer.h"
|
||||
#include "../include/memory.h"
|
||||
#include "../include/printf.h"
|
||||
|
||||
uint8_t bus = 255, dev = 255, func = 255;
|
||||
|
||||
extern unsigned int PCI_ADDR_BASE;
|
||||
extern idt_ptr_t idt_ptr;
|
||||
static int io_base = 0;
|
||||
static uint8_t sendBufferDescMemory[2048 + 15];
|
||||
static uint8_t sendBuffers[8][2048 + 15];
|
||||
static uint8_t currentSendBuffer;
|
||||
static uint8_t recvBufferDescMemory[2048 + 15];
|
||||
static uint8_t recvBuffers[8][2048 + 15];
|
||||
static uint8_t currentRecvBuffer;
|
||||
uint8_t mac0, mac1, mac2, mac3, mac4, mac5;
|
||||
struct InitializationBlock initBlock;
|
||||
static struct BufferDescriptor* sendBufferDesc;
|
||||
static struct BufferDescriptor* recvBufferDesc;
|
||||
int recv = 0;
|
||||
|
||||
static void set_handler(int IRQ, int addr) {
|
||||
register_interrupt_handler(0x20 + IRQ, (int)addr);
|
||||
}
|
||||
|
||||
void into_32bitsRW() {
|
||||
io_out16(io_base + RAP16, BCR18);
|
||||
uint16_t tmp = io_in16(io_base + BDP16);
|
||||
tmp |= 0x80;
|
||||
io_out16(io_base + RAP16, BCR18);
|
||||
io_out16(io_base + BDP16, tmp);
|
||||
// 此时就处于32位读写模式了
|
||||
}
|
||||
void into_16bitsRW() {
|
||||
// 切换到16位读写模式 与切换到32位读写模式相反
|
||||
io_out32(io_base + RAP32, BCR18);
|
||||
uint32_t tmp = io_in32(io_base + BDP32);
|
||||
tmp &= ~0x80;
|
||||
io_out32(io_base + RAP32, BCR18);
|
||||
io_out32(io_base + BDP32, tmp);
|
||||
}
|
||||
|
||||
void reset_card() {
|
||||
// PCNET卡复位(约等于切换到16位读写模式
|
||||
io_in16(io_base + RESET16);
|
||||
io_out16(io_base + RESET16, 0x00);
|
||||
// 执行完后需等待(sleep(1))
|
||||
}
|
||||
|
||||
void Activate() {
|
||||
// 激活PCNET IRQ中断
|
||||
io_out16(io_base + RAP16, CSR0);
|
||||
io_out16(io_base + RDP16, 0x41);
|
||||
|
||||
io_out16(io_base + RAP16, CSR4);
|
||||
uint32_t temp = io_in16(io_base + RDP16);
|
||||
io_out16(io_base + RAP16, CSR4);
|
||||
io_out16(io_base + RDP16, temp | 0xc00);
|
||||
|
||||
io_out16(io_base + RAP16, CSR0);
|
||||
io_out16(io_base + RDP16, 0x42);
|
||||
}
|
||||
|
||||
int pcnet_find_card() {
|
||||
//printk("pcnet_find:");
|
||||
PCI_GET_DEVICE(CARD_VENDOR_ID, CARD_DEVICE_ID, &bus, &dev, &func);
|
||||
if (bus == 255) {
|
||||
//printk("false\n");
|
||||
return 0;
|
||||
}
|
||||
//printk("true");
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
static void init_Card_all() {
|
||||
currentSendBuffer = 0;
|
||||
currentRecvBuffer = 0;
|
||||
|
||||
// 获取MAC地址并保存
|
||||
mac0 = io_in8(io_base + APROM0);
|
||||
mac1 = io_in8(io_base + APROM1);
|
||||
mac2 = io_in8(io_base + APROM2);
|
||||
mac3 = io_in8(io_base + APROM3);
|
||||
mac4 = io_in8(io_base + APROM4);
|
||||
mac5 = io_in8(io_base + APROM5);
|
||||
// printk("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", mac0, mac1, mac2,
|
||||
// mac3,
|
||||
// mac4, mac5);
|
||||
// 这里约等于 into_16bitsRW();
|
||||
reset_card();
|
||||
clock_sleep(1);
|
||||
|
||||
io_out16(io_base + RAP16, BCR20);
|
||||
io_out16(io_base + BDP16, 0x102);
|
||||
io_out16(io_base + RAP16, CSR0);
|
||||
io_out16(io_base + RDP16, 0x0004); // 暂时停止所有传输(用于初始化PCNET网卡
|
||||
|
||||
// initBlock传输初始化(CSR1=IB地址低16位,CSR2=IB地址高16位)
|
||||
// &
|
||||
// Send/Recv环形缓冲区的初始化
|
||||
initBlock.mode = 0;
|
||||
initBlock.reserved1numSendBuffers =
|
||||
(0 << 4) | 3; // 高4位是reserved1 低4位是numSendBuffers
|
||||
initBlock.reserved2numRecvBuffers =
|
||||
(0 << 4) | 3; // 高4位是reserved2 低4位是numRecvBuffers
|
||||
initBlock.mac0 = mac0;
|
||||
initBlock.mac1 = mac1;
|
||||
initBlock.mac2 = mac2;
|
||||
initBlock.mac3 = mac3;
|
||||
initBlock.mac4 = mac4;
|
||||
initBlock.mac5 = mac5;
|
||||
initBlock.reserved3 = 0;
|
||||
initBlock.logicalAddress = 0;
|
||||
|
||||
sendBufferDesc =
|
||||
(struct BufferDescriptor*)(((uint32_t)&sendBufferDescMemory[0] + 15) &
|
||||
0xfffffff0);
|
||||
initBlock.sendBufferDescAddress = (uint32_t)sendBufferDesc;
|
||||
recvBufferDesc =
|
||||
(struct BufferDescriptor*)(((uint32_t)&recvBufferDescMemory[0] + 15) &
|
||||
0xfffffff0);
|
||||
initBlock.recvBufferDescAddress = (uint32_t)recvBufferDesc;
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
sendBufferDesc[i].address = (((uint32_t)&sendBuffers[i] + 15) & 0xfffffff0);
|
||||
sendBufferDesc[i].flags = 0xf7ff;
|
||||
sendBufferDesc[i].flags2 = 0;
|
||||
sendBufferDesc[i].avail = 0;
|
||||
|
||||
recvBufferDesc[i].address = (((uint32_t)&recvBuffers[i] + 15) & 0xfffffff0);
|
||||
recvBufferDesc[i].flags = 0xf7ff | 0x80000000;
|
||||
recvBufferDesc[i].flags2 = 0;
|
||||
recvBufferDesc[i].avail = 0;
|
||||
memclean(recvBufferDesc[i].address, 2048);
|
||||
}
|
||||
// CSR1,CSR2赋值(initBlock地址
|
||||
io_out16(io_base + RAP16, CSR1);
|
||||
io_out16(io_base + RDP16, (uint16_t)&initBlock);
|
||||
io_out16(io_base + RAP16, CSR2);
|
||||
io_out16(io_base + RDP16, (uint32_t)&initBlock >> 16);
|
||||
|
||||
Activate();
|
||||
|
||||
initBlock.logicalAddress = 0xFFFFFFFF;
|
||||
ip = 0xFFFFFFFF;
|
||||
gateway = 0xFFFFFFFF;
|
||||
submask = 0xFFFFFFFF;
|
||||
dns = 0xFFFFFFFF;
|
||||
dhcp_discovery(&mac0);
|
||||
while (gateway == 0xFFFFFFFF && submask == 0xFFFFFFFF && dns == 0xFFFFFFFF &&
|
||||
ip == 0xFFFFFFFF) {
|
||||
initBlock.logicalAddress = ip;
|
||||
}
|
||||
|
||||
// 初始化ARP表
|
||||
|
||||
|
||||
// DNSParseIP("baidu.com");
|
||||
|
||||
// UDPProviderSend(0x761ff8d7, initBlock.logicalAddress, 52949, 38,
|
||||
// "来自Powerint DOS 386的消息:我是周志昊!!!", strlen("来自Powerint DOS
|
||||
// 386的消息:我是周志昊!!!"));
|
||||
}
|
||||
*/
|
||||
void init_pcnet_card() {
|
||||
printf("[\035kernel\036]: Loading pcnet driver.\n");
|
||||
// 允许PCNET网卡产生中断
|
||||
// 1.注册中断
|
||||
register_interrupt_handler(pci_get_drive_irq(bus, dev, func),PCNET_IRQ);
|
||||
// 2,写COMMAND和STATUS寄存器
|
||||
uint32_t conf = pci_read_command_status(bus, dev, func);
|
||||
conf &= 0xffff0000; // 保留STATUS寄存器,清除COMMAND寄存器
|
||||
conf |= 0x7; // 设置第0~2位(允许PCNET网卡产生中断
|
||||
pci_write_command_status(bus, dev, func, conf);
|
||||
io_base = pci_get_port_base(bus, dev, func);
|
||||
//init_Card_all();
|
||||
}
|
||||
|
||||
void PCNET_IRQ(registers_t *reg) {
|
||||
|
||||
io_out16(io_base + RAP16, CSR0);
|
||||
uint16_t temp = io_in16(io_base + RDP16);
|
||||
|
||||
if ((temp & 0x0400) == 0x0400)
|
||||
Recv();
|
||||
|
||||
io_out16(io_base + RAP16, CSR0);
|
||||
io_out16(io_base + RDP16, temp); // 通知PCNET网卡 中断处理完毕
|
||||
|
||||
if ((temp & 0x0100) == 0x0100)
|
||||
printf("PCNET INIT DONE\n");
|
||||
return;
|
||||
}
|
||||
|
||||
void Recv() {
|
||||
recv = 1;
|
||||
//printk("\nPCNET RECV: ");
|
||||
for (; (recvBufferDesc[currentRecvBuffer].flags & 0x80000000) == 0;
|
||||
currentRecvBuffer = (currentRecvBuffer + 1) % 8) {
|
||||
if (!(recvBufferDesc[currentRecvBuffer].flags & 0x40000000) &&
|
||||
(recvBufferDesc[currentRecvBuffer].flags & 0x03000000) == 0x03000000) {
|
||||
uint32_t size = recvBufferDesc[currentRecvBuffer].flags & 0xfff;
|
||||
if (size > 128)
|
||||
size -= 4;
|
||||
|
||||
uint8_t* buffer = (uint8_t*)(recvBufferDesc[currentRecvBuffer].address);
|
||||
for (int i = 0; i < (size > 128 ? 128 : size); i++) {
|
||||
//printk("%02x ", buffer[i]);
|
||||
}
|
||||
//printk("\n");
|
||||
}
|
||||
recv = 0;
|
||||
currentRecvBuffer = 0;
|
||||
//TODO Card_Recv_Handler(recvBufferDesc[currentRecvBuffer].address);
|
||||
|
||||
memclean(recvBufferDesc[currentRecvBuffer].address, 2048);
|
||||
recvBufferDesc[currentRecvBuffer].flags2 = 0;
|
||||
recvBufferDesc[currentRecvBuffer].flags = 0x8000f7ff;
|
||||
}
|
||||
currentRecvBuffer = 0;
|
||||
|
||||
}
|
||||
|
15
driver/rtl8139.c
Normal file
15
driver/rtl8139.c
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* rtl8139.c
|
||||
* Realtek rtl8139 网卡驱动
|
||||
* Copyright (C) zhouzhihao 2023
|
||||
*/
|
||||
|
||||
#include "../include/rtl8139.h"
|
||||
|
||||
static uint8_t bus, dev, func;
|
||||
static uint32_t io_base;
|
||||
static uint8_t *sendBuffer[4];
|
||||
static uint8_t *recvBuffer;
|
||||
static uint8_t currentSendBuffer;
|
||||
|
||||
extern uint8_t mac0, mac1, mac2, mac3, mac4, mac5;
|
46
driver/vbe.c
46
driver/vbe.c
@ -1,45 +1,17 @@
|
||||
#include "../include/graphics.h"
|
||||
#include "../include/io.h"
|
||||
|
||||
unsigned int vesa_fb_width, vesa_fb_height, vesa_fb_bpp, vesa_fb_pitch;
|
||||
uint8_t *vesa_fb_addr;
|
||||
extern int status;
|
||||
|
||||
void putPix(unsigned int x, unsigned int y, uint32_t color) {
|
||||
if (status != 1)
|
||||
return;
|
||||
color_rgba col;
|
||||
col.r = color >> 16;
|
||||
col.g = color >> 8;
|
||||
col.b = color;
|
||||
col.a = 0xFF;
|
||||
|
||||
if (x >= vesa_fb_width || y >= vesa_fb_height)
|
||||
return;
|
||||
unsigned where = x * (vesa_fb_bpp / 8) + y * vesa_fb_pitch;
|
||||
vesa_fb_addr[where + 0] = col.b;
|
||||
vesa_fb_addr[where + 1] = col.g;
|
||||
vesa_fb_addr[where + 2] = col.r;
|
||||
int isVBEDisplayMode(uint16_t vbe_mode_info) {
|
||||
if (vbe_mode_info & (1 << 12)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void initVBE(multiboot_t *mboot) {
|
||||
vesa_fb_addr = (uint8_t * )(
|
||||
int)(mboot->framebuffer_addr);
|
||||
vesa_fb_pitch = mboot->framebuffer_pitch;
|
||||
vesa_fb_bpp = mboot->framebuffer_bpp;
|
||||
vesa_fb_width = mboot->framebuffer_width;
|
||||
vesa_fb_height = mboot->framebuffer_height;
|
||||
|
||||
printf("[\035VBE driver\036]: Framebuffer address: 0x%08x\n",vesa_fb_addr);
|
||||
printf("[\035VBE driver\036]: Screen Size: width:%d - height:%d\n",mboot->framebuffer_width,mboot->framebuffer_height);
|
||||
// TODO: insert into devtable
|
||||
}
|
||||
|
||||
|
||||
void vbe_putchar(char c) {
|
||||
|
||||
}
|
||||
|
||||
void vbe_clear() {
|
||||
|
||||
if(isVBEDisplayMode(mboot->vbe_mode_info)){
|
||||
printf("[\035kernel\036]: Graphics mode: \037VBE\036\n");
|
||||
} else printf("[\035kernel\036]: Graphics mode: \037VGA\036\n");
|
||||
}
|
||||
|
113
driver/vdisk.c
Normal file
113
driver/vdisk.c
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Plants-OS VDiskDriver
|
||||
* Copyright by min0911.
|
||||
*/
|
||||
|
||||
#include "../include/vdisk.h"
|
||||
#include "../include/printf.h"
|
||||
|
||||
int getReadyDisk();
|
||||
|
||||
vdisk vdisk_ctl[10];
|
||||
|
||||
int init_vdisk() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
vdisk_ctl[i].flag = 0; // 设置为未使用
|
||||
}
|
||||
printf("[\035kernel\036]: VDisk driver load success!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int register_vdisk(vdisk vd) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (!vdisk_ctl[i].flag) {
|
||||
vdisk_ctl[i] = vd; // 找到了!
|
||||
return i + ('A'); // 注册成功,返回drive
|
||||
}
|
||||
}
|
||||
printf("[vdisk]not found\n");
|
||||
return 0; // 注册失败
|
||||
}
|
||||
|
||||
int logout_vdisk(char drive) {
|
||||
int indx = drive - ('A');
|
||||
if (indx > 10) {
|
||||
return 0; // 失败
|
||||
}
|
||||
if (vdisk_ctl[indx].flag) {
|
||||
vdisk_ctl[indx].flag = 0; // 设置为没有
|
||||
return 1; // 成功
|
||||
} else {
|
||||
return 0; // 失败
|
||||
}
|
||||
}
|
||||
|
||||
int rw_vdisk(char drive, unsigned int lba, unsigned char *buffer,
|
||||
unsigned int number, int read) {
|
||||
int indx = drive - ('A');
|
||||
if (indx > 10) {
|
||||
return 0; // 失败
|
||||
}
|
||||
if (vdisk_ctl[indx].flag) {
|
||||
if (read) {
|
||||
vdisk_ctl[indx].Read(drive, buffer, number, lba);
|
||||
//for(;;);
|
||||
} else {
|
||||
vdisk_ctl[indx].Write(drive, buffer, number, lba);
|
||||
}
|
||||
return 1; // 成功
|
||||
} else {
|
||||
return 0; // 失败
|
||||
}
|
||||
}
|
||||
|
||||
int have_vdisk(char drive) {
|
||||
int indx = drive - 'A';
|
||||
if (indx > 10) {
|
||||
return 0; // 失败
|
||||
}
|
||||
if (vdisk_ctl[indx].flag) {
|
||||
return 1; // 成功
|
||||
} else {
|
||||
return 0; // 失败
|
||||
}
|
||||
}
|
||||
|
||||
void Disk_Read(unsigned int lba, unsigned int number, void *buffer,
|
||||
char drive) {
|
||||
if (have_vdisk(drive)) {
|
||||
for (int i = 0; i < number; i += SECTORS_ONCE) {
|
||||
int sectors =
|
||||
((number - i) >= SECTORS_ONCE) ? SECTORS_ONCE : (number - i);
|
||||
rw_vdisk(drive, lba + i, buffer + i * 512, sectors, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int disk_Size(char drive) {
|
||||
unsigned char drive1 = drive;
|
||||
if (have_vdisk(drive1)) {
|
||||
int indx = drive1 - 'A';
|
||||
return vdisk_ctl[indx].size;
|
||||
} else {
|
||||
print("Disk Not Ready.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DiskReady(char drive) { return have_vdisk(drive); }
|
||||
|
||||
int getReadyDisk() { return 0; }
|
||||
|
||||
void Disk_Write(unsigned int lba, unsigned int number, void *buffer,
|
||||
char drive) {
|
||||
if (have_vdisk(drive)) {
|
||||
for (int i = 0; i < number; i += SECTORS_ONCE) {
|
||||
int sectors =
|
||||
((number - i) >= SECTORS_ONCE) ? SECTORS_ONCE : (number - i);
|
||||
rw_vdisk(drive, lba + i, buffer + i * 512, sectors, 0);
|
||||
}
|
||||
}
|
||||
}
|
18
driver/vga.c
18
driver/vga.c
@ -47,10 +47,6 @@ void vga_install(void) {
|
||||
}
|
||||
|
||||
void vga_clear() {
|
||||
if(status){
|
||||
vbe_clear();
|
||||
return;
|
||||
}
|
||||
for (size_t y = 0; y < VGA_HEIGHT; y++) {
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++) {
|
||||
const size_t index = y * VGA_WIDTH + x;
|
||||
@ -80,10 +76,6 @@ void vga_putentryat(char c, uint8_t color, size_t x, size_t y) {
|
||||
}
|
||||
|
||||
void vga_putchar(char c) {
|
||||
if(status){
|
||||
vbe_putchar(c);
|
||||
return;
|
||||
}
|
||||
uint8_t attributeByte = terminal_color; // 黑底白字
|
||||
uint16_t attribute = attributeByte << 8;
|
||||
uint16_t *location;
|
||||
@ -148,13 +140,3 @@ void vga_write(const char *data, size_t size) {
|
||||
void vga_writestring(const char *data) {
|
||||
vga_write(data, strlen(data));
|
||||
}
|
||||
|
||||
void printf(const char *formet, ...) {
|
||||
int len;
|
||||
va_list ap;
|
||||
va_start(ap, formet);
|
||||
char *buf[1024] = {0};
|
||||
len = vsprintf(buf, formet, ap);
|
||||
vga_writestring(buf);
|
||||
va_end(ap);
|
||||
}
|
@ -11,6 +11,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef int bool;
|
||||
|
||||
void assert(int b,char* message);
|
||||
size_t strlen(const char* str);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
|
@ -126,4 +126,6 @@ void write_tss(int32_t num, uint16_t ss0, uint32_t esp0);
|
||||
void gdt_install();
|
||||
void idt_install();
|
||||
|
||||
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags);
|
||||
|
||||
#endif //CRASHPOWEROS_DESCRIPTION_TABLE_H
|
||||
|
93
include/fat.h
Normal file
93
include/fat.h
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef CRASHPOWEROS_FAT_H
|
||||
#define CRASHPOWEROS_FAT_H
|
||||
|
||||
#include "../include/common.h"
|
||||
|
||||
struct FAT_CACHE {
|
||||
unsigned int ADR_DISKIMG;
|
||||
struct FAT_FILEINFO *root_directory;
|
||||
struct LIST *directory_list;
|
||||
struct LIST *directory_max_list;
|
||||
struct LIST *directory_clustno_list;
|
||||
int *fat;
|
||||
int FatMaxTerms;
|
||||
unsigned int ClustnoBytes;
|
||||
unsigned short RootMaxFiles;
|
||||
unsigned int RootDictAddress;
|
||||
unsigned int FileDataAddress;
|
||||
unsigned int imgTotalSize;
|
||||
unsigned short SectorBytes;
|
||||
unsigned int Fat1Address, Fat2Address;
|
||||
unsigned char *FatClustnoFlags;
|
||||
int type;
|
||||
};
|
||||
typedef struct {
|
||||
struct FAT_CACHE dm;
|
||||
struct FAT_FILEINFO *dir;
|
||||
} fat_cache;
|
||||
|
||||
#define get_dm(vfs) ((fat_cache *)(vfs->cache))->dm
|
||||
#define get_now_dir(vfs) ((fat_cache *)(vfs->cache))->dir
|
||||
#define get_clustno(high, low) (high << 16) | (low & 0xffff)
|
||||
#define clustno_end(type) 0xfffffff & ((((1 << (type - 1)) - 1) << 1) + 1)
|
||||
|
||||
struct FAT_FILEINFO {
|
||||
unsigned char name[8], ext[3], type;
|
||||
char reserve;
|
||||
unsigned char create_time_tenth;
|
||||
unsigned short create_time, create_date, access_date, clustno_high;
|
||||
unsigned short update_time, update_date, clustno_low;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
typedef struct FILE {
|
||||
unsigned int mode;
|
||||
unsigned int fileSize;
|
||||
unsigned char *buffer;
|
||||
unsigned int bufferSize;
|
||||
unsigned int p;
|
||||
char *name;
|
||||
} FILE;
|
||||
|
||||
typedef enum { FLE, DIR, RDO, HID, SYS } ftype;
|
||||
typedef struct {
|
||||
char name[255];
|
||||
ftype type;
|
||||
unsigned int size;
|
||||
unsigned short year, month, day;
|
||||
unsigned short hour, minute;
|
||||
} vfs_file;
|
||||
|
||||
typedef struct vfs_t {
|
||||
struct List *path;
|
||||
void *cache;
|
||||
char FSName[255];
|
||||
int disk_number;
|
||||
uint8_t drive; // 大写(必须)
|
||||
vfs_file *(*FileInfo)(struct vfs_t *vfs, char *filename);
|
||||
struct List *(*ListFile)(struct vfs_t *vfs, char *dictpath);
|
||||
bool (*ReadFile)(struct vfs_t *vfs, char *path, char *buffer);
|
||||
bool (*WriteFile)(struct vfs_t *vfs, char *path, char *buffer, int size);
|
||||
bool (*DelFile)(struct vfs_t *vfs, char *path);
|
||||
bool (*DelDict)(struct vfs_t *vfs, char *path);
|
||||
bool (*CreateFile)(struct vfs_t *vfs, char *filename);
|
||||
bool (*CreateDict)(struct vfs_t *vfs, char *filename);
|
||||
bool (*RenameFile)(struct vfs_t *vfs, char *filename, char *filename_of_new);
|
||||
bool (*Attrib)(struct vfs_t *vfs, char *filename, ftype type);
|
||||
bool (*Format)(uint8_t disk_number);
|
||||
void (*InitFs)(struct vfs_t *vfs, uint8_t disk_number);
|
||||
void (*DeleteFs)(struct vfs_t *vfs);
|
||||
bool (*Check)(uint8_t disk_number);
|
||||
bool (*cd)(struct vfs_t *vfs, char *dictName);
|
||||
int (*FileSize)(struct vfs_t *vfs, char *filename);
|
||||
void (*CopyCache)(struct vfs_t *dest, struct vfs_t *src);
|
||||
int flag;
|
||||
} vfs_t;
|
||||
/*
|
||||
void read_fat(unsigned char *img, int *fat, unsigned char *ff, int max,int type);
|
||||
int get_directory_max(struct FAT_FILEINFO *directory, vfs_t *vfs);
|
||||
void file_loadfile(int clustno, int size, char *buf, int *fat, vfs_t *vfs);
|
||||
void file_savefat(int *fat, int clustno, int length, vfs_t *vfs);
|
||||
*/
|
||||
|
||||
#endif
|
@ -69,13 +69,6 @@ struct color_rgba {
|
||||
uint8_t a;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned short di, si, bp, sp, bx, dx, cx, ax;
|
||||
unsigned short gs, fs, es, ds, eflags;
|
||||
} regs16_t;
|
||||
|
||||
|
||||
|
||||
typedef struct color_rgba color_rgba;
|
||||
|
||||
uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg);
|
||||
@ -100,14 +93,4 @@ void vga_clear();
|
||||
|
||||
void move_cursor();
|
||||
|
||||
void printf(const char *formet, ...);
|
||||
|
||||
void vbe_putchar(char c);
|
||||
|
||||
void vbe_clear();
|
||||
|
||||
void initVBE(multiboot_t *mboot);
|
||||
|
||||
void putPix(unsigned int x, unsigned int y, uint32_t color);
|
||||
|
||||
#endif
|
@ -4,6 +4,11 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned short di, si, bp, sp, bx, dx, cx, ax;
|
||||
unsigned short gs, fs, es, ds, eflags;
|
||||
} regs16_t;
|
||||
|
||||
struct tty {
|
||||
int using1; // 使用标志
|
||||
void *vram; // 显存(也可以当做图层)
|
||||
|
24
include/list.h
Normal file
24
include/list.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef CRASHPOWEROS_LIST_H
|
||||
#define CRASHPOWEROS_LIST_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct ListCtl {
|
||||
struct List *start;
|
||||
struct List *end;
|
||||
int all;
|
||||
};
|
||||
struct List {
|
||||
struct ListCtl *ctl;
|
||||
struct List *prev;
|
||||
uintptr_t val;
|
||||
struct List *next;
|
||||
};
|
||||
|
||||
typedef struct List List;
|
||||
|
||||
struct List* FindForCount(size_t count, struct List* Obj);
|
||||
int GetLastCount(struct List* Obj);
|
||||
|
||||
#endif
|
@ -83,4 +83,6 @@ uint32_t kmalloc_ap(uint32_t size, uint32_t *phys);
|
||||
|
||||
void init_page();
|
||||
|
||||
void memclean(char *s, int len);
|
||||
|
||||
#endif //CRASHPOWEROS_MEMORY_H
|
||||
|
@ -18,14 +18,6 @@
|
||||
|
||||
typedef struct multiboot_t {
|
||||
uint32_t flags; // Multiboot 的版本信息
|
||||
/**
|
||||
* 从 BIOS 获知的可用内存
|
||||
*
|
||||
* mem_lower和mem_upper分别指出了低端和高端内存的大小,单位是K。
|
||||
* 低端内存的首地址是0,高端内存的首地址是1M。
|
||||
* 低端内存的最大可能值是640K。
|
||||
* 高端内存的最大可能值是最大值减去1M。但并不保证是这个值。
|
||||
*/
|
||||
uint32_t mem_lower;
|
||||
uint32_t mem_upper;
|
||||
|
||||
|
57
include/pci.h
Normal file
57
include/pci.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef CRASHPOWEROS_PCI_H
|
||||
#define CRASHPOWEROS_PCI_H
|
||||
|
||||
#define PCI_COMMAND_PORT 0xCF8
|
||||
#define PCI_DATA_PORT 0xCFC
|
||||
#define mem_mapping 0
|
||||
#define input_output 1
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct base_address_register {
|
||||
int prefetchable;
|
||||
uint8_t* address;
|
||||
uint32_t size;
|
||||
int type;
|
||||
} base_address_register;
|
||||
|
||||
struct pci_config_space_public {
|
||||
unsigned short VendorID;
|
||||
unsigned short DeviceID;
|
||||
unsigned short Command;
|
||||
unsigned short Status;
|
||||
unsigned char RevisionID;
|
||||
unsigned char ProgIF;
|
||||
unsigned char SubClass;
|
||||
unsigned char BaseClass;
|
||||
unsigned char CacheLineSize;
|
||||
unsigned char LatencyTimer;
|
||||
unsigned char HeaderType;
|
||||
unsigned char BIST;
|
||||
unsigned int BaseAddr[6];
|
||||
unsigned int CardbusCIS;
|
||||
unsigned short SubVendorID;
|
||||
unsigned short SubSystemID;
|
||||
unsigned int ROMBaseAddr;
|
||||
unsigned char CapabilitiesPtr;
|
||||
unsigned char Reserved[3];
|
||||
unsigned int Reserved1;
|
||||
unsigned char InterruptLine;
|
||||
unsigned char InterruptPin;
|
||||
unsigned char MinGrant;
|
||||
unsigned char MaxLatency;
|
||||
};
|
||||
|
||||
uint32_t pci_read_command_status(uint8_t bus, uint8_t slot, uint8_t func);
|
||||
void PCI_GET_DEVICE(uint16_t vendor_id, uint16_t device_id, uint8_t* bus, uint8_t* slot, uint8_t* func);
|
||||
uint32_t pci_get_port_base(uint8_t bus, uint8_t slot, uint8_t func);
|
||||
uint8_t pci_get_drive_irq(uint8_t bus, uint8_t slot, uint8_t func);
|
||||
void pci_write_command_status(uint8_t bus, uint8_t slot, uint8_t func, uint32_t value);
|
||||
void write_pci(uint8_t bus, uint8_t device, uint8_t function, uint8_t registeroffset, uint32_t value);
|
||||
uint32_t read_bar_n(uint8_t bus, uint8_t device, uint8_t function, uint8_t bar_n);
|
||||
uint32_t read_pci(uint8_t bus, uint8_t device, uint8_t function, uint8_t registeroffset);
|
||||
base_address_register get_base_address_register(uint8_t bus, uint8_t device, uint8_t function, uint8_t bar);
|
||||
void pci_config(unsigned int bus, unsigned int f, unsigned int equipment, unsigned int adder);
|
||||
void init_pci();
|
||||
|
||||
#endif
|
62
include/pcnet.h
Normal file
62
include/pcnet.h
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef CRASHPOWEROS_PCNET_H
|
||||
#define CRASHPOWEROS_PCNET_H
|
||||
|
||||
#define CARD_VENDOR_ID 0x1022
|
||||
#define CARD_DEVICE_ID 0x2000
|
||||
// 为了使用该寄存器,必须将RAP设置为这些值
|
||||
#define CSR0 0
|
||||
#define CSR1 1
|
||||
#define CSR2 2
|
||||
#define CSR3 3
|
||||
#define CSR4 4
|
||||
#define BCR18 18
|
||||
#define BCR20 20
|
||||
// 16位I/O端口(或到I/O空间开始的偏移)。
|
||||
#define APROM0 0x00
|
||||
#define APROM1 0x01
|
||||
#define APROM2 0x02
|
||||
#define APROM3 0x03
|
||||
#define APROM4 0x04
|
||||
#define APROM5 0x05
|
||||
// 16位读写模式下
|
||||
#define RDP16 0x10
|
||||
#define RAP16 0x12
|
||||
#define RESET16 0x14
|
||||
#define BDP16 0x16
|
||||
// 32位读写模式下
|
||||
#define RDP32 0x10
|
||||
#define RAP32 0x14
|
||||
#define RESET32 0x18
|
||||
#define BDP32 0x1c
|
||||
|
||||
#include <stdint.h>
|
||||
#include "isr.h"
|
||||
|
||||
struct InitializationBlock {
|
||||
uint16_t mode;
|
||||
uint8_t reserved1numSendBuffers;
|
||||
uint8_t reserved2numRecvBuffers;
|
||||
uint8_t mac0, mac1, mac2, mac3, mac4, mac5;
|
||||
uint16_t reserved3;
|
||||
uint64_t logicalAddress;
|
||||
uint32_t recvBufferDescAddress;
|
||||
uint32_t sendBufferDescAddress;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct BufferDescriptor {
|
||||
uint32_t address;
|
||||
uint32_t flags;
|
||||
uint32_t flags2;
|
||||
uint32_t avail;
|
||||
} __attribute__((packed));
|
||||
|
||||
void into_32bitsRW();
|
||||
void into_16bitsRW();
|
||||
void reset_card();
|
||||
void Activate();
|
||||
int pcnet_find_card();
|
||||
void init_pcnet_card();
|
||||
void PCNET_IRQ(registers_t *reg);
|
||||
void Recv();
|
||||
|
||||
#endif
|
@ -5,4 +5,9 @@
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int vsprintf(char *buf, const char *fmt, va_list args);
|
||||
int sprintf(char *buf, const char *fmt, ...);
|
||||
void printf(const char *formet, ...);
|
||||
void print(char *message);
|
||||
|
||||
#endif //CRASHPOWEROS_PRINTF_H
|
||||
|
26
include/rtl8139.h
Normal file
26
include/rtl8139.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef CRASHPOWEROS_RTL8139_H
|
||||
#define CRASHPOWEROS_RTL8139_H
|
||||
|
||||
#define CARD_VENDOR_ID 0x10EC
|
||||
#define CARD_DEVICE_ID 0x8139
|
||||
#define MAC0 0x00
|
||||
#define MAC1 0x01
|
||||
#define MAC2 0x02
|
||||
#define MAC3 0x03
|
||||
#define MAC4 0x04
|
||||
#define MAC5 0x05
|
||||
#define MAR 0x08
|
||||
#define RBSTART 0x30
|
||||
#define CAPR 0x38
|
||||
#define CMD 0x37
|
||||
#define IMR 0x3C
|
||||
#define ISR 0x3E
|
||||
#define CONFIG_1 0x52
|
||||
#define TCR 0x40
|
||||
#define RCR 0x44
|
||||
#define TSAD0 0x20
|
||||
#define TSD0 0x10
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#endif
|
46
include/vdisk.h
Normal file
46
include/vdisk.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef CRASHPOWEROS_VDISK_H
|
||||
#define CRASHPOWEROS_VDISK_H
|
||||
|
||||
#define SECTORS_ONCE 8
|
||||
|
||||
typedef struct {
|
||||
void (*Read)(char drive, unsigned char *buffer, unsigned int number,
|
||||
unsigned int lba);
|
||||
void (*Write)(char drive, unsigned char *buffer, unsigned int number,
|
||||
unsigned int lba);
|
||||
int flag;
|
||||
unsigned int size; // 大小
|
||||
char DriveName[50];
|
||||
} vdisk;
|
||||
|
||||
struct IDEHardDiskInfomationBlock {
|
||||
char reserve1[2];
|
||||
unsigned short CylinesNum;
|
||||
char reserve2[2];
|
||||
unsigned short HeadersNum;
|
||||
unsigned short TrackBytes;
|
||||
unsigned short SectorBytes;
|
||||
unsigned short TrackSectors;
|
||||
char reserve3[6];
|
||||
char OEM[20];
|
||||
char reserve4[2];
|
||||
unsigned short BuffersBytes;
|
||||
unsigned short EECCheckSumLength;
|
||||
char Version[8];
|
||||
char ID[40];
|
||||
};
|
||||
|
||||
int init_vdisk();
|
||||
int register_vdisk(vdisk vd);
|
||||
int logout_vdisk(char drive);
|
||||
int rw_vdisk(char drive, unsigned int lba, unsigned char *buffer,
|
||||
unsigned int number, int read);
|
||||
int have_vdisk(char drive);
|
||||
void Disk_Read(unsigned int lba, unsigned int number, void *buffer,
|
||||
char drive);
|
||||
int disk_Size(char drive);
|
||||
int DiskReady(char drive);
|
||||
void Disk_Write(unsigned int lba, unsigned int number, void *buffer,
|
||||
char drive);
|
||||
|
||||
#endif
|
380
kernel/fat.c
Normal file
380
kernel/fat.c
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* PlantsOS fat FileSystem
|
||||
* Copyright by min0911
|
||||
*/
|
||||
#include "../include/vdisk.h"
|
||||
#include "../include/fat.h"
|
||||
#include "../include/memory.h"
|
||||
#include "../include/list.h"
|
||||
#include "../include/common.h"
|
||||
/*
|
||||
static inline int get_fat_date(unsigned short year, unsigned short month,
|
||||
unsigned short day) {
|
||||
year -= 1980;
|
||||
unsigned short date = 0;
|
||||
date |= (year & 0x7f) << 9;
|
||||
date |= (month & 0x0f) << 5;
|
||||
date |= (day & 0x1f);
|
||||
return date;
|
||||
}
|
||||
static inline int get_fat_time(unsigned short hour, unsigned short minute) {
|
||||
unsigned short time = 0;
|
||||
time |= (hour & 0x1f) << 11;
|
||||
time |= (minute & 0x3f) << 5;
|
||||
return time;
|
||||
}
|
||||
|
||||
void read_fat(unsigned char *img, int *fat, unsigned char *ff, int max,
|
||||
int type) {
|
||||
if (type == 12) {
|
||||
for (int i = 0, j = 0; i < max; i += 2) {
|
||||
fat[i + 0] = (img[j + 0] | img[j + 1] << 8) & 0xfff;
|
||||
fat[i + 1] = (img[j + 1] >> 4 | img[j + 2] << 4) & 0xfff;
|
||||
j += 3;
|
||||
}
|
||||
// 保留簇
|
||||
ff[0] = 1;
|
||||
ff[1] = 1;
|
||||
for (int i = 1; i < max; i++) {
|
||||
if (fat[i] > 0 && fat[i] < 0xff0) {
|
||||
ff[fat[i]] = 1;
|
||||
} else if (fat[i] >= 0xff0 && fat[i] <= 0xfff) {
|
||||
ff[i + 1] = 1;
|
||||
}
|
||||
}
|
||||
} else if (type == 16) {
|
||||
unsigned short *p = (unsigned short *)img;
|
||||
for (int i = 0; i != max; i++) {
|
||||
fat[i] = p[i];
|
||||
}
|
||||
ff[0] = 1;
|
||||
ff[1] = 1;
|
||||
for (int i = 1; i < max; i++) {
|
||||
if (fat[i] > 0 && fat[i] < 0xfff0) {
|
||||
ff[fat[i]] = 1;
|
||||
} else if (fat[i] >= 0xfff0 && fat[i] <= 0xffff) {
|
||||
ff[i + 1] = 1;
|
||||
}
|
||||
}
|
||||
} else if (type == 32) {
|
||||
unsigned int *p = (unsigned int *)img;
|
||||
for (int i = 0; i != max; i++) {
|
||||
fat[i] = p[i];
|
||||
}
|
||||
ff[0] = 1;
|
||||
ff[1] = 1;
|
||||
for (int i = 1; i < max; i++) {
|
||||
if (fat[i] > 0 && fat[i] < 0xffffff0) {
|
||||
ff[fat[i]] = 1;
|
||||
} else if (fat[i] >= 0xffffff0 && fat[i] <= 0xfffffff) {
|
||||
ff[i + 1] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int get_directory_max(struct FAT_FILEINFO *directory, vfs_t *vfs) {
|
||||
if (directory == get_dm(vfs).root_directory) {
|
||||
return get_dm(vfs).RootMaxFiles;
|
||||
}
|
||||
for (int i = 1; FindForCount(i, get_dm(vfs).directory_list) != NULL; i++) {
|
||||
struct List *l = FindForCount(i, get_dm(vfs).directory_list);
|
||||
if ((struct FAT_FILEINFO *)l->val == directory) {
|
||||
return (int)FindForCount(i, get_dm(vfs).directory_max_list)->val;
|
||||
}
|
||||
}
|
||||
}
|
||||
void file_loadfile(int clustno, int size, char *buf, int *fat, vfs_t *vfs) {
|
||||
if (!size) {
|
||||
return;
|
||||
}
|
||||
void *img = kmalloc(((size - 1) / get_dm(vfs).ClustnoBytes + 1) *
|
||||
get_dm(vfs).ClustnoBytes);
|
||||
for (int i = 0; i != (size - 1) / get_dm(vfs).ClustnoBytes + 1; i++) {
|
||||
uint32_t sec = (get_dm(vfs).FileDataAddress +
|
||||
(clustno - 2) * get_dm(vfs).ClustnoBytes) /
|
||||
get_dm(vfs).SectorBytes;
|
||||
Disk_Read(sec, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
|
||||
img + i * get_dm(vfs).ClustnoBytes, vfs->disk_number);
|
||||
clustno = fat[clustno];
|
||||
}
|
||||
memcpy((void *)buf, img, size);
|
||||
kfree(img, ((size - 1) / get_dm(vfs).SectorBytes + 1) *
|
||||
get_dm(vfs).SectorBytes);
|
||||
return;
|
||||
}
|
||||
|
||||
void file_savefile(int clustno, int size, char *buf, int *fat,
|
||||
unsigned char *ff, vfs_t *vfs) {
|
||||
uint32_t clustall = 0;
|
||||
int tmp = clustno;
|
||||
int end = clustno_end(get_dm(vfs).type);
|
||||
while (fat[clustno] != end) { // 计算文件占多少Fat项 Fat项 = 大小 / 簇大小 + 1
|
||||
clustno = fat[clustno];
|
||||
clustall++;
|
||||
}
|
||||
int old_clustno = clustno;
|
||||
clustno = tmp;
|
||||
int alloc_size;
|
||||
if (size >
|
||||
(clustall + 1) *
|
||||
get_dm(vfs).ClustnoBytes) { // 新大小 > (旧大小 / 簇大小 + 1) * 簇大小
|
||||
// 请求内存大小 = (新大小 / 簇大小 + 1) * 簇大小
|
||||
alloc_size =
|
||||
((size - 1) / get_dm(vfs).ClustnoBytes + 1) * get_dm(vfs).ClustnoBytes;
|
||||
// 分配Fat(这里需要在写盘前分配)
|
||||
for (int size1 = size; size1 > ((clustall + 1) * get_dm(vfs).ClustnoBytes);
|
||||
size1 -= get_dm(vfs).ClustnoBytes) {
|
||||
for (int i = 0; i != get_dm(vfs).FatMaxTerms; i++) {
|
||||
if (!ff[i]) {
|
||||
fat[old_clustno] = i;
|
||||
old_clustno = i;
|
||||
ff[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fat[old_clustno] = end; // 结尾Fat
|
||||
ff[old_clustno] = true;
|
||||
} else if (size <=
|
||||
(clustall + 1) *
|
||||
get_dm(vfs).ClustnoBytes) { // 新大小 <= (旧大小 / 簇大小
|
||||
// + 1) * 簇大小
|
||||
// 请求内存大小 = (旧大小 / 簇大小 + 1) * 簇大小
|
||||
alloc_size = (clustall + 1) * get_dm(vfs).ClustnoBytes;
|
||||
// 这里不分配Fat的原因是要清空更改后多余的数据
|
||||
}
|
||||
void *img = kmalloc(alloc_size);
|
||||
clean((char *)img, alloc_size);
|
||||
memcpy(img, buf, size); // 把要写入的数据复制到新请求的内存地址
|
||||
for (int i = 0; i != (alloc_size / get_dm(vfs).ClustnoBytes); i++) {
|
||||
uint32_t sec = (get_dm(vfs).FileDataAddress +
|
||||
(clustno - 2) * get_dm(vfs).ClustnoBytes) /
|
||||
get_dm(vfs).SectorBytes;
|
||||
Disk_Write(sec, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
|
||||
img + i * get_dm(vfs).ClustnoBytes, vfs->disk_number);
|
||||
clustno = fat[clustno];
|
||||
}
|
||||
kfree(img, alloc_size);
|
||||
if (size <
|
||||
clustall *
|
||||
get_dm(vfs).ClustnoBytes) { // 新大小 < (旧大小 / 簇大小) * 簇大小
|
||||
// 分配Fat(中间情况没必要分配)
|
||||
int i = old_clustno;
|
||||
for (int size1 = clustall * get_dm(vfs).ClustnoBytes; size1 > size;
|
||||
size1 -= get_dm(vfs).ClustnoBytes) {
|
||||
fat[i] = 0;
|
||||
ff[i] = 0;
|
||||
for (int j = 0; j != get_dm(vfs).FatMaxTerms; j++) {
|
||||
if (fat[j] == i) {
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
old_clustno = i;
|
||||
fat[old_clustno] = end;
|
||||
ff[old_clustno] = 1;
|
||||
}
|
||||
file_savefat(fat, 0, get_dm(vfs).FatMaxTerms, vfs);
|
||||
}
|
||||
|
||||
void file_savefat(int *fat, int clustno, int length, vfs_t *vfs) {
|
||||
unsigned char *img = get_dm(vfs).ADR_DISKIMG + get_dm(vfs).Fat1Address;
|
||||
int size, sec;
|
||||
if (get_dm(vfs).type == 12) {
|
||||
for (int i = 0; i <= length; i++) {
|
||||
if ((clustno + i) % 2 == 0) {
|
||||
img[(clustno + i) * 3 / 2 + 0] = fat[clustno + i] & 0xff;
|
||||
img[(clustno + i) * 3 / 2 + 1] =
|
||||
(fat[clustno + i] >> 8 | (img[(clustno + i) * 3 / 2 + 1] & 0xf0)) &
|
||||
0xff;
|
||||
} else if ((clustno + i) % 2 != 0) {
|
||||
img[(clustno + i - 1) * 3 / 2 + 1] =
|
||||
((img[(clustno + i - 1) * 3 / 2 + 1] & 0x0f) | fat[clustno + i]
|
||||
<< 4) &
|
||||
0xff;
|
||||
img[(clustno + i - 1) * 3 / 2 + 2] = (fat[clustno + i] >> 4) & 0xff;
|
||||
}
|
||||
}
|
||||
size = length * 3 / 2 - 1;
|
||||
sec = clustno * 3 / 2;
|
||||
} else if (get_dm(vfs).type == 16) {
|
||||
for (int i = 0; i <= length; i++) {
|
||||
img[(clustno + i) * 2 + 0] = fat[clustno + i] & 0xff;
|
||||
img[(clustno + i) * 2 + 1] = (fat[clustno + i] >> 8) & 0xff;
|
||||
}
|
||||
size = length * 2 - 1;
|
||||
sec = clustno * 2;
|
||||
} else if (get_dm(vfs).type == 32) {
|
||||
for (int i = 0; i <= length; i++) {
|
||||
img[(clustno + i) * 4 + 0] = fat[clustno + i] & 0xff;
|
||||
img[(clustno + i) * 4 + 1] = (fat[clustno + i] >> 8) & 0xff;
|
||||
img[(clustno + i) * 4 + 2] = (fat[clustno + i] >> 16) & 0xff;
|
||||
img[(clustno + i) * 4 + 3] = fat[clustno + i] >> 24;
|
||||
}
|
||||
size = length * 4 - 1;
|
||||
sec = clustno * 4;
|
||||
}
|
||||
Disk_Write((get_dm(vfs).Fat1Address + sec) / get_dm(vfs).SectorBytes,
|
||||
size / get_dm(vfs).SectorBytes + 1,
|
||||
get_dm(vfs).ADR_DISKIMG + get_dm(vfs).Fat1Address,
|
||||
vfs->disk_number);
|
||||
Disk_Write((get_dm(vfs).Fat2Address + sec) / get_dm(vfs).SectorBytes,
|
||||
size / get_dm(vfs).SectorBytes + 1,
|
||||
get_dm(vfs).ADR_DISKIMG + get_dm(vfs).Fat2Address,
|
||||
vfs->disk_number);
|
||||
}
|
||||
|
||||
struct FAT_FILEINFO *file_search(char *name, struct FAT_FILEINFO *finfo,
|
||||
int max) {
|
||||
int i, j;
|
||||
char s[12];
|
||||
for (j = 0; j < 11; j++) {
|
||||
s[j] = ' ';
|
||||
}
|
||||
j = 0;
|
||||
for (i = 0; name[i] != 0; i++) {
|
||||
if (j >= 11) {
|
||||
return 0; //没有找到
|
||||
}
|
||||
if (name[i] == '.' && j <= 8) {
|
||||
j = 8;
|
||||
} else {
|
||||
s[j] = name[i];
|
||||
if ('a' <= s[j] && s[j] <= 'z') {
|
||||
//将小写字母转换为大写字母
|
||||
s[j] -= 0x20;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < max;) {
|
||||
if (finfo[i].name[0] == 0x00) {
|
||||
break;
|
||||
}
|
||||
if ((finfo[i].type & 0x18) == 0) {
|
||||
for (j = 0; j < 11; j++) {
|
||||
if (finfo[i].name[j] != s[j]) {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
return finfo + i; //找到文件
|
||||
}
|
||||
next:
|
||||
i++;
|
||||
}
|
||||
return 0; //没有找到
|
||||
}
|
||||
struct FAT_FILEINFO *dict_search(char *name, struct FAT_FILEINFO *finfo,
|
||||
int max) {
|
||||
int i, j;
|
||||
char s[12];
|
||||
for (j = 0; j < 11; j++) {
|
||||
s[j] = ' ';
|
||||
}
|
||||
j = 0;
|
||||
for (i = 0; name[i] != 0; i++) {
|
||||
if (j >= 11) {
|
||||
return 0; //没有找到
|
||||
} else {
|
||||
s[j] = name[i];
|
||||
if ('a' <= s[j] && s[j] <= 'z') {
|
||||
//将小写字母转换为大写字母
|
||||
s[j] -= 0x20;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < max;) {
|
||||
if (finfo[i].name[0] == 0x00) {
|
||||
break;
|
||||
}
|
||||
if (finfo[i].type == 0x10) {
|
||||
for (j = 0; j < 11; j++) {
|
||||
if (finfo[i].name[j] != s[j]) {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
return finfo + i; // 找到文件
|
||||
}
|
||||
next:
|
||||
i++;
|
||||
}
|
||||
return 0; //没有找到
|
||||
}
|
||||
struct FAT_FILEINFO *Get_File_Address(char *path1, vfs_t *vfs) {
|
||||
// TODO: Modifly it
|
||||
struct FAT_FILEINFO *bmpDict = get_now_dir(vfs);
|
||||
int drive_number = vfs->disk_number;
|
||||
char *path = (char *)page_malloc(strlen(path1) + 1);
|
||||
char *bmp = path;
|
||||
strcpy(path, path1);
|
||||
strtoupper(path);
|
||||
if (strncmp("/", path, 1) == 0) {
|
||||
path += 1;
|
||||
bmpDict = get_dm(vfs).root_directory;
|
||||
}
|
||||
if (path[0] == '\\' || path[0] == '/') {
|
||||
//跳过反斜杠和正斜杠
|
||||
for (int i = 0; i < strlen(path); i++) {
|
||||
if (path[i] != '\\' && path[i] != '/') {
|
||||
path += i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
char *temp_name = (char *)kmalloc(128);
|
||||
struct FAT_FILEINFO *finfo = get_dm(vfs).root_directory;
|
||||
int i = 0;
|
||||
while (1) {
|
||||
int j;
|
||||
for (j = 0; i < strlen(path); i++, j++) {
|
||||
if (path[i] == '\\' || path[i] == '/') {
|
||||
temp_name[j] = '\0';
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
temp_name[j] = path[i];
|
||||
}
|
||||
finfo = dict_search(temp_name, bmpDict, get_directory_max(bmpDict, vfs));
|
||||
if (finfo == 0) {
|
||||
if (path[i] != '\0') {
|
||||
kfree((void *)temp_name, 128);
|
||||
kfree((void *)bmp, strlen(path1) + 1);
|
||||
return 0;
|
||||
}
|
||||
finfo = file_search(temp_name, bmpDict, get_directory_max(bmpDict, vfs));
|
||||
if (finfo == 0) {
|
||||
kfree((void *)temp_name, 128);
|
||||
kfree((void *)bmp, strlen(path1) + 1);
|
||||
return 0;
|
||||
} else {
|
||||
goto END;
|
||||
}
|
||||
} else {
|
||||
if (get_clustno(finfo->clustno_high, finfo->clustno_low) != 0) {
|
||||
for (int count = 1;
|
||||
FindForCount(count, get_dm(vfs).directory_clustno_list) != NULL;
|
||||
count++) {
|
||||
struct List *list =
|
||||
FindForCount(count, get_dm(vfs).directory_clustno_list);
|
||||
if (get_clustno(finfo->clustno_high, finfo->clustno_low) ==
|
||||
list->val) {
|
||||
list = FindForCount(count, get_dm(vfs).directory_list);
|
||||
bmpDict = (struct FAT_FILEINFO *)list->val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bmpDict = get_dm(vfs).root_directory;
|
||||
}
|
||||
clean(temp_name, 128);
|
||||
}
|
||||
}
|
||||
END:
|
||||
kfree((void *)temp_name, 128);
|
||||
kfree((void *)bmp, strlen(path1) + 1);
|
||||
return finfo;
|
||||
}
|
||||
*/
|
@ -9,7 +9,7 @@ idt_ptr_t idt_ptr;
|
||||
|
||||
extern void idt_flush(uint32_t);
|
||||
|
||||
static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) {
|
||||
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) {
|
||||
idt_entries[num].base_low = base & 0xFFFF;
|
||||
idt_entries[num].base_high = (base >> 16) & 0xFFFF; // 拆成低位和高位
|
||||
|
||||
|
@ -12,12 +12,16 @@
|
||||
#include "../include/date.h"
|
||||
#include "../include/acpi.h"
|
||||
#include "../include/syscall.h"
|
||||
#include "../include/vdisk.h"
|
||||
#include "../include/pci.h"
|
||||
#include "../include/pcnet.h"
|
||||
|
||||
extern uint32_t end;
|
||||
extern int status;
|
||||
uint32_t placement_address = (uint32_t) & end;
|
||||
multiboot_t *multiboot_all;
|
||||
|
||||
|
||||
void reset_kernel(){
|
||||
printf("Restart %s for x86...\n",OS_NAME);
|
||||
kill_all_task();
|
||||
@ -37,7 +41,6 @@ uint32_t memory_all(){
|
||||
}
|
||||
|
||||
void kernel_main(multiboot_t *multiboot) {
|
||||
multiboot_all = multiboot;
|
||||
io_cli();
|
||||
vga_install();
|
||||
if ((multiboot->mem_upper + multiboot->mem_lower) / 1024 + 1 < 16) {
|
||||
@ -60,8 +63,15 @@ void kernel_main(multiboot_t *multiboot) {
|
||||
printf("[\035kernel\036]: task load success!\n");
|
||||
init_keyboard();
|
||||
printf("[\035kernel\036]: Keyboard driver load success!\n");
|
||||
|
||||
multiboot_all = multiboot;
|
||||
init_vdisk();
|
||||
init_pci();
|
||||
syscall_install();
|
||||
|
||||
if(pcnet_find_card()){
|
||||
init_pcnet_card();
|
||||
} else printf("[\035kernel\036]: \033Cannot found pcnet.\036\n");
|
||||
|
||||
print_cpu_id();
|
||||
io_sti();
|
||||
|
||||
@ -69,7 +79,7 @@ void kernel_main(multiboot_t *multiboot) {
|
||||
|
||||
clock_sleep(25);
|
||||
|
||||
kernel_thread(setup_shell, NULL, "CPOS-Shell");
|
||||
//kernel_thread(setup_shell, NULL, "CPOS-Shell");
|
||||
launch_date();
|
||||
|
||||
for (;;) {
|
||||
|
@ -1,5 +1,13 @@
|
||||
#include "../include/memory.h"
|
||||
|
||||
void memclean(char *s, int len) {
|
||||
// 清理某个内存区域(全部置0)
|
||||
int i;
|
||||
for (i = 0; i != len; i++) {
|
||||
s[i] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void *memcpy(void *dst_, const void *src_, uint32_t size) {
|
||||
uint8_t *dst = dst_;
|
||||
|
21
util/list.c
Normal file
21
util/list.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include "../include/list.h"
|
||||
|
||||
int GetLastCount(struct List* Obj) {
|
||||
return Obj->ctl->all;
|
||||
}
|
||||
|
||||
struct List* FindForCount(size_t count, struct List* Obj) {
|
||||
int count_last = GetLastCount(Obj);
|
||||
struct List *p = Obj, *q = Obj->ctl->end;
|
||||
if (count > count_last)
|
||||
return (List*)NULL;
|
||||
for (int i = 0, j = count_last;; i++, j--) {
|
||||
if (i == count) {
|
||||
return p;
|
||||
} else if (j == count) {
|
||||
return q;
|
||||
}
|
||||
p = p->next;
|
||||
q = q->prev;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include "../include/printf.h"
|
||||
#include "../include/common.h"
|
||||
#include "../include/graphics.h"
|
||||
|
||||
static int skip_atoi(const char **s) {
|
||||
int i = 0;
|
||||
@ -279,3 +280,18 @@ int sprintf(char *buf, const char *fmt, ...) {
|
||||
va_end(args);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
void printf(const char *formet, ...) {
|
||||
int len;
|
||||
va_list ap;
|
||||
va_start(ap, formet);
|
||||
char *buf[1024] = {0};
|
||||
len = vsprintf(buf, formet, ap);
|
||||
print(buf);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void print(char *message) {
|
||||
vga_writestring(message);
|
||||
}
|
Loading…
Reference in New Issue
Block a user