15adb129eSJérôme Duval //------------------------------------------------------------------------------
25adb129eSJérôme Duval //
35adb129eSJérôme Duval // EchoGals/Echo24 BeOS Driver for Echo audio cards
45adb129eSJérôme Duval //
55adb129eSJérôme Duval // Copyright (c) 2003, Jérôme Duval
65adb129eSJérôme Duval //
75adb129eSJérôme Duval // Permission is hereby granted, free of charge, to any person obtaining a
85adb129eSJérôme Duval // copy of this software and associated documentation files (the "Software"),
95adb129eSJérôme Duval // to deal in the Software without restriction, including without limitation
105adb129eSJérôme Duval // the rights to use, copy, modify, merge, publish, distribute, sublicense,
115adb129eSJérôme Duval // and/or sell copies of the Software, and to permit persons to whom the
125adb129eSJérôme Duval // Software is furnished to do so, subject to the following conditions:
135adb129eSJérôme Duval //
145adb129eSJérôme Duval // The above copyright notice and this permission notice shall be included in
155adb129eSJérôme Duval // all copies or substantial portions of the Software.
165adb129eSJérôme Duval //
175adb129eSJérôme Duval // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
185adb129eSJérôme Duval // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
195adb129eSJérôme Duval // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
205adb129eSJérôme Duval // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
215adb129eSJérôme Duval // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
225adb129eSJérôme Duval // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
235adb129eSJérôme Duval // DEALINGS IN THE SOFTWARE.
245adb129eSJérôme Duval
255adb129eSJérôme Duval #include <KernelExport.h>
265adb129eSJérôme Duval #include <Drivers.h>
275adb129eSJérôme Duval #include <unistd.h>
285adb129eSJérôme Duval #include "OsSupportBeOS.h"
295adb129eSJérôme Duval #include "EchoGalsXface.h"
30c2ddc71cSJérôme Duval #include "C3g.h"
315adb129eSJérôme Duval #include "CDarla24.h"
325adb129eSJérôme Duval #include "CDarla.h"
335adb129eSJérôme Duval #include "CGina.h"
345adb129eSJérôme Duval #include "CGina24.h"
3508661eb2SJérôme Duval #include "CIndigo.h"
3608661eb2SJérôme Duval #include "CIndigoDJ.h"
3708661eb2SJérôme Duval #include "CIndigoIO.h"
385adb129eSJérôme Duval #include "CLayla.h"
395adb129eSJérôme Duval #include "CLayla24.h"
405adb129eSJérôme Duval #include "CMia.h"
415adb129eSJérôme Duval #include "CMona.h"
425adb129eSJérôme Duval #include "echo.h"
435adb129eSJérôme Duval #include "debug.h"
445adb129eSJérôme Duval #include "util.h"
455adb129eSJérôme Duval
46ec816dffSJérôme Duval #ifdef CARDBUS
47ec816dffSJérôme Duval static cb_enabler_module_info *cbemi;
48ec816dffSJérôme Duval struct _echodevs devices;
49ec816dffSJérôme Duval static char *names[NUM_CARDS];
50ec816dffSJérôme Duval int32 num_names = 0;
51ec816dffSJérôme Duval static uint32 device_index = 0;
52ec816dffSJérôme Duval static sem_id device_lock = 0;
53ec816dffSJérôme Duval
54ec816dffSJérôme Duval static const cb_device_descriptor descriptors[] = {
55ec816dffSJérôme Duval {VENDOR_ID, DEVICE_ID_56301, 0xff, 0xff, 0xff}
56ec816dffSJérôme Duval };
57ec816dffSJérôme Duval
58ec816dffSJérôme Duval #define COUNT_DESCRIPTOR 1
59ec816dffSJérôme Duval
60ec816dffSJérôme Duval status_t cardbus_device_added(pci_info *info, void **cookie);
61ec816dffSJérôme Duval void cardbus_device_removed(void *cookie);
62ec816dffSJérôme Duval
63ec816dffSJérôme Duval static cb_notify_hooks cardbus_hooks = {
64ec816dffSJérôme Duval cardbus_device_added, // Add entry point
65ec816dffSJérôme Duval cardbus_device_removed // Remove entry point
66ec816dffSJérôme Duval };
67ec816dffSJérôme Duval
68ec816dffSJérôme Duval #else // CARDBUS
695adb129eSJérôme Duval static pci_module_info *pci;
705adb129eSJérôme Duval int32 num_cards;
715adb129eSJérôme Duval echo_dev cards[NUM_CARDS];
725adb129eSJérôme Duval int32 num_names;
735adb129eSJérôme Duval char * names[NUM_CARDS*20+1];
74ec816dffSJérôme Duval #endif // CARDBUS
755adb129eSJérôme Duval
765adb129eSJérôme Duval extern device_hooks multi_hooks;
770bb683faSJérôme Duval #ifdef MIDI_SUPPORT
780bb683faSJérôme Duval extern device_hooks midi_hooks;
790bb683faSJérôme Duval #endif
805adb129eSJérôme Duval
815adb129eSJérôme Duval int32 echo_int(void *arg);
825adb129eSJérôme Duval status_t init_hardware(void);
835adb129eSJérôme Duval status_t init_driver(void);
845adb129eSJérôme Duval static void make_device_names(echo_dev * card);
855adb129eSJérôme Duval
865adb129eSJérôme Duval static status_t echo_setup(echo_dev * card);
875adb129eSJérôme Duval static void echo_shutdown(echo_dev *card);
885adb129eSJérôme Duval
895adb129eSJérôme Duval void uninit_driver(void);
905adb129eSJérôme Duval const char ** publish_devices(void);
915adb129eSJérôme Duval device_hooks * find_device(const char * name);
925adb129eSJérôme Duval
935adb129eSJérôme Duval
945adb129eSJérôme Duval /* Echo Memory management */
955adb129eSJérôme Duval
965adb129eSJérôme Duval echo_mem *
echo_mem_new(echo_dev * card,size_t size)975adb129eSJérôme Duval echo_mem_new(echo_dev *card, size_t size)
985adb129eSJérôme Duval {
995adb129eSJérôme Duval echo_mem *mem;
1005adb129eSJérôme Duval
1015adb129eSJérôme Duval if ((mem = (echo_mem *) malloc(sizeof(*mem))) == NULL)
1025adb129eSJérôme Duval return (NULL);
1035adb129eSJérôme Duval
104*d3503944SPulkoMandy mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "echo buffer", true);
1055adb129eSJérôme Duval mem->size = size;
1065adb129eSJérôme Duval if (mem->area < B_OK) {
1075adb129eSJérôme Duval free(mem);
1085adb129eSJérôme Duval return NULL;
1095adb129eSJérôme Duval }
1105adb129eSJérôme Duval return mem;
1115adb129eSJérôme Duval }
1125adb129eSJérôme Duval
113e480c1b6SPhilippe Saint-Pierre
1145adb129eSJérôme Duval void
echo_mem_delete(echo_mem * mem)1155adb129eSJérôme Duval echo_mem_delete(echo_mem *mem)
1165adb129eSJérôme Duval {
1175adb129eSJérôme Duval if (mem->area > B_OK)
1185adb129eSJérôme Duval delete_area(mem->area);
1195adb129eSJérôme Duval free(mem);
1205adb129eSJérôme Duval }
1215adb129eSJérôme Duval
122e480c1b6SPhilippe Saint-Pierre
1235adb129eSJérôme Duval echo_mem *
echo_mem_alloc(echo_dev * card,size_t size)1245adb129eSJérôme Duval echo_mem_alloc(echo_dev *card, size_t size)
1255adb129eSJérôme Duval {
1265adb129eSJérôme Duval echo_mem *mem;
1275adb129eSJérôme Duval
1285adb129eSJérôme Duval mem = echo_mem_new(card, size);
1295adb129eSJérôme Duval if (mem == NULL)
1305adb129eSJérôme Duval return (NULL);
1315adb129eSJérôme Duval
1325adb129eSJérôme Duval LIST_INSERT_HEAD(&(card->mems), mem, next);
1335adb129eSJérôme Duval
1345adb129eSJérôme Duval return mem;
1355adb129eSJérôme Duval }
1365adb129eSJérôme Duval
137e480c1b6SPhilippe Saint-Pierre
1385adb129eSJérôme Duval void
echo_mem_free(echo_dev * card,void * ptr)1395adb129eSJérôme Duval echo_mem_free(echo_dev *card, void *ptr)
1405adb129eSJérôme Duval {
1415adb129eSJérôme Duval echo_mem *mem;
1425adb129eSJérôme Duval
1435adb129eSJérôme Duval LIST_FOREACH(mem, &card->mems, next) {
1445adb129eSJérôme Duval if (mem->log_base != ptr)
1455adb129eSJérôme Duval continue;
1465adb129eSJérôme Duval LIST_REMOVE(mem, next);
1475adb129eSJérôme Duval
1485adb129eSJérôme Duval echo_mem_delete(mem);
1495adb129eSJérôme Duval break;
1505adb129eSJérôme Duval }
1515adb129eSJérôme Duval }
1525adb129eSJérôme Duval
1535adb129eSJérôme Duval /* Echo stream functions */
1545adb129eSJérôme Duval
1559524098cSshatty extern char *pStatusStrs[ECHOSTATUS_LAST];
1569524098cSshatty
1575adb129eSJérôme Duval status_t
echo_stream_set_audioparms(echo_stream * stream,uint8 channels,uint8 bitsPerSample,uint32 sample_rate,uint8 index)1585adb129eSJérôme Duval echo_stream_set_audioparms(echo_stream *stream, uint8 channels,
159c9002531SJérôme Duval uint8 bitsPerSample, uint32 sample_rate, uint8 index)
1605adb129eSJérôme Duval {
1615adb129eSJérôme Duval int32 i;
1625adb129eSJérôme Duval uint8 sample_size, frame_size;
1635adb129eSJérôme Duval ECHOGALS_OPENAUDIOPARAMETERS open_params;
1645adb129eSJérôme Duval ECHOGALS_CLOSEAUDIOPARAMETERS close_params;
1655adb129eSJérôme Duval ECHOGALS_AUDIOFORMAT format_params;
1669524098cSshatty ECHOSTATUS status;
1675adb129eSJérôme Duval
1685adb129eSJérôme Duval LOG(("echo_stream_set_audioparms\n"));
1695adb129eSJérôme Duval
1704aeaaaaeSJérôme Duval if (stream->pipe >= 0) {
1715adb129eSJérôme Duval close_params.wPipeIndex = stream->pipe;
1729524098cSshatty status = stream->card->pEG->CloseAudio(&close_params);
1732eabcdebSshatty if (status != ECHOSTATUS_OK && status != ECHOSTATUS_CHANNEL_NOT_OPEN) {
1749524098cSshatty PRINT(("echo_stream_set_audioparms : CloseAudio failed\n"));
1755608ef1aSJérôme Duval PRINT((" status: %s \n", pStatusStrs[status]));
1769524098cSshatty return B_ERROR;
1779524098cSshatty }
1784aeaaaaeSJérôme Duval }
1795adb129eSJérôme Duval
1805adb129eSJérôme Duval open_params.bIsCyclic = TRUE;
181c9002531SJérôme Duval open_params.Pipe.nPipe = index;
1825adb129eSJérôme Duval open_params.Pipe.bIsInput = stream->use == ECHO_USE_RECORD ? TRUE : FALSE;
18304980002Sshatty open_params.Pipe.wInterleave = channels;
18404980002Sshatty open_params.ProcessId = NULL;
1855adb129eSJérôme Duval
1869524098cSshatty status = stream->card->pEG->OpenAudio(&open_params, &stream->pipe);
1879524098cSshatty if (status != ECHOSTATUS_OK) {
1889524098cSshatty PRINT(("echo_stream_set_audioparms : OpenAudio failed\n"));
189c9002531SJérôme Duval PRINT((" status: %s \n", pStatusStrs[status]));
1909524098cSshatty return B_ERROR;
1919524098cSshatty }
1925adb129eSJérôme Duval
19392b10541Sshatty //PRINT(("VerifyAudioOpen\n"));
1942eabcdebSshatty status = stream->card->pEG->VerifyAudioOpen(stream->pipe);
1952eabcdebSshatty if (status != ECHOSTATUS_OK) {
1962eabcdebSshatty PRINT(("echo_stream_set_audioparms : VerifyAudioOpen failed\n"));
197c9002531SJérôme Duval PRINT((" status: %s \n", pStatusStrs[status]));
1982eabcdebSshatty return B_ERROR;
1992eabcdebSshatty }
200f0a85f97SJérôme Duval
201f0a85f97SJérôme Duval if (bitsPerSample == 24)
202f0a85f97SJérôme Duval bitsPerSample = 32;
2032eabcdebSshatty
204ac0b3253SJérôme Duval if ((stream->channels == channels)
205ac0b3253SJérôme Duval && (stream->bitsPerSample == bitsPerSample)
206ac0b3253SJérôme Duval && (stream->sample_rate == sample_rate))
2075adb129eSJérôme Duval return B_OK;
2085adb129eSJérôme Duval
20904980002Sshatty format_params.wBitsPerSample = bitsPerSample;
2105adb129eSJérôme Duval format_params.byDataAreBigEndian = 0;
2115adb129eSJérôme Duval format_params.byMonoToStereo = 0;
2125adb129eSJérôme Duval format_params.wDataInterleave = channels == 1 ? 1 : 2;
2135adb129eSJérôme Duval
2149524098cSshatty status = stream->card->pEG->QueryAudioFormat(stream->pipe, &format_params);
2159524098cSshatty if (status != ECHOSTATUS_OK) {
2165adb129eSJérôme Duval PRINT(("echo_stream_set_audioparms : bad format when querying\n"));
217c9002531SJérôme Duval PRINT((" status: %s \n", pStatusStrs[status]));
2185adb129eSJérôme Duval return B_ERROR;
2195adb129eSJérôme Duval }
2205adb129eSJérôme Duval
22104980002Sshatty status = stream->card->pEG->SetAudioFormat(stream->pipe, &format_params);
2229524098cSshatty if (status != ECHOSTATUS_OK) {
22304980002Sshatty PRINT(("echo_stream_set_audioparms : bad format when setting\n"));
224c9002531SJérôme Duval PRINT((" status: %s \n", pStatusStrs[status]));
2255adb129eSJérôme Duval return B_ERROR;
2265adb129eSJérôme Duval }
2275adb129eSJérôme Duval
22804980002Sshatty /* XXXX : setting sample rate is global in this driver */
22904980002Sshatty status = stream->card->pEG->QueryAudioSampleRate(sample_rate);
2309524098cSshatty if (status != ECHOSTATUS_OK) {
23104980002Sshatty PRINT(("echo_stream_set_audioparms : bad sample rate when querying\n"));
232c9002531SJérôme Duval PRINT((" status: %s \n", pStatusStrs[status]));
2335adb129eSJérôme Duval return B_ERROR;
2345adb129eSJérôme Duval }
2355adb129eSJérôme Duval
2365adb129eSJérôme Duval /* XXXX : setting sample rate is global in this driver */
2379524098cSshatty status = stream->card->pEG->SetAudioSampleRate(sample_rate);
2389524098cSshatty if (status != ECHOSTATUS_OK) {
2395adb129eSJérôme Duval PRINT(("echo_stream_set_audioparms : bad sample rate when setting\n"));
2409524098cSshatty PRINT((" status: %s \n", pStatusStrs[status]));
2415adb129eSJérôme Duval return B_ERROR;
2425adb129eSJérôme Duval }
2435adb129eSJérôme Duval
2445adb129eSJérôme Duval if (stream->buffer)
2455adb129eSJérôme Duval echo_mem_free(stream->card, stream->buffer->log_base);
2465adb129eSJérôme Duval
24704980002Sshatty stream->bitsPerSample = bitsPerSample;
2485adb129eSJérôme Duval stream->sample_rate = sample_rate;
2495adb129eSJérôme Duval stream->channels = channels;
2505adb129eSJérôme Duval
25104980002Sshatty sample_size = stream->bitsPerSample / 8;
2525adb129eSJérôme Duval frame_size = sample_size * stream->channels;
2535adb129eSJérôme Duval
254e480c1b6SPhilippe Saint-Pierre stream->buffer = echo_mem_alloc(stream->card,
255e480c1b6SPhilippe Saint-Pierre stream->bufframes * frame_size * stream->bufcount);
2565adb129eSJérôme Duval
25792b10541Sshatty stream->trigblk = 1;
2585adb129eSJérôme Duval stream->blkmod = stream->bufcount;
2595adb129eSJérôme Duval stream->blksize = stream->bufframes * frame_size;
2605adb129eSJérôme Duval
2615adb129eSJérôme Duval CDaffyDuck *duck = stream->card->pEG->GetDaffyDuck(stream->pipe);
2625adb129eSJérôme Duval if (duck == NULL) {
2635adb129eSJérôme Duval PRINT(("echo_stream_set_audioparms : Could not get daffy duck pointer\n"));
2645adb129eSJérôme Duval return B_ERROR;
2655adb129eSJérôme Duval }
2665adb129eSJérôme Duval
2675adb129eSJérôme Duval uint32 dwNumFreeEntries = 0;
2685adb129eSJérôme Duval
2695adb129eSJérôme Duval for (i = 0; i < stream->bufcount; i++) {
2705adb129eSJérôme Duval duck->AddMapping(((uint32)stream->buffer->phy_base) +
2715adb129eSJérôme Duval i * stream->blksize, stream->blksize, 0, TRUE, dwNumFreeEntries);
2725adb129eSJérôme Duval }
2735adb129eSJérôme Duval
2745adb129eSJérôme Duval duck->Wrap();
2755adb129eSJérôme Duval
2765adb129eSJérôme Duval if (stream->card->pEG->GetAudioPositionPtr(stream->pipe, stream->position)!=ECHOSTATUS_OK) {
2775adb129eSJérôme Duval PRINT(("echo_stream_set_audioparms : Could not get audio position ptr\n"));
2785adb129eSJérôme Duval return B_ERROR;
2795adb129eSJérôme Duval }
2805adb129eSJérôme Duval
2815adb129eSJérôme Duval return B_OK;
2825adb129eSJérôme Duval }
2835adb129eSJérôme Duval
2845adb129eSJérôme Duval
2855adb129eSJérôme Duval status_t
echo_stream_get_nth_buffer(echo_stream * stream,uint8 chan,uint8 buf,char ** buffer,size_t * stride)2865adb129eSJérôme Duval echo_stream_get_nth_buffer(echo_stream *stream, uint8 chan, uint8 buf,
2875adb129eSJérôme Duval char** buffer, size_t *stride)
2885adb129eSJérôme Duval {
2895adb129eSJérôme Duval uint8 sample_size, frame_size;
2905adb129eSJérôme Duval LOG(("echo_stream_get_nth_buffer\n"));
2915adb129eSJérôme Duval
29204980002Sshatty sample_size = stream->bitsPerSample / 8;
2935adb129eSJérôme Duval frame_size = sample_size * stream->channels;
2945adb129eSJérôme Duval
2955adb129eSJérôme Duval *buffer = (char*)stream->buffer->log_base + (buf * stream->bufframes * frame_size)
2965adb129eSJérôme Duval + chan * sample_size;
2975adb129eSJérôme Duval *stride = frame_size;
2985adb129eSJérôme Duval
2995adb129eSJérôme Duval return B_OK;
3005adb129eSJérôme Duval }
3015adb129eSJérôme Duval
3025adb129eSJérôme Duval
3035adb129eSJérôme Duval static uint32
echo_stream_curaddr(echo_stream * stream)3045adb129eSJérôme Duval echo_stream_curaddr(echo_stream *stream)
3055adb129eSJérôme Duval {
30692b10541Sshatty uint32 addr = B_LENDIAN_TO_HOST_INT32(*stream->position);
30792b10541Sshatty // TRACE(("stream_curaddr %p, phy_base %p\n", addr));
308da249551Sshatty return (addr / stream->blksize) % stream->blkmod;
3095adb129eSJérôme Duval }
3105adb129eSJérôme Duval
3115adb129eSJérôme Duval
3125adb129eSJérôme Duval void
echo_stream_start(echo_stream * stream,void (* inth)(void *),void * inthparam)3135adb129eSJérôme Duval echo_stream_start(echo_stream *stream, void (*inth) (void *), void *inthparam)
3145adb129eSJérôme Duval {
3155adb129eSJérôme Duval LOG(("echo_stream_start\n"));
3165608ef1aSJérôme Duval ECHOSTATUS status;
3175adb129eSJérôme Duval
3185adb129eSJérôme Duval stream->inth = inth;
3195adb129eSJérôme Duval stream->inthparam = inthparam;
3205adb129eSJérôme Duval
3215adb129eSJérôme Duval stream->state |= ECHO_STATE_STARTED;
3225adb129eSJérôme Duval
3235608ef1aSJérôme Duval status = stream->card->pEG->Start(stream->pipe);
3245608ef1aSJérôme Duval if (status!=ECHOSTATUS_OK) {
3255608ef1aSJérôme Duval PRINT(("echo_stream_start : Could not start the pipe %s\n", pStatusStrs[status]));
3265adb129eSJérôme Duval }
3275adb129eSJérôme Duval }
3285adb129eSJérôme Duval
329e480c1b6SPhilippe Saint-Pierre
3305adb129eSJérôme Duval void
echo_stream_halt(echo_stream * stream)3315adb129eSJérôme Duval echo_stream_halt(echo_stream *stream)
3325adb129eSJérôme Duval {
3335adb129eSJérôme Duval LOG(("echo_stream_halt\n"));
3345608ef1aSJérôme Duval ECHOSTATUS status;
3355adb129eSJérôme Duval
3365adb129eSJérôme Duval stream->state &= ~ECHO_STATE_STARTED;
3375adb129eSJérôme Duval
3385608ef1aSJérôme Duval status = stream->card->pEG->Stop(stream->pipe);
3395608ef1aSJérôme Duval if (status!=ECHOSTATUS_OK) {
3405608ef1aSJérôme Duval PRINT(("echo_stream_halt : Could not stop the pipe %s\n", pStatusStrs[status]));
3415adb129eSJérôme Duval }
3425adb129eSJérôme Duval }
3435adb129eSJérôme Duval
344e480c1b6SPhilippe Saint-Pierre
3455adb129eSJérôme Duval echo_stream *
echo_stream_new(echo_dev * card,uint8 use,uint32 bufframes,uint8 bufcount)3465adb129eSJérôme Duval echo_stream_new(echo_dev *card, uint8 use, uint32 bufframes, uint8 bufcount)
3475adb129eSJérôme Duval {
3485adb129eSJérôme Duval echo_stream *stream;
3495adb129eSJérôme Duval cpu_status status;
3505adb129eSJérôme Duval LOG(("echo_stream_new\n"));
3515adb129eSJérôme Duval
3525adb129eSJérôme Duval stream = (echo_stream *) malloc(sizeof(echo_stream));
3535adb129eSJérôme Duval if (stream == NULL)
3545adb129eSJérôme Duval return (NULL);
3555adb129eSJérôme Duval stream->card = card;
3565adb129eSJérôme Duval stream->use = use;
357*d3503944SPulkoMandy stream->state = 0;
35804980002Sshatty stream->bitsPerSample = 0;
3595adb129eSJérôme Duval stream->sample_rate = 0;
3605adb129eSJérôme Duval stream->channels = 0;
3615adb129eSJérôme Duval stream->bufframes = bufframes;
3625adb129eSJérôme Duval stream->bufcount = bufcount;
3635adb129eSJérôme Duval stream->inth = NULL;
3645adb129eSJérôme Duval stream->inthparam = NULL;
3655adb129eSJérôme Duval stream->buffer = NULL;
3665adb129eSJérôme Duval stream->blksize = 0;
3675adb129eSJérôme Duval stream->trigblk = 0;
3685adb129eSJérôme Duval stream->blkmod = 0;
3695adb129eSJérôme Duval
3705608ef1aSJérôme Duval stream->pipe = -1;
3715adb129eSJérôme Duval
3725adb129eSJérôme Duval stream->frames_count = 0;
3735adb129eSJérôme Duval stream->real_time = 0;
37481a7deddSJérôme Duval stream->buffer_cycle = 0;
3755adb129eSJérôme Duval stream->update_needed = false;
3765adb129eSJérôme Duval
3775adb129eSJérôme Duval status = lock();
3785adb129eSJérôme Duval LIST_INSERT_HEAD((&card->streams), stream, next);
3795adb129eSJérôme Duval unlock(status);
3805adb129eSJérôme Duval
3815adb129eSJérôme Duval return stream;
3825adb129eSJérôme Duval }
3835adb129eSJérôme Duval
384e480c1b6SPhilippe Saint-Pierre
3855adb129eSJérôme Duval void
echo_stream_delete(echo_stream * stream)3865adb129eSJérôme Duval echo_stream_delete(echo_stream *stream)
3875adb129eSJérôme Duval {
3885adb129eSJérôme Duval cpu_status status;
389b5f75a7eSJérôme Duval ECHOGALS_CLOSEAUDIOPARAMETERS close_params;
3905adb129eSJérôme Duval LOG(("echo_stream_delete\n"));
3915adb129eSJérôme Duval
3925adb129eSJérôme Duval echo_stream_halt(stream);
3935adb129eSJérôme Duval
394b5f75a7eSJérôme Duval if (stream->pipe >= 0) {
395b5f75a7eSJérôme Duval close_params.wPipeIndex = stream->pipe;
396b5f75a7eSJérôme Duval status = stream->card->pEG->CloseAudio(&close_params);
397b5f75a7eSJérôme Duval if (status != ECHOSTATUS_OK && status != ECHOSTATUS_CHANNEL_NOT_OPEN) {
398b5f75a7eSJérôme Duval PRINT(("echo_stream_set_audioparms : CloseAudio failed\n"));
399b5f75a7eSJérôme Duval PRINT((" status: %s \n", pStatusStrs[status]));
400b5f75a7eSJérôme Duval }
401b5f75a7eSJérôme Duval }
402b5f75a7eSJérôme Duval
4035adb129eSJérôme Duval if (stream->buffer)
4045adb129eSJérôme Duval echo_mem_free(stream->card, stream->buffer->log_base);
4055adb129eSJérôme Duval
4065adb129eSJérôme Duval status = lock();
4075adb129eSJérôme Duval LIST_REMOVE(stream, next);
4085adb129eSJérôme Duval unlock(status);
4095adb129eSJérôme Duval
4105adb129eSJérôme Duval free(stream);
4115adb129eSJérôme Duval }
4125adb129eSJérôme Duval
4135adb129eSJérôme Duval
4145adb129eSJérôme Duval /* Echo interrupt */
4155adb129eSJérôme Duval
echo_int(void * arg)4165adb129eSJérôme Duval int32 echo_int(void *arg)
4175adb129eSJérôme Duval {
4185adb129eSJérôme Duval echo_dev* card = (echo_dev*)arg;
4195adb129eSJérôme Duval BOOL midiReceived;
4205adb129eSJérôme Duval ECHOSTATUS err;
4215adb129eSJérôme Duval echo_stream* stream;
4225adb129eSJérôme Duval uint32 curblk;
4235adb129eSJérôme Duval
4245adb129eSJérôme Duval err = card->pEG->ServiceIrq(midiReceived);
4255adb129eSJérôme Duval
42692b10541Sshatty if (err != ECHOSTATUS_OK) {
42792b10541Sshatty return B_UNHANDLED_INTERRUPT;
42892b10541Sshatty }
42992b10541Sshatty
4300bb683faSJérôme Duval #ifdef MIDI_SUPPORT
4310bb683faSJérôme Duval if (midiReceived)
43289f3467fSJérôme Duval release_sem_etc(card->midi.midi_ready_sem, 1, B_DO_NOT_RESCHEDULE);
4330bb683faSJérôme Duval #endif
4340bb683faSJérôme Duval
4355adb129eSJérôme Duval LIST_FOREACH(stream, &card->streams, next) {
43692b10541Sshatty if ((stream->state & ECHO_STATE_STARTED) == 0 ||
4375adb129eSJérôme Duval (stream->inth == NULL))
4385adb129eSJérôme Duval continue;
4395adb129eSJérôme Duval
440da249551Sshatty curblk = echo_stream_curaddr(stream);
441da249551Sshatty //TRACE(("echo_int stream %p at trigblk %lu at stream->trigblk %lu\n",
442da249551Sshatty // stream, curblk, stream->trigblk));
4435adb129eSJérôme Duval if (curblk == stream->trigblk) {
4445adb129eSJérôme Duval if (stream->inth)
4455adb129eSJérôme Duval stream->inth(stream->inthparam);
4465adb129eSJérôme Duval
4475adb129eSJérôme Duval stream->trigblk++;
448da249551Sshatty stream->trigblk %= stream->blkmod;
4495adb129eSJérôme Duval }
4505adb129eSJérôme Duval }
4515adb129eSJérôme Duval
45292b10541Sshatty return B_INVOKE_SCHEDULER;
4535adb129eSJérôme Duval }
4545adb129eSJérôme Duval
455c9002531SJérôme Duval /* dumps card capabilities */
456c9002531SJérôme Duval void
echo_dump_caps(echo_dev * card)457c9002531SJérôme Duval echo_dump_caps(echo_dev *card)
458c9002531SJérôme Duval {
459c9002531SJérôme Duval PECHOGALS_CAPS caps = &card->caps;
460c9002531SJérôme Duval PRINT(("name: %s\n", caps->szName));
461c9002531SJérôme Duval PRINT(("out pipes: %d, in pipes: %d, out busses: %d, in busses: %d, out midi: %d, in midi: %d\n",
462c9002531SJérôme Duval caps->wNumPipesOut, caps->wNumPipesIn, caps->wNumBussesOut, caps->wNumBussesIn, caps->wNumMidiOut, caps->wNumMidiIn));
463c9002531SJérôme Duval
464c9002531SJérôme Duval }
465c9002531SJérôme Duval
466c9002531SJérôme Duval
4675adb129eSJérôme Duval /* detect presence of our hardware */
4685adb129eSJérôme Duval status_t
init_hardware(void)4695adb129eSJérôme Duval init_hardware(void)
4705adb129eSJérôme Duval {
471ec816dffSJérôme Duval #ifdef CARDBUS
472ec816dffSJérôme Duval return B_OK;
473ec816dffSJérôme Duval #else
4745adb129eSJérôme Duval int ix = 0;
4755adb129eSJérôme Duval pci_info info;
4765adb129eSJérôme Duval status_t err = ENODEV;
4775adb129eSJérôme Duval
4785adb129eSJérôme Duval LOG_CREATE();
4795adb129eSJérôme Duval
4805adb129eSJérôme Duval PRINT(("init_hardware()\n"));
4815adb129eSJérôme Duval
48215a2aa68SJérôme Duval if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci))
4835adb129eSJérôme Duval return ENOSYS;
4845adb129eSJérôme Duval
4855adb129eSJérôme Duval while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) {
4865adb129eSJérôme Duval
4875adb129eSJérôme Duval ushort card_type = info.u.h0.subsystem_id & 0xfff0;
4885adb129eSJérôme Duval
489ac0b3253SJérôme Duval if (info.vendor_id == VENDOR_ID
490ac0b3253SJérôme Duval && ((info.device_id == DEVICE_ID_56301)
491ac0b3253SJérôme Duval || (info.device_id == DEVICE_ID_56361))
492ac0b3253SJérôme Duval && (info.u.h0.subsystem_vendor_id == SUBVENDOR_ID)
493ac0b3253SJérôme Duval && (
4945adb129eSJérôme Duval #ifdef ECHOGALS_FAMILY
4955adb129eSJérôme Duval (card_type == DARLA)
4965adb129eSJérôme Duval || (card_type == GINA)
4975adb129eSJérôme Duval || (card_type == LAYLA)
4985adb129eSJérôme Duval || (card_type == DARLA24)
4995adb129eSJérôme Duval #endif
5005adb129eSJérôme Duval #ifdef ECHO24_FAMILY
5015adb129eSJérôme Duval (card_type == GINA24)
5025adb129eSJérôme Duval || (card_type == LAYLA24)
5035adb129eSJérôme Duval || (card_type == MONA)
5045adb129eSJérôme Duval || (card_type == MIA)
50508661eb2SJérôme Duval #endif
50608661eb2SJérôme Duval #ifdef INDIGO_FAMILY
50708661eb2SJérôme Duval (card_type == INDIGO)
508c2ddc71cSJérôme Duval || (card_type == INDIGO_IO)
509c2ddc71cSJérôme Duval || (card_type == INDIGO_DJ)
51008661eb2SJérôme Duval #endif
51108661eb2SJérôme Duval #ifdef ECHO3G_FAMILY
51208661eb2SJérôme Duval (card_type == ECHO3G)
5135adb129eSJérôme Duval #endif
5145adb129eSJérôme Duval )) {
5155adb129eSJérôme Duval err = B_OK;
5165adb129eSJérôme Duval }
5175adb129eSJérôme Duval ix++;
5185adb129eSJérôme Duval }
5195adb129eSJérôme Duval
52015a2aa68SJérôme Duval put_module(B_PCI_MODULE_NAME);
5215adb129eSJérôme Duval
5225adb129eSJérôme Duval if (err != B_OK) {
5235adb129eSJérôme Duval PRINT(("no card found\n"));
5245adb129eSJérôme Duval }
5255adb129eSJérôme Duval
5265adb129eSJérôme Duval return err;
527ec816dffSJérôme Duval #endif
5285adb129eSJérôme Duval }
5295adb129eSJérôme Duval
5305adb129eSJérôme Duval
5315adb129eSJérôme Duval status_t
init_driver(void)5325adb129eSJérôme Duval init_driver(void)
5335adb129eSJérôme Duval {
534bd9d5861SJérôme Duval PRINT(("init_driver()\n"));
535bd9d5861SJérôme Duval
536ec816dffSJérôme Duval #ifdef CARDBUS
537ec816dffSJérôme Duval // Get card services client module
538ec816dffSJérôme Duval if (get_module(CB_ENABLER_MODULE_NAME, (module_info **)&cbemi) != B_OK) {
539ec816dffSJérôme Duval dprintf(DRIVER_NAME ": cardbus enabler module error\n");
54015a2aa68SJérôme Duval return B_ERROR;
541ec816dffSJérôme Duval }
542ec816dffSJérôme Duval // Create the devices lock
543ec816dffSJérôme Duval device_lock = create_sem(1, DRIVER_NAME " device");
544ec816dffSJérôme Duval if (device_lock < B_OK) {
545ec816dffSJérôme Duval dprintf(DRIVER_NAME ": create device semaphore error 0x%.8x\n", device_lock);
546ec816dffSJérôme Duval put_module(CB_ENABLER_MODULE_NAME);
54715a2aa68SJérôme Duval return B_ERROR;
548ec816dffSJérôme Duval }
549ec816dffSJérôme Duval // Register driver
550ec816dffSJérôme Duval cbemi->register_driver(DRIVER_NAME, descriptors, COUNT_DESCRIPTOR);
551ec816dffSJérôme Duval cbemi->install_notify(DRIVER_NAME, &cardbus_hooks);
552ec816dffSJérôme Duval LIST_INIT(&(devices));
553ec816dffSJérôme Duval return B_OK;
554ec816dffSJérôme Duval #else
5555adb129eSJérôme Duval int ix = 0;
5565adb129eSJérôme Duval
5575adb129eSJérôme Duval pci_info info;
558bbb55d15SFrançois Revol status_t err;
5595adb129eSJérôme Duval num_cards = 0;
5605adb129eSJérôme Duval
56115a2aa68SJérôme Duval if (get_module(B_PCI_MODULE_NAME, (module_info **) &pci))
5625adb129eSJérôme Duval return ENOSYS;
5635adb129eSJérôme Duval
564ee9a07fcSFrançois Revol while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) {
5655adb129eSJérôme Duval ushort card_type = info.u.h0.subsystem_id & 0xfff0;
5665adb129eSJérôme Duval
567ac0b3253SJérôme Duval if (info.vendor_id == VENDOR_ID
568ac0b3253SJérôme Duval && ((info.device_id == DEVICE_ID_56301)
569ac0b3253SJérôme Duval || (info.device_id == DEVICE_ID_56361))
570ac0b3253SJérôme Duval && (info.u.h0.subsystem_vendor_id == SUBVENDOR_ID)
571ac0b3253SJérôme Duval && (
5725adb129eSJérôme Duval #ifdef ECHOGALS_FAMILY
5735adb129eSJérôme Duval (card_type == DARLA)
5745adb129eSJérôme Duval || (card_type == GINA)
5755adb129eSJérôme Duval || (card_type == LAYLA)
5765adb129eSJérôme Duval || (card_type == DARLA24)
5775adb129eSJérôme Duval #endif
5785adb129eSJérôme Duval #ifdef ECHO24_FAMILY
5795adb129eSJérôme Duval (card_type == GINA24)
5805adb129eSJérôme Duval || (card_type == LAYLA24)
5815adb129eSJérôme Duval || (card_type == MONA)
5825adb129eSJérôme Duval || (card_type == MIA)
58308661eb2SJérôme Duval #endif
58408661eb2SJérôme Duval #ifdef INDIGO_FAMILY
58508661eb2SJérôme Duval (card_type == INDIGO)
586c2ddc71cSJérôme Duval || (card_type == INDIGO_IO)
587c2ddc71cSJérôme Duval || (card_type == INDIGO_DJ)
58808661eb2SJérôme Duval #endif
58908661eb2SJérôme Duval #ifdef ECHO3G_FAMILY
59008661eb2SJérôme Duval (card_type == ECHO3G)
5915adb129eSJérôme Duval #endif
5925adb129eSJérôme Duval )) {
5935adb129eSJérôme Duval
5945adb129eSJérôme Duval if (num_cards == NUM_CARDS) {
5955adb129eSJérôme Duval PRINT(("Too many " DRIVER_NAME " cards installed!\n"));
5965adb129eSJérôme Duval break;
5975adb129eSJérôme Duval }
5985adb129eSJérôme Duval memset(&cards[num_cards], 0, sizeof(echo_dev));
5995adb129eSJérôme Duval cards[num_cards].info = info;
6005adb129eSJérôme Duval cards[num_cards].type = card_type;
601bbb55d15SFrançois Revol #ifdef __HAIKU__
602bbb55d15SFrançois Revol if ((err = (*pci->reserve_device)(info.bus, info.device, info.function,
603bbb55d15SFrançois Revol DRIVER_NAME, &cards[num_cards])) < B_OK) {
604bbb55d15SFrançois Revol dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n",
605bbb55d15SFrançois Revol DRIVER_NAME, info.bus, info.device, info.function,
606bbb55d15SFrançois Revol strerror(err));
607bbb55d15SFrançois Revol continue;
608bbb55d15SFrançois Revol }
609bbb55d15SFrançois Revol #endif
6105adb129eSJérôme Duval if (echo_setup(&cards[num_cards])) {
611*d3503944SPulkoMandy PRINT(("Setup of " DRIVER_NAME " %" B_PRId32 " failed\n", num_cards + 1));
612bbb55d15SFrançois Revol #ifdef __HAIKU__
613bbb55d15SFrançois Revol (*pci->unreserve_device)(info.bus, info.device, info.function,
614bbb55d15SFrançois Revol DRIVER_NAME, &cards[num_cards]);
615bbb55d15SFrançois Revol #endif
6165adb129eSJérôme Duval }
6175adb129eSJérôme Duval else {
6185adb129eSJérôme Duval num_cards++;
6195adb129eSJérôme Duval }
6205adb129eSJérôme Duval }
6215adb129eSJérôme Duval }
6225adb129eSJérôme Duval if (!num_cards) {
6235adb129eSJérôme Duval PRINT(("no cards\n"));
62415a2aa68SJérôme Duval put_module(B_PCI_MODULE_NAME);
6255adb129eSJérôme Duval PRINT(("no suitable cards found\n"));
6265adb129eSJérôme Duval return ENODEV;
6275adb129eSJérôme Duval }
6285adb129eSJérôme Duval
6295adb129eSJérôme Duval return B_OK;
630ec816dffSJérôme Duval #endif
6315adb129eSJérôme Duval }
6325adb129eSJérôme Duval
6335adb129eSJérôme Duval
634ec816dffSJérôme Duval #ifndef CARDBUS
6355adb129eSJérôme Duval static void
make_device_names(echo_dev * card)636e480c1b6SPhilippe Saint-Pierre make_device_names(echo_dev * card)
6375adb129eSJérôme Duval {
6380bb683faSJérôme Duval #ifdef MIDI_SUPPORT
6390bb683faSJérôme Duval sprintf(card->midi.name, "midi/" DRIVER_NAME "/%ld", card-cards + 1);
6400bb683faSJérôme Duval names[num_names++] = card->midi.name;
6410bb683faSJérôme Duval #endif
6423f047e87SJérôme Duval sprintf(card->name, "audio/hmulti/" DRIVER_NAME "/%ld", card-cards + 1);
6435adb129eSJérôme Duval names[num_names++] = card->name;
6445adb129eSJérôme Duval
6455adb129eSJérôme Duval names[num_names] = NULL;
6465adb129eSJérôme Duval }
647ec816dffSJérôme Duval #else
648ec816dffSJérôme Duval
649ec816dffSJérôme Duval status_t
cardbus_device_added(pci_info * info,void ** cookie)650ec816dffSJérôme Duval cardbus_device_added(pci_info *info, void **cookie) {
651ec816dffSJérôme Duval echo_dev * card, *dev;
652ec816dffSJérôme Duval uint32 index;
653ec816dffSJérôme Duval char buffer[32];
654ec816dffSJérôme Duval
655ec816dffSJérôme Duval LOG(("cardbus_device_added at %.2d:%.2d:%.2d\n", info->bus, info->device, info->function));
656ec816dffSJérôme Duval // Allocate cookie
657ec816dffSJérôme Duval if (!(*cookie = card = (echo_dev *)malloc(sizeof(echo_dev)))) {
658ec816dffSJérôme Duval return B_NO_MEMORY;
659ec816dffSJérôme Duval }
660ec816dffSJérôme Duval // Clear cookie
661ec816dffSJérôme Duval memset(card, 0, sizeof(echo_dev));
662ec816dffSJérôme Duval // Initialize cookie
663ec816dffSJérôme Duval card->info = *info;
664ec816dffSJérôme Duval card->plugged = true;
665ec816dffSJérôme Duval card->index = 0;
666ec816dffSJérôme Duval
667ec816dffSJérôme Duval LIST_FOREACH(dev, &devices, next) {
668ec816dffSJérôme Duval if (dev->index == card->index) {
669ec816dffSJérôme Duval card->index++;
670ec816dffSJérôme Duval dev = LIST_FIRST(&devices);
671ec816dffSJérôme Duval }
672ec816dffSJérôme Duval }
673ec816dffSJérôme Duval
674ec816dffSJérôme Duval // Format device name
6753f047e87SJérôme Duval sprintf(card->name, "audio/hmulti/" DRIVER_NAME "/%ld", card->index);
676ec816dffSJérôme Duval // Lock the devices
677ec816dffSJérôme Duval acquire_sem(device_lock);
678ec816dffSJérôme Duval LIST_INSERT_HEAD((&devices), card, next);
679ec816dffSJérôme Duval // Unlock the devices
680ec816dffSJérôme Duval release_sem(device_lock);
681ec816dffSJérôme Duval
682ec816dffSJérôme Duval echo_setup(card);
683ec816dffSJérôme Duval return B_OK;
684ec816dffSJérôme Duval }
685ec816dffSJérôme Duval
686ec816dffSJérôme Duval
687ec816dffSJérôme Duval // cardbus_device_removed - handle cardbus device removal.
688ec816dffSJérôme Duval // status : OK
689ec816dffSJérôme Duval void
cardbus_device_removed(void * cookie)690ec816dffSJérôme Duval cardbus_device_removed(void *cookie)
691ec816dffSJérôme Duval {
692ec816dffSJérôme Duval echo_dev *card = (echo_dev *) cookie;
693ec816dffSJérôme Duval
694ec816dffSJérôme Duval LOG((": cardbus_device_removed\n"));
695ec816dffSJérôme Duval // Check
696ec816dffSJérôme Duval if (card == NULL) {
697ec816dffSJérôme Duval LOG((": null device 0x%.8x\n", card));
698ec816dffSJérôme Duval return;
699ec816dffSJérôme Duval }
700ec816dffSJérôme Duval
701ec816dffSJérôme Duval echo_shutdown(card);
702ec816dffSJérôme Duval
703ec816dffSJérôme Duval // Lock the devices
704ec816dffSJérôme Duval acquire_sem(device_lock);
705ec816dffSJérôme Duval // Finalize
706ec816dffSJérôme Duval card->plugged = false;
707ec816dffSJérôme Duval // Check if the device is opened
708ec816dffSJérôme Duval if (card->opened) {
709ec816dffSJérôme Duval LOG(("device 0x%.8x %s still in use\n", card, card->name));
710ec816dffSJérôme Duval } else {
711ec816dffSJérôme Duval LOG(("free device 0x%.8x %s\n", card, card->name));
712ec816dffSJérôme Duval LIST_REMOVE(card, next);
713ec816dffSJérôme Duval free(card);
714ec816dffSJérôme Duval }
715ec816dffSJérôme Duval // Unlock the devices
716ec816dffSJérôme Duval release_sem(device_lock);
717ec816dffSJérôme Duval }
718ec816dffSJérôme Duval
719ec816dffSJérôme Duval #endif
7205adb129eSJérôme Duval
7215adb129eSJérôme Duval
7225adb129eSJérôme Duval static status_t
echo_setup(echo_dev * card)7235adb129eSJérôme Duval echo_setup(echo_dev* card)
7245adb129eSJérôme Duval {
7255adb129eSJérôme Duval unsigned char cmd;
726*d3503944SPulkoMandy const char* name;
7275adb129eSJérôme Duval
7285adb129eSJérôme Duval PRINT(("echo_setup(%p)\n", card));
7295adb129eSJérôme Duval
730ec816dffSJérôme Duval #ifndef CARDBUS
731b5d91600SJérôme Duval (*pci->write_pci_config)(card->info.bus, card->info.device,
732b5d91600SJérôme Duval card->info.function, PCI_latency, 1, 0xc0 );
7335adb129eSJérôme Duval
7345adb129eSJérôme Duval make_device_names(card);
735ec816dffSJérôme Duval #endif
7365adb129eSJérôme Duval card->bmbar = card->info.u.h0.base_registers[0];
7375adb129eSJérôme Duval card->irq = card->info.u.h0.interrupt_line;
7385adb129eSJérôme Duval
739ac0b3253SJérôme Duval card->area_bmbar = map_mem(&card->log_bmbar, card->bmbar,
740b5d91600SJérôme Duval card->info.u.h0.base_register_sizes[0], DRIVER_NAME" bmbar io");
741b5d91600SJérôme Duval if (card->area_bmbar <= B_OK) {
742b5d91600SJérôme Duval LOG(("mapping of bmbar io failed, error = %#x\n",card->area_bmbar));
743b5d91600SJérôme Duval goto err5;
744b5d91600SJérôme Duval }
745b5d91600SJérôme Duval LOG(("mapping of bmbar: area %#x, phys %#x, log %#x\n", card->area_bmbar,
746b5d91600SJérôme Duval card->bmbar, card->log_bmbar));
747ec816dffSJérôme Duval
748c2ddc71cSJérôme Duval card->pOSS = new COsSupport(card->info.device_id, card->info.revision);
7495adb129eSJérôme Duval if (card->pOSS == NULL)
750b5d91600SJérôme Duval goto err4;
7515adb129eSJérôme Duval
7525adb129eSJérôme Duval switch (card->type) {
7535adb129eSJérôme Duval #ifdef ECHOGALS_FAMILY
7545adb129eSJérôme Duval case DARLA:
7555adb129eSJérôme Duval card->pEG = new CDarla(card->pOSS);
756c9002531SJérôme Duval name = "Echo Darla";
7575adb129eSJérôme Duval break;
7585adb129eSJérôme Duval case GINA:
7595adb129eSJérôme Duval card->pEG = new CGina(card->pOSS);
760c9002531SJérôme Duval name = "Echo Gina";
7615adb129eSJérôme Duval break;
7625adb129eSJérôme Duval case LAYLA:
7635adb129eSJérôme Duval card->pEG = new CLayla(card->pOSS);
764c9002531SJérôme Duval name = "Echo Layla";
7655adb129eSJérôme Duval break;
7665adb129eSJérôme Duval case DARLA24:
7675adb129eSJérôme Duval card->pEG = new CDarla24(card->pOSS);
768c9002531SJérôme Duval name = "Echo Darla24";
7695adb129eSJérôme Duval break;
7705adb129eSJérôme Duval #endif
7715adb129eSJérôme Duval #ifdef ECHO24_FAMILY
7725adb129eSJérôme Duval case GINA24:
7735adb129eSJérôme Duval card->pEG = new CGina24(card->pOSS);
774c9002531SJérôme Duval name = "Echo Gina24";
7755adb129eSJérôme Duval break;
7765adb129eSJérôme Duval case LAYLA24:
7775adb129eSJérôme Duval card->pEG = new CLayla24(card->pOSS);
778ec816dffSJérôme Duval name = "Echo Layla24";
7795adb129eSJérôme Duval break;
7805adb129eSJérôme Duval case MONA:
7815adb129eSJérôme Duval card->pEG = new CMona(card->pOSS);
782c9002531SJérôme Duval name = "Echo Mona";
7835adb129eSJérôme Duval break;
7845adb129eSJérôme Duval case MIA:
7855adb129eSJérôme Duval card->pEG = new CMia(card->pOSS);
786c9002531SJérôme Duval name = "Echo Mia";
7875adb129eSJérôme Duval break;
78808661eb2SJérôme Duval #endif
78908661eb2SJérôme Duval #ifdef INDIGO_FAMILY
79008661eb2SJérôme Duval case INDIGO:
79108661eb2SJérôme Duval card->pEG = new CIndigo(card->pOSS);
792ec816dffSJérôme Duval name = "Echo Indigo";
79308661eb2SJérôme Duval break;
79408661eb2SJérôme Duval case INDIGO_IO:
79508661eb2SJérôme Duval card->pEG = new CIndigoIO(card->pOSS);
796ec816dffSJérôme Duval name = "Echo IndigoIO";
79708661eb2SJérôme Duval break;
79808661eb2SJérôme Duval case INDIGO_DJ:
79908661eb2SJérôme Duval card->pEG = new CIndigoDJ(card->pOSS);
800ec816dffSJérôme Duval name = "Echo IndigoDJ";
80108661eb2SJérôme Duval break;
80208661eb2SJérôme Duval #endif
80308661eb2SJérôme Duval #ifdef ECHO3G_FAMILY
804c2ddc71cSJérôme Duval case ECHO3G:
805c2ddc71cSJérôme Duval card->pEG = new C3g(card->pOSS);
806c9002531SJérôme Duval name = "Echo 3g";
807c2ddc71cSJérôme Duval break;
8085adb129eSJérôme Duval #endif
8095adb129eSJérôme Duval default:
810b5d91600SJérôme Duval PRINT(("card type 0x%x not supported by " DRIVER_NAME "\n",
811b5d91600SJérôme Duval card->type));
812*d3503944SPulkoMandy name = "Unknown";
8135adb129eSJérôme Duval }
8145adb129eSJérôme Duval
8155adb129eSJérôme Duval if (card->pEG == NULL)
816b5d91600SJérôme Duval goto err2;
8175adb129eSJérôme Duval
818ec816dffSJérôme Duval #ifndef CARDBUS
819b5d91600SJérôme Duval cmd = (*pci->read_pci_config)(card->info.bus, card->info.device,
820b5d91600SJérôme Duval card->info.function, PCI_command, 2);
8215adb129eSJérôme Duval PRINT(("PCI command before: %x\n", cmd));
822b5d91600SJérôme Duval (*pci->write_pci_config)(card->info.bus, card->info.device,
823b5d91600SJérôme Duval card->info.function, PCI_command, 2, cmd | PCI_command_io);
824b5d91600SJérôme Duval cmd = (*pci->read_pci_config)(card->info.bus, card->info.device,
825b5d91600SJérôme Duval card->info.function, PCI_command, 2);
8265adb129eSJérôme Duval PRINT(("PCI command after: %x\n", cmd));
827ec816dffSJérôme Duval #endif
8285adb129eSJérôme Duval
829c9002531SJérôme Duval card->pEG->AssignResources(card->log_bmbar, name);
8305adb129eSJérôme Duval
8315adb129eSJérôme Duval ECHOSTATUS status;
8325adb129eSJérôme Duval status = card->pEG->InitHw();
8335adb129eSJérôme Duval if (status != ECHOSTATUS_OK)
834b5d91600SJérôme Duval goto err3;
8355adb129eSJérôme Duval
836c9002531SJérôme Duval card->pEG->GetCapabilities(&card->caps);
837c9002531SJérôme Duval
8385adb129eSJérôme Duval /* Init streams list */
8395adb129eSJérôme Duval LIST_INIT(&(card->streams));
8405adb129eSJérôme Duval
8415adb129eSJérôme Duval /* Init mems list */
8425adb129eSJérôme Duval LIST_INIT(&(card->mems));
8435adb129eSJérôme Duval
8440bb683faSJérôme Duval #ifdef MIDI_SUPPORT
8450bb683faSJérôme Duval card->midi.midi_ready_sem = create_sem(0, "midi sem");
8460bb683faSJérôme Duval #endif
8470bb683faSJérôme Duval
8485adb129eSJérôme Duval PRINT(("installing interrupt : %x\n", card->irq));
849b5d91600SJérôme Duval status = install_io_interrupt_handler(card->irq, echo_int, card, 0);
850b5d91600SJérôme Duval if (status != B_OK) {
851b5d91600SJérôme Duval PRINT(("failed to install interrupt\n"));
852b5d91600SJérôme Duval goto err2;
853b5d91600SJérôme Duval }
8545adb129eSJérôme Duval
8555adb129eSJérôme Duval PRINT(("echo_setup done\n"));
8565adb129eSJérôme Duval
857c9002531SJérôme Duval echo_dump_caps(card);
858c9002531SJérôme Duval
85908661eb2SJérôme Duval #ifdef ECHO3G_FAMILY
860a2f1c2e0SJérôme Duval if (card->type == ECHO3G) {
861e480c1b6SPhilippe Saint-Pierre strlcpy(card->caps.szName, ((C3g*)card->pEG)->Get3gBoxName(),
862b5d91600SJérôme Duval ECHO_MAXNAMELEN);
863a2f1c2e0SJérôme Duval }
864a2f1c2e0SJérôme Duval #endif
865a2f1c2e0SJérôme Duval
866c9002531SJérôme Duval status = card->pEG->OpenMixer(card->mixer);
867b5d91600SJérôme Duval if (status != ECHOSTATUS_OK) {
868b5d91600SJérôme Duval PRINT(("failed to open mixer\n"));
869b5d91600SJérôme Duval goto err1;
870b5d91600SJérôme Duval }
871c9002531SJérôme Duval
872b5d91600SJérôme Duval return B_OK;
873b5d91600SJérôme Duval
874b5d91600SJérôme Duval err1:
875b5d91600SJérôme Duval remove_io_interrupt_handler(card->irq, echo_int, card);
876b5d91600SJérôme Duval err2:
877b5d91600SJérôme Duval #ifdef MIDI_SUPPORT
878b5d91600SJérôme Duval delete_sem(card->midi.midi_ready_sem);
879b5d91600SJérôme Duval #endif
880b5d91600SJérôme Duval err3:
881b5d91600SJérôme Duval delete card->pEG;
882b5d91600SJérôme Duval err4:
883b5d91600SJérôme Duval delete card->pOSS;
884b5d91600SJérôme Duval err5:
885b5d91600SJérôme Duval delete_area(card->area_bmbar);
886b5d91600SJérôme Duval return B_ERROR;
8875adb129eSJérôme Duval }
8885adb129eSJérôme Duval
8895adb129eSJérôme Duval static void
echo_shutdown(echo_dev * card)8905adb129eSJérôme Duval echo_shutdown(echo_dev *card)
8915adb129eSJérôme Duval {
892c9002531SJérôme Duval ECHOSTATUS status;
893c9002531SJérôme Duval
8945adb129eSJérôme Duval PRINT(("shutdown(%p)\n", card));
895c9002531SJérôme Duval status = card->pEG->CloseMixer(card->mixer);
896c9002531SJérôme Duval if (status != ECHOSTATUS_OK)
897c9002531SJérôme Duval PRINT(("echo_shutdown: error when CloseMixer\n"));
898c9002531SJérôme Duval
8995adb129eSJérôme Duval remove_io_interrupt_handler(card->irq, echo_int, card);
9005adb129eSJérôme Duval
9010bb683faSJérôme Duval #ifdef MIDI_SUPPORT
9020bb683faSJérôme Duval delete_sem(card->midi.midi_ready_sem);
9030bb683faSJérôme Duval #endif
9040bb683faSJérôme Duval
9055adb129eSJérôme Duval delete card->pEG;
9065adb129eSJérôme Duval delete card->pOSS;
9075adb129eSJérôme Duval
9085adb129eSJérôme Duval delete_area(card->area_bmbar);
9095adb129eSJérôme Duval }
9105adb129eSJérôme Duval
9115adb129eSJérôme Duval
9125adb129eSJérôme Duval
9135adb129eSJérôme Duval void
uninit_driver(void)9145adb129eSJérôme Duval uninit_driver(void)
9155adb129eSJérôme Duval {
9165adb129eSJérôme Duval PRINT(("uninit_driver()\n"));
9175adb129eSJérôme Duval
918ec816dffSJérôme Duval #ifdef CARDBUS
919ec816dffSJérôme Duval echo_dev *dev;
920ec816dffSJérôme Duval
921ec816dffSJérôme Duval LIST_FOREACH(dev, &devices, next) {
922ec816dffSJérôme Duval echo_shutdown(dev);
923ec816dffSJérôme Duval }
924ec816dffSJérôme Duval put_module(CB_ENABLER_MODULE_NAME);
925ec816dffSJérôme Duval #else
926ec816dffSJérôme Duval int ix, cnt = num_cards;
927ec816dffSJérôme Duval num_cards = 0;
9285adb129eSJérôme Duval for (ix=0; ix<cnt; ix++) {
9295adb129eSJérôme Duval echo_shutdown(&cards[ix]);
93012a9da01SJérôme Duval #ifdef __HAIKU__
93112a9da01SJérôme Duval (*pci->unreserve_device)(cards[ix].info.bus,
93212a9da01SJérôme Duval cards[ix].info.device, cards[ix].info.function,
93312a9da01SJérôme Duval DRIVER_NAME, &cards[ix]);
93412a9da01SJérôme Duval #endif
9355adb129eSJérôme Duval }
936ec816dffSJérôme Duval
9375adb129eSJérôme Duval memset(&cards, 0, sizeof(cards));
93815a2aa68SJérôme Duval put_module(B_PCI_MODULE_NAME);
939ec816dffSJérôme Duval #endif
9405adb129eSJérôme Duval }
9415adb129eSJérôme Duval
9425adb129eSJérôme Duval
9435adb129eSJérôme Duval const char **
publish_devices(void)9445adb129eSJérôme Duval publish_devices(void)
9455adb129eSJérôme Duval {
946ec816dffSJérôme Duval #ifdef CARDBUS
947ec816dffSJérôme Duval echo_dev *dev;
948ec816dffSJérôme Duval int ix = 0;
949ec816dffSJérôme Duval
950ec816dffSJérôme Duval // Lock the devices
951ec816dffSJérôme Duval acquire_sem(device_lock);
952ec816dffSJérôme Duval // Loop
953ec816dffSJérôme Duval LIST_FOREACH(dev, &devices, next) {
954ec816dffSJérôme Duval if (dev->plugged == true) {
955ec816dffSJérôme Duval names[ix] = dev->name;
956ec816dffSJérôme Duval ix++;
957ec816dffSJérôme Duval }
958ec816dffSJérôme Duval }
959ec816dffSJérôme Duval names[ix] = NULL;
960ec816dffSJérôme Duval release_sem(device_lock);
961ec816dffSJérôme Duval #else
9625adb129eSJérôme Duval int ix = 0;
9635adb129eSJérôme Duval PRINT(("publish_devices()\n"));
9645adb129eSJérôme Duval
9655adb129eSJérôme Duval for (ix=0; names[ix]; ix++) {
9665adb129eSJérôme Duval PRINT(("publish %s\n", names[ix]));
9675adb129eSJérôme Duval }
968ec816dffSJérôme Duval #endif
9695adb129eSJérôme Duval return (const char **)names;
9705adb129eSJérôme Duval }
9715adb129eSJérôme Duval
9725adb129eSJérôme Duval
9735adb129eSJérôme Duval device_hooks *
find_device(const char * name)9745adb129eSJérôme Duval find_device(const char * name)
9755adb129eSJérôme Duval {
976ec816dffSJérôme Duval #ifdef CARDBUS
977*d3503944SPulkoMandy echo_dev *dev;
978ec816dffSJérôme Duval LIST_FOREACH(dev, &devices, next) {
979ec816dffSJérôme Duval if (!strcmp(dev->name, name)) {
980ec816dffSJérôme Duval return &multi_hooks;
981ec816dffSJérôme Duval }
982ec816dffSJérôme Duval }
983ec816dffSJérôme Duval
984ec816dffSJérôme Duval #else
9855adb129eSJérôme Duval int ix;
9865adb129eSJérôme Duval
9875adb129eSJérôme Duval PRINT(("find_device(%s)\n", name));
9885adb129eSJérôme Duval
9895adb129eSJérôme Duval for (ix=0; ix<num_cards; ix++) {
9900bb683faSJérôme Duval #ifdef MIDI_SUPPORT
9910bb683faSJérôme Duval if (!strcmp(cards[ix].midi.name, name)) {
9920bb683faSJérôme Duval return &midi_hooks;
9930bb683faSJérôme Duval }
9940bb683faSJérôme Duval #endif
9955adb129eSJérôme Duval if (!strcmp(cards[ix].name, name)) {
9965adb129eSJérôme Duval return &multi_hooks;
9975adb129eSJérôme Duval }
9985adb129eSJérôme Duval }
999ec816dffSJérôme Duval #endif
10005adb129eSJérôme Duval PRINT(("find_device(%s) failed\n", name));
10015adb129eSJérôme Duval return NULL;
10025adb129eSJérôme Duval }
10035adb129eSJérôme Duval
10045adb129eSJérôme Duval int32 api_version = B_CUR_DRIVER_API_VERSION;
1005