Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / dev / sound / isa / i386 / patmgr.c
1 /*
2  * sound/patmgr.c
3  * 
4  * The patch maneger interface for the /dev/sequencer
5  * 
6  * Copyright by Hannu Savolainen 1993
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met: 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer. 2.
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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
17  * 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 AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  * 
28  */
29
30 #define PATMGR_C
31 #include <i386/isa/sound/sound_config.h>
32
33 #if defined(CONFIG_SEQUENCER)
34
35 static int     *server_procs[MAX_SYNTH_DEV] = {NULL};
36 static volatile struct snd_wait server_wait_flag[MAX_SYNTH_DEV] = { {0}};
37
38 static struct patmgr_info *mbox[MAX_SYNTH_DEV] = {NULL};
39 static volatile int msg_direction[MAX_SYNTH_DEV] = {0};
40
41 static int      pmgr_opened[MAX_SYNTH_DEV] = {0};
42
43 #define A_TO_S  1
44 #define S_TO_A  2
45
46 static int     *appl_proc = NULL;
47 static volatile struct snd_wait appl_wait_flag =
48 {0};
49
50 int
51 pmgr_open(int dev)
52 {
53     if (dev < 0 || dev >= num_synths)
54         return -(ENXIO);
55
56     if (pmgr_opened[dev])
57         return -(EBUSY);
58     pmgr_opened[dev] = 1;
59
60     server_wait_flag[dev].aborting = 0;
61     server_wait_flag[dev].mode = WK_NONE;
62
63     return 0;
64 }
65
66 void
67 pmgr_release(int dev)
68 {
69
70     if (mbox[dev]) {    /* Killed in action. Inform the client */
71
72         mbox[dev]->key = PM_ERROR;
73         mbox[dev]->parm1 = -(EIO);
74
75         if ((appl_wait_flag.mode & WK_SLEEP)) {
76             appl_wait_flag.mode = WK_WAKEUP;
77             wakeup(appl_proc);
78         };
79     }
80     pmgr_opened[dev] = 0;
81 }
82
83 int
84 pmgr_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
85 {
86     u_long   flags;
87     int             ok = 0;
88
89     if (count != sizeof(struct patmgr_info)) {
90         printf("PATMGR%d: Invalid read count\n", dev);
91         return -(EIO);
92     }
93     while (!ok && !(server_wait_flag[dev].aborting)) {
94         flags = splhigh();
95
96         while (!(mbox[dev] && msg_direction[dev] == A_TO_S) &&
97                !(server_wait_flag[dev].aborting)) {
98
99             int  chn;
100             server_procs[dev] = &chn;
101             DO_SLEEP(chn, server_wait_flag[dev], 0); 
102
103         }
104
105         if (mbox[dev] && msg_direction[dev] == A_TO_S) {
106
107             if (uiomove((char *) mbox[dev], count, buf)) {
108                 printf("sb: Bad copyout()!\n");
109             };
110             msg_direction[dev] = 0;
111             ok = 1;
112         }
113         splx(flags);
114
115     }
116
117     if (!ok)
118         return -(EINTR);
119     return count;
120 }
121
122 int
123 pmgr_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
124 {
125     u_long   flags;
126
127     if (count < 4) {
128         printf("PATMGR%d: Write count < 4\n", dev);
129         return -(EIO);
130     }
131     if (uiomove((char *) mbox[dev], 4, buf)) {
132         printf("sb: Bad copyin()!\n");
133     };
134
135     if (*(u_char *) mbox[dev] == SEQ_FULLSIZE) {
136         int             tmp_dev;
137
138         tmp_dev = ((u_short *) mbox[dev])[2];
139         if (tmp_dev != dev)
140             return -(ENXIO);
141
142         return synth_devs[dev]->load_patch(dev, *(u_short *) mbox[dev],
143                                                    buf, 4, count, 1);
144     }
145     if (count != sizeof(struct patmgr_info)) {
146         printf("PATMGR%d: Invalid write count\n", dev);
147         return -(EIO);
148     }
149     /*
150      * If everything went OK, there should be a preallocated buffer in
151      * the mailbox and a client waiting.
152      */
153
154     flags = splhigh();
155
156     if (mbox[dev] && !msg_direction[dev]) {
157
158         if (uiomove(&((char *) mbox[dev])[4], count - 4, buf)) {
159             printf("sb: Bad copyin()!\n");
160         };
161         msg_direction[dev] = S_TO_A;
162
163         if ((appl_wait_flag.mode & WK_SLEEP)) {
164             appl_wait_flag.mode = WK_WAKEUP;
165             wakeup(appl_proc);
166         }
167     }
168     splx(flags);
169
170     return count;
171 }
172
173 int
174 pmgr_access(int dev, struct patmgr_info * rec)
175 {
176     u_long   flags;
177     int             err = 0;
178
179     flags = splhigh();
180
181     if (mbox[dev])
182         printf("  PATMGR: Server %d mbox full. Why?\n", dev);
183     else {
184         int             chn;
185
186         rec->key = PM_K_COMMAND;
187         mbox[dev] = rec;
188         msg_direction[dev] = A_TO_S;
189
190         if ((server_wait_flag[dev].mode & WK_SLEEP)) {
191             server_wait_flag[dev].mode = WK_WAKEUP;
192             wakeup(server_procs[dev]);
193         }
194
195
196         appl_proc = &chn;
197         DO_SLEEP(chn, appl_wait_flag, 0);
198
199         if (msg_direction[dev] != S_TO_A) {
200             rec->key = PM_ERROR;
201             rec->parm1 = -(EIO);
202         } else if (rec->key == PM_ERROR) {
203             err = rec->parm1;
204             if (err > 0)
205                 err = -err;
206         }
207         mbox[dev] = NULL;
208         msg_direction[dev] = 0;
209     }
210
211     splx(flags);
212
213     return err;
214 }
215
216 int
217 pmgr_inform(int dev, int event, u_long p1, u_long p2, u_long p3, u_long p4)
218 {
219     u_long   flags;
220     int             err = 0;
221
222     struct patmgr_info *tmp_mbox;
223
224     if (!pmgr_opened[dev])
225         return 0;
226
227     tmp_mbox = (struct patmgr_info *) malloc(sizeof(struct patmgr_info), M_TEMP, M_WAITOK);
228
229     if (tmp_mbox == NULL) {
230         printf("pmgr: Couldn't allocate memory for a message\n");
231         return 0;
232     }
233     flags = splhigh();
234
235     if (mbox[dev])
236         printf("  PATMGR: Server %d mbox full. Why?\n", dev);
237     else {
238         int             chn;
239
240         mbox[dev] = tmp_mbox;
241         mbox[dev]->key = PM_K_EVENT;
242         mbox[dev]->command = event;
243         mbox[dev]->parm1 = p1;
244         mbox[dev]->parm2 = p2;
245         mbox[dev]->parm3 = p3;
246         msg_direction[dev] = A_TO_S;
247
248         if ((server_wait_flag[dev].mode & WK_SLEEP)) {
249             server_wait_flag[dev].mode = WK_WAKEUP;
250             wakeup(server_procs[dev]);
251         }
252
253
254         appl_proc = &chn;
255         DO_SLEEP(chn, appl_wait_flag, 0);
256
257         mbox[dev] = NULL;
258         msg_direction[dev] = 0;
259     }
260
261     splx(flags);
262     free(tmp_mbox, M_TEMP);
263
264     return err;
265 }
266
267 #endif