3: The Tube

While the 80186 processor may be the heart of the 512 board, the Tube is the most critical part of the complete system. Every byte of data read from disc or keyboard or output to disc, screen or printer must pass through the Tube at least twice.

It is equally true that, even for experienced users, the Tube is also the most mysterious part of the machine. Its operations cannot directly be inferred from the activities which take place at either end of it and, particularly in the case of the 512, it is difficult to investigate, since two very different types of machine code are involved at the same time. The remainder of this chapter examines the general functions of the Tube and the standard inter-processor communication code which provides the coprocessor with MOS and filing system support in the host.

General Description

The Tube is an Acorn designed and registered proprietary data interface for connecting two microcomputers, which may be of similar or different types. The data transmission rate of the Tube is nominally 2 million bits (250,000 bytes) per second. With due allowance made for the overhead of mutually understood communication signals and latency between the two processors, effective data rates are less, though still more than fast enough to be small penalty even for rapid peripherals such as disc drives and powerful processors such as the 80186.

The Tube terminates in each machine in a dedicated chip called a Tube ULA (Uncommitted Logic Array), so as to provide a data bus 32 bits wide, giving four independent bi-directional communication paths. Each path consists of a one-byte wide control register, also referred to as a status register, and a one byte wide data transfer register.

While the two machines connected by Tube may appear to work in synchronisation to provide the facilities of the system as a whole, the Tube is seen by both processors more or less as an input-output peripheral. Each can make a request, or a response to a request, and then continue to perform other tasks, for example, processing interrupts or events.

In Acorn systems to date, the host, which provides all physical I/O services, has always been a variant of the 6502 based BBC microcomputer. Tube communication, therefore, is based around the facilities provided by the host's MOS and filing system and the parasite's anticipated requirements for them. In all versions of host, the range of MOS functions provided for parasite support is common, and this, therefore, dictates the protocol for requesting services or accepting a response. This constant base has, so far, ensured that all versions of the host (when fitted with the appropriate hardware) can support all versions of co-processor.

Since the host's software interface and its facilities are effectively invariant, it is the responsibility of the parasite to provide such machine code routines in its own language as are necessary to conform to Tube communications standards and to use the facilities as provided. If additional or non-standard facilities are required by the parasite over and above those provided by the Tube host code, they must be supplied by the parasite, but by means of extra code located within the host. This is the case for the 512, since it uses both non-standard screen output and non-standard disc formats, neither of which are supported by the host's MOS or filing systems.

The two processors on each side of the Tube are not in any way directly synchronised with each other. The Tube is regarded by both as an asynchronous data channel, which in the host must be checked for activity requests from time to time and in the parasite must likewise be checked, or it may demand attention by means of interrupt requests, or non-maskable interrupts for very fast transfers. This situation can best be envisaged by two simple illustrations. From the 512's viewpoint, keyboard or serial data input may be waiting at any time in the host, while from the host's point of view, the 512 might request any input or output services at any time.

To maximise overall system performance the Tube is therefore given a high priority by both processors. So as to avoid keeping the other processor waiting, each might delay certain other operations in order to service the Tube. This is sometimes visible in the 512 system when large quantities of screen data are output rapidly. Although data is being transferred and written directly to the host's screen memory map, the host may not be permitted sufficient time to update the visible image concurrently, which therefore is seen by the user to appear in 'chunks', or sometimes even a screenful at a time.

In the host the highest priority activity is usually the disc filing system (DFS), or the fileserver in networked systems. One of these two is normally the owner of the (sole) Non-Maskable Interrupt (NMI) in the host and NMI routines are permitted to cut across all other activity when the 6502 processor's services are required. In co-processors that exclusively use standard host facilities this is acceptable, since all I/O is via the Tube host code, using only MOS and filing system services. In the 512 system, however, since discs are also read and written by the 512's own 6502-resident code, this is not so.

The extra host code provided by the 512 is loaded from 6502.SYS and is subsequently downloaded into the 6502 host's RAM to supplement the Tube host code facilities- Amongst the extra routines provided are facilities for directly programming several of the host's hardware device controllers. Therefore this code introduces an extra NMI owner into the system. During such 512 operations, the host's MOS and filing system are by-passed and NMI ownership is claimed from the host (or from the network) and may be retained for the duration of the operation, which under no circumstances can then be interrupted. Since no NMI routine, once started, can be interrupted before completion, the 6502.SYS code has, by claiming the NMI, effectively implemented a method of masking both maskable and non maskable interrupts from any external source.

In the host to parasite direction, such critical operations as the transferring of disc data must not be delayed, since this would, in effect, hold up a host NMI, which itself holds up other host interrupt and event activity. For this reason many Tube transfer requests generated in the host cause an interrupt request in the parasite, which therefore services the transfer rapidly. In practice, apart from the case of a machine connected to a network, there is nothing on the host side of the Tube which can generate unexpected NMIs. Even host disc activity is normally a direct result of a parasite request, which therefore will often be 'waiting' for the response.

However, there is one autonomous activity in the parasite that could interfere with such time critical functions. That is, processor clock interrupts, (an 86 clock interrupt is generally called a 'tick' for short, for the obvious reason). To avoid this potential conflict, very fast Tube data transfers can be set up so as to generate an NMI m the parasite, thus suppressing dock interrupts for the duration.

Tube Operations

The prime purpose of the Tube interface is to permit a parasite processor to gain access to host MOS and filing system functions which are concerned with host configuration and peripheral device support. The host system software calls, that form the basis of this support, are essentially of three types.

  1. Calls which cause the host to carry out some independent action for which there is no returned information. For example, writing characters to the current output stream (OSWRCH) or changing the serial port speed (OSBYTE).
  2. Calls which cause the host to perform an activity which will result in a return of low volumes of information in a non time critical (i.e. asynchronous) manner. For example, reading characters from the current input stream, usually the keyboard or the RS232 port.
  3. Calls which cause the host to perform a function which will result in information being returned in volume and/or in a time critical manner. For example reading or writing disc information or communication through a network.

The four Tube registers are broadly assigned to these call categories as follows. Calls of type one from the parasite to the host are passed through Tube register one. Type two, the general MOS and filing system commands, are passed through register two.

Calls of both types (if appropriate) from the host to the parasite pass through register two. In both these types of call the relevant processor polls the appropriate status register until the status flags indicate that the data register is ready to accept or supply data. In the host code source listing, this loop of code is called Tube_idle_loop, which is executed permanently when the system is not involved in servicing existing Tube requests or its own interrupts. In the 512, the counterpart to these Tube registers are checked on each processor clock interrupt, and serviced if a Tube interrupt request (IRQ) is outstanding.

From parasite to host, register one is used for writing to the current output stream via OSWRCH, while register two is used to request various calls such as OSBYTE, OSWORD and filing system calls. However, a filing system call depending on the service requested, may or may not result in a transfer (in either direction) of type three.

If it does and the transfer is to the host, the host will read register three until data is received and process it according to the operation requested. When data is written to (or read from) register three by the host, if necessary an NMI can be generated in the parasite, which must therefore immediately suspend other activities So as to service Tube register three without delaying the host.

If the transfer is from the host, register one or four is first used by the host to generate an IRQ in the parasite to warn of the impending arrival of data. The host then waits for a response from the parasite.

The parasite immediately sets status register three to signal its readiness. At this stage, the host assumes all the data may be sent and proceeds to transfer the data through register three at a regular rate with no further status checks. It is therefore the parasite's responsibility to ensure that data is read from register three at a rate fast enough to keep pace with the host before the next interrupt is generated. It will be seen from the host source listing that, because this type of Tube transfer is time critical, the code includes three NOPs to introduce delays into the transfer loop to increase reliability, especially of the slower co-processors such as 6502 and Z80 based versions.

Note that not all transfers through register three generate NMIs in the parasite, only host NMI or large block transfer routines are so time critical as to require NMIs in the parasite. In addition, many type two calls return low volume information through register two.

Tube registers do not normally cause direct interrupt requests in the host, although the peripheral activity requested by the parasite may do so by means of the host's normal hardware and software functions. However, the parasite has no peripheral hardware except the Tube ULA, so the reading or writing of Tube registers by the host serves to set parasite IRQs or generate NMIs while the reading or writing of the registers by the parasite clears such requests. It should also be noted that at any time it is possible for more than one type of Tube transfer to be outstanding by the use of different Tube registers.

Tube Protocol

Since at any point when there is no current activity neither processor can know what the next Tube request is likely to be, or what the other processor is doing, both must be prepared to recognise and carry out any of the range of Tube functions at any time. A communication system must exist therefore, where each processor can either leave a request for action, or acknowledge a request left by the other, which will be understood and acted on accordingly. Many of these actions are followed by the transmission or receipt of data, which require a similar understanding. This communication system, together with the Tube register usage, is known as the Tube protocol.

Tube protocol is a standard method of signalling intentions, requests or results through Tube registers, which will be understood by both processors, even when they are of different types. The eight registers are generally used in pairs, the status register being used to signal a request or condition, the data register for the actual transfer or response, though in some cases the request is made through one register and subsequent data transfer uses another.

The first necessity for any facility wishing to use the Tube is to successfully claim temporary ownership of it. This prevents any other facility attempting a simultaneous transfer in the same or the opposite direction. In this context a 'facility' can be the operating system in either processor, the host filing system or a network controller, each of which may wish to use the Tube host code for their own separate purposes. The entry point at &406 in the Tube host code is used for the purposes of claiming or releasing the Tube, as well as for transfers of data between the memories of the two processors.

To claim the Tube a call to this code should be made with a value in the accumulator of &C0 plus an identifier code that is unique to the caller. The identifier is a value between &1 and &F inclusive and is stored in the host's page zero on a successful Tube claim to record who currently has control. The claim at first may appear to have failed if the Tube is already in use, but the caller maybe the existing owner, therefore the caller's identity is compared with the current owner's. If it matches, the Tube claim is deemed to have succeeded. In other words, there is no 'you already have it' type of reply. There are only two possible results from a Tube claim, success or failure.

If the Tube claim is successful, the carry flag is set. The caller may then proceed with the next stage in the operation. If the claim returns with the carry flag dear the Tube claim was unsuccessful, which means it has already been claimed by another facility. If in this case the failed claimant is an operating system, it should immediately poll the Tube status registers on its own side of the Tube to ascertain what action follows. Filing systems and the additional Tube code in 6502.SYS simply keep trying the claim until successful. Since they have no Tube registers to monitor, such requests as are intended for them are notified by the operating system.

This aspect of Tube protocol is perhaps the most confusing. While transfer responses are made exclusively in the appropriate processor, all Tube claim or release attempts and data transfer requests (even the parasite's) take place in the host. It is perhaps easiest to think that, in effect, the Tube host code temporarily adopts the identity of the caller for the purposes of initiating these functions. A much-simplified example of this across Tube dialogue by the 512 may further clarify things, and is included at the end of this chapter after the Tube registers and calls have been described.

After a successful Tube claim and carrying out the subsequent transfer operation, the Tube owner should immediately either issue another Tube command, or release the Tube so as to make it available again to both processors for further operations in either direction. The release is called at the same entry point and with the same value in the accumulator as was used for the claim. The callers identity is then cleared and the Tube busy, flag is reset to 'available'.

The Tube Registers

All eight registers are read/write. In general, when intending to read or write any of the registers, both the host and the parasite first read the status, simply looping back to check again if the status shows 'not ready'. The exceptions to this are the time critical block transfers through register three, when the status is checked only once prior to the start of the transfer, but not again during it.

The eight Tube ULA registers are memory mapped in both processors. This is always at fixed locations in SHIELA in the host, but varies in the parasite depending on the type and in the 512 depending on the version of DOS Plus. Each register is, however, assigned general purposes and status protocols as shown below, which do not vary with the parasite or OS type. Note that in all the Tube status registers bit six set is shown as 'not full'. It should be noted that, since some transfers are more than a single byte, 'not full' does not mean the same as empty. Frequently all the sender needs to know is that more data can be sent immediately, regardless of whether previous data has yet been received or not.

Register 1
Status	- bit 7 = data available + parasite IRQ pending
	- bit 6= not full
	- bit 5 = Set parasite reset active low (BREAK pressed)
	- bit 4 = Enable 2 byte FIFO register three transfers
	- bit 3 = Enable parasite NMI from register three data
	- bit 2 = Enable parasite IRQ from register four data
	- bit 1 = Enable parasite IRQ from register one data
	- bit 0 = Enable host IRQ from register four data
Data	- read or write. 
	Host write generates parasite IRQ 
	Parasite read clears IRQ

In the parasite to host direction, register one is used for OSWRCH. The data register acts a FIFO buffer big enough to permit the longest VDU command to be processed, thus increasing the chance that the two processors will achieve parallel execution.

In the host to parasite direction, the data register provides a one byte buffer which, when written to, generates an IRQ in the parasite. It is used to pass on host events, interrupts such as are caused by a keypress, and the ESCAPE flag. On initial system start-up, the value of bit 5 informs the parasite that a reset is in progress (i.e. the BREAK key has been pressed). During this start-up sequence, status register one may also be used to set up a returned IRQ to the host.

Register 2
Status	- bit 7 = data available
	- bit 6 = not full
	bits 5 to 0 not used 
Data	- read or write.

This register is used to implement long (in terms of processor time) MOS calls, or those which cannot be permitted to interrupt the parasite to host OSWRCH serviced by register one. This group of calls, in fact, consists of all the remainder of the standard direct host MOS calls from the parasite except OSWRCH itself. The parasite passes a byte to indicate the call required and this causes a jump in the host code to the appropriate routine. The two machines then continue their dialogue through register two to pass any required parameters needed by the call.

The same register is used to initiate non time-critical data transfers through the Tube when the host code is entered at &406. The type of transfer is signalled by a reason code followed by an appropriate relocation address in the host or parasite (depending on the direction) sent in the usual 6502 four byte form. In the Tube host code these relocation addresses are indirected through X and Y in the normal 6502 manner. If an address in four byte format is not suitable for the parasite to use directly, as in the 512, it is the parasite's responsibility to translate the address to or from a suitable form (e.g. segment:offset), hence the host need not be aware of the processor type currently in use.

Register two is also used as the channel through which requests on the filing system are made, which may result in time critical filing system data transfers such as reading or writing a file. In this case, although the request is issued through register two, the transfer takes place through register three.

The reason codes passed through register two for all these data transfers and their meanings are:

0 - A single byte parasite to host transfer
1 - A single byte host to parasite transfer

These two calls transfer any number of single bytes and terminate in the release of the Tube by the sender, or recommending for a different action.

2 - A double byte parasite to host transfer
3 - A double byte host to parasite transfer

These calls transfer an even number of bytes, as each transfer is two bytes. This also results in a faster transfer than types zero or one, since less status polling is involved per byte transferred.

4 - Execute code

This call is used to instruct the parasite to commence code execution at a given address, as in the initial start-up signal prior to the co-processor entering the bootstrap loader. This call contains an implied Tube release and control is not returned to the caller.

5 - Not used for transfer, reserved for filing system release

6 - A 236-byte parasite to host transfer

7 - A 256-byte host to parasite transfer

Both of these calls transfer exactly and only 256 bytes, or by repeated calls using a counter, multiples thereof. They are the fastest form of data transfer since no status checking is carried out within the block and therefore no other interrupts are generated. Only after a complete block is transferred ray the Tube be released or re-commanded.

Bulk disc data transfers are, by definition, always a multiple of 256 bytes, but for other transfers two strategies are possible. If a transfer of, say, 300 bytes were required, in some cases two blocks totalling 512 bytes might be sent, the extra bytes being discarded. Alternatively, the first 256 bytes could be transferred by these calls and the remainder by means of calls zero to three.

Register 3

Status	- bit 7 = data available and parasite NMI generated
	- bit 6 = not full
	- bits 5 to 0 not used
Data	- Read or write. 
Host to parasite:
	Host write can generate parasite NMI
	Parasite read clears NMI
Parasite to host:
	Host read can generate parasite NMI
	Parasite write clears NMI

Register three is used by transfers which require the attention of the host's NMI owner (i.e. the filing system or the network), hence any data transfer to or from the host may need to also generate an NMI in the parasite.

Register three data can be programmed as a one-byte channel or as a two-byte FIFO channel. The setting of status bits in register one determines whether NMIs should be generated in the parasite by these transfers. If set as a two-byte channel and NMIs are enabled, both bytes must be written to generate a parasite NMI. In the host to parasite direction, the writing of two bytes by the host causes the NMI, which must be cleared by the parasite reading both bytes. In the parasite to host direction, the action of the host reading both bytes causes a parasite NMI which is only cleared when the next two bytes are written by the parasite.

This technique ensures that any action on the part of the host can, if required, produce an immediate response from the parasite, hence the host (and it's own NMI functions) are not delayed. Since there are no physical external devices that can cause either IRQs or NMIs in the parasite (which would in a conventional processor be triggered by direct hardware activity), the Tube registers are used to fulfil this purpose. So as to avoid the need for buffering and relocating in the 512, the Tube register three NMI is processed by the direct memory access (DMA) routine in DOS, hence data is read and transferred immediately to its final memory destination, rather than being buffered and moved.

When register three is set as a single byte channel, slow or time independent transfers are carried out through it which do not generate NMIs in the parasite.

Register 4
Status	- bit 7 = data available + parasite IRQ pending
	- bit 6 = not full
	- bits 5 to 0 not used
Data	- Read or write. 
Host write generates parasite IRQ 
Parasite read clears IRQ

Register four is used as the control channel for the register three time critical block transfers. It is also used to transfer errors from the host to the parasite. In both cases the host can generate an interrupt in the parasite by setting the status and placing a byte in the data register.

In the case of fast-register three data transfers, the byte is an instruction byte describing the required action. The two processors then co-operate in passing data back and forth through register four until the parasite removes a synchronisation byte to indicate that it is ready for the register three transfer to begin. This interactive (or the nearest to it in Tube protocol) communication effectively causes the host to wait (for a short time) while the parasite prepares itself for the very fast register three transfer. This action will include disabling its own internal interrupts (i.e. the clock) and pushing all registers on the stack in preparation for the NMI, which will then follow as soon as the host is notified to proceed.

When used for error signalling, the host causes a parasite error interrupt request by writing an error code to register four. The two processors then co-operate in passing the error string through data register two. Typically these errors are as a result of the failure of a MOS or filing system function; (e.g. file not found, drive not ready, corrupted disc, RS232 parity error etc.). Some of these errors are reported verbatim by the 512, others are translated into DOS standard message, before presentation to the user.

It can be seen that, although the setting up of transfer requests and the possible delay before a response is received is asynchronous, if the timing of many transfers, once started, were not carefully synchronised, serious problems could arise. The code in both processors, therefore, has to be matched, not only for function, but in some cases is tuned for elapsed execution time for each operation, once begun.

The timings for the six categories of transfer shown above now follow. If in practice these times are exceeded, data loss or corruption may be incured. In Table 4.1, P refers to the parasite, H to the host.

Type Direction Start delay Service time
0 P to H 24 secs 24 secs
1 H to P 0 secs 24 secs
2 P to H 26 secs 26 secs/pair
3 H to P 0 secs 24 secs/pair
4 - - -
5 - - -
6 P to H 19 secs 10 secs
7 H to P 0 secs 10 secs

Table 4.1 Timings of Transfers.

Note that not all 512 to host (or vice versa) activity is directed through the calls provided by the Tube host code. Special custornised functions are provided by the extra code in 6502.SYS, which is loaded from disc when DOS is booted. Functions which are not controlled through the host code are essentially all the IBM type operations, since none of these are supported by the host's Tube code, its MOS or its filing systems. These are:

  1. 6845 CRTC direct programming for IBM to BBC screen mapping
  2. The writing of all screen Characters
  3. IBM graphics display bytes
  4. Reading and writing of the user port
  5. WD1770/1772 direct programming for all disc formats except 640k
  6. NMI ownership swapping, necessitated by the above

These functions are discussed separately in the next chapter. The 6502.SYS source code is listed elsewhere with full commentary.

Host MOS Calls

The co-processor MOS calls supported by the 6502 are now detailed as seen from be host side of the Tube. That is, those for which facilities are provided in the standard Tube host code and which are available to all Acorn co-processors. The entry conditions for the 80186 registers for these calls within the 512 are detailed later.

In all cases below, it is implicit that the caller has already successfully claimed the Tube before issuing the request. During any call an error may result, in which case the call is abandoned by the host and the error information returned through a register four interrupt, as already described.

OSWRCH: Host Operating System Write Character

This call is directed through register one. In the 512 this is used for writing to the printer and the RS232 port. The parasite protocol is simply to wait until register one data 'not full' and write a character. Nothing is returned.

OSRDCH: Host Operating System Read Character

This call is directed through register two. The 512 requests a byte to be read from the current input stream. The parasite protocol is wait for register two not full and write &00 to it. A single byte is read by the host's MOS and transferred back, also in register two.

OSCLI: Host Operating System Command Line Interpreter

This call is directed through register two. The parasite protocol is wait for register two not full and write &02 to it. The host code then reads a slow block transfer through register two of up to 256 bytes or until CHR$13 is received. The command string is stored at &700 and immediately passed to the host's MOS. A completion byte (&7F) is then returned to the parasite to confirm completion of the command.

OSBYTE: Host Operating System Byte General Function Call

This call is directed through register two and is implemented in two forms. The first is known as a short OSBYTE, when only the 6502's accumulator and the X register require parameters. The second is the long OSBYTE, when the accumulator and both the X and Y registers parameters to the call must be supplied.

For a short OSBYTE the parasite waits for register two not full as normal then sends the short OSBYTE request, &04. It then transfers the x register value followed by the accumulator value defining the call. The MOS call is issued immediately and the 6502 polls register two status until not full, when it returns the x register value only.

For a long OSBYTE, the parasite must request the call by sending a value of &06. It must then send the X, Y and accumulator values in that order. The host code then calls the MOS routine, but before returning the call tests to see if the call was an OSBYTE 157, which is a 'fast Tube BPUT'. If it was there is no reply and the routine exits back to the idle loop. In this circumstance it is the parasite's responsibility to 'know that no parameters will be returned, so the Tube should be released or re-commanded immediately.

For all other long OSBYTE calls, all three of the 6502 register's contents are returned to the parasite. The sequence of return is accumulator, Y register and then X register.

OSWORD: Host Operating System Word General Function Call

This call is directed through register two, but again two separate versions of the call are implemented.

A general OSWORD call (i.e. any except zero) is indicated by the parasite writing a call value of &08. Next the OSWORD type is sent, followed by the number of parameters which will be required. Finally the parameters themselves are sent and stored in the host's RAM prior to the call.

The X and Y registers are pointed to the parameter block and the call is issued. If no parameters are to be returned the call ends. As for OSBYTE 157, the parasite should know from the type of call whether values will be returned and act accordingly. If returned values are to be transferred back to the parasite the data is sent through register two. The number of parameters sent and returned can be read from the following table.

OSWORD
number
Params
Sent Ret'd
1 (&01) 0 5
2 (&02) 5 0
3 (&03) 0 5
4 (&04) 5 0
5 (&05) 2 5
6 (&06) 5 0
7 (&07) 8 0
8 (&08) 14 0
9 (&09) 4 5
10 (&0A) 1 9
11 (&0B) 5 0
12 (&0C) 0 8
13 (&0D) 16 16
14 (&0E) 16 16
15 (&0F) 16 16
16 (&10) 16 13
17 (&11) 13 13
18 (&12) 0 128
19 (&13) 8 8
20 (&14) 128 128
21 (&15)
to 127 (&7F)
16 16

Table 4.2 Numbers of OSWORD parameters transferred

For OSWORDs 128 (&80) to 255 (&FF) the number of parameters is embedded in the parameter block at X-Y offset zero for calls, and the number returned after the call is at (X-Y)+1.

OSWORD 0, read line from input, is indicated by writing register two with a call value of &0A. This call is irnplemented separately from the other OSWORD calls as it is a special case. This is because it may well be reading from user input at the keyboard, so firstly it may be extremely slow in processor terms. Secondly, although a maximum input length is specified in the call parameters, the user can terminate the call earlier by pressing one of several keys, therefore the length of returned information cannot be determined until the call is complete.

Finally, the user might press the ESCAPE key, which means the call will be abandoned entirely before completion, not necessarily with an error, and code must be provided to cater for this.

If the call is successfully completed, up to a maximum of 256 characters may be retumed through register two, or up to the first encounter of RETURN (CHR$13).

If the call is abandoned by the user pressing the ESCAPE key, the call is terminated, input is discarded and the escape is signalled by returning a single byte of value &FF.

OSARGS: Read/Write File Attributes or Read Filing System Type

This call is directed through register two and is requested by the parasite setting a call value of &0C. The parasite then transfers the file handle concerned, (or zero if none) followed by a varying number of actual parameters, though four bytes are always sent. This is followed by the OSARGS call type in the accumulator.
The call is immediately executed and four bytes (not all necessarily significant) are returned through register two.

OSBGET: Get (Read) a Byte from an Open File

This call is directed through register two, and is indicated by a call number of &0E. The file handle is passed, transferred to Y and the call is issued. If successful a single byte is returned, otherwise an error is generated and the call is abandoned.

OSBPUT: Put (Byte) a Byte to an Open File

This call is directed through register two, requested by a call number of &10. The file handle is first passed, followed by the byte to be written. The call is issued immediately and if successful, a single completion byte (&7F) is returned.

OSFIND: Open or Close a File for Byte Access

This call is directed through register two, by setting a call request number of &12. First the file handle is transferred, followed by the operation code which the host code stores on the stack, while the filename is transferred by the 'slow' block transfer using register two. The operation code is restored and the call is issued. If successful a single byte, the file handle, is returned, or zero for failure.

OSFILE: Read or Write a Whole File or its Attributes

This call is directed through register two by issuing a call request number of &12. This is followed by the sixteen-byte parameter block required by the call. The filing system call is then issued. The result is transferred back through register two, followed in all cases by the sixteen bytes contained in the parameter block.

OSGBPB: Multiple Byte Read or Write an Open File

This call is directed through register two by a call request of &16. The call parameters are then transferred followed by the call type. After the call the returned parameters are transferred through register two, followed always by the accumulator value, which contains the original call type.

A Short Conversation

As a brief (in real time, if not in words) illustration of how the host and parasite interact in their various activities, the following simplified scenario (missing out many of the actual steps) demonstrates how ownership of the Tube is swapped back and forth during even the simplest operations.

The user wishes to copy two files from drive A: to B: while a text file is printing in the background. The first copy command has been typed and RETURN pressed. Typing ahead of the next command continues.

DOS attempts to claim the Tube which is already in use. However, it was being used by the background 'PRINT' utility and the transfer was held up by the fact that the last character written to register one was not read by the host, which was processing and buffering a keyboard entry on an interrupt request. Since the Tube claim is successful DOS requests a filing system operation to open the input file and then must wait for a response. At this point two current 512 to host requests are outstanding and one host to parasite keypress is pending.

The host has now finished its keyboard interrupt processing and so it polls the Tube, finding a character to be transferred to the printer buffer from register one, which it proceeds to do. It next finds the outstanding register two filing-system request, the data for which it then transfers from the 512. The file is successfully opened and the file handle is returned to the 512, clearing the second request. By this time another host interrupt is outstanding (held up by the filing system NMI) and DOS is ready to request the output file to be opened. The Tube claim is successful (still owned) and the next request is issued by the 512, during which time the host scans the keyboard again and also writes another character to the printer. Immediately after its interrupt the host polls the Tube and finds the next file opening request, which it exits, again returning a file handle.

DOS now Issues a filing system request to load the 'from' file, then releases the Tube. The host passes the filing system request on, which generates a host NMI. The filing system claims the Tube (now free) and loads the file data straight to the 512 DMA routines via register three, releasing the Tube on completion. This generates an NMI in the 512, which therefore temporarily 'forgets' about printing and keyboard entries while the bulk data transfer is received. Next DOS claims the Tube (again free) and issues a request to write the data to the output file. On receipt of the reply the 512 waits for a farther signal from the host to tell it to proceed. The signal is produced when the host filing system is ready to write the data, which again generates an NMI in both the host and the 512 for the duration.

On completion of the read/write cycle (which may be repeated several times, depending on the length of the file) the Tube is released and normal interrupt activity resumes in both processors. The host will again scan the keyboard regularly and service its other normal interrupts, while the 512, under clock interrupts, will request keyboard entries and resume background printing.

During this type of operation, however lengthy printing will almost certainly visibly continue as normal because of the size of the printer's own integral buffer. After the operation is complete, the print routine and the host will easily 'catch up' and refill the printer's buffer, so the process remains 'non-stop'. However, the reason that keyboard characters may be 'lost' when typing ahead during disc activity can easily be seen. The cause is the fact that the interrupt routines of both the host and the 512 can be delayed for (relatively) quite lengthy periods during such operations. If this occurs during a host to parasite filing system transfer, one or two key depressions maybe lost by not being recorded by the host.

This point is mentioned because, as will be seen in the next chapter, the 512 requests key presses, even at its maximum rate, only half as often as the keyboard is scanned by the host, and the actual rate is frequently much less when other activity intervenes.