Skip to content

AmigaOS 4.1FE support#5

Open
reinauer wants to merge 24 commits into
mainfrom
amigaos4.1fe
Open

AmigaOS 4.1FE support#5
reinauer wants to merge 24 commits into
mainfrom
amigaos4.1fe

Conversation

@reinauer

Copy link
Copy Markdown
Owner

No description provided.

reinauer added 24 commits May 21, 2026 12:46
Start separating Amiga-family OS integration from the packet
handler so AmigaOS 4 can grow a native frontend without cloning
the OS3 handler.

Select an os3 or os4 platform subdirectory from the Makefile and
add shared sys_compat declarations. Route allocation, message
ports, I/O requests, signals, interrupt setup, library/interface
ownership, and utility hook calls through per-OS implementations.

Keep -lauto out of the OS4 link. Explicitly open dos.library,
obtain IDOS, open utility.library, and obtain its main interface.
Move the temporary OS4 main wrapper into the OS4 frontend directory
and document the remaining OS4 porting work.
Move the remaining AmigaOS 4 source differences out of the shared
packet handler. Add per-target compatibility headers and route the
interrupt callback ABI, FileInfoBlock entry type, and DeviceNode lock
copying through sys_compat helpers.

Document the CD0 default, OD0 fallback, and requester policy for
unsafe conflicts. Name fallback should be quiet, while duplicate OD0
or same physical Device/Unit conflicts should fail visibly.
Teach the OS4 entry wrapper to receive and validate the initial
ACTION_STARTUP packet before passing it into the shared handler
loop.

Add a native FileSystemVectorPort template with explicit
unsupported-vector stubs. This gives the next slice a real OS4
frontend to map onto shared read-only operations.
Move the first native OS4 vector callbacks onto shared handler
operations for locks, file handles, reads, seeks, and info. Keep
the packet frontend on the same operations so behavior stays aligned.

Add native ExamineData allocation for object, lock, and filehandle
examine calls. Leave directory iteration unsupported until the OS4
private context ownership rules are confirmed.
Wire native OS4 vector callbacks for inhibit, serialize, and lock or
file mode changes into the shared handler operations.

Return ERROR_DISK_WRITE_PROTECTED from mutating vectors so DOS sees a
deliberate read-only filesystem result instead of missing support.
Add a shared handler operation that returns the next directory entry by
resume key, matching the existing packet iteration rules.

Use it from FSExamineDir to allocate native ExamineData entries,
recycle stale context nodes when possible, and append results to the
OS4 examine context FreshNodeList.
Make always defines CC, defaulting to "cc", so the conditional
assignment "CC ?= m68k-amigaos-gcc" never took effect and a plain
"make amiga" tried to build the handler with the host compiler.

Assign the m68k cross-compiler only when CC still carries make's
built-in default, so command-line and environment overrides such as
CC=ppc-amigaos-gcc keep selecting their own toolchain unchanged.
On AmigaOS 4, dos.library only calls a filesystem through its native
FileSystemVectors when the handler's port validates as a vector port.
The handler replied to ACTION_STARTUP with the plain process message
port, so even with the vector callbacks implemented, every DOS call
was forced through legacy packet emulation.

Allocate the FileSystemVectorPort during startup, attach a dedicated
signal to its embedded message port, and verify the object with
GetFileSystemVectorPort() before relying on it. Switch the handler
port to the vector port before replying to the startup packet, so
the device node, volume node, locks, and the packet loop all
reference the port DOS validates. If activation fails, the startup
packet is rejected and the port and signal are released; on shutdown
the process port is restored before the handler exits.

Track the owning process port separately from the active handler
port in handler_global, and introduce an ODFS_AMIGA_OS4 macro in the
per-target compat headers so shared code can test the build target
without scattering __amigaos4__ checks.
The SERIAL_DEBUG log sink wrote bytes to the serial port with inline
m68k assembly calling exec's RawPutChar vector, which cannot build
for the PPC OS4 target.

Keep the raw serial path for OS3 and use exec's DebugPrintF() on
OS4, which ends up in the same serial/Sashimi debug stream. This
makes the SERIAL_DEBUG=1 and PACKET_TRACE=1 build variants compile
for OS4.
AmigaOS 4 deprecates ACTION_DIE in favor of ACTION_SHUTDOWN (V51+),
which DismountDevice() sends to ask a filesystem to remove its volume
node and terminate. The handler only recognized ACTION_DIE, so an OS4
dismount would have been answered with ERROR_ACTION_NOT_KNOWN and the
handler process would have stayed alive.

Accept ACTION_SHUTDOWN wherever ACTION_DIE is accepted: reply DOSTRUE
and leave the packet loop, which already unmounts the volume, drains
outstanding locks and filehandles, and unpublishes the device node.
The OS4 SDK defines no shutdown member in struct FileSystemVectors,
so the packet loop remains the correct delivery path even with the
native vector port active.

The OS3 NDK does not define the packet number, so the OS3 target
compat header supplies it; OS3 DOS never sends it, and accepting it
unconditionally keeps the shared loop free of OS conditionals.
The OS4 frontend cast the portable one-argument media-change callback
directly into is_Code. On AmigaOS 4 the V50+ conventions documented
in the exec autodocs pass is_Data as the third argument:

  Cause() soft interrupts:
      void handler(int32 unused, struct ExecBase *sysbase,
                   APTR is_data);
  interrupt servers (AddIntServer):
      ULONG handler(struct ExceptionContext *ctx,
                    struct ExecBase *sysbase, APTR userData);

With the old cast, the callback's data parameter received zero (or
the exception context) instead of the change-interrupt data, so the
NULL check in the callback made the handler silently miss every
media-change event fired through TD_ADDCHANGEINT.

Install a V50-style trampoline that ignores the first two arguments
and forwards is_Data to the portable callback. Both documented
conventions place is_Data third, so one entry point covers either
delivery path. This mirrors the a1 register-binding trampoline the
OS3 frontend already uses.
The OS4 build needed -Wno-error=deprecated-declarations while the
shared handler still called AllocMem(), CreateMsgPort(),
CreateIORequest() and friends directly. Those calls now go through
the per-OS sys_compat wrappers, and the OS4 implementations use
AllocVecTags() and AllocSysObjectTags()/FreeSysObject(), so a full
rebuild compiles warning-clean without the suppression.

Remove it so the build fails again if a deprecated interface member
sneaks back in; the SDK marks them with __attribute__((deprecated)),
which -Werror turns into a hard error.
The handler built its published DeviceNode and the volume DeviceList
node by hand: AllocMem of the structure plus a name buffer, then
filling every field. On AmigaOS 4 those are compatibility layouts
whose real definitions (struct DeviceNode, struct VolumeNode) carry a
StructSize field and reserved members that DOS expects the allocator
to initialize; the manual path left them zero.

Add odfs_amiga_create_dos_entry()/odfs_amiga_delete_dos_entry() to
the per-OS compatibility layer. The OS3 implementation keeps the
manual allocation, including its deliberate avoidance of
MakeDosEntry() so volume names with AmigaDOS metacharacters such as
parentheses are not normalized. The OS4 implementation uses
AllocDosObject(DOS_DOSLIST, ADO_Type, ADO_Name), which the dos
autodoc documents as the supported allocator (MakeDosEntry() itself
is a stub over it since V52.16) and which fills dol_StructSize and
the V52 fields.

AddDosEntry()/RemDosEntry()/AttemptLockDosList() are unchanged; they
remain current API on OS4.
The OS4 dospackets autodoc states that vector-port functions are
invoked from the calling process context, like library calls, and
that all access to filesystem state from them must be protected by a
semaphore. The vector callbacks previously called the shared handler
operations with no locking, racing against each other and against
the handler process (packet dispatch and media-change handling) over
the lock list, filehandle list, block cache, and the single device
IORequest and DMA bounce buffer.

Add a SignalSemaphore to the handler globals on OS4. Every vector
callback that touches handler state now holds it across the shared
operation, and the handler process takes it around media-change
handling and shutdown teardown. Pure stub callbacks that only return
an error do not take it.

Direct legacy packets are now routed through the DOSEmulatePacket()
function that AllocDosObject() installs in the vector port, as the
autodoc prescribes. The emulator performs the equivalent vector call
under the same serialization as native DOS callers, so the handler
process no longer mutates filesystem state through a second
unsynchronized dispatch path. Packets are validated (non-null,
dp_Link == msg) before being trusted, since hand-built packets and
private messages can reach the port directly. The shared
handle_packet() dispatch remains the OS3/AROS path and the OS4
fallback if the vector port is absent.

Shutdown now follows the documented sequence: invalidate the vector
port by zeroing FSV.Version so dos.library stops vectoring new
callers, tear down DOS-visible state while holding the semaphore so
in-flight calls finish first, and reply the shutdown packet only
after teardown. This also moves the OS3 ACTION_DIE reply after
teardown, which matches common classic handler practice.
The OS4 filesystem handler must receive ACTION_STARTUP as its
first process message. Newlib startup consumes that message while
probing for a Workbench launch, which can deadlock the boot mount.

Link the handler without C runtime startup, provide a small _start
entry that initializes the Exec interface, and add the Kickstart
Resident plus FileSysEntry registration used when the module loads
from Kickstart.zip.

Provide the small libc surface the freestanding link still needs
and translate legacy allocation flags before passing them to
AllocVecTags().
Diskboot starts one filesystem handler process per CD unit. The
media callback context was static, so a later process could
replace the device binding used by an earlier mounted volume.

Move the media callback context into handler_global and pass that
per-process instance to the core media layer. Reinitialize the
same context after media-change remounts.
Some OS4 device paths report phantom ATAPI units that open but
hang when probed through SCSI commands. Mounting those units
publishes a dead volume that DOS can keep polling.

Answer allocation failures on the startup packet, remove the
TEST UNIT READY probe, and use TD_GETGEOMETRY before publishing
the volume. Only issue MODE SELECT after geometry proves that a
usable drive is present.
Workbench and native OS4 filesystem vectors expect lock objects
with the OS4 DOS lock layout. The classic handler embedded a
FileLock in its private lock wrapper, which leaves OS4-only
fields uninitialized.

Store a DOS-allocated struct Lock in each ODFS lock on OS4, keep
the classic embedded FileLock on OS3, and convert through
fl_FSPrivate1. Free the DOS lock when the ODFS lock is released
or drained.
Workbench exercises native filesystem vectors more strictly than
shell packet paths. Several callbacks returned classic packet
values, left fh_Arg1 empty, or allocated ExamineData outside the
directory context that DOS owns.

Return native boolean SameLock and SameFile values, preserve
fh_Arg1 together with fh_Arg2, implement FileSystemAttr queries,
bind ExamineDir data to the DOS context, and reject inactive
directory locks before iteration.
OS4 still sends legacy packet APIs such as Lock(), Examine(), and
ExNext() to the handler port. Routing those packets through
DOSEmulatePacket returns vector-era semantics and can reject
classic examine actions that callers still use.

Leave direct packets on the shared packet dispatcher and
serialize that dispatcher with the OS4 filesystem semaphore.
Native vector calls and legacy packets now share the same handler
state without using the vector packet emulator as an extra
dispatch path.
Native OS4 vector callbacks run in the caller task, but the
handler reused its device IORequest whose reply port belongs to
the handler task. If a caller-task DoIO() waited for completion,
the device signaled the wrong task and Workbench could hang while
opening a drawer.

Record the handler task at startup. When media reads run from
another task, allocate a temporary reply port and IORequest for
that caller while reusing the same device and unit binding.
Add explicit AmigaOS 3 and AmigaOS 4 build instructions to the
README. Describe compiler target selection, separate build directories,
explicit tool overrides, and per-target size limits.
Add a PPC CI job that runs in the amigappc-gcc container. Put
/opt/amigappc/bin on PATH, verify ppc-amigaos-gcc, and build both
release and serial-debug handler variants.
Split the draft release workflow into OS3 and OS4 builders so each
target uses its matching container and toolchain. Download both
artifact sets before creating the draft release, and attach the PPC
release and serial-debug handlers alongside the OS3 files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant