source: GPL/drv32/dispatch.c@ 18

Last change on this file since 18 was 18, checked in by vladest, 20 years ago

initial import

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