mca_machdep.c revision 302408
1114402Sru/*-
2114402Sru * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net>
3114402Sru * All rights reserved.
4114402Sru *
5114402Sru * Redistribution and use in source and binary forms, with or without
6114402Sru * modification, are permitted provided that the following conditions
7114402Sru * are met:
8114402Sru * 1. Redistributions of source code must retain the above copyright
9114402Sru *    notice, this list of conditions and the following disclaimer.
10114402Sru * 2. Redistributions in binary form must reproduce the above copyright
11114402Sru *    notice, this list of conditions and the following disclaimer in the
12114402Sru *    documentation and/or other materials provided with the distribution.
13114402Sru *
14114402Sru * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15114402Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16114402Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17114402Sru * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18114402Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19114402Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20114402Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21114402Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22114402Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23114402Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24114402Sru * SUCH DAMAGE.
25114402Sru */
26114402Sru
27114402Sru#include <sys/cdefs.h>
28114402Sru__FBSDID("$FreeBSD: stable/11/sys/i386/bios/mca_machdep.c 295880 2016-02-22 09:02:20Z skra $");
29114402Sru
30114402Sru#include <sys/param.h>
31114402Sru#include <sys/systm.h>
32114402Sru#include <sys/kernel.h>
33114402Sru#include <vm/vm.h>
34114402Sru#include <vm/vm_param.h>
35114402Sru#include <vm/pmap.h>
36114402Sru#include <machine/md_var.h>
37114402Sru#include <machine/vm86.h>
38114402Sru#include <machine/pc/bios.h>
39114402Sru#include <machine/cpufunc.h>
40114402Sru
41114402Sru#include <dev/mca/mca_busreg.h>
42114402Sru#include <i386/bios/mca_machdep.h>
43114402Sru
44114402Sru/* Global MCA bus flag */
45114402Sruint MCA_system = 0;
46114402Sru
47114402Sru/* System Configuration Block */
48114402Srustruct sys_config {
49114402Sru	u_int16_t	count;
50114402Sru	u_int8_t	model;
51114402Sru	u_int8_t	submodel;
52114402Sru	u_int8_t	bios_rev;
53114402Sru	u_int8_t	feature;
54114402Sru#define FEATURE_MCAISA	0x01	/* Machine contains both MCA and ISA bus*/
55114402Sru#define FEATURE_MCABUS	0x02	/* MicroChannel Architecture		*/
56114402Sru#define FEATURE_EBDA	0x04	/* Extended BIOS data area allocated	*/
57114402Sru#define FEATURE_WAITEV	0x08	/* Wait for external event is supported	*/
58114402Sru#define FEATURE_KBDINT	0x10	/* Keyboard intercept called by Int 09h	*/
59114402Sru#define FEATURE_RTC	0x20	/* Real-time clock present		*/
60114402Sru#define FEATURE_IC2	0x40	/* Second interrupt chip present	*/
61114402Sru#define FEATURE_DMA3	0x80	/* DMA channel 3 used by hard disk BIOS	*/
62114402Sru	u_int8_t	pad[3];
63114402Sru} __packed;
64114402Sru
65114402Sru/* Function Prototypes */
66114402Srustatic void bios_mcabus_present	(void *);
67114402SruSYSINIT(mca_present, SI_SUB_CPU, SI_ORDER_ANY, bios_mcabus_present, NULL);
68114402Sru
69114402Sru/* Functions */
70114402Srustatic void
71114402Srubios_mcabus_present(void * dummy)
72114402Sru{
73114402Sru	struct vm86frame	vmf;
74114402Sru	struct sys_config *	scp;
75114402Sru	vm_offset_t		paddr;
76114402Sru
77114402Sru	bzero(&vmf, sizeof(struct vm86frame));
78114402Sru
79114402Sru	vmf.vmf_ah = 0xc0;
80114402Sru	if (vm86_intcall(0x15, &vmf)) {
81114402Sru		if (bootverbose) {
82114402Sru			printf("BIOS SDT: INT call failed.\n");
83114402Sru		}
84114402Sru		return;
85114402Sru	}
86114402Sru
87114402Sru	if ((vmf.vmf_ah != 0) && (vmf.vmf_flags & 0x01)) {
88114402Sru		if (bootverbose) {
89114402Sru			printf("BIOS SDT: Not supported.  Not PS/2?\n");
90114402Sru			printf("BIOS SDT: AH 0x%02x, Flags 0x%04x\n",
91114402Sru				vmf.vmf_ah, vmf.vmf_flags);
92114402Sru		}
93114402Sru		return;
94114402Sru	}
95114402Sru
96114402Sru	paddr = vmf.vmf_es;
97114402Sru	paddr = (paddr << 4) + vmf.vmf_bx;
98114402Sru	scp = (struct sys_config *)BIOS_PADDRTOVADDR(paddr);
99114402Sru
100114402Sru	if (bootverbose) {
101114402Sru		printf("BIOS SDT: model 0x%02x, submodel 0x%02x, bios_rev 0x%02x\n",
102114402Sru			scp->model, scp->submodel, scp->bios_rev);
103114402Sru		printf("BIOS SDT: features 0x%b\n", scp->feature,
104114402Sru			"\20"
105114402Sru			"\01MCA+ISA"
106114402Sru			"\02MCA"
107114402Sru			"\03EBDA"
108114402Sru			"\04WAITEV"
109114402Sru			"\05KBDINT"
110114402Sru			"\06RTC"
111114402Sru			"\07IC2"
112114402Sru			"\08DMA3"
113114402Sru			"\n");
114114402Sru	}
115114402Sru
116114402Sru	MCA_system = ((scp->feature & FEATURE_MCABUS) ? 1 : 0);
117114402Sru
118114402Sru	if (MCA_system)
119114402Sru		printf("MicroChannel Architecture System detected.\n");
120114402Sru
121114402Sru	return;
122114402Sru}
123114402Sru
124114402Sruint
125114402Srumca_bus_nmi (void)
126114402Sru{
127114402Sru	int	slot;
128114402Sru	int	retval = 0;
129114402Sru	int	pos5 = 0;
130114402Sru
131114402Sru	/* Disable motherboard setup */
132114402Sru	outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
133114402Sru
134114402Sru	/* For each slot */
135114402Sru	for (slot = 0; slot < MCA_MAX_SLOTS; slot++) {
136114402Sru
137114402Sru		/* Select the slot */
138114402Sru		outb(MCA_ADAP_SETUP_REG, slot | MCA_ADAP_SET);
139114402Sru		pos5 = inb(MCA_POS_REG(MCA_POS5));
140114402Sru
141114402Sru		/* If Adapter Check is low */
142114402Sru		if ((pos5 & MCA_POS5_CHCK) == 0) {
143114402Sru			retval++;
144114402Sru
145114402Sru			/* If Adapter Check Status is available */
146114402Sru			if ((pos5 & MCA_POS5_CHCK_STAT) == 0) {
147114402Sru				printf("MCA NMI: slot %d, POS6=0x%02x, POS7=0x%02x\n",
148114402Sru					slot+1,
149114402Sru					inb( MCA_POS_REG(MCA_POS6) ),
150114402Sru					inb( MCA_POS_REG(MCA_POS7) ));
151114402Sru			} else {
152114402Sru				printf("MCA NMI: slot %d\n", slot+1);
153114402Sru			}
154114402Sru		}
155114402Sru		/* Disable adapter setup */
156114402Sru		outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
157114402Sru	}
158114402Sru
159114402Sru	return (retval);
160114402Sru}
161114402Sru