if_mn.c revision 71139
1/* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 * 9 * $Id: if_mn.c,v 1.1 1999/02/01 13:06:40 phk Exp $ 10 * 11 * Driver for Siemens reference design card "Easy321-R1". 12 * 13 * This card contains a FALC54 E1/T1 framer and a MUNICH32X 32-channel HDLC 14 * controller. 15 * 16 * The driver supports E1 mode with up to 31 channels. We send CRC4 but don't 17 * check it coming in. 18 * 19 * The FALC54 and MUNICH32X have far too many registers and weird modes for 20 * comfort, so I have not bothered typing it all into a "fooreg.h" file, 21 * you will (badly!) need the documentation anyway if you want to mess with 22 * this gadget. 23 * 24 * $FreeBSD: head/sys/pci/if_mn.c 71139 2001-01-17 01:17:00Z peter $ 25 */ 26 27/* 28 * Stuff to describe the MUNIC32X and FALC54 chips. 29 */ 30 31#define M32_CHAN 32 /* We have 32 channels */ 32#define M32_TS 32 /* We have 32 timeslots */ 33 34#define NG_MN_NODE_TYPE "mn" 35 36#include <sys/param.h> 37#include <sys/kernel.h> 38#include <sys/sysctl.h> 39#include <sys/bus.h> 40#include <sys/mbuf.h> 41#include <sys/systm.h> 42#include <sys/malloc.h> 43 44#include <pci/pcireg.h> 45#include <pci/pcivar.h> 46#include "pci_if.h" 47 48#include <machine/bus.h> 49#include <machine/resource.h> 50 51#include <sys/rman.h> 52 53#include <vm/vm.h> 54#include <vm/pmap.h> 55 56#include <netgraph/ng_message.h> 57#include <netgraph/netgraph.h> 58 59 60static int mn_maxlatency = 1000; 61SYSCTL_INT(_debug, OID_AUTO, mn_maxlatency, CTLFLAG_RW, 62 &mn_maxlatency, 0, 63 "The number of milliseconds a packet is allowed to spend in the output queue. " 64 "If the output queue is longer than this number of milliseconds when the packet " 65 "arrives for output, the packet will be dropped." 66); 67 68#ifndef NMN 69/* Most machines don't support more than 4 busmaster PCI slots, if even that many */ 70#define NMN 4 71#endif 72 73/* From: PEB 20321 data sheet, p187, table 22 */ 74struct m32xreg { 75 u_int32_t conf, cmd, stat, imask; 76 u_int32_t fill10, piqba, piql, fill1c; 77 u_int32_t mode1, mode2, ccba, txpoll; 78 u_int32_t tiqba, tiql, riqba, riql; 79 u_int32_t lconf, lccba, fill48, ltran; 80 u_int32_t ltiqba, ltiql, lriqba, lriql; 81 u_int32_t lreg0, lreg1, lreg2, lreg3; 82 u_int32_t lreg4, lreg5, lre6, lstat; 83 u_int32_t gpdir, gpdata, gpod, fill8c; 84 u_int32_t ssccon, sscbr, ssctb, sscrb; 85 u_int32_t ssccse, sscim, fillab, fillac; 86 u_int32_t iomcon1, iomcon2, iomstat, fillbc; 87 u_int32_t iomcit0, iomcit1, iomcir0, iomcir1; 88 u_int32_t iomtmo, iomrmo, filld8, filldc; 89 u_int32_t mbcmd, mbdata1, mbdata2, mbdata3; 90 u_int32_t mbdata4, mbdata5, mbdata6, mbdata7; 91}; 92 93/* From: PEB 2254 data sheet, p80, table 10 */ 94struct f54wreg { 95 u_int16_t xfifo; 96 u_int8_t cmdr, mode, rah1, rah2, ral1, ral2; 97 u_int8_t ipc, ccr1, ccr3, pre, rtr1, rtr2, rtr3, rtr4; 98 u_int8_t ttr1, ttr2, ttr3, ttr4, imr0, imr1, imr2, imr3; 99 u_int8_t imr4, fill19, fmr0, fmr1, fmr2, loop, xsw, xsp; 100 u_int8_t xc0, xc1, rc0, rc1, xpm0, xpm1, xpm2, tswm; 101 u_int8_t test1, idle, xsa4, xsa5, xsa6, xsa7, xsa8, fmr3; 102 u_int8_t icb1, icb2, icb3, icb4, lim0, lim1, pcd, pcr; 103 u_int8_t lim2, fill39[7]; 104 u_int8_t fill40[8]; 105 u_int8_t fill48[8]; 106 u_int8_t fill50[8]; 107 u_int8_t fill58[8]; 108 u_int8_t dec, fill61, test2, fill63[5]; 109 u_int8_t fill68[8]; 110 u_int8_t xs[16]; 111}; 112 113/* From: PEB 2254 data sheet, p117, table 10 */ 114struct f54rreg { 115 u_int16_t rfifo; 116 u_int8_t fill2, mode, rah1, rah2, ral1, ral2; 117 u_int8_t ipc, ccr1, ccr3, pre, rtr1, rtr2, rtr3, rtr4; 118 u_int8_t ttr1, ttr2, ttr3, ttr4, imr0, imr1, imr2, imr3; 119 u_int8_t imr4, fill19, fmr0, fmr1, fmr2, loop, xsw, xsp; 120 u_int8_t xc0, xc1, rc0, rc1, xpm0, xpm1, xpm2, tswm; 121 u_int8_t test, idle, xsa4, xsa5, xsa6, xsa7, xsa8, fmr13; 122 u_int8_t icb1, icb2, icb3, icb4, lim0, lim1, pcd, pcr; 123 u_int8_t lim2, fill39[7]; 124 u_int8_t fill40[8]; 125 u_int8_t fill48[4], frs0, frs1, rsw, rsp; 126 u_int16_t fec, cvc, cec1, ebc; 127 u_int16_t cec2, cec3; 128 u_int8_t rsa4, rsa5, rsa6, rsa7; 129 u_int8_t rsa8, rsa6s, tsr0, tsr1, sis, rsis; 130 u_int16_t rbc; 131 u_int8_t isr0, isr1, isr2, isr3, fill6c, fill6d, gis, vstr; 132 u_int8_t rs[16]; 133}; 134 135/* Transmit & receive descriptors */ 136struct trxd { 137 u_int32_t flags; 138 vm_offset_t next; 139 vm_offset_t data; 140 u_int32_t status; /* only used for receive */ 141 struct mbuf *m; /* software use only */ 142 struct trxd *vnext; /* software use only */ 143}; 144 145/* Channel specification */ 146struct cspec { 147 u_int32_t flags; 148 vm_offset_t rdesc; 149 vm_offset_t tdesc; 150 u_int32_t itbs; 151}; 152 153struct m32_mem { 154 vm_offset_t csa; 155 u_int32_t ccb; 156 u_int32_t reserve1[2]; 157 u_int32_t ts[M32_TS]; 158 struct cspec cs[M32_CHAN]; 159 vm_offset_t crxd[M32_CHAN]; 160 vm_offset_t ctxd[M32_CHAN]; 161}; 162 163struct softc; 164struct sockaddr; 165struct rtentry; 166 167static int mn_probe (device_t self); 168static int mn_attach (device_t self); 169static void mn_create_channel(struct softc *sc, int chan); 170static int mn_reset(struct softc *sc); 171static struct trxd * mn_alloc_desc(void); 172static void mn_free_desc(struct trxd *dp); 173static void mn_intr(void *xsc); 174static u_int32_t mn_parse_ts(const char *s, int *nbit); 175#ifdef notyet 176static void m32_dump(struct softc *sc); 177static void f54_dump(struct softc *sc); 178static void mn_fmt_ts(char *p, u_int32_t ts); 179#endif /* notyet */ 180 181static ng_constructor_t ngmn_constructor; 182static ng_rcvmsg_t ngmn_rcvmsg; 183static ng_shutdown_t ngmn_shutdown; 184static ng_newhook_t ngmn_newhook; 185static ng_connect_t ngmn_connect; 186static ng_rcvdata_t ngmn_rcvdata; 187static ng_disconnect_t ngmn_disconnect; 188 189static struct ng_type mntypestruct = { 190 NG_ABI_VERSION, 191 NG_MN_NODE_TYPE, 192 NULL, 193 ngmn_constructor, 194 ngmn_rcvmsg, 195 ngmn_shutdown, 196 ngmn_newhook, 197 NULL, 198 ngmn_connect, 199 ngmn_rcvdata, 200 ngmn_disconnect, 201 NULL 202}; 203 204static MALLOC_DEFINE(M_MN, "mn", "Mx driver related"); 205 206#define NIQB 64 207 208struct schan { 209 enum {DOWN, UP} state; 210 struct softc *sc; 211 int chan; 212 u_int32_t ts; 213 char name[8]; 214 struct trxd *r1, *rl; 215 struct trxd *x1, *xl; 216 hook_p hook; 217 218 time_t last_recv; 219 time_t last_rxerr; 220 time_t last_xmit; 221 222 u_long rx_error; 223 224 u_long short_error; 225 u_long crc_error; 226 u_long dribble_error; 227 u_long long_error; 228 u_long abort_error; 229 u_long overflow_error; 230 231 int last_error; 232 int prev_error; 233 234 u_long tx_pending; 235 u_long tx_limit; 236}; 237 238struct softc { 239 int unit; 240 device_t dev; 241 struct resource *irq; 242 void *intrhand; 243 void *m0v, *m1v; 244 vm_offset_t m0p, m1p; 245 struct m32xreg *m32x; 246 struct f54wreg *f54w; 247 struct f54rreg *f54r; 248 struct m32_mem m32_mem; 249 u_int32_t tiqb[NIQB]; 250 u_int32_t riqb[NIQB]; 251 u_int32_t piqb[NIQB]; 252 u_int32_t ltiqb[NIQB]; 253 u_int32_t lriqb[NIQB]; 254 char name[8]; 255 u_int32_t falc_irq, falc_state, framer_state; 256 struct schan *ch[M32_CHAN]; 257 char nodename[NG_NODELEN + 1]; 258 node_p node; 259 260 u_long cnt_fec; 261 u_long cnt_cvc; 262 u_long cnt_cec1; 263 u_long cnt_ebc; 264 u_long cnt_cec2; 265 u_long cnt_cec3; 266 u_long cnt_rbc; 267}; 268 269static int 270ngmn_constructor(node_p node) 271{ 272 273 return (EINVAL); 274} 275 276static int 277ngmn_shutdown(node_p nodep) 278{ 279 280 return (EINVAL); 281} 282 283static int 284ngmn_rcvmsg(node_p node, item_p item, hook_p lasthook) 285{ 286 struct softc *sc; 287 struct ng_mesg *resp = NULL; 288 struct schan *sch; 289 char *arg; 290 int pos, i; 291 struct ng_mesg *msg; 292 293 NGI_GET_MSG(item, msg); 294 sc = NG_NODE_PRIVATE(node); 295 296 if (msg->header.typecookie != NGM_GENERIC_COOKIE || 297 msg->header.cmd != NGM_TEXT_STATUS) { 298 NG_FREE_ITEM(item); 299 NG_FREE_MSG(msg); 300 return (EINVAL); 301 } 302 NG_MKRESPONSE(resp, msg, sizeof(struct ng_mesg) + NG_TEXTRESPONSE, 303 M_NOWAIT); 304 if (resp == NULL) { 305 NG_FREE_ITEM(item); 306 NG_FREE_MSG(msg); 307 return (ENOMEM); 308 } 309 arg = (char *)resp->data; 310 pos = 0; 311 pos += sprintf(pos + arg,"Framer status %b;\n", sc->framer_state, "\20" 312 "\40LOS\37AIS\36LFA\35RRA" 313 "\34AUXP\33NMF\32LMFA\31frs0.0" 314 "\30frs1.7\27TS16RA\26TS16LOS\25TS16AIS" 315 "\24TS16LFA\23frs1.2\22XLS\21XLO" 316 "\20RS1\17rsw.6\16RRA\15RY0" 317 "\14RY1\13RY2\12RY3\11RY4" 318 "\10SI1\7SI2\6rsp.5\5rsp.4" 319 "\4rsp.3\3RSIF\2RS13\1RS15"); 320 pos += sprintf(pos + arg," Framing errors: %lu", sc->cnt_fec); 321 pos += sprintf(pos + arg," Code Violations: %lu\n", sc->cnt_cvc); 322 323 pos += sprintf(pos + arg," Falc State %b;\n", sc->falc_state, "\20" 324 "\40LOS\37AIS\36LFA\35RRA" 325 "\34AUXP\33NMF\32LMFA\31frs0.0" 326 "\30frs1.7\27TS16RA\26TS16LOS\25TS16AIS" 327 "\24TS16LFA\23frs1.2\22XLS\21XLO" 328 "\20RS1\17rsw.6\16RRA\15RY0" 329 "\14RY1\13RY2\12RY3\11RY4" 330 "\10SI1\7SI2\6rsp.5\5rsp.4" 331 "\4rsp.3\3RSIF\2RS13\1RS15"); 332 pos += sprintf(pos + arg, " Falc IRQ %b\n", sc->falc_irq, "\20" 333 "\40RME\37RFS\36T8MS\35RMB\34CASC\33CRC4\32SA6SC\31RPF" 334 "\30b27\27RDO\26ALLS\25XDU\24XMB\23b22\22XLSC\21XPR" 335 "\20FAR\17LFA\16MFAR\15T400MS\14AIS\13LOS\12RAR\11RA" 336 "\10ES\7SEC\6LMFA16\5AIS16\4RA16\3API\2SLN\1SLP"); 337 for (i = 0; i < M32_CHAN; i++) { 338 if (!sc->ch[i]) 339 continue; 340 sch = sc->ch[i]; 341 342 pos += sprintf(arg + pos, " Chan %d <%s> ", 343 i, NG_HOOK_NAME(sch->hook)); 344 345 pos += sprintf(arg + pos, " Last Rx: "); 346 if (sch->last_recv) 347 pos += sprintf(arg + pos, "%lu s", time_second - sch->last_recv); 348 else 349 pos += sprintf(arg + pos, "never"); 350 351 pos += sprintf(arg + pos, ", last RxErr: "); 352 if (sch->last_rxerr) 353 pos += sprintf(arg + pos, "%lu s", time_second - sch->last_rxerr); 354 else 355 pos += sprintf(arg + pos, "never"); 356 357 pos += sprintf(arg + pos, ", last Tx: "); 358 if (sch->last_xmit) 359 pos += sprintf(arg + pos, "%lu s\n", time_second - sch->last_xmit); 360 else 361 pos += sprintf(arg + pos, "never\n"); 362 363 pos += sprintf(arg + pos, " RX error(s) %lu", sch->rx_error); 364 pos += sprintf(arg + pos, " Short: %lu", sch->short_error); 365 pos += sprintf(arg + pos, " CRC: %lu", sch->crc_error); 366 pos += sprintf(arg + pos, " Mod8: %lu", sch->dribble_error); 367 pos += sprintf(arg + pos, " Long: %lu", sch->long_error); 368 pos += sprintf(arg + pos, " Abort: %lu", sch->abort_error); 369 pos += sprintf(arg + pos, " Overflow: %lu\n", sch->overflow_error); 370 371 pos += sprintf(arg + pos, " Last error: %b Prev error: %b\n", 372 sch->last_error, "\20\7SHORT\5CRC\4MOD8\3LONG\2ABORT\1OVERRUN", 373 sch->prev_error, "\20\7SHORT\5CRC\4MOD8\3LONG\2ABORT\1OVERRUN"); 374 pos += sprintf(arg + pos, " Xmit bytes pending %ld\n", 375 sch->tx_pending); 376 } 377 resp->header.arglen = pos + 1; 378 379 /* Take care of synchronous response, if any */ 380 NG_RESPOND_MSG(i, node, item, resp); 381 NG_FREE_MSG(msg); 382 return (0); 383} 384 385static int 386ngmn_newhook(node_p node, hook_p hook, const char *name) 387{ 388 u_int32_t ts, chan; 389 struct softc *sc; 390 int nbit; 391 392 sc = NG_NODE_PRIVATE(node); 393 394 if (name[0] != 't' || name[1] != 's') 395 return (EINVAL); 396 397 ts = mn_parse_ts(name + 2, &nbit); 398 if (ts == 0) 399 return (EINVAL); 400 chan = ffs(ts) - 1; 401 if (!sc->ch[chan]) 402 mn_create_channel(sc, chan); 403 else if (sc->ch[chan]->state == UP) 404 return (EBUSY); 405 sc->ch[chan]->ts = ts; 406 sc->ch[chan]->hook = hook; 407 sc->ch[chan]->tx_limit = nbit * 8; 408 NG_HOOK_SET_PRIVATE(hook, sc->ch[chan]); 409 return(0); 410} 411 412 413static struct trxd *mn_desc_free; 414 415static struct trxd * 416mn_alloc_desc(void) 417{ 418 struct trxd *dp; 419 420 dp = mn_desc_free; 421 if (dp) 422 mn_desc_free = dp->vnext; 423 else 424 dp = (struct trxd *)malloc(sizeof *dp, M_MN, M_NOWAIT); 425 return (dp); 426} 427 428static void 429mn_free_desc(struct trxd *dp) 430{ 431 dp->vnext = mn_desc_free; 432 mn_desc_free = dp; 433} 434 435static u_int32_t 436mn_parse_ts(const char *s, int *nbit) 437{ 438 unsigned r; 439 int i, j; 440 char *p; 441 442 r = 0; 443 j = 0; 444 *nbit = 0; 445 while(*s) { 446 i = strtol(s, &p, 0); 447 if (i < 1 || i > 31) 448 return (0); 449 while (j && j < i) { 450 r |= 1 << j++; 451 (*nbit)++; 452 } 453 j = 0; 454 r |= 1 << i; 455 (*nbit)++; 456 if (*p == ',') { 457 s = p + 1; 458 continue; 459 } else if (*p == '-') { 460 j = i; 461 s = p + 1; 462 continue; 463 } else if (!*p) { 464 break; 465 } else { 466 return (0); 467 } 468 } 469 return (r); 470} 471 472#ifdef notyet 473static void 474mn_fmt_ts(char *p, u_int32_t ts) 475{ 476 char *s; 477 int j; 478 479 s = ""; 480 ts &= 0xfffffffe; 481 for (j = 1; j < 32; j++) { 482 if (!(ts & (1 << j))) 483 continue; 484 sprintf(p, "%s%d", s, j); 485 p += strlen(p); 486 s = ","; 487 if (!(ts & (1 << (j+1)))) 488 continue; 489 for (; j < 32; j++) 490 if (!(ts & (1 << (j+1)))) 491 break; 492 sprintf(p, "-%d", j); 493 p += strlen(p); 494 s = ","; 495 } 496} 497#endif /* notyet */ 498 499/* 500 * OUTPUT 501 */ 502 503static int 504ngmn_rcvdata(hook_p hook, item_p item) 505{ 506 struct mbuf *m2; 507 struct trxd *dp, *dp2; 508 struct schan *sch; 509 struct softc *sc; 510 int chan, pitch, len; 511 struct mbuf *m; 512 513 sch = NG_HOOK_PRIVATE(hook); 514 sc = sch->sc; 515 chan = sch->chan; 516 517 if (sch->state != UP) { 518 NG_FREE_ITEM(item); 519 return (0); 520 } 521 NGI_GET_M(item, m); 522 if (sch->tx_pending + m->m_pkthdr.len > sch->tx_limit * mn_maxlatency) { 523 NG_FREE_M(m); 524 NG_FREE_ITEM(item); 525 return (0); 526 } 527 NG_FREE_ITEM(item); 528 pitch = 0; 529 m2 = m; 530 dp2 = sc->ch[chan]->xl; 531 len = m->m_pkthdr.len; 532 while (len) { 533 dp = mn_alloc_desc(); 534 if (!dp) { 535 pitch++; 536 m_freem(m); 537 sc->ch[chan]->xl = dp2; 538 dp = dp2->vnext; 539 while (dp) { 540 dp2 = dp->vnext; 541 mn_free_desc(dp); 542 dp = dp2; 543 } 544 sc->ch[chan]->xl->vnext = 0; 545 break; 546 } 547 dp->data = vtophys(m2->m_data); 548 dp->flags = m2->m_len << 16; 549 dp->flags += 1; 550 len -= m2->m_len; 551 dp->next = vtophys(dp); 552 dp->vnext = 0; 553 sc->ch[chan]->xl->next = vtophys(dp); 554 sc->ch[chan]->xl->vnext = dp; 555 sc->ch[chan]->xl = dp; 556 if (!len) { 557 dp->m = m; 558 dp->flags |= 0xc0000000; 559 dp2->flags &= ~0x40000000; 560 } else { 561 dp->m = 0; 562 m2 = m2->m_next; 563 } 564 } 565 if (pitch) 566 printf("%s%d: Short on mem, pitched %d packets\n", 567 sc->name, chan, pitch); 568 else { 569#if 0 570 printf("%d = %d + %d (%p)\n", 571 sch->tx_pending + m->m_pkthdr.len, 572 sch->tx_pending , m->m_pkthdr.len, m); 573#endif 574 sch->tx_pending += m->m_pkthdr.len; 575 } 576 return (0); 577} 578 579/* 580 * OPEN 581 */ 582static int 583ngmn_connect(hook_p hook) 584{ 585 int i, nts, chan; 586 struct trxd *dp, *dp2; 587 struct mbuf *m; 588 struct softc *sc; 589 struct schan *sch; 590 u_int32_t u; 591 592 sch = NG_HOOK_PRIVATE(hook); 593 chan = sch->chan; 594 sc = sch->sc; 595 596 if (sch->state == UP) 597 return (0); 598 sch->state = UP; 599 600 /* Count and configure the timeslots for this channel */ 601 for (nts = i = 0; i < 32; i++) 602 if (sch->ts & (1 << i)) { 603 sc->m32_mem.ts[i] = 0x00ff00ff | 604 (chan << 24) | (chan << 8); 605 nts++; 606 } 607 608 /* Init the receiver & xmitter to HDLC */ 609 sc->m32_mem.cs[chan].flags = 0x80e90006; 610 /* Allocate two buffers per timeslot */ 611 sc->m32_mem.cs[chan].itbs = nts * 2; 612 613 /* Setup a transmit chain with one descriptor */ 614 /* XXX: we actually send a 1 byte packet */ 615 dp = mn_alloc_desc(); 616 MGETHDR(m, M_TRYWAIT, MT_DATA); 617 if (m == NULL) 618 return ENOBUFS; 619 m->m_pkthdr.len = 0; 620 dp->m = m; 621 dp->flags = 0xc0000000 + (1 << 16); 622 dp->next = vtophys(dp); 623 dp->vnext = 0; 624 dp->data = vtophys(sc->name); 625 sc->m32_mem.cs[chan].tdesc = vtophys(dp); 626 sc->ch[chan]->x1 = dp; 627 sc->ch[chan]->xl = dp; 628 629 /* Setup a receive chain with 5 + NTS descriptors */ 630 631 dp = mn_alloc_desc(); 632 m = NULL; 633 MGETHDR(m, M_TRYWAIT, MT_DATA); 634 if (m == NULL) { 635 mn_free_desc(dp); 636 return (ENOBUFS); 637 } 638 MCLGET(m, M_TRYWAIT); 639 if ((m->m_flags & M_EXT) == 0) { 640 mn_free_desc(dp); 641 m_freem(m); 642 return (ENOBUFS); 643 } 644 dp->m = m; 645 dp->data = vtophys(m->m_data); 646 dp->flags = 0x40000000; 647 dp->flags += 1600 << 16; 648 dp->next = vtophys(dp); 649 dp->vnext = 0; 650 sc->ch[chan]->rl = dp; 651 652 for (i = 0; i < (nts + 10); i++) { 653 dp2 = dp; 654 dp = mn_alloc_desc(); 655 m = NULL; 656 MGETHDR(m, M_TRYWAIT, MT_DATA); 657 if (m == NULL) { 658 mn_free_desc(dp); 659 m_freem(m); 660 return (ENOBUFS); 661 } 662 MCLGET(m, M_TRYWAIT); 663 if ((m->m_flags & M_EXT) == 0) { 664 mn_free_desc(dp); 665 m_freem(m); 666 return (ENOBUFS); 667 } 668 dp->m = m; 669 dp->data = vtophys(m->m_data); 670 dp->flags = 0x00000000; 671 dp->flags += 1600 << 16; 672 dp->next = vtophys(dp2); 673 dp->vnext = dp2; 674 } 675 sc->m32_mem.cs[chan].rdesc = vtophys(dp); 676 sc->ch[chan]->r1 = dp; 677 678 /* Initialize this channel */ 679 sc->m32_mem.ccb = 0x00008000 + (chan << 8); 680 sc->m32x->cmd = 0x1; 681 DELAY(1000); 682 u = sc->m32x->stat; 683 if (!(u & 1)) 684 printf("%s: init chan %d stat %08x\n", sc->name, chan, u); 685 sc->m32x->stat = 1; 686 /* probably not at splnet, force outward queueing */ 687 NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 688 689 return (0); 690} 691 692/* 693 * CLOSE 694 */ 695static int 696ngmn_disconnect(hook_p hook) 697{ 698 int chan, i; 699 struct softc *sc; 700 struct schan *sch; 701 struct trxd *dp, *dp2; 702 u_int32_t u; 703 704 sch = NG_HOOK_PRIVATE(hook); 705 chan = sch->chan; 706 sc = sch->sc; 707 708 if (sch->state == DOWN) 709 return (0); 710 sch->state = DOWN; 711 712 /* Set receiver & transmitter off */ 713 sc->m32_mem.cs[chan].flags = 0x80920006; 714 sc->m32_mem.cs[chan].itbs = 0; 715 716 /* free the timeslots */ 717 for (i = 0; i < 32; i++) 718 if (sc->ch[chan]->ts & (1 << i)) 719 sc->m32_mem.ts[i] = 0x20002000; 720 721 /* Initialize this channel */ 722 sc->m32_mem.ccb = 0x00008000 + (chan << 8); 723 sc->m32x->cmd = 0x1; 724 DELAY(30); 725 u = sc->m32x->stat; 726 if (!(u & 1)) 727 printf("%s: zap chan %d stat %08x\n", sc->name, chan, u); 728 sc->m32x->stat = 1; 729 730 /* Free all receive descriptors and mbufs */ 731 for (dp = sc->ch[chan]->r1; dp ; dp = dp2) { 732 if (dp->m) 733 m_freem(dp->m); 734 sc->ch[chan]->r1 = dp2 = dp->vnext; 735 mn_free_desc(dp); 736 } 737 738 /* Free all transmit descriptors and mbufs */ 739 for (dp = sc->ch[chan]->x1; dp ; dp = dp2) { 740 if (dp->m) { 741 sc->ch[chan]->tx_pending -= dp->m->m_pkthdr.len; 742 m_freem(dp->m); 743 } 744 sc->ch[chan]->x1 = dp2 = dp->vnext; 745 mn_free_desc(dp); 746 } 747 return(0); 748} 749 750/* 751 * Create a new channel. 752 */ 753static void 754mn_create_channel(struct softc *sc, int chan) 755{ 756 struct schan *sch; 757 758 sch = sc->ch[chan] = (struct schan *)malloc(sizeof *sc->ch[chan], 759 M_MN, M_WAITOK | M_ZERO); 760 sch->sc = sc; 761 sch->state = DOWN; 762 sch->chan = chan; 763 sprintf(sch->name, "%s%d", sc->name, chan); 764 return; 765} 766 767#ifdef notyet 768/* 769 * Dump Munich32x state 770 */ 771static void 772m32_dump(struct softc *sc) 773{ 774 u_int32_t *tp4; 775 int i, j; 776 777 printf("mn%d: MUNICH32X dump\n", sc->unit); 778 tp4 = (u_int32_t *)sc->m0v; 779 for(j = 0; j < 64; j += 8) { 780 printf("%02x", j * sizeof *tp4); 781 for(i = 0; i < 8; i++) 782 printf(" %08x", tp4[i+j]); 783 printf("\n"); 784 } 785 for(j = 0; j < M32_CHAN; j++) { 786 if (!sc->ch[j]) 787 continue; 788 printf("CH%d: state %d ts %08x", 789 j, sc->ch[j]->state, sc->ch[j]->ts); 790 printf(" %08x %08x %08x %08x %08x %08x\n", 791 sc->m32_mem.cs[j].flags, 792 sc->m32_mem.cs[j].rdesc, 793 sc->m32_mem.cs[j].tdesc, 794 sc->m32_mem.cs[j].itbs, 795 sc->m32_mem.crxd[j], 796 sc->m32_mem.ctxd[j] ); 797 } 798} 799 800/* 801 * Dump Falch54 state 802 */ 803static void 804f54_dump(struct softc *sc) 805{ 806 u_int8_t *tp1; 807 int i, j; 808 809 printf("%s: FALC54 dump\n", sc->name); 810 tp1 = (u_int8_t *)sc->m1v; 811 for(j = 0; j < 128; j += 16) { 812 printf("%s: %02x |", sc->name, j * sizeof *tp1); 813 for(i = 0; i < 16; i++) 814 printf(" %02x", tp1[i+j]); 815 printf("\n"); 816 } 817} 818#endif /* notyet */ 819 820/* 821 * Init Munich32x 822 */ 823static void 824m32_init(struct softc *sc) 825{ 826 827 sc->m32x->conf = 0x00000000; 828 sc->m32x->mode1 = 0x81048000 + 1600; /* XXX: temp */ 829#if 1 830 sc->m32x->mode2 = 0x00000081; 831 sc->m32x->txpoll = 0xffffffff; 832#else 833 sc->m32x->mode2 = 0x00000101; 834#endif 835 sc->m32x->lconf = 0x6060009B; 836 sc->m32x->imask = 0x00000000; 837} 838 839/* 840 * Init the Falc54 841 */ 842static void 843f54_init(struct softc *sc) 844{ 845 sc->f54w->ipc = 0x07; 846 847 sc->f54w->xpm0 = 0xbd; 848 sc->f54w->xpm1 = 0x03; 849 sc->f54w->xpm2 = 0x00; 850 851 sc->f54w->imr0 = 0x18; /* RMB, CASC */ 852 sc->f54w->imr1 = 0x08; /* XMB */ 853 sc->f54w->imr2 = 0x00; 854 sc->f54w->imr3 = 0x38; /* LMFA16, AIS16, RA16 */ 855 sc->f54w->imr4 = 0x00; 856 857 sc->f54w->fmr0 = 0xf0; /* X: HDB3, R: HDB3 */ 858 sc->f54w->fmr1 = 0x0e; /* Send CRC4, 2Mbit, ECM */ 859 sc->f54w->fmr2 = 0x03; /* Auto Rem-Alarm, Auto resync */ 860 861 sc->f54w->lim1 = 0xb0; /* XCLK=8kHz, .62V threshold */ 862 sc->f54w->pcd = 0x0a; 863 sc->f54w->pcr = 0x15; 864 sc->f54w->xsw = 0x9f; /* fmr4 */ 865 sc->f54w->xsp = 0x1c; /* fmr5 */ 866 sc->f54w->xc0 = 0x07; 867 sc->f54w->xc1 = 0x3d; 868 sc->f54w->rc0 = 0x05; 869 sc->f54w->rc1 = 0x00; 870 sc->f54w->cmdr = 0x51; 871} 872 873static int 874mn_reset(struct softc *sc) 875{ 876 u_int32_t u; 877 int i; 878 879 sc->m32x->ccba = vtophys(&sc->m32_mem.csa); 880 sc->m32_mem.csa = vtophys(&sc->m32_mem.ccb); 881 882 bzero(sc->tiqb, sizeof sc->tiqb); 883 sc->m32x->tiqba = vtophys(&sc->tiqb); 884 sc->m32x->tiql = NIQB / 16 - 1; 885 886 bzero(sc->riqb, sizeof sc->riqb); 887 sc->m32x->riqba = vtophys(&sc->riqb); 888 sc->m32x->riql = NIQB / 16 - 1; 889 890 bzero(sc->ltiqb, sizeof sc->ltiqb); 891 sc->m32x->ltiqba = vtophys(&sc->ltiqb); 892 sc->m32x->ltiql = NIQB / 16 - 1; 893 894 bzero(sc->lriqb, sizeof sc->lriqb); 895 sc->m32x->lriqba = vtophys(&sc->lriqb); 896 sc->m32x->lriql = NIQB / 16 - 1; 897 898 bzero(sc->piqb, sizeof sc->piqb); 899 sc->m32x->piqba = vtophys(&sc->piqb); 900 sc->m32x->piql = NIQB / 16 - 1; 901 902 m32_init(sc); 903 f54_init(sc); 904 905 u = sc->m32x->stat; 906 sc->m32x->stat = u; 907 sc->m32_mem.ccb = 0x4; 908 sc->m32x->cmd = 0x1; 909 DELAY(1000); 910 u = sc->m32x->stat; 911 sc->m32x->stat = u; 912 913 /* set all timeslots to known state */ 914 for (i = 0; i < 32; i++) 915 sc->m32_mem.ts[i] = 0x20002000; 916 917 if (!(u & 1)) { 918 printf( 919"mn%d: WARNING: Controller failed the PCI bus-master test.\n" 920"mn%d: WARNING: Use a PCI slot which can support bus-master cards.\n", 921 sc->unit, sc->unit); 922 return (0); 923 } 924 return (1); 925} 926 927/* 928 * FALC54 interrupt handling 929 */ 930static void 931f54_intr(struct softc *sc) 932{ 933 unsigned g, u, s; 934 935 g = sc->f54r->gis; 936 u = sc->f54r->isr0 << 24; 937 u |= sc->f54r->isr1 << 16; 938 u |= sc->f54r->isr2 << 8; 939 u |= sc->f54r->isr3; 940 sc->falc_irq = u; 941 /* don't chat about the 1 sec heart beat */ 942 if (u & ~0x40) { 943#if 0 944 printf("%s*: FALC54 IRQ GIS:%02x %b\n", sc->name, g, u, "\20" 945 "\40RME\37RFS\36T8MS\35RMB\34CASC\33CRC4\32SA6SC\31RPF" 946 "\30b27\27RDO\26ALLS\25XDU\24XMB\23b22\22XLSC\21XPR" 947 "\20FAR\17LFA\16MFAR\15T400MS\14AIS\13LOS\12RAR\11RA" 948 "\10ES\7SEC\6LMFA16\5AIS16\4RA16\3API\2SLN\1SLP"); 949#endif 950 s = sc->f54r->frs0 << 24; 951 s |= sc->f54r->frs1 << 16; 952 s |= sc->f54r->rsw << 8; 953 s |= sc->f54r->rsp; 954 sc->falc_state = s; 955 956 s &= ~0x01844038; /* undefined or static bits */ 957 s &= ~0x00009fc7; /* bits we don't care about */ 958 s &= ~0x00780000; /* XXX: TS16 related */ 959 s &= ~0x06000000; /* XXX: Multiframe related */ 960#if 0 961 printf("%s*: FALC54 Status %b\n", sc->name, s, "\20" 962 "\40LOS\37AIS\36LFA\35RRA\34AUXP\33NMF\32LMFA\31frs0.0" 963 "\30frs1.7\27TS16RA\26TS16LOS\25TS16AIS\24TS16LFA\23frs1.2\22XLS\21XLO" 964 "\20RS1\17rsw.6\16RRA\15RY0\14RY1\13RY2\12RY3\11RY4" 965 "\10SI1\7SI2\6rsp.5\5rsp.4\4rsp.3\3RSIF\2RS13\1RS15"); 966#endif 967 if (s != sc->framer_state) { 968#if 0 969 for (i = 0; i < M32_CHAN; i++) { 970 if (!sc->ch[i]) 971 continue; 972 sp = &sc->ch[i]->ifsppp; 973 if (!(sp->pp_if.if_flags & IFF_UP)) 974 continue; 975 if (s) 976 timeout((timeout_t *)sp->pp_down, sp, 1 * hz); 977 else 978 timeout((timeout_t *)sp->pp_up, sp, 1 * hz); 979 } 980#endif 981 sc->framer_state = s; 982 } 983 } 984 /* Once per second check error counters */ 985 /* XXX: not clear if this is actually ok */ 986 if (!(u & 0x40)) 987 return; 988 sc->cnt_fec += sc->f54r->fec; 989 sc->cnt_cvc += sc->f54r->cvc; 990 sc->cnt_cec1 += sc->f54r->cec1; 991 sc->cnt_ebc += sc->f54r->ebc; 992 sc->cnt_cec2 += sc->f54r->cec2; 993 sc->cnt_cec3 += sc->f54r->cec3; 994 sc->cnt_rbc += sc->f54r->rbc; 995} 996 997/* 998 * Transmit interrupt for one channel 999 */ 1000static void 1001mn_tx_intr(struct softc *sc, u_int32_t vector) 1002{ 1003 u_int32_t chan; 1004 struct trxd *dp; 1005 struct mbuf *m; 1006 1007 chan = vector & 0x1f; 1008 if (!sc->ch[chan]) 1009 return; 1010 if (sc->ch[chan]->state != UP) { 1011 printf("%s: tx_intr when not UP\n", sc->name); 1012 return; 1013 } 1014 for (;;) { 1015 dp = sc->ch[chan]->x1; 1016 if (vtophys(dp) == sc->m32_mem.ctxd[chan]) 1017 return; 1018 m = dp->m; 1019 if (m) { 1020#if 0 1021 printf("%d = %d - %d (%p)\n", 1022 sc->ch[chan]->tx_pending - m->m_pkthdr.len, 1023 sc->ch[chan]->tx_pending , m->m_pkthdr.len, m); 1024#endif 1025 sc->ch[chan]->tx_pending -= m->m_pkthdr.len; 1026 m_freem(m); 1027 } 1028 sc->ch[chan]->last_xmit = time_second; 1029 sc->ch[chan]->x1 = dp->vnext; 1030 mn_free_desc(dp); 1031 } 1032} 1033 1034/* 1035 * Receive interrupt for one channel 1036 */ 1037static void 1038mn_rx_intr(struct softc *sc, u_int32_t vector) 1039{ 1040 u_int32_t chan, err; 1041 struct trxd *dp; 1042 struct mbuf *m; 1043 struct schan *sch; 1044 1045 chan = vector & 0x1f; 1046 if (!sc->ch[chan]) 1047 return; 1048 sch = sc->ch[chan]; 1049 if (sch->state != UP) { 1050 printf("%s: rx_intr when not UP\n", sc->name); 1051 return; 1052 } 1053 vector &= ~0x1f; 1054 if (vector == 0x30000b00) 1055 sch->rx_error++; 1056 for (;;) { 1057 dp = sch->r1; 1058 if (vtophys(dp) == sc->m32_mem.crxd[chan]) 1059 return; 1060 m = dp->m; 1061 dp->m = 0; 1062 m->m_pkthdr.len = m->m_len = (dp->status >> 16) & 0x1fff; 1063 err = (dp->status >> 8) & 0xff; 1064 if (!err) { 1065 int error; 1066 NG_SEND_DATA_ONLY(error, sch->hook, m); 1067 sch->last_recv = time_second; 1068 /* we could be down by now... */ 1069 if (sch->state != UP) 1070 return; 1071 } else if (err & 0x40) { 1072 sch->short_error++; 1073 } else if (err & 0x10) { 1074 sch->crc_error++; 1075 } else if (err & 0x08) { 1076 sch->dribble_error++; 1077 } else if (err & 0x04) { 1078 sch->long_error++; 1079 } else if (err & 0x02) { 1080 sch->abort_error++; 1081 } else if (err & 0x01) { 1082 sch->overflow_error++; 1083 } 1084 if (err) { 1085 sch->last_rxerr = time_second; 1086 sch->prev_error = sch->last_error; 1087 sch->last_error = err; 1088 } 1089 1090 sc->ch[chan]->r1 = dp->vnext; 1091 1092 /* Replenish desc + mbuf supplies */ 1093 if (!m) { 1094 MGETHDR(m, M_DONTWAIT, MT_DATA); 1095 if (m == NULL) { 1096 mn_free_desc(dp); 1097 return; /* ENOBUFS */ 1098 } 1099 MCLGET(m, M_DONTWAIT); 1100 if((m->m_flags & M_EXT) == 0) { 1101 mn_free_desc(dp); 1102 m_freem(m); 1103 return; /* ENOBUFS */ 1104 } 1105 } 1106 dp->m = m; 1107 dp->data = vtophys(m->m_data); 1108 dp->flags = 0x40000000; 1109 dp->flags += 1600 << 16; 1110 dp->next = vtophys(dp); 1111 dp->vnext = 0; 1112 sc->ch[chan]->rl->next = vtophys(dp); 1113 sc->ch[chan]->rl->vnext = dp; 1114 sc->ch[chan]->rl->flags &= ~0x40000000; 1115 sc->ch[chan]->rl = dp; 1116 } 1117} 1118 1119 1120/* 1121 * Interupt handler 1122 */ 1123 1124static void 1125mn_intr(void *xsc) 1126{ 1127 struct softc *sc; 1128 u_int32_t stat, lstat, u; 1129 int i, j; 1130 1131 sc = xsc; 1132 stat = sc->m32x->stat; 1133 lstat = sc->m32x->lstat; 1134#if 0 1135 if (!stat && !(lstat & 2)) 1136 return; 1137#endif 1138 1139 if (stat & ~0xc200) { 1140 printf("%s: I stat=%08x lstat=%08x\n", sc->name, stat, lstat); 1141 } 1142 1143 if ((stat & 0x200) || (lstat & 2)) 1144 f54_intr(sc); 1145 1146 for (j = i = 0; i < 64; i ++) { 1147 u = sc->riqb[i]; 1148 if (u) { 1149 sc->riqb[i] = 0; 1150 mn_rx_intr(sc, u); 1151 if ((u & ~0x1f) == 0x30000800 || (u & ~0x1f) == 0x30000b00) 1152 continue; 1153 u &= ~0x30000400; /* bits we don't care about */ 1154 if ((u & ~0x1f) == 0x00000900) 1155 continue; 1156 if (!(u & ~0x1f)) 1157 continue; 1158 if (!j) 1159 printf("%s*: RIQB:", sc->name); 1160 printf(" [%d]=%08x", i, u); 1161 j++; 1162 } 1163 } 1164 if (j) 1165 printf("\n"); 1166 1167 for (j = i = 0; i < 64; i ++) { 1168 u = sc->tiqb[i]; 1169 if (u) { 1170 sc->tiqb[i] = 0; 1171 mn_tx_intr(sc, u); 1172 if ((u & ~0x1f) == 0x20000800) 1173 continue; 1174 u &= ~0x20000000; /* bits we don't care about */ 1175 if (!u) 1176 continue; 1177 if (!j) 1178 printf("%s*: TIQB:", sc->name); 1179 printf(" [%d]=%08x", i, u); 1180 j++; 1181 } 1182 } 1183 if (j) 1184 printf("\n"); 1185 sc->m32x->stat = stat; 1186} 1187 1188static void 1189mn_timeout(void *xsc) 1190{ 1191 static int round = 0; 1192 struct softc *sc; 1193 1194 mn_intr(xsc); 1195 sc = xsc; 1196 timeout(mn_timeout, xsc, 10 * hz); 1197 round++; 1198 if (round == 2) { 1199 sc->m32_mem.ccb = 0x00008004; 1200 sc->m32x->cmd = 0x1; 1201 } else if (round > 2) { 1202 printf("%s: timeout\n", sc->name); 1203 } 1204} 1205 1206/* 1207 * PCI initialization stuff 1208 */ 1209 1210static int 1211mn_probe (device_t self) 1212{ 1213 u_int id = pci_get_devid(self); 1214 1215 if (sizeof (struct m32xreg) != 256) { 1216 printf("MN: sizeof(struct m32xreg) = %d, should have been 256\n", sizeof (struct m32xreg)); 1217 return (ENXIO); 1218 } 1219 if (sizeof (struct f54rreg) != 128) { 1220 printf("MN: sizeof(struct f54rreg) = %d, should have been 128\n", sizeof (struct f54rreg)); 1221 return (ENXIO); 1222 } 1223 if (sizeof (struct f54wreg) != 128) { 1224 printf("MN: sizeof(struct f54wreg) = %d, should have been 128\n", sizeof (struct f54wreg)); 1225 return (ENXIO); 1226 } 1227 1228 if (id != 0x2101110a) 1229 return (ENXIO); 1230 1231 device_set_desc_copy(self, "Munich32X E1/T1 HDLC Controller"); 1232 return (0); 1233} 1234 1235static int 1236mn_attach (device_t self) 1237{ 1238 struct softc *sc; 1239 u_int32_t u; 1240 u_int32_t ver; 1241 static int once; 1242 int rid, error; 1243 struct resource *res; 1244 1245 if (!once) { 1246 if (ng_newtype(&mntypestruct)) 1247 printf("ng_newtype failed\n"); 1248 once++; 1249 } 1250 1251 sc = (struct softc *)malloc(sizeof *sc, M_MN, M_WAITOK | M_ZERO); 1252 device_set_softc(self, sc); 1253 1254 sc->dev = self; 1255 sc->unit = device_get_unit(self); 1256 sprintf(sc->name, "mn%d", sc->unit); 1257 1258 rid = PCIR_MAPS; 1259 res = bus_alloc_resource(self, SYS_RES_MEMORY, &rid, 1260 0, ~0, 1, RF_ACTIVE); 1261 if (res == NULL) { 1262 device_printf(self, "Could not map memory\n"); 1263 return ENXIO; 1264 } 1265 sc->m0v = rman_get_virtual(res); 1266 sc->m0p = rman_get_start(res); 1267 1268 rid = PCIR_MAPS + 4; 1269 res = bus_alloc_resource(self, SYS_RES_MEMORY, &rid, 1270 0, ~0, 1, RF_ACTIVE); 1271 if (res == NULL) { 1272 device_printf(self, "Could not map memory\n"); 1273 return ENXIO; 1274 } 1275 sc->m1v = rman_get_virtual(res); 1276 sc->m1p = rman_get_start(res); 1277 1278 /* Allocate interrupt */ 1279 rid = 0; 1280 sc->irq = bus_alloc_resource(self, SYS_RES_IRQ, &rid, 0, ~0, 1281 1, RF_SHAREABLE | RF_ACTIVE); 1282 1283 if (sc->irq == NULL) { 1284 printf("couldn't map interrupt\n"); 1285 return(ENXIO); 1286 } 1287 1288 error = bus_setup_intr(self, sc->irq, INTR_TYPE_NET, mn_intr, sc, &sc->intrhand); 1289 1290 if (error) { 1291 printf("couldn't set up irq\n"); 1292 return(ENXIO); 1293 } 1294 1295 u = pci_read_config(self, PCIR_COMMAND, 1); 1296 printf("%x\n", u); 1297 pci_write_config(self, PCIR_COMMAND, u | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN, 1); 1298#if 0 1299 pci_write_config(self, PCIR_COMMAND, 0x02800046, 4); 1300#endif 1301 u = pci_read_config(self, PCIR_COMMAND, 1); 1302 printf("%x\n", u); 1303 1304 ver = pci_get_revid(self); 1305 1306 sc->m32x = (struct m32xreg *) sc->m0v; 1307 sc->f54w = (struct f54wreg *) sc->m1v; 1308 sc->f54r = (struct f54rreg *) sc->m1v; 1309 1310 /* We must reset before poking at FALC54 registers */ 1311 u = mn_reset(sc); 1312 if (!u) 1313 return (0); 1314 1315 printf("mn%d: Munich32X", sc->unit); 1316 switch (ver) { 1317 case 0x13: 1318 printf(" Rev 2.2"); 1319 break; 1320 default: 1321 printf(" Rev 0x%x\n", ver); 1322 } 1323 printf(", Falc54"); 1324 switch (sc->f54r->vstr) { 1325 case 0: 1326 printf(" Rev < 1.3\n"); 1327 break; 1328 case 1: 1329 printf(" Rev 1.3\n"); 1330 break; 1331 case 2: 1332 printf(" Rev 1.4\n"); 1333 break; 1334 case 0x10: 1335 printf("-LH Rev 1.1\n"); 1336 break; 1337 case 0x13: 1338 printf("-LH Rev 1.3\n"); 1339 break; 1340 default: 1341 printf(" Rev 0x%x\n", sc->f54r->vstr); 1342 } 1343 1344 if (ng_make_node_common(&mntypestruct, &sc->node) != 0) { 1345 printf("ng_make_node_common failed\n"); 1346 return (0); 1347 } 1348 NG_NODE_SET_PRIVATE(sc->node, sc); 1349 sprintf(sc->nodename, "%s%d", NG_MN_NODE_TYPE, sc->unit); 1350 if (ng_name_node(sc->node, sc->nodename)) { 1351 NG_NODE_UNREF(sc->node); 1352 return (0); 1353 } 1354 1355 return (0); 1356} 1357 1358 1359static device_method_t mn_methods[] = { 1360 /* Device interface */ 1361 DEVMETHOD(device_probe, mn_probe), 1362 DEVMETHOD(device_attach, mn_attach), 1363 DEVMETHOD(device_suspend, bus_generic_suspend), 1364 DEVMETHOD(device_resume, bus_generic_resume), 1365 DEVMETHOD(device_shutdown, bus_generic_shutdown), 1366 1367 {0, 0} 1368}; 1369 1370static driver_t mn_driver = { 1371 "mn", 1372 mn_methods, 1373 0 1374}; 1375 1376static devclass_t mn_devclass; 1377 1378DRIVER_MODULE(mn, pci, mn_driver, mn_devclass, 0, 0); 1379