Initial revision

This commit is contained in:
manderso 2003-10-22 22:21:02 +00:00
commit 5b6d45f286
18 changed files with 26726 additions and 0 deletions

57
CHANGES Normal file
View file

@ -0,0 +1,57 @@
Version 1.19.2
- Enhance the start/stop parity screens to support new hardware.
Multiple arrays with specified devices and RAID levels may not be
chosen.
- Add screens to support hot spare
- To support new hardware, add options to format dasd devices to
allow advanced function or to be formatted as JBOD.
- Add screens to allow SCSI Bus configurations
- Add screens to allow device driver configurations.
- Updated screens to present pSeries and xSeries platform device
locations.
- Add support for 5703 and 2780 IOAs.
---------------------------------------------------------------------
Version 1.18.14
- update sisconfig screens for start parity, formatting of the
device no longer occurs before starting parity set. The start
parity is now one step operation.
---------------------------------------------------------------------
Version 1.18.10
- Update concurrent maintanence to check if device is in use before
allowing device removal.
---------------------------------------------------------------------
Version 1.18.9
- Fixes for format operations on 5702 IOA
- smart dump enhancements
---------------------------------------------------------------------
Version 1.18.1
- Add support for 2757, 2782 and 5702 IOAs
- Add Dynamic major numbering mechanism.
---------------------------------------------------------------------
Version 1.17.1
- DASD RAID 5* (device parity array) support
- sisdump.c moved to sistrace.c sisdump.c now used for IOA auto
dump facility
---------------------------------------------------------------------
Version 1.16.1
- DASD concurrent maintenance support
- DASD microcode update support
---------------------------------------------------------------------
Version 1.15.4
- Added a bunch of fixes/hacks to make sisconfig more useable across
5250 telnet.
- Added documentation on using sisconfig across 5250 telnet
- Fixed some multiple paging bugs on Display Dist Unit Details screen
and on the reclaim screen.
---------------------------------------------------------------------
Version 1.15.2
- Improved the robustness of /proc parsing. ibmsis device driver
can now change the format of its proc file entry much more
easily.
- Fixed a bug in sisconfig when running in non-devfs mode prior to
running scsidev the first time. It would try to open the /dev/scsi
directory, which may not have existed at this point.
---------------------------------------------------------------------
Version 1.15.2
- Created this file to track updates
---------------------------------------------------------------------

67
Makefile Normal file
View file

@ -0,0 +1,67 @@
INCLUDEDIR = -I.
CC = gcc
include version.mk
CFLAGS = -g -Wall $(IPR_DEFINES) -DIPR_IPRUTILS
UTILS_VER = $(IPR_MAJOR_RELEASE).$(IPR_MINOR_RELEASE).$(IPR_FIX_LEVEL)
all: iprconfig iprupdate iprdump iprtrace iprdbg docs
iprconfig: iprconfig.c iprlib.o
$(CC) $(CFLAGS) $(INCLUDEDIR) -o iprconfig iprconfig.c iprlib.o -lform -lpanel -lncurses -lmenu
iprupdate: iprupdate.c iprlib.o
$(CC) $(CFLAGS) $(INCLUDEDIR) -o iprupdate iprlib.o iprupdate.c
iprdump:iprdump.c iprlib.o
$(CC) $(CFLAGS) $(INCLUDEDIR) -o iprdump iprlib.o iprdump.c
iprtrace:iprtrace.c iprlib.o
$(CC) $(CFLAGS) $(INCLUDEDIR) -o iprtrace iprlib.o iprtrace.c
iprdbg:iprdbg.c iprlib.o
$(CC) $(CFLAGS) $(INCLUDEDIR) -o iprdbg iprlib.o iprdbg.c
iprlib.o: iprlib.c
$(CC) $(CFLAGS) $(INCLUDEDIR) -o iprlib.o -c iprlib.c
docs: iprconfig.8 iprupdate.8 iprdump.8
mkdir -p docs
cp *.8 docs/
gzip -f docs/iprconfig.8
gzip -f docs/iprupdate.8
gzip -f docs/iprdump.8
pdfs: docs
nroff -man iprconfig.8 > docs/iprconfig.nroff
nroff -man iprupdate.8 > docs/iprupdate.nroff
nroff -man iprdump.8 > docs/iprdump.nroff
a2ps -B --columns=1 -R -o docs/iprconfig.ps docs/iprconfig.nroff
a2ps -B --columns=1 -R -o docs/iprupdate.ps docs/iprupdate.nroff
a2ps -B --columns=1 -R -o docs/iprdump.ps docs/iprdump.nroff
ps2pdf docs/iprconfig.ps docs/iprconfig.pdf
ps2pdf docs/iprupdate.ps docs/iprupdate.pdf
ps2pdf docs/iprdump.ps docs/iprdump.pdf
rm docs/iprupdate.nroff docs/iprconfig.nroff docs/iprdump.nroff
utils: ./*.c ./*.h
cd ..
tar -zcpf iprutils-$(UTILS_VER)-src.tgz --directory ../ --exclude CVS iprutils
clean:
rm -f iprupdate iprconfig iprdump iprtrace iprupdate.ps iprupdate.pdf iprlib.o
rm -f iprconfig.ps iprconfig.pdf iprdump.pdf iprdump.ps
rm -rf docs
install: all
install -d $(INSTALL_MOD_PATH)/sbin
install --mode=755 iprconfig $(INSTALL_MOD_PATH)/sbin/iprconfig
install --mode=755 iprupdate $(INSTALL_MOD_PATH)/sbin/iprupdate
install --mode=755 iprdump $(INSTALL_MOD_PATH)/sbin/iprdump
install --mode=755 iprtrace $(INSTALL_MOD_PATH)/sbin/iprtrace
install --mode=700 iprdbg $(INSTALL_MOD_PATH)/sbin/iprdbg
install -d $(INSTALL_MOD_PATH)/usr/share/man/man8
install docs/iprconfig.8.gz $(INSTALL_MOD_PATH)/usr/share/man/man8/iprconfig.8.gz
install docs/iprupdate.8.gz $(INSTALL_MOD_PATH)/usr/share/man/man8/iprupdate.8.gz
install docs/iprdump.8.gz $(INSTALL_MOD_PATH)/usr/share/man/man8/iprdump.8.gz

98
README Normal file
View file

@ -0,0 +1,98 @@
This directory contains user space tools required by the ibmsis device driver.
To install them, type 'make' and then 'make install'. You will need pciutils-devel,
ncurses and ncurses-devel packages installed to perform the 'make'. If you have
trouble compiling the utilities due to not finding ibmsislib.h, you also need to
download the ibmsis device driver source.
sisdump - A user program meant to be run in the background to gather debug
information should an IOA failure occur. Ideally, this program should be
started during IPL/boot time after file systems are loaded when the ibmsis
SCSI driver is used.
sisupdate - IOA/disk unit microcode update utility
This tool requires no arguments and should be run after each time the device driver
is loaded. It will query each adapter/disk unit for the microcode version and update
adapters/disk units that need to be updated.
sisconfig - IOA Configuration and Recovery tool
This is an ncurses based utility made to look similar to the iSeries green screens.
The basic functions of this tool are:
CONFIGURATION
1. Display disk hardware status. This can be used to display all native disk attached
to your Linux partition. Using this option it is possible to obtain the physical location
of each device on the system.
2. Work with SCSI Bus Configuration. With some adapters, this enablement allows
flexibility in setting some SCSI Bus operating parameters such is Max Bus Throughput
and host SCSI ID.
3. Work with Driver Configuration. Currently allows adjustment to the devices drivers
debug verbosity level and internal trace enablement.
PARITY/RAID
4. Stop parity protection. This utility allows you to stop existing arrays. Data stored
on the devices will not be preserved after issuing this command.
5. Start parity protection. This option is used to combine a set of previously non-
redundant devices into one or more data redundant arrays. WARNING: All data on
targeted devices will be lost as ALL targeted devices are zeroed when array is created.
6. Include device. This option allows compatible devices to be included into an existing
parity protected array. WARNING: All data on the devices to be included will be lost
as the devices will be zeroed before being included into the array. Data already on
a device in the existing array will not be affected.
7. Configure hot spare device. With some adapters, this allows additional protection
by configuring a hot spare device which can be used to automatically replace a failed device
in a parity set. WARNING: All data on the devices to be configured as hot spare may be
lost.
8. Format Device for advanced function/Format Device for JBOD (Just a Bunch Of Dasd) function.
Some adapters now support two modes of interacion with dasd devices. The devices can be
formatted for use in a RAID set in which the device must be configured for RAID
before being usable or the devices can be formatted as a JBOD device and be used without
data protection.
RECOVERY
9. Rebuild parity protection. This option is generally used following concurrent
maintenance. Select this option after failing array member device has been replaced to
reconstruct device as an Active array member.
10. Device concurrent maintenance. This can be used to concurrently add or replace disk
units from a running system.
11. Reclaim IOA cache storage. This is to be used by IBM hardware service personnel only.
Use of this function is potentially dangerous and may delete data from the non-volatile
write cache on the adapter.
12. Initialize and format disk unit. This allows you to issue an actual SCSI format command
to natively attached disks. Proceed with caution when using this option.
13. Work with Resources Containing Cache Battery Packs. A set of displays are used to view
the current status of the Cache Battery on resources containing battery packs and allow
maintanence actions to be performed against those resources when necessary.
14. Analyze Log. This allows you to view the error messages logged by the ibmsis device driver.
Troubleshooting direct attach DASD:
Q1. I just moved some DASD over to my linux partition and now they don't work. I get Data
Protect sense data looking error logs.
A1. More than likely the DASD are being read/write protected by the adapter for some reason.
Use the sisconfig utility, take option 5. Analyze Log, then option 1. Use vi to view
IBM Storage error messages. If you wish to use an editor more familiar to
you than vi, select option 5 first to change the editor. (If you get into vi and get stuck
type Esc-q!-Enter. This should get you out.) This will display the errors logged by the
ibmsis device driver.
Now look for "Configuration Error". If you have an error log that looks similar to this:
Configuration Error. The following devices contain
attributes not supported by this driver
Refer to the appropriate Linux on iSeries service documents
Device Serial # COMP
/dev/scsi/host0/bus0/target0/lun0/disc 00452957 Yes
Then you have devices that are using compression. To make the devices usable under Linux,
you will need to verify that the device is not part of a parity protected array. Use
sisconfig, take option 2 from the main menu to Work with device parity protection, then
option 1 to display device parity status. If you see the same device as an array member,
then take option 3 from the Work with Device Parity Protection screen to stop device
parity protection. When the device is not parity protected, you will need to initialize
the devices. To do this use sisconfig, take option 3, then option 2. Initialize and format
disk unit and select the devices you wish to format. When the format is complete, the
devices should now be usable to Linux. If the devices you are having difficulty getting
to work are not listed as candidates for format or you are still having problems, contact
your next level of support.

77
init.d/iprdump Normal file
View file

@ -0,0 +1,77 @@
#!/bin/bash
#
# /etc/rc.d/init.d/sisdumpd
#
# Runs the sisdump utility for the ibmsis device driver
#
# chkconfig: 2345 20 90
# description: Starts the sisdump daemon which is used to gather \
# data for failure analysis in the event of a severe failure \
# of the ibmsis driver and its supported hardware.
# processname: sisdump
prog="sisdump"
RETVAL=0
. /etc/init.d/functions
start() {
echo -n $"Starting $prog: "
daemon $prog
RETVAL=$?
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/sisdump
echo
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc $prog
RETVAL=$?
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sisdump
echo
return $RETVAL
}
rhstatus() {
status $prog
}
restart() {
stop
start
}
reload() {
echo -n $"Reloading $prog: "
killproc $prog -HUP
RETVAL=$?
echo
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
reload)
reload
;;
status)
rhstatus
;;
condrestart)
[ -f /var/lock/subsys/sisdump ] && restart || :
;;
*)
echo "Usage: $0 {start|stop|status|restart|condrestart}"
exit 1
esac
exit $?

65
init.d/iprupdate Normal file
View file

@ -0,0 +1,65 @@
#!/bin/bash
#
# /etc/rc.d/init.d/sisupdated
#
# Runs the sisupdate utility for ibmsis supported devices
#
# chkconfig: 2345 30 90
# description: Runs the sisupdate utility to update firmware images \
# for adapters and devices under the ibmsis device driver.
# processname: sisupdate
. /etc/init.d/functions
prog="sisupdate"
start() {
echo -n $"Starting $prog: "
$prog
RETVAL=$?
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/sisupdate
echo
return $RETVAL
}
stop() {
return 0
}
rhstatus() {
status $prog
}
restart() {
stop
start
}
reload() {
return 0
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
reload)
reload
;;
status)
rhstatus
;;
condrestart)
[ -f /var/lock/subsys/sisupdate ] && restart || :
;;
*)
echo "Usage: $0 {start|stop|status|restart|condrestart}"
exit 1
esac
exit $?

6
install.sh Executable file
View file

@ -0,0 +1,6 @@
install -d /sbin
install sisconfig /sbin/sisconfig
install sisupdate /sbin/sisupdate
install sisdump /sbin/sisdump
install docs/sisconfig.8.gz /usr/man/man8/sisconfig.8.gz
install docs/sisupdate.8.gz /usr/man/man8/sisupdate.8.gz

203
iprconfig.8 Normal file
View file

@ -0,0 +1,203 @@
.TH SISCONFIG 8 "March 2003"
.SH NAME
sisconfig \- IBM storage adapter configuration/recovery utility
.SH SYNOPSIS
.BI "sisconfig [-e editor] [-k dir] [-p mode]"
.sp
.BI "sisconfig --version"
.SH DESCRIPTION
.B sisconfig
is used to configure IBM storage adapters, display information
about them, and to perform IOA and disk unit recovery scenarios. It was originally
designed to emulate IBM iSeries DST/SST green screens and should have similar
behavior. The interface is completely menu driven. The various screens will
look slightly different depending on the hardware platform sisconfig is
being run on. The various menu options are:
.PP
.B 1. Display disk hardware status.
.br
This option can be used to display various information regarding
the SCSI IOAs attached to the system and the disk units controlled by
them. For each IOA and disk unit, their serial number, type,
model number, resource name, and hardware status will be
available. The model numbers are:
.PP
001 IOA resource
.br
020 JBOD Disk unit resource
.br
050 Disk unit resource
.br
060 Compressed disk unit
.br
07x Parity protected disk unit
.br
08x Compressed, parity protected disk unit
.br
090 Hot Spare disk unit
.br
200 Parity set resource
.br
.br
Note: for the 07x and 08x models, the x describes the amount
of the device which is used as parity. 4 = 1/4 parity,
2 = 1/8 parity, 1 = 1/16 parity, 0 = no parity, 9 = other parity distribution.
.PP
By selecting Display disk unit details from this screen it is possible
to obtain the physical location for each resource listed. This information
can be used to locate failing devices. On this
screen, beside each resource is an OPT field. By entering a 5 beside
any resource, detailed information about that resource can be obtained.
For an IOA resource, this will display the driver version, the IOA
firmware version, and the physical location amongst other things.
.PP
.B 2. Work with device parity protection
.br
This option will present a second menu containing device parity related
commands.
.PP
.B Display device parity status
is used to display the status of hardware parity protection
on the system.
.PP
.B Start device parity protection
is used to combine a set of devices into one or more disk arrays/parity sets.
.B ATTENTION:
Data on selected devices will NOT be preserved when creating the parity set.
.PP
.B Stop device parity protection
is used to stop device parity protection and delete disk arrays.
Selecting this option will provide you with a candidate list of disk arrays
which can be stopped. If you have devices which are in disk arrays and they
are not available as candidates to stop, you may need to format the
devices using sisconfig.
.PP
.B Include unit in device parity protection
is used to allow compatible devices to be included into an existing
parity protected array.
.B ATTENTION:
All data on the devices to be included will be lost
as the devices will be zeroed before being included into the array. Data already on
a device in the existing array will not be affected.
.PP
.B Work with disk unit configuration
is used to create and delete hot spare devices and to enable and disable device
advanced functions. In order to create a disk array when starting from JBOD disks (020),
the disks must first be enabled for advanced function which will reformat the devices.
.PP
.B 3. Work with disk unit recovery
is used to perform the following disk unit recovery actions:
.PP
.B Device Concurrent Maintenance.
.br
This is used to add or replace disk units from the system concurrent with running.
Not all systems support device concurrent maintenance. Concurrent maintenance is
currently only supported with SES (SCSI Enclosure Services) packaging.
To use this facility, you will need to know the physical location of the
device you would like to replace. Device concurrent maintenance can be used to
add a new device to a running system and to replace a failed device. Extreme
caution should be used when performing device concurrent maintenance.
.PP
.B Initialize and format disk unit
is used to issue a SCSI format command to attached devices. A format
unit command has special meaning to the IOA and is used as a service
action for certain error conditions. Formatting a disk unit will lose
all data on that drive. To make a compressed disk unit usable a format
can must used.
.PP
.B Reclaim IOA cache storage
is used to repair cache error conditions.
.B Warning!
Use this option with care. This is used to discard data from the cache
and may result in data loss. This option is designed to be used by
authorized IBM hardware customer engineers.
.PP
.B Rebuild disk unit data
is generally used following concurrent maintenance. Select this option after
failing array member device has been replaced to reconstruct the device as
an active array member.
.PP
.B Work with resources containing cache battery packs
is used to display information regarding rechargeable cache battery packs
and to force rechargeable cache battery packs into an error state so that
they can be replaced prior to failure.
.B ATTENTION:
Once an error has been forced on a rechargeable cache battery pack write
caching will be disabled until the battery pack is replaced.
.PP
.B 4. Work with configuration
is used to change configurable driver and adapter options, such as driver
verbosity, maximum bus speed allowed, initiator SCSI ID, etc.
.PP
.B 5. Analyze Log
is an option available to analyze /var/log/messages* files. By default
it will use vi as the editor to open the concatenated error log files.
This can be changed by using option 6 on the
.B Kernel Messages Log
menu. Selecting
option 1 on the Kernel Messages Log menu will display only the most recent
errors logged by the ibmsis device driver and may be useful to filter out
some of the clutter. Option 2 will display all recorded errors logged by the
ibmsis device driver. Option 3 will display all kernel messages. Option 4 will
display errors logged by the sisconfig utility. This may be useful for
debugging problems. Option 5 can be used to change where the tool looks
to find the kernel messages files. The default is to look in /var/log.
.SH OPTIONS
.TP
.B \-e editor
Default editor for viewing error logs. The default editor is vi, but can be
changed with this parameter.
.TP
.B -k directory
Kernel messages root directory. Root directory to look for kernel messages.
Default is /var/log.
.TP
.B -p mode
Select the mode in which device location data should be displayed. Mode options are
.B iseries, pseries
and
.B
generic.
.TP
.B \-\-version
Print version number of
.B sisconfig
.SH AUTHOR
Brian King (bjking1@us.ibm.com)
.SH AVAILABILITY
The ibmsis device driver and all associated user space utilities are available
for download at
.nf
.B http://www.ibm.com/servers/eserver/iseries/linux/
.SH NOTES
.TP
.B Notes on using under iSeries 5250 telnet
.PP
Only use this utility across 5250 telnet when there are no other options
available to you. Since there may be occasions when 5250 telnet is your only
option to access your Linux console, every attempt has been made to make
this utility usable under 5250 telnet. By following a few guidelines,
you can make your 5250 telnet experience more productive and much less
frustrating.
.PP
1. First of all, it will be helpful to know how the keys are mapped under
5250 telnet. From the 5250 telnet window, hit ESC. This will get you to the
.B Send TELNET Control Functions
menu. Take option 6 to display the keyboard map. Take note of how TAB, ESC,
CTLC, and SENDWOCR are bound. They will be useful in the future.
.PP
2. When selecting menu options, enter the menu number, followed by the
enter key, same as usual.
.PP
3. When typing single character commands (eg. r=Refresh), type the single
character followed by the SENDWOCR key (F11 by default).
.PP
4. When on a device/array/IOA selection screen (eg. Display Disk Unit Details),
do NOT use the arrow keys to navigate. Instead use the TAB key (F7 by default)
to navigate these screens.
.PP
5. Beware of the backspace and delete keys. As a rule do NOT use them.
.PP
6. When editing the root kernel message log directory or the default editor,
you may use the arrow keys, but not the backspace and delete keys. Use the
space bar to remove already typed characters.

20884
iprconfig.c Normal file

File diff suppressed because it is too large Load diff

475
iprdbg.c Normal file
View file

@ -0,0 +1,475 @@
/******************************************************************/
/* Linux IBM SIS IOA debug utility */
/* Description: IBM Storage IOA Interface Specification (SIS) */
/* Linux debug utility */
/* */
/* (C) Copyright 2003 */
/* International Business Machines Corporation and others. */
/* All Rights Reserved. */
/******************************************************************/
/*
* $Header: /cvsroot/iprdd/iprutils/iprdbg.c,v 1.1 2003/10/22 22:21:02 manderso Exp $
*/
#ifndef iprlib_h
#include "iprlib.h"
#endif
#include <sys/ioctl.h>
#include <scsi/sg.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define IBMSIS_MAX_FLIT_ENTRIES 59
#define IBMSIS_FLIT_TIMESTAMP_LEN 12
#define IBMSIS_FLIT_FILENAME_LEN 184
enum sisdbg_cmd
{
SISDBG_READ = IBMSIS_IOA_DEBUG_READ_IOA_MEM,
SISDBG_WRITE = IBMSIS_IOA_DEBUG_WRITE_IOA_MEM,
SISDBG_FLIT = IBMSIS_IOA_DEBUG_READ_FLIT
};
struct ibmsis_bus_speeds
{
u8 speed;
char *description;
};
struct ibmsis_bus_speeds bus_speeds[] =
{
{0, "Async"},
{1, "10MB/s"},
{2, "20MB/s"},
{3, "40MB/s"},
{4, "80MB/s"},
{5, "160MB/s (DT)"},
{13, "160MB/s (packetized)"},
{14, "320MB/s (packetized)"}
};
struct ibmsis_flit_entry
{
u32 flags;
u32 load_name;
u32 text_ptr;
u32 text_len;
u32 data_ptr;
u32 data_len;
u32 bss_ptr;
u32 bss_len;
u32 prg_parms;
u32 lid_flags;
u8 timestamp[IBMSIS_FLIT_TIMESTAMP_LEN];
u8 filename[IBMSIS_FLIT_FILENAME_LEN];
};
struct ibmsis_flit
{
u32 ioa_ucode_img_rel_lvl;
u32 num_entries;
struct ibmsis_flit_entry flit_entry[IBMSIS_MAX_FLIT_ENTRIES];
};
int debug_ioctl(int fd, enum sisdbg_cmd cmd, int ioa_adx, int mask,
int *buffer, int len);
int format_flit(struct ibmsis_flit *p_flit);
#define logtofile(...) {if (outfile) {fprintf(outfile, __VA_ARGS__);}}
#define sisprint(...) {printf(__VA_ARGS__); if (outfile) {fprintf(outfile, __VA_ARGS__);}}
#define sisloginfo(...) {syslog(LOG_INFO, __VA_ARGS__); if (outfile) {fprintf(outfile, __VA_ARGS__);}}
FILE *outfile;
int main(int argc, char *argv[])
{
int num_args, address, prev_address = 0;
int length, prev_length = 0;
int ioa_num;
int rc, fd, i, j, k, bus, num_buses;
int arg[16], write_buf[16], bus_speed;
int *buffer;
char cmd[100], prev_cmd[100], cmd_line[1000];
struct sis_ioa *p_cur_ioa;
char ascii_buffer[17];
struct ibmsis_flit flit;
openlog("sisdbg",
LOG_PERROR | /* Print error to stderr as well */
LOG_PID | /* Include the PID with each error */
LOG_CONS, /* Write to system console if there is an error
sending to system logger */
LOG_USER);
if (argc != 2)
{
syslog(LOG_ERR, "Usage: sisdbg /dev/ibmsis0\n");
return -EINVAL;
}
outfile = fopen(".sisdbglog", "a");
tool_init("sisdbg");
for (p_cur_ioa = p_head_sis_ioa, ioa_num = 0;
ioa_num < num_ioas;
p_cur_ioa = p_cur_ioa->p_next, ioa_num++)
{
if (!strcmp(p_cur_ioa->ioa.dev_name, argv[1]))
break;
}
if (p_cur_ioa == NULL)
{
syslog(LOG_ERR, "Invalid device name %s\n", argv[1]);
return -EINVAL;
}
fd = open(argv[1], O_RDWR);
if (fd < 0)
{
syslog(LOG_ERR, "Error opening %s. %m\n", argv[1]);
return -1;
}
closelog();
openlog("sisdbg", LOG_PID, LOG_USER);
sisloginfo("sisdbg on %s started\n", argv[1]);
closelog();
openlog("sisdbg", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
printf("\nATTENTION: This utility is for adapter developers only! Use at your own risk!\n");
printf("\nUse \"quit\" to exit the program.\n\n");
memset(cmd, 0, sizeof(cmd));
memset(prev_cmd, 0, sizeof(prev_cmd));
while(1)
{
printf("SISDB(%X)> ", p_cur_ioa->ccin);
memset(cmd, 0, sizeof(cmd));
memset(cmd_line, 0, sizeof(cmd_line));
memset(arg, 0, sizeof(arg));
address = 0;
fgets(cmd_line, 999, stdin);
logtofile("\n%s\n", cmd_line);
num_args = sscanf(cmd_line, "%80s %x %x %x %x %x %x %x %x "
"%x %x %x %x %x %x %x %x %x\n",
cmd, &address, &arg[0],
&arg[1], &arg[2], &arg[3],
&arg[4], &arg[5], &arg[6],
&arg[7], &arg[8], &arg[9],
&arg[10], &arg[11], &arg[12],
&arg[13], &arg[14], &arg[15]);
if ((cmd[0] == '\0') && !strncmp("mr4", prev_cmd, 3))
{
strcpy(cmd, prev_cmd);
address = prev_address + prev_length;
num_args = 3;
arg[0] = prev_length;
}
if (!strcmp(cmd, "speeds"))
{
length = 64;
buffer = calloc(length/4, 4);
if (buffer == NULL)
{
syslog(LOG_ERR, "Memory allocation error\n");
continue;
}
if ((p_cur_ioa->ccin == 0x2780) ||
(p_cur_ioa->ccin == 0x2757))
{
num_buses = 4;
}
else
{
num_buses = 2;
}
for (bus = 0, address = 0xF0016380;
bus < num_buses;
bus++)
{
rc = debug_ioctl(fd, SISDBG_READ, address, 0,
buffer, length);
if (!rc)
{
sisprint("\nBus %d speeds:\n", bus);
for (i = 0; i < 16; i++)
{
bus_speed = sistoh32(buffer[i]) & 0x0000000f;
for (j = 0; j < sizeof(bus_speeds)/sizeof(struct ibmsis_bus_speeds); j++)
{
if (bus_speed == bus_speeds[j].speed)
{
sisprint("Target %d: %s\n", i, bus_speeds[j].description);
}
}
}
}
switch(bus)
{
case 0:
address = 0xF001e380;
break;
case 1:
address = 0xF4016380;
break;
case 2:
address = 0xF401E380;
break;
};
}
free(buffer);
}
else if (!strcmp(cmd, "mr4"))
{
if (num_args < 2)
{
sisprint("Invalid syntax\n");
continue;
}
else if (num_args == 2)
{
length = 4;
}
else if ((length % 4) != 0)
{
sisprint("Length must be 4 byte multiple\n");
continue;
}
else
length = arg[0];
buffer = calloc(length/4, 4);
if (buffer == NULL)
{
syslog(LOG_ERR, "Memory allocation error\n");
continue;
}
rc = debug_ioctl(fd, SISDBG_READ, address, 0,
buffer, length);
for (i = 0; (rc == 0) && (i < (length / 4));)
{
sisprint("%08X: ", address+(i*4));
memset(ascii_buffer, '\0', sizeof(ascii_buffer));
for (j = 0;
(i < (length / 4)) && (j < 4);
j++, i++)
{
sisprint("%08X ", sistoh32(buffer[i]));
memcpy(&ascii_buffer[j*4], &buffer[i], 4);
for (k = 0; k < 4; k++)
{
if (!isprint(ascii_buffer[(j*4)+k]))
ascii_buffer[(j*4)+k] = '.';
}
}
for (;j < 4; j++)
{
sisprint(" ");
strncat(ascii_buffer, "....", sizeof(ascii_buffer)-1);
}
sisprint(" |%s|\n", ascii_buffer);
}
free(buffer);
prev_address = address;
prev_length = length;
}
else if (!strcmp(cmd, "mw4"))
{
if (num_args < 3)
{
sisprint("Invalid syntax\n");
continue;
}
/* Byte swap everything */
for (i = 0; i < num_args-2; i++)
write_buf[i] = htosis32(arg[i]);
debug_ioctl(fd, SISDBG_WRITE, address, 0,
write_buf, (num_args-2)*4);
}
else if (!strcmp(cmd, "bm4"))
{
if (num_args < 3)
{
sisprint("Invalid syntax\n");
continue;
}
/* Byte swap the data */
write_buf[0] = htosis32(arg[0]);
debug_ioctl(fd, SISDBG_WRITE, address, arg[1],
write_buf, 4);
}
else if (!strcmp(cmd, "flit"))
{
rc = debug_ioctl(fd, SISDBG_FLIT, 0, 0,
(int *)&flit, sizeof(flit));
if (rc != 0)
continue;
format_flit(&flit);
}
else if (!strcmp(cmd, "help"))
{
printf("\n");
printf("mr4 address length "
"- Read memory\n");
printf("mw4 address data "
"- Write memory\n");
printf("bm4 address data preserve_mask "
"- Modify bits set to 0 in preserve_mask\n");
printf("speeds "
"- Current bus speeds for each device\n");
printf("flit "
"- Format the flit\n");
printf("exit "
"- Exit the program\n\n");
continue;
}
else if (!strcmp(cmd, "exit") || !strcmp(cmd, "quit") ||
!strcmp(cmd, "q") || !strcmp(cmd, "x"))
{
closelog();
openlog("sisdbg", LOG_PID, LOG_USER);
sisloginfo("sisdbg on %s exited\n", argv[1]);
closelog();
return 0;
}
else
{
sisprint("Invalid command %s. Use \"help\" for a list "
"of valid commands\n", cmd);
continue;
}
strcpy(prev_cmd, cmd);
}
return 0;
}
int debug_ioctl(int fd, enum sisdbg_cmd cmd, int ioa_adx, int mask,
int *buffer, int len)
{
struct ibmsis_ioctl_cmd_internal ioa_cmd;
int rc;
memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal));
ioa_cmd.buffer = buffer;
ioa_cmd.buffer_len = len;
ioa_cmd.cdb[0] = IBMSIS_IOA_DEBUG;
ioa_cmd.cdb[1] = cmd;
ioa_cmd.cdb[2] = (ioa_adx >> 24) & 0xff;
ioa_cmd.cdb[3] = (ioa_adx >> 16) & 0xff;
ioa_cmd.cdb[4] = (ioa_adx >> 8) & 0xff;
ioa_cmd.cdb[5] = ioa_adx & 0xff;
ioa_cmd.cdb[6] = (mask >> 24) & 0xff;
ioa_cmd.cdb[7] = (mask >> 16) & 0xff;
ioa_cmd.cdb[8] = (mask >> 8) & 0xff;
ioa_cmd.cdb[9] = mask & 0xff;
ioa_cmd.cdb[10] = (len >> 24) & 0xff;
ioa_cmd.cdb[11] = (len >> 16) & 0xff;
ioa_cmd.cdb[12] = (len >> 8) & 0xff;
ioa_cmd.cdb[13] = len & 0xff;
if (cmd != SISDBG_WRITE)
ioa_cmd.read_not_write = 1;
rc = sis_ioctl(fd, IBMSIS_IOA_DEBUG, &ioa_cmd);
if (rc != 0)
fprintf(stderr, "Debug IOCTL failed. %d\n", errno);
return rc;
}
int format_flit(struct ibmsis_flit *p_flit)
{
int num_entries = sistoh32(p_flit->num_entries) - 1;
struct ibmsis_flit_entry *p_flit_entry;
signed int path_length;
u8 filename[IBMSIS_FLIT_FILENAME_LEN+1];
u8 time[IBMSIS_FLIT_TIMESTAMP_LEN+1];
u8 buf1[IBMSIS_FLIT_FILENAME_LEN+1];
u8 buf2[IBMSIS_FLIT_FILENAME_LEN+1];
u8 lid_name[IBMSIS_FLIT_FILENAME_LEN+1];
u8 path[IBMSIS_FLIT_FILENAME_LEN+1];
int num_args, i;
for (i = 0, p_flit_entry = p_flit->flit_entry;
(i < num_entries) && (*p_flit_entry->timestamp);
p_flit_entry++, i++)
{
snprintf(time, IBMSIS_FLIT_TIMESTAMP_LEN, p_flit_entry->timestamp);
time[IBMSIS_FLIT_TIMESTAMP_LEN] = '\0';
snprintf(filename, IBMSIS_FLIT_FILENAME_LEN, p_flit_entry->filename);
filename[IBMSIS_FLIT_FILENAME_LEN] = '\0';
num_args = sscanf(filename, "%184s "
"%184s "
"%184s "
"%184s ",
buf1, buf2, lid_name, path);
if (num_args != 4)
{
syslog(LOG_ERR, "Cannot parse flit\n");
return 1;
}
path_length = strlen(path);
sisprint("LID Name: %s (%8X)\n", lid_name, sistoh32(p_flit_entry->load_name));
sisprint("Time Stamp: %s\n", time);
sisprint("LID Path: %s\n", lid_name);
sisprint("Text Segment: Address %08X, Length %8X\n",
sistoh32(p_flit_entry->text_ptr), sistoh32(p_flit_entry->text_len));
sisprint("Data Segment: Address %08X, Length %8X\n",
sistoh32(p_flit_entry->data_ptr), sistoh32(p_flit_entry->data_len));
sisprint("BSS Segment: Address %08X, Length %8X\n",
sistoh32(p_flit_entry->bss_ptr), sistoh32(p_flit_entry->bss_len));
sisprint("\n");
}
return 0;
}

29
iprdump.8 Normal file
View file

@ -0,0 +1,29 @@
.TH SISDUMP 8 "July 2002"
.SH NAME
sisdump - IBM storage adapter dump utility
.SH SYNOPSIS
.B sisdump
.SH DESCRIPTION
.B sisdump
is used to gather information in the event of an adapter failure.
The dump data will by default be saved in the /var/log/ directory with the
prefix ibmsis_D# where # will be the dump ID of the file. Information
will be posted in /var/log/messages in the event of a dump condition
indicating the dump ID for cross reference. The sisdump utility can be
instantiated any time after the ibmsis driver is loaded and the file system
to where the dump data is targetted to be stored has also been loaded.
.SH OPTIONS
.TP
.B \-\-version
Print the version number of
.B sisdump
.TP
.B \-d <directory>
Assign directory where dump data is to be stored. Default is /var/log/.
.SH AUTHOR
Michael Anderson (mjanders@us.ibm.com)
.SH AVAILABILITY
The ibmsis device driver and all associated userspace utilities are available
for download at
.nf
.B http://www.ibm.com/servers/eserver/iseries/linux/

270
iprdump.c Normal file
View file

@ -0,0 +1,270 @@
/******************************************************************/
/* Linux IBM SIS microcode update utility */
/* Description: IBM Storage IOA Interface Specification (SIS) */
/* Linux microcode update utility */
/* */
/* (C) Copyright 2000, 2001 */
/* International Business Machines Corporation and others. */
/* All Rights Reserved. */
/******************************************************************/
/*
* $Header: /cvsroot/iprdd/iprutils/iprdump.c,v 1.1 2003/10/22 22:21:02 manderso Exp $
*/
#ifndef iprlib_h
#include "iprlib.h"
#endif
#include <sys/mman.h>
#define SISDUMP_SIZE 0x01000000 /* 16M dump */
#define SISDUMP_DIR "/var/log/"
#define MAX_DUMP_FILES 4
int main(int argc, char *argv[])
{
int rc = 0;
struct ibmsis_ioctl_cmd_type2 *ioa_cmd;
DIR *dump_dir;
struct dirent *dir_entry;
char *p_temp;
int fd, f_dump, str_len;
char usr_dir[50], sisdump_fn[60];
char temp_string[80];
u32 new_dumpID = 0, used_dumpID;
int index, len, ioa_num;
struct sis_ioa *p_cur_ioa;
int files_queue[MAX_DUMP_FILES];
int delete_file, j, min_dumpID;
int file_queue_index;
int signals;
struct dump_header
{
u32 total_length;
u32 num_elems;
u32 first_entry_offset;
} *dump_header;
struct dump_entry_header
{
u32 length;
u32 id;
#define IBMSIS_DUMP_TEXT_ID 3
char data[0];
} *dump_entry_header;
if (fork())
{
return 0;
}
openlog("sisdump",
LOG_PERROR | /* Print error to stderr as well */
LOG_PID | /* Include the PID with each error */
LOG_CONS, /* Write to system console if there is an error
sending to system logger */
LOG_USER);
if (argc > 1)
{
if (strcmp(argv[1], "--version") == 0)
{
printf("sisdump: %s"IBMSIS_EOL, IPR_VERSION_STR);
exit(1);
}
else if (strcmp(argv[1], "-d") == 0)
{
strcpy(usr_dir,argv[2]);
str_len = strlen(usr_dir);
if ((str_len < 50) && (usr_dir[str_len] != '/'))
{
usr_dir[str_len + 1] = '/';
usr_dir[str_len + 2] = '\0';
}
}
else
{
printf("Usage: sisdump [options]"IBMSIS_EOL);
printf(" Options: --version Print sisdump version"IBMSIS_EOL);
printf(" -d <usr_dir>"IBMSIS_EOL);
exit(1);
}
}
else
{
strcpy(usr_dir,SISDUMP_DIR);
}
dump_dir = opendir(usr_dir);
for (j = 0; j < MAX_DUMP_FILES; j++)
{
files_queue[j] = 0;
}
/* Scan the assigned dump directory for any dump that may already be there
and assign any new dump files created to one higher than the highest
numbered file */
file_queue_index = 0;
for (dir_entry = readdir(dump_dir),
delete_file = 0;
dir_entry != NULL;
dir_entry = readdir(dump_dir))
{
p_temp = strstr(dir_entry->d_name, "ibmsis_D");
if (p_temp)
{
used_dumpID = strtoul(&dir_entry->d_name[8], NULL, 10);
if (used_dumpID >= new_dumpID)
{
new_dumpID = used_dumpID + 1;
}
files_queue[file_queue_index++] = used_dumpID;
if ((file_queue_index == MAX_DUMP_FILES) || delete_file)
{
if (file_queue_index == MAX_DUMP_FILES)
{
delete_file = 1;
file_queue_index = 0;
}
min_dumpID = used_dumpID;
for (j=0; j < MAX_DUMP_FILES; j++)
{
if (files_queue[j] < min_dumpID)
{
min_dumpID = files_queue[j];
files_queue[j] = files_queue[file_queue_index];
files_queue[file_queue_index] = min_dumpID;
}
}
sprintf(temp_string,"rm %sibmsis_D%d",SISDUMP_DIR, files_queue[file_queue_index]);
system(temp_string);
}
}
}
tool_init("sisdump");
signals = sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTERM);
sigblock(~signals);
/* Loop for all attached adapters */
for (p_cur_ioa = p_head_sis_ioa, ioa_num = 0;
ioa_num < num_ioas;
p_cur_ioa = p_cur_ioa->p_next, ioa_num++)
{
ioa_cmd = malloc(sizeof(struct ibmsis_ioctl_cmd_type2) + SISDUMP_SIZE);
fd = open(p_cur_ioa->ioa.dev_name, O_RDWR | O_NONBLOCK);
if (fd < 0)
{
syslog(LOG_ERR, "Cannot open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name);
continue;
}
while (1) {
memset(ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_type2) + SISDUMP_SIZE);
ioa_cmd->buffer_len = SISDUMP_SIZE;
ioa_cmd->cdb[0] = IBMSIS_DUMP_IOA;
ioa_cmd->type = IBMSIS_IOCTL_TYPE_2;
ioa_cmd->driver_cmd = 1;
rc = ioctl(fd, IBMSIS_IOCTL_SEND_COMMAND, ioa_cmd);
if (rc != 0)
{
if (errno == EINVAL)
syslog(LOG_ERR, "sisdump version incompatible with current driver"IBMSIS_EOL);
break;
}
else
{
sprintf(sisdump_fn,"%sibmsis_D%d",usr_dir,new_dumpID);
f_dump = creat(sisdump_fn, S_IRUSR);
if (f_dump < 0)
{
syslog(LOG_ERR, "Cannot open %s. %m"IBMSIS_EOL, sisdump_fn);
break;
}
/* get length of data obtained from within buffer */
dump_header = (struct dump_header *)ioa_cmd->buffer;
write(f_dump, ioa_cmd->buffer, sistoh32(dump_header->total_length));
close(f_dump);
/* parse through buffer and find the IBMSIS_DUMP_TEXT_ID
information */
dump_entry_header =
(struct dump_entry_header *)&ioa_cmd->buffer[sistoh32(dump_header->first_entry_offset)];
while (sistoh32(dump_entry_header->id) != IBMSIS_DUMP_TEXT_ID)
{
dump_entry_header = (struct dump_entry_header *)
((unsigned long)dump_entry_header +
sizeof(struct dump_entry_header) +
sistoh32(dump_entry_header->length));
}
syslog(LOG_ERR,"*********************************************************"IBMSIS_EOL);
syslog(LOG_ERR, "Dump of ibmsis IOA has completed to file: %s"IBMSIS_EOL, sisdump_fn);
if (sistoh32(dump_entry_header->id) == IBMSIS_DUMP_TEXT_ID)
{
index = 0;
while (dump_entry_header->data[index] != 0)
{
len = 0;
while ((dump_entry_header->data[index] != '\n') &&
(dump_entry_header->data[index] != 0))
{
temp_string[len++] = dump_entry_header->data[index++];
}
temp_string[len] = 0;
syslog(LOG_ERR,"%s"IBMSIS_EOL,temp_string);
index++;
}
}
syslog(LOG_ERR,"*********************************************************"IBMSIS_EOL);
/* removed old file if necessary */
files_queue[file_queue_index++] = new_dumpID;
if ((file_queue_index == MAX_DUMP_FILES) || delete_file)
{
if (file_queue_index == MAX_DUMP_FILES)
{
delete_file = 1;
file_queue_index = 0;
}
min_dumpID = new_dumpID;
for (j=0; j < MAX_DUMP_FILES; j++)
{
if (files_queue[j] < min_dumpID)
{
min_dumpID = files_queue[j];
files_queue[j] = files_queue[file_queue_index];
files_queue[file_queue_index] = min_dumpID;
}
}
sprintf(temp_string,"rm %sibmsis_D%d",SISDUMP_DIR, files_queue[file_queue_index]);
system(temp_string);
}
new_dumpID++;
}
}
free(ioa_cmd);
close(fd);
}
return rc;
}

2170
iprlib.c Normal file

File diff suppressed because it is too large Load diff

1456
iprlib.h Normal file

File diff suppressed because it is too large Load diff

107
iprtrace.c Normal file
View file

@ -0,0 +1,107 @@
/******************************************************************/
/* Linux IBM SIS trace dump utility */
/* Description: IBM Storage IOA Interface Specification (SIS) */
/* Linux trace dump utility */
/* Used to dump the internal trace of an IOA */
/* Usage: sistrace /dev/ibmsis0 */
/* sistrace /dev/scsi/host0/controller */
/* */
/* (C) Copyright 2000, 2001 */
/* International Business Machines Corporation and others. */
/* All Rights Reserved. */
/******************************************************************/
/*
* $Header: /cvsroot/iprdd/iprutils/Attic/iprtrace.c,v 1.1 2003/10/22 22:21:02 manderso Exp $
*/
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mount.h>
#include <linux/types.h>
#include <scsi/scsi.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/sg.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/file.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
#include <syslog.h>
#include <term.h>
#ifndef iprlib_h
#include "iprlib.h"
#endif
struct ibmsis_trace_entry
{
u32 element[4];
};
int main (int argc, char *argv[])
{
struct ibmsis_ioctl_cmd_internal ioa_cmd;
struct ibmsis_trace_entry *p_trace_entry;
int num_trace_entries;
int fd, rc, i;
if (argc != 2)
{
printf("Usage: sistrace [controller]"IBMSIS_EOL);
printf(" Example: sistrace /dev/ibmsis0"IBMSIS_EOL);
return -1;
}
openlog("sistrace",
LOG_PERROR | /* Print error to stderr as well */
LOG_PID | /* Include the PID with each error */
LOG_CONS, /* Write to system console if there is an error
sending to system logger */
LOG_USER);
fd = open(argv[1], O_RDWR);
if (fd <= 1)
{
syslog(LOG_ERR, "Cannot open %s. %m"IBMSIS_EOL, argv[1]);
return -1;
}
num_trace_entries = IBMSIS_DUMP_TRACE_ENTRY_SIZE/sizeof(struct ibmsis_trace_entry);
p_trace_entry = malloc(IBMSIS_DUMP_TRACE_ENTRY_SIZE);
memset(ioa_cmd.cdb, 0, 16);
ioa_cmd.buffer = p_trace_entry;
ioa_cmd.buffer_len = IBMSIS_DUMP_TRACE_ENTRY_SIZE;
ioa_cmd.read_not_write = 1;
ioa_cmd.driver_cmd = 1;
rc = sis_ioctl(fd, IBMSIS_GET_TRACE, &ioa_cmd);
close(fd);
if (rc != 0)
{
syslog(LOG_ERR, "Get trace failed. %m"IBMSIS_EOL);
return -1;
}
for (i = 0; i < num_trace_entries; i++)
{
printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
p_trace_entry[i].element[0], p_trace_entry[i].element[1],
p_trace_entry[i].element[2], p_trace_entry[i].element[3]);
}
return 0;
}

30
iprupdate.8 Normal file
View file

@ -0,0 +1,30 @@
.TH SISUPDATE 8 "May 2001"
.SH NAME
sisupdate - IBM storage adapter/disk unit microcode/configuration update utility
.SH SYNOPSIS
.B sisupdate
.SH DESCRIPTION
.B sisupdate
is used to update the firmware on IBM storage adapters and the disk units
attached to them and to update the configuration to use the saved configuration.
It can be run at any time while the ibmsis device driver is loaded. The
utility will check the firmware revision level of each storage adapter/disk unit on
the system and compare it to the firmware revision level that is installed
in /etc/microcode. If the firmware levels do not
match, the firmware will be updated. Only adapters/disk units needing an update
will be updated. Additionally, this utility will configure SCSI bus attributes
such as maximum bus speed, initiator SCSI ID, etc. This utility MUST be run in order
to enable bus speeds > 80 MB/s. It is desired that this be called in early boot
shortly after the ibmsis device driver is loaded.
.SH OPTIONS
.TP
.B \-\-version
Print the version number of
.B sisupdate
.SH AUTHOR
Brian King (bjking1@us.ibm.com)
.SH AVAILABILITY
The ibmsis device driver and all associated userspace utilities are available
for download at
.nf
.B http://www.ibm.com/servers/eserver/iseries/linux/

668
iprupdate.c Normal file
View file

@ -0,0 +1,668 @@
/******************************************************************/
/* Linux IBM SIS microcode update utility */
/* Description: IBM Storage IOA Interface Specification (SIS) */
/* Linux microcode update utility */
/* */
/* (C) Copyright 2000, 2001 */
/* International Business Machines Corporation and others. */
/* All Rights Reserved. */
/******************************************************************/
/*
* $Header: /cvsroot/iprdd/iprutils/iprupdate.c,v 1.1 2003/10/22 22:21:02 manderso Exp $
*/
#include <unistd.h>
#include <sys/ioctl.h>
#include <scsi/sg.h>
#include <sys/stat.h>
#ifndef iprlib_h
#include "iprlib.h"
#endif
#include <sys/mman.h>
struct image_header
{
u32 header_length;
u32 lid_table_offset;
u8 major_release;
u8 card_type;
u8 minor_release[2];
#define LINUX_HEADER_RESERVED_BYTES 20
u8 reserved[LINUX_HEADER_RESERVED_BYTES];
char eyecatcher[16]; /* IBMAS400 CCIN */
u32 num_lids;
struct ibmsis_software_inq_lid_info lid[1];
};
int open_dev(struct sis_ioa *p_ioa, struct sis_device *p_device);
int main(int argc, char *argv[])
{
int rc = 0;
struct stat ucode_stats;
struct ibmsis_ioctl_cmd_internal ioa_cmd;
struct ibmsis_inquiry_page0 page0_inq;
struct ibmsis_inquiry_page3 page3_inq;
struct ibmsis_inquiry_page_cx page_cx_inq;
int num_ioa_lids = 0;
int num_binary_lids = 0;
char ucode_file[50];
int do_download, ucode_fd, dasd_ucode_fd;
struct image_header *p_image_hdr;
struct ibmsis_dasd_ucode_header *p_dasd_image_hdr;
u32 updated = 0;
int fd, dev_fd, i, j, num_entries, ioa_num;
struct ibmsis_software_inq_lid_info *p_lid_info;
u32 force_download, force_devs, force_ioas;
struct ibmsis_dasd_inquiry_page3 dasd_page3_inq;
struct sis_ioa *p_cur_ioa;
char *p_dev_name;
struct sis_device *p_device;
char config_file_name[64];
u8 cdb[IBMSIS_CCB_CDB_LEN];
struct sense_data_t sense_data;
int image_offset;
void *p_dasd_image;
int image_size;
int device_update_blocked;
int u320_disabled;
struct software_inq_lid_info
{
u32 load_id;
u32 timestamp[3];
u32 found;
};
struct software_inq_lid_info ioa_lid_info[50];
openlog("sisupdate",
LOG_PERROR | /* Print error to stderr as well */
LOG_PID | /* Include the PID with each error */
LOG_CONS, /* Write to system console if there is an error
sending to system logger */
LOG_USER);
force_download = force_devs = force_ioas = 0;
if (argc > 1)
{
if (strcmp(argv[1], "--force") == 0)
force_download = 1;
else if (strcmp(argv[1], "--version") == 0)
{
printf("sisupdate: %s"IBMSIS_EOL, IPR_VERSION_STR);
exit(1);
}
else if (strcmp(argv[1], "--force-devs") == 0)
{
force_devs = 1;
}
else if (strcmp(argv[1], "--force-ioas") == 0)
{
force_ioas = 1;
}
else
{
printf("Usage: sisdate [options]"IBMSIS_EOL);
printf(" Options: --version Print sisupdate version"IBMSIS_EOL);
exit(1);
}
}
tool_init("sisupdate");
check_current_config(false);
/* Loop for all attached adapters */
for (p_cur_ioa = p_head_sis_ioa, ioa_num = 0;
ioa_num < num_ioas;
p_cur_ioa = p_cur_ioa->p_next, ioa_num++)
{
fd = open(p_cur_ioa->ioa.dev_name, O_RDWR | O_NONBLOCK);
if (fd < 0)
{
syslog(LOG_ERR, "Cannot open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name);
continue;
}
sprintf(ucode_file, "/etc/microcode/ibmsis%X.img", p_cur_ioa->ccin);
/* Do a page 0 inquiry to the adapter to get the supported page codes */
memset(&ioa_cmd, 0, sizeof(ioa_cmd));
ioa_cmd.buffer = &page0_inq;
ioa_cmd.buffer_len = sizeof(struct ibmsis_inquiry_page0);
ioa_cmd.cdb[1] = 0x01;
ioa_cmd.cdb[2] = 0x00;
ioa_cmd.read_not_write = 1;
rc = sis_ioctl(fd, INQUIRY, &ioa_cmd);
if (rc != 0)
{
syslog(LOG_ERR, "Inquiry to controller %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name);
close(fd);
continue;
}
/* Starting at page code 0xC0, the first software VPD page,
issue inquiries to the adapter for the supported pages */
for (i = 0, num_ioa_lids = 0; (page0_inq.supported_page_codes[i] != 0) &&
(i < page0_inq.page_length); i++)
{
if (page0_inq.supported_page_codes[i] < 0xc0)
continue;
memset(&ioa_cmd, 0, sizeof(ioa_cmd));
ioa_cmd.buffer = &page_cx_inq;
ioa_cmd.buffer_len = sizeof(struct ibmsis_inquiry_page_cx);
ioa_cmd.cdb[1] = 0x01;
ioa_cmd.cdb[2] = page0_inq.supported_page_codes[i];
ioa_cmd.read_not_write = 1;
rc = sis_ioctl(fd, INQUIRY, &ioa_cmd);
if (rc != 0)
{
syslog(LOG_ERR, "Inquiry to controller %s failed. %m"IBMSIS_EOL,
p_cur_ioa->ioa.dev_name);
continue;
}
num_entries = (page_cx_inq.page_length - 4) /
sizeof(struct ibmsis_software_inq_lid_info);
/* Build up a data structure describing all the IOA LIDs
the adapter currently has loaded */
for (j = 0; j < num_entries; j++)
{
ioa_lid_info[num_ioa_lids].load_id =
page_cx_inq.lidinfo[j].load_id;
ioa_lid_info[num_ioa_lids].timestamp[0] =
page_cx_inq.lidinfo[j].timestamp[0];
ioa_lid_info[num_ioa_lids].timestamp[1] =
page_cx_inq.lidinfo[j].timestamp[1];
ioa_lid_info[num_ioa_lids].timestamp[2] =
page_cx_inq.lidinfo[j].timestamp[2];
num_ioa_lids++;
}
}
/* Issue a page 3 inquiry to get the versioning information */
memset(&ioa_cmd, 0, sizeof(ioa_cmd));
ioa_cmd.buffer = &page3_inq;
ioa_cmd.buffer_len = sizeof(struct ibmsis_inquiry_page3);
ioa_cmd.cdb[1] = 0x01;
ioa_cmd.cdb[2] = 0x03;
ioa_cmd.read_not_write = 1;
rc = sis_ioctl(fd, INQUIRY, &ioa_cmd);
if (rc != 0)
{
syslog(LOG_ERR, "Inquiry to controller %s failed. %m"IBMSIS_EOL,
p_cur_ioa->ioa.dev_name);
close(fd);
continue;
}
do_download = 0;
/* Parse the binary file */
ucode_fd = open(ucode_file, O_RDONLY);
if (ucode_fd < 0)
{
syslog(LOG_ERR, "Could not open firmware file %s. %m"IBMSIS_EOL, ucode_file);
close(fd);
continue;
}
/* Get the size of the microcode image */
rc = fstat(ucode_fd, &ucode_stats);
if (rc != 0)
{
syslog(LOG_ERR, "Error accessing IOA firmware file: %s. %m"IBMSIS_EOL, ucode_file);
close(fd);
close(ucode_fd);
continue;
}
/* Map the image in memory */
p_image_hdr = mmap(NULL, ucode_stats.st_size,
PROT_READ, MAP_SHARED, ucode_fd, 0);
if (p_dasd_image_hdr == MAP_FAILED)
{
syslog(LOG_ERR, "Error mapping IOA firmware file: %s. %m"IBMSIS_EOL, ucode_file);
close(fd);
close(ucode_fd);
continue;
}
p_lid_info = (struct ibmsis_software_inq_lid_info *)
((unsigned long)p_image_hdr + sistoh32(p_image_hdr->lid_table_offset) + 4);
num_binary_lids = sistoh32(*((u32*)p_lid_info - 1));
/* Compare the two */
for (i = 0; (i < num_binary_lids) && (do_download == 0); i++, p_lid_info++)
{
int found = 0;
/* Loop through the LIDs loaded on the IOA to find a match */
for (j = 0; j < num_ioa_lids; j++)
{
if (ioa_lid_info[j].load_id == p_lid_info->load_id)
{
found = 1;
if (memcmp(p_lid_info->timestamp,
ioa_lid_info[j].timestamp,
12) != 0)
{
do_download = 1;
break;
}
}
}
if (found == 0)
do_download = 1;
}
if ((page3_inq.major_release != p_image_hdr->major_release) ||
(page3_inq.minor_release[0] != p_image_hdr->minor_release[0]) ||
(page3_inq.minor_release[1] != p_image_hdr->minor_release[1]))
{
do_download = 1;
}
u320_disabled = 0;
/* check for mode page 28 changes before adapter reset */
sprintf(config_file_name,"%x_%x", p_cur_ioa->ccin, p_cur_ioa->host_addr);
if (RC_SUCCESS == sis_config_file_valid(config_file_name))
{
sis_set_page_28(p_cur_ioa, SIS_LIMITED_CONFIG,
do_download | force_download | force_ioas);
}
else
{
sis_set_page_28_init(p_cur_ioa, SIS_LIMITED_CONFIG);
}
if ((do_download == 1) ||
(force_download == 1) ||
(force_ioas == 1))
{
syslog(LOG_NOTICE, "Updating IOA firmware on %s"IBMSIS_EOL, p_cur_ioa->ioa.dev_name);
/* Do the update if the two are different */
/* Might want to fork off a process here so we can start
on the next adapter. Would have to remember the child's PID
so we could wait on it when we were done, though. This would also
greatly complicate the load source case */
memset(&ioa_cmd, 0, sizeof(ioa_cmd));
ioa_cmd.buffer = (void *)((unsigned long)p_image_hdr + sistoh32(p_image_hdr->header_length));
ioa_cmd.buffer_len = ucode_stats.st_size - sistoh32(p_image_hdr->header_length);
ioa_cmd.read_not_write = 0;
/* The write buffer here takes care of both the IOA shutdown and the
reset of the adapter */
rc = sis_ioctl(fd, WRITE_BUFFER, &ioa_cmd);
if (rc != 0)
syslog(LOG_ERR, "Write buffer to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name);
else
{
/* Write buffer was successful. Now we need to see if all our devices
are available. The IOA may have been in braindead prior to the ucode
download, in which case the upper layer scsi device drivers do not
know anything about our devices. */
check_current_config(false);
for (j = 0; j < p_cur_ioa->num_devices; j++)
{
/* If not a DASD, ignore */
if (!IBMSIS_IS_DASD_DEVICE(p_cur_ioa->dev[j].p_resource_entry->std_inq_data))
continue;
/* See if we can open device */
dev_fd = open(p_cur_ioa->dev[j].dev_name, O_RDWR);
if ((dev_fd <= 1) && ((errno == ENOENT) || (errno == ENXIO)))
{
scan_device(p_cur_ioa->dev[j].p_resource_entry->resource_address,
p_cur_ioa->host_num);
}
else
close(dev_fd);
}
updated = 1;
}
}
/* Check DASD microcode */
for (i = 0; i < p_cur_ioa->num_devices; i++)
{
p_device = &p_cur_ioa->dev[i];
/* If not a DASD, ignore */
if (!IBMSIS_IS_DASD_DEVICE(p_cur_ioa->dev[i].p_resource_entry->std_inq_data) ||
((p_device->p_resource_entry->subtype != IBMSIS_SUBTYPE_AF_DASD) &&
(p_device->p_resource_entry->subtype != IBMSIS_SUBTYPE_GENERIC_SCSI)))
continue;
if (p_device->p_resource_entry->subtype == IBMSIS_SUBTYPE_GENERIC_SCSI)
p_dev_name = p_device->gen_name;
else
p_dev_name = p_cur_ioa->ioa.dev_name;
/* Do a page 3 inquiry */
dev_fd = open_dev(p_cur_ioa, p_device);
if (dev_fd > 1)
{
if (p_device->p_resource_entry->subtype == IBMSIS_SUBTYPE_GENERIC_SCSI)
{
memset(&dasd_page3_inq, 0, sizeof(dasd_page3_inq));
memset(cdb, 0, IBMSIS_CCB_CDB_LEN);
/* Issue page 3 inquiry */
cdb[0] = INQUIRY;
cdb[1] = 0x01; /* EVPD */
cdb[2] = 0x03; /* Page 3 */
cdb[4] = sizeof(dasd_page3_inq);
rc = sg_ioctl(dev_fd, cdb, &dasd_page3_inq,
sizeof(dasd_page3_inq),
SG_DXFER_FROM_DEV, &sense_data, 30);
if (rc == CHECK_CONDITION)
{
syslog(LOG_ERR, "Page 3 inquiry to %02X%02X%02X%02X failed: %x %x %x"IBMSIS_EOL,
p_device->p_resource_entry->host_no,
p_device->p_resource_entry->resource_address.bus,
p_device->p_resource_entry->resource_address.target,
p_device->p_resource_entry->resource_address.lun,
sense_data.sense_key & 0x0F,
sense_data.add_sense_code,
sense_data.add_sense_code_qual);
close(dev_fd);
continue;
}
}
else
{
memset(&ioa_cmd, 0, sizeof(ioa_cmd));
ioa_cmd.buffer = &dasd_page3_inq;
ioa_cmd.buffer_len = sizeof(dasd_page3_inq);
ioa_cmd.cdb[1] = 0x01;
ioa_cmd.cdb[2] = 0x03;
ioa_cmd.read_not_write = 1;
ioa_cmd.device_cmd = 1;
ioa_cmd.resource_address = p_device->p_resource_entry->resource_address;
rc = sis_ioctl(dev_fd, INQUIRY, &ioa_cmd);
}
if (rc != 0)
{
syslog(LOG_ERR, "Inquiry to %02X%02X%02X%02X failed. %m"IBMSIS_EOL,
p_device->p_resource_entry->host_no,
p_device->p_resource_entry->resource_address.bus,
p_device->p_resource_entry->resource_address.target,
p_device->p_resource_entry->resource_address.lun);
close(dev_fd);
continue;
}
device_update_blocked = 0;
/* check if vendor id is IBMAS400 */
if (memcmp(p_device->p_resource_entry->std_inq_data.vpids.vendor_id, "IBMAS400", 8) == 0)
{
sprintf(ucode_file, "/etc/microcode/device/ibmsis%02X%02X%02X%02X.img",
dasd_page3_inq.load_id[0], dasd_page3_inq.load_id[1],
dasd_page3_inq.load_id[2],
dasd_page3_inq.load_id[3]);
image_offset = 0;
}
else if (memcmp(p_device->p_resource_entry->std_inq_data.vpids.vendor_id, "IBM ", 8) == 0)
{
if (p_device->opens)
{
device_update_blocked = 1;
}
sprintf(ucode_file, "/etc/microcode/device/%.7s.%02X%02X%02X%02X",
p_device->p_resource_entry->std_inq_data.vpids.product_id,
dasd_page3_inq.load_id[0], dasd_page3_inq.load_id[1],
dasd_page3_inq.load_id[2],
dasd_page3_inq.load_id[3]);
image_offset = sizeof(struct ibmsis_dasd_ucode_header);
}
else if ((platform == SIS_ISERIES) || (platform == SIS_PSERIES))
{
close(dev_fd);
continue;
}
else
{
close(dev_fd);
continue;
}
do_download = 0;
/* Parse the binary file */
dasd_ucode_fd = open(ucode_file, O_RDONLY);
if (dasd_ucode_fd < 0)
{
syslog_dbg(LOG_ERR, "Could not open firmware file %s. %m"IBMSIS_EOL, ucode_file);
close(dev_fd);
continue;
}
/* Get the size of the microcode image */
rc = fstat(dasd_ucode_fd, &ucode_stats);
if (rc != 0)
{
syslog(LOG_ERR, "Error accessing firmware file: %s. %m"IBMSIS_EOL, ucode_file);
close(dev_fd);
close(dasd_ucode_fd);
continue;
}
/* Map the image in memory */
p_dasd_image_hdr = mmap(NULL, ucode_stats.st_size,
PROT_READ, MAP_SHARED, dasd_ucode_fd, 0);
if (p_dasd_image_hdr == MAP_FAILED)
{
syslog(LOG_ERR, "Error reading firmware file: %s. %m"IBMSIS_EOL, ucode_file);
close(dev_fd);
close(dasd_ucode_fd);
continue;
}
if ((memcmp(p_dasd_image_hdr->load_id, dasd_page3_inq.load_id, 4)) &&
(memcmp(p_device->p_resource_entry->std_inq_data.vpids.vendor_id, "IBMAS400", 8) == 0))
{
syslog(LOG_ERR, "Firmware file corrupt: %s. %m"IBMSIS_EOL, ucode_file);
close(dev_fd);
close(dasd_ucode_fd);
munmap(p_dasd_image_hdr, ucode_stats.st_size);
continue;
}
if ((memcmp(p_dasd_image_hdr->modification_level,
dasd_page3_inq.release_level, 4) > 0) ||
(force_download == 1) ||
(force_devs == 1))
{
if (device_update_blocked)
{
if (is_af_blocked(&p_cur_ioa->dev[j], 1))
{
u320_disabled |= (1 << p_device->p_resource_entry->resource_address.bus) |
SIS_SAVE_LIMITED_CONFIG;
}
syslog(LOG_ERR,"Device update to %02X%02X%02X%02X blocked, device in use."IBMSIS_EOL,
p_device->p_resource_entry->host_no,
p_device->p_resource_entry->resource_address.bus,
p_device->p_resource_entry->resource_address.target,
p_device->p_resource_entry->resource_address.lun);
continue;
}
if ((p_device->p_resource_entry->subtype == IBMSIS_SUBTYPE_GENERIC_SCSI) &&
(memcmp(p_device->p_resource_entry->std_inq_data.vpids.vendor_id, "IBMAS400", 8) == 0))
{
/* updating AS400 drives which are 512 formatted is not a supported operation */
continue;
}
if (isprint(p_dasd_image_hdr->modification_level[0]) &&
isprint(p_dasd_image_hdr->modification_level[1]) &&
isprint(p_dasd_image_hdr->modification_level[2]) &&
isprint(p_dasd_image_hdr->modification_level[3]) &&
isprint(dasd_page3_inq.release_level[0]) &&
isprint(dasd_page3_inq.release_level[1]) &&
isprint(dasd_page3_inq.release_level[2]) &&
isprint(dasd_page3_inq.release_level[3]))
{
syslog(LOG_NOTICE, "Updating DASD firmware on %02X%02X%02X%02X, using file %s from version %c%c%c%c to %c%c%c%c"IBMSIS_EOL,
p_device->p_resource_entry->host_no,
p_device->p_resource_entry->resource_address.bus,
p_device->p_resource_entry->resource_address.target,
p_device->p_resource_entry->resource_address.lun,
ucode_file,
dasd_page3_inq.release_level[0],
dasd_page3_inq.release_level[1],
dasd_page3_inq.release_level[2],
dasd_page3_inq.release_level[3],
p_dasd_image_hdr->modification_level[0],
p_dasd_image_hdr->modification_level[1],
p_dasd_image_hdr->modification_level[2],
p_dasd_image_hdr->modification_level[3]);
}
else
{
syslog(LOG_NOTICE, "Updating DASD firmware on %02X%02X%02X%02X, using file %s"IBMSIS_EOL,
p_device->p_resource_entry->host_no,
p_device->p_resource_entry->resource_address.bus,
p_device->p_resource_entry->resource_address.target,
p_device->p_resource_entry->resource_address.lun,
ucode_file);
}
p_dasd_image = (void *)p_dasd_image_hdr + image_offset;
image_size = ucode_stats.st_size - image_offset;
/* Do the update if the firmware file is newer than the firmware loaded on the DASD */
if (p_device->p_resource_entry->subtype == IBMSIS_SUBTYPE_GENERIC_SCSI)
{
memset(cdb, 0, IBMSIS_CCB_CDB_LEN);
/* Issue mode sense to get the block size */
cdb[0] = WRITE_BUFFER;
cdb[1] = 5; /* Mode 5 */
cdb[6] = (image_size & 0xff0000) >> 16;
cdb[7] = (image_size & 0x00ff00) >> 8;
cdb[8] = image_size & 0x0000ff;
rc = sg_ioctl(dev_fd, cdb,
p_dasd_image, image_size, SG_DXFER_TO_DEV,
&sense_data, 120);
}
else
{
memset(&ioa_cmd, 0, sizeof(ioa_cmd));
ioa_cmd.buffer = (void *)p_dasd_image;
ioa_cmd.buffer_len = image_size;
ioa_cmd.read_not_write = 0;
ioa_cmd.device_cmd = 1;
ioa_cmd.resource_address = p_device->p_resource_entry->resource_address;
rc = sis_ioctl(dev_fd, WRITE_BUFFER, &ioa_cmd);
}
if (rc != 0)
syslog(LOG_ERR, "Write buffer to %02X%02X%02X%02X failed. %m"IBMSIS_EOL,
p_device->p_resource_entry->host_no,
p_device->p_resource_entry->resource_address.bus,
p_device->p_resource_entry->resource_address.target,
p_device->p_resource_entry->resource_address.lun);
}
close(dev_fd);
close(dasd_ucode_fd);
if (munmap(p_dasd_image_hdr, ucode_stats.st_size))
syslog(LOG_ERR, "munmap failed. %m"IBMSIS_EOL);
}
else
{
syslog(LOG_ERR, "Cannot open device %s. Retry failed. %m"IBMSIS_EOL, p_dev_name);
continue;
}
}
munmap(p_image_hdr, ucode_stats.st_size);
close (ucode_fd);
close (fd);
if (RC_SUCCESS == sis_config_file_valid(config_file_name))
{
sis_set_page_28(p_cur_ioa, u320_disabled,
do_download | force_download | force_ioas);
}
else
{
sis_set_page_28_init(p_cur_ioa, u320_disabled);
}
}
return rc;
}
int open_dev(struct sis_ioa *p_ioa, struct sis_device *p_device)
{
int dev_fd;
if (p_device->p_resource_entry->subtype == IBMSIS_SUBTYPE_GENERIC_SCSI)
{
dev_fd = open(p_device->gen_name, O_RDWR);
if ((dev_fd <= 1) && ((errno == ENOENT) || (errno == ENXIO)))
{
syslog(LOG_ERR, "Cannot open device %s. %m"IBMSIS_EOL, p_device->gen_name);
syslog(LOG_ERR, "Rescanning SCSI bus for device"IBMSIS_EOL);
scan_device(p_device->p_resource_entry->resource_address, p_ioa->host_num);
dev_fd = open(p_device->gen_name, O_RDWR);
}
}
else
dev_fd = open(p_ioa->ioa.dev_name, O_RDWR);
return dev_fd;
}

52
spec/iprutils.spec Normal file
View file

@ -0,0 +1,52 @@
Summary: Utilities for the IBM iSeries/pSeries SCSI storage adapter
Name: ibmsisutils
Version: 1.19.12
Release: 1
License: IPL
Group: Hardware/SCSI
Source0: ibmsisutils-%version-src.tgz
BuildRequires: ibmsis-devel
%description
Provides a suite of utilities to manage and configure SCSI devices
supported by the ibmsis SCSI storage device driver.
%prep
rm -rf $RPM_BUILD_DIR/sisutils
tar -xvzf $RPM_SOURCE_DIR/ibmsisutils-%version-src.tgz
%build
cd sisutils
make
%install
cd sisutils
make INSTALL_MOD_PATH=$RPM_BUILD_ROOT install
install -d $RPM_BUILD_ROOT/etc/rc.d/init.d
install init.d/sisdump $RPM_BUILD_ROOT/etc/rc.d/init.d/sisdump
install init.d/sisupdate $RPM_BUILD_ROOT/etc/rc.d/init.d/sisupdate
%post
/sbin/chkconfig --add sisdump
/sbin/chkconfig --add sisupdate
%postun
/sbin/chkconfig --del sisdump
/sbin/chkconfig --del sisupdate
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
%doc sisutils/README
/sbin/sisconfig
/sbin/sisupdate
/sbin/sisdump
/sbin/sistrace
/sbin/sisdbg
%{_mandir}/man8/sisdump.8.gz
%{_mandir}/man8/sisconfig.8.gz
%{_mandir}/man8/sisupdate.8.gz
/etc/rc.d/init.d/sisupdate
/etc/rc.d/init.d/sisdump

12
version.mk Normal file
View file

@ -0,0 +1,12 @@
IPR_MAJOR_RELEASE=1
IPR_MINOR_RELEASE=0
IPR_FIX_LEVEL=0
IPR_FIX_DATE=(October 22, 2003)
IPR_VERSION_STR=Ver. $(IPR_MAJOR_RELEASE) Rev. $(IPR_MINOR_RELEASE).$(IPR_FIX_LEVEL)
IPR_DEFINES = -DIPR_MAJOR_RELEASE=$(IPR_MAJOR_RELEASE) \
-DIPR_MINOR_RELEASE=$(IPR_MINOR_RELEASE) \
-DIPR_FIX_LEVEL=$(IPR_FIX_LEVEL) \
-DIPR_FIX_DATE='"$(IPR_FIX_DATE)"' \
-DIPR_VERSION_STR='"$(IPR_VERSION_STR)"'