1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 27 /* 28 * sun4v console driver 29 */ 30 31 #include <sys/errno.h> 32 #include <sys/stat.h> 33 #include <sys/kmem.h> 34 #include <sys/conf.h> 35 #include <sys/termios.h> 36 #include <sys/modctl.h> 37 #include <sys/kbio.h> 38 #include <sys/stropts.h> 39 #include <sys/stream.h> 40 #include <sys/strsun.h> 41 #include <sys/sysmacros.h> 42 #include <sys/promif.h> 43 #include <sys/ddi.h> 44 #include <sys/sunddi.h> 45 #include <sys/cyclic.h> 46 #include <sys/intr.h> 47 #include <sys/spl.h> 48 #include <sys/qcn.h> 49 #include <sys/hypervisor_api.h> 50 #include <sys/hsvc.h> 51 #include <sys/machsystm.h> 52 #include <sys/consdev.h> 53 54 /* dev_ops and cb_ops for device driver */ 55 static int qcn_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 56 static int qcn_attach(dev_info_t *, ddi_attach_cmd_t); 57 static int qcn_detach(dev_info_t *, ddi_detach_cmd_t); 58 static int qcn_open(queue_t *, dev_t *, int, int, cred_t *); 59 static int qcn_close(queue_t *, int, cred_t *); 60 static int qcn_wput(queue_t *, mblk_t *); 61 static int qcn_wsrv(queue_t *); 62 static int qcn_rsrv(queue_t *); 63 64 /* other internal qcn routines */ 65 static void qcn_ioctl(queue_t *, mblk_t *); 66 static void qcn_reioctl(void *); 67 static void qcn_ack(mblk_t *, mblk_t *, uint_t); 68 static void qcn_start(void); 69 static int qcn_transmit_write(queue_t *, mblk_t *); 70 static int qcn_transmit_putchr(queue_t *, mblk_t *); 71 static void qcn_receive_read(void); 72 static void qcn_receive_getchr(void); 73 static void qcn_flush(void); 74 static uint_t qcn_hi_intr(caddr_t arg); 75 static uint_t qcn_soft_intr(caddr_t arg1, caddr_t arg2); 76 77 /* functions required for polled io */ 78 static boolean_t qcn_polledio_ischar(cons_polledio_arg_t arg); 79 static int qcn_polledio_getchar(cons_polledio_arg_t arg); 80 static void qcn_polledio_putchar(cons_polledio_arg_t arg, uchar_t c); 81 static void qcn_polledio_enter(cons_polledio_arg_t arg); 82 static void qcn_polledio_exit(cons_polledio_arg_t arg); 83 84 85 static boolean_t abort_charseq_recognize(uchar_t); 86 87 static qcn_t *qcn_state; 88 static uchar_t qcn_stopped = B_FALSE; 89 static int qcn_timeout_period = 20; /* time out in seconds */ 90 size_t qcn_input_dropped; /* dropped input character counter */ 91 92 #ifdef QCN_POLLING 93 static void qcn_poll_handler(void *unused); 94 static cyc_time_t qcn_poll_time; 95 static cyc_handler_t qcn_poll_cychandler = { 96 qcn_poll_handler, 97 NULL, 98 CY_LOW_LEVEL /* XXX need softint to make this high */ 99 }; 100 static cyclic_id_t qcn_poll_cycid = CYCLIC_NONE; 101 static uint64_t qcn_poll_interval = 5; /* milli sec */ 102 static uint64_t sb_interval = 0; 103 uint_t qcn_force_polling = 0; 104 #endif 105 106 #define QCN_MI_IDNUM 0xABCE 107 #define QCN_MI_HIWAT 8192 108 #define QCN_MI_LOWAT 128 109 110 /* streams structures */ 111 static struct module_info minfo = { 112 QCN_MI_IDNUM, /* mi_idnum */ 113 "qcn", /* mi_idname */ 114 0, /* mi_minpsz */ 115 INFPSZ, /* mi_maxpsz */ 116 QCN_MI_HIWAT, /* mi_hiwat */ 117 QCN_MI_LOWAT /* mi_lowat */ 118 }; 119 120 static struct qinit rinit = { 121 putq, /* qi_putp */ 122 qcn_rsrv, /* qi_srvp */ 123 qcn_open, /* qi_qopen */ 124 qcn_close, /* qi_qclose */ 125 NULL, /* qi_qadmin */ 126 &minfo, /* qi_minfo */ 127 NULL /* qi_mstat */ 128 }; 129 130 static struct qinit winit = { 131 qcn_wput, /* qi_putp */ 132 qcn_wsrv, /* qi_srvp */ 133 qcn_open, /* qi_qopen */ 134 qcn_close, /* qi_qclose */ 135 NULL, /* qi_qadmin */ 136 &minfo, /* qi_minfo */ 137 NULL /* qi_mstat */ 138 }; 139 140 static struct streamtab qcnstrinfo = { 141 &rinit, 142 &winit, 143 NULL, 144 NULL 145 }; 146 147 /* standard device driver structures */ 148 static struct cb_ops qcn_cb_ops = { 149 nulldev, /* open() */ 150 nulldev, /* close() */ 151 nodev, /* strategy() */ 152 nodev, /* print() */ 153 nodev, /* dump() */ 154 nodev, /* read() */ 155 nodev, /* write() */ 156 nodev, /* ioctl() */ 157 nodev, /* devmap() */ 158 nodev, /* mmap() */ 159 nodev, /* segmap() */ 160 nochpoll, /* poll() */ 161 ddi_prop_op, /* prop_op() */ 162 &qcnstrinfo, /* cb_str */ 163 D_NEW | D_MP /* cb_flag */ 164 }; 165 166 static struct dev_ops qcn_ops = { 167 DEVO_REV, 168 0, /* refcnt */ 169 qcn_getinfo, /* getinfo() */ 170 nulldev, /* identify() */ 171 nulldev, /* probe() */ 172 qcn_attach, /* attach() */ 173 qcn_detach, /* detach() */ 174 nodev, /* reset() */ 175 &qcn_cb_ops, /* cb_ops */ 176 (struct bus_ops *)NULL, /* bus_ops */ 177 NULL, /* power() */ 178 ddi_quiesce_not_needed, /* quiesce() */ 179 }; 180 181 static struct modldrv modldrv = { 182 &mod_driverops, 183 "sun4v console driver", 184 &qcn_ops 185 }; 186 187 static struct modlinkage modlinkage = { 188 MODREV_1, 189 (void*)&modldrv, 190 NULL 191 }; 192 193 /* driver configuration routines */ 194 int 195 _init(void) 196 { 197 int error; 198 uint64_t major, minor; 199 200 qcn_state = kmem_zalloc(sizeof (qcn_t), KM_SLEEP); 201 qcn_state->qcn_ring = contig_mem_alloc(RINGSIZE); 202 if (qcn_state->qcn_ring == NULL) 203 cmn_err(CE_PANIC, "console ring allocation failed"); 204 205 error = mod_install(&modlinkage); 206 if (error != 0) { 207 contig_mem_free(qcn_state->qcn_ring, RINGSIZE); 208 kmem_free(qcn_state, sizeof (qcn_t)); 209 return (error); 210 } 211 /* 212 * check minor number to see if CONS_WRITE is supported 213 * if so, set up real address of the buffers for hv calls. 214 */ 215 216 if (((hsvc_version(HSVC_GROUP_CORE, &major, &minor) == 0) && 217 (major == QCN_API_MAJOR) && (minor >= QCN_API_MINOR))) { 218 qcn_state->cons_write_buffer = 219 contig_mem_alloc(CONS_WR_BUF_SIZE); 220 if (qcn_state->cons_write_buffer != NULL) { 221 qcn_state->cons_write_buf_ra = 222 va_to_pa(qcn_state->cons_write_buffer); 223 qcn_state->cons_transmit = qcn_transmit_write; 224 qcn_state->cons_receive = qcn_receive_read; 225 qcn_state->cons_read_buf_ra = 226 va_to_pa((char *)RING_ADDR(qcn_state)); 227 } 228 } 229 if (qcn_state->cons_transmit == NULL) { 230 qcn_state->cons_transmit = qcn_transmit_putchr; 231 qcn_state->cons_receive = qcn_receive_getchr; 232 } 233 return (0); 234 } 235 236 int 237 _fini(void) 238 { 239 /* can't remove console driver */ 240 return (EBUSY); 241 } 242 243 int 244 _info(struct modinfo *modinfop) 245 { 246 return (mod_info(&modlinkage, modinfop)); 247 } 248 249 static int 250 qcn_add_intrs(void) 251 { 252 dev_info_t *devinfo = qcn_state->qcn_dip; 253 int actual, count = 0; 254 int x, y, rc, inum = 0; 255 256 257 /* get number of interrupts */ 258 rc = ddi_intr_get_nintrs(devinfo, DDI_INTR_TYPE_FIXED, &count); 259 if ((rc != DDI_SUCCESS) || (count == 0)) { 260 return (DDI_FAILURE); 261 } 262 263 /* Allocate an array of interrupt handles */ 264 qcn_state->qcn_intr_size = count * sizeof (ddi_intr_handle_t); 265 qcn_state->qcn_htable = kmem_zalloc(qcn_state->qcn_intr_size, KM_SLEEP); 266 267 /* call ddi_intr_alloc() */ 268 rc = ddi_intr_alloc(devinfo, qcn_state->qcn_htable, 269 DDI_INTR_TYPE_FIXED, inum, count, &actual, 270 DDI_INTR_ALLOC_STRICT); 271 272 if ((rc != DDI_SUCCESS) || (actual == 0)) { 273 kmem_free(qcn_state->qcn_htable, qcn_state->qcn_intr_size); 274 return (DDI_FAILURE); 275 } 276 277 if (actual < count) { 278 for (x = 0; x < actual; x++) { 279 (void) ddi_intr_free(qcn_state->qcn_htable[x]); 280 } 281 282 kmem_free(qcn_state->qcn_htable, qcn_state->qcn_intr_size); 283 return (DDI_FAILURE); 284 } 285 286 qcn_state->qcn_intr_cnt = actual; 287 288 /* Get intr priority */ 289 if (ddi_intr_get_pri(qcn_state->qcn_htable[0], 290 &qcn_state->qcn_intr_pri) != DDI_SUCCESS) { 291 for (x = 0; x < actual; x++) { 292 (void) ddi_intr_free(qcn_state->qcn_htable[x]); 293 } 294 295 kmem_free(qcn_state->qcn_htable, qcn_state->qcn_intr_size); 296 return (DDI_FAILURE); 297 } 298 299 /* Call ddi_intr_add_handler() */ 300 for (x = 0; x < actual; x++) { 301 if (ddi_intr_add_handler(qcn_state->qcn_htable[x], 302 (ddi_intr_handler_t *)qcn_hi_intr, 303 (caddr_t)qcn_state, NULL) != DDI_SUCCESS) { 304 305 for (y = 0; y < x; y++) { 306 (void) ddi_intr_remove_handler( 307 qcn_state->qcn_htable[y]); 308 } 309 310 for (y = 0; y < actual; y++) { 311 (void) ddi_intr_free(qcn_state->qcn_htable[y]); 312 } 313 314 kmem_free(qcn_state->qcn_htable, 315 qcn_state->qcn_intr_size); 316 return (DDI_FAILURE); 317 } 318 } 319 320 return (DDI_SUCCESS); 321 } 322 323 static void 324 qcn_remove_intrs(void) 325 { 326 int x; 327 for (x = 0; x < qcn_state->qcn_intr_cnt; x++) { 328 (void) ddi_intr_disable(qcn_state->qcn_htable[x]); 329 (void) ddi_intr_remove_handler(qcn_state->qcn_htable[x]); 330 (void) ddi_intr_free(qcn_state->qcn_htable[x]); 331 } 332 kmem_free(qcn_state->qcn_htable, qcn_state->qcn_intr_size); 333 } 334 335 static void 336 qcn_intr_enable(void) 337 { 338 int x; 339 340 for (x = 0; x < qcn_state->qcn_intr_cnt; x++) { 341 (void) ddi_intr_enable(qcn_state->qcn_htable[x]); 342 } 343 } 344 345 /* 346 * qcn_attach is called at startup time. 347 * There is only once instance of this driver. 348 */ 349 static int 350 qcn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 351 { 352 extern int ddi_create_internal_pathname(dev_info_t *, char *, 353 int, minor_t); 354 uint_t soft_prip; 355 356 #ifdef QCN_POLLING 357 char *binding_name; 358 #endif 359 if (cmd != DDI_ATTACH) 360 return (DDI_FAILURE); 361 362 if (ddi_create_internal_pathname(dip, "qcn", 363 S_IFCHR, 0) != DDI_SUCCESS) 364 return (DDI_FAILURE); 365 366 qcn_state->qcn_soft_pend = 0; 367 qcn_state->qcn_hangup = 0; 368 qcn_state->qcn_rbuf_overflow = 0; 369 370 /* prepare some data structures in soft state */ 371 372 qcn_state->qcn_dip = dip; 373 374 qcn_state->qcn_polling = 0; 375 376 #ifdef QCN_POLLING 377 /* 378 * This test is for the sole purposes of allowing 379 * the console to work on older firmware releases. 380 */ 381 binding_name = ddi_binding_name(qcn_state->qcn_dip); 382 if ((strcmp(binding_name, "qcn") == 0) || 383 (qcn_force_polling)) 384 qcn_state->qcn_polling = 1; 385 386 if (qcn_state->qcn_polling) { 387 qcn_poll_time.cyt_when = 0ull; 388 qcn_poll_time.cyt_interval = 389 qcn_poll_interval * 1000ull * 1000ull; 390 mutex_enter(&cpu_lock); 391 qcn_poll_cycid = cyclic_add(&qcn_poll_cychandler, 392 &qcn_poll_time); 393 mutex_exit(&cpu_lock); 394 } 395 #endif 396 397 if (!qcn_state->qcn_polling) { 398 if (qcn_add_intrs() != DDI_SUCCESS) { 399 cmn_err(CE_WARN, "qcn_attach: add_intr failed\n"); 400 return (DDI_FAILURE); 401 } 402 if (ddi_intr_add_softint(dip, &qcn_state->qcn_softint_hdl, 403 DDI_INTR_SOFTPRI_MAX, qcn_soft_intr, 404 (caddr_t)qcn_state) != DDI_SUCCESS) { 405 cmn_err(CE_WARN, "qcn_attach: add_soft_intr failed\n"); 406 qcn_remove_intrs(); 407 return (DDI_FAILURE); 408 } 409 if (ddi_intr_get_softint_pri(qcn_state->qcn_softint_hdl, 410 &soft_prip) != DDI_SUCCESS) { 411 cmn_err(CE_WARN, "qcn_attach: softint_pri failed\n"); 412 (void) ddi_intr_remove_softint( 413 qcn_state->qcn_softint_hdl); 414 qcn_remove_intrs(); 415 return (DDI_FAILURE); 416 } 417 418 mutex_init(&qcn_state->qcn_hi_lock, NULL, MUTEX_DRIVER, 419 (void *)(uintptr_t)(qcn_state->qcn_intr_pri)); 420 } 421 422 mutex_init(&qcn_state->qcn_lock, NULL, MUTEX_DRIVER, NULL); 423 424 /* 425 * Fill in the polled I/O structure. 426 */ 427 qcn_state->qcn_polledio.cons_polledio_version = CONSPOLLEDIO_V1; 428 qcn_state->qcn_polledio.cons_polledio_argument = 429 (cons_polledio_arg_t)qcn_state; 430 qcn_state->qcn_polledio.cons_polledio_putchar = qcn_polledio_putchar; 431 qcn_state->qcn_polledio.cons_polledio_getchar = qcn_polledio_getchar; 432 qcn_state->qcn_polledio.cons_polledio_ischar = qcn_polledio_ischar; 433 qcn_state->qcn_polledio.cons_polledio_enter = qcn_polledio_enter; 434 qcn_state->qcn_polledio.cons_polledio_exit = qcn_polledio_exit; 435 436 /* 437 * Enable interrupts 438 */ 439 if (!qcn_state->qcn_polling) { 440 qcn_intr_enable(); 441 } 442 #ifdef QCN_DEBUG 443 prom_printf("qcn_attach(): qcn driver attached\n"); 444 #endif 445 446 return (DDI_SUCCESS); 447 448 } 449 450 /* ARGSUSED */ 451 static int 452 qcn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 453 { 454 455 if (cmd != DDI_DETACH) 456 return (DDI_FAILURE); 457 458 459 #ifdef QCN_DEBUG 460 prom_printf("qcn_detach(): QCN driver detached\n"); 461 #endif 462 463 #ifdef QCN_POLLING 464 if (qcn_state->qcn_polling) { 465 mutex_enter(&cpu_lock); 466 if (qcn_poll_cycid != CYCLIC_NONE) 467 cyclic_remove(qcn_poll_cycid); 468 qcn_poll_cycid = CYCLIC_NONE; 469 mutex_exit(&cpu_lock); 470 } 471 #endif 472 473 if (!qcn_state->qcn_polling) 474 qcn_remove_intrs(); 475 476 return (DDI_SUCCESS); 477 } 478 479 /* ARGSUSED */ 480 static int 481 qcn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 482 { 483 int error = DDI_FAILURE; 484 int instance = 0; 485 switch (infocmd) { 486 case DDI_INFO_DEVT2DEVINFO: 487 if (qcn_state) { 488 #ifdef QCN_DEBUG 489 prom_printf("qcn_getinfo(): devt2dip %lx\n", arg); 490 #endif 491 *result = (void *)qcn_state->qcn_dip; 492 error = DDI_SUCCESS; 493 } 494 break; 495 496 case DDI_INFO_DEVT2INSTANCE: 497 #ifdef QCN_DEBUG 498 prom_printf("qcn_getinfo(): devt2instance %lx\n", arg); 499 #endif 500 if (getminor((dev_t)arg) == 0) { 501 *result = (void *)(uintptr_t)instance; 502 error = DDI_SUCCESS; 503 } 504 break; 505 } 506 507 return (error); 508 } 509 510 /* streams open & close */ 511 /* ARGSUSED */ 512 static int 513 qcn_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *credp) 514 { 515 tty_common_t *tty; 516 int unit = getminor(*devp); 517 518 #ifdef QCN_DEBUG 519 prom_printf("qcn_open(): minor %x\n", unit); 520 #endif 521 522 if (unit != 0) 523 return (ENXIO); 524 525 /* stream already open */ 526 if (q->q_ptr != NULL) 527 return (DDI_SUCCESS); 528 529 if (!qcn_state) { 530 cmn_err(CE_WARN, "qcn_open: console was not configured by " 531 "autoconfig\n"); 532 return (ENXIO); 533 } 534 535 mutex_enter(&qcn_state->qcn_lock); 536 tty = &(qcn_state->qcn_tty); 537 538 tty->t_readq = q; 539 tty->t_writeq = WR(q); 540 541 /* Link the RD and WR Q's */ 542 q->q_ptr = WR(q)->q_ptr = (caddr_t)qcn_state; 543 qcn_state->qcn_readq = RD(q); 544 qcn_state->qcn_writeq = WR(q); 545 qprocson(q); 546 547 mutex_exit(&qcn_state->qcn_lock); 548 549 #ifdef QCN_DEBUG 550 prom_printf("qcn_open: opened as dev %lx\n", *devp); 551 #endif 552 553 return (DDI_SUCCESS); 554 } 555 556 /* ARGSUSED */ 557 static int 558 qcn_close(queue_t *q, int flag, cred_t *credp) 559 { 560 561 ASSERT(qcn_state == q->q_ptr); 562 563 if (qcn_state->qcn_wbufcid != 0) { 564 unbufcall(qcn_state->qcn_wbufcid); 565 } 566 ttycommon_close(&qcn_state->qcn_tty); 567 568 qprocsoff(q); 569 q->q_ptr = WR(q)->q_ptr = NULL; 570 qcn_state->qcn_readq = NULL; 571 qcn_state->qcn_writeq = NULL; 572 573 return (DDI_SUCCESS); 574 } 575 576 /* 577 * Put procedure for write queue. 578 * Respond to M_IOCTL, M_DATA and M_FLUSH messages here; 579 * It put's the data onto internal qcn_output_q. 580 */ 581 static int 582 qcn_wput(queue_t *q, mblk_t *mp) 583 { 584 585 #ifdef QCN_DEBUG 586 struct iocblk *iocp; 587 int i; 588 #endif 589 590 ASSERT(qcn_state == q->q_ptr); 591 592 if (!mp->b_datap) { 593 cmn_err(CE_PANIC, "qcn_wput: null datap"); 594 } 595 596 #ifdef QCN_DEBUG 597 prom_printf("qcn_wput(): QCN wput q=%X mp=%X rd=%X wr=%X type=%X\n", 598 q, mp, mp->b_rptr, mp->b_wptr, mp->b_datap->db_type); 599 #endif 600 601 mutex_enter(&qcn_state->qcn_lock); 602 603 switch (mp->b_datap->db_type) { 604 case M_IOCTL: 605 case M_CTL: 606 #ifdef QCN_DEBUG 607 iocp = (struct iocblk *)mp->b_rptr; 608 prom_printf("qcn_wput(): M_IOCTL cmd=%X TIOC=%X\n", 609 iocp->ioc_cmd, TIOC); 610 #endif 611 switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) { 612 case TCSETSW: 613 case TCSETSF: 614 case TCSETAW: 615 case TCSETAF: 616 case TCSBRK: 617 /* 618 * The change do not take effect until all 619 * output queued before them is drained. 620 * Put this message on the queue, so that 621 * "qcn_start" will see it when it's done 622 * with the output before it. Poke the start 623 * routine, just in case. 624 */ 625 (void) putq(q, mp); 626 qcn_start(); 627 break; 628 default: 629 mutex_exit(&qcn_state->qcn_lock); 630 qcn_ioctl(q, mp); 631 mutex_enter(&qcn_state->qcn_lock); 632 } 633 break; 634 635 case M_FLUSH: 636 if (*mp->b_rptr & FLUSHW) { 637 flushq(q, FLUSHDATA); 638 *mp->b_rptr &= ~FLUSHW; 639 } 640 if (*mp->b_rptr & FLUSHR) { 641 flushq(RD(q), FLUSHDATA); 642 qreply(q, mp); 643 } else { 644 freemsg(mp); 645 } 646 break; 647 648 case M_STOP: 649 qcn_stopped = B_TRUE; 650 freemsg(mp); 651 break; 652 653 case M_START: 654 qcn_stopped = B_FALSE; 655 freemsg(mp); 656 qenable(q); /* Start up delayed messages */ 657 break; 658 659 case M_DATA: 660 /* 661 * Queue the message up to be transmitted, 662 * and poke the start routine. 663 */ 664 #ifdef QCN_DEBUG 665 if (mp->b_rptr < mp->b_wptr) { 666 prom_printf("qcn_wput(): DATA q=%X mp=%X rd=%X wr=%X\n", 667 q, mp, mp->b_rptr, mp->b_wptr); 668 prom_printf("qcn_wput(): ["); 669 for (i = 0; i < mp->b_wptr-mp->b_rptr; i++) { 670 prom_printf("%c", *(mp->b_rptr+i)); 671 } 672 prom_printf("]\n"); 673 } 674 #endif /* QCN_DEBUG */ 675 (void) putq(q, mp); 676 qcn_start(); 677 break; 678 679 default: 680 freemsg(mp); 681 } 682 683 mutex_exit(&qcn_state->qcn_lock); 684 685 return (0); 686 } 687 688 /* 689 * Process an "ioctl" message sent down to us. 690 */ 691 static void 692 qcn_ioctl(queue_t *q, mblk_t *mp) 693 { 694 struct iocblk *iocp; 695 tty_common_t *tty; 696 mblk_t *datamp; 697 int data_size; 698 int error = 0; 699 700 #ifdef QCN_DEBUG 701 prom_printf("qcn_ioctl(): q=%X mp=%X\n", q, mp); 702 #endif 703 704 iocp = (struct iocblk *)mp->b_rptr; 705 706 tty = &(qcn_state->qcn_tty); 707 708 if (tty->t_iocpending != NULL) { 709 freemsg(tty->t_iocpending); 710 tty->t_iocpending = NULL; 711 } 712 713 /* 714 * Handle the POLLEDIO ioctls now because ttycommon_ioctl 715 * (below) frees up the message block (mp->b_cont) which 716 * contains the pointer used to pass back results. 717 */ 718 switch (iocp->ioc_cmd) { 719 case CONSOPENPOLLEDIO: 720 error = miocpullup(mp, sizeof (struct cons_polledio *)); 721 if (error != 0) 722 break; 723 724 *(struct cons_polledio **)mp->b_cont->b_rptr = 725 &qcn_state->qcn_polledio; 726 727 mp->b_datap->db_type = M_IOCACK; 728 break; 729 730 case CONSCLOSEPOLLEDIO: 731 mp->b_datap->db_type = M_IOCACK; 732 iocp->ioc_error = 0; 733 iocp->ioc_rval = 0; 734 break; 735 736 default: 737 data_size = ttycommon_ioctl(tty, q, mp, &error); 738 if (data_size != 0) { 739 if (qcn_state->qcn_wbufcid) 740 unbufcall(qcn_state->qcn_wbufcid); 741 /* call qcn_reioctl() */ 742 qcn_state->qcn_wbufcid = 743 bufcall(data_size, BPRI_HI, qcn_reioctl, qcn_state); 744 return; 745 } 746 } 747 748 mutex_enter(&qcn_state->qcn_lock); 749 750 if (error < 0) { 751 iocp = (struct iocblk *)mp->b_rptr; 752 /* 753 * "ttycommon_ioctl" didn't do anything; we process it here. 754 */ 755 error = 0; 756 switch (iocp->ioc_cmd) { 757 case TCSBRK: 758 case TIOCSBRK: 759 case TIOCCBRK: 760 case TIOCMSET: 761 case TIOCMBIS: 762 case TIOCMBIC: 763 if (iocp->ioc_count != TRANSPARENT) 764 qcn_ack(mp, NULL, 0); 765 else 766 mcopyin(mp, NULL, sizeof (int), NULL); 767 break; 768 769 case TIOCMGET: 770 datamp = allocb(sizeof (int), BPRI_MED); 771 if (datamp == NULL) { 772 error = EAGAIN; 773 break; 774 } 775 776 *(int *)datamp->b_rptr = 0; 777 778 if (iocp->ioc_count != TRANSPARENT) 779 qcn_ack(mp, datamp, sizeof (int)); 780 else 781 mcopyout(mp, NULL, sizeof (int), NULL, datamp); 782 break; 783 784 default: 785 error = EINVAL; 786 break; 787 } 788 } 789 if (error != 0) { 790 iocp->ioc_count = 0; 791 iocp->ioc_error = error; 792 mp->b_datap->db_type = M_IOCNAK; 793 } 794 mutex_exit(&qcn_state->qcn_lock); 795 qreply(q, mp); 796 } 797 798 static void 799 qcn_reioctl(void *unit) 800 { 801 queue_t *q; 802 mblk_t *mp; 803 qcn_t *qcnp = (qcn_t *)unit; 804 805 if (!qcnp->qcn_wbufcid) 806 return; 807 808 qcnp->qcn_wbufcid = 0; 809 if ((q = qcnp->qcn_tty.t_writeq) == NULL) 810 return; 811 812 if ((mp = qcnp->qcn_tty.t_iocpending) == NULL) 813 return; 814 815 qcnp->qcn_tty.t_iocpending = NULL; 816 qcn_ioctl(q, mp); 817 } 818 819 static void 820 qcn_ack(mblk_t *mp, mblk_t *dp, uint_t size) 821 { 822 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 823 824 mp->b_datap->db_type = M_IOCACK; 825 iocp->ioc_count = size; 826 iocp->ioc_error = 0; 827 iocp->ioc_rval = 0; 828 if (mp->b_cont != NULL) 829 freeb(mp->b_cont); 830 if (dp != NULL) { 831 mp->b_cont = dp; 832 dp->b_wptr += size; 833 } else 834 mp->b_cont = NULL; 835 } 836 837 static void 838 qcn_start(void) 839 { 840 841 queue_t *q; 842 mblk_t *mp; 843 int rv; 844 845 ASSERT(MUTEX_HELD(&qcn_state->qcn_lock)); 846 847 /* 848 * read stream queue and remove data from the queue and 849 * transmit them if possible 850 */ 851 q = qcn_state->qcn_writeq; 852 ASSERT(q != NULL); 853 while (mp = getq(q)) { 854 if (mp->b_datap->db_type == M_IOCTL) { 855 /* 856 * These are those IOCTLs queued up 857 * do it now 858 */ 859 mutex_exit(&qcn_state->qcn_lock); 860 qcn_ioctl(q, mp); 861 mutex_enter(&qcn_state->qcn_lock); 862 continue; 863 } 864 /* 865 * M_DATA 866 */ 867 rv = qcn_state->cons_transmit(q, mp); 868 if (rv == EBUSY || rv == EAGAIN) 869 return; 870 } 871 } 872 873 static int 874 qcn_transmit_write(queue_t *q, mblk_t *mp) 875 { 876 mblk_t *bp; 877 size_t len; 878 uint64_t i; 879 uint64_t retval = 0; 880 881 #ifdef QCN_DEBUG 882 prom_printf("qcn_transmit_write(): q=%X mp=%X\n", q, mp); 883 #endif 884 885 while (mp) { 886 bp = mp; 887 len = bp->b_wptr - bp->b_rptr; 888 /* 889 * Use the console write call to send a block of characters to 890 * the console. 891 */ 892 i = (len > CONS_WR_BUF_SIZE) ? CONS_WR_BUF_SIZE : len; 893 bcopy(bp->b_rptr, qcn_state->cons_write_buffer, i); 894 retval = hv_cnwrite(qcn_state->cons_write_buf_ra, i, &i); 895 896 if (retval == H_EOK) { 897 len -= i; 898 bp->b_rptr += i; 899 /* 900 * if we have finished with this buf, free 901 * and get the next buf if present. 902 */ 903 if (len == 0) { 904 mp = bp->b_cont; 905 freeb(bp); 906 } 907 } else { 908 (void) putbq(q, mp); 909 910 switch (retval) { 911 912 case H_EWOULDBLOCK : 913 /* 914 * hypervisor cannot process the request - 915 * channel busy. Try again later. 916 */ 917 return (EAGAIN); 918 919 case H_EIO : 920 return (EIO); 921 default : 922 return (ENXIO); 923 } 924 } 925 } 926 return (0); 927 } 928 929 static int 930 qcn_transmit_putchr(queue_t *q, mblk_t *mp) 931 { 932 caddr_t buf; 933 mblk_t *bp; 934 size_t len; 935 uint64_t i; 936 937 #ifdef QCN_DEBUG 938 prom_printf("qcn_transmit_putchr(): q=%X mp=%X\n", q, mp); 939 #endif 940 while (mp) { 941 bp = mp; 942 len = bp->b_wptr - bp->b_rptr; 943 buf = (caddr_t)bp->b_rptr; 944 for (i = 0; i < len; i++) { 945 if (hv_cnputchar(buf[i]) == H_EWOULDBLOCK) 946 break; 947 } 948 if (i != len) { 949 bp->b_rptr += i; 950 (void) putbq(q, mp); 951 return (EAGAIN); 952 } 953 mp = bp->b_cont; 954 freeb(bp); 955 } 956 return (0); 957 } 958 959 /* 960 * called when SC first establishes console connection 961 * drop all the data on the output queue 962 */ 963 static void 964 qcn_flush(void) 965 { 966 queue_t *q; 967 mblk_t *mp; 968 969 ASSERT(MUTEX_HELD(&qcn_state->qcn_lock)); 970 971 q = qcn_state->qcn_writeq; 972 973 prom_printf("qcn_flush(): WARNING console output is dropped time=%lx\n", 974 gethrestime_sec()); 975 while (mp = getq(q)) 976 freemsg(mp); 977 } 978 979 static void 980 qcn_trigger_softint(void) 981 { 982 /* 983 * if we are not currently servicing a software interrupt 984 * (qcn_soft_pend == 0), trigger the service routine to run. 985 */ 986 if (atomic_swap_uint(&qcn_state->qcn_soft_pend, QCN_SP_DO) == 987 QCN_SP_IDL) { 988 (void) ddi_intr_trigger_softint( 989 qcn_state->qcn_softint_hdl, NULL); 990 } 991 } 992 993 /*ARGSUSED*/ 994 static uint_t 995 qcn_soft_intr(caddr_t arg1, caddr_t arg2) 996 { 997 mblk_t *mp; 998 int cc; 999 int overflow_check; 1000 1001 do { 1002 (void) atomic_swap_uint(&qcn_state->qcn_soft_pend, QCN_SP_IP); 1003 mutex_enter(&qcn_state->qcn_hi_lock); 1004 cc = RING_CNT(qcn_state); 1005 mutex_exit(&qcn_state->qcn_hi_lock); 1006 if (cc <= 0) { 1007 goto out; 1008 } 1009 1010 if ((mp = allocb(cc, BPRI_MED)) == NULL) { 1011 mutex_enter(&qcn_state->qcn_hi_lock); 1012 qcn_input_dropped += cc; 1013 mutex_exit(&qcn_state->qcn_hi_lock); 1014 cmn_err(CE_WARN, "qcn_intr: allocb" 1015 "failed (console input dropped)"); 1016 goto out; 1017 } 1018 1019 mutex_enter(&qcn_state->qcn_hi_lock); 1020 do { 1021 /* put console input onto stream */ 1022 *(char *)mp->b_wptr++ = RING_GET(qcn_state); 1023 } while (--cc); 1024 1025 if ((overflow_check = qcn_state->qcn_rbuf_overflow) != 0) { 1026 qcn_state->qcn_rbuf_overflow = 0; 1027 } 1028 mutex_exit(&qcn_state->qcn_hi_lock); 1029 1030 if (overflow_check) { 1031 cmn_err(CE_WARN, "qcn: Ring buffer overflow\n"); 1032 } 1033 1034 if (qcn_state->qcn_readq) { 1035 putnext(qcn_state->qcn_readq, mp); 1036 } 1037 out: 1038 /* 1039 * If there are pending transmits because hypervisor 1040 * returned EWOULDBLOCK poke start now. 1041 */ 1042 1043 if (qcn_state->qcn_writeq != NULL) { 1044 if (qcn_state->qcn_hangup) { 1045 (void) putctl(qcn_state->qcn_readq, M_HANGUP); 1046 flushq(qcn_state->qcn_writeq, FLUSHDATA); 1047 qcn_state->qcn_hangup = 0; 1048 } else { 1049 mutex_enter(&qcn_state->qcn_lock); 1050 qcn_start(); 1051 mutex_exit(&qcn_state->qcn_lock); 1052 } 1053 } 1054 /* 1055 * now loop if another interrupt came in (qcn_trigger_softint 1056 * called) while we were processing the loop 1057 */ 1058 } while (atomic_swap_uint(&qcn_state->qcn_soft_pend, QCN_SP_IDL) == 1059 QCN_SP_DO); 1060 return (DDI_INTR_CLAIMED); 1061 } 1062 1063 /*ARGSUSED*/ 1064 static uint_t 1065 qcn_hi_intr(caddr_t arg) 1066 { 1067 mutex_enter(&qcn_state->qcn_hi_lock); 1068 1069 qcn_state->cons_receive(); 1070 1071 mutex_exit(&qcn_state->qcn_hi_lock); 1072 qcn_trigger_softint(); 1073 1074 return (DDI_INTR_CLAIMED); 1075 } 1076 1077 static void 1078 qcn_receive_read(void) 1079 { 1080 int64_t rv; 1081 uint8_t *bufp; 1082 int64_t retcount = 0; 1083 int i; 1084 1085 do { 1086 /* 1087 * Maximize available buffer size 1088 */ 1089 if (RING_CNT(qcn_state) <= 0) { 1090 RING_INIT(qcn_state); 1091 } 1092 rv = hv_cnread(qcn_state->cons_read_buf_ra + 1093 RING_POFF(qcn_state), 1094 RING_LEFT(qcn_state), 1095 &retcount); 1096 bufp = RING_ADDR(qcn_state); 1097 if (rv == H_EOK) { 1098 /* 1099 * if the alternate break sequence is enabled, test 1100 * the buffer for the sequence and if it is there, 1101 * enter the debugger. 1102 */ 1103 if (abort_enable == KIOCABORTALTERNATE) { 1104 for (i = 0; i < retcount; i++) { 1105 if (abort_charseq_recognize(*bufp++)) { 1106 abort_sequence_enter( 1107 (char *)NULL); 1108 } 1109 } 1110 } 1111 1112 /* put console input onto stream */ 1113 if (retcount > 0) { 1114 /* 1115 * the characters are already in the ring, 1116 * just update the pointer so the characters 1117 * can be retrieved. 1118 */ 1119 RING_UPD(qcn_state, retcount); 1120 } 1121 } else { 1122 switch (rv) { 1123 1124 case H_EWOULDBLOCK : 1125 /* 1126 * hypervisor cannot handle the request. 1127 * Try again later. 1128 */ 1129 break; 1130 1131 1132 case H_BREAK : 1133 /* 1134 * on break enter the debugger 1135 */ 1136 if (abort_enable != KIOCABORTALTERNATE) 1137 abort_sequence_enter((char *)NULL); 1138 break; 1139 1140 case H_HUP : 1141 qcn_state->qcn_hangup = 1; 1142 break; 1143 1144 default : 1145 break; 1146 } 1147 } 1148 } while (rv == H_EOK); 1149 } 1150 1151 static void 1152 qcn_receive_getchr(void) 1153 { 1154 int64_t rv; 1155 uint8_t buf; 1156 1157 do { 1158 rv = hv_cngetchar(&buf); 1159 if (rv == H_EOK) { 1160 if (abort_enable == KIOCABORTALTERNATE) { 1161 if (abort_charseq_recognize(buf)) { 1162 abort_sequence_enter((char *)NULL); 1163 } 1164 } 1165 1166 /* put console input onto stream */ 1167 if (RING_POK(qcn_state, 1)) { 1168 RING_PUT(qcn_state, buf); 1169 } else { 1170 qcn_state->qcn_rbuf_overflow++; 1171 } 1172 } else { 1173 if (rv == H_BREAK) { 1174 if (abort_enable != KIOCABORTENABLE) 1175 abort_sequence_enter((char *)NULL); 1176 } 1177 1178 if (rv == H_HUP) { 1179 qcn_state->qcn_hangup = 1; 1180 } 1181 return; 1182 } 1183 } while (rv == H_EOK); 1184 } 1185 1186 #ifdef QCN_POLLING 1187 /*ARGSUSED*/ 1188 static void 1189 qcn_poll_handler(void *unused) 1190 { 1191 mblk_t *mp; 1192 int64_t rv; 1193 uint8_t buf; 1194 int qcn_writeq_flush = 0; 1195 1196 /* LINTED: E_CONSTANT_CONDITION */ 1197 while (1) { 1198 rv = hv_cngetchar(&buf); 1199 if (rv == H_BREAK) { 1200 if (abort_enable != KIOCABORTALTERNATE) 1201 abort_sequence_enter((char *)NULL); 1202 } 1203 1204 if (rv == H_HUP) { 1205 if (qcn_state->qcn_readq) { 1206 (void) putctl(qcn_state->qcn_readq, M_HANGUP); 1207 qcn_writeq_flush = 1; 1208 } 1209 goto out; 1210 } 1211 1212 if (rv != H_EOK) 1213 goto out; 1214 1215 if (abort_enable == KIOCABORTALTERNATE) { 1216 if (abort_charseq_recognize(buf)) { 1217 abort_sequence_enter((char *)NULL); 1218 } 1219 } 1220 1221 /* put console input onto stream */ 1222 if (qcn_state->qcn_readq) { 1223 if ((mp = allocb(1, BPRI_MED)) == NULL) { 1224 qcn_input_dropped++; 1225 cmn_err(CE_WARN, "qcn_intr: allocb" 1226 "failed (console input dropped)"); 1227 return; 1228 } 1229 *(char *)mp->b_wptr++ = buf; 1230 putnext(qcn_state->qcn_readq, mp); 1231 } 1232 } 1233 out: 1234 /* 1235 * If there are pending transmits because hypervisor 1236 * returned EWOULDBLOCK poke start now. 1237 */ 1238 1239 mutex_enter(&qcn_state->qcn_lock); 1240 if (qcn_state->qcn_writeq != NULL) { 1241 if (qcn_writeq_flush) { 1242 flushq(qcn_state->qcn_writeq, FLUSHDATA); 1243 } else { 1244 qcn_start(); 1245 } 1246 } 1247 mutex_exit(&qcn_state->qcn_lock); 1248 } 1249 #endif 1250 1251 /* 1252 * Check for abort character sequence, copied from zs_async.c 1253 */ 1254 #define CNTRL(c) ((c)&037) 1255 1256 static boolean_t 1257 abort_charseq_recognize(uchar_t ch) 1258 { 1259 static int state = 0; 1260 static char sequence[] = { '\r', '~', CNTRL('b') }; 1261 1262 if (ch == sequence[state]) { 1263 if (++state >= sizeof (sequence)) { 1264 state = 0; 1265 return (B_TRUE); 1266 } 1267 } else { 1268 state = (ch == sequence[0]) ? 1 : 0; 1269 } 1270 return (B_FALSE); 1271 } 1272 1273 1274 static int 1275 qcn_rsrv(queue_t *q) 1276 { 1277 mblk_t *mp; 1278 1279 if (qcn_stopped == B_TRUE) 1280 return (0); 1281 1282 mutex_enter(&qcn_state->qcn_lock); 1283 1284 while ((mp = getq(q)) != NULL) { 1285 if (canputnext(q)) 1286 putnext(q, mp); 1287 else if (mp->b_datap->db_type >= QPCTL) 1288 (void) putbq(q, mp); 1289 } 1290 1291 mutex_exit(&qcn_state->qcn_lock); 1292 1293 return (0); 1294 } 1295 1296 /* ARGSUSED */ 1297 static int 1298 qcn_wsrv(queue_t *q) 1299 { 1300 if (qcn_stopped == B_TRUE) 1301 return (0); 1302 1303 mutex_enter(&qcn_state->qcn_lock); 1304 1305 if (qcn_state->qcn_writeq != NULL) 1306 qcn_start(); 1307 1308 mutex_exit(&qcn_state->qcn_lock); 1309 1310 return (0); 1311 } 1312 1313 static boolean_t 1314 qcn_polledio_ischar(cons_polledio_arg_t arg) 1315 { 1316 qcn_t *state = (qcn_t *)arg; 1317 1318 if (state->qcn_char_available) 1319 return (B_TRUE); 1320 1321 return (state->qcn_char_available = 1322 (hv_cngetchar(&state->qcn_hold_char) == H_EOK)); 1323 } 1324 1325 1326 static int 1327 qcn_polledio_getchar(cons_polledio_arg_t arg) 1328 { 1329 qcn_t *state = (qcn_t *)arg; 1330 1331 while (!qcn_polledio_ischar(arg)) 1332 drv_usecwait(10); 1333 1334 state->qcn_char_available = B_FALSE; 1335 1336 return ((int)state->qcn_hold_char); 1337 } 1338 1339 static void 1340 qcn_polledio_putchar(cons_polledio_arg_t arg, uchar_t c) 1341 { 1342 if (c == '\n') 1343 qcn_polledio_putchar(arg, '\r'); 1344 1345 while (hv_cnputchar((uint8_t)c) == H_EWOULDBLOCK) 1346 drv_usecwait(10); 1347 } 1348 1349 static void 1350 qcn_polledio_enter(cons_polledio_arg_t arg) 1351 { 1352 qcn_t *state = (qcn_t *)arg; 1353 1354 state->qcn_char_available = B_FALSE; 1355 } 1356 1357 /* ARGSUSED */ 1358 static void 1359 qcn_polledio_exit(cons_polledio_arg_t arg) 1360 { 1361 } 1362