Annotation of Gnu-Mach/chips/scc_8530_hdw.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1993-1989 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     File: scc_8530_hdw.c
                     28:  *     Author: Alessandro Forin, Carnegie Mellon University
                     29:  *     Date:   6/91
                     30:  *
                     31:  *     Hardware-level operations for the SCC Serial Line Driver
                     32:  */
                     33: 
                     34: #include <scc.h>
                     35: #if    NSCC > 0
                     36: #include <bm.h>
                     37: #include <platforms.h>
                     38: 
                     39: #include <mach_kdb.h>
                     40: 
                     41: #include <machine/machspl.h>           /* spl definitions */
                     42: #include <mach/std_types.h>
                     43: #include <device/io_req.h>
                     44: #include <device/tty.h>
                     45: 
                     46: #include <chips/busses.h>
                     47: #include <chips/serial_defs.h>
                     48: #include <chips/screen_defs.h>
                     49: 
                     50: /* Alignment and padding */
                     51: #if    defined(DECSTATION)
                     52: /*
                     53:  * 3min's padding
                     54:  */
                     55: typedef struct {
                     56:        char                    pad0;
                     57:        volatile unsigned char  datum;
                     58:        char                    pad1[2];
                     59: } scc_padded1_register_t;
                     60: 
                     61: #define        scc_register_t  scc_padded1_register_t
                     62: #endif
                     63: 
                     64: #if    defined(FLAMINGO)
                     65: typedef struct {
                     66:        volatile unsigned int   datum;
                     67:        unsigned int            pad1;
                     68: } scc_padded1_register_t;
                     69: 
                     70: #define        scc_register_t  scc_padded1_register_t
                     71: 
                     72: #define        scc_set_datum(d,v)      (d) = (volatile unsigned int) (v) << 8, wbflush()
                     73: #define        scc_get_datum(d,v)      (v) = ((d) >> 8) & 0xff
                     74: 
                     75: #endif
                     76: 
                     77: #include <chips/scc_8530.h>    /* needs the above defs */
                     78: 
                     79: #define private static
                     80: #define public
                     81: 
                     82: /*
                     83:  * Forward decls
                     84:  */
                     85: private check_car( struct tty *, boolean_t );
                     86: 
                     87: /*
                     88:  * On the 3min keyboard and mouse come in on channels A
                     89:  * of the two units.  The MI code expects them at 'lines'
                     90:  * 0 and 1, respectively.  So we map here back and forth.
                     91:  * Note also the MI code believes unit 0 has four lines.
                     92:  */
                     93: 
                     94: #define        SCC_KBDUNIT     1
                     95: #define        SCC_PTRUNIT     0
                     96: 
                     97: mi_to_scc(unitp, linep)
                     98:        int     *unitp, *linep;
                     99: {
                    100:        /* only play games on MI 'unit' 0 */
                    101:        if (*unitp) {
                    102:                /* e.g. by mapping the first four lines specially */
                    103:                *unitp++;
                    104:                return;
                    105:        }
                    106: 
                    107:        /* always get unit=0 (console) and line = 0|1 */
                    108:        if (*linep == SCREEN_LINE_KEYBOARD) {
                    109:                *unitp = SCC_KBDUNIT;
                    110:                *linep = SCC_CHANNEL_A;
                    111:        } else if (*linep == SCREEN_LINE_POINTER) {
                    112:                *unitp = SCC_PTRUNIT;
                    113:                *linep = SCC_CHANNEL_A;
                    114:        } else {
                    115:                *unitp = (*linep & 1);
                    116:                *linep = SCC_CHANNEL_B;
                    117:        }
                    118: /* line 0 is channel B, line 1 is channel A */
                    119: }
                    120: 
                    121: #define        NSCC_LINE       2       /* 2 ttys per chip */
                    122: 
                    123: /* only care for mapping to ttyno */
                    124: scc_to_mi(sccunit, sccline)
                    125: {
                    126:        if (sccunit > 1)
                    127:                return (sccunit * NSCC_LINE + sccline);
                    128:        /* only for console (first pair of SCCs): */
                    129:        if (sccline == SCC_CHANNEL_A)
                    130:                return ((!sccunit) & 1);
                    131:        return 2+sccunit;
                    132: }
                    133: 
                    134: 
                    135: /*
                    136:  * Driver status
                    137:  */
                    138: struct scc_softc {
                    139:        scc_regmap_t    *regs;
                    140: 
                    141:        /* software copy of some write regs, for reg |= */
                    142:        struct softreg {
                    143:                unsigned char   wr1;
                    144:                unsigned char   wr4;
                    145:                unsigned char   wr5;
                    146:                unsigned char   wr14;
                    147:        } softr[2];     /* per channel */
                    148: 
                    149:        unsigned char   last_rr0[2];    /* for modem signals */
                    150:        unsigned short  fake;   /* missing rs232 bits, channel A */
                    151:        char            polling_mode;
                    152:        char            softCAR, osoftCAR;
                    153:        char            probed_once;
                    154: 
                    155:        boolean_t       full_modem;
                    156:        boolean_t       isa_console;
                    157: 
                    158: } scc_softc_data[NSCC];
                    159: 
                    160: typedef struct scc_softc *scc_softc_t;
                    161: 
                    162: scc_softc_t    scc_softc[NSCC];
                    163: 
                    164: scc_softCAR(unit, line, on)
                    165: {
                    166:        mi_to_scc(&unit, &line);
                    167:        if (on)
                    168:                scc_softc[unit]->softCAR |= 1<<line;
                    169:        else
                    170:                scc_softc[unit]->softCAR &= ~(1 << line);
                    171: }
                    172: 
                    173: 
                    174: /*
                    175:  * BRG formula is:
                    176:  *                             ClockFrequency
                    177:  *     BRGconstant =   ---------------------------  -  2
                    178:  *                     2 * BaudRate * ClockDivider
                    179:  */
                    180: /* Speed selections with Pclk=7.3728Mhz, clock x16 */
                    181: static
                    182: short  scc_speeds[] =
                    183:        /* 0   50    75    110  134.5  150  200   300  600 1200 1800 2400 */
                    184:        {  0, 4606, 3070, 2093, 1711, 1534, 1150, 766, 382, 190, 126, 94,
                    185: 
                    186:        /* 4800 9600 19.2k 38.4k */
                    187:          46,   22,  10,    4};
                    188: 
                    189: /*
                    190:  * Definition of the driver for the auto-configuration program.
                    191:  */
                    192: 
                    193: int    scc_probe(), scc_intr();
                    194: static void scc_attach();
                    195: 
                    196: vm_offset_t    scc_std[NSCC] = { 0 };
                    197: struct bus_device *scc_info[NSCC];
                    198: struct bus_driver scc_driver = 
                    199:         { scc_probe, 0, scc_attach, 0, scc_std, "scc", scc_info,};
                    200: 
                    201: /*
                    202:  * Adapt/Probe/Attach functions
                    203:  */
                    204: boolean_t              scc_uses_modem_control = FALSE;/* patch this with adb */
                    205: 
                    206: set_scc_address(
                    207:        int             sccunit,
                    208:        vm_offset_t     regs,
                    209:        boolean_t       has_modem,
                    210:        boolean_t       isa_console)
                    211: {
                    212:        extern int      scc_probe(), scc_param(), scc_start(),
                    213:                        scc_putc(), scc_getc(),
                    214:                        scc_pollc(), scc_mctl(), scc_softCAR();
                    215: 
                    216:        scc_std[sccunit] = regs;
                    217:        scc_softc_data[sccunit].full_modem = has_modem & scc_uses_modem_control;
                    218:        scc_softc_data[sccunit].isa_console = isa_console;
                    219: 
                    220:        /* Do this here */
                    221:        console_probe           = scc_probe;
                    222:        console_param           = scc_param;
                    223:        console_start           = scc_start;
                    224:        console_putc            = scc_putc;
                    225:        console_getc            = scc_getc;
                    226:        console_pollc           = scc_pollc;
                    227:        console_mctl            = scc_mctl;
                    228:        console_softCAR         = scc_softCAR;
                    229: 
                    230: }
                    231: 
                    232: scc_probe(
                    233:        int               xxx,
                    234:        struct bus_device *ui)
                    235: {
                    236:        int             sccunit = ui->unit;
                    237:        scc_softc_t     scc;
                    238:        register int    val;
                    239:        register scc_regmap_t   *regs;
                    240: 
                    241:        regs = (scc_regmap_t *)scc_std[sccunit];
                    242:        if (regs == 0)
                    243:                return 0;
                    244: 
                    245:        /*
                    246:         * See if we are here
                    247:         */
                    248:        if (check_memory(regs, 0)) {
                    249:                /* no rides today */
                    250:                return 0;
                    251:        }
                    252: 
                    253:        scc = &scc_softc_data[sccunit];
                    254: 
                    255:        if (scc->probed_once++){
                    256:                return 1;
                    257:        }
                    258:        /*
                    259:         * Chip once-only initialization
                    260:         *
                    261:         * NOTE: The wiring we assume is the one on the 3min:
                    262:         *
                    263:         *      out     A-TxD   -->     TxD     keybd or mouse
                    264:         *      in      A-RxD   -->     RxD     keybd or mouse
                    265:         *      out     A-DTR~  -->     DTR     comm
                    266:         *      out     A-RTS~  -->     RTS     comm
                    267:         *      in      A-CTS~  -->     SI      comm
                    268:         *      in      A-DCD~  -->     RI      comm
                    269:         *      in      A-SYNCH~-->     DSR     comm
                    270:         *      out     B-TxD   -->     TxD     comm
                    271:         *      in      B-RxD   -->     RxD     comm
                    272:         *      in      B-RxC   -->     TRxCB   comm
                    273:         *      in      B-TxC   -->     RTxCB   comm
                    274:         *      out     B-RTS~  -->     SS      comm
                    275:         *      in      B-CTS~  -->     CTS     comm
                    276:         *      in      B-DCD~  -->     CD      comm
                    277:         */
                    278: 
                    279:        scc_softc[sccunit] = scc;
                    280:        scc->regs = regs;
                    281: 
                    282:        scc->fake = 1<<SCC_CHANNEL_A;
                    283: 
                    284:        { 
                    285:                register int i;
                    286:                /* We need this in scc_start only, hence the funny
                    287:                   value: we need it non-zero and we want to avoid
                    288:                   too much overhead in getting to (scc,regs,line) */
                    289:                for (i = 0; i < NSCC_LINE; i++) {
                    290:                        register struct tty     *tp;
                    291: 
                    292:                        tp = console_tty[scc_to_mi(sccunit,i)];
                    293:                        tp->t_addr = (char*)(0x80000000L + (sccunit<<1) + (i&1));
                    294:                        /* do min buffering */
                    295:                        tp->t_state |= TS_MIN;
                    296:                }
                    297:        }
                    298: 
                    299:        /* make sure reg pointer is in known state */
                    300:        scc_init_reg(regs, SCC_CHANNEL_A);
                    301:        scc_init_reg(regs, SCC_CHANNEL_B);
                    302: 
                    303:        /* reset chip, fully */
                    304:        scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET);
                    305:        delay(50000);/*enough ? */
                    306:        scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, 0);
                    307: 
                    308:        /* program the interrupt vector */
                    309:        scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0);
                    310:        scc_write_reg(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0);
                    311:        scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS);
                    312: 
                    313:        /* most of the init is in scc_param() */
                    314: 
                    315:        /* timing base defaults */
                    316:        scc->softr[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16;
                    317:        scc->softr[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16;
                    318: 
                    319:        /* enable DTR, RTS and dont SS */
                    320: #if    0
                    321:        /* According to one book I have this signal (pin 23, "SS")
                    322:           is "specified by the provider", meaning the EIA-232-D
                    323:           standard does not define what it is.  Better leave
                    324:           it alone */
                    325:        scc->softr[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS;
                    326: #else
                    327:        scc->softr[SCC_CHANNEL_B].wr5 = 0;
                    328: #endif
                    329:        scc->softr[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR;
                    330: 
                    331:        /* baud rates */
                    332:        val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC;
                    333:        scc->softr[SCC_CHANNEL_B].wr14 = val;
                    334:        scc->softr[SCC_CHANNEL_A].wr14 = val;
                    335: 
                    336:        /* interrupt conditions */
                    337:        val =   SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE |
                    338:                SCC_WR1_EXT_IE | SCC_WR1_TX_IE;         
                    339:        scc->softr[SCC_CHANNEL_A].wr1 = val;
                    340:        scc->softr[SCC_CHANNEL_B].wr1 = val;
                    341: 
                    342:        scc_read_reg_zero(regs, SCC_CHANNEL_A, scc->last_rr0[SCC_CHANNEL_A]);
                    343:        scc_read_reg_zero(regs, SCC_CHANNEL_B, scc->last_rr0[SCC_CHANNEL_B]);
                    344: 
                    345:        /*
                    346:         * After probing, any line that should be active
                    347:         * (keybd,mouse,rcline) is activated via scc_param().
                    348:         */
                    349: 
                    350:        scc_set_modem_control(scc, scc->full_modem);
                    351: 
                    352: #if defined(KMIN) || defined (FLAMINGO) || defined(KN03)
                    353:        /*
                    354:         * Crock: MI code knows of unit 0 as console, we need
                    355:         * unit 1 as well since the keyboard is there
                    356:         * This is acceptable on maxine, which has to call its
                    357:         * only one chip unit 1 so that rconsole is happy.
                    358:         */
                    359:        if (sccunit == 0) {
                    360:                struct bus_device d;
                    361:                d = *ui;
                    362:                d.unit = 1;
                    363:                scc_probe( xxx, &d);
                    364:        }
                    365: #endif
                    366:        return 1;
                    367: }
                    368: 
                    369: boolean_t scc_timer_started = FALSE;
                    370: 
                    371: static void
                    372: scc_attach(
                    373:        register struct bus_device *ui)
                    374: {
                    375:        int sccunit = ui->unit;
                    376:        extern scc_scan();
                    377:        extern int tty_inq_size;
                    378:        int i;
                    379: 
                    380:        /* We only have 4 ttys, but always at 9600
                    381:         * Give em a lot of room (plus dma..)
                    382:         */
                    383:        tty_inq_size = 4096;
                    384:        if (!scc_timer_started) {
                    385:                /* do all of them, before we call scc_scan() */
                    386:                /* harmless if done already */
                    387:                for (i = 0; i < NSCC*NSCC_LINE; i++)
                    388:                        ttychars(console_tty[i]);
                    389: 
                    390:                scc_timer_started = TRUE;
                    391:                scc_scan();
                    392:        }
                    393: 
                    394: #if    NBM > 0
                    395:        if (SCREEN_ISA_CONSOLE() && scc_softc[sccunit]->isa_console) {
                    396:                printf("\n sl0: ");
                    397:                if (sccunit && rcline == 3) printf("( rconsole )");
                    398: 
                    399:                if (sccunit == SCC_KBDUNIT) {
                    400:                        printf("\n sl1: "); lk201_attach(0, sccunit >> 1);
                    401:                } else if (sccunit == SCC_PTRUNIT) {
                    402:                        printf("\n sl1: "); mouse_attach(0, sccunit >> 1);
                    403:                }
                    404:        } else
                    405: #endif /*NBM > 0*/
                    406:        {
                    407:                printf("%s", (sccunit == 1) ?
                    408:                        "\n sl0: ( alternate console )\n sl1:" :
                    409:                        "\n sl0:\n sl1:");
                    410:        }
                    411: }
                    412: 
                    413: /*
                    414:  * Would you like to make a phone call ?
                    415:  */
                    416: scc_set_modem_control(
                    417:        scc_softc_t     scc,
                    418:        boolean_t       on)
                    419: {
                    420:        if (on)
                    421:                /* your problem if the hardware then is broke */
                    422:                scc->fake = 0;
                    423:        else
                    424:                scc->fake = 3;
                    425:        scc->full_modem = on;
                    426:        /* user should do an scc_param() ifchanged */
                    427: }
                    428: 
                    429: /*
                    430:  * Polled I/O (debugger)
                    431:  */
                    432: scc_pollc(
                    433:        int                     unit,
                    434:        boolean_t               on)
                    435: {
                    436:        scc_softc_t             scc;
                    437:        int                     line = SCREEN_LINE_KEYBOARD,
                    438:                                sccunit = unit;
                    439: 
                    440:        mi_to_scc(&sccunit, &line);
                    441: 
                    442:        scc = scc_softc[sccunit];
                    443:        if (on) {
                    444:                scc->polling_mode++;
                    445: #if    NBM > 0
                    446:                screen_on_off(unit, TRUE);
                    447: #endif NBM > 0
                    448:        } else
                    449:                scc->polling_mode--;
                    450: }
                    451: 
                    452: /*
                    453:  * Interrupt routine
                    454:  */
                    455: int scc_intr_count;
                    456: 
                    457: scc_intr(
                    458:        int     unit,
                    459:        spl_t   spllevel)
                    460: {
                    461:        scc_softc_t             scc = scc_softc[unit];
                    462:        register scc_regmap_t   *regs = scc->regs;
                    463:        register int            rr1, rr2;
                    464:        register int            c;
                    465: 
                    466: scc_intr_count++;
                    467: 
                    468: #if    mips
                    469:        splx(spllevel);         /* lower priority */
                    470: #endif
                    471: 
                    472:        while (1) {
                    473: 
                    474:          scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR2, rr2);
                    475: 
                    476:          rr2 = SCC_RR2_STATUS(rr2);
                    477: 
                    478:          /* are we done yet ? */
                    479:          if (rr2 == 6) {       /* strange, distinguished value */
                    480:                register int rr3;
                    481:                scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR3, rr3);
                    482:                if (rr3 == 0)
                    483:                        return;
                    484:          }
                    485: 
                    486:          if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) {
                    487: 
                    488:                register chan = (rr2 == SCC_RR2_A_XMIT_DONE) ?
                    489:                                        SCC_CHANNEL_A : SCC_CHANNEL_B;
                    490: 
                    491:                scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    492:                c = cons_simple_tint(scc_to_mi(unit,chan), FALSE);
                    493: 
                    494:                if (c == -1) {
                    495:                        /* no more data for this line */
                    496: 
                    497:                        scc_read_reg(regs, chan, SCC_RR15, c);
                    498:                        c &= ~SCC_WR15_TX_UNDERRUN_IE;
                    499:                        scc_write_reg(regs, chan, SCC_WR15, c);
                    500: 
                    501:                        c = scc->softr[chan].wr1 & ~SCC_WR1_TX_IE;
                    502:                        scc_write_reg(regs, chan, SCC_WR1, c);
                    503:                        scc->softr[chan].wr1 = c;
                    504: 
                    505:                        c = cons_simple_tint(scc_to_mi(unit,chan), TRUE);
                    506:                        if (c != -1)
                    507:                                /* funny race, scc_start has been called already */
                    508:                                scc_write_data(regs, chan, c);
                    509:                } else {
                    510:                        scc_write_data(regs, chan, c);
                    511:                        /* and leave it enabled */
                    512:                }
                    513:          }
                    514: 
                    515:          else if (rr2 == SCC_RR2_A_RECV_DONE) {
                    516:                int     err = 0;
                    517: 
                    518:                scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    519:                if (scc->polling_mode)
                    520:                        continue;
                    521: 
                    522:                scc_read_data(regs, SCC_CHANNEL_A, c);
                    523:                rr1 = scc_to_mi(unit,SCC_CHANNEL_A);
                    524:                cons_simple_rint (rr1, rr1, c, 0);
                    525:          }
                    526: 
                    527:          else if (rr2 == SCC_RR2_B_RECV_DONE) {
                    528:                int     err = 0;
                    529: 
                    530:                scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    531:                if (scc->polling_mode)
                    532:                        continue;
                    533: 
                    534:                scc_read_data(regs, SCC_CHANNEL_B, c);
                    535:                rr1 = scc_to_mi(unit,SCC_CHANNEL_B);
                    536:                cons_simple_rint (rr1, rr1, c, 0);
                    537:          }
                    538: 
                    539:          else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) {
                    540:                int chan = (rr2 == SCC_RR2_A_EXT_STATUS) ?
                    541:                        SCC_CHANNEL_A : SCC_CHANNEL_B;
                    542:                scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_EXT_IP);
                    543:                scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    544:                scc_modem_intr(scc, chan, unit);
                    545:          }
                    546: 
                    547:          else if ((rr2 == SCC_RR2_A_RECV_SPECIAL) || (rr2 == SCC_RR2_B_RECV_SPECIAL)) {
                    548:                register int chan = (rr2 == SCC_RR2_A_RECV_SPECIAL) ?
                    549:                        SCC_CHANNEL_A : SCC_CHANNEL_B;
                    550: 
                    551:                scc_read_reg(regs, chan, SCC_RR1, rr1);
                    552:                if (rr1 & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
                    553:                        int err;
                    554:                        /* map to CONS_ERR_xxx MI error codes */
                    555:                        err =   ((rr1 & SCC_RR1_PARITY_ERR)<<8) |
                    556:                                ((rr1 & SCC_RR1_RX_OVERRUN)<<9) |
                    557:                                ((rr1 & SCC_RR1_FRAME_ERR)<<7);
                    558:                        scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR);
                    559:                        rr1 = scc_to_mi(unit,chan);
                    560:                        cons_simple_rint(rr1, rr1, 0, err);
                    561:                }
                    562:                scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    563:          }
                    564: 
                    565:        }
                    566: 
                    567: }
                    568: 
                    569: boolean_t
                    570: scc_start(
                    571:        struct tty *tp)
                    572: {
                    573:        register scc_regmap_t   *regs;
                    574:        register int            chan, temp;
                    575:        register struct softreg *sr;
                    576: 
                    577:        temp = (natural_t)tp->t_addr;
                    578:        chan = (temp & 1);      /* channel */
                    579:        temp = (temp >> 1)&0xff;/* sccunit */
                    580:        regs = scc_softc[temp]->regs;
                    581:        sr   = &scc_softc[temp]->softr[chan];
                    582: 
                    583:        scc_read_reg(regs, chan, SCC_RR15, temp);
                    584:        temp |= SCC_WR15_TX_UNDERRUN_IE;
                    585:        scc_write_reg(regs, chan, SCC_WR15, temp);
                    586: 
                    587:        temp = sr->wr1 | SCC_WR1_TX_IE;
                    588:        scc_write_reg(regs, chan, SCC_WR1, temp);
                    589:        sr->wr1 = temp;
                    590: 
                    591:        /* but we need a first char out or no cookie */
                    592:        scc_read_reg(regs, chan, SCC_RR0, temp);
                    593:        if (temp & SCC_RR0_TX_EMPTY)
                    594:        {
                    595:                register char   c;
                    596: 
                    597:                c = getc(&tp->t_outq);
                    598:                scc_write_data(regs, chan, c);
                    599:        }
                    600: }
                    601: 
                    602: /*
                    603:  * Get a char from a specific SCC line
                    604:  * [this is only used for console&screen purposes]
                    605:  */
                    606: scc_getc(
                    607:        int             unit,
                    608:        int             line,
                    609:        boolean_t       wait,
                    610:        boolean_t       raw)
                    611: {
                    612:        scc_softc_t     scc;
                    613:        register scc_regmap_t *regs;
                    614:        unsigned char   c;
                    615:        int             value, mi_line, rcvalue, from_line;
                    616: 
                    617:        mi_line = line;
                    618:        mi_to_scc(&unit, &line);
                    619: 
                    620:        scc = scc_softc[unit];
                    621:        regs = scc->regs;
                    622: 
                    623:        /*
                    624:         * wait till something available
                    625:         *
                    626:         * NOTE: we know! that rcline==3
                    627:         */
                    628:        if (rcline) rcline = 3;
                    629: again:
                    630:        rcvalue = 0;
                    631:        while (1) {
                    632:                scc_read_reg_zero(regs, line, value);
                    633:                if (rcline && (mi_line == SCREEN_LINE_KEYBOARD)) {
                    634:                        scc_read_reg_zero(regs, SCC_CHANNEL_B, rcvalue);
                    635:                        value |= rcvalue;
                    636:                }
                    637:                if (((value & SCC_RR0_RX_AVAIL) == 0) && wait)
                    638:                        delay(10);
                    639:                else
                    640:                        break;
                    641:        }
                    642: 
                    643:        /*
                    644:         * if nothing found return -1 
                    645:         */
                    646:        from_line = (rcvalue & SCC_RR0_RX_AVAIL) ? SCC_CHANNEL_B : line;
                    647: 
                    648:        if (value & SCC_RR0_RX_AVAIL) {
                    649:                scc_read_reg(regs, from_line, SCC_RR1, value);
                    650:                scc_read_data(regs, from_line, c);
                    651:        } else {
                    652: /*             splx(s);*/
                    653:                return -1;
                    654:        }
                    655: 
                    656:        /*
                    657:         * bad chars not ok 
                    658:         */
                    659:        if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
                    660: /* scc_state(unit,from_line); */
                    661:                scc_write_reg(regs, from_line, SCC_RR0, SCC_RESET_ERROR);
                    662:                if (wait) {
                    663:                        scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    664:                        goto again;
                    665:                }
                    666:        }
                    667:        scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
                    668: /*     splx(s);*/
                    669: 
                    670: 
                    671: #if    NBM > 0
                    672:        if ((mi_line == SCREEN_LINE_KEYBOARD) && (from_line == SCC_CHANNEL_A) &&
                    673:            !raw && SCREEN_ISA_CONSOLE() && scc->isa_console)
                    674:                return lk201_rint(SCREEN_CONS_UNIT(), c, wait, scc->polling_mode);
                    675:        else
                    676: #endif NBM > 0
                    677:                return c;
                    678: }
                    679: 
                    680: /*
                    681:  * Put a char on a specific SCC line
                    682:  */
                    683: scc_putc(
                    684:        int     unit,
                    685:        int     line,
                    686:        int     c)
                    687: {
                    688:        scc_softc_t      scc;
                    689:        register scc_regmap_t *regs;
                    690:        spl_t             s = spltty();
                    691:        register int    value;
                    692: 
                    693:        mi_to_scc(&unit, &line);
                    694: 
                    695:        scc = scc_softc[unit];
                    696:        regs = scc->regs;
                    697: 
                    698:        do {
                    699:                scc_read_reg(regs, line, SCC_RR0, value);
                    700:                if (value & SCC_RR0_TX_EMPTY)
                    701:                        break;
                    702:                delay(100);
                    703:        } while (1);
                    704: 
                    705:        scc_write_data(regs, line, c);
                    706: /* wait for it to swallow the char ? */
                    707: 
                    708:        splx(s);
                    709: }
                    710: 
                    711: scc_param(
                    712:        struct tty      *tp,
                    713:        int             line)
                    714: {
                    715:        scc_regmap_t    *regs;
                    716:        int             value, sccline, unit;
                    717:        struct softreg  *sr;
                    718:        scc_softc_t     scc;
                    719:  
                    720:        line = tp->t_dev;
                    721:        /* MI code wants us to handle 4 lines on unit 0 */
                    722:        unit = (line < 4) ? 0 : (line / NSCC_LINE);
                    723:        sccline = line;
                    724:        mi_to_scc(&unit, &sccline);
                    725: 
                    726:        if ((scc = scc_softc[unit]) == 0) return;       /* sanity */
                    727:        regs = scc->regs;
                    728: 
                    729:        sr = &scc->softr[sccline];
                    730: 
                    731:        /*
                    732:         * Do not let user fool around with kbd&mouse
                    733:         */
                    734: #if    NBM > 0
                    735:        if (screen_captures(line)) {
                    736:                tp->t_ispeed = tp->t_ospeed = B4800;
                    737:                tp->t_flags |= TF_LITOUT;
                    738:        }
                    739: #endif NBM > 0
                    740: 
                    741:        if (tp->t_ispeed == 0) {
                    742:                (void) scc_mctl(tp->t_dev, TM_HUP, DMSET);      /* hang up line */
                    743:                return;
                    744:        }
                    745: 
                    746:        /* reset line */
                    747:        value = (sccline == SCC_CHANNEL_A) ? SCC_WR9_RESET_CHA_A : SCC_WR9_RESET_CHA_B;
                    748:        scc_write_reg(regs, sccline, SCC_WR9, value);
                    749:        delay(25);
                    750: 
                    751:        /* stop bits, normally 1 */
                    752:        value = sr->wr4 & 0xf0;
                    753:        value |= (tp->t_ispeed == B110) ? SCC_WR4_2_STOP : SCC_WR4_1_STOP;
                    754: 
                    755:        /* .. and parity */
                    756:        if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_ODDP)
                    757:                value |= SCC_WR4_PARITY_ENABLE;
                    758: 
                    759:        /* set it now, remember it must be first after reset */
                    760:        sr->wr4 = value;
                    761:        scc_write_reg(regs, sccline, SCC_WR4, value);
                    762: 
                    763:        /* vector again */
                    764:        scc_write_reg(regs, sccline, SCC_WR2, 0xf0);
                    765: 
                    766:        /* we only do 8 bits per char */
                    767:        value = SCC_WR3_RX_8_BITS;
                    768:        scc_write_reg(regs, sccline, SCC_WR3, value);
                    769: 
                    770:        /* clear break, keep rts dtr */
                    771:        value = sr->wr5 & (SCC_WR5_DTR|SCC_WR5_RTS);
                    772:        value |= SCC_WR5_TX_8_BITS;
                    773:        sr->wr5 = value;
                    774:        scc_write_reg(regs, sccline, SCC_WR5, value);
                    775:        /* some are on the other channel, which might
                    776:           never be used (e.g. maxine has only one line) */
                    777:        {
                    778:                register int otherline = (sccline+1)&1;
                    779: 
                    780:                scc_write_reg(regs, otherline, SCC_WR5, scc->softr[otherline].wr5);
                    781:        }
                    782: 
                    783:        scc_write_reg(regs, sccline, SCC_WR6, 0);
                    784:        scc_write_reg(regs, sccline, SCC_WR7, 0);
                    785: 
                    786:        scc_write_reg(regs, sccline, SCC_WR9, SCC_WR9_VIS);
                    787: 
                    788:        scc_write_reg(regs, sccline, SCC_WR10, 0);
                    789: 
                    790:        /* clock config */
                    791:        value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR |
                    792:                SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR;
                    793:        scc_write_reg(regs, sccline, SCC_WR11, value);
                    794: 
                    795:        value = scc_speeds[tp->t_ispeed];
                    796:        scc_set_timing_base(regs,sccline,value);
                    797: 
                    798:        value = sr->wr14;
                    799:        scc_write_reg(regs, sccline, SCC_WR14, value);
                    800: 
                    801: #if    FLAMINGO
                    802:        if (unit != 1)
                    803: #else
                    804:        if (1)
                    805: #endif
                    806:        {
                    807:                /* Chan-A: CTS==SI DCD==RI DSR=SYNCH */
                    808:                value = SCC_WR15_CTS_IE | SCC_WR15_DCD_IE | SCC_WR15_SYNCHUNT_IE;
                    809:                scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR15, value);
                    810: 
                    811:                /* Chan-B: CTS==CTS DCD==DCD */
                    812:                value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE;
                    813:                scc_write_reg(regs, SCC_CHANNEL_B, SCC_WR15, value);
                    814:        } else {
                    815:                /* Here if modem bits are floating noise, keep quiet */
                    816:                value = SCC_WR15_BREAK_IE;
                    817:                scc_write_reg(regs, sccline, SCC_WR15, value);
                    818:        }
                    819: 
                    820:        /* and now the enables */
                    821:        value = SCC_WR3_RX_8_BITS | SCC_WR3_RX_ENABLE;
                    822:        scc_write_reg(regs, sccline, SCC_WR3, value);
                    823: 
                    824:        value = sr->wr5 | SCC_WR5_TX_ENABLE;
                    825:        sr->wr5 = value;
                    826:        scc_write_reg(regs, sccline, SCC_WR5, value);
                    827: 
                    828:        /* master inter enable */
                    829:        scc_write_reg(regs,sccline,SCC_WR9,SCC_WR9_MASTER_IE|SCC_WR9_VIS);
                    830: 
                    831:        scc_write_reg(regs, sccline, SCC_WR1, sr->wr1);
                    832: 
                    833: }
                    834:  
                    835: /*
                    836:  * Modem control functions
                    837:  */
                    838: scc_mctl(
                    839:        int     dev,
                    840:        int     bits,
                    841:        int     how)
                    842: {
                    843:        register scc_regmap_t *regs;
                    844:        struct softreg  *sra, *srb, *sr;
                    845:        int unit, sccline;
                    846:        int b = 0;
                    847:        spl_t   s;
                    848:        scc_softc_t      scc;
                    849: 
                    850:        /* MI code wants us to handle 4 lines on unit 0 */
                    851:        unit = (dev < 4) ? 0 : (dev / NSCC_LINE);
                    852:        sccline = dev;
                    853:        mi_to_scc(&unit, &sccline);
                    854: 
                    855:        if ((scc = scc_softc[unit]) == 0) return 0;     /* sanity */
                    856:        regs = scc->regs;
                    857: 
                    858:        sr  = &scc->softr[sccline];
                    859:        sra = &scc->softr[SCC_CHANNEL_A];
                    860:        srb = &scc->softr[SCC_CHANNEL_B];
                    861: 
                    862:        if (bits == TM_HUP) {   /* close line (internal) */
                    863:                bits = TM_DTR | TM_RTS;
                    864:                how = DMBIC;
                    865:                /* xxx interrupts too ?? */
                    866:        }
                    867: 
                    868:        if (bits & TM_BRK) {
                    869:                switch (how) {
                    870:                case DMSET:
                    871:                case DMBIS:
                    872:                        sr->wr5 |= SCC_WR5_SEND_BREAK;
                    873:                        break;
                    874:                case DMBIC:
                    875:                        sr->wr5 &= ~SCC_WR5_SEND_BREAK;
                    876:                        break;
                    877:                default:
                    878:                        goto dontbrk;
                    879:                }
                    880:                s = spltty();
                    881:                scc_write_reg(regs, sccline, SCC_WR5, sr->wr5);
                    882:                splx(s);
                    883: dontbrk:
                    884:                b |= (sr->wr5 & SCC_WR5_SEND_BREAK) ? TM_BRK : 0;
                    885:        }
                    886: 
                    887:        /* no modem support on channel A */
                    888:        if (sccline == SCC_CHANNEL_A)
                    889:                return (b | TM_LE | TM_DTR | TM_CTS | TM_CAR | TM_DSR);
                    890: 
                    891:        sra = &scc->softr[SCC_CHANNEL_A];
                    892:        srb = &scc->softr[SCC_CHANNEL_B];
                    893: 
                    894: #if 0
                    895:        /* do I need to do something on this ? */
                    896:        if (bits & TM_LE) {     /* line enable */
                    897:        }
                    898: #endif
                    899: 
                    900:        if (bits & (TM_DTR|TM_RTS)) {   /* data terminal ready, request to send */
                    901:                register int    w = 0;
                    902: 
                    903:                if (bits & TM_DTR) w |= SCC_WR5_DTR;
                    904:                if (bits & TM_RTS) w |= SCC_WR5_RTS;
                    905: 
                    906:                switch (how) {
                    907:                case DMSET:
                    908:                case DMBIS:
                    909:                        sra->wr5 |= w;
                    910:                        break;
                    911:                case DMBIC:
                    912:                        sra->wr5 &= ~w;
                    913:                        break;
                    914:                default:
                    915:                        goto dontdtr;
                    916:                }
                    917:                s = spltty();
                    918:                scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR5, sra->wr5);
                    919:                splx(s);
                    920: dontdtr:
                    921:                b |= (sra->wr5 & w) ? (bits & (TM_DTR|TM_RTS)) : 0;
                    922:        }
                    923: 
                    924:        s = spltty();
                    925: 
                    926: #if 0
                    927:        /* Unsupported */
                    928:        if (bits & TM_ST) {     /* secondary transmit */
                    929:        }
                    930:        if (bits & TM_SR) {     /* secondary receive */
                    931:        }
                    932: #endif
                    933: 
                    934:        if (bits & TM_CTS) {    /* clear to send */
                    935:                register int value;
                    936:                scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR0, value);
                    937:                b |= (value & SCC_RR0_CTS) ? TM_CTS : 0;
                    938:        }
                    939: 
                    940:        if (bits & TM_CAR) {    /* carrier detect */
                    941:                register int value;
                    942:                scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR0, value);
                    943:                b |= (value & SCC_RR0_DCD) ? TM_CAR : 0;
                    944:        }
                    945: 
                    946:        if (bits & TM_RNG) {    /* ring */
                    947:                register int value;
                    948:                scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR0, value);
                    949:                b |= (value & SCC_RR0_DCD) ? TM_RNG : 0;
                    950:        }
                    951: 
                    952:        if (bits & TM_DSR) {    /* data set ready */
                    953:                register int value;
                    954:                scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR0, value);
                    955:                b |= (value & SCC_RR0_SYNCH) ? TM_DSR : 0;
                    956:        }
                    957: 
                    958:        splx(s);
                    959: 
                    960:        return b;
                    961: }
                    962: 
                    963: #define debug 0
                    964: 
                    965: scc_modem_intr(
                    966:        scc_softc_t      scc,
                    967:        int             chan,
                    968:        int             unit)
                    969: {
                    970:        register int value, changed;
                    971: 
                    972:        scc_read_reg_zero(scc->regs, chan, value);
                    973: 
                    974:        /* See what changed */
                    975:        changed = value ^ scc->last_rr0[chan];
                    976:        scc->last_rr0[chan] = value;
                    977: 
                    978: #if debug
                    979: printf("sccmodem: chan %c now %x, changed %x : ",
                    980:        (chan == SCC_CHANNEL_B) ? 'B' : 'A',
                    981:        value, changed);
                    982: #endif
                    983: 
                    984:        if (chan == SCC_CHANNEL_A) {
                    985:                if (changed & SCC_RR0_CTS) {
                    986:                        /* Speed indicator, ignore XXX */
                    987: #if debug
                    988: printf("%s-speed ", (value & SCC_RR0_CTS) ? "Full" : "Half");
                    989: #endif
                    990:                }
                    991:                if (changed & SCC_RR0_DCD) {
                    992:                        /* Ring indicator */
                    993: #if debug
                    994: printf("Ring ");
                    995: #endif
                    996:                }
                    997:                if (changed & SCC_RR0_SYNCH) {
                    998:                        /* Data Set Ready */
                    999: #if debug
                   1000: printf("DSR ");
                   1001: #endif
                   1002:                        /* If modem went down then CD will also go down,
                   1003:                           or it did already.
                   1004:                           If modem came up then we have to wait for CD
                   1005:                           anyways before enabling the line.
                   1006:                           Either way, nothing to do here */
                   1007:                }
                   1008:        } else {
                   1009:                if (changed & SCC_RR0_CTS) {
                   1010:                        /* Clear To Send */
                   1011: #if debug
                   1012: printf("CTS ");
                   1013: #endif
                   1014:                        tty_cts(console_tty[scc_to_mi(unit,chan)],
                   1015:                                value & SCC_RR0_CTS);
                   1016:                }
                   1017:                if (changed & SCC_RR0_DCD) {
                   1018: #if debug
                   1019: printf("CD ");
                   1020: #endif
                   1021:                        check_car(console_tty[scc_to_mi(unit,chan)],
                   1022:                                  value & SCC_RR0_DCD);
                   1023:                }
                   1024:        }
                   1025: #if debug
                   1026: printf(".\n");
                   1027: #endif
                   1028: }
                   1029: 
                   1030: private check_car(
                   1031:        register struct tty *tp,
                   1032:         boolean_t car)
                   1033:                
                   1034: {
                   1035:        if (car) {
                   1036: #if notyet
                   1037:                /* cancel modem timeout if need to */
                   1038:                if (car & (SCC_MSR_CD2 | SCC_MSR_CD3))
                   1039:                        untimeout(scc_hup, (vm_offset_t)tp);
                   1040: #endif
                   1041: 
                   1042:                /* I think this belongs in the MI code */
                   1043:                if (tp->t_state & TS_WOPEN)
                   1044:                        tp->t_state |= TS_ISOPEN;
                   1045:                /* carrier present */
                   1046:                if ((tp->t_state & TS_CARR_ON) == 0)
                   1047:                        (void)ttymodem(tp, 1);
                   1048:        } else if ((tp->t_state&TS_CARR_ON) && ttymodem(tp, 0) == 0)
                   1049:                scc_mctl( tp->t_dev, TM_DTR, DMBIC);
                   1050: }
                   1051: 
                   1052: /*
                   1053:  * Periodically look at the CD signals:
                   1054:  * they do generate interrupts but we
                   1055:  * must fake them on channel A.  We might
                   1056:  * also fake them on channel B.
                   1057:  */
                   1058: scc_scan()
                   1059: {
                   1060:        register i;
                   1061:        spl_t s = spltty();
                   1062: 
                   1063:        for (i = 0; i < NSCC; i++) {
                   1064:                register scc_softc_t    scc;
                   1065:                register int            car;
                   1066:                register struct tty     **tpp;
                   1067: 
                   1068:                scc = scc_softc[i];
                   1069:                if (scc == 0)
                   1070:                        continue;
                   1071:                car = scc->softCAR | scc->fake;
                   1072: 
                   1073:                tpp = &console_tty[i * NSCC_LINE];
                   1074: 
                   1075:                while (car) {
                   1076:                        if (car & 1)
                   1077:                                check_car(*tpp, 1);
                   1078:                        tpp++;
                   1079:                        car  = car>>1;
                   1080:                }
                   1081: 
                   1082:        }
                   1083:        splx(s);
                   1084:        timeout(scc_scan, (vm_offset_t)0, 5*hz);
                   1085: }
                   1086: 
                   1087: 
                   1088: #if debug
                   1089: scc_rr0(unit,chan)
                   1090: {
                   1091:        int val;
                   1092:        scc_read_reg_zero(scc_softc[unit]->regs, chan, val);
                   1093:        return val;
                   1094: }
                   1095: 
                   1096: scc_rreg(unit,chan,n)
                   1097: {
                   1098:        int val;
                   1099:        scc_read_reg(scc_softc[unit]->regs, chan, n, val);
                   1100:        return val;
                   1101: }
                   1102: 
                   1103: scc_wreg(unit,chan,n,val)
                   1104: {
                   1105:        scc_write_reg(scc_softc[unit]->regs, chan, n, val);
                   1106: }
                   1107: 
                   1108: scc_state(unit,soft)
                   1109: {
                   1110:        int     rr0, rr1, rr3, rr12, rr13, rr15;
                   1111: 
                   1112:        rr0 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR0);
                   1113:        rr1 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR1);
                   1114:        rr3 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR3);
                   1115:        rr12 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR12);
                   1116:        rr13 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR13);
                   1117:        rr15 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR15);
                   1118:        printf("{%d intr, A: R0 %x R1 %x R3 %x baudr %x R15 %x}\n",
                   1119:                scc_intr_count, rr0, rr1, rr3, 
                   1120:                (rr13 << 8) | rr12, rr15);
                   1121: 
                   1122:        rr0 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR0);
                   1123:        rr1 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR1);
                   1124:        rr3 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR2);
                   1125:        rr12 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR12);
                   1126:        rr13 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR13);
                   1127:        rr15 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR15);
                   1128:        printf("{B: R0 %x R1 %x R2 %x baudr %x R15 %x}\n",
                   1129:                rr0, rr1, rr3, 
                   1130:                (rr13 << 8) | rr12, rr15);
                   1131: 
                   1132:        if (soft) {
                   1133:                struct softreg *sr;
                   1134:                sr = scc_softc[unit]->softr;
                   1135:                printf("{B: W1 %x W4 %x W5 %x W14 %x}",
                   1136:                        sr->wr1, sr->wr4, sr->wr5, sr->wr14);
                   1137:                sr++;
                   1138:                printf("{A: W1 %x W4 %x W5 %x W14 %x}\n",
                   1139:                        sr->wr1, sr->wr4, sr->wr5, sr->wr14);
                   1140:        }
                   1141: }
                   1142: 
                   1143: #endif
                   1144: 
                   1145: #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.