#!/opt/SUNWstade/bin/perl
#<copyright>
# ----------------------------------------------------------
# Sun Proprietary/Confidential Code
# Copyright 2001, Sun Microsystems, Inc. All rights reserved.
# ----------------------------------------------------------
#</copyright>

##################################################################
#MinnowUtil.pm
#Package MinnowUtil
##################################################################
package MinnowUtil;

use strict;
use LWP::UserAgent;
use Data::Dumper;
use Util;
use Agent::3310;

##################################################################
#MinnowUtil Consturctor
##################################################################
sub new {
  my $this = {}; 
  # object properties
  shift;
  $this->{address} = shift;
  $this->{sysModel} = "device";
  $this->{set_debug}=undef;
  $this->{set_verbose}=undef;
  $this->{error}=undef;
  $this->{ondgOperPending}=undef;
  $this->{ondgOperProgress}=undef;
  $this->{ondgError}=undef;
  $this->{num_error}=0;
  bless($this, 'MinnowUtil'); 
  return $this;
}

##################################################################
#MinnowUtil::connect
##################################################################
sub connect {
  my $this = shift;
  my $TO = 120;
  my $count = 0;
 
  if ($this->{set_debug}) { 
     print "probe 3510 $this->{address}\n"; 
  }
  my $sccli = &sccli_path();
  my $ip = $this->{address}; 
  my ($err, $info) = Util->run_command("$sccli $ip inquiry","3510_probe.txt",$TO);
  if (!$err) {
      foreach my $l (@$info) {
            $count++; 
      }
      if ($count > 1) {
        return 1;
      } else {
        return 0;  # some error 
      }
  } else {
      return 0;
  }
}

##################################################################
#MinnowUtil::getShutDownStatus
#  return values: 1  ( shutdown )
#                 0  ( not shutdown )
#                 -1 ( err  )
##################################################################

sub getShutDownStatus {
     my $this = shift;
     my $para = shift;
     my $TO = 240;
     my $count = 0;
     my $msg1 = "Please shut down controller first, then re-start running this test\n";
     my $msg2 = "Can not get the system shutdown status, please check password in test setup \n";
     my $sccli = &sccli_path();
     my $ip = $this->{address};
     #my ($err, $info) = Util->run_command("$sccli $ip show shutdown","shutdown.txt",$TO);

     my $device;
     $device->{path} = $para->{"dev"};
     $device->{telnet} = Util->encodeAll($para->{passwd});
     
     my $option = " show shutdown"; 

     require Agent::3310;
     my ($err, $info) = Agent::3310->run_command($device,
                                            "$sccli $ip",
                                             $option, $TO);

     if (!$err) {
        foreach my $l (@$info) {  
          if ($l =~ /not shutdown/) {
             return (0,$msg1);
          } 
          if ($l =~ /already shutdown/ ) {
             return (1, undef);
          } 
        }
        return (-1, $msg2); 
     } else {
       return (-1, $msg2);
     }
}


##################################################################
#MinnowUtil::getLoopMode
#  return values: loop_mode   :  1
#                 fabric_mode :  0
##################################################################
sub getLoopMode {
     my $this = shift;
     my $TO = 120;
     my $count = 0;

     my $sccli = &sccli_path();
     my $ip = $this->{address};
     my ($err, $info) = Util->run_command("$sccli $ip show chan","showchan.txt",$TO);
     if (!$err) {
        foreach my $l (@$info) {
          if ($l =~ /FC\(L\)/) {
             return 1;
          }
          if ($l =~ /FC\(P\)/ ) {
             return 0;
          }
        }
     }
}


sub sccli_path {
  return System->get_home() . "/bin/sccli ";
}


##################################################################
#MinnowUtil::getFailCtrStatus
#  return values: 1  ( reduncdancy status is failed )
#                 0  ( not failed )
#                 -1 ( err  )
##################################################################

sub getFailCtrStatus {
     my $this = shift;
     my $para = shift;
     my $TO = 120;
     my $count = 0;

     my $sccli = &sccli_path();
     my $ip = $this->{address};

     my $device;
     $device->{path} = $para->{"dev"};
     $device->{telnet} = Util->encodeAll($para->{passwd});

     my $option = " show redundancy";
      require Agent::3310;
      my ($err, $info, $stderr) = Agent::3310->run_command($device,
                                            "$sccli $ip",
                                             $option, $TO);

     push @{$info}, $stderr;
     if (!$err) {
        foreach my $l (@$info) {
          if (($l =~ /status/) && ($l =~ /Enabled/i )) {
             return 0;
          } 
          if (($l =~ /status/) &&  ($l =~ /failed/i)) {
             return 1;
          } 

        }
        return (-1);
     } else {
       return (-1);
     }
}

##################################################################
#MinnowUtil::set_debug
##################################################################
sub set_debug {
  my $this = shift;
  $this->{set_debug}="On";
  return "On";
}

##################################################################
#MinnowUtil::set_verbose
##################################################################
sub set_verbose {
  my $this = shift;
  $this->{set_verbose}="On";
  return "On";
}

##################################################################
#MinnowUtil:runWRBTest
##################################################################

sub runWRBTest {
  my $this = shift;
  my $para = shift;
  my $option;
  my $TO =60;
  my @critical_patterns = ("0x7e7e7e7e7e7e7e7e", 
        "0xb5b5b5b5b5b5b5b5",
        "0x4a4a4a4a4a4a4a4a",
        "0x7878787878787878",
        "0xe7e7e7e7e7e7e7e7",
        "0xaa55aa55aa55aa55",
        "0x7f7f7f7f7f7f7f7f",
        "0x0f0f0f0f0f0f0f0f",
        "0x00ff00ff00ff00ff",
        "0x1e1e1e1e1e1e1e1e",
        "0x2525252525252525"
  );

#  foreach $option (keys(%$para)){
#        print "key is :".$option."\n";
#        print "value is :".$para->{$option}."\n";
#  }
  my $dev           = $para->{"dev"};
  my $selectpattern = $para->{"selectpattern"};
  my $userpattern   = $para->{"userpattern"};
  my $wrbtest       = $para->{"wrbtest"};
  my $channel       = $para->{"channel"};
  my $target        = $para->{"target"};
  my $write_count   = $para->{"write"};
  my $read_count    = $para->{"read"};
  my $passwd        = $para->{"passwd"};  

  my $compare;
  my $stop;
   
  if ($para->{"compare"} =~ /enable/i ) {
     $compare = "compare";
  } else {
     $compare = "nocompare";
  }

  if ($para->{"stop-on-error"} =~ /enable/i ) {
     $stop = "on_err";
  } else {
     $stop = "no_on_err";
  }

  my $size          = $para->{"size"};
  my $count         = $para->{"count"};
  my $final_result  = 0;
  my $status;
  my $fc_status;
  my $info;
  my $old_report = {};
  my $new_report = {};

  my $sccli = &sccli_path();
  my $testdevice;
  $testdevice->{path} = $dev;
  $testdevice->{telnet} = Util->encodeAll($passwd);

  if ($selectpattern =~ /user/i) {
      my $ct;
      for ($ct=1; $ct<=$count; $ct++) { 
       print "write read buffer test for user selected pattern begins :"."\n";
 
       # first get all Error information from LESB
       $old_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);  
       
       # my $command = $sccli.$dev." diag buffer-test"." -chan ".$channel." -targ ".$target." -pay ".$userpattern." -size ".$size." -write ".$write_count." -read ".$read_count." -com ".$compare." -stop ".$stop;
      # print $command."\n";
      

      my $part2= " diag buffer-test"." -chan ".$channel." -targ ".$target." -pay ".$userpattern." -size ".$size." -write ".$write_count." -read ".$read_count." -com ".$compare." -stop ".$stop;
      # $status = $this->initWRBTest($command);
      $status = $this->initWRBTest($testdevice, $part2);
      if (!$status) {
          print "failed to start the write read buffer test for pattern ".$userpattern. "\n";
          return (-1);
      } 
      while ( !$final_result ) {
            do {
                ($status, $info) = $this->getWRBTestStatus($para);
                sleep(20);
                # print $status."\n";
                print $info."\n";
            } while (($status !~ "PASS") && ($status !~ "FAIL") && ($status !~ "ERROR") && ($status !~ "ABORT"));
            $final_result = 1;
            print "write read buffer test finished ".$ct." iterations for pattern ".$userpattern."\n"; 

            $new_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);
            
            $fc_status = $this->compFC($new_report, $old_report);
            if ($fc_status =~ /FAIL/i) {
                return (-1);
            } 
      }
      $final_result = 0; #reset for next iteration
    } 
    return (0);
  } 
 
  if ( $selectpattern =~ /critical/i ) {
    print "write read buffer test for critical patterns begins :"."\n";
    my $ct;
    $old_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);
    foreach my $pattern ( @critical_patterns ) { 
         for ($ct=1; $ct<=$count; $ct++) {
           print "write read buffer test for pattern ".$pattern." starts: "."\n"; 
       #    my $command = $sccli.$dev." diag buffer-test"." -chan ".$channel." -targ ".$target." -pay ".$pattern." -size ".$size." -write ".$write_count." -read ".$read_count." -com ".$compare." -stop ".$stop;          
       #    print $command."\n";
           my $part2= " diag buffer-test"." -chan ".$channel." -targ ".$target." -pay ".$pattern." -size ".$size." -write ".$write_count." -read ".$read_count." -com ".$compare." -stop ".$stop;
           $final_result  = 0; 
           $status = $this->initWRBTest($testdevice,$part2);
           if (!$status) {
               print "failed to start the write read buffer test for pattern ".$pattern. "\n";
               return (-1);
           }  
           while ( !$final_result ) {
             do {
                ($status, $info) = $this->getWRBTestStatus($para);
                 # print $info."and I get init status is ".$status."\n";
                 sleep(20);
             } while (($status !~ "PASS") && ($status !~ "FAIL") && ($status !~ "ERROR") && ($status !~ "ABORT"));
             $final_result = 1;
             print "write read buffer test finished ".$ct." iterations for pattern ".$pattern."\n";
             
          }
          $new_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);
           
          $fc_status = $this->compFC($new_report, $old_report);
          # print "I get the true debug status is: ".$fc_status."\n";
          if ($fc_status =~ /FAIL/i) {
               return (-1);
          } 
       }
    }
    return (0);
  }

  if ( $selectpattern =~ /all/i ) {
     print "write read buffer test for all patterns begins :"."\n";
     my $ct;
     $old_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);
     my $all_pattern = $this->getAllPattern();
     my $x;
     my $pattern;
     for ($x=0; $x<= $#$all_pattern;$x++) {
       for ($ct=1; $ct<=$count; $ct++) {
           $pattern = $all_pattern->[$x];
           print "write read buffer test for pattern ".$pattern." starts: "."\n";
           my $part2= " diag buffer-test"." -chan ".$channel." -targ ".$target." -pay ".$pattern." -size ".$size." -write ".$write_count." -read ".$read_count." -com ". $compare." -stop ".$stop;
           $final_result  = 0;
           $status = $this->initWRBTest($testdevice,$part2);
           if (!$status) {
               print "failed to start the write read buffer test for pattern ".$pattern. "\n";
               return (-1);
           }
           while ( !$final_result ) {
             do {
                ($status, $info) = $this->getWRBTestStatus($para);
                 # print $info."and I get init status is ".$status."\n";
                 sleep(20);
             } while (($status !~ "PASS") && ($status !~ "FAIL") && ($status !~ "ERROR") && ($status !~ "ABORT"));
             $final_result = 1;
             print "write read buffer test finished for pattern ".$pattern."\n";

          }
          $new_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);

          $fc_status = $this->compFC($new_report, $old_report);
          # print "I get the true debug status is: ".$fc_status."\n";
          if ($fc_status =~ /FAIL/i) {
               return (-1);
          }
       }
    }

    return (0);
  }
}


##################################################################
#MinnowUtil:initWRBTest
#if initilize test ok then return 1
#else return 0
##################################################################

sub initWRBTest {
  my $this = shift;
  my $device = shift;
  my $option = shift;
  my $TO =120;

  my $sccli = &sccli_path();
  my $w = $device->{path};
  require Agent::3310;

  my ($err,$info, $stderr) = Agent::3310->run_command($device,
                                             "$sccli $w",
                                             $option, $TO);
  
   push @{$info}, $stderr; 
  if (!$err) {
      foreach my $l (@$info) {
        if ($l =~ /Test OK!/i) { 
           return 1;
        }
      }
      return 0;   # do not see OK
  } else {
      return 0;   # some error
  }
  
}

##################################################################
#MinnowUtil::getWRBTestStatus
##################################################################

sub getWRBTestStatus {
     my $this = shift;
     my $para = shift;
     my $option;
     my $TO =60;
     
    my $dev        = $para->{"dev"};
    my $channel    = $para->{"channel"};
    my $target     = $para->{"target"};
    my $sccli = &sccli_path();
    my $option = " diag status -type wrbuf "." -chan ".$channel." -targ ".$target;
    my ($err, $info, $stderr) =(undef, undef, undef); 

    my $device;
    $device->{path} = $dev;
    $device->{telnet} = Util->encodeAll($para->{passwd});

    require Agent::3310;
    ($err, $info, $stderr) = Agent::3310->run_command($device,
                                            "$sccli $dev",  
                                             $option, $TO); 
    push @{$info}, $stderr;    # sometimes testing status is from stderr
    if (!$err) {
        foreach my $l (@$info) {
           # print $l."\n";
           if ($l =~ /completed with no error/i) {
               return ("PASS", $l);
           } elsif ( $l =~ /in progress/i) {
               return ("PROGRESS", "write read buffer test is in progress");
           } elsif ( $l =~ /aborted/i) {
               return ("ABORT", "write read buffer test is aborted");
           } 
        }
        return ("FAIL", "write read buffer test failed");
    } else {
        return ("ERROR", "failed to get the test status");   # some error
    }

}

##################################################################
#MinnowUtil:runLoopTest
##################################################################

sub runLoopTest {
  my $this = shift;
  my $para = shift;
  my $option;
  my $TO =60;
  my @critical_patterns = ("0x7e7e7e7e7e7e7e7e",
        "0xb5b5b5b5b5b5b5b5",
        "0x4a4a4a4a4a4a4a4a",
        "0x7878787878787878",
        "0xe7e7e7e7e7e7e7e7",
        "0xaa55aa55aa55aa55",
        "0x7f7f7f7f7f7f7f7f",
        "0x0f0f0f0f0f0f0f0f",
        "0x00ff00ff00ff00ff",
        "0x1e1e1e1e1e1e1e1e",
        "0x2525252525252525"
  );

  foreach $option (keys(%$para)){
        # print "key is :".$option."\n";
        # print "value is :".$para->{$option}."\n";
  }
  my $dev           = $para->{"dev"};
  my $selectpattern = $para->{"selectpattern"};
  my $userpattern   = $para->{"userpattern"};
  my $looptest      = $para->{"looptest"};
  my $channel       = $para->{"channel"};
  my $mode          = $para->{"mode"};
  my $passwd        = $para->{"passwd"};
   my $compare;
  my $stop;
  
  if ($para->{"compare"} =~ /enable/i ) {
     $compare = "yes";
  } else {
     $compare = "no";
  }

  if ($para->{"stop-on-error"} =~ /enable/i ) {
     $stop = "yes";
  } else {
     $stop = "no";
  }

  my $size          = $para->{"size"};
  my $count         = $para->{"count"};
  my $final_result  = 0;
  my $status;
  my $fc_status;
  my $info;

  my $old_report = {};
  my $new_report = {};

  my $sccli = &sccli_path();

   my $testdevice;
  $testdevice->{path} = $dev;
  $testdevice->{telnet} = Util->encodeAll($passwd);

  if ($selectpattern =~ /user/i) {
      my $ct;
      for ($ct=1; $ct<=$count; $ct++) {
        print "looptest for user selected pattern begins :"."\n";

        # first get all Error information from LESB
        $old_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);

        my $part2= " diag loopback"." channel ".$channel." payload ".$userpattern." size ".$size." mode ".$mode." count ".$count." compare ".$compare." stop-on-error " .$stop; 
         $status = $this->initLoopTest($testdevice, $part2);
        if (!$status) {
          print "failed to start the looptest for pattern ".$userpattern. "\n";
          return (-1);
        }
        while ( !$final_result ) {
            do {
                ($status, $info) = $this->getLoopTestStatus($para);
                sleep(20);
                # print $status."\n";
                print $info."\n";
            } while (($status !~ "PASS") && ($status !~ "FAIL") && ($status !~ "ERROR") && ($status !~ "ABORT"));
            $final_result = 1;
            print "loop test finished ".$ct." iterations for pattern ".$userpattern."\n";

            $new_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);

            $fc_status = $this->compFC($new_report, $old_report);
            if ($fc_status =~ /FAIL/i) {
                return (-1);
            }

        }
        $final_result = 0; #reset for next iteration
     }

     return (0); 
  } 
  if ( $selectpattern =~ /critical/i ) {
      my $ct;
      print "loop test for critical patterns begins :"."\n";
      $old_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);
      foreach my $pattern ( @critical_patterns ) {
          for ($ct=1; $ct<=$count; $ct++) {
           print "looptest for pattern ".$pattern." starts: "."\n";
           $final_result  = 0;

           my $part2= " diag loopback"." channel ".$channel." payload ".$pattern." size ".$size." mode ".$mode." count ".$count." compare ".$compare." stop-on-error ".$stop;
           $status = $this->initLoopTest($testdevice,$part2);
           if (!$status) {
               print "failed to start the loop test for pattern ".$pattern. "\n";
               return (-1);
           }
           while ( !$final_result ) {
             do {
                ($status, $info) = $this->getLoopTestStatus($para);
                sleep(20);
                # print $status."\n";
                print $info."\n";
             } while (($status !~ "PASS") && ($status !~ "FAIL") && ($status !~ "ERROR") && ($status !~ "ABORT"));
             $final_result = 1;
             print "looptest finished ".$ct." iterations for pattern ".$pattern."\n";
          }
          $new_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);

          $fc_status = $this->compFC($new_report, $old_report);
          # print "I get the true debug status is: ".$fc_status."\n";
          if ($fc_status =~ /FAIL/i) {
               return (-1);
          }
        }
      }  
      return (0);
  }
  if ( $selectpattern =~ /all/i ) {
      print "loop test for all patterns begins :"."\n";
      my $ct; 
      $old_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);
      my $all_pattern = $this->getAllPattern();
      my $x;
      my $pattern;
      for ($x=0; $x<= $#$all_pattern;$x++) {
         for ($ct=1; $ct<=$count; $ct++) { 
           $pattern = $all_pattern->[$x];
           print "looptest for pattern ".$pattern." starts: "."\n";
           $final_result  = 0;
           my $part2= " diag loopback"." channel ".$channel." payload ".$pattern." size ".$size." mode ".$mode." count ".$count." compare ".$compare." stop-on-error ".$stop;
           $status = $this->initLoopTest($testdevice,$part2);
           if (!$status) {
               print "failed to start the loop test for pattern ".$pattern. "\n";
               return (-1);
           }
           while ( !$final_result ) {
             do {
                ($status, $info) = $this->getLoopTestStatus($para);
                sleep(20);
                # print $status."\n";
                print $info."\n";
             } while (($status !~ "PASS") && ($status !~ "FAIL") && ($status !~ "ERROR") && ($status !~ "ABORT"));
             $final_result = 1;
             print "looptest finished ".$ct." iterations for pattern ".$pattern."\n";
          }
          $new_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);

          $fc_status = $this->compFC($new_report, $old_report);
          # print "I get the true debug status is: ".$fc_status."\n";
          if ($fc_status =~ /FAIL/i) {
               return (-1);
          }

       } 
     }
     return (0);
  }

}

##################################################################
#MinnowUtil:initLoopTest
#if initilize test ok then return 1
#else return 0
##################################################################
sub initLoopTest {
  my $this = shift;
  my $device = shift;
  my $option = shift;
  my $TO =120;

  my $sccli = &sccli_path();
  my $w = $device->{path};

  require Agent::3310;

  my ($err, $info, $stderr) = Agent::3310->run_command($device,
                                             "$sccli $w",
                                             $option, $TO);

   push @{$info}, $stderr;

  if (!$err) {
      foreach my $l (@$info) {
        if ($l =~ /succeeded/i) {
           return 1;
        }
      }
      return 0;   # do not see OK
  } else {
      return 0;   # some error
  }

}

##################################################################
#MinnowUtil::getLoopTestStatus
##################################################################

sub getLoopTestStatus {
     my $this = shift;
     my $para = shift;
     my $option;
     my $TO =120;

    my $dev        = $para->{"dev"};
    my $channel    = $para->{"channel"};
    my $sccli = &sccli_path();
    my $option = "diag status -type loopback "." -chan ".$channel;
    my ($err, $info, $stderr) =(undef, undef, undef);

    my $device;
    $device->{path} = $dev;
    $device->{telnet} = Util->encodeAll($para->{passwd});

    require Agent::3310;
    ($err, $info, $stderr) = Agent::3310->run_command($device,
                                            "$sccli $dev",
                                             $option, $TO);

    if (!$err) {
        foreach my $l (@$info) {
           # print $l."\n";
          if ( $l =~ /Status/ )  { #note: Capital "S" is important
           if ($l =~ /completed with no error/i) {
               return ("PASS", $l);
           } elsif ( $l =~ /in progress/i) {
               return ("PROGRESS", "looptest is in progress");
           } elsif ( $l =~ /aborted/i) {
               return ("ABORT", "looptest is aborted");
           } elsif ($l =~ /fail/i ) {
               return ("FAIL","looptest failed");
           }
          }
        }
        return ("NO_RESULT_YET", "not finish yet");
    } else {
        return ("ERROR", "failed to get the loop test status");   # some error
    }

}


##################################################################
#MinnowUtil::KillTest
##################################################################

sub runKillTest {
  my $this = shift;
  my $unit = shift;
  my $loop = shift;
  my $settings="update?sysOndgMode=off";
  my $command="sysApplySettings=Apply";
  $this->issueCommand($settings, $command);
  my $settings="update?ondgAbort=Abort";
  my $command="sysApplySettings=Apply";
  $this->issueCommand($settings, $command);
}


##################################################################
#T3Connection::AbortVolumeOperation
##################################################################

sub AbortVolumeOperation {
  my $this = shift;
  my $unit = shift;
  my $vol = shift;
  my $settings="update?unitIndex=$unit".
	       "&volIndex=$vol";
  my $command="volAbort=Abort";
  $this->issueCommand($settings, $command);
}

####################################################################
#MinnowUtil::getFCfromDevice  
####################################################################

sub getFCfromDevice {
    my $this = shift;
    my $device = shift;

    my(%SW, $x , %X, $err);

    my $R = {};

    $err = $this->getTotalFC($device, $R);
    return {} if ($err);
   
    for ($x=1; $x < 7; $x++) {  # reconstruct the key for chan error
        my $key = "|$device|port.$x|3510";
        $X{$key} = $R->{"channel.$x.error.link"}   . "\t" .
                      $R->{"channel.$x.error.signal"} . "\t" .
                      $R->{"channel.$x.error.seq"}    . "\t" .
                      $R->{"channel.$x.error.crc"}    . "\t" .
                      $R->{"channel.$x.error.sync"}   . "\t" .
                      $R->{"channel.$x.error.itw"};
    }

    foreach my $key (sort keys %$R) {
        if ( $key =~ /components\.disk/ ) {
               $X{$key} = $R->{$key};
        } 

    }
   
    return { data => \%X,  hba => {} };

}

####################################################################
#getTotalFC():   get all the error counters including disk and chan
####################################################################

sub getTotalFC {
  # this one is a little different from that in Agent::3310
  my($class, $dev, $rep) = @_;

  my($renv) = System->get_renv();
  my($TO) = $renv->{'timeout.sccli'} || 400;

  my $device = {};

  $device->{path} = $dev;
  my $w = $dev;
  my $sccli = &sccli_path();
  my($err, $com, $chan, $chan0);
  my $chan_type;


  for ($chan0=0; $chan0 < 6; $chan0++) {
    ($err,$com) = Util->run_command("$sccli $w diag error -chan $chan0 -target all", "chan.txt" , $TO);
    return $err if ($err);
    my $chan = $chan0 + 1;

    require Agent::3310;
    Agent::3310->parseChanFC($com, $rep, "channel.$chan.error");

    #check the chan type

    $chan_type=Agent::3310->getChanType($device,$chan0);

    if ($chan_type == "Drive") { # only drive chan can show us the disk statistic data
       Agent::3310->parseDiskFC($com, $rep, $chan); # pass $chan in to construct key
    }

  }
  return undef;
}

sub compFC {
    my ($class, $ndata, $odata) = @_;
    my $rep  = $ndata->{"FC_COUNTERS"};
    my $orep = $odata->{"FC_COUNTERS"};

    my $new = $rep->{data};
    my $old = $orep->{data};

    my $err_count = 0 ;
    foreach my $k (sort keys %$new) { 
        my @n1 = split(/\t/, $new->{$k});
        my @o1 = split(/\t/, $old->{$k});
        
        my $o_crc = $o1[3];
        my $n_crc = $n1[3];

        if ($n_crc > $o_crc) {     
            my $diff = $n_crc-$o_crc;
            my $message; 
            $message = "CRC went up by ".$diff." in $k";
            print $message."\n";   # show err info on GUI
            $err_count++;
        }

        my $o_itw = $o1[5];
        my $n_itw = $n1[5];
  
        if ($n_itw > $o_itw) {
            my $diff = $n_itw-$o_itw;
            my $message; 
            $message = " Invalid TxW went up by ".$diff." in $k";
            print $message."\n";   # show err info on GUI
            $err_count++;
        }

        my $o_sig = $o1[1];
        my $n_sig = $n1[1];
        if ($n_sig > $o_sig) {
           my $diff = $n_sig -$o_sig;
           my $message; 
           $message = " Signal_loss went up by ".$diff." in $k";
           $err_count++; 
        }
    } 
 
    if ($err_count >0) {
        return ("FAIL");
    } else {
        return ("PASS");
    }
}

##################################################################
#MinnowUtil:runEchoTest
##################################################################

sub runEchoTest {
  my $this = shift;
  my $para = shift;
  my $option;
  my $TO =60;
  my @critical_patterns = ("0x7e7e7e7e7e7e7e7e",
        "0xb5b5b5b5b5b5b5b5",
        "0x4a4a4a4a4a4a4a4a",
        "0x7878787878787878",
        "0xe7e7e7e7e7e7e7e7",
        "0xaa55aa55aa55aa55",
        "0x7f7f7f7f7f7f7f7f",
        "0x0f0f0f0f0f0f0f0f",
        "0x00ff00ff00ff00ff",
        "0x1e1e1e1e1e1e1e1e",
        "0x2525252525252525"
  );

#  foreach $option (keys(%$para)){
        # print "key is :".$option."\n";
        # print "value is :".$para->{$option}."\n";
#  }
  my $dev           = $para->{"dev"};
  my $selectpattern = $para->{"selectpattern"};
  my $userpattern   = $para->{"userpattern"};
  my $looptest      = $para->{"echotest"};
  my $channel       = $para->{"channel"};
  my $passwd        = $para->{"passwd"};
  my $compare;
  my $stop;
 
  if ($para->{"compare"} =~ /enable/i ) {
     $compare = "yes";
  } else {
     $compare = "no";
  }

  if ($para->{"stop-on-error"} =~ /enable/i ) {
     $stop = "yes";
  } else {
     $stop = "no";
  }

  my $size          = $para->{"size"};
  my $count         = $para->{"count"};
  my $final_result  = 0;
  my $status;
  my $fc_status;
  my $info;

  my $old_report = {};
  my $new_report = {};

  my $sccli = &sccli_path();
  my $testdevice;
  $testdevice->{path} = $dev;
  $testdevice->{telnet} = Util->encodeAll($passwd);

  if ($selectpattern =~ /user/i) {
      
      print "echo test for user selected pattern begins :"."\n";
      my $ct;
      for ($ct=1; $ct<=$count; $ct++) {
         # first get all Error information from LESB
         $old_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);

         my $part2= "diag echo"." channel ".$channel." payload ".$userpattern." size ".$size." count ".$count." compare ".$compare." stop-on-error ".$stop;
         $status = $this->initEchoTest($testdevice,$part2);

         if (!$status) {
            print "failed to start the echotest for pattern ".$userpattern. "\n";
            return (-1);
         }
         while ( !$final_result ) {
            do {
                ($status, $info) = $this->getEchoTestStatus($para);
                sleep(20);
                # print $status."\n";
                print $info."\n";
            } while (($status !~ "PASS") && ($status !~ "FAIL") && ($status !~ "ERROR") && ($status !~ "ABORT"));
            $final_result = 1;
            print "Echo test finished ".$ct." iterations for pattern ".$userpattern."\n";

            $new_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);

            $fc_status = $this->compFC($new_report, $old_report);
            if ($fc_status =~ /FAIL/i) {
                return (-1);
            }
        }
        $final_result = 0; #reset for next iteration
     }

     return (0);
  }
  if ( $selectpattern =~ /critical/i ) {
      print "Echo test for critical patterns begins :"."\n";
      my $ct;
      $old_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);
      foreach my $pattern ( @critical_patterns ) {
         for ($ct=1; $ct<=$count; $ct++) {
           print "Echo test for pattern ".$pattern." starts: "."\n";
           my $part2= " diag echo"." channel ".$channel." payload ".$pattern." size ".$size." count ".$count." compare ".$compare." stop-on-error ".$stop;
           $final_result  = 0;
           $status = $this->initEchoTest($testdevice,$part2);
           if (!$status) {
               print "failed to start the echo test for pattern ".$pattern. "\n";
               return (-1);
           }
           while ( !$final_result ) {
             do {
                ($status, $info) = $this->getEchoTestStatus($para);
                sleep(20);
                # print $status."\n";
                print $info."\n";
             } while (($status !~ "PASS") && ($status !~ "FAIL") && ($status !~ "ERROR") && ($status !~ "ABORT"));
             $final_result = 1;
             print "Echo test finished ".$ct." iterations for pattern ".$pattern."\n";
          }
          $new_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);

          $fc_status = $this->compFC($new_report, $old_report);
          # print "I get the true debug status is: ".$fc_status."\n";
          if ($fc_status =~ /FAIL/i) {
               return (-1);
          }
        }
     } 
     return (0);
  }
  if ( $selectpattern =~ /all/i ) {
      print "Echo test for all patterns begins :"."\n";
      my $ct;
      $old_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);
      my $all_pattern = $this->getAllPattern();
      my $x;
      my $pattern;

      for ($x=0; $x<= $#$all_pattern;$x++) {
        for ($ct=1; $ct<=$count; $ct++) {
           $pattern = $all_pattern->[$x];
           print "Echo test for pattern ".$pattern." starts: "."\n";
           my $part2= " diag echo"." channel ".$channel." payload ".$pattern." size ".$size." count ".$count." compare ".$compare." stop-on-error ".$stop;
           $final_result  = 0;
           $status = $this->initEchoTest($testdevice,$part2);
           if (!$status) {
               print "failed to start the echo test for pattern ".$pattern. "\n";
               return (-1);
           }
           while ( !$final_result ) {
             do {
                ($status, $info) = $this->getEchoTestStatus($para);
                sleep(20);
                # print $status."\n";
                print $info."\n";
             } while (($status !~ "PASS") && ($status !~ "FAIL") && ($status !~ "ERROR") && ($status !~ "ABORT"));
             $final_result = 1;
             print "Echo test finished ".$ct." iterations for pattern ".$pattern."\n";
          }
          $new_report->{"FC_COUNTERS"} = $this->getFCfromDevice($dev);

          $fc_status = $this->compFC($new_report, $old_report);
          # print "I get the true debug status is: ".$fc_status."\n";
          if ($fc_status =~ /FAIL/i) {
               return (-1);
          }
       }
      }
      return (0);
  }

}


##################################################################
#MinnowUtil:initEchoTest
#if initilize test ok then return 1
#else return 0
##################################################################

sub initEchoTest {
  my $this = shift;
  my $device = shift;
  my $option = shift;

  my $TO =120;

  my $sccli = &sccli_path();
  my $w = $device->{path};

  require Agent::3310;

  my ($err,$info, $stderr) = Agent::3310->run_command($device,
                                             "$sccli $w",
                                             $option, $TO);

  push @{$info},$stderr;
  if (!$err) {
      foreach my $l (@$info) {
        if ($l =~ /succeeded/i) {
           return 1;
        }
      }
      return 0;   # do not see OK
  } else {
      return 0;   # some error
  }

}

##################################################################
#MinnowUtil::getEchoTestStatus
##################################################################

sub getEchoTestStatus {
     my $this = shift;
     my $para = shift;
     my $option;
     my $TO =120;

    my $dev        = $para->{"dev"};
    my $channel    = $para->{"channel"};
    my $option = " diag status -type echo "." -chan ".$channel;
    my ($err, $info, $stderr) =(undef, undef, undef);

    my $device;
    $device->{path} = $dev;
    $device->{telnet} = Util->encodeAll($para->{passwd});

    my $sccli = &sccli_path();
    require Agent::3310;
    ($err, $info, $stderr) = Agent::3310->run_command($device,
                                            "$sccli $dev",
                                             $option, $TO);

    push @{$info},$stderr;

    if (!$err) {
        foreach my $l (@$info) {
            # print $l."\n";
          if ( $l =~ /Status/ )  { #note: Capital "S" is important
           if ($l =~ /completed with no error/i) {
               return ("PASS", $l);
           } elsif ( $l =~ /in progress/i) {
               return ("PROGRESS", "Echo test is in progress");
           } elsif ( $l =~ /aborted/i) {
               return ("ABORT", "Echo test is aborted");
           } elsif ($l =~ /fail/i ) {
               return ("FAIL","Echotest failed");
           }
          }
        }
        return ("NO_RESULT_YET", "not finish yet");
    } else {
        return ("ERROR", "failed to get the echo test status");   # some error
    }

}

##################################################################
#MinnowUtil::runLoopMapTest ()
##################################################################

sub runLoopMapTest {
     my $this = shift;
     my $para = shift;
     my $option;
     my $TO =60;

     my $dev           = $para->{"dev"};
     my $channel       = $para->{"channel"};

     my $sccli = &sccli_path();
     # my $command = $sccli.$dev." show loop-map channel ".$channel; 
     # my ($err, $info) = Util->run_command($command,"loopmap.txt",$TO);


     my $option = " show loop-map channel ".$channel;
     my ($err, $info, $stderr) =(undef, undef, undef);
     my $device;
     $device->{path} = $dev;
     $device->{telnet} = Util->encodeAll($para->{passwd});

     require Agent::3310;
     ($err, $info, $stderr) = Agent::3310->run_command($device,
                                            "$sccli $dev",
                                             $option, $TO);

     if ($err) {
         return (-1); 
     } elsif ($#$info <= 0) {
         print " Not valid ses target, please check whether the controller is shutdown. If so, please choose another channel as ses target and re-run the test. If you still do not get map information, please check your system setup"."\n";
         return (-1);
     }  else {
         foreach my $l (@$info) {
            print $l."\n";
         }
         return (0);
     } 
}

##################################################################
#MinnowUtil::runShowBypassTest ()
##################################################################

sub runShowBypassTest {
     my $this = shift;
     my $para = shift;
     my $option;
     my $TO =60;

     my $dev           = $para->{"dev"};
     my $channel       = $para->{"channel"};
     my $loop          = $para->{"loop"};

     my $sccli = &sccli_path();
     my $command = $sccli.$dev." show bypass device channel ".$channel." loop ".$loop;
     my ($err, $info) = Util->run_command($command,"bypass.txt",$TO);
     if ($err) {
         return (-1);
     } else {
         foreach my $l (@$info) {
             print $l."\n";
            if ($l =~ /No valid device/) {
              print "The controller may have been shut-down, please choose another channel option for testing, If you still can not get the bypass information, please check your system setup"."\n";
             return (-1);
            }
         }
         return (0);
     }
}

##################################################################
#MinnowUtil::runShowBypassSfpTest ()
##################################################################

sub runShowBypassSfpTest {
     my $this = shift;
     my $para = shift;
     my $option;
     my $TO =60;

     my $dev           = $para->{"dev"};
     my $channel       = $para->{"channel"};
     my $loop          = $para->{"loop"};

     my $sccli = &sccli_path();
     my $command = $sccli.$dev." show bypass sfp channel ".$channel." loop ".$loop;
     my ($err, $info) = Util->run_command($command,"bypasssfp.txt",$TO);
     if ($err) {
         return (-1);
     } else {
         foreach my $l (@$info) {
             print $l."\n";
            if ($l =~ /No valid device/) {
              print "The controller may have been shut-down, please choose another channel option for testing, If you still can not get the bypass information, please check your system setup"."\n";
             return (-1);
            }
         }
         return (0);
     }
}

##################################################################
#MinnowUtil::runDiagBypassSfpTest ()
##################################################################

sub runDiagBypassSfpTest {
     my $this = shift;
     my $para = shift;
     my $option;
     my $TO =60;

     my $dev           = $para->{"dev"};
     my $channel       = $para->{"channel"};
     my $loop          = $para->{"loop"};
     my $eid           = $para->{"enclosure"};
     my $port          = $para->{"port"};

     my $data ="yes";

     my $sccli = &sccli_path();
     my $command = $sccli.$dev." diag bypass sfp channel ".$channel." loop ".$loop." enclosure ".$eid." port ".$port;
     my ($err, $info) = Util->run_command($command,"diagbypasssfp.txt",$TO, 
                                          { data => $data, }    );
     if ($err) {
         return (-1);
     } else {
         foreach my $l (@$info) {
             print $l."\n";
            if ($l =~ /No valid device/) {
          print "The controller may have been shut-down, please choose another channel option for testing, If you still can not succeed the test, please check your system setup"."\n";
             return (-1);
            }
         }
         return (0);
     }
}


######################################################################

sub getAllPattern {
     my $this = shift;
    my $all_pattern = [ "0x7e7e7e7e7e7e7e7e",
        "0xb5b5b5b5b5b5b5b5",
        "0x4a4a4a4a4a4a4a4a",
        "0x7878787878787878",
        "0xe7e7e7e7e7e7e7e7",
        "0xaa55aa55aa55aa55",
        "0x7f7f7f7f7f7f7f7f",
        "0x0f0f0f0f0f0f0f0f",
        "0x00ff00ff00ff00ff",
        "0x1e1e1e1e1e1e1e1e",
        "0x2525252525252525",
        "0xffffffffffffffff",
        "0xfefefefefefefefe",
        "0xfdfdfdfdfdfdfdfd",
        "0xfcfcfcfcfcfcfcfc",
        "0xfbfbfbfbfbfbfbfb",
        "0xfafafafafafafafa",
        "0xf9f9f9f9f9f9f9f9",
        "0xf8f8f8f8f8f8f8f8",
        "0xf7f7f7f7f7f7f7f7",
        "0xf6f6f6f6f6f6f6f6",
        "0xf5f5f5f5f5f5f5f5",
        "0xf4f4f4f4f4f4f4f4",
        "0xf3f3f3f3f3f3f3f3",
        "0xf2f2f2f2f2f2f2f2",
        "0xf1f1f1f1f1f1f1f1",
        "0xf0f0f0f0f0f0f0f0",
        "0x7d7d7d7d7d7d7d7d",
        "0x7c7c7c7c7c7c7c7c",
        "0x7b7b7b7b7b7b7b7b",
        "0x7a7a7a7a7a7a7a7a",
        "0x7979797979797979",
        "0x7777777777777777",
        "0x7676767676767676",
        "0x7575757575757575",
        "0x7474747474747474",
        "0x7373737373737373",
        "0x7272727272727272",
        "0x7171717171717171",
        "0x7070707070707070",
        "0xefefefefefefefef",
        "0xeeeeeeeeeeeeeeee",
        "0xedededededededed",
        "0xecececececececec",
        "0xebebebebebebebeb",
        "0xeaeaeaeaeaeaeaea",
        "0xe9e9e9e9e9e9e9e9",
        "0xe8e8e8e8e8e8e8e8",
        "0xe6e6e6e6e6e6e6e6",
        "0xe5e5e5e5e5e5e5e5",
        "0xe4e4e4e4e4e4e4e4",
        "0xe3e3e3e3e3e3e3e3",
        "0x3d3d3d3d3d3d3d3d",
        "0x3c3c3c3c3c3c3c3c",
        "0x3b3b3b3b3b3b3b3b",
        "0x3a3a3a3a3a3a3a3a",
        "0x3939393939393939",
        "0x3838383838383838",
        "0x3737373737373737",
        "0x3636363636363636",
        "0x3535353535353535",
        "0x3434343434343434",
        "0x3333333333333333",
        "0x3232323232323232",
        "0x3131313131313131",
        "0x3030303030303030",
        "0xafafafafafafafaf",
        "0xaeaeaeaeaeaeaeae",
        "0xadadadadadadadad",
        "0xacacacacacacacac",
        "0xabababababababab",
        "0xaaaaaaaaaaaaaaaa",
        "0xa9a9a9a9a9a9a9a9",
        "0xa8a8a8a8a8a8a8a8",
        "0xa7a7a7a7a7a7a7a7",
        "0xa6a6a6a6a6a6a6a6",
        "0xa5a5a5a5a5a5a5a5",
        "0xa4a4a4a4a4a4a4a4",
        "0xa3a3a3a3a3a3a3a3",
        "0xa2a2a2a2a2a2a2a2",
        "0xa1a1a1a1a1a1a1a1",
        "0xa0a0a0a0a0a0a0a0",
        "0x2f2f2f2f2f2f2f2f",
        "0x2e2e2e2e2e2e2e2e",
        "0x2d2d2d2d2d2d2d2d",
        "0x2c2c2c2c2c2c2c2c",
        "0x2b2b2b2b2b2b2b2b",
        "0x2a2a2a2a2a2a2a2a",
        "0x2929292929292929",
        "0x2828282828282828",
        "0x2727272727272727",
        "0x2626262626262626",
        "0x2424242424242424",
        "0x2323232323232323",
        "0x2222222222222222",
        "0x2121212121212121",
        "0x2020202020202020",
        "0x9f9f9f9f9f9f9f9f",
        "0x9e9e9e9e9e9e9e9e",
        "0x9d9d9d9d9d9d9d9d",
        "0x9c9c9c9c9c9c9c9c",
        "0x9b9b9b9b9b9b9b9b",
        "0x9a9a9a9a9a9a9a9a",
        "0x9999999999999999",
        "0x9898989898989898",
        "0x9797979797979797",
        "0x9696969696969696",
        "0x9595959595959595",
        "0x9494949494949494",
        "0x9393939393939393",
        "0x9292929292929292",
        "0x9191919191919191",
        "0x9090909090909090",
        "0x1f1f1f1f1f1f1f1f",
        "0x1d1d1d1d1d1d1d1d",
        "0x1c1c1c1c1c1c1c1c",
        "0x1b1b1b1b1b1b1b1b",
        "0x1a1a1a1a1a1a1a1a",
        "0x1919191919191919",
        "0x1818181818181818",
        "0x1717171717171717",
        "0x1616161616161616",
        "0x1515151515151515",
        "0x1414141414141414",
        "0x1313131313131313",
        "0x1212121212121212",
        "0x1111111111111111",
        "0x1010101010101010",
        "0x8f8f8f8f8f8f8f8f",
        "0x8e8e8e8e8e8e8e8e",
        "0x8d8d8d8d8d8d8d8d",
        "0x8c8c8c8c8c8c8c8c",
        "0x8b8b8b8b8b8b8b8b",
        "0x8a8a8a8a8a8a8a8a",
        "0x8989898989898989",
        "0x8888888888888888",
        "0x8787878787878787",
        "0x8686868686868686",
        "0x8585858585858585",
        "0x8484848484848484",
        "0x8383838383838383",
        "0x8282828282828282",
        "0x8181818181818181",
        "0x8080808080808080",
        "0x0e0e0e0e0e0e0e0e",
        "0x0d0d0d0d0d0d0d0d",
        "0x0c0c0c0c0c0c0c0c",
        "0x0b0b0b0b0b0b0b0b",
        "0x0a0a0a0a0a0a0a0a",
        "0x0909090909090909",
        "0x0808080808080808",
        "0x0707070707070707",
        "0x0606060606060606",
        "0x0505050505050505",
        "0x0404040404040404",
        "0x0303030303030303",
        "0x0202020202020202",
        "0x0101010101010101",
        "0x0000000000000000"
     ];
     return $all_pattern;

}

1;

