The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/sqtsec/co.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1991 Carnegie Mellon University
    4  * Copyright (c) 1991 Sequent Computer Systems
    5  * All Rights Reserved.
    6  * 
    7  * Permission to use, copy, modify and distribute this software and its
    8  * documentation is hereby granted, provided that both the copyright
    9  * notice and this permission notice appear in all copies of the
   10  * software, derivative works or modified versions, and any portions
   11  * thereof, and that both notices appear in supporting documentation.
   12  * 
   13  * CARNEGIE MELLON AND SEQUENT COMPUTER SYSTEMS ALLOW FREE USE OF
   14  * THIS SOFTWARE IN ITS "AS IS" CONDITION.  CARNEGIE MELLON AND
   15  * SEQUENT COMPUTER SYSTEMS DISCLAIM ANY LIABILITY OF ANY KIND FOR
   16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  * 
   18  * Carnegie Mellon requests users of this software to return to
   19  * 
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  * 
   25  * any improvements or extensions that they make and grant Carnegie Mellon 
   26  * the rights to redistribute these changes.
   27  */
   28 
   29 /*
   30  * HISTORY
   31  * $Log:        co.c,v $
   32  * Revision 2.3  91/07/31  18:06:19  dbg
   33  *      Changed copyright.
   34  *      [91/07/31            dbg]
   35  * 
   36  * Revision 2.2  91/05/08  13:04:47  dbg
   37  *      Added cn routines for kernel debugger input.
   38  *      [90/11/16            dbg]
   39  * 
   40  *      Adapted for pure kernel.
   41  *      [90/09/24            dbg]
   42  * 
   43  */
   44 
   45 #ifndef lint
   46 static char rcsid[]= "$Header: co.c,v 2.3 91/07/31 18:06:19 dbg Exp $";
   47 #endif
   48 
   49 /*
   50  * SCSI/Ether console driver
   51  *
   52  * There are two consoles per SEC card.  The SEC attached to the
   53  * front panel is distinguished.  The port selected as console on this
   54  * sec can be accessed through minor device 64 (0x40).  All ports can
   55  * be accessed through minor device numbers 0 through 2*n, for n sec
   56  * boards.  The minor device number 64 is an alias for one of these
   57  * devices.
   58  */
   59 
   60 /* 
   61  * Revision 1.3  89/08/03  12:30:02  kak
   62  * balance -> sqt
   63  * 
   64  * Revision 1.2  89/07/25  11:20:56  kak
   65  * fixed p_sema_v_lock define
   66  * 
   67  * Revision 1.1  89/07/05  13:20:12  kak
   68  * Initial revision
   69  * 
   70  */
   71 
   72 #ifdef  MACH_KERNEL
   73 #include <mach_kdb.h>
   74 
   75 #include <kern/time_out.h>
   76 
   77 #include <device/conf.h>
   78 #include <device/tty.h>
   79 #include <device/errno.h>
   80 #include <device/io_req.h>
   81 
   82 #include <sqt/vm_defs.h>
   83 #include <sqt/cfg.h>
   84 
   85 #include <sqt/ioconf.h>
   86 #include <sqt/intctl.h>
   87 #include <sqt/mutex.h>
   88 
   89 #include <sqtsec/sec.h>
   90 #include <sqtsec/co.h>
   91 
   92 #else   /* MACH_KERNEL */
   93 #include "sys/param.h"
   94 #include "sys/user.h"
   95 #include "sys/conf.h"
   96 #include "sys/ioctl.h"
   97 #include "sys/tty.h"
   98 #include "sys/systm.h"
   99 #include "sys/clist.h"
  100 #include "sys/file.h"
  101 #include "sys/uio.h"
  102 #include "sys/proc.h"
  103 
  104 #include "sqt/cfg.h"
  105 
  106 #include "sqt/ioconf.h"
  107 #include "sqt/intctl.h"
  108 #include "sqt/mutex.h"
  109 
  110 #include "sqtsec/sec.h"
  111 #include "sqtsec/co.h"
  112 
  113 #endif  /* MACH_KERNEL */
  114 
  115 #ifdef  DEBUG
  116 int     co_debug = 0;
  117 #endif  DEBUG
  118 
  119 #ifdef  MACH_KERNEL
  120 /*
  121  * Pure kernel really does locks
  122  */
  123 #define CO_TTYLOCK(tp)          p_lock(&(tp)->t_lock, SPLTTY)
  124 #define CO_TTYUNLOCK(tp,spl)    v_lock(&(tp)->t_lock, (spl))
  125 
  126 /*
  127  * But no gates on i386
  128  */
  129 #define ttyinit(tty_p, gate)
  130 
  131 #else   /* MACH_KERNEL */
  132 #ifndef MACH
  133 
  134 /*
  135  * Dynix really does locks/etc.
  136  */
  137 
  138 #define CO_TTYLOCK(tp)          p_lock(&(tp)->t_ttylock, SPLTTY)
  139 #define CO_TTYUNLOCK(tp,spl)    v_lock(&(tp)->t_ttylock, (spl))
  140 
  141 #else   MACH
  142 
  143 /*
  144  * For now, MACH calls all driver code on master_cpu.  Also, no sema_t
  145  * and lock_t with full semantics (eg, force_v_sema(), etc).  Thus,
  146  * define the primitives so the driver can work.
  147  *
  148  * Since all code runs on master_cpu, it is sufficient for the driver
  149  * that all semaphore activity is treated as "sleep/wakeup",
  150  * and "p_lock" is just an spl().
  151  */
  152 
  153 #define CO_TTYLOCK(tp)          spltty()
  154 #define CO_TTYUNLOCK(tp,spl)    splx(spl)
  155 
  156 #define t_rawqwait      t_rawq
  157 #define t_outqwait      t_outq
  158 
  159 #define ttyinit(tty_p, gate)
  160 
  161 #define p_sema_v_lock(sema_p, pri, lock_p, spl) \
  162         sleep((caddr_t) (sema_p), pri)
  163 
  164 #define vall_sema(sema_p)       wakeup((caddr_t) (sema_p))
  165 
  166 #endif  MACH
  167 #endif  /* MACH_KERNEL */
  168 
  169 #define CO_FLAG 0x40
  170 
  171 int coprobe(), coboot(), cointr();
  172 
  173 struct sec_driver co_driver={
  174 /*      name    base    flags           probe           boot    intr    */
  175         "co",   3,      SED_TYPICAL,    coprobe,        coboot, cointr
  176 };
  177 
  178 int     co_max_unit = -1;
  179 u_char  co_base_vec;
  180 struct  co_state *co_state;
  181 struct  co_state *co_costate;
  182 
  183 extern int coflags;
  184 extern char cospeed;
  185 struct sec_dev_prog * CO_GET_Q_TAIL();
  186 struct sec_dev_prog * CO_GET_Q_HEAD();
  187 
  188 
  189 /*
  190  * coprobe - probe a SCSI/Ether for a console device.
  191  *
  192  * Look at the flags returned by the powerup firmware.
  193  */
  194 
  195 coprobe(probe)
  196         struct sec_probe *probe;
  197 {
  198         int failure_flag;
  199 
  200         switch(probe->secp_chan) {
  201         case SDEV_CONSOLE0IN:
  202         case SDEV_CONSOLE0OUT:
  203                 failure_flag = CFG_PORT0;
  204                 break;
  205         case SDEV_CONSOLE1IN:
  206         case SDEV_CONSOLE1OUT:
  207                 failure_flag = CFG_PORT1;
  208                 break;
  209         }
  210 
  211         if(probe->secp_desc->sec_diag_flags & failure_flag) {
  212 #ifdef  DEBUG
  213                 if(co_debug) printf("P-");
  214 #endif  DEBUG
  215                 return(0);
  216         }
  217 #ifdef  DEBUG
  218         if(co_debug) printf("P+");
  219 #endif  DEBUG
  220         return(1);
  221 }
  222 
  223 /*
  224  * coboot - allocate data structures, etc at beginning of time.
  225  *
  226  * Called by autoconfig with an array of configured devices and their
  227  * number.  We allocate the necessary soft descriptions and fill them
  228  * with the various fields from the devs[] array.  Due to the dual 
  229  * device-channel nature of SEC devices, each devs[] entry describes
  230  * input side or output side of a console device.
  231  */
  232 
  233 coboot(ndevs, devs)
  234         struct sec_dev *devs;
  235 {
  236         register int i;
  237 
  238         /* 
  239          * find out the maximum potential unit number, and
  240          * allocate array of soft states.
  241          */
  242 
  243         for (i = 0; i < ndevs; ++i) {
  244                 if (co_max_unit < 2*devs[i].sd_sec_idx + 1)
  245                         co_max_unit = 2*devs[i].sd_sec_idx + 1;
  246         }
  247 
  248         co_state = (struct co_state *)calloc((co_max_unit + 1) *
  249                         sizeof(struct co_state));
  250         
  251         co_base_vec = devs[0].sd_vector;
  252 
  253 
  254         /*
  255          * now boot each configured device.
  256          */
  257 
  258         for (i = 0; i < ndevs; ++i) {
  259                 register struct sec_dev *devp;
  260                 register int unit;
  261 
  262                 devp = &devs[i];
  263                 if (devp->sd_alive == 0)
  264                         continue;
  265 
  266                 unit = i/2;
  267 
  268                 if (unit >= co_bin_config_count) {
  269                         printf("%s%d: console device not binary configured.\n",
  270                                 co_driver.sed_name, unit);
  271                         continue;
  272                 }
  273 
  274                 co_boot_one(&co_state[unit], devp, &co_bin_config[unit]);
  275         }
  276 #ifdef  MACH_KERNEL
  277         /*
  278          * Fix the console indirection
  279          */
  280         if (co_costate) /* had better be non-zero */
  281             dev_change_indirect("console", "co", co_costate - co_state);
  282 
  283 #endif  MACH_KERNEL
  284 }
  285 
  286 /*
  287  * co_boot_one - combine binary config, autoconfig information into
  288  *               softstate, for convenient access.
  289  *
  290  * Allocate device program, etc.  The device program queues were allocated
  291  * by autoconfig.
  292  *
  293  * status pointers for cibs point to data in the soft state.
  294  *
  295  * No locking needs to be done here, as we are still running config
  296  * code single processor.
  297  */
  298 
  299 co_boot_one(softp, sd, bc)
  300         register struct co_state *softp;
  301         register struct sec_dev *sd;
  302         register struct co_bin_config *bc;
  303 {
  304         struct sec_cib *pu_cib;
  305 
  306 #ifdef DEBUG
  307         if (co_debug > 2)
  308                 printf("B%d.\n", sd->sd_unit);
  309 #endif DEBUG
  310 
  311         if (!softp->ss_initted) {
  312 
  313                 ttyinit(&softp->ss_tty, bc->cobc_gate);
  314                 softp->ss_alive = 1;
  315                 softp->ss_initted = 1;
  316                 if (sd->sd_desc->sec_is_cons) {
  317                         switch(sd->sd_desc->sec_is_cons) {
  318 
  319                         case CDSC_LOCAL:
  320 #if DEBUG
  321                                 printf("local console\n");
  322 #endif DEBUG
  323                                 if (sd->sd_chan == SDEV_CONSOLE0IN ||
  324                                         sd->sd_chan == SDEV_CONSOLE0OUT)
  325                                         co_costate = softp;
  326                                 break;
  327 
  328                         case CDSC_REMOTE:
  329 #if DEBUG
  330                                 printf("remote console\n");
  331 #endif DEBUG
  332                                 if (sd->sd_chan == SDEV_CONSOLE1IN ||
  333                                         sd->sd_chan == SDEV_CONSOLE1OUT)
  334                                         co_costate = softp;
  335                                 break;
  336 
  337                         default:
  338                                 panic("console: invalid device as console \n");
  339                                 break;
  340                         }
  341                 }
  342 
  343         }
  344 
  345         if (sd->sd_chan == SDEV_CONSOLE0IN || sd->sd_chan == SDEV_CONSOLE1IN) {
  346                 assert(!softp->is_initted);
  347 
  348                 softp->is_sd = sd;
  349                 softp->is_ovc = 0;
  350                 softp->is_parc = 0;
  351 
  352                 softp->is_reqq.sq_size = sd->sd_req_size;
  353                 softp->is_reqq.sq_progq = sd->sd_requestq;
  354 
  355                 softp->is_doneq.sq_size = sd->sd_doneq_size;
  356                 softp->is_doneq.sq_progq = sd->sd_doneq;
  357 
  358                 SEC_fill_progq(softp->is_reqq.sq_progq,
  359                                (int)softp->is_reqq.sq_size,
  360                                (int)sizeof(struct sec_dev_prog));
  361 
  362                 softp->is_initted = 1;
  363 
  364         } else 
  365         if (sd->sd_chan==SDEV_CONSOLE0OUT || sd->sd_chan==SDEV_CONSOLE1OUT) {
  366                 assert(!softp->os_initted);
  367                 softp->os_sd = sd;
  368 
  369                 softp->os_reqq.sq_size = sd->sd_req_size;
  370                 softp->os_reqq.sq_progq = sd->sd_requestq;
  371 
  372                 softp->os_doneq.sq_size = sd->sd_doneq_size;
  373                 softp->os_doneq.sq_progq = sd->sd_doneq;
  374 
  375                 SEC_fill_progq(softp->os_reqq.sq_progq,
  376                                 (int)softp->os_reqq.sq_size,
  377                                 (int)sizeof(struct sec_dev_prog));
  378 
  379                 softp->os_busy_flag = 0;
  380                 init_sema(&softp->os_busy_wait, 0, 0, bc->cobc_gate);
  381 
  382                 pu_cib = &softp->os_sd->sd_desc->sec_powerup->pu_cib;
  383 #ifdef  DEBUG
  384                 if (co_debug > 1){
  385                         printf("coboot doing getmode\n");
  386                 }
  387 #endif  DEBUG
  388                 SEC_startio(SINST_GETMODE, &softp->os_smode.sm_status, 
  389                         sd->sd_bin,
  390                         sd->sd_chan,
  391                         pu_cib,
  392                         sd->sd_desc->sec_slicaddr);
  393                 if (softp->os_smode.sm_status & (~SINST_INSDONE))
  394                         printf("co: bad get_mode: %x\n", softp->os_smode.sm_status);
  395 #ifdef  DEBUG
  396                 if (co_debug > 1)
  397                         printf("coboot getmode done flags %x, baud %x\n",
  398                         softp->os_smode.CM_FLAGS, softp->os_smode.CM_BAUD);
  399 #endif  DEBUG
  400 
  401                 softp->os_smode.CM_FLAGS &= ~(SCONS_DZMODE );
  402  
  403 #ifdef  DEBUG
  404                 if (co_debug > 1)
  405                         printf("coboot doing setmode\n");
  406 #endif  DEBUG
  407                 SEC_startio(SINST_SETMODE, &softp->os_smode.sm_status, 
  408                         sd->sd_bin,
  409                         sd->sd_chan,
  410                         pu_cib,
  411                         sd->sd_desc->sec_slicaddr);
  412                 if (softp->os_smode.sm_status & (~SINST_INSDONE))
  413                 printf("co: bad set_mode: %x\n", softp->os_smode.sm_status);
  414 #ifdef  DEBUG
  415                 if (co_debug > 1)
  416                         printf("coboot setmode done flags %x, baud %x\n",
  417                         softp->os_smode.CM_FLAGS, softp->os_smode.CM_BAUD);
  418 #endif  DEBUG
  419 
  420                 softp->os_initted = 1;
  421 
  422         } else {
  423                 printf("%s %d: invalid device chan %d(0x%x) in boot routine\n",
  424                         co_driver.sed_name, sd->sd_sec_idx,
  425                         sd->sd_chan, sd->sd_chan);
  426         }
  427 }
  428 
  429 int costart();
  430 #ifdef  MACH_KERNEL
  431 int costop();
  432 int cogetstat();
  433 int cosetstat();
  434 #endif  /* MACH_KERNEL */
  435 
  436 /*ARGSUSED*/
  437 #ifdef  MACH_KERNEL
  438 coopen(dev, flag, ior)
  439         register dev_t  dev;
  440         int             flag;
  441         io_req_t        ior;
  442 #else   /* MACH_KERNEL */
  443 coopen(dev, flag)
  444         register dev_t  dev;
  445                  int    flag;
  446 #endif  /* MACH_KERNEL */
  447 {
  448         register struct tty *tp;
  449         register struct co_state *softp;
  450         register unit;
  451         spl_t   tplock;
  452         int     retval;
  453 
  454 #ifdef DEBUG
  455         if(co_debug)
  456                 printf("O");
  457 #endif DEBUG
  458         /*
  459          * Check for errors
  460          */
  461 
  462         unit = minor(dev);
  463         if (unit & CO_FLAG)
  464                 softp = co_costate;
  465         else {
  466                 softp = &co_state[unit];
  467                 if(unit > co_max_unit || softp->ss_alive == 0)
  468                         return(ENXIO);
  469         }
  470 
  471         /*
  472          * Lock the device and initialize the channel
  473          */
  474         
  475         tp = &softp->ss_tty;
  476         tplock = CO_TTYLOCK(tp);
  477 
  478 #ifdef  MACH_KERNEL
  479         /* done at higher level */
  480 #else   /* MACH_KERNEL */
  481         tp->t_nopen++;
  482         while(tp->t_state&TS_LCLOSE) {          /* In process close so hang! */
  483                 tp->t_state |= TS_WOPEN;
  484                 p_sema_v_lock(&tp->t_rawqwait, TTIPRI, &tp->t_ttylock, tplock);
  485                 tplock = CO_TTYLOCK(tp);
  486         }
  487 #endif  /* MACH_KERNEL */
  488 
  489         if((tp->t_state & TS_ISOPEN) == 0) {
  490                 tp->t_oproc = costart;
  491 #ifdef  MACH_KERNEL
  492                 tp->t_stop = costop;
  493                 tp->t_setstat = cosetstat;
  494                 tp->t_getstat = cogetstat;
  495 #endif  /* MACH_KERNEL */
  496                 tp->t_addr = (caddr_t)softp;
  497                 if(tp->t_ispeed == 0) {
  498                         if (softp == co_costate)
  499                                 tp->t_ospeed = tp->t_ispeed = 
  500                                                 softp->os_smode.CM_BAUD;
  501                         else
  502                                 tp->t_ospeed = tp->t_ispeed = cospeed;
  503                         tp->t_flags = coflags;
  504                 }
  505                 ttychars(tp);                   /* setup default signal chars */
  506                 /*
  507                  * over ride some of those defaults with those from
  508                  * the cfg structure.  Only for /dev/console
  509                  */
  510 #ifdef  MACH_KERNEL
  511 #else   /* MACH_KERNEL */
  512                 if (softp == co_costate) {
  513                         tp->t_erase = CD_LOC->c_erase;
  514                         tp->t_kill = CD_LOC->c_kill;
  515                         tp->t_intrc = CD_LOC->c_interrupt;
  516                 }
  517 #endif  /* MACH_KERNEL */
  518 
  519                 co_param(softp);        /* setup default baud rate */
  520 
  521                 co_abort_read(softp);
  522                 softp->is_restart_read = 1;
  523                 co_start_read(softp);
  524         }else{
  525 #ifdef  MACH_KERNEL
  526 #else   /* MACH_KERNEL */
  527                 /*
  528                  * Someone has an exclusive open on the device.
  529                  * Return error EBUSY
  530                  */
  531                 if((tp->t_state & TS_XCLUDE) && u.u_uid != 0) {
  532                         tp->t_nopen--;
  533                         CO_TTYUNLOCK(tp, tplock);
  534                         return(EBUSY);
  535                 }
  536 #endif  /* MACH_KERNEL */
  537         }
  538 
  539 
  540         /*
  541          * Set up modem status.
  542          */
  543         softp->os_smode.CM_FLAGS &= ~(  SCONS_CLEAR_RTS |
  544                                                 SCONS_CLEAR_DTR |
  545                                                 SCONS_IGN_CARRIER);
  546         co_wset_modes(softp);
  547 
  548         /*
  549          * Block waiting for carrier.
  550          */
  551         co_get_modes(softp);
  552         if ((softp->os_smode.CM_FLAGS & SCONS_CARRIER_CLEAR)==0)
  553                 tp->t_state |= TS_CARR_ON;
  554 #ifdef  MACH_KERNEL
  555         CO_TTYUNLOCK(tp, tplock);
  556         return (char_open(dev, tp, flag, ior));
  557 #else   /* MACH_KERNEL */
  558         while((tp->t_state&TS_CARR_ON) == 0) {
  559                 tp->t_state |= TS_WOPEN;
  560 #ifdef  DEBUG
  561                 if (co_debug > 1)
  562                         printf("coopen: waiting for carrier\n");
  563 #endif  DEBUG
  564                 p_sema_v_lock(&tp->t_rawqwait, PZERO+1, &tp->t_ttylock, tplock);
  565                 tplock = CO_TTYLOCK(tp);
  566         }
  567 #ifdef  DEBUG
  568         if (co_debug > 1)
  569                 printf("coopen: got carrier\n");
  570 #endif  DEBUG
  571         
  572         retval = (*(linesw[tp->t_line].l_open))(dev, tp);
  573 #ifdef  DEBUG
  574         if (co_debug > 1)
  575                 printf("coopen: open finished\n");
  576 #endif  DEBUG
  577         CO_TTYUNLOCK(tp, tplock);
  578         return(retval);
  579 #endif  /* MACH_KERNEL */
  580 }
  581 
  582 /*
  583  * To "close" an CO channel, we need to kill off the read that is
  584  * pending all the time.  If the TS_HUPCLS flag is set,
  585  * the RTS and DTR lines are turned off after all of the output queues are
  586  * flushed. Note: ttyclose makes tp->t_state = 0;
  587  *
  588  * NOTE: The driver will get called on every close and must keep track
  589  *       of when last close happens to know when to call linesw close.
  590  */
  591 /*ARGSUSED*/
  592 coclose(dev, flag)
  593         dev_t dev;
  594         int flag;
  595 {
  596         register struct tty *tp;
  597         register struct co_state *softp;
  598         register unit;
  599         spl_t   tplock;
  600 
  601 #ifdef DEBUG
  602         if(co_debug>2)
  603                 printf("co_close dev=%x\n", dev);
  604         else if(co_debug)
  605                 printf("C");
  606 #endif DEBUG
  607         unit = minor(dev);
  608         if (unit & CO_FLAG) 
  609                 softp = co_costate;
  610         else {
  611                 softp = &co_state[unit];
  612                 assert(unit <= co_max_unit);
  613                 assert(softp->ss_alive == 1);
  614         }
  615 
  616         tp = &softp->ss_tty;
  617         tplock = CO_TTYLOCK(tp);
  618 #ifdef  MACH_KERNEL
  619 #else   /* MACH_KERNEL */
  620         if(--tp->t_nopen > 0 || (tp->t_state&TS_LCLOSE)) {
  621                 CO_TTYUNLOCK(tp, tplock);
  622                 return;
  623         }
  624         assert(tp->t_nopen>=0);
  625         tp->t_state |= TS_LCLOSE;
  626         (*linesw[tp->t_line].l_close)(tp);
  627 #endif  /* MACH_KERNEL */
  628         if((tp->t_state & TS_ISOPEN) == 0 || (tp->t_state&TS_HUPCLS)) {
  629                 /*
  630                  * Turn h/w off on hupcls on last close (new line disc).
  631                  * Assumes all output flushed before here.
  632                  */
  633                 softp->os_smode.CM_FLAGS |= (SCONS_CLEAR_DTR | 
  634                                                 SCONS_CLEAR_RTS );
  635                                                 
  636                 softp->os_smode.CM_FLAGS &= ~(SCONS_SET_BREAK);
  637                 co_wset_modes(softp);
  638         }
  639         softp->is_restart_read = 0;
  640         co_abort_read(softp);
  641         ttyclose(tp);
  642         CO_TTYUNLOCK(tp, tplock);
  643 }
  644 
  645 #ifdef  MACH_KERNEL
  646 coportdeath(dev, port)
  647         dev_t dev;
  648         mach_port_t port;
  649 {
  650         register struct co_state *softp;
  651         register int    unit;
  652 
  653         unit = minor(dev);
  654         if (unit & CO_FLAG)
  655                 softp = co_costate;
  656         else {
  657                 softp = &co_state[unit];
  658                 assert(unit <= co_max_unit);
  659                 assert(softp->ss_alive==1);
  660         }
  661 
  662         return (tty_portdeath(&softp->ss_tty, port));
  663 }
  664 
  665 /*
  666  * Standard read and write.
  667  *
  668  * Mutual exclusion: called procedures lock tp themselves.
  669  */
  670 coread(dev, ior)
  671         dev_t dev;
  672         io_req_t ior;
  673 {
  674         register struct co_state *softp;
  675         register int    unit;
  676 
  677         unit = minor(dev);
  678         if (unit & CO_FLAG)
  679                 softp = co_costate;
  680         else {
  681                 softp = &co_state[unit];
  682                 assert(unit <= co_max_unit);
  683                 assert(softp->ss_alive==1);
  684         }
  685 
  686         return (char_read(&softp->ss_tty, ior));
  687 }
  688 
  689 cowrite(dev, ior)
  690         dev_t dev;
  691         io_req_t ior;
  692 {
  693         register struct co_state *softp;
  694         register int    unit;
  695 
  696         unit = minor(dev);
  697         if (unit & CO_FLAG)
  698                 softp = co_costate;
  699         else {
  700                 softp = &co_state[unit];
  701                 assert(unit <= co_max_unit);
  702                 assert(softp->ss_alive==1);
  703         }
  704 
  705         return (char_write(&softp->ss_tty, ior));
  706 }
  707 #else   /* MACH_KERNEL */
  708 /*
  709  * Standard read.
  710  *
  711  * Mutual exclusion: called procedures assume locked tp.
  712  */
  713 coread(dev, uio)
  714         register dev_t dev;
  715         register struct uio *uio;
  716 {       
  717         register struct co_state *softp;
  718         register struct tty *tp;
  719         register int retval;
  720         int unit;
  721         spl_t   tplock;
  722 
  723 #ifdef DEBUG
  724         if(co_debug)
  725                 printf("r");
  726 #endif DEBUG
  727         unit = minor(dev);
  728         if (unit & CO_FLAG)
  729                 softp = co_costate;
  730         else {
  731                 softp = &co_state[unit];
  732                 assert(unit <= co_max_unit);
  733                 assert(softp->ss_alive==1);
  734         }
  735 
  736 
  737         
  738         tp = &softp->ss_tty;
  739         tplock = CO_TTYLOCK(tp);
  740         retval = ((*(linesw[tp->t_line].l_read))(tp, uio));
  741         CO_TTYUNLOCK(tp, tplock);
  742         return(retval);
  743 }
  744 
  745 /*
  746  * Standard write.
  747  *
  748  * Mutual exclusion: called procedures assume locked tp.
  749  */
  750 cowrite(dev, uio)
  751         register dev_t dev;
  752         register struct uio *uio;
  753 {
  754         register struct co_state *softp;
  755         register struct tty *tp;
  756         register int retval;
  757         int unit;
  758         spl_t   tplock;
  759 
  760 #ifdef DEBUG
  761         if(co_debug)
  762                 printf("w");
  763 #endif DEBUG
  764 
  765         unit = minor(dev);
  766         if (unit & CO_FLAG)
  767                 softp = co_costate;
  768         else {
  769                 softp = &co_state[unit];
  770                 assert(unit <= co_max_unit);
  771                 assert(softp->ss_alive == 1);
  772         }
  773 
  774         tp = &softp->ss_tty;
  775         if (!tp)
  776                 panic("null tp");
  777         tplock = CO_TTYLOCK(tp);
  778         retval = ((*(linesw[tp->t_line].l_write))(tp, uio));
  779         CO_TTYUNLOCK(tp, tplock);
  780         return(retval);
  781 }
  782 #endif  /* MACH_KERNEL */
  783 
  784 #if     MACH_KDB
  785 /*
  786  * Console input for ddb.
  787  */
  788 
  789 #define CNDEBUG 0
  790 
  791 char *  cnbptr = 0;     /* console buffer pointer - current character */
  792 int     cncount = 0;    /* number of characters in buffer */
  793 boolean_t
  794         cnpolling = FALSE;
  795                         /* polling switch for interrupt handler */
  796 
  797 /*
  798  * Return character from console, or -1 if none available.
  799  */
  800 int
  801 cnmaygetc()
  802 {
  803         register struct co_state *softp;
  804         register struct sec_dev_prog *completion;
  805         register int status;
  806         int     c;
  807 
  808         softp = co_costate;
  809 
  810         if (cncount == 0) {
  811             /*
  812              * No characters.  Check for input.
  813              */
  814             if (CO_TEST_Q_EMPTY(&softp->is_doneq))
  815                 return -1;      /* no input */
  816 
  817 #if     CNDEBUG
  818  printf("*c");
  819 #endif
  820             completion = CO_GET_Q_TAIL(&softp->is_doneq);
  821             status = (int)completion->dp_status1;
  822             if (!(status & SCONS_FLUSHED)) {
  823                 /* Have more characters. */
  824                 cnbptr = softp->is_buffer;
  825                 cncount = completion->dp_count;
  826 #if     CNDEBUG
  827  printf("%d",cncount);
  828 #endif
  829             }
  830             else {
  831                 cncount = 0;
  832 #if     CNDEBUG
  833  printf("%#x",status);
  834 #endif
  835             }
  836             CO_INCR_Q_TAIL(&softp->is_doneq);
  837 #if     CNDEBUG
  838  printf("*i");
  839 #endif
  840 
  841             if (cncount == 0) {
  842                 /* still do not have any characters */
  843 #if     CNDEBUG
  844  printf("*s");
  845 #endif
  846                 co_start_read(softp);
  847                 return;
  848             }
  849         }
  850 
  851         c = *cnbptr++;
  852         if (--cncount == 0) {
  853             /*
  854              * No more characters in buffer - restart read.
  855              */
  856 #if     CNDEBUG
  857  printf("*s");
  858 #endif
  859             co_start_read(softp);
  860         }
  861         return c;
  862 }
  863 
  864 /*
  865  * Return character from console.
  866  * Wait until one appears.
  867  */
  868 int
  869 cngetc()
  870 {
  871         register int    c;
  872 
  873         while ((c = cnmaygetc()) == -1)
  874             continue;
  875         return c;
  876 }
  877 
  878 /*
  879  * Turn console polling input on or off.
  880  */
  881 cnpollc(on)
  882         boolean_t on;
  883 {
  884         register struct co_state *softp;
  885 
  886         softp = co_costate;
  887 
  888 #if     CNDEBUG
  889  printf("*a%d",on);
  890 #endif
  891         if (on) {
  892             /* Disable console interrupts before aborting read. */
  893 
  894             cnpolling = TRUE;
  895 
  896             co_abort_read(softp);
  897 
  898             /* no characters in buffer.  Start read. */
  899             cnbptr = 0;
  900             cncount = 0;
  901 #if     CNDEBUG
  902  printf("*s");
  903 #endif
  904             co_start_read(softp);
  905         }
  906         else {
  907             co_abort_read(softp);
  908 
  909             /* Restart read for user if TTY open. */
  910             if (softp->is_restart_read)
  911                 co_start_read(softp);
  912 
  913             /* Enable console interrupts after restarting read. */
  914             cnpolling = FALSE;
  915         }
  916 }
  917 
  918 int     cnescape = 0;   /* escape character was last */
  919 
  920 #endif  MACH_KDB
  921 
  922 cointr(vector)
  923         int vector;
  924 {
  925         register int count;
  926         register caddr_t bptr;
  927         register int status;
  928         register struct tty *tp;
  929         register struct co_state *softp;
  930         int unit;
  931         spl_t   tplock;
  932         int is_read;
  933         struct sec_dev_prog *completion;
  934 
  935         unit = (vector - co_base_vec)/2;
  936         is_read = (((vector - co_base_vec) % 2) == 0);
  937         softp = &co_state[unit];
  938 
  939         if (unit < 0 || unit > co_max_unit) {
  940                 printf("co: stray interrupt, unit out of range %x\n",unit);
  941                 return;
  942         }
  943 
  944         if (softp->ss_alive == 0) {
  945                 printf("co: stray interrupt, dead unit %x\n", unit);
  946                 return;
  947         }
  948 
  949 #if     MACH_KDB
  950         /* Ignore interrupt if polling input from console. */
  951         if (softp == co_costate && cnpolling)
  952                 return;
  953 #endif  MACH_KDB
  954 #ifdef  DEBUG
  955         if (co_debug)
  956                 printf("C");
  957 #endif  DEBUG
  958 
  959         tp = &softp->ss_tty;
  960         tplock = CO_TTYLOCK(tp);
  961 
  962         if (is_read) {
  963             while (!CO_TEST_Q_EMPTY(&softp->is_doneq)) {
  964                 completion = CO_GET_Q_TAIL(&softp->is_doneq);
  965                 status = (int)completion->dp_status1;
  966 #ifdef  DEBUG
  967                 if (co_debug)
  968                         printf("I");
  969                 if (co_debug > 1)
  970                         printf("%x ", status);
  971 #endif  DEBUG
  972 
  973                 if(status & SCONS_CARR_DET) {
  974                         co_get_modes(softp);
  975                         if (softp->os_smode.CM_FLAGS & SCONS_CARRIER_CLEAR) {
  976 #ifdef  MACH_KERNEL
  977                                 (void) ttymodem(tp, 0);
  978 #else   /* MACH_KERNEL */
  979                                 if (tp->t_state & TS_CARR_ON) {
  980                                         tp->t_state &= ~TS_CARR_ON;
  981                                         if(((tp->t_state&TS_WOPEN) == 0)
  982                                         &&(tp->t_state&TS_ISOPEN)
  983                                         &&((tp->t_flags&NOHANG) == 0)) {
  984                                                 gsignal(tp->t_pgrp, SIGHUP);
  985                                                 gsignal(tp->t_pgrp, SIGCONT);
  986                                                 ttyflush(tp, FREAD|FWRITE);
  987                                         }
  988                                 }
  989 #endif  /* MACH_KERNEL */
  990                         } else {
  991 #ifdef  MACH_KERNEL
  992                                 (void) ttymodem(tp, 1);
  993 #else   /* MACH_KERNEL */
  994                                 if ((tp->t_state & TS_CARR_ON) == 0) {
  995                                         tp->t_state |= TS_CARR_ON;
  996                                         vall_sema(&tp->t_rawqwait);
  997                                 }
  998 #endif  /* MACH_KERNEL */
  999                         }
 1000                 }
 1001                 if (!(status & SCONS_FLUSHED)) {
 1002                         if(status & SCONS_PARITY_ERR)
 1003                                 softp->is_parc++;
 1004                         if(status & SCONS_OVRFLOW)
 1005                                 softp->is_ovc++;
 1006                         if(status & SCONS_BREAK_DET)
 1007 #ifdef  MACH_KERNEL
 1008                             ttyinput(tp->t_breakc, tp);
 1009 #else   /* MACH_KERNEL */
 1010                              if(tp->t_flags&RAW)
 1011                                    (*linesw[tp->t_line].l_rint)(0, tp); 
 1012                              else
 1013                                    (*linesw[tp->t_line].l_rint)(tp->t_intrc, tp); 
 1014 #endif  /* MACH_KERNEL */
 1015                         count = completion->dp_count;
 1016 #ifdef  DEBUG
 1017                         if (co_debug > 1)
 1018                                 printf("%x\n", count);
 1019 #endif  DEBUG
 1020                         bptr = softp->is_buffer;
 1021                         while(count-- > 0) {
 1022 #if     MACH_KDB
 1023 #define CNESC   ('_' & 077)
 1024                         {
 1025                             register int c;
 1026 
 1027                             c = *bptr++;
 1028 
 1029                             if (cnescape) {
 1030                                 cnescape = 0;
 1031                                 switch (c & 0177) {
 1032                                     case CNESC:
 1033                                         /* Escaped escape character. */
 1034                                         /* Use it. */
 1035                                         break;
 1036 
 1037                                     case 'k':
 1038                                     case 'K':
 1039                                         /* Kernel debugger keyboard intr. */
 1040                                         simple_unlock(&tp->t_lock);
 1041                                         kdb_kintr();
 1042                                         splx(tplock);
 1043                                         return;
 1044 
 1045                                     default:
 1046                                         /* Any other character.  Queue the */
 1047                                         /* delayed escape character, then */
 1048                                         /* the current character. */
 1049                                         ttyinput(CNESC, tp);
 1050                                         break;
 1051                                 }
 1052                             }
 1053                             else if ((c & 0177) == CNESC) {
 1054                                 cnescape = 1;
 1055                                 continue;
 1056                             }
 1057                             ttyinput(c, tp);
 1058                         }
 1059 #else   MACH_KDB
 1060                                 
 1061 #ifdef  DEBUG
 1062                                 /*
 1063                                  * Handle debug stuff.
 1064                                  */
 1065         
 1066                                 if (gc_last == DBGCHAR) {
 1067                                         gc_last = '\0';
 1068                                         debugit(*bptr);
 1069                                 } else {
 1070                                         gc_last = *bptr;
 1071                                         if (*bptr != DBGCHAR) 
 1072                                                 (*linesw[tp->t_line].l_rint)(*bptr, tp); 
 1073                                 }
 1074                                 bptr++;
 1075 #else   !DEBUG
 1076         
 1077 #ifdef  MACH_KERNEL
 1078                                 ttyinput(*bptr, tp);
 1079 #else   /* MACH_KERNEL */
 1080                                 (*linesw[tp->t_line].l_rint)(*bptr, tp); 
 1081 #endif  /* MACH_KERNEL */
 1082                                 bptr++;
 1083 #endif  DEBUG
 1084 #endif  MACH_KDB
 1085                         }
 1086                 }
 1087                 CO_INCR_Q_TAIL(&softp->is_doneq);
 1088             }
 1089             if(softp->is_restart_read)
 1090                 co_start_read(softp);
 1091         } else {
 1092             while (!CO_TEST_Q_EMPTY(&softp->os_doneq)) {
 1093                 completion = CO_GET_Q_TAIL(&softp->os_doneq);
 1094                 status = (int)completion->dp_status1;
 1095                 count = completion->dp_count;
 1096 #ifdef  DEBUG
 1097                 if (co_debug)
 1098                         printf("O");
 1099                 if (co_debug > 1)
 1100                         printf("%x %x\n", status, count);
 1101 #endif  DEBUG
 1102 
 1103                 tp->t_state &= ~TS_BUSY;
 1104 
 1105                 if(tp->t_state&TS_FLUSH)
 1106                         tp->t_state &= ~TS_FLUSH;
 1107                 else
 1108                         ndflush(&tp->t_outq, count);
 1109 
 1110                 CO_INCR_Q_TAIL(&softp->os_doneq);
 1111 
 1112 #ifdef  MACH_KERNEL
 1113 #else   /* MACH_KERNEL */
 1114                 if(tp->t_line)
 1115                         (*linesw[tp->t_line].l_start)(tp);
 1116                 else
 1117 #endif  /* MACH_KERNEL */
 1118                         costart(tp);
 1119             }
 1120         }
 1121         CO_TTYUNLOCK(tp, tplock);
 1122 }
 1123 
 1124 #ifdef  MACH_KERNEL
 1125 cogetstat(dev, flavor, data, count)
 1126         dev_t           dev;
 1127         int             flavor;
 1128         int *           data;           /* pointer to OUT array */
 1129         unsigned int    *count;         /* out */
 1130 {
 1131         register int    unit;
 1132         register struct tty *tp;
 1133         register struct co_state *softp;
 1134 
 1135         unit = minor(dev);
 1136         if (unit & CO_FLAG)
 1137                 softp = co_costate;
 1138         else {
 1139                 softp = &co_state[unit];
 1140                 assert(unit <= co_max_unit);
 1141                 assert(softp->ss_alive == 1);
 1142         }
 1143 
 1144         return (tty_get_status(&softp->ss_tty, flavor, data, count));
 1145 }
 1146 
 1147 cosetstat(dev, flavor, data, count)
 1148         dev_t           dev;
 1149         int             flavor;
 1150         int *           data;
 1151         unsigned int    count;
 1152 {
 1153         register int    unit;
 1154         register struct tty *tp;
 1155         register struct co_state *softp;
 1156         spl_t           tplock;
 1157 
 1158         unit = minor(dev);
 1159         if (unit & CO_FLAG)
 1160                 softp = co_costate;
 1161         else {
 1162                 softp = &co_state[unit];
 1163                 assert(unit <= co_max_unit);
 1164                 assert(softp->ss_alive == 1);
 1165         }
 1166 
 1167         tp = &softp->ss_tty;
 1168         tplock = CO_TTYLOCK(tp);
 1169 
 1170         switch (flavor) {
 1171             case TTY_MODEM:
 1172                 if ((*data & TM_DTR) != 0) {
 1173                     if (softp->os_smode.CM_FLAGS & (SCONS_CLEAR_DTR |
 1174                                                     SCONS_CLEAR_RTS)) {
 1175                         softp->os_smode.CM_FLAGS &= ~(SCONS_CLEAR_DTR |
 1176                                                       SCONS_CLEAR_RTS);
 1177                         co_wset_modes(softp);
 1178                     }
 1179                 }
 1180                 else if ((*data & TM_DTR) == 0) {
 1181                     if ((softp->os_smode.CM_FLAGS & (SCONS_CLEAR_DTR |
 1182                                                     SCONS_CLEAR_RTS)) == 0) {
 1183                         softp->os_smode.CM_FLAGS |= (SCONS_CLEAR_DTR |
 1184                                                      SCONS_CLEAR_RTS);
 1185                         co_wset_modes(softp);
 1186                     }
 1187                 }
 1188                 break;
 1189             case TTY_SET_BREAK:
 1190                 softp->os_smode.CM_FLAGS |= SCONS_SET_BREAK;
 1191                 co_wset_modes(softp);
 1192                 break;
 1193             case TTY_CLEAR_BREAK:
 1194                 softp->os_smode.CM_FLAGS &= ~SCONS_SET_BREAK;
 1195                 co_wset_modes(softp);
 1196                 break;
 1197             default:
 1198                 CO_TTYUNLOCK(tp, tplock);
 1199                 return (tty_get_status(&softp->ss_tty, flavor, data, count));
 1200         }
 1201         CO_TTYUNLOCK(tp, tplock);
 1202         return (D_SUCCESS);
 1203 }
 1204 
 1205 #else   /* MACH_KERNEL */
 1206 /*
 1207  * stioctl - io controls
 1208  *
 1209  * Mutex: assumes called with a non-locked tp.
 1210  */
 1211 coioctl(dev, cmd, data, flag)
 1212         dev_t   dev;
 1213         register cmd;
 1214         int     flag;
 1215         caddr_t data;
 1216 {       
 1217         register struct tty *tp;
 1218         register error;
 1219         register int    unit;
 1220         register struct co_state *softp;
 1221         spl_t    tplock;
 1222 
 1223 #ifdef DEBUG
 1224         if(co_debug)
 1225                 printf("coioctl: dev=0x%x, cmd=0x%x, flag=0x%x, data=0x%x\n", 
 1226                         dev, cmd, flag, data);
 1227 #endif DEBUG
 1228 
 1229         unit = minor(dev);
 1230         if (unit & CO_FLAG)
 1231                 softp = co_costate;
 1232         else {
 1233                 softp = &co_state[unit];
 1234                 assert(unit <= co_max_unit);
 1235                 assert(softp->ss_alive == 1);
 1236         }
 1237 
 1238         tp = &softp->ss_tty;
 1239 
 1240         tplock = CO_TTYLOCK(tp);
 1241 
 1242         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
 1243         if(error >= 0) {
 1244                 CO_TTYUNLOCK(tp, tplock);
 1245                 return(error);
 1246         }
 1247 
 1248         error = ttioctl(tp, cmd, data, flag);
 1249         if(error >= 0) {
 1250                 if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
 1251                     cmd == TIOCLBIC || cmd == TIOCLSET)
 1252                         co_param(softp);
 1253                 CO_TTYUNLOCK(tp, tplock);
 1254                 return(error);
 1255         }
 1256 
 1257         /*
 1258          * Process special stuff...
 1259          */
 1260         error = 0;
 1261         switch(cmd) {
 1262                 case TIOCSBRK:  /* set break on */
 1263                         softp->os_smode.CM_FLAGS |= SCONS_SET_BREAK;
 1264                         co_wset_modes(softp);
 1265                         break;
 1266                 case TIOCCBRK:  /* clear break off */
 1267                         softp->os_smode.CM_FLAGS &= ~SCONS_SET_BREAK;
 1268                         co_wset_modes(softp);
 1269                         break;
 1270                 case TIOCSDTR:  /* Turn on dtr rts */
 1271                         softp->os_smode.CM_FLAGS &= ~(SCONS_CLEAR_DTR | SCONS_CLEAR_RTS);
 1272                         co_wset_modes(softp);
 1273                         break;
 1274                 case TIOCCDTR:  /* turn off dtr rts */
 1275                         softp->os_smode.CM_FLAGS |= (SCONS_CLEAR_DTR | SCONS_CLEAR_RTS);
 1276                         co_wset_modes(softp);
 1277                         break;
 1278                 default:
 1279                         error = ENOTTY;
 1280         }
 1281         CO_TTYUNLOCK(tp, tplock);
 1282         return(error);
 1283 }
 1284 
 1285 
 1286 
 1287 /*
 1288  * coselect
 1289  *
 1290  * Mutual exclusion: called procedures assume locked tp.
 1291  */
 1292 coselect(dev, rw)
 1293         dev_t   dev;
 1294         int     rw;
 1295 {
 1296         register struct tty *tp;
 1297         int     retval;
 1298         spl_t   tplock;
 1299         int     unit;
 1300 
 1301         unit = minor(dev);
 1302         if (unit & CO_FLAG)
 1303                 tp = &co_costate->ss_tty;
 1304         else
 1305                 tp = &co_state[unit].ss_tty;
 1306         tplock = CO_TTYLOCK(tp);
 1307 #ifndef MACH
 1308         retval = (*linesw[tp->t_line].l_select)(tp, rw);
 1309 #else
 1310         retval = tpselect(tp, rw);
 1311 #endif  MACH
 1312         CO_TTYUNLOCK(tp, tplock);
 1313         return(retval);
 1314 }
 1315 #endif  /* MACH_KERNEL */
 1316 
 1317 /*
 1318  * This table defines the CO command bits for setting asynchronous
 1319  * baud rates.  '-1' is the signal to turn off the DTR and RTS signals.
 1320  * '-2' indicates that a baud rate is not available on the CO.  The
 1321  * 'Mxxx' entries are for the 'rate' parameter in calls to co_setmodes();
 1322  */
 1323 
 1324 
 1325 /*
 1326  * co_param - set line parameters on the hardware.
 1327  *
 1328  * Mutex: assumed called with locked tp to insure stable data
 1329  * being read.
 1330  */
 1331 co_param(softp)
 1332         register struct co_state *softp;
 1333 {
 1334         register struct tty *tp;
 1335         u_char lpar, len, stop, parflag;
 1336 
 1337 #ifdef DEBUG
 1338         if(co_debug>1)
 1339                 printf(" co_param: enter  ");
 1340         else if(co_debug)
 1341                 printf("P");
 1342 #endif DEBUG
 1343 
 1344         tp = &softp->ss_tty;
 1345 
 1346         if(tp->t_ispeed == 0) {
 1347                 tp->t_state |= TS_HUPCLS;
 1348                 softp->os_smode.CM_FLAGS |= (SCONS_CLEAR_DTR | 
 1349                                                 SCONS_CLEAR_RTS);
 1350                 softp->os_smode.CM_FLAGS &= ~(SCONS_SET_BREAK);
 1351                 co_wset_modes(softp);
 1352                 return;
 1353         }
 1354 
 1355         if (tp->t_flags & (RAW|LITOUT|PASS8)) {
 1356                 len = SCONS_DATA8;
 1357                 parflag = 0;
 1358         } else {
 1359                  len = SCONS_DATA7;
 1360                  parflag = 1;
 1361         }
 1362         lpar = 0;
 1363         if (parflag)
 1364                 if ((tp->t_flags&EVENP) == 0)
 1365                         lpar = SCONS_ODD_PARITY;
 1366                 else
 1367                         lpar = SCONS_EVEN_PARITY;
 1368         if ((tp->t_ospeed) == B110)
 1369                 stop = SCONS_STOP2;
 1370         else
 1371                 stop = SCONS_STOP1;
 1372 
 1373         softp->os_smode.CM_BAUD = tp->t_ospeed;
 1374         softp->os_smode.CM_FLAGS &= ~(SCONS_STOP1P5 | SCONS_STOP2 |
 1375                                         SCONS_DATA7 |
 1376                                         SCONS_EVEN_PARITY |
 1377                                         SCONS_ODD_PARITY);
 1378         softp->os_smode.CM_FLAGS |= (stop | len | lpar);
 1379         co_wset_modes(softp);
 1380 }
 1381 int ttrstrt();
 1382 
 1383 /*
 1384  * costart - start a character out on the interface.
 1385  *
 1386  * This procedure starts a character out by calculating the maximum
 1387  * number of characters it can get from the clist and then programming
 1388  * the scsi to send that many characters from the clist.
 1389  * When the device program completes there will
 1390  * be included in the completion a byte count which is what was transmitted.
 1391  *
 1392  * Assumes: caller locks the tp before calling costart().
 1393  */
 1394 costart(tp)
 1395         register struct tty *tp;
 1396 {
 1397         register int nch;
 1398         register struct co_state *softp;
 1399         u_char *addr;
 1400 
 1401         /*
 1402          * If the channel is already working, or if it is waiting on
 1403          * a delay, then nothing is done right now.
 1404          */
 1405 #ifdef DEBUG
 1406         if(co_debug>1)
 1407                 printf("c\n");
 1408 #endif DEBUG
 1409 
 1410         if(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
 1411                 return;
 1412         }
 1413 
 1414         /*
 1415          * let those wanting to do setmodes get a chance first.
 1416          */
 1417 
 1418         softp = (struct co_state *)tp->t_addr;
 1419         if(softp->os_busy_flag) {
 1420                 softp->os_busy_flag = 0;
 1421                 vall_sema(&softp->os_busy_wait);
 1422                 return;
 1423         }
 1424 
 1425         /*
 1426          * If the output queue has emptied to the low threshold, and
 1427          * if anyone is sleeping on this queue, wake them up.
 1428          */
 1429 
 1430         if(tp->t_outq.c_cc <= TTLOWAT(tp)) {
 1431 #ifdef  MACH_KERNEL
 1432                 tt_write_wakeup(tp);
 1433 #else   /* MACH_KERNEL */
 1434                 if(tp->t_state & TS_ASLEEP) {
 1435                         tp->t_state &= ~TS_ASLEEP;
 1436                         vall_sema(&tp->t_outqwait);
 1437                 }
 1438                 if(tp->t_wsel) {
 1439                         selwakeup(tp->t_wsel, tp->t_state&TS_WCOLL);
 1440                         tp->t_state &= ~TS_WCOLL;
 1441                         tp->t_wsel = (struct proc *)NULL;
 1442                 }
 1443 #endif  /* MACH_KERNEL */
 1444         }
 1445 
 1446         if(tp->t_outq.c_cc == 0) {      /* Nothing to process */
 1447                 return;
 1448         }
 1449 
 1450 
 1451         /*
 1452          * Dma from clist direct.
 1453          *
 1454          * Find where on clist and tell board to dma from there. When the interrupt
 1455          * comes in that signals the block output done all we have to do 
 1456          * is ndflush the clist which is much less overhead then many getc's.
 1457          */
 1458         if(tp->t_flags & (RAW|LITOUT))
 1459                 nch = ndqb(&tp->t_outq, 0);
 1460         else{   
 1461                 /*
 1462                  * not raw so check for timeout chars and if we 
 1463                  * have dma'd out to one then do the timeout.
 1464                  */
 1465                 nch = ndqb(&tp->t_outq, 0200);
 1466                 if(nch==0) {
 1467                         nch = getc(&tp->t_outq);
 1468                         timeout(ttrstrt, (caddr_t)tp, ((nch & 0x7f) + 6));
 1469                         tp->t_state |= TS_TIMEOUT;
 1470                         return;
 1471                 }
 1472         }
 1473 
 1474         addr = (u_char *)tp->t_outq.c_cf;
 1475 #ifdef  MACH_KERNEL
 1476         /*
 1477          * Copy characters from the circular buffer to the output
 1478          * buffer.  The circular buffer may not be within SCED space.
 1479          */
 1480         if (nch > CBSIZE)
 1481                 nch = CBSIZE;
 1482         bcopy((char *)addr, softp->os_buffer, nch);
 1483         addr = (u_char *)softp->os_buffer;
 1484 #endif  /* MACH_KERNEL */
 1485 #ifdef DEBUG
 1486         if(co_debug>2)
 1487                 printf("BO: %d\n", nch);
 1488         else if(co_debug)
 1489                 printf("X");
 1490 #endif DEBUG
 1491         assert(((nch>0) && (nch<=CBSIZE)));
 1492         co_start_write(softp, nch, addr);
 1493         tp->t_state |= TS_BUSY;
 1494 }
 1495 
 1496 /*
 1497  * costop - Abort an in progress dma on a channel.
 1498  *
 1499  * This procedure aborts output on a line.
 1500  * Curious note:  No driver seems to ever use the flag parameter.
 1501  *
 1502  * Mutex: Assumes caller has locked the tp prior to
 1503  *        calling this procedure.
 1504  */
 1505 /*ARGSUSED*/
 1506 costop(tp, flag)
 1507         register struct tty *tp;
 1508 {
 1509         register struct co_state *softp;
 1510 
 1511 #ifdef DEBUG
 1512         if(co_debug)
 1513                 printf("S");
 1514 #endif DEBUG
 1515 
 1516         if (tp->t_state & TS_BUSY) {
 1517                 /*
 1518                  * Device is transmitting; stop output.
 1519                  * We will clean up later
 1520                  * by examining the xfer count for a completion.
 1521                  *
 1522                  * The TS_FLUSH flag is used to tell us HOW to clean
 1523                  * up.  If it is set, the characters have 
 1524                  * aleady been cleaned off the t_outq by ttyflush().
 1525                  * Otherwise, we need to clean off the ones that have
 1526                  * been transmitted.
 1527                  */
 1528                 if ((tp->t_state&TS_TTSTOP)==0)
 1529                         tp->t_state |= TS_FLUSH;
 1530 
 1531                 softp = (struct co_state *)tp->t_addr;
 1532                 co_abort_write(softp);
 1533         }
 1534 }
 1535 
 1536 
 1537 
 1538 /*
 1539  * co_start_write   -queue a write request to the output channel.
 1540  *
 1541  * assume request queue and status are locked prior to entry
 1542  * also assumes that the request queue is not full.
 1543  */
 1544 co_start_write(softp, nch, addr)
 1545         register struct co_state *softp;
 1546         register int nch;
 1547         register u_char *addr;
 1548 {
 1549         register struct sec_dev_prog *request;
 1550 
 1551         request = CO_GET_Q_HEAD(&softp->os_reqq);
 1552         request->dp_status1 = 0;
 1553         request->dp_count = 0;
 1554         request->dp_un.dp_data = KVTOPHYS(addr, u_char *);
 1555         request->dp_data_len = nch;
 1556         request->dp_next = (struct sec_dev_prog*)0;
 1557         CO_INCR_Q_HEAD(&softp->os_reqq);
 1558         sec_startio(SINST_STARTIO, &softp->os_status, softp->os_sd);
 1559         if (softp->os_status & (~SINST_INSDONE))
 1560                 printf("co: bad start_write: %x\n", softp->os_status);
 1561 }
 1562 
 1563 /*
 1564  * co_start_read   -queue a read request to the output channel.
 1565  *
 1566  * assume request queue and status are locked prior to entry
 1567  * also assumes that the request queue is not full.
 1568  */
 1569 co_start_read(softp)
 1570         register struct co_state * softp;
 1571 {
 1572         register struct sec_dev_prog *request;
 1573 
 1574         request = CO_GET_Q_HEAD(&softp->is_reqq);
 1575         request->dp_status1 = 0;
 1576         request->dp_count = 0;
 1577         request->dp_un.dp_data = KVTOPHYS(softp->is_buffer, u_char *);
 1578         request->dp_data_len = CBSIZE;
 1579         request->dp_next = (struct sec_dev_prog*)0;
 1580         CO_INCR_Q_HEAD(&softp->is_reqq);
 1581         sec_startio(SINST_STARTIO, &softp->is_status, softp->is_sd);
 1582         if (softp->is_status & (~SINST_INSDONE))
 1583                 printf("co: bad start_read: %x\n", softp->is_status);
 1584 }
 1585 
 1586 /*
 1587  * co_wset_modes - set console modes.
 1588  *
 1589  * This procedure assumes that access to the os_smode structure and
 1590  * to the cib are locked.  It waits until the transmitting channel is
 1591  * not busy, then does the set modes.  This ensures that the last of
 1592  * previous output has gone to the display before changing anything.
 1593  */
 1594 co_wset_modes(softp)
 1595         register struct co_state *softp;
 1596 {
 1597         register struct tty *tp;
 1598 
 1599         tp = &softp->ss_tty;
 1600         while (tp->t_state & TS_BUSY) {
 1601                 softp->os_busy_flag = 1;
 1602 #ifdef  MACH_KERNEL
 1603                 p_sema_v_lock(&softp->os_busy_wait, 0, &tp->t_lock, SPLTTY);
 1604 #else   /* MACH_KERNEL */
 1605                 p_sema_v_lock(&softp->os_busy_wait, TTIPRI, &tp->t_ttylock, SPLTTY);
 1606 #endif  MACH_KERNEL
 1607                 (void) CO_TTYLOCK(tp);
 1608         }
 1609 
 1610         sec_startio(SINST_SETMODE, &softp->os_smode.sm_status, softp->os_sd);
 1611         if (softp->os_smode.sm_status & (~SINST_INSDONE))
 1612                 printf("co: bad set_mode: %x\n", softp->os_smode.sm_status);
 1613 #ifdef  DEBUG
 1614         if (co_debug > 1)
 1615                 printf("setmode done flags %x, baud %x\n",
 1616                 softp->os_smode.CM_FLAGS, softp->os_smode.CM_BAUD);
 1617 #endif  DEBUG
 1618         costart(tp);
 1619 }
 1620 
 1621 /*
 1622  * co_get_modes - get console modes.
 1623  *
 1624  * This procedure assumes that access to the os_smode structure and
 1625  * to the cib are locked.  
 1626  */
 1627 co_get_modes(softp)
 1628         register struct co_state *softp;
 1629 {
 1630         sec_startio(SINST_GETMODE, &softp->os_smode.sm_status, softp->os_sd);
 1631         if (softp->os_smode.sm_status & (~SINST_INSDONE))
 1632                 printf("co: bad get_mode: %x\n", softp->os_smode.sm_status);
 1633 #ifdef  DEBUG
 1634         if (co_debug > 1)
 1635                 printf("getmode done flags %x, baud %x\n",
 1636                 softp->os_smode.CM_FLAGS, softp->os_smode.CM_BAUD);
 1637 #endif  DEBUG
 1638 }
 1639 
 1640 
 1641 
 1642 /*
 1643  * co_abort_write - abort any pending or current write device programs
 1644  *
 1645  * This procedure assumes that access to the output structures are locked.  
 1646  */
 1647 co_abort_write(softp)
 1648         register struct co_state *softp;
 1649 {
 1650         sec_startio(SINST_FLUSHQUEUE, &softp->os_status, softp->os_sd);
 1651         if (softp->os_status & (~SINST_INSDONE))
 1652                 printf("co: bad abort_write: %x\n", softp->os_status);
 1653 }
 1654 
 1655 /*
 1656  * co_abort_read - abort any pending or current read device programs
 1657  *
 1658  * This procedure assumes that access to the output structures are locked.  
 1659  */
 1660 co_abort_read(softp)
 1661         register struct co_state *softp;
 1662 {
 1663         sec_startio(SINST_FLUSHQUEUE, &softp->is_status, softp->is_sd);
 1664         if (softp->is_status & (~SINST_INSDONE))
 1665                 printf("co: bad abort_read: %x\n", softp->is_status);
 1666 }
 1667 
 1668 /*
 1669  * Program queue management routines.  These may be candidates for
 1670  * implementation as macros.  Or, they may be moved in line and
 1671  * implemented more efficiently later.
 1672  *
 1673  * CO_TEST_Q_EMPTY  - return true if program queue is empty
 1674  */
 1675 
 1676 CO_TEST_Q_EMPTY(sq)
 1677         struct sec_pq   *sq;
 1678 {
 1679         struct sec_progq *pq;
 1680 
 1681         pq = sq->sq_progq;
 1682         assert(pq->pq_tail < sq->sq_size);
 1683         assert(pq->pq_head < sq->sq_size);
 1684 
 1685         return(pq->pq_head == pq->pq_tail);
 1686 }
 1687 
 1688 /*
 1689  * CO_GET_Q_HEAD  - return pointer to first available "empty" device
 1690  *                      program.
 1691  */
 1692 
 1693 struct sec_dev_prog *
 1694 CO_GET_Q_HEAD(sq)
 1695         struct sec_pq   *sq;
 1696 {
 1697         struct sec_progq *pq;
 1698 
 1699         pq = sq->sq_progq;
 1700         assert(pq->pq_tail < sq->sq_size);
 1701         assert(pq->pq_head < sq->sq_size);
 1702 
 1703         return(PHYSTOKV(pq->pq_un.pq_progs[pq->pq_head],
 1704                         struct sec_dev_prog *));
 1705 }
 1706 
 1707 /*
 1708  * CO_INCR_Q_HEAD  - increment the head of the queue, thus adding a
 1709  *                      device program to the request queue.
 1710  */
 1711 
 1712 CO_INCR_Q_HEAD(sq)
 1713         struct sec_pq   *sq;
 1714 {
 1715         struct sec_progq *pq;
 1716 
 1717         pq = sq->sq_progq;
 1718         assert(pq->pq_tail < sq->sq_size);
 1719         assert(pq->pq_head < sq->sq_size);
 1720 
 1721         pq->pq_head = (pq->pq_head + 1) % sq->sq_size;
 1722 }
 1723 
 1724 /*
 1725  * CO_GET_Q_TAIL  - return pointer to first completed device
 1726  *                      program.
 1727  */
 1728 
 1729 struct sec_dev_prog *
 1730 CO_GET_Q_TAIL(sq)
 1731         struct sec_pq   *sq;
 1732 {
 1733         struct sec_progq *pq;
 1734 
 1735         pq = sq->sq_progq;
 1736         assert(pq->pq_tail < sq->sq_size);
 1737         assert(pq->pq_head < sq->sq_size);
 1738 
 1739         return(PHYSTOKV(pq->pq_un.pq_progs[pq->pq_tail],
 1740                         struct sec_dev_prog *));
 1741 }
 1742 
 1743 /*
 1744  * CO_INCR_Q_TAIL  - increment the tail of the queue, thus deleting a
 1745  *                      device program to the completion queue.
 1746  */
 1747 
 1748 CO_INCR_Q_TAIL(sq)
 1749         struct sec_pq   *sq;
 1750 {
 1751         struct sec_progq *pq;
 1752 
 1753         pq = sq->sq_progq;
 1754         assert(pq->pq_tail < sq->sq_size);
 1755         assert(pq->pq_head < sq->sq_size);
 1756 
 1757         pq->pq_tail = (pq->pq_tail + 1) % sq->sq_size;
 1758 }

Cache object: d479a1055914e8e937ebc562b05f7615


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.