Annotation of sys/arch/mvme88k/dev/cl.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cl.c,v 1.52 2006/05/08 14:36:10 miod Exp $ */
2:
3: /*
4: * Copyright (c) 1995 Dale Rahn. All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: /* DMA mode still does not work!!! */
28:
29: #include <sys/param.h>
30: #include <sys/ioctl.h>
31: #include <sys/proc.h>
32: #include <sys/tty.h>
33: #include <sys/uio.h>
34: #include <sys/systm.h>
35: #include <sys/time.h>
36: #include <sys/device.h>
37: #include <sys/syslog.h>
38:
39: #include <machine/autoconf.h>
40: #include <machine/conf.h>
41: #include <machine/cpu.h>
42: #include <machine/psl.h>
43:
44: #include <dev/cons.h>
45:
46: #include <mvme88k/dev/clreg.h>
47: #include <mvme88k/dev/pcctworeg.h>
48: #include <mvme88k/dev/pcctwovar.h>
49:
50: #ifdef DDB
51: #include <ddb/db_var.h>
52: #endif
53:
54: #define splcl() spltty()
55:
56: /* min timeout 0xa, what is a good value */
57: #define CL_TIMEOUT 0x10
58: #define CL_FIFO_MAX 0x10
59: #define CL_FIFO_CNT 0xc
60: #define CL_RX_TIMEOUT 0x10
61:
62: #define CL_RXDMAINT 0x82
63: #define CL_TXDMAINT 0x42
64: #define CL_TXMASK 0x47
65: #define CL_RXMASK 0x87
66: #define CL_TXINTR 0x02
67: #define CL_RXINTR 0x02
68:
69: struct cl_cons {
70: bus_space_tag_t cl_iot;
71: bus_space_handle_t cl_ioh;
72: volatile u_int8_t *cl_rxiack;
73: u_int8_t channel;
74: } cl_cons;
75:
76: struct cl_info {
77: struct tty *tty;
78: u_char cl_swflags;
79: u_char cl_softchar;
80: u_char cl_consio;
81: u_char cl_speed;
82: u_char cl_parstop; /* parity, stop bits. */
83: u_char cl_rxmode;
84: u_char cl_txmode;
85: u_char cl_clen;
86: u_char cl_parity;
87: #if 0
88: u_char transmitting;
89: #endif
90: u_long txcnt;
91: u_long rxcnt;
92:
93: void *rx[2];
94: void *rxp[2];
95: void *tx[2];
96: void *txp[2];
97: };
98: #define CLCD_PORTS_PER_CHIP 4
99: #define CL_BUFSIZE 256
100:
101: #ifndef DO_MALLOC
102: /* four (4) buffers per port */
103: char cl_dmabuf[CLCD_PORTS_PER_CHIP * CL_BUFSIZE * 4];
104: char cl_dmabuf1[CLCD_PORTS_PER_CHIP * CL_BUFSIZE * 4];
105: #endif
106:
107: struct clsoftc {
108: struct device sc_dev;
109: bus_space_tag_t sc_iot;
110: bus_space_handle_t sc_ioh;
111: time_t sc_fotime; /* time of last fifo overrun */
112: struct cl_info sc_cl[CLCD_PORTS_PER_CHIP];
113: struct intrhand sc_ih_e;
114: struct intrhand sc_ih_m;
115: struct intrhand sc_ih_t;
116: struct intrhand sc_ih_r;
117: char sc_errintrname[16 + 4];
118: char sc_mxintrname[16 + 3];
119: char sc_rxintrname[16 + 3];
120: char sc_txintrname[16 + 3];
121: struct pcctwosoftc *sc_pcctwo;
122: };
123:
124: const struct {
125: u_int speed;
126: u_char divisor;
127: u_char clock;
128: u_char rx_timeout;
129: } cl_clocks[] = {
130: { 64000, 0x26, 0, 0x01},
131: { 56000, 0x2c, 0, 0x01},
132: { 38400, 0x40, 0, 0x01},
133: { 19200, 0x81, 0, 0x02},
134: { 9600, 0x40, 1, 0x04},
135: { 7200, 0x56, 1, 0x04},
136: { 4800, 0x81, 1, 0x08},
137: { 3600, 0xad, 1, 0x08},
138: { 2400, 0x40, 2, 0x10},
139: { 1200, 0x81, 2, 0x20},
140: { 600, 0x40, 3, 0x40},
141: { 300, 0x81, 3, 0x80},
142: { 150, 0x40, 3, 0x80},
143: { 110, 0x58, 4, 0xff},
144: { 50, 0xC2, 4, 0xff},
145: { 0, 0x00, 0, 0},
146: };
147:
148: #define CL_SAFE_CLOCK 4 /* 9600 entry */
149:
150: /* prototypes */
151: cons_decl(cl);
152: int cl_instat(struct clsoftc *sc);
153: u_int8_t cl_clkdiv(int speed);
154: u_int8_t cl_clknum(int speed);
155: u_int8_t cl_clkrxtimeout(int speed);
156: void clstart(struct tty *tp);
157: void cl_unblock(struct tty *tp);
158: int clccparam(struct clsoftc *sc, struct termios *par, int channel);
159:
160: int clparam(struct tty *tp, struct termios *t);
161: int cl_mintr(void *);
162: int cl_txintr(void *);
163: int cl_rxintr(void *);
164: void cl_overflow(struct clsoftc *sc, int channel, long *ptime, char *msg);
165: void cl_parity(struct clsoftc *sc, int channel);
166: void cl_frame(struct clsoftc *sc, int channel);
167: void cl_break( struct clsoftc *sc, int channel);
168: int clmctl(dev_t dev, int bits, int how);
169: #ifdef DEBUG
170: void cl_dumpport(struct clsoftc *, int);
171: #endif
172:
173: int clprobe(struct device *parent, void *self, void *aux);
174: void clattach(struct device *parent, struct device *self, void *aux);
175:
176: void cl_initchannel(struct clsoftc *sc, int channel);
177: void clputc(struct clsoftc *sc, int unit, u_char c);
178:
179: struct cfattach cl_ca = {
180: sizeof(struct clsoftc), clprobe, clattach
181: };
182:
183: struct cfdriver cl_cd = {
184: NULL, "cl", DV_TTY
185: };
186:
187: #if 0
188: #define CLCDBUF 80
189: void cloutput(struct tty *tp);
190: #endif
191:
192: #define CL_UNIT(x) (minor(x) >> 2)
193: #define CL_CHANNEL(x) (minor(x) & 3)
194:
195: struct tty *
196: cltty(dev)
197: dev_t dev;
198: {
199: int unit, channel;
200: struct clsoftc *sc;
201:
202: unit = CL_UNIT(dev);
203: if (unit >= cl_cd.cd_ndevs ||
204: (sc = (struct clsoftc *)cl_cd.cd_devs[unit]) == NULL) {
205: return NULL;
206: }
207: channel = CL_CHANNEL(dev);
208: return sc->sc_cl[channel].tty;
209: }
210:
211: int
212: clprobe(parent, self, aux)
213: struct device *parent;
214: void *self;
215: void *aux;
216: {
217: struct confargs *ca = aux;
218: bus_space_handle_t ioh;
219: int rc;
220:
221: if (brdtyp == BRD_188)
222: return 0;
223:
224: /*
225: * We do not accept empty locators here...
226: */
227: if (ca->ca_paddr == CD2400_BASE_ADDR ||
228: (ca->ca_paddr == CD2400_SECONDARY_ADDR && brdtyp == BRD_8120)) {
229: if (bus_space_map(ca->ca_iot, ca->ca_paddr, CD2400_SIZE,
230: 0, &ioh) != 0)
231: return 0;
232: rc = badaddr((vaddr_t)bus_space_vaddr(ca->ca_iot, ioh), 1);
233: bus_space_unmap(ca->ca_iot, ioh, CD2400_SIZE);
234: return rc == 0;
235: }
236:
237: return 0;
238: }
239:
240: void
241: clattach(parent, self, aux)
242: struct device *parent;
243: struct device *self;
244: void *aux;
245: {
246: struct clsoftc *sc = (struct clsoftc *)self;
247: struct confargs *ca = aux;
248: bus_space_tag_t iot;
249: bus_space_handle_t ioh;
250: int i;
251:
252: if (ca->ca_ipl < 0)
253: ca->ca_ipl = IPL_TTY;
254:
255: iot = sc->sc_iot = ca->ca_iot;
256: if (bus_space_map(iot, ca->ca_paddr, CD2400_SIZE, 0, &ioh) != 0) {
257: printf(": can't map registers!\n");
258: return;
259: }
260: sc->sc_ioh = ioh;
261: sc->sc_pcctwo = (struct pcctwosoftc *)parent;
262:
263: if (ca->ca_paddr == CD2400_BASE_ADDR) {
264: /*
265: * Although we are still running using the BUG routines,
266: * this device will be elected as the console after
267: * autoconf. Mark it as such.
268: */
269: sc->sc_cl[0].cl_consio = 1;
270: printf(": console");
271: } else {
272: /* reset chip only if we are not console device */
273: /* wait for GFRCR */
274: }
275: /* allow chip to settle before continuing */
276: delay(800);
277:
278: /* set up global registers */
279: bus_space_write_1(iot, ioh, CL_TPR, CL_TIMEOUT);
280: bus_space_write_1(iot, ioh, CL_RPILR, 0x03);
281: bus_space_write_1(iot, ioh, CL_TPILR, 0x02);
282: bus_space_write_1(iot, ioh, CL_MPILR, 0x01);
283:
284: #ifdef DO_MALLOC
285: sc->sc_cl[0].rx[0] = (void *)(dvma_malloc(16 * CL_BUFSIZE));
286: #else
287: /* XXX */
288: if ((vaddr_t)ca->ca_paddr == CD2400_BASE_ADDR)
289: sc->sc_cl[0].rx[0] = (void *)(&cl_dmabuf);
290: else
291: sc->sc_cl[0].rx[0] = (void *)(&cl_dmabuf1);
292: #endif
293: sc->sc_cl[0].rx[1] = (void *)(((int)sc->sc_cl[0].rx[0]) + CL_BUFSIZE);
294: sc->sc_cl[1].rx[0] = (void *)(((int)sc->sc_cl[0].rx[1]) + CL_BUFSIZE);
295: sc->sc_cl[1].rx[1] = (void *)(((int)sc->sc_cl[1].rx[0]) + CL_BUFSIZE);
296:
297: sc->sc_cl[2].rx[0] = (void *)(((int)sc->sc_cl[1].rx[1]) + CL_BUFSIZE);
298: sc->sc_cl[2].rx[1] = (void *)(((int)sc->sc_cl[2].rx[0]) + CL_BUFSIZE);
299: sc->sc_cl[3].rx[0] = (void *)(((int)sc->sc_cl[2].rx[1]) + CL_BUFSIZE);
300: sc->sc_cl[3].rx[1] = (void *)(((int)sc->sc_cl[3].rx[0]) + CL_BUFSIZE);
301:
302: sc->sc_cl[0].tx[0] = (void *)(((int)sc->sc_cl[3].rx[1]) + CL_BUFSIZE);
303: sc->sc_cl[0].tx[1] = (void *)(((int)sc->sc_cl[0].tx[0]) + CL_BUFSIZE);
304: sc->sc_cl[1].tx[0] = (void *)(((int)sc->sc_cl[0].tx[1]) + CL_BUFSIZE);
305: sc->sc_cl[1].tx[1] = (void *)(((int)sc->sc_cl[1].tx[0]) + CL_BUFSIZE);
306:
307: sc->sc_cl[2].tx[0] = (void *)(((int)sc->sc_cl[1].tx[1]) + CL_BUFSIZE);
308: sc->sc_cl[2].tx[1] = (void *)(((int)sc->sc_cl[2].tx[0]) + CL_BUFSIZE);
309: sc->sc_cl[3].tx[0] = (void *)(((int)sc->sc_cl[2].tx[1]) + CL_BUFSIZE);
310: sc->sc_cl[3].tx[1] = (void *)(((int)sc->sc_cl[3].tx[0]) + CL_BUFSIZE);
311: for (i = 0; i < CLCD_PORTS_PER_CHIP; i++) {
312: #if 0
313: int j;
314:
315: for (j = 0; j < 2 ; j++) {
316: sc->sc_cl[i].rxp[j] = (void *)kvtop(sc->sc_cl[i].rx[j]);
317: printf("cl[%d].rxbuf[%d] %x p %x\n",
318: i, j, sc->sc_cl[i].rx[j], sc->sc_cl[i].rxp[j]);
319: sc->sc_cl[i].txp[j] = (void *)kvtop(sc->sc_cl[i].tx[j]);
320: printf("cl[%d].txbuf[%d] %x p %x\n",
321: i, j, sc->sc_cl[i].tx[j], sc->sc_cl[i].txp[j]);
322: }
323: #endif
324: #if 0
325: sc->sc_cl[i].cl_rxmode =
326: !(!((flags >> (i * CL_FLAG_BIT_PCH)) & 0x01));
327: sc->sc_cl[i].cl_txmode =
328: !(!((flags >> (i * CL_FLAG_BIT_PCH)) & 0x02));
329: sc->sc_cl[i].cl_softchar =
330: !(!((flags >> (i * CL_FLAG_BIT_PCH)) & 0x04));
331: #endif
332: cl_initchannel(sc, i);
333: }
334:
335: /* clear errors */
336: bus_space_write_1(sc->sc_pcctwo->sc_iot, sc->sc_pcctwo->sc_ioh,
337: PCCTWO_SCCERR, 0x01);
338:
339: /* enable interrupts */
340: sc->sc_ih_e.ih_fn = cl_rxintr;
341: sc->sc_ih_e.ih_arg = sc;
342: sc->sc_ih_e.ih_wantframe = 0;
343: sc->sc_ih_e.ih_ipl = ca->ca_ipl;
344:
345: sc->sc_ih_m.ih_fn = cl_mintr;
346: sc->sc_ih_m.ih_arg = sc;
347: sc->sc_ih_m.ih_wantframe = 0;
348: sc->sc_ih_m.ih_ipl = ca->ca_ipl;
349:
350: sc->sc_ih_t.ih_fn = cl_txintr;
351: sc->sc_ih_t.ih_arg = sc;
352: sc->sc_ih_t.ih_wantframe = 0;
353: sc->sc_ih_t.ih_ipl = ca->ca_ipl;
354:
355: sc->sc_ih_r.ih_fn = cl_rxintr;
356: sc->sc_ih_r.ih_arg = sc;
357: sc->sc_ih_r.ih_wantframe = 0;
358: sc->sc_ih_r.ih_ipl = ca->ca_ipl;
359:
360: snprintf(sc->sc_errintrname, sizeof sc->sc_errintrname,
361: "%s_err", self->dv_xname);
362: snprintf(sc->sc_mxintrname, sizeof sc->sc_mxintrname,
363: "%s_mx", self->dv_xname);
364: snprintf(sc->sc_rxintrname, sizeof sc->sc_rxintrname,
365: "%s_rx", self->dv_xname);
366: snprintf(sc->sc_txintrname, sizeof sc->sc_txintrname,
367: "%s_tx", self->dv_xname);
368:
369: pcctwointr_establish(PCC2V_SCC_RXE, &sc->sc_ih_e, sc->sc_errintrname);
370: pcctwointr_establish(PCC2V_SCC_M, &sc->sc_ih_m, sc->sc_mxintrname);
371: pcctwointr_establish(PCC2V_SCC_TX, &sc->sc_ih_t, sc->sc_txintrname);
372: pcctwointr_establish(PCC2V_SCC_RX, &sc->sc_ih_r, sc->sc_rxintrname);
373:
374: bus_space_write_1(sc->sc_pcctwo->sc_iot, sc->sc_pcctwo->sc_ioh,
375: PCCTWO_SCCICR, PCC2_IRQ_IEN | (ca->ca_ipl & PCC2_IRQ_IPL));
376: bus_space_write_1(sc->sc_pcctwo->sc_iot, sc->sc_pcctwo->sc_ioh,
377: PCCTWO_SCCTX, PCC2_IRQ_IEN | (ca->ca_ipl & PCC2_IRQ_IPL));
378: bus_space_write_1(sc->sc_pcctwo->sc_iot, sc->sc_pcctwo->sc_ioh,
379: PCCTWO_SCCRX, PCC2_IRQ_IEN | (ca->ca_ipl & PCC2_IRQ_IPL));
380:
381: printf("\n");
382: }
383:
384: void
385: cl_initchannel(sc, channel)
386: struct clsoftc *sc;
387: int channel;
388: {
389: int s;
390: bus_space_tag_t iot;
391: bus_space_handle_t ioh;
392:
393: iot = sc->sc_iot;
394: ioh = sc->sc_ioh;
395:
396: /* set up option registers */
397: sc->sc_cl[channel].tty = NULL;
398: s = splhigh();
399:
400: bus_space_write_1(iot, ioh, CL_CAR, channel);
401: bus_space_write_1(iot, ioh, CL_LIVR, PCC2_VECT + PCC2V_SCC_RXE);
402: bus_space_write_1(iot, ioh, CL_IER, 0);
403:
404: if (sc->sc_cl[channel].cl_consio == 0) {
405: bus_space_write_1(iot, ioh, CL_CMR, 0x02);
406: bus_space_write_1(iot, ioh, CL_COR1, 0x17);
407: bus_space_write_1(iot, ioh, CL_COR2, 0x00);
408: bus_space_write_1(iot, ioh, CL_COR3, 0x02);
409: bus_space_write_1(iot, ioh, CL_COR4, 0xec);
410: bus_space_write_1(iot, ioh, CL_COR5, 0xec);
411: bus_space_write_1(iot, ioh, CL_COR6, 0x00);
412: bus_space_write_1(iot, ioh, CL_COR7, 0x00);
413: bus_space_write_1(iot, ioh, CL_SCHR1, 0x00);
414: bus_space_write_1(iot, ioh, CL_SCHR2, 0x00);
415: bus_space_write_1(iot, ioh, CL_SCHR3, 0x00);
416: bus_space_write_1(iot, ioh, CL_SCHR4, 0x00);
417: bus_space_write_1(iot, ioh, CL_SCRL, 0x00);
418: bus_space_write_1(iot, ioh, CL_SCRH, 0x00);
419: bus_space_write_1(iot, ioh, CL_LNXT, 0x00);
420: bus_space_write_1(iot, ioh, CL_RBPR, 0x40); /* 9600 */
421: bus_space_write_1(iot, ioh, CL_RCOR, 0x01);
422: bus_space_write_1(iot, ioh, CL_TBPR, 0x40); /* 9600 */
423: bus_space_write_1(iot, ioh, CL_TCOR, 0x01 << 5);
424: /* console port should be 0x88 already */
425: bus_space_write_1(iot, ioh, CL_MSVR_RTS, 0x00);
426: bus_space_write_1(iot, ioh, CL_MSVR_DTR, 0x00);
427: bus_space_write_1(iot, ioh, CL_RTPRL, CL_RX_TIMEOUT);
428: bus_space_write_1(iot, ioh, CL_RTPRH, 0x00);
429: }
430: bus_space_write_1(iot, ioh, CL_CCR, 0x20);
431: while (bus_space_read_1(iot, ioh, CL_CCR) != 0)
432: ;
433:
434: splx(s);
435: }
436:
437:
438: int cldefaultrate = TTYDEF_SPEED;
439:
440: int
441: clmctl(dev, bits, how)
442: dev_t dev;
443: int bits;
444: int how;
445: {
446: struct clsoftc *sc;
447: bus_space_tag_t iot;
448: bus_space_handle_t ioh;
449: int s;
450:
451: /* should only be called with valid device */
452: sc = (struct clsoftc *)cl_cd.cd_devs[CL_UNIT(dev)];
453: iot = sc->sc_iot;
454: ioh = sc->sc_ioh;
455:
456: /* settings are currently ignored */
457: s = splcl();
458: switch (how) {
459: case DMSET:
460: if (bits & TIOCM_RTS)
461: bus_space_write_1(iot, ioh, CL_MSVR_RTS, 0x01);
462: else
463: bus_space_write_1(iot, ioh, CL_MSVR_RTS, 0x00);
464: if (bits & TIOCM_DTR)
465: bus_space_write_1(iot, ioh, CL_MSVR_DTR, 0x02);
466: else
467: bus_space_write_1(iot, ioh, CL_MSVR_DTR, 0x00);
468: break;
469:
470: case DMBIC:
471: if (bits & TIOCM_RTS)
472: bus_space_write_1(iot, ioh, CL_MSVR_RTS, 0x00);
473: if (bits & TIOCM_DTR)
474: bus_space_write_1(iot, ioh, CL_MSVR_DTR, 0x00);
475: break;
476:
477: case DMBIS:
478: if (bits & TIOCM_RTS)
479: bus_space_write_1(iot, ioh, CL_MSVR_RTS, 0x01);
480: if (bits & TIOCM_DTR)
481: bus_space_write_1(iot, ioh, CL_MSVR_DTR, 0x02);
482: break;
483:
484: case DMGET:
485: bits = 0;
486:
487: {
488: u_int8_t msvr;
489:
490: msvr = bus_space_read_1(iot, ioh, CL_MSVR_RTS);
491: if (msvr & 0x80)
492: bits |= TIOCM_DSR;
493: if (msvr & 0x40)
494: bits |= TIOCM_CD;
495: if (msvr & 0x20)
496: bits |= TIOCM_CTS;
497: if (msvr & 0x10)
498: bits |= TIOCM_DTR;
499: if (msvr & 0x02)
500: bits |= TIOCM_DTR;
501: if (msvr & 0x01)
502: bits |= TIOCM_RTS;
503: }
504: break;
505: }
506: splx(s);
507: #if 0
508: bits = 0;
509: /* proper defaults? */
510: bits |= TIOCM_DTR;
511: bits |= TIOCM_RTS;
512: bits |= TIOCM_CTS;
513: bits |= TIOCM_CD;
514: /* bits |= TIOCM_RI; */
515: bits |= TIOCM_DSR;
516: #endif
517:
518: return bits;
519: }
520:
521: int
522: clopen(dev, flag, mode, p)
523: dev_t dev;
524: int flag;
525: int mode;
526: struct proc *p;
527: {
528: int s, unit, channel;
529: struct cl_info *cl;
530: struct clsoftc *sc;
531: struct tty *tp;
532:
533: unit = CL_UNIT(dev);
534: if (unit >= cl_cd.cd_ndevs ||
535: (sc = (struct clsoftc *)cl_cd.cd_devs[unit]) == NULL) {
536: return ENODEV;
537: }
538:
539: channel = CL_CHANNEL(dev);
540: cl = &sc->sc_cl[channel];
541:
542: s = splcl();
543: if (cl->tty) {
544: tp = cl->tty;
545: } else {
546: tp = cl->tty = ttymalloc();
547: }
548: tp->t_oproc = clstart;
549: tp->t_param = clparam;
550: tp->t_dev = dev;
551:
552: if ((tp->t_state & TS_ISOPEN) == 0) {
553: tp->t_state |= TS_WOPEN;
554: ttychars(tp);
555: if (tp->t_ispeed == 0) {
556: /*
557: * only when cleared do we reset to defaults.
558: */
559: tp->t_iflag = TTYDEF_IFLAG;
560: tp->t_oflag = TTYDEF_OFLAG;
561: tp->t_lflag = TTYDEF_LFLAG;
562: tp->t_ispeed = tp->t_ospeed = cldefaultrate;
563:
564: if (sc->sc_cl[channel].cl_consio != 0) {
565: /* console is 8N1 */
566: tp->t_cflag = (CREAD | CS8 | HUPCL);
567: } else {
568: tp->t_cflag = TTYDEF_CFLAG;
569: }
570: }
571: /*
572: * do these all the time
573: */
574: if (cl->cl_swflags & TIOCFLAG_CLOCAL)
575: tp->t_cflag |= CLOCAL;
576: if (cl->cl_swflags & TIOCFLAG_CRTSCTS)
577: tp->t_cflag |= CRTSCTS;
578: if (cl->cl_swflags & TIOCFLAG_MDMBUF)
579: tp->t_cflag |= MDMBUF;
580: clparam(tp, &tp->t_termios);
581: ttsetwater(tp);
582:
583: (void)clmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
584: #ifdef XXX
585: if ((cl->cl_swflags & TIOCFLAG_SOFTCAR) ||
586: (clmctl(dev, 0, DMGET) & TIOCM_CD)) {
587: tp->t_state |= TS_CARR_ON;
588: } else {
589: tp->t_state &= ~TS_CARR_ON;
590: }
591: #endif
592: tp->t_state |= TS_CARR_ON;
593: {
594: u_int8_t save;
595:
596: save = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CL_CAR);
597: bus_space_write_1(sc->sc_iot, sc->sc_ioh, CL_CAR,
598: channel);
599: bus_space_write_1(sc->sc_iot, sc->sc_ioh, CL_IER, 0x88);
600: bus_space_write_1(sc->sc_iot, sc->sc_ioh, CL_CAR,
601: save);
602: }
603: } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
604: splx(s);
605: return EBUSY;
606: }
607: splx(s);
608:
609: /*
610: * Reset the tty pointer, as there could have been a dialout
611: * use of the tty with a dialin open waiting.
612: */
613: tp->t_dev = dev;
614: #ifdef DEBUG
615: cl_dumpport(sc, channel);
616: #endif
617: return (*linesw[tp->t_line].l_open)(dev, tp);
618: }
619:
620: int
621: clparam(tp, t)
622: struct tty *tp;
623: struct termios *t;
624: {
625: int unit, channel;
626: struct clsoftc *sc;
627: int s;
628: dev_t dev;
629:
630: dev = tp->t_dev;
631: unit = CL_UNIT(dev);
632: if (unit >= cl_cd.cd_ndevs ||
633: (sc = (struct clsoftc *)cl_cd.cd_devs[unit]) == NULL) {
634: return ENODEV;
635: }
636: channel = CL_CHANNEL(dev);
637: tp->t_ispeed = t->c_ispeed;
638: tp->t_ospeed = t->c_ospeed;
639: tp->t_cflag = t->c_cflag;
640: clccparam(sc, t, channel);
641: s = splcl();
642: cl_unblock(tp);
643: splx(s);
644: return 0;
645: }
646:
647: #if 0
648: void
649: cloutput(tp)
650: struct tty *tp;
651: {
652: int cc, s, unit, cnt;
653: u_char *tptr;
654: int channel;
655: struct clsoftc *sc;
656: dev_t dev;
657: u_char cl_obuffer[CLCDBUF+1];
658:
659: dev = tp->t_dev;
660: unit = CL_UNIT(dev);
661: if (unit >= cl_cd.cd_ndevs ||
662: (sc = (struct clsoftc *)cl_cd.cd_devs[unit]) == NULL) {
663: return;
664: }
665: channel = CL_CHANNEL(dev);
666:
667: if ((tp->t_state & TS_ISOPEN) == 0)
668: return;
669:
670: s = splcl();
671: cc = tp->t_outq.c_cc;
672: while (cc > 0) {
673: /*XXX*/
674: cnt = min (CLCDBUF,cc);
675: cnt = q_to_b(&tp->t_outq, cl_obuffer, cnt);
676: if (cnt == 0) {
677: break;
678: }
679: for (tptr = cl_obuffer; tptr < &cl_obuffer[cnt]; tptr++) {
680: clputc(sc, channel, *tptr);
681: }
682: cc -= cnt;
683: }
684: splx(s);
685: }
686: #endif
687:
688: int
689: clclose(dev, flag, mode, p)
690: dev_t dev;
691: int flag;
692: int mode;
693: struct proc *p;
694: {
695: int unit, channel;
696: struct tty *tp;
697: struct cl_info *cl;
698: struct clsoftc *sc;
699: bus_space_tag_t iot;
700: bus_space_handle_t ioh;
701: int s;
702:
703: unit = CL_UNIT(dev);
704: if (unit >= cl_cd.cd_ndevs ||
705: (sc = (struct clsoftc *)cl_cd.cd_devs[unit]) == NULL) {
706: return ENODEV;
707: }
708: channel = CL_CHANNEL(dev);
709: cl = &sc->sc_cl[channel];
710: iot = sc->sc_iot;
711: ioh = sc->sc_ioh;
712: tp = cl->tty;
713: (*linesw[tp->t_line].l_close)(tp, flag);
714:
715: s = splcl();
716: bus_space_write_1(iot, ioh, CL_CAR, channel);
717: if (cl->cl_consio == 0 && (tp->t_cflag & HUPCL) != 0) {
718: bus_space_write_1(iot, ioh, CL_MSVR_RTS, 0x00);
719: bus_space_write_1(iot, ioh, CL_MSVR_DTR, 0x00);
720: bus_space_write_1(iot, ioh, CL_CCR, 0x05);
721: }
722:
723:
724: splx(s);
725: ttyclose(tp);
726:
727: #if 0
728: cl->tty = NULL;
729: #endif
730: #ifdef DEBUG
731: cl_dumpport(sc, channel);
732: #endif
733:
734: return 0;
735: }
736:
737: int
738: clread(dev, uio, flag)
739: dev_t dev;
740: struct uio *uio;
741: int flag;
742: {
743: int unit, channel;
744: struct tty *tp;
745: struct cl_info *cl;
746: struct clsoftc *sc;
747: unit = CL_UNIT(dev);
748: if (unit >= cl_cd.cd_ndevs ||
749: (sc = (struct clsoftc *)cl_cd.cd_devs[unit]) == NULL) {
750: return ENODEV;
751: }
752: channel = CL_CHANNEL(dev);
753: cl = &sc->sc_cl[channel];
754: tp = cl->tty;
755: if (tp == NULL)
756: return ENXIO;
757: return (*linesw[tp->t_line].l_read)(tp, uio, flag);
758: }
759:
760: int
761: clwrite(dev, uio, flag)
762: dev_t dev;
763: struct uio *uio;
764: int flag;
765: {
766: int unit, channel;
767: struct tty *tp;
768: struct cl_info *cl;
769: struct clsoftc *sc;
770: unit = CL_UNIT(dev);
771: if (unit >= cl_cd.cd_ndevs ||
772: (sc = (struct clsoftc *)cl_cd.cd_devs[unit]) == NULL) {
773: return ENODEV;
774: }
775: channel = CL_CHANNEL(dev);
776: cl = &sc->sc_cl[channel];
777: tp = cl->tty;
778: if (tp == NULL)
779: return ENXIO;
780: return (*linesw[tp->t_line].l_write)(tp, uio, flag);
781: }
782:
783: int
784: clioctl(dev, cmd, data, flag, p)
785: dev_t dev;
786: u_long cmd;
787: caddr_t data;
788: int flag;
789: struct proc *p;
790: {
791: int error;
792: int unit, channel;
793: struct tty *tp;
794: struct cl_info *cl;
795: struct clsoftc *sc;
796: unit = CL_UNIT(dev);
797: if (unit >= cl_cd.cd_ndevs ||
798: (sc = (struct clsoftc *)cl_cd.cd_devs[unit]) == NULL) {
799: return ENODEV;
800: }
801: channel = CL_CHANNEL(dev);
802: cl = &sc->sc_cl[channel];
803: tp = cl->tty;
804: if (tp == NULL)
805: return ENXIO;
806:
807: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
808: if (error >= 0)
809: return error;
810:
811: error = ttioctl(tp, cmd, data, flag, p);
812: if (error >= 0)
813: return error;
814:
815: switch (cmd) {
816: case TIOCSBRK:
817: /* */
818: break;
819:
820: case TIOCCBRK:
821: /* */
822: break;
823:
824: case TIOCSDTR:
825: (void) clmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
826: break;
827:
828: case TIOCCDTR:
829: (void) clmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
830: break;
831:
832: case TIOCMSET:
833: (void) clmctl(dev, *(int *) data, DMSET);
834: break;
835:
836: case TIOCMBIS:
837: (void) clmctl(dev, *(int *) data, DMBIS);
838: break;
839:
840: case TIOCMBIC:
841: (void) clmctl(dev, *(int *) data, DMBIC);
842: break;
843:
844: case TIOCMGET:
845: *(int *)data = clmctl(dev, 0, DMGET);
846: break;
847: case TIOCGFLAGS:
848: *(int *)data = cl->cl_swflags;
849: break;
850: case TIOCSFLAGS:
851: error = suser(p, 0);
852: if (error != 0)
853: return EPERM;
854:
855: cl->cl_swflags = *(int *)data;
856: cl->cl_swflags &= /* only allow valid flags */
857: (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
858: break;
859: default:
860: return ENOTTY;
861: }
862:
863: return 0;
864: }
865:
866: int
867: clstop(tp, flag)
868: struct tty *tp;
869: int flag;
870: {
871: int s;
872:
873: s = splcl();
874: if (tp->t_state & TS_BUSY) {
875: if ((tp->t_state & TS_TTSTOP) == 0)
876: tp->t_state |= TS_FLUSH;
877: }
878: splx(s);
879: return 0;
880: }
881:
882: void
883: clcnprobe(cp)
884: struct consdev *cp;
885: {
886: int maj;
887:
888: /* bomb if it'a a MVME188 */
889: if (brdtyp == BRD_188 || badaddr(CD2400_BASE_ADDR, 1) != 0)
890: return;
891:
892: /* do not attach as console if cl has been disabled */
893: if (cl_cd.cd_ndevs == 0 || cl_cd.cd_devs[0] == NULL)
894: return;
895:
896: /* locate the major number */
897: for (maj = 0; maj < nchrdev; maj++)
898: if (cdevsw[maj].d_open == clopen)
899: break;
900: if (maj == nchrdev)
901: return;
902:
903: cp->cn_dev = makedev(maj, 0);
904: cp->cn_pri = CN_NORMAL;
905: }
906:
907: void
908: clcninit(cp)
909: struct consdev *cp;
910: {
911: struct clsoftc *sc;
912:
913: sc = (struct clsoftc *)cl_cd.cd_devs[0];
914: cl_cons.cl_iot = sc->sc_iot;
915: cl_cons.cl_ioh = sc->sc_ioh;
916: cl_cons.cl_rxiack = (void *)(sc->sc_pcctwo->sc_base + PCCTWO_SCCRXIACK);
917: }
918:
919: int
920: cl_instat(sc)
921: struct clsoftc *sc;
922: {
923: u_int8_t rir;
924:
925: if (sc == NULL)
926: rir = bus_space_read_1(cl_cons.cl_iot, cl_cons.cl_ioh, CL_RIR);
927: else
928: rir = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CL_RIR);
929:
930: return (rir & 0x40);
931: }
932:
933: int
934: clcngetc(dev)
935: dev_t dev;
936: {
937: u_int8_t val, reoir, licr, data;
938: int got_char = 0;
939: u_int8_t ier_old;
940: bus_space_tag_t iot;
941: bus_space_handle_t ioh;
942:
943: iot = cl_cons.cl_iot;
944: ioh = cl_cons.cl_ioh;
945:
946: bus_space_write_1(iot, ioh, CL_CAR, 0);
947: ier_old = bus_space_read_1(iot, ioh, CL_IER);
948: if ((ier_old & 0x08) == 0) {
949: bus_space_write_1(iot, ioh, CL_IER, 0x08);
950: } else
951: ier_old = 0xff;
952:
953: while (got_char == 0) {
954: val = bus_space_read_1(iot, ioh, CL_RIR);
955: /* if no receive interrupt pending wait */
956: if ((val & 0x80) == 0)
957: continue;
958:
959: /* XXX do we need to suck the entire FIFO contents? */
960: reoir = *cl_cons.cl_rxiack; /* receive PIACK */
961: licr = bus_space_read_1(iot, ioh, CL_LICR);
962: /* is the interrupt for us? (port 0) */
963: if (((licr >> 2) & 0x3) == 0) {
964: (void)bus_space_read_1(iot, ioh, CL_RISRL);
965: (void)bus_space_read_1(iot, ioh, CL_RFOC);
966: data = bus_space_read_1(iot, ioh, CL_RDR);
967: if (ier_old != 0xff)
968: bus_space_write_1(iot, ioh, CL_IER, ier_old);
969: got_char = 1;
970: } else {
971: /* read and discard the character */
972: data = bus_space_read_1(iot, ioh, CL_RDR);
973: }
974: bus_space_write_1(iot, ioh, CL_TEOIR, 0x00);
975: }
976:
977: return data;
978: }
979:
980: void
981: clcnputc(dev, c)
982: dev_t dev;
983: u_char c;
984: {
985: clputc(0, 0, c);
986: }
987:
988: void
989: clcnpollc(dev, on)
990: dev_t dev;
991: int on;
992: {
993: if (on != 0) {
994: /* enable polling */
995: } else {
996: /* disable polling */
997: }
998: }
999:
1000: void
1001: clputc(sc, unit, c)
1002: struct clsoftc *sc;
1003: int unit;
1004: u_char c;
1005: {
1006: u_int8_t schar;
1007: u_int8_t oldchannel;
1008: bus_space_tag_t iot;
1009: bus_space_handle_t ioh;
1010: int s;
1011:
1012: if (sc == NULL) {
1013: /* output on console */
1014: iot = cl_cons.cl_iot;
1015: ioh = cl_cons.cl_ioh;
1016: } else {
1017: iot = sc->sc_iot;
1018: ioh = sc->sc_ioh;
1019: }
1020:
1021: s = splhigh();
1022: oldchannel = bus_space_read_1(iot, ioh, CL_CAR);
1023: bus_space_write_1(iot, ioh, CL_CAR, unit);
1024: if (unit == 0) {
1025: schar = bus_space_read_1(iot, ioh, CL_SCHR3);
1026: /* send special char, number 3 */
1027: bus_space_write_1(iot, ioh, CL_SCHR3, c);
1028: bus_space_write_1(iot, ioh, CL_STCR, 0x08 | 3);
1029: while (bus_space_read_1(iot, ioh, CL_STCR) != 0) {
1030: /* wait until cl notices the command
1031: * otherwise it may not notice the character
1032: * if we send characters too fast.
1033: */
1034: }
1035: DELAY(5);
1036: bus_space_write_1(iot, ioh, CL_SCHR3, schar);
1037: } else {
1038: if (bus_space_read_1(iot, ioh, CL_TFTC) != 0)
1039: bus_space_write_1(iot, ioh, CL_TDR, c);
1040: }
1041: bus_space_write_1(iot, ioh, CL_CAR, oldchannel);
1042: splx(s);
1043: }
1044:
1045: int
1046: clccparam(sc, par, channel)
1047: struct clsoftc *sc;
1048: struct termios *par;
1049: int channel;
1050: {
1051: bus_space_tag_t iot;
1052: bus_space_handle_t ioh;
1053: u_int divisor, clk, clen;
1054: int s, imask, ints;
1055:
1056: iot = sc->sc_iot;
1057: ioh = sc->sc_ioh;
1058:
1059: s = splcl();
1060: bus_space_write_1(iot, ioh, CL_CAR, channel);
1061: if (par->c_ospeed == 0) {
1062: /* dont kill the console */
1063: if (sc->sc_cl[channel].cl_consio == 0) {
1064: /* disconnect, drop RTS DTR stop receiver */
1065: bus_space_write_1(iot, ioh, CL_MSVR_RTS, 0x00);
1066: bus_space_write_1(iot, ioh, CL_MSVR_DTR, 0x00);
1067: bus_space_write_1(iot, ioh, CL_CCR, 0x05);
1068: }
1069: splx(s);
1070: return 0xff;
1071: }
1072:
1073: bus_space_write_1(iot, ioh, CL_MSVR_RTS, 0x03);
1074: bus_space_write_1(iot, ioh, CL_MSVR_DTR, 0x03);
1075:
1076: divisor = cl_clkdiv(par->c_ospeed);
1077: clk = cl_clknum(par->c_ospeed);
1078: bus_space_write_1(iot, ioh, CL_TBPR, divisor);
1079: bus_space_write_1(iot, ioh, CL_TCOR, clk << 5);
1080: divisor = cl_clkdiv(par->c_ispeed);
1081: clk = cl_clknum(par->c_ispeed);
1082: bus_space_write_1(iot, ioh, CL_RBPR, divisor);
1083: bus_space_write_1(iot, ioh, CL_RCOR, clk);
1084: bus_space_write_1(iot, ioh, CL_RTPRL, cl_clkrxtimeout(par->c_ispeed));
1085: bus_space_write_1(iot, ioh, CL_RTPRH, 0x00);
1086:
1087: switch (par->c_cflag & CSIZE) {
1088: case CS5:
1089: clen = 4; /* this is the mask for the chip. */
1090: imask = 0x1F;
1091: break;
1092: case CS6:
1093: clen = 5;
1094: imask = 0x3F;
1095: break;
1096: case CS7:
1097: clen = 6;
1098: imask = 0x7F;
1099: break;
1100: default:
1101: clen = 7;
1102: imask = 0xFF;
1103: }
1104:
1105: bus_space_write_1(iot, ioh, CL_COR3, par->c_cflag & PARENB ? 4 : 2);
1106:
1107: {
1108: u_int8_t cor1;
1109: if (par->c_cflag & PARENB) {
1110: if (par->c_cflag & PARODD) {
1111: cor1 = 0xE0 | clen ; /* odd */
1112: } else {
1113: cor1 = 0x40 | clen ; /* even */
1114: }
1115: } else {
1116: cor1 = 0x10 | clen; /* ignore parity */
1117: }
1118:
1119: if (bus_space_read_1(iot, ioh, CL_COR1) != cor1) {
1120: bus_space_write_1(iot, ioh, CL_COR1, cor1);
1121: bus_space_write_1(iot, ioh, CL_CCR, 0x20);
1122: while (bus_space_read_1(iot, ioh, CL_CCR) != 0)
1123: ;
1124: }
1125: }
1126:
1127: if (sc->sc_cl[channel].cl_consio == 0 && (par->c_cflag & CREAD) == 0)
1128: bus_space_write_1(iot, ioh, CL_CCR, 0x08);
1129: else
1130: bus_space_write_1(iot, ioh, CL_CCR, 0x0a);
1131:
1132: while (bus_space_read_1(iot, ioh, CL_CCR) != 0)
1133: ;
1134:
1135: ints = 0;
1136: #define SCC_DSR 0x80
1137: #define SCC_DCD 0x40
1138: #define SCC_CTS 0x20
1139: if ((par->c_cflag & CLOCAL) == 0) {
1140: ints |= SCC_DCD;
1141: }
1142: if ((par->c_cflag & CCTS_OFLOW) != 0) {
1143: ints |= SCC_CTS;
1144: }
1145: if ((par->c_cflag & CRTSCTS) != 0) {
1146: ints |= SCC_CTS;
1147: }
1148: #ifdef DONT_LET_HARDWARE
1149: if ((par->c_cflag & CCTS_IFLOW) != 0) {
1150: ints |= SCC_DSR;
1151: }
1152: #endif
1153: bus_space_write_1(iot, ioh, CL_COR4, ints | CL_FIFO_CNT);
1154: bus_space_write_1(iot, ioh, CL_COR5, ints | CL_FIFO_CNT);
1155:
1156: splx(s);
1157:
1158: return imask;
1159: }
1160:
1161: static int clknum = 0;
1162:
1163: u_int8_t
1164: cl_clkdiv(speed)
1165: int speed;
1166: {
1167: int i;
1168:
1169: if (cl_clocks[clknum].speed == speed)
1170: return cl_clocks[clknum].divisor;
1171:
1172: for (i = 0; cl_clocks[i].speed != 0; i++) {
1173: if (cl_clocks[i].speed == speed) {
1174: clknum = i;
1175: return cl_clocks[clknum].divisor;
1176: }
1177: }
1178:
1179: /* return some sane value if unknown speed */
1180: return cl_clocks[CL_SAFE_CLOCK].divisor;
1181: }
1182:
1183: u_int8_t
1184: cl_clknum(speed)
1185: int speed;
1186: {
1187: int i;
1188:
1189: if (cl_clocks[clknum].speed == speed)
1190: return cl_clocks[clknum].clock;
1191:
1192: for (i = 0; cl_clocks[i].speed != 0; i++) {
1193: if (cl_clocks[clknum].speed == speed) {
1194: clknum = i;
1195: return cl_clocks[clknum].clock;
1196: }
1197: }
1198:
1199: /* return some sane value if unknown speed */
1200: return cl_clocks[CL_SAFE_CLOCK].clock;
1201: }
1202:
1203: u_int8_t
1204: cl_clkrxtimeout(speed)
1205: int speed;
1206: {
1207: int i;
1208:
1209: if (cl_clocks[clknum].speed == speed)
1210: return cl_clocks[clknum].rx_timeout;
1211:
1212: for (i = 0; cl_clocks[i].speed != 0; i++) {
1213: if (cl_clocks[i].speed == speed) {
1214: clknum = i;
1215: return cl_clocks[clknum].rx_timeout;
1216: }
1217: }
1218:
1219: /* return some sane value if unknown speed */
1220: return cl_clocks[CL_SAFE_CLOCK].rx_timeout;
1221: }
1222:
1223: void
1224: cl_unblock(tp)
1225: struct tty *tp;
1226: {
1227: tp->t_state &= ~TS_FLUSH;
1228: if (tp->t_outq.c_cc != 0)
1229: clstart(tp);
1230: }
1231:
1232: void
1233: clstart(tp)
1234: struct tty *tp;
1235: {
1236: dev_t dev;
1237: struct clsoftc *sc;
1238: int channel, unit, s;
1239: #if 0
1240: int cnt;
1241: u_int8_t cbuf;
1242: #endif
1243:
1244: dev = tp->t_dev;
1245: channel = CL_CHANNEL(dev);
1246: /* hack to test output on non console only */
1247: #if 0
1248: if (channel == 0) {
1249: cloutput(tp);
1250: return;
1251: }
1252: #endif
1253: unit = CL_UNIT(dev);
1254: if (unit >= cl_cd.cd_ndevs ||
1255: (sc = (struct clsoftc *)cl_cd.cd_devs[unit]) == NULL) {
1256: return;
1257: }
1258:
1259: if ((tp->t_state & TS_ISOPEN) == 0)
1260: return;
1261:
1262: s = splcl();
1263: #if 0
1264: if (sc->sc_cl[channel].transmitting == 1) {
1265: /* i'm busy, go away, I will get to it later. */
1266: splx(s);
1267: return;
1268: }
1269: cnt = q_to_b(&tp->t_outq, &cbuf, 1);
1270: if ( cnt != 0 ) {
1271: sc->sc_cl[channel].transmitting = 1;
1272: bus_space_write_1(sc->sc_iot, sc->sc_ioh, CL_CAR, channel);
1273: bus_space_write_1(sc->sc_iot, sc->sc_ioh, CL_TDR, cbuf);
1274: } else {
1275: sc->sc_cl[channel].transmitting = 0;
1276: }
1277: #else
1278: if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_FLUSH)) == 0)
1279: {
1280: tp->t_state |= TS_BUSY;
1281: bus_space_write_1(sc->sc_iot, sc->sc_ioh, CL_CAR, channel);
1282: bus_space_write_1(sc->sc_iot, sc->sc_ioh, CL_IER,
1283: bus_space_read_1(sc->sc_iot, sc->sc_ioh, CL_IER) | 0x03);
1284: }
1285: #endif
1286: splx(s);
1287: }
1288:
1289: int
1290: cl_mintr(arg)
1291: void *arg;
1292: {
1293: struct clsoftc *sc = arg;
1294: bus_space_tag_t iot;
1295: bus_space_handle_t ioh;
1296: u_int8_t mir, misr, msvr;
1297: int channel;
1298:
1299: iot = sc->sc_iot;
1300: ioh = sc->sc_ioh;
1301:
1302: mir = bus_space_read_1(iot, ioh, CL_MIR);
1303: if ((mir & 0x40) == 0) {
1304: return 0;
1305: }
1306:
1307: channel = mir & 0x03;
1308: misr = bus_space_read_1(iot, ioh, CL_MISR);
1309: msvr = bus_space_read_1(iot, ioh, CL_MSVR_RTS);
1310: if (misr & 0x01) {
1311: /* timers are not currently used?? */
1312: log(LOG_WARNING, "cl_mintr: channel %x timer 1 unexpected\n",channel);
1313: }
1314: if (misr & 0x02) {
1315: /* timers are not currently used?? */
1316: log(LOG_WARNING, "cl_mintr: channel %x timer 2 unexpected\n",channel);
1317: }
1318: if (misr & 0x20) {
1319: #ifdef DEBUG
1320: log(LOG_WARNING, "cl_mintr: channel %x cts %x\n",channel,
1321: ((msvr & 0x20) != 0x0)
1322: );
1323: #endif
1324: }
1325: if (misr & 0x40) {
1326: struct tty *tp = sc->sc_cl[channel].tty;
1327: #ifdef DEBUG
1328: log(LOG_WARNING, "cl_mintr: channel %x cd %x\n",channel,
1329: ((msvr & 0x40) != 0x0)
1330: );
1331: #endif
1332: ttymodem(tp, ((msvr & 0x40) != 0x0) );
1333: }
1334: if (misr & 0x80) {
1335: #ifdef DEBUG
1336: log(LOG_WARNING, "cl_mintr: channel %x dsr %x\n",channel,
1337: ((msvr & 0x80) != 0x0)
1338: );
1339: #endif
1340: }
1341: bus_space_write_1(iot, ioh, CL_MEOIR, 0);
1342: return 1;
1343: }
1344:
1345: int
1346: cl_txintr(arg)
1347: void *arg;
1348: {
1349: static int empty;
1350: struct clsoftc *sc = arg;
1351: bus_space_tag_t iot;
1352: bus_space_handle_t ioh;
1353: u_int8_t tir, cmr, teoir;
1354: u_int8_t max;
1355: int channel;
1356: struct tty *tp;
1357: int cnt;
1358: u_char buffer[CL_FIFO_MAX +1];
1359:
1360: iot = sc->sc_iot;
1361: ioh = sc->sc_ioh;
1362: tir = bus_space_read_1(iot, ioh, CL_TIR);
1363: if ((tir & 0x40) == 0) {
1364: return 0;
1365: }
1366:
1367: channel = tir & 0x03;
1368: sc->sc_cl[channel].txcnt ++;
1369:
1370: cmr = bus_space_read_1(iot, ioh, CL_CMR);
1371:
1372: tp = sc->sc_cl[channel].tty;
1373: if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) {
1374: bus_space_write_1(iot, ioh, CL_IER,
1375: bus_space_read_1(iot, ioh, CL_IER) & ~0x03);
1376: bus_space_write_1(iot, ioh, CL_TEOIR, 0x08);
1377: return 1;
1378: }
1379:
1380: switch (cmr & CL_TXMASK) {
1381: case CL_TXDMAINT:
1382: {
1383: u_int8_t dmabsts;
1384: int nbuf, busy, resid;
1385: void *pbuffer;
1386:
1387: dmabsts = bus_space_read_1(iot, ioh, CL_DMABSTS);
1388: nbuf = ((dmabsts & 0x8) >> 3) & 0x1;
1389: busy = ((dmabsts & 0x4) >> 2) & 0x1;
1390:
1391: do {
1392: pbuffer = sc->sc_cl[channel].tx[nbuf];
1393: resid = tp->t_outq.c_cc;
1394: cnt = min (CL_BUFSIZE,resid);
1395: log(LOG_WARNING, "cl_txintr: resid %x cnt %x pbuf %p\n",
1396: resid, cnt, pbuffer);
1397: if (cnt != 0) {
1398: cnt = q_to_b(&tp->t_outq, pbuffer, cnt);
1399: resid -= cnt;
1400: if (nbuf == 0) {
1401: bus_space_write_2(iot, ioh, CL_ATBADRU,
1402: ((u_long)sc->sc_cl[channel].txp[nbuf]) >> 16);
1403: bus_space_write_2(iot, ioh, CL_ATBADRL,
1404: ((u_long) sc->sc_cl[channel].txp[nbuf]) & 0xffff);
1405: bus_space_write_2(iot, ioh, CL_ATBCNT,
1406: cnt);
1407: bus_space_write_1(iot, ioh, CL_ATBSTS,
1408: 0x43);
1409: } else {
1410: bus_space_write_2(iot, ioh, CL_BTBADRU,
1411: ((u_long)sc->sc_cl[channel].txp[nbuf]) >> 16);
1412: bus_space_write_2(iot, ioh, CL_BTBADRL,
1413: ((u_long) sc->sc_cl[channel].txp[nbuf]) & 0xffff);
1414: bus_space_write_2(iot, ioh, CL_BTBCNT,
1415: cnt);
1416: bus_space_write_1(iot, ioh, CL_BTBSTS,
1417: 0x43);
1418: }
1419: teoir = 0x08;
1420: } else {
1421: teoir = 0x08;
1422: if (tp->t_state & TS_BUSY) {
1423: tp->t_state &= ~(TS_BUSY | TS_FLUSH);
1424: if (tp->t_state & TS_ASLEEP) {
1425: tp->t_state &= ~TS_ASLEEP;
1426: wakeup((caddr_t) &tp->t_outq);
1427: }
1428: selwakeup(&tp->t_wsel);
1429: }
1430: bus_space_write_1(iot, ioh, CL_IER,
1431: bus_space_read_1(iot, ioh, CL_IER) & ~0x03);
1432: }
1433: nbuf = ~nbuf & 0x1;
1434: busy--;
1435: } while (resid != 0 && busy != -1);/* if not busy do other buffer */
1436: }
1437: break;
1438: case CL_TXINTR:
1439: max = bus_space_read_1(iot, ioh, CL_TFTC);
1440: cnt = min((int)max,tp->t_outq.c_cc);
1441: if (cnt != 0) {
1442: cnt = q_to_b(&tp->t_outq, buffer, cnt);
1443: empty = 0;
1444: bus_space_write_multi_1(iot, ioh, CL_TDR, buffer, cnt);
1445: teoir = 0x00;
1446: } else {
1447: if (empty > 5 && ((empty % 20000 )== 0)) {
1448: log(LOG_WARNING, "cl_txintr to many empty intr %d channel %d\n",
1449: empty, channel);
1450: }
1451: empty++;
1452: teoir = 0x08;
1453: if (tp->t_state & TS_BUSY) {
1454: tp->t_state &= ~(TS_BUSY | TS_FLUSH);
1455: if (tp->t_state & TS_ASLEEP) {
1456: tp->t_state &= ~TS_ASLEEP;
1457: wakeup((caddr_t) &tp->t_outq);
1458: }
1459: selwakeup(&tp->t_wsel);
1460: }
1461: bus_space_write_1(iot, ioh, CL_IER,
1462: bus_space_read_1(iot, ioh, CL_IER) & ~0x03);
1463: }
1464: break;
1465: default:
1466: log(LOG_WARNING, "cl_txintr unknown mode %x\n", cmr);
1467: /* we probably will go to hell quickly now */
1468: teoir = 0x08;
1469: }
1470: bus_space_write_1(iot, ioh, CL_TEOIR, teoir);
1471: return 1;
1472: }
1473:
1474: int
1475: cl_rxintr(arg)
1476: void *arg;
1477: {
1478: struct clsoftc *sc = arg;
1479: bus_space_tag_t iot;
1480: bus_space_handle_t ioh;
1481: u_int8_t rir, channel, cmr, risrl;
1482: u_int8_t fifocnt;
1483: struct tty *tp;
1484: int i;
1485: u_int8_t reoir;
1486: u_char buffer[CL_FIFO_MAX +1];
1487: #ifdef DDB
1488: int wantddb = 0;
1489: #endif
1490:
1491: iot = sc->sc_iot;
1492: ioh = sc->sc_ioh;
1493:
1494: rir = bus_space_read_1(iot, ioh, CL_RIR);
1495: if ((rir & 0x40) == 0x0) {
1496: return 0;
1497: }
1498:
1499: channel = rir & 0x3;
1500: cmr = bus_space_read_1(iot, ioh, CL_CMR);
1501:
1502: sc->sc_cl[channel].rxcnt ++;
1503: risrl = bus_space_read_1(iot, ioh, CL_RISRL);
1504: if (risrl & 0x80) {
1505: /* timeout, no characters */
1506: } else
1507: /* We don't need no stinkin special characters */
1508: if (risrl & 0x08) {
1509: cl_overflow(sc, channel, (long *)&sc->sc_fotime, "fifo");
1510: } else
1511: if (risrl & 0x04) {
1512: cl_parity(sc, channel);
1513: } else
1514: if (risrl & 0x02) {
1515: cl_frame(sc, channel);
1516: } else
1517: if (risrl & 0x01) {
1518: #ifdef DDB
1519: if (sc->sc_cl[channel].cl_consio)
1520: wantddb = db_console;
1521: #endif
1522: cl_break(sc, channel);
1523: }
1524: reoir = 0x08;
1525:
1526: switch (cmr & CL_RXMASK) {
1527: case CL_RXDMAINT:
1528: {
1529: int nbuf;
1530: u_int16_t cnt;
1531: int bufcomplete;
1532: u_int8_t status, dmabsts;
1533: u_int8_t risrh;
1534:
1535: risrh = bus_space_read_1(iot, ioh, CL_RISRH);
1536: dmabsts = bus_space_read_1(iot, ioh, CL_DMABSTS);
1537: nbuf = (risrh & 0x08) ? 1 : 0;
1538: bufcomplete = (risrh & 0x20) ? 1 : 0;
1539: if (nbuf == 0) {
1540: cnt = bus_space_read_2(iot, ioh, CL_ARBCNT);
1541: status = bus_space_read_1(iot, ioh, CL_ARBSTS);
1542: } else {
1543: cnt = bus_space_read_2(iot, ioh, CL_BRBCNT);
1544: status = bus_space_read_1(iot, ioh, CL_BRBSTS);
1545: }
1546: #if USE_BUFFER
1547: cl_appendbufn(sc, channel, sc->rx[nbuf], cnt);
1548: #else
1549: {
1550: int i;
1551: u_char *pbuf;
1552:
1553: tp = sc->sc_cl[channel].tty;
1554: pbuf = sc->sc_cl[channel].rx[nbuf];
1555: /* this should be done at off level */
1556: {
1557: u_int16_t rcbadru, rcbadrl;
1558: u_int8_t arbsts, brbsts;
1559: u_char *pbufs, *pbufe;
1560:
1561: rcbadru = bus_space_read_2(iot, ioh,
1562: CL_RCBADRU);
1563: rcbadrl = bus_space_read_2(iot, ioh,
1564: CL_RCBADRL);
1565: arbsts = bus_space_read_1(iot, ioh, CL_ARBSTS);
1566: brbsts = bus_space_read_1(iot, ioh, CL_BRBSTS);
1567: pbufs = sc->sc_cl[channel].rxp[nbuf];
1568: pbufe = (u_char *)(((u_long)rcbadru << 16) | (u_long)rcbadrl);
1569: cnt = pbufe - pbufs;
1570: }
1571: reoir = 0x0 | (bufcomplete) ? 0 : 0xd0;
1572: bus_space_write_1(iot, ioh, CL_REOIR, reoir);
1573:
1574: DELAY(10); /* give the chip a moment */
1575:
1576: for (i = 0; i < cnt; i++) {
1577: u_char c;
1578: c = pbuf[i];
1579: (*linesw[tp->t_line].l_rint)(c,tp);
1580: }
1581: /* this should be done at off level */
1582: if (nbuf == 0) {
1583: bus_space_write_2(iot, ioh, CL_ARBCNT,
1584: CL_BUFSIZE);
1585: bus_space_write_2(iot, ioh, CL_ARBSTS, 0x01);
1586: } else {
1587: bus_space_write_2(iot, ioh, CL_BRBCNT,
1588: CL_BUFSIZE);
1589: bus_space_write_2(iot, ioh, CL_BRBSTS, 0x01);
1590: }
1591: }
1592: #endif
1593: }
1594: bus_space_write_1(iot, ioh, CL_REOIR, reoir);
1595: break;
1596: case CL_RXINTR:
1597: fifocnt = bus_space_read_1(iot, ioh, CL_RFOC);
1598: tp = sc->sc_cl[channel].tty;
1599: bus_space_read_multi_1(iot, ioh, CL_RDR, buffer, fifocnt);
1600: if (tp == NULL) {
1601: /* if the channel is not configured,
1602: * dont send characters upstream.
1603: * also fix problem with NULL dereference
1604: */
1605: reoir = 0x00;
1606: break;
1607: }
1608:
1609: bus_space_write_1(iot, ioh, CL_REOIR, reoir);
1610: for (i = 0; i < fifocnt; i++) {
1611: u_char c;
1612: c = buffer[i];
1613: #if USE_BUFFER
1614: cl_appendbuf(sc, channel, c);
1615: #else
1616: /* does any restricitions exist on spl
1617: * for this call
1618: */
1619: (*linesw[tp->t_line].l_rint)(c,tp);
1620: #endif
1621: }
1622: break;
1623: default:
1624: log(LOG_WARNING, "cl_rxintr unknown mode %x\n", cmr);
1625: /* we probably will go to hell quickly now */
1626: bus_space_write_1(iot, ioh, CL_REOIR, 0x08);
1627: }
1628: #ifdef DDB
1629: if (wantddb != 0)
1630: Debugger();
1631: #endif
1632: return 1;
1633: }
1634:
1635: void
1636: cl_overflow(sc, channel, ptime, msg)
1637: struct clsoftc *sc;
1638: int channel;
1639: long *ptime;
1640: char *msg;
1641: {
1642: log(LOG_WARNING, "%s[%d]: %s overrun\n", sc->sc_dev.dv_xname,
1643: channel, msg);
1644: }
1645:
1646: void
1647: cl_parity(sc, channel)
1648: struct clsoftc *sc;
1649: int channel;
1650: {
1651: log(LOG_WARNING, "%s[%d]: parity error\n", sc->sc_dev.dv_xname,
1652: channel);
1653: }
1654:
1655: void
1656: cl_frame(sc, channel)
1657: struct clsoftc *sc;
1658: int channel;
1659: {
1660: log(LOG_WARNING, "%s[%d]: frame error\n", sc->sc_dev.dv_xname,
1661: channel);
1662: }
1663:
1664: void
1665: cl_break(sc, channel)
1666: struct clsoftc *sc;
1667: int channel;
1668: {
1669: #ifdef DEBUG
1670: log(LOG_WARNING, "%s[%d]: break detected\n", sc->sc_dev.dv_xname,
1671: channel);
1672: #endif
1673: }
1674:
1675: #ifdef DEBUG
1676: void
1677: cl_dumpport(struct clsoftc *sc, int channel)
1678: {
1679: bus_space_tag_t iot;
1680: bus_space_handle_t ioh;
1681: u_int8_t livr, cmr, cor1, cor2, cor3, cor4, cor5, cor6, cor7,
1682: schr1, schr2, schr3, schr4, scrl, scrh, lnxt,
1683: rbpr, rcor, tbpr, tcor, rpilr, rir, tpr, ier, ccr,
1684: dmabsts, arbsts, brbsts, atbsts, btbsts,
1685: csr, rts, dtr, rtprl, rtprh;
1686: u_int16_t rcbadru, rcbadrl, arbadru, arbadrl, arbcnt,
1687: brbadru, brbadrl, brbcnt;
1688: u_int16_t tcbadru, tcbadrl, atbadru, atbadrl, atbcnt,
1689: btbadru, btbadrl, btbcnt;
1690: int s;
1691:
1692: iot = sc->sc_iot;
1693: ioh = sc->sc_ioh;
1694:
1695: s = splcl();
1696: bus_space_write_1(iot, ioh, CL_CAR, channel);
1697: livr = bus_space_read_1(iot, ioh, CL_LIVR);
1698: cmr = bus_space_read_1(iot, ioh, CL_CMR);
1699: cor1 = bus_space_read_1(iot, ioh, CL_COR1);
1700: cor2 = bus_space_read_1(iot, ioh, CL_COR2);
1701: cor3 = bus_space_read_1(iot, ioh, CL_COR3);
1702: cor4 = bus_space_read_1(iot, ioh, CL_COR4);
1703: cor5 = bus_space_read_1(iot, ioh, CL_COR5);
1704: cor6 = bus_space_read_1(iot, ioh, CL_COR6);
1705: cor7 = bus_space_read_1(iot, ioh, CL_COR7);
1706: schr1 = bus_space_read_1(iot, ioh, CL_SCHR1);
1707: schr2 = bus_space_read_1(iot, ioh, CL_SCHR2);
1708: schr3 = bus_space_read_1(iot, ioh, CL_SCHR3);
1709: schr4 = bus_space_read_1(iot, ioh, CL_SCHR4);
1710: scrl = bus_space_read_1(iot, ioh, CL_SCRL);
1711: scrh = bus_space_read_1(iot, ioh, CL_SCRH);
1712: lnxt = bus_space_read_1(iot, ioh, CL_LNXT);
1713: rbpr = bus_space_read_1(iot, ioh, CL_RBPR);
1714: rcor = bus_space_read_1(iot, ioh, CL_RCOR);
1715: tbpr = bus_space_read_1(iot, ioh, CL_TBPR);
1716: rpilr = bus_space_read_1(iot, ioh, CL_RPILR);
1717: rir = bus_space_read_1(iot, ioh, CL_RIR);
1718: ier = bus_space_read_1(iot, ioh, CL_IER);
1719: ccr = bus_space_read_1(iot, ioh, CL_CCR);
1720: tcor = bus_space_read_1(iot, ioh, CL_TCOR);
1721: csr = bus_space_read_1(iot, ioh, CL_CSR);
1722: tpr = bus_space_read_1(iot, ioh, CL_TPR);
1723: rts = bus_space_read_1(iot, ioh, CL_MSVR_RTS);
1724: dtr = bus_space_read_1(iot, ioh, CL_MSVR_DTR);
1725: rtprl = bus_space_read_1(iot, ioh, CL_RTPRL);
1726: rtprh = bus_space_read_1(iot, ioh, CL_RTPRH);
1727: dmabsts = bus_space_read_1(iot, ioh, CL_DMABSTS);
1728: tcbadru = bus_space_read_2(iot, ioh, CL_TCBADRU);
1729: tcbadrl = bus_space_read_2(iot, ioh, CL_TCBADRL);
1730: rcbadru = bus_space_read_2(iot, ioh, CL_RCBADRU);
1731: rcbadrl = bus_space_read_2(iot, ioh, CL_RCBADRL);
1732: arbadru = bus_space_read_2(iot, ioh, CL_ARBADRU);
1733: arbadrl = bus_space_read_2(iot, ioh, CL_ARBADRL);
1734: arbcnt = bus_space_read_2(iot, ioh, CL_ARBCNT);
1735: arbsts = bus_space_read_1(iot, ioh, CL_ARBSTS);
1736: brbadru = bus_space_read_2(iot, ioh, CL_BRBADRU);
1737: brbadrl = bus_space_read_2(iot, ioh, CL_BRBADRL);
1738: brbcnt = bus_space_read_2(iot, ioh, CL_BRBCNT);
1739: brbsts = bus_space_read_1(iot, ioh, CL_BRBSTS);
1740: atbadru = bus_space_read_2(iot, ioh, CL_ATBADRU);
1741: atbadrl = bus_space_read_2(iot, ioh, CL_ATBADRL);
1742: atbcnt = bus_space_read_2(iot, ioh, CL_ATBCNT);
1743: atbsts = bus_space_read_1(iot, ioh, CL_ATBSTS);
1744: btbadru = bus_space_read_2(iot, ioh, CL_BTBADRU);
1745: btbadrl = bus_space_read_2(iot, ioh, CL_BTBADRL);
1746: btbcnt = bus_space_read_2(iot, ioh, CL_BTBCNT);
1747: btbsts = bus_space_read_1(iot, ioh, CL_BTBSTS);
1748: splx(s);
1749:
1750: printf("{ port %x livr %x cmr %x\n",
1751: channel,livr, cmr);
1752: printf("cor1 %x cor2 %x cor3 %x cor4 %x cor5 %x cor6 %x cor7 %x\n",
1753: cor1, cor2, cor3, cor4, cor5, cor6, cor7);
1754: printf("schr1 %x schr2 %x schr3 %x schr4 %x\n",
1755: schr1, schr2, schr3, schr4);
1756: printf("scrl %x scrh %x lnxt %x\n",
1757: scrl, scrh, lnxt);
1758: printf("rbpr %x rcor %x tbpr %x tcor %x\n",
1759: rbpr, rcor, tbpr, tcor);
1760: printf("rpilr %x rir %x ier %x ccr %x\n",
1761: rpilr, rir, ier, ccr);
1762: printf("tpr %x csr %x rts %x dtr %x\n",
1763: tpr, csr, rts, dtr);
1764: printf("rtprl %x rtprh %x\n",
1765: rtprl, rtprh);
1766: printf("rxcnt %x txcnt %x\n",
1767: sc->sc_cl[channel].rxcnt, sc->sc_cl[channel].txcnt);
1768: printf("dmabsts %x, tcbadru %x, tcbadrl %x, rcbadru %x, rcbadrl %x,\n",
1769: dmabsts, tcbadru, tcbadrl, rcbadru, rcbadrl );
1770: printf("arbadru %x, arbadrl %x, arbcnt %x, arbsts %x\n",
1771: arbadru, arbadrl, arbcnt, arbsts);
1772: printf("brbadru %x, brbadrl %x, brbcnt %x, brbsts %x\n",
1773: brbadru, brbadrl, brbcnt, brbsts);
1774: printf("atbadru %x, atbadrl %x, atbcnt %x, atbsts %x\n",
1775: atbadru, atbadrl, atbcnt, atbsts);
1776: printf("btbadru %x, btbadrl %x, btbcnt %x, btbsts %x\n",
1777: btbadru, btbadrl, btbcnt, btbsts);
1778: printf("}\n");
1779: }
1780: #endif
CVSweb