/* $Id: init.cpp 191 2001-09-28 12:10:07Z sandervl $ */ /* SCCSID = %W% %E% */ /**************************************************************************** * * * Copyright (c) IBM Corporation 1994 - 1997. * * * * The following IBM OS/2 source code is provided to you solely for the * * the purpose of assisting you in your development of OS/2 device drivers. * * You may use this code in accordance with the IBM License Agreement * * provided in the IBM Device Driver Source Kit for OS/2. * * * ****************************************************************************/ /**@internal %W% * Top level device driver initialization. * @version %I% * @context * Physical DD initialization context: Ring3 with I/O privledge. * Discarded after use. * @notes * Creates resource manager object and uses that RM object to figure out * whether audio hardware is present. If present, RM provides IO resources * to operate hardware. This modules uses that information to create * Audio HW objects and other global data structures. * @history */ #pragma code_seg ("_inittext"); ////#pragma data_seg ("_initdata","endds"); extern "C" { // 16-bit header files are not C++ aware #define INCL_NOPMAPI #define INCL_DOSMISC #include #include #include } #include #include #include #include "strategy.h" // OS/2 DD strategy interface #include "header.h" // Device driver header #include "parse.h" // Parses DEVICE= command line #include "malloc.h" // Heap memory used by this driver #include "mpu401.hpp" // Object definition #include "wavehw.hpp" // Object definition #include "irq.hpp" // Object definition #include "timer.hpp" // Object definition #include "stream.hpp" // pStreamList #include "rm.hpp" // Object definition #include "end.h" // end_of_data, end_of_text() #include "sizedefs.h" // HEAP_SIZE #include "idc_vdd.h" // VDD interface and Data Structs #include // Pragmas and more. #include #include "commdbg.h" #include #ifndef PCI_VENDOR_ID_CREATIVE #define PCI_VENDOR_ID_CREATIVE 0x1102UL #endif #ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1 #define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002UL #endif #ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1_JOYSTICK #define PCI_DEVICE_ID_CREATIVE_EMU10K1_JOYSTICK 0x7002 #endif #define PCI_ID ((PCI_DEVICE_ID_CREATIVE_EMU10K1<<16UL)|PCI_VENDOR_ID_CREATIVE) #define PCI_IDJOY ((PCI_DEVICE_ID_CREATIVE_EMU10K1_JOYSTICK<<16UL)|PCI_VENDOR_ID_CREATIVE) // Default MIDI timer interval, milliseconds. static USHORT MIDI_TimerInterval = 10; static char szSBLive[] = "SoundBlaster Live! MMPM/2 Audio Driver v"SBLIVE_VERSION; static char szCopyRight[] = "Copyright 2000-2001 Sander van Leeuwen (sandervl@xs4all.nl)"; static char NEWLINE[] = "\r\n"; static char szSBLiveNotFound[] = "SB Live! hardware not detected!"; static char szSBLiveAllocResFailed1[] = "Another device driver was granted exclusive access to IRQ "; static char szSBLiveAllocResFailed2[] = "Unable to allocate hardware resources! Aborting..."; static char szSBLiveConfig1[] = "SB Live! configuration: IRQ "; static char szSBLiveConfig2[] = ", IO Port 0x"; static char szSBLiveConfigJoy[] = "SB Live! Joystick : IO Port 0x"; // // ASCII Z-String used to register for PDD-VDD IDC must // Name is copied from header at runtime. // char szPddName[9] = {0}; char digit[16] = {0}; ResourceManager* pRM = 0; // Resource manager object. // // Strategy Init // void StrategyInit(PREQPACKET prp) { Device_Help = (PFN) prp->s.init_in.ulDevHlp; prp->s.init_out.usCodeEnd = 0; prp->s.init_out.usDataEnd = 0; prp->usStatus = RPDONE | RPERR | RPGENFAIL; /* Initialize Heap. */ unsigned uInitSize; // Actual size of Heap following initialization. uInitSize = HeapInit( HEAP_SIZE ); if ((HEAP_SIZE-uInitSize) > 64) { // Should get size of request, less some overhead. // ### pError->vLog( HeapInitFailure ); //### Error log 'pError' not yet created. return; } /* Heap initialized. */ // Initialize global lists. pAudioHWList = new QUEUEHEAD; pStreamList = new QUEUEHEAD; pTimerList = new QUEUEHEAD; // Fetch command line parameters. if (!GetParms(prp->s.init_in.szArgs)) { return; } // Now that we've grabbed our cmd line options, // we can start processing stuff that depends on those switches. if (fInt3BeforeInit) DebugInt3(); // If we got a /V (verbose) flag on the DEVICE= command, route messages // to the display. if (fVerbose) { USHORT result; DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); DosWrite(1, (VOID FAR*)szSBLive, sizeof(szSBLive)-1, &result); DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); DosWrite(1, (VOID FAR*)szCopyRight, sizeof(szCopyRight), &result); DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); } if (szCL_DevName[0] != ' ') // Was a valid device name specified? memcpy(phdr->abName,szCL_DevName,8); // yes, copy it to the dev header pRM = new ResourceManager(PCI_ID); // Create the RM object. if (! pRM) { return; } //SvL: Check if SB Live hardware has been detected by the resource manager if(pRM->getState() != rmDriverCreated || !pRM->bIsDevDetected(PCI_ID, SEARCH_ID_DEVICEID, TRUE)) { hardware_notfound: USHORT result; DosWrite(1, (VOID FAR*)szSBLiveNotFound, sizeof(szSBLiveNotFound)-1, &result); DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); return; } LDev_Resources *pResources = pRM->pGetDevResources(PCI_ID, SEARCH_ID_DEVICEID, TRUE); if ((!pResources) || pResources->isEmpty()) { goto hardware_notfound; } if (pRM->getState() == rmAllocFailed) { USHORT result; DosWrite(1, (VOID FAR*)szSBLiveAllocResFailed1, sizeof(szSBLiveAllocResFailed1)-1, &result); DecWordToASCII(digit, (USHORT)pResources->uIRQLevel[0], 0); DosWrite(1, (VOID FAR*)digit, strlen(digit), &result); DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); DosWrite(1, (VOID FAR*)szSBLiveAllocResFailed2, sizeof(szSBLiveAllocResFailed2)-1, &result); DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); return; } if (fVerbose) { USHORT result; DecWordToASCII(digit, (USHORT)pResources->uIRQLevel[0], 0); DosWrite(1, (VOID FAR*)szSBLiveConfig1, sizeof(szSBLiveConfig1)-1, &result); DosWrite(1, (VOID FAR*)digit, strlen(digit), &result); DosWrite(1, (VOID FAR*)szSBLiveConfig2, sizeof(szSBLiveConfig2)-1, &result); HexWordToASCII(digit, pResources->uIOBase[0], 0); DosWrite(1, (VOID FAR*)digit, strlen(digit), &result); } delete pResources; //Joystick detection if(pRM->bIsDevDetected(PCI_IDJOY, SEARCH_ID_DEVICEID, TRUE)) { pResources = pRM->pGetDevResources(PCI_IDJOY, SEARCH_ID_DEVICEID, TRUE, TRUE); if((pResources) && !pResources->isEmpty() && fVerbose) { USHORT result; DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); DosWrite(1, (VOID FAR*)szSBLiveConfigJoy, sizeof(szSBLiveConfigJoy)-1, &result); HexWordToASCII(digit, pResources->uIOBase[0], 0); DosWrite(1, (VOID FAR*)digit, strlen(digit), &result); } delete pResources; } if (fVerbose) { USHORT result; DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); DosWrite(1, (VOID FAR*)NEWLINE, sizeof(NEWLINE)-1, &result); } // Build the MPU401 object only if we got a good 2115 init. // First create a timer, then the HW object. TIMER* pMPUTimer = new TIMER(NULL, MIDI_TimerInterval, STREAM_MPU401_PLAY ); if (pMPUTimer->eState() != TIMER_Disabled) new MPU_401(pMPUTimer); SetHardwareType(AUDIOHW_MPU401_PLAY, MIDI, OPERATION_PLAY, 0); SetHardwareType(AUDIOHW_MPU401_PLAY, DATATYPE_MIDI, OPERATION_PLAY, 0); //// SetHardwareType(AUDIOHW_MPU401_PLAY, 0, OPERATION_PLAY, 0); //### Must be fixed. // DART on Warp3 SetHardwareType(AUDIOHW_WAVE_PLAY, DATATYPE_NULL, OPERATION_PLAY, 0); SetHardwareType(AUDIOHW_WAVE_CAPTURE, DATATYPE_NULL, OPERATION_RECORD, 0); // Build the Wave Playback Hardware object new WAVEPLAY(); new WAVEREC(); #if 0 // fill in the ADAPTERINFO codec_info.ulNumPorts = NUMIORANGES; codec_info.Range[0].ulPort = pResourcesWSS->uIOBase[0]; codec_info.Range[0].ulRange = pResourcesWSS->uIOLength[0]; codec_info.Range[1].ulPort = pResourcesWSS->uIOBase[1]; codec_info.Range[1].ulRange = pResourcesWSS->uIOLength[1]; codec_info.Range[2].ulPort = pResourcesWSS->uIOBase[2]; codec_info.Range[2].ulRange = pResourcesWSS->uIOLength[2]; codec_info.Range[3].ulPort = pResourcesICS->uIOBase[0]; codec_info.Range[3].ulRange = pResourcesICS->uIOLength[0]; // set up the addressing to the codec data for the vdd pfcodec_info = (ADAPTERINFO __far *)&codec_info; DevHelp_VirtToLin (SELECTOROF(pfcodec_info), (ULONG)(OFFSETOF(pfcodec_info)), (PLIN)&pLincodec); // copy the pdd name out of the header. for (int i = 0; i < sizeof(szPddName)-1 ; i++) { if (phdr->abName[i] <= ' ') break; szPddName[i] = phdr->abName[i]; } // register the VDD IDC entry point.. DevHelp_RegisterPDD ((NPSZ)szPddName, (PFN)IDCEntry_VDD); #endif prp->usStatus = RPDONE; prp->s.init_out.usCodeEnd = (USHORT) &end_of_text; prp->s.init_out.usDataEnd = (USHORT) &end_of_heap; }