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