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