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

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

Added quirk for Gateway 2000 ICH2/AD1885

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#ifdef DEBUG
105 //printk("StratIOCtl 0x%x\n", rp->Function);
106#endif
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 GetUniaudControlValuePut(card_id, ctl_id,(void*)*pData);
397 } break;
398
399 case IOCTL_OSS32_SET_PCM:
400 {
401
402 if (rp->ParmLength < sizeof(ULONG))
403 {
404 // invalid Data Pkt
405 rc = RPERR_PARAMETER | RPDONE;
406 break;
407 }
408
409 ULONG pcm = (ULONG) *linParm;
410
411 printk("set PCM %i\n",pcm);
412 SetPCMInstance(0, pcm);
413 } break;
414
415 case IOCTL_OSS32_CNTRL_WAIT:
416 {
417 if (rp->DataLength < sizeof(ULONG))
418 {
419 // invalid Data Pkt
420 rc = RPERR_PARAMETER | RPDONE;
421 break;
422 }
423 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
424 pData = (ULONG *) linData;
425 (*pData) = WaitForControlChange(pcm->deviceid, pcm->streamtype);
426 }
427 break;
428 case IOCTL_OSS32_PCM_OPEN:
429 {
430 pData = (ULONG *)linData;
431 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
432 // close all pcms from uniaud16 first
433 pcm->ret = OSS32_WaveOpen(pcm->deviceid, pcm->streamtype, pData, pcm->pcm, rp->FileID);
434 }
435 break;
436
437 case IOCTL_OSS32_PCM_CLOSE:
438 {
439 ULONG alsa_id = *((ULONG *)linParm);
440 OSS32_WaveClose(alsa_id);
441 }
442 break;
443 case IOCTL_OSS32_PCM_READ:
444 {
445 char *pData1 = (char *)linData;
446 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
447 pcm->ret = UniaudIoctlPCMRead(pcm->deviceid, pData1, pcm->size);
448 }
449 break;
450 case IOCTL_OSS32_PCM_WRITE:
451 {
452 char *pData1 = (char *)linData;
453 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
454 pcm->ret = UniaudIoctlPCMWrite(pcm->deviceid, pData1, pcm->size);
455 }
456 break;
457 case IOCTL_OSS32_PCM_PAUSE:
458 {
459 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
460 pcm->ret = UniaudIoctlPCMResume(pcm->deviceid, 0);
461 }
462 break;
463 case IOCTL_OSS32_PCM_RESUME:
464 {
465 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
466 pcm->ret = UniaudIoctlPCMResume(pcm->deviceid, 1);
467 }
468 break;
469 case IOCTL_OSS32_PCM_START:
470 {
471 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
472 pcm->ret = UniaudIoctlPCMStart(pcm->deviceid);
473 }
474 break;
475 case IOCTL_OSS32_PCM_DROP:
476 {
477 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
478 pcm->ret = UniaudIoctlPCMDrop(pcm->deviceid);
479 }
480 break;
481 case IOCTL_OSS32_PCM_DRAIN:
482 break;
483 case IOCTL_OSS32_PCM_STATUS:
484 {
485 void *pData1 = (void *)linData;
486 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
487 pcm->ret = UniaudIoctlPCMStatus(pcm->deviceid, pData1);
488 }
489 break;
490 case IOCTL_OSS32_PCM_REFINEHWPARAMS:
491 {
492 void *pData1 = (void *)linData;
493 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
494 pcm->ret = UniaudIoctlHWRefine(pcm->deviceid, pData1);
495 }
496 break;
497 case IOCTL_OSS32_PCM_SETHWPARAMS:
498 {
499 void *pData1 = (void *)linData;
500 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
501 pcm->ret = UniaudIoctlHWParamSet(pcm->deviceid, pData1);
502 }
503 break;
504 case IOCTL_OSS32_PCM_SETSWPARAMS:
505 {
506 void *pData1 = (void *)linData;
507 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
508 pcm->ret = UniaudIoctlSWParamSet(pcm->deviceid, pData1);
509 }
510 break;
511 case IOCTL_OSS32_PCM_PREPARE:
512 {
513 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
514 pcm->ret = UniaudIoctlPCMPrepare(pcm->deviceid);
515 }
516 break;
517
518 case IOCTL_OSS32_PCM_CLOSE_ALL:
519 {
520 int unlock = (int)*linParm;
521 if (unlock)
522 unlock_all = 1;
523 else
524 UniaudCloseAll(0);
525 }
526 break;
527 case IOCTL_OSS32_PCM_CLOSE_16:
528 OSS32_CloseUNI16();
529 break;
530 case IOCTL_OSS32_PCM_WAIT_INT:
531 {
532 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
533 pcm->ret = WaitForPCMInterrupt((void*)pcm->deviceid, pcm->streamtype);
534 }
535 break;
536
537 default:
538 {
539 printk("invalid function code %i\n",rp->Function);
540 // invalid function code
541 rc = RPERR_PARAMETER | RPDONE;
542 } break;
543 }
544
545 // unlock Parm & Data if needed
546 if (linParm != NULL)
547 {
548 // linParm present & locked, must to unlock it
549 DevVMUnLock(lhParm);
550 }
551 if (linData != NULL)
552 {
553 // linData present & locked, must to unlock it
554 DevVMUnLock(lhData);
555 }
556
557 // all done
558 return (rc);
559}
560
561//******************************************************************************
562// Dispatch Close requests received from the strategy routine
563//******************************************************************************
564ULONG StratClose(RP __far* _rp)
565{
566 RPOpenClose __far* rp = (RPOpenClose __far*)_rp;
567
568 // only called if device successfully opened
569// printk("strat close\n");
570 numOS2Opens--;
571
572 UniaudCloseAll(rp->FileID);
573
574 if (numOS2Opens == 0) {
575 deviceOwner = DEV_NO_OWNER;
576 }
577 return(RPDONE);
578}
579//******************************************************************************
580//******************************************************************************
Note: See TracBrowser for help on using the repository browser.