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$ 27 */ 28 29 #include <dev/sound/pcm/sound.h> 30 #include <dev/sound/pcm/ac97.h> 31 #include <dev/sound/pci/t4dwave.h> 32 33 #include <pci/pcireg.h> 34 #include <pci/pcivar.h> 35 36 /* -------------------------------------------------------------------- */ 37 38 #define TDX_PCI_ID 0x20001023 39 #define TNX_PCI_ID 0x20011023 40 41 #define TR_BUFFSIZE 0xf000 42 #define TR_TIMEOUT_CDC 0xffff 43 #define TR_INTSAMPLES 0x2000 44 #define TR_MAXPLAYCH 4 45 46 struct tr_info; 47 48 /* channel registers */ 49 struct tr_chinfo { 50 u_int32_t cso, alpha, fms, fmc, ec; 51 u_int32_t lba; 52 u_int32_t eso, delta; 53 u_int32_t rvol, cvol; 54 u_int32_t gvsel, pan, vol, ctrl; 55 int index, ss; 56 snd_dbuf *buffer; 57 pcm_channel *channel; 58 struct tr_info *parent; 59 }; 60 61 /* device private data */ 62 struct tr_info { 63 u_int32_t type; 64 65 bus_space_tag_t st; 66 bus_space_handle_t sh; 67 bus_dma_tag_t parent_dmat; 68 69 struct resource *reg, *irq; 70 int regtype, regid, irqid; 71 void *ih; 72 73 u_int32_t playchns; 74 struct tr_chinfo chinfo[TR_MAXPLAYCH]; 75 struct tr_chinfo recchinfo; 76 }; 77 78 /* -------------------------------------------------------------------- */ 79 80 /* 81 * prototypes 82 */ 83 84 /* channel interface */ 85 static void *trchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 86 static int trchan_setdir(void *data, int dir); 87 static int trchan_setformat(void *data, u_int32_t format); 88 static int trchan_setspeed(void *data, u_int32_t speed); 89 static int trchan_setblocksize(void *data, u_int32_t blocksize); 90 static int trchan_trigger(void *data, int go); 91 static int trchan_getptr(void *data); 92 static pcmchan_caps *trchan_getcaps(void *data); 93 94 /* talk to the codec - called from ac97.c */ 95 static u_int32_t tr_rdcd(void *, int); 96 static void tr_wrcd(void *, int, u_int32_t); 97 98 /* stuff */ 99 static int tr_init(struct tr_info *); 100 static void tr_intr(void *); 101 102 /* talk to the card */ 103 static u_int32_t tr_rd(struct tr_info *, int, int); 104 static void tr_wr(struct tr_info *, int, u_int32_t, int); 105 106 /* manipulate playback channels */ 107 static void tr_clrint(struct tr_info *, char); 108 static void tr_enaint(struct tr_info *, char, int); 109 static u_int32_t tr_testint(struct tr_info *, char); 110 static void tr_rdch(struct tr_info *, char, struct tr_chinfo *); 111 static void tr_wrch(struct tr_info *, char, struct tr_chinfo *); 112 static void tr_selch(struct tr_info *, char); 113 static void tr_startch(struct tr_info *, char); 114 static void tr_stopch(struct tr_info *, char); 115 116 /* -------------------------------------------------------------------- */ 117 118 static u_int32_t tr_recfmt[] = { 119 AFMT_U8, 120 AFMT_STEREO | AFMT_U8, 121 AFMT_S8, 122 AFMT_STEREO | AFMT_S8, 123 AFMT_S16_LE, 124 AFMT_STEREO | AFMT_S16_LE, 125 AFMT_U16_LE, 126 AFMT_STEREO | AFMT_U16_LE, 127 0 128 }; 129 static pcmchan_caps tr_reccaps = {4000, 48000, tr_recfmt, 0}; 130 131 static u_int32_t tr_playfmt[] = { 132 AFMT_U8, 133 AFMT_STEREO | AFMT_U8, 134 AFMT_S8, 135 AFMT_STEREO | AFMT_S8, 136 AFMT_S16_LE, 137 AFMT_STEREO | AFMT_S16_LE, 138 AFMT_U16_LE, 139 AFMT_STEREO | AFMT_U16_LE, 140 0 141 }; 142 static pcmchan_caps tr_playcaps = {4000, 48000, tr_playfmt, 0}; 143 144 static pcm_channel tr_chantemplate = { 145 trchan_init, 146 trchan_setdir, 147 trchan_setformat, 148 trchan_setspeed, 149 trchan_setblocksize, 150 trchan_trigger, 151 trchan_getptr, 152 trchan_getcaps, 153 NULL, /* free */ 154 NULL, /* nop1 */ 155 NULL, /* nop2 */ 156 NULL, /* nop3 */ 157 NULL, /* nop4 */ 158 NULL, /* nop5 */ 159 NULL, /* nop6 */ 160 NULL, /* nop7 */ 161 }; 162 163 /* -------------------------------------------------------------------- */ 164 165 static u_int32_t 166 tr_fmttobits(u_int32_t fmt) 167 { 168 u_int32_t bits = 0; 169 bits |= (fmt & AFMT_STEREO)? 0x4 : 0; 170 bits |= (fmt & (AFMT_S8 | AFMT_S16_LE))? 0x2 : 0; 171 bits |= (fmt & (AFMT_S16_LE | AFMT_U16_LE))? 0x8 : 0; 172 return bits; 173 } 174 175 /* Hardware */ 176 177 static u_int32_t 178 tr_rd(struct tr_info *tr, int regno, int size) 179 { 180 switch(size) { 181 case 1: 182 return bus_space_read_1(tr->st, tr->sh, regno); 183 case 2: 184 return bus_space_read_2(tr->st, tr->sh, regno); 185 case 4: 186 return bus_space_read_4(tr->st, tr->sh, regno); 187 default: 188 return 0xffffffff; 189 } 190 } 191 192 static void 193 tr_wr(struct tr_info *tr, int regno, u_int32_t data, int size) 194 { 195 switch(size) { 196 case 1: 197 bus_space_write_1(tr->st, tr->sh, regno, data); 198 break; 199 case 2: 200 bus_space_write_2(tr->st, tr->sh, regno, data); 201 break; 202 case 4: 203 bus_space_write_4(tr->st, tr->sh, regno, data); 204 break; 205 } 206 } 207 208 /* ac97 codec */ 209 210 static u_int32_t 211 tr_rdcd(void *devinfo, int regno) 212 { 213 struct tr_info *tr = (struct tr_info *)devinfo; 214 int i, j, treg, trw; 215 216 switch (tr->type) { 217 case TDX_PCI_ID: 218 treg=TDX_REG_CODECRD; 219 trw=TDX_CDC_RWSTAT; 220 break; 221 case TNX_PCI_ID: 222 treg=(regno & 0x100)? TNX_REG_CODEC2RD : TNX_REG_CODEC1RD; 223 trw=TNX_CDC_RWSTAT; 224 break; 225 default: 226 printf("!!! tr_rdcd defaulted !!!\n"); 227 return 0xffffffff; 228 } 229 230 regno &= 0x7f; 231 tr_wr(tr, treg, regno | trw, 4); 232 j=trw; 233 for (i=TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--) j=tr_rd(tr, treg, 4); 234 if (i == 0) printf("codec timeout during read of register %x\n", regno); 235 return (j >> TR_CDC_DATA) & 0xffff; 236 } 237 238 static void 239 tr_wrcd(void *devinfo, int regno, u_int32_t data) 240 { 241 struct tr_info *tr = (struct tr_info *)devinfo; 242 int i, j, treg, trw; 243 244 switch (tr->type) { 245 case TDX_PCI_ID: 246 treg=TDX_REG_CODECWR; 247 trw=TDX_CDC_RWSTAT; 248 break; 249 case TNX_PCI_ID: 250 treg=TNX_REG_CODECWR; 251 trw=TNX_CDC_RWSTAT | ((regno & 0x100)? TNX_CDC_SEC : 0); 252 break; 253 default: 254 printf("!!! tr_wrcd defaulted !!!"); 255 return; 256 } 257 258 regno &= 0x7f; 259 #if 0 260 printf("tr_wrcd: reg %x was %x", regno, tr_rdcd(devinfo, regno)); 261 #endif 262 j=trw; 263 for (i=TR_TIMEOUT_CDC; (i>0) && (j & trw); i--) j=tr_rd(tr, treg, 4); 264 tr_wr(tr, treg, (data << TR_CDC_DATA) | regno | trw, 4); 265 #if 0 266 printf(" - wrote %x, now %x\n", data, tr_rdcd(devinfo, regno)); 267 #endif 268 if (i==0) printf("codec timeout writing %x, data %x\n", regno, data); 269 } 270 271 /* playback channel interrupts */ 272 273 static u_int32_t 274 tr_testint(struct tr_info *tr, char channel) 275 { 276 return tr_rd(tr, (channel & 0x20)? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 277 4) & (1<<(channel & 0x1f)); 278 } 279 280 static void 281 tr_clrint(struct tr_info *tr, char channel) 282 { 283 tr_wr(tr, (channel & 0x20)? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 284 1<<(channel & 0x1f), 4); 285 } 286 287 static void 288 tr_enaint(struct tr_info *tr, char channel, int enable) 289 { 290 u_int32_t reg = (channel & 0x20)? TR_REG_INTENB : TR_REG_INTENA; 291 u_int32_t i = tr_rd(tr, reg, 4); 292 channel &= 0x1f; 293 i &= ~(1 << channel); 294 i |= (enable? 1 : 0) << channel; 295 tr_clrint(tr, channel); 296 tr_wr(tr, reg, i, 4); 297 } 298 299 /* playback channels */ 300 301 static void 302 tr_selch(struct tr_info *tr, char channel) 303 { 304 int i=tr_rd(tr, TR_REG_CIR, 4); 305 i &= ~TR_CIR_MASK; 306 i |= channel & 0x3f; 307 tr_wr(tr, TR_REG_CIR, i, 4); 308 } 309 310 static void 311 tr_startch(struct tr_info *tr, char channel) 312 { 313 tr_wr(tr, (channel & 0x20)? TR_REG_STARTB : TR_REG_STARTA, 314 1<<(channel & 0x1f), 4); 315 } 316 317 static void 318 tr_stopch(struct tr_info *tr, char channel) 319 { 320 tr_wr(tr, (channel & 0x20)? TR_REG_STOPB : TR_REG_STOPA, 321 1<<(channel & 0x1f), 4); 322 } 323 324 static void 325 tr_wrch(struct tr_info *tr, char channel, struct tr_chinfo *ch) 326 { 327 u_int32_t cr[TR_CHN_REGS], i; 328 329 ch->gvsel &= 0x00000001; 330 ch->fmc &= 0x00000003; 331 ch->fms &= 0x0000000f; 332 ch->ctrl &= 0x0000000f; 333 ch->pan &= 0x0000007f; 334 ch->rvol &= 0x0000007f; 335 ch->cvol &= 0x0000007f; 336 ch->vol &= 0x000000ff; 337 ch->ec &= 0x00000fff; 338 ch->alpha &= 0x00000fff; 339 ch->delta &= 0x0000ffff; 340 ch->lba &= 0x3fffffff; 341 342 cr[1]=ch->lba; 343 cr[3]=(ch->rvol<<7) | (ch->cvol); 344 cr[4]=(ch->gvsel<<31)|(ch->pan<<24)|(ch->vol<<16)|(ch->ctrl<<12)|(ch->ec); 345 346 switch (tr->type) { 347 case TDX_PCI_ID: 348 ch->cso &= 0x0000ffff; 349 ch->eso &= 0x0000ffff; 350 cr[0]=(ch->cso<<16) | (ch->alpha<<4) | (ch->fms); 351 cr[2]=(ch->eso<<16) | (ch->delta); 352 cr[3]|=0x0000c000; 353 break; 354 case TNX_PCI_ID: 355 ch->cso &= 0x00ffffff; 356 ch->eso &= 0x00ffffff; 357 cr[0]=((ch->delta & 0xff)<<24) | (ch->cso); 358 cr[2]=((ch->delta>>16)<<24) | (ch->eso); 359 cr[3]|=(ch->alpha<<20) | (ch->fms<<16) | (ch->fmc<<14); 360 break; 361 } 362 tr_selch(tr, channel); 363 for (i=0; i<TR_CHN_REGS; i++) 364 tr_wr(tr, TR_REG_CHNBASE+(i<<2), cr[i], 4); 365 } 366 367 static void 368 tr_rdch(struct tr_info *tr, char channel, struct tr_chinfo *ch) 369 { 370 u_int32_t cr[5], i; 371 tr_selch(tr, channel); 372 for (i=0; i<5; i++) cr[i]=tr_rd(tr, TR_REG_CHNBASE+(i<<2), 4); 373 ch->lba= (cr[1] & 0x3fffffff); 374 ch->fmc= (cr[3] & 0x0000c000) >> 14; 375 ch->rvol= (cr[3] & 0x00003f80) >> 7; 376 ch->cvol= (cr[3] & 0x0000007f); 377 ch->gvsel= (cr[4] & 0x80000000) >> 31; 378 ch->pan= (cr[4] & 0x7f000000) >> 24; 379 ch->vol= (cr[4] & 0x00ff0000) >> 16; 380 ch->ctrl= (cr[4] & 0x0000f000) >> 12; 381 ch->ec= (cr[4] & 0x00000fff); 382 switch(tr->type) { 383 case TDX_PCI_ID: 384 ch->cso= (cr[0] & 0xffff0000) >> 16; 385 ch->alpha= (cr[0] & 0x0000fff0) >> 4; 386 ch->fms= (cr[0] & 0x0000000f); 387 ch->eso= (cr[2] & 0xffff0000) >> 16; 388 ch->delta= (cr[2] & 0x0000ffff); 389 break; 390 case TNX_PCI_ID: 391 ch->cso= (cr[0] & 0x00ffffff); 392 ch->eso= (cr[2] & 0x00ffffff); 393 ch->delta= ((cr[2] & 0xff000000) >> 16) | 394 ((cr[0] & 0xff000000) >> 24); 395 ch->alpha= (cr[3] & 0xfff00000) >> 20; 396 ch->fms= (cr[3] & 0x000f0000) >> 16; 397 break; 398 } 399 } 400 401 /* channel interface */ 402 403 void * 404 trchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 405 { 406 struct tr_info *tr = devinfo; 407 struct tr_chinfo *ch; 408 if (dir == PCMDIR_PLAY) { 409 ch = &tr->chinfo[tr->playchns]; 410 ch->index = tr->playchns++; 411 } else { 412 ch = &tr->recchinfo; 413 ch->index = -1; 414 } 415 ch->buffer = b; 416 ch->buffer->bufsize = TR_BUFFSIZE; 417 ch->parent = tr; 418 ch->channel = c; 419 if (chn_allocbuf(ch->buffer, tr->parent_dmat) == -1) return NULL; 420 else return ch; 421 } 422 423 static int 424 trchan_setdir(void *data, int dir) 425 { 426 struct tr_chinfo *ch = data; 427 struct tr_info *tr = ch->parent; 428 if (dir == PCMDIR_PLAY && ch->index >= 0) { 429 ch->fmc = ch->fms = ch->ec = ch->alpha = 0; 430 ch->lba = vtophys(ch->buffer->buf); 431 ch->cso = 0; 432 ch->eso = ch->buffer->bufsize - 1; 433 ch->rvol = ch->cvol = 0; 434 ch->gvsel = 0; 435 ch->pan = 0; 436 ch->vol = 0; 437 ch->ctrl = 0x01; 438 ch->delta = 0; 439 tr_wrch(tr, ch->index, ch); 440 tr_enaint(tr, ch->index, 1); 441 } else if (dir == PCMDIR_REC && ch->index == -1) { 442 /* set up dma mode regs */ 443 u_int32_t i; 444 tr_wr(tr, TR_REG_DMAR15, 0, 1); 445 i = tr_rd(tr, TR_REG_DMAR11, 1) & 0x03; 446 tr_wr(tr, TR_REG_DMAR11, i | 0x54, 1); 447 /* set up base address */ 448 tr_wr(tr, TR_REG_DMAR0, vtophys(ch->buffer->buf), 4); 449 /* set up buffer size */ 450 i = tr_rd(tr, TR_REG_DMAR4, 4) & ~0x00ffffff; 451 tr_wr(tr, TR_REG_DMAR4, i | (ch->buffer->bufsize - 1), 4); 452 } else return -1; 453 return 0; 454 } 455 456 static int 457 trchan_setformat(void *data, u_int32_t format) 458 { 459 struct tr_chinfo *ch = data; 460 struct tr_info *tr = ch->parent; 461 u_int32_t bits = tr_fmttobits(format); 462 463 ch->ss = 1; 464 ch->ss <<= (format & AFMT_STEREO)? 1 : 0; 465 ch->ss <<= (format & AFMT_16BIT)? 1 : 0; 466 if (ch->index >= 0) { 467 tr_rdch(tr, ch->index, ch); 468 ch->eso = (ch->buffer->bufsize / ch->ss) - 1; 469 ch->ctrl = bits | 0x01; 470 tr_wrch(tr, ch->index, ch); 471 } else { 472 u_int32_t i; 473 /* set # of samples between interrupts */ 474 i = (TR_INTSAMPLES >> ((bits & 0x08)? 1 : 0)) - 1; 475 tr_wr(tr, TR_REG_SBBL, i | (i << 16), 4); 476 /* set sample format */ 477 i = 0x18 | (bits << 4); 478 tr_wr(tr, TR_REG_SBCTRL, i, 1); 479 } 480 return 0; 481 } 482 483 static int 484 trchan_setspeed(void *data, u_int32_t speed) 485 { 486 struct tr_chinfo *ch = data; 487 struct tr_info *tr = ch->parent; 488 489 if (ch->index >= 0) { 490 tr_rdch(tr, ch->index, ch); 491 ch->delta = (speed << 12) / 48000; 492 tr_wrch(tr, ch->index, ch); 493 return (ch->delta * 48000) >> 12; 494 } else { 495 /* setup speed */ 496 ch->delta = (48000 << 12) / speed; 497 tr_wr(tr, TR_REG_SBDELTA, ch->delta, 2); 498 return (48000 << 12) / ch->delta; 499 } 500 return 0; 501 } 502 503 static int 504 trchan_setblocksize(void *data, u_int32_t blocksize) 505 { 506 struct tr_chinfo *ch = data; 507 return ch->buffer->bufsize / 2; 508 } 509 510 static int 511 trchan_trigger(void *data, int go) 512 { 513 struct tr_chinfo *ch = data; 514 struct tr_info *tr = ch->parent; 515 516 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 517 return 0; 518 519 if (ch->index >= 0) { 520 if (go == PCMTRIG_START) { 521 tr_rdch(tr, ch->index, ch); 522 ch->cso = 0; 523 tr_wrch(tr, ch->index, ch); 524 tr_startch(tr, ch->index); 525 } else tr_stopch(tr, ch->index); 526 } else { 527 u_int32_t i = tr_rd(tr, TR_REG_SBCTRL, 1) & ~7; 528 tr_wr(tr, TR_REG_SBCTRL, i | (go == PCMTRIG_START)? 1 : 0, 1); 529 } 530 return 0; 531 } 532 533 static int 534 trchan_getptr(void *data) 535 { 536 struct tr_chinfo *ch = data; 537 struct tr_info *tr = ch->parent; 538 539 if (ch->index >= 0) { 540 tr_rdch(tr, ch->index, ch); 541 return ch->cso * ch->ss; 542 } else return tr_rd(tr, TR_REG_DMAR0, 4) - vtophys(ch->buffer->buf); 543 } 544 545 static pcmchan_caps * 546 trchan_getcaps(void *data) 547 { 548 struct tr_chinfo *ch = data; 549 return (ch->index >= 0)? &tr_playcaps : &tr_reccaps; 550 } 551 552 /* The interrupt handler */ 553 554 static void 555 tr_intr(void *p) 556 { 557 struct tr_info *tr = (struct tr_info *)p; 558 u_int32_t intsrc = tr_rd(tr, TR_REG_MISCINT, 4); 559 560 if (intsrc & TR_INT_ADDR) { 561 int i; 562 for (i = 0; i < tr->playchns; i++) { 563 if (tr_testint(tr, i)) { 564 chn_intr(tr->chinfo[i].channel); 565 tr_clrint(tr, i); 566 } 567 } 568 } 569 if (intsrc & TR_INT_SB) { 570 chn_intr(tr->recchinfo.channel); 571 tr_rd(tr, TR_REG_SBR9, 1); 572 tr_rd(tr, TR_REG_SBR10, 1); 573 } 574 } 575 576 /* -------------------------------------------------------------------- */ 577 578 /* 579 * Probe and attach the card 580 */ 581 582 static int 583 tr_init(struct tr_info *tr) 584 { 585 if (tr->type == TDX_PCI_ID) { 586 tr_wr(tr, TDX_REG_CODECST, TDX_CDC_ON, 4); 587 } else tr_wr(tr, TNX_REG_CODECST, TNX_CDC_ON, 4); 588 589 tr_wr(tr, TR_REG_CIR, TR_CIR_MIDENA | TR_CIR_ADDRENA, 4); 590 tr->playchns = 0; 591 return 0; 592 } 593 594 static int 595 tr_pci_probe(device_t dev) 596 { 597 if (pci_get_devid(dev) == TDX_PCI_ID) { 598 device_set_desc(dev, "Trident 4DWave DX"); 599 return 0; 600 } 601 if (pci_get_devid(dev) == TNX_PCI_ID) { 602 device_set_desc(dev, "Trident 4DWave NX"); 603 return 0; 604 } 605 606 return ENXIO; 607 } 608 609 static int 610 tr_pci_attach(device_t dev) 611 { 612 u_int32_t data; 613 struct tr_info *tr; 614 struct ac97_info *codec = 0; 615 int i; 616 int mapped; 617 char status[SND_STATUSLEN]; 618 619 if ((tr = malloc(sizeof(*tr), M_DEVBUF, M_NOWAIT)) == NULL) { 620 device_printf(dev, "cannot allocate softc\n"); 621 return ENXIO; 622 } 623 624 bzero(tr, sizeof(*tr)); 625 tr->type = pci_get_devid(dev); 626 627 data = pci_read_config(dev, PCIR_COMMAND, 2); 628 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 629 pci_write_config(dev, PCIR_COMMAND, data, 2); 630 data = pci_read_config(dev, PCIR_COMMAND, 2); 631 632 mapped = 0; 633 /* XXX dfr: is this strictly necessary? */ 634 for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) { 635 tr->regid = PCIR_MAPS + i*4; 636 tr->regtype = SYS_RES_MEMORY; 637 tr->reg = bus_alloc_resource(dev, tr->regtype, &tr->regid, 638 0, ~0, 1, RF_ACTIVE); 639 if (!tr->reg) { 640 tr->regtype = SYS_RES_IOPORT; 641 tr->reg = bus_alloc_resource(dev, tr->regtype, 642 &tr->regid, 0, ~0, 1, 643 RF_ACTIVE); 644 } 645 if (tr->reg) { 646 tr->st = rman_get_bustag(tr->reg); 647 tr->sh = rman_get_bushandle(tr->reg); 648 mapped++; 649 } 650 } 651 652 if (mapped == 0) { 653 device_printf(dev, "unable to map register space\n"); 654 goto bad; 655 } 656 657 if (tr_init(tr) == -1) { 658 device_printf(dev, "unable to initialize the card\n"); 659 goto bad; 660 } 661 662 codec = ac97_create(dev, tr, NULL, tr_rdcd, tr_wrcd); 663 if (codec == NULL) goto bad; 664 if (mixer_init(dev, &ac97_mixer, codec) == -1) goto bad; 665 666 tr->irqid = 0; 667 tr->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &tr->irqid, 668 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 669 if (!tr->irq || 670 bus_setup_intr(dev, tr->irq, INTR_TYPE_TTY, tr_intr, tr, &tr->ih)) { 671 device_printf(dev, "unable to map interrupt\n"); 672 goto bad; 673 } 674 675 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 676 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 677 /*highaddr*/BUS_SPACE_MAXADDR, 678 /*filter*/NULL, /*filterarg*/NULL, 679 /*maxsize*/TR_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff, 680 /*flags*/0, &tr->parent_dmat) != 0) { 681 device_printf(dev, "unable to create dma tag\n"); 682 goto bad; 683 } 684 685 snprintf(status, 64, "at %s 0x%lx irq %ld", 686 (tr->regtype == SYS_RES_IOPORT)? "io" : "memory", 687 rman_get_start(tr->reg), rman_get_start(tr->irq)); 688 689 if (pcm_register(dev, tr, TR_MAXPLAYCH, 1)) goto bad; 690 pcm_addchan(dev, PCMDIR_REC, &tr_chantemplate, tr); 691 for (i = 0; i < TR_MAXPLAYCH; i++) 692 pcm_addchan(dev, PCMDIR_PLAY, &tr_chantemplate, tr); 693 pcm_setstatus(dev, status); 694 695 return 0; 696 697 bad: 698 if (codec) ac97_destroy(codec); 699 if (tr->reg) bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); 700 if (tr->ih) bus_teardown_intr(dev, tr->irq, tr->ih); 701 if (tr->irq) bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq); 702 if (tr->parent_dmat) bus_dma_tag_destroy(tr->parent_dmat); 703 free(tr, M_DEVBUF); 704 return ENXIO; 705 } 706 707 static int 708 tr_pci_detach(device_t dev) 709 { 710 int r; 711 struct tr_info *tr; 712 713 r = pcm_unregister(dev); 714 if (r) 715 return r; 716 717 tr = pcm_getdevinfo(dev); 718 bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); 719 bus_teardown_intr(dev, tr->irq, tr->ih); 720 bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq); 721 bus_dma_tag_destroy(tr->parent_dmat); 722 free(tr, M_DEVBUF); 723 724 return 0; 725 } 726 727 static device_method_t tr_methods[] = { 728 /* Device interface */ 729 DEVMETHOD(device_probe, tr_pci_probe), 730 DEVMETHOD(device_attach, tr_pci_attach), 731 DEVMETHOD(device_detach, tr_pci_detach), 732 733 { 0, 0 } 734 }; 735 736 static driver_t tr_driver = { 737 "pcm", 738 tr_methods, 739 sizeof(snddev_info), 740 }; 741 742 static devclass_t pcm_devclass; 743 744 DRIVER_MODULE(snd_t4dwave, pci, tr_driver, pcm_devclass, 0, 0); 745 MODULE_DEPEND(snd_t4dwave, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 746 MODULE_VERSION(snd_t4dwave, 1); 747