The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

THE PSION SIBO HARDWARE DEVELOPMENT KIT

Version 1.00

May 26 1995

Revision 1.00 Page i

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

(c) Copyright Psion PLC 1990-93

All rights reserved. This manual and the programs referred to herein are copyrighted works of Psion PLC, London, England. Reproduction in whole or part, including utilisation in machines capable of reproduction or retrieval, without express written permission of Psion PLC, is prohibited. Reverse engineering is also prohibited.

The information in this document is subject to change without notice.

Psion and the Psion logo are registered trademarks, and Psion, Psion MC, Psion HC, Psion Series 3, Psion Series 3a and Psion Workabout are trademarks of Psion PLC.

TopSpeed is a registered trademark of Clarion Software Corporation. Intel 8086 and 80286 are registered trademarks of Intel Corporation. IBM, IBM XT and IBM AT are registered trademarks of International Business Machines Corp. Microsoft and MS-DOS are registered trademarks of Microsoft Corporation. Apple and Macintosh are registered trademarks of Digital Equipment Corporation. Brief is a registered trademark of Underware Inc. Psion PLC acknowledges that some other names referred to are registered trademarks.

Revision 1.00 Page ii

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Contents

‘ De IMGrOMUCUON sec ioiciescccetisshicattxstcathaslicatixssdcstenslacatenstecatenslicatinssdesvenslacevinswdvatensldcsvisatibiteislacibedse

2. System Overview..........scccccscssccssssscscsscsseccsscssecssccsesssscssesssscsssesscssesssssesssscssssssscssssssscsessssesesseeees

3. Hardware Overview .........sssccssssssssssscssscssscsssssssesssesssesssesssesssssssssessscssscsssessesssesssnssseesscseoeeees The Psion SIBO serial protocol .... Psion ASICs and what they do.. Interrupts . The current range of Psion periphera

4. The Psion SIBO Serial Protocol . Hardware Interface ... The Physical layer . The Transport layer ..

5. Mechanical Overview ...........sscssscsssssrscsssssessscessecssessessssesseessessscesssessesscssssssscsssessccssesssessosees LD The Psion Series 3/3a range ... The Psion Workabout The Psion HC range

6. ASIC 4......... ASIC4 Addressing and Modes Reset and configuration ASIC4 Pin-out

7. ASIC 5.......scesee ASICS Mode Reset and configuration ASICS Pin-out

8. Example Peripheralls................cccssccssssssssssssseccsscscccssssscsssscccesssscscesssssesssscsssssssssesscsssssscsseeesess OO The ASIC4 Example Interface Board.. The Psion 3-Link

9. Device Driver Overview...........cccsrsercesssserscersserecssecssesscesssesesssessssessesssesscsscssscsssssssesssessosees OT Introduction Device Names and Channel: Loadable Logical Device Driver Structure Mandatory LDD Functions ............... Interrupts and Interrupt Service Routines at Loadable Physical Device Driver Structure... ccscecesesesseesssesssesesssesesesescseseseenenesesesesesesenenesseesesesusueasaeaeseeessecacaeaeaeenenssesecasaseeeeeneeeeeaeaes

10. ASIC4/ASIC5 Based Device Drivers

Introduction SIBO Hardware Expansion Channels Talking to ASIC4.. ASIC4 Registers Talking to ASICS .. ASICS Registers... Communicating with ASIC4 Sending and Receiving data using ASIC4. Obtaining and using a channel... Controlling ASICS's UART Hold and Resumes. Example Device Driver:

11. An Example Device Driver for ASIC4: A4EXIF.LDD..

Introduction

oo TO eR UU RS gs pad

Mandatory LDD Function: The Non-Mandatory LDD Functions..........cceee The handling of synchronous and asynchronous I/O Interrupts and Interrupt Service Routines Other important local device driver functions Structures and Include files «0... cee

12. An Example Device Driver for ASIC5: SYS$AS5.PDD.............ssssssssssssssessessessssesscsessessesseee 77

Introduction The LDD-PDD interface.

13. Debugging and Testing Device Drivers Introduction .... Debugging Techniqu Further Testing Strategies ae Memory Lestitng seiscs lech easch oiece siscn Sates losecdestecwcsautsse sean tosevaleslosedtracepudtesiiensdertoanioenteoisebeensse bait es ieettaus adanus teats a a tanta eae

APPENDIX: Source Code Files.. A4EXIF.ASM oo SYS$AS5.ASM .... 102 Assembler Macros. 1S

Revision 1.00

Page iii

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

1. INTRODUCTION

This document is intended to provide guidance to anyone wishing to construct peripherals for the Psion SIBO (sixteen bit organiser) range of computers. It describes in detail all aspects of Psion peripheral hardware development and the structure of the software required to drive such peripherals. It is the aim of this document to aid third party development engineers in producing production ready peripherals for any of the following Psion products: Series 3/3a, Workabout, HC and HCDOS. Mechanical and plastic moulding information and information on how to develop production test equipment is therefore also included. The emphasis throughout is on the two key Psion peripheral chips ASIC4 and ASIC5. Detailed information regarding their functionality is provided. The structure of Psion hardware device drivers is examined both in general outline and then with regard to two specific examples whose source code is provided in the appendix to this document. It has been assumed that the reader has some knowledge of a Psion computer such as the Series 3/3a and an understanding of how such a machine is programmed. A good understanding of electronics, the C programming language and 8086 assembler is also assumed.

Due to the continuous nature of development, information in this manual may change without notice.

Developers are advised to contact Psion Support to confirm critical details prior to committing products to manufacture.

Revision 1.00 Page | of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

2. SYSTEM OVERVIEW

All present Psion computers are based around the proprietary SIBO architecture. A SIBO machine is a battery-powered, 8086-based, computer system. SIBO stands for SIxteen Bit Organiser. The architecture has been designed with the size, weight and power consumption of computers designed for the portable environment in mind. The key components of the SIBO architecture are:

e —_ An 8086 class processor .

e A sophisticated power management system that selectively powers subsystems under software control.

e — Asynchronous, high speed, serial protocol (the Psion SIBO serial interface) for communication between a machine and its peripherals.

e —_ Solid State Disks (SSDs) that provide fast, low-power, silicon-based mass storage with no moving parts.

e Hardware protection of the system from aberrant software processes (trapping of out of range

addressing and a watch-dog timer on interrupts being disabled).

Real-time clock.

ROM-resident system software.

Graphics LCD display.

A touch sensitive digitising pad that provides a pointing device (only available on some models).

ISDN-8bit standard combo sound system (only available on some models).

The SIBO architecture has primarily been implemented in custom ICs called ASICs. At the time of writing there are ten different SIBO ASICs. Some of these ASICs have been designed for use inside peripherals and these will discussed in detail throughout this document. All SIBO ASICs have been implemented in surface mount packages and are based on a static CMOS technology. Current SIBO products in the MC, HC and Series 3 range are based on the same three principal chips. These are the V30H (an 8086-compatible processor) and two Psion custom chips known as ASIC1 and ASIC2. Later SIBO products including the Series 3a and Workabout have these three devices integrated into a single Psion custom chip known as ASIC9. The V30H is an enhanced 16-bit CMOS version of the 8088 found in the original IBM PC. It is software compatible with the 8088. The V30H is a fully static design which means that all the internal storage elements (i.e. its registers) are made from static rather than dynamic storage components. This in turn means that there is no minimum clock speed required to refresh the storage elements and the system clock can be stopped at any time with no loss of internal state. This technique is used extensively in the SIBO architecture to save power while the processor is idle (i.e. waiting for an event).

The Psion SIBO serial protocol is a proprietary synchronous two wire serial standard by which host Psion handhelds communicate with external devices. These devices will typically be Memory Packs (usually referred to as Solid State Disks or SSDs), RS232 and Centronics printer interfaces, fax modems, bar-code scanners, and so on. The SIBO architecture provides for two basic forms of expansion device, namely the extended internal expansion connection (as with SSDs) and the reduced external expansion connection (the 6-pin S3a serial port or the 11-pin LIF connector). The MC and HC range of computers have two SSD ports and two separate independent single row 25-way extended internal expansion ports. These ports have in addition to a Psion SIBO Channel, direct, parallel I/O from the processor. Direct connection to these machines 7.2 volt battery is included to support high power peripherals such as Printers and Barcode readers. The Series 3 range of computers have two ports for SSDs and a single, reduced, 6-pin expansion port, which provides only a Psion SIBO serial channel and limited power (<25mA). The Psion Workabout has two SSD ports, two internal expansion points, and one external expansion port. The single external expansion port uses an | 1-pin Low Insertion Force (LIF) socket which provides a Psion SIBO channel, 25mA of current and additional lines required for detecting the presence of the Workabout cradle. Each internal expansion port consists of a single row 26-way connector carrying two high speed serial ports.

Revision 1.00 Page 2 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

A range of Psion peripherals have been produced for connection to the Psion handhelds outlined above. These peripherals currently incorporate one of two custom integrated circuits (ASIC4 and ASICS) that convert SIBO serial protocol signals to data bus TTL level voltages which enable memory and memory-mapped peripherals to be addressed. ASIC4 is used in SSDs and for memory- mapped peripherals. A typical ASIC4 peripheral for a Psion S3a would consist of an ASIC4 connected to port C of the host machine and a peripheral chip/device mapped into ASIC4's addressing space. ASICS is a general purpose I/O chip with a UART on board that can be run in several different modes. For example ASICS can be used for MCRs (magnetic card readers) or Centronics interfaces thereby simplifying peripheral design. Psion extended internal expansion ports carries an active low interrupt input line to the host controller circuitry. The reduced external expansion ports has an active high interrupt input line. The function of the interrupt can thus be programmed into the host machine's ASIC1 or ASIC9.

The low-level programming interface to a Psion handheld peripheral is encapsulated within an appropriate device driver. Psion device drivers are written in 8086 assembler and follow a prescribed pattern outlined later in this document. The construction of a peripheral and the coding of its complimentary device driver enable the developer to access its functionality through the means of library calls in a C program. Examples of such calls are p_loadldd(), p_open() and p_close(). I/O requests are routed through the device driver's strategy vector which maps to the PLIB p_iow () call. The device driver is built using the Borland Turbo Assembler and resides in a single code segment. The device driver can be stored in either RAM or a ROM on board the peripheral or can be supplied on an SSD (solid state disk).

Revision 1.00 Page 3 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

3. HARDWARE OVERVIEW

The Psion SIBO serial protocol

The Psion SIBO serial protocol is a general purpose method of bi-directional serial data transfer. It has been designed for synchronous communication between a host controlling device and a number of slave devices. On a hardware level, the SIBO serial protocol is implemented through Psion ASICs. The controlling device must contain an ASIC2 (or ASIC9) and the slave devices an ASIC4 or ASICS. The various Psion ASICs are described in more detail below.

The synchronous SIBO serial protocol interface consists of 2 wires:

CLK ~ - Aclock output from the controller to the slaves. Nominally 3.84 MHz.

DATA - A bi-directional synchronous data line.

The data is transferred using a series of 12 bit frames including 8 data bits each. This equates to a theoretical maximum data transfer rate of approximately 312 Kbytes/second. Other bits of the frame contain control information. The "system" is generically defined by 2 protocol layers, namely the Physical layer and the Transport layer. These layers are described in detail in the next chapter.

Psion ASICs and what they do

ASIC stands for Application Specific Integrated Circuit and as previously indicated, these devices are widely used within Psion hardware. Summaries of the functionality of each ASIC that is relevant to peripheral development are presented below:

ASIC1: ASIC1 is the main system controller chip for the SIBO architecture. It connects directly to the 8086-based processor (i.e. the V30H) controlling all bus cycles to and from the processor. This configuration effectively forms a micro-controller like device that executes 8086 instruction codes. ASIC 1 is made up of a number of functional blocks including a bus controller, a programmable timer, an eight input interrupt controller, an LCD controller and the memory decoding circuitry.

ASIC2: ASIC2 is the peripheral controller chip for the SIBO architecture. It contains the system clock oscillator and controls switching between the standby and operating states. ASIC2 provides an interface to the power supply, keyboard, buzzer and SSDs. ASIC 2 includes the eight-channel SIBO serial protocol controller and provides interface circuitry to both the reduced external and extended internal peripheral expansion ports.

ASIC4: ASIC4 is a serial protocol slave IC for addressing memory and general memory-mapped peripherals. It is used in SSDs to convert SIBO serial protocol signals into addresses within the memory range of the memory pack. ASIC4 was designed to be a cut-down version of ASICS which was the original SIBO serial protocol slave chip.

ASICS: ASICS is a general purpose I/O chip with a built-in UART that can be set to run in a number of different modes thereby simplifying the task of peripheral design. For example, it is possible to set up ASICS to run as a Centronics parallel port interface, an 8-bit parallel I/O port, a serial bar code controller or a serial RS232 converter.

ASIC9: ASIC9 is a composite chip comprising of a V30H processor, ASIC1, ASIC2 and general I/O and PSU control logic all on one IC. ASIC9 thus integrates all the digital logic required to produce a SIBO architecture computer less the memory onto one chip. ASIC9 has a few additional features such as an extra free-running clock (FRC) and a codec interface for sound.

Revision 1.00 Page 4 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Interrupts

Psion peripherals usually incorporate some circuitry to generate hardware interrupts. Both reduced external expansion ports (such as the LIF connector on the Workabout or the 6-pin serial port connector on the S3a) and extended internal expansion ports (such as the two single row 25-way HC connectors) carry an interrupt line. This is an active high input to the host machine's interrupt controller circuitry which resides on the logical equivalent of ASIC1. The OS intercepts all interrupts and can be requested to call a particular function within a controlling device driver. Eight hardware interrupts are supported by SIBO hardware. IRQO is the highest priority and IRQ7 the lowest. All interrupts are level triggered and must be serviced in the following order:

e Device asserts the appropriate interrupt request line.

e The interrupt controller unit within either ASIC2 or ASIC9 places onto the data bus the vector of the highest priority device with an interrupt pending. This enables the CPU to jump to the correct interrupt service routine code.

e During the interrupt service routine, the software clears the interrupt line by some action specific to the device.

e The interrupt service routine then informs the interrupt controller that the interrupt has been cleared by writing to the non-specific end of interrupt (NSEOD) location.

e If another interrupt is pending then go back to the second step.

With 8086-based processors, it is not possible to have nested interrupts.

The current range of Psion peripherals

There are currently a number of Psion peripherals in use and some of the key ones are outlined below in order to provide the developer with a feel for peripheral design issues:

SSDs: Solid State Disks (or Memory Packs) use a built-in ASIC4 to decode SIBO serial protocol signals into memory addresses within the memory range of the SSD.

Psion 3-link: The 3-link translates the high speed SIBO serial protocol channel on the S3a 6-pin reduced external expansion socket into a serial RS232 format. This enables the host machine to communicate with a PC for example by means of connecting the 3-link unit from the handheld's 6-pin port to the PC's COM1 or COM2 port. The 3-link contains an ASICS which uses its on-board UART to convert SIBO serial protocol signals to RS232 format TTL level voltages.

The HC Printer: The HC Printer translates SIBO serial protocol signals transmitted across the single row 25-way extended internal expansion socket of the host HC into a parallel 8-bit format that is compatible with the universal Centronics printer interface standard. The HC Printer unit contains an ASICS running in Centronics interface mode which acts as the serial protocol slave and requires a small number of support chips.

Psion 3-Fax: The 3-Fax contains an ASIC4 and a memory-mapped modem chip set which permits the host machine to transmit (but not receive) fax messages.

Barcode: The Psion Barcode reader employs an ASICS running in serial mode to read the data received from the barcode decoder chip into a SIBO serial protocol format that can be transmitted to the host ASIC2/ASIC9.

Workabout RS232 Interface: This peripheral connects to the single row 26-way extended internal expansion port of the Workabout. It incorporates an ASICS running in its default mode to translate SIBO serial protocol signals into a TTL level (+/-5v) serial RS232 format using ASIC5's on-board UART. The TTL level RS232 signals are converted into the standard EIA format (+/-12v) before coming out on the conventional RS232 9-pin D-type connector.

Revision 1.00 Page 5 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

4. THE PSION SIBO SERIAL PROTOCOL

Introduction

The Psion SIBO serial protocol is a proprietary standard for bi-directional serial data transfer between

a controlling device and a number of slave devices. The synchronous interface consists of 2 wires

CLK and DATA as mentioned earlier:

CLK _~ - Aclock output from the controller to the slaves. Nominally 3.84 Mhz for memory

interfaces or 1.536.Mhz continuous for peripherals.

DATA - A bi-directional synchronous data line.

The data is transferred using a series of 12 bit frames including 8 data bits each. This equates to a

theoretical maximum data transfer rate of approximately 312 Kbytes/second. Other bits of the frame

contain control information. The "system" is generically defined by 2 protocol layers:-

e The Physical layer defining the hardware interface and frame structure.

e The Transport layer defines system control and register transfers between the controller and the slaves.

Using this system, a large number of higher level implementations can be defined. In normal use the

controller will communicate to slaves in a point to point configuration. Multidrop configurations with

a number of slaves attached to one channel of the controller are also supported.

As indicated in the previous chapter, the SIBO serial protocol controller circuitry resides in either an ASIC2 or an ASIC9 depending on the particular Psion hardware platform. The S3a and Workabout employ ASIC9 whereas the HC, MC and S3 use ASIC2.

Hardware Interface

As indicated above, the SIBO serial protocol consists of two lines that switch at 5V CMOS voltage levels:

Clock Line

This line is used to synchronously clock data between the controller and slaves. It is always output from the controller circuitry that resides in ASIC2/ASIC9. The clock should only be active during the transfer of data or when the serial channel is continuous clocking mode (used by ASICS). At all other times it is tri-state pulled low.

Clock Timing Parameters

Parameter Width of Clock High

Width of Clock Low Cycle time of clock Clock Frequency

Data Line

This is a bi-directional line used to transfer data synchronously between the controller and slaves. The direction of the data line is not determined by the physical layer but by the control information in the transport layer. This is described in the next section. When no data transfers are in progress the data line is always set to input on both the controller and slaves. This line is pulled low. Data is changed on the falling edge of clock by the transmit device and latched into the receiving device on the rising edge of the clock.

Revision 1.00 Page 6 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

The Physical layer

This section specifies the low level protocol of the SIBO serial protocol. The physical layer protocol consists of a series of 12 bit frames. There are four types of frames:-

Null frames - Transmitted by controller to synchronise slaves.

Control frames - Control information transmitted by controller to slaves.

Data output frames - Data frame transmitted by controller to slaves.

Data input frames - Data frame received by controller from a slave.

Frame structure

All 12 bit frames have the following structure:-

Bit

Name ST

ST Start bit. This bit goes high to indicate the start of a valid frame.

CTL ~~ Control bit. When low indicates this is a control frame. High indicates a data frame. Il Idle bit. Used to turn around direction of data line. Normally Low.

DO-D7 Data bits.

12 Idle bit. Used to turn around direction of data line. Normally low.

Null Frame

This is a special frame transmitted by the controller to ensure all slaves are synchronised. It is generated by transmitting 12 clock pulses with the data line set to input. Since the data line is pulled low this results in 12 zeroes being transmitted.

Control frame

This frame is transmitted from the controller to one or more slaves. The data line is an output from the controller throughout the whole frame. The bits in the frame have the following value in a control frame:

ST Start bit. This bit goes high to indicate the start of a valid frame. CTL Control bit. Low to indicate this is a control frame.

I1 Idle bit Set low.

DO-D7 Data bits. 8 bits of control information.

I2 Idle bit Set low.

Data Output Frame

This frame is transmitted from the controller to one or more slaves. The data line is an output from the controller throughout the whole frame. The bits in the frame have the following value in a data output frame:

ST Start bit. This bit goes high to indicate the start of a valid frame. CTL Control bit. High to indicate this is a data frame.

Il Idle bit Set low.

DO-D7 Data bits. 8 bits of transmitted data.

12 Idle bit Set low.

Data Input Frame

This frame is received by the controller from a slave. The data line is an output from the controller for cycles 1 and 2 and input to the controller for cycles 4 to 11. The bits in the frame have the following value in a data input frame:

ST Start bit. Output from controller. This bit goes high to indicate the start of a valid frame.

CTL Control bit. Output from controller. High to indicate this is a data frame.

Il Idle bit. Used to turn around direction of data line. Both controller and slave

should tri-state the data line during this bit. This bit should be low due to pull

down resistor on data line. The controller changes the data line from output to

Revision 1.00 Page 7 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

input at the end of cycle 2. The slave changes the data line from input to output at the start of cycle 4.

DO-D7 Data bits. Output from slave 8 bits of data transmitted by slave. Controller sets data line to input during these bits.

12 Idle bit. Used to turn around direction of data line. Both controller and slave

should tri-state the data line during this bit. Should be low due to pull down

resistor on data line. The slave changes data line from output to input at the end of cycle 11.

Data line direction

The following table summarises the direction of the data line.

CONTROLLER SLAVE Condition CK DATA CK

Outside Frame

Null frame

Control Frame

Data output from controller

Data input to controller:- Cycles 1-2 Cycle 3 Cycles 4-11 Cycle 12

OO000 0004

Key T Tri-state I Input O Output

The Transport layer

This section specifies the transport level protocol that operates above the SIBO serial communication physical layer. The transport layer protocol controls the serial communication between the SIBO Protocol Controller (SPC) and a number of SIBO Protocol Slave (SPS) devices. The following rules apply:-

1) The interface is controlled by the writing of control bytes from the controller to the slaves. Control bytes cannot be written by the slaves.

Unsolicited data cannot be sent from the slave to the controller.

2) The controlling device contains two registers to communicate to the slaves. These are the control register (byte, write only) and the Data register (byte or word, read/write).

Control bytes are transmitted to the slaves by writing to the control register.

The format of the control byte is as follows:-

The control word can have 2 distinct formats depending on the setting of bit 7 the Select (S) bit:- Select = 0 This is the slave select mode. This mode is for selecting, deselecting and resetting slaves. Select = 1 This is the slave control mode. This mode is for communicating with a slave which has been previously selected using the select slave command.

Revision 1.00 Page 8 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Slave select mode

The format of the slave select byte is as follows:-

Key:- R single reset bit. TU 6 bit ID field.

The 6 bit ID field is a property only of the slave. No slave may have an ID of zero, hence there can be 63 different slaves connected to one controller. The reset bit (R) controls whether the slave(s) are selected or reset. If R = 0 slave(s) are reset, R = | slave(s) are selected. Slave select control bytes can be summarised by the following table:-

Description Reset all slaves

Reset specific slave with ID = xx Deselect slave (does not reset slave) Select slave with ID=xx and read slave info (see below).

The Reset function is dependant on the slave. It would normally put the slave into a known passive reset state.

Select Slave with ID=xx (S=0,R=1)

This is a special command that causes a slave with ID=xx to transmit to the controller an 8 bit information field. This field depends entirely on the slave but must be non zero. A reply of 0 indicates that there is no slave of the requested ID present.

Slave control mode

This mode is for communicating with a slave which has been previously selected using the select slave command described above. The format of the control word in slave select mode is as follows:-

R/W Read/write select. 0 = write, 1 = read

B/W Data transfer size. 0 = 1 byte transfer, 1 = word (2 byte transfer). S/M Single/Multi transfer mode. 0 = single, 1 = multibyte.

XXXX = 4 bits of data to slave.

Note the meaning of the 4 bits of data (XX XX) is entirely dependent on the slave.

The settings of R/W,B/W,S/M bits in the control word determine the size, type and direction of subsequent data transfers in the following manner:-

Revision 1.00 Page 9 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

R/W B/W _ S/M

0 0 0 write a single byte to slave

0 0 1 write a number of single bytes to slave

0 1 0 write a byte pair to slave (not implemented)

0 1 1 write a number of byte pairs to slave (not implemented)

1 0 0 read a single byte from slave

1 0 1 read a number of single bytes from slave

1 1 0 read a byte pair from slave (not implemented)

1 1 1 read a number of byte pairs from slave (not implemented) Write a single byte

This command readies the currently selected slave to receive a byte of data and sets up the controller so that the next byte (or the LSB of a word) written to its data register will be transmitted to that slave. Anything further written to the controller's data register will have no effect.

Write a number of single bytes

This command readies the currently selected slave to receive a number of sequential bytes of data. The slave will expect to receive data bytes until another control byte is received. The controller is set up so that the next byte (or the LSB of a word) written to its data register will be transmitted to that slave. All subsequent bytes written to the controller's data register will be transmitted to the slave. This will continue until another byte is written to the controller's control register.

Write a byte pair

This command readies the currently selected slave to receive two bytes of data and sets up the controller so that the next word written to its data register will be transmitted to that slave (LSB first). Anything further written to the controller's data register will have no effect.

Write a number of byte pairs

This command readies the currently selected slave to receive a number of sequential byte pairs of data. The slave will expect to receive byte pairs until another control byte is received. The controller is set up so that the next word written to its data register will be transmitted to that slave (LSB first). All subsequent words written to the controller's data register will be transmitted to the slave. This will continue until another byte is written to the controller's control register.

Read a single byte

This command triggers a byte to be transmitted from the selected slave to the controller. This byte can then be read from the LSB of the controller's data register. Further reads of the controller's data register will return the same data but have no effect on the protocol.

Read a number of single bytes

This command triggers a byte to be transmitted from the selected slave to the controller. This byte can then be read from the LSB of the data register. This read will trigger the next byte to be transmitted to the data register of the controller. All subsequent reads of the controller's data register will trigger further bytes to be transmitted to the controller. This will continue until another byte is written to the controller's control register.

Read a byte pair

This command triggers a byte pair to be transmitted from the selected slave to the controller. This word can then be read from the controller's data register. Further reads of the controller's data register will return the same data but have no effect on the protocol.

Read a number of byte pairs

This command triggers a byte pair to be transmitted from the selected slave to the controller. This word can then be read from the controller's data register. This read will trigger the next byte pair to

Revision 1.00 Page 10 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

be transmitted to the data register of the controller. All subsequent reads of the controller's data register will trigger further byte pairs to be transmitted to the controller. This will continue until another byte is written to the controller's control register.

Timing The time taken for commands to be processed and data sent is shown below. The time is given in

SIBO pack protocol clock cycles. The length of a clock cycle is nominally 260 nanoseconds for a clock frequency of 3.84 MHz.

Receive and process the control byte 12 cycles Byte transfer to or from slave 12 cycles Byte pair transfer to or from slave 24 cycles

When writing to the controller's data and control registers the following rules apply:-

e After writing to the control register there must be a delay of at least 12 cycles before the data register is accessed or another control word is written.

e Toread a word from the data register after the command to read byte pair is issued there must a delay of at least 12 (for control byte)+24 (for the byte pair transfer)= 36 cycles.

e To perform a multiple byte pair write there must be a delay of at least 12 cycles after the command is written to the control register before the first word can be written to the data register and a delay of at least 24 cycles between subsequent writes to the data register.

States

A slave can be in one of 5 states. Note a control byte can be received and interpreted at any time. 1) Waiting to receive a data byte or control byte

2) Waiting to receive a data byte pair or control byte

3) Waiting to transmit a data byte or control byte

4) Waiting to transmit a data byte pair or control byte

5) Waiting to receive control byte only

Revision 1.00 Page 11 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

5. MECHANICAL OVERVIEW

This section will contain information regarding mechanical and plastic moulding for Series 3/3a, Workabout and HC machines that is deemed to be of especial importance to developers who are considering producing peripherals for these particular Psion platforms.

The Psion Series 3/3a range

S3a/Series 3 Reduced External Expansion Port

The Psion Series 3/S3a personal digital assistants have two SSD slots and provide access to external peripheral units through a single reduced internal expansion port, port C, on the left edge of the machine. The reduced external serial interface expansion port from the Series 3/3a forms six wires. The purpose of each is described in the table below. In addition to data, clock and power an active high interrupt line is provided. This allows the peripheral device to generate an interrupt within the host series 3/3a. The level of interrupt that is generated depends on both the machine and the expansion port that is used. Either ASIC4 or ASICS can act as the other end of the Psion Serial Interface. With exception of the interrupt line all used signals should be connected directly to the appropriate pins on ASIC4/5.

ASIC4/5 SDAT MCLK Serial clock ASIC4/5 SCLK

| 6 | SCK/EXON | Not used in this scenario | Donot Connect____|

Signal Definition

MSD and MCLK form a single master SIBO serial protocol channel. This is normally channel 7 on a Series 3 and channel 5 on an S3a. The serial channel clock can be continuously enabled to provide a free running clock for expansion devices. The frequency is fixed at 1.536MHz regardless of the system clock frequency. SDKs/INT and SCK/EXON are both dual function pins. SDKS and SCK form a single slave SIBO serial protocol channel. This can be combined with MSD and MCLK to form a bi-directional high speed data link. SDS/INT can also be used to as an active high interrupt input. The function of SDS/INT can be programmed in ASIC2 or ASIC9. A rising edge on the SCK/EXON input will bring the system out of the standby state into the operating state. VCC is a +5 volt supply that is switched off when the system is in the standby state and is switched on when the system is in the operating or idle state. The maximum current that can be drawn is 25mA. Opening the pack doors on either an S3a or a Workabout will cut power to external peripherals.

Physical Connector

The reduced expansion port is made up of a 6-way two row connector spaced on a 2x3 way 0.1 inch pitch. The diagram below shows the physical connector numbering:

Revision 1.00 Page 12 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Looking into Series 3 / 3a

The male plug is connected to a 0.5m long plastic moulded 3-link cable assembly (part no. 25020013) which is terminated in a six-pin in-line connector which connects to a 6-way 1.5mm pitch transition header (part no. 47000106).

The Psion Workabout

The Workabout Expansion Interfaces

The Psion Workabout provides a rugged and easy-to-use computer system for a wide range of mobile corporate needs. The machine can be readily adapted to support various peripheral units such as barcode scanners and modems attached to the expansion ports. The Workabout has a 26-way extended internal expansion interface and a special 11-pin reduced external expansion interface.

Workabout Extended Internal Expansion Interface

The pin-out of the Workabout 26-way internal Torson connector is outlined below:

Torson 26 way connector pin Workabout Signal name NICD (not used)

THM (not used) VIN (not used)

Revision 1.00 Page 13 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

e = Vccl is 3.0V nominal power supply. Current available from Workabout is limited to 100mA.

e =Vcc2 is 5V nominal power supply. Current available from Workabout is limited to 200mA.

e RUN is low when powered down and high when powered up. It is used to power down or reset the peripheral module.

e SCK2 and SCK3 are serial data clocks. The clocks are left running continuously at 1.536MHz when the serial port is in use. They are used to clock the UART in ASICS in the RS232 AT/TTL and AT/Barcode modules respectively.

e SD2 and SD3 are bi-directional serial data lines used in the RS232 AT/TTL and AT/Barcode

modules respectively.

EINT1 and EINT2 are active low signals for interrupt input.

EXON is an active high signal used to turn on the Workabout.

All of the above logic signals are at 3.0V or 3.3V levels, depending upon the logic supply Vcc1.

Lines currently described as unused relate to a yet unspecified codec interface.

Workabout Reduced External Expansion Interface

For the Workabout reduced external expansion interface, a new | 1-pin Low Insertion Force (LIF) connector has been designed for connecting the computer to the Cradle System. The computer mounted male LIF may be weather proofed, the cable mounted female LIF cannot. Currently the LIF connector cover can be moulded with a polarising pin in one of two positions. The facility exists to manufacture the cover with the polarising pin in two more positions, giving four possible variants. If more than four versions are required it is possible to have the cover and the socket bezel moulded in a range of colours to differentiate between variants. The polarising options are presented below:

Pin numbers 1st (1 GROUND 9 2nd (________] SIGNALS 2,3,4,5,8,10 1,6,7,11

The step arrangement of the LIF Connector pins

Cable mounted LIF (Female plug) Computer mounted LIF (Male socket)

Revision 1.00 Page 14 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

3S 310

@e0000 08 ODOOOO

Cable mounted LIF (Female plug) Computer mounted LIF (Male socket)

Type A and Type B polarisation of the LIF Connector

Revision 1.00 Page 15 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Pin Definition for LIF - PFS Connector LIF Connector Polarisation Type B

Pin Pin Name Wire Colour Contact Direction Standard Function Cradle usage No Gauge (Cradle's perspective)

1 LCA 710.1 Brown third Input Local’ Computer Active. High when the Used as an enable for the cradle computer is on. (The Workabout can source resident Xmod 5V supply. 100mA from this pin and the HC/HCDOS 5mA to power remote circuitry)

EXON 710.1 Blue second Output EXternal switch ON, active high (+5V). May be asserted by a cradle resident Asserted by a remote” device to switch on Xmod. the computer. Xmod.

se He 1 a eee eet Battery thermistor terminal. Allows remote“ function eae of the battery temperature.

meal 1 Bead ie Output Disconnect Local” ASIC, active high (+5V). Asserted by the Cradle ASIC, (does not apply to Workabout). When this connects the cradle resident Xmod to signal is asserted the serial channel is the serial channel. disconnected from the local? ASIC4/5 in the HC resident Xmod (if present) and instead connected to a remote ASIC4/5 (if present).

FN Te | 7 | vin | 28SwG Power supply to computer (+10V) | 8 | SCLK 710.1 | SerialchannelCLocK.

GND 28 SWG White “fiat Power, [Seval channel Chev —_____ ground and -ve battery Standard function terminal (1 amp)

SDATA 710.1 Serial channel DATA.

11 STATUS 710.1 Pink third Cai STATUS. Connected to a pull-up resistor to Driven low by an open collector driver allow connection to an open-collector/drain when LCA is high and the cradle is driver. Normal usage is: low indicates the powered-up to allow the computer to presence of a remote” device. sense whether or not the cradle is

connected.

LIF Connector Polarisation Type A

Pin Wire Colour Contact Direction Function No eine Gauge (Computer's perspective) ee oe RS2I2 signal a a RS232 signal

77 Output | RS232 signal THERM [7101 [Yellow [ second_[ =] Battery thermistor terminal

[svar [2sswo [Red [tind [- | tvebattery terminal ——SSSSSCSCSCSCSCSCSCSCC~C~* [3 [pe 701 [Grey [second [Input [ RS232signal OSS [9 [exp eswo [white [fist [= | Power, signal ground and ve battery terminal —____——SS—~S

Definitions

Computer HC, HCDOS or Workabout

Cradle resident Xmod Expansion module fitted to the cradle, may or may not be present.

HC resident Xmod Expansion module fitted to the HC, which contains the cradle interface and possibly another peripheral. HC peripheral A peripheral, located in the HC resident Xmod which is connected to the same serial channel as the cradle. Cradle ASIC An ASICS located on the main cradle PCB which remains connected to the serial channel

irrespective of the state of DLA.

1. | The term "local computer" implies the computer local to the LIF connector, i.e. the HC, HCDOS or Workabout, as opposed to a "remote" computer which might be connected via a cradle resident Xmod for example.

2. The term "remote" implies something on the other side of the LIF connector to the computer.

3. | The term "local" implies something on the computer side of the LIF connector including devices on an HC resident Xmod.

Revision 1.00 Page 16 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Exploded view of the Psion Workabout

Below is an exploded view of a complete Psion Workabout showing part numbers for various components and illustrating the positioning of the expansion interfaces.

4 g y o # ” 4 a § 8 Ss 8 4 gy Fa i f a Of i a 8 a a a « a 2 8G Roo ae 38 a3 3 a @ ¢ me oON Sgt 3 ROS a 3 g ® S +8 Be $3 $s $8 a 8 28 = o j z a 3 a3 F | 8 a 4 9 Boa ey 3 a a 9 3 a g 4g 1 o & & a9 3 4 2 # 8 . p 3 3 zh ae 6 ¢ a 3 i 3 f é i 3 " 3 a8 a 8 2 3 § goa 3 BS g a 8 Poa 3 5 : a 8 a 9 a oF a + & § ff 42 Oo oN bos ng a 3 al a «38 i hoon 2 8 > f 9° a 38 ag eg 2 as & a $3 Gc @ aa 4 a og 3 4 o § 8 g 8 & g 3 a a S$ 0 y 8 3 4 8 d 1 a 3 ages a Be, gy ee! 8 g 3 ae a 3 8 & 4 9 2 3 p t ° ib a oO © 3 Re eS 3 y § 3 4 3 3 ae oe: n oc = «© x » zg a3 xg é a3 28 4 a 3 6 4 4 s 3 ¢ 2 3 os 3 a a 8 § a 4 hoa gs 4 $ 3 ROS * § a & aoa g g 8 i 3 a 3 5 3 3 i rf g Son 8 38 4 og F 2 9 * 3 8 a a 4 j 4:8 8 ‘ a5 3 a

Revision 1.00 Page 17 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

The Psion HC range

HC Extended Internal Expansion Port

The Psion HC range of computers are intended to provide a rugged and powerful mobile computer system for a wide variety of demanding application requirements. As part of its adaptability, every element of the hardware is configurable from the plug-in SSDs to the expansion ports for peripheral devices such as bar code scanners, modems and magnetic card readers. There are two independent extended internal expansion ports at either end of an HC unit. The top port is termed the "A" port and the bottom one the "B" port. Each expansion port provides direct I/O with the processor, a SIBO serial channel, and connection to the power supply. It allows for higher powered expansion devices to be added by including a direct connection to the main 7.2 volt battery.

Physical Connector

The expansion port is made up of a 25 way single row connector spaced on a 0.1 inch pitch. The 26th position is a polarising key and should be left blank. The correct mating connector on the expansion device is made up from a number of Molex C-Grid series 90148 connectors. Pins | and 2 are ground and should have there own connector placed nearer the board edge to ensure the ground connection is made first when the expansion device is inserted. The required connectors are Molex 90148-1102 for the GND contacts and Molex 90148-1123 for the signal contacts. The diagram below shows the physical position of the connectors.

=$f ene 98148-1182 3

Se : EXPANSION D =e

sad Abe COMPONENT SID

fet

feu) HHDE eorn AEM on

38148-1125

raftats afte + [o}:o loo) en] Heonwnm Zuaorom Scteorn aa ne

raftofea Lsfosfra wn Ox ol Fr!

wi Zo OR

ge

voce (SPACE?

SIBO COMPUTER

Revision 1.00 Page 18 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Signal definition

The following table defines the 25 way expansion connector:-

Pin No. Name _ Sig. type Comments

GND Power Should mate first when device inserted

GND Power Should mate first when device inserted

ADO BCMOS 8 bit multiplexed address and data bus pulled low with 100 K resistors ADI BCMOS

AD2 BCMOS

AD3 BCMOS

AD4 BCMOS

ADS BCMOS

AD6 BCMOS

AD7 BCMOS

ALE OCMOS Address latch enable - high when valid address on ADO-AD7

IOWR OCMOS I/O write strobe - active high, data valid on falling edge of IOWR IORD OCMOS I/O read strobe - high when device can place valid data on ADO-AD7 EES OCMOS External Expansion Select - high during I/O cycles to expansion device SCLX TCMOS 512 KHz SCL signal for SLD bus - usually Hi-Z and pulled low

DNC N/A For future expansion - do not use.

THERM Resistor Connected to thermistor (bottom slot only - top slot DNC)

VBI Battery Connected to the internal NiCd battery (bottom slot only - top slot DNC) Vsup Power Unregulated battery voltage - present all the time

INTR ICMOS Active high interrupt input

_EXON ICMOS Active low input pulled up to Vccl - pull low to switch machine on

SD B CMOS SIBO serial protocol data line - pulled low

SCLK TCMOS SIBO serial protocol clock line - Hi-Z in standby needs a pull down GND Power

Vcc2 Power +5 volt supply, switched off in standby. Max current available = 50 mA

AADNKRWN KH

DNC (Do Not Connect) indicates that the pin should not be connected. The signal types are:-

O CMOS CMOS output to the expansion device.

B CMOS CMOS bi-directional line to the expansion device. T CMOS CMOS tri-state output to the expansion device.

I CMOS CMOS input from the expansion device.

All the CMOS signals including the ADO-AD7 bus are buffered from the main system busses and so present a load of one HC series logic gate.

Direct I/O

Expansion devices can be connected to direct processor I/O space using the following signals; ADO- AD7, ALE, IOWR, IORD, EES and INTR.

ADO-AD7 is the least significant half of the multiplexed address and data bus, this means that up to 128 I/O addresses are available for each expansion device. As only the least significant half of the bus is available and no bus conversion is done only even addresses can be used.

ALE must be used to latch the address from ADO-AD7 for devices that require a stable address. The address is valid on the falling edge of ALE. Note that AO will always be low for valid writes to the expansion device and as such should not be used as an address line, Al should be used as the lowest order address line. AO can be used as an additional enable signal to stop odd I/O accesses disturbing the expansion device.

EES is the External Expansion Select and is high during all I/O accesses to the expansion device, i.e.

for I/O reads and writes to address range 100 to 1FF hex. for expansion port 1, and 200 to 2FF for expansion port 2.

Revision 1.00 Page 19 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

IOWR is an active high signal which is high during all I/O write bus cycles. The data on ADO-AD7 is guaranteed to be stable before the rising edge of IOWR and after the falling edge of IOWR. IORD is an active high signal which is high during all I/O read bus cycles. The ADO-AD7 bus is guaranteed to be tri-state before the rising edge of IORD and after the falling edge of IORD. The expansion device must present valid data on the bus when IORD is high, see the timing details below.

INTR is an active high interrupt input to ASIC1. T his can be used as a directly readable bit or as a dedicated interrupt input. It must not be driven high when the system is in the standby state as this input is pulled down and will cause excessive standby current consumption. The diagram below shows the timing of the I/O write and read cycles.

T/0 WRITE CYCLE

ADS-ADT VALID ADDR

VALID WwW

QOD

FES q_Tadstp _ plyTadhidy,

| Tudstp | Tudhld |

IYO READ CYCLE

ADS-ADT VALID ADDR>

} Tadetp fel adhd ,,

| Thztd Trdste Trdhid

Parameter

Address set up time Address hold time Write data set up time Write cycle pulse width

Write data hold time

Time from Hi-Z to data active Read cycle pulse width

Read data set up time

Read data hold time

Note the typical values given are for an HC with a system oscillator of 7.68 MHz.

The SIBO serial channel

A single SIBO serial protocol channel is provided on each expansion port. Expansion port | is connected to serial channel 5, expansion port 2 is connected to serial channel 6. The serial channel clock can be continuously enabled to provide a free running clock for expansion devices. The frequency is fixed at 1.536 MHz regardless of the system clock frequency. This frequency is a multiple of the SLD clock rate and of all normal RS232 baud rates.

High Speed Side Port

Port C on an HC houses an 8-pin in-line connector that allows access to a high speed SIBO serial interface. This interface is currently used only by the HC cradle peripheral. Its pin-out is outlined in the table overleaf:

Revision 1.00 Page 20 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

[Pin | Signal | Type | Description,

fo | Sb7_ | InOut__| Bi-directional Serial Data line- Side portC [8 TSEN Input Battery temperature sensor

Power supplies

Two power supplies are available for expansion devices these are Vcc2 and Vsup. Vcc2 is a +5 volt supply that is derived from Vsup. Vcc2 is switched off when the system is in the standby state and is switched on when the operating or idle state is entered. Each expansion device can draw up to 50 mA from Vcc2. If an expansion device requires more than 50 mA or cannot be powered down when the system is in the standby state the Vsup power supply must be used. Vsup is the unregulated supply directly from the main system batteries or from the DC jack input. It will be in the range 5.5 to 12 volts under normal conditions. To use Vsup the expansion device must regulate Vsup to 5 volts with a low drop-out linear regulator. Care must be taken to not be active and driving any signals high when the system is in the standby state as Vsup is always present. This can be achieved either in software or by using Vcc2 as a signal indicating the active state.

Mechanical Information

Mechanical details regarding the numerous build variants and accessories that currently exist for the HC are presented overleaf. The peripheral expansion boards for these build variants are housed in a special plastic casing that can be machined to hold the requisite connectors. In the matrix, ae indicates that the relevant combination of HC and accessory are compatible and an X indicates that the combination is not compatible. Following the build variant table are two diagrams that display exploded views of the HC expansion connector and the HC Expansion Board complete with part numbers and dimensions.

Revision 1.00 Page 21 of 115 pages

The Psion SIBO Hardware Development Kit

Build Variants

With EL Backlighting Without EL Backlighting

Industrial

Non-Industrial

Keypad Variants

53 Key A/N UK 2401-0026 A/N European 2401-0051 A/N Scandinavian 2401-0050 Numeric only UK 2401-0046 DOS Keypad 2401-0147 53 Key A/N USA 2400-0026 HC Expansion Modules

RS232 / Parallel (Printer) 1502-0001 25 way D type (F) + 9 way Mini DIN Certified FCC Class B / Passed VDE Class B

RS232 / TTL

1502-0039 (IP64), 1502-0040 (NON IP64)

9 way D type (F) + 9 way D type (M)

Passed FCC Class B / Passed EN55022 Class B

UK Modem (Asic 8) 1502-0010 RJ 11 connector BABT Approved in UK, BS6301 (Safety)

Barcode Only

HP Wand HBCS-A207 + Plug + EXMOD 1502-0020 Wand Welch Allen + Plug + EXMOD 1502-0021 FCC Class A/ Passed VDE Class B

RS232 / Barcode 1502-0044 9 way D type Quick Loc(F) + 9 way D type (M) Complies with FCC Class A

MCR / Scanner / RS232 1502-0003 Scanner NipDenso + Plug 1502-0022 Scanner DigVision + Plug 1502-0023 Magnetic Card Reader + Plug 1502-0024 Certified FCC Class B / Passed VDE Class B

LIF / RS232 (Under development) 9 way D type (M) + 9 way LIF- PFS (M)

LIF / TTL (Under development) 9 way D type (F) + 9 way LIF- PFS (M)

LIF / BARCODE 1502-0043 9 way D type Quick Loc(F) + 9 way LIF- PFS (M)

Vehicle / TTL 9 way D type (F) + 9 way LIF- RS232 (M)

16550 RS232 / TTL (Under development) 9 way D type (F) + 9 way D type (M) Complies with FCC Class A

Printer (High Res.) 1502-0037 Laser Scanner 1503-0012

Fast Charger Variants

Fast Charger with Holster (Due Jan 95) Fast Charger without Holster (Due Jan 95)

Additional Accessories Nicad Battery Pack 500 mA 1503-0005

Revision 1.00

Psion PLC (c) May 1995

CHARGER

a a a Ee i ie IE a a ee ee Re ca Da ca

ans he ae Ss eee FS a a a a

Page 22 of 115 pages

Psion PLC (c) May 1995

The Psion SIBO Hardware Development Kit

Corporate Hand Held (CHH)

Expansion Module Exploded Assembly Drawing

(yovig) Sso0-zoz9

(USENNN LYVd YSLINO OSTY) (A3N9) £000-20z9

YANVIG NOISNVdX4d 138V1

(440 2) 2000-z0¢g WSO IZOd WWOXZZ% MINIS

(OV1E) 9107-2018

(AJN9) 9101-2018 ONITINOW Y3LNO NOISNVdxX3 OLS HHO

(wov1d) $10Z-Z018 (AIUD) SLOL-ZOL8 ONIGINOW YSNNI NOISNYdX3 HHO |

6000-0072 ANVIG dd

SNOISNSNIG YSLLNS ANVIG NOISNVdX3 138V1

Page 23 of 115 pages

Revision 1.00

Psion PLC (c) May 1995

t

The Psion SIBO Hardware Development

QrOr o22 ILD :xW4 008! 802 120 “7131 1G) HIM

NOONOT N/OIl

AS 18NOQYVH 61-21 Jd NOd

MSV LENOd Ni dl JNWOS ION OG

(SOs 2) ONDOEL =O w300 34 OL G3U0Y vey

26,

94 01 GMQy SFI NOILWOOT

26/1/91

Sa @ SINSNOGNOD 40 wa) 38 OL G200V vw

26/0178

‘Gadd NOWOWISIS AHOIBH LN3NOEWOD W207

06 /c0/zal

108 X3T0K a300¥ $89 8ou93~N09

oss 9792

SSI Sas

SONVHO,

SmAOVd NOISNVdx4

SH T1¥ A044 GssyINGS

NOILYWAOSANI 4H

L SMOHS SONIMVAC Sit

LH513H LN3SNOdWOD X¥W ONIMOHS 311 408d

216

cay) Y_NOISN3WIC

C30N31LX3

CAVONVLS

JdWwOS aNv

qa.0N3d vaav

A11V901 NO3IaLS34

COMPONENT HEIGHT RESTRICTION

(SEE PLAN VIEW)

(SOd 2) ONIMDVYL ANY WOS4 3384 38 O1 voav

CAVA 92 WiOL) SYOLO3NNO9

LTO

SOd 2) SIN3NOdWOD ANY WOSs 3384 34 OL vaav

: @szaze @ S3143S 8y106 X370N

a2

4.5 BOTH SIDES

1 | 31.75 CRS l 31.75 CRS

Page 24 of 115 pages

Revision 1.00

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

6. ASIC 4

What is ASIC 4?

ASIC4 is custom integrated circuit designed for use in Memory Packs (called SSDs) and peripheral devices. Its primary purpose is to convert the PSION Serial protocol into the signals required to address memory and memory-mapped peripherals. A typical Series 3/3a ASIC4 peripheral will consist of an ASIC4 connected to port C of the host machine and a peripheral chip/device mapped into ASIC4's addressing space. An example could be an ASIC4 connected to a simple 1k memory device:

Chip select

To write a value, <v>, to address <addr>, the appropriate control codes must be sent along the port C Psion Serial link to assert <addr> on ASIC4's address outputs and <v> on ASIC4's data outputs.

ASIC4 Addressing and Modes

ASIC4 has an 8 bit data bus and a 28 bit address bus. Also provided are eight chip select lines that form selectable addressing blocks each of a size defined by software. The default is 32Kbyte/block. The filing system will set this to the appropriate size while accessing memory in the upper portion of the address space.

ASIC4 has two basic modes of operation, namely ASIC5 Compatibility (or SSD) mode and ASIC4 Extended mode. To select the mode, ASIC4 must be selected with an appropriate ID. This is achieved by writing a SIBO serial protocol slave control frame, as detailed in chapter four, to the ASIC prior to sending any read or write requests. After sending this frame, the so-called Info Byte is read off the data bus. Details concerning the meaning of the various Info Byte bits are provided in the following section. In the case of SSD mode, the ID is 2 and for ASIC4 Extended mode, the ID is 6.

Putting ASIC4 into SSD mode makes the chip compatible with all current versions of existing SSD software in production by Psion including all HC, series 3/3a and MC software. In this mode, ASIC4 mimics an ASICS in pack mode (see next chapter). This is because ASIC4 was originally designed to be a cut-down version of ASICS and so from the outset it was necessary to make previously existing ASICS software run on the new chip. The maximum address space in SSD mode is 21 address bits and 4 chip selects (which comes to 4 x 2Mb). In ASIC4 Extended mode, ASIC4 is capable of addressing up to 28 address bits (256Mb). In this mode, in addition to the Info Byte, a further 4 bits of information can be elicited from the state of the address lines A27-A24 during reset. Of these bits, the state of A27 (bit M) determines whether ASIC4 is going to be used as a standard SSD (M=0) or in a mixed mode (M=1) comprising of memory devices and peripherals. It is only the latter case which is of interest to the potential developer since this is the mode intended specifically for peripheral type expansion. In mixed mode ASIC4's address space is split into two equal halves. The lower half of the addressing range is set aside for memory-mapped peripherals and can be used for any purpose. The upper portion of the address space is reserved for pure memory. The Series 3/3a, Workabout and

Revision 1.00 Page 25 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

HC filing system is able to use this memory (which does not have to be present) as an additional storage medium. Typically it will be a ROM containing the software that controls the peripheral. On reset, configuration data is supplied to ASIC4 on its data bus lines which the filing system can read in order to determine what form of and how much memory it has available in this upper region.

In mixed mode chip selects are split into four selectable peripheral blocks and four selectable memory blocks. CSO-CS3 are for peripheral access. CS4-CS7 select memory devices one to four. This set-up is illustrated below:

Peripherals S1 $2 $3 Total Addressing S4 Range Memory (256Mb) SS S6 S7

Reset and configuration

As indicated earlier, in mixed mode, following a reset or power up ASIC4 will read the form in which to configure itself from the data on data lines DO-D7 (the Info Byte) and address lines A24, A25, A26, A27 (most significant nibble of the Extended Info Byte). The table below shows the meaning of each of these lines during reset.

| A27 | A26 | A25 | A24 | D7 | Do | Ds | D4 | D3 | D2 | Di | DO |

Don't care, some 000 RAM 00 1 device No memory codes are reserved. | 001 Typel Flash | 01 2 32Kbyte 000 No peripheral | 010 Type2 Flash | 10 3 64Kbyte

001 T3Link 110 ROM 114 128Kbyte 010 3Fax 256Kbyte Contact Psion for 512Kbyte an official code. 1Mbyte

Pull up, pull down resisters would usually be used to place these lines in the desired state on reset. High value resisters of typically 100k would be used to allow ASIC4 and bus devices to drive these lines to other levels during normal operation.

ASIC4 should be powered from its host Series 3/3a/HC. High current peripheral chips or volatile memories should have their own supply. Whenever the Series 3/3a/HC is powered down, has its batteries removed, or has it's pack doors open, any attached ASIC4 will be powered down and reset upon resumption of power. Taking the 3Fax as an example with one Read Only Memory device of 512k the required configuration is:

Revision 1.00 Page 26 of 115 pages

The Psion SIBO Hardware Development Kit

ASIC4 Pin-out

Pin No Pin Name 50 DO 49 D1 48 D2 47 D3 46 D4 45 D5 44 D6 43 D7

13 AO 12 Al

11 A2

8 A3

7 A4

6 AS

5 A6

4 AT

3 A8

2 AQ

1 Al0 64 All 63 Al2 62 Al3 61 Al4 60 Al5 29 Al6 28 Al7 27 Al8 25 Al9 24 A20 23 A21 22 A22 21 A23 20 A24 19 A25 18 A26 17 A27 37 CSO 36 CS1 35 CS2 34 CS3 33 CS4 32 CS5 31 CS6 30 CS7 16 OE 14 WR 15 VPS 39 POR 40 SCLK 38 SDAT 59 SDIR 51 LBO 56 MCSD 52 INO 53 INI 54 IN2 55 X2D2 57 ATST 10 VDD 42 VDD 9 GND 26 GND 41 GND 58 GND

Revision 1.00

Direction VO vO

fe)

~*=“O0O000000000

fo)

PWR PWR PWR PWR PWR PWR

Pin Description

Databus

Databus

Databus

Databus

Databus

Databus

Databus

Databus

Address bus - register ATO Address bus - register ATO Address bus - register ATO Address bus - register ATO Address bus - register ATO Address bus - register ATO Address bus - register ATO Address bus - register ATO Address bus - register AT 1 Address bus - register AT 1 Address bus - register AT 1 Address bus - register AT 1 Address bus - register AT 1 Address bus - register AT 1 Address bus - register AT 1 Address bus - register AT 1 Address bus - register AT2 Address bus - register AT2 Address bus - register AT2 Address bus - register AT2 Address bus - register AT2 Address bus - register AT2 Address bus - register AT2

Address bus - register AT2/Oscillator Output in PSPRAM Mode

Address bus - register AT3 Inputs to set device size on reset Address bus - register AT3 Inputs to set device size on reset Address bus - register AT3 Inputs to set device size on reset Address bus - register AT3 Inputs to set device size on reset Device chip selects

Device chip selects

Device chip selects

Device chip selects

Device chip selects

Device chip selects

Device chip selects

Device chip selects

Output Enable/Refresh in PSRAM Mode

Write pulse

VPP control

Reset input

Serial clock input

Serial Data input

Protocol Direction indication Bit

Low Battery detect driver output (Open drain)

PSRAM Mode Select

General Purpose inputs

General Purpose inputs

General Purpose inputs/Refresh Disable in PSRAM Mode Oscillator Input for PSRAM Mode

Test input (pull high to put device into address test mode) Power inputs

Power inputs

Ground

Ground

Ground

Ground

Psion PLC (c) May 1995

Page 27 of 115 pages

The Psion SIBO Hardware Development Kit

A11 A12 A13 A14 A15 SDIR GND ATST PS OSCIN IN2. IN1 INO LBO DO D1

- LU Li Lt Ly ae L Ls LI Li

62 61 60 57 56 54 53 52 51

64

A10 48 D2 AQ 47 D3 A8 46 D4 A7 45 D5 A6 44 D6 AS 43 D7 A4 42 VDD AS ASIC4 41} —J GNo

GND 40 SCLK VDD 39 POR A2 38 SDAT Al 37 cso AO 36 cs1 WR 35 cs2 VPS 34 CS3 OE 33 cs4

17° 18 «#19 20 21 22 23 24 25 26 27 28 29 30 31° 32

Rigizipininigiolgipinipimdeig

A27 A26 A25 A24 A23 A22 A21 A20 A19 GND A18 A17 A16 CS7 CS6 CS5 OSCOUT

Diagram of ASIC4 Pin-out (NEC)

Revision 1.00

Psion PLC (c) May 1995

Page 28 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

7. ASIC 5

What is ASIC 5?

ASICS is custom integrated circuit designed for use in Memory Packs (called SSDs) and peripheral devices. ASICS provides three primary functions. A built in UART provides for serial communication at baud rates of up to 48000 baud. General purpose I/O pins provide for a wide range of control and communication applications. Finally ASIC5 provides address and data lines for access to memory devices and memory mapped peripherals. A typical ASICS peripheral such as the 3Link consists of an ASICS connected to port C of a series 3/3a, a ROM memory device mapped into ASICS's addressing space and line drivers to convert the UART signals from ASICS into standard RS232 levels.

Chip select

ASIC5 rea Memory

RS232 Line Drivers

Psion Serial link

ASIC5 Modes

ASICS can operate in two modes. In pack mode ASICS generates all the address, data, and control signals necessary to access memory devices. No peripheral functions are available in this mode. In peripheral mode ASICS has only limited memory address capabilities as some or all address and control lines are reused for I/O purposes. ASICS is placed into peripheral mode by setting the peripheral bit in ASIC5's PBMODE register.

ASIC5 as a UART

ASICS contains a full function UART which supports baud rates of up to 48000 bits per second. In order to use ASIC5 as a UART, ASICS5 must be placed into peripheral mode. In this mode the input signals PAO, PAI, PA2, PA3 become the UART inputs RX, CTS, DSR, and DCD respectively. The output signals PDO, PD1, PD2 become the UART signals TX, RTS, and DTR. Serial data is transmitted from the TX line. Incoming serial data is received by the RX line. RTS and DTR can be used for handshaking or as general purpose outputs and need to be set high or low explicitly by software. CTS, DSR, and DCD can be used for handshaking or as general purpose inputs.

The Psion SIBO serial link which connects ASIC5 to a host computer is a two wire interface consisting of a data and a clock line. ASICS generates it's baud rate clocks from this clock line. Under normal operation, clock pulses along a Psion SIBO serial link only accompany data frames. To be able to generate baud rate clocks ASICS requires a steady clock from the Hosts Psion port. To facilitate this, Psion serial links can be put into a mode called continuous clocking where clock pulses are generated regardless of whether there is any actual data to be transferred. Continuous clocking

Revision 1.00 Page 29 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

increases power consumption and Psion serial links should not be left in this mode unnecessarily. The UART portion of ASICS is capable of generating interrupts when characters are received, when the transmitter is awaiting a character to send and when there is a change of state on the handshaking lines. ASICS has only one, active high, interrupt line. This line is shared between these interrupt sources. When an interrupt is generated it is the responsibility of software to determine the cause of the interrupt.

A character to be transmitted should be written to the Transmitter Holding Register where ASICS will convert it to serial form for transmission. The register will be emptied once the character has been transmitted. ASIC5 contains no internal buffering. The Transmitter Holding Register must be empty before writing a character to it. The state of the Transmitter Holding Register is reflected in the Transmitter Empty bit in the UART status register. Enabling the Transmitting Holding Register interrupt will cause ASICS to generate an interrupt every time that the Transmitting Holding Register becomes empty. Reading the UART Status Register will clear the interrupt. Received characters are copied into the Receive Character Register. If the Receive Character Interrupt is enabled, ASICS generates an interrupt on each character received. If the character is received in error due either parity, framing or overrun errors, appropriate bits in the UART Status Register are set to reflect this.

ASIC5 for parallel I/O

Lines PAO-PA7 form a general purpose, non latched, 8 bit input/output port. All access to this port take a total of twelve clock cycles. The clock is generated from the Psion Serial Link. Actual memory access cycles only last for one clock cycle. Twelve cycles are required because data being sent or received needs to be converted to or from the Psion serial format. Because of the conversion read accesses occur on the third cycle, write cycles on the twelfth. This is usually of no real consequence to the peripheral designer

In peripheral mode CSO will be taken low for one clock period each time Port A is accessed. Data outputted from this port will remain valid for only the period that CSO is low. In pack mode Port A forms the data bus in memory mapped systems. A read from or write to Port A in this mode will result in one of the lines CSO-CS3, being taken low for one clock period. The line which will be taken low will depend on the address being generated for the access. During read cycles OE line will be taken low and remain so for 10 cycles. Data present on PAO-PA7 must remain stable for the last nine cycles. During write cycles the WR_B line will be taken low for the second half of the cycle over which one of CSO-CS3 is low. If port B is set to counter mode, accessing port A will result in the counter being incremented upon completion of the access.

ASICS can be programmed to generate an interrupt whenever the state of line PA4 changes. Reading port A will clear this interrupt. One use of PA4 is as the BUSY line in a Centronics port implementation.

The Lines PBO-PB7 can be programmed to operate in four different modes. Two of these modes are for testing purposes and will not be discussed further. In latched mode, data written to the Port B resister is latched onto the Lines PBO-PB7 and will remain there until a following write to Port B or a reset condition occurs. In counter mode, the binary value on lines PBO-PB7 is incremented following any access to port A. With ASICS in pack mode lines PBO-PB7 form the address lines AO-A7. Placing port B into counter mode allows 256 consecutive memory locations to be read without need to set-up the address of each access.

Lines PDO-PD7 are general purpose outputs. In pack mode these form the address lines A8-A15. In peripheral mode lines PDO, PD1, PD2 become UART outputs.

Lines PCO-PC4 in pack mode form the address lines A16-A20. In peripheral mode lines PC4 and PC7 become inverted inputs and can be used as edge triggered interrupt lines. PC5 becomes the interrupt output line. PC6 becomes a general purpose latched output. PCO-PC3 become a dual synchronous serial port for use in magnetic card systems.

Revision 1.00 Page 30 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

ASIC5 for Barcodes

Psion barcode peripherals use the UART functionality of ASICS to receive data from a dedicated barcode scanner IC.

ASIC5 for Card readers

Magnetic card readers generate clocked serial data. ASIC5 contains two synchronous serial ports for connection to card readers or other peripherals which generate clocked serial data.

Reset and configuration

Following a reset or power up ASIC5 will read the form in which to configure itself from the data on data lines PAO-PA7. Line PC6 is used to select whether ASICS is to operate in pack or peripheral mode. The table below shows the meaning of each of these lines during reset. In peripheral mode lines PAO-PA7 should be set to give an indication of the type peripheral the ASICS is forming. combinations of types can be used.

000 RAM 00 1 device No memory

001 Typel Flash | 01 2 32Kbyte

010 Type2 Flash | 10 3 64Kbyte

110 ROM 114 128Kbyte

1 1 1 Write protect 256Kbyte 512Kbyte 1Mbyte

Peripheral Mode Type

RS232 port Centronics (Parallel) port

Hx KK KK XX xo KKM KK XX

0 0 0 0 0 0 0 0

Pull up, pull down resisters would usually be used to place these lines in the desired state on reset. High value resisters of typically 100k would be used to allow ASICS and bus devices to drive these lines to other levels during normal operation.

ASICS should be powered from its host Series 3/3a, Workabout or HC. High current peripheral chips or volatile memories should have their own supply. Whenever the Series 3/3a/HC is powered down, has its batteries removed or has its pack doors open, any attached ASICS will be powered down and will be reset upon resumption of power.

Revision 1.00 Page 31 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

ASIC5 Pin-out

A10 Ali A1l2 Ai3 NC A14 A15 DO D1 D2

DONO o net

ASIC5

14 15 16 17 18 19 20 21

MAMAMAAMMo

WR VPS OE A20 A19 NC A18 A17 A116 CS3 CS2

ASIC 5 current pin-out (TI version CF30179)

Revision 1.00 Page 32 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

8. EXAMPLE PERIPHERALS

The ASIC4 Example Interface Board

The ASIC4 Example Interface Board detailed in this chapter is intended to provide the developer with a simple example of a Psion ASIC4 peripheral. To this end, the actual practical usefulness of the hardware is of secondary importance. In fact, the board essentially consists of eight LEDs connected via some latches to an ASIC4. Using a device driver, the host machine is able to control the status of the LEDs. Specifically, the board translates SIBO serial protocol signals into a parallel 8-way data bus format that can be used to set the various 74HC series latches and gates. It is intended that the board can be readily adapted to run on all currently available Psion machines. The only physical change that need be made concerns connection to the host machine's external expansion interface.

In the following circuit, an eight-bit tri-state data buffer, U3, and an eight-bit output data latch, US, are commoned together to the eight LEDs thereby enabling their status to be sensed and set. In addition, a facility for generating hardware interrupts is provided by means of a suitably connected switch, S1, and a third eight-way buffer, U4. U4 is the interrupt switch status buffer. It holds the values of the two input switches S2 and S3 which are read as part of the interrupt service routine. Depending on the value of the switch positions, a different response can be output to the LEDs from the set buffer, US. One of the D-type flip-flops in U6 is used to latch hardware interrupt signals into the INT line (pin 5) of the reduced external expansion interface connector. On completion of the interrupt routine code, it is necessary to reset this flip-flop and hence the interrupt hardware by means of a write to address Al. Address decoding is provided by two 2-to-4 decoders on chip U1 paralleled to address lines AO and Al. A circuit diagram of the ASIC4 Example Interface Board is presented overleaf for the case of a host S3a.

Note that it is possible to construct this circuit with or without the compiled driver code in an on- board ROM. The developer merely has to set the resistors on the three data bus lines DO-D2 such that the corresponding info byte conveys the appropriate information. The meaning of the various bits in an ASIC4 info byte was discussed earlier in chapter 6. If a ROM is to be used, then the info byte read off DO-D7 on reset should include bits 001 on lines D2-D0. This requires the R1/R2 optional resistor to be connected to Vcc. If a ROM is not used, as was the case with the constructed test circuit, the data bus lines D2-D0 should be set to 000. This is done by choosing the resistors connected to ground from the three R1/R2, R3/R4 and R5/R6 pairs.

Revision 1.00 Page 33 of 115 pages

Psion PLC (c) May 1995

The Psion SIBO Hardware Development Kit

VOD voc voc voc voc 3 cs ca cio _|+ caa For 128K Bute ROM fit option resistors Ri, R4, RG, RE and Rio eibe idon toon ioon Our evs For no ROM fit option resistors RZ, R4, RE bo 2 ue ve ve as VOD SNC GND GND GND 1 3 Xf RE-/R4 vor GND res Di 2g 100K ag voo | 338 bo = ae base es Do Di 14 Bd 1 AS Bi DE Be be (45 De veo DS ce be Cie mE v Biel Da 18 ba SNC oS aé ba Te DS az BS R22 [ery AS be 20 [T= 3 100K Br aS BS [ei isk RE RE aio fa 100K ort ze | 22 bz z Al2 ails oe [24 7 ate 1 aaa oe awe hae Aiz L ae GND eto nigga | ao vor voc ZEK—ine ROM DS R16 100K Ss Is RT-RE RS/RL0 vos z z 7 FaHcT4a ja oR oR R26 Rea 100K 1 1 DF R20. 100K LooR GND GND Ree SND aoe t R27 ba voc LED GND CONNL sp7 bo * 0 sck7 b-# = Bo 18/ivi = 1ai +329 = Di is a_i LED ND sDSs/INT iv2 0 1Az SCKS/“EXON a Wie D2 14 is. 1AS & P2 z z Ds iz = Ps Wor * a vo ava iaa 4 z bas ii_F4 She , a. be revi 281 Ge re LED GND YE 2Yz ZAz CON COMMS CONN be oer te be S| S02 282 (re Pe bre) S)5: Soy bere FPS4HC1sg GND te het LED GND vor 28 brs DL uza 1 OE 4 ae FaHceas FaHCETS z 3 ORD LED ND 2 cso 2 FaHca4d A t ua WF Baves clr Se T4Hese DO 18 Tyg LAL GND 1006F El tel ge: {ee LED GND 1B a De 14 ive 9 1az Mee Nf 14) 4 vo BS tetiva iad D2 GND U2B is ba 3 B vi Zvi ZAL 4 WR 4 oS + LED GND Y2 2vz BAZ = 6 Lor 15 bss Gc YS 2yYe 2As =P = Dre 3/oy4q Baa FaHCLss yo OBAYSS FaHese ee 470 LED GND GND Vos a Si voc ¥ v vos J" GND SND DATA OUTPUT vor FaHCe44 DOS la Us6Al Lk Interrupt Sw a: = Ne Saal = a B Db 2 CC? 1993 (PSIOS PLS. aa ADDRESS R-M FUNC 3 Interrupt In + Bava fal RYH Read & write to latch SLK Eiki Sp ee) omnes GND rs Md Clear Interrupt els; = R25 1 R Read status 100K Poe REY : oO status Bit Func F4HCr4 Title a Ineut a L Tneut 1 > ASICS Example IF 2-5 Not Used GND GND Size Pocument Number REV 6 Interrupt Line B 7 lo.s ? Interrupt Latch : Date: Aerial 19, 1995|[Sheet i_of Z

Page 34 of 115 pages

1.00

1S10n

Rev

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

The Psion 3-Link

The Psion 3-Link is an ASIC5-based peripheral that enables the user to transform SIBO serial protocol signals into RS232 format data so that a host Psion machine can communicate with a PC or printer. The diagram below shows the schematic of a TTL level RS232 based expansion device. The interface is based around ASICS and allows the standard RS232 device driver contained in EPOC to be used.

Transistor Q1 provides a switched power rail for any other expansion device. This rail will automatically be switched off when the RS232 port is closed. D1 is required to isolate the supply so that the external device does not back power the SIBO computer when it enters the standby state. If the additional device does not require a supply or only uses a few microamps then Q1 and D1 can be omitted. Vcc and the supply for the expansion device can be directly connected to Vcc2.

If CMOS level RS232 signals are required then IC1 can be replaced with a 74HC244 device. If inverted sense RS232 signals are required, IC1 can be replaced with a 74HC241 device.

The diagram overleaf shows the circuitry for an ASICS-based 3-link with ROM.

Revision 1.00 Page 35 of 115 pages

Psion PLC (c) May 1995

The Psion SIBO Hardware Development Kit

vec Rig Icz vec 100K 64/128K PROM SITE E B ag 12Tag wy po Laz ba ta ¥ 14 Di AL D1 To é TS Be Az Dz g id Da as DS 3 tg ba Aa ba id 15 DS aS DS 20 DE AS De }s¢ = ay DF ae voc voc ag Alo vec AlL - A1lz ne |S? ars ver 4 i Ais Pst [22 +08 ce cz $3 rea Our /25v idon io0n Ale. + N B * T le t GND GND ND Fs ey eee 2g Re 100K TRL + BCH 1 cs cz + 1ur/50¥ LuF/so¥ GND vee mS 1 | s aL rs 82 (ita 1 ies veo 22 [aa i wees 23 i 19° + iOurv2sy D1 Fi 14 + ¢ 13 " 24s ex i ca | 1 4 aa c = vor 15 | coy yo LAZ ayes 2 t 16 7 SKT1 CASE za 2- Fi Teu uF 7254 BAYS? I FaHorS 7d TitN taout 2 GND SKTL 36 e _DTR PBO Y¥ PAD TBIN TZOUT RLSD/bco| ba PBL © pai }32 294 7 SIN TzouT 2 rs RX 4 tad Sa ei ze _Tx x * PBZ paz [3 T4IN T40UT Tx 2 PES paz = 3 Pare DIR PB4 paa [22 £4 R1OuIT R1IN p32 _RX__§_+ t GND a ee PBS pas fed eno se] RZOUT R2IN Pst—Bek . DSR PES Pas pse 25) REOUT RSIN bee—GeR 4 RTS PE? PA? R4ouT RaIN * cts DS, ig Te RI * a WEE — RS0UT . RSIN * RI PDO poco i at S| = a PDL pci H2 24 eR ql sp }25 SIBO RS2S2 CONNECTOR PDE pez He ibe Ria L c BAYSS co: pea fas REG Too 100K a mMaxzan GND 12 ciolesilcizicizicis4 PDS pes SMB PDS roe 3S PD? pe? L414 L GND in Jin Jin Jain Jain | 1008 R4 25 /ep zen b24 GND vovVoov¥ vo 1O5R at 27 €39 Pox GND GND GND GND GND ' CLK eSi 26 2 FOR cs2 i7q Fo s T 3g N53 PIL cs NG BD ¢np PL2 fh 100pF iz veo asics [8 4 GND GND ND R? RL 100R 100K Sue o——___| cL SH SPDT vee 100n CONNI cer GND SRT ee RG RS SDS/INT BS Copuriaht CC) Psion PLO 1991 ScKS/ExON PS Vee bs File name! CONHH DRAFT RS232.5CH yee Bg ioorR is a 10k Braun: MG CON COMMS CONN R20 B2xe4—Cay7 PCB Rey 1.4 100K Title ¥ 2|a GND Rev 1.2 Move SD (pin 25 IC2> from pin 23 to 21 of Ici : EONSUMER Bases ExCeL on Rev 1.3 Alter Ri? from 100K to 10K Size Pocument Number REV Rev 114 Added C1io—c14 = Rev 1.5 Moved C3 to CLK input GND GND is 6500.0008 cata Date: June i0, i953 Sheet i oF L

Page 36 of 115 pages

1.00

1S10n

Rev

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

9. DEVICE DRIVER OVERVIEW

Introduction

Once a piece of peripheral hardware has been designed the appropriate software must be written to control it. All hardware on Series 3/3a, Workabout and HC machines is controlled by logical and physical device drivers. These act as the logical low-level software interface between a piece of hardware and an application that uses it. The remainder of this document is concerned with the methods by which a device driver is able to communicate with and thereby control an ASIC4 or ASICS-based peripheral.

APPLICA TION SOFTW ARE

Psion C PLIB call interface LOGICAL DEVICE DRIVER

PHYSICAL DEVICE DRIVER

PHYSICAL HARDW ARE

This chapter is intended to guide the programmer through the central issues involved in writing device drivers for peripherals that attach to the family of Psion host machines based around the proprietary SIxteen-Bit Organiser (SIBO) architecture. The purpose of a device driver is to abstract away the hardware details required to conduct communication between a peripheral and a software application that uses that peripheral. The device driver therefore performs the logical processing required to translate low level hardware instructions into high level application services. Psion device drivers are written in 8086 assembler and following convention are divided into a logical layer residing over a physical layer. A physical device driver (PDD) contains the code required for talking directly with the hardware device and provides a set of low level hardware specific services. A logical device driver (LDD) performs the logical processing that transforms these low level services into the high level services used by an application. This two-layer nature of device drivers at Psion can be illustrated by the following example. An application using the serial driver decides that it requires RTS/CTS handshaking. It calls an LDD which decides whether or not a line should be driven. If the answer is yes, the LDD calls the appropriate PDD and asks for a particular line to be driven to a specific state. The PDD duly carries out the requested service. Psion SIBO machines often use the same LDD with a PDD written specifically for each version of the hardware device. In such a situation, splitting the device driver is highly desirable. In the example given above, however, the LDD could have talked directly with the hardware negating the requirement for a separate PDD. Similarly, most external peripherals would normally use an LDD.

An LDD must provide a minimum of eight functions for use by the operating system. The functions are passed to the OS via a table of function offsets (referred to as the vector function table). These functions are mandatory. Similarly, a PDD must provide two functions for use by the operating system and may provide more if required. An LDD will usually provide further services/functions for use by an application. The form these take is dependent on the LDD requirements and the functions supplied by the associated PDD(s).

Revision 1.00 Page 37 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Psion SIBO machines are supplied with a set of resident device drivers built into the ROM each of which can be replaced with an installable device driver having the same name. Installable device drivers can also be added to increase the number of available device drivers. Installing a device driver is carried out dynamically without resetting the machine (this is not the case with many operating systems).

Device Names and Channels

The name of a device driver is the mechanism by which an application can obtain a channel to that device driver. A logical device driver name always has three characters followed by a colon. For example, "TTy:" is the serial LDD. This name is required to uniquely identify the LDD to the EPOC OS when attempting to open a channel on it. A physical device driver name always has the three characters of its owning LDD followed by a period, a further three characters and a colon. For example "TTy.UAR" is the ASICS UART driver and "TTy.srRx" is the 16450/16550 driver. The first three characters of a PDD name are the name of the LDD to which the PDD belongs. The second set of three characters uniquely identify the PDD. Thus in the above examples, both PDDs belong to the "tty:" LDD.

A channel can be opened on an LDD by calling the PLIB library function p_open. EPOC uses the driver name passed through an application p_open call to invoke the IoOpen operating system service. This service in turn calls the associated driver ‘open vector’ which can decide whether or not to open a channel on the driver. The assembled ASIC4 Example Interface Board logical device driver, A4EXIF.LDD, for example, has the three-character device name "LED" so a channel with its handle in pcb may be obtained on it by means of the following call:

p_open(&pcb, "LED:", -1)

In this call, the third argument refers to the open mode and a value of -1 indicates that the mode parameter is to be ignored. To obtain a channel on a PDD, an application should call the DevopenPpp OS service. Typically, only LDDs open PDDs though the p_open library function can be used to open a PDD indirectly as illustrated in the following example:

p_open(&pcb, “"TTY.UAR:", -1)

For a device driver configuration consisting of an LDD and a PDD, the application will usually open a channel to the LDD only: the LDD as part of its initialisation would open a channel to the required PDD. If an LDD requires a PDD and none is specified, it is up to the LDD to either fail the open request or hunt for a loaded PDD that it can use. An LDD uses the DevFind OS service to search for a PDD as for instance in the case of the "TTy:" device.

A device driver may be capable of supporting more than one open expansion channel at a time. In order to distinguish the channels, a qualifier can be added to the open request as part of the device name. It is then up to the device driver to specify the format of the qualifier. By convention, channels are allocated a single character sequentially from the character 'A'. For example, the parallel port driver can support two open channel, 'A' and 'B'. The LDD requires one of these qualifiers in order to open a parallel driver channel:

p_open(&pcb, "PAR:A", -1) p_open(&pcb, "PAR:B", -1)

The number of channels that can be thus supported will in general be dependent on the host SIBO hardware. In the case of the serial port on the S3a, for instance, only one SIBO channel can legitimately be opened corresponding to expansion port C. With the Workabout and HC, however, it is possible to open up to three separate SIBO channels on ports A through to C where A refers to the top port of the host machine, B to the bottom port and C to the side (or cradle) port.

LDDs have been designed to be accessed via the I/O system. I/O requests on the opened channel will reach the 'strategy vector' of the device driver. PDDs have been designed to be accessed by an LDD

Revision 1.00 Page 38 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

either via far calls or the Devvector OS system service. Once a channel has been obtained on a device driver, the operating system can send it events not sent to other applications. Examples are events generated by the machine being switched on or off, memory segments being moved about and the owning application being panicked. The EPOC OS can handle a maximum of 32 device drivers on a Series3 machine and 48 on other machines.

Loadable Logical Device Driver Structure

Common features of the structure of loadable LDDs

All loadable LDDs must conform to the following rules:

e There must be a single code segment and no data segments. The code segment is encapsulated in the assembler .asm file by calls to the codeSeg and EndCodeSeg defines respectively.

e The code segment must begin with a LibEnt structure which indicates the LDD name or signature which is used to identify the driver when trying to open and close channels.

e There must be at least eight supported functions which are listed in the LibEnt struc.

LibEnt Structure

The first field of the LibEnt structure consists of a two-byte signature containing the define ‘LDDSignature’ or 'PDDSignature’ in the case of a PDD. The remaining fields consist of an eight byte name which holds the device driver name stored as a zero terminated string (note that the trailing colon is omitted), a two byte vector count which must be at least eight and a vector table listing the supported device driver functions. The relevant code in the case of a hypothetical DevFunc LDD (DEVFUNC.LDD) with the device name of "TES:" is listed below:

CodeSeg

ProcBegin@ DevFuncLDD

dw LDDSignature db 'TES',0,0,0,0,0 dw (VectorEnd-Vector) /2 Vector: dw DevFuncInstall dw DevFuncRemove dw DevFuncHold dw DevFuncResume ; Mandatory LDD vectors dw DevFuncReset ; must be in this order dw DevFuncUnits dw DevFuncOpen dw DevFuncStrategy VectorHandler: dw DevFuncHandler ; Optional LDD vectors InterruptVectors: dw DevFuncTickInt VectorEnd:

ProcEnd noret The vector table contains the offsets within the device drivers code segment for the functions required

by the EPOC operating system which must be entered in the order shown. Note that in this document, the terms vector and function are used interchangeably.

Mandatory LDD Functions

All LDDs must support the following eight functions:

@ DevFuncInstall called on device installation

@ DevFuncRemove called on device removal

@ DevFuncHold called to temporarily disable the driver

@ DevFuncResume called to enable the driver after it has been temporarily disabled

Revision 1.00 Page 39 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

@ DevFuncReset called when an application terminates without closing the channel @ DevFuncUnits called to query the number of supported units (i.e. channels)

@ DevFuncOpen called to open a channel to an LDD

@ DevFuncStrategy called to access the driver's functionality from the I/O system

All of the eight mandatory routines pointed at by the function vector table will be called FAR by the operating system and should therefore use a FAR return machine code instruction to return control back to the OS. Since the FAR return address is to the OS it does not matter if the OS moves memory whilst code in the LDD is being executed: the OS cannot move its own code.

DevFunclinstall

This function is called by the operating system when the device driver is loaded in order to initialise any internal variables. It should not be called directly by an application process. The DevInstall operating system service will cause this function to be called. Applications should not call this service directly and should call instead the DevLoadLDD service.

An installable device driver may have the same name as a resident device driver. When the operating system loads a device driver, it places it at the end of the device driver table. The operating system will search this table for the appropriate device driver when it wishes to establish a channel. The search starts at the end and thus will locate the most recently installed device driver (if any) or if not, the resident driver. By this mechanism an installable driver can replace any resident driver.

When called, the DS and ES segment registers are in an unknown state. The device driver should take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this involves setting the DS and ES registers to the CS register or more commonly just using the CS override. The operating system will not move memory whilst in this function, thus the normal rules governing DS and ES may be ignored. All operating system services may be called, except those concerning file or device access.

PASSED

No values are passed to the install vector.

RETURN

If the installation was successful, return with the carry flag clear.

If the installation failed, return with the carry flag set and the error number in the AL register. PANIC

The install vector must not panic: it will cause an operating system kernel fault if it does. PRESERVE

The SS, SP and BP registers must be preserved by the install function.

DevFuncRemove

This function will be called by the operating system when the device driver is requested to be unloaded. It should not be called directly by an application process. The DevRemove operating system service will cause this function to be called. Applications should not call this directly, they should use the DevDelete service. Before the remove function is requested, the device driver will have received a hold request. Thus devices will only ever be removed when in a held state. If the device driver is currently busy serving a client, the remove request should return an error. Note that all resident device drivers will return an error since there is no mechanism by which they can be re-installed.

When called, the DS and ES segment registers are in an unknown state; the device driver should take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this involves setting the DS and ES registers to the CS register. The operating system will not move memory whilst in this function, thus the normal rules governing DS and ES may be ignored. All operating system services may be called inside the remove vector, except those concerning file or device access.

PASSED

No values are passed to the remove vector.

RETURN

If the remove was successful, return with the carry flag clear.

If the remove failed, return with the carry flag set and the error number in the AL register.

Revision 1.00 Page 40 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

PANIC

The remove vector must not panic: it will cause an operating system kernel fault if it does. PRESERVE

The SS, SP and BP registers must be preserved by the remove vector.

DevFuncHold

This vector will be called by the operating system when a logical device driver is requested to be held. The hold vector is called in the context of the operating system so DS and ES are not available. The DevHold operating system service will cause this vector to be called. Applications should not call this service. Physical device drivers cannot invoke holds and resumes. The operating system will call the hold vector under three conditions:

e Device memory segments are about to be moved.

e The machine is about to switch off due to the auto switch off time-out or user request, it enters the standby state.

e The machine is about to switch off due to the power source being removed.

It should be noted that holds and resumes are called on a per driver basis and so the corresponding driver code must deal with all the currently open channels. In all cases the device driver must respond to the request as quickly as possible. It must also ensure that ALL interrupts from the hardware device that it is driving are disabled. Device memory segments can only be moved if an installable device driver is being installed or removed. If the LDD uses an attached PDD and uses the faster FAR call mechanism to call the PDD strategy vector, the PDD strategy vector address will potentially move, thus the FAR address will be wrong. This address can be resolved in the resume vector. The LDD must not call the PDD between a hold and resume. Typically, the device driver only needs to disable its interrupts. When a resume occurs, the device driver should continue as though nothing had happened.

If the machine is about to switch off due to the auto switch off or user request mechanisms (enter the standby state), the device driver should make an orderly shut down of the device such that the state before the shut down can be recovered when the system powers up again. The device driver should also attempt to ensure that no data is lost. For example, in the serial driver the current state of the hardware handshaking lines should be noted so that each state can be restored on power up. For this type of power down the hold vector is allowed to take a significant length of time to shut down a device. For example in a serial driver the hold vector should wait until the remote end stops transmitting data after any hardware handshaking has been applied. Of course, the time taken should be kept to a minimum: in the case of the serial driver above the time is roughly equivalent to 3 character transmission times. When a resume occurs the device driver should continue as though nothing had happened.

If the machine is about to switch off due to the power source being removed, the device driver should reset the device in the minimum possible time: no attempt should be made to perform an orderly shut- down. The device driver is not expected to be able to recover the hardware state. When a resume occurs, the device driver would typically fail any outstanding application requests. If the hold vector takes too long the voltage will fall below the threshold to hold the state of the internal RAM. If this occurs the machine will perform a warm re-boot when powering up, all data in the internal memory of the machine will be lost including the device driver code! On power fail there is about 2ms available to power down all devices.

On a power failure hold, the operating system will already have sent a 'reset' to all the SIBO serial channels. Any device drivers using these channels need only record the hold reason for the resume vector. Any other peripherals should be designed to allow a power fail mechanism with the minimum amount of code. It must be noted that the power fail type hold can occur whilst the device driver is in the memory move hold state. In this case, the device driver will receive two hold requests before seeing a resume request. A device driver must be capable of handling this. In this case, the device driver will also receive two resume requests. A device driver will not get a power fail hold whilst in

Revision 1.00 Page 41 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

power down hold. A call to the hold vector will always be followed by a call to the resume vector (except when a device is requested to be removed).

Note that with the Series 3a and Workabout, there is an additional case when hold and resume must be invoked and that is on opening/closing of the pack doors. In this case, the LDD must generate its own Hold and Resume. This situation is examined in more depth in the context of the specific example drivers presented later in this document.

When called, the DS and ES segment registers are in an unknown state; the device driver should take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this involves setting the DS and ES registers to the CS register. The device driver should not call any operating system services in the hold vector code due to the time taken, especially on power failure. PASSED

The AH register takes one of the following

@ DevHoldNormal Device memory is about to be moved. @ DevHoldPowerDown The system is about to enter the standby state. @ DevHoldPowerFail The system has lost its power supply. RETURN None. PANIC

The hold vector must not panic: it will cause an operating system kernel fault if it does. PRESERVE The SS, SP and BP registers must be preserved by the hold vector.

DevFuncResume

This vector will be called by the operating system when the device driver is requested to be resumed. The resume vector is called in the context of the operating system. The DevResume operating system service will cause this vector to be called. Applications should not call this service. The resume vector will be called either when memory has finished being moved or when the machine powers back up. In both cases the hold vector will have been called before this vector is called. The device driver is expected to recover from the previous hold request (except power fail) and resume any I/O that was suspended. If the device driver has an interrupt service routine, it should reset the interrupt service routine's address since the device driver may have moved in memory; its absolute segment address will be different.

If the hold was a device memory segment move type hold, interrupts should be re-enabled. If the LDD uses an attached PDD and uses the FAR call mechanism to access the PDD strategy vector, the address of the PDD should be reset by using the DevGet PDDAddress operating system service before enabling interrupts. Typically, the PDD will have a call back to the LDD and it needs to be informed of the change of address of the LDD call back function, the LDD-PDD interface definition should allow such a function request.

If the hold was a power down type hold, the resume vector needs to power up the peripheral and set it to the state that it was in before the power down occurred. If this is not possible or data has been lost, the device driver should inform any outstanding requests of this fact. It is also possible that the hardware device that the driver is associated with has been removed. The driver should be able to handle this properly. If the device driver is expected to generate events due to an external state change, the driver should check the external state and generate appropriate events. For example, the serial driver may be requested to inform an application when the DTR line changes state. The remote end may have changed the state of DTR whilst the driver is held.

If the hold was a power failure type hold, the resume vector should power up the peripheral and put it

into a known state, preferably the state that the application software thinks that the device is in and fail any outstanding requests as data is quite likely to have been lost.

Revision 1.00 Page 42 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

When called, the DS and ES segment registers are in an unknown state. The device driver should take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this involves setting the DS and ES registers to the CS register. All operating system services may be called, except those concerning file or device access.

PASSED

None

RETURN

None.

PANIC

The resume vector must not panic, it will cause an operating system kernel fault if it does. PRESERVE

The SS, SP and BP registers must be preserved by the resume vector.

DevFuncReset

This function will be called by the operating system when the device driver is requested to reset a channel. The reset function is called in the context of the operating system so DS and ES are not available. The device driver must request that the operating system call the reset function. This is achieved by calling the IoRequestReset system service, usually in the open vector. To cancel this request, the device driver should call the IoRequestResetCancel system service. The cancel service is usually called as part of the close functionality in the strategy vector. The reset vector will be called when the operating system is tidying up resources owned by a process that has terminated. Ifa process terminated before it closed the device driver channel and no reset service is requested, that channel would remain allocated; no process will ever close the channel. The reset vector allows a device driver to reset itself and allow the channel to be opened again. Any data required to perform the reset must be stored in the device driver. The data space belonging to the process that originally opened the channel has been returned to the operating system memory pool and is no longer valid. If a device driver can handle multiple channels then the data passed to the IoRequestReset system service should identify the channel. This data will be passed in the CX register to the reset vector. The device driver should only have a reset request outstanding with the operating system while a process has a channel open.

When called, the DS and ES segment registers are in an unknown state; the device driver should take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this involves setting the DS and ES registers to the CS register or using CS override. All operating system services may be called, except those concerning file or device access.

PASSED

This function is passed data in the CX register that the device driver requested it be sent to determine which channel should be reset.

RETURN

None.

PANIC

The reset vector must not panic; it will cause an operating system kernel fault if it does.

PRESERVE

The SS, SP and BP registers must be preserved by the reset vector.

DevFuncUnits

This function will be called by the operating system when the device driver is requested to report the number of units (i.e. channels) the device driver can support. This function is called in the context of the operating system. The operating system places no significance on the number of channels a device driver can support. It is primarily used for informational purposes. An application may use the number of units to attempt to open any available channel on that device driver.

When called, the DS and ES segment registers are in an unknown state; the device driver should take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this involves setting the DS and ES registers to the CS register. All operating system services may be called, except those concerning file or device access.

PASSED

Revision 1.00 Page 43 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

None.

RETURN

The AX register should contain the number of channels supported. If a device driver can support multiple channels (limited only by memory constraints) then the driver may return -1. A serial device driver, for example, might only support two channels (TTY:a and TTy:8) whereas the file device driver can open an unlimited number of files.

PANIC

The channels units vector must not panic; it will cause an operating system kernel fault if it does. PRESERVE

The SS, SP and BP registers must be preserved by the units vector.

DevFuncOpen

This function will be called by the operating system when a channel to the device driver is required to be opened. This function is called in the context of the process that called the Ioopen system service. This means that DS and ES point to the application data space. The device driver is passed two parameters, its device handle and a pointer to an OpenEnt structure. The device handle is the entry in the system device table of this device driver. The device driver is required to place this handle in the ChanLibHandle field of the ChanEnt structure which must be allocated in the user's data space. The operating system uses the device handle to route any I/O requests on the opened channel to the correct device driver.

The OpenEnt structure contains three fields, openNamePtr, OpenMode and OpenChan.

The openNamePt r field contains a pointer to the character that exists after the device name as passed to the ToOpen system service. For example, if the ToOpen service was passed a name of PAR:A, the OpenNamePtr field would point to the colon. If the ToOpen service was passed a name of TTY.AS5:B the OpenNamePtr field would point to the full stop. The device driver should process the name appropriately, opening the correct PDD as required.

The OpenMode field contains the mode for opening the device driver. The available modes are specified by the device driver writers. For example, a combined Xmodem and Ymodem device driver could use the mode to specify whether the Xmodem or the Ymodem protocol is to be used.

The Openchan field contains the I/O channel handle of the device that this driver is required to ‘attach’ to. Attached device drivers are dealt with later in the chapter.

The code in a device driver open vector tends to follow a very similar pattern. This is demonstrated by the following code fragments and associated comments. The first stage is to allocate some data space in the calling process' heap space. This will contain the I/O channel control block:

mov cx, (size DeviceEnt)

HeapAllocateCell

jc noMemory

mov bx, ax ; cell handle

If the device driver requires a WaitHandler (described later):

mov al, (VectorHandler-Vector) /2 ToAddHandler

jc endFreeMemory

mov [bx].DriverHandler, ax

If the device driver's DevFuncReset vector is required to be called:

push bx

mov cx, ChannelIndicator 7 unique per channel mov bx, ax ; the device handle ToRequestReset

pop bx ; restore alloc cell

The chanEnt field of the DriverEnt structure must be initialised:

mov [bx] .DriverIo.ChanNext, bx mov [bx] .DriverIo.ChanSignature, IoChanSignature mov [bx] .DriverIo.ChanLibHandle, dx

The ChanNext field is used by attached drivers and will usually be set to be the allocated cell handle of the device driver being opened. The IoFuncattach and IoFuncDetach functions manipulate these fields. The I/O system uses this field to direct the I/O request to the correct driver.

Revision 1.00 Page 44 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

The ChanSignature field is checked by the operating system during any I/O requests for the value IoChanSignature. If it does not contain that value, the process calling the I/O service will be panicked for having passed an invalid I/O channel handle.

The ChanLibHandle field is used by the operating system to route an application's I/O request to this device. The I/O request will call the DevFuncstrategy vector of the device driver.

If the driver is an attached driver the following is required:

mov cx, bx ; allocated channel

mov bx, [si] .OpenChan ; channel attaching to mov al, IoFuncAttach ; return in BX the ToWithWait ; channel attached to

Finally, if the channel has been successfully opened: ele Opened Ok ret return BX and DX

’

’

The error recovery code typically follows the following pattern:

endFreeReset: push ax push bx mov cx, ChannelIndicator mov bx, ax ToRequestResetCancel pop bx pop ax endFreeHandler: push ax push bx mov bx, [bx] .DriverHandler ToRemoveHandler pop bx pop ax endFreeMemory: push ax HeapFreeCell pop ax stc noMemory: ret

If a device driver supports a fixed number of channels, it typically contains static control blocks. In order to determine if a requested channel is currently open, a field should be interrogated. The device driver should ensure that interrupts are disabled during this sort of check since a context switch could occur and another process request the opening of the same channel. This is the classic 'test and set' problem encountered in multi-tasking environments.

When called, the DS and ES segment registers point to the data segment of the application process attempting to open a device channel. The application should ensure that the DS and ES segment registers do in fact point to its data segment. The device driver must obey the normal rules concerning segment register manipulation. The DS and ES segment registers can be reloaded if required from the IntEnt structure pointed at by the BP register. All operating system services may be called.

PASSED

DX contains the device handle of the device driver.

SI is a pointer to the OpenEnt structure

BP is a pointer to the IntEnt structure.

RETURN

If the channel open was successful, return with the carry flag clear and the BX register containing the open channel.

If the open failed, return with the carry flag set and the error number in the AL register.

PANIC

The open vector can panic; it will cause the process requesting the device open to terminate. It is however more usual to return an error to the calling process.

PRESERVE

The DS, ES, SS, SP, BP and DX registers must be preserved by the open vector.

Revision 1.00 Page 45 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

DevFuncStrategy

When an application makes an I/O request on the opened device driver channel the request is routed to this vector by the operating system. A device driver defines the set of functions that it supports. These typically include IoFuncSet, IoFuncSense, IoFuncRead, IoFuncWrite and IoFuncClose. A device driver does not have to support any particular function, as it is a matter of design between a device driver writer and application writer as to what functions and associated parameters are provided. To obtain the power of attached device drivers, however, it is recommended that the device driver use the system defines with their appropriate functionality, for example, the loFuncWrite function number should always be associated with writing data.

The strategy function is passed the channel handle as allocated in the open vector in the BX register. This typically contains control information concerning the current state of the I/O channel.

The SI register contains a pointer to a RgEnt structure. This structure contains four fields, RqFunction, RqStatusPtr, RqA1Ptr and RqA2Ptr.

The RgFunction field contains the function number as passed to the IowithWait (or IoAsynchronous) I/O request by the application. If a device driver does not support the specified function, it should pass the request on to its 'parent' device driver.

The RqStatus pointer contains a pointer to a memory location in the application process's data space that receives the I/O requests completion status. The device driver must set this memory location to the value PendingErr whilst the I/O request is outstanding and a completion code when the I/O request completes. An I/O request may complete within the strategy vector or it may complete some time in the future, presumably from some interrupt.

The RgA1Ptr and RqA2Ptr fields contain the argument | and 2 parameters as passed to the IoWithWait (or IoAsynchronous) system services. The device driver is free to specify what these parameters are (if any).

The operating system defines a set of common function numbers used by device drivers referred to as the IoFuncxxx set of defines. By convention, a device driver should select from this list, particularly if some of the more advanced features of the I/O system are to be used, such as attached device drivers. The more common defines are listed below:

@ ToFuncRead ; read from the device.

® TfoFuncWrite ; write to the device.

@ TloFuncClose ; close device channel.

@ = =ToFuncCancel ; cancel an I/O request.

® ToFuncSet ; set driver characteristics.

® tloFuncSense ; sense driver characteristics. e lIoFuncFlush ; flush any buffers.

The PLIB library functions p_read, p_write and p_close will call the device driver with the IoFuncRead, IoFuncWrite and IoFuncClose function numbers. Thus, if the device driver chooses an alternative function number set, an application will not be able to use the supplied library functions. All resident device drivers obey the following conventions: e Acancel request will cancel any outstanding requests. A cancel request will not return any error.

e Aclose request will ensure that any outstanding requests are completed before closing the channel. A close request will not return any error.

e Only one request of a particular type can be outstanding at any one time. If a second request is made the device driver will panic the calling application.

Any functions that the strategy function does not support should be passed on to the next driver down the driver hierarchy. If the driver is a root driver (attached driver), this is achieved using the IoRoot

Revision 1.00 Page 46 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

(IoSuper)system service. If the requested function is not supported by any driver, the operating system will return a Not Supported error.

When called, the DS and ES segment registers point to the data segment of the application process making the I/O function request. The application should ensure that the DS and ES segment registers do in fact point to its data segment. The device driver must obey the normal rules concerning segment register manipulation. The DS and ES segment registers can be reloaded if required from the IntEnt structure pointed at by the BP register. All operating system services may be called. PASSED

BX contains the allocated channel control block.

DX contains the device handle of the device driver.

SI is a pointer to the RqEnt structure.

BP is a pointer to the IntEnt structure.

RETURN

If the function request is successful, the strategy vector should return with carry clear. A request typically causes some I/O. If the I/O is completed by the strategy vector (i.e. the request is for a synchronous function such as close), the completion status should be written back to the RqStatusPtr location and the I/O semaphore signalled (using the IoSignal system service). If the request has not yet completed (i.e. the request is for an asynchronous function), the RqStatusPtr location should contain the value PendingErr and the I/O semaphore should not be signalled.

If the function request failed the strategy vector should return with carry set and the error code in AL. In this case, typically no I/O requests will be completed.

PANIC

The strategy vector can panic; it will cause the process making the I/O request to terminate. In most cases it is usual to return an error to the calling process. A major exception to this is if the calling process makes an I/O request of the same type as one that is currently outstanding and the device driver only supports one I/O request of a particular type at a time; by convention the device driver should panic the calling process with the PanicIoPending panic code.

PRESERVE

The DS, ES, SS, SP and BP registers must be preserved by the strategy vector.

Interrupts and Interrupt Service Routines

Device drivers that talk to hardware tend to have interrupt service routines associated with them, especially if they are receiving data from an external source. The EPOC operating system provides a framework within which an interrupt service routine can be written relatively easily. An interrupt service routine is a code section that is called by the OS in response to a particular hardware event. As indicated in the Hardware Overview, the SIBO architecture allows for eight independent hardware interrupt sources, some of which are pre-allocated to system components. The operating system provides the GenSetRevector service to allow a device driver to install an interrupt service routine for any of the eight hardware interrupt sources. This call passes the interrupt vector (the address of the interrupt service routine) and the interrupt number (which is dependent on the host hardware) to the OS so that it knows where to jump to when the interrupt occurs. A device driver should use this system service and not poke directly into the 8086 interrupt vector table. The address passed to the GenSetRevector Service is not written into the interrupt vector table but to an internal table. After invoking this service, the desired interrupts must be masked in by writing the appropriate mask to the mask register. Initially, of the eight interrupt sources, only the tick interrupt is masked in.

When an interrupt occurs, the microprocessor could be running any currently active process. The OS handles the servicing of interrupts by building a mandatory operating system call frame. All CPU registers are preserved on route. The interrupt service routine is then called as a FAR routine. Since the operating system preserves all registers the interrupt service routine is free to use any register. As with all interrupt service routines various rules apply:

e Interrupt service routines should execute as fast as possible. Operating system interrupt service routines are tuned to last no longer than one millisecond.

Revision 1.00 Page 47 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

e Typically, interrupt service routines do not enable interrupts unless the routine can handle re- entrancy.

e Interrupt service routines run in the context of whatever process is running at the time of the interrupt. An interrupt service routine should not attempt to obtain admissibility to the process that opened the channel but access the internal driver space only which in general is its own code space.

e An interrupt service routine must not directly cause the OS to reschedule the running process as this would significantly delay its completion. It must use the IoSignalByPidNoReSched system service in order to indicate to the handler that an event has occurred to the owning process. The handler function of the device driver must pick up the event and inform the owning process.

e An interrupt service routine should return with the carry flag clear if it requires a reschedule to occur (it has called IoSignalByPidNoReSched) otherwise return with the carry flag set. This will cause the operating system to reschedule if the internal state allows such an action otherwise the reschedule request is effectively queued until such time that the operating system can reschedule.

At some stage during the course of an interrupt service routine, it is necessary to clear the interrupt line with some hardware-specific action. Then the interrupt controller inside the host ASIC1 or ASIC9 has to be cleared with a write to the NonSpecificEoi location. To remove the interrupt service routine address, the operating system service GenResetRevector should be used. This will reset the internal table entry to the default held in the ROM. Additionally, the interrupt mask should be reset to the original value.

Device Driver I/O Semaphore Wait Handlers

An LDD may nominate one of its functions to be called by the operating system every time the I/O semaphore of the process that opened the channel is signalled. The nominated function, known as the wait handler, will only be called if the application is waiting for an outstanding I/O request to complete. For well written applications this is practically all the time. By convention the vector table entry after the mandatory vectors contains the handler vector. A handler routine is similar to an interrupt service routine in that it appears to run ‘from nowhere’. Comparing handlers and interrupt services routines shows that:

e A handler will always run in the context of the process that has opened a channel. An interrupt service routine will run in the context of whatever process happens to be running at the time of the interrupt.

e A handler can access the data space of the process that opened the channel. The interrupt service routine must not. An interrupt service routine should only access the data space in the driver which is usually its own CS space.

e A handler can cause a reschedule. An interrupt service routine must not cause a reschedule. If it did, the interrupt would not be fully serviced (the rest of the interrupt service routine would not be executed until a reschedule back to the process running at the time of the interrupt, which may not happen for a significant length of time). The interrupt service routine must only use the IoSignalByPidNoReSched to signal the channel owner.

The handler is the mechanism by which hardware interrupt events can be filtered through to the process using the I/O channel. Typically, it is in the handler code that the 1oSignal signifying completion of an asynchronous I/O request is invoked.

Loadable Physical Device Driver Structure

A loadable PDD must obey the following rules: e There must be a single code segment and no data segments.

Revision 1.00 Page 48 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

e The code segment must start with a LibEnt structure. e There must be at least two supported functions, with typically a further two defined.

Single Code Segment

A PDD must be written to contain any internal variables within its own code segment. Typically, these variables are only concerned with unit (i.e. channel) allocation and hardware state. Data space for a particular open channel can be allocated in the heap space of the process that opens the device. This data space will however disappear if the process terminates, thus any variables required for ‘freeing’ the hardware after a process terminates must exist in the code space of the device driver.

The LibEnt Structure

A LibEnt structure has the following format: e =A two byte signature

e §=6©An eight byte name e A two byte vector count e A vector table

The two byte signature should contain the 'PDDSignature' define. The eight byte name contains a zero terminated name, being that of the device driver. Note that there is no trailing colon. The two byte vector count contains the number of vectors that follow immediately after the count. There should be at least two. For example:

dw PDDSignature ; Its an PDD driver

db "DVR.HW1',0 ; Name of the driver

dw (VectorEnd-Vector)/2 ; Number of vectors Vector:

dw DvriInstall ; Install vector

dw DvrRemove ; Remove vector VectorEnd:

Most PDDs also define a further two vectors: dw DvrOpen , Open Vector dw DvrStrategy ; Strategy vector

The table of vectors is a table of offsets within the device drivers code segment of the routines that implement the required functionality. The vector table must have the entries in the order shown in the example.

Mandatory PDD functions

All PDDs must support the following two functions: @ DevFuncInstallppp called on device installation.

@ DevFuncRemovePDD called on device removal.

Most PDDs will support the following two additional functions: @ DevFuncOpenPDD called to open a PDD.

@ DevFuncStrategyPDD called to provide PDD functionality.

All of the routines pointed at by the function vector table will be called FAR by the operating system and should consequently use a FAR return machine code instruction to return back to the operating system. Since the FAR return address is to the operating system, it does not matter if the operating system moves memory whilst code in the LDD is being executed; the operating system cannot move.

DevFunclnstallPDD

This vector will be called by the operating system when the device driver is loaded to initialise any of its internal variables. The install vector is called in the context of the operating system and not the process that is loading the device driver. The DevInstall operating system service will cause this

Revision 1.00 Page 49 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

vector to be called. Applications should not call this directly, they should use the DevLoadPDD service.

An installable device driver may have the same name as a currently installed device driver. When installed, the driver is added to the end of the device driver table. When a channel to a device driver is being established by the operating system, it searches the device table from the end first, thus the latest installed device driver with the required name will be asked first for a channel. So as with LDDs by this mechanism installable device drivers can replace any of the resident drivers.

When called, the DS and ES segment registers are in an unknown state. The device driver should take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this involves setting the DS and ES registers to the CS register. The operating system will not move memory whilst in this function, thus the normal rules governing DS and ES may be ignored. All operating system services may be called except those concerning file or device access.

PASSED

No values are passed to the install vector.

RETURN

If the installation was successful, return with the carry flag clear.

If the installation failed, return with the carry flag set and the error number in the AL register. PANIC

The install vector must not panic; it will cause an operating system kernel fault if it does. PRESERVE

The SS, SP and BP registers must be preserved by the install vector.

DevFuncRemovePDD

This vector will be called by the operating system when the device driver is requested to be unloaded. The remove vector is called in the context of the operating system and not the process that requests the unload. The DevRemove operating system service will cause this vector to be called. Applications should not call this service directly; instead, they should call the DevDelete service. Before the remove function is requested, the operating system will send a DevFuncHold request to all LDDs. The LDD is responsible for ensuring that no activity will occur during the remove. Note that any device driver that handles hardware interrupts must contain an LDD since only LDDs receive a hold request. If the device driver is currently busy serving a client, the remove request should return an error. All resident device drivers will return an error since there is no mechanism by which they can be re-installed.

When called, the DS and ES segment registers are in an unknown state; the device driver should take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this involves setting the DS and ES registers to the CS register. The operating system will not move memory whilst in this function, thus the normal rules governing DS and ES may be ignored. All operating system services may be called except those concerning file or device access.

PASSED

No values are passed to the remove vector.

RETURN

If the remove was successful, return with the carry flag clear.

If the remove failed, return with the carry flag set and the error number in the AL register. PANIC

The remove vector must not panic; it will cause an operating system kernel fault if it does. PRESERVE

The SS, SP and BP registers must be preserved by the remove vector.

DevFuncOpenPDD

This function is defined as a convenience function for the LDD-PDD interface. When an application opens a channel to an LDD, it normally uses the Ioopen system service. If the name specifies, or the LDD requires, a PDD then it needs to open a channel toa PDD. The Devopenppp system service will call this PDD vector to establish a channel. The LDD now has a choice of calling a PDD vector using the DevVector system service or calling the fourth vector in the vector table directly. The fourth

Revision 1.00 Page 50 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

vector is assumed to be a strategy vector to which any parameters as required by the LDD-PDD interface can be passed. The FAR address of the strategy vector is returned by the DevGetPDDAddress. When an LDD receives a DevFuncResume it should call DevGet PDDAddress again to ensure that if the PDD has moved the LDD still has its correct address. As a design, a PDD could provide many vectors, one for each required function. The LDD would then use the Devvector system service to access each of these functions. The DevGetPDDAddress will only return the FAR address of the fourth vector.

When called, the DS and ES segment registers point to the data segment of the application process making the open function request. The application should ensure that this is indeed the case. The device driver must obey the normal rules concerning segment register manipulation. All operating system services may be called.

PASSED

The BX register contains a pointer to the PDD unit name. The pointer passed to the DevOpenPDD service is used to find the PDD device to open. The BX register is loaded with a pointer to the trailing colon (if any) in the PDD unit name. For example if the name "TTy.AS5:A" was passed to the DevOpenPDD service, BX would contain a pointer to :A upon calling the open vector. RETURN

If the open was successful, return with the carry flag clear.

If the open failed, return with the carry flag set and the error number in the AL register.

PANIC

The open vector can panic; it will cause the process requesting the device open to terminate. It is however more usual to return an error to the calling process.

PRESERVE

The SS, SP and BP registers must be preserved by the open vector.

DevFuncStrategyPDD

This function is defined as a convenience function for the LDD-PDD interface. Typically, all application function requests are routed through the strategy vector. To speed the calling interface, the DevGet PDDAddress operating system function will return a FAR address of this vector. The device driver writer defines all the functions and return values as required.

When called, the DS and ES segment registers point to the data segment of the application process making the function request. The application should ensure that the DS and ES segment registers do in fact point to its data segment. The device driver must obey the normal rules concerning segment register manipulation. All operating system services may be called.

PASSED

The parameters passed are defined by the device driver write.

RETURN

All returns are defined by the device driver writer.

PANIC

The strategy vector can panic; it will cause the process requesting the function to terminate. It is however more usual to return an error to the calling process.

PRESERVE

Which registers are preserved is defined by the device driver writer.

Revision 1.00 Page 51 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

10. ASIC4/ASIC5 BASED DEVICE DRIVERS

Introduction

This chapter describes the rules and problems involved in writing a device driver that controls some form of ASIC4 or ASICS based hardware. Details concerning the internal organisation of these ASICs were presented earlier in chapters 6 and 7. The emphasis is on their use for Series 3a applications, though most issues that will be discussed also apply to the Series 3, MC and HC range of Psion products.

In addition to the eight mandatory functions already detailed in the Device Driver Overview chapter, an LDD will usually provide additional functionality in the form of further vector table entries dependent upon the requirements of its application. Wherever possible, these functions should make use of the various pre-defined system defines for services such as reading (p_read) and writing (p_write) etc. It should be noted that there is no particular requirement to implement a device driver as a separate PDD and LDD and in the case of the example logical device driver A4EXIF.LDD, the approach taken is to incorporate both aspects into the one LDD.

SIBO Hardware Expansion Channels

The number of SIBO expansion channels supported by the host machine will vary according to the particular Psion hardware present. So that a single device driver may be compiled for the different host machine possibilities, a number of build flags can be used to set various constants within the include files. The hardware options are outlined in the table below:

SIBO Machine Flags | Number of SIBO serial channels supported Machine Build Flag

Consumer (S3a) Refers to $3a with ASIC9 only. Supports 1 SIBO channel (A)

ES ae Mat AST lysed SPS PTT

It should be noted that Psion device drivers should be designed to be easily adapted from machine to machine. For a well-written driver, the only change that needs to be made in adapting it for use on another Psion machine is the alteration of the build flag at the start of the code. This flag indicates to the compiler which SIBO machine flags as well as other variables should be set for the host machine. The four most important SIBO machine variables are the channel interrupt mask, the channel interrupt number, the channel interrupt vector and the hardware SIBO channel. The channel interrupt mask is an eight bit value or'd with the contents of either AlInterruptMask or A9BInterruptMask (the mask registers) to initiate interrupts on the relevant channel depending on whether the interrupt controller resides in ASIC1 or ASIC9. If this mask is then used in a HwGetChannel call, any hardware interrupts on the selected expansion channel will be directed to the appropriately coded interrupt service routine. The channel interrupt mask is also required in the subsequent HwFreeChannel OS service call and when stopping hardware interrupts. The channel interrupt number is a sixteen-bit quantity required by the GenSetRevector and GenResetRevector OS system services to indicate to the OS which default interrupt service routine is to be replaced by the suitably coded device driver interrupt vector. The channel interrupt vector is a sixteen-bit pointer to the location of that interrupt vector in the device driver code. Finally, the hardware SIBO channel is used by the HwSelectChannel OS service to direct any SIBO serial control or data frames

Revision 1.00 Page 52 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

along the appropriate channel. The situation regarding the value of these variables for the expansion ports on all current SIBO platforms is illustrated in the table overleaf:

IW orkabout (Series3) a en en an Channels

Controller ASIC |ASIC? ASICO Mask Register A9BInterruptMaskRW a a a ae

IHwIrq2Revector

mask A9MExpIntA (Expansion Port A) mask A9MExpIntB (Expansion Port B) Imask AOMSlave

(Expansion Port C)

IHwIrq4Revector IHwIrgq5Revector IHwIrq2Revector

ASIC2

mask ExpIntLeftA (Expansion Port A) mask ExpIntRightB (Expansion Port B) mask Asic2Int (Expansion Port C)

IHwIrgq3Revector IHwIrq2Revector IHwIrq4Revector

ASIC2 ASIC2

mask Asic2Int (Expansion Port C)

mask ExpIntLeftA

(Expansion Port A) mask ExpIntRightB (Expansion Port B)

IHwIrgq3Revector IHwIrq2Revector

IHwIrq4Revector

Ptr Channel SelectChannel5. SelectChannel3 IExpChannelLeftA IExpChannelLeftA SelectChannel7 Hard Select SelectChannel4 ExpChannelRightB = |ExpChannelRightB

arOWAre Dre’ SelectChannel5 SelectChannel7

Talking to ASIC4

All communication to an ASIC4 is via a Psion Serial Link. As explained in the chapter on the SIBO serial protocol, two forms of data can be sent and received along this channel. These are control and data bytes. Control bytes give specific instructions to ASIC4 and data bytes can either be data sent to or from ASIC4 or data given to or taken from peripheral chips in ASIC4's address space. Sending and receiving control and data frames down a Psion Serial Channel from a Series 3/HC host is simply a matter of IN and OUT instructions to various fixed I/O addresses. Various assembler macros have been set up to ease this task and provide machine independence and they are detailed in the appendix. These include:

SCONTOUT Output the control byte held in the AL register SDATAIN Input a byte of data and place it in AL

SDATAOUT Output the data byte in the AL register

XNOP Wait a short while

SBUSY Wait while the Psion Serial Link is busy

Once a piece of peripheral hardware has been designed the appropriate software must be written to control it. All hardware devices on Series 3/3a, Workabout and HC machines are controlled by device drivers. These act as an interface between a piece of hardware and an application that uses it. The following section goes into further detail regarding the methods by which a device driver is able to communicate with and thereby control an ASIC4 and ASICS based peripheral.

ASIC4 Registers

ASIC4 has eight registers and their functions in mixed (i.e. peripheral) mode are outlined below:

Register 0: This register is the read/write Data Register that controls the data lines DO-D7 which are normally in tri-state mode. Data written to the Data Register is output on DO-D7 during a write cycle and data input to the DO-D7 may be read from the register during a read cycle. On reset, this register holds the Info Byte and its bits have the following meanings:

Revision 1.00 Page 53 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Bit No. D7 D6 DS D4 D3 D2 DI DO DD DN N S S _ S

D D_ OD i _ Device type

0 0 O RAM SSD

0 oO 1 Intel Flash type 1

0 1 O Intel Flash type 2

Oo 1 1 TBS

1 0 O TBS

1 0 1 TBS

1 1 0 Read only SSD (ROM OTP etc.) 1 1 1 Hardware Write protected SSD N N Number of devices

0 O 1

0 1 2

1 0O 3

| ae | 4

S S_ S__ Device Size

0 O O Illegal (Indicates no SSD present) 0 0 1 32Kbyte

0 1 O 64Kbyte

Oo 1 1 128Kbyte

1 0 O 256Kbyte

1 0 1 512Kbyte

1 1 O 1Mbyte

1 1 1 2Mbyte

Register 1: This register is both a read and write register. In read mode, it is termed the Input Register. The eight bits of this register are then defined as follows:

The Se, De and Ne bits hold, on reset, the Extended Info Byte which is used in ASIC4 Extended mode to define the type of peripheral device as explained later in the section on ASIC4 reset and configuration and outlined below:

M De Ne Se 1 0 0 90 No peripheral devices 1 0 O 1 Turbo RS232 serial (16550) 1 oO 1 O 3Fax 1 oO 1 1 T.B.S. 1 1 0O 0 T.B.S. 1 1 OO 1 T.B.S. 1 1 1 O T.B.S. 1 1 1 1 Extended info contained in ROM.

The X2 bit sets the state of the X2D2 input which is used to indicate whether the device size is correct. In M=0 mixed mode, the X2 bit must be low. Inputs In0-In2 hold the current status of the three correspondingly named general input lines to ASIC4.

In write mode, Register 1 is termed the Device Size Register where bits 3-0 (S3-SO) map to the settings of the decoder inputs (and hence the peripheral device size) as follows overleaf:

Revision 1.00 Page 54 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Size Register Decoder Inputs Device Size (bytes) S3 S2 S1 SO DCO DC1 DC2

0 0 0 0 A15 Al6 Al7 32k

0 0 0 1 Al15 Al6 Al7 32k

0 0 1 =O Al6 Al7 A18 64k

0 oO 1 1 Al7 Al18 A19 128k 0 1 0 0 Al8 Al19 A20 256k 0 1 0 1 A19 A20 A21 512k 0 1 1 =O A20 A21 A22 1M

0 1 1 1 A21 A22 A23 2M

1 0 0 0 A22 A23 A24 4M

1 0 O 1 A23 A24 A25 8M

1 0 1 O A24 A25 A26 16M

1 oO 1 1 A25 A26 A27 32M

1 1 0 0 A26 A27 0 64M

1 1 0 1 A27 0 O 128M 1 1 1 = O 0 0 O 256M 1 1 1 1 0 oO O Not Used

This register defaults to OxOf on reset (i.e. not used).

Register 2: A write to this register , the Address Increment Register, will increment the addresses AO-A3.

Register3: This register is the write-only Address Register which controls all 28 address lines (AO- A27) directly and the eight chip selects (CSO-CS7) indirectly. The address register is written to in multi-transfer mode LSByte (ATO) first. There can be up to four bytes written:

Byte Address lines ATO AQ - A7 ATI A8& - Al5 AT2 Al6 - A23 AT3 A24 - A27

When the first byte is written, all the higher address lines (A8-A27) are reset to 0. Bits 4-6 of AT3 may be used by the internal address decoder to control the CS outputs CSO-CS3 if appropriate. On reset, all bits of this register are cleared.

Register 4, 5 and 6: Not implemented. Register 7: This register is the write only ASIC4 Control Register and holds the following bits:

Bit: 7 6 5 4 3 2 1 0 Label: LBO TSTA LTM VPS EDA CSS WRS OES

Setting the LBO and VPS bits causes the corresponding lines on ASIC4 to be set high enabling them to be used as general purpose outputs for peripheral development. OES and WRS control R/W accesses.

Additional ASIC4 Signals

InO, In1, In2 are general purpose digital inputs. LBO, VPS are general purpose digital outputs. OE, WR control Read/Write bus accesses. MCSD, X2D2 should be tied to ground via a 100k resister. POR is the reset line.

Revision 1.00 Page 55 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Talking to ASIC5

The Psion serial protocol was designed to allow many different peripheral ASICs to lie on the same serial channel. Before software can communicate with an ASICS it must first be selected. ASICS must be selected in different ways depending on whether it has been configured (in hardware) to operate in either Pack or Peripheral mode. In addition to selecting ASICS when it is first used, ASICS must be re-selected whenever a hold and resume is generated due to power down, pack doors opening or when the peripheral is inserted or removed. ASIC5 will always respond to a select with a byte indicating what type of peripheral or pack it is. If there is no ASICS connected to the Psion serial link there will obviously be no response (zero is returned) and software must then take the appropriate action. To select a peripheral mode ASICS the following code can be used:

HwNullFrame

mov al, (SerialSelect or Asic5NormallId) SBUSY

SCONTOUT

XNOP

SBUSY

SDATAIN

test al,al

je NoASIC5PeripheralOutThere

To select a pack mode ASICS the following code can be used.

HwNullFrame

mov al, (SerialSelect or Asic5PackId) SBUSY

SCONTOUT

XNOP

SBUSY

SDATAIN

test al,al

je NoASIC5PackOut There

Note that an ASIC4 can pretend to be an ASICS in pack mode and will respond appropriately.

ASIC5 Registers

ASICS has sixteen internal registers. To read or write from an ASICS register takes two steps. First a control byte must be sent along the Psion serial link to select which register. This should be followed by a read or write of the appropriate data value. The sixteen registers are listed in the table below. Some can be read and written to and some are read or write only.

| oO | URW PortAreadandwritedata | 6 | RW Interrupt Maskread and write | 8 | RW __| UART Status/UART Control register | 9 | R/W_| UART Receive/UART transmit holding register_| UART Baud rate LSB

| 13) | OR Barcodereaddata | 4 {| ER Synchronous Port2read

Revision 1.00 Page 56 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Reading from the Port A register causes ASICS to generate a memory access cycle. The value read from port A will be the value retrieved from any attached memory or memory mapped peripheral. Writing to Port A will cause ASICS to generate a write cycle and write the supplied value to attached memory. In both cases the address used for the access will depend on ASICS's mode and the configuration of ports B, C, and D. If the UART is enabled (Bit 0 of the port B mode register) memory cannot be accessed because port A lines are reused.

Writing to port B will cause the value written to be latched onto the output lines PBO-PB7 (which form address lines AO-A7 for memory access cycles). Reading from this register will return the last value written.

Writing to the port B mode controls various aspects of ASIC5 behaviour. The table below indicates the meanings of each bit in the register. When set to operate in counter mode the value output on lines PBO-PB7 can be incremented by reading from the port B mode register, post-incremented by reading or writing to the port A register or cleared to zero by writing to the Port D and C register.

| 0 _| 0, Memory mode. 1, Peripheral mode -enables UART____| | 6 NotUsed — a

7 Not Used

POT | Countermode POT Latch mode Pot | Baud rate outon portB

When ASICS is in pack mode the first write to the port D and C register will be latched onto lines PDO-PD7. In multiwrite mode the second and subsequent data writes will be latched onto port C with the following bits in the register forming the following functions.

| Databit_ | Pin, | Function _| a |

The bit SELO and SEL1 determine which chip select is used when a memory access cycle is generated by accessing port A. CSO-CS3 are selected as follows.

CSO

CS2

=

Revision 1.00 Page 57 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

In peripheral mode a write to the port D and C register will latch the value written onto lines PD1- PD7. In peripheral mode the line PDO forms the UART TX line. Setting bit zero in the port C and D register therefore has no effect.

ASICS is capable of generating an interrupt due to various external events. The interrupt mask register is used to select which events will generate an interrupt. Writing to the interrupt mask register will set the mask to the value written. Reading the interrupt mask register will return the current mask. The meanings of each bit in this register is given in the table below. Setting an appropriate bit to 1 will enable that events interrupt, clearing to 0 will stop that event from causing an interrupt. On reset all events are disabled.

Bit | OP UART CT UART character received

Synchronous port] character received Synchronous port2 character received | 6 [PCA Barcode data/general interrupt

When an interrupt occurs reading the Interrupt Status register will indicate the source of the interrupt. The meaning of each bit corresponds directly to each bit in the interrupt mask (see table above). A high bit indicates an active interrupt event.

Reading the Barcode data register returns a byte representing the states of the following lines.

Communicating with ASIC4

ASIC4 is capable of operating in several modes. Attached peripherals can contain an ASICS chip instead of an ASIC4. Before talking to an ASIC4 you must first ensure that there is an ASIC4 at the end of your serial link and you must set ASIC4 into the correct operating mode. You must do this when the channel is first obtained to ensure you have the right peripheral to start with, and also whenever you get a Hold and Resume due to a power down, Pack doors opening, or the peripheral being removed. You should also check the peripherals ID to check what peripheral it is. The user is more than likely to pull out your I/O port and replace it with a 3Fax in mid operation. You select ASIC4 in the correct mode by sending a special control code. If there is an ASIC4 out there it will respond by sending back a non zero value. The peripherals ID can be read back from ASIC4's info register. This register also returns the state of the input lines INO, IN1, IN2. The coding example below shows how ASIC4 can be checked for, selected and the peripheral ID checked:

HwNullFrame

mov al, (SerialSelect or Asic4Id) ; First look for an SBUSY ; ASIC4 at the other SCONTOUT ; end of the link XNOP

Revision 1.00 Page 58 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

SBUSY SDATAIN test al,al je NoAnASIC4IsItAnASIC5 mov al, (SerialReadSingle or A4InfoR) ; Now see if we SBUSY ; have the right SCONTOUT ; peripheral XNOP SBUSY SDATAIN ; Mask out the unwanted and al,0Of0h ; bits cmp al,PERIPHERAL_ID ; check for correct ID jne IsASIC4ButNotRightPeripheral ; Got our peripheral ele ; Connection Okay! ret IsASIC4ButNotRightPeripheral: + Is an ASIC4 but not popt ; the right peripheral stc ; Connection Failed! ret NoAnASIC4IsItAnASIC5: ; No ASIC4 mov al, (SerialSelect or Asic5NormallId) SBUSY ; Could have been an SCONTOUT ; ASIC5 so try to put XNOP stc ; back in the right mode ret ; Connection Failed

Bits in ASIC4’s info register have the following definitions:

Pot | Dmsb | DT Wiss | TN? TN NO Sending and Receiving data using ASIC4

All ASIC4 peripherals are memory mapped into that ASIC's address space. To access a peripheral or a particular peripheral's register the ASIC must first be told to set its address bus to the appropriate location. Once it has been informed of the address which it is to access that location can be read from or written to as many times as required. The value to be written is held in the data register. To read or write to another location the address that the ASIC is accessing must be changed. To read from a random address within the ASIC's address space the sequence would be:

1) Send a control code to inform the ASIC that it is to set its address bus to the following address.

2) Send the address to position to.

3) Send a control frame to inform the ASIC that we wish to read from this address.

4) Read back the byte.

To write a random value to and address within the ASIC's address space the sequence would be:

1) Send a control code to inform the ASIC that it is to set its address bus to the following address. 2) Send the address to position to.

3) Send a control frame to inform the ASIC that we wish to write to this address.

4) Send the byte.

Overleaf are two 8086 assembler functions Input and Output which read from or write to an address within the ASIC's address space. These functions only give access to the bottom 256 addresses. For peripheral devices this is usually more than adequate. Interrupts should always be off during calls to these functions to prevent the S3/S3a/HC from multitasking. Note that in the following routines, A4Address and A4Data refer to the value of the respective ASIC4 registers. SerialWriteSingle has the value corresponding to a single frame write in the SIBO serial protocol format. These system defines can be found in the important include files ospack.inc and ossibo.inc.

ProcBegin@ Output

; ;

; Output byte to ASIC4-based peripheral

; IN: DL holds the hardware address ASIC4 is to write to

Revision 1.00 Page 59 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

; AL holds the byte to be output to that address

push ax

mov al, (SerialWriteSingle or A4Address) ;CTRL=Write to A4 address reg

SBUSY

SCONTOUT ;Send this control frame

mov al,dl ;DATA=Hardware address

SBUSY

SDATAOUT ;Send this data frame

mov al, (SerialWriteSingle or A4Data) ;CTRL=Writing data now

SBUSY

SCONTOUT ;Send this control frame

pop ax ;DATA=Data to write

SBUSY

SDATAOUT ;Send this data frame

ret

ProcEnd noret

ProcBegin@ Input

; Input byte from ASIC4-based peripheral 7 IN: DL holds the hardware address ASIC4 is to read from ; OUT:AL holds the value read from that address

mov al, (SerialWriteSingle or A4Address) ;CTRL=Write to A4 address reg

SBUSY

SCONTOUT ;Send this control frame

mov al,dl ;DATA=Hardware address

SBUSY

SDATAOUT ;Send this data frame

mov al, (SerialReadSingle or A4Data) ;CTRL=Reading data now

SBUSY

SCONTOUT ;Send above control frame

SBUSY

XNOP

SDATAIN ;Receive data frame

ret ;AL holds the data

ProcEnd noret

Obtaining and using a channel

The s3/S3a/HC have three Psion serial links. Only one of these channels can be selected for communication at any one time. Two of these channels form the SSD slots. The third forms the expansion port. Before a device driver is able to talk to a peripheral it must both own and have this third channel selected. Many device drivers can exist in memory and more than one may access the peripheral. To prevent multiple access to a single peripheral a device driver must first own a serial channel before it is free to communicate to the ASIC4/S peripheral at the end of it. To check if a channel is free and then reserve it call the operating system function HwGetChannel. This will return with carry clear if the attempt to capture the channel was successful, carry set otherwise.

mov al, InterruptMaskForDesiredChannel HwGetChannel jc CouldntGetTheChannel

Obtaining the desired channel will usually be performed by a device drivers open vector. Open should fail if the channel is unavailable. If a device drivers takes possession of a channel it is its duty

Revision 1.00 Page 60 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

to free it again once it is finished. This would normally be done when the device drivers is closed and is performed by the operating system function HwFreeChannel.

mov al, InterruptMaskForDesiredChannel HwF reeChannel

As illustrated in the above table, on a series 3a the interrupt mask for the expansion port (Port C) is defined by A9MSlave, on a series 3 Asic2Int. Interrupts are IRQ2 and IRQ4 respectively. Only one serial link can ever be selected at one moment in time. Selecting a particular channel means that you are unable to speak to another without selecting it instead. To select a channel the operating system call HwSelectChannel is used.

mov al, SelectForDesiredChannel HwSelectChannel push ax

HwSelectChannel will return in al the channel that was previously selected. Device drivers should select the correct channel on entry to any vector or interrupt service routine that needs to communicate down that channel. On exit the previously selected channel should be restored. Between the time when the channel is first selected and when the old channel is restored multitasking should be disabled. this will usually mean switching off interrupts. Because of the watchdog timer, interrupts cannot be left off for an indeterminate length of time. Communications down channels therefore will usually be restricted to short bursts. For the expansion port the channel to select on an S3a is defined by Select Channel5 on an $3 SelectChannel7.

pushf

eli

mov al, SelectChannel5 hwSelectChannel

push ax

mov dl, AddressOfInputBuffer call Input

mov dl, AddressOfOutputBuffer

call Output

pop ax hwSelectChannel popf

Controlling ASIC5's UART

Before data can be sent or received from ASIC5's UART continuous clocking from the host must be enabled and a baud rate selected. The UART must be enabled by setting bit 0 in the port B mode register. The selected baud rate value is related to the result of dividing the required baud rate into the input clock frequency from the host of 1.536 MHz. The value generated from the equation given below forms a sixteen bit word. ASICS has two registers for selecting the baud rate. Register 10 should contain the least significant byte and register 11 the most significant byte of the calculated word value. The table below lists the divisor values for some of the more commonly required baud rates:

Divisor = 1-(96000/Desired Baud Rate)

9600 a ee ae ee 7200 fff 4800

Revision 1.00 Page 61 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

The format of data communicated, stop bits, data bits, parity checking, is controlled by writing to the UART status/control Register. Bits in the UART status/control register have the following meanings:

| 0 | Stateof the CTS line (PAI) ___| Generate break character iar

A character to be transmitted should be written to the Transmitter Holding Register where ASICS will convert it to serial form for transmission. The register will be emptied once the character has been transmitted. ASIC5 contains no internal buffering. The Transmitter Holding Register must be empty before writing a character to it. The state of the Transmitter Holding Register is reflected in the Transmitter Empty bit in the UART status register. Enabling the Transmitting Holding Register interrupt will cause ASICS to generate an interrupt every time that the Transmitting Holding Register becomes empty. Reading the UART Status Register will clear the interrupt. Received characters are copied into the Receive Character Register. If the Receive Character Interrupt is enabled ASICS generates an interrupt on each character received. If the character is received in error due either parity, framing or overrun errors, appropriate bits in the UART Status Register are set to reflect this.

Hold and Resumes

There are three types of hold and resume. The first occurs when memory is being moved. An LDDs hold and resume vectors will always be called when this occurs. The second is a On/Off Hold and resume. An LDD will always be held and resumed when this occurs although it is not guaranteed that power will have been restored to the expansion ports when the resume is issued. The third type occurs when one of the pack doors is opened or a peripheral inserted. Only certain internal LDDs receive a Hold and Resume under these circumstances. Any loaded LDD will definitely not receive a Hold or Resume. To get around these problem, the TcK: device driver is used to provide a regular call to a routine within your driver. This call monitors the power to the expansion port and issues its own holds and resumes as appropriate. Holds and resumes can become nested and the whole situation can become rather complicated. The correct procedure for dealing with holds and resumes for an ASIC4 peripheral device driver (LDD) is given below.

When a hold is received through the normal route the channel is marked as being under a normal hold. If the polling routine sees that the power has vanished and the channel is not already under a

Revision 1.00 Page 62 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

normal hold then it holds the channel and marks it as being under a special hold. If a normal resume is issued channel can be resumed but only if power is present. If power is not present then the channel is marked as being under a special hold and the resume is put off. If the polling routine sees that the power is present and that the channel is under a special hold then it should resume the channel.

Alternatively of course each time you read and write to your peripheral you could do a quick pre- check to see if the hardware is available and set-up correctly. This would dispense with the need to handle power up/down or pack door holds and resumes. You would still have to start and stop interrupts though when appropriate.

Example Device Drivers

An example device driver which will control the ASIC4 Example Interface Board described earlier can be found in the file A4EXIF.ASM. The device driver is a fully comprehensive multi-channel implementation. It supports all the mandatory logical device driver functions. Open will fail if the Interface Board hardware is not present. It has an interrupt service routine and handles Holds and Resumes correctly in all the distinct cases outlined earlier. In addition, asynchronous reads of the LED status are possible so a special routine to handle this case, the Wait Handler, is included. The driver has been made as fully comprehensive as possible both in terms of functionality and the choice of host machine. To this end, the code given can be compiled for the entire range of Psion machines simply by changing the appropriate machine Build Flag at the head of the file which then causes the correct interrupt masks to be selected for the machine. Chapter 11 of this document details the structure of A4EXIF.LDD a logical device driver constructed for the ASIC4 Example Interface Board.

Chapter 12 details the functionality of a physical device driver for the ASIC5-based Psion 3-link peripheral that enables the host hardware to communicate with a PC by converting SIBO serial protocol signals into RS232 signals. Once again, this driver contains various build flags to facilitate conditional compilation. Common interrupt routine code is included and the LDD-PDD interface is specified.

The source code for both A4ZEXIF.LDD and SYS$AS5.PDD is presented in the appendix to this document.

Revision 1.00 Page 63 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

11. AN EXAMPLE DEVICE DRIVER FOR ASIC4: A4EXIF.LDD

Introduction

In this chapter, the functionality and code structure an example installable logical device driver, A4EXIF.LDD, is presented in some depth. Circuit details of the corresponding Psion peripheral for this driver, the ASIC4 Example Interface board, were outlined in chapter 8. A4EXIF.LDD enables software written using the Psion SDK to communicate with the prototype ASIC4 Example Interface board through means of standard PLIB calls such as ‘p_open' and 'p_write’. The description of A4EXIF.LDD is intended to provide a clear insight into the generalised structure of logical device drivers for peripherals based around the SIBO architecture. To this end the actual usefulness of the combined hardware-driver interface is of secondary importance. As shown earlier, the ASIC4 Interface Board translates SIBO serial protocol signals into a parallel 8-way data bus format which can be used to set various 74HC series latches and gates. An eight-bit buffer and latch are commoned to eight LEDs. The latch is write-only and is used for setting the state of the LEDs. The buffer is read-only and is used to sense the state of the LEDs. In addition, a facility for generating hardware interrupts is provided by means of a suitably connected switch and third 8-way buffer (the status buffer). Address decoding is provided by two 2-to-4 decoders attached to address lines AO and Al.

Code Structure

Loading A4EXIF.LDD and Device Names

A4EXIF.LDD is loaded into the RAM of the host machine by means of the following PLIB call in the application code:

p_loadldd ("A4EXIF.LDD") ;

The name of a device driver is the mechanism by which an application can obtain a channel to that device driver. LDDs all have three character names which are stored in the second field of the driver's LibEnt structure followed by a colon. This name is required to uniquely identify the LDD to the OS when attempting to open a channel on it. The A4EXIF LDD has the three character name "LED" so a channel with its handle in pcb may be obtained on it by means of the following call:

p_open (&pcb, "LED:",-1);

EPOC used the driver name in the p_open call to invoke the ToOpen system service which in turn invokes the Open vector on the associated device driver.

The Single Code Segment and Data Storage

As indicated earlier, loadable Psion device drivers have a single code segment and no data segment. Data associated with the driver is stored in one of two distinct ways dependent on its nature. Global data associated with the driver is stored in its code segment. Examples of such data are the channel interrupt masks and numbers have to be visible to all processes that may be using A4EXIF.LDD. Data local to the application invoking the driver, however, is stored in the heap space of that application. An example in A4EXIF.LDD would be the pointers to the open channel strategy vector parameters.

The overall structure of the code segment is typical of Psion logical device drivers. The code segment begins with a CodeSeg directive followed by the LibEnt structure which defines the mandatory device driver functions as well as two non-mandatory ones. These are the Wait Handler and the replacement

Revision 1.00 Page 64 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Tick Interrupt Vector. Before entering the code for these functions, all global variables are declared in what is termed the device driver's internal data space. Following the code for the Lib Ent functions comes the code for all the local driver functions. After these are the EndCodeSeg and end A4ExifLDD directives.

Channel Status Ent and Open Channel Control Block

At the head of the driver's assembler source file A4EXIF.ASM, various constants, compiler defines and type definitions are listed. It is here that templates are declared for the global structures that hold the key driver variables. In view of the above discussion, most device drivers employ at least one globally defined structure to hold the various important flags and masks that relate to the status of each separate channel on that driver. In the case of A4EXIF.LDD, two different structure types are employed, namely A4ExifStatusEnt and A4ExifEnt. The former is referred to in this chapter as the StatusEnt struc and is instantiated later on in the device driver code segment with each separate permissible channel of the main Psion host machines being assigned its own StatusEnt struc. A channel's StatusEnt struc is generally accessed through CS:DI and holds important channel-related information such as the A4ExifChannelOpen and A4ExifChannelRunning flags and the channel interrupt masks and interrupt numbers. The StatusEnt structure resides in the driver code segment whereas the A4ExifEnt struc is held in the heap space of the application invoking the driver and so is accessed through DS:BX. The A4ExifEnt structure contains a number of variables that are logically associated with a successfully opened channel and as such should be distinguished from the StatusEnt variables. An A4ExifEnt struc instantiated by invoking the device driver's open vector is referred to as the open channel control block and it is generally accessed through DS:BX.

The layout of both the StatusEnt struc and the A4ExifEnt open channel control block struc are presented later in this chapter along with various other important pre-defined structs that were used in the construction of A4EXIF.LDD. Both of these structures were extensively used in the coding of the LDD functions described in the following pages.

SIBO hardware and conditional compilation

The number of expansion channels supported by a host SIBO machine is dependent on the hardware. In the case of the S3a, only one SIBO channel can legitimately be opened corresponding to expansion port A. With the HC and Workabout, it is possible to open up to three separate SIBO channels on ports A through to C. In A4EXIF.LDD, a global constant numberofchannels 1s set at the start of the device driver code segment to indicate the number of serial SIBO channels supported by the different machines. This will vary according to the Psion hardware present and in order to aid conditional compilation of the A4EXIF driver for the different host machine possibilities, a number of build flags can be used to set various constants within the include files. The hardware options with regard to these flags were outlined in the previous chapter.

It should be noted that Psion device drivers should be designed to be easily adapted from machine to machine. With the A4EXIF driver, for instance, the only change that needs to be made in adapting it for use on another Psion machine is the alteration of the build flag at the start of the code segment. This flag indicates to the compiler which SIBO machine flags as well as other variables should be set. The SIBO machine flags are in turn used later in the code segment header to set the global numberofchannels variable mentioned above. For example, in A4EXIF.LDD, we have the following:

if Corporate or Workabout numberofchannels equ 3 else

endif

This type of code is used extensively in the conditional instantiation of A4ExifStatusEnts in the device driver's internal data space. Here different interrupt masks and SIBO channels are invoked for the different machines according to the host controller ASIC. For instance, in the case of a consumer (S3a), the hardware interrupt mask corresponding to expansion port C on an ASIC9 is mask A9MsSlave and the interrupt number is HwIrq2Revector. On an Workabout, the masks for expansion

Revision 1.00 Page 65 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

ports A, B and C are A9MExpIntA, A9MExpIntB and A9MSlave respectively. The corresponding interrupt numbers are HwIrq4Revector, HwIrq5Revector and HwIrq2Revector. This conditional compilation code in A4EXIF.LDD outlined here is worthy of some study because it encapsulates all the information regarding masks and SIBO hardware channels required by the prospective developer interested in constructing a multi-platform Psion peripheral and driver.

Mandatory LDD Functions

The eight mandatory LDD functions are the Install, Remove, Hold, Resume, Reset, Units, Open and Strategy and they are all discussed in the context of the example device driver A4EXIF.LDD below.

A4Exifinstall IN: No values are passed to the install vector. OUT: If successful return with carry clear. If installation unsuccessful, return with the carry flag set and error number in the AL register.

PRESERVE: SS, SP and BP

The install vector is called by the operating system when the device driver is loaded in order to initialise any internal variables. It should not be called directly by an application process but invoked indirectly by a 'p_loadldd("A4EXIF.LDD")' call. Typically at this stage the various open channel flags would be initialised to zero but in the case of the A4EXIF.LDD, this has already been done in the appropriate A4ExifStatusEnt struc headers. As a result, the install vector merely clears the carry flag and returns.

A4ExifRemove IN: No values are passed to the remove vector OUT: If successful return with carry clear.

If installation unsuccessful, return with carry set and error number in the AL register. PRESERVE: SS, SP and BP

The remove vector is called by the operating system whenever the device driver is requested to be unloaded which is usually indirectly as the result of a call to 'p_devdel ("LED", E_LDD)'. ROM- resident drivers cannot be deleted so any attempt to invoke this vector on them will result in an error being returned. The code for the remove vector checks to see that all the device driver channels are closed and returns carry clear if this is the case. In the case of A4EXIF.LDD, a closed channel will hold a zero in its corresponding StatusEnt open channel flag. If any of the open channel flags is non- zero then the carry flag is set before returning indicating that an attempt has been made to unload a device driver that still holds at least one open channel. In the case of A4EXIF.LDD, the numberofchannels flag is used as a loop counter for the different hardware channel possibilities in a similar manner to the corresponding code in the open vector.

A4ExifHold

IN: AH register holds one of the following values: DevHoldNormal, DevHoldPowerDown Or DevHoldPowerFail

OUT: None

PRESERVE: SS, SP and BP

The hold vector is called by the operating system whenever the device driver is requested to be held. This can occur as a result of three conditions which result in the three different possibilities for the value held in AH:

1. Device memory segments about to be moved. AH holds DevHoldNormal.

Revision 1.00 Page 66 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

2. Machine about to switch off due to power-save time-out or the off switch being pressed. AH holds DevHoldPowerDown.

3. Machine about to switch off due to power source being removed or the batteries failing. AH holds DevHoldPowerFail.

The hold vector code must be able to conduct a rapid shut down of the device driver because in the case of DevHoldPowerFail, the driver may only have a couple of ms before internal voltages fall to an unworkable level. The EPOC OS automatically handles the three cases highlighted above but in Series 3a machines and the Workabout, in addition to these there is another situation that requires the invocation of the hold vector, namely the opening/closing of the SSD pack doors on an S3a or Workabout. This is an action which can only be detected by means of software polling which requires the setting up of the ROM-resident "TcK:" device driver so that the door status can be checked each system tick (i.e. 32 times a second). The section on A4ExifTickInt provides a more detailed outline of the TCK interrupt code required to handle pack door opening and closing. It is this latter routine that polls for the open or closed status of the host machine doors, setting the global HoldFlag accordingly. The Hold vector code thus includes a check on the status of the HoldFlag and is generally optimised to be as efficient as possible. An outline of the structure of A4ExifHold presented below. It follows the pattern for a typical device driver:

e Check the state of the global HoldFlag.

e If the flag is non-zero, then the driver is already held and the function returns without taking any further action.

e = If the HoldFlag is zero, then the function checks the status of all the channels that the driver is permitted to open. If any of these channels have their open channel flags cleared, it is not necessary to do anything as part of the process of holding the channel. Only in the case when the flags are set is the 'stopChannelRunning’ function invoked. As with the similar loop in the Reset vector, the global numberofchannels is used as the loop counter as each of the possible channels has to be checked.

A4ExifResume IN: None OUT: None

PRESERVE: SS, SP and BP

The resume vector is called by the operating system to restart a held device driver. Resume will be called after a hold caused by any of the four possibilities indicated above in the section on A4ExifHold but it should be noted that in some cases, ASIC4 will only be switched on after the call to resume. The device driver is expected to recover from the previous hold and resume any suspended I/O except in the case of power failure where the resume vector ought to power up the peripheral and put it into a known state indicating to the user that data may have been lost. The resume vector will also have to handle the reinstallation of any interrupt service routines by checking the status of the open channel flag.

e Check the state of the global HoldFlag.

e If the flag is zero, then the driver has already resumed so return without further action.

e If the flag is non-zero, then check the door status of the host machine with a call to the OS HwGetSsdData service. If the doors are open, then set HoldFlag to 2 to signal this position to the driver. If the doors are closed, then numberofchannels is used as a loop counter while the open channel flags of each of the permissible channels for the host hardware are checked. Only if these flags are set is the 'start TheChannelRunning’ function invoked.

A4ExifReset IN: BX holds the device driver device handle CX holds user specified channel identification data. In this case, holds the address of the status struc identifying the open channel to be reset. OUT: None

Revision 1.00 Page 67 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

PRESERVE: SS, SP and BP

The reset vector enables a device driver to reset itself when the application which owns the device driver terminates abnormally before closing one or more open channels on that driver. The vector is only invoked by the operating system if it has been primed by means of a call to the ToRequestReset operating system service in the open vector. Such a call must be balanced by a corresponding call to IoRequestResetCancel in the close function code of the strategy vector. Registers BX and CX are required to be set up by the user prior to invocation of either of these services. BX should contain the device driver handle which is passed through DX in the open vector. CX should hold any suitable open channel identification data that can be accessed in the driver's internal data space (i.e. through CS:DI). In the case of A4EXIF.LDD, this information is the address of the channel StatusEnt structure. If a device driver is only capable of opening one channel, then it is irrelevant what CX holds. A reset should only be outstanding while some process has a channel open on the device driver. The format of A4ExifReset is similar to that of a typical reset vector and can be summarised as follows:

e Move the address of the channel status Ent from CX into DI.

e Check the value of the corresponding cs:[di].A4ExifChannelOpen flag.

e If channel is not open to reset, then return from the vector otherwise call "StopTheChannelRunning’ and use HwFreeChannel to release the SIBO serial channel. Set the ChannelOpen flag to zero.

A4ExifUnits IN: None OUT: AX holds the number of channels supported.

PRESERVE: SS, SP and BP

The A4ExifUnits function is called by the operating system when the device driver is requested to report the number of units (or channels) that it can support. This is primarily useful for purposes of information.

A4ExifOpen

IN: DX contains the device handle of the device driver SL is a pointer to an OpenEnt struc BP is a pointer to an IntEnt struc DS, ES point to the application process's data segment OUT: If successful return with carry clear and the address of the open channel in BX. i.e. BX holds the address of an A4ExifEnt struc which contains various fields of information concerning the open channel. If installation unsuccessful, return with carry set and error number in the AL register. PRESERVE: DS, ES, SS, SP, BP and DX

The open vector is called by the operating system when a channel to the device driver is required to be opened. The device handle, which is passed through DX, is used by the operating system to route any I/O requests on the opened channel to the correct device driver. An LDD must place this handle in the ChanLibHandle field of the ChanEnt struc of the open channel structure allocated within the application's data segment. In the case of A4EXIF.LDD, this structure is the A4ExifEnt struc described in the Appendix to this document. The open vector of a device driver runs in the context of the process that has called p_open to open a serial port on that device driver.

The OpenEnt struc consists of three fields , OpenNamePtr, OpenMode and OpenChan. The OpenNamefPtr points to the character immediately following the device name as passed in the p_open call. For instance, in the case of A4EXIF.LDD, the OpenNamePtr would point to the colon after LED in the name "LED:". The OpenMode field contains the mode for opening the device driver

Revision 1.00 Page 68 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

which is not used in this example. The OpenChan field holds the I/O channel handle of the device that the driver is required to 'attach' to. Attached drivers add functionality to, or replace, a service provided by an underlying device driver. The IntEnt struc pointed to by BP can be used to reload the various segment registers if their contents have been altered. The A4ExifEnt struc requires further elaboration. It consists of four fields: A4Exiflo, A4ExifHandlerPtr, A4ExifStatusPtr and A4ExifA1Ptr. A4ExifHandlerPtr contains a handle to the driver's WaitHandler, A4ExifHandler. This is the routine required to handle the completion of asynchronous I/O requests and is described in more detail later on in this chapter. Of the remaining fields, A4ExifStatusPtr holds the location of the completion status word for I/O requests and A4ExifA1Ptr is a user-defined parameter. These two values are passed to the strategy vector through the RqEnt structure. A4Exiflo is itself a ChanEnt struc with sub fields ChanSignature, ChanNext and ChanLibHandle. After initialisation of this structure, [bx]. A4Exiflo.ChanSignature must hold 'TochanSignature’ and [bx].A4Exiflo.ChanLibHandle holds the handle to the device driver (stored in DX). Both of these values are again required by the strategy vector. The [bx].A4Exiflo.ChanNext field is used by attached drivers and is set to 0 for root drivers like A4EXIF.LDD.

The code in an open vector follows a similar pattern in many LDDs and is presented in outline form below:

e Determine the channel to be opened using the pointer to the device name held in [si]. OpenNamePtr.

e If OK, disable interrupts and invoke the OS HwGet Channel call.

e If OK, then set A4ExifChannelOpen flag to non-zero.

e In order to poll for door-opening and closing, it is necessary to open a "TcK:" channel at this stage and initialise it by means of using the OS IowithWait service to call the TickInt vector on each system tick.

e Re-enable interrupts and set up the calling process id using the ProcId service.

e Check for the presence of the required hardware. If present return with carry clear.

e Allocate space in calling process' heap (i.e. the application data space) to contain the I/O channel control block (an A4ExifEnt struc in the case of A4AEXIF.LDD) and set its base address to BX (thus BX holds the address of the open channel control block).

e If OK, install the device driver Wait Handler using the IoAddHandler system service. A Wait Handler is required only if there are any asynchronous I/O requests to be handled.

e If OK, initialise the fields inside the I/O channel control block that were outlined above.

e Invoke IoRequestReset system service to handle unexpected termination of main program by invoking the driver's Reset vector.

e Before leaving the Open vector, if the call succeeded, BX must hold the open channel control

block handle. A4ExifStrategy IN: BX holds the allocated channel control block initialised in the open vector

DX contains device handle of the device driver in the case of an LDD

SL is pointer to RqEnt struc

BP is pointer to IntEnt struc

DS, ES point to data segment of application making the I/O function request

OUT: If successful return with carry clear. Furthermore, in this case, if the strategy vector is meant to complete the I/O request (as is the case with IoClose for instance) then the completion status should be written back to RqStatusPtr location and the I/O semaphore signalled by calling IoSignal. If the I/O request is not completed by the strategy vector (as is the case with the asynchronous functions IoFuncRead and IoFuncWrite) then PendingErr should be written back to the location pointed to by

RqStatusPtr and the I/O semaphore should not be signalled.

If installation unsuccessful, return with carry set and error number in the AL register. PRESERVE: DS, ES, SS, SP and BP

Revision 1.00 Page 69 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

When an application makes a I/O request on the opened device driver channel, the request is routed to this vector by the operating system. A device driver defines the set of strategy functions that it supports such as IoFuncSet, IoFuncSense, IoFuncWrite and IoFuncClose. The functions of a device driver are usually dependent on its purpose and there is no requirement to support any particular function. The ordering of these functions in the strategy vector table is defined in p_file.h and presented in A4EXIF.ASM.

The SI register contains a pointer to an RqEnt struc which consists of four fields: RqFunction, RqStatusPtr, RgA1Ptr and RqA2Ptr. RqFunction contains the function number passed to the I/O request by the application. In the device driver strategy vector code, the value held in RqFunction is compared against the supported function numbers held in ToFuncClose, IoFuncRead etc. If the function number is not one of those supported then a call to IoRoot is necessary in the case of a root device driver such as A4EXIF.LDD. toRoot chains the I/O request through to the operating system which runs some default code to handle it. RqStatusPtr is a pointer to a memory location in the application data space which holds the value of the I/O request's completion status word. While a request is outstanding, this value is set to PendingErr and only when it completes does a completion code get written to this location. I/O requests can complete within the strategy vector or later after an interrupt. Often as is the case with A4EXIF.LDD, only a single request of any one kind can be outstanding at any time otherwise the application is panicked. RqA1Ptr and RqA2Ptr hold the values of two parameters that are passed to the IoAsynchronous EPOC service. Each synchronous strategy function has a similar pattern with explicit I/O being conducted whilst interrupts are disabled and a completed request being signalled with an OS ToSignal call prior to exit from the function. This call signals to the OS the completion of the particular I/O request entailed by the function call. The situation with regard to the one asynchronous strategy function is somewhat more complicated and is dealt with in greater detail in a later section.

The structure of the strategy vector of A4EXIF.ASM is outlined below:

e Determine the strategy function number using [si].RqFunction and compare with the below:

e JIOFUNCREAD: Asynchronous read of latches U4 and U3. Panic if [bx].A4ExifStatusPtr != 0. Update [bx].A4ExifA1Ptr and [bx].A4ExifStatusPtr with [si].RqA1Ptr and [si].RqStatusPtr respectively as the locations to be accessed on receipt of interrupt. Move PendingErr into the location pointed to by [bx].A4ExifStatusPtr to signal that the request is awaiting completion. Allow handler to be enabled through the IoEnableHandler OS call and exit without signalling completion of the request.

e IOFUNCWRITE: Identical behaviour to that of IoFUNCSET which it calls.

e TIOFUNCCANCEL: Used to cancel any pending asynchronous reads. This involves disabling the wait handler, consuming any stray signal from the interrupt routine by means of an OS IoWaitForSignal call and then storing cancelErr in the channel I/O request status word.

e IOFUNCCLOSE: Close down the TCK channel and remove handler. Disable interrupts and HwFreeChannel setting A4ExifPid to 0 before re-enabling interrupts. Invoke IoRequestResetCancel system service and HeapFreeCell. Signal completion of I/O request by calling IoSignal system service.

e IOFUNCSENSE: Reads the status and LED bytes from latches U4 and U3 respectively storing the results at the addresses pointed to by RgA1Ptr and RqA2Ptr.

e IOFUNCSET: Sets latch U5 to contain the value pointed to by the sole argument in the call to P_FSENSE.

e If not supported then call IoRoot system service.

The Non-Mandatory LDD Functions

The eight functions described above must be supported by all device driver. Typical Psion LDDs employ at least two other LDD functions. The first of these is a pseudo-interrupt routine which is invoked by the OS on each system tick. In A4EXIF.LDD, this function is represented by A4ExifTickInt and an outline of its purpose was presented earlier in the discussion on holding and

Revision 1.00 Page 70 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

resuming device drivers. As was indicated then, the minimum functionality required by this routine is to poll the status of the host machine doors and if appropriate call the driver's Hold and Resume vectors. If in addition the LDD is intended to service any asynchronous I/O requests, a wait handler and common interrupt service routine are required. With A4EXIF.LDD, these two additional functions are represented by A4ExifHandler and ComInt respectively. The former function constitutes the second of the additional LDD functions as can be seen by examining the LibEnt structure for A4EXIF.LDD. The latter function is set up so that it replaces the default interrupt service routine code invoked by the OS on the receipt of hardware interrupts on the peripheral's SIBO channels. A4ExifHandler is invoked by the OS every time the I/O semaphore of the process that opened the channel is signalled with through an IoSignalByPidNoResched call indicating that an interrupt has been received and an outstanding I/O request has completed. The function of the wait handler is to deal with I/O semaphore signalling and to update the appropriate open channel control block field variables. The common interrupt service routine code in ComInt cannot do this because it is not permitted to access the application data space. This in turn is because the routine runs in the context of the process which was running when the interrupt occurred. A4ExifTickInt, the wait handler and the common interrupt service routine for A4EXIF.LDD as well further details as to how the latter two interact to handle asynchronous I/O requests are described below.

A4ExifTicklint

As was explained earlier in discussing the A4ExifHold vector, it is necessary to utilise the "TcK:" system tick device driver in order to handle the particular case of invoking a hold on A4EXIF.LDD when the host machine SSD pack doors are opened. Such an action automatically causes power to be removed from any peripherals. The TCK driver is opened via an OS Toopen call in the A4ExifOpen vector which returns with carry clear and a non-zero handle in AX if successful. In this case, the IoWithWait function is called to request an synchronous I/O service from the TCK driver. Prior to this call, the service number requested is held in AL and the I/O handle procured from the previous call to ToOpen is loaded into BX. The interrupt number of the tick poll routine, A4ExifTickInt, is loaded into CX so that as its parent driver is invoked on each system tick, the OS enters this vector. The reason the TickInt routine is required in A4EXIF.LDD is solely to handle the problem of recognising a sudden removal of power from the host machine. The OS has no way of testing for this condition other than polling its global 'Doorstatus' variable every system tick and taking the requisite course of action. As such, the outline of the code for the tick poll routine which is required in all Psion LDDs can be presented below. This outline should be carefully compared with the structure of the Hold and Resume vectors shown earlier in order to see how they interact:

e Check the current status of doors which is held in SI. e¢ If DoorlsOpen then if global HoldFlag is zero, force a call to A4ExifHold, set HoldFlag to 2 and return far else do a far ret e = Else if DoorIsClosed then if global HoldFlag is 2, force a call to A4ExifResume and return far else do a far ret

It should be emphasised that A4ExifTickInt is only a pseudo interrupt service routine in that it does not preserve the status of the registers which is something that the device driver writer must undertake to ensure is done explicitly.

The handling of synchronous and asynchronous I/O

The provision of synchronous and asynchronous I/O services are an important aspect of writing any device driver. In the case of Psion drivers, all such services are the provided through the Strategy vector which is typically preceded by a Strategy Vector Table listing the complete set of I/O services that can be invoked on the driver. The strategy vector table for A4EXIF.LDD is presented below to provide an indication as to the kind of service routines that can be written:

StrategyVectorTable label word

Revision 1.00 Page 71 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

dw offset A4ExifDefault 7StrategyPanic

dw offset A4ExifRead ;StrategyRead (function define is P_FREAD)

dw offset A4ExifWrite ;StrategyWrite (function define is P_FWRITE) dw offset A4ExifClose ;StrategyClose (function define is P_FCLOSE) dw offset A4ExifCancel ;StrategyCancel (function define is P_FCANCEL)

dw offset A4ExifDefault 7StrategyAttach

dw offset A4ExifDefault 7 StrategyDetach

dw offset A4ExifSet ;StrategySet (function define is P_FSET)

dw offset A4ExifSense ;StrategySense (function define is P_FSENSE)

Both synchronous and asynchronous I/O requests can be made on the driver through means of the PLIB 'p_iow (pcb, <func>, &A1, &A2)' call where pcb is the open channel handle, <func> is one of the above function defines and Al and A2 are two optional parameters required for the servicing of the request. The routing of an I/O request to the correct service code is done by the common code at the head of the strategy vector. Each time this vector is entered, BX holds the address of the open channel control block, DX the device handle of the device driver and SI a pointer to the strategy RqEnt struc used by the OS to follow the course of the I/O request. Using this information, it is possible to access all the relevant flags in the channel StatusEnt by moving [bx].A4ExifStatusEntPtr into DI. This leaves us with the open channel control block in DS:BX and the channel StatusEnt in CS:DI.

Armed with the above information, it is possible to outline the general pattern of both synchronous and asynchronous I/O requests at an OS level. The case of synchronous requests is particularly straightforward since the servicing of the request can be completed entirely within the relevant strategy vector table function. It should be emphasised that in the outline presented below, disabling and re-enabling of interrupts only actually has to be done around any I/O.

SYNCHRONOUS I/O REQUEST STRATEGY VECTOR TABLE FUNCTION

pushf cli ;Disable interrupts < request service code > ;Relevant synchr. I/O processing

ExitWithCompletionStatusZero: < set I/O request status word to zero >

IoSignal ;Signals completion of I/O to OS XOr ax, ax

onl ol ;Tells OS that strategy exited OK popf ;Re-enable interrupts

ret

ProcEnd noret

Note that in the above outline, the single ToSignal call is made after completion of the I/O request in order to signal this fact to the OS. The situation is somewhat more complicated in the case of an asynchronous request because the I/O request strategy vector table function has to interact with both a wait handler function and an interrupt service routine. Of the I/O request services outlined above for A4EXIF.LDD, only one, namely A4ExifRead, is asynchronous and it serves as a good illustration of the nature of programming for asynchroneity. The steps taken in the A4ExifRead vector are outlined below:

e = Set the ChannelReadCompleted flag to 0 (stored in cs:[di]. A4ExifChanReadCompleted) e If the address of the I/O request status word is non-zero then panic (i.e. there is an outstanding read request)

e Update the open channel control block variables using the RqEnt struc

e Load I/O request status word with PendingErr

e Enable the wait handler by using the To—EnableHandler OS service The read request is now in a pending state waiting for completion via receipt of a hardware interrupt. When such an interrupt is received, the OS switches into the appropriately configured common interrupt routine ComInt. Here, the channelReadCompleted flag is set to indicate to the handler that the read request has completed. An IoSignalByPidNoReSched OS service call is also made to indicate to the OS that an as yet unspecified I/O request has terminated. This signal is consumed by the OS which means that at this stage, an IoSignal for completion of the original asynchronous request has yet to be made. The interrupt service routine exits after sensing the status and LED byte values from the ASIC4 Example Interface Board and loading the appropriate response bytes into the relevant locations in the device driver code segment. More details as to the functionality of the interrupt service routine are provided in the section on interrupts. The OS now invokes all the currently active wait handlers in order to determine which application is responsible for consuming

Revision 1.00 Page 72 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

the completed read. The wait handler code includes the all-important IoSignal call that indicates to the OS that the original asynchronous read request has finally been accounted for. Receipt of this signal by the OS constitutes completion of the request. The outline code for the A4EXIF.LDD wait handler A4ExifHandler is outlined in the next section.

A4ExifHandler

A WaitHandler is a special function of the LDD which is nominated to be called by the operating system every time the I/O semaphore of the process that opened the channel is signalled. It will only actually be called if the application is already waiting for an outstanding I/O request to complete (1.e. while the application is hung in p_iowait). The handler function is the means by which hardware interrupts can be filtered through to the process which opened the I/O channel since it permits the rescheduling of processes.

The WaitHandler is invoked in the open vector by using the IoAddHandler system service. When an application makes an I/O request, the I/O semaphore is signalled and the operating system calls the Wait Handler function while the application is waiting for the request to complete. The wait handler returns with CLC if no outstanding request has completed. Otherwise the wait handler returns with STC and zero in AL. The wait handler can include within it synchronous I/O requests to cancel or use up signals but it is not entered recursively (i.e. re-enterently) by the operating system. A wait handler is best viewed as a necessary requirement in dealing with the I/O semaphore signalling which cannot entirely be addressed in the appropriate interrupt service routine because the latter is not able to access the open channel's control block.

Interrupts and Interrupt Service Routines

The SIBO architecture allows for eight separate hardware interrupt sources. The EPOC operating system provides a GenSetRevector service to enable a device driver to install an interrupt service routine for any of these eight interrupt sources. When an interrupt occurs, the operating system preserves the state of all the registers before calling the appropriately-installed interrupt service routine. As a result of this, the interrupt service routine is free to employ any register it sees fit to use. A few important points ought to be made concerning the code within an interrupt service routine:

e On an 8086 processor, interrupts cannot be nested so their is no requirement to disable interrupts whilst inside the interrupt service routine.

e Interrupt service routines should operate as fast as possible. In general, operating system service routines are tuned to be of less than Ims duration.

e Interrupt service routines run in the context of the process that was running at the time of the interrupt and should access only the device driver data space which, as with A4EXIF.LDD, typically resides in its own CS space.

e Interrupt service routines should not cause a process rescheduling. To indicate that an event has occurred to the interrupted process, the ToSignalByPidNoResched system service should be called. If a call is made to this service, the interrupt service routine should exit with CLC otherwise it returns with STC.

The interrupt routines called require knowledge as to the particular hardware SIBO channel being used by the driver at the time an interrupt occurs. This information is passed through to the GenSetRevector function in StartInterrupts by loading the address of the appropriate Int Vec routine from the A4ExifChannelIntVec field of the channel StatusEnt struc. As a result, when an interrupt occurs, the currently loaded IntVec routine is invoked. All the Intvec routines reload DI with the appropriate address of the channel StatusEnt in the device driver code segment before falling through to the common interrupt routine service code held in ComInt.

Comint

Revision 1.00 Page 73 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

The common interrupt service routine code resides in the ComInt vector. The structure of this code is presented below. It should be emphasised that no data in the application data space and hence in the open channel control block can be accessed from ComInt. This explains why it is necessary for the OS to invoke a wait handler to clean up after the interrupt service routine code for a particular asynchronous I/O request has been run.

e Check the value held in the chanReadCompleted flag

e If this value is 2 then we do not have an asynchronous read completed but rather the interrupt line has been pulled low outside of an asynchronous I/O request.

e If this value is 1 then we have an asynchronous I/O request completed and so IoSignalByPidNoResched must be invoked to signal to the OS that a read has completed.

e In both cases, sense the status and LED bytes from the Example Interface hardware and load these values in the device driver's code segment A4ExifStatusEnt struc.

e There are four possibilities of status byte corresponding to the four combinations offered by the two input switches, S1 and S2. These are used to output one of four separate LED bytes to the LEDs.

e Awrite to AlNonSpecificEoi register (or A9BNonSpecificEoiW in the case of an ASIC9 machine) must be done prior to exiting to let the OS know that the installed interrupt service routine has terminated.

Other important local device driver functions

The functions presented in this section are local to A4EXIF.LDD and perform various important tasks relating to the peripheral hardware such as groping the hardware and setting interrupts running. Since these tasks have to be undertaken by most device drivers, the relevant functions are outlined in greater detail.

A4ExifCheckHardwarePresent

Every Psion device driver has a characteristic 'CheckHardwarePresent’ or 'GropeHardware" function that usually involves checking for the presence of the required peripheral device by means of comparing a couple of ASIC4 identification bytes returned by the peripheral in response to a SIBO serial protocol identification message with the expected answers. The specific value of the InfoByte is unimportant as long asa "test al, al" call is made which will always return a non-zero answer if ASIC4 is present. In that case, the extended info byte should be tested for against what is expected from address lines A23-A27.

Psion Workabout/HC machines have three physical serial links and two of these are accessed via the SSD slots. The third link corresponds to the serial expansion port. In order for a driver to talk to a peripheral connected to this port, it must specifically select this serial link. In order to prevent multiple access to a single peripheral, it is necessary in the first instance to check whether the serial channel is free or not. A call to the operating system function HwGet Channel with the appropriate interrupt mask in AL returns with CLC if the channel was captured successfully. Logically this call should be made in the Open vector but since it can only sensibly be made after the hardware has been successfully located it can be placed at the end of the GropeHardware function. A corresponding call to HwFreeChannel must be made when closing the channel. To actually select a channel prior to communication along it, a call to HwSelectChannel Is necessary.

A4ExifStartChannelRunning

This function is called at the end of the Open vector to set the ASIC4 Example Interface hardware running. It can also be invoked by the Hold vector. The function first checks the status of the global StatusEnt ChannelRunning flag. If this flag is clear, CheckHardware is called to determine whether the hardware is still connected and then StartInterrupts is called before the channelRunning flag is

Revision 1.00 Page 74 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

set to indicate that the channel hardware has been started. The function returns with CLC on successful completion or with STC if no hardware was located.

A4ExifStopChannelRunning

This function simply clears the channelRunning flag if set and calls StopInterrupts unless the channel already has its ChannelRunning flag clear. The StopChannelRunning function will be called by Strategy vector when trying to close a channel and can also be called by the Resume vector.

A4ExifStartinterrupts

StartInterrupts is called whenever a call is made to StartChannelRunning. At the heart of the function is a call to the OS GenSetRevector function which is used to install a specified interrupt service routine in the place of the default routine held in the interrupt vector table. GenSetRevector is called with the interrupt vector number of the service to be replaced in AX and the offset and code segment of the replacement interrupt vector service in BX and CX respectively. BX is loaded from the ChannelIntVec field of the channel StatusEnt which holds the name of the specific interrupt service routine code (i.e. IntVecO, IntVec1 etc.). The latter functions set up the appropriate channel- specific variables before falling through to the common ComInt routine. The channel interrupt mask which is machine and channel dependent is written to the appropriate register on the host ASIC. In the case of ASIC9, this register will be A9BInterruptMaskRW. For ASIC1 it will be AlInterruptMask.

A4ExifStopInterrupts

StopInterrupts reinstalls the original interrupt service routine by invoking the GenResetRevector OS system service and signalling the interrupt mask to the corresponding host ASIC register.

Structures and Include files

Epocdef.inc and device driver strucs

Epocdef.inc is an important header file that contains the definitions of various strucs extensively used in the construction of device drivers. It also contains the definitions of all the OS error values such as DeviceErr and NameErr that are used in A4EXIF.LDD to communicate an error to the application via AX. Listed below and overleaf are the key strucs defined in Epocdef.inc that were used in the coding of A4EXIF.LDD.

LibEnt struc Start of device driver LibSignature dw ?

LibInfo dw 2

LibCount dw ?

LibBase dw ?

LibEnt ends

OpenEnt struc Pointed to by SI in Open vector OpenNamePtr dw ?

OpenMode dw ?

OpenChan dw ?

OpenEnt ends

ChanEnt struc Used in open channel control block ChanSignature dw 2

ChanNext dw ?

ChanLibHandle dw ?

ChanEnt ends

IntEnt struc Pointed to by BP in Open and Strategy vectors IntFrame dw ?

IntBP dw ?

IntES dw 2

IntDS dw ?

Revision 1.00 Page 75 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

IntPC dw ? IntCs dw 2 IntFLAGS dw ?

IntEnt struc ends

RqEnt struc Pointed to by SI in strategy vector RqFunction dw 2 RqA1Ptr dw ? RqA2Ptr dw ? RqStatusPtr dw ?

RqEnt struc ends

A4EXIF channel strucs

These are defined at the start of the A4EXIF.LDD code segment. The open channel control block is held in a structure of type A4ExifEnt and is allocated space from the heap of the process invoking the device driver's open vector. As such, it cannot be accessed from the Hold, Resume and Reset vectors or from the interrupt service routine, ComInt. The channel StatusEnt holds various key channel related flags. Each hardware channel has its own StatusEnt which is instantiated in a header in the device driver code segment following the LibEnt structure. This header block is usually held in CS:DI which is how the StatusEnt variables are accessed. The structure of both A4EXIF channel strucs is shown below:

A4ExifEnt struc OPEN CHANNEL CONTROL BLOCK A4xifIo ChanEnt<>

A4ExifHandlerPtr dw ? Pointer to the Wait Handler A4ExifStatus dw ? Address of I/O request status word A4ExifAlPtr dw ? Pointer to first argument

A4ExifA2Ptr dw 2. Pointer to second argument A4ExifStatusEntPtr dw ? Pointer to channel's StatusEnt A4ExifTickHandle dw ? Handle to the TCK device channel

A4ExifEnt ends

A4ExifStatusEnt struc CHANNEL STATUS_ENT

A4ExifChannelPid db ? Process id of process holding channel open

A4ExifChannelOpen db 2 Is the channel open or not? A4ExifChannelRunning db ? Is the channel running? A4ExifChanReadCompleted db ? Flag used to indicate to handler when

A4ExifChanneliIntMask db ? Contains the HW channel interrupt mask A4ExifChannelIntNum db ? Holds no. of interrupt vector to be replaced

A4ExifChannelSelect db 2 SIBO channel select flag A4ExifChannelDummy db 2 Spare

A4ExifChanneliIntVec dw ? Holds replacement int. vector routine name

A4ExifStatusEnt ends

Ossibo.inc and Ospack.inc

Ossibo.inc is an important header file that contains the defines for all the ASIC2 and ASIC9 register addresses. Ospack.inc contains similar information but for ASIC4.

Revision 1.00 Page 76 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

12. AN EXAMPLE DEVICE DRIVER FOR ASIC5: SYS$AS5.PDD

Introduction

In this chapter, the functionality and code structure an example installable physical device driver, SYS$AS5.PDD, is presented in some depth. Circuit details of the corresponding Psion peripheral for this driver, the Psion 3-link, were outlined in chapter 8. SYS$AS5.PDD enables software written using the Psion SDK to communicate with the 3-link peripheral through means of standard PLIB calls such as ‘p_open' and 'p_write'. This peripheral incorporates an ASICS as the SIBO serial protocol slave device. As explained earlier in chapter 7, ASICS has an on-board 16550 UART which means that it can be used in conjunction with the standard serial LDD provided an appropriate PDD is loaded. SYS$AS5 is a PDD intended for this purpose and its description in this chapter provides a clear insight into the generalised structure and construction of physical device drivers for peripherals based around the SIBO architecture.

The LDD-PDD interface

All Psion device drivers have a LibEnt structure at the head of their code segment which includes a vector table defining the functionality of the driver. In the case of SYS$AS5, four vectors are defined. These are: Install, Remove, Open and Strategy. The structure of the first three of these are fixed for most device drivers but the fourth can be specified in any way. This fourth vector defines the LDD- PDD interface and is constructed to allow the two drivers to best communicate with each other. In the case of serial PDDs, the approach taken is modelled on the LDD strategy vector with the corresponding strategy vector table and function numbers. This is a logical choice but it is important to emphasise that the LDD-PDD interface is completely user-definable and that the approach described in this chapter is optional.

The key feature of any LDD-PDD interface is that the LDD must have no explicit concept of hardware. In the case of the serial LDD, for instance, it knows that it has a serial port that it can read data bytes from or write data bytes to but it is ignorant of the explicit implementation of the hardware at this port. That aspect is handled by the corresponding PDD which handles all the specifics of data byte I/O. In the case of an application writing a buffer to the serial port by means of a p_iow(P_FWRITE....) call, for instance, the LDD will first copy the data in the application's DS into a local CS buffer. It will then call the PDD to indicate that it intends to start sending data bytes when the PDD is ready to start receiving. When the PDD is ready to commence sending a byte out of the serial port, it calls a function (TransmitByte) in the LDD. This function reads the next byte to be transmitted from its local buffer and hands it to the PDD. The PDD duly transmits the byte and again calls TransmitByte until all the bytes are completed. The LDD then sends a special 'NothingToSend' signal to the PDD which indicates that transmission is finished. The LDD also sends an IoSignalByPidNoResched which causes its wait handler to be invoked by the OS. In this way, the IoSignal that signifies completion of the original write request is invoked by the LDD. Note that the LDD has no concept of interrupts, merely of sending a byte at a time and registering completion or otherwise of I/O requests. Futhermore, the PDD never takes the initiative from the LDD and merely undertakes one function at a time before returning control back to the LDD. The LDD-PDD interface is examined in greater depth later in this chapter when the structure of the PDD strategy vector is presented.

Revision 1.00 Page 77 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Code Structure

Device Names and Loading SYS$AS5.PDD

SYS$AS5.PDD is loaded into the RAM of the host machine by means of the following PLIB call in the application code:

p_loadldd("SYSS$AS5.PDD") ;

The name of a device driver is the mechanism by which an application can obtain a channel to that device driver. LDDs all have three character names followed by a period, a further three characters and acolon. The first three characters of a PDD name are the name of the LDD to which the PDD belongs. The second set of three characters uniquely identify the PDD. The device name is required to uniquely identify the LDD to the OS when attempting to open a channel on it. The SYS$AS5 PDD belongs to the "TTY:" LDD. Its name as defined in its LibEnt structure is 'TTY.SR5'. Thus a channel with its handle in pcb may be obtained on it at the application level by means of the following call:

p_open (&pcb, "TTY.SR5:A",-1);

The qualifier after the colon indicates that the driver can support more than one channel. Channels are allocated a single character sequentially from the character 'A' up to the character 'C'. The number of channels that can be supported in this way is dependent upon the host hardware. Only one expansion port can be opened on the S3a for instance whereas three are possible on the Workabout and HC. EPOC uses the driver name in the p_open call to invoke the ToOpen system service which in turn invokes the Open vector on the associated device driver.

The Single Code Segment and Data Storage

All data associated with a physical device driver must be stored in its code segment. Examples of such data are the channel interrupt masks and numbers that have to be visible to all processes that may be using SYS$AS5.PDD.

The overall structure of the code segment is typical of Psion physical device drivers. The segment begins with a CodeSeg directive followed by the LibEnt structure which defines all the device driver functions. Before entering the code for these functions, all global variables are declared in the internal (CS) data space. Following the code for the LibEnt functions comes the code for all the local driver functions, After these are the EndCodeSeg and end OsAs5PDD directives.

The Channel struct and A5Ent struct

At the head of the driver's assembler source file, SYS$AS5.ASM, various constants, compiler defines and types are listed. It is here that templates are declared for the global structures that hold the key driver variables. in the case of SYS$AS5, one main structure, the Sr5ChannelStruct, is employed to hold the various important flags and masks that relate to the status of each separate channel on the driver. This structure is termed the Channel struct and its fields are filled in during the course of running the PDD install and open vectors. Whenever the serial LDD invokes one of the PDD functions, the application must ensure that CS holds the address of the PDD's code segment which is where the Channel struc resides. The channel's Channel struct is usually accessed through DI or BX depending on preference. Its layout is presented later in this chapter along with other important defines that were used in the construction of SYS$AS5.PDD.

SIBO hardware and conditional compilation

As indicated previously, the number of expansion channels supported by a host Psion machine is dependent on the hardware. In the case of the S3a, only one SIBO channel can legitimately be opened corresponding to expansion port A. With the HC and the Workabout, it is possible to open up to three separate SIBO channels on ports A through to C. SYS$AS5.PDD is constructed to enable it to run on any host Psion platform. In its internal data space, the various hardware options for the SIBO channels, interrupt masks and interrupt numbers are coded in a large if statement thereby

Revision 1.00 Page 78 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

permitting conditional compilation of the driver for the required host hardware. The only change that need be made in adapting it for use on another Psion machine is the alteration of the build flag at the start of the code segment. This flag indicates to the compiler which SIBO machine flags as well as other variables should be set. The conditional compilation table outlined here is worthy of some study because it encapsulates all the information regarding masks and SIBO hardware channels required by the prospective developer interested in constructing a multi-platform peripheral and accompanying PDD.

The PDD Functions

OsAS5install IN: Nothing OUT: If successful, return with carry clear If installation unsuccessful, return with the carry flag set and error number in the AL register

PRESERVE: SS, SP, BP

The install vector is called by the parent LDD whenever the PDD is required to be loaded. It cannot be called directly be an application only indirectly through the LDD in its Install vector. The install vector is called in the context of the OS with DS and ES in an unknown state. Memory will not be moved while in this function so the normal rules governing the use of ES and DS may be ignored.

OsAS5Remove

IN: Nothing OUT: If successful, return with carry clear

If installation unsuccessful, return with the carry flag set and error number in the AL register

PRESERVE: SS, SP, BP

The remove vector is called by the parent LDD whenever the PDD is required to be unloaded. It cannot be called directly by an application and only indirectly through the LDD in its Remove vector. The remove vector is called in the context of the OS with DS and ES in an unknown state. Memory will not be moved while in this function so the normal rules governing the use of ES and DS may be ignored.

OsAS5Open IN: SS:SI points to the OpenEnt structure ES, DS point to the DS of the application process. OUT: If successful, return with carry clear and control block in BX If installation unsuccessful, return with the carry flag set and error number in the AL register

PRESERVE: SS, SP, BP

The open vector is called by the parent LDD whenever a channel to the PDD is required to be opened. It cannot be called directly by an application and is typically invoked in the higher level LDD Open vector code by means of the DevOpenPpp OS system call. On invoking the open vector, SI points to the OpenEnt structure which contains three fields, namely OpenNamePtr, OpenMode and OpenChan. The OpenNamePtr points to the qualifier immediately following the device name in the call to p_open. In the case of SYS$ASS5, for instance, the OpenNamePtr would point to the 'a' in the name "TTY.SR5:A". This corresponds to an attempt to open the first hardware SIBO channel on the host machine which if successful will leave the address of the ChanO Sr5ChannelStruct in BX. The PDD open vector finally includes a call to the OS service HwGet Channel to obtain the requested SIBO channel.

Revision 1.00 Page 79 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

The order of action undertaken by the parent serial LDD's open vector is generally fairly complicated and includes various calls to the PDD strategy vector routines. The situation is outlined overleaf:

e Ensure that the LDD itself can be opened.

e Call the PDD open vector using the OS DevOpenPDD OS call.

e = If successful, call the OS service DevGet PDDAddress which returns the full segment:offset address of the PDD's fourth strategy vector in BX:AX. These values are loaded into the dword Channel struct field SerialPDDEntry.

e Invoke the PDD strategy Open and SetHandlerCS functions to set up offsets and segments respectively to locations in the LDD above.

e Invoke strategy Set to initialise the transmission baud rate.

e Invoke strategy Start to set-up and then enable interrupts

Once the DevGetPDDAddress service has been used to load the LDD's SerialPDDEntry field, it may be used to load in the address of any of the PDD's strategy functions. The DevGetPDDAddress OS call invoked in the LDD open vector must also be invoked in the LDD resume vector code since memory may have been moved while the LDD was held. The PDD is ignorant of such activity since the serial LDD is responsible for handling all holds and resumes.

OsAS5Strategy IN: AX holds the vector number ES, DS point to the DS of the application process. OUT: If successful, return with carry clear and control block in BX If installation unsuccessful, return with the carry flag set and error number in the AL register

PRESERVE: SS, SP, BP

The strategy functions are invoked directly from the various serial LDD vectors to provide hardware- specific services. For instance, in order to set up the baud rate, it is necessary to invoke strategy Set. The strategy vector table for OsAS5Strategy is presented below and then the functionality of the important component vectors is outlined:

AS5StrategyJumpTable label word

dw offset AS5Open ;Load Handler offsets

dw offset AS5Close ;Close the channel

dw offset AS5Start ;Start the channel

dw offset AS5Stop ;Stop the channel

dw offset AS5Set ;Set the channel status

dw offset AS5Sense ,;Return channel status dw offset AS5Control ;Drive the handshaking lines dw offset ASS5Enquire ;Returns baud rate

dw offset AS5Enable ;Begin sending output dw offset ASS5SetHandlercCs ;Load Handler segments

Open and SetHandlerCS go together and are invoked from the LDD open and resume vector code. Both are required to let the PDD know the address at which its LDD resides. The four full addresses passed through to Open and SetHandlerCS are of the LDD's control block and the LDD StatusInt, RecvInt and XmitInt vectors. Close is called in order to close an opened channel. Start and Stop are used to enable/disable interrupts and are invoked from the LDD open, hold/resume and set vectors. The order of action in the PDD Start vector is as follows: e Initialise PDD variables e Check H/W present e Start the hardware running. In the case of SYS$ASS5, part of this process involves starting a continuous clock from the host controller ASIC in order to trigger the UART clock on the 3- link's ASICS. In addition to this clock, the RTS and DTR lines must be driven low. e = Start interrupts. The common interrupt service routine code resides in the PDD ComInt function. This code is patched into the interrupt vector via the GenSetRevector system service. The interrupt mask contains bits to

Revision 1.00 Page 80 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

generate the following interrupts: Receive character, Ready to send next character and Modem line change character. In SYS$ASS, all three interrupts are enabled in Start. It is important to realise that after masking in these bits, a Ready to send next character interrupt is almost immediately generated so the corresponding ComInt code must be able to handle this.

CheckHardwarePresent

This non-mandatory function is called from the Open vector and follows the lines of previously discussed CheckHardwarePresent code. After checking for an ASICS at the end of the serial link, the function returns with the carry flag clear if one is found. If a non-zero info byte is returned with an Asic5Normalld, then various other IDs are tried (Asic4Id, Asic8Id, Asic5PackId) before returning with the carry flag set.

CheckHardwarePresentFromStart

This is a non-mandatory function called only from the PDD Start vector. After checking that we have an ASICS at the end of the SIBO channel, the function sets the S_PERIPHERALMODE bit of the A5PortBMode register. This then puts ASICS into UART mode.

Comint

The common interrupt routine code is entered with DI holding the address of the appropriate channel struct. ASICS's control register (A5CtrlReg) is read first to determine which interrupt has occurred. The byte read from the register is compared against S_ MDINT (Modem lines interrupt), S_RXINT (Receive character interrupt) and S_TXINT (Transmit interrupt). The code to handle each of these cases is then entered prior to returning control back to the LDD via the Channel struct fields that were filled by a previous LDD calls to the PDD strategy Open and SetHandlersCS vectors. The LDD has no knowledge of interrupts and the purpose of ComInt is therefore to hide the hardware details of handling interrupts from the LDD. Once the interrupt has been serviced, a write is made to A9BNonSpecificEoiW in the case of ASIC9 or AlNonSpecificEoi for an ASIC1/ASIC2 based system to indicate to the OS that the interrupt has been serviced.

Revision 1.00 Page 81 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

13. DEBUGGING AND TESTING DEVICE DRIVERS

Introduction

This chapter will detail the techniques that can be used by the developer to first debug and then test device drivers. The emphasis will be on the software methods such as: e¢ Good use of variables. e.g. Starting all the fields in the CS Channel Status structure with CS. e Debugging by eye. Even more important with regard to device drivers. e Using SDBG. The pitfalls and benefits. Working your way around the strategy vector calls with SDBG. e Construction of C test harness programs. Catching all the error flags that can be returned by device driver functions. e The comprehensive memory check program mem.c.

Debugging Techniques

A Psion device driver is written in 8086 assembler as an asm file and built using the Borland Turbo Assembler compiler. The subsequent debugging process centres around the construction of an appropriate PLIB test harness. The purpose of a test harness is to check a number of the device driver vectors to ensure that they do not return errors or cause panics. The majority of PLIB calls that would be used in this context return a negative integer that is used to ascertain the cause of the problem in the corresponding device driver vector. The code below, for instance, would be used to test the install, open, strategy close and remove vectors of the A4EXIF LDD:

GLDEF_C VOID main(VOID) {

VOID *serH;

INT ret;

if ((ret=p_loadldd("A4EXIF.LDD") ) <0) { p_printf ("Error %d on p_loadldd", ret); p_getch () p_exit (0) }

else p_printf ("Successfully loaded A4EXIF.LDD");

if ((ret=p_open(&serH, "LED:",-1) ) <0) { p_printf ("Error %d on p_open", ret); p_getch();

x

else

p_printf ("Successfully opened LED: channel"); p_close(serH) ; p_printf ("Successfully closed LED: channel"); }

p_devdel ("LED",E_LDD) ;

p_getch();

p_exit (0);

}

Revision 1.00 Page 82 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

If as often happens at this stage, a bug in the device driver causes the test harness program to crash, it is necessary to debug the driver code either by eye or using SDBG. Debugging by eye should always be the first resort, however, whenever the bug can be readily pinned down to a particular vector. Things to look out for include:

e ~=An unbalanced stack: Check that the number of 'pushes' equals the number of 'pops' in the appropriate vector code.

e Addressing the wrong location: Ensure that all the Channel status fields (stored in CS) are offset using the correct register and that that register holds the right value. The following code for instance requires DI to hold the address of the channel status struct prior to

invocation: mov al, cs: [di].ChannelOpenFlag

e Consistency: With regard to the last point, it is important to be consistent if possible and try and use the same register (i.e. DI) to hold the channel status structure. A different one (usually BX) should also be used to hold the address of the open channel control block.

e Trashing BX and DI: If these registers are used in the vector code for anything other than addressing, check that their value is not being trashed by the operation.

Debugging using SDBG is an extension of debugging by eye. The SIBO debugger allows the programmer to trace through the driver's source code instruction by instruction and observe the contents of the CPU registers in the process. In this way it is possible to discover any discrepancies in terms of the values stored in the various registers. Furthermore, tracing with SDBG will enable the user to pinpoint the source of panics. The first objective of the device driver debugging process should be to get the code outlined on the previous page to work OK.

Further Testing Strategies

Once installing, opening, closing and unloading are dealt with, a test harness can be expanded to include p_iow or p_ioc calls which map onto the LDD's strategy vector. At this stage, SDBG is particularly useful for testing purposes as breakpoints can be set and jumped to. In this way for any p_ioc(serH, <func>, &serStat, &Al,&A2) call, the contents of the status word, serStat, and the A1 and a2 parameters can be tracked through the LDD's strategy vector. The value held by the status word at the end of a particular strategy call is the value returned by the corresponding PLIB p_iow/p_ioc call. Thus negative errors within the strategy code can be picked up by the test harness. A good test harness should be able to catch all the possible errors and at the least invoke p_printf to let the user know when one of them is returned. The file p_file.h contains a list of all the current return error values and the corresponding PLIB level error name. The entry for PendingErr, for instance is as follows:

#define PendingErr (-46) #define E_FILE_PENDING PendingErr

In order to induce the return of these error values it is necessary to extend the basic test harness outline to allow the user to undertake various pathological actions. For instance, the harness may include code that tries to open a channel twice which should result in InUseErr being invoked. By such means it is possible to ensure that a driver is not only operating as it should in normal circumstances but returning the correct error value when relevant.

Memory Testing

The final process that should be undertaken to fully test a device driver consists of the construction of an appropriate memory test harness. Three functions are presented on the next two pages which provide the core of such a comprehensive memory test program. The first function, CheckMemory, uses the PLIB routines p_allspce and p_sgfree to print out the current free bytes on the heap and the number of free segments in the host RAM. This function can be invoked after installing, opening, closing or removing a device driver to ensure that memory is not going to ‘alloc heaven’. The GobbleMemory function is first used to determine the amount of free memory available in segments

Revision 1.00 Page 83 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

through calling p_sgfree. The PLIB p_sgcreate function is then invoked to create a new segment, "Test", that consists of all of this free memory. Finally, the p_sgcopyto PLIB function is called to fill "Test" with Ox55's. By using up all free memory in this way, it is possible to use segment "Test" to determine whether a particular driver vector is writing to the wrong location. TestGobble, presented overleaf, is the third function outlined. It uses the PLIB function p_sgcopyfr to check the values of the bytes in the segment "Test". If any of the 0x55's have been overwritten then we know that we have a problem. These three functions should be incorporated within the standard test harness functions already presented in this chapter. In this way, it is possible to generate a powerful generic test program that can be used as the basis for all device driver testing.

LOCAL_C VOID CheckMemory (VOID) {

VOID *Heap;

INT fbytes;

fbytes=p_allspc (&Heap) ;

p_printf ("Free Heap Memory =>%x bytes", fbytes) ; p_printf ("Free Segments =>%d",p_sgfree()); p_getch();

}

[KR KR KK KR KK KI KK IK I I I I /

LOCAL_C VOID GobbleMemory (VOID) { UINT nParas, segSize; INT 3;

LONG pos,i;

UBYTE buf [256];

p_printf(" System RAM size = %d",p_getram()); p_printf ("Internal RAM usage = %d",p_sgramdisk())j; nParas=p_sgfree()j; p_printf ("Amount of free RAM = %d",nParas); segH=p_sgcreate("Test",nParas, E_SEGMENT_HIGH) ; if (segH)

p_printf ("Created segment \"test\"");

else { p_printf ("Error in creating segment"); p_getch(); p_exit (0); } segSize=p_sgsize(segH) ; p_printf("Size of segment is %d",segSize); p_printf("In 16-byte paragraphs"); p_sleep(5L); for (j=0; j<16; j++) buf [j]=0x55;

i=0; while (i<segSize) { pos=i*16; if (p_sgcopyto(segH, pos, &buf [0],16) <0) { p_printf ("Failed on p_sgcopy"); p_printf ("%d",i); p_getch(); } i++; } p_printf("Test segment full of 0x55s"); p_getch(); }

[RRR KK KK KK KKK IK I I I I /

Revision 1.00 Page 84 of 115 pages

The Psion SIBO Hardware Development Kit

LOCAL_C VOID TestGobble (VOID)

UINT segCount; buf [16];

segCount=0; p_printf ("Checking segment integrity ..."); for (segCount=0; segCount<p_sgsize(segH); segCount+t+) { if (p_sgcopyfr(segH, segCount*16, &buf [0] ,16) <0) p_printf ("Error in segment");

else { for (i=0;i<16;i++) if (buf[i] !=0x55) { p_printf ("OVERWRITE ERROR!"); p_printf ("Segment count=%d",segCount) ; p_printf ("Byte count=%d",i); } } } p_printf ("Test segment OK"); p_printf ("Heap integrity checks OK"); p_allchk (44); p_printf("If get here, heap OK"); p_getch();

}

[KR KR KK KR KK KKK I I I I I /

Revision 1.00

Psion PLC (c) May 1995

Page 85 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

APPENDIX: SOURCE CODE FILES

A4EXIF.ASM

title A4EXIF -- Example ASIC4 Interface device driver subttl Copyright (c) Psion PLC (1994) name A4EXIF ; ; VER DATE BY DESCRIPTION jo -o-------------------------------------- 7 1.00F 26/1/95 Mal Working Version BUILDSB=1 7S3a build environment (channels=1) S3c=0 ;Need to specify no s3c ; BUILDSC=1 7S3c build environment (channels=3) ; BUILDCH=1 ;HC build environment (channels=3) ; BUILDHH=1 753 build environment (channels=1) include ..\inc\epoc.inc include ..\inc\epoclib.inc include ..\inc\epocsibo.inc

include ossibo.inc include ospack.inc

Example Logical Device Driver for prototype LED-ASIC4 Interface circuit for Corporate/S3C/Consumer serial port. Written by Mal Dec 1994/Jan 1995.

Me oNe Ne

A4EXIF CONSTANTS AND TYPES

The following constants and type definitions are compiler directives used by the TCEP assembler when it is creating the LDD.

Ne Ne Ne Ne Ne

if Consumer

numberofchannels equ 1 else if Corporate or S3c numberofchannels equ 3 else numberofchannels equ 2 endif endif

7;Channel StatusEnt block accessed through CS:DI A4ExifStatusEnt struc

A4ExifCSProcessId dw <i ;Channel parent process id A4ExifCSChannelOpen db 2 ;Channel open flag A4ExifCSChannelRunning db ? ;Channel hardware running flag A4ExifCSChanReadCompleted db 2 ;Channel request completed flag A4ExifCSChannelIntMask db 2 ;Channel interrupt mask A4ExifCSChanneliIntNum db ? ;Channel interrupt number A4ExifCSChannelSelect db 2 ;SIBO Channel select A4ExifCSChanneliIntVec dw ? ;Channel int vector number A4ExifCSTickHandle dw ee ;TCK channel handle A4ExifCSA1Value db i ;Channel strategy Al parameter A4ExifCSA2Value db ? ;Channel strategy A2 parameter

A4ExifStatusEnt ends

;Open Channel Control block accessed through DS:BX A4ExifEnt struc

A4ExifDSIo ChanEnt <> 7;Open channel control block Ent A4ExifDSHandlerPtr dw 2 ;Cant touch when under A4ExifDSStatusPtr dw ? ;Hold, Resume, Reset or A4ExifDSA1Ptr dw ? ;interrupt routine A4ExifDSA2Ptr dw es A4ExifDSStatusEntPtr dw ?

A4ExifEnt ends A4PERIPH MASK equ Of0h 711110000b

Revision 1.00 Page 86 of 115 pages

The Psion SIBO Hardware Development Kit

EXTENDED_INFO_BYTE equ 090h U5_ENABLE_ON equ 080h U5_ENABLE_OFF equ 000h ;Latch addresses for reading/writing USOUTPUT_LATCH equ 00000000b U3INPUT_BUFFER equ 00000000b U4STATUS_BUFFER equ 00000001b cs: [di] .A4ExifCsAlValuefor INTERRUPT_LATCH equ 00000001b ;Status byte masks S2S3_ON equ 00000011b S2S3_OFF equ 00000000b S2_ONLY equ 00000001b S3_ONLY equ 00000010b INTERRUPT_STATUS_MASK equ 00000011b 7; LED bytes SOME_LEDS_ON equ 01010101b SOME_LEDS_OFF equ 10101010b TOP_LEDS_ON equ 11110000b BOTTOM_LEDS_ON equ 00001111b ZERO_BYTE equ 00h dgroup group stack assume ds:dgroup,es:dgroup,ss:dgroup CodeSeg 7 A4EXIF ENTRY TABLE ; Seseseo eee ee sececs ProcBegin@ A4ExifLDD ; ssieceees dw LDDSignature db 'LED',0,0,0,0,0 dw (VectorEnd-Vector) /2 Vector: dw A4ExifInstall dw A4ExifRemove dw A4ExifHold dw A4ExifResume dw A4ExifReset dw A4ExifUnits dw A4ExifOpen dw A4ExifStrategy VectorHandler: dw A4ExifHandler if Asic9 InterruptVectors: dw A4ExifTickInt endif VectorEnd: H A4EXIF INTERNAL DATA SPACE , ; Device Driver global variables follow. ; These variables reside in the code segment ; and as such can always be accessed with 7 the 'cs:' prefix.

if Asic9 if Consumer

Channel0O A4ExifStatusEnt<0,0,0,0,mask

Psion PLC (c) May 1995

710010000b 7;Sets LBO for latch U5 ;Deselects LBO for U5

;Selects ;Selects ;Selects

;Selects

A9MSlave, HwIrq2Revector, SelectChannel5, IntVec0O,0,0>

else if Corporate or S3c

Channel0 A4ExifStatusEnt<0,0,0,0,mask

AOMExpIntA, HwIrq4Revector, SelectChannel3, IntVec0O,0,0>

Channell A4ExifStatusEnt<0,0,0,0,mask

AQMExpIntB, HwIrq5Revector, SelectChannel4, IntVec1,0,0>

Channel2 A4ExifStatusEnt<0,0,0,0,mask

A9MSlave, HwIrq2Revector, SelectChannel5, IntVec2,0,0>

Revision 1.00

AO for writing AO for reading

; reading Al for writing

Page 87 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

else Channel0 A4ExifStatusEnt<0,0,0,0,mask

AOMExpIntA, HwIrq4Revector, SelectChannel3, IntVec0O,0,0> Channell A4ExifStatusEnt<0,0,0,0,mask

AQ9MExpIntB, HwIrq5Revector, SelectChannel4, IntVec1,0,0> endif endif else if Consumer Channel0O A4ExifStatusEnt<0,0,0,0,mask

Asic2Int, HwIrq4Revector, SelectChannel7, IntVec0,0,0>

else if Corporate ChannelO A4ExifStatusEnt<0,0,0,0,mask ExpIntLeftA, HwIrq3Revector, ExpChannelLeftA, IntVec0O,0,0> Channell A4ExifStatusEnt<0,0,0,0,mask ExpIntRightB, HwIrq2Revector, ExpChannelRightB, IntVecl1,0,0> Channel2 A4ExifStatusEnt<0,0,0,0,mask Asic2Int, HwIrq4Revector, SelectChannel7, IntVec2,0,0> else ChannelO A4ExifStatusEnt<0,0,0,0,mask ExpIntLeftA, HwIrq3Revector, ExpChannelLeftA, IntVec0O,0,0> Channell A4ExifStatusEnt<0,0,0,0,mask ExpIntRightB, HwIrq2Revector, ExpChannelRightB, IntVecl1,0,0> endif endif endif HoldFlag db 0 ;Hold/Resume flag SwitchStatus db ? ;Holds the masked status byte from U4 after interrupt ProcEnd noret ProcBegin@ A4ExifInstall, far ; eee ; Installs the device driver. 7 Invoked after a PLIB 'p_loadldd("A4EXIF.LDD")' call to load the LDD ; All of the fields inside the CS control blocks are preloaded ; with the correct values at install time. Install therefore does ; not do any work. 7 IN: ; Nothing 7 OUT: ; Carry Clear - driver successfully installed 7 cle ;The ChannelOpen fields are set to zero ret ;in the relevant ChannelStatusEnt headers ProcEnd noret ProcBegin@ A4ExifRemove, far ; eSeseces eee ; Removes the device driver. ; Invoked after a PLIB 'p_devdel("LED",E_LDD) 'call to unload the H device driver. ; A device driver cannot be removed if any of its channels i are still open. H IN: ; Nothing H OUT: ; Carry clear - successfully removed 7 Carry set - remove failed, error number in AL 7 mov cx, numberofchannels ;Check that each mov di, offset Channel0O ;channel is closed xor ax, ax CheckAl1lChannelsClosedLoop: cmp cs: [di] .A4ExifCSChannelOpen, al ;Closed channels will jne WeHaveAChannelOpenSoFail ;have the value 0 in add di, (size A4ExifStatusEnt) ;their ChannelOpen

Revision 1.00 Page 88 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

loop CheckAl1ChannelsClosedLoop ;flags jmp FinishedOkay WeHaveAChannelOpenSoFail: mov al, InUseErr ;Fail if not all stc ;closed ret FinishedOkay: cle ret ProcEnd noret

ProcBegin@ A4ExifHold, far

v

; Called by the operating system whenever the device driver is

; being moved or the machine is powering down.

; This will also be called by our pack door polling function when

; it sees that the doors have been opened and our peripheral has

; lost power.

; IN:

7 Reason for the hold in AH

7 OUT:

7 Nothing

13 mov cx, 1 ;Hold can be called xchg cl, HoldFlag ;when the driver is cmp cl, 0 ;under a hold so jne AlreadyHeld ;re-entrancy blocking

A4HoldFromTick: ;is required mov cx, numberofchannels mov di, offset Channel0 ; Loop because Hold

HoldAllTheChannelsLoop:

;must stop all the

cmp cs: [di] .-A4ExifCSChannelOpen, ; channels je DontHoldBecauseNotOpen ;Is the channel open? push cx ;If it is then stop call StopTheChannelRunning yall interrupts pop cx DontHoldBecauseNotOpen: add di, (size A4ExifStatusEnt) loop HoldAl1lTheChannelsLoop AlreadyHeld: ret

ProcEnd noret

ProcBegin@ A4ExifResume, far

3 Called by the operating system when it has finished moving the - device driver in memory or when the machine is switching back on. ; Also called by our door polling routine when it sees that the doors ; have been closed and we can resume communication with our peripheral. ; IN: iH Nothing ; OUT: 7 Nothing is xor CX, cx ;Block in case of re-entrancy xchg cl, HoldFlag cmp cl, 0 je AlreadyResumed if Asic9 GenDataSegment ;Check to see if the pack HwGetSsdData ;doors are still closed mov bx, ax cmp es: [bx] .SsdDoorStatus, DoorOpen je DoorsAreOpen endif A4ResumeFromTick: mov cx, numberofchannels ; Loop because resume must mov di, offset Channel0 ;restart each open channel ResumeAllTheChannelsLoop: cmp cs: [di] .A4ExifCSChannelOpen, 0 ;Is the channel open? je DontResumeBecauseNotOpen push Cx call StartTheChannelRunning pop cx DontResumeBecauseNotOpen: add di, (size A4ExifStatusEnt) loop ResumeAl1lTheChannelsLoop AlreadyResumed:

Revision 1.00 Page 89 of 115 pages

The Psion SIBO Hardware Development Kit

Psion PLC (c) May 1995

ret

DoorsAreOpen:

mov HoldFlag, 2 ret ProcEnd noret

ProcBegin@ A4ExifReset, far

Called when an application which opened a channel terminates without closing the device driver. A device driver, for each open channel, has to request that the operating system calls this function when the application terminates abnormally (ie without closing an open channel). Reset can supply one piece of identifying data which will be passed in CX. This would usually be the channel's number or CS control block pointer. Reset just needs to clear interrupts, hardware reservations, and free the channel. Any allocated space will be cleaned up for you by the OS. IN:

The device driver's handle in BX

The address of the status struc identifying the channel in CX

7 OUT: ; Nothing , mov di, cx cmp cs: [di] .A4ExifCSChannelOpen, 0 je NotOpenToReset call StopTheChannelRunning 7Stop interrupts mov al, cs: [di] .A4ExifCSChannelIntMask ;Free the reserved HwF reeChannel ;hardware mov cs: [di] .A4ExifCSChannelOpen, 0 ;The channel is now NotOpenToReset: ;free ret

ProcEnd noret

ProcBegin@ A4ExifUnits, far

Called to find how many open channels the driver will support

- In: ; Nothing - Out: H The total number of channels supported in AX , mov ax, numberofchannels ret

~

ProcEnd noret

ProcBegin@ A4ExifOpen, far

Opens a device driver channel. Invoked after the PLIB call 'p_open(é&appHandle, "LED:*",-1)'to open a channel to the device driver.

,

,

7

H Tn:

; OS device handle of the device driver in DX

; Pointer to the OpenEnt struc in SI

; Pointer to the IntEnt struc in BP

; DS,ES,SS point to the applications data space

i Out:

; Carry clear - BX holds the address of the open channel

7 Carry set - AL holds the error number

is cld ;Interrupts off to pushf ;prevent multiple apps oli ;calling open mov si, [si] .OpenNamePtr ; Simultaneously mov al, [sitl] CharToFoldedChar ;Read the unit no. cmp al, 'A' ;part of device name jb OpenNameErr ;to find which channel sub al, 'A' ;to open. eg "LED:A" cmp al, numberofchannels jae OpenNameErr xor ah, ah push ax ;Map the channel no. mov dx, (size A4ExifStatusEnt) ;to a channel control mul dx ;block in our CS pop ax 7; space

Revision 1.00

Page 90 of 115 pages

The Psion SIBO Hardware Development Kit

mov di, ax add di, offset Channel0O cmp cs: [di] .A4ExifCSChannelOpen, 0 je GetATickChannel popft mov ax, AlreadyOpenErr jmp ChannelAlreadyOpen GetATickChannel: mov cs: [di] .A4ExifCSChannelOpen, 1 mov cs: [di] .-A4ExifCSChannelRunning, 0 popft ife Asic9 jmp GetHardwareChannel else push ax mov ax, ((':' shl 8)+'K') push ax mov ax, (('C' shl 8)+'T') push ax mov bx, sp ToOpen jne GotATickChannel add sp, 6 mov ax, LockedErr jmp OpenFailed GotATickChannel: add sp, 6 mov cs: [di] .A4ExifCSTickHandle, ax push ax mov bx, ax mov ax, IoFuncStart mov ex, 1 push cx push cx push ax mov cx, (InterruptVectors-Vector) /2 push cx mov cx, sp ToWithWait add sp, 8 pop dx jmp GetHardwareChannel endif OpenNameErr: popft mov ax, NameErr jmp ChannelAlreadyOpen GetHardwareChannel: mov al, cs: [di] .A4ExifCSChannelIntMask HwGetChannel jne CheckHardwareNowThatSIBOChannellIsOpen mov ax, InUseErr jmp FreeTckAndExit FreeTckAndChannelHardware: mov al, cs: [di] .A4ExifCSChannelIntMask HwF reeChannel mov ax, DeviceErr FreeTckAndExit: if Asic9 push ax mov bx, cs: [di] .A4ExifCSTickHandle IoClose pop ax endif OpenFailed: mov cs: [di] .A4ExifCSChannelOpen, 0 ChannelAlreadyOpen: stc OpenExit: ret CheckHardwareNowThatSIBOChannellIsOpen: Proclid mov cs: [di].A4ExifCSProcessId, ax mov cs: [di] .A4ExifCSChanReadCompleted, 0 call CheckHardwarePresent jc FreeTckAndChannelHardware mov cx, (size A4ExifEnt) HeapAllocateCell jc FreeTckAndChannelHardware mov bx, ax

Revision 1.00

Psion PLC (c) May 1995

;Offset in DI

;Check to see if ;channel is already ;open

,Obtain a TCK channel so ;we can poll the door state

7;If HC, we don't need ;to set up the TCK ; routine

;Try to open "TCK:" ;channel with "TCK:" ; string on stack

;TCK will call our ,door-polling function 732 times a second

7Start our ,door-polling function ;running by starting ;the "TCK:" channel

7Frequency 1 tick ;Data irrelevant ;Handle to driver ;TCK function to call

7;Check the hardware ;is available then ;reserve it ;Returns with carry ;clear if OK

7Set up the calling ;process ID

;Returns with carry ;clear if successful ;Allocate a control ;block in our app's ;data space

Page 91 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

push bx ;IloAddHandler trashes BX mov al, (VectorHandler-Vector) /2 ;Set up our wait handler ToAddHandler ;Leaves the address of pop bx ;handler in AX jne GotHandler push ax ;If no handler, open fails HeapFreeCell pop ax jmp FreeTckAndChannelHardware GotHandler: mov [bx] .A4ExifDSStatusEntPtr, di mov [bx] .A4ExifDSHandlerPtr, ax mov [bx] .A4ExifDSStatusPtr, 0 mov [bx] .A4ExifDSIo.ChanNext, bx mov [bx] .A4ExifDSIo.ChanSignature, IoChanSignature mov [bx] .A4ExifDSIo.ChanLibHandle, dx mov cx, al ; loRequestReset takes xchg bx, dx ;the device handle in IoRequestReset 7BX and the channel xchg bx, dx ;handle in CX xor ax, ax call StartTheChannelRunning ReturnCLc: cle ret ProcEnd if Asic9

ProcBegin@ A4ExifTickInt, far

This function is called by the tick handler on every tick of

; the system clock. This happens 32 times a second.

; The operating system will call a device driver to hold when memory is ; being moved and when the machine is being powered down. It will not

; call the device driver when the pack doors are opened.

Opening the pack doors will cause power to the peripheral to be cut,

; ; and therefore the driver needs to be held in the way it would be if ; the machine powered down. Only for Asic9 based machines. ; This function checks the state of the doors on every tick and calls iH Hold and resume when it sees the status of the doors change. H IN: ; The state of the door in SI ; OUT: ; Nothing ; cmp si, DoorOpen 7Is the door open je TheDoorIsOpen 7or closed? cmp HoldFlag, 2 7Closed Door, HoldFlag=2 je NeedToDoTheResume ;means we do a resume ret 7Closed Door, HoldFlag!=2 NeedToDoTheHold: mov HoldFlag, 2 jmp A4HoldFromTick NeedToDoTheResume: mov HoldFlag, 0 jmp A4ResumeFromTick TheDoorIsOpen: xor ax, ax cmp HoldFlag, al je NeedToDoTheHold ret ProcEnd noret endif ProcBegin@ A4ExifHandler, far ; ; When an application is waiting within an iowait and a signal is ; generated then before passing that signal to the application the : OS first runs any wait handlers belonging to the device driver ; channels that the application has open. ; The interrupt routine can generate a signal but cannot fill in any ; status words or pass values back to the application because the ; applications DS space is not available. The handler can consume a ; signal generated by an interrupt and then fill any status words 7 before re-signalling the application. A handler always has access ; to the application's DS space. The wait handler can consume the 7 signal which is then no longer passed back to the application. Hi IN:

Revision 1.00 Page 92 of 115 pages

The Psion SIBO Hardware Development Kit

Ne Ne Ne Ne

Psion PLC (c) May 1995

Pointer to our control block in applications DS space in BX DS,ES,SS point at application's data space

OUT: Carry clear - do not consume the signal, signal not for us 7 Carry set - consume the signal, re-enable handler if AL ; non-zero else don't re-enable handler if AL=0. 7 cld pushf cli mov di, [bx].A4ExifDSStatusEntPtr ;Is the signal for us? cmp cs: [di] .A4ExifCSChanReadCompleted, 1 jne ExitHandlerSignalNotForuUs ;If it is, copy mov cs: [di] .A4ExifCSChanReadCompleted, 0 ;the values read in mov al, cs: [di] .A4ExifCSA1Value ;the interrupt mov ah, cs: [di] .A4ExifCSA2Value ;routine back to mov di, [bx].A4ExifDSA1Ptr ;the application mov [di], al ;Asynchronous read mov di, [bx].A4ExifDSA2Ptr ;has been completed mov [di], ah xor di, di xchg [bx] .A4ExifDSStatusPtr, di ;Clear the status mov word ptr [di], 0 ;word popft ToSignal xor ax, ax stc ;STC and AL!=0 => ret ;consume signal and ExitHandlerSignalNotForus: ;don't re-enable popft ;handler elec ret ProcEnd StrategyVectorTable label word dw offset A4ExifDefault ;StrategyPanic dw offset A4ExifRead 7 StrategyRead ie P_FREAD dw offset A4ExifWrite ;StrategyWrite ie P_FWRITE dw offset A4ExifClose ;StrategyClose ie P_FCLOSE dw offset A4ExifCancel 7 StrategyCancel ie P_FCANCEL dw offset A4ExifDefault ;StrategyAttach dw offset A4ExifDefault ;StrategyDetach dw offset A4ExifSet ;StrategySet ie P_FSET dw offset A4ExifSense ;StrategySense ie P_FSENSE ProcBegin@ A4ExifStrategy, far Called by the operating system when an I/O request is made on

the device driver.

Calls to this funcion from an owning application will usually take the form p_ioc(pcb, func, &Stat, &Al, &A2) ;

The strategy function is called with a function number specifying the action which the driver is to take, a status word to fill when the action is complete, and two arguments Al and A2.

Nee Ne Ne

Se ee

All strategy functions must complete with a signal to the application. Functions can be asynchronous and need not complete immediately. IN: Pointer to our control block in the applications DS in BX 7 Device driver handle in DX ; Pointer to the RqEnt struct in SI ; Pointer to a IntEnt struct in BP ; DS,ES,SS point at the applications data space i OUT: ; Returned value in AX ; Must call IoSignal somewhere to signal completion ; of the I/O request. v mov ax, [si].RqFunction ;Get the function number mov dx, [si].RqAlPtr ;DX holds the first argument mov di, [si].RqStatusPtr ;for convenience mov word ptr [di], PendingErr 7Status word holds shl ax, 1 ; E_FILE_PENDING mov di, ax push StrategyVectorTable[di] ;Jump to required function mov di, [bx] .A4ExifDSStatusEntPtr ;with our CS control block retn ;pointer in DI A4ExifDefault: ToRoot

Revision 1.00

Page 93 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

ret ExitWithCompletionStatusZero:

xor ax, ax ;Common exit points ExitWithOtherCompletionStatus:

mov di, [si].RqStatusPtr

mov word ptr [di], ax

ToSignal ExitStillPending:

xOr ax, ax

cle

ret

ProcEnd noret

STRATEGY VECTOR TABLE FUNCTIONS

IN: DX holds the pointer to the first argument in 'p_iow(...)' call BX holds the address of the open channel control block CS:DI holds the address of status struc identifying the open channel

See eee Ty

ProcBegin@ A4ExifRead, far

H Strategy vector table function that handles asynchronous byte reads 7 from the LEDs and switches.

i; The corresponding PLIB call is p_ioc(pcb,P_FREAD, &Stat, &Argl, &Arg2) ; ; The request is completed when the interrupt routine signals the

; handler which in turn signals the application passing back the values ; read at the time of the interrupt through the AlPtr and A2Ptr.

H IN:

; Pointer to control block in applications data space in BX

i Pointer to control block in our CS space in DI

; Al (pointer to Argl) in DX

,

v

OUT: Jumps to common exit point . Panics if multiple requests , cmp [bx] .A4ExifDSStatusPtr, 0 ;Panic if we already jne PanicPending ;have an I/O read request pushf ;pending on the channel cli ;Disable interrupts mov cs: [di] .A4ExifCSChanReadCompleted, 2 mov ax, [si].RqA1Ptr mov [bx] .A4ExifDSA1Ptr, ax ; Store the locations to mov ax, [si].RqA2Ptr ;put the data when we get it mov [bx] .A4ExifDSA2Ptr, ax mov di, [si].RqStatusPtr mov [bx] .A4ExifDSStatusPtr, di ;DI holds the address mov word ptr [di], PendingErr 7of status word and we popf ;Signal that we are waiting mov bx, [bx] .A4ExifDSHandlerPtr ;for completion of read mov cl, ToEnableHandler ;Enable Wait Handler jmp short ExitStillPending 7No IoSignal because PanicPending: ;we are still waiting mov al, PaniclIoPending ProcPanic

ProcEnd noret

ProcBegin@ A4ExifWrite, far

This function sets the state of the LEDs.

It completes immediately after setting the state as it has nothing to wait for.

Write is the same as set.

Ne Ne Ne Ne Ne te

IN: ; Pointer to control block in applications data space in BX ; Pointer to control block in our CS space in DI . Al in DX - OUT: - Jumps to Set , jmp WriteAndSetAreTheSame

ProcEnd noret

ProcBegin@ A4ExifClose, far

Revision 1.00 Page 94 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Handles the request to close a channel. called by the PLIB call p_iow(pcb,P_FCLOSE) or p_close (pcb)

Ne Ne Ne Ne

IN: Pointer to control block in applications data space in BX ; Pointer to control block in our CS space in DI ; OUT: ; Jumps to common exit point , call StopTheChannelRunning 7Stop interrupts if Asic9 push bx ;Close down the mov bx, cs: [di] .A4ExifCSTickHandle 7;"TCK:" channel IoClose pop bx endif push bx mov ax, [bx] .A4ExifDSIo.ChanLibHandle ;Remove the wait push ax ;handler mov bx, [bx] .A4ExifDSHandlerPtr IoRemoveHandler cmp cs: [di] .A4ExifCSChanReadCompleted, 0 ;If the interrupt je NoSignalToConsumeFromInterrupt ;has signalled the ToWaitForSignal ;handler we need to NoSignalToConsumeFromInterrupt: ;consume its signal pop bx ;now the handler mov cx, di ;has been removed ToRequestResetCancel pop bx 7No longer need reset HeapFreeCell ;Free our control mov al, cs: [di] .-A4ExifCSChannelIntMask ;block in app's DS HwFreeChannel mov cs: [di] .A4ExifCSChannelOpen, 0 jmp ExitWithCompletionStatusZero 7To signal completion ProcEnd noret 7,of close request ProcBegin@ A4ExifCancel, far v ; Cancel any pending asynchronous read. ; Called by the PLIB function p_iow(pcb,P_FCANCEL) ; i In: ; Pointer to control block in applications data space in BX ; Pointer to control block in our CS space in DI ; Out: ; Jumps to common exit point 7 pushf cli cmp [bx] .A4ExifDSStatusPtr, 0 ;Check that there is je NothingToCancel ya request pending push bx mov bx, [bx] .A4ExifDSHandlerPtr sub cl ol ToEnableHandler ;Disable Wait Handler pop bx cmp cs: [di] .A4ExifCSChanReadCompleted, 1 jne NoSignalFromInterrupt ;TO consume any stray ToWaitForSignal ;Signal from the NoSignalFromInterrupt: ;interrupt routine mov cs: [di] .A4ExifCSChanReadCompleted, 0 xor fomcramre be ;To signal completion xchg di, [bx].A4ExifDSStatusPtr ;of the outstanding mov word ptr [di], CancelErr pasync read request ToSignal ;Signal to p_waitstat NothingToCancel: popft jmp ExitWithCompletionStatusZero 7To signal completion ProcEnd noret 7of the cancel request ProcBegin@ A4ExifSet, far , 7 Write a value to the LED latch. ; Can be called by the PLIB call p_iow(pcb,P_FSET, &Argl); where Al ; is an unsigned byte. ; Write is the same as set. 7 IN: ; Pointer to control block in applications data space in BX 7 Pointer to control block in our CS space in DI 7 Al (pointer to Argl) in DX

Revision 1.00 Page 95 of 115 pages

The Psion SIBO Hardware Development Kit

’

’

OUT: Jumps to common exit point

, WriteAndSetAreTheSame:

Steere Ty

Ne Ne Ne Ne

seo

pushf

cli

mov al, cs: [di] .-A4ExifCSChannelSelect HwSelectChannel

push ax

mov bx, dx

mov dl, U50UTPUT_LATCH

mov al, [bx]

call OutputByte

pop ax

HwSelectChannel

popft

jmp ExitWithCompletionStatusZero

ProcEnd noret

ProcBegin@ A4ExifSense, far

Reads the state of the LEDS and Switches.

Psion PLC (c) May 1995

7Select our SIBO ; serial channel 7Store old channel

;DX (now BX) points ;to the value to output to our ;peripheral

;Return old channel

;To signal completion

7of set request

Can be called from PLIB using p_iow(pcb, P_FSENSE, éArgl, &Arg2)

Where Argl and Arg2 are unsigned bytes. In:

Pointer to control block in applications data space in BX Pointer to control block in our CS space in DI

Al (pointer to Argl) in DX

Out: Jumps to common exit point pushf cli mov al, cs: [di] .-A4ExifCSChannelSelect HwSelectChannel push ax mov bx, dx mov dl, U4STATUS_BUFFER call InputByte mov [bx], al mov bx, [si] .RqA2Ptr mov dl, U3INPUT_BUFFER call InputByte mov [bx], al pop ax HwSelectChannel popft jmp ExitWithCompletionStatusZero

ProcEnd noret

LOCAL DEVICE DRIVER FUNCTIONS

7Select our SIBO ;serial channel 7 Store old channel

;DX (now BX) points ;to the variable in ;which to place the ;value read from U4. 7BX now points to

;the variable in

;which to place the ;value read from U3.

;Return old channel

;To signal completion

;of a sense request

Interrupts must be off prior to the call to this function.

IN:

DL has address to which Asic4 is to write

AL holds the value to output

mov al, (SerialWriteSingle or A4Address)

SBUSY SCONTOUT mov al, dl SBUSY SDATAOUT mov al, (SerialReadSingle or A4Data) SBUSY

SCONTOUT

SBUSY

SDATAIN

ret

ProcEnd noret

ProcBegin@ OutputByte

Interrupts must be off prior to the call to this function.

Revision 1.00

Page 96 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

H IN: ; DL has address to which Asic4 is to write ; AL has the value to output

mov al, (SerialWriteSingle or A4Address)

mov al, dl

mov al, (SerialWriteSingle or A4Data) SBUSY SCONTOUT SBUSY XNOP pop ax SDATAOUT ret ProcEnd noret

ProcBegin@ IntVecO, far

- Interrupt on serial channel0 3 Calls Comint with channel control block pointer in DI ,

mov di, offset Channel0O

jmp ComIint

ProcEnd noret

if Corporate or S3c ProcBegin@ IntVecl1, far

Sat

Interrupt on serial channell

; Calls Comint with channel control block pointer in DI ,

mov di, offset Channell

jmp ComInt

ProcEnd noret

ProcBegin@ IntVec2,far

Interrupt on serial channel2 Calls Comint with channel control block pointer in DI

Ne Ne Ne Ne

mov di, offset Channel2 7 FALL THROUGH ProcEnd noret endif ProcBegin@ ComInt, far , ; The common interrupt service routine code. ; When an interrupt occurs, the first task is to read the status 7 buffer of latch U4. The subsequent action is dependent on the ; postion of switches Sl and S2. For the purposes of this example, ; the four posibilities for the switch values correspond somewhat ; arbitrarily to four different byte values that are written to U5. ; in the 8086, interrupts cannot occur while in an interrupt routine. ; If an asynchronous read is pending then the handler is signalled. 7 IN: ; Channel's CS based control block pointer in DI , cmp cs: [di] .A4ExifCSChanReadCompleted, 2 ;Only if 2 do we have jne NotAsynchronousRead ;asynch read completed mov cs: [di] .A4ExifCSChanReadCompleted, 1 mov bx, cs: [di] .A4ExifCSProcessId ;Signals completion ToSignalByPidNoReSched 7Of read to OS so as NotAsynchronousRead: ;to invoke handler mov al, cs: [di] .-A4ExifCSChannelSelect HwSelectChannel push ax mov dl, U3INPUT_BUFFER call InputByte mov cs: [di] .A4ExifCSA2Value, al ;LED byte mov dl, U4STATUS_BUFFER

Revision 1.00 Page 97 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

call InputByte mov cs: [di] .A4ExifCSAlValue, al ; Status byte and al, INTERRUPT_STATUS_MASK xchg al, SwitchStatus cmp SwitchStatus, S2S3_ON 7;S2 and S3 on => turn je A11LEDsOn 7on alternate LEDs cmp SwitchStatus, S2S3_OFF 7S2 and S3 off => not je A11LEDsOff ;the alternate LEDs cmp SwitchStatus, S2_ONLY 782 on, S3 off => turn je TopLEDsOn 7on top four LEDs cmp SwitchStatus, S3_ONLY 753 on, S2 off => turn je BottomLEDsOn 7on bottom four LEDs ErroriInSwitchStatusByte: jmp ClearInterruptAndReschedule A11LEDsOn: mov al, SOME_LEDS_ON jmp Output LEDByte A11LEDsOff: mov al, SOME_LEDS_OFF jmp Output LEDByte TopLEDsOn: mov al, TOP_LEDS_ON jmp Output LEDByte BottomLEDsOn: mov al, BOTTOM_LEDS_ON OutputLEDByte: mov dl, US50UTPUT_LATCH call OutputByte ClearInterruptAndReschedule: mov dl, INTERRUPT_LATCH call OutputByte if Asic9 ;A write to this location out A9BNonSpecificEoiw, al ;informs the interrupt else ;controller that the out AlNonSpecificEoi, al ;installed interrupt endif ;service routine has pop ax ; finished HwSelectChannel onlkres ;Reschedule if necessary ret ProcEnd noret ProcBegin@ StartInterrupts po SSS SES ; Start interrupts assuming interrupts are ; off prior to call. ; The EPOC GenSetRevector service loads in ; a user-specified interrupt service routine ; located at the address given in cx:bx ; (segment cx, offset bx) for the interrupt ; vector number given in AL. Note that the 7 variable A4ExifCSChannelIntVec holds the ; name of the appropriate required interrupt ; vector routine for the channel. H IN: ; Our CS control block pointer in DI H OUT: i; Nothing is mov al, cs: [di] .-A4ExifCSChannelIntNum 7Get the OS to call mov cx, CS ;the function in push bx 7CS:BX every time mov bx, cs: [di] .A4ExifCSChannelIntVec ;that the interrupt GenSetRevector ;whose number is in pop bx 7;AL occurs ife Asic9 in al, AlInterruptMask or al, cs: [di] .A4ExifCSChannelIntMask ;Set the mask out AlInterruptMask, al ;location so as ; interrupt else ;to enable that in al, A9BInterruptMaskRW ; interrupt or al, cs: [di] .A4ExifCSChannelIntMask out A9BInterruptMaskRW, al endif ret

ProcEnd noret

Revision 1.00 Page 98 of 115 pages

The Psion SIBO Hardware Development Kit

ProcBegin@ StopInterrupts

; Stop interrupts assuming that interrupts are off

The EPOC GenResetRevector OS service

interrupt service routine with the original routine and interrupt mask for the vector given in AL. IN:

Our CS control block pointer in DI

Se ee Te

OUT: ; Nothing

ife Asic9

replaces the previously loaded user-specified

Psion PLC (c) May 1995

in al, AlInterruptMask ;Disable the mov ah, cs: [di] .A4ExifCSChannelIntMask ; interrupt not ah and al, ah out AlInterruptMask, al else in al, A9BInterruptMaskRW mov ah, cs: [di] .A4ExifCSChannelIntMask not ah and al, ah out A9BInterruptMaskRW, al endif mov al, cs: [di] .-A4ExifCSChannelIntNum ;Return the interrupt GenResetRevector ;vector to the OS ret ; default ProcEnd noret ProcBegin@ StartTheChannelRunning Fo eee eeeeeeea= ; Starts the hardware and interrupts going ; If the hardware is aready running then there is nothing to do ; Must check that the hardware has not vanished before restarting it H IN: ; Our CS control block pointer in DI 7 OUT: i Nothing 7 pushf cli cmp byte ptr cs: [di].A4ExifCSChannelRunning, 0 jne ChannelAlreadyRunning call CheckHardwarePresent jc HardwareNotPresent mov al, cs: [di] .-A4ExifCSChannelSelect HwSelectChannel push ax mov al, (SerialWriteSingle or A4Control) ; Switch on the SBUSY output latch U5 SCONTOUT ;by asserting mov al, U5_ENABLE_ON ;the ASIC4 LBO line SBUSY ; (LBO is inverted) SDATAOUT xor ax,ax mov dl, INTERRUPT_LATCH 7Clear any pending call OutputByte ;interrupt on the mov dl, US5OUTPUT_LATCH ;peripheral call OutputByte 7Preset the LEDs pop ax ;to all off HwSelectChannel call StartInterrupts mov cs: [di] .A4ExifCSChannelRunning, 1 ChannelAlreadyRunning: popft cle ret HardwareNotPresent: popft stc ret

ProcEnd noret

ProcBegin@ StopTheChannelRunning

Revision 1.00

Page 99 of 115 pages

The Psion SIBO Hardware Development Kit

Ne Ne Ne Ne

Stops the hardware and interrupts

Psion PLC (c) May 1995

Checks to see if the hardware is really running to start with

IN: Our CS control block pointer in DI

i OUT: ; Nothing 7

pushf

cli

cmp byte ptr cs:[di].A4ExifCSChannelRunning, 0

je ChannelNotRunning

mov al, cs: [di] .-A4ExifCSChannelSelect

HwSelectChannel

push ax

mov al, (SerialWriteSingle or A4Control)

SBUSY

SCONTOUT

mov al, U5_ENABLE_OFF

SBUSY

SDATAOUT

xor ax, ax

mov dl, US50OUTPUT_LATCH

call OutputByte

pop ax

HwSelectChannel

call StopInterrupts

mov cs: [di] .A4ExifCSChannelRunning, 0 ChannelNotRunning:

popft

ret

Se eT

ProcEnd noret

ProcBegin@ CheckHardwarePresent

Used to determine whether the correct hardware is present

on the successfully procured serial channel.

IN:

CS control block pointer in DI OUT:

Carry clear - correct hardware is there

Carry set - wrong or no hardware pushf cli ;Select the correct mov al, cs: [di] .A4ExifCSChannelSelect ;SIBO channel that HwSelectChannel ;the peripheral is push ax ;attached to HwNullFrame mov al, (SerialSelect or Asic4Id) SBUSY ;First look for an SCONTOUT 7;ASIC4 at the other XNOP ;end of the link SBUSY SDATAIN ;Ilf the returned test al,al ;value is non-zero je ConnectionFailedA4NotPresent ;we have an ASIC4 mov al, (SerialReadSingle or A4InfoR) SBUSY ;Now see if we have SCONTOUT ;the right peripheral XNOP 7;XNOP allows the busy SBUSY 7Signal to come SDATAIN ;through for the wait and al, A4PERIPH_MASK cmp al, EXTENDED_INFO_BYTE ;Mask out the bottom jne ConnectionFailed ;four bits as the pop ax yupper four contain HwSelectChannel ;the peripheral ID popft cle ;If it is our hardware ret 7exit with carry clear

ConnectionFailedA4NotPresent:

mov al, (SerialSelect or Asic5Normalld) ;Its not an ASIC4 SBUSY ;peripheral SCONTOUT 7By selecting a non XNOP 7;ASIC4 as an ASIC4, SDATAIN ;we effectively

test al,al

Revision 1.00

;disable whatever is

Page 100 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

jne ConnectionFailed yout there so we do mov al, (SerialSelect or Asic5PackId) ja select for all SBUSY ;possibilities so SCONTOUT ;that we don't end XNOP ;up disabling SDATAIN yanything that we

test al,al ;can't control. jne ConnectionFailed

mov al, (SerialSelect or Asic8Id) 7Modem chip id

SBUSY

SCONTOUT

XNOP

SDATAIN ConnectionFailed:

pop ax

HwSelectChannel

popft

stc

ret

ProcEnd noret

EndCodeSeg

stack segment stack para 'data' stack ends

end A4ExifLDD

Revision 1.00 Page 101 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

SYSS$AS5.ASM

title ASSPDD Epoc Serial physical device driver for the 16550 subttl Copyright Psion PLC 1993 name SYSSAS5

i VERSION DATE DESCRIPTION

me MEE ee ee ee eee

; Lat 08/12/94 Initial version

7 Written by Jason December 1994

: Serial Driver for Epoc based around ASIC5

Sr5s3 = 0

Sr5S3a = 1

ifdef BUILDS3

Sr5S3 = 1.

Sr5S3a = 0

BUILDHH equ 1

endif

a Sr5S3a

BUILDSB equ 1

endif include ..\inc\epoc.inc include ..\inc\epocser.inc include ..\inc\epoclib.inc include ..\inc\epocsibo.inc include ..\srcs\ossibo.inc include ..\srces\ospack.inc

Sr5ChannelStruct struc

Sr50pen db ? ; Is the channel open SrKSCtY1L db ? ; State of control lines Sr5IntVector db 2 ; The Vector number Sr5Channel db ? ; Which channel are we Sr5Mask db ? ; InterruptMask Sr5Running db ; Are we running Sr5IntRoutineVec dw cs ; Vector to Interrupt Sr5Baud dw ? ; The baud rate Sr5LddData dw ? ; Info from Ldd above Sr5StatusInt dd ? ; Vectors in serial Sr5Recvint dd 2 ; Above to be called Sr5XmitInt dd ? ; On input/output Sr5ClockEnable db ? ; Reason to stop

Sr5TheLines db ? ; State of the modem lines

Sr5ChannelStruct ends

A5Ent struc A5PortA A5PortB A5PortBMode A5PortD A5Swipel A5Swipe2 A5IntMask A5CtrlReg A5USR A5RHR A5BDLSB A5SBDMSB A5MCRIEoi A5MCRPresentEoi A5MCR2Eoi ASDUMMYF

A5Ent ends

Lt Consumer NumberOfChannels else NumberOfChannels endif OsActivityMeter StopTimeOut

S_RS2320N

Revision 1.00

db db db db db db db db

db db

db db db db db db

equ

equ

equ

equ

equ

VVV Vv vw

YN vn vv

158ch 1000

00000001b

at

ASIC5 Read/Write Port A R/W

Port B R/W Inc/Mode

Port CD Write only

Ne Ne Ne Ne Ne

Interrupt mask R/W IntType/Ctrl register UART Status/Ctrl Receive/Transmit

Baud Rate write only Baud Rate write only MCR shift register Barcode data&ints

’ ’

Ne Ne Ne Ne

; S3 Single Channel , HC,S3C Three Channel

; Activity Channel ; w~ls (1000ms) wait

7 RS232 on

Page 102 of 115 pages

The Psion SIBO Hardware Development Kit

Psion PLC (c) May 1995

S_RSTTLON equ 00000100b ; Line drivers on S_CENTON equ 00010000b ; Line drivers enable S_RXENB equ 00000001b ; Receive interrupt on S_TXENB equ 00000010b ; Transmit interrupt on S_TXEMPTY equ 00010000b ; transmit buffer empty S_RXINT equ 00000001b ; Receive interrupt? S_TXINT equ 00000010b ; transmit interrupt? S_MDINT equ 00000100b ; Modem status interrupt S_CTS equ 00000001b # CLS S_RTS equ 00000010b ; RTS S_DCD equ 00000100b DCD S_DSR equ 00000010b ; DCR S_DTR equ 00000100b ; DIR OVERRUN_ERROR equ 01000000b ; Character overrun PARITY_ERROR equ 10000000b ; Parity error S_PERIPHERALMODE equ 00000011b ; ASIC5 RS232 mode S_UART_OFF equ 00000010b ; ASIC5 peripheral mode dgroup group stack assume ds:dgroup,es:dgroup,ss:dgroup CodeSeg ProcBegin@ OsAS5PDD ; SiS SeSe Sees Ses eceses dw PDDSignature db 'TTY.SR5',0 dw (VectorEnd-Vector) /2 Vector: dw OsAS5SInstall dw OsAS5Remove dw OsAS50Open dw OsAS5Strategy VectorEnd:

BaudRateTable dw

-077f£h, -04£fh, -0368h, -02cch, -027£h, -013fh

dw -009fh, -004fh, -0035h, -0030h, -0027h, -0019h dw -—0013h, -000ch, -0009h, -0004h

DataBitsTable db 0,2,4,6

’

5,6,7,8 bits per char frame

ParityTable db 08h,18h, 0h, 0h ; Even,Odd,Mark, Space parity Chan0O Sr5ChannelStruct <> Chanl Sr5ChannelStruct <> Chan2 Sr5ChannelStruct <>

if Consumer

if Asic9 SetupTable dw offset AS5Int1l db HwIrq2Revector,mask A9MSlave db SelectChannel5, (mask A9MClockEnable5 shr 8) else SetupTable dw offset AS5Intl db HwIrq4Revector,mask Asic2Int db SelectChannel7, (mask ClockEnable7 shr 8) endif else if Asic9 SetupTable dw offset AS5Int1l db HwIrq4Revector,mask A9MExpIntA db SelectChannel3, (mask A9MClockEnable3 shr 8) dw offset AS5Int2 db HwIrq5Revector,mask A9MExpIntB db SelectChannel4, (mask A9MClockEnable4 shr 8) dw offset ASSInt3 db HwIrq2Revector,mask A9MSlave db SelectChannel5, (mask A9MClockEnable5 shr 8) else SetupTable dw offset AS5Int1l db HwIrq3Revector,mask ExpIntLeftA db ExpChannelLeftA, (mask ClockEnableé shr 8) dw offset AS5Int2 db HwIlrq2Revector,mask ExpIntRightB db ExpChannelRightB, (mask ClockEnable5 shr 8) dw offset AS5Int3 db HwIrq4Revector,mask Asic2Int db SelectChannel7, (mask ClockEnable7 shr 8) endif endif

ProcEnd noret

Revision 1.00

Page 103 of 115 pages

The Psion SIBO Hardware Development Kit

ProcBegin@ OsAS5Install, far

Install the device driver Out: Carry clear -happy to install

cld mov cx, NumberOfChannels mov di, offset Chan0od mov si, offset SetupTable pushf cli push ds mov ax, Cs mov ds, ax ResetAllChannelsLoop: mov di].Sr50pen, 0 lodsw mov di].Sr5IntRoutineVec, ax lodsb mov di].Sr5IntVector, al lodsb mov di].Sr5Mask, al lodsb mov di].Sr5Channel, al lodsb mov di].Sr5ClockEnable, al add di, size Sr5ChannelStruct loop ResetAllChannelsLoop pop ds popft AllChannelsOkay: cle ret

Mee Ne

Ne Ne Ne Ne

GotChan:

Revision

ProcEnd noret

ProcBegin@ OsAS5Remove, far

Remove the device driver Out: Carry clear -happy to remove

’ ’

~

Ne Ne Ne Ne

Psion PLC (c) May 1995

Clear the channels and set up fixed parameters such

as the interrupt vectors and masks for each channel

Channel not open

Set the interrupt handler to call hich Interrupt

=

Mask for that interrupt

Which Psion serial channel

Baud rate clocking enable

Returns with Carry clear

Carry set -we have an open channel and cant be removed.

xor ax, ax or al, Chan0O.Sr50pen or al, Chanl.Sr50pen or al, Chan2.Sr50pen jz AllChannelsOkay mov ax, InUseErr

stc

ret

ProcEnd noret

ProcBegin@ OsAS5Open, far

Open a serial channel

see

In: SS:SI is a pointer to the open Ent Structure

Out: Carry clear, control block in BX

Carry set, error in AX

cld

mov si, [si] .OpenNamePtr mov al, [sitl] CharToFoldedChar

cmp al, 'A'

jb ErrorInOpen

sub al, ‘'A'

cmp al, NumberOfChannels jae ErrorInOpen

xoOr ah, ah

mov bx, offset Chan0O

cmp al, 1

jb GotChan

mov bx, offset Chan2

ja GotChan

mov bx, offset Chanl

mov al, 1

1.00

If we have a channel Still open then return a can't do error else complete okay

Open the channel Get the channel Make Upper Case Indicator which is Part of the name Should be A,B,C

What Channel are We Openning Pointer to Control Block in bx

Page 104 of 115 pages

The Psion SIBO Hardware Development Kit

xchg al, cs: [bx].Sr50Open cmp al, 0 je OkayToOpen CantOpen: mov ax, InUseErr CantOpenDiffErr: stc ret ErroriInOpen: mov ax, NameErr stc ret OkayToOpen: xor al, al mov cs: [bx].Sr5Running, al mov cs: [bx].Sr5TheLines, al mov cs: [bx].Sr5Ctrl, al mov al, cs: [bx].Sr5Mask HwGetChannel jc CantOpenSoClose call CheckHardwarePresent jne OpenedOkay mov al, cs: [bx].Sr5Mask HwF reeChannel CantOpenSoClose: mov cs: [bx].Sr50pen, 0 mov ax, DeviceErr jmp short CantOpenDiffErr OpenedOkay: xor ax, ax ret

ProcEnd noret

AS5StrategyJumpTable label word

dw offset AS50Open

dw offset AS5Close

dw offset AS5Start channel

dw offset AS5Stop

dw offset AS5Set

dw offset AS5Sense

dw offset AS5Control

dw offset ASS5Enquire

dw offset AS5Enable

dw offset AS5SetHandlerCs

ProcBegin@ OsAS5Strategy, far

Strategy functions entry point

Psion PLC (c) May 1995

7 Now try to Open ; That channel

; Check that we have ; The right Hardware

Return with the Offset of our Control Block In bx

Ne Ne Ne Ne

; Load Handler offsets ; Close the channel ; Start the

7 Stop the channel ; Does nothing ; Returns chan status ; Drive the lines ; Returns baud rate ; Begin Output ; Get Handler segments

In: vector number in AX + various data in other registers

; Select the correct

; Output channel Then Call the right Function to deal

; With the strategy

7; request

’ ’

; Interrupts off ;, and flags are on ; the stack

7 7 Warning! This can be called from within Interrupt 7 iH DS is OsDataGroup (and MUST be preserved) ; Out: DI is pointer to control block H Old channel and flags on stack

cld

mov bx, sp

mov bx, ss: [bx+4]

mov bl, cs: [bx].Sr5Channel

xchg bx, ax

pushf

cli

HwSelectChannel

mov ah, bh

xOr bh, bh

push ax

mov ax, di

mov di, sp

mov di, ss: [dit+8]

jmp AS5StrategyJumpTable [bx]

ProcEnd noret

ProcBegin@ AS5Open, far

; Old channel and flags on the stack, mov cs: [di].Sr5LddData, cx mov word ptr cs: [di].Sr5StatusInt,

Revision 1.00

interrupts off

; Load the offsets of

ax ; the data send and

Page 105 of 115 pages

The Psion SIBO Hardware Development Kit

if

else

endif

mov word ptr cs:[di].Sr5RecvInt, si mov word ptr cs:[di].Sr5XmitInt, dx xor ax, ax

pop ax

HwSelectChannel

popft

ret

ProcEnd noret

ProcBegin@ AS5Close, far

Old channel and flags on the stack,

and cs:[di].Sr50Open, 0 mov al, cs: [di].Sr5Mask HwF reeChannel

pop ax

HwSelectChannel

popft

ret

ProcEnd noret

ProcBegin@ AS5Start, far

Old channel and flags on the stack,

call CheckHardwareFromStart

mov dx, 0

je CantStartSomethingWhichIsntThere Asic9

in ax, AQWControlExtraRW

or ah, cs: [di].Sr5ClockEnable

out A9QWControlExtraRW, ax

mov al, cs: [di].Sr5ClockEnable HwSetA2Control2Bits

mov al, SerialWriteSingle or A5USR SBUSY

SCONTOUT

mov al, cs: [di].Sr5Ctrl

SBUSY

SDATAOUT

mov al, SerialWriteSingle or A5BDLSB SBUSY

SCONTOUT

mov al, byte ptr cs: [di].Sr5Baud SBUSY

SDATAOUT

mov al, SerialWriteSingle or A5BDMSB SBUSY

SCONTOUT

mov al, byte ptr cs: [dit+1].Sr5Baud SBUSY

SDATAOUT

call Get TheInterrupt

xor CX), Cx

call DriveRts

mov al, SerialWriteSingle or A5CtrlReg SBUSY

SCONTOUT

mov al, (S_CENTON or S_RS2320N or SBUSY

SDATAOUT

mov cx, 8 ; 8 ms

pop dx

call WaitTimer

push dx

mov ah, (S_RXENB or S_TXENB or S_MDINT) call EnableTheInterrupt

mov cs:[di].Sr5Running, 1

mov bx, Asic5SerialCurrent HwSetPCurrent

call Status

Revision 1.00

interrupts

Psion PLC (c) May 1995

; veceive routines in ; the Ldd above us ; DX=0 —-We don't support 7; power management ; Return the old ; Channel

interrupts off

; Close the Channel

; Free up our channel ; And the Hardware

; Channel

; Return the old

; channel

off

; Start the S3s clock ; Generator

; Set the baud rate ; and other ; Characteristics

Get the interrupt and clear down

the RTS line (DTR stays at the state ; it was set)

’ ’

’ ’

S_RSTTLON)

; Switch on the line ; QGrivers and wait ; for them to power up

; Start all interrupts

Page 106 of 115 pages

The Psion SIBO Hardware Development Kit

CantStartSomethingWhichIsntThere:

pop ax HwSelectChannel popft ret

ProcEnd noret

ProcBegin@ AS5Stop, far

Psion PLC (c) May 1995

; Return the old ; Channel

; Old channel and flags on the stack, interrupts off xor CX, CX ; Clear the state of call DriveRts ; the modem lines mov al, SerialReadSingle or A5IntMask ; Stop all of the SBUSY ; interrupts SCONTOUT XNOP SBUSY SDATAIN and al, not (S_TXENB or S_RXENB or S_MDINT) mov ah, al mov al, SerialWriteSingle or A5IntMask SBUSY SCONTOUT mov al, ah SBUSY SDATAOUT pop ax cmp dh, DevHoldPowerFail je Dont StopHardware cmp cs:[di].Sr5Running, 1 jne DontWait mov cx, StopTimeOut jmp short CompareNow WaitForEmpty: call TickTimer CompareNow: mov al, SerialReadSingle or A5USR SBUSY SCONTOUT XNOP SBUSY SDATAIN test al, S_TXEMPTY loopne WaitForEmpty DontWait: cmp bh, DevHoldNormal je Dont StopHardware if Asic9 mov cl, cs: [di].Sr5ClockEnable ; Turn off baud rate not cl ; Clocking from the in ax, A9WControlExtraRW } S3y3a and ah, cl out A9WControlExtraRW, ax else mov al, cs: [di].Sr5ClockEnable HwClearA2Control2Bits endif mov al, SerialWriteSingle or A5CtrlReg ; Stop the drivers SBUSY , and stuff SCONTOUT sub al, al ; Clear S_CENTON, SBUSY 7 S_RS2320N, S_RSTTLON SDATAOUT Dont StopHardware: mov al, dl ; Return the old HwSelectChannel ; Channel popft xor bx, bx HwSetPCurrent ret ProcEnd noret ProcBegin@ AS5Set, far ; Se SeSeees ees Sees ; Old channel and flags on the stack, interrupts off

Revision 1.00

Page 107 of 115 pages

The Psion SIBO Hardware Development Kit

; In: Information required is on the stack pop ax HwSelectChannel popft mov ah, ss:[si].SerialCharTbaud cmp ah, ss: [si] .SerialCharRbaud jnz ErrorInSet cmp ah, P_BAUD_50 jb ErroriInSet cmp ah, P_BAUD_19200 ja ErroriInSet Got TheSpecialBaud: dec ah mov cl, ss:[si].SerialCharFrame mov al, ss:[si].SerialCharParity dec al xor ch, ch push bx test cl, P_TWOSTOP jz OnlyOneStopBit or ch, 020h OnlyOneStopBit: test cl, P_PARITY jz NoParity mov bx, offset ParityTable xlat cs: [ParityTable] or ch, al NoParity: mov bx, offset DataBitsTable and cl, P_DATA_FRM mov al, cl xlat cs: [DataBitsTable] Or ch, al mov bx, offset BaudRateTable mov al, ah xOr ah, ah shl ax, 1 add bx, ax mov ax, cs: [bx] pop bx mov es? [dt] .Sractrl; ch mov cs:[di].Sr5Baud, ax xOr al, al ret ErroriInSet: mov al, NotSupportedErr stc ret

ProcEnd noret

ProcBegin@ AS5Sense, far

seo

’

’

’

’

~

Psion PLC (c) May 1995

Return the old channel

Set the Recieve, Transmit characteristics First set the Baud

Rate

Then the number of Stop bits

The Parity

And finally the Number of data bits Per frame

; Old channel and flags on the stack, interrupts off ; Out: The state of the DCD,CTS,DSR lines returned in DX call Status pop ax ; Return the old HwSelectChannel ; Channel popft ret

ProcEnd noret

ProcBegin@ Status

i Out: State of modem lines in DX mov al, SerialReadSingle or A5USR SBUSY SCONTOUT XNOP SBUSY SDATAIN and al, (S_CTS or S_DSR or S_DCD) xor al, (S_CTS or S_DSR or S_DCD) xOr ah, ah

Revision 1.00

see

Get the current Modem status Lines and return With the result In dx

Get the lines we want Invert signals

Page 108 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

mov ax, ax ret ProcEnd noret

ProcBegin@ AS5Control, far

; Old channel and flags on the stack, interrupts off

7 In: Lines to drive and state to drive them in DX mov onl emo ie ; Set the state of one test dh, P_SRCTRL_DTR ; of the modem Lines jz DriveRtsNow ; DH is the line to call DriveDtr ; Drive and DL is the pop ax ; Stateto drive it to HwSelectChannel ; Return the old popft ; channel ret

DriveRtsNow: call DriveRts pop ax ; Return the old HwSelectChannel ; channel popft ret

ProcEnd noret

ProcBegin@ DriveDtr

mov ah, S_DTR ; Set/Reset the DTR jmp short DriveTheLine ; Line ProcEnd noret

ProcBegin@ DriveRts

mov ah, S_RTS ; Set/Reset RTS DriveTheLine: mov al, SerialWriteSingle or A5PortD ; Common code to set SBUSY ; and reset either SCONTOUT ; line while mov al, cs:[di].Sr5TheLines ; preserving the test cl, cl ; states of the other IZ ClearLine ; lines or al, ah jmp DoTheOutput ClearLine: not ah and al, ah DoTheOutput: mov cs:[di].Sr5TheLines, al SBUSY SDATAOUT ret

ProcEnd noret

ProcBegin@ AS5Enquire, far

7 Old channel and flags on the stack, interrupts off - Out: DX,AX are the supported baud rates AX for 50 to 19200 DX for above ; CX says what data bits, parity, etc we support pop ax ; Return the old HwSelectChannel ; Channel popf if Asic9 mov ax, —-1 else mov ax, O7fffh endif xor dx, ax mov cx, (Offffh AND (NOT (P_SRINQ_SPLIT OR P_SRINQ_PARSPACE OR P_SRINQ_PARMARK) ) ) ret

ProcEnd noret

ProcBegin@ AS5Enable, far

Revision 1.00 Page 109 of 115 pages

The Psion SIBO Hardware Development Kit

Psion PLC (c) May 1995

- Old channel and flags on the stack, interrupts off mov ah, S_TXENB ; Begin Output by call EnableTheInterrupt ; enabling transmit pop ax ; interrupts HwSelectChannel ; Return the old popft ; channel ret

ProcEnd noret

ProcBegin@ AS5SetHandlerCs, far

CX is CS of above LDD

sew

mov word ptr cs: [di]. (Sr5StatusInt+2), cx mov word ptr cs:[di].(Sr5RecvInt+2), cx mov word ptr cs: [di]. (Sr5XmitInt+2), cx pop ax

HwSelectChannel

popft

ret

ProcEnd noret

ProcBegin@ AS5Int3, far

mov di, offset Chan2 mov ax, PortCActive jmp ComInt

ProcEnd noret

ProcBegin@ AS5Int2,far

mov di, offset Chanl mov ax, PortBActive jmp ComIint

ProcEnd noret

ProcBegin@ AS5Int1,far

mov di,offset Chan0 mov ax, PortAActive 4 FALL THROUGH

ProcEnd noret

ProcBegin@ ComInt, far

The common interrupt handler DS points to OS data space DI is our control block

Mee Ne

; AX is the Active channel ab S3b or S3c

or ds: [OsActivityMeter], ax endif

mov al, cs: [di].Sr5Channel

HwSelectChannel

push ax

mov bx, cs: [di].Sr5LddData TheInterruptLoop:

mov al, SerialReadSingle or A5CtrlReg

SBUSY

SCONTOUT

XNOP

SBUSY

SDATAIN

test al, al

je NothingToDo HaveWeGotAModemStatusLineInterrupt:

test al, S_MDINT

4z HaveWeGotARecievelInterrupt

mov al, SerialReadSingle or A5USR

SBUSY

SCONTOUT

Revision 1.00

~

Mee Ne

Old channel and flags on the stack, interrupts off

; Load the Segment

; Within which the The Ldd above us Return the old channel

; Resides

Channel 3 interrupt vector Jumps to Comint

see

~

Channel 2 interrupt vector Jumps to Comint

seo

~

Channel 1 interrupt 7; vector

; Falls through

7 to Comint

; Set active state

; Select our ; Channel

; Data for LDD above ; in bx

; Find out what

; caused the

; interrupt

Page 110 of 115 pages

The Psion SIBO Hardware Development Kit

Psion PLC (c) May 1995

; Something has been ; recieved in error

; Establish the error

; Get the character ; in question

; invert signals

XNOP SBUSY SDATAIN test al, (OVERRUN_ERROR or PARITY_ERROR) jz ModemStatusInterruptOnly push ax mov ah, SERPARITY_ERR test al, PARITY_ERROR jnz IsAParityError mov ah, SEROVERRUN_ERR IsAParityError: mov al, SerialReadSingle or A5RHR SBUSY SCONTOUT XNOP SBUSY SDATAIN push di call dword ptr cs: [di] .Sr5RecvInt pop di pop ax ModemStatusInterruptOnly: and ax, (S_CTS or S_DSR or S_DCD) xor al, (S_CTS or S_DSR or S_DCD) mov ax, ax push di call dword ptr cs: [di].Sr5StatusInt pop di jmp short TheInterruptLoop

HaveWeGotARecievelInterrupt:

; AX has character received

Resced if neccessary

; Gisable TX interrupts

test al, S_RXINT jz HaveWeGotATransmitInterrupt mov al, SerialReadSingle or A5RHR SBUSY SCONTOUT XNOP SBUSY SDATAIN xOr ah, ah push di call dword ptr cs: [di] .Sr5RecvInt pop di jmp short TheInterruptLoop HaveWeGotATransmitInterrupt: test al, S_TXINT jz NothingToDo push di call dword ptr cs: [di] .Sr5XmitInt pop di test ax, ax ; —-l1 if disable js DisableTransmitInts mov ah, al mov al, SerialWriteSingle or A5RHR SBUSY SCONTOUT mov al, ah SBUSY SDATAOUT jmp TheInterrupt Loop NothingToDo: if Asic9 out A9BNonSpecificEoiwW, al else out AlNonSpecificEoi, al endif pop ax HwSelectChannel cle ; ret DisableTransmitInts: mov al, SerialReadSingle or A5IntMask SBUSY SCONTOUT XNOP SBUSY SDATAIN and al, not S_TXENB mov ah, al mov al, SerialWriteSingle or A5IntMask SBUSY

Revision 1.00

Page 111 of 115 pages

The Psion SIBO Hardware Development Kit

SCONTOUT mov SBUSY SDATAOUT jmp TheInterrupt Loop ProcEnd noret

al, ah

ProcBegin@ GetTheInterrupt

mov al, cs:[di].Sr5IntVector H mov Cx, CS F mov bx, cs:[di].Sr5IntRoutineVec ; GenSetRevector A ret ,

ProcEnd noret

ProcBegin@ EnableTheInterrupt

mov al, SerialReadSingle or A5IntMask SBUSY SCONTOUT XNOP SBUSY SDATAIN or ah, al mov al, SerialWriteSingle or A5IntMask SBUSY SCONTOUT mov al, ah SBUSY SDATAOUT if Asic9 in al, A9BInterruptMaskRW ; or al, cs: [di].Sr5Mask ; out A9BInterruptMaskRwW, al else in al, AlInterruptMask or al, cs: [di] .Sr5Mask out AlInterruptMask, al endif ret ProcEnd noret ProcBegin@ StopInterrupts ; StessSeSesee—e-Seeeseeese mov al, SerialReadSingle or A5IntMask H SBUSY ; SCONTOUT XNOP SBUSY SDATAIN and al, not (S_RXENB or S_TXENB or S_MDINT) mov ah, al mov al, SerialWriteSingle or A5IntMask SBUSY SCONTOUT mov al, ah SBUSY SDATAOUT mov ah, cs: [di].Sr5Mask not ah if Asic9 in al, A9BInterruptMaskRW ; and al,ah ; out A9BInterruptMaskRW, al ; else ; in al, AlInterruptMask and al,ah out AlInterruptMask, al endif mov al, cs:[di].Sr5IntVector GenResetRevector ret

Revision 1.00

Psion PLC (c) May 1995

Load the address of the appropriate interrupt routine into the correct vector

Set the mask to enable Interrupts

Stop interrupts from Asic5

Stop Interrupts By clearing the

Mask and resetting The Vector

Page 112 of 115 pages

The Psion SIBO Hardware Development Kit

ProcEnd noret

ProcBegin@ CheckHardwarePresent

mov al, cs: [bx] .Sr5Channel HwSelectChannel HwNullFrame mov al, (SerialSelect or Asic5Normalld) SBUSY SCONTOUT XNOP SBUSY SDATAIN test al,al je ConnectionFailed GotConnection: popft ous) ret ConnectionFailed: mov al, SBUSY SCONTOUT XNOP SBUSY SDATAIN test jne mov SBUSY SCONTOUT XNOP SBUSY SDATAIN test jne mov SBUSY SCONTOUT XNOP SBUSY SDATAIN ConnectionFailedExit: popft stc ret ProcEnd noret

SerialSelect or Asic4Id

al, al ConnectionFailedExit al, SerialSelect or Asic8Id

al, al ConnectionFailedExit al, SerialSelect or Asic5PackId

ProcBegin@ CheckHardwareFromStart

pushf

HwNullFrame

mov al, (SerialSelect or Asic5Normalld) SBUSY

SCONTOUT

XNOP

SBUSY

SDATAIN

test al,al

je ConnectionFailed

test al, mask A5MultiDrop

jne ConnectionFailedExit

popft mov SBUSY SCONTOUT mov SBUSY SDATAOUT cle

ret ProcEnd noret

al,

al, S_PERIPHERALMODE

ProcBegin@ WaitTimer

Revision 1.00

SerialWriteSingle or A5PortBMode

Ne Ne Ne Ne te

Ne Ne Ne Ne Ne

’

Psion PLC (c) May 1995

Check that the ; Harware is there

And that it is what It should be

First look for An ASIC4 at the other End of the link

’

’

’

Asic4 Id

Modem chip Id

Asic5Spack Id

Check that the Harware is there First look for An ASIC5 at the other End of the link

’ ’ ’

If not a 3link or if in multidrop mode then we are in trouble

Put the 3Link in peripheral mode

Page 113 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

In: CX number of ms to wait for Channel store in DL Out: Channel store in DL

Wait for a given

inc cx i

WaitTickLoop: ; Number of ms call TickTimer ; Plus one to guarantee loop WaitTickLoop ; That at least cx ms ret 7 Go by ProcEnd

WaiterLoop:

stack stack

ProcBegin@ TickTimer

Uses writes down our channel to simulate tick timer waits

Must allow interrupts so other things can run -we will be here for 1/1000 of a second and may be called many times ChannelStore in/out in DL

mov al, dl ; Return the old HwSelectChannel ; Channel

mov ah, al pushf

sez

push Cx

mov cx, 12 ims

128 frames =1lms

pushf about 12 times

cli 7 round the loop

out ResetWatchDog, al

mov al, ah

HwSelectChannel

mov dl, al ; Get Correct channel mov al, (SerialWriteSingle or 0) Do a write to

SBUSY nowhere and

SCONTOUT waste some time

See Ne

See Ne

SCONTOUT ; Do it eight times

SBUSY SCONTOUT SBUSY mov al, dl HwSelectChannel mov ah, al popft

loop WaiterLoop pop CX

popft

mov al, ah HwSelectChannel mov dl, al ret

ProcEnd

Return the old channel

’ ’

EndCodeSeg

segment stack para 'data' ends

end OsAS5PDD

Revision 1.00 Page 114 of 115 pages

The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995

Assembler Macros

Excerpts from the include file ossibo.inc.

if ASIC1 SCONTOUT macro out A2SerialControl, al endm SDATAOUT macro out A2SerialData, al endm SBUSY macro wait endm SREAD macro _REG mov al, SerialReadSingle or _REG out A2SerialControl, al nop SBUSY in al, A2SerialData endm SREADM macro _REG mov al, SerialReadMulti or _REG out A2SerialControl, al nop SBUSY in al, A2SerialData endm SWRITE macro _REG,_VAL mov al, SerialWriteSingle or _REG out A2SerialControl, al SBUSY mov al, _VAL out A2SerialData, al endm SWRITEM macro _REG,_VAL mov al, SerialWriteMulti, _REG out A2SerialControl, al SBUSY mov al, _VAL out A2SerialData, al endm endif ach ASIC9 SCONTOUT macro out A9BSerialControlW, al endm SDATAOUT macro out A9BSerialDataRW, al endm SDATAIN macro in al, A9BSerialDataRW endm SBUSY macro endm SREAD macro _REG mov al, SerialReadSingle or _REG out A9BSerialControlwW, al in al, A9BSerialDataRW endm SREADM macro _REG mov al, SerialReadMulti or _REG out A9BSerialControlwW, al in al, A9BSerialDataRW endm SWRITE macro _REG,_VAL mov al, SerialWriteSingle or _REG out A9BSerialControlwW, al mov al, _VAL out A9BSerialDataRW, al endm SWRITEM macro _REG,_VAL mov al, SerialWriteMulti or _REG out A9BSerialControlwW, al mov al, _VAL out A9BSerialDataRW, al endm endif

Revision 1.00 Page 115 of 115 pages