package Revision::HBA;
use strict;
use base 'Revision';
use System;
use Util;

#
#  PASS, LOW, HIGH, NI (not installed), ERR


sub class {"host.hba"}
sub description {"HBA Patches"}
sub type {"hba"}

sub RUN {
  my($class, $Matrix, $InstalledPatches) = @_;
  my($l, @R);

  #################################################
  # get the hba list                              #
  #################################################
  my @Li;
  my @Li_qlc;
  my @Li_jni;
  my $file = "luxadm -e port";
  my $cache = "default";
  my @err_info;
  my $rc4 = undef;

  if (open(T, "$file 2>&1|")) {
      while ($l = <T>) {
          if ( $l =~ /devices/ ) {
               if (( $l =~ /socal/ ) || ( $l =~ /ifp/ )) { # only deal with soc+, on-board soc+ , ifp now 
                    my ($port_path, $tem) = split (/\s+/,$l);
                    my ($dev,$tem1) = split (/:/,$l);
                    if ( $dev !~ $cache) {
                        push (@Li,$dev);
                    }
                    $cache = $dev;
               }
               elsif  ($l =~ /qlc/)  {
                    my ( $dev, $tem1) = split (/\s+/, $l);
                    push ( @Li_qlc, $dev);                      
               }
           
               elsif ($l =~ /jfca/ ) {
                    my ( $dev, $tem1) = split (/\s+/, $l);
                    push ( @Li_jni, $dev);
                    
               }

               if  (($l =~ /scsi/) || ($l =~ /fibre/)) {
                    if ($l =~ /scsi/) {
                      my ( $dev, $tem1) = split (/\s+/, $l);
                      push(@err_info, ['HBA',$dev,'Error',
                               undef, undef,
                               undef, undef,
                              'This is a scsi hba, revision check does not support it']);
                    }
                    if ($l =~ /fibre/) {
                      my ( $dev, $tem1) = split (/\s+/, $l);
                      push(@err_info, ['HBA',$dev,'Error',
                               undef, undef,
                               undef, undef,
                              'This is an unknown fibre-channel hba, revision check does not support it']);
                    }
                    $rc4 = \@err_info;
 
               }
          }
      } 
      close (T);
  }
  else {
      # print "err\n";
      my $rc;
      my @err_record;
      push(@err_record, ['HBA',undef,'Error',
                               undef, undef,
                               undef, undef, 
                              'can not run cmd: luxadm -e port, please check system setup']);
     $rc = \@err_record;
     return[@$rc];
  }
  #################################################
  # now we have the device list to check revision #
  #################################################
  my $Liptr_qlc = \@Li_qlc;
  my $rc1 = undef;
  my $rc2 = undef;
  my $rc3 = undef;

  $rc1 = $class->check_qlc_hba_revision($Matrix, $InstalledPatches,$Liptr_qlc);

  my $Liptr = \@Li;
  $rc2 = $class->check_soc_ifp_hba_revision($Matrix, $InstalledPatches,$Liptr );

  my $Liptr_jni = \@Li_jni;
  $rc3 = $class->check_jni_hba_revision($Matrix, $InstalledPatches,$Liptr_jni);
 
 if (!$rc4) {
  return [@$rc1, @$rc2, @$rc3];
 }
 else {
   return [@$rc1, @$rc2, @$rc3, @$rc4];
 }
}

sub check_jni_hba_revision {
    my ($class, $Matrix, $InstalledP, $hba_list) = @_;
     my $FCODE = $Matrix->{HBA_FCODE};
     my @R;
     my $Dir = "/usr/sbin/";
     my $info =" No patch available for the  HBA, please contact your SUN representative";
     my $info2 = " There is no information of this device in the matrix you chose, please use the latest version of matrix. If the problem still exists, please  contact your SUN representative";
     my $curr_fcode;

     my $cmd = $Dir."modinfo |grep J";
    # 28  1256198  6b515 254   1  jfca (SunFC JNI FCA v20031204-1.19) 
     if (open(T, "$cmd 2>&1|")){
               while (my $l = <T>) {
                        if ( $l =~ /(.*) jfca \(SunFC (.*) (.*) (.*)\)/ ) {
                             $curr_fcode= $4;
                        }
               }

               close (T);
     }  else {
                   my @err_record;
                   push(@err_record, ['HBA',undef,'Error',
                               undef, undef,
                               undef, undef,
                              'can not run $cmd, please check system setup']);
                   return \@err_record;

    }


     my $Dir2 = System->get_home();
     my $cmd2 = $Dir2."/sbin/jni_fcode_version";
     my $full_path = "unknown";
     my $hba_cat = "JNI_FCODE";
     my $entry2 = $FCODE->{$hba_cat};
     my ($hba_manu, $hba_re, $fw_ver, $patch_list2) = @$entry2;
 
     if (open(T2, "$cmd2 2>&1|")){
               while (my $line = <T2>) {
                    #if (!$line) {
                      my ($tem1, $tem2, $hba_path, $tem4, $tem5, $tem6, $tem7, $cur_fw) = split (/\s+/, $line);
                      my $comp_result = $class->compareFwLevels($cur_fw, $fw_ver);

                      foreach my $hba_device (@$hba_list) {                 
                        if ($hba_device =~ /$hba_path/ ) {
                           $full_path = $hba_device;  
                        } 
                      }

                      if ( $comp_result == -1) {
                                           if ( ($patch_list2 =~ /xxxx/ ) || (!$patch_list2) ) {
                                                push(@R, ['HBA',$full_path,'DOWNREV',
                                                           $cur_fw, $fw_ver,
                                                           undef, "N/A", $info ]);
                                            } else {
                                                push(@R, ['HBA', $full_path, 'DOWNREV',
                                                      $cur_fw, $fw_ver,
                                                      undef, $patch_list2,  undef]);
                                            }
                      } elsif ($comp_result == 0) {
                                            if ( ($patch_list2 =~ /xxxx/ ) || (!$patch_list2) ) {
                                                push(@R, ['HBA', $full_path, 'PASS',
                                                           $cur_fw, $fw_ver,
                                                           undef, undef,  undef]);
                                            } else {
                                                push(@R, ['HBA', $full_path, 'PASS',
                                                      $cur_fw, $fw_ver,
                                                      undef, undef,  undef]);
                                            }
                      } else {
                                            if ( ($patch_list2 =~ /xxxx/ ) || (!$patch_list2) ) {
                                                push(@R, ['HBA',$full_path,'UPREV',
                                                           $cur_fw, $fw_ver,
                                                           undef, undef, $info ]);
                                            } else {
                                                push(@R, ['HBA', $full_path, 'UPREV',
                                                      $cur_fw, $fw_ver,
                                                      undef, $patch_list2,  undef]);
                                            }
                     }
                  # }

               }

               close (T2);
     }  else {
                   my @err_record;
                   push(@err_record, ['HBA',undef,'Error',
                               undef, undef,
                               undef, undef,
                              'can not run $cmd2, please check system setup']);
                   return \@err_record;

    }

    

     return \@R;
}


sub check_soc_ifp_hba_revision{
     my ($class, $Matrix, $InstalledP, $hba_list) = @_;
     my $FCODE = $Matrix->{HBA_FCODE};
     my @R;
     my $Dir = System->get_home();
     my $info =" No patch available for the  HBA, please contact your SUN representative"; 
     my $info2 = " There is no information of this device in the matrix you chose, please use the
latest version of matrix. If the problem still exists, please  contact your SUN representative";

     foreach my $hba (@$hba_list){
          my $cmd = $Dir."/sbin/soc_hba ";
          my $file2 =$cmd.$hba; 
          if (open(T, "$file2 2>&1|")){
               while (my $l = <T>) {
                    ######################################################
                    #   example out put is like:                         #
                    #   @(#) FCode 1.11 97/12/07                         #
                    #   or :                                             #
                    #   FC100/P FC-AL Host Adapter Driver: 1.9 00/03/10  # 
                    ######################################################
                    # print "$l\n";                    
                    if ( $l =~ /FCode/ )  {  # soc+  | on-board soc+
                          my ($tem1, $tem2, $curr_fcode , $installed_time) = split (/\s+/,$l); 
                          if ( $hba =~ /socal\@d\,10000/)
                          {
                             #  soc on-board case
                             #   print "soc on-board card , $hba\n";
                                my $hba_name = "Onboard Soc+"; 
                                my $entry = $FCODE->{$hba_name};
                                my ($hba_manufact, $hba_reg, $fw_version, $patch_list) = @$entry;
                                my $comp_result = $class->version_ok($fw_version,$curr_fcode);
                                if (!$comp_result) {
                                            if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                                push(@R, ['HBA',$hba,'DOWNREV',
                                                           $curr_fcode, $fw_version,
                                                           undef, "N/A", $info ]);
                                            } else {
                                                push(@R, ['HBA', $hba, 'DOWNREV',
                                                      $curr_fcode, $fw_version,
                                                      undef, $patch_list,  undef]);    
                                            } 
                                } elsif ($comp_result == 1) {
                                            if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                                push(@R, ['HBA', $hba, 'PASS',
                                                           $curr_fcode, $fw_version,
                                                           undef, undef,  undef]);
                                            } else {
                                                push(@R, ['HBA', $hba, 'PASS',
                                                      $curr_fcode, $fw_version,
                                                      undef, undef,  undef]);
                                            }
                                } else {
                                            if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                                push(@R, ['HBA',$hba,'UPREV',
                                                           $curr_fcode, $fw_version,
                                                           undef, undef, $info ]);
                                            } else { 
                                                push(@R, ['HBA', $hba, 'UPREV',
                                                      $curr_fcode, $fw_version,
                                                      undef, undef,  undef]);
                                            }
                                }
 
                          } 
                          else
                          {
                                # print "soc card, $hba\n";
                                my $hba_name = "Soc+";
                                my $entry = $FCODE->{$hba_name};
                                my ($hba_manufact, $hba_reg, $fw_version, $patch_list) = @$entry;
                                my $comp_result = $class->version_ok($fw_version,$curr_fcode);
                                if (!$comp_result) {
                                            if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                                push(@R, ['HBA',$hba,'DOWNREV',
                                                           $curr_fcode, $fw_version,
                                                           undef, "N/A", $info ]);
                                            } else {
                                                push(@R, ['HBA', $hba, 'DOWNREV',
                                                      $curr_fcode, $fw_version,
                                                      undef, $patch_list,  undef]);
                                            }
                                } elsif ($comp_result == 1) {
                                            if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                                push(@R, ['HBA', $hba, 'PASS',
                                                           $curr_fcode, $fw_version,
                                                           undef, undef,  undef]);
                                            } else {
                                                push(@R, ['HBA', $hba, 'PASS',
                                                      $curr_fcode, $fw_version,
                                                      undef, undef,  undef]);
                                            }

                                } else {
                                            if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                                push(@R, ['HBA',$hba,'UPREV',
                                                           $curr_fcode, $fw_version,
                                                           undef, undef, $info ]);
                                            } else {
                                                push(@R, ['HBA', $hba, 'UPREV',
                                                      $curr_fcode, $fw_version,
                                                      undef, $patch_list,  undef]);
                                            }
                                }

                          }
                    }
                    else {   #  Qlogic 2100 or ifp card case
                                my ($tem1, $tem2, $tem3, $tem4, $tem5, $curr_fcode , $installed_time) = split (/\s+/,$l);
                                my $hba_name = "Qlogic 2100";
                                my $entry = $FCODE->{$hba_name};
                                my ($hba_manufact, $hba_reg, $fw_version, $patch_list) = @$entry;
                                my $comp_result = $class->version_ok($fw_version,$curr_fcode);
                                if (!$comp_result) {
                                            if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                                push(@R, ['HBA',$hba,'DOWNREV',
                                                           $curr_fcode, $fw_version,
                                                           undef, "N/A", $info ]);
                                            } else {
                                                push(@R, ['HBA', $hba, 'DOWNREV',
                                                      $curr_fcode, $fw_version,
                                                      undef, $patch_list,  undef]);
                                            }
                                } elsif ($comp_result == 1) {
                                            if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                                push(@R, ['HBA', $hba, 'PASS',
                                                           $curr_fcode, $fw_version,
                                                           undef, undef,  undef]);
                                            } else {
                                                push(@R, ['HBA', $hba, 'PASS',
                                                      $curr_fcode, $fw_version,
                                                      undef, undef,  undef]);
                                            }

                                } else {
                                            if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                                push(@R, ['HBA',$hba,'UPREV',
                                                           $curr_fcode, $fw_version,
                                                           undef, undef, $info ]);
                                            } else {
                                                push(@R, ['HBA', $hba, 'UPREV',
                                                      $curr_fcode, $fw_version,
                                                      undef, $patch_list,  undef]);
                                            }
                                }

                    }
               }
          }
          else {
                my @err_record;
                push(@err_record, ['HBA',undef,'Error',
                               undef, undef,
                               undef, undef,
                              'can not run $cmd, please check system setup']);
                return \@err_record;

          }
          close(T);
     }  
     return \@R;
}


sub check_qlc_hba_revision {
     my ($class, $Matrix, $InstalledP, $hba_list) = @_;
     my $FCODE = $Matrix->{HBA_FCODE};
     my @R;
     my $Dir = System->get_home();
     my $type;
     my $tem1;
     my $comment;
     my $hba_name;
     my $curr_fcode;
     my $install_date;
     my @record;
     my $info = " No patch available for this kind of HBA, please contact your SUN representative";
     my $info2 = " There is no information of this device in the matrix you chose, please use the
latest version of matrix. If the problem still exists, please  contact your SUN representative";

     foreach my $hba (@$hba_list){
        my $cmd = $Dir."/sbin/qlc_hba ";
        my $file2 =$cmd.$hba;
        if (open(T, "$file2 2>&1|")){
              while (my $l = <T>) {
                ($type, $tem1) = split(/:/, $l);
                $tem1 =~ s/^\s+//; 
                ($curr_fcode, $install_date) = split(/\s+/, $tem1);
                if (( $type =~ /ISP22(\d*)/ ) && ($type !~ /Sbus/) ){
                    $hba_name = "Qlogic 2200 PCI";
                    $comment = "1Gb HBA";
                } elsif ( $type =~ /ISP22(\d*) Sbus/ ) {
                    $hba_name = "Qlogic 2200 SBUS";
                    $comment = "1Gb HBA";
                } elsif (( $type =~ /ISP23(\d*)/ ) && ( $type !~ /Sbus/) ){
                    if ( $type =~ /0x10a/) {
                       $hba_name = "Qlogic 2312 PCI";
                       $comment = "2Gb HBA";
                    } else {   
                       $hba_name = "Qlogic 2310 PCI";
                       $comment = "2Gb HBA";
                    }
                } elsif ( $type =~ /ISP23(\d*) Sbus/ ) {
                    $hba_name = "Qlogic 2300 SBUS";
                    $comment = "2Gb HBA";
                } 
                my $entry = $FCODE->{$hba_name};
                if (! $entry ) {
                        push(@R, ['HBA',$hba,'ERR',
                                              undef, undef,
                                               undef, undef, $info2 ]);
                } else {
                my ($hba_manufact, $hba_reg, $fw_version, $patch_list) = @$entry;
                my $comp_result = $class->version_ok($fw_version,$curr_fcode);
                if (!$comp_result) {
                        if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                    push(@R, ['HBA',$hba,'DOWNREV',
                                               $curr_fcode, $fw_version,
                                               undef, undef, $info ]);
                        } else {
                                    push(@R, ['HBA', $hba, 'DOWNREV',
                                               $curr_fcode, $fw_version,
                                               undef, $patch_list,  $comment]);
                        }
                } elsif ($comp_result == 1) {
                        if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                                    push(@R, ['HBA', $hba, 'PASS',
                                               $curr_fcode, $fw_version,
                                               undef, undef,  $comment]);
                        } else {
                                    push(@R, ['HBA', $hba, 'PASS',
                                               $curr_fcode, $fw_version,
                                               undef, undef,  $comment]);
                        }

                } else {
                        if ( ($patch_list =~ /xxxx/ ) || (!$patch_list) ) {
                               push(@R, ['HBA',$hba,'UPREV',
                                          $curr_fcode, $fw_version,
                                          undef, undef, $info ]);
                        } else {
                               push(@R, ['HBA', $hba, 'UPREV',
                                          $curr_fcode, $fw_version,
                                          undef, $patch_list,  $comment]);
                        }
                }
              }

        }     
        close (T);
     } else {   # open failed
           my @err_record;
           push(@err_record, ['HBA',undef,'Error',
                               undef, undef,
                               undef, undef,
                              'can not run $cmd, please check system setup']);
           return \@err_record;
     }
   }
   return \@R;

}



1;


