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