home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Computer Consoles Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)mp.c 7.17 (Berkeley) 5/16/91
- */
-
- #include "mp.h"
- #if NMP > 0
- /*
- * Multi Protocol Communications Controller (MPCC).
- * Asynchronous Terminal Protocol Support.
- */
- #include "sys/param.h"
- #include "sys/ioctl.h"
- #include "sys/tty.h"
- #include "sys/user.h"
- #include "sys/map.h"
- #include "sys/buf.h"
- #include "sys/conf.h"
- #include "sys/file.h"
- #include "sys/errno.h"
- #include "sys/syslog.h"
- #include "sys/vmmac.h"
- #include "sys/kernel.h"
- #include "sys/clist.h"
-
- #include "../include/pte.h"
- #include "../include/mtpr.h"
-
- #include "../vba/vbavar.h"
- #include "../vba/mpreg.h"
-
- #define MPCHUNK 16
- #define MPPORT(n) ((n) & 0xf)
- #define MPUNIT(n) ((n) >> 4)
-
- /*
- * Driver information for auto-configuration stuff.
- */
- int mpprobe(), mpattach(), mpintr();
- struct vba_device *mpinfo[NMP];
- long mpstd[] = { 0 };
- struct vba_driver mpdriver =
- { mpprobe, 0, mpattach, 0, mpstd, "mp", mpinfo };
-
- int mpstart();
- int mpparam();
- struct mpevent *mpparam2();
- struct mpevent *mp_getevent();
-
- /*
- * The following structure is needed to deal with mpcc's convoluted
- * method for locating it's mblok structures (hold your stomach).
- * When an mpcc is reset at boot time it searches host memory
- * looking for a string that says ``ThIs Is MpCc''. The mpcc
- * then reads the structure to locate the pointer to it's mblok
- * structure (you can wretch now).
- */
- struct mpbogus {
- char s[12]; /* `ThIs Is MpCc'' */
- u_char status;
- u_char unused;
- u_short magic;
- struct mblok *mb;
- struct mblok *mbloks[NMP]; /* can support at most 16 mpcc's */
- } mpbogus = { 'T','h','I','s',' ','I','s',' ','M','p','C','c' };
-
- /*
- * Software state per unit.
- */
- struct mpsoftc {
- u_int ms_ivec; /* interrupt vector */
- u_int ms_softCAR; /* software carrier for async */
- struct mblok *ms_mb; /* mpcc status area */
- struct vb_buf ms_buf; /* vba resources for ms_mb */
- struct hxmtl ms_hxl[MPMAXPORT];/* host transmit list */
- struct asyncparam ms_async[MPMAXPORT][MPINSET];/* async structs */
- char ms_cbuf[MPMAXPORT][MPOUTSET][CBSIZE];/* input character buffers */
- } mp_softc[NMP];
-
- struct speedtab
- mpspeedtab[] = {
- 9600, M9600, /* baud rate = 9600 */
- 4800, M4800, /* baud rate = 4800 */
- 2400, M2400, /* baud rate = 2400 */
- 1800, M1800, /* baud rate = 1800 */
- 1200, M1200, /* baud rate = 1200 */
- 600, M600, /* baud rate = 600 */
- 300, M300, /* baud rate = 300 */
- 200, M200, /* baud rate = 200 */
- 150, M150, /* baud rate = 150 */
- 134, M134_5, /* baud rate = 134.5 */
- 110, M110, /* baud rate = 110 */
- 75, M75, /* baud rate = 75 */
- 50, M50, /* baud rate = 50 */
- 0, M0, /* baud rate = 0 */
- 2000, M2000, /* baud rate = 2000 */
- 3600, M3600, /* baud rate = 3600 */
- 7200, M7200, /* baud rate = 7200 */
- 19200, M19200, /* baud rate = 19,200 */
- 24000, M24000, /* baud rate = 24,000 */
- 28400, M28400, /* baud rate = 28,400 */
- 37800, M37800, /* baud rate = 37,800 */
- 40300, M40300, /* baud rate = 40,300 */
- 48000, M48000, /* baud rate = 48,000 */
- 52000, M52000, /* baud rate = 52,000 */
- 56800, M56800, /* baud rate = 56,800 */
- EXTA, MEXTA, /* baud rate = Ext A */
- EXTB, MEXTB, /* baud rate = Ext B */
- -1, -1,
- };
-
- struct tty mp_tty[NMP*MPCHUNK];
- #ifndef lint
- int nmp = NMP*MPCHUNK;
- #endif
-
- int ttrstrt();
-
- mpprobe(reg, vi)
- caddr_t reg;
- struct vba_device *vi;
- {
- register int br, cvec;
- register struct mpsoftc *ms;
-
- #ifdef lint
- br = 0; cvec = br; br = cvec;
- mpintr(0);
- mpdlintr(0);
- #endif
- if (badaddr(reg, 2))
- return (0);
- ms = &mp_softc[vi->ui_unit];
- /*
- * Allocate page tables and mblok
- * structure (mblok in non-cached memory).
- */
- if (vbainit(&ms->ms_buf, sizeof (struct mblok), VB_32BIT) == 0) {
- printf("mp%d: vbainit failed\n", vi->ui_unit);
- return (0);
- }
- ms->ms_mb = (struct mblok *)ms->ms_buf.vb_rawbuf;
- ms->ms_ivec = MPINTRBASE + 2*vi->ui_unit; /* XXX */
- br = 0x14, cvec = ms->ms_ivec; /* XXX */
- return (sizeof (*reg));
- }
-
- mpattach(vi)
- register struct vba_device *vi;
- {
- register struct mpsoftc *ms = &mp_softc[vi->ui_unit];
-
- ms->ms_softCAR = vi->ui_flags;
- /*
- * Setup pointer to mblok, initialize bogus
- * status block used by mpcc to locate the pointer
- * and then poke the mpcc to get it to search host
- * memory to find mblok pointer.
- */
- mpbogus.mbloks[vi->ui_unit] = (struct mblok *)ms->ms_buf.vb_physbuf;
- *(short *)vi->ui_addr = 0x100; /* magic */
- }
-
- /*
- * Open an mpcc port.
- */
- /* ARGSUSED */
- mpopen(dev, mode)
- dev_t dev;
- {
- register struct tty *tp;
- register struct mpsoftc *ms;
- int error, s, port, unit, mpu;
- struct vba_device *vi;
- struct mpport *mp;
- struct mpevent *ev;
-
- unit = minor(dev);
- mpu = MPUNIT(unit);
- if (mpu >= NMP || (vi = mpinfo[mpu]) == 0 || vi->ui_alive == 0)
- return (ENXIO);
- tp = &mp_tty[unit];
- if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
- return (EBUSY);
- ms = &mp_softc[mpu];
- port = MPPORT(unit);
- if (ms->ms_mb->mb_proto[port] != MPPROTO_ASYNC ||
- ms->ms_mb->mb_status != MP_OPOPEN)
- return (ENXIO);
- mp = &ms->ms_mb->mb_port[port]; /* host mpcc struct */
- s = spl8();
- /*
- * serialize open and close events
- */
- while ((mp->mp_flags & MP_PROGRESS) || ((tp->t_state & TS_WOPEN) &&
- !(mode&O_NONBLOCK) && !(tp->t_cflag&CLOCAL)))
- if (error = tsleep((caddr_t)&tp->t_canq, TTIPRI | PCATCH,
- ttopen, 0)) {
- splx(s);
- return (error);
- }
- restart:
- tp->t_state |= TS_WOPEN;
- tp->t_addr = (caddr_t)ms;
- tp->t_oproc = mpstart;
- tp->t_param = mpparam;
- tp->t_dev = dev;
- if ((tp->t_state & TS_ISOPEN) == 0) {
- ttychars(tp);
- if (tp->t_ispeed == 0) {
- tp->t_ispeed = TTYDEF_SPEED;
- tp->t_ospeed = TTYDEF_SPEED;
- tp->t_iflag = TTYDEF_IFLAG;
- tp->t_oflag = TTYDEF_OFLAG;
- tp->t_lflag = TTYDEF_LFLAG;
- tp->t_cflag = TTYDEF_CFLAG;
- }
- /*
- * Initialize port state: init MPCC interface
- * structures for port and setup modem control.
- */
- error = mpportinit(ms, mp, port);
- if (error)
- goto bad;
- ev = mpparam2(tp, &tp->t_termios);
- if (ev == 0) {
- error = ENOBUFS;
- goto bad;
- }
- mp->mp_flags |= MP_PROGRESS;
- mpcmd(ev, EVCMD_OPEN, 0, ms->ms_mb, port);
- /*
- * wait for port to start
- */
- while (mp->mp_proto != MPPROTO_ASYNC)
- if (error = tsleep((caddr_t)&tp->t_canq,
- TTIPRI | PCATCH, ttopen, 0))
- goto bad;
- ttsetwater(tp);
- mp->mp_flags &= ~MP_PROGRESS;
- }
- while ((mode&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
- (tp->t_state & TS_CARR_ON) == 0) {
- if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
- ttopen, 0))
- goto bad;
- /*
- * a mpclose() might have disabled port. if so restart
- */
- if (mp->mp_proto != MPPROTO_ASYNC)
- goto restart;
- tp->t_state |= TS_WOPEN;
- }
- error = (*linesw[tp->t_line].l_open)(dev,tp);
- done:
- splx(s);
- /*
- * wakeup those processes waiting for the open to complete
- */
- wakeup((caddr_t)&tp->t_canq);
- return (error);
- bad:
- tp->t_state &= ~TS_WOPEN;
- goto done;
- }
-
- /*
- * Close an mpcc port.
- */
- /* ARGSUSED */
- mpclose(dev, flag)
- dev_t dev;
- {
- register struct tty *tp;
- register struct mpport *mp;
- register struct mpevent *ev;
- int s, port, unit, error = 0;
- struct mblok *mb;
-
- unit = minor(dev);
- tp = &mp_tty[unit];
- port = MPPORT(unit);
- mb = mp_softc[MPUNIT(unit)].ms_mb;
- mp = &mb->mb_port[port];
- s = spl8();
- if (mp->mp_flags & MP_PROGRESS) {
- if (mp->mp_flags & MP_REMBSY) {
- mp->mp_flags &= ~MP_REMBSY;
- splx(s);
- return (0);
- }
- while (mp->mp_flags & MP_PROGRESS)
- if (error = tsleep((caddr_t)&tp->t_canq,
- TTIPRI | PCATCH, ttclos, 0)) {
- splx(s);
- return (error);
- }
- }
- mp->mp_flags |= MP_PROGRESS;
- (*linesw[tp->t_line].l_close)(tp, flag);
- ev = mp_getevent(mp, unit, 1);
- if (ev == 0) {
- error = ENOBUFS;
- mp->mp_flags &= ~MP_PROGRESS;
- goto out;
- }
- if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0)
- mpmodem(unit, MMOD_OFF);
- else
- mpmodem(unit, MMOD_ON);
- mpcmd(ev, EVCMD_CLOSE, 0, mb, port);
- error = ttyclose(tp);
- out:
- if (mp->mp_flags & MP_REMBSY)
- mpclean(mb, port);
- else
- while (mp->mp_flags & MP_PROGRESS && error == 0)
- error = tsleep((caddr_t)&tp->t_canq, TTIPRI | PCATCH,
- ttclos, 0);
- splx(s);
- return (error);
- }
-
- /*
- * Read from an mpcc port.
- */
- mpread(dev, uio, flag)
- dev_t dev;
- struct uio *uio;
- {
- struct tty *tp;
-
- tp = &mp_tty[minor(dev)];
- return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
- }
-
- /*
- * Write to an mpcc port.
- */
- mpwrite(dev, uio, flag)
- dev_t dev;
- struct uio *uio;
- {
- struct tty *tp;
-
- tp = &mp_tty[minor(dev)];
- return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
- }
-
- /*
- * Ioctl for a mpcc port
- */
- mpioctl(dev, cmd, data, flag)
- dev_t dev;
- caddr_t data;
- {
- register struct tty *tp;
- register struct mpsoftc *ms;
- register struct mpport *mp;
- register struct mpevent *ev;
- int s, port, error, unit;
- struct mblok *mb;
-
- unit = minor(dev);
- tp = &mp_tty[unit];
- ms = &mp_softc[MPUNIT(unit)];
- mb = ms->ms_mb;
- port = MPPORT(unit);
- mp = &mb->mb_port[port];
- if (mp->mp_proto != MPPROTO_ASYNC)
- return(ENXIO);
- error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
- if (error >= 0)
- return (error);
- error = ttioctl(tp, cmd, data, flag);
- if (error >= 0)
- return (error);
- switch (cmd) {
- case TIOCSBRK: /* send break */
- case TIOCCBRK: /* clear break */
- s = spl8();
- while (mp->mp_flags & MP_IOCTL) {
- if (error = tsleep((caddr_t)&tp->t_canq,
- TTIPRI | PCATCH, ttyout, 0)) {
- splx(s);
- return (error);
- }
- if (mp->mp_proto != MPPROTO_ASYNC) {
- splx(s);
- return (ENXIO);
- }
- }
- ev = mp_getevent(mp, unit, 0);
- if (ev) {
- mp->mp_flags |= MP_IOCTL;
- mpcmd(ev, EVCMD_IOCTL,
- (cmd == TIOCSBRK ? A_BRKON : A_BRKOFF), mb, port);
- } else
- error = ENOBUFS;
- splx(s);
- break;
- case TIOCSDTR: /* set dtr control line */
- break;
- case TIOCCDTR: /* clear dtr control line */
- break;
- default:
- error = ENOTTY;
- break;
- }
- return (error);
- }
-
- mpparam(tp, t)
- struct tty *tp;
- struct termios *t;
- {
- register struct mpevent *ev;
- int unit = minor(tp->t_dev);
- struct mpsoftc *ms = &mp_softc[MPUNIT(unit)];
- struct mblok *mb = ms->ms_mb;
-
- ev = mpparam2(tp, t);
- if (ev == 0)
- return (ENOBUFS);
- mpcmd(ev, EVCMD_IOCTL, A_CHGALL, mb, MPPORT(unit));
- return (0);
- }
-
- struct mpevent *
- mpparam2(tp, t)
- register struct tty *tp;
- struct termios *t;
- {
- register struct mpevent *ev;
- register struct mpport *mp;
- int unit = minor(tp->t_dev);
- struct mblok *mb;
- struct mpsoftc *ms;
- register struct asyncparam *asp;
- int port, speedcode;
-
- ms = &mp_softc[MPUNIT(unit)];
- mb = ms->ms_mb;
- port = MPPORT(unit);
- mp = &mb->mb_port[port];
- ev = mp_getevent(mp, unit, 0); /* XXX */
- speedcode = ttspeedtab(t->c_ospeed, mpspeedtab);
- if (ev == 0 || speedcode < 0) {
- printf("mp mpunit %d port %d param2 failed ev: %x speed %d, wanted %d\n",
- MPUNIT(unit), port, ev, speedcode, t->c_ospeed);
- return (0); /* XXX */
- }
- /* YUCK */
- asp = &ms->ms_async[port][mp->mp_on?mp->mp_on-1:MPINSET-1];
- asp->ap_xon = t->c_cc[VSTART];
- asp->ap_xoff = t->c_cc[VSTOP];
- if (!(t->c_iflag&IXON) || (asp->ap_xon == _POSIX_VDISABLE) ||
- (asp->ap_xoff == _POSIX_VDISABLE))
- asp->ap_xena = MPA_DIS;
- else
- asp->ap_xena = MPA_ENA;
- asp->ap_xany = ((t->c_iflag & IXANY) ? MPA_ENA : MPA_DIS);
- #ifdef notnow
- if (t->t_cflag&CSIZE) == CS8) {
- #endif
- asp->ap_data = MPCHAR_8;
- asp->ap_parity = MPPAR_NONE;
- #ifdef notnow
- } else {
- asp->ap_data = MPCHAR_7;
- if ((t->c_flags & (EVENP|ODDP)) == ODDP) /* XXX */
- asp->ap_parity = MPPAR_ODD;
- else
- asp->ap_parity = MPPAR_EVEN;
- }
- #endif
- asp->ap_loop = MPA_DIS; /* disable loopback */
- asp->ap_rtimer = A_RCVTIM; /* default receive timer */
- if (t->c_ospeed == B110)
- asp->ap_stop = MPSTOP_2;
- else
- asp->ap_stop = MPSTOP_1;
- if (t->c_ospeed == 0) {
- tp->t_state |= TS_HUPCLS;
- setm(&asp->ap_modem, 0, DROP);
- seti(&asp->ap_intena, A_DCD);
- return (ev);
- }
- if (t->c_ospeed == EXTA || t->c_ospeed == EXTB)
- asp->ap_baud = M19200;
- else
- asp->ap_baud = speedcode;
- if (1 || ms->ms_softCAR & (1<<port)) /* XXX HARDWIRE FOR NOW */
- setm(&asp->ap_modem, A_DTR, ASSERT);
- else
- setm(&asp->ap_modem, A_DTR, AUTO);
- seti(&asp->ap_intena, A_DCD);
- return(ev);
- }
-
- mpstart(tp)
- register struct tty *tp;
- {
- register struct mpevent *ev;
- register struct mpport *mp;
- struct mblok *mb;
- struct mpsoftc *ms;
- int port, unit, xcnt, n, s, i;
- struct hxmtl *hxp;
- struct clist outq;
-
- s = spl8();
- unit = minor(tp->t_dev);
- ms = &mp_softc[MPUNIT(unit)];
- mb = ms->ms_mb;
- port = MPPORT(unit);
- mp = &mb->mb_port[port];
- hxp = &ms->ms_hxl[port];
- xcnt = 0;
- outq = tp->t_outq;
- for (i = 0; i < MPXMIT; i++) {
- if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
- break;
- if (outq.c_cc <= tp->t_lowat) {
- if (tp->t_state & TS_ASLEEP) {
- tp->t_state &= ~TS_ASLEEP;
- wakeup((caddr_t)&tp->t_outq);
- }
- if (tp->t_wsel) {
- selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
- tp->t_wsel = 0;
- tp->t_state &= ~TS_WCOLL;
- }
- }
- if (outq.c_cc == 0)
- break;
- /*
- * If we're not currently busy outputting,
- * and there is data to be output, set up
- * port transmit structure to send to mpcc.
- */
- if (1) /* || tp->t_flags & (RAW|LITOUT)) XXX FIX */
- n = ndqb(&outq, 0);
- else {
- n = ndqb(&outq, 0200);
- if (n == 0) {
- if (xcnt > 0)
- break;
- n = getc(&outq);
- timeout(ttrstrt, (caddr_t)tp, (n&0177)+6);
- tp->t_state |= TS_TIMEOUT;
- break;
- }
- }
- hxp->dblock[i] = (caddr_t)kvtophys(outq.c_cf);
- hxp->size[i] = n;
- xcnt++; /* count of xmts to send */
- ndadvance(&outq, n);
- }
- /*
- * If data to send, poke mpcc.
- */
- if (xcnt) {
- ev = mp_getevent(mp, unit, 0);
- if (ev == 0) {
- tp->t_state &= ~(TS_BUSY|TS_TIMEOUT);
- } else {
- tp->t_state |= TS_BUSY;
- ev->ev_count = xcnt;
- mpcmd(ev, EVCMD_WRITE, 0, mb, MPPORT(unit));
- }
- }
- splx(s);
- }
-
- /*
- * Advance cc bytes from q but don't free memory.
- */
- ndadvance(q, cc)
- register struct clist *q;
- register cc;
- {
- register struct cblock *bp;
- char *end;
- int rem, s;
-
- s = spltty();
- if (q->c_cc <= 0)
- goto out;
- while (cc>0 && q->c_cc) {
- bp = (struct cblock *)((int)q->c_cf & ~CROUND);
- if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
- end = q->c_cl;
- } else {
- end = (char *)((int)bp + sizeof (struct cblock));
- }
- rem = end - q->c_cf;
- if (cc >= rem) {
- cc -= rem;
- q->c_cc -= rem;
- q->c_cf = bp->c_next->c_info;
- } else {
- q->c_cc -= cc;
- q->c_cf += cc;
- break;
- }
- }
- if (q->c_cc <= 0) {
- q->c_cf = q->c_cl = NULL;
- q->c_cc = 0;
- }
- out:
- splx(s);
- }
-
- /*
- * Stop output on a line, e.g. for ^S/^Q or output flush.
- */
- /* ARGSUSED */
- mpstop(tp, rw)
- register struct tty *tp;
- int rw;
- {
- register struct mpport *mp;
- register struct mpevent *ev;
- int unit = minor(tp->t_dev);
- int port;
- struct mblok *mb;
- int s;
-
- s = spl8();
- if (tp->t_state & TS_BUSY) {
- if ((tp->t_state & TS_TTSTOP) == 0) {
- tp->t_state |= TS_FLUSH;
- port = MPPORT(unit);
- mb = mp_softc[MPUNIT(unit)].ms_mb;
- mp = &mb->mb_port[port];
- ev = mp_getevent(mp, unit, 0);
- if (ev == 0) {
- splx(s);
- return;
- }
- mpcmd(ev, EVCMD_WRITE, A_FLUSH, mb, port);
- }
- }
- splx(s);
- }
-
- /*
- * Initialize an async port's MPCC state.
- */
- mpportinit(ms, mp, port)
- register struct mpsoftc *ms;
- register struct mpport *mp;
- int port;
- {
- register struct mpevent *ev;
- register int i;
- caddr_t ptr;
-
- mp->mp_on = mp->mp_off = 0;
- mp->mp_nextrcv = 0;
- mp->mp_flags = 0;
- ev = &mp->mp_recvq[0];
- for (i = 0; ev < &mp->mp_recvq[MPINSET]; ev++, i++) {
- ev->ev_status = EVSTATUS_FREE;
- ev->ev_cmd = 0;
- ev->ev_opts = 0;
- ev->ev_error = 0;
- ev->ev_flags = 0;
- ev->ev_count = 0;
- ev->ev_un.hxl = (struct hxmtl *) kvtophys(&ms->ms_hxl[port]);
- ev->ev_params = (caddr_t) kvtophys(&ms->ms_async[port][i]);
- }
- ev = &mp->mp_sendq[0];
- for (i = 0; ev < &mp->mp_sendq[MPOUTSET]; ev++, i++) {
- /* init so that L2 can't send any events */
- /* to host until open has completed */
- ev->ev_status = EVSTATUS_FREE;
- ev->ev_cmd = 0;
- ev->ev_opts = 0;
- ev->ev_error = 0;
- ev->ev_flags = 0;
- ev->ev_count = 0;
- ptr = (caddr_t) &ms->ms_cbuf[port][i][0];
- ev->ev_un.rcvblk = (u_char *)kvtophys(ptr);
- ev->ev_params = (caddr_t) kvtophys(ptr);
- }
- return (0);
- }
-
- /*
- * Send an event to an mpcc.
- */
- mpcmd(ev, cmd, flags, mb, port)
- register struct mpevent *ev;
- struct mblok *mb;
- {
- int s;
-
- s = spl8();
- /* move host values to inbound entry */
- ev->ev_cmd = cmd;
- ev->ev_opts = flags;
- /* show event ready for mpcc */
- ev->ev_status = EVSTATUS_GO;
- mpintmpcc(mb, port);
- splx(s);
- }
-
- /*
- * Return the next available event entry for the indicated port.
- */
- struct mpevent *
- mp_getevent(mp, unit, cls_req)
- register struct mpport *mp;
- int unit;
- int cls_req;
- {
- register struct mpevent *ev;
- int i, s;
-
- s = spl8();
- ev = &mp->mp_recvq[mp->mp_on];
- if (ev->ev_status != EVSTATUS_FREE)
- goto bad;
- /*
- * If not a close request, verify one extra
- * event is available for closing the port.
- */
- if (!cls_req) {
- if ((i = mp->mp_on + 1) >= MPINSET)
- i = 0;
- if (mp->mp_recvq[i].ev_status != EVSTATUS_FREE)
- goto bad;
- }
- /* init inbound fields marking this entry as busy */
- ev->ev_cmd = 0;
- ev->ev_opts = 0;
- ev->ev_error = 0;
- ev->ev_flags = 0;
- ev->ev_count = 0;
- ev->ev_status = EVSTATUS_BUSY;
- /* adjust pointer to next available inbound entry */
- adjptr(mp->mp_on, MPINSET);
- splx(s);
- return (ev);
- bad:
- splx(s);
- log(LOG_ERR, "mp%d: port%d, out of events\n",
- MPUNIT(unit), MPPORT(unit));
- return ((struct mpevent *)0);
- }
-
- mpmodem(unit, flag)
- int unit, flag;
- {
- struct mpsoftc *ms = &mp_softc[MPUNIT(unit)];
- int port = MPPORT(unit);
- register struct mpport *mp;
- register struct asyncparam *asp;
-
- mp = &ms->ms_mb->mb_port[port];
- asp = &ms->ms_async[port][mp->mp_on?mp->mp_on-1:MPINSET-1];
- if (flag == MMOD_ON) {
- if (1 || ms->ms_softCAR & (1 << port))/* XXX HARDWIRE FOR NOW */
- setm(&asp->ap_modem, A_DTR, ASSERT);
- else
- setm(&asp->ap_modem, A_DTR, AUTO);
- seti(&asp->ap_intena, A_DCD);
- } else {
- setm(&asp->ap_modem, 0, DROP);
- seti(&asp->ap_intena, 0);
- }
- }
-
- /*
- * Set up the modem control structure according to mask.
- * Each set bit in the mask means assert the corresponding
- * modem control line, otherwise, it will be dropped.
- * RTS is special since it can either be asserted, dropped
- * or put in auto mode for auto modem control.
- */
- static
- setm(mc, mask, rts)
- register struct mdmctl *mc;
- register int mask;
- {
-
- mc->mc_rngdsr = (mask & A_RNGDSR) ? ASSERT : DROP;
- mc->mc_rate = (mask & A_RATE) ? ASSERT : DROP;
- mc->mc_dcd = (mask & A_DCD) ? ASSERT : DROP;
- mc->mc_sectx = (mask & A_SECTX) ? ASSERT : DROP;
- mc->mc_cts = (mask & A_CTS) ? ASSERT : DROP;
- mc->mc_secrx = (mask & A_SECRX) ? ASSERT : DROP;
- mc->mc_dtr = (mask & A_DTR) ? ASSERT : DROP;
- mc->mc_rts = rts;
- }
-
- /*
- * Set up the status change enable field from mask.
- * When a signal is enabled in this structure and
- * and a change in state on a corresponding modem
- * control line occurs, a status change event will
- * be delivered to the host.
- */
- static
- seti(mc, mask)
- register struct mdmctl *mc;
- register int mask;
- {
-
- mc->mc_rngdsr = (mask & A_RNGDSR) ? MDM_ON : MDM_OFF;
- mc->mc_rate = (mask & A_RATE) ? MDM_ON : MDM_OFF;
- mc->mc_dcd = (mask & A_DCD) ? MDM_ON : MDM_OFF;
- mc->mc_sectx = (mask & A_SECTX) ? MDM_ON : MDM_OFF;
- mc->mc_cts = (mask & A_CTS) ? MDM_ON : MDM_OFF;
- mc->mc_secrx = (mask & A_SECRX) ? MDM_ON : MDM_OFF;
- mc->mc_dtr = (mask & A_DTR) ? MDM_ON : MDM_OFF;
- mc->mc_rts = (mask & A_RTS) ? MDM_ON : MDM_OFF;
- }
-
- mpcleanport(mb, port)
- struct mblok *mb;
- int port;
- {
- register struct mpport *mp;
- register struct tty *tp;
-
- mp = &mb->mb_port[port];
- if (mp->mp_proto == MPPROTO_ASYNC) {
- mp->mp_flags = MP_REMBSY;
- /* signal loss of carrier and close */
- tp = &mp_tty[mb->mb_unit*MPCHUNK+port];
- ttyflush(tp, FREAD|FWRITE);
- (void) (*linesw[tp->t_line].l_modem)(tp, 0);
- }
- }
-
- mpclean(mb, port)
- register struct mblok *mb;
- int port;
- {
- register struct mpport *mp;
- register struct mpevent *ev;
- register int i;
- u_char list[2];
- int unit;
-
- mp = &mb->mb_port[port];
- unit = mb->mb_unit;
- for (i = mp->mp_off; i != mp->mp_on; i = (i+1 % MPINSET)) {
- ev = &mp->mp_recvq[i];
- ev->ev_error = ENXIO;
- ev->ev_status = EVSTATUS_DONE;
- }
- list[0] = port, list[1] = MPPORT_EOL;
- mpxintr(unit, list);
- mprintr(unit, list);
- /* Clear async for port */
- mp->mp_proto = MPPROTO_UNUSED;
- mp->mp_flags = 0;
- mp->mp_on = 0;
- mp->mp_off = 0;
- mp->mp_nextrcv = 0;
-
- mp_tty[unit*MPCHUNK + port].t_state = 0;
- for (ev = &mp->mp_sendq[0]; ev < &mp->mp_sendq[MPOUTSET]; ev++) {
- ev->ev_status = EVSTATUS_FREE;
- ev->ev_cmd = 0;
- ev->ev_error = 0;
- ev->ev_un.rcvblk = 0;
- ev->ev_params = 0;
- }
- for (ev = &mp->mp_recvq[0]; ev < &mp->mp_recvq[MPINSET]; ev++) {
- ev->ev_status = EVSTATUS_FREE;
- ev->ev_cmd = 0;
- ev->ev_error = 0;
- ev->ev_params = 0;
- }
- }
-
- /*
- * MPCC interrupt handler.
- */
- mpintr(mpcc)
- int mpcc;
- {
- register struct mblok *mb;
- register struct his *his;
-
- mb = mp_softc[mpcc].ms_mb;
- if (mb == 0) {
- printf("mp%d: stray interrupt\n", mpcc);
- return;
- }
- his = &mb->mb_hostint;
- his->semaphore &= ~MPSEMA_AVAILABLE;
- /*
- * Check for events to be processed.
- */
- if (his->proto[MPPROTO_ASYNC].outbdone[0] != MPPORT_EOL)
- mprintr(mpcc, his->proto[MPPROTO_ASYNC].outbdone);
- if (his->proto[MPPROTO_ASYNC].inbdone[0] != MPPORT_EOL)
- mpxintr(mpcc, his->proto[MPPROTO_ASYNC].inbdone);
- if (mb->mb_harderr || mb->mb_softerr)
- mperror(mb, mpcc);
- his->semaphore |= MPSEMA_AVAILABLE;
- }
-
- /*
- * Handler for processing completion of transmitted events.
- */
- mpxintr(unit, list)
- register u_char *list;
- {
- register struct mpport *mp;
- register struct mpevent *ev;
- register struct mblok *mb;
- register struct tty *tp;
- register struct asyncparam *ap;
- struct mpsoftc *ms;
- int port, i, j;
- # define nextevent(mp) &mp->mp_recvq[mp->mp_off]
-
- ms = &mp_softc[unit];
- mb = mp_softc[unit].ms_mb;
- for (j = 0; j < MPMAXPORT && ((port = *list++) != MPPORT_EOL); j++) {
- /*
- * Process each completed entry in the inbound queue.
- */
- mp = &mb->mb_port[port];
- tp = &mp_tty[unit*MPCHUNK + port];
- ev = nextevent(mp);
- for (; ev->ev_status & EVSTATUS_DONE; ev = nextevent(mp)) {
- /* YUCK */
- ap = &ms->ms_async[port][mp->mp_off];
- mppurge((caddr_t)ap, (int)sizeof (*ap));
- switch (ev->ev_cmd) {
- case EVCMD_OPEN:
- /*
- * Open completion, start all reads and
- * assert modem status information.
- */
- for (i = 0; i < MPOUTSET; i++)
- mp->mp_sendq[i].ev_status = EVSTATUS_GO;
- (*linesw[tp->t_line].l_modem)
- (tp, ap->ap_modem.mc_dcd == ASSERT);
- mp_freein(ev);
- adjptr(mp->mp_off, MPINSET);
- mp->mp_proto = MPPROTO_ASYNC; /* XXX */
- wakeup((caddr_t)&tp->t_canq);
- break;
- case EVCMD_CLOSE:
- /*
- * Close completion, flush all pending
- * transmissions, free resources, and
- * cleanup mpcc port state.
- */
- for (i = 0; i < MPOUTSET; i++) {
- mp->mp_sendq[i].ev_status =
- EVSTATUS_FREE;
- mp->mp_sendq[i].ev_un.rcvblk = 0;
- mp->mp_sendq[i].ev_params = 0;
- }
- mp_freein(ev);
- adjptr(mp->mp_off, MPINSET);
- tp->t_state &= ~(TS_CARR_ON|TS_BUSY|TS_FLUSH);
- mp->mp_on = mp->mp_off = mp->mp_nextrcv = 0;
- mp->mp_flags &= ~MP_PROGRESS;
- mp->mp_proto = MPPROTO_UNUSED;
- wakeup((caddr_t)&tp->t_canq);
- break;
- case EVCMD_IOCTL:
- mp_freein(ev);
- adjptr(mp->mp_off, MPINSET);
- mp->mp_flags &= ~MP_IOCTL;
- wakeup((caddr_t)&tp->t_canq);
- break;
- case EVCMD_WRITE:
- /*
- * Transmission completed, update tty
- * state and restart output.
- */
- if (ev->ev_opts != A_FLUSH) {
- tp->t_state &= ~TS_BUSY;
- if (tp->t_state & TS_FLUSH)
- tp->t_state &= ~TS_FLUSH;
- else {
- register int cc = 0, n;
- struct hxmtl *hxp;
-
- hxp = &ms->ms_hxl[port];
- for (n=0;n < ev->ev_count; n++)
- cc += hxp->size[n];
- ndflush(&tp->t_outq, cc);
- }
- }
- switch (ev->ev_error) {
- case A_SIZERR: /*# error in xmt data size */
- mplog(unit, port, A_XSIZE, 0);
- break;
- case A_NXBERR: /*# no more xmt evt buffers */
- mplog(unit, port, A_NOXBUF, 0);
- break;
- }
- mp_freein(ev);
- adjptr(mp->mp_off, MPINSET);
- mpstart(tp);
- break;
- default:
- mplog(unit, port, A_INVCMD, (int)ev->ev_cmd);
- mp_freein(ev);
- adjptr(mp->mp_off, MPINSET);
- break;
- }
- }
- }
- #undef nextevent
- }
-
- mp_freein(ev)
- register struct mpevent *ev;
- {
- /* re-init all values in this entry */
- ev->ev_cmd = 0;
- ev->ev_opts = 0;
- ev->ev_error = 0;
- ev->ev_flags = 0;
- ev->ev_count = 0;
- /* show this entry is available for use */
- ev->ev_status = EVSTATUS_FREE;
- }
-
- /*
- * Handler for processing received events.
- */
- mprintr(unit, list)
- u_char *list;
- {
- register struct tty *tp;
- register struct mpport *mp;
- register struct mpevent *ev;
- struct mblok *mb;
- register int cc;
- register char *cp;
- struct mpsoftc *ms;
- caddr_t ptr;
- char *rcverr;
- int port, i;
-
- ms = &mp_softc[unit];
- mb = mp_softc[unit].ms_mb;
- for (i = 0; i < MPMAXPORT && (port = *list++) != MPPORT_EOL; i++) {
- tp = &mp_tty[unit*MPCHUNK + port];
- mp = &mb->mb_port[port];
- ev = &mp->mp_sendq[mp->mp_nextrcv];
- while (ev->ev_status & EVSTATUS_DONE) {
- switch(ev->ev_cmd) {
- case EVCMD_STATUS:
- /*
- * Status change, look for carrier changes.
- */
- switch(ev->ev_opts) {
- case DCDASRT:
- (*linesw[tp->t_line].l_modem)(tp, 1);
- wakeup((caddr_t)&tp->t_canq);
- break;
- case DCDDROP:
- (*linesw[tp->t_line].l_modem)(tp, 0);
- wakeup((caddr_t)&tp->t_canq);
- break;
- case NORBUF:
- case NOEBUF:
- mplog(unit, port,
- "out of receive events", 0);
- break;
- default:
- mplog(unit, port,
- "unexpect status command",
- (int)ev->ev_opts);
- break;
- }
- break;
- case EVCMD_READ:
- /*
- * Process received data.
- */
- if ((tp->t_state & TS_ISOPEN) == 0) {
- wakeup((caddr_t)&tp->t_rawq);
- break;
- }
- if ((cc = ev->ev_count) == 0)
- break;
- cp = ms->ms_cbuf[port][mp->mp_nextrcv];
- mppurge(cp, CBSIZE);
- while (cc-- > 0) {
- /*
- * A null character is inserted,
- * potentially when a break or framing
- * error occurs. If we're not in raw
- * mode, substitute the interrupt
- * character.
- */
- /*** XXX - FIXUP ***/
- if (*cp == 0 &&
- (ev->ev_error == BRKASRT ||
- ev->ev_error == FRAMERR))
- if ((tp->t_flags&RAW) == 0)
- ;
- /* XXX was break */
- (*linesw[tp->t_line].l_rint)(*cp++, tp);
- }
- /* setup for next read */
- ptr = (caddr_t)&mp_softc[unit].ms_cbuf[port][mp->mp_nextrcv][0];
- ev->ev_un.rcvblk = (u_char *)kvtophys(ptr);
- ev->ev_params = (caddr_t) kvtophys(ptr);
- switch(ev->ev_error) {
- case RCVDTA:
- /* Normal (good) rcv data do not
- * report the following they are
- * "normal" errors
- */
- case FRAMERR:
- /* frame error */
- case BRKASRT:
- /* Break condition */
- case PARERR:
- /* parity error */
- rcverr = (char *)0;
- break;
- case OVRNERR:
- /* Overrun error */
- rcverr = "overrun error";
- break;
- case OVFERR:
- /* Overflow error */
- rcverr = "overflow error";
- break;
- default:
- rcverr = "undefined rcv error";
- break;
- }
- if (rcverr != (char *)0)
- mplog(unit, port, rcverr,
- (int)ev->ev_error);
- break;
- default:
- mplog(unit, port, "unexpected command",
- (int)ev->ev_cmd);
- break;
- }
- ev->ev_cmd = 0;
- ev->ev_opts = 0;
- ev->ev_error = 0;
- ev->ev_flags = 0;
- ev->ev_count = 0;
- ev->ev_status = EVSTATUS_GO; /* start next read */
- adjptr(mp->mp_nextrcv, MPOUTSET);
- ev = &mp->mp_sendq[mp->mp_nextrcv];
- }
- }
- }
-
- /*
- * Log an mpcc diagnostic.
- */
- mplog(unit, port, cp, flags)
- char *cp;
- {
-
- if (flags)
- log(LOG_ERR, "mp%d: port%d, %s (%d)\n",
- unit, port, cp, flags);
- else
- log(LOG_ERR, "mp%d: port%d, %s\n", unit, port, cp);
- }
-
- int MPHOSTINT = 1;
-
- mptimeint(mb)
- register struct mblok *mb;
- {
-
- mb->mb_mpintcnt = 0;
- mb->mb_mpintclk = (caddr_t)0;
- *(u_short *)mpinfo[mb->mb_unit]->ui_addr = 2;
- }
-
- /*
- * Interupt mpcc
- */
- mpintmpcc(mb, port)
- register struct mblok *mb;
- {
-
- mb->mb_intr[port] |= MPSEMA_WORK;
- if (++mb->mb_mpintcnt == MPHOSTINT) {
- mb->mb_mpintcnt = 0;
- *(u_short *)mpinfo[mb->mb_unit]->ui_addr = 2;
- if (mb->mb_mpintclk) {
- untimeout(mptimeint, (caddr_t)mb);
- mb->mb_mpintclk = 0;
- }
- } else {
- if (mb->mb_mpintclk == 0) {
- timeout(mptimeint, (caddr_t)mb, 4);
- mb->mb_mpintclk = (caddr_t)1;
- }
- }
- }
-
- static char *mpherrmsg[] = {
- "",
- "Bus error", /* MPBUSERR */
- "Address error", /* ADDRERR */
- "Undefined ecc interrupt", /* UNDECC */
- "Undefined interrupt", /* UNDINT */
- "Power failure occurred", /* PWRFL */
- "Stray transmit done interrupt", /* NOXENTRY */
- "Two fast timers on one port", /* TWOFTMRS */
- "Interrupt queue full", /* INTQFULL */
- "Interrupt queue ack error", /* INTQERR */
- "Uncorrectable dma parity error", /* CBPERR */
- "32 port ACAP failed power up", /* ACPDEAD */
- };
- #define NHERRS (sizeof (mpherrmsg) / sizeof (mpherrmsg[0]))
-
- mperror(mb, unit)
- register struct mblok *mb;
- int unit;
- {
- register char *cp;
- register int i;
-
- if (mb->mb_softerr) {
- switch (mb->mb_softerr) {
- case DMAPERR: /* dma parity error */
- cp = "dma parity error";
- break;
- case ECCERR:
- cp = "local memory ecc error";
- break;
- default:
- cp = "unknown error";
- break;
- }
- log(LOG_ERR, "mp%d: soft error, %s", unit, cp);
- mb->mb_softerr = 0;
- }
- if (mb->mb_harderr) {
- if (mb->mb_harderr < NHERRS)
- cp = mpherrmsg[mb->mb_harderr];
- else
- cp = "unknown error";
- log(LOG_ERR, "mp%d: hard error, %s", unit, cp);
- if (mb->mb_status == MP_OPOPEN) {
- for (i = 0; i < MPMAXPORT; i++) {
- mpcleanport(mb, i);
- mb->mb_proto[i] = MPPROTO_UNUSED;
- }
- }
- mb->mb_harderr = 0;
- mb->mb_status = 0;
- }
- }
-
- mppurge(addr, cc)
- register caddr_t addr;
- register int cc;
- {
-
- for (; cc >= 0; addr += NBPG, cc -= NBPG)
- mtpr(P1DC, addr);
- }
-
- /*
- * MPCC Download Pseudo-device.
- */
- char mpdlbuf[MPDLBUFSIZE];
- int mpdlbusy; /* interlock on download buffer */
- int mpdlerr;
-
- mpdlopen(dev)
- dev_t dev;
- {
- int unit, mpu;
- struct vba_device *vi;
-
- unit = minor(dev);
- mpu = MPUNIT(unit);
- if (mpu >= NMP || (vi = mpinfo[mpu]) == 0 || vi->ui_alive == 0)
- return (ENODEV);
- return (0);
- }
-
- mpdlwrite(dev, uio)
- dev_t dev;
- struct uio *uio;
- {
- register struct mpsoftc *ms = &mp_softc[MPUNIT(minor(dev))];
- register struct mpdl *dl;
- int error;
-
- if (ms->ms_mb == 0 || ms->ms_mb->mb_status != MP_DLOPEN)
- return (EFAULT);
- dl = &ms->ms_mb->mb_dl;
- dl->mpdl_count = uio->uio_iov->iov_len;
- dl->mpdl_data = (caddr_t) kvtophys(mpdlbuf);
- if (error = uiomove(mpdlbuf, (int)dl->mpdl_count, uio))
- return (error);
- uio->uio_resid -= dl->mpdl_count; /* set up return from write */
- dl->mpdl_cmd = MPDLCMD_NORMAL;
- error = mpdlwait(dl);
- return (error);
- }
-
- mpdlclose(dev)
- dev_t dev;
- {
- register struct mblok *mb = mp_softc[MPUNIT(minor(dev))].ms_mb;
-
- if (mb == 0 || mb->mb_status != MP_DLDONE) {
- mpbogus.status = 0;
- if (mpbogus.mb == mpbogus.mbloks[MPUNIT(minor(dev))])
- mpdlbusy--;
- return (EEXIST);
- }
- mb->mb_status = MP_OPOPEN;
- mpbogus.status = 0;
- /* set to dead, for board handshake */
- mb->mb_hostint.imok = MPIMOK_DEAD;
- return (0);
- }
-
- /* ARGSUSED */
- mpdlioctl(dev, cmd, data, flag)
- dev_t dev;
- caddr_t data;
- {
- register struct mblok *mb;
- register struct mpdl *dl;
- int unit, error = 0, s, i;
-
- mb = mp_softc[unit=MPUNIT(minor(dev))].ms_mb;
- if (mb == 0)
- return (EEXIST);
- dl = &mb->mb_dl;
- error = 0;
- switch (cmd) {
- case MPIOPORTMAP:
- bcopy(data, (caddr_t)mb->mb_proto, sizeof (mb->mb_proto));
- break;
- case MPIOHILO:
- bcopy(data, (caddr_t)&mb->mb_hiport, 2*(sizeof(mb->mb_hiport)));
- break;
- case MPIOENDDL:
- dl->mpdl_count = 0;
- dl->mpdl_data = 0;
- dl->mpdl_cmd = MPIOENDDL&IOCPARM_MASK;
- error = mpdlwait(dl);
- mpccinit(unit);
- mb->mb_status = MP_DLDONE;
- mpdlbusy--;
- break;
- case MPIOENDCODE:
- dl->mpdl_count = 0;
- dl->mpdl_data = 0;
- dl->mpdl_cmd = MPIOENDCODE&IOCPARM_MASK;
- error = mpdlwait(dl);
- break;
- case MPIOASYNCNF:
- bcopy(data, mpdlbuf, sizeof (struct abdcf));
- dl->mpdl_data = (caddr_t) kvtophys(mpdlbuf);
- dl->mpdl_count = sizeof (struct abdcf);
- dl->mpdl_cmd = MPIOASYNCNF&IOCPARM_MASK;
- error = mpdlwait(dl);
- break;
- case MPIOSTARTDL:
- s = spl8();
- while (mpdlbusy)
- if (error = tsleep((caddr_t)&mpdlbusy,
- (PZERO+1) | PCATCH, devioc, 0))
- break;
- splx(s);
- if (error)
- break;
- mpdlbusy++;
- /* initialize the downloading interface */
- mpbogus.magic = MPMAGIC;
- mpbogus.mb = mpbogus.mbloks[unit];
- mpbogus.status = 1;
- dl->mpdl_status = EVSTATUS_FREE;
- dl->mpdl_count = 0;
- dl->mpdl_cmd = 0;
- dl->mpdl_data = (char *) 0;
- mpdlerr = 0;
- mb->mb_magic = MPMAGIC;
- mb->mb_ivec = mp_softc[unit].ms_ivec+1; /* download vector */
- mb->mb_status = MP_DLPEND;
- mb->mb_diagswitch[0] = 'A';
- mb->mb_diagswitch[1] = 'P';
- s = spl8();
- *(u_short *)mpinfo[unit]->ui_addr = 2;
- error = tsleep((caddr_t)&mb->mb_status, (PZERO+1) | PCATCH,
- devio, 30*hz);
- splx(s);
- if (error == EWOULDBLOCK)
- error = ETIMEDOUT;
- if (error)
- mpbogus.status = 0;
- bzero((caddr_t)mb->mb_port, sizeof (mb->mb_port));
- break;
- case MPIORESETBOARD:
- s = spl8();
- if (mb->mb_imokclk)
- mb->mb_imokclk = 0;
- *(u_short *)mpinfo[unit]->ui_addr = 0x100;
- if (mb->mb_status == MP_DLOPEN || mb->mb_status == MP_DLDONE) {
- mpdlerr = MP_DLERROR;
- dl->mpdl_status = EVSTATUS_FREE;
- wakeup((caddr_t)&dl->mpdl_status);
- mpbogus.status = 0;
- }
- for (i = 0; i < MPMAXPORT; i++) {
- if (mb->mb_harderr || mb->mb_softerr)
- mperror(mb, i);
- mpcleanport(mb, i);
- mb->mb_proto[i] = MPPROTO_UNUSED;
- }
- mb->mb_status = 0;
- splx(s);
- break;
- default:
- error = EINVAL;
- break;
- }
- return (error);
- }
-
- mpccinit(unit)
- int unit;
- {
- register struct mblok *mb = mp_softc[unit].ms_mb;
- register struct his *his;
- register int i, j;
-
- mb->mb_status = MP_DLDONE;
- mb->mb_ivec = mp_softc[unit].ms_ivec;
- mb->mb_magic = MPMAGIC;
- /* Init host interface structure */
- his = &mb->mb_hostint;
- his->semaphore = MPSEMA_AVAILABLE;
- for (i = 0; i < NMPPROTO; i++)
- for (j = 0; j < MPMAXPORT; j++) {
- his->proto[i].inbdone[j] = MPPORT_EOL;
- his->proto[i].outbdone[j] = MPPORT_EOL;
- }
- mb->mb_unit = unit;
- }
-
- mpdlintr(mpcc)
- int mpcc;
- {
- register struct mblok *mb;
- register struct mpdl *dl;
-
- mb = mp_softc[mpcc].ms_mb;
- if (mb == 0) {
- printf("mp%d: stray download interrupt\n", mpcc);
- return;
- }
- dl = &mb->mb_dl;
- switch (mb->mb_status) {
- case MP_DLOPEN:
- if (dl->mpdl_status != EVSTATUS_DONE)
- mpdlerr = MP_DLERROR;
- dl->mpdl_status = EVSTATUS_FREE;
- wakeup((caddr_t)&dl->mpdl_status);
- return;
- case MP_DLPEND:
- mb->mb_status = MP_DLOPEN;
- wakeup((caddr_t)&mb->mb_status);
- /* fall thru... */
- case MP_DLTIME:
- return;
- case MP_OPOPEN:
- if (mb->mb_imokclk)
- mb->mb_imokclk = 0;
- mb->mb_nointcnt = 0; /* reset no interrupt count */
- mb->mb_hostint.imok = MPIMOK_DEAD;
- mb->mb_imokclk = (caddr_t)1;
- break;
- default:
- log(LOG_ERR, "mp%d: mpdlintr, status %x\n",
- mpcc, mb->mb_status);
- break;
- }
- }
-
- /*
- * Wait for a transfer to complete or a timeout to occur.
- */
- mpdlwait(dl)
- register struct mpdl *dl;
- {
- int s, error = 0;
-
- s = spl8();
- dl->mpdl_status = EVSTATUS_GO;
- while (dl->mpdl_status != EVSTATUS_FREE) {
- error = tsleep((caddr_t)&dl->mpdl_status, (PZERO+1) | PCATCH,
- devout, 0);
- if (mpdlerr == MP_DLERROR)
- error = EIO;
- if (error)
- break;
- }
- splx(s);
- return (error);
- }
- #endif
-