Return to BSD News archive
Received: by minnie.vk1xwt.ampr.org with NNTP id AA91 ; Thu, 28 Jan 93 08:00:30 EST Xref: sserve comp.unix.bsd:10476 comp.sys.ibm.pc.hardware:42427 Newsgroups: comp.unix.bsd,comp.sys.ibm.pc.hardware Path: sserve!manuel.anu.edu.au!munnari.oz.au!sgiblab!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