if_mn.c revision 130415
140843Smsmith/* 240843Smsmith * ---------------------------------------------------------------------------- 340843Smsmith * "THE BEER-WARE LICENSE" (Revision 42): 440843Smsmith * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 540843Smsmith * can do whatever you want with this stuff. If we meet some day, and you think 676116Sdcs * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 740843Smsmith * ---------------------------------------------------------------------------- 840843Smsmith * 976116Sdcs * $Id: if_mn.c,v 1.38 2003/06/11 06:24:36 obrien Exp $ 1076116Sdcs * 1176116Sdcs * Driver for Siemens reference design card "Easy321-R1". 1276116Sdcs * 1376116Sdcs * This card contains a FALC54 E1/T1 framer and a MUNICH32X 32-channel HDLC 1476116Sdcs * controller. 1540843Smsmith * 1676116Sdcs * The driver supports E1 mode with up to 31 channels. We send CRC4 but don't 1776116Sdcs * check it coming in. 1876116Sdcs * 1976116Sdcs * The FALC54 and MUNICH32X have far too many registers and weird modes for 2076116Sdcs * comfort, so I have not bothered typing it all into a "fooreg.h" file, 2176116Sdcs * you will (badly!) need the documentation anyway if you want to mess with 2276116Sdcs * this gadget. 2376116Sdcs */ 2476116Sdcs 2576116Sdcs#include <sys/cdefs.h> 2676116Sdcs__FBSDID("$FreeBSD: head/sys/pci/if_mn.c 130415 2004-06-13 17:15:05Z phk $"); 2776116Sdcs 2876116Sdcs/* 2976116Sdcs * Stuff to describe the MUNIC32X and FALC54 chips. 3076116Sdcs */ 3176116Sdcs 3276116Sdcs#define M32_CHAN 32 /* We have 32 channels */ 3376116Sdcs#define M32_TS 32 /* We have 32 timeslots */ 3476116Sdcs 3576116Sdcs#define NG_MN_NODE_TYPE "mn" 3676116Sdcs 3740843Smsmith#include <sys/param.h> 3840843Smsmith#include <sys/kernel.h> 3976116Sdcs#include <sys/sysctl.h> 4076116Sdcs#include <sys/bus.h> 4176116Sdcs#include <sys/mbuf.h> 4276116Sdcs#include <sys/systm.h> 4340843Smsmith#include <sys/malloc.h> 4440843Smsmith 4551786Sdcs#include <dev/pci/pcireg.h> 4651786Sdcs#include <dev/pci/pcivar.h> 4740843Smsmith#include "pci_if.h" 4840843Smsmith 4940843Smsmith#include <machine/bus.h> 5040843Smsmith#include <machine/resource.h> 5140843Smsmith 5240843Smsmith#include <sys/rman.h> 5340843Smsmith 5440843Smsmith#include <vm/vm.h> 5540843Smsmith#include <vm/pmap.h> 5640843Smsmith 5740843Smsmith#include <netgraph/ng_message.h> 5840843Smsmith#include <netgraph/netgraph.h> 5940843Smsmith 6040843Smsmith 6140843Smsmithstatic int mn_maxlatency = 1000; 6240843SmsmithSYSCTL_INT(_debug, OID_AUTO, mn_maxlatency, CTLFLAG_RW, 6340843Smsmith &mn_maxlatency, 0, 6440843Smsmith "The number of milliseconds a packet is allowed to spend in the output queue. " 6540843Smsmith "If the output queue is longer than this number of milliseconds when the packet " 6640843Smsmith "arrives for output, the packet will be dropped." 6740843Smsmith); 6840843Smsmith 6940843Smsmith#ifndef NMN 7040843Smsmith/* Most machines don't support more than 4 busmaster PCI slots, if even that many */ 7140843Smsmith#define NMN 4 7240843Smsmith#endif 7340843Smsmith 7440843Smsmith/* From: PEB 20321 data sheet, p187, table 22 */ 7540843Smsmithstruct m32xreg { 7640843Smsmith u_int32_t conf, cmd, stat, imask; 7740843Smsmith u_int32_t fill10, piqba, piql, fill1c; 7840843Smsmith u_int32_t mode1, mode2, ccba, txpoll; 7940843Smsmith u_int32_t tiqba, tiql, riqba, riql; 8040843Smsmith u_int32_t lconf, lccba, fill48, ltran; 8140843Smsmith u_int32_t ltiqba, ltiql, lriqba, lriql; 8240843Smsmith u_int32_t lreg0, lreg1, lreg2, lreg3; 8340843Smsmith u_int32_t lreg4, lreg5, lre6, lstat; 8440843Smsmith u_int32_t gpdir, gpdata, gpod, fill8c; 8540843Smsmith u_int32_t ssccon, sscbr, ssctb, sscrb; 8640843Smsmith u_int32_t ssccse, sscim, fillab, fillac; 8740843Smsmith u_int32_t iomcon1, iomcon2, iomstat, fillbc; 8840843Smsmith u_int32_t iomcit0, iomcit1, iomcir0, iomcir1; 8940843Smsmith u_int32_t iomtmo, iomrmo, filld8, filldc; 9040843Smsmith u_int32_t mbcmd, mbdata1, mbdata2, mbdata3; 9140843Smsmith u_int32_t mbdata4, mbdata5, mbdata6, mbdata7; 9240843Smsmith}; 9340843Smsmith 9440843Smsmith/* From: PEB 2254 data sheet, p80, table 10 */ 9540843Smsmithstruct f54wreg { 9640843Smsmith u_int16_t xfifo; 9740843Smsmith u_int8_t cmdr, mode, rah1, rah2, ral1, ral2; 9840843Smsmith u_int8_t ipc, ccr1, ccr3, pre, rtr1, rtr2, rtr3, rtr4; 9940843Smsmith u_int8_t ttr1, ttr2, ttr3, ttr4, imr0, imr1, imr2, imr3; 10040843Smsmith u_int8_t imr4, fill19, fmr0, fmr1, fmr2, loop, xsw, xsp; 10140843Smsmith u_int8_t xc0, xc1, rc0, rc1, xpm0, xpm1, xpm2, tswm; 10240843Smsmith u_int8_t test1, idle, xsa4, xsa5, xsa6, xsa7, xsa8, fmr3; 10340843Smsmith u_int8_t icb1, icb2, icb3, icb4, lim0, lim1, pcd, pcr; 10440843Smsmith u_int8_t lim2, fill39[7]; 10540843Smsmith u_int8_t fill40[8]; 10640843Smsmith u_int8_t fill48[8]; 10740843Smsmith u_int8_t fill50[8]; 10840843Smsmith u_int8_t fill58[8]; 10940843Smsmith u_int8_t dec, fill61, test2, fill63[5]; 11040843Smsmith u_int8_t fill68[8]; 11140843Smsmith u_int8_t xs[16]; 11240843Smsmith}; 11340843Smsmith 11440843Smsmith/* From: PEB 2254 data sheet, p117, table 10 */ 11540843Smsmithstruct f54rreg { 11640843Smsmith u_int16_t rfifo; 11740843Smsmith u_int8_t fill2, mode, rah1, rah2, ral1, ral2; 11840843Smsmith u_int8_t ipc, ccr1, ccr3, pre, rtr1, rtr2, rtr3, rtr4; 11940843Smsmith u_int8_t ttr1, ttr2, ttr3, ttr4, imr0, imr1, imr2, imr3; 12040843Smsmith u_int8_t imr4, fill19, fmr0, fmr1, fmr2, loop, xsw, xsp; 12140843Smsmith u_int8_t xc0, xc1, rc0, rc1, xpm0, xpm1, xpm2, tswm; 12240843Smsmith u_int8_t test, idle, xsa4, xsa5, xsa6, xsa7, xsa8, fmr13; 12340843Smsmith u_int8_t icb1, icb2, icb3, icb4, lim0, lim1, pcd, pcr; 12440843Smsmith u_int8_t lim2, fill39[7]; 12540843Smsmith u_int8_t fill40[8]; 12640843Smsmith u_int8_t fill48[4], frs0, frs1, rsw, rsp; 12740843Smsmith u_int16_t fec, cvc, cec1, ebc; 12840843Smsmith u_int16_t cec2, cec3; 12940843Smsmith u_int8_t rsa4, rsa5, rsa6, rsa7; 13040843Smsmith u_int8_t rsa8, rsa6s, tsr0, tsr1, sis, rsis; 13140843Smsmith u_int16_t rbc; 13240843Smsmith u_int8_t isr0, isr1, isr2, isr3, fill6c, fill6d, gis, vstr; 13340843Smsmith u_int8_t rs[16]; 13440843Smsmith}; 13540843Smsmith 13640843Smsmith/* Transmit & receive descriptors */ 13740843Smsmithstruct trxd { 13840843Smsmith u_int32_t flags; 13940843Smsmith vm_offset_t next; 14040843Smsmith vm_offset_t data; 14140843Smsmith u_int32_t status; /* only used for receive */ 14240843Smsmith struct mbuf *m; /* software use only */ 14340843Smsmith struct trxd *vnext; /* software use only */ 14440843Smsmith}; 14540843Smsmith 14640843Smsmith/* Channel specification */ 14740843Smsmithstruct cspec { 14840843Smsmith u_int32_t flags; 14940843Smsmith vm_offset_t rdesc; 15040843Smsmith vm_offset_t tdesc; 15140843Smsmith u_int32_t itbs; 15240843Smsmith}; 15340843Smsmith 15440843Smsmithstruct m32_mem { 15540843Smsmith vm_offset_t csa; 15640843Smsmith u_int32_t ccb; 15740843Smsmith u_int32_t reserve1[2]; 15840843Smsmith u_int32_t ts[M32_TS]; 15940843Smsmith struct cspec cs[M32_CHAN]; 16040843Smsmith vm_offset_t crxd[M32_CHAN]; 16140843Smsmith vm_offset_t ctxd[M32_CHAN]; 16240843Smsmith}; 16340843Smsmith 16440843Smsmithstruct mn_softc; 16540843Smsmithstruct sockaddr; 16640843Smsmithstruct rtentry; 16740843Smsmith 16840843Smsmithstatic int mn_probe (device_t self); 16940843Smsmithstatic int mn_attach (device_t self); 17040843Smsmithstatic void mn_create_channel(struct mn_softc *sc, int chan); 17140843Smsmithstatic int mn_reset(struct mn_softc *sc); 17240843Smsmithstatic struct trxd * mn_alloc_desc(void); 17351786Sdcsstatic void mn_free_desc(struct trxd *dp); 17451786Sdcsstatic void mn_intr(void *xsc); 17551786Sdcsstatic u_int32_t mn_parse_ts(const char *s, int *nbit); 17643078Smsmith#ifdef notyet 17743078Smsmithstatic void m32_dump(struct mn_softc *sc); 17843078Smsmithstatic void f54_dump(struct mn_softc *sc); 17943078Smsmithstatic void mn_fmt_ts(char *p, u_int32_t ts); 18043078Smsmith#endif /* notyet */ 18143078Smsmithstatic void f54_init(struct mn_softc *sc); 18243078Smsmith 18343078Smsmithstatic ng_constructor_t ngmn_constructor; 18440843Smsmithstatic ng_rcvmsg_t ngmn_rcvmsg; 18540843Smsmithstatic ng_shutdown_t ngmn_shutdown; 18640843Smsmithstatic ng_newhook_t ngmn_newhook; 18740843Smsmithstatic ng_connect_t ngmn_connect; 18840843Smsmithstatic ng_rcvdata_t ngmn_rcvdata; 18940843Smsmithstatic ng_disconnect_t ngmn_disconnect; 19040843Smsmith 19140843Smsmithstatic struct ng_type mntypestruct = { 19240843Smsmith .version = NG_ABI_VERSION, 19340843Smsmith .name = NG_MN_NODE_TYPE, 19440843Smsmith .constructor = ngmn_constructor, 19540843Smsmith .rcvmsg = ngmn_rcvmsg, 19640843Smsmith .shutdown = ngmn_shutdown, 19740843Smsmith .newhook = ngmn_newhook, 19840843Smsmith .connect = ngmn_connect, 19940843Smsmith .rcvdata = ngmn_rcvdata, 20040843Smsmith .disconnect = ngmn_disconnect, 20140843Smsmith}; 20240843Smsmith 20340843Smsmithstatic MALLOC_DEFINE(M_MN, "mn", "Mx driver related"); 20440843Smsmith 20540843Smsmith#define NIQB 64 20640843Smsmith 20740843Smsmithstruct schan { 20840843Smsmith enum {DOWN, UP} state; 20940843Smsmith struct mn_softc *sc; 21040843Smsmith int chan; 21140843Smsmith u_int32_t ts; 21240843Smsmith char name[8]; 21340843Smsmith struct trxd *r1, *rl; 21440843Smsmith struct trxd *x1, *xl; 21540843Smsmith hook_p hook; 21640843Smsmith 21740843Smsmith time_t last_recv; 21840843Smsmith time_t last_rxerr; 21940843Smsmith time_t last_xmit; 22040843Smsmith 22140843Smsmith u_long rx_error; 22240843Smsmith 22340843Smsmith u_long short_error; 22440843Smsmith u_long crc_error; 22540843Smsmith u_long dribble_error; 22640843Smsmith u_long long_error; 22740843Smsmith u_long abort_error; 22840843Smsmith u_long overflow_error; 22940843Smsmith 23040843Smsmith int last_error; 23140843Smsmith int prev_error; 23240843Smsmith 23376116Sdcs u_long tx_pending; 23476116Sdcs u_long tx_limit; 23540843Smsmith}; 23640843Smsmith 23740843Smsmithenum framing {WHOKNOWS, E1, E1U, T1, T1U}; 23840843Smsmith 23976116Sdcsstruct mn_softc { 24051786Sdcs int unit; 24151786Sdcs device_t dev; 24240949Smsmith struct resource *irq; 24340843Smsmith void *intrhand; 24440843Smsmith enum framing framing; 24540843Smsmith int nhooks; 24640843Smsmith void *m0v, *m1v; 24740843Smsmith vm_offset_t m0p, m1p; 24840843Smsmith struct m32xreg *m32x; 24976116Sdcs struct f54wreg *f54w; 25040843Smsmith struct f54rreg *f54r; 25140843Smsmith struct m32_mem m32_mem; 25240843Smsmith u_int32_t tiqb[NIQB]; 25340843Smsmith u_int32_t riqb[NIQB]; 25440843Smsmith u_int32_t piqb[NIQB]; 25540843Smsmith u_int32_t ltiqb[NIQB]; 25651786Sdcs u_int32_t lriqb[NIQB]; 25751786Sdcs char name[8]; 25840843Smsmith u_int32_t falc_irq, falc_state, framer_state; 25940843Smsmith struct schan *ch[M32_CHAN]; 26040843Smsmith char nodename[NG_NODELEN + 1]; 26176116Sdcs node_p node; 26251786Sdcs 26376116Sdcs u_long cnt_fec; 26476116Sdcs u_long cnt_cvc; 26576116Sdcs u_long cnt_cec1; 26676116Sdcs u_long cnt_ebc; 26776116Sdcs u_long cnt_cec2; 26840843Smsmith u_long cnt_cec3; 26940843Smsmith u_long cnt_rbc; 27040843Smsmith}; 27140843Smsmith 27240843Smsmithstatic int 27340843Smsmithngmn_constructor(node_p node) 27440843Smsmith{ 27540843Smsmith 27640843Smsmith return (EINVAL); 27740843Smsmith} 27840843Smsmith 27940843Smsmithstatic int 28040843Smsmithngmn_shutdown(node_p nodep) 28140843Smsmith{ 28240843Smsmith 28340843Smsmith return (EINVAL); 28440843Smsmith} 28540843Smsmith 28640843Smsmithstatic void 28740843Smsmithngmn_config(node_p node, char *set, char *ret) 28840843Smsmith{ 28940843Smsmith struct mn_softc *sc; 29040843Smsmith enum framing wframing; 29140843Smsmith 29240843Smsmith sc = NG_NODE_PRIVATE(node); 29340843Smsmith 29440843Smsmith if (set != NULL) { 29540843Smsmith if (!strncmp(set, "line ", 5)) { 29640843Smsmith wframing = sc->framing; 29740843Smsmith if (!strcmp(set, "line e1")) { 29840843Smsmith wframing = E1; 29940843Smsmith } else if (!strcmp(set, "line e1u")) { 30040843Smsmith wframing = E1U; 30140843Smsmith } else { 30240843Smsmith strcat(ret, "ENOGROK\n"); 30340843Smsmith return; 30440843Smsmith } 30561182Sdcs if (wframing == sc->framing) 30640843Smsmith return; 30740843Smsmith if (sc->nhooks > 0) { 30840843Smsmith sprintf(ret, "Cannot change line when %d hooks open\n", sc->nhooks); 30940843Smsmith return; 31040843Smsmith } 31161182Sdcs sc->framing = wframing; 31240843Smsmith#if 1 31340843Smsmith f54_init(sc); 31440843Smsmith#else 31540843Smsmith mn_reset(sc); 31640843Smsmith#endif 31740843Smsmith } else { 31840843Smsmith printf("%s CONFIG SET [%s]\n", sc->nodename, set); 31940843Smsmith strcat(ret, "ENOGROK\n"); 32040843Smsmith return; 32140843Smsmith } 32240843Smsmith } 32340843Smsmith 32440843Smsmith} 32576116Sdcs 32640843Smsmithstatic int 32740843Smsmithngmn_rcvmsg(node_p node, item_p item, hook_p lasthook) 32840843Smsmith{ 32943078Smsmith struct mn_softc *sc; 33043078Smsmith struct ng_mesg *resp = NULL; 33143078Smsmith struct schan *sch; 33243078Smsmith char *s, *r; 33343078Smsmith int pos, i; 33443078Smsmith struct ng_mesg *msg; 33543078Smsmith 33643078Smsmith NGI_GET_MSG(item, msg); 33740843Smsmith sc = NG_NODE_PRIVATE(node); 33840843Smsmith 33940843Smsmith if (msg->header.typecookie != NGM_GENERIC_COOKIE) { 34061149Sdcs NG_FREE_ITEM(item); 34143078Smsmith NG_FREE_MSG(msg); 34240843Smsmith return (EINVAL); 34340843Smsmith } 34440843Smsmith 34540843Smsmith if (msg->header.cmd != NGM_TEXT_CONFIG && 34640843Smsmith msg->header.cmd != NGM_TEXT_STATUS) { 34740843Smsmith NG_FREE_ITEM(item); 34840843Smsmith NG_FREE_MSG(msg); 34940843Smsmith return (EINVAL); 35040843Smsmith } 35140843Smsmith 35240843Smsmith NG_MKRESPONSE(resp, msg, sizeof(struct ng_mesg) + NG_TEXTRESPONSE, 35340843Smsmith M_NOWAIT); 35440843Smsmith if (resp == NULL) { 35540843Smsmith NG_FREE_ITEM(item); 35640843Smsmith NG_FREE_MSG(msg); 35751786Sdcs return (ENOMEM); 35840843Smsmith } 35940843Smsmith 36076116Sdcs if (msg->header.arglen) 36140843Smsmith s = (char *)msg->data; 36240843Smsmith else 36340843Smsmith s = NULL; 36440843Smsmith r = (char *)resp->data; 36540843Smsmith *r = '\0'; 36640843Smsmith 36740843Smsmith if (msg->header.cmd == NGM_TEXT_CONFIG) { 36840843Smsmith ngmn_config(node, s, r); 36940843Smsmith resp->header.arglen = strlen(r) + 1; 37040843Smsmith NG_RESPOND_MSG(i, node, item, resp); 37140843Smsmith NG_FREE_MSG(msg); 37240843Smsmith return (0); 37340843Smsmith } 37440843Smsmith pos = 0; 37576116Sdcs pos += sprintf(pos + r,"Framer status %b;\n", sc->framer_state, "\20" 37651786Sdcs "\40LOS\37AIS\36LFA\35RRA" 37751786Sdcs "\34AUXP\33NMF\32LMFA\31frs0.0" 37840843Smsmith "\30frs1.7\27TS16RA\26TS16LOS\25TS16AIS" 37940843Smsmith "\24TS16LFA\23frs1.2\22XLS\21XLO" 38051786Sdcs "\20RS1\17rsw.6\16RRA\15RY0" 38151786Sdcs "\14RY1\13RY2\12RY3\11RY4" 38240843Smsmith "\10SI1\7SI2\6rsp.5\5rsp.4" 38340843Smsmith "\4rsp.3\3RSIF\2RS13\1RS15"); 38440843Smsmith pos += sprintf(pos + r," Framing errors: %lu", sc->cnt_fec); 38540843Smsmith pos += sprintf(pos + r," Code Violations: %lu\n", sc->cnt_cvc); 38640843Smsmith 38740843Smsmith pos += sprintf(pos + r," Falc State %b;\n", sc->falc_state, "\20" 38876116Sdcs "\40LOS\37AIS\36LFA\35RRA" 38976116Sdcs "\34AUXP\33NMF\32LMFA\31frs0.0" 39076116Sdcs "\30frs1.7\27TS16RA\26TS16LOS\25TS16AIS" 39176116Sdcs "\24TS16LFA\23frs1.2\22XLS\21XLO" 39276116Sdcs "\20RS1\17rsw.6\16RRA\15RY0" 39376116Sdcs "\14RY1\13RY2\12RY3\11RY4" 39476116Sdcs "\10SI1\7SI2\6rsp.5\5rsp.4" 39576116Sdcs "\4rsp.3\3RSIF\2RS13\1RS15"); 39676116Sdcs pos += sprintf(pos + r, " Falc IRQ %b\n", sc->falc_irq, "\20" 39776116Sdcs "\40RME\37RFS\36T8MS\35RMB\34CASC\33CRC4\32SA6SC\31RPF" 39876116Sdcs "\30b27\27RDO\26ALLS\25XDU\24XMB\23b22\22XLSC\21XPR" 39976116Sdcs "\20FAR\17LFA\16MFAR\15T400MS\14AIS\13LOS\12RAR\11RA" 40076116Sdcs "\10ES\7SEC\6LMFA16\5AIS16\4RA16\3API\2SLN\1SLP"); 40176116Sdcs for (i = 0; i < M32_CHAN; i++) { 40276116Sdcs if (!sc->ch[i]) 40376116Sdcs continue; 40476116Sdcs sch = sc->ch[i]; 40576116Sdcs 40676116Sdcs pos += sprintf(r + pos, " Chan %d <%s> ", 40776116Sdcs i, NG_HOOK_NAME(sch->hook)); 40876116Sdcs 40976116Sdcs pos += sprintf(r + pos, " Last Rx: "); 41076116Sdcs if (sch->last_recv) 41176116Sdcs pos += sprintf(r + pos, "%lu s", 41276116Sdcs (unsigned long)(time_second - sch->last_recv)); 41376116Sdcs else 41476116Sdcs pos += sprintf(r + pos, "never"); 41576116Sdcs 41676116Sdcs pos += sprintf(r + pos, ", last RxErr: "); 41776116Sdcs if (sch->last_rxerr) 41876116Sdcs pos += sprintf(r + pos, "%lu s", 41976116Sdcs (unsigned long)(time_second - sch->last_rxerr)); 42040843Smsmith else 42140843Smsmith pos += sprintf(r + pos, "never"); 42240843Smsmith 42340843Smsmith pos += sprintf(r + pos, ", last Tx: "); 42440843Smsmith if (sch->last_xmit) 42540843Smsmith pos += sprintf(r + pos, "%lu s\n", 42640843Smsmith (unsigned long)(time_second - sch->last_xmit)); 42740843Smsmith else 42840843Smsmith pos += sprintf(r + pos, "never\n"); 42940843Smsmith 43040843Smsmith pos += sprintf(r + pos, " RX error(s) %lu", sch->rx_error); 43140843Smsmith pos += sprintf(r + pos, " Short: %lu", sch->short_error); 43240843Smsmith pos += sprintf(r + pos, " CRC: %lu", sch->crc_error); 43340843Smsmith pos += sprintf(r + pos, " Mod8: %lu", sch->dribble_error); 43440843Smsmith pos += sprintf(r + pos, " Long: %lu", sch->long_error); 43540843Smsmith pos += sprintf(r + pos, " Abort: %lu", sch->abort_error); 43640843Smsmith pos += sprintf(r + pos, " Overflow: %lu\n", sch->overflow_error); 43740843Smsmith 43840843Smsmith pos += sprintf(r + pos, " Last error: %b Prev error: %b\n", 43940843Smsmith sch->last_error, "\20\7SHORT\5CRC\4MOD8\3LONG\2ABORT\1OVERRUN", 44040843Smsmith sch->prev_error, "\20\7SHORT\5CRC\4MOD8\3LONG\2ABORT\1OVERRUN"); 44140843Smsmith pos += sprintf(r + pos, " Xmit bytes pending %ld\n", 44240843Smsmith sch->tx_pending); 44340843Smsmith } 44440843Smsmith resp->header.arglen = pos + 1; 44540843Smsmith 44640843Smsmith /* Take care of synchronous response, if any */ 44740843Smsmith NG_RESPOND_MSG(i, node, item, resp); 44840843Smsmith NG_FREE_MSG(msg); 44940843Smsmith return (0); 45040843Smsmith} 45140843Smsmith 45240843Smsmithstatic int 45340843Smsmithngmn_newhook(node_p node, hook_p hook, const char *name) 45440843Smsmith{ 45540843Smsmith u_int32_t ts, chan; 45640843Smsmith struct mn_softc *sc; 45740843Smsmith int nbit; 45840843Smsmith 45940843Smsmith sc = NG_NODE_PRIVATE(node); 46040843Smsmith 46140843Smsmith if (name[0] != 't' || name[1] != 's') 46240843Smsmith return (EINVAL); 46340843Smsmith 46440843Smsmith ts = mn_parse_ts(name + 2, &nbit); 46576116Sdcs printf("%d bits %x\n", nbit, ts); 46640843Smsmith if (sc->framing == E1 && (ts & 1)) 46740843Smsmith return (EINVAL); 46840843Smsmith if (sc->framing == E1U && nbit != 32) 46940843Smsmith return (EINVAL); 47040843Smsmith if (ts == 0) 47140843Smsmith return (EINVAL); 47240843Smsmith if (sc->framing == E1) 47376116Sdcs chan = ffs(ts) - 1; 47440843Smsmith else 47540843Smsmith chan = 1; 47640843Smsmith if (!sc->ch[chan]) 47740843Smsmith mn_create_channel(sc, chan); 47840843Smsmith else if (sc->ch[chan]->state == UP) 47940843Smsmith return (EBUSY); 48040843Smsmith sc->ch[chan]->ts = ts; 48140843Smsmith sc->ch[chan]->hook = hook; 48261182Sdcs sc->ch[chan]->tx_limit = nbit * 8; 48361182Sdcs NG_HOOK_SET_PRIVATE(hook, sc->ch[chan]); 48440843Smsmith sc->nhooks++; 48540843Smsmith return(0); 48676116Sdcs} 48776116Sdcs 48876116Sdcs 48940843Smsmithstatic struct trxd *mn_desc_free; 49040843Smsmith 49140843Smsmithstatic struct trxd * 49240843Smsmithmn_alloc_desc(void) 49340843Smsmith{ 49440843Smsmith struct trxd *dp; 49540843Smsmith 49640843Smsmith dp = mn_desc_free; 49740843Smsmith if (dp) 49840843Smsmith mn_desc_free = dp->vnext; 49940843Smsmith else 50040843Smsmith dp = (struct trxd *)malloc(sizeof *dp, M_MN, M_NOWAIT); 50140843Smsmith return (dp); 50240843Smsmith} 50340843Smsmith 50440843Smsmithstatic void 50540843Smsmithmn_free_desc(struct trxd *dp) 50640843Smsmith{ 50740843Smsmith dp->vnext = mn_desc_free; 50840843Smsmith mn_desc_free = dp; 50940843Smsmith} 51051786Sdcs 51151786Sdcsstatic u_int32_t 51251786Sdcsmn_parse_ts(const char *s, int *nbit) 51351786Sdcs{ 51451786Sdcs unsigned r; 51551786Sdcs int i, j; 51640843Smsmith char *p; 51740843Smsmith 51840843Smsmith r = 0; 51940843Smsmith j = -1; 52040843Smsmith *nbit = 0; 52140843Smsmith while(*s) { 52240843Smsmith i = strtol(s, &p, 0); 52340843Smsmith if (i < 0 || i > 31) 52440843Smsmith return (0); 52540843Smsmith while (j != -1 && j < i) { 52640843Smsmith r |= 1 << j++; 52740843Smsmith (*nbit)++; 52840843Smsmith } 52940843Smsmith j = -1; 53040843Smsmith r |= 1 << i; 53140843Smsmith (*nbit)++; 53240843Smsmith if (*p == ',') { 53340843Smsmith s = p + 1; 53440843Smsmith continue; 53540843Smsmith } else if (*p == '-') { 53640843Smsmith j = i + 1; 53740843Smsmith s = p + 1; 53840843Smsmith continue; 53940843Smsmith } else if (!*p) { 54040843Smsmith break; 54140843Smsmith } else { 54240843Smsmith return (0); 54340843Smsmith } 54440843Smsmith } 54540843Smsmith return (r); 54640843Smsmith} 54740843Smsmith 54840843Smsmith#ifdef notyet 54940843Smsmithstatic void 55040843Smsmithmn_fmt_ts(char *p, u_int32_t ts) 55140843Smsmith{ 55240843Smsmith char *s; 55340843Smsmith int j; 55440843Smsmith 55540843Smsmith s = ""; 55640843Smsmith ts &= 0xffffffff; 55751786Sdcs for (j = 0; j < 32; j++) { 55851786Sdcs if (!(ts & (1 << j))) 55951786Sdcs continue; 56051786Sdcs sprintf(p, "%s%d", s, j); 56151786Sdcs p += strlen(p); 56276116Sdcs s = ","; 56343078Smsmith if (!(ts & (1 << (j+1)))) 56443078Smsmith continue; 56543078Smsmith for (; j < 32; j++) 56640843Smsmith if (!(ts & (1 << (j+1)))) 56740843Smsmith break; 56840843Smsmith sprintf(p, "-%d", j); 56940843Smsmith p += strlen(p); 57040843Smsmith s = ","; 57140843Smsmith } 57240843Smsmith} 57340843Smsmith#endif /* notyet */ 57440843Smsmith 57540843Smsmith/* 57640843Smsmith * OUTPUT 57760959Sdcs */ 57860959Sdcs 57960959Sdcsstatic int 58040843Smsmithngmn_rcvdata(hook_p hook, item_p item) 58140843Smsmith{ 58240843Smsmith struct mbuf *m2; 58340843Smsmith struct trxd *dp, *dp2; 58440843Smsmith struct schan *sch; 58560959Sdcs struct mn_softc *sc; 58660959Sdcs int chan, pitch, len; 58760959Sdcs struct mbuf *m; 58840843Smsmith 58940843Smsmith sch = NG_HOOK_PRIVATE(hook); 59040843Smsmith sc = sch->sc; 59140843Smsmith chan = sch->chan; 59251786Sdcs 59351786Sdcs if (sch->state != UP) { 59451786Sdcs NG_FREE_ITEM(item); 59540843Smsmith return (0); 59651786Sdcs } 59751786Sdcs NGI_GET_M(item, m); 59851786Sdcs if (sch->tx_pending + m->m_pkthdr.len > sch->tx_limit * mn_maxlatency) { 59960959Sdcs NG_FREE_M(m); 60051786Sdcs NG_FREE_ITEM(item); 60151786Sdcs return (0); 60251786Sdcs } 60351786Sdcs NG_FREE_ITEM(item); 60460959Sdcs pitch = 0; 60560959Sdcs m2 = m; 60651786Sdcs dp2 = sc->ch[chan]->xl; 60760959Sdcs len = m->m_pkthdr.len; 60851786Sdcs while (len) { 60951786Sdcs dp = mn_alloc_desc(); 61051786Sdcs if (!dp) { 61151786Sdcs pitch++; 61251786Sdcs m_freem(m); 61351786Sdcs sc->ch[chan]->xl = dp2; 61451786Sdcs dp = dp2->vnext; 61540843Smsmith while (dp) { 61640843Smsmith dp2 = dp->vnext; 61740843Smsmith mn_free_desc(dp); 61840843Smsmith dp = dp2; 61940843Smsmith } 62040843Smsmith sc->ch[chan]->xl->vnext = 0; 62176116Sdcs break; 62276116Sdcs } 62376116Sdcs dp->data = vtophys(m2->m_data); 62440843Smsmith dp->flags = m2->m_len << 16; 62540843Smsmith dp->flags += 1; 62640843Smsmith len -= m2->m_len; 62740843Smsmith dp->next = vtophys(dp); 62840843Smsmith dp->vnext = 0; 62940843Smsmith sc->ch[chan]->xl->next = vtophys(dp); 63040843Smsmith sc->ch[chan]->xl->vnext = dp; 63140843Smsmith sc->ch[chan]->xl = dp; 63240843Smsmith if (!len) { 63340843Smsmith dp->m = m; 63440843Smsmith dp->flags |= 0xc0000000; 63561182Sdcs dp2->flags &= ~0x40000000; 63640843Smsmith } else { 63740843Smsmith dp->m = 0; 63851786Sdcs m2 = m2->m_next; 63951786Sdcs } 64076116Sdcs } 64140843Smsmith if (pitch) 64240843Smsmith printf("%s%d: Short on mem, pitched %d packets\n", 64340843Smsmith sc->name, chan, pitch); 64440843Smsmith else { 64540843Smsmith#if 0 64640843Smsmith printf("%d = %d + %d (%p)\n", 64740843Smsmith sch->tx_pending + m->m_pkthdr.len, 64840843Smsmith sch->tx_pending , m->m_pkthdr.len, m); 64940843Smsmith#endif 65040843Smsmith sch->tx_pending += m->m_pkthdr.len; 65140843Smsmith sc->m32x->txpoll &= ~(1 << chan); 65240843Smsmith } 65340843Smsmith return (0); 65440843Smsmith} 65540843Smsmith 65651786Sdcs/* 65751786Sdcs * OPEN 65851786Sdcs */ 65951786Sdcsstatic int 66040843Smsmithngmn_connect(hook_p hook) 66140843Smsmith{ 66251786Sdcs int i, nts, chan; 66340843Smsmith struct trxd *dp, *dp2; 66476116Sdcs struct mbuf *m; 66540843Smsmith struct mn_softc *sc; 66640843Smsmith struct schan *sch; 66740843Smsmith u_int32_t u; 66840843Smsmith 66940843Smsmith sch = NG_HOOK_PRIVATE(hook); 67040843Smsmith chan = sch->chan; 67140843Smsmith sc = sch->sc; 67240843Smsmith 67340843Smsmith if (sch->state == UP) 67440843Smsmith return (0); 67540843Smsmith sch->state = UP; 67640843Smsmith 67751786Sdcs /* Count and configure the timeslots for this channel */ 67876116Sdcs for (nts = i = 0; i < 32; i++) 67940843Smsmith if (sch->ts & (1 << i)) { 68040843Smsmith sc->m32_mem.ts[i] = 0x00ff00ff | 68140843Smsmith (chan << 24) | (chan << 8); 68240843Smsmith nts++; 68376116Sdcs } 68476116Sdcs 68576116Sdcs /* Init the receiver & xmitter to HDLC */ 68640843Smsmith sc->m32_mem.cs[chan].flags = 0x80e90006; 68740843Smsmith /* Allocate two buffers per timeslot */ 68840843Smsmith if (nts == 32) 68940843Smsmith sc->m32_mem.cs[chan].itbs = 63; 69040843Smsmith else 69140843Smsmith sc->m32_mem.cs[chan].itbs = nts * 2; 69240843Smsmith 69340843Smsmith /* Setup a transmit chain with one descriptor */ 69440843Smsmith /* XXX: we actually send a 1 byte packet */ 69540843Smsmith dp = mn_alloc_desc(); 69640843Smsmith MGETHDR(m, M_TRYWAIT, MT_DATA); 69740843Smsmith if (m == NULL) 69840843Smsmith return ENOBUFS; 69940843Smsmith m->m_pkthdr.len = 0; 70040843Smsmith dp->m = m; 70140843Smsmith dp->flags = 0xc0000000 + (1 << 16); 70240843Smsmith dp->next = vtophys(dp); 70340843Smsmith dp->vnext = 0; 70440843Smsmith dp->data = vtophys(sc->name); 70540843Smsmith sc->m32_mem.cs[chan].tdesc = vtophys(dp); 70640843Smsmith sc->ch[chan]->x1 = dp; 70740843Smsmith sc->ch[chan]->xl = dp; 70840843Smsmith 70940843Smsmith /* Setup a receive chain with 5 + NTS descriptors */ 71040843Smsmith 71140843Smsmith dp = mn_alloc_desc(); 71240843Smsmith m = NULL; 71340843Smsmith MGETHDR(m, M_TRYWAIT, MT_DATA); 71440843Smsmith if (m == NULL) { 71540843Smsmith mn_free_desc(dp); 71640843Smsmith return (ENOBUFS); 71740843Smsmith } 71840843Smsmith MCLGET(m, M_TRYWAIT); 71940843Smsmith if ((m->m_flags & M_EXT) == 0) { 72040843Smsmith mn_free_desc(dp); 72140843Smsmith m_freem(m); 72240843Smsmith return (ENOBUFS); 72340843Smsmith } 72440843Smsmith dp->m = m; 72540843Smsmith dp->data = vtophys(m->m_data); 72640843Smsmith dp->flags = 0x40000000; 72740843Smsmith dp->flags += 1600 << 16; 72840843Smsmith dp->next = vtophys(dp); 72940843Smsmith dp->vnext = 0; 73040843Smsmith sc->ch[chan]->rl = dp; 73140843Smsmith 73240843Smsmith for (i = 0; i < (nts + 10); i++) { 73340843Smsmith dp2 = dp; 73440843Smsmith dp = mn_alloc_desc(); 73540843Smsmith m = NULL; 73640843Smsmith MGETHDR(m, M_TRYWAIT, MT_DATA); 73760014Sdcs if (m == NULL) { 73840843Smsmith mn_free_desc(dp); 73940843Smsmith m_freem(m); 74040843Smsmith return (ENOBUFS); 74140843Smsmith } 74240843Smsmith MCLGET(m, M_TRYWAIT); 74340843Smsmith if ((m->m_flags & M_EXT) == 0) { 74440843Smsmith mn_free_desc(dp); 74540843Smsmith m_freem(m); 74640843Smsmith return (ENOBUFS); 74740843Smsmith } 74840843Smsmith dp->m = m; 74940843Smsmith dp->data = vtophys(m->m_data); 75040843Smsmith dp->flags = 0x00000000; 75140843Smsmith dp->flags += 1600 << 16; 75240843Smsmith dp->next = vtophys(dp2); 75340843Smsmith dp->vnext = dp2; 75440843Smsmith } 75551786Sdcs sc->m32_mem.cs[chan].rdesc = vtophys(dp); 75640843Smsmith sc->ch[chan]->r1 = dp; 75740843Smsmith 75840843Smsmith /* Initialize this channel */ 75940843Smsmith sc->m32_mem.ccb = 0x00008000 + (chan << 8); 76040843Smsmith sc->m32x->cmd = 0x1; 76176116Sdcs DELAY(1000); 76240843Smsmith u = sc->m32x->stat; 76340843Smsmith if (!(u & 1)) 76440843Smsmith printf("%s: init chan %d stat %08x\n", sc->name, chan, u); 76540843Smsmith sc->m32x->stat = 1; 76640843Smsmith /* probably not at splnet, force outward queueing */ 76740843Smsmith NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 76840843Smsmith 76940843Smsmith return (0); 77040843Smsmith} 77140843Smsmith 77240843Smsmith/* 77340843Smsmith * CLOSE 77440843Smsmith */ 77540843Smsmithstatic int 77676116Sdcsngmn_disconnect(hook_p hook) 77776116Sdcs{ 77876116Sdcs int chan, i; 77976116Sdcs struct mn_softc *sc; 78076116Sdcs struct schan *sch; 78176116Sdcs struct trxd *dp, *dp2; 78276116Sdcs u_int32_t u; 78376116Sdcs 78476116Sdcs sch = NG_HOOK_PRIVATE(hook); 78576116Sdcs chan = sch->chan; 78676116Sdcs sc = sch->sc; 78776116Sdcs 78876116Sdcs if (sch->state == DOWN) 78976116Sdcs return (0); 79076116Sdcs sch->state = DOWN; 79176116Sdcs 79276116Sdcs /* Set receiver & transmitter off */ 79376116Sdcs sc->m32_mem.cs[chan].flags = 0x80920006; 79476116Sdcs sc->m32_mem.cs[chan].itbs = 0; 79576116Sdcs 79676116Sdcs /* free the timeslots */ 79776116Sdcs for (i = 0; i < 32; i++) 79840843Smsmith if (sc->ch[chan]->ts & (1 << i)) 79976116Sdcs sc->m32_mem.ts[i] = 0x20002000; 80076116Sdcs 80176116Sdcs /* Initialize this channel */ 80276116Sdcs sc->m32_mem.ccb = 0x00008000 + (chan << 8); 80376116Sdcs sc->m32x->cmd = 0x1; 80476116Sdcs DELAY(30); 80576116Sdcs u = sc->m32x->stat; 80676116Sdcs if (!(u & 1)) 80776116Sdcs printf("%s: zap chan %d stat %08x\n", sc->name, chan, u); 80876116Sdcs sc->m32x->stat = 1; 80976116Sdcs 81076116Sdcs /* Free all receive descriptors and mbufs */ 81176116Sdcs for (dp = sc->ch[chan]->r1; dp ; dp = dp2) { 81276116Sdcs if (dp->m) 81376116Sdcs m_freem(dp->m); 81476116Sdcs sc->ch[chan]->r1 = dp2 = dp->vnext; 81576116Sdcs mn_free_desc(dp); 81676116Sdcs } 81776116Sdcs 81876116Sdcs /* Free all transmit descriptors and mbufs */ 81976116Sdcs for (dp = sc->ch[chan]->x1; dp ; dp = dp2) { 82076116Sdcs if (dp->m) { 82176116Sdcs sc->ch[chan]->tx_pending -= dp->m->m_pkthdr.len; 82276116Sdcs m_freem(dp->m); 82376116Sdcs } 82476116Sdcs sc->ch[chan]->x1 = dp2 = dp->vnext; 82576116Sdcs mn_free_desc(dp); 82676116Sdcs } 82776116Sdcs sc->nhooks--; 82876116Sdcs return(0); 82976116Sdcs} 83076116Sdcs 83176116Sdcs/* 83276116Sdcs * Create a new channel. 83376116Sdcs */ 83476116Sdcsstatic void 83576116Sdcsmn_create_channel(struct mn_softc *sc, int chan) 83676116Sdcs{ 83776116Sdcs struct schan *sch; 83840843Smsmith 83940843Smsmith sch = sc->ch[chan] = (struct schan *)malloc(sizeof *sc->ch[chan], 84040843Smsmith M_MN, M_WAITOK | M_ZERO); 84140843Smsmith sch->sc = sc; 84240843Smsmith sch->state = DOWN; 84340843Smsmith sch->chan = chan; 84440843Smsmith sprintf(sch->name, "%s%d", sc->name, chan); 84540843Smsmith return; 84640843Smsmith} 84740843Smsmith 84840843Smsmith#ifdef notyet 84940843Smsmith/* 85040843Smsmith * Dump Munich32x state 85140843Smsmith */ 85240843Smsmithstatic void 85340843Smsmithm32_dump(struct mn_softc *sc) 85440843Smsmith{ 85540843Smsmith u_int32_t *tp4; 85640843Smsmith int i, j; 85740843Smsmith 85840843Smsmith printf("mn%d: MUNICH32X dump\n", sc->unit); 85940843Smsmith tp4 = (u_int32_t *)sc->m0v; 86040843Smsmith for(j = 0; j < 64; j += 8) { 86140843Smsmith printf("%02x", j * sizeof *tp4); 86240843Smsmith for(i = 0; i < 8; i++) 86340843Smsmith printf(" %08x", tp4[i+j]); 86440843Smsmith printf("\n"); 86540843Smsmith } 86651786Sdcs for(j = 0; j < M32_CHAN; j++) { 86751786Sdcs if (!sc->ch[j]) 86840843Smsmith continue; 86940843Smsmith printf("CH%d: state %d ts %08x", 87040843Smsmith j, sc->ch[j]->state, sc->ch[j]->ts); 87140843Smsmith printf(" %08x %08x %08x %08x %08x %08x\n", 87240843Smsmith sc->m32_mem.cs[j].flags, 87340843Smsmith sc->m32_mem.cs[j].rdesc, 87440843Smsmith sc->m32_mem.cs[j].tdesc, 87540843Smsmith sc->m32_mem.cs[j].itbs, 87640843Smsmith sc->m32_mem.crxd[j], 87740843Smsmith sc->m32_mem.ctxd[j] ); 87840843Smsmith } 87943078Smsmith} 88043078Smsmith 88140843Smsmith/* 88240843Smsmith * Dump Falch54 state 88340843Smsmith */ 88451786Sdcsstatic void 88561182Sdcsf54_dump(struct mn_softc *sc) 88651786Sdcs{ 88740843Smsmith u_int8_t *tp1; 88840843Smsmith int i, j; 88940989Sjkh 89040989Sjkh printf("%s: FALC54 dump\n", sc->name); 89140989Sjkh tp1 = (u_int8_t *)sc->m1v; 89240989Sjkh for(j = 0; j < 128; j += 16) { 89340989Sjkh printf("%s: %02x |", sc->name, j * sizeof *tp1); 89440989Sjkh for(i = 0; i < 16; i++) 89540989Sjkh printf(" %02x", tp1[i+j]); 89640989Sjkh printf("\n"); 89740843Smsmith } 89840843Smsmith} 89940843Smsmith#endif /* notyet */ 90040843Smsmith 90140843Smsmith/* 90240843Smsmith * Init Munich32x 90340843Smsmith */ 90440843Smsmithstatic void 90560959Sdcsm32_init(struct mn_softc *sc) 90660959Sdcs{ 90760959Sdcs 90860959Sdcs sc->m32x->conf = 0x00000000; 90960959Sdcs sc->m32x->mode1 = 0x81048000 + 1600; /* XXX: temp */ 91060959Sdcs#if 1 91160959Sdcs sc->m32x->mode2 = 0x00000081; 91260959Sdcs sc->m32x->txpoll = 0xffffffff; 91360959Sdcs#elif 1 91460959Sdcs sc->m32x->mode2 = 0x00000081; 91551786Sdcs sc->m32x->txpoll = 0xffffffff; 91651786Sdcs#else 91751786Sdcs sc->m32x->mode2 = 0x00000101; 91851786Sdcs#endif 91951786Sdcs sc->m32x->lconf = 0x6060009B; 92051786Sdcs sc->m32x->imask = 0x00000000; 92140843Smsmith} 92240843Smsmith 92340843Smsmith/* 92440843Smsmith * Init the Falc54 92540843Smsmith */ 92640843Smsmithstatic void 92740843Smsmithf54_init(struct mn_softc *sc) 92840843Smsmith{ 92940843Smsmith sc->f54w->ipc = 0x07; 93040843Smsmith 93140843Smsmith sc->f54w->xpm0 = 0xbd; 93240843Smsmith sc->f54w->xpm1 = 0x03; 93340843Smsmith sc->f54w->xpm2 = 0x00; 93461182Sdcs 93561182Sdcs sc->f54w->imr0 = 0x18; /* RMB, CASC */ 93640843Smsmith sc->f54w->imr1 = 0x08; /* XMB */ 93740843Smsmith sc->f54w->imr2 = 0x00; 93840843Smsmith sc->f54w->imr3 = 0x38; /* LMFA16, AIS16, RA16 */ 93940843Smsmith sc->f54w->imr4 = 0x00; 94040843Smsmith 94140843Smsmith sc->f54w->fmr0 = 0xf0; /* X: HDB3, R: HDB3 */ 94240843Smsmith sc->f54w->fmr1 = 0x0e; /* Send CRC4, 2Mbit, ECM */ 94340843Smsmith if (sc->framing == E1) 94440843Smsmith sc->f54w->fmr2 = 0x03; /* Auto Rem-Alarm, Auto resync */ 94540843Smsmith else if (sc->framing == E1U) 94640843Smsmith sc->f54w->fmr2 = 0x33; /* dais, rtm, Auto Rem-Alarm, Auto resync */ 94740843Smsmith 94840843Smsmith sc->f54w->lim1 = 0xb0; /* XCLK=8kHz, .62V threshold */ 94940843Smsmith sc->f54w->pcd = 0x0a; 95040843Smsmith sc->f54w->pcr = 0x15; 95140843Smsmith sc->f54w->xsw = 0x9f; /* fmr4 */ 95240843Smsmith if (sc->framing == E1) 95340843Smsmith sc->f54w->xsp = 0x1c; /* fmr5 */ 95440843Smsmith else if (sc->framing == E1U) 95540843Smsmith sc->f54w->xsp = 0x3c; /* tt0, fmr5 */ 95640843Smsmith sc->f54w->xc0 = 0x07; 95740843Smsmith sc->f54w->xc1 = 0x3d; 95840843Smsmith sc->f54w->rc0 = 0x05; 95940843Smsmith sc->f54w->rc1 = 0x00; 96040843Smsmith sc->f54w->cmdr = 0x51; 96140843Smsmith} 96276116Sdcs 96376116Sdcsstatic int 96476116Sdcsmn_reset(struct mn_softc *sc) 96576116Sdcs{ 96676116Sdcs u_int32_t u; 96776116Sdcs int i; 96876116Sdcs 96976116Sdcs sc->m32x->ccba = vtophys(&sc->m32_mem.csa); 97076116Sdcs sc->m32_mem.csa = vtophys(&sc->m32_mem.ccb); 97176116Sdcs 97276116Sdcs bzero(sc->tiqb, sizeof sc->tiqb); 97340843Smsmith sc->m32x->tiqba = vtophys(&sc->tiqb); 97440843Smsmith sc->m32x->tiql = NIQB / 16 - 1; 97540843Smsmith 97640843Smsmith bzero(sc->riqb, sizeof sc->riqb); 97740843Smsmith sc->m32x->riqba = vtophys(&sc->riqb); 97840843Smsmith sc->m32x->riql = NIQB / 16 - 1; 97976116Sdcs 98076116Sdcs bzero(sc->ltiqb, sizeof sc->ltiqb); 98176116Sdcs sc->m32x->ltiqba = vtophys(&sc->ltiqb); 98240843Smsmith sc->m32x->ltiql = NIQB / 16 - 1; 98343139Smsmith 98476116Sdcs bzero(sc->lriqb, sizeof sc->lriqb); 98576116Sdcs sc->m32x->lriqba = vtophys(&sc->lriqb); 98676116Sdcs sc->m32x->lriql = NIQB / 16 - 1; 98776116Sdcs 98876116Sdcs bzero(sc->piqb, sizeof sc->piqb); 98976116Sdcs sc->m32x->piqba = vtophys(&sc->piqb); 99076116Sdcs sc->m32x->piql = NIQB / 16 - 1; 99176116Sdcs 99276116Sdcs m32_init(sc); 99376116Sdcs f54_init(sc); 99476116Sdcs 99576116Sdcs u = sc->m32x->stat; 99676116Sdcs sc->m32x->stat = u; 99776116Sdcs sc->m32_mem.ccb = 0x4; 99876116Sdcs sc->m32x->cmd = 0x1; 99976116Sdcs DELAY(1000); 100076116Sdcs u = sc->m32x->stat; 100176116Sdcs sc->m32x->stat = u; 100276116Sdcs 100376116Sdcs /* set all timeslots to known state */ 100476116Sdcs for (i = 0; i < 32; i++) 100576116Sdcs sc->m32_mem.ts[i] = 0x20002000; 100676116Sdcs 100776116Sdcs if (!(u & 1)) { 100876116Sdcs printf( 100976116Sdcs"mn%d: WARNING: Controller failed the PCI bus-master test.\n" 101076116Sdcs"mn%d: WARNING: Use a PCI slot which can support bus-master cards.\n", 101176116Sdcs sc->unit, sc->unit); 101260014Sdcs return (0); 101360014Sdcs } 101477443Sdcs return (1); 101577443Sdcs} 101660014Sdcs 101760014Sdcs/* 101861374Sdcs * FALC54 interrupt handling 101961374Sdcs */ 102061374Sdcsstatic void 102142679Sabialf54_intr(struct mn_softc *sc) 102242679Sabial{ 102342679Sabial unsigned g, u, s; 102442634Sabial 102542634Sabial g = sc->f54r->gis; 102661374Sdcs u = sc->f54r->isr0 << 24; 102761374Sdcs u |= sc->f54r->isr1 << 16; 102861374Sdcs u |= sc->f54r->isr2 << 8; 102961374Sdcs u |= sc->f54r->isr3; 103061374Sdcs sc->falc_irq = u; 103161374Sdcs /* don't chat about the 1 sec heart beat */ 103261374Sdcs if (u & ~0x40) { 103365617Sdcs#if 0 103465617Sdcs printf("%s*: FALC54 IRQ GIS:%02x %b\n", sc->name, g, u, "\20" 103565617Sdcs "\40RME\37RFS\36T8MS\35RMB\34CASC\33CRC4\32SA6SC\31RPF" 103665617Sdcs "\30b27\27RDO\26ALLS\25XDU\24XMB\23b22\22XLSC\21XPR" 103761374Sdcs "\20FAR\17LFA\16MFAR\15T400MS\14AIS\13LOS\12RAR\11RA" 103861374Sdcs "\10ES\7SEC\6LMFA16\5AIS16\4RA16\3API\2SLN\1SLP"); 103940843Smsmith#endif 104040843Smsmith s = sc->f54r->frs0 << 24; 104140843Smsmith s |= sc->f54r->frs1 << 16; 104240843Smsmith s |= sc->f54r->rsw << 8; 104340843Smsmith s |= sc->f54r->rsp; 1044 sc->falc_state = s; 1045 1046 s &= ~0x01844038; /* undefined or static bits */ 1047 s &= ~0x00009fc7; /* bits we don't care about */ 1048 s &= ~0x00780000; /* XXX: TS16 related */ 1049 s &= ~0x06000000; /* XXX: Multiframe related */ 1050#if 0 1051 printf("%s*: FALC54 Status %b\n", sc->name, s, "\20" 1052 "\40LOS\37AIS\36LFA\35RRA\34AUXP\33NMF\32LMFA\31frs0.0" 1053 "\30frs1.7\27TS16RA\26TS16LOS\25TS16AIS\24TS16LFA\23frs1.2\22XLS\21XLO" 1054 "\20RS1\17rsw.6\16RRA\15RY0\14RY1\13RY2\12RY3\11RY4" 1055 "\10SI1\7SI2\6rsp.5\5rsp.4\4rsp.3\3RSIF\2RS13\1RS15"); 1056#endif 1057 if (s != sc->framer_state) { 1058#if 0 1059 for (i = 0; i < M32_CHAN; i++) { 1060 if (!sc->ch[i]) 1061 continue; 1062 sp = &sc->ch[i]->ifsppp; 1063 if (!(sp->pp_if.if_flags & IFF_UP)) 1064 continue; 1065 if (s) 1066 timeout((timeout_t *)sp->pp_down, sp, 1 * hz); 1067 else 1068 timeout((timeout_t *)sp->pp_up, sp, 1 * hz); 1069 } 1070#endif 1071 sc->framer_state = s; 1072 } 1073 } 1074 /* Once per second check error counters */ 1075 /* XXX: not clear if this is actually ok */ 1076 if (!(u & 0x40)) 1077 return; 1078 sc->cnt_fec += sc->f54r->fec; 1079 sc->cnt_cvc += sc->f54r->cvc; 1080 sc->cnt_cec1 += sc->f54r->cec1; 1081 sc->cnt_ebc += sc->f54r->ebc; 1082 sc->cnt_cec2 += sc->f54r->cec2; 1083 sc->cnt_cec3 += sc->f54r->cec3; 1084 sc->cnt_rbc += sc->f54r->rbc; 1085} 1086 1087/* 1088 * Transmit interrupt for one channel 1089 */ 1090static void 1091mn_tx_intr(struct mn_softc *sc, u_int32_t vector) 1092{ 1093 u_int32_t chan; 1094 struct trxd *dp; 1095 struct mbuf *m; 1096 1097 chan = vector & 0x1f; 1098 if (!sc->ch[chan]) 1099 return; 1100 if (sc->ch[chan]->state != UP) { 1101 printf("%s: tx_intr when not UP\n", sc->name); 1102 return; 1103 } 1104 for (;;) { 1105 dp = sc->ch[chan]->x1; 1106 if (vtophys(dp) == sc->m32_mem.ctxd[chan]) 1107 return; 1108 m = dp->m; 1109 if (m) { 1110#if 0 1111 printf("%d = %d - %d (%p)\n", 1112 sc->ch[chan]->tx_pending - m->m_pkthdr.len, 1113 sc->ch[chan]->tx_pending , m->m_pkthdr.len, m); 1114#endif 1115 sc->ch[chan]->tx_pending -= m->m_pkthdr.len; 1116 m_freem(m); 1117 } 1118 sc->ch[chan]->last_xmit = time_second; 1119 sc->ch[chan]->x1 = dp->vnext; 1120 mn_free_desc(dp); 1121 } 1122} 1123 1124/* 1125 * Receive interrupt for one channel 1126 */ 1127static void 1128mn_rx_intr(struct mn_softc *sc, u_int32_t vector) 1129{ 1130 u_int32_t chan, err; 1131 struct trxd *dp; 1132 struct mbuf *m; 1133 struct schan *sch; 1134 1135 chan = vector & 0x1f; 1136 if (!sc->ch[chan]) 1137 return; 1138 sch = sc->ch[chan]; 1139 if (sch->state != UP) { 1140 printf("%s: rx_intr when not UP\n", sc->name); 1141 return; 1142 } 1143 vector &= ~0x1f; 1144 if (vector == 0x30000b00) 1145 sch->rx_error++; 1146 for (;;) { 1147 dp = sch->r1; 1148 if (vtophys(dp) == sc->m32_mem.crxd[chan]) 1149 return; 1150 m = dp->m; 1151 dp->m = 0; 1152 m->m_pkthdr.len = m->m_len = (dp->status >> 16) & 0x1fff; 1153 err = (dp->status >> 8) & 0xff; 1154 if (!err) { 1155 int error; 1156 NG_SEND_DATA_ONLY(error, sch->hook, m); 1157 sch->last_recv = time_second; 1158 /* we could be down by now... */ 1159 if (sch->state != UP) 1160 return; 1161 } else if (err & 0x40) { 1162 sch->short_error++; 1163 } else if (err & 0x10) { 1164 sch->crc_error++; 1165 } else if (err & 0x08) { 1166 sch->dribble_error++; 1167 } else if (err & 0x04) { 1168 sch->long_error++; 1169 } else if (err & 0x02) { 1170 sch->abort_error++; 1171 } else if (err & 0x01) { 1172 sch->overflow_error++; 1173 } 1174 if (err) { 1175 sch->last_rxerr = time_second; 1176 sch->prev_error = sch->last_error; 1177 sch->last_error = err; 1178 } 1179 1180 sc->ch[chan]->r1 = dp->vnext; 1181 1182 /* Replenish desc + mbuf supplies */ 1183 if (!m) { 1184 MGETHDR(m, M_DONTWAIT, MT_DATA); 1185 if (m == NULL) { 1186 mn_free_desc(dp); 1187 return; /* ENOBUFS */ 1188 } 1189 MCLGET(m, M_DONTWAIT); 1190 if((m->m_flags & M_EXT) == 0) { 1191 mn_free_desc(dp); 1192 m_freem(m); 1193 return; /* ENOBUFS */ 1194 } 1195 } 1196 dp->m = m; 1197 dp->data = vtophys(m->m_data); 1198 dp->flags = 0x40000000; 1199 dp->flags += 1600 << 16; 1200 dp->next = vtophys(dp); 1201 dp->vnext = 0; 1202 sc->ch[chan]->rl->next = vtophys(dp); 1203 sc->ch[chan]->rl->vnext = dp; 1204 sc->ch[chan]->rl->flags &= ~0x40000000; 1205 sc->ch[chan]->rl = dp; 1206 } 1207} 1208 1209 1210/* 1211 * Interupt handler 1212 */ 1213 1214static void 1215mn_intr(void *xsc) 1216{ 1217 struct mn_softc *sc; 1218 u_int32_t stat, lstat, u; 1219 int i, j; 1220 1221 sc = xsc; 1222 stat = sc->m32x->stat; 1223 lstat = sc->m32x->lstat; 1224#if 0 1225 if (!stat && !(lstat & 2)) 1226 return; 1227#endif 1228 1229 if (stat & ~0xc200) { 1230 printf("%s: I stat=%08x lstat=%08x\n", sc->name, stat, lstat); 1231 } 1232 1233 if ((stat & 0x200) || (lstat & 2)) 1234 f54_intr(sc); 1235 1236 for (j = i = 0; i < 64; i ++) { 1237 u = sc->riqb[i]; 1238 if (u) { 1239 sc->riqb[i] = 0; 1240 mn_rx_intr(sc, u); 1241 if ((u & ~0x1f) == 0x30000800 || (u & ~0x1f) == 0x30000b00) 1242 continue; 1243 u &= ~0x30000400; /* bits we don't care about */ 1244 if ((u & ~0x1f) == 0x00000900) 1245 continue; 1246 if (!(u & ~0x1f)) 1247 continue; 1248 if (!j) 1249 printf("%s*: RIQB:", sc->name); 1250 printf(" [%d]=%08x", i, u); 1251 j++; 1252 } 1253 } 1254 if (j) 1255 printf("\n"); 1256 1257 for (j = i = 0; i < 64; i ++) { 1258 u = sc->tiqb[i]; 1259 if (u) { 1260 sc->tiqb[i] = 0; 1261 mn_tx_intr(sc, u); 1262 if ((u & ~0x1f) == 0x20000800) 1263 continue; 1264 u &= ~0x20000000; /* bits we don't care about */ 1265 if (!u) 1266 continue; 1267 if (!j) 1268 printf("%s*: TIQB:", sc->name); 1269 printf(" [%d]=%08x", i, u); 1270 j++; 1271 } 1272 } 1273 if (j) 1274 printf("\n"); 1275 sc->m32x->stat = stat; 1276} 1277 1278static void 1279mn_timeout(void *xsc) 1280{ 1281 static int round = 0; 1282 struct mn_softc *sc; 1283 1284 mn_intr(xsc); 1285 sc = xsc; 1286 timeout(mn_timeout, xsc, 10 * hz); 1287 round++; 1288 if (round == 2) { 1289 sc->m32_mem.ccb = 0x00008004; 1290 sc->m32x->cmd = 0x1; 1291 } else if (round > 2) { 1292 printf("%s: timeout\n", sc->name); 1293 } 1294} 1295 1296/* 1297 * PCI initialization stuff 1298 */ 1299 1300static int 1301mn_probe (device_t self) 1302{ 1303 u_int id = pci_get_devid(self); 1304 1305 if (sizeof (struct m32xreg) != 256) { 1306 printf("MN: sizeof(struct m32xreg) = %zd, should have been 256\n", sizeof (struct m32xreg)); 1307 return (ENXIO); 1308 } 1309 if (sizeof (struct f54rreg) != 128) { 1310 printf("MN: sizeof(struct f54rreg) = %zd, should have been 128\n", sizeof (struct f54rreg)); 1311 return (ENXIO); 1312 } 1313 if (sizeof (struct f54wreg) != 128) { 1314 printf("MN: sizeof(struct f54wreg) = %zd, should have been 128\n", sizeof (struct f54wreg)); 1315 return (ENXIO); 1316 } 1317 1318 if (id != 0x2101110a) 1319 return (ENXIO); 1320 1321 device_set_desc_copy(self, "Munich32X E1/T1 HDLC Controller"); 1322 return (0); 1323} 1324 1325static int 1326mn_attach (device_t self) 1327{ 1328 struct mn_softc *sc; 1329 u_int32_t u; 1330 u_int32_t ver; 1331 static int once; 1332 int rid, error; 1333 struct resource *res; 1334 1335 if (!once) { 1336 if (ng_newtype(&mntypestruct)) 1337 printf("ng_newtype failed\n"); 1338 once++; 1339 } 1340 1341 sc = (struct mn_softc *)malloc(sizeof *sc, M_MN, M_WAITOK | M_ZERO); 1342 device_set_softc(self, sc); 1343 1344 sc->dev = self; 1345 sc->unit = device_get_unit(self); 1346 sc->framing = E1; 1347 sprintf(sc->name, "mn%d", sc->unit); 1348 1349 rid = PCIR_BAR(0); 1350 res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); 1351 if (res == NULL) { 1352 device_printf(self, "Could not map memory\n"); 1353 free(sc, M_MN); 1354 return ENXIO; 1355 } 1356 sc->m0v = rman_get_virtual(res); 1357 sc->m0p = rman_get_start(res); 1358 1359 rid = PCIR_BAR(1); 1360 res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); 1361 if (res == NULL) { 1362 device_printf(self, "Could not map memory\n"); 1363 free(sc, M_MN); 1364 return ENXIO; 1365 } 1366 sc->m1v = rman_get_virtual(res); 1367 sc->m1p = rman_get_start(res); 1368 1369 /* Allocate interrupt */ 1370 rid = 0; 1371 sc->irq = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, 1372 RF_SHAREABLE | RF_ACTIVE); 1373 1374 if (sc->irq == NULL) { 1375 printf("couldn't map interrupt\n"); 1376 free(sc, M_MN); 1377 return(ENXIO); 1378 } 1379 1380 error = bus_setup_intr(self, sc->irq, INTR_TYPE_NET, mn_intr, sc, &sc->intrhand); 1381 1382 if (error) { 1383 printf("couldn't set up irq\n"); 1384 free(sc, M_MN); 1385 return(ENXIO); 1386 } 1387 1388 u = pci_read_config(self, PCIR_COMMAND, 1); 1389 printf("%x\n", u); 1390 pci_write_config(self, PCIR_COMMAND, u | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN, 1); 1391#if 0 1392 pci_write_config(self, PCIR_COMMAND, 0x02800046, 4); 1393#endif 1394 u = pci_read_config(self, PCIR_COMMAND, 1); 1395 printf("%x\n", u); 1396 1397 ver = pci_get_revid(self); 1398 1399 sc->m32x = (struct m32xreg *) sc->m0v; 1400 sc->f54w = (struct f54wreg *) sc->m1v; 1401 sc->f54r = (struct f54rreg *) sc->m1v; 1402 1403 /* We must reset before poking at FALC54 registers */ 1404 u = mn_reset(sc); 1405 if (!u) 1406 return (0); 1407 1408 printf("mn%d: Munich32X", sc->unit); 1409 switch (ver) { 1410 case 0x13: 1411 printf(" Rev 2.2"); 1412 break; 1413 default: 1414 printf(" Rev 0x%x\n", ver); 1415 } 1416 printf(", Falc54"); 1417 switch (sc->f54r->vstr) { 1418 case 0: 1419 printf(" Rev < 1.3\n"); 1420 break; 1421 case 1: 1422 printf(" Rev 1.3\n"); 1423 break; 1424 case 2: 1425 printf(" Rev 1.4\n"); 1426 break; 1427 case 0x10: 1428 printf("-LH Rev 1.1\n"); 1429 break; 1430 case 0x13: 1431 printf("-LH Rev 1.3\n"); 1432 break; 1433 default: 1434 printf(" Rev 0x%x\n", sc->f54r->vstr); 1435 } 1436 1437 if (ng_make_node_common(&mntypestruct, &sc->node) != 0) { 1438 printf("ng_make_node_common failed\n"); 1439 return (0); 1440 } 1441 NG_NODE_SET_PRIVATE(sc->node, sc); 1442 sprintf(sc->nodename, "%s%d", NG_MN_NODE_TYPE, sc->unit); 1443 if (ng_name_node(sc->node, sc->nodename)) { 1444 NG_NODE_UNREF(sc->node); 1445 return (0); 1446 } 1447 1448 return (0); 1449} 1450 1451 1452static device_method_t mn_methods[] = { 1453 /* Device interface */ 1454 DEVMETHOD(device_probe, mn_probe), 1455 DEVMETHOD(device_attach, mn_attach), 1456 DEVMETHOD(device_suspend, bus_generic_suspend), 1457 DEVMETHOD(device_resume, bus_generic_resume), 1458 DEVMETHOD(device_shutdown, bus_generic_shutdown), 1459 1460 {0, 0} 1461}; 1462 1463static driver_t mn_driver = { 1464 "mn", 1465 mn_methods, 1466 0 1467}; 1468 1469static devclass_t mn_devclass; 1470 1471DRIVER_MODULE(mn, pci, mn_driver, mn_devclass, 0, 0); 1472