IOCB's - easier than
you think!
This issue, as promised, we will delve into the
working of the IOCB block. This block is controlled by certain
locations in memory and if these locations are POKEd correctly then
some great things can be achieved.
When you connect the tape or disk lead into the input/output socket
of your computer you have given yourself a choice of eight
communication channels, 0 – 7 (remember OPEN #1, etc.?). Each
channel has sixteen bytes of memory reserved for it in ROM, from
locations 832 to 959. You will be told by various handbooks that you
can use all channels for your own use except channel 0 because this
is reserved for the screen editor. This is not true, as the 'Forced
Read Mode' demonstrated in my last column showed.
Channels 1 to 5 can be used at will. Number 6 is mainly used by the
PRINT statement to input characters to GRAPHICS 1 and 2 (for
example, PRINT #6; "TEXT"), but can be used as an I/O channel in
GRAPHICS mode 0. Due to public demand, I once wrote a column of
PEEKs and POKEs in which I mentioned location 703 which would amend
GRAPHICS 0. A window would be placed in this mode, normally a full
sized screen, and PRINT #6; would have to be used if printing was
required on the screen, while PRINT would display to the window.
The last channel, channel 7, is another complicated channel. If you
use this channel as your own and try to send something to the
printer, an error will occur. LIST (to or from a device) will use
this channel, even if it is already open. When finished, LIST will
close it. LIST, LOAD, LPRINT, RUN, and SAVE all use channel 7. LOAD
and DOS commands close all channels except 0.
WHAT CAN WE DO?
Now we know about the IOCB, let us see how we can use it to our
advantage.
Firstly we must let the computer know that we require to use a
channel. This is done by
OPEN #A,B,C,D
where A = the channel number you wish to use, B = a command to be
implemented, C = an auxiliary code, normally zero, and D = filename
(e.g. D:FILESPEC.EXT or C:FILESPEC.EXT).
Although only C: and not the filename is used by the computer to
open the cassette, it is handy for future reference to use this
approach with cassette based files. Do not worry for the moment
about variable B, I will explain this in a later article.
If we go back to the last column regarding storing screens, we can
now use a channel to transfer all our stored screen data to or from
cassette or disk. Let's assume we have opened channel #1. We can PUT
a single byte that had been stored in the variable Z through to our
peripheral by PUT #1, Z or we could transfer a string by PRINT #1,
A$. The opposite of these commands are GET #1, Z and INPUT #1, A$
respectively. When we have finished transferring data the computer
will add an END-OF-FILE marker and the channel should then be closed
by using CLOSE #1.
Listing 1 is a program that will open a file named `SCREEN' on the
disk and place the contents of the screen into this file. The screen
is then cleared and all the information is taken from the file and
placed back onto the screen (note how slow it is). The program can
be easily amended for cassette users, but do not forget to reset the
tape to the start of the file.
DOING IT IN MACHINE LANGUAGE
All this can take some time if we use Basic. What we need is a handy
machine language routine to speed things up. Fortunately, within the
operating system of the ATARI there is such a routine which we can
access and let it do all the work for us. No need to panic about
Assemblers just yet! This routine is the Central Input/Output which
calls the Serial Input/Output to drive the serial bus and
peripherals. That sounds like deep computer philosophy and I am sure
that you have visions of a program with yards of illegible DATA
statements, a USR command that does work but you have no idea how,
and you may think that this is just another mystery that will be
relegated to the realms of 'Life, the Universe and Everything'.
Would I confuse you? The USR call has only half a dozen op codes and
they are explained fully in Table 1. All that we need to do is to
let the CIO know what IOCB we will want to use and the computer will
do the rest!
You will note that I am using the PUT variable statement. The reason
for this is a limitation to the PUT string statement. Although the
string can be dimensioned to the full extent of spare RAM if needs
be (leaving no workspace of course!), the INPUT statement does not
generally read strings greater than about 110 characters. This
necessitates a FOR/NEXT loop similar to GET. As CIO handles only one
byte at a time, it is easier to use PUT/GET routines for fast access
times.
ALL IS EXPLAINED!
And now, finally, the long awaited explanation of fast I/O access!
As you will notice in Listing 2, line 10120, the code is very short.
Listing 2 is the save routine and Listing 3 is the retrieval. Both
are very similar in nature and need few changes (aren't I kind?).
The graphic mode and screen colours are noted, as is the amount of
bytes to move, and the screen memory position to start from. Both of
these programs can be used as a basis for any transfer of large
amounts of data, such as fonts.
The USR call lets the program be controlled by the CIO routine at
location 58454 ($E456). You must tell the routine what IOCB block
you will be using (RD in the programs), then use the offset to set
the IOCB details. The offsets are detailed in Table 2 and the line
workings are explained in Listing 2. The listings will work just as
well with the cassette if the device designation is changed from D:
to C:.
One last point should be noted. While running the program, the
computer is always updating the screen. If the screen was turned
off, the computer would operate faster. In fact up to 30% faster in
some cases, so use this little code.
P = PEEK (559):POKE 559,0 – This will turn off the screen.
POKE 559,P – Turn on the screen.
ARE YOU STILL THERE?
During the summer months I have received very little correspondence.
Does this mean that there are no more beginners reading this column?
Or has everybody suddenly become shy? S.A.E.'s as usual to me at 1,
Hollymount, Finaghy, Belfast BT10 OGL
__________________
Table 1
ATASCII |
DECIMAL |
OP CODE |
REMARK |
h |
104 |
PLA |
CLEAR STACK |
h |
104 |
PLA |
CLEAR STACK |
h |
104 |
PLA |
GET IOCB BLOCK NUMBER |
* |
170 |
TAX |
TRANSFER TO X REGISTER |
L |
76 |
JMP |
GO TO ROUTINE AT |
V |
86 |
$56 |
LOW BYTE |
J |
228 |
$E4 |
HIGH BYTE |
The stack is like a column of pop up plates that you would find in a
self service restaurant. The last to go on top is the first to come
off. When a subroutine is called (via USR) the computer places two
bytes of information for its own use on the stack. These we do not
need and they are taken off by PLA. The third is the IOCB number
(I0) and this is transferred to the X register. The program is sent
(jumped) to an inbuilt routine in the Operating System at location
58454 (228*256 + 86). This routine will do all the work for us.
Table 2
INPUT/OUTPUT CONTROL BLOCK.
This consists of eight channels (0-7) each of 16 bytes, from
locations 832 to 959. The byte offset (that which is added to the
IOCB location) is given below.
OFFSET |
BYTES |
USE |
0 |
1 |
Index to device
name for current OPEN file. |
1 |
1 |
Device number (1
for D1, 2 for D2). |
2 |
1 |
Action to be
taken during open command, in our case 11 for PUT, 7 for
GET. |
3 |
1 |
Most recent
status. |
4,5 |
2 |
Buffer address
for data transfer or the address of the OPEN file. In our
case the Display List pointer. |
6,7 |
2 |
Address of
device's PUT one byte routine. |
8,9 |
2 |
Buffer length
for PUT/GET routines. In our case the number of PUT's and
GET's. |
10 |
1 |
Used to specify
file access. |
11 |
1 |
Used by device
driver. |
12,13 |
2 |
Disk sector
number for NOTE and POINT. |
14 |
1 |
Byte within
sector for NOTE and POINT. |
15 |
1 |
Spare. |
_________________
Listing 1
|
|
|
Listing
2
|
|
|
Explanation of Listing 2
Line 10000 opens a file called "PICSAVE" to disk.
Line 10010 places the GRAPHICS mode, held in location 87, and all
the colours from locations 704-712 into the file.
Line 10020 finds the top of RAM and the screen pointer for the
graphics mode you are using. This will change with different modes
as each mode uses a differing amount of memory.
Line 10030 sets two variables for use later on.
Line 10040 changes I0 to 16 and adds to IOCB. Channel 0 is at
location 832. Channel 1 (our opened channel) is 16 bytes further on.
Set the offset for PUT.
Line 10050 works out the high byte of the
address.
Line 10060 works out the low byte of the address.
Line 10070 Places the two bytes in the relative IOCB offsets.
Line 10080 works out the number of bytes used by the screen. This is
the same as the number of PUT's we will use.
Line 10090 places the number of PUT's in the relative IOCB offset.
Line 10100 Activates the machine code routine, held at an address
known to the computer.
Listing 3
|
|
|