From 8fedbd8497309b36e8c4dc57d6287b80f767cdd0 Mon Sep 17 00:00:00 2001 From: jdolecek Date: Thu, 11 May 2000 16:38:10 +0000 Subject: [PATCH] Add i386-specific part of MicroChannel Architecture bus support, as found in some older IBM PS/2 machines. This code is based upon work by Scott D. Telford, with some minor bits in arch/i386/mca/mca_machdep.c taken from FreeBSD. XXX this is still very experimental and development version; use at your XXX own risk --- sys/arch/i386/conf/PS2 | 91 +++++++++ sys/arch/i386/conf/files.i386 | 11 +- sys/arch/i386/i386/machdep.c | 14 +- sys/arch/i386/i386/mainbus.c | 23 ++- sys/arch/i386/i386/trap.c | 29 ++- sys/arch/i386/include/mca_machdep.h | 83 +++++++++ sys/arch/i386/isa/clock.c | 14 +- sys/arch/i386/isa/isa_machdep.c | 63 ++++++- sys/arch/i386/mca/mca_machdep.c | 275 ++++++++++++++++++++++++++++ 9 files changed, 581 insertions(+), 22 deletions(-) create mode 100644 sys/arch/i386/conf/PS2 create mode 100644 sys/arch/i386/include/mca_machdep.h create mode 100644 sys/arch/i386/mca/mca_machdep.c diff --git a/sys/arch/i386/conf/PS2 b/sys/arch/i386/conf/PS2 new file mode 100644 index 000000000000..2ee0290eb73b --- /dev/null +++ b/sys/arch/i386/conf/PS2 @@ -0,0 +1,91 @@ +# $NetBSD: PS2,v 1.1 2000/05/11 16:38:10 jdolecek Exp $ +# +# Sample kernel config for PS/2 with MCA bus +# +# BEWARE: do NOT use MCA-enabled kernel on non-MCA machine + +include "arch/i386/conf/std.i386" + +maxusers 32 # estimated number of users + +options I386_CPU +options I486_CPU + +options MATH_EMULATE # floating point emulation +#options XSERVER # X server support in console drivers + +#options UCONSOLE # users can use TIOCCONS (for xconsole) +options INSECURE # disable kernel security levels + +options RTC_OFFSET=-600 # hardware clock is this many mins. west of GMT +options KTRACE # system call tracing via ktrace(1) + +options SYSVMSG # System V-like message queues +options SYSVSEM # System V-like semaphores +options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=1024 # 1024 pages is the default + +options DIAGNOSTIC # cheap kernel consistency checks +options DEBUG # expensive debugging checks/support +options KMEMSTATS # kernel memory statistics (vmstat -m) +options DDB # in-kernel debugger + +file-system FFS # UFS +#file-system NFS # Network File System client +file-system MSDOSFS # MS-DOS file system +#file-system FDESC # /dev/fd +#file-system KERNFS # /kern + +#options QUOTA # UFS quotas +#options NFSSERVER # Network File System server +options FIFO # FIFOs; RECOMMENDED + +options INET # IP + ICMP + TCP + UDP + +options COMPAT_AOUT +options COMPAT_13 +options COMPAT_14 + +options MCAVERBOSE # verbose MCA device autoconfig messages + +#options NFS_BOOT_BOOTP + +options WSEMUL_VT100 # VT100 / VT220 emulation +options WS_KERNEL_FG=WSCOL_GREEN + +config netbsd root on ? type ? +#config netbsd root on ? type nfs + +# +# Device Configuration +# + +mainbus0 at root +mca0 at mainbus0 +isa0 at mainbus0 + +npx0 at isa? port 0xf0 irq 13 # x86 math coprocessor + +#pc0 at isa? port 0x60 irq 1 + +# wscons +pckbc0 at isa? # pc keyboard controller +#pcconskbd* at pckbc? +pms* at pckbc? # PS/2 mouse for wsmouse +wsmouse* at pms? +pckbd* at pckbc? # PC keyboard +wskbd* at pckbd? console ? +vga0 at isa? +wsdisplay* at vga? console ? +options WSDISPLAY_DEFAULTSCREENS=4 + +com0 at isa? port 0x3f8 irq 4 # "SERIAL_!" +lpt0 at isa? port 0x3bc irq 7 # "PARALLEL_1" +fdc0 at isa? port 0x3f0 irq 6 drq 2 # standard PC floppy controllers +fd* at fdc? drive ? # the drives themselves +tr* at mca? slot ? # IBM Token Ring adapter +#ef* at mca? slot ? # 3Com 3C523 (not yet) + +pseudo-device bpfilter 4 # Berkeley packet filter +pseudo-device loop # network loopback +pseudo-device pty 16 # pseudo-terminals diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386 index f4d8b95846a7..5a091486731a 100644 --- a/sys/arch/i386/conf/files.i386 +++ b/sys/arch/i386/conf/files.i386 @@ -1,4 +1,4 @@ -# $NetBSD: files.i386,v 1.158 2000/04/28 17:23:51 uch Exp $ +# $NetBSD: files.i386,v 1.159 2000/05/11 16:38:10 jdolecek Exp $ # # new style config file for i386 architecture # @@ -108,8 +108,7 @@ file arch/i386/i386/bios32.c bios32 needs-flag define mainbus { } # XXX BIOS32 only if something that uses it is configured! -# device mainbus: isabus, eisabus, mcabus, pcibus, mainbus, bios32 -device mainbus: isabus, eisabus, pcibus, mainbus, bios32 +device mainbus: isabus, eisabus, mcabus, pcibus, mainbus, bios32 attach mainbus at root file arch/i386/i386/mainbus.c mainbus @@ -260,9 +259,9 @@ file arch/i386/eisa/eisa_machdep.c eisa # MCA-only drivers # -# device mca {[slot = -1]} : bioscall -# include "dev/mca/files.mca" -# file arch/i386/mca/mca_machdep.c mca +device mca {[slot = -1]} : bioscall +include "dev/mca/files.mca" +file arch/i386/mca/mca_machdep.c mca # ISA Plug 'n Play devices file arch/i386/isa/isapnp_machdep.c isapnp diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 2432e6eb4a86..cd1ec5e15916 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.383 2000/05/03 20:17:37 mycroft Exp $ */ +/* $NetBSD: machdep.c,v 1.384 2000/05/11 16:38:11 jdolecek Exp $ */ /*- * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. @@ -162,6 +162,11 @@ extern struct proc *npxproc; #endif +#include "mca.h" +#if NMCA > 0 +#include /* for mca_busprobe() */ +#endif + /* the following is used externally (sysctl_hw) */ char machine[] = "i386"; /* cpu "architecture" */ char machine_arch[] = "i386"; /* machine == machine_arch */ @@ -1687,6 +1692,13 @@ init386(first_avail) } #endif +#if NMCA > 0 + /* check for MCA bus, needed to be done before ISA stuff - if + * MCA is detected, ISA needs to use level triggered interrupts + * by default */ + mca_busprobe(); +#endif + #if NISA > 0 isa_defaultirq(); #endif diff --git a/sys/arch/i386/i386/mainbus.c b/sys/arch/i386/i386/mainbus.c index 35b1041a0b30..93d14cf2ded7 100644 --- a/sys/arch/i386/i386/mainbus.c +++ b/sys/arch/i386/i386/mainbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: mainbus.c,v 1.30 2000/03/22 20:58:27 ws Exp $ */ +/* $NetBSD: mainbus.c,v 1.31 2000/05/11 16:38:11 jdolecek Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. @@ -45,6 +45,7 @@ #include "pci.h" #include "eisa.h" #include "isa.h" +#include "mca.h" #include "apm.h" #include "pnpbios.h" @@ -57,6 +58,10 @@ #include #endif +#if NMCA > 0 +#include +#endif + int mainbus_match __P((struct device *, struct cfdata *, void *)); void mainbus_attach __P((struct device *, struct device *, void *)); @@ -71,6 +76,9 @@ union mainbus_attach_args { struct pcibus_attach_args mba_pba; struct eisabus_attach_args mba_eba; struct isabus_attach_args mba_iba; +#if NMCA > 0 + struct mcabus_attach_args mba_mba; +#endif #if NAPM > 0 struct apm_attach_args mba_aaa; #endif @@ -151,6 +159,19 @@ mainbus_attach(parent, self, aux) } #endif +#if NMCA > 0 + /* note MCA bus probe is done in i386/machdep.c */ + if (MCA_system) { + mba.mba_mba.mba_busname = "mca"; + mba.mba_mba.mba_iot = I386_BUS_SPACE_IO; + mba.mba_mba.mba_memt = I386_BUS_SPACE_MEM; + mba.mba_mba.mba_dmat = &mca_bus_dma_tag; + mba.mba_mba.mba_mc = NULL; + mba.mba_mba.mba_bus = 0; + config_found(self, &mba.mba_mba, mainbus_print); + } +#endif + if (memcmp(ISA_HOLE_VADDR(EISA_ID_PADDR), EISA_ID, EISA_ID_LEN) == 0 && eisa_has_been_seen == 0) { mba.mba_eba.eba_busname = "eisa"; diff --git a/sys/arch/i386/i386/trap.c b/sys/arch/i386/i386/trap.c index 8cd67b45f6b1..f1723683a64d 100644 --- a/sys/arch/i386/i386/trap.c +++ b/sys/arch/i386/i386/trap.c @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.134 1999/12/04 21:20:32 ragge Exp $ */ +/* $NetBSD: trap.c,v 1.135 2000/05/11 16:38:12 jdolecek Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -114,6 +114,13 @@ #include #endif +#include "mca.h" +#if NMCA > 0 +#include +#endif + +#include "isa.h" + #ifdef KGDB #include #endif @@ -530,8 +537,7 @@ trap(frame) trapsignal(p, SIGTRAP, type &~ T_USER); break; -#include "isa.h" -#if NISA > 0 +#if NISA > 0 || NMCA > 0 case T_NMI: #if defined(KGDB) || defined(DDB) /* NMI can be hooked up to a pushbutton for debugging */ @@ -547,11 +553,20 @@ trap(frame) #endif #endif /* KGDB || DDB */ /* machine/parity/power fail/"kitchen sink" faults */ - if (isa_nmi() == 0) - return; - else + +#if NMCA > 0 + /* mca_nmi() takes care to call isa_nmi() if appropriate */ + if (mca_nmi() != 0) goto we_re_toast; -#endif + else + return; +#else /* NISA > 0 */ + if (isa_nmi() != 0) + goto we_re_toast; + else + return; +#endif /* NMCA > 0 */ +#endif /* NISA > 0 || NMCA > 0 */ } if ((type & T_USER) == 0) diff --git a/sys/arch/i386/include/mca_machdep.h b/sys/arch/i386/include/mca_machdep.h new file mode 100644 index 000000000000..9d9f06ca959a --- /dev/null +++ b/sys/arch/i386/include/mca_machdep.h @@ -0,0 +1,83 @@ +/* $NetBSD: mca_machdep.h,v 1.1 2000/05/11 16:38:13 jdolecek Exp $ */ + +/* + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * Copyright (c) 1999 Scott D. Telford. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. + */ + +#ifndef _I386_MCA_MACHDEP_H_ +#define _I386_MCA_MACHDEP_H_ + +/* + * i386-specific definitions for MCA autoconfiguration. + */ + +extern struct i386_bus_dma_tag mca_bus_dma_tag; + +/* set to 1 if MCA bus is detected */ +extern int MCA_system; + +int mca_nmi __P((void)); + +/* + * Types provided to machine-independent MCA code. + */ +struct i386_mca_chipset { + void * /*struct mca_dma_state*/ ic_dmastate; +}; + +typedef struct i386_mca_chipse *mca_chipset_tag_t; +typedef int mca_intr_handle_t; + +/* + * Functions provided to machine-independent MCA code. + */ +struct mcabus_attach_args; + +void mca_attach_hook __P((struct device *, struct device *, + struct mcabus_attach_args *)); +void *mca_intr_establish __P((mca_chipset_tag_t, mca_intr_handle_t, + int, int (*)(void *), void *)); +void mca_intr_disestablish __P((mca_chipset_tag_t, void *)); +int mca_conf_read __P((mca_chipset_tag_t, int, int)); +void mca_conf_write __P((mca_chipset_tag_t, int, int, int)); +void mca_busprobe __P((void)); + +/* MCA register addresses for IBM PS/2 */ + +#define PS2_SYS_CTL_A 0x92 /* PS/2 System Control Port A */ +#define MCA_MB_SETUP_REG 0x94 /* Motherboard setup register */ +#define MCA_ADAP_SETUP_REG 0x96 /* Adapter setup register */ +#define MCA_POS_REG_BASE 0x100 /* POS registers base address */ +#define MCA_POS_REG_SIZE 8 /* POS registers window size */ + +#define MCA_POS_REG(n) (0x100+(n)) /* POS registers 0-7 */ + +/* Adapter setup register bits */ + +#define MCA_ADAP_SET 0x08 /* Adapter setup mode */ +#define MCA_ADAP_CHR 0x80 /* Adapter channel reset */ + +#endif /* _I386_MCA_MACHDEP_H_ */ diff --git a/sys/arch/i386/isa/clock.c b/sys/arch/i386/isa/clock.c index 963ecfe3e705..3d317c853ada 100644 --- a/sys/arch/i386/isa/clock.c +++ b/sys/arch/i386/isa/clock.c @@ -1,4 +1,4 @@ -/* $NetBSD: clock.c,v 1.64 2000/05/03 21:32:59 mycroft Exp $ */ +/* $NetBSD: clock.c,v 1.65 2000/05/11 16:38:13 jdolecek Exp $ */ /*- * Copyright (c) 1993, 1994 Charles M. Hannum. @@ -113,6 +113,11 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #if (NPCPPI > 0) #include +#include "mca.h" +#if NMCA > 0 +#include /* for MCA_system */ +#endif + #ifdef CLOCKDEBUG int clock_debug = 0; #define DPRINTF(arg) if (clock_debug) printf arg @@ -402,6 +407,13 @@ clockintr(arg) struct clockframe *frame = arg; /* not strictly necessary */ hardclock(frame); + +#if NMCA > 0 + if (MCA_system) { + /* Reset PS/2 clock interrupt by asserting bit 7 of port 0x61 */ + outb(0x61, inb(0x61) | 0x80); + } +#endif return -1; } diff --git a/sys/arch/i386/isa/isa_machdep.c b/sys/arch/i386/isa/isa_machdep.c index ec6c6ebf78a1..6a759508f5a7 100644 --- a/sys/arch/i386/isa/isa_machdep.c +++ b/sys/arch/i386/isa/isa_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: isa_machdep.c,v 1.45 1999/11/12 18:39:38 drochner Exp $ */ +/* $NetBSD: isa_machdep.c,v 1.46 2000/05/11 16:38:13 jdolecek Exp $ */ #define ISA_DMA_STATS @@ -98,6 +98,11 @@ #include +#include "mca.h" +#if NMCA > 0 +#include /* for MCA_system */ +#endif + /* * ISA can only DMA to 0-16M. */ @@ -110,7 +115,11 @@ typedef void (vector) __P((void)); extern vector *IDTVEC(intr)[]; void isa_strayintr __P((int)); void intr_calculatemasks __P((void)); -int fakeintr __P((void *)); +static int fakeintr __P((void *)); +#if NMCA > 0 +static int mca_clockfakeintr __P((void *)); +#endif + int _isa_bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int, bus_size_t, bus_size_t, int, bus_dmamap_t *)); @@ -171,7 +180,14 @@ isa_defaultirq() SDT_SYS386IGT, SEL_KPL); /* initialize 8259's */ - outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ +#if NMCA > 0 + /* level-triggered interrupts on MCA PS/2s */ + 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+1, ICU_OFFSET); /* starting at this vector index */ outb(IO_ICU1+1, 1 << IRQ_SLAVE); /* slave on line 2 */ #ifdef AUTO_EOI_1 @@ -186,7 +202,14 @@ isa_defaultirq() outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ #endif - outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ +#if NMCA > 0 + /* level-triggered interrupts on MCA PS/2s */ + 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+1, ICU_OFFSET+8); /* staring at this vector index */ outb(IO_ICU2+1, IRQ_SLAVE); #ifdef AUTO_EOI_2 @@ -206,7 +229,6 @@ isa_defaultirq() int isa_nmi() { - log(LOG_CRIT, "NMI port 61 %x, port 70 %x\n", inb(0x61), inb(0x70)); return(0); } @@ -335,7 +357,7 @@ intr_calculatemasks() } } -int +static int fakeintr(arg) void *arg; { @@ -434,6 +456,15 @@ isa_intr_establish(ic, irq, type, level, ih_fun, ih_arg) struct intrhand **p, *q, *ih; static struct intrhand fakehand = {fakeintr}; +#if NMCA > 0 + /* + * Need special fake handler for PS/2 MCA clock interrupt + */ + + if (MCA_system && irq == 0) + fakehand.ih_fun = &mca_clockfakeintr; +#endif + /* no point in sleeping unless someone can free memory. */ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); if (ih == NULL) @@ -442,6 +473,12 @@ isa_intr_establish(ic, irq, type, level, ih_fun, ih_arg) if (!LEGAL_IRQ(irq) || type == IST_NONE) panic("intr_establish: bogus irq or type"); +#if NMCA > 0 + /* change IST_EDGE to IST_LEVEL if MCA system */ + if (MCA_system && type == IST_EDGE) + type = IST_LEVEL; +#endif + switch (intrtype[irq]) { case IST_NONE: intrtype[irq] = type; @@ -1130,3 +1167,17 @@ _isa_dma_free_bouncebuf(t, map) cookie->id_nbouncesegs = 0; cookie->id_flags &= ~ID_HAS_BOUNCE; } + +#if NMCA > 0 +/* + * Special fake handler for PS/2 MCA clock interrupts + */ +static int +mca_clockfakeintr(arg) + void *arg; +{ + /* Reset clock interrupt by asserting bit 7 of port 0x61 */ + outb(0x61, inb(0x61) | 0x80); + return 0; +} +#endif diff --git a/sys/arch/i386/mca/mca_machdep.c b/sys/arch/i386/mca/mca_machdep.c new file mode 100644 index 000000000000..848e223e1c3b --- /dev/null +++ b/sys/arch/i386/mca/mca_machdep.c @@ -0,0 +1,275 @@ +/* $NetBSD: mca_machdep.c,v 1.1 2000/05/11 16:38:14 jdolecek Exp $ */ + +/* + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * Copyright (c) 1996-1999 Scott D. Telford. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. + */ + +/* + * Machine-specific functions for MCA autoconfiguration. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define _I386_BUS_DMA_PRIVATE +#include + +#include +#include +#include +#include +#include + +#include "isa.h" +#include "opt_mcaverbose.h" + +struct i386_bus_dma_tag mca_bus_dma_tag = { + NULL, /* _cookie */ + _bus_dmamap_create, + _bus_dmamap_destroy, + _bus_dmamap_load, + _bus_dmamap_load_mbuf, + _bus_dmamap_load_uio, + _bus_dmamap_load_raw, + _bus_dmamap_unload, + NULL, /* _dmamap_sync */ + _bus_dmamem_alloc, + _bus_dmamem_free, + _bus_dmamem_map, + _bus_dmamem_unmap, + _bus_dmamem_mmap, +}; + +/* setup by mca_busprobe() */ +int MCA_system = 1; /* XXX force MCA for now */ +int bios_features = 1; + +/* 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)); + +void +mca_attach_hook(parent, self, mba) + struct device *parent, *self; + struct mcabus_attach_args *mba; +{ + /* Nothing */ +} + +/* + * Read value of MCA POS register "reg" in slot "slot". + */ + +int +mca_conf_read(mc, slot, reg) + mca_chipset_tag_t mc; + int slot, reg; +{ + int data; + + slot &= 7; /* slot must be in range 0-7 */ + outb(MCA_MB_SETUP_REG, 0xff); /* ensure m/board setup is disabled */ + outb(MCA_ADAP_SETUP_REG, slot | MCA_ADAP_SET); + data = inb(MCA_POS_REG(reg)); + outb(MCA_ADAP_SETUP_REG, 0); + return data; +} + + +/* + * Write "data" to MCA POS register "reg" in slot "slot". + */ + +void +mca_conf_write(mc, slot, reg, data) + mca_chipset_tag_t mc; + int slot, reg, data; +{ + slot&=7; /* slot must be in range 0-7 */ + outb(MCA_MB_SETUP_REG, 0xff); /* ensure m/board setup is disabled */ + outb(MCA_ADAP_SETUP_REG, slot | MCA_ADAP_SET); + outb(MCA_POS_REG(reg), data); + outb(MCA_ADAP_SETUP_REG, 0); +} + +#if NISA <= 0 +#error mca_intr_(dis)establish: needs ISA to be configured into kernel +#endif + +void * +mca_intr_establish(mc, ih, level, func, arg) + mca_chipset_tag_t mc; + mca_intr_handle_t ih; + int level, (*func) __P((void *)); + void *arg; +{ + if (ih == 0 || ih >= ICU_LEN || ih == 2) + panic("mca_intr_establish: bogus handle 0x%x\n", ih); + + /* MCA interrupts are always level-triggered */ + return isa_intr_establish(NULL, ih, IST_LEVEL, level, func, arg); +} + +void +mca_intr_disestablish(mc, cookie) + mca_chipset_tag_t mc; + void *cookie; +{ + return isa_intr_disestablish(NULL, cookie); +} + + +/* + * Handle a NMI. + * return true to panic system, false to ignore. + */ +int +mca_nmi() +{ + /* + * PS/2 MCA devices can generate NMIs - we can find out which + * slot generated it from the POS registers. + */ + + int slot, mcanmi=0; + + /* if there is no MCA bus, call isa_nmi() */ + if (!MCA_system) + goto out; + + /* ensure motherboard setup is disabled */ + outb(MCA_MB_SETUP_REG, 0xff); + + /* find if an MCA slot has the CHCK bit asserted (low) in POS 5 */ + for(slot=0; slot 0 + if (!mcanmi) { + /* no CHCK bits asserted, assume ISA NMI */ + return (isa_nmi()); + } else +#endif + return(0); +} + +void +mca_busprobe() +{ + /* According to Linux's linux/arch/i386/boot/setup.S, + * we can get the extra BIOS information via int 0x15, + * ah == 0xc0. The extra information is stored on + * es:bx; it contains two bytes of length, then byte + * of machine id, byte of machine submodel, byte of BIOS + * revision number and byte of feature info. + */ + /* + * Scott Telford's code used + * ((inb(MCA_ADAP_SETUP_REG) & (MCA_ADAP_SET | MCA_ADAP_CHR)) == 0) + * - somewhat dubious, but good enough. + */ + +#if notyet + /* + * Following has been taken from FreeBSD, for now just for + * documentation purposes + */ + struct bioscallregs regs; + struct sys_config *scp; + paddr_t paddr; + + memset(®s, 0, sizeof(regs)); + regs.AX_HI = 0xc0; + bioscall(0x15, ®s); + + if ((regs.EFLAGS & PSL_C) + || (regs.AX_HI != 0 && (regs.FLAGS & PSL_AC))) + { +#ifdef MCAVERBOSE + printf("BIOS SDT: Not supported. Not PS/2?\n"); +#endif + return; + } + + paddr = (regs.ES << 4) + regs.BX; + scp = (struct sys_config *)ISA_HOLE_VADDR(paddr); + + printf("BIOS SDT: model 0x%x, submodel 0x%x, BIOS rev. 0x%x\n", + scp->model, scp->submodel, scp->bios_rev); + +#ifdef MCAVERBOSE + printf("BIOS SDT: features 0x%b\n", scp->feature, + "\20" + "\01RESV" + "\02MCABUS" + "\03EBDA" + "\04WAITEV" + "\05KBDINT" + "\06RTC" + "\07IC2" + "\08DMA3\n"); +#endif + + bios_features = scp->feature; + MCA_system = (bios_features & FEATURE_MCABUS) ? 1 : 0; +#endif /* 0 */ +}