Diff for /src/sys/kern/tty_cons.c between versions 1.12 and 1.13

version 1.12, 2004/05/13 23:49:23 version 1.13, 2004/05/19 22:52:58
Line 60 Line 60
   
 #include <machine/cpu.h>  #include <machine/cpu.h>
   
static  d_open_t        cnopen;static int cnopen(struct cdevmsg_open *msg);
static  d_close_t        cnclose;static int cnclose(struct cdevmsg_close *msg);
static  d_read_t        cnread;static int cnread(struct cdevmsg_read *msg);
static  d_write_t        cnwrite;static int cnwrite(struct cdevmsg_write *msg);
static  d_ioctl_t        cnioctl;static int cnioctl(struct cdevmsg_ioctl *msg);
static  d_poll_t        cnpoll;static int cnpoll(struct cdevmsg_poll *msg);
static  d_kqfilter_t        cnkqfilter;static int cnkqfilter(struct cdevmsg_kqfilter *msg);
 
 static int console_putport(lwkt_port_t port, lwkt_msg_t lmsg);  static int console_putport(lwkt_port_t port, lwkt_msg_t lmsg);
   static int console_interceptport(lwkt_port_t port, lwkt_msg_t lmsg);
   
   static struct lwkt_port cn_port;        /* console device port */
   static struct lwkt_port cn_iport;       /* intercept port */
   
 #define CDEV_MAJOR      0  #define CDEV_MAJOR      0
 static struct cdevsw cn_cdevsw = {  static struct cdevsw cn_cdevsw = {
         /* name */      "console",          /* name */      "console",
         /* maj */       CDEV_MAJOR,          /* maj */       CDEV_MAJOR,
         /* flags */     D_TTY | D_KQFILTER,          /* flags */     D_TTY | D_KQFILTER,
        /* port */      NULL,        /* port */      &cn_port,
        /* clone */     NULL,        /* clone */     NULL
 
        /* open */      cnopen, 
        /* close */     cnclose, 
        /* read */      cnread, 
        /* write */     cnwrite, 
        /* ioctl */     cnioctl, 
        /* poll */      cnpoll, 
        /* mmap */      nommap, 
        /* strategy */  nostrategy, 
        /* dump */      nodump, 
        /* psize */     nopsize, 
        /* kqfilter */  cnkqfilter 
 };  };
   
static dev_t    cn_dev_t;       /* seems to be never really used */static dev_t    cn_dev_t;
 static udev_t   cn_udev_t;  static udev_t   cn_udev_t;
 SYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLFLAG_RD,  SYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLFLAG_RD,
         &cn_udev_t, sizeof cn_udev_t, "T,dev_t", "");          &cn_udev_t, sizeof cn_udev_t, "T,dev_t", "");
Line 112  static char *console_pausestr= Line 105  static char *console_pausestr=
 "<pause; press any key to proceed to next line or '.' to end pause mode>";  "<pause; press any key to proceed to next line or '.' to end pause mode>";
   
 static lwkt_port_t      cn_fwd_port;  static lwkt_port_t      cn_fwd_port;
 static struct lwkt_port cn_port;  
   
   
 CONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL, NULL);  CONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
 SET_DECLARE(cons_set, struct consdev);  SET_DECLARE(cons_set, struct consdev);
Line 128  cninit() Line 119  cninit()
          */           */
         lwkt_initport(&cn_port, NULL);          lwkt_initport(&cn_port, NULL);
         cn_port.mp_putport = console_putport;          cn_port.mp_putport = console_putport;
           lwkt_initport(&cn_iport, NULL);
           cn_iport.mp_putport = console_interceptport;
   
         /*          /*
          * Find the first console with the highest priority.           * Find the first console with the highest priority.
Line 180  cninit() Line 173  cninit()
         cn_tab = best_cp;          cn_tab = best_cp;
 }  }
   
   /*
    * Hook the open and close functions on the selected device.
    */
 void  void
 cninit_finish()  cninit_finish()
 {  {
Line 187  cninit_finish() Line 183  cninit_finish()
                 return;                  return;
   
         /*          /*
         * Hook the open and close functions.         * Hook the open and close functions.  XXX bad hack.
          */           */
        if (dev_dport(cn_tab->cn_dev))        if (dev_is_good(cn_tab->cn_dev))
                cn_fwd_port = cdevsw_dev_override(cn_tab->cn_dev, &cn_port);                cn_fwd_port = cdevsw_dev_override(cn_tab->cn_dev, &cn_iport);
         cn_dev_t = cn_tab->cn_dev;          cn_dev_t = cn_tab->cn_dev;
         cn_udev_t = dev2udev(cn_dev_t);          cn_udev_t = dev2udev(cn_dev_t);
         console_pausing = 0;          console_pausing = 0;
Line 203  cnuninit(void) Line 199  cnuninit(void)
                 return;                  return;
   
         /*          /*
         * Unhook the open and close functions.         * Unhook the open and close functions.  XXX bad hack
          */           */
        cdevsw_dev_override(cn_tab->cn_dev, NULL);        if (cn_fwd_port)
                 cdevsw_dev_override(cn_tab->cn_dev, cn_fwd_port);
         cn_fwd_port = NULL;          cn_fwd_port = NULL;
         cn_dev_t = NODEV;          cn_dev_t = NODEV;
         cn_udev_t = NOUDEV;          cn_udev_t = NOUDEV;
Line 230  sysctl_kern_consmute(SYSCTL_HANDLER_ARGS Line 227  sysctl_kern_consmute(SYSCTL_HANDLER_ARGS
                          * if the console has been openned                           * if the console has been openned
                          */                           */
                         cninit_finish();                          cninit_finish();
                        if(cn_is_open)                        if (cn_is_open) {
                                 /* XXX curproc is not what we want really */                                  /* XXX curproc is not what we want really */
                                error = cnopen(cn_dev_t, openflag,                                error = dev_dopen(cn_dev_t, openflag,
                                        openmode, curthread);                                                openmode, curthread);
                         }
                         /* if it failed, back it out */                          /* if it failed, back it out */
                         if ( error != 0) cnuninit();                          if ( error != 0) cnuninit();
                 } else if (!ocn_mute && cn_mute) {                  } else if (!ocn_mute && cn_mute) {
Line 241  sysctl_kern_consmute(SYSCTL_HANDLER_ARGS Line 239  sysctl_kern_consmute(SYSCTL_HANDLER_ARGS
                          * going from unmuted to muted.. close the physical dev                            * going from unmuted to muted.. close the physical dev 
                          * if it's only open via /dev/console                           * if it's only open via /dev/console
                          */                           */
                        if(cn_is_open)                        if (cn_is_open) {
                                error = cnclose(cn_dev_t, openflag,                                error = dev_dclose(cn_dev_t, openflag,
                                        openmode, curthread);                                                openmode, curthread);
                        if ( error == 0) cnuninit();                        }
                         if (error == 0)
                                 cnuninit();
                 }                  }
                 if (error != 0) {                  if (error != 0) {
                         /*                           /* 
Line 259  sysctl_kern_consmute(SYSCTL_HANDLER_ARGS Line 259  sysctl_kern_consmute(SYSCTL_HANDLER_ARGS
 SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW,  SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW,
         0, sizeof cn_mute, sysctl_kern_consmute, "I", "");          0, sizeof cn_mute, sysctl_kern_consmute, "I", "");
   
   /*
    * We intercept the OPEN and CLOSE calls on the original device, and
    * forward the rest through.
    */
   static int
   console_interceptport(lwkt_port_t port, lwkt_msg_t lmsg)
   {
           cdevallmsg_t msg = (cdevallmsg_t)lmsg;
           int error;
   
           switch(msg->am_lmsg.ms_cmd.cm_op) {
           case CDEV_CMD_OPEN:
                   error = cnopen(&msg->am_open);
                   break;
           case CDEV_CMD_CLOSE:
                   error = cnclose(&msg->am_close);
                   break;
           default:
                   error = lwkt_forwardmsg(cn_fwd_port, &msg->am_lmsg);
                   break;
           }
           return(error);
   }
   
   /*
    * This is the port handler for /dev/console.  These functions will basically
    * past the request through to the actual physical device representing the
    * console. 
    *
    * Note, however, that cnopen() and cnclose() are also called from the mute
    * code and the intercept code.
    */
 static int  static int
 console_putport(lwkt_port_t port, lwkt_msg_t lmsg)  console_putport(lwkt_port_t port, lwkt_msg_t lmsg)
 {  {
Line 267  console_putport(lwkt_port_t port, lwkt_m Line 299  console_putport(lwkt_port_t port, lwkt_m
   
         switch(msg->am_lmsg.ms_cmd.cm_op) {          switch(msg->am_lmsg.ms_cmd.cm_op) {
         case CDEV_CMD_OPEN:          case CDEV_CMD_OPEN:
                error = cnopen(                error = cnopen(&msg->am_open);
                            msg->am_open.msg.dev, 
                            msg->am_open.oflags, 
                            msg->am_open.devtype, 
                            msg->am_open.td 
                        ); 
                 break;                  break;
         case CDEV_CMD_CLOSE:          case CDEV_CMD_CLOSE:
                error = cnclose(                error = cnclose(&msg->am_close);
                            msg->am_close.msg.dev,                break;
                            msg->am_close.fflag,        case CDEV_CMD_STRATEGY:
                            msg->am_close.devtype,                nostrategy(msg->am_strategy.bp);
                            msg->am_close.td                error = 0;
                        );                break;
         case CDEV_CMD_IOCTL:
                 error = cnioctl(&msg->am_ioctl);
                 break;
         case CDEV_CMD_DUMP:
                 error = nodump(msg->am_dump.msg.dev, 0, 0, 0);
                 break;
         case CDEV_CMD_PSIZE:
                 error = nopsize(msg->am_psize.msg.dev);
                 break;
         case CDEV_CMD_READ:
                 error = cnread(&msg->am_read);
                 break;
         case CDEV_CMD_WRITE:
                 error = cnwrite(&msg->am_write);
                 break;
         case CDEV_CMD_POLL:
                 error = cnpoll(&msg->am_poll);
                 break;
         case CDEV_CMD_KQFILTER:
                 error = cnkqfilter(&msg->am_kqfilter);
                 break;
         case CDEV_CMD_MMAP:
                 error = nommap(msg->am_mmap.msg.dev,
                                 msg->am_mmap.offset,
                                 msg->am_mmap.nprot);
                 break;                  break;
         default:          default:
                 error = lwkt_forwardmsg(cn_fwd_port, &msg->am_lmsg);                error = ENODEV;
                 break;                break;
         }          }
         return(error);          return(error);
 }  }
   
   /*
    * cnopen() is called as a port intercept function (dev will be that of the
    * actual physical device representing our console), and also called from
    * the muting code and from the /dev/console switch (dev will have the
    * console's cdevsw).
    */
 static int  static int
cnopen(dev, flag, mode, td)cnopen(struct cdevmsg_open *msg)
        dev_t dev; 
        int flag, mode; 
        struct thread *td; 
 {  {
           dev_t dev = msg->msg.dev;
           int flag = msg->oflags;
           int mode = msg->devtype;
         dev_t cndev, physdev;          dev_t cndev, physdev;
         int retval = 0;          int retval = 0;
   
Line 302  cnopen(dev, flag, mode, td) Line 360  cnopen(dev, flag, mode, td)
                 return (0);                  return (0);
         cndev = cn_tab->cn_dev;          cndev = cn_tab->cn_dev;
         physdev = (major(dev) == major(cndev) ? dev : cndev);          physdev = (major(dev) == major(cndev) ? dev : cndev);
   
         /*          /*
          * If mute is active, then non console opens don't get here           * If mute is active, then non console opens don't get here
         * so we don't need to check for that. They          * so we don't need to check for that. They bypass this and go
         * bypass this and go straight to the device.         * straight to the device.
          *
          * XXX at the moment we assume that the port forwarding function
          * is synchronous for open.
          */           */
        if(!cn_mute)        if (!cn_mute) {
                retval = dev_port_dopen(cn_fwd_port, physdev, flag, mode, td);                msg->msg.dev = physdev;
                 retval = lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg);
         }
         if (retval == 0) {          if (retval == 0) {
                 /*                   /* 
                  * check if we openned it via /dev/console or                    * check if we openned it via /dev/console or 
Line 326  cnopen(dev, flag, mode, td) Line 390  cnopen(dev, flag, mode, td)
         return (retval);          return (retval);
 }  }
   
   /*
    * cnclose() is called as a port intercept function (dev will be that of the
    * actual physical device representing our console), and also called from
    * the muting code and from the /dev/console switch (dev will have the
    * console's cdevsw).
    */
 static int  static int
cnclose(dev, flag, mode, td)cnclose(struct cdevmsg_close *msg)
        dev_t dev; 
        int flag, mode; 
        struct thread *td; 
 {  {
           dev_t dev = msg->msg.dev;
         dev_t cndev;          dev_t cndev;
         struct tty *cn_tp;          struct tty *cn_tp;
   
Line 364  cnclose(dev, flag, mode, td) Line 432  cnclose(dev, flag, mode, td)
                         return (0);                          return (0);
                 dev = cndev;                  dev = cndev;
         }          }
        if (cn_fwd_port)        if (cn_fwd_port) {
                return (dev_port_dclose(cn_fwd_port, dev, flag, mode, td));                msg->msg.dev = dev;
                 return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg));
         }
         return (0);          return (0);
 }  }
   
   /*
    * The following functions are dispatched solely from the /dev/console
    * port switch.  Their job is primarily to forward the request through.
    * If the console is not attached to anything then write()'s are sunk
    * to null and reads return 0 (mostly).
    */
 static int  static int
cnread(dev, uio, flag)cnread(struct cdevmsg_read *msg)
        dev_t dev; 
        struct uio *uio; 
        int flag; 
 {  {
   
         if (cn_tab == NULL || cn_fwd_port == NULL)          if (cn_tab == NULL || cn_fwd_port == NULL)
                 return (0);                  return (0);
        dev = cn_tab->cn_dev;        msg->msg.dev = cn_tab->cn_dev;
        return (dev_port_dread(cn_fwd_port, dev, uio, flag));        return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg));
 }  }
   
 static int  static int
cnwrite(dev, uio, flag)cnwrite(struct cdevmsg_write *msg)
        dev_t dev; 
        struct uio *uio; 
        int flag; 
 {  {
           struct uio *uio = msg->uio;
           dev_t dev;
   
         if (cn_tab == NULL || cn_fwd_port == NULL) {          if (cn_tab == NULL || cn_fwd_port == NULL) {
                 uio->uio_resid = 0; /* dump the data */                  uio->uio_resid = 0; /* dump the data */
Line 398  cnwrite(dev, uio, flag) Line 469  cnwrite(dev, uio, flag)
         else          else
                 dev = cn_tab->cn_dev;                  dev = cn_tab->cn_dev;
         log_console(uio);          log_console(uio);
        return (dev_port_dwrite(cn_fwd_port, dev, uio, flag));        msg->msg.dev = dev;
         return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg));
 }  }
   
 static int  static int
cnioctl(dev, cmd, data, flag, td)cnioctl(struct cdevmsg_ioctl *msg)
        dev_t dev; 
        u_long cmd; 
        caddr_t data; 
        int flag; 
        struct thread *td; 
 {  {
           u_long cmd = msg->cmd;
         int error;          int error;
   
         if (cn_tab == NULL || cn_fwd_port == NULL)          if (cn_tab == NULL || cn_fwd_port == NULL)
                 return (0);                  return (0);
        KKASSERT(td->td_proc != NULL);        KKASSERT(msg->td->td_proc != NULL);
         /*          /*
          * Superuser can always use this to wrest control of console           * Superuser can always use this to wrest control of console
          * output from the "virtual" console.           * output from the "virtual" console.
          */           */
         if (cmd == TIOCCONS && constty) {          if (cmd == TIOCCONS && constty) {
                error = suser(td);                error = suser(msg->td);
                 if (error)                  if (error)
                         return (error);                          return (error);
                 constty = NULL;                  constty = NULL;
                 return (0);                  return (0);
         }          }
        dev = cn_tab->cn_dev;        msg->msg.dev = cn_tab->cn_dev;
        return (dev_port_dioctl(cn_fwd_port, dev, cmd, data, flag, td));        return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg));
 }  }
   
 static int  static int
cnpoll(dev, events, td)cnpoll(struct cdevmsg_poll *msg)
        dev_t dev; 
        int events; 
        struct thread *td; 
 {  {
         if ((cn_tab == NULL) || cn_mute || cn_fwd_port == NULL)          if ((cn_tab == NULL) || cn_mute || cn_fwd_port == NULL)
                 return (1);                  return (1);
        msg->msg.dev = cn_tab->cn_dev;
        dev = cn_tab->cn_dev;        return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg));
 
        return (dev_port_dpoll(cn_fwd_port, dev, events, td)); 
 }  }
   
 static int  static int
cnkqfilter(dev, kn)cnkqfilter(struct cdevmsg_kqfilter *msg)
        dev_t dev; 
        struct knote *kn; 
 {  {
         if ((cn_tab == NULL) || cn_mute || cn_fwd_port == NULL)          if ((cn_tab == NULL) || cn_mute || cn_fwd_port == NULL)
                 return (1);                  return (1);
        msg->msg.dev = cn_tab->cn_dev;
        dev = cn_tab->cn_dev;        return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg));
        return (dev_port_dkqfilter(cn_fwd_port, dev, kn)); 
 }  }
   
   /*
    * These synchronous functions are primarily used the kernel needs to 
    * access the keyboard (e.g. when running the debugger), or output data
    * directly to the console.
    */
 int  int
cngetc()cngetc(void)
 {  {
         int c;          int c;
         if ((cn_tab == NULL) || cn_mute)          if ((cn_tab == NULL) || cn_mute)
Line 467  cngetc() Line 532  cngetc()
 }  }
   
 int  int
cncheckc()cncheckc(void)
 {  {
         if ((cn_tab == NULL) || cn_mute)          if ((cn_tab == NULL) || cn_mute)
                 return (-1);                  return (-1);
Line 475  cncheckc() Line 540  cncheckc()
 }  }
   
 void  void
cnputc(c)cnputc(int c)
        int c; 
 {  {
         char *cp;          char *cp;
   
Line 504  cnputc(c) Line 568  cnputc(c)
 }  }
   
 void  void
cndbctl(on)cndbctl(int on)
        int on; 
 {  {
         static int refcount;          static int refcount;
   
Line 522  cndbctl(on) Line 585  cndbctl(on)
 static void  static void
 cn_drvinit(void *unused)  cn_drvinit(void *unused)
 {  {
        cdevsw_add(&cn_cdevsw, 0, 0);
        cn_devfsdev = make_dev(&cn_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,        cn_devfsdev = make_dev(&cn_cdevsw, 0, UID_ROOT, GID_WHEEL,
            "console");                                0600, "console");
 }  }
   
 SYSINIT(cndev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cn_drvinit,NULL)  SYSINIT(cndev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cn_drvinit,NULL)

Removed from v.1.12  
changed lines
  Added in v.1.13