From 7612e4c12217566df9b94eb7b40226f33a40e0c0 Mon Sep 17 00:00:00 2001 From: "Matthew N. Dodd" Date: Fri, 3 Sep 1999 02:04:28 +0000 Subject: [PATCH] This adds the i386 specific support for systems with a MicroChannel Architecture bus. Reviewed by: msmith --- sys/amd64/amd64/legacy.c | 9 ++ sys/amd64/amd64/nexus.c | 9 ++ sys/amd64/amd64/tsc.c | 10 +++ sys/amd64/isa/clock.c | 10 +++ sys/amd64/isa/intr_machdep.c | 25 +++++- sys/amd64/isa/nmi.c | 25 +++++- sys/conf/files.i386 | 1 + sys/i386/bios/mca_machdep.c | 161 +++++++++++++++++++++++++++++++++++ sys/i386/bios/mca_machdep.h | 31 +++++++ sys/i386/conf/files.i386 | 1 + sys/i386/i386/legacy.c | 9 ++ sys/i386/i386/nexus.c | 9 ++ sys/i386/i386/tsc.c | 10 +++ sys/i386/isa/clock.c | 10 +++ sys/i386/isa/intr_machdep.c | 25 +++++- sys/i386/isa/mca_machdep.c | 161 +++++++++++++++++++++++++++++++++++ sys/i386/isa/mca_machdep.h | 31 +++++++ sys/i386/isa/nmi.c | 25 +++++- sys/isa/atrtc.c | 10 +++ 19 files changed, 564 insertions(+), 8 deletions(-) create mode 100644 sys/i386/bios/mca_machdep.c create mode 100644 sys/i386/bios/mca_machdep.h create mode 100644 sys/i386/isa/mca_machdep.c create mode 100644 sys/i386/isa/mca_machdep.h diff --git a/sys/amd64/amd64/legacy.c b/sys/amd64/amd64/legacy.c index 22e98eda7106..23e6fdc69606 100644 --- a/sys/amd64/amd64/legacy.c +++ b/sys/amd64/amd64/legacy.c @@ -41,6 +41,7 @@ */ #include "opt_smp.h" +#include "mca.h" #include #include @@ -209,6 +210,14 @@ nexus_attach(device_t dev) panic("nexus_attach eisa"); device_probe_and_attach(child); } +#if NMCA > 0 + if (!devclass_get_device(devclass_find("mca"), 0)) { + child = device_add_child(dev, "mca", 0, 0); + if (child == 0) + panic("nexus_probe mca"); + device_probe_and_attach(child); + } +#endif if (!devclass_get_device(devclass_find("isa"), 0)) { child = device_add_child(dev, "isa", 0, 0); if (child == NULL) diff --git a/sys/amd64/amd64/nexus.c b/sys/amd64/amd64/nexus.c index 22e98eda7106..23e6fdc69606 100644 --- a/sys/amd64/amd64/nexus.c +++ b/sys/amd64/amd64/nexus.c @@ -41,6 +41,7 @@ */ #include "opt_smp.h" +#include "mca.h" #include #include @@ -209,6 +210,14 @@ nexus_attach(device_t dev) panic("nexus_attach eisa"); device_probe_and_attach(child); } +#if NMCA > 0 + if (!devclass_get_device(devclass_find("mca"), 0)) { + child = device_add_child(dev, "mca", 0, 0); + if (child == 0) + panic("nexus_probe mca"); + device_probe_and_attach(child); + } +#endif if (!devclass_get_device(devclass_find("isa"), 0)) { child = device_add_child(dev, "isa", 0, 0); if (child == NULL) diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c index 8a3e1c93030c..c65974141b01 100644 --- a/sys/amd64/amd64/tsc.c +++ b/sys/amd64/amd64/tsc.c @@ -85,6 +85,11 @@ #include +#include "mca.h" +#if NMCA > 0 +#include +#endif + #ifdef SMP #define disable_intr() CLOCK_DISABLE_INTR() #define enable_intr() CLOCK_ENABLE_INTR() @@ -258,6 +263,11 @@ clkintr(struct clockframe frame) } break; } +#if NMCA > 0 + /* Reset clock interrupt by asserting bit 7 of port 0x61 */ + if (MCA_system) + outb(0x61, inb(0x61) | 0x80); +#endif } /* diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c index 8a3e1c93030c..c65974141b01 100644 --- a/sys/amd64/isa/clock.c +++ b/sys/amd64/isa/clock.c @@ -85,6 +85,11 @@ #include +#include "mca.h" +#if NMCA > 0 +#include +#endif + #ifdef SMP #define disable_intr() CLOCK_DISABLE_INTR() #define enable_intr() CLOCK_ENABLE_INTR() @@ -258,6 +263,11 @@ clkintr(struct clockframe frame) } break; } +#if NMCA > 0 + /* Reset clock interrupt by asserting bit 7 of port 0x61 */ + if (MCA_system) + outb(0x61, inb(0x61) | 0x80); +#endif } /* diff --git a/sys/amd64/isa/intr_machdep.c b/sys/amd64/isa/intr_machdep.c index 8bdb4b6d72d4..a429ef48fa85 100644 --- a/sys/amd64/isa/intr_machdep.c +++ b/sys/amd64/isa/intr_machdep.c @@ -79,6 +79,11 @@ #include #endif +#include "mca.h" +#if NMCA > 0 +#include +#endif + /* XXX should be in suitable include files */ #ifdef PC98 #define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ @@ -169,6 +174,11 @@ isa_nmi(cd) int isa_port = inb(0x61); int eisa_port = inb(0x461); +#if NMCA > 0 + if (MCA_system && mca_bus_nmi()) + return; +#endif + if (isa_port & NMI_PARITY) panic("RAM parity error, likely hardware failure."); @@ -211,7 +221,12 @@ isa_defaultirq() icu_unset(i, (inthand2_t *)NULL); /* initialize 8259's */ - outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ +#if NMCA > 0 + if (MCA_system) + outb(IO_ICU1, 0x19); /* reset; program device, four bytes */ + else +#endif + outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ outb(IO_ICU1+ICU_IMR_OFFSET, NRSVIDT); /* starting at this vector index */ outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE); /* slave on line 7 */ @@ -234,7 +249,13 @@ isa_defaultirq() outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ #endif /* !PC98 */ - outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ +#if NMCA > 0 + if (MCA_system) + outb(IO_ICU2, 0x19); /* reset; program device, four bytes */ + else +#endif + outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ + outb(IO_ICU2+ICU_IMR_OFFSET, NRSVIDT+8); /* staring at this vector index */ outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 7 */ #ifdef PC98 diff --git a/sys/amd64/isa/nmi.c b/sys/amd64/isa/nmi.c index 8bdb4b6d72d4..a429ef48fa85 100644 --- a/sys/amd64/isa/nmi.c +++ b/sys/amd64/isa/nmi.c @@ -79,6 +79,11 @@ #include #endif +#include "mca.h" +#if NMCA > 0 +#include +#endif + /* XXX should be in suitable include files */ #ifdef PC98 #define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ @@ -169,6 +174,11 @@ isa_nmi(cd) int isa_port = inb(0x61); int eisa_port = inb(0x461); +#if NMCA > 0 + if (MCA_system && mca_bus_nmi()) + return; +#endif + if (isa_port & NMI_PARITY) panic("RAM parity error, likely hardware failure."); @@ -211,7 +221,12 @@ isa_defaultirq() icu_unset(i, (inthand2_t *)NULL); /* initialize 8259's */ - outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ +#if NMCA > 0 + if (MCA_system) + outb(IO_ICU1, 0x19); /* reset; program device, four bytes */ + else +#endif + outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ outb(IO_ICU1+ICU_IMR_OFFSET, NRSVIDT); /* starting at this vector index */ outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE); /* slave on line 7 */ @@ -234,7 +249,13 @@ isa_defaultirq() outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ #endif /* !PC98 */ - outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ +#if NMCA > 0 + if (MCA_system) + outb(IO_ICU2, 0x19); /* reset; program device, four bytes */ + else +#endif + outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ + outb(IO_ICU2+ICU_IMR_OFFSET, NRSVIDT+8); /* staring at this vector index */ outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 7 */ #ifdef PC98 diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 1ec918cdb623..3ad56a1af979 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -220,6 +220,7 @@ i386/isa/joy.c optional joy i386/isa/labpc.c optional labpc i386/isa/loran.c optional loran i386/isa/matcd/matcd.c optional matcd +i386/isa/mca_machdep.c optional mca i386/isa/mcd.c optional mcd i386/isa/mse.c optional mse i386/isa/npx.c mandatory npx diff --git a/sys/i386/bios/mca_machdep.c b/sys/i386/bios/mca_machdep.c new file mode 100644 index 000000000000..8eaf682a32bf --- /dev/null +++ b/sys/i386/bios/mca_machdep.c @@ -0,0 +1,161 @@ +/*- + * Copyright (c) 1999 Matthew N. Dodd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "mca.h" +#if NMCA > 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Global MCA bus flag */ +int MCA_system = 0; + +/* System Configuration Block */ +struct sys_config { + u_int16_t count; + u_int8_t model; + u_int8_t submodel; + u_int8_t bios_rev; + u_int8_t feature; +#define FEATURE_RESV 0x01 /* Reserved */ +#define FEATURE_MCABUS 0x02 /* MicroChannel Architecture */ +#define FEATURE_EBDA 0x04 /* Extended BIOS data area allocated */ +#define FEATURE_WAITEV 0x08 /* Wait for external event is supported */ +#define FEATURE_KBDINT 0x10 /* Keyboard intercept called by Int 09h */ +#define FEATURE_RTC 0x20 /* Real-time clock present */ +#define FEATURE_IC2 0x40 /* Second interrupt chip present */ +#define FEATURE_DMA3 0x80 /* DMA channel 3 used by hard disk BIOS */ + u_int8_t pad[3]; +} __attribute__ ((packed)); + +/* Function Prototypes */ +static void bios_mcabus_present (void *); +SYSINIT(mca_present, SI_SUB_CPU, SI_ORDER_ANY, bios_mcabus_present, NULL); + +/* Functions */ +static void +bios_mcabus_present(void * dummy) +{ + struct vm86frame vmf; + struct sys_config * scp; + vm_offset_t paddr; + + bzero(&vmf, sizeof(struct vm86frame)); + + vmf.vmf_ah = 0xc0; + if (vm86_intcall(0x15, &vmf)) { + if (bootverbose) { + printf("BIOS SDT: INT call failed.\n"); + } + return (0); + } + + if ((vmf.vmf_ah != 0) && (vmf.vmf_flags != 0)) { + if (bootverbose) { + printf("BIOS SDT: Not supported. Not PS/2?\n"); + printf("BIOS SDT: AH 0x%02x, Flags 0x%04x\n", + vmf.vmf_ah, vmf.vmf_flags); + } + return (0); + } + + paddr = vmf.vmf_es; + paddr = (paddr << 4) + vmf.vmf_bx; + scp = (struct sys_config *)BIOS_PADDRTOVADDR(paddr); + + if (bootverbose) { + printf("BIOS SDT: model 0x%02x, submodel 0x%02x, bios_rev 0x%02x\n", + scp->model, scp->submodel, scp->bios_rev); + printf("BIOS SDT: features 0x%b\n", scp->feature, + "\20" + "\01RESV" + "\02MCABUS" + "\03EBDA" + "\04WAITEV" + "\05KBDINT" + "\06RTC" + "\07IC2" + "\08DMA3\n"); + } + + MCA_system = ((scp->feature & FEATURE_MCABUS) ? 1 : 0); + + if (MCA_system) + printf("MicroChannel Architecture System detected.\n"); + + return; +} + +int +mca_bus_nmi (void) +{ + int slot; + int retval = 0; + int pos5 = 0; + + /* Disable motherboard setup */ + outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS); + + /* For each slot */ + for (slot = 0; slot < MCA_MAX_SLOTS; slot++) { + + /* Select the slot */ + outb(MCA_ADAP_SETUP_REG, slot | MCA_ADAP_SET); + pos5 = inb(MCA_POS_REG(MCA_POS5)); + + /* If Adapter Check is low */ + if ((pos5 & MCA_POS5_CHCK) == 0) { + retval++; + + /* If Adapter Check Status is available */ + if ((pos5 & MCA_POS5_CHCK_STAT) == 0) { + printf("MCA NMI: slot %d, POS6=0x%02x, POS7=0x%02x\n", + slot+1, + inb( MCA_POS_REG(MCA_POS6) ), + inb( MCA_POS_REG(MCA_POS7) )); + } else { + printf("MCA NMI: slot %d\n", slot+1); + } + } + /* Disable adapter setup */ + outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS); + } + + return (retval); +} +#endif diff --git a/sys/i386/bios/mca_machdep.h b/sys/i386/bios/mca_machdep.h new file mode 100644 index 000000000000..c639b5b74044 --- /dev/null +++ b/sys/i386/bios/mca_machdep.h @@ -0,0 +1,31 @@ +/*- + * Copyright (c) 1999 Matthew N. Dodd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +extern int MCA_system; + +extern int mca_bus_nmi (void); diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386 index 1ec918cdb623..3ad56a1af979 100644 --- a/sys/i386/conf/files.i386 +++ b/sys/i386/conf/files.i386 @@ -220,6 +220,7 @@ i386/isa/joy.c optional joy i386/isa/labpc.c optional labpc i386/isa/loran.c optional loran i386/isa/matcd/matcd.c optional matcd +i386/isa/mca_machdep.c optional mca i386/isa/mcd.c optional mcd i386/isa/mse.c optional mse i386/isa/npx.c mandatory npx diff --git a/sys/i386/i386/legacy.c b/sys/i386/i386/legacy.c index 22e98eda7106..23e6fdc69606 100644 --- a/sys/i386/i386/legacy.c +++ b/sys/i386/i386/legacy.c @@ -41,6 +41,7 @@ */ #include "opt_smp.h" +#include "mca.h" #include #include @@ -209,6 +210,14 @@ nexus_attach(device_t dev) panic("nexus_attach eisa"); device_probe_and_attach(child); } +#if NMCA > 0 + if (!devclass_get_device(devclass_find("mca"), 0)) { + child = device_add_child(dev, "mca", 0, 0); + if (child == 0) + panic("nexus_probe mca"); + device_probe_and_attach(child); + } +#endif if (!devclass_get_device(devclass_find("isa"), 0)) { child = device_add_child(dev, "isa", 0, 0); if (child == NULL) diff --git a/sys/i386/i386/nexus.c b/sys/i386/i386/nexus.c index 22e98eda7106..23e6fdc69606 100644 --- a/sys/i386/i386/nexus.c +++ b/sys/i386/i386/nexus.c @@ -41,6 +41,7 @@ */ #include "opt_smp.h" +#include "mca.h" #include #include @@ -209,6 +210,14 @@ nexus_attach(device_t dev) panic("nexus_attach eisa"); device_probe_and_attach(child); } +#if NMCA > 0 + if (!devclass_get_device(devclass_find("mca"), 0)) { + child = device_add_child(dev, "mca", 0, 0); + if (child == 0) + panic("nexus_probe mca"); + device_probe_and_attach(child); + } +#endif if (!devclass_get_device(devclass_find("isa"), 0)) { child = device_add_child(dev, "isa", 0, 0); if (child == NULL) diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c index 8a3e1c93030c..c65974141b01 100644 --- a/sys/i386/i386/tsc.c +++ b/sys/i386/i386/tsc.c @@ -85,6 +85,11 @@ #include +#include "mca.h" +#if NMCA > 0 +#include +#endif + #ifdef SMP #define disable_intr() CLOCK_DISABLE_INTR() #define enable_intr() CLOCK_ENABLE_INTR() @@ -258,6 +263,11 @@ clkintr(struct clockframe frame) } break; } +#if NMCA > 0 + /* Reset clock interrupt by asserting bit 7 of port 0x61 */ + if (MCA_system) + outb(0x61, inb(0x61) | 0x80); +#endif } /* diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index 8a3e1c93030c..c65974141b01 100644 --- a/sys/i386/isa/clock.c +++ b/sys/i386/isa/clock.c @@ -85,6 +85,11 @@ #include +#include "mca.h" +#if NMCA > 0 +#include +#endif + #ifdef SMP #define disable_intr() CLOCK_DISABLE_INTR() #define enable_intr() CLOCK_ENABLE_INTR() @@ -258,6 +263,11 @@ clkintr(struct clockframe frame) } break; } +#if NMCA > 0 + /* Reset clock interrupt by asserting bit 7 of port 0x61 */ + if (MCA_system) + outb(0x61, inb(0x61) | 0x80); +#endif } /* diff --git a/sys/i386/isa/intr_machdep.c b/sys/i386/isa/intr_machdep.c index 8bdb4b6d72d4..a429ef48fa85 100644 --- a/sys/i386/isa/intr_machdep.c +++ b/sys/i386/isa/intr_machdep.c @@ -79,6 +79,11 @@ #include #endif +#include "mca.h" +#if NMCA > 0 +#include +#endif + /* XXX should be in suitable include files */ #ifdef PC98 #define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ @@ -169,6 +174,11 @@ isa_nmi(cd) int isa_port = inb(0x61); int eisa_port = inb(0x461); +#if NMCA > 0 + if (MCA_system && mca_bus_nmi()) + return; +#endif + if (isa_port & NMI_PARITY) panic("RAM parity error, likely hardware failure."); @@ -211,7 +221,12 @@ isa_defaultirq() icu_unset(i, (inthand2_t *)NULL); /* initialize 8259's */ - outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ +#if NMCA > 0 + if (MCA_system) + outb(IO_ICU1, 0x19); /* reset; program device, four bytes */ + else +#endif + outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ outb(IO_ICU1+ICU_IMR_OFFSET, NRSVIDT); /* starting at this vector index */ outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE); /* slave on line 7 */ @@ -234,7 +249,13 @@ isa_defaultirq() outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ #endif /* !PC98 */ - outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ +#if NMCA > 0 + if (MCA_system) + outb(IO_ICU2, 0x19); /* reset; program device, four bytes */ + else +#endif + outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ + outb(IO_ICU2+ICU_IMR_OFFSET, NRSVIDT+8); /* staring at this vector index */ outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 7 */ #ifdef PC98 diff --git a/sys/i386/isa/mca_machdep.c b/sys/i386/isa/mca_machdep.c new file mode 100644 index 000000000000..8eaf682a32bf --- /dev/null +++ b/sys/i386/isa/mca_machdep.c @@ -0,0 +1,161 @@ +/*- + * Copyright (c) 1999 Matthew N. Dodd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "mca.h" +#if NMCA > 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Global MCA bus flag */ +int MCA_system = 0; + +/* System Configuration Block */ +struct sys_config { + u_int16_t count; + u_int8_t model; + u_int8_t submodel; + u_int8_t bios_rev; + u_int8_t feature; +#define FEATURE_RESV 0x01 /* Reserved */ +#define FEATURE_MCABUS 0x02 /* MicroChannel Architecture */ +#define FEATURE_EBDA 0x04 /* Extended BIOS data area allocated */ +#define FEATURE_WAITEV 0x08 /* Wait for external event is supported */ +#define FEATURE_KBDINT 0x10 /* Keyboard intercept called by Int 09h */ +#define FEATURE_RTC 0x20 /* Real-time clock present */ +#define FEATURE_IC2 0x40 /* Second interrupt chip present */ +#define FEATURE_DMA3 0x80 /* DMA channel 3 used by hard disk BIOS */ + u_int8_t pad[3]; +} __attribute__ ((packed)); + +/* Function Prototypes */ +static void bios_mcabus_present (void *); +SYSINIT(mca_present, SI_SUB_CPU, SI_ORDER_ANY, bios_mcabus_present, NULL); + +/* Functions */ +static void +bios_mcabus_present(void * dummy) +{ + struct vm86frame vmf; + struct sys_config * scp; + vm_offset_t paddr; + + bzero(&vmf, sizeof(struct vm86frame)); + + vmf.vmf_ah = 0xc0; + if (vm86_intcall(0x15, &vmf)) { + if (bootverbose) { + printf("BIOS SDT: INT call failed.\n"); + } + return (0); + } + + if ((vmf.vmf_ah != 0) && (vmf.vmf_flags != 0)) { + if (bootverbose) { + printf("BIOS SDT: Not supported. Not PS/2?\n"); + printf("BIOS SDT: AH 0x%02x, Flags 0x%04x\n", + vmf.vmf_ah, vmf.vmf_flags); + } + return (0); + } + + paddr = vmf.vmf_es; + paddr = (paddr << 4) + vmf.vmf_bx; + scp = (struct sys_config *)BIOS_PADDRTOVADDR(paddr); + + if (bootverbose) { + printf("BIOS SDT: model 0x%02x, submodel 0x%02x, bios_rev 0x%02x\n", + scp->model, scp->submodel, scp->bios_rev); + printf("BIOS SDT: features 0x%b\n", scp->feature, + "\20" + "\01RESV" + "\02MCABUS" + "\03EBDA" + "\04WAITEV" + "\05KBDINT" + "\06RTC" + "\07IC2" + "\08DMA3\n"); + } + + MCA_system = ((scp->feature & FEATURE_MCABUS) ? 1 : 0); + + if (MCA_system) + printf("MicroChannel Architecture System detected.\n"); + + return; +} + +int +mca_bus_nmi (void) +{ + int slot; + int retval = 0; + int pos5 = 0; + + /* Disable motherboard setup */ + outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS); + + /* For each slot */ + for (slot = 0; slot < MCA_MAX_SLOTS; slot++) { + + /* Select the slot */ + outb(MCA_ADAP_SETUP_REG, slot | MCA_ADAP_SET); + pos5 = inb(MCA_POS_REG(MCA_POS5)); + + /* If Adapter Check is low */ + if ((pos5 & MCA_POS5_CHCK) == 0) { + retval++; + + /* If Adapter Check Status is available */ + if ((pos5 & MCA_POS5_CHCK_STAT) == 0) { + printf("MCA NMI: slot %d, POS6=0x%02x, POS7=0x%02x\n", + slot+1, + inb( MCA_POS_REG(MCA_POS6) ), + inb( MCA_POS_REG(MCA_POS7) )); + } else { + printf("MCA NMI: slot %d\n", slot+1); + } + } + /* Disable adapter setup */ + outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS); + } + + return (retval); +} +#endif diff --git a/sys/i386/isa/mca_machdep.h b/sys/i386/isa/mca_machdep.h new file mode 100644 index 000000000000..c639b5b74044 --- /dev/null +++ b/sys/i386/isa/mca_machdep.h @@ -0,0 +1,31 @@ +/*- + * Copyright (c) 1999 Matthew N. Dodd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +extern int MCA_system; + +extern int mca_bus_nmi (void); diff --git a/sys/i386/isa/nmi.c b/sys/i386/isa/nmi.c index 8bdb4b6d72d4..a429ef48fa85 100644 --- a/sys/i386/isa/nmi.c +++ b/sys/i386/isa/nmi.c @@ -79,6 +79,11 @@ #include #endif +#include "mca.h" +#if NMCA > 0 +#include +#endif + /* XXX should be in suitable include files */ #ifdef PC98 #define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ @@ -169,6 +174,11 @@ isa_nmi(cd) int isa_port = inb(0x61); int eisa_port = inb(0x461); +#if NMCA > 0 + if (MCA_system && mca_bus_nmi()) + return; +#endif + if (isa_port & NMI_PARITY) panic("RAM parity error, likely hardware failure."); @@ -211,7 +221,12 @@ isa_defaultirq() icu_unset(i, (inthand2_t *)NULL); /* initialize 8259's */ - outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ +#if NMCA > 0 + if (MCA_system) + outb(IO_ICU1, 0x19); /* reset; program device, four bytes */ + else +#endif + outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ outb(IO_ICU1+ICU_IMR_OFFSET, NRSVIDT); /* starting at this vector index */ outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE); /* slave on line 7 */ @@ -234,7 +249,13 @@ isa_defaultirq() outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ #endif /* !PC98 */ - outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ +#if NMCA > 0 + if (MCA_system) + outb(IO_ICU2, 0x19); /* reset; program device, four bytes */ + else +#endif + outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ + outb(IO_ICU2+ICU_IMR_OFFSET, NRSVIDT+8); /* staring at this vector index */ outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 7 */ #ifdef PC98 diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c index 8a3e1c93030c..c65974141b01 100644 --- a/sys/isa/atrtc.c +++ b/sys/isa/atrtc.c @@ -85,6 +85,11 @@ #include +#include "mca.h" +#if NMCA > 0 +#include +#endif + #ifdef SMP #define disable_intr() CLOCK_DISABLE_INTR() #define enable_intr() CLOCK_ENABLE_INTR() @@ -258,6 +263,11 @@ clkintr(struct clockframe frame) } break; } +#if NMCA > 0 + /* Reset clock interrupt by asserting bit 7 of port 0x61 */ + if (MCA_system) + outb(0x61, inb(0x61) | 0x80); +#endif } /*