1 /* 2 * Auich BeOS Driver for Intel Southbridge audio 3 * 4 * Copyright (c) 2003, Jerome Duval (jerome.duval@free.fr) 5 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <KernelExport.h> 29 #include <PCI.h> 30 #include <driver_settings.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include "auich.h" 35 #include "debug.h" 36 #include "config.h" 37 #include "util.h" 38 #include "io.h" 39 #include <fcntl.h> 40 #include <unistd.h> 41 #include "ac97.h" 42 43 status_t init_hardware(void); 44 status_t init_driver(void); 45 void uninit_driver(void); 46 const char ** publish_devices(void); 47 device_hooks * find_device(const char *); 48 int32 auich_int(void *arg); 49 status_t auich_init(auich_dev * card); 50 51 pci_module_info *pci; 52 53 int32 num_cards; 54 auich_dev cards[NUM_CARDS]; 55 int32 num_names; 56 char * names[NUM_CARDS*20+1]; 57 58 volatile bool int_thread_exit = false; 59 thread_id int_thread_id = -1; 60 61 extern device_hooks multi_hooks; 62 63 auich_settings current_settings = { 64 48000, // sample rate 65 4096, // buffer frames 66 4, // buffer count 67 false // use thread 68 }; 69 70 /* The SIS7012 chipset has SR and PICB registers swapped when compared to Intel */ 71 #define GET_REG_PICB(x) (IS_SIS7012(x) ? AUICH_REG_X_SR : AUICH_REG_X_PICB) 72 #define GET_REG_SR(x) (IS_SIS7012(x) ? AUICH_REG_X_PICB : AUICH_REG_X_SR) 73 74 static void 75 dump_hardware_regs(device_config *config) 76 { 77 LOG(("GLOB_CNT = %#08x\n", auich_reg_read_32(config, AUICH_REG_GLOB_CNT))); 78 LOG(("GLOB_STA = %#08x\n", auich_reg_read_32(config, AUICH_REG_GLOB_STA))); 79 LOG(("PI AUICH_REG_X_BDBAR = %#x\n", auich_reg_read_32(config, AUICH_REG_X_BDBAR + AUICH_REG_PI_BASE))); 80 LOG(("PI AUICH_REG_X_CIV = %#x\n", auich_reg_read_8(config, AUICH_REG_X_CIV + AUICH_REG_PI_BASE))); 81 LOG(("PI AUICH_REG_X_LVI = %#x\n", auich_reg_read_8(config, AUICH_REG_X_LVI + AUICH_REG_PI_BASE))); 82 LOG(("PI REG_X_SR = %#x\n", auich_reg_read_16(config, AUICH_REG_X_SR + AUICH_REG_PI_BASE))); 83 LOG(("PI REG_X_PICB = %#x\n", auich_reg_read_16(config, AUICH_REG_X_PICB + AUICH_REG_PI_BASE))); 84 LOG(("PI AUICH_REG_X_PIV = %#x\n", auich_reg_read_8(config, AUICH_REG_X_PIV + AUICH_REG_PI_BASE))); 85 LOG(("PI AUICH_REG_X_CR = %#x\n", auich_reg_read_8(config, AUICH_REG_X_CR + AUICH_REG_PI_BASE))); 86 LOG(("PO AUICH_REG_X_BDBAR = %#x\n", auich_reg_read_32(config, AUICH_REG_X_BDBAR + AUICH_REG_PO_BASE))); 87 LOG(("PO AUICH_REG_X_CIV = %#x\n", auich_reg_read_8(config, AUICH_REG_X_CIV + AUICH_REG_PO_BASE))); 88 LOG(("PO AUICH_REG_X_LVI = %#x\n", auich_reg_read_8(config, AUICH_REG_X_LVI + AUICH_REG_PO_BASE))); 89 LOG(("PO REG_X_SR = %#x\n", auich_reg_read_16(config, AUICH_REG_X_SR + AUICH_REG_PO_BASE))); 90 LOG(("PO REG_X_PICB = %#x\n", auich_reg_read_16(config, AUICH_REG_X_PICB + AUICH_REG_PO_BASE))); 91 LOG(("PO AUICH_REG_X_PIV = %#x\n", auich_reg_read_8(config, AUICH_REG_X_PIV + AUICH_REG_PO_BASE))); 92 LOG(("PO AUICH_REG_X_CR = %#x\n", auich_reg_read_8(config, AUICH_REG_X_CR + AUICH_REG_PO_BASE))); 93 } 94 95 /* auich Memory management */ 96 97 static auich_mem * 98 auich_mem_new(auich_dev *card, size_t size) 99 { 100 auich_mem *mem; 101 102 if ((mem = malloc(sizeof(*mem))) == NULL) 103 return (NULL); 104 105 mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "auich buffer", 106 true); 107 mem->size = size; 108 if (mem->area < B_OK) { 109 free(mem); 110 return NULL; 111 } 112 return mem; 113 } 114 115 116 static void 117 auich_mem_delete(auich_mem *mem) 118 { 119 if (mem->area > B_OK) 120 delete_area(mem->area); 121 free(mem); 122 } 123 124 125 static void * 126 auich_mem_alloc(auich_dev *card, size_t size) 127 { 128 auich_mem *mem; 129 130 mem = auich_mem_new(card, size); 131 if (mem == NULL) 132 return (NULL); 133 134 LIST_INSERT_HEAD(&(card->mems), mem, next); 135 136 return mem; 137 } 138 139 140 static void 141 auich_mem_free(auich_dev *card, void *ptr) 142 { 143 auich_mem *mem; 144 145 LIST_FOREACH(mem, &card->mems, next) { 146 if (mem->log_base != ptr) 147 continue; 148 LIST_REMOVE(mem, next); 149 150 auich_mem_delete(mem); 151 break; 152 } 153 } 154 155 /* auich stream functions */ 156 157 status_t 158 auich_stream_set_audioparms(auich_stream *stream, uint8 channels, 159 uint8 b16, uint32 sample_rate) 160 { 161 uint8 sample_size, frame_size; 162 LOG(("auich_stream_set_audioparms\n")); 163 164 if ((stream->channels == channels) 165 && (stream->b16 == b16) 166 && (stream->sample_rate == sample_rate)) 167 return B_OK; 168 169 if (stream->buffer) 170 auich_mem_free(stream->card, stream->buffer->log_base); 171 172 stream->b16 = b16; 173 stream->sample_rate = sample_rate; 174 stream->channels = channels; 175 176 sample_size = stream->b16 + 1; 177 frame_size = sample_size * stream->channels; 178 179 stream->buffer = auich_mem_alloc(stream->card, stream->bufframes * frame_size * stream->bufcount); 180 181 stream->trigblk = 0; /* This shouldn't be needed */ 182 stream->blkmod = stream->bufcount; 183 stream->blksize = stream->bufframes * frame_size; 184 185 return B_OK; 186 } 187 188 189 status_t 190 auich_stream_commit_parms(auich_stream *stream) 191 { 192 uint32 *page; 193 uint32 i; 194 LOG(("auich_stream_commit_parms\n")); 195 196 auich_reg_write_8(&stream->card->config, stream->base + AUICH_REG_X_CR, 0); 197 snooze(10000); // 10 ms 198 199 auich_reg_write_8(&stream->card->config, 200 stream->base + AUICH_REG_X_CR, CR_RR); 201 for (i = 10000; i > 0; i--) { 202 if (0 == auich_reg_read_8(&stream->card->config, 203 stream->base + AUICH_REG_X_CR)) { 204 LOG(("channel reset finished, %x, %d\n", stream->base, i)); 205 break; 206 } 207 spin(1); 208 } 209 210 if (i == 0) 211 PRINT(("channel reset failed after 10ms\n")); 212 213 page = stream->dmaops_log_base; 214 215 for (i = 0; i < AUICH_DMALIST_MAX; i++) { 216 page[2 * i] = ((uint32)stream->buffer->phy_base) 217 + (i % stream->bufcount) * stream->blksize; 218 page[2 * i + 1] = AUICH_DMAF_IOC | (stream->blksize 219 / (IS_SIS7012(&stream->card->config) ? 1 : 2)); 220 } 221 222 // set physical buffer descriptor base address 223 auich_reg_write_32(&stream->card->config, stream->base + AUICH_REG_X_BDBAR, 224 (uint32)stream->dmaops_phy_base); 225 226 if (stream->use & AUICH_USE_RECORD) 227 auich_codec_write(&stream->card->config, AC97_PCM_L_R_ADC_RATE, (uint16)stream->sample_rate); 228 else 229 auich_codec_write(&stream->card->config, AC97_PCM_FRONT_DAC_RATE, (uint16)stream->sample_rate); 230 231 if (stream->use & AUICH_USE_RECORD) 232 LOG(("rate : %d\n", auich_codec_read(&stream->card->config, AC97_PCM_L_R_ADC_RATE))); 233 else 234 LOG(("rate : %d\n", auich_codec_read(&stream->card->config, AC97_PCM_FRONT_DAC_RATE))); 235 return B_OK; 236 } 237 238 239 status_t 240 auich_stream_get_nth_buffer(auich_stream *stream, uint8 chan, uint8 buf, 241 char** buffer, size_t *stride) 242 { 243 uint8 sample_size, frame_size; 244 LOG(("auich_stream_get_nth_buffer\n")); 245 246 sample_size = stream->b16 + 1; 247 frame_size = sample_size * stream->channels; 248 249 *buffer = (char*)stream->buffer->log_base 250 + (buf * stream->bufframes * frame_size) + chan * sample_size; 251 *stride = frame_size; 252 253 return B_OK; 254 } 255 256 257 static uint8 258 auich_stream_curaddr(auich_stream *stream) 259 { 260 uint8 index = auich_reg_read_8(&stream->card->config, stream->base + AUICH_REG_X_CIV); 261 TRACE(("stream_curaddr %d\n", index)); 262 return index; 263 } 264 265 266 void 267 auich_stream_start(auich_stream *stream, void (*inth) (void *), void *inthparam) 268 { 269 int32 civ; 270 LOG(("auich_stream_start\n")); 271 272 stream->inth = inth; 273 stream->inthparam = inthparam; 274 275 stream->state |= AUICH_STATE_STARTED; 276 277 civ = auich_reg_read_8(&stream->card->config, stream->base + AUICH_REG_X_CIV); 278 279 // step 1: clear status bits 280 auich_reg_write_16(&stream->card->config, 281 stream->base + GET_REG_SR(&stream->card->config), 282 auich_reg_read_16(&stream->card->config, stream->base + GET_REG_SR(&stream->card->config))); 283 auich_reg_read_16(&stream->card->config, stream->base + GET_REG_SR(&stream->card->config)); 284 // step 2: prepare buffer transfer 285 auich_reg_write_8(&stream->card->config, stream->base + AUICH_REG_X_LVI, (civ + 2) % AUICH_DMALIST_MAX); 286 auich_reg_read_8(&stream->card->config, stream->base + AUICH_REG_X_LVI); 287 // step 3: enable interrupts & busmaster transfer 288 auich_reg_write_8(&stream->card->config, stream->base + AUICH_REG_X_CR, CR_RPBM | CR_LVBIE | CR_FEIE | CR_IOCE); 289 auich_reg_read_8(&stream->card->config, stream->base + AUICH_REG_X_CR); 290 291 #ifdef DEBUG 292 dump_hardware_regs(&stream->card->config); 293 #endif 294 } 295 296 297 void 298 auich_stream_halt(auich_stream *stream) 299 { 300 LOG(("auich_stream_halt\n")); 301 302 stream->state &= ~AUICH_STATE_STARTED; 303 304 auich_reg_write_8(&stream->card->config, stream->base + AUICH_REG_X_CR, 305 auich_reg_read_8(&stream->card->config, stream->base + AUICH_REG_X_CR) & ~CR_RPBM); 306 } 307 308 309 auich_stream * 310 auich_stream_new(auich_dev *card, uint8 use, uint32 bufframes, uint8 bufcount) 311 { 312 auich_stream *stream; 313 cpu_status status; 314 LOG(("auich_stream_new\n")); 315 316 stream = malloc(sizeof(auich_stream)); 317 if (stream == NULL) 318 return (NULL); 319 stream->card = card; 320 stream->use = use; 321 stream->state = !AUICH_STATE_STARTED; 322 stream->b16 = 0; 323 stream->sample_rate = 0; 324 stream->channels = 0; 325 stream->bufframes = bufframes; 326 stream->bufcount = bufcount; 327 stream->inth = NULL; 328 stream->inthparam = NULL; 329 stream->buffer = NULL; 330 stream->blksize = 0; 331 stream->trigblk = 0; 332 stream->blkmod = 0; 333 334 if (use & AUICH_USE_PLAY) { 335 stream->base = AUICH_REG_PO_BASE; 336 stream->sta = STA_POINT; 337 } else { 338 stream->base = AUICH_REG_PI_BASE; 339 stream->sta = STA_PIINT; 340 } 341 342 stream->frames_count = 0; 343 stream->real_time = 0; 344 stream->buffer_cycle = 0; 345 stream->update_needed = false; 346 347 /* allocate memory for our dma ops */ 348 stream->dmaops_area = alloc_mem(&stream->dmaops_phy_base, &stream->dmaops_log_base, 349 sizeof(auich_dmalist) * AUICH_DMALIST_MAX, "auich dmaops", false); 350 351 if (stream->dmaops_area < B_OK) { 352 PRINT(("couldn't allocate memory\n")); 353 free(stream); 354 return NULL; 355 } 356 357 status = lock(); 358 LIST_INSERT_HEAD((&card->streams), stream, next); 359 unlock(status); 360 361 return stream; 362 } 363 364 365 void 366 auich_stream_delete(auich_stream *stream) 367 { 368 cpu_status status; 369 int32 i; 370 LOG(("auich_stream_delete\n")); 371 372 auich_stream_halt(stream); 373 374 auich_reg_write_8(&stream->card->config, stream->base + AUICH_REG_X_CR, 0); 375 snooze(10000); // 10 ms 376 377 auich_reg_write_8(&stream->card->config, stream->base + AUICH_REG_X_CR, CR_RR); 378 for (i = 10000; i>=0; i--) { 379 if (0 == auich_reg_read_8(&stream->card->config, stream->base + AUICH_REG_X_CR)) { 380 LOG(("channel reset finished, %x, %d\n", stream->base, i)); 381 break; 382 } 383 spin(1); 384 } 385 386 if (i < 0) { 387 LOG(("channel reset failed after 10ms\n")); 388 } 389 390 auich_reg_write_32(&stream->card->config, stream->base + AUICH_REG_X_BDBAR, 0); 391 392 if (stream->dmaops_area > B_OK) 393 delete_area(stream->dmaops_area); 394 395 if (stream->buffer) 396 auich_mem_free(stream->card, stream->buffer->log_base); 397 398 status = lock(); 399 LIST_REMOVE(stream, next); 400 unlock(status); 401 402 free(stream); 403 } 404 405 /* auich interrupt */ 406 407 int32 408 auich_int(void *arg) 409 { 410 auich_dev *card = arg; 411 bool gotone = false; 412 uint8 curblk; 413 auich_stream *stream = NULL; 414 uint32 sta; 415 uint16 sr; 416 417 // TRACE(("auich_int(%p)\n", card)); 418 419 sta = auich_reg_read_32(&card->config, AUICH_REG_GLOB_STA) & STA_INTMASK; 420 if (sta & (STA_S0RI | STA_S1RI | STA_S2RI)) { 421 // ignore and clear resume interrupt(s) 422 auich_reg_write_32(&card->config, AUICH_REG_GLOB_STA, sta & (STA_S0RI | STA_S1RI | STA_S2RI)); 423 TRACE(("interrupt !! %x\n", sta)); 424 gotone = true; 425 sta &= ~(STA_S0RI | STA_S1RI | STA_S2RI); 426 } 427 428 if (sta & card->interrupt_mask) { 429 //TRACE(("interrupt !! %x\n", sta)); 430 431 LIST_FOREACH(stream, &card->streams, next) 432 if (sta & stream->sta) { 433 sr = auich_reg_read_16(&card->config, 434 stream->base + GET_REG_SR(&stream->card->config)); 435 sr &= SR_MASK; 436 437 if (!sr) 438 continue; 439 440 gotone = true; 441 442 if (sr & SR_BCIS) { 443 curblk = auich_stream_curaddr(stream); 444 445 auich_reg_write_8(&card->config, stream->base + AUICH_REG_X_LVI, 446 (curblk + 2) % AUICH_DMALIST_MAX); 447 448 stream->trigblk = (curblk) % stream->blkmod; 449 450 if (stream->inth) 451 stream->inth(stream->inthparam); 452 } else { 453 TRACE(("interrupt !! sta %x, sr %x\n", sta, sr)); 454 } 455 456 auich_reg_write_16(&card->config, 457 stream->base + GET_REG_SR(&stream->card->config), sr); 458 auich_reg_write_32(&card->config, AUICH_REG_GLOB_STA, stream->sta); 459 sta &= ~stream->sta; 460 } 461 462 if (sta != 0) { 463 dprintf("global status not fully handled %" B_PRIx32 "!\n", sta); 464 auich_reg_write_32(&card->config, AUICH_REG_GLOB_STA, sta); 465 } 466 } else if (sta != 0) { 467 dprintf("interrupt masked %" B_PRIx32 ", sta %" B_PRIx32 "\n", 468 card->interrupt_mask, sta); 469 } 470 471 if (gotone) 472 return B_INVOKE_SCHEDULER; 473 474 TRACE(("Got unhandled interrupt\n")); 475 return B_UNHANDLED_INTERRUPT; 476 } 477 478 479 static int32 480 auich_int_thread(void *data) 481 { 482 cpu_status status; 483 while (!int_thread_exit) { 484 status = disable_interrupts(); 485 auich_int(data); 486 restore_interrupts(status); 487 snooze(1500); 488 } 489 return 0; 490 } 491 492 493 /* auich driver functions */ 494 495 static status_t 496 map_io_memory(device_config *config) 497 { 498 if ((config->type & TYPE_ICH4) == 0) 499 return B_OK; 500 501 config->area_mmbar = map_mem(&config->log_mmbar, config->mmbar, ICH4_MMBAR_SIZE, "auich mmbar io"); 502 if (config->area_mmbar <= B_OK) { 503 LOG(("mapping of mmbar io failed, error = %#x\n",config->area_mmbar)); 504 return B_ERROR; 505 } 506 LOG(("mapping of mmbar: area %#x, phys %#x, log %#x\n", config->area_mmbar, config->mmbar, config->log_mmbar)); 507 508 config->area_mbbar = map_mem(&config->log_mbbar, config->mbbar, ICH4_MBBAR_SIZE, "auich mbbar io"); 509 if (config->area_mbbar <= B_OK) { 510 LOG(("mapping of mbbar io failed, error = %#x\n",config->area_mbbar)); 511 delete_area(config->area_mmbar); 512 config->area_mmbar = -1; 513 return B_ERROR; 514 } 515 LOG(("mapping of mbbar: area %#x, phys %#x, log %#x\n", config->area_mbbar, config->mbbar, config->log_mbbar)); 516 517 return B_OK; 518 } 519 520 521 static status_t 522 unmap_io_memory(device_config *config) 523 { 524 status_t rv; 525 if ((config->type & TYPE_ICH4) == 0) 526 return B_OK; 527 rv = delete_area(config->area_mmbar); 528 rv |= delete_area(config->area_mbbar); 529 return rv; 530 } 531 532 /* detect presence of our hardware */ 533 status_t 534 init_hardware(void) 535 { 536 int ix=0; 537 pci_info info; 538 status_t err = ENODEV; 539 540 LOG_CREATE(); 541 542 PRINT(("init_hardware()\n")); 543 544 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci)) 545 return ENOSYS; 546 547 while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { 548 if ((info.vendor_id == INTEL_VENDOR_ID && 549 (info.device_id == INTEL_82443MX_AC97_DEVICE_ID 550 || info.device_id == INTEL_82801AA_AC97_DEVICE_ID 551 || info.device_id == INTEL_82801AB_AC97_DEVICE_ID 552 || info.device_id == INTEL_82801BA_AC97_DEVICE_ID 553 || info.device_id == INTEL_82801CA_AC97_DEVICE_ID 554 || info.device_id == INTEL_82801DB_AC97_DEVICE_ID 555 || info.device_id == INTEL_82801EB_AC97_DEVICE_ID 556 || info.device_id == INTEL_82801FB_AC97_DEVICE_ID 557 || info.device_id == INTEL_82801GB_AC97_DEVICE_ID 558 || info.device_id == INTEL_6300ESB_AC97_DEVICE_ID 559 )) 560 || (info.vendor_id == SIS_VENDOR_ID && 561 (info.device_id == SIS_SI7012_AC97_DEVICE_ID 562 )) 563 || (info.vendor_id == NVIDIA_VENDOR_ID && 564 (info.device_id == NVIDIA_nForce_AC97_DEVICE_ID 565 || info.device_id == NVIDIA_nForce2_AC97_DEVICE_ID 566 || info.device_id == NVIDIA_nForce2_400_AC97_DEVICE_ID 567 || info.device_id == NVIDIA_nForce3_AC97_DEVICE_ID 568 || info.device_id == NVIDIA_nForce3_250_AC97_DEVICE_ID 569 || info.device_id == NVIDIA_CK804_AC97_DEVICE_ID 570 || info.device_id == NVIDIA_MCP51_AC97_DEVICE_ID 571 || info.device_id == NVIDIA_MCP04_AC97_DEVICE_ID 572 )) 573 || (info.vendor_id == AMD_VENDOR_ID && 574 (info.device_id == AMD_AMD8111_AC97_DEVICE_ID 575 || info.device_id == AMD_AMD768_AC97_DEVICE_ID 576 )) 577 ) 578 { 579 err = B_OK; 580 } 581 ix++; 582 } 583 584 put_module(B_PCI_MODULE_NAME); 585 586 return err; 587 } 588 589 590 static void 591 make_device_names( 592 auich_dev * card) 593 { 594 sprintf(card->name, "audio/hmulti/auich/%ld", card-cards+1); 595 names[num_names++] = card->name; 596 597 names[num_names] = NULL; 598 } 599 600 601 status_t 602 auich_init(auich_dev * card) 603 { 604 card->interrupt_mask = STA_PIINT | STA_POINT; //STA_INTMASK; 605 606 /* Init streams list */ 607 LIST_INIT(&(card->streams)); 608 609 /* Init mems list */ 610 LIST_INIT(&(card->mems)); 611 612 return B_OK; 613 } 614 615 616 static status_t 617 auich_setup(auich_dev * card) 618 { 619 status_t err = B_OK; 620 status_t rv; 621 unsigned char cmd; 622 int i; 623 624 PRINT(("auich_setup(%p)\n", card)); 625 626 make_device_names(card); 627 628 card->config.subvendor_id = card->info.u.h0.subsystem_vendor_id; 629 card->config.subsystem_id = card->info.u.h0.subsystem_id; 630 card->config.nabmbar = card->info.u.h0.base_registers[0]; 631 card->config.irq = card->info.u.h0.interrupt_line; 632 card->config.type = 0; 633 if ((card->info.device_id == INTEL_82801DB_AC97_DEVICE_ID) 634 || (card->info.device_id == INTEL_82801EB_AC97_DEVICE_ID) 635 || (card->info.device_id == INTEL_82801FB_AC97_DEVICE_ID) 636 || (card->info.device_id == INTEL_82801GB_AC97_DEVICE_ID) 637 || (card->info.device_id == INTEL_6300ESB_AC97_DEVICE_ID)) 638 card->config.type |= TYPE_ICH4; 639 if (card->info.device_id == SIS_SI7012_AC97_DEVICE_ID) 640 card->config.type |= TYPE_SIS7012; 641 642 PRINT(("%s deviceid = %#04x chiprev = %x model = %x " 643 "enhanced at %" B_PRIx32 "lx\n", 644 card->name, card->info.device_id, card->info.revision, 645 card->info.u.h0.subsystem_id, card->config.nabmbar)); 646 647 if (IS_ICH4(&card->config)) { 648 // memory mapped access 649 card->config.mmbar = 0xfffffffe & (*pci->read_pci_config) 650 (card->info.bus, card->info.device, card->info.function, 0x18, 4); 651 card->config.mbbar = 0xfffffffe & (*pci->read_pci_config) 652 (card->info.bus, card->info.device, card->info.function, 0x1C, 4); 653 if (card->config.mmbar == 0 || card->config.mbbar == 0) { 654 PRINT(("memory mapped IO not configured\n")); 655 return B_ERROR; 656 } 657 } else { 658 // pio access 659 card->config.nambar = 0xfffffffe & (*pci->read_pci_config) 660 (card->info.bus, card->info.device, card->info.function, 0x10, 4); 661 card->config.nabmbar = 0xfffffffe & (*pci->read_pci_config) 662 (card->info.bus, card->info.device, card->info.function, 0x14, 4); 663 if (card->config.nambar == 0 || card->config.nabmbar == 0) { 664 PRINT(("IO space not configured\n")); 665 return B_ERROR; 666 } 667 } 668 669 /* before doing anything else, map the IO memory */ 670 rv = map_io_memory(&card->config); 671 if (rv != B_OK) { 672 PRINT(("mapping of memory IO space failed\n")); 673 return B_ERROR; 674 } 675 676 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, 677 card->info.function, PCI_command, 2); 678 PRINT(("PCI command before: %x\n", cmd)); 679 cmd |= PCI_command_master; 680 if (IS_ICH4(&card->config)) { 681 (*pci->write_pci_config)(card->info.bus, card->info.device, 682 card->info.function, PCI_command, 2, cmd | PCI_command_memory); 683 } else { 684 (*pci->write_pci_config)(card->info.bus, card->info.device, 685 card->info.function, PCI_command, 2, cmd | PCI_command_io); 686 } 687 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, 688 card->info.function, PCI_command, 2); 689 PRINT(("PCI command after: %x\n", cmd)); 690 691 /* do a cold reset */ 692 LOG(("cold reset\n")); 693 auich_reg_write_32(&card->config, AUICH_REG_GLOB_CNT, 0); 694 snooze(50000); // 50 ms 695 auich_reg_write_32(&card->config, AUICH_REG_GLOB_CNT, CNT_COLD | CNT_PRIE); 696 LOG(("cold reset finished\n")); 697 rv = auich_reg_read_32(&card->config, AUICH_REG_GLOB_CNT); 698 if ((rv & CNT_COLD) == 0) { 699 LOG(("cold reset failed\n")); 700 } 701 702 for (i = 0; i < 500; i++) { 703 rv = auich_reg_read_32(&card->config, AUICH_REG_GLOB_STA); 704 if (rv & STA_S0CR) 705 break; 706 snooze(1000); 707 } 708 709 if (!(rv & STA_S0CR)) { /* reset failure */ 710 /* It never return STA_S0CR in some cases */ 711 PRINT(("reset failure\n")); 712 } 713 714 /* attach the codec */ 715 PRINT(("codec attach\n")); 716 ac97_attach(&card->config.ac97, (codec_reg_read)auich_codec_read, 717 (codec_reg_write)auich_codec_write, &card->config, 718 card->config.subvendor_id, card->config.subsystem_id); 719 720 /* Print capabilities though there are no supports for now */ 721 if ((rv & STA_SAMPLE_CAP) == STA_POM20) { 722 LOG(("20 bit precision support\n")); 723 } 724 if ((rv & STA_CHAN_CAP) == STA_PCM4) { 725 LOG(("4ch PCM output support\n")); 726 } 727 if ((rv & STA_CHAN_CAP) == STA_PCM6) { 728 LOG(("6ch PCM output support\n")); 729 } 730 731 if (current_settings.use_thread || card->config.irq == 0 732 || card->config.irq == 0xff) { 733 int_thread_id = spawn_kernel_thread(auich_int_thread, 734 "auich interrupt poller", B_REAL_TIME_PRIORITY, card); 735 resume_thread(int_thread_id); 736 } else { 737 PRINT(("installing interrupt : %" B_PRIx32 "\n", card->config.irq)); 738 err = install_io_interrupt_handler(card->config.irq, auich_int, 739 card, 0); 740 if (err != B_OK) { 741 PRINT(("failed to install interrupt\n")); 742 ac97_detach(card->config.ac97); 743 unmap_io_memory(&card->config); 744 return err; 745 } 746 } 747 748 if ((err = auich_init(card)) != B_OK) 749 return err; 750 751 PRINT(("init_driver done\n")); 752 753 return err; 754 } 755 756 757 status_t 758 init_driver(void) 759 { 760 int ix = 0; 761 void *settings_handle; 762 pci_info info; 763 status_t err; 764 num_cards = 0; 765 766 PRINT(("init_driver()\n")); 767 768 // get driver settings 769 settings_handle = load_driver_settings(AUICH_SETTINGS); 770 if (settings_handle != NULL) { 771 current_settings.use_thread = get_driver_boolean_parameter (settings_handle, "use_thread", false, false); 772 unload_driver_settings (settings_handle); 773 } 774 775 if (get_module(B_PCI_MODULE_NAME, (module_info **) &pci)) 776 return ENOSYS; 777 778 while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) { 779 if ((info.vendor_id == INTEL_VENDOR_ID 780 && (info.device_id == INTEL_82443MX_AC97_DEVICE_ID 781 || info.device_id == INTEL_82801AA_AC97_DEVICE_ID 782 || info.device_id == INTEL_82801AB_AC97_DEVICE_ID 783 || info.device_id == INTEL_82801BA_AC97_DEVICE_ID 784 || info.device_id == INTEL_82801CA_AC97_DEVICE_ID 785 || info.device_id == INTEL_82801DB_AC97_DEVICE_ID 786 || info.device_id == INTEL_82801EB_AC97_DEVICE_ID 787 || info.device_id == INTEL_82801FB_AC97_DEVICE_ID 788 || info.device_id == INTEL_82801GB_AC97_DEVICE_ID 789 || info.device_id == INTEL_6300ESB_AC97_DEVICE_ID 790 )) 791 || (info.vendor_id == SIS_VENDOR_ID 792 && (info.device_id == SIS_SI7012_AC97_DEVICE_ID 793 )) 794 || (info.vendor_id == NVIDIA_VENDOR_ID 795 && (info.device_id == NVIDIA_nForce_AC97_DEVICE_ID 796 || info.device_id == NVIDIA_nForce2_AC97_DEVICE_ID 797 || info.device_id == NVIDIA_nForce2_400_AC97_DEVICE_ID 798 || info.device_id == NVIDIA_nForce3_AC97_DEVICE_ID 799 || info.device_id == NVIDIA_nForce3_250_AC97_DEVICE_ID 800 || info.device_id == NVIDIA_CK804_AC97_DEVICE_ID 801 || info.device_id == NVIDIA_MCP51_AC97_DEVICE_ID 802 || info.device_id == NVIDIA_MCP04_AC97_DEVICE_ID 803 )) 804 || (info.vendor_id == AMD_VENDOR_ID 805 && (info.device_id == AMD_AMD8111_AC97_DEVICE_ID 806 || info.device_id == AMD_AMD768_AC97_DEVICE_ID 807 )) 808 ) { 809 if (num_cards == NUM_CARDS) { 810 PRINT(("Too many auich cards installed!\n")); 811 break; 812 } 813 memset(&cards[num_cards], 0, sizeof(auich_dev)); 814 cards[num_cards].info = info; 815 #ifdef __HAIKU__ 816 if ((err = (*pci->reserve_device)(info.bus, info.device, info.function, 817 DRIVER_NAME, &cards[num_cards])) < B_OK) { 818 dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n", 819 DRIVER_NAME, info.bus, info.device, info.function, 820 strerror(err)); 821 continue; 822 } 823 #endif 824 if (auich_setup(&cards[num_cards])) { 825 PRINT(("Setup of auich %" B_PRId32 " failed\n", 826 num_cards + 1)); 827 #ifdef __HAIKU__ 828 (*pci->unreserve_device)(info.bus, info.device, info.function, 829 DRIVER_NAME, &cards[num_cards]); 830 #endif 831 } 832 else { 833 num_cards++; 834 } 835 } 836 } 837 if (!num_cards) { 838 PRINT(("no cards\n")); 839 put_module(B_PCI_MODULE_NAME); 840 PRINT(("no suitable cards found\n")); 841 return ENODEV; 842 } 843 844 845 #if DEBUG 846 //add_debugger_command("auich", auich_debug, "auich [card# (1-n)]"); 847 #endif 848 return B_OK; 849 } 850 851 852 static void 853 auich_shutdown(auich_dev *card) 854 { 855 PRINT(("shutdown(%p)\n", card)); 856 ac97_detach(card->config.ac97); 857 858 card->interrupt_mask = 0; 859 860 if (current_settings.use_thread) { 861 status_t exit_value; 862 int_thread_exit = true; 863 wait_for_thread(int_thread_id, &exit_value); 864 } else 865 remove_io_interrupt_handler(card->config.irq, auich_int, card); 866 867 unmap_io_memory(&card->config); 868 } 869 870 871 void 872 uninit_driver(void) 873 { 874 int ix, cnt = num_cards; 875 num_cards = 0; 876 877 PRINT(("uninit_driver()\n")); 878 //remove_debugger_command("auich", auich_debug); 879 880 for (ix=0; ix<cnt; ix++) { 881 auich_shutdown(&cards[ix]); 882 #ifdef __HAIKU__ 883 (*pci->unreserve_device)(cards[ix].info.bus, 884 cards[ix].info.device, cards[ix].info.function, 885 DRIVER_NAME, &cards[ix]); 886 #endif 887 } 888 memset(&cards, 0, sizeof(cards)); 889 put_module(B_PCI_MODULE_NAME); 890 } 891 892 893 const char ** 894 publish_devices(void) 895 { 896 int ix = 0; 897 PRINT(("publish_devices()\n")); 898 899 for (ix=0; names[ix]; ix++) { 900 PRINT(("publish %s\n", names[ix])); 901 } 902 return (const char **)names; 903 } 904 905 906 device_hooks * 907 find_device(const char * name) 908 { 909 int ix; 910 911 PRINT(("find_device(%s)\n", name)); 912 913 for (ix=0; ix<num_cards; ix++) { 914 if (!strcmp(cards[ix].name, name)) { 915 return &multi_hooks; 916 } 917 } 918 PRINT(("find_device(%s) failed\n", name)); 919 return NULL; 920 } 921 922 int32 api_version = B_CUR_DRIVER_API_VERSION; 923