home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.unix.bsd:11916 comp.sys.ibm.pc.hardware:37378
- Newsgroups: comp.unix.bsd,comp.sys.ibm.pc.hardware
- Path: sparky!uunet!ferkel.ucsb.edu!taco!gatech!paladin.american.edu!howland.reston.ans.net!usc!sdd.hp.com!caen!batcomputer!cornell!uw-beaver!cs.ubc.ca!newsserver.sfu.ca!sfu.ca!vanepp
- From: vanepp@fraser.sfu.ca (Peter Van Epp)
- Subject: Re: Programming the 8259 (and a possible 386bsd bug)
- Message-ID: <vanepp.728105387@sfu.ca>
- Sender: news@sfu.ca
- Organization: Simon Fraser University, Burnaby, B.C., Canada
- References: <1993Jan26.170934.5461@zip.eecs.umich.edu>
- Date: Wed, 27 Jan 1993 03:29:47 GMT
- Lines: 118
-
- dmuntz@quip.eecs.umich.edu (Dan Muntz) writes:
-
- >I'd like to know what people have found to be good (accurate/complete) sources
- >of information about programming the 8259 as it is used in 386/486 machines.
-
- The chip data sheet while less than readable, and not necessarily complete
- (nor accurate) at least gives the meaning of all the bits and registers
- and what they in theory do.
-
- >In isa.c in 386bsd the following sequence is used to initialize the "lower"
- >8259:
-
- From the data sheet on the 8259a:
-
- > /* initialize 8259's */
- > outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
-
- Icw1: (address line is 0)
-
- bits d7 - d5 Interrupt vector address (bits 7 - 3, bits 2 - 0 are set to the
- level of the interrupt) (0)
- bit d4 1 (always)
- bit d3 edge trigger mode (0), a 1 would be level trigger mode
- bit d2 call interval of 8 (0), a 1 would be call interval of 4
- but it is ignored in 8086 mode (which this is, see later)
- bit d1 cascade mode (0), a 1 would be single mode (no icw3)
- bit d0 Icw4 needed (1) no Icw4 needed would be 0.
-
- > outb(IO_ICU1+1, NRSVIDT); /* starting at this vector index */
-
- Icw2: (address line is one)
-
- Interrupt vector address (the bits are probably not important).
-
- > outb(IO_ICU1+1, 1<<2); /* slave on line 2 */
-
- Icw3: (address line is one)
-
- bits d7 - d3 0 (always)
-
- bits d2 - d0 binary address of slave id (2 in this case).
-
- > outb(IO_ICU1+1, 1); /* 8086 mode */
-
- Icw4: (address line is 1)
-
- bits d7 - d5 0 (always)
- bit d4 not fully special nested mode (0) 1 is fully special nested mode
- bit d3 - d2 0x non buffered mode
- 10 buffered mode slave
- 11 buffered mode master
- bit d1 normal EOI (0) 1 auto EOI (EOI = End Of Interrupt)
- bit d0 8086 mode (1) 0 8080 mode (my first micro, the CPU chip was $350,
- and 4k of static ram was $500, add wire wrap sockets,
- ttl, an lh0026 MOS clock driver and 8 toggle switches
- and voila heaven!).
-
- This completes the initialization sequence, now for the interrupt masks.
-
- > outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
-
- Ocw1: (address line is 1)
-
- bits d7 - d0 corresponding interrupt is masked (1) or not masked (0)
-
- > outb(IO_ICU1, 2); /* default to ISR on read */
-
- Ocw2: (address line is 0)
-
- bit d7 non rotating priority (0), 1 is rotating priority
- bit d6 no action (0), 1 is specific EOI (selected by bits 2 - 0)
- bit d5 no action (0), 1 is reset highest active interrupt
- bits d4 - d3 0 (always)
- bit d2 - d0 interrupt level to reset (level 2 in this case, but probably
- don't care?).
-
- I expect that you are correct, the comment is wrong. When something needs
- doing, Ocw3 will get written to do whatever wants to be done (and then
- indeed, writing 3 not 2 will get you the ISR register).
-
- It is now sitting waiting for an OCW3 command whose format is
-
- Ocw3: (address line is 0)
-
- bit d7 don't care
- bit d6 - d5 00 no action
- 01 no action
- 10 read special mask
- 11 set special mask
- bit d4 0 (always)
- bit d3 1 (always)
- bit d2 0 no action, 1 read code of highest int on next read.
- bits d1 - d0 00 no action
- 01 no action
- 10 read IR reg on next read pulse (IR = Interrupt Request reg)
- (bit map of incoming interrupts, not masked)
- 11 read IS reg on next rd pulse (IS = In Service reg)
- (shows the priority of the levels being serviced).
-
- A quick grep for IO_ICU finds hits in icu.h, a look at that finds a bunch of
- inline assembler in macros, at least some of which deals with doing EOIs to
- interrupt controllers. I expect that you will find the missing Ocw3 hidden
- away in there somewhere.
-
- >According to the meager amount of information I've found, the last line
- >should be outb(IO_ICU1, 3); to select ISR on read (or the comment should
- >say IRR instead of ISR). From other points in the code, it appears that
- >ISR is expected. If this line is wrong, the other 8259 is also being
- >initialized incorrectly. Can anyone shed some light on this?
-
- Hopefully the above helps some, if you need more info just ask and I'll
- see what else I can dig up (or maybe someone more knowledgable will comment),
- I seem to remember some comments on $%$#$%^ interrupt controllers in one
- of the early DDJ articles on BSD386 as well, so that may be another source
- of info (straight from the horse's mouth as it were!).
-
- Peter Van Epp / Operations and Technical Support
- Simon Fraser University, Burnaby, B.C. Canada
-