1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3*0Sstevel@tonic-gate * Use is subject to license terms.
4*0Sstevel@tonic-gate */
5*0Sstevel@tonic-gate
6*0Sstevel@tonic-gate /*
7*0Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California.
8*0Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement
9*0Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
10*0Sstevel@tonic-gate */
11*0Sstevel@tonic-gate
12*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
13*0Sstevel@tonic-gate
14*0Sstevel@tonic-gate #include <sys/types.h>
15*0Sstevel@tonic-gate #include <sys/param.h>
16*0Sstevel@tonic-gate #include <sys/signal.h>
17*0Sstevel@tonic-gate #include <sys/systm.h>
18*0Sstevel@tonic-gate #include <sys/termio.h>
19*0Sstevel@tonic-gate #include <sys/ttold.h>
20*0Sstevel@tonic-gate #include <sys/stropts.h>
21*0Sstevel@tonic-gate #include <sys/stream.h>
22*0Sstevel@tonic-gate #include <sys/strsubr.h>
23*0Sstevel@tonic-gate #include <sys/strsun.h>
24*0Sstevel@tonic-gate #include <sys/tty.h>
25*0Sstevel@tonic-gate #include <sys/kmem.h>
26*0Sstevel@tonic-gate #include <sys/errno.h>
27*0Sstevel@tonic-gate #include <sys/ddi.h>
28*0Sstevel@tonic-gate #include <sys/sunddi.h>
29*0Sstevel@tonic-gate #include <sys/esunddi.h>
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gate /*
32*0Sstevel@tonic-gate * The default (sane) set of termios values, unless
33*0Sstevel@tonic-gate * otherwise set by the user.
34*0Sstevel@tonic-gate */
35*0Sstevel@tonic-gate static struct termios default_termios = {
36*0Sstevel@tonic-gate BRKINT|ICRNL|IXON|IMAXBEL, /* c_iflag */
37*0Sstevel@tonic-gate OPOST|ONLCR|TAB3, /* c_oflag */
38*0Sstevel@tonic-gate B9600|CS8|CREAD, /* c_cflag */
39*0Sstevel@tonic-gate ISIG|ICANON|IEXTEN|ECHO|ECHOK|ECHOE|ECHOKE|ECHOCTL, /* c_lflag */
40*0Sstevel@tonic-gate {
41*0Sstevel@tonic-gate CINTR,
42*0Sstevel@tonic-gate CQUIT,
43*0Sstevel@tonic-gate CERASE,
44*0Sstevel@tonic-gate CKILL,
45*0Sstevel@tonic-gate CEOF,
46*0Sstevel@tonic-gate CEOL,
47*0Sstevel@tonic-gate CEOL2,
48*0Sstevel@tonic-gate CNSWTCH,
49*0Sstevel@tonic-gate CSTART,
50*0Sstevel@tonic-gate CSTOP,
51*0Sstevel@tonic-gate CSUSP,
52*0Sstevel@tonic-gate CDSUSP,
53*0Sstevel@tonic-gate CRPRNT,
54*0Sstevel@tonic-gate CFLUSH,
55*0Sstevel@tonic-gate CWERASE,
56*0Sstevel@tonic-gate CLNEXT,
57*0Sstevel@tonic-gate 0 /* nonexistent STATUS */
58*0Sstevel@tonic-gate }
59*0Sstevel@tonic-gate };
60*0Sstevel@tonic-gate
61*0Sstevel@tonic-gate
62*0Sstevel@tonic-gate static int termioval(char **, uint_t *, char *);
63*0Sstevel@tonic-gate
64*0Sstevel@tonic-gate void
ttycommon_close(tty_common_t * tc)65*0Sstevel@tonic-gate ttycommon_close(tty_common_t *tc)
66*0Sstevel@tonic-gate {
67*0Sstevel@tonic-gate mutex_enter(&tc->t_excl);
68*0Sstevel@tonic-gate tc->t_flags &= ~TS_XCLUDE;
69*0Sstevel@tonic-gate tc->t_readq = NULL;
70*0Sstevel@tonic-gate tc->t_writeq = NULL;
71*0Sstevel@tonic-gate if (tc->t_iocpending != NULL) {
72*0Sstevel@tonic-gate mblk_t *mp;
73*0Sstevel@tonic-gate
74*0Sstevel@tonic-gate mp = tc->t_iocpending;
75*0Sstevel@tonic-gate tc->t_iocpending = NULL;
76*0Sstevel@tonic-gate mutex_exit(&tc->t_excl);
77*0Sstevel@tonic-gate /*
78*0Sstevel@tonic-gate * We were holding an "ioctl" response pending the
79*0Sstevel@tonic-gate * availability of an "mblk" to hold data to be passed up;
80*0Sstevel@tonic-gate * another "ioctl" came through, which means that "ioctl"
81*0Sstevel@tonic-gate * must have timed out or been aborted.
82*0Sstevel@tonic-gate */
83*0Sstevel@tonic-gate freemsg(mp);
84*0Sstevel@tonic-gate } else
85*0Sstevel@tonic-gate mutex_exit(&tc->t_excl);
86*0Sstevel@tonic-gate }
87*0Sstevel@tonic-gate
88*0Sstevel@tonic-gate /*
89*0Sstevel@tonic-gate * A "line discipline" module's queue is full.
90*0Sstevel@tonic-gate * Check whether IMAXBEL is set; if so, output a ^G, otherwise send an M_FLUSH
91*0Sstevel@tonic-gate * upstream flushing all the read queues.
92*0Sstevel@tonic-gate */
93*0Sstevel@tonic-gate void
ttycommon_qfull(tty_common_t * tc,queue_t * q)94*0Sstevel@tonic-gate ttycommon_qfull(tty_common_t *tc, queue_t *q)
95*0Sstevel@tonic-gate {
96*0Sstevel@tonic-gate mblk_t *mp;
97*0Sstevel@tonic-gate
98*0Sstevel@tonic-gate if (tc->t_iflag & IMAXBEL) {
99*0Sstevel@tonic-gate if (canput(WR(q))) {
100*0Sstevel@tonic-gate if ((mp = allocb(1, BPRI_HI)) != NULL) {
101*0Sstevel@tonic-gate *mp->b_wptr++ = CTRL('g');
102*0Sstevel@tonic-gate (void) putq(WR(q), mp);
103*0Sstevel@tonic-gate }
104*0Sstevel@tonic-gate }
105*0Sstevel@tonic-gate } else {
106*0Sstevel@tonic-gate flushq(q, FLUSHDATA);
107*0Sstevel@tonic-gate (void) putnextctl1(q, M_FLUSH, FLUSHR);
108*0Sstevel@tonic-gate }
109*0Sstevel@tonic-gate }
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate /*
112*0Sstevel@tonic-gate * Process an "ioctl" message sent down to us, and return a reply message,
113*0Sstevel@tonic-gate * even if we don't understand the "ioctl". Our client may want to use
114*0Sstevel@tonic-gate * that reply message for its own purposes if we don't understand it but
115*0Sstevel@tonic-gate * they do, and may want to modify it if we both understand it but they
116*0Sstevel@tonic-gate * understand it better than we do.
117*0Sstevel@tonic-gate * If the "ioctl" reply requires additional data to be passed up to the
118*0Sstevel@tonic-gate * caller, and we cannot allocate an mblk to hold the data, we return the
119*0Sstevel@tonic-gate * amount of data to be sent, so that our caller can do a "bufcall" and try
120*0Sstevel@tonic-gate * again later; otherwise, we return 0.
121*0Sstevel@tonic-gate */
122*0Sstevel@tonic-gate size_t
ttycommon_ioctl(tty_common_t * tc,queue_t * q,mblk_t * mp,int * errorp)123*0Sstevel@tonic-gate ttycommon_ioctl(tty_common_t *tc, queue_t *q, mblk_t *mp, int *errorp)
124*0Sstevel@tonic-gate {
125*0Sstevel@tonic-gate struct iocblk *iocp;
126*0Sstevel@tonic-gate size_t ioctlrespsize;
127*0Sstevel@tonic-gate mblk_t *tmp;
128*0Sstevel@tonic-gate
129*0Sstevel@tonic-gate *errorp = 0; /* no error detected yet */
130*0Sstevel@tonic-gate
131*0Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
132*0Sstevel@tonic-gate
133*0Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) {
134*0Sstevel@tonic-gate *errorp = -1; /* we don't understand it, maybe they do */
135*0Sstevel@tonic-gate return (0);
136*0Sstevel@tonic-gate }
137*0Sstevel@tonic-gate
138*0Sstevel@tonic-gate switch (iocp->ioc_cmd) {
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate case TCSETSF:
141*0Sstevel@tonic-gate /*
142*0Sstevel@tonic-gate * Flush the driver's queue, and send an M_FLUSH upstream
143*0Sstevel@tonic-gate * to flush everybody above us.
144*0Sstevel@tonic-gate */
145*0Sstevel@tonic-gate flushq(RD(q), FLUSHDATA);
146*0Sstevel@tonic-gate (void) putnextctl1(RD(q), M_FLUSH, FLUSHR);
147*0Sstevel@tonic-gate /* FALLTHROUGH */
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gate case TCSETSW:
150*0Sstevel@tonic-gate case TCSETS: {
151*0Sstevel@tonic-gate struct termios *cb;
152*0Sstevel@tonic-gate
153*0Sstevel@tonic-gate if (miocpullup(mp, sizeof (struct termios)) != 0) {
154*0Sstevel@tonic-gate *errorp = -1;
155*0Sstevel@tonic-gate break;
156*0Sstevel@tonic-gate }
157*0Sstevel@tonic-gate
158*0Sstevel@tonic-gate /*
159*0Sstevel@tonic-gate * The only information we look at are the iflag word,
160*0Sstevel@tonic-gate * the cflag word, and the start and stop characters.
161*0Sstevel@tonic-gate */
162*0Sstevel@tonic-gate cb = (struct termios *)mp->b_cont->b_rptr;
163*0Sstevel@tonic-gate mutex_enter(&tc->t_excl);
164*0Sstevel@tonic-gate tc->t_iflag = cb->c_iflag;
165*0Sstevel@tonic-gate tc->t_cflag = cb->c_cflag;
166*0Sstevel@tonic-gate tc->t_stopc = cb->c_cc[VSTOP];
167*0Sstevel@tonic-gate tc->t_startc = cb->c_cc[VSTART];
168*0Sstevel@tonic-gate mutex_exit(&tc->t_excl);
169*0Sstevel@tonic-gate break;
170*0Sstevel@tonic-gate }
171*0Sstevel@tonic-gate
172*0Sstevel@tonic-gate case TCSETAF:
173*0Sstevel@tonic-gate /*
174*0Sstevel@tonic-gate * Flush the driver's queue, and send an M_FLUSH upstream
175*0Sstevel@tonic-gate * to flush everybody above us.
176*0Sstevel@tonic-gate */
177*0Sstevel@tonic-gate flushq(RD(q), FLUSHDATA);
178*0Sstevel@tonic-gate (void) putnextctl1(RD(q), M_FLUSH, FLUSHR);
179*0Sstevel@tonic-gate /* FALLTHROUGH */
180*0Sstevel@tonic-gate
181*0Sstevel@tonic-gate case TCSETAW:
182*0Sstevel@tonic-gate case TCSETA: {
183*0Sstevel@tonic-gate struct termio *cb;
184*0Sstevel@tonic-gate
185*0Sstevel@tonic-gate if (miocpullup(mp, sizeof (struct termio)) != 0) {
186*0Sstevel@tonic-gate *errorp = -1;
187*0Sstevel@tonic-gate break;
188*0Sstevel@tonic-gate }
189*0Sstevel@tonic-gate
190*0Sstevel@tonic-gate /*
191*0Sstevel@tonic-gate * The only information we look at are the iflag word
192*0Sstevel@tonic-gate * and the cflag word. Don't touch the unset portions.
193*0Sstevel@tonic-gate */
194*0Sstevel@tonic-gate cb = (struct termio *)mp->b_cont->b_rptr;
195*0Sstevel@tonic-gate mutex_enter(&tc->t_excl);
196*0Sstevel@tonic-gate tc->t_iflag = (tc->t_iflag & 0xffff0000 | cb->c_iflag);
197*0Sstevel@tonic-gate tc->t_cflag = (tc->t_cflag & 0xffff0000 | cb->c_cflag);
198*0Sstevel@tonic-gate mutex_exit(&tc->t_excl);
199*0Sstevel@tonic-gate break;
200*0Sstevel@tonic-gate }
201*0Sstevel@tonic-gate
202*0Sstevel@tonic-gate case TIOCSWINSZ: {
203*0Sstevel@tonic-gate struct winsize *ws;
204*0Sstevel@tonic-gate
205*0Sstevel@tonic-gate if (miocpullup(mp, sizeof (struct winsize)) != 0) {
206*0Sstevel@tonic-gate *errorp = -1;
207*0Sstevel@tonic-gate break;
208*0Sstevel@tonic-gate }
209*0Sstevel@tonic-gate
210*0Sstevel@tonic-gate /*
211*0Sstevel@tonic-gate * If the window size changed, send a SIGWINCH.
212*0Sstevel@tonic-gate */
213*0Sstevel@tonic-gate ws = (struct winsize *)mp->b_cont->b_rptr;
214*0Sstevel@tonic-gate mutex_enter(&tc->t_excl);
215*0Sstevel@tonic-gate if (bcmp(&tc->t_size, ws, sizeof (struct winsize)) != 0) {
216*0Sstevel@tonic-gate tc->t_size = *ws;
217*0Sstevel@tonic-gate mutex_exit(&tc->t_excl);
218*0Sstevel@tonic-gate (void) putnextctl1(RD(q), M_PCSIG, SIGWINCH);
219*0Sstevel@tonic-gate } else
220*0Sstevel@tonic-gate mutex_exit(&tc->t_excl);
221*0Sstevel@tonic-gate break;
222*0Sstevel@tonic-gate }
223*0Sstevel@tonic-gate
224*0Sstevel@tonic-gate /*
225*0Sstevel@tonic-gate * Prevent more opens.
226*0Sstevel@tonic-gate */
227*0Sstevel@tonic-gate case TIOCEXCL:
228*0Sstevel@tonic-gate mutex_enter(&tc->t_excl);
229*0Sstevel@tonic-gate tc->t_flags |= TS_XCLUDE;
230*0Sstevel@tonic-gate mutex_exit(&tc->t_excl);
231*0Sstevel@tonic-gate break;
232*0Sstevel@tonic-gate
233*0Sstevel@tonic-gate /*
234*0Sstevel@tonic-gate * Permit more opens.
235*0Sstevel@tonic-gate */
236*0Sstevel@tonic-gate case TIOCNXCL:
237*0Sstevel@tonic-gate mutex_enter(&tc->t_excl);
238*0Sstevel@tonic-gate tc->t_flags &= ~TS_XCLUDE;
239*0Sstevel@tonic-gate mutex_exit(&tc->t_excl);
240*0Sstevel@tonic-gate break;
241*0Sstevel@tonic-gate
242*0Sstevel@tonic-gate /*
243*0Sstevel@tonic-gate * Set or clear the "soft carrier" flag.
244*0Sstevel@tonic-gate */
245*0Sstevel@tonic-gate case TIOCSSOFTCAR:
246*0Sstevel@tonic-gate if (miocpullup(mp, sizeof (int)) != 0) {
247*0Sstevel@tonic-gate *errorp = -1;
248*0Sstevel@tonic-gate break;
249*0Sstevel@tonic-gate }
250*0Sstevel@tonic-gate
251*0Sstevel@tonic-gate mutex_enter(&tc->t_excl);
252*0Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr)
253*0Sstevel@tonic-gate tc->t_flags |= TS_SOFTCAR;
254*0Sstevel@tonic-gate else
255*0Sstevel@tonic-gate tc->t_flags &= ~TS_SOFTCAR;
256*0Sstevel@tonic-gate mutex_exit(&tc->t_excl);
257*0Sstevel@tonic-gate break;
258*0Sstevel@tonic-gate
259*0Sstevel@tonic-gate /*
260*0Sstevel@tonic-gate * The permission checking has already been done at the stream
261*0Sstevel@tonic-gate * head, since it has to be done in the context of the process
262*0Sstevel@tonic-gate * doing the call.
263*0Sstevel@tonic-gate */
264*0Sstevel@tonic-gate case TIOCSTI: {
265*0Sstevel@tonic-gate mblk_t *bp;
266*0Sstevel@tonic-gate
267*0Sstevel@tonic-gate if (miocpullup(mp, sizeof (char)) != 0) {
268*0Sstevel@tonic-gate *errorp = -1;
269*0Sstevel@tonic-gate break;
270*0Sstevel@tonic-gate }
271*0Sstevel@tonic-gate
272*0Sstevel@tonic-gate /*
273*0Sstevel@tonic-gate * Simulate typing of a character at the terminal.
274*0Sstevel@tonic-gate */
275*0Sstevel@tonic-gate if ((bp = allocb(1, BPRI_MED)) != NULL) {
276*0Sstevel@tonic-gate if (!canput(tc->t_readq->q_next))
277*0Sstevel@tonic-gate freemsg(bp);
278*0Sstevel@tonic-gate else {
279*0Sstevel@tonic-gate *bp->b_wptr++ = *mp->b_cont->b_rptr;
280*0Sstevel@tonic-gate putnext(tc->t_readq, bp);
281*0Sstevel@tonic-gate }
282*0Sstevel@tonic-gate }
283*0Sstevel@tonic-gate break;
284*0Sstevel@tonic-gate }
285*0Sstevel@tonic-gate }
286*0Sstevel@tonic-gate
287*0Sstevel@tonic-gate /*
288*0Sstevel@tonic-gate * Turn the ioctl message into an ioctl ACK message.
289*0Sstevel@tonic-gate */
290*0Sstevel@tonic-gate iocp->ioc_count = 0; /* no data returned unless we say so */
291*0Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
292*0Sstevel@tonic-gate
293*0Sstevel@tonic-gate switch (iocp->ioc_cmd) {
294*0Sstevel@tonic-gate
295*0Sstevel@tonic-gate case TCSETSF:
296*0Sstevel@tonic-gate case TCSETSW:
297*0Sstevel@tonic-gate case TCSETS:
298*0Sstevel@tonic-gate case TCSETAF:
299*0Sstevel@tonic-gate case TCSETAW:
300*0Sstevel@tonic-gate case TCSETA:
301*0Sstevel@tonic-gate case TIOCSWINSZ:
302*0Sstevel@tonic-gate case TIOCEXCL:
303*0Sstevel@tonic-gate case TIOCNXCL:
304*0Sstevel@tonic-gate case TIOCSSOFTCAR:
305*0Sstevel@tonic-gate case TIOCSTI:
306*0Sstevel@tonic-gate /*
307*0Sstevel@tonic-gate * We've done all the important work on these already;
308*0Sstevel@tonic-gate * just reply with an ACK.
309*0Sstevel@tonic-gate */
310*0Sstevel@tonic-gate break;
311*0Sstevel@tonic-gate
312*0Sstevel@tonic-gate case TCGETS: {
313*0Sstevel@tonic-gate struct termios *cb;
314*0Sstevel@tonic-gate mblk_t *datap;
315*0Sstevel@tonic-gate
316*0Sstevel@tonic-gate if ((datap = allocb(sizeof (struct termios),
317*0Sstevel@tonic-gate BPRI_HI)) == NULL) {
318*0Sstevel@tonic-gate ioctlrespsize = sizeof (struct termios);
319*0Sstevel@tonic-gate goto allocfailure;
320*0Sstevel@tonic-gate }
321*0Sstevel@tonic-gate cb = (struct termios *)datap->b_wptr;
322*0Sstevel@tonic-gate /*
323*0Sstevel@tonic-gate * The only information we supply is the cflag word.
324*0Sstevel@tonic-gate * Our copy of the iflag word is just that, a copy.
325*0Sstevel@tonic-gate */
326*0Sstevel@tonic-gate bzero(cb, sizeof (struct termios));
327*0Sstevel@tonic-gate cb->c_cflag = tc->t_cflag;
328*0Sstevel@tonic-gate datap->b_wptr += sizeof (struct termios);
329*0Sstevel@tonic-gate iocp->ioc_count = sizeof (struct termios);
330*0Sstevel@tonic-gate if (mp->b_cont != NULL)
331*0Sstevel@tonic-gate freemsg(mp->b_cont);
332*0Sstevel@tonic-gate mp->b_cont = datap;
333*0Sstevel@tonic-gate break;
334*0Sstevel@tonic-gate }
335*0Sstevel@tonic-gate
336*0Sstevel@tonic-gate case TCGETA: {
337*0Sstevel@tonic-gate struct termio *cb;
338*0Sstevel@tonic-gate mblk_t *datap;
339*0Sstevel@tonic-gate
340*0Sstevel@tonic-gate if ((datap = allocb(sizeof (struct termio), BPRI_HI)) == NULL) {
341*0Sstevel@tonic-gate ioctlrespsize = sizeof (struct termio);
342*0Sstevel@tonic-gate goto allocfailure;
343*0Sstevel@tonic-gate }
344*0Sstevel@tonic-gate
345*0Sstevel@tonic-gate cb = (struct termio *)datap->b_wptr;
346*0Sstevel@tonic-gate /*
347*0Sstevel@tonic-gate * The only information we supply is the cflag word.
348*0Sstevel@tonic-gate * Our copy of the iflag word is just that, a copy.
349*0Sstevel@tonic-gate */
350*0Sstevel@tonic-gate bzero(cb, sizeof (struct termio));
351*0Sstevel@tonic-gate cb->c_cflag = tc->t_cflag;
352*0Sstevel@tonic-gate datap->b_wptr += sizeof (struct termio);
353*0Sstevel@tonic-gate iocp->ioc_count = sizeof (struct termio);
354*0Sstevel@tonic-gate if (mp->b_cont != NULL)
355*0Sstevel@tonic-gate freemsg(mp->b_cont);
356*0Sstevel@tonic-gate mp->b_cont = datap;
357*0Sstevel@tonic-gate break;
358*0Sstevel@tonic-gate }
359*0Sstevel@tonic-gate
360*0Sstevel@tonic-gate /*
361*0Sstevel@tonic-gate * Get the "soft carrier" flag.
362*0Sstevel@tonic-gate */
363*0Sstevel@tonic-gate case TIOCGSOFTCAR: {
364*0Sstevel@tonic-gate mblk_t *datap;
365*0Sstevel@tonic-gate
366*0Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
367*0Sstevel@tonic-gate ioctlrespsize = sizeof (int);
368*0Sstevel@tonic-gate goto allocfailure;
369*0Sstevel@tonic-gate }
370*0Sstevel@tonic-gate if (tc->t_flags & TS_SOFTCAR)
371*0Sstevel@tonic-gate *(int *)datap->b_wptr = 1;
372*0Sstevel@tonic-gate else
373*0Sstevel@tonic-gate *(int *)datap->b_wptr = 0;
374*0Sstevel@tonic-gate datap->b_wptr += sizeof (int);
375*0Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
376*0Sstevel@tonic-gate if (mp->b_cont != NULL)
377*0Sstevel@tonic-gate freemsg(mp->b_cont);
378*0Sstevel@tonic-gate mp->b_cont = datap;
379*0Sstevel@tonic-gate break;
380*0Sstevel@tonic-gate }
381*0Sstevel@tonic-gate
382*0Sstevel@tonic-gate case TIOCGWINSZ: {
383*0Sstevel@tonic-gate mblk_t *datap;
384*0Sstevel@tonic-gate
385*0Sstevel@tonic-gate if ((datap = allocb(sizeof (struct winsize),
386*0Sstevel@tonic-gate BPRI_HI)) == NULL) {
387*0Sstevel@tonic-gate ioctlrespsize = sizeof (struct winsize);
388*0Sstevel@tonic-gate goto allocfailure;
389*0Sstevel@tonic-gate }
390*0Sstevel@tonic-gate /*
391*0Sstevel@tonic-gate * Return the current size.
392*0Sstevel@tonic-gate */
393*0Sstevel@tonic-gate *(struct winsize *)datap->b_wptr = tc->t_size;
394*0Sstevel@tonic-gate datap->b_wptr += sizeof (struct winsize);
395*0Sstevel@tonic-gate iocp->ioc_count = sizeof (struct winsize);
396*0Sstevel@tonic-gate if (mp->b_cont != NULL)
397*0Sstevel@tonic-gate freemsg(mp->b_cont);
398*0Sstevel@tonic-gate mp->b_cont = datap;
399*0Sstevel@tonic-gate break;
400*0Sstevel@tonic-gate }
401*0Sstevel@tonic-gate
402*0Sstevel@tonic-gate default:
403*0Sstevel@tonic-gate *errorp = -1; /* we don't understand it, maybe they do */
404*0Sstevel@tonic-gate break;
405*0Sstevel@tonic-gate }
406*0Sstevel@tonic-gate return (0);
407*0Sstevel@tonic-gate
408*0Sstevel@tonic-gate allocfailure:
409*0Sstevel@tonic-gate
410*0Sstevel@tonic-gate mutex_enter(&tc->t_excl);
411*0Sstevel@tonic-gate tmp = tc->t_iocpending;
412*0Sstevel@tonic-gate tc->t_iocpending = mp; /* hold this ioctl */
413*0Sstevel@tonic-gate mutex_exit(&tc->t_excl);
414*0Sstevel@tonic-gate /*
415*0Sstevel@tonic-gate * We needed to allocate something to handle this "ioctl", but
416*0Sstevel@tonic-gate * couldn't; save this "ioctl" and arrange to get called back when
417*0Sstevel@tonic-gate * it's more likely that we can get what we need.
418*0Sstevel@tonic-gate * If there's already one being saved, throw it out, since it
419*0Sstevel@tonic-gate * must have timed out.
420*0Sstevel@tonic-gate */
421*0Sstevel@tonic-gate if (tmp != NULL)
422*0Sstevel@tonic-gate freemsg(tmp);
423*0Sstevel@tonic-gate return (ioctlrespsize);
424*0Sstevel@tonic-gate }
425*0Sstevel@tonic-gate
426*0Sstevel@tonic-gate #define NFIELDS 20 /* 16 control characters + 4 sets of modes */
427*0Sstevel@tonic-gate
428*0Sstevel@tonic-gate /*
429*0Sstevel@tonic-gate * Init routine run from main at boot time.
430*0Sstevel@tonic-gate * Creates a property in the "options" node that is
431*0Sstevel@tonic-gate * the default set of termios modes upon driver open.
432*0Sstevel@tonic-gate * If the property already existed, then it was
433*0Sstevel@tonic-gate * defined in the options.conf file. In this case we
434*0Sstevel@tonic-gate * need to convert this string (stty -g style) to an
435*0Sstevel@tonic-gate * actual termios structure and store the new property
436*0Sstevel@tonic-gate * value.
437*0Sstevel@tonic-gate */
438*0Sstevel@tonic-gate
439*0Sstevel@tonic-gate void
ttyinit()440*0Sstevel@tonic-gate ttyinit()
441*0Sstevel@tonic-gate {
442*0Sstevel@tonic-gate dev_info_t *dip;
443*0Sstevel@tonic-gate struct termios new_termios;
444*0Sstevel@tonic-gate struct termios *tp;
445*0Sstevel@tonic-gate char *property = "ttymodes";
446*0Sstevel@tonic-gate char **modesp, *cp;
447*0Sstevel@tonic-gate int i;
448*0Sstevel@tonic-gate uint_t val;
449*0Sstevel@tonic-gate uint_t len;
450*0Sstevel@tonic-gate
451*0Sstevel@tonic-gate
452*0Sstevel@tonic-gate /*
453*0Sstevel@tonic-gate * If the termios defaults were NOT set up by the
454*0Sstevel@tonic-gate * user via the options.conf file, create it using the
455*0Sstevel@tonic-gate * "sane" set of termios modes.
456*0Sstevel@tonic-gate * Note that if the property had been created via the
457*0Sstevel@tonic-gate * options.conf file, it would have been created as
458*0Sstevel@tonic-gate * a string property. Since we would like to store
459*0Sstevel@tonic-gate * a structure (termios) in this property, we need
460*0Sstevel@tonic-gate * to change the property type to byte array.
461*0Sstevel@tonic-gate */
462*0Sstevel@tonic-gate if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, ddi_root_node(), 0,
463*0Sstevel@tonic-gate property, (char ***)&modesp, &len) != DDI_PROP_SUCCESS) {
464*0Sstevel@tonic-gate
465*0Sstevel@tonic-gate if ((dip = ddi_find_devinfo("options", -1, 0)) == NULL) {
466*0Sstevel@tonic-gate cmn_err(CE_PANIC,
467*0Sstevel@tonic-gate "ttyinit: Can't find options node!\n");
468*0Sstevel@tonic-gate }
469*0Sstevel@tonic-gate /*
470*0Sstevel@tonic-gate * Create the property.
471*0Sstevel@tonic-gate */
472*0Sstevel@tonic-gate if (ddi_prop_update_byte_array(DDI_DEV_T_NONE, dip,
473*0Sstevel@tonic-gate property, (uchar_t *)&default_termios,
474*0Sstevel@tonic-gate sizeof (struct termios)) != DDI_PROP_SUCCESS) {
475*0Sstevel@tonic-gate cmn_err(CE_PANIC, "ttyinit: can't create %s property\n",
476*0Sstevel@tonic-gate property);
477*0Sstevel@tonic-gate }
478*0Sstevel@tonic-gate return;
479*0Sstevel@tonic-gate }
480*0Sstevel@tonic-gate
481*0Sstevel@tonic-gate /*
482*0Sstevel@tonic-gate * This property was already set in the options.conf
483*0Sstevel@tonic-gate * file. We must convert it from a "stty -g" string
484*0Sstevel@tonic-gate * to an actual termios structure.
485*0Sstevel@tonic-gate */
486*0Sstevel@tonic-gate bzero(&new_termios, sizeof (struct termios));
487*0Sstevel@tonic-gate tp = &new_termios;
488*0Sstevel@tonic-gate cp = *modesp;
489*0Sstevel@tonic-gate for (i = 0; i < NFIELDS; i++) {
490*0Sstevel@tonic-gate /*
491*0Sstevel@tonic-gate * Check for bad field/string.
492*0Sstevel@tonic-gate */
493*0Sstevel@tonic-gate if (termioval(&cp, &val, *modesp+strlen(*modesp)) == -1) {
494*0Sstevel@tonic-gate cmn_err(CE_WARN,
495*0Sstevel@tonic-gate "ttyinit: property '%s' %s\n", property,
496*0Sstevel@tonic-gate "set incorrectly, using sane value");
497*0Sstevel@tonic-gate tp = &default_termios;
498*0Sstevel@tonic-gate break;
499*0Sstevel@tonic-gate }
500*0Sstevel@tonic-gate switch (i) {
501*0Sstevel@tonic-gate case 0:
502*0Sstevel@tonic-gate new_termios.c_iflag = (tcflag_t)val;
503*0Sstevel@tonic-gate break;
504*0Sstevel@tonic-gate case 1:
505*0Sstevel@tonic-gate new_termios.c_oflag = (tcflag_t)val;
506*0Sstevel@tonic-gate break;
507*0Sstevel@tonic-gate case 2:
508*0Sstevel@tonic-gate new_termios.c_cflag = (tcflag_t)val;
509*0Sstevel@tonic-gate break;
510*0Sstevel@tonic-gate case 3:
511*0Sstevel@tonic-gate new_termios.c_lflag = (tcflag_t)val;
512*0Sstevel@tonic-gate break;
513*0Sstevel@tonic-gate default:
514*0Sstevel@tonic-gate new_termios.c_cc[i - 4] = (cc_t)val;
515*0Sstevel@tonic-gate }
516*0Sstevel@tonic-gate }
517*0Sstevel@tonic-gate if ((dip = ddi_find_devinfo("options", -1, 0)) == NULL) {
518*0Sstevel@tonic-gate cmn_err(CE_PANIC, "ttyinit: Can't find options node!\n");
519*0Sstevel@tonic-gate }
520*0Sstevel@tonic-gate
521*0Sstevel@tonic-gate /*
522*0Sstevel@tonic-gate * We need to create ttymode property as a byte array
523*0Sstevel@tonic-gate * since it will be interpreted as a termios struct.
524*0Sstevel@tonic-gate * The property was created as a string by default.
525*0Sstevel@tonic-gate * So remove the old property and add the new one -
526*0Sstevel@tonic-gate * otherwise we end up with two ttymodes properties.
527*0Sstevel@tonic-gate */
528*0Sstevel@tonic-gate if (e_ddi_prop_remove(DDI_DEV_T_NONE, dip, property)
529*0Sstevel@tonic-gate != DDI_PROP_SUCCESS) {
530*0Sstevel@tonic-gate cmn_err(CE_WARN, "ttyinit: cannot remove '%s' property\n",
531*0Sstevel@tonic-gate property);
532*0Sstevel@tonic-gate }
533*0Sstevel@tonic-gate /*
534*0Sstevel@tonic-gate * Store the new defaults. Since, this property was
535*0Sstevel@tonic-gate * autoconfig'ed, we must use e_ddi_prop_update_byte_array().
536*0Sstevel@tonic-gate */
537*0Sstevel@tonic-gate if (e_ddi_prop_update_byte_array(DDI_DEV_T_NONE, dip, property,
538*0Sstevel@tonic-gate (uchar_t *)tp, sizeof (struct termios)) != DDI_PROP_SUCCESS) {
539*0Sstevel@tonic-gate cmn_err(CE_PANIC, "ttyinit: cannot modify '%s' property\n",
540*0Sstevel@tonic-gate property);
541*0Sstevel@tonic-gate }
542*0Sstevel@tonic-gate ddi_prop_free(modesp);
543*0Sstevel@tonic-gate }
544*0Sstevel@tonic-gate
545*0Sstevel@tonic-gate /*
546*0Sstevel@tonic-gate * Convert hex string representation of termios field
547*0Sstevel@tonic-gate * to a uint_t. Increments string pointer to the next
548*0Sstevel@tonic-gate * field, and assigns value. Returns -1 if no more fields
549*0Sstevel@tonic-gate * or an error.
550*0Sstevel@tonic-gate */
551*0Sstevel@tonic-gate
552*0Sstevel@tonic-gate static int
termioval(char ** sp,uint_t * valp,char * ep)553*0Sstevel@tonic-gate termioval(char **sp, uint_t *valp, char *ep)
554*0Sstevel@tonic-gate {
555*0Sstevel@tonic-gate char *s = *sp;
556*0Sstevel@tonic-gate uint_t digit;
557*0Sstevel@tonic-gate
558*0Sstevel@tonic-gate if (s == 0)
559*0Sstevel@tonic-gate return (-1);
560*0Sstevel@tonic-gate *valp = 0;
561*0Sstevel@tonic-gate while (s < ep) {
562*0Sstevel@tonic-gate if (*s >= '0' && *s <= '9')
563*0Sstevel@tonic-gate digit = *s++ - '0';
564*0Sstevel@tonic-gate else if (*s >= 'a' && *s <= 'f')
565*0Sstevel@tonic-gate digit = *s++ - 'a' + 10;
566*0Sstevel@tonic-gate else if (*s >= 'A' && *s <= 'F')
567*0Sstevel@tonic-gate digit = *s++ - 'A' + 10;
568*0Sstevel@tonic-gate else if (*s == ':' || *s == '\0')
569*0Sstevel@tonic-gate break;
570*0Sstevel@tonic-gate else
571*0Sstevel@tonic-gate return (-1);
572*0Sstevel@tonic-gate *valp = (*valp * 16) + digit;
573*0Sstevel@tonic-gate }
574*0Sstevel@tonic-gate /*
575*0Sstevel@tonic-gate * Null string or empty field.
576*0Sstevel@tonic-gate */
577*0Sstevel@tonic-gate if (s == *sp)
578*0Sstevel@tonic-gate return (-1);
579*0Sstevel@tonic-gate
580*0Sstevel@tonic-gate if (s < ep && *s == ':')
581*0Sstevel@tonic-gate s++;
582*0Sstevel@tonic-gate
583*0Sstevel@tonic-gate *sp = s;
584*0Sstevel@tonic-gate return (0);
585*0Sstevel@tonic-gate }
586