1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2013 Neel Natu <neel@freebsd.org> 5 * Copyright (c) 2013 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 /* 33 * Copyright 2018 Joyent, Inc. 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include <sys/types.h> 40 #include <machine/vmm.h> 41 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 46 #include <vmmapi.h> 47 48 #include "acpi.h" 49 #include "debug.h" 50 #include "bootrom.h" 51 #include "config.h" 52 #include "inout.h" 53 #include "pci_emul.h" 54 #include "pci_irq.h" 55 #include "pci_lpc.h" 56 #include "pctestdev.h" 57 #include "uart_emul.h" 58 59 #define IO_ICU1 0x20 60 #define IO_ICU2 0xA0 61 62 SET_DECLARE(lpc_dsdt_set, struct lpc_dsdt); 63 SET_DECLARE(lpc_sysres_set, struct lpc_sysres); 64 65 #define ELCR_PORT 0x4d0 66 SYSRES_IO(ELCR_PORT, 2); 67 68 #define IO_TIMER1_PORT 0x40 69 70 #define NMISC_PORT 0x61 71 SYSRES_IO(NMISC_PORT, 1); 72 73 static struct pci_devinst *lpc_bridge; 74 75 #define LPC_UART_NUM 4 76 static struct lpc_uart_softc { 77 struct uart_softc *uart_softc; 78 int iobase; 79 int irq; 80 int enabled; 81 } lpc_uart_softc[LPC_UART_NUM]; 82 83 static const char *lpc_uart_names[LPC_UART_NUM] = { 84 "com1", "com2", "com3", "com4" 85 }; 86 87 static const char *lpc_uart_acpi_names[LPC_UART_NUM] = { 88 "COM1", "COM2", "COM3", "COM4" 89 }; 90 91 /* 92 * LPC device configuration is in the following form: 93 * <lpc_device_name>[,<options>] 94 * For e.g. "com1,stdio" or "bootrom,/var/romfile" 95 */ 96 int 97 lpc_device_parse(const char *opts) 98 { 99 int unit, error; 100 char *str, *cpy, *lpcdev, *node_name; 101 102 error = -1; 103 str = cpy = strdup(opts); 104 lpcdev = strsep(&str, ","); 105 if (lpcdev != NULL) { 106 if (strcasecmp(lpcdev, "bootrom") == 0) { 107 set_config_value("lpc.bootrom", str); 108 error = 0; 109 goto done; 110 } 111 for (unit = 0; unit < LPC_UART_NUM; unit++) { 112 if (strcasecmp(lpcdev, lpc_uart_names[unit]) == 0) { 113 asprintf(&node_name, "lpc.%s.path", 114 lpc_uart_names[unit]); 115 set_config_value(node_name, str); 116 free(node_name); 117 error = 0; 118 goto done; 119 } 120 } 121 if (strcasecmp(lpcdev, pctestdev_getname()) == 0) { 122 asprintf(&node_name, "lpc.%s", pctestdev_getname()); 123 set_config_bool(node_name, true); 124 free(node_name); 125 error = 0; 126 goto done; 127 } 128 } 129 130 done: 131 free(cpy); 132 133 return (error); 134 } 135 136 void 137 lpc_print_supported_devices() 138 { 139 size_t i; 140 141 printf("bootrom\n"); 142 for (i = 0; i < LPC_UART_NUM; i++) 143 printf("%s\n", lpc_uart_names[i]); 144 printf("%s\n", pctestdev_getname()); 145 } 146 147 const char * 148 lpc_bootrom(void) 149 { 150 151 return (get_config_value("lpc.bootrom")); 152 } 153 154 static void 155 lpc_uart_intr_assert(void *arg) 156 { 157 struct lpc_uart_softc *sc = arg; 158 159 assert(sc->irq >= 0); 160 161 vm_isa_pulse_irq(lpc_bridge->pi_vmctx, sc->irq, sc->irq); 162 } 163 164 static void 165 lpc_uart_intr_deassert(void *arg) 166 { 167 /* 168 * The COM devices on the LPC bus generate edge triggered interrupts, 169 * so nothing more to do here. 170 */ 171 } 172 173 static int 174 lpc_uart_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 175 uint32_t *eax, void *arg) 176 { 177 int offset; 178 struct lpc_uart_softc *sc = arg; 179 180 offset = port - sc->iobase; 181 182 switch (bytes) { 183 case 1: 184 if (in) 185 *eax = uart_read(sc->uart_softc, offset); 186 else 187 uart_write(sc->uart_softc, offset, *eax); 188 break; 189 case 2: 190 if (in) { 191 *eax = uart_read(sc->uart_softc, offset); 192 *eax |= uart_read(sc->uart_softc, offset + 1) << 8; 193 } else { 194 uart_write(sc->uart_softc, offset, *eax); 195 uart_write(sc->uart_softc, offset + 1, *eax >> 8); 196 } 197 break; 198 #ifndef __FreeBSD__ 199 case 4: 200 if (in) { 201 *eax = uart_read(sc->uart_softc, offset); 202 *eax |= uart_read(sc->uart_softc, offset + 1) << 8; 203 *eax |= uart_read(sc->uart_softc, offset + 2) << 16; 204 *eax |= uart_read(sc->uart_softc, offset + 3) << 24; 205 } else { 206 uart_write(sc->uart_softc, offset, *eax); 207 uart_write(sc->uart_softc, offset + 1, *eax >> 8); 208 uart_write(sc->uart_softc, offset + 2, *eax >> 16); 209 uart_write(sc->uart_softc, offset + 3, *eax >> 24); 210 } 211 break; 212 #endif 213 default: 214 return (-1); 215 } 216 217 return (0); 218 } 219 220 static int 221 lpc_init(struct vmctx *ctx) 222 { 223 struct lpc_uart_softc *sc; 224 struct inout_port iop; 225 const char *backend, *name, *romfile; 226 char *node_name; 227 int unit, error; 228 229 romfile = get_config_value("lpc.bootrom"); 230 if (romfile != NULL) { 231 error = bootrom_loadrom(ctx, romfile); 232 if (error) 233 return (error); 234 } 235 236 /* COM1 and COM2 */ 237 for (unit = 0; unit < LPC_UART_NUM; unit++) { 238 sc = &lpc_uart_softc[unit]; 239 name = lpc_uart_names[unit]; 240 241 if (uart_legacy_alloc(unit, &sc->iobase, &sc->irq) != 0) { 242 EPRINTLN("Unable to allocate resources for " 243 "LPC device %s", name); 244 return (-1); 245 } 246 pci_irq_reserve(sc->irq); 247 248 sc->uart_softc = uart_init(lpc_uart_intr_assert, 249 lpc_uart_intr_deassert, sc); 250 251 asprintf(&node_name, "lpc.%s.path", name); 252 backend = get_config_value(node_name); 253 free(node_name); 254 if (uart_set_backend(sc->uart_softc, backend) != 0) { 255 EPRINTLN("Unable to initialize backend '%s' " 256 "for LPC device %s", backend, name); 257 return (-1); 258 } 259 260 bzero(&iop, sizeof(struct inout_port)); 261 iop.name = name; 262 iop.port = sc->iobase; 263 iop.size = UART_IO_BAR_SIZE; 264 iop.flags = IOPORT_F_INOUT; 265 iop.handler = lpc_uart_io_handler; 266 iop.arg = sc; 267 268 error = register_inout(&iop); 269 assert(error == 0); 270 sc->enabled = 1; 271 } 272 273 /* pc-testdev */ 274 asprintf(&node_name, "lpc.%s", pctestdev_getname()); 275 if (get_config_bool_default(node_name, false)) { 276 error = pctestdev_init(ctx); 277 if (error) 278 return (error); 279 } 280 free(node_name); 281 282 return (0); 283 } 284 285 static void 286 pci_lpc_write_dsdt(struct pci_devinst *pi) 287 { 288 struct lpc_dsdt **ldpp, *ldp; 289 290 dsdt_line(""); 291 dsdt_line("Device (ISA)"); 292 dsdt_line("{"); 293 dsdt_line(" Name (_ADR, 0x%04X%04X)", pi->pi_slot, pi->pi_func); 294 dsdt_line(" OperationRegion (LPCR, PCI_Config, 0x00, 0x100)"); 295 dsdt_line(" Field (LPCR, AnyAcc, NoLock, Preserve)"); 296 dsdt_line(" {"); 297 dsdt_line(" Offset (0x60),"); 298 dsdt_line(" PIRA, 8,"); 299 dsdt_line(" PIRB, 8,"); 300 dsdt_line(" PIRC, 8,"); 301 dsdt_line(" PIRD, 8,"); 302 dsdt_line(" Offset (0x68),"); 303 dsdt_line(" PIRE, 8,"); 304 dsdt_line(" PIRF, 8,"); 305 dsdt_line(" PIRG, 8,"); 306 dsdt_line(" PIRH, 8"); 307 dsdt_line(" }"); 308 dsdt_line(""); 309 310 dsdt_indent(1); 311 SET_FOREACH(ldpp, lpc_dsdt_set) { 312 ldp = *ldpp; 313 ldp->handler(); 314 } 315 316 dsdt_line(""); 317 dsdt_line("Device (PIC)"); 318 dsdt_line("{"); 319 dsdt_line(" Name (_HID, EisaId (\"PNP0000\"))"); 320 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 321 dsdt_line(" {"); 322 dsdt_indent(2); 323 dsdt_fixed_ioport(IO_ICU1, 2); 324 dsdt_fixed_ioport(IO_ICU2, 2); 325 dsdt_fixed_irq(2); 326 dsdt_unindent(2); 327 dsdt_line(" })"); 328 dsdt_line("}"); 329 330 dsdt_line(""); 331 dsdt_line("Device (TIMR)"); 332 dsdt_line("{"); 333 dsdt_line(" Name (_HID, EisaId (\"PNP0100\"))"); 334 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 335 dsdt_line(" {"); 336 dsdt_indent(2); 337 dsdt_fixed_ioport(IO_TIMER1_PORT, 4); 338 dsdt_fixed_irq(0); 339 dsdt_unindent(2); 340 dsdt_line(" })"); 341 dsdt_line("}"); 342 dsdt_unindent(1); 343 344 dsdt_line("}"); 345 } 346 347 static void 348 pci_lpc_sysres_dsdt(void) 349 { 350 struct lpc_sysres **lspp, *lsp; 351 352 dsdt_line(""); 353 dsdt_line("Device (SIO)"); 354 dsdt_line("{"); 355 dsdt_line(" Name (_HID, EisaId (\"PNP0C02\"))"); 356 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 357 dsdt_line(" {"); 358 359 dsdt_indent(2); 360 SET_FOREACH(lspp, lpc_sysres_set) { 361 lsp = *lspp; 362 switch (lsp->type) { 363 case LPC_SYSRES_IO: 364 dsdt_fixed_ioport(lsp->base, lsp->length); 365 break; 366 case LPC_SYSRES_MEM: 367 dsdt_fixed_mem32(lsp->base, lsp->length); 368 break; 369 } 370 } 371 dsdt_unindent(2); 372 373 dsdt_line(" })"); 374 dsdt_line("}"); 375 } 376 LPC_DSDT(pci_lpc_sysres_dsdt); 377 378 static void 379 pci_lpc_uart_dsdt(void) 380 { 381 struct lpc_uart_softc *sc; 382 int unit; 383 384 for (unit = 0; unit < LPC_UART_NUM; unit++) { 385 sc = &lpc_uart_softc[unit]; 386 if (!sc->enabled) 387 continue; 388 dsdt_line(""); 389 dsdt_line("Device (%s)", lpc_uart_acpi_names[unit]); 390 dsdt_line("{"); 391 dsdt_line(" Name (_HID, EisaId (\"PNP0501\"))"); 392 dsdt_line(" Name (_UID, %d)", unit + 1); 393 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 394 dsdt_line(" {"); 395 dsdt_indent(2); 396 dsdt_fixed_ioport(sc->iobase, UART_IO_BAR_SIZE); 397 dsdt_fixed_irq(sc->irq); 398 dsdt_unindent(2); 399 dsdt_line(" })"); 400 dsdt_line("}"); 401 } 402 } 403 LPC_DSDT(pci_lpc_uart_dsdt); 404 405 static int 406 pci_lpc_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 407 int coff, int bytes, uint32_t val) 408 { 409 int pirq_pin; 410 411 if (bytes == 1) { 412 pirq_pin = 0; 413 if (coff >= 0x60 && coff <= 0x63) 414 pirq_pin = coff - 0x60 + 1; 415 if (coff >= 0x68 && coff <= 0x6b) 416 pirq_pin = coff - 0x68 + 5; 417 if (pirq_pin != 0) { 418 pirq_write(ctx, pirq_pin, val); 419 pci_set_cfgdata8(pi, coff, pirq_read(pirq_pin)); 420 return (0); 421 } 422 } 423 return (-1); 424 } 425 426 static void 427 pci_lpc_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 428 int baridx, uint64_t offset, int size, uint64_t value) 429 { 430 } 431 432 static uint64_t 433 pci_lpc_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 434 int baridx, uint64_t offset, int size) 435 { 436 return (0); 437 } 438 439 #define LPC_DEV 0x7000 440 #define LPC_VENDOR 0x8086 441 442 static int 443 pci_lpc_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) 444 { 445 446 /* 447 * Do not allow more than one LPC bridge to be configured. 448 */ 449 if (lpc_bridge != NULL) { 450 EPRINTLN("Only one LPC bridge is allowed."); 451 return (-1); 452 } 453 454 /* 455 * Enforce that the LPC can only be configured on bus 0. This 456 * simplifies the ACPI DSDT because it can provide a decode for 457 * all legacy i/o ports behind bus 0. 458 */ 459 if (pi->pi_bus != 0) { 460 EPRINTLN("LPC bridge can be present only on bus 0."); 461 return (-1); 462 } 463 464 if (lpc_init(ctx) != 0) 465 return (-1); 466 467 /* initialize config space */ 468 pci_set_cfgdata16(pi, PCIR_DEVICE, LPC_DEV); 469 pci_set_cfgdata16(pi, PCIR_VENDOR, LPC_VENDOR); 470 pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_BRIDGE); 471 pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_BRIDGE_ISA); 472 473 lpc_bridge = pi; 474 475 return (0); 476 } 477 478 char * 479 lpc_pirq_name(int pin) 480 { 481 char *name; 482 483 if (lpc_bridge == NULL) 484 return (NULL); 485 asprintf(&name, "\\_SB.PC00.ISA.LNK%c,", 'A' + pin - 1); 486 return (name); 487 } 488 489 void 490 lpc_pirq_routed(void) 491 { 492 int pin; 493 494 if (lpc_bridge == NULL) 495 return; 496 497 for (pin = 0; pin < 4; pin++) 498 pci_set_cfgdata8(lpc_bridge, 0x60 + pin, pirq_read(pin + 1)); 499 for (pin = 0; pin < 4; pin++) 500 pci_set_cfgdata8(lpc_bridge, 0x68 + pin, pirq_read(pin + 5)); 501 } 502 503 struct pci_devemu pci_de_lpc = { 504 .pe_emu = "lpc", 505 .pe_init = pci_lpc_init, 506 .pe_write_dsdt = pci_lpc_write_dsdt, 507 .pe_cfgwrite = pci_lpc_cfgwrite, 508 .pe_barwrite = pci_lpc_write, 509 .pe_barread = pci_lpc_read 510 }; 511 PCI_EMUL_SET(pci_de_lpc); 512