From abc35492427ddf6dd932ab3992f750c990d37889 Mon Sep 17 00:00:00 2001 From: "Ithamar R. Adema" Date: Thu, 17 May 2007 08:23:42 +0000 Subject: [PATCH] * Made code more Coding Guidelines compliant * Fixed several sem/area leaks when restarting media services. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21160 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/drivers/audio/hda/driver.h | 4 +- .../kernel/drivers/audio/hda/hda_codec.c | 36 ++++++++++++++- .../kernel/drivers/audio/hda/hda_controller.c | 44 ++++++++++++++++--- 3 files changed, 74 insertions(+), 10 deletions(-) diff --git a/src/add-ons/kernel/drivers/audio/hda/driver.h b/src/add-ons/kernel/drivers/audio/hda/driver.h index 3a7b1aae65..3f3719af9b 100644 --- a/src/add-ons/kernel/drivers/audio/hda/driver.h +++ b/src/add-ons/kernel/drivers/audio/hda/driver.h @@ -200,6 +200,7 @@ extern uint32 num_cards; /* hda_codec.c */ hda_codec* hda_codec_new(hda_controller* ctrlr, uint32 cad); +void hda_codec_delete(hda_codec*); /* hda_multi_audio.c */ status_t multi_audio_control(void* cookie, uint32 op, void* arg, size_t len); @@ -211,7 +212,8 @@ void hda_hw_uninit(hda_controller* ctrlr); status_t hda_send_verbs(hda_codec* codec, corb_t* verbs, uint32* responses, int count); /* hda_controller.c: Stream support */ -hda_stream* hda_stream_alloc(hda_controller* ctrlr, int type); +hda_stream* hda_stream_new(hda_controller* ctrlr, int type); +void hda_stream_delete(hda_stream* s); status_t hda_stream_setup_buffers(hda_afg* afg, hda_stream* s, const char* desc); status_t hda_stream_start(hda_controller* ctrlr, hda_stream* s); status_t hda_stream_stop(hda_controller* ctrlr, hda_stream* s); diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_codec.c b/src/add-ons/kernel/drivers/audio/hda/hda_codec.c index 9eede8ccf4..52ed5b75dc 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_codec.c +++ b/src/add-ons/kernel/drivers/audio/hda/hda_codec.c @@ -300,6 +300,21 @@ hda_codec_afg_find_dac_path(hda_afg* afg, uint32 wid, uint32 depth) return 0; } +static void +hda_afg_delete(hda_afg* afg) +{ + if (afg != NULL) { + if (afg->playback_stream != NULL) + hda_stream_delete(afg->playback_stream); + + if (afg->record_stream != NULL) + hda_stream_delete(afg->record_stream); + + free(afg->widgets); + free(afg); + } +} + static status_t hda_codec_afg_new(hda_codec* codec, uint32 afg_nid) { @@ -357,8 +372,8 @@ hda_codec_afg_new(hda_codec* codec, uint32 afg_nid) corb_t verb; /* Setup playback/record streams for Multi Audio API */ - afg->playback_stream = hda_stream_alloc(afg->codec->ctrlr, STRM_PLAYBACK); - afg->record_stream = hda_stream_alloc(afg->codec->ctrlr, STRM_RECORD); + afg->playback_stream = hda_stream_new(afg->codec->ctrlr, STRM_PLAYBACK); + afg->record_stream = hda_stream_new(afg->codec->ctrlr, STRM_RECORD); afg->playback_stream->pin_wid = idx + afg->wid_start; afg->playback_stream->io_wid = output_wid; @@ -389,6 +404,23 @@ done: return rc; } +void +hda_codec_delete(hda_codec* codec) +{ + if (codec != NULL) { + uint32 idx; + + delete_sem(codec->response_sem); + + for (idx=0; idx < codec->num_afgs; idx++) { + hda_afg_delete(codec->afgs[idx]); + codec->afgs[idx] = NULL; + } + + free(codec); + } +} + hda_codec* hda_codec_new(hda_controller* ctrlr, uint32 cad) { diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_controller.c b/src/add-ons/kernel/drivers/audio/hda/hda_controller.c index 9ba8046c16..bebb0e24c1 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_controller.c +++ b/src/add-ons/kernel/drivers/audio/hda/hda_controller.c @@ -4,8 +4,23 @@ #include "driver.h" +void +hda_stream_delete(hda_stream* s) +{ + if (s->buffer_ready_sem >= B_OK) + delete_sem(s->buffer_ready_sem); + + if (s->buffer_area >= B_OK) + delete_area(s->buffer_area); + + if (s->bdl_area >= B_OK) + delete_area(s->bdl_area); + + free(s); +} + hda_stream* -hda_stream_alloc(hda_controller* ctrlr, int type) +hda_stream_new(hda_controller* ctrlr, int type) { hda_stream* s = calloc(1, sizeof(hda_stream)); if (s != NULL) { @@ -45,7 +60,7 @@ hda_stream_start(hda_controller* ctrlr, hda_stream* s) { OREG8(ctrlr,s->off,CTL0) |= CTL0_RUN; - while(!(OREG8(ctrlr,s->off,CTL0) & CTL0_RUN)) + while (!(OREG8(ctrlr,s->off,CTL0) & CTL0_RUN)) snooze(1); s->running = true; @@ -84,7 +99,7 @@ hda_stream_stop(hda_controller* ctrlr, hda_stream* s) { OREG8(ctrlr,s->off,CTL0) &= ~CTL0_RUN; - while(OREG8(ctrlr,s->off,CTL0) & CTL0_RUN) + while (OREG8(ctrlr,s->off,CTL0) & CTL0_RUN) snooze(1); s->running = false; @@ -262,7 +277,7 @@ hda_interrupt_handler(hda_controller* ctrlr) if (rirbsts & RIRBSTS_RINTFL) { uint16 rirbwp = REG16(ctrlr,RIRBWP); - while(ctrlr->rirbrp <= rirbwp) { + while (ctrlr->rirbrp <= rirbwp) { uint32 resp_ex = ctrlr->rirb[ctrlr->rirbrp].resp_ex; uint32 cad = resp_ex & HDA_MAXCODECS; hda_codec* codec = ctrlr->codecs[cad]; @@ -326,7 +341,7 @@ hda_hw_start(hda_controller* ctrlr) do { snooze(100); - } while(--timeout && !(REG32(ctrlr,GCTL) & GCTL_CRST)); + } while (--timeout && !(REG32(ctrlr,GCTL) & GCTL_CRST)); return timeout ? B_OK : B_TIMED_OUT; } @@ -383,7 +398,7 @@ hda_hw_corb_rirb_init(hda_controller* ctrlr) if ((rc=get_memory_map(ctrlr->corb, memsz, &pe, 1)) != B_OK) { delete_area(ctrlr->rb_area); - return ctrlr->rb_area; + return rc; } /* Program CORB/RIRB for these locations */ @@ -395,7 +410,7 @@ hda_hw_corb_rirb_init(hda_controller* ctrlr) REG16(ctrlr,CORBRP) = CORBRP_RST; do { snooze(10); - } while( !(REG16(ctrlr,CORBRP) & CORBRP_RST) ); + } while ( !(REG16(ctrlr,CORBRP) & CORBRP_RST) ); REG16(ctrlr,CORBRP) = 0; /* Reset RIRB write pointer */ @@ -522,6 +537,8 @@ void hda_hw_uninit(hda_controller* ctrlr) { if (ctrlr != NULL) { + uint32 idx; + /* Stop all audio streams */ hda_hw_stop(ctrlr); @@ -535,6 +552,14 @@ hda_hw_uninit(hda_controller* ctrlr) remove_io_interrupt_handler(ctrlr->irq, (interrupt_handler)hda_interrupt_handler, ctrlr); + + /* Delete corb/rirb area */ + if (ctrlr->rb_area >= 0) { + delete_area(ctrlr->rb_area); + ctrlr->rb_area = B_ERROR; + ctrlr->corb = NULL; + ctrlr->rirb = NULL; + } /* Unmap registers */ if (ctrlr->regs_area >= 0) { @@ -542,5 +567,10 @@ hda_hw_uninit(hda_controller* ctrlr) ctrlr->regs_area = B_ERROR; ctrlr->regs = NULL; } + + /* Now delete all codecs */ + for (idx=0; idx < HDA_MAXCODECS; idx++) + if (ctrlr->codecs[idx] != NULL) + hda_codec_delete(ctrlr->codecs[idx]); } }