// **********************************************************************
// * IBMASM HEADER FILE                                                 *
// *                                                                    *
// * Written by Matthew DeLoera (deloera@us.ibm.com)                    *
// * (C) Copyright IBM Corporation, 1998-2001                           *
// *                                                                    *
// *  This software may be used and distributed according to the terms  *
// *  of the GNU Public License, incorporated herein by reference.      *
// **********************************************************************






 
 
 

















 
 
























 
 

 
 
 



 
typedef struct _vpd_segments
{
   ULONG  addr;
   USHORT size;

} VPD_SEGMENTS;

 
typedef struct _machine_vpd
{

} MACHINE_VPD, *PMACHINE_VPD;

 
 
typedef struct _def_install_pgm
{
   char mach_model[4 ];
   char bios_id[8 ];
   int  bios_id_size;
   char novell_pgm[20 ];
   char os2_pgm[20 ];
   char winnt_pgm[20 ];
   int  scouw7_hdw;

} DEF_INSTALL_PGM;


 
 
 





 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 


     


 


 


 

 
 
 
 

 
 
 
 

 
 
 
 

 
 
 
 

 
 


typedef struct _STRUCT_DDINST_TABLE
{
   UCHAR  BIOSid [4];         
   UCHAR  WinNT;              
   UCHAR  Win2K;              
   UCHAR  OS2;                
   UCHAR  NetWare;            
   UCHAR  SCO;                
   UCHAR  Linux;              
} STRUCT_DDINST_TABLE;


STRUCT_DDINST_TABLE DDINST_ranger_table  [] = { {  "MOJT",  1,     1,     1,    1,       1,   1     }, {  "KIJT",  1,     1,     1,    1,       1,   1     }, {  "KIJT",  1,     1,     1,    1,       1,   1     }, {  "KQJT",  1,     1,     1,    1,       1,   1     }, {  "TPJT",  1,     1,     1,    1,       1,   1     }, {  "MWJT",  1,     1,     1,    1,       1,   1     }, {  "MWJT",  1,     1,     1,    1,       1,   1     }, {  "ILJT",  1,     1,     1,    1,       1,   1     }, {  "ARJT",  1,     1,     1,    1,       1,   1     }, {  "ILJT",  1,     1,     1,    1,       1,   1     }, {  "PKJT",  1,     1,     1,    1,       1,   1     }, {  "TTJT",  1,     1,     1,    1,       1,   1     }, {  "TXJO",  1,     1,     1,    1,       1,   1     }, {  "TPJT",  1,     1,     1,    1,       1,   1     }, {  "EMJT",  1,     1,     1,    1,       1,   1     }, {  "ENJT",  1,     1,     1,    1,       1,   1     }, {  "TVJT",  1,     1,     1,    1,       1,   1     }, {  "stop",  0,     0,     0,    0,       0,   0     }   };
STRUCT_DDINST_TABLE DDINST_wiseman_table [] = { {  "****",  1,     1,     1,    1,       1,   1     }, {  "stop",  0,     0,     0,    0,       0,   0     }  };
STRUCT_DDINST_TABLE DDINST_eagle_table   [] = { {  "****",  1,     1,     0,    1,       1,   1     }, {  "stop",  0,     0,     0,    0,       0,   0     }    };
STRUCT_DDINST_TABLE DDINST_asr_table     [] = { {  "****",  1,     1,     0,    1,       0,   1     }, {  "stop",  0,     0,     0,    0,       0,   0     }      };
STRUCT_DDINST_TABLE DDINST_hum_table     [] = { {  "****",  1,     1,     0,    1,       0,   0     }, {  "stop",  0,     0,     0,    0,       0,   0     }      };
STRUCT_DDINST_TABLE DDINST_amber_table   [] = { {  "ABJT",  1,     1,     0,    1,       0,   0     }, {  "ZRJT",  1,     1,     0,    1,       0,   0     }, {  "stop",  0,     0,     0,    0,       0,   0     }    };
STRUCT_DDINST_TABLE DDINST_pearl_table   [] = { {  "****",  1,     1,     0,    1,       0,   1     }, {  "stop",  0,     0,     0,    0,       0,   0     }    };
STRUCT_DDINST_TABLE DDINST_jasper_table  [] = { {  "****",  1,     1,     0,    1,       0,   1     }, {  "stop",  0,     0,     0,    0,       0,   0     }   };


 
 
 





     







     







     







     







     







     







     



 
 
 

UCHAR DDINST_SearchTable(STRUCT_DDINST_TABLE *Table);
UCHAR DDINST_WhichDriver(UCHAR *HardwareCode);
UCHAR DDINST_IsEagle(void);
UCHAR DDINST_IsWiseman(void);
UCHAR DDINST_IsRanger(void);
UCHAR DDINST_IsASR(void);      
UCHAR DDINST_IsPASR(void);     
UCHAR DDINST_IsJASR(void);     
UCHAR DDINST_IsHASR(void);     
UCHAR DDINST_IsBASR(void);     
UCHAR DDINST_GetBIOSid(UCHAR *BIOSid);
UCHAR DDINST_SMBIOSscan(UCHAR *DetectionString);
UCHAR *DDINST_CopyPhysicalSegment(unsigned long Segment);
UCHAR DDINST_PCIscan(USHORT VendorID, USHORT DeviceID);






int DDINST_Linux_SegmentCopy(unsigned long Segment, unsigned char *pX, unsigned long length);



UCHAR DDINST_SearchTable(STRUCT_DDINST_TABLE *Table)
{
     USHORT row, found = 0;
     UCHAR BIOSid [5];

      
     if (!DDINST_GetBIOSid(BIOSid)) return 0;

      
     for (row = 0; ((Table[row].BIOSid[0] != 's') || (Table[row].BIOSid[1] != 't') || (Table[row].BIOSid[2] != 'o') || (Table[row].BIOSid[3] != 'p')); row++)
     {
           
          if ((Table[row].BIOSid[0] == BIOSid[0]) && (Table[row].BIOSid[1] == BIOSid[1])) found = 1;
          if ((Table[row].BIOSid[0] == '*')       && (Table[row].BIOSid[1] == '*'))       found = 1;
          if (found) break;
     }
     if (!found) return 0;

      






     return Table[row].Linux;

     return 0;   
}








UCHAR DDINST_WhichDriver(UCHAR *HardwareCode)
{
     if      (DDINST_IsRanger())             *HardwareCode = 'R';
     else if (DDINST_IsEagle())              *HardwareCode = 'E';
     else if (DDINST_IsWiseman())            *HardwareCode = 'W';
     else if (DDINST_IsASR())                *HardwareCode = 'A';   
     else if (DDINST_IsPASR())               *HardwareCode = 'P';   
     else if (DDINST_IsJASR())               *HardwareCode = 'J';   
     else if (DDINST_IsHASR())               *HardwareCode = 'H';   
     else if (DDINST_IsBASR())               *HardwareCode = 'B';   
     else return 0;
     return 1;
}


UCHAR DDINST_IsEagle(void)
{
     if (DDINST_PCIscan(0x1014 ,   0x010F ))   return DDINST_SearchTable(DDINST_eagle_table);
     return 0;
}


UCHAR DDINST_IsWiseman(void)
{
     if (DDINST_PCIscan(0x1014 , 0x00DC )) return DDINST_SearchTable(DDINST_wiseman_table);
     return 0;
}


UCHAR DDINST_IsRanger(void)
{
     return DDINST_SearchTable(DDINST_ranger_table);
}


UCHAR DDINST_IsASR(void)
{
      
     if (DDINST_SMBIOSscan("IBM Automatic Server Restart - eserver xSeries 220")) return DDINST_SearchTable(DDINST_asr_table);
     return 0;
}

UCHAR DDINST_IsPASR(void)
{
      
     if (DDINST_SMBIOSscan("IBM Automatic Server Restart - Machine Type 8673")) return DDINST_SearchTable(DDINST_pearl_table);
     return 0;
}

UCHAR DDINST_IsJASR(void)
{
      
     if (DDINST_SMBIOSscan("IBM Automatic Server Restart - Machine Type 8480")) return DDINST_SearchTable(DDINST_jasper_table);
     return 0;
}

UCHAR DDINST_IsHASR(void)
{
      
     if (DDINST_SMBIOSscan("IBM Automatic Server Restart - Integrated System Management Processor")) return DDINST_SearchTable(DDINST_hum_table);
     return 0;
}

UCHAR DDINST_IsBASR(void)
{
     return DDINST_SearchTable(DDINST_amber_table);
}



UCHAR DDINST_GetBIOSid(UCHAR *BIOSid)
{
     unsigned char  *pX;
     unsigned long  base = 0x000F0000;
     unsigned short idx, idx2;

      
     for (idx2 = 0; idx2 < 2; idx2++)
     {
           
          if (NULL == (pX = DDINST_CopyPhysicalSegment(base))) return 0;

           
          for (idx = 0; idx < 0xfff9; idx++)
          {    
               if ((pX[idx + 0] == 0xaa) && (pX[idx + 1] == 0x55) && (pX[idx + 2] == 'V') && (pX[idx + 3] == 'P') && (pX[idx + 4] == 'D'))
               {
                     
                    BIOSid[0] = pX[idx + 13];
                    BIOSid[1] = pX[idx + 14];
                    BIOSid[2] = 0;

                     
                    if (DBG_DDINST ) printk ("Found VPD Info - BIOS ID = %s.\r\n", BIOSid);
                    kfree( pX ) ;
                    return 1;
               }
          }

           
          base = 0x000E0000;
     }
     kfree( pX ) ;
     return 0;
}


UCHAR DDINST_SMBIOSscan(UCHAR *DetectionString)
{
     unsigned char  *pX;
     unsigned short idx, idx2, idx3, match;
     unsigned short SM_TableLength, SM_NumStructs, SM_TableOffset;
     unsigned long  SM_TableBase;
     unsigned short StructureIdx, MasterOffset, StringOffset;
     unsigned char  Type10_NumDevices, Type10_DevType, Type10_StringIdx, Type10_Enabled, Type10_String[65];
     unsigned short StructLength, StructType, StructHandle;

      
     if (NULL == (pX = DDINST_CopyPhysicalSegment(0x000F0000))) return 0;

      
     for (idx = 0; idx < 0xfff9; idx++)
     {
          if ((pX[idx + 0] == '_') && (pX[idx + 1] == 'D') && (pX[idx + 2] == 'M') && (pX[idx + 3] == 'I') && (pX[idx + 4] == '_'))
          {
                
               SM_TableLength = (pX[idx + 7] * 0x100) + pX[idx + 6];
               SM_TableBase   = (pX[idx + 11] * 0x1000000) + (pX[idx + 10] * 0x10000) + (pX[idx + 9] * 0x100) + pX[idx + 8];
               SM_TableOffset = (pX[idx + 9] * 0x100) + pX[idx + 8];
               SM_NumStructs  = (pX[idx + 13] * 0x100) + pX[idx + 12];

                
               if (DBG_DDINST )
               {
                    printk ("Found SM BIOS @ offset %04x : Structure Table Address = %08lx.\r\n", idx, SM_TableBase);
                    printk ("                              Structure Table Length  = %d.\r\n",        SM_TableLength);
                    printk ("                              Table Offset in Struct  = %d.\r\n",        SM_TableOffset);
                    printk ("                              Number of Structs       = %d.\r\n",        SM_NumStructs);
               }

                
               MasterOffset = SM_TableOffset;
               for (StructureIdx = 0; StructureIdx < SM_NumStructs; StructureIdx++)
               {
                     
                    StructType   = pX[MasterOffset];
                    StructLength = pX[MasterOffset + 1];
                    StructHandle = (pX[MasterOffset + 3] * 0x100) + pX[MasterOffset + 2];

                     
                    if (StructType == 10)
                    {
                          
                         Type10_NumDevices = (StructLength - 4) / 2;
                         if (DBG_DDINST ) printk ("Found type 10 struct. (Handle = %04x)  (Length = %x)  (Devices = %d).\r\n", StructHandle, StructLength, Type10_NumDevices);

                          
                         for (idx2 = 0; idx2 < Type10_NumDevices; idx2++)
                         {
                               
                              Type10_DevType   = pX[MasterOffset + 4 + (idx2 * 2)];
                              Type10_StringIdx = pX[MasterOffset + 4 + (idx2 * 2) + 1];
                              Type10_Enabled   = Type10_DevType >> 7;
                              Type10_DevType   = Type10_DevType & 0x7f;

                               
                              StringOffset = MasterOffset + StructLength;
                              for (idx3 = 1; idx3 < Type10_StringIdx; idx3++)
                              {
                                   while (pX[StringOffset]) StringOffset++;
                                   StringOffset++;
                              }

                               
                              Type10_String[0] = 0;
                              for (idx3 = 0; idx3 < 64; idx3++)
                              {
                                   if (!pX[StringOffset]) break;
                                   Type10_String[idx3] = pX[StringOffset + idx3];
                              }
                              Type10_String[idx3] = 0;

                               
                              if (DBG_DDINST )
                              {
                                   if (Type10_Enabled) printk ("     Type %02x - Enabled  - %s.\r\n", Type10_DevType, Type10_String);
                                   else                printk ("     Type %02x - Disabled - %s.\r\n", Type10_DevType, Type10_String);
                              }

                               
                              for (idx3 = 0, match = 1; (Type10_String[idx3] && DetectionString[idx3]); idx3++)
                              {
                                   if (Type10_String[idx3] != DetectionString[idx3]) match = 0;
                              }
                              if (match)
                              {
                                   kfree( pX ) ;
                                   return 1;
                              }
                         }
                    }

                     
                    MasterOffset = MasterOffset + StructLength;
                    while (pX[MasterOffset] || pX[MasterOffset + 1]) MasterOffset++;
                    MasterOffset = MasterOffset + 2;
               }
          }
     }

      
     kfree( pX ) ;
     return 0;
}


UCHAR *DDINST_CopyPhysicalSegment(unsigned long Segment)
{
     unsigned char  *pX = NULL;
     int   rc;

      
     if (NULL == (pX = kmalloc( 0xFFFF , GFP_KERNEL) ))
     {
          printk ("Unable to allocate memory for browsing.\r\n");
          pX = NULL;
          return pX;
     }

      
     rc = DDINST_Linux_SegmentCopy( 0x000F0000 ,   pX ,   0xFFFF ); ;
     if (!  rc  )
     {
          printk ("Unable to copy memory segment.\r\n");
          kfree( pX ) ;
          pX = NULL;
          return pX;
     }
     return pX;
}


 
 
 
 
 
 
 
 
 
 
 
 
 












UCHAR DDINST_PCIscan(USHORT VendorID, USHORT DeviceID)
{
     struct pci_dev *pci_device = NULL;

      
     if (!pci_present()) return 0;

      
     if (NULL == (pci_device = pci_find_device(VendorID, DeviceID, pci_device))) return 0;
     return 1;
}


int DDINST_Linux_SegmentCopy(unsigned long Segment, unsigned char *pX, unsigned long length)
{
     unsigned char *pROM;

      
     if (NULL == ((void *)pROM = ioremap(Segment, 0xffff))) return 0;

      
     memcpy_fromio(pX, pROM, 0xffff);
     return 1;
}






 
          
     

     
 






