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