Page 1 of 1

Programming the PIC

Posted: Thu Apr 12, 2007 8:32 am
by madeofstaples
Hello everyone

I've just been reading about operating system development for the past week or so out of interest. I haven't started anything (yet), if I do I'd like to have a very clear plan before I start.

I just got caught up on programming the PIC. In particular I'm looking at two articles:

http://www.osdever.net/bkerndev/Docs/irqs.htm and
http://www.osdever.net/tutorials/pic.php

The first article says:
Remember that the slave controller is connected to the primary controller through IRQ2: This means that every time an IRQ from 8 to 15 occurs, IRQ2 fires at exactly the same time.
And the second article says:
ICW3 is used for telling the PICs which IRQ to use for the communication between each other
My question at this point: Does this mean that I can decide some IRQ other than IRQ2 is triggered by the slave controller? I guess this is trivial, but it leads me to my next question:

Both articles handle ICW3 exactly the same - they send the data 4 to the master PIC, and 2 to the slave PIC. This leads me to believe that this is how things must be done, no?

(I added space around the first code segment's ICW3 since it wasn't commented.)
From Article 1:

Code: Select all

void irq_remap(void)
{
    outportb(0x20, 0x11);
    outportb(0xA0, 0x11);
    outportb(0x21, 0x20);
    outportb(0xA1, 0x28);


    outportb(0x21, 0x04);
    outportb(0xA1, 0x02);


    outportb(0x21, 0x01);
    outportb(0xA1, 0x01);
    outportb(0x21, 0x0);
    outportb(0xA1, 0x0);
}
From Article 2

Code: Select all

void init_pics(int pic1, int pic2)
{
	/* send ICW1 */
	outb(PIC1, ICW1);
	outb(PIC2, ICW1);

	/* send ICW2 */
	outb(PIC1 + 1, pic1);	/* remap */
	outb(PIC2 + 1, pic2);	/*  pics */

	/* send ICW3 */
	outb(PIC1 + 1, 4);	/* IRQ2 -> connection to slave */
	outb(PIC2 + 1, 2);

	/* send ICW4 */
	outb(PIC1 + 1, ICW4);
	outb(PIC2 + 1, ICW4);

	/* disable all IRQs */
	outb(PIC1 + 1, 0xFF);
}
But now I'm confused, I get that the 2 in the second of the two ICW3 lines (outb(PIC2 + 1, 2)) probably sets the slave controller to trigger IRQ2, but what does the 4 do in the first of the two lines???

Thanks for your help!

Posted: Thu Apr 12, 2007 8:37 am
by ~
I have always assumed that it must be a PIC command to prepare it to "connect to slave", corresponding to the named ICW3 (Integrated Circuit Word No. N?) thing.

The only way to find out is to get the PIC specifications and find it out.

Re: Programming the PIC

Posted: Thu Apr 12, 2007 9:25 am
by Brendan
Hi,
madeofstaples wrote:My question at this point: Does this mean that I can decide some IRQ other than IRQ2 is triggered by the slave controller? I guess this is trivial, but it leads me to my next question:

Both articles handle ICW3 exactly the same - they send the data 4 to the master PIC, and 2 to the slave PIC. This leads me to believe that this is how things must be done, no?
Short Answer

Both articles program ICW3 exactly the same because ICW3 must be programmed according to how the PIC chip is/was hardwired to other things. The slave PIC is/was hardwired to "Input 2" of the master PIC for historical reasons, and will never be wired differently on any 80x86 compatible computer with an 80286 or later CPU.


Long Answer

The original PIC chip was designed as a generic chip for use in a variety of computers (and was used in systems that were made before "80x86 PC's" existed). Being a generic chip meant that it needed to handle a variety of requirements. For example, you could use one of them for up to 8 inputs or have a set of 9 chips (one master and 8 slaves) for 256 inputs, and it handles at least 2 different CPU bus protocols.

Before the PIC chip can work you need to tell it how it's been used - which inputs are IRQs, which inputs are connected to slave PIC chips, which CPU bus protocol to use, etc. All of this information depends on how it's hard-wired to everything else (including other PIC chips).

For the earliest 80x86 PCs there was only one PIC chip with 8 inputs, and IRQs where prioritized - IRQ0 was considered more important than IRQ1, and IRQ7 was the lowest priority IRQ.

Eventually as more hardware was created IBM needed more PIC inputs. Luckily the PIC chip they used was a generic/flexible chip and they could add slaves. Unfortunately the interrupt priorities depends on how the slave is connected to the master PIC. To avoid making a mess of the existing interrupt priority scheme they chose to use input 2, so that the interrupt priorities became (in order) IRQ0, IRQ1, IRQ8, IRQ9, IRQ10, IRQ11, IRQ12, IRQ13, IRQ14, IRQ15, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7. This meant that a device using a low priority interrupt (like the floppy disk controller) still had a low priority interrupt, and a device that was using a high priority interrupt (e.g. the PIT timer) still had a high priority interrupt.

This left a compatability problem with the old IRQ2, which was used by the CMOS/RTC interrupt and couldn't be used anymore because it was being used to connect the slave PIC. To fix this the CMOS/RTC became IRQ8 (same priority as it was) and the BIOS was changed so that the interrupt handler for IRQ8 jumped to an interrupt handler for IRQ2. The end result was that old software that hooked IRQ2 would still work without changes (even though the CMOS/RTC was actually connected to IRQ8).

In modern computers the PIC chips retain the majority of these features/problems despite becoming integrated into larger scale chips that aren't generic. This is mostly for backward compatability - software from 20 years ago that configured the original PIC chips still works on modern chipsets. Unfortunately the reverse is also true - new software needs to pretend there's 20 year old generic PIC chips and configure them accordingly, even though the PIC in modern chipsets can't be wired differently.


Cheers,

Brendan

Posted: Thu Apr 12, 2007 9:25 am
by madeofstaples
~ wrote:I have always assumed that it must be a PIC command to prepare it to "connect to slave", corresponding to the named ICW3 thing.

The only way to find out is to get the PIC specifications and find it out.
I found some specifications:
http://www.arl.wustl.edu/Publications/1 ... rl9801.pdf
(page 18 )
For everyone's reference: it doesn't matter, the bits are hardwired.

But if it did: the 2nd bit sent to the master PIC turns on or off Cascade Mode so that the slave PIC does forward through one of the master PIC's IRQ's, and the two least significant bits of the command sent to the slave PIC (would) do as you expect, and say which IRQ to forward to.

Now my question: why do things this way? why not turn off cascade mode and not have to worry about things like:
Remember that the slave controller is connected to the primary controller through IRQ2: This means that every time an IRQ from 8 to 15 occurs, IRQ2 fires at exactly the same time.
Or does turning off Cascade Mode disable the slave PIC all together?

Ugh, I just remembered: you can't actually turn it off, it's hardwired.

Well, whatever, this is for your reference then :)

/edit:
Brendan wrote:...
Thank you, makes much more sense now that things are this way.