summaryrefslogtreecommitdiffstats
path: root/private/ntos/fw/mips/jxconfig.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/fw/mips/jxconfig.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/fw/mips/jxconfig.c')
-rw-r--r--private/ntos/fw/mips/jxconfig.c1956
1 files changed, 1956 insertions, 0 deletions
diff --git a/private/ntos/fw/mips/jxconfig.c b/private/ntos/fw/mips/jxconfig.c
new file mode 100644
index 000000000..409086a03
--- /dev/null
+++ b/private/ntos/fw/mips/jxconfig.c
@@ -0,0 +1,1956 @@
+#if defined(JAZZ)
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxconfig.c
+
+Abstract:
+
+ This module implements the ARC firmware Configuration Query functions as
+ described in the Advanced Risc Computing Specification (Revision 1.00),
+ section 3.3.3.4, for a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David M. Robinson (davidro) 13-June-1991
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+#include "string.h"
+#include "selftest.h"
+extern ULONG end;
+
+//
+// Define the ARC pathname mnemonics.
+//
+
+PCHAR MnemonicTable[] = {
+ "arc",
+ "cpu",
+ "fpu",
+ "pic",
+ "pdc",
+ "sic",
+ "sdc",
+ "sc",
+ "eisa",
+ "tc",
+ "scsi",
+ "dti",
+ "multi",
+ "disk",
+ "tape",
+ "cdrom",
+ "worm",
+ "serial",
+ "net",
+ "video",
+ "par",
+ "point",
+ "key",
+ "audio",
+ "other",
+ "rdisk",
+ "fdisk",
+ "tape",
+ "modem",
+ "monitor",
+ "print",
+ "pointer",
+ "keyboard",
+ "term",
+ "other"
+ };
+
+//
+// Function prototypes.
+//
+
+ARC_STATUS
+FwRestoreConfiguration (
+ VOID
+ );
+
+VOID
+FwConfigurationSetChecksum(
+ VOID
+ );
+
+ULONG
+FwZeroCompressLength (
+ IN ULONG DataLength,
+ IN PVOID ConfigurationData
+ );
+
+ULONG
+FwZeroCompress (
+ IN ULONG DataLength,
+ IN PVOID ConfigurationData,
+ OUT PVOID OutputBuffer
+ );
+
+VOID
+FwZeroDecompress (
+ IN PVOID InBuffer,
+ IN ULONG Index,
+ OUT PVOID ConfigurationData,
+ IN ULONG Length
+ );
+
+//
+// IdentifierIndex and DataIndex identify the next free locations in the
+// configuration identifier and data areas. Configuration points to the
+// allocated configuration area.
+//
+
+ULONG IdentifierIndex;
+ULONG DataIndex;
+ULONG EisaDataIndex;
+PCONFIGURATION Configuration;
+
+//
+// Boolean to keep checksum status of the NVRAM.
+//
+
+BOOLEAN NvramValid = FALSE;
+
+//
+// External data.
+//
+
+extern MONITOR_CONFIGURATION_DATA DefaultMonitor;
+
+
+VOID
+FwConfigurationInitialize (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the configuration area in memory, and the
+ configuration routine addresses.
+
+ Note: This routine is called at phase 1 initialization and
+ at this time nothing is available.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCONFIGURATION_COMPONENT Processor, Child;
+ ULONG ProcessorNumber;
+ CHAR CpuPath[10];
+
+ //
+ // Initialize the configuration routine addresses in the system
+ // parameter block.
+ //
+
+ (PARC_GET_CHILD_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetChildRoutine] =
+ FwGetChild;
+ (PARC_GET_PARENT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetParentRoutine] =
+ FwGetParent;
+ (PARC_GET_PEER_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetPeerRoutine] =
+ FwGetPeer;
+ (PARC_ADD_CHILD_ROUTINE)SYSTEM_BLOCK->FirmwareVector[AddChildRoutine] =
+ FwAddChild;
+ (PARC_DELETE_COMPONENT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[DeleteComponentRoutine] =
+ FwDeleteComponent;
+ (PARC_GET_COMPONENT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetComponentRoutine] =
+ FwGetComponent;
+ (PARC_GET_DATA_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetDataRoutine] =
+ FwGetConfigurationData;
+ (PARC_SAVE_CONFIGURATION_ROUTINE)SYSTEM_BLOCK->FirmwareVector[SaveConfigurationRoutine] =
+ FwSaveConfiguration;
+
+ //
+ // Allocate a region to store the volatile configuration database.
+ //
+
+ Configuration = (PCONFIGURATION)FwAllocatePool(sizeof(CONFIGURATION));
+
+ //
+ // Initialize other static data.
+ //
+
+ IdentifierIndex = 0;
+ DataIndex = 0;
+ EisaDataIndex = 0;
+
+ if (FwRestoreConfiguration() == ESUCCESS) {
+
+ //
+ // Delete processor components.
+ //
+
+ for (ProcessorNumber = 0; ProcessorNumber < 2 ; ProcessorNumber++ ) {
+ sprintf(CpuPath,"cpu(%1d)", ProcessorNumber);
+ Processor = FwGetComponent(CpuPath);
+ if ((Processor != NULL) && (Processor->Type == CentralProcessor)) {
+ while ((Child = FwGetChild(Processor)) != NULL) {
+ FwDeleteComponent(Child);
+ }
+ FwDeleteComponent(Processor);
+ }
+ }
+
+ //
+ // Add the first processor.
+ //
+
+ JzAddProcessor(0);
+
+#ifdef DUO
+ //
+ // Add the second processor
+ //
+
+ ExecuteOnProcessorB((PPROCESSOR_TASK_ROUTINE)JzAddProcessor,1);
+#endif
+
+ FwSaveConfiguration();
+ }
+
+ return;
+}
+
+PCONFIGURATION_COMPONENT
+FwAddChild (
+ IN PCONFIGURATION_COMPONENT Component,
+ IN PCONFIGURATION_COMPONENT NewComponent,
+ IN PVOID ConfigurationData OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds a new component entry as a child of Component, including
+ an identifier string if the IdentifierLength field of NewComponent is
+ non-zero, and configuration data if the ConfigurationDataLength field of
+ NewComponent is non-zero and the ConfigurationData parameter is present.
+ If Component is NULL, the root component is being added.
+
+Arguments:
+
+ Component - Supplies a pointer to a configuration component.
+
+ NewComponent - Supplies a pointer to a new configuration component
+ to be added as a child of Component.
+
+ ConfigurationData - Supplies an optional pointer to a configuration
+ data buffer.
+
+Return Value:
+
+ Returns a pointer to the new configuration component entry. If the
+ create operation was unsuccessful, NULL is returned.
+
+--*/
+{
+ PCONFIGURATION_PACKET Packet;
+ PCONFIGURATION_PACKET ParentPacket;
+ ULONG Index;
+ PUCHAR String;
+ PUCHAR Data;
+ BOOLEAN Eisa;
+ ULONG DataLength;
+
+ //
+ // If Component is NULL and the new Class is system, the root component is
+ // being added, otherwise find the first free component entry.
+ //
+
+ if ((Component == NULL) && (NewComponent->Class == SystemClass)) {
+
+ Packet = &Configuration->Packet[0];
+
+ //
+ // TEMPTEMP If the root component is being added, clear all of the
+ // configuration area. This is a Hack, should be replaced by
+ // a good way to do this.
+ //
+
+ RtlZeroMemory(Configuration, sizeof(CONFIGURATION));
+ IdentifierIndex = 0;
+ DataIndex = 0;
+ EisaDataIndex = 0;
+
+ } else {
+
+ //
+ // If the configuration is not valid, return NULL.
+ //
+
+ if (!NvramValid) {
+ return(NULL);
+ }
+
+ Packet = &Configuration->Packet[1];
+
+ for ( Index = 1 ; Packet->Parent != NULL ; Index++ ) {
+
+ //
+ // If no more entries, return NULL. Since Index is 0 based
+ // subtract one from NUMBER_OF_ENTRIES for end check.
+ //
+
+ if (Index >= (NUMBER_OF_ENTRIES - 1)) {
+ return NULL;
+ }
+
+ Packet++;
+ }
+ }
+
+ //
+ // Check to see if the parent component is the eisa bus.
+ //
+
+ if ((Component != NULL) && (Component->Type == EisaAdapter)) {
+ Eisa = TRUE;
+ } else {
+ Eisa = FALSE;
+ }
+
+ //
+ // If there is not enough space for the new identifier string or the
+ // configuration data, return NULL.
+ //
+
+ if (IdentifierIndex + NewComponent->IdentifierLength >= LENGTH_OF_IDENTIFIER) {
+ return(NULL);
+ }
+
+ if (Eisa) {
+ DataLength = FwZeroCompressLength(NewComponent->ConfigurationDataLength,
+ ConfigurationData);
+
+ if (EisaDataIndex + DataLength >= LENGTH_OF_EISA_DATA) {
+ return(NULL);
+ }
+ } else {
+ if (DataIndex + NewComponent->ConfigurationDataLength >= LENGTH_OF_DATA) {
+ return(NULL);
+ }
+ }
+
+ //
+ // There is space for everything. Fill in new configuration entry first.
+ //
+
+ Packet->Component.Class = NewComponent->Class;
+ Packet->Component.Type = NewComponent->Type;
+ Packet->Component.Flags = NewComponent->Flags;
+ Packet->Component.Version = NewComponent->Version;
+ Packet->Component.Revision = NewComponent->Revision;
+ Packet->Component.Key = NewComponent->Key;
+ Packet->Component.AffinityMask = 0xffffffff;
+ Packet->Component.IdentifierLength = NewComponent->IdentifierLength;
+ Packet->Component.Identifier = &Configuration->Identifier[IdentifierIndex];
+
+ //
+ // If Component is NULL, this is the root component so the parent is NULL,
+ // otherwise find the parent packet.
+ //
+
+ if (Component == NULL) {
+ ParentPacket = NULL;
+ } else {
+ ParentPacket = CONTAINING_RECORD(Component,
+ CONFIGURATION_PACKET,
+ Component);
+ }
+
+ //
+ // Only copy configuration data length if configuration data is supplied.
+ //
+
+ if (ConfigurationData != NULL) {
+ Packet->Component.ConfigurationDataLength =
+ NewComponent->ConfigurationDataLength;
+ } else {
+ Packet->Component.ConfigurationDataLength = 0;
+ }
+
+ Packet->Parent = ParentPacket;
+
+ Packet->Child = NULL;
+
+ //
+ // Add identifer string.
+ //
+
+ String = NewComponent->Identifier;
+
+ for ( Index = 0 ; Index < NewComponent->IdentifierLength ; Index++ ) {
+ Configuration->Identifier[IdentifierIndex++] = *String++;
+ }
+
+ //
+ // Make sure identifier is zero terminated, if not add one.
+ //
+
+ if (Configuration->Identifier[IdentifierIndex - 1] != 0) {
+ Configuration->Identifier[IdentifierIndex++] = 0;
+ Packet->Component.IdentifierLength += 1;
+ }
+
+ //
+ // Copy configuration data.
+ //
+
+ if (Eisa) {
+ Packet->ConfigurationData = &Configuration->EisaData[EisaDataIndex];
+ EisaDataIndex += FwZeroCompress(NewComponent->ConfigurationDataLength,
+ ConfigurationData,
+ &Configuration->EisaData[EisaDataIndex]);
+ } else {
+ Data = (PUCHAR)ConfigurationData;
+ Packet->ConfigurationData = &Configuration->Data[DataIndex];
+ for ( Index = 0 ; Index < NewComponent->ConfigurationDataLength ; Index++ ) {
+ Configuration->Data[DataIndex++] = *Data++;
+ }
+ }
+
+ //
+ // Add the new component as the first child of Component, unless this is
+ // the root component.
+ //
+
+ if (Component == NULL) {
+ Packet->Peer = NULL;
+ } else {
+ Packet->Peer = ParentPacket->Child;
+ ParentPacket->Child = Packet;
+ }
+
+ return (&Packet->Component);
+}
+
+
+ARC_STATUS
+FwDeleteComponent (
+ IN PCONFIGURATION_COMPONENT Component
+ )
+
+/*++
+
+Routine Description:
+
+ This function deletes a component entry. If the entry has one or more
+ children, an error is returned, otherwise the entry is deleted. Deleting
+ the entry will implicitly delete the identifier string and the configuration
+ data.
+
+ Note that no attempt is made to compress the entry, identifier, or the
+ configuration data areas after an entry is deleted, as doing so would
+ potentially invalidate outstanding pointers.
+
+Arguments:
+
+ Component - Supplies a pointer to a configuration component.
+
+Return Value:
+
+ Returns ESUCCESS if the entry was successfully deleted, otherwise one of
+ the following error codes is returned.
+
+ EINVAL Component is not a valid configuration component, or the
+ configuration is not valid.
+
+ EACCES Component has children, and cannot be freed until they
+ are deleted.
+
+
+--*/
+{
+ PCONFIGURATION_PACKET Packet;
+ PCONFIGURATION_PACKET SearchPacket;
+
+ if (!NvramValid || (Component == NULL)) {
+ return EINVAL;
+ }
+
+ Packet = CONTAINING_RECORD(Component,
+ CONFIGURATION_PACKET,
+ Component);
+
+ //
+ // If Component's Parent field is NULL, return EINVAL.
+ //
+
+ if (Packet->Parent == NULL) {
+ return EINVAL;
+ }
+
+ //
+ // If Component has children, return EACCES.
+ //
+
+ if (Packet->Child != NULL) {
+ return EACCES;
+ }
+
+ //
+ // Find the entry that points to Component, and point it to
+ // Component's peer. If this is Component's parent, update the child
+ // pointer, otherwise this is a peer and update the peer pointer.
+ //
+
+ SearchPacket = Packet->Parent;
+
+ if (SearchPacket->Child == Packet) {
+ SearchPacket->Child = Packet->Peer;
+ } else {
+ SearchPacket = SearchPacket->Child;
+ while (SearchPacket->Peer != Packet) {
+ SearchPacket = SearchPacket->Peer;
+ }
+ SearchPacket->Peer = Packet->Peer;
+ }
+
+ //
+ // Delete Component by zeroing the parent pointer.
+ //
+
+ Packet->Parent = NULL;
+
+ return ESUCCESS;
+}
+
+
+PCONFIGURATION_COMPONENT
+FwGetComponent (
+ IN PCHAR Pathname
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the configuration tree for the component that best
+ matches the Pathname string.
+
+Arguments:
+
+ Pathname - Supplies a string containing the pathname to search.
+
+Return Value:
+
+ Returns a pointer to the configuration component that best matches
+ pathname. The algorithm is to search for each component starting with
+ the first. When the string has been exhausted or no component matches the
+ current string section, then a pointer to the last successfully matched
+ component is returned. If the configuration information is not valid,
+ NULL is returned.
+
+--*/
+{
+ PCONFIGURATION_COMPONENT Component;
+ PCONFIGURATION_COMPONENT MatchComponent;
+ PCHAR PathString;
+ PCHAR MatchString;
+ PCHAR Token;
+ ULONG Key;
+
+ //
+ // If the configuration is not valid, return NULL.
+ //
+
+ if (!NvramValid) {
+ return(NULL);
+ }
+
+ PathString = Pathname;
+
+ //
+ // Get the the root component.
+ //
+
+ MatchComponent = FwGetChild(NULL);
+
+ //
+ // Repeat search for each new match component.
+ //
+
+ do {
+
+ //
+ // Get the first child of the current match component.
+ //
+
+ Component = FwGetChild( MatchComponent );
+
+ //
+ // Search each child of the current match component for the next match.
+ //
+
+ while ( Component != NULL ) {
+
+ //
+ // Reset Token to be the current position on the pathname.
+ //
+
+ Token = PathString;
+
+ MatchString = MnemonicTable[Component->Type];
+
+ //
+ // Compare strings.
+ //
+
+ while (*MatchString == tolower(*Token)) {
+ MatchString++;
+ Token++;
+ }
+
+ //
+ // Strings compare if the first mismatch is the terminator for
+ // each.
+ //
+
+ if ((*MatchString == 0) && (*Token == '(')) {
+
+ //
+ // Form key.
+ //
+
+ Key = 0;
+ Token++;
+ while ((*Token != ')') && (*Token != 0)) {
+ Key = (Key * 10) + *Token++ - '0';
+ }
+
+ //
+ // If the key matches the component matches, so update
+ // pointers and break.
+ //
+
+ if (Component->Key == Key) {
+ PathString = Token + 1;
+ MatchComponent = Component;
+ break;
+ }
+ }
+
+NextPeer:
+ Component = FwGetPeer( Component );
+ }
+
+ } while ((Component != NULL) && (*PathString != 0));
+
+ return MatchComponent;
+}
+
+PCONFIGURATION_COMPONENT
+FwGetChild (
+ IN PCONFIGURATION_COMPONENT Component OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ Returns a pointer to the configuration component for the first child of
+ Component. If Component is NULL, a pointer to the root configuration
+ component is returned.
+
+Arguments:
+
+ Component - Supplies an optional pointer to a configuration component.
+
+Return Value:
+
+ Returns a pointer to the configuration component for the first child of
+ Component. If Component has no children, this pointer will be NULL. If
+ Component is NULL, a pointer to the root configuration component is
+ returned. If the configuration is not valid, NULL is returned.
+
+--*/
+{
+ PCONFIGURATION_PACKET Packet;
+
+ //
+ // If the configuration is not valid, return NULL.
+ //
+
+ if (!NvramValid) {
+ return(NULL);
+ }
+
+
+ if (Component == NULL) {
+ return &Configuration->Packet[0].Component;
+ } else {
+ Packet = CONTAINING_RECORD(Component,
+ CONFIGURATION_PACKET,
+ Component);
+
+ return &((PCONFIGURATION_PACKET)(Packet->Child))->Component;
+ }
+}
+
+
+PCONFIGURATION_COMPONENT
+FwGetParent (
+ IN PCONFIGURATION_COMPONENT Component
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the parent of the named component.
+
+Arguments:
+
+ Component - Supplies a pointer to a configuration component.
+
+Return Value:
+
+ Returns a pointer to the configuration component for the parent of
+ Component. If Component has no parent NULL is returned (this is only
+ true for the root configuration component). If the configuration is
+ not valid, NULL is returned.
+
+--*/
+{
+ PCONFIGURATION_PACKET Packet;
+
+ //
+ // If the configuration is not valid, return NULL.
+ //
+
+ if (!NvramValid) {
+ return(NULL);
+ }
+
+ Packet = CONTAINING_RECORD(Component,
+ CONFIGURATION_PACKET,
+ Component);
+
+ if (Packet->Parent == NULL) {
+ return NULL;
+ } else {
+ return &((PCONFIGURATION_PACKET)(Packet->Parent))->Component;
+ }
+}
+
+
+PCONFIGURATION_COMPONENT
+FwGetPeer (
+ IN PCONFIGURATION_COMPONENT Component
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the peer of the named component.
+
+Arguments:
+
+ Component - Supplies a pointer to a configuration component.
+
+Return Value:
+
+ Returns a pointer to the configuration component for the next peer of
+ Component. If Component has no next peer, NULL is returned. If the
+ configuration is not valid, NULL is returned.
+
+--*/
+{
+ PCONFIGURATION_PACKET Packet;
+
+ //
+ // If the configuration is not valid, return NULL.
+ //
+
+ if (!NvramValid) {
+ return(NULL);
+ }
+
+ Packet = CONTAINING_RECORD(Component,
+ CONFIGURATION_PACKET,
+ Component);
+
+ if (Packet->Peer == NULL) {
+ return NULL;
+ } else {
+ return &((PCONFIGURATION_PACKET)(Packet->Peer))->Component;
+ }
+}
+
+
+ARC_STATUS
+FwGetConfigurationDataIndex
+ (
+ OUT PVOID ConfigurationData,
+ IN PCONFIGURATION_COMPONENT Component,
+ IN ULONG Index,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This functions returns the specified configuration data
+ associated with Component in the buffer supplied by
+ ConfigurationData. The max length of the data is stored
+ in the Component structure.
+
+Arguments:
+
+ ConfigurationData - Supplies a pointer to a buffer to receive the
+ configuration data.
+
+ Component - Supplies a pointer to a configuration component.
+
+ Index - Supplies an index within the configuration data.
+
+ Length - Supplies the number of bytes to read (see the
+ ConfigurationDataLength field within the Component for the max
+ value).
+
+Return Value:
+
+ If the configuration data is successfully copied into the buffer
+ provided by ConfigurationData, ESUCCESS is returned. Otherwise one of
+ the following error codes is returned.
+
+ EINVAL Component is not a valid configuration component or the
+ other arguments are invalid or the configuration is
+ not valid.
+
+--*/
+
+{
+ PCONFIGURATION_PACKET Packet;
+ ULONG DataSize;
+ PUCHAR SourceData;
+ PUCHAR DestinationData;
+
+ //
+ // If the configuration is not valid, return EINVAL.
+ //
+
+ if (!NvramValid) {
+ return(EINVAL);
+ }
+
+ DataSize = Component->ConfigurationDataLength;
+
+ //
+ // check the passing parameters
+ //
+
+ if ( DataSize == 0 || Index >= DataSize || DataSize - Index < Length ) {
+ return EINVAL;
+ }
+
+ Packet = CONTAINING_RECORD( Component, CONFIGURATION_PACKET, Component );
+
+ //
+ // If Component's Parent field is NULL, return EINVAL.
+ //
+
+ if (Packet->Parent == NULL) {
+ return EINVAL;
+ }
+
+ //
+ // If this is an eisa component, decompress the data, otherwise just copy it.
+ //
+
+ if (Packet->Parent->Component.Type == EisaAdapter) {
+ FwZeroDecompress(Packet->ConfigurationData,
+ Index,
+ ConfigurationData,
+ Length);
+
+ } else {
+ SourceData = (PUCHAR)Packet->ConfigurationData + Index;
+ DestinationData = ConfigurationData;
+
+ while ( Length-- )
+ {
+ *DestinationData++ = *SourceData++;
+ }
+ }
+
+ return ESUCCESS;
+}
+
+
+ARC_STATUS
+FwGetConfigurationData (
+ OUT PVOID ConfigurationData,
+ IN PCONFIGURATION_COMPONENT Component
+ )
+
+/*++
+
+Routine Description:
+
+ This functions returns the configuration data associated with Component
+ in the buffer supplied by ConfigurationData. The length of the data
+ is stored in the Component structure.
+
+Arguments:
+
+ ConfigurationData - Supplies a pointer to a buffer to receive the
+ configuration data.
+
+ Component - Supplies a pointer to a configuration component.
+
+Return Value:
+
+ If the configuration data is successfully copied into the buffer
+ provided by ConfigurationData, ESUCCESS is returned. Otherwise one of
+ the following error codes is returned.
+
+ EINVAL Component is not a valid configuration component, or the
+ configuration is invalid.
+
+--*/
+
+{
+ return(FwGetConfigurationDataIndex(ConfigurationData,
+ Component,
+ 0,
+ Component->ConfigurationDataLength));
+}
+
+
+
+ARC_STATUS
+FwSaveConfiguration (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine stores all of the configuration entries into NVRAM,
+ including the associated identifier strings and configuration data.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns ESUCCESS if the save completed successfully, otherwise one of the
+ following error codes is returned.
+
+ ENOSPC Not enough space in the NVRAM to save all of the data.
+
+--*/
+
+{
+ ULONG EntryIndex;
+ ULONG Index;
+ PCONFIGURATION_PACKET Packet;
+ PCONFIGURATION_COMPONENT Component;
+ PNV_CONFIGURATION NvConfiguration;
+ COMPRESSED_CONFIGURATION_PACKET CompressedPacket;
+ USHORT NvIdentifierIndex;
+ USHORT NvDataIndex;
+ USHORT NvEisaDataIndex;
+ PUCHAR CompressedChars, NvChars, Data;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+ NvIdentifierIndex = 0;
+ NvDataIndex = 0;
+ NvEisaDataIndex = 0;
+
+ //
+ // Write each volatile packet into a compressed non-volatile packet,
+ // including the identifier string and the configuration data.
+ //
+
+ for ( EntryIndex = 0 ; EntryIndex < NUMBER_OF_ENTRIES ; EntryIndex++ ) {
+
+ //
+ // Get pointers to the volatile data.
+ //
+
+ Packet = (PCONFIGURATION_PACKET)&Configuration->Packet[EntryIndex];
+ Component = &Packet->Component;
+
+ //
+ // If this is not the root entry and the parent field is NULL, zero
+ // entry and skip to next.
+ //
+
+ if ((EntryIndex != 0) && (Packet->Parent == NULL)) {
+ NvChars = (PUCHAR)&NvConfiguration->Packet[EntryIndex];
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) ;
+ Index++ ) {
+ WRITE_REGISTER_UCHAR( NvChars++, 0);
+ }
+ continue;
+ }
+
+ //
+ // Determine the parent and store as an index. Note that the index
+ // (Packet->Parent) is 1 based, to reserve the value 0 to mean no
+ // parent.
+ //
+
+ if (EntryIndex != 0) {
+ CompressedPacket.Parent =
+ (UCHAR)(Packet->Parent - &Configuration->Packet[0]) + 1;
+ } else {
+ CompressedPacket.Parent = 0;
+ }
+
+ //
+ // Fill in the rest of the fields. Version and ConfigurationDataLength will
+ // never be larger than USHORTS.
+ //
+
+ CompressedPacket.Class = (UCHAR)Component->Class;
+ CompressedPacket.Type = (UCHAR)Component->Type;
+ CompressedPacket.Version = (UCHAR)Component->Version;
+ CompressedPacket.Revision = (UCHAR)Component->Revision;
+ CompressedPacket.Key = Component->Key;
+ CompressedPacket.ConfigurationDataLength =
+ (USHORT)Component->ConfigurationDataLength;
+ CompressedPacket.ConfigurationData = 0;
+
+ //
+ // Make sure the top bit of the flag field is zero unless it's set
+ // to be eisa below.
+ //
+
+ CompressedPacket.Flags = *(PUCHAR)(&Component->Flags) & 0x7f;
+
+ //
+ // If the component has an identifier string, copy it to NVRAM,
+ // otherwise set the index to indicate no identifier.
+ //
+
+ if (Component->IdentifierLength != 0) {
+ CompressedPacket.Identifier = NvIdentifierIndex;
+ for ( Index = 0 ; Index < Component->IdentifierLength ; Index++ ) {
+ WRITE_REGISTER_UCHAR(
+ &NvConfiguration->Identifier[NvIdentifierIndex++],
+ Component->Identifier[Index]);
+ }
+ } else {
+ CompressedPacket.Identifier = NO_CONFIGURATION_IDENTIFIER;
+ }
+
+ //
+ // If the component has configuration data, copy it to NVRAM.
+ //
+
+ if (Component->ConfigurationDataLength != 0) {
+
+ //
+ // If the parent component is the eisa bus, copy until the end
+ // of the compressed data.
+ //
+
+ if (Packet->Parent->Component.Type == EisaAdapter) {
+ CompressedPacket.ConfigurationData = NvEisaDataIndex;
+ Data = (PUCHAR)Packet->ConfigurationData;
+ for ( Index = 0 ; TRUE ; Index++ ) {
+ WRITE_REGISTER_UCHAR( &NvConfiguration->EisaData[NvEisaDataIndex++],
+ *Data++);
+
+ //
+ // If we've written at least two bytes and the last two
+ // bytes were zero we're at the end.
+ //
+
+ if ((Index > 1) && (!*(Data - 1) && !*(Data - 2))) {
+ break;
+ }
+ }
+
+ //
+ // Set a flag to make it easier to determine that this is an
+ // Eisa component.
+ //
+
+ CompressedPacket.Flags |= 0x80;
+
+ } else {
+ CompressedPacket.ConfigurationData = NvDataIndex;
+ Data = (PUCHAR)Packet->ConfigurationData;
+ for ( Index = 0 ; Index < Component->ConfigurationDataLength ; Index++ ) {
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Data[NvDataIndex++],
+ *Data++);
+ }
+ }
+ }
+
+ //
+ // Write compressed packet to NVRAM.
+ //
+
+ CompressedChars = (PUCHAR)&CompressedPacket;
+ NvChars = (PUCHAR)&NvConfiguration->Packet[EntryIndex];
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) ;
+ Index++ ) {
+ WRITE_REGISTER_UCHAR( NvChars++, *CompressedChars++);
+ }
+ }
+
+ //
+ // Zero the rest of the identifier and configuration data areas.
+ //
+
+ for ( Index = NvIdentifierIndex ; Index < LENGTH_OF_IDENTIFIER ; Index++ ) {
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Identifier[Index], 0);
+ }
+
+ for ( Index = NvDataIndex ; Index < LENGTH_OF_DATA ; Index++ ) {
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Data[Index] ,0);
+ }
+
+ for ( Index = NvEisaDataIndex ; Index < LENGTH_OF_EISA_DATA ; Index++ ) {
+ WRITE_REGISTER_UCHAR( &NvConfiguration->EisaData[Index] ,0);
+ }
+
+ //
+ // Write configuration data checksum.
+ //
+
+ FwConfigurationSetChecksum();
+
+ //
+ // Restore configuration information out of NVRAM. This acts to compress
+ // the identifier and configuration data areas if any deletes have been
+ // performed.
+ //
+
+ return FwRestoreConfiguration();
+}
+
+
+ARC_STATUS
+FwRestoreConfiguration (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores all of the configuration entries from NVRAM,
+ including the associated identifier strings and configuration data.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns ESUCCESS if the restore completed successfully, otherwise one of
+ the following error codes is returned.
+
+ EIO Invalid NVRAM checksum.
+
+--*/
+
+{
+ ULONG EntryIndex;
+ ULONG Index;
+ PCONFIGURATION_PACKET Packet;
+ PCONFIGURATION_COMPONENT Component;
+ PNV_CONFIGURATION NvConfiguration;
+ COMPRESSED_CONFIGURATION_PACKET CompressedPacket;
+ USHORT NvIdentifierIndex;
+ USHORT NvDataIndex;
+ USHORT NvEisaDataIndex;
+ PUCHAR CompressedChars, NvChars;
+ PCONFIGURATION_PACKET SearchPacket;
+ ULONG Long;
+
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+ NvIdentifierIndex = 0;
+ NvDataIndex = 0;
+ NvEisaDataIndex = 0;
+ IdentifierIndex = 0;
+ DataIndex = 0;
+ EisaDataIndex = 0;
+
+ //
+ // Check the checksum, return error if invalid.
+ //
+
+ if (FwConfigurationCheckChecksum() != ESUCCESS) {
+ return EIO;
+ }
+
+ //
+ // Clear the configuration area.
+ //
+
+ RtlZeroMemory(Configuration, sizeof(CONFIGURATION));
+
+ //
+ // Read each non-volatile compressed packet into a volatile packet,
+ // including the identifier string and the configuration data.
+ //
+
+ for ( EntryIndex = 0 ; EntryIndex < NUMBER_OF_ENTRIES ; EntryIndex++ ) {
+
+ //
+ // Read compressed packet from NVRAM.
+ //
+
+ CompressedChars = (PUCHAR)&CompressedPacket;
+ NvChars = (PUCHAR)&NvConfiguration->Packet[EntryIndex];
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) ;
+ Index++ ) {
+ *CompressedChars++ = READ_REGISTER_UCHAR( NvChars++ );
+ }
+
+ //
+ // If this is not the root entry and the parent field is NULL,
+ // go to the next.
+ //
+
+ if ((EntryIndex != 0) && (CompressedPacket.Parent == 0)) {
+ continue;
+ }
+
+ //
+ // Get pointers to the volatile area.
+ //
+
+ Packet = (PCONFIGURATION_PACKET)&Configuration->Packet[EntryIndex];
+ Component = &Packet->Component;
+
+ //
+ // If not the root entry and the parent field is within range, fill
+ // in parent field (note that the parent index
+ // is 1 based, subtract 1 to get correct index). If the parent's child
+ // pointer is NULL, fill in with the current entry, otherwise follow
+ // the links and add the current entry as the last peer.
+ //
+
+ if ((EntryIndex != 0) && (CompressedPacket.Parent <= NUMBER_OF_ENTRIES)) {
+ Packet->Parent = &Configuration->Packet[CompressedPacket.Parent - 1];
+ SearchPacket = Packet->Parent;
+
+ if (SearchPacket->Child == NULL) {
+ SearchPacket->Child = Packet;
+ } else {
+ SearchPacket = SearchPacket->Child;
+ while ( SearchPacket->Peer != NULL ) {
+ SearchPacket = SearchPacket->Peer;
+ }
+ SearchPacket->Peer = Packet;
+ }
+ } else {
+ Packet->Parent = NULL;
+ }
+
+ //
+ // NULL current packet's child and peer pointers.
+ //
+
+ Packet->Child = NULL;
+ Packet->Peer = NULL;
+
+ //
+ // Fill in the rest of the fields.
+ //
+
+ Component->Class = (CONFIGURATION_CLASS)CompressedPacket.Class;
+ Component->Type = (CONFIGURATION_TYPE)CompressedPacket.Type;
+ Component->Flags.Failed = (CompressedPacket.Flags & 0x01) ? 1 : 0;
+ Component->Flags.ReadOnly = (CompressedPacket.Flags & 0x02) ? 1 : 0;
+ Component->Flags.Removable = (CompressedPacket.Flags & 0x04) ? 1 : 0;
+ Component->Flags.ConsoleIn = (CompressedPacket.Flags & 0x08) ? 1 : 0;
+ Component->Flags.ConsoleOut = (CompressedPacket.Flags & 0x10) ? 1 : 0;
+ Component->Flags.Input = (CompressedPacket.Flags & 0x20) ? 1 : 0;
+ Component->Flags.Output = (CompressedPacket.Flags & 0x40) ? 1 : 0;
+ Component->Version = (USHORT)CompressedPacket.Version;
+ Component->Revision = (USHORT)CompressedPacket.Revision;
+ Component->Key = CompressedPacket.Key;
+ Component->AffinityMask = 0xffffffff;
+ Component->ConfigurationDataLength =
+ (ULONG)CompressedPacket.ConfigurationDataLength;
+
+ //
+ // If the component has an identifier string, copy it to memory.
+ //
+
+ Index = 0;
+
+ if (CompressedPacket.Identifier != NO_CONFIGURATION_IDENTIFIER) {
+ Component->Identifier = &Configuration->Identifier[IdentifierIndex];
+ do {
+ Configuration->Identifier[IdentifierIndex++] =
+ READ_REGISTER_UCHAR(
+ &NvConfiguration->Identifier[NvIdentifierIndex] );
+ Index++;
+ } while ( READ_REGISTER_UCHAR(&NvConfiguration->Identifier[NvIdentifierIndex++] ) );
+ }
+
+ //
+ // Set identifier length field.
+ //
+
+ Component->IdentifierLength = Index;
+
+ //
+ // If the component has configuration data, copy it to memory.
+ //
+
+ if (Component->ConfigurationDataLength != 0) {
+
+ //
+ // If the eisa flag is set, only copy the compressed data.
+ //
+
+ if (CompressedPacket.Flags & 0x80) {
+ Packet->ConfigurationData = &Configuration->EisaData[EisaDataIndex];
+ for ( Index = 0 ; TRUE ; Index++ ) {
+ Configuration->EisaData[EisaDataIndex++] =
+ READ_REGISTER_UCHAR( &NvConfiguration->EisaData[NvEisaDataIndex++] );
+
+ //
+ // If at least two bytes have been written and the last
+ // two bytes are zero, we're at the end.
+ //
+
+ if ((Index > 1) &&
+ (!Configuration->EisaData[EisaDataIndex - 1] &
+ !Configuration->EisaData[EisaDataIndex - 2])) {
+ break;
+ }
+ }
+ } else {
+ Packet->ConfigurationData = &Configuration->Data[DataIndex];
+ for ( Index = 0 ; Index < Component->ConfigurationDataLength ; Index++ ) {
+ Configuration->Data[DataIndex++] =
+ READ_REGISTER_UCHAR( &NvConfiguration->Data[NvDataIndex++] );
+ }
+ }
+ }
+ }
+
+ return(ESUCCESS);
+}
+
+
+ARC_STATUS
+FwConfigurationCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the configuration checksum.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the checksum is good, ESUCCESS is returned, otherwise EIO is returned.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum1, Checksum2;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)NvConfiguration;
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) * NUMBER_OF_ENTRIES +
+ LENGTH_OF_IDENTIFIER + LENGTH_OF_DATA;
+ Index++ ) {
+ Checksum1 += READ_REGISTER_UCHAR( NvChars++ );
+ }
+
+ //
+ // Reconstitute checksum and return error if no compare.
+ //
+
+ Checksum2 = (ULONG)READ_REGISTER_UCHAR( &NvConfiguration->Checksum1[0] ) |
+ (ULONG)READ_REGISTER_UCHAR( &NvConfiguration->Checksum1[1] ) << 8 |
+ (ULONG)READ_REGISTER_UCHAR( &NvConfiguration->Checksum1[2] ) << 16 |
+ (ULONG)READ_REGISTER_UCHAR( &NvConfiguration->Checksum1[3] ) << 24 ;
+
+ if (Checksum1 != Checksum2) {
+ NvramValid = FALSE;
+ return EIO;
+ }
+
+ //
+ // Repeat for the eisa data area.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)NvConfiguration->EisaData;
+
+ for ( Index = 0 ;
+ Index < LENGTH_OF_EISA_DATA;
+ Index++ ) {
+ Checksum1 += READ_REGISTER_UCHAR( NvChars++ );
+ }
+
+ //
+ // Reconstitute checksum and return error if no compare.
+ //
+
+ Checksum2 = (ULONG)READ_REGISTER_UCHAR( &NvConfiguration->Checksum3[0] ) |
+ (ULONG)READ_REGISTER_UCHAR( &NvConfiguration->Checksum3[1] ) << 8 |
+ (ULONG)READ_REGISTER_UCHAR( &NvConfiguration->Checksum3[2] ) << 16 |
+ (ULONG)READ_REGISTER_UCHAR( &NvConfiguration->Checksum3[3] ) << 24 ;
+
+ if (Checksum1 != Checksum2) {
+ NvramValid = FALSE;
+ return EIO;
+ }
+
+ NvramValid = TRUE;
+ return(ESUCCESS);
+}
+
+VOID
+FwConfigurationSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the configuration checksum.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum1;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)NvConfiguration;
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) * NUMBER_OF_ENTRIES +
+ LENGTH_OF_IDENTIFIER + LENGTH_OF_DATA;
+ Index++ ) {
+ Checksum1 += READ_REGISTER_UCHAR( NvChars++ );
+ }
+
+ //
+ // Set checksum.
+ //
+
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum1[0], Checksum1);
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum1[1], Checksum1 >> 8);
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum1[2], Checksum1 >> 16);
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum1[3], Checksum1 >> 24);
+
+ //
+ // Repeat for the eisa data area.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)NvConfiguration->EisaData;
+
+ for ( Index = 0 ;
+ Index < LENGTH_OF_EISA_DATA;
+ Index++ ) {
+ Checksum1 += READ_REGISTER_UCHAR( NvChars++ );
+ }
+
+ //
+ // Set checksum.
+ //
+
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum3[0], Checksum1);
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum3[1], Checksum1 >> 8);
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum3[2], Checksum1 >> 16);
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum3[3], Checksum1 >> 24);
+
+ NvramValid = TRUE;
+ return;
+
+}
+
+ARC_STATUS
+FwGetVideoData (
+ OUT PMONITOR_CONFIGURATION_DATA MonitorData
+ )
+
+/*++
+
+Routine Description:
+
+ This routine finds the video board and monitor configuration data in the
+ NVRAM. Normally this information would be accessed through
+ FwGetConfigurationData, but the initialization code needs the video
+ information before the firmware routines have been initialized. If no
+ monitor data is found, then default data is returned.
+
+Arguments:
+
+ MonitorData - Supplies a pointer to a structure to receive the monitor
+ configuration data.
+
+Return Value:
+
+ Returns ESUCCESS if data was found and restored, otherwise returns one of
+ the following error codes.
+
+ EIO Invalid NVRAM checksum.
+
+ ENODEV Monitor data not found.
+
+ Note that in any event valid data is returned.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ ULONG EntryIndex;
+ ULONG Index;
+ COMPRESSED_CONFIGURATION_PACKET CompressedPacket;
+ PUCHAR CompressedChars;
+ PUCHAR NvChars;
+ PUCHAR Data;
+ PNV_CONFIGURATION NvConfiguration;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Check configuration checksum, return error if not valid.
+ //
+
+ if (FwConfigurationCheckChecksum() != ESUCCESS){
+ Status = EIO;
+ } else {
+
+ //
+ // Search the NVRAM configuration entries for the monitor, skip
+ // the root entry.
+ //
+
+ for ( EntryIndex = 1 ; EntryIndex < NUMBER_OF_ENTRIES ; EntryIndex++ ) {
+
+ //
+ // Read compressed packet from NVRAM.
+ //
+
+ CompressedChars = (PUCHAR)&CompressedPacket;
+ NvChars = (PUCHAR)&NvConfiguration->Packet[EntryIndex];
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) ;
+ Index++ ) {
+ *CompressedChars++ = READ_REGISTER_UCHAR( NvChars++ );
+ }
+
+ //
+ // If the parent field is not Null, and the packet is class Peripheral,
+ // type Monitor, this is the display.
+ //
+
+ if ((CompressedPacket.Parent != 0) &&
+ (CompressedPacket.Class == PeripheralClass) &&
+ (CompressedPacket.Type == MonitorPeripheral)) {
+ break;
+ }
+ }
+
+ //
+ // If we've fallen out of the loop the monitor was not found, return
+ // error.
+ //
+
+ if (EntryIndex == NUMBER_OF_ENTRIES) {
+ Status = ENODEV;
+ } else {
+
+ //
+ // If the configuration data length is the correct value, copy the data
+ // into the monitor data structure, otherwise return an error.
+ //
+
+ if (CompressedPacket.ConfigurationDataLength == sizeof(MONITOR_CONFIGURATION_DATA)) {
+ Data = (PUCHAR)MonitorData;
+ for ( DataIndex = CompressedPacket.ConfigurationData ;
+ DataIndex < (CompressedPacket.ConfigurationData +
+ CompressedPacket.ConfigurationDataLength) ;
+ DataIndex++ ) {
+ *Data++ = READ_REGISTER_UCHAR( &NvConfiguration->Data[DataIndex] );
+ }
+ Status = ESUCCESS;
+ } else {
+ Status = ENODEV;
+ }
+ }
+ }
+
+ if (Status != ESUCCESS) {
+ MonitorData->HorizontalResolution = DefaultMonitor.HorizontalResolution;
+ MonitorData->HorizontalDisplayTime = DefaultMonitor.HorizontalDisplayTime;
+ MonitorData->HorizontalBackPorch = DefaultMonitor.HorizontalBackPorch;
+ MonitorData->HorizontalFrontPorch = DefaultMonitor.HorizontalFrontPorch;
+ MonitorData->HorizontalSync = DefaultMonitor.HorizontalSync;
+ MonitorData->VerticalResolution = DefaultMonitor.VerticalResolution;
+ MonitorData->VerticalBackPorch = DefaultMonitor.VerticalBackPorch;
+ MonitorData->VerticalFrontPorch = DefaultMonitor.VerticalFrontPorch;
+ MonitorData->VerticalSync = DefaultMonitor.VerticalSync;
+ MonitorData->HorizontalScreenSize = DefaultMonitor.HorizontalScreenSize;
+ MonitorData->VerticalScreenSize = DefaultMonitor.VerticalScreenSize;
+ }
+
+ return(Status);
+}
+
+VOID
+FwSetVideoData (
+ IN PMONITOR_CONFIGURATION_DATA MonitorData
+ )
+
+/*++
+
+Routine Description:
+
+ This routine stores the monitor configuration data in the
+ NVRAM. Normally this information would be accessed through
+ FwAddChild, but this routine allows this data to be set before the
+ configuration routines have been initialized.
+
+ N.B. This routine assumes the NVRAM has already been checked by
+ FwGetVideoData and is valid.
+
+Arguments:
+
+ MonitorData - Supplies a pointer to a structure containing the monitor
+ configuration data.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+{
+ ARC_STATUS Status;
+ ULONG EntryIndex;
+ ULONG Index;
+ COMPRESSED_CONFIGURATION_PACKET CompressedPacket;
+ PUCHAR CompressedChars;
+ PUCHAR NvChars;
+ PUCHAR Data;
+ PNV_CONFIGURATION NvConfiguration;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Search the NVRAM configuration entries for the monitor, skip
+ // the root entry.
+ //
+
+ for ( EntryIndex = 1 ; EntryIndex < NUMBER_OF_ENTRIES ; EntryIndex++ ) {
+
+ //
+ // Read compressed packet from NVRAM.
+ //
+
+ CompressedChars = (PUCHAR)&CompressedPacket;
+ NvChars = (PUCHAR)&NvConfiguration->Packet[EntryIndex];
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) ;
+ Index++ ) {
+ *CompressedChars++ = READ_REGISTER_UCHAR( NvChars++ );
+ }
+
+ //
+ // If the parent field is not Null, and the packet is class Peripheral,
+ // type Monitor, this is the display.
+ //
+
+ if ((CompressedPacket.Parent != 0) &&
+ (CompressedPacket.Class == PeripheralClass) &&
+ (CompressedPacket.Type == MonitorPeripheral)) {
+ break;
+ }
+ }
+
+ //
+ // Copy the data into the monitor data structure.
+ //
+
+ Data = (PUCHAR)MonitorData;
+ for ( DataIndex = CompressedPacket.ConfigurationData ;
+ DataIndex < (CompressedPacket.ConfigurationData +
+ CompressedPacket.ConfigurationDataLength) ;
+ DataIndex++ ) {
+ WRITE_REGISTER_UCHAR( &NvConfiguration->Data[DataIndex], *Data++);
+ }
+
+ //
+ // Fix the checksum.
+ //
+
+ FwConfigurationSetChecksum();
+
+ return;
+}
+
+
+ULONG
+FwZeroCompressLength (
+ IN ULONG DataLength,
+ IN PVOID ConfigurationData
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the compressed length of a configuration data sample.
+
+Arguments:
+
+ DataLength - Supplies the uncompressed length of the data.
+
+ ConfigurationData - Supplies a pointer to the uncompressed configuration data.
+
+Return Value:
+
+ Returns the compressed length of the configuration data.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG CompressedLength;
+ ULONG Zero;
+ PUCHAR In;
+
+ CompressedLength = 2;
+ Zero = 0;
+ In = ConfigurationData;
+
+ for (Index = 0; Index < DataLength ; Index++ ) {
+ if (*In++) {
+ CompressedLength++;
+ Zero = 0;
+ } else {
+ if (Zero++) {
+ if (Zero == 0x100) {
+ Zero = 1;
+ CompressedLength += 2;
+ }
+ } else {
+ CompressedLength += 2;
+ }
+ }
+ }
+ return(CompressedLength);
+}
+
+
+ULONG
+FwZeroCompress (
+ IN ULONG DataLength,
+ IN PVOID ConfigurationData,
+ OUT PVOID OutputBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine compresses configuration data.
+
+Arguments:
+
+ DataLength - Supplies the uncompressed length of the data.
+
+ ConfigurationData - Supplies a pointer to the uncompressed configuration data.
+
+ OutputBuffer - Supplies a pointer to the buffer to receive the compressed data.
+
+Return Value:
+
+ Returns the compressed length of the configuration data.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG CompressedLength;
+ ULONG Zero;
+ PUCHAR In, Out;
+
+ In = (PUCHAR)ConfigurationData;
+ Out = (PUCHAR)OutputBuffer;
+ CompressedLength = 2;
+ Zero = 0;
+
+ for (Index = 0; Index < DataLength ; Index++ ) {
+ if (*In) {
+ if (Zero) {
+ Out++;
+ Zero = 0;
+ }
+ *Out++ = *In;
+ CompressedLength++;
+ } else {
+ if (Zero++) {
+ if (Zero == 0x100) {
+ *Out++ = 0xFF;
+ *Out++ = 0;
+ *Out = 1;
+ Zero = 1;
+ CompressedLength += 2;
+ } else {
+ *Out += 1;
+ }
+ } else {
+ *Out++ = 0;
+ *Out = 1;
+ CompressedLength += 2;
+ }
+ }
+ In++;
+ }
+
+ if (Zero) {
+ Out++;
+ }
+
+ *Out++ = 0;
+ *Out = 0;
+
+ return(CompressedLength);
+}
+
+
+VOID
+FwZeroDecompress (
+ IN PVOID InBuffer,
+ IN ULONG Index,
+ OUT PVOID ConfigurationData,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine compresses configuration data.
+
+Arguments:
+
+ InBuffer - Supplies a pointer to the compressed configuration data.
+
+ Index - Supplies the index into the uncompressed data to start returning.
+
+ ConfigurationData - Supplies a pointer to the output buffer.
+
+ Length - Supplies the length of data to uncompress.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG DecompressedLength;
+ ULONG Zero;
+ PUCHAR In, Out;
+ UCHAR OutChar;
+
+ if (InBuffer == NULL) {
+ return;
+ }
+
+ In = (PUCHAR)InBuffer;
+ Out = (PUCHAR)ConfigurationData;
+ DecompressedLength = 0;
+ Zero = 0;
+
+ while (DecompressedLength++ < Index + Length) {
+
+ if (Zero) {
+ Zero--;
+ } else if (*In) {
+ OutChar = *In++;
+ } else {
+ OutChar = 0;
+ Zero = *(++In) - 1;
+ In++;
+ }
+
+ if (DecompressedLength > Index) {
+ *Out++ = OutChar;
+ }
+
+ }
+
+}
+#endif