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/ipsc/usm.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  * 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  * Copyright 1988, 1989, 1990, 1991 by Intel Corporation,
   28  * Santa Clara, California.
   29  * 
   30  *                          All Rights Reserved
   31  * 
   32  * Permission to use, copy, modify, and distribute this software and its
   33  * documentation for any purpose and without fee is hereby granted,
   34  * provided that the above copyright notice appears in all copies and that
   35  * both the copyright notice and this permission notice appear in
   36  * supporting documentation, and that the name of Intel not be used in
   37  * advertising or publicity pertaining to distribution of the software
   38  * without specific, written prior permission.
   39  * 
   40  * INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
   41  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
   42  * SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
   43  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
   44  * PROFITS, WHETHER IN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS
   45  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
   46  * THIS SOFTWARE.
   47  */
   48 /*
   49  *  Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
   50  *  Cupertino, California.
   51  * 
   52  *              All Rights Reserved
   53  * 
   54  *   Permission to use, copy, modify, and distribute this software and
   55  * its documentation for any purpose and without fee is hereby
   56  * granted, provided that the above copyright notice appears in all
   57  * copies and that both the copyright notice and this permission notice
   58  * appear in supporting documentation, and that the name of Olivetti
   59  * not be used in advertising or publicity pertaining to distribution
   60  * of the software without specific, written prior permission.
   61  * 
   62  *   OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
   63  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
   64  * IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
   65  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   66  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
   67  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
   68  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   69  */
   70 /*
   71  * HISTORY
   72  * $Log:        usm.c,v $
   73  * Revision 2.7  91/12/10  16:32:35  jsb
   74  *      Fixes from Intel
   75  *      [91/12/10  15:33:41  jsb]
   76  * 
   77  * Revision 2.3  91/09/04  11:28:22  jsb
   78  *      This is Intel's most recent usm.c, with my JUSTHACKIT code added
   79  *      and enabled since things still act funny without it.
   80  *      [91/09/04  08:39:09  jsb]
   81  * 
   82  * Revision 2.2  91/06/18  20:52:42  jsb
   83  *      First checkin. Just a hack until ipsc/usm.c gets merged again.
   84  *      [91/06/18  19:04:14  jsb]
   85  * 
   86  * Revision 2.3  90/12/22  00:00:00  prp
   87  *      Change to use slot number
   88  * 
   89  * Revision 2.2  90/12/04  14:50:53  jsb
   90  *      Eliminated compiler warning.
   91  *      [90/12/04  12:18:23  jsb]
   92  * 
   93  *      Merged (and mostly replaced) with i386ipsc version.
   94  *      Unmerged parts are conditionalized with JUSTHACKIT;
   95  *      the i386ipsc seems to need this code.
   96  *      [90/12/04  10:46:15  jsb]
   97  * 
   98  *      First checkin.
   99  *      [90/12/03  21:57:51  jsb]
  100  * 
  101  */
  102 
  103 #include <mach_kdb.h>
  104 #include <sys/types.h>
  105 #include <device/conf.h>
  106 #include <device/tty.h>
  107 #include <device/io_req.h>
  108 #include <device/errno.h>
  109 #include <device/cirbuf.h>
  110 
  111 #define JUSTHACKIT      0
  112 
  113 #if i860
  114 #include <i860ipsc/nodehw.h>
  115 #endif
  116 #include <ipsc/usm.h>
  117 
  118 /* These magic values from NX's kt.h */
  119 #define KT_RDY          0x81
  120 #define KT_HOLD         0x82
  121 #define KT_SELECT       0x83
  122 #define KT_KDB          0x84
  123 
  124 /* Multiplex states */
  125 #define NOT_WAITING             0
  126 #define WAITING_FOR_KT_RDY      1
  127 #define WAITING_FOR_SELECT      2
  128 
  129 extern void     timeout(), ttrstrt();
  130 int     usmstop(), usmgetstat(), usmsetstat();
  131 
  132 
  133 /*
  134  * Switches for polling vs. interrupt.
  135  */
  136 static int      polling = 0;
  137 static int      interrupts_on = 0;
  138 
  139 extern void     splx();
  140 extern int      spltty();
  141 extern int      soft_pic_enable(), soft_pic_disable();
  142 
  143 struct tty      usm_tty;
  144 static int      initialized = 0;
  145 
  146 /* variables below allow USM serial line to be shared by more than one node */
  147 static boolean_t selected = FALSE; /* is serial line selected for this node */
  148 static int state = NOT_WAITING; /* are we waiting for special characters */
  149 
  150 /* variables for polled IO */
  151 #define UNSBUF          2048
  152 static char     unselbuf[UNSBUF]; /* buffer to hold output when unselected */
  153 static char     stray[64];      /* characters rcv'd while waiting for KT_RDY */
  154 static struct cirbuf conbuf;    /* circular buffer for output */
  155 static char     column = 0;     /* for tab expansion */
  156 static short    stray_count = 0;
  157 
  158 extern ipsc_slot;
  159 
  160 /* forward declarations */
  161 static int enable_interrupts();
  162 static int disable_interrupts();
  163 int usmstart();
  164 int usmstop();
  165 
  166 #if     i860
  167 int     led_console = 0;
  168 int     led_usm = 0;
  169 #endif  i860
  170 
  171 /*
  172  *      Initialize the console.
  173  */
  174 cninit()
  175 {
  176         if (!initialized) {
  177                 /*
  178                  * I'd like to use cb_alloc(&conbuf, UNSBUF),
  179                  * but kalloc() hasn't been initialized yet.
  180                  */
  181                 conbuf.c_start = unselbuf;
  182                 conbuf.c_end = unselbuf + UNSBUF;
  183                 conbuf.c_cf = unselbuf;
  184                 conbuf.c_cl = unselbuf;
  185                 conbuf.c_cc = 0;
  186 
  187                 uart_hardreset();
  188                 disable_interrupts();
  189 
  190                 while (!inb(iUSM_GIR) & 1) {
  191                         (void) inb(iUSM_LSR);
  192                         (void) inb(iUSM_RXD);
  193                         (void) inb(iUSM_MSR);
  194                 }
  195 
  196                 column = 0;
  197                 polling = 1;
  198                 initialized++;
  199         }
  200 }
  201 
  202 
  203 usmopen(dev, flag, ior)
  204 dev_t           dev;
  205 int             flag;
  206 io_req_t        ior;
  207 {
  208         int             s;
  209         struct  tty *   tp;
  210         int             unit;
  211         io_return_t     ret_val;
  212 
  213         unit = minor(dev);
  214         if (unit != 0) {
  215                 /* we only support a single usm device */
  216                 return(ENXIO);
  217         }
  218 
  219         tp = &usm_tty;
  220         s = spltty();
  221 
  222         if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0) {
  223                 ttychars(tp);
  224                 tp->t_addr = (caddr_t) tp;
  225                 tp->t_dev = dev;
  226                 tp->t_oproc = usmstart;
  227                 tp->t_stop = usmstop;
  228                 tp->t_getstat = usmgetstat;
  229                 tp->t_setstat = usmsetstat;
  230                 tp->t_ispeed = B9600;
  231                 tp->t_ospeed = B9600;
  232                 tp->t_flags = ODDP|EVENP|ECHO|CRMOD;
  233                 tp->t_state &= ~TS_BUSY;
  234 #if i860
  235                 uart_softreset();
  236                 uart_clkstart();
  237 #endif
  238                 polling = 0;
  239                 enable_interrupts();
  240         }
  241         if ((tp->t_state & TS_ISOPEN) == 0)
  242                 usmparam(unit);
  243         tp->t_state |= TS_CARR_ON;
  244 
  245         splx(s);
  246 
  247         ret_val = char_open(dev, tp, flag, ior);
  248         return ret_val;
  249 }
  250 
  251 
  252 int usmclose(dev, flag)
  253 int     dev;
  254 int     flag;
  255 {
  256         struct  tty     *tp;
  257         int     s;
  258 
  259         tp = &usm_tty;
  260 
  261         s = spltty();
  262         ttyclose(tp);
  263         disable_interrupts();
  264         polling = 1;
  265         splx(s);
  266 
  267         return 0;
  268 
  269 }
  270 
  271 
  272 int usmread(dev, ior)
  273 int     dev;
  274 io_req_t ior;
  275 {
  276         int     r;
  277 
  278         r = char_read(&usm_tty, ior);
  279         return r;
  280 }
  281 
  282 
  283 int usmwrite(dev, ior)
  284 int     dev;
  285 io_req_t ior;
  286 {
  287         int     r;
  288 
  289         r = char_write(&usm_tty, ior);
  290         return r;
  291 }
  292 
  293 
  294 usmportdeath(dev, port)
  295 dev_t           dev;
  296 mach_port_t     port;
  297 {
  298         return (tty_portdeath(&usm_tty, port));
  299 }
  300 
  301 
  302 /*ARGSUSED*/
  303 io_return_t usmgetstat(dev, flavor, data, count)
  304 dev_t           dev;
  305 int             flavor;
  306 int             *data;          /* pointer to OUT array */
  307 unsigned int    *count;         /* OUT */
  308 {
  309         return (tty_get_status(&usm_tty, flavor, data, count));
  310 }
  311 
  312 
  313 /*ARGSUSED*/
  314 io_return_t usmsetstat(dev, flavor, data, count)
  315 dev_t           dev;
  316 int             flavor;
  317 int             *data;
  318 unsigned int    count;
  319 {
  320         io_return_t     result = D_SUCCESS;
  321         int             unit = minor(dev);
  322 
  323         result = tty_set_status(&usm_tty, flavor, data, count);
  324         if (result == D_SUCCESS && flavor == TTY_STATUS)
  325                 usmparam(unit);
  326         return (result);
  327 }
  328 
  329 
  330 usmparam(unit)
  331 register int unit;
  332 {
  333         /* we don't need no stinking params... */
  334         return;
  335 }
  336 
  337 
  338 /*
  339  * we're only called if there was an RX interrupt from the usm...
  340  * ...but that can mean more than one thing...
  341  */
  342 usmintr(unit)
  343 int     unit;
  344 {
  345         register struct tty *tp;
  346         register int    c;
  347         int     s;
  348 #if     i860
  349         extern int intr_debug;
  350 #endif  i860
  351 
  352         if (polling) {
  353                 return;
  354         }
  355 
  356 #if     i860
  357         if (intr_debug) led_char('u');
  358 #endif  i860
  359 
  360         tp = &usm_tty;
  361         if (!(tp->t_state & TS_ISOPEN)) {
  362                 tt_open_wakeup(tp);
  363                 return;
  364         }
  365 
  366 #if     i860
  367         if (intr_debug) led_char('R');
  368 #endif  i860
  369 
  370         c = inb(iUSM_RXD) & 0xff;
  371 
  372         if (state == WAITING_FOR_SELECT) {
  373                 state = NOT_WAITING;
  374                 if ((c & 0x7F) == ipsc_slot || (c & 0x80)) {
  375                         selected = TRUE;
  376                 } else {
  377                         selected = FALSE;
  378                 }
  379         } else if (c == KT_SELECT) {
  380                 state = WAITING_FOR_SELECT;
  381         } else if (! selected) {
  382                 ;
  383         } else if (c == KT_RDY) {
  384                 if (state == WAITING_FOR_KT_RDY) {
  385                         /*
  386                          * getting a KT_RDY is kind of like getting
  387                          * a TX interrupt from a *normal* uart.
  388                          */
  389                         state = NOT_WAITING;
  390                         tp->t_state &= ~TS_BUSY;
  391                 } else {
  392                         outb(iUSM_TXD, KT_HOLD);
  393                 }
  394         } else if (c == KT_KDB) {
  395                 kdb_kintr();
  396         } else {
  397                 if (tp->t_state&TS_ISOPEN) {
  398                         ttyinput(c, tp);
  399                 } else {
  400                         tt_open_wakeup(tp);
  401                 }
  402         }
  403 
  404         if (selected) {
  405                 usmstart(tp);
  406         }
  407 
  408 #if     i860
  409         if (intr_debug) led_char(';');
  410 #endif  i860
  411 }
  412 
  413 
  414 #if     JUSTHACKIT
  415 int kt_rdy_deficit = 0;
  416 #define MAX_KT_RDY_DEFICIT      16
  417 
  418 justhackit(c, tp)
  419         u_char c;
  420         struct tty *tp;
  421 {
  422         while ((inb(iUSM_LSR) & iTHRE) == 0) {
  423                 continue;
  424         }
  425         outb(iUSM_TXD, c);
  426         if (++kt_rdy_deficit < MAX_KT_RDY_DEFICIT) {
  427                 return;
  428         }
  429         while (kt_rdy_deficit > 0) {
  430                 while((inb(iUSM_LSR) & iDR) == 0) {
  431                         continue;
  432                 }
  433                 c = inb(iUSM_RXD) & 0xff;
  434                 if (c == KT_RDY) {
  435                         kt_rdy_deficit--;
  436                         break;
  437                 }
  438                 if (tp) {
  439                         (*linesw[tp->t_line].l_rint)(c, tp);
  440                 } else if (stray_count < sizeof(stray)) {
  441                         stray[stray_count++] = c;
  442                 }
  443         }
  444 }
  445 #endif
  446 
  447 
  448 usmstart(tp)
  449 struct tty *tp;
  450 {
  451         char    nch;
  452 
  453         if (polling) {
  454                 return;
  455         }
  456         if (!selected) {
  457                 return;
  458         }
  459         if (state != NOT_WAITING) {
  460                 return;
  461         }
  462         if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) {
  463                 return;
  464         }
  465 #if     JUSTHACKIT
  466         while (tp->t_outq.c_cc > 0 && (nch=getc(&tp->t_outq)) != -1) {
  467                 justhackit(nch, tp);
  468         }
  469         tp->t_state &= ~TS_BUSY;
  470         tt_write_wakeup(tp);
  471 #else   JUSTHACKIT
  472         if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
  473                 tt_write_wakeup(tp);
  474         }
  475         if (!tp->t_outq.c_cc) {
  476                 return;
  477         }
  478         nch = getc(&tp->t_outq);
  479         if ((tp->t_flags & LITOUT) == 0 && (nch & 0200)) {
  480                 timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
  481                 tp->t_state |= TS_TIMEOUT;
  482                 return;
  483         }
  484 #if     i860
  485         if (led_usm) led_char(nch);
  486 #endif
  487         outb(iUSM_TXD, nch);
  488         state = WAITING_FOR_KT_RDY;
  489         tp->t_state |= TS_BUSY;
  490         return;
  491 #endif  JUSTHACKIT
  492 }
  493 
  494 
  495 usmstop(tp, flags)
  496 register struct tty *tp;
  497 int     flags;
  498 {
  499         if ((tp->t_state & TS_BUSY) && (tp->t_state & TS_TTSTOP) == 0)
  500                 tp->t_state |= TS_FLUSH;
  501 }
  502 
  503 
  504 dumpunsel()
  505 {
  506         int     c;
  507 
  508         while ((c = getc(&conbuf)) != -1) {
  509                 cnputc(c);
  510         }
  511 }
  512 
  513 
  514 /*
  515  * This procedure provides the console out routine for the
  516  * kernel's putchar (printf) routine.  When output for this 
  517  * node is selected, it polls the UART until the TX Ready bit
  518  * is set and then outputs the character. If IO is not selected
  519  * then the character is saved in a buffer so that it can be
  520  * written later.
  521  */
  522 cnputc(c)
  523         char    c;
  524 {
  525         unsigned char x;
  526         int s, i, was;
  527 
  528         if (!initialized) {
  529                 cninit();
  530         }
  531 
  532         switch (c) {
  533         case '\n':
  534                 cnputc('\r');
  535         case '\r':
  536                 column = 0;
  537                 break;
  538         case '\t':
  539                 do {
  540                         cnputc(' ');
  541                 } while (column & 07);
  542                 return(c);
  543         case '\b':
  544                 if (column)
  545                         column--;
  546                 break;
  547         default:
  548                 column++;
  549                 break;
  550 
  551         }
  552 
  553 #if     i860
  554         if (led_console) led_char(c);
  555 #endif  i860
  556 
  557         if (!selected) {
  558                 if (putc(c, &conbuf)) {
  559                         int     drop = getc(&conbuf);
  560                         (void) putc(c, &conbuf);
  561                 }
  562                 return (c);
  563         }
  564 
  565 #if     JUSTHACKIT
  566         justhackit(c, 0);
  567 #else   JUSTHACKIT
  568 
  569         was = usm2cn();
  570         outb(iUSM_TXD, c);
  571         for (;;) {
  572                 while((inb(iUSM_LSR) & iDR) == 0);
  573                 if ((x = inb(iUSM_RXD)) == KT_RDY) {
  574                         break;
  575                 } else if (stray_count < sizeof(stray)) {
  576                         stray[stray_count++] = x;
  577                 }
  578                 outb(iUSM_TXD, c);
  579         }
  580         cn2usm(was);
  581 
  582 #endif  JUSTHACKIT
  583 
  584         return(c);
  585 }
  586 
  587 
  588 usm2cn()
  589 {
  590         int     was, s;
  591 
  592         was = interrupts_on;
  593         if (was) {
  594                 s = spltty();
  595                 /*
  596                  * we need to let the interrupt driven state machine
  597                  * kick around until we can jump in.
  598                  */
  599                 while (state != NOT_WAITING) {
  600 #if     i860
  601                         /*led_printf("usm2cn: state = %d\n", state);*/
  602 #endif  i860
  603                         splx(s);
  604                         s = spltty();
  605                 }
  606                 disable_interrupts();
  607                 polling = 1;
  608                 splx(s);
  609         }
  610 
  611         return was;
  612 }
  613 
  614 
  615 cn2usm(was)
  616 int     was;
  617 {
  618         if (was) {
  619                 polling = 0;
  620                 enable_interrupts();
  621         }
  622 }
  623 
  624 
  625 cnswitch(wait)
  626 boolean_t       wait;
  627 {
  628         int     c, was;
  629 
  630         was = usm2cn();
  631         c = cndogetc(wait);
  632         cn2usm(was);
  633 
  634         return c;
  635 }
  636 
  637 
  638 cngetc()
  639 {
  640         return (cnswitch(TRUE));
  641 }
  642 
  643 
  644 cnmaygetc()
  645 {
  646         return (cnswitch(FALSE));
  647 }
  648 
  649 
  650 /*
  651  * This procedure reads a character from the console. It returns
  652  * -1 if there is no character in the UART receive buffer or if
  653  * this node is not selected for IO.
  654  *
  655  * Note that interrupts must be disabled so that usmintr doesn't
  656  * get the character first.
  657  */
  658 cndogetc(wait)
  659         boolean_t       wait;
  660 {
  661         int i, c, s, was;
  662 
  663         assert(interrupts_on == 0);
  664 
  665         if (stray_count > 0) {
  666                 c = stray[0];
  667                 for (i = 1; i < stray_count; i++) {
  668                         stray[i - 1] = stray[i]; /* lazyness */
  669                 }
  670                 stray_count--;
  671         } else {
  672                 do {
  673                         c = uart_getc();
  674                         if (c == KT_RDY)  {
  675                                 if (selected) {
  676                                         outb(iUSM_TXD, KT_HOLD);
  677                                 }
  678                                 c = -1;
  679                         } else if (c == KT_SELECT) {
  680         
  681                                 do { c = uart_getc(); } while (c == -1);
  682                                 if (((c & 0x7F) == ipsc_slot) || (c & 0x80)) {
  683                                         selected = TRUE;
  684                                         dumpunsel();
  685                                 } else {
  686                                         selected = FALSE;
  687                                 }
  688                                 c = -1;
  689                         } else if (! selected) {
  690                                 c = -1;
  691                         } else if (c == KT_KDB) {
  692 #if     MACH_KDB
  693                                 kdb_kintr();
  694 #endif  MACH_KDB
  695                                 c = -1;
  696                         }
  697         
  698                 } while (wait && (c == -1));
  699         }
  700         if (c == '\r')
  701                 c = '\n';
  702 
  703         if (c != -1) {
  704                 c &= 0177;
  705         }
  706 
  707         return(c);
  708 }
  709 
  710 
  711 /* Called by kdb to switch keyboard from polled to interrupt */
  712 cnpollc(on)
  713         boolean_t       on;
  714 {
  715         static int      usm_interrupt_state = 0;
  716         static int      usm_interrupt_state_valid = 0;
  717         int     s;
  718 
  719         s = sploff();
  720         if (on) {
  721                 usm_interrupt_state = interrupts_on;
  722                 usm_interrupt_state_valid = 1;
  723                 disable_interrupts();
  724                 polling = 1;
  725         }
  726         else {
  727                 assert(usm_interrupt_state_valid != 0);
  728                 if (usm_interrupt_state) {
  729                         usm_interrupt_state = 0;
  730                         polling = 0;
  731                         enable_interrupts();
  732                 }
  733         }
  734         splon(s);
  735 }
  736 
  737 
  738 static disable_interrupts()
  739 {
  740         int     s;
  741 
  742         s = sploff();
  743 
  744         /* switch to bank 0, 8250 compatibility */
  745         outb(iUSM_BANK, iBANK0);
  746 
  747         /* disable interrupts */
  748         outb(iUSM_GER, inb(iUSM_GER) & ~(iRX_ENAB | iTX_ENAB));
  749         interrupts_on = FALSE;
  750 
  751         splon(s);
  752 }
  753 
  754 static enable_interrupts()
  755 {
  756         int     s;
  757 
  758         s = sploff();
  759 
  760         /* switch to bank 0, 8250 compatibility */
  761         outb(iUSM_BANK, iBANK0);
  762 
  763         /* enable interrupts */
  764         outb(iUSM_GER, inb(iUSM_GER) | iRX_ENAB);
  765 
  766         interrupts_on = TRUE;
  767 
  768 #if     i860
  769         soft_pic_enable(SERIAL_INT_MASK);
  770 #endif  i860
  771 
  772         splon(s);
  773 }
  774 
  775 
  776 /*
  777  * Hard reset the uart.
  778  * Not really a hardware reset, but it does send a software reset command
  779  * to the uart (which is more "firm" than reprogramming a bunch of registers).
  780  */
  781 uart_hardreset()
  782 {
  783         uart_reset(1);
  784 }
  785 
  786 
  787 /*
  788  * Reprogram the uart without zapping some of the timer registers
  789  * that are used in uart_clkstart().
  790  */
  791 uart_softreset()
  792 {
  793         uart_reset(0);
  794 }
  795 
  796 
  797 /*
  798  * Program the uart to a known state.
  799  * If a hard reset, it fakes it with a software reset command (which is
  800  * slightly more firm than simply programming a few of the registers).
  801  */
  802 uart_reset(hard)
  803         int     hard;
  804 {
  805         int     b;
  806 
  807         if (hard) {
  808                 outb(iUSM_BANK, iBANK1); /* move to work bank (bank 1) */
  809                 outb(iUSM_ICM, 0x10);   /* do a SW reset usmmand */
  810                 uart_delay();
  811                 uart_delay();
  812                 uart_delay();
  813                 uart_delay();
  814         }
  815         else {
  816                 outb(iUSM_BANK, iBANK0);
  817         }
  818 
  819         /*
  820          * Set timer B count for 100 Hz
  821          */
  822         b = 25000;
  823 
  824         /* we are now in bank 0 (because a SW reset usmmand puts us there) */
  825         outb(iUSM_LCR, 0x80);   /* turn on DLAB bit to load BAL & BAH regs */
  826         outb(iUSM_BAL, 0x01);   /* set duty cycle of baud rate generator A */
  827         outb(iUSM_BAH, 0x00);   /* same as external serial clock */
  828         outb(iUSM_BANK, iBANK3); /* Switch to bank 3 */
  829         outb(iUSM_BBL, b & 0xff);       /* set baud rate generator B */
  830         outb(iUSM_BBH, b >> 8);
  831         outb(iUSM_BANK, iBANK0); /* Switch back to bank 0 */
  832         outb(iUSM_LCR, 0x03);   /* 1 stop, 8 bits, non-parity, clear DLAB */
  833         outb(iUSM_MCR, 0x00);   /* clear modem I/O pins status register */
  834 /*hmm*/ outb(iUSM_GER, 0x28);   /* Enable modem, timer interrupt */
  835 
  836         outb(iUSM_BANK, iBANK2); /* move to general config (bank 2) */
  837         outb(iUSM_FMD, 0x00);   /* normal */
  838         outb(iUSM_RMD, 0x00);   /* normal */
  839         outb(iUSM_TMD, 0xC0);   /* manual mode, 4/4 stop bits */
  840         outb(iUSM_IMD, 0x08);   /* auto interrupt ack, FIFO depth 4 bytes */
  841         outb(iUSM_RIE, 0x00);   /* disable receive interrupts */
  842 
  843         outb(iUSM_BANK, iBANK3); /* Switch to bank 3 */
  844         outb(iUSM_CLCF, 0x50);  /* X16 mode, BRG A is clock source */
  845         outb(iUSM_BACF, 0x44);  /* SCLK pin is clk src, enables BRG mode */
  846         outb(iUSM_BBCF, 0x00);  /* timer mode (system clock input) */
  847         outb(iUSM_MIE, 0x09);   /* enable CTS/, DCD/ change interrupts */
  848         outb(iUSM_TMIE, 0x02);  /* enable timer B interrupts */
  849         outb(iUSM_PMD, 0xA0);   /* make DSR/, DCD/ inputs */
  850 
  851         outb(iUSM_BANK, iBANK1); /* move to work bank (bank 1) */
  852         outb(iUSM_RCM, 0xB4);   /* enables reception of characters */
  853         outb(iUSM_TCM, 0x0E);   /* enables transmission of characters */
  854         outb(iUSM_ICM, 0x0C);   /* status clear, int acknowledge */
  855 
  856         outb(iUSM_BANK, iBANK0); /* move to compat bank (bank 0) */
  857 }
  858 
  859 
  860 /*
  861  * Retrigger timer B to interrupt.
  862  * It assumes that the timer value set in uart_reset() is
  863  * still intact.
  864  */
  865 uart_clkstart()
  866 {
  867         int     s;
  868 
  869         s = sploff();
  870         outb(iUSM_BANK, iBANK1);
  871         inb(iUSM_TMST);
  872         outb(iUSM_TMCR, 0x22);
  873         outb(iUSM_BANK, iBANK0);
  874 
  875 #if     i860
  876         soft_pic_enable(SERIAL_INT_MASK);
  877 #endif  i860
  878 
  879         splon(s);
  880 }
  881 
  882 
  883 #if i386
  884 int uart_delay()
  885 {
  886         volatile long time = 64000;
  887 
  888         while (time--);
  889 }
  890 #endif i386
  891 
  892 #if i860
  893 /*
  894  * uart_delay allows the serial chip to recover from read or write
  895  */
  896 uart_delay()
  897 {
  898         while ((inb(COUNTER_PORT) & 0x20) == 0);
  899         while ((inb(COUNTER_PORT) & 0x20) != 0);
  900 }
  901 #endif
  902 
  903 /*
  904  * Pull in a character from the uart.
  905  * No interrupts while checking...
  906  */
  907 uart_getc()
  908 {
  909         int     s, c;
  910 
  911         s = sploff();
  912         if ((inb(iUSM_LSR) & iDR) == 0) {
  913                 splon(s);
  914                 return (-1);
  915         }
  916         c = inb(iUSM_RXD) & 0xff;
  917         splon(s);
  918 
  919         return (c);
  920 }
  921 
  922 
  923 #if 0
  924 /*
  925  * Push a character out of the uart.
  926  * No interrupts while waiting for TX ready...
  927  */
  928 uart_putc(c)
  929         char    c;
  930 {
  931         int     s = sploff();
  932 
  933         while ((inb(iUSM_LSR) & iTHRE) == 0);
  934         outb(iUSM_TXD, c);
  935 
  936         splon(s);
  937 
  938         return (c);
  939 }
  940 #endif 0

Cache object: 68777d601a3e0efb6c4c1cd9e6c6d79a


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