< Previous | Contents | Next >
6: DOS Plus MOS calls | ||
Having seen how the standard Tube host code and the extra facilities provided by 6502.SYS are implemented on the host's side of the Tube, this chapter details the MOS and filing system calls which can be made from within 512 code.
In 512 user programs, any language which includes the ability to load nominated 80186 registers with specified values, directly as in machine code or indirectly as in, for example, BASIC's CALL or USR functions, can access the host's MOS or filing system via these calls. The various facilities of 6502.SYS can likewise be accessed by means of issuing the appropriate unknown OSWORD call.
Note, though, that in general applications programming it is neither necessary nor desirable to directly program the host's hardware device controllers or internal software flags – the FDC, perhaps, being the most obvious example. Most languages have specific filing system support commands for loading or saving data and these should be used whenever possible. Screen mapping too should remain transparent in DOS applications code.
If standard DOS Plus or CP/M facilities are used, not only will the resulting programs be easier to write and understand, they will also be more easily maintained or transferred to a different machine or a different language should the need arise. 512 users, perhaps more than others, should appreciate the penalties of dubious programming techniques or 'illegal' direct hardware device control. Programs which use MOS Tube calls will no more work on a PC than PC programs that used direct PC hardware access do on the 512.
The following information is intended to allow programs to be written for the 512 which must, for particular reasons, gain direct access to the MOS or filing system calls of the host. Readers should note that, as we are now referring to 80186 registers and DOS functions, 86 series conventions apply and hexadecimal values are written according to the normal 86 standards. For example, a value of 127, which in native BBC mode would be written as &7F, is shown here as 7Fh.
All Operating System functions required by code running in the 512 under DOS Plus are made by calling a DOS interrupt. In fact, unless illegal coding techniques are employed, all program communication with all other software and the machine's hardware should be achieved through these calls. The bottom 1024 bytes of DOS memory is reserved for the interrupt vector table, each entry of which points to the DOS routines designed to handle the particular type of call. Each interrupt vector entry is a four-byte segment:offset address, therefore the full range of interrupts number 256 (1024/4).
The MOS Operating System calls of the Tube host code detailed in Chapter Four, and the unknown OSWORD giving access to 6502.SYS explained in Chapter Five, can be called from the 512 by means of several (otherwise unused) DOS interrupt numbers appropriated for the purpose. Of the possible total of 256 hardware and software interrupts, the majority are unused in all DOS versions to date. Although more will inevitably be used by succeeding versions of MS-DOS or PC-DOS and later hardware, even as far as MS-DOS version 3.3 only (some of) the interrupt numbers up to 2Fh, plus 33h, 44h and 67h had been allocated.
In the version of DOS Plus supplied for the 512, interrupt numbers between 040h and 04Ch are used for the eleven different MOS call types supported by the 6502's Tube host code, plus two MOS calls which are simulated. Some MOS calls, for example OSBYTE, normally require parameters to be placed in the 6502's registers. When called from DOS the values are placed in the 80186's AL, BH and BL registers. When the call is passed to the host for service through the Tube protocol, these values will be transferred to the 6502's A, X and Y registers respectively.
The following is an outline of the supported call types, but users wishing to employ them should refer to suitable MOS reference texts for the precise details of parameters and how the calls are implemented in the host.
The 13 MOS calls supported by the Tube host code are listed in Table 6.1 below in order of ascending interrupt call numbers. Interrupts 47h and 48h are included in the table only for completeness, though these are not supported by the Tube host code, as can be seen from Chapter Three and the host code source listing.
Interrupts 47h and 48h are actually simulations provided in the XIOS to avoid the need for two more explicit calls in the Tube host code or 6502.SYS. A call to INT 47h, OSASCI, results in the current output character value being tested. If the character is Dh, (CHRS13) then INT 48h is called, if not then it is output directly through a call to INT 49h. A call to INT 48h, OSNEWL, simply loads Character Dh and calls INT 49h, then loads Ah and calls INT 49h.
Routine |
INT |
Function |
|||
OSFIND | 40h | Open or close a file for byte access | |||
OSGBPB | 41h | Multiple byte read or write an open file | |||
OSBPUT | 42h | Put (write) a byte to an open file | |||
OSBGET | 43h | Get (read) a byte from an open file | |||
OSARGS | 44h | Read/write file attributes or read filing system type | |||
OSFILE | 45h | Read or write a whole file or its attributes | |||
OSRDCH | 46h | Host operating system read character | |||
OSASCI | 47h | Simulated, if Dh also send Ah through INT 49h | |||
OSNEWL | 48h | Simulated, output Ah and Dh through INT 49h | |||
OSWRCH | 49h | Host operating system write character | |||
OSWORD | 4Ah | Host operating system word general function call | |||
OSBYTE | 4Bh | Host operating system byte general function call | |||
OSCLI | 4Ch | Host operating system command line interpreter | |||
Table 6.1 MOS calls supported by the Tube |
The only 'standard' additions to this list are the functions provided by 6502.SYS, explained in the preceding chapter, or routines you may implement yourself by patching an additional 6502 routine into the jump table in 6502.SYS. Such a routine must, of course, be loaded after booting the system.
It should be understood that the following calls, when referencing a disc filing system operation, relate only to ADFS format (that is, bootable DOS 640K or true ADFS) or DFS format discs, not to any of the IBM DOS formats controlled through 6502.SYS. It should also be appreciated that, unless you are accessing a true MOS format disc for a special purpose, many of the host's filing system options are meaningless in DOS.
The same is true for the more general MOS calls which must be used with care. As a dramatic and salutary demonstration, you can prove this very simply by trying this example. While *FX13,4 in native mode produces no visible effects, (the MOS does not normally use this event itself) the same command issued as STAR FX13,4 from DOS will instantly and permanently paralyse the system by disabling all 6502.SYS operations.
As can be seen in the preceding chapter, event four is critical to the functioning of 6502.SYS, particularly for keyboard input. While both the MOS and DOS actually continue to function after this 'FX', you will have irreversibly severed their (and your) only means of communication through the Tube. It is not, in fact, just the keyboard you have disabled, all inter-processor communication is triggered by event four, which causes 50 IRQs per second in the 512 and which you have now permanently (until re-booting) disabled.
Function: | Open or close a file for byte access |
|||||||||||||
On entry: | AL specifies the operation DS contains the segment pointer to the filename BX contain the offset pointer to the filename |
|||||||||||||
Operations: |
The filename must be terminated by Dh (CHR$13). |
|||||||||||||
On exit: | AL contains the returned file handle, or 0 if file has been closed or could not be opened. |
|||||||||||||
80186 flags: | Undefined |
Function: | Read/write a block of bytes from / to a specified open file. |
|||||||||||||||||||||||||
On entry: | AL specifies the operation type
|
|||||||||||||||||||||||||
Operations: |
|
|||||||||||||||||||||||||
On exit: |
|
|||||||||||||||||||||||||
80186 flags: |
|
Function: | Write a single byte to an open file using the file's sequential pointer |
|
On entry: | AL contains the byte to be written BH contains the file handle (provided by OSFIND) |
|
On exit: | Nothing returned |
|
80186 flags: | Undefined |
Function: | Read a single byte from an open file using the file's sequential pointer. |
|
On entry: | BH contains the file handle (provided by OSFIND) |
|
On exit: | AL contains the byte read from the file |
|
80186 flags: | CF is set if an attempt is made to read past the end of the file. Others are undefined. |
Function: | Read/write an open file's arguments or read the current filing system type |
|||||||||||||||||||||||||||||||||||||
On entry: | AL = operation type AH = file handle (provided by OSFIND) or 0. BX points to a 4-byte attribute block, which must have been previously set up in the host's RAM |
|||||||||||||||||||||||||||||||||||||
Operations: | If AH = 0 and
If AH is greater than 0 and
|
|||||||||||||||||||||||||||||||||||||
On exit: | If entered with AH=0 and AL=0 AL contains the filing system number as follows:
If entered with AH = 0 and AL = 1, then the address of the remainder of the last command line is returned in a four byte zero page control block pointed to by BX. This address is always in the I/O processor and its data should be read using OSWORD 5. The remainder of the last command line is always terminated by 13h (CHR$13). For all other calls no data is returned unless an error is reported via a normal register four IRQ. |
<This does not work properly on the Master 512. See here – YP> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Function: | Read/write a complete file or catalogue information |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
On entry: | AL contains the operation type DS:BX point to the file's control block |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Operations: |
The file control block is in the form:
File attributes are stored in 4 bytes. The most significant 3 bytes are filing system specific. The least significant byte indicates the following when a bit is set on:
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ADFS Note: | The three most significant bytes are undefined, ie not used. In the least significant byte, bit 2 is not used and bits 4-7 are always the same as bits 0-3.
In write attribute operations all bits except zero, one and three are therefore ignored.
If the object is a directory, bits zero and one are also ignored.
The other bytes and bits are used by other filing systems, eg network. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
On exit: | AL contains the result code as follows:
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
80186 flags: | Undefined |
Function: | Read a character from currently selected input stream |
|||||||
On entry: | No parameters |
|||||||
On exit: | AL contains the character or an error code |
|||||||
80186 flags: |
|
Function: | Write character to the currently selected output stream but also output character Ah if current character is Dh |
|
On entry: | AL contains the character to be written |
|
Operations: | IF AL = Dh (CHR$13) THEN call INT 48h ELSE call INT 49h |
|
On exit: | No returned information |
|
80186 flags: | Undefined |
Function: | Write carriage return / linefeed to current output stream |
|
On entry: | No parameters |
|
Operations: | Loads AL with Dh (CHR$13) and calls INT 49h then loads AL with Ah (CHR$10) and calls INT 49h |
|
On exit: | No returned information |
|
80186 flags: | Undefined |
Function: | Write a character to the currently selected output stream |
|
On entry: | AL contains the character to be written |
|
On exit: | No returned information |
|
80186 flags: | Undefined |
Function: | Various functions, with parameters in a memory control block. (See also OSWORD FAh at the end of the chapter). |
|
On entry: | AL contains the OSWORD function. DS:BX points to a control block, the size and organisation of which is call dependent. See 6502 MOS reference texts for full call specifications. |
|
On exit: | Parameters returned are call dependent and if any, are placed in the control block |
|
80186 flags: | Undefined |
Function: | Various MOS byte operations |
||||||||||
On entry: |
|
||||||||||
On exit: | BL contains the returned 6502 X register value BH contains any returned 6502 Y register value (see note) |
||||||||||
Note: | For OSBYTE calls that do not require a Y parameter, the Tube host code implements a short OSBYTE routine which neither expects nor transfers the value in BH, which therefore may be safely ignored. However, for all OSBYTE calls, if the value in BH is important it should be preserved by the caller. When a short OSBYTE call is used, the Tube host code does not actually return this value and BH is therefore undefined. For other OSBYTE calls the Y register value is returned, but is not meaningful. |
||||||||||
80186 flags: | CF value is call dependent but unless significant to the 6502, returned values should be regarded as undefined. |
Function: | Sends a string to the host's MOS Command Line Interpreter. (* command) |
|
On entry: | DS:BX point to the command string |
|
On exit: | No returned values |
|
80186 flags: | Undefined |
|
Notes: | The command string passed does not need a preceeding '*' and may be up to a maximum of 256 characters long. The string should be terminated by Dh (CHR$13). Eg, setting DS:BX to point to the string cat<CR> would produce a catalogue of the currently selected filing system directory of the chosen drive. Any variable parameters you wish to pass must be entirely included within the command string length. Unrecognised commands will produce an error which will be reported via the Tube register four error IRQ, ultimately causing a DOS error unless this is trapped by your own code. |
As a simple example of how the MOS interrupts are called, the following extract of 80186 assembler code shows how OSCLI (interrupt 4Ch) would be called with a fixed string which is the equivalent to '*HELP ADFS' issued in native mode.
; some fixed constant declarations
oscli equ 04Ch ; OSCLI interrupt
cr equ 0Dh ; Carriage return
; the code that does the call
mov ds, cs ; just in case it wasn't
xor al, al ; clear AL to be neat
mov bx, offset string_1 ; point BX to the string
int oscli ; call INT 04Ch
string_1:
ds "help adfs"
db cr
The OSWORD &FA which was removed from 6502.SYS is still available, but has been moved from the host code to the 80186 monitor, which already provides a similar facility for manual entry in TFER. It permits transfers to or from the 512.
The OSWORD interrupt code tests for a value of AL = 0FAh and diverts the call if it matches. This OSWORD call requires a control block to be set up in the 512, the location of which is pointed to by DS.BX. The format of the control block is:
0 | Number of parameters sent to I/O processor (0Dh or 0Eh) | |
1 | Number or parameters read from I/O processor (01h) | |
2 | LSB of I/O processor address | |
3 | ... | |
4 | ... | |
5 | MSB of I/O processor address | |
6 | LSB of 512 offset address | |
7 | MSB of 512 offset address | |
8 | LSB of 512 segment address | |
9 | MSB of 512 segment address | |
A | LSB of length of transfer | |
B | MSB of length of transfer | |
C | Operation type (See below) | |
D | 6502 memory access control |
The operation type specifies the type of transfer as follows:
0 | Write to 6502 at 24 µs/byte | |
1 | Read from 6502 at 24 µs/byte | |
2 | Write to 6502 at 26 µs/pair of bytes | |
3 | Read from 6502 at 26 µs/pair of bytes | |
6 | Write to 6502 at 10 µs/byte using 256 byte blocks | |
7 | Read from 6502 at 10 µs/byte using 256 byte blocks |
The memory access control byte allows access to the paged RAMs, paged RAM and shadow RAM in the host machine and is laid out as follows:
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||||||||
- | sm | m/s | c | pr3 | pr2 | pr1 | pr0 |
where the bits have the following functions.
Bit 7 | Unused |
|||||||
sm | IF (I/O address between 3000h and 8000h) AND (sm=SET)
THEN use screen memory regardless of state of *SHADOW – overrides bit 5 |
|||||||
m/s |
|
|||||||
c | IF (I/O address between 3000h and 8000h) AND (c=SET) THEN use currently selected ROM |
|||||||
pr3‑pr0 | Paged ROM number (binary value 0 to Fh) |
The memory access byte is only used if the first byte of the control block is set to 0Eh, otherwise it is ignored. Use of the memory access byte allows paged ROM software to be copied and therefore should be restricted to system use. This would prevent access to the shadow RAM, which is not used by the system and could not be legally accessed by other means.
A small example of the call is now given. This assumes that the control block has been set up correctly and is located in the first 64k segment. A contiguous 36 kbyte area of memory is used as a buffer for data written from 2000:1000 in the 512. The host buffer starts at 3000h and extends to BFFFh. 3000h to 7FFFh is specified as shadow screen memory and 8000h to BFFFh is specified as paged RAM in bank 5.
osword equ 04Ah
transfer equ 0FAh
sub ax,ax ; make ax zero
mov ds,ax ; point DS at segment 0
mov bx,offset_transfer_block
mov al,transfer ; set up OSWORD type
int osword ; call interrupt 4Ah
transfer_block:
db 0Eh ; number of parameters sent
db 01h ; number of parameters read
dw 3000h,0 ; base address in 6502
dw l000h,2000h ; base address in 512
dw 9000h ; length = 36K
db 6 ; fast 256 byte type 6 transfer
db 025h ; use shadow and paged RAM
< Previous | Contents | Next >