Annotation of sys/arch/sparc/dev/z8530sc.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: z8530sc.c,v 1.2 2003/06/02 23:27:54 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 <sparc/dev/z8530reg.h>
65: #include <machine/z8530var.h>
66:
67: void
68: zs_break(cs, set)
69: struct zs_chanstate *cs;
70: int set;
71: {
72:
73: if (set) {
74: cs->cs_preg[5] |= ZSWR5_BREAK;
75: cs->cs_creg[5] |= ZSWR5_BREAK;
76: } else {
77: cs->cs_preg[5] &= ~ZSWR5_BREAK;
78: cs->cs_creg[5] &= ~ZSWR5_BREAK;
79: }
80: zs_write_reg(cs, 5, cs->cs_creg[5]);
81: }
82:
83:
84: /*
85: * drain on-chip fifo
86: */
87: void
88: zs_iflush(cs)
89: struct zs_chanstate *cs;
90: {
91: u_char c, rr0, rr1;
92: int i;
93:
94: /*
95: * Count how many times we loop. Some systems, such as some
96: * Apple PowerBooks, claim to have SCC's which they really don't.
97: */
98: for (i = 0; i < 32; i++) {
99: /* Is there input available? */
100: rr0 = zs_read_csr(cs);
101: if ((rr0 & ZSRR0_RX_READY) == 0)
102: break;
103:
104: /*
105: * First read the status, because reading the data
106: * destroys the status of this char.
107: */
108: rr1 = zs_read_reg(cs, 1);
109: c = zs_read_data(cs);
110:
111: if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
112: /* Clear the receive error. */
113: zs_write_csr(cs, ZSWR0_RESET_ERRORS);
114: }
115: }
116: }
117:
118:
119: /*
120: * Write the given register set to the given zs channel in the proper order.
121: * The channel must not be transmitting at the time. The receiver will
122: * be disabled for the time it takes to write all the registers.
123: * Call this with interrupts disabled.
124: */
125: void
126: zs_loadchannelregs(cs)
127: struct zs_chanstate *cs;
128: {
129: u_char *reg;
130:
131: zs_write_csr(cs, ZSM_RESET_ERR); /* XXX: reset error condition */
132:
133: #if 1
134: /*
135: * XXX: Is this really a good idea?
136: * XXX: Should go elsewhere! -gwr
137: */
138: zs_iflush(cs); /* XXX */
139: #endif
140:
141: if (memcmp((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16) == 0)
142: return; /* only change if values are different */
143:
144: /* Copy "pending" regs to "current" */
145: memcpy((caddr_t)cs->cs_creg, (caddr_t)cs->cs_preg, 16);
146: reg = cs->cs_creg; /* current regs */
147:
148: /* disable interrupts */
149: zs_write_reg(cs, 1, reg[1] & ~ZSWR1_IMASK);
150:
151: /* baud clock divisor, stop bits, parity */
152: zs_write_reg(cs, 4, reg[4]);
153:
154: /* misc. TX/RX control bits */
155: zs_write_reg(cs, 10, reg[10]);
156:
157: /* char size, enable (RX/TX) */
158: zs_write_reg(cs, 3, reg[3] & ~ZSWR3_RX_ENABLE);
159: zs_write_reg(cs, 5, reg[5] & ~ZSWR5_TX_ENABLE);
160:
161: /* synchronous mode stuff */
162: zs_write_reg(cs, 6, reg[6]);
163: zs_write_reg(cs, 7, reg[7]);
164:
165: #if 0
166: /*
167: * Registers 2 and 9 are special because they are
168: * actually common to both channels, but must be
169: * programmed through channel A. The "zsc" attach
170: * function takes care of setting these registers
171: * and they should not be touched thereafter.
172: */
173: /* interrupt vector */
174: zs_write_reg(cs, 2, reg[2]);
175: /* master interrupt control */
176: zs_write_reg(cs, 9, reg[9]);
177: #endif
178:
179: /* Shut down the BRG */
180: zs_write_reg(cs, 14, reg[14] & ~ZSWR14_BAUD_ENA);
181:
182: #ifdef ZS_MD_SETCLK
183: /* Let the MD code setup any external clock. */
184: ZS_MD_SETCLK(cs);
185: #endif /* ZS_MD_SETCLK */
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: /*
201: * Zilog docs recommend resetting external status twice at this
202: * point. Mainly as the status bits are latched, and the first
203: * interrupt clear might unlatch them to new values, generating
204: * a second interrupt request.
205: */
206: zs_write_csr(cs, ZSM_RESET_STINT);
207: zs_write_csr(cs, ZSM_RESET_STINT);
208:
209: /* char size, enable (RX/TX)*/
210: zs_write_reg(cs, 3, reg[3]);
211: zs_write_reg(cs, 5, reg[5]);
212:
213: /* interrupt enables: TX, TX, STATUS */
214: zs_write_reg(cs, 1, reg[1]);
215: }
216:
217:
218: /*
219: * ZS hardware interrupt. Scan all ZS channels. NB: we know here that
220: * channels are kept in (A,B) pairs.
221: *
222: * Do just a little, then get out; set a software interrupt if more
223: * work is needed.
224: *
225: * We deliberately ignore the vectoring Zilog gives us, and match up
226: * only the number of `reset interrupt under service' operations, not
227: * the order.
228: */
229: int
230: zsc_intr_hard(arg)
231: void *arg;
232: {
233: struct zsc_softc *zsc = arg;
234: struct zs_chanstate *cs;
235: u_char rr3;
236:
237: /* First look at channel A. */
238: cs = &zsc->zsc_cs[0];
239: /* Note: only channel A has an RR3 */
240: rr3 = zs_read_reg(cs, 3);
241:
242: /*
243: * Clear interrupt first to avoid a race condition.
244: * If a new interrupt condition happens while we are
245: * servicing this one, we will get another interrupt
246: * shortly. We can NOT just sit here in a loop, or
247: * we will cause horrible latency for other devices
248: * on this interrupt level (i.e. sun3x floppy disk).
249: */
250: if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
251: zs_write_csr(cs, ZSWR0_CLR_INTR);
252: if (rr3 & ZSRR3_IP_A_RX)
253: (*cs->cs_ops->zsop_rxint)(cs);
254: if (rr3 & ZSRR3_IP_A_STAT)
255: (*cs->cs_ops->zsop_stint)(cs, 0);
256: if (rr3 & ZSRR3_IP_A_TX)
257: (*cs->cs_ops->zsop_txint)(cs);
258: }
259:
260: /* Now look at channel B. */
261: cs = &zsc->zsc_cs[1];
262: if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
263: zs_write_csr(cs, ZSWR0_CLR_INTR);
264: if (rr3 & ZSRR3_IP_B_RX)
265: (*cs->cs_ops->zsop_rxint)(cs);
266: if (rr3 & ZSRR3_IP_B_STAT)
267: (*cs->cs_ops->zsop_stint)(cs, 0);
268: if (rr3 & ZSRR3_IP_B_TX)
269: (*cs->cs_ops->zsop_txint)(cs);
270: }
271:
272: /* Note: caller will check cs_x->cs_softreq and DTRT. */
273: return (rr3);
274: }
275:
276:
277: /*
278: * ZS software interrupt. Scan all channels for deferred interrupts.
279: */
280: int
281: zsc_intr_soft(arg)
282: void *arg;
283: {
284: struct zsc_softc *zsc = arg;
285: struct zs_chanstate *cs;
286: int rval, chan;
287:
288: rval = 0;
289: for (chan = 0; chan < 2; chan++) {
290: cs = &zsc->zsc_cs[chan];
291:
292: /*
293: * The softint flag can be safely cleared once
294: * we have decided to call the softint routine.
295: * (No need to do splzs() first.)
296: */
297: if (cs->cs_softreq) {
298: cs->cs_softreq = 0;
299: (*cs->cs_ops->zsop_softint)(cs);
300: rval++;
301: }
302: }
303: return (rval);
304: }
305:
306: /*
307: * Provide a null zs "ops" vector.
308: */
309:
310: void zsnull_rxint(struct zs_chanstate *);
311: void zsnull_stint(struct zs_chanstate *, int);
312: void zsnull_txint(struct zs_chanstate *);
313: void zsnull_softint(struct zs_chanstate *);
314:
315: void
316: zsnull_rxint(cs)
317: struct zs_chanstate *cs;
318: {
319: /* Ask for softint() call. */
320: cs->cs_softreq = 1;
321: }
322:
323: void
324: zsnull_stint(cs, force)
325: struct zs_chanstate *cs;
326: int force;
327: {
328: /* Ask for softint() call. */
329: cs->cs_softreq = 1;
330: }
331:
332: void
333: zsnull_txint(cs)
334: struct zs_chanstate *cs;
335: {
336: /* Ask for softint() call. */
337: cs->cs_softreq = 1;
338: }
339:
340: void
341: zsnull_softint(cs)
342: struct zs_chanstate *cs;
343: {
344: zs_write_reg(cs, 1, 0);
345: zs_write_reg(cs, 15, 0);
346: }
347:
348: struct zsops zsops_null = {
349: zsnull_rxint, /* receive char available */
350: zsnull_stint, /* external/status */
351: zsnull_txint, /* xmit buffer empty */
352: zsnull_softint, /* process software interrupt */
353: };
CVSweb