![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Technical Reference ManualEXTERNAL INTERFACING
GENERALThe Organiser II has been designed to be extended in a number of ways
In both cases an extension to the operating system is known as a "DEVICE". As far as the operating system is concerned a "DEVICE" can be just an extra software service, or both an extra software service and an hardware interface. In general if an extra device is added, it will probably be designed to interface to the top slot. However there is no reason why it need not be designed to run in one of the side slots. In fact it is perfectly possible to design an adapter board which will allow an interfaces to run in one of the side slots. SOFTWARE INTERFACINGBuilt into the operating system is a service DV$BOOT which will load devices into the operating system. This service will scan each slot in the machine for a normal PACK of any kind which has the NOBOOT bit clear in the first byte on the PACK. Packs with this bit clear are called "BOOTABLE" packs. Bootable packs have a special header which contains the information the DV$BOOT service requires to load the device into RAM. Hardware interfaces like the RS232 adapter have an 8K PACK built into them as well as the interface hardware. Together they form the device. BOOTABLE PACK DESCRIPTIONA pack which is BOOTABLE must have the following header information in the first six bytes of the pack: ADDRESS
PACK_CONTROL_BYTEThis byte is used by the PACK handling services to hold various bits of information about the PACK. Each bit in the byte has a particular function as follows:
Hence BIT 4 of the PACK_CONTROL_BYTE must be cleared to indicate that the PACK contains a device to be loaded into the machine. Some examples of valid PACK_CONTROL_BYTEs are as follows:
PACK_SIZE_BYTEThis byte contains the number of 8K blocks in the PACK. DEVICE_OR_CODE_BYTEThis byte is used for descriptive purposes only. It should be set to 0 the device is a software application with no additional hardware, otherwise it should be set to 1. DEVICE_NUMBER_BYTEThis byte contains the device number of the code extension or hardware device. As more than one device can be "BOOTED" into the operating system, it is necessary to have a mechanism to identify each of the devices currently booted. This is accomplished by having a unique device number for each device. The device number is a value in the range $01 to $FF. However a number of these are reserved by Psion and should not be used. The reserved numbers are in the range $80 to $C0 and $01 to $40. In 1986 (when the technical manual was published) Psion already supplied a number of devices whose device numbers are as follows:
By convention devices which do not have an hardware interface are allocated device numbers in the range $01 to $40 and devices with a hardware interface are allocated device numbers in the range $80 to $C0. DEVICE_VERSION_BYTEThis byte contains the release version number of the device. This byte is not used by the operating system and is only for documentary purposes. By convention version numbers are N.M and the byte is formed by the following:
Thus for a version number of 2.3 the byte will have the value 35 ($23). DEVICE_PRIORITY_BYTEThis byte determines the order in which devices are booted into memory. The priority byte may have any value in the range $1 to $FF. The higher the value the higher the priority of the device. Thus a device with priority $FF will be booted before a device with priority $FE. The DV$BOOT service scans all the slots and builds a table of priorities from all the bootable packs. The priorities are then sorted and each device is loaded in turn. In the event of a tie in priorities the devices will be loaded in the following order:
By convention priorities are the same as the device number. By this convention hardware devices will always be booted before software-only applications such as the concise oxford spelling checker etc. DEVICE_CODE_ADDRESS_WORDThis word contains the address on the PACK of the device code to be booted into the operating system. If the device code immediately follows the 8 byte header on the PACK then this address will be 8. However it is often desirable to have other information on the PACK before the device code and as such this word allows the device code to be anywhere on the PACK. RELOCATABLE OBJECT CODE DESCRIPTIONAs device code can be loaded anywhere in memory, depending on the machine type (CM, XP or LA etc.), and on how many devices are loaded, it is mandatory that the code to be loaded is in a relocatable form. The operating system provides a service DV$LOAD which will load the relocatable code into the machine and apply the relocation fix-ups. The code pointed to by the DEVICE_CODE_ADDRESS_WORD must be in Psion's relocatable object code format. The relocatable object code format is as follows:
Psion was supplying an assembler which would automatically generate object code in the relocatable format. However to illustrate the relocatable object code format, the following simulates the relocatable object code format using a normal assembler.
ORG 0
0000 0011 DW CEND-CBASE ; SIZE OF CODE
ORG 0100h
0100 CBASE:
0100 CE 2188 LDX #RTT_BF ; RUN TIME BUFFER
0103 86 20 LDAA #20h ; SPACE CHARACTER
0105 C6 14 LDAB #10 ; DO 10 TIMES
0107 LOOP:
0107 A7 00 STAA 0,X ; STORE SPACE IN BUFFER
0109 08 INX ; GO ON TO NEXT BYTE
010A 5A DECB ; DECREASE COUNT
010B 26 03 BNE LEND ; FINISHED ?
010D 7E 0007 FIX1: JMP LOOP ; NO - SO LOOP
0110 LEND:
0110 39 RTS ; EXIT ROUTINE
0111 CEND:
0111 04E9 DW 04E9h ; CHECKSUM OF CODE BLOCK
0113 0001 DW (FIXEN-FIXST)/2 ; NUMBER OF FIXUPS
0115 FIXST:
0115 000E DW FIX1-CBASE+1 ; ADDRESS IN CODE BLOCK
0117 FIXEN:
0117 000E DW 0Eh ; CHECKSUM OF FIXUPS
The code must be assembled at an address above the zero page (here $100) to avoid zero page adressing. All checksums are calculated by accumulating each byte in a word. Overflow is ignored. The following code fragment will checksum the code between CBASE and CEND.
LDX #CBASE ; START ADDRESS
CLRA
CLRB
STD UTW_S0 ; START CHECKSUM AS 0
LOOP:
CLRA
LDAB 0,X ; GET BYTE
ADDD UTW_S0 ; ADD CHECKSUM
STD UTW_S0 ; SAVE IT
INX
CPX #CEND ; ALL DONE
BNE LOOP ; NO - SO DO MORE
; UTW_S0 NOW HAS THE CHECKSUM
Each entry in the fix-up table is the word-offset of a word in the code which requires relocation. After the code block is loaded, the DV$LOAD service adds the load address to all relative addresses in the code which are mentioned in the fix-up table. If for example the above code segment was loaded at address $2000 then the fix-up of $E in the fix-up table, would result in $2000 being added to the code block at address $2000+$E in memory. This would change $7E $00 $07 to being $7E $20 $07, the correct absolute address of LOOP. DEVICE CODE DESCRIPTIONJust loading the code from a device into memory is insufficient as the code itself must interface to the operating system. The following describes the component parts of the interface between the device code and the operating system: CODE_START:
DW 0 ; FILLED IN BY DV$BOOT
BOOT_DEVICE:
DB 0 ; FILLED IN BY DV$BOOT
DEVICE_NUMBER:
DB 12 ; AS IN THE PACK HEADER
VERSION_NUMBER:
DB $10 ; AS IN THE PACK HEADER
MAX_VECTOR_NUMBER:
DB 3 ; NUMBER OF VECTORS PROVIDED
VECTABLE:
DW INSTALL ; INSTALL VECTOR
DW REMOVE ; REMOVE VECTOR
DW LANG ; LANGUAGE VECTOR
INSTALL:
; THE INSTALL CODE
REMOVE:
; THE REMOVE CODE
LANG:
; THE LANG CODE
When the device is booted into memory DV$BOOT will load the size of the code into the word at CODE_START. This is necessary for DV$VECT to be able to walk the list of device drivers in memory. At the same time the slot that the code was loaded from will be placed in BOOT_DEVICE. This is to allow the device to know which slot it has been booted from. Thus if a device wants to access the PACK from which it has been booted the following code fragment can be used: CLRA ; REPORT PACK CHANGED ERROR
LDAB BOOT_DEVICE ; SLOT DEVICE WAS BOOTED FROM
OS PK$SETP ; SELECT THE SLOT
The DEVICE_NUMBER byte and the VERSION_NUMBER byte are the same as those on the PACK header. DV$VECT uses the DEVICE_NUMBER byte to select the right device from the list in memory. The VERSION_NUMBER byte is purely for documentary purposes. The MAX_VECTOR_NUMBER is to allow DV$VECT to check that the device service exists. Thus if DV$VECT were used to call the device in the example above to perform vector number 3, it would fail, as it only provides vectors 0,1 and 2. There follows a list of vectors which are used to jump to appropriate parts of the code in the device. DV$VECT is called with the device number in the A register and the vector number to be called in the B register. DV$VECT will scan the devices in memory to see if the device is present and if it is, it will then jump to the appropriate vector. All devices must provide vectors 0,1 and 2, and may provide up to 255. DEVICE VECTORSEvery device which is loaded into the operating system has a vector table which directs the operating system to the appropriate code to handle that "VECTOR SERVICE". The first 3 "VECTOR SERVICES" have a defined meaning as follows: VECTOR SERVICE 0 - INSTALL VECTORWhenever the DV$BOOT service loads a device it will call the INSTALL vector immediately after loading the device. This will give the device the opportunity to initialize itself. For example the RS232 interface installs the COMMS menu item into the top level menu at this stage by calling the system service TL$ADDI. On completing the required INSTALL code the device should clear the carry flag and then do an RTS instruction. If for any reason the INSTALL code decides the device cannot run properly (i.e. not enough memory), then the carry flag should be set and the device will not be installed (and no RAM will be allocated for the device). A device need not return from this vector, in which case it will have effectively taken control of the machine. NOTE: The DV$BOOT service uses the first 4 bytes of RTT_FF to build the priorities table and as such the install vector should preserve these 4 bytes if there is any danger of them being corrupted. See the description of DV$BOOT for more details. VECTOR SERVICE 1 - REMOVE VECTORWhen DV$BOOT is called, it first calls DV$CLER, which calls the REMOVE vector for each device. DV$BOOT then zeroes the permanent cell (and also resets DVA_TOP in LA/OS) effectively discarding all devices. The REMOVE code can then tidy up anything that needs to be done before the device is thrown out of memory. For example the RS232 interface removes the COMMS menu item from the main menu in its REMOVE code. The REMOVE code should terminate with the carry clear and an RTS instruction, even though any errors are ignored. VECTOR SERVICE 2 - LANGUAGE VECTORThis vector service is required by the OPL language and provides the mechanism by which the language can be extended. For any procedure called in an OPL program, the language will first call the DV$LKUP service to see if any devices are prepared to handle the procedure. To do this DV$LKUP calls each device's LANGUAGE vector with the X register pointing to a leading count-byte string containing the name of the procedure. If none of the devices are prepared to handle the procedure then the language will search packs A,B,C and D for an OPL procedure of that name. If a device is prepared to handle the procedure then it will return its device number in the A register and the vector service number which will handle the procedure in the B register. The language will then immediately call the DV$VECT service which will call the vector service. For example the RS232 interface provides a language procedure LINPUT$: and as such the LANGUAGE vector code can be coded as follows: LANGUAGE_VECTOR:
LDD 0,X ; GET SIZE AND FIRST LETTER
SUBD #7*256+'L' ; COMPARE
BNE NOT_LINPUT ; NOT A MATCH
LDD 2,X ; GET NEXT TWO LETTERS
SUBD #'IN' ; COMPARE
BNE NOT_LINPUT
LDD 4,X ; GET NEXT TWO LETTERS
SUBD #'PU' ; COMPARE
BNE NOT_LINPUT
LDD 6,X ; GET NEXT TWO LETTERS
SUBD #'T$' ; COMPARE
BNE NOT_LINPUT
LDAA #C0h ; RS232 DEVICE NUMBER
LDAB #4 ; VECTOR NUMBER TO HANDLE LINPUT$
CLC
RTS
NOT_LINPUT: ; NOT LINPUT$ - SO NOT PREPARED TO
SEC ; HANDLE THE PROCEDURE
RTS
NOTE: As the LANGUAGE vector code is called every time an OPL procedure is executed, it is important that the LANGUAGE vector code be as fast as possible. Clearly a device can handle as many procedures as necessary by just chaining the name matches or by searching a list of procedures. See the chapter on the language as to how OPL passes parameters to device procedure handlers and how devices pass back their results. BOOTINGThe system service DV$BOOT is responsible for loading and removing devices. The area in which devices are loaded in the operating system is one of the preallocated cells, known as the PERMANENT cell. This cell is the first allocated cell and has the unique property that it will never be moved by the allocator (i.e. it always has the same base address). This is obviously crucial as once the code has been relocated in memory it can no longer be moved, as all addresses have been converted from relative addresses to absolute addresses. Organisers with 32kb or more RAM use the RAM from $0400 to $2000 ('low' RAM) for loading device code, in preference to the permanent cell. This means that while devices occupy less than 7k in total, the full 24k will be available for the user. Note that INFO will only show devices which are occupying high memory - i.e. any devices which have overflowed the 7k. For example with an RS232, a barcode reader, and a concise oxford spelling checker booted, only the spelling checker will be loaded into the permanent cell in high memory, so INFO will report DEVICES xxx%. The addresses DVA_BOT and DVA_TOP mark the lower and upper limits of low memory. DVA_TOP is increased as devices are loaded into low memory. DVA_BOT is initialised to $0400 at cold startup. The operations performed by DV$BOOT are as follows:
Organisers with 32kb or more RAM:
The DV$BOOT service is called by the operating system when a cold start is required. (On multi-lingual machines like the LZ, devices are booted on cold start before asking for a language and again afterwards when the language has been selected to enable the device to switch languages. This feature can be disabled - see foreign languages.) Thereafter DV$BOOT is only ever called when the ON/CLEAR key is pressed in the main menu (i.e. at the top level). Thus to load a device into the operating system the device must be plugged into the machine and the ON/CLEAR key pressed until the main menu is reached. Then one further press will execute the DV$BOOT service and load the device driver. There is no problem in booting the device drivers any number of times. To remove a device from memory, simply remove the device from the machine and repeat the above procedure (i.e. perform a boot). As the device is no longer present and as DV$BOOT always throws out all devices before performing the boot procedure the device will be effectively removed from memory. NOTE: As DV$BOOT always throws all devices out of memory, no device can call the DV$BOOT service. In order for a device to call the DV$BOOT service it must copy a routine to call DV$BOOT into some safe portion of memory and then jump to that code. The code can then either get back to device, which will have been reloaded, through a known vector service or just simply return from where it came. OPL programs, because they are running in a different area of memory can easily call the DV$BOOT service as follows: REBOOT: REM BOOTS ANY DEVICES INTO MEMORY LOCAL I%,CODE$(4) I%=ADDR(CODE$)+1 : REM SKIP THE SIZE BYTE OF THE STRING POKEB I%,$3F : REM THE SWI INSTRUCTION POKEB I%+1,23 : REM THE DV$BOOT VECTOR NUMBER POKEB I%+2,$39 : REM A RETURN INSTRUCTION USR(I%,0) : REM CALL THE MACHINE CODE This procedure when called will execute the DV$BOOT service. The following procedure will remove all devices from memory:
OS DV$CLER ; run 'remove' vector of all devices
LDX DVA_BOT ; reset low memory (harmless on non-LA/OS)
STX DVA_TOP
LDX #2000h ; zero the permanent cell
OS AL$ZERO
From model LA onward, the user can reserve an area of low memory
from $400 upwards LDA A,$FFE8 ; TEST OS/VERSION
ANDA #7
CMPA #2 ; must be >= 2
BLT NOT_OK
OS DV$CLER ; RUN 'REMOVE' VECTOR OF ALL DEVICES
LDX #2000h ; AND KILL ANY DEVICES IN HIGH MEMORY
OS AL$ZERO ; SO THAT THEY CANNOT BE ACCESSED AFTER THEIR
; REMOVE VECTORS HAVE BEEN CALLED
LDX #SPACE_REQUIRED+0400h
STX DVA_BOT ; SET BASE ADDRESS FOR FUTURE DEVICE LOADING
STX DVA_TOP ; SET TOP= NEW BOTTOM
; RAM NOW AVAILABLE from $0400 - DVA_BOT - 1
2 AND 4 LINE MODELSAll machine code applications that run on the LZ will automatically
be put into "2-line compatibility mode" as soon as anything
is printed to the screen. The LZ will however be switched back
to 4-line mode after returning. The device itself must put the
machine into 4-line mode if required, by calling system service
DP$MSET.
Note that machine code applications can simply check DPB_MODE rather than looking at the ROM id bytes because the mode will not change until anything is printed to the screen. However, OPL applications will have already been put into 2-line mode by the time they are running, so they must check the ROM id. For example the following procedure will print "HELLO" on the 2nd line of a 2-line machine and on the 4th line of an LZ: LDAA DPB_MODE
BEQ 1$ ;branch to run in 2-line mode
OS DP$MSET ;set to 4-line mode A=1
OS UT$DISP
DB 12,23 ;clear screen and goto 4th line
ASCIZ "HELLO"
RTS
1$: OS UT$DISP
DB 12,10 ;clear screen and goto 2nd line
ASCIZ "HELLO"
RTS
HARDWARE INTERFACESThe Organiser has three slots available in which hardware interfaces can be fitted. The TOP slot (slot 3) is the preferred slot for interfacing to external hardware as it has been especially designed for this purpose. However there is no reason why one of the two SIDE slots (slots 1 and 2) cannot be used. There are however a number of fundamental differences between the top slot and the side slots. In general though the 16 way connectors from the Organiser to the outside world constitute a proprietary BUS and as such there are a number of rules from a hardware and software point of view with regard to interfacing on this BUS. In the following sections the BUS components which are common to all slots are described followed by a section on the differences between the TOP slot and the SIDE slots. BUS SIGNALS
This common set of signals comprise the Psion proprietary BUS. This BUS was designed to allow Psion's removable PACKS to be interfaced to the Organiser. In order to understand the following description of the BUS it is necessary to have read and understood the chapter on low level access to packs. All Psion's hardware interfaces consist of both a PACK and the hardware interface itself. The PACK is used to provide the DEVICE code which is loaded into the operating system, thereby providing the software interfacing to the OPL language and the operating system itself. While it is possible to build hardware interfaces without a PACK on board, it is strongly recommended that this is not done. The PACK not only provides a mechanism for adding extra code associated with the hardware, it also provides a means whereby the code can tell that the interface is still plugged into the machine by reading the on board PACK. SSS_BThis signal is the SLOT select signal and is used to select the hardware plugged into that slot. At no time should an external interface try to control any of the signals on the BUS until SSS_B goes low. There is obviously one SSS_B signal for each slot in the machine. It is also mandatory that none of the control signals on the BUS should be changed while SSS_B is active. The control signals are SOE_B,SMR and SCLK. Thus to change a signal, SSS_B should be raised high, then the signal changed and finally SSS_B can be lowered again. This signal should always be pulled up through a resistor to SVCC. SOE_BThe SOE_B signal is used to select between the PACK on the interface and the external hardware. With SOE_B low (i.e. active) the PACK should output its contents onto the DATABUS. With SOE_B high then the hardware interface circuitry should control the DATABUS. This signal should always be pulled down through a resistor to 0 volts SMRThe SMR signal is used to reset the counters on the PACK to 0. It is also used in a number of combinations with SOE_B high. These are explained in a table later on. This signal should always be pulled down through a resistor to 0 volts SCLKThe SCLK signal is used to clock the counters on the PACK. It can also be used in a number of combinations with SMR high. These are explained in a table later. This signal should always be pulled down through a resistor to 0 volts SVCCThis is the +5 Volt rail to external hardware interfaces. It can be used to supply power to the hardware interface. Note that when the Organiser is switched off, this voltage will no longer be supplied. Instead a small amount of current can be drawn from the SSS_B signal as it is supplied from a different power rail. See Chapter 3 for more details. SGNDThis is the 0 Volt signal to the interface. SD0-SD7These 8 signals represent an 8 bit DATABUS between the hardware and the Organiser. Since it is possible to both read from and write to hardware interfaces, this bus is BI-DIRECTIONAL. However the rest state when not in use is always INPUT to the Organiser. i.e. The PORT2 direction register should be set to 0 so that all bits of PORT2 are input. If the direction of these bits are ever changed to OUTPUT they must be reset to INPUT before control is passed back to the operating system, as the operating system assumes that PORT2 is always configured as all INPUT. All these signals are pulled down internally to the Organiser to 0 Volts. Thus if no interface is present in a slot the Organiser will always read a 0. This is used by the operating system to determine that a pack is not present in the slot. BUS STATESThe following table represents the rules by which the interface should respond to various states of the BUS control signals. In the table, HIGH stands for +5 Volts, LOW stands for 0 Volts and X stands for don't care.
When the operating system selects a slot using the PK$SETP service, it will place the control signals in a number of these states. However the top slot is treated slightly differently, in that the operating system will not support 128K packs or RAM packs. Thus the following states can occur for the various slots:
STATE 0
This state is the rest state for all interfaces. When SSS_B is high no interface should be trying to control the databus or any of the control signals. STATE 1
This state is used by the operating system to select the 16K segment in 128K PACK devices. Note that PK$SETP selects segment 0 every time it is called regardless of the device fitted in the slot. As the operating system does not support 128K PACK in the top slot this state can be used to select devices in a hardware interface to be used in the top slot. STATE 2
This state is used to write data to either packs or RAM packs in the slots. However if the RDWRT bit in the ID byte of the pack is clear then the operating system will never place state 2 on the control lines. This state is the only state that can be used safely to select other devices than the PACK on interfaces intended for use in the side slots. STATE 3
This state is used by the operating system to select the RAM pack hardware ID 1. Note that PK$SETP uses this state to determine if a RAM pack is plugged into a slot. If so, it will output an ID byte of 1 in response to this state. Note that packs output byte 1 of the ')"; onMouseout="hideddrivetip()"> EPROM in response to this state. As the operating system does not support RAM packs in the top slot this state can be used to select devices in a hardware interface to be used in the top slot. STATE 4
This state is used by the operating system to select the RAM pack hardware ID 0. Note that PK$SETP uses this state to determine if a RAM pack is plugged into a slot. If so, it will output an ID byte of 1 in response to this state. Note that Packs output byte 0 of the ')"; onMouseout="hideddrivetip()"> EPROM in response to this state. As the operating system does not support RAM packs in the top slot this state can be used to select devices in a hardware interface to be used in the top slot. STATE 5
This state is used by the operating system to read data from the PACK circuitry on interfaces. The byte, corresponding to the currently selected address on the PACK counters, is output on the databus in response to this state. EXAMPLETake as an example the BARCODE interface for the top slot, as supplied by Psion. The interface has two discrete interface circuits:
State 5 is used to enable the ')"; onMouseout="hideddrivetip()"> EPROM in the PACK circuitry to output its contents on the databus. States 1 and 2 are used to enable the BARCODE input signal buffer circuitry. I.e.
Thus to select the BARCODE PACK circuitry the following code fragment can be used: SELECT_PACK:
CLRA
LDAB #PAKD
OS PK$SETP ; THE PACK IS NOW SELECTED
; THE CONTROL LINES ARE IN STATE 5
To select the BARCODE input signal buffer circuitry the following code fragment can be used: SELECT_BARCODE:
CLRA
LDAB #PAKD
OS PK$SETP ; SELECT PACK AS NORMAL
OIM #CS3,POB_PORT6 ; DESELECT THE SLOT
OIM #OE,POB_PORT6 ; SET SOE_B HIGH
AIM #~CS3,POB_PORT6 ; SELECT THE SLOT AGAIN
; BARCODE HARDWARE NOW SELECTED
; THE CONTROL LINES ARE IN STATE 1 OR 2
NOTE: Before control can be returned to the operating system, STATE 5 must be reestablished on the control lines. This can be achieved as follows: DESELECT_BARCODE:
OIM #CS3,POB_PORT6 ; DESELECT THE SLOT
AIM #~OE,POB_PORT6 ; SET SOE_B LOW
OIM #~CS3,POB_PORT6 ; SELECT THE SLOT AGAIN
NOTE: Control lines should only ever change state when the control lines are in STATE 0, i.e. the interface is deselected. SYSTEM SERVICESDV$BOOTWill boot all devices plugged into the Organiser. Any errors occurring during the boot are reported directly. However the screen is saved before the message is displayed and restored immediately afterwards. DV$LOADThis service will load code from a pack which is in the Psion relocatable object format. It loads the code into memory and then applies any fix-ups that are required, thus relocating the code to the address as specified. The routine assumes that the correct slot has already been selected with the PK$SETP service. DV$VECTThis service will search the devices in the PERMANENT cell for a device whose device number matches the given number. Then the service checks that the passed vector number is not greater than the maximum vector number supported by the device. If it is, then an error is returned. Otherwise the appropriate vector is loaded from the device vector table and a JMP is done to the vector. DV$VECT passes the X register and the scratch register UTW_S0 through to the vectored routine, so that these may be used to pass parameters to the device vector routine. It is up to the device to specify what is passed and what is returned. DV$VECT returns the same things as the vectored routine. DV$LKUPThis service will call the LANGUAGE vector of all devices in memory. If a device signals that it is prepared to handle the given procedure name then the service will return the device number and the vector number of the code to handle the procedure. DV$CLERThis service calls the REMOVE vector for all devices currently in memory. It is usually called by DV$BOOT just before zeroing the permanent cell in preparation to booting. EXAMPLEThis is an example of a device to allow the operating system services to be called from OPL procedures. The device is a procedure called SWI%: and it takes as its argument an integer specifying which service should be invoked. Most functions also require values in the A,B(D) or X register as well and so the function requires 2 global variables X% and D% to be declared by the OPL procedure. Any values to be passed in UTW_S0 or UTW_S1 can be set with POKEW before calling SWI%:. If carry is clear after the call to the operating system SWI%: will return 0 and if it is set, SWI%: will return -1 and D% will have the error number. If SWI%: signals success D% and X% will be set directly from the machine registers D and X. NOTE: The D register is actually made up of the A register and the B register so that D = A*256 + B. The global variable D% mimics this. So if a routine requires A = 1 and B = 3 this can be passed as D = 1*256+3. On return the values of A and B can be determined from D% as follows:
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||