|5 : 6502.SYS|
In addition to the facilities provided by the Tube host code, the 512 co-processor boot process loads additional 6502 resident routines to support the non-standard facilities of the required IBM hardware emulation. Broadly, the control offered by these routines falls into three categories:
The extra code in 6502.SYS is necessary for the 512 because, in native mode, the host MOS or filing system does not provide support for these facilities in the correct form, or at all.
In order to allow these facilities to be 'bolted-on' to the standard Tube host code and MOS facilities without disturbing the availability of existing functions, accepted 6502 coding practices are employed.
During the 512 system boot, the required code is first loaded into the 512 and then downloaded (both operations using the standard host code facilities) to reside at &2800 in the host's main RAM. The new code is then initialised, which results in the re-direction of three vectors. The user vector at &200 is re-directed to enter the program &2803, the host's main interrupt vector, IRQ1V at &204, is re-directed to point to an entry at &2834, and the event vector, at &220, is re-directed to enter the code at &2831.
It should be noted that the 6502.SYS code claims and releases the Tube and also carries out some data transfers itself by means of the standard facilities in the Tube host code, which it enters at &406, but for reasons of efficiency and execution speed some MOS calls and Tube transfers are also carried out directly from within the code.
So as to achieve the desired speed of operation for such a rapid processor as the 80186, many of the functions of 6502.SYS use techniques that are not strictly (or even vaguely) legal in other circumstances. Two obvious examples are directly poking the screen map for screen output, and bypassing the host's filing system by directly programming the FDC. For the latter operations 6502.SYS also takes control of the NMI for certain commands, thus preventing any interference by the host's normal interrupt services, or indeed from external NMI sources such as a network fileserver.
This is why some 512 operations, such as reading or writing IBM format disc data can lead to lost keystrokes if characters are typed at the same time, or screen updates may be slightly delayed, though they are rapid when they do finally resume. For the duration of these NMI operations all normal host functions are effectively 'turned off' and are only permitted to resume on completion. As a result, most of the functions in 6502.SYS are time critical and must be completed in the shortest possible time, hence the coding techniques employed.
6502.SYS is entered on one of three conditions, two of which provide a degree of autonomous (from the 512) control and monitoring capability of both hardware and software functions in the 6502 host. When such monitoring produces an FDC result, the 512 is informed by means of an IRQ. The third entry point allows the 512 to directly control 6502.SYS operations on demand.
The main 'automated' entry to 6502.SYS is via the event vector, on event type four (screen vertical synchronisation, or vsync) which occurs fifty times per second in the host when the event is enabled. Adopting this technique has significant implications for the overall efficiency and performance of the system.
First, vsync uses existing, but otherwise unused, normal host event facilities. By examining the event code entry into 6502.SYS at &2AFC, it can be seen that only an extremely small penalty is incurred by the host processor when the event type is other than four. When the event is type four, any possible screen display disruption is minimised, since much of 6502.SYS's activity is performed during frame flyback, which occupies approximately 50% of the total elapsed time.
Secondly, when 6502.SYS controlled functions are required, the 512 can send the information across the Tube very rapidly without having to wait while the function is performed, as this will be entirely automatic. After the information has been passed and buffered, the 512 can return to its own processes and leave 6502.SYS to carry out the function on its own as an independent 6502 routine.
This is best illustrated by many of the initial commands involved in floppy disc control. While the resulting transfers may incur high data rates, initial command execution (opening a file, for example) requires small amounts of data but is relatively very slow. In 80816 terms it takes a great deal of time to get the drive up to speed and to move the read/write heads into position, during which time the 80186 could process, for example, a large amount of applications code, some background printing and perhaps several complete clock interrupt cycles
Finally, because 6502.SYS contains very specific code for 512 operations, the 512 does not need to interrupt its own processing to claim the Tube to issue specific calls to monitor the progress or results of previous commands. Commands issued to the host via 6502.SYS are automatically monitored by the 6502 code itself.
For some types of command, the 512 does not wait for results to be produced by the subsequent host processes because there aren't any. For example, after transferring the bytes required to perform a particular action, the 512 may assume it will be carried out successfully. In practice, whether it is or not, for some host calls there will be no returned information, therefore 6502.SYS can be left to perform the activity alone, regardless of the outcome.
For calls in which the 512 does have a further interest, for example the result of a previously issued disc command, the 512 can still return to its own activities and continue its own processing, knowing that 6502.SYS will monitor the situation on every vsync and report only when results are finally available.
After the prime vsync operations, the 512 also has the option of performing any or all of several ad-hoc activities a number of times before releasing the Tube.
The major secondary entry point is 'on demand', via the user vector which enters 6502.SYS at &2803. This occurs on an unknown OSWORD call, which was issued originally by the 512 via the standard Tube host code. OSWORD calls which have a number greater than &E0 are not processed by the MOS and should not be used by other proprietary software. They are reserved for user code and so, when such a call is received, the MOS directs execution to the code pointed to by the user vector. If this vector has not been redirected, as in an idle host, the result is the production of the familiar Bad command error.
For the 512 OSWORD numbers between &FA and &FF are used, though within this range only three calls are functional in version 2.1 of 6502.SYS. OSWORD &FA is implemented separately, while OSWORD &FD is not implemented at all and OSWORD &FE is harmless but non-functional, simply jumping to an RTS. On entry through the user vector the accumulator value is compared to each known 6502.SYS OSWORD and the code is entered according to the action required. The unrecognised OSWORD calls used or reserved by 6502.SYS in DOS Plus version 2.1 are:
|&FF||Fast graphics update|
|&FE||Hard disk read/write (never implemented)|
|&FD||Not used – was originally for text output|
|&FC||Cursor control, soft scrolling and mouse|
|&FB||FDC track/sector seek and read/write operations|
|&FA||Not in 6502.SYS – now implemented separately in code downloaded from 512 ROM to reside at &2500 in host main memory.|
|Table 5.1 OSWORD calls used or reserved in DOS Plus, v2.1|
It should be remembered that booting DOS and 6502.SYS initialisation take place after normal host initialisation on a hard break, which means the user vector is always redirected to 6502.SYS. Those who might wish to interface alien devices by means of unknown OSWORDs should note that such extra code as is required, ideally and for reliability, should be implemented in sideways ROM using calls with a value of less than &E0. All such unknown OSWORDs are offered to the ROMs on a service call of type &08, prior to being passed to the user vector if unrecognised. Call numbers above &E0 are never passed to paged ROMs.
The only valid alternative is to modify the jump table in 6502.SYS at &2813, adding a jump to your own routines, which must in turn jump to the original address in &2813 after execution with all registers preserved. In other words the technique is directly analogous to intercepting normal host vectors. This is vital, since yours isn't the only routine relying on 6502.SYS. Even when no other third party software is involved, the OSWORD &FA code at &2500 must always be the last in the chain, as can be seen by reference to the source code in appendix F. Examination of the source listings will show that the final jump to the default handler is NOT vectored and cannot be intercepted.
Note also that if this method is chosen, none of the existing entry points or addresses in 6502.SYS may be moved. You may 'plug in' only by an extra jump at &2813, as neither 6502.SYS nor the OSWORD &FA code is relocatable. It should also be noted that very little of the host's RAM remains available when the tube is active, particularly when running a 512 – yet more reason to implement extra routines in paged ROM.
It is absolutely impossible to install an independent 6502 main RAM 'unknown OSWORD' routine. Any attempt to issue any unknown OSWORD to 6502 RAM resident routines when the 512 is active (except one of those listed, or one added by you by the above methods) would result in the equivalent of a 'bad command' error and would hang the machine, since the 512's legitimate OSWORDs would never be executed.
The final entry point to 6502.SYS is via IRQ1V, which is re-directed to enter the code at &2834. It is used for GEM mouse control only. Again, the entry uses existing host facilities and again, if the interrupt request is of no interest to the 512, the processing overhead in the 6502 host is very little.
Entry to 6502.SYS on an OSWORD &FC (issued through the Tube host) is used to directly program various hardware devices and to initialise 6502.SYS and the host after a system boot.
The routine is initially entered at the routine which programs the host's 6845 Cathode Ray Tube Controller (CRTC – the screen display controller) at &2A7F. If the byte received has the top bit set, it signifies one of the other functions or termination. Any byte with a value of &7F or less indicates the 6845 is to be programmed.
Although using native screen modes as a basis, the IBM screen formats have differences and these are programmed directly into the 6845 within this routine. Two bytes are read from register two for every CRTC register change, the first being the control register number, the second is the new value to be written to it. On receipt of a (first byte) value of &80 or greater the 6845 programming loop terminates.
After programming the CRTC, the OSWORD routine may continue or not, depending on the value of the terminating byte. If &FF was received the routine exits (eg after a PC screen mode change).
If a value of &FE is sent the mouse code is initialised, followed by the re-direction of IRQ1V and the setting of the user-port direction register to input. Following this, user-port interrupts are enabled and the peripheral control register is re-programmed to allow mouse input. The routine then jumps back to the original 6845 control entry to await further commands or to terminate (on &FF).
If a value of &FD is sent the event vector is redirected and the routine jumps back to the original 6845 control entry.
If &FC is received it is ignored and control returns to the original 6845 control entry. Any value below &FC causes an immediate exit from the OSWORD without return to the control entry. OSWORD &FC was originally used to write to the user-port, but this is no longer supported.
Screen output is carried out by entry to 6502.SYS on an OSWORD &FF. As many of the displayed characters may be IBM special characters, not supported by the host, all characters including normal text characters are sent as eight bytes of bit patterns.
(For an explanation of how an 8x8 screen character matrix is defined, examine the setting up of user-defined characters using VDU23 in native mode and screen character mapping in 80 and 40 column native screen modes.)
Users will have realised from the screen display that the normal BBC Micro character set is used for alphanumeric display, but these definitions too are stored in the 512 and transferred in the same way.
This permits character highlighting or inverse video, while still using the standard Acorn screen character matrix which, it must be acknowledged, does not permit much variation. A further benefit of this approach is that the bit manipulation is carried out by the very much faster 80186, rather than the 6502. The steps in the routine following are numbered to aid references to previous steps, which may or may not be repeated depending on how many consecutive bytes or areas of screen are to be updated.
First the memory start address for the update is sent. This is actually the low byte high byte screen RAM address which is to be updated, but always sent high byte first. If instead of a high address value (which by definition cannot be zero) the first byte is &00, the OSWORD is complete and the routine exits.
The screen address is stored at &70 and &71 in zero page, but the low byte of the base address held in &70 is always set to zero, with the real offset held in register Y. Because screen addresses always occupy a number of whole RAM pages, the base of the screen's current RAM block address is always the stored as the start address of the page. When this is combined with the index value in Y, the result addresses RAM at the correct byte.
This permits quite an elegant technique for writing a full screen or large contiguous sections of screen very quickly without the need to transfer updated addresses through the Tube. This is used to good effect in the fast output routines described below.
Next the program reads Tube register two status until a sync byte indicates that data or a command byte follows.
If the byte following the sync byte is &FF, the currently addressed output is complete and the routine jumps back to the original entry point to read new memory co-ordinates at 1. This follows at least one and possibly numerous iterations of 3 and/or 4 below.
If the next register two data byte following the sync byte is &00, an irregular character definition pattern is to be sent, and these bytes are written directly to the screen RAM as they are read from register one, in the linear routine at &2A43, labelled transfer_loop2. After the character is written, the routine jumps back to wait for another sync byte at 2, which may result in immediate output of another character in the next screen position, or the sending of new co-ordinates.
If the next byte is any other value (than &00 or &FF) then part of the screen is to be cleared by writing spaces to it. If the character is a space all eight bytes of the character's fill pattern are of course the same, and so for this operation, only a single fill byte need be read. The program reads a single space fill byte from data register one and immediately writes the byte eight times in linear code without the need to read more data. After the character is written, the routine jumps back to wait for another sync byte at 2 as detailed in 3.
This technique results in very rapid screen updates because, not only are spaces by far the quickest characters to write, they are by far the most common. In graphics modes, of course, a space character is replaced by the pattern which represents the background colour, so the method still holds.
Note that after outputting every eight byte pattern the code jumps to read the next sync byte, at 2. If a contiguous area of the screen is to be updated, since both the space fill and the irregular pattern fill routines include code to implement both the index value in register Y and, on Y overflow, the high byte of the page address held in &71, no new addresses need be read through the Tube. The next screen fill bytes can be sent and output immediately, resulting in remarkably rapid bulk screen updates – so rapid, in fact, that the host's video hardware frequently visibly cannot keep up.
This OSWORD is the only facility by which direct access may be gained to read or write data between the two processors completely independently of other functions. In addition it is the only method available for reading or writing either to shadow RAM (on a Master 128 or B+) regardless of the MOS shadow configuration, or directly accessing paged ROM or sideways RAM.
Apart from initial system load, it is not used by any standard DOS Plus facility.
Entry to 6502.SYS via an OSWORD &FB is used for floppy disc control for all 512 DOS Plus disc formats except Acorn 640k, for which the code in the ADFS is used. This is the reason that all other DOS disc handling, even of the low density IBM 320k and 360k formats is very much faster than the native BBC 640k ADFS format, which must be used to boot the system (as explained in Chapter Three).
This series of operations is the most complex in 6502.SYS and a full explanation would be extremely lengthy and somewhat pointless. Therefore the functions are described here at a high level. A detailed exposition on the programming of the floppy disc controller is not relevant in this context even for 80186 machine code programmers, unless they wish either to invent a new disc format or to hack protected IBM discs used by some software suppliers. For those with sufficient knowledge and inclination the source listing of 6502.SYS is fully commented and all memory locations used and the FDC registers are identified.
The program is always entered at OSWORD_fdc (&28E0) via the unknown OSWORD passed through the Tube host code. The various instruction codes are passed directly through Tube register two for each operation to be performed. The first requirement prior to any FDC activity is that the NMI must be claimed from the current owner. This involves issuing a (direct) OSBYTE &8F, which is passed to the paged ROMs. The current NMI owner should respond to this by saving any of its important NMI data to its private workspace and releasing the NMI. This it does by returning its identity in the Y register. The previous NMI owner's ID is then stored by 6502.SYS, for return of NMI ownership on completion of the 512's FDC operation.
On successfully checking the NMI, the next step is for 6502.SYS to claim the Tube, which might have been released since the OSWORD was first issued. Next, four bytes are passed which are stored in the host's RAM and will be used to program the DMA transfer to or from the 512's RAM.
Following this, the identity of the host (recorded during system boot) is passed to 6502.SYS from the 512 and 32 bytes of the NMI data image, stored within the 6502.SYS code area, are copied down to page &D, the host's NMI work area. Next the appropriate host type's addresses are set up for the three memory mapped FDC control registers in SHEILA.
These locations differ between Master 128 hosts and Model B/B+ machines. The byte passed to these routines identifies the host as a Master (1) or as a B, B+ (2) so that the correct SHEILA indirection addresses are stored in &A0 and &A1 in zero page.
Having claimed the Tube, claimed the NMI and set up the FDC base for the particular host type, the FDC command can be executed. This requires parameters to be passed through register two for the intended operation. As various different formats of disc are processed by this code, the parameters must completely describe the operation to be performed in every detail (eg drive ID, start track, start sector, sector size, number of sectors, read or write, time allowed, etc). The command is executed and 6502.SYS enters a loop, monitoring the FDC status until an error, a timeout or a successful completion. Whatever the termination type, an FDC event is returned to the 512 together with the FDC status, possibly though not necessarily, within this call – see event functions overleaf.
If the operation is a read or write, data is transferred, a sector at a time, by means of DMA interrupts generated in the 512. Even when the read/write activity is continuous, the DMA routines in the 512 and the Tube transfer speed are more than fast enough to keep pace with disc transfer rates. On completion of all reads/writes and transfers, the Tube is released and the NMI is released back to its original owner.
In practice, particularly for the slower disc formats, the 512 may issue the commands for a single logical disc operation as several separate OSWORD &FBs, causing 6502.SYS to release and reclaim the Tube several times. For example, the simple operation of writing a single file could well translate to mean separate calls to:
Some of these are slow operations and none except the data transfer (5) will require the 512's permanent attention. In these cases the 512 can continue to process its own code and 6502.SYS will monitor FDC status in the event four entry, described below, until the 512 is again required to intervene.
The hard disc OSWORD &FE, is included for documentary purposes only. A 512 DOS Plus hard disc partition is allocated as a single large file on an ADFS disc and standard ADFS 'get byte' and 'put byte' routines are used. This is done for two reasons, the prime one being that the hard disc interface used in the DISC Micro host (SCSI with Acorn adaptor) is not standard for DOS systems and requires customised code to drive it. Duplication of this code is unnecessary, since it already exists in the ADFS.
Using the ADFS ROM code (via FS commands issued through the Tube host code) has two benefits. First it permits ADFS to maintain its view of the DOS partition as a normal file and therefore a mixed native ADFS/DOS Plus disc is possible. Secondly, from DOS's point of view (through the XIOS, which does the logical to physical translation work) the hard disc appears merely as a normal but large DOS drive, no different to any other.
6502.SYS is entered on vsync (nominally) fifty times per second, at &2AFC, labelled 'eventcode'. Events other than four are ignored. This entry point is used for monitoring progress of any oustanding FDC functions, monitoring and reading the keyboard, keyboard LED control, screen re-mapping and reading the userport.
The first operation checks the FDC status to see if an FDC command (which was previously left to its own devices for the duration) has now completed. If so, the code diverts to signal an FDC event to the 512 by generating a host event ten, which is passed through Tube register one by the MOS, followed by the contents of 6502 registers A, X and Y to generate an IRQ in the co-processor. The 512 will then issue the appropriate OSWORD to execute the next step in the FDC command, or take suitable action if an error has occurred.
If no FDC event is outstanding, the states of the SHIFT and CONTROL keys are tested. First a call to the MOS's keyboard vector is made. On return the two 6502 processor status flags N and V indicate the state of the SHIFT and CONTROL keys. If N, the negative flag (bit 7) is set the CONTROL key was pressed at the time. If V, the overflow flag (bit 6) is set the SHIFT key was pressed at the time.
The MOS's two key rollover locations, &EC and &ED, contain respectively the current key pressed and the last key pressed if two keys were depressed at the same time. The current keypress is transferred to register X with the top bit set on if CONTROL was pressed, off otherwise. The last keypress (if any, zero otherwise) is transferred to register Y, and the top bit is set on if SHIFT was pressed, off otherwise. As can be seen from this arrangement, it is impossible for DOS software to recognise more than two simultaneous ASCII key depressions, with optionally SHIFT and CONTROL, hence any PC software requiring three simultaneous ASCII key presses cannot possibly be made to work in the 512.
Immediately after the keyboard scan, the event type (four) is reloaded into the accumulator and the event is passed on to the normal host routine by means of a subroutine call. All host events are passed to the co-processor by the MOS via a Tube register one parasite IRQ, along with the 6502's three processor registers, and this is the method used to pass host keypresses to the 512. However, as the host event routine was called by a JSR control returns to 6502.SYS and further operations may then follow as described below.
When the call returns, the 512 will have placed a command byte in register four as a result of the register one event IRQ. This point is labelled async_command in the source code, since any number of ad-hoc commands can be sent to 6502.SYS via this re-entry without recourse to further unknown OSWORD calls through the Tube host code, thus avoiding their attendant processing overheads and delays. Four possible command bytes are passed.
A value of zero indicates no further action. Exit 6502.SYS.
A value of one 'drops through' to the 6845 CRTC control routine, which executes as previously described under OSWORD &FC. This command is used for colour or PC screen mode changes.
A value of two is an instruction to read the user port data. This routine allows for a trackball or an AMX type mouse, with due allowance for the hardware differences. The user port (&FE60) is read directly for any button presses and these are transferred through Tube register one, causing an IRQ. The four RAM locations holding the two 'low byte-high byte' screen RAM Y-X co-ordinates of the mouse pointer are then read and are also transferred through Tube register one. The reading of the user port for mouse movement, and the translation and storing of those movements in RAM, is carried out in the host IRQ1V intercept routine controlled by the host's interrupt timers (see below).
A value of three causes Tube register four to be read for the X parameter required for an OSBYTE &CA (*FX 202) which writes the keyboard status byte to agree with the 512's current recorded SHIFT/CONTROL settings. Following this, an OSBYTE &76 (*FX 118) is issued to set the keyboard SHIFT and CONTROL LEDS appropriately to reflect the actual situation.
Each of these operations terminates by returning to the entry point at async_command to read further possible commands, or until a zero is received to terminate asynchronous operations.
The redirected IRQ1V enters 6502.SYS at &2B8C and the interrupt flag register is loaded from SHEILA. The value read is masked to test for user port input. If there is no user port activity, the routine jumps to the original vector address for the host to service its own IRQ facilities.
The remainder of 6502.SYS, between &2B8C and &2C2F, is concerned with reading the user port hardware data lines to determine the direction and magnitude of the mouse or trackball movement.
This involves examining each of the four possible hardware direction signals for activity and translating them into screen mapped Y-X movements, allowing for pointer movement off the edge of the current screen limits. The resulting movement is finally stored in Y-X co-ordinate low-byte-high-byte form in four RAM locations, which are subsequently read by a call to async_command during a vsync event (see above).