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