summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authormartin <martin@NetBSD.org>2001-01-05 12:49:52 +0000
committermartin <martin@NetBSD.org>2001-01-05 12:49:52 +0000
commitc3cb638bcaf3ab422b9fbdaa4552afd21a817f40 (patch)
tree739005e0a66c10d03cc90d4791b5e1597b016670 /sys/dev
parentf60c2ea4df70477bade4f1c69ac781c95f862a0c (diff)
Initial import of ISDN4BSD release 0.96
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/daic.c1060
-rw-r--r--sys/dev/ic/daicreg.h150
-rw-r--r--sys/dev/ic/daicvar.h101
-rw-r--r--sys/dev/ic/i4b_hscx.c679
-rw-r--r--sys/dev/ic/i4b_hscx.h301
-rw-r--r--sys/dev/ic/i4b_ipac.h204
-rw-r--r--sys/dev/ic/i4b_isac.c683
-rw-r--r--sys/dev/ic/i4b_isac.h391
-rw-r--r--sys/dev/ic/i4b_isic.c341
-rw-r--r--sys/dev/ic/i4b_isicbchan.c470
-rw-r--r--sys/dev/ic/i4b_isicl1.c315
-rw-r--r--sys/dev/ic/i4b_isicl1.h528
-rw-r--r--sys/dev/ic/i4b_isicl1fsm.c531
-rw-r--r--sys/dev/isa/i4b_avm_a1.c507
-rw-r--r--sys/dev/isa/i4b_itk_ix1.c496
-rw-r--r--sys/dev/isa/i4b_tel_s016.c455
-rw-r--r--sys/dev/isa/i4b_tel_s0163.c602
-rw-r--r--sys/dev/isa/i4b_tel_s08.c388
-rw-r--r--sys/dev/isa/i4b_usr_sti.c439
-rw-r--r--sys/dev/isa/isa_isic.c1299
-rw-r--r--sys/dev/isa/isadaic.c146
-rw-r--r--sys/dev/isapnp/i4b_ctx_s0P.c358
-rw-r--r--sys/dev/isapnp/i4b_drn_ngo.c534
-rw-r--r--sys/dev/isapnp/i4b_dynalink.c570
-rw-r--r--sys/dev/isapnp/i4b_elsa_qs1i.c501
-rw-r--r--sys/dev/isapnp/i4b_siemens_isurf.c479
-rw-r--r--sys/dev/isapnp/i4b_sws.c386
-rw-r--r--sys/dev/isapnp/i4b_tel_s0P.c373
-rw-r--r--sys/dev/isapnp/isapnp_isic.c412
-rw-r--r--sys/dev/microcode/daic/Makefile31
-rw-r--r--sys/dev/microcode/daic/dnload.h-dist42
-rw-r--r--sys/dev/microcode/daic/gendnloadh47
-rw-r--r--sys/dev/pci/i4b_avm_fritz_pci.c1756
-rw-r--r--sys/dev/pci/i4b_elsa_qs1p.c456
-rw-r--r--sys/dev/pci/pci_isic.c354
-rw-r--r--sys/dev/pci/pci_isic.h53
-rw-r--r--sys/dev/pcmcia/i4b_avm_fritz_pcmcia.c499
-rw-r--r--sys/dev/pcmcia/i4b_elsa_isdnmc.c323
-rw-r--r--sys/dev/pcmcia/i4b_elsa_mcall.c249
-rw-r--r--sys/dev/pcmcia/pcmcia_isic.c369
-rw-r--r--sys/dev/pcmcia/pcmcia_isic.h60
41 files changed, 17938 insertions, 0 deletions
diff --git a/sys/dev/ic/daic.c b/sys/dev/ic/daic.c
new file mode 100644
index 00000000000..b6ecd0e7f27
--- /dev/null
+++ b/sys/dev/ic/daic.c
@@ -0,0 +1,1060 @@
+/*
+ * Copyright (c) 1997,1999,2001 Martin Husemann <martin@duskware.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Last Edit-Date: [Fri Jan 5 12:31:50 2001]
+ *
+ * daic.c: MI driver for Diehl active ISDN cards (S, SX, SXn, SCOM, QUADRO)
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <netisdn/i4b_ioctl.h>
+#include <netisdn/i4b_l3l4.h>
+#include <netisdn/i4b_isdnq931.h>
+#include <netisdn/i4b_q931.h>
+#include <netisdn/i4b_l3fsm.h>
+#include <netisdn/i4b_l4.h>
+
+#include <machine/bus.h>
+#include <dev/ic/daicvar.h>
+#include <dev/ic/daicreg.h>
+#include <dev/microcode/daic/dnload.h>
+
+#ifdef NetBSD1_3
+#if NetBSD1_3 < 2
+/* the device is MI, only the attach struct is in the bus
+ dependend frontend. And only on old versions... */
+struct cfdriver daic_cd = {
+ NULL, "daic", DV_DULL
+};
+#endif
+#endif
+
+/* local function prototypes */
+static char * cardtypename __P((int cardtype));
+static int daic_download __P((int unit, int portcount, struct isdn_dr_prot *data));
+static int daic_diagnostic __P((int unit, struct isdn_diagnostic_request *req));
+static void daic_connect_request(unsigned int);
+static void daic_connect_response(unsigned int, int, int);
+static void daic_disconnect_request(unsigned int, int);
+static int daic_reset __P((bus_space_tag_t bus, bus_space_handle_t io, int port, int quiet));
+static int daic_handle_intr __P((struct daic *sc, int port));
+static int daic_register_port(struct daic *sc, int port);
+static void daic_request(struct daic *sc, int port, u_int req, u_int id, bus_size_t parmsize, const u_int8_t *parms);
+static u_int daic_assign(struct daic *sc, int port, u_int instance, bus_size_t parmsize, const u_int8_t *parms);
+static void daic_indicate_ind(struct daic *sc, int port);
+static void daic_bch_config(int unit, int channel, int bprot, int updown);
+static void daic_bch_tx_start(int unit, int channel);
+static void daic_set_linktab(int unit, int channel, drvr_link_t *dlt);
+static isdn_link_t *daic_ret_linktab(int unit, int channel);
+
+#ifdef DAIC_DEBUG
+static void daic_dump_request(struct daic *sc, int port, u_int req, u_int id, bus_size_t parmsize, u_int8_t *parms);
+#endif
+
+/* static data */
+static char *cardnames[] = {
+ "S", "SX", "SCOM", "QUADRO"
+};
+
+static char *err_codes[DAIC_RC_ERRMASK+1] = {
+ "NO ERROR",
+ "UNKNOWN COMMAND",
+ "WRONG COMMAND",
+ "WRONG ID",
+ "WRONG CH",
+ "UNKNOWN IE",
+ "WRONG IE",
+ "OUT OF RESOURCES"
+};
+
+/* fixed parameters */
+
+/* no parameters */
+static u_int8_t parm_none[] = { 0 };
+#define VOIDREQ(sc,port,req,id) daic_request(sc, port, req, id, sizeof parm_none, parm_none)
+
+/* assign request for the global d-channel instance */
+static u_int8_t parm_global_assign[] = {
+/* BC len cap rate a-law */
+ 0x04, 0x03, 0x80, 0x90, 0xa3, /* 64k speech */
+ 0x04, 0x02, 0x88, 0x90, /* 64k data */
+ 0x04, 0x03, 0x89, 0x90, 0xa3, /* restricted digital info */
+ 0x04, 0x03, 0x90, 0x90, 0xa3, /* 3.1k speech */
+/* shift6 SIN len service */
+ 0x96, 0x01, 0x02, 0x00, 0x00, /* any service */
+/* end of parms */
+ 0x00
+};
+
+/*---------------------------------------------------------------------------*
+ * structure mapping one isdn port (a 'unit') to an sc/port pair
+ *---------------------------------------------------------------------------*/
+struct daic_unit_map {
+ struct daic *sc;
+ int port;
+};
+static struct daic_unit_map *unit_map = NULL;
+static int next_unit = 0;
+
+/*---------------------------------------------------------------------------*
+ * Return the name of a card with given cardtype
+ *---------------------------------------------------------------------------*/
+static char *
+cardtypename(cardtype)
+ int cardtype;
+{
+ if (cardtype >= 0 && cardtype < (sizeof(cardnames) / sizeof(cardnames[0])))
+ return cardnames[cardtype];
+ else
+ return "unknown type";
+}
+
+/*---------------------------------------------------------------------------*
+ * Probe for presence of device at given io space.
+ * Return: 0 no card identified
+ * 1 card found
+ *---------------------------------------------------------------------------*/
+int
+daic_probe(bus, io)
+ bus_space_tag_t bus;
+ bus_space_handle_t io;
+{
+ return daic_reset(bus, io, 0, 1);
+}
+
+/*---------------------------------------------------------------------------*
+ * Attach and initialize the card at given io space.
+ *---------------------------------------------------------------------------*/
+void
+daic_attach(self, sc)
+ struct device *self;
+ struct daic *sc;
+{
+ int i, num_ports;
+
+ num_ports = sc->sc_cardtype == DAIC_TYPE_QUAD ? 4 : 1;
+
+ /* init sc */
+ bzero(sc->sc_assign_res, sizeof sc->sc_assign_res);
+ bzero(sc->sc_assign, sizeof sc->sc_assign);
+ for (i = 0; i < num_ports; i++) {
+ sc->sc_state[i] = DAIC_STATE_COLD;
+ }
+ sc->sc_cardtype = -1;
+
+ /* init card */
+ sc->sc_cardtype = daic_reset(sc->sc_iot, sc->sc_ioh, 0, 0);
+ if (sc->sc_cardtype >= 0)
+ for (i = 0; i < num_ports; i++)
+ sc->sc_state[i] = DAIC_STATE_DOWNLOAD;
+
+ /* register all ports this card has */
+ for (i = 0; i < num_ports; i++)
+ daic_register_port(sc, i);
+}
+
+/*---------------------------------------------------------------------------*
+ * handle interrupts for one port of the card
+ *---------------------------------------------------------------------------*/
+static int
+daic_handle_intr(sc, port)
+ struct daic *sc;
+ int port;
+{
+ struct outcallentry *assoc;
+ int off = port * DAIC_ISA_MEMSIZE;
+ u_int8_t rc, rcid;
+ u_int8_t ind, indid;
+ int chan;
+
+ /* check if we caused the interrupt */
+ if (!bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_IRQ+off))
+ return 0; /* nope, exit */
+
+ /* is the card in running state yet? */
+ if (sc->sc_state[port] == DAIC_STATE_TESTING) {
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
+ sc->sc_state[port] = DAIC_STATE_RUNNING;
+ wakeup(&sc->sc_state[port]);
+ goto done;
+ }
+
+ /* what caused the interrupt? */
+ /* (1) Check for a return code */
+ rc = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off);
+ rcid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RCID+off);
+ if (!rc) goto check_ind;
+
+ /* maybe an assign answer (positive or negative) */
+ if (rc == DAIC_RC_ASSIGN_OK) {
+ sc->sc_assign_res[port] = rcid;
+ /* assing rc is special, we tell the card it's done */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, 0);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
+ /* we handle some types of assigns to global dchannel id's automaticaly */
+ if (sc->sc_assign[port] & DAIC_ASSIGN_GLOBAL) {
+ sc->sc_global_dchan[port] = rcid;
+ sc->sc_assign[port] &= ~(DAIC_ASSIGN_GLOBAL|DAIC_ASSIGN_PENDING);
+ if (sc->sc_assign[port] & DAIC_ASSIGN_SLEEPING) {
+ sc->sc_assign[port] = 0;
+ wakeup(&sc->sc_assign_res[port]);
+ }
+ } else {
+ wakeup(&sc->sc_assign[port]);
+ }
+ goto check_ind;
+ } else if ((rc & DAIC_RC_ASSIGN_MASK) == DAIC_RC_ASSIGN_RC) {
+ printf("%s: assign request failed, error 0x%02x: %s\n",
+ sc->sc_dev.dv_xname, rc & DAIC_RC_ERRMASK,
+ err_codes[rc & DAIC_RC_ERRMASK]);
+ sc->sc_assign_res[port] = 0;
+ /* assing rc is special, we tell the card it's done */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, 0);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
+ /* that's it */
+ wakeup(&sc->sc_assign[port]);
+ goto check_ind;
+ }
+ if (rcid == sc->sc_global_dchan[port]) {
+ sc->sc_request_res[port] = rc;
+ wakeup(&sc->sc_request_res[port]);
+ goto req_done;
+ }
+ for (chan = 0; chan < 2; chan++) {
+ if (rcid == sc->sc_con[port*2+chan].dchan_inst) {
+ sc->sc_con[port*2+chan].dchan_rc = rc;
+ wakeup(&sc->sc_con[port*2+chan].dchan_rc);
+ goto req_done;
+ } else if (rcid == sc->sc_con[port*2+chan].bchan_inst) {
+ sc->sc_con[port*2+chan].bchan_rc = rc;
+ wakeup(&sc->sc_con[port*2+chan].bchan_rc);
+ goto req_done;
+ }
+ }
+ for (assoc = sc->sc_outcalls[port].tqh_first; assoc; assoc = assoc->queue.tqe_next) {
+ if (rcid == assoc->dchan_id) {
+ assoc->rc = rc;
+ wakeup(assoc);
+ goto req_done;
+ }
+ }
+
+ /* not found? */
+ printf("%s: unknown id 0x%02x got rc 0x%02x: %s\n",
+ sc->sc_dev.dv_xname, rcid, rc,
+ err_codes[rc & DAIC_RC_ERRMASK]);
+
+req_done:
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
+
+check_ind:
+ /* (2) Check for an indication */
+ ind = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_IND+off);
+ indid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_INDID+off);
+ if (!ind) goto done;
+
+ /* incoming call routed to global dchannel task? */
+ if (indid == sc->sc_global_dchan[port]) {
+ if (ind == DAIC_IND_INDICATE) {
+ daic_indicate_ind(sc, port);
+ } else if (ind == DAIC_IND_INFO) {
+ int i;
+
+ printf("%s: got info indication\n",
+ sc->sc_dev.dv_xname);
+
+ for (i = 0; i < 48; i++) {
+ if (!(i % 16))
+ printf("\n%02x:", i);
+ printf(" %02x", bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+off+i));
+ }
+ printf("\n");
+ } else if (ind == DAIC_IND_HANGUP) {
+ printf("%s: got global HANGUP indication\n",
+ sc->sc_dev.dv_xname);
+ } else {
+ printf("%s: unknown global indication: 0x%02x\n",
+ sc->sc_dev.dv_xname, ind);
+ }
+ goto ind_done;
+ }
+
+ for (chan = 0; chan < 2; chan++) {
+ if (indid == sc->sc_con[port*2+chan].dchan_inst) {
+ printf("%s: D-Channel indication 0x%02x for channel %d\n",
+ sc->sc_dev.dv_xname, ind, chan);
+ goto ind_done;
+ } else if (indid == sc->sc_con[port*2+chan].bchan_inst) {
+ printf("%s: B-Channel indication 0x%02x for channel %d\n",
+ sc->sc_dev.dv_xname, ind, chan);
+ goto ind_done;
+ }
+ }
+
+ for (assoc = sc->sc_outcalls[port].tqh_first; assoc; assoc = assoc->queue.tqe_next) {
+ if (indid == assoc->dchan_id) {
+ printf("%s: D-Channel indication 0x%02x for outgoing call with cdid %d\n",
+ sc->sc_dev.dv_xname, ind, assoc->cdid);
+ goto ind_done;
+ }
+ }
+
+ /* not found - something's wrong! */
+ printf("%s: got ind 0x%02x for id 0x%02x\n", sc->sc_dev.dv_xname, ind, indid);
+
+ind_done:
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_IND+off, 0);
+
+done:
+ /* tell card we're ready for more... */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_IRQ+off, 0);
+
+ return 1;
+}
+
+/*---------------------------------------------------------------------------*
+ * Handle interrupts
+ *---------------------------------------------------------------------------*/
+int
+daic_intr(sc)
+ struct daic *sc;
+{
+ int handeld = 0;
+ if (sc->sc_cardtype == DAIC_TYPE_QUAD) {
+ int i;
+ for (i = 0; i < 4; i++)
+ handeld |= daic_handle_intr(sc, i);
+ } else
+ handeld = daic_handle_intr(sc, 0);
+ return handeld;
+}
+
+/*---------------------------------------------------------------------------*
+ * Download primary protocol microcode to on-board processor
+ *---------------------------------------------------------------------------*/
+static int
+daic_download(unit, count, data)
+ int unit, count;
+ struct isdn_dr_prot *data;
+{
+ struct daic *sc = unit_map[unit].sc;
+ int i;
+
+ if (sc->sc_cardtype != DAIC_TYPE_QUAD)
+ count = 1; /* XXX - or signal error ? */
+
+ for (i = 0; i < count; i++) {
+ int off = DAIC_ISA_MEMSIZE * i;
+ u_int8_t *p = data[i].microcode;
+ size_t s = data[i].bytecount;
+ u_int32_t sw_id;
+ int cnt, x;
+ for (p = data[i].microcode+4, cnt = 0; *p && cnt < 70; p++, cnt++)
+ ;
+ sw_id = p[1] | (p[2] << 8) | (p[3] << 16) | (p[4] << 24);
+ if (sc->sc_cardtype == DAIC_TYPE_QUAD)
+ printf("%s port %d: downloading %s\n",
+ sc->sc_dev.dv_xname, i, data[i].microcode+4);
+ else
+ printf("%s: downloading %s\n",
+ sc->sc_dev.dv_xname, data[i].microcode+4);
+ x = splnet();
+ p = data[i].microcode;
+ while (s > 0) {
+ size_t size = (s > 256) ? 256 : s;
+ bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_BUF+off, p, size);
+ p += size;
+ s -= size;
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off, 1);
+ splx(x);
+ for (cnt = 0; cnt < 2*hz; cnt++) {
+ x = splnet();
+ if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off) == 0)
+ break;
+ splx(x);
+ tsleep(sc, 0, "daic download", 1);
+ }
+ if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off) != 0) {
+ splx(x);
+ printf("%s: download of microcode failed\n",
+ sc->sc_dev.dv_xname);
+ return EIO;
+ }
+ }
+
+ /* configure microcode - no parameters yet - XXX */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_TEI+off, 0);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_NT2+off, 0);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_ZERO+off, 0);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_WATCHDOG+off, 0);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_PERMANENT+off, 0);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_XINTERFACE+off, 0);
+
+ /* start protocol */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off, 2);
+
+ /* wait for signature */
+ for (cnt = 0; cnt < 2*hz; cnt++) {
+ u_int16_t signature;
+ signature = bus_space_read_2(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_SIGNATURE+off);
+ if (signature == DAIC_SIGNATURE_VALUE)
+ break;
+ if (signature) {
+ if (signature != DAIC_SIGNATURE_VALUE) {
+ splx(x);
+ printf("%s: microcode signature bad: should be %04x, is %04x\n",
+ sc->sc_dev.dv_xname, DAIC_SIGNATURE_VALUE,signature);
+ return EIO;
+ }
+ break;
+ }
+ splx(x);
+ tsleep(&sc->sc_state[i], 0, "daic protocol init", hz/25);
+ x = splnet();
+ }
+
+ /* real check: send an invalid request and wait for an interrupt */
+ sc->sc_state[i] = DAIC_STATE_TESTING;
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQID+off, 0xff);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, 1);
+ splx(x);
+ tsleep(&sc->sc_state[i], 0, "daic irq test", 2*hz);
+ x = splnet();
+ if (sc->sc_state[i] != DAIC_STATE_RUNNING) {
+ splx(x);
+ printf("%s: download interrupt test timeout\n",
+ sc->sc_dev.dv_xname);
+ return EIO;
+ }
+
+ /* finish card configuration */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, DAIC_SWID+off, sw_id);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_SET_CARD+off, sc->sc_cardtype);
+ splx(x);
+
+ /* assign global d-channel id for that port */
+ sc->sc_global_dchan[i] =
+ daic_assign(sc, i, DAIC_GLOBALID_DCHAN,
+ sizeof parm_global_assign, parm_global_assign);
+
+ /* send an INDICATE request to get incoming calls on this id */
+ x = splnet();
+ VOIDREQ(sc, i, DAIC_REQ_INDICATE, sc->sc_global_dchan[i]);
+ splx(x);
+ tsleep(&sc->sc_request_res[i], 0, "daic request", 0);
+ x = splnet();
+ if (sc->sc_request_res[i] != DAIC_RC_OK) {
+ printf("%s: INDICATE request error (0x%02x): %s\n",
+ sc->sc_dev.dv_xname, sc->sc_request_res[i],
+ err_codes[sc->sc_request_res[i] & DAIC_RC_ERRMASK]);
+ splx(x);
+ return EIO;
+ }
+ splx(x);
+ }
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * Reset the card, download primary bootstrap, let it check the
+ * card and return the cardtype identified by the microcode
+ * or -1 if no known card is detected.
+ *---------------------------------------------------------------------------*/
+static int
+daic_reset(bus, io, port, quiet)
+ bus_space_tag_t bus;
+ bus_space_handle_t io;
+ int port, quiet;
+{
+ int memsize = 0, cardtype = -1;
+ int i, off = port * DAIC_ISA_MEMSIZE;
+
+ /* clear any pending interrupt */
+ bus_space_read_1(bus, io, DAIC_IRQ+off);
+ /* reset card */
+ bus_space_write_1(bus, io, DAIC_BOOT_SET_RESET+off, 0);
+
+ /* download primary bootstrap */
+ bus_space_set_region_1(bus, io, DAIC_BOOT_START+off, 0, DAIC_BOOT_CODE-DAIC_BOOT_START);
+ bus_space_write_region_1(bus, io, DAIC_BOOT_CODE+off, dnload, DAIC_BOOT_END-DAIC_BOOT_CODE+1);
+ if (bus_space_read_1(bus, io, DAIC_BOOT_CTRL+off)
+ || bus_space_read_1(bus, io, DAIC_BOOT_EBIT+off)) {
+ if (!quiet) printf(": shared memory test failed!\n");
+ return -1;
+ }
+ /* let card perform memory test */
+ bus_space_write_1(bus, io, DAIC_BOOT_CTRL+off, DAIC_TEST_MEM);
+ /* and off we go... */
+ bus_space_write_1(bus, io, DAIC_BOOT_CLR_RESET+off, 0);
+ /* wait for response from bootstrap */
+ for (i = 0; i < 15000 && bus_space_read_1(bus, io, DAIC_BOOT_CTRL+off) != DAIC_TEST_RDY; i++)
+ DELAY(100);
+ if (i >= 15000) {
+ if (!quiet) printf(": on board processor test failed!\n");
+ return -1;
+ }
+ if (bus_space_read_1(bus, io, DAIC_BOOT_EBIT+off)) {
+ if (!quiet) printf(": on board memory test failed at %p\n",
+ (void*)bus_space_read_2(bus, io, DAIC_BOOT_ELOC+off));
+ return -1;
+ }
+
+ /* fetch info from primary bootstrap code */
+ cardtype = bus_space_read_1(bus, io, DAIC_BOOT_CARD+off);
+ memsize = bus_space_read_1(bus, io, DAIC_BOOT_MSIZE+off);
+
+ /* done, output info */
+ if (!quiet) printf(": EICON.Diehl-%s (%d kB RAM)\n", cardtypename(cardtype), memsize << 4);
+
+ return cardtype;
+}
+
+/*---------------------------------------------------------------------------*
+ * Generic diagnostic interface - pass through the microcode data
+ * without knowing too much about it. This passes a lot work to
+ * userland, but hey, this is only a diagnostic tool...
+ *---------------------------------------------------------------------------*/
+static int
+daic_diagnostic(unit, req)
+ int unit;
+ struct isdn_diagnostic_request *req;
+{
+ struct daic *sc = unit_map[unit].sc;
+ int port = unit_map[unit].port;
+ int off = port * DAIC_ISA_MEMSIZE;
+ int rc, cnt;
+ int s, err = 0;
+
+ /* validate parameters */
+ if (req->cmd < 0 || req->cmd > DAIC_DIAG_MAXCMD) {
+ printf("%s: daic_diagnostic: illegal cmd %d\n",
+ sc->sc_dev.dv_xname, req->cmd);
+ return EIO;
+ }
+ if (req->out_param_len > (DAIC_DIAG_DATA_SIZE+1)) {
+ printf("%s: daic_diagnostic: illegal out_param_len %d\n",
+ sc->sc_dev.dv_xname, req->out_param_len);
+ return EIO;
+ }
+
+ /* XXX - only for debug */
+ if (req->cmd == 0x05) {
+ /* pass through request from userland */
+
+ u_int8_t id;
+ static u_int8_t parms[] = {
+ IEI_CALLID, 0x01, 0x81,
+ IEI_CALLINGPN, 7, NUMBER_TYPEPLAN, '9', '8', '9', '0', '2', '0',
+ 0x96, 0x01, 0x02, 0x01, 0x00,
+ 0x00
+ };
+
+ /* create the d-channel task for this call */
+ printf("%s: assigning id for pass-through call\n", sc->sc_dev.dv_xname);
+ id = daic_assign(sc, port, DAIC_GLOBALID_DCHAN, sizeof(parms), parms);
+ printf("%s: got id 0x%02x\n", sc->sc_dev.dv_xname, id);
+
+#ifdef DAIC_DEBUG
+ daic_dump_request(sc, port, DAIC_REQ_CALL, id, req->in_param_len, req->in_param);
+#endif
+ daic_request(sc, port, DAIC_REQ_CALL, id, req->in_param_len, req->in_param);
+ return 0;
+ }
+
+ /* all these need an output parameter */
+ if (req->out_param == NULL)
+ return EIO;
+
+ /* check state and switch to DIAGNOSTIC */
+ s = splnet();
+ if (sc->sc_state[port] != DAIC_STATE_RUNNING) {
+ splx(s);
+ return EWOULDBLOCK;
+ }
+ sc->sc_state[port] = DAIC_STATE_DIAGNOSTIC;
+ splx(s);
+
+ /* set new request */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_REQ+off, req->cmd);
+
+ /* sorry, no interrupt on completition - have to poll */
+ for (cnt = 0; cnt < 3*hz; cnt++) {
+ if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_REQ+off) == 0
+ && bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off) != 0)
+ break;
+ tsleep(sc, 0, "daic diagnostic", 1);
+ }
+ rc = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off);
+ if (rc == 0) {
+ /* stop request and return error */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_REQ+off, 0);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off, 0);
+ err = EIO;
+ goto done;
+ }
+ /* out param gets rc and all the data */
+ if (req->out_param_len >= 2) {
+ ((u_int8_t*)(req->out_param))[0] = (u_int8_t)rc;
+ bus_space_read_region_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_DATA+off, ((u_int8_t*)req->out_param)+1, req->out_param_len-1);
+ }
+ /* acknowledge data */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off, 0);
+
+done: /* back to normal state */
+ s = splnet();
+ sc->sc_state[port] = DAIC_STATE_RUNNING;
+ splx(s);
+
+ return err;
+}
+
+/*---------------------------------------------------------------------------*
+ * Register one port and attach it to the upper layers
+ *---------------------------------------------------------------------------*/
+static int
+daic_register_port(struct daic *sc, int port)
+{
+ int chan;
+ int unit = next_unit++;
+
+ /* make sure this hardware driver type is known to layer 4 */
+ ctrl_types[CTRL_DAIC].set_linktab = daic_set_linktab;
+ ctrl_types[CTRL_DAIC].get_linktab = daic_ret_linktab;
+
+ /* attach a new unit */
+ if (unit_map) {
+ struct daic_unit_map *temp = malloc(next_unit*sizeof(struct daic_unit_map), 0, M_DEVBUF);
+ bcopy(unit_map, temp, unit*sizeof(struct daic_unit_map));
+ free(unit_map, M_DEVBUF);
+ unit_map = temp;
+ } else {
+ unit_map = malloc(sizeof(struct daic_unit_map), 0, M_DEVBUF);
+ next_unit = 0;
+ }
+ next_unit++;
+ unit_map[unit].sc = sc;
+ unit_map[unit].port = port;
+
+ /* setup function pointers */
+ ctrl_desc[nctrl].N_CONNECT_REQUEST = daic_connect_request;
+ ctrl_desc[nctrl].N_CONNECT_RESPONSE = daic_connect_response;
+ ctrl_desc[nctrl].N_DISCONNECT_REQUEST = daic_disconnect_request;
+ ctrl_desc[nctrl].N_DOWNLOAD = daic_download;
+ ctrl_desc[nctrl].N_DIAGNOSTICS = daic_diagnostic;
+
+ /* init type and unit */
+ ctrl_desc[nctrl].unit = unit;
+ ctrl_desc[nctrl].ctrl_type = CTRL_DAIC;
+ ctrl_desc[nctrl].card_type = sc->sc_cardtype + 1;
+
+ /* state fields */
+ ctrl_desc[nctrl].dl_est = DL_DOWN;
+ ctrl_desc[nctrl].bch_state[0] = BCH_ST_FREE;
+ ctrl_desc[nctrl].bch_state[1] = BCH_ST_FREE;
+ sc->sc_ctrl[port] = nctrl++;
+
+ /* initialize linktabs for this port */
+ for (chan = 0; chan < 2; chan++) {
+ isdn_link_t *lt = &sc->sc_con[port*2+chan].isdn_linktab;
+ lt->unit = unit;
+ lt->channel = chan;
+ lt->bch_config = daic_bch_config;
+ lt->bch_tx_start = daic_bch_tx_start;
+ lt->tx_queue = &sc->sc_con[port*2+chan].tx_queue;
+ lt->rx_queue = &sc->sc_con[port*2+chan].rx_queue;
+ }
+ TAILQ_INIT(&sc->sc_outcalls[port]);
+
+ return unit;
+}
+
+/*---------------------------------------------------------------------------*
+ * return the address of daic drivers linktab
+ *---------------------------------------------------------------------------*/
+static isdn_link_t *
+daic_ret_linktab(int unit, int channel)
+{
+ struct daic *sc = unit_map[unit].sc;
+ int port = unit_map[unit].port;
+ struct daic_connection *con = &sc->sc_con[port*2+channel];
+
+ return(&con->isdn_linktab);
+}
+
+/*---------------------------------------------------------------------------*
+ * set the driver linktab in the b channel softc
+ *---------------------------------------------------------------------------*/
+static void
+daic_set_linktab(int unit, int channel, drvr_link_t *dlt)
+{
+ struct daic *sc = unit_map[unit].sc;
+ int port = unit_map[unit].port;
+ struct daic_connection *con = &sc->sc_con[port*2+channel];
+
+ con->drvr_linktab = dlt;
+}
+
+/*---------------------------------------------------------------------------*
+ * Send a request to the card.
+ *---------------------------------------------------------------------------*/
+static void
+daic_request(
+ struct daic *sc, /* ourself */
+ int port, /* and the port on this card */
+ u_int req, /* the request to send */
+ u_int id, /* id of communication task */
+ bus_size_t parmsize, /* size of parms including the terminating zero */
+ const u_int8_t *parms) /* pointer to parms to pass */
+{
+ int off = port*DAIC_ISA_MEMSIZE;
+
+ /* spin while card is yet busy */
+ while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ))
+ ; /* unlikely to happen with this driver */
+
+ /* output parameters */
+ bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_XBUFFER+off, parms, parmsize);
+
+ /* output request and id */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQID+off, id);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, req);
+}
+
+/*---------------------------------------------------------------------------*
+ * Assign a unique instance id for some communication class
+ * on the card. Only one assign request may be running on a
+ * port at any time, handle this and return the instance id.
+ *---------------------------------------------------------------------------*/
+static u_int
+daic_assign(
+ struct daic *sc, /* our state and port no */
+ int port,
+ u_int classid, /* Diehl calls this "global instance id" */
+ bus_size_t parmsize, /* sizeof paramter arra */
+ const u_int8_t *parms) /* task instance parameters */
+{
+ static char wchan[] = "daic assign";
+ u_int8_t id;
+ int x;
+
+ /* there only may be one assignment running concurrently */
+ x = splnet();
+ for (;;) {
+ if (!(sc->sc_assign[port] & DAIC_ASSIGN_PENDING))
+ break; /* we got it! */
+
+ /* somebody else is assigning, record state and sleep */
+ sc->sc_assign[port] |= DAIC_ASSIGN_SLEEPING;
+ tsleep(&sc->sc_assign_res[port], 0, wchan, 0);
+ }
+
+ /* put parameters and request to card */
+ sc->sc_assign[port] |= DAIC_ASSIGN_PENDING;
+ daic_request(sc, port, DAIC_REQ_ASSIGN, classid, parmsize, parms);
+
+ /* wait for completition of assignment by the card */
+ tsleep(&sc->sc_assign[port], 0, wchan, 0);
+ id = sc->sc_assign_res[port];
+
+ /* have we lost our global dchannel id in the meantime? */
+ if (sc->sc_assign[port] & DAIC_ASSIGN_NOGLOBAL) {
+ /* start an assign request and let the result
+ be handled by the interrupt handler - we don't
+ have to wait for it here. As the assign lock
+ isn't freed, we don't wake up others... */
+ sc->sc_assign[port] &= ~DAIC_ASSIGN_NOGLOBAL;
+ sc->sc_assign[port] |= DAIC_ASSIGN_PENDING|DAIC_ASSIGN_GLOBAL;
+ daic_request(sc, port, DAIC_REQ_ASSIGN, DAIC_GLOBALID_DCHAN,
+ sizeof parm_global_assign, parm_global_assign);
+ splx(x);
+ return id;
+ }
+
+ /* XXX - review this, can't remember why I did it this complicated */
+
+ /* unlock and wakup others, if any */
+ if (sc->sc_assign[port] & DAIC_ASSIGN_SLEEPING) {
+ sc->sc_assign[port] = 0;
+ wakeup(&sc->sc_assign_res[port]);
+ } else
+ sc->sc_assign[port] = 0;
+ splx(x);
+
+ return id;
+}
+
+#ifdef DAIC_DEBUG
+/*---------------------------------------------------------------------------*
+ * Debug output of request parameters
+ *---------------------------------------------------------------------------*/
+static void
+daic_dump_request(struct daic *sc, int port, u_int req, u_int id, bus_size_t parmsize, u_int8_t *parms)
+{
+ int i;
+ printf("%s: request 0x%02x to task id 0x%02x:",
+ sc->sc_dev.dv_xname, req, id);
+ for (i = 0; i < parmsize; i++) {
+ if (i % 16 == 0)
+ printf("\n%02x:", i);
+ printf(" %02x", parms[i]);
+ }
+ printf("\n");
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Decode parameters of an INDICATE indication from the card
+ * and pass them to layer 4. Called from within an interrupt
+ * context.
+ *---------------------------------------------------------------------------*/
+static void
+daic_indicate_ind(struct daic *sc, int port)
+{
+ int offset = port*DAIC_ISA_MEMSIZE;
+ int i;
+ u_int8_t ie, ielen;
+ call_desc_t *cd;
+
+ /* get and init new calldescriptor */
+ cd = reserve_cd(); /* cdid filled in */
+ cd->controller = sc->sc_ctrl[port];
+ cd->bprot = BPROT_NONE;
+ cd->cause_in = 0;
+ cd->cause_out = 0;
+ cd->dst_telno[0] = '\0';
+ cd->src_telno[0] = '\0';
+ cd->channelid = CHAN_NO;
+ cd->channelexcl = 0;
+ cd->cr = -1;
+ cd->crflag = CRF_DEST;
+ cd->ilt = NULL; /* reset link tab ptrs */
+ cd->dlt = NULL;
+
+ i = 0;
+ for (;;) {
+ ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
+ if (!ie) break;
+ i++;
+ if (ie & 0x80) continue;
+ ielen = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
+ i++;
+ switch (ie) {
+ case IEI_BEARERCAP:
+ ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
+ if (ie == 0x80 || ie == 0x89 || ie == 0x90)
+ cd->bprot = BPROT_NONE;
+ else if (ie == 0x88)
+ cd->bprot = BPROT_RHDLC;
+ break;
+ case IEI_CALLINGPN:
+ {
+ int off;
+ ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
+ if (ie & 0x80)
+ off = 1;
+ else
+ off = 2;
+ bus_space_read_region_1(sc->sc_iot, sc->sc_ioh,
+ DAIC_COM_RBUFFER+offset+i+off, cd->src_telno,
+ ielen - off);
+ cd->src_telno[ielen-off+1] = '\0';
+ }
+ break;
+ case IEI_CALLEDPN:
+ bus_space_read_region_1(sc->sc_iot, sc->sc_ioh,
+ DAIC_COM_RBUFFER+offset+i+1,
+ cd->dst_telno, ielen-1);
+ cd->dst_telno[ielen] = '\0';
+ break;
+ case IEI_CHANNELID:
+ ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
+ if ((ie & 0xf4) != 0x80)
+ cd->channelid = CHAN_NO;
+ else {
+ switch(ie & 0x03) {
+ case IE_CHAN_ID_NO: cd->channelid = CHAN_NO; break;
+ case IE_CHAN_ID_B1: cd->channelid = CHAN_B1; break;
+ case IE_CHAN_ID_B2: cd->channelid = CHAN_B2; break;
+ case IE_CHAN_ID_ANY: cd->channelid = CHAN_ANY; break;
+ }
+ cd->channelexcl = (ie & 0x08) >> 3;
+ }
+ }
+ i += ielen;
+ }
+ cd->event = EV_SETUP;
+ ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_RSVD;
+
+ /* record the dchannel id for this call and the call descriptor */
+ sc->sc_con[port*2+cd->channelid].dchan_inst = sc->sc_global_dchan[port];
+ sc->sc_con[port*2+cd->channelid].cdid = cd->cdid;
+
+ /* this task is busy now, we need a new global dchan id */
+ if (sc->sc_assign[port] & DAIC_ASSIGN_PENDING) {
+ /* argh - can't assign right now */
+ sc->sc_assign[port] |= DAIC_ASSIGN_NOGLOBAL;
+ } else {
+ /* yeah - can request the assign right away, but let the
+ interrupt handler autohandle the result */
+ sc->sc_assign[port] |= DAIC_ASSIGN_PENDING|DAIC_ASSIGN_GLOBAL;
+ daic_request(sc, port, DAIC_REQ_ASSIGN, DAIC_GLOBALID_DCHAN,
+ sizeof parm_global_assign, parm_global_assign);
+ }
+
+ if (cd->bprot == BPROT_NONE)
+ printf("\nincoming voice call from \"%s\" to \"%s\"\n",
+ cd->src_telno, cd->dst_telno);
+ else
+ printf("\nincoming data call from \"%s\" to \"%s\"\n",
+ cd->src_telno, cd->dst_telno);
+
+ /* hand up call to layer 4 */
+ i4b_l4_connect_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * Layer 4 request a call setup
+ *---------------------------------------------------------------------------*/
+static void
+daic_connect_request(unsigned int cdid)
+{
+ u_int8_t id, cpn[TELNO_MAX+4], parms[TELNO_MAX+16], *p;
+ call_desc_t *cd = cd_by_cdid(cdid);
+ struct daic *sc = unit_map[cd->driver_unit].sc;
+ int port = unit_map[cd->driver_unit].port;
+ int x, len;
+ struct outcallentry *assoc;
+
+ /* to associate the cdid with the communication task
+ we are going to create for this outgoing call,
+ we maintain a queue of pending outgoing calls.
+ As soon as a SETUP response is received, we move
+ the association to the allocated b-channel. */
+
+ /* configure d-channel task parameters */
+ p = parms;
+ *p++ = IEI_CALLID; *p++ = 0x01;
+ if (cd->bprot == BPROT_NONE) {
+ *p++ = 0x82;
+ } else if (cd->bprot == BPROT_RHDLC) {
+ *p++ = 0x85;
+ } else {
+ printf("%s: daic_connect_request for unknown bchan protocol 0x%x\n",
+ sc->sc_dev.dv_xname, cd->bprot);
+ return;
+ }
+ if (cd->src_telno[0]) {
+ *p++ = IEI_CALLINGPN;
+ *p++ = strlen(cd->src_telno)+1;
+ *p++ = NUMBER_TYPEPLAN;
+ strcpy(p, cd->src_telno);
+ p += strlen(p);
+ }
+ if (cd->channelid == CHAN_B1 || cd->channelid == CHAN_B2) {
+ *p++ = IEI_CHANNELID;
+ *p++ = 0x01;
+ *p++ = 0x81 + cd->channelid;
+ }
+ if (cd->bprot == BPROT_NONE) {
+ *p++ = 0x96; /* shift6 */
+ *p++ = 0x01; /* SIN */
+ *p++ = 0x02; /* len */
+ *p++ = 0x01; /* Telephony */
+ *p++ = 0x00; /* add.info */
+ }
+ *p++ = 0;
+
+ /* create the d-channel task for this call */
+ id = daic_assign(sc, port, DAIC_GLOBALID_DCHAN, p - parms, parms);
+
+ /* map it to the call descriptor id */
+ assoc = malloc(sizeof(struct outcallentry), 0, M_DEVBUF);
+ assoc->cdid = cdid;
+ assoc->dchan_id = id;
+ x = splnet();
+ TAILQ_INSERT_TAIL(&sc->sc_outcalls[port], assoc, queue);
+
+ /* send a call request */
+ len = strlen(cd->dst_telno);
+ cpn[0] = IEI_CALLEDPN;
+ cpn[1] = len+1;
+ cpn[2] = NUMBER_TYPEPLAN;
+ strcpy(cpn+3, cd->dst_telno);
+#ifdef DAIC_DEBUG
+ daic_dump_request(sc, port, DAIC_REQ_CALL, id, len+4, cpn);
+#endif
+ daic_request(sc, port, DAIC_REQ_CALL, id, len+4, cpn);
+ splx(x);
+ tsleep(assoc, 0, "daic call", 0);
+ if (assoc->rc != DAIC_RC_OK) {
+ printf("%s: call request failed, error 0x%02x: %s\n",
+ sc->sc_dev.dv_xname, assoc->rc & DAIC_RC_ERRMASK,
+ err_codes[assoc->rc & DAIC_RC_ERRMASK]);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * TODO:
+ *---------------------------------------------------------------------------*/
+static void daic_connect_response(unsigned int cdid, int response, int cause)
+{
+}
+
+/*---------------------------------------------------------------------------*
+ * TODO:
+ *---------------------------------------------------------------------------*/
+static void daic_disconnect_request(unsigned int cdid, int cause)
+{
+}
+
+/*---------------------------------------------------------------------------*
+ * TODO:
+ *---------------------------------------------------------------------------*/
+static void daic_bch_config(int unit, int channel, int bprot, int updown)
+{
+ printf("daic: bch_config\n");
+}
+
+/*---------------------------------------------------------------------------*
+ * TODO:
+ *---------------------------------------------------------------------------*/
+static void daic_bch_tx_start(int unit, int channel)
+{
+ printf("daic: bch_tx_start\n");
+}
+
diff --git a/sys/dev/ic/daicreg.h b/sys/dev/ic/daicreg.h
new file mode 100644
index 00000000000..613567eefa0
--- /dev/null
+++ b/sys/dev/ic/daicreg.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1997,2001 Martin Husemann <martin@duskware.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Shared memory definitions for Diehl activ isdn adapters.
+ */
+
+/*
+ * Values after reset, before isdn support is downloaded
+ */
+#define DAIC_BOOT_CTRL 0 /* byte */
+#define DAIC_BOOT_CARD 1 /* byte */
+#define DAIC_BOOT_MSIZE 2 /* byte */
+#define DAIC_BOOT_EBIT 4 /* 2 byte */
+#define DAIC_BOOT_ELOC 6 /* 4 byte */
+#define DAIC_BOOT_SIGNATURE 30 /* 2 byte */
+#define DAIC_BOOT_BUF 256 /* 256 bytes */
+
+#define DAIC_SERNO 1008
+#define DAIC_SWID 1016
+#define DAIC_DOSIO 0x3e8
+#define DAIC_MEMFREE 0x3f4
+#define DAIC_SET_CARD 0x3fc
+#define DAIC_IRQ 0x3fe
+
+#define DAIC_BOOT_START 0
+#define DAIC_BOOT_CODE 0x200
+#define DAIC_BOOT_END 0x3ff
+#define DAIC_BOOT_SET_RESET 0x400 /* byte */
+#define DAIC_BOOT_CLR_RESET 0x401 /* byte */
+
+/*
+ * Parameters for the microcode
+ */
+#define DAIC_BOOT_TEI 8
+#define DAIC_BOOT_NT2 9
+#define DAIC_BOOT_ZERO 10
+#define DAIC_BOOT_WATCHDOG 11
+#define DAIC_BOOT_PERMANENT 12
+#define DAIC_BOOT_XINTERFACE 13
+
+/*
+ * Response from microcode
+ */
+#define DAIC_SIGNATURE_VALUE 0x4447
+
+/*
+ * Diagnostic interface
+ */
+#define DAIC_DIAG_REQ 0x380 /* byte */
+#define DAIC_DIAG_RC 0x381 /* byte */
+#define DAIC_DIAG_MEM 0x382 /* 4 byte */
+#define DAIC_DIAG_LENGTH 0x386 /* 2 byte */
+#define DAIC_DIAG_PORT 0x388 /* 2 byte */
+#define DAIC_DIAG_DATA 0x390 /* 48 byte */
+#define DAIC_DIAG_DATA_SIZE 48
+#define DAIC_DIAG_MAXCMD 14
+
+/*
+ * Values after download, with software running on card
+ */
+#define DAIC_COM_REQ 0 /* byte */
+#define DAIC_COM_REQID 1 /* byte */
+#define DAIC_COM_RC 2 /* byte */
+#define DAIC_COM_RCID 3 /* byte */
+#define DAIC_COM_IND 4 /* byte */
+#define DAIC_COM_INDID 5 /* byte */
+#define DAIC_COM_IMASK 6 /* byte */
+#define DAIC_COM_RNR 7 /* byte */
+#define DAIC_COM_XLOCK 8 /* byte */
+#define DAIC_COM_INTERRUPT 9 /* byte */
+#define DAIC_COM_REQCH 10 /* byte */
+#define DAIC_COM_RCCH 11 /* byte */
+#define DAIC_COM_INDCH 12 /* byte */
+#define DAIC_COM_MIND 13 /* byte */
+#define DAIC_COM_MLENGTH 14 /* 2 byte */
+#define DAIC_COM_SIGNATURE 30 /* 2 byte */
+#define DAIC_COM_XBUFFER 32 /* 272 byte */
+#define DAIC_COM_RBUFFER 304 /* 272 byte */
+
+/*
+ * Diagnostic commands/results
+ */
+#define DAIC_TEST_RDY 0
+#define DAIC_TEST_MEM 1
+#define DAIC_TEST_SKIP 2
+#define DAIC_TEST_BUSY 3
+
+/*
+ * ID's of global instances on the card
+ */
+#define DAIC_GLOBALID_DCHAN 0
+#define DAIC_GLOBALID_ISO3 0x20
+#define DAIC_GLOBALID_ISO2 0x60
+#define DAIC_GLOBALID_TASKS 0x80
+#define DAIC_GLOBALID_TIMER 0xa0
+#define DAIC_GLOBALID_PHONE 0xc0
+
+/*
+ * REQUEST codes
+ */
+#define DAIC_REQ_ASSIGN 0x01
+#define DAIC_REQ_INDICATE 0x0a
+#define DAIC_REQ_CALL 0x01
+
+/*
+ * INDICATION codes
+ */
+#define DAIC_IND_HANGUP 0x03
+#define DAIC_IND_INDICATE 0x0a
+#define DAIC_IND_INFO 0x0d
+
+/*
+ * return codes
+ */
+#define DAIC_RC_UNKNOWN_COMMAND 0x01
+#define DAIC_RC_WRONG_COMMAND 0x02
+#define DAIC_RC_WRONG_ID 0x03
+#define DAIC_RC_WRONG_CH 0x04
+#define DAIC_RC_UNKNOWN_IE 0x05
+#define DAIC_RC_WRONG_IE 0x06
+#define DAIC_RC_OUT_OF_RESRCS 0x07
+#define DAIC_RC_ASSIGN_RC 0xe0
+#define DAIC_RC_ASSIGN_MASK 0xf0
+#define DAIC_RC_ERRMASK 0x0f
+#define DAIC_RC_ASSIGN_OK 0xef
+#define DAIC_RC_TIMER_INT 0xfe
+#define DAIC_RC_OK 0xff
diff --git a/sys/dev/ic/daicvar.h b/sys/dev/ic/daicvar.h
new file mode 100644
index 00000000000..fcb35e64fe7
--- /dev/null
+++ b/sys/dev/ic/daicvar.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1997,2001 Martin Husemann <martin@duskware.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef DIEHLISDNVAR
+#define DIEHLISDNVAR
+#if defined(KERNEL) || defined(_KERNEL)
+
+#define DAIC_MAX_PORT 4
+#define DAIC_ISA_MEMSIZE 2048
+#define DAIC_ISA_QUADSIZE (DAIC_MAX_PORT*DAIC_ISA_MEMSIZE)
+#define DAIC_MAX_ACTIVE (2*DAIC_MAX_PORT) /* simlutaneous connections on one instance */
+
+/* A queue of pending outgoing calls */
+struct outcallentry {
+ TAILQ_ENTRY(outcallentry) queue;
+ unsigned int cdid; /* call descriptor id for layer 4 */
+ u_int8_t dchan_id; /* task id for microcode */
+ u_int8_t rc; /* return code */
+};
+
+/* One active connection */
+struct daic_connection {
+ u_int cdid; /* layer 4 call descriptor id */
+ struct ifqueue tx_queue; /* outgoing data */
+ struct ifqueue rx_queue; /* incoming data */
+ isdn_link_t isdn_linktab; /* description of ourself */
+ drvr_link_t *drvr_linktab; /* application driver using us */
+ u_int8_t dchan_inst; /* d-channel instance */
+ u_int8_t dchan_rc; /* return code for dchannel requests */
+ u_int8_t bchan_inst; /* b-channel instance */
+ u_int8_t bchan_rc; /* return code for bchannel requests */
+};
+
+/* superclass of all softc structs for attachments, you should
+ * always be able to cast an attachments struct device *self to this. */
+struct daic {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot; /* bus identifier */
+ bus_space_handle_t sc_ioh; /* mem handle */
+ int sc_cardtype; /* variant of card */
+#define DAIC_TYPE_S 0
+#define DAIC_TYPE_SX 1
+#define DAIC_TYPE_SCOM 2
+#define DAIC_TYPE_QUAD 3
+
+ int sc_ctrl[DAIC_MAX_PORT]; /* upper layer controller number */
+
+ int sc_state[DAIC_MAX_PORT]; /* state of board, see below */
+#define DAIC_STATE_COLD 0 /* nothing happened to the board */
+#define DAIC_STATE_DOWNLOAD 1 /* the card is waiting for protocol code */
+#define DAIC_STATE_TESTING 2 /* waiting for first interrupt from card */
+#define DAIC_STATE_RUNNING 3 /* the protocol is running */
+#define DAIC_STATE_DIAGNOSTIC 4 /* temporary disabled for diagnostics */
+
+ int sc_assign[DAIC_MAX_PORT]; /* allocating new protocol instance */
+#define DAIC_ASSIGN_PENDING 1 /* we are awaiting a new ID */
+#define DAIC_ASSIGN_SLEEPING 2 /* somebody sleeping, wakeup after we got the ID */
+#define DAIC_ASSIGN_GLOBAL 4 /* result is a global d-channel id */
+#define DAIC_ASSIGN_NOGLOBAL 8 /* need to assign a global d-channel id */
+
+ u_int8_t sc_global_dchan[DAIC_MAX_PORT]; /* handle of global dchannel instance */
+ u_int8_t sc_request_res[DAIC_MAX_PORT]; /* result of requests */
+ u_int8_t sc_assign_res[DAIC_MAX_PORT]; /* result of assigns */
+
+ /* one record for each b-channel we could handle concurrently */
+ struct daic_connection sc_con[DAIC_MAX_ACTIVE];
+ /* a tailq of ougoing calls no yet assigned to any b-channel */
+ TAILQ_HEAD(outcallhead, outcallentry) sc_outcalls[DAIC_MAX_PORT];
+};
+
+/*
+ * functions exported from MI part
+ */
+extern int daic_probe __P((bus_space_tag_t bus, bus_space_handle_t io));
+extern void daic_attach __P((struct device *self, struct daic *sc));
+extern int daic_intr __P((struct daic *));
+
+#endif
+#endif
diff --git a/sys/dev/ic/i4b_hscx.c b/sys/dev/ic/i4b_hscx.c
new file mode 100644
index 00000000000..04d1961d868
--- /dev/null
+++ b/sys/dev/ic/i4b_hscx.c
@@ -0,0 +1,679 @@
+/*
+ * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b - Siemens HSCX chip (B-channel) handling
+ * --------------------------------------------
+ *
+ * $Id: i4b_hscx.c,v 1.1.1.1 2001/01/05 12:50:10 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:36:10 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/param.h>
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#ifndef __bsdi__
+#include <machine/bus.h>
+#endif
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#include <netisdn/i4b_trace.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_mbuf.h>
+
+/*---------------------------------------------------------------------------*
+ * HSCX IRQ Handler
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_irq(register struct l1_softc *sc, u_char ista, int h_chan, u_char ex_irq)
+{
+ register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+ u_char exir = 0;
+ int activity = -1;
+ u_char cmd = 0;
+
+ NDBGL1(L1_H_IRQ, "%#x", ista);
+
+ if(ex_irq)
+ {
+ /* get channel extended irq reg */
+
+ exir = HSCX_READ(h_chan, H_EXIR);
+
+ if(exir & HSCX_EXIR_RFO)
+ {
+ chan->stat_RFO++;
+ NDBGL1(L1_H_XFRERR, "ex_irq: receive data overflow");
+ }
+
+ if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
+ {
+ chan->stat_XDU++;
+ NDBGL1(L1_H_XFRERR, "ex_irq: xmit data underrun");
+ isic_hscx_cmd(sc, h_chan, HSCX_CMDR_XRES);
+
+ if (chan->out_mbuf_head != NULL) /* don't continue to transmit this buffer */
+ {
+ i4b_Bfreembuf(chan->out_mbuf_head);
+ chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
+ }
+ }
+
+ }
+
+ /* rx message end, end of frame */
+
+ if(ista & HSCX_ISTA_RME)
+ {
+ register int fifo_data_len;
+ u_char rsta;
+ int error = 0;
+
+ rsta = HSCX_READ(h_chan, H_RSTA);
+
+ if((rsta & 0xf0) != 0xa0)
+ {
+ if((rsta & HSCX_RSTA_VFR) == 0)
+ {
+ chan->stat_VFR++;
+ cmd |= (HSCX_CMDR_RHR);
+ NDBGL1(L1_H_XFRERR, "received invalid Frame");
+ error++;
+ }
+
+ if(rsta & HSCX_RSTA_RDO)
+ {
+ chan->stat_RDO++;
+ NDBGL1(L1_H_XFRERR, "receive data overflow");
+ error++;
+ }
+
+ if((rsta & HSCX_RSTA_CRC) == 0)
+ {
+ chan->stat_CRC++;
+ cmd |= (HSCX_CMDR_RHR);
+ NDBGL1(L1_H_XFRERR, "CRC check failed");
+ error++;
+ }
+
+ if(rsta & HSCX_RSTA_RAB)
+ {
+ chan->stat_RAB++;
+ NDBGL1(L1_H_XFRERR, "Receive message aborted");
+ error++;
+ }
+ }
+
+ fifo_data_len = ((HSCX_READ(h_chan, H_RBCL)) &
+ ((sc->sc_bfifolen)-1));
+
+ if(fifo_data_len == 0)
+ fifo_data_len = sc->sc_bfifolen;
+
+ /* all error conditions checked, now decide and take action */
+
+ if(error == 0)
+ {
+ if(chan->in_mbuf == NULL)
+ {
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 isic_hscx_irq: RME, cannot allocate mbuf!\n");
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ }
+
+ fifo_data_len -= 1; /* last byte in fifo is RSTA ! */
+
+ if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
+ {
+ /* read data from HSCX fifo */
+
+ HSCX_RDFIFO(h_chan, chan->in_cbptr, fifo_data_len);
+
+ cmd |= (HSCX_CMDR_RMC);
+ isic_hscx_cmd(sc, h_chan, cmd);
+ cmd = 0;
+
+ chan->in_len += fifo_data_len;
+ chan->rxcount += fifo_data_len;
+
+ /* setup mbuf data length */
+
+ chan->in_mbuf->m_len = chan->in_len;
+ chan->in_mbuf->m_pkthdr.len = chan->in_len;
+
+ if(sc->sc_trace & TRACE_B_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit);
+
+ activity = ACT_RX;
+
+ /* mark buffer ptr as unused */
+
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ else
+ {
+ NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d", chan->in_len, fifo_data_len);
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ cmd |= (HSCX_CMDR_RHR | HSCX_CMDR_RMC);
+ }
+ }
+ else
+ {
+ if (chan->in_mbuf != NULL)
+ {
+ i4b_Bfreembuf(chan->in_mbuf);
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ cmd |= (HSCX_CMDR_RMC);
+ }
+ }
+
+ /* rx fifo full */
+
+ if(ista & HSCX_ISTA_RPF)
+ {
+ if(chan->in_mbuf == NULL)
+ {
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 isic_hscx_irq: RPF, cannot allocate mbuf!\n");
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ }
+
+ chan->rxcount += sc->sc_bfifolen;
+
+ if((chan->in_len + sc->sc_bfifolen) <= BCH_MAX_DATALEN)
+ {
+ /* read data from HSCX fifo */
+
+ HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
+
+ chan->in_cbptr += sc->sc_bfifolen;
+ chan->in_len += sc->sc_bfifolen;
+ }
+ else
+ {
+ if(chan->bprot == BPROT_NONE)
+ {
+ /* setup mbuf data length */
+
+ chan->in_mbuf->m_len = chan->in_len;
+ chan->in_mbuf->m_pkthdr.len = chan->in_len;
+
+ if(sc->sc_trace & TRACE_B_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ /* silence detection */
+
+ if(!(isic_hscx_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
+ activity = ACT_RX;
+
+ if(!(IF_QFULL(&chan->rx_queue)))
+ {
+ IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
+ }
+ else
+ {
+ i4b_Bfreembuf(chan->in_mbuf);
+ }
+
+ /* signal upper driver that data is available */
+
+ (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit);
+
+ /* alloc new buffer */
+
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 isic_hscx_irq: RPF, cannot allocate new mbuf!\n");
+
+ /* setup new data ptr */
+
+ chan->in_cbptr = chan->in_mbuf->m_data;
+
+ /* read data from HSCX fifo */
+
+ HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
+
+ chan->in_cbptr += sc->sc_bfifolen;
+ chan->in_len = sc->sc_bfifolen;
+
+ chan->rxcount += sc->sc_bfifolen;
+ }
+ else
+ {
+ NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len);
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ cmd |= (HSCX_CMDR_RHR);
+ }
+ }
+
+ /* command to release fifo space */
+
+ cmd |= HSCX_CMDR_RMC;
+ }
+
+ /* transmit fifo empty, new data can be written to fifo */
+
+ if(ista & HSCX_ISTA_XPR)
+ {
+ /*
+ * for a description what is going on here, please have
+ * a look at isic_bchannel_start() in i4b_bchan.c !
+ */
+
+ int activity = -1;
+ int len;
+ int nextlen;
+
+ NDBGL1(L1_H_IRQ, "unit %d, chan %d - XPR, Tx Fifo Empty!", sc->sc_unit, h_chan);
+
+ if(chan->out_mbuf_cur == NULL) /* last frame is transmitted */
+ {
+ IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
+
+ if(chan->out_mbuf_head == NULL)
+ {
+ chan->state &= ~HSCX_TX_ACTIVE;
+ (*chan->drvr_linktab->bch_tx_queue_empty)(chan->drvr_linktab->unit);
+ }
+ else
+ {
+ chan->state |= HSCX_TX_ACTIVE;
+ chan->out_mbuf_cur = chan->out_mbuf_head;
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+
+ if(chan->bprot == BPROT_NONE)
+ {
+ if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
+ activity = ACT_TX;
+ }
+ else
+ {
+ activity = ACT_TX;
+ }
+ }
+ }
+
+ len = 0;
+
+ while(chan->out_mbuf_cur && len != sc->sc_bfifolen)
+ {
+ nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);
+
+#ifdef NOTDEF
+ printf("i:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
+ chan->out_mbuf_head,
+ chan->out_mbuf_cur,
+ chan->out_mbuf_cur_ptr,
+ chan->out_mbuf_cur_len,
+ len,
+ next_len);
+#endif
+
+ isic_hscx_waitxfw(sc, h_chan); /* necessary !!! */
+
+ HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, nextlen);
+ cmd |= HSCX_CMDR_XTF;
+
+ len += nextlen;
+ chan->txcount += nextlen;
+
+ chan->out_mbuf_cur_ptr += nextlen;
+ chan->out_mbuf_cur_len -= nextlen;
+
+ if(chan->out_mbuf_cur_len == 0)
+ {
+ if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
+ {
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+ }
+ else
+ {
+ if (chan->bprot != BPROT_NONE)
+ cmd |= HSCX_CMDR_XME;
+ i4b_Bfreembuf(chan->out_mbuf_head);
+ chan->out_mbuf_head = NULL;
+ }
+
+ }
+ }
+ }
+
+ if(cmd) /* is there a command for the HSCX ? */
+ {
+ isic_hscx_cmd(sc, h_chan, cmd); /* yes, to HSCX */
+ }
+
+ /* call timeout handling routine */
+
+ if(activity == ACT_RX || activity == ACT_TX)
+ (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity);
+}
+
+/*---------------------------------------------------------------------------*
+ * HSCX initialization
+ *
+ * for telephony: extended transparent mode 1
+ * for raw hdlc: transparent mode 0
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_init(struct l1_softc *sc, int h_chan, int activate)
+{
+ l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+
+ HSCX_WRITE(h_chan, H_MASK, 0xff); /* mask irq's */
+
+ if(sc->sc_ipac)
+ {
+ /* CCR1: Power Up, Clock Mode 5 */
+ HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */
+ HSCX_CCR1_CM1); /* IPAC clock mode 5 */
+ }
+ else
+ {
+ /* CCR1: Power Up, Clock Mode 5 */
+ HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */
+ HSCX_CCR1_CM2 | /* HSCX clock mode 5 */
+ HSCX_CCR1_CM0);
+ }
+
+ /* XAD1: Transmit Address Byte 1 */
+ HSCX_WRITE(h_chan, H_XAD1, 0xff);
+
+ /* XAD2: Transmit Address Byte 2 */
+ HSCX_WRITE(h_chan, H_XAD2, 0xff);
+
+ /* RAH2: Receive Address Byte High Reg. 2 */
+ HSCX_WRITE(h_chan, H_RAH2, 0xff);
+
+ /* XBCH: reset Transmit Byte Count High */
+ HSCX_WRITE(h_chan, H_XBCH, 0x00);
+
+ /* RLCR: reset Receive Length Check Register */
+ HSCX_WRITE(h_chan, H_RLCR, 0x00);
+
+ /* CCR2: set tx/rx clock shift bit 0 */
+ /* disable CTS irq, disable RIE irq*/
+ HSCX_WRITE(h_chan, H_CCR2, HSCX_CCR2_XCS0|HSCX_CCR2_RCS0);
+
+ /* XCCR: tx bit count per time slot */
+ HSCX_WRITE(h_chan, H_XCCR, 0x07);
+
+ /* RCCR: rx bit count per time slot */
+ HSCX_WRITE(h_chan, H_RCCR, 0x07);
+
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ {
+ switch(h_chan)
+ {
+ case HSCX_CH_A: /* Prepare HSCX channel A */
+ /* TSAX: tx clock shift bits 1 & 2 */
+ /* tx time slot number */
+ HSCX_WRITE(h_chan, H_TSAX, 0x2f);
+
+ /* TSAR: rx clock shift bits 1 & 2 */
+ /* rx time slot number */
+ HSCX_WRITE(h_chan, H_TSAR, 0x2f);
+ break;
+
+ case HSCX_CH_B: /* Prepare HSCX channel B */
+ /* TSAX: tx clock shift bits 1 & 2 */
+ /* tx time slot number */
+ HSCX_WRITE(h_chan, H_TSAX, 0x03);
+
+ /* TSAR: rx clock shift bits 1 & 2 */
+ /* rx time slot number */
+ HSCX_WRITE(h_chan, H_TSAR, 0x03);
+ break;
+ }
+ }
+ else /* IOM 1 setup */
+ {
+ /* TSAX: tx clock shift bits 1 & 2 */
+ /* tx time slot number */
+ HSCX_WRITE(h_chan, H_TSAX, 0x07);
+
+ /* TSAR: rx clock shift bits 1 & 2 */
+ /* rx time slot number */
+ HSCX_WRITE(h_chan, H_TSAR, 0x07);
+ }
+
+ if(activate)
+ {
+ if(chan->bprot == BPROT_RHDLC)
+ {
+ /* HDLC Frames, transparent mode 0 */
+ HSCX_WRITE(h_chan, H_MODE,
+ HSCX_MODE_MDS1|HSCX_MODE_RAC|HSCX_MODE_RTS);
+ }
+ else
+ {
+ /* Raw Telephony, extended transparent mode 1 */
+ HSCX_WRITE(h_chan, H_MODE,
+ HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
+ }
+
+ isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES);
+ }
+ else
+ {
+ /* TSAX: tx time slot */
+ HSCX_WRITE(h_chan, H_TSAX, 0xff);
+
+ /* TSAR: rx time slot */
+ HSCX_WRITE(h_chan, H_TSAR, 0xff);
+
+ /* Raw Telephony, extended transparent mode 1 */
+ HSCX_WRITE(h_chan, H_MODE,
+ HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
+ }
+
+ /* don't touch ICA, EXA and EXB bits, this could be HSCX_CH_B */
+ /* always disable RSC and TIN */
+
+ chan->hscx_mask |= HSCX_MASK_RSC | HSCX_MASK_TIN;
+
+ if(activate)
+ {
+ /* enable */
+ chan->hscx_mask &= ~(HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR);
+ }
+ else
+ {
+ /* disable */
+ chan->hscx_mask |= HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR;
+ }
+
+ /* handle ICA, EXA, and EXB via interrupt mask of channel b */
+
+ if (h_chan == HSCX_CH_A)
+ {
+ if (activate)
+ HSCX_B_IMASK &= ~(HSCX_MASK_EXA | HSCX_MASK_ICA);
+ else
+ HSCX_B_IMASK |= HSCX_MASK_EXA | HSCX_MASK_ICA;
+ HSCX_WRITE(HSCX_CH_A, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
+ }
+ else
+ {
+ if (activate)
+ HSCX_B_IMASK &= ~HSCX_MASK_EXB;
+ else
+ HSCX_B_IMASK |= HSCX_MASK_EXB;
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
+ }
+
+ /* clear spurious interrupts left over */
+
+ if(h_chan == HSCX_CH_A)
+ {
+ HSCX_READ(h_chan, H_EXIR);
+ HSCX_READ(h_chan, H_ISTA);
+ }
+ else /* mask ICA, because it must not be cleared by reading ISTA */
+ {
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK | HSCX_MASK_ICA);
+ HSCX_READ(h_chan, H_EXIR);
+ HSCX_READ(h_chan, H_ISTA);
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * write command to HSCX command register
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_cmd(struct l1_softc *sc, int h_chan, unsigned char cmd)
+{
+ int timeout = 20;
+
+ while(((HSCX_READ(h_chan, H_STAR)) & HSCX_STAR_CEC) && timeout)
+ {
+ DELAY(10);
+ timeout--;
+ }
+
+ if(timeout == 0)
+ {
+ NDBGL1(L1_H_ERR, "HSCX wait for CEC timeout!");
+ }
+
+ HSCX_WRITE(h_chan, H_CMDR, cmd);
+}
+
+/*---------------------------------------------------------------------------*
+ * wait for HSCX transmit FIFO write enable
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_waitxfw(struct l1_softc *sc, int h_chan)
+{
+#define WAITVAL 50
+#define WAITTO 200
+
+ int timeout = WAITTO;
+
+ while((!(((HSCX_READ(h_chan, H_STAR)) &
+ (HSCX_STAR_CEC | HSCX_STAR_XFW)) == HSCX_STAR_XFW)) && timeout)
+ {
+ DELAY(WAITVAL);
+ timeout--;
+ }
+
+ if(timeout == 0)
+ {
+ NDBGL1(L1_H_ERR, "HSCX wait for XFW timeout!");
+ }
+ else if (timeout != WAITTO)
+ {
+ NDBGL1(L1_H_XFRERR, "HSCX wait for XFW time: %d uS", (WAITTO-timeout)*50);
+ }
+}
+
diff --git a/sys/dev/ic/i4b_hscx.h b/sys/dev/ic/i4b_hscx.h
new file mode 100644
index 00000000000..241316a3d1d
--- /dev/null
+++ b/sys/dev/ic/i4b_hscx.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 1996, 1998 Gary Jennejohn. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * $Id: i4b_hscx.h,v 1.1.1.1 2001/01/05 12:50:10 martin Exp $
+ *
+ * last edit-date: [Sun Feb 14 10:26:56 1999]
+ *
+ * -hm added AVM config register defs
+ * -hm split up for rewrite of Siemens chipset driver
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef I4B_HSCX_H_
+#define I4B_HSCX_H_
+
+enum HSCX_VERSIONS {
+ HSCX_VA1, /* 82525 A1 */
+ HSCX_UNKN1, /* unknown 1 */
+ HSCX_VA2, /* 82525 A2 */
+ HSCX_UNKN3, /* unknown 3 */
+ HSCX_VA3, /* 82525 A3 */
+ HSCX_V21, /* 82525 2.1 */
+ HSCX_UNKN /* unknown version */
+};
+
+#define HSCX_CH_A 0 /* channel A */
+#define HSCX_CH_B 1 /* channel B */
+
+#define HSCX_FIFO_LEN 32 /* 32 bytes FIFO on chip */
+
+/*
+ * definitions of registers and bits for the HSCX ISDN chip.
+ */
+
+typedef struct hscx_reg {
+
+ /* 32 byte deep FIFO always first */
+
+ unsigned char hscx_fifo [HSCX_FIFO_LEN];
+
+ /* most registers can be read/written, but have different names */
+ /* so define a union with read/write names to make that clear */
+
+ union {
+ struct {
+ unsigned char hscx_ista;
+ unsigned char hscx_star;
+ unsigned char hscx_mode;
+ unsigned char hscx_timr;
+ unsigned char hscx_exir;
+ unsigned char hscx_rbcl;
+ unsigned char dummy_26;
+ unsigned char hscx_rsta;
+ unsigned char hscx_ral1;
+ unsigned char hscx_rhcr;
+ unsigned char dummy_2a;
+ unsigned char dummy_2b;
+ unsigned char hscx_ccr2;
+ unsigned char hscx_rbch;
+ unsigned char hscx_vstr;
+ unsigned char hscx_ccr;
+ unsigned char dummy_30;
+ unsigned char dummy_31;
+ unsigned char dummy_32;
+ unsigned char dummy_33;
+ } hscx_r;
+ struct {
+ unsigned char hscx_mask;
+ unsigned char hscx_cmdr;
+ unsigned char hscx_mode;
+ unsigned char hscx_timr;
+ unsigned char hscx_xad1;
+ unsigned char hscx_xad2;
+ unsigned char hscx_rah1;
+ unsigned char hscx_rah2;
+ unsigned char hscx_ral1;
+ unsigned char hscx_ral2;
+ unsigned char hscx_xbcl;
+ unsigned char hscx_bgr;
+ unsigned char hscx_ccr2;
+ unsigned char hscx_xbch;
+ unsigned char hscx_rlcr;
+ unsigned char hscx_ccr1;
+ unsigned char hscx_tsax;
+ unsigned char hscx_tsar;
+ unsigned char hscx_xccr;
+ unsigned char hscx_rccr;
+ } hscx_w;
+ } hscx_rw;
+} hscx_reg_t;
+
+#define REG_OFFSET(type, field) (int)(&(((type *)0)->field))
+
+/* HSCX read registers */
+
+#define h_ista hscx_rw.hscx_r.hscx_ista
+#define H_ISTA REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ista)
+#define h_star hscx_rw.hscx_r.hscx_star
+#define H_STAR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_star)
+#define h_mode hscx_rw.hscx_r.hscx_mode
+#define H_MODE REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_mode)
+#define h_timr hscx_rw.hscx_r.hscx_timr
+#define H_TIMR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_timr)
+#define h_exir hscx_rw.hscx_r.hscx_exir
+#define H_EXIR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_exir)
+#define h_rbcl hscx_rw.hscx_r.hscx_rbcl
+#define H_RBCL REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rbcl)
+#define h_rsta hscx_rw.hscx_r.hscx_rsta
+#define H_RSTA REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rsta)
+#define h_ral1 hscx_rw.hscx_r.hscx_ral1
+#define H_RAL1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ral1)
+#define h_rhcr hscx_rw.hscx_r.hscx_rhcr
+#define H_RHCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rhcr)
+#define h_ccr2 hscx_rw.hscx_r.hscx_ccr2
+#define H_CCR2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ccr2)
+#define h_rbch hscx_rw.hscx_r.hscx_rbch
+#define H_RBCH REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rbch)
+#define h_vstr hscx_rw.hscx_r.hscx_vstr
+#define H_VSTR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_vstr)
+#define h_ccr hscx_rw.hscx_r.hscx_ccr
+#define H_CCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ccr)
+
+/* HSCX write registers - for hscx_mode, hscx_timr, hscx_ral1, hscx_ccr2 */
+/* see read registers */
+
+#define h_mask hscx_rw.hscx_w.hscx_mask
+#define H_MASK REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_mask)
+#define h_cmdr hscx_rw.hscx_w.hscx_cmdr
+#define H_CMDR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_cmdr)
+#define h_xad1 hscx_rw.hscx_w.hscx_xad1
+#define H_XAD1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xad1)
+#define h_xad2 hscx_rw.hscx_w.hscx_xad2
+#define H_XAD2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xad2)
+#define h_rah1 hscx_rw.hscx_w.hscx_rah1
+#define H_RAH1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rah1)
+#define h_rah2 hscx_rw.hscx_w.hscx_rah2
+#define H_RAH2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rah2)
+#define h_ral2 hscx_rw.hscx_w.hscx_ral2
+#define H_RAL2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_ral2)
+#define h_xbcl hscx_rw.hscx_w.hscx_xbcl
+#define H_XBCL REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xbcl)
+#define h_bgr hscx_rw.hscx_w.hscx_bgr
+#define H_BGR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_bgr)
+#define h_xbch hscx_rw.hscx_w.hscx_xbch
+#define H_XBCH REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xbch)
+#define h_rlcr hscx_rw.hscx_w.hscx_rlcr
+#define H_RLCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rlcr)
+#define h_ccr1 hscx_rw.hscx_w.hscx_ccr1
+#define H_CCR1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_ccr1)
+#define h_tsax hscx_rw.hscx_w.hscx_tsax
+#define H_TSAX REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_tsax)
+#define h_tsar hscx_rw.hscx_w.hscx_tsar
+#define H_TSAR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_tsar)
+#define h_xccr hscx_rw.hscx_w.hscx_xccr
+#define H_XCCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xccr)
+#define h_rccr hscx_rw.hscx_w.hscx_rccr
+#define H_RCCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rccr)
+
+#define HSCX_ISTA_RME 0x80
+#define HSCX_ISTA_RPF 0x40
+#define HSCX_ISTA_RSC 0x20
+#define HSCX_ISTA_XPR 0x10
+#define HSCX_ISTA_TIN 0x08
+#define HSCX_ISTA_ICA 0x04
+#define HSCX_ISTA_EXA 0x02
+#define HSCX_ISTA_EXB 0x01
+
+#define HSCX_MASK_RME 0x80
+#define HSCX_MASK_RPF 0x40
+#define HSCX_MASK_RSC 0x20
+#define HSCX_MASK_XPR 0x10
+#define HSCX_MASK_TIN 0x08
+#define HSCX_MASK_ICA 0x04
+#define HSCX_MASK_EXA 0x02
+#define HSCX_MASK_EXB 0x01
+
+#define HSCX_EXIR_XMR 0x80
+#define HSCX_EXIR_XDU 0x40
+#define HSCX_EXIR_PCE 0x20
+#define HSCX_EXIR_RFO 0x10
+#define HSCX_EXIR_CSC 0x08
+#define HSCX_EXIR_RFS 0x04
+
+/* the other bits are always 0 */
+
+#define HSCX_STAR_XDOV 0x80
+#define HSCX_STAR_XFW 0x40
+#define HSCX_STAR_XRNR 0x20
+#define HSCX_STAR_RRNR 0x10
+#define HSCX_STAR_RLI 0x08
+#define HSCX_STAR_CEC 0x04
+#define HSCX_STAR_CTS 0x02
+#define HSCX_STAR_WFA 0x01
+
+#define HSCX_CMDR_RMC 0x80
+#define HSCX_CMDR_RHR 0x40
+/* also known as XREP in transparent mode */
+#define HSCX_CMDR_RNR 0x20
+#define HSCX_CMDR_STI 0x10
+#define HSCX_CMDR_XTF 0x08
+#define HSCX_CMDR_XIF 0x04
+#define HSCX_CMDR_XME 0x02
+#define HSCX_CMDR_XRES 0x01
+
+#define HSCX_MODE_MDS1 0x80
+#define HSCX_MODE_MDS0 0x40
+#define HSCX_MODE_ADM 0x20
+#define HSCX_MODE_TMD 0x10
+#define HSCX_MODE_RAC 0x08
+#define HSCX_MODE_RTS 0x04
+#define HSCX_MODE_TRS 0x02
+#define HSCX_MODE_TLP 0x01
+
+#define HSCX_RSTA_VFR 0x80
+#define HSCX_RSTA_RDO 0x40
+#define HSCX_RSTA_CRC 0x20
+#define HSCX_RSTA_RAB 0x10
+#define HSCX_RSTA_HA1 0x08
+#define HSCX_RSTA_HA0 0x04
+#define HSCX_RSTA_CR 0x02
+#define HSCX_RSTA_LA 0x01
+
+#define HSCX_RSTA_MASK 0xf0 /* the interesting ones */
+
+/* only used in DMA mode */
+#define HSCX_XBCH_DMA 0x80
+#define HSCX_XBCH_NRM 0x40
+#define HSCX_XBCH_CAS 0x20
+#define HSCX_XBCH_XC 0x10
+/* the rest are bits 11 thru 8 of the byte count */
+
+#define HSCX_RBCH_DMA 0x80
+#define HSCX_RBCH_NRM 0x40
+#define HSCX_RBCH_CAS 0x20
+#define HSCX_RBCH_OV 0x10
+/* the rest are bits 11 thru 8 of the byte count */
+
+#define HSCX_VSTR_CD 0x80
+/* bits 6 thru 4 are 0 */
+/* bits 3 thru 0 are the version number */
+
+#define HSCX_RLCR_RC 0x80
+/* the rest of the bits are used to set the received length */
+
+#define HSCX_CCR1_PU 0x80
+/* bits 6 and 5 are SC1 SC0 */
+#define HSCX_CCR1_ODS 0x10
+#define HSCX_CCR1_ITF 0x08
+#define HSCX_CCR1_CM2 0x04
+#define HSCX_CCR1_CM1 0x02
+#define HSCX_CCR1_CM0 0x01
+
+/* for clock mode 5 */
+#define HSCX_CCR2_SOC2 0x80
+#define HSCX_CCR2_SOC1 0x40
+#define HSCX_CCR2_XCS0 0x20
+#define HSCX_CCR2_RCS0 0x10
+#define HSCX_CCR2_TIO 0x08
+#define HSCX_CCR2_CIE 0x04
+#define HSCX_CCR2_RIE 0x02
+#define HSCX_CCR2_DIV 0x01
+
+/* bits 7 thru 2 are TSNX */
+#define HSCX_TSAX_XCS2 0x02
+#define HSCX_TSAX_XCS1 0x01
+
+/* bits 7 thru 2 are TSNR */
+#define HSCX_TSAR_RCS2 0x02
+#define HSCX_TSAR_RCS1 0x01
+
+#endif /* I4B_HSCX_H_ */
diff --git a/sys/dev/ic/i4b_ipac.h b/sys/dev/ic/i4b_ipac.h
new file mode 100644
index 00000000000..2588d2c0d0f
--- /dev/null
+++ b/sys/dev/ic/i4b_ipac.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_ipac.h - definitions for the Siemens IPAC PSB2115 chip
+ * ==========================================================
+ *
+ * $Id: i4b_ipac.h,v 1.1.1.1 2001/01/05 12:50:10 martin Exp $
+ *
+ * last edit-date: [Thu Jan 6 14:54:19 2000]
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef _I4B_IPAC_H_
+#define _I4B_IPAC_H_
+
+#define IPAC_BFIFO_LEN 64 /* 64 bytes B-channel FIFO on chip */
+
+#define IPAC_HSCXA_OFF 0x00
+#define IPAC_HSCXB_OFF 0x40
+#define IPAC_ISAC_OFF 0x80
+#define IPAC_IPAC_OFF 0xc0
+
+/* chip version */
+
+#define IPAC_V11 0x01 /* IPAC Version 1.1 */
+#define IPAC_V12 0x02 /* IPAC Version 1.2 */
+
+/*
+ * definitions of registers and bits for the IPAC ISDN chip.
+ */
+
+typedef struct ipac_reg {
+
+ /* most registers can be read/written, but have different names */
+ /* so define a union with read/write names to make that clear */
+
+ union {
+ struct {
+ unsigned char ipac_conf;
+ unsigned char ipac_ista;
+ unsigned char ipac_id;
+ unsigned char ipac_acfg;
+ unsigned char ipac_aoe;
+ unsigned char ipac_arx;
+ unsigned char ipac_pita1;
+ unsigned char ipac_pita2;
+ unsigned char ipac_pota1;
+ unsigned char ipac_pota2;
+ unsigned char ipac_pcfg;
+ unsigned char ipac_scfg;
+ unsigned char ipac_timr2;
+ } ipac_r;
+ struct {
+ unsigned char ipac_conf;
+ unsigned char ipac_mask;
+ unsigned char ipac_dummy;
+ unsigned char ipac_acfg;
+ unsigned char ipac_aoe;
+ unsigned char ipac_atx;
+ unsigned char ipac_pita1;
+ unsigned char ipac_pita2;
+ unsigned char ipac_pota1;
+ unsigned char ipac_pota2;
+ unsigned char ipac_pcfg;
+ unsigned char ipac_scfg;
+ unsigned char ipac_timr2;
+ } ipac_w;
+ } ipac_rw;
+} ipac_reg_t;
+
+#define REG_OFFSET(type, field) (int)(&(((type *)0)->field))
+
+/* IPAC read registers */
+
+#define IPAC_CONF REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_conf)
+#define IPAC_ISTA REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_ista)
+#define IPAC_ID REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_id)
+#define IPAC_ACFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_acfg)
+#define IPAC_AOE REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_aoe)
+#define IPAC_ARX REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_arx)
+#define IPAC_PITA1 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pita1)
+#define IPAC_PITA2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pita2)
+#define IPAC_POTA1 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pota1)
+#define IPAC_POTA2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pota2)
+#define IPAC_PCFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pcfg)
+#define IPAC_SCFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_scfg)
+#define IPAC_TIMR2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_timr2)
+
+/* IPAC write registers */
+
+#define IPAC_MASK REG_OFFSET(ipac_reg_t, ipac_rw.ipac_w.ipac_mask)
+#define IPAC_ATX REG_OFFSET(ipac_reg_t, ipac_rw.ipac_w.ipac_atx)
+
+/* register bits */
+
+#define IPAC_CONF_AMP 0x80
+#define IPAC_CONF_CFS 0x40
+#define IPAC_CONF_TEM 0x20
+#define IPAC_CONF_PDS 0x10
+#define IPAC_CONF_IDH 0x08
+#define IPAC_CONF_SGO 0x04
+#define IPAC_CONF_ODS 0x02
+#define IPAC_CONF_IOF 0x01
+
+#define IPAC_ISTA_INT1 0x80
+#define IPAC_ISTA_INT0 0x40
+#define IPAC_ISTA_ICD 0x20
+#define IPAC_ISTA_EXD 0x10
+#define IPAC_ISTA_ICA 0x08
+#define IPAC_ISTA_EXA 0x04
+#define IPAC_ISTA_ICB 0x02
+#define IPAC_ISTA_EXB 0x01
+
+#define IPAC_MASK_INT1 0x80
+#define IPAC_MASK_INT0 0x40
+#define IPAC_MASK_ICD 0x20
+#define IPAC_MASK_EXD 0x10
+#define IPAC_MASK_ICA 0x08
+#define IPAC_MASK_EXA 0x04
+#define IPAC_MASK_ICB 0x02
+#define IPAC_MASK_EXB 0x01
+
+#define IPAC_ACFG_OD7 0x80
+#define IPAC_ACFG_OD6 0x40
+#define IPAC_ACFG_OD5 0x20
+#define IPAC_ACFG_OD4 0x10
+#define IPAC_ACFG_OD3 0x08
+#define IPAC_ACFG_OD2 0x04
+#define IPAC_ACFG_EL1 0x02
+#define IPAC_ACFG_EL2 0x01
+
+#define IPAC_AOE_OE7 0x80
+#define IPAC_AOE_OE6 0x40
+#define IPAC_AOE_OE5 0x20
+#define IPAC_AOE_OE4 0x10
+#define IPAC_AOE_OE3 0x08
+#define IPAC_AOE_OE2 0x04
+
+#define IPAC_ARX_AR7 0x80
+#define IPAC_ARX_AR6 0x40
+#define IPAC_ARX_AR5 0x20
+#define IPAC_ARX_AR4 0x10
+#define IPAC_ARX_AR3 0x08
+#define IPAC_ARX_AR2 0x04
+
+#define IPAC_ATX_AT7 0x80
+#define IPAC_ATX_AT6 0x40
+#define IPAC_ATX_AT5 0x20
+#define IPAC_ATX_AT4 0x10
+#define IPAC_ATX_AT3 0x08
+#define IPAC_ATX_AT2 0x04
+
+#define IPAC_PITA1_ENA 0x80
+#define IPAC_PITA1_DUDD 0x40
+
+#define IPAC_PITA2_ENA 0x80
+#define IPAC_PITA2_DUDD 0x40
+
+#define IPAC_POTA1_ENA 0x80
+#define IPAC_POTA1_DUDD 0x40
+
+#define IPAC_POTA2_ENA 0x80
+#define IPAC_POTA2_DUDD 0x40
+
+#define IPAC_PCFG_DPS 0x80
+#define IPAC_PCFG_ACL 0x40
+#define IPAC_PCFG_LED 0x20
+#define IPAC_PCFG_PLD 0x10
+#define IPAC_PCFG_FBS 0x08
+#define IPAC_PCFG_CSL2 0x04
+#define IPAC_PCFG_CSL1 0x02
+#define IPAC_PCFG_CSL0 0x01
+
+#define IPAC_SCFG_PRI 0x80
+#define IPAC_SCFG_TXD 0x40
+#define IPAC_SCFG_TLEN 0x20
+
+#define IPAC_TIMR2_TMD 0x80
+
+#endif /* _I4B_IPAC_H_ */
diff --git a/sys/dev/ic/i4b_isac.c b/sys/dev/ic/i4b_isac.c
new file mode 100644
index 00000000000..8e1ce794957
--- /dev/null
+++ b/sys/dev/ic/i4b_isac.c
@@ -0,0 +1,683 @@
+/*
+ * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_isac.c - i4b siemens isdn chipset driver ISAC handler
+ * ---------------------------------------------------------
+ *
+ * $Id: i4b_isac.c,v 1.1.1.1 2001/01/05 12:50:11 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:36:10 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "opt_i4b.h"
+#endif
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#ifndef __bsdi__
+#include <machine/bus.h>
+#endif
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#include <netisdn/i4b_trace.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+static u_char isic_isac_exir_hdlr(register struct l1_softc *sc, u_char exir);
+static void isic_isac_ind_hdlr(register struct l1_softc *sc, int ind);
+
+/*---------------------------------------------------------------------------*
+ * ISAC interrupt service routine
+ *---------------------------------------------------------------------------*/
+void
+isic_isac_irq(struct l1_softc *sc, int ista)
+{
+ register u_char c = 0;
+ NDBGL1(L1_F_MSG, "unit %d: ista = 0x%02x", sc->sc_unit, ista);
+
+ if(ista & ISAC_ISTA_EXI) /* extended interrupt */
+ {
+ c |= isic_isac_exir_hdlr(sc, ISAC_READ(I_EXIR));
+ }
+
+ if(ista & ISAC_ISTA_RME) /* receive message end */
+ {
+ register int rest;
+ u_char rsta;
+
+ /* get rx status register */
+
+ rsta = ISAC_READ(I_RSTA);
+
+ if((rsta & ISAC_RSTA_MASK) != 0x20)
+ {
+ int error = 0;
+
+ if(!(rsta & ISAC_RSTA_CRC)) /* CRC error */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: CRC error", sc->sc_unit);
+ }
+
+ if(rsta & ISAC_RSTA_RDO) /* ReceiveDataOverflow */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: Data Overrun error", sc->sc_unit);
+ }
+
+ if(rsta & ISAC_RSTA_RAB) /* ReceiveABorted */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: Receive Aborted error", sc->sc_unit);
+ }
+
+ if(error == 0)
+ {
+ NDBGL1(L1_I_ERR, "unit %d: RME unknown error, RSTA = 0x%02x!", sc->sc_unit, rsta);
+ }
+
+ i4b_Dfreembuf(sc->sc_ibuf);
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES);
+ ISACCMDRWRDELAY();
+
+ return;
+ }
+
+ rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1));
+
+ if(rest == 0)
+ rest = ISAC_FIFO_LEN;
+
+ if(sc->sc_ibuf == NULL)
+ {
+ if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL)
+ sc->sc_ib = sc->sc_ibuf->m_data;
+ else
+ panic("isic_isac_irq: RME, i4b_Dgetmbuf returns NULL!\n");
+ sc->sc_ilen = 0;
+ }
+
+ if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest))
+ {
+ ISAC_RDFIFO(sc->sc_ib, rest);
+ sc->sc_ilen += rest;
+
+ sc->sc_ibuf->m_pkthdr.len =
+ sc->sc_ibuf->m_len = sc->sc_ilen;
+
+ if(sc->sc_trace & TRACE_D_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
+ }
+
+ c |= ISAC_CMDR_RMC;
+
+ if(sc->sc_enabled &&
+ (ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S))
+ {
+ PH_Data_Ind(sc->sc_unit, sc->sc_ibuf);
+ }
+ else
+ {
+ i4b_Dfreembuf(sc->sc_ibuf);
+ }
+ }
+ else
+ {
+ NDBGL1(L1_I_ERR, "RME, input buffer overflow!");
+ i4b_Dfreembuf(sc->sc_ibuf);
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+ }
+
+ if(ista & ISAC_ISTA_RPF) /* receive fifo full */
+ {
+ if(sc->sc_ibuf == NULL)
+ {
+ if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL)
+ sc->sc_ib= sc->sc_ibuf->m_data;
+ else
+ panic("isic_isac_irq: RPF, i4b_Dgetmbuf returns NULL!\n");
+ sc->sc_ilen = 0;
+ }
+
+ if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN))
+ {
+ ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN);
+ sc->sc_ilen += ISAC_FIFO_LEN;
+ sc->sc_ib += ISAC_FIFO_LEN;
+ c |= ISAC_CMDR_RMC;
+ }
+ else
+ {
+ NDBGL1(L1_I_ERR, "RPF, input buffer overflow!");
+ i4b_Dfreembuf(sc->sc_ibuf);
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+ }
+
+ if(ista & ISAC_ISTA_XPR) /* transmit fifo empty (XPR bit set) */
+ {
+ if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL))
+ {
+ sc->sc_freeflag = sc->sc_freeflag2;
+ sc->sc_obuf = sc->sc_obuf2;
+ sc->sc_op = sc->sc_obuf->m_data;
+ sc->sc_ol = sc->sc_obuf->m_len;
+ sc->sc_obuf2 = NULL;
+#ifdef NOTDEF
+ printf("ob2=%x, op=%x, ol=%d, f=%d #",
+ sc->sc_obuf,
+ sc->sc_op,
+ sc->sc_ol,
+ sc->sc_state);
+#endif
+ }
+ else
+ {
+#ifdef NOTDEF
+ printf("ob=%x, op=%x, ol=%d, f=%d #",
+ sc->sc_obuf,
+ sc->sc_op,
+ sc->sc_ol,
+ sc->sc_state);
+#endif
+ }
+
+ if(sc->sc_obuf)
+ {
+ ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN));
+
+ if(sc->sc_ol > ISAC_FIFO_LEN) /* length > 32 ? */
+ {
+ sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */
+ sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */
+ c |= ISAC_CMDR_XTF; /* set XTF bit */
+ }
+ else
+ {
+ if(sc->sc_freeflag)
+ {
+ i4b_Dfreembuf(sc->sc_obuf);
+ sc->sc_freeflag = 0;
+ }
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+
+ c |= ISAC_CMDR_XTF | ISAC_CMDR_XME;
+ }
+ }
+ else
+ {
+ sc->sc_state &= ~ISAC_TX_ACTIVE;
+ }
+ }
+
+ if(ista & ISAC_ISTA_CISQ) /* channel status change CISQ */
+ {
+ register u_char ci;
+
+ /* get command/indication rx register*/
+
+ ci = ISAC_READ(I_CIRR);
+
+ /* if S/Q IRQ, read SQC reg to clr SQC IRQ */
+
+ if(ci & ISAC_CIRR_SQC)
+ (void) ISAC_READ(I_SQRR);
+
+ /* C/I code change IRQ (flag already cleared by CIRR read) */
+
+ if(ci & ISAC_CIRR_CIC0)
+ isic_isac_ind_hdlr(sc, (ci >> 2) & 0xf);
+ }
+
+ if(c)
+ {
+ ISAC_WRITE(I_CMDR, c);
+ ISACCMDRWRDELAY();
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Extended IRQ handler
+ *---------------------------------------------------------------------------*/
+static u_char
+isic_isac_exir_hdlr(register struct l1_softc *sc, u_char exir)
+{
+ u_char c = 0;
+
+ if(exir & ISAC_EXIR_XMR)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Tx Message Repeat");
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_XDU)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Tx Data Underrun");
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_PCE)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Protocol Error");
+ }
+
+ if(exir & ISAC_EXIR_RFO)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Rx Frame Overflow");
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ if(exir & ISAC_EXIR_SOV)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Sync Xfer Overflow");
+ }
+
+ if(exir & ISAC_EXIR_MOS)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Monitor Status");
+ }
+
+ if(exir & ISAC_EXIR_SAW)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ NDBGL1(L1_I_ERR, "EXIRQ Subscriber Awake");
+ }
+
+ if(exir & ISAC_EXIR_WOV)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ NDBGL1(L1_I_ERR, "EXIRQ Watchdog Timer Overflow");
+ }
+
+ return(c);
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Indication handler
+ *---------------------------------------------------------------------------*/
+static void
+isic_isac_ind_hdlr(register struct l1_softc *sc, int ind)
+{
+ register int event;
+
+ switch(ind)
+ {
+ case ISAC_CIRR_IAI8:
+ NDBGL1(L1_I_CICO, "rx AI8 in state %s", isic_printstate(sc));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ isic_isac_l1_cmd(sc, CMD_AR8);
+ event = EV_INFO48;
+ MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_ACTIVE);
+ break;
+
+ case ISAC_CIRR_IAI10:
+ NDBGL1(L1_I_CICO, "rx AI10 in state %s", isic_printstate(sc));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ isic_isac_l1_cmd(sc, CMD_AR10);
+ event = EV_INFO410;
+ MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_ACTIVE);
+ break;
+
+ case ISAC_CIRR_IRSY:
+ NDBGL1(L1_I_CICO, "rx RSY in state %s", isic_printstate(sc));
+ event = EV_RSY;
+ break;
+
+ case ISAC_CIRR_IPU:
+ NDBGL1(L1_I_CICO, "rx PU in state %s", isic_printstate(sc));
+ event = EV_PU;
+ break;
+
+ case ISAC_CIRR_IDR:
+ NDBGL1(L1_I_CICO, "rx DR in state %s", isic_printstate(sc));
+ isic_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_DR;
+ break;
+
+ case ISAC_CIRR_IDID:
+ NDBGL1(L1_I_CICO, "rx DID in state %s", isic_printstate(sc));
+ event = EV_INFO0;
+ MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_IDLE);
+ break;
+
+ case ISAC_CIRR_IDIS:
+ NDBGL1(L1_I_CICO, "rx DIS in state %s", isic_printstate(sc));
+ event = EV_DIS;
+ break;
+
+ case ISAC_CIRR_IEI:
+ NDBGL1(L1_I_CICO, "rx EI in state %s", isic_printstate(sc));
+ isic_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_EI;
+ break;
+
+ case ISAC_CIRR_IARD:
+ NDBGL1(L1_I_CICO, "rx ARD in state %s", isic_printstate(sc));
+ event = EV_INFO2;
+ break;
+
+ case ISAC_CIRR_ITI:
+ NDBGL1(L1_I_CICO, "rx TI in state %s", isic_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_IATI:
+ NDBGL1(L1_I_CICO, "rx ATI in state %s", isic_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_ISD:
+ NDBGL1(L1_I_CICO, "rx SD in state %s", isic_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ default:
+ NDBGL1(L1_I_ERR, "UNKNOWN Indication 0x%x in state %s", ind, isic_printstate(sc));
+ event = EV_INFO0;
+ break;
+ }
+ isic_next_state(sc, event);
+}
+
+/*---------------------------------------------------------------------------*
+ * execute a layer 1 command
+ *---------------------------------------------------------------------------*/
+void
+isic_isac_l1_cmd(struct l1_softc *sc, int command)
+{
+ u_char cmd;
+
+#ifdef I4B_SMP_WORKAROUND
+
+ /* XXXXXXXXXXXXXXXXXXX */
+
+ /*
+ * patch from Wolfgang Helbig:
+ *
+ * Here is a patch that makes i4b work on an SMP:
+ * The card (TELES 16.3) didn't interrupt on an SMP machine.
+ * This is a gross workaround, but anyway it works *and* provides
+ * some information as how to finally fix this problem.
+ */
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, 0xff);
+ DELAY(100);
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ /* XXXXXXXXXXXXXXXXXXX */
+
+#endif /* I4B_SMP_WORKAROUND */
+
+ if(command < 0 || command > CMD_ILL)
+ {
+ NDBGL1(L1_I_ERR, "illegal cmd 0x%x in state %s", command, isic_printstate(sc));
+ return;
+ }
+
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ cmd = ISAC_CIX0_LOW;
+ else
+ cmd = 0;
+
+ switch(command)
+ {
+ case CMD_TIM:
+ NDBGL1(L1_I_CICO, "tx TIM in state %s", isic_printstate(sc));
+ cmd |= (ISAC_CIXR_CTIM << 2);
+ break;
+
+ case CMD_RS:
+ NDBGL1(L1_I_CICO, "tx RS in state %s", isic_printstate(sc));
+ cmd |= (ISAC_CIXR_CRS << 2);
+ break;
+
+ case CMD_AR8:
+ NDBGL1(L1_I_CICO, "tx AR8 in state %s", isic_printstate(sc));
+ cmd |= (ISAC_CIXR_CAR8 << 2);
+ break;
+
+ case CMD_AR10:
+ NDBGL1(L1_I_CICO, "tx AR10 in state %s", isic_printstate(sc));
+ cmd |= (ISAC_CIXR_CAR10 << 2);
+ break;
+
+ case CMD_DIU:
+ NDBGL1(L1_I_CICO, "tx DIU in state %s", isic_printstate(sc));
+ cmd |= (ISAC_CIXR_CDIU << 2);
+ break;
+ }
+ ISAC_WRITE(I_CIXR, cmd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L1 ISAC initialization
+ *---------------------------------------------------------------------------*/
+int
+isic_isac_init(struct l1_softc *sc)
+{
+ ISAC_IMASK = 0xff; /* disable all irqs */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ if(sc->sc_bustyp != BUS_TYPE_IOM2)
+ {
+ NDBGL1(L1_I_SETUP, "configuring for IOM-1 mode");
+
+ /* ADF2: Select mode IOM-1 */
+ ISAC_WRITE(I_ADF2, 0x00);
+
+ /* SPCR: serial port control register:
+ * SPU - software power up = 0
+ * SAC - SIP port high Z
+ * SPM - timing mode 0
+ * TLP - test loop = 0
+ * C1C, C2C - B1 and B2 switched to/from SPa
+ */
+ ISAC_WRITE(I_SPCR, ISAC_SPCR_C1C1|ISAC_SPCR_C2C1);
+
+ /* SQXR: S/Q channel xmit register:
+ * SQIE - S/Q IRQ enable = 0
+ * SQX1-4 - Fa bits = 1
+ */
+ ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
+
+ /* ADF1: additional feature reg 1:
+ * WTC - watchdog = 0
+ * TEM - test mode = 0
+ * PFS - pre-filter = 0
+ * CFS - IOM clock/frame always active
+ * FSC1/2 - polarity of 8kHz strobe
+ * ITF - interframe fill = idle
+ */
+ ISAC_WRITE(I_ADF1, ISAC_ADF1_FC2); /* ADF1 */
+
+ /* STCR: sync transfer control reg:
+ * TSF - terminal secific functions = 0
+ * TBA - TIC bus address = 7
+ * STx/SCx = 0
+ */
+ ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
+
+ /* MODE: Mode Register:
+ * MDSx - transparent mode 2
+ * TMD - timer mode = external
+ * RAC - Receiver enabled
+ * DIMx - digital i/f mode
+ */
+ ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
+ }
+ else
+ {
+ NDBGL1(L1_I_SETUP, "configuring for IOM-2 mode");
+
+ /* ADF2: Select mode IOM-2 */
+ ISAC_WRITE(I_ADF2, ISAC_ADF2_IMS);
+
+ /* SPCR: serial port control register:
+ * SPU - software power up = 0
+ * SPM - timing mode 0
+ * TLP - test loop = 0
+ * C1C, C2C - B1 + C1 and B2 + IC2 monitoring
+ */
+ ISAC_WRITE(I_SPCR, 0x00);
+
+ /* SQXR: S/Q channel xmit register:
+ * IDC - IOM direction = 0 (master)
+ * CFS - Config Select = 0 (clock always active)
+ * CI1E - C/I channel 1 IRQ enable = 0
+ * SQIE - S/Q IRQ enable = 0
+ * SQX1-4 - Fa bits = 1
+ */
+ ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
+
+ /* ADF1: additional feature reg 1:
+ * WTC - watchdog = 0
+ * TEM - test mode = 0
+ * PFS - pre-filter = 0
+ * IOF - IOM i/f off = 0
+ * ITF - interframe fill = idle
+ */
+ ISAC_WRITE(I_ADF1, 0x00);
+
+ /* STCR: sync transfer control reg:
+ * TSF - terminal secific functions = 0
+ * TBA - TIC bus address = 7
+ * STx/SCx = 0
+ */
+ ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
+
+ /* MODE: Mode Register:
+ * MDSx - transparent mode 2
+ * TMD - timer mode = external
+ * RAC - Receiver enabled
+ * DIMx - digital i/f mode
+ */
+ ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
+ }
+
+#ifdef NOTDEF
+ /*
+ * XXX a transmitter reset causes an ISAC tx IRQ which will not
+ * be serviced at attach time under some circumstances leaving
+ * the associated IRQ line on the ISA bus active. This prevents
+ * any further interrupts to be serviced because no low -> high
+ * transition can take place anymore. (-hm)
+ */
+
+ /* command register:
+ * RRES - HDLC receiver reset
+ * XRES - transmitter reset
+ */
+ ISAC_WRITE(I_CMDR, ISAC_CMDR_RRES|ISAC_CMDR_XRES);
+ ISACCMDRWRDELAY();
+#endif
+
+ /* enabled interrupts:
+ * ===================
+ * RME - receive message end
+ * RPF - receive pool full
+ * XPR - transmit pool ready
+ * CISQ - CI or S/Q channel change
+ * EXI - extended interrupt
+ */
+
+ ISAC_IMASK = ISAC_MASK_RSC | /* auto mode only */
+ ISAC_MASK_TIN | /* timer irq */
+ ISAC_MASK_SIN; /* sync xfer irq */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ return(0);
+}
diff --git a/sys/dev/ic/i4b_isac.h b/sys/dev/ic/i4b_isac.h
new file mode 100644
index 00000000000..62e9affaa56
--- /dev/null
+++ b/sys/dev/ic/i4b_isac.h
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 1996, 1998 Gary Jennejohn. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * $Id: i4b_isac.h,v 1.1.1.1 2001/01/05 12:50:11 martin Exp $
+ *
+ * last edit-date: [Sun Feb 14 10:27:13 1999]
+ *
+ * -hm split up for rewrite of Siemens chipset driver
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef I4B_ISAC_H_
+#define I4B_ISAC_H_
+
+/*
+ * The ISAC databook specifies a delay of 2.5 DCL clock cycles between
+ * writes to the ISAC command register CMDR. This is the delay used to
+ * satisfy this requirement.
+ */
+
+#define I4B_ISAC_CMDRWRDELAY 30
+
+#if (I4B_ISAC_CMDRWRDELAY > 0)
+#define ISACCMDRWRDELAY() DELAY(I4B_ISAC_CMDRWRDELAY)
+#else
+#warning "I4B_ISAC_CMDRWRDELAY set to 0!"
+#define ISACCMDRWRDELAY()
+#endif
+
+enum ISAC_VERSIONS {
+ ISAC_VA, /* 2085 A1 or A2, 2086/2186 V1.1 */
+ ISAC_VB1, /* 2085 B1 */
+ ISAC_VB2, /* 2085 B2 */
+ ISAC_VB3, /* 2085 B3/V2.3 */
+ ISAC_UNKN /* unknown version */
+};
+
+#define ISAC_FIFO_LEN 32 /* 32 bytes FIFO on chip */
+
+/*
+ * definitions of registers and bits for the ISAC ISDN chip.
+ */
+
+typedef struct isac_reg {
+
+ /* 32 byte deep FIFO always first */
+
+ unsigned char isac_fifo [ISAC_FIFO_LEN];
+
+ /* most registers can be read/written, but have different names */
+ /* so define a union with read/write names to make that clear */
+
+ union {
+ struct {
+ unsigned char isac_ista;
+ unsigned char isac_star;
+ unsigned char isac_mode;
+ unsigned char isac_timr;
+ unsigned char isac_exir;
+ unsigned char isac_rbcl;
+ unsigned char isac_sapr;
+ unsigned char isac_rsta;
+ unsigned char dummy_28;
+ unsigned char isac_rhcr;
+ unsigned char isac_rbch;
+ unsigned char isac_star2;
+ unsigned char dummy_2c;
+ unsigned char dummy_2d;
+ unsigned char dummy_2e;
+ unsigned char dummt_2f;
+ unsigned char isac_spcr;
+ unsigned char isac_cirr;
+ unsigned char isac_mor;
+ unsigned char isac_sscr;
+ unsigned char isac_sfcr;
+ unsigned char isac_c1r;
+ unsigned char isac_c2r;
+ unsigned char isac_b1cr;
+ unsigned char isac_b2cr;
+ unsigned char isac_adf2;
+ unsigned char isac_mosr;
+ unsigned char isac_sqrr;
+ } isac_r;
+ struct {
+ unsigned char isac_mask;
+ unsigned char isac_cmdr;
+ unsigned char isac_mode;
+ unsigned char isac_timr;
+ unsigned char isac_xad1;
+ unsigned char isac_xad2;
+ unsigned char isac_sap1;
+ unsigned char isac_sap2;
+ unsigned char isac_tei1;
+ unsigned char isac_tei2;
+ unsigned char dummy_2a;
+ unsigned char isac_star2;
+ unsigned char dummy_2c;
+ unsigned char dummy_2d;
+ unsigned char dummy_2e;
+ unsigned char dummt_2f;
+ unsigned char isac_spcr;
+ unsigned char isac_cixr;
+ unsigned char isac_mox;
+ unsigned char isac_sscx;
+ unsigned char isac_sfcw;
+ unsigned char isac_c1r;
+ unsigned char isac_c2r;
+ unsigned char isac_stcr;
+ unsigned char isac_adf1;
+ unsigned char isac_adf2;
+ unsigned char isac_mocr;
+ unsigned char isac_sqxr;
+ } isac_w;
+ } isac_rw;
+} isac_reg_t;
+
+#define REG_OFFSET(type, field) (int)(&(((type *)0)->field))
+
+/* ISAC read registers */
+
+#define i_ista isac_rw.isac_r.isac_ista
+#define I_ISTA REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_ista)
+#define i_star isac_rw.isac_r.isac_star
+#define I_STAR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_star)
+#define i_mode isac_rw.isac_r.isac_mode
+#define I_MODE REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mode)
+#define i_timr isac_rw.isac_r.isac_timr
+#define I_TIMR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_timr)
+#define i_exir isac_rw.isac_r.isac_exir
+#define I_EXIR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_exir)
+#define i_rbcl isac_rw.isac_r.isac_rbcl
+#define I_RBCL REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rbcl)
+#define i_sapr isac_rw.isac_r.isac_sapr
+#define I_SAPR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sapr)
+#define i_rsta isac_rw.isac_r.isac_rsta
+#define I_RSTA REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rsta)
+#define i_rhcr isac_rw.isac_r.isac_rhcr
+#define I_RHCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rhcr)
+#define i_rbch isac_rw.isac_r.isac_rbch
+#define I_RBCH REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rbch)
+#define i_star2 isac_rw.isac_r.isac_star2
+#define I_STAR2 REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_star2)
+#define i_spcr isac_rw.isac_r.isac_spcr
+#define I_SPCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_spcr)
+#define i_cirr isac_rw.isac_r.isac_cirr
+#define I_CIRR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_cirr)
+#define i_mor isac_rw.isac_r.isac_mor
+#define I_MOR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mor)
+#define i_sscr isac_rw.isac_r.isac_sscr
+#define I_SSCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sscr)
+#define i_sfcr isac_rw.isac_r.isac_sfcr
+#define I_SFCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sfcr)
+#define i_c1r isac_rw.isac_r.isac_c1r
+#define I_C1R REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_c1r)
+#define i_c2r isac_rw.isac_r.isac_c2r
+#define I_C2R REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_c2r)
+#define i_b1cr isac_rw.isac_r.isac_b1cr
+#define I_B1CR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_b1cr)
+#define i_b2cr isac_rw.isac_r.isac_b2cr
+#define I_B2CR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_b2cr)
+#define i_adf2 isac_rw.isac_r.isac_adf2
+#define I_ADF2 REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_adf2)
+#define i_mosr isac_rw.isac_r.isac_mosr
+#define I_MOSR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mosr)
+#define i_sqrr isac_rw.isac_r.isac_sqrr
+#define I_SQRR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sqrr)
+
+/* ISAC write registers - isac_mode, isac_timr, isac_star2, isac_spcr, */
+/* isac_c1r, isac_c2r, isac_adf2 see read registers */
+
+#define i_mask isac_rw.isac_w.isac_mask
+#define I_MASK REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mask)
+#define i_cmdr isac_rw.isac_w.isac_cmdr
+#define I_CMDR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_cmdr)
+#define i_xad1 isac_rw.isac_w.isac_xad1
+#define I_XAD1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_xad1)
+#define i_xad2 isac_rw.isac_w.isac_xad2
+#define I_XAD2 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_xad2)
+#define i_sap1 isac_rw.isac_w.isac_sap1
+#define I_SAP1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sap1)
+#define i_sap2 isac_rw.isac_w.isac_sap2
+#define I_SAP2 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sap2)
+#define i_tei1 isac_rw.isac_w.isac_tei1
+#define i_tei2 isac_rw.isac_w.isac_tei2
+#define i_cixr isac_rw.isac_w.isac_cixr
+#define I_CIXR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_cixr)
+#define I_CIX0 I_CIXR
+#define i_mox isac_rw.isac_w.isac_mox
+#define I_MOX REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mox)
+#define i_sscx isac_rw.isac_w.isac_sscx
+#define I_SSCX REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sscx)
+#define i_sfcw isac_rw.isac_w.isac_sfcw
+#define I_SFCW REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sfcw)
+#define i_stcr isac_rw.isac_w.isac_stcr
+#define I_STCR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_stcr)
+#define i_adf1 isac_rw.isac_w.isac_adf1
+#define I_ADF1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_adf1)
+#define i_mocr isac_rw.isac_w.isac_mocr
+#define I_MOCR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mocr)
+#define i_sqxr isac_rw.isac_w.isac_sqxr
+#define I_SQXR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sqxr)
+
+#define ISAC_ISTA_RME 0x80
+#define ISAC_ISTA_RPF 0x40
+#define ISAC_ISTA_RSC 0x20
+#define ISAC_ISTA_XPR 0x10
+#define ISAC_ISTA_TIN 0x08
+#define ISAC_ISTA_CISQ 0x04
+#define ISAC_ISTA_SIN 0x02
+#define ISAC_ISTA_EXI 0x01
+
+#define ISAC_MASK_RME 0x80
+#define ISAC_MASL_RPF 0x40
+#define ISAC_MASK_RSC 0x20
+#define ISAC_MASK_XPR 0x10
+#define ISAC_MASK_TIN 0x08
+#define ISAC_MASK_CISQ 0x04
+#define ISAC_MASK_SIN 0x02
+#define ISAC_MASK_EXI 0x01
+#define ISAC_MASK_ALL 0xff
+
+#define ISAC_STAR_XDOV 0x80
+#define ISAC_STAR_XFW 0x40
+#define ISAC_STAR_XRNR 0x20
+#define ISAC_STAR_RRNR 0x10
+#define ISAC_STAR_MBR 0x08
+#define ISAC_STAR_MAC1 0x04
+#define ISAC_STAR_BVS 0x02
+#define ISAC_STAR_MAC0 0x01
+
+#define ISAC_CMDR_RMC 0x80
+#define ISAC_CMDR_RRES 0x40
+#define ISAC_CMDR_RNR 0x20
+#define ISAC_CMDR_STI 0x10
+#define ISAC_CMDR_XTF 0x08
+#define ISAC_CMDR_XIF 0x04
+#define ISAC_CMDR_XME 0x02
+#define ISAC_CMDR_XRES 0x01
+
+#define ISAC_MODE_MDS2 0x80
+#define ISAC_MODE_MDS1 0x40
+#define ISAC_MODE_MDS0 0x20
+#define ISAC_MODE_TMD 0x10
+#define ISAC_MODE_RAC 0x08
+#define ISAC_MODE_DIM2 0x04
+#define ISAC_MODE_DIM1 0x02
+#define ISAC_MODE_DIM0 0x01
+
+#define ISAC_EXIR_XMR 0x80
+#define ISAC_EXIR_XDU 0x40
+#define ISAC_EXIR_PCE 0x20
+#define ISAC_EXIR_RFO 0x10
+#define ISAC_EXIR_SOV 0x08
+#define ISAC_EXIR_MOS 0x04
+#define ISAC_EXIR_SAW 0x02
+#define ISAC_EXIR_WOV 0x01
+
+#define ISAC_RSTA_RDA 0x80
+#define ISAC_RSTA_RDO 0x40
+#define ISAC_RSTA_CRC 0x20
+#define ISAC_RSTA_RAB 0x10
+#define ISAC_RSTA_SA1 0x08
+#define ISAC_RSTA_SA0 0x04
+#define ISAC_RSTA_CR 0x02
+#define ISAC_RSTA_TA 0x01
+
+#define ISAC_RSTA_MASK 0x70 /* the interesting bits */
+
+#define ISAC_RBCH_XAC 0x80
+#define ISAC_RBCH_VN1 0x40
+#define ISAC_RBCH_VN0 0x20
+#define ISAC_RBCH_OV 0x10
+/* the other 4 bits are the high bits of the receive byte count */
+
+#define ISAC_SPCR_SPU 0x80
+#define ISAC_SPCR_SAC 0x40
+#define ISAC_SPCR_SPM 0x20
+#define ISAC_SPCR_TLP 0x10
+#define ISAC_SPCR_C1C1 0x08
+#define ISAC_SPCR_C1C0 0x04
+#define ISAC_SPCR_C2C1 0x02
+#define ISAC_SPCR_C2C0 0x01
+
+#define ISAC_CIRR_SQC 0x80
+#define ISAC_CIRR_BAS 0x40
+/* bits 5-2 CODR */
+#define ISAC_CIRR_CIC0 0x02
+/* bit 0 is always 0 */
+/* C/I codes from bits 5-2 (>> 2 & 0xf) */
+/* the indications */
+#define ISAC_CIRR_IPU 0x07
+#define ISAC_CIRR_IDR 0x00
+#define ISAC_CIRR_ISD 0x02
+#define ISAC_CIRR_IDIS 0x03
+#define ISAC_CIRR_IEI 0x06
+#define ISAC_CIRR_IRSY 0x04
+#define ISAC_CIRR_IARD 0x08
+#define ISAC_CIRR_ITI 0x0a
+#define ISAC_CIRR_IATI 0x0b
+#define ISAC_CIRR_IAI8 0x0c
+#define ISAC_CIRR_IAI10 0x0d
+#define ISAC_CIRR_IDID 0x0f
+
+#define ISAC_CI_MASK 0x0f
+
+#define ISAC_CIXR_RSS 0x80
+#define ISAC_CIXR_BAC 0x40
+/* bits 5-2 CODX */
+#define ISAC_CIXR_TCX 0x02
+#define ISAC_CIXR_ECX 0x01
+/* in IOM-2 mode the low bits are always 1 */
+#define ISAC_CIX0_LOW 0x03
+/* C/I codes from bits 5-2 (>> 2 & 0xf) */
+/* the commands */
+#define ISAC_CIXR_CTIM 0
+#define ISAC_CIXR_CRS 0x01
+#define ISAC_CIXR_CSCZ 0x04
+#define ISAC_CIXR_CSSZ 0x02
+#define ISAC_CIXR_CAR8 0x08
+#define ISAC_CIXR_CAR10 0x09
+#define ISAC_CIXR_CARL 0x0a
+#define ISAC_CIXR_CDIU 0x0f
+
+#define ISAC_STCR_TSF 0x80
+#define ISAC_STCR_TBA2 0x40
+#define ISAC_STCR_TBA1 0x20
+#define ISAC_STCR_TBA0 0x10
+#define ISAC_STCR_ST1 0x08
+#define ISAC_STCR_ST0 0x04
+#define ISAC_STCR_SC1 0x02
+#define ISAC_STCR_SC0 0x01
+
+#define ISAC_ADF1_WTC1 0x80
+#define ISAC_ADF1_WTC2 0x40
+#define ISAC_ADF1_TEM 0x20
+#define ISAC_ADF1_PFS 0x10
+#define ISAC_ADF1_CFS 0x08
+#define ISAC_ADF1_FC2 0x04
+#define ISAC_ADF1_FC1 0x02
+#define ISAC_ADF1_ITF 0x01
+
+#define ISAC_ADF2_IMS 0x80
+/* all other bits are 0 */
+
+/* bits 7-5 are always 0 */
+#define ISAC_SQRR_SYN 0x10
+#define ISAC_SQRR_SQR1 0x08
+#define ISAC_SQRR_SQR2 0x04
+#define ISAC_SQRR_SQR3 0x02
+#define ISAC_SQRR_SQR4 0x01
+
+#define ISAC_SQXR_IDC 0x80
+#define ISAC_SQXR_CFS 0x40
+#define ISAC_SQXR_CI1E 0x20
+#define ISAC_SQXR_SQIE 0x10
+#define ISAC_SQXR_SQX1 0x08
+#define ISAC_SQXR_SQX2 0x04
+#define ISAC_SQXR_SQX3 0x02
+#define ISAC_SQXR_SQX4 0x01
+
+#endif /* I4B_ISAC_H_ */
diff --git a/sys/dev/ic/i4b_isic.c b/sys/dev/ic/i4b_isic.c
new file mode 100644
index 00000000000..8978f9fa8a7
--- /dev/null
+++ b/sys/dev/ic/i4b_isic.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_isic.c - global isic stuff
+ * ==============================
+ *
+ * $Id: i4b_isic.c,v 1.1.1.1 2001/01/05 12:50:11 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:36:10 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <sys/device.h>
+#if defined(__NetBSD__) && defined(amiga)
+#include <machine/bus.h>
+#else
+#ifndef __bsdi__
+#include <dev/isa/isavar.h>
+#endif
+#endif
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#include <netisdn/i4b_trace.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_ipac.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+#include <netisdn/i4b_global.h>
+
+#ifdef __bsdi__
+static int isicmatch(struct device *parent, struct cfdata *cf, void *aux);
+static void isicattach(struct device *parent, struct device *self, void *aux);
+struct cfdriver isiccd =
+ { NULL, "isic", isicmatch, isicattach, DV_IFNET,
+ sizeof(struct l1_softc) };
+
+int isa_isicmatch(struct device *parent, struct cfdata *cf, struct isa_attach_args *);
+int isapnp_isicmatch(struct device *parent, struct cfdata *cf, struct isa_attach_args *);
+int isa_isicattach(struct device *parent, struct device *self, struct isa_attach_args *ia);
+
+static int
+isicmatch(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct isa_attach_args *ia = (struct isa_attach_args *) aux;
+ if (ia->ia_bustype == BUS_PCMCIA) {
+ ia->ia_irq = IRQNONE;
+ /* return 1; Not yet */
+ return 0; /* for now */
+ }
+ if (ia->ia_bustype == BUS_PNP) {
+ return isapnp_isicmatch(parent, cf, ia);
+ }
+ return isa_isicmatch(parent, cf, ia);
+}
+
+static void
+isicattach(struct device *parent, struct device *self, void *aux)
+{
+ struct isa_attach_args *ia = (struct isa_attach_args *) aux;
+ struct l1_softc *sc = (struct l1_softc *)self;
+
+ sc->sc_flags = sc->sc_dev.dv_flags;
+ isa_isicattach(parent, self, ia);
+ isa_establish(&sc->sc_id, &sc->sc_dev);
+ sc->sc_ih.ih_fun = isicintr;
+ sc->sc_ih.ih_arg = (void *)sc;
+ intr_establish(ia->ia_irq, &sc->sc_ih, DV_NET);
+ /* Could add a shutdown hook here... */
+}
+#endif
+
+#ifdef __FreeBSD__
+void isicintr_sc(struct l1_softc *sc);
+#if !(defined(__FreeBSD_version)) || (defined(__FreeBSD_version) && __FreeBSD_version >= 300006)
+void isicintr(int unit);
+#endif
+#else
+/* XXX - hack, going away soon! */
+struct l1_softc *l1_sc[ISIC_MAXUNIT];
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic - device driver interrupt routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+void
+isicintr_sc(struct l1_softc *sc)
+{
+ isicintr(sc->sc_unit);
+}
+
+void
+isicintr(int unit)
+{
+ register struct l1_softc *sc = &l1_sc[unit];
+#else
+int
+isicintr(void *arg)
+{
+ struct l1_softc *sc = arg;
+#endif
+
+ if(sc->sc_ipac == 0) /* HSCX/ISAC interupt routine */
+ {
+ u_char was_hscx_irq = 0;
+ u_char was_isac_irq = 0;
+
+ register u_char hscx_irq_stat;
+ register u_char isac_irq_stat;
+
+ for(;;)
+ {
+ /* get hscx irq status from hscx b ista */
+ hscx_irq_stat =
+ HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK;
+
+ /* get isac irq status */
+ isac_irq_stat = ISAC_READ(I_ISTA);
+
+ /* do as long as there are pending irqs in the chips */
+ if(!hscx_irq_stat && !isac_irq_stat)
+ break;
+
+ if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF |
+ HSCX_ISTA_RSC | HSCX_ISTA_XPR |
+ HSCX_ISTA_TIN | HSCX_ISTA_EXB))
+ {
+ isic_hscx_irq(sc, hscx_irq_stat,
+ HSCX_CH_B,
+ hscx_irq_stat & HSCX_ISTA_EXB);
+ was_hscx_irq = 1;
+ }
+
+ if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA))
+ {
+ isic_hscx_irq(sc,
+ HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK,
+ HSCX_CH_A,
+ hscx_irq_stat & HSCX_ISTA_EXA);
+ was_hscx_irq = 1;
+ }
+
+ if(isac_irq_stat)
+ {
+ isic_isac_irq(sc, isac_irq_stat); /* isac handler */
+ was_isac_irq = 1;
+ }
+ }
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+
+ if (sc->clearirq)
+ {
+ DELAY(80);
+ sc->clearirq(sc);
+ } else
+ DELAY(100);
+
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+#ifndef __FreeBSD__
+ return(was_hscx_irq || was_isac_irq);
+#endif
+ }
+ else /* IPAC interrupt routine */
+ {
+ register u_char ipac_irq_stat;
+ register u_char was_ipac_irq = 0;
+
+ for(;;)
+ {
+ /* get global irq status */
+
+ ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f;
+
+ /* check hscx a */
+
+ if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA))
+ {
+ /* HSCX A interrupt */
+ isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA),
+ HSCX_CH_A,
+ ipac_irq_stat & IPAC_ISTA_EXA);
+ was_ipac_irq = 1;
+ }
+ if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB))
+ {
+ /* HSCX B interrupt */
+ isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA),
+ HSCX_CH_B,
+ ipac_irq_stat & IPAC_ISTA_EXB);
+ was_ipac_irq = 1;
+ }
+ if(ipac_irq_stat & IPAC_ISTA_ICD)
+ {
+ /* ISAC interrupt */
+ isic_isac_irq(sc, ISAC_READ(I_ISTA));
+ was_ipac_irq = 1;
+ }
+ if(ipac_irq_stat & IPAC_ISTA_EXD)
+ {
+ /* force ISAC interrupt handling */
+ isic_isac_irq(sc, ISAC_ISTA_EXI);
+ was_ipac_irq = 1;
+ }
+
+ /* do as long as there are pending irqs in the chip */
+ if(!ipac_irq_stat)
+ break;
+ }
+#ifdef NOTDEF
+ if(was_ipac_irq == 0)
+ NDBGL1(L1_ERROR, "WARNING: unit %d, No IRQ from IPAC!", sc->sc_unit);
+#endif
+ IPAC_WRITE(IPAC_MASK, 0xff);
+ DELAY(50);
+ IPAC_WRITE(IPAC_MASK, 0xc0);
+
+#ifndef __FreeBSD__
+ return(was_ipac_irq);
+#endif
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_recovery - try to recover from irq lockup
+ *---------------------------------------------------------------------------*/
+void
+isic_recover(struct l1_softc *sc)
+{
+ u_char byte;
+
+ /* get hscx irq status from hscx b ista */
+
+ byte = HSCX_READ(HSCX_CH_B, H_ISTA);
+
+ NDBGL1(L1_ERROR, "HSCX B: ISTA = 0x%x", byte);
+
+ if(byte & HSCX_ISTA_ICA)
+ NDBGL1(L1_ERROR, "HSCX A: ISTA = 0x%x", (u_char)HSCX_READ(HSCX_CH_A, H_ISTA));
+
+ if(byte & HSCX_ISTA_EXB)
+ NDBGL1(L1_ERROR, "HSCX B: EXIR = 0x%x", (u_char)HSCX_READ(HSCX_CH_B, H_EXIR));
+
+ if(byte & HSCX_ISTA_EXA)
+ NDBGL1(L1_ERROR, "HSCX A: EXIR = 0x%x", (u_char)HSCX_READ(HSCX_CH_A, H_EXIR));
+
+ /* get isac irq status */
+
+ byte = ISAC_READ(I_ISTA);
+
+ NDBGL1(L1_ERROR, " ISAC: ISTA = 0x%x", byte);
+
+ if(byte & ISAC_ISTA_EXI)
+ NDBGL1(L1_ERROR, " ISAC: EXIR = 0x%x", (u_char)ISAC_READ(I_EXIR));
+
+ if(byte & ISAC_ISTA_CISQ)
+ {
+ byte = ISAC_READ(I_CIRR);
+
+ NDBGL1(L1_ERROR, " ISAC: CISQ = 0x%x", byte);
+
+ if(byte & ISAC_CIRR_SQC)
+ NDBGL1(L1_ERROR, " ISAC: SQRR = 0x%x", (u_char)ISAC_READ(I_SQRR));
+ }
+
+ NDBGL1(L1_ERROR, "HSCX B: IMASK = 0x%x", HSCX_B_IMASK);
+ NDBGL1(L1_ERROR, "HSCX A: IMASK = 0x%x", HSCX_A_IMASK);
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+ DELAY(100);
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+ DELAY(100);
+
+ NDBGL1(L1_ERROR, " ISAC: IMASK = 0x%x", ISAC_IMASK);
+
+ ISAC_WRITE(I_MASK, 0xff);
+ DELAY(100);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+}
diff --git a/sys/dev/ic/i4b_isicbchan.c b/sys/dev/ic/i4b_isicbchan.c
new file mode 100644
index 00000000000..685c1a14bfc
--- /dev/null
+++ b/sys/dev/ic/i4b_isicbchan.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_bchan.c - B channel handling L1 procedures
+ * ----------------------------------------------
+ *
+ * $Id: i4b_isicbchan.c,v 1.1.1.1 2001/01/05 12:50:12 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:36:11 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#ifndef __bsdi__
+#include <machine/bus.h>
+#endif
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#include <netisdn/i4b_trace.h>
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+#include <netisdn/i4b_global.h>
+
+static void isic_bchannel_start __P((int unit, int h_chan));
+static void isic_bchannel_stat __P((int unit, int h_chan, bchan_statistics_t *bsp));
+
+static void isic_set_linktab(int unit, int channel, drvr_link_t *dlt);
+static isdn_link_t *isic_ret_linktab(int unit, int channel);
+
+/*---------------------------------------------------------------------------*
+ * initialize one B channels rx/tx data structures and init/deinit HSCX
+ *---------------------------------------------------------------------------*/
+void
+isic_bchannel_setup(int unit, int h_chan, int bprot, int activate)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+ l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+
+ int s = SPLI4B();
+
+ if(activate == 0)
+ {
+ /* deactivation */
+ isic_hscx_init(sc, h_chan, activate);
+ }
+
+ NDBGL1(L1_BCHAN, "unit=%d, channel=%d, %s",
+ sc->sc_unit, h_chan, activate ? "activate" : "deactivate");
+
+ /* general part */
+
+ chan->unit = sc->sc_unit; /* unit number */
+ chan->channel = h_chan; /* B channel */
+ chan->bprot = bprot; /* B channel protocol */
+ chan->state = HSCX_IDLE; /* B channel state */
+
+ /* receiver part */
+
+ i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */
+
+ chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+ chan->rxcount = 0; /* reset rx counter */
+
+ i4b_Bfreembuf(chan->in_mbuf); /* clean rx mbuf */
+
+ chan->in_mbuf = NULL; /* reset mbuf ptr */
+ chan->in_cbptr = NULL; /* reset mbuf curr ptr */
+ chan->in_len = 0; /* reset mbuf data len */
+
+ /* transmitter part */
+
+ i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */
+
+ chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+ chan->txcount = 0; /* reset tx counter */
+
+ i4b_Bfreembuf(chan->out_mbuf_head); /* clean tx mbuf */
+
+ chan->out_mbuf_head = NULL; /* reset head mbuf ptr */
+ chan->out_mbuf_cur = NULL; /* reset current mbuf ptr */
+ chan->out_mbuf_cur_ptr = NULL; /* reset current mbuf data ptr */
+ chan->out_mbuf_cur_len = 0; /* reset current mbuf data cnt */
+
+ if(activate != 0)
+ {
+ /* activation */
+ isic_hscx_init(sc, h_chan, activate);
+ }
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * start transmission on a b channel
+ *---------------------------------------------------------------------------*/
+static void
+isic_bchannel_start(int unit, int h_chan)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+
+ register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+ register int next_len;
+ register int len;
+
+ int s;
+ int activity = -1;
+ int cmd = 0;
+
+ s = SPLI4B(); /* enter critical section */
+ if(chan->state & HSCX_TX_ACTIVE) /* already running ? */
+ {
+ splx(s);
+ return; /* yes, leave */
+ }
+
+ /* get next mbuf from queue */
+
+ IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
+
+ if(chan->out_mbuf_head == NULL) /* queue empty ? */
+ {
+ splx(s); /* leave critical section */
+ return; /* yes, exit */
+ }
+
+ /* init current mbuf values */
+
+ chan->out_mbuf_cur = chan->out_mbuf_head;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+
+ /* activity indicator for timeout handling */
+
+ if(chan->bprot == BPROT_NONE)
+ {
+ if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
+ activity = ACT_TX;
+ }
+ else
+ {
+ activity = ACT_TX;
+ }
+
+ chan->state |= HSCX_TX_ACTIVE; /* we start transmitting */
+
+ if(sc->sc_trace & TRACE_B_TX) /* if trace, send mbuf to trace dev */
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+
+ len = 0; /* # of chars put into HSCX tx fifo this time */
+
+ /*
+ * fill the HSCX tx fifo with data from the current mbuf. if
+ * current mbuf holds less data than HSCX fifo length, try to
+ * get the next mbuf from (a possible) mbuf chain. if there is
+ * not enough data in a single mbuf or in a chain, then this
+ * is the last mbuf and we tell the HSCX that it has to send
+ * CRC and closing flag
+ */
+
+ while((len < sc->sc_bfifolen) && chan->out_mbuf_cur)
+ {
+ /*
+ * put as much data into the HSCX fifo as is
+ * available from the current mbuf
+ */
+
+ if((len + chan->out_mbuf_cur_len) >= sc->sc_bfifolen)
+ next_len = sc->sc_bfifolen - len;
+ else
+ next_len = chan->out_mbuf_cur_len;
+
+#ifdef NOTDEF
+ printf("b:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
+ chan->out_mbuf_head,
+ chan->out_mbuf_cur,
+ chan->out_mbuf_cur_ptr,
+ chan->out_mbuf_cur_len,
+ len,
+ next_len);
+#endif
+
+ /* wait for tx fifo write enabled */
+
+ isic_hscx_waitxfw(sc, h_chan);
+
+ /* write what we have from current mbuf to HSCX fifo */
+
+ HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, next_len);
+
+ len += next_len; /* update # of bytes written */
+ chan->txcount += next_len; /* statistics */
+ chan->out_mbuf_cur_ptr += next_len; /* data ptr */
+ chan->out_mbuf_cur_len -= next_len; /* data len */
+
+ /*
+ * in case the current mbuf (of a possible chain) data
+ * has been put into the fifo, check if there is a next
+ * mbuf in the chain. If there is one, get ptr to it
+ * and update the data ptr and the length
+ */
+
+ if((chan->out_mbuf_cur_len <= 0) &&
+ ((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL))
+ {
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+ }
+ }
+
+ /*
+ * if there is either still data in the current mbuf and/or
+ * there is a successor on the chain available issue just
+ * a XTF (transmit) command to HSCX. if ther is no more
+ * data available from the current mbuf (-chain), issue
+ * an XTF and an XME (message end) command which will then
+ * send the CRC and the closing HDLC flag sequence
+ */
+
+ if(chan->out_mbuf_cur && (chan->out_mbuf_cur_len > 0))
+ {
+ /*
+ * more data available, send current fifo out.
+ * next xfer to HSCX tx fifo is done in the
+ * HSCX interrupt routine.
+ */
+
+ cmd |= HSCX_CMDR_XTF;
+ }
+ else
+ {
+ /* end of mbuf chain */
+
+ if(chan->bprot == BPROT_NONE)
+ cmd |= HSCX_CMDR_XTF;
+ else
+ cmd |= HSCX_CMDR_XTF | HSCX_CMDR_XME;
+
+ i4b_Bfreembuf(chan->out_mbuf_head); /* free mbuf chain */
+
+ chan->out_mbuf_head = NULL;
+ chan->out_mbuf_cur = NULL;
+ chan->out_mbuf_cur_ptr = NULL;
+ chan->out_mbuf_cur_len = 0;
+ }
+
+ /* call timeout handling routine */
+
+ if(activity == ACT_RX || activity == ACT_TX)
+ (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity);
+
+ if(cmd)
+ isic_hscx_cmd(sc, h_chan, cmd);
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * fill statistics struct
+ *---------------------------------------------------------------------------*/
+static void
+isic_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+ l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+ int s;
+
+ s = SPLI4B();
+
+ bsp->outbytes = chan->txcount;
+ bsp->inbytes = chan->rxcount;
+
+ chan->txcount = 0;
+ chan->rxcount = 0;
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * return the address of isic drivers linktab
+ *---------------------------------------------------------------------------*/
+static isdn_link_t *
+isic_ret_linktab(int unit, int channel)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+ l1_bchan_state_t *chan = &sc->sc_chan[channel];
+
+ return(&chan->isdn_linktab);
+}
+
+/*---------------------------------------------------------------------------*
+ * set the driver linktab in the b channel softc
+ *---------------------------------------------------------------------------*/
+static void
+isic_set_linktab(int unit, int channel, drvr_link_t *dlt)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+ l1_bchan_state_t *chan = &sc->sc_chan[channel];
+
+ chan->drvr_linktab = dlt;
+}
+
+/*---------------------------------------------------------------------------*
+ * initialize our local linktab
+ *---------------------------------------------------------------------------*/
+void
+isic_init_linktab(struct l1_softc *sc)
+{
+ l1_bchan_state_t *chan = &sc->sc_chan[HSCX_CH_A];
+ isdn_link_t *lt = &chan->isdn_linktab;
+
+ /* make sure the hardware driver is known to layer 4 */
+ ctrl_types[CTRL_PASSIVE].set_linktab = isic_set_linktab;
+ ctrl_types[CTRL_PASSIVE].get_linktab = isic_ret_linktab;
+
+ /* local setup */
+ lt->unit = sc->sc_unit;
+ lt->channel = HSCX_CH_A;
+ lt->bch_config = isic_bchannel_setup;
+ lt->bch_tx_start = isic_bchannel_start;
+ lt->bch_stat = isic_bchannel_stat;
+ lt->tx_queue = &chan->tx_queue;
+
+ /* used by non-HDLC data transfers, i.e. telephony drivers */
+ lt->rx_queue = &chan->rx_queue;
+
+ /* used by HDLC data transfers, i.e. ipr and isp drivers */
+ lt->rx_mbuf = &chan->in_mbuf;
+
+ chan = &sc->sc_chan[HSCX_CH_B];
+ lt = &chan->isdn_linktab;
+
+ lt->unit = sc->sc_unit;
+ lt->channel = HSCX_CH_B;
+ lt->bch_config = isic_bchannel_setup;
+ lt->bch_tx_start = isic_bchannel_start;
+ lt->bch_stat = isic_bchannel_stat;
+ lt->tx_queue = &chan->tx_queue;
+
+ /* used by non-HDLC data transfers, i.e. telephony drivers */
+ lt->rx_queue = &chan->rx_queue;
+
+ /* used by HDLC data transfers, i.e. ipr and isp drivers */
+ lt->rx_mbuf = &chan->in_mbuf;
+}
+
+/*---------------------------------------------------------------------------*
+ * telephony silence detection
+ *---------------------------------------------------------------------------*/
+
+#define TEL_IDLE_MIN (BCH_MAX_DATALEN/2)
+
+int
+isic_hscx_silence(unsigned char *data, int len)
+{
+ register int i = 0;
+ register int j = 0;
+
+ /* count idle bytes */
+
+ for(;i < len; i++)
+ {
+ if((*data >= 0xaa) && (*data <= 0xac))
+ j++;
+ data++;
+ }
+
+#ifdef NOTDEF
+ printf("isic_hscx_silence: got %d silence bytes in frame\n", j);
+#endif
+
+ if(j < (TEL_IDLE_MIN))
+ return(0);
+ else
+ return(1);
+
+}
+
diff --git a/sys/dev/ic/i4b_isicl1.c b/sys/dev/ic/i4b_isicl1.c
new file mode 100644
index 00000000000..e6503f55d48
--- /dev/null
+++ b/sys/dev/ic/i4b_isicl1.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_l1.c - isdn4bsd layer 1 handler
+ * -----------------------------------
+ *
+ * $Id: i4b_isicl1.c,v 1.1.1.1 2001/01/05 12:50:12 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:36:11 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/param.h>
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#ifndef __bsdi__
+#include <machine/bus.h>
+#endif
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#include <netisdn/i4b_trace.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+#include <netisdn/i4b_global.h>
+
+unsigned int i4b_l1_debug = L1_DEBUG_DEFAULT;
+
+static int ph_data_req(int, struct mbuf *, int);
+static int ph_activate_req(int);
+
+/* from i4btrc driver i4b_trace.c */
+extern int get_trace_data_from_l1(int unit, int what, int len, char *buf);
+
+/* from layer 2 */
+extern int i4b_ph_data_ind(int unit, struct mbuf *m);
+extern int i4b_ph_activate_ind(int unit);
+extern int i4b_ph_deactivate_ind(int unit);
+extern int i4b_mph_status_ind(int, int, int);
+
+/* layer 1 lme */
+static int i4b_mph_command_req(int, int, void*);
+
+/* jump table */
+struct i4b_l1l2_func i4b_l1l2_func = {
+
+ /* Layer 1 --> Layer 2 */
+
+ (int (*)(int, struct mbuf *)) i4b_ph_data_ind,
+ (int (*)(int)) i4b_ph_activate_ind,
+ (int (*)(int)) i4b_ph_deactivate_ind,
+
+ /* Layer 2 --> Layer 1 */
+
+ (int (*)(int, struct mbuf *, int)) ph_data_req,
+ (int (*)(int)) ph_activate_req,
+
+ /* Layer 1 --> upstream, ISDN trace data */
+
+ (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1,
+
+ /* Driver control and status information */
+
+ (int (*)(int, int, int)) i4b_mph_status_ind,
+ (int (*)(int, int, void*)) i4b_mph_command_req,
+};
+
+/*---------------------------------------------------------------------------*
+ *
+ * L2 -> L1: PH-DATA-REQUEST
+ * =========================
+ *
+ * parms:
+ * unit physical interface unit number
+ * m mbuf containing L2 frame to be sent out
+ * freeflag MBUF_FREE: free mbuf here after having sent
+ * it out
+ * MBUF_DONTFREE: mbuf is freed by Layer 2
+ * returns:
+ * ==0 fail, nothing sent out
+ * !=0 ok, frame sent out
+ *
+ *---------------------------------------------------------------------------*/
+static int
+ph_data_req(int unit, struct mbuf *m, int freeflag)
+{
+ u_char cmd;
+ int s;
+
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+
+#ifdef NOTDEF
+ NDBGL1(L1_PRIM, "PH-DATA-REQUEST, unit %d, freeflag=%d", unit, freeflag);
+#endif
+
+ if(m == NULL) /* failsafe */
+ return (0);
+
+ s = SPLI4B();
+
+ if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */
+ {
+ NDBGL1(L1_I_ERR, "still in state F3!");
+ ph_activate_req(unit);
+ }
+
+ if(sc->sc_state & ISAC_TX_ACTIVE)
+ {
+ if(sc->sc_obuf2 == NULL)
+ {
+ sc->sc_obuf2 = m; /* save mbuf ptr */
+
+ if(freeflag)
+ sc->sc_freeflag2 = 1; /* IRQ must mfree */
+ else
+ sc->sc_freeflag2 = 0; /* IRQ must not mfree */
+
+ NDBGL1(L1_I_MSG, "using 2nd ISAC TX buffer, state = %s", isic_printstate(sc));
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, m->m_len, m->m_data);
+ }
+ splx(s);
+ return(1);
+ }
+
+ NDBGL1(L1_I_ERR, "No Space in TX FIFO, state = %s", isic_printstate(sc));
+
+ if(freeflag == MBUF_FREE)
+ i4b_Dfreembuf(m);
+
+ splx(s);
+ return (0);
+ }
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, m->m_len, m->m_data);
+ }
+
+ sc->sc_state |= ISAC_TX_ACTIVE; /* set transmitter busy flag */
+
+ NDBGL1(L1_I_MSG, "ISAC_TX_ACTIVE set");
+
+ sc->sc_freeflag = 0; /* IRQ must NOT mfree */
+
+ ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */
+
+ if(m->m_len > ISAC_FIFO_LEN) /* message > 32 bytes ? */
+ {
+ sc->sc_obuf = m; /* save mbuf ptr */
+ sc->sc_op = m->m_data + ISAC_FIFO_LEN; /* ptr for irq hdl */
+ sc->sc_ol = m->m_len - ISAC_FIFO_LEN; /* length for irq hdl */
+
+ if(freeflag)
+ sc->sc_freeflag = 1; /* IRQ must mfree */
+
+ cmd = ISAC_CMDR_XTF;
+ }
+ else
+ {
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+
+ if(freeflag)
+ i4b_Dfreembuf(m);
+
+ cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;
+ }
+
+ ISAC_WRITE(I_CMDR, cmd);
+ ISACCMDRWRDELAY();
+
+ splx(s);
+
+ return(1);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ * L2 -> L1: PH-ACTIVATE-REQUEST
+ * =============================
+ *
+ * parms:
+ * unit physical interface unit number
+ *
+ * returns:
+ * ==0
+ * !=0
+ *
+ *---------------------------------------------------------------------------*/
+static int
+ph_activate_req(int unit)
+{
+
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+
+ NDBGL1(L1_PRIM, "unit %d", unit);
+ isic_next_state(sc, EV_PHAR);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * command from the upper layers
+ *---------------------------------------------------------------------------*/
+static int
+i4b_mph_command_req(int unit, int command, void *parm)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+
+ switch(command)
+ {
+ case CMR_DOPEN: /* daemon running */
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_DOPEN", unit);
+ sc->sc_enabled = 1;
+ break;
+
+ case CMR_DCLOSE: /* daemon not running */
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_DCLOSE", unit);
+ sc->sc_enabled = 0;
+ break;
+
+ case CMR_SETTRACE:
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_SETTRACE, parm = %p", unit, parm);
+ sc->sc_trace = (unsigned int)parm;
+ break;
+
+ default:
+ NDBGL1(L1_ERROR, "ERROR, unknown command = %d, unit = %d, parm = %p", command, unit, parm);
+ break;
+ }
+
+ return(0);
+}
diff --git a/sys/dev/ic/i4b_isicl1.h b/sys/dev/ic/i4b_isicl1.h
new file mode 100644
index 00000000000..235d45c0cf5
--- /dev/null
+++ b/sys/dev/ic/i4b_isicl1.h
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------*
+ *
+ * i4b_l1.h - isdn4bsd layer 1 header file
+ * ---------------------------------------
+ *
+ * $Id: i4b_isicl1.h,v 1.1.1.1 2001/01/05 12:50:13 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:36:11 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef I4B_L1_H_
+#define I4B_L1_H_
+
+#ifdef __bsdi__
+#include <sys/device.h> /* XXX */
+#ifndef ISA_NPORT_CHECK /* Double yuck XXX */
+#include <i386/isa/isavar.h> /* XXX */
+#endif
+#endif
+
+#include <netisdn/i4b_l3l4.h>
+
+#define ISIC_MAXUNIT 4
+
+/*---------------------------------------------------------------------------
+ * kernel config file flags definition
+ *---------------------------------------------------------------------------*/
+#define FLAG_TELES_S0_8 1
+#define FLAG_TELES_S0_16 2
+#define FLAG_TELES_S0_163 3
+#define FLAG_AVM_A1 4
+#define FLAG_TELES_S0_163_PnP 5
+#define FLAG_CREATIX_S0_PnP 6
+#define FLAG_USR_ISDN_TA_INT 7
+#define FLAG_DRN_NGO 8
+#define FLAG_SWS 9
+#define FLAG_AVM_A1_PCMCIA 10
+#define FLAG_DYNALINK 11
+#define FLAG_BLMASTER 12
+#define FLAG_ELSA_QS1P_ISA 13
+#define FLAG_ELSA_QS1P_PCI 14
+#define FLAG_SIEMENS_ITALK 15
+#define FLAG_ELSA_MLIMC 16
+#define FLAG_ELSA_MLMCALL 17
+#define FLAG_ITK_IX1 18
+#define FLAG_AVMA1PCI 19
+#define FLAG_ELSA_PCC16 20
+#define FLAG_AVM_PNP 21
+#define FLAG_SIEMENS_ISURF2 22
+#define FLAG_ASUSCOM_IPAC 23
+
+#define SEC_DELAY 1000000 /* one second DELAY for DELAY*/
+
+#define MAX_DFRAME_LEN 264 /* max length of a D frame */
+
+#ifndef __bsdi__
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif
+
+#if !defined(__FreeBSD__) && !defined(__bsdi__)
+/* We try to map as few as possible as small as possible io and/or
+ memory regions. Each card defines its own interpretation of this
+ mapping array. At probe time we have a fixed size array, later
+ (when the card type is known) we allocate a minimal array
+ dynamically. */
+
+#define ISIC_MAX_IO_MAPS 49 /* no cardtype needs more yet */
+
+/* one entry in mapping array */
+struct isic_io_map {
+ bus_space_tag_t t; /* which bus-space is this? */
+ bus_space_handle_t h; /* handle of mapped bus space region */
+ bus_size_t offset; /* offset into region */
+ bus_size_t size; /* size of region, zero if not ours
+ (i.e.: don't ever unmap it!) */
+};
+
+/* this is passed around at probe time (no struct l1_softc yet) */
+struct isic_attach_args {
+ int ia_flags; /* flags from config file */
+ int ia_num_mappings; /* number of io mappings provided */
+ struct isic_io_map ia_maps[ISIC_MAX_IO_MAPS];
+};
+#endif
+
+#ifdef __FreeBSD__
+extern int next_isic_unit;
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_Bchan: the state of one B channel
+ *---------------------------------------------------------------------------*/
+typedef struct
+{
+ int unit; /* cards unit number */
+ int channel; /* which channel is this*/
+
+#if defined(__FreeBSD__) || defined(__bsdi__)
+ caddr_t hscx; /* HSCX address */
+#endif
+
+ u_char hscx_mask; /* HSCX interrupt mask */
+
+ int bprot; /* B channel protocol */
+
+ int state; /* this channels state */
+#define HSCX_IDLE 0x00 /* channel idle */
+#define HSCX_TX_ACTIVE 0x01 /* tx running */
+
+ /* receive data from ISDN */
+
+ struct ifqueue rx_queue; /* receiver queue */
+
+ int rxcount; /* rx statistics counter*/
+
+ struct mbuf *in_mbuf; /* rx input buffer */
+ u_char *in_cbptr; /* curr buffer pointer */
+ int in_len; /* rx input buffer len */
+
+ /* transmit data to ISDN */
+
+ struct ifqueue tx_queue; /* transmitter queue */
+
+ int txcount; /* tx statistics counter*/
+
+ struct mbuf *out_mbuf_head; /* first mbuf in possible chain */
+ struct mbuf *out_mbuf_cur; /* current mbuf in possbl chain */
+ unsigned char *out_mbuf_cur_ptr; /* data pointer into mbuf */
+ int out_mbuf_cur_len; /* remaining bytes in mbuf */
+
+ /* link between b channel and driver */
+
+ isdn_link_t isdn_linktab; /* b channel addresses */
+ drvr_link_t *drvr_linktab; /* ptr to driver linktab*/
+
+ /* statistics */
+
+ /* RSTA */
+
+ int stat_VFR; /* HSCX RSTA Valid FRame */
+ int stat_RDO; /* HSCX RSTA Rx Data Overflow */
+ int stat_CRC; /* HSCX RSTA CRC */
+ int stat_RAB; /* HSCX RSTA Rx message ABorted */
+
+ /* EXIR */
+
+ int stat_XDU; /* HSCX EXIR tx data underrun */
+ int stat_RFO; /* HSCX EXIR rx frame overflow */
+
+} l1_bchan_state_t;
+
+/*---------------------------------------------------------------------------*
+ * l1_softc: the state of the layer 1 of the D channel
+ *---------------------------------------------------------------------------*/
+struct l1_softc
+{
+#if !defined(__FreeBSD__)
+ /* We are inherited from this class. All drivers must have this
+ as their first entry in struct softc. */
+ struct device sc_dev;
+#endif
+
+ int sc_unit; /* unit number */
+ int sc_irq; /* interrupt vector */
+
+#ifdef __FreeBSD__
+ int sc_port; /* port base address */
+#elif defined(__bsdi__)
+ struct isadev sc_id; /* ISA/PCI device */
+ struct intrhand sc_ih; /* interrupt vectoring */
+ int sc_flags;
+ int sc_port;
+ caddr_t sc_maddr;
+ int sc_abustype; /* PCI, ISA etcetera */
+#else
+ u_int sc_maddr; /* "memory address" for card config register */
+ int sc_num_mappings; /* number of io mappings provided */
+ struct isic_io_map *sc_maps;
+
+#define MALLOC_MAPS(sc) \
+ (sc)->sc_maps = (struct isic_io_map*)malloc(sizeof((sc)->sc_maps[0])*(sc)->sc_num_mappings, M_DEVBUF, 0)
+#endif
+
+ int sc_cardtyp; /* CARD_TYPEP_xxxx */
+
+ int sc_bustyp; /* IOM1 or IOM2 */
+#define BUS_TYPE_IOM1 0x01
+#define BUS_TYPE_IOM2 0x02
+
+ int sc_trace; /* output protocol data for tracing */
+ unsigned int sc_trace_dcount;/* d channel trace frame counter */
+ unsigned int sc_trace_bcount;/* b channel trace frame counter */
+
+ int sc_state; /* ISAC state flag */
+#define ISAC_IDLE 0x00 /* state = idle */
+#define ISAC_TX_ACTIVE 0x01 /* state = transmitter active */
+
+ int sc_init_tries; /* no of out tries to access S0 */
+
+#if defined(__FreeBSD__) || defined(__bsdi__)
+ caddr_t sc_vmem_addr; /* card RAM virtual memory base */
+ caddr_t sc_isac; /* ISAC port base addr */
+#define ISAC_BASE (sc->sc_isac)
+
+ caddr_t sc_ipacbase; /* IPAC port base addr */
+#define IPAC_BASE (sc->sc_ipacbase)
+#endif
+
+ u_char sc_isac_mask; /* ISAC IRQ mask */
+#define ISAC_IMASK (sc->sc_isac_mask)
+
+ l1_bchan_state_t sc_chan[2]; /* B-channel state */
+#define HSCX_A_BASE (sc->sc_chan[0].hscx)
+#define HSCX_A_IMASK (sc->sc_chan[0].hscx_mask)
+#define HSCX_B_BASE (sc->sc_chan[1].hscx)
+#define HSCX_B_IMASK (sc->sc_chan[1].hscx_mask)
+
+ struct mbuf *sc_ibuf; /* input buffer mgmt */
+ u_short sc_ilen;
+ u_char *sc_ib;
+ /* this is for the irq TX routine */
+ struct mbuf *sc_obuf; /* pointer to an mbuf with TX frame */
+ u_char *sc_op; /* ptr to next chunk of frame to tx */
+ int sc_ol; /* length of remaining frame to tx */
+ int sc_freeflag; /* m_freem mbuf if set */
+
+ struct mbuf *sc_obuf2; /* pointer to an mbuf with TX frame */
+ int sc_freeflag2; /* m_freem mbuf if set */
+
+ int sc_isac_version; /* version number of ISAC */
+ int sc_hscx_version; /* version number of HSCX */
+ int sc_ipac_version; /* version number of IPAC */
+
+ int sc_I430state; /* I.430 state F3 .... F8 */
+
+ int sc_I430T3; /* I.430 Timer T3 running */
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ struct callout_handle sc_T3_callout;
+#endif
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+ struct callout sc_T3_callout;
+#endif
+
+ int sc_I430T4; /* Timer T4 running */
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ struct callout_handle sc_T4_callout;
+#endif
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+ struct callout sc_T4_callout;
+#endif
+
+ /*
+ * byte fields for the AVM Fritz!Card PCI. These are packed into
+ * a u_int in the driver.
+ */
+ u_char avma1pp_cmd;
+ u_char avma1pp_txl;
+ u_char avma1pp_prot;
+
+ int sc_enabled; /* daemon is running */
+
+ int sc_ipac; /* flag, running on ipac */
+ int sc_bfifolen; /* length of b channel fifos */
+
+#if defined(__FreeBSD__) || defined(__bsdi__)
+
+ u_char (*readreg)(u_char *, u_int);
+ void (*writereg)(u_char *, u_int, u_int);
+ void (*readfifo)(void *, const void *, size_t);
+ void (*writefifo)(void *, const void *, size_t);
+ void (*clearirq)(void *);
+
+#define ISAC_READ(r) (*sc->readreg)(ISAC_BASE, (r))
+#define ISAC_WRITE(r,v) (*sc->writereg)(ISAC_BASE, (r), (v));
+#define ISAC_RDFIFO(b,s) (*sc->readfifo)((b), ISAC_BASE, (s))
+#define ISAC_WRFIFO(b,s) (*sc->writefifo)(ISAC_BASE, (b), (s))
+
+#define HSCX_READ(n,r) (*sc->readreg)(sc->sc_chan[(n)].hscx, (r))
+#define HSCX_WRITE(n,r,v) (*sc->writereg)(sc->sc_chan[(n)].hscx, (r), (v))
+#define HSCX_RDFIFO(n,b,s) (*sc->readfifo)((b), sc->sc_chan[(n)].hscx, (s))
+#define HSCX_WRFIFO(n,b,s) (*sc->writefifo)(sc->sc_chan[(n)].hscx, (b), (s))
+
+#define IPAC_READ(r) (*sc->readreg)(IPAC_BASE, (r))
+#define IPAC_WRITE(r,v) (*sc->writereg)(IPAC_BASE, (r), (v));
+
+#else /* ! __FreeBSD__ */
+
+#define ISIC_WHAT_ISAC 0
+#define ISIC_WHAT_HSCXA 1
+#define ISIC_WHAT_HSCXB 2
+#define ISIC_WHAT_IPAC 3
+
+ u_int8_t (*readreg) __P((struct l1_softc *sc, int what, bus_size_t offs));
+ void (*writereg) __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+ void (*readfifo) __P((struct l1_softc *sc, int what, void *buf, size_t size));
+ void (*writefifo) __P((struct l1_softc *sc, int what, const void *data, size_t size));
+ void (*clearirq) __P((struct l1_softc *sc));
+
+#define ISAC_READ(r) (*sc->readreg)(sc, ISIC_WHAT_ISAC, (r))
+#define ISAC_WRITE(r,v) (*sc->writereg)(sc, ISIC_WHAT_ISAC, (r), (v))
+#define ISAC_RDFIFO(b,s) (*sc->readfifo)(sc, ISIC_WHAT_ISAC, (b), (s))
+#define ISAC_WRFIFO(b,s) (*sc->writefifo)(sc, ISIC_WHAT_ISAC, (b), (s))
+
+#define HSCX_READ(n,r) (*sc->readreg)(sc, ISIC_WHAT_HSCXA+(n), (r))
+#define HSCX_WRITE(n,r,v) (*sc->writereg)(sc, ISIC_WHAT_HSCXA+(n), (r), (v))
+#define HSCX_RDFIFO(n,b,s) (*sc->readfifo)(sc, ISIC_WHAT_HSCXA+(n), (b), (s))
+#define HSCX_WRFIFO(n,b,s) (*sc->writefifo)(sc, ISIC_WHAT_HSCXA+(n), (b), (s))
+
+#define IPAC_READ(r) (*sc->readreg)(sc, ISIC_WHAT_IPAC, (r))
+#define IPAC_WRITE(r, v) (*sc->writereg)(sc, ISIC_WHAT_IPAC, (r), (v))
+
+#endif /* __FreeBSD__ */
+};
+
+/*---------------------------------------------------------------------------*
+ * possible I.430/ISAC states
+ *---------------------------------------------------------------------------*/
+enum I430states {
+ ST_F3, /* F3 Deactivated */
+ ST_F4, /* F4 Awaiting Signal */
+ ST_F5, /* F5 Identifying Input */
+ ST_F6, /* F6 Synchronized */
+ ST_F7, /* F7 Activated */
+ ST_F8, /* F8 Lost Framing */
+ ST_ILL, /* Illegal State */
+ N_STATES
+};
+
+/*---------------------------------------------------------------------------*
+ * possible I.430/ISAC events
+ *---------------------------------------------------------------------------*/
+enum I430events {
+ EV_PHAR, /* PH ACTIVATE REQUEST */
+ EV_T3, /* Timer 3 expired */
+ EV_INFO0, /* receiving INFO0 */
+ EV_RSY, /* receiving any signal */
+ EV_INFO2, /* receiving INFO2 */
+ EV_INFO48, /* receiving INFO4 pri 8/9 */
+ EV_INFO410, /* receiving INFO4 pri 10/11 */
+ EV_DR, /* Deactivate Request */
+ EV_PU, /* Power UP */
+ EV_DIS, /* Disconnected (only 2085) */
+ EV_EI, /* Error Indication */
+ EV_ILL, /* Illegal Event */
+ N_EVENTS
+};
+
+enum I430commands {
+ CMD_TIM, /* Timing */
+ CMD_RS, /* Reset */
+ CMD_AR8, /* Activation request pri 8 */
+ CMD_AR10, /* Activation request pri 10 */
+ CMD_DIU, /* Deactivate Indication Upstream */
+ CMD_ILL /* Illegal command */
+};
+
+#define N_COMMANDS CMD_ILL
+
+#ifdef __FreeBSD__
+
+extern struct l1_softc l1_sc[];
+
+extern void isic_recover(struct l1_softc *sc);
+extern int isic_realattach(struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_avma1 ( struct isa_device *dev );
+extern int isic_attach_fritzpcmcia ( struct isa_device *dev );
+extern int isic_attach_Cs0P ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_Dyn ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_s016 ( struct isa_device *dev );
+extern int isic_attach_s0163 ( struct isa_device *dev );
+extern int isic_attach_s0163P ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_s08 ( struct isa_device *dev );
+extern int isic_attach_usrtai ( struct isa_device *dev );
+extern int isic_attach_itkix1 ( struct isa_device *dev );
+extern int isic_attach_drnngo ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_sws ( struct isa_device *dev );
+extern int isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_avm_pnp(struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_siemens_isurf(struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_Eqs1pp(int unit, unsigned int iobase1, unsigned int iobase2);
+extern int isic_attach_asi(struct isa_device *dev, unsigned int iobase2);
+extern void isic_bchannel_setup (int unit, int hscx_channel, int bprot, int activate );
+extern int isic_hscx_fifo(l1_bchan_state_t *, struct l1_softc *);
+extern void isic_hscx_init ( struct l1_softc *sc, int hscx_channel, int activate );
+extern void isic_hscx_irq ( struct l1_softc *sc, u_char ista, int hscx_channel, u_char ex_irq );
+extern int isic_hscx_silence ( unsigned char *data, int len );
+extern void isic_hscx_cmd( struct l1_softc *sc, int h_chan, unsigned char cmd );
+extern void isic_hscx_waitxfw( struct l1_softc *sc, int h_chan );
+extern void isic_init_linktab ( struct l1_softc *sc );
+extern int isic_isac_init ( struct l1_softc *sc );
+extern void isic_isac_irq ( struct l1_softc *sc, int r );
+extern void isic_isac_l1_cmd ( struct l1_softc *sc, int command );
+extern void isic_next_state ( struct l1_softc *sc, int event );
+extern char *isic_printstate ( struct l1_softc *sc );
+extern int isic_probe_avma1 ( struct isa_device *dev );
+extern int isic_probe_avma1_pcmcia ( struct isa_device *dev );
+extern int isic_probe_avm_pnp ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_siemens_isurf ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_Cs0P ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_Dyn ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_s016 ( struct isa_device *dev );
+extern int isic_probe_s0163 ( struct isa_device *dev );
+extern int isic_probe_s0163P ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_s08 ( struct isa_device *dev );
+extern int isic_probe_usrtai ( struct isa_device *dev );
+extern int isic_probe_itkix1 ( struct isa_device *dev );
+extern int isic_probe_drnngo ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_sws ( struct isa_device *dev );
+extern int isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_asi(struct isa_device *dev, unsigned int iobase2);
+
+#elif defined(__bsdi__)
+
+extern struct l1_softc *l1_sc[];
+#define isic_find_sc(unit) (l1_sc[(unit)])
+
+#define ATTACHARGS struct device *, struct device *, struct isa_attach_args *
+#define MATCHARGS struct device *, struct cfdata *, struct isa_attach_args *
+extern int isa_isicmatch(MATCHARGS);
+extern int isa_isicattach(ATTACHARGS);
+extern int isicintr(void *);
+extern void isic_recover(struct l1_softc *sc);
+extern int isic_realattach(ATTACHARGS);
+extern int isic_attach_avma1(ATTACHARGS);
+extern int isic_attach_fritzpcmcia(ATTACHARGS);
+extern int isic_attach_Cs0P(ATTACHARGS);
+extern int isic_attach_Dyn(ATTACHARGS);
+extern int isic_attach_s016(ATTACHARGS);
+extern int isic_attach_s0163(ATTACHARGS);
+extern int isic_attach_s0163P(ATTACHARGS);
+extern int isic_attach_s08(ATTACHARGS);
+extern int isic_attach_usrtai(ATTACHARGS);
+extern int isic_attach_itkix1(ATTACHARGS);
+extern int isic_attach_drnngo(ATTACHARGS);
+extern int isic_attach_sws(ATTACHARGS);
+extern int isic_attach_Eqs1pi(ATTACHARGS);
+extern int isic_attach_Eqs1pp(ATTACHARGS);
+extern void isic_bchannel_setup(int unit, int hscx_channel, int bprot, int activate );
+extern void isic_hscx_init(struct l1_softc *sc, int hscx_channel, int activate );
+extern void isic_hscx_irq(struct l1_softc *sc, u_char ista, int hscx_channel, u_char ex_irq );
+extern int isic_hscx_silence(unsigned char *data, int len );
+extern void isic_hscx_cmd(struct l1_softc *sc, int h_chan, unsigned char cmd );
+extern void isic_hscx_waitxfw(struct l1_softc *sc, int h_chan );
+extern void isic_init_linktab(struct l1_softc *sc );
+extern int isic_isac_init(struct l1_softc *sc );
+extern void isic_isac_irq(struct l1_softc *sc, int r );
+extern void isic_isac_l1_cmd(struct l1_softc *sc, int command );
+extern void isic_next_state(struct l1_softc *sc, int event );
+extern char *isic_printstate(struct l1_softc *sc );
+extern int isic_probe_avma1(MATCHARGS);
+extern int isic_probe_avma1_pcmcia(MATCHARGS);
+extern int isic_probe_Cs0P(MATCHARGS);
+extern int isic_probe_Dyn(MATCHARGS);
+extern int isic_probe_s016(MATCHARGS);
+extern int isic_probe_s0163(MATCHARGS);
+extern int isic_probe_s0163P(MATCHARGS);
+extern int isic_probe_s08(MATCHARGS);
+extern int isic_probe_usrtai(MATCHARGS);
+extern int isic_probe_itkix1(MATCHARGS);
+extern int isic_probe_drnngo(MATCHARGS);
+extern int isic_probe_sws(MATCHARGS);
+extern int isic_probe_Eqs1pi(MATCHARGS);
+
+#undef MATCHARGS
+#undef ATTACHARGS
+#else /* not FreeBSD/__bsdi__ */
+
+extern void isic_recover __P((struct l1_softc *sc));
+extern int isicintr __P((void *));
+extern int isicprobe __P((struct isic_attach_args *ia));
+extern int isic_attach_avma1 __P((struct l1_softc *sc));
+extern int isic_attach_s016 __P((struct l1_softc *sc));
+extern int isic_attach_s0163 __P((struct l1_softc *sc));
+extern int isic_attach_s08 __P((struct l1_softc *sc));
+extern int isic_attach_usrtai __P((struct l1_softc *sc));
+extern int isic_attach_itkix1 __P((struct l1_softc *sc));
+extern void isic_bchannel_setup __P((int unit, int hscx_channel, int bprot, int activate));
+extern void isic_hscx_init __P((struct l1_softc *sc, int hscx_channel, int activate));
+extern void isic_hscx_irq __P((struct l1_softc *sc, u_char ista, int hscx_channel, u_char ex_irq));
+extern int isic_hscx_silence __P(( unsigned char *data, int len ));
+extern void isic_hscx_cmd __P(( struct l1_softc *sc, int h_chan, unsigned char cmd ));
+extern void isic_hscx_waitxfw __P(( struct l1_softc *sc, int h_chan ));
+extern void isic_init_linktab __P((struct l1_softc *sc));
+extern int isic_isac_init __P((struct l1_softc *sc));
+extern void isic_isac_irq __P((struct l1_softc *sc, int r));
+extern void isic_isac_l1_cmd __P((struct l1_softc *sc, int command));
+extern void isic_next_state __P((struct l1_softc *sc, int event));
+extern char * isic_printstate __P((struct l1_softc *sc));
+extern int isic_probe_avma1 __P((struct isic_attach_args *ia));
+extern int isic_probe_s016 __P((struct isic_attach_args *ia));
+extern int isic_probe_s0163 __P((struct isic_attach_args *ia));
+extern int isic_probe_s08 __P((struct isic_attach_args *ia));
+extern int isic_probe_usrtai __P((struct isic_attach_args *ia));
+extern int isic_probe_itkix1 __P((struct isic_attach_args *ia));
+
+extern struct l1_softc *l1_sc[];
+
+#define isic_find_sc(unit) (l1_sc[(unit)])
+
+#endif /* __FreeBSD__ */
+
+#endif /* I4B_L1_H_ */
diff --git a/sys/dev/ic/i4b_isicl1fsm.c b/sys/dev/ic/i4b_isicl1fsm.c
new file mode 100644
index 00000000000..ac5c2ffe9e5
--- /dev/null
+++ b/sys/dev/ic/i4b_isicl1fsm.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_l1fsm.c - isdn4bsd layer 1 I.430 state machine
+ * --------------------------------------------------
+ *
+ * $Id: i4b_isicl1fsm.c,v 1.1.1.1 2001/01/05 12:50:13 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:36:11 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#ifndef __bsdi__
+#include <machine/bus.h>
+#endif
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+
+static char *state_text[N_STATES] = {
+ "F3 Deactivated",
+ "F4 Awaiting Signal",
+ "F5 Identifying Input",
+ "F6 Synchronized",
+ "F7 Activated",
+ "F8 Lost Framing",
+ "Illegal State"
+};
+
+static char *event_text[N_EVENTS] = {
+ "EV_PHAR PH_ACT_REQ",
+ "EV_T3 Timer 3 expired",
+ "EV_INFO0 INFO0 received",
+ "EV_RSY Level Detected",
+ "EV_INFO2 INFO2 received",
+ "EV_INFO48 INFO4 received",
+ "EV_INFO410 INFO4 received",
+ "EV_DR Deactivate Req",
+ "EV_PU Power UP",
+ "EV_DIS Disconnected",
+ "EV_EI Error Ind",
+ "Illegal Event"
+};
+
+/* Function prototypes */
+
+static void timer3_expired (struct l1_softc *sc);
+static void T3_start (struct l1_softc *sc);
+static void T3_stop (struct l1_softc *sc);
+static void F_T3ex (struct l1_softc *sc);
+static void timer4_expired (struct l1_softc *sc);
+static void T4_start (struct l1_softc *sc);
+static void T4_stop (struct l1_softc *sc);
+static void F_AI8 (struct l1_softc *sc);
+static void F_AI10 (struct l1_softc *sc);
+static void F_I01 (struct l1_softc *sc);
+static void F_I02 (struct l1_softc *sc);
+static void F_I03 (struct l1_softc *sc);
+static void F_I2 (struct l1_softc *sc);
+static void F_ill (struct l1_softc *sc);
+static void F_NULL (struct l1_softc *sc);
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer3_expired(struct l1_softc *sc)
+{
+ if(sc->sc_I430T3)
+ {
+ NDBGL1(L1_T_ERR, "state = %s", isic_printstate(sc));
+ sc->sc_I430T3 = 0;
+
+ /* XXX try some recovery here XXX */
+
+ isic_recover(sc);
+
+ sc->sc_init_tries++; /* increment retry count */
+
+/*XXX*/ if(sc->sc_init_tries > 4)
+ {
+ int s = SPLI4B();
+
+ sc->sc_init_tries = 0;
+
+ if(sc->sc_obuf2 != NULL)
+ {
+ i4b_Dfreembuf(sc->sc_obuf2);
+ sc->sc_obuf2 = NULL;
+ }
+ if(sc->sc_obuf != NULL)
+ {
+ i4b_Dfreembuf(sc->sc_obuf);
+ sc->sc_obuf = NULL;
+ sc->sc_freeflag = 0;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ }
+
+ splx(s);
+
+ MPH_Status_Ind(sc->sc_unit, STI_NOL1ACC, 0);
+ }
+
+ isic_next_state(sc, EV_T3);
+ }
+ else
+ {
+ NDBGL1(L1_T_ERR, "expired without starting it ....");
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 start
+ *---------------------------------------------------------------------------*/
+static void
+T3_start(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
+ sc->sc_I430T3 = 1;
+
+ START_TIMER(sc->sc_T3_callout, timer3_expired, sc, 2*hz);
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 stop
+ *---------------------------------------------------------------------------*/
+static void
+T3_stop(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
+
+ sc->sc_init_tries = 0; /* init connect retry count */
+
+ if(sc->sc_I430T3)
+ {
+ sc->sc_I430T3 = 0;
+ STOP_TIMER(sc->sc_T3_callout, timer3_expired, sc);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_T3ex(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_T3ex executing");
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ PH_Deact_Ind(sc->sc_unit);
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer4_expired(struct l1_softc *sc)
+{
+ if(sc->sc_I430T4)
+ {
+ NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
+ sc->sc_I430T4 = 0;
+ MPH_Status_Ind(sc->sc_unit, STI_PDEACT, 0);
+ }
+ else
+ {
+ NDBGL1(L1_T_ERR, "expired without starting it ....");
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 start
+ *---------------------------------------------------------------------------*/
+static void
+T4_start(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
+ sc->sc_I430T4 = 1;
+
+ START_TIMER(sc->sc_T4_callout, timer4_expired, sc, hz);
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 stop
+ *---------------------------------------------------------------------------*/
+static void
+T4_stop(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
+
+ if(sc->sc_I430T4)
+ {
+ sc->sc_I430T4 = 0;
+ STOP_TIMER(sc->sc_T4_callout, timer4_expired, sc);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI8
+ *---------------------------------------------------------------------------*/
+static void
+F_AI8(struct l1_softc *sc)
+{
+ T4_stop(sc);
+
+ NDBGL1(L1_F_MSG, "FSM function F_AI8 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ PH_Act_Ind(sc->sc_unit);
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_8;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI10
+ *---------------------------------------------------------------------------*/
+static void
+F_AI10(struct l1_softc *sc)
+{
+ T4_stop(sc);
+
+ NDBGL1(L1_F_MSG, "FSM function F_AI10 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ PH_Act_Ind(sc->sc_unit);
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_10;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in states F3 .. F5
+ *---------------------------------------------------------------------------*/
+static void
+F_I01(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I01 executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F6
+ *---------------------------------------------------------------------------*/
+static void
+F_I02(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I02 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ PH_Deact_Ind(sc->sc_unit);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F7 or F8
+ *---------------------------------------------------------------------------*/
+static void
+F_I03(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I03 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ PH_Deact_Ind(sc->sc_unit);
+
+ T4_start(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: activate request
+ *---------------------------------------------------------------------------*/
+static void
+F_AR(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_AR executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO1_8;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_TE;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+
+ isic_isac_l1_cmd(sc, CMD_AR8);
+
+ T3_start(sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO2
+ *---------------------------------------------------------------------------*/
+static void
+F_I2(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I2 executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO2;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+
+}
+
+/*---------------------------------------------------------------------------*
+ * illegal state default action
+ *---------------------------------------------------------------------------*/
+static void
+F_ill(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_ERR, "FSM function F_ill executing");
+}
+
+/*---------------------------------------------------------------------------*
+ * No action
+ *---------------------------------------------------------------------------*/
+static void
+F_NULL(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_NULL executing");
+}
+
+
+/*---------------------------------------------------------------------------*
+ * layer 1 state transition table
+ *---------------------------------------------------------------------------*/
+struct isic_state_tab {
+ void (*func) (struct l1_softc *sc); /* function to execute */
+ int newstate; /* next state */
+} isic_state_tab[N_EVENTS][N_STATES] = {
+
+/* STATE: F3 F4 F5 F6 F7 F8 ILLEGAL STATE */
+/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/* EV_PHAR x*/ {{F_AR, ST_F4}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_ill, ST_ILL}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_T3 x*/ {{F_NULL, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_INFO0 */ {{F_I01, ST_F3}, {F_I01, ST_F4}, {F_I01, ST_F5}, {F_I02, ST_F3}, {F_I03, ST_F3}, {F_I03, ST_F3}, {F_ill, ST_ILL}},
+/* EV_RSY x*/ {{F_NULL, ST_F3}, {F_NULL, ST_F5}, {F_NULL, ST_F5}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_INFO2 */ {{F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_ill, ST_ILL}},
+/* EV_INFO48*/ {{F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_NULL, ST_F7}, {F_AI8, ST_F7}, {F_ill, ST_ILL}},
+/* EV_INFO41*/ {{F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_NULL, ST_F7}, {F_AI10, ST_F7}, {F_ill, ST_ILL}},
+/* EV_DR */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_PU */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_DIS */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}},
+/* EV_EI */ {{F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_ill, ST_ILL}},
+/* EV_ILL */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}
+};
+
+/*---------------------------------------------------------------------------*
+ * event handler
+ *---------------------------------------------------------------------------*/
+void
+isic_next_state(struct l1_softc *sc, int event)
+{
+ int currstate, newstate;
+
+ if(event >= N_EVENTS)
+ panic("i4b_l1fsm.c: event >= N_EVENTS\n");
+
+ currstate = sc->sc_I430state;
+
+ if(currstate >= N_STATES)
+ panic("i4b_l1fsm.c: currstate >= N_STATES\n");
+
+ newstate = isic_state_tab[event][currstate].newstate;
+
+ if(newstate >= N_STATES)
+ panic("i4b_l1fsm.c: newstate >= N_STATES\n");
+
+ NDBGL1(L1_F_MSG, "FSM event [%s]: [%s => %s]", event_text[event],
+ state_text[currstate],
+ state_text[newstate]);
+
+ (*isic_state_tab[event][currstate].func)(sc);
+
+ if(newstate == ST_ILL)
+ {
+ newstate = ST_F3;
+ NDBGL1(L1_F_ERR, "FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!",
+ state_text[currstate],
+ state_text[newstate],
+ event_text[event]);
+ }
+
+ sc->sc_I430state = newstate;
+}
+
+/*---------------------------------------------------------------------------*
+ * return pointer to current state description
+ *---------------------------------------------------------------------------*/
+char *
+isic_printstate(struct l1_softc *sc)
+{
+ return((char *) state_text[sc->sc_I430state]);
+}
+
diff --git a/sys/dev/isa/i4b_avm_a1.c b/sys/dev/isa/i4b_avm_a1.c
new file mode 100644
index 00000000000..9f080016160
--- /dev/null
+++ b/sys/dev/isa/i4b_avm_a1.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 1996 Andrew Gordon. All rights reserved.
+ *
+ * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_avm_a1.c - AVM A1/Fritz passive card driver for isdn4bsd
+ * ------------------------------------------------------------
+ *
+ * $Id: i4b_avm_a1.c,v 1.1.1.1 2001/01/05 12:50:15 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:37:22 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicisa.h"
+#ifdef ISICISA_AVM_A1
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <netisdn/i4b_global.h>
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#ifndef __FreeBSD__
+static u_int8_t avma1_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void avma1_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void avma1_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+static void avma1_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM A1 and AVM Fritz! Card special registers
+ *---------------------------------------------------------------------------*/
+
+#define AVM_CONF_REG 0x1800 /* base offset for config register */
+#define AVM_CONF_IRQ 0x1801 /* base offset for IRQ register */
+ /* config register write */
+#define AVM_CONF_WR_RESET 0x01 /* 1 = RESET ISAC and HSCX */
+#define AVM_CONF_WR_CCL 0x02 /* 1 = clear counter low nibble */
+#define AVM_CONF_WR_CCH 0x04 /* 1 = clear counter high nibble */
+#define AVM_CONF_WR_IRQEN 0x08 /* 1 = enable IRQ */
+#define AVM_CONF_WR_TEST 0x10 /* test bit */
+ /* config register read */
+#define AVM_CONF_RD_IIRQ 0x01 /* 0 = ISAC IRQ active */
+#define AVM_CONF_RD_HIRQ 0x02 /* 0 = HSCX IRQ active */
+#define AVM_CONF_RD_CIRQ 0x04 /* 0 = counter IRQ active */
+#define AVM_CONF_RD_ZER1 0x08 /* unused, always read 0 */
+#define AVM_CONF_RD_TEST 0x10 /* test bit read back */
+#define AVM_CONF_RD_ZER2 0x20 /* unused, always read 0 */
+
+/*---------------------------------------------------------------------------*
+ * AVM read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base - 0x3e0, (u_char *)buf, (u_int)len);
+}
+#else
+static void
+avma1_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+4].t;
+ bus_space_handle_t h = sc->sc_maps[what+4].h;
+ bus_space_read_multi_1(t, h, 0, buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base - 0x3e0, (u_char *)buf, (u_int)len);
+}
+#else
+static void
+avma1_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+4].t;
+ bus_space_handle_t h = sc->sc_maps[what+4].h;
+ bus_space_write_multi_1(t, h, 0, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+#else
+static void
+avma1_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_space_write_1(t, h, offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+avma1_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+#else
+static u_int8_t
+avma1_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ return bus_space_read_1(t, h, offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_avma1 - probe for AVM A1 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_avma1(struct isa_device *dev)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+ u_char savebyte;
+ u_char byte;
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for AVM A1/Fritz!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq)-1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for AVM A1/Fritz!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for AVM A1/Fritz!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x200:
+ case 0x240:
+ case 0x300:
+ case 0x340:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for AVM A1/Fritz!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_read_reg;
+ sc->writereg = avma1_write_reg;
+
+ sc->readfifo = avma1_read_fifo;
+ sc->writefifo = avma1_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_AVMA1;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t)dev->id_iobase + 0x1400 - 0x20;
+
+ HSCX_A_BASE = (caddr_t)dev->id_iobase + 0x400 - 0x20;
+ HSCX_B_BASE = (caddr_t)dev->id_iobase + 0xc00 - 0x20;
+
+ /*
+ * Read HSCX A/B VSTR.
+ * Expected value for AVM A1 is 0x04 or 0x05 and for the
+ * AVM Fritz!Card is 0x05 in the least significant bits.
+ */
+
+ if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) ||
+ (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
+ {
+ printf("isic%d: HSCX VSTR test failed for AVM A1/Fritz\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ /* AVM A1 or Fritz! control register bits: */
+ /* read write */
+ /* 0x01 hscx irq* RESET */
+ /* 0x02 isac irq* clear counter1 */
+ /* 0x04 counter irq* clear counter2 */
+ /* 0x08 always 0 irq enable */
+ /* 0x10 read test bit set test bit */
+ /* 0x20 always 0 unused */
+
+ /*
+ * XXX the following test may be destructive, to prevent the
+ * worst case, we save the byte first, and in case the test
+ * fails, we write back the saved byte .....
+ */
+
+ savebyte = inb(dev->id_iobase + AVM_CONF_REG);
+
+ /* write low to test bit */
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x00);
+
+ /* test bit and next higher and lower bit must be 0 */
+
+ if((byte = inb(dev->id_iobase + AVM_CONF_REG) & 0x38) != 0x00)
+ {
+ printf("isic%d: Error, probe-1 failed, 0x%02x should be 0x00 for AVM A1/Fritz!\n",
+ dev->id_unit, byte);
+ outb(dev->id_iobase + AVM_CONF_REG, savebyte);
+ return (0);
+ }
+
+ /* write high to test bit */
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x10);
+
+ /* test bit must be high, next higher and lower bit must be 0 */
+
+ if((byte = inb(dev->id_iobase + AVM_CONF_REG) & 0x38) != 0x10)
+ {
+ printf("isic%d: Error, probe-2 failed, 0x%02x should be 0x10 for AVM A1/Fritz!\n",
+ dev->id_unit, byte);
+ outb(dev->id_iobase + AVM_CONF_REG, savebyte);
+ return (0);
+ }
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_avma1(struct isic_attach_args *ia)
+{
+ u_int8_t savebyte, v1, v2;
+
+ /*
+ * Read HSCX A/B VSTR.
+ * Expected value for AVM A1 is 0x04 or 0x05 and for the
+ * AVM Fritz!Card is 0x05 in the least significant bits.
+ */
+
+ v1 = bus_space_read_1(ia->ia_maps[ISIC_WHAT_HSCXA+1].t, ia->ia_maps[ISIC_WHAT_HSCXA+1].h, H_VSTR) & 0x0f;
+ v2 = bus_space_read_1(ia->ia_maps[ISIC_WHAT_HSCXB+1].t, ia->ia_maps[ISIC_WHAT_HSCXB+1].h, H_VSTR) & 0x0f;
+ if (v1 != v2 || (v1 != 0x05 && v1 != 0x04))
+ return 0;
+
+ /* AVM A1 or Fritz! control register bits: */
+ /* read write */
+ /* 0x01 hscx irq* RESET */
+ /* 0x02 isac irq* clear counter1 */
+ /* 0x04 counter irq* clear counter2 */
+ /* 0x08 always 0 irq enable */
+ /* 0x10 read test bit set test bit */
+ /* 0x20 always 0 unused */
+
+ /*
+ * XXX the following test may be destructive, to prevent the
+ * worst case, we save the byte first, and in case the test
+ * fails, we write back the saved byte .....
+ */
+
+ savebyte = bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0);
+
+ /* write low to test bit */
+
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, 0);
+
+ /* test bit and next higher and lower bit must be 0 */
+
+ if((bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0) & 0x38) != 0x00)
+ {
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, savebyte);
+ return 0;
+ }
+
+ /* write high to test bit */
+
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, 0x10);
+
+ /* test bit must be high, next higher and lower bit must be 0 */
+
+ if((bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0) & 0x38) != 0x10)
+ {
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, savebyte);
+ return 0;
+ }
+
+ return (1);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_avma1 - attach AVM A1 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_avma1(struct isa_device *dev)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ /* reset the HSCX and ISAC chips */
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ outb(dev->id_iobase + AVM_CONF_REG, AVM_CONF_WR_RESET);
+ DELAY(SEC_DELAY / 10);
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ outb(dev->id_iobase + AVM_CONF_IRQ, (ffs(sc->sc_irq)) - 1);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ outb(dev->id_iobase + AVM_CONF_REG, AVM_CONF_WR_IRQEN |
+ AVM_CONF_WR_CCH | AVM_CONF_WR_CCL);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+
+#else
+
+int
+isic_attach_avma1(struct l1_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_read_reg;
+ sc->writereg = avma1_write_reg;
+
+ sc->readfifo = avma1_read_fifo;
+ sc->writefifo = avma1_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_AVMA1;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* reset the HSCX and ISAC chips */
+
+ bus_space_write_1(t, h, 0, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ bus_space_write_1(t, h, 0, AVM_CONF_WR_RESET);
+ DELAY(SEC_DELAY / 10);
+
+ bus_space_write_1(t, h, 0, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ bus_space_write_1(t, h, 1, sc->sc_irq);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ bus_space_write_1(t, h, 0, AVM_CONF_WR_IRQEN |
+ AVM_CONF_WR_CCH | AVM_CONF_WR_CCL);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+#endif
+
+#endif /* ISICISA_AVM_A1 */
diff --git a/sys/dev/isa/i4b_itk_ix1.c b/sys/dev/isa/i4b_itk_ix1.c
new file mode 100644
index 00000000000..11a78d737bb
--- /dev/null
+++ b/sys/dev/isa/i4b_itk_ix1.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 1998, 1999, 2001 Martin Husemann <martin@duskware.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_itk_ix1.c - ITK ix1 micro passive card driver for isdn4bsd
+ * --------------------------------------------------------------
+ *
+ * $Id: i4b_itk_ix1.c,v 1.1.1.1 2001/01/05 12:50:16 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 12:31:50 2001]
+ *
+ * mh - created
+ * mh - fixed FreeBSD problems reported by Kevin Sheehan
+ * mh - added probe routine
+ *
+ *---------------------------------------------------------------------------
+ *
+ * The ITK ix1 micro ISDN card is an ISA card with one region
+ * of four io ports mapped and a fixed irq all jumpered on the card.
+ * Access to the board is straight forward and simmilar to
+ * the ELSA and DYNALINK cards. If a PCI version of this card
+ * exists all we need is probably a pci-bus attachment, all
+ * this low level routines should work imediately.
+ *
+ * To reset the card:
+ * - write 0x01 to ITK_CONFIG
+ * - wait >= 10 ms
+ * - write 0x00 to ITK_CONFIG
+ *
+ * To read or write data:
+ * - write address to ITK_ALE port
+ * - read data from or write data to ITK_ISAC_DATA port or ITK_HSCX_DATA port
+ * The two HSCX channel registers are offset by HSCXA (0x00) and HSCXB (0x40).
+ *
+ * The probe routine was derived by trial and error from a representative
+ * sample of two cards ;-) The standard way (checking HSCX versions)
+ * was extended by reading a zero from a non existant HSCX register (register
+ * 0xff). Reading the config register gives varying results, so this doesn't
+ * seem to be used as an id register (like the Teles S0/16.3).
+ *
+ * If the probe fails for your card use "options ITK_PROBE_DEBUG" to get
+ * additional debug output.
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicisa.h"
+
+#ifdef ISICISA_ITKIX1
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_global.h>
+
+/* Register offsets */
+#define ITK_ISAC_DATA 0
+#define ITK_HSCX_DATA 1
+#define ITK_ALE 2
+#define ITK_CONFIG 3
+
+/* Size of IO range to allocate for this card */
+#define ITK_IO_SIZE 4
+
+/* Register offsets for the two HSCX channels */
+#define HSCXA 0
+#define HSCXB 0x40
+
+/*
+ * Local function prototypes
+ */
+#ifdef __FreeBSD__
+/* FreeBSD version */
+static void itkix1_read_fifo(void *buf, const void *base, size_t len);
+static void itkix1_write_fifo(void *base, const void *buf, size_t len);
+static void itkix1_write_reg(u_char *base, u_int offset, u_int v);
+static u_char itkix1_read_reg(u_char *base, u_int offset);
+#else
+/* NetBSD/OpenBSD version */
+static void itkix1_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size);
+static void itkix1_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size);
+static void itkix1_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data);
+static u_int8_t itkix1_read_reg(struct l1_softc *sc, int what, bus_size_t offs);
+#endif
+
+/*
+ * Probe for card
+ */
+#ifdef __FreeBSD__
+int
+isic_probe_itkix1(struct isa_device *dev)
+{
+ u_int8_t hd, hv1, hv2, saveale;
+ int ret;
+
+ /* save old value of this port, we're stomping over it */
+ saveale = inb(dev->id_iobase + ITK_ALE);
+
+ /* select invalid register */
+ outb(dev->id_iobase + ITK_ALE, 0xff);
+ /* get HSCX data for this non existent register */
+ hd = inb(dev->id_iobase + ITK_HSCX_DATA);
+ /* get HSCX version info */
+ outb(dev->id_iobase + ITK_ALE, HSCXA + H_VSTR);
+ hv1 = inb(dev->id_iobase + ITK_HSCX_DATA);
+ outb(dev->id_iobase + ITK_ALE, HSCXB + H_VSTR);
+ hv2 = inb(dev->id_iobase + ITK_HSCX_DATA);
+
+ /* succeed if version bits are OK and we got a zero from the
+ * non existent register. we found verison 0x05 and 0x04
+ * out there... */
+ ret = (hd == 0)
+ && (((hv1 & 0x0f) == 0x05) || ((hv1 & 0x0f) == 0x04))
+ && (((hv2 & 0x0f) == 0x05) || ((hv2 & 0x0f) == 0x04));
+
+ /* retstore save value if we fail (if we succeed the old value
+ * has no meaning) */
+ if (!ret)
+ outb(dev->id_iobase + ITK_ALE, saveale);
+
+#ifdef ITK_PROBE_DEBUG
+ printf("\nITK ix1 micro probe: hscx = 0x%02x, v1 = 0x%02x, v2 = 0x%02x, would have %s\n",
+ hd, hv1, hv2, ret ? "succeeded" : "failed");
+ return 1;
+#else
+ return ret;
+#endif
+}
+#else
+int
+isic_probe_itkix1(struct isic_attach_args *ia)
+{
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t hd, hv1, hv2, saveale;
+ int ret;
+
+ /* save old value of this port, we're stomping over it */
+ saveale = bus_space_read_1(t, h, ITK_ALE);
+
+ /* select invalid register */
+ bus_space_write_1(t, h, ITK_ALE, 0xff);
+ /* get HSCX data for this non existent register */
+ hd = bus_space_read_1(t, h, ITK_HSCX_DATA);
+ /* get HSCX version info */
+ bus_space_write_1(t, h, ITK_ALE, HSCXA + H_VSTR);
+ hv1 = bus_space_read_1(t, h, ITK_HSCX_DATA);
+ bus_space_write_1(t, h, ITK_ALE, HSCXB + H_VSTR);
+ hv2 = bus_space_read_1(t, h, ITK_HSCX_DATA);
+
+ ret = (hd == 0) && ((hv1 & 0x0f) == 0x05) && ((hv2 & 0x0f) == 0x05);
+ /* succeed if version bits are OK and we got a zero from the
+ * non existent register. we found verison 0x05 and 0x04
+ * out there... */
+ ret = (hd == 0)
+ && (((hv1 & 0x0f) == 0x05) || ((hv1 & 0x0f) == 0x04))
+ && (((hv2 & 0x0f) == 0x05) || ((hv2 & 0x0f) == 0x04));
+
+ /* retstore save value if we fail (if we succeed the old value
+ * has no meaning) */
+ if (!ret)
+ bus_space_write_1(t, h, ITK_ALE, saveale);
+
+#ifdef ITK_PROBE_DEBUG
+ printf("\nITK ix1 micro probe: hscx = 0x%02x, v1 = 0x%02x, v2 = 0x%02x, would have %s\n",
+ hd, hv1, hv2, ret ? "succeeded" : "failed");
+ return 1;
+#else
+ return ret;
+#endif
+}
+#endif
+
+/*
+ * Attach card
+ */
+#ifdef __FreeBSD__
+int
+isic_attach_itkix1(struct isa_device *dev)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+ u_int8_t hv1, hv2;
+
+ sc->sc_irq = dev->id_irq;
+
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = itkix1_read_reg;
+ sc->writereg = itkix1_write_reg;
+ sc->readfifo = itkix1_read_fifo;
+ sc->writefifo = itkix1_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_ITKIX1;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+ ISAC_BASE = (caddr_t) sc->sc_port;
+ HSCX_A_BASE = (caddr_t) sc->sc_port + 1;
+ HSCX_B_BASE = (caddr_t) sc->sc_port + 2;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1) or 0x04 (V2.0). */
+ hv1 = HSCX_READ(0, H_VSTR) & 0xf;
+ hv2 = HSCX_READ(1, H_VSTR) & 0xf;
+ if((hv1 != 0x05 && hv1 != 0x04) || (hv2 != 0x05 && hv2 != 0x04))
+ {
+ printf("isic%d: HSCX VSTR test failed for ITK ix1 micro\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ outb((dev->id_iobase)+ITK_CONFIG, 1);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase)+ITK_CONFIG, 0);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else
+
+int isic_attach_itkix1(struct l1_softc *sc)
+{
+ u_int8_t hv1, hv2;
+
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = itkix1_read_reg;
+ sc->writereg = itkix1_write_reg;
+ sc->readfifo = itkix1_read_fifo;
+ sc->writefifo = itkix1_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_ITKIX1;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1) or 0x04 (V2.0). */
+ hv1 = HSCX_READ(0, H_VSTR) & 0xf;
+ hv2 = HSCX_READ(2, H_VSTR) & 0xf;
+ if((hv1 != 0x05 && hv1 != 0x04) || (hv2 != 0x05 && hv2 != 0x04))
+ {
+ printf("%s: HSCX VSTR test failed for ITK ix1 micro\n",
+ sc->sc_dev.dv_xname);
+ printf("%s: HSC0: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
+ printf("%s: HSC1: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
+ return 0;
+ }
+
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 1);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 0);
+ DELAY(SEC_DELAY / 10);
+ return 1;
+}
+
+#endif
+
+#ifdef __FreeBSD__
+static void
+itkix1_read_fifo(void *buf, const void *base, size_t len)
+{
+ u_int port = (u_int)base & ~0x0003;
+ switch ((u_int)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, 0);
+ insb(port+ITK_ISAC_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA);
+ insb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB);
+ insb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ }
+}
+#else
+static void
+itkix1_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, 0);
+ bus_space_read_multi_1(t, h, ITK_ISAC_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA);
+ bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB);
+ bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static void
+itkix1_write_fifo(void *base, const void *buf, size_t len)
+{
+ u_int port = (u_int)base & ~0x0003;
+ switch ((u_int)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, 0);
+ outsb(port+ITK_ISAC_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA);
+ outsb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB);
+ outsb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ }
+}
+#else
+static void itkix1_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, 0);
+ bus_space_write_multi_1(t, h, ITK_ISAC_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA);
+ bus_space_write_multi_1(t, h, ITK_HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB);
+ bus_space_write_multi_1(t, h, ITK_HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static void
+itkix1_write_reg(u_char *base, u_int offset, u_int v)
+{
+ u_int port = (u_int)base & ~0x0003;
+ switch ((u_int)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, offset);
+ outb(port+ITK_ISAC_DATA, (u_char)v);
+ break;
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA+offset);
+ outb(port+ITK_HSCX_DATA, (u_char)v);
+ break;
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB+offset);
+ outb(port+ITK_HSCX_DATA, (u_char)v);
+ break;
+ }
+}
+#else
+static void itkix1_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, offs);
+ bus_space_write_1(t, h, ITK_ISAC_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA+offs);
+ bus_space_write_1(t, h, ITK_HSCX_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB+offs);
+ bus_space_write_1(t, h, ITK_HSCX_DATA, data);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static u_char
+itkix1_read_reg(u_char *base, u_int offset)
+{
+ u_int port = (u_int)base & ~0x0003;
+ switch ((u_int)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, offset);
+ return (inb(port+ITK_ISAC_DATA));
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA+offset);
+ return (inb(port+ITK_HSCX_DATA));
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB+offset);
+ return (inb(port+ITK_HSCX_DATA));
+ }
+}
+#else
+static u_int8_t itkix1_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, offs);
+ return bus_space_read_1(t, h, ITK_ISAC_DATA);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA+offs);
+ return bus_space_read_1(t, h, ITK_HSCX_DATA);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB+offs);
+ return bus_space_read_1(t, h, ITK_HSCX_DATA);
+ }
+ return 0;
+}
+#endif
+
+#endif /* ISICISA_ITKIX1 */
diff --git a/sys/dev/isa/i4b_tel_s016.c b/sys/dev/isa/i4b_tel_s016.c
new file mode 100644
index 00000000000..fe510c726fe
--- /dev/null
+++ b/sys/dev/isa/i4b_tel_s016.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16 and clones
+ * =================================================================
+ *
+ * $Id: i4b_tel_s016.c,v 1.1.1.1 2001/01/05 12:50:16 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:37:22 2001]
+ *
+ * -hm clean up
+ * -hm checked with a Creatix ISDN-S0 (PCB version: mp 130.1)
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ * -hm converting asm -> C
+ *
+ *---------------------------------------------------------------------------*/
+
+
+#include "opt_isicisa.h"
+#ifdef ISICISA_TEL_S0_16
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <machine/md_var.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 };
+
+#ifndef __FreeBSD__
+static u_int8_t tels016_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void tels016_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels016_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+static void tels016_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 write register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels016_write_reg(u_char *base, u_int i, u_int v)
+{
+ if(i & 0x01)
+ i |= 0x200;
+ base[i] = v;
+}
+
+#else
+
+static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
+
+static void
+tels016_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+
+ offs += offset[what];
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ bus_space_write_1(t, h, offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 read register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels016_read_reg(u_char *base, u_int i)
+{
+ if(i & 0x1)
+ i |= 0x200;
+ return(base[i]);
+}
+
+#else
+
+static u_int8_t
+tels016_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+
+ offs += offset[what];
+
+ if(offs & 0x01)
+ offs |= 0x200;
+
+ return bus_space_read_1(t, h, offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 fifo read/write routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels016_memcpyb(void *to, const void *from, size_t len)
+{
+ for(;len > 0; len--)
+ *((unsigned char *)to)++ = *((unsigned char *)from)++;
+}
+
+#else
+
+static void
+tels016_write_fifo(struct l1_softc *sc, int what, const void *data, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ bus_space_write_region_1(t, h, offset[what], data, size);
+}
+
+static void
+tels016_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ bus_space_read_region_1(t, h, offset[what], buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s016 - probe for Teles S0/16 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_s016(struct isa_device *dev)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+ u_char byte;
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ if((intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0xd80:
+ case 0xe80:
+ case 0xf80:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* check if valid memory addr */
+
+ switch((unsigned int)kvtop(dev->id_maddr))
+ {
+ case 0xc0000:
+ case 0xc2000:
+ case 0xc4000:
+ case 0xc6000:
+ case 0xc8000:
+ case 0xca000:
+ case 0xcc000:
+ case 0xce000:
+ case 0xd0000:
+ case 0xd2000:
+ case 0xd4000:
+ case 0xd6000:
+ case 0xd8000:
+ case 0xda000:
+ case 0xdc000:
+ case 0xde000:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid mem addr 0x%lx for Teles S0/16!\n",
+ dev->id_unit, kvtop(dev->id_maddr));
+ return(0);
+ break;
+ }
+ sc->sc_vmem_addr = (caddr_t) dev->id_maddr;
+ dev->id_msize = 0x1000;
+
+ /* check card signature */
+
+ if((byte = inb(sc->sc_port)) != 0x51)
+ {
+ printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ if((byte = inb(sc->sc_port + 1)) != 0x93)
+ {
+ printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ byte = inb(sc->sc_port + 2);
+
+ if((byte != 0x1e) && (byte != 0x1f))
+ {
+ printf("isic%d: Error, signature 3 0x%x != 0x1e or 0x1f for Teles S0/16!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels016_read_reg;
+ sc->writereg = tels016_write_reg;
+
+ sc->readfifo = tels016_memcpyb;
+ sc->writefifo = tels016_memcpyb;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC base addr */
+
+ ISAC_BASE = (caddr_t) ((dev->id_maddr) + 0x100);
+
+ /* setup HSCX base addr */
+
+ HSCX_A_BASE = (caddr_t) ((dev->id_maddr) + 0x180);
+ HSCX_B_BASE = (caddr_t) ((dev->id_maddr) + 0x1c0);
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_s016(struct isic_attach_args *ia)
+{
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t b0, b1, b2;
+
+ b0 = bus_space_read_1(t, h, 0);
+ b1 = bus_space_read_1(t, h, 1);
+ b2 = bus_space_read_1(t, h, 2);
+
+ if (b0 == 0x51 && b1 == 0x93 && (b2 == 0x1e || b2 == 0x1f))
+ return 1;
+
+ return 0;
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s016 - attach Teles S0/16 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+#ifdef __FreeBSD__
+isic_attach_s016(struct isa_device *dev)
+#else
+isic_attach_s016(struct l1_softc *sc)
+#endif
+{
+
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+#endif
+
+ u_long irq;
+
+#ifndef __FreeBSD__
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels016_read_reg;
+ sc->writereg = tels016_write_reg;
+
+ sc->readfifo = tels016_read_fifo;
+ sc->writefifo = tels016_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+#endif
+
+#ifdef __FreeBSD__
+ if((irq = intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Attach error, invalid IRQ [%d] specified for Teles S0/16!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+#else
+ irq = intr_no[sc->sc_irq];
+#endif
+
+ /* configure IRQ */
+
+#ifdef __FreeBSD__
+ irq |= ((u_long) sc->sc_vmem_addr) >> 9;
+
+ DELAY(SEC_DELAY / 10);
+ outb(sc->sc_port + 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ outb(sc->sc_port + 4, irq | 0x01);
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit off */
+
+ sc->sc_vmem_addr[0x80] = 0;
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit on */
+
+ sc->sc_vmem_addr[0x80] = 1;
+ DELAY(SEC_DELAY / 5);
+
+#else
+
+ irq |= ((sc->sc_maddr >> 9) & 0x000000f0);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 4, irq | 0x01);
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit off */
+
+ bus_space_write_1(sc->sc_maps[1].t, sc->sc_maps[1].h, 0x80, 0);
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit on */
+
+ bus_space_write_1(sc->sc_maps[1].t, sc->sc_maps[1].h, 0x80, 1);
+ DELAY(SEC_DELAY / 5);
+#endif
+
+ return (1);
+}
+
+#endif /* ISICISA_TEL_S0_16 */
+
diff --git a/sys/dev/isa/i4b_tel_s0163.c b/sys/dev/isa/i4b_tel_s0163.c
new file mode 100644
index 00000000000..2f0eddda56a
--- /dev/null
+++ b/sys/dev/isa/i4b_tel_s0163.c
@@ -0,0 +1,602 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16.3
+ * ========================================================
+ *
+ * $Id: i4b_tel_s0163.c,v 1.1.1.1 2001/01/05 12:50:14 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:37:22 2001]
+ *
+ * -hm clean up
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ * -hm VSTR detection for older 16.3 cards
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicisa.h"
+#ifdef ISICISA_TEL_S0_16_3
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#elif defined(__bsdi__)
+ /* XXX */
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 };
+
+#if !defined(__FreeBSD__) && !defined(__bsdi__)
+static u_int8_t tels0163_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void tels0163_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels0163_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+static void tels0163_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 read fifo routine
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__) || defined(__bsdi__)
+
+static void
+tels0163_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_read_multi_1(t, h, o + 0x1e, buf, size);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 write fifo routine
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__) || defined(__bsdi__)
+
+static void
+tels0163_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_multi_1(t, h, o + 0x1e, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__) || defined(__bsdi__)
+
+static void
+tels0163_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+
+#else
+
+static void
+tels0163_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_1(t, h, o + offs - 0x20, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__) || defined(__bsdi__)
+
+static u_char
+tels0163_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+
+#else
+
+static u_int8_t
+tels0163_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ return bus_space_read_1(t, h, o + offs - 0x20);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s0163 - probe for Teles S0/16.3 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_s0163(struct isa_device *dev)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+ u_char byte;
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ if((intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0xd80:
+ case 0xe80:
+ case 0xf80:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ if(((byte = inb(sc->sc_port)) != 0x51) && (byte != 0x10))
+ {
+ printf("isic%d: Error, signature 1 0x%x != 0x51 or 0x10 for Teles S0/16.3!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ if((byte = inb(sc->sc_port + 1)) != 0x93)
+ {
+ printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ if(((byte = inb(sc->sc_port + 2)) != 0x1c) && (byte != 0x1f))
+ {
+ printf("isic%d: Error, signature 3 0x%x != (0x1c||0x1f) for Teles S0/16.3!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163_read_reg;
+ sc->writereg = tels0163_write_reg;
+
+ sc->readfifo = tels0163_read_fifo;
+ sc->writefifo = tels0163_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16_3;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ switch(dev->id_iobase)
+ {
+ case 0xd80:
+ ISAC_BASE = (caddr_t) 0x960;
+ HSCX_A_BASE = (caddr_t) 0x160;
+ HSCX_B_BASE = (caddr_t) 0x560;
+ break;
+
+ case 0xe80:
+ ISAC_BASE = (caddr_t) 0xa60;
+ HSCX_A_BASE = (caddr_t) 0x260;
+ HSCX_B_BASE = (caddr_t) 0x660;
+ break;
+
+ case 0xf80:
+ ISAC_BASE = (caddr_t) 0xb60;
+ HSCX_A_BASE = (caddr_t) 0x360;
+ HSCX_B_BASE = (caddr_t) 0x760;
+ break;
+ }
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the S0/16.3 card is
+ * 0x05 or 0x04 (for older 16.3's) in the least significant bits.
+ */
+
+ if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) ||
+ (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Teles S0/16.3\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+#elif defined(__bsdi__)
+
+static int
+set_softc(struct l1_softc *sc, struct isa_attach_args *ia, int unit)
+{
+ sc->sc_irq = ia->ia_irq;
+
+ /* check if we got an iobase */
+
+ switch(ia->ia_iobase)
+ {
+ case 0xd80:
+ case 0xe80:
+ case 0xf80:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!\n",
+ unit, ia->ia_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = ia->ia_iobase;
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163_read_reg;
+ sc->writereg = tels0163_write_reg;
+
+ sc->readfifo = tels0163_read_fifo;
+ sc->writefifo = tels0163_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16_3;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ switch(ia->ia_iobase)
+ {
+ case 0xd80:
+ ISAC_BASE = (caddr_t) 0x960;
+ HSCX_A_BASE = (caddr_t) 0x160;
+ HSCX_B_BASE = (caddr_t) 0x560;
+ break;
+
+ case 0xe80:
+ ISAC_BASE = (caddr_t) 0xa60;
+ HSCX_A_BASE = (caddr_t) 0x260;
+ HSCX_B_BASE = (caddr_t) 0x660;
+ break;
+
+ case 0xf80:
+ ISAC_BASE = (caddr_t) 0xb60;
+ HSCX_A_BASE = (caddr_t) 0x360;
+ HSCX_B_BASE = (caddr_t) 0x760;
+ break;
+ }
+ return 1;
+}
+
+int
+isic_probe_s0163(struct device *dev, struct cfdata *cf,
+ struct isa_attach_args *ia)
+{
+ u_char byte;
+ struct l1_softc dummysc, *sc = &dummysc;
+
+ if((intr_no[ffs(ia->ia_irq) - 1]) == 1)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
+ cf->cf_unit, ffs(ia->ia_irq)-1);
+ return(0);
+ }
+
+ /* check if memory addr specified */
+
+ if(ia->ia_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!\n",
+ cf->cf_unit, (u_long)ia->ia_maddr);
+ return 0;
+ }
+
+ /* Set up a temporary softc for the probe */
+
+ if (set_softc(sc, ia, cf->cf_unit) == 0)
+ return 0;
+
+ if((byte = inb(sc->sc_port)) != 0x51)
+ {
+ printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16.3!\n",
+ cf->cf_unit, byte);
+ return(0);
+ }
+
+ if((byte = inb(sc->sc_port + 1)) != 0x93)
+ {
+ printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!\n",
+ cf->cf_unit, byte);
+ return(0);
+ }
+
+ if(((byte = inb(sc->sc_port + 2)) != 0x1c) && (byte != 0x1f))
+ {
+ printf("isic%d: Error, signature 3 0x%x != (0x1c||0x1f) for Teles S0/16.3!\n",
+ cf->cf_unit, byte);
+ return(0);
+ }
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the S0/16.3 card is
+ * 0x05 or 0x04 (for older 16.3's) in the least significant bits.
+ */
+
+ if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) ||
+ (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Teles S0/16.3\n",
+ cf->cf_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ cf->cf_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ cf->cf_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+
+#else
+
+int
+isic_probe_s0163(struct isic_attach_args *ia)
+{
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t b0, b1, b2;
+
+ b0 = bus_space_read_1(t, h, 0);
+ b1 = bus_space_read_1(t, h, 1);
+ b2 = bus_space_read_1(t, h, 2);
+
+ if (b0 == 0x51 && b1 == 0x93 && (b2 == 0x1c || b2 == 0x1f))
+ return 1;
+
+ return 0;
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163 - attach Teles S0/16.3 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_s0163(struct isa_device *dev)
+{
+ u_char irq;
+
+ if((irq = intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Attach error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+
+ /* configure IRQ */
+
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + 4, irq | 0x01);
+
+ return (1);
+}
+
+#elif defined(__bsdi__)
+
+extern int
+isic_attach_s0163(struct device *parent, struct device *self, struct isa_attach_args *ia)
+{
+ u_char irq;
+ struct l1_softc *sc = (struct l1_softc *)self;
+ int unit = sc->sc_dev.dv_unit;
+
+ /* Commit the probed attachement values */
+
+ if (set_softc(sc, ia, unit) == 0)
+ panic("isic_attach_s0163: set_softc");
+
+ if (((unsigned)sc->sc_unit) >= NISIC)
+ panic("attach isic%d; NISIC=%d", sc->sc_unit, NISIC);
+ l1_sc[sc->sc_unit] = sc;
+ irq = intr_no[ffs(sc->sc_irq) - 1];
+ /* configure IRQ */
+
+ DELAY(SEC_DELAY / 10);
+ outb(sc->sc_port + 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ outb(sc->sc_port + 4, irq | 0x01);
+
+ return 1;
+}
+#else
+
+int
+isic_attach_s0163(struct l1_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ u_int8_t irq = intr_no[sc->sc_irq];
+
+ /* configure IRQ */
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 4, irq | 0x01);
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163_read_reg;
+ sc->writereg = tels0163_write_reg;
+
+ sc->readfifo = tels0163_read_fifo;
+ sc->writefifo = tels0163_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16_3;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ return (1);
+}
+#endif
+
+#endif /* ISICISA_TEL_S0_16_3 */
+
diff --git a/sys/dev/isa/i4b_tel_s08.c b/sys/dev/isa/i4b_tel_s08.c
new file mode 100644
index 00000000000..28839b03934
--- /dev/null
+++ b/sys/dev/isa/i4b_tel_s08.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0/8 and clones
+ * ================================================================
+ *
+ * $Id: i4b_tel_s08.c,v 1.1.1.1 2001/01/05 12:50:16 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:37:22 2001]
+ *
+ * -hm clean up
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ * -hm making it finally work (checked with board revision 1.2)
+ * -hm converting asm -> C
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicisa.h"
+#ifdef ISICISA_TEL_S0_8
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <machine/md_var.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t tels08_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void tels08_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels08_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+static void tels08_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 write register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels08_write_reg(u_char *base, u_int i, u_int v)
+{
+ if(i & 0x01)
+ i |= 0x200;
+ base[i] = v;
+}
+
+#else
+
+static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
+
+static void
+tels08_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+
+ offs += offset[what];
+
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ bus_space_write_1(t, h, offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 read register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels08_read_reg(u_char *base, u_int i)
+{
+ if(i & 0x1)
+ i |= 0x200;
+ return(base[i]);
+}
+
+#else
+
+static u_int8_t
+tels08_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+
+ offs += offset[what];
+
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ return bus_space_read_1(t, h, offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 fifo read/write access
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels08_memcpyb(void *to, const void *from, size_t len)
+{
+ for(;len > 0; len--)
+ *((unsigned char *)to)++ = *((unsigned char *)from)++;
+}
+
+#else
+
+static void
+tels08_write_fifo(struct l1_softc *sc, int what, const void *data, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_region_1(t, h, offset[what], data, size);
+}
+
+static void
+tels08_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_read_region_1(t, h, offset[what], buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s08 - probe for Teles S0/8 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+int
+isic_probe_s08(struct isa_device *dev)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/8!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq)-1)
+ {
+ case 2:
+ case 9: /* XXX */
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/8!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if we got an iobase */
+
+ if(dev->id_iobase > 0)
+ {
+ printf("isic%d: Error, iobase specified for Teles S0/8!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ /* check if inside memory range of 0xA0000 .. 0xDF000 */
+
+ if( (kvtop(dev->id_maddr) < 0xa0000) ||
+ (kvtop(dev->id_maddr) > 0xdf000) )
+ {
+ printf("isic%d: Error, mem addr 0x%lx outside 0xA0000-0xDF000 for Teles S0/8!\n",
+ dev->id_unit, kvtop(dev->id_maddr));
+ return(0);
+ }
+
+ sc->sc_vmem_addr = (caddr_t) dev->id_maddr;
+ dev->id_msize = 0x1000;
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels08_read_reg;
+ sc->writereg = tels08_write_reg;
+
+ sc->readfifo = tels08_memcpyb;
+ sc->writefifo = tels08_memcpyb;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_8;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC base addr */
+
+ ISAC_BASE = (caddr_t)((dev->id_maddr) + 0x100);
+
+ /* setup HSCX base addr */
+
+ HSCX_A_BASE = (caddr_t)((dev->id_maddr) + 0x180);
+ HSCX_B_BASE = (caddr_t)((dev->id_maddr) + 0x1c0);
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_s08(struct isic_attach_args *ia)
+{
+ /* no real sensible probe is easy - write to fifo memory
+ and read back to verify there is memory doesn't work,
+ because you talk to tx fifo and rcv fifo. So, just check
+ HSCX version, which at least fails if no card present
+ at the given location. */
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t v1, v2;
+
+ /* HSCX A VSTR */
+ v1 = bus_space_read_1(t, h, offset[1] + H_VSTR) & 0x0f;
+ if (v1 != HSCX_VA1 && v1 != HSCX_VA2 && v1 != HSCX_VA3 && v1 != HSCX_V21)
+ return 0;
+
+ /* HSCX B VSTR */
+ v2 = bus_space_read_1(t, h, offset[2] + H_VSTR) & 0x0f;
+ if (v2 != HSCX_VA1 && v2 != HSCX_VA2 && v2 != HSCX_VA3 && v2 != HSCX_V21)
+ return 0;
+
+ /* both HSCX channels should have the same version... */
+ if (v1 != v2)
+ return 0;
+
+ return 1;
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s08 - attach Teles S0/8 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+#ifdef __FreeBSD__
+isic_attach_s08(struct isa_device *dev)
+#else
+isic_attach_s08(struct l1_softc *sc)
+#endif
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+#else
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+#endif
+
+ /* set card off */
+
+#ifdef __FreeBSD__
+ sc->sc_vmem_addr[0x80] = 0;
+#else
+ bus_space_write_1(t, h, 0x80, 0);
+#endif
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card on */
+
+#ifdef __FreeBSD__
+ sc->sc_vmem_addr[0x80] = 1;
+#else
+ bus_space_write_1(t, h, 0x80, 1);
+#endif
+
+ DELAY(SEC_DELAY / 5);
+
+#ifndef __FreeBSD__
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels08_read_reg;
+ sc->writereg = tels08_write_reg;
+ sc->readfifo = tels08_read_fifo;
+ sc->writefifo = tels08_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_8;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+#endif
+
+ return (1);
+}
+
+#endif /* ISICISA_TEL_S0_8 */
+
diff --git a/sys/dev/isa/i4b_usr_sti.c b/sys/dev/isa/i4b_usr_sti.c
new file mode 100644
index 00000000000..460a81f4986
--- /dev/null
+++ b/sys/dev/isa/i4b_usr_sti.c
@@ -0,0 +1,439 @@
+/*
+ * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_usr_sti.c - USRobotics Sportster ISDN TA intern (Tina-pp)
+ * -------------------------------------------------------------
+ *
+ * $Id: i4b_usr_sti.c,v 1.1.1.1 2001/01/05 12:50:14 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:37:22 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicisa.h"
+#ifdef ISICISA_USR_STI
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_global.h>
+
+/*---------------------------------------------------------------------------*
+ * USR Sportster TA intern special registers
+ *---------------------------------------------------------------------------*/
+#define USR_HSCXA_OFF 0x0000
+#define USR_HSCXB_OFF 0x4000
+#define USR_INTL_OFF 0x8000
+#define USR_ISAC_OFF 0xc000
+
+#define USR_RES_BIT 0x80 /* 0 = normal, 1 = reset ISAC/HSCX */
+#define USR_INTE_BIT 0x40 /* 0 = IRQ disabled, 1 = IRQ's enabled */
+#define USR_IL_MASK 0x07 /* IRQ level config */
+
+static u_char intr_no[] = { 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 3, 4, 5, 0, 6, 7 };
+
+#ifdef __FreeBSD__
+
+#define ADDR(reg) \
+ (((reg/4) * 1024) + ((reg%4) * 2))
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_read_fifo(void *buf, const void *base, size_t len)
+{
+ register int offset = 0;
+
+ for(;len > 0; len--, offset++)
+ *((u_char *)buf + offset) = inb((int)base + ADDR(offset));
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_fifo(void *base, const void *buf, size_t len)
+{
+ register int offset = 0;
+
+ for(;len > 0; len--, offset++)
+ outb((int)base + ADDR(offset), *((u_char *)buf + offset));
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write register routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + ADDR(offset), (u_char)v);
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read register routine
+ *---------------------------------------------------------------------------*/
+static u_char
+usrtai_read_reg(u_char *base, u_int offset)
+{
+ return(inb((int)base + ADDR(offset)));
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_usrtai - probe for USR
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_usrtai(struct isa_device *dev)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= MAXUNIT for USR Sportster TA!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ if((intr_no[ffs(dev->id_irq) - 1]) == 0)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n",
+ dev->id_unit, (ffs(dev->id_irq))-1);
+ return(0);
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for USR Sportster TA!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x200:
+ case 0x208:
+ case 0x210:
+ case 0x218:
+ case 0x220:
+ case 0x228:
+ case 0x230:
+ case 0x238:
+ case 0x240:
+ case 0x248:
+ case 0x250:
+ case 0x258:
+ case 0x260:
+ case 0x268:
+ case 0x270:
+ case 0x278:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for USR Sportster TA!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = usrtai_read_reg;
+ sc->writereg = usrtai_write_reg;
+
+ sc->readfifo = usrtai_read_fifo;
+ sc->writefifo = usrtai_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_USRTA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t)dev->id_iobase + USR_ISAC_OFF;
+ HSCX_A_BASE = (caddr_t)dev->id_iobase + USR_HSCXA_OFF;
+ HSCX_B_BASE = (caddr_t)dev->id_iobase + USR_HSCXB_OFF;
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for USR Sportster TA based
+ * boards is 0x05 in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for USR Sportster TA\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_usrtai - attach USR
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_usrtai(struct isa_device *dev)
+{
+ u_char irq = 0;
+
+ /* reset the HSCX and ISAC chips */
+
+ outb(dev->id_iobase + USR_INTL_OFF, USR_RES_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ outb(dev->id_iobase + USR_INTL_OFF, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ if((irq = intr_no[ffs(dev->id_irq) - 1]) == 0)
+ {
+ printf("isic%d: Attach error, invalid IRQ [%d] specified for USR Sportster TA!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+
+ /* configure and enable irq */
+
+ outb(dev->id_iobase + USR_INTL_OFF, irq | USR_INTE_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+
+#else /* end of FreeBSD, start NetBSD */
+
+/*
+ * Use of sc->sc_maps:
+ * 0 : config register
+ * 1 - 16 : HSCX A registers
+ * 17 - 32 : HSCX B registers
+ * 33 - 48 : ISAC registers
+ */
+
+#define USR_REG_OFFS(reg) ((reg % 4) * 2)
+#define USR_HSCXA_MAP(reg) ((reg / 4) + 1)
+#define USR_HSCXB_MAP(reg) ((reg / 4) + 17)
+#define USR_ISAC_MAP(reg) ((reg / 4) + 33)
+
+static int map_base[] = { 33, 1, 17, 0 }; /* ISAC, HSCX A, HSCX B */
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ int map, off, offset;
+ u_char * p = buf;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ for (offset = 0; size > 0; size--, offset++) {
+ map = map_base[what] + (offset / 4);
+ t = sc->sc_maps[map].t;
+ h = sc->sc_maps[map].h;
+ off = USR_REG_OFFS(offset);
+
+ *p++ = bus_space_read_1(t, h, off);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ int map, off, offset;
+ const u_char * p = buf;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+ u_char v;
+
+ for (offset = 0; size > 0; size--, offset++) {
+ map = map_base[what] + (offset / 4);
+ t = sc->sc_maps[map].t;
+ h = sc->sc_maps[map].h;
+ off = USR_REG_OFFS(offset);
+
+ v = *p++;
+ bus_space_write_1(t, h, off, v);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write register routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ int map = map_base[what] + (offs / 4),
+ off = USR_REG_OFFS(offs);
+ bus_space_tag_t t = sc->sc_maps[map].t;
+ bus_space_handle_t h = sc->sc_maps[map].h;
+
+ bus_space_write_1(t, h, off, data);
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read register routine
+ *---------------------------------------------------------------------------*/
+static u_char
+usrtai_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ int map = map_base[what] + (offs / 4),
+ off = USR_REG_OFFS(offs);
+ bus_space_tag_t t = sc->sc_maps[map].t;
+ bus_space_handle_t h = sc->sc_maps[map].h;
+
+ return bus_space_read_1(t, h, off);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_usrtai - probe for USR
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_usrtai(struct isic_attach_args *ia)
+{
+ /*
+ * Read HSCX A/B VSTR. Expected value for IOM2 based
+ * boards is 0x05 in the least significant bits.
+ */
+
+ if(((bus_space_read_1(ia->ia_maps[USR_HSCXA_MAP(H_VSTR)].t, ia->ia_maps[USR_HSCXA_MAP(H_VSTR)].h, USR_REG_OFFS(H_VSTR)) & 0x0f) != 0x05) ||
+ ((bus_space_read_1(ia->ia_maps[USR_HSCXB_MAP(H_VSTR)].t, ia->ia_maps[USR_HSCXB_MAP(H_VSTR)].h, USR_REG_OFFS(H_VSTR)) & 0x0f) != 0x05))
+ return 0;
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_usrtai - attach USR
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_usrtai(struct l1_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ u_char irq = intr_no[sc->sc_irq];
+
+ sc->clearirq = NULL;
+ sc->readreg = usrtai_read_reg;
+ sc->writereg = usrtai_write_reg;
+
+ sc->readfifo = usrtai_read_fifo;
+ sc->writefifo = usrtai_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_USRTA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* reset the HSCX and ISAC chips */
+
+ bus_space_write_1(t, h, 0, USR_RES_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ bus_space_write_1(t, h, 0, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ bus_space_write_1(t, h, 0, irq | USR_INTE_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+
+#endif /* __FreeBSD__ */
+
+#endif /* ISICISA_USR_STI */
diff --git a/sys/dev/isa/isa_isic.c b/sys/dev/isa/isa_isic.c
new file mode 100644
index 00000000000..6ea94543674
--- /dev/null
+++ b/sys/dev/isa/isa_isic.c
@@ -0,0 +1,1299 @@
+/*
+ * Copyright (c) 1997-1999 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isa_isic.c - ISA bus frontend for i4b_isic driver
+ * --------------------------------------------------
+ *
+ * $Id: isa_isic.c,v 1.1.1.1 2001/01/05 12:50:14 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:37:22 2001]
+ *
+ * -mh original implementation
+ * -hm NetBSD patches from Martin
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/isa/isavar.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include "opt_isicisa.h"
+
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#include <netisdn/i4b_trace.h>
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_ipac.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+#include <netisdn/i4b_global.h>
+
+#if defined(__OpenBSD__)
+#define __BROKEN_INDIRECT_CONFIG
+#endif
+
+/* local functions */
+#ifdef __BROKEN_INDIRECT_CONFIG
+static int isa_isic_probe __P((struct device *, void *, void *));
+#else
+static int isa_isic_probe __P((struct device *, struct cfdata *, void *));
+#endif
+
+static void isa_isic_attach __P((struct device *, struct device *, void *));
+static int setup_io_map __P((int flags, bus_space_tag_t iot,
+ bus_space_tag_t memt, bus_size_t iobase, bus_size_t maddr,
+ int *num_mappings, struct isic_io_map *maps, int *iosize,
+ int *msize));
+static void args_unmap __P((int *num_mappings, struct isic_io_map *maps));
+
+struct cfattach isa_isic_ca = {
+ sizeof(struct l1_softc), isa_isic_probe, isa_isic_attach
+};
+
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+
+/*
+ * Probe card
+ */
+static int
+#ifdef __BROKEN_INDIRECT_CONFIG
+isa_isic_probe(parent, match, aux)
+#else
+isa_isic_probe(parent, cf, aux)
+#endif
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *cf;
+#endif
+ void *aux;
+{
+#ifdef __BROKEN_INDIRECT_CONFIG
+ struct cfdata *cf = ((struct device*)match)->dv_cfdata;
+#endif
+ struct isa_attach_args *ia = aux;
+ bus_space_tag_t memt = ia->ia_memt, iot = ia->ia_iot;
+ int flags = cf->cf_flags;
+ struct isic_attach_args args;
+ int ret = 0;
+
+#if 0
+ printf("isic%d: enter isa_isic_probe\n", cf->cf_unit);
+#endif
+
+ /* check irq */
+ if (ia->ia_irq == IRQUNK) {
+ printf("isic%d: config error: no IRQ specified\n", cf->cf_unit);
+ return 0;
+ }
+
+ /* setup MI attach args */
+ bzero(&args, sizeof(args));
+ args.ia_flags = flags;
+
+ /* if card type specified setup io map for that card */
+ switch(flags)
+ {
+ case FLAG_TELES_S0_8:
+ case FLAG_TELES_S0_16:
+ case FLAG_TELES_S0_163:
+ case FLAG_AVM_A1:
+ case FLAG_USR_ISDN_TA_INT:
+ case FLAG_ITK_IX1:
+ if (setup_io_map(flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &ia->ia_msize)) {
+ ret = 0;
+ goto done;
+ }
+ break;
+
+ default:
+ /* no io map now, will figure card type later */
+ break;
+ }
+
+ /* probe card */
+ switch(flags)
+ {
+#ifdef DYNALINK
+#ifdef __bsdi__
+ case FLAG_DYNALINK:
+ ret = isic_probe_Dyn(&args);
+ break;
+#endif
+#endif
+
+#ifdef ISICISA_TEL_S0_8
+ case FLAG_TELES_S0_8:
+ ret = isic_probe_s08(&args);
+ break;
+#endif
+
+#ifdef ISICISA_TEL_S0_16
+ case FLAG_TELES_S0_16:
+ ret = isic_probe_s016(&args);
+ break;
+#endif
+
+#ifdef ISICISA_TEL_S0_16_3
+ case FLAG_TELES_S0_163:
+ ret = isic_probe_s0163(&args);
+ break;
+#endif
+
+#ifdef ISICISA_AVM_A1
+ case FLAG_AVM_A1:
+ ret = isic_probe_avma1(&args);
+ break;
+#endif
+
+#ifdef ISICISA_USR_STI
+ case FLAG_USR_ISDN_TA_INT:
+ ret = isic_probe_usrtai(&args);
+ break;
+#endif
+
+#ifdef ISICISA_ITKIX1
+ case FLAG_ITK_IX1:
+ ret = isic_probe_itkix1(&args);
+ break;
+#endif
+
+ default:
+ /* No card type given, try to figure ... */
+ if (ia->ia_iobase == IOBASEUNK) {
+ ret = 0;
+#ifdef ISICISA_TEL_S0_8
+ /* only Teles S0/8 will work without IO */
+ args.ia_flags = FLAG_TELES_S0_8;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s08(&args);
+ }
+#endif /* ISICISA_TEL_S0_8 */
+ } else if (ia->ia_maddr == MADDRUNK) {
+ ret = 0;
+#ifdef ISICISA_TEL_S0_16_3
+ /* no shared memory, only a 16.3 based card,
+ AVM A1, the usr sportster or an ITK would work */
+ args.ia_flags = FLAG_TELES_S0_163;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ break;
+ }
+#endif /* ISICISA_TEL_S0_16_3 */
+#ifdef ISICISA_AVM_A1
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_AVM_A1;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ break;
+ }
+#endif /* AVM_A1 */
+#ifdef ISICISA_USR_STI
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_USR_ISDN_TA_INT;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_usrtai(&args);
+ if (ret)
+ break;
+ }
+#endif /* ISICISA_USR_STI */
+
+#ifdef ISICISA_ITKIX1
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_ITK_IX1;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_itkix1(&args);
+ if (ret)
+ break;
+ }
+#endif /* ISICISA_ITKIX1 */
+
+ } else {
+#ifdef ISICISA_TEL_S0_16_3
+ /* could be anything */
+ args.ia_flags = FLAG_TELES_S0_163;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ break;
+ }
+#endif /* ISICISA_TEL_S0_16_3 */
+#ifdef ISICISA_TEL_S0_16
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_TELES_S0_16;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s016(&args);
+ if (ret)
+ break;
+ }
+#endif /* ISICISA_TEL_S0_16 */
+#ifdef ISICISA_AVM_A1
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_AVM_A1;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ break;
+ }
+#endif /* ISICISA_AVM_A1 */
+#ifdef ISICISA_TEL_S0_8
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_TELES_S0_8;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s08(&args);
+ }
+#endif /* ISICISA_TEL_S0_8 */
+ }
+ break;
+ }
+
+done:
+ /* unmap resources */
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+
+#if 0
+ printf("isic%d: exit isa_isic_probe, return = %d\n", cf->cf_unit, ret);
+#endif
+
+ return ret;
+}
+
+static int
+isicattach(int flags, struct l1_softc *sc)
+{
+ int ret = 0;
+ char *drvid;
+
+#ifdef __FreeBSD__
+
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+#define PARM dev
+#define PARM2 dev, iobase2
+#define FLAGS dev->id_flags
+
+#elif defined(__bsdi__)
+
+ struct l1_softc *sc = (struct l1_softc *)self;
+#define PARM parent, self, ia
+#define PARM2 parent, self, ia
+#define FLAGS sc->sc_flags
+
+#else
+
+#define PARM sc
+#define PARM2 sc
+#define FLAGS flags
+
+#endif /* __FreeBSD__ */
+
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ /* done in bus specific attach code for other OS */
+
+#ifdef __FreeBSD__
+ if(dev->id_unit != next_isic_unit)
+ {
+/*XXX*/ printf("isicattach: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit);
+ return(0);
+ }
+
+ sc->sc_unit = dev->id_unit;
+#else
+ l1_sc[sc->sc_unit] = sc;
+#endif
+
+ /* card dependent setup */
+ switch(FLAGS)
+ {
+#ifdef DYNALINK
+#if defined(__bsdi__) || defined(__FreeBSD__)
+ case FLAG_DYNALINK:
+ ret = isic_attach_Dyn(PARM2);
+ break;
+#endif
+#endif
+
+#ifdef TEL_S0_8
+ case FLAG_TELES_S0_8:
+ ret = isic_attach_s08(PARM);
+ break;
+#endif
+
+#ifdef TEL_S0_16
+ case FLAG_TELES_S0_16:
+ ret = isic_attach_s016(PARM);
+ break;
+#endif
+
+#ifdef TEL_S0_16_3
+ case FLAG_TELES_S0_163:
+ ret = isic_attach_s0163(PARM);
+ break;
+#endif
+
+#ifdef AVM_A1
+ case FLAG_AVM_A1:
+ ret = isic_attach_avma1(PARM);
+ break;
+#endif
+
+#ifdef USR_STI
+ case FLAG_USR_ISDN_TA_INT:
+ ret = isic_attach_usrtai(PARM);
+ break;
+#endif
+
+#ifdef ITKIX1
+ case FLAG_ITK_IX1:
+ ret = isic_attach_itkix1(PARM);
+ break;
+#endif
+
+#ifdef ELSA_PCC16
+ case FLAG_ELSA_PCC16:
+ ret = isic_attach_Eqs1pi(dev, 0);
+ break;
+#endif
+
+#ifdef amiga
+ case FLAG_BLMASTER:
+ ret = 1; /* full detection was done in caller */
+ break;
+#endif
+
+/* ======================================================================
+ * Only P&P cards follow below!!!
+ */
+
+#ifdef __FreeBSD__ /* we've already splitted all non-ISA stuff
+ out of this ISA specific part for the other
+ OS */
+
+#ifdef AVM_A1_PCMCIA
+ case FLAG_AVM_A1_PCMCIA:
+ ret = isic_attach_fritzpcmcia(PARM);
+ break;
+#endif
+
+#ifdef TEL_S0_16_3_P
+ case FLAG_TELES_S0_163_PnP:
+ ret = isic_attach_s0163P(PARM2);
+ break;
+#endif
+
+#ifdef CRTX_S0_P
+ case FLAG_CREATIX_S0_PnP:
+ ret = isic_attach_Cs0P(PARM2);
+ break;
+#endif
+
+#ifdef DRN_NGO
+ case FLAG_DRN_NGO:
+ ret = isic_attach_drnngo(PARM2);
+ break;
+#endif
+
+#ifdef SEDLBAUER
+ case FLAG_SWS:
+ ret = isic_attach_sws(PARM);
+ break;
+#endif
+
+#ifdef ELSA_QS1ISA
+ case FLAG_ELSA_QS1P_ISA:
+ ret = isic_attach_Eqs1pi(PARM2);
+ break;
+#endif
+
+#ifdef AVM_PNP
+ case FLAG_AVM_PNP:
+ ret = isic_attach_avm_pnp(PARM2);
+ ret = 0;
+ break;
+#endif
+
+#ifdef SIEMENS_ISURF2
+ case FLAG_SIEMENS_ISURF2:
+ ret = isic_attach_siemens_isurf(PARM2);
+ break;
+#endif
+
+#ifdef ASUSCOM_IPAC
+ case FLAG_ASUSCOM_IPAC:
+ ret = isic_attach_asi(PARM2);
+ break;
+#endif
+
+#endif /* __FreeBSD__ / P&P specific part */
+
+ default:
+ break;
+ }
+
+ if(ret == 0)
+ return(0);
+
+ if(sc->sc_ipac)
+ {
+ sc->sc_ipac_version = IPAC_READ(IPAC_ID);
+
+ switch(sc->sc_ipac_version)
+ {
+ case IPAC_V11:
+ case IPAC_V12:
+ break;
+
+ default:
+ printf("isic%d: Error, IPAC version %d unknown!\n",
+ sc->sc_unit, ret);
+ return(0);
+ break;
+ }
+ }
+ else
+ {
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return(0);
+ break;
+ }
+ }
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ callout_handle_init(&sc->sc_T3_callout);
+ callout_handle_init(&sc->sc_T4_callout);
+#endif
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+ callout_init(&sc->sc_T3_callout);
+ callout_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce manufacturer and card type */
+
+ switch(FLAGS)
+ {
+ case FLAG_TELES_S0_8:
+ drvid = "Teles S0/8 or Niccy 1008";
+ break;
+
+ case FLAG_TELES_S0_16:
+ drvid = "Teles S0/16, Creatix ISDN S0-16 or Niccy 1016";
+ break;
+
+ case FLAG_TELES_S0_163:
+ drvid = "Teles S0/16.3";
+ break;
+
+ case FLAG_AVM_A1:
+ drvid = "AVM A1 or AVM Fritz!Card";
+ break;
+
+ case FLAG_AVM_A1_PCMCIA:
+ drvid = "AVM PCMCIA Fritz!Card";
+ break;
+
+ case FLAG_TELES_S0_163_PnP:
+ drvid = "Teles S0/PnP";
+ break;
+
+ case FLAG_CREATIX_S0_PnP:
+ drvid = "Creatix ISDN S0-16 P&P";
+ break;
+
+ case FLAG_USR_ISDN_TA_INT:
+ drvid = "USRobotics Sportster ISDN TA intern";
+ break;
+
+ case FLAG_DRN_NGO:
+ drvid = "Dr. Neuhaus NICCY Go@";
+ break;
+
+ case FLAG_DYNALINK:
+ drvid = "Dynalink IS64PH";
+ break;
+
+ case FLAG_SWS:
+ drvid = "Sedlbauer WinSpeed";
+ break;
+
+ case FLAG_BLMASTER:
+ /* board announcement was done by caller */
+ drvid = (char *)0;
+ break;
+
+ case FLAG_ELSA_QS1P_ISA:
+ drvid = "ELSA QuickStep 1000pro (ISA)";
+ break;
+
+ case FLAG_ITK_IX1:
+ drvid = "ITK ix1 micro";
+ break;
+
+ case FLAG_ELSA_PCC16:
+ drvid = "ELSA PCC-16";
+ break;
+
+ case FLAG_ASUSCOM_IPAC:
+ drvid = "Asuscom ISDNlink 128K PnP";
+ break;
+
+ case FLAG_SIEMENS_ISURF2:
+ drvid = "Siemens I-Surf 2.0";
+ break;
+
+ default:
+ drvid = "ERROR, unknown flag used";
+ break;
+ }
+#ifndef __FreeBSD__
+ printf("\n");
+#endif
+ if (drvid)
+ printf(ISIC_FMT "%s\n", ISIC_PARM, drvid);
+
+ /* announce chip versions */
+
+ if(sc->sc_ipac)
+ {
+ if(sc->sc_ipac_version == IPAC_V11)
+ printf(ISIC_FMT "IPAC PSB2115 Version 1.1\n", ISIC_PARM);
+ else
+ printf(ISIC_FMT "IPAC PSB2115 Version 1.2\n", ISIC_PARM);
+ }
+ else
+ {
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+#ifdef __FreeBSD__
+ printf("(Addr=0x%lx)\n", (u_long)ISAC_BASE);
+#endif
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+
+#ifdef __FreeBSD__
+ printf("(AddrA=0x%lx, AddrB=0x%lx)\n", (u_long)HSCX_A_BASE, (u_long)HSCX_B_BASE);
+
+#endif /* __FreeBSD__ */
+ }
+
+#ifdef __FreeBSD__
+ next_isic_unit++;
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300003
+
+ /* set the interrupt handler - no need to change isa_device.h */
+ dev->id_intr = (inthand2_t *)isicintr;
+
+#endif
+
+#endif /* __FreeBSD__ */
+
+ return(1);
+#undef PARM
+#undef FLAGS
+}
+
+/*
+ * Attach the card
+ */
+static void
+isa_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct l1_softc *sc = (void *)self;
+ struct isa_attach_args *ia = aux;
+ int flags = sc->sc_dev.dv_cfdata->cf_flags;
+ int ret = 0;
+ struct isic_attach_args args;
+
+ /* Setup parameters */
+ sc->sc_unit = sc->sc_dev.dv_unit;
+ sc->sc_irq = ia->ia_irq;
+ sc->sc_maddr = ia->ia_maddr;
+ sc->sc_num_mappings = 0;
+ sc->sc_maps = NULL;
+ switch(flags)
+ {
+ case FLAG_TELES_S0_8:
+ case FLAG_TELES_S0_16:
+ case FLAG_TELES_S0_163:
+ case FLAG_AVM_A1:
+ case FLAG_USR_ISDN_TA_INT:
+ setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &(sc->sc_num_mappings), NULL, NULL, NULL);
+ MALLOC_MAPS(sc);
+ setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &(sc->sc_num_mappings), &(sc->sc_maps[0]), NULL, NULL);
+ break;
+
+ default:
+ /* No card type given, try to figure ... */
+
+ /* setup MI attach args */
+ bzero(&args, sizeof(args));
+ args.ia_flags = flags;
+
+ /* Probe cards */
+ if (ia->ia_iobase == IOBASEUNK) {
+ ret = 0;
+#ifdef ISICISA_TEL_S0_8
+ /* only Teles S0/8 will work without IO */
+ args.ia_flags = FLAG_TELES_S0_8;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s08(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ISICISA_TEL_S0_8 */
+ } else if (ia->ia_maddr == MADDRUNK) {
+ /* no shared memory, only a 16.3 based card,
+ AVM A1, the usr sportster or an ITK would work */
+ ret = 0;
+#ifdef ISICISA_TEL_S0_16_3
+ args.ia_flags = FLAG_TELES_S0_163;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ISICISA_TEL_S0_16_3 */
+#ifdef ISICISA_AVM_A1
+ args.ia_flags = FLAG_AVM_A1;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ISICISA_AVM_A1 */
+#ifdef ISICISA_USR_STI
+ args.ia_flags = FLAG_USR_ISDN_TA_INT;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_usrtai(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ISICISA_USR_STI */
+#ifdef ISICISA_ITKIX1
+ args.ia_flags = FLAG_ITK_IX1;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_itkix1(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ISICISA_ITKIX1 */
+ } else {
+ /* could be anything */
+ ret = 0;
+#ifdef ISICISA_TEL_S0_16_3
+ args.ia_flags = FLAG_TELES_S0_163;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ISICISA_TEL_S0_16_3 */
+#ifdef ISICISA_TEL_S0_16
+ args.ia_flags = FLAG_TELES_S0_16;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s016(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ISICISA_TEL_S0_16 */
+#ifdef ISICISA_AVM_A1
+ args.ia_flags = FLAG_AVM_A1;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ISICISA_AVM_A1 */
+#ifdef ISICISA_TEL_S0_8
+ args.ia_flags = FLAG_TELES_S0_8;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s08(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ISICISA_TEL_S0_8 */
+ }
+ break;
+
+ found:
+ flags = args.ia_flags;
+ sc->sc_num_mappings = args.ia_num_mappings;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ if (ret) {
+ MALLOC_MAPS(sc);
+ setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &(sc->sc_num_mappings), &(sc->sc_maps[0]), NULL, NULL);
+ } else {
+ printf(": could not determine card type - not configured!\n");
+ return;
+ }
+ break;
+ }
+
+#if defined(__OpenBSD__)
+ isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, isicintr, sc, sc->sc_dev.dv_xname);
+
+ /* MI initialization of card */
+ isicattach(flags, sc);
+
+#else
+
+ /* MI initialization of card */
+ isicattach(flags, sc);
+
+ /*
+ * Try to get a level-triggered interrupt first. If that doesn't
+ * work (like on NetBSD/Atari, try to establish an edge triggered
+ * interrupt.
+ */
+ if (isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_LEVEL,
+ IPL_NET, isicintr, sc) == NULL) {
+ if(isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, isicintr, sc) == NULL) {
+ args_unmap(&(sc->sc_num_mappings), &(sc->sc_maps[0]));
+ free((sc)->sc_maps, M_DEVBUF);
+ }
+ else {
+ /*
+ * XXX: This is a hack that probably needs to be
+ * solved by setting an interrupt type in the sc
+ * structure. I don't feel familiar enough with the
+ * code to do this currently. Feel free to contact
+ * me about it (leo@netbsd.org).
+ */
+ isicintr(sc);
+ }
+ }
+#endif
+}
+
+/*
+ * Setup card specific io mapping. Return 0 on success,
+ * any other value on config error.
+ * Be prepared to get NULL as maps array.
+ * Make sure to keep *num_mappings in sync with the real
+ * mappings already setup when returning!
+ */
+static int
+setup_io_map(flags, iot, memt, iobase, maddr, num_mappings, maps, iosize, msize)
+ int flags, *num_mappings, *iosize, *msize;
+ bus_size_t iobase, maddr;
+ bus_space_tag_t iot, memt;
+ struct isic_io_map *maps;
+{
+ /* nothing mapped yet */
+ *num_mappings = 0;
+
+ /* which resources do we need? */
+ switch(flags)
+ {
+ case FLAG_TELES_S0_8:
+ if (maddr == MADDRUNK) {
+ printf("isic: config error: no shared memory specified for Teles S0/8!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 0; /* no i/o ports */
+ if (msize) *msize = 0x1000; /* shared memory size */
+
+ /* this card uses a single memory mapping */
+ if (maps == NULL) {
+ *num_mappings = 1;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = memt;
+ maps[0].offset = 0;
+ maps[0].size = 0x1000;
+ if (bus_space_map(maps[0].t, maddr,
+ maps[0].size, 0, &maps[0].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ break;
+
+ case FLAG_TELES_S0_16:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no i/o address specified for Teles S0/16!\n");
+ return 1;
+ }
+ if (maddr == MADDRUNK) {
+ printf("isic: config error: no shared memory specified for Teles S0/16!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* i/o ports */
+ if (msize) *msize = 0x1000; /* shared memory size */
+
+ /* one io and one memory mapping */
+ if (maps == NULL) {
+ *num_mappings = 2;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ maps[0].size = 8;
+ if (bus_space_map(maps[0].t, iobase,
+ maps[0].size, 0, &maps[0].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[1].t = memt;
+ maps[1].offset = 0;
+ maps[1].size = 0x1000;
+ if (bus_space_map(maps[1].t, maddr,
+ maps[1].size, 0, &maps[1].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ break;
+
+ case FLAG_TELES_S0_163:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no i/o address specified for Teles S0/16!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* only some i/o ports shown */
+ if (msize) *msize = 0; /* no shared memory */
+
+ /* Four io mappings: config, isac, 2 * hscx */
+ if (maps == NULL) {
+ *num_mappings = 4;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ maps[0].size = 8;
+ if (bus_space_map(maps[0].t, iobase,
+ maps[0].size, 0, &maps[0].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[1].t = iot;
+ maps[1].offset = 0;
+ maps[1].size = 0x40; /* XXX - ??? */
+ if ((iobase - 0xd80 + 0x980) < 0 || (iobase - 0xd80 + 0x980) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[1].t, iobase - 0xd80 + 0x980,
+ maps[1].size, 0, &maps[1].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[2].t = iot;
+ maps[2].offset = 0;
+ maps[2].size = 0x40; /* XXX - ??? */
+ if ((iobase - 0xd80 + 0x180) < 0 || (iobase - 0xd80 + 0x180) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[2].t, iobase - 0xd80 + 0x180,
+ maps[2].size, 0, &maps[2].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[3].t = iot;
+ maps[3].offset = 0;
+ maps[3].size = 0x40; /* XXX - ??? */
+ if ((iobase - 0xd80 + 0x580) < 0 || (iobase - 0xd80 + 0x580) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[3].t, iobase - 0xd80 + 0x580,
+ maps[3].size, 0, &maps[3].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ break;
+
+ case FLAG_AVM_A1:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no i/o address specified for AVM A1/Fritz! card!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* only some i/o ports shown */
+ if (msize) *msize = 0; /* no shared memory */
+
+ /* Seven io mappings: config, isac, 2 * hscx,
+ isac-fifo, 2 * hscx-fifo */
+ if (maps == NULL) {
+ *num_mappings = 7;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = iot; /* config */
+ maps[0].offset = 0;
+ maps[0].size = 8;
+ if ((iobase + 0x1800) < 0 || (iobase + 0x1800) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[0].t, iobase + 0x1800, maps[0].size, 0, &maps[0].h))
+ return 1;
+ (*num_mappings)++;
+ maps[1].t = iot; /* isac */
+ maps[1].offset = 0;
+ maps[1].size = 0x80; /* XXX - ??? */
+ if ((iobase + 0x1400 - 0x20) < 0 || (iobase + 0x1400 - 0x20) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[1].t, iobase + 0x1400 - 0x20, maps[1].size, 0, &maps[1].h))
+ return 1;
+ (*num_mappings)++;
+ maps[2].t = iot; /* hscx 0 */
+ maps[2].offset = 0;
+ maps[2].size = 0x40; /* XXX - ??? */
+ if ((iobase + 0x400 - 0x20) < 0 || (iobase + 0x400 - 0x20) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[2].t, iobase + 0x400 - 0x20, maps[2].size, 0, &maps[2].h))
+ return 1;
+ (*num_mappings)++;
+ maps[3].t = iot; /* hscx 1 */
+ maps[3].offset = 0;
+ maps[3].size = 0x40; /* XXX - ??? */
+ if ((iobase + 0xc00 - 0x20) < 0 || (iobase + 0xc00 - 0x20) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[3].t, iobase + 0xc00 - 0x20, maps[3].size, 0, &maps[3].h))
+ return 1;
+ (*num_mappings)++;
+ maps[4].t = iot; /* isac-fifo */
+ maps[4].offset = 0;
+ maps[4].size = 1;
+ if ((iobase + 0x1400 - 0x20 -0x3e0) < 0 || (iobase + 0x1400 - 0x20 -0x3e0) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[4].t, iobase + 0x1400 - 0x20 -0x3e0, maps[4].size, 0, &maps[4].h))
+ return 1;
+ (*num_mappings)++;
+ maps[5].t = iot; /* hscx 0 fifo */
+ maps[5].offset = 0;
+ maps[5].size = 1;
+ if ((iobase + 0x400 - 0x20 -0x3e0) < 0 || (iobase + 0x400 - 0x20 -0x3e0) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[5].t, iobase + 0x400 - 0x20 -0x3e0, maps[5].size, 0, &maps[5].h))
+ return 1;
+ (*num_mappings)++;
+ maps[6].t = iot; /* hscx 1 fifo */
+ maps[6].offset = 0;
+ maps[6].size = 1;
+ if ((iobase + 0xc00 - 0x20 -0x3e0) < 0 || (iobase + 0xc00 - 0x20 -0x3e0) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[6].t, iobase + 0xc00 - 0x20 -0x3e0, maps[6].size, 0, &maps[6].h))
+ return 1;
+ (*num_mappings)++;
+ break;
+
+ case FLAG_USR_ISDN_TA_INT:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no I/O base specified for USR Sportster TA intern!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* scattered ports, only some shown */
+ if (msize) *msize = 0; /* no shared memory */
+
+ /* 49 io mappings: 1 config and 48x8 registers */
+ if (maps == NULL) {
+ *num_mappings = 49;
+ return 0;
+ }
+ *num_mappings = 0;
+ {
+ int i, num;
+ bus_size_t base;
+
+ /* config at offset 0x8000 */
+ base = iobase + 0x8000;
+ maps[0].size = 1;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ if (base < 0 || base > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base, 1, 0, &maps[0].h)) {
+ return 1;
+ }
+ *num_mappings = num = 1;
+
+ /* HSCX A at offset 0 */
+ base = iobase;
+ for (i = 0; i < 16; i++) {
+ maps[num].size = 8;
+ maps[num].offset = 0;
+ maps[num].t = iot;
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
+ return 1;
+ }
+ *num_mappings = ++num;
+ }
+ /* HSCX B at offset 0x4000 */
+ base = iobase + 0x4000;
+ for (i = 0; i < 16; i++) {
+ maps[num].size = 8;
+ maps[num].offset = 0;
+ maps[num].t = iot;
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
+ return 1;
+ }
+ *num_mappings = ++num;
+ }
+ /* ISAC at offset 0xc000 */
+ base = iobase + 0xc000;
+ for (i = 0; i < 16; i++) {
+ maps[num].size = 8;
+ maps[num].offset = 0;
+ maps[num].t = iot;
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
+ return 1;
+ }
+ *num_mappings = ++num;
+ }
+ }
+ break;
+
+ case FLAG_ITK_IX1:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no I/O base specified for ITK ix1 micro!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 4;
+ if (msize) *msize = 0;
+ if (maps == NULL) {
+ *num_mappings = 1;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].size = 4;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ if (bus_space_map(iot, iobase, 4, 0, &maps[0].h)) {
+ return 1;
+ }
+ *num_mappings = 1;
+ break;
+
+ default:
+ printf("isic: config error: flags do not specify any known card!\n");
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+static void
+args_unmap(num_mappings, maps)
+ int *num_mappings;
+ struct isic_io_map *maps;
+{
+ int i, n;
+ for (i = 0, n = *num_mappings; i < n; i++)
+ if (maps[i].size)
+ bus_space_unmap(maps[i].t, maps[i].h, maps[i].size);
+ *num_mappings = 0;
+}
diff --git a/sys/dev/isa/isadaic.c b/sys/dev/isa/isadaic.c
new file mode 100644
index 00000000000..86b79ab2d89
--- /dev/null
+++ b/sys/dev/isa/isadaic.c
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 1997, 2001 Martin Husemann <martin@duskware.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <sys/socket.h>
+#include <net/if.h>
+#include <dev/isa/isavar.h>
+#include <netisdn/i4b_ioctl.h>
+#include <netisdn/i4b_l3l4.h>
+#include <dev/ic/daicvar.h>
+
+/* driver state */
+struct isa_daic_softc {
+ struct daic sc_daic; /* MI driver state */
+ void *sc_ih; /* interrupt handler */
+};
+
+/* local functions */
+#ifdef __BROKEN_INDIRECT_CONFIG
+static int isa_daic_probe __P((struct device *, void *, void *));
+#else
+static int isa_daic_probe __P((struct device *, struct cfdata *, void *));
+#endif
+static void isa_daic_attach __P((struct device *, struct device *, void *));
+static int isa_daic_intr __P((void *));
+
+struct cfattach isa_daic_ca = {
+ sizeof(struct isa_daic_softc), isa_daic_probe, isa_daic_attach
+};
+
+static int
+#ifdef __BROKEN_INDIRECT_CONFIG
+isa_daic_probe(parent, match, aux)
+#else
+isa_daic_probe(parent, cf, aux)
+#endif
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *cf;
+#endif
+ void *aux;
+{
+ struct isa_attach_args *ia = aux;
+ bus_space_tag_t memt = ia->ia_memt;
+ bus_space_handle_t memh;
+ int card;
+
+ /* We need some controller memory to comunicate! */
+ if (ia->ia_maddr == MADDRUNK || ia->ia_msize == -1)
+ goto bad;
+
+ /* Map card RAM. */
+ ia->ia_msize = DAIC_ISA_MEMSIZE;
+ ia->ia_iosize = 0;
+ if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize,
+ 0, &memh))
+ goto bad;
+
+ /* MI check for card at this location */
+ card = daic_probe(memt, memh);
+ if (card < 0)
+ goto bad;
+ if (card == DAIC_TYPE_QUAD)
+ ia->ia_msize = DAIC_ISA_QUADSIZE;
+
+ bus_space_unmap(memt, memh, DAIC_ISA_MEMSIZE);
+ return 1;
+
+bad:
+ /* unmap card RAM */
+ bus_space_unmap(memt, memh, DAIC_ISA_MEMSIZE);
+ return 0;
+}
+
+static void
+isa_daic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct isa_daic_softc *sc = (void *)self;
+ struct isa_attach_args *ia = aux;
+ bus_space_tag_t memt = ia->ia_memt;
+ bus_space_handle_t memh;
+
+ /* Map card RAM. */
+ if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize,
+ 0, &memh))
+ return;
+
+ sc->sc_daic.sc_iot = memt;
+ sc->sc_daic.sc_ioh = memh;
+
+ /* MI initialization of card */
+ daic_attach(self, &sc->sc_daic);
+
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, isa_daic_intr, sc);
+}
+
+/*
+ * Controller interrupt.
+ */
+static int
+isa_daic_intr(arg)
+ void *arg;
+{
+ struct isa_daic_softc *sc = arg;
+ return daic_intr(&sc->sc_daic);
+}
diff --git a/sys/dev/isapnp/i4b_ctx_s0P.c b/sys/dev/isapnp/i4b_ctx_s0P.c
new file mode 100644
index 00000000000..710541b9a67
--- /dev/null
+++ b/sys/dev/isapnp/i4b_ctx_s0P.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Creatix PnP cards
+ * ============================================================
+ *
+ * $Id: i4b_ctx_s0P.c,v 1.1.1.1 2001/01/05 12:50:18 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:29 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicpnp.h"
+#if ISICPNP_CRTX_S0_P
+
+#include <sys/param.h>
+
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <netisdn/i4b_global.h>
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t ctxs0P_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void ctxs0P_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void ctxs0P_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+static void ctxs0P_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+void isic_attach_Cs0P(struct l1_softc *sc);
+#endif
+
+#ifdef __FreeBSD__
+#include <i386/isa/pnp.h>
+extern void isicintr ( int unit );
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+ctxs0P_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+ctxs0P_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_read_multi_1(t, h, o + 0x3e, buf, size);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+ctxs0P_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+ctxs0P_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_multi_1(t, h, o + 0x3e, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+ctxs0P_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+
+#else
+
+static void
+ctxs0P_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_1(t, h, o + offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+ctxs0P_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+
+#else
+
+static u_int8_t
+ctxs0P_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ return bus_space_read_1(t, h, o + offs);
+}
+
+#endif
+
+#ifdef __FreeBSD__
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_Cs0P - probe for Creatix ISDN-S0 P&P and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_Cs0P(struct isa_device *dev, unsigned int iobase2)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 5:
+ case 7:
+ case 10:
+ case 11:
+ case 12:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ if(iobase2 == 0)
+ {
+ printf("isic%d: Error, iobase2 is 0 for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x120:
+ case 0x180:
+/*XXX*/ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = ctxs0P_read_reg;
+ sc->writereg = ctxs0P_write_reg;
+
+ sc->readfifo = ctxs0P_read_fifo;
+ sc->writefifo = ctxs0P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_CS0P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t) dev->id_iobase - 0x20;
+ HSCX_A_BASE = (caddr_t) iobase2 - 0x20;
+ HSCX_B_BASE = (caddr_t) iobase2;
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the Creatix PnP card is
+ * 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Creatix PnP\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163P - attach Creatix ISDN-S0 P&P
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_Cs0P(struct isa_device *dev, unsigned int iobase2)
+{
+ outb((dev->id_iobase) + 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase) + 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else /* !__FreeBSD__ */
+
+void
+isic_attach_Cs0P(struct l1_softc *sc)
+{
+ /* init card */
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = ctxs0P_read_reg;
+ sc->writereg = ctxs0P_write_reg;
+
+ sc->readfifo = ctxs0P_read_fifo;
+ sc->writefifo = ctxs0P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_CS0P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+#endif
+
+#endif /* ISICPNP_CRTX_S0_P */
+
diff --git a/sys/dev/isapnp/i4b_drn_ngo.c b/sys/dev/isapnp/i4b_drn_ngo.c
new file mode 100644
index 00000000000..3d89dbf72eb
--- /dev/null
+++ b/sys/dev/isapnp/i4b_drn_ngo.c
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_drn_ngo.c - Dr. Neuhaus Niccy GO@ and SAGEM Cybermod
+ * --------------------------------------------------------
+ *
+ * $Id: i4b_drn_ngo.c,v 1.1.1.1 2001/01/05 12:50:18 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:29 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicpnp.h"
+#ifdef ISICPNP_DRN_NGO
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <netisdn/i4b_global.h>
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+/*---------------------------------------------------------------------------*
+ * Niccy GO@ definitions
+ *
+ * the card uses 2 i/o addressranges each using 2 bytes
+ *
+ * addressrange 0:
+ * offset 0 - ISAC dataregister
+ * offset 1 - HSCX dataregister
+ * addressrange 1:
+ * offset 0 - ISAC addressregister
+ * offset 1 - HSCX addressregister
+ *
+ * to access an ISAC/HSCX register, you have to write the register
+ * number into the ISAC or HSCX addressregister and then read/write
+ * data for the ISAC/HSCX register into/from the corresponding
+ * dataregister.
+ *
+ * Thanks to Klaus Muehle of Dr. Neuhaus Telekommunikation for giving
+ * out this information!
+ *
+ *---------------------------------------------------------------------------*/
+#define NICCY_PORT_MIN 0x200
+#define NICCY_PORT_MAX 0x3e0
+
+#define HSCX_ABIT 0x1000 /* flag, HSCX A is meant */
+#define HSCX_BBIT 0x2000 /* flag, HSCX B is meant */
+
+#define HSCX_BOFF 0x40
+
+#define ADDR_OFF 2 /* address register range offset XXX */
+
+#define ISAC_DATA 0
+#define HSCX_DATA 1
+
+#define ISAC_ADDR 0
+#define HSCX_ADDR 1
+
+#ifdef __FreeBSD__
+
+#if 0
+#define HSCXADEBUG
+#define HSCXBDEBUG
+#define ISACDEBUG
+#else
+#undef HSCXADEBUG
+#undef HSCXBDEBUG
+#undef ISACDEBUG
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_read_fifo(void *buf, const void *base, size_t len)
+{
+ register int offset;
+ register u_int data;
+
+ int x = SPLI4B();
+
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = 0;
+#ifdef HSCXADEBUG
+printf("GO/A/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = HSCX_BOFF;
+#ifdef HSCXBDEBUG
+printf("GO/B/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else
+ {
+ (u_int)data = ((u_int)base + ISAC_DATA);
+ (u_int)base += (ADDR_OFF + ISAC_ADDR);
+ offset = 0;
+#ifdef ISACDEBUG
+printf("GO/I/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+
+ for(;len > 0; len--, offset++)
+ {
+ outb((int)base, (u_char)offset);
+ *((u_char *)buf + offset) = inb((int)data);
+ }
+
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_write_fifo(void *base, const void *buf, size_t len)
+{
+ register int offset;
+ register u_int data;
+
+ int x = SPLI4B();
+
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = 0;
+#ifdef HSCXADEBUG
+printf("GO/A/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = HSCX_BOFF;
+#ifdef HSCXBDEBUG
+printf("GO/B/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else
+ {
+ (u_int)data = ((u_int)base + ISAC_DATA);
+ (u_int)base += (ADDR_OFF + ISAC_ADDR);
+ offset = 0;
+#ifdef ISACDEBUG
+printf("GO/I/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+
+ for(;len > 0; len--, offset++)
+ {
+ outb((int)base, (u_char)offset);
+ outb((int)data, *((u_char *)buf + offset));
+ }
+
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ write register routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_write_reg(u_char *base, u_int offset, u_int v)
+{
+ int x = SPLI4B();
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)offset);
+ outb((int)base + HSCX_DATA, (u_char)v);
+#ifdef HSCXADEBUG
+printf("GO/A/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)offset, (u_char)v);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)(offset + HSCX_BOFF));
+ outb((int)base + HSCX_DATA, (u_char)v);
+#ifdef HSCXBDEBUG
+printf("GO/B/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)(offset + HSCX_BOFF), (u_char)v);
+#endif
+ }
+ else
+ {
+ outb((int)base + ADDR_OFF + ISAC_ADDR, (u_char)offset);
+ outb((int)base + ISAC_DATA, (u_char)v);
+#ifdef ISACDEBUG
+printf("GO/I/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + ISAC_ADDR, (int)base + ISAC_DATA,
+ (u_char)offset, (u_char)v);
+#endif
+ }
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ read register routine
+ *---------------------------------------------------------------------------*/
+static u_char
+drnngo_read_reg(u_char *base, u_int offset)
+{
+ u_char val;
+ int x = SPLI4B();
+
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)offset);
+ val = inb((int)base + HSCX_DATA);
+#ifdef HSCXADEBUG
+printf("GO/A/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)offset, (u_char)val);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)(offset + HSCX_BOFF));
+ val = inb((int)base + HSCX_DATA);
+#ifdef HSCXBDEBUG
+printf("GO/B/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)(offset + HSCX_BOFF), (u_char)val);
+#endif
+ }
+ else
+ {
+ outb((int)base + ADDR_OFF + ISAC_ADDR, (u_char)offset);
+ val = inb((int)base + ISAC_DATA);
+#ifdef ISACDEBUG
+printf("GO/I/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + ISAC_ADDR, (int)base + ISAC_DATA,
+ (u_char)offset, (u_char)val);
+#endif
+ }
+ splx(x);
+ return(val);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_drnngo - probe for Dr. Neuhaus Niccy GO@
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_drnngo(struct isa_device *dev, unsigned int iobase2)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq)-1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ if(dev->id_iobase < NICCY_PORT_MIN || dev->id_iobase > NICCY_PORT_MAX)
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ }
+ sc->sc_port = dev->id_iobase;
+
+ if(iobase2 == 0)
+ {
+ printf("isic%d: Error, iobase2 is 0 for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ if(iobase2 < NICCY_PORT_MIN || iobase2 > NICCY_PORT_MAX)
+ {
+ printf("isic%d: Error, invalid port1 0x%x specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, iobase2);
+ return(0);
+ }
+
+/*XXX*/ if((dev->id_iobase + 2) != iobase2)
+ {
+ printf("isic%d: Error, port1 must be (port0+2) for Dr.Neuhaus Niccy GO@!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = drnngo_read_reg;
+ sc->writereg = drnngo_write_reg;
+
+ sc->readfifo = drnngo_read_fifo;
+ sc->writefifo = drnngo_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_DRNNGO;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t)dev->id_iobase;
+ HSCX_A_BASE = (caddr_t)(((u_int)dev->id_iobase) | HSCX_ABIT);
+ HSCX_B_BASE = (caddr_t)(((u_int)dev->id_iobase) | HSCX_BBIT);
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for Dr. Neuhaus Niccy GO@ based
+ * boards is 0x05 in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Dr. Neuhaus Niccy GO@\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_drnngo - attach Dr. Neuhaus Niccy GO@
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_drnngo(struct isa_device *dev, unsigned int iobase2)
+{
+ return (1);
+}
+
+#else
+
+static u_int8_t drnngo_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void drnngo_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void drnngo_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+static void drnngo_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+void isic_attach_drnngo __P((struct l1_softc *sc));
+
+/*
+ * Mapping from "what" parameter to offsets into the io map
+ */
+static struct {
+ bus_size_t oa, /* address register offset */
+ od, /* data register offset */
+ or; /* additional chip register offset */
+} offset[] =
+{
+ { ISAC_ADDR, ISAC_DATA, 0 }, /* ISAC access */
+ { HSCX_ADDR, HSCX_DATA, 0 }, /* HSCX A access */
+ { HSCX_ADDR, HSCX_DATA, HSCX_BOFF } /* HSCX B access */
+};
+
+static void
+drnngo_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offset[what].or);
+ bus_space_read_multi_1(t, hd, offset[what].od, buf, size);
+}
+
+static void
+drnngo_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offset[what].or);
+ bus_space_write_multi_1(t, hd, offset[what].od, (u_int8_t*)buf, size);
+}
+
+static void
+drnngo_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offs+offset[what].or);
+ bus_space_write_1(t, hd, offset[what].od, data);
+}
+
+static u_int8_t
+drnngo_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offs+offset[what].or);
+ return bus_space_read_1(t, hd, offset[what].od);
+}
+
+void
+isic_attach_drnngo(struct l1_softc *sc)
+{
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = drnngo_read_reg;
+ sc->writereg = drnngo_write_reg;
+
+ sc->readfifo = drnngo_read_fifo;
+ sc->writefifo = drnngo_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_DRNNGO;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+
+#endif
+
+#endif /* ISICPNP_DRN_NGO */
diff --git a/sys/dev/isapnp/i4b_dynalink.c b/sys/dev/isapnp/i4b_dynalink.c
new file mode 100644
index 00000000000..65bc1006828
--- /dev/null
+++ b/sys/dev/isapnp/i4b_dynalink.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 1998 Martijn Plak. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isdn4bsd layer1 driver for Dynalink IS64PH isdn TA
+ * ==================================================
+ *
+ * $Id: i4b_dynalink.c,v 1.1.1.1 2001/01/05 12:50:17 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:29 2001]
+ *
+ * written by Martijn Plak (martijn@be3.com)
+ *
+ * -mp 11 jun 1998 first try, code borrowed from Creatix driver
+ * -mp 18 jun 1998 cleaned up code
+ * -hm FreeBSD PnP
+ * -mp 17 dec 1998 made it compile again
+ *
+ *---------------------------------------------------------------------------*/
+
+/* NOTES:
+
+ This driver was written for the Dynalink IS64PH ISDN TA, based on two
+ Siemens chips (HSCX 21525 and ISAC 2186). It is sold in the Netherlands.
+
+ model numbers found on (my) card:
+ IS64PH, TAS100H-N, P/N:89590555, TA200S100045521
+
+ chips:
+ Siemens PSB 21525N, HSCX TE V2.1
+ Siemens PSB 2186N, ISAC-S TE V1.1
+ 95MS14, PNP
+
+ plug-and-play info:
+ device id "ASU1688"
+ vendor id 0x88167506
+ serial 0x00000044
+ i/o port 4 byte alignment, 4 bytes requested,
+ 10 bit i/o decoding, 0x100-0x3f8 (?)
+ irq 3,4,5,9,10,11,12,15, high true, edge sensitive
+
+ At the moment I'm writing this Dynalink is replacing this card with
+ one based on a single Siemens chip (IPAC). It will apparently be sold
+ under the same model name.
+
+ This driver might also work for Asuscom cards.
+*/
+
+#include "opt_isicpnp.h"
+#ifdef ISICPNP_DYNALINK
+
+/* HEADERS
+*/
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/pnp.h>
+#elif defined(__bsdi__)
+#include <i386/isa/pnp.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#if defined(__FreeBSD__) || defined(__bsdi__)
+static void dynalink_read_fifo(void *buf, const void *base, size_t len);
+static void dynalink_write_fifo(void *base, const void *buf, size_t len);
+static void dynalink_write_reg(u_char *base, u_int offset, u_int v);
+static u_char dynalink_read_reg(u_char *base, u_int offset);
+#endif
+
+#ifdef __FreeBSD__
+extern struct isa_driver isicdriver;
+#endif
+#ifdef __bsdi__
+extern struct cfdriver isiccd;
+#endif
+
+#if !defined(__FreeBSD__) && !defined(__bsdi__)
+static void dynalink_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size);
+static void dynalink_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size);
+static void dynalink_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data);
+static u_int8_t dynalink_read_reg(struct l1_softc *sc, int what, bus_size_t offs);
+void isic_attach_Dyn(struct l1_softc *sc);
+#endif
+
+/* io address mapping */
+#define ISAC 0
+#define HSCX 1
+#define ADDR 2
+
+/* ADDR bits */
+#define ADDRMASK 0x7F
+#define RESET 0x80
+
+/* HSCX register offsets */
+#define HSCXA 0x00
+#define HSCXB 0x40
+
+#if defined(__FreeBSD__) || defined(__bsdi__)
+/* base address juggling */
+#define HSCXB_HACK 0x400
+#define IOBASE(addr) (((int)addr)&0x3FC)
+#define IOADDR(addr) (((int)addr)&0x3FF)
+#define IS_HSCXB_HACK(addr) ((((int)addr)&HSCXB_HACK)?HSCXB:HSCXA)
+#endif
+
+#ifdef __FreeBSD__
+/* ISIC probe and attach
+*/
+
+int
+isic_probe_Dyn(struct isa_device *dev, unsigned int iobase2)
+{
+
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dynalink IS64PH.\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return (0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+ if ( (dev->id_iobase < 0x100) ||
+ (dev->id_iobase > 0x3f8) ||
+ (dev->id_iobase & 3) )
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", dev->id_unit, dev->id_iobase);
+ return(0);
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = dynalink_read_reg;
+ sc->writereg = dynalink_write_reg;
+ sc->readfifo = dynalink_read_fifo;
+ sc->writefifo = dynalink_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+ ISAC_BASE = (caddr_t) sc->sc_port;
+ HSCX_A_BASE = (caddr_t) sc->sc_port + 1;
+ HSCX_B_BASE = (caddr_t) sc->sc_port + 1 + HSCXB_HACK;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Dynalink\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+int
+isic_attach_Dyn(struct isa_device *dev, unsigned int iobase2)
+{
+ outb((dev->id_iobase)+ADDR, RESET);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase)+ADDR, 0);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#elif defined(__bsdi__)
+
+/* ISIC probe and attach
+*/
+
+static int
+set_softc(struct l1_softc *sc, struct isa_attach_args *ia, int unit)
+{
+ if (unit >= NISIC)
+ return 0;
+ sc->sc_unit = unit;
+ switch(ffs(ia->ia_irq) - 1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
+ unit, ffs(ia->ia_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = ia->ia_irq;
+
+ /* check if memory addr specified */
+
+ if(ia->ia_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
+ unit, (u_long)ia->ia_maddr);
+ return (0);
+ }
+
+ /* check if we got an iobase */
+ if ( (ia->ia_iobase < 0x100) ||
+ (ia->ia_iobase > 0x3f8) ||
+ (ia->ia_iobase & 3) )
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", unit, ia->ia_iobase);
+ return(0);
+ }
+ sc->sc_port = ia->ia_iobase;
+
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = dynalink_read_reg;
+ sc->writereg = dynalink_write_reg;
+ sc->readfifo = dynalink_read_fifo;
+ sc->writefifo = dynalink_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+ ISAC_BASE = (caddr_t) sc->sc_port;
+ HSCX_A_BASE = (caddr_t) sc->sc_port + 1;
+ HSCX_B_BASE = (caddr_t) sc->sc_port + 1 + HSCXB_HACK;
+ return 1;
+}
+
+int
+isapnp_match_dynalink(struct device *parent, struct cfdata *cf,
+ struct isa_attach_args *ia)
+{
+ struct l1_softc dummysc, *sc = &dummysc;
+ pnp_resource_t res;
+ char *ids[] = {"ASU1688", NULL};
+ bzero(&res, sizeof res);
+ res.res_irq[0].irq_level = ia->ia_irq;
+ res.res_port[0].prt_base = ia->ia_iobase;
+ res.res_port[0].prt_length = 4;
+
+ if (!pnp_assigndev(ids, isiccd.cd_name, &res))
+ return (0);
+
+ ia->ia_irq = res.res_irq[0].irq_level;
+ ia->ia_iobase = res.res_port[0].prt_base;
+ ia->ia_iosize = res.res_port[0].prt_length;
+
+ if (set_softc(sc, ia, cf->cf_unit) == 0)
+ return 0;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Dynalink\n",
+ cf->cf_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ cf->cf_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ cf->cf_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ cf->cf_flags = FLAG_DYNALINK;
+ return (1);
+}
+
+int
+isic_attach_Dyn(struct device *parent, struct device *self,
+ struct isa_attach_args *ia)
+{
+ struct l1_softc *sc = (struct l1_softc *)self;
+ int unit = sc->sc_dev.dv_unit;
+
+ /* Commit the probed attachment values */
+ if (set_softc(sc, ia, unit) == 0)
+ panic("isic_attach_Dyn: set_softc");
+
+ outb((ia->ia_iobase)+ADDR, RESET);
+ DELAY(SEC_DELAY / 10);
+ outb((ia->ia_iobase)+ADDR, 0);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else
+
+void isic_attach_Dyn(struct l1_softc *sc)
+{
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = dynalink_read_reg;
+ sc->writereg = dynalink_write_reg;
+ sc->readfifo = dynalink_read_fifo;
+ sc->writefifo = dynalink_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("%s: HSCX VSTR test failed for Dynalink PnP\n",
+ sc->sc_dev.dv_xname);
+ printf("%s: HSC0: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
+ printf("%s: HSC1: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
+ return;
+ }
+
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, RESET);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, 0);
+ DELAY(SEC_DELAY / 10);
+}
+
+#endif
+
+/* LOW-LEVEL DEVICE ACCESS
+
+ NOTE: The isdn4bsd code expects the two HSCX channels at different
+ base addresses. I'm faking this, and remap them to the same address
+ in the low-level routines. Search for HSCXB_HACK and IS_HSCXB_HACK.
+
+ REM: this is only true for the FreeBSD version of I4B!
+*/
+
+#if defined(__FreeBSD__) || defined(__bsdi__)
+static void
+dynalink_read_fifo(void *buf, const void *base, size_t len)
+{
+ outb(IOBASE(base)+ADDR, 0+IS_HSCXB_HACK(base));
+ insb(IOADDR(base), (u_char *)buf, (u_int)len);
+}
+#else
+static void
+dynalink_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, 0);
+ bus_space_read_multi_1(t, h, ISAC, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA);
+ bus_space_read_multi_1(t, h, HSCX, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB);
+ bus_space_read_multi_1(t, h, HSCX, buf, size);
+ break;
+ }
+}
+#endif
+
+#if defined(__FreeBSD__) || defined(__bsdi__)
+static void
+dynalink_write_fifo(void *base, const void *buf, size_t len)
+{
+ outb(IOBASE(base)+ADDR, 0+IS_HSCXB_HACK(base));
+ outsb(IOADDR(base), (u_char *)buf, (u_int)len);
+}
+#else
+static void dynalink_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, 0);
+ bus_space_write_multi_1(t, h, ISAC, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA);
+ bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB);
+ bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+#if defined(__FreeBSD__) || defined(__bsdi__)
+static void
+dynalink_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb(IOBASE(base)+ADDR, (offset+IS_HSCXB_HACK(base))&ADDRMASK);
+ outb(IOADDR(base), (u_char)v);
+}
+#else
+static void dynalink_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, offs);
+ bus_space_write_1(t, h, ISAC, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA+offs);
+ bus_space_write_1(t, h, HSCX, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB+offs);
+ bus_space_write_1(t, h, HSCX, data);
+ break;
+ }
+}
+#endif
+
+#if defined(__FreeBSD__) || defined(__bsdi__)
+static u_char
+dynalink_read_reg(u_char *base, u_int offset)
+{
+ outb(IOBASE(base)+ADDR, (offset+IS_HSCXB_HACK(base))&ADDRMASK);
+ return (inb(IOADDR(base)));
+}
+#else
+static u_int8_t dynalink_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, offs);
+ return bus_space_read_1(t, h, ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA+offs);
+ return bus_space_read_1(t, h, HSCX);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB+offs);
+ return bus_space_read_1(t, h, HSCX);
+ }
+ return 0;
+}
+#endif
+
+#endif /* ISICPNP_DYNALINK */
diff --git a/sys/dev/isapnp/i4b_elsa_qs1i.c b/sys/dev/isapnp/i4b_elsa_qs1i.c
new file mode 100644
index 00000000000..d7d388c52cd
--- /dev/null
+++ b/sys/dev/isapnp/i4b_elsa_qs1i.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro ISA
+ * =====================================================================
+ *
+ * $Id: i4b_elsa_qs1i.c,v 1.1.1.1 2001/01/05 12:50:17 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:29 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicpnp.h"
+#if defined(ISICPNP_ELSA_QS1ISA) || defined(ISICPNP_ELSA_PCC16)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/pnp.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#ifdef __FreeBSD__
+static void i4b_eq1i_clrirq(void* base);
+#else
+static void i4b_eq1i_clrirq(struct l1_softc *sc);
+void isic_attach_Eqs1pi __P((struct l1_softc *sc));
+#endif
+
+/* masks for register encoded in base addr */
+
+#define ELSA_BASE_MASK 0x0ffff
+#define ELSA_OFF_MASK 0xf0000
+
+/* register id's to be encoded in base addr */
+
+#define ELSA_IDISAC 0x00000
+#define ELSA_IDHSCXA 0x10000
+#define ELSA_IDHSCXB 0x20000
+
+/* offsets from base address */
+
+#define ELSA_OFF_ISAC 0x00
+#define ELSA_OFF_HSCX 0x02
+#define ELSA_OFF_OFF 0x03
+#define ELSA_OFF_CTRL 0x04
+#define ELSA_OFF_CFG 0x05
+#define ELSA_OFF_TIMR 0x06
+#define ELSA_OFF_IRQ 0x07
+
+/* control register (write access) */
+
+#define ELSA_CTRL_LED_YELLOW 0x02
+#define ELSA_CTRL_LED_GREEN 0x08
+#define ELSA_CTRL_RESET 0x20
+#define ELSA_CTRL_TIMEREN 0x80
+#define ELSA_CTRL_SECRET 0x50
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA clear IRQ routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+i4b_eq1i_clrirq(void* base)
+{
+ outb((u_int)base + ELSA_OFF_IRQ, 0);
+}
+
+#else
+static void
+i4b_eq1i_clrirq(struct l1_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ELSA_OFF_IRQ, 0);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pi_read_fifo(void *buf, const void *base, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pi_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
+ bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pi_write_fifo(void *base, const void *buf, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pi_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_write_multi_1(t, h, ELSA_OFF_ISAC, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
+ bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pi_write_reg(u_char *base, u_int offset, u_int v)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC, (u_char)v);
+ }
+}
+
+#else
+
+static void
+eqs1pi_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ bus_space_write_1(t, h, ELSA_OFF_ISAC, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
+ bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+eqs1pi_read_reg(u_char *base, u_int offset)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC));
+ }
+}
+
+#else
+
+static u_int8_t
+eqs1pi_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ return bus_space_read_1(t, h, ELSA_OFF_ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ return bus_space_read_1(t, h, ELSA_OFF_HSCX);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_HSCX);
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef __FreeBSD__
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_Eqs1pi - probe for ELSA QuickStep 1000pro/ISA and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 7:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ if(!((dev->id_iobase >= 0x160) && (dev->id_iobase <= 0x360)))
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+
+ sc->clearirq = i4b_eq1i_clrirq;
+ sc->readreg = eqs1pi_read_reg;
+ sc->writereg = eqs1pi_write_reg;
+
+ sc->readfifo = eqs1pi_read_fifo;
+ sc->writefifo = eqs1pi_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDISAC);
+ HSCX_A_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXA);
+ HSCX_B_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXB);
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the ELSA QuickStep 1000pro
+ * ISA card is 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for ELSA QuickStep 1000pro/ISA\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163P - attach ELSA QuickStep 1000pro/ISA
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
+{
+ u_char byte = ELSA_CTRL_SECRET;
+
+ byte &= ~ELSA_CTRL_RESET;
+ outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
+ DELAY(20);
+ byte |= ELSA_CTRL_RESET;
+ outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
+
+ DELAY(20);
+ outb(dev->id_iobase + ELSA_OFF_IRQ, 0xff);
+
+ return(1);
+}
+
+#else /* !__FreeBSD__ */
+
+void
+isic_attach_Eqs1pi(struct l1_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ u_char byte = ELSA_CTRL_SECRET;
+
+ byte &= ~ELSA_CTRL_RESET;
+ bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
+ DELAY(20);
+ byte |= ELSA_CTRL_RESET;
+ bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
+
+ DELAY(20);
+ bus_space_write_1(t, h, ELSA_OFF_IRQ, 0xff);
+
+ /* setup access routines */
+
+ sc->clearirq = i4b_eq1i_clrirq;
+ sc->readreg = eqs1pi_read_reg;
+ sc->writereg = eqs1pi_write_reg;
+
+ sc->readfifo = eqs1pi_read_fifo;
+ sc->writefifo = eqs1pi_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+
+#endif
+
+#endif /* ISICPNP_ELSA_QS1ISA or ISICPNP_ELSA_PCC16 */
diff --git a/sys/dev/isapnp/i4b_siemens_isurf.c b/sys/dev/isapnp/i4b_siemens_isurf.c
new file mode 100644
index 00000000000..0b4c4c1e7e5
--- /dev/null
+++ b/sys/dev/isapnp/i4b_siemens_isurf.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 1999 Udo Schweigert. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ * Based on ELSA Quickstep 1000pro PCI driver (i4b_elsa_qs1p.c)
+ *---------------------------------------------------------------------------
+ * In case of trouble please contact Udo Schweigert <ust@cert.siemens.de>
+ *---------------------------------------------------------------------------
+ *
+ * Siemens I-Surf 2.0 PnP specific routines for isic driver
+ * --------------------------------------------------------
+ *
+ * $Id: i4b_siemens_isurf.c,v 1.1.1.1 2001/01/05 12:50:18 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:29 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#if defined(__FreeBSD__)
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__FreeBSD__)
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_ipac.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#if !defined(__FreeBSD__)
+void isic_attach_siemens_isurf __P((struct l1_softc *sc));
+#endif
+
+/* masks for register encoded in base addr */
+
+#define SIE_ISURF_BASE_MASK 0x0ffff
+#define SIE_ISURF_OFF_MASK 0xf0000
+
+/* register id's to be encoded in base addr */
+
+#define SIE_ISURF_IDISAC 0x00000
+#define SIE_ISURF_IDHSCXA 0x10000
+#define SIE_ISURF_IDHSCXB 0x20000
+#define SIE_ISURF_IDIPAC 0x40000
+
+/* offsets from base address */
+
+#define SIE_ISURF_OFF_ALE 0x00
+#define SIE_ISURF_OFF_RW 0x01
+
+/*---------------------------------------------------------------------------*
+ * Siemens I-Surf 2.0 PnP ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__)
+
+static void
+siemens_isurf_read_fifo(void *buf, const void *base, size_t len)
+{
+ if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_HSCXB_OFF);
+ insb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_HSCXA_OFF);
+ insb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) */
+ {
+ outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_ISAC_OFF);
+ insb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+siemens_isurf_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_ISAC_OFF);
+ bus_space_read_multi_1(t, h, SIE_ISURF_OFF_RW, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_HSCXA_OFF);
+ bus_space_read_multi_1(t, h, SIE_ISURF_OFF_RW, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_HSCXB_OFF);
+ bus_space_read_multi_1(t, h, SIE_ISURF_OFF_RW, buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Siemens I-Surf 2.0 PnP ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__)
+
+static void
+siemens_isurf_write_fifo(void *base, const void *buf, size_t len)
+{
+ if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_HSCXB_OFF);
+ outsb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (const u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_HSCXA_OFF);
+ outsb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (const u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) */
+ {
+ outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_ISAC_OFF);
+ outsb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (const u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+siemens_isurf_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_ISAC_OFF);
+ bus_space_write_multi_1(t, h, SIE_ISURF_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_HSCXA_OFF);
+ bus_space_write_multi_1(t, h, SIE_ISURF_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_HSCXB_OFF);
+ bus_space_write_multi_1(t, h, SIE_ISURF_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Siemens I-Surf 2.0 PnP ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__)
+
+static void
+siemens_isurf_write_reg(u_char *base, u_int offset, u_int v)
+{
+ if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB)
+ {
+ outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF));
+ outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW, (u_char)v);
+ }
+ else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA)
+ {
+ outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF));
+ outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW, (u_char)v);
+ }
+ else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC)
+ {
+ outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF));
+ outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW, (u_char)v);
+ }
+ else /* IPAC */
+ {
+ outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF));
+ outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW, (u_char)v);
+ }
+}
+
+#else
+
+static void
+siemens_isurf_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_ISAC_OFF+offs);
+ bus_space_write_1(t, h, SIE_ISURF_OFF_RW, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_HSCXA_OFF+offs);
+ bus_space_write_1(t, h, SIE_ISURF_OFF_RW, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_HSCXB_OFF+offs);
+ bus_space_write_1(t, h, SIE_ISURF_OFF_RW, data);
+ break;
+ case ISIC_WHAT_IPAC:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_IPAC_OFF+offs);
+ bus_space_write_1(t, h, SIE_ISURF_OFF_RW, data);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Siemens I-Surf 2.0 PnP ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__)
+
+static u_char
+siemens_isurf_read_reg(u_char *base, u_int offset)
+{
+ if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF));
+ return(inb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW));
+ }
+ else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF));
+ return(inb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW));
+ }
+ else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC)
+ {
+ outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF));
+ return(inb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW));
+ }
+ else /* IPAC */
+ {
+ outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF));
+ return(inb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW));
+ }
+}
+
+#else
+
+static u_int8_t
+siemens_isurf_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_ISAC_OFF+offs);
+ return bus_space_read_1(t, h, SIE_ISURF_OFF_RW);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_HSCXA_OFF+offs);
+ return bus_space_read_1(t, h, SIE_ISURF_OFF_RW);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_HSCXB_OFF+offs);
+ return bus_space_read_1(t, h, SIE_ISURF_OFF_RW);
+ case ISIC_WHAT_IPAC:
+ bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_IPAC_OFF+offs);
+ return bus_space_read_1(t, h, SIE_ISURF_OFF_RW);
+ }
+ return 0;
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_siemens_isurf - probe for Siemens I-Surf 2.0 PnP
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__)
+
+int
+isic_probe_siemens_isurf(struct isa_device *dev, unsigned int iobase2)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Siemens I-Surf 2.0 PnP\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 7:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Siemens I-Surf 2.0 PnP!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Siemens I-Surf 2.0 PnP!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ if(!((dev->id_iobase >= 0x100) && (dev->id_iobase <= 0xfffc)))
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for Siemens I-Surf 2.0 PnP!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ }
+ sc->sc_port = dev->id_iobase;
+
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = siemens_isurf_read_reg;
+ sc->writereg = siemens_isurf_write_reg;
+
+ sc->readfifo = siemens_isurf_read_fifo;
+ sc->writefifo = siemens_isurf_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ /* setup chip type = IPAC ! */
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_siemens_isurf - attach for Siemens I-Surf 2.0 PnP
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_siemens_isurf(struct isa_device *dev, unsigned int iobase2)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t) ((u_int)sc->sc_port | SIE_ISURF_IDISAC);
+ HSCX_A_BASE = (caddr_t) ((u_int)sc->sc_port | SIE_ISURF_IDHSCXA);
+ HSCX_B_BASE = (caddr_t) ((u_int)sc->sc_port | SIE_ISURF_IDHSCXB);
+ IPAC_BASE = (caddr_t) ((u_int)sc->sc_port | SIE_ISURF_IDIPAC);
+
+ /* enable hscx/isac irq's */
+ IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
+
+ IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */
+ IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */
+ (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
+ IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */
+
+ return(1);
+}
+
+#else
+
+void
+isic_attach_siemens_isurf(struct l1_softc *sc)
+{
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = siemens_isurf_read_reg;
+ sc->writereg = siemens_isurf_write_reg;
+
+ sc->readfifo = siemens_isurf_read_fifo;
+ sc->writefifo = siemens_isurf_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ /* setup chip type = IPAC ! */
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+ /* enable hscx/isac irq's */
+
+ IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
+
+ IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */
+ IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */
+ (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
+ IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */
+}
+
+#endif
diff --git a/sys/dev/isapnp/i4b_sws.c b/sys/dev/isapnp/i4b_sws.c
new file mode 100644
index 00000000000..7b17aa5d385
--- /dev/null
+++ b/sys/dev/isapnp/i4b_sws.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 1998 German Tischler. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * Card format:
+ *
+ * iobase + 0 : reset on (0x03)
+ * iobase + 1 : reset off (0x0)
+ * iobase + 2 : isac read/write
+ * iobase + 3 : hscx read/write ( offset 0-0x3f hscx0 ,
+ * offset 0x40-0x7f hscx1 )
+ * iobase + 4 : offset for indirect adressing
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for SWS cards
+ * ====================================================
+ *
+ * EXPERIMENTAL !!!!
+ * =================
+ *
+ * $Id: i4b_sws.c,v 1.1.1.1 2001/01/05 12:50:17 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:29 2001]
+ *
+ * -hm adding driver to i4b
+ * -hm adjustments for FreeBSD < 2.2.6, no PnP support yet
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicpnp.h"
+#ifdef ISICPNP_SEDLBAUER
+
+#define SWS_RESON 0 /* reset on */
+#define SWS_RESOFF 1 /* reset off */
+#define SWS_ISAC 2 /* ISAC */
+#define SWS_HSCX0 3 /* HSCX0 */
+#define SWS_RW 4 /* indirect access register */
+#define SWS_HSCX1 5 /* this is for fakeing that we mean hscx1, though */
+ /* access is done through hscx0 */
+
+#define SWS_REGS 8 /* we use an area of 8 bytes for io */
+
+#define SWS_BASE(X) ((unsigned int)X&~(SWS_REGS-1))
+#define SWS_PART(X) ((unsigned int)X& (SWS_REGS-1))
+#define SWS_ADDR(X) ((SWS_PART(X) == SWS_ISAC) ? (SWS_BASE(X)+SWS_ISAC) : (SWS_BASE(X)+SWS_HSCX0) )
+#define SWS_REG(X,Y) ((SWS_PART(X) != SWS_HSCX1) ? Y : (Y+0x40) )
+#define SWS_IDO(X) (SWS_BASE(X)+SWS_RW)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t sws_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void sws_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void sws_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+static void sws_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+void isic_attach_sws __P((struct l1_softc *sc));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+static void
+sws_read_fifo(void *buf, const void *base, size_t len)
+{
+ outb(SWS_IDO(base),SWS_REG(base,0));
+ insb(SWS_ADDR(base),buf,len);
+}
+
+#else
+
+static void
+sws_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_read_multi_1(t, h, SWS_ISAC, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_read_multi_1(t, h, SWS_HSCX0, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40);
+ bus_space_read_multi_1(t, h, SWS_HSCX0, buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+static void
+sws_write_fifo(void *base, const void *buf, size_t len)
+{
+ outb (SWS_IDO(base),SWS_REG(base,0));
+ outsb(SWS_ADDR(base),buf,len);
+}
+
+#else
+
+static void
+sws_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_write_multi_1(t, h, SWS_ISAC, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_write_multi_1(t, h, SWS_HSCX0, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40);
+ bus_space_write_multi_1(t, h, SWS_HSCX0, (u_int8_t*)buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC put register routine
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+static void
+sws_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb(SWS_IDO(base),SWS_REG(base,offset));
+ outb(SWS_ADDR(base),v);
+}
+
+#else
+
+static void
+sws_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ bus_space_write_1(t, h, SWS_ISAC, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ bus_space_write_1(t, h, SWS_HSCX0, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40+offs);
+ bus_space_write_1(t, h, SWS_HSCX0, data);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+sws_read_reg(u_char *base, u_int offset)
+{
+ outb(SWS_IDO(base),SWS_REG(base,offset));
+ return inb(SWS_ADDR(base));
+}
+
+#else
+
+static u_int8_t
+sws_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ return bus_space_read_1(t, h, SWS_ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ return bus_space_read_1(t, h, SWS_HSCX0);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40+offs);
+ return bus_space_read_1(t, h, SWS_HSCX0);
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef __FreeBSD__
+
+/* attach callback routine */
+
+int
+isic_attach_sws(struct isa_device *dev)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ /* fill in l1_softc structure */
+
+ sc->readreg = sws_read_reg;
+ sc->writereg = sws_write_reg;
+ sc->readfifo = sws_read_fifo;
+ sc->writefifo = sws_write_fifo;
+ sc->clearirq = NULL;
+ sc->sc_unit = dev->id_unit;
+ sc->sc_irq = dev->id_irq;
+ sc->sc_port = dev->id_iobase;
+ sc->sc_cardtyp = CARD_TYPEP_SWS;
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+ dev->id_msize = 0;
+
+ ISAC_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_ISAC);
+ HSCX_A_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_HSCX0);
+ HSCX_B_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_HSCX1);
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the SWS PnP card is
+ * 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for SWS PnP\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ /* reset card */
+
+ outb( ((u_int) sc->sc_port) + SWS_RESON , 0x3);
+ DELAY(SEC_DELAY / 5);
+ outb( ((u_int) sc->sc_port) + SWS_RESOFF, 0);
+ DELAY(SEC_DELAY / 5);
+
+ return(1);
+}
+
+#else /* !__FreeBSD__ */
+
+void
+isic_attach_sws(struct l1_softc *sc)
+{
+ /* setup access routines */
+
+ sc->readreg = sws_read_reg;
+ sc->writereg = sws_write_reg;
+
+ sc->readfifo = sws_read_fifo;
+ sc->writefifo = sws_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_SWS;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the SWS PnP card is
+ * 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("%s: HSCX VSTR test failed for SWS PnP\n",
+ sc->sc_dev.dv_xname);
+ printf("%s: HSC0: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
+ printf("%s: HSC1: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
+ return;
+ }
+
+ /* reset card */
+ {
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, SWS_RESON, 0x3);
+ DELAY(SEC_DELAY / 5);
+ bus_space_write_1(t, h, SWS_RESOFF, 0);
+ DELAY(SEC_DELAY / 5);
+ }
+}
+
+#endif /* !__FreeBSD__ */
+
+#endif /* ISICPNP_SEDLBAUER */
diff --git a/sys/dev/isapnp/i4b_tel_s0P.c b/sys/dev/isapnp/i4b_tel_s0P.c
new file mode 100644
index 00000000000..fc979ee2ccf
--- /dev/null
+++ b/sys/dev/isapnp/i4b_tel_s0P.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 1997 Andrew Gordon. All rights reserved.
+ *
+ * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0 PnP
+ * =======================================================
+ *
+ * EXPERIMENTAL !!!
+ * ================
+ *
+ * $Id: i4b_tel_s0P.c,v 1.1.1.1 2001/01/05 12:50:18 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:29 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicpnp.h"
+#ifdef ISICPNP_TEL_S0_16_3_P
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t tels0163P_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void tels0163P_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels0163P_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+static void tels0163P_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+void isic_attach_s0163P __P((struct l1_softc *sc));
+#endif
+
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP read fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163P_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163P_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_read_multi_1(t, h, o + 0x3e, buf, size);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP write fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163P_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163P_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_multi_1(t, h, o + 0x3e, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP write register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163P_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+
+#else
+
+static void
+tels0163P_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_1(t, h, o + offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP read register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels0163P_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+
+#else
+
+static u_int8_t
+tels0163P_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ return bus_space_read_1(t, h, o + offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s0163P - probe for Teles S0/16.3 PnP and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_s0163P(struct isa_device *dev, unsigned int iobase2)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3 PnP!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 5:
+ case 7:
+ case 10:
+ case 11:
+ case 12:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3 PnP!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3 PnP!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x580:
+ case 0x500:
+ case 0x680:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3 PnP!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163P_read_reg;
+ sc->writereg = tels0163P_write_reg;
+
+ sc->readfifo = tels0163P_read_fifo;
+ sc->writefifo = tels0163P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_163P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ switch(dev->id_iobase)
+ {
+ case 0x580:
+ ISAC_BASE = (caddr_t) 0x580 - 0x20;
+ HSCX_A_BASE = (caddr_t) 0x180 - 0x20;
+ HSCX_B_BASE = (caddr_t) 0x180;
+ break;
+
+ case 0x500:
+ ISAC_BASE = (caddr_t) 0x500 - 0x20;
+ HSCX_A_BASE = (caddr_t) 0x100 - 0x20;
+ HSCX_B_BASE = (caddr_t) 0x100;
+ break;
+
+ case 0x680:
+ ISAC_BASE = (caddr_t) 0x680 - 0x20;
+ HSCX_A_BASE = (caddr_t) 0x280 - 0x20;
+ HSCX_B_BASE = (caddr_t) 0x280;
+ break;
+ }
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the S0/16.3 PnP card is
+ * 0x05 in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Teles S0/16.3 PnP\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163P - attach Teles S0/16.3 PnP and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_s0163P(struct isa_device *dev, unsigned int iobase2)
+{
+ outb((dev->id_iobase) + 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase) + 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else
+
+void
+isic_attach_s0163P(struct l1_softc *sc)
+{
+ /* init card */
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163P_read_reg;
+ sc->writereg = tels0163P_write_reg;
+
+ sc->readfifo = tels0163P_read_fifo;
+ sc->writefifo = tels0163P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_163P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+#endif
+
+#endif /* ISICPNP_TEL_S0_16_3_P */
+
diff --git a/sys/dev/isapnp/isapnp_isic.c b/sys/dev/isapnp/isapnp_isic.c
new file mode 100644
index 00000000000..44069c46a86
--- /dev/null
+++ b/sys/dev/isapnp/isapnp_isic.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 1997, 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isapnp_isic.c - ISA-P&P bus frontend for i4b_isic driver
+ * --------------------------------------------------------
+ *
+ * $Id: isapnp_isic.c,v 1.1.1.1 2001/01/05 12:50:16 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:29 2001]
+ *
+ * -mh original implementation
+ * -hm NetBSD patches from Martin
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isapnp/isapnpreg.h>
+#include <dev/isapnp/isapnpvar.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <netisdn/i4b_ioctl.h>
+#include <netisdn/i4b_trace.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_ipac.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_global.h>
+
+#include "opt_isicpnp.h"
+
+#ifdef __BROKEN_INDIRECT_CONFIG
+static int isapnp_isic_probe __P((struct device *, void *, void *));
+#else
+static int isapnp_isic_probe __P((struct device *, struct cfdata *, void *));
+#endif
+static void isapnp_isic_attach __P((struct device *, struct device *, void *));
+
+struct cfattach isapnp_isic_ca = {
+ sizeof(struct l1_softc), isapnp_isic_probe, isapnp_isic_attach
+};
+
+typedef void (*allocmaps_func)(struct isapnp_attach_args *ipa, struct l1_softc *sc);
+typedef void (*attach_func)(struct l1_softc *sc);
+
+/* map allocators */
+static void generic_pnp_mapalloc(struct isapnp_attach_args *ipa, struct l1_softc *sc);
+#ifdef ISICPNP_DRN_NGO
+static void ngo_pnp_mapalloc(struct isapnp_attach_args *ipa, struct l1_softc *sc);
+#endif
+#if defined(ISICPNP_CRTX_S0_P) || defined(ISICPNP_TEL_S0_16_3_P)
+static void tls_pnp_mapalloc(struct isapnp_attach_args *ipa, struct l1_softc *sc);
+#endif
+
+/* card attach functions */
+extern void isic_attach_Cs0P __P((struct l1_softc *sc));
+extern void isic_attach_Dyn __P((struct l1_softc *sc));
+extern void isic_attach_s0163P __P((struct l1_softc *sc));
+extern void isic_attach_drnngo __P((struct l1_softc *sc));
+extern void isic_attach_sws __P((struct l1_softc *sc));
+extern void isic_attach_Eqs1pi __P((struct l1_softc *sc));
+extern void isic_attach_siemens_isurf __P((struct l1_softc *sc));
+
+struct isapnp_isic_card_desc {
+ char *devlogic; /* ISAPNP logical device ID */
+ char *name; /* Name of the card */
+ int card_type; /* isic card type identifier */
+ allocmaps_func allocmaps; /* map allocator function */
+ attach_func attach; /* card attach and init function */
+};
+static const struct isapnp_isic_card_desc
+isapnp_isic_descriptions[] =
+{
+#ifdef ISICPNP_CRTX_S0_P
+ { "CTX0000", "Creatix ISDN S0-16 P&P", CARD_TYPEP_CS0P,
+ tls_pnp_mapalloc, isic_attach_Cs0P },
+#endif
+#ifdef ISICPNP_TEL_S0_16_3_P
+ { "TAG2110", "Teles S0/PnP", CARD_TYPEP_163P,
+ tls_pnp_mapalloc, isic_attach_s0163P },
+#endif
+#ifdef ISICPNP_DRN_NGO
+ { "SDA0150", "Dr. Neuhaus NICCY GO@", CARD_TYPEP_DRNNGO,
+ ngo_pnp_mapalloc, isic_attach_drnngo },
+#endif
+#ifdef ISICPNP_ELSA_QS1ISA
+ { "ELS0133", "Elsa QuickStep 1000 (ISA)", CARD_TYPEP_ELSAQS1ISA,
+ generic_pnp_mapalloc, isic_attach_Eqs1pi },
+#endif
+#ifdef ISICPNP_SEDLBAUER
+ { "SAG0001", "Sedlbauer WinSpeed", CARD_TYPEP_SWS,
+ generic_pnp_mapalloc, isic_attach_sws },
+#endif
+#ifdef ISICPNP_DYNALINK
+ { "ASU1688", "Dynalink IS64PH", CARD_TYPEP_DYNALINK,
+ generic_pnp_mapalloc, isic_attach_Dyn },
+#endif
+#ifdef ISICPNP_SIEMENS_ISURF2
+ { "SIE0020", "Siemens I-Surf 2.0 PnP", CARD_TYPEP_SIE_ISURF2,
+ generic_pnp_mapalloc, isic_attach_siemens_isurf },
+#endif
+};
+#define NUM_DESCRIPTIONS (sizeof(isapnp_isic_descriptions)/sizeof(isapnp_isic_descriptions[0]))
+
+/*
+ * Probe card
+ */
+static int
+#ifdef __BROKEN_INDIRECT_CONFIG
+isapnp_isic_probe(parent, match, aux)
+#else
+isapnp_isic_probe(parent, cf, aux)
+#endif
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *cf;
+#endif
+ void *aux;
+{
+ struct isapnp_attach_args *ipa = aux;
+ const struct isapnp_isic_card_desc *desc = isapnp_isic_descriptions;
+ int i;
+
+ for (i = 0; i < NUM_DESCRIPTIONS; i++, desc++)
+ if (strcmp(ipa->ipa_devlogic, desc->devlogic) == 0)
+ return 1;
+
+ return 0;
+}
+
+
+/*---------------------------------------------------------------------------*
+ * card independend attach for ISA P&P cards
+ *---------------------------------------------------------------------------*/
+
+/* parameter and format for message producing e.g. "isic0: " */
+
+#ifdef __FreeBSD__
+#define ISIC_FMT "isic%d: "
+#define ISIC_PARM dev->id_unit
+#define TERMFMT " "
+#else
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+#endif
+
+static void
+isapnp_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ struct l1_softc *sc = (void *)self;
+ struct isapnp_attach_args *ipa = aux;
+ const struct isapnp_isic_card_desc *desc = isapnp_isic_descriptions;
+ int i;
+
+ for (i = 0; i < NUM_DESCRIPTIONS; i++, desc++)
+ if (strcmp(ipa->ipa_devlogic, desc->devlogic) == 0)
+ break;
+ if (i >= NUM_DESCRIPTIONS)
+ panic("could not identify isic PnP device");
+
+ /* setup parameters */
+ sc->sc_cardtyp = desc->card_type;
+ sc->sc_unit = sc->sc_dev.dv_unit;
+ sc->sc_irq = ipa->ipa_irq[0].num;
+ desc->allocmaps(ipa, sc);
+
+ /* announce card name */
+ printf(": %s\n", desc->name);
+
+ /* establish interrupt handler */
+ if (isa_intr_establish(ipa->ipa_ic, ipa->ipa_irq[0].num, IST_EDGE,
+ IPL_NET, isicintr, sc) == NULL)
+ printf("%s: couldn't establish interrupt handler\n",
+ sc->sc_dev.dv_xname);
+
+ /* init card */
+ l1_sc[sc->sc_unit] = sc;
+ desc->attach(sc);
+
+ /* announce chip versions */
+ sc->sc_isac_version = 0;
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return;
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return;
+ break;
+ };
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+ callout_init(&sc->sc_T3_callout);
+ callout_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce chip versions */
+
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+}
+
+static void
+generic_pnp_mapalloc(struct isapnp_attach_args *ipa, struct l1_softc *sc)
+{
+ sc->sc_num_mappings = 1; /* most cards have just one mapping */
+ MALLOC_MAPS(sc); /* malloc the maps */
+ sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */
+ sc->sc_maps[0].h = ipa->ipa_io[0].h;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+}
+
+#ifdef ISICPNP_DRN_NGO
+static void
+ngo_pnp_mapalloc(struct isapnp_attach_args *ipa, struct l1_softc *sc)
+{
+ sc->sc_num_mappings = 2; /* one data, one address mapping */
+ MALLOC_MAPS(sc); /* malloc the maps */
+ sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */
+ sc->sc_maps[0].h = ipa->ipa_io[0].h;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+ sc->sc_maps[1].t = ipa->ipa_iot;
+ sc->sc_maps[1].h = ipa->ipa_io[1].h;
+ sc->sc_maps[1].size = 0;
+}
+#endif
+
+#if defined(ISICPNP_CRTX_S0_P) || defined(ISICPNP_TEL_S0_16_3_P)
+static void
+tls_pnp_mapalloc(struct isapnp_attach_args *ipa, struct l1_softc *sc)
+{
+ sc->sc_num_mappings = 4; /* config, isac, 2 * hscx */
+ MALLOC_MAPS(sc); /* malloc the maps */
+ sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */
+ sc->sc_maps[0].h = ipa->ipa_io[0].h;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+ sc->sc_maps[1].t = ipa->ipa_iot;
+ sc->sc_maps[1].h = ipa->ipa_io[0].h;
+ sc->sc_maps[1].size = 0;
+ sc->sc_maps[1].offset = - 0x20;
+ sc->sc_maps[2].t = ipa->ipa_iot;
+ sc->sc_maps[2].offset = - 0x20;
+ sc->sc_maps[2].h = ipa->ipa_io[1].h;
+ sc->sc_maps[2].size = 0;
+ sc->sc_maps[3].t = ipa->ipa_iot;
+ sc->sc_maps[3].offset = 0;
+ sc->sc_maps[3].h = ipa->ipa_io[1].h;
+ sc->sc_maps[3].size = 0;
+}
+#endif
diff --git a/sys/dev/microcode/daic/Makefile b/sys/dev/microcode/daic/Makefile
new file mode 100644
index 00000000000..ef250072b5b
--- /dev/null
+++ b/sys/dev/microcode/daic/Makefile
@@ -0,0 +1,31 @@
+# The Microcode for the Eicon.Diehl active ISDN cards comes in two parts.
+# A tiny bootstrap loader delivered by Diehl as "dnload.bin" and a
+# D-channel protocol specific file, e.g. "te_etsi.sx" for the SX card
+# running E-DSS1.
+# We can not deliver either of these files. The user is assumed to use
+# the ones distributed with his card or download the newest version from
+# http://www.diehl.de.
+# The bootstrap loader is compiled into the kernel, as it is needed to
+# identify the card. The protocol specific part is later downloaded by
+# the ISDN management daemon.
+
+.NOPATH: dnload.bin
+.if exists(dnload.bin)
+# Real part - the bootstrap image is available. We convert it into a
+# static byte array via the "gendnloadh" shell script.
+dnload.h: dnload.bin
+ @rm -f dnload.h
+ @sh ./gendnloadh
+.else
+# Fake part - user did not copy the necessary file here. Compilation will
+# fail with an error explaining his fault.
+dnload.h: dnload.h-dist
+ cp dnload.h-dist dnload.h
+.endif
+
+clean:
+ rm -f dnload.h
+
+cleandir: clean
+
+includes: dnload.h
diff --git a/sys/dev/microcode/daic/dnload.h-dist b/sys/dev/microcode/daic/dnload.h-dist
new file mode 100644
index 00000000000..11f3fbf6217
--- /dev/null
+++ b/sys/dev/microcode/daic/dnload.h-dist
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1997,2001 Martin Husemann <martin@duskware.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * File: dnload.h
+ * This file is usualy generated from the binary bootstrap image
+ * delivered with the ISDN controller. Just copy the file "dnload.bin"
+ * to this directory, run "make" here and the kernel will compile fine.
+ * If you don't have this software, download the newest version of
+ * the DOS driver software for your card from http://www.diehl.de,
+ * extract the archive and copy "dnload.bin" here.
+ */
+
+#error "You did not copy 'dnload.bin' to sys/dev/microcode/daic and ran 'make' there"
+
+/* ------------------------------------------------------------------------- */
+static u_int8_t dnload[] = {
+ 0
+};
+
+/* ------------------------------------------------------------------------- */
diff --git a/sys/dev/microcode/daic/gendnloadh b/sys/dev/microcode/daic/gendnloadh
new file mode 100644
index 00000000000..29e8b1b8d00
--- /dev/null
+++ b/sys/dev/microcode/daic/gendnloadh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# Copyright (c) 1997,2001 Martin Husemann <martin@duskware.de>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. The name of the author may not be used to endorse or promote products
+# derived from this software withough specific prior written permission
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+echo "Generating dnload.h from dnload.bin"
+
+cat << EOF > dnload.h
+/*
+ * File: dnload.h
+ * Generated from: `ls -lT dnload.bin | awk '{print $10, $6, $7, $8, $9}'`
+ * By: `id -un`@`hostname`, `date`
+ *
+ * DO NOT EDIT THIS FILE!
+ */
+
+/* ------------------------------------------------------------------------- */
+static u_int8_t dnload[] = {
+EOF
+
+hexdump -v -e '" /* %04.4_ax */\t" 8/1 "0x%02x, " "\n"' -s 0x200 dnload.bin >> dnload.h
+
+cat << EOF >> dnload.h
+ 0
+};
+
+/* ------------------------------------------------------------------------- */
+EOF
diff --git a/sys/dev/pci/i4b_avm_fritz_pci.c b/sys/dev/pci/i4b_avm_fritz_pci.c
new file mode 100644
index 00000000000..b2ba7368801
--- /dev/null
+++ b/sys/dev/pci/i4b_avm_fritz_pci.c
@@ -0,0 +1,1756 @@
+/*
+ * Copyright (c) 1999 Gary Jennejohn. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ * a lot of code was borrowed from i4b_bchan.c and i4b_hscx.c
+ *---------------------------------------------------------------------------
+ *
+ * Fritz!Card PCI specific routines for isic driver
+ * ------------------------------------------------
+ *
+ * $Id: i4b_avm_fritz_pci.c,v 1.1.1.1 2001/01/05 12:50:20 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:58 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicpci.h"
+#ifdef ISICPCI_AVM_A1
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <pci/pcivar.h> /* for pcici_t */
+#if __FreeBSD__ < 3
+#include <pci/pcireg.h>
+#include <pci/pcibus.h>
+#endif /* __FreeBSD__ < 3 */
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#ifndef __FreeBSD__
+
+#include <dev/pci/pci_isic.h>
+
+/* PCI config map to use (only one in this driver) */
+#define FRITZPCI_PORT0_MAPOFF PCI_MAPREG_START+4
+
+#endif
+
+/* prototypes */
+static void avma1pp_disable(struct l1_softc *);
+static int isic_hscx_fifo(l1_bchan_state_t *chan, struct l1_softc *sc);
+
+#ifdef __FreeBSD__
+
+static void avma1pp_intr(struct l1_softc *);
+static void avma1pp_disable(struct l1_softc *);
+void avma1pp_map_int(pcici_t , void *, unsigned *);
+static void hscx_write_reg(int, u_int, u_int, struct l1_softc *);
+static u_char hscx_read_reg(int, u_int, struct l1_softc *);
+static u_int hscx_read_reg_int(int, u_int, struct l1_softc *);
+static void hscx_read_fifo(int, void *, size_t, struct l1_softc *);
+static void hscx_write_fifo(int, const void *, size_t, struct l1_softc *);
+static void avma1pp_hscx_int_handler(struct l1_softc *);
+static void avma1pp_hscx_intr(int, u_int, struct l1_softc *);
+static void avma1pp_init_linktab(struct l1_softc *);
+static void avma1pp_bchannel_setup(int, int, int, int);
+static void avma1pp_bchannel_start(int, int);
+static void avma1pp_hscx_init(struct l1_softc *, int, int);
+static void avma1pp_bchannel_stat(int, int, bchan_statistics_t *);
+static void avma1pp_set_linktab(int, int, drvr_link_t *);
+static isdn_link_t * avma1pp_ret_linktab(int, int);
+int isic_attach_avma1pp(int, u_int, u_int);
+extern void isicintr_sc(struct l1_softc *);
+
+#else
+
+static int avma1pp_intr(void*);
+static void avma1pp_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size);
+static void avma1pp_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size);
+static void avma1pp_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data);
+static u_int8_t avma1pp_read_reg(struct l1_softc *sc, int what, bus_size_t offs);
+static void hscx_write_fifo(int chan, const void *buf, size_t len, struct l1_softc *sc);
+static void hscx_read_fifo(int chan, void *buf, size_t len, struct l1_softc *sc);
+static void hscx_write_reg(int chan, u_int off, u_int val, struct l1_softc *sc);
+static u_char hscx_read_reg(int chan, u_int off, struct l1_softc *sc);
+static u_int hscx_read_reg_int(int chan, u_int off, struct l1_softc *sc);
+static void avma1pp_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp);
+static void avma1pp_map_int(struct pci_l1_softc *sc, struct pci_attach_args *pa);
+static void avma1pp_bchannel_setup(int unit, int h_chan, int bprot, int activate);
+static void avma1pp_init_linktab(struct l1_softc *);
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM PCI Fritz!Card special registers
+ *---------------------------------------------------------------------------*/
+
+/*
+ * register offsets from i/o base
+ */
+#define STAT0_OFFSET 0x02
+#define STAT1_OFFSET 0x03
+#define ADDR_REG_OFFSET 0x04
+/*#define MODREG_OFFSET 0x06
+#define VERREG_OFFSET 0x07*/
+
+/* these 2 are used to select an ISAC register set */
+#define ISAC_LO_REG_OFFSET 0x04
+#define ISAC_HI_REG_OFFSET 0x06
+
+/* offset higher than this goes to the HI register set */
+#define MAX_LO_REG_OFFSET 0x2f
+
+/* mask for the offset */
+#define ISAC_REGSET_MASK 0x0f
+
+/* the offset from the base to the ISAC registers */
+#define ISAC_REG_OFFSET 0x10
+
+/* the offset from the base to the ISAC FIFO */
+#define ISAC_FIFO 0x02
+
+/* not really the HSCX, but sort of */
+#define HSCX_FIFO 0x00
+#define HSCX_STAT 0x04
+
+/*
+ * AVM PCI Status Latch 0 read only bits
+ */
+#define ASL_IRQ_ISAC 0x01 /* ISAC interrupt, active low */
+#define ASL_IRQ_HSCX 0x02 /* HSX interrupt, active low */
+#define ASL_IRQ_TIMER 0x04 /* Timer interrupt, active low */
+#define ASL_IRQ_BCHAN ASL_IRQ_HSCX
+/* actually active LOW */
+#define ASL_IRQ_Pending (ASL_IRQ_ISAC | ASL_IRQ_HSCX | ASL_IRQ_TIMER)
+
+/*
+ * AVM Status Latch 0 write only bits
+ */
+#define ASL_RESET_ALL 0x01 /* reset siemens IC's, active 1 */
+#define ASL_TIMERDISABLE 0x02 /* active high */
+#define ASL_TIMERRESET 0x04 /* active high */
+#define ASL_ENABLE_INT 0x08 /* active high */
+#define ASL_TESTBIT 0x10 /* active high */
+
+/*
+ * AVM Status Latch 1 write only bits
+ */
+#define ASL1_INTSEL 0x0f /* active high */
+#define ASL1_ENABLE_IOM 0x80 /* active high */
+
+/*
+ * "HSCX" mode bits
+ */
+#define HSCX_MODE_ITF_FLG 0x01
+#define HSCX_MODE_TRANS 0x02
+#define HSCX_MODE_CCR_7 0x04
+#define HSCX_MODE_CCR_16 0x08
+#define HSCX_MODE_TESTLOOP 0x80
+
+/*
+ * "HSCX" status bits
+ */
+#define HSCX_STAT_RME 0x01
+#define HSCX_STAT_RDO 0x10
+#define HSCX_STAT_CRCVFRRAB 0x0E
+#define HSCX_STAT_CRCVFR 0x06
+#define HSCX_STAT_RML_MASK 0x3f00
+
+/*
+ * "HSCX" interrupt bits
+ */
+#define HSCX_INT_XPR 0x80
+#define HSCX_INT_XDU 0x40
+#define HSCX_INT_RPR 0x20
+#define HSCX_INT_MASK 0xE0
+
+/*
+ * "HSCX" command bits
+ */
+#define HSCX_CMD_XRS 0x80
+#define HSCX_CMD_XME 0x01
+#define HSCX_CMD_RRS 0x20
+#define HSCX_CMD_XML_MASK 0x3f00
+
+/*
+ * Commands and parameters are sent to the "HSCX" as a long, but the
+ * fields are handled as bytes.
+ *
+ * The long contains:
+ * (prot << 16)|(txl << 8)|cmd
+ *
+ * where:
+ * prot = protocol to use
+ * txl = transmit length
+ * cmd = the command to be executed
+ *
+ * The fields are defined as u_char in struct l1_softc.
+ *
+ * Macro to coalesce the byte fields into a u_int
+ */
+#define AVMA1PPSETCMDLONG(f) (f) = ((sc->avma1pp_cmd) | (sc->avma1pp_txl << 8) \
+ | (sc->avma1pp_prot << 16))
+
+#ifdef __FreeBSD__
+
+/* "fake" addresses for the non-existent HSCX */
+/* note: the unit number is in the lower byte for both the ISAC and "HSCX" */
+#define HSCX0FAKE 0xfa000 /* read: fake0 */
+#define HSCX1FAKE 0xfa100 /* read: fake1 */
+#define IS_HSCX_MASK 0xfff00
+
+#endif /* __FreeBSD__ */
+
+/*
+ * to prevent deactivating the "HSCX" when both channels are active we
+ * define an HSCX_ACTIVE flag which is or'd into the channel's state
+ * flag in avma1pp_bchannel_setup upon active and cleared upon deactivation.
+ * It is set high to allow room for new flags.
+ */
+#define HSCX_AVMA1PP_ACTIVE 0x1000
+
+/*---------------------------------------------------------------------------*
+ * AVM read fifo routines
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+static void
+avma1pp_read_fifo(void *buf, const void *base, size_t len)
+{
+ int unit;
+ struct l1_softc *sc;
+
+ unit = (int)base & 0xff;
+ sc = &l1_sc[unit];
+
+ /* check whether the target is an HSCX */
+ if (((int)base & IS_HSCX_MASK) == HSCX0FAKE)
+ {
+ hscx_read_fifo(0, buf, len, sc);
+ return;
+ }
+ if (((int)base & IS_HSCX_MASK) == HSCX1FAKE)
+ {
+ hscx_read_fifo(1, buf, len, sc);
+ return;
+ }
+ /* tell the board to access the ISAC fifo */
+ outb(sc->sc_port + ADDR_REG_OFFSET, ISAC_FIFO);
+ insb(sc->sc_port + ISAC_REG_OFFSET, (u_char *)buf, len);
+}
+
+static void
+hscx_read_fifo(int chan, void *buf, size_t len, struct l1_softc *sc)
+{
+ u_int *ip;
+ size_t cnt;
+
+ outl(sc->sc_port + ADDR_REG_OFFSET, chan);
+ ip = (u_int *)buf;
+ cnt = 0;
+ /* what if len isn't a multiple of sizeof(int) and buf is */
+ /* too small ???? */
+ while (cnt < len)
+ {
+ *ip++ = inl(sc->sc_port + ISAC_REG_OFFSET);
+ cnt += 4;
+ }
+}
+
+#else
+
+static void
+avma1pp_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, ISAC_FIFO);
+ bus_space_read_multi_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ hscx_read_fifo(0, buf, size, sc);
+ break;
+ case ISIC_WHAT_HSCXB:
+ hscx_read_fifo(1, buf, size, sc);
+ break;
+ }
+}
+
+static void
+hscx_read_fifo(int chan, void *buf, size_t len, struct l1_softc *sc)
+{
+ u_int32_t *ip;
+ size_t cnt;
+
+ bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, chan);
+ ip = (u_int32_t *)buf;
+ cnt = 0;
+ /* what if len isn't a multiple of sizeof(int) and buf is */
+ /* too small ???? */
+ while (cnt < len)
+ {
+ *ip++ = bus_space_read_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET);
+ cnt += 4;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1pp_write_fifo(void *base, const void *buf, size_t len)
+{
+ int unit;
+ struct l1_softc *sc;
+
+ unit = (int)base & 0xff;
+ sc = &l1_sc[unit];
+
+ /* check whether the target is an HSCX */
+ if (((int)base & IS_HSCX_MASK) == HSCX0FAKE)
+ {
+ hscx_write_fifo(0, buf, len, sc);
+ return;
+ }
+ if (((int)base & IS_HSCX_MASK) == HSCX1FAKE)
+ {
+ hscx_write_fifo(1, buf, len, sc);
+ return;
+ }
+ /* tell the board to use the ISAC fifo */
+ outb(sc->sc_port + ADDR_REG_OFFSET, ISAC_FIFO);
+ outsb(sc->sc_port + ISAC_REG_OFFSET, (const u_char *)buf, len);
+}
+
+static void
+hscx_write_fifo(int chan, const void *buf, size_t len, struct l1_softc *sc)
+{
+ register const u_int *ip;
+ register size_t cnt;
+ l1_bchan_state_t *Bchan = &sc->sc_chan[chan];
+
+ sc->avma1pp_cmd &= ~HSCX_CMD_XME;
+ sc->avma1pp_txl = 0;
+ if (Bchan->out_mbuf_cur == NULL)
+ {
+ if (Bchan->bprot != BPROT_NONE)
+ sc->avma1pp_cmd |= HSCX_CMD_XME;
+ }
+ if (len != sc->sc_bfifolen)
+ sc->avma1pp_txl = len;
+
+ cnt = 0; /* borrow cnt */
+ AVMA1PPSETCMDLONG(cnt);
+ hscx_write_reg(chan, HSCX_STAT, cnt, sc);
+
+ ip = (const u_int *)buf;
+ cnt = 0;
+ while (cnt < len)
+ {
+ outl(sc->sc_port + ISAC_REG_OFFSET, *ip++);
+ cnt += 4;
+ }
+}
+
+#else
+
+static void
+avma1pp_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, ISAC_FIFO);
+ bus_space_write_multi_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ hscx_write_fifo(0, buf, size, sc);
+ break;
+ case ISIC_WHAT_HSCXB:
+ hscx_write_fifo(1, buf, size, sc);
+ break;
+ }
+}
+
+static void
+hscx_write_fifo(int chan, const void *buf, size_t len, struct l1_softc *sc)
+{
+ u_int32_t *ip;
+ size_t cnt;
+ l1_bchan_state_t *Bchan = &sc->sc_chan[chan];
+
+ sc->avma1pp_cmd &= ~HSCX_CMD_XME;
+ sc->avma1pp_txl = 0;
+ if (Bchan->out_mbuf_cur == NULL)
+ {
+ if (Bchan->bprot != BPROT_NONE)
+ sc->avma1pp_cmd |= HSCX_CMD_XME;
+ }
+ if (len != sc->sc_bfifolen)
+ sc->avma1pp_txl = len;
+
+ cnt = 0; /* borrow cnt */
+ AVMA1PPSETCMDLONG(cnt);
+ hscx_write_reg(chan, HSCX_STAT, cnt, sc);
+
+ ip = (u_int32_t *)buf;
+ cnt = 0;
+ while (cnt < len)
+ {
+ bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET, *ip);
+ ip++;
+ cnt += 4;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1pp_write_reg(u_char *base, u_int offset, u_int v)
+{
+ int unit;
+ struct l1_softc *sc;
+ u_char reg_bank;
+
+ unit = (int)base & 0xff;
+ sc = &l1_sc[unit];
+
+ /* check whether the target is an HSCX */
+ if (((int)base & IS_HSCX_MASK) == HSCX0FAKE)
+ {
+ hscx_write_reg(0, offset, v, sc);
+ return;
+ }
+ if (((int)base & IS_HSCX_MASK) == HSCX1FAKE)
+ {
+ hscx_write_reg(1, offset, v, sc);
+ return;
+ }
+ /* must be the ISAC */
+ reg_bank = (offset > MAX_LO_REG_OFFSET) ? ISAC_HI_REG_OFFSET:ISAC_LO_REG_OFFSET;
+#ifdef AVMA1PCI_DEBUG
+ printf("write_reg bank %d off %d.. ", reg_bank, offset);
+#endif
+ /* set the register bank */
+ outb(sc->sc_port + ADDR_REG_OFFSET, reg_bank);
+ outb(sc->sc_port + ISAC_REG_OFFSET + (offset & ISAC_REGSET_MASK), v);
+}
+
+static void
+hscx_write_reg(int chan, u_int off, u_int val, struct l1_softc *sc)
+{
+ /* HACK */
+ if (off == H_MASK)
+ return;
+ /* point at the correct channel */
+ outl(sc->sc_port + ADDR_REG_OFFSET, chan);
+ outl(sc->sc_port + ISAC_REG_OFFSET + off, val);
+}
+
+#else
+
+static void
+avma1pp_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ u_char reg_bank;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ reg_bank = (offs > MAX_LO_REG_OFFSET) ? ISAC_HI_REG_OFFSET:ISAC_LO_REG_OFFSET;
+#ifdef AVMA1PCI_DEBUG
+ printf("write_reg bank %d off %ld.. ", (int)reg_bank, (long)offs);
+#endif
+ /* set the register bank */
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, reg_bank);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET + (offs & ISAC_REGSET_MASK), data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ hscx_write_reg(0, offs, data, sc);
+ break;
+ case ISIC_WHAT_HSCXB:
+ hscx_write_reg(1, offs, data, sc);
+ break;
+ }
+}
+
+static void
+hscx_write_reg(int chan, u_int off, u_int val, struct l1_softc *sc)
+{
+ /* HACK */
+ if (off == H_MASK)
+ return;
+ /* point at the correct channel */
+ bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, chan);
+ bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET + off, val);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+avma1pp_read_reg(u_char *base, u_int offset)
+{
+ int unit;
+ struct l1_softc *sc;
+ u_char reg_bank;
+
+ unit = (int)base & 0xff;
+ sc = &l1_sc[unit];
+
+ /* check whether the target is an HSCX */
+ if (((int)base & IS_HSCX_MASK) == HSCX0FAKE)
+ return(hscx_read_reg(0, offset, sc));
+ if (((int)base & IS_HSCX_MASK) == HSCX1FAKE)
+ return(hscx_read_reg(1, offset, sc));
+ /* must be the ISAC */
+ reg_bank = (offset > MAX_LO_REG_OFFSET) ? ISAC_HI_REG_OFFSET:ISAC_LO_REG_OFFSET;
+#ifdef AVMA1PCI_DEBUG
+ printf("read_reg bank %d off %d.. ", reg_bank, offset);
+#endif
+ /* set the register bank */
+ outb(sc->sc_port + ADDR_REG_OFFSET, reg_bank);
+ return(inb(sc->sc_port + ISAC_REG_OFFSET +
+ (offset & ISAC_REGSET_MASK)));
+}
+#else
+static u_int8_t
+avma1pp_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ u_char reg_bank;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ reg_bank = (offs > MAX_LO_REG_OFFSET) ? ISAC_HI_REG_OFFSET:ISAC_LO_REG_OFFSET;
+#ifdef AVMA1PCI_DEBUG
+ printf("read_reg bank %d off %ld.. ", (int)reg_bank, (long)offs);
+#endif
+ /* set the register bank */
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, reg_bank);
+ return(bus_space_read_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET +
+ (offs & ISAC_REGSET_MASK)));
+ case ISIC_WHAT_HSCXA:
+ return hscx_read_reg(0, offs, sc);
+ case ISIC_WHAT_HSCXB:
+ return hscx_read_reg(1, offs, sc);
+ }
+ return 0;
+}
+#endif
+
+static u_char
+hscx_read_reg(int chan, u_int off, struct l1_softc *sc)
+{
+ return(hscx_read_reg_int(chan, off, sc) & 0xff);
+}
+
+/*
+ * need to be able to return an int because the RBCH is in the 2nd
+ * byte.
+ */
+static u_int
+hscx_read_reg_int(int chan, u_int off, struct l1_softc *sc)
+{
+ /* HACK */
+ if (off == H_ISTA)
+ return(0);
+ /* point at the correct channel */
+#ifdef __FreeBSD__
+ outl(sc->sc_port + ADDR_REG_OFFSET, chan);
+ return(inl(sc->sc_port + ISAC_REG_OFFSET + off));
+#else
+ bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, chan);
+ return(bus_space_read_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET + off));
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_avma1pp - attach Fritz!Card PCI
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_avma1pp(int unit, u_int iobase1, u_int iobase2)
+{
+ struct l1_softc *sc = &l1_sc[unit];
+ u_int v;
+
+ /* check max unit range */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for AVM FRITZ/PCI!\n",
+ unit, unit);
+ return(0);
+ }
+ sc->sc_unit = unit;
+
+ /* setup iobase */
+
+ if((iobase1 <= 0) || (iobase1 > 0xffff))
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for AVM FRITZ/PCI!\n",
+ unit, iobase1);
+ return(0);
+ }
+ sc->sc_port = iobase1;
+
+ /* the ISAC lives at offset 0x10, but we can't use that. */
+ /* instead, put the unit number into the lower byte - HACK */
+ sc->sc_isac = (caddr_t)((int)(iobase1 & ~0xff) + unit);
+
+ /* this thing doesn't have an HSCX, so fake the base addresses */
+ /* put the unit number into the lower byte - HACK */
+ HSCX_A_BASE = (caddr_t)(HSCX0FAKE + unit);
+ HSCX_B_BASE = (caddr_t)(HSCX1FAKE + unit);
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1pp_read_reg;
+ sc->writereg = avma1pp_write_reg;
+
+ sc->readfifo = avma1pp_read_fifo;
+ sc->writefifo = avma1pp_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_AVMA1PCI;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ /* set up some other miscellaneous things */
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* reset the card */
+ /* the Linux driver does this to clear any pending ISAC interrupts */
+ v = 0;
+ v = ISAC_READ(I_STAR);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_STAR %x...", v);
+#endif
+ v = ISAC_READ(I_MODE);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_MODE %x...", v);
+#endif
+ v = ISAC_READ(I_ADF2);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_ADF2 %x...", v);
+#endif
+ v = ISAC_READ(I_ISTA);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_ISTA %x...", v);
+#endif
+ if (v & ISAC_ISTA_EXI)
+ {
+ v = ISAC_READ(I_EXIR);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_EXIR %x...", v);
+#endif
+ }
+ v = ISAC_READ(I_CIRR);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_CIRR %x...", v);
+#endif
+ ISAC_WRITE(I_MASK, 0xff);
+ /* the Linux driver does this to clear any pending HSCX interrupts */
+ v = hscx_read_reg_int(0, HSCX_STAT, sc);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: 0 HSCX_STAT %x...", v);
+#endif
+ v = hscx_read_reg_int(1, HSCX_STAT, sc);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: 1 HSCX_STAT %x\n", v);
+#endif
+
+ outb(sc->sc_port + STAT0_OFFSET, ASL_RESET_ALL|ASL_TIMERDISABLE);
+ DELAY(SEC_DELAY/100); /* 10 ms */
+ outb(sc->sc_port + STAT0_OFFSET, ASL_TIMERRESET|ASL_ENABLE_INT|ASL_TIMERDISABLE);
+ DELAY(SEC_DELAY/100); /* 10 ms */
+#ifdef AVMA1PCI_DEBUG
+ outb(sc->sc_port + STAT1_OFFSET, ASL1_ENABLE_IOM|sc->sc_irq);
+ DELAY(SEC_DELAY/100); /* 10 ms */
+ printf("after reset: S1 %#x\n", inb(sc->sc_port + STAT1_OFFSET));
+
+ v = inl(sc->sc_port);
+ printf("isic_attach_avma1pp: v %#x\n", v);
+#endif
+
+ /* from here to the end would normally be done in isic_pciattach */
+
+ printf("isic%d: ISAC %s (IOM-%c)\n", unit,
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+
+ /* init the ISAC */
+ isic_isac_init(sc);
+
+ /* init the "HSCX" */
+ avma1pp_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ avma1pp_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* can't use the normal B-Channel stuff */
+ avma1pp_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ callout_handle_init(&sc->sc_T3_callout);
+ callout_handle_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ return(1);
+}
+
+#else
+
+void
+isic_attach_fritzPci(struct pci_l1_softc *psc, struct pci_attach_args *pa)
+{
+ struct l1_softc *sc = &psc->sc_isic;
+ u_int v;
+
+ l1_sc[sc->sc_unit] = sc; /* XXX - hack! */
+
+ /* setup io mappings */
+ sc->sc_num_mappings = 1;
+ MALLOC_MAPS(sc);
+ sc->sc_maps[0].size = 0;
+ if (pci_mapreg_map(pa, FRITZPCI_PORT0_MAPOFF, PCI_MAPREG_TYPE_IO, 0,
+ &sc->sc_maps[0].t, &sc->sc_maps[0].h, NULL, NULL)) {
+ printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1pp_read_reg;
+ sc->writereg = avma1pp_write_reg;
+
+ sc->readfifo = avma1pp_read_fifo;
+ sc->writefifo = avma1pp_write_fifo;
+
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_AVMA1PCI;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ /* this is no IPAC based card */
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* init the card */
+ /* the Linux driver does this to clear any pending ISAC interrupts */
+ /* see if it helps any - XXXX */
+ v = 0;
+ v = ISAC_READ(I_STAR);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_STAR %x...", v);
+#endif
+ v = ISAC_READ(I_MODE);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_MODE %x...", v);
+#endif
+ v = ISAC_READ(I_ADF2);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_ADF2 %x...", v);
+#endif
+ v = ISAC_READ(I_ISTA);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_ISTA %x...", v);
+#endif
+ if (v & ISAC_ISTA_EXI)
+ {
+ v = ISAC_READ(I_EXIR);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_EXIR %x...", v);
+#endif
+ }
+ v = ISAC_READ(I_CIRR);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: I_CIRR %x...", v);
+#endif
+ ISAC_WRITE(I_MASK, 0xff);
+ /* the Linux driver does this to clear any pending HSCX interrupts */
+ v = hscx_read_reg_int(0, HSCX_STAT, sc);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: 0 HSCX_STAT %x...", v);
+#endif
+ v = hscx_read_reg_int(1, HSCX_STAT, sc);
+#ifdef AVMA1PCI_DEBUG
+ printf("avma1pp_attach: 1 HSCX_STAT %x\n", v);
+#endif
+
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, ASL_RESET_ALL|ASL_TIMERDISABLE);
+ DELAY(SEC_DELAY/100); /* 10 ms */
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, ASL_TIMERRESET|ASL_ENABLE_INT|ASL_TIMERDISABLE);
+ DELAY(SEC_DELAY/100); /* 10 ms */
+#ifdef AVMA1PCI_DEBUG
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT1_OFFSET, ASL1_ENABLE_IOM|sc->sc_irq);
+ DELAY(SEC_DELAY/100); /* 10 ms */
+ v = bus_space_read_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT1_OFFSET);
+ printf("after reset: S1 %#x\n", v);
+
+ v = bus_space_read_4(sc->sc_maps[0].t, sc->sc_maps[0].h, 0);
+ printf("isic_attach_avma1pp: v %#x\n", v);
+#endif
+
+ /* setup i4b infrastructure (have to roll our own here) */
+
+ /* sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03; */
+ printf("%s: ISAC %s (IOM-%c)\n", sc->sc_dev.dv_xname,
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+
+ /* init the ISAC */
+ isic_isac_init(sc);
+
+ /* init the "HSCX" */
+ avma1pp_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ avma1pp_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* can't use the normal B-Channel stuff */
+ avma1pp_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* setup interrupt mapping */
+ avma1pp_map_int(psc, pa);
+}
+
+#endif
+
+/*
+ * this is the real interrupt routine
+ */
+static void
+avma1pp_hscx_intr(int h_chan, u_int stat, struct l1_softc *sc)
+{
+ register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+ int activity = -1;
+ u_int param = 0;
+
+ NDBGL1(L1_H_IRQ, "%#x", stat);
+
+ if((stat & HSCX_INT_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
+ {
+ chan->stat_XDU++;
+ NDBGL1(L1_H_XFRERR, "xmit data underrun");
+ /* abort the transmission */
+ sc->avma1pp_txl = 0;
+ sc->avma1pp_cmd |= HSCX_CMD_XRS;
+ AVMA1PPSETCMDLONG(param);
+ hscx_write_reg(h_chan, HSCX_STAT, param, sc);
+ sc->avma1pp_cmd &= ~HSCX_CMD_XRS;
+ AVMA1PPSETCMDLONG(param);
+ hscx_write_reg(h_chan, HSCX_STAT, param, sc);
+
+ if (chan->out_mbuf_head != NULL) /* don't continue to transmit this buffer */
+ {
+ i4b_Bfreembuf(chan->out_mbuf_head);
+ chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
+ }
+ }
+
+ /*
+ * The following is based on examination of the Linux driver.
+ *
+ * The logic here is different than with a "real" HSCX; all kinds
+ * of information (interrupt/status bits) are in stat.
+ * HSCX_INT_RPR indicates a receive interrupt
+ * HSCX_STAT_RDO indicates an overrun condition, abort -
+ * otherwise read the bytes ((stat & HSCX_STZT_RML_MASK) >> 8)
+ * HSCX_STAT_RME indicates end-of-frame and apparently any
+ * CRC/framing errors are only reported in this state.
+ * if ((stat & HSCX_STAT_CRCVFRRAB) != HSCX_STAT_CRCVFR)
+ * CRC/framing error
+ */
+
+ if(stat & HSCX_INT_RPR)
+ {
+ register int fifo_data_len;
+ int error = 0;
+ /* always have to read the FIFO, so use a scratch buffer */
+ u_char scrbuf[HSCX_FIFO_LEN];
+
+ if(stat & HSCX_STAT_RDO)
+ {
+ chan->stat_RDO++;
+ NDBGL1(L1_H_XFRERR, "receive data overflow");
+ error++;
+ }
+
+ /*
+ * check whether we're receiving data for an inactive B-channel
+ * and discard it. This appears to happen for telephony when
+ * both B-channels are active and one is deactivated. Since
+ * it is not really possible to deactivate the channel in that
+ * case (the ASIC seems to deactivate _both_ channels), the
+ * "deactivated" channel keeps receiving data which can lead
+ * to exhaustion of mbufs and a kernel panic.
+ *
+ * This is a hack, but it's the only solution I can think of
+ * without having the documentation for the ASIC.
+ * GJ - 28 Nov 1999
+ */
+ if (chan->state == HSCX_IDLE)
+ {
+ NDBGL1(L1_H_XFRERR, "toss data from %d", h_chan);
+ error++;
+ }
+
+ fifo_data_len = ((stat & HSCX_STAT_RML_MASK) >> 8);
+
+ if(fifo_data_len == 0)
+ fifo_data_len = sc->sc_bfifolen;
+
+ /* ALWAYS read data from HSCX fifo */
+
+ HSCX_RDFIFO(h_chan, scrbuf, fifo_data_len);
+ chan->rxcount += fifo_data_len;
+
+ /* all error conditions checked, now decide and take action */
+
+ if(error == 0)
+ {
+ if(chan->in_mbuf == NULL)
+ {
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 avma1pp_hscx_intr: RME, cannot allocate mbuf!\n");
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ }
+
+ if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
+ {
+ /* OK to copy the data */
+ bcopy(scrbuf, chan->in_cbptr, fifo_data_len);
+ chan->in_cbptr += fifo_data_len;
+ chan->in_len += fifo_data_len;
+
+ /* setup mbuf data length */
+
+ chan->in_mbuf->m_len = chan->in_len;
+ chan->in_mbuf->m_pkthdr.len = chan->in_len;
+
+ if(sc->sc_trace & TRACE_B_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ if (stat & HSCX_STAT_RME)
+ {
+ if((stat & HSCX_STAT_CRCVFRRAB) == HSCX_STAT_CRCVFR)
+ {
+ (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit);
+ activity = ACT_RX;
+
+ /* mark buffer ptr as unused */
+
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ else
+ {
+ chan->stat_CRC++;
+ NDBGL1(L1_H_XFRERR, "CRC/RAB");
+ if (chan->in_mbuf != NULL)
+ {
+ i4b_Bfreembuf(chan->in_mbuf);
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ }
+ }
+ } /* END enough space in mbuf */
+ else
+ {
+ if(chan->bprot == BPROT_NONE)
+ {
+ /* setup mbuf data length */
+
+ chan->in_mbuf->m_len = chan->in_len;
+ chan->in_mbuf->m_pkthdr.len = chan->in_len;
+
+ if(sc->sc_trace & TRACE_B_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ if(!(isic_hscx_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
+ activity = ACT_RX;
+
+ /* move rx'd data to rx queue */
+
+ if (!(IF_QFULL(&chan->rx_queue)))
+ {
+ IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
+ }
+ else
+ {
+ i4b_Bfreembuf(chan->in_mbuf);
+ }
+
+ /* signal upper layer that data are available */
+ (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit);
+
+ /* alloc new buffer */
+
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 avma1pp_hscx_intr: RPF, cannot allocate new mbuf!\n");
+
+ /* setup new data ptr */
+
+ chan->in_cbptr = chan->in_mbuf->m_data;
+
+ /* OK to copy the data */
+ bcopy(scrbuf, chan->in_cbptr, fifo_data_len);
+
+ chan->in_cbptr += fifo_data_len;
+ chan->in_len = fifo_data_len;
+
+ chan->rxcount += fifo_data_len;
+ }
+ else
+ {
+ NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len);
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ }
+ }
+ } /* if(error == 0) */
+ else
+ {
+ /* land here for RDO */
+ if (chan->in_mbuf != NULL)
+ {
+ i4b_Bfreembuf(chan->in_mbuf);
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ sc->avma1pp_txl = 0;
+ sc->avma1pp_cmd |= HSCX_CMD_RRS;
+ AVMA1PPSETCMDLONG(param);
+ hscx_write_reg(h_chan, HSCX_STAT, param, sc);
+ sc->avma1pp_cmd &= ~HSCX_CMD_RRS;
+ AVMA1PPSETCMDLONG(param);
+ hscx_write_reg(h_chan, HSCX_STAT, param, sc);
+ }
+ }
+
+
+ /* transmit fifo empty, new data can be written to fifo */
+
+ if(stat & HSCX_INT_XPR)
+ {
+ /*
+ * for a description what is going on here, please have
+ * a look at isic_bchannel_start() in i4b_bchan.c !
+ */
+
+ NDBGL1(L1_H_IRQ, "unit %d, chan %d - XPR, Tx Fifo Empty!", sc->sc_unit, h_chan);
+
+ if(chan->out_mbuf_cur == NULL) /* last frame is transmitted */
+ {
+ IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
+
+ if(chan->out_mbuf_head == NULL)
+ {
+ chan->state &= ~HSCX_TX_ACTIVE;
+ (*chan->drvr_linktab->bch_tx_queue_empty)(chan->drvr_linktab->unit);
+ }
+ else
+ {
+ chan->state |= HSCX_TX_ACTIVE;
+ chan->out_mbuf_cur = chan->out_mbuf_head;
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+
+ if(chan->bprot == BPROT_NONE)
+ {
+ if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
+ activity = ACT_TX;
+ }
+ else
+ {
+ activity = ACT_TX;
+ }
+ }
+ }
+
+ isic_hscx_fifo(chan, sc);
+ }
+
+ /* call timeout handling routine */
+
+ if(activity == ACT_RX || activity == ACT_TX)
+ (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity);
+}
+
+/*
+ * this is the main routine which checks each channel and then calls
+ * the real interrupt routine as appropriate
+ */
+static void
+avma1pp_hscx_int_handler(struct l1_softc *sc)
+{
+ u_int stat;
+
+ /* has to be a u_int because the byte count is in the 2nd byte */
+ stat = hscx_read_reg_int(0, HSCX_STAT, sc);
+ if (stat & HSCX_INT_MASK)
+ avma1pp_hscx_intr(0, stat, sc);
+ stat = hscx_read_reg_int(1, HSCX_STAT, sc);
+ if (stat & HSCX_INT_MASK)
+ avma1pp_hscx_intr(1, stat, sc);
+}
+
+static void
+avma1pp_disable(struct l1_softc *sc)
+{
+#ifdef __FreeBSD__
+ outb(sc->sc_port + STAT0_OFFSET, ASL_RESET_ALL|ASL_TIMERDISABLE);
+#else
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, ASL_RESET_ALL|ASL_TIMERDISABLE);
+#endif
+}
+
+#ifdef __FreeBSD__
+static void
+avma1pp_intr(struct l1_softc *sc)
+{
+#define OURS /* no return value accumulated */
+#define ISICINTR(sc) isicintr_sc(sc)
+#else
+static int
+avma1pp_intr(void * parm)
+{
+ struct l1_softc *sc = parm;
+ int ret = 0;
+#define OURS ret = 1
+#define ISICINTR(sc) isicintr(sc)
+#endif
+ u_char stat;
+
+#ifdef __FreeBSD__
+ stat = inb(sc->sc_port + STAT0_OFFSET);
+#else
+ stat = bus_space_read_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET);
+#endif
+ NDBGL1(L1_H_IRQ, "stat %x", stat);
+ /* was there an interrupt from this card ? */
+ if ((stat & ASL_IRQ_Pending) == ASL_IRQ_Pending)
+#ifdef __FreeBSD__
+ return; /* no */
+#else
+ return 0; /* no */
+#endif
+ /* interrupts are low active */
+ if (!(stat & ASL_IRQ_TIMER))
+ NDBGL1(L1_H_IRQ, "timer interrupt ???");
+ if (!(stat & ASL_IRQ_HSCX))
+ {
+ NDBGL1(L1_H_IRQ, "HSCX");
+ avma1pp_hscx_int_handler(sc);
+ OURS;
+ }
+ if (!(stat & ASL_IRQ_ISAC))
+ {
+ NDBGL1(L1_H_IRQ, "ISAC");
+ ISICINTR(sc);
+ OURS;
+ }
+#ifndef __FreeBSD__
+ return ret;
+#endif
+}
+
+#ifdef __FreeBSD__
+void
+avma1pp_map_int(pcici_t config_id, void *pisc, unsigned *net_imask)
+{
+ struct l1_softc *sc = (struct l1_softc *)pisc;
+
+#ifdef AVMA1PCI_DEBUG
+ /* may need the irq later */
+#if __FreeBSD__ < 3
+ /* I'd like to call getirq here, but it is static */
+ sc->sc_irq = PCI_INTERRUPT_LINE_EXTRACT(
+ pci_conf_read (config_id, PCI_INTERRUPT_REG));
+
+ if (sc->sc_irq == 0 || sc->sc_irq == 0xff)
+ printf ("avma1pp_map_int:int line register not set by bios\n");
+
+ if (sc->sc_irq >= PCI_MAX_IRQ)
+ printf ("avma1pp_map_int:irq %d out of bounds (must be < %d)\n",
+ sc->sc_irq, PCI_MAX_IRQ);
+#else
+ sc->sc_irq = config_id->intline;
+#endif
+#endif /* AVMA1PCI_DEBUG */
+
+ if(!(pci_map_int(config_id, (void *)avma1pp_intr, sc, net_imask)))
+ {
+ printf("Failed to map interrupt for AVM Fritz!Card PCI\n");
+ /* disable the card */
+ avma1pp_disable(sc);
+ }
+}
+#else
+static void
+avma1pp_map_int(struct pci_l1_softc *psc, struct pci_attach_args *pa)
+{
+ struct l1_softc *sc = &psc->sc_isic;
+ pci_chipset_tag_t pc = pa->pa_pc;
+ pci_intr_handle_t ih;
+ const char *intrstr;
+
+ /* Map and establish the interrupt. */
+ if (pci_intr_map(pa, &ih)) {
+ printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
+ avma1pp_disable(sc);
+ return;
+ }
+ intrstr = pci_intr_string(pc, ih);
+ psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, avma1pp_intr, sc);
+ if (psc->sc_ih == NULL) {
+ printf("%s: couldn't establish interrupt",
+ sc->sc_dev.dv_xname);
+ if (intrstr != NULL)
+ printf(" at %s", intrstr);
+ printf("\n");
+ avma1pp_disable(sc);
+ return;
+ }
+ printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
+}
+#endif
+
+static void
+avma1pp_hscx_init(struct l1_softc *sc, int h_chan, int activate)
+{
+ l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+ u_int param = 0;
+
+ NDBGL1(L1_BCHAN, "unit=%d, channel=%d, %s",
+ sc->sc_unit, h_chan, activate ? "activate" : "deactivate");
+
+ if (activate == 0)
+ {
+ /* only deactivate if both channels are idle */
+ if (sc->sc_chan[HSCX_CH_A].state != HSCX_IDLE ||
+ sc->sc_chan[HSCX_CH_B].state != HSCX_IDLE)
+ {
+ return;
+ }
+ sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS;
+ sc->avma1pp_prot = HSCX_MODE_TRANS;
+ AVMA1PPSETCMDLONG(param);
+ hscx_write_reg(h_chan, HSCX_STAT, param, sc);
+ return;
+ }
+ if(chan->bprot == BPROT_RHDLC)
+ {
+ NDBGL1(L1_BCHAN, "BPROT_RHDLC");
+
+ /* HDLC Frames, transparent mode 0 */
+ sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS;
+ sc->avma1pp_prot = HSCX_MODE_ITF_FLG;
+ AVMA1PPSETCMDLONG(param);
+ hscx_write_reg(h_chan, HSCX_STAT, param, sc);
+ sc->avma1pp_cmd = HSCX_CMD_XRS;
+ AVMA1PPSETCMDLONG(param);
+ hscx_write_reg(h_chan, HSCX_STAT, param, sc);
+ sc->avma1pp_cmd = 0;
+ }
+ else
+ {
+ NDBGL1(L1_BCHAN, "BPROT_NONE??");
+
+ /* Raw Telephony, extended transparent mode 1 */
+ sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS;
+ sc->avma1pp_prot = HSCX_MODE_TRANS;
+ AVMA1PPSETCMDLONG(param);
+ hscx_write_reg(h_chan, HSCX_STAT, param, sc);
+ sc->avma1pp_cmd = HSCX_CMD_XRS;
+ AVMA1PPSETCMDLONG(param);
+ hscx_write_reg(h_chan, HSCX_STAT, param, sc);
+ sc->avma1pp_cmd = 0;
+ }
+}
+
+static void
+avma1pp_bchannel_setup(int unit, int h_chan, int bprot, int activate)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+ l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+
+ int s = SPLI4B();
+
+ if(activate == 0)
+ {
+ /* deactivation */
+ chan->state = HSCX_IDLE;
+ avma1pp_hscx_init(sc, h_chan, activate);
+ }
+
+ NDBGL1(L1_BCHAN, "unit=%d, channel=%d, %s",
+ sc->sc_unit, h_chan, activate ? "activate" : "deactivate");
+
+ /* general part */
+
+ chan->unit = sc->sc_unit; /* unit number */
+ chan->channel = h_chan; /* B channel */
+ chan->bprot = bprot; /* B channel protocol */
+ chan->state = HSCX_IDLE; /* B channel state */
+
+ /* receiver part */
+
+ i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */
+
+ chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+ chan->rxcount = 0; /* reset rx counter */
+
+ i4b_Bfreembuf(chan->in_mbuf); /* clean rx mbuf */
+
+ chan->in_mbuf = NULL; /* reset mbuf ptr */
+ chan->in_cbptr = NULL; /* reset mbuf curr ptr */
+ chan->in_len = 0; /* reset mbuf data len */
+
+ /* transmitter part */
+
+ i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */
+
+ chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+ chan->txcount = 0; /* reset tx counter */
+
+ i4b_Bfreembuf(chan->out_mbuf_head); /* clean tx mbuf */
+
+ chan->out_mbuf_head = NULL; /* reset head mbuf ptr */
+ chan->out_mbuf_cur = NULL; /* reset current mbuf ptr */
+ chan->out_mbuf_cur_ptr = NULL; /* reset current mbuf data ptr */
+ chan->out_mbuf_cur_len = 0; /* reset current mbuf data cnt */
+
+ if(activate != 0)
+ {
+ /* activation */
+ avma1pp_hscx_init(sc, h_chan, activate);
+ chan->state |= HSCX_AVMA1PP_ACTIVE;
+ }
+
+ splx(s);
+}
+
+static void
+avma1pp_bchannel_start(int unit, int h_chan)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+ register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+ int s;
+ int activity = -1;
+
+ s = SPLI4B(); /* enter critical section */
+ if(chan->state & HSCX_TX_ACTIVE) /* already running ? */
+ {
+ splx(s);
+ return; /* yes, leave */
+ }
+
+ /* get next mbuf from queue */
+
+ IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
+
+ if(chan->out_mbuf_head == NULL) /* queue empty ? */
+ {
+ splx(s); /* leave critical section */
+ return; /* yes, exit */
+ }
+
+ /* init current mbuf values */
+
+ chan->out_mbuf_cur = chan->out_mbuf_head;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+
+ /* activity indicator for timeout handling */
+
+ if(chan->bprot == BPROT_NONE)
+ {
+ if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
+ activity = ACT_TX;
+ }
+ else
+ {
+ activity = ACT_TX;
+ }
+
+ chan->state |= HSCX_TX_ACTIVE; /* we start transmitting */
+
+ if(sc->sc_trace & TRACE_B_TX) /* if trace, send mbuf to trace dev */
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+
+ isic_hscx_fifo(chan, sc);
+
+ /* call timeout handling routine */
+
+ if(activity == ACT_RX || activity == ACT_TX)
+ (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity);
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * return the address of isic drivers linktab
+ *---------------------------------------------------------------------------*/
+static isdn_link_t *
+avma1pp_ret_linktab(int unit, int channel)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+ l1_bchan_state_t *chan = &sc->sc_chan[channel];
+
+ return(&chan->isdn_linktab);
+}
+
+/*---------------------------------------------------------------------------*
+ * set the driver linktab in the b channel softc
+ *---------------------------------------------------------------------------*/
+static void
+avma1pp_set_linktab(int unit, int channel, drvr_link_t *dlt)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+ l1_bchan_state_t *chan = &sc->sc_chan[channel];
+
+ chan->drvr_linktab = dlt;
+}
+
+
+/*---------------------------------------------------------------------------*
+ * initialize our local linktab
+ *---------------------------------------------------------------------------*/
+static void
+avma1pp_init_linktab(struct l1_softc *sc)
+{
+ l1_bchan_state_t *chan = &sc->sc_chan[HSCX_CH_A];
+ isdn_link_t *lt = &chan->isdn_linktab;
+
+ /* make sure the hardware driver is known to layer 4 */
+ /* avoid overwriting if already set */
+ if (ctrl_types[CTRL_PASSIVE].set_linktab == NULL)
+ {
+ ctrl_types[CTRL_PASSIVE].set_linktab = avma1pp_set_linktab;
+ ctrl_types[CTRL_PASSIVE].get_linktab = avma1pp_ret_linktab;
+ }
+
+ /* local setup */
+ lt->unit = sc->sc_unit;
+ lt->channel = HSCX_CH_A;
+ lt->bch_config = avma1pp_bchannel_setup;
+ lt->bch_tx_start = avma1pp_bchannel_start;
+ lt->bch_stat = avma1pp_bchannel_stat;
+ lt->tx_queue = &chan->tx_queue;
+
+ /* used by non-HDLC data transfers, i.e. telephony drivers */
+ lt->rx_queue = &chan->rx_queue;
+
+ /* used by HDLC data transfers, i.e. ipr and isp drivers */
+ lt->rx_mbuf = &chan->in_mbuf;
+
+ chan = &sc->sc_chan[HSCX_CH_B];
+ lt = &chan->isdn_linktab;
+
+ lt->unit = sc->sc_unit;
+ lt->channel = HSCX_CH_B;
+ lt->bch_config = avma1pp_bchannel_setup;
+ lt->bch_tx_start = avma1pp_bchannel_start;
+ lt->bch_stat = avma1pp_bchannel_stat;
+ lt->tx_queue = &chan->tx_queue;
+
+ /* used by non-HDLC data transfers, i.e. telephony drivers */
+ lt->rx_queue = &chan->rx_queue;
+
+ /* used by HDLC data transfers, i.e. ipr and isp drivers */
+ lt->rx_mbuf = &chan->in_mbuf;
+}
+
+/*
+ * use this instead of isic_bchannel_stat in i4b_bchan.c because it's static
+ */
+static void
+avma1pp_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp)
+{
+#ifdef __FreeBSD__
+ struct l1_softc *sc = &l1_sc[unit];
+#else
+ struct l1_softc *sc = isic_find_sc(unit);
+#endif
+ l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+ int s;
+
+ s = SPLI4B();
+
+ bsp->outbytes = chan->txcount;
+ bsp->inbytes = chan->rxcount;
+
+ chan->txcount = 0;
+ chan->rxcount = 0;
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * fill HSCX fifo with data from the current mbuf
+ * Put this here until it can go into i4b_hscx.c
+ *---------------------------------------------------------------------------*/
+static int
+isic_hscx_fifo(l1_bchan_state_t *chan, struct l1_softc *sc)
+{
+ int len;
+ int nextlen;
+ int i;
+ int cmd;
+ /* using a scratch buffer simplifies writing to the FIFO */
+ u_char scrbuf[HSCX_FIFO_LEN];
+
+ len = 0;
+
+ /*
+ * fill the HSCX tx fifo with data from the current mbuf. if
+ * current mbuf holds less data than HSCX fifo length, try to
+ * get the next mbuf from (a possible) mbuf chain. if there is
+ * not enough data in a single mbuf or in a chain, then this
+ * is the last mbuf and we tell the HSCX that it has to send
+ * CRC and closing flag
+ */
+
+ while(chan->out_mbuf_cur && len != sc->sc_bfifolen)
+ {
+ nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);
+
+#ifdef NOTDEF
+ printf("i:mh=%p, mc=%p, mcp=%p, mcl=%d l=%d nl=%d # ",
+ chan->out_mbuf_head,
+ chan->out_mbuf_cur,
+ chan->out_mbuf_cur_ptr,
+ chan->out_mbuf_cur_len,
+ len,
+ nextlen);
+#endif
+
+ cmd |= HSCX_CMDR_XTF;
+ /* collect the data in the scratch buffer */
+ for (i = 0; i < nextlen; i++)
+ scrbuf[i + len] = chan->out_mbuf_cur_ptr[i];
+
+ len += nextlen;
+ chan->txcount += nextlen;
+
+ chan->out_mbuf_cur_ptr += nextlen;
+ chan->out_mbuf_cur_len -= nextlen;
+
+ if(chan->out_mbuf_cur_len == 0)
+ {
+ if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
+ {
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (chan->channel == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+ }
+ else
+ {
+ if (chan->bprot != BPROT_NONE)
+ cmd |= HSCX_CMDR_XME;
+ i4b_Bfreembuf(chan->out_mbuf_head);
+ chan->out_mbuf_head = NULL;
+ }
+ }
+ }
+ /* write what we have from the scratch buf to the HSCX fifo */
+ if (len != 0)
+ HSCX_WRFIFO(chan->channel, scrbuf, len);
+ return(cmd);
+}
+
+#endif /* ISICPCI_AVM_A1 */
diff --git a/sys/dev/pci/i4b_elsa_qs1p.c b/sys/dev/pci/i4b_elsa_qs1p.c
new file mode 100644
index 00000000000..67a33fae7d7
--- /dev/null
+++ b/sys/dev/pci/i4b_elsa_qs1p.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro PCI
+ * =====================================================================
+ *
+ * $Id: i4b_elsa_qs1p.c,v 1.1.1.1 2001/01/05 12:50:18 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:58 2001]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicpci.h"
+#ifdef ISICPCI_ELSA_QS1PCI
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_mbuf.h>
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+#include <dev/ic/i4b_ipac.h>
+
+#ifndef __FreeBSD__
+#include <dev/pci/pci_isic.h>
+#endif
+
+/* masks for register encoded in base addr */
+
+#define ELSA_BASE_MASK 0x0ffff
+#define ELSA_OFF_MASK 0xf0000
+
+/* register id's to be encoded in base addr */
+
+#define ELSA_IDISAC 0x00000
+#define ELSA_IDHSCXA 0x10000
+#define ELSA_IDHSCXB 0x20000
+#define ELSA_IDIPAC 0x40000
+
+/* offsets from base address */
+
+#define ELSA_OFF_ALE 0x00
+#define ELSA_OFF_RW 0x01
+
+#define ELSA_PORT0_MAPOFF PCI_MAPREG_START+4
+#define ELSA_PORT1_MAPOFF PCI_MAPREG_START+12
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pp_read_fifo(void *buf, const void *base, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pp_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pp_write_fifo(void *base, const void *buf, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pp_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pp_write_reg(u_char *base, u_int offset, u_int v)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+ else /* IPAC */
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+}
+
+#else
+
+static void
+eqs1pp_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ case ISIC_WHAT_IPAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+eqs1pp_read_reg(u_char *base, u_int offset)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+ else /* IPAC */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+}
+
+#else
+
+static u_int8_t
+eqs1pp_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ case ISIC_WHAT_IPAC:
+ {
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ }
+ }
+
+ return 0;
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_Eqs1pp - attach for ELSA QuickStep 1000pro/PCI
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_Eqs1pp(int unit, unsigned int iobase1, unsigned int iobase2)
+{
+ struct l1_softc *sc = &l1_sc[unit];
+
+ /* check max unit range */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/PCI!\n",
+ unit, unit);
+ return(0);
+ }
+ sc->sc_unit = unit;
+
+ /* setup iobase */
+
+ if((iobase2 <= 0) || (iobase2 > 0xffff))
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/PCI!\n",
+ unit, iobase2);
+ return(0);
+ }
+ sc->sc_port = iobase2;
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = eqs1pp_read_reg;
+ sc->writereg = eqs1pp_write_reg;
+
+ sc->readfifo = eqs1pp_read_fifo;
+ sc->writefifo = eqs1pp_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ /* setup chip type = IPAC ! */
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDISAC);
+ HSCX_A_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDHSCXA);
+ HSCX_B_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDHSCXB);
+ IPAC_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDIPAC);
+
+ /* enable hscx/isac irq's */
+ IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
+
+ IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */
+ IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */
+ (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
+ IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */
+
+ outb(iobase1 + 0x4c, 0x41); /* enable card interrupt */
+
+ return (1);
+}
+
+#else /* !FreeBSD */
+
+void
+isic_attach_Eqs1pp(psc, pa)
+ struct pci_l1_softc *psc;
+ struct pci_attach_args *pa;
+{
+ struct l1_softc *sc = &psc->sc_isic;
+
+ /* setup io mappings */
+ sc->sc_num_mappings = 2;
+ MALLOC_MAPS(sc);
+ sc->sc_maps[0].size = 0;
+ if (pci_mapreg_map(pa, ELSA_PORT0_MAPOFF, PCI_MAPREG_TYPE_IO, 0,
+ &sc->sc_maps[0].t, &sc->sc_maps[0].h, NULL, NULL)) {
+ printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ sc->sc_maps[1].size = 0;
+ if (pci_mapreg_map(pa, ELSA_PORT1_MAPOFF, PCI_MAPREG_TYPE_IO, 0,
+ &sc->sc_maps[1].t, &sc->sc_maps[1].h, NULL, NULL)) {
+ printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = eqs1pp_read_reg;
+ sc->writereg = eqs1pp_write_reg;
+
+ sc->readfifo = eqs1pp_read_fifo;
+ sc->writefifo = eqs1pp_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ /* setup chip type = IPAC ! */
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+ /* enable hscx/isac irq's */
+ IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
+
+ IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */
+ IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */
+ (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
+ IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */
+
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 0x4c, 0x41); /* enable card interrupt */
+}
+
+#endif
+
+#endif /* ISICPCI_ELSA_QS1PCI */
diff --git a/sys/dev/pci/pci_isic.c b/sys/dev/pci/pci_isic.c
new file mode 100644
index 00000000000..64c12a69168
--- /dev/null
+++ b/sys/dev/pci/pci_isic.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 1998,1999 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * pci_isic.c - pcmcia bus frontend for i4b_isic driver
+ * -------------------------------------------------------
+ *
+ * $Id: pci_isic.c,v 1.1.1.1 2001/01/05 12:50:20 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:38:58 2001]
+ *
+ * -mh original implementation
+ * -mh added support for Fritz! PCI card
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_ioctl.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_ipac.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_global.h>
+#include <netisdn/i4b_l1l2.h>
+#include <dev/pci/pci_isic.h>
+
+#include "opt_isicpci.h"
+
+static int pci_isic_match __P((struct device *, struct cfdata *, void *));
+static void pci_isic_attach __P((struct device *, struct device *, void *));
+static const struct isic_pci_product * find_matching_card __P((struct pci_attach_args *pa));
+
+static void isic_pciattach __P((struct pci_l1_softc *psc, struct pci_attach_args *pa));
+
+struct cfattach pci_isic_ca = {
+ sizeof(struct pci_l1_softc), pci_isic_match, pci_isic_attach
+};
+
+
+static const struct isic_pci_product {
+ pci_vendor_id_t npp_vendor;
+ pci_product_id_t npp_product;
+ int cardtype;
+ const char * name;
+ void (*attach)(struct pci_l1_softc *psc, struct pci_attach_args *pa);
+ void (*pciattach)(struct pci_l1_softc *psc, struct pci_attach_args *pa);
+} isic_pci_products[] = {
+
+#ifdef ISICPCI_ELSA_QS1PCI
+#ifndef PCI_PRODUCT_ELSA_QS1PCI
+#define PCI_PRODUCT_ELSA_QS1PCI 0x1000 /* added to pcidevs in 1.3K, earlier versions missing it */
+#endif
+ { PCI_VENDOR_ELSA, PCI_PRODUCT_ELSA_QS1PCI,
+ CARD_TYPEP_ELSAQS1PCI,
+ "ELSA QuickStep 1000pro/PCI",
+ isic_attach_Eqs1pp, /* card specific initialization */
+ isic_pciattach /* generic setup for ISAC/HSCX or IPAC boards */
+ },
+#endif
+
+#ifdef ISICPCI_AVM_A1
+#ifndef PCI_VENDOR_AVM
+#define PCI_VENDOR_AVM 0x1244 /* earlier versions missing this */
+#define PCI_PRODUCT_AVM_FRITZ_CARD 0x0a00
+#endif
+ { PCI_VENDOR_AVM, PCI_PRODUCT_AVM_FRITZ_CARD,
+ CARD_TYPEP_AVMA1PCI,
+ "Fritz!Card",
+ isic_attach_fritzPci,
+ NULL /* card rolls its own setup */
+ },
+#endif
+
+ { 0, 0, 0, NULL, NULL },
+};
+
+static const struct isic_pci_product * find_matching_card(pa)
+ struct pci_attach_args *pa;
+{
+ const struct isic_pci_product * pp = NULL;
+
+ for (pp = isic_pci_products; pp->npp_vendor; pp++)
+ if (PCI_VENDOR(pa->pa_id) == pp->npp_vendor &&
+ PCI_PRODUCT(pa->pa_id) == pp->npp_product)
+ return pp;
+
+ return NULL;
+}
+
+/*
+ * Match card
+ */
+static int
+pci_isic_match(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct pci_attach_args *pa = aux;
+
+ if (!find_matching_card(pa))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Attach the card
+ */
+static void
+pci_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pci_l1_softc *psc = (void*) self;
+ struct l1_softc *sc = &psc->sc_isic;
+ struct pci_attach_args *pa = aux;
+ const struct isic_pci_product * prod;
+
+ /* Redo probe */
+ prod = find_matching_card(pa);
+ if (prod == NULL) return; /* oops - not found?!? */
+
+ sc->sc_unit = sc->sc_dev.dv_unit;
+ printf(": %s\n", prod->name);
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+ callout_init(&sc->sc_T3_callout);
+ callout_init(&sc->sc_T4_callout);
+#endif
+
+ /* card initilization and sc setup */
+ prod->attach(psc, pa);
+
+ /* generic setup, if needed for this card */
+ if (prod->pciattach) prod->pciattach(psc, pa);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - pci device driver attach routine
+ *---------------------------------------------------------------------------*/
+static void
+isic_pciattach(psc, pa)
+ struct pci_l1_softc *psc;
+ struct pci_attach_args *pa;
+{
+ struct l1_softc *sc = &psc->sc_isic;
+ pci_chipset_tag_t pc = pa->pa_pc;
+ pci_intr_handle_t ih;
+ const char *intrstr;
+
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ l1_sc[sc->sc_unit] = sc; /* XXX - hack! */
+
+ sc->sc_isac_version = 0;
+ sc->sc_hscx_version = 0;
+
+ if(sc->sc_ipac)
+ {
+ u_int ret = IPAC_READ(IPAC_ID);
+
+ switch(ret)
+ {
+ case 0x01:
+ printf("%s: IPAC PSB2115 Version 1.1\n", sc->sc_dev.dv_xname);
+ break;
+
+ case 0x02:
+ printf("%s: IPAC PSB2115 Version 2\n", sc->sc_dev.dv_xname);
+ break;
+
+ default:
+ printf("%s: Error, IPAC version %d unknown!\n",
+ sc->sc_dev.dv_xname, ret);
+ return;
+ }
+ }
+ else
+ {
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ printf("%s: ISAC %s (IOM-%c)\n",
+ sc->sc_dev.dv_xname,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ break;
+
+ default:
+ printf("%s: Error, ISAC version %d unknown!\n",
+ sc->sc_dev.dv_xname, sc->sc_isac_version);
+ return;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ printf("%s: HSCX %s\n",
+ sc->sc_dev.dv_xname,
+ HSCXversion[sc->sc_hscx_version]);
+ break;
+
+ default:
+ printf("%s: Error, HSCX version %d unknown!\n",
+ sc->sc_dev.dv_xname, sc->sc_hscx_version);
+ return;
+ }
+ }
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ callout_handle_init(&sc->sc_T3_callout);
+ callout_handle_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+
+ /* Map and establish the interrupt. */
+ if (pci_intr_map(pa, &ih)) {
+ printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ intrstr = pci_intr_string(pc, ih);
+ psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, isicintr, sc);
+ if (psc->sc_ih == NULL) {
+ printf("%s: couldn't establish interrupt",
+ sc->sc_dev.dv_xname);
+ if (intrstr != NULL)
+ printf(" at %s", intrstr);
+ printf("\n");
+ return;
+ }
+ printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
+}
+
diff --git a/sys/dev/pci/pci_isic.h b/sys/dev/pci/pci_isic.h
new file mode 100644
index 00000000000..560f25515da
--- /dev/null
+++ b/sys/dev/pci/pci_isic.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1999 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * pci_isic.h - pci bus frontend for i4b_isic driver
+ * -------------------------------------------------
+ *
+ * $Id: pci_isic.h,v 1.1.1.1 2001/01/05 12:50:20 martin Exp $
+ *
+ * last edit-date: [Wed Mar 10 07:22:08 1999]
+ *
+ * -mh original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+struct pci_l1_softc {
+ struct l1_softc sc_isic; /* parent class */
+
+ /* PCI-specific goo */
+ void *sc_ih; /* interrupt handler */
+};
+
+extern void isic_attach_Eqs1pp __P((struct pci_l1_softc *psc, struct pci_attach_args *pa));
+extern void isic_attach_fritzPci __P((struct pci_l1_softc *psc, struct pci_attach_args *pa));
+
diff --git a/sys/dev/pcmcia/i4b_avm_fritz_pcmcia.c b/sys/dev/pcmcia/i4b_avm_fritz_pcmcia.c
new file mode 100644
index 00000000000..73f1473f65b
--- /dev/null
+++ b/sys/dev/pcmcia/i4b_avm_fritz_pcmcia.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 1998 Matthias Apitz. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * Fritz!Card pcmcia specific routines for isic driver
+ * ---------------------------------------------------
+ *
+ * $Id: i4b_avm_fritz_pcmcia.c,v 1.1.1.1 2001/01/05 12:50:21 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:39:32 2001]
+ *
+ * -ap added support for AVM PCMCIA Fritz!Card
+ * -mh split into separate file
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicpcmcia.h"
+#ifdef ISICPCMCIA_AVM_A1
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#ifndef __FreeBSD__
+#include <dev/pcmcia/pcmcia_isic.h>
+
+/* PCMCIA support routines */
+static u_int8_t avma1_pcmcia_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void avma1_pcmcia_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void avma1_pcmcia_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+static void avma1_pcmcia_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM PCMCIA Fritz!Card special registers
+ *---------------------------------------------------------------------------*/
+
+/*
+ * register offsets from i/o base 0x140 or 0x300
+ */
+#define ADDR_REG_OFFSET 0x02
+#define DATA_REG_OFFSET 0x03
+#define STAT0_OFFSET 0x04
+#define STAT1_OFFSET 0x05
+#define MODREG_OFFSET 0x06
+#define VERREG_OFFSET 0x07
+/*
+ * AVM PCMCIA Status Latch 0 read only bits
+ */
+#define ASL_IRQ_TIMER 0x10 /* Timer interrupt, active low */
+#define ASL_IRQ_ISAC 0x20 /* ISAC interrupt, active low */
+#define ASL_IRQ_HSCX 0x40 /* HSX interrupt, active low */
+#define ASL_IRQ_BCHAN ASL_IRQ_HSCX
+#define ASL_IRQ_Pending (ASL_IRQ_ISAC | ASL_IRQ_HSCX | ASL_IRQ_TIMER)
+/*
+ * AVM Status Latch 0 write only bits
+ */
+#define ASL_RESET_ALL 0x01 /* reset siemens IC's, active 1 */
+#define ASL_TIMERDISABLE 0x02 /* active high */
+#define ASL_TIMERRESET 0x04 /* active high */
+#define ASL_ENABLE_INT 0x08 /* active high */
+/*
+ * AVM Status Latch 1 write only bits
+ */
+#define ASL1_LED0 0x10 /* active high */
+#define ASL1_LED1 0x20 /* active high */
+
+#define ASL1_ENABLE_S0 0xc0 /* enable active S0 I/F */
+
+/*----- EEpromless controller -----*/
+/*
+ * AVM Status Latch read/write bit
+ */
+
+#define ASL_TESTBIT 0x80
+
+
+/*---------------------------------------------------------------------------*
+ * AVM read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static int PCMCIA_IO_BASE = 0; /* ap: XXX hack */
+static void
+avma1_pcmcia_read_fifo(void *buf, const void *base, size_t len)
+{
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base - 0x20);
+ insb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char *)buf, (u_int)len);
+}
+#else
+/* offsets of the different 'what' arguments */
+static u_int8_t what_map[] = {
+ 0x20-0x20, /* ISIC_WHAT_ISAC */
+ 0xA0-0x20, /* ISIC_WHAT_HSCXA */
+ 0xE0-0x20 /* ISIC_WHAT_HSCXB */
+};
+static void
+avma1_pcmcia_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]);
+ bus_space_read_multi_1(t, h, DATA_REG_OFFSET, buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_pcmcia_write_fifo(void *base, const void *buf, size_t len)
+{
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base - 0x20);
+ outsb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char *)buf, (u_int)len);
+}
+#else
+static void
+avma1_pcmcia_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]);
+ bus_space_write_multi_1(t, h, DATA_REG_OFFSET, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_pcmcia_write_reg(u_char *base, u_int offset, u_int v)
+{
+ /* offset includes 0x20 FIFO ! */
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base+offset-0x20);
+ outb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char)v);
+}
+#else
+static void
+avma1_pcmcia_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]+offs);
+ bus_space_write_1(t, h, DATA_REG_OFFSET, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+avma1_pcmcia_read_reg(u_char *base, u_int offset)
+{
+ /* offset includes 0x20 FIFO ! */
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base+offset-0x20);
+ return (inb(PCMCIA_IO_BASE + DATA_REG_OFFSET));
+}
+#else
+static u_int8_t
+avma1_pcmcia_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]+offs);
+ return bus_space_read_1(t, h, DATA_REG_OFFSET);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_avma1_pcmcia - probe for AVM PCMCIA Fritz!Card
+ * This is in the bus attachemnt part on NetBSD (pcmcia_isic.c), no
+ * card specicfic probe is needed on direct config buses like pcmcia.
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_avma1_pcmcia(struct isa_device *dev)
+{
+ struct l1_softc *sc = &l1_sc[dev->id_unit];
+ u_char byte;
+ int i;
+ u_int cardinfo;
+
+ /* check max unit range */
+
+ if(dev->id_unit > 1)
+ {
+ printf("isic%d: Error, unit %d > MAXUNIT for AVM PCMCIA Fritz!Card\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /*
+ * we trust the IRQ we got from PCCARD service
+ */
+ sc->sc_irq = dev->id_irq;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x140:
+ case 0x300:
+ break;
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for AVM PCMCIA Fritz!Card.\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* ResetController */
+
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 20);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x01);
+ DELAY(SEC_DELAY / 20);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+
+ /*
+ * CheckController
+ * The logic to check for the PCMCIA was adapted as
+ * described by AVM.
+ */
+
+ outb(dev->id_iobase + ADDR_REG_OFFSET, 0x21); /* ISAC STAR */
+ if ( (byte=inb(dev->id_iobase + DATA_REG_OFFSET) & 0xfd) != 0x48 )
+ {
+ printf("isic%d: Error, ISAC STAR for AVM PCMCIA is 0x%0x (should be 0x48)\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ outb(dev->id_iobase + ADDR_REG_OFFSET, 0xa1); /* HSCX STAR */
+ if ( (byte=inb(dev->id_iobase + DATA_REG_OFFSET) & 0xfd) != 0x48 )
+ {
+ printf("isic%d: Error, HSCX STAR for AVM PCMCIA is 0x%0x (should be 0x48)\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ byte = ASL_TESTBIT;
+ for (i=0; i<256; i++) {
+ byte = byte ? 0 : ASL_TESTBIT;
+ outb(dev->id_iobase + STAT0_OFFSET, byte);
+ if ((inb(dev->id_iobase+STAT0_OFFSET)&ASL_TESTBIT)!=byte) {
+ printf("isic%d: Error during toggle of AVM PCMCIA Status Latch0\n",
+ dev->id_unit);
+ return(0);
+ }
+ }
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_pcmcia_read_reg;
+ sc->writereg = avma1_pcmcia_write_reg;
+
+ sc->readfifo = avma1_pcmcia_read_fifo;
+ sc->writefifo = avma1_pcmcia_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_PCFRITZ;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2; /* ap: XXX ??? */
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+ /*
+ * NOTE: for PCMCIA these are no real addrs; they are
+ * offsets to be written into the base+ADDR_REG_OFFSET register
+ * to pick up the values of the bytes fro base+DATA_REG_OFFSET
+ *
+ * see also the logic in the avma1_pcmcia_* routines;
+ * therefore we also must have the base addr in some static
+ * space or struct; XXX better solution?
+ */
+
+ PCMCIA_IO_BASE = dev->id_iobase;
+ ISAC_BASE = (caddr_t)0x20;
+
+ HSCX_A_BASE = (caddr_t)0xA0;
+ HSCX_B_BASE = (caddr_t)0xE0;
+
+ /*
+ * Read HSCX A/B VSTR.
+ * Expected value for AVM A1 is 0x04 or 0x05 and for the
+ * AVM Fritz!Card is 0x05 in the least significant bits.
+ */
+
+ if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) ||
+ (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
+ {
+ printf("isic%d: HSCX VSTR test failed for AVM PCMCIA Fritz!Card\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: 0x%0x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: 0x%0x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ /*
+ * seems we really have an AVM PCMCIA Fritz!Card controller
+ */
+ cardinfo = inb(dev->id_iobase + VERREG_OFFSET)<<8 | inb(dev->id_iobase + MODREG_OFFSET);
+ printf("isic%d: successfully detect AVM PCMCIA cardinfo = 0x%0x\n",
+ dev->id_unit, cardinfo);
+ dev->id_flags = FLAG_AVM_A1_PCMCIA;
+ return (1);
+}
+#endif /* __FreeBSD__ */
+
+
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_fritzpcmcia - attach Fritz!Card
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_fritzpcmcia(struct isa_device *dev)
+{
+ /* ResetController again just to make sure... */
+
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x01);
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ outb(dev->id_iobase + STAT0_OFFSET, ASL_TIMERDISABLE |
+ ASL_TIMERRESET | ASL_ENABLE_INT);
+ /* DELAY(SEC_DELAY / 10); */
+
+ return(1);
+}
+
+#else
+
+/*
+ * XXX - one time only! Some of this has to go into an enable
+ * function, with apropriate counterpart in disable, so a card
+ * could be removed an inserted again. But never mind for now,
+ * this won't work anyway for several reasons (both in NetBSD
+ * and in I4B).
+ */
+int
+isic_attach_fritzpcmcia(struct pcmcia_l1_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa)
+{
+ struct l1_softc *sc = &psc->sc_isic;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ /* Validate config info */
+ if (cfe->num_memspace != 0)
+ printf(": unexpected number of memory spaces %d should be 0\n",
+ cfe->num_memspace);
+ if (cfe->num_iospace != 1)
+ printf(": unexpected number of memory spaces %d should be 1\n",
+ cfe->num_iospace);
+
+ /* Allocate pcmcia space - exactly as dictated by the card */
+ if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start, cfe->iospace[0].length,
+ 0, &psc->sc_pcioh))
+ printf(": can't allocate i/o space\n");
+
+ /* map them */
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0,
+ cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return 0;
+ }
+
+ /* Setup bus space maps */
+ sc->sc_num_mappings = 1;
+ sc->sc_cardtyp = CARD_TYPEP_PCFRITZ;
+ MALLOC_MAPS(sc);
+
+ /* Copy our handles/tags to the MI maps */
+ sc->sc_maps[0].t = psc->sc_pcioh.iot;
+ sc->sc_maps[0].h = psc->sc_pcioh.ioh;
+ sc->sc_maps[0].offset = 0;
+ sc->sc_maps[0].size = 0; /* not our mapping */
+
+ t = sc->sc_maps[0].t;
+ h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_pcmcia_read_reg;
+ sc->writereg = avma1_pcmcia_write_reg;
+
+ sc->readfifo = avma1_pcmcia_read_fifo;
+ sc->writefifo = avma1_pcmcia_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_PCFRITZ;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* Reset controller again just to make sure... */
+
+ bus_space_write_1(t, h, STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, STAT0_OFFSET, 0x01);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ bus_space_write_1(t, h, STAT0_OFFSET, ASL_TIMERDISABLE |
+ ASL_TIMERRESET | ASL_ENABLE_INT);
+
+ return 1;
+}
+#endif
+
+#endif /* ISICPCMCIA_AVM_A1 */
diff --git a/sys/dev/pcmcia/i4b_elsa_isdnmc.c b/sys/dev/pcmcia/i4b_elsa_isdnmc.c
new file mode 100644
index 00000000000..b047b09dcc0
--- /dev/null
+++ b/sys/dev/pcmcia/i4b_elsa_isdnmc.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ELSA MicroLink ISDN/MC card specific routines
+ * ---------------------------------------------
+ *
+ * $Id: i4b_elsa_isdnmc.c,v 1.1.1.1 2001/01/05 12:50:21 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:39:32 2001]
+ *
+ * -mh added support for elsa ISDN/mc
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicpcmcia.h"
+#ifdef ISICPCMCIA_ELSA_ISDNMC
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <dev/pcmcia/pcmcia_isic.h>
+
+#ifndef __FreeBSD__
+/* PCMCIA support routines */
+static u_int8_t elsa_isdnmc_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void elsa_isdnmc_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void elsa_isdnmc_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+static void elsa_isdnmc_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+static void elsa_isdnmc_clrirq __P((struct l1_softc *sc));
+#endif
+
+/*
+ * The ELSA MicroLink ISDN/MC uses one contigous IO region,
+ * mapped by the pcmcia code.
+ * The chip access is via three ports:
+ */
+#define ISAC_DATA 1 /* ISAC dataport at offset 1 */
+#define HSCX_DATA 2 /* HSCX dataport at offset 2 */
+#define ADDR_LATCH 4 /* address latch at offset 4 */
+
+/* This is very similar to the ELSA QuickStep 1000 (ISA) card */
+
+#ifdef __FreeBSD__
+static void
+elsa_isdnmc_clrirq(void *base)
+{
+}
+#else
+static void
+elsa_isdnmc_clrirq(struct l1_softc *sc)
+{
+ ISAC_WRITE(I_MASK, 0xff);
+ HSCX_WRITE(0, H_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_isdnmc_read_fifo(void *buf, const void *base, size_t len)
+{
+}
+#else
+static void
+elsa_isdnmc_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_read_multi_1(t, h, ISAC_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_read_multi_1(t, h, HSCX_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40);
+ bus_space_read_multi_1(t, h, HSCX_DATA, buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_isdnmc_write_fifo(void *base, const void *buf, size_t len)
+{
+}
+#else
+static void
+elsa_isdnmc_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_write_multi_1(t, h, ISAC_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_write_multi_1(t, h, HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40);
+ bus_space_write_multi_1(t, h, HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_isdnmc_write_reg(u_char *base, u_int offset, u_int v)
+{
+}
+#else
+static void
+elsa_isdnmc_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ bus_space_write_1(t, h, ISAC_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ bus_space_write_1(t, h, HSCX_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40+offs);
+ bus_space_write_1(t, h, HSCX_DATA, data);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+elsa_isdnmc_read_reg(u_char *base, u_int offset)
+{
+ return 0;
+}
+#else
+static u_int8_t
+elsa_isdnmc_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ return bus_space_read_1(t, h, ISAC_DATA);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ return bus_space_read_1(t, h, HSCX_DATA);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40+offs);
+ return bus_space_read_1(t, h, HSCX_DATA);
+ }
+ return 0;
+}
+#endif
+
+#ifdef __FreeBSD__
+#else
+
+/*
+ * XXX - one time only! Some of this has to go into an enable
+ * function, with apropriate counterpart in disable, so a card
+ * could be removed an inserted again. But never mind for now,
+ * this won't work anyway for several reasons (both in NetBSD
+ * and in I4B).
+ */
+int
+isic_attach_elsaisdnmc(struct pcmcia_l1_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa)
+{
+ struct l1_softc *sc = &psc->sc_isic;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ /* Validate config info */
+ if (cfe->num_memspace != 0)
+ printf(": unexpected number of memory spaces %d should be 0\n",
+ cfe->num_memspace);
+ if (cfe->num_iospace != 1)
+ printf(": unexpected number of memory spaces %d should be 1\n",
+ cfe->num_iospace);
+
+ /* Allocate pcmcia space */
+ if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
+ cfe->iospace[0].length, &psc->sc_pcioh))
+ printf(": can't allocate i/o space\n");
+
+ /* map them */
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0,
+ cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return 0;
+ }
+
+ /* OK, this will work! */
+ sc->sc_cardtyp = CARD_TYPEP_ELSAMLIMC;
+
+ /* Setup bus space maps */
+ sc->sc_num_mappings = 1;
+ MALLOC_MAPS(sc);
+
+ /* Copy our handles/tags to the MI maps */
+ sc->sc_maps[0].t = psc->sc_pcioh.iot;
+ sc->sc_maps[0].h = psc->sc_pcioh.ioh;
+ sc->sc_maps[0].offset = 0;
+ sc->sc_maps[0].size = 0; /* not our mapping */
+
+ t = sc->sc_maps[0].t;
+ h = sc->sc_maps[0].h;
+
+ sc->clearirq = elsa_isdnmc_clrirq;
+
+ sc->readreg = elsa_isdnmc_read_reg;
+ sc->writereg = elsa_isdnmc_write_reg;
+
+ sc->readfifo = elsa_isdnmc_read_fifo;
+ sc->writefifo = elsa_isdnmc_write_fifo;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ return 1;
+}
+#endif
+
+#endif /* ISICPCMCIA_ELSA_ISDNMC */
diff --git a/sys/dev/pcmcia/i4b_elsa_mcall.c b/sys/dev/pcmcia/i4b_elsa_mcall.c
new file mode 100644
index 00000000000..5fadd4a4859
--- /dev/null
+++ b/sys/dev/pcmcia/i4b_elsa_mcall.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ELSA MicroLink MC/all card specific routines
+ * --------------------------------------------
+ *
+ * $Id: i4b_elsa_mcall.c,v 1.1.1.1 2001/01/05 12:50:21 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:39:32 2001]
+ *
+ * -mh started support for ELSA MC/all
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "opt_isicpcmcia.h"
+#ifdef ISICPCMCIA_ELSA_MCALL
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <netisdn/i4b_debug.h>
+#include <netisdn/i4b_ioctl.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+#include <dev/ic/i4b_ipac.h>
+
+#include <dev/pcmcia/pcmcia_isic.h>
+
+#ifndef __FreeBSD__
+/* PCMCIA support routines */
+static u_int8_t elsa_mcall_read_reg __P((struct l1_softc *sc, int what, bus_size_t offs));
+static void elsa_mcall_write_reg __P((struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void elsa_mcall_read_fifo __P((struct l1_softc *sc, int what, void *buf, size_t size));
+static void elsa_mcall_write_fifo __P((struct l1_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static int PCMCIA_IO_BASE = 0; /* ap: XXX hack */
+static void
+elsa_mcall_read_fifo(void *buf, const void *base, size_t len)
+{
+}
+#else
+static void
+elsa_mcall_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_mcall_write_fifo(void *base, const void *buf, size_t len)
+{
+}
+#else
+static void
+elsa_mcall_write_fifo(struct l1_softc *sc, int what, const void *buf, size_t size)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_mcall_write_reg(u_char *base, u_int offset, u_int v)
+{
+}
+#else
+static void
+elsa_mcall_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+elsa_mcall_read_reg(u_char *base, u_int offset)
+{
+ return 0;
+}
+#else
+static u_int8_t
+elsa_mcall_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+ return 0;
+}
+#endif
+
+#ifdef __FreeBSD__
+#else
+
+/*
+ * XXX - one time only! Some of this has to go into an enable
+ * function, with apropriate counterpart in disable, so a card
+ * could be removed an inserted again. But never mind for now,
+ * this won't work anyway for several reasons (both in NetBSD
+ * and in I4B).
+ */
+int
+isic_attach_elsamcall(struct pcmcia_l1_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa)
+{
+ struct l1_softc *sc = &psc->sc_isic;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ /* Validate config info */
+ if (cfe->num_memspace != 0)
+ printf(": unexpected number of memory spaces %d should be 0\n",
+ cfe->num_memspace);
+ if (cfe->num_iospace != 1)
+ printf(": unexpected number of memory spaces %d should be 1\n",
+ cfe->num_iospace);
+
+ /* Allocate pcmcia space */
+ if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
+ cfe->iospace[0].length, &psc->sc_pcioh))
+ printf(": can't allocate i/o space\n");
+
+ /* map them */
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0,
+ cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return 0;
+ }
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_ELSAMLMCALL;
+
+ /* Setup bus space maps */
+ sc->sc_num_mappings = 1;
+ MALLOC_MAPS(sc);
+
+ /* Copy our handles/tags to the MI maps */
+ sc->sc_maps[0].t = psc->sc_pcioh.iot;
+ sc->sc_maps[0].h = psc->sc_pcioh.ioh;
+ sc->sc_maps[0].offset = 0;
+ sc->sc_maps[0].size = 0; /* not our mapping */
+
+ t = sc->sc_maps[0].t;
+ h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = elsa_mcall_read_reg;
+ sc->writereg = elsa_mcall_write_reg;
+
+ sc->readfifo = elsa_mcall_read_fifo;
+ sc->writefifo = elsa_mcall_write_fifo;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+ return 1;
+}
+#endif
+
+#endif /* ISICPCMCIA_ELSA_MCALL */
diff --git a/sys/dev/pcmcia/pcmcia_isic.c b/sys/dev/pcmcia/pcmcia_isic.c
new file mode 100644
index 00000000000..f77b26ea534
--- /dev/null
+++ b/sys/dev/pcmcia/pcmcia_isic.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * pcmcia_isic.c - pcmcia bus frontend for i4b_isic driver
+ * -------------------------------------------------------
+ *
+ * $Id: pcmcia_isic.c,v 1.1.1.1 2001/01/05 12:50:20 martin Exp $
+ *
+ * last edit-date: [Fri Jan 5 11:39:32 2001]
+ *
+ * -mh original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+#include <sys/callout.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciadevs.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <netisdn/i4b_ioctl.h>
+#include <netisdn/i4b_trace.h>
+#endif
+
+#include <dev/ic/i4b_isicl1.h>
+#include <dev/ic/i4b_ipac.h>
+#include <dev/ic/i4b_isac.h>
+#include <dev/ic/i4b_hscx.h>
+
+#include <netisdn/i4b_l1l2.h>
+#include <netisdn/i4b_global.h>
+
+#include <dev/pcmcia/pcmcia_isic.h>
+
+#include "opt_isicpcmcia.h"
+
+static int pcmcia_isic_match __P((struct device *, struct cfdata *, void *));
+static void pcmcia_isic_attach __P((struct device *, struct device *, void *));
+static const struct isic_pcmcia_card_entry * find_matching_card __P((struct pcmcia_attach_args *pa));
+static int pcmcia_isicattach __P((struct l1_softc *sc));
+
+struct cfattach pcmcia_isic_ca = {
+ sizeof(struct pcmcia_l1_softc), pcmcia_isic_match, pcmcia_isic_attach
+};
+
+struct isic_pcmcia_card_entry {
+ int32_t vendor; /* vendor ID */
+ int32_t product; /* product ID */
+ char *cis1_info[4]; /* CIS info to match */
+ char *name; /* name of controller */
+ int function; /* expected PCMCIA function type */
+ int card_type; /* card type found */
+ isic_pcmcia_attach_func attach; /* card initialization */
+};
+
+static const struct isic_pcmcia_card_entry card_list[] = {
+
+#ifdef ISICPCMCIA_AVM_A1
+ { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
+ { "AVM", "ISDN A", NULL, NULL },
+ "AVM Fritz!Card", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_PCFRITZ, isic_attach_fritzpcmcia },
+#endif
+
+#ifdef ISICPCMCIA_ELSA_ISDNMC
+ { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
+ { "ELSA GmbH, Aachen", "MicroLink ISDN/MC ", NULL, NULL },
+ "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
+ { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
+ { "ELSA AG, Aachen", "MicroLink ISDN/MC ", NULL, NULL },
+ "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
+#endif
+
+#ifdef ISICPCMCIA_ELSA_MCALL
+ { 0x105, 0x410a,
+ { "ELSA", "MicroLink MC all", NULL, NULL },
+ "ELSA MicroLink MCall", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_ELSAMLMCALL, isic_attach_elsamcall },
+#endif
+
+};
+#define NUM_MATCH_ENTRIES (sizeof(card_list)/sizeof(card_list[0]))
+
+static const struct isic_pcmcia_card_entry *
+find_matching_card(pa)
+ struct pcmcia_attach_args *pa;
+{
+ int i, j;
+
+ for (i = 0; i < NUM_MATCH_ENTRIES; i++) {
+ if (card_list[i].vendor != PCMCIA_VENDOR_INVALID && pa->card->manufacturer != card_list[i].vendor)
+ continue;
+ if (card_list[i].product != PCMCIA_PRODUCT_INVALID && pa->card->product != card_list[i].product)
+ continue;
+ if (pa->pf->function != card_list[i].function)
+ continue;
+ for (j = 0; j < 4; j++) {
+ if (card_list[i].cis1_info[j] == NULL)
+ continue; /* wildcard */
+ if (pa->card->cis1_info[j] == NULL)
+ break; /* not available */
+ if (strcmp(pa->card->cis1_info[j], card_list[i].cis1_info[j]) != 0)
+ break; /* mismatch */
+ }
+ if (j >= 4)
+ break;
+ }
+ if (i >= NUM_MATCH_ENTRIES)
+ return NULL;
+
+ return &card_list[i];
+}
+
+/*
+ * Match card
+ */
+static int
+pcmcia_isic_match(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct pcmcia_attach_args *pa = aux;
+
+ if (!find_matching_card(pa))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Attach the card
+ */
+static void
+pcmcia_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pcmcia_l1_softc *psc = (void*) self;
+ struct l1_softc *sc = &psc->sc_isic;
+ struct pcmcia_attach_args *pa = aux;
+ struct pcmcia_config_entry *cfe;
+ const struct isic_pcmcia_card_entry * cde;
+
+ /* Which card is it? */
+ cde = find_matching_card(pa);
+ if (cde == NULL) return; /* oops - not found?!? */
+
+ psc->sc_pf = pa->pf;
+ cfe = pa->pf->cfe_head.sqh_first;
+
+ /* Enable the card */
+ pcmcia_function_init(pa->pf, cfe);
+ pcmcia_function_enable(pa->pf);
+
+ if (!cde->attach(psc, cfe, pa))
+ return; /* Ooops ? */
+
+ sc->sc_unit = sc->sc_dev.dv_unit;
+
+ /* Announce card name */
+ printf(": %s\n", cde->name);
+
+ /* MI initilization */
+ pcmcia_isicattach(sc);
+
+ /* setup interrupt */
+ psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, isicintr, sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * card independend attach for pcmicia cards
+ *---------------------------------------------------------------------------*/
+
+/* parameter and format for message producing e.g. "isic0: " */
+
+#ifdef __FreeBSD__
+#define ISIC_FMT "isic%d: "
+#define ISIC_PARM dev->id_unit
+#define TERMFMT " "
+#else
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+#endif
+
+int
+pcmcia_isicattach(struct l1_softc *sc)
+{
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ l1_sc[sc->sc_unit] = sc;
+ sc->sc_isac_version = 0;
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return(0);
+ break;
+ };
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
+ callout_init(&sc->sc_T3_callout);
+ callout_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce chip versions */
+
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+
+ return(1);
+}
+
diff --git a/sys/dev/pcmcia/pcmcia_isic.h b/sys/dev/pcmcia/pcmcia_isic.h
new file mode 100644
index 00000000000..f98d0611632
--- /dev/null
+++ b/sys/dev/pcmcia/pcmcia_isic.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * pcmcia_isic.h - common definitions for pcmcia isic cards
+ * --------------------------------------------------------
+ *
+ * $Id: pcmcia_isic.h,v 1.1.1.1 2001/01/05 12:50:21 martin Exp $
+ *
+ * last edit-date: [Sun Feb 14 10:29:33 1999]
+ *
+ * -mh original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+struct pcmcia_l1_softc {
+ struct l1_softc sc_isic; /* parent class */
+
+ /* PCMCIA-specific goo */
+ struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
+ int sc_io_window; /* our i/o window */
+ struct pcmcia_function *sc_pf; /* our PCMCIA function */
+ void *sc_ih; /* interrupt handler */
+};
+
+typedef int (*isic_pcmcia_attach_func)(struct pcmcia_l1_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+
+extern int isic_attach_fritzpcmcia(struct pcmcia_l1_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+extern int isic_attach_elsaisdnmc(struct pcmcia_l1_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+extern int isic_attach_elsamcall(struct pcmcia_l1_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+
+