2 * Auich BeOS Driver for Intel Southbridge audio
4 * Copyright (c) 2003, Jerome Duval (jerome.duval@free.fr)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
28 #include <KernelExport.h>
30 #include <driver_settings.h>
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
);
54 auich_dev cards
[NUM_CARDS
];
56 char * names
[NUM_CARDS
*20+1];
58 volatile bool int_thread_exit
= false;
59 thread_id int_thread_id
= -1;
61 extern device_hooks multi_hooks
;
63 auich_settings current_settings
= {
65 4096, // buffer frames
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)
75 dump_hardware_regs(device_config
*config
)
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
)));
95 /* auich Memory management */
98 auich_mem_new(auich_dev
*card
, size_t size
)
102 if ((mem
= malloc(sizeof(*mem
))) == NULL
)
105 mem
->area
= alloc_mem(&mem
->phy_base
, &mem
->log_base
, size
, "auich buffer");
107 if (mem
->area
< B_OK
) {
116 auich_mem_delete(auich_mem
*mem
)
118 if (mem
->area
> B_OK
)
119 delete_area(mem
->area
);
125 auich_mem_alloc(auich_dev
*card
, size_t size
)
129 mem
= auich_mem_new(card
, size
);
133 LIST_INSERT_HEAD(&(card
->mems
), mem
, next
);
140 auich_mem_free(auich_dev
*card
, void *ptr
)
144 LIST_FOREACH(mem
, &card
->mems
, next
) {
145 if (mem
->log_base
!= ptr
)
147 LIST_REMOVE(mem
, next
);
149 auich_mem_delete(mem
);
154 /* auich stream functions */
157 auich_stream_set_audioparms(auich_stream
*stream
, uint8 channels
,
158 uint8 b16
, uint32 sample_rate
)
160 uint8 sample_size
, frame_size
;
161 LOG(("auich_stream_set_audioparms\n"));
163 if ((stream
->channels
== channels
)
164 && (stream
->b16
== b16
)
165 && (stream
->sample_rate
== sample_rate
))
169 auich_mem_free(stream
->card
, stream
->buffer
->log_base
);
172 stream
->sample_rate
= sample_rate
;
173 stream
->channels
= channels
;
175 sample_size
= stream
->b16
+ 1;
176 frame_size
= sample_size
* stream
->channels
;
178 stream
->buffer
= auich_mem_alloc(stream
->card
, stream
->bufframes
* frame_size
* stream
->bufcount
);
180 stream
->trigblk
= 0; /* This shouldn't be needed */
181 stream
->blkmod
= stream
->bufcount
;
182 stream
->blksize
= stream
->bufframes
* frame_size
;
189 auich_stream_commit_parms(auich_stream
*stream
)
193 LOG(("auich_stream_commit_parms\n"));
195 auich_reg_write_8(&stream
->card
->config
, stream
->base
+ AUICH_REG_X_CR
, 0);
196 snooze(10000); // 10 ms
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
));
210 PRINT(("channel reset failed after 10ms\n"));
212 page
= stream
->dmaops_log_base
;
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));
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
);
225 if (stream
->use
& AUICH_USE_RECORD
)
226 auich_codec_write(&stream
->card
->config
, AC97_PCM_L_R_ADC_RATE
, (uint16
)stream
->sample_rate
);
228 auich_codec_write(&stream
->card
->config
, AC97_PCM_FRONT_DAC_RATE
, (uint16
)stream
->sample_rate
);
230 if (stream
->use
& AUICH_USE_RECORD
)
231 LOG(("rate : %d\n", auich_codec_read(&stream
->card
->config
, AC97_PCM_L_R_ADC_RATE
)));
233 LOG(("rate : %d\n", auich_codec_read(&stream
->card
->config
, AC97_PCM_FRONT_DAC_RATE
)));
239 auich_stream_get_nth_buffer(auich_stream
*stream
, uint8 chan
, uint8 buf
,
240 char** buffer
, size_t *stride
)
242 uint8 sample_size
, frame_size
;
243 LOG(("auich_stream_get_nth_buffer\n"));
245 sample_size
= stream
->b16
+ 1;
246 frame_size
= sample_size
* stream
->channels
;
248 *buffer
= stream
->buffer
->log_base
+ (buf
* stream
->bufframes
* frame_size
)
249 + chan
* sample_size
;
250 *stride
= frame_size
;
257 auich_stream_curaddr(auich_stream
*stream
)
259 uint8 index
= auich_reg_read_8(&stream
->card
->config
, stream
->base
+ AUICH_REG_X_CIV
);
260 TRACE(("stream_curaddr %d\n", index
));
266 auich_stream_start(auich_stream
*stream
, void (*inth
) (void *), void *inthparam
)
269 LOG(("auich_stream_start\n"));
272 stream
->inthparam
= inthparam
;
274 stream
->state
|= AUICH_STATE_STARTED
;
276 civ
= auich_reg_read_8(&stream
->card
->config
, stream
->base
+ AUICH_REG_X_CIV
);
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
);
291 dump_hardware_regs(&stream
->card
->config
);
297 auich_stream_halt(auich_stream
*stream
)
299 LOG(("auich_stream_halt\n"));
301 stream
->state
&= ~AUICH_STATE_STARTED
;
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
);
309 auich_stream_new(auich_dev
*card
, uint8 use
, uint32 bufframes
, uint8 bufcount
)
311 auich_stream
*stream
;
313 LOG(("auich_stream_new\n"));
315 stream
= malloc(sizeof(auich_stream
));
320 stream
->state
= !AUICH_STATE_STARTED
;
322 stream
->sample_rate
= 0;
323 stream
->channels
= 0;
324 stream
->bufframes
= bufframes
;
325 stream
->bufcount
= bufcount
;
327 stream
->inthparam
= NULL
;
328 stream
->buffer
= NULL
;
333 if (use
& AUICH_USE_PLAY
) {
334 stream
->base
= AUICH_REG_PO_BASE
;
335 stream
->sta
= STA_POINT
;
337 stream
->base
= AUICH_REG_PI_BASE
;
338 stream
->sta
= STA_PIINT
;
341 stream
->frames_count
= 0;
342 stream
->real_time
= 0;
343 stream
->buffer_cycle
= 0;
344 stream
->update_needed
= false;
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");
350 if (stream
->dmaops_area
< B_OK
) {
351 PRINT(("couldn't allocate memory\n"));
357 LIST_INSERT_HEAD((&card
->streams
), stream
, next
);
365 auich_stream_delete(auich_stream
*stream
)
369 LOG(("auich_stream_delete\n"));
371 auich_stream_halt(stream
);
373 auich_reg_write_8(&stream
->card
->config
, stream
->base
+ AUICH_REG_X_CR
, 0);
374 snooze(10000); // 10 ms
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
));
386 LOG(("channel reset failed after 10ms\n"));
389 auich_reg_write_32(&stream
->card
->config
, stream
->base
+ AUICH_REG_X_BDBAR
, 0);
391 if (stream
->dmaops_area
> B_OK
)
392 delete_area(stream
->dmaops_area
);
395 auich_mem_free(stream
->card
, stream
->buffer
->log_base
);
398 LIST_REMOVE(stream
, next
);
404 /* auich interrupt */
409 auich_dev
*card
= arg
;
412 auich_stream
*stream
= NULL
;
416 // TRACE(("auich_int(%p)\n", card));
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
));
424 sta
&= ~(STA_S0RI
| STA_S1RI
| STA_S2RI
);
427 if (sta
& card
->interrupt_mask
) {
428 //TRACE(("interrupt !! %x\n", sta));
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
));
442 curblk
= auich_stream_curaddr(stream
);
444 auich_reg_write_8(&card
->config
, stream
->base
+ AUICH_REG_X_LVI
,
445 (curblk
+ 2) % AUICH_DMALIST_MAX
);
447 stream
->trigblk
= (curblk
) % stream
->blkmod
;
450 stream
->inth(stream
->inthparam
);
452 TRACE(("interrupt !! sta %x, sr %x\n", sta
, sr
));
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
);
462 dprintf("global status not fully handled %lx!\n", sta
);
463 auich_reg_write_32(&card
->config
, AUICH_REG_GLOB_STA
, sta
);
465 } else if (sta
!= 0) {
466 dprintf("interrupt masked %lx, sta %lx\n", card
->interrupt_mask
, sta
);
470 return B_INVOKE_SCHEDULER
;
472 TRACE(("Got unhandled interrupt\n"));
473 return B_UNHANDLED_INTERRUPT
;
478 auich_int_thread(void *data
)
481 while (!int_thread_exit
) {
482 status
= disable_interrupts();
484 restore_interrupts(status
);
491 /* auich driver functions */
494 map_io_memory(device_config
*config
)
496 if ((config
->type
& TYPE_ICH4
) == 0)
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
));
504 LOG(("mapping of mmbar: area %#x, phys %#x, log %#x\n", config
->area_mmbar
, config
->mmbar
, config
->log_mmbar
));
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;
513 LOG(("mapping of mbbar: area %#x, phys %#x, log %#x\n", config
->area_mbbar
, config
->mbbar
, config
->log_mbbar
));
520 unmap_io_memory(device_config
*config
)
523 if ((config
->type
& TYPE_ICH4
) == 0)
525 rv
= delete_area(config
->area_mmbar
);
526 rv
|= delete_area(config
->area_mbbar
);
530 /* detect presence of our hardware */
536 status_t err
= ENODEV
;
540 PRINT(("init_hardware()\n"));
542 if (get_module(B_PCI_MODULE_NAME
, (module_info
**)&pci
))
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
558 || (info
.vendor_id
== SIS_VENDOR_ID
&&
559 (info
.device_id
== SIS_SI7012_AC97_DEVICE_ID
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
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
582 put_module(B_PCI_MODULE_NAME
);
592 sprintf(card
->name
, "audio/hmulti/auich/%ld", card
-cards
+1);
593 names
[num_names
++] = card
->name
;
595 names
[num_names
] = NULL
;
600 auich_init(auich_dev
* card
)
602 card
->interrupt_mask
= STA_PIINT
| STA_POINT
; //STA_INTMASK;
604 /* Init streams list */
605 LIST_INIT(&(card
->streams
));
608 LIST_INIT(&(card
->mems
));
615 auich_setup(auich_dev
* card
)
622 PRINT(("auich_setup(%p)\n", card
));
624 make_device_names(card
);
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
;
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
));
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"));
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"));
666 /* before doing anything else, map the IO memory */
667 rv
= map_io_memory(&card
->config
);
669 PRINT(("mapping of memory IO space failed\n"));
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
);
680 (*pci
->write_pci_config
)(card
->info
.bus
, card
->info
.device
,
681 card
->info
.function
, PCI_command
, 2, cmd
| PCI_command_io
);
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
));
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"));
698 for (i
= 0; i
< 500; i
++) {
699 rv
= auich_reg_read_32(&card
->config
, AUICH_REG_GLOB_STA
);
705 if (!(rv
& STA_S0CR
)) { /* reset failure */
706 /* It never return STA_S0CR in some cases */
707 PRINT(("reset failure\n"));
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
);
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"));
720 if ((rv
& STA_CHAN_CAP
) == STA_PCM4
) {
721 LOG(("4ch PCM output support\n"));
723 if ((rv
& STA_CHAN_CAP
) == STA_PCM6
) {
724 LOG(("6ch PCM output support\n"));
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
);
733 PRINT(("installing interrupt : %lx\n", card
->config
.irq
));
734 err
= install_io_interrupt_handler(card
->config
.irq
, auich_int
,
737 PRINT(("failed to install interrupt\n"));
738 ac97_detach(card
->config
.ac97
);
739 unmap_io_memory(&card
->config
);
744 if ((err
= auich_init(card
)) != B_OK
)
747 PRINT(("init_driver done\n"));
757 void *settings_handle
;
762 PRINT(("init_driver()\n"));
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
);
771 if (get_module(B_PCI_MODULE_NAME
, (module_info
**) &pci
))
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
787 || (info
.vendor_id
== SIS_VENDOR_ID
788 && (info
.device_id
== SIS_SI7012_AC97_DEVICE_ID
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
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
805 if (num_cards
== NUM_CARDS
) {
806 PRINT(("Too many auich cards installed!\n"));
809 memset(&cards
[num_cards
], 0, sizeof(auich_dev
));
810 cards
[num_cards
].info
= info
;
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
,
820 if (auich_setup(&cards
[num_cards
])) {
821 PRINT(("Setup of auich %ld failed\n", num_cards
+1));
823 (*pci
->unreserve_device
)(info
.bus
, info
.device
, info
.function
,
824 DRIVER_NAME
, &cards
[num_cards
]);
833 PRINT(("no cards\n"));
834 put_module(B_PCI_MODULE_NAME
);
835 PRINT(("no suitable cards found\n"));
841 //add_debugger_command("auich", auich_debug, "auich [card# (1-n)]");
848 auich_shutdown(auich_dev
*card
)
850 PRINT(("shutdown(%p)\n", card
));
851 ac97_detach(card
->config
.ac97
);
853 card
->interrupt_mask
= 0;
855 if (current_settings
.use_thread
) {
857 int_thread_exit
= true;
858 wait_for_thread(int_thread_id
, &exit_value
);
860 remove_io_interrupt_handler(card
->config
.irq
, auich_int
, card
);
862 unmap_io_memory(&card
->config
);
869 int ix
, cnt
= num_cards
;
872 PRINT(("uninit_driver()\n"));
873 //remove_debugger_command("auich", auich_debug);
875 for (ix
=0; ix
<cnt
; ix
++) {
876 auich_shutdown(&cards
[ix
]);
878 (*pci
->unreserve_device
)(cards
[ix
].info
.bus
,
879 cards
[ix
].info
.device
, cards
[ix
].info
.function
,
880 DRIVER_NAME
, &cards
[ix
]);
883 memset(&cards
, 0, sizeof(cards
));
884 put_module(B_PCI_MODULE_NAME
);
889 publish_devices(void)
892 PRINT(("publish_devices()\n"));
894 for (ix
=0; names
[ix
]; ix
++) {
895 PRINT(("publish %s\n", names
[ix
]));
897 return (const char **)names
;
902 find_device(const char * name
)
906 PRINT(("find_device(%s)\n", name
));
908 for (ix
=0; ix
<num_cards
; ix
++) {
909 if (!strcmp(cards
[ix
].name
, name
)) {
913 PRINT(("find_device(%s) failed\n", name
));
917 int32 api_version
= B_CUR_DRIVER_API_VERSION
;