150823Smdodd/*-
250823Smdodd * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net>
350823Smdodd * All rights reserved.
450823Smdodd *
550823Smdodd * Redistribution and use in source and binary forms, with or without
650823Smdodd * modification, are permitted provided that the following conditions
750823Smdodd * are met:
850823Smdodd * 1. Redistributions of source code must retain the above copyright
950823Smdodd *    notice, this list of conditions and the following disclaimer.
1050823Smdodd * 2. Redistributions in binary form must reproduce the above copyright
1150823Smdodd *    notice, this list of conditions and the following disclaimer in the
1250823Smdodd *    documentation and/or other materials provided with the distribution.
1350823Smdodd *
1450823Smdodd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1550823Smdodd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1650823Smdodd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1750823Smdodd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1850823Smdodd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1950823Smdodd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2050823Smdodd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2150823Smdodd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2250823Smdodd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2350823Smdodd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2450823Smdodd * SUCH DAMAGE.
2550823Smdodd */
2650823Smdodd
27115679Sobrien#include <sys/cdefs.h>
28115679Sobrien__FBSDID("$FreeBSD$");
29115679Sobrien
3050823Smdodd#include <sys/param.h>
3150823Smdodd#include <sys/systm.h>
3250824Smdodd#include <sys/kernel.h>
3350823Smdodd#include <vm/vm.h>
34130312Sjhb#include <vm/vm_param.h>
3550823Smdodd#include <vm/pmap.h>
3650823Smdodd#include <machine/md_var.h>
3750823Smdodd#include <machine/vm86.h>
3850823Smdodd#include <machine/pc/bios.h>
3950823Smdodd#include <machine/cpufunc.h>
4050823Smdodd
4150823Smdodd#include <dev/mca/mca_busreg.h>
42112551Smdodd#include <i386/bios/mca_machdep.h>
4350823Smdodd
4450823Smdodd/* Global MCA bus flag */
4550823Smdoddint MCA_system = 0;
4650823Smdodd
4750823Smdodd/* System Configuration Block */
4850823Smdoddstruct sys_config {
4950823Smdodd	u_int16_t	count;
5050823Smdodd	u_int8_t	model;
5150823Smdodd	u_int8_t	submodel;
5250823Smdodd	u_int8_t	bios_rev;
5350823Smdodd	u_int8_t	feature;
54134582Smdodd#define FEATURE_MCAISA	0x01	/* Machine contains both MCA and ISA bus*/
5550823Smdodd#define FEATURE_MCABUS	0x02	/* MicroChannel Architecture		*/
5650823Smdodd#define FEATURE_EBDA	0x04	/* Extended BIOS data area allocated	*/
5750823Smdodd#define FEATURE_WAITEV	0x08	/* Wait for external event is supported	*/
5850823Smdodd#define FEATURE_KBDINT	0x10	/* Keyboard intercept called by Int 09h	*/
5950823Smdodd#define FEATURE_RTC	0x20	/* Real-time clock present		*/
6050823Smdodd#define FEATURE_IC2	0x40	/* Second interrupt chip present	*/
6150823Smdodd#define FEATURE_DMA3	0x80	/* DMA channel 3 used by hard disk BIOS	*/
6250823Smdodd	u_int8_t	pad[3];
63103870Salfred} __packed;
6450823Smdodd
6550823Smdodd/* Function Prototypes */
6650823Smdoddstatic void bios_mcabus_present	(void *);
6750823SmdoddSYSINIT(mca_present, SI_SUB_CPU, SI_ORDER_ANY, bios_mcabus_present, NULL);
6850823Smdodd
6950823Smdodd/* Functions */
7050823Smdoddstatic void
7150823Smdoddbios_mcabus_present(void * dummy)
7250823Smdodd{
7350823Smdodd	struct vm86frame	vmf;
7450823Smdodd	struct sys_config *	scp;
7550823Smdodd	vm_offset_t		paddr;
7650823Smdodd
7750823Smdodd	bzero(&vmf, sizeof(struct vm86frame));
7850823Smdodd
7950823Smdodd	vmf.vmf_ah = 0xc0;
8050823Smdodd	if (vm86_intcall(0x15, &vmf)) {
8150823Smdodd		if (bootverbose) {
8250823Smdodd			printf("BIOS SDT: INT call failed.\n");
8350823Smdodd		}
8450824Smdodd		return;
8550823Smdodd	}
8650823Smdodd
8755889Smdodd	if ((vmf.vmf_ah != 0) && (vmf.vmf_flags & 0x01)) {
8850823Smdodd		if (bootverbose) {
8950823Smdodd			printf("BIOS SDT: Not supported.  Not PS/2?\n");
9050823Smdodd			printf("BIOS SDT: AH 0x%02x, Flags 0x%04x\n",
9150823Smdodd				vmf.vmf_ah, vmf.vmf_flags);
9250823Smdodd		}
9350824Smdodd		return;
9450823Smdodd	}
9550823Smdodd
9650823Smdodd	paddr = vmf.vmf_es;
9750823Smdodd	paddr = (paddr << 4) + vmf.vmf_bx;
9850823Smdodd	scp = (struct sys_config *)BIOS_PADDRTOVADDR(paddr);
9950823Smdodd
10050823Smdodd	if (bootverbose) {
10150823Smdodd		printf("BIOS SDT: model 0x%02x, submodel 0x%02x, bios_rev 0x%02x\n",
10250823Smdodd			scp->model, scp->submodel, scp->bios_rev);
10350823Smdodd		printf("BIOS SDT: features 0x%b\n", scp->feature,
10450823Smdodd			"\20"
105134582Smdodd			"\01MCA+ISA"
106134582Smdodd			"\02MCA"
10750823Smdodd			"\03EBDA"
10850823Smdodd			"\04WAITEV"
10950823Smdodd			"\05KBDINT"
11050823Smdodd			"\06RTC"
11150823Smdodd			"\07IC2"
112134582Smdodd			"\08DMA3"
113134582Smdodd			"\n");
11450823Smdodd	}
11550823Smdodd
11650823Smdodd	MCA_system = ((scp->feature & FEATURE_MCABUS) ? 1 : 0);
11750823Smdodd
11850823Smdodd	if (MCA_system)
11950823Smdodd		printf("MicroChannel Architecture System detected.\n");
12050823Smdodd
12150823Smdodd	return;
12250823Smdodd}
12350823Smdodd
12450823Smdoddint
12550823Smdoddmca_bus_nmi (void)
12650823Smdodd{
12750823Smdodd	int	slot;
12850823Smdodd	int	retval = 0;
12950823Smdodd	int	pos5 = 0;
13050823Smdodd
13150823Smdodd	/* Disable motherboard setup */
13250823Smdodd	outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
13350823Smdodd
13450823Smdodd	/* For each slot */
13550823Smdodd	for (slot = 0; slot < MCA_MAX_SLOTS; slot++) {
13650823Smdodd
13750823Smdodd		/* Select the slot */
13850823Smdodd		outb(MCA_ADAP_SETUP_REG, slot | MCA_ADAP_SET);
13950823Smdodd		pos5 = inb(MCA_POS_REG(MCA_POS5));
14050823Smdodd
14150823Smdodd		/* If Adapter Check is low */
14250823Smdodd		if ((pos5 & MCA_POS5_CHCK) == 0) {
14350823Smdodd			retval++;
14450823Smdodd
14550823Smdodd			/* If Adapter Check Status is available */
14650823Smdodd			if ((pos5 & MCA_POS5_CHCK_STAT) == 0) {
14750823Smdodd				printf("MCA NMI: slot %d, POS6=0x%02x, POS7=0x%02x\n",
14850823Smdodd					slot+1,
14950823Smdodd					inb( MCA_POS_REG(MCA_POS6) ),
15050823Smdodd					inb( MCA_POS_REG(MCA_POS7) ));
15150823Smdodd			} else {
15250823Smdodd				printf("MCA NMI: slot %d\n", slot+1);
15350823Smdodd			}
15450823Smdodd		}
15550823Smdodd		/* Disable adapter setup */
15650823Smdodd		outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
15750823Smdodd	}
15850823Smdodd
15950823Smdodd	return (retval);
16050823Smdodd}
161