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/osfmk/ppc/serial_io.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  * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * The contents of this file constitute Original Code as defined in and
    7  * are subject to the Apple Public Source License Version 1.1 (the
    8  * "License").  You may not use this file except in compliance with the
    9  * License.  Please obtain a copy of the License at
   10  * http://www.apple.com/publicsource and read it before using this file.
   11  * 
   12  * This Original Code and all software distributed under the License are
   13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
   17  * License for the specific language governing rights and limitations
   18  * under the License.
   19  * 
   20  * @APPLE_LICENSE_HEADER_END@
   21  */
   22 /*
   23  * @OSF_COPYRIGHT@
   24  */
   25 /*
   26  * @APPLE_FREE_COPYRIGHT@
   27  */
   28 /* 
   29  * Mach Operating System
   30  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
   31  * All Rights Reserved.
   32  * 
   33  * Permission to use, copy, modify and distribute this software and its
   34  * documentation is hereby granted, provided that both the copyright
   35  * notice and this permission notice appear in all copies of the
   36  * software, derivative works or modified versions, and any portions
   37  * thereof, and that both notices appear in supporting documentation.
   38  * 
   39  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   40  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   41  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   42  * 
   43  * Carnegie Mellon requests users of this software to return to
   44  * 
   45  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   46  *  School of Computer Science
   47  *  Carnegie Mellon University
   48  *  Pittsburgh PA 15213-3890
   49  * 
   50  * any improvements or extensions that they make and grant Carnegie Mellon
   51  * the rights to redistribute these changes.
   52  */
   53 /*
   54  */
   55 /*
   56  *      File: scc_8530_hdw.c
   57  *      Author: Alessandro Forin, Carnegie Mellon University
   58  *      Date:   6/91
   59  *
   60  *      Hardware-level operations for the SCC Serial Line Driver
   61  */
   62 
   63 #define NSCC    1       /* Number of serial chips, two ports per chip. */
   64 #if     NSCC > 0
   65 
   66 #include <mach_kdb.h>
   67 #include <platforms.h>
   68 #include <kern/spl.h>
   69 #include <mach/std_types.h>
   70 #include <types.h>
   71 #include <sys/syslog.h>
   72 #include <kern/thread.h>
   73 #include <ppc/misc_protos.h>
   74 #include <ppc/proc_reg.h>
   75 #include <ppc/exception.h>
   76 #include <ppc/Firmware.h>
   77 #include <ppc/serial_io.h>
   78 #include <ppc/scc_8530.h>
   79 
   80 #if     MACH_KDB
   81 #include <machine/db_machdep.h>
   82 #endif  /* MACH_KDB */
   83 
   84 #define kdebug_state()  (1)
   85 #define delay(x)        { volatile int _d_; for (_d_ = 0; _d_ < (10000*x); _d_++) ; }
   86 
   87 #define NSCC_LINE       2       /* 2 ttys per chip */
   88 
   89 #define SCC_DMA_TRANSFERS       0
   90   
   91 struct scc_tty scc_tty[NSCC_LINE];
   92 
   93 #define scc_tty_for(chan)       (&scc_tty[chan])
   94 /* #define scc_unit(dev_no)     (dev_no) */
   95 
   96 #define scc_dev_no(chan) ((chan)^0x01)
   97 #define scc_chan(dev_no) ((dev_no)^0x01)
   98 
   99 extern unsigned int disableSerialOuput;
  100 
  101 int     serial_initted = 0;
  102 unsigned int scc_parm_done = 0;
  103 
  104 extern unsigned int serialmode;
  105 
  106 static struct scc_byte {
  107         unsigned char   reg;
  108         unsigned char   val;
  109 } scc_init_hw[] = {
  110         
  111         9, 0x80,
  112         4, 0x44,
  113         3, 0xC0,
  114         5, 0xE2,
  115         2, 0x00,
  116         10, 0x00,
  117         11, 0x50,
  118         12, 0x0A,
  119         13, 0x00,
  120         3, 0xC1,
  121         5, 0xEA,
  122         14, 0x01,
  123         15, 0x00,
  124         0, 0x10,
  125         0, 0x10,
  126 #if 0
  127         1, 0x12,                        /* int or Rx, Tx int enable */
  128 #else
  129         1, 0x10,                        /* int or Rx,  no Tx int enable */
  130 #endif
  131         9, 0x0A
  132 };
  133 
  134 static int      scc_init_hw_count = sizeof(scc_init_hw)/sizeof(scc_init_hw[0]);
  135 
  136 enum scc_error {SCC_ERR_NONE, SCC_ERR_PARITY, SCC_ERR_BREAK, SCC_ERR_OVERRUN};
  137 
  138 
  139 /*
  140  * BRG formula is:
  141  *                              ClockFrequency (115200 for Power Mac)
  142  *      BRGconstant =   ---------------------------  -  2
  143  *                            BaudRate
  144  */
  145 
  146 #define SERIAL_CLOCK_FREQUENCY (115200*2) /* Power Mac value */
  147 #define convert_baud_rate(rate) ((((SERIAL_CLOCK_FREQUENCY) + (rate)) / (2 * (rate))) - 2)
  148 
  149 #define DEFAULT_SPEED 57600
  150 #define DEFAULT_PORT0_SPEED 1200
  151 #define DEFAULT_FLAGS (TF_LITOUT|TF_ECHO)
  152 
  153 int     scc_param(struct scc_tty *tp);
  154 
  155 
  156 struct scc_softc        scc_softc[NSCC];
  157 caddr_t scc_std[NSCC] = { (caddr_t) 0};
  158 
  159 
  160 #define SCC_RR1_ERRS (SCC_RR1_FRAME_ERR|SCC_RR1_RX_OVERRUN|SCC_RR1_PARITY_ERR)
  161 #define SCC_RR3_ALL (SCC_RR3_RX_IP_A|SCC_RR3_TX_IP_A|SCC_RR3_EXT_IP_A|\
  162                      SCC_RR3_RX_IP_B|SCC_RR3_TX_IP_B|SCC_RR3_EXT_IP_B)
  163 
  164 #define DEBUG_SCC
  165 #undef  DEBUG_SCC
  166 
  167 #ifdef DEBUG_SCC
  168 static int total_chars, total_ints, total_overruns, total_errors, num_ints, max_chars;
  169 static int chars_received[8];
  170 static int __SCC_STATS = 0;
  171 static int max_in_q = 0;
  172 static int max_out_q = 0;
  173 #endif
  174 
  175 DECL_FUNNEL(, scc_funnel)       /* funnel to serialize the SCC driver */
  176 boolean_t scc_funnel_initted = FALSE;
  177 #define SCC_FUNNEL              scc_funnel
  178 #define SCC_FUNNEL_INITTED      scc_funnel_initted
  179 
  180 
  181 /*
  182  * Adapt/Probe/Attach functions
  183  */
  184 boolean_t       scc_uses_modem_control = FALSE;/* patch this with adb */
  185 decl_simple_lock_data(,scc_stomp)
  186 
  187 /* This is called VERY early on in the init and therefore has to have
  188  * hardcoded addresses of the serial hardware control registers. The
  189  * serial line may be needed for console and debugging output before
  190  * anything else takes place
  191  */
  192 
  193 void
  194 initialize_serial( caddr_t scc_phys_base, int32_t serial_baud )
  195 {
  196         int i, chan, bits;
  197         scc_regmap_t    regs;
  198         DECL_FUNNEL_VARS
  199 
  200         assert( scc_phys_base );
  201 
  202         if (!SCC_FUNNEL_INITTED) {
  203                 FUNNEL_INIT(&SCC_FUNNEL, master_processor);
  204                 SCC_FUNNEL_INITTED = TRUE;
  205         }
  206         FUNNEL_ENTER(&SCC_FUNNEL);
  207 
  208         if (serial_initted) {
  209                 FUNNEL_EXIT(&SCC_FUNNEL);
  210                 return;
  211         }
  212 
  213         simple_lock_init(&scc_stomp, FALSE);
  214         
  215         if (serial_baud == -1) serial_baud = DEFAULT_SPEED;
  216         
  217         scc_softc[0].full_modem = TRUE;
  218 
  219         scc_std[0] = scc_phys_base;
  220 
  221         regs = scc_softc[0].regs = (scc_regmap_t)scc_std[0];
  222 
  223         for (chan = 0; chan < NSCC_LINE; chan++) {
  224                 if (chan == 1)
  225                         scc_init_hw[0].val = 0x80;
  226 
  227                 for (i = 0; i < scc_init_hw_count; i++) {
  228                         scc_write_reg(regs, chan,
  229                                       scc_init_hw[i].reg, scc_init_hw[i].val);
  230                 }
  231         }
  232 
  233         /* Call probe so we are ready very early for remote gdb and for serial
  234            console output if appropriate.  */
  235         if (scc_probe(serial_baud)) {
  236                 for (i = 0; i < NSCC_LINE; i++) {
  237                         scc_softc[0].softr[i].wr5 = SCC_WR5_DTR | SCC_WR5_RTS;
  238                         scc_param(scc_tty_for(i));
  239         /* Enable SCC interrupts (how many interrupts are to this thing?!?) */
  240                         scc_write_reg(regs,  i,  9, SCC_WR9_NV);
  241 
  242                         scc_read_reg_zero(regs, 0, bits);/* Clear the status */
  243                 }
  244                 scc_parm_done = 1;
  245         }
  246 
  247         serial_initted = TRUE;
  248 
  249         FUNNEL_EXIT(&SCC_FUNNEL);
  250         return;
  251 }
  252 
  253 int
  254 scc_probe(int32_t serial_baud)
  255 {
  256         scc_softc_t     scc;
  257         register int    val, i;
  258         register scc_regmap_t   regs;
  259         spl_t   s;
  260         DECL_FUNNEL_VARS
  261 
  262         if (!SCC_FUNNEL_INITTED) {
  263                 FUNNEL_INIT(&SCC_FUNNEL, master_processor);
  264                 SCC_FUNNEL_INITTED = TRUE;
  265         }
  266         FUNNEL_ENTER(&SCC_FUNNEL);
  267 
  268         /* Readjust the I/O address to handling 
  269          * new memory mappings.
  270          */
  271 
  272         regs = (scc_regmap_t)scc_std[0];
  273 
  274         if (regs == (scc_regmap_t) 0) {
  275                 FUNNEL_EXIT(&SCC_FUNNEL);
  276                 return 0;
  277         }
  278 
  279         scc = &scc_softc[0];
  280         scc->regs = regs;
  281 
  282         s = splhigh();
  283 
  284         for (i = 0; i < NSCC_LINE; i++) {
  285                 register struct scc_tty *tp;
  286                 tp = scc_tty_for(i);
  287                 tp->t_addr = (char*)(0x80000000L + (i&1));
  288                 /* Set default values.  These will be overridden on
  289                    open but are needed if the port will be used
  290                    independently of the Mach interfaces, e.g., for
  291                    gdb or for a serial console.  */
  292                 if (i == 0) {
  293                   tp->t_ispeed = DEFAULT_PORT0_SPEED;
  294                   tp->t_ospeed = DEFAULT_PORT0_SPEED;
  295                 } else {
  296                   tp->t_ispeed = serial_baud;
  297                   tp->t_ospeed = serial_baud;
  298                 }
  299                 tp->t_flags = DEFAULT_FLAGS;
  300                 scc->softr[i].speed = -1;
  301 
  302                 /* do min buffering */
  303                 tp->t_state |= TS_MIN;
  304 
  305                 tp->t_dev = scc_dev_no(i);
  306         }
  307 
  308         splx(s);
  309 
  310         FUNNEL_EXIT(&SCC_FUNNEL);
  311         return 1;
  312 }
  313 
  314 /*
  315  * Get a char from a specific SCC line
  316  * [this is only used for console&screen purposes]
  317  * must be splhigh since it may be called from another routine under spl
  318  */
  319 
  320 int
  321 scc_getc(int unit, int line, boolean_t wait, boolean_t raw)
  322 {
  323         register scc_regmap_t   regs;
  324         unsigned char   c, value;
  325         int             rcvalue, from_line;
  326         uint32_t        fcrmunge;
  327         spl_t           s = splhigh();
  328         DECL_FUNNEL_VARS
  329 
  330         FUNNEL_ENTER(&SCC_FUNNEL);
  331 
  332 
  333         simple_lock(&scc_stomp);
  334         regs = scc_softc[0].regs;
  335 
  336         /*
  337          * wait till something available
  338          *
  339          */
  340 again:
  341         rcvalue = 0;
  342         while (1) {
  343                 scc_read_reg_zero(regs, line, value);
  344 
  345                 if (value & SCC_RR0_RX_AVAIL)
  346                         break;
  347 
  348                 if (!wait) {
  349                         simple_unlock(&scc_stomp);
  350                         splx(s);
  351                         FUNNEL_EXIT(&SCC_FUNNEL);
  352                         return -1;
  353                 }
  354         }
  355 
  356         /*
  357          * if nothing found return -1
  358          */
  359 
  360         scc_read_reg(regs, line, SCC_RR1, value);
  361         scc_read_data(regs, line, c);
  362 
  363 #if     MACH_KDB
  364         if (console_is_serial() &&
  365             c == ('_' & 0x1f)) {
  366                 /* Drop into the debugger */
  367                 simple_unlock(&scc_stomp);
  368                 Debugger("Serial Line Request");
  369                 simple_lock(&scc_stomp);
  370                 scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
  371                 if (wait) {
  372                         goto again;
  373                 }
  374                 simple_unlock(&scc_stomp);
  375                 splx(s);
  376                 FUNNEL_EXIT(&SCC_FUNNEL);
  377                 return -1;
  378         }
  379 #endif  /* MACH_KDB */
  380 
  381         /*
  382          * bad chars not ok
  383          */
  384         if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
  385                 scc_write_reg(regs, line, SCC_RR0, SCC_RESET_ERROR);
  386 
  387                 if (wait) {
  388                         scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
  389                         goto again;
  390                 }
  391         }
  392 
  393         scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
  394 
  395         simple_unlock(&scc_stomp);
  396         splx(s);
  397 
  398         FUNNEL_EXIT(&SCC_FUNNEL);
  399         return c;
  400 }
  401 
  402 /*
  403  * Put a char on a specific SCC line
  404  * use splhigh since we might be doing a printf in high spl'd code
  405  */
  406 
  407 int
  408 scc_putc(int unit, int line, int c)
  409 {
  410         scc_regmap_t    regs;
  411         spl_t            s;
  412         unsigned char    value;
  413         uint32_t fcrmunge;
  414         DECL_FUNNEL_VARS
  415 
  416 
  417         if (disableSerialOuput)
  418                 return 0;
  419 
  420         s = splhigh();
  421         FUNNEL_ENTER(&SCC_FUNNEL);
  422         simple_lock(&scc_stomp);                
  423 
  424         regs = scc_softc[0].regs;
  425 
  426         do {
  427                 scc_read_reg(regs, line, SCC_RR0, value);
  428                 if (value & SCC_RR0_TX_EMPTY)
  429                         break;
  430                 delay(1);
  431         } while (1);
  432 
  433         scc_write_data(regs, line, c);
  434 /* wait for it to swallow the char ? */
  435 
  436         do {
  437                 scc_read_reg(regs, line, SCC_RR0, value);
  438                 if (value & SCC_RR0_TX_EMPTY)
  439                         break;
  440         } while (1);
  441         scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
  442         simple_unlock(&scc_stomp);              
  443 
  444         splx(s);
  445 
  446         FUNNEL_EXIT(&SCC_FUNNEL);
  447         return 0;
  448 }
  449 
  450 
  451 void
  452 powermac_scc_set_datum(scc_regmap_t regs, unsigned int offset, unsigned char value)
  453 {
  454         volatile unsigned char *address = (unsigned char *) regs + offset;
  455   
  456         assert(FUNNEL_IN_USE(&SCC_FUNNEL));
  457 
  458         *address = value;
  459         eieio();
  460 
  461         assert(FUNNEL_IN_USE(&SCC_FUNNEL));
  462 }
  463   
  464 unsigned char
  465 powermac_scc_get_datum(scc_regmap_t regs, unsigned int offset)
  466 {
  467         volatile unsigned char *address = (unsigned char *) regs + offset;
  468         unsigned char   value;
  469   
  470         assert(FUNNEL_IN_USE(&SCC_FUNNEL));
  471 
  472         value = *address; eieio();
  473         return value;
  474 
  475         assert(FUNNEL_IN_USE(&SCC_FUNNEL));
  476 }
  477 
  478 int
  479 scc_param(struct scc_tty *tp)
  480 {
  481         scc_regmap_t    regs;
  482         unsigned char   value;
  483         unsigned short  speed_value;
  484         int             bits, chan;
  485         spl_t           s;
  486         struct scc_softreg      *sr;
  487         scc_softc_t     scc;
  488 
  489         assert(FUNNEL_IN_USE(&SCC_FUNNEL));
  490         
  491         s = splhigh();
  492         simple_lock(&scc_stomp);
  493 
  494         chan = scc_chan(tp->t_dev);
  495         scc = &scc_softc[0];
  496         regs = scc->regs;
  497 
  498         sr = &scc->softr[chan];
  499         
  500         /* Do a quick check to see if the hardware needs to change */
  501         if ((sr->flags & (TF_ODDP|TF_EVENP)) == (tp->t_flags & (TF_ODDP|TF_EVENP))
  502             && sr->speed == tp->t_ispeed) {
  503                 assert(FUNNEL_IN_USE(&SCC_FUNNEL));
  504                 simple_unlock(&scc_stomp);
  505                 splx(s);
  506                 return 0;
  507         }
  508 
  509         if(scc_parm_done)       {                                                               
  510                 
  511                 scc_write_reg(regs,  chan,  3, SCC_WR3_RX_8_BITS|SCC_WR3_RX_ENABLE);
  512                 sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE;
  513                 scc_write_reg(regs,  chan,  1, sr->wr1);
  514         scc_write_reg(regs,  chan, 15, SCC_WR15_ENABLE_ESCC);
  515                 scc_write_reg(regs,  chan,  7, SCC_WR7P_RX_FIFO);
  516                 scc_write_reg(regs,  chan,  0, SCC_IE_NEXT_CHAR);
  517                 scc_write_reg(regs,  chan,  0, SCC_RESET_EXT_IP);
  518                 scc_write_reg(regs,  chan,  0, SCC_RESET_EXT_IP);
  519                 scc_write_reg(regs,  chan,  9, SCC_WR9_MASTER_IE|SCC_WR9_NV);
  520                 scc_read_reg_zero(regs, 0, bits);
  521                 sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE;
  522                 scc_write_reg(regs,  chan,  1, sr->wr1);
  523                 scc_write_reg(regs,  chan,  0, SCC_IE_NEXT_CHAR);
  524                 simple_unlock(&scc_stomp);
  525                 splx(s);
  526                 return 0;
  527         }
  528         
  529         sr->flags = tp->t_flags;
  530         sr->speed = tp->t_ispeed;
  531 
  532 
  533         if (tp->t_ispeed == 0) {
  534                 sr->wr5 &= ~SCC_WR5_DTR;
  535                 scc_write_reg(regs,  chan, 5, sr->wr5);
  536                 simple_unlock(&scc_stomp);
  537                 splx(s);
  538 
  539                 assert(FUNNEL_IN_USE(&SCC_FUNNEL));
  540                 return 0;
  541         }
  542         
  543 
  544 #if     SCC_DMA_TRANSFERS
  545         if (scc->dma_initted & (1<<chan)) 
  546                 scc->dma_ops->scc_dma_reset_rx(chan);
  547 #endif
  548 
  549         value = SCC_WR4_1_STOP;
  550 
  551         /* 
  552          * For 115K the clocking divide changes to 64.. to 230K will
  553          * start at the normal clock divide 16.
  554          *
  555          * However, both speeds will pull from a different clocking
  556          * source
  557          */
  558 
  559         if (tp->t_ispeed == 115200)
  560                 value |= SCC_WR4_CLK_x32;
  561         else    
  562                 value |= SCC_WR4_CLK_x16 ;
  563 
  564         /* .. and parity */
  565         if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_EVENP)
  566                 value |= (SCC_WR4_EVEN_PARITY |  SCC_WR4_PARITY_ENABLE);
  567         else if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_ODDP)
  568                 value |= SCC_WR4_PARITY_ENABLE;
  569 
  570         /* set it now, remember it must be first after reset */
  571         sr->wr4 = value;
  572 
  573         /* Program Parity, and Stop bits */
  574         scc_write_reg(regs,  chan, 4, sr->wr4);
  575 
  576         /* Setup for 8 bits */
  577         scc_write_reg(regs,  chan, 3, SCC_WR3_RX_8_BITS);
  578 
  579         // Set DTR, RTS, and transmitter bits/character.
  580         sr->wr5 = SCC_WR5_TX_8_BITS | SCC_WR5_RTS | SCC_WR5_DTR;
  581 
  582         scc_write_reg(regs,  chan, 5, sr->wr5);
  583         
  584         scc_write_reg(regs, chan, 14, 0);       /* Disable baud rate */
  585 
  586         /* Setup baud rate 57.6Kbps, 115K, 230K should all yeild
  587          * a converted baud rate of zero
  588          */
  589         speed_value = convert_baud_rate(tp->t_ispeed);
  590 
  591         if (speed_value == 0xffff)
  592                 speed_value = 0;
  593 
  594         scc_set_timing_base(regs, chan, speed_value);
  595         
  596         if (tp->t_ispeed == 115200 || tp->t_ispeed == 230400) {
  597                 /* Special case here.. change the clock source*/
  598                 scc_write_reg(regs, chan, 11, 0);
  599                 /* Baud rate generator is disabled.. */
  600         } else {
  601                 scc_write_reg(regs, chan, 11, SCC_WR11_RCLK_BAUDR|SCC_WR11_XTLK_BAUDR);
  602                 /* Enable the baud rate generator */
  603                 scc_write_reg(regs,  chan, 14, SCC_WR14_BAUDR_ENABLE);
  604         }
  605 
  606 
  607         scc_write_reg(regs,  chan,  3, SCC_WR3_RX_8_BITS|SCC_WR3_RX_ENABLE);
  608 
  609 
  610         sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE;
  611         scc_write_reg(regs,  chan,  1, sr->wr1);
  612         scc_write_reg(regs,  chan, 15, SCC_WR15_ENABLE_ESCC);
  613         scc_write_reg(regs,  chan,  7, SCC_WR7P_RX_FIFO);
  614         scc_write_reg(regs,  chan,  0, SCC_IE_NEXT_CHAR);
  615 
  616 
  617         /* Clear out any pending external or status interrupts */
  618         scc_write_reg(regs,  chan,  0, SCC_RESET_EXT_IP);
  619         scc_write_reg(regs,  chan,  0, SCC_RESET_EXT_IP);
  620         //scc_write_reg(regs,  chan,  0, SCC_RESET_ERROR);
  621 
  622         /* Enable SCC interrupts (how many interrupts are to this thing?!?) */
  623         scc_write_reg(regs,  chan,  9, SCC_WR9_MASTER_IE|SCC_WR9_NV);
  624 
  625         scc_read_reg_zero(regs, 0, bits);/* Clear the status */
  626 
  627 #if     SCC_DMA_TRANSFERS
  628         if (scc->dma_initted & (1<<chan))  {
  629                 scc->dma_ops->scc_dma_start_rx(chan);
  630                 scc->dma_ops->scc_dma_setup_8530(chan);
  631         } else
  632 #endif
  633         {
  634                 sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE;
  635                 scc_write_reg(regs, chan, 1, sr->wr1);
  636                 scc_write_reg(regs, chan, 0, SCC_IE_NEXT_CHAR);
  637         }
  638 
  639         sr->wr5 |= SCC_WR5_TX_ENABLE;
  640         scc_write_reg(regs,  chan,  5, sr->wr5);
  641 
  642         simple_unlock(&scc_stomp);
  643         splx(s);
  644 
  645         assert(FUNNEL_IN_USE(&SCC_FUNNEL));
  646         return 0;
  647 
  648 }
  649 
  650 /*
  651  *  This routine will start a thread that polls the serial port, listening for
  652  *  characters that have been typed.
  653  */
  654 
  655 void
  656 serial_keyboard_init(void)
  657 {
  658         kern_return_t   result;
  659         thread_t                thread;
  660 
  661         if(!(serialmode & 2)) return;           /* Leave if we do not want a serial console */
  662 
  663         kprintf("Serial keyboard started\n");
  664         result = kernel_thread_start_priority((thread_continue_t)serial_keyboard_start, NULL, MAXPRI_KERNEL, &thread);
  665         if (result != KERN_SUCCESS)
  666                 panic("serial_keyboard_init");
  667 
  668         thread_deallocate(thread);
  669 }
  670 
  671 void
  672 serial_keyboard_start(void)
  673 {
  674         serial_keyboard_poll();                 /* Go see if there are any characters pending now */
  675         panic("serial_keyboard_start: we can't get back here\n");
  676 }
  677 
  678 static int ptestxxx = 0;
  679 
  680 void
  681 serial_keyboard_poll(void)
  682 {
  683         int chr;
  684         uint64_t next;
  685         extern void cons_cinput(char ch);       /* The BSD routine that gets characters */
  686 
  687 
  688         while(1) {                              /* Do this for a while */
  689                 chr = scc_getc(0, 1, 0, 1);     /* Get a character if there is one */
  690                 if(chr < 0) break;              /* The serial buffer is empty */
  691                 cons_cinput((char)chr);         /* Buffer up the character */
  692         }
  693 
  694         clock_interval_to_deadline(16, 1000000, &next); /* Get time of pop */
  695 
  696         assert_wait_deadline((event_t)serial_keyboard_poll, THREAD_UNINT, next);        /* Show we are "waiting" */
  697         thread_block((thread_continue_t)serial_keyboard_poll);  /* Wait for it */
  698         panic("serial_keyboard_poll: Shouldn't never ever get here...\n");
  699 }
  700 
  701 #endif  /* NSCC > 0 */

Cache object: 5a5d47f93016127217511926eb72e1d4


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