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