Home | History | Annotate | Line # | Download | only in x86
      1 /*	$NetBSD: consinit.c,v 1.44 2025/11/29 01:33:40 manu Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1998
      5  *	Matthias Drochner.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  *
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: consinit.c,v 1.44 2025/11/29 01:33:40 manu Exp $");
     31 
     32 #include "opt_kgdb.h"
     33 #include "opt_puc.h"
     34 #include "opt_xen.h"
     35 
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/device.h>
     39 #include <sys/bus.h>
     40 #include <sys/cpu.h>
     41 #include <machine/bootinfo.h>
     42 #include <arch/x86/include/genfb_machdep.h>
     43 
     44 #include <dev/cons.h>
     45 
     46 #include "nullcons.h"
     47 #include "genfb.h"
     48 #include "vga.h"
     49 #include "ega.h"
     50 #include "pcdisplay.h"
     51 #include "com_puc.h"
     52 #if (NVGA > 0) || (NEGA > 0) || (NPCDISPLAY > 0)
     53 #include <dev/ic/mc6845reg.h>
     54 #include <dev/ic/pcdisplayvar.h>
     55 #if (NVGA > 0)
     56 #include <dev/ic/vgareg.h>
     57 #include <dev/ic/vgavar.h>
     58 #endif
     59 #if (NEGA > 0)
     60 #include <dev/isa/egavar.h>
     61 #endif
     62 #if (NPCDISPLAY > 0)
     63 #include <dev/isa/pcdisplayvar.h>
     64 #endif
     65 #endif
     66 
     67 #include "pckbc.h"
     68 #if (NPCKBC > 0)
     69 #include <dev/isa/isareg.h>
     70 #include <dev/ic/i8042reg.h>
     71 #include <dev/ic/pckbcvar.h>
     72 #include <dev/pckbport/pckbportvar.h>
     73 #endif
     74 #include "pckbd.h" /* for pckbc_machdep_cnattach */
     75 
     76 #if (NGENFB > 0)
     77 #include <dev/wsfb/genfbvar.h>
     78 #endif
     79 
     80 #include "com.h"
     81 #if (NCOM > 0)
     82 #include <sys/termios.h>
     83 #include <dev/ic/comreg.h>
     84 #include <dev/ic/comvar.h>
     85 #endif
     86 #if (NCOM_PUC > 0)
     87 #include <dev/pci/puccn.h>
     88 #endif
     89 
     90 #include "ucom.h"
     91 #if (NUCOM > 0)
     92 #include <dev/usb/ucomvar.h>
     93 #endif
     94 
     95 #include "ukbd.h"
     96 #if (NUKBD > 0)
     97 #include <dev/usb/ukbdvar.h>
     98 #endif
     99 
    100 #ifndef XENPV
    101 #include "hvkbd.h"
    102 #if NHVKBD > 0
    103 #include <dev/hyperv/hvkbdvar.h>
    104 #endif
    105 #endif
    106 
    107 #ifdef XENPVHVM
    108 #include <xen/hypervisor.h>
    109 #include <xen/xen.h>
    110 #endif
    111 
    112 #ifndef CONSDEVNAME
    113 #define CONSDEVNAME "pc"
    114 #endif
    115 
    116 #if (NCOM > 0)
    117 #ifndef CONADDR
    118 #define CONADDR 0x3f8
    119 #endif
    120 #ifndef CONSPEED
    121 #define CONSPEED TTYDEF_SPEED
    122 #endif
    123 #ifndef CONMODE
    124 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
    125 #endif
    126 int comcnmode = CONMODE;
    127 #endif /* NCOM */
    128 
    129 const struct btinfo_console default_consinfo = {
    130 	{0, 0},
    131 	CONSDEVNAME,
    132 #if (NCOM > 0)
    133 	CONADDR, CONSPEED
    134 #else
    135 	0, 0
    136 #endif
    137 };
    138 
    139 #ifdef KGDB
    140 #ifndef KGDB_DEVNAME
    141 #define KGDB_DEVNAME "com"
    142 #endif
    143 const char kgdb_devname[] = KGDB_DEVNAME;
    144 
    145 #if (NCOM > 0)
    146 #ifndef KGDB_DEVADDR
    147 #define KGDB_DEVADDR 0x3f8
    148 #endif
    149 int comkgdbaddr = KGDB_DEVADDR;
    150 #ifndef KGDB_DEVRATE
    151 #define KGDB_DEVRATE TTYDEF_SPEED
    152 #endif
    153 int comkgdbrate = KGDB_DEVRATE;
    154 #ifndef KGDB_DEVMODE
    155 #define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
    156 #endif
    157 int comkgdbmode = KGDB_DEVMODE;
    158 #endif /* NCOM */
    159 
    160 #endif /* KGDB */
    161 
    162 /*
    163  * consinit:
    164  * initialize the system console.
    165  * XXX - shouldn't deal with this initted thing, but then,
    166  * it shouldn't be called from init386 either.
    167  */
    168 void
    169 consinit(void)
    170 {
    171 	const struct btinfo_console *consinfo;
    172 #if (NGENFB > 0)
    173 	const struct btinfo_framebuffer *fbinfo = NULL;
    174 #endif
    175 	static int initted;
    176 #if (NCOM > 0)
    177 	int rv;
    178 #endif
    179 	char console_devname[16] = "";
    180 
    181 #ifdef XENPVHVM
    182 	if (vm_guest == VM_GUEST_XENPVH) {
    183 		if (xen_pvh_consinit() != 0)
    184 			return;
    185 		/* fallback to native console selection, useful for dom0 PVH */
    186 	}
    187 	if (pvh_boot) { /* GENPVH */
    188 		union xen_cmdline_parseinfo xcp;
    189 		/* get console= parameter from generic PVH VMM */
    190 		xen_parse_cmdline(XEN_PARSE_CONSOLE, &xcp);
    191 		strncpy(console_devname, xcp.xcp_console,
    192 			sizeof(console_devname));
    193 	}
    194 #endif
    195 	if (initted)
    196 		return;
    197 	initted = 1;
    198 
    199 #ifndef CONS_OVERRIDE
    200 	consinfo = lookup_bootinfo(BTINFO_CONSOLE);
    201 	if (!consinfo)
    202 #endif
    203 		consinfo = &default_consinfo;
    204 	/* console= parameter was not passed via a generic PVH VMM */
    205 	if (!console_devname[0])
    206 		strncpy(console_devname, consinfo->devname,
    207 			sizeof(console_devname));
    208 #if (NGENFB > 0)
    209 #if defined(XENPVHVM) && defined(DOM0OPS)
    210 	if (vm_guest == VM_GUEST_XENPVH && xendomain_is_dom0())
    211 		fbinfo = xen_genfb_getbtinfo();
    212 	else
    213 #endif /* XENPVHVM */
    214 		fbinfo = lookup_bootinfo(BTINFO_FRAMEBUFFER);
    215 #endif
    216 	if (!strcmp(console_devname, "pc")) {
    217 		int error;
    218 #if (NGENFB > 0)
    219 		if (fbinfo && fbinfo->physaddr > 0) {
    220 			/*
    221 			 * If we have a framebuffer address, and
    222 			 * x86_genfb_cnattach can map it, then
    223 			 * genfb_cnattach causes genfb_is_console to
    224 			 * later return true.  device_pci_register will
    225 			 * use this to set up the device properties for
    226 			 * a PCI display-class device to notify it that
    227 			 * it has been selected as the console.
    228 			 */
    229 			if (x86_genfb_cnattach() == -1) {
    230 				initted = 0;	/* defer */
    231 				return;
    232 			}
    233 			genfb_cnattach();
    234 			goto dokbd;
    235 		}
    236 		genfb_disable();
    237 #endif
    238 #if (NVGA > 0)
    239 		if (!vga_cnattach(x86_bus_space_io, x86_bus_space_mem,
    240 				  -1, 1))
    241 			goto dokbd;
    242 #endif
    243 #if (NEGA > 0)
    244 		if (!ega_cnattach(x86_bus_space_io, x86_bus_space_mem))
    245 			goto dokbd;
    246 #endif
    247 #if (NPCDISPLAY > 0)
    248 		if (!pcdisplay_cnattach(x86_bus_space_io, x86_bus_space_mem))
    249 			goto dokbd;
    250 #endif
    251 		if (0) goto dokbd; /* XXX stupid gcc */
    252 dokbd:
    253 		error = ENODEV;
    254 #if (NPCKBC > 0)
    255 		error = pckbc_cnattach(x86_bus_space_io, IO_KBD, KBCMDP,
    256 		    PCKBC_KBD_SLOT, 0);
    257 #endif
    258 #if (NHVKBD > 0)
    259 		if (error && vm_guest == VM_GUEST_HV)
    260 			error = hvkbd_cnattach();
    261 #endif
    262 #if (NUKBD > 0)
    263 		if (error)
    264 			error = ukbd_cnattach();
    265 #endif
    266 		if (error)
    267 			printf("WARNING: no console keyboard, error=%d\n",
    268 			       error);
    269 		return;
    270 	}
    271 #if (NCOM > 0)
    272 	if (!strcmp(console_devname, "com")) {
    273 		int addr = consinfo->addr;
    274 		int speed = consinfo->speed;
    275 
    276 #if (NCOM_PUC > 0) && defined(PUC_CNAUTO)
    277 		puc_cnprobe(NULL);
    278 		rv = puc_cninit(NULL);
    279 		if (rv == 0)
    280 			return;
    281 #endif
    282 
    283 		if (addr == 0)
    284 			addr = CONADDR;
    285 		if (speed == 0)
    286 			speed = CONSPEED;
    287 
    288 		rv = comcnattach(x86_bus_space_io, addr, speed,
    289 				 COM_FREQ, COM_TYPE_NORMAL, comcnmode);
    290 		if (rv != 0)
    291 			panic("can't init serial console @%x", consinfo->addr);
    292 
    293 		return;
    294 	}
    295 #endif
    296 #if (NUCOM > 0)
    297 	if (!strcmp(console_devname, "ucom")) {
    298 		int unit = consinfo->addr;
    299 		int speed = consinfo->speed;
    300 
    301 		if (ucom_cnattach(unit, speed) != 0)
    302 			panic("can't init console %s", console_devname);
    303 
    304 		return;
    305 	}
    306 #endif
    307 #if (NNULLCONS > 0)
    308 	if (!strcmp(console_devname, "nullcons")) {
    309 		void nullcninit(struct consdev *cn);
    310 
    311 		nullcninit(0);
    312 		return;
    313 	}
    314 #endif
    315 	panic("invalid console device %s", console_devname);
    316 }
    317 
    318 #ifdef KGDB
    319 void
    320 kgdb_port_init(void)
    321 {
    322 #if (NCOM > 0)
    323 	if (!strcmp(kgdb_devname, "com")) {
    324 		com_kgdb_attach(x86_bus_space_io, comkgdbaddr, comkgdbrate,
    325 		    COM_FREQ, COM_TYPE_NORMAL, comkgdbmode);
    326 	}
    327 #endif
    328 }
    329 #endif
    330