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