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/i386at/com.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) 1993,1991,1990 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        com.c,v $
   29  * Revision 2.21  93/11/17  16:42:59  dbg
   30  *      Restore earlier fix: can`t use ttymodem "flow control" since
   31  *      modem drops carrier but still talks to machine.  Shut down FIFO
   32  *      on close.
   33  *      [93/06/15            dbg]
   34  * 
   35  *      Include kern/time_out.h for hz.
   36  *      [93/06/04            dbg]
   37  * 
   38  * Revision 2.20  93/08/10  15:57:14  mrt
   39  *      Add computc(char ch, int unit) puts a character out on the
   40  *      give serial line.  For mice, etc.
   41  *      Add comgetc(int unit) for same.
   42  *      Add comparm(int unit, int baud, int intr, int mode, int modem)
   43  *      [93/06/06            rvb]
   44  * 
   45  * Revision 2.19  93/05/30  21:08:04  rvb
   46  *      Changed to use MI modem code, adding commctl.
   47  *      Does CTS/RTS flow control now.
   48  *      [93/05/29  09:52:46  af]
   49  * 
   50  * Revision 2.18  93/05/15  19:31:09  mrt
   51  *      machparam.h -> machspl.h
   52  * 
   53  * Revision 2.17  93/05/14  15:09:59  rvb
   54  *      Berman is right; check txbusy first then write for comrc_put
   55  *      [93/05/14            rvb]
   56  * 
   57  * Revision 2.16  93/05/11  13:20:16  rvb
   58  *      Accept either keyboard in cn_dogetc
   59  * 
   60  * Revision 2.15  93/05/10  21:18:46  rvb
   61  *      Removed 2.5 compat cruft. FIFOs work, but needs more work.
   62  *      Added watchdog to cure lost xmit interrupts [there is a
   63  *      bug somewhere else because I am losing them even on a
   64  *      chip that has no hardware bugs].  Do input buffering
   65  *      at all speeds higher than 300 bauds.
   66  *      [93/05/06  09:29:11  af]
   67  * 
   68  * Revision 2.14  93/05/10  17:47:18  rvb
   69  *      I spend a little time working out rconsole with Steve Berman
   70  *      and don't want to lose the code.  It's not quite done yet
   71  *      but it seems close.
   72  *      [93/05/10            rvb]
   73  * 
   74  * Revision 2.13  93/03/09  10:54:24  danner
   75  *      Don Lindsay kindly provides us with:
   76  *        Bug fix in comopen() - cleans up chip status.
   77  *        Change in debug routine compr_addr() to print line state first,
   78  *          because touching other things changes the line state.
   79  *        Made comparam() static, since no outside uses.
   80  *        Added several (void)s and fixed some function return types.
   81  *        Changed a return; to return 0; in comparam().
   82  *      [93/03/05            af]
   83  * 
   84  * Revision 2.12  93/01/24  13:15:06  danner
   85  *      [93/01/19  11:03:26  rvb]
   86  * 
   87  *      convert com_addr to vm_offset_t.
   88  * 
   89  * Revision 2.11  93/01/14  17:30:00  danner
   90  *      Always disable fifo in comprobe().
   91  *      [92/12/12            dbg]
   92  *      Added changes suggested from Finland for FIFOs.
   93  *      They still do not work, but we'll get there eventually...
   94  *      [92/12/19  10:55:22  af]
   95  * 
   96  *      Disabled FIFOs until we have good code for them.
   97  *      Do input buffering at 9600 and over.
   98  *      [92/12/10            af]
   99  * 
  100  *      Proper spl typing.
  101  *      [92/11/30            af]
  102  * 
  103  * Revision 2.10  92/05/22  13:08:34  jfriedl
  104  *      Moved disable of FIFO in comprobe().
  105  *      From Jordan K. Hubbard <jkh@meepmeep.pcs.com>
  106  * 
  107  * Revision 2.9  92/02/19  15:08:12  elf
  108  *      Made comprobe more selective. Try to recognize chip.
  109  *      [92/01/20            kivinen]
  110  * 
  111  * Revision 2.8  92/01/03  20:10:27  dbg
  112  *      Don't drop software CARR_ON if carrier drops - modem drops
  113  *      carrier but still can talk to machine.
  114  *      [91/10/30            dbg]
  115  * 
  116  * Revision 2.7  91/10/07  17:25:14  af
  117  *      Add some improvements from 2.5 version.
  118  *      [91/09/04  22:05:25  rvb]
  119  * 
  120  * Revision 2.6  91/08/24  11:57:21  af
  121  *      New MI autoconf.
  122  *      [91/08/02  02:50:03  af]
  123  * 
  124  * Revision 2.5  91/05/14  16:21:14  mrt
  125  *      Correcting copyright
  126  * 
  127  * Revision 2.4  91/02/14  14:42:06  mrt
  128  *      Merge of dbg's latest working com.c onto the old com.c
  129  *      with the new autoconf and other major changes.
  130  *      [91/01/28  15:26:13  rvb]
  131  * 
  132  * Revision 2.3  91/02/05  17:16:33  mrt
  133  *      Changed to new Mach copyright
  134  *      [91/02/01  17:42:21  mrt]
  135  * 
  136  * Revision 2.2  90/11/26  14:49:26  rvb
  137  *      jsb beat me to XMK34, sigh ...
  138  *      [90/11/26            rvb]
  139  *      Apparently first version is r2.2
  140  *      [90/11/25  10:44:41  rvb]
  141  * 
  142  *      Synched 2.5 & 3.0 at I386q (r2.3.1.6) & XMK35 (r2.2)
  143  *      [90/11/15            rvb]
  144  * 
  145  * Revision 2.3.1.5  90/08/25  15:43:06  rvb
  146  *      I believe that nothing of the early Olivetti code remains.
  147  *      Copyright gone.
  148  *      [90/08/21            rvb]
  149  * 
  150  *      Use take_<>_irq() vs direct manipulations of ivect and friends.
  151  *      [90/08/20            rvb]
  152  * 
  153  *              Moved and rewrote much of the code to improve performance.
  154  *           Still suffers from overruns.
  155  *      [90/08/14            mg32]
  156  * 
  157  * Revision 2.3.1.4  90/07/10  11:43:07  rvb
  158  *      Rewrote several functions to look more like vax-BSD dh.c.
  159  *      [90/06/25            mg32]
  160  * 
  161  *      New style probe/attach.
  162  *      Also com_struct has been radically reworked, ...
  163  *      [90/06/15            rvb]
  164  * 
  165  * Revision 2.3.1.3  90/02/28  15:49:12  rvb
  166  *      Fix numerous typo's in Olivetti disclaimer.
  167  *      [90/02/28            rvb]
  168  * 
  169  * Revision 2.3.1.2  90/01/08  13:32:00  rvb
  170  *      Add Olivetti copyright.
  171  *      [90/01/08            rvb]
  172  * 
  173  * Revision 2.3.1.1  89/12/21  18:01:29  rvb
  174  *      Changes from Ali Ezzet.
  175  * 
  176  * Revision 2.2.0.0  89/07/17  10:39:30  rvb
  177  *      New from Olivetti.
  178  * 
  179  */
  180 
  181 #include <com.h>
  182 #if NCOM > 0
  183 
  184 #include <mach/std_types.h>
  185 #include <sys/types.h>
  186 #include <kern/kern_io.h>
  187 #include <kern/time_out.h>
  188 #include <device/conf.h>
  189 #include <device/errno.h>
  190 #include <device/tty.h>
  191 #include <device/io_req.h>
  192 
  193 #include <i386/ipl.h>
  194 #include <i386/pio.h>
  195 #include <i386/machspl.h>
  196 #include <chips/busses.h>
  197 #include <i386at/comreg.h>
  198 
  199 extern void ttrstrt();
  200 
  201 /*
  202  *      Forward declarations
  203  */
  204 boolean_t comprobe(
  205         vm_offset_t     port,
  206         struct bus_device *dev);
  207 void comattach(
  208         struct bus_device *dev);
  209 void comintr(
  210         int unit);
  211 void comstart(
  212         struct tty *tp);
  213 void fix_modem_state(
  214         int     unit,
  215         int     modem_stat);
  216 int commctl(
  217         struct tty      *tp,
  218         int     bits,
  219         int     how);
  220 static void comparam(
  221         register int unit);
  222 void comtimer(void *);
  223 void comstop(
  224         register struct tty *tp,
  225         int     flags);
  226 void commodem_intr(
  227         int     unit,
  228         int     stat);
  229 io_return_t comgetstat(
  230         int             dev,
  231         dev_flavor_t    flavor,
  232         dev_status_t    data,
  233         natural_t       *count);
  234 io_return_t comsetstat(
  235         int             dev,
  236         dev_flavor_t    flavor,
  237         dev_status_t    data,
  238         natural_t       count);
  239 
  240 struct bus_device *cominfo[NCOM];       /* ??? */
  241 
  242 static vm_offset_t com_std[NCOM] = { 0 };
  243 static struct bus_device *com_info[NCOM];
  244 struct bus_driver comdriver = {
  245         comprobe, 0, comattach, 0, com_std, "com", com_info, 0, 0, 0};
  246 
  247 struct tty com_tty[NCOM];
  248 int commodem[NCOM];
  249 int comcarrier[NCOM] = {0, 0,};
  250 boolean_t comfifo[NCOM];
  251 boolean_t comtimer_active;
  252 int comtimer_state[NCOM];
  253 
  254 #ifndef PORTSELECTOR
  255 #define ISPEED  B9600
  256 #define IFLAGS  (EVENP|ODDP|ECHO|CRMOD)
  257 #else
  258 #define ISPEED  B4800
  259 #define IFLAGS  (EVENP|ODDP)
  260 #endif
  261 
  262 u_short divisorreg[] = {
  263         0,      2304,   1536,   1047,           /*     0,    50,    75,   110*/
  264         857,     768,    576,    384,    192,   /*   134.5, 150,   200,   300,   600*/
  265          96,      64,             48,           /*  1200,  1800,  2000,  2400 */
  266                   24,             12,           /*  3600,  4800,  7200,  9600 */
  267           6,       3,      2};                  /* 19200, 38400, 56000 */
  268 
  269 /*
  270  *
  271  * Probe's are called during kernel boot: return 1 to mean that
  272  * the relevant device is present today.
  273  *
  274  */
  275 boolean_t
  276 comprobe(
  277         vm_offset_t     port,
  278         struct bus_device *dev)
  279 {
  280         u_short addr = dev->address;
  281         int     unit = dev->unit;
  282         int     oldctl, oldmsb;
  283         char    *type = "8250";
  284         int     i;
  285 
  286         if ((unit < 0) || (unit > NCOM)) {
  287                 printf("com %d out of range\n", unit);
  288                 return(0);
  289         }
  290         oldctl = inb(LINE_CTL(addr));    /* Save old value of LINE_CTL */
  291         oldmsb = inb(BAUD_MSB(addr));    /* Save old value of BAUD_MSB */
  292         outb(LINE_CTL(addr), 0);         /* Select INTR_ENAB */    
  293         outb(BAUD_MSB(addr), 0);
  294         if (inb(BAUD_MSB(addr)) != 0)
  295           {
  296             outb(LINE_CTL(addr), oldctl);
  297             outb(BAUD_MSB(addr), oldmsb);
  298             return 0;
  299           }
  300         outb(LINE_CTL(addr), iDLAB);     /* Select BAUD_MSB */
  301         outb(BAUD_MSB(addr), 255);
  302         if (inb(BAUD_MSB(addr)) != 255)
  303           {
  304             outb(LINE_CTL(addr), oldctl);
  305             outb(BAUD_MSB(addr), oldmsb);
  306             return 0;
  307           }
  308         outb(LINE_CTL(addr), 0);         /* Select INTR_ENAB */
  309         if (inb(BAUD_MSB(addr)) != 0)    /* Check that it has kept it's value*/
  310           {
  311             outb(LINE_CTL(addr), oldctl);
  312             outb(BAUD_MSB(addr), oldmsb);
  313             return 0;
  314           }
  315 
  316         /* Com port found, now check what chip it has */
  317         
  318         for(i = 0; i < 256; i++)         /* Is there Scratch register */
  319           {
  320             outb(SCR(addr), i);
  321             if (inb(SCR(addr)) != i)
  322               break;
  323           }
  324         if (i == 256)
  325           {                              /* Yes == 450 or 460 */
  326             outb(SCR(addr), 0);
  327             type = "82450 or 16450";
  328             outb(FIFO_CTL(addr), iFIFOENA | iFIFO14CH);  /* Enable fifo */
  329             if ((inb(FIFO_CTL(addr)) & iFIFO14CH) != 0)
  330               {                          /* Was it successfull */
  331                 /* if both bits are not set then broken xx550 */
  332                 if ((inb(FIFO_CTL(addr)) & iFIFO14CH) == iFIFO14CH)
  333                   {
  334                     type = "82550 or 16550";
  335                     comfifo[unit] = TRUE;
  336                   }
  337                 else
  338                   {
  339                     type = "82550 or 16550 with non-working FIFO";
  340                   }
  341                 outb(INTR_ID(addr), 0x00); /* Disable fifos */
  342               }
  343           }
  344         printf("com%d: %s chip.\n", unit, type);
  345         return 1;
  346 }
  347 
  348 /*
  349  *
  350  * Device Attach's are called during kernel boot, but only if the matching
  351  * device Probe returned a 1.
  352  * No return value, despite the "int" signature.
  353  *
  354  */
  355 void comattach(
  356         struct bus_device *dev)
  357 {
  358         u_char  unit = dev->unit;
  359         u_short addr = dev->address;
  360 
  361         take_dev_irq(dev);
  362         printf(", port = %x, spl = %d, pic = %d. (DOS COM%d)",
  363                 dev->address, dev->sysdep, dev->sysdep1, unit+1);
  364 
  365         cominfo[unit] = dev;
  366 /*      comcarrier[unit] = addr->flags;*/
  367         commodem[unit] = 0;
  368 
  369         outb(INTR_ENAB(addr), 0);
  370         outb(MODEM_CTL(addr), 0);
  371         while (!(inb(INTR_ID(addr))&1)) {
  372                 (void) inb(LINE_STAT (addr));   /* reset overrun error etc */
  373                 (void) inb(TXRX      (addr));   /* reset data-ready */
  374                 (void) inb(MODEM_STAT(addr));   /* reset modem status reg */
  375         }
  376 }
  377 
  378 io_return_t comopen(
  379         int dev,
  380         int flag,
  381         io_req_t ior)
  382 {
  383         int             unit = minor(dev);
  384         u_short         addr;
  385         struct bus_device       *isai;
  386         struct tty      *tp;
  387         spl_t           s;
  388         io_return_t     result;
  389 
  390         if (unit >= NCOM || (isai = cominfo[unit]) == 0 || isai->alive == 0)
  391                 return(ENXIO);
  392         tp = &com_tty[unit];
  393 
  394         if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0) {
  395                 ttychars(tp);
  396                 tp->t_addr = (char *)isai->address;
  397                 tp->t_dev = dev;
  398                 tp->t_oproc = comstart;
  399                 tp->t_stop = comstop;
  400                 tp->t_mctl = commctl;
  401                 tp->t_getstat = comgetstat;
  402                 tp->t_setstat = comsetstat;
  403 #ifndef PORTSELECTOR
  404                 if (tp->t_ispeed == 0) {
  405 #else
  406                         tp->t_state |= TS_HUPCLS;
  407 #endif  /* PORTSELECTOR */
  408                         tp->t_ispeed = ISPEED;
  409                         tp->t_ospeed = ISPEED;
  410                         tp->t_flags = IFLAGS;
  411                         tp->t_state &= ~TS_BUSY;
  412 #ifndef PORTSELECTOR
  413                 }
  414 #endif  /* PORTSELECTOR */
  415         }
  416 /*rvb   tp->t_state |= TS_WOPEN; */
  417         if ((tp->t_state & TS_ISOPEN) == 0)
  418                 comparam(unit);
  419         addr = (int)tp->t_addr;
  420 
  421         s = spltty();
  422         if (!comcarrier[unit])  /* not originating */
  423                 tp->t_state |= TS_CARR_ON;
  424         else {
  425                 int modem_stat = inb(MODEM_STAT(addr));
  426                 if (modem_stat & iRLSD)
  427                         tp->t_state |= TS_CARR_ON;
  428                 else
  429                         tp->t_state &= ~TS_CARR_ON;
  430                 fix_modem_state(unit, modem_stat);
  431         } 
  432         splx(s);
  433 
  434         result = char_open(dev, tp, flag, ior);
  435 
  436         if (!comtimer_active) {
  437                 comtimer_active = TRUE;
  438                 comtimer(0);
  439         }
  440 
  441         s = spltty();
  442         while(!(inb(INTR_ID(addr))&1)) { /* while pending interrupts */
  443                 (void) inb(LINE_STAT (addr)); /* reset overrun error  */
  444                 (void) inb(TXRX      (addr)); /* reset data-ready           */
  445                 (void) inb(MODEM_STAT(addr)); /* reset modem status   */
  446         }
  447         splx(s);
  448         return result;
  449 }
  450 
  451 io_return_t comclose(
  452         int dev,
  453         int flag)
  454 {
  455         struct tty      *tp = &com_tty[minor(dev)];
  456         u_short         addr = (int)tp->t_addr;
  457 
  458         ttyclose(tp);
  459         if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) { 
  460                 outb(INTR_ENAB(addr), 0);
  461                 outb(MODEM_CTL(addr), 0);
  462                 tp->t_state &= ~TS_BUSY;
  463                 commodem[minor(dev)] = 0;
  464                 if (comfifo[minor(dev)])
  465                         outb(INTR_ID(addr), 0x00); /* Disable fifos */
  466         }
  467         return 0;
  468 }
  469 
  470 io_return_t comread(
  471         int     dev,
  472         io_req_t ior)
  473 {
  474         return char_read(&com_tty[minor(dev)], ior);
  475 }
  476 
  477 io_return_t comwrite(
  478         int     dev,
  479         io_req_t ior)
  480 {
  481         return char_write(&com_tty[minor(dev)], ior);
  482 }
  483 
  484 io_return_t comportdeath(
  485         dev_t           dev,
  486         mach_port_t     port)
  487 {
  488         return tty_portdeath(&com_tty[minor(dev)], port);
  489 }
  490 
  491 io_return_t
  492 comgetstat(
  493         int             dev,
  494         dev_flavor_t    flavor,
  495         dev_status_t    data,           /* pointer to OUT array */
  496         natural_t       *count)         /* out */
  497 {
  498         io_return_t     result = D_SUCCESS;
  499         int             unit = minor(dev);
  500 
  501         switch (flavor) {
  502         case TTY_MODEM:
  503                 fix_modem_state(unit, inb(MODEM_STAT(cominfo[unit]->address)));
  504                 *data = commodem[unit];
  505                 *count = 1;
  506                 break;
  507         default:
  508                 result = tty_get_status(&com_tty[unit], flavor, data, count);
  509                 break;
  510         }
  511         return result;
  512 }
  513 
  514 io_return_t
  515 comsetstat(
  516         int             dev,
  517         dev_flavor_t    flavor,
  518         dev_status_t    data,
  519         natural_t       count)
  520 {
  521         io_return_t     result = D_SUCCESS;
  522         int             unit = minor(dev);
  523         struct tty      *tp = &com_tty[unit];
  524 
  525         switch (flavor) {
  526         case TTY_SET_BREAK:
  527                 commctl(tp, TM_BRK, DMBIS);
  528                 break;
  529         case TTY_CLEAR_BREAK:
  530                 commctl(tp, TM_BRK, DMBIC);
  531                 break;
  532         case TTY_MODEM:
  533                 commctl(tp, *data, DMSET);
  534                 break;
  535         default:
  536                 result = tty_set_status(&com_tty[unit], flavor, data, count);
  537                 if (result == D_SUCCESS && flavor == TTY_STATUS)
  538                         comparam(unit);
  539                 return result;
  540         }
  541         return D_SUCCESS;
  542 }
  543 
  544 void comintr(
  545         int unit)
  546 {
  547         register struct tty     *tp = &com_tty[unit];
  548         u_short                 addr = cominfo[unit]->address;
  549         static char             comoverrun = 0;
  550         char                    c, line, intr_id;
  551         int                     line_stat;
  552 
  553         while (! ((intr_id=(inb(INTR_ID(addr))&MASKi)) & 1))
  554             switch (intr_id) { 
  555                 case MODi: 
  556                     /* modem change */
  557                         commodem_intr(unit, inb(MODEM_STAT(addr)));
  558                         break;
  559 
  560                 case TRAi:
  561                         comtimer_state[unit] = 0;
  562                         tp->t_state &= ~(TS_BUSY|TS_FLUSH);
  563                         tt_write_wakeup(tp);
  564                         comstart(tp);
  565                         break;
  566                 case RECi:
  567                 case CTIi:         /* Character timeout indication */
  568                         if (tp->t_state&TS_ISOPEN) {
  569                                 while ((line = inb(LINE_STAT(addr))) & iDR) {
  570                                         c = inb(TXRX(addr));
  571                                         ttyinput(c, tp);
  572                                 }
  573                         } else
  574                                 tt_open_wakeup(tp);
  575                         break;
  576                 case LINi: 
  577                         line_stat = inb(LINE_STAT(addr));
  578 
  579                         if ((line_stat & iPE) &&
  580                             ((tp->t_flags&(EVENP|ODDP)) == EVENP ||
  581                              (tp->t_flags&(EVENP|ODDP)) == ODDP)) {
  582                                 /* parity error */;
  583                         } else  if (line&iOR && !comoverrun) {
  584                                 printf("com%d: overrun\n", unit);
  585                                 comoverrun = 1;
  586                         } else if (line_stat & (iFE | iBRKINTR)) {
  587                                 /* framing error or break */
  588                                 ttyinput(tp->t_breakc, tp);
  589                         }
  590                         break;
  591                 }
  592 }
  593 
  594 static void
  595 comparam(
  596         register int unit)
  597 {
  598         struct tty      *tp = &com_tty[unit];
  599         u_short         addr = (int)tp->t_addr;
  600         spl_t           s = spltty();
  601         int             mode;
  602 
  603         if (tp->t_ispeed == B0) {
  604                 tp->t_state |= TS_HUPCLS;
  605                 outb(MODEM_CTL(addr), iOUT2);
  606                 commodem[unit] = 0;
  607                 splx(s);
  608                 return;
  609         }
  610 
  611         /* Do input buffering */
  612         if (tp->t_ispeed >= B300)
  613                 tp->t_state |= TS_MIN;
  614 
  615         outb(LINE_CTL(addr), iDLAB);
  616         outb(BAUD_LSB(addr), divisorreg[tp->t_ispeed] & 0xff);
  617         outb(BAUD_MSB(addr), divisorreg[tp->t_ispeed] >> 8);
  618 
  619         if (tp->t_flags & (RAW|LITOUT|PASS8))
  620                 mode = i8BITS;
  621         else
  622                 mode = i7BITS | iPEN;
  623         if (tp->t_flags & EVENP)
  624                 mode |= iEPS;
  625         if (tp->t_ispeed == B110)
  626                 /*
  627                  * 110 baud uses two stop bits -
  628                  * all other speeds use one
  629                  */
  630                 mode |= iSTB;
  631 
  632         outb(LINE_CTL(addr), mode);
  633 
  634         outb(INTR_ENAB(addr), iTX_ENAB|iRX_ENAB|iMODEM_ENAB|iERROR_ENAB);
  635         if (comfifo[unit])
  636                 outb(FIFO_CTL(addr), iFIFOENA|iFIFO14CH);
  637         outb(MODEM_CTL(addr), iDTR|iRTS|iOUT2);
  638         commodem[unit] |= (TM_DTR|TM_RTS);
  639         splx(s);
  640 }
  641 
  642 void computc(char ch, int unit)
  643 {
  644         u_short addr = (u_short)(cominfo[unit]->address);
  645 
  646         /* send the char */
  647         outb(addr, ch);
  648 
  649         /* wait for transmitter to empty */
  650         while((inb(LINE_STAT(addr)) & iTHRE) == 0);     
  651 }
  652 
  653 int comgetc(int unit)
  654 {
  655         u_short         addr = (u_short)(cominfo[unit]->address);
  656         spl_t           s = spltty();
  657         natural_t       c;
  658 
  659         while((inb(LINE_STAT(addr)) & iDR) == 0) ;
  660 
  661         c = inb(TXRX(addr));
  662         splx(s);
  663         return c;
  664 }
  665 
  666 void comparm(int unit, int baud, int intr, int mode, int modem)
  667 {
  668         u_short addr = (u_short)(cominfo[unit]->address);
  669         spl_t   s = spltty();
  670 
  671         if (unit != 0 && unit != 1) {
  672                 printf("comparm(unit, baud, mode, intr, modem)\n");
  673                 splx(s);
  674                 return;
  675         }
  676         outb(LINE_CTL(addr), iDLAB);
  677         outb(BAUD_LSB(addr), divisorreg[baud] & 0xff);
  678         outb(BAUD_MSB(addr), divisorreg[baud] >> 8);
  679         outb(LINE_CTL(addr), mode);
  680         outb(INTR_ENAB(addr), intr);
  681         outb(MODEM_CTL(addr), modem);
  682         splx(s);
  683 }
  684 
  685 int comst_1, comst_2, comst_3, comst_4, comst_5 = 14;
  686 
  687 void comstart(
  688         struct tty *tp)
  689 {
  690         char nch;
  691 #if 0
  692         int i;
  693 #endif
  694 
  695         if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) {
  696 comst_1++;
  697                 return;
  698         }
  699         if ((!queue_empty(&tp->t_delayed_write)) &&
  700             (tp->t_outq.c_cc <= TTLOWAT(tp))) {
  701 comst_2++;
  702                 tt_write_wakeup(tp);
  703         }
  704         if (!tp->t_outq.c_cc) {
  705 comst_3++;
  706                 return;
  707         }
  708 
  709 #if 0
  710         i = (comfifo[minor(tp->t_dev)]) ? /*14*/comst_5 : 1;
  711 
  712         tp->t_state |= TS_BUSY;
  713         while (i-- > 0) {
  714                 nch = getc(&tp->t_outq);
  715                 if (nch == -1) break;
  716                 if ((nch & 0200) && ((tp->t_flags & LITOUT) == 0)) {
  717                     timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
  718                     tp->t_state |= TS_TIMEOUT;
  719 comst_4++;
  720                     return;
  721                 }
  722                 outb(TXRX((int)tp->t_addr), nch);
  723         }
  724 #else
  725         nch = getc(&tp->t_outq);
  726         if ((nch & 0200) && ((tp->t_flags & LITOUT) == 0)) {
  727             timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
  728             tp->t_state |= TS_TIMEOUT;
  729 comst_4++;
  730             return;
  731         }
  732         outb(TXRX((int)tp->t_addr), nch);
  733         tp->t_state |= TS_BUSY;
  734 #endif
  735         return;
  736 }
  737 
  738 /* Check for stuck xmitters */
  739 int comtimer_interval = 5;
  740 
  741 void comtimer(void *param)
  742 {
  743         spl_t   s = spltty();
  744         struct tty *tp = com_tty;
  745         int i, nch;
  746 
  747         for (i = 0; i < NCOM; i++, tp++) {
  748                 if ((tp->t_state & TS_ISOPEN) == 0)
  749                         continue;
  750                 if (!tp->t_outq.c_cc)
  751                         continue;
  752                 if (++comtimer_state[i] < 2)
  753                         continue;
  754                 /* Its stuck */
  755 printf("Tty %#x was stuck\n", (vm_offset_t)tp);
  756                 nch = getc(&tp->t_outq);
  757                 outb(TXRX((int)tp->t_addr), nch);
  758         }
  759 
  760         splx(s);
  761         timeout(comtimer, 0, comtimer_interval*hz);
  762 }
  763 
  764 /*
  765  * Set receive modem state from modem status register.
  766  */
  767 void fix_modem_state(
  768         int     unit,
  769         int     modem_stat)
  770 {
  771         int     stat = 0;
  772 
  773         if (modem_stat & iCTS)
  774             stat |= TM_CTS;     /* clear to send */
  775         if (modem_stat & iDSR)
  776             stat |= TM_DSR;     /* data set ready */
  777         if (modem_stat & iRI)
  778             stat |= TM_RNG;     /* ring indicator */
  779         if (modem_stat & iRLSD)
  780             stat |= TM_CAR;     /* carrier? */
  781 
  782         commodem[unit] = (commodem[unit] & ~(TM_CTS|TM_DSR|TM_RNG|TM_CAR))
  783                                 | stat;
  784 }
  785 
  786 /*
  787  * Modem change (input signals)
  788  */
  789 void commodem_intr(
  790         int     unit,
  791         int     stat)
  792 {
  793         int     changed;
  794 
  795         changed = commodem[unit];
  796         fix_modem_state(unit, stat);
  797         stat = commodem[unit];
  798 
  799         /* Assumption: if the other party can handle
  800            modem signals then it should handle all
  801            the necessary ones. Else fix the cable. */
  802 
  803         changed ^= stat;        /* what changed ? */
  804 
  805         if (changed & TM_CTS)
  806                 tty_cts( &com_tty[unit], stat & TM_CTS );
  807 
  808 #if 0
  809         if (changed & TM_CAR)
  810                 ttymodem( &com_tty[unit], stat & TM_CAR );
  811 #endif
  812 
  813 }
  814 
  815 /*
  816  * Set/get modem bits
  817  */
  818 int commctl(
  819         register struct tty     *tp,
  820         int     bits,
  821         int     how)
  822 {
  823         spl_t           s;
  824         int             unit;
  825         vm_offset_t     dev_addr;
  826         register int    b;
  827 
  828         unit = minor(tp->t_dev);
  829 
  830         if (bits == TM_HUP) { /* close line (internal) */
  831                 bits = TM_DTR | TM_RTS;
  832                 how = DMBIC;
  833         }
  834 
  835         if (how == DMGET) return commodem[unit];
  836 
  837         dev_addr = cominfo[unit]->address;
  838 
  839         s = spltty();
  840 
  841         switch (how) {
  842         case DMSET:
  843                 b = bits; break;
  844         case DMBIS:
  845                 b = commodem[unit] | bits; break;
  846         case DMBIC:
  847                 b = commodem[unit] & ~bits; break;
  848         }
  849         commodem[unit] = b;
  850 
  851         if (bits & TM_BRK) {
  852                 if (b & TM_BRK) {
  853                         outb(LINE_CTL(dev_addr), inb(LINE_CTL(dev_addr)) | iSETBREAK);
  854                 } else {
  855                         outb(LINE_CTL(dev_addr), inb(LINE_CTL(dev_addr)) & ~iSETBREAK);
  856                 }
  857         }
  858 
  859 #if 0
  860         /* do I need to do something on this ? */
  861         if (bits & TM_LE) {     /* line enable */
  862         }
  863 #endif
  864 #if 0
  865         /* Unsupported */
  866         if (bits & TM_ST) {     /* secondary transmit */
  867         }
  868         if (bits & TM_SR) {     /* secondary receive */
  869         }
  870 #endif
  871         if (bits & (TM_DTR|TM_RTS)) {   /* data terminal ready, request to send */
  872                 how = iOUT2;
  873                 if (b & TM_DTR) how |= iDTR;
  874                 if (b & TM_RTS) how |= iRTS;
  875                 outb(MODEM_CTL(dev_addr), how);
  876         }
  877 
  878         splx(s);
  879 
  880         /* the rest are inputs */
  881         return commodem[unit];
  882 }
  883 
  884 void comstop(
  885         register struct tty *tp,
  886         int     flags)
  887 {
  888         if ((tp->t_state & TS_BUSY) && (tp->t_state & TS_TTSTOP) == 0)
  889             tp->t_state |= TS_FLUSH;
  890 }
  891 
  892 /*
  893  *
  894  * Code to be called from debugger.
  895  *
  896  */
  897 void compr_addr(int addr)
  898 {
  899         /* The two line_stat prints may show different values, since
  900         *  touching some of the registers constitutes changing them.
  901         */
  902         printf("LINE_STAT(%x) %x\n",
  903                 LINE_STAT(addr), inb(LINE_STAT(addr)));
  904 
  905         printf("TXRX(%x) %x, INTR_ENAB(%x) %x, INTR_ID(%x) %x, LINE_CTL(%x) %x,\n\
  906 MODEM_CTL(%x) %x, LINE_STAT(%x) %x, MODEM_STAT(%x) %x\n",
  907         TXRX(addr),      inb(TXRX(addr)),
  908         INTR_ENAB(addr), inb(INTR_ENAB(addr)),
  909         INTR_ID(addr),   inb(INTR_ID(addr)),
  910         LINE_CTL(addr),  inb(LINE_CTL(addr)),
  911         MODEM_CTL(addr), inb(MODEM_CTL(addr)),
  912         LINE_STAT(addr), inb(LINE_STAT(addr)),
  913         MODEM_STAT(addr),inb(MODEM_STAT(addr)));
  914 }
  915 
  916 int compr(int unit)
  917 {
  918         compr_addr(cominfo[unit]->address);
  919         return(0);
  920 }
  921 
  922 int rcline = -1;
  923 int rcbaud = B9600;
  924 void comrc_put(
  925         int     ch)
  926 {
  927     static int          opened = 0;
  928     u_short             addr;
  929 
  930     if (cominfo[rcline] == 0) return;
  931 
  932     addr = (u_short)(cominfo[rcline]->address);
  933 
  934     if (!opened) {      /* whap down chip config for rconsole */
  935         int     mode = i7BITS | iPEN;
  936 
  937         opened = 1;
  938         outb(LINE_CTL(addr), iDLAB);
  939         outb(BAUD_LSB(addr), divisorreg[rcbaud] & 0xff);
  940         outb(BAUD_MSB(addr), divisorreg[rcbaud] >>8);
  941         outb(LINE_CTL(addr), mode);
  942         outb(INTR_ENAB(addr), 0);
  943         outb(MODEM_CTL(addr), iDTR|iRTS|iOUT2);
  944     }
  945 
  946     /* wait for transmitter to empty */
  947     while((inb(LINE_STAT(addr)) & iTHRE) == 0); 
  948     /* send the char */
  949     outb(addr, ch);
  950 }
  951 
  952 int comrc_may(
  953         boolean_t       wait)
  954 {
  955     unsigned char       c;
  956     u_short             addr;
  957 
  958     if (cominfo[rcline] == 0) return -1;
  959 
  960     addr = (u_short)(cominfo[rcline]->address);
  961 
  962     if ((inb(LINE_STAT(addr)) & iDR) == 0) {
  963             return -1;
  964     }
  965 
  966     c = inb(TXRX(addr));
  967     return (c & 0x7f);
  968 }
  969 
  970 int
  971 comrc_get(
  972         boolean_t       wait)
  973 {
  974     unsigned char       c;
  975     u_short             addr;
  976 
  977 
  978     addr = (u_short)(cominfo[rcline]->address);
  979 
  980     while((inb(LINE_STAT(addr)) & iDR) == 0) {
  981         if (!wait)
  982             return -1;
  983     }
  984 
  985     c = inb(TXRX(addr));
  986     return (c & 0x7f);
  987 }
  988 
  989 #endif  /* NCOM */

Cache object: cbea28b23718711984658440ebcd6ff4


[ 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.