Misc fixes to disk driver and real mode ints
This commit is contained in:
parent
33ce263987
commit
859b767b5d
|
@ -7,7 +7,7 @@
|
|||
|
||||
#define SECTOR_SIZE 512
|
||||
|
||||
static uint64_t last_sector = -1;
|
||||
static uint64_t cached_sector = -1;
|
||||
static uint8_t sector_buf[512];
|
||||
|
||||
static struct {
|
||||
|
@ -18,25 +18,38 @@ static struct {
|
|||
uint64_t lba;
|
||||
} dap = { 16, 1, 0, 0, 0 };
|
||||
|
||||
int read_sector(int drive, void *buffer, uint64_t lba, size_t count) {
|
||||
static int cache_sector(int drive, uint64_t lba) {
|
||||
if (lba == cached_sector)
|
||||
return 0;
|
||||
|
||||
dap.offset = (uint16_t)(size_t)sector_buf;
|
||||
dap.lba = lba;
|
||||
|
||||
struct rm_regs r = {0};
|
||||
r.eax = 0x4200;
|
||||
r.edx = drive;
|
||||
r.esi = (uint32_t)&dap;
|
||||
|
||||
rm_int(0x13, &r, &r);
|
||||
|
||||
if (r.eflags & EFLAGS_CF) {
|
||||
int ah = (r.eax >> 8) & 0xff;
|
||||
print("Disk error %x. Drive %x, LBA %x.\n", ah, drive, lba);
|
||||
return ah;
|
||||
}
|
||||
|
||||
cached_sector = lba;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_sector(int drive, void *buffer, uint64_t lba, uint64_t count) {
|
||||
while (count--) {
|
||||
dap.lba = lba;
|
||||
struct rm_regs r = {0};
|
||||
r.eax = 0x4200;
|
||||
r.edx = drive;
|
||||
r.esi = (unsigned int)&dap;
|
||||
rm_int(0x13, &r, &r);
|
||||
|
||||
int ah = (r.eax >> 8) & 0xFF;
|
||||
if (ah) {
|
||||
print("Disk error %x\n", ah);
|
||||
return ah;
|
||||
}
|
||||
int ret;
|
||||
if ((ret = cache_sector(drive, lba++)))
|
||||
return ret;
|
||||
|
||||
memcpy(buffer, sector_buf, SECTOR_SIZE);
|
||||
last_sector = lba++;
|
||||
|
||||
buffer += SECTOR_SIZE;
|
||||
}
|
||||
|
@ -44,29 +57,22 @@ int read_sector(int drive, void *buffer, uint64_t lba, size_t count) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int read(int drive, void *buffer, int offset, size_t count) {
|
||||
int res;
|
||||
|
||||
if (last_sector == (uint64_t)-1)
|
||||
if ((res = read_sector(drive, sector_buf, 0, 1)))
|
||||
return res;
|
||||
|
||||
uint64_t cur_sector = last_sector + (offset / SECTOR_SIZE);
|
||||
offset %= SECTOR_SIZE;
|
||||
int read(int drive, void *buffer, uint64_t loc, uint64_t count) {
|
||||
uint64_t progress = 0;
|
||||
while (progress < count) {
|
||||
uint64_t sect = (loc + progress) / SECTOR_SIZE;
|
||||
|
||||
size_t sectors_count = 1 + ((offset + count) / SECTOR_SIZE);
|
||||
int ret;
|
||||
if ((ret = cache_sector(drive, sect)))
|
||||
return ret;
|
||||
|
||||
while (sectors_count--) {
|
||||
if (cur_sector != last_sector)
|
||||
if ((res = read_sector(drive, sector_buf, cur_sector, 1)))
|
||||
return res;
|
||||
uint64_t chunk = count - progress;
|
||||
uint64_t offset = (loc + progress) % SECTOR_SIZE;
|
||||
if (chunk > SECTOR_SIZE - offset)
|
||||
chunk = SECTOR_SIZE - offset;
|
||||
|
||||
size_t limited_count = ((offset + count) > SECTOR_SIZE) ? (size_t)(SECTOR_SIZE - offset) : count;
|
||||
memcpy(buffer, §or_buf[offset], limited_count);
|
||||
|
||||
offset = (offset + limited_count) % SECTOR_SIZE;
|
||||
buffer += limited_count;
|
||||
cur_sector++;
|
||||
memcpy(buffer + progress, §or_buf[offset], chunk);
|
||||
progress += chunk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#ifndef __DISK_H__
|
||||
#define __DISK_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int read_sector(int, void *, uint64_t, size_t);
|
||||
int read(int, void *, int, size_t);
|
||||
int read_sector(int, void *, uint64_t, uint64_t);
|
||||
int read(int, void *, uint64_t, uint64_t);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@ void rm_int(
|
|||
"push esi\n\t"
|
||||
"push edi\n\t"
|
||||
"push ebp\n\t"
|
||||
"pushf\n\t"
|
||||
|
||||
// Jump to real mode
|
||||
"jmp 0x08:1f\n\t"
|
||||
|
@ -48,6 +49,7 @@ void rm_int(
|
|||
// Load in_regs
|
||||
"mov dword ptr ds:[5f], esp\n\t"
|
||||
"mov esp, dword ptr ds:[7f]\n\t"
|
||||
"popfd\n\t"
|
||||
"pop ebp\n\t"
|
||||
"pop edi\n\t"
|
||||
"pop esi\n\t"
|
||||
|
@ -64,7 +66,7 @@ void rm_int(
|
|||
// Load out_regs
|
||||
"mov dword ptr ds:[5f], esp\n\t"
|
||||
"mov esp, dword ptr ds:[6f]\n\t"
|
||||
"add esp, 7*4\n\t"
|
||||
"lea esp, [esp + 8*4]\n\t"
|
||||
"push eax\n\t"
|
||||
"push ebx\n\t"
|
||||
"push ecx\n\t"
|
||||
|
@ -72,6 +74,7 @@ void rm_int(
|
|||
"push esi\n\t"
|
||||
"push edi\n\t"
|
||||
"push ebp\n\t"
|
||||
"pushfd\n\t"
|
||||
"mov esp, dword ptr ds:[5f]\n\t"
|
||||
|
||||
// Jump back to pmode
|
||||
|
@ -88,6 +91,7 @@ void rm_int(
|
|||
"mov ss, ax\n\t"
|
||||
|
||||
// Restore non-scratch GPRs
|
||||
"popf\n\t"
|
||||
"pop ebp\n\t"
|
||||
"pop edi\n\t"
|
||||
"pop esi\n\t"
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
#define rm_seg(x) (unsigned short)(((int)x & 0xFFFF0) >> 4)
|
||||
#define rm_off(x) (unsigned short)(((int)x & 0x0000F) >> 0)
|
||||
|
||||
#define EFLAGS_CF (1 << 0)
|
||||
|
||||
struct rm_regs {
|
||||
uint32_t eflags;
|
||||
uint32_t ebp;
|
||||
uint32_t edi;
|
||||
uint32_t esi;
|
||||
|
|
Loading…
Reference in New Issue