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

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