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

Cache object: d23b58219505516e4278d0a9ab63480a


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