Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e99bc2db1 | ||
|
|
096db148d0 | ||
|
|
663bfbb0e4 | ||
|
|
aadc59f831 | ||
|
|
5d7aacc28f | ||
|
|
4810617922 | ||
|
|
666a011a9f | ||
|
|
a6e81bf5d3 |
+334
-9
File diff suppressed because it is too large
Load Diff
@@ -195,6 +195,7 @@ procedure do_refresh_load(state: PFileBrowserState); forward;
|
||||
procedure do_refresh_build(state: PFileBrowserState); forward;
|
||||
procedure schedule_refresh(state: PFileBrowserState); forward;
|
||||
procedure fb_refresh_poll_cb(tmr: Plv_timer); cdecl; forward;
|
||||
function fb_error_name(err : TError) : pchar; forward;
|
||||
procedure fb_collect_cb(key: pchar; data: void; ud: void); forward;
|
||||
procedure do_refresh(state: PFileBrowserState); forward;
|
||||
procedure navigate_to(state: PFileBrowserState; newDir: pchar); forward;
|
||||
@@ -582,6 +583,51 @@ begin
|
||||
puint32(@state^.refresh_pending)^ := 1;
|
||||
end;
|
||||
|
||||
function fb_error_name(err : TError) : pchar;
|
||||
begin
|
||||
case err of
|
||||
eNone: fb_error_name := 'eNone';
|
||||
eUnknown: fb_error_name := 'eUnknown';
|
||||
eNotSupported: fb_error_name := 'eNotSupported';
|
||||
eOutOfMemory: fb_error_name := 'eOutOfMemory';
|
||||
eInvalidArgument: fb_error_name := 'eInvalidArgument';
|
||||
eFileInUse: fb_error_name := 'eFileInUse';
|
||||
eFileDoesNotExist: fb_error_name := 'eFileDoesNotExist';
|
||||
eInvalidFileName: fb_error_name := 'eInvalidFileName';
|
||||
eInvalidFileExtension: fb_error_name := 'eInvalidFileExtension';
|
||||
eFilenameTooLong: fb_error_name := 'eFilenameTooLong';
|
||||
eDirectoryDoesNotExist: fb_error_name := 'eDirectoryDoesNotExist';
|
||||
eDirectoryAlreadyExists: fb_error_name := 'eDirectoryAlreadyExists';
|
||||
eDirectoryNotEmpty: fb_error_name := 'eDirectoryNotEmpty';
|
||||
eDirectoryFull: fb_error_name := 'eDirectoryFull';
|
||||
eNotADirectory: fb_error_name := 'eNotADirectory';
|
||||
eWriteOnly: fb_error_name := 'eWriteOnly';
|
||||
eReadOnly: fb_error_name := 'eReadOnly';
|
||||
ePermissionDenied: fb_error_name := 'ePermissionDenied';
|
||||
eInvalidPath: fb_error_name := 'eInvalidPath';
|
||||
eTooManyOpenFiles: fb_error_name := 'eTooManyOpenFiles';
|
||||
eInvalidHandle: fb_error_name := 'eInvalidHandle';
|
||||
eFileNotLoaded: fb_error_name := 'eFileNotLoaded';
|
||||
eAlreadyExists: fb_error_name := 'eAlreadyExists';
|
||||
eDiskFull: fb_error_name := 'eDiskFull';
|
||||
eIOError: fb_error_name := 'eIOError';
|
||||
eIOTimeout: fb_error_name := 'eIOTimeout';
|
||||
eIOCancelled: fb_error_name := 'eIOCancelled';
|
||||
eDeviceNotReady: fb_error_name := 'eDeviceNotReady';
|
||||
eDeviceRemoved: fb_error_name := 'eDeviceRemoved';
|
||||
eDeviceNotFound: fb_error_name := 'eDeviceNotFound';
|
||||
eQueueFull: fb_error_name := 'eQueueFull';
|
||||
eNoFreeSlot: fb_error_name := 'eNoFreeSlot';
|
||||
eCorruptFilesystem: fb_error_name := 'eCorruptFilesystem';
|
||||
eBadSector: fb_error_name := 'eBadSector';
|
||||
eAlreadyMounted: fb_error_name := 'eAlreadyMounted';
|
||||
eNotMounted: fb_error_name := 'eNotMounted';
|
||||
eUnsupportedFilesystem: fb_error_name := 'eUnsupportedFilesystem';
|
||||
eInvalidPartitionTable: fb_error_name := 'eInvalidPartitionTable';
|
||||
eVolumeNotFound: fb_error_name := 'eVolumeNotFound';
|
||||
end;
|
||||
end;
|
||||
|
||||
{ fb_refresh_poll_cb — 50ms LVGL poll timer; when rd_ready=1, build UI }
|
||||
procedure fb_refresh_poll_cb(tmr: Plv_timer); cdecl;
|
||||
var
|
||||
@@ -604,9 +650,12 @@ begin
|
||||
case state^.wop_kind of
|
||||
1: lv_msgbox_add_text(mbox, 'Could not create folder.');
|
||||
2: lv_msgbox_add_text(mbox, 'Could not rename item.');
|
||||
3: lv_msgbox_add_text(mbox, 'Could not create file.');
|
||||
4: lv_msgbox_add_text(mbox, 'Could not delete item.');
|
||||
else
|
||||
lv_msgbox_add_text(mbox, 'Operation failed.');
|
||||
end;
|
||||
lv_msgbox_add_text(mbox, fb_error_name(state^.wop_result));
|
||||
ok_b := lv_msgbox_add_footer_button(mbox, 'OK');
|
||||
lv_obj_add_event_cb(ok_b, @fb_mbox_close_cb, LV_EVENT_CLICKED, mbox);
|
||||
end;
|
||||
@@ -619,8 +668,8 @@ begin
|
||||
kfree(void(state^.wop_path2));
|
||||
state^.wop_path2 := nil;
|
||||
end;
|
||||
{ For rename, clear selection }
|
||||
if state^.wop_kind = 2 then
|
||||
{ For rename/delete, clear selection }
|
||||
if (state^.wop_kind = 2) or (state^.wop_kind = 4) then
|
||||
clear_selection(state);
|
||||
schedule_refresh(state);
|
||||
end;
|
||||
@@ -1591,15 +1640,16 @@ begin
|
||||
@fb_delete_done, state);
|
||||
end;
|
||||
|
||||
{ Async completion callback — runs in ISR/worker context, defer to LVGL }
|
||||
{ Async completion callback — runs outside the LVGL thread, so only set flags. }
|
||||
procedure fb_delete_done(error: TError; userdata: pointer);
|
||||
var
|
||||
state: PFileBrowserState;
|
||||
begin
|
||||
state := PFileBrowserState(userdata);
|
||||
if state = nil then exit;
|
||||
state^.op_err := error;
|
||||
lv_timer_create(@fb_delete_done_timer, 1, state);
|
||||
state^.wop_kind := 4;
|
||||
state^.wop_result := error;
|
||||
puint32(@state^.wop_done)^ := 1;
|
||||
end;
|
||||
|
||||
{ Deferred UI update after delete }
|
||||
@@ -1860,15 +1910,20 @@ begin
|
||||
if (error = eNone) and (nfctx^.handle <> 0) then begin
|
||||
{ WriteFileAsync needs a non-nil buffer; Length=0 so it is never read }
|
||||
driver.storage.vfs.WriteFileAsync(nfctx^.handle, 0,
|
||||
puint8(@nfctx^.err), 0, @fb_newfile_written, nfctx);
|
||||
puint8(@nfctx^.err), 0, nil, @fb_newfile_written, nfctx);
|
||||
end else begin
|
||||
if nfctx^.handle <> 0 then
|
||||
driver.storage.vfs.CloseFile(nfctx^.handle);
|
||||
lv_timer_create(@fb_newfile_done_timer, 1, nfctx);
|
||||
if nfctx^.state <> nil then begin
|
||||
nfctx^.state^.wop_kind := 3;
|
||||
nfctx^.state^.wop_result := nfctx^.err;
|
||||
puint32(@nfctx^.state^.wop_done)^ := 1;
|
||||
end;
|
||||
kfree(void(nfctx));
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Async step 2: write complete — close handle and schedule UI refresh }
|
||||
{ Async step 2: write complete — close handle and defer UI work via poll flags }
|
||||
procedure fb_newfile_written(error: TError; userdata: pointer);
|
||||
var
|
||||
nfctx : PNewFileCtx;
|
||||
@@ -1878,7 +1933,12 @@ begin
|
||||
if error <> eNone then nfctx^.err := error;
|
||||
if nfctx^.handle <> 0 then
|
||||
driver.storage.vfs.CloseFile(nfctx^.handle);
|
||||
lv_timer_create(@fb_newfile_done_timer, 1, nfctx);
|
||||
if nfctx^.state <> nil then begin
|
||||
nfctx^.state^.wop_kind := 3;
|
||||
nfctx^.state^.wop_result := nfctx^.err;
|
||||
puint32(@nfctx^.state^.wop_done)^ := 1;
|
||||
end;
|
||||
kfree(void(nfctx));
|
||||
end;
|
||||
|
||||
procedure fb_newfile_done_timer(tmr: Plv_timer); cdecl;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -26,7 +26,7 @@ uses
|
||||
boot.mgr,
|
||||
debug.tracer, io.stdio, proc.mgr,
|
||||
//progs
|
||||
app.base64, app.md5sum, app.dhclient, app.vbeinfo, app.testcmd, app.ping, app.meminfo, app.setres,
|
||||
app.base64, app.md5sum, app.dhclient, app.vbeinfo, app.testcmd, app.ping, app.meminfo, app.setres, app.iotest,
|
||||
//drivers
|
||||
driver.storage.ctl.ram, driver.mgr,
|
||||
//network
|
||||
@@ -92,6 +92,7 @@ begin
|
||||
app.bsod.init();
|
||||
app.vterminal.init;
|
||||
app.filebrowser.init();
|
||||
app.iotest.init();
|
||||
end;
|
||||
|
||||
Initialization
|
||||
|
||||
@@ -44,6 +44,7 @@ function inl(port : uint16) : uint32;
|
||||
procedure io_wait;
|
||||
|
||||
procedure __SSE_128_memcpy(source : uint32; dest : uint32);
|
||||
procedure __REP_MOVSB_memcpy(source : uint32; dest : uint32; size : uint32);
|
||||
|
||||
procedure halt_and_catch_fire();
|
||||
procedure halt_and_dont_catch_fire();
|
||||
@@ -113,6 +114,19 @@ asm
|
||||
MOVAPS [EAX], XMM1
|
||||
end;
|
||||
|
||||
procedure __REP_MOVSB_memcpy(source : uint32; dest : uint32; size : uint32); assembler;
|
||||
asm
|
||||
push esi
|
||||
push edi
|
||||
cld
|
||||
mov esi, source
|
||||
mov edi, dest
|
||||
mov ecx, size
|
||||
rep movsb
|
||||
pop edi
|
||||
pop esi
|
||||
end;
|
||||
|
||||
function getESP : uint32;
|
||||
var
|
||||
tmp: uint32;
|
||||
|
||||
+28
-9
@@ -42,6 +42,26 @@ function HexCharToDecimal(hex : char) : uint8;
|
||||
function abs(x : sint32) : uint32;
|
||||
|
||||
implementation
|
||||
{$ifdef CPU386}
|
||||
uses
|
||||
arch.x86.util;
|
||||
|
||||
const
|
||||
MEMCPY_X86_SMALL_COPY_THRESHOLD = 16;
|
||||
{$endif}
|
||||
|
||||
procedure scalar_memcpy(source : uint32; dest : uint32; size : uint32);
|
||||
var
|
||||
src, dst : puint8;
|
||||
i : uint32;
|
||||
begin
|
||||
if size = 0 then exit;
|
||||
for i := 0 to size - 1 do begin
|
||||
src := puint8(source + i);
|
||||
dst := puint8(dest + i);
|
||||
dst^ := src^;
|
||||
end;
|
||||
end;
|
||||
|
||||
function abs(x : sint32) : uint32;
|
||||
var
|
||||
@@ -123,17 +143,16 @@ begin
|
||||
end;
|
||||
|
||||
procedure memcpy(source : uint32; dest : uint32; size : uint32);
|
||||
var
|
||||
src, dst : puint8;
|
||||
i : uint32;
|
||||
|
||||
begin
|
||||
if size = 0 then exit;
|
||||
for i:=0 to size-1 do begin
|
||||
src:= puint8(source + i);
|
||||
dst:= puint8(dest + i);
|
||||
dst^:= src^;
|
||||
end;
|
||||
{$ifdef CPU386}
|
||||
if size < MEMCPY_X86_SMALL_COPY_THRESHOLD then
|
||||
scalar_memcpy(source, dest, size)
|
||||
else
|
||||
arch.x86.util.__REP_MOVSB_memcpy(source, dest, size);
|
||||
{$else}
|
||||
scalar_memcpy(source, dest, size);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
function getWord(i : uint32; hi : boolean) : uint16;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -269,6 +269,9 @@ type
|
||||
port : PHBA_Port;
|
||||
device_type : TDeviceType;
|
||||
ata_info : TIdentResponse;
|
||||
supportsNCQ : boolean;
|
||||
queueDepth : uint32; { safe active depth for this device }
|
||||
slotCount : uint32; { controller slot count from CAP.NCS + 1 }
|
||||
command_list : PHBA_CMD_HEADER;
|
||||
fis : PHBA_FIS;
|
||||
command_table: PHBA_CMD_TABLE;
|
||||
@@ -335,4 +338,3 @@ end;
|
||||
// end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
@@ -82,38 +82,12 @@ end;
|
||||
|
||||
{ ---- Filesystem hook callbacks ---- }
|
||||
|
||||
{ PPReadHook — load entire file into a new kalloc'd buffer.
|
||||
Sets buffer^ to the data pointer, bytecount^ to the size.
|
||||
Returns 0 on success, 1 on failure. }
|
||||
function rd_Read(volume : PStorage_Volume; directory : pchar;
|
||||
fileName : pchar; buffer : puint32;
|
||||
bytecount : puint32) : uint32;
|
||||
var
|
||||
clean : pchar;
|
||||
idx : sint32;
|
||||
dest : puint8;
|
||||
begin
|
||||
rd_Read := 1;
|
||||
clean := stripLeadingSlash(fileName);
|
||||
if clean = nil then exit;
|
||||
idx := findFileByName(clean);
|
||||
if idx < 0 then exit;
|
||||
|
||||
{ VFS expects a fresh buffer it can own }
|
||||
dest := puint8(kalloc(Files[idx].Size));
|
||||
if dest = nil then exit;
|
||||
memcpy(uint32(Files[idx].Data), uint32(dest), Files[idx].Size);
|
||||
|
||||
buffer^ := uint32(dest);
|
||||
bytecount^ := Files[idx].Size;
|
||||
rd_Read := 0;
|
||||
end;
|
||||
|
||||
{ PPReadOffsetHook — read byteCount bytes at offset into caller buffer.
|
||||
Returns actual bytes copied. }
|
||||
function rd_ReadOffset(volume : PStorage_Volume; directory : pchar;
|
||||
fileName : pchar; offset : uint32;
|
||||
buffer : puint32; byteCount : uint32) : uint32;
|
||||
buffer : puint32; byteCount : uint32;
|
||||
ctx : pointer) : uint32;
|
||||
var
|
||||
clean : pchar;
|
||||
idx : sint32;
|
||||
@@ -133,6 +107,20 @@ begin
|
||||
rd_ReadOffset := copyLen;
|
||||
end;
|
||||
|
||||
function rd_FileSize(volume : PStorage_Volume; directory : pchar;
|
||||
fileName : pchar) : uint32;
|
||||
var
|
||||
clean : pchar;
|
||||
idx : sint32;
|
||||
begin
|
||||
rd_FileSize := 0;
|
||||
clean := stripLeadingSlash(fileName);
|
||||
if clean = nil then exit;
|
||||
idx := findFileByName(clean);
|
||||
if idx < 0 then exit;
|
||||
rd_FileSize := Files[idx].Size;
|
||||
end;
|
||||
|
||||
{ PPReadDirHook — return a linked list of TDirectory_Entry for all files.
|
||||
VFS owns the returned list and frees each entry^.fileName. }
|
||||
function rd_ReadDir(volume : PStorage_Volume; directory : pchar;
|
||||
@@ -269,9 +257,9 @@ begin
|
||||
{ Set up a minimal filesystem descriptor with our callbacks }
|
||||
memset(uint32(@RAMFS), 0, sizeof(TFilesystem));
|
||||
RAMFS.sName := 'ramfs';
|
||||
RAMFS.readCallback := @rd_Read;
|
||||
RAMFS.readDirCallback := @rd_ReadDir;
|
||||
RAMFS.readOffsetCallback := @rd_ReadOffset;
|
||||
RAMFS.fileSizeCallback := @rd_FileSize;
|
||||
RAMFS.identifyCallback := @rd_Identify;
|
||||
|
||||
{ Set up a virtual volume backed by our filesystem }
|
||||
|
||||
@@ -45,10 +45,12 @@ const
|
||||
ATA_CMD_READ_PIO_EXT = $24;
|
||||
ATA_CMD_READ_DMA = $C8;
|
||||
ATA_CMD_READ_DMA_EXT = $25;
|
||||
ATA_CMD_READ_FPDMA_QUEUED = $60;
|
||||
ATA_CMD_WRITE_PIO = $30;
|
||||
ATA_CMD_WRITE_PIO_EXT = $34;
|
||||
ATA_CMD_WRITE_DMA = $CA;
|
||||
ATA_CMD_WRITE_DMA_EXT = $35;
|
||||
ATA_CMD_WRITE_FPDMA_QUEUED = $61;
|
||||
ATA_CMD_CACHE_FLUSH = $E7;
|
||||
ATA_CMD_CACHE_FLUSH_EXT = $EA;
|
||||
ATA_CMD_PACKET = $A0;
|
||||
@@ -146,4 +148,4 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
end.
|
||||
|
||||
@@ -37,17 +37,17 @@ type
|
||||
PFileDescriptor = ^TFileDescriptor;
|
||||
TFileDescriptor = record
|
||||
InUse : boolean;
|
||||
AsyncRefs : uint32; { in-flight async ops using this descriptor }
|
||||
Volume : PStorage_Volume;
|
||||
Directory : pchar; { directory path within the volume }
|
||||
FileName : pchar; { filename within that directory }
|
||||
VFSDir : pchar; { full VFS parent directory path, e.g. '/sys' }
|
||||
OpenMode : uint8; { TOpenMode ordinal — avoids VFS type dependency }
|
||||
DataBuffer : puint32; { pre-loaded data for small files, nil otherwise }
|
||||
DataSize : uint32; { size of pre-loaded data in bytes }
|
||||
Loaded : boolean; { true if pre-loaded into DataBuffer }
|
||||
StreamOff : uint32; { current byte offset for streaming / on-demand reads }
|
||||
DataSize : uint32; { cached file size in bytes (from fileSizeCallback) }
|
||||
DeviceOps : pointer; { PVFSDeviceOps — non-nil for device FDs }
|
||||
DeviceData : pointer; { opaque data passed to device callbacks }
|
||||
FSPrivate : pointer; { opaque FS-level per-file metadata (from openFileCallback) }
|
||||
FSCloseHook : pointer; { procedure(pointer) — frees FSPrivate on close }
|
||||
end;
|
||||
|
||||
PFDTable = ^TFDTable;
|
||||
@@ -71,6 +71,9 @@ function fd_alloc(table : PFDTable) : uint32;
|
||||
{ Get a pointer to the descriptor for a 1-based handle.
|
||||
Returns nil if handle is out of range or the slot is not in use. }
|
||||
function fd_get(table : PFDTable; handle : uint32) : PFileDescriptor;
|
||||
function fd_begin_async(entry : PFileDescriptor) : boolean;
|
||||
procedure fd_end_async(entry : PFileDescriptor);
|
||||
function fd_has_async(entry : PFileDescriptor) : boolean;
|
||||
|
||||
{ Close a single file descriptor: free its buffers and core.strings,
|
||||
mark the slot as not-in-use.
|
||||
@@ -81,6 +84,10 @@ function fd_close(table : PFDTable; handle : uint32) : boolean;
|
||||
Used during process cleanup. }
|
||||
procedure fd_close_all(table : PFDTable);
|
||||
|
||||
{ Close all file descriptors in the table that reference a specific volume.
|
||||
Called when a volume is removed to prevent dangling pointers. }
|
||||
procedure fd_close_for_volume(table : PFDTable; vol : PStorage_Volume);
|
||||
|
||||
implementation
|
||||
|
||||
function fd_table_new : PFDTable;
|
||||
@@ -93,15 +100,20 @@ begin
|
||||
fd_table_new := tbl;
|
||||
end;
|
||||
|
||||
type
|
||||
TFSPrivateClose = procedure(data : pointer);
|
||||
|
||||
procedure fd_free_entry(entry : PFileDescriptor);
|
||||
begin
|
||||
if entry = nil then exit;
|
||||
if not entry^.InUse then exit;
|
||||
|
||||
if entry^.DataBuffer <> nil then begin
|
||||
kfree(entry^.DataBuffer);
|
||||
entry^.DataBuffer := nil;
|
||||
end;
|
||||
{ Free FS-level per-file metadata first }
|
||||
if (entry^.FSPrivate <> nil) and (entry^.FSCloseHook <> nil) then
|
||||
TFSPrivateClose(entry^.FSCloseHook)(entry^.FSPrivate);
|
||||
entry^.FSPrivate := nil;
|
||||
entry^.FSCloseHook := nil;
|
||||
|
||||
if entry^.Directory <> nil then begin
|
||||
kfree(void(entry^.Directory));
|
||||
entry^.Directory := nil;
|
||||
@@ -116,9 +128,8 @@ begin
|
||||
end;
|
||||
|
||||
entry^.InUse := false;
|
||||
entry^.Loaded := false;
|
||||
entry^.AsyncRefs := 0;
|
||||
entry^.DataSize := 0;
|
||||
entry^.StreamOff := 0;
|
||||
entry^.DeviceOps := nil;
|
||||
entry^.DeviceData := nil;
|
||||
end;
|
||||
@@ -153,6 +164,34 @@ begin
|
||||
fd_get := @table^.Entries[handle - 1];
|
||||
end;
|
||||
|
||||
function fd_begin_async(entry : PFileDescriptor) : boolean;
|
||||
begin
|
||||
fd_begin_async := false;
|
||||
if entry = nil then exit;
|
||||
asm pushf; cli end;
|
||||
if entry^.InUse then begin
|
||||
entry^.AsyncRefs := entry^.AsyncRefs + 1;
|
||||
fd_begin_async := true;
|
||||
end;
|
||||
asm popf end;
|
||||
end;
|
||||
|
||||
procedure fd_end_async(entry : PFileDescriptor);
|
||||
begin
|
||||
if entry = nil then exit;
|
||||
asm pushf; cli end;
|
||||
if entry^.AsyncRefs > 0 then
|
||||
entry^.AsyncRefs := entry^.AsyncRefs - 1;
|
||||
asm popf end;
|
||||
end;
|
||||
|
||||
function fd_has_async(entry : PFileDescriptor) : boolean;
|
||||
begin
|
||||
fd_has_async := false;
|
||||
if entry = nil then exit;
|
||||
fd_has_async := entry^.AsyncRefs > 0;
|
||||
end;
|
||||
|
||||
function fd_close(table : PFDTable; handle : uint32) : boolean;
|
||||
begin
|
||||
fd_close := false;
|
||||
@@ -174,4 +213,16 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure fd_close_for_volume(table : PFDTable; vol : PStorage_Volume);
|
||||
var
|
||||
i : uint32;
|
||||
begin
|
||||
if table = nil then exit;
|
||||
if vol = nil then exit;
|
||||
for i := 0 to MAX_FDS - 1 do begin
|
||||
if table^.Entries[i].InUse and (table^.Entries[i].Volume = vol) then
|
||||
fd_free_entry(@table^.Entries[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@@ -219,10 +219,9 @@ begin
|
||||
validity := driver.storage.vfs.PathValid(absPath);
|
||||
if validity <> pvFile then exit;
|
||||
|
||||
{ 2. Open the file in stream mode — only reads the bytes we ask for,
|
||||
avoids pre-loading the entire file just to check a few magic bytes. }
|
||||
{ 2. Open the file for reading — reads the magic bytes on demand. }
|
||||
err := eNone;
|
||||
fh := driver.storage.vfs.OpenFile(absPath, omStream, @err);
|
||||
fh := driver.storage.vfs.OpenFile(absPath, omRead, @err);
|
||||
if fh = 0 then exit;
|
||||
|
||||
memset(uint32(@headerBuf[0]), 0, MAX_MAGIC_LEN);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
{
|
||||
Driver->Storage->IORequest - I/O request allocation and lifecycle helpers.
|
||||
|
||||
Provides heap allocation/free for TIORequest records used by the
|
||||
Provides fixed-pool allocation/free for TIORequest records used by the
|
||||
submit_io / complete_io path in driver.storage.mgr.pas.
|
||||
|
||||
@author(Aaron Hance <[email protected]>)
|
||||
@@ -27,7 +27,7 @@ uses
|
||||
memory.heap,
|
||||
driver.storage.types;
|
||||
|
||||
{ Allocate a new TIORequest on the heap and initialise its core fields.
|
||||
{ Allocate a new TIORequest from the fixed request pool and initialise its core fields.
|
||||
Caller, State, Error and ByteCount are zeroed (caller fills as needed). }
|
||||
function ioreq_alloc(reqType : TIORequestType;
|
||||
device : PStorage_Device;
|
||||
@@ -35,16 +35,90 @@ function ioreq_alloc(reqType : TIORequestType;
|
||||
sectors : uint32;
|
||||
buf : pointer) : PIORequest;
|
||||
|
||||
{ Free a heap-allocated TIORequest. Safe to call with nil. }
|
||||
{ Return a pooled TIORequest to the free list. Safe to call with nil. }
|
||||
procedure ioreq_free(req : PIORequest);
|
||||
|
||||
{ Copy an existing TIORequest into a new heap allocation (deep copy of the
|
||||
{ Copy an existing TIORequest into a new pooled allocation (deep copy of the
|
||||
record, NOT the buffer it points to). Used by dispatch_next to create an
|
||||
ISR-safe copy from the CFIFO value-element. }
|
||||
function ioreq_copy(src : PIORequest) : PIORequest;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
IOREQ_POOL_CAPACITY = 512;
|
||||
IOREQ_REQ_OFFSET = sizeof(pointer);
|
||||
|
||||
type
|
||||
PIORequestPoolNode = ^TIORequestPoolNode;
|
||||
TIORequestPoolNode = record
|
||||
Next : PIORequestPoolNode;
|
||||
Req : TIORequest;
|
||||
end;
|
||||
|
||||
var
|
||||
ioreqPoolReady : boolean;
|
||||
ioreqPoolBuf : pointer;
|
||||
ioreqFreeList : PIORequestPoolNode;
|
||||
|
||||
procedure ioreq_pool_init();
|
||||
var
|
||||
i : uint32;
|
||||
base : uint32;
|
||||
node : PIORequestPoolNode;
|
||||
begin
|
||||
if ioreqPoolReady then exit;
|
||||
|
||||
ioreqPoolBuf := kalloc(IOREQ_POOL_CAPACITY * sizeof(TIORequestPoolNode));
|
||||
if ioreqPoolBuf = nil then exit;
|
||||
|
||||
ioreqFreeList := nil;
|
||||
base := uint32(ioreqPoolBuf);
|
||||
if IOREQ_POOL_CAPACITY > 0 then
|
||||
for i := 0 to IOREQ_POOL_CAPACITY - 1 do begin
|
||||
node := PIORequestPoolNode(base + (i * sizeof(TIORequestPoolNode)));
|
||||
node^.Next := ioreqFreeList;
|
||||
ioreqFreeList := node;
|
||||
end;
|
||||
|
||||
ioreqPoolReady := true;
|
||||
end;
|
||||
|
||||
function ioreq_take() : PIORequest;
|
||||
var
|
||||
node : PIORequestPoolNode;
|
||||
begin
|
||||
if not ioreqPoolReady then
|
||||
ioreq_pool_init();
|
||||
if not ioreqPoolReady then begin
|
||||
ioreq_take := nil;
|
||||
exit;
|
||||
end;
|
||||
|
||||
asm pushf; cli end;
|
||||
node := ioreqFreeList;
|
||||
if node <> nil then
|
||||
ioreqFreeList := node^.Next;
|
||||
asm popf end;
|
||||
|
||||
if node = nil then
|
||||
ioreq_take := nil
|
||||
else
|
||||
ioreq_take := @node^.Req;
|
||||
end;
|
||||
|
||||
procedure ioreq_release(req : PIORequest);
|
||||
var
|
||||
node : PIORequestPoolNode;
|
||||
begin
|
||||
if req = nil then exit;
|
||||
node := PIORequestPoolNode(uint32(req) - IOREQ_REQ_OFFSET);
|
||||
asm pushf; cli end;
|
||||
node^.Next := ioreqFreeList;
|
||||
ioreqFreeList := node;
|
||||
asm popf end;
|
||||
end;
|
||||
|
||||
function ioreq_alloc(reqType : TIORequestType;
|
||||
device : PStorage_Device;
|
||||
lba : uint32;
|
||||
@@ -53,7 +127,7 @@ function ioreq_alloc(reqType : TIORequestType;
|
||||
var
|
||||
req : PIORequest;
|
||||
begin
|
||||
req := PIORequest(kalloc(SizeOf(TIORequest)));
|
||||
req := ioreq_take();
|
||||
if req = nil then begin
|
||||
ioreq_alloc := nil;
|
||||
exit;
|
||||
@@ -75,15 +149,14 @@ end;
|
||||
|
||||
procedure ioreq_free(req : PIORequest);
|
||||
begin
|
||||
if req <> nil then
|
||||
kfree(void(req));
|
||||
ioreq_release(req);
|
||||
end;
|
||||
|
||||
function ioreq_copy(src : PIORequest) : PIORequest;
|
||||
var
|
||||
dst : PIORequest;
|
||||
begin
|
||||
dst := PIORequest(kalloc(SizeOf(TIORequest)));
|
||||
dst := ioreq_take();
|
||||
if dst = nil then begin
|
||||
ioreq_copy := nil;
|
||||
exit;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user