----------------------- AmigaOS 3.2 project -------------------------- trackfile.device 1.18 (25.4.2020) - First regular AmigaOS 3.2 build for trackfile.device trackfile.device 1.19 (27.4.2020) - For CMD_READ, CMD_WRITE and TD_FORMAT the io_Data address must be WORD-aligned (16 bit word). This is what the documentation for trackdisk.device requires and stresses, too. - TD_REMCHANGEINT must use the same IOStdReq which was previously used with TD_ADDCHANGEINT. This is what the documentation for trackdisk.device requires and stresses, too. trackfile.device 1.20 (27.4.2020) - Added the first bunch of AutoDoc comments. - Added the standard, but previously absent, parameter validation for the TD_ADDCHANGEINT and TD_REMCHANGEINT commands. - TD_FORMAT now follows the specifications by requiring that only full tracks may be written to. This is one of the points at which TD_FORMAT deviates from CMD_WRITE. - TD_REMOVE now checks if the IORequest is really an IOStdRequest but refrains from reporting an error if this is not so. The legacy code which would use TD_REMOVE did not perform any error checking anyway :-( trackfile.device 1.21 (29.4.2020) - Broke up "trackfile_device.c" into "commands.c", "functions.c", "tools.c" and "unit.c" to be more manageable. trackfile.device 1.22 (29.4.2020) - Made most of the functions in "commands.c" local to that file. - Turns out that the TD_REMOVE command was not even hooked up. That might explain a lot... - Moved from one single "protos.h" file to individual files with function prototype definitions for the respective module. - Disabled the debug build option in "assert.h" which I had checked in by mistake... trackfile.device 1.23 (30.4.2020) - TD_REMOVE and TD_GETGEOMETRY are now immediate commands and do not involve the unit process. - Updated the device command documentation to reflect which commands are immediate commands (they observe the IOF_QUICK flag) and which ones are not (they do not observe the IOF_QUICK flag and are always handled by the unit process). - Added a ton of assertions which will hopefully never ever produce any output. - The test for an overflowing unit number in TFStartUnitTagList() did not work as it should. Fixed. - TFInsertMediaTagList() now returns an error if checking the volume on which the file to be used resides does not work out. - The timeout option for TFEjectMediaTagList() now has the effect of polling the "can we proceed with ejecting the medium" status twice per second for better responsiveness. Also, the timeout is now observed correctly. - If TFGetUnitData() cannot fill in the unit data it prepared, such as can happen in a multitasking environment, it now marks the respective unit record both as having size=0 and a drive type of -1. DAControl so far checked only the size information, but that used to be non-zero up until now :-( - Moved the I/O requester message type initialization right to the beginning of the dev_open() function where it belongs. Previously, it was initialized only if opening the device and unit was both successful, which was not as robust as this should have been. The initialization must be performed at all times, or otherwise the client might accidentally call WaitIO() and hang. trackfile.device 1.24 (1.5.2020) - Replaced the DeviceNode startup field wrangling with one single function responsible for the whole affair. trackfile.device 1.25 (10.5.2020) - Replaced duplicate code with individual functions which perform the same services as the duplicates. - TD_SEEK did not verify that a valid IOStdReq had been passed as the parameter. - Moved the "medium present" and "medium is write protected" checks in front of all the I/O request tests in those command functions for which this made sense. trackfile.device 1.26 (10.5.2020) - Refactoring can be hazardous for your code if you name scratch variables like those you actually wanted to retain their values until after a loop has run its course. trackfile.device 1.27 (11.5.2020) - Added support for the ETD_CLEAR, ETD_FORMAT, ETD_MOTOR, ETD_READ, ETD_SEEK, ETD_UPDATE and ETD_WRITE commands in the hope that this will be useful somehow. Note that for ETD_READ with a buffer for the sector label information supplied trackfile.device will pretend that only zeroes could be read. - Removed the unused and nonsensical TD_RAWWRITE command handling which dropped into the regular CMD_WRITE handling. - Simplified the CMD_UPDATE handling. trackfile.device 1.28 (11.5.2020) - Added support for the CMD_STOP and CMD_START commands. Just like trackdisk.device uses them... - Restricted the immediate commands to CMD_START, TD_CHANGENUM, TD_CHANGESTATE, TD_GETDRIVETYPE, TD_GETNUMTRACKS and TD_REMCHANGEINT so that the behaviour follows trackdisk.device exactly. - Updated the code documentation. trackfile.device 1.29 (12.5.2020) - Replaced the unit structure with the documented trackdisk.device public unit structure. Track numbers (0..159) are updated in real time as needed and the change counter value is updated as well. Some of the unit flags are updated, as well as the unit usage counter. If the motor is turned off, the track number reported in the public unit structure is always set to -1. Existing tools which monitored the track information, e.g. for display purposes could be adapted to use trackfile.device as well. - When starting up a new unit TFStartUnitTagList() now waits for the unit to initialize. Since it has to open timer.device now, that step makes sure that the unit is ready by the time a file system needs to open it. - The unit process now denies any attempt to eject a disk image file medium if the motor is currently running, the track buffer has been modified and not yet written back to the file, or both conditions are met. - TFGetUnitData() now marks a unit as busy only if the motor is currently on. - Closing a unit with the motor still on or the track buffer contents having been modified now causes the buffer to be written back and the motor to be turned off again if there is no further disk activity within the next 2.5 seconds. trackfile.device 1.30 (14.5.2020) - Closing the device could cause an Enforcer hit if the control unit (as used by the DAControl command) was being used. Fixed. trackfile.device 1.31 (16.5.2020) - Moved code which marks the track buffer contents as invalid, as well as the code which marks the motor as turned off into its own set of functions. These functions need to update more than just a single variable. It's a bit safer to have that done in one place only than to repeat the same code and forget something. - If Read() fails then the track buffer contents will now always get marked as being invalid. - TD_EJECT now also calls ACTION_FLUSH on the file system on which the file resides, just in case. - If starting the unit Process fails, but the Process itself fails to initialize correctly, this is now handled safely and the unit data structures are removed and freed as well. - If the unit Process is asked to eject a medium, it will now write back the track buffer to the file on its own accord rather than refusing to eject the medium if the track buffer still has changes pending. The eject operation now also calls ACTION_FLUSH on the file system on which the file resides. trackfile.device 1.32 (16.5.2020) - A read/write/format operation now always turns on the motor, regardless of whether io_Length is > 0. If the operation passes the parameter validation, then the motor will be enabled. - Moved the disk image file eject operation (closes the file, flushes the buffers, triggers change notification, etc.) into its own distinct function. - Read operations now check if an actual error was returned or if fewer data was read than requested. In the latter case this will now set a trackdisk.device error in order to make it somewhat clear that there was trouble. Also, regardless of what may have gone wrong, the track buffer's contents are invalidated. trackfile.device 1.33 (23.5.2020) - Added proper arbitration to state information shared between the individual units, such as whether the disk image file is currently open, device commands and library functions. Previously, access was a more cavalier with read access and locking was reserved to write access. - Moved the unit-specific data structures and constant from the "trackfile_device.h" into "unit.h". - Replaced duplicate code by shared functions which do the same work but only in a single place. trackfile.device 2.1 (30.5.2020) - Preparations for API additions, which aren't fully baked yet, though... This accounts for the version bump. - With a writable medium the track buffer now covered by a checksum to verify if its contents have indeed changed if it was written to. Future feature: optionally take a checksum of all the tracks of a medium before it gets mounted, to detect media with the same contents in spite of being stored in different files. This would help to avoid crashing the file system... - Refactored a bit of common code used by file read error processing. - The device structure now "mimics" the V33 trackdisk.device as far as this can make sense. It seems that some client software is not beyond peeking the internal device data, and trackfile.device now halfway convincingly stores zero data in this area. trackfile.device 2.2 (30.5.2020) - Ouch! Destructive typo in the Fletcher-64 checksum calculation, now fixed. Also unrolled that loop a bit. trackfile.device 2.3 (31.5.2020) - Added optional support for maintaining track and disk checksums, so as to avoid mounting two disk image files with identical contents. Such disk images are an issue for the AmigaDOS default file system which tends to crash if it cannot tell two volumes apart. The track checksums are updated as data gets written to the disk image, and the disk checksum is derived from all the track checksums. The disk checksum is only recalculated when it becomes necessary, e.g. when a new disk image is to be used or when the unit information is retrieved. Because the track an disk checksums need to be calculated when the disk image file is inserted, the startup time may be impacted, but I do not know yet if this is a noticeable problem. Time to find out... trackfile.device 2.4 (1.6.2020) - Track boundary checking was too error prone. Reviewed all the tests and introduced a device unit variable which holds the total number of tracks instead of multiplying the number of heads and cylinders every time the same number is needed. - Added further diagnostic output for checksum calculation and verification. - Updated the Fletcher-64 checksum code after reviewing what little documentation there is on it. The Fletcher-16 and Fletcher-32 checksums seem to be much more popular than the Fletcher-64 variant. - Duplicate image detection should have skipped comparing the unit file data with itself. Now it actually does ;-) trackfile.device 2.5 (1.6.2020) - Realized that the checksum calculation result does not need to be inverted unless it's use to calculate/verify a block checksum, such as is done for creating the checksum of a boot block. trackfile.device 2.6 (6.6.2020) - Added scaffolding for the TD_RAWREAD and ETD_RAWREAD commmands. The relevant code is enabled through a compile-time option. We don't want to ship this feature enabled by accident, especially since it's going to require a lot of code to make it work well. - Removed the last surprising remnants of the TD_RAWWRITE command, which must have slipped in by virtue (or lack thereof) of copy & paste programming :-( trackfile.device 2.7 (6.6.2020) - Added the actual MFM encoding code for required for the TD_RAWREAD and ETD_RAWREAD commmands to work. Building these and more is optional and is controlled through the '#define ENABLE_MFM_ENCODING' line in "mfm_encoding.h". trackfile.device 2.8 (6.6.2020) - Plugged the MFM encoding code into the TD_RAWREAD command implementation. - Added code to simulate the effects of the IOTDF_INDEXSYNC and IOTDF_WORDSYNC flags, the combination of both and the lack of both. The contents of the track buffer may be rotated, the first bit in the read buffer may belong to a random sector, or even to a random bit of a random sector. Not sure if all of this works yet, but if Disk Doctor can handle it... trackfile.device 2.9 (7.6.2020) - Added more debug output. - Updated the code documentation. - TFInsertMediaTagList() can make use of a ready-made file handle. Prior to setting up the disk and track checksum information we now seek to the beginning of the disk image file since it's not a given that the file handle read position will already be set to that position. - The MFM encoding buffer is now allocated via AllocVec() and is released through FreeVec(). - Changed the seed value for the PRNG which the TD_RAWREAD command may make use of. - Found another TD_RAWWRITE remnant and removed it. trackfile.device 2.10 (7.6.2020) - The initial disk image checksum calculation could have work better. Now it does... - Remembered that the "asyncio.c" code aligned the buffer for use with file I/O to an MC68040 cache line address boundary to avoid flushing more cache data than necessary during DMA. Also, the memory buffer preferences of the file system which the disk image file would reside on were never taken into account. Now we've got a new set of functions which take care of both these aspects. trackfile.device 2.11 (11.6.2020) - Updated the code documentation and debug output. - Formatting a track now writes back the track buffer contents, if necessary, since it's not a given that formatting a track will be followed by formatting all the tracks. So we need to preserve what's been modified just to be safe. - If CMD_WRITE will overwrite the contents of a full track, we no longer bother to read the contents of that track into the buffer. - The unit Processes are now running at Task priority level 5, just like the trackdisk.device unit Tasks do. - Scanning the AmigaDOS device list now follows a single consistent scheme which matches existing best practices. - Changed TFGetUnitData() to use LockDosList() instead of trying to make do with AttemptLockDosList(). trackfile.device 2.12 (11.6.2020) - Added TFExamineFileSize() function which DAControl can make use of. No sense in duplicating this test in both the device and the control command, should we support 5.25" disk image files in the future, for example. trackfile.device 2.13 (13.6.2020) - Lucky number 13! - Finally, the TD_RAWREAD/ETD_RAWREAD commands are working as intended for the purpose of testing within a debug build. What shall we do with all this useless beauty? trackfile.device 2.14 (14.6.2020) - Updated the code documentation again. - The TD_RAWREAD code did not take the size of the sector gap into account, which is twice the size of the double density disk for a high density disk. - Changed the logic for handling index and word sync (and the combination of both) again to be more consistent with what trackdisk.device would probably do. trackfile.device 2.15 (14.6.2020) - Added HD_SCSICMD to the list of commands which could be unreasonably expected to see use with this device. When it comes and the debug mode is enabled we can now see it coming. - Fleshed out TFChangeMediaTagList() so that you can now request that the write-protection of the medium may be changed without ejecting the medium first. - Updated the unit process capabilities to handle the write protection change. Note that if you want to disable the write protection, the state of the volume on which the disk image file is found will be checked first and then whether or not the disk image file is write protected. If any of these conditions state that the file cannot be changed, then this operation will fail. trackfile.device 2.16 (15.6.2020) - Surprisingly, TFChangeMediaTagList() works even better if the correct tag item value is used when changing the write protection of a unit. trackfile.device 2.17 (4.7.2020) - Small change for (hopefully) better scalability with lots of disk units around. Each time a search for a unit is performed, that unit data structure is now bumped to the head of the unit list (if it's not already there). This will have the effect of the most frequently-used units to bubble up to the top of the list, making the access a snappier over time. trackfile.device 2.18 (9.7.2020) - Updated the disk checksum algorithm to include the file size itself as the last 64 bit value processed. This should make the algorithm yield a more robust checksum since it will now properly discriminate between data which has been padded with zeroes and data which is unpadded. - TFExamineFileSize() now returns TFEFS_Unsupported (which is -1) if the size of an Amiga disk image file does not match any known supported drive types. trackfile.device 2.19 (11.7.2020) - Padding the track checkums with the total size of the disk image did not always add the correct file size, defeating the purpose of the measure as a guard against mounting disks with identical contents twice. trackfile.device 2.20 (16.7.2020) - Prepared scaffolding for checking the contents of the disk's reserved and root directory blocks. - If the contents of an image file exactly match what a currently active unit uses, the error code returned is no longer ERROR_OBJECT_IN_USE but the more specific TFERROR_DuplicateDisk. - Added an additional layer of safety checks to avoid mounting a disk with volume information which matches the volume node of an already active file system. This is not yet enabled. - The write protection flag for TFC_ChangeWriteProtection doesn't have to be exactly TRUE, it just has to be not FALSE. This could have produced a nasty API bug. - Verified that the unit and device locking are still robust and do not overlap to the point that deadlocks are possible. - Debug output in the unit process no longer has the side-effect of indenting all debug messages for every new unit started. trackfile.device 2.21 (17.7.2020) - Fixed debug output indentation error caused by a missing RETURN() macro in the TD_PROTSTATUS command handling. - Simplified the unit startup procedure to use message passing rather than signals. It's better to keep this kind of stuff simple. Also, the unit Process can now perform almost all its initialization work by itself. - Enabled the code which obtains the file system signature, whether or not the reserved blocks contain a valid boot block checksum, the root directory name, the root directory creation date and whether or not any of the previous two is valid. This information is available through the unit information API and can be used by DAControl (whic does not use it yet). - Made the code work which checks in advance whether or not the volume name and creation date stored on a disk image matches an existing volume node which is being actively used by a file system process already. With this change in place, trackfile.device may be able to stop file systems from crashing which use identical root directory names and root directory creation dates. This is either a clever solution, or beyond clever and really stupid. Time to find out... trackfile.device 2.22 (18.7.2020) - Cleanup and integration work for the code which obtains boot block and root block data. - Process creation was missing the "NP_ConsoleTask,NULL," tag item. Previously, the console task information would have been inherited from the caller. Not that this matters much, but it's one less dangling pointer that could make mischief. - Verified that the volume name/creation date check indeed works for the case of an unused volume node. trackfile.device 2.23 (19.7.2020) - Documented how the boot block checksum algorithm works and also how it is used for testing a checksum. This must correspond to how DAControl 2.21 does this, too. trackfile.device 2.24 (24.7.2020) - Stopping a unit and then restarting it again failed because while the unit Process was inactive, the presence of the unused specific unit data structure was considered an error, which it is not. Fixed. Thanks go to Gerben van Kesteren for reporting the problem and to Camilla Boemann for reminding me to get it fixed. trackfile.device 2.25 (29.7.2020) - As a quirky workaround for FFS v40 and likely all previous versions all checks to verify that the IOStdReq.io_Message.mn_Length field has some meaning towards whether it's safe to use that request are now skipped if a length of 0 is found. Without this workaround FFS V40 would not even mount the disk because TD_CHANGESTATE, etc. would fail. trackfile.device 2.26 (30.7.2020) - Added more diagnostic & debug output to track I/O request processing. - API functions which do not work for a Task and which require a Process (e.g. opening and closing files) now return either an error code or NULL. Better than crashing... - Turns out that the BeginIO() function did not check if an I/O request was actually requested to use quick I/O. Every command that support quick I/O was processed as such. Now this only happens if I/O requests specifically have the IOF_QUICK flag set. - Added the same workaround for the TD_REMCHANGEINT command which trackdisk.device uses. It's possible that the client which used TD_ADDCHANGEINT will reuse the same I/O request for TD_REMCHANGEINT. This must be treated as if IOF_QUICK had been set or otherwise the internal list of I/O requests which contain change interrupts would be corrupted. trackfile.device 2.27 (31.7.2020) - Added reporting of available stack size to all entry points of trackfile.device. Looks good so far. - Simplified the code in all device commands which are callable directly if the I/O request used has the IOF_QUICK flag set, so that only the minimum required steps are taken. This limits how much stack space is required to call these functions. - Added more assertions and precondition/postcondition tests to smoke out undefined behaviour, but so far things are looking sane enough. - Fixed a design bug introduced by the trackdisk.device CMD_START command which now, like the TD_REMCHANGEINT command, is always executed on the context of the caller regardless of whether the associated I/O request has the IOF_QUICK flag set or not. This solves the problem of using CMD_START getting queued like any other command if IOF_QUICK is not set, thus rendering it useless... But then the original trackdisk.device CMD_STOP/CMD_START code was undocumented anyway and likely nobody ever used it. - Simplified the unit I/O request cleanup code which now resorts to sending all queued commands back with error code IOERR_ABORTED. trackfile.device 2.28 (4.8.2020) - The FFS does not use the ETD_READ, etc. commands, so the check_extended_command() function won't ignore its I/O request message length value being zero. - close_unit_file() now properly invalidates the track buffer contents and also safely changes the file handle to zero. This is an emergency shutdown after all. - Refactored the common file read code for all the read/write/format commands. It also takes care of writing the track buffer back to disk, if necessary. This resulted in much shorter read/write/format command implementations. - The few commands which support IOF_QUICK no longer hold onto the unit lock. Instead they read from the unit data. That unit data is only written to under Forbid() conditions, making the read access safe. This is also a precaution for making these read accesses safe if the respective function had been called from Disable() or supervisor state. - Added more arithmetic overflow checking in the debug build. - Reworked how the track and disk checksums are calculated, which now use a separate table which is not part of the unit data structure allocated. The size of that table is now stored explicitly in the unit data structure and is always large enough for an 80 cylinder disk. - eject_image_file() is now safe to use even if the unit file had been closed by close_unit_file() due to an emergency. Also, close_unit_file() now sends an ACTION_FLUSH packet to the file system only if the file had ever been modified. - Added more code comments and debug output. - Updated the local AutoDocs to indicate precisely which commands really support IOF_QUICK mode operations, which is only a small subset. - Added a new stack size checking and reporting function which will also report if the execution context is not currently in user mode. trackfile.device 2.29 (4.8.2020) - The device open function does not actually need to use the global signal semaphore. - The device begin I/O function does not need the global signal semaphore either, Forbid() locking is fine, too. - send_unit_control_command() and find_unit_by_number() do not need the global signal semaphore, Forbid() locking is fine, too. - tf_start_unit_taglist() needs to use Forbid() locking when adding a new unit to the global list, now that find_unit_by_number() no longer uses the global signal semaphore. trackfile.device 2.30 (4.8.2020) - tf_get_unit_data() no longer trashes memory if called from a Task context. - The assert.c code no longer uses debug.lib and is no longer compatible with GCC or OS4, for that matter. - Disabled all code optimizations in the build GNUmakefile. trackfile.device 2.31 (5.8.2020) - update_disk_checksum() can no longer be called accidentally through tf_get_unit_data() if there are no track checksums enabled for a unit. Previously, it could have trashed memory. This seems to have been the only execute path through which this memory trashing could have been triggered. - The medium insert/eject operations now trigger the medium change notifications after they have replied the respective control messages. - Changed the name of the local vsnprintf() and snprintf() functions to make clang happy and not complain about the function prototypes being different from the C99 versions. - Added unit address validation in AbortIO() and BeginO() device functions. - Added more code documentation. - Debug output in read/write/format code now prints more detailed information on the I/O request. trackfile.device 2.32 (6.8.2020) - If the file system of the ovlume on which disk image files reside does not support AmigaDOS 2.x functions such as ExamineFH(), DupLockFromFH(), ParentOfFH() or NameFromFH(), trackfile.device now uses fallbacks if possible. This may have the effect of the full path name of disk image files being unavailable, but is mostly harmless. For example, trackfile.device may no longer be able to conclude that a disk image file cannot be written to because it cannot safely examine the volume on which that file is stored. trackfile.device 2.33 (7.8.2020) - If ExamineFH() does not work for a disk image file to learn its file size, we now try Lock() and Examine() if at least the file name is known. This should be faster and more scalable (for large files) than the use of Seek(). Obtaining a lock on the disk image file will also allow for the volume on which the file resides to be checked for write protection. - Reviewed how the global device lock vs the Forbid()/Permit() locking is used and made a few changes for more robustness. Turns out that locking was used frequently under the assumption that a unit could be removed, but in the current design this is not possible. Accessing the unit list now always requires that the global device lock is being held. trackfile.device 2.34 (8.8.2020) - Added more cache support code, including control tags which are probably best placed in a new API. The code still needs hooking up in DAControl or at least a test build for initial experiments ;-) - Just because it might actually make a difference on slow devices, the trackfile units now remember the last file read/write position and will skip the Seek() call if it has not changed. trackfile.device 2.35 (9.8.2020) - Added more diagnostic code for the seek optimizations. - Added references for the source of the splay tree code. - tf_get_unit_data() now supplies information about the state of the cache for the unit, as in whether it is enabled, how many accesses have taken place, and how many of these were cache misses. - Trying to enable the disk cache for a unit is now denied if the disk drive type is not currently supported. support for high density 3.5" disks still needs to be worked out. - If the cache is enabled for a unit, reading from the disk image fill will now actively fill it or update existing entries. Likewise, successful write accesses will update existing cache entries. However, successful write accesses will not create new cache entries. - Failed write operations now invalidate the cache entry which corresponds to the track which could not be written to. - Ejecting a disk image file now invalidates all the cache entries of this specific unit. This code currently does not scale particularly well at all :-/ - Unfortunately, the caching imposes an artificial limit on the number of units which can be in operation at the same time. Available memory is no longer the limiting factor here, and only up to 8,388,608 units may be used at a time now. trackfile.device 2.36 (9.8.2020) - Fixed the seek optimization which did not play well with the caching... - The cache enable/prefill options did not get evaluated properly, producing the odd side-effect of always getting enabled by default. Fixed. - The test for an unusable cache size was put in the wrong way round and thereby rendered the cache ineffective. Fixed. - The percentage figure calculated for the cache hit ratio was too far off. Fixed. - The prefill option will be ignored if the size of the disk image file is larger than what the device cache can hold. trackfile.device 2.37 (10.8.2020) - Changed the name of the TFChangeMediaTagList/TFChangeMediaTags function to TFChangeUnitTagList/TFChangeUnitTags so that the API changes which affect all units could find a more fitting home here. - The just-renamed TFChangeUnitTagList function now supports the TF_MaxCacheMemory tag, which will change the maximum amount of cache memory which all units share. This setting can only be changed for the control unit, though, not for any individual units. - Added code to handle the "this should never happen" case of duplicate keys in the cache. - Removed the empty_cache() cache function which might make a comeback one of these days... - Changing the size of the shared cache no longer clears the current cache first. If the new cache size results in fewer cache entries to be active, then these will be removed and freed first. - The seek optimization debugging code could have a Seek() function calls left even if the code was not built for debugging. Fixed. trackfile.device 2.38 (10.8.2020) - Updated the code documentation. - The update_cache_contents() function now tries to reuse an unused cache node before it attempts to allocate memory for a new node. Previously, a test to verify that adding another node would not break the memory limit prevented the unused node to be picked up. Fixed. trackfile.device 2.39 (11.8.2020) - Added code which should make the invalidation of all the cache entries associated with a single unit more scalable. Instead of checking all the probation and protection segment entries to find out which entries need to go, the respective unit now keeps track of all the cache nodes associated with. - The unit data structure is now passed along to the respective cache functions which previously had to rely solely on the unit and track numbers to read from or write to the cache (and invalidate all the cache entries for a unit). - Added scaffolding for getting on the good side of the 'C' compiler when using MinList/MinNode types with the exec.library functions Insert(), AddHead(), AddTail(), Remove(), RemHead() and RemTail() as well as the amiga.lib function NewList(). This scaffolding will have to go, eventually, but in the mean time it's useful for switching List/Node types to MinList and MinNode types, respectively, and have the compiler watch your back for a change ;-) trackfile.device 2.40 (11.8.2020) - Switched List/Node types to MinList and MinNode types, respectively, where this made good sense. This had the side-effect of rendering the padding words in several data structures unnecessary. - Added fancy function prototypes for MinList/MinNode-specific versions of Insert(), AddHead(), AddTail(), Remove(), RemHead(), RemTail() and NewList() which helped to verify that the change to MinList/MinNode was good enough. The scaffolding code for these has been commented out now. trackfile.device 2.41 (12.8.2020) - TFChangeUnitTagList() can now change the size of the shared cache (only for the control unit). Also, for each unit (with the exception of the control unit) the cache can now be enabled and disabled; disabling the cache will also invalidate all cache entries for this unit. - Following the lead of how the Amiga default file system processes what may be a root directory block, the checks applied to the contents of the block now go beyond verifying the checksum and the block type information. trackfile.device 2.42 (14.8.2020) - Forgot that the device expunge function must not call Wait(), and that means ObtainSemaphore() is unsuitable. Now we're trying to get by with AttemptSemaphore() instead. - tf_start_unit_taglist() will now configure the cache exactly once and won't change the cache size when invoked again. This is how it was always supposed to be like. trackfile.device 2.43 (14.8.2020) - The memory handler which may be called if memory is tight now uses a separate stack to avoid trouble. As per the API documentation the memory handler may be called with as little as 64 bytes of stack available. The separate stack will have room for 2000 bytes which is hopefully much more than is required for the memory handler cleanup function to do its job. trackfile.device 2.44 (15.8.2020) - The cache feature is now enabled by default. - Simplified the code which adjusts the amount of memory which the cache may use, removing duplicate/sufficiently similar implementations of functions which performed the same tasks. - Removed non-essential data structures from the caching code. trackfile.device 2.45 (15.8.2020) - Stack swapping was set up incorrectly, yielding maximum trouble :-( Fixed. - The maximum cache size is now broken down into actual cache entry size chunks rather than just the size of the cache entry payload. This means that each cache entry now counts for 32 + 5632 = 5664 bytes total. - The maximum cache size is now rounded up to a multiple of the cache node size unless it's too small or 0. - Disabling a unit cache now also resets its cache access/miss counters to 0. trackfile.device 2.46 (19.10.2020) - The unit Process no longer calls ReplyMsg() on an IOStdReq which successfully uses TD_ADDCHANGEINT. This is necessary because that IOStdReq will be stored in a unit-local list until a corresponding TD_REMCHANGEINT using the very same IOStdReq will remove it. Please note that this behaviour is "normal", for trackdisk.device, at least. Thanks go to Gerben van Kesteren for finding the conditions under which the problem emerged!