|
|
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.