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