| [354] | 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 |
|
|---|