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

Last change on this file since 543 was 543, checked in by David Azarewicz, 15 years ago

Merge changes from trunk

File size: 17.9 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 <devrp.h>
33#include "devown.h"
34#include <ossidc.h>
35#include <ossidc32.h>
36#include <version.h>
37
38extern "C" int cdecl printk(const char * fmt, ...);
39//******************************************************************************
40// Dispatch IOCtl requests received from the Strategy routine
41//******************************************************************************
42extern "C" int GetUniaudCardInfo(ULONG deviceid, void *info);
43extern "C" int GetUniaudControlNum(ULONG deviceid);
44extern "C" int GetUniaudControls(ULONG deviceid, void *pids);
45extern "C" int GetUniaudControlInfo(ULONG deviceid, ULONG id, void *info);
46extern "C" int GetUniaudControlValueGet(ULONG deviceid, ULONG id, void *value);
47extern "C" int GetUniaudControlValuePut(ULONG deviceid, ULONG id, void *value);
48extern "C" int GetNumberOfPcm(int card_id);
49extern "C" int GetUniaudPcmCaps(ULONG deviceid, void *caps);
50extern "C" int SetPCMInstance(int card_id, int pcm);
51extern "C" int WaitForControlChange(int card_id, int timeout);
52extern "C" int GetNumberOfCards(void);
53extern "C" OSSRET OSS32_WaveOpen(ULONG deviceid, ULONG streamtype, OSSSTREAMID *pStreamId, int pcm, USHORT fileid);
54extern "C" OSSRET OSS32_WaveClose(OSSSTREAMID streamid);
55extern "C" int UniaudIoctlHWRefine(OSSSTREAMID streamid, void *pHwParams);
56extern "C" int UniaudIoctlHWParamSet(OSSSTREAMID streamid, void *pHwParams);
57extern "C" int UniaudIoctlSWParamSet(OSSSTREAMID streamid, void *pSwParams);
58extern "C" int UniaudIoctlPCMStatus(OSSSTREAMID streamid, void *pstatus);
59extern "C" int UniaudIoctlPCMWrite(OSSSTREAMID streamid, char *buf, int size);
60extern "C" int UniaudIoctlPCMRead(OSSSTREAMID streamid, char *buf, int size);
61extern "C" int UniaudIoctlPCMPrepare(OSSSTREAMID streamid);
62extern "C" int UniaudIoctlPCMStart(OSSSTREAMID streamid);
63extern "C" int UniaudIoctlPCMDrop(OSSSTREAMID streamid);
64extern "C" int UniaudIoctlPCMResume(OSSSTREAMID streamid, int pause);
65extern "C" void UniaudCloseAll(USHORT fileid);
66extern "C" int WaitForPCMInterrupt(void *file, int timeout);
67extern "C" int unlock_all;
68extern "C" int OSS32_CloseUNI16(void);
69extern "C" int UniaudCtlGetPowerState(ULONG deviceid, void *state);
70extern "C" 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(RP __far* _rp)
88{
89 RPIOCtl __far* rp = (RPIOCtl __far*)_rp;
90 USHORT rc = 0;;
91 LOCKHANDLE lhParm, lhData;
92 LINEAR linParm, linData;
93 ULONG pages;
94 ULONG *pData;
95 ULONG card_id;
96 ULONG ctl_id;
97
98 if (rp->Category != CAT_IOCTL_OSS32)
99 {
100// printk("not our cat %x. func %x\n", rp->Category, rp->Function);
101 // not our category, exit with error
102 return (RPERR_COMMAND | RPDONE);
103 }
104
105#ifdef DEBUG
106 //printk("StratIOCtl 0x%x\n", rp->Function);
107#endif
108// printk("cmd: %x, len: %i, pack: %x\n",rp->Function, rp->ParmLength, rp->ParmPacket);
109 // work with Parm Packet
110 if ((rp->ParmLength != 0 ||
111 rp->Function == IOCTL_OSS32_ATTACH /*16 bit ioctl*/) &&
112 ((rp->ParmPacket & 0xfffcffff) != 0))
113 {
114 // got Parm Packet
115 rc = DevVirtToLin((USHORT)((ULONG)(rp->ParmPacket) >> 16),
116 (ULONG)((USHORT)(rp->ParmPacket)),
117 (UCHAR * __far *)&linParm);
118
119 if (rc == 0)
120 {
121 if (rp->Function == IOCTL_OSS32_ATTACH)
122 {
123 rc = DevVMLock(VMDHL_LONG,
124 (ULONG)linParm,
125 4,
126 (LINEAR)-1L,
127 lhParm,
128 (UCHAR*)&pages);
129 }else
130 {
131 rc = DevVMLock(VMDHL_LONG,
132 (ULONG)linParm,
133 rp->ParmLength,
134 (LINEAR)-1L,
135 lhParm,
136 (UCHAR*)&pages);
137 }
138
139 if (rc != 0)
140 {
141 printk("error in DevVMLock rc = %i\n",rc);
142 return (RPERR_PARAMETER | RPDONE);
143 }
144 } else
145 {
146 printk("error in VirtToLin rc = %i\n",rc);
147 return (RPERR_PARAMETER | RPDONE);
148 }
149 } else
150 {
151 // no Parm Packet
152 linParm = NULL;
153 }
154
155 // work with Data Packet
156 if ((rp->DataLength != 0) &&
157 ((rp->DataPacket & 0xfffcffff) != 0))
158 {
159 // got Data Packet
160 rc = DevVirtToLin((USHORT)((ULONG)(rp->DataPacket) >> 16),
161 (ULONG)((USHORT)(rp->DataPacket)),
162 (UCHAR * __far *)&linData);
163 if (rc == 0)
164 {
165 rc = DevVMLock(VMDHL_LONG,
166 (ULONG)linData,
167 rp->DataLength,
168 (LINEAR)-1L,
169 lhData,
170 (UCHAR*)&pages);
171 } else
172 printk("error in VirtToLin rc = %i\n",rc);
173
174 if (rc != 0)
175 {
176
177 printk("error in DevVMLock rc = %i\n",rc);
178 // error in VirtToLin or DevVMLock
179 if (linParm != NULL)
180 {
181 // linParm present & locked, must to unlock it
182 DevVMUnLock(lhParm);
183 }
184 return (RPERR_PARAMETER | RPDONE);
185 }
186 } else
187 {
188 // no Data Packet
189 linData = NULL;
190 }
191
192 // functions handling
193 rc = RPDONE; // ok by default
194
195 switch(rp->Function)
196 {
197 case IOCTL_OSS32_ATTACH:
198 {
199 card_id = (ULONG) *linParm;
200 // Check if audio init was successful
201 if (OSS32_QueryNames(card_id, NULL, 0,
202 NULL, 0, FALSE) != OSSERR_SUCCESS)
203 {
204 rc = RPERR_GENERAL | RPDONE;
205 }
206 } break;
207
208 case IOCTL_OSS32_VERSION:
209 {
210 if (rp->DataLength < sizeof(ULONG))
211 {
212 // invalid Data Pkt
213 rc = RPERR_PARAMETER | RPDONE;
214 break;
215 }
216 pData = (ULONG *) linData;
217 (*pData) = RM_VERSION;
218
219 } break;
220
221 case IOCTL_OSS32_GET_PCM_NUM:
222 {
223 if (rp->DataLength < sizeof(ULONG))
224 {
225 // invalid Data Pkt
226 rc = RPERR_PARAMETER | RPDONE;
227 break;
228 }
229 card_id = (ULONG) *linParm;
230 pData = (ULONG *) linData;
231 (*pData) = GetNumberOfPcm(card_id);
232
233 } break;
234
235 case IOCTL_OSS32_CARDS_NUM:
236 if (rp->DataLength < sizeof(ULONG))
237 {
238 // invalid Data Pkt
239 rc = RPERR_PARAMETER | RPDONE;
240 break;
241 }
242 pData = (ULONG *) linData;
243 (*pData) = GetNumberOfCards();
244 break;
245
246 case IOCTL_OSS32_PCM_CAPS:
247 {
248 if (rp->DataLength < sizeof(ULONG))
249 {
250 // invalid Data Pkt
251 rc = RPERR_PARAMETER | RPDONE;
252 break;
253 }
254 card_id = (ULONG) *linParm;
255 pData = (ULONG *) linData;
256 GetUniaudPcmCaps(card_id,(void*)*pData);
257 } break;
258
259 case IOCTL_OSS32_CARD_INFO:
260 {
261 if (rp->DataLength < sizeof(ULONG))
262 {
263 // invalid Data Pkt
264 rc = RPERR_PARAMETER | RPDONE;
265 break;
266 }
267 pData = (ULONG *) linData;
268 card_id = (ULONG) *linParm;
269 GetUniaudCardInfo(card_id,(void*)*pData);
270 } break;
271
272 case IOCTL_OSS32_GET_POWER_STATE:
273 {
274 if (rp->DataLength < sizeof(ULONG))
275 {
276 // invalid Data Pkt
277 rc = RPERR_PARAMETER | RPDONE;
278 break;
279 }
280 pData = (ULONG *) linData;
281 card_id = (ULONG) *linParm;
282 UniaudCtlGetPowerState(card_id,(void*)*pData);
283 } break;
284
285 case IOCTL_OSS32_SET_POWER_STATE:
286 {
287 if (rp->DataLength < sizeof(ULONG))
288 {
289 // invalid Data Pkt
290 rc = RPERR_PARAMETER | RPDONE;
291 break;
292 }
293 pData = (ULONG *) linData;
294 card_id = (ULONG) *linParm;
295 UniaudCtlSetPowerState(card_id,(void*)*pData);
296 } break;
297
298 case IOCTL_OSS32_GET_CNTRLS_NUM:
299 {
300 if (rp->DataLength < 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 (*pData) = GetUniaudControlNum(card_id);
309
310 } break;
311
312
313 case IOCTL_OSS32_GET_CNTRLS:
314 {
315 if (rp->DataLength < sizeof(ULONG))
316 {
317 // invalid Data Pkt
318 rc = RPERR_PARAMETER | RPDONE;
319 break;
320 }
321 pData = (ULONG *) linData;
322 card_id = (ULONG) *linParm;
323 GetUniaudControls(card_id,(void*)*pData);
324 } break;
325
326 case IOCTL_OSS32_CNTRL_INFO:
327 {
328
329 if (rp->DataLength < sizeof(ULONG))
330 {
331 // invalid Data Pkt
332 rc = RPERR_PARAMETER | RPDONE;
333 break;
334 }
335
336 if (rp->ParmLength < sizeof(ULONG))
337 {
338 // invalid Data Pkt
339 rc = RPERR_PARAMETER | RPDONE;
340 break;
341 }
342
343 pData = (ULONG *) linData;
344 ULONG id = *((ULONG *)linParm);
345 card_id = (id >> 16) & 0x0000FFFF;
346 ctl_id = id & 0x0000FFFF;
347// printk("id: %x, card: %x, ctl: %x\n",id, card_id, ctl_id);
348 GetUniaudControlInfo(card_id, ctl_id, (void*)*pData);
349 } break;
350
351 case IOCTL_OSS32_CNTRL_GET:
352 {
353 if (rp->DataLength < sizeof(ULONG))
354 {
355 // invalid Data Pkt
356 rc = RPERR_PARAMETER | RPDONE;
357 break;
358 }
359
360 if (rp->ParmLength < sizeof(ULONG))
361 {
362 // invalid Data Pkt
363 rc = RPERR_PARAMETER | RPDONE;
364 break;
365 }
366
367 pData = (ULONG *) linData;
368 ULONG id = *((ULONG *)linParm);
369 card_id = (id >> 16) & 0x0000FFFF;
370 ctl_id = id & 0x0000FFFF;
371
372 GetUniaudControlValueGet(card_id, ctl_id,(void*)*pData);
373 } break;
374
375 case IOCTL_OSS32_CNTRL_PUT:
376 {
377
378 if (rp->DataLength < sizeof(ULONG)) {
379 // invalid Data Pkt
380 rc = RPERR_PARAMETER | RPDONE;
381 break;
382 }
383
384 if (rp->ParmLength < sizeof(ULONG)) {
385 // invalid Data Pkt
386 rc = RPERR_PARAMETER | RPDONE;
387 break;
388 }
389
390 pData = (ULONG *)linData;
391 ULONG id = *((ULONG *)linParm);
392 card_id = (id >> 16) & 0x0000FFFF;
393 ctl_id = id & 0x0000FFFF;
394
395 GetUniaudControlValuePut(card_id, ctl_id,(void*)*pData);
396 } break;
397
398 case IOCTL_OSS32_SET_PCM:
399 {
400
401 if (rp->ParmLength < sizeof(ULONG))
402 {
403 // invalid Data Pkt
404 rc = RPERR_PARAMETER | RPDONE;
405 break;
406 }
407
408 ULONG pcm = (ULONG) *linParm;
409
410 printk("set PCM %i\n",pcm);
411 SetPCMInstance(0, pcm);
412 } break;
413
414 case IOCTL_OSS32_CNTRL_WAIT:
415 {
416 if (rp->DataLength < sizeof(ULONG))
417 {
418 // invalid Data Pkt
419 rc = RPERR_PARAMETER | RPDONE;
420 break;
421 }
422 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
423 pData = (ULONG *) linData;
424 (*pData) = WaitForControlChange(pcm->deviceid, pcm->streamtype);
425 }
426 break;
427 case IOCTL_OSS32_PCM_OPEN:
428 {
429 pData = (ULONG *)linData;
430 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
431 // close all pcms from uniaud16 first
432 pcm->ret = OSS32_WaveOpen(pcm->deviceid, pcm->streamtype, pData, pcm->pcm, rp->FileID);
433 }
434 break;
435
436 case IOCTL_OSS32_PCM_CLOSE:
437 {
438 ULONG alsa_id = *((ULONG *)linParm);
439 OSS32_WaveClose(alsa_id);
440 }
441 break;
442 case IOCTL_OSS32_PCM_READ:
443 {
444 char *pData1 = (char *)linData;
445 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
446 pcm->ret = UniaudIoctlPCMRead(pcm->deviceid, pData1, pcm->size);
447 }
448 break;
449 case IOCTL_OSS32_PCM_WRITE:
450 {
451 char *pData1 = (char *)linData;
452 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
453 pcm->ret = UniaudIoctlPCMWrite(pcm->deviceid, pData1, pcm->size);
454 }
455 break;
456 case IOCTL_OSS32_PCM_PAUSE:
457 {
458 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
459 pcm->ret = UniaudIoctlPCMResume(pcm->deviceid, 0);
460 }
461 break;
462 case IOCTL_OSS32_PCM_RESUME:
463 {
464 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
465 pcm->ret = UniaudIoctlPCMResume(pcm->deviceid, 1);
466 }
467 break;
468 case IOCTL_OSS32_PCM_START:
469 {
470 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
471 pcm->ret = UniaudIoctlPCMStart(pcm->deviceid);
472 }
473 break;
474 case IOCTL_OSS32_PCM_DROP:
475 {
476 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
477 pcm->ret = UniaudIoctlPCMDrop(pcm->deviceid);
478 }
479 break;
480 case IOCTL_OSS32_PCM_DRAIN:
481 break;
482 case IOCTL_OSS32_PCM_STATUS:
483 {
484 void *pData1 = (void *)linData;
485 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
486 pcm->ret = UniaudIoctlPCMStatus(pcm->deviceid, pData1);
487 }
488 break;
489 case IOCTL_OSS32_PCM_REFINEHWPARAMS:
490 {
491 void *pData1 = (void *)linData;
492 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
493 pcm->ret = UniaudIoctlHWRefine(pcm->deviceid, pData1);
494 }
495 break;
496 case IOCTL_OSS32_PCM_SETHWPARAMS:
497 {
498 void *pData1 = (void *)linData;
499 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
500 pcm->ret = UniaudIoctlHWParamSet(pcm->deviceid, pData1);
501 }
502 break;
503 case IOCTL_OSS32_PCM_SETSWPARAMS:
504 {
505 void *pData1 = (void *)linData;
506 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
507 pcm->ret = UniaudIoctlSWParamSet(pcm->deviceid, pData1);
508 }
509 break;
510 case IOCTL_OSS32_PCM_PREPARE:
511 {
512 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
513 pcm->ret = UniaudIoctlPCMPrepare(pcm->deviceid);
514 }
515 break;
516
517 case IOCTL_OSS32_PCM_CLOSE_ALL:
518 {
519 int unlock = (int)*linParm;
520 if (unlock)
521 unlock_all = 1;
522 else
523 UniaudCloseAll(0);
524 }
525 break;
526 case IOCTL_OSS32_PCM_CLOSE_16:
527 OSS32_CloseUNI16();
528 break;
529 case IOCTL_OSS32_PCM_WAIT_INT:
530 {
531 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
532 pcm->ret = WaitForPCMInterrupt((void*)pcm->deviceid, pcm->streamtype);
533 }
534 break;
535
536 default:
537 {
538 printk("invalid function code %i\n",rp->Function);
539 // invalid function code
540 rc = RPERR_PARAMETER | RPDONE;
541 } break;
542 }
543
544 // unlock Parm & Data if needed
545 if (linParm != NULL)
546 {
547 // linParm present & locked, must to unlock it
548 DevVMUnLock(lhParm);
549 }
550 if (linData != NULL)
551 {
552 // linData present & locked, must to unlock it
553 DevVMUnLock(lhData);
554 }
555
556 // all done
557 return (rc);
558}
559
560//******************************************************************************
561// Dispatch Close requests received from the strategy routine
562//******************************************************************************
563ULONG StratClose(RP __far* _rp)
564{
565 RPOpenClose __far* rp = (RPOpenClose __far*)_rp;
566
567 // only called if device successfully opened
568// printk("strat close\n");
569 numOS2Opens--;
570
571 UniaudCloseAll(rp->FileID);
572
573 if (numOS2Opens == 0) {
574 deviceOwner = DEV_NO_OWNER;
575 }
576 return(RPDONE);
577}
578//******************************************************************************
579//******************************************************************************
Note: See TracBrowser for help on using the repository browser.