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