summaryrefslogtreecommitdiff
path: root/i386/pc/pic.c
diff options
context:
space:
mode:
authorThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
committerThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
commitf07a4c844da9f0ecae5bbee1ab94be56505f26f7 (patch)
tree12b07c7e578fc1a5f53dbfde2632408491ff2a70 /i386/pc/pic.c
Initial source
Diffstat (limited to 'i386/pc/pic.c')
-rw-r--r--i386/pc/pic.c283
1 files changed, 283 insertions, 0 deletions
diff --git a/i386/pc/pic.c b/i386/pc/pic.c
new file mode 100644
index 0000000..eaf7b56
--- /dev/null
+++ b/i386/pc/pic.c
@@ -0,0 +1,283 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+Copyright (c) 1988,1989 Prime Computer, Inc. Natick, MA 01760
+All Rights Reserved.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and
+without fee is hereby granted, provided that the above
+copyright notice appears in all copies and that both the
+copyright notice and this permission notice appear in
+supporting documentation, and that the name of Prime
+Computer, Inc. not be used in advertising or publicity
+pertaining to distribution of the software without
+specific, written prior permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS", AND PRIME COMPUTER,
+INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
+NO EVENT SHALL PRIME COMPUTER, INC. BE LIABLE FOR ANY
+SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+PROFITS, WHETHER IN ACTION OF CONTRACT, NEGLIGENCE, OR
+OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <mach/machine/pio.h>
+
+#include <sys/types.h>
+
+#include "ipl.h"
+#include "pic.h"
+
+
+u_short pic_mask[SPLHI+1];
+
+int curr_ipl;
+u_short curr_pic_mask;
+
+u_short orig_pic_mask;
+int orig_pic_mask_initialized;
+
+u_char intpri[NINTR];
+
+/*
+** picinit() - This routine
+** * Establishes a table of interrupt vectors
+** * Establishes a table of interrupt priority levels
+** * Establishes a table of interrupt masks to be put
+** in the PICs.
+** * Establishes location of PICs in the system
+** * Initialises them
+**
+** At this stage the interrupt functionality of this system should be
+** coplete.
+**
+*/
+
+
+/*
+** 1. First we form a table of PIC masks - rather then calling form_pic_mask()
+** each time there is a change of interrupt level - we will form a table
+** of pic masks, as there are only 7 interrupt priority levels.
+**
+** 2. The next thing we must do is to determine which of the PIC interrupt
+** request lines have to be masked out, this is done by calling
+** form_pic_mask() with a (int_lev) of zero, this will find all the
+** interrupt lines that have priority 0, (ie to be ignored).
+** Then we split this up for the master/slave PICs.
+**
+** 2. Initialise the PICs , master first, then the slave.
+** All the register field definitions are described in pic_jh.h, also
+** the settings of these fields for the various registers are selected.
+**
+*/
+
+pic_init(int master_base, int slave_base)
+{
+ u_short PICM_OCW1, PICS_OCW1 ;
+ u_short PICM_OCW2, PICS_OCW2 ;
+ u_short PICM_OCW3, PICS_OCW3 ;
+ u_short i;
+
+ if (!orig_pic_mask_initialized)
+ {
+ unsigned omaster, oslave;
+
+ omaster = inb(MASTER_OCW);
+ PIC_DELAY();
+ oslave = inb(SLAVES_OCW);
+ PIC_DELAY();
+
+ orig_pic_mask = omaster | (oslave << 8);
+ orig_pic_mask_initialized = 1;
+ }
+
+
+ /*
+ ** 1. Form pic mask table
+ */
+
+ form_pic_mask();
+
+ /*
+ ** 1a. Select current SPL.
+ */
+
+ curr_ipl = SPLHI;
+ curr_pic_mask = pic_mask[SPLHI];
+
+ /*
+ ** 3. Select options for each ICW and each OCW for each PIC.
+ */
+
+#if 0
+ PICM_ICW1 = (ICW_TEMPLATE | EDGE_TRIGGER | ADDR_INTRVL8
+ | CASCADE_MODE | ICW4__NEEDED);
+
+ PICS_ICW1 = (ICW_TEMPLATE | EDGE_TRIGGER | ADDR_INTRVL8
+ | CASCADE_MODE | ICW4__NEEDED);
+
+ PICM_ICW2 = master_base;
+ PICS_ICW2 = slave_base;
+
+ PICM_ICW3 = ( SLAVE_ON_IR2 );
+ PICS_ICW3 = ( I_AM_SLAVE_2 );
+
+ PICM_ICW4 = (SNF_MODE_DIS | NONBUFD_MODE | NRML_EOI_MOD
+ | I8086_EMM_MOD);
+ PICS_ICW4 = (SNF_MODE_DIS | NONBUFD_MODE | NRML_EOI_MOD
+ | I8086_EMM_MOD);
+#endif
+
+ PICM_OCW1 = (curr_pic_mask & 0x00FF);
+ PICS_OCW1 = ((curr_pic_mask & 0xFF00)>>8);
+
+ PICM_OCW2 = NON_SPEC_EOI;
+ PICS_OCW2 = NON_SPEC_EOI;
+
+ PICM_OCW3 = (OCW_TEMPLATE | READ_NEXT_RD | READ_IR_ONRD );
+ PICS_OCW3 = (OCW_TEMPLATE | READ_NEXT_RD | READ_IR_ONRD );
+
+
+ /*
+ ** 4. Initialise master - send commands to master PIC
+ */
+
+ outb ( MASTER_ICW, PICM_ICW1 );
+ PIC_DELAY();
+ outb ( MASTER_OCW, master_base );
+ PIC_DELAY();
+ outb ( MASTER_OCW, PICM_ICW3 );
+ PIC_DELAY();
+ outb ( MASTER_OCW, PICM_ICW4 );
+ PIC_DELAY();
+
+#if 0
+ outb ( MASTER_OCW, PICM_MASK );
+ PIC_DELAY();
+ outb ( MASTER_ICW, PICM_OCW3 );
+ PIC_DELAY();
+#endif
+
+ /*
+ ** 5. Initialise slave - send commands to slave PIC
+ */
+
+ outb ( SLAVES_ICW, PICS_ICW1 );
+ PIC_DELAY();
+ outb ( SLAVES_OCW, slave_base );
+ PIC_DELAY();
+ outb ( SLAVES_OCW, PICS_ICW3 );
+ PIC_DELAY();
+ outb ( SLAVES_OCW, PICS_ICW4 );
+ PIC_DELAY();
+
+#if 0
+ outb ( SLAVES_OCW, PICS_OCW1 );
+ PIC_DELAY();
+ outb ( SLAVES_ICW, PICS_OCW3 );
+ PIC_DELAY();
+
+ /*
+ ** 6. Initialise interrupts
+ */
+ outb ( MASTER_OCW, PICM_OCW1 );
+ PIC_DELAY();
+#endif
+
+ outb(MASTER_OCW, orig_pic_mask);
+ PIC_DELAY();
+ outb(SLAVES_OCW, orig_pic_mask >> 8);
+ PIC_DELAY();
+
+#if 0
+ /* XXX */
+ if (master_base != 8)
+ {
+ outb(0x21, 0xff);
+ PIC_DELAY();
+ outb(0xa1, 0xff);
+ PIC_DELAY();
+ }
+#endif
+
+ outb(MASTER_ICW, NON_SPEC_EOI);
+ PIC_DELAY();
+ outb(SLAVES_ICW, NON_SPEC_EOI);
+ PIC_DELAY();
+
+ inb(0x60);
+
+}
+
+/*
+** form_pic_mask(int_lvl)
+**
+** For a given interrupt priority level (int_lvl), this routine goes out
+** and scans through the interrupt level table, and forms a mask based on the
+** entries it finds there that have the same or lower interrupt priority level
+** as (int_lvl). It returns a 16-bit mask which will have to be split up between
+** the 2 pics.
+**
+*/
+
+#define SLAVEMASK (0xFFFF ^ SLAVE_ON_IR2)
+#define SLAVEACTV 0xFF00
+
+form_pic_mask()
+{
+ unsigned short i, j, bit, mask;
+
+ for (i=SPL0; i <= SPLHI; i++) {
+ for (j=0x00, bit=0x01, mask = 0; j < NINTR; j++, bit<<=1)
+ if (intpri[j] <= i)
+ mask |= bit;
+
+ if ((mask & SLAVEACTV) != SLAVEACTV )
+ mask &= SLAVEMASK;
+
+ pic_mask[i] = mask;
+ }
+}
+
+#if 0
+
+intnull(unit_dev)
+{
+ printf("intnull(%d)\n", unit_dev);
+}
+
+int prtnull_count = 0;
+prtnull(unit)
+{
+ ++prtnull_count;
+}
+
+#endif 0