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