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", 641 card->name, card->info.device_id, card->info.revision, 642 card->info.u.h0.subsystem_id, card->config.nabmbar)); 643 644 if (IS_ICH4(&card->config)) { 645 // memory mapped access 646 card->config.mmbar = 0xfffffffe & (*pci->read_pci_config) 647 (card->info.bus, card->info.device, card->info.function, 0x18, 4); 648 card->config.mbbar = 0xfffffffe & (*pci->read_pci_config) 649 (card->info.bus, card->info.device, card->info.function, 0x1C, 4); 650 if (card->config.mmbar == 0 || card->config.mbbar == 0) { 651 PRINT(("memory mapped IO not configured\n")); 652 return B_ERROR; 653 } 654 } else { 655 // pio access 656 card->config.nambar = 0xfffffffe & (*pci->read_pci_config) 657 (card->info.bus, card->info.device, card->info.function, 0x10, 4); 658 card->config.nabmbar = 0xfffffffe & (*pci->read_pci_config) 659 (card->info.bus, card->info.device, card->info.function, 0x14, 4); 660 if (card->config.nambar == 0 || card->config.nabmbar == 0) { 661 PRINT(("IO space not configured\n")); 662 return B_ERROR; 663 } 664 } 665 666 /* before doing anything else, map the IO memory */ 667 rv = map_io_memory(&card->config); 668 if (rv != B_OK) { 669 PRINT(("mapping of memory IO space failed\n")); 670 return B_ERROR; 671 } 672 673 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, 674 card->info.function, PCI_command, 2); 675 PRINT(("PCI command before: %x\n", cmd)); 676 if (IS_ICH4(&card->config)) { 677 (*pci->write_pci_config)(card->info.bus, card->info.device, 678 card->info.function, PCI_command, 2, cmd | PCI_command_memory); 679 } else { 680 (*pci->write_pci_config)(card->info.bus, card->info.device, 681 card->info.function, PCI_command, 2, cmd | PCI_command_io); 682 } 683 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, 684 card->info.function, PCI_command, 2); 685 PRINT(("PCI command after: %x\n", cmd)); 686 687 /* do a cold reset */ 688 LOG(("cold reset\n")); 689 auich_reg_write_32(&card->config, AUICH_REG_GLOB_CNT, 0); 690 snooze(50000); // 50 ms 691 auich_reg_write_32(&card->config, AUICH_REG_GLOB_CNT, CNT_COLD | CNT_PRIE); 692 LOG(("cold reset finished\n")); 693 rv = auich_reg_read_32(&card->config, AUICH_REG_GLOB_CNT); 694 if ((rv & CNT_COLD) == 0) { 695 LOG(("cold reset failed\n")); 696 } 697 698 for (i = 0; i < 500; i++) { 699 rv = auich_reg_read_32(&card->config, AUICH_REG_GLOB_STA); 700 if (rv & STA_S0CR) 701 break; 702 snooze(1000); 703 } 704 705 if (!(rv & STA_S0CR)) { /* reset failure */ 706 /* It never return STA_S0CR in some cases */ 707 PRINT(("reset failure\n")); 708 } 709 710 /* attach the codec */ 711 PRINT(("codec attach\n")); 712 ac97_attach(&card->config.ac97, (codec_reg_read)auich_codec_read, 713 (codec_reg_write)auich_codec_write, &card->config, 714 card->config.subvendor_id, card->config.subsystem_id); 715 716 /* Print capabilities though there are no supports for now */ 717 if ((rv & STA_SAMPLE_CAP) == STA_POM20) { 718 LOG(("20 bit precision support\n")); 719 } 720 if ((rv & STA_CHAN_CAP) == STA_PCM4) { 721 LOG(("4ch PCM output support\n")); 722 } 723 if ((rv & STA_CHAN_CAP) == STA_PCM6) { 724 LOG(("6ch PCM output support\n")); 725 } 726 727 if (current_settings.use_thread || card->config.irq == 0 728 || card->config.irq == 0xff) { 729 int_thread_id = spawn_kernel_thread(auich_int_thread, 730 "auich interrupt poller", B_REAL_TIME_PRIORITY, card); 731 resume_thread(int_thread_id); 732 } else { 733 PRINT(("installing interrupt : %lx\n", card->config.irq)); 734 err = install_io_interrupt_handler(card->config.irq, auich_int, 735 card, 0); 736 if (err != B_OK) { 737 PRINT(("failed to install interrupt\n")); 738 ac97_detach(card->config.ac97); 739 unmap_io_memory(&card->config); 740 return err; 741 } 742 } 743 744 if ((err = auich_init(card)) != B_OK) 745 return err; 746 747 PRINT(("init_driver done\n")); 748 749 return err; 750 } 751 752 753 status_t 754 init_driver(void) 755 { 756 int ix = 0; 757 void *settings_handle; 758 pci_info info; 759 status_t err; 760 num_cards = 0; 761 762 PRINT(("init_driver()\n")); 763 764 // get driver settings 765 settings_handle = load_driver_settings(AUICH_SETTINGS); 766 if (settings_handle != NULL) { 767 current_settings.use_thread = get_driver_boolean_parameter (settings_handle, "use_thread", false, false); 768 unload_driver_settings (settings_handle); 769 } 770 771 if (get_module(B_PCI_MODULE_NAME, (module_info **) &pci)) 772 return ENOSYS; 773 774 while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) { 775 if ((info.vendor_id == INTEL_VENDOR_ID 776 && (info.device_id == INTEL_82443MX_AC97_DEVICE_ID 777 || info.device_id == INTEL_82801AA_AC97_DEVICE_ID 778 || info.device_id == INTEL_82801AB_AC97_DEVICE_ID 779 || info.device_id == INTEL_82801BA_AC97_DEVICE_ID 780 || info.device_id == INTEL_82801CA_AC97_DEVICE_ID 781 || info.device_id == INTEL_82801DB_AC97_DEVICE_ID 782 || info.device_id == INTEL_82801EB_AC97_DEVICE_ID 783 || info.device_id == INTEL_82801FB_AC97_DEVICE_ID 784 || info.device_id == INTEL_82801GB_AC97_DEVICE_ID 785 || info.device_id == INTEL_6300ESB_AC97_DEVICE_ID 786 )) 787 || (info.vendor_id == SIS_VENDOR_ID 788 && (info.device_id == SIS_SI7012_AC97_DEVICE_ID 789 )) 790 || (info.vendor_id == NVIDIA_VENDOR_ID 791 && (info.device_id == NVIDIA_nForce_AC97_DEVICE_ID 792 || info.device_id == NVIDIA_nForce2_AC97_DEVICE_ID 793 || info.device_id == NVIDIA_nForce2_400_AC97_DEVICE_ID 794 || info.device_id == NVIDIA_nForce3_AC97_DEVICE_ID 795 || info.device_id == NVIDIA_nForce3_250_AC97_DEVICE_ID 796 || info.device_id == NVIDIA_CK804_AC97_DEVICE_ID 797 || info.device_id == NVIDIA_MCP51_AC97_DEVICE_ID 798 || info.device_id == NVIDIA_MCP04_AC97_DEVICE_ID 799 )) 800 || (info.vendor_id == AMD_VENDOR_ID 801 && (info.device_id == AMD_AMD8111_AC97_DEVICE_ID 802 || info.device_id == AMD_AMD768_AC97_DEVICE_ID 803 )) 804 ) { 805 if (num_cards == NUM_CARDS) { 806 PRINT(("Too many auich cards installed!\n")); 807 break; 808 } 809 memset(&cards[num_cards], 0, sizeof(auich_dev)); 810 cards[num_cards].info = info; 811 #ifdef __HAIKU__ 812 if ((err = (*pci->reserve_device)(info.bus, info.device, info.function, 813 DRIVER_NAME, &cards[num_cards])) < B_OK) { 814 dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n", 815 DRIVER_NAME, info.bus, info.device, info.function, 816 strerror(err)); 817 continue; 818 } 819 #endif 820 if (auich_setup(&cards[num_cards])) { 821 PRINT(("Setup of auich %ld failed\n", num_cards+1)); 822 #ifdef __HAIKU__ 823 (*pci->unreserve_device)(info.bus, info.device, info.function, 824 DRIVER_NAME, &cards[num_cards]); 825 #endif 826 } 827 else { 828 num_cards++; 829 } 830 } 831 } 832 if (!num_cards) { 833 PRINT(("no cards\n")); 834 put_module(B_PCI_MODULE_NAME); 835 PRINT(("no suitable cards found\n")); 836 return ENODEV; 837 } 838 839 840 #if DEBUG 841 //add_debugger_command("auich", auich_debug, "auich [card# (1-n)]"); 842 #endif 843 return B_OK; 844 } 845 846 847 static void 848 auich_shutdown(auich_dev *card) 849 { 850 PRINT(("shutdown(%p)\n", card)); 851 ac97_detach(card->config.ac97); 852 853 card->interrupt_mask = 0; 854 855 if (current_settings.use_thread) { 856 status_t exit_value; 857 int_thread_exit = true; 858 wait_for_thread(int_thread_id, &exit_value); 859 } else 860 remove_io_interrupt_handler(card->config.irq, auich_int, card); 861 862 unmap_io_memory(&card->config); 863 } 864 865 866 void 867 uninit_driver(void) 868 { 869 int ix, cnt = num_cards; 870 num_cards = 0; 871 872 PRINT(("uninit_driver()\n")); 873 //remove_debugger_command("auich", auich_debug); 874 875 for (ix=0; ix<cnt; ix++) { 876 auich_shutdown(&cards[ix]); 877 #ifdef __HAIKU__ 878 (*pci->unreserve_device)(cards[ix].info.bus, 879 cards[ix].info.device, cards[ix].info.function, 880 DRIVER_NAME, &cards[ix]); 881 #endif 882 } 883 memset(&cards, 0, sizeof(cards)); 884 put_module(B_PCI_MODULE_NAME); 885 } 886 887 888 const char ** 889 publish_devices(void) 890 { 891 int ix = 0; 892 PRINT(("publish_devices()\n")); 893 894 for (ix=0; names[ix]; ix++) { 895 PRINT(("publish %s\n", names[ix])); 896 } 897 return (const char **)names; 898 } 899 900 901 device_hooks * 902 find_device(const char * name) 903 { 904 int ix; 905 906 PRINT(("find_device(%s)\n", name)); 907 908 for (ix=0; ix<num_cards; ix++) { 909 if (!strcmp(cards[ix].name, name)) { 910 return &multi_hooks; 911 } 912 } 913 PRINT(("find_device(%s) failed\n", name)); 914 return NULL; 915 } 916 917 int32 api_version = B_CUR_DRIVER_API_VERSION; 918