summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-02-14 15:00:39 +0000
committerjkh <jkh@FreeBSD.org>1995-02-14 15:00:39 +0000
commit1ff34ff975e38dfd1087289b463b765f409104ad (patch)
treefde5c0029111a58a30ca5ffc6ca10322a59d1605
parent01bd5245a2bcb750f43b611651b1b7cae5754109 (diff)
downloadFreeBSD-src-1ff34ff975e38dfd1087289b463b765f409104ad.zip
FreeBSD-src-1ff34ff975e38dfd1087289b463b765f409104ad.tar.gz
An ISDN driver that supports the EDSS1 and the 1TR6 ISDN interfaces.
EDSS1 is the "Euro-ISDN", 1TR6 is the soon obsolete german ISDN Interface. Obtained from: Dietmar Friede <dfriede@drnhh.neuhaus.de> and Juergen Krause <jkr@saarlink.de> This is only one part - the rest to follow in a couple of hours. This part is a benign import, since it doesn't affect anything else.
-rw-r--r--sys/gnu/i386/isa/nic3008.c1142
-rw-r--r--sys/gnu/i386/isa/nic3008.h114
-rw-r--r--sys/gnu/i386/isa/nic3009.c1209
-rw-r--r--sys/gnu/i386/isa/nic3009.h79
-rw-r--r--sys/gnu/i386/isa/niccyreg.h158
-rw-r--r--sys/gnu/isdn/if_ii.c245
-rw-r--r--sys/gnu/isdn/iispy.c171
-rw-r--r--sys/gnu/isdn/iitel.c234
-rw-r--r--sys/gnu/isdn/iitty.c306
-rw-r--r--sys/gnu/isdn/isdn.c626
-rw-r--r--sys/gnu/isdn/isdn_ioctl.h136
-rw-r--r--sys/gnu/scsi/nic5000.c1467
-rw-r--r--sys/gnu/scsi/scsi_nic.h53
13 files changed, 5940 insertions, 0 deletions
diff --git a/sys/gnu/i386/isa/nic3008.c b/sys/gnu/i386/isa/nic3008.c
new file mode 100644
index 0000000..a581408
--- /dev/null
+++ b/sys/gnu/i386/isa/nic3008.c
@@ -0,0 +1,1142 @@
+static char nic38_id[] = "@(#)$Id: nic3008.c,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: nic3008.c,v $
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (c) 1994 Dietmar Friede (dietmar@friede.de) All rights reserved.
+ * FSF/FSAG GNU Copyright applies
+ *
+ * A low level driver for the NICCY-3008 ISDN Card.
+ *
+ */
+
+#include "nic.h"
+#if NNIC > 0
+
+#include "param.h"
+#include "ioctl.h"
+#include "kernel.h"
+#include "systm.h"
+
+#include "i386/isa/isa_device.h"
+#include "i386/isa/nic3008.h"
+#include "i386/isa/niccyreg.h"
+#include "isdn/isdn_ioctl.h"
+
+#define OPEN 1
+#define LOAD_HEAD 3
+#define LOAD_DATA 5
+#define IS_DIAL(p) (((p)&0x20)==0)
+#define IS_LISTEN(p) ((p)&0x20)
+#define CHAN(pl) (((pl)&7)-1)
+#define C_CHAN(x) ((x)&1)
+#define APPL(pl) ((((pl)>>6)&0x7f)-1)
+#define CARD(pl) (((pl)>>13)&7)
+#define MK_APPL(pl) (((pl)+1)<<6)
+
+#define con_act_resp(sc,pl) en_q_d(sc,DD_CONN_ACT_RSP, pl ,0,NULL)
+#define discon_resp(sc,pl) en_q_d(sc,DD_DISC_RSP, pl ,0,NULL)
+#define inf_resp(sc,pl) en_q_d(sc,DD_INFO_RSP, pl ,0,NULL)
+#define listen_b3_req(sc,mb,pl) en_q_b(sc,mb,BD_LIST_B3_REQ,pl,0,NULL)
+#define con_b3_req(sc,mb,pl) en_q_b(sc,mb,BD_CONN_B3_REQ,pl,0,NULL)
+#define min(a,b) ((a)<(b)?(a):(b))
+
+extern isdn_appl_t isdn_appl[];
+extern u_short isdn_state;
+extern isdn_ctrl_t isdn_ctrl[];
+extern int ispy_applnr;
+extern int Isdn_Appl, Isdn_Ctrl, Isdn_Typ;
+extern int hz;
+
+static old_spy= 0;
+
+int nicprobe(), nicattach();
+int nic_connect(), nic_listen(), nic_disconnect(), nic_accept();
+int nic_output();
+extern isdn_start_out();
+
+static void s_intr(), reset_req(), reset_card();
+static int cstrcmp(), discon_req(), reset_plci(), sel_b2_prot_req();
+
+static short bsintr;
+
+struct isa_driver nicdriver = {nicprobe, nicattach, "nic"};
+
+typedef enum
+{
+ DISCON, ISDISCON, DIAL, CALLED, CONNECT, IDLE, ACTIVE
+} io_state;
+typedef struct
+{
+ char ctrl;
+ u_char msg_nr;
+ u_char morenr;
+ short plci;
+ short ncci;
+ short state;
+ short i_len;
+ char i_buf[2048];
+ char o_buf[2048];
+ u_short more;
+ char *more_b;
+} chan_t;
+
+struct nic_softc
+{
+ dpr_type *sc_dpr; /* card RAM virtual memory base */
+ u_short sc_vector; /* interrupt vector */
+ short sc_port;
+ u_char sc_flags;
+ u_char sc_unit;
+ u_char sc_ctrl;
+ short sc_stat;
+ chan_t sc_chan[2];
+} nic_sc[NNIC];
+
+
+int
+nicprobe(struct isa_device * is)
+{
+ register struct nic_softc *sc = &nic_sc[is->id_unit & 127];
+ dpr_type *dpr;
+
+ sc->sc_vector = is->id_irq;
+ sc->sc_port = is->id_iobase;
+ sc->sc_unit = is->id_unit;
+ dpr = sc->sc_dpr = (dpr_type *) is->id_maddr;
+
+ if (cstrcmp(dpr->niccy_ver, "NICCY V ") == 0)
+ {
+ printf("NICCY NICCY-Card %d not found at %x\n"
+ ,is->id_unit, is->id_maddr);
+ return (0);
+ }
+ while (dpr->card_state & 1); /* self test running */
+
+ if (dpr->card_state & 0x8A)
+ {
+ printf("Check Niccy Card, error state %d \n", dpr->card_state);
+ return (0);
+ }
+ dpr->card_number = is->id_unit;
+ is->id_msize = 8192;
+ reset_card(sc);
+ return (8);
+}
+
+/*
+ * nicattach() Install device
+ */
+int
+nicattach(struct isa_device * is)
+{
+ struct nic_softc *sc;
+ dpr_type *dpr;
+ int cn;
+ isdn_ctrl_t *ctrl0, *ctrl1;
+
+ sc = &nic_sc[is->id_unit];
+ dpr = sc->sc_dpr;
+ sc->sc_ctrl = -1;
+ if ((cn = isdn_ctrl_attach(2)) == -1)
+ {
+ return (0);
+ }
+ sc->sc_ctrl = cn;
+
+ sc->sc_chan[0].plci = sc->sc_chan[1].plci = -1;
+
+ ctrl0 = &isdn_ctrl[cn];
+ ctrl1 = &isdn_ctrl[cn + 1];
+ sc->sc_chan[0].ctrl = ctrl0->ctrl = cn;
+ sc->sc_chan[1].ctrl = ctrl1->ctrl = cn + 1;
+ ctrl0->o_buf = sc->sc_chan[0].o_buf;
+ ctrl1->o_buf = sc->sc_chan[1].o_buf;
+ ctrl0->listen = ctrl1->listen = nic_listen;
+ ctrl0->disconnect = ctrl1->disconnect = nic_disconnect;
+ ctrl0->accept = ctrl1->accept = nic_accept;
+ ctrl0->connect = ctrl1->connect = nic_connect;
+ ctrl0->output = ctrl1->output = nic_output;
+ ctrl0->unit = ctrl1->unit = is->id_unit;
+ ctrl0->appl = ctrl1->appl = -1;
+ ctrl0->o_len = ctrl1->o_len = -1;
+
+ while (dpr->card_state & 1); /* self test running */
+ dpr->card_number = is->id_unit;
+ dpr->int_flg_pc = 0xff;
+ reset_req(sc, MBX_MU, 4);
+ return (1);
+}
+
+static int
+cstrcmp(char *str1, char *str2)
+{
+ while (*str2 && (*str2 == *str1))
+ {
+ str1++;
+ str2++;
+ }
+ if (!*str2)
+ return (1);
+ return (0);
+}
+
+/* If the niccy card wants it: Interupt it. */
+static void
+make_intr(int box, struct nic_softc * sc)
+{
+ dpr_type *dpr = sc->sc_dpr;
+
+ dpr->watchdog_cnt = 0xFF;
+ if ((dpr->int_flg_nic & (1 << box)) == 0)
+ return;
+ if (dpr->ext_hw_config == 1)
+ {
+ u_char s;
+ s = inb(sc->sc_port + 4);
+ outb(sc->sc_port + 4, s & 0xfb);
+ outb(sc->sc_port + 4, s | 4);
+ outb(sc->sc_port + 4, s);
+ return;
+ }
+ outb(sc->sc_port + 2, 1);
+}
+
+static void
+reset_req(struct nic_softc * sc, unsigned box, int w)
+{
+ if(box >= 8)
+ return;
+
+ (sc->sc_dpr)->msg_flg[box] = 0;
+ make_intr(box, sc);
+}
+
+static int
+en_q_d(struct nic_softc * sc, int t, int pl, int l, u_char * b)
+{
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx = &dpr->dpr_mbx[3];
+
+ if (dpr->card_state & ~4)
+ return (ENODEV);
+ if (dpr->msg_flg[3])
+ return (EBUSY);
+
+ bzero(mbx, 18);
+ mbx->type = t;
+ mbx->add_info = pl;
+ if (l)
+ {
+ mbx->data_len = l;
+ bcopy(b, mbx->data, l);
+ }
+ dpr->msg_flg[3] = 1;
+ make_intr(3, sc);
+ return (0);
+}
+
+static int
+en_q_b(struct nic_softc * sc, int mb, int t, int pl, int l, u_char * b)
+{
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx = &dpr->dpr_mbx[++mb];
+
+ if (mb == 7)
+ t |= 0x40;
+
+ if (dpr->card_state)
+ return (ENODEV);
+ if (dpr->msg_flg[mb])
+ return (EBUSY);
+
+ bzero(mbx, 18);
+ mbx->type = t;
+ mbx->add_info = pl;
+ if (l)
+ {
+ mbx->data_len = l;
+ bcopy(b, mbx->data, l);
+ }
+ dpr->msg_flg[mb] = 1;
+ make_intr(mb, sc);
+ return (0);
+}
+
+static void
+badstate(mbx_type * mbx, int n, int mb, dpr_type *dpr)
+{
+ printf("Niccy: not implemented %x len %d at %d.", mbx->type,mbx->data_len,n);
+ if(mbx->data_len)
+ {
+ u_char *b = (u_char *) dpr;
+ int i;
+
+ b += dpr->buf_ptr[mb];
+ for(i=0; i<mbx->data_len; i++) printf(" %x",mbx->data[i]);
+ printf(".");
+ for(i=0; i<mbx->data_len; i++) printf(" %x",b[i]);
+ }
+ printf("\n");
+}
+
+int
+nic_connect(int cn, int ap, int b_channel, int inf_mask, int out_serv
+ ,int out_serv_add, int src_subadr, unsigned ad_len
+ ,char *dest_addr, int spv)
+{
+ char buf[128];
+
+ if (ad_len > 22)
+ return (-1);
+
+ buf[0] = spv ? 0x53 : 0;
+ buf[1] = b_channel;
+ if (spv)
+ inf_mask |= 0x40000000;
+ *(u_long *) & buf[2] = inf_mask;
+ buf[6] = out_serv;
+ buf[7] = out_serv_add;
+ buf[8] = src_subadr;
+ buf[9] = ad_len;
+ bcopy(dest_addr, &buf[10], ad_len);
+ return (en_q_d(&nic_sc[isdn_ctrl[cn].unit], DD_CONN_REQ, MK_APPL(ap), ad_len + 10, buf));
+}
+
+int
+nic_listen(int cn, int ap, int inf_mask, int subadr_mask, int si_mask)
+{
+ u_short sbuf[4];
+
+ *(u_long *) sbuf = inf_mask;
+ sbuf[2] = subadr_mask;
+ sbuf[3] = si_mask;
+ return (en_q_d(&nic_sc[isdn_ctrl[cn].unit], DD_LISTEN_REQ, MK_APPL(ap), 8, (u_char *) sbuf));
+}
+
+int
+nic_disconnect(int cn, int rea)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ struct nic_softc *sc = &nic_sc[ctrl->unit];
+ chan_t *chan = &sc->sc_chan[C_CHAN(cn)];
+ u_char buf[16];
+ int l = 3;
+ int p;
+ int err;
+
+ if(chan->ncci != -1)
+ {
+ bzero(buf,16);
+ *(u_short *) buf = chan->ncci;
+ l += sizeof(ncpi_t);
+ err= en_q_b(sc, C_CHAN(cn)?6:4, BD_DISC_B3_REQ, chan->plci, l, buf);
+ if(err==0)
+ {
+ chan->more= 0;
+ ctrl->o_len= -1;
+ }
+ return(err);
+ }
+
+ p = chan->plci;
+ if((p == 0) || (p == -1))
+ return (ENODEV);
+
+ err= en_q_d(sc, DD_DISC_REQ, p, 1, (u_char *) & rea);
+ if(err==0)
+ {
+ chan->more= 0;
+ ctrl->o_len= -1;
+ }
+ return(err);
+}
+
+int
+nic_accept(int cn, int an, int rea)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ struct nic_softc *sc = &nic_sc[ctrl->unit];
+ chan_t *chan = &sc->sc_chan[C_CHAN(cn)];
+ isdn_appl_t *appl = &isdn_appl[an];
+
+ if (rea)
+ {
+ ctrl->appl= -1;
+ return(discon_req(1, sc, chan->plci, rea, 0));
+ }
+ ctrl->appl= an;
+ ctrl->lastact = time.tv_sec;
+ appl->ctrl= cn;
+ appl->state= 4;
+
+ return(sel_b2_prot_req(sc, C_CHAN(cn), chan->plci, &appl->dlpd));
+}
+
+int
+nic_output(int cn)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ struct nic_softc *sc = &nic_sc[ctrl->unit];
+ chan_t *chan = &sc->sc_chan[C_CHAN(cn)];
+ int mb = C_CHAN(cn) ? 7 : 5;
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx = &dpr->dpr_mbx[mb];
+ int r, l;
+ u_char *b = (u_char *) dpr;
+ int len= ctrl->o_len;
+ char *buf= ctrl->o_buf;
+
+ if (dpr->card_state /* & ~4 */)
+ return (ENODEV);
+
+ if ((chan->ncci == -1) || dpr->msg_flg[mb] || (chan->state != IDLE))
+ return (EBUSY);
+
+ chan->state = ACTIVE;
+
+ bzero(mbx, 20);
+ mbx->type = BD_DATA_B3_REQ;
+ if (C_CHAN(cn))
+ mbx->type |= 0x40;
+ *(u_short *) mbx->data = chan->ncci;
+ mbx->data[4] = chan->msg_nr++;
+ b += dpr->buf_ptr[mb];
+ l = min(1024, len);
+ mbx->data_len = l;
+ bcopy(buf, b, l);
+
+ if (l < len)
+ {
+ chan->more = min(len - l, 1024); /* This is a bug, but */
+ /* max. blocks length is 2048 bytes including protokoll */
+ chan->more_b = buf + l;
+ mbx->more_data = 1;
+ } else
+ {
+ chan->more = 0;
+ ctrl->o_len = -1;
+ }
+
+ dpr->msg_flg[mb] = 3;
+ bsintr |= (1 << C_CHAN(cn));
+ make_intr(mb, sc);
+ ctrl->lastact = time.tv_sec;
+ return (0);
+}
+
+static void
+con_resp(struct nic_softc * sc, int pl, int rea)
+{
+ en_q_d(sc, DD_CONN_RSP, pl, 1, (u_char *) & rea);
+}
+
+static int
+discon_req(int w, struct nic_softc * sc, int pl, int rea, int err)
+{
+ if ((pl == 0) || (pl == -1))
+ return(0);
+ return(en_q_d(sc, DD_DISC_REQ, pl, 1, (u_char *) & rea));
+}
+
+static int
+sel_b2_prot_req(struct nic_softc * sc, int c, int pl, dlpd_t * dlpd)
+{
+ return(en_q_b(sc, c ? 6 : 4, BD_SEL_PROT_REQ | 0x200, pl,
+ sizeof(dlpd_t), (u_char *) dlpd));
+}
+
+static void
+sel_b3_prot_req(struct nic_softc * sc, int mb, u_short pl, ncpd_t * ncpd)
+{
+ en_q_b(sc, mb, BD_SEL_PROT_REQ | 0x300, pl, sizeof(ncpd_t), (u_char *) ncpd);
+}
+
+static void
+con_b3_resp(struct nic_softc * sc, int mb, u_short ncci, u_char reject)
+{
+ u_char buf[32];
+ int l = 4;
+
+ bzero(buf, 32);
+ *(u_short *) buf = ncci;
+ buf[2] = reject;
+ buf[3] = 0; /* ncpi ???? */
+ l += 15;
+ en_q_b(sc, mb, BD_CONN_B3_RSP, 0, l, buf);
+}
+
+static int
+reset_plci(int w, chan_t * chan, int p)
+{
+ isdn_ctrl_t *ctrl;
+
+ if (p == -1)
+ return (-1);
+
+ if(chan == NULL)
+ return(p);
+
+ ctrl = &isdn_ctrl[chan->ctrl];
+ if (chan->plci == p)
+ {
+ if (ISBUSY(ctrl->appl))
+ {
+ isdn_disconn_ind(ctrl->appl);
+ isdn_appl[ctrl->appl].ctrl = -1;
+ isdn_appl[ctrl->appl].state = 0;
+ }
+ ctrl->appl = -1;
+ ctrl->o_len = -1;
+ chan->plci = -1;
+ chan->ncci = -1;
+ chan->state = DISCON;
+ chan->i_len = 0;
+ chan->more = 0;
+ }
+ return (p);
+}
+
+static void
+reset_card(struct nic_softc * sc)
+{
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx = &dpr->dpr_mbx[1];
+ bzero(mbx, 16);
+ mbx->type = MD_RESET_REQ;
+ dpr->msg_flg[1] = 1;
+ make_intr(1, sc);
+}
+
+/*
+ * nicopen() New open on device.
+ *
+ * We forbid all but first open
+ */
+int
+nicopen(dev_t dev, int flag)
+{
+ struct nic_softc *sc;
+ u_char unit;
+ dpr_type *dpr;
+ int x;
+
+ unit = minor(dev);
+
+ /* minor number out of limits ? */
+ if (unit >= NNIC)
+ return (ENXIO);
+ sc = &nic_sc[unit];
+
+ sc->sc_flags |= OPEN;
+ dpr = sc->sc_dpr;
+ dpr->card_number = sc->sc_unit;
+ dpr->int_flg_pc = 0xff;
+ if (dpr->msg_flg[0])
+ {
+ x = splhigh();
+ s_intr(sc, dpr);
+ splx(x);
+ }
+ return (0);
+}
+
+/*
+ * nicclose() Close device
+ */
+int
+nicclose(dev_t dev, int flag)
+{
+ struct nic_softc *sc = &nic_sc[minor(dev)];
+
+ sc->sc_flags = 0;
+ return (0);
+}
+
+int
+nicioctl(dev_t dev, int cmd, caddr_t data, int flag)
+{
+ int error;
+ u_char unit;
+ int i, x;
+ struct nic_softc *sc = &nic_sc[minor(dev)];
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx;
+
+ dpr->int_flg_pc = 0xff;
+
+ error = 0;
+ switch (cmd)
+ {
+ case NICCY_DEBUG:
+ data[0]= 0x38;
+ bcopy((char *)dpr, data+1, sizeof(dpr_type));
+ break;
+ case NICCY_LOAD:
+ {
+ struct head *head = (struct head *) data;
+ u_char *b = (u_char *) dpr;
+ int len, l, off;
+
+ x = splhigh();
+ while (dpr->msg_flg[1])
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic1head", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+ mbx = &dpr->dpr_mbx[1];
+ bzero(mbx, 16);
+ mbx->type = MD_DNL_MOD_REQ | ((u_short) head->typ << 8);
+ mbx->data_len = 12;
+ bcopy(head->nam, mbx->data, 8);
+ *(u_long *) (mbx->data + 8) = head->len;
+
+ sc->sc_flags = LOAD_HEAD;
+ sc->sc_stat = -1;
+ dpr->msg_flg[1] = 1;
+ make_intr(1, sc);
+ while (sc->sc_flags == LOAD_HEAD)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic2head", 1);
+ if (error != EWOULDBLOCK)
+ break;
+ }
+
+ len= head->d_len;
+ off= 0;
+ b += dpr->buf_ptr[1];
+
+ while(len > 0)
+ {
+ while (dpr->msg_flg[1])
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic1load", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+ bzero(mbx, 16);
+ mbx->type = MD_DNL_MOD_DATA | ((u_short) head->typ << 8);
+ l= min(len,1024);
+ len-= l;
+ mbx->buf_valid = 1;
+ mbx->more_data = len > 0;
+ mbx->data_len = l;
+ bcopy(head->nam, mbx->data, 8);
+
+ if(error= copyin(head->data+off, b, l))
+ {
+ splx(x);
+ return(error);
+ }
+ off+= l;
+ sc->sc_flags = LOAD_DATA;
+ sc->sc_stat = -1;
+ dpr->msg_flg[1] = 3;
+ make_intr(1, sc);
+ }
+
+ while ((sc->sc_flags == LOAD_DATA) || (dpr->card_state & 0x20))
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic2load", 1);
+ if (error != EWOULDBLOCK)
+ break;
+ }
+ if (sc->sc_flags)
+ sc->sc_flags = OPEN;
+ head->status = sc->sc_stat;
+ splx(x);
+ return (0);
+ }
+ case NICCY_SET_CLOCK:
+ x = splhigh();
+ if (dpr->msg_flg[1])
+ {
+ splx(x);
+ return (EBUSY);
+ }
+ mbx = &dpr->dpr_mbx[1];
+ bzero(mbx, 16);
+ mbx->type = MD_SET_CLOCK_REQ;
+ mbx->data_len = 14;
+ bcopy(data, mbx->data, 14);
+
+ dpr->msg_flg[1] = 1;
+ if (dpr->int_flg_nic & 2)
+ make_intr(1, sc);
+ splx(x);
+ return (0);
+ case NICCY_SPY:
+ x = splhigh();
+ if (dpr->msg_flg[1])
+ {
+ splx(x);
+ return (EBUSY);
+ }
+ mbx = &dpr->dpr_mbx[1];
+ bzero(mbx, 16);
+ mbx->type = MD_MANUFACT_REQ | (18<<8);
+ mbx->data_len = 1;
+ mbx->add_info = MK_APPL(ispy_applnr);
+/* There are ilegal states. So I use them to toggle */
+ if((data[0] == 0) && (old_spy == 0)) data[0]= 255;
+ else if(data[0] && old_spy ) data[0]= 0;
+ old_spy= mbx->data[0]= data[0];
+
+ dpr->msg_flg[1] = 1;
+ if (dpr->int_flg_nic & 2)
+ make_intr(1, sc);
+ splx(x);
+ return (0);
+ case NICCY_RESET:
+ x = splhigh();
+
+ reset_card(sc);
+
+ while (dpr->card_state & 1) /* self test running */
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic: reset", 10);
+ if (error != EWOULDBLOCK)
+ break;
+ }
+ dpr->card_number = sc->sc_unit;
+ dpr->int_flg_pc = 0xff;
+ if (dpr->msg_flg[0])
+ s_intr(sc, dpr);
+ splx(x);
+ return (0);
+
+ default:
+ error = ENODEV;
+ }
+ return (error);
+}
+
+static void
+b_intr(int mb, int c, struct nic_softc * sc)
+{
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx = &dpr->dpr_mbx[mb];
+ chan_t *chan = &sc->sc_chan[c];
+ u_short ap, n, err = 0;
+ u_short pl = mbx->add_info;
+ isdn_ctrl_t *ctrl = &isdn_ctrl[chan->ctrl];
+
+ if(((unsigned)(mbx->type >> 8) > 3) || ((pl & 0xff00) == 0xff00))
+ panic("3008 conflict with 16 bit card\nReconfig your system\n");
+
+ if (dpr->msg_flg[mb+1])
+ return; /* can happen. Should make no problems */
+
+ if (ISBUSY(ap = ctrl->appl))
+ switch (mbx->type & 0x1f)
+ {
+ case 0: /* SELECT PROT CONF */
+ err = *(u_short *) mbx->data;
+ if (err)
+ {
+ discon_req(2, sc, pl, 0, err);
+ break;
+ }
+
+ switch ((mbx->type >> 8) & 3)
+ {
+ case 2:/* SELECT B2 PROTOCOL */
+ sel_b3_prot_req(sc, mb, pl, &isdn_appl[ap].ncpd);
+ break;
+
+ case 3:/* SELECT B3 PROTOCOL */
+ if (IS_DIAL(pl))
+ con_b3_req(sc, mb, pl);
+ else
+ listen_b3_req(sc, mb, pl);
+ break;
+ }
+ break;
+
+ case 1: /* LISTEN B3 CONF */
+ err = *(u_short *) mbx->data;
+ if (err)
+ {
+ discon_req(4, sc, pl, 0, err);
+ break;
+ }
+ con_resp(sc, pl, 0);
+ break;
+
+ case 2: /* CONNECT B3 CONF */
+ err = *(u_short *) (mbx->data + 2);
+ n = *(u_short *) mbx->data;
+
+ if (err)
+ {
+ discon_req(5, sc, pl, 0, err);
+ break;
+ }
+ chan->ncci = n;
+ chan->state = CONNECT;
+ break;
+
+ case 3: /* CONNECT B3 IND */
+ n = *(u_short *) mbx->data;
+ chan->ncci = n;
+ chan->state = CONNECT;
+ con_b3_resp(sc, mb, n, 0);
+ break;
+
+ case 4: /* CONNECT B3 ACTIVE IND */
+ if (chan->state < IDLE)
+ {
+ chan->state = IDLE;
+ ctrl->o_len = 0;
+ timeout(isdn_start_out,chan->ctrl,hz/5);
+ break;
+ }
+ break;
+
+ case 5: /* DISCONNECT B3 CONF */
+ chan->state = ISDISCON;
+ err = *(u_short *) (mbx->data + 2);
+ if (err)
+ {
+ discon_req(6, sc, chan->plci, 0, err);
+ break;
+ }
+ break;
+ case 6: /* DISCONNECT B3 IND */
+ chan->state = ISDISCON;
+ err = *(u_short *) (mbx->data + 2);
+ discon_req(7, sc, chan->plci, 0, err);
+ break;
+
+ case 8: /* DATA B3 CONF */
+ err = *(u_short *) (mbx->data + 2);
+ if (err)
+ {
+ ctrl->send_err++;
+ isdn_appl[ap].send_err++;
+ }
+ ctrl->o_len = 0;
+ chan->state= IDLE;
+ isdn_start_out(chan->ctrl);
+ break;
+
+ case 9: /* DATA B3 IND */
+ {
+ u_char *b = (u_char *) dpr;
+ u_char mno;
+
+ b += dpr->buf_ptr[mb];
+ if (mbx->more_data)
+ {
+ chan->morenr= mbx->data[4];
+ if(chan->i_len)
+ {
+ chan->i_len= 0;
+ break;
+ }
+ bcopy(b, &chan->i_buf[chan->i_len], mbx->data_len);
+ chan->i_len = mbx->data_len;
+ break;
+ } /* mbx->more_data == 0 */
+ if (chan->i_len)
+ {
+ int l;
+ if(chan->morenr != mbx->data[4])
+ break;
+
+ if ((l = chan->i_len + mbx->data_len) <= 2048)
+ {
+ bcopy(b, &chan->i_buf[chan->i_len], mbx->data_len);
+ if(isdn_input(ap, l, chan->i_buf, ctrl->islisten))
+ ctrl->lastact = time.tv_sec;
+ }
+ chan->i_len = 0;
+ break;
+ } /* chan->i_len == 0 && mbx->more_data == 0 */
+ if(isdn_input(ap, mbx->data_len, b, ctrl->islisten))
+ ctrl->lastact = time.tv_sec;
+ break;
+ }
+ break;
+
+ default:
+ badstate(mbx,1,mb,dpr);
+ }
+/*
+ else badstate(mbx,2,mb,dpr);
+*/
+
+ reset_req(sc, mb,1);
+}
+
+static void
+d_intr(struct nic_softc * sc)
+{
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx = &dpr->dpr_mbx[2];
+ chan_t *chan;
+ u_short ap, c, pl, err = 0;
+ isdn_ctrl_t *ctrl;
+ isdn_appl_t *appl;
+
+ if (dpr->msg_flg[3])
+ return; /* should not happen. might make problems */
+ /* but there should be another intr., so what? */
+
+ pl = mbx->add_info;
+ if ((c = CHAN(pl)) < 2)
+ {
+ chan = &sc->sc_chan[c];
+ ctrl = &isdn_ctrl[chan->ctrl];
+ } else
+ {
+ c = 0xffff;
+ chan = NULL;
+ ctrl = NULL;
+ }
+
+ ap= APPL(pl);
+ if(ctrl && (ctrl->appl & 0xC0) == 0)
+ appl= &isdn_appl[ctrl->appl];
+ else if(ap < 0x30)
+ appl = &isdn_appl[ap];
+ else if(ap < 0x40)
+ appl = NULL;
+ else
+ {
+ reset_req(sc, 2,2);
+ return;
+ }
+
+ switch (mbx->type & 0x1f)
+ {
+ case 0: /* CONNECT CONF */
+ err = *(u_short *) mbx->data;
+ if(err || (appl == NULL) || (chan == NULL) || (ctrl == NULL))
+ {
+ if(chan) reset_plci(1, chan, pl);
+ if(appl) appl->state= 0;
+ break;
+ }
+
+ if (ISBUSY(ctrl->appl))
+ {
+ discon_req(8, sc, pl, 0, 0);
+ break;
+ }
+ chan->plci = pl;
+ chan->msg_nr= 0;
+ chan->ncci = -1;
+ ctrl->lastact = time.tv_sec;
+ ctrl->appl = ap;
+ appl->ctrl = chan->ctrl;
+ ctrl->islisten= 0;
+ chan->state = DIAL;
+ appl->state = 3;
+ break;
+
+ case 1: /* CONNECT IND */
+ if (ISBUSY(ctrl->appl))
+ {
+ discon_req(9, sc, pl, 0, 0);
+ break;
+ }
+ chan->plci = pl;
+ chan->msg_nr= 0;
+ chan->ncci = -1;
+ ctrl->lastact = time.tv_sec;
+ ctrl->appl = 0x7f;
+ ctrl->islisten= 1;
+ chan->state = CALLED;
+ mbx->data[mbx->data[3] + 4] = 0;
+ isdn_accept_con_ind(ap, chan->ctrl, mbx->data[0], mbx->data[1]
+ ,mbx->data[2], mbx->data[3], (char *) &mbx->data[4]);
+ break;
+
+ case 2: /* CONNECT ACTIVE IND */
+ con_act_resp(sc, pl);
+ if (IS_LISTEN(pl))
+ {
+ isdn_conn_ind(ctrl->appl,chan->ctrl,0);
+ break;
+ }
+ isdn_conn_ind(APPL(pl),chan->ctrl,1);
+ chan->state = CONNECT;
+ ctrl->appl = ap;
+ appl->ctrl = chan->ctrl;
+ break;
+
+ case 3: /* DISCONNECT CONF */
+ reset_plci(2, chan, pl);
+ break;
+
+ case 4: /* DISCONNECT IND */
+ discon_resp(sc, reset_plci(3, chan, pl));
+ break;
+
+ case 7: /* LISTEN CONF */
+ isdn_state = *(u_short *) mbx->data;
+ break;
+
+ case 10: /* INFO IND */
+ isdn_info(ap,*(u_short *)mbx->data, mbx->data[2], mbx->data+3);
+ inf_resp(sc, pl);
+ break;
+
+ default:
+ badstate(mbx,3,2,dpr);
+ }
+ reset_req(sc, 2,2);
+}
+
+static void
+s_intr(struct nic_softc * sc)
+{
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx = &dpr->dpr_mbx[0];
+ mbx_type *smbx = &dpr->dpr_mbx[1];
+
+ if (dpr->msg_flg[1])
+ return; /* should not happen. might make problems */
+ /* but there should be another intr., so what? */
+
+ bzero(smbx, 16);
+
+ switch (mbx->type & 0x1f)
+ {
+ case 0: /* INIT CONF */
+ break;
+ case 1: /* INIT IND */
+ smbx->type = mbx->type + 0x20;
+ dpr->msg_flg[1] = 1;
+ make_intr(1, sc);
+ break;
+ case 4: /* DNL MOD CONF */
+ sc->sc_stat = mbx->data[0];
+ if (sc->sc_flags)
+ sc->sc_flags = OPEN;
+ break;
+ case 6: /* DNL MOD IND */
+ smbx->type = mbx->type + 0x20;
+ smbx->data_len = 1;
+ smbx->data[0] = mbx->data[1];
+ sc->sc_stat = mbx->data[0];
+ if (sc->sc_flags)
+ sc->sc_flags = OPEN;
+ dpr->msg_flg[1] = 1;
+ make_intr(1, sc);
+ break;
+ case 0x0e: /* SET CLOCK CONF */
+ dpr->watchdog_cnt = 0xFF;
+ dpr->int_flg_pc = 0xFF;
+ dpr->api_active = 1;
+ break;
+ case 0x15: /* POLL IND */
+ dpr->watchdog_cnt = 0xFF;
+ dpr->int_flg_pc = 0xFF;
+ dpr->api_active = 1;
+ smbx->type = mbx->type + 0x20;
+ dpr->msg_flg[1] = 1;
+ make_intr(1, sc);
+ break;
+ case 0x1e: /* MANUFACT CONF */
+ if(((mbx->type >> 8) == 18 ) && (*mbx->data == 0)) /* LISTEN */
+ break;
+ badstate(mbx,4,0,dpr);
+ break;
+ case 0x1f: /* MANUFACT IND */
+ if((mbx->type >> 8) == 19 ) /* DATA */
+ {
+ u_char *b = (u_char *) dpr;
+ b += dpr->buf_ptr[0];
+ isdn_input(ispy_applnr, mbx->data_len, b, 0);
+ smbx->type = mbx->type + 0x20;
+ dpr->msg_flg[1] = 1;
+ make_intr(1, sc);
+ break;
+ }
+ default:
+ badstate(mbx,5,0,dpr);
+ }
+ reset_req(sc, 0, 3);
+}
+
+static void
+bs_intr(int mb, int c, struct nic_softc * sc)
+{
+ chan_t *chan = &sc->sc_chan[c];
+ isdn_ctrl_t *ctrl = &isdn_ctrl[chan->ctrl];
+
+ if (chan->state == ACTIVE)
+ {
+ if (chan->more)
+ {
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx = &dpr->dpr_mbx[mb];
+ u_char *b = (u_char *) dpr;
+
+ bzero(mbx, 20);
+ mbx->type = BD_DATA_B3_REQ;
+ if (mb == 7)
+ mbx->type |= 0x40;
+ *(u_short *) mbx->data = chan->ncci;
+ mbx->data[4] = chan->msg_nr;
+ b += dpr->buf_ptr[mb];
+ mbx->data_len = chan->more;
+ bcopy(chan->more_b, b, chan->more);
+
+ chan->more = 0;
+ ctrl->o_len = -1;
+
+ dpr->msg_flg[mb] = 3;
+ make_intr(mb, sc);
+
+ ctrl->lastact = time.tv_sec;
+ return;
+ }
+ bsintr &= ~(1 << c);
+ }
+}
+
+void
+nicintr(int unit)
+{
+ register struct nic_softc *sc = &nic_sc[unit];
+ dpr_type *dpr = sc->sc_dpr;
+
+ if (dpr->msg_flg[2])
+ d_intr(sc);
+ if (dpr->msg_flg[0])
+ s_intr(sc);
+ if (dpr->msg_flg[6])
+ b_intr(6, 1, sc);
+ if (dpr->msg_flg[4])
+ b_intr(4, 0, sc);
+ if (bsintr)
+ {
+ if (dpr->msg_flg[7] == 0)
+ bs_intr(7, 1, sc);
+ if (dpr->msg_flg[5] == 0)
+ bs_intr(5, 0, sc);
+ }
+}
+
+#endif /* NNIC > 0 */
diff --git a/sys/gnu/i386/isa/nic3008.h b/sys/gnu/i386/isa/nic3008.h
new file mode 100644
index 0000000..da82696
--- /dev/null
+++ b/sys/gnu/i386/isa/nic3008.h
@@ -0,0 +1,114 @@
+static char nic38hid[] = "@(#)$Id: nic3008.h,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: nic3008.h,v $
+ *
+ ******************************************************************************/
+
+/*
+ * This file defines the NICCY 3008 Interface.
+ * Copyright Dr. Neuhaus GmbH, Hamburg and Dietmar Friede
+ *
+*/
+
+#pragma pack (1)
+
+typedef struct {
+ u_short type; /* Message Subtype/Type */
+ u_char source;
+ u_char dest;
+ u_short number; /* laufende Nachrichten-Nummer */
+ u_short timeoutval; /* Wert fr Timeout */
+ u_char priority; /* Nachrichten-Priorit„t */
+ u_char more_data; /* Nachricht vollst„ndig? */
+ u_short data_len; /* Datenmenge */
+ u_char buf_valid; /* im aux. buf.? */
+ u_char reserved[1];
+ u_short add_info; /* Maske */
+ u_char data[0x30];/* Datenfeld */
+} mbx_type;
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct {
+/* Offset 0x0000 ---------------------------------------------------------- */
+ u_char msg_flg[8]; /* Messages in MBX i */
+ u_char card_number; /* Kartennummer of Applikation */
+ u_char card_state; /* Kartenstatus */
+ u_short mainloop_cnt; /* NICCY's M'loop,68000-Notation*/
+ u_char watchdog_cnt; /* Applikation "lebt"? */
+ u_char hw_config; /* Steckmodule? */
+ u_char jmp_config; /* Karten-Jumper? */
+ u_char ram_config; /* Karten-Speicher? */
+/* Offset 0x0010 -----------------------------------------------------------*/
+ char niccy_ver[0x0E]; /* "NICCY V x.yyy\c" */
+ u_char int_flg_pc; /* Will PC Interrupts? */
+ u_char int_flg_nic; /* Will NICCY Interrupts? */
+/* Offset 0x0020 -----------------------------------------------------------*/
+ u_short buf_ptr[8]; /* Pointer to aux. buf. ... */
+/* Offset 0x0030 -----------------------------------------------------------*/
+ u_short buf_len[8]; /* Size of aux. buf. ... */
+/* Offset 0x0040 -----------------------------------------------------------*/
+ /* 0x40 Bytes fr die */
+ /* frei verfgbar */
+ u_char old_flg[8]; /* Messages in MBX i */
+ u_char irq_level; /* welcher IRQ (als Bitmaske */
+ u_char res[7]; /* FREI */
+/* Offset 0x0050 -----------------------------------------------------------*/
+ u_char api_area_int_nr; /*SW-Int des API wenn API_ACTIVE*/
+ u_char api_area_PLCI[2]; /* PLCI w„hrend ApiManufacturer */
+ u_char capi_version[6]; /* Versionsnummer der CAPI */
+ u_char api_area[0x27]; /* FREI */
+/* Offset 0x0080 -----------------------------------------------------------*/
+ u_char api_active; /* Flag ob CAPI aktiv ist */
+ u_char ext_hw_config; /* Bit 0: UART 16550 */
+ /* Bit 1..7: reserved */
+ u_char dpr_hw_id[0x0E]; /* Hardware ID */
+/* Offset 0x0090 -----------------------------------------------------------*/
+ u_char dpr_listen_req;/* Anzahl Listen Request's */
+ u_char dpr_state_b1; /* state B1 channel */
+ /* 0x00 : channel ist frei */
+ /* 0x01 : Verbindungsaufb. Req */
+ /* 0x02 : Verbindungsaufb. Act */
+ /* 0x03 : Verbindung besteht */
+ /* 0x04 : eintreffender Ruf */
+ /* 0x05 : Verbindung angenommen */
+ /* 0x06 : Verbindungsabb. Req */
+ /* 0x07 : Verbindungsabb. laeuft*/
+ /* 0x08 : Verbindung getrennt */
+ u_char dpr_state_b2; /* state B2 channel (siehe oben)*/
+ u_char dpr_state_ic1; /* state of Intercomm-Channel */
+ u_char dpr_state_ic2; /* ----------- " -------------- */
+ u_char state_res[0x04];
+ u_char dpr_si_b1; /* Service Indicator auf B1 */
+ u_char dpr_si_b2; /* Service Indicator auf B2 */
+ u_char dpr_state_res_0[0x05];
+/* Offset 0x00A0 -----------------------------------------------------------*/
+ u_char dpr_state_hscx; /* state of HSCX */
+ u_char dpr_state_itac; /* state of ITAC */
+ u_char dpr_state_arcofi;/* state of ARCOFI */
+ u_char dpr_state_modem; /* state of Aufsteckmodem */
+ u_char dpr_state_com; /* state of COM */
+ u_char dpr_state_res[0x0B];
+/* Offset 0x00B0 -----------------------------------------------------------*/
+ u_char dpr_state_ia_tel;/* state of internal Appl. */
+ u_char dpr_state_ia_com;/* state of internal Appl. */
+ u_char dpr_state_ia_mod;/* state of internal Appl. */
+ u_char dpr_state_res_1[0x0D];
+/* Offset 0x00C0 -----------------------------------------------------------*/
+ u_char dpr_state_dcp[0x10];/* state of D-channel Prot */
+/* Offset 0x00D0 -----------------------------------------------------------*/
+ u_char reserved[0x130];
+/* Offset 0x0200 -----------------------------------------------------------*/
+ mbx_type dpr_mbx[8]; /* the mailboxes ... */
+} dpr_type;
+
+#pragma pack ()
diff --git a/sys/gnu/i386/isa/nic3009.c b/sys/gnu/i386/isa/nic3009.c
new file mode 100644
index 0000000..8062586
--- /dev/null
+++ b/sys/gnu/i386/isa/nic3009.c
@@ -0,0 +1,1209 @@
+static char nic39_id[] = "@(#)$Id: nic3009.c,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: nic3009.c,v $
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (c) 1994 Dietmar Friede (dietmar@friede.de) All rights reserved.
+ * FSF/FSAG GNU Copyright applies
+ *
+ * A low level driver for the NICCY-3009 ISDN Card.
+ *
+ */
+
+#include "nnic.h"
+#if NNNIC > 0
+
+#include "param.h"
+#include "ioctl.h"
+#include "kernel.h"
+#include "systm.h"
+
+#include "i386/isa/isa_device.h"
+#include "i386/isa/nic3009.h"
+#include "i386/isa/niccyreg.h"
+#include "isdn/isdn_ioctl.h"
+
+#define OPEN 1
+#define LOAD_HEAD 3
+#define LOAD_DATA 5
+#define LOAD_ENTITY 8
+#define IS_DIAL(p) (((p)&0x20)==0)
+#define IS_LISTEN(p) ((p)&0x20)
+#define CHAN(pl) (((pl)&7)-1)
+#define C_CHAN(x) ((x)&1)
+#define APPL(pl) ((((pl)>>6)&0x7f)-1)
+#define CARD(pl) (((pl)>>13)&7)
+#define MK_APPL(pl) (((pl)+1)<<6)
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+extern isdn_appl_t isdn_appl[];
+extern u_short isdn_state;
+extern isdn_ctrl_t isdn_ctrl[];
+extern int ispy_applnr;
+extern int Isdn_Appl, Isdn_Ctrl, Isdn_Typ;
+extern int hz;
+extern isdn_start_out();
+
+static old_spy= 0;
+
+int nnicprobe(), nnicattach();
+int nnic_connect(), nnic_listen(), nnic_disconnect(), nnic_accept();
+int nnic_output(), nnic_state();
+
+static discon_req(), sel_b2_prot_req(), reset_plci();
+static short bsintr;
+
+struct isa_driver nnidriver = {nnicprobe, nnicattach, "nnic"};
+
+typedef enum
+{
+ DISCON, ISDISCON, DIAL, CALLED, CONNECT, IDLE, ACTIVE
+} io_state;
+
+typedef struct
+{
+ char ctrl;
+ u_char msg_nr;
+ u_char morenr;
+ short plci;
+ short ncci;
+ short state;
+ short i_len;
+ char i_buf[2048];
+ char o_buf[2048];
+ u_short more;
+ char *more_b;
+} chan_t;
+
+struct nnic_softc
+{
+ dpr_type *sc_dpr; /* card RAM virtual memory base */
+ u_short sc_vector; /* interrupt vector */
+ short sc_port;
+ u_char sc_flags;
+ u_char sc_unit;
+ u_char sc_ctrl;
+ u_char sc_type;
+ short sc_stat;
+ chan_t sc_chan[2];
+} nnic_sc[NNNIC];
+
+
+int
+nnicprobe(struct isa_device * is)
+{
+ register struct nnic_softc *sc = &nnic_sc[is->id_unit & 127];
+ dpr_type *dpr;
+ u_char *w;
+ int i;
+
+ sc->sc_vector = is->id_irq;
+ sc->sc_port = is->id_iobase;
+ sc->sc_unit = is->id_unit;
+ w= (u_char *) dpr = sc->sc_dpr = (dpr_type *) is->id_maddr;
+
+ i= ffs(sc->sc_vector)-1;
+ if(i == 9) i= 1;
+ outb(sc->sc_port, 0);
+ outb(sc->sc_port+1, i);
+ outb(sc->sc_port, ((unsigned) dpr >> 12) & 0xff);
+
+/* There should be memory, so lets test that */
+ for (i=0;i<DPR_LEN;i++)
+ w[i] = (i+0xaf) & 0xff;
+ for (i=0;i<DPR_LEN;i++)
+ if (w[i] != ((i+0xaf) & 0xff))
+ {
+ printf("Niccy card not found or bad memory %x\n",is->id_maddr);
+ outb(sc->sc_port, 0);
+ return(0);
+ }
+ bzero(w,DPR_LEN-4);
+
+ is->id_msize = DPR_LEN;
+ return (2);
+}
+
+static void
+nnic_reset(struct nnic_softc *sc, int reset)
+{
+ u_char o;
+ o= ffs(sc->sc_vector)-1;
+ if(reset == 0)
+ o|= 0x80;
+ outb(sc->sc_port+1,o);
+}
+
+/*
+ * nnicattach() Install device
+ */
+int
+nnicattach(struct isa_device * is)
+{
+ struct nnic_softc *sc;
+ int cn;
+ isdn_ctrl_t *ctrl0, *ctrl1;
+
+ sc = &nnic_sc[is->id_unit];
+ sc->sc_ctrl = -1;
+ if ((cn = isdn_ctrl_attach(2)) == -1)
+ {
+ return (0);
+ }
+ sc->sc_ctrl = cn;
+ sc->sc_chan[0].plci = sc->sc_chan[1].plci = -1;
+
+ ctrl0 = &isdn_ctrl[cn];
+ ctrl1 = &isdn_ctrl[cn + 1];
+ sc->sc_chan[0].ctrl = ctrl0->ctrl = cn;
+ sc->sc_chan[1].ctrl = ctrl1->ctrl = cn + 1;
+ ctrl0->o_buf = sc->sc_chan[0].o_buf;
+ ctrl1->o_buf = sc->sc_chan[1].o_buf;
+ ctrl0->listen = ctrl1->listen = nnic_listen;
+ ctrl0->disconnect = ctrl1->disconnect = nnic_disconnect;
+ ctrl0->accept = ctrl1->accept = nnic_accept;
+ ctrl0->connect = ctrl1->connect = nnic_connect;
+ ctrl0->output = ctrl1->output = nnic_output;
+ ctrl0->state = ctrl1->state = nnic_state;
+ ctrl0->unit = ctrl1->unit = is->id_unit;
+ ctrl0->appl = ctrl1->appl = -1;
+ ctrl0->o_len = ctrl1->o_len = -1;
+ sc->sc_flags= LOAD_ENTITY;
+
+ return (1);
+}
+
+#define con_b3_req(unit,mb,pl) en_q(unit,mb|BD_CONN_B3_REQ,0,pl,0,NULL)
+#define con_act_resp(unit,pl) en_q(unit,DD_CONN_ACT_RSP,0, pl,0,NULL)
+#define discon_resp(sc,pl) en_q(unit,DD_DISC_RSP,0, pl,0,NULL)
+#define inf_resp(unit,pl) en_q(unit,DD_INFO_RSP,0, pl,0,NULL)
+#define listen_b3_req(unit,mb,pl) en_q(unit,mb|BD_LIST_B3_REQ,0,pl,0,NULL)
+
+/* If the Niccy card wants it: Interupt it. */
+static void
+make_intr(struct nnic_softc * sc)
+{
+ dpr_type *dpr = sc->sc_dpr;
+
+ dpr->watchdog_cnt = 0xFF;
+
+ if (dpr->int_flg_nic)
+ dpr->signal_pc_to_niccy++;
+}
+
+static int
+en_q(int unit, int t, int st, int pl, int l, u_char *b)
+{
+ struct nnic_softc * sc= &nnic_sc[unit];
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx = &dpr->dn_mbx;
+
+/*
+ if (dpr->card_state & ~4)
+ return (ENODEV);
+*/
+ if (mbx->msg_flag)
+ return (EBUSY);
+
+ bzero(&mbx->type, 18);
+ mbx->type = t;
+ mbx->subtype = st;
+ mbx->plci = pl;
+ if (l)
+ {
+ mbx->data_len = l;
+ bcopy(b, mbx->data, l);
+ }
+ mbx->msg_flag = 1;
+ make_intr(sc);
+ return (0);
+}
+
+static void
+badstate(mbx_type * mbx, int n, int mb, dpr_type *dpr)
+{
+ printf("Niccy: not implemented %x len %d at %d.", mbx->type,mbx->data_len,n);
+ if(mbx->data_len)
+ {
+ int i;
+
+ for(i=0; i<mbx->data_len; i++) printf(" %x",mbx->data[i]);
+ }
+ printf("\n");
+}
+
+int
+nnic_state(int cn)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ struct nnic_softc *sc = &nnic_sc[ctrl->unit];
+ chan_t *chan0 = &sc->sc_chan[0];
+ chan_t *chan1 = &sc->sc_chan[1];
+ dpr_type *dpr = sc->sc_dpr;
+
+ if(sc->sc_flags == LOAD_ENTITY)
+ return(ENODEV);
+ if (dpr->card_state & ~4 )
+ return (ENODEV);
+ if (dpr->card_state & 4 )
+ return (EAGAIN);
+ if(chan0->state && chan1->state)
+ return(EBUSY);
+ return(0);
+}
+
+int
+nnic_output(int cn)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ struct nnic_softc *sc = &nnic_sc[ctrl->unit];
+ chan_t *chan = &sc->sc_chan[C_CHAN(cn)];
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx = &dpr->dn_mbx;
+ int l;
+ int len= ctrl->o_len;
+
+ if (dpr->card_state /* & ~4 */)
+ return (ENODEV);
+
+ if (bsintr || (chan->ncci == -1) || mbx->msg_flag || (chan->state != IDLE))
+ return (EBUSY);
+
+ chan->state = ACTIVE;
+
+ bzero(&mbx->type, 20);
+ mbx->type = BD_DATA_B3_REQ;
+ if (C_CHAN(cn))
+ mbx->type |= 0x40;
+ *(u_short *) mbx->data = chan->ncci;
+ mbx->data[4] = chan->msg_nr;
+ l = min(DATAFIELD_LEN-5, len);
+ mbx->data_len = l+5;
+ bcopy(ctrl->o_buf, &mbx->data[5], l);
+
+ if (l < len)
+ {
+ chan->more = len - l;
+ chan->more_b = ctrl->o_buf + l;
+ mbx->more_data = 1;
+ bsintr = C_CHAN(cn)+1;
+ } else
+ {
+ chan->more = 0;
+ ctrl->o_len = -1;
+ bsintr= 0;
+ ++chan->msg_nr;
+ }
+
+ mbx->msg_flag = 1;
+ make_intr(sc);
+ ctrl->lastact = time.tv_sec;
+ return (0);
+}
+
+static int
+con_resp(int unit, int pl, int rea)
+{
+ return(en_q(unit, DD_CONN_RSP, 0, pl, 1, (u_char *) & rea));
+}
+
+static int
+reset_plci(int w, chan_t * chan, int p)
+{
+ isdn_ctrl_t *ctrl;
+
+ if (p == -1)
+ return (-1);
+
+ if(chan == NULL)
+ return(p);
+
+ ctrl = &isdn_ctrl[chan->ctrl];
+ if (chan->plci == p)
+ {
+ if (ISBUSY(ctrl->appl))
+ {
+ isdn_disconn_ind(ctrl->appl);
+ isdn_appl[ctrl->appl].ctrl = -1;
+ isdn_appl[ctrl->appl].state = 0;
+ }
+ ctrl->appl = -1;
+ ctrl->o_len = -1;
+ chan->plci = -1;
+ chan->ncci = -1;
+ chan->state = DISCON;
+ chan->i_len = 0;
+ chan->more = 0;
+ }
+ return (p);
+}
+
+static int
+sel_b2_prot_req(int unit, int c, int pl, dlpd_t * dlpd)
+{
+ return(en_q(unit, (c ? 0x40 : 0)| BD_SEL_PROT_REQ, 2, pl, sizeof(dlpd_t), (u_char *) dlpd));
+}
+
+static int
+sel_b3_prot_req(int unit, int mb, u_short pl, ncpd_t * ncpd)
+{
+ return(en_q(unit, mb | BD_SEL_PROT_REQ, 3, pl, sizeof(ncpd_t), (u_char *) ncpd));
+}
+
+static int
+discon_req(int w, int unit , int pl, int rea, int err)
+{
+ if((pl == 0) || (pl == -1))
+ return(0);
+ return(en_q(unit, DD_DISC_REQ,0, pl, 1, (u_char *) &rea));
+}
+
+static int
+con_b3_resp(int unit, int mb, u_short ncci, u_short pl, u_char reject)
+{
+ u_char buf[32];
+ int l = 4;
+
+ bzero(buf, 32);
+ *(u_short *) buf = ncci;
+ buf[2] = reject;
+ buf[3] = 0; /* ncpi ??? */
+ l += 15;
+ return(en_q(unit, mb | BD_CONN_B3_RSP,0, pl, l, buf));
+}
+
+int
+nnic_connect(int cn, int ap, int b_channel, int inf_mask, int out_serv
+ ,int out_serv_add, int src_subadr, unsigned ad_len
+ ,char *dest_addr, int spv)
+{
+ char buf[128];
+
+ if (ad_len > 118)
+ return (-1);
+
+ buf[0] = spv ? 0x53 : 0;
+ buf[1] = b_channel;
+ if (spv)
+ inf_mask |= 0x40000000;
+ *(u_long *) & buf[2] = inf_mask;
+ buf[6] = out_serv;
+ buf[7] = out_serv_add;
+ buf[8] = src_subadr;
+ buf[9] = ad_len;
+ bcopy(dest_addr, &buf[10], ad_len);
+ return (en_q(isdn_ctrl[cn].unit, DD_CONN_REQ, 0, MK_APPL(ap), ad_len + 10, buf));
+}
+
+int
+nnic_listen(int cn, int ap, int inf_mask, int subadr_mask, int si_mask, int spv)
+{
+ u_short sbuf[4];
+
+ if (spv)
+ inf_mask |= 0x40000000;
+ *(u_long *) sbuf = inf_mask;
+ sbuf[2] = subadr_mask;
+ sbuf[3] = si_mask;
+ return (en_q(isdn_ctrl[cn].unit, DD_LISTEN_REQ, 0, MK_APPL(ap), 8, (u_char *) sbuf));
+}
+
+int
+nnic_disconnect(int cn, int rea)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ chan_t *chan = &nnic_sc[ctrl->unit].sc_chan[C_CHAN(cn)];
+ int p, err;
+ u_char buf[16];
+
+ if(chan->ncci != -1)
+ {
+ bzero(buf,16);
+ *(u_short *) buf = chan->ncci;
+ err= en_q(ctrl->unit, (C_CHAN(cn)?0x40:0)|BD_DISC_B3_REQ, 0
+ , chan->plci, 3+sizeof(ncpi_t), buf);
+ if((err==0) && (ctrl->o_len == 0))
+ ctrl->o_len= -1;
+ return(err);
+ }
+ p = chan->plci;
+ if ((p == 0) || (p == -1))
+ return (ENODEV);
+
+ err= en_q(ctrl->unit, DD_DISC_REQ, 0, p, 1, (u_char *) &rea);
+ if((err==0) && (ctrl->o_len == 0))
+ ctrl->o_len= -1;
+ return(err);
+}
+
+int
+nnic_accept(int cn, int an, int rea)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ struct nnic_softc *sc = &nnic_sc[ctrl->unit];
+ chan_t *chan = &sc->sc_chan[C_CHAN(cn)];
+ isdn_appl_t *appl = &isdn_appl[an];
+
+ if(ISFREE(ctrl->appl))
+ return(ENODEV);
+
+ if (rea)
+ {
+ ctrl->appl= -1;
+ return(discon_req(1, ctrl->unit, chan->plci, rea, 0));
+ }
+ ctrl->appl= an;
+ ctrl->lastact = time.tv_sec;
+ appl->ctrl= cn;
+ appl->state= 4;
+
+ return(sel_b2_prot_req(ctrl->unit, C_CHAN(cn), chan->plci, &appl->dlpd));
+}
+
+int
+nnicopen(dev_t dev, int flag)
+{
+ struct nnic_softc *sc;
+ u_char unit;
+ int x;
+ unsigned error;
+ u_char b= 0xff;
+
+ unit = minor(dev);
+ /* minor number out of limits ? */
+ if (unit >= NNNIC)
+ return (ENXIO);
+ sc = &nnic_sc[unit];
+
+ x= splhigh();
+ /* Card busy ? */
+/*
+ if (sc->sc_flags & 7)
+ {
+ splx(x);
+ return (EBUSY);
+ }
+*/
+ sc->sc_flags |= OPEN;
+
+ splx(x);
+ return (0);
+}
+
+int
+nnicclose(dev_t dev, int flag)
+{
+ struct nnic_softc *sc = &nnic_sc[minor(dev)];
+
+ sc->sc_flags &= ~7;
+ return (0);
+}
+
+int
+nnicioctl(dev_t dev, int cmd, caddr_t data, int flag)
+{
+ int error;
+ int i, x;
+ struct nnic_softc *sc = &nnic_sc[minor(dev)];
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx= &dpr->dn_mbx;
+ u_char *p= (u_char *)dpr;
+ struct head *head = (struct head *) data;
+
+ error = 0;
+ switch (cmd)
+ {
+ case NICCY_DEBUG:
+ data[0]= 0x39;
+ bcopy(p, &data[1], 2044);
+ break;
+ case NICCY_LOAD:
+ switch(head->status)
+ {
+ case 0: /* Loading initial boot code */
+ x = splhigh();
+ nnic_reset(sc,1);
+ if(error = copyin(head->data+0x16,p, head->d_len-0x16))
+ {
+ splx(x);
+ return (error);
+ }
+ nnic_reset(sc,0);
+ i= hz;
+ while (p[7] && i--)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "l9_0", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+ nnic_reset(sc,1);
+ splx(x);
+ if(p[7]) return(ENODEV);
+ return(0);
+
+ case 1: /* Loading boot code */
+ x = splhigh();
+
+ if(error = copyin(head->data+0x64,p, head->d_len-0x64))
+ {
+ splx(x);
+ return (error);
+ }
+ nnic_reset(sc,0);
+ i= 5*hz;
+ while ((dpr->mainloop_cnt != 0x1147) && i--)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "l9_1", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+
+ if(dpr->mainloop_cnt != 0x1147)
+ {
+ splx(x);
+ return(ENODEV);
+ }
+
+ i= 1*hz;
+ while ((dpr->up_mbx.type != 1) && i--)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "l9_2", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+ if(dpr->up_mbx.type != 1)
+ {
+ splx(x);
+ return(ENODEV);
+ }
+ bzero(&mbx->type, 16);
+ dpr->up_mbx.msg_flag= 0;
+ mbx->type= 0x21;
+ mbx->msg_flag= 1;
+
+ i= 1*hz;
+ while (mbx->msg_flag && i--)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "l9_3", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+ if(mbx->msg_flag)
+ {
+ splx(x);
+ return(ENODEV);
+ }
+
+ head->status= 0;
+ splx(x);
+ return(0);
+
+ default:
+ x = splhigh();
+ while (mbx->msg_flag)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "l9_1h", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+
+ bzero(&mbx->type, 16);
+ mbx->type = MD_DNL_MOD_REQ;
+ mbx->subtype = head->typ;
+ sc->sc_type = head->typ;
+ mbx->data_len = 12;
+ bcopy(head->nam, mbx->data, 8);
+ *(u_long *) (mbx->data + 8) = head->len;
+
+ mbx->msg_flag = 1;
+ make_intr(sc);
+ i= 1*hz;
+ while ((dpr->up_mbx.msg_flag == 0) && i--)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "l9_2", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+
+ if((dpr->up_mbx.type != MU_DNL_MOD_CNF) || dpr->up_mbx.data[0])
+ {
+ dpr->up_mbx.msg_flag= 0;
+ make_intr(sc);
+ splx(x);
+ return(ENODEV);
+ }
+ dpr->up_mbx.msg_flag= 0;
+ make_intr(sc);
+ {
+ int len, l, off;
+ len= head->d_len;
+ off= 0;
+ l= 0x64;
+
+ while(len > 0)
+ {
+ while (mbx->msg_flag)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "l9_4load", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+ mbx->type = MD_DNL_MOD_DATA;
+ len-= l;
+ mbx->more_data = len > 0;
+ mbx->data_len = l;
+ if(error= copyin(head->data+off, mbx->data, l))
+ {
+ splx(x);
+ return (error);
+ }
+ off+= l;
+ l= min(len,512);
+ mbx->msg_flag = 1;
+ make_intr(sc);
+ }
+ }
+
+ i= 3*hz;
+ while ((dpr->up_mbx.msg_flag == 0) && i--)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "l9_2", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+ if(dpr->up_mbx.type == 0)
+ {
+ dpr->up_mbx.msg_flag= 0;
+ make_intr(sc);
+ i= 3*hz;
+ while ((dpr->up_mbx.msg_flag == 0) && i--)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "l9_3", 1);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return (error);
+ }
+ }
+ }
+
+ if(dpr->up_mbx.type != MU_DNL_MOD_IND)
+ {
+ dpr->up_mbx.msg_flag= 0;
+ make_intr(sc);
+ splx(x);
+ return(ENODEV);
+ }
+ head->status = dpr->up_mbx.data[0];
+ mbx->data[0] = dpr->up_mbx.data[1];
+ mbx->type= 0x20|MU_DNL_MOD_IND;
+ mbx->subtype = head->typ;
+ mbx->data_len = 1;
+ dpr->card_number = sc->sc_unit;
+ dpr->up_mbx.msg_flag= 0;
+ mbx->msg_flag= 1;
+ make_intr(sc);
+ splx(x);
+ return (0);
+ }
+ splx(x);
+ return(0);
+ case NICCY_SET_CLOCK:
+ x = splhigh();
+ dpr->int_flg_pc = 0xff;
+ dpr->card_number = sc->sc_unit;
+ if (mbx->msg_flag)
+ {
+ splx(x);
+ return (EBUSY);
+ }
+ bzero(&mbx->type, 16);
+ mbx->type = MD_SET_CLOCK_REQ;
+ mbx->data_len = 14;
+ bcopy(data, mbx->data, 14);
+
+ mbx->msg_flag = 1;
+ make_intr(sc);
+ splx(x);
+ return (0);
+ case NICCY_SPY:
+ x = splhigh();
+ if (mbx->msg_flag)
+ {
+ splx(x);
+ return (EBUSY);
+ }
+ bzero(&mbx->type, 16);
+ mbx->type = MD_MANUFACT_REQ;
+ mbx->subtype = 18;
+ mbx->data_len = 1;
+ mbx->plci = MK_APPL(ispy_applnr);
+/* There are ilegal states. So I use them to toggle */
+ if((data[0] == 0) && (old_spy == 0)) data[0]= 255;
+ else if(data[0] && old_spy ) data[0]= 0;
+ old_spy= mbx->data[0]= data[0];
+
+ mbx->msg_flag = 1;
+ make_intr(sc);
+ splx(x);
+ return (0);
+
+ case NICCY_RESET:
+ x = splhigh();
+ nnic_reset(sc,1);
+ bzero((u_char*)dpr,DPR_LEN);
+ sc->sc_flags= LOAD_ENTITY;
+ splx(x);
+ return (0);
+
+ default:
+ error = ENODEV;
+ }
+ return (error);
+}
+
+static void
+dn_intr(unsigned unit, struct nnic_softc * sc)
+{
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *mbx= &dpr->dn_mbx;
+ chan_t *chan;
+ isdn_ctrl_t *ctrl;
+ int c,l, len;
+
+ c= bsintr-1;
+ chan = &sc->sc_chan[c];
+ ctrl = &isdn_ctrl[chan->ctrl];
+
+ if ((chan->state == ACTIVE) && (chan->more))
+ {
+ len= chan->more;
+
+ bzero(&mbx->type, 20);
+ mbx->type = BD_DATA_B3_REQ;
+ if (c)
+ mbx->type |= 0x40;
+ *(u_short *) mbx->data = chan->ncci;
+ mbx->data[4] = chan->msg_nr;
+ l = min(DATAFIELD_LEN-5, len);
+ mbx->data_len = l+5;
+ bcopy(chan->more_b, &mbx->data[5], l);
+
+ if (l < len)
+ {
+ chan->more = len - l;
+ chan->more_b += l;
+ mbx->more_data = 1;
+ } else
+ {
+ chan->more = 0;
+ ctrl->o_len = -1;
+ bsintr= 0;
+ ++chan->msg_nr;
+ }
+
+ mbx->msg_flag = 1;
+ make_intr(sc);
+ ctrl->lastact = time.tv_sec;
+ return;
+ }
+ bsintr= 0;
+}
+
+static void
+up_intr(unsigned unit, struct nnic_softc * sc)
+{
+ dpr_type *dpr = sc->sc_dpr;
+ mbx_type *msg= &dpr->up_mbx;
+ chan_t *chan;
+ u_short n, mb, c, pl, err = 0;
+ isdn_ctrl_t *ctrl;
+ isdn_appl_t *appl;
+ int error= 0;
+
+ chan= NULL;
+ ctrl= NULL;
+ appl= NULL;
+ mb= 0;
+ pl = msg->plci;
+
+ if(pl && (msg->type >= 0x40) && (msg->type < 0xfd) && (msg->type != 0x47))
+ {
+ if ((c = CHAN(pl)) < 2)
+ {
+ chan = &sc->sc_chan[c];
+ ctrl = &isdn_ctrl[chan->ctrl];
+ } else
+ {
+ c = 0xffff;
+ chan= NULL;
+ ctrl= NULL;
+ }
+
+ if(ctrl && (ctrl->appl & 0xC0) == 0)
+ appl= &isdn_appl[ctrl->appl];
+ else if( APPL(pl) < 0x30)
+ appl = &isdn_appl[APPL(pl)];
+ else if( APPL(pl) < 0x40)
+ appl= NULL;
+ else goto fin;
+
+ if(msg->type >= 0x80)
+ {
+ mb= msg->type & 0x40;
+ msg->type &= 0xbf;
+ }
+ }
+
+ switch (msg->type)
+ {
+ case 0x01: /* INIT IND */
+ if(dpr->dn_mbx.msg_flag) return;
+ error= en_q(unit,msg->type|0x20,0,0,0,NULL);
+ break;
+ case 0x04: /* DNL MOD */
+ sc->sc_stat = msg->data[0];
+ if (sc->sc_flags )
+ sc->sc_flags = OPEN;
+ break;
+ case 0x06: /* DNL MOD IND */
+ if(dpr->dn_mbx.msg_flag) return;
+ sc->sc_stat = msg->data[0];
+ if (sc->sc_flags)
+ sc->sc_flags = OPEN;
+ if(sc->sc_stat)
+ break;
+ error= en_q(unit,msg->type|0x20,sc->sc_type,0,1, &msg->data[1]);
+ break;
+ case 0x0e: /* SET CLOCK CONF */
+ dpr->card_number = unit;
+/*
+ dpr->api_active = 1;
+ dpr->watchdog_cnt = 0xFF;
+ dpr->api_area[0] = 0;
+ dpr->api_area[2] = 0;
+*/
+ dpr->int_flg_pc = 0xFF;
+ break;
+ case 0x15: /* POLL IND */
+ if(dpr->dn_mbx.msg_flag) return;
+ dpr->api_active = 1;
+ dpr->watchdog_cnt = 0xFF;
+ dpr->int_flg_pc = 0xFF;
+ error= en_q(unit,msg->type|0x20,0,0,0,NULL);
+ break;
+ case 0x16: /* STATE IND */
+ if(dpr->dn_mbx.msg_flag) return;
+ if(sc->sc_flags & LOAD_ENTITY)
+ {
+ if(sc->sc_flags & 7)
+ sc->sc_flags = OPEN;
+ else sc->sc_flags= 0;
+ }
+ error= en_q(unit,msg->type|0x20,0,0,0,NULL);
+ break;
+ case 0x17: /* STATE RESP */
+ break;
+ case 0x1e: /* MANUFACT CONF */
+ if(msg->subtype == 18)
+ break;
+ badstate(msg,1,0,dpr);
+ break;
+ case 0x1f: /* MANUFACT IND */
+ if(msg->subtype == 19)
+ {
+ if(dpr->dn_mbx.msg_flag) return;
+ isdn_input(ispy_applnr, msg->data_len, msg->data,0);
+ error= en_q(unit,msg->type|0x20,msg->subtype,0,0,NULL);
+ break;
+ }
+ badstate(msg,2,0,dpr);
+ break;
+ case 0x40: /* CONNECT CONF */
+ err = *(u_short *) msg->data;
+ if (err || (appl == NULL) || (chan == NULL) || (ctrl == NULL))
+ {
+ if(chan) reset_plci(3, chan, pl);
+ if(appl) appl->state= 0;
+ break;
+ }
+ if (ISBUSY(ctrl->appl))
+ {
+ if(dpr->dn_mbx.msg_flag) return;
+ error= discon_req(2, unit, pl, 0, 0);
+ break;
+ }
+ chan->plci = pl;
+ chan->msg_nr = 0;
+ chan->ncci = -1;
+ ctrl->lastact = time.tv_sec;
+ ctrl->appl = APPL(pl);
+ appl->ctrl = chan->ctrl;
+ ctrl->islisten= 0;
+ chan->state = DIAL;
+ appl->state= 3;
+ break;
+
+ case 0x41: /* CONNECT IND */
+ if (ISBUSY(ctrl->appl))
+ {
+ if(dpr->dn_mbx.msg_flag) return;
+ error= discon_req(3, unit, pl, 0, 0);
+ break;
+ }
+ chan->plci = pl;
+ chan->msg_nr = 0;
+ chan->ncci = -1;
+ ctrl->lastact = time.tv_sec;
+ ctrl->appl = 0x7f;
+ ctrl->islisten= 1;
+ chan->state = CALLED;
+ msg->data[msg->data[3] + 4] = 0;
+ isdn_accept_con_ind(APPL(pl), chan->ctrl, msg->data[0], msg->data[1]
+ ,msg->data[2], msg->data[3], (char *) &msg->data[4]);
+ break;
+
+ case 0x42: /* CONNECT ACTIVE IND */
+ if(dpr->dn_mbx.msg_flag) return;
+ error= con_act_resp(unit, pl);
+ if (IS_LISTEN(pl))
+ {
+ isdn_conn_ind(ctrl->appl,chan->ctrl,0);
+ break;
+ }
+ isdn_conn_ind(APPL(pl),chan->ctrl,1);
+ chan->state = CONNECT;
+ ctrl->appl = APPL(pl);
+ appl->ctrl = chan->ctrl;
+ break;
+
+ case 0x43: /* DISCONNECT CONF */
+ reset_plci(4, chan, pl);
+ break;
+
+ case 0x44: /* DISCONNECT IND */
+ if(dpr->dn_mbx.msg_flag) return;
+ error= discon_resp(unit, reset_plci(5, chan, pl));
+ break;
+
+ case 0x47: /* LISTEN CONF */
+ isdn_state = *(u_short *) msg->data;
+ break;
+
+ case 0x4a: /* INFO IND */
+ if(dpr->dn_mbx.msg_flag) return;
+ isdn_info(APPL(pl),*(u_short *)msg->data, msg->data[2], msg->data+3);
+ error= inf_resp(unit, pl);
+ break;
+ case 0x80: /* SELECT PROT CONF */
+ if(dpr->dn_mbx.msg_flag) return;
+ err = *(u_short *) msg->data;
+ if (err)
+ {
+ error= discon_req(4, unit, pl, 0, err);
+ break;
+ }
+
+ switch (msg->subtype)
+ {
+ case 2:/* SELECT B2 PROTOCOL */
+ if(ISFREE(ctrl->appl))
+ break;
+ error= sel_b3_prot_req(unit, mb, pl, &isdn_appl[ctrl->appl].ncpd);
+ break;
+
+ case 3:/* SELECT B3 PROTOCOL */
+ if (IS_DIAL(pl))
+ error= con_b3_req(unit, mb, pl);
+ else
+ error= listen_b3_req(unit, mb, pl);
+ break;
+ }
+ break;
+
+ case 0x81: /* LISTEN B3 CONF */
+ if(dpr->dn_mbx.msg_flag) return;
+ err = *(u_short *) msg->data;
+ if (err)
+ {
+ error= discon_req(5, unit, pl, 0, err);
+ break;
+ }
+ error= con_resp(unit, pl, 0);
+ break;
+
+ case 0x82: /* CONNECT B3 CONF */
+ err = *(u_short *) (msg->data + 2);
+ n = *(u_short *) msg->data;
+
+ if (err)
+ {
+ if(dpr->dn_mbx.msg_flag) return;
+ error= discon_req(6, unit, pl, 0, err);
+ break;
+ }
+ if(ISFREE(ctrl->appl))
+ break;
+ chan->ncci = n;
+ chan->state = CONNECT;
+ break;
+
+ case 0x83: /* CONNECT B3 IND */
+ if(ISFREE(ctrl->appl))
+ break;
+ if(dpr->dn_mbx.msg_flag) return;
+ n = *(u_short *) msg->data;
+ chan->ncci = n;
+ chan->state = CONNECT;
+ error= con_b3_resp(unit, mb, n, pl, 0);
+ break;
+
+ case 0x84: /* CONNECT B3 ACTIVE IND */
+ if(ISFREE(ctrl->appl))
+ break;
+ if (chan->state < IDLE)
+ {
+ chan->state = IDLE;
+ ctrl->o_len = 0;
+ timeout(isdn_start_out,chan->ctrl,hz/5);
+ }
+ break;
+
+ case 0x85: /* DISCONNECT B3 CONF */
+ if(ISBUSY(ctrl->appl))
+ chan->state = ISDISCON;
+ err = *(u_short *) (msg->data + 2);
+ if (err)
+ {
+ if(dpr->dn_mbx.msg_flag) return;
+ error= discon_req(7, unit, pl, 0, err);
+ break;
+ }
+ break;
+ case 0x86: /* DISCONNECT B3 IND */
+ if(dpr->dn_mbx.msg_flag) return;
+ if(ISBUSY(ctrl->appl))
+ chan->state = ISDISCON;
+ err = *(u_short *) (msg->data + 2);
+ error= discon_req(8, unit, pl, 0, err);
+ break;
+
+ case 0x88: /* DATA B3 CONF */
+ if(ISFREE(ctrl->appl))
+ break;
+ err = *(u_short *) (msg->data + 2);
+ if (err)
+ {
+ ctrl->send_err++;
+ isdn_appl[ctrl->appl].send_err++;
+ }
+ chan->state = IDLE;
+ ctrl->o_len = 0;
+ isdn_start_out(chan->ctrl);
+ break;
+
+ case 0x89: /* DATA B3 IND */
+ if(ISFREE(ctrl->appl))
+ break;
+ if (msg->more_data)
+ {
+ if(chan->i_len)
+ {
+ if((chan->morenr != msg->data[4]) || ((chan->i_len + msg->data_len - 5) > 2048))
+ break;
+ }
+ else
+ chan->morenr= msg->data[4];
+ bcopy(msg->data+5, &chan->i_buf[chan->i_len], msg->data_len-5);
+ chan->i_len += msg->data_len -5;
+ break;
+ } /* msg->more_data == 0 */
+ if (chan->i_len)
+ {
+ int l;
+
+ if(chan->morenr != msg->data[4])
+ break;
+
+ if ((l = chan->i_len + msg->data_len - 5) <= 2048)
+ {
+ bcopy(msg->data+5, &chan->i_buf[chan->i_len], msg->data_len);
+ if(isdn_input(ctrl->appl, l, chan->i_buf, ctrl->islisten))
+ ctrl->lastact = time.tv_sec;
+ }
+ chan->i_len = 0;
+ break;
+ } /* chan->i_len == 0 && msg->more_data == 0 */
+ if(isdn_input(ctrl->appl, msg->data_len-5, msg->data+5,ctrl->islisten))
+ ctrl->lastact = time.tv_sec;
+ break;
+
+ default:
+ badstate(msg,3,mb,dpr);
+ break;
+ }
+
+fin:
+ if(error)
+ {
+printf("E?%x",error);
+ return;
+ }
+ msg->msg_flag= 0;
+ timeout(make_intr,sc,1);
+}
+
+static void
+nnnicintr(unsigned unit)
+{
+ register struct nnic_softc *sc = &nnic_sc[unit];
+ dpr_type *dpr = sc->sc_dpr;
+
+ if(dpr->up_mbx.msg_flag)
+ up_intr(unit,sc);
+ if (bsintr && (dpr->dn_mbx.msg_flag == 0))
+ dn_intr(unit,sc);
+}
+void
+nnicintr(unsigned unit)
+{
+ timeout(nnnicintr,unit,1);
+}
+
+#endif /* NNNIC > 0 */
diff --git a/sys/gnu/i386/isa/nic3009.h b/sys/gnu/i386/isa/nic3009.h
new file mode 100644
index 0000000..223619f
--- /dev/null
+++ b/sys/gnu/i386/isa/nic3009.h
@@ -0,0 +1,79 @@
+static char nic39hid[] = "@(#)$Id: nic3009.h,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: nic3009.h,v $
+ *
+ ******************************************************************************/
+
+/*
+ * This file defines the NICCY 3009 Interface. Copyright Dr. Neuhaus GmbH,
+ * Hamburg and Dietmar Friede
+ *
+ */
+
+#define NO_MORE_DATA 0x00 /* der Message folgen keine Daten */
+#define MORE_DATA 0x01 /* der Message folgen weitere Daten */
+
+#define DPR_LEN 0x800 /* 2 kBytes gross */
+#define DPR_VAR_AREA_LEN 0x100 /* davon fuer allg. Variablen */
+
+#define DPR_MBX_LEN (DPR_LEN-DPR_VAR_AREA_LEN)/2 /* 0x380 lang */
+#define DPR_MBX_FLAG_LEN 2 /* zwei Bytes MBX-Zustand... */
+#define DPR_MSG_HDR_LEN 10 /* Msg-Laenge ohne Datafield */
+#define DATAFIELD_LEN (DPR_MBX_LEN-DPR_MBX_FLAG_LEN-DPR_MSG_HDR_LEN)
+#define MAX_B3_LEN (2048+2) /* Daten und Network-Header */
+
+#pragma pack (1)
+typedef struct
+{
+ u_char msg_flag; /* Signalisierung NICCY / PC */
+ u_char progress; /* NICCY-interne Verwendung ! */
+ u_char type;
+ u_char subtype;
+ u_short number;
+ u_char more_data;
+ u_char reserved;
+ u_short data_len;
+ u_short plci;
+ u_char data[DATAFIELD_LEN];
+} mbx_type;
+
+typedef struct
+{
+ mbx_type up_mbx; /* Offset 0x000-0x37F */
+ mbx_type dn_mbx; /* Offset 0x380-0x6FF */
+ u_char card_number; /* Offset 0x700 */
+ u_char card_state; /* Offset 0x701 */
+ u_short mainloop_cnt; /* Offset 0x702-0x703 */
+ u_char watchdog_cnt; /* Offset 0x704 */
+ u_char hw_config; /* Offset 0x705 */
+ u_char int_flg_pc; /* Offset 0x706 */
+ u_char int_flg_nic; /* Offset 0x707 */
+ u_char api_area[64]; /* Offset 0x708-0x747 */
+ u_char api_active; /* Offset 0x748 */
+ u_char tei; /* Offset 0x749 */
+ u_char state_b1; /* Offset 0x74A */
+ u_char state_b2; /* Offset 0x74B */
+ u_char si_b1; /* Offset 0x74C */
+ u_char si_b2; /* Offset 0x74D */
+ u_short calls_in; /* Offset 0x74E-0x74F */
+ u_short calls_out; /* Offset 0x750-0x751 */
+ u_char ram_config; /* Offset 0x752 */
+ u_char spv_request_flag; /* Offset 0x753 */
+ u_char dcp_state_b1; /* Offset 0x754 */
+ u_char dcp_state_b2; /* Offset 0x755 */
+ u_char dc_protocol; /* Offset 0x756 */
+ u_char poll_flag; /* Offset 0x757 */
+ u_char debug[DPR_LEN - 0x758 - 4]; /* Offset 0x758-0x7FB */
+ u_short signal_niccy_to_pc; /* Offset 0x7FC-0x7FD */
+ u_short signal_pc_to_niccy; /* Offset 0x7FE-0x7FF */
+} dpr_type;
+#pragma pack ()
diff --git a/sys/gnu/i386/isa/niccyreg.h b/sys/gnu/i386/isa/niccyreg.h
new file mode 100644
index 0000000..a9d8328
--- /dev/null
+++ b/sys/gnu/i386/isa/niccyreg.h
@@ -0,0 +1,158 @@
+static char nicregh_id[] = "@(#)$Id: niccyreg.h,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: niccyreg.h,v $
+ *
+ ******************************************************************************/
+
+/*
+ * This file defines the NICCY 3008 Interface.
+ * Copyright Dr. Neuhaus GmbH, Hamburg and Dietmar Friede
+ *
+*/
+
+#define MBX_MU 0
+#define MBX_MD 1
+#define MBX_DU 2
+#define MBX_DD 3
+#define MBX_B1U 4
+#define MBX_B1D 5
+#define MBX_B2U 6
+#define MBX_B2D 7
+
+#define MBX_xU 0x55
+#define MBX_xD 0xAA
+
+/* -------------------------------------------------------------------- */
+
+#define MU_INIT_CNF 0x00
+#define MU_INIT_IND 0x01
+#define MU_RESET_CNF 0x02
+#define MU_HANDSET_IND 0x03
+#define MU_DNL_MOD_CNF 0x04
+/* reserved: 0x05 */
+#define MU_DNL_MOD_IND 0x06
+#define MU_DISC_MOD_CNF 0x07
+#define MU_LIST_MOD_CNF 0x08
+#define MU_LIST_MOD_DATA 0x09
+/* reserved: 0x0A to 0x0B */
+#define MU_HW_CONFIG_CNF 0x0C
+#define MU_HW_ID_CNF 0x0D
+#define MU_SET_CLOCK_CNF 0x0E
+#define MU_GET_CLOCK_CNF 0x0F
+#define MU_ACT_IA_CNF 0x10
+#define MU_ACT_IA_IND 0x11
+#define MU_DEACT_IA_CNF 0x12
+#define MU_DEACT_IA_IND 0x13
+#define MU_POLL_CNF 0x14
+#define MU_POLL_IND 0x15
+/* reserved: 0x16 to 0x1D */
+#define MU_MANUFACT_CNF 0x1E
+#define MU_MANUFACT_IND 0x1F
+
+/*---------------------------------------------------------------------------*/
+
+#define MD_INIT_REQ 0x20
+#define MD_INIT_RSP 0x21
+#define MD_RESET_REQ 0x22
+#define MD_HANDSET_RSP 0x23
+#define MD_DNL_MOD_REQ 0x24
+#define MD_DNL_MOD_DATA 0x25
+#define MD_DNL_MOD_RSP 0x26
+#define MD_DISC_MOD_REQ 0x27
+#define MD_LIST_MOD_REQ 0x28
+/* reserved: 0x29 to 0x2B */
+#define MD_HW_CONFIG_REQ 0x2C
+#define MD_HW_ID_REQ 0x2D
+#define MD_SET_CLOCK_REQ 0x2E
+#define MD_GET_CLOCK_REQ 0x2F
+#define MD_ACT_IA_REQ 0x30
+#define MD_ACT_IA_RSP 0x31
+#define MD_DEACT_IA_REQ 0x32
+#define MD_DEACT_IA_RSP 0x33
+#define MD_POLL_REQ 0x34
+#define MD_POLL_RSP 0x35
+#define MD_STATE_IND 0x37
+#define MD_MANUFACT_REQ 0x3E
+#define MD_MANUFACT_RSP 0x3F
+
+/*---------------------------------------------------------------------------*/
+
+#define DU_CONN_CNF 0x40
+#define DU_CONN_IND 0x41
+#define DU_CONN_ACT_IND 0x42
+#define DU_DISC_CNF 0x43
+#define DU_DISC_IND 0x44
+#define DU_DATA_CNF 0x45
+#define DU_DATA_IND 0x46
+#define DU_LISTEN_CNF 0x47
+#define DU_GET_PAR_CNF 0x48
+#define DU_INFO_CNF 0x49
+#define DU_INFO_IND 0x4A
+#define DU_CONN_INFO_CNF 0x4B
+#define DU_REL_PLCI_CNF 0x4C
+/* reserved: 0x4C to 0x5E */
+#define DU_STR_NOT_COMP 0x5F
+
+/*---------------------------------------------------------------------------*/
+
+#define DD_CONN_REQ 0x60
+#define DD_CONN_RSP 0x61
+#define DD_CONN_ACT_RSP 0x62
+#define DD_DISC_REQ 0x63
+#define DD_DISC_RSP 0x64
+#define DD_DATA_REQ 0x65
+#define DD_DATA_RSP 0x66
+#define DD_LISTEN_REQ 0x67
+#define DD_GET_PAR_REQ 0x68
+#define DD_INFO_REQ 0x69
+#define DD_INFO_RSP 0x6A
+#define DD_CONN_INFO_REQ 0x6B
+#define DD_REL_PLCI_REQ 0x6C
+
+/*---------------------------------------------------------------------------*/
+
+#define BD_SEL_PROT_REQ 0xA0
+#define BD_LIST_B3_REQ 0xA1
+#define BD_CONN_B3_REQ 0xA2
+#define BD_CONN_B3_RSP 0xA3
+#define BD_C_B3_ACT_RSP 0xA4
+#define BD_DISC_B3_REQ 0xA5
+#define BD_DISC_B3_RSP 0xA6
+#define BD_GET_P_B3_REQ 0xA7
+#define BD_DATA_B3_REQ 0xA8
+#define BD_DATA_B3_RSP 0xA9
+#define BD_RESET_B3_REQ 0xAA
+#define BD_RESET_B3_RSP 0xAB
+
+/*---------------------------------------------------------------------------*/
+
+
+#define NICCY_DEBUG _IOWR('N',1,dbg_type)
+#define NICCY_RESET _IOWR('N',2,int)
+#define NICCY_LOAD _IOWR('N',3,struct head)
+#define NICCY_SET_CLOCK _IOWR('N',4,time_str_t)
+#define NICCY_SPY _IOWR('N',5,int)
+
+struct head
+{
+ u_long len;
+ u_long sig;
+ char nam[8];
+ char ver[5];
+ u_char typ;
+ u_short status;
+ u_long d_len;
+ u_char *data;
+};
+
+typedef char time_str_t[14];
+typedef u_char dbg_type[10000];
diff --git a/sys/gnu/isdn/if_ii.c b/sys/gnu/isdn/if_ii.c
new file mode 100644
index 0000000..c02657e
--- /dev/null
+++ b/sys/gnu/isdn/if_ii.c
@@ -0,0 +1,245 @@
+static char _if_iiid[] = "@(#)$Id: if_ii.c,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: if_ii.c,v $
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (c) 1994 Dietmar Friede (dietmar@friede.de) All rights reserved.
+ * FSF/FSAG GNU Copyright applies
+ *
+ * A high level ip isdn driver.
+ *
+ * Uses loop driver as template. Small - and simple - is beautiful.
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "mbuf.h"
+#include "socket.h"
+#include "errno.h"
+#include "ioctl.h"
+#include "protosw.h"
+
+#include "net/if.h"
+#include "net/if_types.h"
+#include "net/netisr.h"
+#include "net/route.h"
+
+#ifdef INET
+#include "netinet/in.h"
+#include "netinet/in_systm.h"
+#include "netinet/in_var.h"
+#include "netinet/ip.h"
+#endif
+
+#include "ii.h"
+#include "isdn/isdn_ioctl.h"
+
+#define IIMTU 1500
+
+static struct ifnet ii_if[NII];
+static int applnr[NII];
+static int next_if = 0;
+int iioutput(), ii_ioctl();
+
+int
+iiattach(int ap)
+{
+ register struct ifnet *ifp;
+
+ if (next_if >= NII)
+ return -1;
+
+ applnr[next_if] = ap;
+ ifp = &ii_if[next_if];
+ ifp->if_unit = next_if;
+ ifp->if_name = "ii";
+ ifp->if_mtu = IIMTU;
+ ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT ;
+ ifp->if_ioctl = ii_ioctl;
+ ifp->if_output = iioutput;
+ ifp->if_type = IFT_ISDNBASIC;
+ ifp->if_hdrlen = 0;
+ ifp->if_addrlen = 0;
+ ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ if_attach(ifp);
+ /* ifp->if_flags |= IFF_RUNNING; */
+ return next_if++;
+}
+
+int
+iioutput(struct ifnet * ifp, struct mbuf * m, struct sockaddr * dst)
+{
+ int s, isr;
+ register struct ifqueue *ifq = 0;
+
+ if (dst->sa_family != AF_INET)
+ {
+ m_freem(m);
+ return EAFNOSUPPORT;
+ }
+ s = splhigh();
+ if (IF_QFULL(&ifp->if_snd))
+ {
+ IF_DROP(&ifp->if_snd);
+ m_freem(m);
+ ifp->if_oerrors++;
+ isdn_output(applnr[ifp->if_unit]);
+ splx(s);
+ return (ENOBUFS);
+ }
+ IF_ENQUEUE(&ifp->if_snd, m);
+
+ ifp->if_opackets++;
+ ifp->if_obytes += m->m_pkthdr.len;
+
+ isdn_output(applnr[ifp->if_unit]);
+ splx(s);
+ return (0);
+}
+
+int
+ii_input(int no, int len, char *buf)
+{
+ int error = 0;
+ struct mbuf *m;
+ struct ifnet *ifp = &(ii_if[no]);
+ int s;
+
+ s = splhigh();
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == 0)
+ {
+ splx(s);
+ return (0);
+ }
+
+ if (len >= MHLEN)
+ {
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0)
+ {
+ (void) m_free(m);
+ splx(s);
+ return (0);
+ }
+ }
+ bcopy((caddr_t) buf, mtod(m, caddr_t), len);
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = len;
+ m->m_len = len;
+
+ if (IF_QFULL(&ipintrq))
+ {
+ IF_DROP(&ipintrq);
+ ifp->if_ierrors++;
+ m_freem(m);
+ splx(s);
+ return(0);
+ }
+ IF_ENQUEUE(&ipintrq, m);
+ ifp->if_ipackets++;
+ schednetisr(NETISR_IP);
+ splx(s);
+ return(len);
+}
+
+int
+ii_connect(int no)
+{
+ struct ifnet *ifp = &ii_if[no];
+ ifp->if_flags |= IFF_RUNNING;
+}
+
+int
+ii_disconnect(int no)
+{
+ struct ifnet *ifp = &ii_if[no];
+ ifp->if_flags &= ~IFF_RUNNING;
+}
+
+int
+ii_out(int no, char *buf, int len)
+{
+ struct ifnet *ifp = &ii_if[no];
+ struct mbuf *m0, *m;
+ int l;
+
+ IF_DEQUEUE(&ifp->if_snd, m);
+ if (m == 0)
+ {
+ return (0);
+ }
+ /*
+ * Copy the mbuf chain into the transmit buf
+ */
+ l = 0;
+ for (m0 = m; m != 0; m = m->m_next)
+ {
+ if((l+= m->m_len) > len)
+ {
+ m_freem(m0);
+ return(0);
+ }
+ bcopy(mtod(m, caddr_t), buf, m->m_len);
+ buf += m->m_len;
+ }
+ m_freem(m0);
+
+ return (l);
+}
+
+/*
+ * Process an ioctl request.
+ */
+int
+ii_ioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ int cmd;
+ caddr_t data;
+{
+ struct ifaddr *ifa = (struct ifaddr *) data;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int s;
+
+ switch (cmd)
+ {
+ case SIOCSIFDSTADDR:
+ case SIOCAIFADDR:
+ case SIOCSIFADDR:
+ if (ifa->ifa_addr->sa_family != AF_INET)
+ return(EAFNOSUPPORT);
+ ifp->if_flags |= IFF_UP;
+ /* FALLTHROUGH */
+ case SIOCSIFFLAGS:
+ s= splhigh();
+ if((!(ifp->if_flags & IFF_UP)) && (ifp->if_flags & IFF_RUNNING))
+ {
+ isdn_disconnect(applnr[ifp->if_unit],0);
+ ifp->if_flags &= ~IFF_RUNNING;
+ }
+ break;
+ case SIOCSIFMTU:
+ ifr->ifr_metric = ifp->if_mtu;
+ break;
+ case SIOCGIFMTU:
+ if(ifr->ifr_metric < 2048)
+ return(EAFNOSUPPORT);
+ ifp->if_mtu = ifr->ifr_metric;
+ break;
+ default:
+printf("IIO %x",cmd);
+ return(EINVAL);
+ }
+ return(0);
+}
diff --git a/sys/gnu/isdn/iispy.c b/sys/gnu/isdn/iispy.c
new file mode 100644
index 0000000..e426f1d
--- /dev/null
+++ b/sys/gnu/isdn/iispy.c
@@ -0,0 +1,171 @@
+static char _ispyid[] = "@(#)$Id: iispy.c,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: iispy.c,v $
+ *
+ ******************************************************************************/
+
+#include "ispy.h"
+#if NISPY > 0
+
+#include "param.h"
+#include "buf.h"
+#include "systm.h"
+#include "ioctl.h"
+#include "tty.h"
+#include "proc.h"
+#include "user.h"
+#include "uio.h"
+#include "kernel.h"
+/*#include "malloc.h"*/
+
+#include "isdn/isdn_ioctl.h"
+
+int ispyattach();
+
+int nispy = NISPY;
+int ispy_applnr;
+static int next_if =0;
+static unsigned long ispy_cnt, ispy_out;
+static char dir;
+#define ISPY_SIZE 260
+#define OPEN 1
+#define READ_WAIT 2
+#define ISPYBUF 16
+#define ISPYMASK (ISPYBUF-1)
+/* ISPYBUF has to be a power of 2 */
+
+static
+struct ispy_data
+{
+ struct ispy_buf
+ {
+ unsigned long cnt;
+ struct timeval stamp;
+ char ibuf[ISPY_SIZE];
+ unsigned char dir;
+ int ilen;
+ } b[ISPYBUF];
+ int state;
+} ispy_data[NISPY];
+
+int
+ispyattach(int ap)
+{
+ struct ispy_data *ispy;
+ if(next_if >= NISPY)
+ return(-1);
+ ispy= &ispy_data[next_if];
+ ispy->state= 0;
+ ispy_applnr= ap;
+ return(next_if++);
+}
+
+int
+ispy_input(int no, int len, char *buf, int out)
+{
+ struct ispy_data *ispy= &ispy_data[no];
+ struct ispy_buf *b= &ispy->b[ispy_cnt&ISPYMASK];
+
+ if(len > ISPY_SIZE)
+ return(0);
+ if(len)
+ {
+ b->cnt= ispy_cnt++;
+ b->stamp= time;
+ b->dir= out;
+ bcopy(buf, b->ibuf, len);
+ }
+ b->ilen= len;
+ if(ispy->state & READ_WAIT)
+ {
+ ispy->state &= ~READ_WAIT;
+ wakeup((caddr_t) &ispy->state);
+ }
+ return(len);
+}
+
+int
+ispyopen(dev_t dev, int flag)
+{
+ int err;
+ struct ispy_data *ispy;
+
+ if (minor(dev)>NISPY)
+ return (ENXIO);
+
+ ispy= &ispy_data[minor(dev)];
+
+ if(ispy->state&OPEN) return(EBUSY);
+ ispy->state |= OPEN;
+
+ return (0);
+}
+
+int
+ispyclose(dev_t dev, int flag)
+{
+ struct ispy_data *ispy= &ispy_data[minor(dev)];
+
+ if(ispy->state & READ_WAIT)
+ wakeup((caddr_t) &ispy->state);
+ ispy->state = 0;
+ return (0);
+}
+
+int
+ispyioctl (dev, cmd, data, flag)
+dev_t dev;
+caddr_t data;
+int cmd, flag;
+{
+ int unit = minor(dev);
+
+ switch (cmd) {
+ default:
+ return (ENOTTY);
+ }
+ return (0);
+}
+
+int
+ispyread(dev_t dev, struct uio * uio)
+{
+ int x;
+ int error = 0;
+ struct ispy_data *ispy= &ispy_data[minor(dev)];
+ struct ispy_buf *b;
+
+ if((ispy_cnt-ispy_out) > ISPYBUF)
+ ispy_out= ispy_cnt - ISPYBUF;
+ b= &ispy->b[ispy_out&ISPYMASK];
+ ispy_out++;
+ while(b->ilen == 0)
+ {
+ ispy->state |= READ_WAIT;
+ if(error= tsleep((caddr_t) &ispy->state, TTIPRI | PCATCH, "ispy", 0 ))
+ return(error);
+ }
+
+ x = splhigh();
+ if(b->ilen)
+ {
+ error = uiomove((char *) &b->dir, 1, uio);
+ if(error == 0)
+ error = uiomove((char *) &b->cnt
+ ,sizeof(unsigned long)+sizeof(struct timeval)+b->ilen, uio);
+ b->ilen= 0;
+ }
+ splx(x);
+ return error;
+}
+
+#endif
diff --git a/sys/gnu/isdn/iitel.c b/sys/gnu/isdn/iitel.c
new file mode 100644
index 0000000..bf2b72a
--- /dev/null
+++ b/sys/gnu/isdn/iitel.c
@@ -0,0 +1,234 @@
+static char _itelid[] = "@(#)$Id: iitel.c,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: iitel.c,v $
+ *
+ ******************************************************************************/
+
+#include "itel.h"
+#if NITEL > 0
+
+#include "param.h"
+#include "buf.h"
+#include "systm.h"
+#include "ioctl.h"
+#include "tty.h"
+#include "proc.h"
+#include "user.h"
+#include "uio.h"
+#include "kernel.h"
+#include "malloc.h"
+
+#include "isdn/isdn_ioctl.h"
+
+int itelattach();
+
+int nitel = NITEL;
+static int applnr[NITEL];
+static int next_if =0;
+#define ITEL_SIZE 1024
+#define OPEN 1
+#define CONNECT 2
+#define READ_WAIT 4
+#define WRITE_WAIT 8
+#define min(a,b) ((a)<(b)?(a):(b))
+
+static
+struct itel_data
+{
+ char ibuf[ITEL_SIZE];
+ char obuf[ITEL_SIZE];
+ int state;
+ int ilen, olen;
+} itel_data[NITEL];
+
+int
+itelattach(int ap)
+{
+ struct itel_data *itel;
+ if(next_if >= NITEL)
+ return(-1);
+ itel= &itel_data[next_if];
+ itel->ilen= itel->olen= 0;
+ itel->state= 0;
+ applnr[next_if]= ap;
+ return(next_if++);
+}
+
+int
+itel_input(int no, int len, char *buf)
+{
+ struct itel_data *itel= &itel_data[no];
+
+ if(itel->ilen || ( len > ITEL_SIZE))
+ return(0);
+ if(len)
+ bcopy(buf, itel->ibuf, len);
+ itel->ilen= len;
+ if(itel->state & READ_WAIT)
+ {
+ itel->state &= ~READ_WAIT;
+ wakeup((caddr_t) itel->ibuf);
+ }
+ return(len);
+}
+
+int
+itel_out(int no, char *buf, int len)
+{
+ struct itel_data *itel= &itel_data[no];
+ int l;
+
+ if((itel->state & CONNECT) == 0)
+ return(0);
+ if((l= itel->olen) && (itel->olen <= len))
+ bcopy(itel->obuf, buf, l);
+
+ itel->olen= 0;
+ if(itel->state & WRITE_WAIT)
+ {
+ itel->state &= ~WRITE_WAIT;
+ wakeup((caddr_t) itel->obuf);
+ }
+ return(l);
+}
+
+void
+itel_connect(int no)
+{
+ itel_data[no].state |= CONNECT;
+}
+
+void
+itel_disconnect(int no)
+{
+ struct itel_data *itel= &itel_data[no];
+ int s;
+
+ s= itel->state;
+ if(itel->state &= OPEN)
+ {
+ itel->ilen= itel->olen= 0;
+ if(s & READ_WAIT)
+ wakeup((caddr_t) itel->ibuf);
+ if(s & WRITE_WAIT)
+ wakeup((caddr_t) itel->obuf);
+ }
+}
+
+int
+itelopen(dev_t dev, int flag)
+{
+ int err;
+ struct itel_data *itel;
+
+ if (minor(dev)>NITEL)
+ return (ENXIO);
+
+ itel= &itel_data[minor(dev)];
+ if((itel->state & CONNECT) == 0)
+ return(EIO);
+
+ if(itel->state&OPEN) return(0);
+ itel->ilen= itel->olen= 0;
+ itel->state |= OPEN;
+
+ return (0);
+}
+
+int
+itelclose(dev_t dev, int flag)
+{
+ struct itel_data *itel= &itel_data[minor(dev)];
+
+ if(itel->state & READ_WAIT)
+ wakeup((caddr_t) itel->ibuf);
+ if(itel->state & WRITE_WAIT)
+ wakeup((caddr_t) itel->obuf);
+ itel_data[minor(dev)].state &= CONNECT;
+ return (0);
+}
+
+int
+itelioctl (dev, cmd, data, flag)
+dev_t dev;
+caddr_t data;
+int cmd, flag;
+{
+ int unit = minor(dev);
+
+ switch (cmd) {
+ default:
+ return (ENOTTY);
+ }
+ return (0);
+}
+
+int
+itelread(dev_t dev, struct uio * uio)
+{
+ int x;
+ int error = 0;
+ struct itel_data *itel= &itel_data[minor(dev)];
+
+ if((itel->state & CONNECT) == 0)
+ return(EIO);
+
+ while((itel->ilen == 0) && (itel->state & CONNECT))
+ {
+ itel->state |= READ_WAIT;
+ sleep((caddr_t) itel->ibuf, PZERO | PCATCH);
+ }
+
+ x = splhigh();
+ if(itel->ilen)
+ {
+ error = uiomove(itel->ibuf, itel->ilen, uio);
+ itel->ilen= 0;
+ } else error= EIO;
+ splx(x);
+ return error;
+}
+
+int
+itelwrite(dev_t dev, struct uio * uio)
+{
+ int x;
+ int error = 0;
+ struct itel_data *itel= &itel_data[minor(dev)];
+
+ if((itel->state & CONNECT) == 0)
+ return(EIO);
+
+ while(itel->olen && (itel->state & CONNECT))
+ {
+ itel->state |= WRITE_WAIT;
+ sleep((caddr_t) itel->obuf, PZERO | PCATCH);
+ }
+
+ x = splhigh();
+ if((itel->state & CONNECT) == 0)
+ {
+ splx(x);
+ return(0);
+ }
+
+ if(itel->olen == 0)
+ {
+ itel->olen= min(ITEL_SIZE, uio->uio_resid);
+ error = uiomove(itel->obuf, itel->olen, uio);
+ isdn_output(applnr[minor(dev)]);
+ }
+ splx(x);
+ return error;
+}
+
+#endif
diff --git a/sys/gnu/isdn/iitty.c b/sys/gnu/isdn/iitty.c
new file mode 100644
index 0000000..815da76
--- /dev/null
+++ b/sys/gnu/isdn/iitty.c
@@ -0,0 +1,306 @@
+static char _ittyid[] = "@(#)$Id: iitty.c,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: iitty.c,v $
+ *
+ ******************************************************************************/
+
+#include "ity.h"
+#if NITY > 0
+
+#include "param.h"
+#include "systm.h"
+#include "ioctl.h"
+#include "select.h"
+#include "tty.h"
+#include "proc.h"
+#include "user.h"
+#include "conf.h"
+#include "file.h"
+#include "uio.h"
+#include "kernel.h"
+#include "syslog.h"
+#include "types.h"
+
+#include "isdn/isdn_ioctl.h"
+
+int ityattach(), itystart(), ityparam();
+
+int nity = NITY;
+int itydefaultrate = 64000;
+short ity_addr[NITY];
+struct tty ity_tty[NITY];
+static int applnr[NITY];
+static int next_if= 0;
+
+#define UNIT(x) (minor(x)&0x3f)
+#define OUTBOUND(x) ((minor(x)&0x80)==0x80)
+
+int
+ityattach(int ap)
+{
+ if(next_if >= NITY)
+ return(-1);
+
+ applnr[next_if]= ap;
+ return(next_if++);
+}
+
+/* ARGSUSED */
+ityopen(dev_t dev, int flag, int mode, struct proc * p)
+{
+ register struct tty *tp;
+ register int unit;
+ int error = 0;
+
+ unit = UNIT(dev);
+ if (unit >= next_if)
+ return (ENXIO);
+
+ tp = &ity_tty[unit];
+ tp->t_oproc = itystart;
+ tp->t_param = ityparam;
+ tp->t_dev = dev;
+ if ((tp->t_state & TS_ISOPEN) == 0)
+ {
+ tp->t_state |= TS_WOPEN;
+ ttychars(tp);
+ if (tp->t_ispeed == 0)
+ {
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = itydefaultrate;
+ }
+ ityparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+ } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
+ return (EBUSY);
+ (void) spltty();
+
+ if(OUTBOUND(dev)) tp->t_cflag |= CLOCAL;
+
+ while ((flag & O_NONBLOCK) == 0 && (tp->t_cflag & CLOCAL) == 0 &&
+ (tp->t_state & TS_CARR_ON) == 0)
+ {
+ tp->t_state |= TS_WOPEN;
+ if (error = ttysleep(tp, (caddr_t) & tp->t_rawq, TTIPRI | PCATCH,
+ ttopen, 0))
+ break;
+ }
+ (void) spl0();
+ if (error == 0)
+ error = (*linesw[tp->t_line].l_open) (dev, tp);
+ return (error);
+}
+
+/* ARGSUSED */
+ityclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ register struct tty *tp;
+ register ity;
+ register int unit;
+
+ unit = UNIT(dev);
+ ity = ity_addr[unit];
+ if(tp = &ity_tty[unit])
+ (*linesw[tp->t_line].l_close) (tp, flag);
+ ttyclose(tp);
+ isdn_disconnect(applnr[unit],0);
+ return (0);
+}
+
+ityread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+{
+ register struct tty *tp = &ity_tty[UNIT(dev)];
+
+ return ((*linesw[tp->t_line].l_read) (tp, uio, flag));
+}
+
+itywrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+{
+ int unit = UNIT(dev);
+ register struct tty *tp = &ity_tty[unit];
+
+ return ((*linesw[tp->t_line].l_write) (tp, uio, flag));
+}
+
+ity_input(int no, int len, char *buf)
+{
+ register struct tty *tp = &ity_tty[no];
+ int i;
+
+ if (tp->t_state & TS_ISOPEN)
+ for(i= 0; i<len; i++)
+ (*linesw[tp->t_line].l_rint)(buf[i], tp);
+ else len= 0;
+ return(len);
+}
+
+itystart(struct tty *tp)
+{
+ int s, unit;
+
+ unit = UNIT(tp->t_dev);
+
+ s = splhigh();
+ if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))
+ {
+ splx(s);
+ return;
+ }
+ if (tp->t_outq.c_cc <= tp->t_lowat)
+ {
+ if (tp->t_state & TS_ASLEEP)
+ {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t) & tp->t_outq);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+ if (tp->t_outq.c_cc)
+ {
+ if(OUTBOUND(tp->t_dev) && (tp->t_cflag & CLOCAL) &&
+ ((tp->t_state & TS_CARR_ON) == 0))
+ isdn_msg(applnr[unit]);
+ else isdn_output(applnr[unit]);
+ tp->t_state |= TS_BUSY;
+ }
+ splx(s);
+}
+
+ity_out(int no, char *buf, int len)
+{
+ struct tty *tp = &ity_tty[no];
+ int i;
+
+ if(tp == NULL)
+ return(0);
+ if(tp->t_outq.c_cc)
+ {
+ for (i = 0; i < len && tp->t_outq.c_cc; ++i)
+ buf[i]= getc(&tp->t_outq);
+ return(i);
+ }
+ tp->t_state &=~ (TS_BUSY|TS_FLUSH);
+ if (tp->t_line)
+ (*linesw[tp->t_line].l_start)(tp);
+ else
+ itystart(tp);
+ return(0);
+}
+
+ity_connect(int no)
+{
+ struct tty *tp = &ity_tty[no];
+
+ if(tp == NULL)
+ return;
+ if(OUTBOUND(tp->t_dev)) tp->t_cflag &= ~CLOCAL;
+ (*linesw[tp->t_line].l_modem) (tp, 1);
+ tp->t_state |= TS_CARR_ON;
+ tp->t_state &=~ (TS_BUSY|TS_FLUSH);
+ if (tp->t_line)
+ (*linesw[tp->t_line].l_start)(tp);
+ else
+ itystart(tp);
+}
+
+ity_disconnect(int no)
+{
+ struct tty *tp = &ity_tty[no];
+ if(tp) (*linesw[tp->t_line].l_modem) (tp, 0);
+}
+
+ityioctl(dev, cmd, data, flag,p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ register struct tty *tp;
+ register int unit = UNIT(dev);
+ register int error;
+
+ tp = &ity_tty[unit];
+ error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag,p);
+ if (error >= 0)
+ return (error);
+ error = ttioctl(tp, cmd, data, flag);
+ if (error >= 0)
+ return (error);
+
+ switch (cmd)
+ {
+ default:
+ return (ENOTTY);
+ }
+ return (0);
+}
+
+ityparam(tp, t)
+ register struct tty *tp;
+ register struct termios *t;
+{
+ register ity;
+ register int cfcr, cflag = t->c_cflag;
+ int unit = UNIT(tp->t_dev);
+ int ospeed = t->c_ospeed;
+
+ /* check requested parameters */
+ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
+ return (EINVAL);
+ /* and copy to tty */
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = cflag;
+
+ if (ospeed == 0)
+ {
+ isdn_disconnect(applnr[unit],0);
+ return (0);
+ }
+ return (0);
+}
+
+/*
+ * Stop output on a line.
+ */
+/* ARGSUSED */
+itystop(struct tty *tp, int flag)
+{
+ register int s;
+
+ s = splhigh();
+ if (tp->t_state & TS_BUSY)
+ {
+ if ((tp->t_state & TS_TTSTOP) == 0)
+ tp->t_state |= TS_FLUSH;
+ }
+ splx(s);
+}
+
+int
+ityselect(dev_t dev, int rw, struct proc *p)
+{
+ return (ttselect(dev, rw, p));
+}
+
+#endif
diff --git a/sys/gnu/isdn/isdn.c b/sys/gnu/isdn/isdn.c
new file mode 100644
index 0000000..ddf59ed
--- /dev/null
+++ b/sys/gnu/isdn/isdn.c
@@ -0,0 +1,626 @@
+static char _isdnid[] = "@(#)$Id: isdn.c,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: isdn.c,v $
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (c) 1994 Dietmar Friede (dietmar@friede.de) All rights reserved.
+ * FSF/FSAG GNU Copyright applies
+ *
+ * An intermediate level for ISDN Drivers.
+ *
+ */
+
+#include "isdn.h"
+#include "ii.h"
+#include "ity.h"
+#include "itel.h"
+#include "ispy.h"
+#if NISDN > 0
+
+#define TYPNR 4
+#define N_ISDN_APPL (NII + NITY + NITEL + NISPY)
+
+#include "param.h"
+#include "ioctl.h"
+#include "kernel.h"
+#include "systm.h"
+
+#include "isdn/isdn_ioctl.h"
+
+isdn_appl_t isdn_appl[N_ISDN_APPL];
+isdn_ctrl_t isdn_ctrl[N_ISDN_CTRL];
+int Isdn_Appl, Isdn_Ctrl, Isdn_Typ;
+
+int isdn_input(), isdn_output();
+int ii_input(), ii_out(), ii_connect(), ii_disconnect();
+int ity_input(), ity_out(), ity_connect(), ity_disconnect();
+int itel_input(), itel_out(), itel_connect(), itel_disconnect();
+int ispy_input();
+int isdn_stat();
+
+void isdn_disconnect();
+static int o_flags, r_flags, bufind[TYPNR];
+static char buffer[TYPNR][257];
+static u_char appl_list[TYPNR];
+
+typedef u_char prot[2];
+static u_char prot_size[2] = {0, 2};
+static prot passiv[6] = {{0}, {3, 3}};
+static prot activ[6] = {{0}, {1, 3}};
+static void passout();
+
+u_short isdn_state= 0;
+static isdn_timeout= 0;
+extern int hz;
+
+int
+isdn_get_prot_size(int ap)
+{
+ return (prot_size[isdn_appl[ap].prot]);
+}
+
+char *
+isdn_get_prot(int ap, int dir)
+{
+ if(dir)
+ return(activ[isdn_appl[ap].prot]);
+ return(passiv[isdn_appl[ap].prot]);
+}
+
+int
+isdn_set_prot(int ap, int dir, char *p)
+{
+ char *pr;
+ int i, l;
+ if ((l = isdn_get_prot_size(ap)) == 0)
+ return (0);
+ if (dir)
+ pr = passiv[isdn_appl[ap].prot];
+ else
+ pr = activ[isdn_appl[ap].prot];
+ for (i = 0; i < l; i++, pr++, p++)
+ *p = *pr;
+ return (l);
+}
+
+void
+isdn_attach()
+{
+ isdn_appl_t *appl;
+ int i, an;
+
+ appl_list[0]= Isdn_Typ= an= 0;
+
+ for(i= 0 ; i<NII; i++,an++)
+ {
+ appl = &isdn_appl[an];
+ appl->ctrl = -1;
+ appl->state = 0;
+ appl->appl = an;
+ appl->typ = Isdn_Typ;
+ appl->drivno = iiattach(an);
+ appl->PassUp = ii_input;
+ appl->PassDown = ii_out;
+ appl->Connect = ii_connect;
+ appl->DisConn = ii_disconnect;
+ }
+
+ appl_list[1]= an;
+ Isdn_Typ= 1;
+ for(i= 0 ; i<NITY; i++,an++)
+ {
+ appl = &isdn_appl[an];
+ appl->ctrl = -1;
+ appl->state = 0;
+ appl->appl = an;
+ appl->typ = Isdn_Typ;
+ appl->drivno = ityattach(an);
+ appl->PassUp = ity_input;
+ appl->PassDown = ity_out;
+ appl->Connect = ity_connect;
+ appl->DisConn = ity_disconnect;
+ }
+
+ appl_list[2]= an;
+ Isdn_Typ= 2;
+ for(i= 0 ; i<NITEL; i++,an++)
+ {
+ appl = &isdn_appl[an];
+ appl->ctrl = -1;
+ appl->state = 0;
+ appl->appl = an;
+ appl->typ = Isdn_Typ;
+ appl->drivno = itelattach(an);
+ appl->PassUp = itel_input;
+ appl->PassDown = itel_out;
+ appl->Connect = itel_connect;
+ appl->DisConn = itel_disconnect;
+ }
+
+ appl_list[3]= an;
+ Isdn_Typ= 3;
+ for(i= 0 ; i<NISPY; i++,an++)
+ {
+ appl = &isdn_appl[an];
+ appl->ctrl = -1;
+ appl->state = 0;
+ appl->appl = an;
+ appl->typ = Isdn_Typ;
+ appl->drivno = ispyattach(an);
+ appl->PassUp = ispy_input;
+ }
+ Isdn_Appl= an;
+}
+
+int
+isdn_ctrl_attach(int n)
+{
+ int c = Isdn_Ctrl;
+
+ if(Isdn_Ctrl == 0) isdn_attach();
+ if ((Isdn_Ctrl += n) <= N_ISDN_CTRL)
+ return (c);
+ Isdn_Ctrl = c;
+ return (-1);
+}
+
+/*
+ * isdnopen() New open on device.
+ *
+ * I forbid all but one open per application. The only programs opening the
+ * isdn device are the ISDN-daemon
+ */
+int
+isdnopen(dev_t dev, int flag)
+{
+ int err;
+
+ if (minor(dev)>Isdn_Typ)
+ return (ENXIO);
+
+ /* Card busy ? */
+ if (o_flags & (1 << minor(dev)))
+ return (EBUSY);
+
+ o_flags |= (1 << minor(dev));
+
+ return (0);
+}
+
+int
+isdnclose(dev_t dev, int flag)
+{
+ o_flags &= ~(1 << minor(dev));
+ return (0);
+}
+
+int
+isdnread(dev_t dev, struct uio * uio)
+{
+ int x;
+ int error = 0;
+ int unit= minor(dev);
+
+ r_flags &= ~(1 << unit);
+
+ x = splhigh();
+ if(bufind[unit] == 0)
+ {
+ r_flags |= (1 << unit);
+ error= tsleep((caddr_t) buffer[unit], PZERO + 1, "isdnin", hz);
+ }
+ if(bufind[unit])
+ {
+ buffer[unit][bufind[unit]++]= 0;
+ error = uiomove(buffer[unit], bufind[unit], uio);
+ bufind[unit] = 0;
+ }
+ splx(x);
+ return error;
+}
+
+int
+isdnioctl(dev_t dev, int cmd, caddr_t data, int flag)
+{
+ int err, x, i;
+ isdn_appl_t *appl;
+ isdn_ctrl_t *ctrl;
+ short *val = (short *) data;
+ unsigned ab, an, cn;
+
+ err = 0;
+ ab= appl_list[minor(dev)];
+
+ switch (cmd)
+ {
+ case ISDN_LISTEN:
+ {
+ listen_t *s= (listen_t *) data;
+
+ an= ab;
+ if (s->ctrl >= Isdn_Ctrl)
+ return (ENODEV);
+ cn= s->ctrl;
+ ctrl = &isdn_ctrl[cn];
+
+ x = splhigh();
+ while(isdn_state)
+ {
+ err = tsleep((caddr_t) ctrl, PZERO | PCATCH, "slisten", 2);
+ if (err != EWOULDBLOCK)
+ {
+ splx(x);
+ return (err);
+ }
+ }
+
+ isdn_state = 0xffff;
+ while((err = (*ctrl->listen) (s->ctrl, minor(dev) | 0x30
+ , s->inf_mask ,s->subadr_mask ,s->si_mask)) == EBUSY)
+ {
+ err = tsleep((caddr_t) ctrl, PZERO | PCATCH, "blisten", 2);
+ if (err != EWOULDBLOCK)
+ {
+ splx(x);
+ return (err);
+ }
+ }
+
+ if (err)
+ {
+ splx(x);
+ return (err);
+ }
+ while (isdn_state == 0xffff)
+ {
+ err = tsleep((caddr_t) ctrl, PZERO | PCATCH, "ilisten", 2);
+ if (err != EWOULDBLOCK)
+ {
+ splx(x);
+ return (err);
+ }
+ }
+ splx(x);
+ err= isdn_state;
+ isdn_state= 0;
+ return (err); /* tricky but it works */
+ }
+ break;
+
+ case ISDN_DIAL:
+ {
+ dial_t *d= (dial_t*)data;
+ telno_t *t= &d->telno;
+
+ an = d->appl + ab;
+ cn = d->ctrl;
+
+ if (an >= Isdn_Appl || cn >= Isdn_Ctrl)
+ return (ENODEV);
+
+ appl = &isdn_appl[an];
+
+ if (ISBUSY(appl->ctrl) || appl->state)
+ return (EBUSY);
+
+ appl->state= 1;
+ x = splhigh();
+
+ while((err = (*isdn_ctrl[cn].connect) (cn, an
+ ,d->b_channel, d->inf_mask, d->out_serv
+ ,d->out_serv_add, d->src_subadr, t->length
+ ,t->no, d->spv)) == EBUSY)
+ {
+ err = tsleep((caddr_t) appl, PZERO | PCATCH, "idial", 2);
+ if (err != EWOULDBLOCK)
+ {
+ splx(x);
+ return (err);
+ }
+ }
+ if(err) appl->state= 0;
+ splx(x);
+ return(err);
+ }
+ break;
+ case ISDN_HANGUP:
+ cn = data[0];
+ if (cn >= Isdn_Ctrl)
+ return (ENODEV);
+ x = splhigh();
+
+ while((err = (*isdn_ctrl[cn].disconnect) (cn, data[1])) == EBUSY)
+ {
+ err = tsleep((caddr_t) data, PZERO | PCATCH, "ihang", 2);
+ if (err != EWOULDBLOCK)
+ {
+ splx(x);
+ return (err);
+ }
+ }
+ splx(x);
+ break;
+ case ISDN_ACCEPT:
+ cn = data[0];
+ an = data[1] + ab;
+ if (cn >= Isdn_Ctrl)
+ return (ENODEV);
+ x = splhigh();
+ while((err = (*isdn_ctrl[cn].accept) (cn, an, data[2])) == EBUSY)
+ {
+ err = tsleep((caddr_t) data, PZERO | PCATCH, "iaccept", 2);
+ if (err != EWOULDBLOCK)
+ {
+ splx(x);
+ return (err);
+ }
+ }
+ splx(x);
+ break;
+ case ISDN_SET_PARAM:
+ {
+ isdn_param *p = (isdn_param *) data;
+
+ an = p->appl + ab;
+ if (an >= Isdn_Appl)
+ return (ENODEV);
+ appl = &isdn_appl[an];
+ bcopy(p, appl, sizeof(isdn_param));
+ appl->appl+= ab;
+ }
+ break;
+ case ISDN_GET_PARAM:
+ {
+ isdn_param *p = (isdn_param *) data;
+ an = p->appl + ab;
+ if (an >= Isdn_Appl)
+ return (ENODEV);
+ appl = &isdn_appl[an];
+ bcopy(appl, p, sizeof(isdn_param));
+ }
+ break;
+ default:
+ err = ENODEV;
+ }
+
+ return (err);
+}
+
+void
+isdn_start_out(int cn)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ isdn_appl_t *appl = &isdn_appl[ctrl->appl];
+ int x;
+
+ x= splhigh();
+ if (ctrl->o_len == 0)
+ {
+ int l;
+ l = isdn_set_prot(ctrl->appl, ctrl->islisten, ctrl->o_buf);
+ ctrl->o_len = (*appl->PassDown) (appl->drivno, ctrl->o_buf+l,2048-l);
+
+ if (ctrl->o_len == 0)
+ {
+ splx(x);
+ return;
+ }
+ ctrl->o_len+= l;
+ (*ctrl->output) (cn);
+ }
+
+ splx(x);
+}
+
+int
+isdn_stat(int cn)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ return((*ctrl->state) (cn));
+}
+
+int
+isdn_output(int an)
+{
+ isdn_appl_t *appl = &isdn_appl[an];
+
+ if (ISFREE(appl->ctrl))
+ {
+ int l;
+ char buf[10];
+
+ if(appl->state)
+ return(0);
+
+ l = sprintf(buf,"d %d", an-appl_list[appl->typ]);
+ passout(appl->typ,l,buf);
+ return(0);
+ }
+ isdn_start_out(appl->ctrl);
+ return (0);
+}
+
+int
+isdn_msg(int an)
+{
+ isdn_appl_t *appl = &isdn_appl[an];
+
+ if (ISFREE(appl->ctrl))
+ {
+ int l;
+ char buf[256];
+
+ l = sprintf(buf,"M %d", an-appl_list[appl->typ]);
+ l += (*appl->PassDown) (appl->drivno, buf+l,256-l);
+ passout(appl->typ,l,buf);
+ return(0);
+ }
+ return (1);
+}
+
+int
+isdn_input(int an, int len, char *buf, int dir)
+{
+ int l;
+ char *p;
+ isdn_appl_t *appl = &isdn_appl[an];
+
+ if (l = isdn_get_prot_size(an))
+ {
+ p= isdn_get_prot(an,dir);
+ if((p[0] != buf[0]) || (p[1] != buf[1]))
+ return(0);
+ len -= l;
+ buf += l;
+ }
+ return ((*appl->PassUp) (appl->drivno, len, buf, dir));
+}
+
+void
+isdn_accept_con_ind(int an, int cn, char serv, char serv_add, char subadr, char nl, char *num)
+{
+ int l;
+ char buf[32];
+
+ an&= 0xf;
+ l = sprintf(buf, "a %d %d %d %d %c %d %d %s", an, cn ,serv, serv_add
+ , subadr,(u_char) num[0], nl, num + 1);
+ passout(an,l,buf);
+}
+
+void
+isdn_info(int an, int typ, int len, char *data)
+{
+ int l;
+ char buf[64];
+ u_short no;
+
+ if(an < Isdn_Appl)
+ no= isdn_appl[an].typ;
+ else no= an&0xf;
+
+ if(no > Isdn_Typ) no= 3;
+
+ if(len>48) len= 48;
+ data[len]= 0;
+ l = sprintf(buf,"i %d %d %d %s", an, typ, len, data);
+ passout(no,l,buf);
+}
+
+static void
+isdn_check()
+{
+ int i;
+
+ isdn_timeout= 0;
+ for(i= 0; i < Isdn_Ctrl; i++)
+ {
+ int an;
+ isdn_ctrl_t *ctrl = &isdn_ctrl[i];
+
+ if((an= ctrl->appl) < Isdn_Appl)
+ {
+ isdn_appl_t *appl = &isdn_appl[an];
+
+ if(appl->timeout)
+ {
+ isdn_timeout= 1;
+ if(time.tv_sec > (ctrl->lastact + (appl->timeout)))
+ {
+ isdn_disconnect(an,0);
+ break;
+ }
+ }
+ }
+ }
+
+ if(isdn_timeout)
+ {
+ timeout(isdn_check,0,hz/2);
+ }
+}
+
+void
+isdn_conn_ind(int an, int cn, int dial)
+{
+ isdn_appl_t *appl = &isdn_appl[an];
+ int l;
+ char buf[10];
+
+ if (appl->Connect)
+ (*appl->Connect) (appl->drivno);
+
+ l = sprintf(buf,"C %d %d %d", an-appl_list[appl->typ], cn, dial);
+ passout(appl->typ,l,buf);
+ if((isdn_timeout == 0) && appl->timeout)
+ {
+ isdn_timeout= 1;
+ timeout(isdn_check,0,hz/2);
+ }
+}
+
+void
+isdn_disconn_ind(int an)
+{
+ isdn_appl_t *appl = &isdn_appl[an];
+ int l;
+ char buf[10];
+
+ if(( an < 0) || (an >= Isdn_Appl))
+ return;
+
+ appl->state= 0;
+ if (appl->DisConn)
+ (*appl->DisConn) (appl->drivno);
+ l = sprintf(buf,"D %d", an-appl_list[appl->typ]);
+ passout(appl->typ,l,buf);
+}
+
+void
+isdn_disconnect(int an, int rea)
+{
+ isdn_appl_t *appl = &isdn_appl[an];
+
+ if (ISBUSY(appl->ctrl))
+ {
+ int x;
+ x = splhigh();
+ (*isdn_ctrl[appl->ctrl].disconnect)(appl->ctrl,rea);
+ splx(x);
+ }
+}
+
+static void
+passout(int unit, int l, char *buf)
+{
+ int x;
+
+ x = splhigh();
+ if ((bufind[unit] + l) >= 256)
+ {
+ splx(x);
+ return;
+ }
+ bcopy(buf,&buffer[unit][bufind[unit]],l);
+ bufind[unit] += l;
+ buffer[unit][bufind[unit]++]= 0;
+ if (r_flags & (1<<unit))
+ {
+ r_flags &= ~(1 << unit);
+ wakeup((caddr_t) buffer[unit]);
+ }
+ splx(x);
+}
+
+#endif /* NISDN > 0 */
diff --git a/sys/gnu/isdn/isdn_ioctl.h b/sys/gnu/isdn/isdn_ioctl.h
new file mode 100644
index 0000000..ff49486
--- /dev/null
+++ b/sys/gnu/isdn/isdn_ioctl.h
@@ -0,0 +1,136 @@
+static char _isdn_ioctl_id[] = "@(#)$Id: isdn_ioctl.h,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: isdn_ioctl.h,v $
+ *
+ ******************************************************************************/
+
+
+#pragma pack (1)
+typedef struct
+{
+ u_char protokoll;
+ u_char length;
+ u_short data_length;
+ u_char link_addr_a;
+ u_char link_addr_b;
+ u_char modulo_mode;
+ u_char window_size;
+ u_char xid;
+} dlpd_t;
+
+typedef struct
+{
+ u_char protokoll;
+ u_char length;
+ u_short lic, hic, ltc, htc, loc, hoc;
+ u_char modulo_mode;
+}ncpd_t;
+
+typedef struct
+{
+ u_char length;
+ u_short lic, hic, ltc, htc, loc, hoc;
+ u_char modulo_mode;
+}ncpi_t;
+
+typedef struct
+{
+ u_char stat;
+ u_char length;
+ u_char no[124];
+} telno_t;
+
+#pragma pack ()
+
+typedef struct
+{
+ short appl;
+ dlpd_t dlpd;
+ ncpd_t ncpd;
+ u_long timeout;
+ u_char prot;
+ int (*PassUp)(); /* pass data from isdn interface upstream to appl. */
+ int (*PassUpInfo)(); /* pass info from isdn interface upstream to appl. */
+ int (*PassDown)(); /* get data from application */
+ int (*Connect)(); /* Connect Indikation */
+ int (*DisConn)(); /* Disconnect Indikation */
+ short drivno; /* Number of the high level Driver */
+ char ctrl;
+ char typ;
+ short state;
+ short listen_state;
+ u_long send_err;
+} isdn_appl_t;
+
+typedef struct
+{
+ char ctrl;
+ char islisten;
+ short unit;
+ short appl;
+ int (*connect)();
+ int (*listen)();
+ int (*accept)();
+ int (*disconnect)();
+ int (*output)();
+ int (*state)();
+ short o_len;
+ char *o_buf;
+ time_t lastact;
+ u_long send_err;
+ u_long rcv_err;
+} isdn_ctrl_t;
+
+typedef struct
+{
+ short appl;
+ dlpd_t dlpd;
+ ncpd_t ncpd;
+ u_long timeout;
+ u_char prot;
+} isdn_param;
+
+typedef struct
+{
+ short appl;
+ short ctrl;
+ u_char b_channel;
+ u_long inf_mask;
+ u_char out_serv;
+ u_char out_serv_add;
+ u_char src_subadr;
+ u_char spv;
+ telno_t telno;
+} dial_t;
+
+typedef struct
+{
+ short appl;
+ short ctrl;
+ u_long inf_mask;
+ u_short subadr_mask;
+ u_short si_mask;
+} listen_t;
+
+#define ISBUSY(x) (((x) & 0x80) == 0)
+#define ISFREE(x) (((x) & 0x80) == 0x80)
+#define TELNO_VALID 1
+#define TELNO_PROMISC 2
+
+#define N_ISDN_CTRL 2
+
+#define ISDN_DIAL _IOWR('I',1,dial_t)
+#define ISDN_LISTEN _IOWR('I',2,listen_t)
+#define ISDN_ACCEPT _IOWR('I',3,int)
+#define ISDN_HANGUP _IOWR('I',4,int)
+#define ISDN_SET_PARAM _IOWR('I',8,isdn_param)
+#define ISDN_GET_PARAM _IOWR('I',9,isdn_param)
diff --git a/sys/gnu/scsi/nic5000.c b/sys/gnu/scsi/nic5000.c
new file mode 100644
index 0000000..b885dca
--- /dev/null
+++ b/sys/gnu/scsi/nic5000.c
@@ -0,0 +1,1467 @@
+static char rcsid[] = "@(#)$Id: nic5000.c,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: nic5000.c,v $
+ *
+ ******************************************************************************/
+
+/*
+ *
+ * Copyright (c) 1994 Dietmar Friede (dietmar@friede.de) All rights reserved.
+ * FSF/FSAG GNU Copyright applies
+ *
+ * A low level driver for the NICCY-5000 ISDN/SCSI device
+ *
+ */
+
+#include "snic.h"
+#if NSNIC > 0
+
+#define SPLSNIC splbio
+#define ESUCCESS 0
+#define SNIC_RETRIES 8
+#include "sys/types.h"
+#include "sys/param.h"
+#include "sys/ioctl.h"
+#include "sys/malloc.h"
+#include "sys/kernel.h"
+
+#include "scsi/scsi_all.h"
+#include "scsi/scsiconf.h"
+#include "isdn/isdn_ioctl.h"
+#include "i386/isa/niccyreg.h"
+#include "scsi/scsi_nic.h"
+/* #define NETBSD */
+
+#undef SCSI_NOMASK
+#define OPEN 1
+#define LOAD_HEAD 2
+#define LOAD_DATA 4
+#define LOAD_ENTITY 8
+#define IS_DIAL(p) (((p)&0x20)==0)
+#define IS_LISTEN(p) ((p)&0x20)
+#define CHAN(pl) (((pl)&7)-1)
+#define C_CHAN(x) ((x)&1)
+#define APPL(pl) ((((pl)>>6)&0x7f)-1)
+#define CARD(pl) (((pl)>>13)&7)
+#define MK_APPL(pl) (((pl)+1)<<6)
+#define min(a,b) ((a)<(b)?(a):(b))
+
+#define SNICOUTSTANDING 2
+
+extern int hz;
+
+struct snic_data
+{
+ struct scsi_switch *sc_sw; /* address of scsi low level switch */
+ int ctrl; /* so they know which one we want */
+ int targ; /* our scsi target ID */
+ int lu; /* out scsi lu */
+ int cmdscount; /* cmds allowed outstanding by board*/
+ int xfer_block_wait;
+ struct scsi_xfer *free_xfer;
+ struct scsi_xfer scsi_xfer[SNICOUTSTANDING]; /* XXX */
+};
+
+struct snic_driver
+{
+ int size;
+ struct snic_data **snic_data;
+}*snic_driver;
+
+static int next_snic_unit = 0;
+static unsigned dnlnum = 0;
+
+static u_char ack_msg= 0xff;
+static u_char snic_nxt_b;
+
+typedef enum
+{
+ DISCON, ISDISCON, DIAL, CALLED, CONNECT, IDLE, ACTIVE, WAITING, WAIT_ACK
+} io_state;
+
+typedef struct
+{
+ char ctrl;
+ u_char msg_nr;
+ short plci;
+ short ncci;
+ short state;
+ Buffer o_buf;
+} chan_t;
+
+struct snic_softc
+{
+ short sc_stat;
+ u_char sc_flags;
+ u_char sc_unit;
+ u_char sc_ctrl;
+ u_char sc_type;
+ u_short sc_istat;
+ struct scsi_msg sc_icmd;
+ Buffer sc_imsg;
+ Header sc_imsg0;
+ u_short sc_ostat;
+ struct scsi_msg sc_ocmd;
+ Buffer sc_omsg;
+ chan_t sc_chan[2];
+ u_char sc_state_ind[8];
+ u_char sc_gotack;
+} snic_sc[NSNIC];
+
+extern isdn_appl_t isdn_appl[];
+extern isdn_ctrl_t isdn_ctrl[];
+extern u_short isdn_state;
+extern int ispy_applnr;
+extern int Isdn_Appl, Isdn_Ctrl, Isdn_Typ;
+extern void isdn_start_out();
+
+static old_spy= 0;
+static void snic_interupt();
+static int snic_get_msg();
+static void snic_start();
+
+int snic_connect(), snic_listen(), snic_disconnect(), snic_accept();
+int snic_output();
+
+#ifdef NETBSD
+int snicattach(int ctrl, struct scsi_switch *scsi_switch, int physid, int *sunit)
+{
+ int targ, lu;
+#else /* FreeBSD */
+int snicattach(int ctrl, int targ, int lu, struct scsi_switch *scsi_switch)
+{
+#endif
+ int unit,i;
+ struct snic_data *snic, **snicrealloc;
+ struct snic_softc *sc;
+ int cn;
+ isdn_ctrl_t *ctrl0, *ctrl1;
+
+#ifdef NETBSD
+ targ = physid >> 3;
+ lu = physid & 7;
+#endif
+
+ if(next_snic_unit >= NSNIC)
+ return(0);
+
+ unit = next_snic_unit;
+ if (next_snic_unit == 0)
+ {
+ snic_driver =
+ malloc(sizeof(struct snic_driver),M_DEVBUF,M_NOWAIT);
+ if(!snic_driver)
+ {
+ printf("snic%d: malloc failed\n",unit);
+ return(0);
+ }
+ bzero(snic_driver,sizeof(snic_driver));
+ snic_driver->size = 0;
+ }
+ next_snic_unit++;
+
+ if(unit >= snic_driver->size)
+ {
+ snicrealloc =
+ malloc(sizeof(snic_driver->snic_data) * next_snic_unit,
+ M_DEVBUF,M_NOWAIT);
+ if(!snicrealloc)
+ {
+ printf("snic%d: malloc failed\n",unit);
+ return(0);
+ }
+ /* Make sure we have something to copy before we copy it */
+ bzero(snicrealloc,sizeof(snic_driver->snic_data) * next_snic_unit);
+ if(snic_driver->size)
+ {
+ bcopy(snic_driver->snic_data,snicrealloc,
+ sizeof(snic_driver->snic_data) * snic_driver->size);
+ free(snic_driver->snic_data,M_DEVBUF);
+ }
+ snic_driver->snic_data = snicrealloc;
+ snic_driver->snic_data[unit] = NULL;
+ snic_driver->size++;
+ }
+
+ if(snic_driver->snic_data[unit])
+ {
+ return(0);
+ }
+
+ snic = snic_driver->snic_data[unit] =
+ malloc(sizeof(struct snic_data),M_DEVBUF,M_NOWAIT);
+ if(!snic)
+ {
+ printf("snic%d: malloc failed\n",unit);
+ return(0);
+ }
+#ifdef NETBSD
+ *sunit= unit;
+#endif
+ bzero(snic,sizeof(struct snic_data));
+
+ snic->sc_sw = scsi_switch;
+ snic->ctrl = ctrl;
+ snic->targ = targ;
+ snic->lu = lu;
+ snic->cmdscount = SNICOUTSTANDING; /* XXX (ask the board) */
+
+ i = snic->cmdscount;
+ while(i-- )
+ {
+ snic->scsi_xfer[i].next = snic->free_xfer;
+ snic->free_xfer = &snic->scsi_xfer[i];
+ }
+
+ sc = &snic_sc[unit];
+ sc->sc_ctrl = -1;
+ sc->sc_gotack= 1;
+ if ((cn = isdn_ctrl_attach(2)) == -1)
+ {
+ return (0);
+ }
+ sc->sc_ctrl = cn;
+
+ sc->sc_chan[0].plci = sc->sc_chan[1].plci = -1;
+
+ ctrl0 = &isdn_ctrl[cn];
+ ctrl1 = &isdn_ctrl[cn + 1];
+ sc->sc_chan[0].ctrl = ctrl0->ctrl = cn;
+ sc->sc_chan[1].ctrl = ctrl1->ctrl = cn + 1;
+ ctrl0->o_buf = &sc->sc_chan[0].o_buf.Data[5];
+ ctrl1->o_buf = &sc->sc_chan[1].o_buf.Data[5];
+
+ ctrl0->listen = ctrl1->listen = snic_listen;
+ ctrl0->disconnect = ctrl1->disconnect = snic_disconnect;
+ ctrl0->accept = ctrl1->accept = snic_accept;
+ ctrl0->connect = ctrl1->connect = snic_connect;
+ ctrl0->output = ctrl1->output = snic_output;
+ ctrl0->unit = ctrl1->unit = unit;
+ ctrl0->appl = ctrl1->appl = -1;
+ ctrl0->o_len = ctrl1->o_len = -1;
+ sc->sc_flags= LOAD_ENTITY;
+ return(1);
+}
+
+static
+struct scsi_xfer *snic_get_xs(int unit)
+{
+ struct scsi_xfer *xs;
+ struct snic_data *snic;
+ int s;
+
+ snic = snic_driver->snic_data[unit];
+ if (xs = snic->free_xfer)
+ {
+ snic->free_xfer = xs->next;
+ xs->flags = 0;
+ }
+ return(xs);
+}
+
+static void
+snic_free_xs(int unit, struct scsi_xfer *xs)
+{
+ struct snic_data *snic;
+
+ snic = snic_driver->snic_data[unit];
+ xs->next = snic->free_xfer;
+ snic->free_xfer = xs;
+}
+
+static void
+snic_timout(int unit)
+{
+ struct snic_softc * sc= &snic_sc[unit&0xff];
+
+ if(sc->sc_istat&0x100)
+ {
+ snic_interupt(unit);
+ return;
+ }
+ if(sc->sc_istat & 2)
+ sc->sc_istat= sc->sc_ostat= 0;
+ else if((sc->sc_istat & 0x200) == 0 ) return;
+ if(sc->sc_ostat & 0xff)
+ {
+ sc->sc_istat|= 0x200;
+ timeout(snic_timout,unit,2);
+ return;
+ }
+ if(sc->sc_gotack) snic_start(unit);
+ snic_get_msg(unit);
+}
+
+static int
+isdn_small_interupt(int unit, struct scsi_xfer *xs)
+{
+ struct snic_data *snic = snic_driver->snic_data[unit];
+ struct snic_softc * sc= &snic_sc[unit];
+ Header *msg = &sc->sc_imsg0;
+ int c;
+
+ switch (msg->Type)
+ {
+ case 0:
+ if(sc->sc_istat&0x200)
+ break;
+ sc->sc_istat|= 0x200;
+ timeout(snic_timout,unit,2);
+ break;
+ case 0xff:
+ sc->sc_gotack= 1;
+ break;
+ case 0xfe:
+printf("f");
+ sc->sc_gotack= 1;
+ for(c= 0; c < 2; c++)
+ {
+ chan_t *chan = &sc->sc_chan[c];
+ if(chan->state == WAIT_ACK)
+ {
+ chan->state = WAITING;
+ sc->sc_ostat |= c?0x800:0x400;
+ }
+ }
+ break;
+ case 0xfd:
+printf("fd");
+ break;
+ default:
+ return(0);
+ }
+ sc->sc_istat&= ~0xff;
+ sc->sc_imsg0.Type= 0;
+ return(1);
+}
+
+static void
+snic_get_done(int unit, struct scsi_xfer *xs)
+{
+ struct snic_data *snic = snic_driver->snic_data[unit];
+ struct snic_softc * sc= &snic_sc[unit];
+ Header *msg = &sc->sc_imsg0;
+ int len, error;
+
+ error= xs->error;
+
+ switch(error)
+ {
+ case XS_NOERROR:
+ if(xs->datalen == 0)
+ sc->sc_imsg.h.Type= 0;
+
+ if(isdn_small_interupt(unit,xs)) break;
+
+ if(xs->datalen < (len=(msg->DataLen + 10)))
+ {
+ struct scsi_msg *scsi_cmd= &sc->sc_icmd;
+ /* resubmit it */
+
+ sc->sc_imsg.h.Type= 0xba;
+ scsi_cmd->len[1]= (len>>8)&0xff;
+ scsi_cmd->len[2]= len&0xff;
+ xs->retries= SNIC_RETRIES;
+ xs->error = XS_NOERROR;
+ xs->flags &= ~ITSDONE;
+ xs->data = (char *) &sc->sc_imsg;
+ xs->datalen = len;
+ xs->resid = len;
+
+ if ((*(snic->sc_sw->scsi_cmd))(xs) == SUCCESSFULLY_QUEUED)
+ {
+ return;
+ }
+ error= xs->error | 0x1000;
+ break;
+ }
+ if(xs->datalen <= 10)
+ {
+ sc->sc_istat|= 0x400;
+ sc->sc_imsg.h = sc->sc_imsg0;
+ }
+ sc->sc_imsg0.Type= 0;
+ break;
+
+ case XS_TIMEOUT:
+ case XS_BUSY:
+ case XS_DRIVER_STUFFUP:
+ break;
+ default:
+ printf("snic%d: unknown error %x\n",unit,xs->error);
+ }
+
+ if(error)
+ {
+ sc->sc_imsg.h.Type= sc->sc_imsg0.Type= 0;
+ sc->sc_istat&= 0x200;
+ if((sc->sc_istat&0x200) == 0)
+ {
+ sc->sc_istat= 0x200;
+ timeout(snic_timout,unit,2);
+ }
+ }
+
+ snic_free_xs(unit,xs);
+ if(sc->sc_istat&0x4ff == 0x400 )
+ sc->sc_istat|= 1;
+ if(sc->sc_istat&0xff)
+ {
+ snic_interupt(unit);
+ return;
+ }
+ if(sc->sc_gotack) snic_start(unit);
+ if(sc->sc_istat & 0x200)
+ return;
+ sc->sc_istat|= 0x200;
+ timeout(snic_timout,unit,2);
+}
+
+static int
+snic_get_msg(unit)
+int unit;
+{
+ struct snic_data *snic = snic_driver->snic_data[unit];
+ struct snic_softc * sc= &snic_sc[unit];
+ struct scsi_msg *scsi_cmd= &sc->sc_icmd;
+ struct scsi_xfer *xs;
+ Header *data= &sc->sc_imsg0;
+ int retval;
+
+ if(sc->sc_istat&0xff)
+ return(-1);
+ sc->sc_istat |= 1;
+
+ data->Type= 0xbb;
+ sc->sc_istat &= ~0x200;
+
+ bzero(scsi_cmd, sizeof(struct scsi_msg));
+ bzero(data,10);
+
+ scsi_cmd->op_code = GET_MSG_COMMAND;
+ scsi_cmd->len[2]= 10;
+
+ xs = snic_get_xs(unit);
+ if(!xs)
+ {
+ sc->sc_istat&= ~0xff;
+ data->Type= 0;
+ return(EBUSY);
+ }
+
+ xs->flags |= (INUSE | SCSI_DATA_IN | SCSI_NOSLEEP);
+ xs->adapter = snic->ctrl;
+ xs->targ = snic->targ;
+ xs->lu = snic->lu;
+ xs->retries = SNIC_RETRIES;
+ xs->timeout = 2000;
+ xs->cmd = (struct scsi_generic *) scsi_cmd;
+ xs->cmdlen = sizeof(struct scsi_msg);
+ xs->data = (char *) data;
+ xs->datalen = 10;
+ xs->resid = 10;
+ xs->when_done = snic_get_done;
+ xs->done_arg = unit;
+ xs->done_arg2 = (int)xs;
+ xs->bp = NULL;
+ xs->error = XS_NOERROR;
+
+ if(retval = (*(snic->sc_sw->scsi_cmd))(xs))
+ {
+ sc->sc_istat= ~0xff;
+ data->Type= 0;
+ snic_free_xs(unit,xs);
+ }
+ return (retval);
+}
+
+static void
+snic_put_done(int unit, struct scsi_xfer *xs)
+{
+ int retval;
+ struct snic_data *snic = snic_driver->snic_data[unit];
+ struct snic_softc * sc= &snic_sc[unit];
+ Header *b= (Header *) xs->data;
+ int c;
+
+ sc->sc_ostat&= ~0xff;
+ if(xs->error != XS_NOERROR)
+ {
+ snic_free_xs(unit,xs);
+ switch(b->Type)
+ {
+ case 0:
+ return;
+ case 0xff:
+ sc->sc_ostat|= 0x100;
+ return;
+ case BD_DATA_B3_REQ | 0x40:
+ case BD_DATA_B3_REQ:
+ sc->sc_ostat|= 0x400;
+ return;
+ default:
+ sc->sc_ostat|= 0x200;
+ return;
+ }
+ }
+
+ snic_free_xs(unit,xs);
+
+ c= 0;
+ switch(b->Type)
+ {
+ case 0xff: break;
+ case BD_DATA_B3_REQ | 0x40:
+ c= 1;
+ case BD_DATA_B3_REQ:
+ sc->sc_chan[c].state = WAIT_ACK;
+ break;
+ default:
+ b->Type= 0;
+ }
+
+ if(sc->sc_istat&0x100)
+ {
+ snic_interupt(unit);
+ return;
+ }
+
+ if(sc->sc_ostat&0x100)
+ {
+ sc->sc_ostat&= ~0x100;
+ if(snic_put_msg(unit,&ack_msg,1,0))
+ sc->sc_ostat|= 0x100;
+ else return;
+ }
+
+ if(sc->sc_gotack) snic_start(unit);
+ if(sc->sc_istat&0x200)
+ return;
+ sc->sc_istat|= 0x200;
+ timeout(snic_timout,unit,2);
+}
+
+static void
+snic_start(int unit)
+{
+ int retval;
+ struct snic_softc * sc= &snic_sc[unit];
+ Header *b;
+ int c;
+
+ if(sc->sc_ostat&0x200)
+ {
+ b= &sc->sc_omsg.h;
+ sc->sc_ostat&= ~0x200;
+ if(snic_put_msg(unit,b, b->DataLen+10,2))
+ sc->sc_ostat|= 0x200;
+ else return;
+ }
+
+
+ for(c= 0; c<2; c++)
+ {
+ int cc= (snic_nxt_b++)&1;
+ u_short m= 0x400 << cc;
+
+ if(sc->sc_ostat&m)
+ {
+ chan_t *chan= &sc->sc_chan[cc];
+ b= &chan->o_buf.h;
+ sc->sc_ostat&= ~m;
+ if(chan->state == WAITING)
+ {
+ chan->state= ACTIVE;
+ if(snic_put_msg(unit,b, b->DataLen+10,4))
+ {
+ chan->state= WAITING;
+ sc->sc_ostat|= m;
+ }
+ else return;
+ }
+ }
+ }
+}
+
+int
+snic_put_msg(int unit, Header *data, unsigned len, int w)
+{
+ struct snic_softc *sc = &snic_sc[unit];
+ struct scsi_msg *scsi_cmd = &sc->sc_ocmd;
+ int retval;
+ struct scsi_xfer *xs;
+ struct snic_data *snic = snic_driver->snic_data[unit];
+
+ if(data->Type==0)
+ return(0);
+
+ if(sc->sc_ostat&0xff)
+ return(EBUSY);
+
+ sc->sc_ostat |= 1;
+ if((data->Type == 0xa8) || (data->Type == 0xe8))
+ {
+ if(sc->sc_gotack==0)
+ {
+ sc->sc_ostat &= ~0xff;
+ return(EBUSY);
+ }
+ }
+ if(data->Type != 0xff)
+ sc->sc_gotack= 0;
+ bzero(scsi_cmd, sizeof(struct scsi_msg));
+
+ scsi_cmd->op_code = PUT_MSG_COMMAND;
+ if(len > 2063)
+ {
+ printf("snic%d: unsupported length %d\n",unit,len);
+ sc->sc_ostat &= ~0xff;
+ return(ENODEV);
+ }
+ scsi_cmd->len[1]= (len >> 8) & 0xff;
+ scsi_cmd->len[2]= len & 0xff;
+
+ xs = snic_get_xs(unit);
+ if(!xs)
+ {
+ printf("snic pm%d: busy %d\n", unit, w);
+ sc->sc_ostat &= ~0xff;
+ return(EBUSY);
+ }
+ xs->flags |= (INUSE | SCSI_DATA_OUT | SCSI_NOSLEEP);
+ xs->adapter = snic->ctrl;
+ xs->targ = snic->targ;
+ xs->lu = snic->lu;
+ xs->retries = SNIC_RETRIES;
+ xs->timeout = 2000;
+ xs->cmd = (struct scsi_generic *) scsi_cmd;
+ xs->cmdlen = sizeof(struct scsi_msg);
+ xs->data = (char *)data;
+ xs->datalen = len;
+ xs->resid = len;
+ xs->when_done = snic_put_done;
+ xs->done_arg = unit;
+ xs->done_arg2 = (int)xs;
+ xs->bp = NULL;
+ xs->error = XS_NOERROR;
+
+ if(retval = (*(snic->sc_sw->scsi_cmd))(xs))
+ {
+ sc->sc_ostat &= ~0xff;
+ snic_free_xs(unit,xs);
+ return(EBUSY);
+ }
+
+ return(0);
+}
+
+int
+snicopen(dev_t dev, int flag)
+{
+ struct snic_softc *sc;
+ u_char unit;
+ int x;
+ unsigned error;
+ u_char b= 0xff;
+
+ unit = minor(dev);
+ /* minor number out of limits ? */
+ if (unit >= next_snic_unit)
+ return (ENXIO);
+ sc = &snic_sc[unit];
+
+ x= splhigh();
+ /* Card busy ? */
+ if (sc->sc_flags & 7)
+ {
+ splx(x);
+ return (EBUSY);
+ }
+ sc->sc_flags |= OPEN;
+
+ if(sc->sc_flags & LOAD_ENTITY)
+ {
+ snic_get_msg(unit);
+/*
+ if(snic_put_msg(unit,(Header *) &ack_msg,1,5))
+ sc->sc_ostat|= 0x100;
+*/
+ }
+
+ splx(x);
+ return (0);
+}
+
+int
+snicclose(dev_t dev, int flag)
+{
+ struct snic_softc *sc = &snic_sc[minor(dev)];
+
+ sc->sc_flags &= ~7;
+ return (0);
+}
+
+int
+snicioctl(dev_t dev, int cmd, caddr_t data, int flag)
+{
+ int error;
+ u_char unit= minor(dev);
+ int i, x;
+ struct snic_softc *sc = &snic_sc[minor(dev)];
+ Buffer *b= &sc->sc_omsg;
+
+ error = 0;
+ x= splhigh();
+ while(sc->sc_ostat || (sc->sc_gotack==0))
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "ioctl", 2);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return(error);
+ }
+ }
+
+ switch (cmd)
+ {
+ case NICCY_DEBUG:
+ data[0]= 0x50;
+ bcopy(sc->sc_state_ind,data+1,8);
+ break;
+ case NICCY_LOAD:
+ {
+ struct head *head = (struct head *) data;
+ int len, l, off;
+
+ bzero(b, 22);
+ b->h.Type = MD_DNL_MOD_REQ;
+ sc->sc_type = head->typ;
+ b->h.SubType = head->typ;
+ b->h.DataLen = 12;
+ bcopy(head->nam, b->Data, 8);
+ bcopy(&head->len, &b->Data[8], 4);
+
+ sc->sc_flags |= LOAD_HEAD;
+ sc->sc_stat = -1;
+ while((error= snic_put_msg(unit,(Header *) b,22,6)) == EBUSY)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic1", 1);
+ if (error != EWOULDBLOCK)
+ break;
+ }
+ if(error == 0)
+ {
+ while (sc->sc_flags & LOAD_HEAD)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic2", 1);
+ if (error != EWOULDBLOCK)
+ break;
+ error= 0;
+ }
+ }
+ if (sc->sc_flags & 7)
+ sc->sc_flags = (sc->sc_flags & ~7 ) | OPEN;
+ if(error)
+ {
+ head->status = sc->sc_stat;
+ splx(x);
+ return (error);
+ }
+
+ len= head->d_len;
+ off= 0;
+ while(len > 0)
+ {
+ while(sc->sc_ostat || (sc->sc_gotack==0))
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic7", 2);
+ if (error != EWOULDBLOCK)
+ {
+ splx(x);
+ return(error);
+ }
+ }
+ bzero(b,10);
+ b->h.Type = MD_DNL_MOD_DATA;
+ sc->sc_type = head->typ;
+ b->h.SubType = head->typ;
+ l= min(len,512);
+ len-= l;
+ b->h.DataLen = l + 8;
+ b->h.Number = dnlnum++;
+ b->h.MoreData= len>0;
+ bcopy(head->nam, b->Data, 8);
+ if(error= copyin(head->data+off, b->Data+8, l))
+ {
+ splx(x);
+ return(error);
+ }
+ off+= l;
+ sc->sc_flags |= LOAD_DATA;
+ sc->sc_stat = -1;
+
+ while((error= snic_put_msg(unit,(Header *) b,b->h.DataLen+10,7)) == EBUSY)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic3", 1);
+ if (error != EWOULDBLOCK)
+ break;
+ }
+ }
+
+ if(error == 0)
+ {
+ while (sc->sc_flags & LOAD_DATA)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic4", 1);
+ if (error != EWOULDBLOCK)
+ break;
+ error= 0;
+ }
+ }
+ if (sc->sc_flags & 7)
+ sc->sc_flags = (sc->sc_flags & ~7 ) | OPEN;
+ head->status = sc->sc_stat;
+ splx(x);
+ return (error);
+ }
+ case NICCY_SET_CLOCK:
+ bzero(b,10);
+ b->h.Type = MD_SET_CLOCK_REQ;
+ b->h.DataLen = 14;
+ bcopy(data, b->Data,14);
+ while((error= snic_put_msg(unit,(Header *) b,24,8)) == EBUSY)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic5", 1);
+ if (error != EWOULDBLOCK)
+ break;
+ }
+ splx(x);
+ return (error);
+ case NICCY_SPY:
+ bzero(b,10);
+ b->h.Type = MD_MANUFACT_REQ;
+ b->h.SubType = 18;
+ b->h.DataLen = 1;
+/* There are ilegal states. So I use them to toggle */
+ if((data[0] == 0) && (old_spy == 0)) data[0]= 255;
+ else if(data[0] && old_spy ) data[0]= 0;
+ old_spy= b->Data[0]= data[0];
+ while((error= snic_put_msg(unit,(Header *) b,11,9)) == EBUSY)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic6", 1);
+ if (error != EWOULDBLOCK)
+ break;
+ }
+ splx(x);
+ return (error);
+ case NICCY_RESET:
+ bzero(b,10);
+ b->h.Type = MD_RESET_REQ;
+ while((error= snic_put_msg(unit,(Header *) b,10,9)) == EBUSY)
+ {
+ error = tsleep((caddr_t) sc, PZERO | PCATCH, "nic6", 1);
+ if (error != EWOULDBLOCK)
+ break;
+ }
+ sc->sc_flags|= LOAD_ENTITY;
+ splx(x);
+ return (error);
+
+ default:
+ error = ENODEV;
+ }
+ splx(x);
+ return (error);
+}
+
+#define con_b3_req(unit,mb,pl) en_q(unit,mb|BD_CONN_B3_REQ,0,pl,0,NULL)
+#define con_act_resp(unit,pl) en_q(unit,DD_CONN_ACT_RSP,0, pl,0,NULL)
+#define discon_resp(sc,pl) en_q(unit,DD_DISC_RSP,0, pl,0,NULL)
+#define inf_resp(unit,pl) en_q(unit,DD_INFO_RSP,0, pl,0,NULL)
+#define listen_b3_req(unit,mb,pl) en_q(unit,mb|BD_LIST_B3_REQ,0,pl,0,NULL)
+#define con_resp(unit,pl,rea) en_q(unit,DD_CONN_RSP,0, pl, 1,(u_char *) &rea)
+
+static int
+en_q(int unit, int t, int st, int pl, int l, u_char *val)
+{
+ struct snic_softc * sc= &snic_sc[unit];
+ Buffer *b= &sc->sc_omsg;
+ int error= 0;
+
+ if(b->h.Type)
+ {
+ return(EBUSY);
+ }
+ bzero(b,10);
+if(( t >= 0x80) && CHAN(pl) && ((t & 0x40) == 0))
+printf("?%x %x",t,pl);
+if(t>=0x40)
+printf("S%x %x",t,pl);
+
+ b->h.Type = t;
+ b->h.SubType = st;
+ b->h.PLCI = pl;
+ if(l)
+ {
+ b->h.DataLen= l;
+ bcopy(val,b->Data,l);
+ }
+
+ if((error= snic_put_msg(unit,(Header *) b,10+l,13)) == EBUSY)
+ {
+ sc->sc_ostat|= 0x200;
+ return(0);
+ }
+ return(error);
+}
+
+static int
+reset_plci(int w, chan_t * chan, short p)
+{
+ isdn_ctrl_t *ctrl;
+
+ if (p == -1)
+ return (-1);
+
+ if(chan == NULL)
+ return(p);
+
+ ctrl = &isdn_ctrl[chan->ctrl];
+ if(chan->plci == p)
+ {
+ if (ISBUSY(ctrl->appl))
+ {
+ isdn_disconn_ind(ctrl->appl);
+ isdn_appl[ctrl->appl].ctrl = -1;
+ isdn_appl[ctrl->appl].state = 0;
+ }
+ ctrl->appl = -1;
+ ctrl->o_len = -1;
+ chan->plci = -1;
+ chan->ncci = -1;
+ chan->state = DISCON;
+ chan->o_buf.h.Type= 0;
+ }
+ return (p);
+}
+
+static int
+sel_b2_prot_req(int unit, int c, int pl, dlpd_t * dlpd)
+{
+ return(en_q(unit, (c ? 0x40 : 0)| BD_SEL_PROT_REQ, 2, pl, sizeof(dlpd_t), (u_char *) dlpd));
+}
+
+static int
+sel_b3_prot_req(int unit, int mb, u_short pl, ncpd_t * ncpd)
+{
+ return(en_q(unit, mb | BD_SEL_PROT_REQ, 3, pl, sizeof(ncpd_t), (u_char *) ncpd));
+}
+
+static int
+discon_req(int w, int unit , int pl, int rea, int err)
+{
+ if((pl == 0) || (pl == -1))
+ return(0);
+ return(en_q(unit, DD_DISC_REQ,0, pl, 1, (u_char *) &rea));
+}
+
+static int
+state_ind(int unit, int api, int spv)
+{
+ u_char buf[3];
+
+ buf[0]= unit; buf[1]= api; buf[2]= spv;
+ return(en_q(unit, MD_STATE_IND,0, 0, 3, buf));
+}
+
+static int
+con_b3_resp(int unit, int mb, u_short ncci, u_short pl, u_char reject)
+{
+ u_char buf[32];
+ int l = 4;
+
+ bzero(buf, 32);
+ *(u_short *) buf = ncci;
+ buf[2] = reject;
+ buf[3] = 0; /* ncpi ??? */
+ l += 15;
+ return(en_q(unit, mb | BD_CONN_B3_RSP,0, pl, l, buf));
+}
+
+int
+snic_connect(int cn, int ap, int b_channel, int inf_mask, int out_serv
+ ,int out_serv_add, int src_subadr, unsigned ad_len
+ ,char *dest_addr, int spv)
+{
+ char buf[128];
+
+ if (ad_len > 118)
+ return (-1);
+
+ buf[0] = spv ? 0x53 : 0;
+ buf[1] = b_channel;
+ if (spv)
+ inf_mask |= 0x40000000;
+ *(u_long *) & buf[2] = inf_mask;
+ buf[6] = out_serv;
+ buf[7] = out_serv_add;
+ buf[8] = src_subadr;
+ buf[9] = ad_len;
+ bcopy(dest_addr, &buf[10], ad_len);
+ return (en_q(isdn_ctrl[cn].unit, DD_CONN_REQ, 0, MK_APPL(ap), ad_len + 10, buf));
+}
+
+int
+snic_listen(int cn, int ap, int inf_mask, int subadr_mask, int si_mask, int spv)
+{
+ u_short sbuf[4];
+
+ if (spv)
+ inf_mask |= 0x40000000;
+ *(u_long *) sbuf = inf_mask;
+ sbuf[2] = subadr_mask;
+ sbuf[3] = si_mask;
+ return (en_q(isdn_ctrl[cn].unit, DD_LISTEN_REQ, 0, MK_APPL(ap), 8, (u_char *) sbuf));
+}
+
+int
+snic_disconnect(int cn, int rea)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ chan_t *chan = &snic_sc[ctrl->unit].sc_chan[C_CHAN(cn)];
+ int p, err;
+ u_char buf[16];
+
+ if(chan->ncci != -1)
+ {
+ bzero(buf,16);
+ *(u_short *) buf = chan->ncci;
+ err= en_q(ctrl->unit, (C_CHAN(cn)?0x40:0)|BD_DISC_B3_REQ, 0
+ , chan->plci, 3+sizeof(ncpi_t), buf);
+ if((err==0) && (ctrl->o_len == 0))
+ ctrl->o_len= -1;
+ return(err);
+ }
+ p = chan->plci;
+ if ((p == 0) || (p == -1))
+ return (ENODEV);
+
+ err= en_q(ctrl->unit, DD_DISC_REQ, 0, p, 1, (u_char *) &rea);
+ if((err==0) && (ctrl->o_len == 0))
+ ctrl->o_len= -1;
+ return(err);
+}
+
+int
+snic_accept(int cn, int an, int rea)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ struct snic_softc *sc = &snic_sc[ctrl->unit];
+ chan_t *chan = &sc->sc_chan[C_CHAN(cn)];
+ isdn_appl_t *appl = &isdn_appl[an];
+
+ if(ISFREE(ctrl->appl))
+ return(ENODEV);
+
+ if (rea)
+ {
+ ctrl->appl= -1;
+ return(discon_req(1, ctrl->unit, chan->plci, rea, 0));
+ }
+ ctrl->appl= an;
+ ctrl->lastact = time.tv_sec;
+ appl->ctrl= cn;
+ appl->state= 4;
+
+ return(sel_b2_prot_req(ctrl->unit, C_CHAN(cn), chan->plci, &appl->dlpd));
+}
+
+int
+snic_output(int cn)
+{
+ isdn_ctrl_t *ctrl = &isdn_ctrl[cn];
+ struct snic_softc *sc = &snic_sc[ctrl->unit];
+ chan_t *chan = &sc->sc_chan[C_CHAN(cn)];
+ int len= ctrl->o_len;
+ Buffer *b= &chan->o_buf;
+ int error= 0;
+
+ if (sc->sc_state_ind[1] || (chan->ncci == -1))
+ return (ENODEV);
+
+ if(chan->state != IDLE)
+ return(EBUSY);
+ chan->state= WAITING;
+
+ bzero(b,10);
+
+ b->h.Type = BD_DATA_B3_REQ;
+ if(C_CHAN(cn)) b->h.Type |= 0x40;
+ b->h.PLCI = chan->plci;
+ b->h.DataLen= len+5;
+ *(u_short *) b->Data = chan->ncci;
+ *(u_short *) &b->Data[2] = 0;
+ b->h.Number = b->Data[4] = chan->msg_nr++;
+
+ chan->state = ACTIVE;
+ ctrl->lastact = time.tv_sec;
+
+ if((error= snic_put_msg(ctrl->unit,(Header *) b,15+len,14)) == EBUSY)
+ {
+ sc->sc_ostat|= C_CHAN(cn)?0x800:0x400;
+ chan->state= WAITING;
+ return(0);
+ }
+ return(error);
+}
+
+static void
+badstate(Header *h, int n)
+{
+ int i;
+ u_char *p= (u_char *)h;
+ printf("Niccy: not implemented %x.%x len %d at %d", h->Type,
+ h->SubType, h->DataLen,n);
+ if(h->DataLen)
+ {
+ p+= 10;
+ for(i=0; i < h->DataLen ; i++) printf(" %x",p[i]);
+ }
+ printf("\n");
+}
+
+unsigned SavMsgTyp;
+
+static void
+snic_interupt(unsigned unit)
+{
+ struct snic_softc * sc= &snic_sc[unit&0xff];
+ Buffer *msg;
+ chan_t *chan;
+ u_short n, mb, c, pl, err = 0;
+ isdn_ctrl_t *ctrl;
+ isdn_appl_t *appl;
+ int error= 0;
+
+ msg = &sc->sc_imsg;
+ chan= NULL;
+ ctrl= NULL;
+ appl= NULL;
+
+SavMsgTyp= msg->h.Type;
+
+ if(sc->sc_istat & 2)
+ return;
+
+ if(sc->sc_ostat&0xff)
+ {
+ sc->sc_istat|= 0x101;
+ if(sc->sc_istat&0x200)
+ return;
+ sc->sc_istat|= 0x200;
+ timeout(snic_timout,unit,2);
+ return;
+ }
+
+ mb= 0;
+ pl = msg->h.PLCI;
+ if(pl && (msg->h.Type >= 0x40) && (msg->h.Type < 0xfd) && (msg->h.Type != 0x47))
+ {
+ if ((c = CHAN(pl)) < 2)
+ {
+ chan = &sc->sc_chan[c];
+ ctrl = &isdn_ctrl[chan->ctrl];
+ } else
+ {
+ c = 0xffff;
+ chan= NULL;
+ ctrl= NULL;
+ }
+
+ if(ctrl && (ctrl->appl & 0xC0) == 0)
+ appl= &isdn_appl[ctrl->appl];
+ else if( APPL(pl) < 0x30)
+ appl = &isdn_appl[APPL(pl)];
+ else if( APPL(pl) < 0x40)
+ appl= NULL;
+ else goto fin;
+
+ if(msg->h.Type >= 0x80)
+ {
+ mb= msg->h.Type & 0x40;
+ msg->h.Type &= 0xbf;
+ }
+ }
+SavMsgTyp|= 0x100;
+
+if(msg->h.Type>=0x40)
+printf("I%x %x %x",msg->h.Type,pl,mb);
+ switch (msg->h.Type)
+ {
+ case 0x01: /* INIT IND */
+ case 0x15: /* POLL IND */
+ error= en_q(unit,msg->h.Type|0x20,0,0,0,NULL);
+ break;
+ case 0x04: /* DNL MOD CONF */
+ sc->sc_stat = msg->Data[0];
+ if (sc->sc_flags & 7)
+ sc->sc_flags = (sc->sc_flags & ~7) | OPEN;
+ break;
+ case 0x06: /* DNL MOD IND */
+ sc->sc_stat = msg->Data[0];
+ error= en_q(unit,msg->h.Type|0x20,sc->sc_type,0,1, &msg->Data[1]);
+ if(sc->sc_flags & LOAD_ENTITY)
+ {
+ sc->sc_istat= sc->sc_ostat= 2;
+ timeout(snic_timout,unit,hz);
+ msg->h.Type= 0;
+ return;
+ }
+ if (sc->sc_flags)
+ sc->sc_flags = OPEN;
+ break;
+ case 0x0e: /* SET CLOCK CONF */
+ error= state_ind(unit,1,0);
+ break;
+ case 0x16: /* STATE IND */
+ if(sc->sc_flags & LOAD_ENTITY)
+ {
+ if(sc->sc_flags & 7)
+ sc->sc_flags = OPEN;
+ else sc->sc_flags= 0;
+ }
+ bcopy( msg->Data, sc->sc_state_ind, 8);
+ error= en_q(unit,msg->h.Type|0x20,0,0,0,NULL);
+ break;
+ case 0x17: /* STATE RESP */
+ bcopy( msg->Data, sc->sc_state_ind, 8);
+ break;
+ case 0x1e: /* MANUFACT CONF */
+ if(msg->h.SubType == 18)
+ break;
+ badstate(&msg->h,1);
+ break;
+ case 0x1f: /* MANUFACT IND */
+ if(msg->h.SubType == 19)
+ {
+ isdn_input(ispy_applnr, msg->h.DataLen, msg->Data,0);
+ error= en_q(unit,msg->h.Type|0x20,msg->h.SubType,0,0,NULL);
+ break;
+ }
+ badstate(&msg->h,2);
+ break;
+ case 0x40: /* CONNECT CONF */
+ err = *(u_short *) msg->Data;
+ if (err || (appl == NULL) || (chan == NULL) || (ctrl == NULL))
+ {
+ if(chan) reset_plci(3, chan, pl);
+ if(appl) appl->state= 0;
+ break;
+ }
+ if (ISBUSY(ctrl->appl))
+ {
+ error= discon_req(2, unit, pl, 0, 0);
+ break;
+ }
+ chan->plci = pl;
+ chan->msg_nr = 0;
+ chan->ncci = -1;
+ ctrl->lastact = time.tv_sec;
+ ctrl->appl = APPL(pl);
+ appl->ctrl = chan->ctrl;
+ ctrl->islisten= 0;
+ chan->state = DIAL;
+ appl->state= 3;
+ break;
+
+ case 0x41: /* CONNECT IND */
+ if (ISBUSY(ctrl->appl))
+ {
+ error= discon_req(3, unit, pl, 0, 0);
+ break;
+ }
+ chan->plci = pl;
+ chan->msg_nr = 0;
+ chan->ncci = -1;
+ ctrl->lastact = time.tv_sec;
+ ctrl->appl = 0x7f;
+ ctrl->islisten= 1;
+ chan->state = CALLED;
+ msg->Data[msg->Data[3] + 4] = 0;
+ isdn_accept_con_ind(APPL(pl), chan->ctrl, msg->Data[0], msg->Data[1]
+ ,msg->Data[2], msg->Data[3], (char *) &msg->Data[4]);
+ break;
+
+ case 0x42: /* CONNECT ACTIVE IND */
+ error= con_act_resp(unit, pl);
+ if (IS_LISTEN(pl))
+ {
+ isdn_conn_ind(ctrl->appl,chan->ctrl,0);
+ break;
+ }
+ isdn_conn_ind(APPL(pl),chan->ctrl,1);
+ chan->state = CONNECT;
+ ctrl->appl = APPL(pl);
+ appl->ctrl = chan->ctrl;
+ break;
+
+ case 0x43: /* DISCONNECT CONF */
+ reset_plci(4, chan, pl);
+ break;
+
+ case 0x44: /* DISCONNECT IND */
+ error= discon_resp(unit, reset_plci(5, chan, pl));
+ break;
+
+ case 0x47: /* LISTEN CONF */
+ isdn_state = *(u_short *) msg->Data;
+ break;
+
+ case 0x4a: /* INFO IND */
+ isdn_info(APPL(pl),*(u_short *)msg->Data, msg->Data[2], msg->Data+3);
+ error= inf_resp(unit, pl);
+ break;
+ case 0x80: /* SELECT PROT CONF */
+ err = *(u_short *) msg->Data;
+ if (err)
+ {
+ error= discon_req(4, unit, pl, 0, err);
+ break;
+ }
+
+ switch (msg->h.SubType)
+ {
+ case 2:/* SELECT B2 PROTOCOL */
+ if(ISFREE(ctrl->appl))
+ break;
+ error= sel_b3_prot_req(unit, mb, pl, &isdn_appl[ctrl->appl].ncpd);
+ break;
+
+ case 3:/* SELECT B3 PROTOCOL */
+ if (IS_DIAL(pl))
+ error= con_b3_req(unit, mb, pl);
+ else
+ error= listen_b3_req(unit, mb, pl);
+ break;
+ }
+ break;
+
+ case 0x81: /* LISTEN B3 CONF */
+ err = *(u_short *) msg->Data;
+ if (err)
+ {
+ error= discon_req(5, unit, pl, 0, err);
+ break;
+ }
+ error= con_resp(unit, pl, err);
+ break;
+
+ case 0x82: /* CONNECT B3 CONF */
+ err = *(u_short *) (msg->Data + 2);
+ n = *(u_short *) msg->Data;
+
+ if (err)
+ {
+ error= discon_req(6, unit, pl, 0, err);
+ break;
+ }
+ if(ISFREE(ctrl->appl))
+ break;
+ chan->ncci = n;
+ chan->state = CONNECT;
+ break;
+
+ case 0x83: /* CONNECT B3 IND */
+ if(ISFREE(ctrl->appl))
+ break;
+ n = *(u_short *) msg->Data;
+ chan->ncci = n;
+ chan->state = CONNECT;
+ error= con_b3_resp(unit, mb, n, pl, 0);
+ break;
+
+ case 0x84: /* CONNECT B3 ACTIVE IND */
+ if(ISFREE(ctrl->appl))
+ break;
+ if (chan->state < IDLE)
+ {
+ chan->state = IDLE;
+ ctrl->o_len = 0;
+ timeout(isdn_start_out,chan->ctrl,hz/5);
+ }
+ break;
+
+ case 0x85: /* DISCONNECT B3 CONF */
+ if(ISBUSY(ctrl->appl))
+ chan->state = ISDISCON;
+ err = *(u_short *) (msg->Data + 2);
+ if (err)
+ {
+ error= discon_req(7, unit, pl, 0, err);
+ break;
+ }
+ break;
+ case 0x86: /* DISCONNECT B3 IND */
+ if(ISBUSY(ctrl->appl))
+ chan->state = ISDISCON;
+ err = *(u_short *) (msg->Data + 2);
+ error= discon_req(8, unit, pl, 0, err);
+ break;
+
+ case 0x88: /* DATA B3 CONF */
+ if(ISFREE(ctrl->appl))
+ break;
+ err = *(u_short *) (msg->Data + 2);
+ if (err)
+ {
+printf("e%x\n",err);
+ ctrl->send_err++;
+ isdn_appl[ctrl->appl].send_err++;
+ }
+ chan->state = IDLE;
+ chan->o_buf.h.Type= 0;
+ ctrl->o_len = 0;
+ isdn_start_out(chan->ctrl);
+ break;
+
+ case 0x89: /* DATA B3 IND */
+ if(ISFREE(ctrl->appl))
+ break;
+ if(isdn_input(ctrl->appl, msg->h.DataLen-5, msg->Data+5,ctrl->islisten))
+ ctrl->lastact = time.tv_sec;
+ break;
+
+ default:
+ badstate(&msg->h,3);
+ break;
+ }
+
+fin:
+ if(error)
+ {
+printf("x%x %x %x %x %x\n",error,msg->h.Type,sc->sc_istat,sc->sc_ostat,sc->sc_omsg.h.Type);
+ sc->sc_istat|= 0x101;
+ if(sc->sc_istat&0x200)
+ return;
+ sc->sc_istat|= 0x200;
+ timeout(snic_timout,unit,2);
+ return;
+ }
+
+ msg->h.Type= 0;
+ if(snic_put_msg(unit,(Header *) &ack_msg,1,15))
+ sc->sc_ostat|= 0x100;
+ sc->sc_istat= 0x200;
+ snic_get_msg(unit);
+}
+
+#endif /* NSNIC > 0 */
diff --git a/sys/gnu/scsi/scsi_nic.h b/sys/gnu/scsi/scsi_nic.h
new file mode 100644
index 0000000..4847df8
--- /dev/null
+++ b/sys/gnu/scsi/scsi_nic.h
@@ -0,0 +1,53 @@
+static char rcsid[] = "@(#)$Id: scsi_nic.h,v 1.1 1995/01/25 14:06:18 jkr Exp jkr $";
+/*******************************************************************************
+ * II - Version 0.1 $Revision: 1.1 $ $State: Exp $
+ *
+ * Copyright 1994 Dietmar Friede
+ *******************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * jkr@saarlink.de or jkrause@guug.de
+ *
+ *******************************************************************************
+ * $Log: scsi_nic.h,v $
+ *
+ ******************************************************************************/
+
+/*
+ * This file defines the NICCY 5000 Interface.
+ * Copyright Dr. Neuhaus GmbH, Hamburg and Dietmar Friede
+ *
+*/
+#define GET_MSG_COMMAND 0x08
+#define PUT_MSG_COMMAND 0x0a
+
+#pragma pack (1)
+struct scsi_msg
+{
+ u_char op_code;
+ u_char dummy;
+ u_char len[3];
+ u_char control;
+};
+
+typedef struct
+{
+ unsigned char Type;
+ unsigned char SubType;
+ unsigned short Number ;
+ unsigned char MoreData ;
+ unsigned char Reserved[1] ;
+ unsigned short DataLen ;
+ unsigned short PLCI;
+} Header;
+
+#define SNIC_BUF_SIZE 2048+15
+
+typedef struct
+{
+ Header h;
+ unsigned char Data[SNIC_BUF_SIZE];
+} Buffer;
+
+#pragma pack ()
+
OpenPOWER on IntegriCloud