source: GPL/branches/uniaud-2.0/drv32/dispatch.c@ 313

Last change on this file since 313 was 235, checked in by Brendan Oakley, 18 years ago

New mkversion thanks to Mike, with BLDLEVEL and driver load output fixes from Allan

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