emu10k1.c revision 60958
1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/dev/sound/pci/emu10k1.c 60958 2000-05-26 21:15:47Z cg $ 27 */ 28 29#include "pci.h" 30#include "pcm.h" 31 32#include <dev/sound/pcm/sound.h> 33#include <dev/sound/pcm/ac97.h> 34#include <gnu/dev/sound/pci/emu10k1.h> 35 36#include <pci/pcireg.h> 37#include <pci/pcivar.h> 38#include <sys/queue.h> 39 40/* -------------------------------------------------------------------- */ 41 42#define EMU10K1_PCI_ID 0x00021102 43#define EMU_BUFFSIZE 4096 44#undef EMUDEBUG 45 46struct emu_memblk { 47 SLIST_ENTRY(emu_memblk) link; 48 void *buf; 49 u_int32_t pte_start, pte_size; 50}; 51 52struct emu_mem { 53 u_int8_t bmap[MAXPAGES / 8]; 54 u_int32_t *ptb_pages; 55 void *silent_page; 56 SLIST_HEAD(, emu_memblk) blocks; 57}; 58 59struct emu_voice { 60 int vnum; 61 int b16:1, stereo:1, busy:1, running:1, ismaster:1, istracker:1; 62 int speed; 63 int start, end, vol; 64 u_int32_t buf; 65 struct emu_voice *slave, *tracker; 66 pcm_channel *channel; 67}; 68 69struct sc_info; 70 71/* channel registers */ 72struct sc_chinfo { 73 int spd, dir, fmt; 74 struct emu_voice *master, *slave, *tracker; 75 snd_dbuf *buffer; 76 pcm_channel *channel; 77 struct sc_info *parent; 78}; 79 80/* device private data */ 81struct sc_info { 82 device_t dev; 83 u_int32_t type, rev; 84 u_int32_t tos_link:1, APS:1; 85 86 bus_space_tag_t st; 87 bus_space_handle_t sh; 88 bus_dma_tag_t parent_dmat; 89 90 struct resource *reg, *irq; 91 int regtype, regid, irqid; 92 void *ih; 93 94 struct emu_mem mem; 95 struct emu_voice voice[64]; 96 struct sc_chinfo pch, rch; 97}; 98 99/* -------------------------------------------------------------------- */ 100 101/* 102 * prototypes 103 */ 104 105/* channel interface */ 106static void *emuchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 107static int emuchan_setdir(void *data, int dir); 108static int emuchan_setformat(void *data, u_int32_t format); 109static int emuchan_setspeed(void *data, u_int32_t speed); 110static int emuchan_setblocksize(void *data, u_int32_t blocksize); 111static int emuchan_trigger(void *data, int go); 112static int emuchan_getptr(void *data); 113static pcmchan_caps *emuchan_getcaps(void *data); 114 115/* talk to the codec - called from ac97.c */ 116static u_int32_t emu_rdcd(void *, int); 117static void emu_wrcd(void *, int, u_int32_t); 118 119/* stuff */ 120static int emu_init(struct sc_info *); 121static void emu_intr(void *); 122static void *emu_malloc(struct sc_info *sc, u_int32_t sz); 123static void *emu_memalloc(struct sc_info *sc, u_int32_t sz); 124#ifdef notyet 125static int emu_memfree(struct sc_info *sc, void *buf); 126#endif 127static int emu_memstart(struct sc_info *sc, void *buf); 128#ifdef EMUDEBUG 129static void emu_vdump(struct sc_info *sc, struct emu_voice *v); 130#endif 131 132/* talk to the card */ 133static u_int32_t emu_rd(struct sc_info *, int, int); 134static void emu_wr(struct sc_info *, int, u_int32_t, int); 135 136/* -------------------------------------------------------------------- */ 137 138static pcmchan_caps emu_reccaps = { 139 4000, 48000, 140 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, 141 AFMT_STEREO | AFMT_S16_LE 142}; 143 144static pcmchan_caps emu_playcaps = { 145 4000, 48000, 146 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, 147 AFMT_STEREO | AFMT_S16_LE 148}; 149 150static pcm_channel emu_chantemplate = { 151 emuchan_init, 152 emuchan_setdir, 153 emuchan_setformat, 154 emuchan_setspeed, 155 emuchan_setblocksize, 156 emuchan_trigger, 157 emuchan_getptr, 158 emuchan_getcaps, 159}; 160 161/* -------------------------------------------------------------------- */ 162/* Hardware */ 163static u_int32_t 164emu_rd(struct sc_info *sc, int regno, int size) 165{ 166 switch (size) { 167 case 1: 168 return bus_space_read_1(sc->st, sc->sh, regno); 169 case 2: 170 return bus_space_read_2(sc->st, sc->sh, regno); 171 case 4: 172 return bus_space_read_4(sc->st, sc->sh, regno); 173 default: 174 return 0xffffffff; 175 } 176} 177 178static void 179emu_wr(struct sc_info *sc, int regno, u_int32_t data, int size) 180{ 181 switch (size) { 182 case 1: 183 bus_space_write_1(sc->st, sc->sh, regno, data); 184 break; 185 case 2: 186 bus_space_write_2(sc->st, sc->sh, regno, data); 187 break; 188 case 4: 189 bus_space_write_4(sc->st, sc->sh, regno, data); 190 break; 191 } 192} 193 194static u_int32_t 195emu_rdptr(struct sc_info *sc, int chn, int reg) 196{ 197 u_int32_t ptr, val, mask, size, offset; 198 199 ptr = ((reg << 16) & PTR_ADDRESS_MASK) | (chn & PTR_CHANNELNUM_MASK); 200 emu_wr(sc, PTR, ptr, 4); 201 val = emu_rd(sc, DATA, 4); 202 if (reg & 0xff000000) { 203 size = (reg >> 24) & 0x3f; 204 offset = (reg >> 16) & 0x1f; 205 mask = ((1 << size) - 1) << offset; 206 val &= mask; 207 val >>= offset; 208 } 209 return val; 210} 211 212static void 213emu_wrptr(struct sc_info *sc, int chn, int reg, u_int32_t data) 214{ 215 u_int32_t ptr, mask, size, offset; 216 217 ptr = ((reg << 16) & PTR_ADDRESS_MASK) | (chn & PTR_CHANNELNUM_MASK); 218 emu_wr(sc, PTR, ptr, 4); 219 if (reg & 0xff000000) { 220 size = (reg >> 24) & 0x3f; 221 offset = (reg >> 16) & 0x1f; 222 mask = ((1 << size) - 1) << offset; 223 data <<= offset; 224 data &= mask; 225 data |= emu_rd(sc, DATA, 4) & ~mask; 226 } 227 emu_wr(sc, DATA, data, 4); 228} 229 230static void 231emu_wrefx(struct sc_info *sc, unsigned int pc, unsigned int data) 232{ 233 emu_wrptr(sc, 0, MICROCODEBASE + pc, data); 234} 235 236/* playback channel interrupts */ 237static u_int32_t 238emu_testint(struct sc_info *sc, char channel) 239{ 240 int reg = (channel & 0x20)? CLIPH : CLIPL; 241 channel &= 0x1f; 242 reg |= 1 << 24; 243 reg |= channel << 16; 244 return emu_rdptr(sc, 0, reg); 245} 246 247static void 248emu_clrint(struct sc_info *sc, char channel) 249{ 250 int reg = (channel & 0x20)? CLIPH : CLIPL; 251 channel &= 0x1f; 252 reg |= 1 << 24; 253 reg |= channel << 16; 254 emu_wrptr(sc, 0, reg, 1); 255} 256 257static void 258emu_enaint(struct sc_info *sc, char channel, int enable) 259{ 260 int reg = (channel & 0x20)? CLIEH : CLIEL; 261 channel &= 0x1f; 262 reg |= 1 << 24; 263 reg |= channel << 16; 264 emu_wrptr(sc, 0, reg, enable); 265} 266 267static void 268emu_enastop(struct sc_info *sc, char channel, int enable) 269{ 270 int reg = (channel & 0x20)? SOLEH : SOLEL; 271 channel &= 0x1f; 272 reg |= 1 << 24; 273 reg |= channel << 16; 274 emu_wrptr(sc, 0, reg, enable); 275} 276 277/* ac97 codec */ 278static u_int32_t 279emu_rdcd(void *devinfo, int regno) 280{ 281 struct sc_info *sc = (struct sc_info *)devinfo; 282 283 emu_wr(sc, AC97ADDRESS, regno, 1); 284 return emu_rd(sc, AC97DATA, 2); 285} 286 287static void 288emu_wrcd(void *devinfo, int regno, u_int32_t data) 289{ 290 struct sc_info *sc = (struct sc_info *)devinfo; 291 292 emu_wr(sc, AC97ADDRESS, regno, 1); 293 emu_wr(sc, AC97DATA, data, 2); 294} 295 296static u_int32_t 297emu_rate_to_pitch(u_int32_t rate) 298{ 299 static u_int32_t logMagTable[128] = { 300 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2, 301 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5, 302 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081, 303 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191, 304 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, 305 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, 306 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e, 307 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26, 308 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d, 309 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885, 310 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, 311 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, 312 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, 313 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3, 314 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83, 315 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df 316 }; 317 static char logSlopeTable[128] = { 318 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58, 319 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53, 320 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f, 321 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b, 322 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47, 323 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44, 324 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41, 325 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e, 326 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, 327 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 328 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37, 329 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35, 330 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34, 331 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32, 332 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30, 333 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f 334 }; 335 int i; 336 337 if (rate == 0) 338 return 0; /* Bail out if no leading "1" */ 339 rate *= 11185; /* Scale 48000 to 0x20002380 */ 340 for (i = 31; i > 0; i--) { 341 if (rate & 0x80000000) { /* Detect leading "1" */ 342 return (((u_int32_t) (i - 15) << 20) + 343 logMagTable[0x7f & (rate >> 24)] + 344 (0x7f & (rate >> 17)) * 345 logSlopeTable[0x7f & (rate >> 24)]); 346 } 347 rate <<= 1; 348 } 349 350 return 0; /* Should never reach this point */ 351} 352 353static struct emu_voice * 354emu_valloc(struct sc_info *sc) 355{ 356 struct emu_voice *v; 357 int i; 358 359 v = NULL; 360 for (i = 0; i < 64 && sc->voice[i].busy; i++); 361 if (i < 64) { 362 v = &sc->voice[i]; 363 v->busy = 1; 364 } 365 return v; 366} 367 368static int 369emu_vinit(struct sc_info *sc, struct emu_voice *m, struct emu_voice *s, struct emu_voice *t, 370 u_int32_t sz, pcm_channel *c) 371{ 372 void *buf; 373 374 buf = emu_memalloc(sc, sz); 375 if (buf == NULL) 376 return -1; 377 m->start = emu_memstart(sc, buf) * EMUPAGESIZE; 378 m->end = m->start + sz; 379 m->channel = NULL; 380 m->speed = 0; 381 m->b16 = 0; 382 m->stereo = 0; 383 m->running = 0; 384 m->ismaster = 1; 385 m->istracker = 0; 386 m->vol = 0xff; 387 m->buf = vtophys(buf); 388 m->slave = s; 389 m->tracker = t; 390 if (s != NULL) { 391 s->start = m->start; 392 s->end = m->end; 393 s->channel = NULL; 394 s->speed = 0; 395 s->b16 = 0; 396 s->stereo = 0; 397 s->running = 0; 398 s->ismaster = 0; 399 s->istracker = 0; 400 s->vol = m->vol; 401 s->buf = m->buf; 402 s->slave = NULL; 403 s->tracker = NULL; 404 } 405 if (t != NULL) { 406 t->start = m->start; 407 t->end = t->start + sz / 2; 408 t->channel = c; 409 t->speed = 0; 410 t->b16 = 0; 411 t->stereo = 0; 412 t->running = 0; 413 t->ismaster = 0; 414 t->istracker = 1; 415 t->vol = 0; 416 t->buf = m->buf; 417 t->slave = NULL; 418 t->tracker = NULL; 419 } 420 if (c != NULL) { 421 c->buffer.buf = buf; 422 c->buffer.bufsize = sz; 423 } 424 return 0; 425} 426 427static void 428emu_vsetup(struct sc_chinfo *ch) 429{ 430 struct emu_voice *v = ch->master; 431 432 if (ch->fmt) { 433 v->b16 = (ch->fmt & AFMT_16BIT)? 1 : 0; 434 v->stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; 435 if (v->slave != NULL) { 436 v->slave->b16 = v->b16; 437 v->slave->stereo = v->stereo; 438 } 439 if (v->tracker != NULL) { 440 v->tracker->b16 = v->b16; 441 v->tracker->stereo = v->stereo; 442 } 443 } 444 if (ch->spd) { 445 v->speed = ch->spd; 446 if (v->slave != NULL) 447 v->slave->speed = v->speed; 448 if (v->tracker != NULL) 449 v->tracker->speed = v->speed; 450 } 451} 452 453static void 454emu_vwrite(struct sc_info *sc, struct emu_voice *v) 455{ 456 int s, l, r, p, x; 457 u_int32_t sa, ea, start = 0, val = 0, v2 = 0, sample, silent_page, i; 458 459 s = (v->stereo? 1 : 0) + (v->b16? 1 : 0); 460 sa = v->start >> s; 461 ea = v->end >> s; 462 l = r = x = v->vol; 463 if (v->stereo) { 464 l = v->ismaster? l : 0; 465 r = v->ismaster? 0 : r; 466 } 467 p = emu_rate_to_pitch(v->speed) >> 8; 468 sample = v->b16? 0 : 0x80808080; 469 470 emu_wrptr(sc, v->vnum, DCYSUSV, ENV_OFF); 471 emu_wrptr(sc, v->vnum, VTFT, VTFT_FILTERTARGET_MASK); 472 emu_wrptr(sc, v->vnum, CVCF, CVCF_CURRENTFILTER_MASK); 473 emu_wrptr(sc, v->vnum, FXRT, 0xd01c0000); 474 475 emu_wrptr(sc, v->vnum, PTRX, (x << 8) | r); 476 if (v->ismaster) { 477 val = 0x20; 478 if (v->stereo) { 479 val <<= 1; 480 emu_wrptr(sc, v->vnum, CPF, CPF_STEREO_MASK); 481 emu_wrptr(sc, v->slave->vnum, CPF, CPF_STEREO_MASK); 482 } else 483 emu_wrptr(sc, v->vnum, CPF, 0); 484 sample = 0x80808080; 485 if (!v->b16) 486 val <<= 1; 487 val -= 4; 488 /* 489 * mono 8bit: val = 0x3c 490 * stereo 8bit: val = 0x7c 491 * mono 16bit: val = 0x1c 492 * stereo 16bit: val = 0x3c 493 */ 494 if (v->stereo) { 495 v2 = 0x3c << 16; 496 emu_wrptr(sc, v->vnum, CCR, v2); 497 emu_wrptr(sc, v->slave->vnum, CCR, val << 16); 498 emu_wrptr(sc, v->slave->vnum, CDE, sample); 499 emu_wrptr(sc, v->slave->vnum, CDF, sample); 500 start = sa + val / 2; 501 } else { 502 v2 = 0x1c << 16; 503 emu_wrptr(sc, v->vnum, CCR, v2); 504 emu_wrptr(sc, v->vnum, CDE, sample); 505 emu_wrptr(sc, v->vnum, CDF, sample); 506 start = sa + val; 507 } 508 val <<= 25; 509 val |= v2; 510 /* 511 * mono 8bit: val = 0x781c0000 512 * stereo 8bit: val = 0xf83c0000 513 * mono 16bit: val = 0x381c0000 514 * stereo 16bit: val = 0x783c0000 515 */ 516 start |= CCCA_INTERPROM_0; 517 } 518 emu_wrptr(sc, v->vnum, DSL, ea); 519 emu_wrptr(sc, v->vnum, PSST, sa | (l << 24)); 520 emu_wrptr(sc, v->vnum, CCCA, start | (v->b16? 0 : CCCA_8BITSELECT)); 521 522 emu_wrptr(sc, v->vnum, Z1, 0); 523 emu_wrptr(sc, v->vnum, Z2, 0); 524 525 silent_page = ((u_int32_t)v->buf << 1) | (v->start / EMUPAGESIZE); 526 emu_wrptr(sc, v->vnum, MAPA, silent_page); 527 emu_wrptr(sc, v->vnum, MAPB, silent_page); 528 529 if (v->ismaster) 530 emu_wrptr(sc, v->vnum, CCR, val); 531 532 for (i = CD0; i < CDF; i++) 533 emu_wrptr(sc, v->vnum, i, sample); 534 535 emu_wrptr(sc, v->vnum, ATKHLDV, ATKHLDV_HOLDTIME_MASK | ATKHLDV_ATTACKTIME_MASK); 536 emu_wrptr(sc, v->vnum, LFOVAL1, 0x8000); 537 emu_wrptr(sc, v->vnum, ATKHLDM, 0); 538 emu_wrptr(sc, v->vnum, DCYSUSM, DCYSUSM_DECAYTIME_MASK); 539 emu_wrptr(sc, v->vnum, LFOVAL2, 0x8000); 540 emu_wrptr(sc, v->vnum, IP, p); 541 emu_wrptr(sc, v->vnum, PEFE, 0x7f); 542 emu_wrptr(sc, v->vnum, FMMOD, 0); 543 emu_wrptr(sc, v->vnum, TREMFRQ, 0); 544 emu_wrptr(sc, v->vnum, FM2FRQ2, 0); 545 emu_wrptr(sc, v->vnum, ENVVAL, 0xbfff); 546 emu_wrptr(sc, v->vnum, ENVVOL, 0xbfff); 547 emu_wrptr(sc, v->vnum, IFATN, IFATN_FILTERCUTOFF_MASK); 548 549 if (v->slave != NULL) 550 emu_vwrite(sc, v->slave); 551 if (v->tracker != NULL) 552 emu_vwrite(sc, v->tracker); 553} 554 555#define IP_TO_CP(ip) ((ip == 0) ? 0 : (((0x00001000uL | (ip & 0x00000FFFL)) << (((ip >> 12) & 0x000FL) + 4)) & 0xFFFF0000uL)) 556static void 557emu_vtrigger(struct sc_info *sc, struct emu_voice *v, int go) 558{ 559 u_int32_t pitch_target; 560 if (go) { 561 pitch_target = IP_TO_CP((emu_rate_to_pitch(v->speed) >> 8)) >> 16; 562 emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, pitch_target); 563 emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, pitch_target); 564 emu_wrptr(sc, v->vnum, VTFT, 0xffff); 565 emu_wrptr(sc, v->vnum, CVCF, 0xffff); 566 emu_enastop(sc, v->vnum, 0); 567 emu_enaint(sc, v->vnum, v->istracker); 568 emu_wrptr(sc, v->vnum, DCYSUSV, ENV_ON | 0x00007f7f); 569 } else { 570 emu_wrptr(sc, v->vnum, IFATN, 0xffff); 571 emu_wrptr(sc, v->vnum, IP, 0); 572 emu_wrptr(sc, v->vnum, VTFT, 0xffff); 573 emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, 0); 574 emu_enaint(sc, v->vnum, 0); 575 } 576 if (v->slave != NULL) 577 emu_vtrigger(sc, v->slave, go); 578 if (v->tracker != NULL) 579 emu_vtrigger(sc, v->tracker, go); 580} 581 582static int 583emu_vpos(struct sc_info *sc, struct emu_voice *v) 584{ 585 int s; 586 s = (v->b16? 1 : 0) + (v->stereo? 1 : 0); 587 return ((emu_rdptr(sc, v->vnum, CCCA_CURRADDR) >> s) - v->start); 588} 589 590#ifdef EMUDEBUG 591static void 592emu_vdump(struct sc_info *sc, struct emu_voice *v) 593{ 594 char *regname[] = { "cpf", "ptrx", "cvcf", "vtft", "z2", "z1", "psst", "dsl", 595 "ccca", "ccr", "clp", "fxrt", "mapa", "mapb", NULL, NULL, 596 "envvol", "atkhldv", "dcysusv", "lfoval1", 597 "envval", "atkhldm", "dcysusm", "lfoval2", 598 "ip", "ifatn", "pefe", "fmmod", "tremfrq", "fmfrq2", 599 "tempenv" }; 600 int i, x; 601 602 printf("voice number %d\n", v->vnum); 603 for (i = 0, x = 0; i <= 0x1e; i++) { 604 if (regname[i] == NULL) 605 continue; 606 printf("%s\t[%08x]", regname[i], emu_rdptr(sc, v->vnum, i)); 607 printf("%s", (x == 2)? "\n" : "\t"); 608 x++; 609 if (x > 2) 610 x = 0; 611 } 612 printf("\n\n"); 613} 614#endif 615 616/* channel interface */ 617void * 618emuchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 619{ 620 struct sc_info *sc = devinfo; 621 struct sc_chinfo *ch; 622 623 ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; 624 ch->buffer = b; 625 ch->parent = sc; 626 ch->channel = c; 627 ch->master = emu_valloc(sc); 628 ch->slave = emu_valloc(sc); 629 ch->tracker = emu_valloc(sc); 630 if (emu_vinit(sc, ch->master, ch->slave, ch->tracker, EMU_BUFFSIZE, ch->channel)) 631 return NULL; 632 else 633 return ch; 634} 635 636static int 637emuchan_setdir(void *data, int dir) 638{ 639 struct sc_chinfo *ch = data; 640 641 ch->dir = dir; 642 return 0; 643} 644 645static int 646emuchan_setformat(void *data, u_int32_t format) 647{ 648 struct sc_chinfo *ch = data; 649 650 ch->fmt = format; 651 return 0; 652} 653 654static int 655emuchan_setspeed(void *data, u_int32_t speed) 656{ 657 struct sc_chinfo *ch = data; 658 659 ch->spd = speed; 660 return ch->spd; 661} 662 663static int 664emuchan_setblocksize(void *data, u_int32_t blocksize) 665{ 666 return blocksize; 667} 668 669static int 670emuchan_trigger(void *data, int go) 671{ 672 struct sc_chinfo *ch = data; 673 struct sc_info *sc = ch->parent; 674 675 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 676 return 0; 677 678 if (go == PCMTRIG_START) { 679 emu_vsetup(ch); 680 emu_vwrite(sc, ch->master); 681#ifdef EMUDEBUG 682 printf("start [%d bit, %s, %d hz]\n", 683 ch->master->b16? 16 : 8, 684 ch->master->stereo? "stereo" : "mono", 685 ch->master->speed); 686 emu_vdump(sc, ch->master); 687 emu_vdump(sc, ch->slave); 688#endif 689 } 690 emu_vtrigger(sc, ch->master, (go == PCMTRIG_START)? 1 : 0); 691 return 0; 692} 693 694static int 695emuchan_getptr(void *data) 696{ 697 struct sc_chinfo *ch = data; 698 struct sc_info *sc = ch->parent; 699 700 return emu_vpos(sc, ch->master); 701} 702 703static pcmchan_caps * 704emuchan_getcaps(void *data) 705{ 706 struct sc_chinfo *ch = data; 707 708 return (ch->dir == PCMDIR_PLAY)? &emu_playcaps : &emu_reccaps; 709} 710 711/* The interrupt handler */ 712static void 713emu_intr(void *p) 714{ 715 struct sc_info *sc = (struct sc_info *)p; 716 u_int32_t stat, i; 717 718 do { 719 stat = emu_rd(sc, IPR, 4); 720 721 /* process irq */ 722 for (i = 0; i < 64; i++) { 723 if (emu_testint(sc, i)) { 724 if (sc->voice[i].channel) 725 chn_intr(sc->voice[i].channel); 726 else 727 device_printf(sc->dev, "bad irq voice %d\n", i); 728 emu_clrint(sc, i); 729 } 730 } 731 732 emu_wr(sc, IPR, stat, 4); 733 } while (stat); 734} 735 736/* -------------------------------------------------------------------- */ 737 738static void * 739emu_malloc(struct sc_info *sc, u_int32_t sz) 740{ 741 void *buf; 742 bus_dmamap_t map; 743 744 if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map)) 745 return NULL; 746 return buf; 747} 748 749static void 750emu_free(struct sc_info *sc, void *buf) 751{ 752 bus_dmamem_free(sc->parent_dmat, buf, NULL); 753} 754 755static void * 756emu_memalloc(struct sc_info *sc, u_int32_t sz) 757{ 758 u_int32_t blksz, start, idx, ofs, tmp, found; 759 struct emu_mem *mem = &sc->mem; 760 struct emu_memblk *blk; 761 void *buf; 762 763 blksz = sz / EMUPAGESIZE; 764 if (sz > (blksz * EMUPAGESIZE)) 765 blksz++; 766 /* find a free block in the bitmap */ 767 found = 0; 768 start = 0; 769 while (!found && start + blksz < MAXPAGES) { 770 found = 1; 771 for (idx = start; idx < start + blksz; idx++) 772 if (mem->bmap[idx >> 3] & (1 << (idx & 7))) 773 found = 0; 774 if (!found) 775 start++; 776 } 777 if (!found) 778 return NULL; 779 blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT); 780 if (blk == NULL) 781 return NULL; 782 buf = emu_malloc(sc, sz); 783 if (buf == NULL) { 784 free(blk, M_DEVBUF); 785 return NULL; 786 } 787 blk->buf = buf; 788 blk->pte_start = start; 789 blk->pte_size = blksz; 790 /* printf("buf %p, pte_start %d, pte_size %d\n", blk->buf, blk->pte_start, blk->pte_size); */ 791 ofs = 0; 792 for (idx = start; idx < start + blksz; idx++) { 793 mem->bmap[idx >> 3] |= 1 << (idx & 7); 794 tmp = (u_int32_t)vtophys((u_int8_t *)buf + ofs); 795 /* printf("pte[%d] -> %x phys, %x virt\n", idx, tmp, ((u_int32_t)buf) + ofs); */ 796 mem->ptb_pages[idx] = (tmp << 1) | idx; 797 ofs += EMUPAGESIZE; 798 } 799 SLIST_INSERT_HEAD(&mem->blocks, blk, link); 800 return buf; 801} 802 803#ifdef notyet 804static int 805emu_memfree(struct sc_info *sc, void *buf) 806{ 807 u_int32_t idx, tmp; 808 struct emu_mem *mem = &sc->mem; 809 struct emu_memblk *blk, *i; 810 811 blk = NULL; 812 SLIST_FOREACH(i, &mem->blocks, link) { 813 if (i->buf == buf) 814 blk = i; 815 } 816 if (blk == NULL) 817 return EINVAL; 818 SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link); 819 emu_free(sc, buf); 820 tmp = (u_int32_t)vtophys(sc->mem.silent_page) << 1; 821 for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) { 822 mem->bmap[idx >> 3] &= ~(1 << (idx & 7)); 823 mem->ptb_pages[idx] = tmp | idx; 824 } 825 free(blk, M_DEVBUF); 826 return 0; 827} 828#endif 829 830static int 831emu_memstart(struct sc_info *sc, void *buf) 832{ 833 struct emu_mem *mem = &sc->mem; 834 struct emu_memblk *blk, *i; 835 836 blk = NULL; 837 SLIST_FOREACH(i, &mem->blocks, link) { 838 if (i->buf == buf) 839 blk = i; 840 } 841 if (blk == NULL) 842 return -EINVAL; 843 return blk->pte_start; 844} 845 846static void 847emu_addefxop(struct sc_info *sc, int op, int z, int w, int x, int y, u_int32_t *pc) 848{ 849 emu_wrefx(sc, (*pc) * 2, (x << 10) | y); 850 emu_wrefx(sc, (*pc) * 2 + 1, (op << 20) | (z << 10) | w); 851 (*pc)++; 852} 853 854static void 855emu_initefx(struct sc_info *sc) 856{ 857 int i; 858 u_int32_t pc = 16; 859 860 for (i = 0; i < 512; i++) { 861 emu_wrefx(sc, i * 2, 0x10040); 862 emu_wrefx(sc, i * 2 + 1, 0x610040); 863 } 864 865 for (i = 0; i < 256; i++) 866 emu_wrptr(sc, 0, FXGPREGBASE + i, 0); 867 868 /* FX-8010 DSP Registers: 869 FX Bus 870 0x000-0x00f : 16 registers 871 Input 872 0x010/0x011 : AC97 Codec (l/r) 873 0x012/0x013 : ADC, S/PDIF (l/r) 874 0x014/0x015 : Mic(left), Zoom (l/r) 875 0x016/0x017 : APS S/PDIF?? (l/r) 876 Output 877 0x020/0x021 : AC97 Output (l/r) 878 0x022/0x023 : TOS link out (l/r) 879 0x024/0x025 : ??? (l/r) 880 0x026/0x027 : LiveDrive Headphone (l/r) 881 0x028/0x029 : Rear Channel (l/r) 882 0x02a/0x02b : ADC Recording Buffer (l/r) 883 Constants 884 0x040 - 0x044 = 0 - 4 885 0x045 = 0x8, 0x046 = 0x10, 0x047 = 0x20 886 0x048 = 0x100, 0x049 = 0x10000, 0x04a = 0x80000 887 0x04b = 0x10000000, 0x04c = 0x20000000, 0x04d = 0x40000000 888 0x04e = 0x80000000, 0x04f = 0x7fffffff 889 Temporary Values 890 0x056 : Accumulator 891 0x058 : Noise source? 892 0x059 : Noise source? 893 General Purpose Registers 894 0x100 - 0x1ff 895 Tank Memory Data Registers 896 0x200 - 0x2ff 897 Tank Memory Address Registers 898 0x300 - 0x3ff 899 */ 900 901 /* Operators: 902 0 : z := w + (x * y >> 31) 903 4 : z := w + x * y 904 6 : z := w + x + y 905 */ 906 907 /* Routing - this will be configurable in later version */ 908 909 /* GPR[0/1] = FX * 4 + SPDIF-in */ 910 emu_addefxop(sc, 4, 0x100, 0x12, 0, 0x44, &pc); 911 emu_addefxop(sc, 4, 0x101, 0x13, 1, 0x44, &pc); 912 /* GPR[0/1] += APS-input */ 913 emu_addefxop(sc, 6, 0x100, 0x100, 0x40, sc->APS ? 0x16 : 0x40, &pc); 914 emu_addefxop(sc, 6, 0x101, 0x101, 0x40, sc->APS ? 0x17 : 0x40, &pc); 915 /* FrontOut (AC97) = GPR[0/1] */ 916 emu_addefxop(sc, 6, 0x20, 0x40, 0x40, 0x100, &pc); 917 emu_addefxop(sc, 6, 0x21, 0x40, 0x41, 0x101, &pc); 918 /* RearOut = (GPR[0/1] * RearVolume) >> 31 */ 919 /* RearVolume = GRP[0x10/0x11] */ 920 emu_addefxop(sc, 0, 0x28, 0x40, 0x110, 0x100, &pc); 921 emu_addefxop(sc, 0, 0x29, 0x40, 0x111, 0x101, &pc); 922 /* TOS out = GPR[0/1] */ 923 emu_addefxop(sc, 6, 0x22, 0x40, 0x40, 0x100, &pc); 924 emu_addefxop(sc, 6, 0x23, 0x40, 0x40, 0x101, &pc); 925 /* Mute Out2 */ 926 emu_addefxop(sc, 6, 0x24, 0x40, 0x40, 0x40, &pc); 927 emu_addefxop(sc, 6, 0x25, 0x40, 0x40, 0x40, &pc); 928 /* Mute Out3 */ 929 emu_addefxop(sc, 6, 0x26, 0x40, 0x40, 0x40, &pc); 930 emu_addefxop(sc, 6, 0x27, 0x40, 0x40, 0x40, &pc); 931 /* Input0 (AC97) -> Record */ 932 emu_addefxop(sc, 6, 0x2a, 0x40, 0x40, 0x10, &pc); 933 emu_addefxop(sc, 6, 0x2b, 0x40, 0x40, 0x11, &pc); 934 935 emu_wrptr(sc, 0, DBG, 0); 936} 937 938/* Probe and attach the card */ 939static int 940emu_init(struct sc_info *sc) 941{ 942 u_int32_t spcs, ch, tmp, i; 943 944 /* disable audio and lock cache */ 945 emu_wr(sc, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE | HCFG_MUTEBUTTONENABLE, 4); 946 947 /* reset recording buffers */ 948 emu_wrptr(sc, 0, MICBS, 0); 949 emu_wrptr(sc, 0, MICBA, 0); 950 emu_wrptr(sc, 0, FXBS, 0); 951 emu_wrptr(sc, 0, FXBA, 0); 952 emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE); 953 emu_wrptr(sc, 0, ADCBA, 0); 954 955 /* disable channel interrupt */ 956 emu_wr(sc, INTE, DISABLE, 4); 957 emu_wrptr(sc, 0, CLIEL, 0); 958 emu_wrptr(sc, 0, CLIEH, 0); 959 emu_wrptr(sc, 0, SOLEL, 0); 960 emu_wrptr(sc, 0, SOLEH, 0); 961 962 /* init envelope engine */ 963 for (ch = 0; ch < NUM_G; ch++) { 964 emu_wrptr(sc, ch, DCYSUSV, ENV_OFF); 965 emu_wrptr(sc, ch, IP, 0); 966 emu_wrptr(sc, ch, VTFT, 0xffff); 967 emu_wrptr(sc, ch, CVCF, 0xffff); 968 emu_wrptr(sc, ch, PTRX, 0); 969 emu_wrptr(sc, ch, CPF, 0); 970 emu_wrptr(sc, ch, CCR, 0); 971 972 emu_wrptr(sc, ch, PSST, 0); 973 emu_wrptr(sc, ch, DSL, 0x10); 974 emu_wrptr(sc, ch, CCCA, 0); 975 emu_wrptr(sc, ch, Z1, 0); 976 emu_wrptr(sc, ch, Z2, 0); 977 emu_wrptr(sc, ch, FXRT, 0xd01c0000); 978 979 emu_wrptr(sc, ch, ATKHLDM, 0); 980 emu_wrptr(sc, ch, DCYSUSM, 0); 981 emu_wrptr(sc, ch, IFATN, 0xffff); 982 emu_wrptr(sc, ch, PEFE, 0); 983 emu_wrptr(sc, ch, FMMOD, 0); 984 emu_wrptr(sc, ch, TREMFRQ, 24); /* 1 Hz */ 985 emu_wrptr(sc, ch, FM2FRQ2, 24); /* 1 Hz */ 986 emu_wrptr(sc, ch, TEMPENV, 0); 987 988 /*** these are last so OFF prevents writing ***/ 989 emu_wrptr(sc, ch, LFOVAL2, 0); 990 emu_wrptr(sc, ch, LFOVAL1, 0); 991 emu_wrptr(sc, ch, ATKHLDV, 0); 992 emu_wrptr(sc, ch, ENVVOL, 0); 993 emu_wrptr(sc, ch, ENVVAL, 0); 994 995 sc->voice[ch].vnum = ch; 996 sc->voice[ch].slave = NULL; 997 sc->voice[ch].busy = 0; 998 sc->voice[ch].running = 0; 999 sc->voice[ch].b16 = 0; 1000 sc->voice[ch].stereo = 0; 1001 sc->voice[ch].speed = 0; 1002 sc->voice[ch].start = 0; 1003 sc->voice[ch].end = 0; 1004 sc->voice[ch].channel = NULL; 1005 } 1006 1007 /* 1008 * Init to 0x02109204 : 1009 * Clock accuracy = 0 (1000ppm) 1010 * Sample Rate = 2 (48kHz) 1011 * Audio Channel = 1 (Left of 2) 1012 * Source Number = 0 (Unspecified) 1013 * Generation Status = 1 (Original for Cat Code 12) 1014 * Cat Code = 12 (Digital Signal Mixer) 1015 * Mode = 0 (Mode 0) 1016 * Emphasis = 0 (None) 1017 * CP = 1 (Copyright unasserted) 1018 * AN = 0 (Audio data) 1019 * P = 0 (Consumer) 1020 */ 1021 spcs = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | 1022 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | 1023 SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | 1024 SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; 1025 emu_wrptr(sc, 0, SPCS0, spcs); 1026 emu_wrptr(sc, 0, SPCS1, spcs); 1027 emu_wrptr(sc, 0, SPCS2, spcs); 1028 1029 emu_initefx(sc); 1030 1031 SLIST_INIT(&sc->mem.blocks); 1032 sc->mem.ptb_pages = emu_malloc(sc, MAXPAGES * sizeof(u_int32_t)); 1033 if (sc->mem.ptb_pages == NULL) 1034 return -1; 1035 1036 sc->mem.silent_page = emu_malloc(sc, EMUPAGESIZE); 1037 if (sc->mem.silent_page == NULL) { 1038 emu_free(sc, sc->mem.ptb_pages); 1039 return -1; 1040 } 1041 /* Clear page with silence & setup all pointers to this page */ 1042 bzero(sc->mem.silent_page, EMUPAGESIZE); 1043 tmp = (u_int32_t)vtophys(sc->mem.silent_page) << 1; 1044 for (i = 0; i < MAXPAGES; i++) 1045 sc->mem.ptb_pages[i] = tmp | i; 1046 1047 emu_wrptr(sc, 0, PTB, vtophys(sc->mem.ptb_pages)); 1048 emu_wrptr(sc, 0, TCB, 0); /* taken from original driver */ 1049 emu_wrptr(sc, 0, TCBS, 4); /* taken from original driver */ 1050 1051 for (ch = 0; ch < NUM_G; ch++) { 1052 emu_wrptr(sc, ch, MAPA, tmp | MAP_PTI_MASK); 1053 emu_wrptr(sc, ch, MAPB, tmp | MAP_PTI_MASK); 1054 } 1055 1056 /* emu_memalloc(sc, EMUPAGESIZE); */ 1057 /* 1058 * Hokay, now enable the AUD bit 1059 * Enable Audio = 1 1060 * Mute Disable Audio = 0 1061 * Lock Tank Memory = 1 1062 * Lock Sound Memory = 0 1063 * Auto Mute = 1 1064 */ 1065 tmp = HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE | HCFG_AUTOMUTE; 1066 if (sc->rev >= 6) 1067 tmp |= HCFG_JOYENABLE; 1068 emu_wr(sc, HCFG, tmp, 4); 1069 1070 /* TOSLink detection */ 1071 sc->tos_link = 0; 1072 tmp = emu_rd(sc, HCFG, 4); 1073 if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) { 1074 emu_wr(sc, HCFG, tmp | 0x800, 4); 1075 DELAY(50); 1076 if (tmp != (emu_rd(sc, HCFG, 4) & ~0x800)) { 1077 sc->tos_link = 1; 1078 emu_wr(sc, HCFG, tmp, 4); 1079 } 1080 } 1081 1082 return 0; 1083} 1084 1085static int 1086emu_pci_probe(device_t dev) 1087{ 1088 char *s = NULL; 1089 1090 switch (pci_get_devid(dev)) { 1091 case EMU10K1_PCI_ID: 1092 s = "Creative EMU10K1"; 1093 break; 1094 } 1095 1096 if (s) device_set_desc(dev, s); 1097 return s? 0 : ENXIO; 1098} 1099 1100static int 1101emu_pci_attach(device_t dev) 1102{ 1103 snddev_info *d; 1104 u_int32_t data; 1105 struct sc_info *sc; 1106 struct ac97_info *codec; 1107 int i, mapped; 1108 char status[SND_STATUSLEN]; 1109 1110 d = device_get_softc(dev); 1111 if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { 1112 device_printf(dev, "cannot allocate softc\n"); 1113 return ENXIO; 1114 } 1115 1116 bzero(sc, sizeof(*sc)); 1117 sc->type = pci_get_devid(dev); 1118 sc->rev = pci_get_revid(dev); 1119 1120 data = pci_read_config(dev, PCIR_COMMAND, 2); 1121 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 1122 pci_write_config(dev, PCIR_COMMAND, data, 2); 1123 data = pci_read_config(dev, PCIR_COMMAND, 2); 1124 1125 mapped = 0; 1126 /* Xemu dfr: is this strictly necessary? */ 1127 for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) { 1128 sc->regid = PCIR_MAPS + i*4; 1129 sc->regtype = SYS_RES_MEMORY; 1130 sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, 1131 0, ~0, 1, RF_ACTIVE); 1132 if (!sc->reg) { 1133 sc->regtype = SYS_RES_IOPORT; 1134 sc->reg = bus_alloc_resource(dev, sc->regtype, 1135 &sc->regid, 0, ~0, 1, 1136 RF_ACTIVE); 1137 } 1138 if (sc->reg) { 1139 sc->st = rman_get_bustag(sc->reg); 1140 sc->sh = rman_get_bushandle(sc->reg); 1141 mapped++; 1142 } 1143 } 1144 1145 if (mapped == 0) { 1146 device_printf(dev, "unable to map register space\n"); 1147 goto bad; 1148 } 1149 1150 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 1151 /*lowaddr*/1 << 31, /* can only access 0-2gb */ 1152 /*highaddr*/BUS_SPACE_MAXADDR, 1153 /*filter*/NULL, /*filterarg*/NULL, 1154 /*maxsize*/262144, /*nsegments*/1, /*maxsegz*/0x3ffff, 1155 /*flags*/0, &sc->parent_dmat) != 0) { 1156 device_printf(dev, "unable to create dma tag\n"); 1157 goto bad; 1158 } 1159 1160 if (emu_init(sc) == -1) { 1161 device_printf(dev, "unable to initialize the card\n"); 1162 goto bad; 1163 } 1164 1165 codec = ac97_create(dev, sc, NULL, emu_rdcd, emu_wrcd); 1166 if (codec == NULL) goto bad; 1167 if (mixer_init(d, &ac97_mixer, codec) == -1) goto bad; 1168 1169 sc->irqid = 0; 1170 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, 1171 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 1172 if (!sc->irq || 1173 bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, emu_intr, sc, &sc->ih)) { 1174 device_printf(dev, "unable to map interrupt\n"); 1175 goto bad; 1176 } 1177 1178 snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld", 1179 (sc->regtype == SYS_RES_IOPORT)? "io" : "memory", 1180 rman_get_start(sc->reg), rman_get_start(sc->irq)); 1181 1182 if (pcm_register(dev, sc, 1, 0)) goto bad; 1183 pcm_addchan(dev, PCMDIR_PLAY, &emu_chantemplate, sc); 1184 /* pcm_addchan(dev, PCMDIR_REC, &emu_chantemplate, sc); */ 1185 1186 pcm_setstatus(dev, status); 1187 1188 return 0; 1189 1190bad: 1191 if (sc->reg) bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); 1192 if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); 1193 if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 1194 free(sc, M_DEVBUF); 1195 return ENXIO; 1196} 1197 1198static device_method_t emu_methods[] = { 1199 /* Device interface */ 1200 DEVMETHOD(device_probe, emu_pci_probe), 1201 DEVMETHOD(device_attach, emu_pci_attach), 1202 1203 { 0, 0 } 1204}; 1205 1206static driver_t emu_driver = { 1207 "pcm", 1208 emu_methods, 1209 sizeof(snddev_info), 1210}; 1211 1212static devclass_t pcm_devclass; 1213 1214DRIVER_MODULE(emu, pci, emu_driver, pcm_devclass, 0, 0); 1215