1 /*- 2 * Copyright (c) 2014, Bryan Venteicher <bryanv@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 /* Driver for VirtIO console devices. */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/malloc.h> 36 #include <sys/module.h> 37 #include <sys/lock.h> 38 #include <sys/mutex.h> 39 #include <sys/sglist.h> 40 #include <sys/sysctl.h> 41 #include <sys/taskqueue.h> 42 #include <sys/queue.h> 43 44 #include <sys/conf.h> 45 #include <sys/cons.h> 46 #include <sys/tty.h> 47 48 #include <machine/bus.h> 49 #include <machine/resource.h> 50 #include <sys/bus.h> 51 52 #include <dev/virtio/virtio.h> 53 #include <dev/virtio/virtqueue.h> 54 #include <dev/virtio/console/virtio_console.h> 55 56 #include "virtio_if.h" 57 58 #define VTCON_MAX_PORTS 1 59 #define VTCON_TTY_PREFIX "V" 60 #define VTCON_BULK_BUFSZ 128 61 62 struct vtcon_softc; 63 64 struct vtcon_port { 65 struct vtcon_softc *vtcport_sc; 66 TAILQ_ENTRY(vtcon_port) vtcport_next; 67 struct mtx vtcport_mtx; 68 int vtcport_id; 69 struct tty *vtcport_tty; 70 struct virtqueue *vtcport_invq; 71 struct virtqueue *vtcport_outvq; 72 char vtcport_name[16]; 73 }; 74 75 #define VTCON_PORT_MTX(_port) &(_port)->vtcport_mtx 76 #define VTCON_PORT_LOCK_INIT(_port) \ 77 mtx_init(VTCON_PORT_MTX((_port)), (_port)->vtcport_name, NULL, MTX_DEF) 78 #define VTCON_PORT_LOCK(_port) mtx_lock(VTCON_PORT_MTX((_port))) 79 #define VTCON_PORT_UNLOCK(_port) mtx_unlock(VTCON_PORT_MTX((_port))) 80 #define VTCON_PORT_LOCK_DESTROY(_port) mtx_destroy(VTCON_PORT_MTX((_port))) 81 #define VTCON_PORT_LOCK_ASSERT(_port) \ 82 mtx_assert(VTCON_PORT_MTX((_port)), MA_OWNED) 83 #define VTCON_PORT_LOCK_ASSERT_NOTOWNED(_port) \ 84 mtx_assert(VTCON_PORT_MTX((_port)), MA_NOTOWNED) 85 86 struct vtcon_softc { 87 device_t vtcon_dev; 88 struct mtx vtcon_mtx; 89 uint64_t vtcon_features; 90 uint32_t vtcon_flags; 91 #define VTCON_FLAG_DETACHED 0x0001 92 #define VTCON_FLAG_SIZE 0x0010 93 #define VTCON_FLAG_MULTIPORT 0x0020 94 95 struct task vtcon_ctrl_task; 96 struct virtqueue *vtcon_ctrl_rxvq; 97 struct virtqueue *vtcon_ctrl_txvq; 98 99 uint32_t vtcon_max_ports; 100 TAILQ_HEAD(, vtcon_port) 101 vtcon_ports; 102 103 /* 104 * Ports can be added and removed during runtime, but we have 105 * to allocate all the virtqueues during attach. This array is 106 * indexed by the port ID. 107 */ 108 struct vtcon_port_extra { 109 struct vtcon_port *port; 110 struct virtqueue *invq; 111 struct virtqueue *outvq; 112 } *vtcon_portsx; 113 }; 114 115 #define VTCON_MTX(_sc) &(_sc)->vtcon_mtx 116 #define VTCON_LOCK_INIT(_sc, _name) \ 117 mtx_init(VTCON_MTX((_sc)), (_name), NULL, MTX_DEF) 118 #define VTCON_LOCK(_sc) mtx_lock(VTCON_MTX((_sc))) 119 #define VTCON_UNLOCK(_sc) mtx_unlock(VTCON_MTX((_sc))) 120 #define VTCON_LOCK_DESTROY(_sc) mtx_destroy(VTCON_MTX((_sc))) 121 #define VTCON_LOCK_ASSERT(_sc) mtx_assert(VTCON_MTX((_sc)), MA_OWNED) 122 #define VTCON_LOCK_ASSERT_NOTOWNED(_sc) \ 123 mtx_assert(VTCON_MTX((_sc)), MA_NOTOWNED) 124 125 #define VTCON_ASSERT_VALID_PORTID(_sc, _id) \ 126 KASSERT((_id) >= 0 && (_id) < (_sc)->vtcon_max_ports, \ 127 ("%s: port ID %d out of range", __func__, _id)) 128 129 #define VTCON_FEATURES 0 130 131 static struct virtio_feature_desc vtcon_feature_desc[] = { 132 { VIRTIO_CONSOLE_F_SIZE, "ConsoleSize" }, 133 { VIRTIO_CONSOLE_F_MULTIPORT, "MultiplePorts" }, 134 135 { 0, NULL } 136 }; 137 138 static int vtcon_modevent(module_t, int, void *); 139 140 static int vtcon_probe(device_t); 141 static int vtcon_attach(device_t); 142 static int vtcon_detach(device_t); 143 static int vtcon_config_change(device_t); 144 145 static void vtcon_negotiate_features(struct vtcon_softc *); 146 static int vtcon_alloc_virtqueues(struct vtcon_softc *); 147 static void vtcon_read_config(struct vtcon_softc *, 148 struct virtio_console_config *); 149 150 static void vtcon_determine_max_ports(struct vtcon_softc *, 151 struct virtio_console_config *); 152 static void vtcon_deinit_ports(struct vtcon_softc *); 153 static void vtcon_stop(struct vtcon_softc *); 154 155 static void vtcon_ctrl_rx_vq_intr(void *); 156 static int vtcon_ctrl_enqueue_msg(struct vtcon_softc *, 157 struct virtio_console_control *); 158 static int vtcon_ctrl_add_msg(struct vtcon_softc *); 159 static void vtcon_ctrl_readd_msg(struct vtcon_softc *, 160 struct virtio_console_control *); 161 static int vtcon_ctrl_populate(struct vtcon_softc *); 162 static void vtcon_ctrl_send_msg(struct vtcon_softc *, 163 struct virtio_console_control *control); 164 static void vtcon_ctrl_send_event(struct vtcon_softc *, uint32_t, 165 uint16_t, uint16_t); 166 static int vtcon_ctrl_init(struct vtcon_softc *); 167 static void vtcon_ctrl_drain(struct vtcon_softc *); 168 static void vtcon_ctrl_deinit(struct vtcon_softc *); 169 static void vtcon_ctrl_port_add_event(struct vtcon_softc *, int); 170 static void vtcon_ctrl_port_remove_event(struct vtcon_softc *, int); 171 static void vtcon_ctrl_port_console_event(struct vtcon_softc *, int); 172 static void vtcon_ctrl_port_open_event(struct vtcon_softc *, int); 173 static void vtcon_ctrl_process_msg(struct vtcon_softc *, 174 struct virtio_console_control *); 175 static void vtcon_ctrl_task_cb(void *, int); 176 177 static int vtcon_port_add_inbuf(struct vtcon_port *); 178 static void vtcon_port_readd_inbuf(struct vtcon_port *, void *); 179 static int vtcon_port_populate(struct vtcon_port *); 180 static void vtcon_port_destroy(struct vtcon_port *); 181 static int vtcon_port_create(struct vtcon_softc *, int, 182 struct vtcon_port **); 183 static void vtcon_port_drain_inbufs(struct vtcon_port *); 184 static void vtcon_port_teardown(struct vtcon_port *, int); 185 static void vtcon_port_change_size(struct vtcon_port *, uint16_t, 186 uint16_t); 187 static void vtcon_port_enable_intr(struct vtcon_port *); 188 static void vtcon_port_disable_intr(struct vtcon_port *); 189 static void vtcon_port_intr(struct vtcon_port *); 190 static void vtcon_port_in_vq_intr(void *); 191 static void vtcon_port_put(struct vtcon_port *, void *, int); 192 static void vtcon_port_send_ctrl_msg(struct vtcon_port *, uint16_t, 193 uint16_t); 194 static struct vtcon_port *vtcon_port_lookup_by_id(struct vtcon_softc *, int); 195 196 static int vtcon_tty_open(struct tty *); 197 static void vtcon_tty_close(struct tty *); 198 static void vtcon_tty_outwakeup(struct tty *); 199 static void vtcon_tty_free(void *); 200 201 static void vtcon_get_console_size(struct vtcon_softc *, uint16_t *, 202 uint16_t *); 203 204 static void vtcon_enable_interrupts(struct vtcon_softc *); 205 static void vtcon_disable_interrupts(struct vtcon_softc *); 206 207 static int vtcon_pending_free; 208 209 static struct ttydevsw vtcon_tty_class = { 210 .tsw_flags = 0, 211 .tsw_open = vtcon_tty_open, 212 .tsw_close = vtcon_tty_close, 213 .tsw_outwakeup = vtcon_tty_outwakeup, 214 .tsw_free = vtcon_tty_free, 215 }; 216 217 static device_method_t vtcon_methods[] = { 218 /* Device methods. */ 219 DEVMETHOD(device_probe, vtcon_probe), 220 DEVMETHOD(device_attach, vtcon_attach), 221 DEVMETHOD(device_detach, vtcon_detach), 222 223 /* VirtIO methods. */ 224 DEVMETHOD(virtio_config_change, vtcon_config_change), 225 226 DEVMETHOD_END 227 }; 228 229 static driver_t vtcon_driver = { 230 "vtcon", 231 vtcon_methods, 232 sizeof(struct vtcon_softc) 233 }; 234 static devclass_t vtcon_devclass; 235 236 DRIVER_MODULE(virtio_console, virtio_pci, vtcon_driver, vtcon_devclass, 237 vtcon_modevent, 0); 238 MODULE_VERSION(virtio_console, 1); 239 MODULE_DEPEND(virtio_console, virtio, 1, 1, 1); 240 241 static int 242 vtcon_modevent(module_t mod, int type, void *unused) 243 { 244 int error; 245 246 switch (type) { 247 case MOD_LOAD: 248 error = 0; 249 break; 250 case MOD_QUIESCE: 251 case MOD_UNLOAD: 252 error = vtcon_pending_free != 0 ? EBUSY : 0; 253 /* error = EOPNOTSUPP; */ 254 break; 255 case MOD_SHUTDOWN: 256 error = 0; 257 break; 258 default: 259 error = EOPNOTSUPP; 260 break; 261 } 262 263 return (error); 264 } 265 266 static int 267 vtcon_probe(device_t dev) 268 { 269 270 if (virtio_get_device_type(dev) != VIRTIO_ID_CONSOLE) 271 return (ENXIO); 272 273 device_set_desc(dev, "VirtIO Console Adapter"); 274 275 return (BUS_PROBE_DEFAULT); 276 } 277 278 static int 279 vtcon_attach(device_t dev) 280 { 281 struct vtcon_softc *sc; 282 struct virtio_console_config concfg; 283 int error; 284 285 sc = device_get_softc(dev); 286 sc->vtcon_dev = dev; 287 288 VTCON_LOCK_INIT(sc, device_get_nameunit(dev)); 289 TASK_INIT(&sc->vtcon_ctrl_task, 0, vtcon_ctrl_task_cb, sc); 290 TAILQ_INIT(&sc->vtcon_ports); 291 292 virtio_set_feature_desc(dev, vtcon_feature_desc); 293 vtcon_negotiate_features(sc); 294 295 if (virtio_with_feature(dev, VIRTIO_CONSOLE_F_SIZE)) 296 sc->vtcon_flags |= VTCON_FLAG_SIZE; 297 if (virtio_with_feature(dev, VIRTIO_CONSOLE_F_MULTIPORT)) 298 sc->vtcon_flags |= VTCON_FLAG_MULTIPORT; 299 300 vtcon_read_config(sc, &concfg); 301 vtcon_determine_max_ports(sc, &concfg); 302 303 error = vtcon_alloc_virtqueues(sc); 304 if (error) { 305 device_printf(dev, "cannot allocate virtqueues\n"); 306 goto fail; 307 } 308 309 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) 310 error = vtcon_ctrl_init(sc); 311 else 312 error = vtcon_port_create(sc, 0, NULL); 313 if (error) 314 goto fail; 315 316 error = virtio_setup_intr(dev, INTR_TYPE_TTY); 317 if (error) { 318 device_printf(dev, "cannot setup virtqueue interrupts\n"); 319 goto fail; 320 } 321 322 vtcon_enable_interrupts(sc); 323 324 vtcon_ctrl_send_event(sc, VIRTIO_CONSOLE_BAD_ID, 325 VIRTIO_CONSOLE_DEVICE_READY, 1); 326 327 fail: 328 if (error) 329 vtcon_detach(dev); 330 331 return (error); 332 } 333 334 static int 335 vtcon_detach(device_t dev) 336 { 337 struct vtcon_softc *sc; 338 339 sc = device_get_softc(dev); 340 341 VTCON_LOCK(sc); 342 sc->vtcon_flags |= VTCON_FLAG_DETACHED; 343 if (device_is_attached(dev)) 344 vtcon_stop(sc); 345 VTCON_UNLOCK(sc); 346 347 taskqueue_drain(taskqueue_thread, &sc->vtcon_ctrl_task); 348 349 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) 350 vtcon_ctrl_deinit(sc); 351 352 vtcon_deinit_ports(sc); 353 354 VTCON_LOCK_DESTROY(sc); 355 356 return (0); 357 } 358 359 static int 360 vtcon_config_change(device_t dev) 361 { 362 struct vtcon_softc *sc; 363 struct vtcon_port *port; 364 uint16_t cols, rows; 365 366 sc = device_get_softc(dev); 367 368 /* 369 * With the multiport feature, all configuration changes are 370 * done through control virtqueue events. This is a spurious 371 * interrupt. 372 */ 373 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) 374 return (0); 375 376 if (sc->vtcon_flags & VTCON_FLAG_SIZE) { 377 /* 378 * For now, assume the first (only) port is the 'console'. 379 * Note QEMU does not implement this feature yet. 380 */ 381 VTCON_LOCK(sc); 382 if ((port = vtcon_port_lookup_by_id(sc, 0)) != NULL) { 383 vtcon_get_console_size(sc, &cols, &rows); 384 vtcon_port_change_size(port, cols, rows); 385 } 386 VTCON_UNLOCK(sc); 387 } 388 389 return (0); 390 } 391 392 static void 393 vtcon_negotiate_features(struct vtcon_softc *sc) 394 { 395 device_t dev; 396 uint64_t features; 397 398 dev = sc->vtcon_dev; 399 features = VTCON_FEATURES; 400 401 sc->vtcon_features = virtio_negotiate_features(dev, features); 402 } 403 404 #define VTCON_GET_CONFIG(_dev, _feature, _field, _cfg) \ 405 if (virtio_with_feature(_dev, _feature)) { \ 406 virtio_read_device_config(_dev, \ 407 offsetof(struct virtio_console_config, _field), \ 408 &(_cfg)->_field, sizeof((_cfg)->_field)); \ 409 } 410 411 static void 412 vtcon_read_config(struct vtcon_softc *sc, struct virtio_console_config *concfg) 413 { 414 device_t dev; 415 416 dev = sc->vtcon_dev; 417 418 bzero(concfg, sizeof(struct virtio_console_config)); 419 420 /* Read the configuration if the feature was negotiated. */ 421 VTCON_GET_CONFIG(dev, VIRTIO_CONSOLE_F_SIZE, cols, concfg); 422 VTCON_GET_CONFIG(dev, VIRTIO_CONSOLE_F_SIZE, rows, concfg); 423 VTCON_GET_CONFIG(dev, VIRTIO_CONSOLE_F_MULTIPORT, max_nr_ports, concfg); 424 } 425 426 #undef VTCON_GET_CONFIG 427 428 static int 429 vtcon_alloc_virtqueues(struct vtcon_softc *sc) 430 { 431 device_t dev; 432 struct vq_alloc_info *info; 433 struct vtcon_port_extra *portx; 434 int i, idx, portidx, nvqs, error; 435 436 dev = sc->vtcon_dev; 437 438 sc->vtcon_portsx = malloc(sizeof(struct vtcon_port_extra) * 439 sc->vtcon_max_ports, M_DEVBUF, M_NOWAIT | M_ZERO); 440 if (sc->vtcon_portsx == NULL) 441 return (ENOMEM); 442 443 nvqs = sc->vtcon_max_ports * 2; 444 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) 445 nvqs += 2; 446 447 info = malloc(sizeof(struct vq_alloc_info) * nvqs, M_TEMP, M_NOWAIT); 448 if (info == NULL) 449 return (ENOMEM); 450 451 for (i = 0, idx = 0, portidx = 0; i < nvqs / 2; i++, idx+=2) { 452 453 if (i == 1) { 454 /* The control virtqueues are after the first port. */ 455 VQ_ALLOC_INFO_INIT(&info[idx], 0, 456 vtcon_ctrl_rx_vq_intr, sc, &sc->vtcon_ctrl_rxvq, 457 "%s-control rx", device_get_nameunit(dev)); 458 VQ_ALLOC_INFO_INIT(&info[idx+1], 0, 459 NULL, sc, &sc->vtcon_ctrl_txvq, 460 "%s-control tx", device_get_nameunit(dev)); 461 continue; 462 } 463 464 portx = &sc->vtcon_portsx[portidx]; 465 466 VQ_ALLOC_INFO_INIT(&info[idx], 0, vtcon_port_in_vq_intr, 467 portx, &portx->invq, "%s-port%d in", 468 device_get_nameunit(dev), portidx); 469 VQ_ALLOC_INFO_INIT(&info[idx+1], 0, NULL, 470 NULL, &portx->outvq, "%s-port%d out", 471 device_get_nameunit(dev), portidx); 472 473 portidx++; 474 } 475 476 error = virtio_alloc_virtqueues(dev, 0, nvqs, info); 477 free(info, M_TEMP); 478 479 return (error); 480 } 481 482 static void 483 vtcon_determine_max_ports(struct vtcon_softc *sc, 484 struct virtio_console_config *concfg) 485 { 486 487 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) { 488 sc->vtcon_max_ports = 489 min(concfg->max_nr_ports, VTCON_MAX_PORTS); 490 if (sc->vtcon_max_ports == 0) 491 sc->vtcon_max_ports = 1; 492 } else 493 sc->vtcon_max_ports = 1; 494 } 495 496 static void 497 vtcon_deinit_ports(struct vtcon_softc *sc) 498 { 499 struct vtcon_port *port, *tmp; 500 501 TAILQ_FOREACH_SAFE(port, &sc->vtcon_ports, vtcport_next, tmp) { 502 vtcon_port_teardown(port, 1); 503 } 504 505 if (sc->vtcon_portsx != NULL) { 506 free(sc->vtcon_portsx, M_DEVBUF); 507 sc->vtcon_portsx = NULL; 508 } 509 } 510 511 static void 512 vtcon_stop(struct vtcon_softc *sc) 513 { 514 515 vtcon_disable_interrupts(sc); 516 virtio_stop(sc->vtcon_dev); 517 } 518 519 static void 520 vtcon_ctrl_rx_vq_intr(void *xsc) 521 { 522 struct vtcon_softc *sc; 523 524 sc = xsc; 525 526 /* 527 * Some events require us to potentially block, but it easier 528 * to just defer all event handling to a seperate thread. 529 */ 530 taskqueue_enqueue(taskqueue_thread, &sc->vtcon_ctrl_task); 531 } 532 533 static int 534 vtcon_ctrl_enqueue_msg(struct vtcon_softc *sc, 535 struct virtio_console_control *control) 536 { 537 struct sglist_seg segs[1]; 538 struct sglist sg; 539 struct virtqueue *vq; 540 int error __unused; 541 542 vq = sc->vtcon_ctrl_rxvq; 543 544 sglist_init(&sg, 1, segs); 545 error = sglist_append(&sg, control, sizeof(*control)); 546 KASSERT(error == 0 && sg.sg_nseg == 1, 547 ("%s: error %d adding control msg to sglist", __func__, error)); 548 549 return (virtqueue_enqueue(vq, control, &sg, 0, 1)); 550 } 551 552 static int 553 vtcon_ctrl_add_msg(struct vtcon_softc *sc) 554 { 555 struct virtio_console_control *control; 556 int error; 557 558 control = malloc(sizeof(*control), M_DEVBUF, M_ZERO | M_NOWAIT); 559 if (control == NULL) 560 return (ENOMEM); 561 562 error = vtcon_ctrl_enqueue_msg(sc, control); 563 if (error) 564 free(control, M_DEVBUF); 565 566 return (error); 567 } 568 569 static void 570 vtcon_ctrl_readd_msg(struct vtcon_softc *sc, 571 struct virtio_console_control *control) 572 { 573 int error; 574 575 bzero(control, sizeof(*control)); 576 577 error = vtcon_ctrl_enqueue_msg(sc, control); 578 KASSERT(error == 0, 579 ("%s: cannot requeue control buffer %d", __func__, error)); 580 } 581 582 static int 583 vtcon_ctrl_populate(struct vtcon_softc *sc) 584 { 585 struct virtqueue *vq; 586 int nbufs, error; 587 588 vq = sc->vtcon_ctrl_rxvq; 589 error = ENOSPC; 590 591 for (nbufs = 0; !virtqueue_full(vq); nbufs++) { 592 error = vtcon_ctrl_add_msg(sc); 593 if (error) 594 break; 595 } 596 597 if (nbufs > 0) { 598 virtqueue_notify(vq); 599 /* 600 * EMSGSIZE signifies the virtqueue did not have enough 601 * entries available to hold the last buf. This is not 602 * an error. 603 */ 604 if (error == EMSGSIZE) 605 error = 0; 606 } 607 608 return (error); 609 } 610 611 static void 612 vtcon_ctrl_send_msg(struct vtcon_softc *sc, 613 struct virtio_console_control *control) 614 { 615 struct sglist_seg segs[1]; 616 struct sglist sg; 617 struct virtqueue *vq; 618 int error; 619 620 vq = sc->vtcon_ctrl_txvq; 621 KASSERT(virtqueue_empty(vq), 622 ("%s: virtqueue is not emtpy", __func__)); 623 624 sglist_init(&sg, 1, segs); 625 error = sglist_append(&sg, control, sizeof(*control)); 626 KASSERT(error == 0 && sg.sg_nseg == 1, 627 ("%s: error %d adding control msg to sglist", __func__, error)); 628 629 error = virtqueue_enqueue(vq, control, &sg, 1, 0); 630 if (error == 0) { 631 virtqueue_notify(vq); 632 virtqueue_poll(vq, NULL); 633 } 634 } 635 636 static void 637 vtcon_ctrl_send_event(struct vtcon_softc *sc, uint32_t portid, uint16_t event, 638 uint16_t value) 639 { 640 struct virtio_console_control control; 641 642 if ((sc->vtcon_flags & VTCON_FLAG_MULTIPORT) == 0) 643 return; 644 645 control.id = portid; 646 control.event = event; 647 control.value = value; 648 649 vtcon_ctrl_send_msg(sc, &control); 650 } 651 652 static int 653 vtcon_ctrl_init(struct vtcon_softc *sc) 654 { 655 int error; 656 657 error = vtcon_ctrl_populate(sc); 658 659 return (error); 660 } 661 662 static void 663 vtcon_ctrl_drain(struct vtcon_softc *sc) 664 { 665 struct virtio_console_control *control; 666 struct virtqueue *vq; 667 int last; 668 669 vq = sc->vtcon_ctrl_rxvq; 670 last = 0; 671 672 if (vq == NULL) 673 return; 674 675 while ((control = virtqueue_drain(vq, &last)) != NULL) 676 free(control, M_DEVBUF); 677 } 678 679 static void 680 vtcon_ctrl_deinit(struct vtcon_softc *sc) 681 { 682 683 vtcon_ctrl_drain(sc); 684 } 685 686 static void 687 vtcon_ctrl_port_add_event(struct vtcon_softc *sc, int id) 688 { 689 device_t dev; 690 struct vtcon_port *port; 691 int error; 692 693 dev = sc->vtcon_dev; 694 695 if (vtcon_port_lookup_by_id(sc, id) != NULL) { 696 device_printf(dev, "%s: adding port %d, but already exists\n", 697 __func__, id); 698 return; 699 } 700 701 error = vtcon_port_create(sc, id, &port); 702 if (error) { 703 device_printf(dev, "%s: cannot create port %d: %d\n", 704 __func__, id, error); 705 return; 706 } 707 708 vtcon_port_send_ctrl_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); 709 } 710 711 static void 712 vtcon_ctrl_port_remove_event(struct vtcon_softc *sc, int id) 713 { 714 device_t dev; 715 struct vtcon_port *port; 716 717 dev = sc->vtcon_dev; 718 719 port = vtcon_port_lookup_by_id(sc, id); 720 if (port == NULL) { 721 device_printf(dev, "%s: remove port %d, but does not exist\n", 722 __func__, id); 723 return; 724 } 725 726 vtcon_port_teardown(port, 1); 727 } 728 729 static void 730 vtcon_ctrl_port_console_event(struct vtcon_softc *sc, int id) 731 { 732 device_t dev; 733 734 dev = sc->vtcon_dev; 735 736 /* 737 * BMV: I don't think we need to do anything. 738 */ 739 device_printf(dev, "%s: port %d console event\n", __func__, id); 740 } 741 742 static void 743 vtcon_ctrl_port_open_event(struct vtcon_softc *sc, int id) 744 { 745 device_t dev; 746 struct vtcon_port *port; 747 748 dev = sc->vtcon_dev; 749 750 port = vtcon_port_lookup_by_id(sc, id); 751 if (port == NULL) { 752 device_printf(dev, "%s: open port %d, but does not exist\n", 753 __func__, id); 754 return; 755 } 756 757 vtcon_port_enable_intr(port); 758 } 759 760 static void 761 vtcon_ctrl_process_msg(struct vtcon_softc *sc, 762 struct virtio_console_control *control) 763 { 764 device_t dev; 765 int id; 766 767 dev = sc->vtcon_dev; 768 id = control->id; 769 770 if (id < 0 || id >= sc->vtcon_max_ports) { 771 device_printf(dev, "%s: invalid port ID %d\n", __func__, id); 772 return; 773 } 774 775 switch (control->event) { 776 case VIRTIO_CONSOLE_PORT_ADD: 777 vtcon_ctrl_port_add_event(sc, id); 778 break; 779 780 case VIRTIO_CONSOLE_PORT_REMOVE: 781 vtcon_ctrl_port_remove_event(sc, id); 782 break; 783 784 case VIRTIO_CONSOLE_CONSOLE_PORT: 785 vtcon_ctrl_port_console_event(sc, id); 786 break; 787 788 case VIRTIO_CONSOLE_RESIZE: 789 break; 790 791 case VIRTIO_CONSOLE_PORT_OPEN: 792 vtcon_ctrl_port_open_event(sc, id); 793 break; 794 795 case VIRTIO_CONSOLE_PORT_NAME: 796 break; 797 } 798 } 799 800 static void 801 vtcon_ctrl_task_cb(void *xsc, int pending) 802 { 803 struct vtcon_softc *sc; 804 struct virtqueue *vq; 805 struct virtio_console_control *control; 806 807 sc = xsc; 808 vq = sc->vtcon_ctrl_rxvq; 809 810 VTCON_LOCK(sc); 811 while ((sc->vtcon_flags & VTCON_FLAG_DETACHED) == 0) { 812 control = virtqueue_dequeue(vq, NULL); 813 if (control == NULL) 814 break; 815 816 VTCON_UNLOCK(sc); 817 vtcon_ctrl_process_msg(sc, control); 818 VTCON_LOCK(sc); 819 vtcon_ctrl_readd_msg(sc, control); 820 } 821 VTCON_UNLOCK(sc); 822 823 if (virtqueue_enable_intr(vq) != 0) 824 taskqueue_enqueue(taskqueue_thread, &sc->vtcon_ctrl_task); 825 } 826 827 static int 828 vtcon_port_enqueue_inbuf(struct vtcon_port *port, void *buf, size_t len) 829 { 830 struct sglist_seg segs[1]; 831 struct sglist sg; 832 struct virtqueue *vq; 833 int error; 834 835 vq = port->vtcport_invq; 836 837 sglist_init(&sg, 1, segs); 838 error = sglist_append(&sg, buf, len); 839 KASSERT(error == 0 && sg.sg_nseg == 1, 840 ("%s: error %d adding buffer to sglist", __func__, error)); 841 842 return (virtqueue_enqueue(vq, buf, &sg, 0, 1)); 843 } 844 845 static int 846 vtcon_port_add_inbuf(struct vtcon_port *port) 847 { 848 void *buf; 849 int error; 850 851 buf = malloc(VTCON_BULK_BUFSZ, M_DEVBUF, M_ZERO | M_NOWAIT); 852 if (buf == NULL) 853 return (ENOMEM); 854 855 error = vtcon_port_enqueue_inbuf(port, buf, VTCON_BULK_BUFSZ); 856 if (error) 857 free(buf, M_DEVBUF); 858 859 return (error); 860 } 861 862 static void 863 vtcon_port_readd_inbuf(struct vtcon_port *port, void *buf) 864 { 865 int error __unused; 866 867 error = vtcon_port_enqueue_inbuf(port, buf, VTCON_BULK_BUFSZ); 868 KASSERT(error == 0, 869 ("%s: cannot requeue input buffer %d", __func__, error)); 870 } 871 872 static int 873 vtcon_port_populate(struct vtcon_port *port) 874 { 875 struct virtqueue *vq; 876 int nbufs, error; 877 878 vq = port->vtcport_invq; 879 error = ENOSPC; 880 881 for (nbufs = 0; !virtqueue_full(vq); nbufs++) { 882 error = vtcon_port_add_inbuf(port); 883 if (error) 884 break; 885 } 886 887 if (nbufs > 0) { 888 virtqueue_notify(vq); 889 /* 890 * EMSGSIZE signifies the virtqueue did not have enough 891 * entries available to hold the last buf. This is not 892 * an error. 893 */ 894 if (error == EMSGSIZE) 895 error = 0; 896 } 897 898 return (error); 899 } 900 901 static void 902 vtcon_port_destroy(struct vtcon_port *port) 903 { 904 905 port->vtcport_sc = NULL; 906 port->vtcport_id = -1; 907 VTCON_PORT_LOCK_DESTROY(port); 908 free(port, M_DEVBUF); 909 } 910 911 static int 912 vtcon_port_create(struct vtcon_softc *sc, int id, struct vtcon_port **portp) 913 { 914 device_t dev; 915 struct vtcon_port_extra *portx; 916 struct vtcon_port *port; 917 int error; 918 919 MPASS(id < sc->vtcon_max_ports); 920 dev = sc->vtcon_dev; 921 portx = &sc->vtcon_portsx[id]; 922 923 if (portx->port != NULL) 924 return (EEXIST); 925 926 port = malloc(sizeof(struct vtcon_port), M_DEVBUF, M_NOWAIT | M_ZERO); 927 if (port == NULL) 928 return (ENOMEM); 929 930 port->vtcport_sc = sc; 931 port->vtcport_id = id; 932 snprintf(port->vtcport_name, sizeof(port->vtcport_name), "%s-port%d", 933 device_get_nameunit(dev), id); 934 VTCON_PORT_LOCK_INIT(port); 935 port->vtcport_tty = tty_alloc_mutex(&vtcon_tty_class, port, 936 &port->vtcport_mtx); 937 938 /* 939 * Assign virtqueues saved from attach. To be safe, clear the 940 * virtqueue too. 941 */ 942 port->vtcport_invq = portx->invq; 943 port->vtcport_outvq = portx->outvq; 944 vtcon_port_drain_inbufs(port); 945 946 error = vtcon_port_populate(port); 947 if (error) { 948 vtcon_port_teardown(port, 0); 949 return (error); 950 } 951 952 tty_makedev(port->vtcport_tty, NULL, "%s%r.%r", VTCON_TTY_PREFIX, 953 device_get_unit(dev), id); 954 955 VTCON_LOCK(sc); 956 portx->port = port; 957 TAILQ_INSERT_TAIL(&sc->vtcon_ports, port, vtcport_next); 958 VTCON_UNLOCK(sc); 959 960 if (portp != NULL) 961 *portp = port; 962 963 return (0); 964 } 965 966 static void 967 vtcon_port_drain_inbufs(struct vtcon_port *port) 968 { 969 struct virtqueue *vq; 970 void *buf; 971 int last; 972 973 vq = port->vtcport_invq; 974 last = 0; 975 976 if (vq == NULL) 977 return; 978 979 while ((buf = virtqueue_drain(vq, &last)) != NULL) 980 free(buf, M_DEVBUF); 981 } 982 983 static void 984 vtcon_port_teardown(struct vtcon_port *port, int ontailq) 985 { 986 struct vtcon_softc *sc; 987 struct vtcon_port_extra *portx; 988 struct tty *tp; 989 int id; 990 991 sc = port->vtcport_sc; 992 id = port->vtcport_id; 993 tp = port->vtcport_tty; 994 995 VTCON_ASSERT_VALID_PORTID(sc, id); 996 portx = &sc->vtcon_portsx[id]; 997 998 VTCON_PORT_LOCK(port); 999 vtcon_port_drain_inbufs(port); 1000 VTCON_PORT_UNLOCK(port); 1001 1002 VTCON_LOCK(sc); 1003 KASSERT(portx->port == NULL || portx->port == port, 1004 ("%s: port %d mismatch %p/%p", __func__, id, portx->port, port)); 1005 portx->port = NULL; 1006 if (ontailq != 0) 1007 TAILQ_REMOVE(&sc->vtcon_ports, port, vtcport_next); 1008 VTCON_UNLOCK(sc); 1009 1010 if (tp != NULL) { 1011 port->vtcport_tty = NULL; 1012 atomic_add_int(&vtcon_pending_free, 1); 1013 1014 VTCON_PORT_LOCK(port); 1015 tty_rel_gone(tp); 1016 } else 1017 vtcon_port_destroy(port); 1018 } 1019 1020 static void 1021 vtcon_port_change_size(struct vtcon_port *port, uint16_t cols, uint16_t rows) 1022 { 1023 struct tty *tp; 1024 struct winsize sz; 1025 1026 tp = port->vtcport_tty; 1027 1028 if (tp == NULL) 1029 return; 1030 1031 bzero(&sz, sizeof(struct winsize)); 1032 sz.ws_col = cols; 1033 sz.ws_row = rows; 1034 1035 VTCON_PORT_LOCK(port); 1036 tty_set_winsize(tp, &sz); 1037 VTCON_PORT_UNLOCK(port); 1038 } 1039 1040 static void 1041 vtcon_port_enable_intr(struct vtcon_port *port) 1042 { 1043 1044 /* 1045 * NOTE: The out virtqueue is always polled, so we keep its 1046 * interupt disabled. 1047 */ 1048 1049 virtqueue_enable_intr(port->vtcport_invq); 1050 } 1051 1052 static void 1053 vtcon_port_disable_intr(struct vtcon_port *port) 1054 { 1055 1056 if (port->vtcport_invq != NULL) 1057 virtqueue_disable_intr(port->vtcport_invq); 1058 if (port->vtcport_outvq != NULL) 1059 virtqueue_disable_intr(port->vtcport_outvq); 1060 } 1061 1062 static void 1063 vtcon_port_intr(struct vtcon_port *port) 1064 { 1065 struct tty *tp; 1066 struct virtqueue *vq; 1067 char *buf; 1068 uint32_t len; 1069 int i, deq; 1070 1071 tp = port->vtcport_tty; 1072 vq = port->vtcport_invq; 1073 1074 again: 1075 deq = 0; 1076 1077 VTCON_PORT_LOCK(port); 1078 while ((buf = virtqueue_dequeue(vq, &len)) != NULL) { 1079 deq++; 1080 for (i = 0; i < len; i++) 1081 ttydisc_rint(tp, buf[i], 0); 1082 vtcon_port_readd_inbuf(port, buf); 1083 } 1084 ttydisc_rint_done(tp); 1085 VTCON_PORT_UNLOCK(port); 1086 1087 if (deq > 0) 1088 virtqueue_notify(vq); 1089 1090 if (virtqueue_enable_intr(vq) != 0) 1091 goto again; 1092 } 1093 1094 static void 1095 vtcon_port_in_vq_intr(void *xportx) 1096 { 1097 struct vtcon_port_extra *portx; 1098 struct vtcon_port *port; 1099 1100 portx = xportx; 1101 port = portx->port; 1102 1103 if (port != NULL) 1104 vtcon_port_intr(port); 1105 } 1106 1107 static void 1108 vtcon_port_put(struct vtcon_port *port, void *buf, int bufsize) 1109 { 1110 struct sglist_seg segs[1]; 1111 struct sglist sg; 1112 struct virtqueue *vq; 1113 int error; 1114 1115 vq = port->vtcport_outvq; 1116 1117 sglist_init(&sg, 1, segs); 1118 error = sglist_append(&sg, buf, bufsize); 1119 KASSERT(error == 0 && sg.sg_nseg == 1, 1120 ("%s: error %d adding buffer to sglist", __func__, error)); 1121 1122 KASSERT(virtqueue_empty(vq), ("%s: port %p virtqueue not emtpy", 1123 __func__, port)); 1124 1125 if (virtqueue_enqueue(vq, buf, &sg, 1, 0) == 0) { 1126 virtqueue_notify(vq); 1127 virtqueue_poll(vq, NULL); 1128 } 1129 } 1130 1131 static void 1132 vtcon_port_send_ctrl_msg(struct vtcon_port *port, uint16_t event, 1133 uint16_t value) 1134 { 1135 struct vtcon_softc *sc; 1136 1137 sc = port->vtcport_sc; 1138 1139 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) 1140 vtcon_ctrl_send_event(sc, port->vtcport_id, event, value); 1141 } 1142 1143 static struct vtcon_port * 1144 vtcon_port_lookup_by_id(struct vtcon_softc *sc, int id) 1145 { 1146 struct vtcon_port *port; 1147 1148 TAILQ_FOREACH(port, &sc->vtcon_ports, vtcport_next) { 1149 if (port->vtcport_id == id) 1150 break; 1151 } 1152 1153 return (port); 1154 } 1155 1156 static int 1157 vtcon_tty_open(struct tty *tp) 1158 { 1159 struct vtcon_port *port; 1160 1161 port = tty_softc(tp); 1162 1163 vtcon_port_send_ctrl_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1); 1164 1165 return (0); 1166 } 1167 1168 static void 1169 vtcon_tty_close(struct tty *tp) 1170 { 1171 struct vtcon_port *port; 1172 1173 port = tty_softc(tp); 1174 1175 vtcon_port_send_ctrl_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); 1176 } 1177 1178 static void 1179 vtcon_tty_outwakeup(struct tty *tp) 1180 { 1181 struct vtcon_port *port; 1182 char buf[VTCON_BULK_BUFSZ]; 1183 int len; 1184 1185 port = tty_softc(tp); 1186 1187 while ((len = ttydisc_getc(tp, buf, sizeof(buf))) != 0) 1188 vtcon_port_put(port, buf, len); 1189 } 1190 1191 static void 1192 vtcon_tty_free(void *xport) 1193 { 1194 struct vtcon_port *port; 1195 1196 port = xport; 1197 1198 vtcon_port_destroy(port); 1199 atomic_subtract_int(&vtcon_pending_free, 1); 1200 } 1201 1202 static void 1203 vtcon_get_console_size(struct vtcon_softc *sc, uint16_t *cols, uint16_t *rows) 1204 { 1205 struct virtio_console_config concfg; 1206 1207 KASSERT(sc->vtcon_flags & VTCON_FLAG_SIZE, 1208 ("%s: size feature not negotiated", __func__)); 1209 1210 vtcon_read_config(sc, &concfg); 1211 1212 *cols = concfg.cols; 1213 *rows = concfg.rows; 1214 } 1215 1216 static void 1217 vtcon_enable_interrupts(struct vtcon_softc *sc) 1218 { 1219 struct vtcon_port *port; 1220 1221 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) 1222 virtqueue_enable_intr(sc->vtcon_ctrl_rxvq); 1223 1224 TAILQ_FOREACH(port, &sc->vtcon_ports, vtcport_next) 1225 vtcon_port_enable_intr(port); 1226 } 1227 1228 static void 1229 vtcon_disable_interrupts(struct vtcon_softc *sc) 1230 { 1231 struct vtcon_port *port; 1232 1233 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) 1234 virtqueue_disable_intr(sc->vtcon_ctrl_rxvq); 1235 1236 TAILQ_FOREACH(port, &sc->vtcon_ports, vtcport_next) 1237 vtcon_port_disable_intr(port); 1238 } 1239