Disk does very basic read caching
This commit is contained in:
parent
89c0f95219
commit
d1024d7793
78
disk.c
78
disk.c
@ -5,6 +5,13 @@
|
|||||||
|
|
||||||
extern void *memcpy(void *restrict dest, const void *restrict src, uintptr_t n);
|
extern void *memcpy(void *restrict dest, const void *restrict src, uintptr_t n);
|
||||||
|
|
||||||
|
uintptr_t DiskCacheBlockSize = 0x1000; // 512 * 4
|
||||||
|
uintptr_t DiskCacheSectorMask = 7;
|
||||||
|
uintptr_t DiskCacheSectorSize = 8;
|
||||||
|
uint8_t (*DiskCache)[128][0x1000] = (uint8_t (*)[128][0x1000])0x280000;
|
||||||
|
uint32_t DiskCacheLastRead[128];
|
||||||
|
uint32_t DiskCacheSector[128];
|
||||||
|
|
||||||
extern uint32_t _gpf_eax_save;
|
extern uint32_t _gpf_eax_save;
|
||||||
extern uint32_t _gpf_eflags_save;
|
extern uint32_t _gpf_eflags_save;
|
||||||
extern uint16_t error_screen[80*50]; // defined in kernel.c
|
extern uint16_t error_screen[80*50]; // defined in kernel.c
|
||||||
@ -14,6 +21,7 @@ uint32_t numHead;
|
|||||||
uint32_t secPerTrack;
|
uint32_t secPerTrack;
|
||||||
uint32_t maxCylinder;
|
uint32_t maxCylinder;
|
||||||
char useCHS = -1;
|
char useCHS = -1;
|
||||||
|
// TODO This function also inits cache, make that go somewhere else
|
||||||
void Disk_SetupCHS() {
|
void Disk_SetupCHS() {
|
||||||
union V86Regs_t regs;
|
union V86Regs_t regs;
|
||||||
// Check for INT 13 Extensions support
|
// Check for INT 13 Extensions support
|
||||||
@ -39,25 +47,77 @@ void Disk_SetupCHS() {
|
|||||||
maxCylinder = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2);
|
maxCylinder = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2);
|
||||||
useCHS = 1;
|
useCHS = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init Cache
|
||||||
|
for (int i = 0; i < 128; i++) {
|
||||||
|
DiskCacheLastRead[i] = 0;
|
||||||
|
DiskCacheSector[i] = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern uint32_t TIMERVAL;
|
||||||
|
uint8_t *FindInCache(uint32_t sector) {
|
||||||
|
uint32_t maskedSector = sector & ~DiskCacheSectorMask;
|
||||||
|
for (int i = 0; i < 128; i++) {
|
||||||
|
// Found
|
||||||
|
if (DiskCacheSector[i] == maskedSector) {
|
||||||
|
DiskCacheLastRead[i] = TIMERVAL;
|
||||||
|
return &(*DiskCache)[i][(sector & DiskCacheSectorMask) << 9];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Not Found
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddToCache(uint32_t sector, uint8_t *buffer) {
|
||||||
|
uintptr_t lowestFoundTime = DiskCacheLastRead[0];
|
||||||
|
uintptr_t lowestFoundIdx = 0;
|
||||||
|
for (int i = 1; i < 32; i++) {
|
||||||
|
if (DiskCacheLastRead[i] < lowestFoundTime) {
|
||||||
|
lowestFoundTime = DiskCacheLastRead[i];
|
||||||
|
lowestFoundIdx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < DiskCacheBlockSize / sizeof(uint32_t); i++)
|
||||||
|
((uint32_t *)((*DiskCache)[lowestFoundIdx]))[i] = ((uint32_t*)buffer)[i];
|
||||||
|
DiskCacheLastRead[lowestFoundIdx] = TIMERVAL;
|
||||||
|
DiskCacheSector[lowestFoundIdx] = sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE Only updates one sector (512B)
|
||||||
|
void UpdateCache(uint32_t sector, uint8_t *buffer) {
|
||||||
|
uint8_t *cache = FindInCache(sector);
|
||||||
|
// Not in cache, nothing to update
|
||||||
|
if (!cache) return;
|
||||||
|
for (int i = 0; i < SECTOR_SIZE/sizeof(uint32_t); i++)
|
||||||
|
((uint32_t*)cache)[i] = ((uint32_t*)buffer)[i];
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
|
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,
|
// NOTE If the buffer provided is outside the 0x20000-0x2FE00 range,
|
||||||
// the function will use that buffer for the Virtual 8086 process
|
// the function will use that buffer for the Virtual 8086 process
|
||||||
// and copy to the other buffer after
|
// and copy to the other buffer after
|
||||||
uint8_t *v86buf = buffer;
|
uint8_t *v86buf = buffer;
|
||||||
if ((uintptr_t)v86buf < 0x20000 || (uintptr_t)v86buf > 0x2FE00)
|
if ((uintptr_t)v86buf >= 0x20000 && (uintptr_t)v86buf < 0x28000)
|
||||||
v86buf = (uint8_t *)0x20000;
|
v86buf = (uint8_t *)0x28000;
|
||||||
|
else v86buf = (uint8_t *)0x20000;
|
||||||
|
|
||||||
// TODO This check should probably happen at the kernel level
|
// TODO This check should probably happen at the kernel level
|
||||||
if (useCHS == -1) {
|
if (useCHS == -1) {
|
||||||
Disk_SetupCHS();
|
Disk_SetupCHS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t *cache = FindInCache(sector);
|
||||||
|
if (cache) {
|
||||||
|
memcpy(buffer, cache, count * SECTOR_SIZE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Do error handling
|
// TODO Do error handling
|
||||||
if (!useCHS) {
|
if (!useCHS) {
|
||||||
// LBA Read
|
// LBA Read
|
||||||
v86disk_addr_packet.start_block = sector;
|
v86disk_addr_packet.start_block = sector & ~DiskCacheSectorMask;
|
||||||
v86disk_addr_packet.blocks = count;
|
v86disk_addr_packet.blocks = DiskCacheSectorSize;
|
||||||
v86disk_addr_packet.transfer_buffer =
|
v86disk_addr_packet.transfer_buffer =
|
||||||
(uintptr_t)v86buf & 0x000F |
|
(uintptr_t)v86buf & 0x000F |
|
||||||
(((uintptr_t)v86buf & 0xFFFF0) << 12);
|
(((uintptr_t)v86buf & 0xFFFF0) << 12);
|
||||||
@ -65,6 +125,15 @@ uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t
|
|||||||
regs.h.ah = 0x42;
|
regs.h.ah = 0x42;
|
||||||
FARPTR v86_entry = i386LinearToFp(v86DiskOp);
|
FARPTR v86_entry = i386LinearToFp(v86DiskOp);
|
||||||
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||||
|
if (v86disk_addr_packet.blocks != DiskCacheSectorSize) {
|
||||||
|
uint16_t *vga = error_screen;
|
||||||
|
vga += printStr("INT13 Read Secs: ", vga);
|
||||||
|
vga += printDec(v86disk_addr_packet.blocks, vga);
|
||||||
|
error_environment();
|
||||||
|
for(;;);
|
||||||
|
}
|
||||||
|
AddToCache(sector & ~DiskCacheSectorMask, v86buf);
|
||||||
|
v86buf = &v86buf[(sector & DiskCacheSectorMask) << 9];
|
||||||
} else {
|
} else {
|
||||||
uint32_t tmp = sector / secPerTrack;
|
uint32_t tmp = sector / secPerTrack;
|
||||||
uint32_t sec = (sector % (secPerTrack)) + 1;
|
uint32_t sec = (sector % (secPerTrack)) + 1;
|
||||||
@ -110,6 +179,7 @@ uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_
|
|||||||
regs.w.ax = 0x4300;
|
regs.w.ax = 0x4300;
|
||||||
FARPTR v86_entry = i386LinearToFp(v86DiskOp);
|
FARPTR v86_entry = i386LinearToFp(v86DiskOp);
|
||||||
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||||
|
UpdateCache(sector, buffer);
|
||||||
} else {
|
} else {
|
||||||
uint16_t *vga = error_screen;
|
uint16_t *vga = error_screen;
|
||||||
vga += printStr("CHS Write Unimplemented", vga);
|
vga += printStr("CHS Write Unimplemented", vga);
|
||||||
|
@ -50,6 +50,7 @@ test eax, eax
|
|||||||
jz .loop
|
jz .loop
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
global TIMERVAL
|
||||||
TIMERVAL: dd 0
|
TIMERVAL: dd 0
|
||||||
global timerHandler
|
global timerHandler
|
||||||
timerHandler:
|
timerHandler:
|
||||||
|
3
kernel.c
3
kernel.c
@ -174,7 +174,8 @@ Protected Only (1MB+)
|
|||||||
100000 - 200000 Kernel Code (1mB)
|
100000 - 200000 Kernel Code (1mB)
|
||||||
200000 - 200080 TSS (128B)
|
200000 - 200080 TSS (128B)
|
||||||
200080 - 202080 TSS IOMAP (8kB)
|
200080 - 202080 TSS IOMAP (8kB)
|
||||||
202080 - 300000 Free (~1mB)
|
202080 - 300000 Free (~1/2mB)
|
||||||
|
280000 - 300000 Disk Cache (512kB)
|
||||||
300000 - 310000 Task Stack (64kB)
|
300000 - 310000 Task Stack (64kB)
|
||||||
310000 - 320000 Interrupt Stack (64kB)
|
310000 - 320000 Interrupt Stack (64kB)
|
||||||
320000 - 400000 Kernel Stack (896kB)
|
320000 - 400000 Kernel Stack (896kB)
|
||||||
|
Loading…
Reference in New Issue
Block a user