Annotation of kernel/machdep/ppc/serial_io.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:  *     File: scc_8530_hdw.c
        !            27:  *     Author: Alessandro Forin, Carnegie Mellon University
        !            28:  *     Date:   6/91
        !            29:  *
        !            30:  *     Hardware-level operations for the SCC Serial Line Driver
        !            31:  */
        !            32: 
        !            33: #define        NSCC    1       /* Number of serial chips, two ports per chip. */
        !            34: #if    NSCC > 0
        !            35: 
        !            36: /* #include <mach_kgdb.h> */
        !            37: 
        !            38: /* #include <platforms.h> */
        !            39: 
        !            40: /* #include <mach_kdb.h> */
        !            41: /* #include <kgdb/gdb_defs.h> */
        !            42: /* #include <kgdb/kgdb_defs.h> */    /* For kgdb_printf */
        !            43: 
        !            44: #include <kernserv/machine/spl.h>
        !            45: #include <mach/std_types.h>
        !            46: /* #include <types.h> */
        !            47: /* #include <sys/syslog.h> */
        !            48: /* #include <device/io_req.h> */
        !            49: /* #include <device/tty.h> */
        !            50: /* #include <chips/busses.h> */
        !            51: /* #include <ppc/misc_protos.h> */
        !            52: #include <machdep/ppc/proc_reg.h>
        !            53: #include <mach/machine/exception.h>
        !            54: #include <machdep/ppc/serial_io.h>
        !            55: #include <machdep/ppc/powermac.h>
        !            56: #include <machdep/ppc/interrupts.h>
        !            57: #include <machdep/ppc/scc_8530.h>
        !            58: 
        !            59: #define        kdebug_state()  (1)
        !            60: #define        scc_delay(x)    { volatile int _d_; for (_d_ = 0; _d_ < (10000*x); _d_++) ; }
        !            61: 
        !            62: #define        NSCC_LINE       2       /* 2 ttys per chip */
        !            63: 
        !            64: #if    !MACH_KGDB
        !            65: #define        SCC_DMA_TRANSFERS       1
        !            66: #else
        !            67: /* 
        !            68:  * Don't deal with DMA because of the way KGDB needs to handle
        !            69:  * the system and serial ports.
        !            70:  */
        !            71: #define        SCC_DMA_TRANSFERS       0
        !            72: #endif
        !            73:   
        !            74: /*struct tty scc_tty[NSCC_LINE];*/
        !            75: 
        !            76: #define scc_dev_no(chan)       (chan)
        !            77: /* #define scc_tty_for(chan)   (&scc_tty[chan]) */
        !            78: #define scc_unit(dev_no)       (dev_no)
        !            79: #define scc_chan(dev_no)       (dev_no)
        !            80: 
        !            81: int    serial_initted = 0;
        !            82: 
        !            83: static struct scc_byte {
        !            84:        unsigned char   reg;
        !            85:        unsigned char   val;
        !            86: } scc_init_hw[] = {
        !            87:        9, 0x40,        /* SCC_WR9_RESET_CHA_B */
        !            88:        4, 0x44,        /* SCC_WR4_CLK_x16| SCC_WR4_1_STOP, */
        !            89:        3, 0xC0,        /* SCC_WR3_RX_8_BITS| */
        !            90:        5, 0xE2,        /* SCC_WR5_DTR| SCC_WR5_TX_8_BITS| SCC_WR5_RTS, */
        !            91:        2, 0x00,
        !            92:        10, 0x00,       /* SCC_WR10_NRZ| SCC_WR10_8BIT_SYNCH, */
        !            93:        11, 0x50,       /* SCC_WR11_RCLK_BAUDR| SCC_WR11_XTLK_BAUDR|
        !            94:                           SCC_WR11_XTLK_RTc_PIN| SCC_WR11_TRcOUT_XTAL, */
        !            95:        12, 0x01,
        !            96:        13, 0x00,
        !            97:        3, 0xC1,        /* SCC_WR3_RX_8_BITS| SCC_WR3_RX_ENABLE, */
        !            98:        5, 0xEA,        /* SCC_WR5_DTR| SCC_WR5_TX_8_BITS|
        !            99:                           SCC_WR5_TX_ENABLE| SCC_WR5_RTS, */
        !           100:        14, 0x01,       /* SCC_WR14_BAUDR_ENABLE, */
        !           101:        15, 0x00,
        !           102:        0, 0x10,        /* SCC_RESET_EXT_IP, */
        !           103:        0, 0x10,        /* SCC_RESET_EXT_IP, */
        !           104:        1, 0x12,        /* SCC_WR1_RXI_ALL_CHAR|SCC_WR1_TX_IE, */
        !           105:        9, 0x0A         /* SCC_WR9_MASTER_IE| SCC_WR9_NV, */
        !           106: 
        !           107: };
        !           108: 
        !           109: static int     scc_init_hw_count = sizeof(scc_init_hw)/sizeof(scc_init_hw[0]);
        !           110: 
        !           111: enum scc_error {SCC_ERR_NONE, SCC_ERR_PARITY, SCC_ERR_BREAK, SCC_ERR_OVERRUN};
        !           112: 
        !           113: 
        !           114: /*
        !           115:  * BRG formula is:
        !           116:  *                             ClockFrequency (115200 for Power Mac)
        !           117:  *     BRGconstant =   ---------------------------  -  2
        !           118:  *                           BaudRate
        !           119:  */
        !           120: 
        !           121: #define SERIAL_CLOCK_FREQUENCY (115200*2) /* Power Mac value */
        !           122: #define        convert_baud_rate(rate) ((((SERIAL_CLOCK_FREQUENCY) + (rate)) / (2 * (rate))) - 2)
        !           123: 
        !           124: #define DEFAULT_SPEED 9600
        !           125: #define DEFAULT_FLAGS (TF_LITOUT|TF_ECHO)
        !           126: 
        !           127: #ifdef notdef_next
        !           128: void   scc_attach(struct bus_device *ui );
        !           129: void   scc_set_modem_control(scc_softc_t scc, boolean_t on);
        !           130: int    scc_pollc(int unit, boolean_t on);
        !           131: int    scc_param(struct tty *tp);
        !           132: int    scc_mctl(struct tty* tp, int bits, int how);
        !           133: int    scc_cd_scan(void);
        !           134: void   scc_start(struct tty *tp);
        !           135: void   scc_intr(int device, struct ppc_saved_state *);
        !           136: int    scc_simple_tint(dev_t dev, boolean_t all_sent);
        !           137: void   scc_input(dev_t dev, int c, enum scc_error err);
        !           138: void   scc_stop(struct tty *tp, int flags);
        !           139: void   scc_update_modem(struct tty *tp);
        !           140: void   scc_waitforempty(struct tty *tp);
        !           141: #endif /* notdef_next */
        !           142: 
        !           143: struct scc_softc       scc_softc[NSCC];
        !           144: caddr_t        scc_std[NSCC] = { (caddr_t) 0};
        !           145: 
        !           146: #ifdef notdef_next
        !           147: /*
        !           148:  * Definition of the driver for the auto-configuration program.
        !           149:  */
        !           150: 
        !           151: struct bus_device *scc_info[NSCC];
        !           152: 
        !           153: struct bus_driver scc_driver =
        !           154:         {scc_probe,
        !           155:         0,
        !           156:        scc_attach,
        !           157:         0,
        !           158:         scc_std,
        !           159:        "scc",
        !           160:        scc_info,
        !           161:        0,
        !           162:        0,
        !           163:        0
        !           164: };
        !           165: #endif /* notdef_next */
        !           166: 
        !           167: #if    SCC_DMA_TRANSFERS
        !           168: 
        !           169: extern struct scc_dma_ops      scc_amic_ops /*, scc_db_ops*/;
        !           170: #endif
        !           171: 
        !           172: /*
        !           173:  * Adapt/Probe/Attach functions
        !           174:  */
        !           175: boolean_t      scc_uses_modem_control = FALSE;/* patch this with adb */
        !           176: 
        !           177: /* This is called VERY early on in the init and therefore has to have
        !           178:  * hardcoded addresses of the serial hardware control registers. The
        !           179:  * serial line may be needed for console and debugging output before
        !           180:  * anything else takes place
        !           181:  */
        !           182: 
        !           183: void
        !           184: initialize_serial()
        !           185: {
        !           186:        int i, chan, bits;
        !           187:        scc_regmap_t    regs;
        !           188:        /* static struct bus_device d; */ 
        !           189: 
        !           190:        if (serial_initted) 
        !           191:                return;
        !           192: 
        !           193:        // If this machine has PMU then turn on the serial ports.
        !           194:        if (HasPMU()) {
        !           195:          volatile unsigned long *ohareFeatureCntl;
        !           196:          
        !           197:          ohareFeatureCntl = powermac_io_info.io_base_phys + 0x38;
        !           198:          
        !           199:          *ohareFeatureCntl &= ~(1 << 24);
        !           200:          eieio();
        !           201:          *ohareFeatureCntl |= (1 << 17) | ( 1 << 22) | (1 << 23);
        !           202:          eieio();
        !           203:        }
        !           204: 
        !           205:        scc_softc[0].full_modem = TRUE;
        !           206: 
        !           207:        scc_std[0] = (caddr_t) PCI_SCC_BASE_PHYS;
        !           208: 
        !           209:        regs = scc_softc[0].regs = (scc_regmap_t)scc_std[0];
        !           210: 
        !           211:        scc_write_reg(regs, 0, 9, 0xc0); /* hard reset */
        !           212:        scc_delay(100);
        !           213:        for (chan = 0; chan < NSCC_LINE; chan++) {
        !           214:                if (chan == 1)
        !           215:                        scc_init_hw[0].val = 0x80;
        !           216: 
        !           217:                for (i = 0; i < scc_init_hw_count; i++) {
        !           218:                        if (scc_init_hw[i].reg == 0xff) {
        !           219:                                scc_delay(100);
        !           220:                        } else
        !           221:                        scc_write_reg(regs, chan,
        !           222:                                      scc_init_hw[i].reg, scc_init_hw[i].val);
        !           223:                }
        !           224:        }
        !           225: 
        !           226: #ifdef notdef_next
        !           227:        /* Call probe so we are ready very early for remote gdb and for serial
        !           228:           console output if appropriate.  */
        !           229:        /* d.unit = 0; */
        !           230:        if (scc_probe(0, (void *) &d)) {
        !           231:                for (i = 0; i < NSCC_LINE; i++) {
        !           232:                        scc_softc[0].softr[i].wr5 = SCC_WR5_DTR | SCC_WR5_RTS;
        !           233:                        scc_param(scc_tty_for(i));
        !           234:        /* Enable SCC interrupts (how many interrupts are to this thing?!?) */
        !           235:                        scc_write_reg(regs,  i,  9, SCC_WR9_NV);
        !           236: 
        !           237:                        scc_read_reg_zero(regs, 0, bits);/* Clear the status */
        !           238:                }
        !           239:        }
        !           240: #endif /* notdef_next */
        !           241: 
        !           242:        serial_initted = TRUE;
        !           243:        return;
        !           244: }
        !           245: 
        !           246: #ifdef notdef_next
        !           247: int
        !           248: scc_probe(caddr_t  xxx, void *param)
        !           249: {
        !           250:        struct bus_device *ui = (struct bus_device *) param;
        !           251:        scc_softc_t     scc;
        !           252:        register int    val, i;
        !           253:        register scc_regmap_t   regs;
        !           254:        spl_t   s;
        !           255: 
        !           256:        /* Readjust the I/O address to handling 
        !           257:         * new memory mappings.
        !           258:         */
        !           259: 
        !           260:        scc_std[0] = POWERMAC_IO(scc_std[0]);
        !           261: 
        !           262:        regs = (scc_regmap_t)scc_std[0];
        !           263: 
        !           264:        if (regs == (scc_regmap_t) 0) {
        !           265:                return 0;
        !           266:        }
        !           267: 
        !           268:        scc = &scc_softc[0];
        !           269:        scc->regs = regs;
        !           270: 
        !           271:        if (scc->probed_once++){
        !           272:                /* Second time in means called from system */
        !           273: 
        !           274:                switch (powermac_info.class) {
        !           275:                case    POWERMAC_CLASS_PDM:
        !           276: #if    SCC_DMA_TRANSFERS
        !           277:                        scc_softc[0].dma_ops = &scc_amic_ops;
        !           278: #endif
        !           279:                        pmac_register_int(PMAC_DEV_SCC, SPLTTY,
        !           280:                                          (void (*)(int, void *))scc_intr);
        !           281:                        break;
        !           282: 
        !           283:                case    POWERMAC_CLASS_PCI:
        !           284: #if    SCC_DMA_TRANSFERS
        !           285:                        /*scc_softc[0].dma_ops = &scc_db_ops;*/
        !           286: #endif
        !           287:                        pmac_register_int(PMAC_DEV_SCC_A, SPLTTY,
        !           288:                                          (void (*)(int, void *))scc_intr);
        !           289:                        pmac_register_int(PMAC_DEV_SCC_B, SPLTTY,
        !           290:                                          (void (*)(int, void *))scc_intr);
        !           291:                        break;
        !           292:                default:
        !           293:                        panic("unsupported class for serial code\n");
        !           294:                }
        !           295: 
        !           296:                return 1;
        !           297:        }
        !           298: 
        !           299:        s = spltty();
        !           300: 
        !           301:        for (i = 0; i < NSCC_LINE; i++) {
        !           302:                register struct tty     *tp;
        !           303:                tp = scc_tty_for(i);
        !           304:                simple_lock_init(&tp->t_lock);
        !           305:                tp->t_addr = (char*)(0x80000000L + (i&1));
        !           306:                /* Set default values.  These will be overridden on
        !           307:                   open but are needed if the port will be used
        !           308:                   independently of the Mach interfaces, e.g., for
        !           309:                   gdb or for a serial console.  */
        !           310:                tp->t_ispeed = DEFAULT_SPEED;
        !           311:                tp->t_ospeed = DEFAULT_SPEED;
        !           312:                tp->t_flags = DEFAULT_FLAGS;
        !           313:                scc->softr[i].speed = -1;
        !           314: 
        !           315:                /* do min buffering */
        !           316:                tp->t_state |= TS_MIN;
        !           317: 
        !           318:                tp->t_dev = scc_dev_no(i);
        !           319:        }
        !           320: 
        !           321:        splx(s);
        !           322: 
        !           323:        return 1;
        !           324: }
        !           325: 
        !           326: boolean_t scc_timer_started = FALSE;
        !           327: 
        !           328: void
        !           329: scc_attach( register struct bus_device *ui )
        !           330: {
        !           331:        extern int tty_inq_size, tty_outq_size;
        !           332:        int i;
        !           333:        struct tty *tp;
        !           334: 
        !           335: #if    SCC_DMA_TRANSFERS
        !           336:        /* DMA Serial can send a lot... ;-) */
        !           337:        tty_inq_size = 16384;
        !           338:        tty_outq_size = 16384;
        !           339: 
        !           340:        for (i = 0; i < NSCC_LINE; i++) {
        !           341:                if (scc_softc[0].dma_ops) {
        !           342:                        scc_softc[0].dma_ops->scc_dma_init(i);
        !           343:                        scc_softc[0].dma_initted |= (1<<i);
        !           344:                }
        !           345:        }
        !           346: #endif
        !           347: 
        !           348:        if (!scc_timer_started) {
        !           349:                /* do all of them, before we call scc_scan() */
        !           350:                /* harmless if done already */
        !           351:                for (i = 0; i < NSCC_LINE; i++)  {
        !           352:                        tp = scc_tty_for(i);
        !           353:                        ttychars(tp);
        !           354:                        /* hack MEB 1/5/96 */
        !           355:                        tp->t_state |= TS_CARR_ON;
        !           356:                        scc_softc[0].modem[i] = 0;
        !           357:                }
        !           358: 
        !           359:                scc_timer_started = TRUE;
        !           360:                scc_cd_scan();
        !           361:        }
        !           362: 
        !           363:        printf("\n sl0: ( alternate console )\n sl1:");
        !           364:        return;
        !           365: }
        !           366: 
        !           367: /*
        !           368:  * Would you like to make a phone call ?
        !           369:  */
        !           370: 
        !           371: void
        !           372: scc_set_modem_control(scc, on)
        !           373:        scc_softc_t      scc;
        !           374:        boolean_t       on;
        !           375: {
        !           376:        scc->full_modem = on;
        !           377:        /* user should do an scc_param() ifchanged */
        !           378: }
        !           379: 
        !           380: /*
        !           381:  * Polled I/O (debugger)
        !           382:  */
        !           383: 
        !           384: int
        !           385: scc_pollc(int unit, boolean_t on)
        !           386: {
        !           387:        scc_softc_t             scc;
        !           388: 
        !           389:        scc = &scc_softc[unit];
        !           390:        if (on) {
        !           391:                scc->polling_mode++;
        !           392:        } else
        !           393:                scc->polling_mode--;
        !           394: 
        !           395:        return 0;
        !           396: }
        !           397: 
        !           398: /*
        !           399:  * Interrupt routine
        !           400:  */
        !           401: int scc_intr_count;
        !           402: 
        !           403: void
        !           404: scc_intr(int device, struct ppc_saved_state *ssp)
        !           405: {
        !           406:        int                     chan;
        !           407:        scc_softc_t             scc = &scc_softc[0];
        !           408:        register scc_regmap_t   regs = scc->regs;
        !           409:        register int            rr1, rr2, status;
        !           410:        register int            c;
        !           411: 
        !           412: scc_intr_count++;
        !           413: 
        !           414:        scc_read_reg_zero(regs, 0, status);/* Clear the status */
        !           415: 
        !           416:        scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR2, rr2);
        !           417: 
        !           418:        rr2 = SCC_RR2_STATUS(rr2);
        !           419: 
        !           420:        /*printf("{INTR %x}", rr2);*/
        !           421:        if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) {
        !           422: 
        !           423:                chan = (rr2 == SCC_RR2_A_XMIT_DONE) ?
        !           424:                                        SCC_CHANNEL_A : SCC_CHANNEL_B;
        !           425: 
        !           426:                scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_TX_IP);
        !           427: 
        !           428:                c = scc_simple_tint(scc_dev_no(chan), FALSE);
        !           429: 
        !           430:                if (c == -1) {
        !           431:                        /* no more data for this line */
        !           432:                        c = scc->softr[chan].wr1 & ~SCC_WR1_TX_IE;
        !           433:                        scc_write_reg(regs, chan, SCC_WR1, c);
        !           434:                        scc->softr[chan].wr1 = c;
        !           435: 
        !           436:                        c = scc_simple_tint(scc_dev_no(chan), TRUE);
        !           437:                        if (c != -1) {
        !           438:                                /* funny race, scc_start has been called
        !           439:                                   already */
        !           440:                                scc_write_data(regs, chan, c);
        !           441:                        }
        !           442:                } else {
        !           443: 
        !           444:                        scc_write_data(regs, chan, c);
        !           445:                        /* and leave it enabled */
        !           446:                }
        !           447:        }
        !           448: 
        !           449:        else if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_B_RECV_DONE) {
        !           450:                int     err = 0;
        !           451:                chan = (rr2 == SCC_RR2_A_RECV_DONE) ?
        !           452:                                        SCC_CHANNEL_A : SCC_CHANNEL_B;
        !           453: 
        !           454:                scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0,
        !           455:                              SCC_RESET_HIGHEST_IUS);
        !           456: 
        !           457: #if MACH_KGDB
        !           458:                if (chan == KGDB_PORT) {
        !           459:                        /* 11/10/95 MEB
        !           460:                         * Drop into the debugger.. scc_getc() will
        !           461:                         * pick up the character
        !           462:                         */
        !           463: 
        !           464:                        call_kgdb_with_ctx(EXC_INTERRUPT, 0, ssp);
        !           465:                        goto next_intr;
        !           466:                }
        !           467: #endif
        !           468: 
        !           469:                scc_read_data(regs, chan, c);
        !           470: 
        !           471:                scc_input(scc_dev_no(chan), c, SCC_ERR_NONE);
        !           472:        }
        !           473: 
        !           474:        else if ((rr2 == SCC_RR2_A_EXT_STATUS) ||
        !           475:                 (rr2 == SCC_RR2_B_EXT_STATUS)) {
        !           476:                chan = (rr2 == SCC_RR2_A_EXT_STATUS) ?
        !           477:                        SCC_CHANNEL_A : SCC_CHANNEL_B;
        !           478: 
        !           479:                scc_read_reg(regs, chan, SCC_RR0, status);
        !           480:                if (status & SCC_RR0_TX_UNDERRUN)
        !           481:                        scc_write_reg(regs, chan, SCC_RR0,
        !           482:                                      SCC_RESET_TXURUN_LATCH);
        !           483:                if (status & SCC_RR0_BREAK)
        !           484:                        scc_input(scc_dev_no(chan), 0, SCC_ERR_BREAK);
        !           485: 
        !           486:                scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_EXT_IP);
        !           487:                scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_HIGHEST_IUS);
        !           488:                scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR);
        !           489: 
        !           490:                /* Update the modem lines */
        !           491:                scc_update_modem(&scc_tty[chan]);
        !           492:        }
        !           493: 
        !           494:        else if ((rr2 == SCC_RR2_A_RECV_SPECIAL) ||
        !           495:                 (rr2 == SCC_RR2_B_RECV_SPECIAL)) {
        !           496:                chan = (rr2 == SCC_RR2_A_RECV_SPECIAL) ?
        !           497:                        SCC_CHANNEL_A : SCC_CHANNEL_B;
        !           498: 
        !           499:                scc_read_reg(regs, chan, SCC_RR1, rr1);
        !           500: #if SCC_DMA_TRANSFERS
        !           501:                if (scc->dma_initted & (chan<<1)) {
        !           502:                        scc->dma_ops->scc_dma_reset_rx(chan);
        !           503:                        scc->dma_ops->scc_dma_start_rx(chan);
        !           504:                }
        !           505: #endif
        !           506:                if (rr1 & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
        !           507:                        enum scc_error err;
        !           508:                        scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR);
        !           509:                        if (rr1 & SCC_RR1_FRAME_ERR)
        !           510:                                err = SCC_ERR_BREAK;
        !           511:                        else if (rr1 & SCC_RR1_PARITY_ERR)
        !           512:                                err = SCC_ERR_OVERRUN;
        !           513:                        else {
        !           514:                                assert(rr1 & SCC_RR1_RX_OVERRUN);
        !           515:                                err = SCC_ERR_OVERRUN;
        !           516:                        }
        !           517: #if SCC_DMA_TRANSFERS
        !           518:                        if ((scc->dma_initted & (chan<<1)) == 0)
        !           519: #endif
        !           520:                                scc_input(scc_dev_no(chan), 0, err);
        !           521:                }
        !           522:                scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
        !           523:        }
        !           524: 
        !           525: next_intr:
        !           526:        return;
        !           527: }
        !           528: 
        !           529: 
        !           530: /*
        !           531:  * Start output on a line
        !           532:  */
        !           533: 
        !           534: void
        !           535: scc_start(tp)
        !           536:        struct tty *tp;
        !           537: {
        !           538:        spl_t                   s;
        !           539:        int                     cc;
        !           540:        scc_regmap_t    regs;
        !           541:        int                     chan = scc_chan(tp->t_dev), temp;
        !           542:        struct scc_softreg      *sr = &scc_softc[0].softr[chan];
        !           543:        scc_softc_t             scc = &scc_softc[0];
        !           544: 
        !           545:        s = spltty();
        !           546: 
        !           547:        /* Start up the DMA channel if it was paused */
        !           548:        if ((tp->t_state & TS_TTSTOP) == 0 && sr->dma_flags & SCC_FLAGS_DMA_PAUSED) {
        !           549:                /*printf("{DMA RESUME}");*/
        !           550:                scc->dma_ops->scc_dma_continue_tx(chan);
        !           551:                splx(s);
        !           552:                return;
        !           553:        }
        !           554: 
        !           555:        if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 
        !           556:                goto out;
        !           557: 
        !           558: 
        !           559: #if    SCC_DMA_TRANSFERS
        !           560:        if (scc_softc[0].dma_initted & (1<<chan)) {
        !           561:                /* Don't worry about low water marks...
        !           562:                 * The DMA operation should be able to pull off most
        !           563:                 * if not all of the TTY output queue
        !           564:                */
        !           565:        
        !           566:                tt_write_wakeup(tp);
        !           567: 
        !           568:                if (tp->t_outq.c_cc <= 0) 
        !           569:                        goto out;
        !           570: 
        !           571:                tp->t_state |= TS_BUSY;
        !           572: 
        !           573:                scc_softc[0].dma_ops->scc_dma_start_tx(chan, tp);
        !           574:        } else 
        !           575: #endif
        !           576:        {
        !           577:                cc = tp->t_outq.c_cc;
        !           578:                if (cc <= TTLOWAT(tp)) {
        !           579:                        tt_write_wakeup(tp);
        !           580:                }
        !           581:                if (cc <= 0)
        !           582:                        goto out;
        !           583:                tp->t_state |= TS_BUSY;
        !           584:        
        !           585:                regs = scc_softc[0].regs;
        !           586:                sr   = &scc_softc[0].softr[chan];
        !           587:        
        !           588:                scc_read_reg(regs, chan, SCC_RR15, temp);
        !           589:                temp |= SCC_WR15_TX_UNDERRUN_IE;
        !           590:                scc_write_reg(regs, chan, SCC_WR15, temp);
        !           591:        
        !           592:                temp = sr->wr1 | SCC_WR1_TX_IE;
        !           593:                scc_write_reg(regs, chan, SCC_WR1, temp);
        !           594:                sr->wr1 = temp;
        !           595:        
        !           596:                /* but we need a first char out or no cookie */
        !           597:                scc_read_reg(regs, chan, SCC_RR0, temp);
        !           598:                if (temp & SCC_RR0_TX_EMPTY)
        !           599:                {
        !           600:                        register char   c;
        !           601:        
        !           602:                        c = getc(&tp->t_outq);
        !           603:                        scc_write_data(regs, chan, c);
        !           604:                }
        !           605:        }
        !           606: out:
        !           607:        splx(s);
        !           608: }
        !           609: 
        !           610: #define        u_min(a,b)      ((a) < (b) ? (a) : (b))
        !           611: #endif /* notdef_next */
        !           612: 
        !           613: /*
        !           614:  * Get a char from a specific SCC line
        !           615:  * [this is only used for console&screen purposes]
        !           616:  */
        !           617: 
        !           618: int
        !           619: scc_getc(int unit, int line, boolean_t wait, boolean_t raw)
        !           620: {
        !           621:        register scc_regmap_t   regs;
        !           622:        unsigned char   c, value;
        !           623:        int             rcvalue, from_line;
        !           624:        spl_t           s = spltty();
        !           625: 
        !           626:        regs = scc_softc[0].regs;
        !           627: 
        !           628:        /*
        !           629:         * wait till something available
        !           630:         *
        !           631:         */
        !           632: again:
        !           633:        rcvalue = 0;
        !           634:        while (1) {
        !           635:                scc_read_reg_zero(regs, line, value);
        !           636: 
        !           637:                if (value & SCC_RR0_RX_AVAIL)
        !           638:                        break;
        !           639: 
        !           640:                if (!wait) {
        !           641:                        splx(s);
        !           642:                        return -1;
        !           643:                }
        !           644:        }
        !           645: 
        !           646:        /*
        !           647:         * if nothing found return -1
        !           648:         */
        !           649: 
        !           650:        scc_read_reg(regs, line, SCC_RR1, value);
        !           651:        scc_read_data(regs, line, c);
        !           652: 
        !           653:        /*
        !           654:         * bad chars not ok
        !           655:         */
        !           656:        if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
        !           657:                scc_write_reg(regs, line, SCC_RR0, SCC_RESET_ERROR);
        !           658: 
        !           659:                if (wait) {
        !           660:                        scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
        !           661:                        goto again;
        !           662:                }
        !           663:        }
        !           664: 
        !           665:        scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
        !           666:        splx(s);
        !           667: 
        !           668:        return c;
        !           669: }
        !           670: 
        !           671: /*
        !           672:  * Put a char on a specific SCC line
        !           673:  */
        !           674: 
        !           675: int
        !           676: scc_putc(int unit, int line, int c)
        !           677: {
        !           678:        scc_regmap_t    regs;
        !           679:        spl_t            s = spltty();
        !           680:        unsigned char    value;
        !           681: 
        !           682:        regs = scc_softc[0].regs;
        !           683: 
        !           684:        do {
        !           685:                scc_read_reg(regs, line, SCC_RR0, value);
        !           686:                if (value & SCC_RR0_TX_EMPTY)
        !           687:                        break;
        !           688:                scc_delay(100);
        !           689:        } while (1);
        !           690: 
        !           691:        scc_write_data(regs, line, c);
        !           692: /* wait for it to swallow the char ? */
        !           693: 
        !           694:        do {
        !           695:                scc_read_reg(regs, line, SCC_RR0, value);
        !           696:                if (value & SCC_RR0_TX_EMPTY)
        !           697:                        break;
        !           698:        } while (1);
        !           699:        scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS);
        !           700:        splx(s);
        !           701: 
        !           702:        return 0;
        !           703: }
        !           704: 
        !           705: #ifdef notdef_next
        !           706: int
        !           707: scc_param(struct tty *tp)
        !           708: {
        !           709:        scc_regmap_t    regs;
        !           710:        unsigned char   value;
        !           711:        unsigned short  speed_value;
        !           712:        int             bits, chan;
        !           713:        spl_t           s;
        !           714:        struct scc_softreg      *sr;
        !           715:        scc_softc_t     scc;
        !           716: 
        !           717:        chan = scc_chan(tp->t_dev);
        !           718:        scc = &scc_softc[0];
        !           719:        regs = scc->regs;
        !           720: 
        !           721:        sr = &scc->softr[chan];
        !           722: 
        !           723:        /* Do a quick check to see if the hardware needs to change */
        !           724:        if ((sr->flags & (TF_ODDP|TF_EVENP)) == (tp->t_flags & (TF_ODDP|TF_EVENP))
        !           725:        && sr->speed == tp->t_ispeed) 
        !           726:                return 0;
        !           727: 
        !           728:        sr->flags = tp->t_flags;
        !           729:        sr->speed = tp->t_ispeed;
        !           730: 
        !           731:        s = spltty();
        !           732: 
        !           733:        if (tp->t_ispeed == 0) {
        !           734:                sr->wr5 &= ~SCC_WR5_DTR;
        !           735:                scc_write_reg(regs,  chan, 5, sr->wr5);
        !           736:                splx(s);
        !           737: 
        !           738:                return 0;
        !           739:        }
        !           740:        
        !           741: 
        !           742: #if    SCC_DMA_TRANSFERS
        !           743:        if (scc->dma_initted & (1<<chan)) 
        !           744:                scc->dma_ops->scc_dma_reset_rx(chan);
        !           745: #endif
        !           746: 
        !           747:        value = SCC_WR4_1_STOP;
        !           748: 
        !           749:        /* 
        !           750:         * For 115K the clocking divide changes to 64.. to 230K will
        !           751:         * start at the normal clock divide 16.
        !           752:         *
        !           753:         * However, both speeds will pull from a different clocking
        !           754:         * source
        !           755:         */
        !           756: 
        !           757:        if (tp->t_ispeed == 115200)
        !           758:                value |= SCC_WR4_CLK_x32;
        !           759:        else    
        !           760:                value |= SCC_WR4_CLK_x16 ;
        !           761: 
        !           762:        /* .. and parity */
        !           763:        if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_EVENP)
        !           764:                value |= (SCC_WR4_EVEN_PARITY |  SCC_WR4_PARITY_ENABLE);
        !           765:        else if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_ODDP)
        !           766:                value |= SCC_WR4_PARITY_ENABLE;
        !           767: 
        !           768:        /* set it now, remember it must be first after reset */
        !           769:        sr->wr4 = value;
        !           770: 
        !           771:        /* Program Parity, and Stop bits */
        !           772:        scc_write_reg(regs,  chan, 4, sr->wr4);
        !           773: 
        !           774:        /* Setup for 8 bits */
        !           775:        scc_write_reg(regs,  chan, 3, SCC_WR3_RX_8_BITS);
        !           776: 
        !           777:        // Set DTR, RTS, and transmitter bits/character.
        !           778:        sr->wr5 = SCC_WR5_TX_8_BITS | SCC_WR5_RTS | SCC_WR5_DTR;
        !           779: 
        !           780:        scc_write_reg(regs,  chan, 5, sr->wr5);
        !           781:        
        !           782:        scc_write_reg(regs, chan, 14, 0);       /* Disable baud rate */
        !           783: 
        !           784:        /* Setup baud rate 57.6Kbps, 115K, 230K should all yeild
        !           785:         * a converted baud rate of zero
        !           786:         */
        !           787:        speed_value = convert_baud_rate(tp->t_ispeed);
        !           788: 
        !           789:        if (speed_value == 0xffff)
        !           790:                speed_value = 0;
        !           791: 
        !           792:        scc_set_timing_base(regs, chan, speed_value);
        !           793:        
        !           794:        if (tp->t_ispeed == 115200 || tp->t_ispeed == 230400) {
        !           795:                /* Special case here.. change the clock source*/
        !           796:                scc_write_reg(regs, chan, 11, 0);
        !           797:                /* Baud rate generator is disabled.. */
        !           798:        } else {
        !           799:                scc_write_reg(regs, chan, 11, SCC_WR11_RCLK_BAUDR|SCC_WR11_XTLK_BAUDR);
        !           800:                /* Enable the baud rate generator */
        !           801:                scc_write_reg(regs,  chan, 14, SCC_WR14_BAUDR_ENABLE);
        !           802:        }
        !           803: 
        !           804: 
        !           805:        scc_write_reg(regs,  chan,  3, SCC_WR3_RX_8_BITS|SCC_WR3_RX_ENABLE);
        !           806: 
        !           807: 
        !           808:        sr->wr1 = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_EXT_IE;
        !           809:        scc_write_reg(regs,  chan,  1, sr->wr1);
        !           810:        
        !           811:        scc_write_reg(regs,  chan, 15, 0);
        !           812: 
        !           813:        /* Clear out any pending external or status interrupts */
        !           814:        scc_write_reg(regs,  chan,  0, SCC_RESET_EXT_IP);
        !           815:        scc_write_reg(regs,  chan,  0, SCC_RESET_EXT_IP);
        !           816:        //scc_write_reg(regs,  chan,  0, SCC_RESET_ERROR);
        !           817:        scc_write_reg(regs,  chan,  0, SCC_IE_NEXT_CHAR);
        !           818: 
        !           819:        /* Enable SCC interrupts (how many interrupts are to this thing?!?) */
        !           820:        scc_write_reg(regs,  chan,  9, SCC_WR9_MASTER_IE|SCC_WR9_NV);
        !           821: 
        !           822:        scc_read_reg_zero(regs, 0, bits);/* Clear the status */
        !           823: 
        !           824: #if    SCC_DMA_TRANSFERS
        !           825:        if (scc->dma_initted & (1<<chan))  {
        !           826:                scc->dma_ops->scc_dma_start_rx(chan);
        !           827:                scc->dma_ops->scc_dma_setup_8530(chan);
        !           828:        } else
        !           829: #endif
        !           830:        {
        !           831:                sr->wr1 = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_EXT_IE;
        !           832:                scc_write_reg(regs, chan, 1, sr->wr1);
        !           833:        }
        !           834: 
        !           835:        sr->wr5 |= SCC_WR5_TX_ENABLE;
        !           836:        scc_write_reg(regs,  chan,  5, sr->wr5);
        !           837: 
        !           838:        splx(s);
        !           839: 
        !           840:        return 0;
        !           841: 
        !           842: }
        !           843: 
        !           844: void
        !           845: scc_update_modem(struct tty *tp)
        !           846: {
        !           847:        scc_softc_t scc = &scc_softc[0];
        !           848:        int chan = scc_chan(tp->t_dev);
        !           849:        scc_regmap_t    regs = scc->regs;
        !           850:        unsigned char rr0, old_modem;
        !           851: 
        !           852:        old_modem = scc->modem[chan];
        !           853:        scc->modem[chan] &= ~(TM_CTS|TM_CAR|TM_RNG|TM_DSR);
        !           854:        scc->modem[chan] |= TM_DSR|TM_CTS;
        !           855: 
        !           856:        scc_read_reg_zero(regs, chan, rr0);
        !           857: 
        !           858:        if (rr0 & SCC_RR0_DCD) {
        !           859:                scc->modem[chan] |= TM_CAR;
        !           860:                if ((old_modem & TM_CAR) == 0) {
        !           861:                        /*printf("{DTR-ON %x/%x}", rr0, old_modem);*/
        !           862:                        /*
        !           863:                         * The trick here is that
        !           864:                         * the device_open does not hang
        !           865:                         * waiting for DCD, but a message
        !           866:                         * is sent to the process 
        !           867:                         */
        !           868: 
        !           869:                        if ((tp->t_state & (TS_ISOPEN|TS_WOPEN))
        !           870:                        && tp->t_flags & TF_OUT_OF_BAND) {
        !           871:                                /*printf("{NOTIFY}");*/
        !           872:                                tp->t_outofband = TOOB_CARRIER;
        !           873:                                tp->t_outofbandarg = TRUE;
        !           874:                                tty_queue_completion(&tp->t_delayed_read);
        !           875:                        }
        !           876:                }
        !           877:        } else if (old_modem & TM_CAR) {
        !           878:                if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
        !           879:                        /*printf("{DTR-OFF %x/%x}", rr0, old_modem);*/
        !           880: 
        !           881:                        if (tp->t_flags & TF_OUT_OF_BAND) {
        !           882:                                tp->t_outofband = TOOB_CARRIER;
        !           883:                                tp->t_outofbandarg = FALSE;
        !           884:                                tty_queue_completion(&tp->t_delayed_read);
        !           885:                        } else
        !           886:                                ttymodem(tp, FALSE);
        !           887:                }
        !           888:        }
        !           889: }
        !           890: 
        !           891: /*
        !           892:  * Modem control functions
        !           893:  */
        !           894: int
        !           895: scc_mctl(struct tty* tty, int bits, int how)
        !           896: {
        !           897:        register dev_t dev = tty->t_dev;
        !           898:        int sccline;
        !           899:        register int tcr, msr, brk, n_tcr, n_brk;
        !           900:        int b;
        !           901:        scc_softc_t      scc;
        !           902:        int wr5;
        !           903: 
        !           904:        sccline = scc_chan(dev);
        !           905: 
        !           906:        if (bits == TM_HUP) {   /* close line (internal) */
        !           907:            bits = TM_DTR | TM_RTS;
        !           908:            how = DMBIC;
        !           909:        }
        !           910: 
        !           911:        scc = &scc_softc[0];
        !           912:        wr5 = scc->softr[sccline].wr5;
        !           913: 
        !           914:        if (how == DMGET) {
        !           915:            scc_update_modem(tty);
        !           916:            return scc->modem[sccline];
        !           917:        }
        !           918: 
        !           919:        switch (how) {
        !           920:        case DMSET:
        !           921:            b = bits; break;
        !           922:        case DMBIS:
        !           923:            b = scc->modem[sccline] | bits; break;
        !           924:        case DMBIC:
        !           925:            b = scc->modem[sccline] & ~bits; break;
        !           926:        default:
        !           927:            return 0;
        !           928:        }
        !           929: 
        !           930:        if (scc->modem[sccline] == b)
        !           931:            return b;
        !           932: 
        !           933:        scc->modem[sccline] = b;
        !           934: 
        !           935:        if (bits & TM_BRK) {
        !           936:            ttydrain(tty);
        !           937:            scc_waitforempty(tty);
        !           938:        }
        !           939: 
        !           940:        wr5 &= ~(SCC_WR5_SEND_BREAK|SCC_WR5_DTR);
        !           941: 
        !           942:        if (b & TM_BRK)
        !           943:                wr5 |= SCC_WR5_SEND_BREAK;
        !           944: 
        !           945:        if (b & TM_DTR)
        !           946:                wr5 |= SCC_WR5_DTR;
        !           947: 
        !           948:        wr5 |= SCC_WR5_RTS;
        !           949: 
        !           950:        scc_write_reg(scc->regs, sccline, 5, wr5);
        !           951:        scc->softr[sccline].wr5 = wr5;
        !           952: 
        !           953:        return scc->modem[sccline];
        !           954: }
        !           955: 
        !           956: /*
        !           957:  * Periodically look at the CD signals:
        !           958:  * they do generate interrupts but we
        !           959:  * must fake them on channel A.  We might
        !           960:  * also fake them on channel B.
        !           961:  */
        !           962: 
        !           963: int
        !           964: scc_cd_scan(void)
        !           965: {
        !           966:        spl_t s = spltty();
        !           967:        scc_softc_t     scc;
        !           968:        int             j;
        !           969: 
        !           970:        scc = &scc_softc[0];
        !           971:        for (j = 0; j < NSCC_LINE; j++) {
        !           972:                if (scc_tty[j].t_state & (TS_ISOPEN|TS_WOPEN))
        !           973:                        scc_update_modem(&scc_tty[j]);
        !           974:        }
        !           975:        splx(s);
        !           976: 
        !           977:        timeout((timeout_fcn_t)scc_cd_scan, (void *)0, hz/4);
        !           978: 
        !           979:        return 0;
        !           980: }
        !           981: 
        !           982: #if MACH_KGDB
        !           983: void no_spl_scc_putc(int chan, char c)
        !           984: {
        !           985:        register scc_regmap_t   regs;
        !           986:        register unsigned char  value;
        !           987: 
        !           988:        if (!serial_initted)
        !           989:                initialize_serial();
        !           990: 
        !           991:        regs = scc_softc[0].regs;
        !           992: 
        !           993:        do {
        !           994:                scc_read_reg(regs, chan, SCC_RR0, value);
        !           995:                if (value & SCC_RR0_TX_EMPTY)
        !           996:                        break;
        !           997:                scc_delay(100);
        !           998:        } while (1);
        !           999: 
        !          1000:        scc_write_data(regs, chan, c);
        !          1001: /* wait for it to swallow the char ? */
        !          1002: 
        !          1003:        do {
        !          1004:                scc_read_reg(regs, chan, SCC_RR0, value);
        !          1005:                if (value & SCC_RR0_TX_EMPTY)
        !          1006:                        break;
        !          1007:        } while (1);
        !          1008:        scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_HIGHEST_IUS);
        !          1009: 
        !          1010:        if (c == '\n')
        !          1011:                no_spl_scc_putc(chan, '\r');
        !          1012:  
        !          1013: }
        !          1014: 
        !          1015: #define        SCC_KGDB_BUFFER 15
        !          1016: 
        !          1017: int no_spl_scc_getc(int chan, boolean_t timeout)
        !          1018: {
        !          1019:        register scc_regmap_t   regs;
        !          1020:        unsigned char   c, value, i;
        !          1021:        int             rcvalue, from_line;
        !          1022:        int     timeremaining = timeout ? 10000000 : 0; /* XXX */
        !          1023:        static unsigned char    buffer[2][SCC_KGDB_BUFFER];
        !          1024:        static int              bufcnt[2], bufidx[2];
        !          1025: 
        !          1026:        /* This should be rewritten to produce a constant timeout
        !          1027:           regardless of the processor speed.  */
        !          1028: 
        !          1029:        if (!serial_initted)
        !          1030:                initialize_serial();
        !          1031: 
        !          1032:        regs = scc_softc[0].regs;
        !          1033: 
        !          1034: get_char:
        !          1035:        if (bufcnt[chan]) {
        !          1036:                bufcnt[chan] --;
        !          1037:                return ((unsigned int) buffer[chan][bufidx[chan]++]);
        !          1038:        }
        !          1039: 
        !          1040:        /*
        !          1041:         * wait till something available
        !          1042:         *
        !          1043:         */
        !          1044:        bufidx[chan] = 0;
        !          1045: 
        !          1046:        for (i = 0; i < SCC_KGDB_BUFFER; i++) {
        !          1047:                rcvalue = 0;
        !          1048: 
        !          1049:                while (1) {
        !          1050:                        scc_read_reg_zero(regs, chan, value);
        !          1051:                        if (value & SCC_RR0_RX_AVAIL)
        !          1052:                                break;
        !          1053:                        if (timeremaining && !--timeremaining) {
        !          1054:                                if (i)
        !          1055:                                        goto get_char;
        !          1056:                                else
        !          1057:                                        return KGDB_GETC_TIMEOUT;
        !          1058:                        }
        !          1059:                }
        !          1060: 
        !          1061:                scc_read_reg(regs, chan, SCC_RR1, value);
        !          1062:                scc_read_data(regs, chan, c);
        !          1063:                buffer[chan][bufcnt[chan]] = c;
        !          1064:                bufcnt[chan]++;
        !          1065: 
        !          1066:                /*
        !          1067:                 * bad chars not ok
        !          1068:                 */
        !          1069: 
        !          1070: 
        !          1071:                if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
        !          1072:                        scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR);
        !          1073: 
        !          1074:                        scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_HIGHEST_IUS);
        !          1075:                        bufcnt[chan] = 0;
        !          1076:                        return KGDB_GETC_BAD_CHAR;
        !          1077:                }
        !          1078: 
        !          1079:                        
        !          1080:                scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_HIGHEST_IUS);
        !          1081:                
        !          1082:                for (timeremaining = 0; timeremaining < 1000; timeremaining++) {
        !          1083:                        scc_read_reg_zero(regs, chan, value);
        !          1084: 
        !          1085:                        if (value & SCC_RR0_RX_AVAIL)
        !          1086:                                continue;
        !          1087:                }
        !          1088: 
        !          1089:                if (timeout == FALSE)
        !          1090:                        break;
        !          1091: 
        !          1092:        }
        !          1093: 
        !          1094: 
        !          1095:        goto get_char;
        !          1096: }
        !          1097: #endif /* MACH_KGDB */
        !          1098: 
        !          1099: /*
        !          1100:  * Open routine
        !          1101:  */
        !          1102: 
        !          1103: io_return_t
        !          1104: scc_open(
        !          1105:        dev_t           dev,
        !          1106:        dev_mode_t      flag,
        !          1107:        io_req_t        ior)
        !          1108: {
        !          1109:        register struct tty     *tp;
        !          1110:        spl_t                   s;
        !          1111:        scc_softc_t             scc;
        !          1112:        int                     chan;
        !          1113:        int                     forcedcarrier;
        !          1114:        io_return_t             result;
        !          1115: 
        !          1116:        if (dev >= NSCC * NSCC_LINE)
        !          1117:                return D_NO_SUCH_DEVICE;
        !          1118: 
        !          1119:        chan = scc_chan(dev);
        !          1120:        tp = &scc_tty[chan];
        !          1121:        scc = &scc_softc[0];
        !          1122: 
        !          1123:        /* But was it there at probe time */
        !          1124:        if (tp->t_addr == 0)
        !          1125:                return D_NO_SUCH_DEVICE;
        !          1126: 
        !          1127:        s = spltty();
        !          1128:        simple_lock(&tp->t_lock);
        !          1129: 
        !          1130:        if (!(tp->t_state & (TS_ISOPEN|TS_WOPEN))) {
        !          1131:                tp->t_dev       = dev;
        !          1132:                tp->t_start     = scc_start;
        !          1133:                tp->t_stop      = scc_stop;
        !          1134:                tp->t_mctl      = scc_mctl;
        !          1135:                tp->t_getstat   = scc_get_status;
        !          1136:                tp->t_setstat   = scc_set_status;
        !          1137:                scc->modem[chan] = 0;   /* No assumptions on things.. */
        !          1138:                if (tp->t_ispeed == 0) {
        !          1139:                        tp->t_ispeed = DEFAULT_SPEED;
        !          1140:                        tp->t_ospeed = DEFAULT_SPEED;
        !          1141:                        tp->t_flags = DEFAULT_FLAGS;
        !          1142:                }
        !          1143: 
        !          1144:                scc->softr[chan].speed = -1;    /* Force reset */
        !          1145:                scc->softr[chan].wr5 |= SCC_WR5_DTR;
        !          1146:                scc_param(tp);
        !          1147:        }
        !          1148: 
        !          1149:        scc_update_modem(tp);
        !          1150: 
        !          1151:        tp->t_state |= TS_CARR_ON;      /* Always.. */
        !          1152: 
        !          1153:        simple_unlock(&tp->t_lock);
        !          1154:        splx(s);
        !          1155:        result = char_open(dev, tp, flag, ior);
        !          1156: 
        !          1157:        if (tp->t_flags & CRTSCTS) {
        !          1158:                simple_lock(&tp->t_lock);
        !          1159:                if (!(scc->modem[chan] & TM_CTS)) 
        !          1160:                        tp->t_state |= TS_TTSTOP;
        !          1161:                simple_unlock(&tp->t_lock);
        !          1162:        }
        !          1163: 
        !          1164:        return result;
        !          1165: }
        !          1166: 
        !          1167: /*
        !          1168:  * Close routine
        !          1169:  */
        !          1170: void
        !          1171: scc_close(
        !          1172:        dev_t   dev)
        !          1173: {
        !          1174:        register struct tty     *tp;
        !          1175:        spl_t                   s;
        !          1176:        scc_softc_t             scc = &scc_softc[0];
        !          1177:        int                     chan = scc_chan(dev);
        !          1178: 
        !          1179:        tp = &scc_tty[dev];
        !          1180: 
        !          1181:        s = spltty();
        !          1182:        simple_lock(&tp->t_lock);
        !          1183: 
        !          1184:        ttstart(tp);
        !          1185:        ttydrain(tp);
        !          1186:        scc_waitforempty(tp);
        !          1187: 
        !          1188:        /* Disable Receiver.. */
        !          1189:        scc_write_reg(scc->regs, chan, SCC_WR3, 0);
        !          1190: #if SCC_DMA_TRANSFERS
        !          1191:        if (scc->dma_initted & (chan <<1))
        !          1192:                scc->dma_ops->scc_dma_reset_rx(chan);
        !          1193: #endif
        !          1194: 
        !          1195:        ttyclose(tp);
        !          1196:        if (tp->t_state & TS_HUPCLS) {
        !          1197:                scc->softr[chan].wr5 &= ~(SCC_WR5_DTR);
        !          1198:                scc_write_reg(scc->regs, chan, SCC_WR5, scc->softr[chan].wr5);
        !          1199:                scc->modem[chan] &= ~(TM_DTR|TM_RTS);
        !          1200:        }
        !          1201: 
        !          1202: 
        !          1203:        tp->t_state &= ~TS_ISOPEN;
        !          1204: 
        !          1205:        simple_unlock(&tp->t_lock);
        !          1206:        splx(s);
        !          1207: }
        !          1208: 
        !          1209: io_return_t
        !          1210: scc_read(
        !          1211:        dev_t           dev,
        !          1212:        io_req_t        ior)
        !          1213: {
        !          1214:        return char_read(&scc_tty[dev], ior);
        !          1215: }
        !          1216: 
        !          1217: io_return_t
        !          1218: scc_write(
        !          1219:        dev_t           dev,
        !          1220:        io_req_t        ior)
        !          1221: {
        !          1222:        return char_write(&scc_tty[dev], ior);
        !          1223: }
        !          1224: 
        !          1225: /*
        !          1226:  * Stop output on a line.
        !          1227:  */
        !          1228: void
        !          1229: scc_stop(
        !          1230:        struct tty      *tp,
        !          1231:        int             flags)
        !          1232: {
        !          1233:        int chan = scc_chan(tp->t_dev);
        !          1234:        scc_softc_t scc = &scc_softc[0];
        !          1235:        struct scc_softreg *sr = &scc->softr[chan];
        !          1236: 
        !          1237:        spl_t s = spltty();
        !          1238: 
        !          1239:        if (tp->t_state & TS_BUSY) {
        !          1240:                if (sr->dma_flags & SCC_FLAGS_DMA_TX_BUSY) {
        !          1241:                        /*printf("{DMA OFF}");*/
        !          1242:                        scc->dma_ops->scc_dma_pause_tx(chan);
        !          1243:                } else if ((tp->t_state&TS_TTSTOP)==0)
        !          1244:                        tp->t_state |= TS_FLUSH;
        !          1245:        }
        !          1246: 
        !          1247:        splx(s);
        !          1248:        /*printf("{STOP %x}", flags);*/
        !          1249: }
        !          1250: 
        !          1251: /*
        !          1252:  * Abnormal close
        !          1253:  */
        !          1254: boolean_t
        !          1255: scc_portdeath(
        !          1256:        dev_t           dev,
        !          1257:        ipc_port_t      port)
        !          1258: {
        !          1259:        return (tty_portdeath(&scc_tty[dev], port));
        !          1260: }
        !          1261: 
        !          1262: /*
        !          1263:  * Get/Set status rotuines
        !          1264:  */
        !          1265: io_return_t
        !          1266: scc_get_status(
        !          1267:        dev_t                   dev,
        !          1268:        dev_flavor_t            flavor,
        !          1269:        dev_status_t            data,
        !          1270:        mach_msg_type_number_t  *status_count)
        !          1271: {
        !          1272:        register struct tty *tp;
        !          1273: 
        !          1274:        tp = &scc_tty[dev];
        !          1275: 
        !          1276:        switch (flavor) {
        !          1277:        case TTY_MODEM:
        !          1278:                scc_update_modem(tp);
        !          1279:                *data = scc_softc[0].modem[scc_chan(dev)];
        !          1280:                *status_count = 1;
        !          1281:                return (D_SUCCESS);
        !          1282:        default:
        !          1283:                return (tty_get_status(tp, flavor, data, status_count));
        !          1284:        }
        !          1285: }
        !          1286: 
        !          1287: io_return_t
        !          1288: scc_set_status(
        !          1289:        dev_t                   dev,
        !          1290:        dev_flavor_t            flavor,
        !          1291:        dev_status_t            data,
        !          1292:        mach_msg_type_number_t  status_count)
        !          1293: {
        !          1294:        register struct tty *tp;
        !          1295:        spl_t s;
        !          1296:        io_return_t result = D_SUCCESS;
        !          1297:        scc_softc_t scc = &scc_softc[0];
        !          1298:        int chan = scc_chan(dev);
        !          1299: 
        !          1300:        tp = &scc_tty[dev];
        !          1301: 
        !          1302:        s = spltty();
        !          1303:        simple_lock(&tp->t_lock);
        !          1304: 
        !          1305:        switch (flavor) {
        !          1306:        case TTY_MODEM:
        !          1307:                (void) scc_mctl(tp, *data, DMSET);
        !          1308:                break;
        !          1309: 
        !          1310:        case TTY_NMODEM:
        !          1311:                break;
        !          1312: 
        !          1313:        case TTY_SET_BREAK:
        !          1314:                (void) scc_mctl(tp, TM_BRK, DMBIS);
        !          1315:                break;
        !          1316: 
        !          1317:        case TTY_CLEAR_BREAK:
        !          1318:                (void) scc_mctl(tp, TM_BRK, DMBIC);
        !          1319:                break;
        !          1320: 
        !          1321:        default:
        !          1322:                simple_unlock(&tp->t_lock);
        !          1323:                splx(s);
        !          1324:                result = tty_set_status(tp, flavor, data, status_count);
        !          1325:                s = spltty();
        !          1326:                simple_lock(&tp->t_lock);
        !          1327:                if (result == D_SUCCESS &&
        !          1328:                    (flavor== TTY_STATUS_NEW || flavor == TTY_STATUS_COMPAT)) {
        !          1329:                        result = scc_param(tp);
        !          1330: 
        !          1331:                        if (tp->t_flags & CRTSCTS) {
        !          1332:                                if (scc->modem[chan] & TM_CTS) {
        !          1333:                                        tp->t_state &= ~TS_TTSTOP;
        !          1334:                                        ttstart(tp);
        !          1335:                                } else
        !          1336:                                        tp->t_state |= TS_TTSTOP;
        !          1337:                        }
        !          1338:                }
        !          1339:                break;
        !          1340:        }
        !          1341: 
        !          1342:        simple_unlock(&tp->t_lock);
        !          1343:        splx(s);
        !          1344: 
        !          1345:        return result;
        !          1346: }
        !          1347: 
        !          1348: void
        !          1349: scc_waitforempty(struct tty *tp)
        !          1350: {
        !          1351:        int chan = scc_chan(tp->t_dev);
        !          1352:        scc_softc_t scc = &scc_softc[0];
        !          1353:        int rr0;
        !          1354: 
        !          1355:        while (1) {
        !          1356:                scc_read_reg(scc->regs, chan, SCC_RR0, rr0);
        !          1357:                if (rr0 & SCC_RR0_TX_EMPTY)
        !          1358:                        break;
        !          1359:                assert_wait(0, TRUE);
        !          1360:                thread_set_timeout(1);
        !          1361:                simple_unlock(&tp->t_lock);
        !          1362:                thread_block((void (*)(void)) 0);
        !          1363:                reset_timeout_check(&current_thread()->timer);
        !          1364:                simple_lock(&tp->t_lock);
        !          1365:        }
        !          1366: }
        !          1367: 
        !          1368: /*
        !          1369:  * Send along a character on a tty.  If we were waiting for
        !          1370:  * this char to complete the open procedure do so; check
        !          1371:  * for errors; if all is well proceed to ttyinput().
        !          1372:  */
        !          1373: 
        !          1374: void
        !          1375: scc_input(dev_t dev, int c, enum scc_error err)
        !          1376: {
        !          1377:        register struct tty *tp;
        !          1378: 
        !          1379:        tp = &scc_tty[dev];
        !          1380: 
        !          1381:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !          1382:                if (tp->t_state & TS_INIT)
        !          1383:                        tt_open_wakeup(tp);
        !          1384:                return;
        !          1385:        }
        !          1386:        switch (err) {
        !          1387:        case SCC_ERR_NONE:
        !          1388:                ttyinput(c, tp);
        !          1389:                break;
        !          1390:        case SCC_ERR_OVERRUN:
        !          1391:                /*log(LOG_WARNING, "sl%d: silo overflow\n", dev);*/
        !          1392:                /* Currently the Mach interface doesn't define an out-of-band
        !          1393:                   event that we could use to signal this error to the user
        !          1394:                   task that has this device open.  */
        !          1395:                break;
        !          1396:        case SCC_ERR_PARITY:
        !          1397:                ttyinputbadparity(c, tp);
        !          1398:                break;
        !          1399:        case SCC_ERR_BREAK:
        !          1400:                ttybreak(c, tp);
        !          1401:                break;
        !          1402:        }
        !          1403: }
        !          1404: 
        !          1405: /*
        !          1406:  * Transmission of a character is complete.
        !          1407:  * Return the next character or -1 if none.
        !          1408:  */
        !          1409: int
        !          1410: scc_simple_tint(dev_t dev, boolean_t all_sent)
        !          1411: {
        !          1412:        register struct tty *tp;
        !          1413: 
        !          1414:        tp = &scc_tty[dev];
        !          1415:        if ((tp->t_addr == 0) || /* not probed --> stray */
        !          1416:            (tp->t_state & TS_TTSTOP))
        !          1417:                return -1;
        !          1418: 
        !          1419:        if (all_sent) {
        !          1420:                tp->t_state &= ~TS_BUSY;
        !          1421:                if (tp->t_state & TS_FLUSH)
        !          1422:                        tp->t_state &= ~TS_FLUSH;
        !          1423: 
        !          1424:                scc_start(tp);
        !          1425:        }
        !          1426: 
        !          1427:        if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
        !          1428:                return -1;
        !          1429: 
        !          1430:        return getc(&tp->t_outq);
        !          1431: }
        !          1432: #endif /* notdef_next */
        !          1433: 
        !          1434: void
        !          1435: powermac_scc_set_datum(scc_regmap_t regs, unsigned int offset, unsigned char value)
        !          1436: {
        !          1437:        volatile unsigned char *address = (unsigned char *) regs + offset;
        !          1438:   
        !          1439:        *address = value;
        !          1440:        eieio();
        !          1441: }
        !          1442:   
        !          1443: unsigned char
        !          1444: powermac_scc_get_datum(scc_regmap_t regs, unsigned int offset)
        !          1445: {
        !          1446:        volatile unsigned char *address = (unsigned char *) regs + offset;
        !          1447:        unsigned char   value;
        !          1448:   
        !          1449:        value = *address; eieio();
        !          1450:        return value;
        !          1451: }
        !          1452: 
        !          1453: /* modem port is 1, printer port is 0 */
        !          1454: #define LINE   1
        !          1455: 
        !          1456: #if got_console_now
        !          1457: int
        !          1458: kmtrygetc()
        !          1459: {
        !          1460:        return scc_getc(0 /* ignored */, LINE, 0 /*no_wait*/, 0);
        !          1461: }
        !          1462: 
        !          1463: int
        !          1464: cngetc()
        !          1465: {
        !          1466:        return scc_getc(0 /* ignored */, LINE, 1 /*wait*/, 0);
        !          1467: }
        !          1468: 
        !          1469: int
        !          1470: cnputc(char c)
        !          1471: {
        !          1472:        int a;
        !          1473: 
        !          1474:        a= scc_putc(0 /* ignored */, LINE, c);
        !          1475:        if (c == '\n')
        !          1476:                a = cnputc('\r');
        !          1477:        return a;
        !          1478: }
        !          1479: #endif /* got_console_now */
        !          1480: #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.