1 /* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * All rights reserved. 4 * 5 * Derived from the public domain Linux driver 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <dev/sound/pcm/sound.h> 32 #include <dev/sound/pcm/ac97.h> 33 #include <dev/sound/pci/neomagic.h> 34 #include <dev/sound/pci/neomagic-coeff.h> 35 36 #include <pci/pcireg.h> 37 #include <pci/pcivar.h> 38 39 /* -------------------------------------------------------------------- */ 40 41 #define NM_BUFFSIZE 16384 42 43 #define NM256AV_PCI_ID 0x800510c8 44 #define NM256ZX_PCI_ID 0x800610c8 45 46 struct sc_info; 47 48 /* channel registers */ 49 struct sc_chinfo { 50 int spd, dir, fmt; 51 snd_dbuf *buffer; 52 pcm_channel *channel; 53 struct sc_info *parent; 54 }; 55 56 /* device private data */ 57 struct sc_info { 58 device_t dev; 59 u_int32_t type; 60 61 struct resource *reg, *irq, *buf; 62 int regid, irqid, bufid; 63 void *ih; 64 65 u_int32_t ac97_base, ac97_status, ac97_busy; 66 u_int32_t buftop, pbuf, rbuf, cbuf, acbuf; 67 u_int32_t playint, recint, misc1int, misc2int; 68 u_int32_t irsz, badintr; 69 70 struct sc_chinfo pch, rch; 71 }; 72 73 /* -------------------------------------------------------------------- */ 74 75 /* 76 * prototypes 77 */ 78 79 /* channel interface */ 80 static void *nmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 81 static int nmchan_setdir(void *data, int dir); 82 static int nmchan_setformat(void *data, u_int32_t format); 83 static int nmchan_setspeed(void *data, u_int32_t speed); 84 static int nmchan_setblocksize(void *data, u_int32_t blocksize); 85 static int nmchan_trigger(void *data, int go); 86 static int nmchan_getptr(void *data); 87 static pcmchan_caps *nmchan_getcaps(void *data); 88 89 static int nm_waitcd(struct sc_info *sc); 90 /* talk to the codec - called from ac97.c */ 91 static u_int32_t nm_rdcd(void *, int); 92 static void nm_wrcd(void *, int, u_int32_t); 93 94 /* stuff */ 95 static int nm_loadcoeff(struct sc_info *sc, int dir, int num); 96 static int nm_setch(struct sc_chinfo *ch); 97 static int nm_init(struct sc_info *); 98 static void nm_intr(void *); 99 100 /* talk to the card */ 101 static u_int32_t nm_rd(struct sc_info *, int, int); 102 static void nm_wr(struct sc_info *, int, u_int32_t, int); 103 static u_int32_t nm_rdbuf(struct sc_info *, int, int); 104 static void nm_wrbuf(struct sc_info *, int, u_int32_t, int); 105 106 static u_int32_t badcards[] = { 107 0x0007103c, 108 0x008f1028, 109 }; 110 #define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t)) 111 112 /* The actual rates supported by the card. */ 113 static int samplerates[9] = { 114 8000, 115 11025, 116 16000, 117 22050, 118 24000, 119 32000, 120 44100, 121 48000, 122 99999999 123 }; 124 125 /* -------------------------------------------------------------------- */ 126 127 static pcmchan_caps nm_caps = { 128 4000, 48000, 129 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, 130 AFMT_STEREO | AFMT_S16_LE 131 }; 132 133 static pcm_channel nm_chantemplate = { 134 nmchan_init, 135 nmchan_setdir, 136 nmchan_setformat, 137 nmchan_setspeed, 138 nmchan_setblocksize, 139 nmchan_trigger, 140 nmchan_getptr, 141 nmchan_getcaps, 142 }; 143 144 /* -------------------------------------------------------------------- */ 145 146 /* Hardware */ 147 static u_int32_t 148 nm_rd(struct sc_info *sc, int regno, int size) 149 { 150 bus_space_tag_t st = rman_get_bustag(sc->reg); 151 bus_space_handle_t sh = rman_get_bushandle(sc->reg); 152 153 switch (size) { 154 case 1: 155 return bus_space_read_1(st, sh, regno); 156 case 2: 157 return bus_space_read_2(st, sh, regno); 158 case 4: 159 return bus_space_read_4(st, sh, regno); 160 default: 161 return 0xffffffff; 162 } 163 } 164 165 static void 166 nm_wr(struct sc_info *sc, int regno, u_int32_t data, int size) 167 { 168 bus_space_tag_t st = rman_get_bustag(sc->reg); 169 bus_space_handle_t sh = rman_get_bushandle(sc->reg); 170 171 switch (size) { 172 case 1: 173 bus_space_write_1(st, sh, regno, data); 174 break; 175 case 2: 176 bus_space_write_2(st, sh, regno, data); 177 break; 178 case 4: 179 bus_space_write_4(st, sh, regno, data); 180 break; 181 } 182 } 183 184 static u_int32_t 185 nm_rdbuf(struct sc_info *sc, int regno, int size) 186 { 187 bus_space_tag_t st = rman_get_bustag(sc->buf); 188 bus_space_handle_t sh = rman_get_bushandle(sc->buf); 189 190 switch (size) { 191 case 1: 192 return bus_space_read_1(st, sh, regno); 193 case 2: 194 return bus_space_read_2(st, sh, regno); 195 case 4: 196 return bus_space_read_4(st, sh, regno); 197 default: 198 return 0xffffffff; 199 } 200 } 201 202 static void 203 nm_wrbuf(struct sc_info *sc, int regno, u_int32_t data, int size) 204 { 205 bus_space_tag_t st = rman_get_bustag(sc->buf); 206 bus_space_handle_t sh = rman_get_bushandle(sc->buf); 207 208 switch (size) { 209 case 1: 210 bus_space_write_1(st, sh, regno, data); 211 break; 212 case 2: 213 bus_space_write_2(st, sh, regno, data); 214 break; 215 case 4: 216 bus_space_write_4(st, sh, regno, data); 217 break; 218 } 219 } 220 221 /* ac97 codec */ 222 static int 223 nm_waitcd(struct sc_info *sc) 224 { 225 int cnt = 10; 226 227 while (cnt-- > 0) { 228 if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy) 229 DELAY(100); 230 else 231 break; 232 } 233 return (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy); 234 } 235 236 static u_int32_t 237 nm_rdcd(void *devinfo, int regno) 238 { 239 struct sc_info *sc = (struct sc_info *)devinfo; 240 u_int32_t x; 241 242 if (!nm_waitcd(sc)) { 243 x = nm_rd(sc, sc->ac97_base + regno, 2); 244 DELAY(1000); 245 return x; 246 } else { 247 device_printf(sc->dev, "ac97 codec not ready\n"); 248 return 0xffffffff; 249 } 250 } 251 252 static void 253 nm_wrcd(void *devinfo, int regno, u_int32_t data) 254 { 255 struct sc_info *sc = (struct sc_info *)devinfo; 256 int cnt = 3; 257 258 if (!nm_waitcd(sc)) { 259 while (cnt-- > 0) { 260 nm_wr(sc, sc->ac97_base + regno, data, 2); 261 if (!nm_waitcd(sc)) { 262 DELAY(1000); 263 return; 264 } 265 } 266 } 267 device_printf(sc->dev, "ac97 codec not ready\n"); 268 } 269 270 static void 271 nm_ackint(struct sc_info *sc, u_int32_t num) 272 { 273 if (sc->type == NM256AV_PCI_ID) { 274 nm_wr(sc, NM_INT_REG, num << 1, 2); 275 } else if (sc->type == NM256ZX_PCI_ID) { 276 nm_wr(sc, NM_INT_REG, num, 4); 277 } 278 } 279 280 static int 281 nm_loadcoeff(struct sc_info *sc, int dir, int num) 282 { 283 int ofs, sz, i; 284 u_int32_t addr; 285 286 addr = (dir == PCMDIR_PLAY)? 0x01c : 0x21c; 287 if (dir == PCMDIR_REC) 288 num += 8; 289 sz = coefficientSizes[num]; 290 ofs = 0; 291 while (num-- > 0) 292 ofs+= coefficientSizes[num]; 293 for (i = 0; i < sz; i++) 294 nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1); 295 nm_wr(sc, addr, sc->cbuf, 4); 296 if (dir == PCMDIR_PLAY) 297 sz--; 298 nm_wr(sc, addr + 4, sc->cbuf + sz, 4); 299 return 0; 300 } 301 302 static int 303 nm_setch(struct sc_chinfo *ch) 304 { 305 struct sc_info *sc = ch->parent; 306 u_int32_t base; 307 u_int8_t x; 308 309 for (x = 0; x < 8; x++) 310 if (ch->spd < (samplerates[x] + samplerates[x + 1]) / 2) 311 break; 312 313 if (x == 8) return 1; 314 315 ch->spd = samplerates[x]; 316 nm_loadcoeff(sc, ch->dir, x); 317 318 x <<= 4; 319 x &= NM_RATE_MASK; 320 if (ch->fmt & AFMT_16BIT) x |= NM_RATE_BITS_16; 321 if (ch->fmt & AFMT_STEREO) x |= NM_RATE_STEREO; 322 323 base = (ch->dir == PCMDIR_PLAY)? NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET; 324 nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1); 325 return 0; 326 } 327 328 /* channel interface */ 329 static void * 330 nmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 331 { 332 struct sc_info *sc = devinfo; 333 struct sc_chinfo *ch; 334 u_int32_t chnbuf; 335 336 chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf; 337 ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; 338 ch->buffer = b; 339 ch->buffer->bufsize = NM_BUFFSIZE; 340 ch->buffer->buf = (u_int8_t *)(rman_get_bushandle(sc->buf) + chnbuf); 341 if (bootverbose) 342 device_printf(sc->dev, "%s buf %p\n", (dir == PCMDIR_PLAY)? 343 "play" : "rec", ch->buffer->buf); 344 ch->parent = sc; 345 ch->channel = c; 346 ch->dir = dir; 347 return ch; 348 } 349 350 static int 351 nmchan_setdir(void *data, int dir) 352 { 353 return 0; 354 } 355 356 static int 357 nmchan_setformat(void *data, u_int32_t format) 358 { 359 struct sc_chinfo *ch = data; 360 361 ch->fmt = format; 362 return nm_setch(ch); 363 } 364 365 static int 366 nmchan_setspeed(void *data, u_int32_t speed) 367 { 368 struct sc_chinfo *ch = data; 369 370 ch->spd = speed; 371 return nm_setch(ch)? 0 : ch->spd; 372 } 373 374 static int 375 nmchan_setblocksize(void *data, u_int32_t blocksize) 376 { 377 return blocksize; 378 } 379 380 static int 381 nmchan_trigger(void *data, int go) 382 { 383 struct sc_chinfo *ch = data; 384 struct sc_info *sc = ch->parent; 385 int ssz; 386 387 if (go == PCMTRIG_EMLDMAWR) return 0; 388 389 ssz = (ch->fmt & AFMT_16BIT)? 2 : 1; 390 if (ch->fmt & AFMT_STEREO) 391 ssz <<= 1; 392 393 if (ch->dir == PCMDIR_PLAY) { 394 if (go == PCMTRIG_START) { 395 nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4); 396 nm_wr(sc, NM_PBUFFER_END, sc->pbuf + NM_BUFFSIZE - ssz, 4); 397 nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4); 398 nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + NM_BUFFSIZE / 2, 4); 399 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN | 400 NM_PLAYBACK_ENABLE_FLAG, 1); 401 nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2); 402 } else { 403 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1); 404 nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2); 405 } 406 } else { 407 if (go == PCMTRIG_START) { 408 nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN | 409 NM_RECORD_ENABLE_FLAG, 1); 410 nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4); 411 nm_wr(sc, NM_RBUFFER_END, sc->rbuf + NM_BUFFSIZE, 4); 412 nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4); 413 nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + NM_BUFFSIZE / 2, 4); 414 } else { 415 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1); 416 } 417 } 418 return 0; 419 } 420 421 static int 422 nmchan_getptr(void *data) 423 { 424 struct sc_chinfo *ch = data; 425 struct sc_info *sc = ch->parent; 426 427 if (ch->dir == PCMDIR_PLAY) 428 return nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf; 429 else 430 return nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf; 431 } 432 433 static pcmchan_caps * 434 nmchan_getcaps(void *data) 435 { 436 return &nm_caps; 437 } 438 439 /* The interrupt handler */ 440 static void 441 nm_intr(void *p) 442 { 443 struct sc_info *sc = (struct sc_info *)p; 444 int status, x, active; 445 446 active = (sc->pch.channel->buffer.dl || sc->rch.channel->buffer.dl); 447 status = nm_rd(sc, NM_INT_REG, sc->irsz); 448 if (status == 0 && active) { 449 if (sc->badintr++ > 1000) { 450 device_printf(sc->dev, "1000 bad intrs\n"); 451 sc->badintr = 0; 452 } 453 return; 454 } 455 sc->badintr = 0; 456 457 if (status & sc->playint) { 458 status &= ~sc->playint; 459 nm_ackint(sc, sc->playint); 460 chn_intr(sc->pch.channel); 461 } 462 if (status & sc->recint) { 463 status &= ~sc->recint; 464 nm_ackint(sc, sc->recint); 465 chn_intr(sc->rch.channel); 466 } 467 if (status & sc->misc1int) { 468 status &= ~sc->misc1int; 469 nm_ackint(sc, sc->misc1int); 470 x = nm_rd(sc, 0x400, 1); 471 nm_wr(sc, 0x400, x | 2, 1); 472 device_printf(sc->dev, "misc int 1\n"); 473 } 474 if (status & sc->misc2int) { 475 status &= ~sc->misc2int; 476 nm_ackint(sc, sc->misc2int); 477 x = nm_rd(sc, 0x400, 1); 478 nm_wr(sc, 0x400, x & ~2, 1); 479 device_printf(sc->dev, "misc int 2\n"); 480 } 481 if (status) { 482 status &= ~sc->misc2int; 483 nm_ackint(sc, sc->misc2int); 484 device_printf(sc->dev, "unknown int\n"); 485 } 486 } 487 488 /* -------------------------------------------------------------------- */ 489 490 /* 491 * Probe and attach the card 492 */ 493 494 static int 495 nm_init(struct sc_info *sc) 496 { 497 u_int32_t ofs, i; 498 499 if (sc->type == NM256AV_PCI_ID) { 500 sc->ac97_base = NM_MIXER_OFFSET; 501 sc->ac97_status = NM_MIXER_STATUS_OFFSET; 502 sc->ac97_busy = NM_MIXER_READY_MASK; 503 504 sc->buftop = 2560 * 1024; 505 506 sc->irsz = 2; 507 sc->playint = NM_PLAYBACK_INT; 508 sc->recint = NM_RECORD_INT; 509 sc->misc1int = NM_MISC_INT_1; 510 sc->misc2int = NM_MISC_INT_2; 511 } else if (sc->type == NM256ZX_PCI_ID) { 512 sc->ac97_base = NM_MIXER_OFFSET; 513 sc->ac97_status = NM2_MIXER_STATUS_OFFSET; 514 sc->ac97_busy = NM2_MIXER_READY_MASK; 515 516 sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024; 517 518 sc->irsz = 4; 519 sc->playint = NM2_PLAYBACK_INT; 520 sc->recint = NM2_RECORD_INT; 521 sc->misc1int = NM2_MISC_INT_1; 522 sc->misc2int = NM2_MISC_INT_2; 523 } else return -1; 524 sc->badintr = 0; 525 ofs = sc->buftop - 0x0400; 526 sc->buftop -= 0x1400; 527 528 if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) { 529 i = nm_rdbuf(sc, ofs + 4, 4); 530 if (i != 0 && i != 0xffffffff) 531 sc->buftop = i; 532 } 533 534 sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT; 535 sc->rbuf = sc->cbuf - NM_BUFFSIZE; 536 sc->pbuf = sc->rbuf - NM_BUFFSIZE; 537 sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4); 538 539 nm_wr(sc, 0, 0x11, 1); 540 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1); 541 nm_wr(sc, 0x214, 0, 2); 542 543 return 0; 544 } 545 546 static int 547 nm_pci_probe(device_t dev) 548 { 549 char *s = NULL; 550 u_int32_t subdev, i; 551 552 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); 553 switch (pci_get_devid(dev)) { 554 case NM256AV_PCI_ID: 555 i = 0; 556 while ((i < NUM_BADCARDS) && (badcards[i] != subdev)) 557 i++; 558 if (i == NUM_BADCARDS) 559 s = "NeoMagic 256AV"; 560 DEB(else) 561 DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attaching\n")); 562 break; 563 564 case NM256ZX_PCI_ID: 565 s = "NeoMagic 256ZX"; 566 break; 567 } 568 569 if (s) device_set_desc(dev, s); 570 return s? 0 : ENXIO; 571 } 572 573 static int 574 nm_pci_attach(device_t dev) 575 { 576 snddev_info *d; 577 u_int32_t data; 578 struct sc_info *sc; 579 struct ac97_info *codec; 580 char status[SND_STATUSLEN]; 581 582 d = device_get_softc(dev); 583 if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { 584 device_printf(dev, "cannot allocate softc\n"); 585 return ENXIO; 586 } 587 588 bzero(sc, sizeof(*sc)); 589 sc->dev = dev; 590 sc->type = pci_get_devid(dev); 591 592 data = pci_read_config(dev, PCIR_COMMAND, 2); 593 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 594 pci_write_config(dev, PCIR_COMMAND, data, 2); 595 data = pci_read_config(dev, PCIR_COMMAND, 2); 596 597 sc->bufid = PCIR_MAPS; 598 sc->buf = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bufid, 599 0, ~0, 1, RF_ACTIVE); 600 sc->regid = PCIR_MAPS + 4; 601 sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid, 602 0, ~0, 1, RF_ACTIVE); 603 604 if (!sc->buf || !sc->reg) { 605 device_printf(dev, "unable to map register space\n"); 606 goto bad; 607 } 608 609 if (nm_init(sc) == -1) { 610 device_printf(dev, "unable to initialize the card\n"); 611 goto bad; 612 } 613 614 codec = ac97_create(dev, sc, nm_rdcd, nm_wrcd); 615 if (codec == NULL) goto bad; 616 mixer_init(d, &ac97_mixer, codec); 617 618 sc->irqid = 0; 619 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, 620 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 621 if (!sc->irq || 622 bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, nm_intr, sc, &sc->ih)) { 623 device_printf(dev, "unable to map interrupt\n"); 624 goto bad; 625 } 626 627 snprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld", 628 rman_get_start(sc->buf), rman_get_start(sc->reg), 629 rman_get_start(sc->irq)); 630 631 if (pcm_register(dev, sc, 1, 1)) goto bad; 632 pcm_addchan(dev, PCMDIR_REC, &nm_chantemplate, sc); 633 pcm_addchan(dev, PCMDIR_PLAY, &nm_chantemplate, sc); 634 pcm_setstatus(dev, status); 635 636 return 0; 637 638 bad: 639 if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf); 640 if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); 641 if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); 642 if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 643 free(sc, M_DEVBUF); 644 return ENXIO; 645 } 646 647 static device_method_t nm_methods[] = { 648 /* Device interface */ 649 DEVMETHOD(device_probe, nm_pci_probe), 650 DEVMETHOD(device_attach, nm_pci_attach), 651 652 { 0, 0 } 653 }; 654 655 static driver_t nm_driver = { 656 "pcm", 657 nm_methods, 658 sizeof(snddev_info), 659 }; 660 661 static devclass_t pcm_devclass; 662 663 DRIVER_MODULE(nm, pci, nm_driver, pcm_devclass, 0, 0); 664