source: GPL/trunk/drv32/dispatch.c

Last change on this file was 679, checked in by David Azarewicz, 4 years ago

Merge changes from Paul's uniaud32next branch.

File size: 15.5 KB
RevLine 
[32]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
[542]29#include <dbgos2.h>
[32]30#include <ossidc.h>
31#include <ossidc32.h>
32#include <version.h>
[679]33#include <kee.h>
34#include <u32ioctl.h>
35#include "strategy.h"
[32]36
37/*
38 * structure passed to pcm open ioctl
39 */
40#pragma pack(1)
41typedef struct ioctl_pcm {
42 ULONG deviceid; // card number
43 ULONG streamtype; // type of stream (play or record)
44 ULONG pcm; // pcm instance
45 int size; // data size
46 ULONG ret; // return code
47} ioctl_pcm;
48#pragma pack()
49
[587]50ULONG StratIOCtl(REQPACKET __far* rp)
[32]51{
[679]52 USHORT rc = 0;
53 KEEVMLock lhParm, lhData;
54 char *linParm;
55 char *linData;
[32]56 ULONG *pData;
57 ULONG card_id;
58 ULONG ctl_id;
59
[587]60 if (rp->ioctl.bCategory != CAT_IOCTL_OSS32)
[32]61 {
[587]62 //printk("not our cat %x. func %x\n", rp->Category, rp->Function);
[32]63 // not our category, exit with error
[587]64 return (RPERR_BADCOMMAND | RPDONE);
[32]65 }
66
[587]67 #ifdef DEBUG
[485]68 //printk("StratIOCtl 0x%x\n", rp->Function);
[587]69 #endif
[598]70 // printk("cmd: %x, len: %i, pack: %x\n",rp->ioctl.bFunction, rp->ioctl.usParmLen, rp->ioctl.pvParm);
[32]71 // work with Parm Packet
[587]72 if ((rp->ioctl.usParmLen != 0 ||
73 rp->ioctl.bFunction == IOCTL_OSS32_ATTACH /*16 bit ioctl*/) &&
74 ((rp->ioctl.pvParm & 0xfffcffff) != 0))
[32]75 {
76 // got Parm Packet
[679]77 linParm = (char*)KernSelToFlat(rp->ioctl.pvParm);
[32]78
[679]79 if (rp->ioctl.bFunction == IOCTL_OSS32_ATTACH)
[32]80 {
[679]81 rc = KernVMLock(KEE_VML_LONGLOCK, (PVOID)linParm, 4, &lhParm, (KEEVMPageList*)-1, 0);
82 }
83 else
84 {
85 rc = KernVMLock(KEE_VML_LONGLOCK, (PVOID)linParm, rp->ioctl.usParmLen, &lhParm, (KEEVMPageList*)-1, 0);
86 }
[32]87
[679]88 if (rc != 0)
[32]89 {
[679]90 printk("error in KernVMLock rc = %i\n",rc);
[32]91 return (RPERR_PARAMETER | RPDONE);
92 }
[679]93 }
94 else
[32]95 {
96 // no Parm Packet
97 linParm = NULL;
98 }
99
100 // work with Data Packet
[587]101 if ((rp->ioctl.usDataLen != 0) &&
102 ((rp->ioctl.pvData & 0xfffcffff) != 0))
[32]103 {
104 // got Data Packet
[679]105 linData = (char*)KernSelToFlat(rp->ioctl.pvData);
[32]106
[679]107 rc = KernVMLock(KEE_VML_LONGLOCK, (PVOID)linData, rp->ioctl.usDataLen, &lhData, (KEEVMPageList*)-1, 0);
[32]108 if (rc != 0)
109 {
[679]110 printk("error in KernVMLock rc = %i\n",rc);
[32]111 if (linParm != NULL)
112 {
113 // linParm present & locked, must to unlock it
[679]114 KernVMUnlock(&lhParm);
[32]115 }
116 return (RPERR_PARAMETER | RPDONE);
117 }
118 } else
119 {
120 // no Data Packet
121 linData = NULL;
122 }
123
124 // functions handling
125 rc = RPDONE; // ok by default
126
[587]127 switch(rp->ioctl.bFunction)
[32]128 {
129 case IOCTL_OSS32_ATTACH:
130 {
[598]131 dprintf(("OSS32_ATTACH\n"));
[32]132 card_id = (ULONG) *linParm;
133 // Check if audio init was successful
[587]134 if (OSS32_QueryNames(card_id, NULL, 0, NULL, 0, FALSE) != OSSERR_SUCCESS)
[32]135 {
136 rc = RPERR_GENERAL | RPDONE;
137 }
138 } break;
139
140 case IOCTL_OSS32_VERSION:
141 {
[598]142 dprintf(("OSS32_VERSION\n"));
[587]143 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]144 {
145 // invalid Data Pkt
146 rc = RPERR_PARAMETER | RPDONE;
147 break;
148 }
149 pData = (ULONG *) linData;
[235]150 (*pData) = RM_VERSION;
[32]151
152 } break;
153
154 case IOCTL_OSS32_GET_PCM_NUM:
155 {
[598]156 dprintf(("GET_PCM_NUM\n"));
[587]157 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]158 {
159 // invalid Data Pkt
160 rc = RPERR_PARAMETER | RPDONE;
161 break;
162 }
163 card_id = (ULONG) *linParm;
164 pData = (ULONG *) linData;
165 (*pData) = GetNumberOfPcm(card_id);
166
167 } break;
168
169 case IOCTL_OSS32_CARDS_NUM:
[598]170 dprintf(("OSS32_CARDS_NUM\n"));
[587]171 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]172 {
173 // invalid Data Pkt
174 rc = RPERR_PARAMETER | RPDONE;
175 break;
176 }
177 pData = (ULONG *) linData;
178 (*pData) = GetNumberOfCards();
179 break;
180
181 case IOCTL_OSS32_PCM_CAPS:
182 {
[598]183 dprintf(("OSS32_PCM_CAPS\n"));
[587]184 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]185 {
186 // invalid Data Pkt
187 rc = RPERR_PARAMETER | RPDONE;
188 break;
189 }
190 card_id = (ULONG) *linParm;
191 pData = (ULONG *) linData;
192 GetUniaudPcmCaps(card_id,(void*)*pData);
193 } break;
194
195 case IOCTL_OSS32_CARD_INFO:
196 {
[598]197 dprintf(("OSS32_CARD_INFO\n"));
[587]198 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]199 {
200 // invalid Data Pkt
201 rc = RPERR_PARAMETER | RPDONE;
202 break;
203 }
204 pData = (ULONG *) linData;
205 card_id = (ULONG) *linParm;
206 GetUniaudCardInfo(card_id,(void*)*pData);
207 } break;
208
209 case IOCTL_OSS32_GET_POWER_STATE:
210 {
[598]211 dprintf(("OSS32_GET_POWER_STATE\n"));
[587]212 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]213 {
214 // invalid Data Pkt
215 rc = RPERR_PARAMETER | RPDONE;
216 break;
217 }
218 pData = (ULONG *) linData;
219 card_id = (ULONG) *linParm;
220 UniaudCtlGetPowerState(card_id,(void*)*pData);
221 } break;
222
223 case IOCTL_OSS32_SET_POWER_STATE:
224 {
[598]225 dprintf(("OSS32_SET_POWER_STATE\n"));
[587]226 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]227 {
228 // invalid Data Pkt
229 rc = RPERR_PARAMETER | RPDONE;
230 break;
231 }
232 pData = (ULONG *) linData;
233 card_id = (ULONG) *linParm;
234 UniaudCtlSetPowerState(card_id,(void*)*pData);
235 } break;
236
237 case IOCTL_OSS32_GET_CNTRLS_NUM:
238 {
[598]239 dprintf(("OSS32_GET_CNTRLS_NUM\n"));
[587]240 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]241 {
242 // invalid Data Pkt
243 rc = RPERR_PARAMETER | RPDONE;
244 break;
245 }
246 pData = (ULONG *) linData;
247 card_id = (ULONG) *linParm;
248 (*pData) = GetUniaudControlNum(card_id);
249
250 } break;
251
252
253 case IOCTL_OSS32_GET_CNTRLS:
254 {
[598]255 dprintf(("OSS32_GET_CNTRLS\n"));
[587]256 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]257 {
258 // invalid Data Pkt
259 rc = RPERR_PARAMETER | RPDONE;
260 break;
261 }
262 pData = (ULONG *) linData;
263 card_id = (ULONG) *linParm;
264 GetUniaudControls(card_id,(void*)*pData);
265 } break;
266
267 case IOCTL_OSS32_CNTRL_INFO:
268 {
[598]269 dprintf(("OSS32_CNTRL_INFO\n"));
[32]270
[587]271 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]272 {
273 // invalid Data Pkt
274 rc = RPERR_PARAMETER | RPDONE;
275 break;
276 }
277
[587]278 if (rp->ioctl.usParmLen < sizeof(ULONG))
[32]279 {
280 // invalid Data Pkt
281 rc = RPERR_PARAMETER | RPDONE;
282 break;
283 }
284
285 pData = (ULONG *) linData;
286 ULONG id = *((ULONG *)linParm);
287 card_id = (id >> 16) & 0x0000FFFF;
288 ctl_id = id & 0x0000FFFF;
289// printk("id: %x, card: %x, ctl: %x\n",id, card_id, ctl_id);
290 GetUniaudControlInfo(card_id, ctl_id, (void*)*pData);
291 } break;
292
293 case IOCTL_OSS32_CNTRL_GET:
294 {
[598]295 dprintf(("OSS32_CNTRL_GET\n"));
[587]296 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]297 {
298 // invalid Data Pkt
299 rc = RPERR_PARAMETER | RPDONE;
300 break;
301 }
302
[587]303 if (rp->ioctl.usParmLen < sizeof(ULONG))
[32]304 {
305 // invalid Data Pkt
306 rc = RPERR_PARAMETER | RPDONE;
307 break;
308 }
309
310 pData = (ULONG *) linData;
311 ULONG id = *((ULONG *)linParm);
312 card_id = (id >> 16) & 0x0000FFFF;
313 ctl_id = id & 0x0000FFFF;
314
315 GetUniaudControlValueGet(card_id, ctl_id,(void*)*pData);
316 } break;
317
318 case IOCTL_OSS32_CNTRL_PUT:
319 {
[598]320 dprintf(("OSS32_CNTRL_PUT\n"));
[32]321
[587]322 if (rp->ioctl.usDataLen < sizeof(ULONG)) {
[32]323 // invalid Data Pkt
324 rc = RPERR_PARAMETER | RPDONE;
325 break;
326 }
327
[587]328 if (rp->ioctl.usParmLen < sizeof(ULONG)) {
[32]329 // invalid Data Pkt
330 rc = RPERR_PARAMETER | RPDONE;
331 break;
332 }
333
[542]334 pData = (ULONG *)linData;
[32]335 ULONG id = *((ULONG *)linParm);
336 card_id = (id >> 16) & 0x0000FFFF;
337 ctl_id = id & 0x0000FFFF;
338
339 GetUniaudControlValuePut(card_id, ctl_id,(void*)*pData);
340 } break;
341
342 case IOCTL_OSS32_SET_PCM:
343 {
[598]344 dprintf(("OSS32_SET_PCM\n"));
[32]345
[587]346 if (rp->ioctl.usParmLen < sizeof(ULONG))
[32]347 {
348 // invalid Data Pkt
349 rc = RPERR_PARAMETER | RPDONE;
350 break;
351 }
352
353 ULONG pcm = (ULONG) *linParm;
354
355 printk("set PCM %i\n",pcm);
356 SetPCMInstance(0, pcm);
357 } break;
358
359 case IOCTL_OSS32_CNTRL_WAIT:
360 {
[598]361 dprintf(("OSS32_CNTRL_WAIT\n"));
[587]362 if (rp->ioctl.usDataLen < sizeof(ULONG))
[32]363 {
364 // invalid Data Pkt
365 rc = RPERR_PARAMETER | RPDONE;
366 break;
367 }
368 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
369 pData = (ULONG *) linData;
370 (*pData) = WaitForControlChange(pcm->deviceid, pcm->streamtype);
371 }
372 break;
373 case IOCTL_OSS32_PCM_OPEN:
374 {
375 pData = (ULONG *)linData;
376 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]377
378 dprintf(("OSS32_PCM_OPEN\n"));
[32]379 // close all pcms from uniaud16 first
[587]380 pcm->ret = OSS32_WaveOpen(pcm->deviceid, pcm->streamtype, pData, pcm->pcm, rp->ioctl.usSysFileNum);
[32]381 }
382 break;
383
384 case IOCTL_OSS32_PCM_CLOSE:
385 {
386 ULONG alsa_id = *((ULONG *)linParm);
[598]387
388 dprintf(("OSS32_PCM_CLOSE\n"));
[32]389 OSS32_WaveClose(alsa_id);
390 }
391 break;
392 case IOCTL_OSS32_PCM_READ:
393 {
394 char *pData1 = (char *)linData;
395 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]396
397 dprintf(("OSS32_PCM_READ\n"));
[32]398 pcm->ret = UniaudIoctlPCMRead(pcm->deviceid, pData1, pcm->size);
399 }
400 break;
401 case IOCTL_OSS32_PCM_WRITE:
402 {
403 char *pData1 = (char *)linData;
404 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]405
406 dprintf(("OSS32_PCM_WRITE\n"));
[32]407 pcm->ret = UniaudIoctlPCMWrite(pcm->deviceid, pData1, pcm->size);
408 }
409 break;
410 case IOCTL_OSS32_PCM_PAUSE:
411 {
412 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]413
414 dprintf(("OSS32_PCM_PAUSE\n"));
[32]415 pcm->ret = UniaudIoctlPCMResume(pcm->deviceid, 0);
416 }
417 break;
418 case IOCTL_OSS32_PCM_RESUME:
419 {
420 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]421
422 dprintf(("OSS32_PCM_RESUME\n"));
[32]423 pcm->ret = UniaudIoctlPCMResume(pcm->deviceid, 1);
424 }
425 break;
426 case IOCTL_OSS32_PCM_START:
427 {
428 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]429
430 dprintf(("OSS32_PCM_START\n"));
[32]431 pcm->ret = UniaudIoctlPCMStart(pcm->deviceid);
432 }
433 break;
434 case IOCTL_OSS32_PCM_DROP:
435 {
436 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]437
438 dprintf(("OSS32_PCM_DROP\n"));
[32]439 pcm->ret = UniaudIoctlPCMDrop(pcm->deviceid);
440 }
441 break;
442 case IOCTL_OSS32_PCM_DRAIN:
443 break;
444 case IOCTL_OSS32_PCM_STATUS:
445 {
446 void *pData1 = (void *)linData;
447 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]448
449 dprintf(("OSS32_PCM_STATUS\n"));
[32]450 pcm->ret = UniaudIoctlPCMStatus(pcm->deviceid, pData1);
451 }
452 break;
453 case IOCTL_OSS32_PCM_REFINEHWPARAMS:
454 {
455 void *pData1 = (void *)linData;
456 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]457
458 dprintf(("OSS32_PCM_REFINEHWPARAMS\n"));
[32]459 pcm->ret = UniaudIoctlHWRefine(pcm->deviceid, pData1);
460 }
461 break;
462 case IOCTL_OSS32_PCM_SETHWPARAMS:
463 {
464 void *pData1 = (void *)linData;
465 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]466
467 dprintf(("OSS32_PCM_SETHWPARAMS\n"));
[32]468 pcm->ret = UniaudIoctlHWParamSet(pcm->deviceid, pData1);
469 }
470 break;
471 case IOCTL_OSS32_PCM_SETSWPARAMS:
472 {
473 void *pData1 = (void *)linData;
474 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]475
476 dprintf(("OSS32_PCM_SETSWPARAMS\n"));
[32]477 pcm->ret = UniaudIoctlSWParamSet(pcm->deviceid, pData1);
478 }
479 break;
480 case IOCTL_OSS32_PCM_PREPARE:
481 {
482 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]483
484 dprintf(("OSS32_PCM_PREPARE\n"));
[32]485 pcm->ret = UniaudIoctlPCMPrepare(pcm->deviceid);
486 }
487 break;
488
489 case IOCTL_OSS32_PCM_CLOSE_ALL:
490 {
491 int unlock = (int)*linParm;
[598]492
493 dprintf(("OSS32_PCM_CLOSE_ALL\n"));
[32]494 if (unlock)
495 unlock_all = 1;
496 else
497 UniaudCloseAll(0);
498 }
499 break;
500 case IOCTL_OSS32_PCM_CLOSE_16:
[598]501 dprintf(("OSS32_PCM_CLOSE_16\n"));
[32]502 OSS32_CloseUNI16();
503 break;
504 case IOCTL_OSS32_PCM_WAIT_INT:
505 {
506 ioctl_pcm *pcm = (ioctl_pcm *)linParm;
[598]507
508 dprintf(("OSS32_PCM_WAIT_INT\n"));
[32]509 pcm->ret = WaitForPCMInterrupt((void*)pcm->deviceid, pcm->streamtype);
510 }
511 break;
512
513 default:
514 {
[587]515 printk("invalid function code %i\n",rp->ioctl.bFunction);
[32]516 // invalid function code
517 rc = RPERR_PARAMETER | RPDONE;
518 } break;
519 }
520
521 // unlock Parm & Data if needed
522 if (linParm != NULL)
523 {
524 // linParm present & locked, must to unlock it
[679]525 KernVMUnlock(&lhParm);
[32]526 }
527 if (linData != NULL)
528 {
529 // linData present & locked, must to unlock it
[679]530 KernVMUnlock(&lhData);
[32]531 }
532
533 // all done
534 return (rc);
535}
Note: See TracBrowser for help on using the repository browser.