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 "inout.h" 52 #include "pci_emul.h" 53 #include "pci_irq.h" 54 #include "pci_lpc.h" 55 #include "uart_emul.h" 56 57 #define IO_ICU1 0x20 58 #define IO_ICU2 0xA0 59 60 SET_DECLARE(lpc_dsdt_set, struct lpc_dsdt); 61 SET_DECLARE(lpc_sysres_set, struct lpc_sysres); 62 63 #define ELCR_PORT 0x4d0 64 SYSRES_IO(ELCR_PORT, 2); 65 66 #define IO_TIMER1_PORT 0x40 67 68 #define NMISC_PORT 0x61 69 SYSRES_IO(NMISC_PORT, 1); 70 71 static struct pci_devinst *lpc_bridge; 72 73 static const char *romfile; 74 75 #define LPC_UART_NUM 2 76 static struct lpc_uart_softc { 77 struct uart_softc *uart_softc; 78 const char *opts; 79 int iobase; 80 int irq; 81 int enabled; 82 } lpc_uart_softc[LPC_UART_NUM]; 83 84 static const char *lpc_uart_names[LPC_UART_NUM] = { "COM1", "COM2" }; 85 86 /* 87 * LPC device configuration is in the following form: 88 * <lpc_device_name>[,<options>] 89 * For e.g. "com1,stdio" or "bootrom,/var/romfile" 90 */ 91 int 92 lpc_device_parse(const char *opts) 93 { 94 int unit, error; 95 char *str, *cpy, *lpcdev; 96 97 error = -1; 98 str = cpy = strdup(opts); 99 lpcdev = strsep(&str, ","); 100 if (lpcdev != NULL) { 101 if (strcasecmp(lpcdev, "bootrom") == 0) { 102 romfile = str; 103 error = 0; 104 goto done; 105 } 106 for (unit = 0; unit < LPC_UART_NUM; unit++) { 107 if (strcasecmp(lpcdev, lpc_uart_names[unit]) == 0) { 108 lpc_uart_softc[unit].opts = str; 109 error = 0; 110 goto done; 111 } 112 } 113 } 114 115 done: 116 if (error) 117 free(cpy); 118 119 return (error); 120 } 121 122 void 123 lpc_print_supported_devices() 124 { 125 size_t i; 126 127 printf("bootrom\n"); 128 for (i = 0; i < LPC_UART_NUM; i++) 129 printf("%s\n", lpc_uart_names[i]); 130 } 131 132 const char * 133 lpc_bootrom(void) 134 { 135 136 return (romfile); 137 } 138 139 static void 140 lpc_uart_intr_assert(void *arg) 141 { 142 struct lpc_uart_softc *sc = arg; 143 144 assert(sc->irq >= 0); 145 146 vm_isa_pulse_irq(lpc_bridge->pi_vmctx, sc->irq, sc->irq); 147 } 148 149 static void 150 lpc_uart_intr_deassert(void *arg) 151 { 152 /* 153 * The COM devices on the LPC bus generate edge triggered interrupts, 154 * so nothing more to do here. 155 */ 156 } 157 158 static int 159 lpc_uart_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 160 uint32_t *eax, void *arg) 161 { 162 int offset; 163 struct lpc_uart_softc *sc = arg; 164 165 offset = port - sc->iobase; 166 167 switch (bytes) { 168 case 1: 169 if (in) 170 *eax = uart_read(sc->uart_softc, offset); 171 else 172 uart_write(sc->uart_softc, offset, *eax); 173 break; 174 case 2: 175 if (in) { 176 *eax = uart_read(sc->uart_softc, offset); 177 *eax |= uart_read(sc->uart_softc, offset + 1) << 8; 178 } else { 179 uart_write(sc->uart_softc, offset, *eax); 180 uart_write(sc->uart_softc, offset + 1, *eax >> 8); 181 } 182 break; 183 #ifndef __FreeBSD__ 184 case 4: 185 if (in) { 186 *eax = uart_read(sc->uart_softc, offset); 187 *eax |= uart_read(sc->uart_softc, offset + 1) << 8; 188 *eax |= uart_read(sc->uart_softc, offset + 2) << 16; 189 *eax |= uart_read(sc->uart_softc, offset + 3) << 24; 190 } else { 191 uart_write(sc->uart_softc, offset, *eax); 192 uart_write(sc->uart_softc, offset + 1, *eax >> 8); 193 uart_write(sc->uart_softc, offset + 2, *eax >> 16); 194 uart_write(sc->uart_softc, offset + 3, *eax >> 24); 195 } 196 break; 197 #endif 198 default: 199 return (-1); 200 } 201 202 return (0); 203 } 204 205 static int 206 lpc_init(struct vmctx *ctx) 207 { 208 struct lpc_uart_softc *sc; 209 struct inout_port iop; 210 const char *name; 211 int unit, error; 212 213 if (romfile != NULL) { 214 error = bootrom_loadrom(ctx, romfile); 215 if (error) 216 return (error); 217 } 218 219 /* COM1 and COM2 */ 220 for (unit = 0; unit < LPC_UART_NUM; unit++) { 221 sc = &lpc_uart_softc[unit]; 222 name = lpc_uart_names[unit]; 223 224 if (uart_legacy_alloc(unit, &sc->iobase, &sc->irq) != 0) { 225 EPRINTLN("Unable to allocate resources for " 226 "LPC device %s", name); 227 return (-1); 228 } 229 pci_irq_reserve(sc->irq); 230 231 sc->uart_softc = uart_init(lpc_uart_intr_assert, 232 lpc_uart_intr_deassert, sc); 233 234 if (uart_set_backend(sc->uart_softc, sc->opts) != 0) { 235 EPRINTLN("Unable to initialize backend '%s' " 236 "for LPC device %s", sc->opts, name); 237 return (-1); 238 } 239 240 bzero(&iop, sizeof(struct inout_port)); 241 iop.name = name; 242 iop.port = sc->iobase; 243 iop.size = UART_IO_BAR_SIZE; 244 iop.flags = IOPORT_F_INOUT; 245 iop.handler = lpc_uart_io_handler; 246 iop.arg = sc; 247 248 error = register_inout(&iop); 249 assert(error == 0); 250 sc->enabled = 1; 251 } 252 253 return (0); 254 } 255 256 static void 257 pci_lpc_write_dsdt(struct pci_devinst *pi) 258 { 259 struct lpc_dsdt **ldpp, *ldp; 260 261 dsdt_line(""); 262 dsdt_line("Device (ISA)"); 263 dsdt_line("{"); 264 dsdt_line(" Name (_ADR, 0x%04X%04X)", pi->pi_slot, pi->pi_func); 265 dsdt_line(" OperationRegion (LPCR, PCI_Config, 0x00, 0x100)"); 266 dsdt_line(" Field (LPCR, AnyAcc, NoLock, Preserve)"); 267 dsdt_line(" {"); 268 dsdt_line(" Offset (0x60),"); 269 dsdt_line(" PIRA, 8,"); 270 dsdt_line(" PIRB, 8,"); 271 dsdt_line(" PIRC, 8,"); 272 dsdt_line(" PIRD, 8,"); 273 dsdt_line(" Offset (0x68),"); 274 dsdt_line(" PIRE, 8,"); 275 dsdt_line(" PIRF, 8,"); 276 dsdt_line(" PIRG, 8,"); 277 dsdt_line(" PIRH, 8"); 278 dsdt_line(" }"); 279 dsdt_line(""); 280 281 dsdt_indent(1); 282 SET_FOREACH(ldpp, lpc_dsdt_set) { 283 ldp = *ldpp; 284 ldp->handler(); 285 } 286 287 dsdt_line(""); 288 dsdt_line("Device (PIC)"); 289 dsdt_line("{"); 290 dsdt_line(" Name (_HID, EisaId (\"PNP0000\"))"); 291 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 292 dsdt_line(" {"); 293 dsdt_indent(2); 294 dsdt_fixed_ioport(IO_ICU1, 2); 295 dsdt_fixed_ioport(IO_ICU2, 2); 296 dsdt_fixed_irq(2); 297 dsdt_unindent(2); 298 dsdt_line(" })"); 299 dsdt_line("}"); 300 301 dsdt_line(""); 302 dsdt_line("Device (TIMR)"); 303 dsdt_line("{"); 304 dsdt_line(" Name (_HID, EisaId (\"PNP0100\"))"); 305 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 306 dsdt_line(" {"); 307 dsdt_indent(2); 308 dsdt_fixed_ioport(IO_TIMER1_PORT, 4); 309 dsdt_fixed_irq(0); 310 dsdt_unindent(2); 311 dsdt_line(" })"); 312 dsdt_line("}"); 313 dsdt_unindent(1); 314 315 dsdt_line("}"); 316 } 317 318 static void 319 pci_lpc_sysres_dsdt(void) 320 { 321 struct lpc_sysres **lspp, *lsp; 322 323 dsdt_line(""); 324 dsdt_line("Device (SIO)"); 325 dsdt_line("{"); 326 dsdt_line(" Name (_HID, EisaId (\"PNP0C02\"))"); 327 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 328 dsdt_line(" {"); 329 330 dsdt_indent(2); 331 SET_FOREACH(lspp, lpc_sysres_set) { 332 lsp = *lspp; 333 switch (lsp->type) { 334 case LPC_SYSRES_IO: 335 dsdt_fixed_ioport(lsp->base, lsp->length); 336 break; 337 case LPC_SYSRES_MEM: 338 dsdt_fixed_mem32(lsp->base, lsp->length); 339 break; 340 } 341 } 342 dsdt_unindent(2); 343 344 dsdt_line(" })"); 345 dsdt_line("}"); 346 } 347 LPC_DSDT(pci_lpc_sysres_dsdt); 348 349 static void 350 pci_lpc_uart_dsdt(void) 351 { 352 struct lpc_uart_softc *sc; 353 int unit; 354 355 for (unit = 0; unit < LPC_UART_NUM; unit++) { 356 sc = &lpc_uart_softc[unit]; 357 if (!sc->enabled) 358 continue; 359 dsdt_line(""); 360 dsdt_line("Device (%s)", lpc_uart_names[unit]); 361 dsdt_line("{"); 362 dsdt_line(" Name (_HID, EisaId (\"PNP0501\"))"); 363 dsdt_line(" Name (_UID, %d)", unit + 1); 364 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 365 dsdt_line(" {"); 366 dsdt_indent(2); 367 dsdt_fixed_ioport(sc->iobase, UART_IO_BAR_SIZE); 368 dsdt_fixed_irq(sc->irq); 369 dsdt_unindent(2); 370 dsdt_line(" })"); 371 dsdt_line("}"); 372 } 373 } 374 LPC_DSDT(pci_lpc_uart_dsdt); 375 376 static int 377 pci_lpc_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 378 int coff, int bytes, uint32_t val) 379 { 380 int pirq_pin; 381 382 if (bytes == 1) { 383 pirq_pin = 0; 384 if (coff >= 0x60 && coff <= 0x63) 385 pirq_pin = coff - 0x60 + 1; 386 if (coff >= 0x68 && coff <= 0x6b) 387 pirq_pin = coff - 0x68 + 5; 388 if (pirq_pin != 0) { 389 pirq_write(ctx, pirq_pin, val); 390 pci_set_cfgdata8(pi, coff, pirq_read(pirq_pin)); 391 return (0); 392 } 393 } 394 return (-1); 395 } 396 397 static void 398 pci_lpc_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 399 int baridx, uint64_t offset, int size, uint64_t value) 400 { 401 } 402 403 static uint64_t 404 pci_lpc_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 405 int baridx, uint64_t offset, int size) 406 { 407 return (0); 408 } 409 410 #define LPC_DEV 0x7000 411 #define LPC_VENDOR 0x8086 412 413 static int 414 pci_lpc_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) 415 { 416 417 /* 418 * Do not allow more than one LPC bridge to be configured. 419 */ 420 if (lpc_bridge != NULL) { 421 EPRINTLN("Only one LPC bridge is allowed."); 422 return (-1); 423 } 424 425 /* 426 * Enforce that the LPC can only be configured on bus 0. This 427 * simplifies the ACPI DSDT because it can provide a decode for 428 * all legacy i/o ports behind bus 0. 429 */ 430 if (pi->pi_bus != 0) { 431 EPRINTLN("LPC bridge can be present only on bus 0."); 432 return (-1); 433 } 434 435 if (lpc_init(ctx) != 0) 436 return (-1); 437 438 /* initialize config space */ 439 pci_set_cfgdata16(pi, PCIR_DEVICE, LPC_DEV); 440 pci_set_cfgdata16(pi, PCIR_VENDOR, LPC_VENDOR); 441 pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_BRIDGE); 442 pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_BRIDGE_ISA); 443 444 lpc_bridge = pi; 445 446 return (0); 447 } 448 449 char * 450 lpc_pirq_name(int pin) 451 { 452 char *name; 453 454 if (lpc_bridge == NULL) 455 return (NULL); 456 asprintf(&name, "\\_SB.PC00.ISA.LNK%c,", 'A' + pin - 1); 457 return (name); 458 } 459 460 void 461 lpc_pirq_routed(void) 462 { 463 int pin; 464 465 if (lpc_bridge == NULL) 466 return; 467 468 for (pin = 0; pin < 4; pin++) 469 pci_set_cfgdata8(lpc_bridge, 0x60 + pin, pirq_read(pin + 1)); 470 for (pin = 0; pin < 4; pin++) 471 pci_set_cfgdata8(lpc_bridge, 0x68 + pin, pirq_read(pin + 5)); 472 } 473 474 struct pci_devemu pci_de_lpc = { 475 .pe_emu = "lpc", 476 .pe_init = pci_lpc_init, 477 .pe_write_dsdt = pci_lpc_write_dsdt, 478 .pe_cfgwrite = pci_lpc_cfgwrite, 479 .pe_barwrite = pci_lpc_write, 480 .pe_barread = pci_lpc_read 481 }; 482 PCI_EMUL_SET(pci_de_lpc); 483