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/pc/uarti8250.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 #include "u.h"
    2 #include "../port/lib.h"
    3 #include "mem.h"
    4 #include "dat.h"
    5 #include "fns.h"
    6 #include "io.h"
    7 #include "../port/error.h"
    8 
    9 /*
   10  * 8250 UART and compatibles.
   11  */
   12 enum {
   13         Uart0           = 0x3F8,        /* COM1 */
   14         Uart0IRQ        = 4,
   15         Uart1           = 0x2F8,        /* COM2 */
   16         Uart1IRQ        = 3,
   17 
   18         UartFREQ        = 1843200,
   19 };
   20 
   21 enum {                                  /* I/O ports */
   22         Rbr             = 0,            /* Receiver Buffer (RO) */
   23         Thr             = 0,            /* Transmitter Holding (WO) */
   24         Ier             = 1,            /* Interrupt Enable */
   25         Iir             = 2,            /* Interrupt Identification (RO) */
   26         Fcr             = 2,            /* FIFO Control (WO) */
   27         Lcr             = 3,            /* Line Control */
   28         Mcr             = 4,            /* Modem Control */
   29         Lsr             = 5,            /* Line Status */
   30         Msr             = 6,            /* Modem Status */
   31         Scr             = 7,            /* Scratch Pad */
   32         Dll             = 0,            /* Divisor Latch LSB */
   33         Dlm             = 1,            /* Divisor Latch MSB */
   34 };
   35 
   36 enum {                                  /* Ier */
   37         Erda            = 0x01,         /* Enable Received Data Available */
   38         Ethre           = 0x02,         /* Enable Thr Empty */
   39         Erls            = 0x04,         /* Enable Receiver Line Status */
   40         Ems             = 0x08,         /* Enable Modem Status */
   41 };
   42 
   43 enum {                                  /* Iir */
   44         Ims             = 0x00,         /* Ms interrupt */
   45         Ip              = 0x01,         /* Interrupt Pending (not) */
   46         Ithre           = 0x02,         /* Thr Empty */
   47         Irda            = 0x04,         /* Received Data Available */
   48         Irls            = 0x06,         /* Receiver Line Status */
   49         Ictoi           = 0x0C,         /* Character Time-out Indication */
   50         IirMASK         = 0x3F,
   51         Ifena           = 0xC0,         /* FIFOs enabled */
   52 };
   53 
   54 enum {                                  /* Fcr */
   55         FIFOena         = 0x01,         /* FIFO enable */
   56         FIFOrclr        = 0x02,         /* clear Rx FIFO */
   57         FIFOtclr        = 0x04,         /* clear Tx FIFO */
   58         FIFO1           = 0x00,         /* Rx FIFO trigger level 1 byte */
   59         FIFO4           = 0x40,         /*      4 bytes */
   60         FIFO8           = 0x80,         /*      8 bytes */
   61         FIFO14          = 0xC0,         /*      14 bytes */
   62 };
   63 
   64 enum {                                  /* Lcr */
   65         Wls5            = 0x00,         /* Word Length Select 5 bits/byte */
   66         Wls6            = 0x01,         /*      6 bits/byte */
   67         Wls7            = 0x02,         /*      7 bits/byte */
   68         Wls8            = 0x03,         /*      8 bits/byte */
   69         WlsMASK         = 0x03,
   70         Stb             = 0x04,         /* 2 stop bits */
   71         Pen             = 0x08,         /* Parity Enable */
   72         Eps             = 0x10,         /* Even Parity Select */
   73         Stp             = 0x20,         /* Stick Parity */
   74         Brk             = 0x40,         /* Break */
   75         Dlab            = 0x80,         /* Divisor Latch Access Bit */
   76 };
   77 
   78 enum {                                  /* Mcr */
   79         Dtr             = 0x01,         /* Data Terminal Ready */
   80         Rts             = 0x02,         /* Ready To Send */
   81         Out1            = 0x04,         /* no longer in use */
   82         Ie              = 0x08,         /* IRQ Enable */
   83         Dm              = 0x10,         /* Diagnostic Mode loopback */
   84 };
   85 
   86 enum {                                  /* Lsr */
   87         Dr              = 0x01,         /* Data Ready */
   88         Oe              = 0x02,         /* Overrun Error */
   89         Pe              = 0x04,         /* Parity Error */
   90         Fe              = 0x08,         /* Framing Error */
   91         Bi              = 0x10,         /* Break Interrupt */
   92         Thre            = 0x20,         /* Thr Empty */
   93         Temt            = 0x40,         /* Tramsmitter Empty */
   94         FIFOerr         = 0x80,         /* error in receiver FIFO */
   95 };
   96 
   97 enum {                                  /* Msr */
   98         Dcts            = 0x01,         /* Delta Cts */
   99         Ddsr            = 0x02,         /* Delta Dsr */
  100         Teri            = 0x04,         /* Trailing Edge of Ri */
  101         Ddcd            = 0x08,         /* Delta Dcd */
  102         Cts             = 0x10,         /* Clear To Send */
  103         Dsr             = 0x20,         /* Data Set Ready */
  104         Ri              = 0x40,         /* Ring Indicator */
  105         Dcd             = 0x80,         /* Data Set Ready */
  106 };
  107 
  108 typedef struct Ctlr {
  109         int     io;
  110         int     irq;
  111         int     tbdf;
  112         int     iena;
  113 
  114         uchar   sticky[8];
  115 
  116         Lock;
  117         int     hasfifo;
  118         int     checkfifo;
  119         int     fena;
  120 } Ctlr;
  121 
  122 extern PhysUart i8250physuart;
  123 
  124 static Ctlr i8250ctlr[2] = {
  125 {       .io     = Uart0,
  126         .irq    = Uart0IRQ,
  127         .tbdf   = BUSUNKNOWN, },
  128 
  129 {       .io     = Uart1,
  130         .irq    = Uart1IRQ,
  131         .tbdf   = BUSUNKNOWN, },
  132 };
  133 
  134 static Uart i8250uart[2] = {
  135 {       .regs   = &i8250ctlr[0],
  136         .name   = "COM1",
  137         .freq   = UartFREQ,
  138         .phys   = &i8250physuart,
  139         .special= 0,
  140         .next   = &i8250uart[1], },
  141 
  142 {       .regs   = &i8250ctlr[1],
  143         .name   = "COM2",
  144         .freq   = UartFREQ,
  145         .phys   = &i8250physuart,
  146         .special= 0,
  147         .next   = nil, },
  148 };
  149 
  150 #define csr8r(c, r)     inb((c)->io+(r))
  151 #define csr8w(c, r, v)  outb((c)->io+(r), (c)->sticky[(r)]|(v))
  152 
  153 static long
  154 i8250status(Uart* uart, void* buf, long n, long offset)
  155 {
  156         char *p;
  157         Ctlr *ctlr;
  158         uchar ier, lcr, mcr, msr;
  159 
  160         ctlr = uart->regs;
  161         p = malloc(READSTR);
  162         mcr = ctlr->sticky[Mcr];
  163         msr = csr8r(ctlr, Msr);
  164         ier = ctlr->sticky[Ier];
  165         lcr = ctlr->sticky[Lcr];
  166         snprint(p, READSTR,
  167                 "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
  168                 "dev(%d) type(%d) framing(%d) overruns(%d) "
  169                 "berr(%d) serr(%d)%s%s%s%s\n",
  170 
  171                 uart->baud,
  172                 uart->hup_dcd, 
  173                 (msr & Dsr) != 0,
  174                 uart->hup_dsr,
  175                 (lcr & WlsMASK) + 5,
  176                 (ier & Ems) != 0, 
  177                 (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
  178                 (mcr & Rts) != 0,
  179                 (lcr & Stb) ? 2: 1,
  180                 ctlr->fena,
  181 
  182                 uart->dev,
  183                 uart->type,
  184                 uart->ferr,
  185                 uart->oerr,
  186                 uart->berr,
  187                 uart->serr,
  188                 (msr & Cts) ? " cts": "",
  189                 (msr & Dsr) ? " dsr": "",
  190                 (msr & Dcd) ? " dcd": "",
  191                 (msr & Ri) ? " ring": ""
  192         );
  193         n = readstr(offset, buf, n, p);
  194         free(p);
  195 
  196         return n;
  197 }
  198 
  199 static void
  200 i8250fifo(Uart* uart, int level)
  201 {
  202         Ctlr *ctlr;
  203 
  204         ctlr = uart->regs;
  205         if(ctlr->hasfifo == 0)
  206                 return;
  207 
  208         /*
  209          * Changing the FIFOena bit in Fcr flushes data
  210          * from both receive and transmit FIFOs; there's
  211          * no easy way to guarantee not losing data on
  212          * the receive side, but it's possible to wait until
  213          * the transmitter is really empty.
  214          */
  215         ilock(ctlr);
  216         while(!(csr8r(ctlr, Lsr) & Temt))
  217                 ;
  218 
  219         /*
  220          * Set the trigger level, default is the max.
  221          * value.
  222          * Some UARTs require FIFOena to be set before
  223          * other bits can take effect, so set it twice.
  224          */
  225         ctlr->fena = level;
  226         switch(level){
  227         case 0:
  228                 break;
  229         case 1:
  230                 level = FIFO1|FIFOena;
  231                 break;
  232         case 4:
  233                 level = FIFO4|FIFOena;
  234                 break;
  235         case 8:
  236                 level = FIFO8|FIFOena;
  237                 break;
  238         default:
  239                 level = FIFO14|FIFOena;
  240                 break;
  241         }
  242         csr8w(ctlr, Fcr, level);
  243         csr8w(ctlr, Fcr, level);
  244         iunlock(ctlr);
  245 }
  246 
  247 static void
  248 i8250dtr(Uart* uart, int on)
  249 {
  250         Ctlr *ctlr;
  251 
  252         /*
  253          * Toggle DTR.
  254          */
  255         ctlr = uart->regs;
  256         if(on)
  257                 ctlr->sticky[Mcr] |= Dtr;
  258         else
  259                 ctlr->sticky[Mcr] &= ~Dtr;
  260         csr8w(ctlr, Mcr, 0);
  261 }
  262 
  263 static void
  264 i8250rts(Uart* uart, int on)
  265 {
  266         Ctlr *ctlr;
  267 
  268         /*
  269          * Toggle RTS.
  270          */
  271         ctlr = uart->regs;
  272         if(on)
  273                 ctlr->sticky[Mcr] |= Rts;
  274         else
  275                 ctlr->sticky[Mcr] &= ~Rts;
  276         csr8w(ctlr, Mcr, 0);
  277 }
  278 
  279 static void
  280 i8250modemctl(Uart* uart, int on)
  281 {
  282         Ctlr *ctlr;
  283 
  284         ctlr = uart->regs;
  285         ilock(&uart->tlock);
  286         if(on){
  287                 ctlr->sticky[Ier] |= Ems;
  288                 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
  289                 uart->modem = 1;
  290                 uart->cts = csr8r(ctlr, Msr) & Cts;
  291         }
  292         else{
  293                 ctlr->sticky[Ier] &= ~Ems;
  294                 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
  295                 uart->modem = 0;
  296                 uart->cts = 1;
  297         }
  298         iunlock(&uart->tlock);
  299 
  300         /* modem needs fifo */
  301         (*uart->phys->fifo)(uart, on);
  302 }
  303 
  304 static int
  305 i8250parity(Uart* uart, int parity)
  306 {
  307         int lcr;
  308         Ctlr *ctlr;
  309 
  310         ctlr = uart->regs;
  311         lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);
  312 
  313         switch(parity){
  314         case 'e':
  315                 lcr |= Eps|Pen;
  316                 break;
  317         case 'o':
  318                 lcr |= Pen;
  319                 break;
  320         case 'n':
  321                 break;
  322         default:
  323                 return -1;
  324         }
  325         ctlr->sticky[Lcr] = lcr;
  326         csr8w(ctlr, Lcr, 0);
  327 
  328         uart->parity = parity;
  329 
  330         return 0;
  331 }
  332 
  333 static int
  334 i8250stop(Uart* uart, int stop)
  335 {
  336         int lcr;
  337         Ctlr *ctlr;
  338 
  339         ctlr = uart->regs;
  340         lcr = ctlr->sticky[Lcr] & ~Stb;
  341 
  342         switch(stop){
  343         case 1:
  344                 break;
  345         case 2:
  346                 lcr |= Stb;
  347                 break;
  348         default:
  349                 return -1;
  350         }
  351         ctlr->sticky[Lcr] = lcr;
  352         csr8w(ctlr, Lcr, 0);
  353 
  354         uart->stop = stop;
  355 
  356         return 0;
  357 }
  358 
  359 static int
  360 i8250bits(Uart* uart, int bits)
  361 {
  362         int lcr;
  363         Ctlr *ctlr;
  364 
  365         ctlr = uart->regs;
  366         lcr = ctlr->sticky[Lcr] & ~WlsMASK;
  367 
  368         switch(bits){
  369         case 5:
  370                 lcr |= Wls5;
  371                 break;
  372         case 6:
  373                 lcr |= Wls6;
  374                 break;
  375         case 7:
  376                 lcr |= Wls7;
  377                 break;
  378         case 8:
  379                 lcr |= Wls8;
  380                 break;
  381         default:
  382                 return -1;
  383         }
  384         ctlr->sticky[Lcr] = lcr;
  385         csr8w(ctlr, Lcr, 0);
  386 
  387         uart->bits = bits;
  388 
  389         return 0;
  390 }
  391 
  392 static int
  393 i8250baud(Uart* uart, int baud)
  394 {
  395         ulong bgc;
  396         Ctlr *ctlr;
  397 
  398         /*
  399          * Set the Baud rate by calculating and setting the Baud rate
  400          * Generator Constant. This will work with fairly non-standard
  401          * Baud rates.
  402          */
  403         if(uart->freq == 0 || baud <= 0)
  404                 return -1;
  405         bgc = (uart->freq+8*baud-1)/(16*baud);
  406 
  407         ctlr = uart->regs;
  408         csr8w(ctlr, Lcr, Dlab);
  409         outb(ctlr->io+Dlm, bgc>>8);
  410         outb(ctlr->io+Dll, bgc);
  411         csr8w(ctlr, Lcr, 0);
  412 
  413         uart->baud = baud;
  414 
  415         return 0;
  416 }
  417 
  418 static void
  419 i8250break(Uart* uart, int ms)
  420 {
  421         Ctlr *ctlr;
  422 
  423         /*
  424          * Send a break.
  425          */
  426         if(ms <= 0)
  427                 ms = 200;
  428 
  429         ctlr = uart->regs;
  430         csr8w(ctlr, Lcr, Brk);
  431         tsleep(&up->sleep, return0, 0, ms);
  432         csr8w(ctlr, Lcr, 0);
  433 }
  434 
  435 static void
  436 i8250kick(Uart* uart)
  437 {
  438         int i;
  439         Ctlr *ctlr;
  440 
  441         if(uart->cts == 0 || uart->blocked)
  442                 return;
  443 
  444         /*
  445          *  128 here is an arbitrary limit to make sure
  446          *  we don't stay in this loop too long.  If the
  447          *  chip's output queue is longer than 128, too
  448          *  bad -- presotto
  449          */
  450         ctlr = uart->regs;
  451         for(i = 0; i < 128; i++){
  452                 if(!(csr8r(ctlr, Lsr) & Thre))
  453                         break;
  454                 if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
  455                         break;
  456                 outb(ctlr->io+Thr, *(uart->op++));
  457         }
  458 }
  459 
  460 static void
  461 i8250interrupt(Ureg*, void* arg)
  462 {
  463         Ctlr *ctlr;
  464         Uart *uart;
  465         int iir, lsr, old, r;
  466 
  467         uart = arg;
  468 
  469         ctlr = uart->regs;
  470         for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
  471                 switch(iir & IirMASK){
  472                 case Ims:               /* Ms interrupt */
  473                         r = csr8r(ctlr, Msr);
  474                         if(r & Dcts){
  475                                 ilock(&uart->tlock);
  476                                 old = uart->cts;
  477                                 uart->cts = r & Cts;
  478                                 if(old == 0 && uart->cts)
  479                                         uart->ctsbackoff = 2;
  480                                 iunlock(&uart->tlock);
  481                         }
  482                         if(r & Ddsr){
  483                                 old = r & Dsr;
  484                                 if(uart->hup_dsr && uart->dsr && !old)
  485                                         uart->dohup = 1;
  486                                 uart->dsr = old;
  487                         }
  488                         if(r & Ddcd){
  489                                 old = r & Dcd;
  490                                 if(uart->hup_dcd && uart->dcd && !old)
  491                                         uart->dohup = 1;
  492                                 uart->dcd = old;
  493                         }
  494                         break;
  495                 case Ithre:             /* Thr Empty */
  496                         uartkick(uart);
  497                         break;
  498                 case Irda:              /* Received Data Available */
  499                 case Irls:              /* Receiver Line Status */
  500                 case Ictoi:             /* Character Time-out Indication */
  501                         /*
  502                          * Consume any received data.
  503                          * If the received byte came in with a break,
  504                          * parity or framing error, throw it away;
  505                          * overrun is an indication that something has
  506                          * already been tossed.
  507                          */
  508                         while((lsr = csr8r(ctlr, Lsr)) & Dr){
  509                                 if(lsr & (FIFOerr|Oe))
  510                                         uart->oerr++;
  511                                 if(lsr & Pe)
  512                                         uart->perr++;
  513                                 if(lsr & Fe)
  514                                         uart->ferr++;
  515                                 r = csr8r(ctlr, Rbr);
  516                                 if(!(lsr & (Bi|Fe|Pe)))
  517                                         uartrecv(uart, r);
  518                         }
  519                         break;
  520 
  521                 default:
  522                         iprint("weird uart interrupt 0x%2.2uX\n", iir);
  523                         break;
  524                 }
  525         }
  526 }
  527 
  528 static void
  529 i8250disable(Uart* uart)
  530 {
  531         Ctlr *ctlr;
  532 
  533         /*
  534          * Turn off DTR and RTS, disable interrupts and fifos.
  535          */
  536         (*uart->phys->dtr)(uart, 0);
  537         (*uart->phys->rts)(uart, 0);
  538         (*uart->phys->fifo)(uart, 0);
  539 
  540         ctlr = uart->regs;
  541         ctlr->sticky[Ier] = 0;
  542         csr8w(ctlr, Ier, ctlr->sticky[Ier]);
  543 
  544         if(ctlr->iena != 0){
  545                 if(intrdisable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name) == 0)
  546                         ctlr->iena = 0;
  547         }
  548 }
  549 
  550 static void
  551 i8250enable(Uart* uart, int ie)
  552 {
  553         Ctlr *ctlr;
  554 
  555         ctlr = uart->regs;
  556 
  557         /*
  558          * Check if there is a FIFO.
  559          * Changing the FIFOena bit in Fcr flushes data
  560          * from both receive and transmit FIFOs; there's
  561          * no easy way to guarantee not losing data on
  562          * the receive side, but it's possible to wait until
  563          * the transmitter is really empty.
  564          * Also, reading the Iir outwith i8250interrupt()
  565          * can be dangerous, but this should only happen
  566          * once before interrupts are enabled.
  567          */
  568         ilock(ctlr);
  569         if(!ctlr->checkfifo){
  570                 /*
  571                  * Wait until the transmitter is really empty.
  572                  */
  573                 while(!(csr8r(ctlr, Lsr) & Temt))
  574                         ;
  575                 csr8w(ctlr, Fcr, FIFOena);
  576                 if(csr8r(ctlr, Iir) & Ifena)
  577                         ctlr->hasfifo = 1;
  578                 csr8w(ctlr, Fcr, 0);
  579                 ctlr->checkfifo = 1;
  580         }
  581         iunlock(ctlr);
  582 
  583         /*
  584          * Enable interrupts and turn on DTR and RTS.
  585          * Be careful if this is called to set up a polled serial line
  586          * early on not to try to enable interrupts as interrupt-
  587          * -enabling mechanisms might not be set up yet.
  588          */
  589         if(ie){
  590                 if(ctlr->iena == 0){
  591                         intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name);
  592                         ctlr->iena = 1;
  593                 }
  594                 ctlr->sticky[Ier] = Ethre|Erda;
  595                 ctlr->sticky[Mcr] |= Ie;
  596         }
  597         else{
  598                 ctlr->sticky[Ier] = 0;
  599                 ctlr->sticky[Mcr] = 0;
  600         }
  601         csr8w(ctlr, Ier, ctlr->sticky[Ier]);
  602         csr8w(ctlr, Mcr, ctlr->sticky[Mcr]);
  603 
  604         (*uart->phys->dtr)(uart, 1);
  605         (*uart->phys->rts)(uart, 1);
  606 
  607         /*
  608          * During startup, the i8259 interrupt controller is reset.
  609          * This may result in a lost interrupt from the i8250 uart.
  610          * The i8250 thinks the interrupt is still outstanding and does not
  611          * generate any further interrupts. The workaround is to call the
  612          * interrupt handler to clear any pending interrupt events.
  613          * Note: this must be done after setting Ier.
  614          */
  615         if(ie)
  616                 i8250interrupt(nil, uart);
  617 }
  618 
  619 void*
  620 i8250alloc(int io, int irq, int tbdf)
  621 {
  622         Ctlr *ctlr;
  623 
  624         if((ctlr = malloc(sizeof(Ctlr))) != nil){
  625                 ctlr->io = io;
  626                 ctlr->irq = irq;
  627                 ctlr->tbdf = tbdf;
  628         }
  629 
  630         return ctlr;
  631 }
  632 
  633 static Uart*
  634 i8250pnp(void)
  635 {
  636         return i8250uart;
  637 }
  638 
  639 static int
  640 i8250getc(Uart *uart)
  641 {
  642         Ctlr *ctlr;
  643 
  644         ctlr = uart->regs;
  645         while(!(csr8r(ctlr, Lsr)&Dr))
  646                 delay(1);
  647         return csr8r(ctlr, Rbr);
  648 }
  649 
  650 static void
  651 i8250putc(Uart *uart, int c)
  652 {
  653         int i;
  654         Ctlr *ctlr;
  655 
  656         ctlr = uart->regs;
  657         for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
  658                 delay(1);
  659         outb(ctlr->io+Thr, c);
  660         for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
  661                 delay(1);
  662 }
  663 
  664 PhysUart i8250physuart = {
  665         .name           = "i8250",
  666         .pnp            = i8250pnp,
  667         .enable         = i8250enable,
  668         .disable        = i8250disable,
  669         .kick           = i8250kick,
  670         .dobreak        = i8250break,
  671         .baud           = i8250baud,
  672         .bits           = i8250bits,
  673         .stop           = i8250stop,
  674         .parity         = i8250parity,
  675         .modemctl       = i8250modemctl,
  676         .rts            = i8250rts,
  677         .dtr            = i8250dtr,
  678         .status         = i8250status,
  679         .fifo           = i8250fifo,
  680         .getc           = i8250getc,
  681         .putc           = i8250putc,
  682 };
  683 
  684 void
  685 i8250console(void)
  686 {
  687         Uart *uart;
  688         int n;
  689         char *cmd, *p;
  690 
  691         if((p = getconf("console")) == nil)
  692                 return;
  693         n = strtoul(p, &cmd, 0);
  694         if(p == cmd)
  695                 return;
  696         switch(n){
  697         default:
  698                 return;
  699         case 0:
  700                 uart = &i8250uart[0];
  701                 break;
  702         case 1:
  703                 uart = &i8250uart[1];
  704                 break;  
  705         }
  706 
  707         (*uart->phys->enable)(uart, 0);
  708         uartctl(uart, "b9600 l8 pn s1");
  709         if(*cmd != '\0')
  710                 uartctl(uart, cmd);
  711 
  712         consuart = uart;
  713         uart->console = 1;
  714 }
  715 
  716 void
  717 i8250mouse(char* which, int (*putc)(Queue*, int), int setb1200)
  718 {
  719         char *p;
  720         int port;
  721 
  722         port = strtol(which, &p, 0);
  723         if(p == which || port < 0 || port > 1)
  724                 error(Ebadarg);
  725         uartmouse(&i8250uart[port], putc, setb1200);
  726 }
  727 
  728 void
  729 i8250setmouseputc(char* which, int (*putc)(Queue*, int))
  730 {
  731         char *p;
  732         int port;
  733 
  734         port = strtol(which, &p, 0);
  735         if(p == which || port < 0 || port > 1)
  736                 error(Ebadarg);
  737         uartsetmouseputc(&i8250uart[port], putc);
  738 
  739 }

Cache object: 968d903e3d6e27ceb840ae6d6d9aa8fb


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