Annotation of sys/arch/mvme88k/dev/vx.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: vx.c,v 1.38 2006/07/28 21:46:02 miod Exp $ */
2: /*
3: * Copyright (c) 1999 Steve Murphree, Jr.
4: * 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: * 3. The name of the author may not be used to endorse or promote products
15: * derived from this software without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29: /* This card lives in D16 space */
30: #define __BUS_SPACE_RESTRICT_D16__
31:
32: #include <sys/param.h>
33: #include <sys/ioctl.h>
34: #include <sys/proc.h>
35: #include <sys/tty.h>
36: #include <sys/uio.h>
37: #include <sys/systm.h>
38: #include <sys/time.h>
39: #include <sys/device.h>
40: #include <sys/syslog.h>
41:
42: #include <machine/autoconf.h>
43: #include <machine/conf.h>
44: #include <machine/cpu.h>
45: #include <machine/psl.h>
46:
47: #include <dev/cons.h>
48:
49: #include <mvme88k/dev/vme.h>
50: #include <mvme88k/dev/vxreg.h>
51:
52: #define splvx() spltty()
53:
54: struct vx_info {
55: struct tty *tty;
56: u_char vx_swflags;
57: int vx_linestatus;
58: int open;
59: int waiting;
60: u_char vx_speed;
61: u_char read_pending;
62: struct wring *wringp;
63: struct rring *rringp;
64: };
65:
66: struct vxsoftc {
67: struct device sc_dev;
68: struct vx_info sc_info[NVXPORTS];
69: struct vxreg *vx_reg;
70: vaddr_t board_vaddr;
71: struct channel *channel;
72: char channel_number;
73: struct packet sc_bppwait_pkt;
74: void *sc_bppwait_pktp;
75: struct intrhand sc_ih;
76: int sc_vec;
77: struct envelope *elist_head, *elist_tail;
78: struct packet *plist_head, *plist_tail;
79: };
80:
81: int vxmatch(struct device *, void *, void *);
82: void vxattach(struct device *, struct device *, void *);
83:
84: struct cfattach vx_ca = {
85: sizeof(struct vxsoftc), vxmatch, vxattach
86: };
87:
88: struct cfdriver vx_cd = {
89: NULL, "vx", DV_TTY
90: };
91:
92: int bpp_send(struct vxsoftc *, void *, int);
93: void ccode(struct vxsoftc *, int, char);
94: int create_channels(struct vxsoftc *);
95: void create_free_queue(struct vxsoftc *);
96: short dtr_ctl(struct vxsoftc *, int, int);
97: int env_isvalid(struct envelope *);
98: struct envelope *find_status_packet(struct vxsoftc *, struct packet *);
99: short flush_ctl(struct vxsoftc *, int, int);
100: struct envelope *get_cmd_tail(struct vxsoftc *);
101: void *get_free_envelope(struct vxsoftc *);
102: void *get_free_packet(struct vxsoftc *);
103: struct envelope *get_next_envelope(struct vxsoftc *, struct envelope *);
104: struct packet *get_packet(struct vxsoftc *, struct envelope *);
105: struct envelope *get_status_head(struct vxsoftc *);
106: void put_free_envelope(struct vxsoftc *, void *);
107: void put_free_packet(struct vxsoftc *, void *);
108: void read_chars(struct vxsoftc *, int);
109: void read_wakeup(struct vxsoftc *, int);
110: short rts_ctl(struct vxsoftc *, int, int);
111: void set_status_head(struct vxsoftc *, void *);
112: void vx_break(struct vxsoftc *, int);
113: int vx_ccparam(struct vxsoftc *, struct termios *, int);
114: int vx_event(struct vxsoftc *, struct packet *);
115: void vx_frame(struct vxsoftc *, int);
116: int vx_init(struct vxsoftc *);
117: int vx_intr(void *);
118: int vx_mctl(dev_t, int, int);
119: void vx_overflow(struct vxsoftc *, int, long *, u_char *);
120: int vx_param(struct tty *, struct termios *);
121: int vx_poll(struct vxsoftc *, struct packet *);
122: void vxputc(struct vxsoftc *, int, u_char);
123: int vx_sintr(struct vxsoftc *);
124: void vxstart(struct tty *tp);
125: u_short vxtspeed(int);
126: void vx_unblock(struct tty *);
127:
128: /* flags for bpp_send() */
129: #define NOWAIT 0
130: #define WAIT 1
131:
132: #define VX_UNIT(x) (minor(x) / NVXPORTS)
133: #define VX_PORT(x) (minor(x) % NVXPORTS)
134:
135: /*
136: * Convert dual-ported physical addresse to host virtual address, and the
137: * opposite.
138: */
139: #define VIRTUAL(addr) (((addr) & 0xffff) + sc->board_vaddr)
140: #define PHYSICAL(addr) \
141: (((addr - sc->board_vaddr) & 0xffff) | LOCAL_DPMEM_ADDRESS)
142:
143: #if 0
144: #define LO(x) (u_short)((unsigned long)x & 0x0000FFFF)
145: #define HI(x) (u_short)((unsigned long)x >> 16)
146: #else
147: #define LO(x) (u_short)(x)
148: #define HI(x) (LOCAL_DPMEM_ADDRESS >> 16)
149: #endif
150:
151: struct tty *
152: vxtty(dev_t dev)
153: {
154: int unit, port;
155: struct vxsoftc *sc;
156:
157: unit = VX_UNIT(dev);
158: if (unit >= vx_cd.cd_ndevs ||
159: (sc = (struct vxsoftc *)vx_cd.cd_devs[unit]) == NULL) {
160: return (NULL);
161: }
162: port = VX_PORT(dev);
163: return sc->sc_info[port].tty;
164: }
165:
166: int
167: vxmatch(struct device *parent, void *self, void *aux)
168: {
169: struct vxreg *vx_reg;
170: struct confargs *ca = aux;
171: bus_space_tag_t iot = ca->ca_iot;
172: bus_space_handle_t ioh;
173: int rc;
174:
175: if (bus_space_map(iot, ca->ca_paddr, 0x10000, 0, &ioh) != 0)
176: return 0;
177: vx_reg = (struct vxreg *)bus_space_vaddr(iot, ioh);
178: rc = badaddr((vaddr_t)&vx_reg->ipc_cr, 1);
179: bus_space_unmap(iot, ioh, 0x10000);
180:
181: return rc == 0;
182: }
183:
184: void
185: vxattach(struct device *parent, struct device *self, void *aux)
186: {
187: struct vxsoftc *sc = (struct vxsoftc *)self;
188: struct confargs *ca = aux;
189: bus_space_tag_t iot = ca->ca_iot;
190: bus_space_handle_t ioh;
191:
192: if (ca->ca_vec < 0) {
193: printf(": no more interrupts!\n");
194: return;
195: }
196: if (ca->ca_ipl < 0)
197: ca->ca_ipl = IPL_TTY;
198:
199: if (bus_space_map(iot, ca->ca_paddr, 0x10000, 0, &ioh) != 0) {
200: printf(": can't map registers!\n");
201: return;
202: }
203:
204: /* set up dual port memory and registers and init */
205: sc->board_vaddr = (vaddr_t)bus_space_vaddr(iot, ioh);
206: sc->vx_reg = (struct vxreg *)sc->board_vaddr;
207: sc->channel = (struct channel *)(sc->board_vaddr + 0x0100);
208: sc->sc_vec = ca->ca_vec;
209:
210: printf("\n");
211:
212: if (create_channels(sc) != 0) {
213: printf("%s: failed to create channel %d\n",
214: sc->sc_dev.dv_xname, sc->channel->channel_number);
215: return;
216: }
217: if (vx_init(sc) != 0) {
218: printf("%s: failed to initialize\n", sc->sc_dev.dv_xname);
219: return;
220: }
221:
222: /* enable interrupts */
223: sc->sc_ih.ih_fn = vx_intr;
224: sc->sc_ih.ih_arg = sc;
225: sc->sc_ih.ih_wantframe = 0;
226: sc->sc_ih.ih_ipl = IPL_TTY;
227:
228: vmeintr_establish(ca->ca_vec, &sc->sc_ih, self->dv_xname);
229: }
230:
231: short
232: dtr_ctl(struct vxsoftc *sc, int port, int on)
233: {
234: struct packet pkt;
235:
236: bzero(&pkt, sizeof(struct packet));
237: pkt.command = CMD_IOCTL;
238: pkt.ioctl_cmd_l = IOCTL_TCXONC;
239: pkt.command_pipe_number = sc->channel_number;
240: pkt.status_pipe_number = sc->channel_number;
241: pkt.device_number = port;
242: if (on) {
243: pkt.ioctl_arg_l = 6; /* assert DTR */
244: } else {
245: pkt.ioctl_arg_l = 7; /* negate DTR */
246: }
247:
248: return bpp_send(sc, &pkt, WAIT);
249: }
250:
251: short
252: rts_ctl(struct vxsoftc *sc, int port, int on)
253: {
254: struct packet pkt;
255:
256: bzero(&pkt, sizeof(struct packet));
257: pkt.command = CMD_IOCTL;
258: pkt.ioctl_cmd_l = IOCTL_TCXONC;
259: pkt.command_pipe_number = sc->channel_number;
260: pkt.status_pipe_number = sc->channel_number;
261: pkt.device_number = port;
262: if (on) {
263: pkt.ioctl_arg_l = 4; /* assert RTS */
264: } else {
265: pkt.ioctl_arg_l = 5; /* negate RTS */
266: }
267:
268: return bpp_send(sc, &pkt, WAIT);
269: }
270:
271: #if 0
272: short
273: flush_ctl(struct vxsoftc *sc, int port, int which)
274: {
275: struct packet pkt;
276:
277: bzero(&pkt, sizeof(struct packet));
278: pkt.command = CMD_IOCTL;
279: pkt.ioctl_cmd_l = IOCTL_TCFLSH;
280: pkt.command_pipe_number = sc->channel_number;
281: pkt.status_pipe_number = sc->channel_number;
282: pkt.device_number = port;
283: pkt.ioctl_arg_l = which; /* 0=input, 1=output, 2=both */
284:
285: return bpp_send(sc, &pkt, WAIT);
286: }
287: #endif
288:
289: int
290: vx_mctl(dev_t dev, int bits, int how)
291: {
292: int s, unit, port;
293: struct vxsoftc *sc;
294: struct vx_info *vxt;
295: u_char msvr;
296:
297: unit = VX_UNIT(dev);
298: port = VX_PORT(dev);
299: sc = (struct vxsoftc *)vx_cd.cd_devs[unit];
300: vxt = &sc->sc_info[port];
301:
302: s = splvx();
303: switch (how) {
304: case DMSET:
305: if (bits & TIOCM_RTS) {
306: rts_ctl(sc, port, 1);
307: vxt->vx_linestatus |= TIOCM_RTS;
308: } else {
309: rts_ctl(sc, port, 0);
310: vxt->vx_linestatus &= ~TIOCM_RTS;
311: }
312: if (bits & TIOCM_DTR) {
313: dtr_ctl(sc, port, 1);
314: vxt->vx_linestatus |= TIOCM_DTR;
315: } else {
316: dtr_ctl(sc, port, 0);
317: vxt->vx_linestatus &= ~TIOCM_DTR;
318: }
319: break;
320: case DMBIC:
321: if (bits & TIOCM_RTS) {
322: rts_ctl(sc, port, 0);
323: vxt->vx_linestatus &= ~TIOCM_RTS;
324: }
325: if (bits & TIOCM_DTR) {
326: dtr_ctl(sc, port, 0);
327: vxt->vx_linestatus &= ~TIOCM_DTR;
328: }
329: break;
330:
331: case DMBIS:
332: if (bits & TIOCM_RTS) {
333: rts_ctl(sc, port, 1);
334: vxt->vx_linestatus |= TIOCM_RTS;
335: }
336: if (bits & TIOCM_DTR) {
337: dtr_ctl(sc, port, 1);
338: vxt->vx_linestatus |= TIOCM_DTR;
339: }
340: break;
341:
342: case DMGET:
343: bits = 0;
344: msvr = vxt->vx_linestatus;
345: if (msvr & TIOCM_DSR) {
346: bits |= TIOCM_DSR;
347: }
348: if (msvr & TIOCM_CD) {
349: bits |= TIOCM_CD;
350: }
351: if (msvr & TIOCM_CTS) {
352: bits |= TIOCM_CTS;
353: }
354: if (msvr & TIOCM_DTR) {
355: bits |= TIOCM_DTR;
356: }
357: if (msvr & TIOCM_RTS) {
358: bits |= TIOCM_RTS;
359: }
360: break;
361: }
362:
363: splx(s);
364:
365: #if 0
366: bits = 0;
367: bits |= TIOCM_DTR;
368: bits |= TIOCM_RTS;
369: bits |= TIOCM_CTS;
370: bits |= TIOCM_CD;
371: bits |= TIOCM_DSR;
372: #endif
373: return (bits);
374: }
375:
376: int
377: vxopen(dev_t dev, int flag, int mode, struct proc *p)
378: {
379: int s, unit, port, error;
380: struct vx_info *vxt;
381: struct vxsoftc *sc;
382: struct tty *tp;
383: struct packet opkt;
384: u_short code;
385:
386: unit = VX_UNIT(dev);
387: port = VX_PORT(dev);
388: if (unit >= vx_cd.cd_ndevs ||
389: (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
390: return (ENODEV);
391: }
392: vxt = &sc->sc_info[port];
393:
394: #if 0
395: flush_ctl(sc, port, 2);
396: #endif
397:
398: bzero(&opkt, sizeof(struct packet));
399: opkt.command_pipe_number = sc->channel_number;
400: opkt.status_pipe_number = sc->channel_number;
401: opkt.command = CMD_OPEN;
402: opkt.device_number = port;
403:
404: if ((error = bpp_send(sc, &opkt, WAIT)) != 0) {
405: #ifdef DEBUG_VXT
406: printf("unit %d, port %d, ", unit, port);
407: printf("error = %d\n", error);
408: #endif
409: return (ENXIO);
410: }
411:
412: code = opkt.event_code;
413:
414: s = splvx();
415: if (vxt->tty) {
416: tp = vxt->tty;
417: } else {
418: tp = vxt->tty = ttymalloc();
419: }
420:
421: /* set line status */
422: tp->t_state |= TS_CARR_ON;
423: if (code & E_DCD) {
424: tp->t_state |= TS_CARR_ON;
425: vxt->vx_linestatus |= TIOCM_CD;
426: }
427: if (code & E_DSR) {
428: vxt->vx_linestatus |= TIOCM_DSR;
429: }
430: if (code & E_CTS) {
431: vxt->vx_linestatus |= TIOCM_CTS;
432: }
433:
434: tp->t_oproc = vxstart;
435: tp->t_param = vx_param;
436: tp->t_dev = dev;
437:
438: if ((tp->t_state & TS_ISOPEN) == 0) {
439: tp->t_state |= TS_WOPEN;
440: ttychars(tp);
441: if (tp->t_ispeed == 0) {
442: /*
443: * only when cleared do we reset to defaults.
444: */
445: tp->t_iflag = TTYDEF_IFLAG;
446: tp->t_oflag = TTYDEF_OFLAG;
447: tp->t_lflag = TTYDEF_LFLAG;
448: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
449: tp->t_cflag = TTYDEF_CFLAG;
450: }
451: /*
452: * do these all the time
453: */
454: if (vxt->vx_swflags & TIOCFLAG_CLOCAL)
455: tp->t_cflag |= CLOCAL;
456: if (vxt->vx_swflags & TIOCFLAG_CRTSCTS)
457: tp->t_cflag |= CRTSCTS;
458: if (vxt->vx_swflags & TIOCFLAG_MDMBUF)
459: tp->t_cflag |= MDMBUF;
460: vx_param(tp, &tp->t_termios);
461: ttsetwater(tp);
462:
463: (void)vx_mctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
464:
465: tp->t_state |= TS_CARR_ON;
466: } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
467: splx(s);
468: return (EBUSY);
469: }
470:
471: /*
472: * Reset the tty pointer, as there could have been a dialout
473: * use of the tty with a dialin open waiting.
474: */
475: tp->t_dev = dev;
476: vxt->open = 1;
477: splx(s);
478: return (*linesw[tp->t_line].l_open)(dev, tp);
479: }
480:
481: int
482: vx_param(struct tty *tp, struct termios *t)
483: {
484: int unit, port;
485: struct vxsoftc *sc;
486: dev_t dev;
487:
488: dev = tp->t_dev;
489: unit = VX_UNIT(dev);
490: if (unit >= vx_cd.cd_ndevs ||
491: (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
492: return (ENODEV);
493: }
494: port = VX_PORT(dev);
495: tp->t_ispeed = t->c_ispeed;
496: tp->t_ospeed = t->c_ospeed;
497: tp->t_cflag = t->c_cflag;
498: vx_ccparam(sc, t, port);
499: vx_unblock(tp);
500: return 0;
501: }
502:
503: int
504: vxclose(dev_t dev, int flag, int mode, struct proc *p)
505: {
506: int unit, port;
507: struct tty *tp;
508: struct vx_info *vxt;
509: struct vxsoftc *sc;
510: int s;
511: struct packet cpkt;
512:
513: unit = VX_UNIT(dev);
514: if (unit >= vx_cd.cd_ndevs ||
515: (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
516: return (ENODEV);
517: }
518: port = VX_PORT(dev);
519: vxt = &sc->sc_info[port];
520: #if 0
521: flush_ctl(sc, port, 2); /* flush both input and output */
522: #endif
523:
524: tp = vxt->tty;
525: (*linesw[tp->t_line].l_close)(tp, flag);
526:
527: s = splvx();
528:
529: if ((tp->t_cflag & HUPCL) != 0) {
530: rts_ctl(sc, port, 0);
531: dtr_ctl(sc, port, 0);
532: }
533:
534: bzero(&cpkt, sizeof(struct packet));
535: cpkt.command_pipe_number = sc->channel_number;
536: cpkt.status_pipe_number = sc->channel_number;
537: cpkt.command = CMD_CLOSE;
538: cpkt.device_number = port;
539: bpp_send(sc, &cpkt, NOWAIT);
540:
541: vxt->open = 0;
542: splx(s);
543: ttyclose(tp);
544:
545: return (0);
546: }
547:
548: void
549: read_wakeup(struct vxsoftc *sc, int port)
550: {
551: struct packet rwp;
552: struct vx_info *volatile vxt;
553:
554: vxt = &sc->sc_info[port];
555: /*
556: * If we already have a read_wakeup paket
557: * for this port, do nothing.
558: */
559: if (vxt->read_pending != 0)
560: return;
561: else
562: vxt->read_pending = 1;
563:
564: bzero(&rwp, sizeof(struct packet));
565: rwp.command_pipe_number = sc->channel_number;
566: rwp.status_pipe_number = sc->channel_number;
567: rwp.command = CMD_READW;
568: rwp.device_number = port;
569:
570: /*
571: * Do not wait. Characters will be transferred
572: * to (*linesw[tp->t_line].l_rint)(c, tp); by
573: * vx_intr() (IPC will notify via interrupt)
574: */
575: bpp_send(sc, &rwp, NOWAIT);
576: }
577:
578: int
579: vxread(dev_t dev, struct uio *uio, int flag)
580: {
581: int unit, port;
582: struct tty *tp;
583: struct vx_info *volatile vxt;
584: struct vxsoftc *volatile sc;
585:
586: unit = VX_UNIT(dev);
587: if (unit >= vx_cd.cd_ndevs ||
588: (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
589: return (ENODEV);
590: }
591: port = VX_PORT(dev);
592: vxt = &sc->sc_info[port];
593: tp = vxt->tty;
594: if (!tp)
595: return ENXIO;
596: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
597: }
598:
599: int
600: vxwrite(dev_t dev, struct uio *uio, int flag)
601: {
602: int unit, port;
603: struct tty *tp;
604: struct vx_info *vxt;
605: struct vxsoftc *sc;
606: struct wring *wp;
607: struct packet wwp;
608: u_short get, put;
609:
610: unit = VX_UNIT(dev);
611: if (unit >= vx_cd.cd_ndevs ||
612: (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
613: return (ENODEV);
614: }
615: port = VX_PORT(dev);
616: vxt = &sc->sc_info[port];
617: tp = vxt->tty;
618: if (!tp)
619: return ENXIO;
620:
621: wp = sc->sc_info[port].wringp;
622: get = wp->get;
623: put = wp->put;
624: if ((put + 1) == get) {
625: bzero(&wwp, sizeof(struct packet));
626: wwp.command_pipe_number = sc->channel_number;
627: wwp.status_pipe_number = sc->channel_number;
628: wwp.command = CMD_WRITEW;
629: wwp.device_number = port;
630: if (bpp_send(sc, &wwp, WAIT))
631: return (ENXIO);
632: }
633:
634: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
635: }
636:
637: int
638: vxioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
639: {
640: int error;
641: int unit, port;
642: struct tty *tp;
643: struct vx_info *vxt;
644: struct vxsoftc *sc;
645:
646: unit = VX_UNIT(dev);
647: if (unit >= vx_cd.cd_ndevs ||
648: (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
649: return (ENODEV);
650: }
651: port = VX_PORT(dev);
652: vxt = &sc->sc_info[port];
653: tp = vxt->tty;
654: if (!tp)
655: return ENXIO;
656:
657: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
658: if (error >= 0)
659: return (error);
660:
661: error = ttioctl(tp, cmd, data, flag, p);
662: if (error >= 0)
663: return (error);
664:
665: switch (cmd) {
666: case TIOCSBRK:
667: /* */
668: break;
669:
670: case TIOCCBRK:
671: /* */
672: break;
673:
674: case TIOCSDTR:
675: vx_mctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
676: break;
677:
678: case TIOCCDTR:
679: vx_mctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
680: break;
681:
682: case TIOCMSET:
683: vx_mctl(dev, *(int *)data, DMSET);
684: break;
685:
686: case TIOCMBIS:
687: vx_mctl(dev, *(int *)data, DMBIS);
688: break;
689:
690: case TIOCMBIC:
691: vx_mctl(dev, *(int *)data, DMBIC);
692: break;
693:
694: case TIOCMGET:
695: *(int *)data = vx_mctl(dev, 0, DMGET);
696: break;
697:
698: case TIOCGFLAGS:
699: *(int *)data = vxt->vx_swflags;
700: break;
701:
702: case TIOCSFLAGS:
703: error = suser(p, 0);
704: if (error != 0)
705: return (EPERM);
706:
707: vxt->vx_swflags = *(int *)data;
708: vxt->vx_swflags &= /* only allow valid flags */
709: (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
710: break;
711:
712: default:
713: return (ENOTTY);
714: }
715:
716: return 0;
717: }
718:
719: int
720: vxstop(struct tty *tp, int flag)
721: {
722: int s;
723:
724: s = splvx();
725: if (tp->t_state & TS_BUSY) {
726: if ((tp->t_state & TS_TTSTOP) == 0)
727: tp->t_state |= TS_FLUSH;
728: }
729: splx(s);
730: return 0;
731: }
732:
733: void
734: vxputc(struct vxsoftc *sc, int port, u_char c)
735: {
736: struct wring *wp;
737:
738: wp = sc->sc_info[port].wringp;
739: wp->data[wp->put++ & (WRING_BUF_SIZE - 1)] = c;
740: wp->put &= (WRING_BUF_SIZE - 1);
741: }
742:
743: u_short
744: vxtspeed(int speed)
745: {
746: switch (speed) {
747: case B0:
748: return VB0;
749: case B50:
750: return VB50;
751: case B75:
752: return VB75;
753: case B110:
754: return VB110;
755: case B134:
756: return VB134;
757: case B150:
758: return VB150;
759: case B200:
760: return VB200;
761: case B300:
762: return VB300;
763: case B600:
764: return VB600;
765: case B1200:
766: return VB1200;
767: case B1800:
768: return VB1800;
769: case B2400:
770: return VB2400;
771: case B4800:
772: return VB4800;
773: case B9600:
774: return VB9600;
775: case B19200:
776: return VB19200;
777: case B38400:
778: return VB38400;
779: default:
780: return VB9600;
781: }
782: }
783:
784: int
785: vx_ccparam(struct vxsoftc *sc, struct termios *par, int port)
786: {
787: int imask = 0, s;
788: int cflag;
789: struct packet pkt;
790:
791: if (par->c_ospeed == 0) {
792: s = splvx();
793: /* disconnect, drop RTS DTR stop receiver */
794: rts_ctl(sc, port, 0);
795: dtr_ctl(sc, port, 0);
796: splx(s);
797: return (0xff);
798: }
799:
800: bzero(&pkt, sizeof(struct packet));
801: pkt.command = CMD_IOCTL;
802: pkt.ioctl_cmd_l = IOCTL_TCGETA;
803: pkt.command_pipe_number = sc->channel_number;
804: pkt.status_pipe_number = sc->channel_number;
805: pkt.device_number = port;
806: if (bpp_send(sc, &pkt, WAIT))
807: return 0xff;
808:
809: cflag = pkt.pb.tio.c_cflag;
810: cflag |= vxtspeed(par->c_ospeed);
811:
812: switch (par->c_cflag & CSIZE) {
813: case CS5:
814: cflag |= VCS5;
815: imask = 0x1F;
816: break;
817: case CS6:
818: cflag |= VCS6;
819: imask = 0x3F;
820: break;
821: case CS7:
822: cflag |= VCS7;
823: imask = 0x7F;
824: break;
825: default:
826: cflag |= VCS8;
827: imask = 0xFF;
828: }
829:
830: if (par->c_cflag & PARENB) cflag |= VPARENB;
831: else cflag &= ~VPARENB;
832: if (par->c_cflag & PARODD) cflag |= VPARODD;
833: else cflag &= ~VPARODD;
834: if (par->c_cflag & CREAD) cflag |= VCREAD;
835: else cflag &= ~VCREAD;
836: if (par->c_cflag & CLOCAL) cflag |= VCLOCAL;
837: else cflag &= ~VCLOCAL;
838: if (par->c_cflag & HUPCL) cflag |= VHUPCL;
839: else cflag &= ~VHUPCL;
840:
841: pkt.command = CMD_IOCTL;
842: pkt.ioctl_cmd_l = IOCTL_TCSETA;
843: pkt.command_pipe_number = sc->channel_number;
844: pkt.status_pipe_number = sc->channel_number;
845: pkt.device_number = port;
846: pkt.pb.tio.c_cflag = cflag;
847: if (bpp_send(sc, &pkt, WAIT))
848: return 0xff;
849:
850: return imask;
851: }
852:
853: void
854: vx_unblock(struct tty *tp)
855: {
856: tp->t_state &= ~TS_FLUSH;
857: if (tp->t_outq.c_cc != 0)
858: vxstart(tp);
859: }
860:
861: void
862: vxstart(struct tty *tp)
863: {
864: dev_t dev;
865: struct vxsoftc *sc;
866: struct wring *wp;
867: int cc, port, unit, s, cnt, i;
868: u_short get, put;
869: char buffer[256];
870:
871: dev = tp->t_dev;
872: port = VX_PORT(dev);
873: unit = VX_UNIT(dev);
874: if (unit >= vx_cd.cd_ndevs ||
875: (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
876: return;
877: }
878:
879: if ((tp->t_state & TS_ISOPEN) == 0)
880: return;
881:
882: s = splvx();
883: if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_FLUSH)) == 0) {
884: tp->t_state |= TS_BUSY;
885: wp = sc->sc_info[port].wringp;
886: get = wp->get;
887: put = wp->put;
888: cc = tp->t_outq.c_cc;
889: while (cc > 0) {
890: cnt = min(sizeof buffer, cc);
891: cnt = q_to_b(&tp->t_outq, buffer, cnt);
892: buffer[cnt] = 0;
893: for (i = 0; i < cnt; i++) {
894: vxputc(sc, port, buffer[i]);
895: }
896: cc -= cnt;
897: }
898: tp->t_state &= ~TS_BUSY;
899: }
900: splx(s);
901: }
902:
903: void
904: read_chars(struct vxsoftc *sc, int port)
905: {
906: /*
907: * This routine is called by vx_intr() when there are
908: * characters in the read ring. It will process one
909: * cooked line, put the chars in the line disipline ring,
910: * and then return. The characters may then
911: * be read by vxread.
912: */
913: struct vx_info *vxt;
914: struct rring *rp;
915: struct tty *tp;
916: u_short get, put;
917: int frame_count, i, open;
918: char c;
919:
920: vxt = &sc->sc_info[port];
921: tp = vxt->tty;
922: rp = vxt->rringp;
923: open = vxt->open;
924: get = rp->get;
925: put = rp->put;
926: #ifdef DEBUG_VXT
927: printf("read_chars() get=%d, put=%d ", get, put);
928: printf("open = %d ring at 0x%x\n", open, rp);
929: #endif
930: while (get != put) {
931: frame_count = rp->data[rp->get++ & (RRING_BUF_SIZE - 1)];
932: rp->get &= (RRING_BUF_SIZE - 1);
933: for (i = 0; i < frame_count; i++) {
934: c = rp->data[rp->get++ & (RRING_BUF_SIZE - 1)];
935: rp->get &= (RRING_BUF_SIZE - 1);
936: if (open)
937: (*linesw[tp->t_line].l_rint)(c, tp);
938: }
939: c = rp->data[rp->get++ & (RRING_BUF_SIZE - 1)];
940: rp->get &= (RRING_BUF_SIZE - 1);
941: if (!(c & DELIMITER)) {
942: vx_frame(sc, port);
943: break;
944: } else {
945: break;
946: }
947: get = rp->get;
948: put = rp->put;
949: }
950: vxt->read_pending = 0;
951: read_wakeup(sc, port);
952: }
953:
954: void
955: ccode(struct vxsoftc *sc, int port, char c)
956: {
957: struct vx_info *vxt;
958: struct tty *tp;
959:
960: tp = vxt->tty;
961: (*linesw[tp->t_line].l_rint)(c, tp);
962: }
963:
964: int
965: vx_intr(void *arg)
966: {
967: struct vxsoftc *sc = arg;
968: struct envelope *envp, *next_envp;
969: struct packet *pktp, pkt;
970: int valid;
971: short cmd;
972: u_char port;
973:
974: while (env_isvalid(get_status_head(sc))) {
975: pktp = get_packet(sc, get_status_head(sc));
976: valid = env_isvalid(get_status_head(sc));
977: cmd = pktp->command;
978: port = pktp->device_number;
979: /*
980: * If we are waiting on this packet, store the info
981: * so bpp_send can process the packet
982: */
983: if (sc->sc_bppwait_pktp == pktp)
984: d16_bcopy(pktp, &sc->sc_bppwait_pkt, sizeof(struct packet));
985:
986: d16_bcopy(pktp, &pkt, sizeof(struct packet));
987: next_envp = get_next_envelope(sc, get_status_head(sc));
988: envp = get_status_head(sc);
989: /* return envelope and packet to the free queues */
990: put_free_envelope(sc, envp);
991: put_free_packet(sc, pktp);
992: /* mark new status pipe head pointer */
993: set_status_head(sc, next_envp);
994: /* if it was valid, process packet */
995: switch (cmd) {
996: case CMD_READW:
997: #ifdef DEBUG_VXT
998: printf("READW Packet\n");
999: #endif
1000: read_chars(sc, port);
1001: break;
1002: case CMD_WRITEW:
1003: #ifdef DEBUG_VXT
1004: printf("WRITEW Packet\n"); /* Still don't know XXXsmurph */
1005: #endif
1006: break;
1007: case CMD_EVENT:
1008: #ifdef DEBUG_VXT
1009: printf("EVENT Packet\n");
1010: #endif
1011: vx_event(sc, &pkt);
1012: break;
1013: case CMD_PROCESSED:
1014: #ifdef DEBUG_VXT
1015: printf("CMD_PROCESSED Packet\n");
1016: #endif
1017: break;
1018: default:
1019: #ifdef DEBUG_VXT
1020: printf("Other packet 0x%x\n", cmd);
1021: #endif
1022: break;
1023: }
1024: }
1025: return 1;
1026: }
1027:
1028: int
1029: vx_event(struct vxsoftc *sc, struct packet *evntp)
1030: {
1031: u_short code = evntp->event_code;
1032: struct packet evnt;
1033: struct vx_info *vxt;
1034:
1035: vxt = &sc->sc_info[evntp->device_number];
1036:
1037: if (code & E_INTR) {
1038: ccode(sc, evntp->device_number, CINTR);
1039: }
1040: if (code & E_QUIT) {
1041: ccode(sc, evntp->device_number, CQUIT);
1042: }
1043: if (code & E_HUP) {
1044: rts_ctl(sc, evntp->device_number, 0);
1045: dtr_ctl(sc, evntp->device_number, 0);
1046: }
1047: if (code & E_DCD) {
1048: vxt->vx_linestatus |= TIOCM_CD;
1049: }
1050: if (code & E_DSR) {
1051: vxt->vx_linestatus |= TIOCM_DSR;
1052: }
1053: if (code & E_CTS) {
1054: vxt->vx_linestatus |= TIOCM_CTS;
1055: }
1056: if (code & E_LOST_DCD) {
1057: vxt->vx_linestatus &= ~TIOCM_CD;
1058: }
1059: if (code & E_LOST_DSR) {
1060: vxt->vx_linestatus &= ~TIOCM_DSR;
1061: }
1062: if (code & E_LOST_CTS) {
1063: vxt->vx_linestatus &= ~TIOCM_CTS;
1064: }
1065: if (code & E_PR_FAULT) {
1066: /* do something... */
1067: }
1068: if (code & E_PR_POUT) {
1069: /* do something... */
1070: }
1071: if (code & E_PR_SELECT) {
1072: /* do something... */
1073: }
1074: if (code & E_SWITCH) {
1075: /* do something... */
1076: }
1077: if (code & E_BREAK) {
1078: vx_break(sc, evntp->device_number);
1079: }
1080:
1081: /* send an event packet back to the device */
1082: bzero(&evnt, sizeof(struct packet));
1083: evnt.command = CMD_EVENT;
1084: evnt.device_number = evntp->device_number;
1085: evnt.command_pipe_number = sc->channel_number;
1086: /* return status on same channel */
1087: evnt.status_pipe_number = sc->channel_number;
1088: /* send packet to the firmware */
1089: bpp_send(sc, &evnt, NOWAIT);
1090:
1091: return 1;
1092: }
1093:
1094: void
1095: vx_overflow(struct vxsoftc *sc, int port, long *ptime, u_char *msg)
1096: {
1097: log(LOG_WARNING, "%s port %d: overrun\n",
1098: sc->sc_dev.dv_xname, port);
1099: }
1100:
1101: void
1102: vx_frame(struct vxsoftc *sc, int port)
1103: {
1104: log(LOG_WARNING, "%s port %d: frame error\n",
1105: sc->sc_dev.dv_xname, port);
1106: }
1107:
1108: void
1109: vx_break(struct vxsoftc *sc, int port)
1110: {
1111: /*
1112: * No need to check for a ddb break, as the console can never be on
1113: * this hardware.
1114: */
1115: log(LOG_WARNING, "%s port %d: break detected\n",
1116: sc->sc_dev.dv_xname, port);
1117: }
1118:
1119: /*
1120: * Initialization and Buffered Pipe Protocol (BPP) code
1121: */
1122:
1123: void
1124: create_free_queue(struct vxsoftc *sc)
1125: {
1126: int i;
1127: struct envelope *envp, env;
1128: struct packet *pktp, pkt;
1129:
1130: envp = (struct envelope *)VIRTUAL(ENVELOPE_AREA);
1131: sc->elist_head = envp;
1132: for (i = 1; i <= NENVELOPES; i++) {
1133: bzero(&env, sizeof(struct envelope));
1134: if (i == NENVELOPES)
1135: env.link = NULL;
1136: else
1137: env.link = ENVELOPE_AREA + i * sizeof(struct envelope);
1138: env.packet_ptr = NULL;
1139: env.valid_flag = 0;
1140: d16_bcopy(&env, envp, sizeof(struct envelope));
1141: envp++;
1142: }
1143: sc->elist_tail = --envp;
1144:
1145: pktp = (struct packet *)VIRTUAL(PACKET_AREA);
1146: sc->plist_head = pktp;
1147: for (i = 1; i <= NPACKETS; i++) {
1148: bzero(&pkt, sizeof(struct packet));
1149: if (i == NPACKETS)
1150: pkt.link = NULL;
1151: else
1152: pkt.link = PACKET_AREA + i * sizeof(struct packet);
1153: d16_bcopy(&pkt, pktp, sizeof(struct packet));
1154: pktp++;
1155: }
1156: sc->plist_tail = --pktp;
1157: }
1158:
1159: void *
1160: get_free_envelope(struct vxsoftc *sc)
1161: {
1162: struct envelope *envp;
1163: paddr_t link;
1164:
1165: envp = sc->elist_head;
1166: /* pick envelope next pointer from the envelope itself */
1167: d16_bcopy((const void *)&envp->link, &link, sizeof link);
1168: sc->elist_head = (struct envelope *)VIRTUAL(link);
1169: d16_bzero(envp, sizeof(struct envelope));
1170:
1171: return envp;
1172: }
1173:
1174: void
1175: put_free_envelope(struct vxsoftc *sc, void *ep)
1176: {
1177: struct envelope *envp = (struct envelope *)ep;
1178: u_long link;
1179:
1180: #if 0
1181: d16_bzero(envp, sizeof(struct envelope));
1182: #endif
1183: /* put envelope next pointer in the envelope itself */
1184: link = PHYSICAL((vaddr_t)envp);
1185: d16_bzero((void *)&envp->link, sizeof envp->link);
1186: d16_bcopy(&link, (void *)&sc->elist_tail->link, sizeof link);
1187:
1188: sc->elist_tail = envp;
1189: }
1190:
1191: void *
1192: get_free_packet(struct vxsoftc *sc)
1193: {
1194: struct packet *pktp;
1195: paddr_t link;
1196:
1197: pktp = sc->plist_head;
1198: /* pick packet next pointer from the packet itself */
1199: d16_bcopy((const void *)&pktp->link, &link, sizeof link);
1200: sc->plist_head = (struct packet *)VIRTUAL(link);
1201: d16_bzero(pktp, sizeof(struct packet));
1202:
1203: return pktp;
1204: }
1205:
1206: void
1207: put_free_packet(struct vxsoftc *sc, void *pp)
1208: {
1209: struct packet *pktp = (struct packet *)pp;
1210: u_long link;
1211:
1212: #if 0
1213: d16_bzero(pktp, sizeof(struct packet));
1214: #endif
1215: pktp->command = CMD_PROCESSED;
1216: /* put packet next pointer in the packet itself */
1217: link = PHYSICAL((vaddr_t)pktp);
1218: d16_bzero((void *)&pktp->link, sizeof pktp->link);
1219: d16_bcopy(&link, (void *)&sc->plist_tail->link, sizeof link);
1220:
1221: sc->plist_tail = pktp;
1222: }
1223:
1224: /*
1225: * This is the nitty gritty. All the rest if this code
1226: * was hell to come by. Getting this right from the
1227: * Moto manual took *time*!
1228: */
1229: int
1230: create_channels(struct vxsoftc *sc)
1231: {
1232: u_long envp;
1233: u_short status;
1234: u_short tas;
1235: struct vxreg *ipc_csr = sc->vx_reg;
1236:
1237: /* wait for busy bit to clear */
1238: while ((ipc_csr->ipc_cr & IPC_CR_BUSY))
1239: ;
1240:
1241: create_free_queue(sc);
1242:
1243: /* set up channel header. we only want one */
1244: tas = ipc_csr->ipc_tas;
1245: while (!(tas & IPC_TAS_VALID_STATUS)) {
1246: envp = PHYSICAL((vaddr_t)get_free_envelope(sc));
1247: sc->channel->command_pipe_head_ptr_h = HI(envp);
1248: sc->channel->command_pipe_head_ptr_l = LO(envp);
1249: sc->channel->command_pipe_tail_ptr_h =
1250: sc->channel->command_pipe_head_ptr_h;
1251: sc->channel->command_pipe_tail_ptr_l =
1252: sc->channel->command_pipe_head_ptr_l;
1253: envp = PHYSICAL((vaddr_t)get_free_envelope(sc));
1254: sc->channel->status_pipe_head_ptr_h = HI(envp);
1255: sc->channel->status_pipe_head_ptr_l = LO(envp);
1256: sc->channel->status_pipe_tail_ptr_h =
1257: sc->channel->status_pipe_head_ptr_h;
1258: sc->channel->status_pipe_tail_ptr_l =
1259: sc->channel->status_pipe_head_ptr_l;
1260: sc->channel->interrupt_level = IPL_TTY;
1261: sc->channel->interrupt_vec = sc->sc_vec;
1262: sc->channel->channel_priority = 0;
1263: sc->channel->channel_number = 0;
1264: sc->channel->valid = 1;
1265: sc->channel->address_modifier = 0x8d; /* A32/D16 supervisor data access */
1266: sc->channel->datasize = 0; /* 32 bit data mode */
1267:
1268: /* loop until TAS bit is zero */
1269: while ((ipc_csr->ipc_tas & IPC_TAS_TAS))
1270: ;
1271: ipc_csr->ipc_tas |= IPC_TAS_TAS;
1272: /* load address of channel header */
1273: ipc_csr->ipc_addrh = HI(CHANNEL_H);
1274: ipc_csr->ipc_addrl = LO(CHANNEL_H);
1275: /* load address modifier reg (supervisor data access) */
1276: ipc_csr->ipc_amr = 0x8d;
1277: /* load tas with create channel command */
1278: ipc_csr->ipc_tas |= IPC_CSR_CREATE;
1279: /* set vaild command bit */
1280: ipc_csr->ipc_tas |= IPC_TAS_VALID_CMD;
1281: /* notify IPC of the CSR command */
1282: ipc_csr->ipc_cr |= IPC_CR_ATTEN;
1283:
1284: /* loop until IPC sets valid status bit */
1285: delay(5000);
1286: tas = ipc_csr->ipc_tas;
1287: }
1288:
1289: /* save the status */
1290: status = ipc_csr->ipc_sr;
1291: /* set COMMAND COMPLETE bit */
1292: ipc_csr->ipc_tas |= IPC_TAS_COMPLETE;
1293: /* notify IPC that we are through */
1294: ipc_csr->ipc_cr |= IPC_CR_ATTEN;
1295: /* check and see if the channel was created */
1296: if (status == 0 && sc->channel->valid) {
1297: sc->channel_number = sc->channel->channel_number;
1298: #ifdef DEBUG_VXT
1299: printf("%s: created channel %d\n", sc->sc_dev.dv_xname,
1300: sc->channel->channel_number);
1301: #endif
1302: return 0;
1303: } else {
1304: switch (status) {
1305: case 0x0000:
1306: printf("%s: channel not valid\n",
1307: sc->sc_dev.dv_xname);
1308: break;
1309: case 0xFFFF:
1310: printf("%s: invalid CSR command\n",
1311: sc->sc_dev.dv_xname);
1312: break;
1313: case 0xC000:
1314: printf("%s: could not read channel structure\n",
1315: sc->sc_dev.dv_xname);
1316: break;
1317: case 0x8000:
1318: printf("%s: could not write channel structure\n",
1319: sc->sc_dev.dv_xname);
1320: break;
1321: default:
1322: printf("%s: unknown IPC CSR command error 0x%x\n",
1323: sc->sc_dev.dv_xname, status);
1324: break;
1325: }
1326: return 1;
1327: }
1328: }
1329:
1330: struct envelope *
1331: get_next_envelope(struct vxsoftc *sc, struct envelope *thisenv)
1332: {
1333: paddr_t ptr;
1334:
1335: d16_bcopy((const void*)&thisenv->link, &ptr, sizeof ptr);
1336:
1337: return (struct envelope *)VIRTUAL(ptr);
1338: }
1339:
1340: int
1341: env_isvalid(struct envelope *thisenv)
1342: {
1343: return (int)thisenv->valid_flag;
1344: }
1345:
1346: struct envelope *
1347: get_cmd_tail(struct vxsoftc *sc)
1348: {
1349: paddr_t retaddr;
1350:
1351: retaddr = sc->channel->command_pipe_tail_ptr_h << 16;
1352: retaddr += sc->channel->command_pipe_tail_ptr_l;
1353: return (struct envelope *)VIRTUAL(retaddr);
1354: }
1355:
1356: struct envelope *
1357: get_status_head(struct vxsoftc *sc)
1358: {
1359: paddr_t retaddr;
1360:
1361: retaddr = sc->channel->status_pipe_head_ptr_h << 16;
1362: retaddr += sc->channel->status_pipe_head_ptr_l;
1363: return (struct envelope *)VIRTUAL(retaddr);
1364: }
1365:
1366: void
1367: set_status_head(struct vxsoftc *sc, void *envp)
1368: {
1369: paddr_t ptr;
1370:
1371: ptr = PHYSICAL((vaddr_t)envp);
1372: sc->channel->status_pipe_head_ptr_h = HI(ptr);
1373: sc->channel->status_pipe_head_ptr_l = LO(ptr);
1374: }
1375:
1376: struct packet *
1377: get_packet(struct vxsoftc *sc, struct envelope *thisenv)
1378: {
1379: paddr_t baseaddr;
1380:
1381: if (thisenv == NULL)
1382: return NULL;
1383:
1384: /*
1385: * packet ptr returned on status pipe is only last two bytes
1386: * so we must supply the full address based on the board address.
1387: * This also works for all envelopes because every address is an
1388: * offset to the board address.
1389: */
1390: d16_bcopy((const void *)&thisenv->packet_ptr, &baseaddr, sizeof baseaddr);
1391: return (struct packet *)VIRTUAL(baseaddr);
1392: }
1393:
1394: /*
1395: * Send a command via BPP
1396: */
1397: int
1398: bpp_send(struct vxsoftc *sc, void *pkt, int wait_flag)
1399: {
1400: struct envelope *envp;
1401: struct packet *pktp;
1402: paddr_t ptr;
1403: int tmo;
1404:
1405: /* load up packet in dual port mem */
1406: pktp = get_free_packet(sc);
1407: d16_bcopy(pkt, pktp, sizeof(struct packet));
1408:
1409: envp = get_cmd_tail(sc);
1410: ptr = PHYSICAL((vaddr_t)get_free_envelope(sc)); /* put a NULL env on the tail */
1411: sc->channel->command_pipe_tail_ptr_h = HI(ptr);
1412: sc->channel->command_pipe_tail_ptr_l = LO(ptr);
1413: d16_bcopy(&ptr, (void *)&envp->link, sizeof envp->link);
1414: ptr = PHYSICAL((vaddr_t)pktp);
1415: d16_bcopy(&ptr, (void *)&envp->packet_ptr, sizeof envp->packet_ptr);
1416: envp->valid_flag = 1;
1417:
1418: sc->vx_reg->ipc_cr |= IPC_CR_ATTEN;
1419:
1420: /* wait for a packet to return */
1421: if (wait_flag == NOWAIT)
1422: return 0;
1423:
1424: tmo = 0;
1425: while (pktp->command != CMD_PROCESSED) {
1426: #ifdef DEBUG_VXT
1427: printf("Polling for packet 0x%x in envelope 0x%x...\n", pktp, envp);
1428: #endif
1429: vx_intr(sc);
1430: if (++tmo > 20) {
1431: printf("%s: bpp_send pkt %x env %x timed out %d\n",
1432: sc->sc_dev.dv_xname, pktp, envp, pktp->command);
1433: return ETIMEDOUT;
1434: }
1435: delay(5000);
1436: }
1437: d16_bcopy(pktp, pkt, sizeof(struct packet));
1438: return pktp->error_l;
1439: }
1440:
1441: /*
1442: * BPP commands
1443: */
1444:
1445: int
1446: vx_init(struct vxsoftc *sc)
1447: {
1448: int i;
1449: int error;
1450: struct init_info *infp, inf;
1451: paddr_t wringp, rringp;
1452: struct packet init;
1453: struct packet evnt;
1454:
1455: /* init wait queue */
1456: d16_bzero(&sc->sc_bppwait_pkt, sizeof(struct packet));
1457: sc->sc_bppwait_pktp = NULL;
1458: /* set up init_info array */
1459: wringp = WRING_AREA;
1460: rringp = RRING_AREA;
1461: infp = (struct init_info *)VIRTUAL(INIT_INFO_AREA);
1462:
1463: for (i = 0; i < NVXPORTS; i++) {
1464: bzero(&inf, sizeof(struct init_info));
1465: inf.write_ring_ptr_h = HI(wringp);
1466: inf.write_ring_ptr_l = LO(wringp);
1467: sc->sc_info[i].wringp = (struct wring *)VIRTUAL(wringp);
1468: inf.read_ring_ptr_h = HI(rringp);
1469: inf.read_ring_ptr_l = LO(rringp);
1470: sc->sc_info[i].rringp = (struct rring *)VIRTUAL(rringp);
1471: #ifdef DEBUG_VXT
1472: printf("write at 0x%8x, read at 0x%8x\n", wringp, rringp);
1473: #endif
1474: inf.write_ring_size = WRING_DATA_SIZE;
1475: inf.read_ring_size = RRING_DATA_SIZE;
1476: inf.def_termio.c_iflag = VBRKINT;
1477: inf.def_termio.c_oflag = 0;
1478: inf.def_termio.c_cflag = (VB9600 | VCS8);
1479:
1480: inf.def_termio.c_lflag = VISIG; /* enable signal processing */
1481: inf.def_termio.c_line = 1; /* raw line discipline */
1482: inf.def_termio.c_cc[0] = CINTR;
1483: inf.def_termio.c_cc[1] = CQUIT;
1484: inf.def_termio.c_cc[2] = CERASE;
1485: inf.def_termio.c_cc[3] = CKILL;
1486: inf.def_termio.c_cc[4] = CEOF;
1487: inf.def_termio.c_cc[5] = CEOL;
1488: d16_bcopy(&inf, infp, sizeof(struct init_info));
1489: wringp += sizeof(struct wring);
1490: rringp += sizeof(struct rring);
1491: infp++;
1492: }
1493:
1494: /* set up init_packet */
1495: bzero(&init, sizeof(struct packet));
1496: init.command = CMD_INIT;
1497: init.command_pipe_number = sc->channel_number;
1498: /* return status on the same channel */
1499: init.status_pipe_number = sc->channel_number;
1500: init.interrupt_level = IPL_TTY;
1501: init.interrupt_vec = sc->sc_vec;
1502: init.init_info_ptr_h = HI(INIT_INFO_AREA);
1503: init.init_info_ptr_l = LO(INIT_INFO_AREA);
1504:
1505: /* send packet to the firmware and wait for completion */
1506: if ((error = bpp_send(sc, &init, WAIT)) != 0)
1507: return error;
1508:
1509: /* send one event packet to each device */
1510: for (i = 0; i < NVXPORTS; i++) {
1511: bzero(&evnt, sizeof(struct packet));
1512: evnt.command = CMD_EVENT;
1513: evnt.device_number = i;
1514: evnt.command_pipe_number = sc->channel_number;
1515: /* return status on same channel */
1516: evnt.status_pipe_number = sc->channel_number;
1517: /* send packet to the firmware */
1518: bpp_send(sc, &evnt, NOWAIT);
1519: }
1520:
1521: return 0;
1522: }
CVSweb