Annotation of sys/arch/mac68k/dev/z8530sc.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: z8530sc.c,v 1.7 2004/11/25 18:32:10 miod Exp $ */
2: /* $NetBSD: z8530sc.c,v 1.5 1996/12/17 20:42:40 gwr Exp $ */
3:
4: /*
5: * Copyright (c) 1994 Gordon W. Ross
6: * Copyright (c) 1992, 1993
7: * The Regents of the University of California. All rights reserved.
8: *
9: * This software was developed by the Computer Systems Engineering group
10: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
11: * contributed to Berkeley.
12: *
13: * All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Lawrence Berkeley Laboratory.
17: *
18: * Redistribution and use in source and binary forms, with or without
19: * modification, are permitted provided that the following conditions
20: * are met:
21: * 1. Redistributions of source code must retain the above copyright
22: * notice, this list of conditions and the following disclaimer.
23: * 2. Redistributions in binary form must reproduce the above copyright
24: * notice, this list of conditions and the following disclaimer in the
25: * documentation and/or other materials provided with the distribution.
26: * 3. Neither the name of the University nor the names of its contributors
27: * may be used to endorse or promote products derived from this software
28: * without specific prior written permission.
29: *
30: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40: * SUCH DAMAGE.
41: *
42: * @(#)zs.c 8.1 (Berkeley) 7/19/93
43: */
44:
45: /*
46: * Zilog Z8530 Dual UART driver (common part)
47: *
48: * This file contains the machine-independent parts of the
49: * driver common to tty and keyboard/mouse sub-drivers.
50: */
51:
52: #include <sys/param.h>
53: #include <sys/systm.h>
54: #include <sys/proc.h>
55: #include <sys/device.h>
56: #include <sys/conf.h>
57: #include <sys/file.h>
58: #include <sys/ioctl.h>
59: #include <sys/tty.h>
60: #include <sys/time.h>
61: #include <sys/kernel.h>
62: #include <sys/syslog.h>
63:
64: #include <mac68k/dev/z8530reg.h>
65: #include <machine/z8530var.h>
66:
67: static void zsnull_intr(struct zs_chanstate *);
68: static void zsnull_softint(struct zs_chanstate *);
69:
70: void
71: zs_break(cs, set)
72: struct zs_chanstate *cs;
73: int set;
74: {
75: int s;
76:
77: s = splzs();
78: if (set) {
79: cs->cs_preg[5] |= ZSWR5_BREAK;
80: cs->cs_creg[5] |= ZSWR5_BREAK;
81: } else {
82: cs->cs_preg[5] &= ~ZSWR5_BREAK;
83: cs->cs_creg[5] &= ~ZSWR5_BREAK;
84: }
85: zs_write_reg(cs, 5, cs->cs_creg[5]);
86: splx(s);
87: }
88:
89:
90: /*
91: * drain on-chip fifo
92: */
93: void
94: zs_iflush(cs)
95: struct zs_chanstate *cs;
96: {
97: u_char c, rr0, rr1;
98:
99: for (;;) {
100: /* Is there input available? */
101: rr0 = zs_read_csr(cs);
102: if ((rr0 & ZSRR0_RX_READY) == 0)
103: break;
104:
105: /*
106: * First read the status, because reading the data
107: * destroys the status of this char.
108: */
109: rr1 = zs_read_reg(cs, 1);
110: c = zs_read_data(cs);
111:
112: if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
113: /* Clear the receive error. */
114: zs_write_csr(cs, ZSWR0_RESET_ERRORS);
115: }
116: }
117: }
118:
119:
120: /*
121: * Write the given register set to the given zs channel in the proper order.
122: * The channel must not be transmitting at the time. The receiver will
123: * be disabled for the time it takes to write all the registers.
124: * Call this with interrupts disabled.
125: */
126: void
127: zs_loadchannelregs(cs)
128: struct zs_chanstate *cs;
129: {
130: u_char *reg;
131:
132: /* Copy "pending" regs to "current" */
133: bcopy((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16);
134: reg = cs->cs_creg; /* current regs */
135:
136: zs_write_csr(cs, ZSM_RESET_ERR); /* XXX: reset error condition */
137:
138: #if 1
139: /*
140: * XXX: Is this really a good idea?
141: * XXX: Should go elsewhere! -gwr
142: */
143: zs_iflush(cs); /* XXX */
144: #endif
145:
146: /* disable interrupts */
147: zs_write_reg(cs, 1, reg[1] & ~ZSWR1_IMASK);
148:
149: /* baud clock divisor, stop bits, parity */
150: zs_write_reg(cs, 4, reg[4]);
151:
152: /* misc. TX/RX control bits */
153: zs_write_reg(cs, 10, reg[10]);
154:
155: /* char size, enable (RX/TX) */
156: zs_write_reg(cs, 3, reg[3] & ~ZSWR3_RX_ENABLE);
157: zs_write_reg(cs, 5, reg[5] & ~ZSWR5_TX_ENABLE);
158:
159: /* synchronous mode stuff */
160: zs_write_reg(cs, 6, reg[6]);
161: zs_write_reg(cs, 7, reg[7]);
162:
163: #if 0
164: /*
165: * Registers 2 and 9 are special because they are
166: * actually common to both channels, but must be
167: * programmed through channel A. The "zsc" attach
168: * function takes care of setting these registers
169: * and they should not be touched thereafter.
170: */
171: /* interrupt vector */
172: zs_write_reg(cs, 2, reg[2]);
173: /* master interrupt control */
174: zs_write_reg(cs, 9, reg[9]);
175: #endif
176:
177: /* Shut down the BRG */
178: zs_write_reg(cs, 14, reg[14] & ~ZSWR14_BAUD_ENA);
179:
180: #ifdef ZS_MD_SETCLK
181: /* Let the MD code setup any external clock. */
182: ZS_MD_SETCLK(cs);
183: #endif /* ZS_MD_SETCLK */
184:
185: /* clock mode control */
186: zs_write_reg(cs, 11, reg[11]);
187:
188: /* baud rate (lo/hi) */
189: zs_write_reg(cs, 12, reg[12]);
190: zs_write_reg(cs, 13, reg[13]);
191:
192: /* Misc. control bits */
193: zs_write_reg(cs, 14, reg[14]);
194:
195: /* which lines cause status interrupts */
196: zs_write_reg(cs, 15, reg[15]);
197:
198: /*
199: * Zilog docs recommend resetting external status twice at this
200: * point. Mainly as the status bits are latched, and the first
201: * interrupt clear might unlatch them to new values, generating
202: * a second interrupt request.
203: */
204: zs_write_csr(cs, ZSM_RESET_STINT);
205: zs_write_csr(cs, ZSM_RESET_STINT);
206:
207: /* char size, enable (RX/TX)*/
208: zs_write_reg(cs, 3, reg[3]);
209: zs_write_reg(cs, 5, reg[5]);
210:
211: /* interrupt enables: RX, TX, STATUS */
212: zs_write_reg(cs, 1, reg[1]);
213: }
214:
215:
216: /*
217: * ZS hardware interrupt. Scan all ZS channels. NB: we know here that
218: * channels are kept in (A,B) pairs.
219: *
220: * Do just a little, then get out; set a software interrupt if more
221: * work is needed.
222: *
223: * We deliberately ignore the vectoring Zilog gives us, and match up
224: * only the number of `reset interrupt under service' operations, not
225: * the order.
226: */
227: int
228: zsc_intr_hard(arg)
229: void *arg;
230: {
231: register struct zsc_softc *zsc = arg;
232: register struct zs_chanstate *cs_a;
233: register struct zs_chanstate *cs_b;
234: register int rval;
235: register u_char rr3, rr3a;
236:
237: cs_a = zsc->zsc_cs[0];
238: cs_b = zsc->zsc_cs[1];
239: rval = 0;
240: rr3a = 0;
241:
242: /* Note: only channel A has an RR3 */
243: while ((rr3 = zs_read_reg(cs_a, 3)) != 0) {
244:
245: /* Handle receive interrupts first. */
246: if (rr3 & ZSRR3_IP_A_RX)
247: (*cs_a->cs_ops->zsop_rxint)(cs_a);
248: if (rr3 & ZSRR3_IP_B_RX)
249: (*cs_b->cs_ops->zsop_stint)(cs_b);
250:
251: /* Handle status interrupts (i.e. flow control). */
252: if (rr3 & ZSRR3_IP_A_STAT)
253: (*cs_a->cs_ops->zsop_stint)(cs_a);
254: if (rr3 & ZSRR3_IP_B_STAT)
255: (*cs_b->cs_ops->zsop_stint)(cs_b);
256:
257: /* Handle transmit done interrupts. */
258: if (rr3 & ZSRR3_IP_A_TX)
259: (*cs_a->cs_ops->zsop_txint)(cs_a);
260: if (rr3 & ZSRR3_IP_B_TX)
261: (*cs_b->cs_ops->zsop_txint)(cs_b);
262:
263: /* Accumulate so we know what needs to be cleared. */
264: rr3a |= rr3;
265: }
266:
267:
268: /* Clear interrupt. */
269: if (rr3a & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
270: zs_write_csr(cs_a, ZSWR0_CLR_INTR);
271: rval |= 1;
272: }
273: if (rr3a & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
274: zs_write_csr(cs_b, ZSWR0_CLR_INTR);
275: rval |= 2;
276: }
277:
278: /* Note: caller will check cs_x->cs_softreq and DTRT. */
279: return (rval);
280: }
281:
282:
283: /*
284: * ZS software interrupt. Scan all channels for deferred interrupts.
285: */
286: int
287: zsc_intr_soft(arg)
288: void *arg;
289: {
290: register struct zsc_softc *zsc = arg;
291: register struct zs_chanstate *cs;
292: register int rval, chan;
293:
294: rval = 0;
295: for (chan = 0; chan < 2; chan++) {
296: cs = zsc->zsc_cs[chan];
297:
298: /*
299: * The softint flag can be safely cleared once
300: * we have decided to call the softint routine.
301: * (No need to do splzs() first.)
302: */
303: if (cs->cs_softreq) {
304: cs->cs_softreq = 0;
305: (*cs->cs_ops->zsop_softint)(cs);
306: rval++;
307: }
308: }
309: return (rval);
310: }
311:
312: /*
313: * Provide a null zs "ops" vector.
314: */
315:
316: static void zsnull_intr(struct zs_chanstate *);
317: static void zsnull_softint(struct zs_chanstate *);
318:
319: static void
320: zsnull_intr(cs)
321: struct zs_chanstate *cs;
322: {
323: /* Ask for softint() call. */
324: cs->cs_softreq = 1;
325: }
326:
327: static void
328: zsnull_softint(cs)
329: struct zs_chanstate *cs;
330: {
331: zs_write_reg(cs, 1, 0);
332: zs_write_reg(cs, 15, 0);
333: }
334:
335: struct zsops zsops_null = {
336: zsnull_intr, /* receive char available */
337: zsnull_intr, /* external/status */
338: zsnull_intr, /* xmit buffer empty */
339: zsnull_softint, /* process software interrupt */
340: };
CVSweb