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

Cache object: e6bfd8d857f595c7817bdc5d3952ddc2


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