143105Sdfr/*- 243105Sdfr * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 343105Sdfr * All rights reserved. 443105Sdfr * 543105Sdfr * Redistribution and use in source and binary forms, with or without 643105Sdfr * modification, are permitted provided that the following conditions 743105Sdfr * are met: 843105Sdfr * 1. Redistributions of source code must retain the above copyright 943105Sdfr * notice, this list of conditions and the following disclaimer as 1043105Sdfr * the first lines of this file unmodified. 1143105Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1243105Sdfr * notice, this list of conditions and the following disclaimer in the 1343105Sdfr * documentation and/or other materials provided with the distribution. 1443105Sdfr * 1543105Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1643105Sdfr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1743105Sdfr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1843105Sdfr * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 1943105Sdfr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2043105Sdfr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2143105Sdfr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2243105Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2343105Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2443105Sdfr * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2543105Sdfr */ 2643105Sdfr 27116181Sobrien#include <sys/cdefs.h> 28116181Sobrien__FBSDID("$FreeBSD$"); 29116181Sobrien 3043105Sdfr#include "opt_syscons.h" 3143105Sdfr 3243105Sdfr#include <sys/param.h> 3343105Sdfr#include <sys/systm.h> 3443105Sdfr#include <sys/kernel.h> 3543105Sdfr#include <sys/module.h> 3643105Sdfr#include <sys/bus.h> 3749558Sphk#include <sys/cons.h> 3866834Sphk#include <sys/kbio.h> 3966834Sphk#include <sys/consio.h> 40109279Smdodd#include <sys/sysctl.h> 4143105Sdfr 42135690Speter#if defined(__i386__) || defined(__amd64__) 4343105Sdfr 4448104Syokota#include <machine/clock.h> 4548104Syokota#include <machine/md_var.h> 4648104Syokota#include <machine/pc/bios.h> 4748104Syokota 4848104Syokota#include <vm/vm.h> 4948104Syokota#include <vm/pmap.h> 50130312Sjhb#include <vm/vm_param.h> 5148104Syokota 5248104Syokota#define BIOS_CLKED (1 << 6) 5348104Syokota#define BIOS_NLKED (1 << 5) 5448104Syokota#define BIOS_SLKED (1 << 4) 5548104Syokota#define BIOS_ALKED 0 5648104Syokota 57135690Speter#endif 5848104Syokota 5943105Sdfr#include <dev/syscons/syscons.h> 6043105Sdfr 6143105Sdfr#include <isa/isavar.h> 6243105Sdfr 63156243Srink#include "opt_xbox.h" 64156243Srink 65156243Srink#ifdef XBOX 66156243Srink#include <machine/xbox.h> 67156243Srink#endif 68156243Srink 6948104Syokotastatic devclass_t sc_devclass; 7043105Sdfr 71208412Sjkimstatic sc_softc_t main_softc; 7243105Sdfr 7362225Speterstatic void 74208412Sjkimscidentify(driver_t *driver, device_t parent) 7562225Speter{ 76208412Sjkim 7762225Speter BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "sc", 0); 7862225Speter} 7943105Sdfr 8043105Sdfrstatic int 8143105Sdfrscprobe(device_t dev) 8243105Sdfr{ 83208412Sjkim 8447618Sdfr /* No pnp support */ 8547618Sdfr if (isa_get_vendorid(dev)) 8647618Sdfr return (ENXIO); 8747618Sdfr 8843105Sdfr device_set_desc(dev, "System console"); 89208412Sjkim return (sc_probe_unit(device_get_unit(dev), device_get_flags(dev))); 9043105Sdfr} 9143105Sdfr 9243105Sdfrstatic int 9343105Sdfrscattach(device_t dev) 9443105Sdfr{ 95189421Sjhb 96189421Sjhb return (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | 97189421Sjhb SC_AUTODETECT_KBD)); 9843105Sdfr} 9943105Sdfr 10048104Syokotaint 10148104Syokotasc_max_unit(void) 10248104Syokota{ 103208412Sjkim 104208412Sjkim return (devclass_get_maxunit(sc_devclass)); 10548104Syokota} 10648104Syokota 10748104Syokotasc_softc_t 10848104Syokota*sc_get_softc(int unit, int flags) 10948104Syokota{ 11048104Syokota sc_softc_t *sc; 11148104Syokota 11256836Speter if (unit < 0) 113208412Sjkim return (NULL); 114208412Sjkim if ((flags & SC_KERNEL_CONSOLE) != 0) { 11548104Syokota /* FIXME: clear if it is wired to another unit! */ 11655849Syokota sc = &main_softc; 11748104Syokota } else { 118208412Sjkim sc = device_get_softc(devclass_get_device(sc_devclass, unit)); 11956836Speter if (sc == NULL) 120208412Sjkim return (NULL); 12148104Syokota } 12255849Syokota sc->unit = unit; 123208412Sjkim if ((sc->flags & SC_INIT_DONE) == 0) { 12455849Syokota sc->keyboard = -1; 12555849Syokota sc->adapter = -1; 12658872Syokota sc->cursor_char = SC_CURSOR_CHAR; 12755849Syokota sc->mouse_char = SC_MOUSE_CHAR; 12855849Syokota } 129208412Sjkim return (sc); 13048104Syokota} 13148104Syokota 13248104Syokotasc_softc_t 13348104Syokota*sc_find_softc(struct video_adapter *adp, struct keyboard *kbd) 13448104Syokota{ 13548104Syokota sc_softc_t *sc; 136208412Sjkim int i; 13748104Syokota int units; 13848104Syokota 13948104Syokota sc = &main_softc; 140208412Sjkim if ((adp == NULL || adp == sc->adp) && 141208412Sjkim (kbd == NULL || kbd == sc->kbd)) 142208412Sjkim return (sc); 14348104Syokota units = devclass_get_maxunit(sc_devclass); 14448104Syokota for (i = 0; i < units; ++i) { 145208412Sjkim sc = device_get_softc(devclass_get_device(sc_devclass, i)); 14648104Syokota if (sc == NULL) 14748104Syokota continue; 148208412Sjkim if ((adp == NULL || adp == sc->adp) && 149208412Sjkim (kbd == NULL || kbd == sc->kbd)) 150208412Sjkim return (sc); 15148104Syokota } 152208412Sjkim return (NULL); 15348104Syokota} 15448104Syokota 15548104Syokotaint 15648104Syokotasc_get_cons_priority(int *unit, int *flags) 15748104Syokota{ 15878262Speter const char *at; 159208413Sjkim int f, u; 16048104Syokota 161156243Srink#ifdef XBOX 162156243Srink /* 163156243Srink * The XBox Loader does not support hints, which makes our initial 164156243Srink * console probe fail. Therefore, if an XBox is found, we hardcode the 165156243Srink * existence of the console, as it is always there anyway. 166156243Srink */ 167156243Srink if (arch_i386_is_xbox) { 168156243Srink *unit = 0; 169156243Srink *flags = SC_KERNEL_CONSOLE; 170208412Sjkim return (CN_INTERNAL); 171156243Srink } 172156243Srink#endif 173156243Srink 17448104Syokota *unit = -1; 17561704Speter for (u = 0; u < 16; u++) { 176117167Sjhb if (resource_disabled(SC_DRIVER_NAME, u)) 17748104Syokota continue; 17861704Speter if (resource_string_value(SC_DRIVER_NAME, u, "at", &at) != 0) 17961704Speter continue; 18048104Syokota if (resource_int_value(SC_DRIVER_NAME, u, "flags", &f) != 0) 18148104Syokota f = 0; 18248104Syokota if (f & SC_KERNEL_CONSOLE) { 18348104Syokota /* the user designates this unit to be the console */ 18448104Syokota *unit = u; 18548104Syokota *flags = f; 18648104Syokota break; 18748104Syokota } 18848104Syokota if (*unit < 0) { 18948104Syokota /* ...otherwise remember the first found unit */ 19048104Syokota *unit = u; 19148104Syokota *flags = f; 19248104Syokota } 19348104Syokota } 194189421Sjhb if (*unit < 0) { 195189421Sjhb *unit = 0; 196189421Sjhb *flags = 0; 197189421Sjhb } 19848104Syokota#if 0 199208412Sjkim return ((*flags & SC_KERNEL_CONSOLE) != 0 ? CN_INTERNAL : CN_NORMAL); 20048104Syokota#endif 201208412Sjkim return (CN_INTERNAL); 20248104Syokota} 20348104Syokota 20448104Syokotavoid 20548104Syokotasc_get_bios_values(bios_values_t *values) 20648104Syokota{ 207135690Speter#if defined(__i386__) || defined(__amd64__) 208208412Sjkim uint8_t shift; 20948104Syokota 210208412Sjkim values->cursor_start = *(uint8_t *)BIOS_PADDRTOVADDR(0x461); 211208412Sjkim values->cursor_end = *(uint8_t *)BIOS_PADDRTOVADDR(0x460); 212208412Sjkim shift = *(uint8_t *)BIOS_PADDRTOVADDR(0x417); 213208412Sjkim values->shift_state = ((shift & BIOS_CLKED) != 0 ? CLKED : 0) | 214208412Sjkim ((shift & BIOS_NLKED) != 0 ? NLKED : 0) | 215208412Sjkim ((shift & BIOS_SLKED) != 0 ? SLKED : 0) | 216208412Sjkim ((shift & BIOS_ALKED) != 0 ? ALKED : 0); 217135690Speter#else 21848104Syokota values->cursor_start = 0; 21948104Syokota values->cursor_end = 32; 22048104Syokota values->shift_state = 0; 221135690Speter#endif 22248104Syokota values->bell_pitch = BELL_PITCH; 22348104Syokota} 22448104Syokota 22548104Syokotaint 22648104Syokotasc_tone(int herz) 22748104Syokota{ 228208412Sjkim 229177650Sphk#if defined(HAS_TIMER_SPKR) 23048104Syokota if (herz) { 231146211Snyan if (timer_spkr_acquire()) 232208412Sjkim return (EBUSY); 233177642Sphk timer_spkr_setfreq(herz); 234208412Sjkim } else 235146211Snyan timer_spkr_release(); 236135690Speter#endif 23748104Syokota 238208412Sjkim return (0); 23948104Syokota} 24048104Syokota 24162225Speterstatic device_method_t sc_methods[] = { 24262225Speter DEVMETHOD(device_identify, scidentify), 24362225Speter DEVMETHOD(device_probe, scprobe), 24462225Speter DEVMETHOD(device_attach, scattach), 24562225Speter { 0, 0 } 24662225Speter}; 24762225Speter 24862225Speterstatic driver_t sc_driver = { 24962225Speter SC_DRIVER_NAME, 25062225Speter sc_methods, 25162225Speter sizeof(sc_softc_t), 25262225Speter}; 25362225Speter 25443105SdfrDRIVER_MODULE(sc, isa, sc_driver, sc_devclass, 0, 0); 255