Annotation of sys/dev/ic/z8530sc.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: z8530sc.c,v 1.6 2003/06/02 23:28:02 millert Exp $ */
2: /* $NetBSD: z8530sc.c,v 1.4 1996/05/17 19:30:34 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 <dev/ic/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: * Compute the current baud rate given a ZSCC channel.
92: */
93: int
94: zs_getspeed(cs)
95: struct zs_chanstate *cs;
96: {
97: int tconst;
98:
99: tconst = zs_read_reg(cs, 12);
100: tconst |= zs_read_reg(cs, 13) << 8;
101: return (TCONST_TO_BPS(cs->cs_brg_clk, tconst));
102: }
103:
104: /*
105: * drain on-chip fifo
106: */
107: void
108: zs_iflush(cs)
109: struct zs_chanstate *cs;
110: {
111: u_char c, rr0, rr1;
112:
113: for (;;) {
114: /* Is there input available? */
115: rr0 = zs_read_csr(cs);
116: if ((rr0 & ZSRR0_RX_READY) == 0)
117: break;
118:
119: /*
120: * First read the status, because reading the data
121: * destroys the status of this char.
122: */
123: rr1 = zs_read_reg(cs, 1);
124: c = zs_read_data(cs);
125:
126: if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
127: /* Clear the receive error. */
128: zs_write_csr(cs, ZSWR0_RESET_ERRORS);
129: }
130: }
131: }
132:
133:
134: /*
135: * Write the given register set to the given zs channel in the proper order.
136: * The channel must not be transmitting at the time. The receiver will
137: * be disabled for the time it takes to write all the registers.
138: * Call this with interrupts disabled.
139: */
140: void
141: zs_loadchannelregs(cs)
142: struct zs_chanstate *cs;
143: {
144: u_char *reg;
145:
146: /* Copy "pending" regs to "current" */
147: bcopy((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16);
148: reg = cs->cs_creg; /* current regs */
149:
150: zs_write_csr(cs, ZSM_RESET_ERR); /* XXX: reset error condition */
151:
152: #if 1
153: /*
154: * XXX: Is this really a good idea?
155: * XXX: Should go elsewhere! -gwr
156: */
157: zs_iflush(cs); /* XXX */
158: #endif
159:
160: /* baud clock divisor, stop bits, parity */
161: zs_write_reg(cs, 4, reg[4]);
162:
163: /* misc. TX/RX control bits */
164: zs_write_reg(cs, 10, reg[10]);
165:
166: /* char size, enable (RX/TX) */
167: zs_write_reg(cs, 3, reg[3] & ~ZSWR3_RX_ENABLE);
168: zs_write_reg(cs, 5, reg[5] & ~ZSWR5_TX_ENABLE);
169:
170: /* interrupt enables: TX, TX, STATUS */
171: zs_write_reg(cs, 1, reg[1]);
172:
173: #if 0
174: /*
175: * Registers 2 and 9 are special because they are
176: * actually common to both channels, but must be
177: * programmed through channel A. The "zsc" attach
178: * function takes care of setting these registers
179: * and they should not be touched thereafter.
180: */
181: /* interrupt vector */
182: zs_write_reg(cs, 2, reg[2]);
183: /* master interrupt control */
184: zs_write_reg(cs, 9, reg[9]);
185: #endif
186:
187: /* clock mode control */
188: zs_write_reg(cs, 11, reg[11]);
189:
190: /* baud rate (lo/hi) */
191: zs_write_reg(cs, 12, reg[12]);
192: zs_write_reg(cs, 13, reg[13]);
193:
194: /* Misc. control bits */
195: zs_write_reg(cs, 14, reg[14]);
196:
197: /* which lines cause status interrupts */
198: zs_write_reg(cs, 15, reg[15]);
199:
200: /* char size, enable (RX/TX)*/
201: zs_write_reg(cs, 3, reg[3]);
202: zs_write_reg(cs, 5, reg[5]);
203: }
204:
205:
206: /*
207: * ZS hardware interrupt. Scan all ZS channels. NB: we know here that
208: * channels are kept in (A,B) pairs.
209: *
210: * Do just a little, then get out; set a software interrupt if more
211: * work is needed.
212: *
213: * We deliberately ignore the vectoring Zilog gives us, and match up
214: * only the number of `reset interrupt under service' operations, not
215: * the order.
216: */
217: int
218: zsc_intr_hard(arg)
219: void *arg;
220: {
221: register struct zsc_softc *zsc = arg;
222: register struct zs_chanstate *cs_a;
223: register struct zs_chanstate *cs_b;
224: register int rval;
225: register u_char rr3;
226:
227: cs_a = &zsc->zsc_cs[0];
228: cs_b = &zsc->zsc_cs[1];
229: rval = 0;
230:
231: /* Note: only channel A has an RR3 */
232: rr3 = zs_read_reg(cs_a, 3);
233:
234: /* Handle receive interrupts first. */
235: if (rr3 & ZSRR3_IP_A_RX)
236: (*cs_a->cs_ops->zsop_rxint)(cs_a);
237: if (rr3 & ZSRR3_IP_B_RX)
238: (*cs_b->cs_ops->zsop_rxint)(cs_b);
239:
240: /* Handle status interrupts (i.e. flow control). */
241: if (rr3 & ZSRR3_IP_A_STAT)
242: (*cs_a->cs_ops->zsop_stint)(cs_a);
243: if (rr3 & ZSRR3_IP_B_STAT)
244: (*cs_b->cs_ops->zsop_stint)(cs_b);
245:
246: /* Handle transmit done interrupts. */
247: if (rr3 & ZSRR3_IP_A_TX)
248: (*cs_a->cs_ops->zsop_txint)(cs_a);
249: if (rr3 & ZSRR3_IP_B_TX)
250: (*cs_b->cs_ops->zsop_txint)(cs_b);
251:
252: /* Clear interrupt. */
253: if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
254: zs_write_csr(cs_a, ZSWR0_CLR_INTR);
255: rval |= 1;
256: }
257: if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
258: zs_write_csr(cs_b, ZSWR0_CLR_INTR);
259: rval |= 2;
260: }
261:
262: if ((cs_a->cs_softreq) || (cs_b->cs_softreq)) {
263: /* This is a machine-dependent function (or macro). */
264: zsc_req_softint(zsc);
265: }
266:
267: return (rval);
268: }
269:
270:
271: /*
272: * ZS software interrupt. Scan all channels for deferred interrupts.
273: */
274: int
275: zsc_intr_soft(arg)
276: void *arg;
277: {
278: register struct zsc_softc *zsc = arg;
279: register struct zs_chanstate *cs;
280: register int rval, unit;
281:
282: rval = 0;
283: for (unit = 0; unit < 2; unit++) {
284: cs = &zsc->zsc_cs[unit];
285:
286: /*
287: * The softint flag can be safely cleared once
288: * we have decided to call the softint routine.
289: * (No need to do splzs() first.)
290: */
291: if (cs->cs_softreq) {
292: cs->cs_softreq = 0;
293: (*cs->cs_ops->zsop_softint)(cs);
294: rval = 1;
295: }
296: }
297: return (rval);
298: }
299:
300:
301: static void
302: zsnull_intr(cs)
303: struct zs_chanstate *cs;
304: {
305: zs_write_reg(cs, 1, 0);
306: zs_write_reg(cs, 15, 0);
307: }
308:
309: static void
310: zsnull_softint(cs)
311: struct zs_chanstate *cs;
312: {
313: }
314:
315: struct zsops zsops_null = {
316: zsnull_intr, /* receive char available */
317: zsnull_intr, /* external/status */
318: zsnull_intr, /* xmit buffer empty */
319: zsnull_softint, /* process software interrupt */
320: };
CVSweb