Last time we designed some hardware that would let us get data into and out
of the machine.  But if you tried this, you might have found out that the
computer failed to notice that a podule was present - so *Podules said 'No
installed podule'.  Now we're going to discuss some of the features that make
RISC OS podules really plug-and-play.

Data bus mapping

But first a slight digression.  I haven't told the whole truth about reading
and writing data from podules, especially if you have a 16 bit wide podule. 
For IOC (all we've covered so far) and MEMC podules, you need to be careful
what you do for writes.  Specifically, a write to the podule bus, which is 16
bits wide, takes the data from the *top half* of the data bus - so bits
16-31.  So when writing, you must ensure that the data is present on the top
16 bits of the write.

In fact this isn't as bad as it sounds.  If you use STRB to write a byte, the
ARM duplicates the byte on all four byte-lanes (bits 0-7, 8-15, 16-23, 24-31)
on the bus.  So your byte gets sent out on bits 16-23, which the IOC receives
and sends down the podule bus on data lines BD0-7.

You only have to be careful when writing 16-bit words.  Later ARMs (StrongARM
onwards) have instructions to allow accessing 16 bit values directly to/from
memory (LDRH and STRH) - but no RISC OS machines before Iyonix support them. 
So you are forced to use a 32 bit write instead (STR).  Now, since the data
is latched on bits 16-31 of the data bus, you must put your 16-bit word
there.  The podule specification also asks for compatibility that the word is
duplicated in the lower 16 bits as well.  So to write &1234 to a location
held in Raddress, you might use:

; A 16 bit value we wish to write to our podule
MOV Rdata,#&1200
ORR Rdata,Rdata,#&0034
...
; shift so that it occupies the top 16 bits
MOV Rdata,Rdata,ASL#16
; duplicate in the lower 16 bits
ORR Rdata,Rdata,Rdata,LSR#16
; do the write
STR Rdata,[Raddress]

EASI and DEBI space aren't subject to these restrictions, but I'll cover this
another time.

Supervisor mode

Now the above is all very well, but remember we need to be in supervisor mode
for the ARM to let us write or even read podule space.  Using *Memory(A) is
all very well, but it doesn't lend itself to writing programs to access
podules.  There is indeed a better way...

The best way to get into supervisor mode is to write a module.  All module
entry points except the start code are called in supervisor mode, so you can
access podule straight away.  In fact if you need to use interrupts a module
is usually necessary anyway  (we'll come to that later).

But if you want to play with podules from applications, it is possible using
assembler.  To switch into supervisor mode, from assembler just call the
SWI OS_EnterOS.  Switching back to user mode is a little more complicated,
especially with the need to support 32 bit versions of RISC OS.  This can be
seen in the example below:


; in user mode
SWI    OS_EnterOS ; switch to supervisor mode

; access the hardware here - now in supervisor mode

;this fragment switches back into user mode
TEQ    r0,r0      ; set Z
TEQ    pc,pc      ; EQ if 32 bit mode, NE if 26
MRSEQ  r8,CPSR    ; or DCD &010FF000
MOVNE  r8,pc      ; get the PSR
BIC    r8,r8,#3   ; set user mode
MSREQ  CPSR_c,r8  ; or DCD &0121F008
TEQNEP r8,#0      ; write to PSR
MOV    r0,r0      ; NOP for ARM2 compatibility
; back in user mode


This uses R8 as a scratch register, and works in both 26 and 32 bit modes on
ARM2 upwards.  If you use the BASIC assembler the MSR/MRS instructions are
only assembled on RISC OS 4 onwards, for which you need to set bit 4 of OPT
to use them.  If you have an earlier OS, replace them with DCD directives as
shown above - this only affects the assembler source, not their function.

If you're even lazier than that, use my SVCUtils module (on this month's
disc, or from my website listed at the bottom of this article).  This is
just called with a SWI and just executes an LDR/STR for you - but being a
module it's already in supervisor mode.  This means you can write simple but
slow BASIC programs to access the hardware, rather than having to use
assembler.

Addressing

Now we ought to understand another convention first before diving in further.
As I mentioned in the first article, each time you read from a podule
address, this address is word aligned.  Our podule may have 32 data bits
connected to it but often the device you wish to connect to it is less than
32 bits wide.  Pre-Risc PC machines also only have access to the lower 16 of
these data bits, which requires the tricks outlined above.  This can cause
confusion with exactly what each address refers to.

Each read or write from the podule is performed by the ARM CPU.  The ARM can
only deal with word aligned addresses, and so each podule access is word
aligned.  However, we may only have connected some of the 32 data lines to
our podule - typically 8, 16 or 32 bits.  In this case we still read a word
but the rest of the data bus (and hence the word the ARM gets) may contain
rubbish.  This is shown in figure 1.

So if, as last time, we attach an 8 bit wide ROM to our podule, we get valid
data only in the lowest 8 bits of the 32 bit words at addresses 0, 4, 8 and
so on from the address of the base of the ROM.  If we attach a 32 bit wide
ROM, we get a full 32 bits from each address of 0, 4, 8 and so on.
Similarly an I/O device containing 8 registers may have three address lines
A0-A2 on it.  If we connect these to LA2-LA4, we can access the registers at
0, 4, 8 ... 24, 28 from the base of the device.  So we must multiply the
ROM/register address by four to get the address the ARM should access it by.

Expansion card identities

Now back to the software.  How do we identify our podule to the machine, and
how do we store software on it to load on booting?

This is achieved by the use of an expansion card ID, or ECId to its friends.
There are two main types of ECId, simple and extended.  A simple ECId is a
single byte, read from bits 0-7 of address 0 in IOC synchronous space on the
podule.  Synchronous space (for the moment) can be viewed as slower than slow speed accesses - this will be covered in a later article.  But more or less anything that works in fast mode should be happy in synchronous mode.  This byte is described in table 1.

Bits 1 and 7 are key, and must both be 0.  The podule bus is pulled up by a
resistor chain, so that if there is no hardware at this address both bits are
read as 1, and RISC OS assumes there isn't a podule here.  By setting the
bits to 0, RISC OS will try to interpret the rest of the ECId.

Of the rest of the bits, I'll ignore the interrupt (bit 0) and fast interrupt
(bit 2) status bits for now.  The main part of the simple ECId is the ID
field, bits 3-6.  You can give a podule a 4 bit number, which will then cause
it to appear in *Podules as 'Simple type &x'.

This field allows a very simple means of identifying a podule.  For example,
a driver might use it to determine which podule contains the hardware it
controls, without having to have the user manually tell it which slot the
hardware is in.  A simple ECId can also be implemented using a single buffer,
such as the input port I discussed in the first article - so there's minimal
hardware cost.  Also you can make the *Podules name a bit more friendly under
RISC OS 3, by looking at Resources:$.Resources.Podule.Messages.  The file
contains tokens for the form Simple1:Acorn Econet.  So instead of saying
'Simple type &1', the podule manager will look up the ID field in this file
and print 'Acorn Econet' instead.  By using a module to replace this file,
you can give your podules a nicer name.

Extended ECId

However, there are some major restrictions.  For a start, we can only
distinguish 15 different podule designs - not a great help considering the
number of podules on sale today!  So the use of a simple ECId is restricted
for internal use and podules using it should not be distributed.  The
solution to this is the extended ECId, which is signified by having an ID
field of 0 - the podule manager will then read data from the low bytes of
each of words &04 to &1C on the podule.  This means we assume that we've
connected an 8 bit wide device to the bus - any higher bits are ignored
as in figure 1a.  The contents of the extended ECId are shown in table 2.

The 16 bit manufacturer is an ID you can allocate from RISC OS Ltd in the
usual way, and together with the product type allows you to uniquely identify
a podule design.  The product type is also allocated by RISC OS Ltd, and has
values for common cards such as SCSI, Ethernet and so on.  If you're
designing an unusual podule (radiotelescope interface, let's say), you'll
probably get a fresh allocation.  Lists of these codes can be found at
various places on the web (see below for links).  If you have no chunk
directory, then *Podules will show the product ID in the form 'Extended type
&1234'.  You can add a tag Ext1234 to the Messages file as before to turn
this into a nicer name - however using a chunk directory is strongly
recommended.

If interrupt status has been relocated, this means that 64 bits after the
extended EcID are reserved for interrupt status pointers (so that's the low
bytes of words from &20 to &3C).  I'll ignore these for the moment, so leave
them zero.

Chunk directory

The chunk directory is a further structure after the ECId, which contains
the meat of the podule ROM.  If it is present, interrupt status *must* be
relocated, so the words from &20 to &3C relate to that.  The chunk directory
then starts at &40 (byte 15).  Up till now we've been reading only bytes, and
ignoring the upper bits of each podule word.  Now, if our hardware supports
it, we can switch to using the full width of the podule.  I'm going to assume
that the description that follows relates to data stored in the podule ROM,
the width of which is indicated in the extended ECId (location &04, bits 2-3)
So if our podule ROM is 32 bits wide, a word at address &0 will involve
reading 32 bits from location 0.  If our ROM is 8 bits wide, a 32 bit word will be
made up of reads from four sequential word addresses as shown in figure 2, and
similarly for 16 bit ROMs.

The chunk directory (CD for short) is quite a complex beast, but if you wish
you can safely ignore it.  The PRMs contain documentation, and there's a
program included which will build a chunk directory for you, including adding
any modules to the podule ROM.  However, for the sake of completeness I'll
document the directory here.

The CD is basically a set of pointers to blocks of data in the podule ROM. 
It is laid out so that code and data can be included for multiple operating
systems, and each will be oblivious to the others.

A CD entry is an 8 byte quantity, shown in figure 3.  It specifies the type,
length and start address of the chunk.  If the size in bytes is zero, this is
assumed to be the end of the chunk directory, otherwise another entry follows
this one  The OS identity byte signifies what type of entry this is - the
main types of note being &80 (RISC OS loader), &81 (RISC OS module) and &Fx
(device data).  It is the device data that contains the messages shown by
*Podules.  By combining blocks of device data and modules, we can build a
podule ROM image.

Loaders, the next piece of the jigsaw, complicate matters even further, but
I'll leave this for next time.  In the meantime, the podule specification and
the podule chapter of the RISC OS 3 PRMs have more documentation on the chunk
directory than I can fit in this article, so are worth a read.

I'll leave you with a couple of BASIC programs.  MkChunkDir is based on the
example from the PRMs to build modules into a ROM image with a chunk
directory - this dates from before even Arthur was released but nothing has
changed!  It's been expanded to assemble the various parts of an extended
ECId as well.  ReadPodHdr does the reverse using RISC OS calls to do the work
- run it to decode the chunk directories of the podules in your machine.
These can be found on the monthly disc and at
http://www.markettos.org.uk/riscos/podules/ where there are also links to
product/manufacturer ID lists.

Next time we'll delve into loaders and paging registers - or how to get 1MB
of ROM into 4KB of address space.  This time a quart into a pint pot does go!
