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

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