Moved INT 13H disk operations outside DOSFS driver
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o usermode.o paging.o fault.o tests.o kbd.o helper.o progs.o
 | 
			
		||||
objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o usermode.o paging.o fault.o tests.o kbd.o helper.o progs.o disk.o
 | 
			
		||||
CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding -march=i686 -fno-stack-protector -Wno-int-conversion -nostdlib -c
 | 
			
		||||
 | 
			
		||||
%.o: %.nasm
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										121
									
								
								disk.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								disk.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,121 @@
 | 
			
		||||
#include "v86defs.h"
 | 
			
		||||
#include "print.h"
 | 
			
		||||
#include "dosfs/dosfs.h"
 | 
			
		||||
#include "stdint.h"
 | 
			
		||||
 | 
			
		||||
extern void *memcpy(void *restrict dest, const void *restrict src, uintptr_t n);
 | 
			
		||||
 | 
			
		||||
extern uint32_t _gpf_eax_save;
 | 
			
		||||
extern uint32_t _gpf_eflags_save;
 | 
			
		||||
extern uint16_t error_screen[80*50]; // defined in kernel.c
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
extern void error_environment(); // defined in kernel.c
 | 
			
		||||
uint32_t numHead;
 | 
			
		||||
uint32_t secPerTrack;
 | 
			
		||||
uint32_t maxCylinder;
 | 
			
		||||
char useCHS = -1;
 | 
			
		||||
void Disk_SetupCHS() {
 | 
			
		||||
	union V86Regs_t regs;
 | 
			
		||||
	// Check for INT 13 Extensions support
 | 
			
		||||
	regs.h.ah = 0x41;
 | 
			
		||||
	regs.w.bx = 0x55AA;
 | 
			
		||||
	regs.h.dl = 0x80;
 | 
			
		||||
	V8086Int(0x13, ®s);
 | 
			
		||||
	// LBA supported if CF clear
 | 
			
		||||
	if (!(_gpf_eflags_save & 0x1)) {
 | 
			
		||||
		useCHS = 0;
 | 
			
		||||
	} else {
 | 
			
		||||
		FARPTR v86_entry = i386LinearToFp(v86DiskGetGeometry);
 | 
			
		||||
		enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
		// check CF for error
 | 
			
		||||
		if (_gpf_eflags_save & 0x1) {
 | 
			
		||||
			uint16_t *vga = error_screen;
 | 
			
		||||
			vga += printStr("Could not get Disk Geometry.", vga);
 | 
			
		||||
			error_environment();
 | 
			
		||||
			for(;;);
 | 
			
		||||
		}
 | 
			
		||||
		numHead = ((_gpf_eax_save & 0xff00) >> 8) + 1;
 | 
			
		||||
		secPerTrack = _gpf_eax_save & 0x3f;
 | 
			
		||||
		maxCylinder = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2);
 | 
			
		||||
		useCHS = 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
 | 
			
		||||
	// NOTE If the buffer provided is outside the 0x20000-0x2FE00 range,
 | 
			
		||||
	// the function will use that buffer for the Virtual 8086 process
 | 
			
		||||
	// and copy to the other buffer after
 | 
			
		||||
	uint8_t *v86buf = buffer;
 | 
			
		||||
	if ((uintptr_t)v86buf < 0x20000 || (uintptr_t)v86buf > 0x2FE00)
 | 
			
		||||
		v86buf = (uint8_t *)0x20000;
 | 
			
		||||
 | 
			
		||||
	// TODO This check should probably happen at the kernel level
 | 
			
		||||
	if (useCHS == -1) {
 | 
			
		||||
		Disk_SetupCHS();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO Do error handling
 | 
			
		||||
	if (!useCHS) {
 | 
			
		||||
		// LBA Read
 | 
			
		||||
		v86disk_addr_packet.start_block = sector;
 | 
			
		||||
		v86disk_addr_packet.blocks = count;
 | 
			
		||||
		v86disk_addr_packet.transfer_buffer =
 | 
			
		||||
			(uintptr_t)v86buf & 0x000F |
 | 
			
		||||
			(((uintptr_t)v86buf & 0xFFFF0) << 12);
 | 
			
		||||
		union V86Regs_t regs;
 | 
			
		||||
		regs.h.ah = 0x42;
 | 
			
		||||
		FARPTR v86_entry = i386LinearToFp(v86DiskOp);
 | 
			
		||||
		enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
	} else {
 | 
			
		||||
        uint32_t tmp = sector / secPerTrack;
 | 
			
		||||
        uint32_t sec = (sector % (secPerTrack)) + 1;
 | 
			
		||||
        uint32_t head = tmp % numHead;
 | 
			
		||||
        uint32_t cyl = tmp / numHead;
 | 
			
		||||
		union V86Regs_t regs;
 | 
			
		||||
        regs.w.ax = 0x0201;
 | 
			
		||||
        regs.h.ch = cyl & 0xff;
 | 
			
		||||
        regs.h.cl = sec | ((cyl >> 2) & 0xc0);
 | 
			
		||||
        regs.h.dh = head;
 | 
			
		||||
        regs.h.dl = 0x80;
 | 
			
		||||
        regs.w.bx = (uintptr_t)v86buf & 0xFFFF;
 | 
			
		||||
        FARPTR v86_entry = i386LinearToFp(v86DiskReadCHS);
 | 
			
		||||
        enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
	}
 | 
			
		||||
	if (v86buf != buffer)
 | 
			
		||||
		memcpy(buffer, v86buf, count * SECTOR_SIZE);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
 | 
			
		||||
	// NOTE If the buffer provided is outside the 0x20000-0x2FE00 range,
 | 
			
		||||
	// the function will use copy that buffer into the Virtual 8086 disk range
 | 
			
		||||
	uint8_t *v86buf = buffer;
 | 
			
		||||
	if ((uintptr_t)v86buf < 0x20000 || (uintptr_t)v86buf > 0x2FE00) {
 | 
			
		||||
		v86buf = (uint8_t *)0x20000;
 | 
			
		||||
		memcpy(v86buf, buffer, count * SECTOR_SIZE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO This check should probably happen at the kernel level
 | 
			
		||||
	if (useCHS == -1) {
 | 
			
		||||
		Disk_SetupCHS();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO Do error handling
 | 
			
		||||
	if (!useCHS) {
 | 
			
		||||
		// LBA Read
 | 
			
		||||
		v86disk_addr_packet.start_block = sector;
 | 
			
		||||
		v86disk_addr_packet.blocks = count;
 | 
			
		||||
		v86disk_addr_packet.transfer_buffer =
 | 
			
		||||
			(uintptr_t)v86buf & 0x000F |
 | 
			
		||||
			(((uintptr_t)v86buf & 0xFFFF0) << 12);
 | 
			
		||||
		union V86Regs_t regs;
 | 
			
		||||
		regs.w.ax = 0x4300;
 | 
			
		||||
		FARPTR v86_entry = i386LinearToFp(v86DiskOp);
 | 
			
		||||
		enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
	} else {
 | 
			
		||||
		uint16_t *vga = error_screen;
 | 
			
		||||
		vga += printStr("CHS Write Unimplemented", vga);
 | 
			
		||||
		error_environment();
 | 
			
		||||
		for(;;);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
#include "tmpstring.c"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	DOSFS Embedded FAT-Compatible Filesystem
 | 
			
		||||
	(C) 2005 Lewin A.R.W. Edwards (sysadm@zws.com)
 | 
			
		||||
@@ -9,88 +11,6 @@
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "dosfs.h"
 | 
			
		||||
#include "tmpstring.c"
 | 
			
		||||
#include "../v86defs.h"
 | 
			
		||||
#include "../print.h"
 | 
			
		||||
 | 
			
		||||
extern uint32_t _gpf_eax_save;
 | 
			
		||||
extern uint32_t _gpf_eflags_save;
 | 
			
		||||
extern uint16_t error_screen[80*50]; // defined in kernel.c
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
extern void error_environment(); // defined in kernel.c
 | 
			
		||||
uint32_t numHead;
 | 
			
		||||
uint32_t secPerTrack;
 | 
			
		||||
uint32_t maxCylinder;
 | 
			
		||||
char useCHS = -1;
 | 
			
		||||
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
 | 
			
		||||
	// NOTE If the buffer provided is outside the 0x20000-0x2FE00 range,
 | 
			
		||||
	// the function will use that buffer for the Virtual 8086 process
 | 
			
		||||
	// and copy to the other buffer after
 | 
			
		||||
	uint8_t *v86buf = buffer;
 | 
			
		||||
	if ((uintptr_t)v86buf < 0x20000 || (uintptr_t)v86buf > 0x2FE00)
 | 
			
		||||
		v86buf = (uint8_t *)0x20000;
 | 
			
		||||
 | 
			
		||||
	// TODO This check should probably happen at the kernel level
 | 
			
		||||
	if (useCHS == -1) {
 | 
			
		||||
		union V86Regs_t regs;
 | 
			
		||||
		// Check for INT 13 Extensions support
 | 
			
		||||
		regs.h.ah = 0x41;
 | 
			
		||||
		regs.w.bx = 0x55AA;
 | 
			
		||||
		regs.h.dl = 0x80;
 | 
			
		||||
		V8086Int(0x13, ®s);
 | 
			
		||||
		// LBA supported if CF clear
 | 
			
		||||
		if (!(_gpf_eflags_save & 0x1)) {
 | 
			
		||||
			useCHS = 0;
 | 
			
		||||
		} else {
 | 
			
		||||
			FARPTR v86_entry = i386LinearToFp(v86DiskGetGeometry);
 | 
			
		||||
			enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
			// check CF for error
 | 
			
		||||
			if (_gpf_eflags_save & 0x1) {
 | 
			
		||||
				uint16_t *vga = error_screen;
 | 
			
		||||
				vga += printStr("Could not get Disk Geometry.", vga);
 | 
			
		||||
				error_environment();
 | 
			
		||||
				for(;;);
 | 
			
		||||
			}
 | 
			
		||||
			numHead = ((_gpf_eax_save & 0xff00) >> 8) + 1;
 | 
			
		||||
			secPerTrack = _gpf_eax_save & 0x3f;
 | 
			
		||||
			maxCylinder = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2);
 | 
			
		||||
			useCHS = 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO Do error handling
 | 
			
		||||
	if (!useCHS) {
 | 
			
		||||
		// LBA Read
 | 
			
		||||
		v86disk_addr_packet.start_block = sector;
 | 
			
		||||
		v86disk_addr_packet.blocks = count;
 | 
			
		||||
		v86disk_addr_packet.transfer_buffer =
 | 
			
		||||
			(uintptr_t)v86buf & 0x000F |
 | 
			
		||||
			(((uintptr_t)v86buf & 0xFFFF0) << 12);
 | 
			
		||||
		union V86Regs_t regs;
 | 
			
		||||
		FARPTR v86_entry = i386LinearToFp(v86DiskRead);
 | 
			
		||||
		enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
	} else {
 | 
			
		||||
        uint32_t tmp = sector / secPerTrack;
 | 
			
		||||
        uint32_t sec = (sector % (secPerTrack)) + 1;
 | 
			
		||||
        uint32_t head = tmp % numHead;
 | 
			
		||||
        uint32_t cyl = tmp / numHead;
 | 
			
		||||
		union V86Regs_t regs;
 | 
			
		||||
        regs.w.ax = 0x0201;
 | 
			
		||||
        regs.h.ch = cyl & 0xff;
 | 
			
		||||
        regs.h.cl = sec | ((cyl >> 2) & 0xc0);
 | 
			
		||||
        regs.h.dh = head;
 | 
			
		||||
        regs.h.dl = 0x80;
 | 
			
		||||
        regs.w.bx = (uintptr_t)v86buf & 0xFFFF;
 | 
			
		||||
        FARPTR v86_entry = i386LinearToFp(v86DiskReadCHS);
 | 
			
		||||
        enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
	}
 | 
			
		||||
	if (v86buf != buffer)
 | 
			
		||||
		memcpy(buffer, v86buf, count * SECTOR_SIZE);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
 | 
			
		||||
	for(;;);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	Get starting sector# of specified partition on drive #unit
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								kernel.c
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								kernel.c
									
									
									
									
									
								
							@@ -239,6 +239,16 @@ void PrintFileList() {
 | 
			
		||||
char IsDir(DIRENT *de) {
 | 
			
		||||
    return de->attr & ATTR_DIRECTORY;
 | 
			
		||||
}
 | 
			
		||||
void ScancodeTest() {
 | 
			
		||||
    uint16_t *vga = (uint16_t*)0xb8000;
 | 
			
		||||
    uint16_t scancode;
 | 
			
		||||
    while(((scancode = get_scancode()) & 0xff) != KEY_F1) {
 | 
			
		||||
        vga += printWord(scancode, vga);
 | 
			
		||||
        vga++;
 | 
			
		||||
        if ((uintptr_t)vga >= 0xb8000+80*25*2)
 | 
			
		||||
            vga = (uint16_t*)0xb8000;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
 | 
			
		||||
void FileSelect() {
 | 
			
		||||
    uint8_t current_path[80];
 | 
			
		||||
@@ -255,15 +265,15 @@ void FileSelect() {
 | 
			
		||||
        // Info line (4)
 | 
			
		||||
        {
 | 
			
		||||
            uint16_t *vga = &vga_text[80*4 + 79 - 24];
 | 
			
		||||
            printStr("T to run tests", vga);
 | 
			
		||||
            vga += 80;
 | 
			
		||||
            printStr("X to view in hex", vga);
 | 
			
		||||
            vga += 80;
 | 
			
		||||
            printStr("V to view as text", vga);
 | 
			
		||||
            printStr("T to view as text", vga);
 | 
			
		||||
            vga += 80;
 | 
			
		||||
            printStr("P to load as program", vga);
 | 
			
		||||
            vga += 80;
 | 
			
		||||
            printStr("O to open directory", vga);
 | 
			
		||||
            vga += 80;
 | 
			
		||||
            printStr("F4 to run tests", vga);
 | 
			
		||||
        }
 | 
			
		||||
        printStr((char*)current_path, &vga_text[80*4 + 2]);
 | 
			
		||||
        for (int i = 2; i < 15; i++)
 | 
			
		||||
@@ -285,15 +295,15 @@ void FileSelect() {
 | 
			
		||||
        uint16_t key = get_scancode();
 | 
			
		||||
        uint8_t path[13];
 | 
			
		||||
        switch (key & 0xff) { // scancode component
 | 
			
		||||
            case 0x50: // down
 | 
			
		||||
            case KEY_DOWN: // down
 | 
			
		||||
                fileHovered++;
 | 
			
		||||
                if (fileHovered >= fileCount) fileHovered = 0;
 | 
			
		||||
                break;
 | 
			
		||||
            case 0x48: // up
 | 
			
		||||
            case KEY_UP: // up
 | 
			
		||||
                fileHovered--;
 | 
			
		||||
                if (fileHovered < 0) fileHovered = fileCount - 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 0x14: // t
 | 
			
		||||
            case KEY_F4:
 | 
			
		||||
                create_child(0x380000, (uintptr_t)RunTests, 0);
 | 
			
		||||
                SetCursorDisabled();
 | 
			
		||||
                reload = 1;
 | 
			
		||||
@@ -313,7 +323,7 @@ void FileSelect() {
 | 
			
		||||
                SetCursorDisabled();
 | 
			
		||||
                reload = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_V:
 | 
			
		||||
            case KEY_T:
 | 
			
		||||
                File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
 | 
			
		||||
                //TextViewTest(path, &vi);
 | 
			
		||||
                create_child(0x380000, (uintptr_t)TextViewTest, 2, current_path, &vi);
 | 
			
		||||
@@ -322,6 +332,7 @@ void FileSelect() {
 | 
			
		||||
                reload = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_O:
 | 
			
		||||
            case 0x9C: // enter release
 | 
			
		||||
                if (IsDir(&entries[fileHovered])) {
 | 
			
		||||
                    uint8_t tmp_path[80];
 | 
			
		||||
                    File83ToPath((char*)entries[fileHovered].name, (char*)tmp_path);
 | 
			
		||||
@@ -346,6 +357,10 @@ void FileSelect() {
 | 
			
		||||
                    fileHovered = 0;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_F6:
 | 
			
		||||
                ScancodeTest();
 | 
			
		||||
                reload = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								tests.c
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								tests.c
									
									
									
									
									
								
							@@ -40,7 +40,8 @@ void TestDiskRead() {
 | 
			
		||||
	v86disk_addr_packet.transfer_buffer =
 | 
			
		||||
		(uintptr_t)diskReadBuf & 0x000F |
 | 
			
		||||
		(((uintptr_t)diskReadBuf & 0xFFFF0) << 12);
 | 
			
		||||
    FARPTR v86_entry = i386LinearToFp(v86DiskRead);
 | 
			
		||||
    regs.h.ah = 0x42;
 | 
			
		||||
    FARPTR v86_entry = i386LinearToFp(v86DiskOp);
 | 
			
		||||
    enter_v86(0x0000, 0x8000, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
    uint16_t *vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
    for (int i = 0; i < (80*25)/2; i++) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								v86.nasm
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								v86.nasm
									
									
									
									
									
								
							@@ -89,11 +89,10 @@ int 0x10
 | 
			
		||||
int 0x30
 | 
			
		||||
jmp $
 | 
			
		||||
 | 
			
		||||
global v86DiskRead
 | 
			
		||||
v86DiskRead:
 | 
			
		||||
xor ax, ax ; TODO fix assuming we're in first 64k
 | 
			
		||||
mov ds, ax
 | 
			
		||||
mov ah, 0x42
 | 
			
		||||
global v86DiskOp
 | 
			
		||||
v86DiskOp:
 | 
			
		||||
xor bx, bx ; TODO fix assuming we're in first 64k
 | 
			
		||||
mov ds, bx
 | 
			
		||||
mov dl, 0x80 ; TODO get this from BIOS or something
 | 
			
		||||
mov si, v86disk_addr_packet ; ds:si
 | 
			
		||||
int 0x13
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user