xref: /haiku/src/add-ons/kernel/drivers/audio/emuxki/midi.c (revision 93aeb8c3bc3f13cb1f282e3e749258a23790d947)
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 
42 extern generic_mpu401_module * mpu401;
43 
44 void
45 midi_interrupt_op(
46 	int32 op,
47 	void * data)
48 {
49 	// dprint seems to be disabled here, will have to enable it to trace
50 
51 	midi_dev * port = (midi_dev *)data;
52 	TRACE(("port = %p\n", port));
53 	if (op == B_MPU_401_ENABLE_CARD_INT) {
54 		// sample code
55 		/*cpu_status cp;
56 		ddprintf(("sonic_vibes: B_MPU_401_ENABLE_CARD_INT\n"));
57 		cp = disable_interrupts();
58 		acquire_spinlock(&port->card->hardware);
59 		increment_interrupt_handler(port->card);
60 		set_direct(port->card, 0x01, 0x00, 0x80);
61 		set_indirect(port->card, 0x2A, 0x04, 0xff);
62 		release_spinlock(&port->card->hardware);
63 		restore_interrupts(cp);*/
64 
65 		//real code
66 		cpu_status status;
67 		status = lock();
68 		emuxki_reg_write_32(&(port->card->config), EMU_INTE,
69 			  emuxki_reg_read_32(&(port->card->config), EMU_INTE) |
70 			  EMU_INTE_MIDITXENABLE | EMU_INTE_MIDIRXENABLE );
71 		unlock(status);
72 	}
73 	else if (op == B_MPU_401_DISABLE_CARD_INT) {
74 		// sample code
75 		/* turn off MPU interrupts */
76 		/*cpu_status cp;
77 		ddprintf(("sonic_vibes: B_MPU_401_DISABLE_CARD_INT\n"));
78 		cp = disable_interrupts();
79 		acquire_spinlock(&port->card->hardware);
80 		set_direct(port->card, 0x01, 0x80, 0x80);*/
81 		/* remove interrupt handler if necessary */
82 		/*decrement_interrupt_handler(port->card);
83 		release_spinlock(&port->card->hardware);
84 		restore_interrupts(cp);*/
85 
86 		//real code
87 		cpu_status status;
88 		status = lock();
89 		emuxki_reg_write_32(&port->card->config, EMU_INTE,
90 			  emuxki_reg_read_32(&port->card->config, EMU_INTE) &
91 			  ~ (EMU_INTE_MIDITXENABLE | EMU_INTE_MIDIRXENABLE ) );
92 		unlock(status);
93 	}
94 	TRACE(("midi_interrupt_op() done\n"));
95 }
96 
97 static status_t midi_open(const char *name, uint32 flags, void **cookie);
98 static status_t midi_close(void *cookie);
99 static status_t midi_free(void *cookie);
100 static status_t midi_control(void *cookie, uint32 op, void *data, size_t len);
101 static status_t midi_read(void *cookie, off_t pos, void *data, size_t *len);
102 static status_t midi_write(void *cookie, off_t pos, const void *data, size_t *len);
103 
104 
105 device_hooks midi_hooks = {
106     &midi_open,
107     &midi_close,
108     &midi_free,
109     &midi_control,
110     &midi_read,
111     &midi_write,
112     NULL,		/* select */
113     NULL,		/* deselect */
114     NULL,		/* readv */
115     NULL		/* writev */
116 };
117 
118 static status_t
119 midi_open(
120 	const char * name,
121 	uint32 flags,
122 	void ** cookie)
123 {
124 	int ix;
125 	int ret;
126 
127 	LOG(("midi_open()\n"));
128 
129 	*cookie = NULL;
130 	for (ix=0; ix<num_cards; ix++) {
131 		if (!strcmp(name, cards[ix].midi.name)) {
132 			break;
133 		}
134 	}
135 	if (ix >= num_cards) {
136 		LOG(("bad device\n"));
137 		return ENODEV;
138 	}
139 
140 	LOG(("mpu401: %p  open(): %p  driver: %p\n", mpu401, mpu401->open_hook, cards[ix].midi.driver));
141 	ret = (*mpu401->open_hook)(cards[ix].midi.driver, flags, cookie);
142 	if (ret >= B_OK) {
143 		cards[ix].midi.cookie = *cookie;
144 		atomic_add(&cards[ix].midi.count, 1);
145 	}
146 	LOG(("mpu401: open returns %x / %p\n", ret, *cookie));
147 	return ret;
148 }
149 
150 
151 static status_t
152 midi_close(
153 	void * cookie)
154 {
155 	LOG(("midi_close()\n"));
156 	return (*mpu401->close_hook)(cookie);
157 }
158 
159 
160 static status_t
161 midi_free(
162 	void * cookie)
163 {
164 	int ix;
165 	status_t f;
166 	LOG(("midi_free()\n"));
167 	f = (*mpu401->free_hook)(cookie);
168 	for (ix=0; ix<num_cards; ix++) {
169 		if (cards[ix].midi.cookie == cookie) {
170 			if (atomic_add(&cards[ix].midi.count, -1) == 1) {
171 				cards[ix].midi.cookie = NULL;
172 				LOG(("cleared %p card %d\n", cookie, ix));
173 			}
174 			break;
175 		}
176 	}
177 	LOG(("midi_free() done\n"));
178 	return f;
179 }
180 
181 
182 static status_t
183 midi_control(
184 	void * cookie,
185 	uint32 iop,
186 	void * data,
187 	size_t len)
188 {
189 	return (*mpu401->control_hook)(cookie, iop, data, len);
190 }
191 
192 
193 static status_t
194 midi_read(
195 	void * cookie,
196 	off_t pos,
197 	void * ptr,
198 	size_t * nread)
199 {
200 	return (*mpu401->read_hook)(cookie, pos, ptr, nread);
201 }
202 
203 
204 static status_t
205 midi_write(
206 	void * cookie,
207 	off_t pos,
208 	const void * ptr,
209 	size_t * nwritten)
210 {
211 	return (*mpu401->write_hook)(cookie, pos, ptr, nwritten);
212 }
213 
214 
215 bool
216 midi_interrupt(emuxki_dev *card)
217 {
218 	TRACE(("midi_interrupt\n"));
219 	if (!card->midi.driver)  {
220 //		kprintf("aiigh\n");
221 		return false;
222 	}
223 
224 	return (*mpu401->interrupt_hook)(card->midi.driver);
225 }
226 
227