99337f1c7d792f74de58b34561f833b08eeff45e
[dragonfly.git] / sys / kern / tty_pty.c
1 /*
2  * (MPSAFE)
3  *
4  * Copyright (c) 1982, 1986, 1989, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by the University of
18  *      California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *      @(#)tty_pty.c   8.4 (Berkeley) 2/20/95
36  * $FreeBSD: src/sys/kern/tty_pty.c,v 1.74.2.4 2002/02/20 19:58:13 dillon Exp $
37  */
38
39 /*
40  * MPSAFE NOTE: 
41  * Most functions here could use a separate lock to deal with concurrent
42  * access to the 'pt's.
43  *
44  * Right now the tty_token must be held for all this.
45  */
46
47 /*
48  * Pseudo-teletype Driver
49  * (Actually two drivers, requiring two dev_ops structures)
50  */
51
52 #include "opt_compat.h"
53
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
57 #include <sys/ioctl_compat.h>
58 #endif
59 #include <sys/proc.h>
60 #include <sys/priv.h>
61 #include <sys/tty.h>
62 #include <sys/conf.h>
63 #include <sys/fcntl.h>
64 #include <sys/kernel.h>
65 #include <sys/vnode.h>
66 #include <sys/signalvar.h>
67 #include <sys/malloc.h>
68 #include <sys/device.h>
69 #include <sys/thread2.h>
70 #include <sys/devfs.h>
71 #include <sys/stat.h>
72 #include <sys/sysctl.h>
73
74 #define UNIX98_PTYS     1
75
76 MALLOC_DEFINE(M_PTY, "ptys", "pty data structures");
77
78 static void ptsstart (struct tty *tp);
79 static void ptsstop (struct tty *tp, int rw);
80 static void ptsunhold (struct tty *tp);
81 static void ptcwakeup (struct tty *tp, int flag);
82 static void ptyinit (int n);
83 static int  filt_ptcread (struct knote *kn, long hint);
84 static void filt_ptcrdetach (struct knote *kn);
85 static int  filt_ptcwrite (struct knote *kn, long hint);
86 static void filt_ptcwdetach (struct knote *kn);
87
88 static  d_open_t        ptsopen;
89 static  d_close_t       ptsclose;
90 static  d_read_t        ptsread;
91 static  d_write_t       ptswrite;
92 static  d_ioctl_t       ptyioctl;
93 static  d_open_t        ptcopen;
94 static  d_close_t       ptcclose;
95 static  d_read_t        ptcread;
96 static  d_write_t       ptcwrite;
97 static  d_kqfilter_t    ptckqfilter;
98
99 #ifdef UNIX98_PTYS
100 DEVFS_DECLARE_CLONE_BITMAP(pty);
101
102 static  d_clone_t       ptyclone;
103
104 static int      pty_debug_level = 0;
105
106 static struct dev_ops pts98_ops = {
107         { "pts98", 0, D_TTY | D_MPSAFE },
108         .d_open =       ptsopen,
109         .d_close =      ptsclose,
110         .d_read =       ptsread,
111         .d_write =      ptswrite,
112         .d_ioctl =      ptyioctl,
113         .d_kqfilter =   ttykqfilter,
114         .d_revoke =     ttyrevoke
115 };
116
117 static struct dev_ops ptc98_ops = {
118         { "ptc98", 0, D_TTY | D_MASTER | D_MPSAFE },
119         .d_open =       ptcopen,
120         .d_close =      ptcclose,
121         .d_read =       ptcread,
122         .d_write =      ptcwrite,
123         .d_ioctl =      ptyioctl,
124         .d_kqfilter =   ptckqfilter,
125         .d_revoke =     ttyrevoke
126 };
127 #endif
128
129 static struct dev_ops pts_ops = {
130         { "pts", 0, D_TTY | D_MPSAFE },
131         .d_open =       ptsopen,
132         .d_close =      ptsclose,
133         .d_read =       ptsread,
134         .d_write =      ptswrite,
135         .d_ioctl =      ptyioctl,
136         .d_kqfilter =   ttykqfilter,
137         .d_revoke =     ttyrevoke
138 };
139
140 #define CDEV_MAJOR_C    6
141 static struct dev_ops ptc_ops = {
142         { "ptc", 0, D_TTY | D_MASTER | D_MPSAFE },
143         .d_open =       ptcopen,
144         .d_close =      ptcclose,
145         .d_read =       ptcread,
146         .d_write =      ptcwrite,
147         .d_ioctl =      ptyioctl,
148         .d_kqfilter =   ptckqfilter,
149         .d_revoke =     ttyrevoke
150 };
151
152 #define BUFSIZ 100              /* Chunk size iomoved to/from user */
153
154 struct  pt_ioctl {
155         int     pt_flags;
156         int     pt_refs;        /* Structural references interlock S/MOPEN */
157         int     pt_uminor;
158         struct  kqinfo pt_kqr, pt_kqw;
159         u_char  pt_send;
160         u_char  pt_ucntl;
161         struct tty pt_tty;
162         cdev_t  devs, devc;
163         struct  prison *pt_prison;
164 };
165
166 /*
167  * pt_flags ptc state
168  */
169 #define PF_PKT          0x0008          /* packet mode */
170 #define PF_STOPPED      0x0010          /* user told stopped */
171 #define PF_REMOTE       0x0020          /* remote and flow controlled input */
172 #define PF_NOSTOP       0x0040
173 #define PF_UCNTL        0x0080          /* user control mode */
174
175 #define PF_PTCSTATEMASK 0x00FF
176
177 /*
178  * pt_flags open state.  Note that PF_SCLOSED is used to activate
179  * read EOF on the ptc so it is only set after the slave has been
180  * opened and then closed, and cleared again if the slave is opened
181  * again.
182  */
183 #define PF_UNIX98       0x0100
184 #define PF_SOPEN        0x0200
185 #define PF_MOPEN        0x0400
186 #define PF_SCLOSED      0x0800
187 #define PF_TERMINATED   0x8000
188
189 /*
190  * This function creates and initializes a pts/ptc pair
191  *
192  * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
193  * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
194  *
195  * XXX: define and add mapping of upper minor bits to allow more 
196  *      than 256 ptys.
197  */
198 static void
199 ptyinit(int n)
200 {
201         cdev_t devs, devc;
202         char *names = "pqrsPQRS";
203         struct pt_ioctl *pt;
204
205         /* For now we only map the lower 8 bits of the minor */
206         if (n & ~0xff)
207                 return;
208
209         pt = kmalloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO);
210         pt->devs = devs = make_dev(&pts_ops, n,
211             0, 0, 0666, "tty%c%r", names[n / 32], n % 32);
212         pt->devc = devc = make_dev(&ptc_ops, n,
213             0, 0, 0666, "pty%c%r", names[n / 32], n % 32);
214
215         pt->pt_tty.t_dev = devs;
216         pt->pt_uminor = n;
217         devs->si_drv1 = devc->si_drv1 = pt;
218         devs->si_tty = devc->si_tty = &pt->pt_tty;
219         devs->si_flags |= SI_OVERRIDE;  /* uid, gid, perms from dev */
220         devc->si_flags |= SI_OVERRIDE;  /* uid, gid, perms from dev */
221         ttyregister(&pt->pt_tty);
222 }
223
224 #ifdef UNIX98_PTYS
225 static int
226 ptyclone(struct dev_clone_args *ap)
227 {
228         int unit;
229         struct pt_ioctl *pt;
230
231         /*
232          * Limit the number of unix98 pty (slave) devices to 1000, as
233          * the utmp(5) format only allows for 8 bytes for the tty,
234          * "pts/XXX".
235          * If this limit is reached, we don't clone and return error
236          * to devfs.
237          */
238         unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(pty), 1000);
239
240         if (unit < 0) {
241                 ap->a_dev = NULL;
242                 return 1;
243         }
244
245         pt = kmalloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO);
246
247         pt->devc = make_only_dev(&ptc98_ops, unit,
248                                  ap->a_cred->cr_ruid,
249                                  0, 0600, "ptm/%d", unit);
250         pt->devs = make_dev(&pts98_ops, unit,
251                             ap->a_cred->cr_ruid,
252                             GID_TTY, 0620, "pts/%d", unit);
253         ap->a_dev = pt->devc;
254
255         pt->devs->si_flags |= SI_OVERRIDE;      /* uid, gid, perms from dev */
256         pt->devc->si_flags |= SI_OVERRIDE;      /* uid, gid, perms from dev */
257
258         pt->pt_tty.t_dev = pt->devs;
259         pt->pt_flags |= PF_UNIX98;
260         pt->pt_uminor = unit;
261         pt->devs->si_drv1 = pt->devc->si_drv1 = pt;
262         pt->devs->si_tty = pt->devc->si_tty = &pt->pt_tty;
263
264         ttyregister(&pt->pt_tty);
265
266         return 0;
267 }
268 #endif
269
270 /*
271  * pti_hold() prevents the pti from being destroyed due to a termination
272  * while a pt*open() is blocked.
273  *
274  * This function returns non-zero if we cannot hold due to a termination
275  * interlock.
276  *
277  * NOTE: Must be called with tty_token held
278  */
279 static int
280 pti_hold(struct pt_ioctl *pti)
281 {
282         if (pti->pt_flags & PF_TERMINATED)
283                 return(ENXIO);
284         ++pti->pt_refs;
285         return(0);
286 }
287
288 /*
289  * pti_done() releases the reference and checks to see if both sides have
290  * been closed on a unix98 pty, allowing us to destroy the device and
291  * release resources.
292  *
293  * We do not release resources on non-unix98 ptys.  Those are left
294  * statically allocated.
295  */
296 static void
297 pti_done(struct pt_ioctl *pti)
298 {
299         lwkt_gettoken(&tty_token);
300         if (--pti->pt_refs == 0) {
301 #ifdef UNIX98_PTYS
302                 cdev_t dev;
303                 int uminor_no;
304
305                 /*
306                  * Only unix09 ptys are freed up
307                  */
308                 if ((pti->pt_flags & PF_UNIX98) == 0) {
309                         lwkt_reltoken(&tty_token);
310                         return;
311                 }
312
313                 /*
314                  * Interlock open attempts against termination by setting
315                  * PF_TERMINATED.  This allows us to block while cleaning
316                  * out the device infrastructure.
317                  *
318                  * Do not terminate the tty if it still has a session
319                  * association (t_refs).
320                  */
321                 if ((pti->pt_flags & (PF_SOPEN|PF_MOPEN)) == 0 &&
322                     pti->pt_tty.t_refs == 0) {
323                         pti->pt_flags |= PF_TERMINATED;
324                         uminor_no = pti->pt_uminor;
325
326                         if ((dev = pti->devs) != NULL) {
327                                 dev->si_drv1 = NULL;
328                                 pti->devs = NULL;
329                                 destroy_dev(dev);
330                         }
331                         if ((dev = pti->devc) != NULL) {
332                                 dev->si_drv1 = NULL;
333                                 pti->devc = NULL;
334                                 destroy_dev(dev);
335                         }
336                         ttyunregister(&pti->pt_tty);
337                         devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(pty),
338                                                uminor_no);
339                         kfree(pti, M_PTY);
340                 }
341 #endif
342         }
343         lwkt_reltoken(&tty_token);
344 }
345
346 /*ARGSUSED*/
347 static  int
348 ptsopen(struct dev_open_args *ap)
349 {
350         cdev_t dev = ap->a_head.a_dev;
351         struct tty *tp;
352         int error;
353         struct pt_ioctl *pti;
354
355         /*
356          * The pti will already be assigned by the clone code or
357          * pre-created if a non-unix 98 pty.  If si_drv1 is NULL
358          * we are somehow racing a unix98 termination.
359          */
360         if (dev->si_drv1 == NULL)
361                 return(ENXIO);
362         pti = dev->si_drv1;
363
364         lwkt_gettoken(&tty_token);
365         if (pti_hold(pti)) {
366                 lwkt_reltoken(&tty_token);
367                 return(ENXIO);
368         }
369
370         tp = dev->si_tty;
371
372         /*
373          * Reinit most of the tty state if it isn't open.  Handle
374          * exclusive access.
375          */
376         if ((tp->t_state & TS_ISOPEN) == 0) {
377                 ttychars(tp);           /* Set up default chars */
378                 tp->t_iflag = TTYDEF_IFLAG;
379                 tp->t_oflag = TTYDEF_OFLAG;
380                 tp->t_lflag = TTYDEF_LFLAG;
381                 tp->t_cflag = TTYDEF_CFLAG;
382                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
383         } else if ((tp->t_state & TS_XCLUDE) &&
384                    priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) {
385                 pti_done(pti);
386                 lwkt_reltoken(&tty_token);
387                 return (EBUSY);
388         } else if (pti->pt_prison != ap->a_cred->cr_prison) {
389                 pti_done(pti);
390                 lwkt_reltoken(&tty_token);
391                 return (EBUSY);
392         }
393
394         /*
395          * If the ptc is already present this will connect us up.  It
396          * is unclear if this is actually needed.
397          *
398          * If neither side is open be sure to clear any left over
399          * ZOMBIE state before continuing.
400          */
401         if (tp->t_oproc)
402                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
403         else if ((pti->pt_flags & PF_SOPEN) == 0)
404                 tp->t_state &= ~TS_ZOMBIE;
405
406         /*
407          * Wait for the carrier (ptc side)
408          */
409         while ((tp->t_state & TS_CARR_ON) == 0) {
410                 if (ap->a_oflags & FNONBLOCK)
411                         break;
412                 error = ttysleep(tp, TSA_CARR_ON(tp), PCATCH, "ptsopn", 0);
413                 if (error) {
414                         pti_done(pti);
415                         lwkt_reltoken(&tty_token);
416                         return (error);
417                 }
418         }
419
420         /*
421          * Mark the tty open and mark the slave side as being open.
422          */
423         error = (*linesw[tp->t_line].l_open)(dev, tp);
424
425         if (error == 0) {
426                 pti->pt_flags |= PF_SOPEN;
427                 pti->pt_flags &= ~PF_SCLOSED;
428                 ptcwakeup(tp, FREAD|FWRITE);
429         }
430         pti_done(pti);
431
432         lwkt_reltoken(&tty_token);
433         return (error);
434 }
435
436 static  int
437 ptsclose(struct dev_close_args *ap)
438 {
439         cdev_t dev = ap->a_head.a_dev;
440         struct tty *tp;
441         struct pt_ioctl *pti = dev->si_drv1;
442         int err;
443
444         lwkt_gettoken(&tty_token);
445         if (pti_hold(pti))
446                 panic("ptsclose on terminated pti");
447
448         /*
449          * Disconnect the slave side
450          */
451         tp = dev->si_tty;
452         err = (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
453         ptsstop(tp, FREAD|FWRITE);
454         ttyclose(tp);                   /* clears t_state */
455
456         /*
457          * Mark the pts side closed and signal the ptc.  Do not mark the
458          * tty a zombie... that is, allow the tty to be re-opened as long
459          * as the ptc is still open.  The ptc will read() EOFs until the
460          * pts side is reopened or the ptc is closed.
461          *
462          * xterm() depends on this behavior as it will revoke() the pts
463          * and then reopen it after the (unnecessary old code) chmod.
464          */
465         pti->pt_flags &= ~PF_SOPEN;
466         pti->pt_flags |= PF_SCLOSED;
467         if (tp->t_oproc)
468                 ptcwakeup(tp, FREAD);
469         pti_done(pti);
470         lwkt_reltoken(&tty_token);
471         return (err);
472 }
473
474 static  int
475 ptsread(struct dev_read_args *ap)
476 {
477         cdev_t dev = ap->a_head.a_dev;
478         struct proc *p = curproc;
479         struct tty *tp = dev->si_tty;
480         struct pt_ioctl *pti = dev->si_drv1;
481         struct lwp *lp;
482
483         int error = 0;
484
485         lp = curthread->td_lwp;
486
487         lwkt_gettoken(&tty_token);
488 again:
489         if (pti->pt_flags & PF_REMOTE) {
490                 while (isbackground(p, tp)) {
491                         if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
492                             SIGISMEMBER(lp->lwp_sigmask, SIGTTIN) ||
493                             p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) {
494                                 lwkt_reltoken(&tty_token);
495                                 return (EIO);
496                         }
497                         pgsignal(p->p_pgrp, SIGTTIN, 1);
498                         error = ttysleep(tp, &lbolt, PCATCH, "ptsbg", 0);
499                         if (error) {
500                                 lwkt_reltoken(&tty_token);
501                                 return (error);
502                         }
503                 }
504                 if (tp->t_canq.c_cc == 0) {
505                         if (ap->a_ioflag & IO_NDELAY) {
506                                 lwkt_reltoken(&tty_token);
507                                 return (EWOULDBLOCK);
508                         }
509                         error = ttysleep(tp, TSA_PTS_READ(tp), PCATCH,
510                                          "ptsin", 0);
511                         if (error) {
512                                 lwkt_reltoken(&tty_token);
513                                 return (error);
514                         }
515                         goto again;
516                 }
517                 while (tp->t_canq.c_cc > 1 && ap->a_uio->uio_resid > 0)
518                         if (ureadc(clist_getc(&tp->t_canq), ap->a_uio) < 0) {
519                                 error = EFAULT;
520                                 break;
521                         }
522                 if (tp->t_canq.c_cc == 1)
523                         clist_getc(&tp->t_canq);
524                 if (tp->t_canq.c_cc) {
525                         lwkt_reltoken(&tty_token);
526                         return (error);
527                 }
528         } else
529                 if (tp->t_oproc)
530                         error = (*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag);
531         ptcwakeup(tp, FWRITE);
532         lwkt_reltoken(&tty_token);
533         return (error);
534 }
535
536 /*
537  * Write to pseudo-tty.
538  * Wakeups of controlling tty will happen
539  * indirectly, when tty driver calls ptsstart.
540  */
541 static  int
542 ptswrite(struct dev_write_args *ap)
543 {
544         cdev_t dev = ap->a_head.a_dev;
545         struct tty *tp;
546         int ret;
547
548         lwkt_gettoken(&tty_token);
549         tp = dev->si_tty;
550         if (tp->t_oproc == 0) {
551                 lwkt_reltoken(&tty_token);
552                 return (EIO);
553         }
554         ret = ((*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag));
555         lwkt_reltoken(&tty_token);
556         return ret;
557 }
558
559 /*
560  * Start output on pseudo-tty.
561  * Wake up process selecting or sleeping for input from controlling tty.
562  */
563 static void
564 ptsstart(struct tty *tp)
565 {
566         lwkt_gettoken(&tty_token);
567         struct pt_ioctl *pti = tp->t_dev->si_drv1;
568
569         if (tp->t_state & TS_TTSTOP) {
570                 lwkt_reltoken(&tty_token);
571                 return;
572         }
573         if (pti) {
574                 if (pti->pt_flags & PF_STOPPED) {
575                         pti->pt_flags &= ~PF_STOPPED;
576                         pti->pt_send = TIOCPKT_START;
577                 }
578         }
579         ptcwakeup(tp, FREAD);
580         lwkt_reltoken(&tty_token);
581 }
582
583 /*
584  * NOTE: Must be called with tty_token held
585  */
586 static void
587 ptcwakeup(struct tty *tp, int flag)
588 {
589         ASSERT_LWKT_TOKEN_HELD(&tty_token);
590
591         if (flag & FREAD) {
592                 wakeup(TSA_PTC_READ(tp));
593                 KNOTE(&tp->t_rkq.ki_note, 0);
594         }
595         if (flag & FWRITE) {
596                 wakeup(TSA_PTC_WRITE(tp));
597                 KNOTE(&tp->t_wkq.ki_note, 0);
598         }
599 }
600
601 static  int
602 ptcopen(struct dev_open_args *ap)
603 {
604         cdev_t dev = ap->a_head.a_dev;
605         struct tty *tp;
606         struct pt_ioctl *pti;
607
608         /*
609          * The pti will already be assigned by the clone code or
610          * pre-created if a non-unix 98 pty.  If si_drv1 is NULL
611          * we are somehow racing a unix98 termination.
612          */
613         if (dev->si_drv1 == NULL)
614                 return(ENXIO);
615
616         lwkt_gettoken(&tty_token);
617         pti = dev->si_drv1;
618         if (pti_hold(pti)) {
619                 lwkt_reltoken(&tty_token);
620                 return(ENXIO);
621         }
622         if (pti->pt_prison && pti->pt_prison != ap->a_cred->cr_prison) {
623                 pti_done(pti);
624                 lwkt_reltoken(&tty_token);
625                 return(EBUSY);
626         }
627         tp = dev->si_tty;
628         if (tp->t_oproc) {
629                 pti_done(pti);
630                 lwkt_reltoken(&tty_token);
631                 return (EIO);
632         }
633
634         /*
635          * If the slave side is not yet open clear any left over zombie
636          * state before doing our modem control.
637          */
638         if ((pti->pt_flags & PF_SOPEN) == 0)
639                 tp->t_state &= ~TS_ZOMBIE;
640
641         tp->t_oproc = ptsstart;
642         tp->t_stop = ptsstop;
643         tp->t_unhold = ptsunhold;
644
645         /*
646          * Carrier on!
647          */
648         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
649
650         tp->t_lflag &= ~EXTPROC;
651         pti->pt_prison = ap->a_cred->cr_prison;
652         pti->pt_flags &= ~PF_PTCSTATEMASK;
653         pti->pt_send = 0;
654         pti->pt_ucntl = 0;
655
656         pti->devs->si_uid = ap->a_cred->cr_uid;
657         pti->devs->si_gid = 0;
658         pti->devs->si_perms = 0600;
659         pti->devc->si_uid = ap->a_cred->cr_uid;
660         pti->devc->si_gid = 0;
661         pti->devc->si_perms = 0600;
662
663         /*
664          * Mark master side open.  This does not cause any events
665          * on the slave side.
666          */
667         pti->pt_flags |= PF_MOPEN;
668         pti_done(pti);
669
670         lwkt_reltoken(&tty_token);
671         return (0);
672 }
673
674 static  int
675 ptcclose(struct dev_close_args *ap)
676 {
677         cdev_t dev = ap->a_head.a_dev;
678         struct tty *tp;
679         struct pt_ioctl *pti = dev->si_drv1;
680
681         lwkt_gettoken(&tty_token);
682         if (pti_hold(pti))
683                 panic("ptcclose on terminated pti");
684
685         tp = dev->si_tty;
686         (void)(*linesw[tp->t_line].l_modem)(tp, 0);
687
688         /*
689          * Mark the master side closed.  If the slave is still open
690          * mark the tty ZOMBIE, preventing any new action until both
691          * sides have closed.
692          *
693          * NOTE: The ttyflush() will wake up the slave once we've
694          *       set appropriate flags.  The ZOMBIE flag will be
695          *       cleared when the slave side is closed.
696          */
697         pti->pt_flags &= ~PF_MOPEN;
698         if (pti->pt_flags & PF_SOPEN)
699                 tp->t_state |= TS_ZOMBIE;
700
701         /*
702          * Turn off the carrier and disconnect.  This will notify the slave
703          * side.
704          */
705         if (tp->t_state & TS_ISOPEN) {
706                 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
707                 ttyflush(tp, FREAD | FWRITE);
708         }
709         tp->t_oproc = NULL;             /* mark closed */
710
711         pti->pt_prison = NULL;
712         pti->devs->si_uid = 0;
713         pti->devs->si_gid = 0;
714         pti->devs->si_perms = 0666;
715         pti->devc->si_uid = 0;
716         pti->devc->si_gid = 0;
717         pti->devc->si_perms = 0666;
718
719         pti_done(pti);
720
721         lwkt_reltoken(&tty_token);
722         return (0);
723 }
724
725 static  int
726 ptcread(struct dev_read_args *ap)
727 {
728         cdev_t dev = ap->a_head.a_dev;
729         struct tty *tp = dev->si_tty;
730         struct pt_ioctl *pti = dev->si_drv1;
731         char buf[BUFSIZ];
732         int error = 0, cc;
733
734         lwkt_gettoken(&tty_token);
735         /*
736          * We want to block until the slave
737          * is open, and there's something to read;
738          * but if we lost the slave or we're NBIO,
739          * then return the appropriate error instead.
740          */
741         for (;;) {
742                 if (tp->t_state&TS_ISOPEN) {
743                         if ((pti->pt_flags & PF_PKT) && pti->pt_send) {
744                                 error = ureadc((int)pti->pt_send, ap->a_uio);
745                                 if (error) {
746                                         lwkt_reltoken(&tty_token);
747                                         return (error);
748                                 }
749                                 if (pti->pt_send & TIOCPKT_IOCTL) {
750                                         cc = (int)szmin(ap->a_uio->uio_resid,
751                                                         sizeof(tp->t_termios));
752                                         uiomove((caddr_t)&tp->t_termios, cc,
753                                                 ap->a_uio);
754                                 }
755                                 pti->pt_send = 0;
756                                 lwkt_reltoken(&tty_token);
757                                 return (0);
758                         }
759                         if ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl) {
760                                 error = ureadc((int)pti->pt_ucntl, ap->a_uio);
761                                 if (error) {
762                                         lwkt_reltoken(&tty_token);
763                                         return (error);
764                                 }
765                                 pti->pt_ucntl = 0;
766                                 lwkt_reltoken(&tty_token);
767                                 return (0);
768                         }
769                         if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
770                                 break;
771                 }
772                 if ((tp->t_state & TS_CONNECTED) == 0) {
773                         lwkt_reltoken(&tty_token);
774                         return (0);     /* EOF */
775                 }
776                 if (ap->a_ioflag & IO_NDELAY) {
777                         lwkt_reltoken(&tty_token);
778                         return (EWOULDBLOCK);
779                 }
780                 error = tsleep(TSA_PTC_READ(tp), PCATCH, "ptcin", 0);
781                 if (error) {
782                         lwkt_reltoken(&tty_token);
783                         return (error);
784                 }
785         }
786         if (pti->pt_flags & (PF_PKT|PF_UCNTL))
787                 error = ureadc(0, ap->a_uio);
788         while (ap->a_uio->uio_resid > 0 && error == 0) {
789                 cc = q_to_b(&tp->t_outq, buf,
790                             (int)szmin(ap->a_uio->uio_resid, BUFSIZ));
791                 if (cc <= 0)
792                         break;
793                 error = uiomove(buf, (size_t)cc, ap->a_uio);
794         }
795         ttwwakeup(tp);
796         lwkt_reltoken(&tty_token);
797         return (error);
798 }
799
800 static  void
801 ptsstop(struct tty *tp, int flush)
802 {
803         struct pt_ioctl *pti = tp->t_dev->si_drv1;
804         int flag;
805
806         lwkt_gettoken(&tty_token);
807         /* note: FLUSHREAD and FLUSHWRITE already ok */
808         if (pti) {
809                 if (flush == 0) {
810                         flush = TIOCPKT_STOP;
811                         pti->pt_flags |= PF_STOPPED;
812                 } else {
813                         pti->pt_flags &= ~PF_STOPPED;
814                 }
815                 pti->pt_send |= flush;
816                 /* change of perspective */
817         }
818         flag = 0;
819         if (flush & FREAD)
820                 flag |= FWRITE;
821         if (flush & FWRITE)
822                 flag |= FREAD;
823         ptcwakeup(tp, flag);
824
825         lwkt_reltoken(&tty_token);
826 }
827
828 /*
829  * ttyunhold() calls us instead of just decrementing tp->t_refs.  This
830  * is needed because a session can hold onto a pts (half closed state)
831  * even if there are no live file descriptors.  Without the callback
832  * we can't clean up.
833  */
834 static  void
835 ptsunhold(struct tty *tp)
836 {
837         struct pt_ioctl *pti = tp->t_dev->si_drv1;
838
839         lwkt_gettoken(&tty_token);
840         pti_hold(pti);
841         --tp->t_refs;
842         pti_done(pti);
843         lwkt_reltoken(&tty_token);
844 }
845
846 /*
847  * kqueue ops for pseudo-terminals.
848  */
849 static struct filterops ptcread_filtops =
850         { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ptcrdetach, filt_ptcread };
851 static struct filterops ptcwrite_filtops =
852         { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ptcwdetach, filt_ptcwrite };
853
854 static  int
855 ptckqfilter(struct dev_kqfilter_args *ap)
856 {
857         cdev_t dev = ap->a_head.a_dev;
858         struct knote *kn = ap->a_kn;
859         struct tty *tp = dev->si_tty;
860         struct klist *klist;
861
862         lwkt_gettoken(&tty_token);
863         ap->a_result = 0;
864         switch (kn->kn_filter) {
865         case EVFILT_READ:
866                 klist = &tp->t_rkq.ki_note;
867                 kn->kn_fop = &ptcread_filtops;
868                 break;
869         case EVFILT_WRITE:
870                 klist = &tp->t_wkq.ki_note;
871                 kn->kn_fop = &ptcwrite_filtops;
872                 break;
873         default:
874                 ap->a_result = EOPNOTSUPP;
875                 lwkt_reltoken(&tty_token);
876                 return (0);
877         }
878
879         kn->kn_hook = (caddr_t)dev;
880         knote_insert(klist, kn);
881         lwkt_reltoken(&tty_token);
882         return (0);
883 }
884
885 static int
886 filt_ptcread (struct knote *kn, long hint)
887 {
888         struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
889         struct pt_ioctl *pti = ((cdev_t)kn->kn_hook)->si_drv1;
890
891         lwkt_gettoken(&tty_token);
892         if ((tp->t_state & TS_ZOMBIE) || (pti->pt_flags & PF_SCLOSED)) {
893                 kn->kn_flags |= (EV_EOF | EV_NODATA);
894                 lwkt_reltoken(&tty_token);
895                 return (1);
896         }
897
898         if ((tp->t_state & TS_ISOPEN) &&
899             ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
900              ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
901              ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) {
902                 kn->kn_data = tp->t_outq.c_cc;
903                 lwkt_reltoken(&tty_token);
904                 return(1);
905         } else {
906                 lwkt_reltoken(&tty_token);
907                 return(0);
908         }
909 }
910
911 static int
912 filt_ptcwrite (struct knote *kn, long hint)
913 {
914         struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
915         struct pt_ioctl *pti = ((cdev_t)kn->kn_hook)->si_drv1;
916
917         lwkt_gettoken(&tty_token);
918         if (tp->t_state & TS_ZOMBIE) {
919                 kn->kn_flags |= (EV_EOF | EV_NODATA);
920                 lwkt_reltoken(&tty_token);
921                 return (1);
922         }
923
924         if (tp->t_state & TS_ISOPEN &&
925             ((pti->pt_flags & PF_REMOTE) ?
926              (tp->t_canq.c_cc == 0) :
927              ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
928               (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON))))) {
929                 kn->kn_data = tp->t_canq.c_cc + tp->t_rawq.c_cc;
930                 lwkt_reltoken(&tty_token);
931                 return(1);
932         } else {
933                 lwkt_reltoken(&tty_token);
934                 return(0);
935         }
936         /* NOTREACHED */
937 }
938
939 static void
940 filt_ptcrdetach (struct knote *kn)
941 {
942         struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
943
944         knote_remove(&tp->t_rkq.ki_note, kn);
945 }
946
947 static void
948 filt_ptcwdetach (struct knote *kn)
949 {
950         struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
951
952         knote_remove(&tp->t_wkq.ki_note, kn);
953 }
954
955 /*
956  * I/O ops
957  */
958 static  int
959 ptcwrite(struct dev_write_args *ap)
960 {
961         cdev_t dev = ap->a_head.a_dev;
962         struct tty *tp = dev->si_tty;
963         u_char *cp = 0;
964         int cc = 0;
965         u_char locbuf[BUFSIZ];
966         int cnt = 0;
967         struct pt_ioctl *pti = dev->si_drv1;
968         int error = 0;
969
970         lwkt_gettoken(&tty_token);
971 again:
972         if ((tp->t_state&TS_ISOPEN) == 0)
973                 goto block;
974         if (pti->pt_flags & PF_REMOTE) {
975                 if (tp->t_canq.c_cc)
976                         goto block;
977                 while ((ap->a_uio->uio_resid > 0 || cc > 0) &&
978                        tp->t_canq.c_cc < TTYHOG - 1) {
979                         if (cc == 0) {
980                                 cc = (int)szmin(ap->a_uio->uio_resid, BUFSIZ);
981                                 cc = imin(cc, TTYHOG - 1 - tp->t_canq.c_cc);
982                                 cp = locbuf;
983                                 error = uiomove(cp, (size_t)cc, ap->a_uio);
984                                 if (error) {
985                                         lwkt_reltoken(&tty_token);
986                                         return (error);
987                                 }
988                                 /* check again for safety */
989                                 if ((tp->t_state & TS_ISOPEN) == 0) {
990                                         /* adjust as usual */
991                                         ap->a_uio->uio_resid += cc;
992                                         lwkt_reltoken(&tty_token);
993                                         return (EIO);
994                                 }
995                         }
996                         if (cc > 0) {
997                                 cc = b_to_q((char *)cp, cc, &tp->t_canq);
998                                 /*
999                                  * XXX we don't guarantee that the canq size
1000                                  * is >= TTYHOG, so the above b_to_q() may
1001                                  * leave some bytes uncopied.  However, space
1002                                  * is guaranteed for the null terminator if
1003                                  * we don't fail here since (TTYHOG - 1) is
1004                                  * not a multiple of CBSIZE.
1005                                  */
1006                                 if (cc > 0)
1007                                         break;
1008                         }
1009                 }
1010                 /* adjust for data copied in but not written */
1011                 ap->a_uio->uio_resid += cc;
1012                 clist_putc(0, &tp->t_canq);
1013                 ttwakeup(tp);
1014                 wakeup(TSA_PTS_READ(tp));
1015                 lwkt_reltoken(&tty_token);
1016                 return (0);
1017         }
1018         while (ap->a_uio->uio_resid > 0 || cc > 0) {
1019                 if (cc == 0) {
1020                         cc = (int)szmin(ap->a_uio->uio_resid, BUFSIZ);
1021                         cp = locbuf;
1022                         error = uiomove(cp, (size_t)cc, ap->a_uio);
1023                         if (error) {
1024                                 lwkt_reltoken(&tty_token);
1025                                 return (error);
1026                         }
1027                         /* check again for safety */
1028                         if ((tp->t_state & TS_ISOPEN) == 0) {
1029                                 /* adjust for data copied in but not written */
1030                                 ap->a_uio->uio_resid += cc;
1031                                 lwkt_reltoken(&tty_token);
1032                                 return (EIO);
1033                         }
1034                 }
1035                 while (cc > 0) {
1036                         if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
1037                            (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) {
1038                                 wakeup(TSA_HUP_OR_INPUT(tp));
1039                                 goto block;
1040                         }
1041                         (*linesw[tp->t_line].l_rint)(*cp++, tp);
1042                         cnt++;
1043                         cc--;
1044                 }
1045                 cc = 0;
1046         }
1047         lwkt_reltoken(&tty_token);
1048         return (0);
1049 block:
1050         /*
1051          * Come here to wait for slave to open, for space
1052          * in outq, or space in rawq, or an empty canq.
1053          */
1054         if ((tp->t_state & TS_CONNECTED) == 0) {
1055                 /* adjust for data copied in but not written */
1056                 ap->a_uio->uio_resid += cc;
1057                 lwkt_reltoken(&tty_token);
1058                 return (EIO);
1059         }
1060         if (ap->a_ioflag & IO_NDELAY) {
1061                 /* adjust for data copied in but not written */
1062                 ap->a_uio->uio_resid += cc;
1063                 if (cnt == 0) {
1064                         lwkt_reltoken(&tty_token);
1065                         return (EWOULDBLOCK);
1066                 }
1067                 lwkt_reltoken(&tty_token);
1068                 return (0);
1069         }
1070         error = tsleep(TSA_PTC_WRITE(tp), PCATCH, "ptcout", 0);
1071         if (error) {
1072                 /* adjust for data copied in but not written */
1073                 ap->a_uio->uio_resid += cc;
1074                 lwkt_reltoken(&tty_token);
1075                 return (error);
1076         }
1077         goto again;
1078 }
1079
1080 /*ARGSUSED*/
1081 static  int
1082 ptyioctl(struct dev_ioctl_args *ap)
1083 {
1084         cdev_t dev = ap->a_head.a_dev;
1085         struct tty *tp = dev->si_tty;
1086         struct pt_ioctl *pti = dev->si_drv1;
1087         u_char *cc = tp->t_cc;
1088         int stop, error;
1089
1090         lwkt_gettoken(&tty_token);
1091         if (dev_dflags(dev) & D_MASTER) {
1092                 switch (ap->a_cmd) {
1093
1094                 case TIOCGPGRP:
1095                         /*
1096                          * We avoid calling ttioctl on the controller since,
1097                          * in that case, tp must be the controlling terminal.
1098                          */
1099                         *(int *)ap->a_data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
1100                         lwkt_reltoken(&tty_token);
1101                         return (0);
1102
1103                 case TIOCPKT:
1104                         if (*(int *)ap->a_data) {
1105                                 if (pti->pt_flags & PF_UCNTL) {
1106                                         lwkt_reltoken(&tty_token);
1107                                         return (EINVAL);
1108                                 }
1109                                 pti->pt_flags |= PF_PKT;
1110                         } else {
1111                                 pti->pt_flags &= ~PF_PKT;
1112                         }
1113                         lwkt_reltoken(&tty_token);
1114                         return (0);
1115
1116                 case TIOCUCNTL:
1117                         if (*(int *)ap->a_data) {
1118                                 if (pti->pt_flags & PF_PKT) {
1119                                         lwkt_reltoken(&tty_token);
1120                                         return (EINVAL);
1121                                 }
1122                                 pti->pt_flags |= PF_UCNTL;
1123                         } else {
1124                                 pti->pt_flags &= ~PF_UCNTL;
1125                         }
1126                         lwkt_reltoken(&tty_token);
1127                         return (0);
1128
1129                 case TIOCREMOTE:
1130                         if (*(int *)ap->a_data)
1131                                 pti->pt_flags |= PF_REMOTE;
1132                         else
1133                                 pti->pt_flags &= ~PF_REMOTE;
1134                         ttyflush(tp, FREAD|FWRITE);
1135                         lwkt_reltoken(&tty_token);
1136                         return (0);
1137
1138 #ifdef UNIX98_PTYS
1139                 case TIOCISPTMASTER:
1140                         if ((pti->pt_flags & PF_UNIX98) &&
1141                             (pti->devc == dev)) {
1142                                 lwkt_reltoken(&tty_token);
1143                                 return (0);
1144                         } else {
1145                                 lwkt_reltoken(&tty_token);
1146                                 return (EINVAL);
1147                         }
1148                 }
1149 #endif
1150
1151                 /*
1152                  * The rest of the ioctls shouldn't be called until 
1153                  * the slave is open.
1154                  */
1155                 if ((tp->t_state & TS_ISOPEN) == 0) {
1156                         lwkt_reltoken(&tty_token);
1157                         return (EAGAIN);
1158                 }
1159
1160                 switch (ap->a_cmd) {
1161 #ifdef COMPAT_43
1162                 case TIOCSETP:
1163                 case TIOCSETN:
1164 #endif
1165                 case TIOCSETD:
1166                 case TIOCSETA:
1167                 case TIOCSETAW:
1168                 case TIOCSETAF:
1169                         /*
1170                          * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
1171                          * ttywflush(tp) will hang if there are characters in
1172                          * the outq.
1173                          */
1174                         ndflush(&tp->t_outq, tp->t_outq.c_cc);
1175                         break;
1176
1177                 case TIOCSIG:
1178                         if (*(unsigned int *)ap->a_data >= NSIG ||
1179                             *(unsigned int *)ap->a_data == 0) {
1180                                 lwkt_reltoken(&tty_token);
1181                                 return(EINVAL);
1182                         }
1183                         if ((tp->t_lflag&NOFLSH) == 0)
1184                                 ttyflush(tp, FREAD|FWRITE);
1185                         pgsignal(tp->t_pgrp, *(unsigned int *)ap->a_data, 1);
1186                         if ((*(unsigned int *)ap->a_data == SIGINFO) &&
1187                             ((tp->t_lflag&NOKERNINFO) == 0))
1188                                 ttyinfo(tp);
1189                         lwkt_reltoken(&tty_token);
1190                         return(0);
1191                 }
1192         }
1193         if (ap->a_cmd == TIOCEXT) {
1194                 /*
1195                  * When the EXTPROC bit is being toggled, we need
1196                  * to send an TIOCPKT_IOCTL if the packet driver
1197                  * is turned on.
1198                  */
1199                 if (*(int *)ap->a_data) {
1200                         if (pti->pt_flags & PF_PKT) {
1201                                 pti->pt_send |= TIOCPKT_IOCTL;
1202                                 ptcwakeup(tp, FREAD);
1203                         }
1204                         tp->t_lflag |= EXTPROC;
1205                 } else {
1206                         if ((tp->t_lflag & EXTPROC) &&
1207                             (pti->pt_flags & PF_PKT)) {
1208                                 pti->pt_send |= TIOCPKT_IOCTL;
1209                                 ptcwakeup(tp, FREAD);
1210                         }
1211                         tp->t_lflag &= ~EXTPROC;
1212                 }
1213                 lwkt_reltoken(&tty_token);
1214                 return(0);
1215         }
1216         error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, ap->a_data,
1217                                               ap->a_fflag, ap->a_cred);
1218         if (error == ENOIOCTL)
1219                  error = ttioctl(tp, ap->a_cmd, ap->a_data, ap->a_fflag);
1220         if (error == ENOIOCTL) {
1221                 if (pti->pt_flags & PF_UCNTL &&
1222                     (ap->a_cmd & ~0xff) == UIOCCMD(0)) {
1223                         if (ap->a_cmd & 0xff) {
1224                                 pti->pt_ucntl = (u_char)ap->a_cmd;
1225                                 ptcwakeup(tp, FREAD);
1226                         }
1227                         lwkt_reltoken(&tty_token);
1228                         return (0);
1229                 }
1230                 error = ENOTTY;
1231         }
1232         /*
1233          * If external processing and packet mode send ioctl packet.
1234          */
1235         if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
1236                 switch(ap->a_cmd) {
1237                 case TIOCSETA:
1238                 case TIOCSETAW:
1239                 case TIOCSETAF:
1240 #ifdef COMPAT_43
1241                 case TIOCSETP:
1242                 case TIOCSETN:
1243 #endif
1244 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1245                 case TIOCSETC:
1246                 case TIOCSLTC:
1247                 case TIOCLBIS:
1248                 case TIOCLBIC:
1249                 case TIOCLSET:
1250 #endif
1251                         pti->pt_send |= TIOCPKT_IOCTL;
1252                         ptcwakeup(tp, FREAD);
1253                 default:
1254                         break;
1255                 }
1256         }
1257         stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
1258                 && CCEQ(cc[VSTART], CTRL('q'));
1259         if (pti->pt_flags & PF_NOSTOP) {
1260                 if (stop) {
1261                         pti->pt_send &= ~TIOCPKT_NOSTOP;
1262                         pti->pt_send |= TIOCPKT_DOSTOP;
1263                         pti->pt_flags &= ~PF_NOSTOP;
1264                         ptcwakeup(tp, FREAD);
1265                 }
1266         } else {
1267                 if (!stop) {
1268                         pti->pt_send &= ~TIOCPKT_DOSTOP;
1269                         pti->pt_send |= TIOCPKT_NOSTOP;
1270                         pti->pt_flags |= PF_NOSTOP;
1271                         ptcwakeup(tp, FREAD);
1272                 }
1273         }
1274         lwkt_reltoken(&tty_token);
1275         return (error);
1276 }
1277
1278
1279 static void ptc_drvinit (void *unused);
1280
1281 #ifdef UNIX98_PTYS
1282 SYSCTL_INT(_kern, OID_AUTO, pty_debug, CTLFLAG_RW, &pty_debug_level,
1283                 0, "Change pty debug level");
1284 #endif
1285
1286 static void
1287 ptc_drvinit(void *unused)
1288 {
1289         int i;
1290
1291 #ifdef UNIX98_PTYS
1292         /*
1293          * Unix98 pty stuff.
1294          * Create the clonable base device.
1295          */
1296         make_autoclone_dev(&ptc_ops, &DEVFS_CLONE_BITMAP(pty), ptyclone,
1297             0, 0, 0666, "ptmx");
1298 #endif
1299
1300         for (i = 0; i < 256; i++) {
1301                 ptyinit(i);
1302         }
1303 }
1304
1305 SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)