PCI, Serial, Shell improvements (VGA is broken)
This commit is contained in:
parent
50f5723733
commit
dac2cff511
|
@ -32,7 +32,7 @@ if (ARCH STREQUAL "i386")
|
|||
endif()
|
||||
|
||||
add_executable(kernel.elf ${SOURCES} ${ASM_SOURCES})
|
||||
set_target_properties(kernel.elf PROPERTIES LINK_FLAGS "-T ${LINKER_SCRIPT} -ffreestanding -O2 -nostdlib -lgcc -g ${ARCH_FLAG}")
|
||||
set_target_properties(kernel.elf PROPERTIES LINK_FLAGS "-T ${LINKER_SCRIPT} -ffreestanding -O2 -nostdlib -lgcc -g ${ARCH_FLAG}" DEPENDS pci_supp)
|
||||
add_custom_command(OUTPUT os.iso
|
||||
COMMAND cp kernel.elf ../iso/boot/kernel.elf
|
||||
COMMAND genisoimage -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -A os -input-charset utf8 -quiet -boot-info-table -o os.iso ../iso
|
||||
|
@ -40,7 +40,13 @@ add_custom_command(OUTPUT os.iso
|
|||
COMMENT "Generating OS ISO"
|
||||
)
|
||||
|
||||
add_custom_target(pci_supp
|
||||
COMMAND xxd -i ../build_supp/pci/pci.ids > ../kernel/pci_supp.c
|
||||
COMMENT "Generating Supplemental PCI data"
|
||||
)
|
||||
|
||||
|
||||
# Run & Debug targets
|
||||
add_custom_target(run COMMAND qemu-system-i386 -boot d -cdrom os.iso -m 512 -machine type=pc-i440fx-3.1 -monitor stdio -drive id=disk,file=/dev/null,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 DEPENDS os.iso)
|
||||
add_custom_target(run COMMAND qemu-system-i386 -boot d -m 512 -machine type=pc-i440fx-3.1 -serial stdio -device piix3-ide,id=ide -drive id=disk,file=/dev/null,format=raw,if=none -device ide-hd,drive=disk,bus=ide.1 -device ide-cd,drive=cdrom -drive id=cdrom,file=os.iso,media=cdrom,if=none DEPENDS os.iso)
|
||||
add_custom_target(debug COMMAND ../debug.sh DEPENDS os.iso)
|
||||
|
||||
|
|
|
@ -27,6 +27,16 @@ static inline unsigned char inb(int port) {
|
|||
return val;
|
||||
}
|
||||
|
||||
static inline void outl(uint32_t port, uint32_t val) {
|
||||
__asm__ volatile("outl %k0, %k1" : : "a"(val), "Nd"(port) : "memory");
|
||||
}
|
||||
|
||||
static inline uint32_t inl(uint32_t port) {
|
||||
uint32_t val;
|
||||
__asm__ volatile("inl %k1, %k0" : "=a"(val) : "Nd"(port) : "memory");
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void interrupt_disable() { __asm__ volatile("cli"); }
|
||||
|
||||
static inline void interrupt_enable() { __asm__ volatile("sti"); }
|
||||
|
|
|
@ -10,6 +10,7 @@ enum irq_code_t {
|
|||
IRQCODE_PIT = 32,
|
||||
IRQCODE_PS2 = 33,
|
||||
IRQCODE_SYSCALL = 128,
|
||||
IRQCODE_COM1 = 36,
|
||||
};
|
||||
|
||||
void kb_handler() {
|
||||
|
@ -69,6 +70,13 @@ void irq_handler(struct regs *r) {
|
|||
kb_handler();
|
||||
break;
|
||||
};
|
||||
case IRQCODE_COM1: {
|
||||
char c = serial_rx();
|
||||
c = c == '\r' ? '\n' : c;
|
||||
c = c == 127 ? '\b' : c;
|
||||
handle_keypress_char(c);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
// Send EOI to follower controller
|
||||
|
|
36
kernel/drivers/serial.c
Normal file
36
kernel/drivers/serial.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
#include "../../arch/i386/asm.c"
|
||||
|
||||
#define COM1 (0x3F8)
|
||||
|
||||
int serial_init() {
|
||||
outb(COM1 + 1, 0x01);
|
||||
outb(COM1 + 3, 0x80);
|
||||
outb(COM1 + 0, 0x03);
|
||||
outb(COM1 + 1, 0x00);
|
||||
outb(COM1 + 3, 0x03);
|
||||
outb(COM1 + 2, 0xC7);
|
||||
outb(COM1 + 4, 0x0B);
|
||||
outb(COM1 + 4, 0x0F);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serial_has_tx() {
|
||||
return inb(COM1 + 5) & 0x20;
|
||||
}
|
||||
|
||||
int serial_has_rx() {
|
||||
return inb(COM1 + 5) & 1;
|
||||
}
|
||||
|
||||
void serial_tx(char a) {
|
||||
while (serial_has_tx() == 0);
|
||||
|
||||
outb(COM1,a);
|
||||
}
|
||||
|
||||
char serial_rx() {
|
||||
while (serial_has_rx() == 0);
|
||||
|
||||
return inb(COM1);
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
#include "./drivers/serial.c"
|
||||
#include "./pci.c"
|
||||
#include "./rsdp.c"
|
||||
#include "./scheduler.c"
|
||||
#include "./vga.c"
|
||||
#include "./rsdp.c"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "./test_processes.c"
|
||||
|
@ -14,10 +16,10 @@ int kernel_main() {
|
|||
|
||||
outb(0x3D4, 0x0A);
|
||||
outb(0x3D5, 0x20);
|
||||
|
||||
serial_init();
|
||||
|
||||
find_rsdp();
|
||||
for(;;){}
|
||||
pci_enumerate_devices();
|
||||
clear_screen();
|
||||
|
||||
interrupt_disable();
|
||||
|
@ -26,8 +28,8 @@ int kernel_main() {
|
|||
|
||||
init_process_table();
|
||||
|
||||
start_process("razzle", (char *) &test_razzle);
|
||||
start_process("dazzle", (char *) &test_dazzle);
|
||||
start_process("razzle", (char *)&test_razzle);
|
||||
start_process("dazzle", (char *)&test_dazzle);
|
||||
|
||||
interrupt_enable();
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
// Below doesn't work!
|
||||
//uint8_t streq(char *ptr, char* ptr2) {
|
||||
// uint8_t streq(char *ptr, char* ptr2) {
|
||||
// while (1 == 1) {
|
||||
// if (*ptr != *ptr2) {
|
||||
// return 0;
|
||||
|
@ -20,13 +20,23 @@
|
|||
|
||||
uint8_t memseq(char *ptr, char *ptr2, uint32_t len) {
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (ptr[i] != ptr2[i]) {
|
||||
return 0;
|
||||
}
|
||||
if (ptr[i] != ptr2[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t streq(char *str, char *str2) {
|
||||
for (uint32_t i = 0;; i++) {
|
||||
if (str[i] != str2[i]) {
|
||||
return 0;
|
||||
} else if (str[i] == '\0' && str2[i] == '\0') {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void memset(char *ptr, char data, uint32_t len) {
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
ptr[i] = data;
|
||||
|
|
220
kernel/pci.c
Normal file
220
kernel/pci.c
Normal file
|
@ -0,0 +1,220 @@
|
|||
#pragma once
|
||||
#include "./pci_supp.c"
|
||||
#include "vga.c"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef ARCH_I386
|
||||
#include "../arch/i386/asm.c"
|
||||
#endif
|
||||
|
||||
#define PCI_NO_VENDOR (0xFFFF)
|
||||
#define PCI_MAX_NAMESIZE (128)
|
||||
#define PCI_MAX_DEVICES (256)
|
||||
|
||||
struct pci_device {
|
||||
uint16_t device_id;
|
||||
uint16_t vendor_id;
|
||||
char device_name[PCI_MAX_NAMESIZE];
|
||||
char vendor_name[PCI_MAX_NAMESIZE];
|
||||
uint32_t bar[6];
|
||||
uint8_t class_code;
|
||||
uint8_t subclass_code;
|
||||
};
|
||||
|
||||
static struct pci_device pci_devices_list[PCI_MAX_DEVICES];
|
||||
static uint32_t pci_devices_count;
|
||||
|
||||
uint16_t pci_read_config(uint8_t bus, uint8_t slot, uint8_t function,
|
||||
uint8_t offset) {
|
||||
uint32_t address = ((bus << 16) | (slot << 11) | (function << 8) |
|
||||
(offset & 0xFC) | (8 << 28));
|
||||
|
||||
outl(0xCF8, address);
|
||||
return (uint16_t)((inl(0xCFC) >> ((offset & 2) * 8)) & 0xFFFF);
|
||||
}
|
||||
|
||||
enum PCI_PARSE_STATE {
|
||||
PPS_NUM_1,
|
||||
PPS_NUM_2,
|
||||
PPS_NUM_3,
|
||||
PPS_NUM_4,
|
||||
PPS_SP,
|
||||
PPS_NAME,
|
||||
PPS_NEXTLN,
|
||||
PPS_TAB
|
||||
};
|
||||
|
||||
enum PCI_PARSE_SSTATE { PPSS_VENDOR, PPSS_DEVICE };
|
||||
|
||||
uint32_t ascii_byte_to_num(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return 0x0 + (c - '0');
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
return 0xA + (c - 'A');
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
return 0xA + (c - 'a');
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void pci_get_vendor_dev_name(uint16_t vendor_id, uint16_t device_id,
|
||||
char *vendor_name, char *device_name) {
|
||||
int len = ___build_supp_pci_pci_ids_len;
|
||||
unsigned char *buf = &___build_supp_pci_pci_ids[0];
|
||||
int pps = PPS_NUM_1;
|
||||
int ppss = PPSS_VENDOR;
|
||||
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
// if we encounter newline, reset state
|
||||
if (buf[i] == '\n') {
|
||||
if (pps == PPS_NAME && ppss == PPSS_VENDOR) {
|
||||
ppss = PPSS_DEVICE;
|
||||
pps = PPS_TAB;
|
||||
vendor_name[j] = '\0';
|
||||
j = 0;
|
||||
}
|
||||
if (pps == PPS_NAME && ppss == PPSS_DEVICE) {
|
||||
device_name[j] = '\0';
|
||||
return;
|
||||
}
|
||||
pps = ppss == PPSS_VENDOR ? PPS_NUM_1 : PPS_TAB;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we're waiting for next line, don't do anything else
|
||||
if (pps == PPS_NEXTLN)
|
||||
continue;
|
||||
|
||||
// If we see a tab, we don't want to read device ids, so
|
||||
// just ignore
|
||||
if (buf[i] == '\t' && ppss == PPSS_VENDOR) {
|
||||
pps = PPS_NEXTLN;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we see a tab, we don't want to read device ids, so
|
||||
// just ignore
|
||||
if (buf[i] == '\t' && ppss == PPSS_DEVICE) {
|
||||
if (pps == PPS_TAB) {
|
||||
pps = PPS_NUM_1;
|
||||
} else {
|
||||
pps = PPS_NEXTLN;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we see a comment, ignore
|
||||
if (buf[i] == '#' && pps == PPS_NUM_1) {
|
||||
pps = PPS_NEXTLN;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t tablenum = ascii_byte_to_num(buf[i]);
|
||||
uint32_t vid = ppss == PPSS_VENDOR ? vendor_id : device_id;
|
||||
|
||||
switch (pps) {
|
||||
case PPS_NUM_1:
|
||||
vid = (vid >> 12) & 0xF;
|
||||
if (vid == tablenum) {
|
||||
pps = PPS_NUM_2;
|
||||
} else {
|
||||
pps = PPS_NEXTLN;
|
||||
}
|
||||
break;
|
||||
case PPS_NUM_2:
|
||||
vid = (vid >> 8) & 0xF;
|
||||
if (vid == tablenum) {
|
||||
pps = PPS_NUM_3;
|
||||
} else {
|
||||
pps = PPS_NEXTLN;
|
||||
}
|
||||
break;
|
||||
case PPS_NUM_3:
|
||||
vid = (vid >> 4) & 0xF;
|
||||
if (vid == tablenum) {
|
||||
pps = PPS_NUM_4;
|
||||
} else {
|
||||
pps = PPS_NEXTLN;
|
||||
}
|
||||
break;
|
||||
case PPS_NUM_4:
|
||||
vid = vid & 0xF;
|
||||
if (vid == tablenum) {
|
||||
pps = PPS_SP;
|
||||
} else {
|
||||
pps = PPS_NEXTLN;
|
||||
}
|
||||
break;
|
||||
case PPS_SP:
|
||||
if (buf[i + 1] == ' ') {
|
||||
pps = PPS_SP;
|
||||
} else {
|
||||
pps = PPS_NAME;
|
||||
}
|
||||
break;
|
||||
case PPS_NAME:
|
||||
if (ppss == PPSS_VENDOR) {
|
||||
vendor_name[j] = buf[i];
|
||||
j++;
|
||||
} else {
|
||||
device_name[j] = buf[i];
|
||||
j++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
device_name[0] = '\0';
|
||||
vendor_name[0] = '\0';
|
||||
}
|
||||
|
||||
struct pci_device pci_get_device(uint8_t bus, uint8_t slot) {
|
||||
struct pci_device found_dev;
|
||||
found_dev.vendor_id = pci_read_config(bus, slot, 0, 0);
|
||||
found_dev.device_id = pci_read_config(bus, slot, 0, 2);
|
||||
if (found_dev.vendor_id != PCI_NO_VENDOR) {
|
||||
pci_get_vendor_dev_name(found_dev.vendor_id, found_dev.device_id,
|
||||
&found_dev.vendor_name[0],
|
||||
&found_dev.device_name[0]);
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
found_dev.bar[i] =
|
||||
(uint32_t)(pci_read_config(bus, slot, 0, 0x12 + (i * 4)) << 16) |
|
||||
(pci_read_config(bus, slot, 0, 0x10 + (i * 4)));
|
||||
}
|
||||
uint16_t class_subclass = pci_read_config(bus, slot, 0, 4);
|
||||
found_dev.class_code = class_subclass & 0xFF;
|
||||
found_dev.subclass_code = (class_subclass >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
if (found_dev.vendor_name[0] == '\0' ||
|
||||
found_dev.vendor_id == PCI_NO_VENDOR) {
|
||||
strncpy("Unknown Vendor", &found_dev.vendor_name[0], 15);
|
||||
strncpy("Unknown Device", &found_dev.device_name[0], 15);
|
||||
}
|
||||
|
||||
return found_dev;
|
||||
}
|
||||
|
||||
void pci_enumerate_devices() {
|
||||
for (uint8_t bus = 0;; ++bus) {
|
||||
for (uint8_t slot = 0;; ++slot) {
|
||||
struct pci_device dev = pci_get_device(bus, slot);
|
||||
if (dev.vendor_id != PCI_NO_VENDOR) {
|
||||
pci_devices_list[pci_devices_count++] = dev;
|
||||
printf_nolock("pci: %d.%d: PCI device found bus %d slot %d vendor %x, "
|
||||
"device %x (%d %d)\n",
|
||||
bus, slot, bus, slot, dev.vendor_id, dev.device_id,
|
||||
dev.class_code, dev.subclass_code);
|
||||
printf_nolock("pci: %d.%d: %s %s\n", bus, slot, dev.vendor_name,
|
||||
dev.device_name);
|
||||
}
|
||||
if (slot == 255)
|
||||
break;
|
||||
}
|
||||
if (bus == 255)
|
||||
break;
|
||||
}
|
||||
}
|
124888
kernel/pci_supp.c
Normal file
124888
kernel/pci_supp.c
Normal file
File diff suppressed because it is too large
Load diff
22
kernel/ps2.c
22
kernel/ps2.c
|
@ -258,6 +258,18 @@ void init_ps2() {
|
|||
}
|
||||
}
|
||||
|
||||
void handle_keypress_char(char c) {
|
||||
if (c != '\0') {
|
||||
for(uint32_t i = 0; i < MAX_PROCESSES; i++) {
|
||||
if(ps2_waiters[i].alloc) {
|
||||
process_table[ps2_waiters[i].pid].registers.eax = c;
|
||||
ps2_waiters[i].alloc = 0;
|
||||
process_table[ps2_waiters[i].pid].state = TASKSTATE_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_keypress(uint8_t char_code) {
|
||||
struct key_event_t event;
|
||||
if ((char_code & 0b11000000) == 0b10000000) {
|
||||
|
@ -286,15 +298,7 @@ void handle_keypress(uint8_t char_code) {
|
|||
default: {
|
||||
if (event.is_down) {
|
||||
char c = keycode_to_char(event.key);
|
||||
if (c != '\0') {
|
||||
for(uint32_t i = 0; i < MAX_PROCESSES; i++) {
|
||||
if(ps2_waiters[i].alloc) {
|
||||
process_table[ps2_waiters[i].pid].registers.eax = c;
|
||||
ps2_waiters[i].alloc = 0;
|
||||
process_table[ps2_waiters[i].pid].state = TASKSTATE_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
handle_keypress_char(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
112
kernel/rsdp.c
Normal file
112
kernel/rsdp.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "memory.c"
|
||||
#include "vga.c"
|
||||
|
||||
struct rsdp_t {
|
||||
char signature[8];
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
uint8_t revision;
|
||||
uint32_t rsdt_address;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct xsdp_t {
|
||||
char signature[8];
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
uint8_t revision;
|
||||
uint32_t unused;
|
||||
uint32_t length;
|
||||
uint32_t xsdt_addr_hi;
|
||||
uint32_t xsdt_addr_lo;
|
||||
uint8_t checksum_ext;
|
||||
uint8_t unused_[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct acpi_header_t {
|
||||
char signature[4];
|
||||
uint32_t length;
|
||||
uint8_t revision;
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
uint32_t oem_revision;
|
||||
uint32_t creator_id;
|
||||
uint32_t creator_division;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct rsdt_t {
|
||||
struct acpi_header_t header;
|
||||
uint32_t pointer[64];
|
||||
};
|
||||
|
||||
uint8_t validate(struct rsdp_t *ptr) {
|
||||
char sig[] = "RSD PTR ";
|
||||
if (!memseq(ptr->signature, sig, 8)) return 0;
|
||||
|
||||
uint8_t *rsdp_bytes = (uint8_t *) ptr;
|
||||
uint8_t sum = 0;
|
||||
for(uint8_t i = 0; i < 20; i++) {
|
||||
sum += rsdp_bytes[i];
|
||||
}
|
||||
|
||||
if (sum == 0 && ptr->revision == 2) {
|
||||
printf_nolock("acpi: ACPI v2+ not yet supported :(\n");
|
||||
for(;;){}
|
||||
// TODO: test with ACPI 2 System
|
||||
struct xsdp_t *r2_ptr = (struct xsdp_t*) ptr;
|
||||
|
||||
uint8_t *xsdp_bytes = ((uint8_t *) r2_ptr) + 8;
|
||||
for(uint8_t i = 0; i < 16; i++) {
|
||||
sum += xsdp_bytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
return sum == 0;
|
||||
}
|
||||
|
||||
char* find_table(struct rsdt_t* table, char* sig) {
|
||||
uint32_t entries = (table->header.length - sizeof table->header) / 4;
|
||||
for (uint32_t i = 0; i < entries; i++) {
|
||||
struct acpi_header_t* entry = (struct acpi_header_t*) table->pointer[i];
|
||||
if (memseq(entry->signature, sig, 4)) {
|
||||
printf_nolock("Found %s / %s\n", entry->oem_id, entry->signature);
|
||||
printf_nolock("Signature: %s\n", entry->signature);
|
||||
printf_nolock("Length : %d\n", entry->length);
|
||||
printf_nolock("Oem ID : %s\n", entry->oem_id);
|
||||
printf_nolock("Checksum : %d\n", entry->checksum);
|
||||
return (void*)entry;
|
||||
}
|
||||
}
|
||||
|
||||
printf_nolock("Not Found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void find_rsdp() {
|
||||
struct rsdp_t *ptr;
|
||||
|
||||
volatile uint8_t found = 0;
|
||||
for (uint32_t addr = 0x00000000; addr <= 0x000FFFFF; addr++) {
|
||||
ptr = (struct rsdp_t *) addr;
|
||||
|
||||
if (validate(ptr)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
uint8_t* ebda = (uint8_t*)(*((uint16_t*)0x40e) << 4);
|
||||
for (uint32_t i = 0; i <= 1024; i += 16) {
|
||||
ptr = (struct rsdp_t*) ebda;
|
||||
if (validate(ptr)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf_nolock("acpi: RSDP Found [OEM: %s, SIG: %s]\n", ptr->oem_id, ptr->signature);
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
enum task_state_t { TASKSTATE_unused, TASKSTATE_ready, TASKSTATE_blocked };
|
||||
|
||||
struct task_struct {
|
||||
uint32_t pid;
|
||||
enum task_state_t state;
|
||||
struct regs registers;
|
||||
unsigned int address_base;
|
||||
|
@ -59,6 +60,7 @@ void start_process(char *name, char *entrypoint) {
|
|||
process_table[pid].allocd_addr = (char *)process_table[pid].address_base;
|
||||
process_table[pid].state = TASKSTATE_ready;
|
||||
process_table[pid].process_name = balloc_pid(16, pid);
|
||||
process_table[pid].pid = pid;
|
||||
strncpy(name, process_table[pid].process_name, 16);
|
||||
|
||||
initialize_registers(&process_table[pid].registers, entrypoint,
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
#include "scheduler.c"
|
||||
#include "ps2.c"
|
||||
#include "pci.c"
|
||||
#include "vga.c"
|
||||
|
||||
#ifdef ARCH_I386
|
||||
#include "../arch/i386/syscall.c"
|
||||
#endif
|
||||
|
||||
enum syscall_type_d { SYSCALL_yield, SYSCALL_getc, SYSCALL_exit };
|
||||
enum syscall_type_d { SYSCALL_yield, SYSCALL_getc, SYSCALL_exit, SYSCALL_lspci, SYSCALL_lsproc };
|
||||
|
||||
void yield() { INVOKE_SYSCALL(SYSCALL_yield); }
|
||||
char getc() {
|
||||
|
@ -19,6 +21,53 @@ char getc() {
|
|||
: "=r"(result)
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
uint32_t lspci(struct pci_device* devlist, uint32_t len) {
|
||||
int result = 0;
|
||||
__asm__ volatile (
|
||||
"movl %0, %%ebx"
|
||||
: : "r"((uint32_t) devlist) : "%ebx"
|
||||
);
|
||||
|
||||
__asm__ volatile (
|
||||
"movl %0, %%ecx"
|
||||
: : "r"(len) : "%ecx"
|
||||
);
|
||||
|
||||
|
||||
INVOKE_SYSCALL(SYSCALL_lspci);
|
||||
|
||||
__asm__ volatile (
|
||||
"movl %%eax, %k0"
|
||||
: "=r"(result)
|
||||
);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t lsproc(struct task_struct* proclist, uint32_t len) {
|
||||
int result = 0;
|
||||
__asm__ volatile (
|
||||
"movl %0, %%ebx"
|
||||
: : "r"((uint32_t) proclist) : "%ebx"
|
||||
);
|
||||
|
||||
__asm__ volatile (
|
||||
"movl %0, %%ecx"
|
||||
: : "r"(len) : "%ecx"
|
||||
);
|
||||
|
||||
|
||||
INVOKE_SYSCALL(SYSCALL_lsproc);
|
||||
|
||||
__asm__ volatile (
|
||||
"movl %%eax, %k0"
|
||||
: "=r"(result)
|
||||
);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -35,6 +84,7 @@ void syscall(struct regs *r) {
|
|||
int syscall_no = r->eax;
|
||||
|
||||
switch (syscall_no) {
|
||||
|
||||
case SYSCALL_yield: {
|
||||
__syscall_yield(r);
|
||||
break;
|
||||
|
@ -55,6 +105,37 @@ void syscall(struct regs *r) {
|
|||
break;
|
||||
};
|
||||
|
||||
case SYSCALL_lspci: {
|
||||
uint32_t len = r->ecx;
|
||||
len = len < pci_devices_count ? len : pci_devices_count;
|
||||
struct pci_device* devlist = (struct pci_device*) r->ebx;
|
||||
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
devlist[i] = pci_devices_list[i];
|
||||
}
|
||||
|
||||
r->eax = len;
|
||||
|
||||
break;
|
||||
};
|
||||
|
||||
case SYSCALL_lsproc: {
|
||||
uint32_t len = r->ecx;
|
||||
struct task_struct*proclist = (struct task_struct*) r->ebx;
|
||||
|
||||
uint32_t i = 0, j = 0;
|
||||
for (; i < len; ++i, ++j) {
|
||||
for(; j < MAX_PROCESSES && process_table[j].state == TASKSTATE_unused; ++j) {}
|
||||
if (j == MAX_PROCESSES) break;
|
||||
|
||||
proclist[i] = process_table[j];
|
||||
}
|
||||
|
||||
r->eax = i;
|
||||
|
||||
break;
|
||||
};
|
||||
|
||||
case SYSCALL_exit: {
|
||||
process_table[current_pid].state = TASKSTATE_unused;
|
||||
__syscall_yield(r);
|
||||
|
|
|
@ -8,23 +8,29 @@
|
|||
#include "./scheduler.c"
|
||||
#include "./spin_lock.c"
|
||||
#include "./syscall.c"
|
||||
#include "./vga.c"
|
||||
#include "./scheduler.c"
|
||||
|
||||
uint32_t lock2 = 0;
|
||||
|
||||
uint32_t counter;
|
||||
|
||||
void test_razzle() {
|
||||
for (uint32_t i = 0;; i++) {
|
||||
sl_acquire(&lock2);
|
||||
row = 1;
|
||||
col = 0;
|
||||
printf("%s (pid %d): %u \n", process_table[current_pid].process_name,
|
||||
current_pid, i);
|
||||
counter = 0;
|
||||
sl_release(&lock2);
|
||||
for (;;) {
|
||||
sl_acquire(&lock2);
|
||||
counter++;
|
||||
//row = 1;
|
||||
//col = 0;
|
||||
//printf("%s (pid %d): %u \n", process_table[current_pid].process_name,
|
||||
// current_pid, i);
|
||||
sl_release(&lock2);
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
void cpuid() {
|
||||
void sh_cpuid() {
|
||||
char model[13];
|
||||
uint32_t res[3];
|
||||
__asm__ volatile ("mov $0, %%eax; cpuid; mov %%ebx, %0; mov %%edx, %1; mov %%ecx, %2;" : "=r" (res[0]), "=r" (res[1]), "=r" (res[2]) ::"ebx", "ecx", "edx");
|
||||
|
@ -35,61 +41,92 @@ void cpuid() {
|
|||
model[(i*4) + 3] = (res[i] >> 24) & 0xFF;
|
||||
}
|
||||
model[12] = '\0';
|
||||
printf("%s", model);
|
||||
printf("%s\n", model);
|
||||
}
|
||||
|
||||
void sh_lspci() {
|
||||
struct pci_device devlist[7];
|
||||
int devices = lspci(&devlist[0], 7);
|
||||
for(int j = 0; j < devices; ++j) {
|
||||
printf("%s %s (%d %d)\n", devlist[j].vendor_name, devlist[j].device_name, devlist[j].class_code, devlist[j].subclass_code);
|
||||
printf("Device ID: %x\n", devlist[j].device_id);
|
||||
printf("Vendor ID: %x\n", devlist[j].vendor_id);
|
||||
printf("Bar 5 : %x %u\n\n", devlist[j].bar[5], devlist[j].bar[5]);
|
||||
}
|
||||
}
|
||||
|
||||
void sh_lsproc() {
|
||||
struct task_struct proclist[7];
|
||||
int procs = lsproc(&proclist[0], 7);
|
||||
for(int j = 0; j < procs; ++j) {
|
||||
switch (proclist[j].state) {
|
||||
case TASKSTATE_ready:
|
||||
printf("R");
|
||||
break;
|
||||
case TASKSTATE_blocked:
|
||||
printf("B");
|
||||
break;
|
||||
default:
|
||||
printf("?");
|
||||
break;
|
||||
}
|
||||
printf(" %d: %s", proclist[j].pid, proclist[j].process_name);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void test_dazzle() {
|
||||
char prompt[] = "you@razzle ~$";
|
||||
char prompt[] = "you@razzle ~$ ";
|
||||
char command[2048];
|
||||
|
||||
uint32_t cr = 2;
|
||||
printf("%s", prompt);
|
||||
for (uint32_t i = sizeof(prompt);;) {
|
||||
uint32_t i = 0;
|
||||
|
||||
for (;;) {
|
||||
char c = getc();
|
||||
|
||||
sl_acquire(&lock2);
|
||||
|
||||
row = cr;
|
||||
col = i;
|
||||
|
||||
switch(c) {
|
||||
case '\b':
|
||||
if (i == 0) {
|
||||
i = 79;
|
||||
cr--;
|
||||
} else {
|
||||
i--;
|
||||
}
|
||||
col = i;
|
||||
row = cr;
|
||||
printf(" ");
|
||||
command[i--] = '\0';
|
||||
printf("\b \b");
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
command[i] = '\0';
|
||||
i = 0;
|
||||
cr++;
|
||||
row++;
|
||||
col = 0;
|
||||
cpuid();
|
||||
cr++;
|
||||
col = i;
|
||||
row = cr;
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (streq(command, "lspci")) {
|
||||
sh_lspci();
|
||||
} else if (streq(command, "cpuid")) {
|
||||
sh_cpuid();
|
||||
} else if (streq(command, "help")) {
|
||||
printf("dazzle, the shell for RAZZLE\n");
|
||||
printf("--------------------------------------------------------\n");
|
||||
printf("help : print this menu\n");
|
||||
printf("cpuid : print CPU vendor id string\n");
|
||||
printf("lspci : print list of PCI devices\n");
|
||||
printf("lsproc : print list of running processes\n");
|
||||
printf("counter : print counter maintained by background process\n");
|
||||
} else if (streq(command, "counter")) {
|
||||
printf("%d\n", counter);
|
||||
} else if (streq(command, "lsproc")) {
|
||||
sh_lsproc();
|
||||
} else {
|
||||
printf("Unknown command\n");
|
||||
}
|
||||
|
||||
printf("%s", prompt);
|
||||
i = sizeof(prompt);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%c", c);
|
||||
command[((cr-2)*80) + i] = c;
|
||||
i++;
|
||||
command[i++] = c;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= 80) {
|
||||
i = 0;
|
||||
cr++;
|
||||
}
|
||||
|
||||
sl_release(&lock2);
|
||||
yield();
|
||||
}
|
||||
|
|
16
kernel/vga.c
16
kernel/vga.c
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "./spin_lock.c"
|
||||
#include "./drivers/serial.c"
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -36,6 +37,7 @@ void putc(char c) {
|
|||
}
|
||||
row = (row + 1) % HEIGHT;
|
||||
col = 0;
|
||||
serial_tx('\n');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -43,12 +45,15 @@ void putc(char c) {
|
|||
col--;
|
||||
vram[(row * WIDTH * 2) + (col * 2)] = ' ';
|
||||
vram[(row * WIDTH * 2) + (col * 2 + 1)] = color_code;
|
||||
serial_tx('\b');
|
||||
return;
|
||||
}
|
||||
|
||||
vram[(row * WIDTH * 2) + (col * 2)] = c;
|
||||
vram[(row * WIDTH * 2) + (col * 2 + 1)] = color_code;
|
||||
col++;
|
||||
|
||||
serial_tx(c);
|
||||
}
|
||||
|
||||
void print_uint(unsigned int x, uint8_t base) {
|
||||
|
@ -79,13 +84,18 @@ void print_int(int x, uint8_t base) {
|
|||
}
|
||||
}
|
||||
|
||||
void print_hex(int x) {
|
||||
void print_hex(uint32_t x) {
|
||||
putc('0');
|
||||
putc('x');
|
||||
|
||||
uint8_t fp = 1;
|
||||
|
||||
do {
|
||||
unsigned int digit = (x & 0xF0000000) >> 28;
|
||||
putc((digit < 10) ? (digit + '0') : (digit - 10 + 'A'));
|
||||
uint32_t digit = (x & 0xF0000000) >> 28;
|
||||
if (digit != 0 || !fp || x == 0) {
|
||||
putc((digit < 10) ? (digit + '0') : (digit - 10 + 'A'));
|
||||
fp = 0;
|
||||
}
|
||||
x <<= 4;
|
||||
} while (x != 0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue