1/*
2 * Emuxki BeOS Driver for Creative Labs SBLive!/Audigy series
3 *
4 * Copyright (c) 2002, Jerome Duval (jerome.duval@free.fr)
5 *
6 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without modification,
8 * are permitted provided that the following conditions are met:
9 *
10 * - Redistributions of source code must retain the above copyright notice,
11 *   this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright notice,
13 *   this list of conditions and the following disclaimer in the documentation
14 *   and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 *
28 * Original code : Copyright 1999, Be Incorporated.   All Rights Reserved.
29 * This file may be used under the terms of the Be Sample Code License.
30*/
31
32#include <string.h>
33#include <stdlib.h>
34#include <signal.h>
35
36#include "emuxki.h"
37#include "io.h"
38#include "debug.h"
39#include "midi_driver.h"
40#include "util.h"
41
42extern generic_mpu401_module * mpu401;
43
44void
45midi_interrupt_op(
46	int32 op,
47	void * data)
48{
49	cpu_status status;
50	// dprint seems to be disabled here, will have to enable it to trace
51
52	midi_dev * port = (midi_dev *)data;
53
54	LOG(("mpu401:midi_interrupt_op %x\n",op));
55	LOG(("port = %p\n", port));
56	if (op == B_MPU_401_ENABLE_CARD_INT) {
57		/* turn on MPU interrupts */
58		LOG(("emuxki: B_MPU_401_ENABLE_CARD_INT\n"));
59		status = lock();
60		emuxki_reg_write_32(&(port->card->config), EMU_INTE,
61			  emuxki_reg_read_32(&(port->card->config), EMU_INTE) | EMU_INTE_MIDIRXENABLE );
62		unlock(status);
63		LOG(("INTE address: %x\n",&port->card->config));
64	}
65	else if (op == B_MPU_401_DISABLE_CARD_INT) {
66		/* turn off MPU interrupts */
67		LOG(("emuxki: B_MPU_401_DISABLE_CARD_INT\n"));
68		status = lock();
69		emuxki_reg_write_32(&port->card->config, EMU_INTE,
70			  emuxki_reg_read_32(&port->card->config, EMU_INTE) &  ~ EMU_INTE_MIDIRXENABLE);
71		unlock(status);
72	}
73
74	LOG(("midi_interrupt_op() done\n"));
75}
76
77static status_t midi_open(const char *name, uint32 flags, void **cookie);
78static status_t midi_close(void *cookie);
79static status_t midi_free(void *cookie);
80static status_t midi_control(void *cookie, uint32 op, void *data, size_t len);
81static status_t midi_read(void *cookie, off_t pos, void *data, size_t *len);
82static status_t midi_write(void *cookie, off_t pos, const void *data, size_t *len);
83
84
85device_hooks midi_hooks = {
86    &midi_open,
87    &midi_close,
88    &midi_free,
89    &midi_control,
90    &midi_read,
91    &midi_write,
92    NULL,		/* select */
93    NULL,		/* deselect */
94    NULL,		/* readv */
95    NULL		/* writev */
96};
97
98static status_t
99midi_open(
100	const char * name,
101	uint32 flags,
102	void ** cookie)
103{
104	int ix;
105	int ret;
106
107	LOG(("midi_open()\n"));
108
109	*cookie = NULL;
110	for (ix=0; ix<num_cards; ix++) {
111		if (!strcmp(name, cards[ix].midi.name)) {
112			break;
113		}
114	}
115	if (ix >= num_cards) {
116		LOG(("bad device\n"));
117		return ENODEV;
118	}
119
120	LOG(("mpu401: %p  open(): %p  driver: %p\n", mpu401, mpu401->open_hook, cards[ix].midi.driver));
121	ret = (*mpu401->open_hook)(cards[ix].midi.driver, flags, cookie);
122	if (ret >= B_OK) {
123		cards[ix].midi.cookie = *cookie;
124		atomic_add(&cards[ix].midi.count, 1);
125	}
126	LOG(("mpu401: open returns %x / %p\n", ret, *cookie));
127	return ret;
128}
129
130
131static status_t
132midi_close(
133	void * cookie)
134{
135	LOG(("midi_close()\n"));
136	return (*mpu401->close_hook)(cookie);
137}
138
139
140static status_t
141midi_free(
142	void * cookie)
143{
144	int ix;
145	status_t f;
146	LOG(("midi_free()\n"));
147	f = (*mpu401->free_hook)(cookie);
148	for (ix=0; ix<num_cards; ix++) {
149		if (cards[ix].midi.cookie == cookie) {
150			if (atomic_add(&cards[ix].midi.count, -1) == 1) {
151				cards[ix].midi.cookie = NULL;
152				LOG(("cleared %p card %d\n", cookie, ix));
153			}
154			break;
155		}
156	}
157	LOG(("midi_free() done\n"));
158	return f;
159}
160
161
162static status_t
163midi_control(
164	void * cookie,
165	uint32 iop,
166	void * data,
167	size_t len)
168{
169	return (*mpu401->control_hook)(cookie, iop, data, len);
170}
171
172
173static status_t
174midi_read(
175	void * cookie,
176	off_t pos,
177	void * ptr,
178	size_t * nread)
179{
180	return (*mpu401->read_hook)(cookie, pos, ptr, nread);
181}
182
183
184static status_t
185midi_write(
186	void * cookie,
187	off_t pos,
188	const void * ptr,
189	size_t * nwritten)
190{
191	return (*mpu401->write_hook)(cookie, pos, ptr, nwritten);
192}
193
194
195bool
196midi_interrupt(emuxki_dev *card)
197{
198	TRACE(("midi_interrupt\n"));
199	if (!card->midi.driver)  {
200		dprintf("aiigh\n");
201		return false;
202	}
203
204	return (*mpu401->interrupt_hook)(card->midi.driver);
205}
206
207