/*++ Copyright (c) 1991 Microsoft Corporation Module Name: cmres.c Abstract: This file contains routines to translate resources between PnP ISA/BIOS format and Windows NT formats. Author: Stephane Plante (splante) 20-Nov-1996 Environment: Kernel mode only. Revision History: 13-Feb-1997: Initial Revision --*/ #include "pch.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE,PnpiCmResourceToBiosAddress) #pragma alloc_text(PAGE,PnpiCmResourceToBiosAddressDouble) #pragma alloc_text(PAGE,PnpiCmResourceToBiosDma) #pragma alloc_text(PAGE,PnpiCmResourceToBiosExtendedIrq) #pragma alloc_text(PAGE,PnpiCmResourceToBiosIoFixedPort) #pragma alloc_text(PAGE,PnpiCmResourceToBiosIoPort) #pragma alloc_text(PAGE,PnpiCmResourceToBiosIrq) #pragma alloc_text(PAGE,PnpiCmResourceToBiosMemory) #pragma alloc_text(PAGE,PnpiCmResourceToBiosMemory32) #pragma alloc_text(PAGE,PnpiCmResourceToBiosMemory32Fixed) #pragma alloc_text(PAGE,PnpiCmResourceValidEmptyList) #pragma alloc_text(PAGE,PnpCmResourcesToBiosResources) #endif NTSTATUS PnpiCmResourceToBiosAddress( IN PUCHAR Buffer, IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine converts the proper Cm resource descriptor back into a word address descriptor Arguments: Buffer - Pointer to the Bios Resource list List - Pointer to the CM resource List Return: NTSTATUS --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PPNP_WORD_ADDRESS_DESCRIPTOR buffer; UCHAR type; ULONG i; PAGED_CODE(); // // Setup the initial buffer // buffer = (PPNP_WORD_ADDRESS_DESCRIPTOR) Buffer; // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1 ); ASSERT( aList->PartialResourceList.Count ); // // Determine which type of descriptor we are looking for // switch (buffer->RFlag) { case PNP_ADDRESS_MEMORY_TYPE: type = CmResourceTypeMemory; break; case PNP_ADDRESS_IO_TYPE: type = CmResourceTypePort; break; case PNP_ADDRESS_BUS_NUMBER_TYPE: type = CmResourceTypeBusNumber; break; default: return STATUS_UNSUCCESSFUL; } // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != type) { // // No // continue; } switch (desc->Type) { case PNP_ADDRESS_MEMORY_TYPE: // // Set the flags // buffer->TFlag = 0; if (desc->Flags & CM_RESOURCE_MEMORY_READ_WRITE) { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_WRITE; } else { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_ONLY; } if (desc->Flags & CM_RESOURCE_MEMORY_CACHEABLE) { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_CACHEABLE; } else if (desc->Flags & CM_RESOURCE_MEMORY_COMBINEDWRITE) { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_WRITE_COMBINE; } else if (desc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_PREFETCHABLE; } else { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_NONCACHEABLE; } // // Set the rest of the information // buffer->MinimumAddress = (USHORT) (desc->u.Memory.Start.LowPart & 0xFFFF); buffer->MaximumAddress = buffer->MinimumAddress + (USHORT) (desc->u.Memory.Length - 1); buffer->AddressLength = (USHORT) desc->u.Memory.Length; break; case PNP_ADDRESS_IO_TYPE: // // We must extract the flags here from the // devicePrivate resource // // // Set the rest of the information // buffer->MinimumAddress = (USHORT) (desc->u.Port.Start.LowPart & 0xFFFF); buffer->MaximumAddress = buffer->MinimumAddress + (USHORT) (desc->u.Port.Length - 1); buffer->AddressLength = (USHORT) desc->u.Port.Length; break; case PNP_ADDRESS_BUS_NUMBER_TYPE: buffer->MinimumAddress = (USHORT) (desc->u.BusNumber.Start & 0xFFFF); buffer->MaximumAddress = buffer->MinimumAddress + (USHORT) (desc->u.BusNumber.Length - 1); buffer->AddressLength = (USHORT) desc->u.BusNumber.Length; break; } // switch // // Handling for the GFlags goes here, if we ever decide to // support it // // // Done with descriptor and match // desc->Type = CmResourceTypeNull; break; } // for // // Done // return STATUS_SUCCESS; } NTSTATUS PnpiCmResourceToBiosAddressDouble( IN PUCHAR Buffer, IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine converts the proper Cm resource descriptor back into a word address descriptor Arguments: Buffer - Pointer to the Bios Resource list List - Pointer to the CM resource List Return: NTSTATUS --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PPNP_DWORD_ADDRESS_DESCRIPTOR buffer; UCHAR type; ULONG i; PAGED_CODE(); // // Setup the initial buffer // buffer = (PPNP_DWORD_ADDRESS_DESCRIPTOR) Buffer; // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1 ); ASSERT( aList->PartialResourceList.Count ); // // Determine which type of descriptor we are looking for // switch (buffer->RFlag) { case PNP_ADDRESS_MEMORY_TYPE: type = CmResourceTypeMemory; break; case PNP_ADDRESS_IO_TYPE: type = CmResourceTypePort; break; case PNP_ADDRESS_BUS_NUMBER_TYPE: type = CmResourceTypeBusNumber; break; default: return STATUS_UNSUCCESSFUL; } // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != type) { // // No // continue; } switch (desc->Type) { case PNP_ADDRESS_MEMORY_TYPE: // // Set the flags // buffer->TFlag = 0; if (desc->Flags & CM_RESOURCE_MEMORY_READ_WRITE) { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_WRITE; } else { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_ONLY; } if (desc->Flags & CM_RESOURCE_MEMORY_CACHEABLE) { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_CACHEABLE; } else if (desc->Flags & CM_RESOURCE_MEMORY_COMBINEDWRITE) { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_WRITE_COMBINE; } else if (desc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_PREFETCHABLE; } else { buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_NONCACHEABLE; } // // Set the rest of the information // buffer->MinimumAddress = (ULONG) desc->u.Memory.Start.LowPart; buffer->MaximumAddress = buffer->MinimumAddress + (ULONG) (desc->u.Memory.Length - 1); buffer->AddressLength = desc->u.Memory.Length; break; case PNP_ADDRESS_IO_TYPE: // // We must extract the flags here from the // devicePrivate resource // // // Set the rest of the information // buffer->MinimumAddress = (ULONG) desc->u.Port.Start.LowPart; buffer->MaximumAddress = buffer->MinimumAddress + (ULONG) (desc->u.Port.Length - 1); buffer->AddressLength = desc->u.Port.Length; break; case PNP_ADDRESS_BUS_NUMBER_TYPE: buffer->MinimumAddress = (ULONG) desc->u.BusNumber.Start; buffer->MaximumAddress = buffer->MinimumAddress + (ULONG) (desc->u.BusNumber.Length - 1); buffer->AddressLength = desc->u.BusNumber.Length; break; } // switch // // Handling for the GFlags goes here if we ever decide to support it // // // Done with descriptor and match // desc->Type = CmResourceTypeNull; break; } // for // // Done // return STATUS_SUCCESS; } NTSTATUS PnpiCmResourceToBiosDma( IN PUCHAR Buffer, IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine stores all of the DMAs in the resource list into the Bios resource list Arguments: Buffer - Pointer to the Bios resource List List - Pointer to the CM resource List Return: NTSTATUS --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PPNP_DMA_DESCRIPTOR buffer; ULONG i; PAGED_CODE(); // // Setup the initial buffer // buffer = (PPNP_DMA_DESCRIPTOR) Buffer; ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 2); // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1); ASSERT( aList->PartialResourceList.Count ); // // We can have a descriptor with no DMA channels // buffer->ChannelMask = 0; // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != CmResourceTypeDma) { // // No // continue; } // // Here we *have* a match... // buffer->ChannelMask = (1 << desc->u.Dma.Channel); // // Set the correct flags // buffer->Flags = 0; if (desc->Flags & CM_RESOURCE_DMA_8) { buffer->Flags |= PNP_DMA_SIZE_8; } else if (desc->Flags & CM_RESOURCE_DMA_8_AND_16) { buffer->Flags |= PNP_DMA_SIZE_8_AND_16; } else if (desc->Flags & CM_RESOURCE_DMA_16) { buffer->Flags |= PNP_DMA_SIZE_16; } else if (desc->Flags & CM_RESOURCE_DMA_32) { buffer->Flags |= PNP_DMA_SIZE_RESERVED; } if (desc->Flags & CM_RESOURCE_DMA_BUS_MASTER) { buffer->Flags |= PNP_DMA_BUS_MASTER; } if (desc->Flags & CM_RESOURCE_DMA_TYPE_A) { buffer->Flags |= PNP_DMA_TYPE_A; } else if (desc->Flags & CM_RESOURCE_DMA_TYPE_B) { buffer->Flags |= PNP_DMA_TYPE_B; } else if (desc->Flags & CM_RESOURCE_DMA_TYPE_F) { buffer->Flags |= PNP_DMA_TYPE_F; } // // Done with descriptor and match // desc->Type = CmResourceTypeNull; break; } // // Done // return STATUS_SUCCESS; } NTSTATUS PnpiCmResourceToBiosExtendedIrq( IN PUCHAR Buffer, IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine stores all of the Irqs in the resource list into the Bios resource list Arguments: Buffer - Pointer to the Bios resource List List - Pointer to the CM resource List Return Value: NTSTATUS --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PPNP_EXTENDED_IRQ_DESCRIPTOR buffer; ULONG i; ULONG matches = 0; PAGED_CODE(); // // Setup the initial buffer // buffer = (PPNP_EXTENDED_IRQ_DESCRIPTOR) Buffer; ASSERT( buffer->TableSize == 1); ASSERT( buffer->Length >= 6); // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1); ASSERT( aList->PartialResourceList.Count ); // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != CmResourceTypeInterrupt) { // // No // continue; } // // Here we *have* a match... // buffer->Table[0] = (ULONG) desc->u.Interrupt.Level; // // Set the Flags // buffer->Flags = 0; if ( (desc->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ) { buffer->Flags |= $EDG | $HGH; } else { buffer->Flags |= $LVL | $LOW; } if (desc->ShareDisposition == CmResourceShareShared) { buffer->Flags |= PNP_EXTENDED_IRQ_SHARED; } // // We need to use DevicePrivate information to store this // bit. For now, assume that it is set to true // buffer->Flags |= PNP_EXTENDED_IRQ_RESOURCE_CONSUMER_ONLY; // // Done with the record // desc->Type = CmResourceTypeNull; matches++; break; } // // Done with matches // return (matches == 0 ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS ); } NTSTATUS PnpiCmResourceToBiosIoFixedPort( IN PUCHAR Buffer, IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine stores all of the IoPort in the resource list into the Bios resource list Arguments: Buffer - Pointer to the Bios resource List List - Pointer to the CM resource List Return: NTSTATUS --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PPNP_FIXED_PORT_DESCRIPTOR buffer; ULONG i; PAGED_CODE(); // // Setup the initial buffer // buffer = (PPNP_FIXED_PORT_DESCRIPTOR) Buffer; ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 3); // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1); ASSERT( aList->PartialResourceList.Count ); // // Our fixed port can be nothing // buffer->MinimumAddress = buffer->Length = 0; // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != CmResourceTypePort) { // // No // continue; } // // This port type is always set to a 10 bit decode // if ( !(desc->Flags & CM_RESOURCE_PORT_10_BIT_DECODE) ) { // // No // continue; } // // Here we *have* a match... // buffer->MinimumAddress = (USHORT) desc->u.Port.Start.LowPart; buffer->Length = (UCHAR) desc->u.Port.Length; // // Done with descriptor and match // desc->Type = CmResourceTypeNull; break; } // // Done // return STATUS_SUCCESS; } NTSTATUS PnpiCmResourceToBiosIoPort( IN PUCHAR Buffer, IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine stores all of the IoPort in the resource list into the Bios resource list Arguments: Buffer - Pointer to the Bios resource List List - Pointer to the CM resource List Return: NTSTATUS --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PPNP_PORT_DESCRIPTOR buffer; ULONG i; PAGED_CODE(); // // Setup the initial buffer // buffer = (PPNP_PORT_DESCRIPTOR) Buffer; ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 7); // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1); ASSERT( aList->PartialResourceList.Count ); // // We can use no ports // buffer->Information = 0; buffer->MinimumAddress = 0; buffer->MaximumAddress = 0; buffer->Alignment = 0; buffer->Length = 0; // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != CmResourceTypePort) { // // No // continue; } // // Here we *have* a match... // buffer->MinimumAddress = (USHORT) desc->u.Port.Start.LowPart; buffer->MaximumAddress = buffer->MinimumAddress; buffer->Alignment = 1; buffer->Length = (UCHAR) desc->u.Port.Length; // // Set the flags // buffer->Information = 0; if (desc->Flags & CM_RESOURCE_PORT_10_BIT_DECODE) { buffer->Information |= PNP_PORT_10_BIT_DECODE; } if (desc->Flags & CM_RESOURCE_PORT_16_BIT_DECODE) { buffer->Information |= PNP_PORT_16_BIT_DECODE; } // // Done with descriptor and match // desc->Type = CmResourceTypeNull; break; } // // Done with matches // return STATUS_SUCCESS; } NTSTATUS PnpiCmResourceToBiosIrq( IN PUCHAR Buffer, IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine stores all of the Irqs in the resource list into the Bios resource list Arguments: Buffer - Pointer to the Bios resource List List - Pointer to the CM resource List Return Value: NTSTATUS --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PPNP_IRQ_DESCRIPTOR buffer; ULONG i; PAGED_CODE(); // // Setup the initial buffer // buffer = (PPNP_IRQ_DESCRIPTOR) Buffer; ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) >= 2); // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1); ASSERT( aList->PartialResourceList.Count ); // // We can use no interrupts // buffer->IrqMask = 0; // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != CmResourceTypeInterrupt) { // // No // continue; } // // Okay, we have a possible match... // if (desc->u.Interrupt.Level >= sizeof(USHORT) * 8) { // // Interrupts > 15 are Extended Irqs // continue; } // // Here we *have* a match... // buffer->IrqMask = ( 1 << desc->u.Interrupt.Level ); if ( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 3) { // // Wipe out the previous flags // buffer->Information = 0; if ( (desc->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ) { buffer->Information |= PNP_IRQ_LATCHED; } else { buffer->Information |= PNP_IRQ_LEVEL; } if (desc->ShareDisposition == CmResourceShareShared) { buffer->Information |= PNP_IRQ_SHARED; } } // // Done with descriptor and match // desc->Type = CmResourceTypeNull; break; } // // Done // return STATUS_SUCCESS; } NTSTATUS PnpiCmResourceToBiosMemory( IN PUCHAR Buffer, IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine stores all of the Memory elements in the resource list into the Bios resource list Arguments: Buffer - Pointer to the Bios resource List List - Pointer to the CM resource List Return: NTSTATUS --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PPNP_MEMORY_DESCRIPTOR buffer; ULONG i; PAGED_CODE(); // // Setup the initial buffer // buffer = (PPNP_MEMORY_DESCRIPTOR) Buffer; ASSERT( buffer->Length == 9); // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1); ASSERT( aList->PartialResourceList.Count ); // // We can use no memory // buffer->Information = 0; buffer->MinimumAddress = 0; buffer->MaximumAddress = 0; buffer->Alignment = 0; buffer->MemorySize = 0; // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != CmResourceTypeMemory) { // // No // continue; } // // Is this a 24 bit memory descriptor? // if ( !(desc->Flags & CM_RESOURCE_MEMORY_24)) { // // No // continue; } // // Here we *have* a match... // buffer->MinimumAddress = buffer->MaximumAddress = (USHORT) (desc->u.Memory.Start.LowPart >> 8); buffer->MemorySize = (USHORT) (desc->u.Memory.Length >> 8); if (desc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) { buffer->Information |= PNP_MEMORY_READ_ONLY; } else { buffer->Information |= PNP_MEMORY_READ_WRITE; } // // Done with descriptor and match // desc->Type = CmResourceTypeNull; break; } // // Done // return STATUS_SUCCESS; } NTSTATUS PnpiCmResourceToBiosMemory32( IN PUCHAR Buffer, IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine stores all of the Memory elements in the resource list into the Bios resource list Arguments: Buffer - Pointer to the Bios resource List List - Pointer to the CM resource List Return: NTSTATUS --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PPNP_MEMORY32_DESCRIPTOR buffer; ULONG i; PAGED_CODE(); // // Setup the initial buffer // buffer = (PPNP_MEMORY32_DESCRIPTOR) Buffer; ASSERT( buffer->Length == 17); // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1); ASSERT( aList->PartialResourceList.Count ); // // We can use no memory // buffer->Information = 0; buffer->MinimumAddress = 0; buffer->MaximumAddress = 0; buffer->Alignment = 0; buffer->MemorySize = 0; // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != CmResourceTypeMemory) { // // No // continue; } // // Here we *have* a match... // buffer->MemorySize = desc->u.Memory.Length; buffer->MinimumAddress = buffer->MaximumAddress = desc->u.Memory.Start.LowPart; if (desc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) { buffer->Information |= PNP_MEMORY_READ_ONLY; } else { buffer->Information |= PNP_MEMORY_READ_WRITE; } // // Done with descriptor and match // desc->Type = CmResourceTypeNull; break; } // // Done with matches // return STATUS_SUCCESS; } NTSTATUS PnpiCmResourceToBiosMemory32Fixed( IN PUCHAR Buffer, IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine stores all of the Memory elements in the resource list into the Bios resource list Arguments: Buffer - Pointer to the Bios resource List List - Pointer to the CM resource List Return: NTSTATUS --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PPNP_FIXED_MEMORY32_DESCRIPTOR buffer; ULONG i; PAGED_CODE(); // // Setup the initial buffer // buffer = (PPNP_FIXED_MEMORY32_DESCRIPTOR) Buffer; ASSERT( buffer->Length == 9); // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1); ASSERT( aList->PartialResourceList.Count ); // // We can use no memory // buffer->Information = 0; buffer->BaseAddress = 0; buffer->MemorySize = 0; // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != CmResourceTypeMemory) { // // No // continue; } // // Here we *have* a match... // buffer->BaseAddress = desc->u.Memory.Start.LowPart; buffer->MemorySize = desc->u.Memory.Length >> 8; if (desc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) { buffer->Information |= PNP_MEMORY_READ_ONLY; } else { buffer->Information |= PNP_MEMORY_READ_WRITE; } // // Done with descriptor and match // desc->Type = CmResourceTypeNull; break; } // // Done // return STATUS_SUCCESS; } BOOLEAN PnpiCmResourceValidEmptyList( IN PCM_RESOURCE_LIST List ) /*++ Routine Description: This routine takes a CM_RESOURCE_LIST and makes sure that no unallocated elements remain... Arguments: List - List to check Return Value: TRUE - Empty FALSE - Nonempty --*/ { PCM_FULL_RESOURCE_DESCRIPTOR aList; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; ULONG i; PAGED_CODE(); // // We can only have one list... // aList = &(List->List[0]); ASSERT( List->Count == 1); ASSERT( aList->PartialResourceList.Count ); // // Loop for each of the partial resource descriptors // for (i = 0; i < aList->PartialResourceList.Count; i++) { // // Current descriptor // desc = &(aList->PartialResourceList.PartialDescriptors[i]); // // Is this an interesting descriptor? // if (desc->Type != CmResourceTypeNull) { // // No // continue; } // // This element wasn't consumed... // break; } // // Done // return ( i == aList->PartialResourceList.Count ? TRUE : FALSE ); } NTSTATUS PnpCmResourcesToBiosResources( IN PCM_RESOURCE_LIST List, IN PUCHAR Data ) /*++ Routine Description: This routine takes a CM_RESOURCE_LIST and a _CRS buffer. The routine sets the resources in the _CRS buffer to equal to those reported in the CM_RESOURCE_LIST. That is: the buffer is used as a template for the new resources that are in the system. Arguments: List - Pointer to the CM_RESOURCE_LIST that we wish to assign Data - Where we wish to store the data, and the template for it Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PUCHAR buffer; UCHAR tagName; USHORT increment; PAGED_CODE(); ASSERT( Data != NULL ); // // Setup initial variables. // buffer = Data; tagName = *buffer; // // The algorithm we use is that we examine each tag in the buffer, and try to // match it with an entry in the resource list. So we take the convertion routine // for the previous problem and turn it upside down. // while (1) { // // Determine the size of the PNP resource descriptor // if ( !(tagName & LARGE_RESOURCE_TAG) ) { // // Small Tag // increment = (USHORT) (tagName & SMALL_TAG_SIZE_MASK) + 1; tagName &= SMALL_TAG_MASK; ACPIPrint( ( ACPI_PRINT_RESOURCES_2, "PnpCmResourcesToBiosResources: small tag = %#02lx increment = %#02lx\n", tagName, increment ) ); } else { // // Large Tag // increment = ( *(USHORT UNALIGNED *)(buffer+1) ) + 3; ACPIPrint( ( ACPI_PRINT_RESOURCES_2, "PnpCmResourcesToBiosResources: large tag = %#02lx increment = %#02lx\n", tagName, increment ) ); } // // We are done if the current tag is the end tag // if (tagName == TAG_END) { ACPIPrint( ( ACPI_PRINT_RESOURCES_2, "PnpCmResourcesToBiosResources: TAG_END\n" ) ); break; } switch(tagName) { case TAG_IRQ: status = PnpiCmResourceToBiosIrq( buffer, List ); break; case TAG_EXTENDED_IRQ: status = PnpiCmResourceToBiosExtendedIrq( buffer, List ); break; case TAG_DMA: status = PnpiCmResourceToBiosDma( buffer, List ); break; case TAG_START_DEPEND: ASSERT( tagName != TAG_START_DEPEND ); break; case TAG_END_DEPEND: ASSERT( tagName != TAG_END_DEPEND ); break; case TAG_IO: status = PnpiCmResourceToBiosIoPort( buffer, List ); break; case TAG_IO_FIXED: status = PnpiCmResourceToBiosIoFixedPort( buffer, List ); break; case TAG_MEMORY: status = PnpiCmResourceToBiosMemory( buffer, List ); break; case TAG_MEMORY32: status = PnpiCmResourceToBiosMemory32( buffer, List ); break; case TAG_MEMORY32_FIXED: status = PnpiCmResourceToBiosMemory32Fixed( buffer, List ); break; case TAG_WORD_ADDRESS: status = PnpiCmResourceToBiosAddress( buffer, List ); break; case TAG_DOUBLE_ADDRESS: status = PnpiCmResourceToBiosAddressDouble( buffer, List ); break; case TAG_VENDOR: // // Ignore this tag // break; default: { // // Unknown tag. Skip it // ACPIPrint( ( ACPI_PRINT_WARNING, "PnpBiosResourceToNtResources: TAG_UNKNOWN [tagName = %#02lx]\n", tagName ) ); break; } } // switch // // Did we fail? // if (!NT_SUCCESS(status)) { break; } // // Move to the next descriptor // buffer += increment; tagName = *buffer; } if (!( NT_SUCCESS(status) )) { return status; } // // Check to see if we have consumed all of the appropriate resources... // if (PnpiCmResourceValidEmptyList( List ) ) { // // We failed to empty the list... // return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }