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