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