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