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/pmap.h>
3750823Smdodd#include <machine/md_var.h>
3850823Smdodd#include <machine/vm86.h>
3950823Smdodd#include <machine/pc/bios.h>
4050823Smdodd#include <machine/cpufunc.h>
4150823Smdodd
4250823Smdodd#include <dev/mca/mca_busreg.h>
43112551Smdodd#include <i386/bios/mca_machdep.h>
4450823Smdodd
4550823Smdodd/* Global MCA bus flag */
4650823Smdoddint MCA_system = 0;
4750823Smdodd
4850823Smdodd/* System Configuration Block */
4950823Smdoddstruct sys_config {
5050823Smdodd	u_int16_t	count;
5150823Smdodd	u_int8_t	model;
5250823Smdodd	u_int8_t	submodel;
5350823Smdodd	u_int8_t	bios_rev;
5450823Smdodd	u_int8_t	feature;
55134582Smdodd#define FEATURE_MCAISA	0x01	/* Machine contains both MCA and ISA bus*/
5650823Smdodd#define FEATURE_MCABUS	0x02	/* MicroChannel Architecture		*/
5750823Smdodd#define FEATURE_EBDA	0x04	/* Extended BIOS data area allocated	*/
5850823Smdodd#define FEATURE_WAITEV	0x08	/* Wait for external event is supported	*/
5950823Smdodd#define FEATURE_KBDINT	0x10	/* Keyboard intercept called by Int 09h	*/
6050823Smdodd#define FEATURE_RTC	0x20	/* Real-time clock present		*/
6150823Smdodd#define FEATURE_IC2	0x40	/* Second interrupt chip present	*/
6250823Smdodd#define FEATURE_DMA3	0x80	/* DMA channel 3 used by hard disk BIOS	*/
6350823Smdodd	u_int8_t	pad[3];
64103870Salfred} __packed;
6550823Smdodd
6650823Smdodd/* Function Prototypes */
6750823Smdoddstatic void bios_mcabus_present	(void *);
6850823SmdoddSYSINIT(mca_present, SI_SUB_CPU, SI_ORDER_ANY, bios_mcabus_present, NULL);
6950823Smdodd
7050823Smdodd/* Functions */
7150823Smdoddstatic void
7250823Smdoddbios_mcabus_present(void * dummy)
7350823Smdodd{
7450823Smdodd	struct vm86frame	vmf;
7550823Smdodd	struct sys_config *	scp;
7650823Smdodd	vm_offset_t		paddr;
7750823Smdodd
7850823Smdodd	bzero(&vmf, sizeof(struct vm86frame));
7950823Smdodd
8050823Smdodd	vmf.vmf_ah = 0xc0;
8150823Smdodd	if (vm86_intcall(0x15, &vmf)) {
8250823Smdodd		if (bootverbose) {
8350823Smdodd			printf("BIOS SDT: INT call failed.\n");
8450823Smdodd		}
8550824Smdodd		return;
8650823Smdodd	}
8750823Smdodd
8855889Smdodd	if ((vmf.vmf_ah != 0) && (vmf.vmf_flags & 0x01)) {
8950823Smdodd		if (bootverbose) {
9050823Smdodd			printf("BIOS SDT: Not supported.  Not PS/2?\n");
9150823Smdodd			printf("BIOS SDT: AH 0x%02x, Flags 0x%04x\n",
9250823Smdodd				vmf.vmf_ah, vmf.vmf_flags);
9350823Smdodd		}
9450824Smdodd		return;
9550823Smdodd	}
9650823Smdodd
9750823Smdodd	paddr = vmf.vmf_es;
9850823Smdodd	paddr = (paddr << 4) + vmf.vmf_bx;
9950823Smdodd	scp = (struct sys_config *)BIOS_PADDRTOVADDR(paddr);
10050823Smdodd
10150823Smdodd	if (bootverbose) {
10250823Smdodd		printf("BIOS SDT: model 0x%02x, submodel 0x%02x, bios_rev 0x%02x\n",
10350823Smdodd			scp->model, scp->submodel, scp->bios_rev);
10450823Smdodd		printf("BIOS SDT: features 0x%b\n", scp->feature,
10550823Smdodd			"\20"
106134582Smdodd			"\01MCA+ISA"
107134582Smdodd			"\02MCA"
10850823Smdodd			"\03EBDA"
10950823Smdodd			"\04WAITEV"
11050823Smdodd			"\05KBDINT"
11150823Smdodd			"\06RTC"
11250823Smdodd			"\07IC2"
113134582Smdodd			"\08DMA3"
114134582Smdodd			"\n");
11550823Smdodd	}
11650823Smdodd
11750823Smdodd	MCA_system = ((scp->feature & FEATURE_MCABUS) ? 1 : 0);
11850823Smdodd
11950823Smdodd	if (MCA_system)
12050823Smdodd		printf("MicroChannel Architecture System detected.\n");
12150823Smdodd
12250823Smdodd	return;
12350823Smdodd}
12450823Smdodd
12550823Smdoddint
12650823Smdoddmca_bus_nmi (void)
12750823Smdodd{
12850823Smdodd	int	slot;
12950823Smdodd	int	retval = 0;
13050823Smdodd	int	pos5 = 0;
13150823Smdodd
13250823Smdodd	/* Disable motherboard setup */
13350823Smdodd	outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
13450823Smdodd
13550823Smdodd	/* For each slot */
13650823Smdodd	for (slot = 0; slot < MCA_MAX_SLOTS; slot++) {
13750823Smdodd
13850823Smdodd		/* Select the slot */
13950823Smdodd		outb(MCA_ADAP_SETUP_REG, slot | MCA_ADAP_SET);
14050823Smdodd		pos5 = inb(MCA_POS_REG(MCA_POS5));
14150823Smdodd
14250823Smdodd		/* If Adapter Check is low */
14350823Smdodd		if ((pos5 & MCA_POS5_CHCK) == 0) {
14450823Smdodd			retval++;
14550823Smdodd
14650823Smdodd			/* If Adapter Check Status is available */
14750823Smdodd			if ((pos5 & MCA_POS5_CHCK_STAT) == 0) {
14850823Smdodd				printf("MCA NMI: slot %d, POS6=0x%02x, POS7=0x%02x\n",
14950823Smdodd					slot+1,
15050823Smdodd					inb( MCA_POS_REG(MCA_POS6) ),
15150823Smdodd					inb( MCA_POS_REG(MCA_POS7) ));
15250823Smdodd			} else {
15350823Smdodd				printf("MCA NMI: slot %d\n", slot+1);
15450823Smdodd			}
15550823Smdodd		}
15650823Smdodd		/* Disable adapter setup */
15750823Smdodd		outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
15850823Smdodd	}
15950823Smdodd
16050823Smdodd	return (retval);
16150823Smdodd}
162