Print this page
8527 tty buffer/queue sizes should be larger
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/ptem.c
+++ new/usr/src/uts/common/io/ptem.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
21 21 */
22 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 23 /* All Rights Reserved */
24 24
25 25
26 26 /*
27 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
28 28 * Use is subject to license terms.
29 29 */
30 30
31 -#pragma ident "%Z%%M% %I% %E% SMI" /* from S5R4 1.13 */
32 -
33 31 /*
34 32 * Description:
35 33 *
36 34 * The PTEM streams module is used as a pseudo driver emulator. Its purpose
37 35 * is to emulate the ioctl() functions of a terminal device driver.
38 36 */
39 37
40 38 #include <sys/types.h>
41 39 #include <sys/param.h>
42 40 #include <sys/stream.h>
43 41 #include <sys/stropts.h>
44 42 #include <sys/strsun.h>
45 43 #include <sys/termio.h>
46 44 #include <sys/pcb.h>
47 45 #include <sys/signal.h>
48 46 #include <sys/cred.h>
49 47 #include <sys/strtty.h>
50 48 #include <sys/errno.h>
51 49 #include <sys/cmn_err.h>
52 50 #include <sys/jioctl.h>
53 51 #include <sys/ptem.h>
54 52 #include <sys/ptms.h>
55 53 #include <sys/debug.h>
56 54 #include <sys/kmem.h>
57 55 #include <sys/ddi.h>
58 56 #include <sys/sunddi.h>
59 57 #include <sys/conf.h>
60 58 #include <sys/modctl.h>
61 59
62 60 extern struct streamtab pteminfo;
63 61
64 62 static struct fmodsw fsw = {
65 63 "ptem",
66 64 &pteminfo,
67 65 D_MTQPAIR | D_MP
68 66 };
69 67
70 68 static struct modlstrmod modlstrmod = {
71 69 &mod_strmodops, "pty hardware emulator", &fsw
72 70 };
73 71
74 72 static struct modlinkage modlinkage = {
75 73 MODREV_1, &modlstrmod, NULL
76 74 };
77 75
78 76 int
79 77 _init()
80 78 {
81 79 return (mod_install(&modlinkage));
82 80 }
83 81
84 82 int
85 83 _fini()
86 84 {
87 85 return (mod_remove(&modlinkage));
88 86 }
89 87
90 88 int
91 89 _info(struct modinfo *modinfop)
92 90 {
93 91 return (mod_info(&modlinkage, modinfop));
94 92 }
95 93
96 94 /*
97 95 * stream data structure definitions
98 96 */
↓ open down ↓ |
56 lines elided |
↑ open up ↑ |
99 97 static int ptemopen(queue_t *, dev_t *, int, int, cred_t *);
100 98 static int ptemclose(queue_t *, int, cred_t *);
101 99 static void ptemrput(queue_t *, mblk_t *);
102 100 static void ptemwput(queue_t *, mblk_t *);
103 101 static void ptemwsrv(queue_t *);
104 102
105 103 static struct module_info ptem_info = {
106 104 0xabcd,
107 105 "ptem",
108 106 0,
109 - 512,
110 - 512,
107 + _TTY_BUFSIZ,
108 + _TTY_BUFSIZ,
111 109 128
112 110 };
113 111
114 112 static struct qinit ptemrinit = {
115 113 (int (*)()) ptemrput,
116 114 NULL,
117 115 ptemopen,
118 116 ptemclose,
119 117 NULL,
120 118 &ptem_info,
121 119 NULL
122 120 };
123 121
124 122 static struct qinit ptemwinit = {
125 123 (int (*)()) ptemwput,
126 124 (int (*)()) ptemwsrv,
127 125 ptemopen,
128 126 ptemclose,
129 127 nulldev,
130 128 &ptem_info,
131 129 NULL
132 130 };
133 131
134 132 struct streamtab pteminfo = {
135 133 &ptemrinit,
136 134 &ptemwinit,
137 135 NULL,
138 136 NULL
139 137 };
140 138
141 139 static void ptioc(queue_t *, mblk_t *, int);
142 140 static int ptemwmsg(queue_t *, mblk_t *);
143 141
144 142 /*
145 143 * ptemopen - open routine gets called when the module gets pushed onto the
146 144 * stream.
147 145 */
148 146 /* ARGSUSED */
149 147 static int
150 148 ptemopen(
151 149 queue_t *q, /* pointer to the read side queue */
152 150 dev_t *devp, /* pointer to stream tail's dev */
153 151 int oflag, /* the user open(2) supplied flags */
154 152 int sflag, /* open state flag */
155 153 cred_t *credp) /* credentials */
156 154 {
157 155 struct ptem *ntp; /* ptem entry for this PTEM module */
158 156 mblk_t *mop; /* an setopts mblk */
159 157 struct stroptions *sop;
160 158 struct termios *termiosp;
161 159 int len;
162 160
163 161 if (sflag != MODOPEN)
164 162 return (EINVAL);
165 163
166 164 if (q->q_ptr != NULL) {
167 165 /* It's already attached. */
168 166 return (0);
169 167 }
170 168
171 169 /*
172 170 * Allocate state structure.
173 171 */
174 172 ntp = kmem_alloc(sizeof (*ntp), KM_SLEEP);
175 173
176 174 /*
177 175 * Allocate a message block, used to pass the zero length message for
178 176 * "stty 0".
179 177 *
180 178 * NOTE: it's better to find out if such a message block can be
181 179 * allocated before it's needed than to not be able to
182 180 * deliver (for possible lack of buffers) when a hang-up
183 181 * occurs.
184 182 */
185 183 if ((ntp->dack_ptr = allocb(4, BPRI_MED)) == NULL) {
186 184 kmem_free(ntp, sizeof (*ntp));
187 185 return (EAGAIN);
188 186 }
189 187
190 188 /*
191 189 * Initialize an M_SETOPTS message to set up hi/lo water marks on
192 190 * stream head read queue and add controlling tty if not set.
193 191 */
↓ open down ↓ |
73 lines elided |
↑ open up ↑ |
194 192 mop = allocb(sizeof (struct stroptions), BPRI_MED);
195 193 if (mop == NULL) {
196 194 freemsg(ntp->dack_ptr);
197 195 kmem_free(ntp, sizeof (*ntp));
198 196 return (EAGAIN);
199 197 }
200 198 mop->b_datap->db_type = M_SETOPTS;
201 199 mop->b_wptr += sizeof (struct stroptions);
202 200 sop = (struct stroptions *)mop->b_rptr;
203 201 sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
204 - sop->so_hiwat = 512;
202 + sop->so_hiwat = _TTY_BUFSIZ;
205 203 sop->so_lowat = 256;
206 204
207 205 /*
208 206 * Cross-link.
209 207 */
210 208 ntp->q_ptr = q;
211 209 q->q_ptr = ntp;
212 210 WR(q)->q_ptr = ntp;
213 211
214 212 /*
215 213 * Get termios defaults. These are stored as
216 214 * a property in the "options" node.
217 215 */
218 216 if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(), 0, "ttymodes",
219 217 (caddr_t)&termiosp, &len) == DDI_PROP_SUCCESS &&
220 218 len == sizeof (struct termios)) {
221 219
222 220 ntp->cflags = termiosp->c_cflag;
223 221 kmem_free(termiosp, len);
224 222 } else {
225 223 /*
226 224 * Gack! Whine about it.
227 225 */
228 226 cmn_err(CE_WARN, "ptem: Couldn't get ttymodes property!");
229 227 }
230 228 ntp->wsz.ws_row = 0;
231 229 ntp->wsz.ws_col = 0;
232 230 ntp->wsz.ws_xpixel = 0;
233 231 ntp->wsz.ws_ypixel = 0;
234 232
235 233 ntp->state = 0;
236 234
237 235 /*
238 236 * Commit to the open and send the M_SETOPTS off to the stream head.
239 237 */
240 238 qprocson(q);
241 239 putnext(q, mop);
242 240
243 241 return (0);
244 242 }
245 243
246 244
247 245 /*
248 246 * ptemclose - This routine gets called when the module gets popped off of the
249 247 * stream.
250 248 */
251 249 /* ARGSUSED */
252 250 static int
253 251 ptemclose(queue_t *q, int flag, cred_t *credp)
254 252 {
255 253 struct ptem *ntp; /* ptem entry for this PTEM module */
256 254
257 255 qprocsoff(q);
258 256 ntp = (struct ptem *)q->q_ptr;
259 257 freemsg(ntp->dack_ptr);
260 258 kmem_free(ntp, sizeof (*ntp));
261 259 q->q_ptr = WR(q)->q_ptr = NULL;
262 260 return (0);
263 261 }
264 262
265 263
266 264 /*
267 265 * ptemrput - Module read queue put procedure.
268 266 *
269 267 * This is called from the module or driver downstream.
270 268 */
271 269 static void
272 270 ptemrput(queue_t *q, mblk_t *mp)
273 271 {
274 272 struct iocblk *iocp; /* M_IOCTL data */
275 273 struct copyresp *resp; /* transparent ioctl response struct */
276 274 int error;
277 275
278 276 switch (mp->b_datap->db_type) {
279 277 case M_DELAY:
280 278 case M_READ:
281 279 freemsg(mp);
282 280 break;
283 281
284 282 case M_IOCTL:
285 283 iocp = (struct iocblk *)mp->b_rptr;
286 284
287 285 switch (iocp->ioc_cmd) {
288 286 case TCSBRK:
289 287 /*
290 288 * Send a break message upstream.
291 289 *
292 290 * XXX: Shouldn't the argument come into play in
293 291 * determining whether or not so send an M_BREAK?
294 292 * It certainly does in the write-side direction.
295 293 */
296 294 error = miocpullup(mp, sizeof (int));
297 295 if (error != 0) {
298 296 miocnak(q, mp, 0, error);
299 297 break;
300 298 }
301 299 if (!(*(int *)mp->b_cont->b_rptr)) {
302 300 if (!putnextctl(q, M_BREAK)) {
303 301 /*
304 302 * Send an NAK reply back
305 303 */
306 304 miocnak(q, mp, 0, EAGAIN);
307 305 break;
308 306 }
309 307 }
310 308 /*
311 309 * ACK it.
312 310 */
313 311 mioc2ack(mp, NULL, 0, 0);
314 312 qreply(q, mp);
315 313 break;
316 314
317 315 case JWINSIZE:
318 316 case TIOCGWINSZ:
319 317 case TIOCSWINSZ:
320 318 ptioc(q, mp, RDSIDE);
321 319 break;
322 320
323 321 case TIOCSIGNAL:
324 322 /*
325 323 * The following subtle logic is due to the fact that
326 324 * `mp' may be in any one of three distinct formats:
327 325 *
328 326 * 1. A transparent M_IOCTL with an intptr_t-sized
329 327 * payload containing the signal number.
330 328 *
331 329 * 2. An I_STR M_IOCTL with an int-sized payload
332 330 * containing the signal number.
333 331 *
334 332 * 3. An M_IOCDATA with an int-sized payload
335 333 * containing the signal number.
336 334 */
337 335 if (iocp->ioc_count == TRANSPARENT) {
338 336 intptr_t sig = *(intptr_t *)mp->b_cont->b_rptr;
339 337
340 338 if (sig < 1 || sig >= NSIG) {
341 339 /*
342 340 * it's transparent with pointer
343 341 * to the arg
344 342 */
345 343 mcopyin(mp, NULL, sizeof (int), NULL);
346 344 qreply(q, mp);
347 345 break;
348 346 }
349 347 }
350 348 ptioc(q, mp, RDSIDE);
351 349 break;
352 350
353 351 case TIOCREMOTE:
354 352 if (iocp->ioc_count != TRANSPARENT)
355 353 ptioc(q, mp, RDSIDE);
356 354 else {
357 355 mcopyin(mp, NULL, sizeof (int), NULL);
358 356 qreply(q, mp);
359 357 }
360 358 break;
361 359
362 360 default:
363 361 putnext(q, mp);
364 362 break;
365 363 }
366 364 break;
367 365
368 366 case M_IOCDATA:
369 367 resp = (struct copyresp *)mp->b_rptr;
370 368 if (resp->cp_rval) {
371 369 /*
372 370 * Just free message on failure.
373 371 */
374 372 freemsg(mp);
375 373 break;
376 374 }
377 375
378 376 /*
379 377 * Only need to copy data for the SET case.
380 378 */
381 379 switch (resp->cp_cmd) {
382 380
383 381 case TIOCSWINSZ:
384 382 case TIOCSIGNAL:
385 383 case TIOCREMOTE:
386 384 ptioc(q, mp, RDSIDE);
387 385 break;
388 386
389 387 case JWINSIZE:
390 388 case TIOCGWINSZ:
391 389 mp->b_datap->db_type = M_IOCACK;
392 390 mioc2ack(mp, NULL, 0, 0);
393 391 qreply(q, mp);
394 392 break;
395 393
396 394 default:
397 395 freemsg(mp);
398 396 break;
399 397 }
400 398 break;
401 399
402 400 case M_IOCACK:
403 401 case M_IOCNAK:
404 402 /*
405 403 * We only pass write-side ioctls through to the master that
406 404 * we've already ACKed or NAKed to the stream head. Thus, we
407 405 * discard ones arriving from below, since they're redundant
408 406 * from the point of view of modules above us.
409 407 */
410 408 freemsg(mp);
411 409 break;
412 410
413 411 case M_HANGUP:
414 412 /*
415 413 * clear blocked state.
416 414 */
417 415 {
418 416 struct ptem *ntp = (struct ptem *)q->q_ptr;
419 417 if (ntp->state & OFLOW_CTL) {
420 418 ntp->state &= ~OFLOW_CTL;
421 419 qenable(WR(q));
422 420 }
423 421 }
424 422 default:
425 423 putnext(q, mp);
426 424 break;
427 425 }
428 426 }
429 427
430 428
431 429 /*
432 430 * ptemwput - Module write queue put procedure.
433 431 *
434 432 * This is called from the module or stream head upstream.
435 433 *
436 434 * XXX: This routine is quite lazy about handling allocation failures,
437 435 * basically just giving up and reporting failure. It really ought to
438 436 * set up bufcalls and only fail when it's absolutely necessary.
439 437 */
440 438 static void
441 439 ptemwput(queue_t *q, mblk_t *mp)
442 440 {
443 441 struct ptem *ntp = (struct ptem *)q->q_ptr;
444 442 struct iocblk *iocp; /* outgoing ioctl structure */
445 443 struct copyresp *resp;
446 444 unsigned char type = mp->b_datap->db_type;
447 445
448 446 if (type >= QPCTL) {
449 447 switch (type) {
450 448
451 449 case M_IOCDATA:
452 450 resp = (struct copyresp *)mp->b_rptr;
453 451 if (resp->cp_rval) {
454 452 /*
455 453 * Just free message on failure.
456 454 */
457 455 freemsg(mp);
458 456 break;
459 457 }
460 458
461 459 /*
462 460 * Only need to copy data for the SET case.
463 461 */
464 462 switch (resp->cp_cmd) {
465 463
466 464 case TIOCSWINSZ:
467 465 ptioc(q, mp, WRSIDE);
468 466 break;
469 467
470 468 case JWINSIZE:
471 469 case TIOCGWINSZ:
472 470 mioc2ack(mp, NULL, 0, 0);
↓ open down ↓ |
258 lines elided |
↑ open up ↑ |
473 471 qreply(q, mp);
474 472 break;
475 473
476 474 default:
477 475 freemsg(mp);
478 476 }
479 477 break;
480 478
481 479 case M_FLUSH:
482 480 if (*mp->b_rptr & FLUSHW) {
483 - if ((ntp->state & IS_PTSTTY) &&
484 - (*mp->b_rptr & FLUSHBAND))
485 - flushband(q, *(mp->b_rptr + 1), FLUSHDATA);
486 - else
487 - flushq(q, FLUSHDATA);
481 + if ((ntp->state & IS_PTSTTY) &&
482 + (*mp->b_rptr & FLUSHBAND))
483 + flushband(q, *(mp->b_rptr + 1),
484 + FLUSHDATA);
485 + else
486 + flushq(q, FLUSHDATA);
488 487 }
489 488 putnext(q, mp);
490 489 break;
491 490
492 491 case M_READ:
493 492 freemsg(mp);
494 493 break;
495 494
496 495 case M_STOP:
497 496 /*
498 497 * Set the output flow control state.
499 498 */
500 499 ntp->state |= OFLOW_CTL;
501 500 putnext(q, mp);
502 501 break;
503 502
504 503 case M_START:
505 504 /*
506 505 * Relieve the output flow control state.
507 506 */
508 507 ntp->state &= ~OFLOW_CTL;
509 508 putnext(q, mp);
510 509 qenable(q);
511 510 break;
512 511 default:
513 512 putnext(q, mp);
514 513 break;
515 514 }
516 515 return;
517 516 }
518 517 /*
519 518 * If our queue is nonempty or flow control persists
520 519 * downstream or module in stopped state, queue this message.
521 520 */
522 521 if (q->q_first != NULL || !bcanputnext(q, mp->b_band)) {
523 522 /*
524 523 * Exception: ioctls, except for those defined to
525 524 * take effect after output has drained, should be
526 525 * processed immediately.
527 526 */
528 527 switch (type) {
529 528
530 529 case M_IOCTL:
531 530 iocp = (struct iocblk *)mp->b_rptr;
532 531 switch (iocp->ioc_cmd) {
533 532 /*
534 533 * Queue these.
535 534 */
536 535 case TCSETSW:
537 536 case TCSETSF:
538 537 case TCSETAW:
539 538 case TCSETAF:
540 539 case TCSBRK:
541 540 break;
542 541
543 542 /*
544 543 * Handle all others immediately.
545 544 */
546 545 default:
547 546 (void) ptemwmsg(q, mp);
548 547 return;
549 548 }
550 549 break;
551 550
552 551 case M_DELAY: /* tty delays not supported */
553 552 freemsg(mp);
554 553 return;
555 554
556 555 case M_DATA:
557 556 if ((mp->b_wptr - mp->b_rptr) < 0) {
558 557 /*
559 558 * Free all bad length messages.
560 559 */
561 560 freemsg(mp);
562 561 return;
563 562 } else if ((mp->b_wptr - mp->b_rptr) == 0) {
564 563 if (!(ntp->state & IS_PTSTTY)) {
565 564 freemsg(mp);
566 565 return;
567 566 }
568 567 }
569 568 }
570 569 (void) putq(q, mp);
571 570 return;
572 571 }
573 572 /*
574 573 * fast path into ptemwmsg to dispose of mp.
575 574 */
576 575 if (!ptemwmsg(q, mp))
577 576 (void) putq(q, mp);
578 577 }
579 578
580 579 /*
581 580 * ptem write queue service procedure.
582 581 */
583 582 static void
584 583 ptemwsrv(queue_t *q)
585 584 {
586 585 mblk_t *mp;
587 586
588 587 while ((mp = getq(q)) != NULL) {
589 588 if (!bcanputnext(q, mp->b_band) || !ptemwmsg(q, mp)) {
590 589 (void) putbq(q, mp);
591 590 break;
592 591 }
593 592 }
594 593 }
595 594
596 595
597 596 /*
598 597 * This routine is called from both ptemwput and ptemwsrv to do the
599 598 * actual work of dealing with mp. ptmewput will have already
600 599 * dealt with high priority messages.
601 600 *
602 601 * Return 1 if the message was processed completely and 0 if not.
603 602 */
604 603 static int
605 604 ptemwmsg(queue_t *q, mblk_t *mp)
606 605 {
607 606 struct ptem *ntp = (struct ptem *)q->q_ptr;
608 607 struct iocblk *iocp; /* outgoing ioctl structure */
609 608 struct termio *termiop;
610 609 struct termios *termiosp;
611 610 mblk_t *dack_ptr; /* disconnect message ACK block */
612 611 mblk_t *pckt_msgp; /* message sent to the PCKT module */
613 612 mblk_t *dp; /* ioctl reply data */
614 613 tcflag_t cflags;
615 614 int error;
616 615
617 616 switch (mp->b_datap->db_type) {
618 617
619 618 case M_IOCTL:
620 619 /*
621 620 * Note: for each "set" type operation a copy
622 621 * of the M_IOCTL message is made and passed
623 622 * downstream. Eventually the PCKT module, if
624 623 * it has been pushed, should pick up this message.
625 624 * If the PCKT module has not been pushed the master
626 625 * side stream head will free it.
627 626 */
628 627 iocp = (struct iocblk *)mp->b_rptr;
629 628 switch (iocp->ioc_cmd) {
630 629
631 630 case TCSETAF:
632 631 case TCSETSF:
633 632 /*
634 633 * Flush the read queue.
635 634 */
636 635 if (putnextctl1(q, M_FLUSH, FLUSHR) == 0) {
637 636 miocnak(q, mp, 0, EAGAIN);
638 637 break;
639 638 }
640 639 /* FALLTHROUGH */
641 640
642 641 case TCSETA:
643 642 case TCSETAW:
644 643 case TCSETS:
645 644 case TCSETSW:
646 645
647 646 switch (iocp->ioc_cmd) {
648 647 case TCSETAF:
649 648 case TCSETA:
650 649 case TCSETAW:
651 650 error = miocpullup(mp, sizeof (struct termio));
652 651 if (error != 0) {
653 652 miocnak(q, mp, 0, error);
654 653 goto out;
655 654 }
656 655 cflags = ((struct termio *)
657 656 mp->b_cont->b_rptr)->c_cflag;
658 657 ntp->cflags =
659 658 (ntp->cflags & 0xffff0000 | cflags);
660 659 break;
661 660
662 661 case TCSETSF:
663 662 case TCSETS:
664 663 case TCSETSW:
665 664 error = miocpullup(mp, sizeof (struct termios));
666 665 if (error != 0) {
667 666 miocnak(q, mp, 0, error);
668 667 goto out;
669 668 }
670 669 cflags = ((struct termios *)
671 670 mp->b_cont->b_rptr)->c_cflag;
672 671 ntp->cflags = cflags;
673 672 break;
674 673 }
675 674
676 675 if ((cflags & CBAUD) == B0) {
677 676 /*
678 677 * Hang-up: Send a zero length message.
679 678 */
680 679 dack_ptr = ntp->dack_ptr;
681 680
682 681 if (dack_ptr) {
683 682 ntp->dack_ptr = NULL;
684 683 /*
685 684 * Send a zero length message
686 685 * downstream.
687 686 */
688 687 putnext(q, dack_ptr);
689 688 }
690 689 } else {
691 690 /*
692 691 * Make a copy of this message and pass it on
693 692 * to the PCKT module.
694 693 */
695 694 if ((pckt_msgp = copymsg(mp)) == NULL) {
696 695 miocnak(q, mp, 0, EAGAIN);
697 696 break;
698 697 }
699 698 putnext(q, pckt_msgp);
700 699 }
701 700 /*
702 701 * Send ACK upstream.
703 702 */
704 703 mioc2ack(mp, NULL, 0, 0);
705 704 qreply(q, mp);
706 705 out:
707 706 break;
708 707
709 708 case TCGETA:
710 709 dp = allocb(sizeof (struct termio), BPRI_MED);
711 710 if (dp == NULL) {
712 711 miocnak(q, mp, 0, EAGAIN);
713 712 break;
714 713 }
715 714 termiop = (struct termio *)dp->b_rptr;
716 715 termiop->c_cflag = (ushort_t)ntp->cflags;
717 716 mioc2ack(mp, dp, sizeof (struct termio), 0);
718 717 qreply(q, mp);
719 718 break;
720 719
721 720 case TCGETS:
722 721 dp = allocb(sizeof (struct termios), BPRI_MED);
723 722 if (dp == NULL) {
724 723 miocnak(q, mp, 0, EAGAIN);
725 724 break;
726 725 }
727 726 termiosp = (struct termios *)dp->b_rptr;
728 727 termiosp->c_cflag = ntp->cflags;
729 728 mioc2ack(mp, dp, sizeof (struct termios), 0);
730 729 qreply(q, mp);
731 730 break;
732 731
733 732 case TCSBRK:
734 733 error = miocpullup(mp, sizeof (int));
735 734 if (error != 0) {
736 735 miocnak(q, mp, 0, error);
737 736 break;
738 737 }
739 738
740 739 /*
741 740 * Need a copy of this message to pass it on to
742 741 * the PCKT module.
743 742 */
744 743 if ((pckt_msgp = copymsg(mp)) == NULL) {
745 744 miocnak(q, mp, 0, EAGAIN);
746 745 break;
747 746 }
748 747 /*
749 748 * Send a copy of the M_IOCTL to the PCKT module.
750 749 */
751 750 putnext(q, pckt_msgp);
752 751
753 752 /*
754 753 * TCSBRK meaningful if data part of message is 0
755 754 * cf. termio(7).
756 755 */
757 756 if (!(*(int *)mp->b_cont->b_rptr))
758 757 (void) putnextctl(q, M_BREAK);
759 758 /*
760 759 * ACK the ioctl.
761 760 */
762 761 mioc2ack(mp, NULL, 0, 0);
763 762 qreply(q, mp);
764 763 break;
765 764
766 765 case JWINSIZE:
767 766 case TIOCGWINSZ:
768 767 case TIOCSWINSZ:
769 768 ptioc(q, mp, WRSIDE);
770 769 break;
771 770
772 771 case TIOCSTI:
773 772 /*
774 773 * Simulate typing of a character at the terminal. In
775 774 * all cases, we acknowledge the ioctl and pass a copy
776 775 * of it along for the PCKT module to encapsulate. If
777 776 * not in remote mode, we also process the ioctl
778 777 * itself, looping the character given as its argument
779 778 * back around to the read side.
780 779 */
781 780
782 781 /*
783 782 * Need a copy of this message to pass on to the PCKT
784 783 * module.
785 784 */
786 785 if ((pckt_msgp = copymsg(mp)) == NULL) {
787 786 miocnak(q, mp, 0, EAGAIN);
788 787 break;
789 788 }
790 789 if ((ntp->state & REMOTEMODE) == 0) {
791 790 mblk_t *bp;
792 791
793 792 error = miocpullup(mp, sizeof (char));
794 793 if (error != 0) {
795 794 freemsg(pckt_msgp);
796 795 miocnak(q, mp, 0, error);
797 796 break;
798 797 }
799 798
800 799 /*
801 800 * The permission checking has already been
802 801 * done at the stream head, since it has to be
803 802 * done in the context of the process doing
804 803 * the call.
805 804 */
806 805 if ((bp = allocb(1, BPRI_MED)) == NULL) {
807 806 freemsg(pckt_msgp);
808 807 miocnak(q, mp, 0, EAGAIN);
809 808 break;
810 809 }
811 810 /*
812 811 * XXX: Is EAGAIN really the right response to
813 812 * flow control blockage?
814 813 */
815 814 if (!bcanputnext(RD(q), mp->b_band)) {
816 815 freemsg(bp);
817 816 freemsg(pckt_msgp);
818 817 miocnak(q, mp, 0, EAGAIN);
819 818 break;
820 819 }
821 820 *bp->b_wptr++ = *mp->b_cont->b_rptr;
822 821 qreply(q, bp);
823 822 }
824 823
825 824 putnext(q, pckt_msgp);
826 825 mioc2ack(mp, NULL, 0, 0);
827 826 qreply(q, mp);
828 827 break;
829 828
830 829 case PTSSTTY:
831 830 if (ntp->state & IS_PTSTTY) {
832 831 miocnak(q, mp, 0, EEXIST);
833 832 } else {
834 833 ntp->state |= IS_PTSTTY;
835 834 mioc2ack(mp, NULL, 0, 0);
836 835 qreply(q, mp);
837 836 }
838 837 break;
839 838
840 839 default:
841 840 /*
842 841 * End of the line. The slave driver doesn't see any
843 842 * ioctls that we don't explicitly pass along to it.
844 843 */
845 844 miocnak(q, mp, 0, EINVAL);
846 845 break;
847 846 }
848 847 break;
849 848
850 849 case M_DELAY: /* tty delays not supported */
851 850 freemsg(mp);
852 851 break;
853 852
854 853 case M_DATA:
855 854 if ((mp->b_wptr - mp->b_rptr) < 0) {
856 855 /*
857 856 * Free all bad length messages.
858 857 */
859 858 freemsg(mp);
860 859 break;
861 860 } else if ((mp->b_wptr - mp->b_rptr) == 0) {
862 861 if (!(ntp->state & IS_PTSTTY)) {
863 862 freemsg(mp);
864 863 break;
865 864 }
866 865 }
867 866 if (ntp->state & OFLOW_CTL)
868 867 return (0);
869 868
870 869 default:
871 870 putnext(q, mp);
872 871 break;
873 872
874 873 }
875 874
876 875 return (1);
877 876 }
878 877
879 878 /*
880 879 * Message must be of type M_IOCTL or M_IOCDATA for this routine to be called.
881 880 */
882 881 static void
883 882 ptioc(queue_t *q, mblk_t *mp, int qside)
884 883 {
885 884 struct ptem *tp;
886 885 struct iocblk *iocp;
887 886 struct winsize *wb;
888 887 struct jwinsize *jwb;
889 888 mblk_t *tmp;
890 889 mblk_t *pckt_msgp; /* message sent to the PCKT module */
891 890 int error;
892 891
893 892 iocp = (struct iocblk *)mp->b_rptr;
894 893 tp = (struct ptem *)q->q_ptr;
895 894
896 895 switch (iocp->ioc_cmd) {
897 896
898 897 case JWINSIZE:
899 898 /*
900 899 * For compatibility: If all zeros, NAK the message for dumb
901 900 * terminals.
902 901 */
903 902 if ((tp->wsz.ws_row == 0) && (tp->wsz.ws_col == 0) &&
904 903 (tp->wsz.ws_xpixel == 0) && (tp->wsz.ws_ypixel == 0)) {
905 904 miocnak(q, mp, 0, EINVAL);
906 905 return;
907 906 }
908 907
909 908 tmp = allocb(sizeof (struct jwinsize), BPRI_MED);
910 909 if (tmp == NULL) {
911 910 miocnak(q, mp, 0, EAGAIN);
912 911 return;
913 912 }
914 913
915 914 if (iocp->ioc_count == TRANSPARENT)
916 915 mcopyout(mp, NULL, sizeof (struct jwinsize), NULL, tmp);
917 916 else
918 917 mioc2ack(mp, tmp, sizeof (struct jwinsize), 0);
919 918
920 919 jwb = (struct jwinsize *)mp->b_cont->b_rptr;
921 920 jwb->bytesx = tp->wsz.ws_col;
922 921 jwb->bytesy = tp->wsz.ws_row;
923 922 jwb->bitsx = tp->wsz.ws_xpixel;
924 923 jwb->bitsy = tp->wsz.ws_ypixel;
925 924
926 925 qreply(q, mp);
927 926 return;
928 927
929 928 case TIOCGWINSZ:
930 929 /*
931 930 * If all zeros NAK the message for dumb terminals.
932 931 */
933 932 if ((tp->wsz.ws_row == 0) && (tp->wsz.ws_col == 0) &&
934 933 (tp->wsz.ws_xpixel == 0) && (tp->wsz.ws_ypixel == 0)) {
935 934 miocnak(q, mp, 0, EINVAL);
936 935 return;
937 936 }
938 937
939 938 tmp = allocb(sizeof (struct winsize), BPRI_MED);
940 939 if (tmp == NULL) {
941 940 miocnak(q, mp, 0, EAGAIN);
942 941 return;
943 942 }
944 943
945 944 mioc2ack(mp, tmp, sizeof (struct winsize), 0);
946 945
947 946 wb = (struct winsize *)mp->b_cont->b_rptr;
948 947 wb->ws_row = tp->wsz.ws_row;
949 948 wb->ws_col = tp->wsz.ws_col;
950 949 wb->ws_xpixel = tp->wsz.ws_xpixel;
951 950 wb->ws_ypixel = tp->wsz.ws_ypixel;
952 951
953 952 qreply(q, mp);
954 953 return;
955 954
956 955 case TIOCSWINSZ:
957 956 error = miocpullup(mp, sizeof (struct winsize));
958 957 if (error != 0) {
959 958 miocnak(q, mp, 0, error);
960 959 return;
961 960 }
962 961
963 962 wb = (struct winsize *)mp->b_cont->b_rptr;
964 963 /*
965 964 * Send a SIGWINCH signal if the row/col information has
966 965 * changed.
967 966 */
968 967 if ((tp->wsz.ws_row != wb->ws_row) ||
969 968 (tp->wsz.ws_col != wb->ws_col) ||
970 969 (tp->wsz.ws_xpixel != wb->ws_xpixel) ||
971 970 (tp->wsz.ws_ypixel != wb->ws_xpixel)) {
972 971 /*
973 972 * SIGWINCH is always sent upstream.
974 973 */
975 974 if (qside == WRSIDE)
976 975 (void) putnextctl1(RD(q), M_SIG, SIGWINCH);
977 976 else if (qside == RDSIDE)
978 977 (void) putnextctl1(q, M_SIG, SIGWINCH);
979 978 /*
980 979 * Message may have come in as an M_IOCDATA; pass it
981 980 * to the master side as an M_IOCTL.
982 981 */
983 982 mp->b_datap->db_type = M_IOCTL;
984 983 if (qside == WRSIDE) {
985 984 /*
986 985 * Need a copy of this message to pass on to
987 986 * the PCKT module, only if the M_IOCTL
988 987 * orginated from the slave side.
989 988 */
990 989 if ((pckt_msgp = copymsg(mp)) == NULL) {
991 990 miocnak(q, mp, 0, EAGAIN);
992 991 return;
993 992 }
994 993 putnext(q, pckt_msgp);
995 994 }
996 995 tp->wsz.ws_row = wb->ws_row;
997 996 tp->wsz.ws_col = wb->ws_col;
998 997 tp->wsz.ws_xpixel = wb->ws_xpixel;
999 998 tp->wsz.ws_ypixel = wb->ws_ypixel;
1000 999 }
1001 1000
1002 1001 mioc2ack(mp, NULL, 0, 0);
1003 1002 qreply(q, mp);
1004 1003 return;
1005 1004
1006 1005 case TIOCSIGNAL: {
1007 1006 /*
1008 1007 * This ioctl can emanate from the master side in remote
1009 1008 * mode only.
1010 1009 */
1011 1010 int sig;
1012 1011
1013 1012 if (DB_TYPE(mp) == M_IOCTL && iocp->ioc_count != TRANSPARENT) {
1014 1013 error = miocpullup(mp, sizeof (int));
1015 1014 if (error != 0) {
1016 1015 miocnak(q, mp, 0, error);
1017 1016 return;
1018 1017 }
1019 1018 }
1020 1019
1021 1020 if (DB_TYPE(mp) == M_IOCDATA || iocp->ioc_count != TRANSPARENT)
1022 1021 sig = *(int *)mp->b_cont->b_rptr;
1023 1022 else
1024 1023 sig = (int)*(intptr_t *)mp->b_cont->b_rptr;
1025 1024
1026 1025 if (sig < 1 || sig >= NSIG) {
1027 1026 miocnak(q, mp, 0, EINVAL);
1028 1027 return;
1029 1028 }
1030 1029
1031 1030 /*
1032 1031 * Send an M_PCSIG message up the slave's read side and
1033 1032 * respond back to the master with an ACK or NAK as
↓ open down ↓ |
536 lines elided |
↑ open up ↑ |
1034 1033 * appropriate.
1035 1034 */
1036 1035 if (putnextctl1(q, M_PCSIG, sig) == 0) {
1037 1036 miocnak(q, mp, 0, EAGAIN);
1038 1037 return;
1039 1038 }
1040 1039
1041 1040 mioc2ack(mp, NULL, 0, 0);
1042 1041 qreply(q, mp);
1043 1042 return;
1044 - }
1043 + }
1045 1044
1046 1045 case TIOCREMOTE: {
1047 1046 int onoff;
1048 1047 mblk_t *mctlp;
1049 1048
1050 1049 if (DB_TYPE(mp) == M_IOCTL) {
1051 1050 error = miocpullup(mp, sizeof (int));
1052 1051 if (error != 0) {
1053 1052 miocnak(q, mp, 0, error);
1054 1053 return;
1055 1054 }
1056 1055 }
1057 1056
1058 1057 onoff = *(int *)mp->b_cont->b_rptr;
1059 1058
1060 1059 /*
1061 1060 * Send M_CTL up using the iocblk format.
1062 1061 */
1063 1062 mctlp = mkiocb(onoff ? MC_NO_CANON : MC_DO_CANON);
1064 1063 if (mctlp == NULL) {
1065 1064 miocnak(q, mp, 0, EAGAIN);
1066 1065 return;
1067 1066 }
1068 1067 mctlp->b_datap->db_type = M_CTL;
1069 1068 putnext(q, mctlp);
1070 1069
1071 1070 /*
1072 1071 * ACK the ioctl.
1073 1072 */
1074 1073 mioc2ack(mp, NULL, 0, 0);
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
1075 1074 qreply(q, mp);
1076 1075
1077 1076 /*
1078 1077 * Record state change.
1079 1078 */
1080 1079 if (onoff)
1081 1080 tp->state |= REMOTEMODE;
1082 1081 else
1083 1082 tp->state &= ~REMOTEMODE;
1084 1083 return;
1085 - }
1084 + }
1086 1085
1087 1086 default:
1088 1087 putnext(q, mp);
1089 1088 return;
1090 1089 }
1091 1090 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX