IRQs and such (was Re: Serial interfaces)
bqt at update.uu.se
Fri Jul 30 18:49:48 CDT 2010
Charlie Carothers <csquared3 at tx.rr.com> wrote:
> Johnny Billquist wrote:
>> > Older cards usually use DIP-switches, while modern cards usually are
>> > programmed.
(And as others mentioned, it could also be jumpers, which works the same
way as dip-switches, but might take some soldering to reconnect... :-) )
>> > 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.
> I'm guessing/assuming a "word" is 16-bits, so a vector is 32-bits in
> all. (Snipped from my original question is my admission that I know
> absolutely nothing about DEC gear.)
Yes. A word is 16 bits on a PDP-11. The device presents a 16-bit vector
on the bus when the interrupt is acknowledged by the CPU.
This 16-bit vector from the device is then used to read the interrupt
vector table in memory, where each entry consist of two 16-bit words.
One is the new PC to be used, and the other is the new PSW.
So, when a device fields an interrupt, and it get's processed, the
current PC and PSW (processor status word, which holds condition codes,
current interrupt level, and some other stuff) gets pushed on the stack,
and a new PC and PSW is loaded, and the processor continues from there.
Already running in the interrupt handler from instruction one.
The reverse is the RETI or RETN instructions, which pops a PC and PSW
from the stack and puts them in the processor registers again.
>> > 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.
> I'm guessing again that you stimulate the card in some fashion, the card
> generates an interrupt, and you check to see which interrupt was
> received. I suppose if the card has no such facility you just have to
> know from a configuration file or something.
Correct. You set up a "fake" PC/PSW pair for all vectors, with some
variation, which makes it possible to see in that interrupt handler
exactly which vector that we got the interrupt through, and then we can
change that vector to point to the correct interrupt handler.
And we get the card to generate the interrupt so that we can do the
whole detection thing.
>> > All that is required is that no two devices use the same vector, because
>> > that would be bad.
> I imagine that would be *very* bad. :-(
Indeed. I guess that in theory you could have an interrupt handler that
then tried to figure out which device was generating the interrupt, but
that kindof defeats the whole idea of having each device present a
>>> >> 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.
> That does indeed seem like a very bad idea.
That would limit us to only having one controller of that type, ever, on
that bus. Not a limitation some would be happy with.
>> > 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.
> I assume that is 8K bytes, so only 4K CSRs. But maybe they are not all
> words, I dunno. For all I know, some are 32 bits...
No, that is correct. Since the PDP-11 access things as 8 or 16 bits, you
could in theory have 8K registers. But registers are normally 16 bits,
or atleast addressed on even addresses, which limits it to 4K registers.
No registers are actually 32 bits, although most devices have more than
one register, and some controllers actually combine registers to manage
quantities larger than 16 bits (such as physical addresses, which can be
18 bits, or 22 bits, depending on system and controller).
>> > 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.
> Hmmm. I get about 6KB decimal in all. I can see where you could run
> out if you have many cards. Just thinking about a typical UART has 8
> each and ISTR a floppy controller has about that many too.
About 6KB is left after the "reserved" addresses are accounted for, yes.
But no, the typical serial interface on a PDP-11 uses two registers for
transmit, and two registers for receive, although they are 16 bits. One
for data, and one for control.
And actually, when we talk about serial ports, we should remember that
usually you had cards that controlled maybe 8 or 16 ports, using just
maybe eight registers. The floppy controllers depend, but for the 8"
floppy, which is the most primitive (thus using the most registers),
it's still only like six registers or so. The modern floppy controllers
use only two registers.
>> > 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
> That's a lot of info. I think I'll save a copy in my DEC subfolder for
> later reference.
Feel free to ask if there is anything more you wonder about... :-)
More information about the cctalk