Compare commits
60
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ae867d929 | ||
|
|
40a1c05728 | ||
|
|
2bfbb44cfb | ||
|
|
8ab2d0d04f | ||
|
|
b51881ced7 | ||
|
|
0d6f1e006c | ||
|
|
6902a406b0 | ||
|
|
36ec7bfdb6 | ||
|
|
6c3c0e63d5 | ||
|
|
df71c59aea | ||
|
|
97244a2b95 | ||
|
|
ecca496978 | ||
|
|
e52b4a9763 | ||
|
|
f78eaa3811 | ||
|
|
acb4a15e41 | ||
|
|
d3581eea2e | ||
|
|
1fc00e3e7c | ||
|
|
2f837ace6e | ||
|
|
f8182b24b3 | ||
|
|
f0531ff861 | ||
|
|
3d9c4cb49a | ||
|
|
3a733b1559 | ||
|
|
deb513c925 | ||
|
|
789fb7971a | ||
|
|
4e3acd6af7 | ||
|
|
262d064b6d | ||
|
|
738e5828f6 | ||
|
|
9fa1c859ac | ||
|
|
d01b534a3d | ||
|
|
491b0ea5c3 | ||
|
|
de6fde05cc | ||
|
|
fb675a2299 | ||
|
|
aa374b6816 | ||
|
|
f427b7bcc7 | ||
|
|
4ba3c5b524 | ||
|
|
7180ad39d8 | ||
|
|
6c7bcc1911 | ||
|
|
e09c9b5595 | ||
|
|
9476bb0c8a | ||
|
|
8f7db8507b | ||
|
|
188b1aebb0 | ||
|
|
452203b7b4 | ||
|
|
76c419336e | ||
|
|
2ad0ae8420 | ||
|
|
c0c199bfe6 | ||
|
|
7ec3bcb9b9 | ||
|
|
4bd0a2dfbf | ||
|
|
431e5bc8f4 | ||
|
|
8169d93a9c | ||
|
|
547251dbd0 | ||
|
|
7bbcc44c5e | ||
|
|
25475a88a7 | ||
|
|
db49c29627 | ||
|
|
c237553508 | ||
|
|
0c96d32754 | ||
|
|
3f83f279d7 | ||
|
|
82fe9fa6df | ||
|
|
983d9a428d | ||
|
|
2fa77d8295 | ||
|
|
f53afc1d2d |
No files matched your search
@@ -1 +1,8 @@
|
|||||||
* text=auto eol=lf
|
* text=auto eol=lf
|
||||||
|
lvglh/** linguist-vendored
|
||||||
|
lvgl/** linguist-vendored
|
||||||
|
.vscode/* linguist-vendored
|
||||||
|
lib/* linguist-generated
|
||||||
|
release/* linguist-generated
|
||||||
|
iso/* linguist-generated
|
||||||
|
*.asm linguist-detectable
|
||||||
@@ -14,4 +14,7 @@ localenv.json
|
|||||||
/lvgl/
|
/lvgl/
|
||||||
dockerout.txt
|
dockerout.txt
|
||||||
AGENTS.md
|
AGENTS.md
|
||||||
|
lessons_learnt.md
|
||||||
*.log
|
*.log
|
||||||
|
/doc/*.md
|
||||||
|
wasuro
|
||||||
@@ -24,6 +24,7 @@ declare -a run_steps=(
|
|||||||
"compile_stub.sh" "Failed to compile stub!"
|
"compile_stub.sh" "Failed to compile stub!"
|
||||||
"compile_vergen.sh" "Versions failed to compile"
|
"compile_vergen.sh" "Versions failed to compile"
|
||||||
"compile_lvgl.sh" "Failed to compile LVGL!"
|
"compile_lvgl.sh" "Failed to compile LVGL!"
|
||||||
|
"compile_wasuro.sh" "Failed to pull Wasuro!"
|
||||||
"compile_sources.sh" "Failed to compile FPC Sources!"
|
"compile_sources.sh" "Failed to compile FPC Sources!"
|
||||||
"compile_link.sh" "Failed linking!"
|
"compile_link.sh" "Failed linking!"
|
||||||
"compile_isogen.sh" "Failed to create ISO!"
|
"compile_isogen.sh" "Failed to create ISO!"
|
||||||
|
|||||||
+21
-7
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# compile_lvgl.sh — Download LVGL v9.2 source and compile into lib/liblvgl.a
|
# compile_lvgl.sh — Download LVGL v9.2 source and compile into lib/liblvgl.a
|
||||||
# Clone & compile in /tmp (fast container-local fs).
|
# Clone & compile in /tmp (fast container-local fs).
|
||||||
# Copy source + objects to /lvgl (host mount) for debugging.
|
# Cache liblvgl.a on host mount (/code/lvgl/) to skip rebuild.
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
LVGL_VERSION="v9.2.2"
|
LVGL_VERSION="v9.2.2"
|
||||||
@@ -10,6 +10,7 @@ LVGL_DIR="/tmp/lvgl"
|
|||||||
OBJ_DIR="/tmp/lvgl_obj"
|
OBJ_DIR="/tmp/lvgl_obj"
|
||||||
CONF_DIR="$(pwd)/lvglh"
|
CONF_DIR="$(pwd)/lvglh"
|
||||||
OUT_DIR="$(pwd)/lib"
|
OUT_DIR="$(pwd)/lib"
|
||||||
|
CACHE_DIR="/code/lvgl"
|
||||||
|
|
||||||
CC="gcc"
|
CC="gcc"
|
||||||
CFLAGS="-m32 -march=i686 -ffreestanding \
|
CFLAGS="-m32 -march=i686 -ffreestanding \
|
||||||
@@ -26,6 +27,17 @@ echo " "
|
|||||||
echo "Compiling LVGL..."
|
echo "Compiling LVGL..."
|
||||||
echo " "
|
echo " "
|
||||||
|
|
||||||
|
# If cached liblvgl.a exists on host mount, just copy it and skip everything
|
||||||
|
if [ -f "${CACHE_DIR}/liblvgl.a" ]; then
|
||||||
|
echo "Found cached liblvgl.a in ${CACHE_DIR}, copying to ${OUT_DIR}..."
|
||||||
|
cp "${CACHE_DIR}/liblvgl.a" "${OUT_DIR}/liblvgl.a"
|
||||||
|
echo "(Delete lvgl/liblvgl.a to force a full rebuild.)"
|
||||||
|
echo " "
|
||||||
|
echo "LVGL compilation complete (cached)."
|
||||||
|
echo " "
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
# Clone LVGL into /tmp (container-local)
|
# Clone LVGL into /tmp (container-local)
|
||||||
rm -rf "$LVGL_DIR"
|
rm -rf "$LVGL_DIR"
|
||||||
echo "Downloading LVGL ${LVGL_VERSION}..."
|
echo "Downloading LVGL ${LVGL_VERSION}..."
|
||||||
@@ -105,12 +117,14 @@ else
|
|||||||
echo "No custom LVGL files in lvglh/."
|
echo "No custom LVGL files in lvglh/."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy source + objects to /lvgl host mount for debugging
|
# Cache liblvgl.a and source to host mount for next build
|
||||||
echo "Copying LVGL source and objects to host mount..."
|
echo "Caching LVGL to host mount..."
|
||||||
mkdir /code/lvgl 2>/dev/null || true
|
mkdir -p "$CACHE_DIR"
|
||||||
rm -rf /code/lvgl/* /code/lvgl/.[!.]* /code/lvgl/..?* 2>/dev/null || true
|
rm -rf ${CACHE_DIR}/* ${CACHE_DIR}/.[!.]* ${CACHE_DIR}/..?* 2>/dev/null || true
|
||||||
cp -a "$LVGL_DIR/src" /code/lvgl/src
|
cp "${OUT_DIR}/liblvgl.a" "${CACHE_DIR}/liblvgl.a"
|
||||||
cp -a "$OBJ_DIR" /code/lvgl/obj
|
cp -a "$LVGL_DIR/src" "${CACHE_DIR}/src"
|
||||||
|
cp -a "$LVGL_DIR"/*.h "${CACHE_DIR}/" 2>/dev/null || true
|
||||||
|
cp -a "$OBJ_DIR" "${CACHE_DIR}/obj"
|
||||||
echo "Done."
|
echo "Done."
|
||||||
|
|
||||||
echo " "
|
echo " "
|
||||||
|
|||||||
+7
-1
@@ -4,4 +4,10 @@ echo "======================="
|
|||||||
echo " "
|
echo " "
|
||||||
echo "Compiling FPC Sources..."
|
echo "Compiling FPC Sources..."
|
||||||
echo " "
|
echo " "
|
||||||
fpc -Aelf -gw -g -gl -n -v0ew -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/driver/* -Fusrc/driver/net/* -Fusrc/driver/bus/* -Fusrc/driver/bus/usb/* -Fusrc/driver/hid/* src/kernel.pas
|
# Build -Fu flags for all directories under src/ and wasuro/
|
||||||
|
FU_PATHS="-Fusrc -Fuwasuro"
|
||||||
|
for dir in $(find src wasuro -type d 2>/dev/null); do
|
||||||
|
FU_PATHS="$FU_PATHS -Fu$dir"
|
||||||
|
done
|
||||||
|
|
||||||
|
fpc -Aelf -gw -g -gl -n -v0e -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ $FU_PATHS src/kernel.pas
|
||||||
@@ -5,3 +5,4 @@ echo " "
|
|||||||
echo "Compiling Stub..."
|
echo "Compiling Stub..."
|
||||||
echo " "
|
echo " "
|
||||||
nasm -f elf src/stub/stub.asm -o lib/stub.o
|
nasm -f elf src/stub/stub.asm -o lib/stub.o
|
||||||
|
nasm -f elf src/stub/splash_tga.asm -o lib/splash_tga.o
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# compile_wasuro.sh — Pull Wasuro WASM runtime source into wasuro/
|
||||||
|
# Clones the repo (sparse, src/wasm only) and copies the Pascal sources
|
||||||
|
# into $PWD/wasuro so the FPC build can reference them via -Fu.
|
||||||
|
set -e
|
||||||
|
|
||||||
|
WASURO_REPO="https://gitea.spexeah.com/Spexeah/Wasuro.git"
|
||||||
|
WASURO_BRANCH="develop"
|
||||||
|
WASURO_TMP="/tmp/wasuro"
|
||||||
|
WASURO_OUT="$(pwd)/wasuro"
|
||||||
|
|
||||||
|
echo " "
|
||||||
|
echo "======================="
|
||||||
|
echo " "
|
||||||
|
echo "Pulling Wasuro WASM runtime..."
|
||||||
|
echo " "
|
||||||
|
|
||||||
|
# Skip if wasuro/ already has .pas files (cached from previous build)
|
||||||
|
if [ -n "$(find "${WASURO_OUT}" -name '*.pas' 2>/dev/null | head -1)" ]; then
|
||||||
|
echo "Wasuro sources already present in ${WASURO_OUT}, skipping pull."
|
||||||
|
echo " "
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clone sparse checkout (only src/wasm)
|
||||||
|
rm -rf "$WASURO_TMP"
|
||||||
|
git clone --depth 1 --branch "${WASURO_BRANCH}" --filter=blob:none --sparse \
|
||||||
|
"${WASURO_REPO}" "${WASURO_TMP}" 2>&1
|
||||||
|
cd "$WASURO_TMP"
|
||||||
|
git sparse-checkout set src/wasm 2>&1
|
||||||
|
cd -
|
||||||
|
|
||||||
|
echo "Copying src/wasm to ${WASURO_OUT}..."
|
||||||
|
rm -rf "$WASURO_OUT"
|
||||||
|
mkdir -p "$WASURO_OUT"
|
||||||
|
cp -a "${WASURO_TMP}/src/wasm/"* "$WASURO_OUT"/
|
||||||
|
rm -rf "$WASURO_TMP"
|
||||||
|
|
||||||
|
TOTAL=$(find "$WASURO_OUT" -name '*.pas' | wc -l)
|
||||||
|
echo "Copied ${TOTAL} Pascal source files."
|
||||||
|
echo " "
|
||||||
|
echo "Wasuro pull complete."
|
||||||
|
echo " "
|
||||||
Whitespace-only changes.
@@ -0,0 +1,32 @@
|
|||||||
|
#Flat filesystem
|
||||||
|
|
||||||
|
A super simple filesystem for asuro. Folders are emulated in filenames.
|
||||||
|
|
||||||
|
Starts with disk info sector, sector 0 of volume
|
||||||
|
|
||||||
|
---
|
||||||
|
#### disk info
|
||||||
|
|
||||||
|
jmp2boot : ubit24;
|
||||||
|
OEMName : array[0..7] of char;
|
||||||
|
version : uint16 // numerical version of filesystem
|
||||||
|
sectorCount : uint16;
|
||||||
|
fileCount : uint16
|
||||||
|
signature : uint32 = 0x0B00B1E5
|
||||||
|
|
||||||
|
|
||||||
|
the Rest of the sector is reserved
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Starting from sector 1 is the file table. Table size is determined by entry size (64) * fileCount
|
||||||
|
|
||||||
|
---
|
||||||
|
####File entry
|
||||||
|
|
||||||
|
name : array[0..59] of char //file name max 60 chars
|
||||||
|
fileStart : 16bit // start sector of data
|
||||||
|
fileSize : 16bit // data size in sectors
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
Generated
+1
@@ -0,0 +1 @@
|
|||||||
|
Hello from the Asuro ISO!
|
||||||
+108
-2
@@ -13,14 +13,120 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
{
|
{
|
||||||
ContextSwitcher - Switch Process Contexts when preempted.
|
ContextSwitcher - Custom IRQ0 handler for preemptive context switching.
|
||||||
|
|
||||||
|
Replaces the default ISR_32 with a naked assembly stub that saves the
|
||||||
|
interrupted context (PUSHAD + segment regs), calls a Pascal helper to
|
||||||
|
dispatch timer hooks, send EOI, and run the scheduler, then restores
|
||||||
|
the next process context (or idles) via the returned ESP.
|
||||||
|
|
||||||
@author(Kieron Morris <[email protected]>)
|
@author(Kieron Morris <[email protected]>)
|
||||||
}
|
}
|
||||||
unit contextswitcher;
|
unit contextswitcher;
|
||||||
|
|
||||||
|
{$ASMMODE intel}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
implementation;
|
uses
|
||||||
|
idt, isrmanager, processmanager, proctypes, util, syslog, tracer;
|
||||||
|
|
||||||
|
{ Initialise: overwrite IDT gate 32 with our custom ISR. }
|
||||||
|
procedure init;
|
||||||
|
|
||||||
|
{ No idle ESP variable needed — idle is now a formal process (PID 0)
|
||||||
|
with its SavedESP managed like any other process. }
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ -----------------------------------------------------------------------
|
||||||
|
do_context_switch_work
|
||||||
|
Pascal helper called from the assembly ISR. Receives the current ESP
|
||||||
|
(pointing to the GS..EFLAGS save area), dispatches timer hooks, sends
|
||||||
|
EOI, runs the scheduler and returns the ESP for the next context.
|
||||||
|
Uses register calling convention: saved_esp in EAX, result in EAX.
|
||||||
|
----------------------------------------------------------------------- }
|
||||||
|
function do_context_switch_work(saved_esp : uint32) : uint32;
|
||||||
|
var
|
||||||
|
next : PProcessContext;
|
||||||
|
begin
|
||||||
|
{ 1. Save ESP into the current process }
|
||||||
|
processmanager.CurrentProcess^.SavedESP := saved_esp;
|
||||||
|
|
||||||
|
{ 2. Dispatch all hooks registered on interrupt 32 (timer hooks).
|
||||||
|
This fires TMR_0_ISR.Main which in turn fires BDA tick,
|
||||||
|
graphics refresh, USB hotplug, etc. }
|
||||||
|
isrmanager.dispatchHooks(32);
|
||||||
|
|
||||||
|
{ 3. Send End-Of-Interrupt to the master PIC }
|
||||||
|
outb($20, $20);
|
||||||
|
|
||||||
|
{ 4. Pick the next process to run (always returns non-nil; idle as fallback) }
|
||||||
|
next := processmanager.scheduler_pick_next;
|
||||||
|
processmanager.CurrentProcess := next;
|
||||||
|
|
||||||
|
{ 5. Return the selected process ESP }
|
||||||
|
do_context_switch_work := next^.SavedESP;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ -----------------------------------------------------------------------
|
||||||
|
context_switch_isr
|
||||||
|
Naked assembly ISR that replaces ISR_32 (IRQ0 / PIT timer).
|
||||||
|
|
||||||
|
Stack on entry (pushed by CPU):
|
||||||
|
[ESP+8] EFLAGS
|
||||||
|
[ESP+4] CS
|
||||||
|
[ESP+0] EIP
|
||||||
|
|
||||||
|
We push general-purpose and segment registers, call the Pascal helper,
|
||||||
|
switch ESP to the returned value, pop registers and IRETD.
|
||||||
|
----------------------------------------------------------------------- }
|
||||||
|
procedure context_switch_isr; assembler; nostackframe;
|
||||||
|
asm
|
||||||
|
{ Save all general-purpose registers (EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI) }
|
||||||
|
pushad
|
||||||
|
|
||||||
|
{ Save segment registers }
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push fs
|
||||||
|
push gs
|
||||||
|
|
||||||
|
{ Load kernel data segments }
|
||||||
|
mov ax, $10
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
{ Call Pascal helper: EAX = current ESP (register calling convention).
|
||||||
|
Returns new ESP in EAX. }
|
||||||
|
mov eax, esp
|
||||||
|
call do_context_switch_work
|
||||||
|
mov esp, eax
|
||||||
|
|
||||||
|
{ Restore segment registers }
|
||||||
|
pop gs
|
||||||
|
pop fs
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
|
||||||
|
{ Restore general-purpose registers }
|
||||||
|
popad
|
||||||
|
|
||||||
|
{ Return from interrupt }
|
||||||
|
iretd
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ -----------------------------------------------------------------------
|
||||||
|
init
|
||||||
|
Override IDT gate 32 with our custom ISR. Must be called AFTER
|
||||||
|
isrmanager.init so that the default gate has been set up first.
|
||||||
|
----------------------------------------------------------------------- }
|
||||||
|
procedure init;
|
||||||
|
begin
|
||||||
|
idt.set_gate(32, uint32(@context_switch_isr), $08, ISR_RING_0);
|
||||||
|
tracer.push_trace('contextswitcher.init');
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
+2
-5
@@ -22,7 +22,7 @@ unit cpu;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
util, RTC;
|
util, RTC, stdio;
|
||||||
|
|
||||||
type
|
type
|
||||||
PCapabilities_Old = ^TCapabilities_Old;
|
PCapabilities_Old = ^TCapabilities_Old;
|
||||||
@@ -113,12 +113,10 @@ var
|
|||||||
CAP_OLD, CAP_NEW : uint32;
|
CAP_OLD, CAP_NEW : uint32;
|
||||||
|
|
||||||
procedure init();
|
procedure init();
|
||||||
|
procedure Terminal_Command_CPU(Params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
|
||||||
stdio;
|
|
||||||
|
|
||||||
procedure getCPUIdentifier;
|
procedure getCPUIdentifier;
|
||||||
var
|
var
|
||||||
id0, id1, id2 : uint32;
|
id0, id1, id2 : uint32;
|
||||||
@@ -325,7 +323,6 @@ end;
|
|||||||
|
|
||||||
procedure init();
|
procedure init();
|
||||||
begin
|
begin
|
||||||
stdio.registerCommand('CPU', @Terminal_Command_CPU, 'CPU Info.');
|
|
||||||
CPUID.Capabilities0:= PCapabilities_Old(@CAP_OLD);
|
CPUID.Capabilities0:= PCapabilities_Old(@CAP_OLD);
|
||||||
CPUID.Capabilities1:= PCapabilities_New(@CAP_NEW);
|
CPUID.Capabilities1:= PCapabilities_New(@CAP_NEW);
|
||||||
getCPUIdentifier;
|
getCPUIdentifier;
|
||||||
|
|||||||
+32
-1
@@ -18,7 +18,7 @@
|
|||||||
@author(Aaron Hance <[email protected]>)
|
@author(Aaron Hance <[email protected]>)
|
||||||
@author(Kieron Morris <[email protected]>)
|
@author(Kieron Morris <[email protected]>)
|
||||||
}
|
}
|
||||||
unit PCI;
|
unit pci;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@@ -91,6 +91,7 @@ function getDeviceInfo(class_code : uint8; subclass_code : uint8; prog_if : uint
|
|||||||
procedure requestConfig(bus : uint8; slot : uint8; func : uint8; row : uint8);
|
procedure requestConfig(bus : uint8; slot : uint8; func : uint8; row : uint8);
|
||||||
procedure writeConfig(bus: uint8; slot : uint8; func : uint8; row : uint8; val : uint32);
|
procedure writeConfig(bus: uint8; slot : uint8; func : uint8; row : uint8; val : uint32);
|
||||||
procedure setBusMaster(bus : uint8; slot : uint8; func : uint8; master : boolean);
|
procedure setBusMaster(bus : uint8; slot : uint8; func : uint8; master : boolean);
|
||||||
|
procedure enableDevice(bus : uint8; slot : uint8; func : uint8);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@@ -442,4 +443,34 @@ begin
|
|||||||
pop_trace;
|
pop_trace;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
//Enable device inturrupts and set bus master
|
||||||
|
procedure enableDevice(bus : uint8; slot : uint8; func : uint8);
|
||||||
|
var
|
||||||
|
addr : uint32;
|
||||||
|
cmd : uint32;
|
||||||
|
begin
|
||||||
|
push_trace('PCI.enableDevice');
|
||||||
|
|
||||||
|
addr := ($1 shl 31);
|
||||||
|
addr := addr or (bus shl 16);
|
||||||
|
addr := addr or ((slot) shl 11);
|
||||||
|
addr := addr or ((func) shl 8);
|
||||||
|
addr := addr or ($04 and $FC);
|
||||||
|
|
||||||
|
outl(PCI_CONFIG_ADDRESS_PORT, addr);
|
||||||
|
cmd := inl(PCI_CONFIG_DATA_PORT);
|
||||||
|
cmd := cmd or PCI_COMMAND_MEM_SPACE;
|
||||||
|
cmd := cmd or PCI_COMMAND_BUS_MASTER;
|
||||||
|
cmd := cmd or (3 shl 1);
|
||||||
|
|
||||||
|
//enable interrupts, remove disable interrupt bit maybe
|
||||||
|
cmd := cmd and not PCI_COMMAND_INT_DISABLE;
|
||||||
|
// cmd := cmd and not (1 shl 9);
|
||||||
|
|
||||||
|
outl(PCI_CONFIG_ADDRESS_PORT, addr);
|
||||||
|
outl(PCI_CONFIG_DATA_PORT, cmd);
|
||||||
|
|
||||||
|
pop_trace;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
+1762
-33
File diff suppressed because it is too large.
Load diff
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
@author(Kieron Morris <[email protected]>)
|
@author(Kieron Morris <[email protected]>)
|
||||||
}
|
}
|
||||||
unit OHCI;
|
unit ohci;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@@ -23,6 +23,7 @@ uses
|
|||||||
drivermanagement,
|
drivermanagement,
|
||||||
usbtypes,
|
usbtypes,
|
||||||
usbcore,
|
usbcore,
|
||||||
|
isrmanager,
|
||||||
lists,
|
lists,
|
||||||
strings;
|
strings;
|
||||||
|
|
||||||
@@ -234,6 +235,7 @@ type
|
|||||||
EDBulk : POHCI_ED; { Head of bulk ED list }
|
EDBulk : POHCI_ED; { Head of bulk ED list }
|
||||||
EDInterrupt : POHCI_ED; { Dummy head for interrupt ED list }
|
EDInterrupt : POHCI_ED; { Dummy head for interrupt ED list }
|
||||||
NumPorts : uint8; { Number of downstream ports }
|
NumPorts : uint8; { Number of downstream ports }
|
||||||
|
PollBusy : boolean; { Re-entrancy guard for poll }
|
||||||
PCIBus : uint8; { PCI address }
|
PCIBus : uint8; { PCI address }
|
||||||
PCISlot : uint8;
|
PCISlot : uint8;
|
||||||
PCIFunc : uint8;
|
PCIFunc : uint8;
|
||||||
@@ -1022,6 +1024,60 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ ========================= Interrupt-Driven Completion ========================= }
|
||||||
|
|
||||||
|
const
|
||||||
|
OHCI_MAX_INSTANCES = 4;
|
||||||
|
|
||||||
|
var
|
||||||
|
OHCIInstances : array[0..OHCI_MAX_INSTANCES-1] of PUSBHCDriver;
|
||||||
|
OHCIInstanceCount : uint32;
|
||||||
|
|
||||||
|
{ ISR handler — registered on the PCI interrupt line. }
|
||||||
|
procedure ohci_isr;
|
||||||
|
var
|
||||||
|
i : uint32;
|
||||||
|
hc : PUSBHCDriver;
|
||||||
|
priv : POHCI_PrivData;
|
||||||
|
intSts : uint32;
|
||||||
|
begin
|
||||||
|
for i := 0 to OHCIInstanceCount - 1 do begin
|
||||||
|
hc := OHCIInstances[i];
|
||||||
|
if hc = nil then continue;
|
||||||
|
priv := POHCI_PrivData(hc^.PrivData);
|
||||||
|
if priv = nil then continue;
|
||||||
|
|
||||||
|
{ Check if this controller has pending interrupt status }
|
||||||
|
intSts := ohci_read(priv^.MMIOBase, OHCI_REG_INTSTATUS);
|
||||||
|
if intSts = 0 then continue;
|
||||||
|
|
||||||
|
{ Acknowledge interrupt status NOW to de-assert level-triggered PCI line.
|
||||||
|
Must happen before ohci_poll, because PollBusy guard may skip the
|
||||||
|
acknowledge inside poll — leaving the line asserted = interrupt storm. }
|
||||||
|
ohci_write(priv^.MMIOBase, OHCI_REG_INTSTATUS, intSts);
|
||||||
|
|
||||||
|
{ Process completions (walks ED lists) }
|
||||||
|
ohci_poll(hc);
|
||||||
|
|
||||||
|
{ Hotplug: if RootHubStatusChange, flag for deferred processing }
|
||||||
|
if ((intSts AND OHCI_INT_RHSC) <> 0) and hc^.HotplugArmed then
|
||||||
|
hc^.PortChangePending := true;
|
||||||
|
end;
|
||||||
|
usbcore.fire_completion_hooks;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Enable hardware interrupts: WritebackDoneHead, RootHubStatusChange, UnrecoverableError + MIE. }
|
||||||
|
procedure ohci_enable_interrupts(hc : PUSBHCDriver);
|
||||||
|
var
|
||||||
|
priv : POHCI_PrivData;
|
||||||
|
begin
|
||||||
|
if (hc = nil) or (hc^.PrivData = nil) then exit;
|
||||||
|
priv := POHCI_PrivData(hc^.PrivData);
|
||||||
|
ohci_write(priv^.MMIOBase, OHCI_REG_INTENABLE,
|
||||||
|
OHCI_INT_WDH OR OHCI_INT_RHSC OR OHCI_INT_UE OR OHCI_INT_MIE);
|
||||||
|
syslog.logln('OHCI', 'Hardware interrupts enabled.');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure ohci_poll(hc : PUSBHCDriver);
|
procedure ohci_poll(hc : PUSBHCDriver);
|
||||||
var
|
var
|
||||||
priv : POHCI_PrivData;
|
priv : POHCI_PrivData;
|
||||||
@@ -1038,6 +1094,11 @@ var
|
|||||||
begin
|
begin
|
||||||
if (hc = nil) or (hc^.PrivData = nil) then exit;
|
if (hc = nil) or (hc^.PrivData = nil) then exit;
|
||||||
priv := POHCI_PrivData(hc^.PrivData);
|
priv := POHCI_PrivData(hc^.PrivData);
|
||||||
|
|
||||||
|
{ Re-entrancy guard }
|
||||||
|
if priv^.PollBusy then exit;
|
||||||
|
priv^.PollBusy := true;
|
||||||
|
|
||||||
base := priv^.MMIOBase;
|
base := priv^.MMIOBase;
|
||||||
|
|
||||||
{ Read and acknowledge interrupt status }
|
{ Read and acknowledge interrupt status }
|
||||||
@@ -1107,6 +1168,7 @@ begin
|
|||||||
ed := nextED;
|
ed := nextED;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
priv^.PollBusy := false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ ========================= Load / Init ========================= }
|
{ ========================= Load / Init ========================= }
|
||||||
@@ -1124,6 +1186,7 @@ var
|
|||||||
begin
|
begin
|
||||||
push_trace('OHCI.load');
|
push_trace('OHCI.load');
|
||||||
load := false;
|
load := false;
|
||||||
|
OHCIInstanceCount := 0;
|
||||||
|
|
||||||
devices := PCI.getDeviceInfo($0C, $03, $10, count);
|
devices := PCI.getDeviceInfo($0C, $03, $10, count);
|
||||||
syslog.log('OHCI', 'Found ');
|
syslog.log('OHCI', 'Found ');
|
||||||
@@ -1220,9 +1283,24 @@ begin
|
|||||||
hcEntry := usbcore.register_hc(@hc);
|
hcEntry := usbcore.register_hc(@hc);
|
||||||
|
|
||||||
{ Scan ports for connected devices (use the stable pointer, not stack-local @hc) }
|
{ Scan ports for connected devices (use the stable pointer, not stack-local @hc) }
|
||||||
if hcEntry <> nil then
|
if hcEntry <> nil then begin
|
||||||
usbcore.scan_ports(hcEntry)
|
{ Track instance for ISR dispatch }
|
||||||
else
|
if OHCIInstanceCount < OHCI_MAX_INSTANCES then begin
|
||||||
|
OHCIInstances[OHCIInstanceCount] := hcEntry;
|
||||||
|
inc(OHCIInstanceCount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Register ISR on PCI interrupt line }
|
||||||
|
syslog.log('OHCI', 'Registering ISR on IRQ ');
|
||||||
|
syslog.writeintln(devices[i].interrupt_line);
|
||||||
|
isrmanager.registerISR(32 + devices[i].interrupt_line, @ohci_isr);
|
||||||
|
|
||||||
|
{ Enable hardware interrupts }
|
||||||
|
ohci_enable_interrupts(hcEntry);
|
||||||
|
|
||||||
|
{ Scan for connected devices }
|
||||||
|
usbcore.scan_ports(hcEntry);
|
||||||
|
end else
|
||||||
syslog.logln('OHCI', 'Failed to register HC with USB core.');
|
syslog.logln('OHCI', 'Failed to register HC with USB core.');
|
||||||
|
|
||||||
syslog.logln('OHCI', 'Controller initialized and registered.');
|
syslog.logln('OHCI', 'Controller initialized and registered.');
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
@author(Kieron Morris <[email protected]>)
|
@author(Kieron Morris <[email protected]>)
|
||||||
}
|
}
|
||||||
unit UHCI;
|
unit uhci;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ uses
|
|||||||
drivermanagement,
|
drivermanagement,
|
||||||
usbtypes,
|
usbtypes,
|
||||||
usbcore,
|
usbcore,
|
||||||
|
isrmanager,
|
||||||
lists,
|
lists,
|
||||||
strings;
|
strings;
|
||||||
|
|
||||||
@@ -154,6 +155,7 @@ type
|
|||||||
QHControl : PUHCI_QH; { Queue Head for control transfers }
|
QHControl : PUHCI_QH; { Queue Head for control transfers }
|
||||||
QHBulk : PUHCI_QH; { Queue Head for bulk transfers }
|
QHBulk : PUHCI_QH; { Queue Head for bulk transfers }
|
||||||
QHInterrupt : PUHCI_QH; { Queue Head for interrupt transfers }
|
QHInterrupt : PUHCI_QH; { Queue Head for interrupt transfers }
|
||||||
|
PollBusy : boolean; { Re-entrancy guard for poll }
|
||||||
PCIBus : uint8; { PCI bus/slot/func for bus mastering }
|
PCIBus : uint8; { PCI bus/slot/func for bus mastering }
|
||||||
PCISlot : uint8;
|
PCISlot : uint8;
|
||||||
PCIFunc : uint8;
|
PCIFunc : uint8;
|
||||||
@@ -750,6 +752,56 @@ begin
|
|||||||
pop_trace;
|
pop_trace;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ ========================= Interrupt-Driven Completion ========================= }
|
||||||
|
|
||||||
|
const
|
||||||
|
UHCI_MAX_INSTANCES = 4;
|
||||||
|
|
||||||
|
var
|
||||||
|
UHCIInstances : array[0..UHCI_MAX_INSTANCES-1] of PUSBHCDriver;
|
||||||
|
UHCIInstanceCount : uint32;
|
||||||
|
|
||||||
|
{ ISR handler — registered on the PCI interrupt line. }
|
||||||
|
procedure uhci_isr;
|
||||||
|
var
|
||||||
|
i : uint32;
|
||||||
|
hc : PUSBHCDriver;
|
||||||
|
priv : PUHCI_PrivData;
|
||||||
|
status : uint16;
|
||||||
|
begin
|
||||||
|
for i := 0 to UHCIInstanceCount - 1 do begin
|
||||||
|
hc := UHCIInstances[i];
|
||||||
|
if hc = nil then continue;
|
||||||
|
priv := PUHCI_PrivData(hc^.PrivData);
|
||||||
|
if priv = nil then continue;
|
||||||
|
|
||||||
|
{ Check if this controller has pending interrupt status }
|
||||||
|
status := uhci_read16(priv^.IOBase, UHCI_REG_USBSTS);
|
||||||
|
if (status AND (UHCI_STS_USBINT OR UHCI_STS_ERROR)) = 0 then continue;
|
||||||
|
|
||||||
|
{ Acknowledge interrupt status NOW to de-assert level-triggered PCI line.
|
||||||
|
Must happen before uhci_poll, because PollBusy guard may skip the
|
||||||
|
acknowledge inside poll — leaving the line asserted = interrupt storm. }
|
||||||
|
uhci_write16(priv^.IOBase, UHCI_REG_USBSTS, status AND (UHCI_STS_USBINT OR UHCI_STS_ERROR));
|
||||||
|
|
||||||
|
{ Process completions (walks QH/TD chains) }
|
||||||
|
uhci_poll(hc);
|
||||||
|
end;
|
||||||
|
usbcore.fire_completion_hooks;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Enable hardware interrupts: Interrupt-on-Complete, Short Packet, Timeout/CRC. }
|
||||||
|
procedure uhci_enable_interrupts(hc : PUSBHCDriver);
|
||||||
|
var
|
||||||
|
priv : PUHCI_PrivData;
|
||||||
|
begin
|
||||||
|
if (hc = nil) or (hc^.PrivData = nil) then exit;
|
||||||
|
priv := PUHCI_PrivData(hc^.PrivData);
|
||||||
|
uhci_write16(priv^.IOBase, UHCI_REG_USBINTR,
|
||||||
|
UHCI_INTR_IOC OR UHCI_INTR_SP OR UHCI_INTR_TIMEOUT);
|
||||||
|
syslog.logln('UHCI', 'Hardware interrupts enabled.');
|
||||||
|
end;
|
||||||
|
|
||||||
{ ========================= Poll / Completion ========================= }
|
{ ========================= Poll / Completion ========================= }
|
||||||
|
|
||||||
procedure uhci_poll(hc : PUSBHCDriver);
|
procedure uhci_poll(hc : PUSBHCDriver);
|
||||||
@@ -768,6 +820,10 @@ begin
|
|||||||
if (hc = nil) or (hc^.PrivData = nil) then exit;
|
if (hc = nil) or (hc^.PrivData = nil) then exit;
|
||||||
priv := PUHCI_PrivData(hc^.PrivData);
|
priv := PUHCI_PrivData(hc^.PrivData);
|
||||||
|
|
||||||
|
{ Re-entrancy guard }
|
||||||
|
if priv^.PollBusy then exit;
|
||||||
|
priv^.PollBusy := true;
|
||||||
|
|
||||||
{ Read and clear status register }
|
{ Read and clear status register }
|
||||||
status := uhci_read16(priv^.IOBase, UHCI_REG_USBSTS);
|
status := uhci_read16(priv^.IOBase, UHCI_REG_USBSTS);
|
||||||
if (status AND (UHCI_STS_USBINT OR UHCI_STS_ERROR)) <> 0 then
|
if (status AND (UHCI_STS_USBINT OR UHCI_STS_ERROR)) <> 0 then
|
||||||
@@ -841,6 +897,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
qh := qh^.SWNext;
|
qh := qh^.SWNext;
|
||||||
end;
|
end;
|
||||||
|
priv^.PollBusy := false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ ========================= Load / Init ========================= }
|
{ ========================= Load / Init ========================= }
|
||||||
@@ -857,6 +914,7 @@ var
|
|||||||
begin
|
begin
|
||||||
push_trace('UHCI.load');
|
push_trace('UHCI.load');
|
||||||
load := false;
|
load := false;
|
||||||
|
UHCIInstanceCount := 0;
|
||||||
|
|
||||||
devices := PCI.getDeviceInfo($0C, $03, $00, count);
|
devices := PCI.getDeviceInfo($0C, $03, $00, count);
|
||||||
syslog.log('UHCI', 'Found ');
|
syslog.log('UHCI', 'Found ');
|
||||||
@@ -945,9 +1003,24 @@ begin
|
|||||||
hcEntry := usbcore.register_hc(@hc);
|
hcEntry := usbcore.register_hc(@hc);
|
||||||
|
|
||||||
{ Scan ports for connected devices (use the stable pointer, not stack-local @hc) }
|
{ Scan ports for connected devices (use the stable pointer, not stack-local @hc) }
|
||||||
if hcEntry <> nil then
|
if hcEntry <> nil then begin
|
||||||
usbcore.scan_ports(hcEntry)
|
{ Track instance for ISR dispatch }
|
||||||
else
|
if UHCIInstanceCount < UHCI_MAX_INSTANCES then begin
|
||||||
|
UHCIInstances[UHCIInstanceCount] := hcEntry;
|
||||||
|
inc(UHCIInstanceCount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Register ISR on PCI interrupt line }
|
||||||
|
syslog.log('UHCI', 'Registering ISR on IRQ ');
|
||||||
|
syslog.writeintln(devices[i].interrupt_line);
|
||||||
|
isrmanager.registerISR(32 + devices[i].interrupt_line, @uhci_isr);
|
||||||
|
|
||||||
|
{ Enable hardware interrupts }
|
||||||
|
uhci_enable_interrupts(hcEntry);
|
||||||
|
|
||||||
|
{ Scan for connected devices }
|
||||||
|
usbcore.scan_ports(hcEntry);
|
||||||
|
end else
|
||||||
syslog.logln('UHCI', 'Failed to register HC with USB core.');
|
syslog.logln('UHCI', 'Failed to register HC with USB core.');
|
||||||
|
|
||||||
syslog.logln('UHCI', 'Controller initialized and registered.');
|
syslog.logln('UHCI', 'Controller initialized and registered.');
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
@author(Kieron Morris <[email protected]>)
|
@author(Kieron Morris <[email protected]>)
|
||||||
}
|
}
|
||||||
unit USB;
|
unit usb;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@@ -35,6 +35,7 @@ uses
|
|||||||
usbhub,
|
usbhub,
|
||||||
usb_keyboard,
|
usb_keyboard,
|
||||||
usb_mouse,
|
usb_mouse,
|
||||||
|
usb_storage,
|
||||||
OHCI, UHCI, EHCI, XHCI;
|
OHCI, UHCI, EHCI, XHCI;
|
||||||
|
|
||||||
procedure init;
|
procedure init;
|
||||||
@@ -90,6 +91,9 @@ begin
|
|||||||
usb_keyboard.init;
|
usb_keyboard.init;
|
||||||
usb_mouse.init;
|
usb_mouse.init;
|
||||||
|
|
||||||
|
{ Initialize storage class driver }
|
||||||
|
usb_storage.init;
|
||||||
|
|
||||||
UHCI_ID.Bus:= biPCI;
|
UHCI_ID.Bus:= biPCI;
|
||||||
UHCI_ID.id0:= idANY;
|
UHCI_ID.id0:= idANY;
|
||||||
UHCI_ID.id1:= $0000000C;
|
UHCI_ID.id1:= $0000000C;
|
||||||
|
|||||||
+2355
-33
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Loaded 20 of 124 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user