Re: Panic with amr and 5.4-PRERELEASE

From: Philippe PEGON <Philippe.Pegon_at_crc.u-strasbg.fr>
Date: Sat, 12 Mar 2005 11:54:52 +0100
My first attachment did not pass.

amrstat.c :

/* amrstat.c 2002/04/10
  *
  * Author: Pierre David <Pierre.David_at_crc.u-strasbg.fr>
  */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>

#include <machine/param.h>

#include "/usr/src/sys/dev/amr/amr_compat.h"
#include "/usr/src/sys/dev/amr/amrreg.h"
#include "/usr/src/sys/dev/amr/amrio.h"

#define NATTEMPTS       5
#define SLEEPTIME       100000          /* microseconds */

int nattempts = NATTEMPTS ;             /* # of attempts before giving up */
int sleeptime = SLEEPTIME ;             /* between attempts, in ms */

/*
  * Include lookup tables, and a function to match a code to a string.
  *
  * XXX
  * Lookup tables cannot be included, since they require symbols from
  * amrreg.h which need in turn the _KERNEL define.
  */

/* #define AMR_DEFINE_TABLES */
/* #include "/usr/src/sys/dev/amr/amr_tables.h" */

/*
  * Offsets in an amr_user_ioctl.au_cmd [] array
  * See amrio.h
  */

#define MB_COMMAND      0
#define MB_CHANNEL      1
#define MB_PARAM        2
#define MB_PAD          3
#define MB_DRIVE        4

#define FIRMWARE_40LD   1
#define FIRMWARE_8LD    2

#define NTAB(tab)       (sizeof tab / sizeof tab [0])

int amr_enquiry (int fd, size_t bufsize, void *buffer, u_int8_t cmd, 
u_int8_t cmdsub, u_int8_t cmdqual)
{
     struct amr_user_ioctl am ;
     int r, i ;

     am.au_cmd [MB_COMMAND] = cmd ;
     am.au_cmd [MB_CHANNEL] = cmdsub ;
     am.au_cmd [MB_PARAM] = cmdqual ;
     am.au_cmd [MB_PAD] = 0 ;
     am.au_cmd [MB_DRIVE] = 0 ;

     am.au_buffer = buffer ;
     am.au_length = bufsize ;
     am.au_direction = AMR_IO_READ ;
     am.au_status = 0 ;

     i = 0 ;
     r = -1 ;
     while (i < nattempts && r == -1)
     {
         r = ioctl (fd, AMR_IO_COMMAND, &am) ;
         if (r == -1)
         {
             if (errno != EBUSY)
             {
                 perror ("ioctl enquiry") ;
                 exit (1) ;
             }
             else usleep (sleeptime) ;
         }
         i++ ;
     }
     return am.au_status ;
}

void usage (void)
{
     fprintf (stderr, "usage: amstat [-v][-f spec][-a #attempts][-t 
time][-g][-l lvol]\n") ;
     exit (1) ;
}

/******************************************************************************
  * Card description
  */

int describe_card (int fd, int verbosity, int globalparam)
{
     int r ;
     char buffer [2048] ;
     struct amr_enquiry *ae ;
     int cardtype ;

     /*
      * Try the 40LD firmware interface
      */

     r = amr_enquiry (fd, sizeof buffer, buffer,
                         AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0) ;
     if (r == AMR_STATUS_SUCCESS)
     {
         struct amr_prodinfo *ap ;

         if (globalparam)
         {
             ap = (struct amr_prodinfo *) buffer ;
             printf ("Product =\t<%.80s>\n",     ap->ap_product) ;
             printf ("Firmware =\t%.16s\n",      ap->ap_firmware) ;
             printf ("BIOS =\t%.16s\n",          ap->ap_bios) ;
             printf ("SCSI Channels =\t%d\n",    ap->ap_nschan) ;
             printf ("Fibre Loops =\t%d\n",      ap->ap_fcloops) ;
             printf ("Memory size =\t%d MB\n",   ap->ap_memsize) ;
             if (verbosity >= 1)
             {
                 printf ("Ioctl = %d (%s)\n",    FIRMWARE_40LD, "40LD") ;
                 printf ("Signature =\t0x%08x\n", ap->ap_signature) ;
                 printf ("Configsig =\t0x%08x\n", ap->ap_configsig) ;
                 printf ("Subsystem =\t0x%04x\n", ap->ap_subsystem) ;
                 printf ("Subvendor =\t0x%04x\n", ap->ap_subvendor) ;
                 printf ("Notify counters =\t%d\n", ap->ap_numnotifyctr) ;
             }
         }

         return FIRMWARE_40LD ;
     }

     /*
      * Try the 8LD firmware interface
      */

     r = amr_enquiry (fd, sizeof buffer, buffer, AMR_CMD_EXT_ENQUIRY2, 
0, 0) ;
     ae = (struct amr_enquiry *) buffer ;
     if (r == AMR_STATUS_SUCCESS)
     {
         cardtype = ae->ae_signature ;
     }
     else
     {
         r = amr_enquiry (fd, 2048, buffer, AMR_CMD_ENQUIRY, 0, 0) ;
         cardtype = 0 ;
     }

     if (r == AMR_STATUS_SUCCESS)
     {
         if (globalparam)
         {
             char *product ;
             char bios [100], firmware [100] ;
             int i ;

             static struct {
                 char *product ;
                 int signature ;
             } prodtable [] = {
                 "Series 431",                   AMR_SIG_431,
                 "Series 438",                   AMR_SIG_438,
                 "Series 762",                   AMR_SIG_762,
                 "Integrated HP NetRAID (T5)",   AMR_SIG_T5,
                 "Series 466",                   AMR_SIG_466,
                 "Series 467",                   AMR_SIG_467,
                 "Integrated HP NetRAID (T7)",   AMR_SIG_T7,
                 "Series 490",                   AMR_SIG_490,
             } ;

             for (i = 0 ; i < NTAB (prodtable) ; i++)
             {
                 if (cardtype == prodtable [i].signature)
                 {
                     product = prodtable [i].product ;
                     break ;
                 }
             }
             if (product == NULL)
                 product = "unknown card signature" ;

             /*
              * HP NetRaid controllers have a special encoding of the 
firmware and
              * BIOS versions. The AMI version seems to have it as 
strings whereas
              * the HP version does it with a leading uppercase 
character and two
              * binary numbers.
              */

             if(ae->ae_adapter.aa_firmware[2] >= 'A' &&
                ae->ae_adapter.aa_firmware[2] <= 'Z' &&
                ae->ae_adapter.aa_firmware[1] <  ' ' &&
                ae->ae_adapter.aa_firmware[0] <  ' ' &&
                ae->ae_adapter.aa_bios[2] >= 'A'     &&
                ae->ae_adapter.aa_bios[2] <= 'Z'     &&
                ae->ae_adapter.aa_bios[1] <  ' '     &&
                ae->ae_adapter.aa_bios[0] <  ' ') {

                 /* looks like we have an HP NetRaid version of the 
MegaRaid */

                 if(cardtype == AMR_SIG_438)
                 {
                     /* the AMI 438 is a NetRaid 3si in HP-land */
                     product = "HP NetRaid 3si";
                 }

                 sprintf (firmware, "%c.%02d.%02d",
                               ae->ae_adapter.aa_firmware[2],
                               ae->ae_adapter.aa_firmware[1],
                               ae->ae_adapter.aa_firmware[0]) ;
                 sprintf (bios, "%c.%02d.%02d",
                               ae->ae_adapter.aa_bios[2],
                               ae->ae_adapter.aa_bios[1],
                               ae->ae_adapter.aa_bios[0]) ;
             } else {
                 sprintf (firmware, "%.4s", ae->ae_adapter.aa_firmware) ;
                 sprintf (bios, "%.4s", ae->ae_adapter.aa_bios) ;
             }

             printf ("Ioctl = %d (%s)\n",        FIRMWARE_8LD, "8LD") ;
             printf ("Product =\t<%s>\n", product) ;
             printf ("Firmware =\t%s\n", firmware) ;
             printf ("BIOS =\t%s\n", bios) ;
             /* printf ("SCSI Channels =\t%d\n", ae->ae_nschan) ; */
             /* printf ("Fibre Loops =\t%d\n", ae->ae_fcloops) ; */
             printf ("Memory size =\t%d MB\n", 
ae->ae_adapter.aa_memorysize) ;
             /* printf ("Notify counters =\t%d\n", ae->ae_numnotifyctr) ; */
         }
         return FIRMWARE_8LD ;
     }

     /*
      * Neither firmware interface succeeded. Abort.
      */

     fprintf (stderr, "Firmware interface not supported\n") ;
     exit (1) ;

}

/******************************************************************************
  * Logical volumes
  */

void describe_one_volume (int ldrv, int verbosity,
                         u_int32_t size, u_int8_t state, u_int8_t prop)
{
     float szgb ;
     int i ;
     int raid_level ;
     char propstr [2000] ;
     char *statestr ;

     static struct {
         int code ;
         char *ifyes, *ifno ;
     } proptable [] = {
         AMR_DRV_WRITEBACK, "writeback", "write-through",
         AMR_DRV_READHEAD, "read-ahead", "no-read-ahead",
         AMR_DRV_ADAPTIVE, "adaptative-io", "no-adaptative-io",
     } ;

     static struct {
         int code ;
         char *status ;
     } statetable [] = {
         AMR_DRV_OFFLINE,        "offline",
         AMR_DRV_DEGRADED,       "degraded",
         AMR_DRV_OPTIMAL,        "optimal",
         AMR_DRV_ONLINE,         "online",
         AMR_DRV_FAILED,         "failed",
         AMR_DRV_REBUILD,        "rebuild",
         AMR_DRV_HOTSPARE,       "hotspare",
     } ;

     szgb = ((float) size) / (1024 * 1024 * 2) ;         /* size in GB */

     raid_level = prop & AMR_DRV_RAID_MASK ;

     strcpy (propstr, "<") ;
     for (i = 0 ; i < NTAB (proptable) ; i++)
     {
         if (i > 0) strcat (propstr, ",") ;
         if (prop & proptable [i].code)
             strcat (propstr, proptable [i].ifyes) ;
         else
             strcat (propstr, proptable [i].ifno) ;
     }
     strcat (propstr, ">") ;

     statestr = NULL ;
     for (i = 0 ; i < NTAB (statetable) && statestr == NULL ; i++)
         if (AMR_DRV_CURSTATE (state) == statetable [i].code)
             statestr = statetable [i].status ;

     printf ("Drive %d: %8.2f GB, RAID%d %s %s\n",
                         ldrv, szgb, raid_level, propstr, statestr) ;
}

void describe_logical_volume (int fd, int verbosity, int fwint, int lvolno)
{
     int r ;
     char buffer [2048] ;
     int ldrv ;

     if (fwint == FIRMWARE_40LD)
     {
         r = amr_enquiry (fd, sizeof buffer, buffer,
                             AMR_CMD_CONFIG, AMR_CONFIG_ENQ3,
                             AMR_CONFIG_ENQ3_SOLICITED_FULL) ;
         if (r == AMR_STATUS_SUCCESS)
         {
             struct amr_enquiry3 *ae3 ;

             ae3 = (struct amr_enquiry3 *) buffer ;
             for (ldrv = 0 ; ldrv < ae3->ae_numldrives ; ldrv++)
             {
                 if (lvolno < 0 || lvolno == ldrv)
                     describe_one_volume (ldrv, verbosity,
                                                 ae3->ae_drivesize [ldrv],
                                                 ae3->ae_drivestate [ldrv],
                                                 ae3->ae_driveprop [ldrv]) ;
             }
         }
     }
     else if (fwint == FIRMWARE_8LD)
     {
     }
     else
     {
         fprintf (stderr, "Firmware interface not supported\n") ;
         exit (1) ;
     }
}

/******************************************************************************
  * Main function
  */

int main (int argc, char *argv [])
{
     int fd ;
     int version ;
     int r ;
     int fwint ;
     int verbosity ;

     char *filename ;
     int lvolno ;
     int globalparam ;

     int o ;
     extern char *optarg ;
     extern int optind ;

     /*
      * Parse arguments
      */

     filename = "/dev/amr0" ;
     lvolno = -1 ;
     globalparam = 0 ;
     verbosity = 0 ;

     while ((o = getopt (argc, argv, "vga:t:f:l:")) != -1)
         switch (o)
         {
             case 'v' :
                 verbosity++ ;
                 break ;
             case 'g' :
                 globalparam = 1 ;
                 break ;
             case 'f' :
                 filename = optarg ;
                 break ;
             case 'a' :
                 nattempts = atoi (optarg) ;
                 break ;
             case 't' :
                 sleeptime = atoi (optarg) ;
                 break ;
             case 'l' :
                 lvolno = atoi (optarg) ;
                 break ;
             case '?' :
             default :
                 usage () ;
         }
     argc -= optind ;
     argv += optind ;

     if (argc != 0)
         usage () ;

     /*
      * Access to the driver
      */

     fd = open (filename, O_RDONLY) ;
     if (fd == -1)
     {
         perror ("open") ;
         exit (1) ;
     }

     r = ioctl (fd, AMR_IO_VERSION, &version) ;
     if (r == -1)
     {
         perror ("ioctl version") ;
         exit (1) ;
     }
     if (globalparam && verbosity >= 1)
         printf ("Version =\t%d\n", version) ;
     if (version != 1)
     {
         fprintf (stderr, "Driver version (%d) not supported\n", version) ;
         exit (1) ;
     }

     fwint = describe_card (fd, verbosity, globalparam) ;

     describe_logical_volume (fd, verbosity, fwint, lvolno) ;


}
Received on Sat Mar 12 2005 - 09:51:30 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:29 UTC