From ebe7ef26eeb40edc0b01618af6a1bb80899f940a Mon Sep 17 00:00:00 2001 From: Tom-on64 Date: Thu, 11 Apr 2024 14:52:30 +0200 Subject: [PATCH] Implemented diskWrite() function!\nWe finally have disk operations!! Get ready for the filetable :) --- src/kernel/disk.c | 27 +++++++++++++++++ src/kernel/disk.h | 2 +- src/kernel/main.c | 71 ++++++++++++++++++++++++++++++--------------- src/kernel/string.c | 5 ++++ src/kernel/string.h | 2 ++ 5 files changed, 83 insertions(+), 24 deletions(-) diff --git a/src/kernel/disk.c b/src/kernel/disk.c index fcd76e6..4659b25 100644 --- a/src/kernel/disk.c +++ b/src/kernel/disk.c @@ -5,6 +5,7 @@ #define PIO_PORT 0x1f0 #define READ_COMMAND 0x20 #define WRITE_COMMAND 0x30 +#define CACHE_FLUSH 0xE7 void diskRead(uint32_t lbaAddress, uint8_t sectorCount, char* dst) { outb(PIO_PORT + 6, ((lbaAddress >> 24) & 0x0f) | 0xe0); // 6 - Use LBA; 4 - Drive number; 3-0 - Highest lba address nibble @@ -29,3 +30,29 @@ void diskRead(uint32_t lbaAddress, uint8_t sectorCount, char* dst) { } } +void diskWrite(uint32_t lbaAddress, uint8_t sectorCount, char* src) { + outb(PIO_PORT + 6, ((lbaAddress >> 24) & 0x0f) | 0xe0); // 6 - Use LBA; 4 - Drive number; 3-0 - Highest lba address nibble + outb(PIO_PORT + 2, sectorCount); // Sector count register + outb(PIO_PORT + 3, (uint8_t)(lbaAddress)); // Lowest lba address byte + outb(PIO_PORT + 4, (uint8_t)(lbaAddress >> 8)); // Middle lba address byte + outb(PIO_PORT + 5, (uint8_t)(lbaAddress >> 16)); // High lba address byte + outb(PIO_PORT + 7, WRITE_COMMAND); // Command register + + uint16_t* address = (uint16_t*)src; + + for (uint8_t i = sectorCount; i > 0; i--) { + while (inb(PIO_PORT + 7) & (1 << 7)); // Poll status register untill BSY bit is clear + + for (size_t j = 0; j < 256; j++) { + outw(PIO_PORT, *address++); // Write 256 words (512 Bytes = 1 Sector) + } + + for (uint8_t delay = 0; delay < 4; delay++) { // 400ns delay + inb(0x3f6); // Alternate status register + } + } + + outb(PIO_PORT + 7, CACHE_FLUSH); // Cache flush + while (inb(PIO_PORT + 7) & (1 << 7)); // Poll status register untill BSY bit is clear +} + diff --git a/src/kernel/disk.h b/src/kernel/disk.h index e8e86d9..5fd87b5 100644 --- a/src/kernel/disk.h +++ b/src/kernel/disk.h @@ -6,6 +6,6 @@ extern uint8_t driveNum; void diskRead(uint32_t lbaAddress, uint8_t sectorCount, char* dst); -// TODO: void diskWrite(uint8_t sector, uint8_t sectorCount, uint8_t drive, const char* src); +void diskWrite(uint32_t lbaAddress, uint8_t sectorCount, char* src); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 9d2ae88..81d42d4 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -39,42 +39,67 @@ void main() { args = strchr(input, '\n'); } - *args = '\0'; // Separate command from args - args++; + *args++ = '\0'; // Separate command from args if (strcmp(input, "clear") == 0) { clear(0x0f); } else if (strcmp(input, "disk") == 0) { - static char buf[512]; + char buf[512] = { 0 }; if (*args == '\0') { - print("test: ", 0x0f); + print("disk: ", 0x0f); print("No arguments given\n", 0x0c); - print("Usage: test \n", 0x0f); + print("Usage: disk [data]\n", 0x0f); continue; } - // TODO: We only support reading right now - //char mode = *args++; - //if (mode != 'r' || mode != 'w') { - // print("test: ", 0x0f); - // print("Invalid access mode. Use r(ead) or w(rite)\n", 0x0c); - // print("Usage: test [data]\n", 0x0f); - // continue; - //} - - uint32_t sector = atoi(args); - print("Reading...\n", 0x0f); - diskRead(sector, 1, buf); + while (isSpace(*args)) { args++; } // Skip whitespace + char mode = *args++; + while (isSpace(*args)) { args++; } - print("Contents:\n", 0x0f); - for (size_t i = 0; i < 512; i++) { - if (buf[i] != '\0') { - putc(buf[i], 0x0f); + if (mode == 'r') { + if (*args == '\0') { + print("disk: ", 0x0f); + print("Sector not specified\n", 0x0c); + print("Usage: disk [data]\n", 0x0f); + continue; } - } - putc('\n', 0x0f); + uint32_t sector = atoi(args); + print("Reading...\n", 0x0f); + diskRead(sector, 1, buf); + + print("Contents:\n", 0x0f); + for (size_t i = 0; i < 512; i++) { + if (buf[i] != '\0') { + putc(buf[i], 0x0f); + } + } + + putc('\n', 0x0f); + } else if (mode == 'w') { + char* data; + if ((data = strchr(args, ' ')) == NULL) { + print("disk: ", 0x0f); + print("No data given\n", 0x0c); + print("Usage: disk [data]\n", 0x0f); + continue; + } + + *data++ = '\0'; + uint32_t sector = atoi(args); + + while (isSpace(*args)) { args++; } // Skip whitespace + + strcpy(buf, data); + print("Writing...\n", 0x0f); + diskWrite(sector, 1, buf); + } else { + print("disk: ", 0x0f); + print("Invalid access mode. Use r(ead) or w(rite)\n", 0x0c); + print("Usage: disk [data]\n", 0x0f); + continue; + } } else if (strcmp(input, "echo") == 0) { print(args, 0x0f); } else if (strcmp(input, "exit") == 0) { diff --git a/src/kernel/string.c b/src/kernel/string.c index 55ac15f..d05e182 100644 --- a/src/kernel/string.c +++ b/src/kernel/string.c @@ -30,6 +30,11 @@ uint32_t atoi(const char* str) { return res; } +int isSpace(char c) { + if (c == ' ' || c == '\t' || c == '\n') return 1; + else return 0; +} + // Some implementations taken from https://en.wikibooks.org/wiki/C_Programming/String_manipulation char* strcat(char* str1, const char* str2) { char* s = str1; diff --git a/src/kernel/string.h b/src/kernel/string.h index f6f700a..557bcc3 100644 --- a/src/kernel/string.h +++ b/src/kernel/string.h @@ -6,6 +6,8 @@ char* itoa(uint32_t val, uint8_t base); uint32_t atoi(const char* str); +int isSpace(char c); + char* strcat(char* str1, const char* str2); char* strchr(const char* str, char c); int strcmp(const char* str1, const char* str2);