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; }
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(¶mTable[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, ¶mTable[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; }
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; }
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; }