Annotation of XNU/osfmk/ppc/POWERMAC/serial_io.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 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  [email protected]
                     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 <ppc/misc_protos.h>
                     73: #include <ppc/proc_reg.h>
                     74: #include <ppc/exception.h>
                     75: #include <ppc/Firmware.h>
                     76: #include <ppc/POWERMAC/serial_io.h>
                     77: #include <pexpert/ppc/powermac.h>
                     78: #include <ppc/POWERMAC/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: int    serial_initted = 0;
                    100: unsigned int scc_parm_done = 0;                                /* (TEST/DEBUG) */
                    101: 
                    102: static struct scc_byte {
                    103:        unsigned char   reg;
                    104:        unsigned char   val;
                    105: } scc_init_hw[] = {
                    106:        
                    107:        9, 0x80,
                    108:        4, 0x44,
                    109:        3, 0xC0,
                    110:        5, 0xE2,
                    111:        2, 0x00,
                    112:        10, 0x00,
                    113:        11, 0x50,
                    114:        12, 0x0A,
                    115:        13, 0x00,
                    116:        3, 0xC1,
                    117:        5, 0xEA,
                    118:        14, 0x01,
                    119:        15, 0x00,
                    120:        0, 0x10,
                    121:        0, 0x10,
                    122: #if 0
                    123:        1, 0x12,                        /* int or Rx, Tx int enable */
                    124: #else
                    125:        1, 0x10,                        /* int or Rx,  no Tx int enable */
                    126: #endif
                    127:        9, 0x0A
                    128: };
                    129: 
                    130: static int     scc_init_hw_count = sizeof(scc_init_hw)/sizeof(scc_init_hw[0]);
                    131: 
                    132: enum scc_error {SCC_ERR_NONE, SCC_ERR_PARITY, SCC_ERR_BREAK, SCC_ERR_OVERRUN};
                    133: 
                    134: 
                    135: /*
                    136:  * BRG formula is:
                    137:  *                             ClockFrequency (115200 for Power Mac)
                    138:  *     BRGconstant =   ---------------------------  -  2
                    139:  *                           BaudRate
                    140:  */
                    141: 
                    142: #define SERIAL_CLOCK_FREQUENCY (115200*2) /* Power Mac value */
                    143: #define        convert_baud_rate(rate) ((((SERIAL_CLOCK_FREQUENCY) + (rate)) / (2 * (rate))) - 2)
                    144: 
                    145: #define DEFAULT_SPEED 38400
                    146: #define DEFAULT_FLAGS (TF_LITOUT|TF_ECHO)
                    147: 
                    148: int    scc_param(struct scc_tty *tp);
                    149: 
                    150: 
                    151: struct scc_softc       scc_softc[NSCC];
                    152: caddr_t        scc_std[NSCC] = { (caddr_t) 0};
                    153: 
                    154: 
                    155: #define SCC_RR1_ERRS (SCC_RR1_FRAME_ERR|SCC_RR1_RX_OVERRUN|SCC_RR1_PARITY_ERR)
                    156: #define SCC_RR3_ALL (SCC_RR3_RX_IP_A|SCC_RR3_TX_IP_A|SCC_RR3_EXT_IP_A|\
                    157:                      SCC_RR3_RX_IP_B|SCC_RR3_TX_IP_B|SCC_RR3_EXT_IP_B)
                    158: 
                    159: #define DEBUG_SCC
                    160: #undef  DEBUG_SCC
                    161: 
                    162: #ifdef DEBUG_SCC
                    163: static int total_chars, total_ints, total_overruns, total_errors, num_ints, max_chars;
                    164: static int chars_received[8];
                    165: static int __SCC_STATS = 0;
                    166: static int max_in_q = 0;
                    167: static int max_out_q = 0;
                    168: #endif
                    169: 
                    170: DECL_FUNNEL(, scc_funnel)      /* funnel to serialize the SCC driver */
                    171: boolean_t scc_funnel_initted = FALSE;
                    172: #define SCC_FUNNEL             scc_funnel
                    173: #define SCC_FUNNEL_INITTED     scc_funnel_initted
                    174: 
                    175: 
                    176: /*
                    177:  * Adapt/Probe/Attach functions
                    178:  */
                    179: boolean_t      scc_uses_modem_control = FALSE;/* patch this with adb */
                    180: decl_simple_lock_data(,scc_stomp)                      /* (TEST/DEBUG) */
                    181: 
                    182: /* This is called VERY early on in the init and therefore has to have
                    183:  * hardcoded addresses of the serial hardware control registers. The
                    184:  * serial line may be needed for console and debugging output before
                    185:  * anything else takes place
                    186:  */
                    187: 
                    188: void
                    189: initialize_serial( caddr_t scc_phys_base )
                    190: {
                    191:        int i, chan, bits;
                    192:        scc_regmap_t    regs;
                    193:        DECL_FUNNEL_VARS
                    194: 
                    195:        assert( scc_phys_base );
                    196: 
                    197:        if (!SCC_FUNNEL_INITTED) {
                    198:                FUNNEL_INIT(&SCC_FUNNEL, master_processor);
                    199:                SCC_FUNNEL_INITTED = TRUE;
                    200:        }
                    201:        FUNNEL_ENTER(&SCC_FUNNEL);
                    202: 
                    203:        if (serial_initted) {
                    204:                FUNNEL_EXIT(&SCC_FUNNEL);
                    205:                return;
                    206:        }
                    207: 
                    208:        simple_lock_init(&scc_stomp, FALSE);                            /* (TEST/DEBUG) */
                    209:        
                    210:        scc_softc[0].full_modem = TRUE;
                    211: 
                    212:         scc_std[0] = scc_phys_base;
                    213: 
                    214:        regs = scc_softc[0].regs = (scc_regmap_t)scc_std[0];
                    215: 
                    216:        for (chan = 0; chan < NSCC_LINE; chan++) {
                    217:                if (chan == 1)
                    218:                        scc_init_hw[0].val = 0x80;
                    219: 
                    220:                for (i = 0; i < scc_init_hw_count; i++) {
                    221:                        scc_write_reg(regs, chan,
                    222:                                      scc_init_hw[i].reg, scc_init_hw[i].val);
                    223:                }
                    224:        }
                    225: 
                    226:        /* Call probe so we are ready very early for remote gdb and for serial
                    227:           console output if appropriate.  */
                    228:        if (scc_probe()) {
                    229:                for (i = 0; i < NSCC_LINE; i++) {
                    230:                        scc_softc[0].softr[i].wr5 = SCC_WR5_DTR | SCC_WR5_RTS;
                    231:                        scc_param(scc_tty_for(i));
                    232:        /* Enable SCC interrupts (how many interrupts are to this thing?!?) */
                    233:                        scc_write_reg(regs,  i,  9, SCC_WR9_NV);
                    234: 
                    235:                        scc_read_reg_zero(regs, 0, bits);/* Clear the status */
                    236:                }
                    237:                 scc_parm_done = 1;                     /* (TEST/DEBUG) */
                    238:        }
                    239: 
                    240:        serial_initted = TRUE;
                    241: 
                    242:        FUNNEL_EXIT(&SCC_FUNNEL);
                    243:        return;
                    244: }
                    245: 
                    246: int
                    247: scc_probe(void)
                    248: {
                    249:        scc_softc_t     scc;
                    250:        register int    val, i;
                    251:        register scc_regmap_t   regs;
                    252:        spl_t   s;
                    253:        DECL_FUNNEL_VARS
                    254: 
                    255:        if (!SCC_FUNNEL_INITTED) {
                    256:                FUNNEL_INIT(&SCC_FUNNEL, master_processor);
                    257:                SCC_FUNNEL_INITTED = TRUE;
                    258:        }
                    259:        FUNNEL_ENTER(&SCC_FUNNEL);
                    260: 
                    261:        /* Readjust the I/O address to handling 
                    262:         * new memory mappings.
                    263:         */
                    264: 
                    265: //     scc_std[0] = POWERMAC_IO(scc_std[0]);
                    266: 
                    267:        regs = (scc_regmap_t)scc_std[0];
                    268: 
                    269:        if (regs == (scc_regmap_t) 0) {
                    270:                FUNNEL_EXIT(&SCC_FUNNEL);
                    271:                return 0;
                    272:        }
                    273: 
                    274:        scc = &scc_softc[0];
                    275:        scc->regs = regs;
                    276: 
                    277:        s = splhigh();
                    278: 
                    279:        for (i = 0; i < NSCC_LINE; i++) {
                    280:                register struct scc_tty *tp;
                    281:                tp = scc_tty_for(i);
                    282:                tp->t_addr = (char*)(0x80000000L + (i&1));
                    283:                /* Set default values.  These will be overridden on
                    284:                   open but are needed if the port will be used
                    285:                   independently of the Mach interfaces, e.g., for
                    286:                   gdb or for a serial console.  */
                    287:                tp->t_ispeed = DEFAULT_SPEED;
                    288:                tp->t_ospeed = DEFAULT_SPEED;
                    289:                tp->t_flags = DEFAULT_FLAGS;
                    290:                scc->softr[i].speed = -1;
                    291: 
                    292:                /* do min buffering */
                    293:                tp->t_state |= TS_MIN;
                    294: 
                    295:                tp->t_dev = scc_dev_no(i);
                    296:        }
                    297: 
                    298:        splx(s);
                    299: 
                    300:        FUNNEL_EXIT(&SCC_FUNNEL);
                    301:        return 1;
                    302: }
                    303: 
                    304: /*
                    305:  * Get a char from a specific SCC line
                    306:  * [this is only used for console&screen purposes]
                    307:  * must be splhigh since it may be called from another routine under spl
                    308:  */
                    309: 
                    310: int
                    311: scc_getc(int unit, int line, boolean_t wait, boolean_t raw)
                    312: {
                    313:        register scc_regmap_t   regs;
                    314:        unsigned char   c, value;
                    315:        int             rcvalue, from_line;
                    316:        spl_t           s = splhigh();
                    317:        DECL_FUNNEL_VARS
                    318: 
                    319:        FUNNEL_ENTER(&SCC_FUNNEL);
                    320: 
                    321:        simple_lock(&scc_stomp);                                        /* (TEST/DEBUG) */
                    322:        regs = scc_softc[0].regs;
                    323: 
                    324:        /*
                    325:         * wait till something available
                    326:         *
                    327:         */
                    328: again:
                    329:        rcvalue = 0;
                    330:        while (1) {
                    331:                scc_read_reg_zero(regs, line, value);
                    332: 
                    333:                if (value & SCC_RR0_RX_AVAIL)
                    334:                        break;
                    335: 
                    336:                if (!wait) {
                    337:                        simple_unlock(&scc_stomp);                      /* (TEST/DEBUG) */
                    338:                        splx(s);
                    339:                        FUNNEL_EXIT(&SCC_FUNNEL);
                    340:                        return -1;
                    341:                }
                    342:        }
                    343: 
                    344:        /*
                    345:         * if nothing found return -1
                    346:         */
                    347: 
                    348:        scc_read_reg(regs, line, SCC_RR1, value);
                    349:        scc_read_data(regs, line, c);
                    350: 
                    351: #if    MACH_KDB
                    352:        if (console_is_serial() &&
                    353:            c == ('_' & 0x1f)) {
                    354:                /* Drop into the debugger */
                    355:                simple_unlock(&scc_stomp);                              /* (TEST/DEBUG) */
                    356:                Debugger("Serial Line Request");
                    357:                simple_lock(&scc_stomp);                                /* (TEST/DEBUG) */
                    358:                scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    359:                if (wait) {
                    360:                        goto again;
                    361:                }
                    362:                simple_unlock(&scc_stomp);                              /* (TEST/DEBUG) */
                    363:                splx(s);
                    364:                FUNNEL_EXIT(&SCC_FUNNEL);
                    365:                return -1;
                    366:        }
                    367: #endif /* MACH_KDB */
                    368: 
                    369:        /*
                    370:         * bad chars not ok
                    371:         */
                    372:        if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
                    373:                scc_write_reg(regs, line, SCC_RR0, SCC_RESET_ERROR);
                    374: 
                    375:                if (wait) {
                    376:                        scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    377:                        goto again;
                    378:                }
                    379:        }
                    380: 
                    381:        scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    382: 
                    383:        simple_unlock(&scc_stomp);                                      /* (TEST/DEBUG) */
                    384:        splx(s);
                    385: 
                    386:        FUNNEL_EXIT(&SCC_FUNNEL);
                    387:        return c;
                    388: }
                    389: 
                    390: /*
                    391:  * Put a char on a specific SCC line
                    392:  * use splhigh since we might be doing a printf in high spl'd code
                    393:  */
                    394: 
                    395: int
                    396: scc_putc(int unit, int line, int c)
                    397: {
                    398:        scc_regmap_t    regs;
                    399:        spl_t            s = splhigh();
                    400:        unsigned char    value;
                    401:        DECL_FUNNEL_VARS
                    402: 
                    403:        FUNNEL_ENTER(&SCC_FUNNEL);
                    404:        simple_lock(&scc_stomp);                                /* (TEST/DEBUG) */
                    405: 
                    406:        regs = scc_softc[0].regs;
                    407: 
                    408:        do {
                    409:                scc_read_reg(regs, line, SCC_RR0, value);
                    410:                if (value & SCC_RR0_TX_EMPTY)
                    411:                        break;
                    412:                delay(1);
                    413:        } while (1);
                    414: 
                    415:        scc_write_data(regs, line, c);
                    416: /* wait for it to swallow the char ? */
                    417: 
                    418:        do {
                    419:                scc_read_reg(regs, line, SCC_RR0, value);
                    420:                if (value & SCC_RR0_TX_EMPTY)
                    421:                        break;
                    422:        } while (1);
                    423:        scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    424:        simple_unlock(&scc_stomp);                              /* (TEST/DEBUG) */
                    425: 
                    426:        splx(s);
                    427: 
                    428:        FUNNEL_EXIT(&SCC_FUNNEL);
                    429:        return 0;
                    430: }
                    431: 
                    432: 
                    433: void
                    434: powermac_scc_set_datum(scc_regmap_t regs, unsigned int offset, unsigned char value)
                    435: {
                    436:        volatile unsigned char *address = (unsigned char *) regs + offset;
                    437:   
                    438:        assert(FUNNEL_IN_USE(&SCC_FUNNEL));
                    439: 
                    440:        *address = value;
                    441:        eieio();
                    442: 
                    443:        assert(FUNNEL_IN_USE(&SCC_FUNNEL));
                    444: }
                    445:   
                    446: unsigned char
                    447: powermac_scc_get_datum(scc_regmap_t regs, unsigned int offset)
                    448: {
                    449:        volatile unsigned char *address = (unsigned char *) regs + offset;
                    450:        unsigned char   value;
                    451:   
                    452:        assert(FUNNEL_IN_USE(&SCC_FUNNEL));
                    453: 
                    454:        value = *address; eieio();
                    455:        return value;
                    456: 
                    457:        assert(FUNNEL_IN_USE(&SCC_FUNNEL));
                    458: }
                    459: 
                    460: int
                    461: scc_param(struct scc_tty *tp)
                    462: {
                    463:        scc_regmap_t    regs;
                    464:        unsigned char   value;
                    465:        unsigned short  speed_value;
                    466:        int             bits, chan;
                    467:        spl_t           s;
                    468:        struct scc_softreg      *sr;
                    469:        scc_softc_t     scc;
                    470: 
                    471:        assert(FUNNEL_IN_USE(&SCC_FUNNEL));
                    472:        
                    473:        s = splhigh();
                    474:        simple_lock(&scc_stomp);                                /* (TEST/DEBUG) */
                    475: 
                    476:        chan = scc_chan(tp->t_dev);
                    477:        scc = &scc_softc[0];
                    478:        regs = scc->regs;
                    479: 
                    480:        sr = &scc->softr[chan];
                    481:        
                    482:        /* Do a quick check to see if the hardware needs to change */
                    483:        if ((sr->flags & (TF_ODDP|TF_EVENP)) == (tp->t_flags & (TF_ODDP|TF_EVENP))
                    484:            && sr->speed == tp->t_ispeed) {
                    485:                assert(FUNNEL_IN_USE(&SCC_FUNNEL));
                    486:                simple_unlock(&scc_stomp);                                      /* (TEST/DEBUG) */
                    487:                splx(s);                                                                                        /* (TEST/DEBUG) */
                    488:                return 0;                                                                                       /* (TEST/DEBUG) */
                    489:        }
                    490: 
                    491:        if(scc_parm_done)       {                                                               
                    492:                
                    493:                scc_write_reg(regs,  chan,  3, SCC_WR3_RX_8_BITS|SCC_WR3_RX_ENABLE);    /* (TEST/DEBUG) */
                    494:                sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE;      /* (TEST/DEBUG) */
                    495:                scc_write_reg(regs,  chan,  1, sr->wr1);                        /* (TEST/DEBUG) */
                    496:                scc_write_reg(regs,  chan, 15, SCC_WR15_ENABLE_ESCC);   /* (TEST/DEBUG) */
                    497:                scc_write_reg(regs,  chan,  7, SCC_WR7P_RX_FIFO);       /* (TEST/DEBUG) */
                    498:                scc_write_reg(regs,  chan,  0, SCC_IE_NEXT_CHAR);       /* (TEST/DEBUG) */
                    499:                scc_write_reg(regs,  chan,  0, SCC_RESET_EXT_IP);       /* (TEST/DEBUG) */
                    500:                scc_write_reg(regs,  chan,  0, SCC_RESET_EXT_IP);       /* (TEST/DEBUG) */
                    501:                scc_write_reg(regs,  chan,  9, SCC_WR9_MASTER_IE|SCC_WR9_NV);   /* (TEST/DEBUG) */
                    502:                scc_read_reg_zero(regs, 0, bits);                                       /* (TEST/DEBUG) */
                    503:                sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE;      /* (TEST/DEBUG) */
                    504:                scc_write_reg(regs,  chan,  1, sr->wr1);                        /* (TEST/DEBUG) */
                    505:                scc_write_reg(regs,  chan,  0, SCC_IE_NEXT_CHAR);       /* (TEST/DEBUG) */
                    506:                simple_unlock(&scc_stomp);                                                      /* (TEST/DEBUG) */
                    507:                splx(s);                                                                                        /* (TEST/DEBUG) */
                    508:                return 0;                                                                                       /* (TEST/DEBUG) */
                    509:        }
                    510:        
                    511:        sr->flags = tp->t_flags;
                    512:        sr->speed = tp->t_ispeed;
                    513: 
                    514: 
                    515:        if (tp->t_ispeed == 0) {
                    516:                sr->wr5 &= ~SCC_WR5_DTR;
                    517:                scc_write_reg(regs,  chan, 5, sr->wr5);
                    518:                simple_unlock(&scc_stomp);                                                      /* (TEST/DEBUG) */
                    519:                splx(s);
                    520: 
                    521:                assert(FUNNEL_IN_USE(&SCC_FUNNEL));
                    522:                return 0;
                    523:        }
                    524:        
                    525: 
                    526: #if    SCC_DMA_TRANSFERS
                    527:        if (scc->dma_initted & (1<<chan)) 
                    528:                scc->dma_ops->scc_dma_reset_rx(chan);
                    529: #endif
                    530: 
                    531:        value = SCC_WR4_1_STOP;
                    532: 
                    533:        /* 
                    534:         * For 115K the clocking divide changes to 64.. to 230K will
                    535:         * start at the normal clock divide 16.
                    536:         *
                    537:         * However, both speeds will pull from a different clocking
                    538:         * source
                    539:         */
                    540: 
                    541:        if (tp->t_ispeed == 115200)
                    542:                value |= SCC_WR4_CLK_x32;
                    543:        else    
                    544:                value |= SCC_WR4_CLK_x16 ;
                    545: 
                    546:        /* .. and parity */
                    547:        if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_EVENP)
                    548:                value |= (SCC_WR4_EVEN_PARITY |  SCC_WR4_PARITY_ENABLE);
                    549:        else if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_ODDP)
                    550:                value |= SCC_WR4_PARITY_ENABLE;
                    551: 
                    552:        /* set it now, remember it must be first after reset */
                    553:        sr->wr4 = value;
                    554: 
                    555:        /* Program Parity, and Stop bits */
                    556:        scc_write_reg(regs,  chan, 4, sr->wr4);
                    557: 
                    558:        /* Setup for 8 bits */
                    559:        scc_write_reg(regs,  chan, 3, SCC_WR3_RX_8_BITS);
                    560: 
                    561:        // Set DTR, RTS, and transmitter bits/character.
                    562:        sr->wr5 = SCC_WR5_TX_8_BITS | SCC_WR5_RTS | SCC_WR5_DTR;
                    563: 
                    564:        scc_write_reg(regs,  chan, 5, sr->wr5);
                    565:        
                    566:        scc_write_reg(regs, chan, 14, 0);       /* Disable baud rate */
                    567: 
                    568:        /* Setup baud rate 57.6Kbps, 115K, 230K should all yeild
                    569:         * a converted baud rate of zero
                    570:         */
                    571:        speed_value = convert_baud_rate(tp->t_ispeed);
                    572: 
                    573:        if (speed_value == 0xffff)
                    574:                speed_value = 0;
                    575: 
                    576:        scc_set_timing_base(regs, chan, speed_value);
                    577:        
                    578:        if (tp->t_ispeed == 115200 || tp->t_ispeed == 230400) {
                    579:                /* Special case here.. change the clock source*/
                    580:                scc_write_reg(regs, chan, 11, 0);
                    581:                /* Baud rate generator is disabled.. */
                    582:        } else {
                    583:                scc_write_reg(regs, chan, 11, SCC_WR11_RCLK_BAUDR|SCC_WR11_XTLK_BAUDR);
                    584:                /* Enable the baud rate generator */
                    585:                scc_write_reg(regs,  chan, 14, SCC_WR14_BAUDR_ENABLE);
                    586:        }
                    587: 
                    588: 
                    589:        scc_write_reg(regs,  chan,  3, SCC_WR3_RX_8_BITS|SCC_WR3_RX_ENABLE);
                    590: 
                    591: 
                    592:        sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE;
                    593:        scc_write_reg(regs,  chan,  1, sr->wr1);
                    594:                scc_write_reg(regs,  chan, 15, SCC_WR15_ENABLE_ESCC);
                    595:        scc_write_reg(regs,  chan,  7, SCC_WR7P_RX_FIFO);
                    596:        scc_write_reg(regs,  chan,  0, SCC_IE_NEXT_CHAR);
                    597: 
                    598: 
                    599:        /* Clear out any pending external or status interrupts */
                    600:        scc_write_reg(regs,  chan,  0, SCC_RESET_EXT_IP);
                    601:        scc_write_reg(regs,  chan,  0, SCC_RESET_EXT_IP);
                    602:        //scc_write_reg(regs,  chan,  0, SCC_RESET_ERROR);
                    603: 
                    604:        /* Enable SCC interrupts (how many interrupts are to this thing?!?) */
                    605:        scc_write_reg(regs,  chan,  9, SCC_WR9_MASTER_IE|SCC_WR9_NV);
                    606: 
                    607:        scc_read_reg_zero(regs, 0, bits);/* Clear the status */
                    608: 
                    609: #if    SCC_DMA_TRANSFERS
                    610:        if (scc->dma_initted & (1<<chan))  {
                    611:                scc->dma_ops->scc_dma_start_rx(chan);
                    612:                scc->dma_ops->scc_dma_setup_8530(chan);
                    613:        } else
                    614: #endif
                    615:        {
                    616:                sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE;
                    617:                scc_write_reg(regs, chan, 1, sr->wr1);
                    618:                scc_write_reg(regs, chan, 0, SCC_IE_NEXT_CHAR);
                    619:        }
                    620: 
                    621:        sr->wr5 |= SCC_WR5_TX_ENABLE;
                    622:        scc_write_reg(regs,  chan,  5, sr->wr5);
                    623: 
                    624:        simple_unlock(&scc_stomp);                      /* (TEST/DEBUG) */
                    625:        splx(s);
                    626: 
                    627:        assert(FUNNEL_IN_USE(&SCC_FUNNEL));
                    628:        return 0;
                    629: 
                    630: }
                    631: 
                    632: #endif /* NSCC > 0 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.