1/*-
2 * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kernel.h>
33#include <vm/vm.h>
34#include <vm/vm_param.h>
35#include <vm/pmap.h>
36#include <machine/md_var.h>
37#include <machine/vm86.h>
38#include <machine/pc/bios.h>
39#include <machine/cpufunc.h>
40
41#include <dev/mca/mca_busreg.h>
42#include <i386/bios/mca_machdep.h>
43
44/* Global MCA bus flag */
45int MCA_system = 0;
46
47/* System Configuration Block */
48struct sys_config {
49	u_int16_t	count;
50	u_int8_t	model;
51	u_int8_t	submodel;
52	u_int8_t	bios_rev;
53	u_int8_t	feature;
54#define FEATURE_MCAISA	0x01	/* Machine contains both MCA and ISA bus*/
55#define FEATURE_MCABUS	0x02	/* MicroChannel Architecture		*/
56#define FEATURE_EBDA	0x04	/* Extended BIOS data area allocated	*/
57#define FEATURE_WAITEV	0x08	/* Wait for external event is supported	*/
58#define FEATURE_KBDINT	0x10	/* Keyboard intercept called by Int 09h	*/
59#define FEATURE_RTC	0x20	/* Real-time clock present		*/
60#define FEATURE_IC2	0x40	/* Second interrupt chip present	*/
61#define FEATURE_DMA3	0x80	/* DMA channel 3 used by hard disk BIOS	*/
62	u_int8_t	pad[3];
63} __packed;
64
65/* Function Prototypes */
66static void bios_mcabus_present	(void *);
67SYSINIT(mca_present, SI_SUB_CPU, SI_ORDER_ANY, bios_mcabus_present, NULL);
68
69/* Functions */
70static void
71bios_mcabus_present(void * dummy)
72{
73	struct vm86frame	vmf;
74	struct sys_config *	scp;
75	vm_offset_t		paddr;
76
77	bzero(&vmf, sizeof(struct vm86frame));
78
79	vmf.vmf_ah = 0xc0;
80	if (vm86_intcall(0x15, &vmf)) {
81		if (bootverbose) {
82			printf("BIOS SDT: INT call failed.\n");
83		}
84		return;
85	}
86
87	if ((vmf.vmf_ah != 0) && (vmf.vmf_flags & 0x01)) {
88		if (bootverbose) {
89			printf("BIOS SDT: Not supported.  Not PS/2?\n");
90			printf("BIOS SDT: AH 0x%02x, Flags 0x%04x\n",
91				vmf.vmf_ah, vmf.vmf_flags);
92		}
93		return;
94	}
95
96	paddr = vmf.vmf_es;
97	paddr = (paddr << 4) + vmf.vmf_bx;
98	scp = (struct sys_config *)BIOS_PADDRTOVADDR(paddr);
99
100	if (bootverbose) {
101		printf("BIOS SDT: model 0x%02x, submodel 0x%02x, bios_rev 0x%02x\n",
102			scp->model, scp->submodel, scp->bios_rev);
103		printf("BIOS SDT: features 0x%b\n", scp->feature,
104			"\20"
105			"\01MCA+ISA"
106			"\02MCA"
107			"\03EBDA"
108			"\04WAITEV"
109			"\05KBDINT"
110			"\06RTC"
111			"\07IC2"
112			"\08DMA3"
113			"\n");
114	}
115
116	MCA_system = ((scp->feature & FEATURE_MCABUS) ? 1 : 0);
117
118	if (MCA_system)
119		printf("MicroChannel Architecture System detected.\n");
120
121	return;
122}
123
124int
125mca_bus_nmi (void)
126{
127	int	slot;
128	int	retval = 0;
129	int	pos5 = 0;
130
131	/* Disable motherboard setup */
132	outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
133
134	/* For each slot */
135	for (slot = 0; slot < MCA_MAX_SLOTS; slot++) {
136
137		/* Select the slot */
138		outb(MCA_ADAP_SETUP_REG, slot | MCA_ADAP_SET);
139		pos5 = inb(MCA_POS_REG(MCA_POS5));
140
141		/* If Adapter Check is low */
142		if ((pos5 & MCA_POS5_CHCK) == 0) {
143			retval++;
144
145			/* If Adapter Check Status is available */
146			if ((pos5 & MCA_POS5_CHCK_STAT) == 0) {
147				printf("MCA NMI: slot %d, POS6=0x%02x, POS7=0x%02x\n",
148					slot+1,
149					inb( MCA_POS_REG(MCA_POS6) ),
150					inb( MCA_POS_REG(MCA_POS7) ));
151			} else {
152				printf("MCA NMI: slot %d\n", slot+1);
153			}
154		}
155		/* Disable adapter setup */
156		outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
157	}
158
159	return (retval);
160}
161