From 35685c20a5dc299edf6f3b76ed898a2e71d0e457 Mon Sep 17 00:00:00 2001 From: Jake Mannens Date: Sat, 14 Jul 2018 03:42:12 +1000 Subject: con_init() is now called during the kernel's boot sequence in kboot() rather than in kmain() as some subsystems may now require early console I/O. Added 16-bit read/write I/O functions to asm/io.h. These functions are inw() and outw() respectively. Added the file kernel/fs.h which will contain definitions relating to filesystem functions. Defined the type off_t as a signed 32-bit value in sys/types.h. This type will be required for filesystem functionality. Added the directory 'kernel/fs' to the project's source tree. The kernel's makefile has been updated accordingly. This directory will contain any source files relating to filesystem functionality (both assembly and C files). Added the file 'fs/hd.c' to the kernel's source tree. This file currently contains three main functions (which are defined in kernel/hd.h). These functions are as follows; hd_init() to enumerate and initialize the hard disks, hd_read() to read sectors from the disk and hd_write() to write sectors to the disk. Currently, all transfers are done in ATA PIO mode using polling, however this will change in future. The function hd_init() is called during the kernel's boot sequence in kboot(). Added the file hd.img to the project's root directory. This is a 20MB raw image file that will be used by Qemu as a 20MB hard disk. The main makefile has been updated to tell Qemu to use this file on launch. --- kernel/fs/hd.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 kernel/fs/hd.c (limited to 'kernel/fs/hd.c') diff --git a/kernel/fs/hd.c b/kernel/fs/hd.c new file mode 100644 index 0000000..706d503 --- /dev/null +++ b/kernel/fs/hd.c @@ -0,0 +1,132 @@ +#include +#include +#include +#include + +#define ST_ERR 1 +#define ST_DRQ 8 +#define ST_SRV 16 +#define ST_DF 32 +#define ST_RDY 64 +#define ST_BSY 128 + +/* sector buffer */ +static char sbuf[512]; + +void hd_init(void) { + int i; + uint8_t s; + uint16_t *buf = (uint16_t*) sbuf; + + /* select the master drive */ + outb(0x1F6, 0xA0); + /* send the IDENTIFY command */ + outb(0x1F7, 0xEC); + + while(1) { + s = inb(0x1F7); + if(!s) { + printk("[hd] Master drive not detected on primary bus!\n"); + panic(); + } + if(s & ST_ERR) { + if(!inb(0x1F4) && !inb(0x1F5)) + continue; + printk("[hd] IDENTIFY command error!\n"); + panic(); + } + if(s & ST_DRQ && !(s & ST_ERR)) + break; + } + + printk("[hd] Master drive detected on primary bus! (status: 0x%02x)\n", s); + + for(i = 0; i < 256; i++) + buf[i] = inw(0x1F0); +} + +int hd_read(void *buf, uint32_t lba, uint8_t c) { + int n; + uint8_t s; + uint16_t *p = buf; + + if(!c) + return 0; + + /* select the master disk on the primary bus */ + outb(0x1F6, 0xE0 | ((lba >> 24) & 0xF)); + /* set the number of sectors to be read */ + outb(0x1F2, c); + /* set the LBA address for the read operation */ + outb(0x1F3, lba); + outb(0x1F4, lba >> 8); + outb(0x1F5, lba >> 16); + /* send the READ command */ + outb(0x1F7, 0x20); + + while(c--) { + /* wait for the drive */ + while(1) { + /* poll the drive's status */ + s = inb(0x1F7); + if(s & ST_DF) { + printk("[hd] Drive failure!\n"); + panic(); + } + if(s & ST_ERR) + return -1; + if(!(s & ST_BSY) && s & ST_DRQ) + break; + } + + /* buffer is full, copy it's data */ + n = 256; + while(n--) + *(p++) = inw(0x1F0); + } + + return 0; +} + +int hd_write(void *buf, uint32_t lba, uint8_t c) { + int n; + uint8_t s; + uint16_t *p = buf; + + if(!c) + return 0; + + /* select the master disk on the primary bus */ + outb(0x1F6, 0xE0 | ((lba >> 24) & 0xF)); + /* set the number of sectors to be written */ + outb(0x1F2, c); + /* set the LBA address for the write operation */ + outb(0x1F3, lba); + outb(0x1F4, lba >> 8); + outb(0x1F5, lba >> 16); + /* send the WRITE command */ + outb(0x1F7, 0x30); + + while(c--) { + /* wait for the drive */ + while(1) { + /* poll the drive's status */ + s = inb(0x1F7); + if(s & ST_DF) { + printk("[hd] Drive failure!\n"); + panic(); + } + if(s & ST_ERR) + return -1; + if(!(s & ST_BSY) && s & ST_DRQ) + break; + } + + /* refill the drive's buffer */ + n = 256; + while(n--) + outw(0x1F0, *(p++)); + } + + return 0; +} -- cgit v1.3