source: GPL/branches/uniaud32-2.1.x/drv32/dispatch.c@ 588

Last change on this file since 588 was 588, checked in by David Azarewicz, 9 years ago

Build system cleanup

File size: 17.3 KB
Line 
1/* $Id: dispatch.c,v 1.1.1.1 2003/07/02 13:56:56 eleph Exp $ */
2/*
3 * Strategy handlers for IOCtl and close
4 *
5 * (C) 2000-2002 InnoTek Systemberatung GmbH
6 * (C) 2000-2001 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
21 * USA.
22 *
23 */
24
25#define INCL_NOPMAPI
26#define INCL_DOSMISC
27#include <os2.h>
28
29#include <dbgos2.h>
30#include <devhelp.h>
31#include <devtype.h>
32#include <strategy.h>
33#include "devown.h"
34#include <ossidc.h>
35#include <ossidc32.h>
36#include <version.h>
37
38extern int cdecl printk(const char * fmt, ...);
39//******************************************************************************
40// Dispatch IOCtl requests received from the Strategy routine
41//******************************************************************************
42extern int GetUniaudCardInfo(ULONG deviceid, void *info);
43extern int GetUniaudControlNum(ULONG deviceid);
44extern int GetUniaudControls(ULONG deviceid, void *pids);
45extern int GetUniaudControlInfo(ULONG deviceid, ULONG id, void *info);
46extern int GetUniaudControlValueGet(ULONG deviceid, ULONG id, void *value);
47extern int GetUniaudControlValuePut(ULONG deviceid, ULONG id, void *value);
48extern int GetNumberOfPcm(int card_id);
49extern int GetUniaudPcmCaps(ULONG deviceid, void *caps);
50extern int SetPCMInstance(int card_id, int pcm);
51extern int WaitForControlChange(int card_id, int timeout);
52extern int GetNumberOfCards(void);
53extern OSSRET OSS32_WaveOpen(ULONG deviceid, ULONG streamtype, OSSSTREAMID *pStreamId, int pcm, USHORT fileid);
54extern OSSRET OSS32_WaveClose(OSSSTREAMID streamid);
55extern int UniaudIoctlHWRefine(OSSSTREAMID streamid, void *pHwParams);
56extern int UniaudIoctlHWParamSet(OSSSTREAMID streamid, void *pHwParams);
57extern int UniaudIoctlSWParamSet(OSSSTREAMID streamid, void *pSwParams);
58extern int UniaudIoctlPCMStatus(OSSSTREAMID streamid, void *pstatus);
59extern int UniaudIoctlPCMWrite(OSSSTREAMID streamid, char *buf, int size);
60extern int UniaudIoctlPCMRead(OSSSTREAMID streamid, char *buf, int size);
61extern int UniaudIoctlPCMPrepare(OSSSTREAMID streamid);
62extern int UniaudIoctlPCMStart(OSSSTREAMID streamid);
63extern int UniaudIoctlPCMDrop(OSSSTREAMID streamid);
64extern int UniaudIoctlPCMResume(OSSSTREAMID streamid, int pause);
65extern void UniaudCloseAll(USHORT fileid);
66extern int WaitForPCMInterrupt(void *file, int timeout);
67extern int unlock_all;
68extern int OSS32_CloseUNI16(void);
69extern int UniaudCtlGetPowerState(ULONG deviceid, void *state);
70extern int UniaudCtlSetPowerState(ULONG deviceid, void *state);
71
72typedef UCHAR LOCKHANDLE[12];
73
74/*
75 * structure passed to pcm open ioctl
76 */
77#pragma pack(1)
78typedef struct ioctl_pcm {
79 ULONG deviceid; // card number
80 ULONG streamtype; // type of stream (play or record)
81 ULONG pcm; // pcm instance
82 int size; // data size
83 ULONG ret; // return code
84} ioctl_pcm;
85#pragma pack()
86
87ULONG StratIOCtl(REQPACKET __far* rp)
88{
89 USHORT rc = 0;;
90 LOCKHANDLE lhParm, lhData;
91 LINEAR linParm, linData;
92 ULONG pages;
93 ULONG *pData;
94 ULONG card_id;
95 ULONG ctl_id;
96
97 if (rp->ioctl.bCategory != CAT_IOCTL_OSS32)
98 {
99 //printk("not our cat %x. func %x\n", rp->Category, rp->Function);
100 // not our category, exit with error
101 return (RPERR_BADCOMMAND | RPDONE);
102 }
103
104 #ifdef DEBUG
105 //printk("StratIOCtl 0x%x\n", rp->Function);
106 #endif
107 // printk("cmd: %x, len: %i, pack: %x\n",rp->Function, rp->ioctl.usParmLen, rp->ParmPacket);
108 // work with Parm Packet
109 if ((rp->ioctl.usParmLen != 0 ||
110 rp->ioctl.bFunction == IOCTL_OSS32_ATTACH /*16 bit ioctl*/) &&
111 ((rp->ioctl.pvParm & 0xfffcffff) != 0))
112 {
113 // got Parm Packet
114 rc = DevVirtToLin((USHORT)((ULONG)(rp->ioctl.pvParm) >> 16),
115 (ULONG)((USHORT)(rp->ioctl.pvParm)),
116 (UCHAR * __far *)&linParm);
117
118 if (rc == 0)
119 {
120 if (rp->ioctl.bFunction == IOCTL_OSS32_ATTACH)
121 {
122 rc = DevVMLock(VMDHL_LONG, (ULONG)linParm, 4, (LINEAR)-1L, lhParm, (UCHAR*)&pages);
123 }
124 else
125 {
126 rc = DevVMLock(VMDHL_LONG, (ULONG)linParm, rp->ioctl.usParmLen, (LINEAR)-1L, lhParm, (UCHAR*)&pages);
127 }
128
129 if (rc != 0)
130 {
131 printk("error in DevVMLock rc = %i\n",rc);
132 return (RPERR_PARAMETER | RPDONE);
133 }
134 } else
135 {
136 printk("error in VirtToLin rc = %i\n",rc);
137 return (RPERR_PARAMETER | RPDONE);
138 }
139 } else
140 {
141 // no Parm Packet
142 linParm = NULL;
143 }
144
145 // work with Data Packet
146 if ((rp->ioctl.usDataLen != 0) &&
147 ((rp->ioctl.pvData & 0xfffcffff) != 0))
148 {
149 // got Data Packet
150 rc = DevVirtToLin((USHORT)((ULONG)(rp->ioctl.pvData) >> 16),
151 (ULONG)((USHORT)(rp->ioctl.pvData)),
152 (UCHAR * __far *)&linData);
153 if (rc == 0)
154 {
155 rc = DevVMLock(VMDHL_LONG, (ULONG)linData, rp->ioctl.usDataLen, (LINEAR)-1L, lhData,
156 (UCHAR*)&pages);
157 } else
158 printk("error in VirtToLin rc = %i\n",rc);
159
160 if (rc != 0)
161 {
162
163 printk("error in DevVMLock rc = %i\n",rc);
164 // error in VirtToLin or DevVMLock
165 if (linParm != NULL)
166 {
167 // linParm present & locked, must to unlock it
168 DevVMUnLock(lhParm);
169 }
170 return (RPERR_PARAMETER | RPDONE);
171 }
172 } else
173 {
174 // no Data Packet
175 linData = NULL;
176 }
177
178 // functions handling
179 rc = RPDONE; // ok by default
180
181 switch(rp->ioctl.bFunction)
182 {
183 case IOCTL_OSS32_ATTACH:
184 {
185 card_id = (ULONG) *linParm;
186 // Check if audio init was successful
187 if (OSS32_QueryNames(card_id, NULL, 0, NULL, 0, FALSE) != OSSERR_SUCCESS)
188 {
189 rc = RPERR_GENERAL | RPDONE;
190 }
191 } break;
192
193 case IOCTL_OSS32_VERSION:
194 {
195 if (rp->ioctl.usDataLen < sizeof(ULONG))
196 {
197 // invalid Data Pkt
198 rc = RPERR_PARAMETER | RPDONE;
199 break;
200 }
201 pData = (ULONG *) linData;
202 (*pData) = RM_VERSION;
203
204 } break;
205
206 case IOCTL_OSS32_GET_PCM_NUM:
207 {
208 if (rp->ioctl.usDataLen < sizeof(ULONG))
209 {
210 // invalid Data Pkt
211 rc = RPERR_PARAMETER | RPDONE;
212 break;
213 }
214 card_id = (ULONG) *linParm;
215 pData = (ULONG *) linData;
216 (*pData) = GetNumberOfPcm(card_id);
217
218 } break;
219
220 case IOCTL_OSS32_CARDS_NUM:
221 if (rp->ioctl.usDataLen < sizeof(ULONG))
222 {
223 // invalid Data Pkt
224 rc = RPERR_PARAMETER | RPDONE;
225 break;
226 }
227 pData = (ULONG *) linData;
228 (*pData) = GetNumberOfCards();
229 break;
230
231 case IOCTL_OSS32_PCM_CAPS:
232 {
233 if (rp->ioctl.usDataLen < sizeof(ULONG))
234 {
235 // invalid Data Pkt
236 rc = RPERR_PARAMETER | RPDONE;
237 break;
238 }
239 card_id = (ULONG) *linParm;
240 pData = (ULONG *) linData;
241 GetUniaudPcmCaps(card_id,(void*)*pData);
242 } break;
243
244 case IOCTL_OSS32_CARD_INFO:
245 {
246 if (rp->ioctl.usDataLen < sizeof(ULONG))
247 {
248 // invalid Data Pkt
249 rc = RPERR_PARAMETER | RPDONE;
250 break;
251 }
252 pData = (ULONG *) linData;
253 card_id = (ULONG) *linParm;
254 GetUniaudCardInfo(card_id,(void*)*pData);
255 } break;
256
257 case IOCTL_OSS32_GET_POWER_STATE:
258 {
259 if (rp->ioctl.usDataLen < sizeof(ULONG))
260 {
261 // invalid Data Pkt
262 rc = RPERR_PARAMETER | RPDONE;
263 break;
264 }
265 pData = (ULONG *) linData;
266 card_id = (ULONG) *linParm;
267 UniaudCtlGetPowerState(card_id,(void*)*pData);
268 } break;
269
270 case IOCTL_OSS32_SET_POWER_STATE:
271 {
272 if (rp->ioctl.usDataLen < sizeof(ULONG))
273 {
274 // invalid Data Pkt
275 rc = RPERR_PARAMETER | RPDONE;
276 break;
277 }
278 pData = (ULONG *) linData;
279 card_id = (ULONG) *linParm;
280 UniaudCtlSetPowerState(card_id,(void*)*pData);
281 } break;
282
283 case IOCTL_OSS32_GET_CNTRLS_NUM:
284 {
285 if (rp->ioctl.usDataLen < sizeof(ULONG))
286 {
287 // invalid Data Pkt
288 rc = RPERR_PARAMETER | RPDONE;
289 break;
290 }
291 pData = (ULONG *) linData;
292 card_id = (ULONG) *linParm;
293 (*pData) = GetUniaudControlNum(card_id);
294
295 } break;
296
297
298 case IOCTL_OSS32_GET_CNTRLS:
299 {
300 if (rp->ioctl.usDataLen < sizeof(ULONG))
301 {
302 // invalid Data Pkt
303 rc = RPERR_PARAMETER | RPDONE;
304 break;
305 }
306 pData = (ULONG *) linData;
307 card_id = (ULONG) *linParm;
308 GetUniaudControls(card_id,(void*)*pData);
309 } break;
310
311 case IOCTL_OSS32_CNTRL_INFO:
312 {
313
314 if (rp->ioctl.usDataLen < sizeof(ULONG))
315 {
316 // invalid Data Pkt
317 rc = RPERR_PARAMETER | RPDONE;
318 break;
319 }
320
321 if (rp->ioctl.usParmLen < sizeof(ULONG))
322 {
323 // invalid Data Pkt
324 rc = RPERR_PARAMETER | RPDONE;
325 break;
326 }
327
328 pData = (ULONG *) linData;
329 ULONG id = *((ULONG *)linParm);
330 card_id = (id >> 16) & 0x0000FFFF;
331 ctl_id = id & 0x0000FFFF;
332// printk("id: %x, card: %x, ctl: %x\n",id, card_id, ctl_id);
333 GetUniaudControlInfo(card_id, ctl_id, (void*)*pData);
334 } break;
335
336 case IOCTL_OSS32_CNTRL_GET:
337 {
338 if (rp->ioctl.usDataLen < sizeof(ULONG))
339 {
340 // invalid Data Pkt
341 rc = RPERR_PARAMETER | RPDONE;
342 break;
343 }
344
345 if (rp->ioctl.usParmLen < sizeof(ULONG))
346 {
347 // invalid Data Pkt
348 rc = RPERR_PARAMETER | RPDONE;
349 break;
350 }
351
352 pData = (ULONG *) linData;
353 ULONG id = *((ULONG *)linParm);
354 card_id = (id >> 16) & 0x0000FFFF;
355 ctl_id = id & 0x0000FFFF;
356
357 GetUniaudControlValueGet(card_id, ctl_id,(void*)*pData);
358 } break;
359
360 case IOCTL_OSS32_CNTRL_PUT:
361 {
362
363 if (rp->ioctl.usDataLen < sizeof(ULONG)) {
364 // invalid Data Pkt
365 rc = RPERR_PARAMETER | RPDONE;
366 break;
367 }
368
369 if (rp->ioctl.usParmLen < sizeof(ULONG)) {
370 // invalid Data Pkt
371 rc = RPERR_PARAMETER | RPDONE;
372 break;
373 }
374
375 pData = (ULONG *)linData;
376 ULONG id = *((ULONG *)linParm);
377 card_id = (id >> 16) & 0x0000FFFF;
378 ctl_id = id & 0x0000FFFF;
379
380 GetUniaudControlValuePut(card_id, ctl_id,(void*)*pData);
381 } break;
382
383 case IOCTL_OSS32_SET_PCM:
384 {
385
386 if (rp->ioctl.usParmLen < sizeof(ULONG))
387 {
388 // invalid Data Pkt
389 rc = RPERR_PARAMETER | RPDONE;
390 break;
391 }
392
393 ULONG pcm = (ULONG) *linParm;
394
395 printk("set PCM %i\n",pcm);
396 SetPCMInstance(0, pcm);
397 } break;
398
399 case IOCTL_OSS32_CNTRL_WAIT:
400 {
401 if (rp->ioctl.usDataLen < sizeof(ULONG))
402 {
403 // invalid Data Pkt
404 rc = RPERR_PARAMETER | RPDONE;
405 break;
406 }
407 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
408 pData = (ULONG *) linData;
409 (*pData) = WaitForControlChange(pcm->deviceid, pcm->streamtype);
410 }
411 break;
412 case IOCTL_OSS32_PCM_OPEN:
413 {
414 pData = (ULONG *)linData;
415 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
416 // close all pcms from uniaud16 first
417 pcm->ret = OSS32_WaveOpen(pcm->deviceid, pcm->streamtype, pData, pcm->pcm, rp->ioctl.usSysFileNum);
418 }
419 break;
420
421 case IOCTL_OSS32_PCM_CLOSE:
422 {
423 ULONG alsa_id = *((ULONG *)linParm);
424 OSS32_WaveClose(alsa_id);
425 }
426 break;
427 case IOCTL_OSS32_PCM_READ:
428 {
429 char *pData1 = (char *)linData;
430 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
431 pcm->ret = UniaudIoctlPCMRead(pcm->deviceid, pData1, pcm->size);
432 }
433 break;
434 case IOCTL_OSS32_PCM_WRITE:
435 {
436 char *pData1 = (char *)linData;
437 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
438 pcm->ret = UniaudIoctlPCMWrite(pcm->deviceid, pData1, pcm->size);
439 }
440 break;
441 case IOCTL_OSS32_PCM_PAUSE:
442 {
443 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
444 pcm->ret = UniaudIoctlPCMResume(pcm->deviceid, 0);
445 }
446 break;
447 case IOCTL_OSS32_PCM_RESUME:
448 {
449 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
450 pcm->ret = UniaudIoctlPCMResume(pcm->deviceid, 1);
451 }
452 break;
453 case IOCTL_OSS32_PCM_START:
454 {
455 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
456 pcm->ret = UniaudIoctlPCMStart(pcm->deviceid);
457 }
458 break;
459 case IOCTL_OSS32_PCM_DROP:
460 {
461 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
462 pcm->ret = UniaudIoctlPCMDrop(pcm->deviceid);
463 }
464 break;
465 case IOCTL_OSS32_PCM_DRAIN:
466 break;
467 case IOCTL_OSS32_PCM_STATUS:
468 {
469 void *pData1 = (void *)linData;
470 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
471 pcm->ret = UniaudIoctlPCMStatus(pcm->deviceid, pData1);
472 }
473 break;
474 case IOCTL_OSS32_PCM_REFINEHWPARAMS:
475 {
476 void *pData1 = (void *)linData;
477 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
478 pcm->ret = UniaudIoctlHWRefine(pcm->deviceid, pData1);
479 }
480 break;
481 case IOCTL_OSS32_PCM_SETHWPARAMS:
482 {
483 void *pData1 = (void *)linData;
484 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
485 pcm->ret = UniaudIoctlHWParamSet(pcm->deviceid, pData1);
486 }
487 break;
488 case IOCTL_OSS32_PCM_SETSWPARAMS:
489 {
490 void *pData1 = (void *)linData;
491 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
492 pcm->ret = UniaudIoctlSWParamSet(pcm->deviceid, pData1);
493 }
494 break;
495 case IOCTL_OSS32_PCM_PREPARE:
496 {
497 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
498 pcm->ret = UniaudIoctlPCMPrepare(pcm->deviceid);
499 }
500 break;
501
502 case IOCTL_OSS32_PCM_CLOSE_ALL:
503 {
504 int unlock = (int)*linParm;
505 if (unlock)
506 unlock_all = 1;
507 else
508 UniaudCloseAll(0);
509 }
510 break;
511 case IOCTL_OSS32_PCM_CLOSE_16:
512 OSS32_CloseUNI16();
513 break;
514 case IOCTL_OSS32_PCM_WAIT_INT:
515 {
516 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
517 pcm->ret = WaitForPCMInterrupt((void*)pcm->deviceid, pcm->streamtype);
518 }
519 break;
520
521 default:
522 {
523 printk("invalid function code %i\n",rp->ioctl.bFunction);
524 // invalid function code
525 rc = RPERR_PARAMETER | RPDONE;
526 } break;
527 }
528
529 // unlock Parm & Data if needed
530 if (linParm != NULL)
531 {
532 // linParm present & locked, must to unlock it
533 DevVMUnLock(lhParm);
534 }
535 if (linData != NULL)
536 {
537 // linData present & locked, must to unlock it
538 DevVMUnLock(lhData);
539 }
540
541 // all done
542 return (rc);
543}
544
545//******************************************************************************
546// Dispatch Close requests received from the strategy routine
547//******************************************************************************
548ULONG StratClose(REQPACKET __far* rp)
549{
550 // only called if device successfully opened
551 // printk("strat close\n");
552 numOS2Opens--;
553
554 UniaudCloseAll(rp->open_close.usSysFileNum);
555
556 if (numOS2Opens == 0) {
557 deviceOwner = DEV_NO_OWNER;
558 }
559 return(RPDONE);
560}
561
Note: See TracBrowser for help on using the repository browser.