/*++ Copyright (c) 1992 Microsoft Corporation Module Name: arcdtect.c Abstract: Provides HAL and SCSI detection for ARC-compliant machines. Author: John Vert (jvert) 21-Oct-1993 Revision History: --*/ #include "setupldr.h" #include // // Stuff used for detecting video // #define MAX_VIDEO_ADAPTERS 5 ULONG VideoAdapterCount; PCONFIGURATION_COMPONENT_DATA VideoAdapter[MAX_VIDEO_ADAPTERS]; VOID DecideVideoAdapter( VOID ); BOOLEAN FoundUnknownScsi; // // private function prototypes // PCHAR SlpSearchSection( IN PCHAR SectionName, IN PCHAR TargetName ); BOOLEAN EnumerateSCSIAdapters( IN PCONFIGURATION_COMPONENT_DATA ConfigData ); BOOLEAN EnumerateVideoAdapters( IN PCONFIGURATION_COMPONENT_DATA ConfigData ); PCHAR SlDetectHal( IN PSETUP_LOADER_BLOCK SetupBlock ) /*++ Routine Description: Determines the canonical short machine name for the HAL to be loaded for this machine. It does this by enumerating the [Map.Computer] section of the INF file and comparing the strings there with the computer description in the ARC tree. [Map.Computer] msjazz_up = *Jazz desksta1_up = "DESKTECH-ARCStation I" pica61_up = "PICA-61" duo_mp = *Duo [Map.Computer] DECjensen = "DEC-20Jensen" DECjensen = "DEC-10Jensen" Arguments: SetupBlock - Supplies a pointer to the Setup loader block. Return Value: PCHAR - pointer to canonical shortname for the machine. NULL - the type of machine could not be determined. --*/ { PCONFIGURATION_COMPONENT_DATA Node; PCHAR MachineName; // // Find the system description node // Node = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot, SystemClass, ArcSystem, NULL); if (Node==NULL) { SlError(0); return(NULL); } MachineName = Node->ComponentEntry.Identifier; return(MachineName ? SlpSearchSection("Map.Computer", MachineName) : NULL); } VOID SlDetectScsi( IN PSETUP_LOADER_BLOCK SetupBlock ) /*++ Routine Description: Detects SCSI adapters on an ARC machine by walking the ARC firmware tree. Fills in the appropriate entries in the setuploaderblock Arguments: SetupBlock - Supplies a pointer to the setup loader block. Return Value: None. --*/ { FoundUnknownScsi = FALSE; BlSearchConfigTree(BlLoaderBlock->ConfigurationRoot, AdapterClass, ScsiAdapter, (ULONG)-1, EnumerateSCSIAdapters); if (FoundUnknownScsi) { // // We found at least one scsi device we didn't recognize, // so force the OEM selection menu. // PromptOemScsi=TRUE; } SetupBlock->ScalarValues.LoadedScsi = 1; } BOOLEAN EnumerateSCSIAdapters( IN PCONFIGURATION_COMPONENT_DATA ConfigData ) /*++ Routine Description: Callback function for enumerating SCSI adapters in the ARC tree. Adds the SCSI adapter that was found to the list of detected SCSI devices. Arguments: ConfigData - Supplies a pointer to the ARC node of the SCSI adapter. Return Value: TRUE - continue searching FALSE - some error, abort the search --*/ { PDETECTED_DEVICE ScsiDevice; PCHAR AdapterName; ULONG Ordinal; PCHAR ScsiFileName; PCHAR ScsiDescription; SCSI_INSERT_STATUS sis; AdapterName = SlpSearchSection("Map.SCSI",ConfigData->ComponentEntry.Identifier); if (AdapterName==NULL) { // // We found an adapter in the ARC tree, but it is not one of the ones // specified in our INF file, so trigger the prompt for an OEM driver // disk. // FoundUnknownScsi = TRUE; return(TRUE); } // // Find this adapter's ordinal within the Scsi.Load section of txtsetup.sif // Ordinal = SlGetSectionKeyOrdinal(InfFile, "Scsi.Load", AdapterName); if(Ordinal == (ULONG)-1) { FoundUnknownScsi = TRUE; return(TRUE); } // // Find the driver filename // ScsiFileName = SlGetSectionKeyIndex(InfFile, "Scsi.Load", AdapterName, SIF_FILENAME_INDEX); if(!ScsiFileName) { FoundUnknownScsi = TRUE; return(TRUE); } // // Create a new detected device entry. // if((sis = SlInsertScsiDevice(Ordinal, &ScsiDevice)) == ScsiInsertError) { SlFriendlyError(ENOMEM, "SCSI detection", 0, NULL); return(FALSE); } if(sis == ScsiInsertExisting) { #if DBG // // Sanity check to make sure we're talking about the same driver // if(_strcmpi(ScsiDevice->BaseDllName, ScsiFileName)) { SlError(400); return FALSE; } #endif } else { // // Find the driver description // ScsiDescription = SlGetIniValue(InfFile, "SCSI", AdapterName, AdapterName); ScsiDevice->IdString = AdapterName; ScsiDevice->Description = ScsiDescription; ScsiDevice->ThirdPartyOptionSelected = FALSE; ScsiDevice->FileTypeBits = 0; ScsiDevice->Files = NULL; ScsiDevice->BaseDllName = ScsiFileName; } return(TRUE); } VOID SlDetectVideo( IN PSETUP_LOADER_BLOCK SetupBlock ) /*++ Routine Description: Detects video adapters on an ARC machine by walking the ARC firmware tree. Fills in the appropriate entries in the setuploaderblock Arguments: SetupBlock - Supplies a pointer to the setup loader block. Return Value: None. --*/ { // // On arc machines, there is no default video type. // SetupBlock->VideoDevice.Next = NULL; SetupBlock->VideoDevice.IdString = NULL; SetupBlock->VideoDevice.ThirdPartyOptionSelected = FALSE; SetupBlock->VideoDevice.FileTypeBits = 0; SetupBlock->VideoDevice.Files = NULL; SetupBlock->VideoDevice.BaseDllName = NULL; SetupBlock->Monitor = NULL; SetupBlock->MonitorId = NULL; BlSearchConfigTree(BlLoaderBlock->ConfigurationRoot, ControllerClass, DisplayController, (ULONG)-1, EnumerateVideoAdapters); DecideVideoAdapter(); } BOOLEAN EnumerateVideoAdapters( IN PCONFIGURATION_COMPONENT_DATA ConfigData ) /*++ Routine Description: Callback function for enumerating video adapters in the ARC tree. Adds the video adapter that was found to the setup block. Arguments: ConfigData - Supplies a pointer to the ARC node of the display adapter. Return Value: TRUE - continue searching FALSE - some error, abort the search --*/ { // // Just remember this guy for later. // if(VideoAdapterCount < MAX_VIDEO_ADAPTERS) { VideoAdapter[VideoAdapterCount++] = ConfigData; } return(TRUE); } VOID DecideVideoAdapter( VOID ) { IN PCONFIGURATION_COMPONENT_DATA ConfigData; PCHAR AdapterName,MonitorId; PCONFIGURATION_COMPONENT_DATA MonitorData; PMONITOR_CONFIGURATION_DATA Monitor; CHAR ArcPath[256]; CHAR ConsoleOut[256]; PCHAR p,q; ULONG u; if(VideoAdapterCount) { // // The first thing we want to do is to see whether any of the // adapters we found match the value of the CONSOLEOUT nvram var. // If so then use that node for detection. Before comparing we have to // change all instances of () to (0) in the value of CONSOLEOUT. // ConfigData = NULL; if(p = ArcGetEnvironmentVariable("CONSOLEOUT")) { strncpy(ArcPath,p,sizeof(ArcPath)-1); ArcPath[sizeof(ArcPath)-1] = 0; ConsoleOut[0] = 0; for(p=ArcPath; q=strstr(p,"()"); p=q+2) { *q = 0; strcat(ConsoleOut,p); strcat(ConsoleOut,"(0)"); } strcat(ConsoleOut,p); // // Finally, we need to truncate the consoleout variable after // the video adapter, if any. // _strlwr(ConsoleOut); if(p = strstr(ConsoleOut,")video(")) { *(p+sizeof(")video(")+1) = 0; } for(u=0; uComponentEntry.Identifier); if (AdapterName==NULL) { // // We found a display adapter in the ARC tree, but it is not one of the ones // specified in our INF file, so trigger the prompt for an OEM driver // disk. // PromptOemVideo = TRUE; return; } BlLoaderBlock->SetupLoaderBlock->VideoDevice.IdString = AdapterName; BlLoaderBlock->SetupLoaderBlock->VideoDevice.Description = NULL; BlLoaderBlock->SetupLoaderBlock->VideoDevice.ThirdPartyOptionSelected = FALSE; BlLoaderBlock->SetupLoaderBlock->VideoDevice.FileTypeBits = 0; BlLoaderBlock->SetupLoaderBlock->VideoDevice.Files = NULL; BlLoaderBlock->SetupLoaderBlock->VideoDevice.BaseDllName = NULL; // // If there is a monitor peripheral associated with this device, // capture its configuration data. Otherwise, let Setup assume an // appropriate default. // MonitorData = ConfigData->Child; if (MonitorData==NULL) { BlLoaderBlock->SetupLoaderBlock->Monitor = NULL; BlLoaderBlock->SetupLoaderBlock->MonitorId = NULL; } else { Monitor = BlAllocateHeap(MonitorData->ComponentEntry.ConfigurationDataLength); if (Monitor==NULL) { SlFriendlyError(ENOMEM, "video detection", 0, NULL); return; } MonitorId = BlAllocateHeap(MonitorData->ComponentEntry.IdentifierLength+1); if (MonitorId==NULL) { SlFriendlyError(ENOMEM, "video detection", 0, NULL); return; } strncpy(MonitorId, MonitorData->ComponentEntry.Identifier, MonitorData->ComponentEntry.IdentifierLength); MonitorId[MonitorData->ComponentEntry.IdentifierLength] = 0; RtlCopyMemory((PVOID)Monitor, MonitorData->ConfigurationData, MonitorData->ComponentEntry.ConfigurationDataLength); BlLoaderBlock->SetupLoaderBlock->Monitor = Monitor; BlLoaderBlock->SetupLoaderBlock->MonitorId = MonitorId; } } } PCHAR SlpSearchSection( IN PCHAR SectionName, IN PCHAR TargetName ) /*++ Routine Description: Searches a section in the INF file to match a name from the ARC identifier with the canonical shortname. If a string starts with *, then use strstr to find it in the node's id string, else use strcmpi. [Map.Computer] msjazz_up = *Jazz desksta1_up = "DESKTECH-ARCStation I" pica61_up = "PICA-61" duo_mp = *Duo [Map.Computer] DECjensen = "DEC-20Jensen" DECjensen = "DEC-10Jensen" Arguments: SectionName - Supplies the name of the section ("Map.Computer") TargetName - Supplies the ARC string to be matched ("DEC-20Jensen") Return Value: NULL - No match was found. PCHAR - Pointer to the canonical shortname of the device. --*/ { ULONG i; PCHAR SearchName; // // Enumerate the entries in the section. If the 0 value // begins with a *, then see if the system name contains the string that // follows. Otherwise, do a case-insensitive compare on the name. // for (i=0;;i++) { SearchName = SlGetSectionLineIndex(InfFile, SectionName, i, 0); if (SearchName==NULL) { // // we have enumerated the entire section without finding a match, // return failure. // return(NULL); } if (SearchName[0]=='*') { if (strstr(TargetName,SearchName+1) != 0) { // // we have a match // break; } } else { if (_stricmp(TargetName, SearchName) == 0) { // // we have a match // break; } } } // // i is the index into the section of the short machine name // return(SlGetKeyName(InfFile, SectionName, i)); }