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 = stream->buffer->log_base + (buf * stream->bufframes * frame_size) 250 + 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 %lx!\n", sta); 464 auich_reg_write_32(&card->config, AUICH_REG_GLOB_STA, sta); 465 } 466 } else if (sta != 0) { 467 dprintf("interrupt masked %lx, sta %lx\n", card->interrupt_mask, sta); 468 } 469 470 if (gotone) 471 return B_INVOKE_SCHEDULER; 472 473 TRACE(("Got unhandled interrupt\n")); 474 return B_UNHANDLED_INTERRUPT; 475 } 476 477 478 static int32 479 auich_int_thread(void *data) 480 { 481 cpu_status status; 482 while (!int_thread_exit) { 483 status = disable_interrupts(); 484 auich_int(data); 485 restore_interrupts(status); 486 snooze(1500); 487 } 488 return 0; 489 } 490 491 492 /* auich driver functions */ 493 494 static status_t 495 map_io_memory(device_config *config) 496 { 497 if ((config->type & TYPE_ICH4) == 0) 498 return B_OK; 499 500 config->area_mmbar = map_mem(&config->log_mmbar, config->mmbar, ICH4_MMBAR_SIZE, "auich mmbar io"); 501 if (config->area_mmbar <= B_OK) { 502 LOG(("mapping of mmbar io failed, error = %#x\n",config->area_mmbar)); 503 return B_ERROR; 504 } 505 LOG(("mapping of mmbar: area %#x, phys %#x, log %#x\n", config->area_mmbar, config->mmbar, config->log_mmbar)); 506 507 config->area_mbbar = map_mem(&config->log_mbbar, config->mbbar, ICH4_MBBAR_SIZE, "auich mbbar io"); 508 if (config->area_mbbar <= B_OK) { 509 LOG(("mapping of mbbar io failed, error = %#x\n",config->area_mbbar)); 510 delete_area(config->area_mmbar); 511 config->area_mmbar = -1; 512 return B_ERROR; 513 } 514 LOG(("mapping of mbbar: area %#x, phys %#x, log %#x\n", config->area_mbbar, config->mbbar, config->log_mbbar)); 515 516 return B_OK; 517 } 518 519 520 static status_t 521 unmap_io_memory(device_config *config) 522 { 523 status_t rv; 524 if ((config->type & TYPE_ICH4) == 0) 525 return B_OK; 526 rv = delete_area(config->area_mmbar); 527 rv |= delete_area(config->area_mbbar); 528 return rv; 529 } 530 531 /* detect presence of our hardware */ 532 status_t 533 init_hardware(void) 534 { 535 int ix=0; 536 pci_info info; 537 status_t err = ENODEV; 538 539 LOG_CREATE(); 540 541 PRINT(("init_hardware()\n")); 542 543 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci)) 544 return ENOSYS; 545 546 while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { 547 if ((info.vendor_id == INTEL_VENDOR_ID && 548 (info.device_id == INTEL_82443MX_AC97_DEVICE_ID 549 || info.device_id == INTEL_82801AA_AC97_DEVICE_ID 550 || info.device_id == INTEL_82801AB_AC97_DEVICE_ID 551 || info.device_id == INTEL_82801BA_AC97_DEVICE_ID 552 || info.device_id == INTEL_82801CA_AC97_DEVICE_ID 553 || info.device_id == INTEL_82801DB_AC97_DEVICE_ID 554 || info.device_id == INTEL_82801EB_AC97_DEVICE_ID 555 || info.device_id == INTEL_82801FB_AC97_DEVICE_ID 556 || info.device_id == INTEL_82801GB_AC97_DEVICE_ID 557 || info.device_id == INTEL_6300ESB_AC97_DEVICE_ID 558 )) 559 || (info.vendor_id == SIS_VENDOR_ID && 560 (info.device_id == SIS_SI7012_AC97_DEVICE_ID 561 )) 562 || (info.vendor_id == NVIDIA_VENDOR_ID && 563 (info.device_id == NVIDIA_nForce_AC97_DEVICE_ID 564 || info.device_id == NVIDIA_nForce2_AC97_DEVICE_ID 565 || info.device_id == NVIDIA_nForce2_400_AC97_DEVICE_ID 566 || info.device_id == NVIDIA_nForce3_AC97_DEVICE_ID 567 || info.device_id == NVIDIA_nForce3_250_AC97_DEVICE_ID 568 || info.device_id == NVIDIA_CK804_AC97_DEVICE_ID 569 || info.device_id == NVIDIA_MCP51_AC97_DEVICE_ID 570 || info.device_id == NVIDIA_MCP04_AC97_DEVICE_ID 571 )) 572 || (info.vendor_id == AMD_VENDOR_ID && 573 (info.device_id == AMD_AMD8111_AC97_DEVICE_ID 574 || info.device_id == AMD_AMD768_AC97_DEVICE_ID 575 )) 576 ) 577 { 578 err = B_OK; 579 } 580 ix++; 581 } 582 583 put_module(B_PCI_MODULE_NAME); 584 585 return err; 586 } 587 588 589 static void 590 make_device_names( 591 auich_dev * card) 592 { 593 sprintf(card->name, "audio/hmulti/auich/%ld", card-cards+1); 594 names[num_names++] = card->name; 595 596 names[num_names] = NULL; 597 } 598 599 600 status_t 601 auich_init(auich_dev * card) 602 { 603 card->interrupt_mask = STA_PIINT | STA_POINT; //STA_INTMASK; 604 605 /* Init streams list */ 606 LIST_INIT(&(card->streams)); 607 608 /* Init mems list */ 609 LIST_INIT(&(card->mems)); 610 611 return B_OK; 612 } 613 614 615 static status_t 616 auich_setup(auich_dev * card) 617 { 618 status_t err = B_OK; 619 status_t rv; 620 unsigned char cmd; 621 int i; 622 623 PRINT(("auich_setup(%p)\n", card)); 624 625 make_device_names(card); 626 627 card->config.subvendor_id = card->info.u.h0.subsystem_vendor_id; 628 card->config.subsystem_id = card->info.u.h0.subsystem_id; 629 card->config.nabmbar = card->info.u.h0.base_registers[0]; 630 card->config.irq = card->info.u.h0.interrupt_line; 631 card->config.type = 0; 632 if ((card->info.device_id == INTEL_82801DB_AC97_DEVICE_ID) 633 || (card->info.device_id == INTEL_82801EB_AC97_DEVICE_ID) 634 || (card->info.device_id == INTEL_82801FB_AC97_DEVICE_ID) 635 || (card->info.device_id == INTEL_82801GB_AC97_DEVICE_ID) 636 || (card->info.device_id == INTEL_6300ESB_AC97_DEVICE_ID)) 637 card->config.type |= TYPE_ICH4; 638 if (card->info.device_id == SIS_SI7012_AC97_DEVICE_ID) 639 card->config.type |= TYPE_SIS7012; 640 641 PRINT(("%s deviceid = %#04x chiprev = %x model = %x enhanced at %lx\n", 642 card->name, card->info.device_id, card->info.revision, 643 card->info.u.h0.subsystem_id, card->config.nabmbar)); 644 645 if (IS_ICH4(&card->config)) { 646 // memory mapped access 647 card->config.mmbar = 0xfffffffe & (*pci->read_pci_config) 648 (card->info.bus, card->info.device, card->info.function, 0x18, 4); 649 card->config.mbbar = 0xfffffffe & (*pci->read_pci_config) 650 (card->info.bus, card->info.device, card->info.function, 0x1C, 4); 651 if (card->config.mmbar == 0 || card->config.mbbar == 0) { 652 PRINT(("memory mapped IO not configured\n")); 653 return B_ERROR; 654 } 655 } else { 656 // pio access 657 card->config.nambar = 0xfffffffe & (*pci->read_pci_config) 658 (card->info.bus, card->info.device, card->info.function, 0x10, 4); 659 card->config.nabmbar = 0xfffffffe & (*pci->read_pci_config) 660 (card->info.bus, card->info.device, card->info.function, 0x14, 4); 661 if (card->config.nambar == 0 || card->config.nabmbar == 0) { 662 PRINT(("IO space not configured\n")); 663 return B_ERROR; 664 } 665 } 666 667 /* before doing anything else, map the IO memory */ 668 rv = map_io_memory(&card->config); 669 if (rv != B_OK) { 670 PRINT(("mapping of memory IO space failed\n")); 671 return B_ERROR; 672 } 673 674 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, 675 card->info.function, PCI_command, 2); 676 PRINT(("PCI command before: %x\n", cmd)); 677 if (IS_ICH4(&card->config)) { 678 (*pci->write_pci_config)(card->info.bus, card->info.device, 679 card->info.function, PCI_command, 2, cmd | PCI_command_memory); 680 } else { 681 (*pci->write_pci_config)(card->info.bus, card->info.device, 682 card->info.function, PCI_command, 2, cmd | PCI_command_io); 683 } 684 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, 685 card->info.function, PCI_command, 2); 686 PRINT(("PCI command after: %x\n", cmd)); 687 688 /* do a cold reset */ 689 LOG(("cold reset\n")); 690 auich_reg_write_32(&card->config, AUICH_REG_GLOB_CNT, 0); 691 snooze(50000); // 50 ms 692 auich_reg_write_32(&card->config, AUICH_REG_GLOB_CNT, CNT_COLD | CNT_PRIE); 693 LOG(("cold reset finished\n")); 694 rv = auich_reg_read_32(&card->config, AUICH_REG_GLOB_CNT); 695 if ((rv & CNT_COLD) == 0) { 696 LOG(("cold reset failed\n")); 697 } 698 699 for (i = 0; i < 500; i++) { 700 rv = auich_reg_read_32(&card->config, AUICH_REG_GLOB_STA); 701 if (rv & STA_S0CR) 702 break; 703 snooze(1000); 704 } 705 706 if (!(rv & STA_S0CR)) { /* reset failure */ 707 /* It never return STA_S0CR in some cases */ 708 PRINT(("reset failure\n")); 709 } 710 711 /* attach the codec */ 712 PRINT(("codec attach\n")); 713 ac97_attach(&card->config.ac97, (codec_reg_read)auich_codec_read, 714 (codec_reg_write)auich_codec_write, &card->config, 715 card->config.subvendor_id, card->config.subsystem_id); 716 717 /* Print capabilities though there are no supports for now */ 718 if ((rv & STA_SAMPLE_CAP) == STA_POM20) { 719 LOG(("20 bit precision support\n")); 720 } 721 if ((rv & STA_CHAN_CAP) == STA_PCM4) { 722 LOG(("4ch PCM output support\n")); 723 } 724 if ((rv & STA_CHAN_CAP) == STA_PCM6) { 725 LOG(("6ch PCM output support\n")); 726 } 727 728 if (current_settings.use_thread || card->config.irq == 0 729 || card->config.irq == 0xff) { 730 int_thread_id = spawn_kernel_thread(auich_int_thread, 731 "auich interrupt poller", B_REAL_TIME_PRIORITY, card); 732 resume_thread(int_thread_id); 733 } else { 734 PRINT(("installing interrupt : %lx\n", card->config.irq)); 735 err = install_io_interrupt_handler(card->config.irq, auich_int, 736 card, 0); 737 if (err != B_OK) { 738 PRINT(("failed to install interrupt\n")); 739 ac97_detach(card->config.ac97); 740 unmap_io_memory(&card->config); 741 return err; 742 } 743 } 744 745 if ((err = auich_init(card)) != B_OK) 746 return err; 747 748 PRINT(("init_driver done\n")); 749 750 return err; 751 } 752 753 754 status_t 755 init_driver(void) 756 { 757 int ix = 0; 758 void *settings_handle; 759 pci_info info; 760 status_t err; 761 num_cards = 0; 762 763 PRINT(("init_driver()\n")); 764 765 // get driver settings 766 settings_handle = load_driver_settings(AUICH_SETTINGS); 767 if (settings_handle != NULL) { 768 current_settings.use_thread = get_driver_boolean_parameter (settings_handle, "use_thread", false, false); 769 unload_driver_settings (settings_handle); 770 } 771 772 if (get_module(B_PCI_MODULE_NAME, (module_info **) &pci)) 773 return ENOSYS; 774 775 while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) { 776 if ((info.vendor_id == INTEL_VENDOR_ID 777 && (info.device_id == INTEL_82443MX_AC97_DEVICE_ID 778 || info.device_id == INTEL_82801AA_AC97_DEVICE_ID 779 || info.device_id == INTEL_82801AB_AC97_DEVICE_ID 780 || info.device_id == INTEL_82801BA_AC97_DEVICE_ID 781 || info.device_id == INTEL_82801CA_AC97_DEVICE_ID 782 || info.device_id == INTEL_82801DB_AC97_DEVICE_ID 783 || info.device_id == INTEL_82801EB_AC97_DEVICE_ID 784 || info.device_id == INTEL_82801FB_AC97_DEVICE_ID 785 || info.device_id == INTEL_82801GB_AC97_DEVICE_ID 786 || info.device_id == INTEL_6300ESB_AC97_DEVICE_ID 787 )) 788 || (info.vendor_id == SIS_VENDOR_ID 789 && (info.device_id == SIS_SI7012_AC97_DEVICE_ID 790 )) 791 || (info.vendor_id == NVIDIA_VENDOR_ID 792 && (info.device_id == NVIDIA_nForce_AC97_DEVICE_ID 793 || info.device_id == NVIDIA_nForce2_AC97_DEVICE_ID 794 || info.device_id == NVIDIA_nForce2_400_AC97_DEVICE_ID 795 || info.device_id == NVIDIA_nForce3_AC97_DEVICE_ID 796 || info.device_id == NVIDIA_nForce3_250_AC97_DEVICE_ID 797 || info.device_id == NVIDIA_CK804_AC97_DEVICE_ID 798 || info.device_id == NVIDIA_MCP51_AC97_DEVICE_ID 799 || info.device_id == NVIDIA_MCP04_AC97_DEVICE_ID 800 )) 801 || (info.vendor_id == AMD_VENDOR_ID 802 && (info.device_id == AMD_AMD8111_AC97_DEVICE_ID 803 || info.device_id == AMD_AMD768_AC97_DEVICE_ID 804 )) 805 ) { 806 if (num_cards == NUM_CARDS) { 807 PRINT(("Too many auich cards installed!\n")); 808 break; 809 } 810 memset(&cards[num_cards], 0, sizeof(auich_dev)); 811 cards[num_cards].info = info; 812 #ifdef __HAIKU__ 813 if ((err = (*pci->reserve_device)(info.bus, info.device, info.function, 814 DRIVER_NAME, &cards[num_cards])) < B_OK) { 815 dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n", 816 DRIVER_NAME, info.bus, info.device, info.function, 817 strerror(err)); 818 continue; 819 } 820 #endif 821 if (auich_setup(&cards[num_cards])) { 822 PRINT(("Setup of auich %ld failed\n", num_cards+1)); 823 #ifdef __HAIKU__ 824 (*pci->unreserve_device)(info.bus, info.device, info.function, 825 DRIVER_NAME, &cards[num_cards]); 826 #endif 827 } 828 else { 829 num_cards++; 830 } 831 } 832 } 833 if (!num_cards) { 834 PRINT(("no cards\n")); 835 put_module(B_PCI_MODULE_NAME); 836 PRINT(("no suitable cards found\n")); 837 return ENODEV; 838 } 839 840 841 #if DEBUG 842 //add_debugger_command("auich", auich_debug, "auich [card# (1-n)]"); 843 #endif 844 return B_OK; 845 } 846 847 848 static void 849 auich_shutdown(auich_dev *card) 850 { 851 PRINT(("shutdown(%p)\n", card)); 852 ac97_detach(card->config.ac97); 853 854 card->interrupt_mask = 0; 855 856 if (current_settings.use_thread) { 857 status_t exit_value; 858 int_thread_exit = true; 859 wait_for_thread(int_thread_id, &exit_value); 860 } else 861 remove_io_interrupt_handler(card->config.irq, auich_int, card); 862 863 unmap_io_memory(&card->config); 864 } 865 866 867 void 868 uninit_driver(void) 869 { 870 int ix, cnt = num_cards; 871 num_cards = 0; 872 873 PRINT(("uninit_driver()\n")); 874 //remove_debugger_command("auich", auich_debug); 875 876 for (ix=0; ix<cnt; ix++) { 877 auich_shutdown(&cards[ix]); 878 #ifdef __HAIKU__ 879 (*pci->unreserve_device)(cards[ix].info.bus, 880 cards[ix].info.device, cards[ix].info.function, 881 DRIVER_NAME, &cards[ix]); 882 #endif 883 } 884 memset(&cards, 0, sizeof(cards)); 885 put_module(B_PCI_MODULE_NAME); 886 } 887 888 889 const char ** 890 publish_devices(void) 891 { 892 int ix = 0; 893 PRINT(("publish_devices()\n")); 894 895 for (ix=0; names[ix]; ix++) { 896 PRINT(("publish %s\n", names[ix])); 897 } 898 return (const char **)names; 899 } 900 901 902 device_hooks * 903 find_device(const char * name) 904 { 905 int ix; 906 907 PRINT(("find_device(%s)\n", name)); 908 909 for (ix=0; ix<num_cards; ix++) { 910 if (!strcmp(cards[ix].name, name)) { 911 return &multi_hooks; 912 } 913 } 914 PRINT(("find_device(%s) failed\n", name)); 915 return NULL; 916 } 917 918 int32 api_version = B_CUR_DRIVER_API_VERSION; 919