xref: /haiku/src/add-ons/kernel/drivers/audio/echo/echo.cpp (revision a5bf12376daeded4049521eb17a6cc41192250d9)
1 //------------------------------------------------------------------------------
2 //
3 //  EchoGals/Echo24 BeOS Driver for Echo audio cards
4 //
5 //	Copyright (c) 2003, Jérôme Duval
6 //
7 //	Permission is hereby granted, free of charge, to any person obtaining a
8 //	copy of this software and associated documentation files (the "Software"),
9 //	to deal in the Software without restriction, including without limitation
10 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 //	and/or sell copies of the Software, and to permit persons to whom the
12 //	Software is furnished to do so, subject to the following conditions:
13 //
14 //	The above copyright notice and this permission notice shall be included in
15 //	all copies or substantial portions of the Software.
16 //
17 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 //	DEALINGS IN THE SOFTWARE.
24 
25 #include <KernelExport.h>
26 #include <Drivers.h>
27 #include <unistd.h>
28 #include "OsSupportBeOS.h"
29 #include "EchoGalsXface.h"
30 #include "C3g.h"
31 #include "CDarla24.h"
32 #include "CDarla.h"
33 #include "CGina.h"
34 #include "CGina24.h"
35 #include "CIndigo.h"
36 #include "CIndigoDJ.h"
37 #include "CIndigoIO.h"
38 #include "CLayla.h"
39 #include "CLayla24.h"
40 #include "CMia.h"
41 #include "CMona.h"
42 #include "echo.h"
43 #include "debug.h"
44 #include "util.h"
45 
46 #ifdef CARDBUS
47 static cb_enabler_module_info	*cbemi;
48 struct _echodevs				devices;
49 static char						*names[NUM_CARDS];
50 int32 							num_names = 0;
51 static uint32					device_index = 0;
52 static sem_id					device_lock = 0;
53 
54 static const cb_device_descriptor	descriptors[] = {
55 	{VENDOR_ID, DEVICE_ID_56301, 0xff, 0xff, 0xff}
56 };
57 
58 #define COUNT_DESCRIPTOR			1
59 
60 status_t cardbus_device_added(pci_info *info, void **cookie);
61 void cardbus_device_removed(void *cookie);
62 
63 static cb_notify_hooks	cardbus_hooks = {
64 	cardbus_device_added, 		// Add entry point
65 	cardbus_device_removed 		// Remove entry point
66 };
67 
68 #else // CARDBUS
69 static pci_module_info	*pci;
70 int32 num_cards;
71 echo_dev cards[NUM_CARDS];
72 int32 num_names;
73 char * names[NUM_CARDS*20+1];
74 #endif // CARDBUS
75 
76 extern device_hooks multi_hooks;
77 #ifdef MIDI_SUPPORT
78 extern device_hooks midi_hooks;
79 #endif
80 
81 int32 echo_int(void *arg);
82 status_t init_hardware(void);
83 status_t init_driver(void);
84 static void make_device_names(echo_dev * card);
85 
86 static status_t echo_setup(echo_dev * card);
87 static void echo_shutdown(echo_dev *card);
88 
89 void uninit_driver(void);
90 const char ** publish_devices(void);
91 device_hooks * find_device(const char * name);
92 
93 
94 /* Echo Memory management */
95 
96 echo_mem *
97 echo_mem_new(echo_dev *card, size_t size)
98 {
99 	echo_mem *mem;
100 
101 	if ((mem = (echo_mem *) malloc(sizeof(*mem))) == NULL)
102 		return (NULL);
103 
104 	mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "echo buffer");
105 	mem->size = size;
106 	if (mem->area < B_OK) {
107 		free(mem);
108 		return NULL;
109 	}
110 	return mem;
111 }
112 
113 void
114 echo_mem_delete(echo_mem *mem)
115 {
116 	if (mem->area > B_OK)
117 		delete_area(mem->area);
118 	free(mem);
119 }
120 
121 echo_mem *
122 echo_mem_alloc(echo_dev *card, size_t size)
123 {
124 	echo_mem *mem;
125 
126 	mem = echo_mem_new(card, size);
127 	if (mem == NULL)
128 		return (NULL);
129 
130 	LIST_INSERT_HEAD(&(card->mems), mem, next);
131 
132 	return mem;
133 }
134 
135 void
136 echo_mem_free(echo_dev *card, void *ptr)
137 {
138 	echo_mem 		*mem;
139 
140 	LIST_FOREACH(mem, &card->mems, next) {
141 		if (mem->log_base != ptr)
142 			continue;
143 		LIST_REMOVE(mem, next);
144 
145 		echo_mem_delete(mem);
146 		break;
147 	}
148 }
149 
150 /*	Echo stream functions */
151 
152 extern char *pStatusStrs[ECHOSTATUS_LAST];
153 
154 status_t
155 echo_stream_set_audioparms(echo_stream *stream, uint8 channels,
156 	uint8 bitsPerSample, uint32 sample_rate, uint8 index)
157 {
158 	int32 			i;
159 	uint8 			sample_size, frame_size;
160 	ECHOGALS_OPENAUDIOPARAMETERS	open_params;
161 	ECHOGALS_CLOSEAUDIOPARAMETERS  close_params;
162 	ECHOGALS_AUDIOFORMAT			format_params;
163 	ECHOSTATUS status;
164 
165 	LOG(("echo_stream_set_audioparms\n"));
166 
167 	if (stream->pipe >= 0) {
168 		close_params.wPipeIndex = stream->pipe;
169 		status = stream->card->pEG->CloseAudio(&close_params);
170 		if (status != ECHOSTATUS_OK && status != ECHOSTATUS_CHANNEL_NOT_OPEN) {
171 			PRINT(("echo_stream_set_audioparms : CloseAudio failed\n"));
172 			PRINT((" status: %s \n", pStatusStrs[status]));
173 			return B_ERROR;
174 		}
175 	}
176 
177 	open_params.bIsCyclic = TRUE;
178 	open_params.Pipe.nPipe = index;
179 	open_params.Pipe.bIsInput = stream->use == ECHO_USE_RECORD ? TRUE : FALSE;
180 	open_params.Pipe.wInterleave = channels;
181 	open_params.ProcessId = NULL;
182 
183 	status = stream->card->pEG->OpenAudio(&open_params, &stream->pipe);
184 	if (status != ECHOSTATUS_OK) {
185 		PRINT(("echo_stream_set_audioparms : OpenAudio failed\n"));
186 		PRINT((" status: %s \n", pStatusStrs[status]));
187 		return B_ERROR;
188 	}
189 
190 	//PRINT(("VerifyAudioOpen\n"));
191 	status = stream->card->pEG->VerifyAudioOpen(stream->pipe);
192 	if (status != ECHOSTATUS_OK) {
193 		PRINT(("echo_stream_set_audioparms : VerifyAudioOpen failed\n"));
194 		PRINT(("  status: %s \n", pStatusStrs[status]));
195 		return B_ERROR;
196 	}
197 
198 	if (bitsPerSample == 24)
199 		bitsPerSample = 32;
200 
201 	if ((stream->channels == channels)
202 		&& (stream->bitsPerSample == bitsPerSample)
203 		&& (stream->sample_rate == sample_rate))
204 		return B_OK;
205 
206 	format_params.wBitsPerSample = bitsPerSample;
207 	format_params.byDataAreBigEndian = 0;
208 	format_params.byMonoToStereo = 0;
209 	format_params.wDataInterleave = channels == 1 ? 1 : 2;
210 
211 	status = stream->card->pEG->QueryAudioFormat(stream->pipe, &format_params);
212 	if (status != ECHOSTATUS_OK) {
213 		PRINT(("echo_stream_set_audioparms : bad format when querying\n"));
214 		PRINT(("  status: %s \n", pStatusStrs[status]));
215 		return B_ERROR;
216 	}
217 
218 	status = stream->card->pEG->SetAudioFormat(stream->pipe, &format_params);
219 	if (status != ECHOSTATUS_OK) {
220 		PRINT(("echo_stream_set_audioparms : bad format when setting\n"));
221 		PRINT(("  status: %s \n", pStatusStrs[status]));
222 		return B_ERROR;
223 	}
224 
225 	/* XXXX : setting sample rate is global in this driver */
226 	status = stream->card->pEG->QueryAudioSampleRate(sample_rate);
227 	if (status != ECHOSTATUS_OK) {
228 		PRINT(("echo_stream_set_audioparms : bad sample rate when querying\n"));
229 		PRINT(("  status: %s \n", pStatusStrs[status]));
230 		return B_ERROR;
231 	}
232 
233 	/* XXXX : setting sample rate is global in this driver */
234 	status = stream->card->pEG->SetAudioSampleRate(sample_rate);
235 	if (status != ECHOSTATUS_OK) {
236 		PRINT(("echo_stream_set_audioparms : bad sample rate when setting\n"));
237 		PRINT(("  status: %s \n", pStatusStrs[status]));
238 		return B_ERROR;
239 	}
240 
241 	if (stream->buffer)
242 		echo_mem_free(stream->card, stream->buffer->log_base);
243 
244 	stream->bitsPerSample = bitsPerSample;
245 	stream->sample_rate = sample_rate;
246 	stream->channels = channels;
247 
248 	sample_size = stream->bitsPerSample / 8;
249 	frame_size = sample_size * stream->channels;
250 
251 	stream->buffer = echo_mem_alloc(stream->card, stream->bufframes * frame_size * stream->bufcount);
252 
253 	stream->trigblk = 1;
254 	stream->blkmod = stream->bufcount;
255 	stream->blksize = stream->bufframes * frame_size;
256 
257 	CDaffyDuck *duck = stream->card->pEG->GetDaffyDuck(stream->pipe);
258 	if (duck == NULL) {
259 		PRINT(("echo_stream_set_audioparms : Could not get daffy duck pointer\n"));
260 		return B_ERROR;
261 	}
262 
263 	uint32 dwNumFreeEntries = 0;
264 
265 	for (i = 0; i < stream->bufcount; i++) {
266 		duck->AddMapping(((uint32)stream->buffer->phy_base) +
267 			i * stream->blksize, stream->blksize, 0, TRUE, dwNumFreeEntries);
268 	}
269 
270 	duck->Wrap();
271 
272 	if (stream->card->pEG->GetAudioPositionPtr(stream->pipe, stream->position)!=ECHOSTATUS_OK) {
273 		PRINT(("echo_stream_set_audioparms : Could not get audio position ptr\n"));
274 		return B_ERROR;
275 	}
276 
277 	return B_OK;
278 }
279 
280 
281 status_t
282 echo_stream_get_nth_buffer(echo_stream *stream, uint8 chan, uint8 buf,
283 	char** buffer, size_t *stride)
284 {
285 	uint8 			sample_size, frame_size;
286 	LOG(("echo_stream_get_nth_buffer\n"));
287 
288 	sample_size = stream->bitsPerSample / 8;
289 	frame_size = sample_size * stream->channels;
290 
291 	*buffer = (char*)stream->buffer->log_base + (buf * stream->bufframes * frame_size)
292 		+ chan * sample_size;
293 	*stride = frame_size;
294 
295 	return B_OK;
296 }
297 
298 
299 static uint32
300 echo_stream_curaddr(echo_stream *stream)
301 {
302 	uint32 addr = B_LENDIAN_TO_HOST_INT32(*stream->position);
303 //	TRACE(("stream_curaddr %p, phy_base %p\n", addr));
304 	return (addr / stream->blksize) % stream->blkmod;
305 }
306 
307 
308 void
309 echo_stream_start(echo_stream *stream, void (*inth) (void *), void *inthparam)
310 {
311 	LOG(("echo_stream_start\n"));
312 	ECHOSTATUS status;
313 
314 	stream->inth = inth;
315 	stream->inthparam = inthparam;
316 
317 	stream->state |= ECHO_STATE_STARTED;
318 
319 	status = stream->card->pEG->Start(stream->pipe);
320 	if (status!=ECHOSTATUS_OK) {
321 		PRINT(("echo_stream_start : Could not start the pipe %s\n", pStatusStrs[status]));
322 	}
323 }
324 
325 void
326 echo_stream_halt(echo_stream *stream)
327 {
328 	LOG(("echo_stream_halt\n"));
329 	ECHOSTATUS status;
330 
331 	stream->state &= ~ECHO_STATE_STARTED;
332 
333 	status = stream->card->pEG->Stop(stream->pipe);
334 	if (status!=ECHOSTATUS_OK) {
335 		PRINT(("echo_stream_halt : Could not stop the pipe %s\n", pStatusStrs[status]));
336 	}
337 }
338 
339 echo_stream *
340 echo_stream_new(echo_dev *card, uint8 use, uint32 bufframes, uint8 bufcount)
341 {
342 	echo_stream *stream;
343 	cpu_status status;
344 	LOG(("echo_stream_new\n"));
345 
346 	stream = (echo_stream *) malloc(sizeof(echo_stream));
347 	if (stream == NULL)
348 		return (NULL);
349 	stream->card = card;
350 	stream->use = use;
351 	stream->state = !ECHO_STATE_STARTED;
352 	stream->bitsPerSample = 0;
353 	stream->sample_rate = 0;
354 	stream->channels = 0;
355 	stream->bufframes = bufframes;
356 	stream->bufcount = bufcount;
357 	stream->inth = NULL;
358 	stream->inthparam = NULL;
359 	stream->buffer = NULL;
360 	stream->blksize = 0;
361 	stream->trigblk = 0;
362 	stream->blkmod = 0;
363 
364 	stream->pipe = -1;
365 
366 	stream->frames_count = 0;
367 	stream->real_time = 0;
368 	stream->buffer_cycle = 0;
369 	stream->update_needed = false;
370 
371 	status = lock();
372 	LIST_INSERT_HEAD((&card->streams), stream, next);
373 	unlock(status);
374 
375 	return stream;
376 }
377 
378 void
379 echo_stream_delete(echo_stream *stream)
380 {
381 	cpu_status status;
382 	ECHOGALS_CLOSEAUDIOPARAMETERS close_params;
383 	LOG(("echo_stream_delete\n"));
384 
385 	echo_stream_halt(stream);
386 
387 	if (stream->pipe >= 0) {
388 		close_params.wPipeIndex = stream->pipe;
389 		status = stream->card->pEG->CloseAudio(&close_params);
390 		if (status != ECHOSTATUS_OK && status != ECHOSTATUS_CHANNEL_NOT_OPEN) {
391 			PRINT(("echo_stream_set_audioparms : CloseAudio failed\n"));
392 			PRINT((" status: %s \n", pStatusStrs[status]));
393 		}
394 	}
395 
396 	if (stream->buffer)
397 		echo_mem_free(stream->card, stream->buffer->log_base);
398 
399 	status = lock();
400 	LIST_REMOVE(stream, next);
401 	unlock(status);
402 
403 	free(stream);
404 }
405 
406 
407 /* Echo interrupt */
408 
409 int32 echo_int(void *arg)
410 {
411 	echo_dev* card = (echo_dev*)arg;
412 	BOOL midiReceived;
413 	ECHOSTATUS err;
414 	echo_stream* stream;
415 	uint32 curblk;
416 
417 	err = card->pEG->ServiceIrq(midiReceived);
418 
419 	if (err != ECHOSTATUS_OK) {
420 		return B_UNHANDLED_INTERRUPT;
421 	}
422 
423 #ifdef MIDI_SUPPORT
424 	if (midiReceived)
425 		release_sem_etc(card->midi.midi_ready_sem, 1, B_DO_NOT_RESCHEDULE);
426 #endif
427 
428 	LIST_FOREACH(stream, &card->streams, next) {
429 		if ((stream->state & ECHO_STATE_STARTED) == 0 ||
430 			(stream->inth == NULL))
431 				continue;
432 
433 		curblk = echo_stream_curaddr(stream);
434 		//TRACE(("echo_int stream %p at trigblk %lu at stream->trigblk %lu\n",
435 		//	   stream, curblk, stream->trigblk));
436 		if (curblk == stream->trigblk) {
437 			if (stream->inth)
438 				stream->inth(stream->inthparam);
439 
440 			stream->trigblk++;
441 			stream->trigblk %= stream->blkmod;
442 		}
443 	}
444 
445 	return B_INVOKE_SCHEDULER;
446 }
447 
448 /* dumps card capabilities */
449 void
450 echo_dump_caps(echo_dev *card)
451 {
452 	PECHOGALS_CAPS caps = &card->caps;
453 	PRINT(("name: %s\n", caps->szName));
454 	PRINT(("out pipes: %d, in pipes: %d, out busses: %d, in busses: %d, out midi: %d, in midi: %d\n",
455 		caps->wNumPipesOut, caps->wNumPipesIn, caps->wNumBussesOut, caps->wNumBussesIn, caps->wNumMidiOut, caps->wNumMidiIn));
456 
457 }
458 
459 
460 /* detect presence of our hardware */
461 status_t
462 init_hardware(void)
463 {
464 #ifdef CARDBUS
465 	return B_OK;
466 #else
467 	int ix=0;
468 	pci_info info;
469 	status_t err = ENODEV;
470 
471 	LOG_CREATE();
472 
473 	PRINT(("init_hardware()\n"));
474 
475 	if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci))
476 		return ENOSYS;
477 
478 	while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) {
479 
480 		ushort card_type = info.u.h0.subsystem_id & 0xfff0;
481 
482 		if (info.vendor_id == VENDOR_ID
483 			&& ((info.device_id == DEVICE_ID_56301)
484 			|| (info.device_id == DEVICE_ID_56361))
485 			&& (info.u.h0.subsystem_vendor_id == SUBVENDOR_ID)
486 			&& (
487 #ifdef ECHOGALS_FAMILY
488 			(card_type == DARLA)
489 			|| (card_type == GINA)
490 			|| (card_type == LAYLA)
491 			|| (card_type == DARLA24)
492 #endif
493 #ifdef ECHO24_FAMILY
494 			(card_type == GINA24)
495 			|| (card_type == LAYLA24)
496 			|| (card_type == MONA)
497 			|| (card_type == MIA)
498 #endif
499 #ifdef INDIGO_FAMILY
500 			(card_type == INDIGO)
501 			|| (card_type == INDIGO_IO)
502 			|| (card_type == INDIGO_DJ)
503 #endif
504 #ifdef ECHO3G_FAMILY
505 			(card_type == ECHO3G)
506 #endif
507 			 )) {
508 			err = B_OK;
509 		}
510 		ix++;
511 	}
512 
513 	put_module(B_PCI_MODULE_NAME);
514 
515 	if (err != B_OK) {
516 		PRINT(("no card found\n"));
517 	}
518 
519 	return err;
520 #endif
521 }
522 
523 
524 status_t
525 init_driver(void)
526 {
527 	PRINT(("init_driver()\n"));
528 
529 #ifdef CARDBUS
530 	// Get card services client module
531 	if (get_module(CB_ENABLER_MODULE_NAME, (module_info **)&cbemi) != B_OK) {
532 		dprintf(DRIVER_NAME ": cardbus enabler module error\n");
533 		return B_ERROR;
534 	}
535 	// Create the devices lock
536 	device_lock = create_sem(1, DRIVER_NAME " device");
537 	if (device_lock < B_OK) {
538 		dprintf(DRIVER_NAME ": create device semaphore error 0x%.8x\n", device_lock);
539 		put_module(CB_ENABLER_MODULE_NAME);
540 		return B_ERROR;
541 	}
542 	// Register driver
543 	cbemi->register_driver(DRIVER_NAME, descriptors, COUNT_DESCRIPTOR);
544 	cbemi->install_notify(DRIVER_NAME, &cardbus_hooks);
545 	LIST_INIT(&(devices));
546 	return B_OK;
547 #else
548 	int ix=0;
549 
550 	pci_info info;
551 	status_t err;
552 	num_cards = 0;
553 
554 	if (get_module(B_PCI_MODULE_NAME, (module_info **) &pci))
555 		return ENOSYS;
556 
557 	while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) {
558 		ushort card_type = info.u.h0.subsystem_id & 0xfff0;
559 
560 		if (info.vendor_id == VENDOR_ID
561 			&& ((info.device_id == DEVICE_ID_56301)
562 			|| (info.device_id == DEVICE_ID_56361))
563 			&& (info.u.h0.subsystem_vendor_id == SUBVENDOR_ID)
564 			&& (
565 #ifdef ECHOGALS_FAMILY
566 			(card_type == DARLA)
567 			|| (card_type == GINA)
568 			|| (card_type == LAYLA)
569 			|| (card_type == DARLA24)
570 #endif
571 #ifdef ECHO24_FAMILY
572 			(card_type == GINA24)
573 			|| (card_type == LAYLA24)
574 			|| (card_type == MONA)
575 			|| (card_type == MIA)
576 #endif
577 #ifdef INDIGO_FAMILY
578 			(card_type == INDIGO)
579 			|| (card_type == INDIGO_IO)
580 			|| (card_type == INDIGO_DJ)
581 #endif
582 #ifdef ECHO3G_FAMILY
583 			(card_type == ECHO3G)
584 #endif
585 			)) {
586 
587 			if (num_cards == NUM_CARDS) {
588 				PRINT(("Too many "DRIVER_NAME" cards installed!\n"));
589 				break;
590 			}
591 			memset(&cards[num_cards], 0, sizeof(echo_dev));
592 			cards[num_cards].info = info;
593 			cards[num_cards].type = card_type;
594 #ifdef __HAIKU__
595 			if ((err = (*pci->reserve_device)(info.bus, info.device, info.function,
596 				DRIVER_NAME, &cards[num_cards])) < B_OK) {
597 				dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n",
598 					DRIVER_NAME, info.bus, info.device, info.function,
599 					strerror(err));
600 				continue;
601 			}
602 #endif
603 			if (echo_setup(&cards[num_cards])) {
604 				PRINT(("Setup of "DRIVER_NAME" %ld failed\n", num_cards+1));
605 #ifdef __HAIKU__
606 				(*pci->unreserve_device)(info.bus, info.device, info.function,
607 					DRIVER_NAME, &cards[num_cards]);
608 #endif
609 			}
610 			else {
611 				num_cards++;
612 			}
613 		}
614 	}
615 	if (!num_cards) {
616 		PRINT(("no cards\n"));
617 		put_module(B_PCI_MODULE_NAME);
618 		PRINT(("no suitable cards found\n"));
619 		return ENODEV;
620 	}
621 
622 	return B_OK;
623 #endif
624 }
625 
626 
627 #ifndef CARDBUS
628 static void
629 make_device_names(
630 	echo_dev * card)
631 {
632 #ifdef MIDI_SUPPORT
633 	sprintf(card->midi.name, "midi/"DRIVER_NAME"/%ld", card-cards+1);
634 	names[num_names++] = card->midi.name;
635 #endif
636 	sprintf(card->name, "audio/hmulti/"DRIVER_NAME"/%ld", card-cards+1);
637 	names[num_names++] = card->name;
638 
639 	names[num_names] = NULL;
640 }
641 #else
642 
643 status_t
644 cardbus_device_added(pci_info *info, void **cookie) {
645 	echo_dev 			* card, *dev;
646 	uint32				index;
647 	char				buffer[32];
648 
649 	LOG(("cardbus_device_added at %.2d:%.2d:%.2d\n", info->bus, info->device, info->function));
650 	// Allocate cookie
651 	if (!(*cookie = card = (echo_dev *)malloc(sizeof(echo_dev)))) {
652 		return B_NO_MEMORY;
653 	}
654 	// Clear cookie
655 	memset(card, 0, sizeof(echo_dev));
656 	// Initialize cookie
657 	card->info = *info;
658 	card->plugged = true;
659 	card->index = 0;
660 
661 	LIST_FOREACH(dev, &devices, next) {
662 		if (dev->index == card->index) {
663 			card->index++;
664 			dev = LIST_FIRST(&devices);
665 		}
666 	}
667 
668 	// Format device name
669 	sprintf(card->name, "audio/hmulti/" DRIVER_NAME "/%ld", card->index);
670 	// Lock the devices
671 	acquire_sem(device_lock);
672 	LIST_INSERT_HEAD((&devices), card, next);
673 	// Unlock the devices
674 	release_sem(device_lock);
675 
676 	echo_setup(card);
677 	return B_OK;
678 }
679 
680 
681 // cardbus_device_removed - handle cardbus device removal.
682 // status : OK
683 void
684 cardbus_device_removed(void *cookie)
685 {
686 	echo_dev		*card = (echo_dev *) cookie;
687 
688 	LOG((": cardbus_device_removed\n"));
689 	// Check
690 	if (card == NULL) {
691 		LOG((": null device 0x%.8x\n", card));
692 		return;
693 	}
694 
695 	echo_shutdown(card);
696 
697 	// Lock the devices
698 	acquire_sem(device_lock);
699 	// Finalize
700 	card->plugged = false;
701 	// Check if the device is opened
702 	if (card->opened) {
703 		LOG(("device 0x%.8x %s still in use\n", card, card->name));
704 	} else {
705 		LOG(("free device 0x%.8x %s\n", card, card->name));
706 		LIST_REMOVE(card, next);
707 		free(card);
708 	}
709 	// Unlock the devices
710 	release_sem(device_lock);
711 }
712 
713 #endif
714 
715 
716 static status_t
717 echo_setup(echo_dev * card)
718 {
719 	unsigned char cmd;
720 	char *name;
721 
722 	PRINT(("echo_setup(%p)\n", card));
723 
724 #ifndef CARDBUS
725 	(*pci->write_pci_config)(card->info.bus, card->info.device,
726 		card->info.function, PCI_latency, 1, 0xc0 );
727 
728 	make_device_names(card);
729 #endif
730 	card->bmbar = card->info.u.h0.base_registers[0];
731 	card->irq = card->info.u.h0.interrupt_line;
732 
733 	card->area_bmbar = map_mem(&card->log_bmbar, card->bmbar,
734 		card->info.u.h0.base_register_sizes[0], DRIVER_NAME" bmbar io");
735 	if (card->area_bmbar <= B_OK) {
736 		LOG(("mapping of bmbar io failed, error = %#x\n",card->area_bmbar));
737 		goto err5;
738 	}
739 	LOG(("mapping of bmbar: area %#x, phys %#x, log %#x\n", card->area_bmbar,
740 		card->bmbar, card->log_bmbar));
741 
742 	card->pOSS = new COsSupport(card->info.device_id, card->info.revision);
743 	if (card->pOSS == NULL)
744 		goto err4;
745 
746 	switch (card->type) {
747 #ifdef ECHOGALS_FAMILY
748 		case DARLA:
749 			card->pEG = new CDarla(card->pOSS);
750 			name = "Echo Darla";
751 			break;
752 		case GINA:
753 			card->pEG = new CGina(card->pOSS);
754 			name = "Echo Gina";
755 			break;
756 		case LAYLA:
757 			card->pEG = new CLayla(card->pOSS);
758 			name = "Echo Layla";
759 			break;
760 		case DARLA24:
761 			card->pEG = new CDarla24(card->pOSS);
762 			name = "Echo Darla24";
763 			break;
764 #endif
765 #ifdef ECHO24_FAMILY
766 		case GINA24:
767 			card->pEG = new CGina24(card->pOSS);
768 			name = "Echo Gina24";
769 			break;
770 		case LAYLA24:
771 			card->pEG = new CLayla24(card->pOSS);
772 			name = "Echo Layla24";
773 			break;
774 		case MONA:
775 			card->pEG = new CMona(card->pOSS);
776 			name = "Echo Mona";
777 			break;
778 		case MIA:
779 			card->pEG = new CMia(card->pOSS);
780 			name = "Echo Mia";
781 			break;
782 #endif
783 #ifdef INDIGO_FAMILY
784 		case INDIGO:
785 			card->pEG = new CIndigo(card->pOSS);
786 			name = "Echo Indigo";
787 			break;
788 		case INDIGO_IO:
789 			card->pEG = new CIndigoIO(card->pOSS);
790 			name = "Echo IndigoIO";
791 			break;
792 		case INDIGO_DJ:
793 			card->pEG = new CIndigoDJ(card->pOSS);
794 			name = "Echo IndigoDJ";
795 			break;
796 #endif
797 #ifdef ECHO3G_FAMILY
798 		case ECHO3G:
799 			card->pEG = new C3g(card->pOSS);
800 			name = "Echo 3g";
801 			break;
802 #endif
803 		default:
804 			PRINT(("card type 0x%x not supported by "DRIVER_NAME"\n",
805 				card->type));
806 	}
807 
808 	if (card->pEG == NULL)
809 		goto err2;
810 
811 #ifndef CARDBUS
812 	cmd = (*pci->read_pci_config)(card->info.bus, card->info.device,
813 		card->info.function, PCI_command, 2);
814 	PRINT(("PCI command before: %x\n", cmd));
815 	(*pci->write_pci_config)(card->info.bus, card->info.device,
816 		card->info.function, PCI_command, 2, cmd | PCI_command_io);
817 	cmd = (*pci->read_pci_config)(card->info.bus, card->info.device,
818 		card->info.function, PCI_command, 2);
819 	PRINT(("PCI command after: %x\n", cmd));
820 #endif
821 
822 	card->pEG->AssignResources(card->log_bmbar, name);
823 
824 	ECHOSTATUS status;
825 	status = card->pEG->InitHw();
826 	if (status != ECHOSTATUS_OK)
827 		goto err3;
828 
829 	card->pEG->GetCapabilities(&card->caps);
830 
831 	/* Init streams list */
832 	LIST_INIT(&(card->streams));
833 
834 	/* Init mems list */
835 	LIST_INIT(&(card->mems));
836 
837 #ifdef MIDI_SUPPORT
838 	card->midi.midi_ready_sem = create_sem(0, "midi sem");
839 #endif
840 
841 	PRINT(("installing interrupt : %x\n", card->irq));
842 	status = install_io_interrupt_handler(card->irq, echo_int, card, 0);
843 	if (status != B_OK) {
844 		PRINT(("failed to install interrupt\n"));
845 		goto err2;
846 	}
847 
848 	PRINT(("echo_setup done\n"));
849 
850 	echo_dump_caps(card);
851 
852 #ifdef ECHO3G_FAMILY
853 	if (card->type == ECHO3G) {
854 		strncpy(card->caps.szName, ((C3g*)card->pEG)->Get3gBoxName(),
855 			ECHO_MAXNAMELEN);
856 	}
857 #endif
858 
859 	status = card->pEG->OpenMixer(card->mixer);
860 	if (status != ECHOSTATUS_OK) {
861 		PRINT(("failed to open mixer\n"));
862 		goto err1;
863 	}
864 
865 	return B_OK;
866 
867 err1:
868 	remove_io_interrupt_handler(card->irq, echo_int, card);
869 err2:
870 #ifdef MIDI_SUPPORT
871 	delete_sem(card->midi.midi_ready_sem);
872 #endif
873 err3:
874 	delete card->pEG;
875 err4:
876 	delete card->pOSS;
877 err5:
878 	delete_area(card->area_bmbar);
879 	return B_ERROR;
880 }
881 
882 static void
883 echo_shutdown(echo_dev *card)
884 {
885 	ECHOSTATUS status;
886 
887 	PRINT(("shutdown(%p)\n", card));
888 	status = card->pEG->CloseMixer(card->mixer);
889 	if (status != ECHOSTATUS_OK)
890 		PRINT(("echo_shutdown: error when CloseMixer\n"));
891 
892 	remove_io_interrupt_handler(card->irq, echo_int, card);
893 
894 #ifdef MIDI_SUPPORT
895 	delete_sem(card->midi.midi_ready_sem);
896 #endif
897 
898 	delete card->pEG;
899 	delete card->pOSS;
900 
901 	delete_area(card->area_bmbar);
902 }
903 
904 
905 
906 void
907 uninit_driver(void)
908 {
909 	PRINT(("uninit_driver()\n"));
910 
911 #ifdef CARDBUS
912 	echo_dev			*dev;
913 
914 	LIST_FOREACH(dev, &devices, next) {
915 		echo_shutdown(dev);
916 	}
917 	put_module(CB_ENABLER_MODULE_NAME);
918 #else
919 	int ix, cnt = num_cards;
920 	num_cards = 0;
921 	for (ix=0; ix<cnt; ix++) {
922 		echo_shutdown(&cards[ix]);
923 	}
924 
925 	memset(&cards, 0, sizeof(cards));
926 	put_module(B_PCI_MODULE_NAME);
927 #endif
928 }
929 
930 
931 const char **
932 publish_devices(void)
933 {
934 #ifdef CARDBUS
935 	echo_dev			*dev;
936 	int			ix = 0;
937 
938 	// Lock the devices
939 	acquire_sem(device_lock);
940 	// Loop
941 	LIST_FOREACH(dev, &devices, next) {
942 		if (dev->plugged == true) {
943 			names[ix] = dev->name;
944 			ix++;
945 		}
946 	}
947 	names[ix] = NULL;
948 	release_sem(device_lock);
949 #else
950 	int ix = 0;
951 	PRINT(("publish_devices()\n"));
952 
953 	for (ix=0; names[ix]; ix++) {
954 		PRINT(("publish %s\n", names[ix]));
955 	}
956 #endif
957 	return (const char **)names;
958 }
959 
960 
961 device_hooks *
962 find_device(const char * name)
963 {
964 	echo_dev *dev;
965 #ifdef CARDBUS
966 	LIST_FOREACH(dev, &devices, next) {
967 		if (!strcmp(dev->name, name)) {
968 			return &multi_hooks;
969 		}
970 	}
971 
972 #else
973 	int ix;
974 
975 	PRINT(("find_device(%s)\n", name));
976 
977 	for (ix=0; ix<num_cards; ix++) {
978 #ifdef MIDI_SUPPORT
979 		if (!strcmp(cards[ix].midi.name, name)) {
980 			return &midi_hooks;
981 		}
982 #endif
983 		if (!strcmp(cards[ix].name, name)) {
984 			return &multi_hooks;
985 		}
986 	}
987 #endif
988 	PRINT(("find_device(%s) failed\n", name));
989 	return NULL;
990 }
991 
992 int32	api_version = B_CUR_DRIVER_API_VERSION;
993