source: GPL/branches/uniaud32-next/drv32/dispatch.c@ 660

Last change on this file since 660 was 598, checked in by David Azarewicz, 8 years ago

Merged/reintegrated v2 branch into trunk. Trunk is now v2

File size: 18.7 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->ioctl.bFunction, rp->ioctl.usParmLen, rp->ioctl.pvParm);
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 dprintf(("OSS32_ATTACH\n"));
186 card_id = (ULONG) *linParm;
187 // Check if audio init was successful
188 if (OSS32_QueryNames(card_id, NULL, 0, NULL, 0, FALSE) != OSSERR_SUCCESS)
189 {
190 rc = RPERR_GENERAL | RPDONE;
191 }
192 } break;
193
194 case IOCTL_OSS32_VERSION:
195 {
196 dprintf(("OSS32_VERSION\n"));
197 if (rp->ioctl.usDataLen < sizeof(ULONG))
198 {
199 // invalid Data Pkt
200 rc = RPERR_PARAMETER | RPDONE;
201 break;
202 }
203 pData = (ULONG *) linData;
204 (*pData) = RM_VERSION;
205
206 } break;
207
208 case IOCTL_OSS32_GET_PCM_NUM:
209 {
210 dprintf(("GET_PCM_NUM\n"));
211 if (rp->ioctl.usDataLen < sizeof(ULONG))
212 {
213 // invalid Data Pkt
214 rc = RPERR_PARAMETER | RPDONE;
215 break;
216 }
217 card_id = (ULONG) *linParm;
218 pData = (ULONG *) linData;
219 (*pData) = GetNumberOfPcm(card_id);
220
221 } break;
222
223 case IOCTL_OSS32_CARDS_NUM:
224 dprintf(("OSS32_CARDS_NUM\n"));
225 if (rp->ioctl.usDataLen < sizeof(ULONG))
226 {
227 // invalid Data Pkt
228 rc = RPERR_PARAMETER | RPDONE;
229 break;
230 }
231 pData = (ULONG *) linData;
232 (*pData) = GetNumberOfCards();
233 break;
234
235 case IOCTL_OSS32_PCM_CAPS:
236 {
237 dprintf(("OSS32_PCM_CAPS\n"));
238 if (rp->ioctl.usDataLen < sizeof(ULONG))
239 {
240 // invalid Data Pkt
241 rc = RPERR_PARAMETER | RPDONE;
242 break;
243 }
244 card_id = (ULONG) *linParm;
245 pData = (ULONG *) linData;
246 GetUniaudPcmCaps(card_id,(void*)*pData);
247 } break;
248
249 case IOCTL_OSS32_CARD_INFO:
250 {
251 dprintf(("OSS32_CARD_INFO\n"));
252 if (rp->ioctl.usDataLen < sizeof(ULONG))
253 {
254 // invalid Data Pkt
255 rc = RPERR_PARAMETER | RPDONE;
256 break;
257 }
258 pData = (ULONG *) linData;
259 card_id = (ULONG) *linParm;
260 GetUniaudCardInfo(card_id,(void*)*pData);
261 } break;
262
263 case IOCTL_OSS32_GET_POWER_STATE:
264 {
265 dprintf(("OSS32_GET_POWER_STATE\n"));
266 if (rp->ioctl.usDataLen < sizeof(ULONG))
267 {
268 // invalid Data Pkt
269 rc = RPERR_PARAMETER | RPDONE;
270 break;
271 }
272 pData = (ULONG *) linData;
273 card_id = (ULONG) *linParm;
274 UniaudCtlGetPowerState(card_id,(void*)*pData);
275 } break;
276
277 case IOCTL_OSS32_SET_POWER_STATE:
278 {
279 dprintf(("OSS32_SET_POWER_STATE\n"));
280 if (rp->ioctl.usDataLen < sizeof(ULONG))
281 {
282 // invalid Data Pkt
283 rc = RPERR_PARAMETER | RPDONE;
284 break;
285 }
286 pData = (ULONG *) linData;
287 card_id = (ULONG) *linParm;
288 UniaudCtlSetPowerState(card_id,(void*)*pData);
289 } break;
290
291 case IOCTL_OSS32_GET_CNTRLS_NUM:
292 {
293 dprintf(("OSS32_GET_CNTRLS_NUM\n"));
294 if (rp->ioctl.usDataLen < sizeof(ULONG))
295 {
296 // invalid Data Pkt
297 rc = RPERR_PARAMETER | RPDONE;
298 break;
299 }
300 pData = (ULONG *) linData;
301 card_id = (ULONG) *linParm;
302 (*pData) = GetUniaudControlNum(card_id);
303
304 } break;
305
306
307 case IOCTL_OSS32_GET_CNTRLS:
308 {
309 dprintf(("OSS32_GET_CNTRLS\n"));
310 if (rp->ioctl.usDataLen < sizeof(ULONG))
311 {
312 // invalid Data Pkt
313 rc = RPERR_PARAMETER | RPDONE;
314 break;
315 }
316 pData = (ULONG *) linData;
317 card_id = (ULONG) *linParm;
318 GetUniaudControls(card_id,(void*)*pData);
319 } break;
320
321 case IOCTL_OSS32_CNTRL_INFO:
322 {
323 dprintf(("OSS32_CNTRL_INFO\n"));
324
325 if (rp->ioctl.usDataLen < sizeof(ULONG))
326 {
327 // invalid Data Pkt
328 rc = RPERR_PARAMETER | RPDONE;
329 break;
330 }
331
332 if (rp->ioctl.usParmLen < 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 dprintf(("OSS32_CNTRL_GET\n"));
350 if (rp->ioctl.usDataLen < sizeof(ULONG))
351 {
352 // invalid Data Pkt
353 rc = RPERR_PARAMETER | RPDONE;
354 break;
355 }
356
357 if (rp->ioctl.usParmLen < sizeof(ULONG))
358 {
359 // invalid Data Pkt
360 rc = RPERR_PARAMETER | RPDONE;
361 break;
362 }
363
364 pData = (ULONG *) linData;
365 ULONG id = *((ULONG *)linParm);
366 card_id = (id >> 16) & 0x0000FFFF;
367 ctl_id = id & 0x0000FFFF;
368
369 GetUniaudControlValueGet(card_id, ctl_id,(void*)*pData);
370 } break;
371
372 case IOCTL_OSS32_CNTRL_PUT:
373 {
374 dprintf(("OSS32_CNTRL_PUT\n"));
375
376 if (rp->ioctl.usDataLen < sizeof(ULONG)) {
377 // invalid Data Pkt
378 rc = RPERR_PARAMETER | RPDONE;
379 break;
380 }
381
382 if (rp->ioctl.usParmLen < sizeof(ULONG)) {
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 GetUniaudControlValuePut(card_id, ctl_id,(void*)*pData);
394 } break;
395
396 case IOCTL_OSS32_SET_PCM:
397 {
398 dprintf(("OSS32_SET_PCM\n"));
399
400 if (rp->ioctl.usParmLen < 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 dprintf(("OSS32_CNTRL_WAIT\n"));
416 if (rp->ioctl.usDataLen < 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
432 dprintf(("OSS32_PCM_OPEN\n"));
433 // close all pcms from uniaud16 first
434 pcm->ret = OSS32_WaveOpen(pcm->deviceid, pcm->streamtype, pData, pcm->pcm, rp->ioctl.usSysFileNum);
435 }
436 break;
437
438 case IOCTL_OSS32_PCM_CLOSE:
439 {
440 ULONG alsa_id = *((ULONG *)linParm);
441
442 dprintf(("OSS32_PCM_CLOSE\n"));
443 OSS32_WaveClose(alsa_id);
444 }
445 break;
446 case IOCTL_OSS32_PCM_READ:
447 {
448 char *pData1 = (char *)linData;
449 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
450
451 dprintf(("OSS32_PCM_READ\n"));
452 pcm->ret = UniaudIoctlPCMRead(pcm->deviceid, pData1, pcm->size);
453 }
454 break;
455 case IOCTL_OSS32_PCM_WRITE:
456 {
457 char *pData1 = (char *)linData;
458 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
459
460 dprintf(("OSS32_PCM_WRITE\n"));
461 pcm->ret = UniaudIoctlPCMWrite(pcm->deviceid, pData1, pcm->size);
462 }
463 break;
464 case IOCTL_OSS32_PCM_PAUSE:
465 {
466 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
467
468 dprintf(("OSS32_PCM_PAUSE\n"));
469 pcm->ret = UniaudIoctlPCMResume(pcm->deviceid, 0);
470 }
471 break;
472 case IOCTL_OSS32_PCM_RESUME:
473 {
474 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
475
476 dprintf(("OSS32_PCM_RESUME\n"));
477 pcm->ret = UniaudIoctlPCMResume(pcm->deviceid, 1);
478 }
479 break;
480 case IOCTL_OSS32_PCM_START:
481 {
482 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
483
484 dprintf(("OSS32_PCM_START\n"));
485 pcm->ret = UniaudIoctlPCMStart(pcm->deviceid);
486 }
487 break;
488 case IOCTL_OSS32_PCM_DROP:
489 {
490 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
491
492 dprintf(("OSS32_PCM_DROP\n"));
493 pcm->ret = UniaudIoctlPCMDrop(pcm->deviceid);
494 }
495 break;
496 case IOCTL_OSS32_PCM_DRAIN:
497 break;
498 case IOCTL_OSS32_PCM_STATUS:
499 {
500 void *pData1 = (void *)linData;
501 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
502
503 dprintf(("OSS32_PCM_STATUS\n"));
504 pcm->ret = UniaudIoctlPCMStatus(pcm->deviceid, pData1);
505 }
506 break;
507 case IOCTL_OSS32_PCM_REFINEHWPARAMS:
508 {
509 void *pData1 = (void *)linData;
510 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
511
512 dprintf(("OSS32_PCM_REFINEHWPARAMS\n"));
513 pcm->ret = UniaudIoctlHWRefine(pcm->deviceid, pData1);
514 }
515 break;
516 case IOCTL_OSS32_PCM_SETHWPARAMS:
517 {
518 void *pData1 = (void *)linData;
519 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
520
521 dprintf(("OSS32_PCM_SETHWPARAMS\n"));
522 pcm->ret = UniaudIoctlHWParamSet(pcm->deviceid, pData1);
523 }
524 break;
525 case IOCTL_OSS32_PCM_SETSWPARAMS:
526 {
527 void *pData1 = (void *)linData;
528 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
529
530 dprintf(("OSS32_PCM_SETSWPARAMS\n"));
531 pcm->ret = UniaudIoctlSWParamSet(pcm->deviceid, pData1);
532 }
533 break;
534 case IOCTL_OSS32_PCM_PREPARE:
535 {
536 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
537
538 dprintf(("OSS32_PCM_PREPARE\n"));
539 pcm->ret = UniaudIoctlPCMPrepare(pcm->deviceid);
540 }
541 break;
542
543 case IOCTL_OSS32_PCM_CLOSE_ALL:
544 {
545 int unlock = (int)*linParm;
546
547 dprintf(("OSS32_PCM_CLOSE_ALL\n"));
548 if (unlock)
549 unlock_all = 1;
550 else
551 UniaudCloseAll(0);
552 }
553 break;
554 case IOCTL_OSS32_PCM_CLOSE_16:
555 dprintf(("OSS32_PCM_CLOSE_16\n"));
556 OSS32_CloseUNI16();
557 break;
558 case IOCTL_OSS32_PCM_WAIT_INT:
559 {
560 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
561
562 dprintf(("OSS32_PCM_WAIT_INT\n"));
563 pcm->ret = WaitForPCMInterrupt((void*)pcm->deviceid, pcm->streamtype);
564 }
565 break;
566
567 default:
568 {
569 printk("invalid function code %i\n",rp->ioctl.bFunction);
570 // invalid function code
571 rc = RPERR_PARAMETER | RPDONE;
572 } break;
573 }
574
575 // unlock Parm & Data if needed
576 if (linParm != NULL)
577 {
578 // linParm present & locked, must to unlock it
579 DevVMUnLock(lhParm);
580 }
581 if (linData != NULL)
582 {
583 // linData present & locked, must to unlock it
584 DevVMUnLock(lhData);
585 }
586
587 // all done
588 return (rc);
589}
590
591//******************************************************************************
592// Dispatch Close requests received from the strategy routine
593//******************************************************************************
594ULONG StratClose(REQPACKET __far* rp)
595{
596 // only called if device successfully opened
597 // printk("strat close\n");
598 numOS2Opens--;
599
600 UniaudCloseAll(rp->open_close.usSysFileNum);
601
602 if (numOS2Opens == 0) {
603 deviceOwner = DEV_NO_OWNER;
604 }
605 return(RPDONE);
606}
607
Note: See TracBrowser for help on using the repository browser.