Ethan Dicks <ethan.dicks at gmail.com> wrote:
On 7/27/10, Charlie Carothers <csquared3 at
tx.rr.com> wrote:
> Tony Duell wrote:
> >> All decent buses allow you to share interrupts -- the ''design'
of the
> >> interrupt suystem on the ISA bus is one reason to hate that bus..
> >>
> >> Very well designed buses (Unibus :-)) have each card send an interrupt
> >> vector which directs the CPU to the right ISR.
>
> ... I'm just curious as to how each card knows what interrupt
> vector value to send? Jumpers/switches on each card?
Can be done that way...
> A "Unibus Interrupt Vector Value
Guru" somewhere who assigns the values?
In a sense, yes....
All the way back to 1970, DEC published lists in various system
handbooks about their own breakdown of assigned CSRs (Control Status
Register - typically the first I/O address that the card responds do,
though there's no way to magically know how many addresses a card will
answer at) an interrupt vectors for disk controllers, comms
controllers, etc. For older devices, DEC would reserve up to four
locations for a given interface, allowing for primary through
quaternary cards to be installed on the same bus. Later, there was
typically a primary address given, then a scheme to calculate a
non-conflicting "floating" address, but by then folks were rarely
installing four of anything except perhaps serial interfaces or MSCP
disk interfaces.
You drift from the question, Ethan... :-)
To answer the original question, it was done in one of two ways.
Either you set a bunch of DIP-switches to the value that should be sent
as the interrupt vector, or else you programmed the card with the
interrupt vector it should send.
Older cards usually use DIP-switches, while modern cards usually are
programmed.
Remember that you don't need the interrupt vector to talk with the card
in polled mode, so you can talk with the card, and set up stuff before
you allow it to start generating interrupts...
What you drift into, Ethan, is then the question of deciding what
interrupt vector to actually set on the card. This is also an
interesting topic.
Very few devices have more than one reserved vector. That is, if we talk
of one vector as assigned to one card. Some cards had more than one
vector because of the nature of the card, such as a terminal interface
which actually use two vectors. One vector for receiving characters, and
one vector for transmitting characters. I can only remember one device
where more than one set of vectors were reserved, and I think it ran to
eight for that one. I'd have to look in a processor book to check the
actual name of that device, though.
For all other devices, vectors are allocated from the "floating" vector
space, which is everything from 300(8) to 774(8).
Each vector takes two words, the the lowest two bits of a vector is
always 0, and are usually not even available on the switch pack, or
register where you program the vector.
For a device like a terminal interface, the next bit was also reserved,
since it was used to differentiate between transmit and receive, so two
vectors were programmed with one switch pack.
There was/is a definitive schema for in which order vectors should be
assigned, but it is more or less not used since all the OSes that
atleast I have tried actually probe what vector each card uses, and use
that vector instead of having some fixed scheme.
All that is required is that no two devices use the same vector, because
that would be bad.
I can give an example of how this worked in practice
by describing a
3rd-party device I used to make and maintain, the COMBOARD. It wasn't
on DEC's list, so we picked an arbitrary CSR up in "unassigned" space.
We gave our customers a list of eight preferred CSR addresses to use,
though any address in the I/O page would work. The user set the CSR
address on a 10-position DIP switch, then, once the machine was
powered on and running, would load the driver and tell it, via setup
files, what CSR the card(s) will respond at. Our product had a 16-bit
double-one-way register we called "the window". If the PDP-11/VAX
wrote a value, the 68000 on the card could read it, and if the 68000
wrote a value, the PDP-11/VAX could read it (a processor could never
read back the value that it just wrote). One of the values passed
during initialization was the vector to use (as stated in a config
file that was written by the user, or by us as a factory default).
The board would retain that value and drop it on the bus during an
interrupt request.
So for our product, the CSR was set by switches that were not meant to
be changed, but the interrupt vector could be changed at every reboot.
Real DEC devices did a number of different things, the older ones
typically relying on jumpers or switches, the newer devices relying on
some mechanism to assign or calculate the values dynamically.
Well, there are really only two ways. Either dip switches, or
programmed. :-)
In practice, there weren't as many kinds of
interfaces for the Unibus
as there ended up being for the ISA bus, so it may sound like anarchy,
but it wasn't. I think in 20-ish years of the hey-day of the Unibus,
they only ever reassigned CSR addresses once or twice, but it was
extremely unlikely that you'd have a particular obscure peripheral
from 1970, literally, on the same bus as a stack of c. 1990 disk
controllers and Ethernet interfaces. Electrically, they would work
together, but logically, a user would have no need to use 20-year-old
devices. The only "old" device we ever used on our VAX-11/750 was an
LP11, an original line-printer interface. The rest of the cards in
our machine were manufactured 10-15 years later. Some of our devices,
then, had a DIP switch for CSR assignment, but not for vector
assignment. Something older, like a PDP-11/34, was probably a
different story.
No, it's just the same for any PDP-11, just as for VAXen with Unibuses.
You *must* use dip-switches for CSRs, or possibly accept that it is at a
fixed address, which is a very bad idea.
Vectors are either set with DIP switches, or programmed into the card at
initialization time.
But vectors are the simple part of the Unibus. The fact that it's easy
to autodetect the vector makes it even simpler. All you need to make
sure is that you don't have a conflict, and your vector issues are done.
The interesting part of the Unibus is actually the CSRs. As the I/O
address page is only 8K, and some devices use quite a few registers in
that area, this is a short resource, so you cannot in general make a
permanent allocation in the I/O page for all possible combination of
devices you might have.
So DEC designed a scheme for automatically detecting and configuring
devices on the Unibus. (Plug and play long before the PC saw the light
of day.) This do, however, require you to change the CSR address of
devices way more often than you might think.
The general idea runs like this. For most of the common devices, *one*
CSR address is reserved. So, for the first device, you know which
address to set it to. Any additional devices of that type goes into the
floating address space.
Each device additionally have a priority, size and modulo number. This
is all on paper. For autoconfiguration to work, you then start with the
highest priority device, and starts assigning CSRs to the devices you
actually have of that type. When you are done, you go on to the next
device, and repeat the exercise. Repeat until you've run through the
whole list of device types, and by then you will have the CSR address of
all the devices you have in your machine.
Now, if you add one additional device of some type, it will probably
affect the CSR address of all devices you have which have a lower
priority, moving them in the floating address space. The same is true if
you remove some device from the machine, which were located in the
floating address space.
More specifically the algorithm goes like this.
(In pseudo-code, all numbers octal)
CSR=160010
DEV_PRIO=1
while (! end_of_devices_you_have)
CSR = round_up(CSR, device_modulo(DEV_PRIO))
for (number_of_devices(DEV_PRIO)) do
this_device_csr = CSR
CSR = round_up(CSR+device_size(DEV_PRIO), device_modulo(DEV_PRIO))
next
CSR += 2
next
Worth pointing out:
Floating address space starts at 160010, and goes up. Preallocated CSR
addresses are usually very high up in this space, and were allocated
downwards. They "end" up somewhere around 174xxx space or so. I'm sure
someone could locate the lowest pre-allocated CSR address that DEC
assigned by looking in some processor book.
Between each device type, one CSR address is reserved. This means that
when you scan for devices, you'll run through one type at a time, and
stop when you hit an address where there is nothing responding. You then
go on to the next type.
It's important to understand that the space after this non-existant
address do not need to be the same size as that of the actual devices
for that prio. That would be wasteful of address space. Once you hit the
non-existant address, you start scanning for the next device type, using
the modulo of that device type instead. So if you have one device type
which uses 20 registers, and you don't have any of that type, you'll
only waste one register, plus the modulo of the next device type.
Once all the CSRs have been figured out, the DEC official scheme for
vector allocation was basically to just allocate all vectors, starting
at 300, for all the devices you have, packed together as closely as
possible. No need for unused spaces, or anything else here.
But this is all about the scheme for actually deciding what to use. The
actual method of getting the card to know this info was switchpacks, or
for vectors, programming a register.
Johnny