Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenid.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
1.7.6.1
|