1 | /* $Id: init.cpp,v 1.6 2001/04/30 21:07:57 sandervl Exp $ */
|
---|
2 |
|
---|
3 | /* SCCSID = %W% %E% */
|
---|
4 | /****************************************************************************
|
---|
5 | * *
|
---|
6 | * Copyright (c) IBM Corporation 1994 - 1997. *
|
---|
7 | * *
|
---|
8 | * The following IBM OS/2 source code is provided to you solely for the *
|
---|
9 | * the purpose of assisting you in your development of OS/2 device drivers. *
|
---|
10 | * You may use this code in accordance with the IBM License Agreement *
|
---|
11 | * provided in the IBM Device Driver Source Kit for OS/2. *
|
---|
12 | * *
|
---|
13 | ****************************************************************************/
|
---|
14 | /**@internal %W%
|
---|
15 | * Top level device driver initialization.
|
---|
16 | * @version %I%
|
---|
17 | * @context
|
---|
18 | * Physical DD initialization context: Ring3 with I/O privledge.
|
---|
19 | * Discarded after use.
|
---|
20 | * @notes
|
---|
21 | * Creates resource manager object and uses that RM object to figure out
|
---|
22 | * whether audio hardware is present. If present, RM provides IO resources
|
---|
23 | * to operate hardware. This modules uses that information to create
|
---|
24 | * Audio HW objects and other global data structures.
|
---|
25 | * @history
|
---|
26 | */
|
---|
27 |
|
---|
28 | #pragma code_seg ("_inittext");
|
---|
29 | ////#pragma data_seg ("_initdata","endds");
|
---|
30 |
|
---|
31 | extern "C" { // 16-bit header files are not C++ aware
|
---|
32 | #define INCL_NOPMAPI
|
---|
33 | #define INCL_DOSMISC
|
---|
34 | #include <os2.h>
|
---|
35 | #include <audio.h>
|
---|
36 | #include <os2mixer.h>
|
---|
37 | }
|
---|
38 |
|
---|
39 | #include <ctype.h>
|
---|
40 | #include <string.h>
|
---|
41 | #include <devhelp.h>
|
---|
42 | #include "strategy.h" // OS/2 DD strategy interface
|
---|
43 | #include "header.h" // Device driver header
|
---|
44 | #include "parse.h" // Parses DEVICE= command line
|
---|
45 | #include "malloc.h" // Heap memory used by this driver
|
---|
46 | #include "mpu401.hpp" // Object definition
|
---|
47 | #include "fmsynth.hpp" // Object definition
|
---|
48 | #include "waudio.hpp" // Object definition
|
---|
49 | #include "irq.hpp" // Object definition
|
---|
50 | #include "timer.hpp" // Object definition
|
---|
51 | #include "stream.hpp" // pStreamList
|
---|
52 | #include "rm.hpp" // Object definition
|
---|
53 | #include "end.h" // end_of_data, end_of_text()
|
---|
54 | #include "sizedefs.h" // HEAP_SIZE
|
---|
55 | #include "idc_vdd.h" // VDD interface and Data Structs
|
---|
56 | #include <include.h> // Pragmas and more.
|
---|
57 | #include <sbversion.h>
|
---|
58 | #include "commdbg.h"
|
---|
59 | #include <dbgos2.h>
|
---|
60 |
|
---|
61 | //#include "log.hpp"
|
---|
62 | //#include "logmsg.hpp"
|
---|
63 |
|
---|
64 |
|
---|
65 | /*
|
---|
66 | #ifndef PCI_VENDOR_ID_CREATIVE
|
---|
67 | #define PCI_VENDOR_ID_CREATIVE 0x1102UL
|
---|
68 | #endif
|
---|
69 |
|
---|
70 | #ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1
|
---|
71 | #define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002UL
|
---|
72 | #endif
|
---|
73 |
|
---|
74 | #define PCI_ID ((PCI_DEVICE_ID_CREATIVE_EMU10K1<<16UL)|PCI_VENDOR_ID_CREATIVE)
|
---|
75 | */
|
---|
76 |
|
---|
77 |
|
---|
78 | #define PCI_VENDOR_ID_CMEDIA 0x13f6UL
|
---|
79 | #define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100UL
|
---|
80 | #define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101UL
|
---|
81 | #define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111UL
|
---|
82 | #define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112UL
|
---|
83 |
|
---|
84 |
|
---|
85 | // Attention: use same detection order in CMPCI.C
|
---|
86 | static struct { ULONG uID; PCHAR pchName; } arDevList[] =
|
---|
87 | {
|
---|
88 | { (PCI_DEVICE_ID_CMEDIA_CM8738B << 16) | PCI_VENDOR_ID_CMEDIA, "CMI8738B" },
|
---|
89 | { (PCI_DEVICE_ID_CMEDIA_CM8738 << 16) | PCI_VENDOR_ID_CMEDIA, "CMI8738" },
|
---|
90 | { (PCI_DEVICE_ID_CMEDIA_CM8338B << 16) | PCI_VENDOR_ID_CMEDIA, "CMI8338B" },
|
---|
91 | { (PCI_DEVICE_ID_CMEDIA_CM8338A << 16) | PCI_VENDOR_ID_CMEDIA, "CMI8338A" },
|
---|
92 | { 0, "" },
|
---|
93 | };
|
---|
94 |
|
---|
95 |
|
---|
96 | // Default MIDI timer interval, milliseconds.
|
---|
97 | static USHORT MIDI_TimerInterval = 10;
|
---|
98 |
|
---|
99 | static char szMsgSignon[] = "\r\n"PRODUCT_NAME" MMPM/2 Audio Driver v"PRODUCT_VERSION;
|
---|
100 | static char szMsgCopyright[] = "Copyright 2000-2001 Sander van Leeuwen (sandervl@xs4all.nl)\r\n"
|
---|
101 | "Copyright 2001-2002 Rdiger Ihle (r.ihle@s-t.de)";
|
---|
102 | static char szMsgNotFound[] = "Hardware not detected!";
|
---|
103 | static char szMsgAllocResFailed1[] = "Another device driver was granted exclusive access to ";
|
---|
104 | static char szMsgAllocResFailed2[] = "\r\nUnable to allocate hardware resources! Aborting...";
|
---|
105 | static char szMsgConfig1[] = " configuration: IRQ ";
|
---|
106 | static char szMsgConfig2[] = ", IO Port 0x";
|
---|
107 | static char szMsgNewLine[] = "\r\n\n";
|
---|
108 | static char szPort[] = "IO Port 0x";
|
---|
109 | static char szIRQ[] = "IRQ ";
|
---|
110 |
|
---|
111 |
|
---|
112 | //
|
---|
113 | // ASCII Z-String used to register for PDD-VDD IDC must
|
---|
114 | // Name is copied from header at runtime.
|
---|
115 | //
|
---|
116 | char szPddName[9] = {0};
|
---|
117 | char digit[32] = {0};
|
---|
118 |
|
---|
119 | ResourceManager* pRM = 0; // Resource manager object.
|
---|
120 |
|
---|
121 | //
|
---|
122 | // Strategy Init
|
---|
123 | //
|
---|
124 | void StrategyInit(PREQPACKET prp)
|
---|
125 | {
|
---|
126 | int i;
|
---|
127 | TIMER *pTimer;
|
---|
128 | LDev_Resources *pResources;
|
---|
129 |
|
---|
130 | Device_Help = (PFN) prp->s.init_in.ulDevHlp;
|
---|
131 | prp->s.init_out.usCodeEnd = 0;
|
---|
132 | prp->s.init_out.usDataEnd = 0;
|
---|
133 | prp->usStatus = RPDONE | RPERR | RPGENFAIL;
|
---|
134 |
|
---|
135 | /* Initialize Heap. */
|
---|
136 | unsigned uInitSize; // Actual size of Heap following initialization.
|
---|
137 | uInitSize = HeapInit( HEAP_SIZE );
|
---|
138 | if ((HEAP_SIZE-uInitSize) > 64) { // Should get size of request, less some overhead.
|
---|
139 | // ### pError->vLog( HeapInitFailure ); //### Error log 'pError' not yet created.
|
---|
140 | return;
|
---|
141 | }
|
---|
142 | /* Heap initialized. */
|
---|
143 |
|
---|
144 |
|
---|
145 | // Crate logging facilities. By default, the LOG facility will write
|
---|
146 | // to the serial line and the system trace log.
|
---|
147 | // pStatus = new LOG( 253, apszStatusMessage );
|
---|
148 | // pError = new LOG( 254, apszErrorMessage );
|
---|
149 | // pSoftError = pError;
|
---|
150 | // pTrace = new BINARYLOG( 255, apszTraceMessage );
|
---|
151 | // pPerfLog = new PERFLOG( 255, apszTraceMessage );
|
---|
152 |
|
---|
153 |
|
---|
154 | // Initialize global lists.
|
---|
155 | pAudioHWList = new QUEUEHEAD;
|
---|
156 | pStreamList = new QUEUEHEAD;
|
---|
157 | pTimerList = new QUEUEHEAD;
|
---|
158 |
|
---|
159 | // Fetch command line parameters.
|
---|
160 | if (!GetParms(prp->s.init_in.szArgs)) {
|
---|
161 | // Rudi: ignore bad parameters
|
---|
162 | // return;
|
---|
163 | }
|
---|
164 |
|
---|
165 | // Now that we've grabbed our cmd line options,
|
---|
166 | // we can start processing stuff that depends on those switches.
|
---|
167 |
|
---|
168 | if (fInt3BeforeInit) DebugInt3();
|
---|
169 |
|
---|
170 | // If we got a /V (verbose) flag on the DEVICE= command, route messages
|
---|
171 | // to the display.
|
---|
172 | if (fVerbose) {
|
---|
173 | USHORT result;
|
---|
174 |
|
---|
175 | DosWrite(1, szMsgSignon, sizeof(szMsgSignon)-1, &result);
|
---|
176 | DosWrite(1, szMsgNewLine, 2, &result);
|
---|
177 | DosWrite(1, szMsgCopyright, sizeof(szMsgCopyright), &result);
|
---|
178 | DosWrite(1, szMsgNewLine, 3, &result);
|
---|
179 | }
|
---|
180 |
|
---|
181 | if (szCL_DevName[0] != ' ') // Was a valid device name specified?
|
---|
182 | memcpy(phdr->abName,szCL_DevName,8); // yes, copy it to the dev header
|
---|
183 |
|
---|
184 | pRM = new ResourceManager(0); // Create the RM object.
|
---|
185 | if (! pRM) {
|
---|
186 | return;
|
---|
187 | }
|
---|
188 |
|
---|
189 | //SvL: Check if SB Live hardware has been detected by the resource manager
|
---|
190 | if( pRM->getState() != rmDriverCreated )
|
---|
191 | {
|
---|
192 | hardware_notfound:
|
---|
193 | USHORT result;
|
---|
194 |
|
---|
195 | DosWrite(1, szMsgNotFound, sizeof(szMsgNotFound)-1, &result);
|
---|
196 | DosWrite(1, szMsgNewLine, 3, &result);
|
---|
197 | return;
|
---|
198 | }
|
---|
199 |
|
---|
200 | for( i = 0;
|
---|
201 | arDevList[i].uID && !pRM->bIsDevDetected(arDevList[i].uID, SEARCH_ID_DEVICEID, TRUE);
|
---|
202 | i++ ) ;
|
---|
203 |
|
---|
204 | if( !arDevList[i].uID ) goto hardware_notfound;
|
---|
205 |
|
---|
206 |
|
---|
207 | // Rudi: detect adapter
|
---|
208 | pResources = pRM->pGetDevResources(arDevList[i].uID, SEARCH_ID_DEVICEID, TRUE, FALSE);
|
---|
209 |
|
---|
210 | if ((!pResources) || pResources->isEmpty()) {
|
---|
211 | goto hardware_notfound;
|
---|
212 | }
|
---|
213 |
|
---|
214 | if (pRM->getState() == rmAllocFailed) {
|
---|
215 | USHORT result;
|
---|
216 |
|
---|
217 | DosWrite(1, szMsgAllocResFailed1, sizeof(szMsgAllocResFailed1)-1, &result);
|
---|
218 |
|
---|
219 | switch( pRM->getResourceType() ) {
|
---|
220 | case RS_TYPE_IRQ :
|
---|
221 | strcpy(digit, szIRQ);
|
---|
222 | *DecWordToASCII(digit+sizeof(szIRQ)-1, (USHORT)pResources->uIRQLevel[0], 0) = '\0';
|
---|
223 | break;
|
---|
224 |
|
---|
225 | case RS_TYPE_IO :
|
---|
226 | strcpy(digit, szPort);
|
---|
227 | *HexWordToASCII(digit+sizeof(szPort)-1, (USHORT)pResources->uIOBase[0], 0) = '\0';
|
---|
228 | break;
|
---|
229 |
|
---|
230 | default:
|
---|
231 | strcpy(digit, "???");
|
---|
232 | }
|
---|
233 |
|
---|
234 | DosWrite(1, digit, strlen(digit), &result);
|
---|
235 | DosWrite(1, szMsgAllocResFailed2, sizeof(szMsgAllocResFailed2)-1, &result);
|
---|
236 | DosWrite(1, szMsgNewLine, 3, &result);
|
---|
237 | return;
|
---|
238 | }
|
---|
239 |
|
---|
240 | if (fVerbose) {
|
---|
241 | USHORT result;
|
---|
242 |
|
---|
243 | DosWrite(1, arDevList[i].pchName, _fstrlen(arDevList[i].pchName), &result);
|
---|
244 | DosWrite(1, szMsgConfig1, sizeof(szMsgConfig1)-1, &result);
|
---|
245 | *DecWordToASCII(digit, (USHORT)pResources->uIRQLevel[0], 0) = '\0';
|
---|
246 | DosWrite(1, digit, strlen(digit), &result);
|
---|
247 |
|
---|
248 | DosWrite(1, szMsgConfig2, sizeof(szMsgConfig2)-1, &result);
|
---|
249 | *HexWordToASCII(digit, pResources->uIOBase[0], 0) = '\0';
|
---|
250 | DosWrite(1, digit, strlen(digit), &result);
|
---|
251 |
|
---|
252 | DosWrite(1, szMsgNewLine, 3, &result);
|
---|
253 | }
|
---|
254 | delete pResources;
|
---|
255 |
|
---|
256 |
|
---|
257 | // Rudi: "detect" joystick
|
---|
258 | pResources = pRM->pGetDevResources(arDevList[i].uID, SEARCH_ID_DEVICEID, TRUE, TRUE);
|
---|
259 | if( pResources ) {
|
---|
260 | if (pRM->getState() == rmAllocFailed) {
|
---|
261 | USHORT result;
|
---|
262 |
|
---|
263 | DosWrite(1, szMsgAllocResFailed1, sizeof(szMsgAllocResFailed1)-1, &result);
|
---|
264 | strcpy(digit, szPort);
|
---|
265 | *HexWordToASCII(digit+sizeof(szPort)-1, (USHORT)pResources->uIOBase[0], 0) = '\0';
|
---|
266 | DosWrite(1, digit, strlen(digit), &result);
|
---|
267 |
|
---|
268 | DosWrite(1, szMsgNewLine, 3, &result);
|
---|
269 | }
|
---|
270 |
|
---|
271 | delete pResources;
|
---|
272 | }
|
---|
273 |
|
---|
274 |
|
---|
275 | // FMSYNTH object, this is the default MIDI device
|
---|
276 | // First create a timer, then the HW object.
|
---|
277 | pTimer = new TIMER(NULL, MIDI_TimerInterval, STREAM_FMSYNTH_PLAY);
|
---|
278 | if (pTimer->eState() != TIMER_Disabled)
|
---|
279 | {
|
---|
280 | new FMSYNTH(0x388, pTimer);
|
---|
281 | SetHardwareType(AUDIOHW_FMSYNTH_PLAY, MIDI, OPERATION_PLAY, 0);
|
---|
282 | SetHardwareType(AUDIOHW_FMSYNTH_PLAY, DATATYPE_MIDI, OPERATION_PLAY, 0);
|
---|
283 | // SetHardwareType(AUDIOHW_FMSYNTH_PLAY, DATATYPE_NULL, OPERATION_PLAY, 0);
|
---|
284 | }
|
---|
285 |
|
---|
286 | #if 0
|
---|
287 | // MPU401 object, this is the secondary MIDI device
|
---|
288 | // First create a timer, then the HW object.
|
---|
289 | pTimer = new TIMER(NULL, MIDI_TimerInterval, STREAM_MPU401_PLAY);
|
---|
290 | if (pTimer->eState() != TIMER_Disabled)
|
---|
291 | {
|
---|
292 | new MPU_401(pTimer);
|
---|
293 | SetHardwareType(AUDIOHW_MPU401_PLAY, MIDI, OPERATION_PLAY, 0);
|
---|
294 | SetHardwareType(AUDIOHW_MPU401_PLAY, DATATYPE_MIDI, OPERATION_PLAY, 0);
|
---|
295 | // SetHardwareType(AUDIOHW_MPU401_PLAY, DATATYPE_NULL, OPERATION_PLAY, 0);
|
---|
296 | }
|
---|
297 | #endif
|
---|
298 |
|
---|
299 | // Build the Wave Playback Hardware object
|
---|
300 | new WAVEAUDIO(AUDIOHW_WAVE_PLAY);
|
---|
301 |
|
---|
302 | // Build the Wave Capture Hardware object
|
---|
303 | new WAVEAUDIO(AUDIOHW_WAVE_CAPTURE);
|
---|
304 |
|
---|
305 |
|
---|
306 | #if 0
|
---|
307 | // fill in the ADAPTERINFO
|
---|
308 | codec_info.ulNumPorts = NUMIORANGES;
|
---|
309 | codec_info.Range[0].ulPort = pResourcesWSS->uIOBase[0];
|
---|
310 | codec_info.Range[0].ulRange = pResourcesWSS->uIOLength[0];
|
---|
311 | codec_info.Range[1].ulPort = pResourcesWSS->uIOBase[1];
|
---|
312 | codec_info.Range[1].ulRange = pResourcesWSS->uIOLength[1];
|
---|
313 | codec_info.Range[2].ulPort = pResourcesWSS->uIOBase[2];
|
---|
314 | codec_info.Range[2].ulRange = pResourcesWSS->uIOLength[2];
|
---|
315 | codec_info.Range[3].ulPort = pResourcesICS->uIOBase[0];
|
---|
316 | codec_info.Range[3].ulRange = pResourcesICS->uIOLength[0];
|
---|
317 |
|
---|
318 | // set up the addressing to the codec data for the vdd
|
---|
319 | pfcodec_info = (ADAPTERINFO __far *)&codec_info;
|
---|
320 | DevHelp_VirtToLin (SELECTOROF(pfcodec_info), (ULONG)(OFFSETOF(pfcodec_info)),
|
---|
321 | (PLIN)&pLincodec);
|
---|
322 |
|
---|
323 | // copy the pdd name out of the header.
|
---|
324 | for (int i = 0; i < sizeof(szPddName)-1 ; i++) {
|
---|
325 | if (phdr->abName[i] <= ' ')
|
---|
326 | break;
|
---|
327 | szPddName[i] = phdr->abName[i];
|
---|
328 | }
|
---|
329 | // register the VDD IDC entry point..
|
---|
330 | DevHelp_RegisterPDD ((NPSZ)szPddName, (PFN)IDCEntry_VDD);
|
---|
331 | #endif
|
---|
332 |
|
---|
333 | prp->usStatus = RPDONE;
|
---|
334 | prp->s.init_out.usCodeEnd = (USHORT) &end_of_text;
|
---|
335 | prp->s.init_out.usDataEnd = (USHORT) &end_of_heap;
|
---|
336 | }
|
---|
337 |
|
---|
338 |
|
---|