1 /*- 2 * Copyright (C) 2011,2015 by Nathan Whitehorn. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 17 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 19 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 21 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include <sys/cdefs.h> 26 #include <sys/endian.h> 27 #include <sys/param.h> 28 #include <sys/conf.h> 29 #include <sys/cons.h> 30 #include <sys/kdb.h> 31 #include <sys/kernel.h> 32 #include <sys/lock.h> 33 #include <sys/module.h> 34 #include <sys/mutex.h> 35 #include <sys/priv.h> 36 #include <sys/proc.h> 37 #include <sys/systm.h> 38 #include <sys/tty.h> 39 40 #include <vm/vm.h> 41 #include <vm/pmap.h> 42 43 #include <machine/bus.h> 44 45 #include <dev/ofw/openfirm.h> 46 #include <dev/ofw/ofw_bus.h> 47 #include <dev/ofw/ofw_bus_subr.h> 48 #include <dev/uart/uart.h> 49 #include <dev/uart/uart_cpu.h> 50 #include <dev/uart/uart_bus.h> 51 52 #include "opal.h" 53 #include "uart_if.h" 54 55 struct uart_opal_softc { 56 device_t dev; 57 phandle_t node; 58 int vtermid; 59 60 struct tty *tp; 61 struct resource *irqres; 62 int irqrid; 63 struct callout callout; 64 void *sc_icookie; 65 int polltime; 66 67 struct mtx sc_mtx; 68 int protocol; 69 70 char opal_inbuf[16]; 71 uint64_t inbuflen; 72 uint8_t outseqno; 73 #if defined(KDB) 74 int alt_break_state; 75 #endif 76 }; 77 78 static struct uart_opal_softc *console_sc = NULL; 79 static struct consdev *stdout_cp; 80 81 enum { 82 OPAL_RAW, OPAL_HVSI 83 }; 84 85 #define VS_DATA_PACKET_HEADER 0xff 86 #define VS_CONTROL_PACKET_HEADER 0xfe 87 #define VSV_SET_MODEM_CTL 0x01 88 #define VSV_MODEM_CTL_UPDATE 0x02 89 #define VSV_RENEGOTIATE_CONNECTION 0x03 90 #define VS_QUERY_PACKET_HEADER 0xfd 91 #define VSV_SEND_VERSION_NUMBER 0x01 92 #define VSV_SEND_MODEM_CTL_STATUS 0x02 93 #define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc 94 95 static int uart_opal_probe(device_t dev); 96 static int uart_opal_attach(device_t dev); 97 static void uart_opal_intr(void *v); 98 99 static device_method_t uart_opal_methods[] = { 100 /* Device interface */ 101 DEVMETHOD(device_probe, uart_opal_probe), 102 DEVMETHOD(device_attach, uart_opal_attach), 103 104 DEVMETHOD_END 105 }; 106 107 static driver_t uart_opal_driver = { 108 "uart", 109 uart_opal_methods, 110 sizeof(struct uart_opal_softc), 111 }; 112 113 DRIVER_MODULE(uart_opal, opalcons, uart_opal_driver, 0, 0); 114 115 static int uart_opal_getc(struct uart_opal_softc *sc); 116 static cn_probe_t uart_opal_cnprobe; 117 static cn_init_t uart_opal_cninit; 118 static cn_term_t uart_opal_cnterm; 119 static cn_getc_t uart_opal_cngetc; 120 static cn_putc_t uart_opal_cnputc; 121 static cn_grab_t uart_opal_cngrab; 122 static cn_ungrab_t uart_opal_cnungrab; 123 124 CONSOLE_DRIVER(uart_opal); 125 126 static void uart_opal_ttyoutwakeup(struct tty *tp); 127 128 static struct ttydevsw uart_opal_tty_class = { 129 .tsw_flags = TF_INITLOCK|TF_CALLOUT, 130 .tsw_outwakeup = uart_opal_ttyoutwakeup, 131 }; 132 133 static struct { 134 char tmpbuf[16]; 135 uint64_t size; 136 struct mtx mtx; 137 } opalcons_buffer; 138 139 static void 140 uart_opal_real_map_outbuffer(uint64_t *bufferp, uint64_t *lenp) 141 { 142 143 if (!mtx_initialized(&opalcons_buffer.mtx)) 144 mtx_init(&opalcons_buffer.mtx, "uart_opal", NULL, 145 MTX_SPIN | MTX_QUIET | MTX_NOWITNESS); 146 147 if (!pmap_bootstrapped) 148 return; 149 150 mtx_lock_spin(&opalcons_buffer.mtx); 151 152 opalcons_buffer.size = *(uint64_t *)(*lenp) = 153 min(sizeof(opalcons_buffer.tmpbuf), *(uint64_t *)(*lenp)); 154 memcpy(opalcons_buffer.tmpbuf, (void *)(*bufferp), 155 *(uint64_t *)(*lenp)); 156 *bufferp = (uint64_t)opalcons_buffer.tmpbuf; 157 *lenp = (uint64_t)&opalcons_buffer.size; 158 } 159 160 static void 161 uart_opal_real_unmap_outbuffer(uint64_t *len) 162 { 163 164 if (!pmap_bootstrapped) 165 return; 166 167 mtx_assert(&opalcons_buffer.mtx, MA_OWNED); 168 *len = opalcons_buffer.size; 169 mtx_unlock_spin(&opalcons_buffer.mtx); 170 } 171 172 static int64_t 173 uart_opal_console_write_buffer_space(int vtermid) 174 { 175 int64_t buffer_space_val = 0; 176 vm_paddr_t buffer_space_ptr; 177 178 if (pmap_bootstrapped) 179 buffer_space_ptr = vtophys(&buffer_space_val); 180 else 181 buffer_space_ptr = (vm_paddr_t)&buffer_space_val; 182 183 if (opal_call(OPAL_CONSOLE_WRITE_BUFFER_SPACE, vtermid, 184 buffer_space_ptr) != OPAL_SUCCESS) 185 return (-1); 186 187 return (be64toh(buffer_space_val)); 188 } 189 190 static int 191 uart_opal_probe_node(struct uart_opal_softc *sc) 192 { 193 phandle_t node = sc->node; 194 uint32_t reg; 195 char buf[64]; 196 197 sc->inbuflen = 0; 198 sc->outseqno = 0; 199 200 if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0) 201 return (ENXIO); 202 if (strcmp(buf, "serial") != 0) 203 return (ENXIO); 204 205 reg = -1; 206 OF_getencprop(node, "reg", ®, sizeof(reg)); 207 if (reg == -1) 208 return (ENXIO); 209 sc->vtermid = reg; 210 sc->node = node; 211 212 if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0) 213 return (ENXIO); 214 if (strcmp(buf, "ibm,opal-console-raw") == 0) { 215 sc->protocol = OPAL_RAW; 216 return (0); 217 } else if (strcmp(buf, "ibm,opal-console-hvsi") == 0) { 218 sc->protocol = OPAL_HVSI; 219 return (0); 220 } 221 222 return (ENXIO); 223 } 224 225 static int 226 uart_opal_probe(device_t dev) 227 { 228 struct uart_opal_softc sc; 229 int err; 230 231 sc.node = ofw_bus_get_node(dev); 232 err = uart_opal_probe_node(&sc); 233 if (err != 0) 234 return (err); 235 236 device_set_desc(dev, "OPAL Serial Port"); 237 238 return (err); 239 } 240 241 static void 242 uart_opal_cnprobe(struct consdev *cp) 243 { 244 char buf[64]; 245 phandle_t input, chosen; 246 static struct uart_opal_softc sc; 247 248 if (opal_check() != 0) 249 goto fail; 250 251 if ((chosen = OF_finddevice("/chosen")) == -1) 252 goto fail; 253 254 /* Check if OF has an active stdin/stdout */ 255 if (OF_getprop(chosen, "linux,stdout-path", buf, sizeof(buf)) <= 0) 256 goto fail; 257 258 input = OF_finddevice(buf); 259 if (input == -1) 260 goto fail; 261 262 sc.node = input; 263 if (uart_opal_probe_node(&sc) != 0) 264 goto fail; 265 mtx_init(&sc.sc_mtx, "uart_opal", NULL, MTX_SPIN | MTX_QUIET | 266 MTX_NOWITNESS); 267 268 cp->cn_pri = CN_NORMAL; 269 console_sc = ≻ 270 cp->cn_arg = console_sc; 271 stdout_cp = cp; 272 return; 273 274 fail: 275 cp->cn_pri = CN_DEAD; 276 return; 277 } 278 279 static int 280 uart_opal_attach(device_t dev) 281 { 282 struct uart_opal_softc *sc; 283 int unit; 284 285 sc = device_get_softc(dev); 286 sc->node = ofw_bus_get_node(dev); 287 uart_opal_probe_node(sc); 288 289 unit = device_get_unit(dev); 290 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, 291 MTX_SPIN | MTX_QUIET | MTX_NOWITNESS); 292 293 if (console_sc != NULL && console_sc->vtermid == sc->vtermid) { 294 device_printf(dev, "console\n"); 295 device_set_softc(dev, console_sc); 296 sc = console_sc; 297 sprintf(uart_opal_consdev.cn_name, "ttyu%r", unit); 298 } 299 sc->tp = tty_alloc(&uart_opal_tty_class, sc); 300 301 if (console_sc == sc) 302 tty_init_console(sc->tp, 0); 303 304 sc->dev = dev; 305 sc->irqrid = 0; 306 sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid, 307 RF_ACTIVE | RF_SHAREABLE); 308 if (sc->irqres != NULL) { 309 bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE, 310 NULL, uart_opal_intr, sc, &sc->sc_icookie); 311 } else { 312 callout_init(&sc->callout, CALLOUT_MPSAFE); 313 sc->polltime = hz / 20; 314 if (sc->polltime < 1) 315 sc->polltime = 1; 316 callout_reset(&sc->callout, sc->polltime, uart_opal_intr, sc); 317 } 318 319 tty_makedev(sc->tp, NULL, "u%r", unit); 320 321 return (0); 322 } 323 324 static void 325 uart_opal_cninit(struct consdev *cp) 326 { 327 328 strcpy(cp->cn_name, "opalcons"); 329 } 330 331 static void 332 uart_opal_cnterm(struct consdev *cp) 333 { 334 } 335 336 static int 337 uart_opal_get(struct uart_opal_softc *sc, void *buffer, size_t bufsize) 338 { 339 int err; 340 int hdr = 0; 341 342 if (sc->protocol == OPAL_RAW) { 343 uint64_t len = htobe64(bufsize); 344 uint64_t olen = (uint64_t)&len; 345 uint64_t obuf = (uint64_t)buffer; 346 347 if (pmap_bootstrapped) { 348 olen = vtophys(&len); 349 obuf = vtophys(buffer); 350 } 351 352 err = opal_call(OPAL_CONSOLE_READ, sc->vtermid, olen, obuf); 353 if (err != OPAL_SUCCESS) 354 return (-1); 355 356 bufsize = be64toh(len); 357 } else { 358 uart_lock(&sc->sc_mtx); 359 if (sc->inbuflen == 0) { 360 err = opal_call(OPAL_CONSOLE_READ, sc->vtermid, 361 &sc->inbuflen, sc->opal_inbuf); 362 if (err != OPAL_SUCCESS) { 363 uart_unlock(&sc->sc_mtx); 364 return (-1); 365 } 366 hdr = 1; 367 sc->inbuflen = be64toh(sc->inbuflen); 368 } 369 370 if (sc->inbuflen == 0) { 371 uart_unlock(&sc->sc_mtx); 372 return (0); 373 } 374 375 if (bufsize > sc->inbuflen) 376 bufsize = sc->inbuflen; 377 378 if (hdr == 1) { 379 sc->inbuflen = sc->inbuflen - 4; 380 /* The HVSI protocol has a 4 byte header, skip it */ 381 memmove(&sc->opal_inbuf[0], &sc->opal_inbuf[4], 382 sc->inbuflen); 383 } 384 385 memcpy(buffer, sc->opal_inbuf, bufsize); 386 sc->inbuflen -= bufsize; 387 if (sc->inbuflen > 0) 388 memmove(&sc->opal_inbuf[0], &sc->opal_inbuf[bufsize], 389 sc->inbuflen); 390 391 uart_unlock(&sc->sc_mtx); 392 } 393 394 return (bufsize); 395 } 396 397 static int 398 uart_opal_put(struct uart_opal_softc *sc, void *buffer, size_t bufsize) 399 { 400 uint16_t seqno; 401 uint64_t len; 402 char cbuf[16]; 403 int err; 404 uint64_t olen = (uint64_t)&len; 405 uint64_t obuf = (uint64_t)cbuf; 406 407 if (sc->protocol == OPAL_RAW) { 408 obuf = (uint64_t)buffer; 409 len = bufsize; 410 411 uart_opal_real_map_outbuffer(&obuf, &olen); 412 *(uint64_t*)olen = htobe64(*(uint64_t*)olen); 413 err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); 414 *(uint64_t*)olen = be64toh(*(uint64_t*)olen); 415 uart_opal_real_unmap_outbuffer(&len); 416 } else { 417 uart_lock(&sc->sc_mtx); 418 if (bufsize > 12) 419 bufsize = 12; 420 seqno = sc->outseqno++; 421 cbuf[0] = VS_DATA_PACKET_HEADER; 422 cbuf[1] = 4 + bufsize; /* total length */ 423 cbuf[2] = (seqno >> 8) & 0xff; 424 cbuf[3] = seqno & 0xff; 425 memcpy(&cbuf[4], buffer, bufsize); 426 len = 4 + bufsize; 427 428 uart_opal_real_map_outbuffer(&obuf, &olen); 429 *(uint64_t*)olen = htobe64(*(uint64_t*)olen); 430 err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); 431 *(uint64_t*)olen = be64toh(*(uint64_t*)olen); 432 uart_opal_real_unmap_outbuffer(&len); 433 434 uart_unlock(&sc->sc_mtx); 435 436 len -= 4; 437 } 438 439 if (err == OPAL_SUCCESS) 440 return (len); 441 else if (err == OPAL_BUSY_EVENT) 442 return(0); 443 444 return (-1); 445 } 446 447 static int 448 uart_opal_cngetc(struct consdev *cp) 449 { 450 return (uart_opal_getc(cp->cn_arg)); 451 } 452 453 static int 454 uart_opal_getc(struct uart_opal_softc *sc) 455 { 456 unsigned char c; 457 int retval; 458 459 retval = uart_opal_get(sc, &c, 1); 460 if (retval != 1) 461 return (-1); 462 #if defined(KDB) 463 kdb_alt_break(c, &sc->alt_break_state); 464 #endif 465 466 return (c); 467 } 468 469 static void 470 uart_opal_cnputc(struct consdev *cp, int c) 471 { 472 unsigned char ch = c; 473 int a; 474 475 if (1) { 476 /* Clear FIFO if needed. Must be repeated few times. */ 477 for (a = 0; a < 20; a++) { 478 opal_call(OPAL_POLL_EVENTS, NULL); 479 } 480 } 481 uart_opal_put(cp->cn_arg, &ch, 1); 482 } 483 484 static void 485 uart_opal_cngrab(struct consdev *cp) 486 { 487 } 488 489 static void 490 uart_opal_cnungrab(struct consdev *cp) 491 { 492 } 493 494 static void 495 uart_opal_ttyoutwakeup(struct tty *tp) 496 { 497 struct uart_opal_softc *sc; 498 char buffer[8]; 499 int len; 500 int64_t buffer_space; 501 502 sc = tty_softc(tp); 503 504 while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0) { 505 int bytes_written = 0; 506 while (bytes_written == 0) { 507 buffer_space = uart_opal_console_write_buffer_space(sc->vtermid); 508 if (buffer_space == -1) 509 /* OPAL failure or invalid terminal */ 510 break; 511 else if (buffer_space >= len) 512 bytes_written = uart_opal_put(sc, buffer, len); 513 514 if (bytes_written == 0) 515 /* OPAL must be busy, poll and retry */ 516 opal_call(OPAL_POLL_EVENTS, NULL); 517 else if (bytes_written == -1) 518 /* OPAL failure or invalid terminal */ 519 break; 520 } 521 } 522 } 523 524 static void 525 uart_opal_intr(void *v) 526 { 527 struct uart_opal_softc *sc = v; 528 struct tty *tp = sc->tp; 529 int c; 530 531 tty_lock(tp); 532 while ((c = uart_opal_getc(sc)) > 0) 533 ttydisc_rint(tp, c, 0); 534 ttydisc_rint_done(tp); 535 tty_unlock(tp); 536 537 opal_call(OPAL_POLL_EVENTS, NULL); 538 539 if (sc->irqres == NULL) 540 callout_reset(&sc->callout, sc->polltime, uart_opal_intr, sc); 541 } 542 543 static int 544 opalcons_probe(device_t dev) 545 { 546 const char *name; 547 548 name = ofw_bus_get_name(dev); 549 if (name == NULL || strcmp(name, "consoles") != 0) 550 return (ENXIO); 551 552 device_set_desc(dev, "OPAL Consoles"); 553 return (BUS_PROBE_SPECIFIC); 554 } 555 556 static int 557 opalcons_attach(device_t dev) 558 { 559 phandle_t child; 560 device_t cdev; 561 struct ofw_bus_devinfo *dinfo; 562 563 for (child = OF_child(ofw_bus_get_node(dev)); child != 0; 564 child = OF_peer(child)) { 565 dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); 566 if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) { 567 free(dinfo, M_DEVBUF); 568 continue; 569 } 570 cdev = device_add_child(dev, NULL, -1); 571 if (cdev == NULL) { 572 device_printf(dev, "<%s>: device_add_child failed\n", 573 dinfo->obd_name); 574 ofw_bus_gen_destroy_devinfo(dinfo); 575 free(dinfo, M_DEVBUF); 576 continue; 577 } 578 device_set_ivars(cdev, dinfo); 579 } 580 581 return (bus_generic_attach(dev)); 582 } 583 584 static const struct ofw_bus_devinfo * 585 opalcons_get_devinfo(device_t dev, device_t child) 586 { 587 return (device_get_ivars(child)); 588 } 589 590 static device_method_t opalcons_methods[] = { 591 /* Device interface */ 592 DEVMETHOD(device_probe, opalcons_probe), 593 DEVMETHOD(device_attach, opalcons_attach), 594 595 /* ofw_bus interface */ 596 DEVMETHOD(ofw_bus_get_devinfo, opalcons_get_devinfo), 597 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 598 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 599 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 600 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 601 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 602 603 DEVMETHOD_END 604 }; 605 606 static driver_t opalcons_driver = { 607 "opalcons", 608 opalcons_methods, 609 0 610 }; 611 612 DRIVER_MODULE(opalcons, opal, opalcons_driver, 0, 0); 613