ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

id.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS PCI Bus Driver
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            drivers/bus/pci/pci/id.c
00005  * PURPOSE:         PCI Device Identification
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include <pci.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 #include "stdio.h"
00015 
00016 /* GLOBALS ********************************************************************/
00017 
00018 /* FUNCTIONS ******************************************************************/
00019 
00020 PWCHAR
00021 NTAPI
00022 PciGetDescriptionMessage(IN ULONG Identifier,
00023                          OUT PULONG Length)
00024 {
00025     PMESSAGE_RESOURCE_ENTRY Entry;
00026     ULONG TextLength;
00027     PWCHAR Description, Buffer;
00028     ANSI_STRING MessageString;
00029     UNICODE_STRING UnicodeString;
00030     NTSTATUS Status;
00031 
00032     /* Find the message identifier in the message table */
00033     MessageString.Buffer = NULL;
00034     Status = RtlFindMessage(PciDriverObject->DriverStart,
00035                             11, // RT_MESSAGETABLE
00036                             LANG_NEUTRAL,
00037                             Identifier,
00038                             &Entry);
00039     if (!NT_SUCCESS(Status)) return NULL;
00040 
00041     /* Check if the resource data is Unicode or ANSI */
00042     if (Entry->Flags & MESSAGE_RESOURCE_UNICODE)
00043     {
00044         /* Subtract one space for the end-of-message terminator */
00045         TextLength = Entry->Length -
00046                      FIELD_OFFSET(MESSAGE_RESOURCE_ENTRY, Text) -
00047                      sizeof(WCHAR);
00048 
00049         /* Grab the text */
00050         Description = (PWCHAR)Entry->Text;
00051 
00052         /* Validate valid message length, ending with a newline character */
00053         ASSERT(TextLength > 1);
00054         ASSERT(Description[TextLength / sizeof(WCHAR)] == L'\n');
00055 
00056         /* Allocate the buffer to hold the message string */
00057         Buffer = ExAllocatePoolWithTag(PagedPool, TextLength, 'BicP');
00058         if (!Buffer) return NULL;
00059 
00060         /* Copy the message, minus the newline character, and terminate it */
00061         RtlCopyMemory(Buffer, Entry->Text, TextLength - 1);
00062         Buffer[TextLength / sizeof(WCHAR)] = UNICODE_NULL;
00063 
00064         /* Return the length to the caller, minus the terminating NULL */
00065         if (Length) *Length = TextLength - 1;
00066     }
00067     else
00068     {
00069         /* Initialize the entry as a string */
00070         RtlInitAnsiString(&MessageString, (PCHAR)Entry->Text);
00071 
00072         /* Remove the newline character */
00073         MessageString.Length -= sizeof(CHAR);
00074 
00075         /* Convert it to Unicode */
00076         RtlAnsiStringToUnicodeString(&UnicodeString, &MessageString, TRUE);
00077         Buffer = UnicodeString.Buffer;
00078 
00079         /* Return the length to the caller */
00080         if (Length) *Length = UnicodeString.Length;
00081     }
00082 
00083     /* Return the message buffer to the caller */
00084     return Buffer;
00085 }
00086 
00087 PWCHAR
00088 NTAPI
00089 PciGetDeviceDescriptionMessage(IN UCHAR BaseClass,
00090                                IN UCHAR SubClass)
00091 {
00092     PWCHAR Message;
00093     ULONG Identifier;
00094 
00095     /* The message identifier in the table is encoded based on the PCI class */
00096     Identifier = (BaseClass << 8) | SubClass;
00097 
00098     /* Go grab the description message for this device */
00099     Message = PciGetDescriptionMessage(Identifier, NULL);
00100     if (!Message)
00101     {
00102         /* It wasn't found, allocate a buffer for a generic description */
00103         Message = ExAllocatePoolWithTag(PagedPool, sizeof(L"PCI Device"), 'bicP');
00104         if (Message) RtlCopyMemory(Message, L"PCI Device", sizeof(L"PCI Device"));
00105     }
00106 
00107     /* Return the description message */
00108     return Message;
00109 }
00110 
00111 VOID
00112 NTAPI
00113 PciInitIdBuffer(IN PPCI_ID_BUFFER IdBuffer)
00114 {
00115     /* Initialize the sizes to zero and the pointer to the start of the buffer */
00116     IdBuffer->TotalLength = 0;
00117     IdBuffer->Count = 0;
00118     IdBuffer->CharBuffer = IdBuffer->BufferData;
00119 }
00120 
00121 ULONG
00122 NTAPI
00123 PciIdPrintf(IN PPCI_ID_BUFFER IdBuffer,
00124             IN PCCH Format,
00125             ...)
00126 {
00127     ULONG Size, Length;
00128     PANSI_STRING AnsiString;
00129     va_list va;
00130     va_start(va, Format);
00131     ASSERT(IdBuffer->Count < MAX_ANSI_STRINGS);
00132  
00133     /* Do the actual string formatting into the character buffer */
00134     vsprintf(IdBuffer->CharBuffer, Format, va);
00135 
00136     /* Initialize the ANSI_STRING that will hold this string buffer */
00137     AnsiString = &IdBuffer->Strings[IdBuffer->Count];
00138     RtlInitAnsiString(AnsiString, IdBuffer->CharBuffer);
00139     
00140     /* Calculate the final size of the string, in Unicode */
00141     Size = RtlAnsiStringToUnicodeSize(AnsiString);
00142  
00143     /* Update hte buffer with the size,and update the character pointer */
00144     IdBuffer->StringSize[IdBuffer->Count] = Size;
00145     IdBuffer->TotalLength += Size;
00146     Length = AnsiString->Length + sizeof(ANSI_NULL);
00147     IdBuffer->CharBuffer += Length;
00148     
00149     /* Move to the next string for next time */
00150     IdBuffer->Count++;
00151     
00152     /* Return the length */
00153     return Length;
00154 }
00155 
00156 ULONG
00157 NTAPI
00158 PciIdPrintfAppend(IN PPCI_ID_BUFFER IdBuffer,
00159                   IN PCCH Format,
00160                   ...)
00161 {
00162     ULONG NextId, Size, Length, MaxLength;
00163     PANSI_STRING AnsiString;
00164     va_list va;
00165     va_start(va, Format);
00166     ASSERT(IdBuffer->Count);
00167   
00168     /* Choose the next static ANSI_STRING to use */
00169     NextId = IdBuffer->Count - 1;
00170   
00171     /* Max length is from the end of the buffer up until the current pointer */
00172     MaxLength = (PCHAR)(IdBuffer + 1) - IdBuffer->CharBuffer; 
00173     
00174     /* Do the actual append, and return the length this string took */
00175     Length = vsprintf(IdBuffer->CharBuffer - 1, Format, va);
00176     ASSERT(Length < MaxLength);
00177 
00178     /* Select the static ANSI_STRING, and update its length information */
00179     AnsiString = &IdBuffer->Strings[NextId];
00180     AnsiString->Length += Length;
00181     AnsiString->MaximumLength += Length;
00182   
00183     /* Calculate the final size of the string, in Unicode */
00184     Size = RtlAnsiStringToUnicodeSize(AnsiString);
00185   
00186     /* Update the buffer with the size, and update the character pointer */
00187     IdBuffer->StringSize[NextId] = Size;
00188     IdBuffer->TotalLength += Size;
00189     IdBuffer->CharBuffer += Length;
00190     
00191     /* Return the size */
00192     return Size;
00193 }
00194 
00195 NTSTATUS
00196 NTAPI
00197 PciQueryId(IN PPCI_PDO_EXTENSION DeviceExtension,
00198            IN BUS_QUERY_ID_TYPE QueryType,
00199            OUT PWCHAR *Buffer)
00200 {
00201     ULONG SubsysId;
00202     CHAR VendorString[22];
00203     PPCI_PDO_EXTENSION PdoExtension;
00204     PPCI_FDO_EXTENSION ParentExtension;
00205     PWCHAR StringBuffer;
00206     ULONG i, Size;
00207     NTSTATUS Status;
00208     PANSI_STRING NextString;
00209     UNICODE_STRING DestinationString;
00210     PCI_ID_BUFFER IdBuffer;
00211     PAGED_CODE();
00212   
00213     /* Assume failure */
00214     Status = STATUS_SUCCESS;
00215     *Buffer = NULL;
00216     
00217     /* Start with the genric vendor string, which is the vendor ID + device ID */
00218     sprintf(VendorString,
00219             "PCI\\VEN_%04X&DEV_%04X",
00220             DeviceExtension->VendorId,
00221             DeviceExtension->DeviceId);
00222     
00223     /* Initialize the PCI ID Buffer */
00224     PciInitIdBuffer(&IdBuffer);
00225     
00226     /* Build the subsystem ID as shown in PCI ID Strings */
00227     SubsysId = DeviceExtension->SubsystemVendorId | (DeviceExtension->SubsystemId << 16);
00228   
00229     /* Check what the caller is requesting */
00230     switch (QueryType)
00231     {
00232         case BusQueryDeviceID:
00233         
00234             /* A single ID, the vendor string + the revision ID */
00235             PciIdPrintf(&IdBuffer,
00236                         "%s&SUBSYS_%08X&REV_%02X",
00237                         VendorString,
00238                         SubsysId,
00239                         DeviceExtension->RevisionId);
00240             break;
00241         
00242         case BusQueryHardwareIDs:
00243         
00244             /* First the vendor string + the subsystem ID + the revision ID */
00245             PciIdPrintf(&IdBuffer,
00246                         "%s&SUBSYS_%08X&REV_%02X",
00247                         VendorString,
00248                         SubsysId,
00249                         DeviceExtension->RevisionId);
00250             
00251             /* Next, without the revision */
00252             PciIdPrintf(&IdBuffer,
00253                         "%s&SUBSYS_%08X",
00254                         VendorString,
00255                         SubsysId);
00256             
00257             /* Next, the vendor string + the base class + sub class + progif */
00258             PciIdPrintf(&IdBuffer,
00259                         "%s&CC_%02X%02X%02X",
00260                         VendorString,
00261                         DeviceExtension->BaseClass,
00262                         DeviceExtension->SubClass,
00263                         DeviceExtension->ProgIf);
00264 
00265             /* Next, without the progif */
00266             PciIdPrintf(&IdBuffer,
00267                         "%s&CC_%02X%02X",
00268                         VendorString,
00269                         DeviceExtension->BaseClass,
00270                         DeviceExtension->SubClass);
00271             
00272             /* And finally, a terminator */
00273             PciIdPrintf(&IdBuffer, "\0");
00274             break;
00275         
00276         case BusQueryCompatibleIDs:
00277         
00278             /* First, the vendor + revision ID only */
00279             PciIdPrintf(&IdBuffer,
00280                         "%s&REV_%02X",
00281                         VendorString,
00282                         DeviceExtension->RevisionId);
00283 
00284             /* Next, the vendor string alone */
00285             PciIdPrintf(&IdBuffer, "%s", VendorString);
00286             
00287             /* Next, the vendor ID + the base class + the sub class + progif */
00288             PciIdPrintf(&IdBuffer,
00289                          "PCI\\VEN_%04X&CC_%02X%02X%02X",
00290                          DeviceExtension->VendorId,
00291                          DeviceExtension->BaseClass,
00292                          DeviceExtension->SubClass,
00293                          DeviceExtension->ProgIf);
00294 
00295             /* Now without the progif */
00296             PciIdPrintf(&IdBuffer,
00297                         "PCI\\VEN_%04X&CC_%02X%02X",
00298                         DeviceExtension->VendorId,
00299                         DeviceExtension->BaseClass,
00300                         DeviceExtension->SubClass);
00301 
00302             /* And then just the vendor ID itself */
00303             PciIdPrintf(&IdBuffer,
00304                         "PCI\\VEN_%04X",
00305                         DeviceExtension->VendorId);
00306 
00307             /* Then the base class + subclass + progif, without any vendor */
00308             PciIdPrintf(&IdBuffer,
00309                         "PCI\\CC_%02X%02X%02X",
00310                         DeviceExtension->BaseClass,
00311                         DeviceExtension->SubClass,
00312                         DeviceExtension->ProgIf);
00313 
00314             /* Next, without the progif */
00315             PciIdPrintf(&IdBuffer,
00316                         "PCI\\CC_%02X%02X",
00317                         DeviceExtension->BaseClass,
00318                         DeviceExtension->SubClass);
00319                         
00320             /* And finally, a terminator */
00321             PciIdPrintf(&IdBuffer, "\0");
00322             break;
00323         
00324         case BusQueryInstanceID:
00325         
00326             /* Start with a terminator */
00327             PciIdPrintf(&IdBuffer, "\0");
00328         
00329             /* And then encode the device and function number */
00330             PciIdPrintfAppend(&IdBuffer,
00331                               "%02X",
00332                               (DeviceExtension->Slot.u.bits.DeviceNumber << 3) |
00333                               DeviceExtension->Slot.u.bits.FunctionNumber);
00334           
00335             /* Loop every parent until the root */
00336             ParentExtension = DeviceExtension->ParentFdoExtension;
00337             while (!PCI_IS_ROOT_FDO(ParentExtension))
00338             {
00339                 /* And encode the parent's device and function number as well */
00340                 PdoExtension = ParentExtension->PhysicalDeviceObject->DeviceExtension;
00341                 PciIdPrintfAppend(&IdBuffer,
00342                                   "%02X",
00343                                   (PdoExtension->Slot.u.bits.DeviceNumber << 3) |
00344                                   PdoExtension->Slot.u.bits.FunctionNumber);
00345             }
00346             break;
00347         
00348         default:
00349         
00350             /* Unknown query type */
00351             DPRINT1("PciQueryId expected ID type = %d\n", QueryType);
00352             return STATUS_NOT_SUPPORTED;
00353     }
00354     
00355     /* Something should've been generated if this has been reached */
00356     ASSERT(IdBuffer.Count > 0);
00357     
00358     /* Allocate the final string buffer to hold the ID */
00359     StringBuffer = ExAllocatePoolWithTag(PagedPool, IdBuffer.TotalLength, 'BicP');
00360     if (!StringBuffer) return STATUS_INSUFFICIENT_RESOURCES;
00361     
00362     /* Build the UNICODE_STRING structure for it */
00363     DPRINT1("PciQueryId(%d)\n", QueryType);
00364     DestinationString.Buffer = StringBuffer;
00365     DestinationString.MaximumLength = IdBuffer.TotalLength;
00366     
00367     /* Loop every ID in the buffer */
00368     for (i = 0; i < IdBuffer.Count; i++)
00369     {
00370         /* Select the ANSI_STRING for the ID */
00371         NextString = &IdBuffer.Strings[i];
00372         DPRINT1("    <- \"%s\"\n", NextString->Buffer);
00373         
00374         /* Convert it to a UNICODE_STRING */
00375         Status = RtlAnsiStringToUnicodeString(&DestinationString, NextString, FALSE);
00376         ASSERT(NT_SUCCESS(Status));
00377         
00378         /* Add it into the final destination buffer */
00379         Size = IdBuffer.StringSize[i];
00380         DestinationString.MaximumLength -= Size;
00381         DestinationString.Buffer += (Size / sizeof(WCHAR));
00382     }
00383 
00384     /* Return the buffer to the caller and return status (should be success) */
00385     *Buffer = StringBuffer;
00386     return Status;
00387 }
00388 
00389 NTSTATUS
00390 NTAPI
00391 PciQueryDeviceText(IN PPCI_PDO_EXTENSION PdoExtension,
00392                    IN DEVICE_TEXT_TYPE QueryType,
00393                    IN ULONG Locale,
00394                    OUT PWCHAR *Buffer)
00395 {
00396     PWCHAR MessageBuffer, LocationBuffer;
00397     ULONG Length;
00398     NTSTATUS Status;
00399     
00400     /* Check what the caller is requesting */
00401     switch (QueryType)
00402     {
00403         case DeviceTextDescription:
00404         
00405             /* Get the message from the resource section */
00406             MessageBuffer = PciGetDeviceDescriptionMessage(PdoExtension->BaseClass,
00407                                                            PdoExtension->SubClass);
00408                                                            
00409             /* Return it to the caller, and select proper status code */
00410             *Buffer = MessageBuffer;
00411             Status = MessageBuffer ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
00412             break;
00413         
00414         case DeviceTextLocationInformation:
00415         
00416             /* Get the message from the resource section */
00417             MessageBuffer = PciGetDescriptionMessage(0x10000, &Length);
00418             if (!MessageBuffer)
00419             {
00420                 /* It should be there, but fail if it wasn't found for some reason */
00421                 Status = STATUS_NOT_SUPPORTED;
00422                 break;
00423             }
00424             
00425             /* Add space for a null-terminator, and allocate the buffer */
00426             Length += 2 * sizeof(UNICODE_NULL);
00427             LocationBuffer = ExAllocatePoolWithTag(PagedPool,
00428                                                    Length * sizeof(WCHAR),
00429                                                    'BicP');
00430             *Buffer = LocationBuffer;
00431             
00432             /* Check if the allocation succeeded */
00433             if (LocationBuffer)
00434             {
00435                 /* Build the location string based on bus, function, and device */
00436                 swprintf(LocationBuffer,
00437                          MessageBuffer,
00438                          PdoExtension->ParentFdoExtension->BaseBus,
00439                          PdoExtension->Slot.u.bits.FunctionNumber,
00440                          PdoExtension->Slot.u.bits.DeviceNumber);
00441             }
00442             
00443             /* Free the original string from the resource section */
00444             ExFreePoolWithTag(MessageBuffer, 0);
00445             
00446             /* Select the correct status */
00447             Status = LocationBuffer ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
00448             break;
00449             
00450         default:
00451             
00452             /* Anything else is unsupported */
00453             Status = STATUS_NOT_SUPPORTED;
00454             break;
00455     }
00456     
00457     /* Return whether or not a device text string was indeed found */
00458     return Status;
00459 }
00460 
00461 /* EOF */

Generated on Sat May 26 2012 04:26:03 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.