示例#1
0
void get_write_paddings(unsigned long addr, int *p1, int *p2, int *p3,
                         int *p4, int bytes_written)
{
    // greetings to scud :-)
    int write_byte;
    int already_written;
    int padding;

    write_byte=SB1(addr);
    already_written=bytes_written;
    write_byte+=0x100;
    already_written%=0x100;
    padding=(write_byte-already_written)%0x100;
    if(padding<10) padding+=0x100;
    *p1=padding;

    write_byte=SB2(addr);
    already_written+=padding;
    write_byte+=0x100;
    already_written%=0x100;
    padding=(write_byte-already_written)%0x100;
    if(padding<10) padding+=0x100;
    *p2=padding;

    write_byte=SB3(addr);
    already_written+=padding;
    write_byte+=0x100;
    already_written%=0x100;
    padding=(write_byte-already_written)%0x100;
    if(padding<10) padding+=0x100;
    *p3=padding;

    write_byte=SB4(addr);
    already_written+=padding;
    write_byte+=0x100;
    already_written%=0x100;
    padding=(write_byte-already_written)%0x100;
    if(padding<10) padding+=0x100;
    *p4=padding;
}
示例#2
0
文件: init.c 项目: BillTheBest/WinNT4
NTSTATUS
SoundCardInstanceInit(
    IN   PWSTR RegistryPathName,
    IN   PVOID Context
)
{
    /*
    ** Instance data
    */

    PSOUND_CARD_INSTANCE CardInstance;

    //
    // Return code from last function called
    //

    NTSTATUS        Status;

    //
    // Configuration data :
    //

    SB_CONFIG_DATA  ConfigData;

    //
    // Where we keep all general driver information
    // We avoid using static data because :
    //     1. Accesses are slower with 32-bit offsets
    //     2. We support more than one card instance
    //

    PGLOBAL_DEVICE_INFO pGDI;

    //
    // The number of devices we actually create
    //

    int         NumberOfDevicesCreated;

    //
    //  The context is the global device info pointer from the previous
    //  instance
    //

    CardInstance = Context;


   /********************************************************************
    *
    * Allocate our global info
    *
    ********************************************************************/

    pGDI =
        (PGLOBAL_DEVICE_INFO)ExAllocatePool(
                                  NonPagedPool,
                                  sizeof(GLOBAL_DEVICE_INFO));

    if (pGDI == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    dprintf4((" DriverEntry():  GlobalInfo    : %08lXH", pGDI));

    RtlZeroMemory(pGDI, sizeof(GLOBAL_DEVICE_INFO));
    pGDI->Key              = GDI_KEY;
    pGDI->Hw.Key           = HARDWARE_KEY;
    pGDI->RegistryPathName = RegistryPathName;

    pGDI->Usage            = 0xFF;                    // Free
    pGDI->DriverObject     = CardInstance->pDriverObject;

    //
    // Mutual exclusion :
    //
    //    Everything is synchronized on the DeviceMutex (except for
    //    some stuff inside the wave device) except
    //
    //    Midi external output which takes too long and so is synchronized
    //    separately but grabs the DeviceMutex every time it actually
    //    writes anything and
    //
    //    Synth output where the hardware is separate but callbacks to the
    //    mixer must grab the DeviceMutex.
    //

    KeInitializeMutex(&pGDI->DeviceMutex,
                       2                     // High level
                       );

    KeInitializeMutex(&pGDI->MidiMutex,
                       1                     // Low level
                       );

    KeInitializeMutex(&pGDI->Hw.DSPMutex,
                       3                     // Highest level
                       );

   /********************************************************************
    *
    *  Add ourselves to the ring of cards
    *
    ********************************************************************/

    if (CardInstance->PrevGDI == NULL) {
        pGDI->Next = pGDI;
    } else {
        PGLOBAL_DEVICE_INFO pNext;
        pNext = CardInstance->PrevGDI->Next;
        CardInstance->PrevGDI->Next = pGDI;
        pGDI->Next = pNext;
    }
    CardInstance->PrevGDI = pGDI;


   /********************************************************************
    *
    *  See if we can find our bus.  We run on both ISA and EISA
    *  We ASSUME that if there's an ISA bus we're on that
    *
    ********************************************************************/

    Status = SoundGetBusNumber(Isa, &pGDI->BusNumber);

    if (!NT_SUCCESS(Status)) {
        //
        // Cound not find an ISA bus so try EISA
        //
        Status = SoundGetBusNumber(Eisa, &pGDI->BusNumber);

        if (!NT_SUCCESS(Status)) {
            Status = SoundGetBusNumber(MicroChannel, &pGDI->BusNumber);

            if (!NT_SUCCESS(Status)) {
                dprintf1(("driver does not work on non-Isa/Eisa/Mca"));
                return Status;
            }
            pGDI->BusType = MicroChannel;

        } else {
            pGDI->BusType = Eisa;
        }
    } else {
        pGDI->BusType = Isa;
    }

    //
    // Set configuration to default in case we don't get all the
    // values back from the registry.
    //
    // Also set default volume for all devices
    //

    ConfigData.Port            = SOUND_DEF_PORT;
    ConfigData.InterruptNumber = SOUND_DEF_INT;
    ConfigData.DmaChannel      = SOUND_DEF_DMACHANNEL;
    ConfigData.DmaChannel16    = SOUND_DEF_DMACHANNEL16;
    ConfigData.DmaBufferSize   = DEFAULT_DMA_BUFFERSIZE;
    ConfigData.MPU401Port      = SOUND_DEF_MPU401_PORT;
    ConfigData.LoadType        = SOUND_LOADTYPE_NORMAL;
    ConfigData.MixerSettingsFound = FALSE;

    //
    // Get the system configuration information for this driver.
    //
    //
    //     Port, Interrupt, DMA channel, DMA 16-bit channel DMA buffer size
    //

    {
        RTL_QUERY_REGISTRY_TABLE    Table[2];

        RtlZeroMemory(Table, sizeof(Table));

        Table[0].QueryRoutine = SoundReadConfiguration;

        Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
                                         pGDI->RegistryPathName,
                                         Table,
                                         &ConfigData,
                                         NULL );

        if (!NT_SUCCESS(Status)) {
            dprintf1(("ERROR: DriverEntry(): RtlQueryRegistryValues() Failed with Status = %XH", Status));
            return Status;
        }           // End IF (!NT_SUCCESS(Status))
    }           // End Query Resistry Values

    //
    // Save additional Config data
    //
    pGDI->InterruptNumber = ConfigData.InterruptNumber;
    pGDI->DmaChannel      = ConfigData.DmaChannel;
    pGDI->DmaChannel16    = ConfigData.DmaChannel16;

    //
    // Verify the DMA Buffer Size
    //
    if ( ConfigData.DmaBufferSize < MIN_DMA_BUFFERSIZE ) {
        ConfigData.DmaBufferSize = MIN_DMA_BUFFERSIZE;
        dprintf1((" DriverEntry(): Adjusting the DMA Buffer size, size in Registry was too small"));
    }

    //
    // print out some info about the configuration
    //

    dprintf2((" DriverEntry():  Base I/O Port     = %XH", ConfigData.Port));
    dprintf2((" DriverEntry():  Interrupt         = %u",  ConfigData.InterruptNumber));
    dprintf2((" DriverEntry():  DMA Channel       = %u",  ConfigData.DmaChannel));
    dprintf2((" DriverEntry():  DMA Channel (16 bit) = %u",  ConfigData.DmaChannel16));
    dprintf2((" DriverEntry():  DMA Buffer Size   = %XH", ConfigData.DmaBufferSize));
    dprintf2((" DriverEntry():  MPU 401 port      = %XH", ConfigData.MPU401Port));

    /*
    **  Create our wave devices to ease reporting problems
    */

    Status = SBCreateDevice(pGDI, WaveInDevice);
    if (!NT_SUCCESS(Status)) {
        return Status;
    }

    Status = SBCreateDevice(pGDI, WaveOutDevice);
    if (!NT_SUCCESS(Status)) {
        return Status;
    }

    /*
    **  Say we want to be called at shutdown time
    */

    Status = IoRegisterShutdownNotification(pGDI->DeviceObject[WaveInDevice]);
    if (!NT_SUCCESS(Status)) {
        return Status;
    }

    pGDI->ShutdownRegistered = TRUE;


    /*
    **  Check the configuration and acquire the resources
    */

    Status = SoundInitHardwareConfig(pGDI, &ConfigData);

    if (!NT_SUCCESS(Status)) {
        dprintf1(("ERROR: DriverEntry(): SoundInitHardwareConfig() Failed with Status = %XH",
                                 Status));
        return Status;
    }

    /*
    **  Initialize generic device environments - first get the
    **  hardware routines in place.
    **  We do this here after we've found out what hardware we've got
    */

    HwInitialize(pGDI);

    SoundInitMidiIn(&pGDI->MidiInfo,
                    &pGDI->Hw);


    /*
    **  Register most of our resources.  Some may be registered on
    **  the wave output device :
    **     16-bit dma channel
    **
    **  We wipe out the registration of the MPU401 port when we do this
    **  but this is OK.
    */

    {
        ULONG PortToReport;
        PortToReport = ConfigData.Port + MIX_ADDR_PORT;

        Status = SoundReportResourceUsage(
                     pGDI->DeviceObject[WaveInDevice],  // As good as any device to own
                                                   // it
                     pGDI->BusType,
                     pGDI->BusNumber,
                     &ConfigData.InterruptNumber,
                     INTERRUPT_MODE,
                     (BOOLEAN)(SB16(&pGDI->Hw) ? TRUE : FALSE),  // Sharable for SB16
                     &ConfigData.DmaChannel,
                     &PortToReport,
                     NUMBER_OF_SOUND_PORTS - MIX_ADDR_PORT);
    }

    if (!NT_SUCCESS(Status)) {
        dprintf1(("Error - failed to claim resources - code %8X", Status));
        pGDI->LoadStatus = SOUND_CONFIG_ERROR;
        return Status;
    }
    /*
    **  Now we know what device we've got we can create the appropriate
    **  devices
    */

    /*
    **  Thuderboard has no external midi and we're going to
    **  drive the SB16 in MPU401 mode if we can
    */

    if (!pGDI->Hw.ThunderBoard) {
        //
        //  Don't create the MPU401 device if it is disabled
        //
        if (!SB16(&pGDI->Hw) ||
            (ULONG)-1 != ConfigData.MPU401Port)
        {
            Status = SBCreateDevice(pGDI, MidiOutDevice);
            if (!NT_SUCCESS(Status)) {
                return Status;
            }
            Status = SBCreateDevice(pGDI, MidiInDevice);
            if (!NT_SUCCESS(Status)) {
                return Status;
            }
        }
    }

    /*
    **  Create volume control stuff for those devices which have it
    */

    if (SBPRO(&pGDI->Hw) || SB16(&pGDI->Hw)
#ifdef SB_CD
        ||
        pGDI->Hw.SBCDBase != NULL
#endif // SB_CD
        ) {
        Status = SBCreateDevice(pGDI, LineInDevice);
        if (!NT_SUCCESS(Status)) {
            return Status;
        }
        Status = SBCreateDevice(pGDI, CDInternal);
        if (!NT_SUCCESS(Status)) {
            return Status;
        }
        Status = SBCreateDevice(pGDI, MixerDevice);
        if (!NT_SUCCESS(Status)) {
            return Status;
        }
    } else {
        /*  Volume setting not supported for our wave device */
        ((PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveOutDevice]->DeviceExtension)->CreationFlags |=
            SOUND_CREATION_NO_VOLUME;
    }

    /*
    ** Init the WaveInfo structure
    */

    SoundInitializeWaveInfo(&pGDI->WaveInfo,
                            (UCHAR)(SB1(&pGDI->Hw) ?
                                        SoundReprogramOnInterruptDMA :
                                        SoundAutoInitDMA),
                            SoundQueryFormat,
                            &pGDI->Hw);

    if (ConfigData.SynthType == SOUND_SYNTH_TYPE_NONE) {
        /*
        **  This will happen if the user selected a basic config without
        **  a synthesizer.
        */
        dprintf2(("No synth!"));
    } else {
        Status = SynthInit(CardInstance->pDriverObject,
                           pGDI->RegistryPathName,
                           &pGDI->Synth,
                           SB16(&pGDI->Hw) ||
                           SBPRO(&pGDI->Hw) && INPORT(&pGDI->Hw, 0) == 0 ?
                               ConfigData.Port : SYNTH_PORT,
                           FALSE,                         // Interrupt not enabled
                           pGDI->BusType,
                           pGDI->BusNumber,
                           NULL,
                           SOUND_MIXER_INVALID_CONTROL_ID,// Set volume later
                           TRUE,                          // Allow multiple
                           SoundMidiOutGetSynthCaps
                           );
        
        if (!NT_SUCCESS(Status)) {
        
            /*
            **  OK - we can get along without a synth
            */
        
            dprintf2(("No synth!"));
        } else {
            if (!pGDI->Synth.IsOpl3) {
                dprintf2(("Synth is Adlib"));
            } else {
        
                /*
                **  Bad aliasing in early sound blasters means we can
                **  guess wrong.
                */
        
                if (!(SB16(&pGDI->Hw) || SBPRO(&pGDI->Hw) && INPORT(&pGDI->Hw, 0) == 0)) {
                    pGDI->Synth.IsOpl3 = FALSE;
                }
                dprintf2(("Synth is Opl3"));
            }
        }
    }

    /*
    **  Set the mixer up.
    **
    **  Note that the mixer info depends on what hardware is present
    **  so this must be called after we have checked out the hardware.
    */

    if (pGDI->DeviceObject[MixerDevice]) {
        Status = SoundMixerInit(pGDI->DeviceObject[MixerDevice]->DeviceExtension,
                                &ConfigData.MixerSettings,
                                ConfigData.MixerSettingsFound);

        if (!NT_SUCCESS(Status)) {
            return Status;
        }
    }

    /*
    ** Save new settings
    */

    Status = SoundSaveConfig(pGDI->RegistryPathName,
                             ConfigData.Port,
                             ConfigData.DmaChannel,
                             ConfigData.DmaChannel16,
                             ConfigData.InterruptNumber,
                             ConfigData.MPU401Port,
                             (BOOLEAN)(pGDI->Synth.DeviceObject != NULL),
                             pGDI->Synth.IsOpl3,
                             pGDI->WaveInfo.DMABuf.BufferSize);

    if (!NT_SUCCESS(Status)) {
        return Status;
    }

    /*
    **  Finally test the PRO interrupt
    */

    if (SBPRO(&pGDI->Hw)) {
        BOOLEAN Ok;

        SoundEnter(pGDI->DeviceObject[WaveOutDevice]->DeviceExtension,
                   TRUE);
        Ok = 0 == SoundTestWaveDevice(pGDI->DeviceObject[WaveOutDevice]);
        SoundEnter(pGDI->DeviceObject[WaveOutDevice]->DeviceExtension,
                   FALSE);
        if (!Ok) {
            pGDI->LoadStatus = SOUND_CONFIG_BADDMA;
            return STATUS_DEVICE_CONFIGURATION_ERROR;
        }
    }

    /*
    ** Exit OK Message
    */

    pGDI->LoadStatus = SOUND_CONFIG_OK;

    return STATUS_SUCCESS;

}
示例#3
0
NTSTATUS
SoundMixerInit(
    PLOCAL_DEVICE_INFO       pLDI,
    PMIXER_REGISTRY_DATA     SavedControlData,
    BOOLEAN                  MixerSettingsFound
)
{
    int i, SetIndex;
    PLOCAL_MIXER_DATA LocalMixerData;
    PGLOBAL_DEVICE_INFO pGDI;
    PMIXER_INFO MixerInfo;

    pGDI           = pLDI->pGlobalInfo;
    MixerInfo      = &pGDI->MixerInfo;
    LocalMixerData = &pGDI->LocalMixerData;

    /*
    **  Avoid assertions by properly entering the mixer
    */


    /*
    **  Pick up the correct mixer type
    */
    if (SB1(&pGDI->Hw)) {
        return STATUS_SUCCESS;
    }

    KeWaitForSingleObject(&pGDI->DeviceMutex,
                          Executive,
                          KernelMode,
                          FALSE,         // Not alertable
                          NULL);

#ifdef SB_CD
    if (pGDI->Hw.SBCDBase) {
        SBCDMixerInit(pGDI);
    } else
#endif // SB_CD
    {
        if (SBPRO(&pGDI->Hw)) {
            SBPROMixerInit(pGDI);
        } else {
            ASSERT(SB16(&pGDI->Hw));
            SB16MixerInit(pGDI);
        }
    }

    ASSERT(LocalMixerData->NumberOfControls <= MAXCONTROLS);
    ASSERT(LocalMixerData->NumberOfLines <= MAXLINES);
    ASSERT(LocalMixerData->MaxSettableItems <= MAXSETTABLECONTROLS);

    /*
    **  Check the saved data matches
    */

    if (MixerSettingsFound) {
        dprintf3(("Saved mixer settings: Version = %x, DSPVersion = %x, NumberOfControls = %d",
                  SavedControlData->MixerVersion,
                  SavedControlData->DSPVersion,
                  SavedControlData->NumberOfControls));

        if (SavedControlData->MixerVersion     != DRIVER_VERSION ||
            SavedControlData->DSPVersion       != pGDI->Hw.DSPVersion ||
            SavedControlData->NumberOfControls !=
                LocalMixerData->MaxSettableItems) {

            dprintf1(("Saved mixer settings incompatible"));
            MixerSettingsFound = FALSE;
        }
    }

    /*
    **  Init the generic mixer stuff first so we can use it
    */

    SoundInitMixerInfo(&pGDI->MixerInfo,
                       HwGetLineFlags,
                       HwGetControl,
                       HwGetCombinedControl,
                       HwSetControl);

    /*
    **  Get to a known state - this is common to ALL mixers
    **  Detecting the SBCD mixer involves resetting it however.
    */

#ifdef SB_CD
    if (pGDI->Hw.SBCDBase == NULL) {
        dspWriteMixer(pGDI, MIX_RESET_REG, 0);
    }
#endif // SB_CD

    /*
    **  Set this device up with its mixer data
    */
    pLDI->DeviceType         = MIXER_DEVICE;
    pLDI->DeviceSpecificData = (PVOID)MixerInfo;

    /*
    ** Make sure everyone can find the mixer device
    */

    {
        PDEVICE_OBJECT pDO;
        PLOCAL_DEVICE_INFO pLDIDev;

        for (pDO = pGDI->DeviceObject[WaveInDevice]->DriverObject->DeviceObject;
             pDO != NULL;
             pDO = pDO->NextDevice) {


            pLDIDev = (PLOCAL_DEVICE_INFO)pDO->DeviceExtension;

            /*
            **  For multiple cards the following test may fail
            */

            if (pLDIDev->pGlobalInfo == pGDI ||
                pDO == pGDI->Synth.DeviceObject) {
                pLDIDev->MixerDevice = pLDI;
            }
        }
    }


    /*
    **  Create control info
    */

    for (i = 0, SetIndex = 0; i < LocalMixerData->NumberOfControls ; i++) {

        /*
        **  Read limits
        */

        if ((LocalMixerData->MixerControlInit[i].dwControlType & MIXERCONTROL_CT_UNITS_MASK) ==
                MIXERCONTROL_CT_UNITS_SIGNED) {

            pGDI->LocalMixerData.ControlInfo[i].Signed = TRUE;
            pGDI->LocalMixerData.ControlInfo[i].Range.Min.s =
                (SHORT)LocalMixerData->MixerControlInit[i].Bounds.lMinimum;
            pGDI->LocalMixerData.ControlInfo[i].Range.Max.s =
                (SHORT)LocalMixerData->MixerControlInit[i].Bounds.lMaximum;
        } else {

            if ((LocalMixerData->MixerControlInit[i].dwControlType & MIXERCONTROL_CT_UNITS_MASK) ==
                     MIXERCONTROL_CT_UNITS_BOOLEAN) {
                pGDI->LocalMixerData.ControlInfo[i].Boolean = TRUE;
            }
            pGDI->LocalMixerData.ControlInfo[i].Range.Min.u =
                (USHORT)LocalMixerData->MixerControlInit[i].Bounds.dwMinimum;
            pGDI->LocalMixerData.ControlInfo[i].Range.Max.u =
                (USHORT)LocalMixerData->MixerControlInit[i].Bounds.dwMaximum;
        }

        /*
        **  Remember if it's a mux and tot up text items
        */

        if (LocalMixerData->MixerControlInit[i].dwControlType == MIXERCONTROL_CONTROLTYPE_MIXER ||
            LocalMixerData->MixerControlInit[i].dwControlType == MIXERCONTROL_CONTROLTYPE_MUX) {
            pGDI->LocalMixerData.ControlInfo[i].Mux = TRUE;

            LocalMixerData->NumberOfTextItems +=
                (UCHAR)LocalMixerData->MixerControlInit[i].cMultipleItems;

            ASSERT(LocalMixerData->MixerControlInit[i].cMultipleItems <=
                   MAXITEMS);
        }

        /*
        **  Only meters are not settable here
        */

        if ((LocalMixerData->MixerControlInit[i].dwControlType & MIXERCONTROL_CT_CLASS_MASK) !=
            MIXERCONTROL_CT_CLASS_METER)
        {
            LocalMixerData->ControlInfo[i].SetIndex = (UCHAR)SetIndex;
            SoundInitDataItem(MixerInfo,
                              &LocalMixerData->ControlNotification[SetIndex],
                              (USHORT)MM_MIXM_CONTROL_CHANGE,
                              (USHORT)i);
            if (MixerSettingsFound) {

                    /*
                    **  What if it's invalid?
                    */

                LocalMixerData->ControlInfo[i].Data =
                    SavedControlData->ControlData[SetIndex];
            }
            SetIndex++;
        } else {
            LocalMixerData->ControlInfo[i].SetIndex = MIXER_SET_INDEX_INVALID;
        }
    }

    ASSERTMSG("MaxSettableItems wrong!",
              SetIndex == LocalMixerData->MaxSettableItems);

    /*
    **  Create line info
    */

    for (i = 0; i < LocalMixerData->NumberOfLines; i++) {
        SoundInitDataItem(MixerInfo,
                          &pGDI->LocalMixerData.LineNotification[i],
                          (USHORT)MM_MIXM_LINE_CHANGE,
                          (USHORT)i);
    }

    /*
    **  Set everything up.
    */

    for (i = 0; i < LocalMixerData->NumberOfControls; i++) {
        SoundMixerSet(pGDI, i);
    }

    KeReleaseMutex(&pGDI->DeviceMutex, FALSE);

    return STATUS_SUCCESS;
}