|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.