Annotation of kernel/machdep/ppc/serial_io.c, revision 1.1.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.