Moved INT 13H disk operations outside DOSFS driver
This commit is contained in:
parent
c7b69675bb
commit
094e278212
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
|
CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding -march=i686 -fno-stack-protector -Wno-int-conversion -nostdlib -c
|
||||||
|
|
||||||
%.o: %.nasm
|
%.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
|
DOSFS Embedded FAT-Compatible Filesystem
|
||||||
(C) 2005 Lewin A.R.W. Edwards (sysadm@zws.com)
|
(C) 2005 Lewin A.R.W. Edwards (sysadm@zws.com)
|
||||||
@ -9,88 +11,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dosfs.h"
|
#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
|
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) {
|
char IsDir(DIRENT *de) {
|
||||||
return de->attr & ATTR_DIRECTORY;
|
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, ...);
|
extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
||||||
void FileSelect() {
|
void FileSelect() {
|
||||||
uint8_t current_path[80];
|
uint8_t current_path[80];
|
||||||
@ -255,15 +265,15 @@ void FileSelect() {
|
|||||||
// Info line (4)
|
// Info line (4)
|
||||||
{
|
{
|
||||||
uint16_t *vga = &vga_text[80*4 + 79 - 24];
|
uint16_t *vga = &vga_text[80*4 + 79 - 24];
|
||||||
printStr("T to run tests", vga);
|
|
||||||
vga += 80;
|
|
||||||
printStr("X to view in hex", vga);
|
printStr("X to view in hex", vga);
|
||||||
vga += 80;
|
vga += 80;
|
||||||
printStr("V to view as text", vga);
|
printStr("T to view as text", vga);
|
||||||
vga += 80;
|
vga += 80;
|
||||||
printStr("P to load as program", vga);
|
printStr("P to load as program", vga);
|
||||||
vga += 80;
|
vga += 80;
|
||||||
printStr("O to open directory", vga);
|
printStr("O to open directory", vga);
|
||||||
|
vga += 80;
|
||||||
|
printStr("F4 to run tests", vga);
|
||||||
}
|
}
|
||||||
printStr((char*)current_path, &vga_text[80*4 + 2]);
|
printStr((char*)current_path, &vga_text[80*4 + 2]);
|
||||||
for (int i = 2; i < 15; i++)
|
for (int i = 2; i < 15; i++)
|
||||||
@ -285,15 +295,15 @@ void FileSelect() {
|
|||||||
uint16_t key = get_scancode();
|
uint16_t key = get_scancode();
|
||||||
uint8_t path[13];
|
uint8_t path[13];
|
||||||
switch (key & 0xff) { // scancode component
|
switch (key & 0xff) { // scancode component
|
||||||
case 0x50: // down
|
case KEY_DOWN: // down
|
||||||
fileHovered++;
|
fileHovered++;
|
||||||
if (fileHovered >= fileCount) fileHovered = 0;
|
if (fileHovered >= fileCount) fileHovered = 0;
|
||||||
break;
|
break;
|
||||||
case 0x48: // up
|
case KEY_UP: // up
|
||||||
fileHovered--;
|
fileHovered--;
|
||||||
if (fileHovered < 0) fileHovered = fileCount - 1;
|
if (fileHovered < 0) fileHovered = fileCount - 1;
|
||||||
break;
|
break;
|
||||||
case 0x14: // t
|
case KEY_F4:
|
||||||
create_child(0x380000, (uintptr_t)RunTests, 0);
|
create_child(0x380000, (uintptr_t)RunTests, 0);
|
||||||
SetCursorDisabled();
|
SetCursorDisabled();
|
||||||
reload = 1;
|
reload = 1;
|
||||||
@ -313,7 +323,7 @@ void FileSelect() {
|
|||||||
SetCursorDisabled();
|
SetCursorDisabled();
|
||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_V:
|
case KEY_T:
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
||||||
//TextViewTest(path, &vi);
|
//TextViewTest(path, &vi);
|
||||||
create_child(0x380000, (uintptr_t)TextViewTest, 2, current_path, &vi);
|
create_child(0x380000, (uintptr_t)TextViewTest, 2, current_path, &vi);
|
||||||
@ -322,6 +332,7 @@ void FileSelect() {
|
|||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_O:
|
case KEY_O:
|
||||||
|
case 0x9C: // enter release
|
||||||
if (IsDir(&entries[fileHovered])) {
|
if (IsDir(&entries[fileHovered])) {
|
||||||
uint8_t tmp_path[80];
|
uint8_t tmp_path[80];
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)tmp_path);
|
File83ToPath((char*)entries[fileHovered].name, (char*)tmp_path);
|
||||||
@ -346,6 +357,10 @@ void FileSelect() {
|
|||||||
fileHovered = 0;
|
fileHovered = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case KEY_F6:
|
||||||
|
ScancodeTest();
|
||||||
|
reload = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
3
tests.c
3
tests.c
@ -40,7 +40,8 @@ void TestDiskRead() {
|
|||||||
v86disk_addr_packet.transfer_buffer =
|
v86disk_addr_packet.transfer_buffer =
|
||||||
(uintptr_t)diskReadBuf & 0x000F |
|
(uintptr_t)diskReadBuf & 0x000F |
|
||||||
(((uintptr_t)diskReadBuf & 0xFFFF0) << 12);
|
(((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);
|
enter_v86(0x0000, 0x8000, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||||
for (int i = 0; i < (80*25)/2; i++) {
|
for (int i = 0; i < (80*25)/2; i++) {
|
||||||
|
9
v86.nasm
9
v86.nasm
@ -89,11 +89,10 @@ int 0x10
|
|||||||
int 0x30
|
int 0x30
|
||||||
jmp $
|
jmp $
|
||||||
|
|
||||||
global v86DiskRead
|
global v86DiskOp
|
||||||
v86DiskRead:
|
v86DiskOp:
|
||||||
xor ax, ax ; TODO fix assuming we're in first 64k
|
xor bx, bx ; TODO fix assuming we're in first 64k
|
||||||
mov ds, ax
|
mov ds, bx
|
||||||
mov ah, 0x42
|
|
||||||
mov dl, 0x80 ; TODO get this from BIOS or something
|
mov dl, 0x80 ; TODO get this from BIOS or something
|
||||||
mov si, v86disk_addr_packet ; ds:si
|
mov si, v86disk_addr_packet ; ds:si
|
||||||
int 0x13
|
int 0x13
|
||||||
|
@ -8,7 +8,7 @@ extern void v86Test();
|
|||||||
extern void v86TransFlag();
|
extern void v86TransFlag();
|
||||||
extern void v86Interrupt();
|
extern void v86Interrupt();
|
||||||
extern void v86TextMode();
|
extern void v86TextMode();
|
||||||
extern void v86DiskRead();
|
extern void v86DiskOp();
|
||||||
extern void v86DiskGetGeometry();
|
extern void v86DiskGetGeometry();
|
||||||
extern void v86DiskReadCHS();
|
extern void v86DiskReadCHS();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user