Annotation of researchv9/sys/sundev/zs_common.c, revision 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.