Annotation of researchv9/sys/sundev/zs_common.c, revision 1.1.1.2

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)zs_common.c 1.1 86/02/03 Copyr 1985 Sun Micro";
                      3: #endif
                      4: 
                      5: /*
                      6:  * Copyright (c) 1985 by Sun Microsystems, Inc.
                      7:  */
                      8: 
                      9: /*
                     10:  *  Sun USART(s) driver - common code for all protocols
                     11:  */
                     12: #include "zs.h"
                     13: #if NZS > 0
                     14: #include "../h/param.h"
                     15: #include "../h/systm.h"
                     16: #include "../h/buf.h"
                     17: 
                     18: #include "../machine/enable.h"
                     19: #include "../machine/mmu.h"
                     20: #include "../machine/cpu.h"
                     21: #include "../machine/scb.h"
                     22: 
                     23: #include "../machine/fault.h"
                     24: /*#include "../sun/consdev.h"*/
                     25: 
                     26: #include "../sundev/mbvar.h"
                     27: #include "../sundev/zsreg.h"
                     28: #include "../sundev/zscom.h"
1.1.1.2 ! root       29: #include "../sundev/zsvar.h"
1.1       root       30: 
                     31: #define NZSLINE        (2*NZS)
                     32: struct zscom zscom[NZSLINE];
                     33: struct zscom *zscurr = &zscom[1];
                     34: struct zscom *zslast = &zscom[0];
                     35: 
                     36: #define        ZREADA(n)       zszread((struct zscc_device *)((int)zs->zs_addr|4), n)
                     37: #define        ZREADB(n)       zszread((struct zscc_device *)((int)zs->zs_addr&~4), n)
                     38: #define        ZWRITEA(n, v)   zszwrite((struct zscc_device *)((int)zs->zs_addr|4), \
                     39:                                n, v)
                     40: #define        ZWRITEB(n, v)   zszwrite((struct zscc_device *)((int)zs->zs_addr&~4), \
                     41:                                n, v)
                     42: 
                     43: /*
                     44:  * Driver information for auto-configuration stuff.
                     45:  */
                     46: int    zsprobe(), zsattach(), zsintr();
                     47: struct mb_device *zs_info[NZS];
                     48: struct mb_driver zsdriver = {
                     49:        zsprobe, 0, zsattach, 0, 0, zsintr,
                     50:        2 * sizeof(struct zscc_device), "zs", zs_info, 0, 0, 0,
                     51: };
                     52: 
1.1.1.2 ! root       53: int    zssoftflags[NZSLINE];
1.1       root       54: 
                     55: /*ARGSUSED*/
                     56: zsprobe(reg, unit)
                     57:        caddr_t reg;
                     58: {
                     59:        register struct zscc_device *zsaddr = (struct zscc_device *)reg;
                     60:        struct zscom tmpzs, *zs = &tmpzs;
                     61:        short speed[2];
                     62:        register int c, loops;
                     63:        label_t jb;
                     64: 
                     65:        /* get in sync with the chip */
                     66:        if ((c = peekc((char *)&zsaddr->zscc_control)) == -1)
                     67:                return (0);
                     68:        /*
                     69:         * We see if it's a Z8530 by looking at register 15
                     70:         * which always has two bits as zero.  If it's not a
                     71:         * Z8530 then setting control to 15 will probably set 
                     72:         * those bits.  Hack, hack.
                     73:         */
                     74:        if (pokec((char *)&zsaddr->zscc_control, 15))   /* set reg 15 */
                     75:                return (0);
                     76:        if ((c = peekc((char *)&zsaddr->zscc_control)) == -1)
                     77:                return (0);
                     78:        if (c & 5)
                     79:                return (0);
                     80:        /* 
                     81:         * Well, that test wasn't strong enough for the damn UARTs 
                     82:         * on the video board in P2 memory, so here comes some more
                     83:         * Anywhere in the following process, the non-existent video
                     84:         * board may decide to give us a parity error, so we use nofault
                     85:         * to catch any errors from here to the end of the probe routine
                     86:         */
                     87:        zs->zs_addr = zsaddr;           /* for zszread/write */
                     88:        nofault = (label_t *)jb;
                     89:        if (setjmp(nofault)) {
                     90:                /* error occurred */
                     91:                goto error;
                     92:        }
                     93:        /*
                     94:         * we can't trust the drain bit in the uart cause we don't know
                     95:         * that the uart is really there.
                     96:         * We need this because trashing the speeds below causes garbage
                     97:         * to be sent.
                     98:         */
                     99:        loops = 0;
                    100:        while ((ZREADA(1) & ZSRR1_ALL_SENT) == 0 ||
                    101:            (ZREADB(1) & ZSRR1_ALL_SENT) == 0 ||
                    102:            (ZREADA(0) & ZSRR0_TX_READY) == 0 ||
                    103:            (ZREADB(0) & ZSRR0_TX_READY) == 0) {
                    104:                DELAY(1000);
                    105:                if (loops++ > 500)
                    106:                        break;
                    107:        }
                    108:        /* must preserve speeds for monitor / console */
                    109:        speed[0] = ZREADA(12);
                    110:        speed[0] |= ZREADA(13) << 8;
                    111:        speed[1] = ZREADB(12);
                    112:        speed[1] |= ZREADB(13) << 8;
                    113:        ZWRITEA(12, 17);
                    114:        ZWRITEA(13, 23);
                    115:        ZWRITEB(12, 29);
                    116:        ZWRITEB(13, 37);
                    117:        if (ZREADA(12) != 17)
                    118:                goto error;
                    119:        if (ZREADA(13) != 23)
                    120:                goto error;
                    121:        if (ZREADB(12) != 29)
                    122:                goto error;
                    123:        if (ZREADB(13) != 37)
                    124:                goto error;
                    125:        /* restore original speeds */
                    126:        ZWRITEA(12, speed[0]);
                    127:        ZWRITEA(13, speed[0] >> 8);
                    128:        ZWRITEB(12, speed[1]);
                    129:        ZWRITEB(13, speed[1] >> 8);
                    130:        nofault = 0;
                    131:        return (2 * sizeof (struct zscc_device));
                    132: error:
                    133:        nofault = 0;
                    134:        return (0);
                    135: }
                    136: 
                    137: #ifdef sun3
                    138: /*
                    139:  * Base vector numbers for SCC chips
                    140:  * Each SCC chip requires 8 contiguous even or odd vectors,
                    141:  * on a multiple of 16 boundary
                    142:  * E.G., nnnnxxxn where nnnn000n is the base value
                    143:  */
                    144: short zsvecbase[] = {
                    145:        144,            /* zs0 - 1001xxx0 */
                    146:        145,            /* zs1 - 1001xxx1 */
                    147: };
                    148: #define        NZSVEC  (sizeof zsvecbase/sizeof zsvecbase[0])
                    149: #endif sun3
                    150: 
                    151: zsattach(md)
                    152:        register struct mb_device *md;
                    153: {
                    154:        register struct zscom *zs = &zscom[md->md_unit*2];
                    155:        register struct zsops *zso;
                    156:        register int i, j;
                    157:        short speed[2];
                    158:        int loops;
                    159:        short vector = 0;
                    160: 
                    161: #ifdef sun3
                    162:        /*
                    163:         * Install the 8 vectors for this SCC chip
                    164:         */
                    165:        if (cpu != CPU_SUN3_50) {
                    166:                extern int (*zsvectab[NZS][8])();
                    167:                int (**p)(), (**q)();
                    168: 
                    169:                if (md->md_unit >= NZSVEC)
                    170:                        panic("zsattach: too many zs units");
                    171:                vector = zsvecbase[md->md_unit];
                    172:                p = &scb.scb_user[vector - VEC_MIN];
                    173:                q = &zsvectab[md->md_unit][0];
                    174:                for (i = 0; i < 8; i++) {
                    175:                        *p = *q++;
                    176:                        p += 2;
                    177:                }
                    178:        }
                    179: #endif sun3
                    180:        stopnmi();
                    181:        zs->zs_addr = (struct zscc_device *)md->md_addr;
                    182:        loops = 0;
                    183:        while ((ZREADA(1) & ZSRR1_ALL_SENT) == 0 ||
                    184:            (ZREADB(1) & ZSRR1_ALL_SENT) == 0 ||
                    185:            (ZREADA(0) & ZSRR0_TX_READY) == 0 ||
                    186:            (ZREADB(0) & ZSRR0_TX_READY) == 0) {
                    187:                DELAY(1000);
                    188:                if (loops++ > 500)
                    189:                        break;
                    190:        }
                    191:        /* must preserve speeds over reset for monitor */
                    192:        speed[0] = ZREADA(12);
                    193:        speed[0] |= ZREADA(13) << 8;
                    194:        speed[1] = ZREADB(12);
                    195:        speed[1] |= ZREADB(13) << 8;
                    196:        ZWRITE(9, ZSWR9_RESET_WORLD); DELAY(10);
                    197:        zs->zs_wreg[9] = 0;
                    198:        for (i = 0; i < 2; i++) {
                    199:                if (i == 0) {           /* port A */
                    200:                        zs->zs_addr = (struct zscc_device *)
                    201:                                        ((int)md->md_addr | 4);
                    202:                } else {                /* port B */
                    203:                        zs++;
                    204:                        zs->zs_addr = (struct zscc_device *)
                    205:                                        ((int)md->md_addr &~ 4);
                    206:                        zscurr = zs;
                    207:                }
                    208:                zs->zs_unit = md->md_unit * 2 + i;
1.1.1.2 ! root      209:                zssoftflags[zs->zs_unit] = (md->md_flags & (1 << i)) ? 1 : 0;
        !           210:                zssoftflags[zs->zs_unit] |= (md->md_flags & ZS_KBDMS);
1.1       root      211:                for (j=0; zs_proto[j]; j++) {
                    212:                        zso = zs_proto[j];
                    213:                        (*zso->zsop_attach)(zs, speed[i]);
                    214:                }
                    215:        }
                    216:        ZWRITE(9, ZSWR9_MASTER_IE + ZSWR9_VECTOR_INCL_STAT);
                    217:        if (vector)
                    218:                ZWRITE(2, vector);
                    219:        DELAY(4000);
                    220:        startnmi();
                    221:        zslast = zs;
                    222:        if (md->md_intpri != 3) {
                    223:                printf("zs%d: priority %d\n", md->md_unit, md->md_intpri);
                    224:                panic("bad zs priority");
                    225:        }
                    226: }
                    227: 
                    228: /*
                    229:  * Handle Hardware level 6 interrupts
                    230:  * These interrupts are locked out only by splzs or spl7,
                    231:  * not by spl6, so this routine may not use UNIX facilities such
                    232:  * as wakeup which depend on being able to disable interrupts with spls.
                    233:  * All communication with the rest of the world is done through the zscom
                    234:  * structure and the use of level 3 software interrupts.
                    235:  *
                    236:  * This routine is only called when the vector indicated by the most
                    237:  * recently interrupting SCC is a "special receive" interrupt.
                    238:  * This vector is used BOTH for special receive interrupts and to 
                    239:  * indicate NO interrupt pending.  In the no interrupt pending case
                    240:  * we must poll the other SCCs to find the interrupter.
                    241:  * Low level assembler code dispatches the other vectors using the zs_vec
                    242:  * array.  This assembler routine is also the code which actually clears
                    243:  * the interrupt; the argzs argument is a value/return argument which changes
                    244:  * when a different SCC interrupts.
                    245:  */
                    246: zslevel6intr(argzs)
                    247:        struct zscom *argzs;            /* NOTE: value/return argument!! */
                    248: {
                    249:        register struct zscom *zs;
                    250:        register short iinf, unit;
                    251:  
                    252:        zs = zscurr;            /* always channel B */
                    253:        unit = 0;
                    254:        for (;;) {
                    255:                if (zs->zs_addr && ZREADA(3))
                    256:                        break;
                    257:                zs += 2;                /* always channel B */
                    258:                if (zs > zslast)
                    259:                        zs = &zscom[1];
                    260:                if (++unit >= NZS)
                    261:                        return;
                    262:        }
                    263:        zscurr = zs;
                    264:        iinf = ZREAD(2);        /* get interrupt vector & status */
                    265:        if (iinf & 8)
                    266:                zs = zscurr - 1;        /* channel A */
                    267:        else
                    268:                zs = zscurr;            /* channel B */
                    269:        switch (iinf & 6) {
                    270:        case 0:         /* xmit buffer empty */
                    271:                (*zs->zs_ops->zsop_txint)(zs);
                    272:                break;
                    273: 
                    274:        case 2:         /* external/status change */
                    275:                (*zs->zs_ops->zsop_xsint)(zs);
                    276:                break;
                    277: 
                    278:        case 4:         /* receive char available */
                    279:                (*zs->zs_ops->zsop_rxint)(zs);
                    280:                break;
                    281: 
                    282:        case 6:         /* special receive condition or no interrupt */
                    283:                (*zs->zs_ops->zsop_srint)(zs);
                    284:                break;
                    285:        }
                    286:        argzs = zs;
                    287: #ifdef lint
                    288:        argzs = argzs;
                    289: #endif lint
                    290: }
                    291: 
                    292: /*
                    293:  * Install a new ops vector into low level vector routine addresses
                    294:  */
                    295: zsopinit(zs, zso)
                    296:        register struct zscom *zs;
                    297:        register struct zsops *zso;
                    298: {
                    299: 
                    300:        zs->zs_vec[0] = zso->zsop_txint;
                    301:        zs->zs_vec[1] = zso->zsop_xsint;
                    302:        zs->zs_vec[2] = zso->zsop_rxint;
                    303: 
                    304:        switch (cpu) {
                    305: #ifdef sun3
                    306:        case CPU_SUN3_160:
                    307:        case CPU_SUN3_260:
                    308:                /* vectored interrupts */
                    309:                zs->zs_vec[3] = zso->zsop_srint;
                    310:                break;
                    311: #endif sun3
                    312:        default:
                    313:                /* non-vectored Sun-2 and Sun-3 50 (Model 25) */
                    314:                zs->zs_vec[3] = zslevel6intr;
                    315:                break;
                    316:        }
                    317:        zs->zs_ops = zso;
                    318: }
                    319: 
                    320: /*
                    321:  * Handle a level 3 interrupt 
                    322:  * This is the routine found by autoconf in the driver structure
                    323:  */
                    324: zsintr()
                    325: {
                    326:        register struct zscom *zs;
                    327: 
                    328:        if (clrzssoft()) {
                    329:                zssoftpend = 0;
                    330:                for (zs = &zscom[0]; zs <= zslast; zs++) {
                    331:                        if (zs->zs_flags & ZS_NEEDSOFT) {
                    332:                                zs->zs_flags &=~ ZS_NEEDSOFT;
                    333:                                (*zs->zs_ops->zsop_softint)(zs);
                    334:                        }
                    335:                }
                    336:                return (1);
                    337:        }
                    338:        return (0);
                    339: }
                    340: 
                    341: /*
                    342:  * The "null" zs protocol
                    343:  * Called before the others to initialize things
                    344:  * and prevent interrupts on unused devices 
                    345:  */
                    346: int    zsnull_attach(), zsnull_intr(), zsnull_softint();
                    347: 
                    348: struct zsops zsops_null = {
                    349:        zsnull_attach,
                    350:        zsnull_intr,
                    351:        zsnull_intr,
                    352:        zsnull_intr,
                    353:        zsnull_intr,
                    354:        zsnull_softint,
                    355: };
                    356: 
                    357: zsnull_attach(zs, speed)
                    358:        register struct zscom *zs;
                    359: {
                    360: 
                    361:        /* make sure ops prt is valid */
                    362:        zsopinit(zs, &zsops_null);
                    363:        /*
                    364:         * Set up the default asynch modes
                    365:         * so the monitor will still work
                    366:         */
                    367:        ZWRITE(4, ZSWR4_PARITY_EVEN + ZSWR4_1_STOP + ZSWR4_X16_CLK);
                    368:        ZWRITE(3, ZSWR3_RX_8);
                    369:        ZWRITE(11, ZSWR11_TXCLK_BAUD + ZSWR11_RXCLK_BAUD);
                    370:        ZWRITE(12, speed);
                    371:        ZWRITE(13, speed >> 8);
                    372:        ZWRITE(14, ZSWR14_BAUD_FROM_PCLK);
                    373:        ZWRITE(3, ZSWR3_RX_8 + ZSWR3_RX_ENABLE);
                    374:        ZWRITE(5, ZSWR5_TX_ENABLE + ZSWR5_TX_8 + ZSWR5_RTS + ZSWR5_DTR);
                    375:        ZWRITE(14, ZSWR14_BAUD_ENA + ZSWR14_BAUD_FROM_PCLK);
                    376:        zs->zs_addr->zscc_control = ZSWR0_RESET_ERRORS + ZSWR0_RESET_STATUS;
                    377: }
                    378: 
                    379: zsnull_intr(zs)
                    380:        register struct zscom *zs;
                    381: {
                    382:        register struct zscc_device *zsaddr = zs->zs_addr;
                    383:        register short c;
                    384: 
                    385:        zsaddr->zscc_control = ZSWR0_RESET_TXINT;
                    386:        DELAY(2);
                    387:        zsaddr->zscc_control = ZSWR0_RESET_STATUS;
                    388:        DELAY(2);
                    389:        c = zsaddr->zscc_data;
                    390: #ifdef lint
                    391:        c = c;
                    392: #endif lint
                    393:        DELAY(2);
                    394:        zsaddr->zscc_control = ZSWR0_RESET_ERRORS;
                    395: }
                    396: 
                    397: zsnull_softint(zs)
                    398:        register struct zscom *zs;
                    399: {
                    400:        printf("zs%d: unexpected soft int\n", zs->zs_unit);
                    401: }
                    402: #endif NZS > 0

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.