#!/usr/bin/perl

%AI_PAGE;
%AO_PAGE;
%DI_PAGE;
%DO_PAGE;
%DRV_NAME;
%MAJOR_NUM;

@MORE_POLL_DEVICE = ( "PCI7200","PCI7300A","PCI7300B","PCI9111","PCI9112","PCI9113","PCI9114","PCI9116","PCI9118","PCI9812" );
$MEM_MGR_LOAD;
$CARD_FOUND;
$DRIVER_PATH;
$DRIVER_DIR;
$CONF_FILE_NAME; 
$INSMOD_COMMAND;

$KERNEL_VER;

if( open(ker_info, "</proc/sys/kernel/version" ) ){
    my $kernel_descrip = <ker_info>;
    ($number, $var1, $var2, $rest) = $kernel_descrip =~ /(\S+)\s+(\S+)\s+(\S+)\s+(.*)/;  
    close ker_info;
    if( $var1 eq "SMP" ){
        print("\nThe SMP information is got from /proc/sys/kernel/version !\n\n"); 
        print("However, the modules are designed based on Uni-Processor kernel,\n");
        print("and the modules cannot work well in SMP kernel\n");
         
        print("Do you continue ? (Y/N)");
        my $input_char = <STDIN>;
        chop( $input_char );
        if( $input_char eq "Y" ){}
        elsif( $input_char eq "y" ){}
        else {exit 0}; 
    }
}
else{
    print("The modules in this directory are compiled for Uni-Processor kernel\n");
    print("However, we can't access the kernel information from /proc/sys/kernel.\n");
    print("Do you continue ? (Y/N)");
    my $input_char = <STDIN>;
    chop( $input_char );
    if( $input_char eq "Y" ){}
    elsif( $input_char eq "y" ){}
    else {exit 0}; 
}

############### check the kernel version 

if( open(ker_info, "</proc/sys/kernel/osrelease" ) ){
    my $kernel_version = <ker_info>;
    ($num1, $num2, $num3, $rest) = $kernel_version =~ /(\d+).(\d+).(\d+)(.*)/;  
    close ker_info;

    if( $num1 == 2 ){
        if( $num2 != 2 && $num2 != 4 ){
    	    print(" The current Pdask/X only supports 2.2.12, 2.2.14, 2.2.16, 2.2.18 and 2.4.2 Linux kernel\n" );
    	    exit 0;
        }
    }else{
        print(" The current Pdask/X only supports 2.2.12, 2.2.14, 2.2.16, 2.2.18 and 2.4.2 Linux kernel\n" );
        print(" Please check the kernel vesion\n" );
        exit 0;
    }

#    if( $num3 >= 18 ){
#    	$DRIVER_DIR = "/drivers-2.2.18/";
#    }else{
#    	$DRIVER_DIR = "/drivers/";
#    }

    $DRIVER_DIR = "/drivers/";
}

############### continue the old operation 

if(  $ARGV[0] eq "" ){
  $CONF_FILE_NAME = "<pcidask.conf";
}
else{
  if( $ARGV[0] =~ /\/$/){
    ($DRIVER_PATH) = $ARGV[0] =~ /(\S+)\/$/;
  }else{
    $DRIVER_PATH = $ARGV[0];  
  }
  $CONF_FILE_NAME = "<" . $DRIVER_PATH . "/drivers/pcidask.conf";   
}

if( ! open(DaskConf, $CONF_FILE_NAME) ){
    my $ERR_MSG; 
    if( $DRIVER_PATH eq "" ){
      $ERR_MSG = "ADLInk module installation: can't open pcidask.conf\n";
      print("$ERR_MSG \t\t\t\t\t\tPress ENTER for exit:");
    }else{
      $ERR_MSG = "ADLInk module installation: can't open " . $DRIVER_PATH . "/drivers/pcidask.conf\n";
      print("$ERR_MSG \t\t\t\t\t\tPress ENTER to continue:");
    }
    my $temp_char = <STDIN>;
    exit 0;
} 

for( $count = 0 ; $count < 4; $count ++ ){
    $line = <DaskConf>;
}

#======================================================================
# read pcidask.conf
while (<DaskConf>){
        chop();
        ($card_type,$cards,$ai_page,$ao_page,$di_page,$do_page) = /(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/;
        ($drv_name) = $card_type =~ /PCI(\w+)/;
        $drv_name =~ tr/A-Z/a-z/;
        $DRV_NAME{$card_type}= $drv_name;
        $CARDS{$card_type}= $cards;
        $AI_PAGE{$card_type}= ($ai_page << 2);
        $AO_PAGE{$card_type}= ($ao_page << 2);
        $DI_PAGE{$card_type}= ($di_page << 2);
        $DO_PAGE{$card_type}= ($do_page << 2);
    }
close DaskConf;


#======================================================================
# copy the 9116.rbf 

if( ! -d "/etc/pdask" ){
  `mkdir -p /etc/pdask/fw`;
}

if( ! -d "/etc/pdask/fw" ){
  `mkdir /etc/pdask/fw`;
}

if( $DRIVER_PATH ne "" ){ 
   $INSMOD_COMMAND ="cp -f " . $DRIVER_PATH . "/drivers/9116.rbf /etc/pdask/fw";
}else{
   $INSMOD_COMMAND ="cp -f ../drivers/9116.rbf /etc/pdask/fw";
}
`$INSMOD_COMMAND`;
#======================================================================
# copy the libpci_dask.so to /usr/lib
if( $DRIVER_PATH ne "" ){ 
   $INSMOD_COMMAND ="cp -f " . $DRIVER_PATH . "/lib/libpci_dask.so /usr/lib";
}else{
   $INSMOD_COMMAND ="cp -f ../lib/libpci_dask.so /usr/lib";
}
`$INSMOD_COMMAND`;

#======================================================================
# card_found check
$CARD_FOUND = 0;
foreach $cardtype (keys(%CARDS)){
   if( $CARDS{$cardtype} > 0 ){
      $CARD_FOUND = 1;
      last;
   }
}

if( $CARD_FOUND == 0 ){
    print(" No PCIDASK adapter in 'pcidask.conf' , you need configure the adapters \n with dask_conf utility \n");
    exit 0;
}
#======================================================================
#insert Adl_Memory_Manager module
$MEM_MGR_LOAD = 0;

foreach $cardtype (keys(%DRV_NAME)){
   foreach $MORE_POLL_DEVICE (@MORE_POLL_DEVICE){
      if( $cardtype eq $MORE_POLL_DEVICE ){
         $MEM_MGR_LOAD = 1;
         last;
      }
   }
   if( $MEM_MGR_LOAD == 1 ){
      last;
   }
}


if( $DRIVER_PATH ne "" ){ 
  $DRIVER_PATH = $DRIVER_PATH . $DRIVER_DIR;

}

if( $MEM_MGR_LOAD == 1 ){
    if( $DRIVER_PATH ne "" ){ 
      $INSMOD_COMMAND = "insmod -f " . $DRIVER_PATH . "/adl_mem_mgr.o";
    }else{
      $INSMOD_COMMAND = "insmod -f adl_mem_mgr.o";
    }
    `$INSMOD_COMMAND`;
}

#======================================================================
#insert the pcidask module
foreach $cardtype (keys(%DRV_NAME)){
  my $BUFSIZE_NEED = 0;
  my $drv_name = "p" . $DRV_NAME{$cardtype} . ".o";

# check the BufSize needed
   foreach $MORE_POLL_DEVICE (@MORE_POLL_DEVICE){
      if( $cardtype eq $MORE_POLL_DEVICE ){
         $BUFSIZE_NEED = 1; # some adapter need AI, AO, DI, or DO , ie. BufSize is needed
         last;
      }
   }

   if( $BUFSIZE_NEED == 1 ){
    print(" insmod -f $drv_name \n");
    if( $DRIVER_PATH ne "" ){ 
      $INSMOD_COMMAND ="insmod -f " . $DRIVER_PATH . $drv_name . " BufSize=$AI_PAGE{$cardtype},$AO_PAGE{$cardtype},$DI_PAGE{$cardtype},$DO_PAGE{$cardtype}";
    }else{
      $INSMOD_COMMAND = "insmod -f " . $drv_name . " BufSize=$AI_PAGE{$cardtype},$AO_PAGE{$cardtype},$DI_PAGE{$cardtype},$DO_PAGE{$cardtype}";
    }
    `$INSMOD_COMMAND`;
   }else{
    print(" insmod -f $drv_name \n");
    if( $DRIVER_PATH ne "" ){ 
      $INSMOD_COMMAND ="insmod -f " . $DRIVER_PATH . $drv_name;
    }else{
      $INSMOD_COMMAND = "insmod -f " . $drv_name;
    }
    `$INSMOD_COMMAND`;
   }
}

# extract major number for devices
open (MODULE_LIST, "</proc/devices") || die "can't open /proc/devices";

while (<MODULE_LIST>){
  ($major,$d)=/(\d+)\s(\w+)/;
  next if !$major;
  $MAJOR_NUM{$d}=$major;
}

close MODULE_LIST;

#======================================================================
# remove /dev/device_node and make new node
foreach $cardtype (keys(%DRV_NAME)){
  for( $count=0; $count< $CARDS{$cardtype}; $count++ ){
      my $card_node = $cardtype . "W" . $count;
      my $driver_name = "p" . $DRV_NAME{$cardtype};
      if( $MAJOR_NUM{$driver_name} != "" ){
           if( -e "/dev/$card_node" ){
               unlink "/dev/$card_node";
           }
          `mknod /dev/$card_node c $MAJOR_NUM{$driver_name} $count`;
          print(" make character device node '/dev/$card_node' for $cardtype \n");
          `chmod a+rw /dev/$card_node`;
      }
  }
}


exit 0;










































