myatari.net

[ Advert ]

> Home

 

 

 

 

 

 

> Issue 10
 

Contents

 

Features

-  

Foreword

-  

DSP Mega Power!

-  

Tip of the day

-  

Arpeggiators

-  

How to build a Lego Atari mouse

-  

Mailbox

-  

The Atari XL PBI -
Part 3

 

 

Reviews

-  

aMail 1.27b

-  

KCS Omega

 

 

The Atari XL Parallel Bus Interface - Part 3

By Roland Scholz

 

The last two articles have shown which signals have to be used to form a PBI device that conforms to the Atari specification. This device is noticed and embedded into the during the power up procedure. As mentioned before, the math-pack-disable (MPD\) signal plays an important role, since it is responsible for switching off the internal Math-ROM and turning on the device's ROM if it is activated using the address NEWPORT ($D1FF).

Now we are going to consider the data structure that has to be programmed into the ROM, to enable the OS to recognize the device:

Figure 1

Figure 1: ROM vector table ($D800- $D81C), fields marked with * do not have to be filled in.

The first three fields can hold information about the checksum and version of firmware contained in the ROM. This information as well as the device name and type is not checked by the OS and can be left out. All other fields have to be filled correctly, otherwise the computer will probably hang.

After pressing the reset key the OS turns off any active PBI device. After this, each bit of NEWPORT is serially set to 1. Then locations $D808 and $D80B are checked for the values $80 and $91 respectively. If both are true (the Math-ROM contains other values, of course), the OS performs a subroutine jump to $D819. A PBI ROM usually contains a JMP ($4C) statement followed by an address to the initialization routine in the device's ROM. This routine can be used to initialize registers and insert the device into the operation system’s device table (HATABS).

The following figure shows an example of a possible data structure and init-routine.

 

DUMMY    ORG $D800

 

PBITAB   DFB $CA,$FE,0     Checksum and ROM version

                           (values don’t care)

         DFB $80           ID-Number 1

         DFB 0             Device-Type

         JMP SIOVEC        SIO I/O-Vector

         JMP IRQVEC        IRQ IRQ-Vector

         DFB $91           ID-Number 2

DEVNAME  DFB 'Z            Handler-Name

         DFW OPEN-1        HATABS-entries

         DFW CLOSE-1

         DFW GET-1

         DFW PUT-1

         DFW CLOSE-1

         DFW SPECIAL-1

         JMP INIT

         DFB 0

Figure 2: PBI data-structure.

 

NEWDEV   EQU $E486

GENDEV   EQU $E48F

 

DEVMASK  EQU $247     PBI-device already known to

                      the OS

NDEVREQ  EQU $248     Activated PBI-devive

 

HATABS  EQU $31A

*

         ORG $somewhere

*

SIOVEC   CLC          All SIO calls try to use the

                      PBI-device. We do not want to

                      implement a SIO driver, so CLC

                      and RTS tell SIO we do not handle

                      its requests.

IRQVEC   RTS          Our implementation does not use

                      interrupts.

*

* The device is registered to the OS by setting

* the appropriate bit in the DEVMASK register

* and the CIO handler is registered in the HATABS

* table by calling the NEWDEV routine

*

INIT     LDA DEVMASK

         ORA NDEVREQ

         STA DEVMASK

 

         LDX DEVNAME

         LDA #GENDEV:H

         LDY #GENDEV:L

         JSR NEWDEV

 

         STA HATABS+1,x

         TYA

         STA HATABS,x

 

         ...

         ... Code device-specific initializations here

         ...

         ...

 

         RTS

 

OPEN     ...

         ...

 

CLOSE    LDY #1

         SEC

         RTS

 

GET      ...

         ...

 

PUT      ...

         ...

 

SPECIAL  ...

         ...

Figure 3: Code example for initialization of PBI-devices.

Since the OS finds the corresponding ID values $80 and $91 at the given addresses, it performs a subroutine jump to $D819. Through the JMP statement execution continues at the routine INIT. There the register DEVMASK containing all PBI-devices that have been found so far is read. To this value the bit of the actual activated device (stored in NDEVREQ) is OR-ed and the result is saved back to DEVMASK. This ensures the OS always knows about out device. The next task is to read the device character under which the device is known to the CIO. This can be any character, however we should be careful and not override such devices as D: or E: without knowing exactly what we are doing. In the example the driver would be registered under the name Z: which is done using the routine NEWDEV.

The routine takes the name of the device in register X and the address of the CIO handler table in the accumulator and Y-register. We are going to register the generic handler GENDEV which is a part of the OS specially written to easily support PBI devices. The routine NEWDEV will end up with following return-codes:

  • Negative bit set: HATABS is full, the entry could not be written.
  • Carry bit clear: The entry has been successfully written to the table.
  • Carry bit set: The table already contains the requested entry, the X register holds  the index to the entry found.

For this example we do not care about the return codes, instead we just write our handler address into the table. After this the hardware registers of the device can be initialized and using RTS we jump back to the calling OS power-up routine.

So far we have registered a certain character as a handler name and we have told the OS there is a PBI device that can be activated using a certain bit in NEWPORT. The last thing to describe is the procedure the GENDEV generic handler undergoes if we try to communicate with the registered Z: handler. We assume a BASIC program would perform an OPEN #2,4,0,“Z:“ statement, in other words channel #2 is to be opened for reading using the handler Z:

Utilizing the CIO handler table HATABS the OS figures out the generic PBI-device driver is to be used to perform that action. GENDEV then activates all registered PBI devices one by one and jumps to the open routine through the open vector contained in the data structure. The open routine should then check if it supports the given handler name (Z:) by checking the content of address IOCBCHIDZ ($20). If it does not, it has to clear the carry flag and to jump back via RTS, so the generic handler can try the next device. If the open routine finds it is the “right“ routine, all actions to open the channel should be done here and a RTS has to be performed with carry bit set, so the generic habdler knows the open action has been performed correctly.

The CIO return-code has to be put back in the Y register and should be 1 if the action was performed correctly. All other functions usually implemented by a device handler (open, close, get, put, status, special) work in the same way; if the function is performed correctly, the carry bit has to be set and the CIO return code is contained in register Y.

Several PBI devices can share the GENDEV driver as long as each firmware checks whether it is the one the OS wants to call.

The next article will show a full-function implementation of a PBI device.The device acts as an interface to PC-cards like multi-I/O (RS232, Centronics) or Hercules graphics cards. The interface consists of both hardware and software (firmware) of which some details will be considered.

roland_scholz@web.de


MyAtari magazine - Feature #7, August 2001

 [ Top of page ]

 

 

Copyright 2001 MyAtari magazine