Z-System Corne� (c)
by Jay Sage
The Computer Journal, Issue 39
Reproduced with permission
of author and publisher
For this issue I will discuss some unique new capabilities made possible�
by NZCOM that have already proved their value and that I hope will be�
exploited to a much greater extent in the future. I originally had several�
other issues on my agenda, but Lee A. Hart sent me such an interesting�
article that I wanted to leave plenty of room for it.
System Enhancements Using NZCOM
I'm afraid that many people think of NZCOM as just a way for unskilled�
users to get Z-System running on their computers. It's true that NZCOM�
accomplishes that, but, as I have asserted often before, NZCOM does much�
more than that. It offers possibilities that a manually installed Z-System�
cannot achieve. I would like to describe one of them here and will do so�
first in the context of a problem that arose with the new ZSDOS and ZDDOS�
disk operating systems on some computers.
Because CP/M was created originally for the 8080 microprocessor, a number�
of BIOS implementors (the BIOS, or Basic Input/Output System, is the�
hardware-dependent part of CP/M) felt that they could make free use of the�
additional registers introduced with the Z80 chip. These registers included�
two index registers, called IX and IY, and a duplicate set of the standard�
registers denoted with primes on the names (e.g., B' or HL').
This was perhaps excusable at the time, but it is poor programming�
practice for an operating system to change anything other than what is�
explicitly indicated in the specifications. Most BIOS writers who have used�
the Zilog registers have been careful to restore the original values before�
exit from the BIOS routines. Unfortunately, a few BIOSes fail to do that. �
Among them are the following: Epson QX10, Zorba, Televideo 803 and TPC-1,�
Oneac On, and the Osborne Executive. The Bondwell is on the suspect list,�
and there are probably others we don't know about yet.
The (mis)use of these registers poses no problem for programs written to�
run on the 8080, but today we are rapidly moving beyond the limitations of�
the 8080 and making extensive use of the Z80 registers to pack more power�
into operating system components and application programs. Today, the Z�
System, true to its name, is intended to run only on the Z80 or upwardly�
compatible processors like the HD64180, Z180, or Z280.
Several users who purchased ZDOS (that is ZSDOS and ZDDOS) found that it�
would not work properly on their computers. An investigation turned up the�
fact that the BIOSes in those computers were modifying the index registers. �
This also explained why those same users had been experiencing strange�
problems with JetLDR, Bridger Mitchell's superb Z-System module loader. It��also explained some mysterious problems I was having with a number of�
programs (for example, EDITNDR) on my Televideo 803! The question was what�
to do about the problem.
In the ancient days, when computers always came with the source to their�
BIOS and their owners were always intimately familiar with the procedures�
for rebuilding their operating systems, the solution would have been to�
rewrite the BIOS with the proper PUSH IX and POP IX instructions to preserve�
the index register values. But what could we do today for nonprogrammers�
and those without BIOS source code? NZCOM provided the answer quite nicely!
As I explained in a column long ago, NZCOM works by creating what I call�
a virtual BIOS (I'll call it VBIOS) lower in memory in order to open up�
space for the Z-System modules between it and the real BIOS (often called�
the custom BIOS or CBIOS). The source for this virtual BIOS is available. �
Except for the warmboot code and some minor complications for IOP�
(input/output processor) support, the standard NZCOM VBIOS module just�
vectors calls that come to it up to the real BIOS.
But no one says this is all it is allowed to do. ZDOS authors Cam�
Cotrill and Hal Bower found it quite easy to surround the vectors with code�
to save and restore registers. First they released ZSNZBI11.LBR, which�
contained the source and ZRL file (loadable by NZCOM) for a VBIOS that�
preserved the IX and IY registers for all disk function calls. Later they�
discovered that some of the machines changed the index registers even for�
console I/O function calls, and others changed the alternate registers. �
They then wrote ZSNZBI12.LBR, whose VBIOS preserves all the registers for�
all BIOS functions.
Instead of having the virtual BIOS routines jump directly to the real�
BIOS, they jump to an intermediate entry point. For example, the list�
status vector in the jump table has a JP ILSTST (intermediate list status),�
and the code at ILSTST is
ILSTST: LD A,45
JR DOBIOS
The offset for the BIOS function is placed in the A register and then�
control is transferred to a general BIOS-calling routine shown in Table 1�
that implements the register protection. The routine JPHL referenced there�
contains only the code line JP (HL), which vectors the CPU off to the BIOS�
with a return to the DOBIOS code.
DOBIOS: LD HL,CBIOS ; Start with address of real BIOS
ADD A,L ; Add offset in A (never a
LD L,A ; ..carry since on page boundary)
EXX ; Swap to alternate registers
LD (HLP),HL ; Save them all in memory
LD (DEP),DE
LD (BCP),BC
� LD (IXREG),IX ; Save index registers, too
LD (IYREG),IY
EXX ; Back to regular registers
EX AF,AF' ; Swap to alternate PSW
PUSH AF ; Save it on stack
EX AF,AF' ; Back to original PSW
CALL JPHL ; Actually call the BIOS!
EXX ; Restore alternate and index
LD HL,(HLP) ; ..registers
LD DE,(DEP)
LD BC,(BCP)
LD IX,(IXREG)
EX AF,AF' ; Alternate PSW, too
POP AF
EX AF,AF'
RET
To use this replacement VBIOS, you have to run MKZCM and create an NZCOM�
system with 4 records allocated for the BIOS instead of the standard 2. �
Because the BIOS must start on a page rather than just a record boundary,�
MKZCM will sometimes make automatic adjustments to the BIOS size. �
Therefore, you should specify changes in MKZCM starting with the higher�
numbered modules; the adjustment in the BIOS allocation should be made last. �
If an attempt to enter a value of 4 results in MKZCM using 5, then you could�
go back (if you don't like wasting memory) and make one of the other modules�
(such as the NDR) one record larger and then respecify a 4-record BIOS.
There are many other ways that NZCOM can be used to introduce system�
enhancements without having to make changes in the real BIOS. As an�
example, we will show how to add support for the drive vector in environment�
descriptors of type 80H and above (implemented with NZCOM and Z3PLUS). The�
drive vector is a 16-bit value stored as a word beginning at offset 34H in�
the environment descriptor. It specifies which disk drives are actually�
implemented on a system. The lowest order bit in the word is for drive A�
and the highest for drive P. A zero in a bit position indicates that the�
corresponding drive is not available. For example, on my SB180 the bytes at�
addresses ENV+34H and ENV+35H were 7FH and 00H, respectively. Thus the word��value is 007FH or 0000,0000,0111,1111 binary, indicating that I had drives�
A, B, C, D, E, F, and G. When the hard disk E partition developed a problem�
that made it unusable, I changed the 7FH value to 6FH, thereby disabling�
drive E. You can display the drive vector using menu selection 3 in the�
SHOW program (ZSHOW for Z3PLUS).
The ZCPR34 command processor knows about the drive vector and will not�
allow command references to unsupported drives. But what about programs�
that you run? Unfortunately, the BIOS generally knows only which drives are�
potentially implemented, and it may try to access a nonexistent drive. When�
'smart' BIOSes encounter this problem, they often prompt the user as to what�
to do next. This is fine if you are sitting at the console and can take�
appropriate action to recover, but if the system is being run remotely,�
there is generally no way for the remote user to recover. In fact, because�
the 'smart' BIOS uses direct hardware calls to display the "Abort, Retry,�
Ignore?" message rather than calls through the BIOS vector table, the remote�
user does not even see the message and just thinks the system has crashed. �
My Z-Node got hung once that way when I forgot to put a diskette back into a�
floppy drive. A caller attempted to access it, and when I got home, the�
BIOS was dutifully beeping at me and waiting for me to tell it what to do.
My first stab at writing a VBIOS that observes the drive vector�
restrictions is shown in Table 2. Now that I have read Lee Hart's column, I�
am sure that this code can be made shorter, faster, or both! But I will�
leave that as an exercise for the reader. (I already see one place where I�
could save a byte.)
The listing assumes you are starting with the ZSNZBIO described earlier. �
Just add the extra equate for DRVEC under the /_ENV_/ common block and�
replace the simple ISELDK (intermediate select disk) code with the slightly�
more complex version shown in the Table. I put this on my Televideo, and�
the results were most pleasant. Now when I attempt to access a nonexistent�
drive, the system does not force a direct-CBIOS warmboot that drops me out�
of NZCOM.
COMMON /_ENV_/
Z3ENV:
DRVEC EQU Z3ENV+34H ; Drive vector
CCP EQU Z3ENV+3FH
DOS EQU Z3ENV+42H
; Modify ISELDK as follows and place it after the DOBIOS code and before
; the data area for register storage.
ISELDK: LD HL,(DRVEC) ; Get drive vector
LD A,16 ; Subtract requested drive
SUB C ; .. from 16
� LD B,A ; .. and put into B
ISELDK1:
ADD HL,HL ; Move bits left into carry
DJNZ ISELDK1 ; Loop 16-<drive> times
LD HL,0 ; BIOS return code for invalid drive
RET NC ; Return if drive vector bit not set
LD A,27 ; Otherwise, use CBIOS function
JR DOBIOS ; .. at offset 27
Table 2. Code added to virtual BIOS to support the environment drive vector�
at the BIOS level.
These two examples of system enhancements by no means exhaust the�
possibilities. One can implement all kinds of additional features and�
drivers right in the NZCOM VBIOS. Joe Wright suggested early during NZCOM�
development that one should create an absolutely stripped down CBIOS, one�
that contains only the functions that are absolutely necessary to get the�
system running and then implement all the bells and whistles in the VBIOS. �
These extra features would include things like RAM-disk drivers, keyboard�
type-ahead buffers, logical drive swapping facilities, and disk error�
recovery management routines. With this strategy, one can actually achieve�
a larger TPA with an NZCOM system than one had under the standard CP/M�
system, since the CBIOS can be made smaller and the fancy features dropped�
when a larger TPA is more important.
For example, the "Abort, Retry, Ignore" message should be implemented in�
the VBIOS, with the CBIOS returning from disk errors with standard error�
codes. With the normal VBIOS, the error will simply be passed back to the�
DOS, which will report the error in its usual way ("BDOS ERROR on..." in the�
case of the Digital Research BDOS). A more elaborate VBIOS can detect the�
error, report it to the user, and allow the operation to be retried. When�
the system is running in remote mode, either the simpler VBIOS can be used�
or the prompt can be vectored properly through the jump table so that the�
remote user will be able to deal with the problem.
Similarly, one should be able to handle the swapping of logical drive�
names in the VBIOS. There are a couple of pitfalls to watch out for,�
however. If you change logical names, you better make sure that the disk�
system is reset, probably both before and after the swap. You also better�
make sure that NZCOM can still find its CCP file, which is normally kept in�
directory A15:. If you swap the A drive without providing a copy of this�
CCP in the new A drive, you'll be in serious trouble. Of course, the�
swapping would be handled by a utility program, and it would worry about�
these requirements. The VBIOS would simply have the code for translating�
references to a logical drive value in register C into a possibly different�
physical drive value.
I hope that this short discussion has given some of you ideas for�
imaginative applications of the new capability offered by the NZCOM virtual�
BIOS. If so, I would love to hear about them and to see sample code.
�
[This article was originally published in issue 39 of The Computer Journal,
P.O. Box 12, South Plainfield, NJ 07080-0012 and is reproduced with the
permission of the author and the publisher. Further reproduction for non-
commercial purposes is authorized. This copyright notice must be retained.
(c) Copyright 1989, 1991 Socrates Press and respective authors]