Panic with amr and 5.4-PRERELEASE
Philippe PEGON
Philippe.Pegon at crc.u-strasbg.fr
Sun Mar 13 07:38:25 PST 2005
ok, sorry, try this
/* 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 <sys/devicestat.h>
#include <machine/param.h>
#include "/usr/src/sys/dev/amr/amrio.h"
#include "/usr/src/sys/dev/amr/amrreg.h"
#include "/usr/src/sys/dev/amr/amr_compat.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) ;
}
More information about the freebsd-current
mailing list