Annotation of XNU/osfmk/ppc/POWERMAC/serial_io.c, revision 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.