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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 /* 28 * MT STREAMS Virtual Console Device Driver 29 */ 30 31 #include <sys/types.h> 32 #include <sys/open.h> 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/signal.h> 36 #include <sys/cred.h> 37 #include <sys/user.h> 38 #include <sys/proc.h> 39 #include <sys/disp.h> 40 #include <sys/vnode.h> 41 #include <sys/uio.h> 42 #include <sys/buf.h> 43 #include <sys/file.h> 44 #include <sys/kmem.h> 45 #include <sys/stat.h> 46 #include <sys/stream.h> 47 #include <sys/stropts.h> 48 #include <sys/strsubr.h> 49 #include <sys/strsun.h> 50 #include <sys/tty.h> 51 #include <sys/ptyvar.h> 52 #include <sys/poll.h> 53 #include <sys/debug.h> 54 #include <sys/conf.h> 55 #include <sys/ddi.h> 56 #include <sys/sunddi.h> 57 #include <sys/errno.h> 58 #include <sys/modctl.h> 59 60 #include <sys/sc_cvc.h> 61 #include <sys/sc_cvcio.h> 62 #include <sys/iosramio.h> 63 64 static int cvc_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 65 static int cvc_attach(dev_info_t *, ddi_attach_cmd_t); 66 static int cvc_detach(dev_info_t *, ddi_detach_cmd_t); 67 static int cvc_open(register queue_t *, dev_t *, int, int, cred_t *); 68 static int cvc_close(queue_t *, int, cred_t *); 69 static int cvc_wput(queue_t *, mblk_t *); 70 static int cvc_wsrv(queue_t *); 71 static void cvc_ioctl(queue_t *, mblk_t *); 72 static void cvc_reioctl(void *); 73 static void cvc_input_daemon(void); 74 static void cvc_send_to_iosram(mblk_t **chainpp); 75 static void cvc_flush_queue(void *); 76 static void cvc_iosram_ops(uint8_t); 77 static void cvc_getstr(char *cp); 78 static void cvc_win_resize(int clear_flag); 79 80 #define ESUCCESS 0 81 #ifndef TRUE 82 #define TRUE 1 83 #define FALSE 0 84 #endif 85 86 /* 87 * Private copy of devinfo pointer; cvc_info uses it. 88 */ 89 static dev_info_t *cvcdip; 90 91 /* 92 * This structure reflects the layout of data in CONI and CONO. If you are 93 * going to add fields that don't get written into those chunks, be sure to 94 * place them _after_ the buffer field. 95 */ 96 typedef struct cvc_buf { 97 ushort_t count; 98 uchar_t buffer[MAX_XFER_COUTPUT]; 99 } cvc_buf_t; 100 101 typedef struct cvc_s { 102 bufcall_id_t cvc_wbufcid; 103 tty_common_t cvc_tty; 104 } cvc_t; 105 106 cvc_t cvc_common_tty; 107 108 static struct module_info cvcm_info = { 109 1313, /* mi_idnum Bad luck number ;-) */ 110 "cvc", /* mi_idname */ 111 0, /* mi_minpsz */ 112 INFPSZ, /* mi_maxpsz */ 113 2048, /* mi_hiwat */ 114 2048 /* mi_lowat */ 115 }; 116 117 static struct qinit cvcrinit = { 118 NULL, /* qi_putp */ 119 NULL, /* qi_srvp */ 120 cvc_open, /* qi_qopen */ 121 cvc_close, /* qi_qclose */ 122 NULL, /* qi_qadmin */ 123 &cvcm_info, /* qi_minfo */ 124 NULL /* qi_mstat */ 125 }; 126 127 static struct qinit cvcwinit = { 128 cvc_wput, /* qi_putp */ 129 cvc_wsrv, /* qi_srvp */ 130 cvc_open, /* qi_qopen */ 131 cvc_close, /* qi_qclose */ 132 NULL, /* qi_qadmin */ 133 &cvcm_info, /* qi_minfo */ 134 NULL /* qi_mstat */ 135 }; 136 137 struct streamtab cvcinfo = { 138 &cvcrinit, /* st_rdinit */ 139 &cvcwinit, /* st_wrinit */ 140 NULL, /* st_muxrinit */ 141 NULL /* st_muxwrinit */ 142 }; 143 144 static krwlock_t cvclock; /* lock protecting everything here */ 145 static queue_t *cvcinput_q; /* queue for console input */ 146 static queue_t *cvcoutput_q; /* queue for console output */ 147 static int cvc_instance = -1; 148 static int cvc_stopped = 0; 149 static int cvc_suspended = 0; 150 151 kthread_id_t cvc_input_daemon_thread; /* just to aid debugging */ 152 static kmutex_t cvcmutex; /* protects input */ 153 static kmutex_t cvc_iosram_input_mutex; /* protects IOSRAM inp buff */ 154 static int input_ok = 0; /* true when stream is valid */ 155 156 static int via_iosram = 0; /* toggle switch */ 157 static timeout_id_t cvc_timeout_id = (timeout_id_t)-1; 158 static int input_daemon_started = 0; 159 160 /* debugging functions */ 161 #ifdef DEBUG 162 uint32_t cvc_dbg_flags = 0x0; 163 static void cvc_dbg(uint32_t flag, char *fmt, 164 uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5); 165 #endif 166 167 /* 168 * Module linkage information for the kernel. 169 */ 170 171 DDI_DEFINE_STREAM_OPS(cvcops, nulldev, nulldev, cvc_attach, cvc_detach, 172 nodev, cvc_info, (D_NEW|D_MTPERQ|D_MP), &cvcinfo, 173 ddi_quiesce_not_supported); 174 175 extern int nodev(), nulldev(); 176 extern struct mod_ops mod_driverops; 177 178 static struct modldrv modldrv = { 179 &mod_driverops, /* Type of module. This one is a pseudo driver */ 180 "CVC driver 'cvc'", 181 &cvcops, /* driver ops */ 182 }; 183 184 static struct modlinkage modlinkage = { 185 MODREV_1, 186 &modldrv, 187 NULL 188 }; 189 190 int 191 _init() 192 { 193 int status; 194 195 status = mod_install(&modlinkage); 196 if (status == 0) { 197 mutex_init(&cvcmutex, NULL, MUTEX_DEFAULT, NULL); 198 } 199 return (status); 200 } 201 202 int 203 _fini() 204 { 205 return (EBUSY); 206 } 207 208 int 209 _info(struct modinfo *modinfop) 210 { 211 return (mod_info(&modlinkage, modinfop)); 212 } 213 214 /* 215 * DDI glue routines. 216 */ 217 218 /* ARGSUSED */ 219 static int 220 cvc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 221 { 222 static char been_here = 0; 223 224 if (cmd == DDI_RESUME) { 225 cvc_suspended = 0; 226 if (cvcinput_q != NULL) { 227 qenable(WR(cvcinput_q)); 228 } 229 return (DDI_SUCCESS); 230 } 231 232 mutex_enter(&cvcmutex); 233 if (!been_here) { 234 been_here = 1; 235 mutex_init(&cvc_iosram_input_mutex, NULL, MUTEX_DEFAULT, NULL); 236 rw_init(&cvclock, NULL, RW_DRIVER, NULL); 237 cvc_instance = ddi_get_instance(devi); 238 } else { 239 #if defined(DEBUG) 240 cmn_err(CE_NOTE, 241 "cvc_attach: called multiple times!! (instance = %d)", 242 ddi_get_instance(devi)); 243 #endif /* DEBUG */ 244 mutex_exit(&cvcmutex); 245 return (DDI_SUCCESS); 246 } 247 mutex_exit(&cvcmutex); 248 249 if (ddi_create_minor_node(devi, "cvc", S_IFCHR, 250 0, NULL, NULL) == DDI_FAILURE) { 251 ddi_remove_minor_node(devi, NULL); 252 return (-1); 253 } 254 cvcdip = devi; 255 cvcinput_q = NULL; 256 cvcoutput_q = NULL; 257 258 CVC_DBG0(CVC_DBG_ATTACH, "Attached"); 259 260 return (DDI_SUCCESS); 261 } 262 263 static int 264 cvc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 265 { 266 if (cmd == DDI_SUSPEND) { 267 cvc_suspended = 1; 268 } else { 269 if (cmd != DDI_DETACH) { 270 return (DDI_FAILURE); 271 } 272 /* 273 * XXX this doesn't even begin to address the detach 274 * issues - it doesn't terminate the outstanding thread, 275 * it doesn't clean up mutexes, kill the timeout routine 276 * etc. 277 */ 278 if (cvc_instance == ddi_get_instance(dip)) { 279 ddi_remove_minor_node(dip, NULL); 280 } 281 } 282 283 CVC_DBG0(CVC_DBG_DETACH, "Detached"); 284 285 return (DDI_SUCCESS); 286 } 287 288 /* ARGSUSED */ 289 static int 290 cvc_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 291 { 292 register int error; 293 294 switch (infocmd) { 295 case DDI_INFO_DEVT2DEVINFO: 296 if (cvcdip == NULL) { 297 error = DDI_FAILURE; 298 } else { 299 *result = (void *)cvcdip; 300 error = DDI_SUCCESS; 301 } 302 break; 303 case DDI_INFO_DEVT2INSTANCE: 304 *result = (void *)0; 305 error = DDI_SUCCESS; 306 break; 307 default: 308 error = DDI_FAILURE; 309 } 310 return (error); 311 } 312 313 /* ARGSUSED */ 314 static int 315 cvc_open(register queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp) 316 { 317 register int unit = getminor(*devp); 318 register int err = DDI_SUCCESS; 319 tty_common_t *tty; 320 cvc_t *cp; 321 322 if (unit != 0) 323 return (ENXIO); 324 325 if (q->q_ptr) 326 return (0); 327 328 cp = (cvc_t *)&cvc_common_tty; 329 bzero((caddr_t)cp, sizeof (cvc_t)); 330 cp->cvc_wbufcid = 0; 331 tty = &cp->cvc_tty; 332 tty->t_readq = q; 333 tty->t_writeq = WR(q); 334 WR(q)->q_ptr = q->q_ptr = (caddr_t)cp; 335 cvcinput_q = RD(q); /* save for cvc_redir */ 336 qprocson(q); 337 mutex_enter(&cvcmutex); 338 input_ok = 1; 339 340 /* 341 * Start the thread that handles input polling if it hasn't been started 342 * previously. 343 */ 344 if (!input_daemon_started) { 345 input_daemon_started = 1; 346 mutex_exit(&cvcmutex); 347 348 cvc_input_daemon_thread = thread_create(NULL, 0, 349 cvc_input_daemon, NULL, 0, &p0, TS_RUN, minclsyspri); 350 CVC_DBG0(CVC_DBG_IOSRAM_RD, "Started input daemon"); 351 } else { 352 mutex_exit(&cvcmutex); 353 } 354 355 /* 356 * Set the console window size. 357 */ 358 mutex_enter(&cvc_iosram_input_mutex); 359 cvc_win_resize(FALSE); 360 mutex_exit(&cvc_iosram_input_mutex); 361 362 CVC_DBG0(CVC_DBG_OPEN, "Plumbed successfully"); 363 364 return (err); 365 } 366 367 /* ARGSUSED */ 368 static int 369 cvc_close(queue_t *q, int flag, cred_t *crp) 370 { 371 register int err = DDI_SUCCESS; 372 register cvc_t *cp; 373 374 mutex_enter(&cvcmutex); 375 input_ok = 0; 376 mutex_exit(&cvcmutex); 377 378 cp = q->q_ptr; 379 if (cp->cvc_wbufcid != 0) { 380 unbufcall(cp->cvc_wbufcid); 381 } 382 ttycommon_close(&cp->cvc_tty); 383 WR(q)->q_ptr = q->q_ptr = NULL; 384 cvcinput_q = NULL; 385 bzero((caddr_t)cp, sizeof (cvc_t)); 386 qprocsoff(q); 387 388 CVC_DBG0(CVC_DBG_CLOSE, "Un-plumbed successfully"); 389 390 return (err); 391 } 392 393 394 /* 395 * cvc_wput() 396 * cn driver does a strwrite of console output data to rconsvp which has 397 * been set by consconfig. The data enters the cvc stream at the streamhead 398 * and flows thru ttycompat and ldterm which have been pushed on the 399 * stream. Console output data gets sent out either to cvcredir, if the 400 * network path is available and selected, or to IOSRAM otherwise. Data is 401 * sent to cvcredir via its read queue (cvcoutput_q, which gets set in 402 * cvc_register()). If the IOSRAM path is selected, or if previous mblks 403 * are currently queued up for processing, the new mblk will be queued 404 * and handled later on by cvc_wsrv. 405 */ 406 static int 407 cvc_wput(queue_t *q, mblk_t *mp) 408 { 409 int error = 0; 410 411 rw_enter(&cvclock, RW_READER); 412 413 CVC_DBG2(CVC_DBG_WPUT, "mp 0x%x db_type 0x%x", 414 mp, mp->b_datap->db_type); 415 416 switch (mp->b_datap->db_type) { 417 418 case M_IOCTL: 419 case M_CTL: { 420 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 421 422 switch (iocp->ioc_cmd) { 423 /* 424 * These ioctls are only supposed to be 425 * processed after everything else that is 426 * already queued awaiting processing, so throw 427 * them on the queue and let cvc_wsrv handle 428 * them. 429 */ 430 case TCSETSW: 431 case TCSETSF: 432 case TCSETAW: 433 case TCSETAF: 434 case TCSBRK: 435 putq(q, mp); 436 break; 437 438 default: 439 cvc_ioctl(q, mp); 440 } 441 break; 442 } 443 444 case M_FLUSH: 445 if (*mp->b_rptr & FLUSHW) { 446 /* 447 * Flush our write queue. 448 */ 449 flushq(q, FLUSHDATA); 450 *mp->b_rptr &= ~FLUSHW; 451 } 452 if (*mp->b_rptr & FLUSHR) { 453 flushq(RD(q), FLUSHDATA); 454 qreply(q, mp); 455 } else 456 freemsg(mp); 457 break; 458 459 case M_STOP: 460 cvc_stopped = 1; 461 freemsg(mp); 462 break; 463 464 case M_START: 465 cvc_stopped = 0; 466 freemsg(mp); 467 qenable(q); /* Start up delayed messages */ 468 break; 469 470 case M_READ: 471 /* 472 * ldterm handles this (VMIN/VTIME processing). 473 */ 474 freemsg(mp); 475 break; 476 477 default: 478 cmn_err(CE_WARN, "cvc_wput: unexpected mblk type - mp =" 479 " 0x%p, type = 0x%x", mp, mp->b_datap->db_type); 480 freemsg(mp); 481 break; 482 483 case M_DATA: 484 /* 485 * If there are other mblks queued up for transmission, 486 * or we're using IOSRAM either because cvcredir hasn't 487 * registered yet or because we were configured that 488 * way, or cvc has been stopped or suspended, place this 489 * mblk on the input queue for future processing. 490 * Otherwise, hand it off to cvcredir for transmission 491 * via the network. 492 */ 493 if (q->q_first != NULL || cvcoutput_q == NULL || 494 via_iosram || cvc_stopped == 1 || 495 cvc_suspended == 1) { 496 (void) putq(q, mp); 497 } else { 498 /* 499 * XXX - should canputnext be called here? 500 * Starfire's cvc doesn't do that, and it 501 * appears to work anyway. 502 */ 503 (void) putnext(cvcoutput_q, mp); 504 } 505 break; 506 507 } 508 rw_exit(&cvclock); 509 return (error); 510 } 511 512 /* 513 * cvc_wsrv() 514 * cvc_wsrv handles mblks that have been queued by cvc_wput either because 515 * the IOSRAM path was selected or the queue contained preceding mblks. To 516 * optimize processing (particularly if the IOSRAM path is selected), all 517 * mblks are pulled off of the queue and chained together. Then, if there 518 * are any mblks on the chain, they are either forwarded to cvcredir or 519 * sent for IOSRAM processing as appropriate given current circumstances. 520 * IOSRAM processing may not be able to handle all of the data in the 521 * chain, in which case the remaining data is placed back on the queue and 522 * a timeout routine is registered to reschedule cvc_wsrv in the future. 523 * Automatic scheduling of the queue is disabled (noenable(q)) while 524 * cvc_wsrv is running to avoid superfluous calls. 525 */ 526 static int 527 cvc_wsrv(queue_t *q) 528 { 529 mblk_t *total_mp = NULL; 530 mblk_t *mp; 531 532 if (cvc_stopped == 1 || cvc_suspended == 1) { 533 return (0); 534 } 535 536 rw_enter(&cvclock, RW_READER); 537 noenable(q); 538 539 /* 540 * If there's already a timeout registered for scheduling this routine 541 * in the future, it's a safe bet that we don't want to run right now. 542 */ 543 if (cvc_timeout_id != (timeout_id_t)-1) { 544 enableok(q); 545 rw_exit(&cvclock); 546 return (0); 547 } 548 549 /* 550 * Start by linking all of the queued M_DATA mblks into a single chain 551 * so we can flush as much as possible to IOSRAM (if we choose that 552 * route). 553 */ 554 while ((mp = getq(q)) != NULL) { 555 /* 556 * Technically, certain IOCTLs are supposed to be processed only 557 * after all preceding data has completely "drained". In an 558 * attempt to support that, we delay processing of those IOCTLs 559 * until this point. It is still possible that an IOCTL will be 560 * processed before all preceding data is drained, for instance 561 * in the case where not all of the preceding data would fit 562 * into IOSRAM and we have to place it back on the queue. 563 * However, since none of these IOCTLs really appear to have any 564 * relevance for cvc, and we weren't supporting delayed 565 * processing at _all_ previously, this partial implementation 566 * should suffice. (Fully implementing the delayed IOCTL 567 * processing would be unjustifiably difficult given the nature 568 * of the underlying IOSRAM console protocol.) 569 */ 570 if (mp->b_datap->db_type == M_IOCTL) { 571 cvc_ioctl(q, mp); 572 continue; 573 } 574 575 /* 576 * We know that only M_IOCTL and M_DATA blocks are placed on our 577 * queue. Since this block isn't an M_IOCTL, it must be M_DATA. 578 */ 579 if (total_mp != NULL) { 580 linkb(total_mp, mp); 581 } else { 582 total_mp = mp; 583 } 584 } 585 586 /* 587 * Do we actually have anything to do? 588 */ 589 if (total_mp == NULL) { 590 enableok(q); 591 rw_exit(&cvclock); 592 return (0); 593 } 594 595 /* 596 * Yes, we do, so send the data to either cvcredir or IOSRAM as 597 * appropriate. In the latter case, we might not be able to transmit 598 * everything right now, so re-queue the remainder. 599 */ 600 if (cvcoutput_q != NULL && !via_iosram) { 601 CVC_DBG0(CVC_DBG_NETWORK_WR, "Sending to cvcredir."); 602 /* 603 * XXX - should canputnext be called here? Starfire's cvc 604 * doesn't do that, and it appears to work anyway. 605 */ 606 (void) putnext(cvcoutput_q, total_mp); 607 } else { 608 CVC_DBG0(CVC_DBG_IOSRAM_WR, "Send to IOSRAM."); 609 cvc_send_to_iosram(&total_mp); 610 if (total_mp != NULL) { 611 (void) putbq(q, total_mp); 612 } 613 } 614 615 /* 616 * If there is still data queued at this point, make sure the queue 617 * gets scheduled again after an appropriate delay (which has been 618 * somewhat arbitrarily selected as half of the SC's input polling 619 * frequency). 620 */ 621 enableok(q); 622 if (q->q_first != NULL) { 623 if (cvc_timeout_id == (timeout_id_t)-1) { 624 cvc_timeout_id = timeout(cvc_flush_queue, 625 NULL, drv_usectohz(CVC_IOSRAM_POLL_USECS / 2)); 626 } 627 } 628 rw_exit(&cvclock); 629 return (0); 630 } 631 632 633 /* 634 * cvc_ioctl() 635 * handle normal console ioctls. 636 */ 637 static void 638 cvc_ioctl(register queue_t *q, register mblk_t *mp) 639 { 640 register cvc_t *cp = q->q_ptr; 641 int datasize; 642 int error = 0; 643 644 /* 645 * Let ttycommon_ioctl take the first shot at processing the ioctl. If 646 * it fails because it can't allocate memory, schedule processing of the 647 * ioctl later when a proper buffer is available. The mblk that 648 * couldn't be processed will have been stored in the tty structure by 649 * ttycommon_ioctl. 650 */ 651 datasize = ttycommon_ioctl(&cp->cvc_tty, q, mp, &error); 652 if (datasize != 0) { 653 if (cp->cvc_wbufcid) { 654 unbufcall(cp->cvc_wbufcid); 655 } 656 cp->cvc_wbufcid = bufcall(datasize, BPRI_HI, cvc_reioctl, cp); 657 return; 658 } 659 660 /* 661 * ttycommon_ioctl didn't do anything, but there's nothing we really 662 * support either with the exception of TCSBRK, which is supported 663 * only to appear a bit more like a serial device for software that 664 * expects TCSBRK to work. 665 */ 666 if (error != 0) { 667 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 668 669 if (iocp->ioc_cmd == TCSBRK) { 670 miocack(q, mp, 0, 0); 671 } else { 672 miocnak(q, mp, 0, EINVAL); 673 } 674 } else { 675 qreply(q, mp); 676 } 677 } 678 679 680 /* 681 * cvc_redir() 682 * called from cvcredir:cvcr_wput() to handle console input 683 * data. This routine puts the cvcredir write (downstream) data 684 * onto the cvc read (upstream) queues. 685 */ 686 int 687 cvc_redir(mblk_t *mp) 688 { 689 register struct iocblk *iocp; 690 int rv = 1; 691 692 /* 693 * This function shouldn't be called if cvcredir hasn't registered yet. 694 */ 695 if (cvcinput_q == NULL) { 696 /* 697 * Need to let caller know that it may be necessary for them to 698 * free the message buffer, so return 0. 699 */ 700 CVC_DBG0(CVC_DBG_REDIR, "redirection not enabled"); 701 cmn_err(CE_WARN, "cvc_redir: cvcinput_q NULL!"); 702 return (0); 703 } 704 705 CVC_DBG1(CVC_DBG_REDIR, "type 0x%x", mp->b_datap->db_type); 706 if (mp->b_datap->db_type == M_DATA) { 707 /* 708 * XXX - should canputnext be called here? Starfire's cvc 709 * doesn't do that, and it appears to work anyway. 710 */ 711 CVC_DBG1(CVC_DBG_NETWORK_RD, "Sending mp 0x%x", mp); 712 (void) putnext(cvcinput_q, mp); 713 } else if (mp->b_datap->db_type == M_IOCTL) { 714 /* 715 * The cvcredir driver filters out ioctl mblks we wouldn't 716 * understand, so we don't have to check for every conceivable 717 * ioc_cmd. However, additional ioctls may be supported (again) 718 * some day, so the code is structured to check the value even 719 * though there's only one that is currently supported. 720 */ 721 iocp = (struct iocblk *)mp->b_rptr; 722 if (iocp->ioc_cmd == CVC_DISCONNECT) { 723 (void) putnextctl(cvcinput_q, M_HANGUP); 724 } 725 } else { 726 /* 727 * Since we don't know what this mblk is, we're not going to 728 * process it. 729 */ 730 CVC_DBG1(CVC_DBG_REDIR, "unrecognized mblk type: %d", 731 mp->b_datap->db_type); 732 rv = 0; 733 } 734 735 return (rv); 736 } 737 738 739 /* 740 * cvc_register() 741 * called from cvcredir to register it's queues. cvc 742 * receives data from cn via the streamhead and sends it to cvcredir 743 * via pointers to cvcredir's queues. 744 */ 745 int 746 cvc_register(queue_t *q) 747 { 748 int error = -1; 749 750 if (cvcinput_q == NULL) 751 cmn_err(CE_WARN, "cvc_register: register w/ no console open!"); 752 rw_enter(&cvclock, RW_WRITER); 753 if (cvcoutput_q == NULL) { 754 cvcoutput_q = RD(q); /* Make sure its the upstream q */ 755 qprocson(cvcoutput_q); /* must be done within cvclock */ 756 error = 0; 757 } else { 758 /* 759 * cmn_err will call us, so release lock. 760 */ 761 rw_exit(&cvclock); 762 if (cvcoutput_q == q) 763 cmn_err(CE_WARN, "cvc_register: duplicate q!"); 764 else 765 cmn_err(CE_WARN, "cvc_register: nondup q = 0x%p", 766 q); 767 return (error); 768 } 769 rw_exit(&cvclock); 770 return (error); 771 } 772 773 774 /* 775 * cvc_unregister() 776 * called from cvcredir to clear pointers to its queues. 777 * cvcredir no longer wants to send or receive data. 778 */ 779 void 780 cvc_unregister(queue_t *q) 781 { 782 rw_enter(&cvclock, RW_WRITER); 783 if (q == cvcoutput_q) { 784 qprocsoff(cvcoutput_q); /* must be done within cvclock */ 785 cvcoutput_q = NULL; 786 } else { 787 rw_exit(&cvclock); 788 cmn_err(CE_WARN, "cvc_unregister: q = 0x%p not registered", q); 789 return; 790 } 791 rw_exit(&cvclock); 792 } 793 794 795 /* 796 * cvc_reioctl() 797 * Retry an "ioctl", now that "bufcall" claims we may be able 798 * to allocate the buffer we need. 799 */ 800 static void 801 cvc_reioctl(void *unit) 802 { 803 register queue_t *q; 804 register mblk_t *mp; 805 register cvc_t *cp = (cvc_t *)unit; 806 807 /* 808 * The bufcall is no longer pending. 809 */ 810 if (!cp->cvc_wbufcid) { 811 return; 812 } 813 cp->cvc_wbufcid = 0; 814 if ((q = cp->cvc_tty.t_writeq) == NULL) { 815 return; 816 } 817 if ((mp = cp->cvc_tty.t_iocpending) != NULL) { 818 /* not pending any more */ 819 cp->cvc_tty.t_iocpending = NULL; 820 cvc_ioctl(q, mp); 821 } 822 } 823 824 825 /* 826 * cvc_iosram_ops() 827 * Process commands sent to cvc from netcon_server via IOSRAM 828 */ 829 static void 830 cvc_iosram_ops(uint8_t op) 831 { 832 int rval = ESUCCESS; 833 static uint8_t stale_op = 0; 834 835 ASSERT(MUTEX_HELD(&cvc_iosram_input_mutex)); 836 837 CVC_DBG1(CVC_DBG_IOSRAM_CNTL, "cntl msg 0x%x", op); 838 839 /* 840 * If this is a repeated notice of a command that was previously 841 * processed but couldn't be cleared due to EAGAIN (tunnel switch in 842 * progress), just clear the data_valid flag and return. 843 */ 844 if (op == stale_op) { 845 if (iosram_set_flag(IOSRAM_KEY_CONC, IOSRAM_DATA_INVALID, 846 IOSRAM_INT_NONE) == 0) { 847 stale_op = 0; 848 } 849 return; 850 } 851 stale_op = 0; 852 853 switch (op) { 854 case CVC_IOSRAM_BREAK: /* A console break (L1-A) */ 855 abort_sequence_enter((char *)NULL); 856 break; 857 858 case CVC_IOSRAM_DISCONNECT: /* Break connection, hang up */ 859 if (cvcinput_q) 860 (void) putnextctl(cvcinput_q, M_HANGUP); 861 break; 862 863 case CVC_IOSRAM_VIA_NET: /* console via network */ 864 via_iosram = 0; 865 break; 866 867 case CVC_IOSRAM_VIA_IOSRAM: /* console via iosram */ 868 via_iosram = 1; 869 /* 870 * Tell cvcd to close any network connection it has. 871 */ 872 rw_enter(&cvclock, RW_READER); 873 if (cvcoutput_q != NULL) { 874 (void) putnextctl(cvcoutput_q, M_HANGUP); 875 } 876 rw_exit(&cvclock); 877 break; 878 879 case CVC_IOSRAM_WIN_RESIZE: /* console window size data */ 880 /* 881 * In the case of window resizing, we don't want to 882 * record a stale_op value because we should always use 883 * the most recent winsize info, which could change 884 * between the time that we fail to clear the flag and 885 * the next time we try to process the command. So, 886 * we'll just let cvc_win_resize clear the data_valid 887 * flag itself (hence the TRUE parameter) and not worry 888 * about whether or not it succeeds. 889 */ 890 cvc_win_resize(TRUE); 891 return; 892 /* NOTREACHED */ 893 894 default: 895 cmn_err(CE_WARN, "cvc: unknown IOSRAM opcode %d", op); 896 break; 897 } 898 899 /* 900 * Clear CONC's data_valid flag to indicate that the chunk is available 901 * for further communications. If the flag can't be cleared due to an 902 * error, record the op value so we'll know to ignore it when we see it 903 * on the next poll. 904 */ 905 rval = iosram_set_flag(IOSRAM_KEY_CONC, IOSRAM_DATA_INVALID, 906 IOSRAM_INT_NONE); 907 if (rval != 0) { 908 stale_op = op; 909 if (rval != EAGAIN) { 910 cmn_err(CE_WARN, 911 "cvc_iosram_ops: set flag for cntlbuf ret %d", 912 rval); 913 } 914 } 915 } 916 917 918 /* 919 * cvc_send_to_iosram() 920 * Flush as much data as possible to the CONO chunk. If successful, free 921 * any mblks that were completely transmitted, update the b_rptr field in 922 * the first remaining mblk if it was partially transmitted, and update the 923 * caller's pointer to the new head of the mblk chain. Since the software 924 * that will be pulling this data out of IOSRAM (dxs on the SC) is just 925 * polling at some frequency, we avoid attempts to flush data to IOSRAM any 926 * faster than a large divisor of that polling frequency. 927 * 928 * Note that "cvc_buf_t out" is only declared "static" to keep it from 929 * being allocated on the stack. Allocating 1K+ structures on the stack 930 * seems rather antisocial. 931 */ 932 static void 933 cvc_send_to_iosram(mblk_t **chainpp) 934 { 935 int rval; 936 uint8_t dvalid; 937 uchar_t *cp; 938 mblk_t *mp; 939 mblk_t *last_empty_mp; 940 static clock_t last_flush = (clock_t)-1; 941 static cvc_buf_t out; /* see note above about static */ 942 943 ASSERT(chainpp != NULL); 944 945 /* 946 * We _do_ have something to do, right? 947 */ 948 if (*chainpp == NULL) { 949 return; 950 } 951 952 /* 953 * We can actually increase throughput by throttling back on attempts to 954 * flush data to IOSRAM, since trying to write every little bit of data 955 * as it shows up will actually generate more delays waiting for the SC 956 * to pick up each of those bits. Instead, we'll avoid attempting to 957 * write data to IOSRAM any faster than half of the polling frequency we 958 * expect the SC to be using. 959 */ 960 if (ddi_get_lbolt() - last_flush < 961 drv_usectohz(CVC_IOSRAM_POLL_USECS / 2)) { 962 return; 963 } 964 965 /* 966 * If IOSRAM is inaccessible or the CONO chunk still holds data that 967 * hasn't been picked up by the SC, there's nothing we can do right now. 968 */ 969 rval = iosram_get_flag(IOSRAM_KEY_CONO, &dvalid, NULL); 970 if ((rval != 0) || (dvalid == IOSRAM_DATA_VALID)) { 971 if ((rval != 0) && (rval != EAGAIN)) { 972 cmn_err(CE_WARN, "cvc_send_to_iosram: get_flag ret %d", 973 rval); 974 } 975 return; 976 } 977 978 /* 979 * Copy up to MAX_XFER_COUTPUT chars from the mblk chain into a buffer. 980 * Don't change any of the mblks just yet, since we can't be certain 981 * that we'll be successful in writing data to the CONO chunk. 982 */ 983 out.count = 0; 984 mp = *chainpp; 985 cp = mp->b_rptr; 986 last_empty_mp = NULL; 987 while ((mp != NULL) && (out.count < MAX_XFER_COUTPUT)) { 988 /* 989 * Process as many of the characters in the current mblk as 990 * possible. 991 */ 992 while ((cp != mp->b_wptr) && (out.count < MAX_XFER_COUTPUT)) { 993 out.buffer[out.count++] = *cp++; 994 } 995 996 /* 997 * Did we process that entire mblk? If so, move on to the next 998 * one. If not, we're done filling the buffer even if there's 999 * space left, because apparently there wasn't room to process 1000 * the next character. 1001 */ 1002 if (cp != mp->b_wptr) { 1003 break; 1004 } 1005 1006 /* 1007 * When this loop terminates, last_empty_mp will point to the 1008 * last mblk that was completely processed, mp will point to the 1009 * following mblk (or NULL if no more mblks exist), and cp will 1010 * point to the first untransmitted character in the mblk 1011 * pointed to by mp. We'll need this data to update the mblk 1012 * chain if all of the data is successfully transmitted. 1013 */ 1014 last_empty_mp = mp; 1015 mp = mp->b_cont; 1016 cp = (mp != NULL) ? mp->b_rptr : NULL; 1017 } 1018 1019 /* 1020 * If we succeeded in preparing some data, try to transmit it through 1021 * IOSRAM. First write the count and the data, which can be done in a 1022 * single operation thanks to the buffer structure we use, then set the 1023 * data_valid flag if the first step succeeded. 1024 */ 1025 if (out.count != 0) { 1026 rval = iosram_wr(IOSRAM_KEY_CONO, COUNT_OFFSET, 1027 CONSBUF_COUNT_SIZE + out.count, (caddr_t)&out); 1028 if ((rval != 0) && (rval != EAGAIN)) { 1029 cmn_err(CE_WARN, "cvc_putc: write ret %d", rval); 1030 } 1031 1032 /* if the data write succeeded, set the data_valid flag */ 1033 if (rval == 0) { 1034 rval = iosram_set_flag(IOSRAM_KEY_CONO, 1035 IOSRAM_DATA_VALID, IOSRAM_INT_NONE); 1036 if ((rval != 0) && (rval != EAGAIN)) { 1037 cmn_err(CE_WARN, 1038 "cvc_putc: set flags for outbuf ret %d", 1039 rval); 1040 } 1041 } 1042 1043 /* 1044 * If we successfully transmitted any data, modify the caller's 1045 * mblk chain to remove the data that was transmitted, freeing 1046 * all mblks that were completely processed. 1047 */ 1048 if (rval == 0) { 1049 last_flush = ddi_get_lbolt(); 1050 1051 /* 1052 * If any data is left over, update the b_rptr field of 1053 * the first remaining mblk in case some of its data was 1054 * processed. 1055 */ 1056 if (mp != NULL) { 1057 mp->b_rptr = cp; 1058 } 1059 1060 /* 1061 * If any mblks have been emptied, unlink them from the 1062 * residual chain, free them, and update the caller's 1063 * mblk pointer. 1064 */ 1065 if (last_empty_mp != NULL) { 1066 last_empty_mp->b_cont = NULL; 1067 freemsg(*chainpp); 1068 *chainpp = mp; 1069 } 1070 } 1071 } 1072 } 1073 1074 1075 /* 1076 * cvc_flush_queue() 1077 * Tell the STREAMS subsystem to schedule cvc_wsrv to process the queue we 1078 * use to gather console output. 1079 */ 1080 /* ARGSUSED */ 1081 static void 1082 cvc_flush_queue(void *notused) 1083 { 1084 rw_enter(&cvclock, RW_WRITER); 1085 if (cvcinput_q != NULL) { 1086 qenable(WR(cvcinput_q)); 1087 } 1088 1089 cvc_timeout_id = (timeout_id_t)-1; 1090 rw_exit(&cvclock); 1091 } 1092 1093 1094 /* 1095 * cvc_getstr() 1096 * Poll IOSRAM for console input while available. 1097 */ 1098 static void 1099 cvc_getstr(char *cp) 1100 { 1101 short count; 1102 uint8_t command = 0; 1103 int rval = ESUCCESS; 1104 uint8_t dvalid = IOSRAM_DATA_INVALID; 1105 uint8_t intrpending = 0; 1106 1107 mutex_enter(&cvc_iosram_input_mutex); 1108 while (dvalid == IOSRAM_DATA_INVALID) { 1109 /* 1110 * Check the CONC data_valid flag to see if a control message is 1111 * available. 1112 */ 1113 rval = iosram_get_flag(IOSRAM_KEY_CONC, &dvalid, &intrpending); 1114 if ((rval != 0) && (rval != EAGAIN)) { 1115 cmn_err(CE_WARN, 1116 "cvc_getstr: get flag for cntl ret %d", rval); 1117 } 1118 1119 /* 1120 * If a control message is available, try to read and process 1121 * it. 1122 */ 1123 if ((dvalid == IOSRAM_DATA_VALID) && (rval == 0)) { 1124 /* read the control reg offset */ 1125 rval = iosram_rd(IOSRAM_KEY_CONC, 1126 CVC_CTL_OFFSET(command), CVC_CTL_SIZE(command), 1127 (caddr_t)&command); 1128 if ((rval != 0) && (rval != EAGAIN)) { 1129 cmn_err(CE_WARN, 1130 "cvc_getstr: read for command ret %d", 1131 rval); 1132 } 1133 1134 /* process the cntl msg and clear the data_valid flag */ 1135 if (rval == 0) { 1136 cvc_iosram_ops(command); 1137 } 1138 } 1139 1140 /* 1141 * Check the CONI data_valid flag to see if console input data 1142 * is available. 1143 */ 1144 rval = iosram_get_flag(IOSRAM_KEY_CONI, &dvalid, &intrpending); 1145 if ((rval != 0) && (rval != EAGAIN)) { 1146 cmn_err(CE_WARN, 1147 "cvc_getstr: get flag for inbuf ret %d", 1148 rval); 1149 } 1150 if ((rval != 0) || (dvalid != IOSRAM_DATA_VALID)) { 1151 goto retry; 1152 } 1153 1154 /* 1155 * Try to read the count. 1156 */ 1157 rval = iosram_rd(IOSRAM_KEY_CONI, COUNT_OFFSET, 1158 CONSBUF_COUNT_SIZE, (caddr_t)&count); 1159 if (rval != 0) { 1160 if (rval != EAGAIN) { 1161 cmn_err(CE_WARN, 1162 "cvc_getstr: read for count ret %d", rval); 1163 } 1164 goto retry; 1165 } 1166 1167 /* 1168 * If there is data to be read, try to read it. 1169 */ 1170 if (count != 0) { 1171 rval = iosram_rd(IOSRAM_KEY_CONI, DATA_OFFSET, count, 1172 (caddr_t)cp); 1173 if (rval != 0) { 1174 if (rval != EAGAIN) { 1175 cmn_err(CE_WARN, 1176 "cvc_getstr: read for count ret %d", 1177 rval); 1178 } 1179 goto retry; 1180 } 1181 cp[count] = '\0'; 1182 } 1183 1184 /* 1185 * Try to clear the data_valid flag to indicate that whatever 1186 * was in CONI was read successfully. If successful, and some 1187 * data was read, break out of the loop to return to the caller. 1188 */ 1189 rval = iosram_set_flag(IOSRAM_KEY_CONI, IOSRAM_DATA_INVALID, 1190 IOSRAM_INT_NONE); 1191 if (rval != 0) { 1192 if (rval != EAGAIN) { 1193 cmn_err(CE_WARN, 1194 "cvc_getstr: set flag for inbuf ret %d", 1195 rval); 1196 } 1197 } else if (count != 0) { 1198 CVC_DBG1(CVC_DBG_IOSRAM_RD, "Read 0x%x", count); 1199 break; 1200 } 1201 1202 /* 1203 * Use a smaller delay between checks of IOSRAM for input 1204 * when cvcd/cvcredir are not running or "via_iosram" has 1205 * been set. 1206 * We don't go away completely when i/o is going through the 1207 * network via cvcd since a command may be sent via IOSRAM 1208 * to switch if the network is down or hung. 1209 */ 1210 retry: 1211 if ((cvcoutput_q == NULL) || (via_iosram)) 1212 delay(drv_usectohz(CVC_IOSRAM_POLL_USECS)); 1213 else 1214 delay(drv_usectohz(CVC_IOSRAM_POLL_USECS * 10)); 1215 1216 } 1217 1218 mutex_exit(&cvc_iosram_input_mutex); 1219 } 1220 1221 1222 /* 1223 * cvc_input_daemon() 1224 * this function runs as a separate kernel thread and polls IOSRAM for 1225 * input, and possibly put it on read stream for the console. 1226 * There are two poll rates (implemented in cvc_getstr): 1227 * 100 000 uS (10 Hz) - no cvcd communications || via_iosram 1228 * 1000 000 uS ( 1 Hz) - cvcd communications 1229 * This continues to run even if there are network console communications 1230 * in order to handle out-of-band signaling. 1231 */ 1232 /* ARGSUSED */ 1233 static void 1234 cvc_input_daemon(void) 1235 { 1236 char linebuf[MAX_XFER_CINPUT + 1]; 1237 char *cp; 1238 mblk_t *mbp; 1239 int c; 1240 int dropped_read = 0; 1241 1242 for (;;) { 1243 cvc_getstr(linebuf); 1244 1245 mbp = allocb(strlen(linebuf), BPRI_MED); 1246 if (mbp == NULL) { /* drop it & go on if no buffer */ 1247 if (!dropped_read) { 1248 cmn_err(CE_WARN, "cvc_input_daemon: " 1249 "dropping IOSRAM reads"); 1250 } 1251 dropped_read++; 1252 continue; 1253 } 1254 1255 if (dropped_read) { 1256 cmn_err(CE_WARN, 1257 "cvc_input_daemon: dropped %d IOSRAM reads", 1258 dropped_read); 1259 dropped_read = 0; 1260 } 1261 1262 for (cp = linebuf; *cp != '\0'; cp++) { 1263 c = (int)*cp; 1264 if (c == '\r') 1265 c = '\n'; 1266 c &= 0177; 1267 *mbp->b_wptr = (char)c; 1268 mbp->b_wptr++; 1269 } 1270 mutex_enter(&cvcmutex); 1271 if (input_ok) { 1272 if (cvcinput_q == NULL) { 1273 cmn_err(CE_WARN, 1274 "cvc_input_daemon: cvcinput_q is NULL!"); 1275 } else { 1276 /* 1277 * XXX - should canputnext be called here? 1278 * Starfire's cvc doesn't do that, and it 1279 * appears to work anyway. 1280 */ 1281 (void) putnext(cvcinput_q, mbp); 1282 } 1283 } else { 1284 freemsg(mbp); 1285 } 1286 mutex_exit(&cvcmutex); 1287 } 1288 1289 /* NOTREACHED */ 1290 } 1291 1292 /* 1293 * cvc_win_resize() 1294 * cvc_win_resize will read winsize data from the CONC IOSRAM chunk and set 1295 * the console window size accordingly. If indicated by the caller, CONC's 1296 * data_valid flag will also be cleared. The flag isn't cleared in all 1297 * cases because we need to process winsize data at startup without waiting 1298 * for a command. 1299 */ 1300 static void 1301 cvc_win_resize(int clear_flag) 1302 { 1303 int rval; 1304 uint16_t rows; 1305 uint16_t cols; 1306 uint16_t xpixels; 1307 uint16_t ypixels; 1308 tty_common_t *tty; 1309 cvc_t *cp; 1310 struct winsize ws; 1311 1312 /* 1313 * Start by reading the new window size out of the CONC chunk and, if 1314 * requested, clearing CONC's data_valid flag. If any of that fails, 1315 * return immediately. (Note that the rather bulky condition in the 1316 * two "if" statements takes advantage of C's short-circuit logic 1317 * evaluation) 1318 */ 1319 if (((rval = iosram_rd(IOSRAM_KEY_CONC, CVC_CTL_OFFSET(winsize_rows), 1320 CVC_CTL_SIZE(winsize_rows), (caddr_t)&rows)) != 0) || 1321 ((rval = iosram_rd(IOSRAM_KEY_CONC, CVC_CTL_OFFSET(winsize_cols), 1322 CVC_CTL_SIZE(winsize_cols), (caddr_t)&cols)) != 0) || 1323 ((rval = iosram_rd(IOSRAM_KEY_CONC, 1324 CVC_CTL_OFFSET(winsize_xpixels), CVC_CTL_SIZE(winsize_xpixels), 1325 (caddr_t)&xpixels)) != 0) || ((rval = iosram_rd(IOSRAM_KEY_CONC, 1326 CVC_CTL_OFFSET(winsize_ypixels), CVC_CTL_SIZE(winsize_ypixels), 1327 (caddr_t)&ypixels)) != 0)) { 1328 if (rval != EAGAIN) { 1329 cmn_err(CE_WARN, 1330 "cvc_win_resize: read for ctlbuf ret %d", rval); 1331 } 1332 return; 1333 } 1334 1335 if (clear_flag && ((rval = iosram_set_flag(IOSRAM_KEY_CONC, 1336 IOSRAM_DATA_INVALID, IOSRAM_INT_NONE)) != 0)) { 1337 if (rval != EAGAIN) { 1338 cmn_err(CE_WARN, 1339 "cvc_win_resize: set_flag for ctlbuf ret %d", rval); 1340 } 1341 return; 1342 } 1343 1344 /* 1345 * Copy the parameters from IOSRAM to a winsize struct. 1346 */ 1347 ws.ws_row = rows; 1348 ws.ws_col = cols; 1349 ws.ws_xpixel = xpixels; 1350 ws.ws_ypixel = ypixels; 1351 1352 /* 1353 * This code was taken from Starfire, and it appears to work correctly. 1354 * However, since the original developer felt it necessary to add the 1355 * following comment, it's probably worth preserving: 1356 * 1357 * XXX I hope this is safe... 1358 */ 1359 cp = cvcinput_q->q_ptr; 1360 tty = &cp->cvc_tty; 1361 mutex_enter(&tty->t_excl); 1362 if (bcmp((caddr_t)&tty->t_size, (caddr_t)&ws, 1363 sizeof (struct winsize))) { 1364 tty->t_size = ws; 1365 mutex_exit(&tty->t_excl); 1366 (void) putnextctl1(cvcinput_q, M_PCSIG, 1367 SIGWINCH); 1368 } else { 1369 mutex_exit(&tty->t_excl); 1370 } 1371 } 1372 1373 #ifdef DEBUG 1374 1375 void 1376 cvc_dbg(uint32_t flag, char *fmt, 1377 uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5) 1378 { 1379 char *s = NULL; 1380 char buf[256]; 1381 1382 if (cvc_dbg_flags && ((cvc_dbg_flags & flag) == flag)) { 1383 switch (flag) { 1384 case CVC_DBG_ATTACH: 1385 s = "attach"; 1386 break; 1387 case CVC_DBG_DETACH: 1388 s = "detach"; 1389 break; 1390 case CVC_DBG_OPEN: 1391 s = "open"; 1392 break; 1393 case CVC_DBG_CLOSE: 1394 s = "close"; 1395 break; 1396 case CVC_DBG_IOCTL: 1397 s = "ioctl"; 1398 break; 1399 case CVC_DBG_REDIR: 1400 s = "redir"; 1401 break; 1402 case CVC_DBG_WPUT: 1403 s = "wput"; 1404 break; 1405 case CVC_DBG_WSRV: 1406 s = "wsrv"; 1407 break; 1408 case CVC_DBG_IOSRAM_WR: 1409 s = "iosram_wr"; 1410 break; 1411 case CVC_DBG_IOSRAM_RD: 1412 s = "iosram_rd"; 1413 break; 1414 case CVC_DBG_NETWORK_WR: 1415 s = "network_wr"; 1416 break; 1417 case CVC_DBG_NETWORK_RD: 1418 s = "network_rd"; 1419 break; 1420 case CVC_DBG_IOSRAM_CNTL: 1421 s = "iosram_cntlmsg"; 1422 break; 1423 default: 1424 s = "Unknown debug flag"; 1425 break; 1426 } 1427 1428 sprintf(buf, "!%s_%s(%d): %s", ddi_driver_name(cvcdip), s, 1429 cvc_instance, fmt); 1430 cmn_err(CE_NOTE, buf, a1, a2, a3, a4, a5); 1431 } 1432 } 1433 1434 #endif /* DEBUG */ 1435