Exemple #1
0
static BOOLEAN NTAPI
AddControllers(PDRIVER_OBJECT DriverObject)
/*
 * FUNCTION: Called on initialization to find our controllers and build device and controller objects for them
 * ARGUMENTS:
 *     DriverObject: Our driver's DriverObject (so we can create devices against it)
 * RETURNS:
 *     FALSE if we can't allocate a device, adapter, or interrupt object, or if we fail to find any controllers
 *     TRUE otherwise (i.e. we have at least one fully-configured controller)
 * NOTES:
 *     - Currently we only support ISA buses.
 *     - BUG: Windows 2000 seems to clobber the response from the IoQueryDeviceDescription callback, so now we
 *       just test a boolean value in the first object to see if it was completely populated.  The same value
 *       is tested for each controller before we build device objects for it.
 * TODO:
 *     - Report resource usage to the HAL
 */
{
    INTERFACE_TYPE InterfaceType = Isa;
    CONFIGURATION_TYPE ControllerType = DiskController;
    CONFIGURATION_TYPE PeripheralType = FloppyDiskPeripheral;
    KAFFINITY Affinity;
    DEVICE_DESCRIPTION DeviceDescription;
    UCHAR i;
    UCHAR j;

    PAGED_CODE();

    /* Find our controllers on all ISA buses */
    IoQueryDeviceDescription(&InterfaceType, 0, &ControllerType, 0, &PeripheralType, 0, ConfigCallback, 0);

    /*
     * w2k breaks the return val from ConfigCallback, so we have to hack around it, rather than just
     * looking for a return value from ConfigCallback.  We expect at least one controller.
     */
    if(!gControllerInfo[0].Populated)
    {
        WARN_(FLOPPY, "AddControllers: failed to get controller info from registry\n");
        return FALSE;
    }

    /* Now that we have a controller, set it up with the system */
    for(i = 0; i < gNumberOfControllers; i++)
    {
        /* 0: Report resource usage to the kernel, to make sure they aren't assigned to anyone else */
        /* FIXME: Implement me. */

        /* 1: Set up interrupt */
        gControllerInfo[i].MappedVector = HalGetInterruptVector(gControllerInfo[i].InterfaceType, gControllerInfo[i].BusNumber,
                                          gControllerInfo[i].Level, gControllerInfo[i].Vector,
                                          &gControllerInfo[i].MappedLevel, &Affinity);

        /* Must set up the DPC before we connect the interrupt */
        KeInitializeDpc(&gControllerInfo[i].Dpc, DpcForIsr, &gControllerInfo[i]);

        INFO_(FLOPPY, "Connecting interrupt %d to controller%d (object 0x%p)\n", gControllerInfo[i].MappedVector,
              i, &gControllerInfo[i]);

        /* NOTE: We cannot share our interrupt, even on level-triggered buses.  See Isr() for details. */
        if(IoConnectInterrupt(&gControllerInfo[i].InterruptObject, Isr, &gControllerInfo[i], 0, gControllerInfo[i].MappedVector,
                              gControllerInfo[i].MappedLevel, gControllerInfo[i].MappedLevel, gControllerInfo[i].InterruptMode,
                              FALSE, Affinity, 0) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "AddControllers: unable to connect interrupt\n");
            continue;
        }

        /* 2: Set up DMA */
        memset(&DeviceDescription, 0, sizeof(DeviceDescription));
        DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
        DeviceDescription.DmaChannel = gControllerInfo[i].Dma;
        DeviceDescription.InterfaceType = gControllerInfo[i].InterfaceType;
        DeviceDescription.BusNumber = gControllerInfo[i].BusNumber;
        DeviceDescription.MaximumLength = 2*18*512; /* based on a 1.44MB floppy */

        /* DMA 0,1,2,3 are 8-bit; 4,5,6,7 are 16-bit (4 is chain i think) */
        DeviceDescription.DmaWidth = gControllerInfo[i].Dma > 3 ? Width16Bits: Width8Bits;

        gControllerInfo[i].AdapterObject = HalGetAdapter(&DeviceDescription, &gControllerInfo[i].MapRegisters);

        if(!gControllerInfo[i].AdapterObject)
        {
            WARN_(FLOPPY, "AddControllers: unable to allocate an adapter object\n");
            IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
            continue;
        }

        /* 2b: Initialize the new controller */
        if(InitController(&gControllerInfo[i]) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "AddControllers(): Unable to set up controller %d - initialization failed\n", i);
            IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
            continue;
        }

        /* 2c: Set the controller's initlized flag so we know to release stuff in Unload */
        gControllerInfo[i].Initialized = TRUE;

        /* 3: per-drive setup */
        for(j = 0; j < gControllerInfo[i].NumberOfDrives; j++)
        {
            WCHAR DeviceNameBuf[MAX_DEVICE_NAME];
            UNICODE_STRING DeviceName;
            UNICODE_STRING LinkName;
            UNICODE_STRING ArcPath;
            UCHAR DriveNumber;

            INFO_(FLOPPY, "AddControllers(): Configuring drive %d on controller %d\n", i, j);

            /*
             * 3a: create a device object for the drive
             * Controllers and drives are 0-based, so the combos are:
             * 0: 0,0
             * 1: 0,1
             * 2: 0,2
             * 3: 0,3
             * 4: 1,0
             * 5: 1,1
             * ...
             * 14: 3,2
             * 15: 3,3
             */

            DriveNumber = (UCHAR)(i*4 + j); /* loss of precision is OK; there are only 16 of 'em */

            RtlZeroMemory(&DeviceNameBuf, MAX_DEVICE_NAME * sizeof(WCHAR));
            swprintf(DeviceNameBuf, L"\\Device\\Floppy%d", DriveNumber);
            RtlInitUnicodeString(&DeviceName, DeviceNameBuf);

            if(IoCreateDevice(DriverObject, sizeof(PVOID), &DeviceName,
                              FILE_DEVICE_DISK, FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE, FALSE,
                              &gControllerInfo[i].DriveInfo[j].DeviceObject) != STATUS_SUCCESS)
            {
                WARN_(FLOPPY, "AddControllers: unable to register a Device object\n");
                IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
                continue; /* continue on to next drive */
            }

            INFO_(FLOPPY, "AddControllers: New device: %S (0x%p)\n", DeviceNameBuf, gControllerInfo[i].DriveInfo[j].DeviceObject);

            /* 3b.5: Create an ARC path in case we're booting from this drive */
            swprintf(gControllerInfo[i].DriveInfo[j].ArcPathBuffer,
                     L"\\ArcName\\multi(%d)disk(%d)fdisk(%d)", gControllerInfo[i].BusNumber, i, DriveNumber);

            RtlInitUnicodeString(&ArcPath, gControllerInfo[i].DriveInfo[j].ArcPathBuffer);
            IoAssignArcName(&ArcPath, &DeviceName);

            /* 3c: Set flags up */
            gControllerInfo[i].DriveInfo[j].DeviceObject->Flags |= DO_DIRECT_IO;

            /* 3d: Create a symlink */
            swprintf(gControllerInfo[i].DriveInfo[j].SymLinkBuffer, L"\\DosDevices\\%c:", DriveNumber + 'A');
            RtlInitUnicodeString(&LinkName, gControllerInfo[i].DriveInfo[j].SymLinkBuffer);
            if(IoCreateSymbolicLink(&LinkName, &DeviceName) != STATUS_SUCCESS)
            {
                WARN_(FLOPPY, "AddControllers: Unable to create a symlink for drive %d\n", DriveNumber);
                IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
                IoDeassignArcName(&ArcPath);
                continue; /* continue to next drive */
            }

            /* 3e: Increase global floppy drives count */
            IoGetConfigurationInformation()->FloppyCount++;

            /* 3f: Set up the DPC */
            IoInitializeDpcRequest(gControllerInfo[i].DriveInfo[j].DeviceObject, (PIO_DPC_ROUTINE)DpcForIsr);

            /* 3g: Point the device extension at our DriveInfo struct */
            gControllerInfo[i].DriveInfo[j].DeviceObject->DeviceExtension = &gControllerInfo[i].DriveInfo[j];

            /* 3h: neat comic strip */

            /* 3i: set the initial media type to unknown */
            memset(&gControllerInfo[i].DriveInfo[j].DiskGeometry, 0, sizeof(DISK_GEOMETRY));
            gControllerInfo[i].DriveInfo[j].DiskGeometry.MediaType = Unknown;

            /* 3j: Now that we're done, set the Initialized flag so we know to free this in Unload */
            gControllerInfo[i].DriveInfo[j].Initialized = TRUE;

            /* 3k: Clear the DO_DEVICE_INITIALIZING flag */
            gControllerInfo[i].DriveInfo[j].DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
        }
    }

    INFO_(FLOPPY, "AddControllers: --------------------------------------------> finished adding controllers\n");

    return TRUE;
}
Exemple #2
0
NTSTATUS kdi_ConfigCallBack
(
/* INPUT PARAMETERS:  */

    dVoidPtr context,
    PUNICODE_STRING path_name,
    INTERFACE_TYPE bus_type,
    dUDWord bus_number,
    PKEY_VALUE_FULL_INFORMATION *bus_information,
    CONFIGURATION_TYPE controller_type,
    dUDWord controller_number,
    PKEY_VALUE_FULL_INFORMATION *controller_information,
    CONFIGURATION_TYPE peripheral_type,
    dUDWord peripheral_number,
    PKEY_VALUE_FULL_INFORMATION *peripheral_information

/* UPDATE PARAMETERS: */

/* OUTPUT PARAMETERS: */

)
/* COMMENTS: *****************************************************************
 *
 * Routine Description:
 *
 *    This routine is used to acquire all of the configuration
 *    information for each floppy disk controller and the
 *    peripheral driver attached to that controller.
 *
 * Arguments:
 *
 *    context - Pointer to the confuration information we are building
 *                    up.
 *
 *    path_name - unicode registry path.    Not Used.
 *
 *    bus_type - Internal, Isa, ...
 *
 *    bus_number - Which bus if we are on a multibus system.
 *
 *    bus_information - Configuration information about the bus. Not Used.
 *
 *    controller_type - Should always be DiskController.
 *
 *    controller_number - Which controller if there is more than one
 *                                controller in the system.
 *
 *    controller_information - Array of pointers to the three pieces of
 *                                    registry information.
 *
 *    peripheral_type - Should always be FloppyDiskPeripheral.
 *
 *    peripheral_number - Which floppy if this controller is maintaining
 *                                more than one.
 *
 *    peripheral_information - Array of pointers to the three pieces of
 *                                    registry information.
 *
 * Return Value:
 *
 *    STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES
 *    if it couldn't map the base csr or acquire the adapter object, or
 *    all of the resource information couldn't be acquired.
 *
 * DEFINITIONS: *************************************************************/
{

/* DATA: ********************************************************************/

    /* So we don't have to typecast the context. */
    ConfigDataPtr config = context;

    /* Simple iteration variable. */
    dUDWord i;

    /* This boolean will be used to denote whether we've seen this */
    /* controller before. */
    dBoolean new_controller;

    /* This will be used to denote whether we even have room */
    /* for a new controller. */
    dBoolean out_of_room;

    /* Iteration variable that will end up indexing to where */
    /* the controller information should be placed. */
    dUDWord controller_slot;

    /* Short hand for referencing the particular controller config */
    /* information that we are building up. */
    ConfigControllerDataPtr controller;

#if !MULTI_CONTROLLER
    PCM_FULL_RESOURCE_DESCRIPTOR peripheral_data_ptr = (PCM_FULL_RESOURCE_DESCRIPTOR)
        (((dUBytePtr)peripheral_information[IoQueryDeviceConfigurationData]) +
        peripheral_information[IoQueryDeviceConfigurationData]->DataOffset);
#endif

    /* These three boolean will tell us whether we got all the */
    /* information that we needed. */
    dBoolean found_port = FALSE;
    dBoolean found_interrupt = FALSE;
    dBoolean found_dma = FALSE;

/* CODE: ********************************************************************/

    ASSERT(controller_type == DiskController);
#if !MULTI_CONTROLLER
    ASSERT(peripheral_type == FloppyDiskPeripheral);
#endif

    /* Loop through the "slots" that we have for a new controller. */
    /* Determine if this is a controller that we've already seen, */
    /* or a new controller. */

    out_of_room = dTRUE;
    for (
        controller_slot = 0;
        controller_slot < MAXIMUM_CONTROLLERS_PER_MACHINE;
        controller_slot++
        ) {

        if (config->controller[controller_slot].actual_controller_number == -1) {

            new_controller = dTRUE;
            out_of_room = dFALSE;
            config->controller[controller_slot].actual_controller_number =
            controller_number;
            config->number_of_controllers++;
            break;

        } else if (config->controller[controller_slot].actual_controller_number
                        == (LONG)controller_number) {

            new_controller = dFALSE;
            out_of_room = dFALSE;
            break;

        }

    }

    if (out_of_room) {

        /* Just return and ignore the controller. */

        return STATUS_SUCCESS;

    }

    controller = &config->controller[controller_slot];

    if (new_controller) {

        PCM_FULL_RESOURCE_DESCRIPTOR controller_data =
                (PCM_FULL_RESOURCE_DESCRIPTOR)
                (((dUBytePtr)controller_information[IoQueryDeviceConfigurationData]) +
                controller_information[IoQueryDeviceConfigurationData]->DataOffset);

        /* We have the pointer. Save off the interface type and */
        /* the busnumber for use when we call the Hal and the */
        /* Io System. */

        controller->interface_type = bus_type;
        controller->bus_number = bus_number;
        controller->sharable_vector = dTRUE;
        controller->save_float_state = dFALSE;

        /* We need to get the following information out of the partial */
        /* resource descriptors. */

        /* The irql and vector. */

        /* The dma channel. */

        /* The base address and span covered by the floppy controllers */
        /* registers. */

        /* It is not defined how these appear in the partial resource */
        /* lists, so we will just loop over all of them.    If we find */
        /* something we don't recognize, we drop that information on */
        /* the floor.    When we have finished going through all the */
        /* partial information, we validate that we got the above */
        /* three. */

        kdi_CheckedDump(QIC117INFO,
                        "Q117i: path: %ls\n",
                        (ULONG)path_name->Buffer);
        kdi_CheckedDump(QIC117INFO,
                        "Q117i: adding controller: %08x\n",
                        controller_number);
        kdi_CheckedDump(QIC117INFO,
                        "Q117i: adding controller slot: %08x\n",
                        controller_slot);

        for (
            i = 0;
            i < controller_data->PartialResourceList.Count;
            i++
            ) {

            PCM_PARTIAL_RESOURCE_DESCRIPTOR partial =
                &controller_data->PartialResourceList.PartialDescriptors[i];

            switch (partial->Type) {

                case CmResourceTypePort: {

                    dBoolean in_io_space = !!partial->Flags;
                    found_port = dTRUE;

                    /* Save of the pointer to the partial so */
                    /* that we can later use it to report resources */
                    /* and we can also use this later in the routine */
                    /* to make sure that we got all of our resources. */

                    controller->span_of_controller_address =
                            partial->u.Port.Length;
                    controller->original_base_address =
                            partial->u.Port.Start;
                    controller->controller_base_address =
                            kdi_GetControllerBase(
                                bus_type,
                                bus_number,
                                partial->u.Port.Start,
                                controller->span_of_controller_address,
                                in_io_space,
                                &controller->mapped_address
                                );

                    if (!controller->controller_base_address) {

                            return STATUS_INSUFFICIENT_RESOURCES;

                    }

                    break;
                }
                case CmResourceTypeInterrupt: {

                    found_interrupt = dTRUE;

                    if (partial->Flags & CM_RESOURCE_INTERRUPT_LATCHED) {

                        controller->interrupt_mode = Latched;

                    } else {

                        controller->interrupt_mode = LevelSensitive;

                    }

                    controller->original_irql =  partial->u.Interrupt.Level;
                    controller->original_vector = partial->u.Interrupt.Vector;
                    controller->controller_vector =
                            HalGetInterruptVector(
                                bus_type,
                                bus_number,
                                partial->u.Interrupt.Level,
                                partial->u.Interrupt.Vector,
                                &controller->controller_irql,
                                &controller->processor_mask
                                );

                    break;
                }
                case CmResourceTypeDma: {

                    DEVICE_DESCRIPTION device_desc;

                    RtlZeroMemory(&device_desc,sizeof(device_desc));
                    found_dma = dTRUE;

                    controller->original_dma_channel = partial->u.Dma.Channel;

                    device_desc.Version = DEVICE_DESCRIPTION_VERSION;
                    if (partial->u.Dma.Channel > 3) {
                        device_desc.DmaWidth = Width16Bits;
                    } else {
                        device_desc.DmaWidth = Width8Bits;
                    }
                    device_desc.DemandMode = dTRUE;
                    device_desc.MaximumLength = 32l*1024l;
                    device_desc.AutoInitialize = dFALSE;
                    device_desc.ScatterGather = dFALSE;
                    device_desc.DmaChannel = partial->u.Dma.Channel;
                    device_desc.InterfaceType = bus_type;
                    device_desc.DmaSpeed = TypeA;
                    controller->number_of_map_registers = BYTES_TO_PAGES(32l*1024l);
                    controller->adapter_object =
                            HalGetAdapter(
                                &device_desc,
                                &controller->number_of_map_registers
                                );

                    kdi_CheckedDump(QIC117INFO,
                                    "Q117i: Bus Type = %08x\n",
                                    bus_type);

                    kdi_CheckedDump(QIC117INFO,
                                    "Q117i: Number of map registers = %08x\n",
                                    controller->number_of_map_registers );

                    if (!controller->adapter_object) {

                            return STATUS_INSUFFICIENT_RESOURCES;

                    }

                    break;

                }
                default: {

                    break;

                }

            }

        }

        /* If we didn't get all the information then we return */
        /* insufficient resources. */

        if ((!found_port) ||
            (!found_interrupt) ||
            (!found_dma)) {

            return STATUS_INSUFFICIENT_RESOURCES;

        }
        controller->number_of_tape_drives++;
        controller->ok_to_use_this_controller = dTRUE;

        {
            //
            // Get extra information about the floppy controller
            //

            RTL_QUERY_REGISTRY_TABLE    paramTable[2];
            ULONG apiSupported;
            WCHAR idstr[200];
            UNICODE_STRING str;

            str.Length = 0;
            str.MaximumLength = 200;
            str.Buffer = idstr;

            RtlZeroMemory(&paramTable[0], sizeof(paramTable));

            paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
            paramTable[0].Name = L"APISupported";
            paramTable[0].EntryContext = &str;
            paramTable[0].DefaultType = REG_SZ;
            paramTable[0].DefaultData = L"";
            paramTable[0].DefaultLength = sizeof(WCHAR);


            if (!NT_SUCCESS(RtlQueryRegistryValues(
                RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
                path_name->Buffer, &paramTable[0], NULL, NULL)))
            {
                str.Buffer[0] = 0;
            }

            controller->controller_data.clk_48mhz = FALSE;
            controller->controller_data.floppyEnablerApiSupported = FALSE;

            if (str.Buffer[0] != 0) {
                NTSTATUS ntStatus;
                PFILE_OBJECT file;      // file object is not needed,  but returned by API

                kdi_CheckedDump(QIC117INFO,
                       "Q117i: Got registry setting for EnablerAPI = %ls\n",
                        (ULONG)str.Buffer );

                ntStatus = IoGetDeviceObjectPointer(
                                &str,
                                FILE_READ_ACCESS,
                                &file,
                                &controller->controller_data.apiDeviceObject);

                if (NT_SUCCESS(ntStatus)) {
                    FDC_INFORMATION info;

                    controller->controller_data.floppyEnablerApiSupported = TRUE;

                    //
                    // set the DMA direction to unknown,  thereby forcing a
                    // call to set the direction
                    //
                    controller->controller_data.dmaDirection = 0xff;

                    ntStatus = kdi_FloppyEnabler(
                                    controller->controller_data.apiDeviceObject,
                                    IOCTL_GET_FDC_INFO, &info);

                    //
                    //  We got the info for the FDC,  now check for a 48MHz clock
                    //
                    if (NT_SUCCESS(ntStatus)) {
                        controller->controller_data.clk_48mhz =
                            (info.ClockRatesSupported == FDC_CLOCK_48MHZ);
                    }


                } else {
                    kdi_CheckedDump(QIC117DBGP,
                       "Q117i: Got registry setting for EnablerAPI = %ls but failed to open channel to device\n",
                        (ULONG)str.Buffer );
                }
            }

        }

    }

    kdi_CheckedDump(QIC117INFO,
            "Q117i: Got setting for 48mhz clock setting = %x\n",
            controller->controller_data.clk_48mhz );



    return STATUS_SUCCESS;
}
Exemple #3
0
BOOLEAN CreateDMA(PDEVICE_OBJECT DeviceObject)
{
    DEVICE_DESCRIPTION Desc;
    ULONG MappedRegs = 0;
    PDEVICE_EXTENSION Device = DeviceObject->DeviceExtension;
    KEVENT DMAEvent;
    KIRQL OldIrql;

    // Buffersize should already be set but it isn't yet !
    Device->BufferSize = SB_BUFSIZE;
    DPRINT("Bufsize == %u\n", Device->BufferSize);

    RtlZeroMemory(&Desc, sizeof(DEVICE_DESCRIPTION));

    // Init memory!
    Desc.Version = DEVICE_DESCRIPTION_VERSION;
    Desc.Master = FALSE;    // Slave
    Desc.ScatterGather = FALSE; // Don't think so anyway
    Desc.DemandMode = FALSE;    // == !SingleModeDMA
    Desc.AutoInitialize = TRUE; // ?
    Desc.Dma32BitAddresses = FALSE; // I don't think we can
    Desc.IgnoreCount = FALSE; // Should be OK
    Desc.Reserved1 = 0;
//    Desc.Reserved2 = 0;
    Desc.BusNumber = 0;
    Desc.DmaChannel = Device->DMA;    // Our channel :)
    Desc.InterfaceType = Isa;   // (BusType == MicroChannel) ? MicroChannel : Isa;
    Desc.DmaWidth = 0;    // hmm... 8 bits?
    Desc.DmaSpeed = 0;     // double hmm (Compatible it should be)
    Desc.MaximumLength = Device->BufferSize;
//    Desc.MinimumLength = 0;
    Desc.DmaPort = 0;

    DPRINT("Calling HalGetAdapter(), asking for %d mapped regs\n", MappedRegs);

    Device->Adapter = HalGetAdapter(&Desc, &MappedRegs);

    DPRINT("Called\n");

    if (! Device->Adapter)
    {
        DPRINT("HalGetAdapter() FAILED\n");
        return FALSE;
    }

    DPRINT("Bufsize == %u\n", Device->BufferSize);

    if (MappedRegs < BYTES_TO_PAGES(Device->BufferSize))
    {
        DPRINT("Could only allocate %u mapping registers\n", MappedRegs);

        if (MappedRegs == 0)
            return FALSE;

        Device->BufferSize = MappedRegs * PAGE_SIZE;
        DPRINT("Bufsize == %u\n", Device->BufferSize);
    }

    DPRINT("Allocated %u mapping registers\n", MappedRegs);

    // Check if we already have memory here...

    // Check to make sure we're >= minimum

    DPRINT("Allocating buffer\n");

    DPRINT("Bufsize == %u\n", Device->BufferSize);

    Device->VirtualBuffer = HalAllocateCommonBuffer(Device->Adapter, Device->BufferSize,
                                                &Device->Buffer, FALSE);

    // For some reason BufferSize == 0 here?!
//    DPRINT("Buffer == 0x%x Bufsize == %u\n", Device->Buffer, Device->BufferSize);
    DPRINT("Bufsize == %u,", Device->BufferSize);
    DPRINT("Buffer == 0x%x\n", Device->Buffer);

    if (! Device->VirtualBuffer)
    {
        DPRINT("Could not allocate buffer :(\n");
        // should try again with smaller buffer...
        return FALSE;
    }

//    DPRINT("Buffer == 0x%x Bufsize == %u\n", Device->Buffer, Device->BufferSize);
    DPRINT("Bufsize == %u,", Device->BufferSize);
    DPRINT("Buffer == 0x%x\n", Device->Buffer);

    DPRINT("Calling IoAllocateMdl()\n");
    Device->Mdl = IoAllocateMdl(Device->VirtualBuffer, Device->BufferSize, FALSE, FALSE, NULL);
    DPRINT("Bufsize == %u\n", Device->BufferSize);

    // IS THIS RIGHT:
    if (! Device->Mdl)
    {
        DPRINT("IoAllocateMdl() FAILED\n");
        // Free the HAL buffer
        return FALSE;
    }

    DPRINT("VBuffer == 0x%x Mdl == %u Bufsize == %u\n", Device->VirtualBuffer, Device->Mdl, Device->BufferSize);

    DPRINT("Calling MmBuildMdlForNonPagedPool\n");
    MmBuildMdlForNonPagedPool(Device->Mdl);

    DPRINT("Bufsize == %u\n", Device->BufferSize);

    // part II:
    KeInitializeEvent(&DMAEvent, SynchronizationEvent, FALSE);
    // Raise IRQL
    KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
    IoAllocateAdapterChannel(Device->Adapter, DeviceObject,
                            BYTES_TO_PAGES(Device->BufferSize),
                            SoundProgramDMA, &DMAEvent);
    // Lower IRQL
    KeLowerIrql(OldIrql);
    DPRINT("VBuffer == 0x%x Bufsize == %u\n", Device->VirtualBuffer, Device->BufferSize);
    KeWaitForSingleObject(&DMAEvent, Executive, KernelMode, FALSE, NULL);


//    if (MappedRegs == 0)
//        MappedRegs = 2;
//    else
//        MappedRegs ++;


//    Status = IoAllocateAdapterChannel(
//                    Adapter,
//                    DeviceObject,
//                    MappedRegs,
//                    CALLBACK,
//                    DeviceObject); // Context
    return TRUE;
}
Exemple #4
0
NDIS_STATUS
NdisMAllocateMapRegisters(
	IN	NDIS_HANDLE				MiniportAdapterHandle,
	IN	UINT					DmaChannel,
	IN	BOOLEAN					Dma32BitAddresses,
	IN	ULONG					PhysicalMapRegistersNeeded,
	IN	ULONG					MaximumPhysicalMapping
	)

/*++

Routine Description:

	Allocates map registers for bus mastering devices.

Arguments:

	MiniportAdapterHandle - Handle passed to MiniportInitialize.

	PhysicalMapRegistersNeeded - The maximum number of map registers needed
		by the Miniport at any one time.

	MaximumPhysicalMapping - Maximum length of a buffer that will have to be mapped.

Return Value:

	None.

--*/

{
	//
	// Convert the handle to our internal structure.
	//
	PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportAdapterHandle;

	//
	// This is needed by HalGetAdapter.
	//
	DEVICE_DESCRIPTION DeviceDescription;

	//
	// Returned by HalGetAdapter.
	//
	ULONG MapRegistersAllowed;

	//
	// Returned by HalGetAdapter.
	//
	PADAPTER_OBJECT AdapterObject;

	//
	// Map registers needed per channel.
	//
	ULONG MapRegistersPerChannel;

	NTSTATUS NtStatus;

	KIRQL OldIrql;

	UINT i;

	LARGE_INTEGER TimeoutValue;

	//
	// If the device is a busmaster, we get an adapter
	// object for it.
	// If map registers are needed, we loop, allocating an
	// adapter channel for each map register needed.
	//

	if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER) &&
		(Miniport->BusType != (NDIS_INTERFACE_TYPE)-1) &&
		(Miniport->BusNumber != (ULONG)-1))
	{
		TimeoutValue.QuadPart = Int32x32To64(2 * 1000, -10000);

		Miniport->PhysicalMapRegistersNeeded = PhysicalMapRegistersNeeded;
		Miniport->MaximumPhysicalMapping = MaximumPhysicalMapping;

		//
		// Allocate storage for holding the appropriate
		// information for each map register.
		//

		Miniport->MapRegisters = (PMAP_REGISTER_ENTRY)
		ALLOC_FROM_POOL(sizeof(MAP_REGISTER_ENTRY) * PhysicalMapRegistersNeeded,
						NDIS_TAG_DEFAULT);

		if (Miniport->MapRegisters == (PMAP_REGISTER_ENTRY)NULL)
		{
			//
			// Error out
			//

			NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
								   NDIS_ERROR_CODE_OUT_OF_RESOURCES,
								   1,
								   0xFFFFFFFF);

			return NDIS_STATUS_RESOURCES;
		}

		//
		// Use this event to tell us when ndisAllocationExecutionRoutine
		// has been called.
		//

		INITIALIZE_EVENT(&Miniport->AllocationEvent);

		//
		// Set up the device description; zero it out in case its
		// size changes.
		//

		ZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));

		DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
		DeviceDescription.Master = TRUE;
		DeviceDescription.ScatterGather = TRUE;

		DeviceDescription.BusNumber = Miniport->BusNumber;
		DeviceDescription.DmaChannel = DmaChannel;
		DeviceDescription.InterfaceType = Miniport->AdapterType;

		if (DeviceDescription.InterfaceType == NdisInterfaceIsa)
		{
			//
			// For ISA devices, the width is based on the DMA channel:
			// 0-3 == 8 bits, 5-7 == 16 bits. Timing is compatibility
			// mode.
			//

			if (DmaChannel > 4)
			{
				DeviceDescription.DmaWidth = Width16Bits;
			}
			else
			{
				DeviceDescription.DmaWidth = Width8Bits;
			}
			DeviceDescription.DmaSpeed = Compatible;

		}
		else if ((DeviceDescription.InterfaceType == NdisInterfaceEisa)	||
				 (DeviceDescription.InterfaceType == NdisInterfacePci)	||
				 (DeviceDescription.InterfaceType == NdisInterfaceMca))
		{
			DeviceDescription.Dma32BitAddresses = Dma32BitAddresses;
		}

		DeviceDescription.MaximumLength = MaximumPhysicalMapping;

		//
		// Get the adapter object.
		//

		AdapterObject = HalGetAdapter (&DeviceDescription, &MapRegistersAllowed);

		if (AdapterObject == NULL)
		{
			NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
								   NDIS_ERROR_CODE_OUT_OF_RESOURCES,
								   1,
								   0xFFFFFFFF);

			FREE_POOL(Miniport->MapRegisters);
			Miniport->MapRegisters = NULL;
			DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
					("<==NdisRegisterAdapter\n"));
			return NDIS_STATUS_RESOURCES;
		}

		//
		// We save this to call IoFreeMapRegisters later.
		//

		Miniport->SystemAdapterObject = AdapterObject;

		//
		// Determine how many map registers we need per channel.
		//

		MapRegistersPerChannel = ((MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2;

		ASSERT (MapRegistersAllowed >= MapRegistersPerChannel);

		//
		// Now loop, allocating an adapter channel each time, then
		// freeing everything but the map registers.
		//

		for (i=0; i<Miniport->PhysicalMapRegistersNeeded; i++)
		{
			Miniport->CurrentMapRegister = i;

			RAISE_IRQL_TO_DISPATCH(&OldIrql);

			NtStatus = IoAllocateAdapterChannel(AdapterObject,
												Miniport->DeviceObject,
												MapRegistersPerChannel,
												ndisAllocationExecutionRoutine,
												Miniport);

			if (!NT_SUCCESS(NtStatus))
			{
				DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
						("AllocateAdapterChannel: %lx\n", NtStatus));

				for (; i != 0; i--)
				{
					IoFreeMapRegisters(Miniport->SystemAdapterObject,
									   Miniport->MapRegisters[i-1].MapRegister,
									   MapRegistersPerChannel);
				}

				LOWER_IRQL(OldIrql);

				NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
									   NDIS_ERROR_CODE_OUT_OF_RESOURCES,
									   1,
									   0xFFFFFFFF);

				FREE_POOL(Miniport->MapRegisters);
				Miniport->MapRegisters = NULL;
				return NDIS_STATUS_RESOURCES;
			}

			LOWER_IRQL(OldIrql);

			TimeoutValue.QuadPart = Int32x32To64(2 * 1000, -10000);

			//
			// ndisAllocationExecutionRoutine will set this event
			// when it has gotten FirstTranslationEntry.
			//

			NtStatus = WAIT_FOR_OBJECT(&Miniport->AllocationEvent, &TimeoutValue);

			if (NtStatus != STATUS_SUCCESS)
			{
				DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
						("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus));

				RAISE_IRQL_TO_DISPATCH(&OldIrql);

				for (; i != 0; i--)
				{
					IoFreeMapRegisters(Miniport->SystemAdapterObject,
									   Miniport->MapRegisters[i-1].MapRegister,
									   MapRegistersPerChannel);
				}

				LOWER_IRQL(OldIrql);

				NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
										NDIS_ERROR_CODE_OUT_OF_RESOURCES,
										1,
										0xFFFFFFFF);

				FREE_POOL(Miniport->MapRegisters);
				Miniport->MapRegisters = NULL;
				return  NDIS_STATUS_RESOURCES;
			}

			RESET_EVENT(&Miniport->AllocationEvent);
		}
	}

	return NDIS_STATUS_SUCCESS;
}