acscsi.device/--background--
PURPOSE
acscsi.device is the Exec device for the AmigaChrome ACStorage
Zorro-II board. It finds the board, reports volume geometry, and
carries the folder operations that ACFS needs to the host.
It is not a block device. An AmigaChrome hard disk is a folder on
the host, and the device's private commands name files and
directories by path. There is no CMD_READ or CMD_WRITE of sectors;
TD_GETGEOMETRY exists only so that tools which ask for geometry get
a plausible answer.
UNITS
Unit numbers are the same on every guest OS and match the host:
0 - 7 DH0: - DH7:
8 BOOT:
ACSCSI_UNIT_DH0, ACSCSI_UNIT_DH1 and ACSCSI_UNIT_BOOT are defined
in <acscsi.h>. OpenDevice() accepts any unit below ACSCSI_MAX_UNITS
(9). Opening a unit does not check that a folder is behind it;
the first command does.
IO REQUEST
The private commands use the extended request ACSIORequest from
<acscsi.h>. Allocate it with CreateIORequest(port,
sizeof(struct ACSIORequest)) and open the device with it:
struct ACSIORequest {
struct IOStdReq io;
CONST_STRPTR path; /* volume-relative path, UTF-8 */
CONST_STRPTR path2; /* second path (RENAME only) */
ULONG offset; /* byte offset, start index or size */
ULONG flags; /* ACSIOF_CREATE, ACSIOF_TRUNCATE */
ULONG actual; /* extra result (LIST: next index) */
LONG result; /* ACSRESULT_xxx, see below */
};
Paths are relative to the root of the unit's volume, use '/' as
the separator and have no leading slash or volume name. "" is the
root. The caller owns the path strings until the request returns.
ERRORS
Two fields report failure, and they mean different things.
io_Error is the transport: 0 when the command reached the host and
came back, otherwise an Exec or trackdisk error (IOERR_BADLENGTH,
IOERR_BADADDRESS, IOERR_NOCMD, IOERR_OPENFAIL, TDERR_NotSpecified
for a timeout or a board fault).
result is the filesystem outcome when io_Error is 0:
ACSRESULT_OK 0 done
ACSRESULT_NOT_FOUND 1 no such file or directory
ACSRESULT_EXISTS 2 target already exists
ACSRESULT_NOT_EMPTY 3 directory is not empty
ACSRESULT_IN_USE 4 host has the object open
ACSRESULT_ACCESS 5 permission denied
ACSRESULT_READ_ONLY 6 volume is read-only
ACSRESULT_INVALID_NAME 7 name is not legal on the host
ACSRESULT_NO_SPACE 8 host disk full
ACSRESULT_WRONG_TYPE 9 file where a directory was needed,
or the other way round
ACSRESULT_RANGE 10 offset or size out of range
ACSRESULT_IO 11 host I/O error
ACSRESULT_PROTOCOL 12 malformed request or reply
A command that fails with result != 0 still sets io_Error to 0, so
check result after every private command.
NOTES
All commands complete synchronously inside BeginIO(). Use DoIO().
AbortIO() does nothing and returns IOERR_NOCMD.
The device polls the board and waits with Delay(1) between polls,
so it needs dos.library.
SEE ALSO
acfs-handler/--background--, acstorage/--background--,
<acscsi.h>, <acstorage.h>acscsi.device/ACSCMD_DELETE
NAME
ACSCMD_DELETE -- delete a file or an empty directory
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command ACSCMD_DELETE
path object to delete
RESULTS
io_Error 0 or a transport error
result ACSRESULT_xxx; NOT_EMPTY for a directory with
anything in it
NOTES
The device does not know about AmigaDOS locks. ACFS refuses the
delete itself when a lock or open file is inside path.
SEE ALSO
ACSCMD_MKDIR, acfs-handler/ACTION_DELETE_OBJECTacscsi.device/ACSCMD_LIST
NAME
ACSCMD_LIST -- read one page of a directory
FUNCTION
Fills an array of ACSDirEntry with entries from the directory at
path, starting at entry index offset. Call again with offset set
to the returned next index until it is 0xffffffff.
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command ACSCMD_LIST
io_Data array of ACSDirEntry
io_Length size of the array in bytes; capacity is
io_Length / sizeof(ACSDirEntry)
path directory to list, "" for the root
offset index of the first entry wanted, 0 to start
RESULTS
io_Error 0, IOERR_BADADDRESS, IOERR_BADLENGTH, or a
transport error
io_Actual bytes filled: entries * sizeof(ACSDirEntry)
actual index to pass as offset next time, or
0xffffffff when the listing is complete
result ACSRESULT_xxx
typedef struct ACSDirEntry {
ULONG type; /* 1 = file, 2 = directory */
ULONG size;
ULONG mtime;
char name[256]; /* NUL-terminated, UTF-8 */
} ACSDirEntry;
NOTES
The host does not hold the listing between calls. If the directory
changes between pages, entries can be skipped or repeated.
SEE ALSO
ACSCMD_STAT, acfs-handler/ACTION_EXAMINE_NEXTacscsi.device/ACSCMD_MKDIR
NAME
ACSCMD_MKDIR -- create one directory
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command ACSCMD_MKDIR
path directory to create; its parent must exist
RESULTS
io_Error 0 or a transport error
result ACSRESULT_xxx; EXISTS if anything is already there
SEE ALSO
ACSCMD_DELETE, acfs-handler/ACTION_CREATE_DIRacscsi.device/ACSCMD_READ_FILE
NAME
ACSCMD_READ_FILE -- read bytes from a file
FUNCTION
Reads up to io_Length bytes from the file at path, starting at
byte offset. The device splits large reads into mailbox-sized
transfers; the caller sees one request.
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command ACSCMD_READ_FILE
io_Data destination buffer
io_Length bytes wanted
path file to read
offset byte offset in the file
RESULTS
io_Error 0, IOERR_BADADDRESS, or a transport error
io_Actual bytes read; less than io_Length at end of file
result ACSRESULT_xxx
NOTES
There is no open file on the host side. Each request names the
path again, so a file renamed or deleted on the host between reads
fails with ACSRESULT_NOT_FOUND.
SEE ALSO
ACSCMD_WRITE_FILE, acstorage/ACSTORAGE_CMD_READ_FILEacscsi.device/ACSCMD_RENAME
NAME
ACSCMD_RENAME -- rename or move an object on one volume
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command ACSCMD_RENAME
path current path
path2 new path, on the same unit
RESULTS
io_Error 0, IOERR_BADADDRESS, or a transport error
result ACSRESULT_xxx; EXISTS if path2 is taken
NOTES
A rename that changes only the case of a name is allowed.
SEE ALSO
acfs-handler/ACTION_RENAME_OBJECTacscsi.device/ACSCMD_SET_SIZE
NAME
ACSCMD_SET_SIZE -- truncate or extend a file
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command ACSCMD_SET_SIZE
path file to resize
offset new size in bytes
RESULTS
io_Error 0 or a transport error
result ACSRESULT_xxx
SEE ALSO
acfs-handler/ACTION_SET_FILE_SIZEacscsi.device/ACSCMD_STAT
NAME
ACSCMD_STAT -- get the type, size and date of one path
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command ACSCMD_STAT
io_Data pointer to an ACSStat
io_Length sizeof(ACSStat)
path object to examine, "" for the volume root
RESULTS
io_Error 0, IOERR_BADLENGTH, or a transport error
io_Actual sizeof(ACSStat) on success
result ACSRESULT_OK or ACSRESULT_NOT_FOUND, among others
typedef struct ACSStat {
ULONG type; /* 1 = file, 2 = directory */
ULONG size; /* bytes; 0 for a directory */
ULONG mtime; /* seconds since 1 Jan 1970, host time */
} ACSStat;
NOTES
The host resolves names without regard to case, as AmigaDOS does.
SEE ALSO
ACSCMD_LIST, acstorage/ACSTORAGE_CMD_STATacscsi.device/ACSCMD_VOLUME_INFO
NAME
ACSCMD_VOLUME_INFO -- describe the unit's volume
FUNCTION
Returns the label, flags, boot priority and synthetic geometry of
the folder behind this unit. The label and boot priority come from
the volume's .amigachrome-volume.json on the host.
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command ACSCMD_VOLUME_INFO
io_Data pointer to an ACSVolumeInfo
io_Length sizeof(ACSVolumeInfo), 92 bytes
RESULTS
io_Error 0, IOERR_BADLENGTH, or a transport error
io_Actual sizeof(ACSVolumeInfo) on success
result ACSRESULT_xxx
typedef struct ACSVolumeInfo {
ULONG flags; /* ACSTORAGE_VOLUME_FLAG_xxx */
LONG bootPriority;
ULONG blockSize;
ULONG cylinders;
ULONG heads;
ULONG sectorsPerTrack;
ULONG lbaSectors;
char label[64]; /* NUL-terminated */
} ACSVolumeInfo;
flags may contain ACSTORAGE_VOLUME_FLAG_BOOTABLE (1) and
ACSTORAGE_VOLUME_FLAG_READONLY (2).
NOTES
The layout is checked at compile time on m68k: lbaSectors at
offset 24, label at offset 28, total size 92.
SEE ALSO
TD_GETGEOMETRY, acstorage/ACSTORAGE_CMD_VOLUME_INFOacscsi.device/ACSCMD_WRITE_FILE
NAME
ACSCMD_WRITE_FILE -- write bytes to a file
FUNCTION
Writes io_Length bytes to the file at path, starting at byte
offset. With ACSIOF_CREATE a missing file is created first. With
ACSIOF_TRUNCATE the file is cut to zero length before the first
byte is written. A write with io_Length 0 still reaches the host,
which is how an empty file is created.
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command ACSCMD_WRITE_FILE
io_Data source buffer
io_Length bytes to write
path file to write
offset byte offset in the file
flags 0, or ACSIOF_CREATE and/or ACSIOF_TRUNCATE
RESULTS
io_Error 0, IOERR_BADADDRESS, or a transport error
io_Actual io_Length on success
result ACSRESULT_xxx; READ_ONLY, NO_SPACE and NOT_FOUND
(no ACSIOF_CREATE) are the usual failures
NOTES
A large write is split into several board commands. If one fails
part way, the earlier parts are already on the host and io_Actual
is 0.
SEE ALSO
ACSCMD_READ_FILE, ACSCMD_SET_SIZEacscsi.device/CMD_CLEAR
NAME
CMD_CLEAR, CMD_UPDATE, CMD_FLUSH -- accepted, do nothing
FUNCTION
The device keeps no buffers, so these standard commands return at
once with io_Error 0. They are accepted so that generic tools and
handlers that send them do not fail.
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command CMD_CLEAR, CMD_UPDATE or CMD_FLUSH
RESULTS
io_Error 0acscsi.device/TD_GETGEOMETRY
NAME
TD_GETGEOMETRY -- return a synthetic drive geometry
FUNCTION
Fills a struct DriveGeometry from the unit's volume information.
The numbers are synthetic values the host reports so that tools
that expect a disk see one; they do not describe real blocks.
IO REQUEST
io_Message mn_ReplyPort initialized
io_Device set by OpenDevice()
io_Unit set by OpenDevice()
io_Command TD_GETGEOMETRY
io_Data pointer to a struct DriveGeometry
io_Length sizeof(struct DriveGeometry)
RESULTS
io_Error 0, IOERR_BADLENGTH if io_Length is too small,
or a transport error
io_Actual sizeof(struct DriveGeometry) on success
dg_SectorSize, dg_Cylinders, dg_Heads, dg_TrackSectors and
dg_TotalSectors come from ACSCMD_VOLUME_INFO. dg_DeviceType is
DG_DIRECT_ACCESS and dg_BufMemType is MEMF_PUBLIC.
SEE ALSO
ACSCMD_VOLUME_INFO, devices/trackdisk.h