1139825Simp/*-
252800Sphk * ----------------------------------------------------------------------------
352800Sphk * "THE BEER-WARE LICENSE" (Revision 42):
452800Sphk * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
552800Sphk * can do whatever you want with this stuff. If we meet some day, and you think
652800Sphk * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
752800Sphk * ----------------------------------------------------------------------------
8139825Simp */
9139825Simp
10139825Simp/*
1152800Sphk * Driver for Siemens reference design card "Easy321-R1".
1252800Sphk *
1352800Sphk * This card contains a FALC54 E1/T1 framer and a MUNICH32X 32-channel HDLC
1452800Sphk * controller.
1552800Sphk *
1657616Sbillf * The driver supports E1 mode with up to 31 channels.  We send CRC4 but don't
1752800Sphk * check it coming in.
1852800Sphk *
1952800Sphk * The FALC54 and MUNICH32X have far too many registers and weird modes for
2052800Sphk * comfort, so I have not bothered typing it all into a "fooreg.h" file,
2152800Sphk * you will (badly!) need the documentation anyway if you want to mess with
2252800Sphk * this gadget.
2352800Sphk */
2452800Sphk
25116192Sobrien#include <sys/cdefs.h>
26116192Sobrien__FBSDID("$FreeBSD$");
27116192Sobrien
2852800Sphk/*
2952800Sphk * Stuff to describe the MUNIC32X and FALC54 chips.
3052800Sphk */
3152800Sphk
3252800Sphk#define M32_CHAN	32	/* We have 32 channels */
3352800Sphk#define M32_TS		32	/* We have 32 timeslots */
3452800Sphk
3552800Sphk#define NG_MN_NODE_TYPE	"mn"
3652800Sphk
3752800Sphk#include <sys/param.h>
3852800Sphk#include <sys/kernel.h>
3957519Sphk#include <sys/sysctl.h>
4062924Sphk#include <sys/bus.h>
4162924Sphk#include <sys/mbuf.h>
4262924Sphk#include <sys/systm.h>
4352800Sphk#include <sys/malloc.h>
4462924Sphk
45119288Simp#include <dev/pci/pcireg.h>
46119288Simp#include <dev/pci/pcivar.h>
4762924Sphk#include "pci_if.h"
4862924Sphk
4962924Sphk#include <machine/bus.h>
5062924Sphk#include <machine/resource.h>
5162924Sphk
5262924Sphk#include <sys/rman.h>
5362924Sphk
5452800Sphk#include <vm/vm.h>
5552800Sphk#include <vm/pmap.h>
5652800Sphk
5752800Sphk#include <netgraph/ng_message.h>
5852800Sphk#include <netgraph/netgraph.h>
5952800Sphk
6058701Simp
6157519Sphkstatic int mn_maxlatency = 1000;
6257519SphkSYSCTL_INT(_debug, OID_AUTO, mn_maxlatency, CTLFLAG_RW,
6357519Sphk    &mn_maxlatency, 0,
6457519Sphk	"The number of milliseconds a packet is allowed to spend in the output queue.  "
6557519Sphk	"If the output queue is longer than this number of milliseconds when the packet "
6657519Sphk	"arrives for output, the packet will be dropped."
6757519Sphk);
6857519Sphk
6952800Sphk#ifndef NMN
7052800Sphk/* Most machines don't support more than 4 busmaster PCI slots, if even that many */
7152800Sphk#define NMN	4
7252800Sphk#endif
7352800Sphk
7452800Sphk/* From: PEB 20321 data sheet, p187, table 22 */
7552800Sphkstruct m32xreg {
7652800Sphk	u_int32_t conf,    cmd,     stat,    imask;
7752800Sphk	u_int32_t fill10,  piqba,   piql,    fill1c;
7852800Sphk	u_int32_t mode1,   mode2,   ccba,    txpoll;
7952800Sphk	u_int32_t tiqba,   tiql,    riqba,   riql;
8052800Sphk	u_int32_t lconf,   lccba,   fill48,  ltran;
8152800Sphk	u_int32_t ltiqba,  ltiql,   lriqba,  lriql;
8252800Sphk	u_int32_t lreg0,   lreg1,   lreg2,   lreg3;
8352800Sphk	u_int32_t lreg4,   lreg5,   lre6,    lstat;
8452800Sphk	u_int32_t gpdir,   gpdata,  gpod,    fill8c;
8552800Sphk	u_int32_t ssccon,  sscbr,   ssctb,   sscrb;
8652800Sphk	u_int32_t ssccse,  sscim,   fillab,  fillac;
8752800Sphk	u_int32_t iomcon1, iomcon2, iomstat, fillbc;
8852800Sphk	u_int32_t iomcit0, iomcit1, iomcir0, iomcir1;
8952800Sphk	u_int32_t iomtmo,  iomrmo,  filld8,  filldc;
9052800Sphk	u_int32_t mbcmd,   mbdata1, mbdata2, mbdata3;
9152800Sphk	u_int32_t mbdata4, mbdata5, mbdata6, mbdata7;
9252800Sphk};
9352800Sphk
9452800Sphk/* From: PEB 2254 data sheet, p80, table 10 */
9552800Sphkstruct f54wreg {
9652800Sphk	u_int16_t xfifo;
9752800Sphk	u_int8_t                  cmdr,   mode,   rah1,   rah2,   ral1,   ral2;
9852800Sphk	u_int8_t  ipc,    ccr1,   ccr3,   pre,    rtr1,   rtr2,   rtr3,   rtr4;
9952800Sphk	u_int8_t  ttr1,   ttr2,   ttr3,   ttr4,   imr0,   imr1,   imr2,   imr3;
10052800Sphk	u_int8_t  imr4,   fill19, fmr0,   fmr1,   fmr2,   loop,   xsw,    xsp;
10152800Sphk	u_int8_t  xc0,    xc1,    rc0,    rc1,    xpm0,   xpm1,   xpm2,   tswm;
10252800Sphk	u_int8_t  test1,  idle,   xsa4,   xsa5,   xsa6,   xsa7,   xsa8,   fmr3;
10352800Sphk	u_int8_t  icb1,   icb2,   icb3,   icb4,   lim0,   lim1,   pcd,    pcr;
10452800Sphk	u_int8_t  lim2,   fill39[7];
10552800Sphk	u_int8_t  fill40[8];
10652800Sphk	u_int8_t  fill48[8];
10752800Sphk	u_int8_t  fill50[8];
10852800Sphk	u_int8_t  fill58[8];
10952800Sphk	u_int8_t  dec,    fill61, test2,  fill63[5];
11052800Sphk	u_int8_t  fill68[8];
11152800Sphk	u_int8_t  xs[16];
11252800Sphk};
11352800Sphk
11452800Sphk/* From: PEB 2254 data sheet, p117, table 10 */
11552800Sphkstruct f54rreg {
11652800Sphk	u_int16_t rfifo;
11752800Sphk	u_int8_t                  fill2,  mode,   rah1,   rah2,   ral1,   ral2;
11852800Sphk	u_int8_t  ipc,    ccr1,   ccr3,   pre,    rtr1,   rtr2,   rtr3,   rtr4;
11952800Sphk	u_int8_t  ttr1,   ttr2,   ttr3,   ttr4,   imr0,   imr1,   imr2,   imr3;
12052800Sphk	u_int8_t  imr4,   fill19, fmr0,   fmr1,   fmr2,   loop,   xsw,    xsp;
12152800Sphk	u_int8_t  xc0,    xc1,    rc0,    rc1,    xpm0,   xpm1,   xpm2,   tswm;
12252800Sphk	u_int8_t  test,   idle,   xsa4,   xsa5,   xsa6,   xsa7,   xsa8,   fmr13;
12352800Sphk	u_int8_t  icb1,   icb2,   icb3,   icb4,   lim0,   lim1,   pcd,    pcr;
12452800Sphk	u_int8_t  lim2,   fill39[7];
12552800Sphk	u_int8_t  fill40[8];
12652800Sphk	u_int8_t  fill48[4],                      frs0,   frs1,   rsw,    rsp;
12752800Sphk	u_int16_t fec,            cvc,            cec1,           ebc;
12852800Sphk	u_int16_t cec2,           cec3;
12952800Sphk	u_int8_t                                  rsa4,   rsa5,   rsa6,   rsa7;
13052800Sphk	u_int8_t  rsa8,   rsa6s,  tsr0,   tsr1,   sis,    rsis;
13152800Sphk	u_int16_t                                                 rbc;
13252800Sphk	u_int8_t  isr0,   isr1,   isr2,   isr3,   fill6c, fill6d, gis,    vstr;
13352800Sphk	u_int8_t  rs[16];
13452800Sphk};
13552800Sphk
13652800Sphk/* Transmit & receive descriptors */
13752800Sphkstruct trxd {
13852800Sphk	u_int32_t	flags;
13952800Sphk	vm_offset_t	next;
14052800Sphk	vm_offset_t	data;
14152800Sphk	u_int32_t	status;	/* only used for receive */
14252800Sphk	struct mbuf	*m;	/* software use only */
14352800Sphk	struct trxd	*vnext;	/* software use only */
14452800Sphk};
14552800Sphk
14652800Sphk/* Channel specification */
14752800Sphkstruct cspec {
14852800Sphk	u_int32_t	flags;
14952800Sphk	vm_offset_t	rdesc;
15052800Sphk	vm_offset_t	tdesc;
15152800Sphk	u_int32_t	itbs;
15252800Sphk};
15352800Sphk
15452800Sphkstruct m32_mem {
15552800Sphk	vm_offset_t	csa;
15652800Sphk	u_int32_t	ccb;
15752800Sphk	u_int32_t	reserve1[2];
15852800Sphk	u_int32_t	ts[M32_TS];
15952800Sphk	struct cspec	cs[M32_CHAN];
16052800Sphk	vm_offset_t	crxd[M32_CHAN];
16152800Sphk	vm_offset_t	ctxd[M32_CHAN];
16252800Sphk};
16352800Sphk
164105213Sphkstruct mn_softc;
16552800Sphkstruct sockaddr;
16652800Sphkstruct rtentry;
16752800Sphk
168142407Simpstatic	int	mn_probe(device_t self);
169142407Simpstatic	int	mn_attach(device_t self);
170105213Sphkstatic	void	mn_create_channel(struct mn_softc *sc, int chan);
171105213Sphkstatic	int	mn_reset(struct mn_softc *sc);
17252800Sphkstatic	struct trxd * mn_alloc_desc(void);
17352800Sphkstatic	void	mn_free_desc(struct trxd *dp);
17452800Sphkstatic	void	mn_intr(void *xsc);
17557519Sphkstatic	u_int32_t mn_parse_ts(const char *s, int *nbit);
17654966Seivind#ifdef notyet
177105213Sphkstatic	void	m32_dump(struct mn_softc *sc);
178105213Sphkstatic	void	f54_dump(struct mn_softc *sc);
17952800Sphkstatic	void	mn_fmt_ts(char *p, u_int32_t ts);
18054966Seivind#endif /* notyet */
181105213Sphkstatic	void	f54_init(struct mn_softc *sc);
18252800Sphk
18352800Sphkstatic	ng_constructor_t ngmn_constructor;
18452800Sphkstatic	ng_rcvmsg_t ngmn_rcvmsg;
18552800Sphkstatic	ng_shutdown_t ngmn_shutdown;
18652800Sphkstatic	ng_newhook_t ngmn_newhook;
18752800Sphkstatic	ng_connect_t ngmn_connect;
18852800Sphkstatic	ng_rcvdata_t ngmn_rcvdata;
18952800Sphkstatic	ng_disconnect_t ngmn_disconnect;
19052800Sphk
19152800Sphkstatic struct ng_type mntypestruct = {
192129823Sjulian	.version =	NG_ABI_VERSION,
193129823Sjulian	.name =		NG_MN_NODE_TYPE,
194129823Sjulian	.constructor =	ngmn_constructor,
195129823Sjulian	.rcvmsg =	ngmn_rcvmsg,
196129823Sjulian	.shutdown =	ngmn_shutdown,
197129823Sjulian	.newhook =	ngmn_newhook,
198129823Sjulian	.connect =	ngmn_connect,
199129823Sjulian	.rcvdata =	ngmn_rcvdata,
200129823Sjulian	.disconnect =	ngmn_disconnect,
20152800Sphk};
20252800Sphk
20352800Sphkstatic MALLOC_DEFINE(M_MN, "mn", "Mx driver related");
20452800Sphk
20552800Sphk#define NIQB	64
20652800Sphk
20752800Sphkstruct schan {
20852800Sphk	enum {DOWN, UP} state;
209105213Sphk	struct mn_softc	*sc;
21052800Sphk	int		chan;
21152800Sphk	u_int32_t	ts;
21252800Sphk	char		name[8];
21352800Sphk	struct trxd	*r1, *rl;
21452800Sphk	struct trxd	*x1, *xl;
21552800Sphk	hook_p		hook;
21652800Sphk
21752800Sphk	time_t		last_recv;
21852800Sphk	time_t		last_rxerr;
21952800Sphk	time_t		last_xmit;
22052800Sphk
22152800Sphk	u_long		rx_error;
22252800Sphk
22352800Sphk	u_long		short_error;
22452800Sphk	u_long		crc_error;
22552800Sphk	u_long		dribble_error;
22652800Sphk	u_long		long_error;
22752800Sphk	u_long		abort_error;
22852800Sphk	u_long		overflow_error;
22952800Sphk
23052800Sphk	int		last_error;
23152800Sphk	int		prev_error;
23257519Sphk
23357519Sphk	u_long		tx_pending;
23457519Sphk	u_long		tx_limit;
23552800Sphk};
23652800Sphk
23771344Sphkenum framing {WHOKNOWS, E1, E1U, T1, T1U};
23871344Sphk
239105213Sphkstruct mn_softc {
24052800Sphk	int	unit;
24162924Sphk	device_t	dev;
24262924Sphk	struct resource *irq;
24362924Sphk	void *intrhand;
24471344Sphk	enum framing	framing;
24571344Sphk	int 		nhooks;
24662924Sphk	void 		*m0v, *m1v;
24762924Sphk	vm_offset_t	m0p, m1p;
24852800Sphk	struct m32xreg	*m32x;
24952800Sphk	struct f54wreg	*f54w;
25052800Sphk	struct f54rreg	*f54r;
25152800Sphk	struct m32_mem	m32_mem;
25252800Sphk	u_int32_t	tiqb[NIQB];
25352800Sphk	u_int32_t	riqb[NIQB];
25452800Sphk	u_int32_t	piqb[NIQB];
25552800Sphk	u_int32_t	ltiqb[NIQB];
25652800Sphk	u_int32_t	lriqb[NIQB];
25752800Sphk	char		name[8];
25852800Sphk	u_int32_t	falc_irq, falc_state, framer_state;
25952800Sphk	struct schan *ch[M32_CHAN];
260130879Sphk	char	nodename[NG_NODESIZ];
26152800Sphk	node_p	node;
26252800Sphk
26352800Sphk	u_long		cnt_fec;
26452800Sphk	u_long		cnt_cvc;
26552800Sphk	u_long		cnt_cec1;
26652800Sphk	u_long		cnt_ebc;
26752800Sphk	u_long		cnt_cec2;
26852800Sphk	u_long		cnt_cec3;
26952800Sphk	u_long		cnt_rbc;
27062924Sphk};
27152800Sphk
27252800Sphkstatic int
27370700Sjulianngmn_constructor(node_p node)
27452800Sphk{
27552800Sphk
27652800Sphk	return (EINVAL);
27752800Sphk}
27852800Sphk
27952800Sphkstatic int
28052800Sphkngmn_shutdown(node_p nodep)
28152800Sphk{
28252800Sphk
28352800Sphk	return (EINVAL);
28452800Sphk}
28552800Sphk
28671344Sphkstatic void
28771344Sphkngmn_config(node_p node, char *set, char *ret)
28871344Sphk{
289105213Sphk	struct mn_softc *sc;
29071344Sphk	enum framing wframing;
29171344Sphk
29271344Sphk	sc = NG_NODE_PRIVATE(node);
29371344Sphk
29471344Sphk	if (set != NULL) {
29571344Sphk		if (!strncmp(set, "line ", 5)) {
29671344Sphk			wframing = sc->framing;
29771344Sphk			if (!strcmp(set, "line e1")) {
29871344Sphk				wframing = E1;
29971344Sphk			} else if (!strcmp(set, "line e1u")) {
30071344Sphk				wframing = E1U;
30171344Sphk			} else {
30271344Sphk				strcat(ret, "ENOGROK\n");
30371344Sphk				return;
30471344Sphk			}
30571344Sphk			if (wframing == sc->framing)
30671344Sphk				return;
30771344Sphk			if (sc->nhooks > 0) {
30871344Sphk				sprintf(ret, "Cannot change line when %d hooks open\n", sc->nhooks);
30971344Sphk				return;
31071344Sphk			}
31171344Sphk			sc->framing = wframing;
31271344Sphk#if 1
31371344Sphk			f54_init(sc);
31471344Sphk#else
31571344Sphk			mn_reset(sc);
31671344Sphk#endif
31771344Sphk		} else {
31871344Sphk			printf("%s CONFIG SET [%s]\n", sc->nodename, set);
31971344Sphk			strcat(ret, "ENOGROK\n");
32071344Sphk			return;
32171344Sphk		}
32271344Sphk	}
32371344Sphk
32471344Sphk}
32571344Sphk
32652800Sphkstatic int
32770700Sjulianngmn_rcvmsg(node_p node, item_p item, hook_p lasthook)
32852800Sphk{
329105213Sphk	struct mn_softc *sc;
33070159Sjulian	struct ng_mesg *resp = NULL;
33152800Sphk	struct schan *sch;
33271344Sphk	char *s, *r;
33352800Sphk	int pos, i;
33470700Sjulian	struct ng_mesg *msg;
33552800Sphk
33670700Sjulian	NGI_GET_MSG(item, msg);
33770784Sjulian	sc = NG_NODE_PRIVATE(node);
33852800Sphk
33971344Sphk	if (msg->header.typecookie != NGM_GENERIC_COOKIE) {
34071344Sphk		NG_FREE_ITEM(item);
34171344Sphk		NG_FREE_MSG(msg);
34271344Sphk		return (EINVAL);
34371344Sphk	}
34471344Sphk
34571344Sphk	if (msg->header.cmd != NGM_TEXT_CONFIG &&
34652800Sphk	    msg->header.cmd != NGM_TEXT_STATUS) {
34770700Sjulian		NG_FREE_ITEM(item);
34870700Sjulian		NG_FREE_MSG(msg);
34952800Sphk		return (EINVAL);
35052800Sphk	}
35171344Sphk
35270159Sjulian	NG_MKRESPONSE(resp, msg, sizeof(struct ng_mesg) + NG_TEXTRESPONSE,
35352800Sphk	    M_NOWAIT);
35470159Sjulian	if (resp == NULL) {
35570700Sjulian		NG_FREE_ITEM(item);
35670700Sjulian		NG_FREE_MSG(msg);
35752800Sphk		return (ENOMEM);
35852800Sphk	}
35971344Sphk
36071344Sphk	if (msg->header.arglen)
36171344Sphk		s = (char *)msg->data;
36271344Sphk	else
36371344Sphk		s = NULL;
36471344Sphk	r = (char *)resp->data;
36571344Sphk	*r = '\0';
36671344Sphk
36771344Sphk	if (msg->header.cmd == NGM_TEXT_CONFIG) {
36871344Sphk		ngmn_config(node, s, r);
36971344Sphk		resp->header.arglen = strlen(r) + 1;
370101336Sphk		NG_RESPOND_MSG(i, node, item, resp);
371130415Sphk		NG_FREE_MSG(msg);
37271344Sphk		return (0);
37371344Sphk	}
37452800Sphk	pos = 0;
37571344Sphk	pos += sprintf(pos + r,"Framer status %b;\n", sc->framer_state, "\20"
37652800Sphk	    "\40LOS\37AIS\36LFA\35RRA"
37752800Sphk	    "\34AUXP\33NMF\32LMFA\31frs0.0"
37852800Sphk	    "\30frs1.7\27TS16RA\26TS16LOS\25TS16AIS"
37952800Sphk	    "\24TS16LFA\23frs1.2\22XLS\21XLO"
38052800Sphk	    "\20RS1\17rsw.6\16RRA\15RY0"
38152800Sphk	    "\14RY1\13RY2\12RY3\11RY4"
38252800Sphk	    "\10SI1\7SI2\6rsp.5\5rsp.4"
38352800Sphk	    "\4rsp.3\3RSIF\2RS13\1RS15");
38471344Sphk	pos += sprintf(pos + r,"    Framing errors: %lu", sc->cnt_fec);
38571344Sphk	pos += sprintf(pos + r,"  Code Violations: %lu\n", sc->cnt_cvc);
38652800Sphk
38771344Sphk	pos += sprintf(pos + r,"    Falc State %b;\n", sc->falc_state, "\20"
38852800Sphk	    "\40LOS\37AIS\36LFA\35RRA"
38952800Sphk	    "\34AUXP\33NMF\32LMFA\31frs0.0"
39052800Sphk	    "\30frs1.7\27TS16RA\26TS16LOS\25TS16AIS"
39152800Sphk	    "\24TS16LFA\23frs1.2\22XLS\21XLO"
39252800Sphk	    "\20RS1\17rsw.6\16RRA\15RY0"
39352800Sphk	    "\14RY1\13RY2\12RY3\11RY4"
39452800Sphk	    "\10SI1\7SI2\6rsp.5\5rsp.4"
39552800Sphk	    "\4rsp.3\3RSIF\2RS13\1RS15");
39671344Sphk	pos += sprintf(pos + r, "    Falc IRQ %b\n", sc->falc_irq, "\20"
39752800Sphk	    "\40RME\37RFS\36T8MS\35RMB\34CASC\33CRC4\32SA6SC\31RPF"
39852800Sphk	    "\30b27\27RDO\26ALLS\25XDU\24XMB\23b22\22XLSC\21XPR"
39952800Sphk	    "\20FAR\17LFA\16MFAR\15T400MS\14AIS\13LOS\12RAR\11RA"
40052800Sphk	    "\10ES\7SEC\6LMFA16\5AIS16\4RA16\3API\2SLN\1SLP");
40152800Sphk	for (i = 0; i < M32_CHAN; i++) {
40252800Sphk		if (!sc->ch[i])
40352800Sphk			continue;
40452800Sphk		sch = sc->ch[i];
40552800Sphk
40671344Sphk		pos += sprintf(r + pos, "  Chan %d <%s> ",
40770784Sjulian		    i, NG_HOOK_NAME(sch->hook));
40852800Sphk
40971344Sphk		pos += sprintf(r + pos, "  Last Rx: ");
41052800Sphk		if (sch->last_recv)
41178254Speter			pos += sprintf(r + pos, "%lu s",
41278254Speter			    (unsigned long)(time_second - sch->last_recv));
41352800Sphk		else
41471344Sphk			pos += sprintf(r + pos, "never");
41552800Sphk
41671344Sphk		pos += sprintf(r + pos, ", last RxErr: ");
41752800Sphk		if (sch->last_rxerr)
41878254Speter			pos += sprintf(r + pos, "%lu s",
41978254Speter			    (unsigned long)(time_second - sch->last_rxerr));
42052800Sphk		else
42171344Sphk			pos += sprintf(r + pos, "never");
42252800Sphk
42371344Sphk		pos += sprintf(r + pos, ", last Tx: ");
42452800Sphk		if (sch->last_xmit)
42578254Speter			pos += sprintf(r + pos, "%lu s\n",
42678254Speter			    (unsigned long)(time_second - sch->last_xmit));
42752800Sphk		else
42871344Sphk			pos += sprintf(r + pos, "never\n");
42952800Sphk
43071344Sphk		pos += sprintf(r + pos, "    RX error(s) %lu", sch->rx_error);
43171344Sphk		pos += sprintf(r + pos, " Short: %lu", sch->short_error);
43271344Sphk		pos += sprintf(r + pos, " CRC: %lu", sch->crc_error);
43371344Sphk		pos += sprintf(r + pos, " Mod8: %lu", sch->dribble_error);
43471344Sphk		pos += sprintf(r + pos, " Long: %lu", sch->long_error);
43571344Sphk		pos += sprintf(r + pos, " Abort: %lu", sch->abort_error);
43671344Sphk		pos += sprintf(r + pos, " Overflow: %lu\n", sch->overflow_error);
43752800Sphk
43871344Sphk		pos += sprintf(r + pos, "    Last error: %b  Prev error: %b\n",
43952800Sphk		    sch->last_error, "\20\7SHORT\5CRC\4MOD8\3LONG\2ABORT\1OVERRUN",
44052800Sphk		    sch->prev_error, "\20\7SHORT\5CRC\4MOD8\3LONG\2ABORT\1OVERRUN");
44171344Sphk		pos += sprintf(r + pos, "    Xmit bytes pending %ld\n",
44257678Sphk		    sch->tx_pending);
44352800Sphk	}
44470159Sjulian	resp->header.arglen = pos + 1;
44570159Sjulian
44670159Sjulian	/* Take care of synchronous response, if any */
44770700Sjulian	NG_RESPOND_MSG(i, node, item, resp);
44870700Sjulian	NG_FREE_MSG(msg);
44952800Sphk	return (0);
45052800Sphk}
45152800Sphk
45252800Sphkstatic int
45352800Sphkngmn_newhook(node_p node, hook_p hook, const char *name)
45452800Sphk{
45552800Sphk	u_int32_t ts, chan;
456105213Sphk	struct mn_softc *sc;
45757519Sphk	int nbit;
45852800Sphk
45970784Sjulian	sc = NG_NODE_PRIVATE(node);
46052800Sphk
46152800Sphk	if (name[0] != 't' || name[1] != 's')
46252800Sphk		return (EINVAL);
46352800Sphk
46457519Sphk	ts = mn_parse_ts(name + 2, &nbit);
46571344Sphk	printf("%d bits %x\n", nbit, ts);
46671344Sphk	if (sc->framing == E1 && (ts & 1))
46771344Sphk		return (EINVAL);
46871344Sphk	if (sc->framing == E1U && nbit != 32)
46971344Sphk		return (EINVAL);
47052800Sphk	if (ts == 0)
47152800Sphk		return (EINVAL);
47271344Sphk	if (sc->framing == E1)
47371344Sphk		chan = ffs(ts) - 1;
47471344Sphk	else
47571344Sphk		chan = 1;
47658700Sphk	if (!sc->ch[chan])
47758700Sphk		mn_create_channel(sc, chan);
47858700Sphk	else if (sc->ch[chan]->state == UP)
47952800Sphk		return (EBUSY);
48052800Sphk	sc->ch[chan]->ts = ts;
48152800Sphk	sc->ch[chan]->hook = hook;
48257519Sphk	sc->ch[chan]->tx_limit = nbit * 8;
48370784Sjulian	NG_HOOK_SET_PRIVATE(hook, sc->ch[chan]);
48471344Sphk	sc->nhooks++;
48552800Sphk	return(0);
48652800Sphk}
48752800Sphk
48852800Sphk
48952800Sphkstatic struct trxd *mn_desc_free;
49052800Sphk
49152800Sphkstatic struct trxd *
49252800Sphkmn_alloc_desc(void)
49352800Sphk{
49452800Sphk	struct trxd *dp;
49552800Sphk
49652800Sphk	dp = mn_desc_free;
49752800Sphk	if (dp)
49852800Sphk		mn_desc_free = dp->vnext;
49952800Sphk	else
50052800Sphk		dp = (struct trxd *)malloc(sizeof *dp, M_MN, M_NOWAIT);
50152800Sphk	return (dp);
50252800Sphk}
50352800Sphk
50452800Sphkstatic void
50552800Sphkmn_free_desc(struct trxd *dp)
50652800Sphk{
50752800Sphk	dp->vnext =  mn_desc_free;
50852800Sphk	mn_desc_free = dp;
50952800Sphk}
51052800Sphk
51152800Sphkstatic u_int32_t
51257519Sphkmn_parse_ts(const char *s, int *nbit)
51352800Sphk{
51452800Sphk	unsigned r;
51552800Sphk	int i, j;
51653648Sarchie	char *p;
51752800Sphk
51852800Sphk	r = 0;
51971344Sphk	j = -1;
52057519Sphk	*nbit = 0;
52152800Sphk	while(*s) {
52252800Sphk		i = strtol(s, &p, 0);
52371344Sphk		if (i < 0 || i > 31)
52452800Sphk			return (0);
52571344Sphk		while (j != -1 && j < i) {
52652800Sphk			r |= 1 << j++;
52757519Sphk			(*nbit)++;
52852800Sphk		}
52971344Sphk		j = -1;
53052800Sphk		r |= 1 << i;
53157519Sphk		(*nbit)++;
53252800Sphk		if (*p == ',') {
53355088Sbde			s = p + 1;
53452800Sphk			continue;
53552800Sphk		} else if (*p == '-') {
53671344Sphk			j = i + 1;
53755088Sbde			s = p + 1;
53852800Sphk			continue;
53952800Sphk		} else if (!*p) {
54052800Sphk			break;
54152800Sphk		} else {
54252800Sphk			return (0);
54352800Sphk		}
54452800Sphk	}
54552800Sphk	return (r);
54652800Sphk}
54752800Sphk
54854966Seivind#ifdef notyet
54952800Sphkstatic void
55052800Sphkmn_fmt_ts(char *p, u_int32_t ts)
55152800Sphk{
55252800Sphk	char *s;
55352800Sphk	int j;
55452800Sphk
55552800Sphk	s = "";
55671344Sphk	ts &= 0xffffffff;
55771344Sphk	for (j = 0; j < 32; j++) {
55852800Sphk		if (!(ts & (1 << j)))
55952800Sphk			continue;
56052800Sphk		sprintf(p, "%s%d", s, j);
56152800Sphk		p += strlen(p);
56252800Sphk		s = ",";
56352800Sphk		if (!(ts & (1 << (j+1))))
56452800Sphk			continue;
56552800Sphk		for (; j < 32; j++)
56652800Sphk			if (!(ts & (1 << (j+1))))
56752800Sphk				break;
56852800Sphk		sprintf(p, "-%d", j);
56952800Sphk		p += strlen(p);
57052800Sphk		s = ",";
57152800Sphk	}
57252800Sphk}
57354966Seivind#endif /* notyet */
57452800Sphk
57552800Sphk/*
57652800Sphk * OUTPUT
57752800Sphk */
57852800Sphk
57952800Sphkstatic int
58070700Sjulianngmn_rcvdata(hook_p hook, item_p item)
58152800Sphk{
58252800Sphk	struct mbuf  *m2;
58352800Sphk	struct trxd *dp, *dp2;
58452800Sphk	struct schan *sch;
585105213Sphk	struct mn_softc *sc;
58652800Sphk	int chan, pitch, len;
58770700Sjulian	struct mbuf *m;
58852800Sphk
58970784Sjulian	sch = NG_HOOK_PRIVATE(hook);
59052800Sphk	sc = sch->sc;
59152800Sphk	chan = sch->chan;
59252800Sphk
59357519Sphk	if (sch->state != UP) {
59470700Sjulian		NG_FREE_ITEM(item);
59552800Sphk		return (0);
59652800Sphk	}
59770700Sjulian	NGI_GET_M(item, m);
59857519Sphk	if (sch->tx_pending + m->m_pkthdr.len > sch->tx_limit * mn_maxlatency) {
59970700Sjulian		NG_FREE_M(m);
60070700Sjulian		NG_FREE_ITEM(item);
60157519Sphk		return (0);
60257519Sphk	}
60370700Sjulian	NG_FREE_ITEM(item);
60452800Sphk	pitch = 0;
60552800Sphk	m2 = m;
60652800Sphk	dp2 = sc->ch[chan]->xl;
60752800Sphk	len = m->m_pkthdr.len;
60852800Sphk	while (len) {
60952800Sphk		dp = mn_alloc_desc();
61052800Sphk		if (!dp) {
61152800Sphk			pitch++;
61252800Sphk			m_freem(m);
61352800Sphk			sc->ch[chan]->xl = dp2;
61452800Sphk			dp = dp2->vnext;
61552800Sphk			while (dp) {
61652800Sphk				dp2 = dp->vnext;
61752800Sphk				mn_free_desc(dp);
61852800Sphk				dp = dp2;
61952800Sphk			}
62052800Sphk			sc->ch[chan]->xl->vnext = 0;
62152800Sphk			break;
62252800Sphk		}
62352800Sphk		dp->data = vtophys(m2->m_data);
62452800Sphk		dp->flags = m2->m_len << 16;
62552800Sphk		dp->flags += 1;
62652800Sphk		len -= m2->m_len;
62752800Sphk		dp->next = vtophys(dp);
62852800Sphk		dp->vnext = 0;
62952800Sphk		sc->ch[chan]->xl->next = vtophys(dp);
63052800Sphk		sc->ch[chan]->xl->vnext = dp;
63152800Sphk		sc->ch[chan]->xl = dp;
63252800Sphk		if (!len) {
63352800Sphk			dp->m = m;
63452800Sphk			dp->flags |= 0xc0000000;
63552800Sphk			dp2->flags &= ~0x40000000;
63652800Sphk		} else {
63752800Sphk			dp->m = 0;
63852800Sphk			m2 = m2->m_next;
63952800Sphk		}
64052800Sphk	}
64152800Sphk	if (pitch)
64252800Sphk		printf("%s%d: Short on mem, pitched %d packets\n",
64352800Sphk		    sc->name, chan, pitch);
64457678Sphk	else {
64557678Sphk#if 0
64657678Sphk		printf("%d = %d + %d (%p)\n",
64757678Sphk		    sch->tx_pending + m->m_pkthdr.len,
64857678Sphk		    sch->tx_pending , m->m_pkthdr.len, m);
64957678Sphk#endif
65057519Sphk		sch->tx_pending += m->m_pkthdr.len;
65171344Sphk		sc->m32x->txpoll &= ~(1 << chan);
65257678Sphk	}
65352800Sphk	return (0);
65452800Sphk}
65552800Sphk
65652800Sphk/*
65752800Sphk * OPEN
65852800Sphk */
65952800Sphkstatic int
66052800Sphkngmn_connect(hook_p hook)
66152800Sphk{
66252800Sphk	int i, nts, chan;
66352800Sphk	struct trxd *dp, *dp2;
66452800Sphk	struct mbuf *m;
665105213Sphk	struct mn_softc *sc;
66652800Sphk	struct schan *sch;
66752800Sphk	u_int32_t u;
66852800Sphk
66970784Sjulian	sch = NG_HOOK_PRIVATE(hook);
67052800Sphk	chan = sch->chan;
67152800Sphk	sc = sch->sc;
67252800Sphk
67352800Sphk	if (sch->state == UP)
67452800Sphk		return (0);
67552800Sphk	sch->state = UP;
67652800Sphk
67752800Sphk	/* Count and configure the timeslots for this channel */
67852800Sphk	for (nts = i = 0; i < 32; i++)
67952800Sphk		if (sch->ts & (1 << i)) {
68052800Sphk			sc->m32_mem.ts[i] = 0x00ff00ff |
68152800Sphk				(chan << 24) | (chan << 8);
68252800Sphk			nts++;
68352800Sphk		}
68452800Sphk
68552800Sphk	/* Init the receiver & xmitter to HDLC */
68652800Sphk	sc->m32_mem.cs[chan].flags = 0x80e90006;
68752800Sphk	/* Allocate two buffers per timeslot */
68871344Sphk	if (nts == 32)
68971344Sphk		sc->m32_mem.cs[chan].itbs = 63;
69071344Sphk	else
69171344Sphk		sc->m32_mem.cs[chan].itbs = nts * 2;
69252800Sphk
69352800Sphk	/* Setup a transmit chain with one descriptor */
69452800Sphk	/* XXX: we actually send a 1 byte packet */
69552800Sphk	dp = mn_alloc_desc();
696243857Sglebius	MGETHDR(m, M_WAITOK, MT_DATA);
69757678Sphk	m->m_pkthdr.len = 0;
69852800Sphk	dp->m = m;
69952800Sphk	dp->flags = 0xc0000000 + (1 << 16);
70052800Sphk	dp->next = vtophys(dp);
70152800Sphk	dp->vnext = 0;
70252800Sphk	dp->data = vtophys(sc->name);
70352800Sphk	sc->m32_mem.cs[chan].tdesc = vtophys(dp);
70452800Sphk	sc->ch[chan]->x1 = dp;
70552800Sphk	sc->ch[chan]->xl = dp;
70652800Sphk
70752800Sphk	/* Setup a receive chain with 5 + NTS descriptors */
70852800Sphk
70952800Sphk	dp = mn_alloc_desc();
71070068Sbmilekic	m = NULL;
711243857Sglebius	MGETHDR(m, M_WAITOK, MT_DATA);
712243857Sglebius	MCLGET(m, M_WAITOK);
71352800Sphk	dp->m = m;
71452800Sphk	dp->data = vtophys(m->m_data);
71552800Sphk	dp->flags = 0x40000000;
71652800Sphk	dp->flags += 1600 << 16;
71752800Sphk	dp->next = vtophys(dp);
71852800Sphk	dp->vnext = 0;
71952800Sphk	sc->ch[chan]->rl = dp;
72052800Sphk
72152800Sphk	for (i = 0; i < (nts + 10); i++) {
72252800Sphk		dp2 = dp;
72352800Sphk		dp = mn_alloc_desc();
72470068Sbmilekic		m = NULL;
725243857Sglebius		MGETHDR(m, M_WAITOK, MT_DATA);
726243857Sglebius		MCLGET(m, M_WAITOK);
72752800Sphk		dp->m = m;
72852800Sphk		dp->data = vtophys(m->m_data);
72952800Sphk		dp->flags = 0x00000000;
73052800Sphk		dp->flags += 1600 << 16;
73152800Sphk		dp->next = vtophys(dp2);
73252800Sphk		dp->vnext = dp2;
73352800Sphk	}
73452800Sphk	sc->m32_mem.cs[chan].rdesc = vtophys(dp);
73552800Sphk	sc->ch[chan]->r1 = dp;
73652800Sphk
73752800Sphk	/* Initialize this channel */
73852800Sphk	sc->m32_mem.ccb = 0x00008000 + (chan << 8);
73952800Sphk	sc->m32x->cmd = 0x1;
74057678Sphk	DELAY(1000);
74152800Sphk	u = sc->m32x->stat;
74252800Sphk	if (!(u & 1))
74352800Sphk		printf("%s: init chan %d stat %08x\n", sc->name, chan, u);
74452800Sphk	sc->m32x->stat = 1;
74569922Sjulian	/* probably not at splnet, force outward queueing */
74670784Sjulian	NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
74752800Sphk
74852800Sphk	return (0);
74952800Sphk}
75052800Sphk
75152800Sphk/*
75252800Sphk * CLOSE
75352800Sphk */
75452800Sphkstatic int
75552800Sphkngmn_disconnect(hook_p hook)
75652800Sphk{
75752800Sphk	int chan, i;
758105213Sphk	struct mn_softc *sc;
75952800Sphk	struct schan *sch;
76052800Sphk	struct trxd *dp, *dp2;
76152800Sphk	u_int32_t u;
76252800Sphk
76370784Sjulian	sch = NG_HOOK_PRIVATE(hook);
76452800Sphk	chan = sch->chan;
76552800Sphk	sc = sch->sc;
76652800Sphk
76752800Sphk	if (sch->state == DOWN)
76852800Sphk		return (0);
76952800Sphk	sch->state = DOWN;
77052800Sphk
77152800Sphk	/* Set receiver & transmitter off */
77252800Sphk	sc->m32_mem.cs[chan].flags = 0x80920006;
77352800Sphk	sc->m32_mem.cs[chan].itbs = 0;
77452800Sphk
77552800Sphk	/* free the timeslots */
77652800Sphk	for (i = 0; i < 32; i++)
77752800Sphk		if (sc->ch[chan]->ts & (1 << i))
77852800Sphk			sc->m32_mem.ts[i] = 0x20002000;
77952800Sphk
78052800Sphk	/* Initialize this channel */
78152800Sphk	sc->m32_mem.ccb = 0x00008000 + (chan << 8);
78252800Sphk	sc->m32x->cmd = 0x1;
78352800Sphk	DELAY(30);
78452800Sphk	u = sc->m32x->stat;
78552800Sphk	if (!(u & 1))
78652800Sphk		printf("%s: zap chan %d stat %08x\n", sc->name, chan, u);
78752800Sphk	sc->m32x->stat = 1;
78852800Sphk
78952800Sphk	/* Free all receive descriptors and mbufs */
79052800Sphk	for (dp = sc->ch[chan]->r1; dp ; dp = dp2) {
79152800Sphk		if (dp->m)
79252800Sphk			m_freem(dp->m);
79352800Sphk		sc->ch[chan]->r1 = dp2 = dp->vnext;
79452800Sphk		mn_free_desc(dp);
79552800Sphk	}
79652800Sphk
79752800Sphk	/* Free all transmit descriptors and mbufs */
79852800Sphk	for (dp = sc->ch[chan]->x1; dp ; dp = dp2) {
79962467Sphk		if (dp->m) {
80062467Sphk			sc->ch[chan]->tx_pending -= dp->m->m_pkthdr.len;
80152800Sphk			m_freem(dp->m);
80262467Sphk		}
80352800Sphk		sc->ch[chan]->x1 = dp2 = dp->vnext;
80452800Sphk		mn_free_desc(dp);
80552800Sphk	}
80671344Sphk	sc->nhooks--;
80752800Sphk	return(0);
80852800Sphk}
80952800Sphk
81052800Sphk/*
81152800Sphk * Create a new channel.
81252800Sphk */
81352800Sphkstatic void
814105213Sphkmn_create_channel(struct mn_softc *sc, int chan)
81552800Sphk{
81652800Sphk	struct schan *sch;
81752800Sphk
81852800Sphk	sch = sc->ch[chan] = (struct schan *)malloc(sizeof *sc->ch[chan],
819111119Simp	    M_MN, M_WAITOK | M_ZERO);
82052800Sphk	sch->sc = sc;
82152800Sphk	sch->state = DOWN;
82252800Sphk	sch->chan = chan;
82352800Sphk	sprintf(sch->name, "%s%d", sc->name, chan);
82452800Sphk	return;
82552800Sphk}
82652800Sphk
82754966Seivind#ifdef notyet
82852800Sphk/*
82952800Sphk * Dump Munich32x state
83052800Sphk */
83152800Sphkstatic void
832105213Sphkm32_dump(struct mn_softc *sc)
83352800Sphk{
83452800Sphk	u_int32_t *tp4;
83552800Sphk	int i, j;
83652800Sphk
83752800Sphk	printf("mn%d: MUNICH32X dump\n", sc->unit);
83852800Sphk	tp4 = (u_int32_t *)sc->m0v;
83952800Sphk	for(j = 0; j < 64; j += 8) {
84052800Sphk		printf("%02x", j * sizeof *tp4);
84152800Sphk		for(i = 0; i < 8; i++)
84252800Sphk			printf(" %08x", tp4[i+j]);
84352800Sphk		printf("\n");
84452800Sphk	}
84552800Sphk	for(j = 0; j < M32_CHAN; j++) {
84652800Sphk		if (!sc->ch[j])
84752800Sphk			continue;
84852800Sphk		printf("CH%d: state %d ts %08x",
84952800Sphk			j, sc->ch[j]->state, sc->ch[j]->ts);
85052800Sphk		printf("  %08x %08x %08x %08x %08x %08x\n",
85152800Sphk			sc->m32_mem.cs[j].flags,
85252800Sphk			sc->m32_mem.cs[j].rdesc,
85352800Sphk			sc->m32_mem.cs[j].tdesc,
85452800Sphk			sc->m32_mem.cs[j].itbs,
85552800Sphk			sc->m32_mem.crxd[j],
85652800Sphk			sc->m32_mem.ctxd[j] );
85752800Sphk	}
85852800Sphk}
85952800Sphk
86052800Sphk/*
86152800Sphk * Dump Falch54 state
86252800Sphk */
86352800Sphkstatic void
864105213Sphkf54_dump(struct mn_softc *sc)
86552800Sphk{
86652800Sphk	u_int8_t *tp1;
86752800Sphk	int i, j;
86852800Sphk
86952800Sphk	printf("%s: FALC54 dump\n", sc->name);
87052800Sphk	tp1 = (u_int8_t *)sc->m1v;
87152800Sphk	for(j = 0; j < 128; j += 16) {
87252800Sphk		printf("%s: %02x |", sc->name, j * sizeof *tp1);
87352800Sphk		for(i = 0; i < 16; i++)
87452800Sphk			printf(" %02x", tp1[i+j]);
87552800Sphk		printf("\n");
87652800Sphk	}
87752800Sphk}
87854966Seivind#endif /* notyet */
87952800Sphk
88052800Sphk/*
88152800Sphk * Init Munich32x
88252800Sphk */
88352800Sphkstatic void
884105213Sphkm32_init(struct mn_softc *sc)
88552800Sphk{
88652800Sphk
88752800Sphk	sc->m32x->conf =  0x00000000;
88852800Sphk	sc->m32x->mode1 = 0x81048000 + 1600; 	/* XXX: temp */
88952800Sphk#if 1
89052800Sphk	sc->m32x->mode2 = 0x00000081;
89152800Sphk	sc->m32x->txpoll = 0xffffffff;
89271344Sphk#elif 1
89371344Sphk	sc->m32x->mode2 = 0x00000081;
89471344Sphk	sc->m32x->txpoll = 0xffffffff;
89552800Sphk#else
89652800Sphk	sc->m32x->mode2 = 0x00000101;
89752800Sphk#endif
89852800Sphk	sc->m32x->lconf = 0x6060009B;
89952800Sphk	sc->m32x->imask = 0x00000000;
90052800Sphk}
90152800Sphk
90252800Sphk/*
90352800Sphk * Init the Falc54
90452800Sphk */
90552800Sphkstatic void
906105213Sphkf54_init(struct mn_softc *sc)
90752800Sphk{
90852800Sphk	sc->f54w->ipc  = 0x07;
90952800Sphk
91052800Sphk	sc->f54w->xpm0 = 0xbd;
91152800Sphk	sc->f54w->xpm1 = 0x03;
91252800Sphk	sc->f54w->xpm2 = 0x00;
91352800Sphk
91452800Sphk	sc->f54w->imr0 = 0x18; /* RMB, CASC */
91552800Sphk	sc->f54w->imr1 = 0x08; /* XMB */
91652800Sphk	sc->f54w->imr2 = 0x00;
91752800Sphk	sc->f54w->imr3 = 0x38; /* LMFA16, AIS16, RA16 */
91852800Sphk	sc->f54w->imr4 = 0x00;
91952800Sphk
92052800Sphk	sc->f54w->fmr0 = 0xf0; /* X: HDB3, R: HDB3 */
92152800Sphk	sc->f54w->fmr1 = 0x0e; /* Send CRC4, 2Mbit, ECM */
92271344Sphk	if (sc->framing == E1)
92371344Sphk		sc->f54w->fmr2 = 0x03; /* Auto Rem-Alarm, Auto resync */
92471344Sphk	else if (sc->framing == E1U)
92571344Sphk		sc->f54w->fmr2 = 0x33; /* dais, rtm, Auto Rem-Alarm, Auto resync */
92652800Sphk
92752800Sphk	sc->f54w->lim1 = 0xb0; /* XCLK=8kHz, .62V threshold */
92852800Sphk	sc->f54w->pcd =  0x0a;
92952800Sphk	sc->f54w->pcr =  0x15;
93052800Sphk	sc->f54w->xsw =  0x9f; /* fmr4 */
93171344Sphk	if (sc->framing == E1)
93271344Sphk		sc->f54w->xsp =  0x1c; /* fmr5 */
93371344Sphk	else if (sc->framing == E1U)
93471344Sphk		sc->f54w->xsp =  0x3c; /* tt0, fmr5 */
93552800Sphk	sc->f54w->xc0 =  0x07;
93652800Sphk	sc->f54w->xc1 =  0x3d;
93752800Sphk	sc->f54w->rc0 =  0x05;
93852800Sphk	sc->f54w->rc1 =  0x00;
93952800Sphk	sc->f54w->cmdr = 0x51;
94052800Sphk}
94152800Sphk
94252800Sphkstatic int
943105213Sphkmn_reset(struct mn_softc *sc)
94452800Sphk{
94552800Sphk	u_int32_t u;
94657967Sphk	int i;
94752800Sphk
94852800Sphk	sc->m32x->ccba = vtophys(&sc->m32_mem.csa);
94952800Sphk	sc->m32_mem.csa = vtophys(&sc->m32_mem.ccb);
95052800Sphk
95152800Sphk	bzero(sc->tiqb, sizeof sc->tiqb);
95252800Sphk	sc->m32x->tiqba = vtophys(&sc->tiqb);
95352800Sphk	sc->m32x->tiql = NIQB / 16 - 1;
95452800Sphk
95552800Sphk	bzero(sc->riqb, sizeof sc->riqb);
95652800Sphk	sc->m32x->riqba = vtophys(&sc->riqb);
95752800Sphk	sc->m32x->riql = NIQB / 16 - 1;
95852800Sphk
95952800Sphk	bzero(sc->ltiqb, sizeof sc->ltiqb);
96052800Sphk	sc->m32x->ltiqba = vtophys(&sc->ltiqb);
96152800Sphk	sc->m32x->ltiql = NIQB / 16 - 1;
96252800Sphk
96352800Sphk	bzero(sc->lriqb, sizeof sc->lriqb);
96452800Sphk	sc->m32x->lriqba = vtophys(&sc->lriqb);
96552800Sphk	sc->m32x->lriql = NIQB / 16 - 1;
96652800Sphk
96752800Sphk	bzero(sc->piqb, sizeof sc->piqb);
96852800Sphk	sc->m32x->piqba = vtophys(&sc->piqb);
96952800Sphk	sc->m32x->piql = NIQB / 16 - 1;
97052800Sphk
97152800Sphk	m32_init(sc);
97252800Sphk	f54_init(sc);
97352800Sphk
97452800Sphk	u = sc->m32x->stat;
97552800Sphk	sc->m32x->stat = u;
97652800Sphk	sc->m32_mem.ccb = 0x4;
97752800Sphk	sc->m32x->cmd = 0x1;
97852800Sphk	DELAY(1000);
97952800Sphk	u = sc->m32x->stat;
98052800Sphk	sc->m32x->stat = u;
98152800Sphk
98252800Sphk	/* set all timeslots to known state */
98352800Sphk	for (i = 0; i < 32; i++)
98452800Sphk		sc->m32_mem.ts[i] = 0x20002000;
98552800Sphk
98652800Sphk	if (!(u & 1)) {
98752800Sphk		printf(
98852800Sphk"mn%d: WARNING: Controller failed the PCI bus-master test.\n"
98952800Sphk"mn%d: WARNING: Use a PCI slot which can support bus-master cards.\n",
99052800Sphk		    sc->unit, sc->unit);
99152800Sphk		return  (0);
99252800Sphk	}
99352800Sphk	return (1);
99452800Sphk}
99552800Sphk
99652800Sphk/*
99752800Sphk * FALC54 interrupt handling
99852800Sphk */
99952800Sphkstatic void
1000105213Sphkf54_intr(struct mn_softc *sc)
100152800Sphk{
100252800Sphk	unsigned g, u, s;
100352800Sphk
100452800Sphk	g = sc->f54r->gis;
100552800Sphk	u = sc->f54r->isr0 << 24;
100652800Sphk	u |= sc->f54r->isr1 << 16;
100752800Sphk	u |= sc->f54r->isr2 <<  8;
100852800Sphk	u |= sc->f54r->isr3;
100952800Sphk	sc->falc_irq = u;
101052800Sphk	/* don't chat about the 1 sec heart beat */
101152800Sphk	if (u & ~0x40) {
101252800Sphk#if 0
101352800Sphk		printf("%s*: FALC54 IRQ GIS:%02x %b\n", sc->name, g, u, "\20"
101452800Sphk		    "\40RME\37RFS\36T8MS\35RMB\34CASC\33CRC4\32SA6SC\31RPF"
101552800Sphk		    "\30b27\27RDO\26ALLS\25XDU\24XMB\23b22\22XLSC\21XPR"
101652800Sphk		    "\20FAR\17LFA\16MFAR\15T400MS\14AIS\13LOS\12RAR\11RA"
101752800Sphk		    "\10ES\7SEC\6LMFA16\5AIS16\4RA16\3API\2SLN\1SLP");
101852800Sphk#endif
101952800Sphk		s = sc->f54r->frs0 << 24;
102052800Sphk		s |= sc->f54r->frs1 << 16;
102152800Sphk		s |= sc->f54r->rsw <<  8;
102252800Sphk		s |= sc->f54r->rsp;
102352800Sphk		sc->falc_state = s;
102452800Sphk
102552800Sphk		s &= ~0x01844038;	/* undefined or static bits */
102652800Sphk		s &= ~0x00009fc7;	/* bits we don't care about */
102752800Sphk		s &= ~0x00780000;	/* XXX: TS16 related */
102852800Sphk		s &= ~0x06000000;	/* XXX: Multiframe related */
102952800Sphk#if 0
103052800Sphk		printf("%s*: FALC54 Status %b\n", sc->name, s, "\20"
103152800Sphk		    "\40LOS\37AIS\36LFA\35RRA\34AUXP\33NMF\32LMFA\31frs0.0"
103252800Sphk		    "\30frs1.7\27TS16RA\26TS16LOS\25TS16AIS\24TS16LFA\23frs1.2\22XLS\21XLO"
103352800Sphk		    "\20RS1\17rsw.6\16RRA\15RY0\14RY1\13RY2\12RY3\11RY4"
103452800Sphk		    "\10SI1\7SI2\6rsp.5\5rsp.4\4rsp.3\3RSIF\2RS13\1RS15");
103552800Sphk#endif
103652800Sphk		if (s != sc->framer_state) {
103752800Sphk#if 0
103852800Sphk			for (i = 0; i < M32_CHAN; i++) {
103952800Sphk				if (!sc->ch[i])
104052800Sphk					continue;
104152800Sphk			        sp = &sc->ch[i]->ifsppp;
1042147256Sbrooks				if (!(SP2IFP(sp)->if_flags & IFF_UP))
104352800Sphk					continue;
104452800Sphk				if (s)
104552800Sphk					timeout((timeout_t *)sp->pp_down, sp, 1 * hz);
104652800Sphk				else
104752800Sphk					timeout((timeout_t *)sp->pp_up, sp, 1 * hz);
104852800Sphk			}
104952800Sphk#endif
105052800Sphk			sc->framer_state = s;
105152800Sphk		}
105252800Sphk	}
105352800Sphk	/* Once per second check error counters */
105452800Sphk	/* XXX: not clear if this is actually ok */
105552800Sphk	if (!(u & 0x40))
105652800Sphk		return;
105752800Sphk	sc->cnt_fec  += sc->f54r->fec;
105852800Sphk	sc->cnt_cvc  += sc->f54r->cvc;
105952800Sphk	sc->cnt_cec1 += sc->f54r->cec1;
106052800Sphk	sc->cnt_ebc  += sc->f54r->ebc;
106152800Sphk	sc->cnt_cec2 += sc->f54r->cec2;
106252800Sphk	sc->cnt_cec3 += sc->f54r->cec3;
106352800Sphk	sc->cnt_rbc  += sc->f54r->rbc;
106452800Sphk}
106552800Sphk
106652800Sphk/*
106752800Sphk * Transmit interrupt for one channel
106852800Sphk */
106952800Sphkstatic void
1070105213Sphkmn_tx_intr(struct mn_softc *sc, u_int32_t vector)
107152800Sphk{
107252800Sphk	u_int32_t chan;
107352800Sphk	struct trxd *dp;
107452800Sphk	struct mbuf *m;
107552800Sphk
107652800Sphk	chan = vector & 0x1f;
107752800Sphk	if (!sc->ch[chan])
107852800Sphk		return;
107952800Sphk	if (sc->ch[chan]->state != UP) {
108052800Sphk		printf("%s: tx_intr when not UP\n", sc->name);
108152800Sphk		return;
108252800Sphk	}
108352800Sphk	for (;;) {
108452800Sphk		dp = sc->ch[chan]->x1;
108552800Sphk		if (vtophys(dp) == sc->m32_mem.ctxd[chan])
108652800Sphk			return;
108752800Sphk		m = dp->m;
108857519Sphk		if (m) {
108957678Sphk#if 0
109057678Sphk			printf("%d = %d - %d (%p)\n",
109157678Sphk			    sc->ch[chan]->tx_pending - m->m_pkthdr.len,
109257678Sphk			    sc->ch[chan]->tx_pending , m->m_pkthdr.len, m);
109357678Sphk#endif
109457519Sphk			sc->ch[chan]->tx_pending -= m->m_pkthdr.len;
109552800Sphk			m_freem(m);
109657519Sphk		}
109752800Sphk		sc->ch[chan]->last_xmit = time_second;
109852800Sphk		sc->ch[chan]->x1 = dp->vnext;
109952800Sphk		mn_free_desc(dp);
110052800Sphk	}
110152800Sphk}
110252800Sphk
110352800Sphk/*
110452800Sphk * Receive interrupt for one channel
110552800Sphk */
110652800Sphkstatic void
1107105213Sphkmn_rx_intr(struct mn_softc *sc, u_int32_t vector)
110852800Sphk{
110952800Sphk	u_int32_t chan, err;
111052800Sphk	struct trxd *dp;
111152800Sphk	struct mbuf *m;
111252800Sphk	struct schan *sch;
111352800Sphk
111452800Sphk	chan = vector & 0x1f;
111552800Sphk	if (!sc->ch[chan])
111652800Sphk		return;
111752800Sphk	sch = sc->ch[chan];
111852800Sphk	if (sch->state != UP) {
111952800Sphk		printf("%s: rx_intr when not UP\n", sc->name);
112052800Sphk		return;
112152800Sphk	}
112252800Sphk	vector &= ~0x1f;
112352800Sphk	if (vector == 0x30000b00)
112452800Sphk		sch->rx_error++;
112552800Sphk	for (;;) {
112652800Sphk		dp = sch->r1;
112752800Sphk		if (vtophys(dp) == sc->m32_mem.crxd[chan])
112852800Sphk			return;
112952800Sphk		m = dp->m;
113052800Sphk		dp->m = 0;
113152800Sphk		m->m_pkthdr.len = m->m_len = (dp->status >> 16) & 0x1fff;
113252800Sphk		err = (dp->status >> 8) & 0xff;
113352800Sphk		if (!err) {
113469922Sjulian			int error;
113569922Sjulian			NG_SEND_DATA_ONLY(error, sch->hook, m);
113652800Sphk			sch->last_recv = time_second;
113752800Sphk			/* we could be down by now... */
113852800Sphk			if (sch->state != UP)
113952800Sphk				return;
114052800Sphk		} else if (err & 0x40) {
114152800Sphk			sch->short_error++;
114252800Sphk		} else if (err & 0x10) {
114352800Sphk			sch->crc_error++;
114452800Sphk		} else if (err & 0x08) {
114552800Sphk			sch->dribble_error++;
114652800Sphk		} else if (err & 0x04) {
114752800Sphk			sch->long_error++;
114852800Sphk		} else if (err & 0x02) {
114952800Sphk			sch->abort_error++;
115052800Sphk		} else if (err & 0x01) {
115152800Sphk			sch->overflow_error++;
115252800Sphk		}
115352800Sphk		if (err) {
115452800Sphk			sch->last_rxerr = time_second;
115552800Sphk			sch->prev_error = sch->last_error;
115652800Sphk			sch->last_error = err;
115752800Sphk		}
115852800Sphk
115952800Sphk		sc->ch[chan]->r1 = dp->vnext;
116052800Sphk
116152800Sphk		/* Replenish desc + mbuf supplies */
116252800Sphk		if (!m) {
1163243857Sglebius			MGETHDR(m, M_NOWAIT, MT_DATA);
116452800Sphk			if (m == NULL) {
116552800Sphk				mn_free_desc(dp);
116670068Sbmilekic				return; /* ENOBUFS */
116752800Sphk			}
1168243857Sglebius			MCLGET(m, M_NOWAIT);
116952800Sphk			if((m->m_flags & M_EXT) == 0) {
117052800Sphk				mn_free_desc(dp);
117170068Sbmilekic				m_freem(m);
117270068Sbmilekic				return; /* ENOBUFS */
117352800Sphk			}
117452800Sphk		}
117552800Sphk		dp->m = m;
117652800Sphk		dp->data = vtophys(m->m_data);
117752800Sphk		dp->flags = 0x40000000;
117852800Sphk		dp->flags += 1600 << 16;
117952800Sphk		dp->next = vtophys(dp);
118052800Sphk		dp->vnext = 0;
118152800Sphk		sc->ch[chan]->rl->next = vtophys(dp);
118252800Sphk		sc->ch[chan]->rl->vnext = dp;
118352800Sphk		sc->ch[chan]->rl->flags &= ~0x40000000;
118452800Sphk		sc->ch[chan]->rl = dp;
118552800Sphk	}
118652800Sphk}
118752800Sphk
118852800Sphk
118952800Sphk/*
119052800Sphk * Interupt handler
119152800Sphk */
119252800Sphk
119352800Sphkstatic void
119452800Sphkmn_intr(void *xsc)
119552800Sphk{
1196105213Sphk	struct mn_softc *sc;
119752800Sphk	u_int32_t stat, lstat, u;
119852800Sphk	int i, j;
119952800Sphk
120052800Sphk	sc = xsc;
120152800Sphk	stat =  sc->m32x->stat;
120252800Sphk	lstat =  sc->m32x->lstat;
120352800Sphk#if 0
120452800Sphk	if (!stat && !(lstat & 2))
120552800Sphk		return;
120652800Sphk#endif
120752800Sphk
120852800Sphk	if (stat & ~0xc200) {
120957678Sphk		printf("%s: I stat=%08x lstat=%08x\n", sc->name, stat, lstat);
121052800Sphk	}
121152800Sphk
121252800Sphk	if ((stat & 0x200) || (lstat & 2))
121352800Sphk		f54_intr(sc);
121452800Sphk
121552800Sphk	for (j = i = 0; i < 64; i ++) {
121652800Sphk		u = sc->riqb[i];
121752800Sphk		if (u) {
121852800Sphk			sc->riqb[i] = 0;
121952800Sphk			mn_rx_intr(sc, u);
122052800Sphk			if ((u & ~0x1f) == 0x30000800 || (u & ~0x1f) == 0x30000b00)
122152800Sphk				continue;
122252800Sphk			u &= ~0x30000400;	/* bits we don't care about */
122352800Sphk			if ((u & ~0x1f) == 0x00000900)
122452800Sphk				continue;
122552800Sphk			if (!(u & ~0x1f))
122652800Sphk				continue;
122752800Sphk			if (!j)
122852800Sphk				printf("%s*: RIQB:", sc->name);
122952800Sphk			printf(" [%d]=%08x", i, u);
123052800Sphk			j++;
123152800Sphk		}
123252800Sphk	}
123352800Sphk	if (j)
123452800Sphk	    printf("\n");
123552800Sphk
123652800Sphk	for (j = i = 0; i < 64; i ++) {
123752800Sphk		u = sc->tiqb[i];
123852800Sphk		if (u) {
123952800Sphk			sc->tiqb[i] = 0;
124052800Sphk			mn_tx_intr(sc, u);
124152800Sphk			if ((u & ~0x1f) == 0x20000800)
124252800Sphk				continue;
124352800Sphk			u &= ~0x20000000;	/* bits we don't care about */
124452800Sphk			if (!u)
124552800Sphk				continue;
124652800Sphk			if (!j)
124752800Sphk				printf("%s*: TIQB:", sc->name);
124852800Sphk			printf(" [%d]=%08x", i, u);
124952800Sphk			j++;
125052800Sphk		}
125152800Sphk	}
125252800Sphk	if (j)
125352800Sphk		printf("\n");
125452800Sphk	sc->m32x->stat = stat;
125552800Sphk}
125652800Sphk
125752800Sphk/*
125852800Sphk * PCI initialization stuff
125952800Sphk */
126052800Sphk
126162924Sphkstatic int
126262924Sphkmn_probe (device_t self)
126352800Sphk{
126462924Sphk	u_int id = pci_get_devid(self);
126552800Sphk
126652800Sphk	if (sizeof (struct m32xreg) != 256) {
1267106626Sjhb		printf("MN: sizeof(struct m32xreg) = %zd, should have been 256\n", sizeof (struct m32xreg));
126862924Sphk		return (ENXIO);
126952800Sphk	}
127052800Sphk	if (sizeof (struct f54rreg) != 128) {
1271106626Sjhb		printf("MN: sizeof(struct f54rreg) = %zd, should have been 128\n", sizeof (struct f54rreg));
127262924Sphk		return (ENXIO);
127352800Sphk	}
127452800Sphk	if (sizeof (struct f54wreg) != 128) {
1275106626Sjhb		printf("MN: sizeof(struct f54wreg) = %zd, should have been 128\n", sizeof (struct f54wreg));
127662924Sphk		return (ENXIO);
127752800Sphk	}
127852800Sphk
127962924Sphk	if (id != 0x2101110a)
128062924Sphk		return (ENXIO);
128152800Sphk
128262924Sphk	device_set_desc_copy(self, "Munich32X E1/T1 HDLC Controller");
1283142398Simp	return (BUS_PROBE_DEFAULT);
128452800Sphk}
128552800Sphk
128662924Sphkstatic int
128762924Sphkmn_attach (device_t self)
128852800Sphk{
1289105213Sphk	struct mn_softc *sc;
129052800Sphk	u_int32_t u;
129162924Sphk	u_int32_t ver;
129252800Sphk	static int once;
129362924Sphk	int rid, error;
129462924Sphk	struct resource *res;
129552800Sphk
129652800Sphk	if (!once) {
129752800Sphk		if (ng_newtype(&mntypestruct))
129852800Sphk			printf("ng_newtype failed\n");
129952800Sphk		once++;
130052800Sphk	}
130152800Sphk
1302111119Simp	sc = (struct mn_softc *)malloc(sizeof *sc, M_MN, M_WAITOK | M_ZERO);
130362924Sphk	device_set_softc(self, sc);
130452800Sphk
130562924Sphk	sc->dev = self;
130662924Sphk	sc->unit = device_get_unit(self);
130771344Sphk	sc->framing = E1;
130862924Sphk	sprintf(sc->name, "mn%d", sc->unit);
130952800Sphk
1310119690Sjhb        rid = PCIR_BAR(0);
1311127135Snjl        res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
131262924Sphk        if (res == NULL) {
131362924Sphk                device_printf(self, "Could not map memory\n");
1314105213Sphk		free(sc, M_MN);
131562924Sphk                return ENXIO;
131662924Sphk        }
131762924Sphk        sc->m0v = rman_get_virtual(res);
131862924Sphk        sc->m0p = rman_get_start(res);
131962924Sphk
1320119690Sjhb        rid = PCIR_BAR(1);
1321127135Snjl        res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
132262924Sphk        if (res == NULL) {
132362924Sphk                device_printf(self, "Could not map memory\n");
1324105213Sphk		free(sc, M_MN);
132562924Sphk                return ENXIO;
132662924Sphk        }
132762924Sphk        sc->m1v = rman_get_virtual(res);
132862924Sphk        sc->m1p = rman_get_start(res);
132962924Sphk
133065491Sphk	/* Allocate interrupt */
133165491Sphk	rid = 0;
1332127135Snjl	sc->irq = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
1333127135Snjl	    RF_SHAREABLE | RF_ACTIVE);
133465491Sphk
133565491Sphk	if (sc->irq == NULL) {
133665491Sphk		printf("couldn't map interrupt\n");
1337105213Sphk		free(sc, M_MN);
133865491Sphk		return(ENXIO);
133965491Sphk	}
134065491Sphk
1341166920Simp	error = bus_setup_intr(self, sc->irq, INTR_TYPE_NET, NULL, mn_intr, sc, &sc->intrhand);
134265491Sphk
134365491Sphk	if (error) {
134465491Sphk		printf("couldn't set up irq\n");
1345105213Sphk		free(sc, M_MN);
134665491Sphk		return(ENXIO);
134765491Sphk	}
134865491Sphk
1349254263Sscottl	u = pci_read_config(self, PCIR_COMMAND, 2);
135062924Sphk	printf("%x\n", u);
1351254263Sscottl	pci_write_config(self, PCIR_COMMAND, u | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN, 2);
135262924Sphk#if 0
135362924Sphk	pci_write_config(self, PCIR_COMMAND, 0x02800046, 4);
135462924Sphk#endif
135562924Sphk	u = pci_read_config(self, PCIR_COMMAND, 1);
135662924Sphk	printf("%x\n", u);
135762924Sphk
135871139Speter	ver = pci_get_revid(self);
135962924Sphk
136052800Sphk	sc->m32x = (struct m32xreg *) sc->m0v;
136152800Sphk	sc->f54w = (struct f54wreg *) sc->m1v;
136252800Sphk	sc->f54r = (struct f54rreg *) sc->m1v;
136352800Sphk
136452800Sphk	/* We must reset before poking at FALC54 registers */
136552800Sphk	u = mn_reset(sc);
136652800Sphk	if (!u)
136762924Sphk		return (0);
136852800Sphk
136952800Sphk	printf("mn%d: Munich32X", sc->unit);
137071139Speter	switch (ver) {
137152800Sphk	case 0x13:
137257967Sphk		printf(" Rev 2.2");
137352800Sphk		break;
137452800Sphk	default:
137571139Speter		printf(" Rev 0x%x\n", ver);
137652800Sphk	}
137752800Sphk	printf(", Falc54");
137852800Sphk	switch (sc->f54r->vstr) {
137952800Sphk	case 0:
138052800Sphk		printf(" Rev < 1.3\n");
138152800Sphk		break;
138252800Sphk	case 1:
138352800Sphk		printf(" Rev 1.3\n");
138452800Sphk		break;
138552800Sphk	case 2:
138652800Sphk		printf(" Rev 1.4\n");
138752800Sphk		break;
138852800Sphk	case 0x10:
138952800Sphk		printf("-LH Rev 1.1\n");
139052800Sphk		break;
139157967Sphk	case 0x13:
139257967Sphk		printf("-LH Rev 1.3\n");
139357967Sphk		break;
139452800Sphk	default:
139552800Sphk		printf(" Rev 0x%x\n", sc->f54r->vstr);
139652800Sphk	}
139752800Sphk
139852800Sphk	if (ng_make_node_common(&mntypestruct, &sc->node) != 0) {
139952800Sphk		printf("ng_make_node_common failed\n");
140062924Sphk		return (0);
140152800Sphk	}
140270784Sjulian	NG_NODE_SET_PRIVATE(sc->node, sc);
140352800Sphk	sprintf(sc->nodename, "%s%d", NG_MN_NODE_TYPE, sc->unit);
140452800Sphk	if (ng_name_node(sc->node, sc->nodename)) {
140570784Sjulian		NG_NODE_UNREF(sc->node);
140662924Sphk		return (0);
140752800Sphk	}
140852800Sphk
140962924Sphk	return (0);
141052800Sphk}
141162924Sphk
141262924Sphk
141362924Sphkstatic device_method_t mn_methods[] = {
141462924Sphk        /* Device interface */
141562924Sphk        DEVMETHOD(device_probe,         mn_probe),
141662924Sphk        DEVMETHOD(device_attach,        mn_attach),
141762924Sphk        DEVMETHOD(device_suspend,       bus_generic_suspend),
141862924Sphk        DEVMETHOD(device_resume,        bus_generic_resume),
141962924Sphk        DEVMETHOD(device_shutdown,      bus_generic_shutdown),
142062924Sphk
1421246128Ssbz	DEVMETHOD_END
142262924Sphk};
142362924Sphk
142462924Sphkstatic driver_t mn_driver = {
142562924Sphk        "mn",
142662924Sphk        mn_methods,
142762924Sphk        0
142862924Sphk};
142962924Sphk
143062924Sphkstatic devclass_t mn_devclass;
143162924Sphk
143262924SphkDRIVER_MODULE(mn, pci, mn_driver, mn_devclass, 0, 0);
1433