mfc.c revision 1.10 1 1.10 thorpej /* $NetBSD: mfc.c,v 1.10 1996/03/17 01:17:43 thorpej Exp $ */
2 1.3 chopps
3 1.1 chopps /*
4 1.1 chopps * Copyright (c) 1994 Michael L. Hitch
5 1.1 chopps * Copyright (c) 1982, 1990 The Regents of the University of California.
6 1.1 chopps * All rights reserved.
7 1.1 chopps *
8 1.1 chopps * Redistribution and use in source and binary forms, with or without
9 1.1 chopps * modification, are permitted provided that the following conditions
10 1.1 chopps * are met:
11 1.1 chopps * 1. Redistributions of source code must retain the above copyright
12 1.1 chopps * notice, this list of conditions and the following disclaimer.
13 1.1 chopps * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 chopps * notice, this list of conditions and the following disclaimer in the
15 1.1 chopps * documentation and/or other materials provided with the distribution.
16 1.1 chopps * 3. All advertising materials mentioning features or use of this software
17 1.1 chopps * must display the following acknowledgement:
18 1.1 chopps * This product includes software developed by the University of
19 1.1 chopps * California, Berkeley and its contributors.
20 1.1 chopps * 4. Neither the name of the University nor the names of its contributors
21 1.1 chopps * may be used to endorse or promote products derived from this software
22 1.1 chopps * without specific prior written permission.
23 1.1 chopps *
24 1.1 chopps * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 1.1 chopps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 1.1 chopps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 1.1 chopps * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 1.1 chopps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 1.1 chopps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 1.1 chopps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 1.1 chopps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 1.1 chopps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 1.1 chopps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 1.1 chopps * SUCH DAMAGE.
35 1.1 chopps */
36 1.1 chopps
37 1.1 chopps #include <sys/param.h>
38 1.1 chopps #include <sys/systm.h>
39 1.1 chopps #include <sys/kernel.h>
40 1.1 chopps #include <sys/device.h>
41 1.1 chopps #include <sys/tty.h>
42 1.1 chopps #include <sys/proc.h>
43 1.1 chopps #include <sys/conf.h>
44 1.1 chopps #include <sys/file.h>
45 1.1 chopps #include <sys/malloc.h>
46 1.1 chopps #include <sys/uio.h>
47 1.1 chopps #include <sys/kernel.h>
48 1.1 chopps #include <sys/syslog.h>
49 1.1 chopps #include <sys/queue.h>
50 1.1 chopps #include <machine/cpu.h>
51 1.1 chopps #include <amiga/amiga/device.h>
52 1.2 chopps #include <amiga/amiga/isr.h>
53 1.1 chopps #include <amiga/amiga/custom.h>
54 1.1 chopps #include <amiga/amiga/cia.h>
55 1.1 chopps #include <amiga/amiga/cc.h>
56 1.2 chopps #include <amiga/dev/zbusvar.h>
57 1.1 chopps
58 1.1 chopps #include <dev/cons.h>
59 1.1 chopps
60 1.1 chopps #include "mfcs.h"
61 1.1 chopps
62 1.7 chopps #ifndef SEROBUF_SIZE
63 1.1 chopps #define SEROBUF_SIZE 128
64 1.7 chopps #endif
65 1.7 chopps #ifndef SERIBUF_SIZE
66 1.1 chopps #define SERIBUF_SIZE 1024
67 1.7 chopps #endif
68 1.1 chopps
69 1.2 chopps #define splser() spl6()
70 1.2 chopps
71 1.2 chopps /*
72 1.2 chopps * 68581 DUART registers
73 1.2 chopps */
74 1.1 chopps struct mfc_regs {
75 1.1 chopps volatile u_char du_mr1a;
76 1.1 chopps #define du_mr2a du_mr1a
77 1.1 chopps u_char pad0;
78 1.1 chopps volatile u_char du_csra;
79 1.1 chopps #define du_sra du_csra
80 1.1 chopps u_char pad2;
81 1.1 chopps volatile u_char du_cra;
82 1.1 chopps u_char pad4;
83 1.1 chopps volatile u_char du_tba;
84 1.1 chopps #define du_rba du_tba
85 1.1 chopps u_char pad6;
86 1.1 chopps volatile u_char du_acr;
87 1.1 chopps #define du_ipcr du_acr
88 1.1 chopps u_char pad8;
89 1.1 chopps volatile u_char du_imr;
90 1.1 chopps #define du_isr du_imr
91 1.1 chopps u_char pad10;
92 1.1 chopps volatile u_char du_ctur;
93 1.1 chopps #define du_cmsb du_ctur
94 1.1 chopps u_char pad12;
95 1.1 chopps volatile u_char du_ctlr;
96 1.1 chopps #define du_clsb du_ctlr
97 1.1 chopps u_char pad14;
98 1.1 chopps volatile u_char du_mr1b;
99 1.1 chopps #define du_mr2b du_mr1b
100 1.1 chopps u_char pad16;
101 1.1 chopps volatile u_char du_csrb;
102 1.1 chopps #define du_srb du_csrb
103 1.1 chopps u_char pad18;
104 1.1 chopps volatile u_char du_crb;
105 1.1 chopps u_char pad20;
106 1.1 chopps volatile u_char du_tbb;
107 1.1 chopps #define du_rbb du_tbb
108 1.1 chopps u_char pad22;
109 1.1 chopps volatile u_char du_ivr;
110 1.1 chopps u_char pad24;
111 1.1 chopps volatile u_char du_opcr;
112 1.1 chopps #define du_ip du_opcr
113 1.1 chopps u_char pad26;
114 1.1 chopps volatile u_char du_btst;
115 1.1 chopps #define du_strc du_btst
116 1.1 chopps u_char pad28;
117 1.1 chopps volatile u_char du_btrst;
118 1.1 chopps #define du_stpc du_btrst
119 1.1 chopps u_char pad30;
120 1.1 chopps };
121 1.1 chopps
122 1.2 chopps /*
123 1.2 chopps * 68681 DUART serial port registers
124 1.2 chopps */
125 1.1 chopps struct duart_regs {
126 1.1 chopps volatile u_char ch_mr1;
127 1.1 chopps #define ch_mr2 ch_mr1
128 1.1 chopps u_char pad0;
129 1.1 chopps volatile u_char ch_csr;
130 1.1 chopps #define ch_sr ch_csr
131 1.1 chopps u_char pad1;
132 1.1 chopps volatile u_char ch_cr;
133 1.1 chopps u_char pad2;
134 1.1 chopps volatile u_char ch_tb;
135 1.1 chopps #define ch_rb ch_tb
136 1.1 chopps u_char pad3;
137 1.1 chopps };
138 1.1 chopps
139 1.1 chopps struct mfc_softc {
140 1.1 chopps struct device sc_dev;
141 1.2 chopps struct isr sc_isr;
142 1.1 chopps struct mfc_regs *sc_regs;
143 1.1 chopps u_long clk_frq;
144 1.1 chopps u_short ct_val;
145 1.1 chopps u_char ct_usecnt;
146 1.1 chopps u_char imask;
147 1.1 chopps u_char mfc_iii;
148 1.1 chopps u_char last_ip;
149 1.1 chopps };
150 1.1 chopps
151 1.2 chopps #if NMFCS > 0
152 1.1 chopps struct mfcs_softc {
153 1.1 chopps struct device sc_dev;
154 1.6 chopps struct tty *sc_tty;
155 1.1 chopps struct duart_regs *sc_duart;
156 1.1 chopps struct mfc_regs *sc_regs;
157 1.1 chopps struct mfc_softc *sc_mfc;
158 1.9 jtc int swflags;
159 1.1 chopps long flags; /* XXX */
160 1.1 chopps #define CT_USED 1 /* CT in use */
161 1.1 chopps u_short *rptr, *wptr, incnt, ovfl;
162 1.1 chopps u_short inbuf[SERIBUF_SIZE];
163 1.1 chopps char *ptr, *end;
164 1.1 chopps char outbuf[SEROBUF_SIZE];
165 1.9 jtc struct vbl_node vbl_node;
166 1.1 chopps };
167 1.2 chopps #endif
168 1.2 chopps
169 1.2 chopps #if NMFCP > 0
170 1.2 chopps struct mfcp_softc {
171 1.2 chopps };
172 1.2 chopps #endif
173 1.1 chopps
174 1.1 chopps struct mfc_args {
175 1.1 chopps struct zbus_args zargs;
176 1.1 chopps char *subdev;
177 1.1 chopps char unit;
178 1.1 chopps };
179 1.1 chopps
180 1.1 chopps int mfcprint __P((void *auxp, char *));
181 1.1 chopps void mfcattach __P((struct device *, struct device *, void *));
182 1.10 thorpej int mfcmatch __P((struct device *, void *, void *));
183 1.2 chopps #if NMFCS > 0
184 1.1 chopps void mfcsattach __P((struct device *, struct device *, void *));
185 1.10 thorpej int mfcsmatch __P((struct device *, void *, void *));
186 1.2 chopps #endif
187 1.2 chopps #if NMFCP > 0
188 1.2 chopps void mfcpattach __P((struct device *, struct device *, void *));
189 1.10 thorpej int mfcpmatch __P((struct device *, void *, void *));
190 1.2 chopps #endif
191 1.2 chopps int mfcintr __P((struct mfc_softc *));
192 1.1 chopps void mfcsmint __P((register int unit));
193 1.1 chopps
194 1.10 thorpej struct mfc_ca = {
195 1.10 thorpej sizeof(struct mfc_softc), mfcmatch, mfcattach
196 1.10 thorpej };
197 1.10 thorpej
198 1.10 thorpej struct cfdriver mfc_cd = {
199 1.10 thorpej NULL, "mfc", DV_DULL, NULL, 0
200 1.10 thorpej };
201 1.1 chopps
202 1.2 chopps #if NMFCS > 0
203 1.10 thorpej struct cfattach mfcs_ca = {
204 1.10 thorpej sizeof(struct mfcs_softc), mfcsmatch, mfcsattach
205 1.10 thorpej };
206 1.10 thorpej
207 1.10 thorpej struct cfdriver mfcs_cd = {
208 1.10 thorpej NULL, "mfcs", DV_TTY, NULL, 0
209 1.10 thorpej };
210 1.2 chopps #endif
211 1.2 chopps
212 1.2 chopps #if NMFCP > 0
213 1.10 thorpej struct cfattach mfcp_ca = {
214 1.10 thorpej sizeof(struct mfcp_softc, mfcpmatch, mfcpattach
215 1.10 thorpej };
216 1.10 thorpej
217 1.10 thorpej struct cfdriver mfcp_cd = {
218 1.10 thorpej NULL, "mfcp", DV_DULL, NULL, 0
219 1.10 thorpej };
220 1.2 chopps #endif
221 1.1 chopps
222 1.1 chopps int mfcsstart(), mfcsparam(), mfcshwiflow();
223 1.1 chopps int mfcs_active;
224 1.1 chopps int mfcsdefaultrate = 38400 /*TTYDEF_SPEED*/;
225 1.9 jtc #define SWFLAGS(dev) (sc->swflags | (((dev) & 0x80) == 0 ? TIOCFLAG_SOFTCAR : 0))
226 1.1 chopps
227 1.4 chopps #ifdef notyet
228 1.4 chopps /*
229 1.4 chopps * MultiFaceCard III, II+ (not supported yet), and
230 1.4 chopps * SerialMaster 500+ (not supported yet)
231 1.4 chopps * baud rate tables for BRG set 1 [not used yet]
232 1.4 chopps */
233 1.4 chopps
234 1.4 chopps struct speedtab mfcs3speedtab1[] = {
235 1.4 chopps 0, 0,
236 1.4 chopps 100, 0x00,
237 1.4 chopps 220, 0x11,
238 1.4 chopps 600, 0x44,
239 1.4 chopps 1200, 0x55,
240 1.4 chopps 2400, 0x66,
241 1.4 chopps 4800, 0x88,
242 1.4 chopps 9600, 0x99,
243 1.4 chopps 19200, 0xbb,
244 1.4 chopps 115200, 0xcc,
245 1.4 chopps -1, -1
246 1.4 chopps };
247 1.4 chopps
248 1.4 chopps /*
249 1.4 chopps * MultiFaceCard II, I, and SerialMaster 500
250 1.4 chopps * baud rate tables for BRG set 1 [not used yet]
251 1.4 chopps */
252 1.4 chopps
253 1.4 chopps struct speedtab mfcs2speedtab1[] = {
254 1.4 chopps 0, 0,
255 1.4 chopps 50, 0x00,
256 1.4 chopps 110, 0x11,
257 1.4 chopps 300, 0x44,
258 1.4 chopps 600, 0x55,
259 1.4 chopps 1200, 0x66,
260 1.4 chopps 2400, 0x88,
261 1.4 chopps 4800, 0x99,
262 1.4 chopps 9600, 0xbb,
263 1.4 chopps 38400, 0xcc,
264 1.4 chopps -1, -1
265 1.4 chopps };
266 1.4 chopps #endif
267 1.4 chopps
268 1.4 chopps /*
269 1.4 chopps * MultiFaceCard III, II+ (not supported yet), and
270 1.4 chopps * SerialMaster 500+ (not supported yet)
271 1.4 chopps * baud rate tables for BRG set 2
272 1.4 chopps */
273 1.4 chopps
274 1.4 chopps struct speedtab mfcs3speedtab2[] = {
275 1.1 chopps 0, 0,
276 1.1 chopps 150, 0x00,
277 1.1 chopps 200, 0x11,
278 1.1 chopps 300, 0x33,
279 1.1 chopps 600, 0x44,
280 1.1 chopps 1200, 0x55,
281 1.1 chopps 2400, 0x66,
282 1.1 chopps 4800, 0x88,
283 1.1 chopps 9600, 0x99,
284 1.1 chopps 19200, 0xbb,
285 1.1 chopps 38400, 0xcc,
286 1.1 chopps -1, -1
287 1.1 chopps };
288 1.1 chopps
289 1.4 chopps /*
290 1.4 chopps * MultiFaceCard II, I, and SerialMaster 500
291 1.4 chopps * baud rate tables for BRG set 2
292 1.4 chopps */
293 1.4 chopps
294 1.4 chopps struct speedtab mfcs2speedtab2[] = {
295 1.1 chopps 0, 0,
296 1.1 chopps 75, 0x00,
297 1.1 chopps 100, 0x11,
298 1.1 chopps 150, 0x33,
299 1.1 chopps 300, 0x44,
300 1.1 chopps 600, 0x55,
301 1.1 chopps 1200, 0x66,
302 1.1 chopps 2400, 0x88,
303 1.1 chopps 4800, 0x99,
304 1.1 chopps 9600, 0xbb,
305 1.1 chopps 19200, 0xcc,
306 1.1 chopps -1, -1
307 1.1 chopps };
308 1.1 chopps
309 1.1 chopps /*
310 1.1 chopps * if we are an bsc/Alf Data MultFaceCard (I, II, and III)
311 1.1 chopps */
312 1.1 chopps int
313 1.10 thorpej mfcmatch(pdp, match, auxp)
314 1.1 chopps struct device *pdp;
315 1.10 thorpej void *match, *auxp;
316 1.1 chopps {
317 1.10 thorpej struct cfdata *cdp = match;
318 1.1 chopps struct zbus_args *zap;
319 1.1 chopps
320 1.1 chopps zap = auxp;
321 1.1 chopps if (zap->manid == 2092 &&
322 1.1 chopps (zap->prodid == 16 || zap->prodid == 17 || zap->prodid == 18))
323 1.2 chopps
324 1.1 chopps return(1);
325 1.1 chopps return(0);
326 1.1 chopps }
327 1.1 chopps
328 1.1 chopps void
329 1.1 chopps mfcattach(pdp, dp, auxp)
330 1.1 chopps struct device *pdp, *dp;
331 1.1 chopps void *auxp;
332 1.1 chopps {
333 1.1 chopps struct mfc_softc *scc;
334 1.1 chopps struct zbus_args *zap;
335 1.1 chopps struct mfc_args ma;
336 1.1 chopps int unit;
337 1.1 chopps struct mfc_regs *rp;
338 1.1 chopps
339 1.1 chopps zap = auxp;
340 1.2 chopps
341 1.1 chopps printf ("\n");
342 1.1 chopps
343 1.1 chopps scc = (struct mfc_softc *)dp;
344 1.1 chopps unit = scc->sc_dev.dv_unit;
345 1.1 chopps scc->sc_regs = rp = zap->va;
346 1.1 chopps if (zap->prodid == 18)
347 1.1 chopps scc->mfc_iii = 3;
348 1.1 chopps scc->clk_frq = scc->mfc_iii ? 230400 : 115200;
349 1.1 chopps
350 1.1 chopps rp->du_opcr = 0x00; /* configure output port? */
351 1.1 chopps rp->du_btrst = 0x0f; /* clear modem lines */
352 1.1 chopps rp->du_ivr = 0; /* IVR */
353 1.1 chopps rp->du_imr = 0; /* IMR */
354 1.1 chopps rp->du_acr = 0xe0; /* baud rate generate set 2 */
355 1.1 chopps rp->du_ctur = 0;
356 1.1 chopps rp->du_ctlr = 4;
357 1.1 chopps rp->du_csra = 0xcc; /* clock select = 38400 */
358 1.1 chopps rp->du_cra = 0x10; /* reset mode register ptr */
359 1.1 chopps rp->du_cra = 0x20;
360 1.1 chopps rp->du_cra = 0x30;
361 1.1 chopps rp->du_cra = 0x40;
362 1.1 chopps rp->du_mr1a = 0x93; /* MRA1 */
363 1.1 chopps rp->du_mr2a = 0x17; /* MRA2 */
364 1.1 chopps rp->du_csrb = 0xcc; /* clock select = 38400 */
365 1.1 chopps rp->du_crb = 0x10; /* reset mode register ptr */
366 1.1 chopps rp->du_crb = 0x20;
367 1.1 chopps rp->du_crb = 0x30;
368 1.1 chopps rp->du_crb = 0x40;
369 1.1 chopps rp->du_mr1b = 0x93; /* MRB1 */
370 1.1 chopps rp->du_mr2b = 0x17; /* MRB2 */
371 1.1 chopps rp->du_cra = 0x05; /* enable A Rx & Tx */
372 1.1 chopps rp->du_crb = 0x05; /* enable B Rx & Tx */
373 1.1 chopps
374 1.2 chopps scc->sc_isr.isr_intr = mfcintr;
375 1.2 chopps scc->sc_isr.isr_arg = scc;
376 1.2 chopps scc->sc_isr.isr_ipl = 6;
377 1.2 chopps add_isr(&scc->sc_isr);
378 1.1 chopps
379 1.1 chopps /* configure ports */
380 1.1 chopps bcopy(zap, &ma.zargs, sizeof(struct zbus_args));
381 1.1 chopps ma.subdev = "mfcs";
382 1.1 chopps ma.unit = unit * 2;
383 1.1 chopps config_found(dp, &ma, mfcprint);
384 1.1 chopps ma.unit = unit * 2 + 1;
385 1.1 chopps config_found(dp, &ma, mfcprint);
386 1.1 chopps ma.subdev = "mfcp";
387 1.1 chopps ma.unit = unit;
388 1.1 chopps config_found(dp, &ma, mfcprint);
389 1.1 chopps }
390 1.1 chopps
391 1.1 chopps /*
392 1.2 chopps *
393 1.1 chopps */
394 1.1 chopps int
395 1.10 thorpej mfcsmatch(pdp, match, auxp)
396 1.1 chopps struct device *pdp;
397 1.10 thorpej void *match, *auxp;
398 1.1 chopps {
399 1.10 thorpej struct cfdata *cdp = match;
400 1.1 chopps struct mfc_args *ma;
401 1.1 chopps
402 1.1 chopps ma = auxp;
403 1.1 chopps if (strcmp(ma->subdev, "mfcs") == 0)
404 1.1 chopps return (1);
405 1.1 chopps return (0);
406 1.1 chopps }
407 1.1 chopps
408 1.1 chopps void
409 1.1 chopps mfcsattach(pdp, dp, auxp)
410 1.1 chopps struct device *pdp, *dp;
411 1.1 chopps void *auxp;
412 1.1 chopps {
413 1.1 chopps int unit;
414 1.1 chopps struct mfcs_softc *sc;
415 1.1 chopps struct mfc_softc *scc;
416 1.1 chopps struct mfc_args *ma;
417 1.1 chopps struct mfc_regs *rp;
418 1.1 chopps
419 1.1 chopps sc = (struct mfcs_softc *) dp;
420 1.1 chopps scc = (struct mfc_softc *) pdp;
421 1.1 chopps ma = auxp;
422 1.1 chopps
423 1.1 chopps if (dp) {
424 1.1 chopps printf (": input fifo %d output fifo %d\n", SERIBUF_SIZE,
425 1.1 chopps SEROBUF_SIZE);
426 1.1 chopps alloc_sicallback();
427 1.1 chopps }
428 1.1 chopps
429 1.1 chopps unit = ma->unit;
430 1.1 chopps mfcs_active |= 1 << unit;
431 1.1 chopps sc->rptr = sc->wptr = sc->inbuf;
432 1.1 chopps sc->sc_mfc = scc;
433 1.1 chopps sc->sc_regs = rp = scc->sc_regs;
434 1.1 chopps sc->sc_duart = (struct duart_regs *) ((unit & 1) ? &rp->du_mr1b :
435 1.1 chopps &rp->du_mr1a);
436 1.1 chopps /*
437 1.1 chopps * should have only one vbl routine to handle all ports?
438 1.1 chopps */
439 1.9 jtc sc->vbl_node.function = (void (*) (void *)) mfcsmint;
440 1.9 jtc sc->vbl_node.data = (void *) unit;
441 1.9 jtc add_vbl_function(&sc->vbl_node, 1, (void *) unit);
442 1.1 chopps }
443 1.1 chopps
444 1.1 chopps /*
445 1.1 chopps * print diag if pnp is NULL else just extra
446 1.1 chopps */
447 1.1 chopps int
448 1.1 chopps mfcprint(auxp, pnp)
449 1.1 chopps void *auxp;
450 1.1 chopps char *pnp;
451 1.1 chopps {
452 1.1 chopps if (pnp == NULL)
453 1.1 chopps return(UNCONF);
454 1.1 chopps return(QUIET);
455 1.1 chopps }
456 1.1 chopps
457 1.1 chopps int
458 1.1 chopps mfcsopen(dev, flag, mode, p)
459 1.1 chopps dev_t dev;
460 1.1 chopps int flag, mode;
461 1.1 chopps struct proc *p;
462 1.1 chopps {
463 1.1 chopps struct tty *tp;
464 1.6 chopps struct mfcs_softc *sc;
465 1.1 chopps int unit, error, s;
466 1.1 chopps
467 1.1 chopps error = 0;
468 1.1 chopps unit = dev & 0x1f;
469 1.1 chopps
470 1.10 thorpej if (unit >= mfcs_cd.cd_ndevs || (mfcs_active & (1 << unit)) == 0)
471 1.1 chopps return (ENXIO);
472 1.10 thorpej sc = mfcs_cd.cd_devs[unit];
473 1.1 chopps
474 1.1 chopps s = spltty();
475 1.1 chopps
476 1.6 chopps if (sc->sc_tty)
477 1.6 chopps tp = sc->sc_tty;
478 1.1 chopps else
479 1.6 chopps tp = sc->sc_tty = ttymalloc();
480 1.1 chopps
481 1.1 chopps tp->t_oproc = (void (*) (struct tty *)) mfcsstart;
482 1.1 chopps tp->t_param = mfcsparam;
483 1.1 chopps tp->t_dev = dev;
484 1.1 chopps tp->t_hwiflow = mfcshwiflow;
485 1.1 chopps
486 1.1 chopps if ((tp->t_state & TS_ISOPEN) == 0) {
487 1.1 chopps tp->t_state |= TS_WOPEN;
488 1.1 chopps ttychars(tp);
489 1.1 chopps if (tp->t_ispeed == 0) {
490 1.1 chopps /*
491 1.1 chopps * only when cleared do we reset to defaults.
492 1.1 chopps */
493 1.1 chopps tp->t_iflag = TTYDEF_IFLAG;
494 1.1 chopps tp->t_oflag = TTYDEF_OFLAG;
495 1.1 chopps tp->t_cflag = TTYDEF_CFLAG;
496 1.1 chopps tp->t_lflag = TTYDEF_LFLAG;
497 1.1 chopps tp->t_ispeed = tp->t_ospeed = mfcsdefaultrate;
498 1.1 chopps }
499 1.1 chopps /*
500 1.1 chopps * do these all the time
501 1.1 chopps */
502 1.9 jtc if (sc->swflags & TIOCFLAG_CLOCAL)
503 1.1 chopps tp->t_cflag |= CLOCAL;
504 1.9 jtc if (sc->swflags & TIOCFLAG_CRTSCTS)
505 1.1 chopps tp->t_cflag |= CRTSCTS;
506 1.9 jtc if (sc->swflags & TIOCFLAG_MDMBUF)
507 1.1 chopps tp->t_cflag |= MDMBUF;
508 1.1 chopps mfcsparam(tp, &tp->t_termios);
509 1.1 chopps ttsetwater(tp);
510 1.2 chopps
511 1.1 chopps (void)mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
512 1.2 chopps if ((SWFLAGS(dev) & TIOCFLAG_SOFTCAR) ||
513 1.1 chopps (mfcsmctl(dev, 0, DMGET) & TIOCM_CD))
514 1.1 chopps tp->t_state |= TS_CARR_ON;
515 1.1 chopps else
516 1.1 chopps tp->t_state &= ~TS_CARR_ON;
517 1.1 chopps } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
518 1.1 chopps splx(s);
519 1.1 chopps return(EBUSY);
520 1.1 chopps }
521 1.1 chopps
522 1.1 chopps /*
523 1.1 chopps * if NONBLOCK requested, ignore carrier
524 1.1 chopps */
525 1.1 chopps if (flag & O_NONBLOCK)
526 1.1 chopps goto done;
527 1.1 chopps
528 1.1 chopps /*
529 1.1 chopps * block waiting for carrier
530 1.1 chopps */
531 1.1 chopps while ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
532 1.1 chopps tp->t_state |= TS_WOPEN;
533 1.2 chopps error = ttysleep(tp, (caddr_t)&tp->t_rawq,
534 1.1 chopps TTIPRI | PCATCH, ttopen, 0);
535 1.1 chopps if (error) {
536 1.1 chopps splx(s);
537 1.1 chopps return(error);
538 1.1 chopps }
539 1.1 chopps }
540 1.1 chopps done:
541 1.1 chopps /* This is a way to handle lost XON characters */
542 1.1 chopps if ((flag & O_TRUNC) && (tp->t_state & TS_TTSTOP)) {
543 1.1 chopps tp->t_state &= ~TS_TTSTOP;
544 1.1 chopps ttstart (tp);
545 1.1 chopps }
546 1.1 chopps
547 1.1 chopps splx(s);
548 1.1 chopps /*
549 1.1 chopps * Reset the tty pointer, as there could have been a dialout
550 1.1 chopps * use of the tty with a dialin open waiting.
551 1.1 chopps */
552 1.1 chopps tp->t_dev = dev;
553 1.1 chopps return((*linesw[tp->t_line].l_open)(dev, tp));
554 1.1 chopps }
555 1.1 chopps
556 1.1 chopps /*ARGSUSED*/
557 1.1 chopps int
558 1.1 chopps mfcsclose(dev, flag, mode, p)
559 1.1 chopps dev_t dev;
560 1.1 chopps int flag, mode;
561 1.1 chopps struct proc *p;
562 1.1 chopps {
563 1.1 chopps struct tty *tp;
564 1.1 chopps int unit;
565 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
566 1.1 chopps struct mfc_softc *scc= sc->sc_mfc;
567 1.1 chopps
568 1.1 chopps unit = dev & 31;
569 1.1 chopps
570 1.6 chopps tp = sc->sc_tty;
571 1.1 chopps (*linesw[tp->t_line].l_close)(tp, flag);
572 1.1 chopps sc->sc_duart->ch_cr = 0x70; /* stop break */
573 1.1 chopps
574 1.1 chopps scc->imask &= ~(0x7 << ((unit & 1) * 4));
575 1.1 chopps scc->sc_regs->du_imr = scc->imask;
576 1.1 chopps if (sc->flags & CT_USED) {
577 1.1 chopps --scc->ct_usecnt;
578 1.1 chopps sc->flags &= ~CT_USED;
579 1.1 chopps }
580 1.1 chopps
581 1.1 chopps /*
582 1.1 chopps * If the device is closed, it's close, no matter whether we deal with
583 1.1 chopps * modem control signals nor not.
584 1.1 chopps */
585 1.1 chopps #if 0
586 1.1 chopps if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN ||
587 1.1 chopps (tp->t_state & TS_ISOPEN) == 0)
588 1.1 chopps #endif
589 1.1 chopps (void) mfcsmctl(dev, 0, DMSET);
590 1.1 chopps ttyclose(tp);
591 1.1 chopps #if not_yet
592 1.1 chopps if (tp != &mfcs_cons) {
593 1.9 jtc remove_vbl_function(&sc->vbl_node);
594 1.1 chopps ttyfree(tp);
595 1.6 chopps sc->sc_tty = (struct tty *) NULL;
596 1.1 chopps }
597 1.1 chopps #endif
598 1.1 chopps return (0);
599 1.1 chopps }
600 1.1 chopps
601 1.1 chopps int
602 1.1 chopps mfcsread(dev, uio, flag)
603 1.1 chopps dev_t dev;
604 1.1 chopps struct uio *uio;
605 1.1 chopps int flag;
606 1.1 chopps {
607 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
608 1.6 chopps struct tty *tp = sc->sc_tty;
609 1.6 chopps if (tp == NULL)
610 1.1 chopps return(ENXIO);
611 1.1 chopps return((*linesw[tp->t_line].l_read)(tp, uio, flag));
612 1.1 chopps }
613 1.1 chopps
614 1.1 chopps int
615 1.1 chopps mfcswrite(dev, uio, flag)
616 1.1 chopps dev_t dev;
617 1.1 chopps struct uio *uio;
618 1.1 chopps int flag;
619 1.1 chopps {
620 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
621 1.6 chopps struct tty *tp = sc->sc_tty;
622 1.1 chopps
623 1.6 chopps if (tp == NULL)
624 1.1 chopps return(ENXIO);
625 1.1 chopps return((*linesw[tp->t_line].l_write)(tp, uio, flag));
626 1.1 chopps }
627 1.5 chopps
628 1.5 chopps struct tty *
629 1.5 chopps mfcstty(dev)
630 1.5 chopps dev_t dev;
631 1.5 chopps {
632 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
633 1.6 chopps
634 1.6 chopps return (sc->sc_tty);
635 1.5 chopps }
636 1.5 chopps
637 1.1 chopps int
638 1.1 chopps mfcsioctl(dev, cmd, data, flag, p)
639 1.1 chopps dev_t dev;
640 1.1 chopps caddr_t data;
641 1.1 chopps struct proc *p;
642 1.1 chopps {
643 1.1 chopps register struct tty *tp;
644 1.1 chopps register int unit = dev & 31;
645 1.1 chopps register int error;
646 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
647 1.1 chopps
648 1.6 chopps tp = sc->sc_tty;
649 1.1 chopps if (!tp)
650 1.1 chopps return ENXIO;
651 1.1 chopps
652 1.1 chopps error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
653 1.1 chopps if (error >= 0)
654 1.1 chopps return(error);
655 1.1 chopps
656 1.1 chopps error = ttioctl(tp, cmd, data, flag, p);
657 1.1 chopps if (error >= 0)
658 1.1 chopps return(error);
659 1.1 chopps
660 1.1 chopps switch (cmd) {
661 1.1 chopps case TIOCSBRK:
662 1.1 chopps sc->sc_duart->ch_cr = 0x60; /* start break */
663 1.1 chopps break;
664 1.1 chopps
665 1.1 chopps case TIOCCBRK:
666 1.1 chopps sc->sc_duart->ch_cr = 0x70; /* stop break */
667 1.1 chopps break;
668 1.1 chopps
669 1.1 chopps case TIOCSDTR:
670 1.1 chopps (void) mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
671 1.1 chopps break;
672 1.1 chopps
673 1.1 chopps case TIOCCDTR:
674 1.1 chopps (void) mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
675 1.1 chopps break;
676 1.1 chopps
677 1.1 chopps case TIOCMSET:
678 1.1 chopps (void) mfcsmctl(dev, *(int *) data, DMSET);
679 1.1 chopps break;
680 1.1 chopps
681 1.1 chopps case TIOCMBIS:
682 1.1 chopps (void) mfcsmctl(dev, *(int *) data, DMBIS);
683 1.1 chopps break;
684 1.1 chopps
685 1.1 chopps case TIOCMBIC:
686 1.1 chopps (void) mfcsmctl(dev, *(int *) data, DMBIC);
687 1.1 chopps break;
688 1.1 chopps
689 1.1 chopps case TIOCMGET:
690 1.1 chopps *(int *)data = mfcsmctl(dev, 0, DMGET);
691 1.1 chopps break;
692 1.1 chopps case TIOCGFLAGS:
693 1.1 chopps *(int *)data = SWFLAGS(dev);
694 1.1 chopps break;
695 1.1 chopps case TIOCSFLAGS:
696 1.2 chopps error = suser(p->p_ucred, &p->p_acflag);
697 1.1 chopps if (error != 0)
698 1.2 chopps return(EPERM);
699 1.1 chopps
700 1.9 jtc sc->swflags = *(int *)data;
701 1.9 jtc sc->swflags &= /* only allow valid flags */
702 1.1 chopps (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
703 1.4 chopps /* XXXX need to change duart parameters? */
704 1.1 chopps break;
705 1.1 chopps default:
706 1.1 chopps return(ENOTTY);
707 1.1 chopps }
708 1.1 chopps
709 1.1 chopps return(0);
710 1.1 chopps }
711 1.1 chopps
712 1.1 chopps int
713 1.1 chopps mfcsparam(tp, t)
714 1.1 chopps struct tty *tp;
715 1.1 chopps struct termios *t;
716 1.1 chopps {
717 1.1 chopps int cfcr, cflag, unit, ospeed;
718 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[tp->t_dev & 31];
719 1.1 chopps struct mfc_softc *scc= sc->sc_mfc;
720 1.2 chopps
721 1.1 chopps cflag = t->c_cflag;
722 1.1 chopps unit = tp->t_dev & 31;
723 1.1 chopps if (sc->flags & CT_USED) {
724 1.1 chopps --scc->ct_usecnt;
725 1.1 chopps sc->flags &= ~CT_USED;
726 1.1 chopps }
727 1.4 chopps ospeed = ttspeedtab(t->c_ospeed, scc->mfc_iii ? mfcs3speedtab2 :
728 1.4 chopps mfcs2speedtab2);
729 1.1 chopps
730 1.1 chopps /*
731 1.1 chopps * If Baud Rate Generator can't generate requested speed,
732 1.1 chopps * try to use the counter/timer.
733 1.1 chopps */
734 1.1 chopps if (ospeed < 0 && (scc->clk_frq % t->c_ospeed) == 0) {
735 1.1 chopps ospeed = scc->clk_frq / t->c_ospeed; /* divisor */
736 1.1 chopps if (scc->ct_usecnt > 0 && scc->ct_val != ospeed)
737 1.1 chopps ospeed = -1;
738 1.1 chopps else {
739 1.1 chopps scc->sc_regs->du_ctur = ospeed >> 8;
740 1.1 chopps scc->sc_regs->du_ctlr = ospeed;
741 1.1 chopps scc->ct_val = ospeed;
742 1.1 chopps ++scc->ct_usecnt;
743 1.1 chopps sc->flags |= CT_USED;
744 1.1 chopps ospeed = 0xdd;
745 1.1 chopps }
746 1.1 chopps }
747 1.1 chopps /* XXXX 68681 duart could handle split speeds */
748 1.1 chopps if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
749 1.1 chopps return(EINVAL);
750 1.1 chopps
751 1.4 chopps /* XXXX handle parity, character size, stop bits, flow control */
752 1.4 chopps
753 1.2 chopps /*
754 1.1 chopps * copy to tty
755 1.1 chopps */
756 1.1 chopps tp->t_ispeed = t->c_ispeed;
757 1.1 chopps tp->t_ospeed = t->c_ospeed;
758 1.1 chopps tp->t_cflag = cflag;
759 1.1 chopps
760 1.1 chopps /*
761 1.1 chopps * enable interrupts
762 1.1 chopps */
763 1.1 chopps scc->imask |= (0x2 << ((unit & 1) * 4)) | 0x80;
764 1.1 chopps scc->sc_regs->du_imr = scc->imask;
765 1.1 chopps #if defined(DEBUG) && 0
766 1.1 chopps printf("mfcsparam: speed %d => %x ct %d imask %x cflag %x\n",
767 1.1 chopps t->c_ospeed, ospeed, scc->ct_val, scc->imask, cflag);
768 1.1 chopps #endif
769 1.1 chopps if (ospeed == 0)
770 1.1 chopps (void)mfcsmctl(tp->t_dev, 0, DMSET); /* hang up line */
771 1.1 chopps else {
772 1.2 chopps /*
773 1.1 chopps * (re)enable DTR
774 1.1 chopps * and set baud rate. (8 bit mode)
775 1.1 chopps */
776 1.1 chopps (void)mfcsmctl(tp->t_dev, TIOCM_DTR | TIOCM_RTS, DMSET);
777 1.1 chopps sc->sc_duart->ch_csr = ospeed;
778 1.1 chopps }
779 1.1 chopps return(0);
780 1.1 chopps }
781 1.1 chopps
782 1.1 chopps int mfcshwiflow(tp, flag)
783 1.1 chopps struct tty *tp;
784 1.1 chopps int flag;
785 1.1 chopps {
786 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[tp->t_dev & 31];
787 1.1 chopps int unit = tp->t_dev & 1;
788 1.1 chopps
789 1.1 chopps if (flag)
790 1.1 chopps sc->sc_regs->du_btrst = 1 << unit;
791 1.1 chopps else
792 1.1 chopps sc->sc_regs->du_btst = 1 << unit;
793 1.1 chopps return 1;
794 1.1 chopps }
795 1.1 chopps
796 1.1 chopps int
797 1.1 chopps mfcsstart(tp)
798 1.1 chopps struct tty *tp;
799 1.1 chopps {
800 1.1 chopps int cc, s, unit;
801 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[tp->t_dev & 31];
802 1.1 chopps struct mfc_softc *scc= sc->sc_mfc;
803 1.1 chopps
804 1.1 chopps if ((tp->t_state & TS_ISOPEN) == 0)
805 1.1 chopps return;
806 1.1 chopps
807 1.1 chopps unit = tp->t_dev & 1;
808 1.1 chopps
809 1.2 chopps s = splser();
810 1.1 chopps if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))
811 1.1 chopps goto out;
812 1.1 chopps
813 1.1 chopps cc = tp->t_outq.c_cc;
814 1.1 chopps if (cc <= tp->t_lowat) {
815 1.1 chopps if (tp->t_state & TS_ASLEEP) {
816 1.1 chopps tp->t_state &= ~TS_ASLEEP;
817 1.1 chopps wakeup((caddr_t) & tp->t_outq);
818 1.1 chopps }
819 1.1 chopps selwakeup(&tp->t_wsel);
820 1.1 chopps }
821 1.1 chopps if (cc == 0 || (tp->t_state & TS_BUSY))
822 1.1 chopps goto out;
823 1.1 chopps
824 1.1 chopps /*
825 1.1 chopps * We only do bulk transfers if using CTSRTS flow control, not for
826 1.1 chopps * (probably sloooow) ixon/ixoff devices.
827 1.1 chopps */
828 1.1 chopps if ((tp->t_cflag & CRTSCTS) == 0)
829 1.1 chopps cc = 1;
830 1.1 chopps
831 1.1 chopps /*
832 1.1 chopps * Limit the amount of output we do in one burst
833 1.1 chopps * to prevent hogging the CPU.
834 1.1 chopps */
835 1.1 chopps if (cc > SEROBUF_SIZE)
836 1.1 chopps cc = SEROBUF_SIZE;
837 1.1 chopps cc = q_to_b(&tp->t_outq, sc->outbuf, cc);
838 1.1 chopps if (cc > 0) {
839 1.1 chopps tp->t_state |= TS_BUSY;
840 1.1 chopps
841 1.1 chopps sc->ptr = sc->outbuf;
842 1.1 chopps sc->end = sc->outbuf + cc;
843 1.1 chopps
844 1.1 chopps /*
845 1.1 chopps * Get first character out, then have TBE-interrupts blow out
846 1.1 chopps * further characters, until buffer is empty, and TS_BUSY gets
847 1.2 chopps * cleared.
848 1.1 chopps */
849 1.1 chopps sc->sc_duart->ch_tb = *sc->ptr++;
850 1.1 chopps scc->imask |= 1 << (unit * 4);
851 1.1 chopps sc->sc_regs->du_imr = scc->imask;
852 1.1 chopps }
853 1.1 chopps out:
854 1.1 chopps splx(s);
855 1.1 chopps }
856 1.1 chopps
857 1.1 chopps /*
858 1.1 chopps * Stop output on a line.
859 1.1 chopps */
860 1.1 chopps /*ARGSUSED*/
861 1.1 chopps int
862 1.1 chopps mfcsstop(tp, flag)
863 1.1 chopps struct tty *tp;
864 1.1 chopps {
865 1.1 chopps int s;
866 1.1 chopps
867 1.2 chopps s = splser();
868 1.1 chopps if (tp->t_state & TS_BUSY) {
869 1.1 chopps if ((tp->t_state & TS_TTSTOP) == 0)
870 1.1 chopps tp->t_state |= TS_FLUSH;
871 1.1 chopps }
872 1.1 chopps splx(s);
873 1.1 chopps }
874 1.1 chopps
875 1.1 chopps int
876 1.1 chopps mfcsmctl(dev, bits, how)
877 1.1 chopps dev_t dev;
878 1.1 chopps int bits, how;
879 1.1 chopps {
880 1.1 chopps int unit, s;
881 1.1 chopps u_char ub;
882 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
883 1.1 chopps
884 1.1 chopps unit = dev & 1;
885 1.1 chopps
886 1.1 chopps /*
887 1.1 chopps * convert TIOCM* mask into CIA mask
888 1.1 chopps * which is active low
889 1.1 chopps */
890 1.1 chopps if (how != DMGET) {
891 1.1 chopps ub = 0;
892 1.1 chopps /*
893 1.1 chopps * need to save current state of DTR & RTS ?
894 1.1 chopps */
895 1.1 chopps if (bits & TIOCM_DTR)
896 1.1 chopps ub |= 0x04 << unit;
897 1.1 chopps if (bits & TIOCM_RTS)
898 1.1 chopps ub |= 0x01 << unit;
899 1.1 chopps }
900 1.2 chopps s = splser();
901 1.1 chopps switch (how) {
902 1.1 chopps case DMSET:
903 1.1 chopps sc->sc_regs->du_btst = ub;
904 1.4 chopps sc->sc_regs->du_btrst = ub ^ (0x05 << unit);
905 1.1 chopps break;
906 1.1 chopps
907 1.1 chopps case DMBIC:
908 1.1 chopps sc->sc_regs->du_btrst = ub;
909 1.1 chopps ub = ~sc->sc_regs->du_ip;
910 1.1 chopps break;
911 1.1 chopps
912 1.1 chopps case DMBIS:
913 1.1 chopps sc->sc_regs->du_btst = ub;
914 1.1 chopps ub = ~sc->sc_regs->du_ip;
915 1.1 chopps break;
916 1.1 chopps
917 1.1 chopps case DMGET:
918 1.1 chopps ub = ~sc->sc_regs->du_ip;
919 1.1 chopps break;
920 1.1 chopps }
921 1.1 chopps (void)splx(s);
922 1.1 chopps
923 1.4 chopps /* XXXX should keep DTR & RTS states in softc? */
924 1.1 chopps bits = TIOCM_DTR | TIOCM_RTS;
925 1.1 chopps if (ub & (1 << unit))
926 1.1 chopps bits |= TIOCM_CTS;
927 1.1 chopps if (ub & (4 << unit))
928 1.1 chopps bits |= TIOCM_DSR;
929 1.1 chopps if (ub & (0x10 << unit))
930 1.1 chopps bits |= TIOCM_CD;
931 1.4 chopps /* XXXX RI is not supported on all boards */
932 1.1 chopps if (sc->sc_regs->pad26 & (1 << unit))
933 1.1 chopps bits |= TIOCM_RI;
934 1.1 chopps
935 1.1 chopps return(bits);
936 1.1 chopps }
937 1.1 chopps
938 1.1 chopps /*
939 1.2 chopps * Level 6 interrupt processing for the MultiFaceCard 68681 DUART
940 1.1 chopps */
941 1.1 chopps
942 1.1 chopps int
943 1.2 chopps mfcintr (scc)
944 1.2 chopps struct mfc_softc *scc;
945 1.1 chopps {
946 1.1 chopps struct mfcs_softc *sc;
947 1.1 chopps struct mfc_regs *regs;
948 1.2 chopps struct tty *tp;
949 1.2 chopps int istat, unit;
950 1.2 chopps u_short c;
951 1.1 chopps
952 1.2 chopps regs = scc->sc_regs;
953 1.2 chopps istat = regs->du_isr & scc->imask;
954 1.2 chopps if (istat == 0)
955 1.2 chopps return (0);
956 1.2 chopps unit = scc->sc_dev.dv_unit * 2;
957 1.2 chopps if (istat & 0x02) { /* channel A receive interrupt */
958 1.10 thorpej sc = mfcs_cd.cd_devs[unit];
959 1.2 chopps while (1) {
960 1.2 chopps c = regs->du_sra << 8;
961 1.2 chopps if ((c & 0x0100) == 0)
962 1.2 chopps break;
963 1.2 chopps c |= regs->du_rba;
964 1.2 chopps if (sc->incnt == SERIBUF_SIZE)
965 1.2 chopps ++sc->ovfl;
966 1.2 chopps else {
967 1.2 chopps *sc->wptr++ = c;
968 1.2 chopps if (sc->wptr == sc->inbuf + SERIBUF_SIZE)
969 1.2 chopps sc->wptr = sc->inbuf;
970 1.2 chopps ++sc->incnt;
971 1.2 chopps if (sc->incnt > SERIBUF_SIZE - 16)
972 1.2 chopps regs->du_btrst = 1;
973 1.1 chopps }
974 1.2 chopps if (c & 0x1000)
975 1.2 chopps regs->du_cra = 0x40;
976 1.1 chopps }
977 1.2 chopps }
978 1.2 chopps if (istat & 0x20) { /* channel B receive interrupt */
979 1.10 thorpej sc = mfcs_cd.cd_devs[unit + 1];
980 1.2 chopps while (1) {
981 1.2 chopps c = regs->du_srb << 8;
982 1.2 chopps if ((c & 0x0100) == 0)
983 1.2 chopps break;
984 1.2 chopps c |= regs->du_rbb;
985 1.2 chopps if (sc->incnt == SERIBUF_SIZE)
986 1.2 chopps ++sc->ovfl;
987 1.2 chopps else {
988 1.2 chopps *sc->wptr++ = c;
989 1.2 chopps if (sc->wptr == sc->inbuf + SERIBUF_SIZE)
990 1.2 chopps sc->wptr = sc->inbuf;
991 1.2 chopps ++sc->incnt;
992 1.2 chopps if (sc->incnt > SERIBUF_SIZE - 16)
993 1.2 chopps regs->du_btrst = 2;
994 1.1 chopps }
995 1.2 chopps if (c & 0x1000)
996 1.2 chopps regs->du_crb = 0x40;
997 1.1 chopps }
998 1.2 chopps }
999 1.2 chopps if (istat & 0x01) { /* channel A transmit interrupt */
1000 1.10 thorpej sc = mfcs_cd.cd_devs[unit];
1001 1.6 chopps tp = sc->sc_tty;
1002 1.2 chopps if (sc->ptr == sc->end) {
1003 1.2 chopps tp->t_state &= ~(TS_BUSY | TS_FLUSH);
1004 1.2 chopps scc->imask &= ~0x01;
1005 1.2 chopps regs->du_imr = scc->imask;
1006 1.2 chopps add_sicallback (tp->t_line ?
1007 1.8 chopps (sifunc_t)linesw[tp->t_line].l_start
1008 1.8 chopps : (sifunc_t)mfcsstart, tp, NULL);
1009 1.2 chopps
1010 1.1 chopps }
1011 1.2 chopps else
1012 1.2 chopps regs->du_tba = *sc->ptr++;
1013 1.2 chopps }
1014 1.2 chopps if (istat & 0x10) { /* channel B transmit interrupt */
1015 1.10 thorpej sc = mfcs_cd.cd_devs[unit + 1];
1016 1.6 chopps tp = sc->sc_tty;
1017 1.2 chopps if (sc->ptr == sc->end) {
1018 1.2 chopps tp->t_state &= ~(TS_BUSY | TS_FLUSH);
1019 1.2 chopps scc->imask &= ~0x10;
1020 1.2 chopps regs->du_imr = scc->imask;
1021 1.2 chopps add_sicallback (tp->t_line ?
1022 1.8 chopps (sifunc_t)linesw[tp->t_line].l_start
1023 1.8 chopps : (sifunc_t)mfcsstart, tp, NULL);
1024 1.1 chopps }
1025 1.2 chopps else
1026 1.2 chopps regs->du_tbb = *sc->ptr++;
1027 1.2 chopps }
1028 1.2 chopps if (istat & 0x80) { /* input port change interrupt */
1029 1.2 chopps c = regs->du_ipcr;
1030 1.2 chopps printf ("%s: ipcr %02x", scc->sc_dev.dv_xname, c);
1031 1.1 chopps }
1032 1.2 chopps return(1);
1033 1.1 chopps }
1034 1.1 chopps
1035 1.1 chopps int
1036 1.1 chopps mfcsxintr(unit)
1037 1.1 chopps int unit;
1038 1.1 chopps {
1039 1.1 chopps int s1, s2, ovfl;
1040 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[unit];
1041 1.6 chopps struct tty *tp = sc->sc_tty;
1042 1.1 chopps
1043 1.1 chopps /*
1044 1.1 chopps * Make sure we're not interrupted by another
1045 1.1 chopps * vbl, but allow level6 ints
1046 1.1 chopps */
1047 1.1 chopps s1 = spltty();
1048 1.1 chopps
1049 1.1 chopps /*
1050 1.1 chopps * pass along any acumulated information
1051 1.1 chopps * while input is not blocked
1052 1.1 chopps */
1053 1.1 chopps while (sc->incnt && (tp->t_state & TS_TBLOCK) == 0) {
1054 1.2 chopps /*
1055 1.1 chopps * no collision with ser_fastint()
1056 1.1 chopps */
1057 1.1 chopps mfcseint(unit, *sc->rptr++);
1058 1.1 chopps
1059 1.1 chopps ovfl = 0;
1060 1.1 chopps /* lock against mfcs_fastint() */
1061 1.2 chopps s2 = splser();
1062 1.1 chopps --sc->incnt;
1063 1.1 chopps if (sc->rptr == sc->inbuf + SERIBUF_SIZE)
1064 1.1 chopps sc->rptr = sc->inbuf;
1065 1.1 chopps if (sc->ovfl != 0) {
1066 1.1 chopps ovfl = sc->ovfl;
1067 1.1 chopps sc->ovfl = 0;
1068 1.1 chopps }
1069 1.1 chopps splx(s2);
1070 1.1 chopps if (ovfl != 0)
1071 1.1 chopps log(LOG_WARNING, "%s: %d buffer overflow!\n",
1072 1.1 chopps sc->sc_dev.dv_xname, ovfl);
1073 1.1 chopps }
1074 1.1 chopps if (sc->incnt == 0 && (tp->t_state & TS_TBLOCK) == 0) {
1075 1.4 chopps sc->sc_regs->du_btst = 1 << unit; /* XXXX */
1076 1.1 chopps }
1077 1.1 chopps splx(s1);
1078 1.1 chopps }
1079 1.1 chopps
1080 1.1 chopps int
1081 1.1 chopps mfcseint(unit, stat)
1082 1.1 chopps int unit, stat;
1083 1.1 chopps {
1084 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[unit];
1085 1.1 chopps struct tty *tp;
1086 1.1 chopps u_char ch;
1087 1.1 chopps int c;
1088 1.1 chopps
1089 1.6 chopps tp = sc->sc_tty;
1090 1.1 chopps ch = stat & 0xff;
1091 1.1 chopps c = ch;
1092 1.1 chopps
1093 1.1 chopps if ((tp->t_state & TS_ISOPEN) == 0) {
1094 1.1 chopps #ifdef KGDB
1095 1.1 chopps /* we don't care about parity errors */
1096 1.1 chopps if (kgdb_dev == makedev(sermajor, unit) && c == FRAME_END)
1097 1.1 chopps kgdb_connect(0); /* trap into kgdb */
1098 1.1 chopps #endif
1099 1.1 chopps return;
1100 1.1 chopps }
1101 1.1 chopps
1102 1.1 chopps /*
1103 1.1 chopps * Check for break and (if enabled) parity error.
1104 1.1 chopps */
1105 1.1 chopps if (stat & 0xc000)
1106 1.1 chopps c |= TTY_FE;
1107 1.1 chopps else if (stat & 0x2000)
1108 1.1 chopps c |= TTY_PE;
1109 1.1 chopps
1110 1.1 chopps if (stat & 0x1000)
1111 1.2 chopps log(LOG_WARNING, "%s: fifo overflow\n",
1112 1.10 thorpej ((struct mfcs_softc *)mfcs_cd.cd_devs[unit])->sc_dev.dv_xname);
1113 1.1 chopps
1114 1.1 chopps (*linesw[tp->t_line].l_rint)(c, tp);
1115 1.1 chopps }
1116 1.1 chopps
1117 1.1 chopps /*
1118 1.1 chopps * This interrupt is periodically invoked in the vertical blank
1119 1.1 chopps * interrupt. It's used to keep track of the modem control lines
1120 1.1 chopps * and (new with the fast_int code) to move accumulated data
1121 1.1 chopps * up into the tty layer.
1122 1.1 chopps */
1123 1.1 chopps void
1124 1.1 chopps mfcsmint(unit)
1125 1.1 chopps int unit;
1126 1.1 chopps {
1127 1.1 chopps struct tty *tp;
1128 1.10 thorpej struct mfcs_softc *sc = mfcs_cd.cd_devs[unit];
1129 1.1 chopps u_char stat, last, istat;
1130 1.1 chopps
1131 1.6 chopps tp = sc->sc_tty;
1132 1.1 chopps if (!tp)
1133 1.1 chopps return;
1134 1.1 chopps
1135 1.1 chopps if ((tp->t_state & (TS_ISOPEN | TS_WOPEN)) == 0) {
1136 1.1 chopps sc->rptr = sc->wptr = sc->inbuf;
1137 1.1 chopps sc->incnt = 0;
1138 1.1 chopps return;
1139 1.1 chopps }
1140 1.1 chopps /*
1141 1.1 chopps * empty buffer
1142 1.1 chopps */
1143 1.1 chopps mfcsxintr(unit);
1144 1.1 chopps
1145 1.1 chopps stat = ~sc->sc_regs->du_ip;
1146 1.1 chopps last = sc->sc_mfc->last_ip;
1147 1.1 chopps sc->sc_mfc->last_ip = stat;
1148 1.1 chopps
1149 1.1 chopps /*
1150 1.1 chopps * check whether any interesting signal changed state
1151 1.1 chopps */
1152 1.1 chopps istat = stat ^ last;
1153 1.1 chopps
1154 1.1 chopps if ((istat & (0x10 << (unit & 1))) && /* CD changed */
1155 1.1 chopps (SWFLAGS(tp->t_dev) & TIOCFLAG_SOFTCAR) == 0) {
1156 1.1 chopps if (stat & (0x10 << (unit & 1)))
1157 1.1 chopps (*linesw[tp->t_line].l_modem)(tp, 1);
1158 1.1 chopps else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
1159 1.1 chopps sc->sc_regs->du_btrst = 0x0a << (unit & 1);
1160 1.1 chopps }
1161 1.1 chopps }
1162 1.1 chopps }
1163