Hi everyone
In case you haven't been following the recent thread on the QL Users mail-list, the issue reported in this post has since been diagnosed and fixed.
Marcel Kilgus has posted on his blog how he tested and identified the very small fault in later versions of Minerva (after v1.92) that can cause a QL to hang when LBYTES is used to receive using the TK2 enhanced Network driver. You can read about it here as well as downloading a recompiled version of Minerva based on v1.98 known to work well with the TK2 NW:
https://www.kilgus.net/2018/02/27/debugging-minerva
If you're interested in a little more detail or if you suspect that your own lack of success using the QL Network might have something to do with the issue Marcel has now fixed, read on...
Ultimately, the root cause was not with the Minerva NET driver, nor the TK2 driver that replaces it (both of which are pretty marvelous bits of programming), but with a QDOS/Minerva routine called 'serio' that all simple, serial device drivers - like NET - call to route each of ten supported access-layer requests to one of three very simple core routines that the device driver provides - "test for pending input", "fetch a byte" and "send a byte".
One of the 10 serial device access-layer requests is "fs.headr" - used to read the (simple) 15x byte file-header that has been prepended to data sent via SBYTES and similar commands (SEXEC, etc) and used by the receiving command to determine the length of the data that follows and, if an executable file, the exec-flag and data-space requirements.
So, before LBYTES reads the data itself, it first attempts to read this simple file-header by calling the fs.headr routine via serio. In turn, fs.headr prepares to call the device driver's core 'test for pending input' or io_pend, effectively to read the first byte from the receiving channel. io_pend returns not just whether there is any data available yet, but also a copy of the next byte that would be retrieved upon the next 'fetch byte' call.
LBYTES et-al check this first byte to ensure it is FFh - which flags the start of simple file-header. This is why you get a 'bad parameter' error when you attempt to LBYTES a file over a serial channel (open to NET, SER or MEM devices etc...) that does not include a file-header - perhaps sent with plain 'COPY'. (Curiously, LOADing a S*Basic program on Minerva also complains if no file-header is detected, even though it shouldn't need one...)
In Minerva sometime after v1.92, but certainly by v1.97, the authors had chosen to tweak very slightly the serio code provided by the OS, based on an assumption that any valid call to io_pend would hold a particular value (0) in register d0. This is true when an access-layer call requests directly to 'test for pending input' (Trap #3, Key $00), but _not_ valid if fs.headr had been requested - effectively serio 'nests' the call to io_pend within the fs.headr routine, by which time the value of d0 is certainly not 0...
Marcel has now sorted that by reintroducing a single instruction (moveq #0,d0) back in to Minerva's serio routine - where, as it happens, it had previously been commented out
One remaining question I had that the above does not directly answer is 'why did LBYTES work at all for Minerva without TK2 loaded, yet failed when it was loaded?'
The answer is that Minerva also introduced - and uses internally - a variant of serio, called 'relio'. relio is slightly more efficient and easier to arrange your access-layer calls around, but effectively runs through most of the serio code to meet the request. Minerva uses relio for NET (and IIRC all its simple device drivers) and it just so happens that relio does not rely on the value of register d0 as serio does when calling io_pend, so never hits the problem described above.
Introduce the TK2 Net driver to Minerva v1.97+ and you are back to using the standard serio call: invoke LBYTES and Bang!
If its not already apparent from the above, whilst this was uncovered whilst playing with the NET driver specifically, _any_ device driver that leverages 'serio' to wrap around its own access-layer routines is liable to hang the QL in a similar manner when a request is made to read the file-header, either indirectly via LBYTES/EXEC* or directly requesting fs.headr (Trap #3, Key $47). This would include the ubiquitous MEM device, for example...
Having now studied as a result of this long-standing issue both the Minerva and TK2 source code enough to make one's head spin, I am left ever more impressed by the brilliance of the original developers and also an ever-so-slightly smug feeling that I was right to be 'curious' about Minerva, Tk2 and LBYTES after-all!
You gotta love the QL...