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