commit 5b6d45f28626cbb3bc4e055a1196932f0eceda9e Author: manderso Date: Wed Oct 22 22:21:02 2003 +0000 Initial revision diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..f8e7409 --- /dev/null +++ b/CHANGES @@ -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 +--------------------------------------------------------------------- diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c53db84 --- /dev/null +++ b/Makefile @@ -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 diff --git a/README b/README new file mode 100644 index 0000000..d85b8a1 --- /dev/null +++ b/README @@ -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. + diff --git a/init.d/iprdump b/init.d/iprdump new file mode 100644 index 0000000..744c541 --- /dev/null +++ b/init.d/iprdump @@ -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 $? diff --git a/init.d/iprupdate b/init.d/iprupdate new file mode 100644 index 0000000..2c3d40c --- /dev/null +++ b/init.d/iprupdate @@ -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 $? diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..ed580dc --- /dev/null +++ b/install.sh @@ -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 diff --git a/iprconfig.8 b/iprconfig.8 new file mode 100644 index 0000000..0274efc --- /dev/null +++ b/iprconfig.8 @@ -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. diff --git a/iprconfig.c b/iprconfig.c new file mode 100644 index 0000000..9f4af11 --- /dev/null +++ b/iprconfig.c @@ -0,0 +1,20884 @@ +/******************************************************************/ +/* Linux IBM SIS configuration utility */ +/* Description: IBM Storage IOA Interface Specification (SIS) */ +/* Linux configuration utility */ +/* */ +/* (C) Copyright 2000, 2001 */ +/* International Business Machines Corporation and others. */ +/* All Rights Reserved. */ +/******************************************************************/ + +/* + * $Header: /cvsroot/iprdd/iprutils/iprconfig.c,v 1.1 2003/10/22 22:21:02 manderso Exp $ + */ + +#ifndef iprlib_h +#include "iprlib.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct device_detail_struct{ + struct sis_ioa *p_ioa; + struct sis_device *p_sis_dev; + int field_index; +}; + +typedef struct { + WINDOW *init_win; + WINDOW *win; + FORM *p_form; + struct termios term; + int max_x; + int max_y; + int start_x; + int start_y; +} curses_info_t; + +struct devs_to_init_t{ + struct sis_device *p_sis_device; + struct sis_ioa *p_ioa; + int change_size; +#define SIS_522_BLOCK 522 +#define SIS_512_BLOCK 512 + int cmplt; + int fd; + int do_init; + int dev_type; +#define IBMSIS_AF_DASD_DEVICE 1 +#define IBMSIS_JBOD_DASD_DEVICE 2 + struct devs_to_init_t *p_next; +}; + +struct prot_level +{ + struct ibmsis_array_cap_entry *p_array_cap_entry; + u8 is_valid_entry:1; + u8 reserved:7; +}; + +struct array_cmd_data{ + u8 array_id; + u8 prot_level; + u16 stripe_size; + u32 array_num; + u32 do_cmd; + struct ibmsis_array_query_data *p_qac_data; + struct sis_ioa *p_sis_ioa; + struct sis_device *p_sis_device; + struct array_cmd_data *p_next; +}; + +struct window_l{ + WINDOW *p_win; + struct window_l *p_next; +}; + +struct panel_l{ + PANEL *p_panel; + struct panel_l *p_next; +}; + +static int max_x, max_y; +static int start_x, start_y; +static curses_info_t curses_info; +struct devs_to_init_t *p_head_dev_to_init; +struct devs_to_init_t *p_tail_dev_to_init; +struct array_cmd_data *p_head_raid_cmd; +struct array_cmd_data *p_tail_raid_cmd; +static char dev_field[] = "dev"; +static int term_is_5250 = 0; +char log_root_dir[200]; +char editor[200]; +FILE *errpath; + +#define DEFAULT_LOG_DIR "/var/log" +#define DEFAULT_EDITOR "vi -R" +#define FAILSAFE_EDITOR "vi -R -" +#define IS_CANCEL_KEY(c) ((c == KEY_F(4)) || (c == 'q') || (c == 'Q')) +#define CANCEL_KEY_LABEL "q" +#define IS_EXIT_KEY(c) ((c == KEY_F(3)) || (c == 'e') || (c == 'E')) +#define EXIT_KEY_LABEL "e" +#define ENTER_KEY 13 +#define IS_ENTER_KEY(c) ((c == KEY_ENTER) || (c == ENTER_KEY)) +#define IS_REFRESH_KEY(c) ((c == 'r') || (c == 'R')) +#define REFRESH_KEY_LABEL "r" + +#define IS_PGDN_KEY(c) ((c == KEY_NPAGE) || (c == 'f') || (c == 'F')) +#define IS_PGUP_KEY(c) ((c == KEY_PPAGE) || (c == 'b') || (c == 'B')) + +#define IS_5250_CHAR(c) (c == 0xa) + +char *strip_trailing_whitespace(char *p_str); +u16 print_dev(struct ibmsis_resource_entry *p_resource_entry, + char *p_buf, + char *dev_name); +u16 print_dev2(struct ibmsis_resource_entry *p_resource_entry, + char *p_buf, + struct ibmsis_resource_flags *p_resource_flags, + char *dev_name); +u16 print_dev_sel(struct ibmsis_resource_entry *p_resource_entry, char *p_buf); +u16 print_dev_pty(struct ibmsis_resource_entry *p_resource_entry, char *p_buf, char *dev_name); +u16 print_dev_pty2(struct ibmsis_resource_entry *p_resource_entry, char *p_buf, char *dev_name); +int device_concurrent_maintenance(); +int issue_concurrent_maintenance(char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, + char *p_action, char *p_delay); +int is_valid_device(char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun); +u16 get_model(struct ibmsis_resource_flags *p_resource_flags); +int not_implemented(); +int init_device(); +int confirm_init_device(); +void handle_sig_int(int dummy); +void handle_sig_term(int signal); +void handle_sig_winch(int dummy); +int open_dev(struct sis_ioa *p_ioa, struct sis_device *p_device); +void free_screen(struct panel_l *p_panel, struct window_l *p_win, FIELD **p_fields); +int confirm_reclaim(struct sis_ioa *p_reclaim_ioa); +int reclaim_result(struct sis_ioa *p_reclaim_ioa); +int device_details(struct device_detail_struct *p_detail_device); +int disk_unit_details(); +int device_extended_vpd(struct device_detail_struct *p_detail_device); +int select_log_file(const struct dirent *p_dir_entry); +int compare_log_file(const void *pp_first, const void *pp_second); +void revalidate_devs(struct sis_ioa *p_ioa); +void revalidate_dev(struct sis_device *p_sis_device, struct sis_ioa *p_ioa, int force); +void evaluate_device(struct sis_device *p_sis_device, struct sis_ioa *p_ioa, int change_size); +void flush_stdscr(); +int flush_line(); +void disk_unit_recovery(); +int concurrent_maintenance_warning(struct sis_ioa *p_ioa, + struct sis_device *p_sis_device, + char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, + char *p_action, u32 delay); +int do_dasd_conc_maintenance(struct sis_ioa *p_ioa, + struct sis_device *p_sis_device, + char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, + char *p_action, u32 delay, int replace_dev); +int conc_maintenance_complt(struct sis_ioa *p_ioa, + struct sis_device *p_sis_device, + char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, + char *p_action, u32 delay, int replace_dev); +int conc_maintenance_failed(char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, char *p_action, int rc); +int is_array_in_use(struct sis_ioa *p_cur_ioa, u8 array_id); +int display_menu(ITEM **menu_item, + int menu_start_row, + int menu_index_max, + int **userptr); +int print_parity_status(char *buffer, + u8 array_id, + struct ibmsis_query_res_state *p_res_state, + struct ibmsis_cmd_status *p_cmd_status); + +int main(int argc, char *argv[]) +{ + int main_menu(); + int next_editor, next_dir, next_platform, i; + char parm_editor[200], parm_dir[200], platform_str[200]; + bool platform_override = false; + + p_head_sis_ioa = p_last_sis_ioa = NULL; + + setenv("TERM", "vt100", 1); + + strcpy(parm_dir, DEFAULT_LOG_DIR); + strcpy(parm_editor, DEFAULT_EDITOR); + + openlog("sisconfig", + 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) + { + next_editor = 0; + next_dir = 0; + next_platform = 0; + for (i = 1; i < argc; i++) + { + if (strcmp(argv[i], "-e") == 0) + next_editor = 1; + else if (strcmp(argv[i], "-k") == 0) + next_dir = 1; + else if (strcmp(argv[i], "-p") == 0) + next_platform = 1; + else if (strcmp(argv[i], "--version") == 0) + { + printf("sisconfig: %s"IBMSIS_EOL, IPR_VERSION_STR); + exit(1); + } + else if (next_editor) + { + strcpy(parm_editor, argv[i]); + next_editor = 0; + } + else if (next_dir) + { + strcpy(parm_dir, argv[i]); + next_dir = 0; + } + else if (next_platform) + { + strcpy(platform_str, argv[i]); + next_platform = 0; + platform_override = true; + } + else + { + printf("Usage: sisconfig [options]"IBMSIS_EOL); + printf(" Options: -e name Default editor for viewing error logs"IBMSIS_EOL); + printf(" -k dir Kernel messages root directory"IBMSIS_EOL); + printf(" --version Print sisconfig version"IBMSIS_EOL); + printf(" Use quotes around parameters with spaces"IBMSIS_EOL); + exit(1); + } + } + } + + strcpy(log_root_dir, parm_dir); + strcpy(editor, parm_editor); + + tool_init("sisconfig"); + + if (platform_override) + { + if (strcasecmp(platform_str, "iseries") == 0) + platform = SIS_ISERIES; + else if (strcasecmp(platform_str, "pseries") == 0) + platform = SIS_PSERIES; + else + platform = SIS_GENERIC; + } + + /* Do ncurses initialization stuff */ + curses_info.init_win = initscr(); + getmaxyx(curses_info.init_win, max_y, max_x); + getbegyx(curses_info.init_win, start_y, start_x); + if (max_y < 16) + { + endwin(); + printf("ERROR: sisconfig requires a window size containing at least 16 rows"IBMSIS_EOL); + printf(" current number of rows is %d"IBMSIS_EOL, max_y); + syslog(LOG_ERR, "Fatal Error! sisconfig requires a window size containing at least 16 rows"IBMSIS_EOL); + exit(1); + } + curses_info.max_y = max_y; + curses_info.max_x = max_x; + curses_info.start_y = start_y; + curses_info.start_x = start_x; + cbreak(); /* take input chars one at a time, no wait for \n */ + noecho(); + nonl(); + keypad(stdscr, TRUE); + + signal(SIGINT, handle_sig_int); + signal(SIGQUIT, handle_sig_term); + signal(SIGTERM, handle_sig_term); + signal(SIGWINCH, handle_sig_winch); + + while(RC_REFRESH == main_menu()) + { + } + + return 0; +} + +int main_menu() +{ + /* + Work with Disk Units + + Select one of the following: + + 1. Display disk hardware status + 2. Work with device parity protection + 3. Work with disk unit recovery + 4. Work with configuration + 5. Analyze Log + + + + Selection: + + e=Exit + + */ + int rc; + FIELD *p_fields[3]; + FORM *p_form; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_cmd_status cmd_status; + char init_message[60]; + int fd, fdev, k, j, ch2; + struct ibmsis_cmd_status_record *p_status_record; + int num_devs = 0; + int num_stops = 0; + int num_starts = 0; + struct sis_ioa *p_cur_ioa; + struct devs_to_init_t *p_cur_dev_to_init; + struct array_cmd_data *p_cur_raid_cmd; + u8 ioctl_buffer[255], *p_byte; + struct sense_data_t sense_data; + u8 cdb[IBMSIS_CCB_CDB_LEN]; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_mode_parm_hdr *p_mode_parm_hdr; + struct ibmsis_block_desc *p_block_desc; + int loop, len, retries; + + void raid_screen(); + int disk_status(); + int reclaim_cache(); + int dev_init_complete(u8 num_devs); + void log_menu(); + int raid_status(); + int raid_stop_complete(); + int raid_start_complete(); + void configure_options(); + + init_message[0] = '\0'; + + check_current_config(false); + + for(p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + p_cur_ioa->num_raid_cmds = 0; + + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + continue; + } + + /* Do a query command status to see if any long running array commands + are currently running */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &cmd_status; + ioa_cmd.buffer_len = sizeof(cmd_status); + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_QUERY_COMMAND_STATUS, &ioa_cmd); + + if (rc != 0) + { + if (errno != EINVAL) + syslog(LOG_ERR, "Query command status to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + close(fd); + continue; + } + + p_status_record = cmd_status.record; + + for (k = 0; k < cmd_status.num_records; k++, p_status_record++) + { + if ((p_status_record->status & IBMSIS_CMD_STATUS_IN_PROGRESS)) + { + if (p_status_record->command_code == IBMSIS_START_ARRAY_PROTECTION) + { + p_cur_ioa->num_raid_cmds++; + num_starts++; + + if (p_head_raid_cmd) + { + p_tail_raid_cmd->p_next = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + p_tail_raid_cmd = p_tail_raid_cmd->p_next; + } + else + { + p_head_raid_cmd = p_tail_raid_cmd = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + } + + p_tail_raid_cmd->p_next = NULL; + + memset(p_tail_raid_cmd, 0, sizeof(struct array_cmd_data)); + + p_tail_raid_cmd->array_id = p_status_record->array_id; + p_tail_raid_cmd->p_sis_ioa = p_cur_ioa; + p_tail_raid_cmd->do_cmd = 1; + } + else if (p_status_record->command_code == IBMSIS_STOP_ARRAY_PROTECTION) + { + p_cur_ioa->num_raid_cmds++; + num_stops++; + + if (p_head_raid_cmd) + { + p_tail_raid_cmd->p_next = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + p_tail_raid_cmd = p_tail_raid_cmd->p_next; + } + else + { + p_head_raid_cmd = p_tail_raid_cmd = + (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + } + + p_tail_raid_cmd->p_next = NULL; + + memset(p_tail_raid_cmd, 0, sizeof(struct array_cmd_data)); + + p_tail_raid_cmd->array_id = p_status_record->array_id; + p_tail_raid_cmd->p_sis_ioa = p_cur_ioa; + p_tail_raid_cmd->do_cmd = 1; + } + else if (p_status_record->command_code == IBMSIS_ADD_ARRAY_DEVICE) + { + while(RC_REFRESH == raid_status()) + { + } + } + else if (p_status_record->command_code == IBMSIS_REMOVE_ARRAY_DEVICE) + { + while(RC_REFRESH == raid_status()) + { + } + } + } + } + + /* Do a query command status for all devices to check for formats in + progress */ + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + + if (p_resource_entry->is_ioa_resource) + continue; + + if (p_resource_entry->is_af) + { + /* ignore if its a volume set */ + if (p_resource_entry->subtype == IBMSIS_SUBTYPE_VOLUME_SET) + continue; + + /* Do a query command status */ + ioa_cmd.buffer = &cmd_status; + ioa_cmd.buffer_len = sizeof(cmd_status); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_resource_entry->resource_address; + + rc = sis_ioctl(fd, IBMSIS_QUERY_COMMAND_STATUS, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Query Command status to %s failed. %m"IBMSIS_EOL, p_cur_ioa->dev[j].dev_name); + close(fd); + continue; + } + + if (cmd_status.num_records == 0) + { + /* Do nothing */ + } + else + { + if (cmd_status.record->status == IBMSIS_CMD_STATUS_IN_PROGRESS) + { + if (strlen(p_cur_ioa->dev[j].dev_name) != 0) + { + fdev = open(p_cur_ioa->dev[j].dev_name, O_RDWR | O_NONBLOCK); + + if (fdev) + { + fcntl(fdev, F_SETFD, 0); + + /* Try to get an exclusive lock to the device */ + rc = flock(fdev, LOCK_EX | LOCK_NB); + } + + /* If one already exists, continue anyway */ + if (rc && (errno != EWOULDBLOCK)) + { + syslog(LOG_ERR, "Couldn't set lock on %s. %m rc=0x%x"IBMSIS_EOL, p_cur_ioa->dev[j].dev_name, rc); + } + } + else + { + fdev = 0; + } + + if (p_head_dev_to_init) + { + p_tail_dev_to_init->p_next = (struct devs_to_init_t *)malloc(sizeof(struct devs_to_init_t)); + p_tail_dev_to_init = p_tail_dev_to_init->p_next; + } + else + p_head_dev_to_init = p_tail_dev_to_init = (struct devs_to_init_t *)malloc(sizeof(struct devs_to_init_t)); + + memset(p_tail_dev_to_init, 0, sizeof(struct devs_to_init_t)); + + p_tail_dev_to_init->p_ioa = p_cur_ioa; + p_tail_dev_to_init->dev_type = IBMSIS_AF_DASD_DEVICE; + p_tail_dev_to_init->p_sis_device = &p_cur_ioa->dev[j]; + p_tail_dev_to_init->fd = fdev; + p_tail_dev_to_init->do_init = 1; + + num_devs++; + } + else if (cmd_status.record->status == IBMSIS_CMD_STATUS_SUCCESSFUL) + { + /* Check if evaluate device capabilities is necessary */ + /* Issue mode sense */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_resource_entry->resource_address; + + rc = sis_ioctl(fd, MODE_SENSE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->dev[j].dev_name); + } + else + { + if (p_mode_parm_hdr->block_desc_len > 0) + { + p_block_desc = (struct ibmsis_block_desc *)(p_mode_parm_hdr+1); + + if((p_block_desc->block_length[1] == 0x02) && + (p_block_desc->block_length[2] == 0x00)) + { + /* Send evaluate device capabilities */ + remove_device(p_cur_ioa->dev[j].p_resource_entry->resource_address, + p_cur_ioa); + evaluate_device(&p_cur_ioa->dev[j], p_cur_ioa, SIS_512_BLOCK); + } + + } + } + } + } + } + else /* JBOD */ + { + retries = 0; + + redo_tur: + /* Send Test Unit Ready to find percent complete in sense data. */ + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + if ((fdev = open(p_cur_ioa->dev[j].gen_name, O_RDWR)) < 0) + { + if (strlen(p_cur_ioa->dev[j].gen_name) != 0) + syslog(LOG_ERR, "Unable to open device %s. %m"IBMSIS_EOL, + p_cur_ioa->dev[j].gen_name); + continue; + } + + cdb[0] = TEST_UNIT_READY; + + rc = sg_ioctl(fdev, cdb, + NULL, 0, SG_DXFER_NONE, + &sense_data, 30); + + if (rc < 0) + { + syslog(LOG_ERR, "Could not send test unit ready to %s. %m"IBMSIS_EOL,p_cur_ioa->dev[j].dev_name); + } + else if ((rc == CHECK_CONDITION) && + ((sense_data.error_code & 0x7F) == 0x70) && + ((sense_data.sense_key & 0x0F) == 0x02) && /* NOT READY */ + (sense_data.add_sense_code == 0x04) && /* LOGICAL UNIT NOT READY */ + (sense_data.add_sense_code_qual == 0x02)) /* INIT CMD REQ */ + { + cdb[0] = START_STOP; + cdb[4] = IBMSIS_START_STOP_START; + + rc = sg_ioctl(fdev, cdb, + NULL, 0, SG_DXFER_NONE, + &sense_data, 120); + + if (retries == 0) + { + retries++; + goto redo_tur; + } + else + { + syslog(LOG_ERR, "Test Unit Ready failed to %s. %m"IBMSIS_EOL, + p_cur_ioa->dev[j].gen_name); + } + } + else if ((rc == CHECK_CONDITION) && + ((sense_data.error_code & 0x7F) == 0x70) && + ((sense_data.sense_key & 0x0F) == 0x02) && /* NOT READY */ + (sense_data.add_sense_code == 0x04) && /* LOGICAL UNIT NOT READY */ + (sense_data.add_sense_code_qual == 0x04)) /* FORMAT IN PROGRESS */ + { + if (p_head_dev_to_init) + { + p_tail_dev_to_init->p_next = (struct devs_to_init_t *)malloc(sizeof(struct devs_to_init_t)); + p_tail_dev_to_init = p_tail_dev_to_init->p_next; + } + else + p_head_dev_to_init = p_tail_dev_to_init = (struct devs_to_init_t *)malloc(sizeof(struct devs_to_init_t)); + + memset(p_tail_dev_to_init, 0, sizeof(struct devs_to_init_t)); + + p_tail_dev_to_init->p_ioa = p_cur_ioa; + p_tail_dev_to_init->dev_type = IBMSIS_JBOD_DASD_DEVICE; + p_tail_dev_to_init->p_sis_device = &p_cur_ioa->dev[j]; + + p_tail_dev_to_init->fd = 0; + p_tail_dev_to_init->do_init = 1; + + num_devs++; + } + else if (rc == CHECK_CONDITION) + { + len = sprintf(ioctl_buffer, "Test Unit Ready failed to %s. %m ", + p_cur_ioa->dev[j].gen_name); + + p_byte = (u8 *)&sense_data; + + for (loop = 0; loop < 18; loop++) + { + len += sprintf(ioctl_buffer + len,"%.2x ", p_byte[loop]); + } + + syslog(LOG_ERR, "sense data = %s"IBMSIS_EOL, ioctl_buffer); + } + else + { + /* Check if evaluate device capabilities needs to be issued */ + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + /* Issue mode sense to get the block size */ + cdb[0] = MODE_SENSE; + cdb[2] = 0x0a; /* PC = current values, page code = 0ah */ + cdb[4] = 255; + + rc = sg_ioctl(fdev, cdb, + &ioctl_buffer, 255, SG_DXFER_FROM_DEV, + &sense_data, 30); + + if (rc < 0) + { + syslog(LOG_ERR, "Could not send mode sense to %s. %m"IBMSIS_EOL, + p_cur_ioa->dev[j].gen_name); + } + else if (rc == CHECK_CONDITION) + { + len = sprintf(ioctl_buffer,"Mode Sense failed to %s. %m ", + p_cur_ioa->dev[j].gen_name); + + p_byte = (u8 *)&sense_data; + + for (loop = 0; loop < 18; loop++) + { + len += sprintf(ioctl_buffer + len,"%.2x ",p_byte[loop]); + } + + syslog(LOG_ERR, "sense data = %s"IBMSIS_EOL, ioctl_buffer); + } + else + { + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + + if (p_mode_parm_hdr->block_desc_len > 0) + { + p_block_desc = (struct ibmsis_block_desc *)(p_mode_parm_hdr+1); + + if ((!(p_block_desc->block_length[1] == 0x02) || + !(p_block_desc->block_length[2] == 0x00)) && + (p_cur_ioa->p_qac_data->num_records != 0)) + { + /* send evaluate device */ + evaluate_device(&p_cur_ioa->dev[j], p_cur_ioa, SIS_522_BLOCK); + } + else + { + if (strlen(p_cur_ioa->dev[j].dev_name) == 0) + { + revalidate_dev(&p_cur_ioa->dev[j], + p_cur_ioa, 1); + } + } + } + } + } + close(fdev); + } + } + close(fd); + } + + if (num_devs) + { + rc = dev_init_complete(num_devs); + + if (rc == RC_SUCCESS) + sprintf(init_message, " Initialize and format completed successfully"); + else if (rc == RC_FAILED) + sprintf(init_message, " Initialize and format failed"); + } + else if (num_stops) + { + rc = raid_stop_complete(); + + if (rc == RC_SUCCESS) + sprintf(init_message, "Stop Parity Protection completed successfully"); + else if (rc == RC_FAILED) + sprintf(init_message, "Stop Parity Protection failed"); + } + else if (num_starts) + { + rc = raid_start_complete(); + + if (rc == RC_SUCCESS) + sprintf(init_message, "Start Parity Protection completed successfully"); + else if (rc == RC_FAILED) + sprintf(init_message, "Start Parity Protection failed"); + } + else + revalidate_devs(NULL); + + p_cur_dev_to_init = p_head_dev_to_init; + while(p_cur_dev_to_init) + { + p_cur_dev_to_init = p_cur_dev_to_init->p_next; + free(p_head_dev_to_init); + p_head_dev_to_init = p_cur_dev_to_init; + } + + p_cur_raid_cmd = p_head_raid_cmd; + while(p_cur_raid_cmd) + { + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + free(p_head_raid_cmd); + p_head_raid_cmd = p_cur_raid_cmd; + } + + /* Title */ + p_fields[0] = new_field(1, max_x - start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 12, 12, + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Work with Disk Units"); /* string value to set */ + + clear(); + refresh(); + post_form(p_form); + + mvaddstr(curses_info.max_y - 1, 0, init_message); + + while(1) + { + mvaddstr(2, 0, "Select one of the following:"); + mvaddstr(4, 0, " 1. Display disk hardware status"); + mvaddstr(5, 0, " 2. Work with device parity protection"); + mvaddstr(6, 0, " 3. Work with disk unit recovery"); + mvaddstr(7, 0, " 4. Work with configuration"); + mvaddstr(8, 0, " 5. Analyze Log"); + mvaddstr(12, 0, "Selection: "); + mvaddstr(curses_info.max_y - 2, 0, EXIT_KEY_LABEL"=Exit"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + refresh(); + for (;;) + { + int ch = getch(); + + if (IS_ENTER_KEY(ch)) + { + char *p_char; + unpost_form(p_form); + + nodelay(stdscr, TRUE); + ch2 = getch(); + nodelay(stdscr, FALSE); + + if (IS_5250_CHAR(ch2)) + term_is_5250 = 1; + + p_char = field_buffer(p_fields[1], 0); + switch(p_char[0]) + { + case '1': + while (RC_REFRESH == (rc = disk_status())) + clear(); + clear(); + post_form(p_form); + break; + case '2': + raid_screen(); + clear(); + post_form(p_form); + break; + case '3': + disk_unit_recovery(); + clear(); + post_form(p_form); + break; + case '4': + configure_options(); + clear(); + post_form(p_form); + break; + case '5': + log_menu(); + clear(); + post_form(p_form); + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + break; + case ' ': + clear(); + post_form(p_form); + break; + default: + clear(); + post_form(p_form); + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + break; + } + form_driver(p_form, ' '); + break; + } + else if (IS_EXIT_KEY(ch) || IS_CANCEL_KEY(ch)) + { + unpost_form(p_form); + free_form(p_form); + + for (j=0; j < 2; j++) + free_field(p_fields[j]); + clear(); + refresh(); + endwin(); + exit(EXIT_SUCCESS); + return 0; + } + else if (( ch == '1') || (ch == '2') || (ch == '3') || (ch == '4') || (ch == '5')) + { + form_driver(p_form, ch); + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + } + } + } +} + +int disk_status() +{ +#define DISK_STATUS_HDR_SIZE 4 +#define DISK_STATUS_MENU_SIZE 5 + + /* iSeries + Display Disk Hardware Status + + Serial Resource Hardware + Number Type Model Name Status + 02137002 2757 001 /dev/ibmsis6 Operational + 03060044 5703 001 /dev/ibmsis5 Not Operational + 02127005 2782 001 /dev/ibmsis4 Operational + 002443C6 6713 072 /dev/sdr DPY/Active + 0024B45C 6713 072 /dev/sds DPY/Active + 00000DC7 6717 072 /dev/sdt DPY/Active + 000BBBC1 6717 072 /dev/sdu DPY/Active + 0002F5AA 6717 070 /dev/sdv DPY/Active + 02123028 5702 001 /dev/ibmsis3 Operational + 09112004 2763 001 /dev/ibmsis2 Operational + 0007438C 6607 050 /dev/sdm Perf Degraded + 0006B81C 6607 050 /dev/sdn Perf Degraded + 00224BF2 6713 050 /dev/sdo Perf Degraded + 00224ABE 6713 050 /dev/sdp Perf Degraded + More... + Press Enter to continue. + + e=Exit q=Cancel r=Refresh f=PageDn b=PageUp + d=Display disk unit details p=Display device parity status + */ + +/* non-iSeries + Display Disk Hardware Status + + Serial Vendor Product Resource Hardware + Number ID ID Model Name Status +03079003 IBM 2780001 001 /dev/ibmsis2 Operational +0024A0B9 IBMAS400 DCHS09W 070 DPY/Active +00D37A11 IBMAS400 DFHSS4W 070 DPY/Active +00D38D0F IBMAS400 DFHSS4W 070 DPY/Active +00034563 IBMAS400 DGVS09U 070 DPY/Active +00D32240 IBMAS400 DFHSS4W 050 Operational +443EA8CA IBM 01BB2952 200 /dev/sdb Operational +A014696F IBM 211CA8B1 200 /dev/sdc Operational +02056069 IBM 5702001 001 /dev/ibmsis1 Operational +02123012 IBM 5702001 001 /dev/ibmsis0 Operational + + + + + + +Press Enter to continue. + +e=Exit q=Cancel r=Refresh f=PageDn b=PageUp +d=Display disk unit details p=Display device parity status + +*/ + + int fd, rc, array_num, j; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + int len = 0; + char buffer[100]; + int max_size = curses_info.max_y - (DISK_STATUS_HDR_SIZE + DISK_STATUS_MENU_SIZE + 1); + int display_index = 0; + struct ibmsis_query_res_state res_state; + int num_lines = 0; + struct sis_ioa *p_cur_ioa; + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel, *p_cur_panel; + WINDOW *p_title_win, *p_menu_win; + PANEL *p_panel; + u8 ioctl_buffer[255]; + int status; + int format_req = 0; + struct ibmsis_resource_entry *p_resource_entry; + u8 cdb[IBMSIS_CCB_CDB_LEN]; + struct ibmsis_mode_parm_hdr *p_mode_parm_hdr; + struct ibmsis_block_desc *p_block_desc; + struct sense_data_t sense_data; + u8 product_id[IBMSIS_PROD_ID_LEN+1]; + u8 vendor_id[IBMSIS_VENDOR_ID_LEN+1]; + + int raid_status(); + + rc = RC_SUCCESS; + + p_title_win = newwin(DISK_STATUS_HDR_SIZE, + curses_info.max_x, + curses_info.start_y, + curses_info.start_x); + + p_menu_win = newwin(DISK_STATUS_MENU_SIZE, + curses_info.max_x, + curses_info.start_y + max_size + DISK_STATUS_HDR_SIZE + 1, + curses_info.start_x); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Display Disk Hardware Status"); /* string value to set */ + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + DISK_STATUS_HDR_SIZE, + curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + clear(); + post_form(p_form); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 2, 0, " Serial Resource Hardware"); + mvwaddstr(p_title_win, 3, 0, " Number Type Model Name Status"); + } + else + { + mvwaddstr(p_title_win, 2, 0, " Serial Vendor Product Resource Hardware"); + mvwaddstr(p_title_win, 3, 0, " Number ID ID Model Name Status"); + } + + mvwaddstr(p_menu_win, 0, 0, "Press Enter to continue."); + mvwaddstr(p_menu_win, + 2, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel r=Refresh f=PageDn b=PageUp"); + mvwaddstr(p_menu_win, 3, 0, "d=Display disk unit details p=Display device parity status"); + + check_current_config(false); + + for(p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + array_num = 1; + if (p_cur_ioa->ioa.p_resource_entry == NULL) + continue; + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, "%8s %X %03d %-39s ", + p_cur_ioa->serial_num, p_cur_ioa->ccin, 1, p_cur_ioa->ioa.dev_name); + } + else + { + memcpy(vendor_id, p_cur_ioa->ioa.p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + vendor_id[IBMSIS_VENDOR_ID_LEN] = '\0'; + memcpy(product_id, p_cur_ioa->ioa.p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + product_id[IBMSIS_PROD_ID_LEN] = '\0'; + + len = sprintf(buffer, "%8s %-8s %-18s %03d %-18s ", + p_cur_ioa->serial_num, + vendor_id, + product_id, + p_cur_ioa->ioa.p_resource_entry->model, p_cur_ioa->ioa.dev_name); + } + + if (p_cur_ioa->ioa.p_resource_entry->ioa_dead) + len += sprintf(buffer+len, "Not Operational"); + else if (p_cur_ioa->ioa.p_resource_entry->nr_ioa_microcode) + len += sprintf(buffer+len, "Not Ready"); + else + len += sprintf(buffer+len, "Operational"); + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + DISK_STATUS_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + if (p_resource_entry->is_ioa_resource) + { + continue; + } + + if (p_resource_entry->is_af) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + + /* Do a query resource state */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &res_state; + ioa_cmd.buffer_len = sizeof(res_state); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_resource_entry->resource_address; + + memset(&res_state, 0, sizeof(res_state)); + + rc = sis_ioctl(fd, IBMSIS_QUERY_RESOURCE_STATE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR,"Query Resource State failed. %m"IBMSIS_EOL); + sislog_location(p_resource_entry); + res_state.not_oper = 1; + } + close(fd); + } + else /* JBOD */ + { + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + memset(&res_state, 0, sizeof(res_state)); + + format_req = 0; + + /* Issue mode sense/mode select to determine if device needs to be formatted */ + cdb[0] = MODE_SENSE; + cdb[2] = 0x0a; /* PC = current values, page code = 0ah */ + cdb[4] = 255; + + fd = open(p_cur_ioa->dev[j].gen_name, O_RDONLY); + + if (fd <= 1) + { + if (strlen(p_cur_ioa->dev[j].gen_name) != 0) + syslog(LOG_ERR, "Could not open file %s. %m"IBMSIS_EOL, p_cur_ioa->dev[j].gen_name); + res_state.not_oper = 1; + } + else + { + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + memset(&sense_data, 0, sizeof(sense_data)); + + status = sg_ioctl(fd, cdb, + &ioctl_buffer, 255, SG_DXFER_FROM_DEV, + &sense_data, 30); + + if (status) + { + syslog(LOG_ERR, "Could not send mode sense to %s. %m"IBMSIS_EOL, p_cur_ioa->dev[j].gen_name); + res_state.not_oper = 1; + } + else + { + if (p_mode_parm_hdr->block_desc_len > 0) + { + p_block_desc = (struct ibmsis_block_desc *)(p_mode_parm_hdr+1); + + if ((p_block_desc->block_length[1] != 0x02) || + (p_block_desc->block_length[2] != 0x00)) + { + format_req = 1; + } + else + { + /* check device with test unit ready */ + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + cdb[0] = TEST_UNIT_READY; + + rc = sg_ioctl(fd, cdb, + NULL, 0, SG_DXFER_NONE, + &sense_data, 30); + + if ((rc < 0) || (rc == CHECK_CONDITION)) + { + format_req = 1; + } + } + } + } + + close(fd); + } + } + + len = print_dev(p_resource_entry, + buffer, + p_cur_ioa->dev[j].dev_name); + + if (res_state.not_oper) + len += sprintf(buffer + len, "Not Operational"); + else if (res_state.not_ready || + (res_state.read_write_prot && (sistoh32(res_state.failing_dev_ioasc) == 0x02040200u))) + len += sprintf(buffer + len, "Not ready"); + else if ((res_state.read_write_prot) || (p_resource_entry->rw_protected)) + len += sprintf(buffer + len, "R/W Protected"); + else if (res_state.prot_dev_failed) + len += sprintf(buffer + len, "DPY/Failed"); + else if (res_state.prot_suspended) + len += sprintf(buffer + len, "DPY/Unprotected"); + else if (res_state.prot_resuming) + len += sprintf(buffer + len, "DPY/Rebuilding"); + else if (res_state.degraded_oper) + len += sprintf(buffer + len, "Perf Degraded"); + else if (res_state.service_req) + len += sprintf(buffer + len, "Redundant Hw Fail"); + else if (format_req) + len += sprintf(buffer + len, "Format Required"); + else + { + if (p_resource_entry->is_array_member) + len += sprintf(buffer + len, "DPY/Active"); + else if (p_resource_entry->is_hot_spare) + len += sprintf(buffer + len, "HS/Active"); + else + len += sprintf(buffer + len, "Operational"); + } + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + DISK_STATUS_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + } + } + + if (num_lines == 0) + mvwaddstr(p_tail_win->p_win, 1, 2, "(No devices found)"); + + display_index = 0; + + p_cur_panel = p_head_panel; + + while(p_cur_panel) + { + bottom_panel(p_cur_panel->p_panel); + p_cur_panel = p_cur_panel->p_next; + } + + while(1) + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + update_panels(); + wrefresh(p_menu_win); + wrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_REFRESH_KEY(ch)) + { + rc = RC_REFRESH; + goto leave; + } + else if ((ch == 'd') || (ch == 'D')) + { + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + werase(stdscr); + + if (disk_unit_details() != RC_EXIT) + return RC_REFRESH; + else + return RC_EXIT; + } + else if ((ch == 'p') || (ch == 'P')) + { + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + while (RC_REFRESH == (rc = raid_status())) + { + clear(); + refresh(); + } + if (RC_CANCEL == rc) + return RC_REFRESH; + return RC_EXIT; + } + else if (IS_PGDN_KEY(ch)) + { + flush_stdscr(); + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + flush_stdscr(); + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_5250_CHAR(ch)) + { + /* Ignore this - we will get this when running under 5250 telnet */ + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + update_panels(); + wrefresh(p_menu_win); + wrefresh(p_title_win); + doupdate(); + } + else + { + mvwaddstr(p_menu_win, 4, 0, "Invalid option specified."); + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + update_panels(); + wrefresh(p_menu_win); + wrefresh(p_title_win); + doupdate(); + } + } + } + + leave: + flush_stdscr(); + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + + return rc; +} + +/* Completely flush any characters in the input buffer */ +void flush_stdscr() +{ + nodelay(stdscr, TRUE); + + while(getch() != ERR) + { + } + nodelay(stdscr, FALSE); +} + +/* Flush the input buffer until we hit either an eol or run + out of characters in the input buffer */ +int flush_line() +{ + int ch; + + nodelay(stdscr, TRUE); + + do + { + ch = getch(); + } while (( ch != ERR) && !IS_5250_CHAR(ch)); + + nodelay(stdscr, FALSE); + + return ch; +} + +int disk_unit_details() +{ +#define DISK_UD_HDR_SIZE 7 +#define DISK_UD_MENU_SIZE 5 + /* iSeries + Display Disk Unit Details + + Type option, press Enter. + 5=Display hardware resource information details + + Serial Sys Sys I/O I/O + OPT Number DSA/UA Bus Card Adapter Bus Ctl Dev + 00234019 00181E00/0FFFFFFF 24 30 0 + 00058B10 00181E00/010700FF 24 30 0 1 7 0 + 00055B7A 00181E00/010600FF 24 30 0 1 6 0 + 0005935E 00181E00/010500FF 24 30 0 1 5 0 + 00055BF8 00181E00/010400FF 24 30 0 1 4 0 + 000585BA 00181E00/010300FF 24 30 0 1 3 0 + 09228053 00181B00/0FFFFFFF 24 27 0 + 000564FD 00181B00/020700FF 24 27 0 2 7 0 + 000585F1 00181B00/020600FF 24 27 0 2 6 0 + 000591FB 00181B00/020500FF 24 27 0 2 5 0 + 00056880 00181B00/020400FF 24 27 0 2 4 0 + 000595AD 00181B00/020300FF 24 27 0 2 3 0 + More... + + + + e=Exit q=Cancel f=PageDn b=PageUp + + */ + /* pSeries + Display Disk Unit Details + + Type option, press Enter. + 5=Display hardware resource information details + + Serial PCI PCI SCSI SCSI SCSI SCSI + OPT Number Location Bus Dev Host Bus ID Lun + 00234019 P1-I1 02 01 0 + 00058B10 P1-I1/Z1-A0 02 01 0 1 0 0 + 00055B7A P1-I1/Z1-A1 02 01 0 1 1 0 + 0005935E P1-I1/Z1-A2 02 01 0 1 2 0 + 00055BF8 P1-I1/Z1-A3 02 01 0 1 3 0 + 000585BA P1-I1/Z1-A4 02 01 0 1 4 0 + 09228053 P1-I2 02 02 1 + 000564FD P1-I2/Z2-A0 02 02 1 2 0 0 + 000585F1 P1-I2/Z2-A1 02 02 1 2 1 0 + 000591FB P1-I2/Z2-A2 02 02 1 2 2 0 + 00056880 P1-I2/Z2-A3 02 02 1 2 3 0 + 000595AD P1-I2/Z2-A4 02 02 1 2 4 0 + More... + + + + e=Exit q=Cancel f=PageDn b=PageUp + + */ + /* Generic + Display Disk Unit Details + + Type option, press Enter. + 5=Display hardware resource information details + + Serial PCI PCI SCSI SCSI SCSI SCSI + OPT Number Bus Dev Host Bus ID Lun + 00234019 02 01 0 + 00058B10 02 01 0 1 0 0 + 00055B7A 02 01 0 1 1 0 + 0005935E 02 01 0 1 2 0 + 00055BF8 02 01 0 1 3 0 + 000585BA 02 01 0 1 4 0 + 09228053 02 02 1 + 000564FD 02 02 1 2 0 0 + 000585F1 02 02 1 2 1 0 + 000591FB 02 02 1 2 2 0 + 00056880 02 02 1 2 3 0 + 000595AD 02 02 1 2 4 0 + More... + + + + e=Exit q=Cancel f=PageDn b=PageUp + + */ + int rc, array_num, j, i, last_char; + struct ibmsis_resource_entry *p_resource; + FIELD *p_fields[3]; + FORM *p_form, *p_old_form, *p_list_form; + int len = 0; + int max_size = curses_info.max_y - (DISK_UD_HDR_SIZE + DISK_UD_MENU_SIZE); + char buffer[100], dev_sn[15], *p_char; + struct sis_ioa *p_cur_ioa; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + int num_devs = 0; + int found = 0; + int dev_num, invalid; + struct device_detail_struct detail_device; + int init_index, init_page, new_page; + u32 dsa, ua; + struct ibmsis_res_addr res_addr; + + rc = RC_SUCCESS; + + p_title_win = newwin(DISK_UD_HDR_SIZE, curses_info.max_x, + curses_info.start_y, curses_info.start_x); + + p_menu_win = newwin(DISK_UD_MENU_SIZE, + curses_info.max_x, + curses_info.start_y + max_size + DISK_UD_HDR_SIZE, + curses_info.start_x); + + p_field_win = newwin(max_size, curses_info.max_x, DISK_UD_HDR_SIZE, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Display Disk Unit Details"); /* string value to set */ + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + clear(); + post_form(p_form); + + check_current_config(false); + + for(p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + if (p_cur_ioa->ioa.p_resource_entry == NULL) + continue; + + start_y = num_devs % (max_size - 1); + if ((num_devs > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + p_resource = p_cur_ioa->ioa.p_resource_entry; + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, "%8s %08X/%08X", + p_cur_ioa->serial_num, + p_resource->dsa, + p_resource->unit_address); + + /* Sys Bus number */ + len += sprintf(buffer + len, + "%7d ", IBMSIS_GET_SYS_BUS(p_resource->dsa)); + + /* Sys Card */ + len += sprintf(buffer + len, + "%6d ", IBMSIS_GET_SYS_CARD(p_resource->dsa)); + + /* I/O Adapter */ + len += sprintf(buffer + len, + "%6d ", IBMSIS_GET_IO_ADAPTER(p_resource->dsa)); + } + else if (platform == SIS_PSERIES) + { + len = sprintf(buffer, "%8s %-22s", + p_cur_ioa->serial_num, + p_resource->pseries_location); + + /* PCI Bus number */ + len += sprintf(buffer + len, + "%02d ", p_resource->pci_bus_number); + + /* PCI Device number */ + len += sprintf(buffer + len, + " %02d ", p_resource->pci_slot); + + /* SCSI Host */ + len += sprintf(buffer + len, + "%6d ", p_resource->host_no); + } + else + { + len = sprintf(buffer, "%8s ", + p_cur_ioa->serial_num); + + /* PCI Bus number */ + len += sprintf(buffer + len, + "%02d ", p_resource->pci_bus_number); + + /* PCI Device number */ + len += sprintf(buffer + len, + " %02d ", p_resource->pci_slot); + + /* SCSI Host */ + len += sprintf(buffer + len, + "%6d ", p_resource->host_no); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 1, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)p_resource); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, + curses_info.max_x - DISK_UD_HDR_SIZE, + start_y, DISK_UD_HDR_SIZE, 0, 0); + + set_field_buffer(pp_field[field_index], 0, buffer); + + field_opts_off(pp_field[field_index], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + + len = 0; + num_devs++; + + array_num = 1; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + if (p_cur_ioa->dev[j].p_resource_entry->is_ioa_resource) + { + continue; + } + + start_y = num_devs % (max_size - 1); + + if ((num_devs > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], O_ACTIVE); + } + + strncpy(dev_sn, (char *)&p_cur_ioa->dev[j].p_resource_entry->std_inq_data.serial_num, 8); + dev_sn[8] = '\0'; + + len = sprintf(buffer, "%8s ", dev_sn); + + res_addr = p_cur_ioa->dev[j].p_resource_entry->resource_address; + + if (platform == SIS_ISERIES) + { + len += sprintf(buffer + len, + "%08X/%08X", + p_cur_ioa->dev[j].p_resource_entry->dsa, + p_cur_ioa->dev[j].p_resource_entry->unit_address); + + dsa = p_cur_ioa->dev[j].p_resource_entry->dsa; + ua = p_cur_ioa->dev[j].p_resource_entry->unit_address; + + /* Sys Bus number */ + len += sprintf(buffer + len, + "%7d ", IBMSIS_GET_SYS_BUS(dsa)); + + /* Sys Card */ + len += sprintf(buffer + len, + "%6d ", IBMSIS_GET_SYS_CARD(dsa)); + + /* I/O Adapter */ + len += sprintf(buffer + len, + "%6d ", IBMSIS_GET_IO_ADAPTER(dsa)); + + /* I/O Bus */ + len += sprintf(buffer + len, + "%5d ", IBMSIS_GET_IO_BUS(ua)); + + /* Ctl */ + len += sprintf(buffer + len, + "%5d ", IBMSIS_GET_CTL(ua)); + + /* Dev */ + len += sprintf(buffer + len, + "%4d ", IBMSIS_GET_DEV(ua)); + } + else + { + if (platform == SIS_PSERIES) + { + len += sprintf(buffer + len, + "%-22s", + p_cur_ioa->dev[j].p_resource_entry->pseries_location); + } + else + { + len += sprintf(buffer + len, " "); + } + + /* PCI Bus number */ + len += sprintf(buffer + len, + "%02d ", p_cur_ioa->dev[j].p_resource_entry->pci_bus_number); + + /* PCI Device number */ + len += sprintf(buffer + len, + " %02d ", p_cur_ioa->dev[j].p_resource_entry->pci_slot); + + /* SCSI Host */ + len += sprintf(buffer + len, + "%6d ", p_cur_ioa->dev[j].p_resource_entry->host_no); + + /* SCSI Bus */ + len += sprintf(buffer + len, + "%5d ", res_addr.bus); + + /* SCSI Target */ + len += sprintf(buffer + len, + "%5d ", res_addr.target); + + /* SCSI Lun */ + len += sprintf(buffer + len, + "%4d ", res_addr.lun); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 1, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)p_cur_ioa->dev[j].p_resource_entry); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, + curses_info.max_x - DISK_UD_HDR_SIZE, + start_y, + DISK_UD_HDR_SIZE, 0, 0); + + set_field_buffer(pp_field[field_index], 0, buffer); + + field_opts_off(pp_field[field_index], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + + len = 0; + num_devs++; + + } + } + + flush_stdscr(); + + if (num_devs == 0) + mvaddstr(1, 2, "(No devices found)"); + else + { + field_opts_off(p_fields[1], O_ACTIVE); + + init_index = ((max_size - 1) * 2) + 1; + for (i = init_index; i < field_index; i += init_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + + while(1) + { + invalid = 0; + mvwaddstr(p_title_win, 2, 0, "Type option, press Enter."); + mvwaddstr(p_title_win, 3, 0, " 5=Display hardware resource information details"); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 5, 0, " Serial Sys Sys I/O I/O"); + mvwaddstr(p_title_win, 6, 0, "OPT Number DSA/UA Bus Card Adapter Bus Ctl Dev"); + } + else if (platform == SIS_PSERIES) + { + mvwaddstr(p_title_win, 5, 0, " Serial PCI PCI SCSI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, "OPT Number Location Bus Dev Host Bus ID Lun"); + } + else + { + mvwaddstr(p_title_win, 5, 0, " Serial PCI PCI SCSI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, "OPT Number Bus Dev Host Bus ID Lun"); + } + + mvwaddstr(p_menu_win, 3, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_ENTER_KEY(ch)) + { + dev_num = 0; + + for (i = 0; (i < field_index) && !invalid; i++) + { + p_resource = (struct ibmsis_resource_entry *)field_userptr(pp_field[i]); + if (p_resource != NULL) + { + p_char = field_buffer(pp_field[i], 0); + + if (strcmp(p_char, "5") == 0) + { + if (dev_num) + { + dev_num++; + break; + } + else + { + found = 0; + + for (p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + if (p_cur_ioa->ioa.p_resource_entry == p_resource) + { + detail_device.p_sis_dev = &p_cur_ioa->ioa; + found = 1; + break; + } + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + if (p_resource == p_cur_ioa->dev[j].p_resource_entry) + { + detail_device.p_sis_dev = &p_cur_ioa->dev[j]; + found = 1; + break; + } + } + if (found) + break; + } + + detail_device.p_ioa = p_cur_ioa; + detail_device.field_index = i; + dev_num++; + } + } + else if (strcmp(p_char, " ") != 0) + { + mvwaddstr(p_menu_win, 4, 1, "The selection is not valid"); + invalid = 1; + } + } + } + + if (invalid) + break; + if (dev_num == 0) + break; + else if (dev_num == 1) + { + unpost_form(p_list_form); + unpost_form(p_form); + + rc = device_details(&detail_device); + + if ((rc == RC_NOOP) || + (rc == RC_CANCEL)) + { + werase(p_title_win); + post_form(p_form); + post_form(p_list_form); + set_field_buffer(pp_field[detail_device.field_index], 0, " "); + set_current_field(p_list_form, pp_field[detail_device.field_index]); + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else + { + goto leave; + } + } + else + { + mvwaddstr(p_menu_win, 4, 0, " Error. More than one unit was selected."); + break; + } + } + else if (ch == KEY_DOWN) + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else if (ch == KEY_UP) + { + form_driver(p_list_form, + REQ_PREV_FIELD); + break; + } + else if (IS_PGDN_KEY(ch)) + { + mvwaddstr(p_menu_win, 4, 0, " "); + init_page = form_page(p_list_form); + form_driver(p_list_form, + REQ_NEXT_PAGE); + + new_page = form_page(p_list_form); + + if (new_page > init_page) + { + form_driver(p_list_form, + REQ_FIRST_FIELD); + } + else + { + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_LAST_FIELD); + mvwaddstr(p_menu_win, 4, 0, " Already at bottom."); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + mvwaddstr(p_menu_win, 4, 0, " "); + init_page = form_page(p_list_form); + form_driver(p_list_form, + REQ_PREV_PAGE); + + new_page = form_page(p_list_form); + + if (new_page < init_page) + { + form_driver(p_list_form, + REQ_FIRST_FIELD); + } + else + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + mvwaddstr(p_menu_win, 4, 0, " Already at top."); + } + break; + } + else if (ch == '\t') + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + break; + } + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + + free_screen(NULL, NULL, p_fields); + free_screen(NULL, NULL, pp_field); + free(pp_field); + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + flush_stdscr(); + return rc; +} + +int device_details(struct device_detail_struct *p_detail_device) +{ + /* iSeries + IOA Hardware Resource Information Details + + + Type. . . . . . . . . . . . : 2778 + Driver Version. . . . . . . : Ver. 1 Rev. 5 (April 18, 2001) + Firmware Version. . . . . . : Ver. 1 Rev. 2 + Serial Number . . . . . . . : 00234019 + Part Number . . . . . . . . : 0000021P3735 + Resource Name . . . . . . . : /dev/scsi/host1/controller + + Physical location: + Frame ID . . . . . . . . . : 3 + Card position. . . . . . . : C15 + Device position. . . . . . : + + + + + + + + Press Enter to continue. + + e=Exit q=Cancel + + */ + /* pSeries + IOA Hardware Resource Information Details + + + Type. . . . . . . . . . . . : 2778 + Driver Version. . . . . . . : Ver. 1 Rev. 5 (April 18, 2001) + Firmware Version. . . . . . : Ver. 1 Rev. 2 + Serial Number . . . . . . . : 00234019 + Part Number . . . . . . . . : 0000021P3735 + Resource Name . . . . . . . : /dev/scsi/host1/controller + + Physical location: + Location . . . . . . . . . : P1-I1 + PCI Bus. . . . . . . . . . : 1 + PCI Device . . . . . . . . : 4 + SCSI Host. . . . . . . . . : 0 + + + + + + + Press Enter to continue. + + e=Exit q=Cancel + + */ + /* Generic + IOA Hardware Resource Information Details + + + Type. . . . . . . . . . . . : 2778 + Driver Version. . . . . . . : Ver. 1 Rev. 5 (April 18, 2001) + Firmware Version. . . . . . : Ver. 1 Rev. 2 + Serial Number . . . . . . . : 00234019 + Part Number . . . . . . . . : 0000021P3735 + Resource Name . . . . . . . : /dev/scsi/host1/controller + + Physical location: + PCI Bus. . . . . . . . . . : 1 + PCI Device . . . . . . . . : 4 + SCSI Host. . . . . . . . . : 0 + + + + + + + Press Enter to continue. + + e=Exit q=Cancel + + */ + + /* iSeries + Disk Unit Hardware Resource Information Details + + + Type. . . . . . . . . . . . : 6717 + Firmware Version. . . . . . : 66209 + Model . . . . . . . . . . . : 074 + Level . . . . . . . . . . . : 3 + Serial Number . . . . . . . : 00058B10 + Resource Name . . . . . . . : /dev/scsi/host1/bus1/target0/lun0/disc + + Physical location: + Frame ID . . . . . . . . . : 3 + Card position. . . . . . . : D10 + Device position. . . . . . : + + + + + + + + Press Enter to continue. + + e=Exit q=Cancel + + */ + /* pSeries + Disk Unit Hardware Resource Information Details + + + Vendor ID . . . . . . . . . : IBM + Product ID. . . . . . . . . : ST336607LC + Firmware Version. . . . . . : 66209 + Model . . . . . . . . . . . : 074 + Level . . . . . . . . . . . : 0 + Serial Number . . . . . . . : 00058B10 + Resource Name . . . . . . . : /dev/scsi/host1/bus1/target0/lun0/disc + + Physical location: + Location . . . . . . . . . : P1-I1/Z1-A4 + PCI Bus. . . . . . . . . . : 1 + PCI Device . . . . . . . . : 4 + SCSI Host. . . . . . . . . : 0 + SCSI Bus . . . . . . . . . : 1 + SCSI Target. . . . . . . . : 4 + SCSI Lun . . . . . . . . . : 0 + + + Press Enter to continue. + + e=Exit q=Cancel + + */ + /* Generic + Disk Unit Hardware Resource Information Details + + + Vendor ID . . . . . . . . . : IBM + Product ID. . . . . . . . . : ST336607LC + Firmware Version. . . . . . : 66209 + Model . . . . . . . . . . . : 074 + Level . . . . . . . . . . . : 0 + Serial Number . . . . . . . : 00058B10 + Resource Name . . . . . . . : /dev/scsi/host1/bus1/target0/lun0/disc + + Physical location: + PCI Bus. . . . . . . . . . : 1 + PCI Device . . . . . . . . : 4 + SCSI Host. . . . . . . . . : 0 + SCSI Bus . . . . . . . . . : 1 + SCSI Target. . . . . . . . : 4 + SCSI Lun . . . . . . . . . : 0 + + + + Press Enter to continue. + + e=Exit q=Cancel + + */ + + FIELD *p_fields[3]; + FORM *p_form; + FORM *p_old_form; + int rc; + char dev_name[50]; + struct ibmsis_resource_entry *p_resource = + p_detail_device->p_sis_dev->p_resource_entry; + struct ibmsis_array2_record *ibmsis_array2_record = + (struct ibmsis_array2_record *)p_detail_device->p_sis_dev->p_qac_entry; + struct sis_ioa *p_ioa = p_detail_device->p_ioa; + struct ibmsis_supported_arrays *p_supported_arrays; + struct ibmsis_array_cap_entry *p_cur_array_cap_entry; + int fd, i, field_index; + unsigned int ucode_rev = 0; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_dasd_inquiry_page3 dasd_page3_inq; + u8 product_id[IBMSIS_PROD_ID_LEN+1]; + u8 vendor_id[IBMSIS_VENDOR_ID_LEN+1]; + u8 cdb[IBMSIS_CCB_CDB_LEN]; + struct ibmsis_read_cap read_cap; + struct ibmsis_read_cap16 read_cap16; + struct sense_data_t sense_data; + long double device_capacity; + unsigned long long max_user_lba_int; + char *p_dev_name; + double lba_divisor; + char pci_bus_number[10], pci_device[10], scsi_channel[3], scsi_id[3], scsi_lun[4]; + char dsa_str[20], ua_str[20]; + bool removeable = false; + char buf[100]; + + dsa_str[0] = ua_str[0] = '\0'; + + if (p_resource->dsa) + sprintf(dsa_str, "%X", p_resource->dsa); + if (p_resource->unit_address) + sprintf(ua_str, "%X", p_resource->unit_address); + sprintf(pci_bus_number, "%d", p_resource->pci_bus_number); + sprintf(pci_device, "%d", p_resource->pci_slot); + sprintf(scsi_channel, "%d", p_resource->resource_address.bus); + sprintf(scsi_id, "%d", p_resource->resource_address.target); + sprintf(scsi_lun, "%d", p_resource->resource_address.lun); + + read_cap.max_user_lba = 0; + read_cap.block_length = 0; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + +refresh: + if (p_resource->is_ioa_resource) + { + set_field_buffer(p_fields[0], 0, "IOA Hardware Resource Information Details"); + + post_form(p_form); + + field_index = 3; + + if (platform == SIS_ISERIES) + { + mvprintw(field_index++, 1, "Type. . . . . . . . . . . . : %X", p_ioa->ccin); + } + else + { + memcpy(vendor_id, p_resource->std_inq_data.vpids.vendor_id, IBMSIS_VENDOR_ID_LEN); + vendor_id[IBMSIS_VENDOR_ID_LEN] = '\0'; + memcpy(product_id, p_resource->std_inq_data.vpids.product_id, IBMSIS_PROD_ID_LEN); + product_id[IBMSIS_PROD_ID_LEN] = '\0'; + + mvprintw(field_index++, 1, "Manufacturer. . . . . . . . : %s", vendor_id); + mvprintw(field_index++, 1, "Type. . . . . . . . . . . . : %X", p_ioa->ccin); + } + + mvprintw(field_index++, 1, "Driver Version. . . . . . . : %s", p_ioa->driver_version); + mvprintw(field_index++, 1, "Firmware Version. . . . . . : %s", p_ioa->firmware_version); + mvprintw(field_index++, 1, "Serial Number . . . . . . . : %-8s", p_resource->serial_num); + mvprintw(field_index++, 1, "Part Number . . . . . . . . : %s", p_ioa->part_num); + mvprintw(field_index++, 1, "Resource Name . . . . . . . : %s", p_ioa->ioa.dev_name); + field_index++; + mvprintw(field_index++, 1, "Physical location:"); + + if (platform == SIS_ISERIES) + { + mvprintw(field_index++, 2, "Frame ID . . . . . . . . . : %s", p_resource->frame_id); + mvprintw(field_index++, 2, "Card position. . . . . . . : %s", p_resource->slot_label); + mvprintw(field_index++, 2, "Device position. . . . . . : "); + } + else + { + if (platform == SIS_PSERIES) + mvprintw(field_index++, 2, + "Location . . . . . . . . . : %s", p_resource->pseries_location); + + mvprintw(field_index++, 2, "PCI Bus. . . . . . . . . . : %d", p_resource->pci_bus_number); + mvprintw(field_index++, 2, "PCI Device . . . . . . . . : %d", p_resource->pci_slot); + mvprintw(field_index++, 2, "SCSI Host Number . . . . . : %d", p_resource->host_no); + } + + mvprintw(curses_info.max_y - 4, 1, "Press Enter to continue."); + mvprintw(curses_info.max_y - 2, 1, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + } + else if ((ibmsis_array2_record) && + (ibmsis_array2_record->common.record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD)) + { + set_field_buffer(p_fields[0], 0, "Disk Array Information Details"); + + post_form(p_form); + + field_index = 3; + + memcpy(vendor_id, p_resource->std_inq_data.vpids.vendor_id, IBMSIS_VENDOR_ID_LEN); + vendor_id[IBMSIS_VENDOR_ID_LEN] = '\0'; + mvprintw(field_index++, 1, "Manufacturer. . . . . . . . : %s", vendor_id); + memcpy(product_id, p_resource->std_inq_data.vpids.product_id, IBMSIS_PROD_ID_LEN); + product_id[IBMSIS_PROD_ID_LEN] = '\0'; + mvprintw(field_index++, 1, "Machine Type and Model. . . : %s", product_id); + mvprintw(field_index++, 1, "Serial Number . . . . . . . : %-8s", + p_resource->serial_num); + + p_supported_arrays = p_ioa->p_supported_arrays; + p_cur_array_cap_entry = (struct ibmsis_array_cap_entry *)p_supported_arrays->data; + for (i=0; inum_entries); i++) + { + if (p_cur_array_cap_entry->prot_level == ibmsis_array2_record->raid_level) + { + mvprintw(field_index++, 1, "RAID Level . . . . . . . . : RAID %s", p_cur_array_cap_entry->prot_level_str); + break; + } + + p_cur_array_cap_entry = (struct ibmsis_array_cap_entry *) + ((void *)p_cur_array_cap_entry + sistoh16(p_supported_arrays->entry_length)); + } + + if (sistoh16(ibmsis_array2_record->stripe_size) > 1024) + { + mvprintw(field_index++, 1, "Stripe Size . . . . . . . . : %d M", + sistoh16(ibmsis_array2_record->stripe_size)/1024); + } + else + { + mvprintw(field_index++, 1, "Stripe Size . . . . . . . . : %d k", + sistoh16(ibmsis_array2_record->stripe_size)); + } + + fd = open(p_ioa->ioa.dev_name, O_RDWR); + + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_ioa->ioa.dev_name); + } + else + { + /* Do a read capacity to determine the capacity */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &read_cap16; + ioa_cmd.buffer_len = sizeof(read_cap16); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.cdb[1] = IBMSIS_READ_CAPACITY_16; + ioa_cmd.resource_address = p_resource->resource_address; + + memset(&read_cap16, 0, sizeof(read_cap16)); + + rc = sis_ioctl(fd, IBMSIS_SERVICE_ACTION_IN, &ioa_cmd); + } + + if (rc != 0) + syslog(LOG_ERR, "Read capacity to %s failed. %m"IBMSIS_EOL, dev_name); + else if ((sistoh32(read_cap16.max_user_lba_hi) || + sistoh32(read_cap16.max_user_lba_lo)) && + sistoh32(read_cap16.block_length)) + { + max_user_lba_int = sistoh32(read_cap16.max_user_lba_hi); + max_user_lba_int <<= 32; + max_user_lba_int |= sistoh32(read_cap16.max_user_lba_lo); + + device_capacity = max_user_lba_int + 1; + + lba_divisor = (1000*1000*1000)/sistoh32(read_cap16.block_length); + + mvprintw(field_index++, 1, "Capacity. . . . . . . . . . : %.2Lf GB", + device_capacity/lba_divisor); + } + + mvprintw(field_index++, 1, "Resource Name . . . . . . . : %s", + p_detail_device->p_sis_dev->dev_name); + + mvprintw(curses_info.max_y - 4, 1, "Press Enter to continue."); + mvprintw(curses_info.max_y - 2, 1, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + } + else + { + set_field_buffer(p_fields[0], 0, "Disk Unit Hardware Resource Information Details"); + + post_form(p_form); + + if (p_resource->subtype == IBMSIS_SUBTYPE_GENERIC_SCSI) + p_dev_name = p_detail_device->p_sis_dev->gen_name; + else + p_dev_name = p_ioa->ioa.dev_name; + + fd = open(p_dev_name, O_RDWR); + + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_dev_name); + } + else + { + if ((platform == SIS_ISERIES) || (platform == SIS_PSERIES)) + { + if (p_detail_device->p_sis_dev->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(fd, cdb, &dasd_page3_inq, + sizeof(dasd_page3_inq), + SG_DXFER_FROM_DEV, &sense_data, 30); + } + else + { + /* Do a page 3 inquiry to determine the firmware level */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + 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_resource->resource_address; + + memset(&dasd_page3_inq, 0, sizeof(dasd_page3_inq)); + + rc = sis_ioctl(fd, INQUIRY, &ioa_cmd); + } + + if (rc != 0) + syslog(LOG_ERR, "Inquiry to %s failed. %m"IBMSIS_EOL, p_dev_name); + else + ucode_rev = (dasd_page3_inq.release_level[0] << 24) | + (dasd_page3_inq.release_level[1] << 16) | + (dasd_page3_inq.release_level[2] << 8) | + dasd_page3_inq.release_level[3]; + } + else + { + char buf[5]; + memcpy(buf, p_detail_device->p_sis_dev->p_resource_entry->std_inq_data.ros_rsvd_ram_rsvd, 4); + buf[4] = '\0'; + + ucode_rev = strtoul(buf, NULL, 16); + } + + if (p_detail_device->p_sis_dev->p_resource_entry->subtype == IBMSIS_SUBTYPE_GENERIC_SCSI) + { + memset(&read_cap, 0, sizeof(read_cap)); + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + cdb[0] = READ_CAPACITY; + + rc = sg_ioctl(fd, cdb, &read_cap, + sizeof(read_cap), SG_DXFER_FROM_DEV, + &sense_data, 30); + } + else + { + /* Do a read capacity to determine the capacity */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + memset(&read_cap, 0, sizeof(read_cap)); + + ioa_cmd.buffer = &read_cap; + ioa_cmd.buffer_len = sizeof(read_cap); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_resource->resource_address; + + rc = sis_ioctl(fd, READ_CAPACITY, &ioa_cmd); + } + + if (rc != 0) + syslog(LOG_ERR, "Read capacity to %s failed. %m"IBMSIS_EOL, dev_name); + + close(fd); + + if (!is_valid_device(p_resource->frame_id, p_resource->slot_label, dsa_str, ua_str, + p_resource->pseries_location, + pci_bus_number, pci_device, scsi_channel, scsi_id, scsi_lun)) + { + removeable = true; + } + } + + field_index = 3; + + if ((platform == SIS_ISERIES) || (p_resource->type != 0x6600)) + { + mvprintw(field_index++, 1, "Type. . . . . . . . . . . . : %X", + p_resource->type); + } + + if (platform != SIS_ISERIES) + { + memcpy(vendor_id, p_resource->std_inq_data.vpids.vendor_id, IBMSIS_VENDOR_ID_LEN); + vendor_id[IBMSIS_VENDOR_ID_LEN] = '\0'; + memcpy(product_id, p_resource->std_inq_data.vpids.product_id, IBMSIS_PROD_ID_LEN); + product_id[IBMSIS_PROD_ID_LEN] = '\0'; + + mvprintw(field_index++, 1, "Manufacturer. . . . . . . . : %s", vendor_id); + mvprintw(field_index++, 1, "Machine Type and Model. . . : %s", product_id); + } + + mvprintw(field_index++, 1, "Firmware Version. . . . . . : %X", + ucode_rev); + + mvprintw(field_index++, 1, "Model . . . . . . . . . . . : %03d", + p_resource->model); + + if (p_resource->type != 0x6600) + { + mvprintw(field_index++, 1, "Level . . . . . . . . . . . : %X", + p_resource->level); + } + + mvprintw(field_index++, 1, "Serial Number . . . . . . . : %-8s", + p_resource->serial_num); + + if (sistoh32(read_cap.block_length) && sistoh32(read_cap.max_user_lba)) + { + lba_divisor = (1000*1000*1000)/sistoh32(read_cap.block_length); + + device_capacity = sistoh32(read_cap.max_user_lba) + 1; + + mvprintw(field_index++, 1, "Capacity. . . . . . . . . . : %.2Lf GB", + device_capacity/lba_divisor); + } + + if (strlen(p_detail_device->p_sis_dev->dev_name) > 0) + { + mvprintw(field_index++, 1, "Resource Name . . . . . . . : %s", + p_detail_device->p_sis_dev->dev_name); + } + + field_index++; + + mvprintw(field_index++, 1, "Physical location:"); + + if (platform == SIS_ISERIES) + { + mvprintw(field_index++, 2, "Frame ID . . . . . . . . . : %s", + p_resource->frame_id); + mvprintw(field_index++, 2, "Card position. . . . . . . : %s", + p_resource->slot_label); + mvprintw(field_index++, 2, "Device position. . . . . . : "); + } + else + { + if (platform == SIS_PSERIES) + { + mvprintw(field_index++, 2, "Location . . . . . . . : %s", + p_resource->pseries_location); + } + + mvprintw(field_index++, 2, "PCI Bus. . . . . . . . . . : %d", + p_resource->pci_bus_number); + mvprintw(field_index++, 2, "PCI Device . . . . . . . . : %d", + p_resource->pci_slot); + mvprintw(field_index++, 2, "SCSI Host Number . . . . . : %d", + p_resource->host_no); + mvprintw(field_index++, 2, "SCSI Channel. . . . . . . : %d", + p_resource->resource_address.bus); + mvprintw(field_index++, 2, "SCSI Id. . . . . . . . . . : %d", + p_resource->resource_address.target); + mvprintw(field_index++, 2, "SCSI Lun. . . . . . . . . : %d", + p_resource->resource_address.lun); + } + + mvprintw(curses_info.max_y - 4, 1, "Press Enter to continue."); + + strcpy(buf, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + if (removeable) + strcat(buf, " r=Remove"); + + if (platform == SIS_PSERIES) + strcat(buf, " v=Display Extended VPD"); + + mvprintw(curses_info.max_y - 2, 1, buf); + } + + while(1) + { + form_driver(p_form, + REQ_LAST_FIELD); + refresh(); + + while(1) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (((ch == 'r') || (ch == 'R')) && removeable) + { + + rc = device_concurrent_maintenance(p_resource->frame_id, p_resource->slot_label, + dsa_str, ua_str, + p_resource->pseries_location, + pci_bus_number, pci_device, scsi_channel, + scsi_id, scsi_lun, "1"); + + goto leave; + } + else if ((platform == SIS_PSERIES) && ((ch == 'v') || (ch == 'V'))) + { + rc = device_extended_vpd(p_detail_device); + if (rc == RC_EXIT) + goto leave; + else + goto refresh; + } + } + } + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(NULL, NULL, p_fields); + + flush_stdscr(); + return rc; +} + +int device_extended_vpd(struct device_detail_struct *p_detail_device) +{ + + FIELD *p_fields[3]; + FORM *p_form; + FORM *p_old_form; + int rc; + struct ibmsis_resource_entry *p_resource = + p_detail_device->p_sis_dev->p_resource_entry; + int fd, field_index; + struct ibmsis_std_inq_data_long std_inq_data; + struct sense_data_t sense_data; + u8 product_id[IBMSIS_PROD_ID_LEN+1]; + u8 vendor_id[IBMSIS_VENDOR_ID_LEN+1]; + u8 cdb[IBMSIS_CCB_CDB_LEN]; + u8 *p_char; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], 0, "Disk Unit Hardware Resource Extended Details"); + + post_form(p_form); + + if (p_detail_device->p_sis_dev->p_resource_entry->subtype == IBMSIS_SUBTYPE_GENERIC_SCSI) + { + fd = open(p_detail_device->p_sis_dev->gen_name, O_RDWR); + + if (fd != -1) + { + memset(&std_inq_data, 0, sizeof(std_inq_data)); + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + /* Issue mode sense to get the block size */ + cdb[0] = INQUIRY; + cdb[4] = sizeof(std_inq_data); + + rc = sg_ioctl(fd, cdb, + &std_inq_data, sizeof(std_inq_data), + SG_DXFER_FROM_DEV, + &sense_data, 30); + + close(fd); + + if (rc == 0) + { + /* Fill in additional VPD information */ + ibmsis_memory_copy(p_resource->part_number, std_inq_data.part_number, + IBMSIS_STD_INQ_PART_NUM_LEN); + p_resource->part_number[IBMSIS_STD_INQ_PART_NUM_LEN] = '\0'; + + ibmsis_memory_copy(p_resource->ec_level, std_inq_data.ec_level, + IBMSIS_STD_INQ_EC_LEVEL_LEN); + p_resource->ec_level[IBMSIS_STD_INQ_EC_LEVEL_LEN] = '\0'; + + ibmsis_memory_copy(p_resource->fru_number, std_inq_data.fru_number, + IBMSIS_STD_INQ_FRU_NUM_LEN); + p_resource->fru_number[IBMSIS_STD_INQ_FRU_NUM_LEN] = '\0'; + + ibmsis_memory_copy(p_resource->z1_term, std_inq_data.z1_term, + IBMSIS_STD_INQ_Z1_TERM_LEN); + p_resource->z1_term[IBMSIS_STD_INQ_Z1_TERM_LEN] = '\0'; + + ibmsis_memory_copy(p_resource->z2_term, std_inq_data.z2_term, + IBMSIS_STD_INQ_Z2_TERM_LEN); + p_resource->z2_term[IBMSIS_STD_INQ_Z2_TERM_LEN] = '\0'; + + ibmsis_memory_copy(p_resource->z3_term, std_inq_data.z3_term, + IBMSIS_STD_INQ_Z3_TERM_LEN); + p_resource->z3_term[IBMSIS_STD_INQ_Z3_TERM_LEN] = '\0'; + + ibmsis_memory_copy(p_resource->z4_term, std_inq_data.z4_term, + IBMSIS_STD_INQ_Z4_TERM_LEN); + p_resource->z4_term[IBMSIS_STD_INQ_Z4_TERM_LEN] = '\0'; + + ibmsis_memory_copy(p_resource->z5_term, std_inq_data.z5_term, + IBMSIS_STD_INQ_Z5_TERM_LEN); + p_resource->z5_term[IBMSIS_STD_INQ_Z5_TERM_LEN] = '\0'; + + ibmsis_memory_copy(p_resource->z6_term, std_inq_data.z6_term, + IBMSIS_STD_INQ_Z6_TERM_LEN); + p_resource->z6_term[IBMSIS_STD_INQ_Z6_TERM_LEN] = '\0'; + } + else + { + syslog(LOG_ERR, "Inquiry to %s failed. %m"IBMSIS_EOL, p_detail_device->p_sis_dev->gen_name); + } + } + else + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_detail_device->p_sis_dev->gen_name); + } + } + + field_index = 3; + + memcpy(vendor_id, p_resource->std_inq_data.vpids.vendor_id, IBMSIS_VENDOR_ID_LEN); + vendor_id[IBMSIS_VENDOR_ID_LEN] = '\0'; + memcpy(product_id, p_resource->std_inq_data.vpids.product_id, IBMSIS_PROD_ID_LEN); + product_id[IBMSIS_PROD_ID_LEN] = '\0'; + + if (strlen(p_detail_device->p_sis_dev->dev_name) > 0) + { + mvprintw(field_index++, 1, "Resource Name . . . . . . . : %s", + p_detail_device->p_sis_dev->dev_name); + } + mvprintw(field_index++, 1, "Manufacturer. . . . . . . . : %s", vendor_id); + mvprintw(field_index++, 1, "Machine Type and Model. . . : %s", product_id); + mvprintw(field_index++, 1, "FRU Number. . . . . . . . . : %s", + p_resource->fru_number); + mvprintw(field_index++, 1, "Serial Number . . . . . . . : %-8s", + p_resource->serial_num); + mvprintw(field_index++, 1, "EC Level . . . . . . . . . : %s", + p_resource->ec_level); + + mvprintw(field_index++, 1, "Part Number. . . . . . . . : %s", + p_resource->part_number); + + p_char = (u8 *)&p_resource->std_inq_data; + + mvprintw(field_index++, 1, "Device Specific (Z0). . . . : %02X%02X%02X%02X%02X%02X%02X%02X", + p_char[0], p_char[1], p_char[2], + p_char[3], p_char[4], p_char[5], + p_char[6], p_char[7]); + + mvprintw(field_index++, 1, "Device Specific (Z1). . . . : %s", + p_resource->z1_term); + + mvprintw(field_index++, 1, "Device Specific (Z2). . . . : %s", + p_resource->z2_term); + + mvprintw(field_index++, 1, "Device Specific (Z3). . . . : %s", + p_resource->z3_term); + + mvprintw(field_index++, 1, "Device Specific (Z4). . . . : %s", + p_resource->z4_term); + + mvprintw(field_index++, 1, "Device Specific (Z5). . . . : %s", + p_resource->z5_term); + + mvprintw(field_index++, 1, "Device Specific (Z6). . . . : %s", + p_resource->z6_term); + + mvprintw(curses_info.max_y - 4, 1, "Press Enter to continue."); + + mvprintw(curses_info.max_y - 2, 1, + EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + while(1) + { + form_driver(p_form, + REQ_LAST_FIELD); + refresh(); + + while(1) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + } + } + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(NULL, NULL, p_fields); + + flush_stdscr(); + return rc; +} + +void raid_screen() +{ + /* + Work with Device Parity Protection + + Select one of the following: + + 1. Display device parity status + 2. Start device parity protection + 3. Stop device parity protection + 4. Include unit in device parity protection + 5. Work with disk unit configuration + + + + Selection: + + e=Exit q=Cancel + */ + FIELD *p_fields[12]; + FORM *p_form, *p_old_form; + int invalid = 0; + int rc = RC_SUCCESS; + int j; + + int raid_status(); + int raid_stop(); + int raid_start(); + int raid_include(); + int configure_device(); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 2, + 12, 12, + 0, + 0); + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Work with Device Parity Protection"); /* string value to set */ + + flush_stdscr(); + + clear(); + + post_form(p_form); + + while(1) + { + mvaddstr(2, 0, "Select one of the following:"); + mvaddstr(4, 0, " 1. Display device parity status"); + mvaddstr(5, 0, " 2. Start device parity protection"); + mvaddstr(6, 0, " 3. Stop device parity protection"); + mvaddstr(7, 0, " 4. Include unit in device parity protection"); + mvaddstr(8, 0, " 5. Work with disk unit configuration"); + mvaddstr(12, 0, "Selection: "); + mvaddstr(curses_info.max_y - 2, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + if (invalid) + { + invalid = 0; + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + } + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + refresh(); + for (;;) + { + int ch = getch(); + + if (IS_ENTER_KEY(ch)) + { + char *p_char; + refresh(); + unpost_form(p_form); + p_char = field_buffer(p_fields[1], 0); + + switch(p_char[0]) + { + case '1': /* Display device parity status */ + while (RC_REFRESH == (rc = raid_status())) + clear(); + clear(); + if (rc == RC_EXIT) + goto leave; + post_form(p_form); + break; + case '2': /* Start device parity protection */ + while (RC_REFRESH == (rc = raid_start())) + clear(); + if (RC_EXIT == rc) + goto leave; + clear(); + post_form(p_form); + if (rc == RC_SUCCESS) + { + mvaddstr(curses_info.max_y - 1, 0, + "Start Parity Protection completed successfully"); + } + else if (rc == RC_FAILED) + { + mvprintw(curses_info.max_y - 1, 0, "Start Parity Protection failed."); + } + else if (rc == RC_EXIT) + goto leave; + break; + case '3': /* Stop device parity protection */ + while (RC_REFRESH == (rc = raid_stop())) + clear(); + clear(); + post_form(p_form); + if (rc == RC_SUCCESS) + { + mvaddstr(curses_info.max_y - 1, 0, + "Stop Parity Protection completed successfully"); + } + else if (rc == RC_FAILED) + { + mvprintw(curses_info.max_y - 1, 0, "Stop Parity Protection failed."); + } + else if (rc == RC_EXIT) + goto leave; + break; + case '4': /* Include unit in device parity protection */ + while (RC_REFRESH == (rc = raid_include())); + if (rc == RC_EXIT) + goto leave; + clear(); + post_form(p_form); + if (rc == RC_SUCCESS) + { + mvaddstr(curses_info.max_y - 1, 0, "Include Unit completed successfully"); + } + else if (rc == RC_FAILED) + mvaddstr(curses_info.max_y - 1, 0, "Include failed"); + break; + case '5': /* Work with disk unit configuration */ + while (RC_REFRESH == (rc = configure_device())); + if (rc == RC_EXIT) + goto leave; + clear(); + post_form(p_form); + break; + case ' ': + clear(); + post_form(p_form); + break; + default: + clear(); + post_form(p_form); + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + break; + } + form_driver(p_form, ' '); + break; + } + else if (IS_EXIT_KEY(ch)) + goto leave; + else if (IS_CANCEL_KEY(ch)) + goto leave; + else + { + form_driver(p_form, ch); + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + for (j=0; j < 2; j++) + free_field(p_fields[j]); + flush_stdscr(); + return; +} + +int configure_device() +{ + /* + Work with Disk Unit Configuration + + Select one of the following: + + 1. Format device for advanced function + 2. Format device for JBOD function + 3. Configure a hot spare device + 4. Unconfigure a hot spare device + + + + + Selection: + + e=Exit q=Cancel + */ + FIELD *p_fields[12]; + FORM *p_form, *p_old_form; + int invalid = 0; + int rc = RC_SUCCESS; + int j; + char title_str[50]; + int configure_af_device(int action_code); + int hot_spare(int action); +#define SIS_INCLUDE 0 +#define SIS_REMOVE 1 +#define SIS_ADD_HOT_SPARE 0 +#define SIS_RMV_HOT_SPARE 1 + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 2, /* new field size */ + 12, 12, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Work with Disk Unit Configuration"); /* string value to set */ + + flush_stdscr(); + + clear(); + + post_form(p_form); + + while(1) + { + mvaddstr(2, 0, "Select one of the following:"); + mvaddstr(4, 0, " 1. Format device for advanced function"); + mvaddstr(5, 0, " 2. Format device for JBOD function"); + mvaddstr(6, 0, " 3. Configure a hot spare device"); + mvaddstr(7, 0, " 4. Unconfigure a hot spare device"); + mvaddstr(12, 0, "Selection: "); + mvaddstr(curses_info.max_y - 2, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + if (invalid) + { + invalid = 0; + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + } + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + refresh(); + for (;;) + { + int ch = getch(); + + if (IS_ENTER_KEY(ch)) + { + char *p_char; + refresh(); + unpost_form(p_form); + p_char = field_buffer(p_fields[1], 0); + + switch(p_char[0]) + { + case '1': /* Display candidates for AF inclusion */ + rc = configure_af_device(SIS_INCLUDE); + if (RC_EXIT == rc) + goto leave; + clear(); + post_form(p_form); + if (rc == RC_SUCCESS) + { + mvaddstr(curses_info.max_y - 1, 0, "Completed successfully"); + } + else if (rc == RC_FAILED) + { + mvprintw(curses_info.max_y - 1, 0, "Failed."); + } + else if (rc == RC_NOOP) + { + sprintf(title_str,"Format device for advanced function failed"); + } + break; + case '2': /* Display candidates for AF removal */ + rc = configure_af_device(SIS_REMOVE); + if (RC_EXIT == rc) + goto leave; + clear(); + post_form(p_form); + if (rc == RC_SUCCESS) + { + mvaddstr(curses_info.max_y - 1, 0, "Completed successfully"); + } + else if (rc == RC_FAILED) + { + mvprintw(curses_info.max_y - 1, 0, "Failed."); + } + else if (rc == RC_NOOP) + { + sprintf(title_str,"Disable Device Advanced Functions Failed"); + } + break; + case '3': /* Display candidates for AF removal */ + rc = hot_spare(SIS_ADD_HOT_SPARE); + if (RC_EXIT == rc) + goto leave; + clear(); + post_form(p_form); + if (rc == RC_SUCCESS) + { + mvaddstr(curses_info.max_y - 1, 0, "Completed successfully"); + } + else if (rc == RC_FAILED) + { + mvprintw(curses_info.max_y - 1, 0, "Failed."); + } + else if (rc == RC_NOOP) + { + sprintf(title_str,"Enable Device as Hot Spare Failed"); + } + break; + case '4': /* Display candidates for AF removal */ + rc = hot_spare(SIS_RMV_HOT_SPARE); + if (RC_EXIT == rc) + goto leave; + clear(); + post_form(p_form); + if (rc == RC_SUCCESS) + { + mvaddstr(curses_info.max_y - 1, 0, "Completed successfully"); + } + else if (rc == RC_FAILED) + { + mvprintw(curses_info.max_y - 1, 0, "Failed."); + } + else if (rc == RC_NOOP) + { + sprintf(title_str,"Disable Device as Hot Spare Failed"); + } + break; + case ' ': + clear(); + post_form(p_form); + break; + default: + clear(); + post_form(p_form); + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + break; + } + + if (rc == RC_NOOP) + { + clear(); + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + title_str); /* string value to set */ + + mvaddstr( 2, 0, "There are no disk units eligible for the selected operation"); + mvaddstr( 3, 0, "due to one or more of the following reasons:"); + mvaddstr( 5, 0, "o There are no eligible device units in the system."); + mvaddstr( 6, 0, "o An IOA is in a condition that makes the disk units attached to"); + mvaddstr( 7, 0, " it read/write protected. Examine the kernel messages log"); + mvaddstr( 8, 0, " for any errors that are logged for the IO subsystem"); + mvaddstr( 9, 0, " and follow the appropriate procedure for the reference code to"); + mvaddstr(10, 0, " correct the problem, if necessary."); + mvaddstr(11, 0, "o Not all disk units attached to an advanced function IOA have"); + mvaddstr(12, 0, " reported to the system. Retry the operation."); + mvaddstr(13, 0, "o The disk units are missing."); + mvaddstr(14, 0, "o The disk unit/s are currently in use."); + mvaddstr( curses_info.max_y - 2, 0, "Press Enter to continue."); + mvaddstr( curses_info.max_y - 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD); /* form request code */ + + wnoutrefresh(stdscr); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + break; + } + } + clear(); + } + + form_driver(p_form, ' '); + break; + } + else if (IS_EXIT_KEY(ch)) + goto leave; + else if (IS_CANCEL_KEY(ch)) + goto leave; + else + { + form_driver(p_form, ch); + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + for (j=0; j < 2; j++) + free_field(p_fields[j]); + flush_stdscr(); + return 0; +} + +int raid_status() +{ +#define RAID_STATUS_HDR_SIZE 4 +#define RAID_STATUS_MENU_SIZE 5 +/* iSeries + Display Device Parity Status + +Parity Serial Resource + Set Number Type Model Name Status + 1 02127005 2782 001 /dev/ibmsis4 + 002443C6 6713 072 /dev/sdr Active + 0024B45C 6713 072 /dev/sds Active + 00000DC7 6717 072 /dev/sdt Active + 000BBBC1 6717 072 /dev/sdu Active + 0002F5AA 6717 070 /dev/sdv Active + 2 00103039 2748 001 /dev/ibmsis0 + 0004C93D 6607 072 /dev/sda Active + 0006E12B 6607 072 /dev/sdb Active + 000716B1 6607 070 /dev/sdc Active + 0006CBF1 6607 072 /dev/sdd Active + 0005722D 6607 072 /dev/sde Active + 0006E103 6607 070 /dev/sdf Active + +e=Exit q=Cancel r=Refresh f=PageDn b=PageUp +*/ + +/* Generic + Display Device Parity Status + +Parity Serial Resource PCI PCI SCSI SCSI SCSI Status + Set Number Model Name Bus Dev Bus ID Lun + 1 02127005 200 /dev/sda 05 03 255 0 0 Active + 002443C6 072 05 03 0 1 0 Active + 0024B45C 072 05 03 0 5 0 Active + 00000DC7 072 05 03 0 9 0 Active + 000BBBC1 072 05 03 0 6 0 Active + 0002F5AA 070 05 03 0 4 0 Active + 2 00103039 200 /dev/sdb 05 03 255 0 1 Active + 0004C93D 072 05 03 1 5 0 Active + 0006E12B 072 05 03 1 6 0 Active + 000716B1 070 05 03 1 9 0 Active + 0006CBF1 072 05 03 1 2 0 Active + 0005722D 072 05 03 1 3 0 Active + 0006E103 070 05 03 1 4 0 Active + +e=Exit q=Cancel r=Refresh f=PageDn b=PageUp +*/ + + int fd, rc, array_num, i, j; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_cmd_status cmd_status; + struct ibmsis_array_query_data *array_query_data; + struct ibmsis_record_common *p_common_record; + struct ibmsis_array_record *p_array_record; + struct ibmsis_array2_record *p_array2_record; + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + int len = 0; + u8 array_id; + int max_size = curses_info.max_y - (RAID_STATUS_HDR_SIZE + RAID_STATUS_MENU_SIZE + 1); + char buffer[100]; + struct ibmsis_query_res_state res_state; + int num_lines = 0; + struct sis_ioa *p_cur_ioa; + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel, *p_cur_panel; + WINDOW *p_title_win, *p_menu_win; + PANEL *p_panel; + struct ibmsis_resource_entry *p_resource_entry; + int is_first; + + rc = RC_SUCCESS; + + p_title_win = newwin(RAID_STATUS_HDR_SIZE, curses_info.max_x, + curses_info.start_y, curses_info.start_x); + + p_menu_win = newwin(RAID_STATUS_MENU_SIZE, + curses_info.max_x, + curses_info.start_y + max_size + RAID_STATUS_HDR_SIZE + 1, + curses_info.start_x); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Display Device Parity Status"); /* string value to set */ + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + RAID_STATUS_HDR_SIZE, + curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + flush_stdscr(); + + clear(); + + post_form(p_form); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 2, 0, + "Parity Serial Resource"); + mvwaddstr(p_title_win, 3, 0, + " Set Number Type Model Name Status"); + } + else + { + mvwaddstr(p_title_win, 2, 0, + "Parity Serial Resource PCI PCI SCSI SCSI SCSI Status"); + mvwaddstr(p_title_win, 3, 0, + " Set Number Model Name Bus Dev Bus ID Lun"); + } + + mvwaddstr(p_menu_win, 3, 0, + EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel r=Refresh f=PageDn b=PageUp"); + + array_num = 1; + check_current_config(false); + + for(p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + continue; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &cmd_status; + ioa_cmd.buffer_len = sizeof(cmd_status); + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_QUERY_COMMAND_STATUS, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Query Command Status to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + close(fd); + continue; + } + + array_query_data = p_cur_ioa->p_qac_data; + p_common_record = + (struct ibmsis_record_common *)array_query_data->data; + + for (i = 0; + i < array_query_data->num_records; + i++, p_common_record = + (struct ibmsis_record_common *)((unsigned long)p_common_record + sistoh16(p_common_record->record_len))) + { + if (p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY_RECORD) + { + p_array_record = (struct ibmsis_array_record *)p_common_record; + array_id = p_array_record->array_id; + + /* Ignore array candidates */ + if (!p_array_record->established) + continue; + + /* Print out "array entry" */ + len += sprintf(buffer, "%4d %8s %x 001 %s", + array_num++, p_cur_ioa->serial_num, p_cur_ioa->ccin, + p_cur_ioa->ioa.dev_name); + } + else if (p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + p_array2_record = (struct ibmsis_array2_record *)p_common_record; + array_id = p_array2_record->array_id; + + /* Ignore array candidates */ + if (!p_array2_record->established) + continue; + + if (p_array2_record->no_config_entry) + { + char serial_num[IBMSIS_SERIAL_NUM_LEN+1]; + + /* Print out "array entry" */ + len += sprintf(buffer, "%4d ",array_num++); + + memcpy(serial_num, p_array2_record->serial_number, IBMSIS_SERIAL_NUM_LEN); + serial_num[IBMSIS_SERIAL_NUM_LEN] = '\0'; + + len += sprintf(buffer + len, "%8s ", serial_num); + + if (platform == SIS_ISERIES) + len += sprintf(buffer + len, "6600 "); + + len += sprintf(buffer + len, "%03d ", IBMSIS_VSET_MODEL_NUMBER); + + if (platform == SIS_ISERIES) + { + len += sprintf(buffer + len, "%-38s", " "); + } + else + { + len += sprintf(buffer + len, "%-16s", " "); + len += sprintf(buffer + len, "%02d %02d", + p_cur_ioa->ioa.p_resource_entry->pci_bus_number, + p_cur_ioa->ioa.p_resource_entry->pci_slot); + + len += sprintf(buffer + len, " %3d %2d %2d ", + p_array2_record->last_resource_address.bus, + p_array2_record->last_resource_address.target, + p_array2_record->last_resource_address.lun); + } + } + else + { + for (j = 0; + j < p_cur_ioa->num_devices; + j++) + { + if (p_cur_ioa->dev[j].p_resource_entry->resource_handle == + p_array2_record->resource_handle) + { + /* Print out "array entry" */ + len += sprintf(buffer, "%4d ",array_num++); + + len += print_dev_pty2(p_cur_ioa->dev[j].p_resource_entry, + buffer + len, + p_cur_ioa->dev[j].dev_name); + + /* Do a query resource state */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &res_state; + ioa_cmd.buffer_len = sizeof(res_state); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = + p_cur_ioa->dev[j].p_resource_entry->resource_address; + + memset(&res_state, 0, sizeof(res_state)); + + rc = sis_ioctl(fd, IBMSIS_QUERY_RESOURCE_STATE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Query Resource State to a device (0x%08X) failed. %m"IBMSIS_EOL, + IBMSIS_GET_PHYSICAL_LOCATOR(p_resource_entry->resource_address)); + res_state.not_oper = 1; + } + + len += print_parity_status(buffer + len, array_id, &res_state, &cmd_status); + + break; + } + } + } + } + else + { + continue; + } + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + RAID_STATUS_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + + for (j = 0; + j < p_cur_ioa->num_devices; + j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + + if ((p_resource_entry->is_array_member) && + (array_id == p_resource_entry->array_id)) + { + len += sprintf(buffer + len, " "); + len += print_dev_pty2(p_resource_entry, + buffer + len, + p_cur_ioa->dev[j].dev_name); + + /* Do a query resource state */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &res_state; + ioa_cmd.buffer_len = sizeof(res_state); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_resource_entry->resource_address; + + memset(&res_state, 0, sizeof(res_state)); + + rc = sis_ioctl(fd, IBMSIS_QUERY_RESOURCE_STATE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Query Resource State to a device (0x%08X) failed. %m"IBMSIS_EOL, + IBMSIS_GET_PHYSICAL_LOCATOR(p_resource_entry->resource_address)); + res_state.not_oper = 1; + } + + len += print_parity_status(buffer + len, array_id, &res_state, &cmd_status); + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + RAID_STATUS_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + } + } + } + + /* now display Hot Spares if any */ + is_first = 1; + for (j = 0; + j < p_cur_ioa->num_devices; + j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + + if (p_resource_entry->is_hot_spare) + { + /* Print out "adapter entry" */ + if (is_first) + { + is_first = 0; + len = sprintf(buffer, " - "); + len += print_dev_pty(p_cur_ioa->ioa.p_resource_entry, + buffer + len, + p_cur_ioa->ioa.dev_name); + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + RAID_STATUS_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + + memset(buffer, 0, 100); + len = 0; + num_lines++; + } + + len = sprintf(buffer + len, " "); + + len += print_dev_pty(p_resource_entry, + buffer + len, + p_cur_ioa->dev[j].dev_name); + + /* Do a query resource state */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &res_state; + ioa_cmd.buffer_len = sizeof(res_state); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_resource_entry->resource_address; + + memset(&res_state, 0, sizeof(res_state)); + + rc = sis_ioctl(fd, IBMSIS_QUERY_RESOURCE_STATE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Query Resource State to a device (0x%08X) failed. %m"IBMSIS_EOL, + IBMSIS_GET_PHYSICAL_LOCATOR(p_resource_entry->resource_address)); + res_state.not_oper = 1; + } + + len += print_parity_status(buffer + len, IBMSIS_INVALID_ARRAY_ID, + &res_state, &cmd_status); + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + RAID_STATUS_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + } + } + close(fd); + } + + + if (num_lines == 0) + mvwaddstr(p_tail_win->p_win, 1, 2, "(Device parity protection has not been started)"); + + p_cur_panel = p_head_panel; + + while(p_cur_panel) + { + bottom_panel(p_cur_panel->p_panel); + p_cur_panel = p_cur_panel->p_next; + } + + while(1) + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + update_panels(); + wrefresh(p_menu_win); + wrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_REFRESH_KEY(ch)) + { + rc = RC_REFRESH; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(panel_below(NULL)); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(panel_above(NULL)); + update_panels(); + doupdate(); + } + break; + } + else + { + mvwaddstr(p_menu_win, 4, 0, "Invalid option specified."); + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + update_panels(); + wrefresh(p_menu_win); + wrefresh(p_title_win); + doupdate(); + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + +int print_parity_status(char *buffer, + u8 array_id, + struct ibmsis_query_res_state *p_res_state, + struct ibmsis_cmd_status *p_cmd_status) +{ + int len = 0; + struct ibmsis_cmd_status_record *p_status_record; + int k; + + if (p_res_state->not_oper) + len += sprintf(buffer + len, "Failed"); + else if (p_res_state->not_ready) + len += sprintf(buffer + len, "Not Ready"); + else if (p_res_state->read_write_prot) + len += sprintf(buffer + len, "R/W Prot"); + else if (p_res_state->prot_dev_failed) + len += sprintf(buffer + len, "Failed"); + else + { + + p_status_record = p_cmd_status->record; + for (k = 0; + k < p_cmd_status->num_records; + k++, p_status_record = + (struct ibmsis_cmd_status_record *)((unsigned long)p_status_record + sistoh16(p_status_record->length))) + { + if ((p_status_record->array_id == array_id) && + (p_status_record->status & IBMSIS_CMD_STATUS_IN_PROGRESS)) + { + len += sprintf(buffer + len,"%d%% ",p_status_record->percent_complete); + switch(p_status_record->command_code) + { + case IBMSIS_RESYNC_ARRAY_PROTECTION: + len += sprintf(buffer + len, "Synched"); + break; + case IBMSIS_REBUILD_DEVICE_DATA: + len += sprintf(buffer + len, "Rebuilt"); + break; + } + break; + } + } + + if (k == p_cmd_status->num_records) + { + if ((p_res_state->prot_suspended || + p_res_state->prot_resuming)) + { + len += sprintf(buffer + len, "Unprot"); + } + else + { + len += sprintf(buffer + len, "Active"); + } + } + } + + return len; +} + +int raid_stop() +{ +/* iSeries + Stop Device Parity Protection + +Select the subsystems to stop device parity protection. + +Type choice, press Enter. + 1=Stop device parity protection + + Parity Serial Resource +Option Set Number Type Model Name + 1 02127005 2782 001 /dev/ibmsis4 + 2 00103039 2748 001 /dev/ibmsis0 + +e=Exit q=Cancel f=PageDn b=PageUp +*/ + +/* non-iSeries + Stop Device Parity Protection + +Select the subsystems to stop device parity protection. + +Type choice, press Enter. + 1=Stop device parity protection + + Parity Vendor Product Serial Resource +Option Set ID ID Number Model Name + 1 IBM DAB61C0E 3AFB348C 200 /dev/sdb + 2 IBM 5C88AFDC A775915E 200 /dev/sdc + + +e=Exit q=Cancel f=PageDn b=PageUp +*/ + int rc, i, array_num, last_char; + struct ibmsis_record_common *p_common_record; + struct ibmsis_array_record *p_array_record; + struct array_cmd_data *p_cur_raid_cmd; + u8 array_id; + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + char buffer[100]; + int array_index; + int max_size = curses_info.max_y - 12; + int confirm_raid_stop(); + int num_lines = 0; + struct sis_ioa *p_cur_ioa; + u32 len; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + int found = 0; + char *p_char; + rc = RC_SUCCESS; + + + p_title_win = newwin(9, curses_info.max_x, 0, 0); + p_menu_win = newwin(3, curses_info.max_x, max_size + 9, 0); + p_field_win = newwin(max_size, curses_info.max_x, 9, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Stop Device Parity Protection"); /* string value to set */ + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + array_num = 1; + + check_current_config(false); + + for(p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + p_cur_ioa->num_raid_cmds = 0; + + for (i = 0; + i < p_cur_ioa->num_devices; + i++) + { + p_common_record = p_cur_ioa->dev[i].p_qac_entry; + + if ((p_common_record != NULL) && + ((p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY_RECORD) || + (p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD))) + { + p_array_record = (struct ibmsis_array_record *)p_common_record; + + if (p_array_record->stop_cand) + { + rc = is_array_in_use(p_cur_ioa, p_array_record->array_id); + if (rc != 0) continue; + + if (p_head_raid_cmd) + { + p_tail_raid_cmd->p_next = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + p_tail_raid_cmd = p_tail_raid_cmd->p_next; + } + else + { + p_head_raid_cmd = p_tail_raid_cmd = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + } + + p_tail_raid_cmd->p_next = NULL; + + memset(p_tail_raid_cmd, 0, sizeof(struct array_cmd_data)); + + array_id = p_array_record->array_id; + + p_tail_raid_cmd->array_id = array_id; + p_tail_raid_cmd->array_num = array_num; + p_tail_raid_cmd->p_sis_ioa = p_cur_ioa; + p_tail_raid_cmd->p_sis_device = &p_cur_ioa->dev[i]; + + start_y = (array_num-1) % (max_size - 1); + + if ((num_lines > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 3, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)p_tail_raid_cmd); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 9, start_y, 9, 0, 0); + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, "%4d %8s %x %03d %s", + array_num, + p_cur_ioa->dev[i].p_resource_entry->serial_num, + p_cur_ioa->dev[i].p_resource_entry->type, + p_cur_ioa->dev[i].p_resource_entry->model, + p_cur_ioa->dev[i].dev_name); + } + else + { + char buf[100]; + + len = sprintf(buffer, "%4d ", array_num); + + memcpy(buf, p_cur_ioa->dev[i].p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-8s ", buf); + + memcpy(buf, p_cur_ioa->dev[i].p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s %03d %s", + p_cur_ioa->dev[i].p_resource_entry->serial_num, + p_cur_ioa->dev[i].p_resource_entry->model, + p_cur_ioa->dev[i].dev_name); + } + set_field_buffer(pp_field[field_index], 0, buffer); + field_opts_off(pp_field[field_index], O_ACTIVE); + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + array_num++; + } + } + } + } + + if (array_num == 1) + { + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Stop Device Parity Protection Failed"); /* string value to set */ + + mvwaddstr(p_title_win, 2, 0, "There are no disk units eligible for the selected operation"); + mvwaddstr(p_title_win, 3, 0, "due to one or more of the following reasons:"); + mvwaddstr(p_title_win, 5, 0, "o There are no device parity protected units in the system."); + mvwaddstr(p_title_win, 6, 0, "o An IOA is in a condition that makes the disk units attached to"); + mvwaddstr(p_title_win, 7, 0, " it read/write protected. Examine the kernel messages log"); + mvwaddstr(p_title_win, 8, 0, " for any errors that are logged for the IO subsystem"); + mvwaddstr(p_field_win, 0, 0, " and follow the appropriate procedure for the reference code to"); + mvwaddstr(p_field_win, 1, 0, " correct the problem, if necessary."); + mvwaddstr(p_field_win, 2, 0, "o Not all disk units attached to an advanced function IOA have"); + mvwaddstr(p_field_win, 3, 0, " reported to the system. Retry the operation."); + mvwaddstr(p_field_win, 4, 0, "o The disk units are missing."); + mvwaddstr(p_field_win, 5, 0, "o The disk unit/s are currently in use."); + mvwaddstr(p_field_win, max_size -1, 0, "Press Enter to continue."); + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD); /* form request code */ + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + } + } + + mvwaddstr(p_title_win, 2, 0, "Select the subsystems to stop device parity protection."); + mvwaddstr(p_title_win, 4, 0, "Type choice, press Enter."); + mvwaddstr(p_title_win, 5, 0, " 1=Stop device parity protection"); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 7, 0, " Parity Serial Resource"); + mvwaddstr(p_title_win, 8, 0, "Option Set Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 7, 0, " Parity Vendor Product Serial Resource"); + mvwaddstr(p_title_win, 8, 0, "Option Set ID ID Number Model Name"); + } + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + + field_opts_off(p_fields[1], O_ACTIVE); + + array_index = ((max_size - 1) * 2) + 1; + for (i = array_index; i < field_index; i += array_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + flush_stdscr(); + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + + while(1) + { + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (IS_PGUP_KEY(ch)) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if ((ch == KEY_DOWN) || + (ch == '\t')) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_NEXT_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (ch == KEY_UP) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_PREV_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (IS_ENTER_KEY(ch)) + { + found = 0; + unpost_form(p_list_form); + + for (i = 0; i < field_index; i++) + { + p_cur_raid_cmd = (struct array_cmd_data *)field_userptr(pp_field[i]); + if (p_cur_raid_cmd != NULL) + { + p_char = field_buffer(pp_field[i], 0); + if (strcmp(p_char, "1") == 0) + { + found = 1; + p_cur_raid_cmd->do_cmd = 1; + + p_array_record = (struct ibmsis_array_record *)p_cur_raid_cmd->p_sis_device->p_qac_entry; + if (!p_array_record->issue_cmd) + { + p_array_record->issue_cmd = 1; + + /* known_zeroed means do not preserve + user data on stop */ + p_array_record->known_zeroed = 1; + p_cur_raid_cmd->p_sis_ioa->num_raid_cmds++; + } + } + else + { + p_cur_raid_cmd->do_cmd = 0; + p_array_record = (struct ibmsis_array_record *)p_cur_raid_cmd->p_sis_device->p_qac_entry; + + if (p_array_record->issue_cmd) + { + p_array_record->issue_cmd = 0; + p_cur_raid_cmd->p_sis_ioa->num_raid_cmds--; + } + } + } + } + + if (found != 0) + { + /* Go to verification screen */ + unpost_form(p_form); + rc = confirm_raid_stop(); + goto leave; + } + else + { + post_form(p_list_form); + rc = 1; + } + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free(pp_field); + + p_cur_raid_cmd = p_head_raid_cmd; + while(p_cur_raid_cmd) + { + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + free(p_head_raid_cmd); + p_head_raid_cmd = p_cur_raid_cmd; + } + + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + + +int confirm_raid_stop() +{ +#define CONFIRM_STOP_HDR_SIZE 10 +#define CONFIRM_STOP_MENU_SIZE 3 +/* iSeries + Confirm Stop Device Parity Protection + +ATTENTION: Disk units connected to these subsystems will not be +protected after you confirm your choice. + +Press Enter to continue. +Press q=Cancel to return and change your choice. + + Parity Serial Resource +Option Set Number Type Model Name + 1 1 02127005 2782 001 /dev/ibmsis4 + 1 1 002443C6 6713 050 /dev/sdr + 1 1 0024B45C 6713 050 /dev/sds + 1 1 00000DC7 6717 050 /dev/sdt + 1 1 000BBBC1 6717 050 /dev/sdu + 1 1 0002F5AA 6717 050 /dev/sdv + +q=Cancel f=PageDn b=PageUp +*/ +/* non-iSeries + + Confirm Stop Device Parity Protection + +ATTENTION: Disk units connected to these subsystems will not be +protected after you confirm your choice. + +Press Enter to continue. +Press q=Cancel to return and change your choice. + + Parity Vendor Product Serial Resource +Option Set ID ID Number Model Name + 1 1 IBM DAB61C0E 3AFB348C 200 /dev/sdb + 1 1 IBMAS400 DCHS09W 0024A0B9 070 + 1 1 IBMAS400 DFHSS4W 00D37A11 070 + +q=Cancel f=PageDn b=PageUp + +*/ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + struct sis_device *p_sis_device; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct array_cmd_data *p_cur_raid_cmd; + struct ibmsis_device_record *p_device_record; + struct ibmsis_resource_flags *p_resource_flags; + struct sis_ioa *p_cur_ioa; + int fd, rc, j; + u16 len; + char buffer[100]; + u32 num_lines = 0; + int max_size = curses_info.max_y - (CONFIRM_STOP_HDR_SIZE + CONFIRM_STOP_MENU_SIZE + 1); + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel, *p_cur_panel; + WINDOW *p_title_win, *p_menu_win; + PANEL *p_panel; + + int raid_stop_complete(); + + p_title_win = newwin(CONFIRM_STOP_HDR_SIZE, + curses_info.max_x, + curses_info.start_y, + curses_info.start_x); + + p_menu_win = newwin(CONFIRM_STOP_MENU_SIZE, + curses_info.max_x, + curses_info.start_y + max_size + CONFIRM_STOP_HDR_SIZE + 1, + curses_info.start_x); + + rc = RC_SUCCESS; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Confirm Stop Device Parity Protection"); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_STOP_HDR_SIZE, + curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + wattron(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 2, 0, "ATTENTION:"); + wattroff(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 2, 10, " Disk units connected to these subsystems will not be"); + mvwaddstr(p_title_win, 3, 0, "protected after you confirm your choice."); + mvwaddstr(p_title_win, 5, 0, "Press Enter to continue."); + mvwaddstr(p_title_win, 6, 0, "Press "CANCEL_KEY_LABEL"=Cancel to return and change your choice."); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 8, 0, " Parity Serial Resource"); + mvwaddstr(p_title_win, 9, 0, "Option Set Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 8, 0, " Parity Vendor Product Serial Resource"); + mvwaddstr(p_title_win, 9, 0, "Option Set ID ID Number Model Name"); + } + + mvwaddstr(p_menu_win, 1, 0, CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_cur_raid_cmd = p_head_raid_cmd; + + while(p_cur_raid_cmd) + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + p_sis_device = p_cur_raid_cmd->p_sis_device; + + if (platform == SIS_ISERIES) + { + /* Print out "array entry" */ + len = sprintf(buffer, " 1 %4d %8s %x %03d %s", + p_cur_raid_cmd->array_num, + p_sis_device->p_resource_entry->serial_num, + p_sis_device->p_resource_entry->type, + p_sis_device->p_resource_entry->model, + p_sis_device->dev_name); + } + else + { + char buf[100]; + + /* Print out "array entry" */ + len = sprintf(buffer, " 1 %4d ", p_cur_raid_cmd->array_num); + + memcpy(buf, p_sis_device->p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-8s ", buf); + + memcpy(buf, p_sis_device->p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s %03d %s", + p_sis_device->p_resource_entry->serial_num, + p_sis_device->p_resource_entry->model, + p_sis_device->dev_name); + } + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_STOP_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + + if (p_resource_entry->is_array_member && + (p_cur_raid_cmd->array_id == p_resource_entry->array_id)) + { + len = sprintf(buffer, " 1 %4d ", p_cur_raid_cmd->array_num); + + p_device_record = (struct ibmsis_device_record *)p_cur_ioa->dev[j].p_qac_entry; + p_resource_flags = &p_device_record->resource_flags_to_become; + + if (platform == SIS_ISERIES) + { + len += print_dev2(p_resource_entry, + buffer + len, + p_resource_flags, + p_cur_ioa->dev[j].dev_name); + } + else + { + char buf[100]; + + memcpy(buf, p_cur_ioa->dev[j].p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(buffer + len, " %-8s ", buf); + + memcpy(buf, p_cur_ioa->dev[j].p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s %03d %s", + p_resource_entry->serial_num, + p_resource_entry->model, + p_cur_ioa->dev[j].dev_name); + } + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_STOP_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + } + } + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + + p_cur_panel = p_head_panel; + + while(p_cur_panel) + { + bottom_panel(p_cur_panel->p_panel); + p_cur_panel = p_cur_panel->p_next; + } + + while(1) + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_REFRESH; + goto leave; + } + else if (IS_ENTER_KEY(ch)) + { + p_cur_raid_cmd = p_head_raid_cmd; + while(p_cur_raid_cmd) + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + p_sis_device = p_cur_raid_cmd->p_sis_device; + + rc = is_array_in_use(p_cur_ioa, p_cur_raid_cmd->array_id); + if (rc != 0) + { + syslog(LOG_ERR, + "Array %s is currently in use and cannot be deleted." + IBMSIS_EOL, p_sis_device->dev_name); + rc = RC_FAILED; + goto leave; + } + + if (p_sis_device->p_qac_entry->record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + goto leave; + } + + mvaddstr(curses_info.max_y - 1, 0, + "Operation in progress - please wait"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = NULL; + ioa_cmd.buffer_len = 0; + ioa_cmd.device_cmd = 1; + ioa_cmd.cdb[4] = IBMSIS_START_STOP_STOP; + ioa_cmd.resource_address = p_sis_device->p_resource_entry->resource_address; + + rc = sis_ioctl(fd, START_STOP, &ioa_cmd); + close(fd); + + if (rc != 0) + { + syslog(LOG_ERR, "Stop Start/Stop Unit to %s failed. %m"IBMSIS_EOL, p_sis_device->dev_name); + rc = RC_FAILED; + goto leave; + } + } + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + + for (p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + if (p_cur_ioa->num_raid_cmds > 0) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + goto leave; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_ioa->p_qac_data; + ioa_cmd.buffer_len = sistoh16(p_cur_ioa->p_qac_data->resp_len); + ioa_cmd.read_not_write = 0; + + rc = sis_ioctl(fd, IBMSIS_STOP_ARRAY_PROTECTION, &ioa_cmd); + close(fd); + + if (rc != 0) + { + syslog(LOG_ERR, "Stop Array Protection to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + rc = RC_FAILED; + goto leave; + } + } + } + + rc = raid_stop_complete(); + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else + { + break; + } + } + + } + + leave: + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + + +int raid_stop_complete() +{ + /* + Stop Device Parity Protection Status + + You selected to stop device parity protection + + + + + + + + + + 16% Complete + */ + + FIELD *p_fields[3]; + FORM *p_form; + FORM *p_old_form; + struct ibmsis_cmd_status cmd_status; + struct ibmsis_cmd_status_record *p_record; + int done_bad; + int not_done = 0; + int rc, j, fd; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + u32 percent_cmplt = 0; + struct sis_ioa *p_cur_ioa; + u32 num_stops = 0; + struct array_cmd_data *p_cur_raid_cmd; + struct ibmsis_record_common *p_common_record; + struct ibmsis_resource_entry *p_resource_entry; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + curses_info.max_y - 1, curses_info.max_x - 1, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Stop Device Parity Protection Status"); + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + while(1) + { + clear(); + post_form(p_form); + + mvaddstr(2, 0, "You selected to stop device parity protection"); + mvprintw(curses_info.max_y / 2, (curses_info.max_x / 2) - 7, "%d%% Complete", percent_cmplt); + + form_driver(p_form, + REQ_FIRST_FIELD); + refresh(); + + percent_cmplt = 100; + done_bad = 0; + num_stops = 0; + not_done = 0; + + for (p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + if (p_cur_ioa->num_raid_cmds > 0) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDONLY); + + if (fd < 0) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + p_cur_ioa->num_raid_cmds = 0; + done_bad = 1; + continue; + } + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &cmd_status; + ioa_cmd.buffer_len = sizeof(cmd_status); + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_QUERY_COMMAND_STATUS, &ioa_cmd); + + if (rc) + { + syslog(LOG_ERR, "Query Command Status to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + close(fd); + p_cur_ioa->num_raid_cmds = 0; + done_bad = 1; + continue; + } + + close(fd); + p_record = cmd_status.record; + + for (j=0; j < cmd_status.num_records; j++, p_record++) + { + if (p_record->command_code == IBMSIS_STOP_ARRAY_PROTECTION) + { + for (p_cur_raid_cmd = p_head_raid_cmd; + p_cur_raid_cmd != NULL; + p_cur_raid_cmd = p_cur_raid_cmd->p_next) + { + if ((p_cur_raid_cmd->p_sis_ioa = p_cur_ioa) && + (p_cur_raid_cmd->array_id == p_record->array_id)) + { + num_stops++; + if (p_record->status == IBMSIS_CMD_STATUS_IN_PROGRESS) + { + if (p_record->percent_complete < percent_cmplt) + percent_cmplt = p_record->percent_complete; + not_done = 1; + } + else if (p_record->status != IBMSIS_CMD_STATUS_SUCCESSFUL) + { + rc = RC_FAILED; + } + break; + } + } + } + } + } + } + + unpost_form(p_form); + + if (!not_done) + { + free_form(p_form); + curses_info.p_form = p_old_form; + for (j=0; j < 2; j++) + free_field(p_fields[j]); + + if (done_bad) + { + flush_stdscr(); + return RC_FAILED; + } + + for (p_cur_raid_cmd = p_head_raid_cmd; + p_cur_raid_cmd != NULL; + p_cur_raid_cmd = p_cur_raid_cmd->p_next) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + p_common_record = p_cur_raid_cmd->p_sis_device->p_qac_entry; + if ((p_common_record != NULL) && + (p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD)) + { + p_resource_entry = p_cur_raid_cmd->p_sis_device->p_resource_entry; + remove_device(p_resource_entry->resource_address, p_cur_ioa); + scan_device(p_resource_entry->resource_address, p_cur_ioa->host_num); + } + } + check_current_config(false); + revalidate_devs(NULL); + flush_stdscr(); + return RC_SUCCESS; + } + not_done = 0; + sleep(2); + } +} + +int raid_start() +{ +/* iSeries + Start Device Parity Protection + +Select the subsystems to start device parity protection. + +Type choice, press Enter. + 1=Start device parity protection + + Parity Serial Resource +Option Set Number Type Model Name + 1 1 02127005 5703 001 /dev/ibmsis1 + + +e=Exit q=Cancel f=PageDn b=PageUp + +*/ +/* non-iSeries + Start Device Parity Protection + +Select the subsystems to start device parity protection. + +Type choice, press Enter. + 1=Start device parity protection + + Parity Vendor Product Serial Resource +Option Set ID ID Number Model Name + 1 IBM DAB61C0E 3AFB348C 200 /dev/sdb + 2 IBM 5C88AFDC A775915E 200 /dev/sdc + + +e=Exit q=Cancel f=PageDn b=PageUp + +*/ + + int rc, i, array_num, last_char; + struct ibmsis_record_common *p_common_record; + struct ibmsis_array_record *p_array_record; + struct array_cmd_data *p_cur_raid_cmd; + u8 array_id; + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + char buffer[100]; + int array_index, num_vsets; + int max_size = curses_info.max_y - 12; + int confirm_raid_start(); + int configure_raid_start(struct array_cmd_data *p_cur_raid_cmd, + int num_vsets); + int num_lines = 0; + struct sis_ioa *p_cur_ioa; + u32 len; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + int found = 0; + char *p_char; + int ch; + + rc = RC_SUCCESS; + + p_title_win = newwin(9, curses_info.max_x, 0, 0); + p_menu_win = newwin(3, curses_info.max_x, max_size + 9, 0); + p_field_win = newwin(max_size, curses_info.max_x, 9, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Start Device Parity Protection"); /* string value to set */ + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + array_num = 1; + + check_current_config(false); + + for(p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + p_cur_ioa->num_raid_cmds = 0; + + for (i = 0; + i < p_cur_ioa->num_devices; + i++) + { + p_common_record = p_cur_ioa->dev[i].p_qac_entry; + + if ((p_common_record != NULL) && + ((p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY_RECORD) || + (p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD))) + { + p_array_record = (struct ibmsis_array_record *)p_common_record; + + if (p_array_record->start_cand) + { + rc = is_array_in_use(p_cur_ioa, p_array_record->array_id); + if (rc != 0) continue; + + if (p_head_raid_cmd) + { + p_tail_raid_cmd->p_next = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + p_tail_raid_cmd = p_tail_raid_cmd->p_next; + } + else + { + p_head_raid_cmd = p_tail_raid_cmd = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + } + + p_tail_raid_cmd->p_next = NULL; + + memset(p_tail_raid_cmd, 0, sizeof(struct array_cmd_data)); + + array_id = p_array_record->array_id; + + p_tail_raid_cmd->array_id = array_id; + p_tail_raid_cmd->array_num = array_num; + p_tail_raid_cmd->p_sis_ioa = p_cur_ioa; + p_tail_raid_cmd->p_sis_device = &p_cur_ioa->dev[i]; + p_tail_raid_cmd->p_qac_data = NULL; + + start_y = (array_num-1) % (max_size - 1); + + if ((num_lines > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 3, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)p_tail_raid_cmd); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 9, start_y, 9, 0, 0); + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, "%4d %8s %x %03d %s", + array_num, + p_cur_ioa->dev[i].p_resource_entry->serial_num, + p_cur_ioa->dev[i].p_resource_entry->type, + p_cur_ioa->dev[i].p_resource_entry->model, + p_cur_ioa->dev[i].dev_name); + } + else + { + char buf[100]; + + len = sprintf(buffer, "%4d ", array_num); + + memcpy(buf, p_cur_ioa->dev[i].p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-8s ", buf); + + memcpy(buf, p_cur_ioa->dev[i].p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s %03d %s", + p_cur_ioa->dev[i].p_resource_entry->serial_num, + p_cur_ioa->dev[i].p_resource_entry->model, + p_cur_ioa->dev[i].dev_name); + } + + set_field_buffer(pp_field[field_index], 0, buffer); + field_opts_off(pp_field[field_index], O_ACTIVE); + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + array_num++; + } + } + } + } + + if (array_num == 1) + { + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Start Device Parity Protection Failed"); /* string value to set */ + + mvwaddstr(p_title_win, 2, 0, "There are no disk units eligible for the selected operation"); + mvwaddstr(p_title_win, 3, 0, "due to one or more of the following reasons:"); + mvwaddstr(p_title_win, 5, 0, "o There are not enough device parity capable units in the system."); + mvwaddstr(p_title_win, 6, 0, "o An IOA is in a condition that makes the disk units attached to"); + mvwaddstr(p_title_win, 7, 0, " it read/write protected. Examine the kernel messages log"); + mvwaddstr(p_title_win, 8, 0, " for any errors that are logged for the IO subsystem"); + mvwaddstr(p_field_win, 0, 0, " and follow the appropriate procedure for the reference code to"); + mvwaddstr(p_field_win, 1, 0, " correct the problem, if necessary."); + mvwaddstr(p_field_win, 2, 0, "o Not all disk units attached to an advanced function IOA have"); + mvwaddstr(p_field_win, 3, 0, " reported to the system. Retry the operation."); + mvwaddstr(p_field_win, 4, 0, "o The disk units are missing."); + mvwaddstr(p_field_win, 5, 0, "o The disk unit/s are currently in use."); + mvwaddstr(p_field_win, max_size -1, 0, "Press Enter to continue."); + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD); /* form request code */ + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + } + } + + mvwaddstr(p_title_win, 2, 0, "Select the subsystems to start device parity protection."); + mvwaddstr(p_title_win, 4, 0, "Type choice, press Enter."); + mvwaddstr(p_title_win, 5, 0, " 1=Start device parity protection"); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 7, 0, " Parity Serial Resource"); + mvwaddstr(p_title_win, 8, 0, "Option Set Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 7, 0, " Parity Vendor Product Serial Resource"); + mvwaddstr(p_title_win, 8, 0, "Option Set ID ID Number Model Name"); + } + + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + + field_opts_off(p_fields[1], O_ACTIVE); + + array_index = ((max_size - 1) * 2) + 1; + for (i = array_index; i < field_index; i += array_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + flush_stdscr(); + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + form_driver(p_list_form, + REQ_FIRST_FIELD); + + while(1) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + } + else if (IS_PGUP_KEY(ch)) + { + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + } + else if ((ch == KEY_DOWN) || + (ch == '\t')) + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + } + else if (ch == KEY_UP) + { + form_driver(p_list_form, + REQ_PREV_FIELD); + } + else if (IS_ENTER_KEY(ch)) + { + found = 0; + + unpost_form(p_list_form); + p_cur_raid_cmd = p_head_raid_cmd; + + for (i = 0; i < field_index; i++) + { + p_cur_raid_cmd = (struct array_cmd_data *)field_userptr(pp_field[i]); + if (p_cur_raid_cmd != NULL) + { + p_char = field_buffer(pp_field[i], 0); + p_array_record = (struct ibmsis_array_record *)p_cur_raid_cmd->p_sis_device->p_qac_entry; + + if (strcmp(p_char, "1") == 0) + { + if (p_array_record->common.record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + rc = RC_SUCCESS; + num_vsets = 0; + while((RC_REFRESH == rc) || + (RC_SUCCESS == rc)) + { + clear(); + rc = configure_raid_start(p_cur_raid_cmd, num_vsets); + + if (RC_SUCCESS == rc) + { + num_vsets++; + found = 1; + p_cur_raid_cmd->do_cmd = 1; + p_array_record->issue_cmd = 1; + p_cur_raid_cmd->p_sis_ioa->num_raid_cmds++; + + p_tail_raid_cmd->p_next = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + p_tail_raid_cmd = p_tail_raid_cmd->p_next; + p_tail_raid_cmd->p_next = NULL; + + memset(p_tail_raid_cmd, 0, sizeof(struct array_cmd_data)); + + array_id = p_array_record->array_id; + + p_tail_raid_cmd->array_id = array_id; + p_tail_raid_cmd->array_num = array_num; + p_tail_raid_cmd->p_sis_ioa = p_cur_raid_cmd->p_sis_ioa; + p_tail_raid_cmd->p_sis_device = p_cur_raid_cmd->p_sis_device; + + p_cur_raid_cmd = p_tail_raid_cmd; + array_num++; + } + } + if (rc == RC_EXIT) + goto leave; + if (rc == RC_CANCEL) + { + rc = RC_REFRESH; + goto leave; + } + } + else + { + found = 1; + p_cur_raid_cmd->do_cmd = 1; + p_array_record->issue_cmd = 1; + p_cur_raid_cmd->p_sis_ioa->num_raid_cmds++; + } + } + else + { + p_cur_raid_cmd->do_cmd = 0; + } + } + } + + if (found != 0) + { + /* Go to verification screen */ + unpost_form(p_form); + rc = confirm_raid_start(); + goto leave; + } + else + { + rc = RC_REFRESH; + goto leave; + } + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free(pp_field); + + p_cur_raid_cmd = p_head_raid_cmd; + while(p_cur_raid_cmd) + { + if (p_cur_raid_cmd->p_qac_data) + { + free(p_cur_raid_cmd->p_qac_data); + p_cur_raid_cmd->p_qac_data = NULL; + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + free(p_head_raid_cmd); + p_head_raid_cmd = p_cur_raid_cmd; + } + + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int configure_raid_start(struct array_cmd_data *p_cur_raid_cmd, + int num_vsets) +{ +/* + + + Select Disk Units for Parity Protection + +Type option, press Enter. + 1=Select + + Vendor Product Serial PCI PCI SCSI SCSI SCSI +OPT ID ID Number Bus Dev Bus ID Lun + IBM DFHSS4W 0024A0B9 05 03 0 3 0 + IBM DFHSS4W 00D38D0F 05 03 0 5 0 + IBM DFHSS4W 00D32240 05 03 0 9 0 + IBM DFHSS4W 00034563 05 03 0 6 0 + IBM DFHSS4W 00D37A11 05 03 0 4 0 + +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + Select Disk Units for Parity Protection + +Type option, press Enter. + 1=Select + + Serial Frame Card PCI PCI SCSI SCSI SCSI +OPT Type Number ID Position Bus Dev Bus ID Lun + 6607 0024A0B9 03 D01 05 03 0 3 0 + 6607 00D38D0F 03 D02 05 03 0 5 0 + 6607 00D32240 03 D03 05 03 0 9 0 + 6607 00034563 03 D04 05 03 0 6 0 + 6717 00D37A11 03 D05 05 03 0 4 0 + +*/ + + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + int rc, i, j, init_index, found, last_char; + char buffer[100]; + int max_size = curses_info.max_y - 10; + int num_devs = 0; + struct sis_ioa *p_cur_ioa; + char *p_char; + u32 len; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int field_index = 0; + int start_y; + struct sis_device *p_sis_device; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_device_record *p_device_record; + struct ibmsis_array_query_data *p_qac_data_tmp; + int configure_raid_parameters(struct array_cmd_data *p_cur_raid_cmd); + int continue_raid_start(struct sis_ioa *p_cur_ioa); + + rc = RC_SUCCESS; + + p_title_win = newwin(7, curses_info.max_x, + 0, 0); + + p_menu_win = newwin(3, curses_info.max_x, + max_size + 7, 0); + + p_field_win = newwin(max_size, curses_info.max_x, 7, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Select Disk Units for Parity Protection"); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + p_device_record = (struct ibmsis_device_record *)p_cur_ioa->dev[j].p_qac_entry; + + if (p_device_record == NULL) + continue; + + if (p_cur_ioa->dev[j].is_start_cand) + continue; + + if (!p_resource_entry->is_ioa_resource && + (p_device_record->common.record_id == IBMSIS_RECORD_ID_DEVICE2_RECORD) && + (p_device_record->start_cand)) + { + len = print_dev_sel(p_resource_entry, buffer); + start_y = num_devs % (max_size - 1); + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 1, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)&p_cur_ioa->dev[j]); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 7, /* new field size */ + start_y, 7, 0, 0); + + set_field_buffer(pp_field[field_index], 0, buffer); + + field_opts_off(pp_field[field_index], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_userptr(pp_field[field_index++], NULL); + + if ((num_devs > 0) && ((num_devs % (max_size - 2)) == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + start_y + 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + memset(buffer, 0, 100); + + len = 0; + num_devs++; + } + } + + if (num_devs) + { + if (num_vsets > 0) + { + rc = continue_raid_start(p_cur_ioa); + if (rc != RC_SUCCESS) + { + free_field(p_fields[0]); + return rc; + } + } + + mvwaddstr(p_title_win, 2, 0, "Type option, press Enter."); + mvwaddstr(p_title_win, 3, 0, " 1=Select"); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 5, 0, + " Serial Frame Card PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "OPT Type Number ID Position Bus Dev Bus ID Lun"); + } + else + { + mvwaddstr(p_title_win, 5, 0, + " Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "OPT ID ID Number Bus Dev Bus ID Lun"); + } + + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_qac_data_tmp = malloc(sizeof(struct ibmsis_array_query_data)); + memcpy(p_qac_data_tmp, + p_cur_ioa->p_qac_data, + sizeof(struct ibmsis_array_query_data)); + + field_opts_off(p_fields[1], O_ACTIVE); + + init_index = ((max_size - 1) * 2) + 1; + for (i = init_index; i < field_index; i += init_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + + while (1) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_NOOP; + goto leave; + } + else if (ch == KEY_DOWN) + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else if (ch == KEY_UP) + { + form_driver(p_list_form, + REQ_PREV_FIELD); + break; + } + else if (IS_ENTER_KEY(ch)) + { + found = 0; + + mvwaddstr(p_menu_win, 2, 1, + " "); + wrefresh(p_menu_win); + + for (i = 0; + i < field_index; i++) + { + p_sis_device = + (struct sis_device *)field_userptr(pp_field[i]); + + if (p_sis_device != NULL) + { + p_char = field_buffer(pp_field[i], 0); + if (strcmp(p_char, "1") == 0) + { + found = 1; + p_device_record = (struct ibmsis_device_record *)p_sis_device->p_qac_entry; + p_device_record->issue_cmd = 1; + p_sis_device->is_start_cand = 1; + } + } + } + + if (found != 0) + { + /* Go to parameters screen */ + unpost_form(p_list_form); + unpost_form(p_form); + rc = configure_raid_parameters(p_cur_raid_cmd); + if (rc == RC_EXIT) + goto leave; + if (rc == RC_CANCEL) + { + /* clear out current selections */ + for (i = 0; i < field_index; i++) + { + p_sis_device = (struct sis_device *)field_userptr(pp_field[i]); + if (p_sis_device != NULL) + { + p_char = field_buffer(pp_field[i], 0); + if (strcmp(p_char, "1") == 0) + { + p_device_record = (struct ibmsis_device_record *)p_sis_device->p_qac_entry; + p_device_record->issue_cmd = 0; + p_sis_device->is_start_cand = 0; + } + } + } + rc = RC_REFRESH; + goto leave; + } + p_cur_raid_cmd->p_qac_data = + malloc(sizeof(struct ibmsis_array_query_data)); + + /* save off qac data image with issue_cmd set + for selected devices */ + memcpy(p_cur_raid_cmd->p_qac_data, + p_cur_ioa->p_qac_data, + sizeof(struct ibmsis_array_query_data)); + goto leave; + } + else + { + break; + } + } + else if (IS_PGDN_KEY(ch)) + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if (IS_PGUP_KEY(ch)) + { + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if (ch == '\t') + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + break; + } + } + } + } + else + { + /* No devices to initialize */ + free_field(p_fields[0]); + return RC_NOOP; + } + leave: + + /* restore unmodified image of qac data */ + memcpy(p_cur_ioa->p_qac_data, + p_qac_data_tmp, + sizeof(struct ibmsis_array_query_data)); + free(p_qac_data_tmp); + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + + free_screen(NULL, NULL, p_fields); + free_screen(NULL, NULL, pp_field); + free(pp_field); + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + flush_stdscr(); + return rc; +} + +int configure_raid_parameters(struct array_cmd_data *p_cur_raid_cmd) +{ + /* + Select Protection Level and Stripe Size + + Default array configurations are shown. To change + setting hit "c" for options menu. Highlight desired + and option and hit Enter. + + c=Change Setting + + + Protection Level . . . . . . . . . . . . : RAID 0 + Stripe Size . . . . . . . . . . . . . . : 64 KB + + + + + + + + Press Enter to Continue. + + e=Exit q=Cancel + */ + FIELD *p_input_fields[4]; + FIELD *p_cur_field; + FORM *p_form, *p_old_form; + ITEM **raid_item = NULL; + int raid_index_default; + unsigned long raid_index = 0; + unsigned long index; + char buffer[24]; + int rc, i; + struct sis_ioa *p_cur_ioa; + struct ibmsis_supported_arrays *p_supported_arrays; + struct ibmsis_array_cap_entry *p_cur_array_cap_entry; + struct ibmsis_device_record *p_device_record; + struct text_str + { + char line[16]; + } *raid_menu_str = NULL, *stripe_menu_str = NULL; + char raid_str[16], stripe_str[16]; + int ch, start_row; + int cur_field_index; + int selected_count = 0; + int stripe_sz, stripe_sz_mask, stripe_sz_list[16]; + struct prot_level *prot_level_list; + int *userptr = NULL; + int *retptr; + + rc = RC_SUCCESS; + + /* Title */ + p_input_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* Protection Level */ + p_input_fields[1] = new_field(1, 9, /* new field size */ + 8, 44, /* */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* Stripe Size */ + p_input_fields[2] = new_field(1, 9, /* new field size */ + 9, 44, /* */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_input_fields[3] = NULL; + + + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + p_supported_arrays = p_cur_ioa->p_supported_arrays; + p_cur_array_cap_entry = (struct ibmsis_array_cap_entry *)p_supported_arrays->data; + + /* determine number of devices selected for this parity set */ + for (i=0; inum_devices; i++) + { + p_device_record = (struct ibmsis_device_record *) + p_cur_ioa->dev[i].p_qac_entry; + + if ((p_device_record != NULL) && + (p_device_record->common.record_id == IBMSIS_RECORD_ID_DEVICE2_RECORD) && + (p_device_record->issue_cmd)) + { + selected_count++; + } + } + + /* set up raid lists */ + raid_index = 0; + raid_index_default = 0; + prot_level_list = malloc(sizeof(struct prot_level)); + prot_level_list[raid_index].is_valid_entry = 0; + + for (i=0; inum_entries); i++) + { + if ((selected_count <= p_cur_array_cap_entry->max_num_array_devices) && + (selected_count >= p_cur_array_cap_entry->min_num_array_devices) && + ((selected_count % p_cur_array_cap_entry->min_mult_array_devices) == 0)) + { + prot_level_list[raid_index].p_array_cap_entry = p_cur_array_cap_entry; + prot_level_list[raid_index].is_valid_entry = 1; + if (0 == strcmp(p_cur_array_cap_entry->prot_level_str,IBMSIS_DEFAULT_RAID_LVL)) + { + raid_index_default = raid_index; + } + raid_index++; + prot_level_list = realloc(prot_level_list, sizeof(struct prot_level) * (raid_index + 1)); + prot_level_list[raid_index].is_valid_entry = 0; + } + p_cur_array_cap_entry = (struct ibmsis_array_cap_entry *) + ((void *)p_cur_array_cap_entry + sistoh16(p_supported_arrays->entry_length)); + } + + raid_index = raid_index_default; + p_cur_array_cap_entry = prot_level_list[raid_index].p_array_cap_entry; + stripe_sz = sistoh16(p_cur_array_cap_entry->recommended_stripe_size); + + p_old_form = curses_info.p_form; + + curses_info.p_form = p_form = new_form(p_input_fields); + + set_current_field(p_form, p_input_fields[1]); + + set_field_just(p_input_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_input_fields[0], O_ACTIVE); + field_opts_off(p_input_fields[1], O_EDIT); + field_opts_off(p_input_fields[2], O_EDIT); + + set_field_buffer(p_input_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Select Protection Level and Stripe Size"); /* string value to set */ + + form_opts_off(p_form, O_BS_OVERLOAD); + + flush_stdscr(); + + clear(); + + post_form(p_form); + + mvaddstr(2, 1, "Default array configurations are shown. To change"); + mvaddstr(3, 1, "setting hit \"c\" for options menu. Highlight desired"); + mvaddstr(4, 1, "option then hit Enter"); + mvaddstr(6, 1, "c=Change Setting"); + mvaddstr(8, 0, "Protection Level . . . . . . . . . . . . :"); + mvaddstr(9, 0, "Stripe Size . . . . . . . . . . . . . . :"); + mvaddstr(curses_info.max_y - 3, 1, "Press Enter to Continue"); + mvaddstr(curses_info.max_y - 1, 1, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + form_driver(p_form, /* form to pass input to */ + REQ_FIRST_FIELD ); /* form request code */ + + while (1) + { + + sprintf(raid_str,"RAID %s",p_cur_array_cap_entry->prot_level_str); + set_field_buffer(p_input_fields[1], /* field to alter */ + 0, /* number of buffer to alter */ + raid_str); /* string value to set */ + + if (stripe_sz > 1024) + sprintf(stripe_str,"%d M",stripe_sz/1024); + else + sprintf(stripe_str,"%d k",stripe_sz); + + set_field_buffer(p_input_fields[2], /* field to alter */ + 0, /* number of buffer to alter */ + stripe_str); /* string value to set */ + + refresh(); + ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (ch == 'c') + { + p_cur_field = current_field(p_form); + cur_field_index = field_index(p_cur_field); + + if (cur_field_index == 1) + { + /* count the number of valid entries */ + index = 0; + while (prot_level_list[index].is_valid_entry) + { + index++; + } + + /* get appropriate memory, the text portion needs to be + done up front as the new_item() function uses the + passed pointer to display data */ + raid_item = realloc(raid_item, sizeof(ITEM **) * (index + 1)); + raid_menu_str = realloc(raid_menu_str, sizeof(struct text_str) * (index)); + userptr = realloc(userptr, sizeof(int) * (index + 1)); + + /* set up protection level menu */ + index = 0; + while (prot_level_list[index].is_valid_entry) + { + raid_item[index] = (ITEM *)NULL; + sprintf(raid_menu_str[index].line,"RAID %s",prot_level_list[index].p_array_cap_entry->prot_level_str); + raid_item[index] = new_item(raid_menu_str[index].line,""); + userptr[index] = index; + set_item_userptr(raid_item[index], + (char *)&userptr[index]); + index++; + } + raid_item[index] = (ITEM *)NULL; + start_row = 8; + rc = display_menu(raid_item, start_row, index, &retptr); + if (rc == RC_SUCCESS) + { + raid_index = *retptr; + + /* find recommended stripe size */ + p_cur_array_cap_entry = prot_level_list[raid_index].p_array_cap_entry; + stripe_sz = sistoh16(p_cur_array_cap_entry->recommended_stripe_size); + } + } + else if (cur_field_index == 2) + { + /* count the number of valid entries */ + index = 0; + for (i=0; i<16; i++) + { + stripe_sz_mask = 1 << i; + if ((stripe_sz_mask & sistoh16(p_cur_array_cap_entry->supported_stripe_sizes)) + == stripe_sz_mask) + { + index++; + } + } + + /* get appropriate memory, the text portion needs to be + done up front as the new_item() function uses the + passed pointer to display data */ + raid_item = realloc(raid_item, sizeof(ITEM **) * (index + 1)); + stripe_menu_str = realloc(stripe_menu_str, sizeof(struct text_str) * (index)); + userptr = realloc(userptr, sizeof(int) * (index + 1)); + + /* set up stripe size menu */ + index = 0; + for (i=0; i<16; i++) + { + stripe_sz_mask = 1 << i; + raid_item[index] = (ITEM *)NULL; + if ((stripe_sz_mask & sistoh16(p_cur_array_cap_entry->supported_stripe_sizes)) + == stripe_sz_mask) + { + stripe_sz_list[index] = stripe_sz_mask; + if (stripe_sz_mask > 1024) + sprintf(stripe_menu_str[index].line,"%d M",stripe_sz_mask/1024); + else + sprintf(stripe_menu_str[index].line,"%d k",stripe_sz_mask); + + if (stripe_sz_mask == sistoh16(p_cur_array_cap_entry->recommended_stripe_size)) + { + sprintf(buffer,"%s - recommend",stripe_menu_str[index].line); + raid_item[index] = new_item(buffer, ""); + } + else + { + raid_item[index] = new_item(stripe_menu_str[index].line, ""); + } + userptr[index] = index; + set_item_userptr(raid_item[index], + (char *)&userptr[index]); + index++; + } + } + raid_item[index] = (ITEM *)NULL; + start_row = 9; + rc = display_menu(raid_item, start_row, index, &retptr); + if (rc == RC_SUCCESS) + { + stripe_sz = stripe_sz_list[*retptr]; + } + } + else + continue; + + i=0; + while (raid_item[i] != NULL) + free_item(raid_item[i++]); + realloc(raid_item, 0); + raid_item = NULL; + + if (rc == RC_EXIT) + goto leave; + } + else if (IS_ENTER_KEY(ch)) + { + /* set protection level and stripe size appropriately */ + p_cur_raid_cmd->prot_level = p_cur_array_cap_entry->prot_level; + p_cur_raid_cmd->stripe_size = stripe_sz; + goto leave; + } + else if (ch == KEY_RIGHT) + form_driver(p_form, REQ_NEXT_CHAR); + else if (ch == KEY_LEFT) + form_driver(p_form, REQ_PREV_CHAR); + else if ((ch == KEY_BACKSPACE) || (ch == 127)) + form_driver(p_form, REQ_DEL_PREV); + else if (ch == KEY_DC) + form_driver(p_form, REQ_DEL_CHAR); + else if (ch == KEY_IC) + form_driver(p_form, REQ_INS_MODE); + else if (ch == KEY_EIC) + form_driver(p_form, REQ_OVL_MODE); + else if (ch == KEY_HOME) + form_driver(p_form, REQ_BEG_FIELD); + else if (ch == KEY_END) + form_driver(p_form, REQ_END_FIELD); + else if (ch == '\t') + form_driver(p_form, REQ_NEXT_FIELD); + else if (ch == KEY_UP) + form_driver(p_form, REQ_PREV_FIELD); + else if (ch == KEY_DOWN) + form_driver(p_form, REQ_NEXT_FIELD); + else if (isascii(ch)) + form_driver(p_form, ch); + } + leave: + + free_form(p_form); + free_screen(NULL, NULL, p_input_fields); + curses_info.p_form = p_old_form; + + flush_stdscr(); + return rc; +} + +int continue_raid_start(struct sis_ioa *p_cur_ioa) +{ +#define CONT_START_HDR_SIZE 10 +#define CONT_START_MENU_SIZE 3 +/* iSeries + Additional Devices For Parity Protection + +Choose to Add more parity sets to this resource or to +Continue with the current configurations + +Press a=Add more parity sets to this resource +Press c=Continue + + Parity Serial Resource + Set Number Type Model Name + 1 02127005 5703 001 /dev/ibmsis1 + 1 000BBBC1 6717 050 + + + +a=Add c=Continue +q=Cancel f=PageDn b=PageUp + +*/ +/* non-iSeries + Additional Devices For Parity Protection + +Choose to Add more parity sets to this resource or to +Continue with the current configurations + +Press a=Add more parity sets to this resource +Press c=Continue + + Parity Vendor Product Serial Resource + Set ID ID Number Model Name + 1 IBM DAB61C0E 3AFB348C 200 /dev/sdb + 1 IBMAS400 DCHS09W 0024A0B9 070 + 1 IBMAS400 DFHSS4W 00D37A11 070 + + +a=Add c=Continue +q=Cancel f=PageDn b=PageUp + +*/ + + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + struct ibmsis_resource_entry *p_resource_entry; + struct array_cmd_data *p_cur_raid_cmd; + struct ibmsis_resource_flags *p_resource_flags; + int rc, j; + u16 len = 0; + char buffer[100]; + u32 num_lines = 0; + int max_size = curses_info.max_y - (CONT_START_HDR_SIZE + CONT_START_MENU_SIZE + 1); + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel, *p_cur_panel; + WINDOW *p_title_win, *p_menu_win; + PANEL *p_panel; + struct ibmsis_array_record *p_array_record; + struct ibmsis_device_record *p_device_record; + struct ibmsis_array_query_data *p_qac_data_tmp; + struct sis_device *p_sis_device; + + p_title_win = newwin(CONT_START_HDR_SIZE, + curses_info.max_x, + curses_info.start_y, + curses_info.start_x); + + p_menu_win = newwin(CONT_START_MENU_SIZE, + curses_info.max_x, + curses_info.start_y + max_size + CONT_START_HDR_SIZE + 1, + curses_info.start_x); + + rc = RC_SUCCESS; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Additional Devices For Parity Protection"); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONT_START_HDR_SIZE, + curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + mvwaddstr(p_title_win, 2, 0, "Choose to Add more parity sets to this resource or to"); + mvwaddstr(p_title_win, 3, 0, "Continue with the current configurations"); + mvwaddstr(p_title_win, 5, 0, "Press a=Add more parity sets to this resource"); + mvwaddstr(p_title_win, 6, 0, "Press c=Continue"); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 8, 0, " Parity Serial Resource"); + mvwaddstr(p_title_win, 9, 0, " Set Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 8, 0, " Parity Vendor Product Serial Resource"); + mvwaddstr(p_title_win, 9, 0, " Set ID ID Number Model Name"); + } + mvwaddstr(p_menu_win, 0, 0, "a=Add c=Continue"); + mvwaddstr(p_menu_win, 1, 0, CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_cur_raid_cmd = p_head_raid_cmd; + + p_qac_data_tmp = malloc(sizeof(struct ibmsis_array_query_data)); + memcpy(p_qac_data_tmp, + p_cur_ioa->p_qac_data, + sizeof(struct ibmsis_array_query_data)); + + while(p_cur_raid_cmd) + { + if ((p_cur_raid_cmd->do_cmd) && + (p_cur_ioa == p_cur_raid_cmd->p_sis_ioa)) + { + p_sis_device = p_cur_raid_cmd->p_sis_device; + + p_array_record = (struct ibmsis_array_record *)p_sis_device->p_qac_entry; + + /* swap in this raid cmd's image of qac data */ + memcpy(p_cur_ioa->p_qac_data, + p_cur_raid_cmd->p_qac_data, + sizeof(struct ibmsis_array_query_data)); + + if (platform == SIS_ISERIES) + { + /* Print out "array entry" */ + len = sprintf(buffer, " %4d %8s %x 001 %s", + p_cur_raid_cmd->array_num, p_cur_ioa->serial_num, + p_cur_ioa->ccin, p_cur_ioa->ioa.dev_name); + } + else + { + char buf[100]; + + /* Print out "array entry" */ + len = sprintf(buffer, " %4d ", p_cur_raid_cmd->array_num); + + memcpy(buf, p_sis_device->p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-8s ", buf); + + memcpy(buf, p_sis_device->p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s %03d %s", + p_sis_device->p_resource_entry->serial_num, + p_sis_device->p_resource_entry->model, + p_sis_device->dev_name); + } + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONT_START_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + p_device_record = (struct ibmsis_device_record *)p_cur_ioa->dev[j].p_qac_entry; + + if ((p_device_record != NULL) && + (p_device_record->common.record_id == IBMSIS_RECORD_ID_DEVICE2_RECORD) && + (p_device_record->issue_cmd)) + { + p_resource_flags = &p_device_record->resource_flags_to_become; + len = sprintf(buffer, " %4d ", p_cur_raid_cmd->array_num); + + if (platform == SIS_ISERIES) + { + print_dev2(p_resource_entry, buffer + len, p_resource_flags, p_cur_ioa->dev[j].dev_name); + } + else + { + char buf[100]; + + memcpy(buf, p_cur_ioa->dev[j].p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(buffer + len, " %-8s ", buf); + + memcpy(buf, p_cur_ioa->dev[j].p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s %03d %s", + p_resource_entry->serial_num, + p_resource_entry->model, + p_cur_ioa->dev[j].dev_name); + } + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONT_START_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + } + } + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + + p_cur_panel = p_head_panel; + + while(p_cur_panel) + { + bottom_panel(p_cur_panel->p_panel); + p_cur_panel = p_cur_panel->p_next; + } + + while(1) + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_ENTER_KEY(ch)) + { + break; + } + else if (IS_PGDN_KEY(ch)) + { + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if ((ch == 'a') || + (ch == 'A')) + { + rc = RC_SUCCESS; + goto leave; + } + else if ((ch == 'c') || + (ch == 'C')) + { + rc = RC_NOOP; + goto leave; + } + else + { + break; + } + } + } + + leave: + + /* restore unmodified image of qac data */ + memcpy(p_cur_ioa->p_qac_data, + p_qac_data_tmp, + sizeof(struct ibmsis_array_query_data)); + free(p_qac_data_tmp); + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + + +int confirm_raid_start() +{ +#define CONFIRM_START_HDR_SIZE 10 +#define CONFIRM_START_MENU_SIZE 3 +/* iSeries + Confirm Start Device Parity Protection + +ATTENTION: Data will not be preserved and may be lost on selected disk +units when parity protection is enabled. + +Press Enter to continue. +Press q=Cancel to return and change your choice. + + Parity Serial Resource +Option Set Number Type Model Name + 1 1 02127005 5703 001 /dev/ibmsis1 + 1 1 0024B45C 6713 050 + 1 1 002443C6 6713 050 + 1 1 00C02D9E 6719 050 + 1 1 0004C93D 6607 050 + +q=Cancel f=PageDn b=PageUp +*/ +/* non-iSeries + Confirm Start Device Parity Protection + +ATTENTION: Data will not be preserved and may be lost on selected disk +units when parity protection is enabled. + +Press Enter to continue. +Press q=Cancel to return and change your choice. + + Parity Vendor Product Serial Resource +Option Set ID ID Number Model Name + 1 1 IBM DAB61C0E 3AFB348C 200 /dev/sdb + 1 1 IBMAS400 DCHS09W 0024A0B9 070 + 1 1 IBMAS400 DFHSS4W 00D37A11 070 + +q=Cancel f=PageDn b=PageUp +*/ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + struct ibmsis_resource_entry *p_resource_entry; + struct array_cmd_data *p_cur_raid_cmd; + struct ibmsis_resource_flags *p_resource_flags; + struct sis_ioa *p_cur_ioa; + int rc, i, j, fd; + u16 len = 0; + char buffer[100]; + u32 num_lines = 0; + int max_size = curses_info.max_y - (CONFIRM_START_HDR_SIZE + CONFIRM_START_MENU_SIZE + 1); + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel, *p_cur_panel; + WINDOW *p_title_win, *p_menu_win; + PANEL *p_panel; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_array_record *p_array_record; + struct ibmsis_record_common *p_common_record_saved; + struct ibmsis_record_common *p_common_record; + struct ibmsis_device_record *p_device_record_saved; + struct ibmsis_device_record *p_device_record; + struct sis_device *p_sis_device; + int found; + int raid_start_complete(); + + p_title_win = newwin(CONFIRM_START_HDR_SIZE, + curses_info.max_x, + curses_info.start_y, + curses_info.start_x); + + p_menu_win = newwin(CONFIRM_START_MENU_SIZE, + curses_info.max_x, + curses_info.start_y + max_size + CONFIRM_START_HDR_SIZE + 1, + curses_info.start_x); + + rc = RC_SUCCESS; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Confirm Start Device Parity Protection"); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_START_HDR_SIZE, + curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + wattron(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 2, 0, "ATTENTION:"); + wattroff(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 2, 10, " All listed device units will be configured for parity"); + mvwaddstr(p_title_win, 3, 0, "protection, existing data will not be preserved."); + mvwaddstr(p_title_win, 5, 0, "Press Enter to continue."); + mvwaddstr(p_title_win, 6, 0, "Press "CANCEL_KEY_LABEL"=Cancel to return and change your choice."); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 8, 0, " Parity Serial Resource"); + mvwaddstr(p_title_win, 9, 0, "Option Set Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 8, 0, " Parity Vendor Product Serial Resource"); + mvwaddstr(p_title_win, 9, 0, "Option Set ID ID Number Model Name"); + } + + mvwaddstr(p_menu_win, 1, 0, CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_cur_raid_cmd = p_head_raid_cmd; + + while(p_cur_raid_cmd) + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + + p_sis_device = p_cur_raid_cmd->p_sis_device; + + p_array_record = (struct ibmsis_array_record *)p_sis_device->p_qac_entry; + + if (p_array_record->common.record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + /* swap in this raid cmd's image of qac data */ + memcpy(p_cur_ioa->p_qac_data, + p_cur_raid_cmd->p_qac_data, + sizeof(struct ibmsis_array_query_data)); + } + + if (platform == SIS_ISERIES) + { + /* Print out "array entry" */ + len = sprintf(buffer, " 1 %4d %8s %x 001 %s", + p_cur_raid_cmd->array_num, p_cur_ioa->serial_num, + p_cur_ioa->ccin, p_cur_ioa->ioa.dev_name); + } + else + { + char buf[100]; + + /* Print out "array entry" */ + len = sprintf(buffer, " 1 %4d ", p_cur_raid_cmd->array_num); + + memcpy(buf, p_sis_device->p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-8s ", buf); + + memcpy(buf, p_sis_device->p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s %03d %s", + p_sis_device->p_resource_entry->serial_num, + p_sis_device->p_resource_entry->model, + p_sis_device->dev_name); + } + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_START_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + p_device_record = (struct ibmsis_device_record *)p_cur_ioa->dev[j].p_qac_entry; + + if ((p_device_record != NULL) && + (((p_device_record->common.record_id == IBMSIS_RECORD_ID_DEVICE_RECORD) && + (p_device_record->array_id == p_cur_raid_cmd->array_id) && + (p_device_record->start_cand)) || + ((p_device_record->common.record_id == IBMSIS_RECORD_ID_DEVICE2_RECORD) && + (p_device_record->issue_cmd)))) + { + p_resource_flags = &p_device_record->resource_flags_to_become; + len = sprintf(buffer, " 1 %4d ", p_cur_raid_cmd->array_num); + + if (platform == SIS_ISERIES) + { + print_dev2(p_resource_entry, buffer + len, + p_resource_flags, p_cur_ioa->dev[j].dev_name); + } + else + { + char buf[100]; + + memcpy(buf, p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(buffer + len, " %-8s ", buf); + + memcpy(buf, p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s %03d %s", + p_resource_entry->serial_num, + p_resource_entry->model, + p_cur_ioa->dev[j].dev_name); + } + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_START_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + } + } + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + + p_cur_panel = p_head_panel; + + while(p_cur_panel) + { + bottom_panel(p_cur_panel->p_panel); + p_cur_panel = p_cur_panel->p_next; + } + + while(1) + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_REFRESH; + goto leave; + } + else if (IS_ENTER_KEY(ch)) + { + /* verify the devices are not in use */ + p_cur_raid_cmd = p_head_raid_cmd; + while (p_cur_raid_cmd) + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + rc = is_array_in_use(p_cur_ioa, p_cur_raid_cmd->array_id); + if (rc != 0) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Devices may have changed state. Command cancelled," + " please issue commands again if RAID still desired %s." + IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + goto leave; + } + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + werase(stdscr); + + /* now issue the start array command */ + for (p_cur_raid_cmd = p_head_raid_cmd; + p_cur_raid_cmd != NULL; + p_cur_raid_cmd = p_cur_raid_cmd->p_next) + { + if (p_cur_raid_cmd->do_cmd == 0) + continue; + + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + + if (p_cur_ioa->num_raid_cmds > 0) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + syslog(LOG_ERR, + "Could not open %s. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + continue; + } + + p_array_record = (struct ibmsis_array_record *) + p_cur_raid_cmd->p_sis_device->p_qac_entry; + + if (p_array_record->common.record_id == + IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + /* refresh qac data for ARRAY2 */ + memset(&ioa_cmd, 0, + sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_ioa->p_qac_data; + ioa_cmd.buffer_len = sizeof(struct ibmsis_array_query_data); + ioa_cmd.cdb[1] = 0x80; /* Prohibit Rebuild Candidate Refresh */ + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_QUERY_ARRAY_CONFIG, &ioa_cmd); + + if (rc != 0) + { + if (errno != EINVAL) + syslog(LOG_ERR,"Query Array Config to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + close(fd); + continue; + } + + /* scan through this raid command to determine which + devices should be part of this parity set */ + p_common_record_saved = (struct ibmsis_record_common *) + p_cur_raid_cmd->p_qac_data->data; + for (i = 0; i < p_cur_raid_cmd->p_qac_data->num_records; i++) + { + p_device_record_saved = (struct ibmsis_device_record *)p_common_record_saved; + if (p_device_record_saved->issue_cmd) + { + p_common_record = (struct ibmsis_record_common *) + p_cur_ioa->p_qac_data->data; + found = 0; + for (j = 0; j < p_cur_ioa->p_qac_data->num_records; j++) + { + p_device_record = (struct ibmsis_device_record *)p_common_record; + if (p_device_record->resource_handle == + p_device_record_saved->resource_handle) + { + p_device_record->issue_cmd = 1; + found = 1; + break; + } + p_common_record = (struct ibmsis_record_common *) + ((unsigned long)p_common_record + + sistoh16(p_common_record->record_len)); + } + if (!found) + { + syslog(LOG_ERR, + "Resource not found to start parity protection to %s" + "failed"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + break; + } + } + p_common_record_saved = (struct ibmsis_record_common *) + ((unsigned long)p_common_record_saved + + sistoh16(p_common_record_saved->record_len)); + } + + if (!found) + { + close(fd); + continue; + } + + p_array_record->issue_cmd = 1; + p_cur_raid_cmd->array_id = p_array_record->array_id; + } + else + { + if (p_cur_ioa->num_raid_cmds > 1) + { + /* need to only issue one start for this + adapter, only send start for the last + listed array, which contains data for + all arrays. A positive value of num_raid_cmds + must be maintained for status screen */ + p_cur_ioa->num_raid_cmds--; + continue; + } + } + + memset(&ioa_cmd, 0, + sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_ioa->p_qac_data; + ioa_cmd.buffer_len = sistoh16(p_cur_ioa->p_qac_data->resp_len); + ioa_cmd.cdb[4] = (u8)(p_cur_raid_cmd->stripe_size >> 8); + ioa_cmd.cdb[5] = (u8)(p_cur_raid_cmd->stripe_size); + ioa_cmd.cdb[6] = p_cur_raid_cmd->prot_level; + rc = sis_ioctl(fd, IBMSIS_START_ARRAY_PROTECTION, &ioa_cmd); + + close(fd); + if (rc != 0) + { + syslog(LOG_ERR, "Start Array Protection to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + } + } + } + + rc = raid_start_complete(); + return rc; + } + else if (IS_PGDN_KEY(ch)) + { + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else + { + break; + } + } + + } + + leave: + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + +int raid_start_complete() +{ + /* + Start Device Parity Protection Status + + You selected to start device parity protection + + + + + + + + + + 16% Complete + + + + + + + + + + + + */ + + FIELD *p_fields[3]; + FORM *p_form; + FORM *p_old_form; + struct ibmsis_cmd_status cmd_status; + struct ibmsis_cmd_status_record *p_record; + int done_bad; + int not_done = 0; + int rc, j; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + u32 percent_cmplt = 0; + struct sis_ioa *p_cur_ioa; + u32 num_starts = 0; + struct array_cmd_data *p_cur_raid_cmd; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + curses_info.max_y - 1, curses_info.max_x - 1, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Start Device Parity Protection Status"); + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + while(1) + { + clear(); + post_form(p_form); + + mvaddstr(2, 0, "You selected to start device parity protection"); + mvprintw(curses_info.max_y / 2, (curses_info.max_x / 2) - 7, "%d%% Complete", percent_cmplt); + + form_driver(p_form, + REQ_FIRST_FIELD); + refresh(); + + percent_cmplt = 100; + done_bad = 0; + num_starts = 0; + not_done = 0; + + for (p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + if (p_cur_ioa->num_raid_cmds > 0) + { + int fd = open(p_cur_ioa->ioa.dev_name, O_RDONLY); + + if (fd < 0) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + p_cur_ioa->num_raid_cmds = 0; + done_bad = 1; + continue; + } + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &cmd_status; + ioa_cmd.buffer_len = sizeof(cmd_status); + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_QUERY_COMMAND_STATUS, &ioa_cmd); + + if (rc) + { + syslog(LOG_ERR, "Query Command Status to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + close(fd); + p_cur_ioa->num_raid_cmds = 0; + done_bad = 1; + continue; + } + + close(fd); + p_record = cmd_status.record; + + for (j=0; j < cmd_status.num_records; j++, p_record++) + { + if (p_record->command_code == IBMSIS_START_ARRAY_PROTECTION) + { + for (p_cur_raid_cmd = p_head_raid_cmd; + p_cur_raid_cmd != NULL; + p_cur_raid_cmd = p_cur_raid_cmd->p_next) + { + if ((p_cur_raid_cmd->p_sis_ioa == p_cur_ioa) && + (p_cur_raid_cmd->array_id == p_record->array_id)) + { + num_starts++; + if (p_record->status == IBMSIS_CMD_STATUS_IN_PROGRESS) + { + if (p_record->percent_complete < percent_cmplt) + percent_cmplt = p_record->percent_complete; + not_done = 1; + } + else if (p_record->status != IBMSIS_CMD_STATUS_SUCCESSFUL) + { + done_bad = 1; + syslog(LOG_ERR, "Start parity protect to %s failed. " + "Check device configuration for proper format."IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + rc = RC_FAILED; + } + break; + } + } + } + } + } + } + + unpost_form(p_form); + + if (!not_done) + { + free_form(p_form); + curses_info.p_form = p_old_form; + for (j=0; j < 2; j++) + free_field(p_fields[j]); + + if (done_bad) + { + flush_stdscr(); + return RC_FAILED; + } + + check_current_config(false); + + revalidate_devs(NULL); + flush_stdscr(); + return RC_SUCCESS; + } + not_done = 0; + sleep(2); + } +} + +int raid_rebuild() +{ + /* iSeries + Rebuild Disk Unit Data + + Select the units to be rebuilt + + Type choice, press Enter. + 1=Rebuild + + Parity Serial Resource + Option Set Number Type Model Name + 1 00058B10 6717 050 /dev/sda + 2 000585F1 6717 050 /dev/sdj + + + e=Exit q=Cancel + + */ + +/* non-iSeries + Rebuild Disk Unit Data + +Type option, press Enter. + 1=Select + + Vendor Product Serial PCI PCI SCSI SCSI SCSI +OPT ID ID Number Bus Dev Bus ID Lun + IBM DFHSS4W 0024A0B9 05 03 0 3 0 + + +e=Exit q=Cancel + +*/ + int rc, i, array_num, last_char; + struct ibmsis_record_common *p_common_record; + struct ibmsis_device_record *p_device_record; + struct array_cmd_data *p_cur_raid_cmd; + struct ibmsis_resource_entry *p_resource_entry; + u8 array_id; + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + char buffer[100]; + int array_index; + int max_size = curses_info.max_y - 12; + int confirm_raid_rebuild(); + int num_lines = 0; + struct sis_ioa *p_cur_ioa; + u32 len = 0; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + int found = 0; + char *p_char; + + rc = RC_SUCCESS; + + p_title_win = newwin(9, curses_info.max_x, 0, 0); + p_menu_win = newwin(3, curses_info.max_x, max_size + 9, 0); + p_field_win = newwin(max_size, curses_info.max_x, 9, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Rebuild Disk Unit Data"); /* string value to set */ + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + array_num = 1; + + check_current_config(true); + + for(p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + p_cur_ioa->num_raid_cmds = 0; + + for (i = 0; + i < p_cur_ioa->num_devices; + i++) + { + p_common_record = p_cur_ioa->dev[i].p_qac_entry; + + if ((p_common_record != NULL) && + ((p_common_record->record_id == IBMSIS_RECORD_ID_DEVICE_RECORD) || + (p_common_record->record_id == IBMSIS_RECORD_ID_DEVICE2_RECORD))) + { + p_device_record = (struct ibmsis_device_record *)p_common_record; + + if (p_device_record->rebuild_cand) + { + /* now find matching resource to display device data */ + p_resource_entry = p_cur_ioa->dev[i].p_resource_entry; + + if (p_head_raid_cmd) + { + p_tail_raid_cmd->p_next = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + p_tail_raid_cmd = p_tail_raid_cmd->p_next; + } + else + { + p_head_raid_cmd = p_tail_raid_cmd = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + } + + p_tail_raid_cmd->p_next = NULL; + + memset(p_tail_raid_cmd, 0, sizeof(struct array_cmd_data)); + + array_id = p_device_record->array_id; + + p_tail_raid_cmd->array_id = array_id; + p_tail_raid_cmd->array_num = array_num; + p_tail_raid_cmd->p_sis_ioa = p_cur_ioa; + p_tail_raid_cmd->p_sis_device = &p_cur_ioa->dev[i]; + + start_y = (array_num-1) % (max_size - 1); + + if ((num_lines > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + + set_field_buffer(pp_field[field_index], 0, "More... "); + + set_field_userptr(pp_field[field_index], NULL); + + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 3, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)p_tail_raid_cmd); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 9, start_y, 9, 0, 0); + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, "%4d %8s %x %03d %-38s", + array_num, + p_resource_entry->serial_num, + p_resource_entry->type, + p_resource_entry->model, + p_cur_ioa->dev[i].dev_name); + } + else + { + len = print_dev_sel(p_resource_entry, buffer); + } + + set_field_buffer(pp_field[field_index], 0, buffer); + + field_opts_off(pp_field[field_index], O_ACTIVE); + + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + array_num++; + } + } + } + } + + if (array_num == 1) + { + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Rebuild Disk Unit Data Failed"); /* string value to set */ + + mvwaddstr(p_title_win, 2, 0, "There are no disk units eligible for the selected operation"); + mvwaddstr(p_title_win, 3, 0, "due to one or more of the following reasons:"); + mvwaddstr(p_title_win, 5, 0, "o There are no disk units that need to be rebuilt."); + mvwaddstr(p_title_win, 6, 0, "o The disk unit that needs to be rebuilt is not at the right"); + mvwaddstr(p_title_win, 7, 0, " location. Examine the 'message log' for the exposed unit"); + mvwaddstr(p_title_win, 8, 0, " and make sure that the replacement unit is at the correct"); + mvwaddstr(p_field_win, 0, 0, " location"); + mvwaddstr(p_field_win, 1, 0, "o Not all disk units attached to an IOA have reported to the"); + mvwaddstr(p_field_win, 2, 0, " system. Retry the operation."); + mvwaddstr(p_field_win, 3, 0, "o All the disk units in a parity set must be the same capacity"); + mvwaddstr(p_field_win, 4, 0, " with a minumum number of 4 disk units and a maximum of 10 units"); + mvwaddstr(p_field_win, 5, 0, " in the resulting parity set"); + mvwaddstr(p_field_win, 6, 0, "o The type/model of the disk units is not supported for the"); + mvwaddstr(p_field_win, 7, 0, " requested operation"); + mvwaddstr(p_field_win, max_size -1, 0, "Press Enter to continue."); + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD); /* form request code */ + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + } + } + + mvwaddstr(p_title_win, 2, 0, "Select the units to be rebuilt"); + mvwaddstr(p_title_win, 4, 0, "Type choice, press Enter."); + mvwaddstr(p_title_win, 5, 0, " 1=Rebuild"); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 7, 0, " Parity Serial Resource"); + mvwaddstr(p_title_win, 8, 0, "Option Set Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 7, 0, " Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 8, 0, "Option ID ID Number Bus Dev Bus ID Lun"); + } + + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + + field_opts_off(p_fields[1], O_ACTIVE); + + array_index = ((max_size - 1) * 2) + 1; + for (i = array_index; i < field_index; i += array_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + flush_stdscr(); + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + + while(1) + { + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (IS_PGUP_KEY(ch)) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if ((ch == KEY_DOWN) || + (ch == '\t')) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_NEXT_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (ch == KEY_UP) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_PREV_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (IS_ENTER_KEY(ch)) + { + found = 0; + + unpost_form(p_list_form); + + for (i = 0; i < field_index; i++) + { + p_cur_raid_cmd = (struct array_cmd_data *)field_userptr(pp_field[i]); + if (p_cur_raid_cmd != NULL) + { + p_char = field_buffer(pp_field[i], 0); + + if (strcmp(p_char, "1") == 0) + { + found = 1; + p_cur_raid_cmd->do_cmd = 1; + + p_device_record = (struct ibmsis_device_record *)p_cur_raid_cmd->p_sis_device->p_qac_entry; + if (!p_device_record->issue_cmd) + { + p_device_record->issue_cmd = 1; + p_cur_raid_cmd->p_sis_ioa->num_raid_cmds++; + } + } + else + { + p_cur_raid_cmd->do_cmd = 0; + + p_device_record = (struct ibmsis_device_record *)p_cur_raid_cmd->p_sis_device->p_qac_entry; + if (p_device_record->issue_cmd) + { + p_device_record->issue_cmd = 0; + p_cur_raid_cmd->p_sis_ioa->num_raid_cmds--; + } + } + } + } + + if (found != 0) + { + /* Go to verification screen */ + unpost_form(p_form); + rc = confirm_raid_rebuild(); + goto leave; + } + else + { + post_form(p_list_form); + rc = 1; + } + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free(pp_field); + + p_cur_raid_cmd = p_head_raid_cmd; + while(p_cur_raid_cmd) + { + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + free(p_head_raid_cmd); + p_head_raid_cmd = p_cur_raid_cmd; + } + + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int confirm_raid_rebuild() +{ +#define CONFIRM_REBUILD_HDR_SIZE 10 +#define CONFIRM_REBUILD_MENU_SIZE 3 + /* iSeries + Confirm Rebuild Disk Unit Data + + Rebuilding the disk unit data may take several minutes for + each unit selected. + + Press Enter to confirm having the data rebuilt. + Press q=Cancel to return and change your choice. + + Parity Serial Resource + Option Set Number Type Model Name + 1 00058B10 6717 070 /dev/sda + 2 000585F1 6717 070 /dev/sdb + + q=Cancel + + */ +/* non-iSeries + Confirm Rebuild Disk Unit Data + +Rebuilding the disk unit data may take several minutes for +each unit selected. + +Press Enter to confirm having the data rebuilt. +Press q=Cancel to return and change your choice. + + Vendor Product Serial PCI PCI SCSI SCSI SCSI +Option ID ID Number Bus Dev Bus ID Lun + 1 IBM DFHSS4W 0024A0B9 05 03 0 3 0 + + q=Cancel + +*/ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct array_cmd_data *p_cur_raid_cmd; + struct ibmsis_device_record *p_device_record; + struct ibmsis_resource_flags *p_resource_flags; + struct sis_ioa *p_cur_ioa; + int fd, rc; + u16 len; + char buffer[100]; + u32 num_lines = 0; + int max_size = curses_info.max_y - (CONFIRM_REBUILD_HDR_SIZE + CONFIRM_REBUILD_MENU_SIZE + 1); + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel, *p_cur_panel; + WINDOW *p_title_win, *p_menu_win; + PANEL *p_panel; + + p_title_win = newwin(CONFIRM_REBUILD_HDR_SIZE, + curses_info.max_x, + curses_info.start_y, + curses_info.start_x); + + p_menu_win = newwin(CONFIRM_REBUILD_MENU_SIZE, + curses_info.max_x, + curses_info.start_y + max_size + CONFIRM_REBUILD_HDR_SIZE + 1, + curses_info.start_x); + + rc = RC_SUCCESS; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Confirm Rebuild Disk Unit Data"); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_REBUILD_HDR_SIZE, + curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + mvwaddstr(p_title_win, 2, 0, "Rebuilding the disk unit data may take several minutes for"); + mvwaddstr(p_title_win, 3, 0, "each unit selected."); + mvwaddstr(p_title_win, 5, 0, "Press Enter to confirm having the data rebuilt."); + mvwaddstr(p_title_win, 6, 0, "Press "CANCEL_KEY_LABEL"=Cancel to return and change your choice."); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 8, 0, " Parity Serial Resource"); + mvwaddstr(p_title_win, 9, 0, "Option Set Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 8, 0, + " Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 9, 0, + "Option ID ID Number Bus Dev Bus ID Lun"); + } + + mvwaddstr(p_menu_win, 1, 0, CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_cur_raid_cmd = p_head_raid_cmd; + + while(p_cur_raid_cmd) + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + p_device_record = (struct ibmsis_device_record *)p_cur_raid_cmd->p_sis_device->p_qac_entry; + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, " 1 %4d ", p_cur_raid_cmd->array_num); + p_resource_flags = &p_device_record->resource_flags_to_become; + len += print_dev2(p_cur_raid_cmd->p_sis_device->p_resource_entry, + buffer + len, + p_resource_flags, + p_cur_raid_cmd->p_sis_device->dev_name); + } + else + { + len = sprintf(buffer, " 1 "); + print_dev_sel(p_cur_raid_cmd->p_sis_device->p_resource_entry, buffer + len); + } + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_REBUILD_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + + p_cur_panel = p_head_panel; + + while(p_cur_panel) + { + bottom_panel(p_cur_panel->p_panel); + p_cur_panel = p_cur_panel->p_next; + } + + while(1) + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_REFRESH; + goto leave; + } + else if (IS_ENTER_KEY(ch)) + { + for (p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + if (p_cur_ioa->num_raid_cmds > 0) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + goto leave; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_ioa->p_qac_data; + ioa_cmd.buffer_len = sistoh16(p_cur_ioa->p_qac_data->resp_len); + ioa_cmd.read_not_write = 0; + + rc = sis_ioctl(fd, IBMSIS_REBUILD_DEVICE_DATA, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Rebuild Disk Unit Data to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + rc = RC_FAILED; + close(fd); + goto leave; + } + close(fd); + } + } + + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else + { + break; + } + } + + } + + leave: + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + +int raid_include() +{ +/* + Include Disk Units in Parity Protection + +Select the subsystem that the disk unit will be included. + +Type choice, press Enter. + 1=Select Parity Array to Include Disk Unit + + Parity Serial Resource +Option Set Number Type Model Name + 1 02127005 2782 001 /dev/ibmsis4 + 2 00103039 2748 001 /dev/ibmsis0 + +e=Exit q=Cancel f=PageDn b=PageUp + +*/ +/* non-iSeries + Include Disk Units in Parity Protection + +Select the subsystem that the disk unit will be included. + +Type choice, press Enter. + 1=Select Parity Array to Include Disk Unit + + Parity Vendor Product Serial Resource +Option Set ID ID Number Model Name + 1 IBM DAB61C0E 3AFB348C 200 /dev/sdb + 2 IBM 5C88AFDC A775915E 200 /dev/sdc + + +e=Exit q=Cancel f=PageDn b=PageUp +*/ + + int rc, i, j, array_num, last_char; + struct ibmsis_record_common *p_common_record; + struct ibmsis_array_record *p_array_record; + struct array_cmd_data *p_cur_raid_cmd; + u8 array_id; + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + char buffer[100]; + int array_index; + int max_size = curses_info.max_y - 12; + int confirm_raid_stop(); + int num_lines = 0; + struct sis_ioa *p_cur_ioa; + u32 len; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + int found = 0; + int include_allowed; + char *p_char; + struct ibmsis_array2_record *p_array2_record; + struct ibmsis_supported_arrays *p_supported_arrays; + struct ibmsis_array_cap_entry *p_cur_array_cap_entry; + int configure_raid_include(struct array_cmd_data *p_cur_raid_cmd); + int confirm_raid_include(); + + rc = RC_SUCCESS; + p_title_win = newwin(9, curses_info.max_x, 0, 0); + p_menu_win = newwin(3, curses_info.max_x, max_size + 9, 0); + p_field_win = newwin(max_size, curses_info.max_x, 9, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Include Disk Units in Parity Protection"); /* string value to set */ + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + array_num = 1; + + check_current_config(false); + + for(p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + p_cur_ioa->num_raid_cmds = 0; + + for (i = 0; + i < p_cur_ioa->num_devices; + i++) + { + p_common_record = p_cur_ioa->dev[i].p_qac_entry; + + if ((p_common_record != NULL) && + ((p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY_RECORD) || + (p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD))) + { + if (p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + p_array2_record = (struct ibmsis_array2_record *) + p_common_record; + + p_supported_arrays = p_cur_ioa->p_supported_arrays; + p_cur_array_cap_entry = + (struct ibmsis_array_cap_entry *)p_supported_arrays->data; + include_allowed = 0; + for (j = 0; + j < sistoh16(p_supported_arrays->num_entries); + j++) + { + if (p_cur_array_cap_entry->prot_level == + p_array2_record->raid_level) + { + if (p_cur_array_cap_entry->include_allowed) + include_allowed = 1; + break; + } + + p_cur_array_cap_entry = (struct ibmsis_array_cap_entry *) + ((void *)p_cur_array_cap_entry + + sistoh16(p_supported_arrays->entry_length)); + } + + if (!include_allowed) + continue; + } + + p_array_record = (struct ibmsis_array_record *)p_common_record; + + if (p_array_record->established) + { + if (p_head_raid_cmd) + { + p_tail_raid_cmd->p_next = + (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + p_tail_raid_cmd = p_tail_raid_cmd->p_next; + } + else + { + p_head_raid_cmd = p_tail_raid_cmd = + (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + } + + p_tail_raid_cmd->p_next = NULL; + + memset(p_tail_raid_cmd, 0, sizeof(struct array_cmd_data)); + + array_id = p_array_record->array_id; + + p_tail_raid_cmd->array_id = array_id; + p_tail_raid_cmd->array_num = array_num; + p_tail_raid_cmd->p_sis_ioa = p_cur_ioa; + p_tail_raid_cmd->p_sis_device = &p_cur_ioa->dev[i]; + p_tail_raid_cmd->p_qac_data = NULL; + + start_y = (array_num-1) % (max_size - 1); + + if ((num_lines > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 3, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)p_tail_raid_cmd); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 9, start_y, 9, 0, 0); + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, "%4d %8s %x %3d %s", + array_num, + p_cur_ioa->dev[i].p_resource_entry->serial_num, + p_cur_ioa->dev[i].p_resource_entry->type, + p_cur_ioa->ioa.p_resource_entry->model, + p_cur_ioa->dev[i].dev_name); + } + else + { + char buf[100]; + + len = sprintf(buffer, "%4d ", array_num); + + memcpy(buf, p_cur_ioa->dev[i].p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-8s ", buf); + + memcpy(buf, p_cur_ioa->dev[i].p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s %03d %s", + p_cur_ioa->dev[i].p_resource_entry->serial_num, + p_cur_ioa->dev[i].p_resource_entry->model, + p_cur_ioa->dev[i].dev_name); + } + + set_field_buffer(pp_field[field_index], 0, buffer); + field_opts_off(pp_field[field_index], O_ACTIVE); + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + array_num++; + } + } + } + } + + if (array_num == 1) + { + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Include Device Parity Protection Failed"); /* string value to set */ + + mvwaddstr(p_title_win, 2, 0, "There are no disk units eligible for the selected operation"); + mvwaddstr(p_title_win, 3, 0, "due to one or more of the following reasons:"); + mvwaddstr(p_title_win, 5, 0, "o There are no device parity protected units in the system."); + mvwaddstr(p_title_win, 6, 0, "o An IOA is in a condition that makes the disk units attached to"); + mvwaddstr(p_title_win, 7, 0, " it read/write protected. Examine the kernel messages log"); + mvwaddstr(p_title_win, 8, 0, " for any errors that are logged for the IO subsystem"); + mvwaddstr(p_field_win, 0, 0, " and follow the appropriate procedure for the reference code to"); + mvwaddstr(p_field_win, 1, 0, " correct the problem, if necessary."); + mvwaddstr(p_field_win, 2, 0, "o Not all disk units attached to an advanced function IOA have"); + mvwaddstr(p_field_win, 3, 0, " reported to the system. Retry the operation."); + mvwaddstr(p_field_win, 4, 0, "o The disk units are missing."); + mvwaddstr(p_field_win, 5, 0, "o The disk unit/s are currently in use."); + mvwaddstr(p_field_win, max_size -1, 0, "Press Enter to continue."); + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD); /* form request code */ + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + } + } + + mvwaddstr(p_title_win, 2, 0, "Select the subsystem that the disk unit will be included."); + mvwaddstr(p_title_win, 4, 0, "Type choice, press Enter."); + mvwaddstr(p_title_win, 5, 0, " 1=Select Parity Array to Include Disk Unit"); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 7, 0, " Parity Serial Resource"); + mvwaddstr(p_title_win, 8, 0, "Option Set Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 7, 0, " Parity Vendor Product Serial Resource"); + mvwaddstr(p_title_win, 8, 0, "Option Set ID ID Number Model Name"); + } + + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + + field_opts_off(p_fields[1], O_ACTIVE); + + array_index = ((max_size - 1) * 2) + 1; + for (i = array_index; i < field_index; i += array_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + flush_stdscr(); + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + + while(1) + { + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (IS_PGUP_KEY(ch)) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if ((ch == KEY_DOWN) || + (ch == '\t')) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_NEXT_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (ch == KEY_UP) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_PREV_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (IS_ENTER_KEY(ch)) + { + found = 0; + unpost_form(p_list_form); + + for (i = 0; i < field_index; i++) + { + p_cur_raid_cmd = (struct array_cmd_data *)field_userptr(pp_field[i]); + if (p_cur_raid_cmd != NULL) + { + p_char = field_buffer(pp_field[i], 0); + if (strcmp(p_char, "1") == 0) + { + rc = configure_raid_include(p_cur_raid_cmd); + if (rc == RC_CANCEL) + { + rc = RC_REFRESH; + goto leave; + } + if (rc == RC_EXIT) + goto leave; + found = 1; + break; + } + } + } + + if (found != 0) + { + /* Go to verification screen */ + unpost_form(p_form); + rc = confirm_raid_include(); + goto leave; + } + else + { + post_form(p_list_form); + rc = 1; + } + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free(pp_field); + + p_cur_raid_cmd = p_head_raid_cmd; + while(p_cur_raid_cmd) + { + if (p_cur_raid_cmd->p_qac_data) + { + free(p_cur_raid_cmd->p_qac_data); + p_cur_raid_cmd->p_qac_data = NULL; + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + free(p_head_raid_cmd); + p_head_raid_cmd = p_cur_raid_cmd; + } + + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int configure_raid_include(struct array_cmd_data *p_cur_raid_cmd) +{ +/* iSeries + Include Disk Units in Device Parity Protection + +Select the units to be included in Device Parity Protection + +Type choice, press Enter. + 1=Include unit in device parity protection + + Parity Serial Resource +Option Set Number Type Model Name + 1 000BBBC1 6717 050 + 2 0002F5AA 6717 050 + + +e=Exit q=Cancel f=PageDn b=PageUp +*/ + +/* non-iSeries + Include Disk Units in Device Parity Protection + +Select the units to be included in Device Parity Protection + +Type choice, press Enter. + 1=Include unit in device parity protection + + Vendor Product Serial PCI PCI SCSI SCSI SCSI +Option ID ID Number Bus Dev Bus ID Lun + IBMAS400 DGVS09U 00034563 05 03 0 6 0 + IBMAS400 DFHSS4W 00D32240 05 03 0 9 0 + + +e=Exit q=Cancel f=PageDn b=PageUp +*/ + int fd, rc, i, j, k, array_num, last_char; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_array_query_data *p_array_query_data; + struct ibmsis_record_common *p_common_record; + struct ibmsis_device_record *p_device_record; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_array2_record *p_array2_record; + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + char buffer[100]; + int array_index; + int max_size = curses_info.max_y - 12; + int num_lines = 0; + struct sis_ioa *p_cur_ioa; + u32 len = 0; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + int found = 0; + char *p_char; + struct sis_device *p_sis_device; + struct ibmsis_supported_arrays *p_supported_arrays; + struct ibmsis_array_cap_entry *p_cur_array_cap_entry; + u8 min_mult_array_devices = 1; + u8 raid_level; + char error_str[128]; + + rc = RC_SUCCESS; + + p_title_win = newwin(9, curses_info.max_x, 0, 0); + p_menu_win = newwin(3, curses_info.max_x, max_size + 9, 0); + p_field_win = newwin(max_size, curses_info.max_x, 9, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Include Disk Units in Device Parity Protection"); /* string value to set */ + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + array_num = 1; + + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + p_sis_device = p_cur_raid_cmd->p_sis_device; + p_common_record = p_sis_device->p_qac_entry; + + if (p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + /* save off raid level, this information will be used to find + minimum multiple */ + p_array2_record = (struct ibmsis_array2_record *)p_common_record; + raid_level = p_array2_record->raid_level; + + /* Get Query Array Config Data */ + p_array_query_data = (struct ibmsis_array_query_data *) + malloc(sizeof(struct ibmsis_array_query_data)); + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_array_query_data; + ioa_cmd.buffer_len = sizeof(struct ibmsis_array_query_data); + ioa_cmd.cdb[1] = 0x01; /* Volume Set Include */ + ioa_cmd.cdb[2] = p_cur_raid_cmd->array_id; + ioa_cmd.read_not_write = 1; + + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + rc = sis_ioctl(fd, IBMSIS_QUERY_ARRAY_CONFIG, &ioa_cmd); + close(fd); + + if (rc != 0) + { + if (errno != EINVAL) + { + syslog(LOG_ERR, "Query Array Config to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + } + free(p_array_query_data); + } + else + { + /* re-map the cross reference table with the new qac data */ + p_cur_raid_cmd->p_qac_data = p_array_query_data; + p_common_record = (struct ibmsis_record_common *)p_array_query_data->data; + for (k = 0; k < p_array_query_data->num_records; k++) + { + if (p_common_record->record_id == IBMSIS_RECORD_ID_DEVICE2_RECORD) + { + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + p_device_record = (struct ibmsis_device_record *)p_common_record; + if (p_resource_entry->resource_handle == + p_device_record->resource_handle) + { + p_cur_ioa->dev[j].p_qac_entry = p_common_record; + } + } + } + + /* find minimum multiple for the raid level being used */ + if (p_common_record->record_id == IBMSIS_RECORD_ID_SUPPORTED_ARRAYS) + { + p_supported_arrays = (struct ibmsis_supported_arrays *)p_common_record; + p_cur_array_cap_entry = (struct ibmsis_array_cap_entry *)p_supported_arrays->data; + + for (i=0; inum_entries); i++) + { + if (p_cur_array_cap_entry->prot_level == raid_level) + { + min_mult_array_devices = p_cur_array_cap_entry->min_mult_array_devices; + } + p_cur_array_cap_entry = (struct ibmsis_array_cap_entry *) + ((void *)p_cur_array_cap_entry + p_supported_arrays->entry_length); + } + } + p_common_record = (struct ibmsis_record_common *) + ((unsigned long)p_common_record + sistoh16(p_common_record->record_len)); + } + } + } + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_device_record = (struct ibmsis_device_record *)p_cur_ioa->dev[j].p_qac_entry; + + if (p_device_record == NULL) + continue; + + if (p_cur_ioa->dev[j].is_start_cand) + continue; + + if (p_device_record->include_cand) + { + if (p_cur_ioa->dev[j].opens != 0) + { + syslog(LOG_ERR,"Include Device not allowed, device in use - %s"IBMSIS_EOL, + p_cur_ioa->dev[j].dev_name); + continue; + } + + start_y = (array_num-1) % (max_size - 1); + + if ((num_lines > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 3, 0, 0); + set_field_userptr(pp_field[field_index++], (char *)&p_cur_ioa->dev[j]); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 9, start_y, 9, 0, 0); + + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, " %8s %x %03d %-38s", + p_resource_entry->serial_num, + p_resource_entry->type, + p_resource_entry->model, + p_cur_ioa->dev[j].dev_name); + } + else + { + len = print_dev_sel(p_resource_entry, buffer); + } + + set_field_buffer(pp_field[field_index], 0, buffer); + field_opts_off(pp_field[field_index], O_ACTIVE); + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + array_num++; + } + } + + if (array_num <= min_mult_array_devices) + { + p_sis_device = p_cur_raid_cmd->p_sis_device; + p_common_record = p_sis_device->p_qac_entry; + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Include Disk Unit Failed"); /* string value to set */ + + mvwaddstr(p_title_win, 2, 0, "There are no disk units eligible for the selected operation"); + mvwaddstr(p_title_win, 3, 0, "due to one or more of the following reasons:"); + mvwaddstr(p_title_win, 5, 0, "o There are not enough disk units available to be included."); + mvwaddstr(p_title_win, 6, 0, "o The disk unit that needs to be included is not at the right"); + mvwaddstr(p_title_win, 7, 0, " location. Examine the 'message log' for the exposed unit"); + mvwaddstr(p_title_win, 8, 0, " and make sure that the replacement unit is at the correct"); + mvwaddstr(p_field_win, 0, 0, " location"); + mvwaddstr(p_field_win, 1, 0, "o Not all disk units attached to an IOA have reported to the"); + mvwaddstr(p_field_win, 2, 0, " system. Retry the operation."); + if (p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + mvwaddstr(p_field_win, 3, 0, "o The disk unit to be included must be the same or greater"); + mvwaddstr(p_field_win, 4, 0, " capacity than the smallest device in the volume set and"); + mvwaddstr(p_field_win, 5, 0, " be formatted correctly"); + } + else + { + mvwaddstr(p_field_win, 3, 0, "o All the disk units in a parity set must be the same capacity"); + mvwaddstr(p_field_win, 4, 0, " with a minumum number of 4 disk units and a maximum of 10 units"); + mvwaddstr(p_field_win, 5, 0, " in the resulting parity set"); + } + mvwaddstr(p_field_win, 6, 0, "o The type/model of the disk units is not supported for the"); + mvwaddstr(p_field_win, 7, 0, " requested operation"); + mvwaddstr(p_field_win, max_size -1, 0, "Press Enter to continue."); + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD); /* form request code */ + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + } + } + + mvwaddstr(p_title_win, 2, 0, "Select the units to be included in Device Parity Protection"); + mvwaddstr(p_title_win, 4, 0, "Type choice, press Enter."); + mvwaddstr(p_title_win, 5, 0, " 1=Include unit in device parity protection"); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 7, 0, " Serial Resource"); + mvwaddstr(p_title_win, 8, 0, "Option Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 7, 0, + " Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 8, 0, + "Option ID ID Number Bus Dev Bus ID Lun"); + } + + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + + field_opts_off(p_fields[1], O_ACTIVE); + + array_index = ((max_size - 1) * 2) + 1; + for (i = array_index; i < field_index; i += array_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + flush_stdscr(); + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + + while(1) + { + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (IS_PGUP_KEY(ch)) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if ((ch == KEY_DOWN) || + (ch == '\t')) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_NEXT_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (ch == KEY_UP) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_PREV_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + else if (IS_ENTER_KEY(ch)) + { + /* first, count devices select to be sure min multiple + is satisfied */ + found = 0; + for (i = 0; i < field_index; i++) + { + p_char = field_buffer(pp_field[i], 0); + + if (strcmp(p_char, "1") == 0) + { + found++; + } + } + + if (found % min_mult_array_devices != 0) + { + sprintf(error_str,"Error: number of devices selected must be a multiple of %d",min_mult_array_devices); + mvwaddstr(p_menu_win, 2, 0, error_str); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + + wnoutrefresh(p_field_win); + doupdate(); + break; + } + + found = 0; + + unpost_form(p_list_form); + + for (i = 0; i < field_index; i++) + { + p_sis_device = (struct sis_device *)field_userptr(pp_field[i]); + if (p_sis_device != NULL) + { + p_char = field_buffer(pp_field[i], 0); + + if (strcmp(p_char, "1") == 0) + { + found = 1; + p_cur_raid_cmd->do_cmd = 1; + + p_device_record = (struct ibmsis_device_record *)p_sis_device->p_qac_entry; + if (!p_device_record->issue_cmd) + { + p_device_record->issue_cmd = 1; + p_device_record->known_zeroed = 1; + p_sis_device->is_start_cand = 1; + p_cur_raid_cmd->p_sis_ioa->num_raid_cmds++; + } + } + else + { + p_device_record = (struct ibmsis_device_record *)p_sis_device->p_qac_entry; + if (p_device_record->issue_cmd) + { + p_device_record->issue_cmd = 0; + p_device_record->known_zeroed = 0; + p_sis_device->is_start_cand = 0; + } + } + } + } + + if (found != 0) + { + /* Go to verification screen */ + unpost_form(p_form); + goto leave; + } + else + { + post_form(p_list_form); + rc = 1; + } + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + break; + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free(pp_field); + + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int confirm_raid_include() +{ +#define CONFIRM_INCLUDE_HDR_SIZE 11 +#define CONFIRM_INCLUDE_MENU_SIZE 3 +/* iSeries + Confirm Disk Units to be Included + +ATTENTION: All listed device units will be formatted and zeroed before +listed device is added to array. + +Press Enter to confirm your choice to have the system include +the selected units in device parity protection. +Press q=Cancel to return and change your choice. + + Parity Serial Resource +Option Set Number Type Model Name + 1 1 00058B10 6717 070 /dev/sda + 1 2 000585F1 6717 070 /dev/sdb + + +q=Cancel + +*/ +/* non-iSeries + Confirm Disk Units to be Included + +ATTENTION: All listed device units will be formatted and zeroed before +listed device is added to array. + +Press Enter to confirm your choice to have the system include +the selected units in device parity protection. +Press q=Cancel to return and change your choice. + +Parity Vendor Product Serial PCI PCI SCSI SCSI SCSI + Set ID ID Number Bus Dev Bus ID Lun + 1 IBMAS400 DGVS09U 00034563 05 03 0 6 0 + 1 IBMAS400 DFHSS4W 00D32240 05 03 0 9 0 + + +q=Cancel + +*/ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + struct ibmsis_resource_entry *p_resource_entry; + struct array_cmd_data *p_cur_raid_cmd; + struct ibmsis_device_record *p_device_record; + int rc, i, j, found; + u16 len; + char buffer[100]; + u32 num_lines = 0; + int max_size = curses_info.max_y - (CONFIRM_INCLUDE_HDR_SIZE + CONFIRM_INCLUDE_MENU_SIZE + 1); + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel, *p_cur_panel; + WINDOW *p_title_win, *p_menu_win; + PANEL *p_panel; + int confirm_raid_include_device(); + struct ibmsis_array_record *p_array_record; + struct ibmsis_array_query_data *p_qac_data; + struct ibmsis_record_common *p_common_record; + struct sis_ioa *p_cur_ioa; + + p_title_win = newwin(CONFIRM_INCLUDE_HDR_SIZE, + curses_info.max_x, + curses_info.start_y, + curses_info.start_x); + + p_menu_win = newwin(CONFIRM_INCLUDE_MENU_SIZE, + curses_info.max_x, + curses_info.start_y + max_size + CONFIRM_INCLUDE_HDR_SIZE + 1, + curses_info.start_x); + + rc = RC_SUCCESS; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Confirm Disk Units to be Included"); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_INCLUDE_HDR_SIZE, + curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + wattron(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 2, 0, "ATTENTION:"); + wattroff(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 2, 10, " All listed device units will be formatted and zeroed before"); + mvwaddstr(p_title_win, 3, 0, "listed device is added to array."); + mvwaddstr(p_title_win, 5, 0, "Press Enter to confirm your choice to have the system include"); + mvwaddstr(p_title_win, 6, 0, " the selected units in device parity protection"); + mvwaddstr(p_title_win, 7, 0, "Press "CANCEL_KEY_LABEL"=Cancel to return and change your choice."); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 9, 0, + " Parity Serial Resource"); + mvwaddstr(p_title_win,10, 0, + "Option Set Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 9, 0, + "Parity Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win,10, 0, + " Set ID ID Number Bus Dev Bus ID Lun"); + } + + mvwaddstr(p_menu_win, 1, 0, CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_cur_raid_cmd = p_head_raid_cmd; + + while(p_cur_raid_cmd) + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + + p_array_record = (struct ibmsis_array_record *) + p_cur_raid_cmd->p_sis_device->p_qac_entry; + + if (p_array_record->common.record_id == + IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + p_qac_data = p_cur_raid_cmd->p_qac_data; + } + else + { + p_qac_data = p_cur_ioa->p_qac_data; + } + + p_common_record = (struct ibmsis_record_common *) + p_qac_data->data; + + for (i = 0; i < p_qac_data->num_records; i++) + { + p_device_record = (struct ibmsis_device_record *)p_common_record; + if (p_device_record->issue_cmd) + { + found = 0; + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + + if (p_resource_entry->resource_handle == + p_device_record->resource_handle) + { + found = 1; + break; + } + } + + if (found) + { + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, " 1 %4d ", p_cur_raid_cmd->array_num); + + len += print_dev2(p_resource_entry, buffer + len, + &p_device_record->resource_flags_to_become, + p_cur_ioa->dev[j].dev_name); + } + else + { + char buf[100]; + + len = sprintf(buffer, " %4d ", p_cur_raid_cmd->array_num); + + memcpy(buf, p_resource_entry->std_inq_data.vpids.vendor_id, IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-8s ", buf); + + memcpy(buf, p_resource_entry->std_inq_data.vpids.product_id, IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s ", p_resource_entry->serial_num); + + len += sprintf(buffer + len, "%02d %02d %2d %2d %2d", + p_resource_entry->pci_bus_number, + p_resource_entry->pci_slot, + p_resource_entry->resource_address.bus, + p_resource_entry->resource_address.target, + p_resource_entry->resource_address.lun); + } + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_INCLUDE_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + } + } + + p_common_record = (struct ibmsis_record_common *) + ((unsigned long)p_common_record + + sistoh16(p_common_record->record_len)); + } + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + + p_cur_panel = p_head_panel; + + while(p_cur_panel) + { + bottom_panel(p_cur_panel->p_panel); + p_cur_panel = p_cur_panel->p_next; + } + + while(1) + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_REFRESH; + goto leave; + } + else if (IS_ENTER_KEY(ch)) + { + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + werase(stdscr); + rc = confirm_raid_include_device(); + + return rc; + } + else if (IS_PGDN_KEY(ch)) + { + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else + { + break; + } + } + + } + + leave: + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + +int confirm_raid_include_device() +{ +/* + Confirm Initialize and Format Disk Unit + +Press 'c' to confirm your choice for 1=Initialize and format. +Press q to return to change your choice. + + Vendor Product Serial PCI PCI SCSI SCSI SCSI +Option ID ID Number Bus Dev Bus ID Lun + IBM DFHSS4W 0024A0B9 05 03 0 3 0 + IBM DFHSS4W 00D38D0F 05 03 0 5 0 + IBM DFHSS4W 00D32240 05 03 0 9 0 + IBM DFHSS4W 00034563 05 03 0 6 0 + IBM DFHSS4W 00D37A11 05 03 0 4 0 + +c=Confirm q=Cancel f=PageDn b=PageUp + +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + Confirm Initialize and Format Disk Unit + +Press 'c' to confirm your choice for 1=Initialize and format. +Press q to return to change your choice. + + Serial Frame Card PCI PCI SCSI SCSI SCSI +Option Type Number ID Position Bus Dev Bus ID Lun + 6607 0024A0B9 03 D01 05 03 0 3 0 + 6607 00D38D0F 03 D02 05 03 0 5 0 + 6607 00D32240 03 D03 05 03 0 9 0 + 6607 00034563 03 D04 05 03 0 6 0 + 6717 00D37A11 03 D05 05 03 0 4 0 + +c=Confirm q=Cancel f=PageDn b=PageUp + + + +*/ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + char buffer[100]; + int max_size = curses_info.max_y - 10; + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel; + WINDOW *p_title_win, *p_menu_win; + struct array_cmd_data *p_cur_raid_cmd; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_device_record *p_device_record; + struct devs_to_init_t *p_cur_dev_to_init; + u32 len, i, j, found; + u32 num_lines = 0; + int rc = RC_SUCCESS; + PANEL *p_panel; + u8 num_devs=0; + struct sis_ioa *p_cur_ioa; + struct ibmsis_array_record *p_array_record; + struct ibmsis_array_query_data *p_qac_data; + struct ibmsis_record_common *p_common_record; + + int format_include_cand(); + int dev_include_complete(u8 num_devs); + + p_title_win = newwin(7, curses_info.max_x, + curses_info.start_y, curses_info.start_x); + + p_menu_win = newwin(3, curses_info.max_x, + curses_info.start_y + max_size + 7, curses_info.start_x); + + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Confirm Initialize and Format Disk Unit"); + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + + + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + 7, + curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + mvwaddstr(p_title_win, 2, 0, "Press 'c' to confirm your choice for 1=Initialize and format."); + mvwaddstr(p_title_win, 3, 0, "Press "CANCEL_KEY_LABEL" to return to change your choice."); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 5, 0, + " Serial Frame Card PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "Option Type Number ID Position Bus Dev Bus ID Lun"); + } + else + { + mvwaddstr(p_title_win, 5, 0, + " Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "Option ID ID Number Bus Dev Bus ID Lun"); + } + + mvwaddstr(p_menu_win, 1, 0, "c=Confirm "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_cur_raid_cmd = p_head_raid_cmd; + + while(p_cur_raid_cmd) + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + + p_array_record = (struct ibmsis_array_record *) + p_cur_raid_cmd->p_sis_device->p_qac_entry; + + if (p_array_record->common.record_id == + IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + p_qac_data = p_cur_raid_cmd->p_qac_data; + } + else + { + p_qac_data = p_cur_ioa->p_qac_data; + } + + p_common_record = (struct ibmsis_record_common *) + p_qac_data->data; + + for (i = 0; i < p_qac_data->num_records; i++) + { + p_device_record = (struct ibmsis_device_record *)p_common_record; + if (p_device_record->issue_cmd) + { + found = 0; + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + + if (p_resource_entry->resource_handle == + p_device_record->resource_handle) + { + found = 1; + break; + } + } + + if (found) + { + len = sprintf(buffer, " 1 "); + len += print_dev_sel(p_resource_entry, buffer + len); + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_INCLUDE_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + } + } + + p_common_record = (struct ibmsis_record_common *) + ((unsigned long)p_common_record + + sistoh16(p_common_record->record_len)); + } + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + + clear(); + flush_stdscr(); + form_driver(p_form, /* form to pass input to */ + REQ_FIRST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + while (1) + { + form_driver(p_form, /* form to pass input to */ + REQ_FIRST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_REFRESH; + goto leave; + } + else if ((ch == 'c') || (ch == 'C')) + { + /* now format each of the devices */ + num_devs = format_include_cand(); + + unpost_form(p_form); + rc = dev_include_complete(num_devs); + + /* free up memory allocated for format */ + p_cur_dev_to_init = p_head_dev_to_init; + while(p_cur_dev_to_init) + { + p_cur_dev_to_init = p_cur_dev_to_init->p_next; + free(p_head_dev_to_init); + p_head_dev_to_init = p_cur_dev_to_init; + } + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else + { + break; + } + } + } + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + +int format_include_cand() +{ + int fd, fdev, pid; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_resource_entry *p_resource_entry; + struct array_cmd_data *p_cur_raid_cmd; + struct sis_ioa *p_cur_ioa; + int num_devs = 0; + int rc = 0; + struct ibmsis_array_record *p_array_record; + struct ibmsis_array_query_data *p_qac_data; + struct ibmsis_record_common *p_common_record; + struct ibmsis_device_record *p_device_record; + int i, j, found, opens; + + p_cur_raid_cmd = p_head_raid_cmd; + while (p_cur_raid_cmd) + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + + p_array_record = (struct ibmsis_array_record *) + p_cur_raid_cmd->p_sis_device->p_qac_entry; + + if (p_array_record->common.record_id == + IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + p_qac_data = p_cur_raid_cmd->p_qac_data; + } + else + { + p_qac_data = p_cur_ioa->p_qac_data; + } + + p_common_record = (struct ibmsis_record_common *) + p_qac_data->data; + + for (i = 0; i < p_qac_data->num_records; i++) + { + p_device_record = (struct ibmsis_device_record *)p_common_record; + if (p_device_record->issue_cmd) + { + found = 0; + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + + if (p_resource_entry->resource_handle == + p_device_record->resource_handle) + { + found = 1; + break; + } + } + + if (found) + { + /* get current "opens" data for this device to determine conditions to continue */ + opens = num_device_opens(p_cur_ioa->host_num, + p_resource_entry->resource_address.bus, + p_resource_entry->resource_address.target, + p_resource_entry->resource_address.lun); + if (opens != 0) + { + syslog(LOG_ERR,"Include Device not allowed, device in use - %s"IBMSIS_EOL, + p_cur_ioa->dev[j].dev_name); + p_device_record->issue_cmd = 0; + continue; + } + + if (p_head_dev_to_init) + { + p_tail_dev_to_init->p_next = (struct devs_to_init_t *)malloc(sizeof(struct devs_to_init_t)); + p_tail_dev_to_init = p_tail_dev_to_init->p_next; + } + else + p_head_dev_to_init = p_tail_dev_to_init = (struct devs_to_init_t *)malloc(sizeof(struct devs_to_init_t)); + + memset(p_tail_dev_to_init, 0, sizeof(struct devs_to_init_t)); + p_tail_dev_to_init->p_ioa = p_cur_ioa; + p_tail_dev_to_init->p_sis_device = &p_cur_ioa->dev[j]; + p_tail_dev_to_init->do_init = 1; + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = NULL; + ioa_cmd.buffer_len = 0; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_resource_entry->resource_address; + + if (!p_tail_dev_to_init->p_sis_device->p_resource_entry->is_hidden) + { + fdev = open(p_tail_dev_to_init->p_sis_device->dev_name, O_RDWR | O_NONBLOCK); + + if (fdev) + { + fcntl(fdev, F_SETFD, 0); + if (flock(fdev, LOCK_EX)) + syslog(LOG_ERR, + "Could not set lock for %s. %m"IBMSIS_EOL, + p_tail_dev_to_init->p_sis_device->dev_name); + } + + p_tail_dev_to_init->fd = fdev; + } + + pid = fork(); + if (pid) + { + /* Do nothing */ + } + else + { + /* Issue the format. Failure will be detected by query command status */ + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + rc = sis_ioctl(fd, FORMAT_UNIT, &ioa_cmd); + close(fd); + exit(0); + } + num_devs++; + + if (rc != 0) + { + syslog(LOG_ERR, "Format failed for device %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + } + } + } + p_common_record = (struct ibmsis_record_common *) + ((unsigned long)p_common_record + + sistoh16(p_common_record->record_len)); + } + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + return num_devs; +} + +int dev_include_complete(u8 num_devs) +{ +#define FORMAT_COMPLETE_HDR_SIZE 7 + FIELD *p_fields[3]; + FORM *p_form; + FORM *p_old_form; + int done_bad; + int max_size = curses_info.max_y - (FORMAT_COMPLETE_HDR_SIZE + 3 + 1); + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel; + struct ibmsis_cmd_status cmd_status; + struct ibmsis_cmd_status_record *p_record; + int not_done = 0; + int rc, i, j; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct devs_to_init_t *p_cur_dev_to_init; + u32 percent_cmplt = 0; + WINDOW *p_title_win, *p_menu_win; + int num_includes = 0; + int fd, found; + struct sis_ioa *p_cur_ioa; + struct array_cmd_data *p_cur_raid_cmd; + struct ibmsis_array_record *p_array_record; + struct ibmsis_record_common *p_common_record_saved; + struct ibmsis_device_record *p_device_record_saved; + struct ibmsis_record_common *p_common_record; + struct ibmsis_device_record *p_device_record; + + p_title_win = newwin(FORMAT_COMPLETE_HDR_SIZE, + curses_info.max_x, + curses_info.start_y, + curses_info.start_x); + + p_menu_win = newwin(3, curses_info.max_x, + curses_info.start_y + max_size + 7, curses_info.start_x); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Include Disk Units in Device Parity Protection Status"); + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + FORMAT_COMPLETE_HDR_SIZE, + curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + mvwaddstr(p_title_win, 2, 0, "The operation to include units in the device parity protection"); + mvwaddstr(p_title_win, 3, 0, "will be done in several phases. The phases are listed here"); + mvwaddstr(p_title_win, 4, 0, "and the status will be indicated when known."); + mvwaddstr(p_title_win, 6, 0, "Phase Status"); + mvwaddstr(p_menu_win, 2, 0, "Please wait for next screen"); + mvwaddstr(p_tail_win->p_win,0, 0, "Prepare to include units . . . . . . . . :"); + mvwaddstr(p_tail_win->p_win,1, 0, "Include units . . . . . . . . . . . . . :"); + + form_driver(p_form, /* form to pass input to */ + REQ_FIRST_FIELD ); /* form request code */ + + clear (); + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_title_win); + wnoutrefresh(p_menu_win); + doupdate(); + + mvprintw(7, 46, "%3d %%", percent_cmplt); + refresh(); + + /* Here we need to sleep for a bit to make sure our children have started + their formats. There isn't really a good way to know whether or not the formats + have started, so we just wait for 60 seconds */ + sleep(60); + + while(1) + { + mvprintw(7, 46, "%3d %%", percent_cmplt); + form_driver(p_form, + REQ_FIRST_FIELD); + refresh(); + + percent_cmplt = 100; + done_bad = 0; + + for (p_cur_dev_to_init = p_head_dev_to_init; + p_cur_dev_to_init != NULL; + p_cur_dev_to_init = p_cur_dev_to_init->p_next) + { + if (p_cur_dev_to_init->do_init) + { + fd = open(p_cur_dev_to_init->p_ioa->ioa.dev_name, O_RDWR); + + if (fd < 0) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_dev_to_init->p_ioa->ioa.dev_name); + done_bad = 1; + continue; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &cmd_status; + ioa_cmd.buffer_len = sizeof(cmd_status); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_cur_dev_to_init->p_sis_device->p_resource_entry->resource_address; + + rc = sis_ioctl(fd, IBMSIS_QUERY_COMMAND_STATUS, &ioa_cmd); + + close(fd); + if (rc) + { + syslog(LOG_ERR, "Query Command Status to %s failed. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + p_cur_dev_to_init->cmplt = 100; + continue; + } + + if (cmd_status.num_records == 0) + p_cur_dev_to_init->cmplt = 100; + else + { + p_record = cmd_status.record; + if (p_record->status == IBMSIS_CMD_STATUS_SUCCESSFUL) + { + p_cur_dev_to_init->cmplt = 100; + } + else if (p_record->status == IBMSIS_CMD_STATUS_FAILED) + { + p_cur_dev_to_init->cmplt = 100; + done_bad = 1; + } + else + { + p_cur_dev_to_init->cmplt = p_record->percent_complete; + if (p_cur_dev_to_init->cmplt < percent_cmplt) + percent_cmplt = p_cur_dev_to_init->cmplt; + not_done = 1; + } + } + } + } + + unpost_form(p_form); + + if (!not_done) + { + p_cur_dev_to_init = p_head_dev_to_init; + while(p_cur_dev_to_init) + { + if (p_cur_dev_to_init->do_init) + { + if (p_cur_dev_to_init->fd) + close(p_cur_dev_to_init->fd); + } + p_cur_dev_to_init = p_cur_dev_to_init->p_next; + } + + if (done_bad) + { + rc = RC_FAILED; + goto leave; + } + + break; + } + not_done = 0; + sleep(10); + } + + mvprintw(7, 44, "Complete"); + form_driver(p_form, + REQ_FIRST_FIELD); + refresh(); + sleep(5); + + /* now issue the start array command with "known to be zero" */ + for (p_cur_raid_cmd = p_head_raid_cmd; + p_cur_raid_cmd != NULL; + p_cur_raid_cmd = p_cur_raid_cmd->p_next) + { + if (p_cur_raid_cmd->do_cmd == 0) + continue; + + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + + if (p_cur_ioa->num_raid_cmds > 0) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + continue; + } + + p_array_record = (struct ibmsis_array_record *) + p_cur_raid_cmd->p_sis_device->p_qac_entry; + + if (p_array_record->common.record_id == + IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + /* refresh qac data for ARRAY2 */ + memset(&ioa_cmd, 0, + sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_ioa->p_qac_data; + ioa_cmd.buffer_len = sizeof(struct ibmsis_array_query_data); + ioa_cmd.cdb[1] = 0x01; /* Volume Set Include */ + ioa_cmd.cdb[2] = p_cur_raid_cmd->array_id; + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_QUERY_ARRAY_CONFIG, &ioa_cmd); + + if (rc != 0) + { + if (errno != EINVAL) + syslog(LOG_ERR,"Query Array Config to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + close(fd); + continue; + } + + /* scan through this raid command to determine which + devices should be part of this parity set */ + p_common_record_saved = (struct ibmsis_record_common *) + p_cur_raid_cmd->p_qac_data->data; + for (i = 0; i < p_cur_raid_cmd->p_qac_data->num_records; i++) + { + p_device_record_saved = (struct ibmsis_device_record *)p_common_record_saved; + if (p_device_record_saved->issue_cmd) + { + p_common_record = (struct ibmsis_record_common *) + p_cur_ioa->p_qac_data->data; + found = 0; + for (j = 0; j < p_cur_ioa->p_qac_data->num_records; j++) + { + p_device_record = (struct ibmsis_device_record *)p_common_record; + if (p_device_record->resource_handle == + p_device_record_saved->resource_handle) + { + p_device_record->issue_cmd = 1; + p_device_record->known_zeroed = 1; + found = 1; + break; + } + p_common_record = (struct ibmsis_record_common *) + ((unsigned long)p_common_record + + sistoh16(p_common_record->record_len)); + } + if (!found) + { + syslog(LOG_ERR,"Resource not found to include device to %s failed"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + break; + } + } + p_common_record_saved = (struct ibmsis_record_common *) + ((unsigned long)p_common_record_saved + + sistoh16(p_common_record_saved->record_len)); + } + + if (!found) + { + close(fd); + continue; + } + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_ioa->p_qac_data; + ioa_cmd.buffer_len = sistoh16(p_cur_ioa->p_qac_data->resp_len); + rc = sis_ioctl(fd, IBMSIS_ADD_ARRAY_DEVICE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Add Array Device to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + rc = RC_FAILED; + close(fd); + goto leave; + } + close(fd); + } + } + + not_done = 0; + percent_cmplt = 0; + + while(1) + { + mvprintw(8, 46, "%3d %%", percent_cmplt); + form_driver(p_form, + REQ_FIRST_FIELD); + refresh(); + + percent_cmplt = 100; + done_bad = 0; + num_includes = 0; + + for (p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + if (p_cur_ioa->num_raid_cmds > 0) + { + int fd = open(p_cur_ioa->ioa.dev_name, O_RDONLY); + + if (fd < 0) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + p_cur_ioa->num_raid_cmds = 0; + done_bad = 1; + continue; + } + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &cmd_status; + ioa_cmd.buffer_len = sizeof(cmd_status); + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_QUERY_COMMAND_STATUS, &ioa_cmd); + + if (rc) + { + syslog(LOG_ERR, "Query Command Status to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + close(fd); + p_cur_ioa->num_raid_cmds = 0; + done_bad = 1; + continue; + } + + close(fd); + p_record = cmd_status.record; + + for (j=0; j < cmd_status.num_records; j++, p_record++) + { + if (p_record->command_code == IBMSIS_ADD_ARRAY_DEVICE) + { + for (p_cur_raid_cmd = p_head_raid_cmd; + p_cur_raid_cmd != NULL; + p_cur_raid_cmd = p_cur_raid_cmd->p_next) + { + if ((p_cur_raid_cmd->p_sis_ioa = p_cur_ioa) && + (p_cur_raid_cmd->array_id == p_record->array_id)) + { + num_includes++; + if (p_record->status == IBMSIS_CMD_STATUS_IN_PROGRESS) + { + if (p_record->percent_complete < percent_cmplt) + percent_cmplt = p_record->percent_complete; + not_done = 1; + } + else if (p_record->status != IBMSIS_CMD_STATUS_SUCCESSFUL) + { + rc = RC_FAILED; + } + break; + } + } + } + } + } + } + + unpost_form(p_form); + + if (!not_done) + { + if (done_bad) + { + rc = RC_FAILED; + goto leave; + } + + check_current_config(false); + revalidate_devs(NULL); + rc = RC_SUCCESS; + mvprintw(8, 44, "Complete"); + form_driver(p_form, + REQ_FIRST_FIELD); + refresh(); + sleep(2); + goto leave; + } + not_done = 0; + sleep(2); + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + +int hot_spare(int action) +{ +/* iSeries + Configure a hot spare device + +Select the subsystems which disk units will be configured as hot spares + +Type choice, press Enter. + 1=Select subsystem + + Serial Resource +Option Number Type Model Name + 02137002 2757 001 /dev/ibmsis5 + 03060044 5703 001 /dev/ibmsis4 + 02127005 5703 001 /dev/ibmsis3 + +e=Exit q=Cancel f=PageDn b=PageUp +*/ +/* non-iSeries + Configure a hot spare device + +Select the subsystems which disk units will be configured as hot spares + +Type choice, press Enter. + 1=Select subsystem + + Vendor Product Serial PCI PCI +Option ID ID Number Bus Dev + IBM 2780001 3AFB348C 05 03 + IBM 5703001 A775915E 04 01 + + +e=Exit q=Cancel f=PageDn b=PageUp +*/ + int rc, array_num, i, last_char; + struct ibmsis_record_common *p_common_record; + struct ibmsis_array_record *p_array_record; + struct ibmsis_device_record *p_device_record; + struct array_cmd_data *p_cur_raid_cmd; + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + char buffer[100]; + int array_index; + int max_size = curses_info.max_y - 12; + int confirm_hot_spare(int action); + int select_hot_spare(struct array_cmd_data *p_cur_raid_cmd, int action); + int num_lines = 0; + struct sis_ioa *p_cur_ioa; + u32 len; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + int found = 0; + char *p_char; + int ch; + char title_str[64]; + char descript_str[128]; + char instruct_str[64]; + struct ibmsis_resource_entry *p_resource_entry; + + rc = RC_SUCCESS; + + array_num = 1; + + p_title_win = newwin(9, curses_info.max_x, 0, 0); + p_menu_win = newwin(3, curses_info.max_x, max_size + 9, 0); + p_field_win = newwin(max_size, curses_info.max_x, 9, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + if (action == SIS_ADD_HOT_SPARE) + { + sprintf(title_str,"Configure a hot spare device"); + sprintf(descript_str,"Select the subsystems which disk units will be configured as hot spares"); + sprintf(instruct_str,"Select subsystem"); + } + else + { + sprintf(title_str,"Unconfigure a Hot Spare Device"); + sprintf(descript_str,"Select the subsystems which hot spares will be unconfigured"); + sprintf(instruct_str,"Select subsystem"); + } + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + title_str); /* string value to set + */ + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + check_current_config(false); + + for(p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + p_cur_ioa->num_raid_cmds = 0; + + for (i = 0; + i < p_cur_ioa->num_devices; + i++) + { + p_common_record = p_cur_ioa->dev[i].p_qac_entry; + + if (p_common_record == NULL) + continue; + + p_array_record = (struct ibmsis_array_record *)p_common_record; + p_device_record = (struct ibmsis_device_record *)p_common_record; + + if (((p_common_record->record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD) && + (!p_array_record->established) && + (action == SIS_ADD_HOT_SPARE)) || + ((p_common_record->record_id == IBMSIS_RECORD_ID_DEVICE2_RECORD) && + (p_device_record->is_hot_spare) && + (action == SIS_RMV_HOT_SPARE))) + { + if (p_head_raid_cmd) + { + p_tail_raid_cmd->p_next = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + p_tail_raid_cmd = p_tail_raid_cmd->p_next; + } + else + { + p_head_raid_cmd = p_tail_raid_cmd = (struct array_cmd_data *)malloc(sizeof(struct array_cmd_data)); + } + + p_tail_raid_cmd->p_next = NULL; + + memset(p_tail_raid_cmd, 0, sizeof(struct array_cmd_data)); + + p_tail_raid_cmd->array_id = 0; + p_tail_raid_cmd->array_num = array_num; + p_tail_raid_cmd->p_sis_ioa = p_cur_ioa; + p_tail_raid_cmd->p_sis_device = NULL; + + start_y = (array_num-1) % (max_size - 1); + + if ((num_lines > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 3, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)p_tail_raid_cmd); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 9, start_y, 9, 0, 0); + + p_resource_entry = p_cur_ioa->ioa.p_resource_entry; + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, "%8s %x 001 %s", + p_resource_entry->serial_num, + p_resource_entry->type, + p_cur_ioa->ioa.dev_name); + } + else + { + char buf[100]; + + memcpy(buf, p_resource_entry->std_inq_data.vpids.vendor_id, IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len = sprintf(buffer, "%-8s ", buf); + + memcpy(buf, p_resource_entry->std_inq_data.vpids.product_id, IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s ", p_resource_entry->serial_num); + + len += sprintf(buffer + len, "%02d %02d", + p_resource_entry->pci_bus_number, + p_resource_entry->pci_slot); + } + + set_field_buffer(pp_field[field_index], 0, buffer); + field_opts_off(pp_field[field_index], O_ACTIVE); + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + array_num++; + break; + } + } + } + + if (array_num == 1) + { + rc = RC_NOOP; + goto leave; + } + + mvwaddstr(p_title_win, 2, 0, descript_str); + mvwaddstr(p_title_win, 4, 0, "Type choice, press Enter."); + mvwaddstr(p_title_win, 5, 0, " 1="); + mvwaddstr(p_title_win, 5, 4, instruct_str); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 7, 0, " Serial Resource"); + mvwaddstr(p_title_win, 8, 0, "Option Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 7, 0, " Vendor Product Serial PCI PCI"); + mvwaddstr(p_title_win, 8, 0, "Option ID ID Number Bus Dev"); + } + + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + + field_opts_off(p_fields[1], O_ACTIVE); + + array_index = ((max_size - 1) * 2) + 1; + for (i = array_index; i < field_index; i += array_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + flush_stdscr(); + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + form_driver(p_list_form, + REQ_FIRST_FIELD); + + while(1) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + } + else if (IS_PGUP_KEY(ch)) + { + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + } + else if ((ch == KEY_DOWN) || + (ch == '\t')) + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + } + else if (ch == KEY_UP) + { + form_driver(p_list_form, + REQ_PREV_FIELD); + } + else if (IS_ENTER_KEY(ch)) + { + found = 0; + + unpost_form(p_list_form); + p_cur_raid_cmd = p_head_raid_cmd; + + for (i = 0; i < field_index; i++) + { + p_cur_raid_cmd = (struct array_cmd_data *)field_userptr(pp_field[i]); + if (p_cur_raid_cmd != NULL) + { + p_char = field_buffer(pp_field[i], 0); + if (strcmp(p_char, "1") == 0) + { + while(RC_REFRESH == (rc = select_hot_spare(p_cur_raid_cmd, action))) + clear(); + if (rc == RC_EXIT) + goto leave; + if (rc == RC_CANCEL) + { + rc = RC_REFRESH; + goto leave; + } + + found = 1; + if (!p_cur_raid_cmd->do_cmd) + { + p_cur_raid_cmd->do_cmd = 1; + p_cur_raid_cmd->p_sis_ioa->num_raid_cmds++; + } + } + else + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_raid_cmd->do_cmd = 0; + p_cur_raid_cmd->p_sis_ioa->num_raid_cmds--; + } + } + } + } + + if (found != 0) + { + /* Go to verification screen */ + unpost_form(p_form); + rc = confirm_hot_spare(action); + goto leave; + } + else + { + post_form(p_list_form); + rc = 1; + } + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free(pp_field); + + p_cur_raid_cmd = p_head_raid_cmd; + while(p_cur_raid_cmd) + { + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + free(p_head_raid_cmd); + p_head_raid_cmd = p_cur_raid_cmd; + } + + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int select_hot_spare(struct array_cmd_data *p_cur_raid_cmd, + int action) +{ +/* + Select Disk Units to Enable as Hot Spare + +Type option, press Enter. +1=Select + + Vendor Product Serial PCI PCI SCSI SCSI SCSI +OPT ID ID Number Bus Dev Bus ID Lun + IBM DFHSS4W 0024A0B9 05 03 0 3 0 + IBM DFHSS4W 00D38D0F 05 03 0 5 0 + IBM DFHSS4W 00D32240 05 03 0 9 0 + IBM DFHSS4W 00034563 05 03 0 6 0 + IBM DFHSS4W 00D37A11 05 03 0 4 0 + +e=Exit q=Cancel f=PageDn b=PageUp + +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + Select Disk Units to Enable as Hot Spare + +Type option, press Enter. +1=Select + + Serial Frame Card PCI PCI SCSI SCSI SCSI +OPT Type Number ID Position Bus Dev Bus ID Lun + 6607 0024A0B9 03 D01 05 03 0 3 0 + 6607 00D38D0F 03 D02 05 03 0 5 0 + 6607 00D32240 03 D03 05 03 0 9 0 + 6607 00034563 03 D04 05 03 0 6 0 + 6717 00D37A11 03 D05 05 03 0 4 0 + +e=Exit q=Cancel f=PageDn b=PageUp + + +*/ + + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + int rc, i, j, init_index, found, last_char; + char buffer[100]; + int max_size = curses_info.max_y - 10; + int num_devs = 0; + struct sis_ioa *p_cur_ioa; + char *p_char; + u32 len; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int field_index = 0; + int start_y; + struct sis_device *p_sis_device; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_device_record *p_device_record; + char title_str[64]; + + rc = RC_SUCCESS; + + p_title_win = newwin(7, curses_info.max_x, + 0, 0); + + p_menu_win = newwin(3, curses_info.max_x, + max_size + 7, 0); + + p_field_win = newwin(max_size, curses_info.max_x, 7, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + if (action == SIS_ADD_HOT_SPARE) + { + sprintf(title_str, "Select Disk Units to Enable as Hot Spare"); + } + else + { + sprintf(title_str, "Select Disk Units to Disable Hot Spare"); + } + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + title_str); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + mvwaddstr(p_title_win, 2, 0, "Type option, press Enter."); + mvwaddstr(p_title_win, 3, 0, " 1=Select"); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 5, 0, + " Serial Frame Card PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "OPT Type Number ID Position Bus Dev Bus ID Lun"); + } + else + { + mvwaddstr(p_title_win, 5, 0, + " Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "OPT ID ID Number Bus Dev Bus ID Lun"); + } + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + p_device_record = (struct ibmsis_device_record *)p_cur_ioa->dev[j].p_qac_entry; + + if (!p_resource_entry->is_ioa_resource && + (p_device_record != NULL) && + (p_device_record->common.record_id == IBMSIS_RECORD_ID_DEVICE2_RECORD) && + (((p_device_record->add_hot_spare_cand) && (action == SIS_ADD_HOT_SPARE)) || + ((p_device_record->rmv_hot_spare_cand) && (action == SIS_RMV_HOT_SPARE)))) + { + len = print_dev_sel(p_resource_entry, buffer); + start_y = num_devs % (max_size - 1); + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 1, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)&p_cur_ioa->dev[j]); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 7, /* new field size */ + start_y, 7, 0, 0); + + set_field_buffer(pp_field[field_index], 0, buffer); + + field_opts_off(pp_field[field_index], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_userptr(pp_field[field_index++], NULL); + + if ((num_devs > 0) && ((num_devs % (max_size - 2)) == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + start_y + 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + memset(buffer, 0, 100); + + len = 0; + num_devs++; + } + } + + if (num_devs) + { + field_opts_off(p_fields[1], O_ACTIVE); + + init_index = ((max_size - 1) * 2) + 1; + for (i = init_index; i < field_index; i += init_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + + while (1) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (ch == KEY_DOWN) + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else if (ch == KEY_UP) + { + form_driver(p_list_form, + REQ_PREV_FIELD); + break; + } + else if (IS_ENTER_KEY(ch)) + { + found = 0; + + unpost_form(p_list_form); + mvwaddstr(p_menu_win, 2, 1, " "); + wrefresh(p_menu_win); + + for (i = 0; i < field_index; i++) + { + p_sis_device = (struct sis_device *)field_userptr(pp_field[i]); + if (p_sis_device != NULL) + { + p_char = field_buffer(pp_field[i], 0); + if (strcmp(p_char, "1") == 0) + { + found = 1; + p_device_record = (struct ibmsis_device_record *)p_sis_device->p_qac_entry; + p_device_record->issue_cmd = 1; + } + } + } + + if (found != 0) + { + /* Go to parameters screen */ + unpost_form(p_form); + } + else + { + post_form(p_list_form); + break; + } + + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if (IS_PGUP_KEY(ch)) + { + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if (ch == '\t') + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + break; + } + } + } + } + else + { + /* No devices to initialize */ + free_field(p_fields[0]); + return RC_NOOP; + } + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + + free_screen(NULL, NULL, p_fields); + free_screen(NULL, NULL, pp_field); + free(pp_field); + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + flush_stdscr(); + return rc; +} + +int confirm_hot_spare(int action) +{ +#define CONFIRM_START_HDR_SIZE 10 +#define CONFIRM_START_MENU_SIZE 3 +/* + Confirm Enable Hot Spare + +ATTENTION: Existing data on these disk units will not be preserved. + + +Press Enter to continue. +Press q=Cancel to return and change your choice. + + Vendor Product Serial PCI PCI SCSI SCSI SCSI +Option ID ID Number Bus Dev Bus ID Lun + IBM DFHSS4W 0024A0B9 05 03 0 3 0 + IBM DFHSS4W 00D38D0F 05 03 0 5 0 + IBM DFHSS4W 00D32240 05 03 0 9 0 + IBM DFHSS4W 00034563 05 03 0 6 0 + IBM DFHSS4W 00D37A11 05 03 0 4 0 + + q=Cancel f=PageDn b=PageUp + +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + Confirm Enable Hot Spare + +ATTENTION: Existing data on these disk units will not be preserved. + + +Press Enter to continue. +Press q=Cancel to return and change your choice. + + Serial Frame Card PCI PCI SCSI SCSI SCSI +Option Type Number ID Position Bus Dev Bus ID Lun + 6607 0024A0B9 03 D01 05 03 0 3 0 + 6607 00D38D0F 03 D02 05 03 0 5 0 + 6607 00D32240 03 D03 05 03 0 9 0 + 6607 00034563 03 D04 05 03 0 6 0 + 6717 00D37A11 03 D05 05 03 0 4 0 + + q=Cancel f=PageDn b=PageUp + + + +*/ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + struct ibmsis_resource_entry *p_resource_entry; + struct array_cmd_data *p_cur_raid_cmd; + struct ibmsis_device_record *p_device_record; + struct sis_ioa *p_cur_ioa; + int rc, j; + u16 len = 0; + char buffer[100]; + u32 num_lines = 0; + int max_size = curses_info.max_y - (CONFIRM_START_HDR_SIZE + CONFIRM_START_MENU_SIZE + 1); + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel, *p_cur_panel; + WINDOW *p_title_win, *p_menu_win; + PANEL *p_panel; + int hot_spare_complete(); + char title_str[64]; + + p_title_win = newwin(CONFIRM_START_HDR_SIZE, + curses_info.max_x, + curses_info.start_y, + curses_info.start_x); + + p_menu_win = newwin(CONFIRM_START_MENU_SIZE, + curses_info.max_x, + curses_info.start_y + max_size + CONFIRM_START_HDR_SIZE + 1, + curses_info.start_x); + + rc = RC_SUCCESS; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + if (action == SIS_ADD_HOT_SPARE) + { + sprintf(title_str, "Confirm Enable Hot Spare"); + } + else + { + sprintf(title_str, "Confirm Disable Hot Spare"); + } + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + title_str); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_START_HDR_SIZE, + curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + wattron(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 2, 0, "ATTENTION:"); + wattroff(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 2, 10, " Existing data on these disk units will not be preserved."); + mvwaddstr(p_title_win, 5, 0, "Press Enter to continue."); + mvwaddstr(p_title_win, 6, 0, "Press "CANCEL_KEY_LABEL"=Cancel to return and change your choice."); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 8, 0, + " Serial Frame Card PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 9, 0, + "Option Type Number ID Position Bus Dev Bus ID Lun"); + } + else + { + mvwaddstr(p_title_win, 8, 0, + " Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 9, 0, + "Option ID ID Number Bus Dev Bus ID Lun"); + } + + mvwaddstr(p_menu_win, 1, 0, CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_cur_raid_cmd = p_head_raid_cmd; + + while(p_cur_raid_cmd) + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + p_device_record = (struct ibmsis_device_record *)p_cur_ioa->dev[j].p_qac_entry; + + if ((p_device_record != NULL) && + (p_device_record->common.record_id == IBMSIS_RECORD_ID_DEVICE2_RECORD) && + (p_device_record->issue_cmd)) + { + len = sprintf(buffer, " 1 "); + print_dev_sel(p_resource_entry, buffer + len); + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, + curses_info.max_x, + curses_info.start_y + CONFIRM_START_HDR_SIZE, + curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + } + } + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + + p_cur_panel = p_head_panel; + + while(p_cur_panel) + { + bottom_panel(p_cur_panel->p_panel); + p_cur_panel = p_cur_panel->p_next; + } + + while(1) + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_REFRESH; + goto leave; + } + else if (IS_ENTER_KEY(ch)) + { + /* verify the devices are not in use */ + p_cur_raid_cmd = p_head_raid_cmd; + while (p_cur_raid_cmd) + { + if (p_cur_raid_cmd->do_cmd) + { + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + if (rc != 0) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Devices may have changed state. Command cancelled, " + "please issue commands again if RAID still desired %s." + IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + goto leave; + } + } + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + } + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + werase(stdscr); + rc = hot_spare_complete(action); + return rc; + } + else if (IS_PGDN_KEY(ch)) + { + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else + { + break; + } + } + + } + + leave: + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + +int hot_spare_complete(int action) +{ + /* + no screen is displayed for this action + */ +#define FORMAT_COMPLETE_HDR_SIZE 7 + int rc; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + int fd; + struct sis_ioa *p_cur_ioa; + struct array_cmd_data *p_cur_raid_cmd; + + /* now issue the start array command with "known to be zero" */ + for (p_cur_raid_cmd = p_head_raid_cmd; + p_cur_raid_cmd != NULL; + p_cur_raid_cmd = p_cur_raid_cmd->p_next) + { + if (p_cur_raid_cmd->do_cmd == 0) + continue; + + p_cur_ioa = p_cur_raid_cmd->p_sis_ioa; + + if (p_cur_ioa->num_raid_cmds > 0) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + return rc; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_ioa->p_qac_data; + ioa_cmd.buffer_len = sistoh16(p_cur_ioa->p_qac_data->resp_len); + ioa_cmd.cdb[1] = 0x01; /* configure Hot Spare */ + if (action == SIS_ADD_HOT_SPARE) + rc = sis_ioctl(fd, IBMSIS_START_ARRAY_PROTECTION, &ioa_cmd); + else + rc = sis_ioctl(fd, IBMSIS_STOP_ARRAY_PROTECTION, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Start Array Protection to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + rc = RC_FAILED; + close(fd); + return rc; + } + close(fd); + } + } + + return rc; +} + +int reclaim_cache() +{ +#define RECLAIM_HDR_SIZE 13 +#define RECLAIM_MENU_SIZE 4 + /* + Reclaim IOA Cache Storage + + Select the IOA to reclaim IOA cache storage. + + ATTENTION: Proceed with this function only if directed to from a + service procedure. Data in the IOA cache will be discarded. + Damaged objects may result on the system. + + Type choice, press Enter. + 1=Reclaim IOA cache storage + + Serial Resource + Option Type Model Number Name + 2748 001 09228053 /dev/ibmsis0 + + + e=Exit q=Cancel + */ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form, *p_list_form; + int fd, rc, i, len, last_char; + struct ibmsis_reclaim_query_data *p_reclaim_buffer, *p_cur_reclaim_buffer; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + int num_lines = 0; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + struct sis_ioa *p_cur_ioa, *p_reclaim_ioa; + int max_size = curses_info.max_y - (RECLAIM_HDR_SIZE + RECLAIM_MENU_SIZE); + int num_needed = 0; + int ioa_num = 0; + char buffer[100], *p_char; + + rc = RC_SUCCESS; + + p_reclaim_buffer = (struct ibmsis_reclaim_query_data*)malloc(sizeof(struct ibmsis_reclaim_query_data) * num_ioas); + + p_title_win = newwin(RECLAIM_HDR_SIZE, curses_info.max_x, 0, 0); + p_menu_win = newwin(RECLAIM_MENU_SIZE, curses_info.max_x, max_size + RECLAIM_HDR_SIZE, 0); + p_field_win = newwin(max_size, curses_info.max_x, RECLAIM_HDR_SIZE, 0); + + clear(); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Reclaim IOA Cache Storage"); /* string value to set */ + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + mvwaddstr(p_title_win, 2, 0, "Select the IOA to reclaim IOA cache storage."); + wattron(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 4, 0, "ATTENTION:"); + wattroff(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 4, 10, " Proceed with this function only if directed to from a"); + mvwaddstr(p_title_win, 5, 0, "service procedure. Data in the IOA cache will be discarded."); + mvwaddstr(p_title_win, 6, 0, "Damaged objects may result on the system."); + mvwaddstr(p_title_win, 8, 0, "Type choice, press Enter."); + mvwaddstr(p_title_win, 9, 0, " 1=Reclaim IOA cache storage"); + mvwaddstr(p_title_win, 11, 0, " Serial Resource"); + mvwaddstr(p_title_win, 12, 0, "Option Type Model Number Name"); + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + for (p_cur_ioa = p_head_sis_ioa, p_cur_reclaim_buffer = p_reclaim_buffer; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next, p_cur_reclaim_buffer++) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + continue; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_reclaim_buffer; + ioa_cmd.buffer_len = sizeof(struct ibmsis_reclaim_query_data); + ioa_cmd.cdb[1] = IBMSIS_RECLAIM_QUERY; + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_RECLAIM_CACHE_STORE, &ioa_cmd); + + if (rc != 0) + { + if (errno != EINVAL) + { + syslog(LOG_ERR, "Reclaim Query to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + } + close(fd); + p_cur_ioa->p_reclaim_data = NULL; + continue; + } + + close(fd); + + p_cur_ioa->p_reclaim_data = p_cur_reclaim_buffer; + + if (p_cur_reclaim_buffer->reclaim_known_needed || + p_cur_reclaim_buffer->reclaim_unknown_needed) + { + num_needed++; + } + } + + if (num_needed) + { + p_cur_ioa = p_head_sis_ioa; + + while(p_cur_ioa) + { + if ((p_cur_ioa->p_reclaim_data) && + (p_cur_ioa->p_reclaim_data->reclaim_known_needed || + p_cur_ioa->p_reclaim_data->reclaim_unknown_needed)) + { + start_y = ioa_num % (max_size - 1); + + if ((num_lines > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, 0, 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + + set_field_buffer(pp_field[field_index], 0, "More... "); + + set_field_userptr(pp_field[field_index], NULL); + + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 2)); + + pp_field[field_index] = new_field(1, 1, start_y, 3, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)p_cur_ioa); + + /* Description field */ + pp_field[field_index] = new_field(1, curses_info.max_x - RECLAIM_HDR_SIZE, + start_y, 10, 0, 0); + + len = sprintf(buffer, "%x 001 %8s %s", + p_cur_ioa->ccin, p_cur_ioa->serial_num, + p_cur_ioa->ioa.dev_name); + + set_field_buffer(pp_field[field_index], 0, buffer); + + field_opts_off(pp_field[field_index], O_ACTIVE); + + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + len = 0; + num_lines++; + ioa_num++; + } + p_cur_reclaim_buffer++; + p_cur_ioa = p_cur_ioa->p_next; + + } + + field_opts_off(p_fields[1], O_ACTIVE); + + ioa_num = ((max_size - 1) * 2) + 1; + for (i = ioa_num; i < field_index; i += ioa_num) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + + + while(1) + { + mvwaddstr(p_title_win, 2, 0, "Select the IOA to reclaim IOA cache storage."); + wattron(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 4, 0, "ATTENTION:"); + wattroff(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 4, 10, " Proceed with this function only if directed to from a"); + mvwaddstr(p_title_win, 5, 0, "service procedure. Data in the IOA cache will be discarded."); + mvwaddstr(p_title_win, 6, 0, "Damaged objects may result on the system."); + mvwaddstr(p_title_win, 8, 0, "Type choice, press Enter."); + mvwaddstr(p_title_win, 9, 0, " 1=Reclaim IOA cache storage"); + mvwaddstr(p_title_win, 11, 0, " Serial Resource"); + mvwaddstr(p_title_win, 12, 0, "Option Type Model Number Name"); + mvwaddstr(p_menu_win, 1, 0, + EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if (IS_PGUP_KEY(ch)) + { + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if ((ch == KEY_DOWN) || + (ch == '\t')) + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else if (ch == KEY_UP) + { + form_driver(p_list_form, + REQ_PREV_FIELD); + break; + } + else if (IS_ENTER_KEY(ch)) + { + ioa_num = 0; + + for (i = 0; i < field_index; i++) + { + p_cur_ioa = (struct sis_ioa *)field_userptr(pp_field[i]); + if (p_cur_ioa != NULL) + { + p_char = field_buffer(pp_field[i], 0); + + if (strcmp(p_char, "1") == 0) + { + if (ioa_num) + { + ioa_num++; + break; + } + else if (p_cur_ioa->p_reclaim_data->reclaim_known_needed || + p_cur_ioa->p_reclaim_data->reclaim_unknown_needed) + { + p_reclaim_ioa = p_cur_ioa; + ioa_num++; + } + } + } + } + + if (ioa_num == 0) + { + wclear(p_menu_win); + break; + } + else if (ioa_num == 1) + { + unpost_form(p_list_form); + unpost_form(p_form); + + rc = confirm_reclaim(p_reclaim_ioa); + if ((rc == RC_NOOP) || + (rc == RC_CANCEL)) + { + werase(p_title_win); + werase(p_menu_win); + post_form(p_form); + post_form(p_list_form); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else + { + goto leave; + } + } + else + { + mvwaddstr(p_menu_win, 2, 0, " Error. You have selected more than one IOA."); + break; + } + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + break; + } + } + } + } + else + { + rc = RC_NOOP; + goto leave; + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free(p_reclaim_buffer); + free(pp_field); + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int confirm_reclaim(struct sis_ioa *p_reclaim_ioa) +{ + /* + Confirm Reclaim IOA Cache Storage + + The disk units that may be affected by the function are displayed. + + ATTENTION: Proceed with this function only if directed to from a + service procedure. Data in the IOA cache will be discarded. + Filesystem corruption may result on the system. + + Press c=Confirm to reclaim cache storage. + Press q=Cancel to return to change your choice. + + Serial Resource + Option Number Type Model Name + 1 000564FD 6717 050 /dev/sda + 1 000585F1 6717 050 /dev/sdb + 1 000591FB 6717 050 /dev/sdc + 1 00056880 6717 050 /dev/sdd + 1 000595AD 6717 050 /dev/sde + + q=Cancel c=Confirm reclaim + */ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_query_res_state res_state; + int fd, j, rc; + u16 len; + u32 num_lines = 0; + char buffer[100]; + int max_size = curses_info.max_y - 16; + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel, *p_cur_panel; + WINDOW *p_title_win, *p_menu_win; + PANEL *p_panel; + int confirm = 0; + + p_title_win = newwin(13, curses_info.max_x, + curses_info.start_y, curses_info.start_x); + + p_menu_win = newwin(3, curses_info.max_x, + curses_info.start_y + max_size + 13, curses_info.start_x); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Confirm Reclaim IOA Cache Storage"); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, curses_info.max_x, + curses_info.start_y + 13, curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + mvwaddstr(p_title_win, 2, 0, "The disk units that may be affected by the function are displayed."); + wattron(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 4, 0, "ATTENTION:"); + wattroff(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 4, 10, " Proceed with this function only if directed to from a"); + mvwaddstr(p_title_win, 5, 0, "service procedure. Data in the IOA cache will be discarded."); + mvwaddstr(p_title_win, 6, 0, "Filesystem corruption may result on the system."); + mvwaddstr(p_title_win, 8, 0, "Press c=Confirm to reclaim cache storage."); + mvwaddstr(p_title_win, 9, 0, "Press "CANCEL_KEY_LABEL"=Cancel to return to change your choice."); + mvwaddstr(p_title_win, 11, 0, " Serial Resource"); + mvwaddstr(p_title_win, 12, 0, "Option Number Type Model Name"); + + mvwaddstr(p_menu_win, 1, 0, CANCEL_KEY_LABEL"=Cancel c=Confirm reclaim f=PageDn b=PageUp"); + + check_current_config(false); + + fd = open(p_reclaim_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_reclaim_ioa->ioa.dev_name); + goto leave; + } + + for (j = 0; j < p_reclaim_ioa->num_devices; j++) + { + p_resource_entry = p_reclaim_ioa->dev[j].p_resource_entry; + if (!IBMSIS_IS_DASD_DEVICE(p_resource_entry->std_inq_data)) + continue; + + /* Do a query resource state to see whether or not the device will be + affected by the operation */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &res_state; + ioa_cmd.buffer_len = sizeof(res_state); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_resource_entry->resource_address; + + memset(&res_state, 0, sizeof(res_state)); + + rc = sis_ioctl(fd, IBMSIS_QUERY_RESOURCE_STATE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Query Resource State to a device (0x%08X) failed. %m"IBMSIS_EOL, + IBMSIS_GET_PHYSICAL_LOCATOR(p_resource_entry->resource_address)); + res_state.not_oper = 1; + } + + if (!res_state.read_write_prot) + continue; + + len = sprintf(buffer, " 1 "); + len += print_dev(p_resource_entry, buffer + len, p_reclaim_ioa->dev[j].dev_name); + + if ((num_lines > 0) && ((num_lines % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, curses_info.max_x, + curses_info.start_y + 13, curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_lines % max_size, 0, buffer); + memset(buffer, 0, 100); + num_lines++; + } + + close(fd); + + p_cur_panel = p_head_panel; + + while(p_cur_panel) + { + bottom_panel(p_cur_panel->p_panel); + p_cur_panel = p_cur_panel->p_next; + } + + while(1) + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if ((ch == 'c') || (ch == 'C') || + (((ch == 's') || (ch == 'S')) && (confirm == 1))) + { + if (p_reclaim_ioa->p_reclaim_data->reclaim_unknown_needed && + ((confirm == 0) || (ch == 'c') || (ch == 'C'))) + { + confirm = 1; + unpost_form(p_form); + werase(p_title_win); + post_form(p_form); + + wattron(p_title_win, A_STANDOUT); + mvwaddstr(p_title_win, 2, 0, "ATTENTION!!! ATTENTION!!! ATTENTION!!! ATTENTION!!!"); + wattroff(p_title_win, A_STANDOUT); + mvwaddstr(p_title_win, 4, 0, "Proceed with this function only if directed to from a"); + mvwaddstr(p_title_win, 5, 0, "service procedure. Data in the IOA cache will be discarded."); + mvwaddstr(p_title_win, 6, 0, "By proceeding you will be allowing "); + wattron(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 6, 35, "UNKNOWN"); + wattroff(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 6, 42, " data loss."); + mvwaddstr(p_title_win, 7, 0, "This data loss may or may not be detected by the host operating system."); + wattron(p_title_win, A_UNDERLINE); + mvwaddstr(p_title_win, 8, 0, "Filesystem corruption may result on the system."); + wattroff(p_title_win, A_UNDERLINE); + mvwaddstr(p_title_win, 10, 0, "Press 's' to continue."); + mvwaddstr(p_title_win, 11, 0, " Serial Resource"); + mvwaddstr(p_title_win, 12, 0, "Option Number Type Model Name"); + mvwaddstr(p_menu_win, 1, 0, CANCEL_KEY_LABEL"=Cancel s=Confirm reclaim f=PageDn b=PageUp"); + + break; + } + else + { + fd = open(p_reclaim_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_reclaim_ioa->ioa.dev_name); + goto leave; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_reclaim_ioa->p_reclaim_data; + ioa_cmd.buffer_len = sizeof(struct ibmsis_reclaim_query_data); + ioa_cmd.cdb[1] = IBMSIS_RECLAIM_PERFORM; + + if (p_reclaim_ioa->p_reclaim_data->reclaim_unknown_needed) + ioa_cmd.cdb[1] |= IBMSIS_RECLAIM_UNKNOWN_PERM; + + mvwaddstr(p_menu_win, 2, 0, "Please wait - reclaim in progress"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + rc = sis_ioctl(fd, IBMSIS_RECLAIM_CACHE_STORE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Reclaim to %s failed. %m"IBMSIS_EOL, p_reclaim_ioa->ioa.dev_name); + close(fd); + rc = RC_FAILED; + goto leave; + } + + close(fd); + + rc = reclaim_result(p_reclaim_ioa); + goto leave; + } + } + else if (IS_PGDN_KEY(ch)) + { + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else + { + break; + } + } + } + + leave: + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + +int reclaim_result(struct sis_ioa *p_reclaim_ioa) +{ + /* + Reclaim IOA Cache Storage Results + + IOA cache storage reclaimation has completed. Use the number + of lost sectors to decide whether to restore data from the + most recent save media or to continue with possible data loss. + + Number of lost sectors . . . . . . . . . . : 40168 + + Press Enter to continue. + + + + + + + + + + + + + + + e=Exit q=Cancel + + */ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + int rc, fd; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Reclaim IOA Cache Storage Results"); + + clear(); + refresh(); + + flush_stdscr(); + + post_form(p_form); + + fd = open(p_reclaim_ioa->ioa.dev_name, O_RDWR); + + if (fd <= 1) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_reclaim_ioa->ioa.dev_name); + goto leave; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + memset(p_reclaim_ioa->p_reclaim_data, 0, sizeof(struct ibmsis_reclaim_query_data)); + ioa_cmd.buffer = p_reclaim_ioa->p_reclaim_data; + ioa_cmd.buffer_len = sizeof(struct ibmsis_reclaim_query_data); + ioa_cmd.cdb[1] = IBMSIS_RECLAIM_QUERY; + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_RECLAIM_CACHE_STORE, &ioa_cmd); + + close(fd); + + if (rc) + goto leave; + + if (p_reclaim_ioa->p_reclaim_data->reclaim_known_performed) + { + mvaddstr(2, 0, "IOA cache storage reclaimation has completed. Use the number"); + mvaddstr(3, 0, "of lost sectors to decide whether to restore data from the"); + mvaddstr(4, 0, "most recent save media or to continue with possible data loss."); + if (p_reclaim_ioa->p_reclaim_data->num_blocks_needs_multiplier) + { + mvprintw(6, 0, "Number of lost sectors . . . . . . . . . . :%12d", + sistoh16(p_reclaim_ioa->p_reclaim_data->num_blocks) * + IBMSIS_RECLAIM_NUM_BLOCKS_MULTIPLIER); + } + else + { + mvprintw(6, 0, "Number of lost sectors . . . . . . . . . . :%12d", + sistoh16(p_reclaim_ioa->p_reclaim_data->num_blocks)); + } + mvaddstr(8, 0, "Press Enter to continue."); + } + else if (p_reclaim_ioa->p_reclaim_data->reclaim_unknown_performed) + { + mvaddstr(2, 0, "IOA cache storage reclaimation has completed. The number of"); + mvaddstr(3, 0, "lost sectors could not be determined."); + mvaddstr(5, 0, "Press Enter to continue."); + } + else + goto leave; + + mvaddstr(curses_info.max_y - 2, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch) || IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_SUCCESS; + goto leave; + } + else + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + } + + leave: + fd = open(p_reclaim_ioa->ioa.dev_name, O_RDWR); + + if (fd <= 1) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_reclaim_ioa->ioa.dev_name); + } + else + { + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_reclaim_ioa->p_reclaim_data; + ioa_cmd.buffer_len = sizeof(struct ibmsis_reclaim_query_data); + ioa_cmd.cdb[1] = IBMSIS_RECLAIM_RESET; + + rc = sis_ioctl(fd, IBMSIS_RECLAIM_CACHE_STORE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Reclaim reset to %s failed. %m"IBMSIS_EOL, p_reclaim_ioa->ioa.dev_name); + rc = RC_FAILED; + } + close(fd); + } + check_current_config(false); + revalidate_devs(p_reclaim_ioa); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int configure_af_device(int action_code) +{ +/* + Select Disk Units for Initialize and Format + +Type option, press Enter. + 1=Select + + Vendor Product Serial PCI PCI SCSI SCSI SCSI +OPT ID ID Number Bus Dev Bus ID Lun + IBM DFHSS4W 0024A0B9 05 03 0 3 0 + IBM DFHSS4W 00D38D0F 05 03 0 5 0 + IBM DFHSS4W 00D32240 05 03 0 9 0 + IBM DFHSS4W 00034563 05 03 0 6 0 + IBM DFHSS4W 00D37A11 05 03 0 4 0 + +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + Select Disk Units for Initialize and Format + +Type option, press Enter. + 1=Select + + Serial Frame Card PCI PCI SCSI SCSI SCSI +OPT Type Number ID Position Bus Dev Bus ID Lun + 6607 0024A0B9 03 D01 05 03 0 3 0 + 6607 00D38D0F 03 D02 05 03 0 5 0 + 6607 00D32240 03 D03 05 03 0 9 0 + 6607 00034563 03 D04 05 03 0 6 0 + 6717 00D37A11 03 D05 05 03 0 4 0 + +*/ + + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + int fd, rc, i, j, init_index, found, last_char; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_device_record *p_device_record; + int can_init; + int dev_type; + int change_size; + char buffer[100]; + int max_size = curses_info.max_y - 10; + int num_devs = 0; + struct sis_ioa *p_cur_ioa; + char *p_char; + u32 len; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int field_index = 0; + int start_y; + struct devs_to_init_t *p_cur_dev_to_init; + u8 cdb[IBMSIS_CCB_CDB_LEN]; + u8 ioctl_buffer[IOCTL_BUFFER_SIZE]; + struct ibmsis_mode_parm_hdr *p_mode_parm_hdr; + struct ibmsis_block_desc *p_block_desc; + int status; + struct sense_data_t sense_data; + + rc = RC_SUCCESS; + + p_title_win = newwin(7, curses_info.max_x, + 0, 0); + + p_menu_win = newwin(3, curses_info.max_x, + max_size + 7, 0); + + p_field_win = newwin(max_size, curses_info.max_x, 7, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Select Disk Units for Initialize and Format"); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + mvwaddstr(p_title_win, 2, 0, "Type option, press Enter."); + mvwaddstr(p_title_win, 3, 0, " 1=Select"); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 5, 0, + " Serial Frame Card PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "OPT Type Number ID Position Bus Dev Bus ID Lun"); + } + else + { + mvwaddstr(p_title_win, 5, 0, + " Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "OPT ID ID Number Bus Dev Bus ID Lun"); + } + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + check_current_config(false); + + for (p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + if ((p_cur_ioa->p_qac_data) && + (p_cur_ioa->p_qac_data->num_records == 0)) + continue; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + can_init = 1; + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + + /* If not a DASD, disallow format */ + if ((!IBMSIS_IS_DASD_DEVICE(p_resource_entry->std_inq_data)) || + (p_resource_entry->is_hot_spare)) + continue; + + /* If Advanced Function DASD */ + if (ibmsis_is_af_dasd_device(p_resource_entry)) + { + if (action_code == SIS_INCLUDE) + continue; + + p_device_record = (struct ibmsis_device_record *)p_cur_ioa->dev[j].p_qac_entry; + if (!p_device_record || + (p_device_record->common.record_id != IBMSIS_RECORD_ID_DEVICE2_RECORD)) + { + continue; + } + + dev_type = IBMSIS_AF_DASD_DEVICE; + change_size = SIS_512_BLOCK; + + /* We allow the user to format the drive if nobody is using it */ + if (p_cur_ioa->dev[j].opens != 0) + { + syslog(LOG_ERR, "Format not allowed to %s, device in use"IBMSIS_EOL, p_cur_ioa->dev[j].dev_name); + continue; + } + + if (p_resource_entry->is_array_member) + { + if (p_device_record->no_cfgte_vol) + can_init = 1; + else + can_init = 0; + } + else + { + can_init = p_resource_entry->format_allowed; + } + } + else if (p_resource_entry->subtype == IBMSIS_SUBTYPE_GENERIC_SCSI) /* Is JBOD */ + { + if (action_code == SIS_REMOVE) + continue; + + dev_type = IBMSIS_JBOD_DASD_DEVICE; + change_size = SIS_522_BLOCK; + + /* We allow the user to format the drive if nobody is using it, or + the device is read write protected. If the drive fails, then is replaced + concurrently it will be read write protected, but the system may still + have a use count for it. We need to allow the format to get the device + into a state where the system can use it */ + if (p_cur_ioa->dev[j].opens != 0) + { + syslog(LOG_ERR, "Format not allowed to %s, device in use"IBMSIS_EOL, p_cur_ioa->dev[j].dev_name); + continue; + } + + if (is_af_blocked(&p_cur_ioa->dev[j], 0)) + { + /* error log is posted in is_af_blocked() routine */ + continue; + } + + /* check if mode select with 522 block size will work, will be + set back to 512 if successfull otherwise will not be candidate. */ + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + cdb[0] = MODE_SELECT; + cdb[1] = 0x10; /* PF = 1, SP = 0 */ + + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + memset(ioctl_buffer, 0, 255); + + p_mode_parm_hdr->block_desc_len = sizeof(struct ibmsis_block_desc); + + p_block_desc = (struct ibmsis_block_desc *)(p_mode_parm_hdr + 1); + + /* Setup block size */ + p_block_desc->block_length[0] = 0x00; + p_block_desc->block_length[1] = 0x02; + p_block_desc->block_length[2] = 0x0a; + + cdb[4] = sizeof(struct ibmsis_block_desc) + + sizeof(struct ibmsis_mode_parm_hdr); + + fd = open(p_cur_ioa->dev[j].gen_name, O_RDWR); + + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->dev[j].gen_name); + continue; + } + + status = sg_ioctl(fd, cdb, + &ioctl_buffer, cdb[4], SG_DXFER_TO_DEV, + &sense_data, 30); + + if (status) + { + syslog(LOG_ERR, "Unable to change block size on device %s."IBMSIS_EOL, + p_cur_ioa->dev[j].dev_name); + close(fd); + continue; + } + else + { + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + memset(ioctl_buffer, 0, 255); + + p_mode_parm_hdr->block_desc_len = sizeof(struct ibmsis_block_desc); + + p_block_desc = (struct ibmsis_block_desc *)(p_mode_parm_hdr + 1); + + p_block_desc->block_length[0] = 0x00; + p_block_desc->block_length[1] = 0x02; + p_block_desc->block_length[2] = 0x00; + + cdb[4] = sizeof(struct ibmsis_block_desc) + + sizeof(struct ibmsis_mode_parm_hdr); + + status = sg_ioctl(fd, cdb, + &ioctl_buffer, cdb[4], SG_DXFER_TO_DEV, + &sense_data, 30); + + close(fd); + if (status) + { + syslog(LOG_ERR, "Unable to preserve block size on device %s."IBMSIS_EOL, + p_cur_ioa->dev[j].dev_name); + continue; + } + } + + can_init = p_resource_entry->format_allowed; + } + else + continue; + + if (can_init) + { + if (p_head_dev_to_init) + { + p_tail_dev_to_init->p_next = (struct devs_to_init_t *)malloc(sizeof(struct devs_to_init_t)); + p_tail_dev_to_init = p_tail_dev_to_init->p_next; + } + else + p_head_dev_to_init = p_tail_dev_to_init = (struct devs_to_init_t *)malloc(sizeof(struct devs_to_init_t)); + + memset(p_tail_dev_to_init, 0, sizeof(struct devs_to_init_t)); + + p_tail_dev_to_init->p_ioa = p_cur_ioa; + p_tail_dev_to_init->dev_type = dev_type; + p_tail_dev_to_init->change_size = change_size; + p_tail_dev_to_init->p_sis_device = &p_cur_ioa->dev[j]; + + len = print_dev_sel(p_resource_entry, buffer); + + start_y = num_devs % (max_size - 1); + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 1, 0, 0); + + set_field_userptr(pp_field[field_index++], dev_field); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 7, /* new field size */ + start_y, 7, 0, 0); + + set_field_buffer(pp_field[field_index], 0, buffer); + + field_opts_off(pp_field[field_index], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_userptr(pp_field[field_index++], NULL); + + if ((num_devs > 0) && ((num_devs % (max_size - 2)) == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + start_y + 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + memset(buffer, 0, 100); + + len = 0; + num_devs++; + } + } + } + + if (num_devs) + { + field_opts_off(p_fields[1], O_ACTIVE); + + init_index = ((max_size - 1) * 2) + 1; + for (i = init_index; i < field_index; i += init_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + flush_stdscr(); + clear(); + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + + while (1) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (ch == KEY_DOWN) + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else if (ch == KEY_UP) + { + form_driver(p_list_form, + REQ_PREV_FIELD); + break; + } + else if (IS_ENTER_KEY(ch)) + { + found = 0; + + unpost_form(p_list_form); + mvwaddstr(p_menu_win, 2, 1, " "); + wrefresh(p_menu_win); + p_cur_dev_to_init = p_head_dev_to_init; + + for (i = 0; i < field_index; i++) + { + + if (field_userptr(pp_field[i]) != NULL) + { + p_char = field_buffer(pp_field[i], 0); + if (strcmp(p_char, "1") == 0) + { + found = 1; + p_cur_dev_to_init->do_init = 1; + } + + p_cur_dev_to_init = p_cur_dev_to_init->p_next; + } + } + + if (found != 0) + { + /* Go to verification screen */ + unpost_form(p_form); + rc = confirm_init_device(); + } + else + { + post_form(p_list_form); + break; + } + + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if (IS_PGUP_KEY(ch)) + { + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if (ch == '\t') + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + break; + } + } + } + } + else + { + /* No devices to initialize */ + free_field(p_fields[0]); + return RC_NOOP; + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + + p_cur_dev_to_init = p_head_dev_to_init; + while(p_cur_dev_to_init) + { + p_cur_dev_to_init = p_cur_dev_to_init->p_next; + free(p_head_dev_to_init); + p_head_dev_to_init = p_cur_dev_to_init; + } + + free_screen(NULL, NULL, p_fields); + free_screen(NULL, NULL, pp_field); + free(pp_field); + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + flush_stdscr(); + return rc; +} + +int init_device() +{ +/* + Select Disk Units for Initialize and Format + +Type option, press Enter. + 1=Select + + Vendor Product Serial PCI PCI SCSI SCSI SCSI +OPT ID ID Number Bus Dev Bus ID Lun + IBM DFHSS4W 0024A0B9 05 03 0 3 0 + IBM DFHSS4W 00D38D0F 05 03 0 5 0 + IBM DFHSS4W 00D32240 05 03 0 9 0 + IBM DFHSS4W 00034563 05 03 0 6 0 + IBM DFHSS4W 00D37A11 05 03 0 4 0 + +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + Select Disk Units for Initialize and Format + +Type option, press Enter. + 1=Select + + Serial Frame Card PCI PCI SCSI SCSI SCSI +OPT Type Number ID Position Bus Dev Bus ID Lun + 6607 0024A0B9 03 D01 05 03 0 3 0 + 6607 00D38D0F 03 D02 05 03 0 5 0 + 6607 00D32240 03 D03 05 03 0 9 0 + 6607 00034563 03 D04 05 03 0 6 0 + 6717 00D37A11 03 D05 05 03 0 4 0 + +*/ + + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + int fd, rc, i, j, init_index, found, last_char; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_query_res_state res_state; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_device_record *p_device_record; + int can_init; + int dev_type; + char buffer[100]; + int max_size = curses_info.max_y - 10; + int num_devs = 0; + struct sis_ioa *p_cur_ioa; + char *p_char; + u32 len; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int field_index = 0; + int start_y; + struct devs_to_init_t *p_cur_dev_to_init; + + rc = RC_SUCCESS; + + p_title_win = newwin(7, curses_info.max_x, + 0, 0); + + p_menu_win = newwin(3, curses_info.max_x, + max_size + 7, 0); + + p_field_win = newwin(max_size, curses_info.max_x, 7, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Select Disk Units for Initialize and Format"); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + mvwaddstr(p_title_win, 2, 0, "Type option, press Enter."); + mvwaddstr(p_title_win, 3, 0, " 1=Select"); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 5, 0, + " Serial Frame Card PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "OPT Type Number ID Position Bus Dev Bus ID Lun"); + } + else + { + mvwaddstr(p_title_win, 5, 0, + " Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "OPT ID ID Number Bus Dev Bus ID Lun"); + } + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + check_current_config(false); + + for (p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + continue; + } + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + can_init = 1; + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + + /* If not a DASD, disallow format */ + if ((!IBMSIS_IS_DASD_DEVICE(p_resource_entry->std_inq_data)) || + (p_resource_entry->is_hot_spare)) + continue; + + /* If Advanced Function DASD */ + if (ibmsis_is_af_dasd_device(p_resource_entry)) + { + dev_type = IBMSIS_AF_DASD_DEVICE; + + p_device_record = (struct ibmsis_device_record *)p_cur_ioa->dev[j].p_qac_entry; + if (p_device_record && + (p_device_record->common.record_id == IBMSIS_RECORD_ID_DEVICE2_RECORD)) + { + /* We allow the user to format the drive if nobody is using it */ + if (p_cur_ioa->dev[j].opens != 0) + { + syslog(LOG_ERR, + "Format not allowed to %s, device in use"IBMSIS_EOL, + p_cur_ioa->dev[j].dev_name); + continue; + } + + if (p_resource_entry->is_array_member) + { + if (p_device_record->no_cfgte_vol) + can_init = 1; + else + can_init = 0; + } + else + { + can_init = p_resource_entry->format_allowed; + } + } + else + { + /* Do a query resource state */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &res_state; + ioa_cmd.buffer_len = sizeof(res_state); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_resource_entry->resource_address; + + memset(&res_state, 0, sizeof(res_state)); + + rc = sis_ioctl(fd, IBMSIS_QUERY_RESOURCE_STATE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Query Resource State to %s failed. %m"IBMSIS_EOL, p_cur_ioa->dev[j].dev_name); + continue; + } + + /* We allow the user to format the drive if + the device is read write protected. If the drive fails, then is replaced + concurrently it will be read write protected, but the system may still + have a use count for it. We need to allow the format to get the device + into a state where the system can use it */ + if ((p_cur_ioa->dev[j].opens != 0) && (!res_state.read_write_prot)) + { + syslog(LOG_ERR, "Format not allowed to %s, device in use"IBMSIS_EOL, p_cur_ioa->dev[j].dev_name); + continue; + } + + if (p_resource_entry->is_array_member) + { + /* If the device is an array member, only allow a format to it */ + /* if it is read/write protected by the IOA */ + if ((res_state.read_write_prot) && !(res_state.not_ready)) + can_init = 1; + else + can_init = 0; + } + else if ((res_state.not_oper) || (res_state.not_ready)) + { + /* Device is failed - cannot talk to the device */ + can_init = 0; + } + else + { + can_init = p_resource_entry->format_allowed; + } + } + } + else if (p_resource_entry->subtype == IBMSIS_SUBTYPE_GENERIC_SCSI) /* Is JBOD */ + { + /* We allow the user to format the drive if nobody is using it */ + if (p_cur_ioa->dev[j].opens != 0) + { + syslog(LOG_ERR, + "Format not allowed to %s, device in use"IBMSIS_EOL, + p_cur_ioa->dev[j].dev_name); + continue; + } + + dev_type = IBMSIS_JBOD_DASD_DEVICE; + can_init = p_resource_entry->format_allowed; + } + else + continue; + + if (can_init) + { + if (p_head_dev_to_init) + { + p_tail_dev_to_init->p_next = (struct devs_to_init_t *)malloc(sizeof(struct devs_to_init_t)); + p_tail_dev_to_init = p_tail_dev_to_init->p_next; + } + else + p_head_dev_to_init = p_tail_dev_to_init = (struct devs_to_init_t *)malloc(sizeof(struct devs_to_init_t)); + + memset(p_tail_dev_to_init, 0, sizeof(struct devs_to_init_t)); + + p_tail_dev_to_init->p_ioa = p_cur_ioa; + p_tail_dev_to_init->dev_type = dev_type; + p_tail_dev_to_init->p_sis_device = &p_cur_ioa->dev[j]; + p_tail_dev_to_init->change_size = 0; + + len = print_dev_sel(p_resource_entry, buffer); + + start_y = num_devs % (max_size - 1); + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 1, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)&p_cur_ioa->dev[j]); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 7, /* new field size */ + start_y, 7, 0, 0); + + set_field_buffer(pp_field[field_index], 0, buffer); + + field_opts_off(pp_field[field_index], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_userptr(pp_field[field_index++], NULL); + + if ((num_devs > 0) && ((num_devs % (max_size - 2)) == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + start_y + 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + memset(buffer, 0, 100); + + len = 0; + num_devs++; + } + } + close(fd); + } + + if (num_devs) + { + field_opts_off(p_fields[1], O_ACTIVE); + + init_index = ((max_size - 1) * 2) + 1; + for (i = init_index; i < field_index; i += init_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + flush_stdscr(); + clear(); + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + form_driver(p_list_form, + REQ_FIRST_FIELD); + wnoutrefresh(p_field_win); + doupdate(); + + while (1) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (ch == KEY_DOWN) + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else if (ch == KEY_UP) + { + form_driver(p_list_form, + REQ_PREV_FIELD); + break; + } + else if (IS_ENTER_KEY(ch)) + { + found = 0; + + unpost_form(p_list_form); + mvwaddstr(p_menu_win, 2, 1, " "); + wrefresh(p_menu_win); + p_cur_dev_to_init = p_head_dev_to_init; + + for (i = 0; i < field_index; i++) + { + + if (field_userptr(pp_field[i]) != NULL) + { + p_char = field_buffer(pp_field[i], 0); + if (strcmp(p_char, "1") == 0) + { + found = 1; + p_cur_dev_to_init->do_init = 1; + } + + p_cur_dev_to_init = p_cur_dev_to_init->p_next; + } + } + + if (found != 0) + { + /* Go to verification screen */ + unpost_form(p_form); + rc = confirm_init_device(); + } + else + { + post_form(p_list_form); + break; + } + + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if (IS_PGUP_KEY(ch)) + { + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if (ch == '\t') + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + break; + } + } + } + } + else + { + /* No devices to initialize */ + free_field(p_fields[0]); + return RC_NOOP; + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + + p_cur_dev_to_init = p_head_dev_to_init; + while(p_cur_dev_to_init) + { + p_cur_dev_to_init = p_cur_dev_to_init->p_next; + free(p_head_dev_to_init); + p_head_dev_to_init = p_cur_dev_to_init; + } + + free_screen(NULL, NULL, p_fields); + free_screen(NULL, NULL, pp_field); + free(pp_field); + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + flush_stdscr(); + return rc; +} + +#define MAX_CMD_LENGTH 1000 + +void log_menu() +{ + /* + Kernel Messages Log + + Select one of the following: + + 1. Use vi to view most recent IBM Storage error messages + 2. Use vi to view IBM Storage error messages + 3. Use vi to view all kernel error messages + 4. Use vi to view sisconfig error messages + 5. Set root kernel message log directory + 6. Set default editor + 7. Restore defaults + 8. Use vi to view IBM boot time messages + + + + + + Selection: + + e=Exit q=Cancel + + */ + FIELD *p_fields[3], *p_input_fields[4]; + FORM *p_form, *p_input_form; + FORM *p_old_form; + int invalid = 0; + char cmnd[MAX_CMD_LENGTH]; + int rc, i, j; + DIR *p_dir; + int dir_changed, editor_changed; + char short_editor[200], status[200]; + char *p_ch; + struct dirent **log_files; + struct dirent **pp_dirent; + int num_dir_entries; + int len, ch, show_op7; + struct stat file_stat; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 2, /* new field size */ + 12, 12, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + status[0] = '\0'; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Kernel Messages Log"); /* string value to set */ + post_form(p_form); + + sprintf(cmnd,"%s/boot.msg",log_root_dir); + rc = stat(cmnd, &file_stat); + if (rc) + { /* file does not exist */ + show_op7 = 0; + } + else + { + show_op7 = 1; + } + + + while(1) + { + strcpy(short_editor, editor); + p_ch = strchr(short_editor, ' '); + if (p_ch) + *p_ch = '\0'; + + mvaddstr(2, 0, "Select one of the following:"); + mvprintw(4, 0, " 1. Use %s to view most recent IBM Storage error messages", short_editor); + mvprintw(5, 0, " 2. Use %s to view IBM Storage error messages", short_editor); + mvprintw(6, 0, " 3. Use %s to view all kernel error messages", short_editor); + mvprintw(7, 0, " 4. Use %s to view sisconfig error messages", short_editor); + mvaddstr(8, 0, " 5. Set root kernel message log directory"); + mvaddstr(9, 0, " 6. Set default editor"); + mvaddstr(10, 0, " 7. Restore defaults"); + if (show_op7) + { + mvprintw(11,0, " 8. Use %s to view IBM Storage boot time messages", short_editor); + } + mvaddstr(12, 0, "Selection: "); + mvaddstr(curses_info.max_y - 2, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + if (status[0]) + { + mvprintw(curses_info.max_y - 1, 0, status); + status[0] = '\0'; + } + + if (invalid) + { + invalid = 0; + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + } + + flush_stdscr(); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + refresh(); + for (;;) + { + ch = getch(); + + if (IS_ENTER_KEY(ch)) + { + char *p_char; + refresh(); + unpost_form(p_form); + p_char = field_buffer(p_fields[1], 0); + + switch(p_char[0]) + { + case '1': + refresh(); + def_prog_mode(); + endwin(); + rc = system("rm -rf /tmp/.ibmsis.err; mkdir /tmp/.ibmsis.err"); + + if (rc != 0) + { + len = sprintf(cmnd, "cd %s; zcat -f messages", log_root_dir); + + len += sprintf(cmnd + len," | grep ibmsis-err | "); + len += sprintf(cmnd + len, "sed \"s/ `hostname -s` kernel: ibmsis-err//g\" | "); + len += sprintf(cmnd + len, "sed \"s/ localhost kernel: ibmsis-err//g\" | "); + len += sprintf(cmnd + len, "sed \"s/ kernel: ibmsis-err//g\" | "); + len += sprintf(cmnd + len, "sed \"s/ eldrad//g\" | "); /* xx */ + len += sprintf(cmnd + len, "sed \"s/\\^M//g\" | "); + len += sprintf(cmnd + len, FAILSAFE_EDITOR); + closelog(); + openlog("sisconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + syslog(LOG_ERR, "Error encountered concatenating log files..."IBMSIS_EOL); + syslog(LOG_ERR, "Using failsafe editor..."IBMSIS_EOL); + closelog(); + openlog("sisconfig", LOG_PID | LOG_CONS, LOG_USER); + sleep(3); + } + else + { + len = sprintf(cmnd,"cd %s; zcat -f messages | grep ibmsis-err |", log_root_dir); + len += sprintf(cmnd + len, "sed \"s/ `hostname -s` kernel: ibmsis-err//g\""); + len += sprintf(cmnd + len, " | sed \"s/ localhost kernel: ibmsis-err//g\""); + len += sprintf(cmnd + len, " | sed \"s/ kernel: ibmsis-err//g\""); + len += sprintf(cmnd + len, "| sed \"s/ eldrad//g\""); /* xx */ + len += sprintf(cmnd + len, " | sed \"s/\\^M//g\" "); + len += sprintf(cmnd + len, ">> /tmp/.ibmsis.err/errors"); + system(cmnd); + + sprintf(cmnd, "%s /tmp/.ibmsis.err/errors", editor); + } + rc = system(cmnd); + + mvaddstr(curses_info.max_y - 1, 0, " "); + post_form(p_form); + if ((rc != 0) && (rc != 127)) + sprintf(status, " Editor returned %d. Try setting the default editor", rc); + + break; + case '2': + refresh(); + def_prog_mode(); + endwin(); + num_dir_entries = scandir(log_root_dir, &log_files, select_log_file, compare_log_file); + rc = system("rm -rf /tmp/.ibmsis.err; mkdir /tmp/.ibmsis.err"); + if (num_dir_entries) + pp_dirent = log_files; + + if (rc != 0) + { + len = sprintf(cmnd, "cd %s; zcat -f ", log_root_dir); + + /* Probably have a read-only root file system */ + for (i = 0; i < num_dir_entries; i++) + { + len += sprintf(cmnd + len, "%s ", (*pp_dirent)->d_name); + pp_dirent++; + } + + len += sprintf(cmnd + len," | grep ibmsis-err | "); + len += sprintf(cmnd + len, "sed \"s/ `hostname -s` kernel: ibmsis-err//g\" | "); + len += sprintf(cmnd + len, "sed \"s/ localhost kernel: ibmsis-err//g\" | "); + len += sprintf(cmnd + len, "sed \"s/ kernel: ibmsis-err//g\" | "); + len += sprintf(cmnd + len, "sed \"s/ eldrad//g\" | "); /* xx */ + len += sprintf(cmnd + len, "sed \"s/\\^M//g\" | "); + len += sprintf(cmnd + len, FAILSAFE_EDITOR); + closelog(); + openlog("sisconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + syslog(LOG_ERR, "Error encountered concatenating log files..."IBMSIS_EOL); + syslog(LOG_ERR, "Using failsafe editor..."IBMSIS_EOL); + closelog(); + openlog("sisconfig", LOG_PID | LOG_CONS, LOG_USER); + sleep(3); + } + else + { + for (i = 0; i < num_dir_entries; i++) + { + len = sprintf(cmnd,"cd %s; zcat -f %s | grep ibmsis-err |", log_root_dir, (*pp_dirent)->d_name); + len += sprintf(cmnd + len, "sed \"s/ `hostname -s` kernel: ibmsis-err//g\""); + len += sprintf(cmnd + len, " | sed \"s/ localhost kernel: ibmsis-err//g\""); + len += sprintf(cmnd + len, " | sed \"s/ kernel: ibmsis-err//g\""); + len += sprintf(cmnd + len, "| sed \"s/ eldrad//g\""); /* xx */ + len += sprintf(cmnd + len, " | sed \"s/\\^M//g\" "); + len += sprintf(cmnd + len, ">> /tmp/.ibmsis.err/errors"); + system(cmnd); + pp_dirent++; + } + + sprintf(cmnd, "%s /tmp/.ibmsis.err/errors", editor); + } + rc = system(cmnd); + + free(*log_files); + mvaddstr(curses_info.max_y - 1, 0, " "); + post_form(p_form); + if ((rc != 0) && (rc != 127)) + sprintf(status, " Editor returned %d. Try setting the default editor", rc); + + break; + case '3': + refresh(); + def_prog_mode(); + endwin(); + num_dir_entries = scandir(log_root_dir, &log_files, select_log_file, compare_log_file); + if (num_dir_entries) + pp_dirent = log_files; + + rc = system("rm -rf /tmp/.ibmsis.err; mkdir /tmp/.ibmsis.err"); + + if (rc != 0) + { + /* Probably have a read-only root file system */ + len = sprintf(cmnd, "cd %s; zcat -f ", log_root_dir); + + /* Probably have a read-only root file system */ + for (i = 0; i < num_dir_entries; i++) + { + len += sprintf(cmnd + len, "%s ", (*pp_dirent)->d_name); + pp_dirent++; + } + + len += sprintf(cmnd + len, " | sed \"s/\\^M//g\" "); + len += sprintf(cmnd + len, "| %s", FAILSAFE_EDITOR); + closelog(); + openlog("sisconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + syslog(LOG_ERR, "Error encountered concatenating log files..."IBMSIS_EOL); + syslog(LOG_ERR, "Using failsafe editor..."IBMSIS_EOL); + openlog("sisconfig", LOG_PID | LOG_CONS, LOG_USER); + sleep(3); + } + else + { + for (i = 0; i < num_dir_entries; i++) + { + sprintf(cmnd, + "cd %s; zcat -f %s | sed \"s/\\^M//g\" >> /tmp/.ibmsis.err/errors", + log_root_dir, (*pp_dirent)->d_name); + system(cmnd); + pp_dirent++; + } + + sprintf(cmnd, "%s /tmp/.ibmsis.err/errors", editor); + } + + rc = system(cmnd); + free(*log_files); + mvaddstr(curses_info.max_y - 1, 0, " "); + post_form(p_form); + if ((rc != 0) && (rc != 127)) + sprintf(status, " Editor returned %d. Try setting the default editor", rc); + break; + case '4': + refresh(); + def_prog_mode(); + endwin(); + num_dir_entries = scandir(log_root_dir, &log_files, select_log_file, compare_log_file); + rc = system("rm -rf /tmp/.ibmsis.err; mkdir /tmp/.ibmsis.err"); + if (num_dir_entries) + pp_dirent = log_files; + + if (rc != 0) + { + len = sprintf(cmnd, "cd %s; zcat -f ", log_root_dir); + + /* Probably have a read-only root file system */ + for (i = 0; i < num_dir_entries; i++) + { + len += sprintf(cmnd + len, "%s ", (*pp_dirent)->d_name); + pp_dirent++; + } + + len += sprintf(cmnd + len," | grep sisconfig | "); + len += sprintf(cmnd + len, FAILSAFE_EDITOR); + closelog(); + openlog("sisconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + syslog(LOG_ERR, "Error encountered concatenating log files..."IBMSIS_EOL); + syslog(LOG_ERR, "Using failsafe editor..."IBMSIS_EOL); + openlog("sisconfig", LOG_PID | LOG_CONS, LOG_USER); + sleep(3); + } + else + { + for (i = 0; i < num_dir_entries; i++) + { + len = sprintf(cmnd,"cd %s; zcat -f %s | grep sisconfig ", log_root_dir, (*pp_dirent)->d_name); + len += sprintf(cmnd + len, ">> /tmp/.ibmsis.err/errors"); + system(cmnd); + pp_dirent++; + } + + sprintf(cmnd, "%s /tmp/.ibmsis.err/errors", editor); + } + rc = system(cmnd); + free(*log_files); + + mvaddstr(curses_info.max_y - 1, 0, " "); + post_form(p_form); + if ((rc != 0) && (rc != 127)) + sprintf(status, " Editor returned %d. Try setting the default editor", rc); + + break; + case '5': + dir_changed = 0; + + /* Title */ + p_input_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_input_fields[1] = new_field(1, 40, /* new field size */ + 11, 24, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_input_fields[2] = new_field(1, 2, /* new field size */ + 12, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_input_fields[3] = NULL; + + p_input_form = new_form(p_input_fields); + + set_field_just(p_input_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_input_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_input_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Kernel Messages Log Root Directory"); /* string value to set */ + + form_opts_off(p_input_form, O_BS_OVERLOAD); + + flush_stdscr(); + + post_form(p_input_form); + + mvprintw(10, 0, "Current root directory: %s", log_root_dir); + mvaddstr(11, 0, "New root directory: "); + mvaddstr(13, 0, "Enter new directory and press Enter"); + mvaddstr(14, 0, "Or leave blank and press Enter to cancel"); + + set_current_field(p_input_form, p_input_fields[1]); + refresh(); + + while(1) + { + char *p_char, *p_tmp; + int len; + int ch = getch(); + + if (IS_ENTER_KEY(ch)) + { + flush_stdscr(); + form_driver(p_input_form, REQ_FIRST_FIELD ); + unpost_form(p_input_form); + p_char = field_buffer(p_input_fields[1], 0); + len = strlen(p_char); + p_tmp = p_char + len - 1; + while(*p_tmp == ' ') + p_tmp--; + p_tmp++; + *p_tmp = '\0'; + p_dir = opendir(p_char); + if (p_char[0] == '\0') + { + break; + } + else if (p_dir == NULL) + { + post_form(p_input_form); + mvprintw(10, 0, "Current root directory: %s", log_root_dir); + mvaddstr(11, 0, "New root directory: "); + mvaddstr(13, 0, "Enter new directory and press Enter"); + mvaddstr(14, 0, "Or leave blank and press Enter to cancel"); + mvprintw(curses_info.max_y - 1, 0, " Invalid directory %s", p_char); + set_current_field(p_input_form, p_input_fields[1]); + + refresh(); + } + else + { + closedir(p_dir); + if (strcmp(log_root_dir, p_char) != 0) + { + werase(stdscr); + set_field_buffer(p_input_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Confirm Root Directory Change"); /* string value to set */ + + post_form(p_input_form); + mvprintw(11, 0, "New root directory: %s ", p_char); + mvprintw(curses_info.max_y - 2, 0, + "c=Confirm "CANCEL_KEY_LABEL"=Cancel"); + set_current_field(p_input_form, p_input_fields[2]); + + refresh(); + + while(1) + { + int ch = getch(); + if ((ch == 'c') || (ch == 'C')) + { + strcpy(log_root_dir, p_char); + dir_changed = 1; + break; + } + else if (IS_CANCEL_KEY(ch)) + { + dir_changed = 0; + break; + } + } + } + break; + } + } + else if (ch == KEY_RIGHT) + form_driver(p_input_form, REQ_NEXT_CHAR); + else if (ch == KEY_LEFT) + form_driver(p_input_form, REQ_PREV_CHAR); + else if ((ch == KEY_BACKSPACE) || (ch == 127)) + form_driver(p_input_form, REQ_DEL_PREV); + else if (ch == KEY_DC) + form_driver(p_input_form, REQ_DEL_CHAR); + else if (ch == KEY_IC) + form_driver(p_input_form, REQ_INS_MODE); + else if (ch == KEY_EIC) + form_driver(p_input_form, REQ_OVL_MODE); + else if (ch == KEY_HOME) + form_driver(p_input_form, REQ_BEG_FIELD); + else if (ch == KEY_END) + form_driver(p_input_form, REQ_END_FIELD); + else if (isascii(ch)) + form_driver(p_input_form, ch); + refresh(); + } + unpost_form(p_input_form); + free_form(p_input_form); + free_screen(NULL, NULL, p_input_fields); + if (rc == RC_EXIT) + goto leave; + post_form(p_form); + if (dir_changed) + sprintf(status, " Root directory changed to %s", log_root_dir); + else + sprintf(status, " Root directory unchanged"); + break; + case '6': + editor_changed = 0; + + /* Title */ + p_input_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_input_fields[1] = new_field(1, 40, /* new field size */ + 11, 16, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_input_fields[2] = new_field(1, 2, /* new field size */ + 12, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_input_fields[3] = NULL; + + p_input_form = new_form(p_input_fields); + + set_field_just(p_input_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_input_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_input_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Kernel Messages Editor"); /* string value to set */ + + form_opts_off(p_input_form, O_BS_OVERLOAD); + + post_form(p_input_form); + + mvprintw(10, 0, "Current editor: %s", editor); + mvaddstr(11, 0, "New editor: "); + mvaddstr(14, 0, "Enter new editor command and press Enter"); + mvaddstr(15, 0, "Or leave blank and press Enter to cancel"); + set_current_field(p_input_form, p_input_fields[1]); + refresh(); + + while(1) + { + char *p_char, *p_tmp; + int len; + int ch = getch(); + + if (IS_ENTER_KEY(ch)) + { + form_driver(p_input_form, REQ_FIRST_FIELD ); + unpost_form(p_input_form); + p_char = field_buffer(p_input_fields[1], 0); + len = strlen(p_char); + p_tmp = p_char + len - 1; + while(*p_tmp == ' ') + p_tmp--; + p_tmp++; + *p_tmp = '\0'; + if ((strcmp(editor, p_char) != 0) && (strlen(p_char) > 0)) + { + werase(stdscr); + set_field_buffer(p_input_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Confirm Editor Change"); /* string value to set */ + + post_form(p_input_form); + mvprintw(11, 0, "New editor: %s ", p_char); + mvprintw(curses_info.max_y - 2, 0, + "c=Confirm "CANCEL_KEY_LABEL"=Cancel"); + set_current_field(p_input_form, p_input_fields[2]); + refresh(); + + while(1) + { + int ch = getch(); + if ((ch == 'c') || (ch == 'C')) + { + strcpy(editor, p_char); + editor_changed = 1; + break; + } + else if (IS_CANCEL_KEY(ch)) + { + editor_changed = 0; + break; + } + } + } + break; + } + else if (ch == KEY_RIGHT) + form_driver(p_input_form, REQ_NEXT_CHAR); + else if (ch == KEY_LEFT) + form_driver(p_input_form, REQ_PREV_CHAR); + else if ((ch == KEY_BACKSPACE) || (ch == 127)) + form_driver(p_input_form, REQ_DEL_PREV); + else if (ch == KEY_DC) + form_driver(p_input_form, REQ_DEL_CHAR); + else if (ch == KEY_IC) + form_driver(p_input_form, REQ_INS_MODE); + else if (ch == KEY_EIC) + form_driver(p_input_form, REQ_OVL_MODE); + else if (ch == KEY_HOME) + form_driver(p_input_form, REQ_BEG_FIELD); + else if (ch == KEY_END) + form_driver(p_input_form, REQ_END_FIELD); + else if (isascii(ch)) + form_driver(p_input_form, ch); + refresh(); + } + unpost_form(p_input_form); + free_form(p_input_form); + free_screen(NULL, NULL, p_input_fields); + if (rc == RC_EXIT) + goto leave; + post_form(p_form); + if (editor_changed) + sprintf(status, " Editor changed to %s", editor); + else + sprintf(status, " Editor unchanged"); + break; + case '7': + strcpy(log_root_dir, DEFAULT_LOG_DIR); + strcpy(editor, DEFAULT_EDITOR); + break; + case '8': + if (show_op7 == 0) + { + post_form(p_form); + if (isdigit(p_char[0])) + sprintf(status, "Invalid option specified."); + break; + } + + refresh(); + def_prog_mode(); + endwin(); + rc = system("rm -rf /tmp/.ibmsis.err; mkdir /tmp/.ibmsis.err"); + + if (rc != 0) + { + len = sprintf(cmnd, "cd %s; zcat -f ", log_root_dir); + + /* Probably have a read-only root file system */ + len += sprintf(cmnd + len, "boot.msg"); + len += sprintf(cmnd + len," | grep ibmsis |"); + len += sprintf(cmnd + len, FAILSAFE_EDITOR); + closelog(); + openlog("sisconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + syslog(LOG_ERR, "Error encountered concatenating log files..."IBMSIS_EOL); + syslog(LOG_ERR, "Using failsafe editor..."IBMSIS_EOL); + closelog(); + openlog("sisconfig", LOG_PID | LOG_CONS, LOG_USER); + sleep(3); + } + else + { + len = sprintf(cmnd,"cd %s; zcat -f boot.msg | grep ibmsis | " + "sed 's/<[0-9]>ibmsis-err: //g' | sed 's/<[0-9]>ibmsis: //g'", + log_root_dir); + len += sprintf(cmnd + len, ">> /tmp/.ibmsis.err/errors"); + system(cmnd); + sprintf(cmnd, "%s /tmp/.ibmsis.err/errors", editor); + } + rc = system(cmnd); + + mvaddstr(curses_info.max_y - 1, 0, " "); + post_form(p_form); + if ((rc != 0) && (rc != 127)) + sprintf(status, " Editor returned %d. Try setting the default editor", rc); + + break; + default: + post_form(p_form); + if (isdigit(p_char[0])) + sprintf(status, "Invalid option specified."); + break; + } + flush_stdscr(); + unpost_form(p_form); + clear(); + post_form(p_form); + form_driver(p_form, ' '); + break; + } + else if (IS_EXIT_KEY(ch)) + { + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + goto leave; + } + else + { + form_driver(p_form, ch); + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + for (j=0; j < 2; j++) + free_field(p_fields[j]); + flush_stdscr(); + return; +} + +int select_log_file(const struct dirent *p_dir_entry) +{ + if (p_dir_entry) + { + if (strstr(p_dir_entry->d_name, "messages") == p_dir_entry->d_name) + return 1; + } + return 0; +} + +int compare_log_file(const void *pp_f, const void *pp_s) +{ + char *p_first_start_num, *p_first_end_num; + char *p_second_start_num, *p_second_end_num; + struct dirent **pp_first, **pp_second; + char name1[100], name2[100]; + int first, second; + + pp_first = (struct dirent **)pp_f; + pp_second = (struct dirent **)pp_s; + + if (strcmp((*pp_first)->d_name, "messages") == 0) + return 1; + if (strcmp((*pp_second)->d_name, "messages") == 0) + return -1; + + strcpy(name1, (*pp_first)->d_name); + strcpy(name2, (*pp_second)->d_name); + p_first_start_num = strchr(name1, '.'); + p_first_end_num = strrchr(name1, '.'); + p_second_start_num = strchr(name2, '.'); + p_second_end_num = strrchr(name2, '.'); + + if (p_first_start_num == p_first_end_num) + { + /* Not compressed */ + p_first_end_num = name1 + strlen(name1); + p_second_end_num = name2 + strlen(name2); + } + else + { + *p_first_end_num = '\0'; + *p_second_end_num = '\0'; + } + first = strtoul(p_first_start_num, NULL, 10); + second = strtoul(p_second_start_num, NULL, 10); + + if (first > second) + return -1; + else + return 1; +} + +int confirm_init_device() +{ +/* + Confirm Initialize and Format Disk Unit + +Press 'c' to confirm your choice for 1=Initialize and format. +Press q to return to change your choice. + + Vendor Product Serial PCI PCI SCSI SCSI SCSI +Option ID ID Number Bus Dev Bus ID Lun + IBM DFHSS4W 0024A0B9 05 03 0 3 0 + IBM DFHSS4W 00D38D0F 05 03 0 5 0 + IBM DFHSS4W 00D32240 05 03 0 9 0 + IBM DFHSS4W 00034563 05 03 0 6 0 + IBM DFHSS4W 00D37A11 05 03 0 4 0 + +c=Confirm q=Cancel f=PageDn b=PageUp + +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + Confirm Initialize and Format Disk Unit + +Press 'c' to confirm your choice for 1=Initialize and format. +Press q to return to change your choice. + + Serial Frame Card PCI PCI SCSI SCSI SCSI +Option Type Number ID Position Bus Dev Bus ID Lun + 6607 0024A0B9 03 D01 05 03 0 3 0 + 6607 00D38D0F 03 D02 05 03 0 5 0 + 6607 00D32240 03 D03 05 03 0 9 0 + 6607 00034563 03 D04 05 03 0 6 0 + 6717 00D37A11 03 D05 05 03 0 4 0 + +c=Confirm q=Cancel f=PageDn b=PageUp + + + +*/ + + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + char buffer[100]; + int max_size = curses_info.max_y - 7 - 3 - 1; + struct window_l *p_head_win, *p_tail_win; + struct panel_l *p_head_panel, *p_tail_panel, *p_cur_panel; + WINDOW *p_title_win, *p_menu_win; + struct devs_to_init_t *p_cur_dev_to_init; + u32 len; + u32 num_devs = 0; + int rc = RC_SUCCESS; + PANEL *p_panel; + int send_dev_inits(u8 num_devs); + + p_title_win = newwin(7, curses_info.max_x, + curses_info.start_y, curses_info.start_x); + + p_menu_win = newwin(3, curses_info.max_x, + curses_info.start_y + max_size + 7 + 1, curses_info.start_x); + + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Confirm Initialize and Format Disk Unit"); + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + p_head_win = p_tail_win = (struct window_l *)malloc(sizeof(struct window_l)); + p_head_panel = p_tail_panel = (struct panel_l *)malloc(sizeof(struct panel_l)); + + p_head_win->p_win = newwin(max_size + 1, curses_info.max_x, + curses_info.start_y + 7, curses_info.start_x); + p_head_win->p_next = NULL; + + p_head_panel->p_panel = new_panel(p_head_win->p_win); + p_head_panel->p_next = NULL; + + mvwaddstr(p_title_win, 2, 0, "Press 'c' to confirm your choice for 1=Initialize and format."); + mvwaddstr(p_title_win, 3, 0, "Press "CANCEL_KEY_LABEL" to return to change your choice."); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 5, 0, + " Serial Frame Card PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "Option Type Number ID Position Bus Dev Bus ID Lun"); + } + else + { + mvwaddstr(p_title_win, 5, 0, + " Vendor Product Serial PCI PCI SCSI SCSI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "Option ID ID Number Bus Dev Bus ID Lun"); + } + mvwaddstr(p_menu_win, 1, 0, "c=Confirm "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_cur_dev_to_init = p_head_dev_to_init; + + while(p_cur_dev_to_init) + { + if (p_cur_dev_to_init->do_init) + { + len = sprintf(buffer, " 1 "); + len += print_dev_sel(p_cur_dev_to_init->p_sis_device->p_resource_entry, + buffer + len); + + if ((num_devs > 0) && ((num_devs % max_size) == 0)) + { + mvwaddstr(p_tail_win->p_win, max_size, curses_info.max_x - 8, "More..."); + + p_tail_win->p_next = (struct window_l *)malloc(sizeof(struct window_l)); + p_tail_win = p_tail_win->p_next; + + p_tail_panel->p_next = (struct panel_l *)malloc(sizeof(struct panel_l)); + p_tail_panel = p_tail_panel->p_next; + + p_tail_win->p_win = newwin(max_size + 1, curses_info.max_x, + curses_info.start_y + 7, curses_info.start_x); + p_tail_win->p_next = NULL; + + p_tail_panel->p_panel = new_panel(p_tail_win->p_win); + p_tail_panel->p_next = NULL; + } + + mvwaddstr(p_tail_win->p_win, num_devs % max_size, 0, buffer); + memset(buffer, 0, 100); + num_devs++; + } + p_cur_dev_to_init = p_cur_dev_to_init->p_next; + } + + p_cur_panel = p_head_panel; + + while(p_cur_panel) + { + bottom_panel(p_cur_panel->p_panel); + p_cur_panel = p_cur_panel->p_next; + } + + form_driver(p_form, /* form to pass input to */ + REQ_FIRST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + while (1) + { + form_driver(p_form, /* form to pass input to */ + REQ_FIRST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_REFRESH; + goto leave; + } + else if ((ch == 'c') || (ch == 'C')) + { + form_driver(p_form, /* form to pass input to */ + REQ_FIRST_FIELD ); /* form request code */ + + wnoutrefresh(stdscr); + update_panels(); + mvwaddstr(p_menu_win, 2, 0, " Please wait for the next screen."); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + doupdate(); + rc = send_dev_inits(num_devs); + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + p_panel = panel_below(NULL); + if (p_panel != p_tail_panel->p_panel) + { + bottom_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + p_panel = panel_above(NULL); + if (p_panel != p_tail_panel->p_panel) + { + top_panel(p_panel); + update_panels(); + doupdate(); + } + break; + } + else + { + break; + } + } + } + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(p_head_panel, p_head_win, p_fields); + delwin(p_title_win); + delwin(p_menu_win); + flush_stdscr(); + return rc; +} + +int send_dev_inits(u8 num_devs) +{ + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct devs_to_init_t *p_cur_dev_to_init; + int rc, fd, fdev, pid; + struct ibmsis_query_res_state res_state; + u8 ioctl_buffer[IOCTL_BUFFER_SIZE]; + u8 ioctl_buffer2[IOCTL_BUFFER_SIZE]; + struct ibmsis_control_mode_page *p_control_mode_page; + struct ibmsis_control_mode_page *p_control_mode_page_changeable; + struct ibmsis_mode_parm_hdr *p_mode_parm_hdr; + struct ibmsis_block_desc *p_block_desc; + struct sense_data_t sense_data; + struct ibmsis_resource_entry *p_resource_entry; + int status, arg; + int loop, len, opens; + u8 remaining_devs = num_devs; + u8 defect_list_hdr[4]; + u8 cdb[IBMSIS_CCB_CDB_LEN]; + u8 *p_char; + int is_520_block = 0; + + int dev_init_complete(u8 num_devs); + + for (p_cur_dev_to_init = p_head_dev_to_init; + p_cur_dev_to_init != NULL; + p_cur_dev_to_init = p_cur_dev_to_init->p_next) + { + if ((p_cur_dev_to_init->do_init) && + (p_cur_dev_to_init->dev_type == IBMSIS_AF_DASD_DEVICE)) + { + fd = open(p_cur_dev_to_init->p_ioa->ioa.dev_name, O_RDWR); + + if (fd < 0) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_ioa->ioa.dev_name); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &res_state; + ioa_cmd.buffer_len = sizeof(res_state); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_cur_dev_to_init->p_sis_device->p_resource_entry->resource_address; + + memset(&res_state, 0, sizeof(res_state)); + + rc = sis_ioctl(fd, IBMSIS_QUERY_RESOURCE_STATE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, + "Query Resource State to %s failed. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + p_resource_entry = p_cur_dev_to_init->p_sis_device->p_resource_entry; + opens = num_device_opens(p_cur_dev_to_init->p_ioa->host_num, + p_resource_entry->resource_address.bus, + p_resource_entry->resource_address.target, + p_resource_entry->resource_address.lun); + + if ((opens != 0) && (!res_state.read_write_prot)) + { + syslog(LOG_ERR, + "Cannot obtain exclusive access to %s"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + if (!p_cur_dev_to_init->p_sis_device->p_resource_entry->is_hidden) + { + fdev = open(p_cur_dev_to_init->p_sis_device->dev_name, O_RDWR | O_NONBLOCK); + + if (fdev) + { + fcntl(fdev, F_SETFD, 0); + if (flock(fdev, LOCK_EX)) + syslog(LOG_ERR, + "Could not set lock for %s. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + } + + p_cur_dev_to_init->fd = fdev; + } + + /* Mode sense */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = ioctl_buffer; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0x0a; + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_cur_dev_to_init->p_sis_device->p_resource_entry->resource_address; + + rc = sis_ioctl(fd, MODE_SENSE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + sislog_location(p_cur_dev_to_init->p_sis_device->p_resource_entry); + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + /* Mode sense - changeable parms */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = ioctl_buffer2; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0x4a; + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_cur_dev_to_init->p_sis_device->p_resource_entry->resource_address; + + rc = sis_ioctl(fd, MODE_SENSE, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + sislog_location(p_cur_dev_to_init->p_sis_device->p_resource_entry); + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + + p_block_desc = (struct ibmsis_block_desc *)(p_mode_parm_hdr + 1); + if ((p_block_desc->block_length[0] == 0x00) && + (p_block_desc->block_length[1] == 0x02) && + (p_block_desc->block_length[2] == 0x08)) + /* block size is 520 */ + is_520_block = 1; + + p_control_mode_page = (struct ibmsis_control_mode_page *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer2; + + p_control_mode_page_changeable = (struct ibmsis_control_mode_page *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + + /* Turn off QERR since some drives do not like QERR + and IMMED bit at the same time. */ + IBMSIS_SET_MODE(p_control_mode_page_changeable->qerr, + p_control_mode_page->qerr, 0); + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = ioctl_buffer; + ioa_cmd.buffer_len = p_mode_parm_hdr->length + 1; + p_mode_parm_hdr->length = 0; + p_mode_parm_hdr->medium_type = 0; + p_mode_parm_hdr->device_spec_parms = 0; + p_control_mode_page->header.parms_saveable = 0; + ioa_cmd.read_not_write = 0; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_cur_dev_to_init->p_sis_device->p_resource_entry->resource_address; + rc = sis_ioctl(fd, MODE_SELECT, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Mode Select %s to disable qerr failed. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + sislog_location(p_cur_dev_to_init->p_sis_device->p_resource_entry); + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + /* Issue mode select to change block size */ + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + memset(ioctl_buffer, 0, 255); + + p_mode_parm_hdr->block_desc_len = sizeof(struct ibmsis_block_desc); + + p_block_desc = (struct ibmsis_block_desc *)(p_mode_parm_hdr + 1); + + /* Setup block size */ + p_block_desc->block_length[0] = 0x00; + p_block_desc->block_length[1] = 0x02; + + if (p_cur_dev_to_init->change_size == SIS_512_BLOCK) + p_block_desc->block_length[2] = 0x00; + else if (is_520_block) + p_block_desc->block_length[2] = 0x08; + else + p_block_desc->block_length[2] = 0x0a; + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = ioctl_buffer; + ioa_cmd.buffer_len = sizeof(struct ibmsis_block_desc) + + sizeof(struct ibmsis_mode_parm_hdr); + ioa_cmd.read_not_write = 0; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_cur_dev_to_init->p_sis_device->p_resource_entry->resource_address; + rc = sis_ioctl(fd, MODE_SELECT, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Mode Select to %s failed. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + sislog_location(p_cur_dev_to_init->p_sis_device->p_resource_entry); + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + pid = fork(); + if (pid) + { + /* Do nothing */ + } + else + { + /* Issue the format. Failure will be detected by query command status */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + ioa_cmd.buffer = NULL; + ioa_cmd.buffer_len = 0; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_cur_dev_to_init->p_sis_device->p_resource_entry->resource_address; + sis_ioctl(fd, FORMAT_UNIT, &ioa_cmd); + close(fd); + exit(0); + } + } + else if ((p_cur_dev_to_init->do_init) && + (p_cur_dev_to_init->dev_type == IBMSIS_JBOD_DASD_DEVICE)) + { + p_resource_entry = p_cur_dev_to_init->p_sis_device->p_resource_entry; + opens = num_device_opens(p_cur_dev_to_init->p_ioa->host_num, + p_resource_entry->resource_address.bus, + p_resource_entry->resource_address.target, + p_resource_entry->resource_address.lun); + + if (opens != 0) + { + syslog(LOG_ERR, + "Cannot obtain exclusive access to %s"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + /* Issue mode sense to get the control mode page */ + cdb[0] = MODE_SENSE; + cdb[2] = 0x0a; /* PC = current values, page code = 0ah */ + cdb[4] = 255; + + fd = open(p_cur_dev_to_init->p_sis_device->gen_name, O_RDWR); + + status = sg_ioctl(fd, cdb, + &ioctl_buffer, 255, SG_DXFER_FROM_DEV, + &sense_data, 30); + + if (status) + { + syslog(LOG_ERR, + "Could not send mode sense to %s. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->gen_name); + sislog_location(p_cur_dev_to_init->p_sis_device->p_resource_entry); + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + /* Issue mode sense to get the control mode page */ + cdb[0] = MODE_SENSE; + cdb[2] = 0x4a; /* PC = changeable values, page code = 0ah */ + cdb[4] = 255; + + status = sg_ioctl(fd, cdb, + &ioctl_buffer2, 255, SG_DXFER_FROM_DEV, + &sense_data, 30); + + if (status) + { + syslog(LOG_ERR, + "Could not send mode sense to %s. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->gen_name); + sislog_location(p_cur_dev_to_init->p_sis_device->p_resource_entry); + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer2; + + p_control_mode_page_changeable = (struct ibmsis_control_mode_page *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + + p_control_mode_page = (struct ibmsis_control_mode_page *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + /* Turn off QERR since some drives do not like QERR + and IMMED bit at the same time. */ + IBMSIS_SET_MODE(p_control_mode_page_changeable->qerr, + p_control_mode_page->qerr, 0); + + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + /* Issue mode select to set page x0A */ + cdb[0] = MODE_SELECT; + cdb[1] = 0x10; /* PF = 1, SP = 0 */ + cdb[4] = p_mode_parm_hdr->length + 1; + + p_mode_parm_hdr->length = 0; + p_control_mode_page->header.parms_saveable = 0; + p_mode_parm_hdr->medium_type = 0; + p_mode_parm_hdr->device_spec_parms = 0; + + status = sg_ioctl(fd, cdb, + &ioctl_buffer, cdb[4], SG_DXFER_TO_DEV, + &sense_data, 30); + + if (status) + { + syslog(LOG_ERR, + "Could not send mode select to %s."IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->gen_name); + sislog_location(p_cur_dev_to_init->p_sis_device->p_resource_entry); + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + /* Issue mode select to setup block size */ + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + memset(ioctl_buffer, 0, 255); + + p_mode_parm_hdr->block_desc_len = sizeof(struct ibmsis_block_desc); + + p_block_desc = (struct ibmsis_block_desc *)(p_mode_parm_hdr + 1); + + /* Setup block size */ + p_block_desc->block_length[0] = 0x00; + p_block_desc->block_length[1] = 0x02; + + if (p_cur_dev_to_init->change_size == SIS_522_BLOCK) + p_block_desc->block_length[2] = 0x0a; + else + p_block_desc->block_length[2] = 0x00; + + cdb[4] = sizeof(struct ibmsis_block_desc) + + sizeof(struct ibmsis_mode_parm_hdr); + + status = sg_ioctl(fd, cdb, + &ioctl_buffer, cdb[4], SG_DXFER_TO_DEV, + &sense_data, 30); + + if (status) + { + syslog(LOG_ERR, "Could not send mode select to %s to change blocksize."IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->gen_name); + sislog_location(p_cur_dev_to_init->p_sis_device->p_resource_entry); + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + + /* Issue format */ + memset(defect_list_hdr, 0, sizeof(defect_list_hdr)); + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + defect_list_hdr[1] = 0x02; /* FOV = 0, DPRY = 0, DCRT = 0, STPF = 0, IP = 0, DSP = 0, Immed = 1, VS = 0 */ + + /* Issue mode sense to get the control mode page */ + cdb[0] = FORMAT_UNIT; + cdb[1] = 0x10; /* lun = 0, fmtdata = 1, cmplst = 0, defect list format = 0 */ + + status = sg_ioctl(fd, cdb, + &defect_list_hdr, 4, SG_DXFER_TO_DEV, + &sense_data, 30); + + if (status) + { + syslog(LOG_ERR, "Could not send format unit to %s."IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->gen_name); + sislog_location(p_cur_dev_to_init->p_sis_device->p_resource_entry); + len = 0; + + p_char = (u8 *)&sense_data; + + for (loop = 0; loop < 18; loop++) + len += sprintf(ioctl_buffer + len,"%.2x ", p_char[loop + 8]); + + syslog(LOG_ERR, "sense data = %s"IBMSIS_EOL, ioctl_buffer); + + /* Send a device reset to cleanup any old state */ + arg = SG_SCSI_RESET_DEVICE; + rc = ioctl(fd, SG_SCSI_RESET, &arg); + + close(fd); + p_cur_dev_to_init->do_init = 0; + remaining_devs--; + continue; + } + close(fd); + p_cur_dev_to_init->fd = 0; + } + } + + /* Here we need to sleep for a bit to make sure our children have started + their formats. There isn't really a good way to know whether or not the formats + have started, so we just wait for 5 seconds */ + sleep(5); + + if (remaining_devs) + rc = dev_init_complete(remaining_devs); + + if (remaining_devs == num_devs) + return rc; + else + return RC_FAILED; +} + +int dev_init_complete(u8 num_devs) +{ + FIELD *p_fields[3]; + FORM *p_form; + FORM *p_old_form; + int done_bad; + struct ibmsis_cmd_status cmd_status; + struct ibmsis_cmd_status_record *p_record; + int not_done = 0; + int rc, j; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct devs_to_init_t *p_cur_dev_to_init; + u32 percent_cmplt = 0; + u8 ioctl_buffer[255]; + struct sense_data_t sense_data; + u8 cdb[IBMSIS_CCB_CDB_LEN], *p_char; + int fd, fdev; + struct sis_ioa *p_ioa; + int len, loop; + struct ibmsis_mode_parm_hdr *p_mode_parm_hdr; + struct ibmsis_block_desc *p_block_desc; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + curses_info.max_y - 1, curses_info.max_x - 1, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Function Status"); + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + while(1) + { + clear(); + post_form(p_form); + + mvaddstr(2, 0, "You selected to initialize and format a disk unit"); + mvprintw(curses_info.max_y / 2, (curses_info.max_x / 2) - 7, "%d%% Complete", percent_cmplt); + + form_driver(p_form, + REQ_FIRST_FIELD); + + refresh(); + + percent_cmplt = 100; + done_bad = 0; + + for (p_cur_dev_to_init = p_head_dev_to_init; + p_cur_dev_to_init != NULL; + p_cur_dev_to_init = p_cur_dev_to_init->p_next) + { + if ((p_cur_dev_to_init->do_init) && + (p_cur_dev_to_init->dev_type == IBMSIS_AF_DASD_DEVICE)) + { + fdev = p_cur_dev_to_init->fd; /* maintained for locking purposes */ + fd = open(p_cur_dev_to_init->p_ioa->ioa.dev_name, O_RDWR); + + if (fd < 0) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_dev_to_init->p_ioa->ioa.dev_name); + done_bad = 1; + continue; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &cmd_status; + ioa_cmd.buffer_len = sizeof(cmd_status); + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_cur_dev_to_init->p_sis_device->p_resource_entry->resource_address; + + rc = sis_ioctl(fd, IBMSIS_QUERY_COMMAND_STATUS, &ioa_cmd); + + close(fd); + + if (rc) + { + syslog(LOG_ERR, "Query Command Status to %s failed. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + p_cur_dev_to_init->cmplt = 100; + continue; + } + + if (cmd_status.num_records == 0) + p_cur_dev_to_init->cmplt = 100; + else + { + p_record = cmd_status.record; + if (p_record->status == IBMSIS_CMD_STATUS_SUCCESSFUL) + { + p_cur_dev_to_init->cmplt = 100; + } + else if (p_record->status == IBMSIS_CMD_STATUS_FAILED) + { + p_cur_dev_to_init->cmplt = 100; + done_bad = 1; + } + else + { + p_cur_dev_to_init->cmplt = p_record->percent_complete; + if (p_record->percent_complete < percent_cmplt) + percent_cmplt = p_record->percent_complete; + not_done = 1; + } + } + } + else if ((p_cur_dev_to_init->do_init) && + (p_cur_dev_to_init->dev_type == IBMSIS_JBOD_DASD_DEVICE)) + { + /* Send Test Unit Ready to find percent complete in sense data. */ + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + fdev = p_cur_dev_to_init->fd; + + if (fdev == 0) + { + fdev = open(p_cur_dev_to_init->p_sis_device->gen_name, O_RDWR); + p_cur_dev_to_init->fd = fdev; + } + + if (fdev <= 1) + { + syslog(LOG_ERR, + "Could not open %s. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->gen_name); + done_bad = 1; + continue; + } + + cdb[0] = TEST_UNIT_READY; + + rc = sg_ioctl(fdev, cdb, + NULL, 0, SG_DXFER_NONE, + &sense_data, 30); + + + if (rc < 0) + { + syslog(LOG_ERR, + "Could not send test unit ready to %s. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->gen_name); + continue; + } + + if ((rc == CHECK_CONDITION) && + ((sense_data.error_code & 0x7F) == 0x70) && + ((sense_data.sense_key & 0x0F) == 0x02)) + { + p_cur_dev_to_init->cmplt = ((int)sense_data.sense_key_spec[1]*100)/0x100; + if (p_cur_dev_to_init->cmplt < percent_cmplt) + percent_cmplt = p_cur_dev_to_init->cmplt; + not_done = 1; + } + else + { + p_cur_dev_to_init->cmplt = 100; + } + } + } + + unpost_form(p_form); + + if (!not_done) + { + p_cur_dev_to_init = p_head_dev_to_init; + while(p_cur_dev_to_init) + { + if (p_cur_dev_to_init->do_init) + { + p_ioa = p_cur_dev_to_init->p_ioa; + + if (p_cur_dev_to_init->dev_type == IBMSIS_AF_DASD_DEVICE) + { + /* check if evaluate device is necessary */ + /* issue mode sense */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.read_not_write = 1; + ioa_cmd.device_cmd = 1; + ioa_cmd.resource_address = p_cur_dev_to_init->p_sis_device->p_resource_entry->resource_address; + + fd = open(p_ioa->ioa.dev_name, O_RDWR); + + if (fd < 0) + { + syslog(LOG_ERR, "Cannot open %s. %m\n", p_ioa->ioa.dev_name); + } + else + { + rc = sis_ioctl(fd, MODE_SENSE, &ioa_cmd); + + close(fd); + + if (rc != 0) + { + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->dev_name); + } + else + { + if (p_mode_parm_hdr->block_desc_len > 0) + { + p_block_desc = (struct ibmsis_block_desc *)(p_mode_parm_hdr+1); + + if((p_block_desc->block_length[1] == 0x02) && + (p_block_desc->block_length[2] == 0x00)) + { + p_cur_dev_to_init->change_size = SIS_512_BLOCK; + } + } + } + } + } + else if (p_cur_dev_to_init->dev_type == IBMSIS_JBOD_DASD_DEVICE) + { + fdev = p_cur_dev_to_init->fd; + + if (fdev == 0) + { + fdev = open(p_cur_dev_to_init->p_sis_device->gen_name, O_RDWR); + p_cur_dev_to_init->fd = fdev; + } + + if (fdev <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->gen_name); + } + else + { + /* Check if evaluate device capabilities needs to be issued */ + memset(ioctl_buffer, 0, 255); + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + + /* Issue mode sense to get the block size */ + cdb[0] = MODE_SENSE; + cdb[4] = 255; + + rc = sg_ioctl(fdev, cdb, + p_mode_parm_hdr, 255, SG_DXFER_FROM_DEV, + &sense_data, 30); + + close(p_cur_dev_to_init->fd); + p_cur_dev_to_init->fd = 0; + + if (rc < 0) + { + syslog(LOG_ERR, "Could not send mode sense to %s. %m"IBMSIS_EOL, + p_cur_dev_to_init->p_sis_device->gen_name); + } + else if (rc == CHECK_CONDITION) + { + len = sprintf("Mode Sense failed to %s. %m ", + p_cur_dev_to_init->p_sis_device->gen_name); + + p_char = (u8 *)&sense_data; + + for (loop = 0; loop < 18; loop++) + len += sprintf(ioctl_buffer + len,"%.2x ",p_char[loop]); + + syslog(LOG_ERR, "sense data = %s"IBMSIS_EOL, ioctl_buffer); + } + else + { + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + + if (p_mode_parm_hdr->block_desc_len > 0) + { + p_block_desc = (struct ibmsis_block_desc *)(p_mode_parm_hdr+1); + + if ((p_block_desc->block_length[1] != 0x02) || + (p_block_desc->block_length[2] != 0x00)) + { + p_cur_dev_to_init->change_size = SIS_522_BLOCK; + remove_device(p_cur_dev_to_init->p_sis_device->p_resource_entry->resource_address, + p_ioa); + } + else + { + if (strlen(p_cur_dev_to_init->p_sis_device->dev_name) == 0) + { + revalidate_dev(p_cur_dev_to_init->p_sis_device, + p_ioa, 1); + } + } + } + } + } + } + + if (p_cur_dev_to_init->fd) + close(p_cur_dev_to_init->fd); + + if (p_cur_dev_to_init->change_size != 0) + { + /* send evaluate device down */ + evaluate_device(p_cur_dev_to_init->p_sis_device, + p_ioa, p_cur_dev_to_init->change_size); + } + } + p_cur_dev_to_init = p_cur_dev_to_init->p_next; + } + + check_current_config(false); + revalidate_devs(NULL); + + free_form(p_form); + curses_info.p_form = p_old_form; + for (j=0; j < 2; j++) + free_field(p_fields[j]); + + flush_stdscr(); + + if (done_bad) + return RC_FAILED; + return RC_SUCCESS; + } + not_done = 0; + sleep(10); + } +} + +void disk_unit_recovery() +{ + /* + Work with Disk Unit Recovery + + Select one of the following: + + 1. Device Concurrent Maintenance + 2. Initialize and format disk unit + 3. Reclaim IOA cache storage + 4. Rebuild disk unit data + 5. Work with resources containing cache battery packs + + + + Selection: + + e=Exit q=Cancel + */ + FIELD *p_fields[12]; + FORM *p_form, *p_old_form; + int invalid = 0; + int rc = RC_SUCCESS; + int j; + char null_char = '\0'; + int battery_maint(); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 2, /* new field size */ + 12, 12, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Work with Disk Unit Recovery"); /* string value to set */ + + flush_stdscr(); + + clear(); + + post_form(p_form); + + while(1) + { + mvaddstr(2, 0, "Select one of the following:"); + mvaddstr(4, 0, " 1. Device Concurrent Maintenance"); + mvaddstr(5, 0, " 2. Initialize and format disk unit"); + mvaddstr(6, 0, " 3. Reclaim IOA cache storage"); + mvaddstr(7, 0, " 4. Rebuild disk unit data"); + mvaddstr(8, 0, " 5. Work with resources containing cache battery packs"); + mvaddstr(12, 0, "Selection: "); + mvaddstr(curses_info.max_y - 2, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + if (invalid) + { + invalid = 0; + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + } + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + refresh(); + for (;;) + { + int ch = getch(); + + if (IS_ENTER_KEY(ch)) + { + char *p_char; + refresh(); + unpost_form(p_form); + p_char = field_buffer(p_fields[1], 0); + + switch(p_char[0]) + { + case '1': /* Device Concurrent Maintenance */ + if (RC_EXIT == (rc = device_concurrent_maintenance(&null_char, &null_char, &null_char, + &null_char, &null_char, &null_char, + &null_char, &null_char, &null_char, + &null_char, &null_char))) + goto leave; + clear(); + post_form(p_form); + if (rc == RC_FAILED) + mvaddstr(curses_info.max_y - 1, 0," Device concurrent maintenance failed"); + else if (rc == RC_IN_USE) + mvaddstr(curses_info.max_y - 1, 0," Device concurrent maintenance failed, device in use"); + else if (rc == RC_SUCCESS) + mvaddstr(curses_info.max_y - 1, 0," Device concurrent maintenance completed successfully"); + break; + case '2': /* Initialize and format disk unit */ + while (RC_REFRESH == (rc = init_device())) + clear(); + clear(); + + post_form(p_form); + if (rc == RC_NOOP) + { + mvaddstr(curses_info.max_y - 1, 0, + " No units available for initialize and format"); + } + else if (rc == RC_SUCCESS) + { + mvaddstr(curses_info.max_y - 1, 0, " Initialize and format completed successfully"); + } + else if (rc == RC_FAILED) + mvaddstr(curses_info.max_y - 1, 0, " Initialize and format failed"); + break; + case '3': /* Reclaim IOA cache storage */ + rc = reclaim_cache(); + clear(); + + post_form(p_form); + if (rc == RC_SUCCESS) + { + mvaddstr(curses_info.max_y - 1, 0, + " Reclaim IOA Cache Storage completed successfully"); + } + else if (rc == RC_FAILED) + { + mvaddstr(curses_info.max_y - 1, 0, + " Reclaim IOA Cache Storage failed"); + } + else if (rc == RC_NOOP) + { + mvaddstr(curses_info.max_y - 1, 0, + " No Reclaim IOA Cache Storage is necessary"); + } + else if (rc == RC_NOT_PERFORMED) + { + mvaddstr(curses_info.max_y - 1, 0, + " No Reclaim IOA Cache Storage performed"); + } + break; + case '4': /* Rebuild disk unit data */ + if (RC_EXIT == (rc = raid_rebuild())) + goto leave; + clear(); + post_form(p_form); + if (rc == RC_SUCCESS) + { + mvaddstr(curses_info.max_y - 1, 0, " Rebuild started, view Parity Status Window for rebuild progress"); + } + else if (rc == RC_FAILED) + mvaddstr(curses_info.max_y - 1, 0, " Rebuild failed"); + break; + case '5': + while (RC_REFRESH == (rc = battery_maint())); + + clear(); + post_form(p_form); + if (rc == RC_SUCCESS) + mvaddstr(curses_info.max_y - 1, 0, + " The selected batter packs have successfully been placed into an error state."); + else if (rc == RC_FAILED) + mvaddstr(curses_info.max_y - 1, 0, + " Attempting to force the selected battery packs into an error state failed."); + else if (rc == RC_NOOP) + mvaddstr(curses_info.max_y - 1, 0, + " No configured resources contain a cache battery pack."); + break; + case ' ': + clear(); + post_form(p_form); + break; + default: + clear(); + post_form(p_form); + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + break; + } + form_driver(p_form, ' '); + refresh(); + break; + } + else if (IS_EXIT_KEY(ch)) + goto leave; + else if (IS_CANCEL_KEY(ch)) + goto leave; + else + { + form_driver(p_form, ch); + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + for (j=0; j < 2; j++) + free_field(p_fields[j]); + flush_stdscr(); + return; +} + +int device_concurrent_maintenance(char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, char *p_action) +{ +/* iSeries + + Device Concurrent Maintenance + + Type the choices, then press Enter. + + Specify either Physical Location or DSA/UA. + Physical Location . . . Frame ID: Position: + OR + DSA/UA in hex . . . . . . DSA: UA: + + + Specify action as 1=Remove device 2=Install device + Action to be performed . . . . . . . . . : + + + Enter a time value between 01 and 19. + Time needed in minutes . . . . . . . . . : + + + Or leave blank and press Enter to cancel + + +*/ +/* pSeries + + Device Concurrent Maintenance + + Type the choices, then press Enter. + + Specify either Physical Location or PCI/SCSI location. + Physical Location . . . : + OR + PCI/SCSI . . . PCI Bus: PCI Device: + SCSI Channel: SCSI Id: SCSI Lun: + + + Specify action as 1=Remove device 2=Install device + Action to be performed . . . . . . . . . : + + + Enter a time value between 01 and 19. + Time needed in minutes . . . . . . . . . : + + + Or leave blank and press Enter to cancel + + +*/ +/* xSeries + + Device Concurrent Maintenance + + Type the choices, then press Enter. + + Specify PCI/SCSI location. + PCI/SCSI . . . PCI Bus: PCI Device: + SCSI Channel: SCSI Id: SCSI Lun: + + + + + Specify action as 1=Remove device 2=Install device + Action to be performed . . . . . . . . . : + + + Enter a time value between 01 and 19. + Time needed in minutes . . . . . . . . . : + + + Or leave blank and press Enter to cancel + + +*/ + + FIELD *p_input_fields[10], *p_confirm_fields[3]; + FORM *p_input_form; + FORM *p_confirm_form; + FORM *p_old_form; + int rc; + int line_num; + int field_index = 0; + + rc = RC_SUCCESS; + + /* Title */ + p_input_fields[field_index++] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + if (platform == SIS_ISERIES) + { + /* Frame ID field */ + p_input_fields[field_index++] = new_field(1, 2, /* new field size */ + 5, 43, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* Position field */ + p_input_fields[field_index++] = new_field(1, 3, /* new field size */ + 5, 60, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* DSA field */ + p_input_fields[field_index++] = new_field(1, 8, /* new field size */ + 7, 38, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* UA field */ + p_input_fields[field_index++] = new_field(1, 8, /* new field size */ + 7, 55, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* Action field */ + p_input_fields[field_index++] = new_field(1, 1, /* new field size */ + 11, 50, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* Delay field */ + p_input_fields[field_index++] = new_field(1, 2, /* new field size */ + 15, 50, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + } + else if (platform == SIS_PSERIES) + { + /* Physical Location field */ + p_input_fields[field_index++] = new_field(1, 16, /* new field size */ + 5, 34, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* PCI Bus field */ + p_input_fields[field_index++] = new_field(1, 4, /* new field size */ + 7, 30, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* PCI Device field */ + p_input_fields[field_index++] = new_field(1, 4, /* new field size */ + 7, 50, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* SCSI Channel field */ + p_input_fields[field_index++] = new_field(1, 1, /* new field size */ + 8, 30, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* SCSI Id field */ + p_input_fields[field_index++] = new_field(1, 2, /* new field size */ + 8, 42, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* SCSI Lun field */ + p_input_fields[field_index++] = new_field(1, 2, /* new field size */ + 8, 55, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* Action field */ + p_input_fields[field_index++] = new_field(1, 1, /* new field size */ + 12, 50, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* Delay field */ + p_input_fields[field_index++] = new_field(1, 2, /* new field size */ + 16, 50, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + } + else + { + /* PCI Bus field */ + p_input_fields[field_index++] = new_field(1, 4, /* new field size */ + 5, 30, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* PCI Device field */ + p_input_fields[field_index++] = new_field(1, 4, /* new field size */ + 5, 50, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* SCSI Channel field */ + p_input_fields[field_index++] = new_field(1, 1, /* new field size */ + 6, 30, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* SCSI Id field */ + p_input_fields[field_index++] = new_field(1, 2, /* new field size */ + 6, 42, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* SCSI Lun field */ + p_input_fields[field_index++] = new_field(1, 2, /* new field size */ + 6, 55, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* Action field */ + p_input_fields[field_index++] = new_field(1, 1, /* new field size */ + 10, 50, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* Delay field */ + p_input_fields[field_index++] = new_field(1, 2, /* new field size */ + 14, 50, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + } + + + p_input_fields[field_index++] = NULL; + + p_old_form = curses_info.p_form; + + curses_info.p_form = p_input_form = new_form(p_input_fields); + + set_current_field(p_input_form, p_input_fields[1]); + + set_field_just(p_input_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_input_fields[0], O_ACTIVE); + + set_field_buffer(p_input_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Device Concurrent Maintenance"); /* string value to set */ + + field_index = 1; + + if (platform == SIS_ISERIES) + { + set_field_buffer(p_input_fields[field_index++], 0, p_frame); + + set_field_buffer(p_input_fields[field_index++], 0, p_slot); + + set_field_buffer(p_input_fields[field_index++], 0, p_dsa); + + set_field_buffer(p_input_fields[field_index++], 0, p_ua); + + set_field_buffer(p_input_fields[field_index++], 0, p_action); + + } + else if (platform == SIS_PSERIES) + { + set_field_buffer(p_input_fields[field_index++], 0, p_location); + + set_field_buffer(p_input_fields[field_index++], 0, p_pci_bus); + + set_field_buffer(p_input_fields[field_index++], 0, p_pci_device); + + set_field_buffer(p_input_fields[field_index++], 0, p_scsi_channel); + + set_field_buffer(p_input_fields[field_index++], 0, p_scsi_id); + + set_field_buffer(p_input_fields[field_index++], 0, p_scsi_lun); + + set_field_buffer(p_input_fields[field_index++], 0, p_action); + + } + else + { + set_field_buffer(p_input_fields[field_index++], 0, p_pci_bus); + + set_field_buffer(p_input_fields[field_index++], 0, p_pci_device); + + set_field_buffer(p_input_fields[field_index++], 0, p_scsi_channel); + + set_field_buffer(p_input_fields[field_index++], 0, p_scsi_id); + + set_field_buffer(p_input_fields[field_index++], 0, p_scsi_lun); + + set_field_buffer(p_input_fields[field_index++], 0, p_action); + } + + form_opts_off(p_input_form, O_BS_OVERLOAD); + + flush_stdscr(); + + clear(); + + post_form(p_input_form); + + line_num = 2; + + mvaddstr(line_num++, 1, "Type the choices, then press Enter."); + line_num++; + + if (platform == SIS_ISERIES) + { + mvaddstr(line_num++, 2, "Specify either Physical Location or DSA/UA."); + mvaddstr(line_num++, 6, "Physical Location . . . Frame ID: Position:"); + mvaddstr(line_num++, 11, "OR"); + mvaddstr(line_num, 6, "DSA/UA in hex . . . . . . DSA:"); + mvaddstr(line_num++, 51, "UA:"); + line_num += 2; + } + else + { + if (platform == SIS_PSERIES) + { + mvaddstr(line_num++, 2, "Specify either Physical Location or PCI/SCSI location."); + mvaddstr(line_num++, 6, "Physical Location . . . :"); + mvaddstr(line_num++, 11, "OR"); + } + else + mvaddstr(line_num++, 2, "Specify PCI/SCSI location."); + + mvaddstr(line_num, 6, "PCI/SCSI . . . PCI Bus:"); + mvaddstr(line_num++, 38, "PCI Device:"); + mvaddstr(line_num, 16, "SCSI Channel:"); + mvaddstr(line_num, 33, "SCSI Id:"); + mvaddstr(line_num++, 45, "SCSI Lun:"); + line_num += 2; + } + + mvaddstr(line_num++, 2, "Specify action as 1=Remove device 2=Install device"); + mvaddstr(line_num++, 6, "Action to be performed . . . . . . . . . :"); + line_num += 2; + mvaddstr(line_num++, 2, "Enter a time value between 01 and 19."); + mvaddstr(line_num++, 6, "Time needed in minutes . . . . . . . . . :"); + line_num += 2; + mvaddstr(18, 2, "Or leave blank and press Enter to cancel"); + + if ((strlen(p_frame) > 0) || (strlen(p_dsa) > 0) || (strlen(p_location) > 0) || + (strlen(p_pci_bus) > 0)) + { + set_current_field(p_input_form, p_input_fields[field_index]); + } + else + { + form_driver(p_input_form, /* form to pass input to */ + REQ_FIRST_FIELD ); /* form request code */ + } + + refresh(); + + while(1) + { + char *p_action, *p_delay; + int ch = getch(); + char null_ch = '\0'; + + if (IS_ENTER_KEY(ch)) + { + form_driver(p_input_form, REQ_NEXT_FIELD); + unpost_form(p_input_form); + + p_action = p_delay = &null_ch; + + if (platform == SIS_ISERIES) + { + p_frame = strip_trailing_whitespace(field_buffer(p_input_fields[1], 0)); + p_slot = strip_trailing_whitespace(field_buffer(p_input_fields[2], 0)); + p_slot[0] = toupper(p_slot[0]); + p_dsa = strip_trailing_whitespace(field_buffer(p_input_fields[3], 0)); + p_ua = strip_trailing_whitespace(field_buffer(p_input_fields[4], 0)); + p_action = strip_trailing_whitespace(field_buffer(p_input_fields[5], 0)); + p_delay = strip_trailing_whitespace(field_buffer(p_input_fields[6], 0)); + } + else if (platform == SIS_PSERIES) + { + p_location = strip_trailing_whitespace(field_buffer(p_input_fields[1], 0)); + p_pci_bus = strip_trailing_whitespace(field_buffer(p_input_fields[2], 0)); + p_pci_device = strip_trailing_whitespace(field_buffer(p_input_fields[3], 0)); + p_scsi_channel = strip_trailing_whitespace(field_buffer(p_input_fields[4], 0)); + p_scsi_id = strip_trailing_whitespace(field_buffer(p_input_fields[5], 0)); + p_scsi_lun = strip_trailing_whitespace(field_buffer(p_input_fields[6], 0)); + p_action = strip_trailing_whitespace(field_buffer(p_input_fields[7], 0)); + p_delay = strip_trailing_whitespace(field_buffer(p_input_fields[8], 0)); + } + else + { + p_pci_bus = strip_trailing_whitespace(field_buffer(p_input_fields[1], 0)); + p_pci_device = strip_trailing_whitespace(field_buffer(p_input_fields[2], 0)); + p_scsi_channel = strip_trailing_whitespace(field_buffer(p_input_fields[3], 0)); + p_scsi_id = strip_trailing_whitespace(field_buffer(p_input_fields[4], 0)); + p_scsi_lun = strip_trailing_whitespace(field_buffer(p_input_fields[5], 0)); + p_action = strip_trailing_whitespace(field_buffer(p_input_fields[6], 0)); + p_delay = strip_trailing_whitespace(field_buffer(p_input_fields[7], 0)); + } + + if ((((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) || + ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) || + (strlen(p_location) > 0) || + ((strlen(p_pci_bus) > 0) && (strlen(p_pci_device) > 0) && + (strlen(p_scsi_channel) && (strlen(p_scsi_id) > 0) && + (strlen(p_scsi_lun) > 0)))) + && ((strlen(p_action) > 0) && (strlen(p_delay) > 0))) + { + rc = is_valid_device(p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun); + + if (rc) + { + rc = conc_maintenance_failed(p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, p_action, rc); + break; + } + + clear(); + + /* Title */ + p_confirm_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* Confirm field */ + p_confirm_fields[1] = new_field(1, 1, /* new field size */ + 16, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_confirm_fields[2] = NULL; + + p_confirm_form = new_form(p_confirm_fields); + + set_current_field(p_confirm_form, p_confirm_fields[1]); + + set_field_just(p_confirm_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_confirm_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + if (rc) + { + set_field_buffer(p_confirm_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Confirm Device Concurrent Maintenance Action");/* string value to set */ + } + else + { + set_field_buffer(p_confirm_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Device Concurrent Maintenance Action");/* string value to set */ + } + + flush_stdscr(); + + clear(); + + post_form(p_confirm_form); + + if (strcmp(p_action, "1") == 0) + { + mvaddstr(2, 1, "Removal of device:"); + } + else if (strcmp(p_action, "2") == 0) + { + mvaddstr(2, 1, "Installation of device:"); + } + else + { + rc = RC_FAILED; + unpost_form(p_confirm_form); + free_form(p_confirm_form); + free_screen(NULL, NULL, p_confirm_fields); + syslog(LOG_ERR, + "Invalid Device Concurrent Maintenance action selected: %s"IBMSIS_EOL, + p_action); + goto leave; + } + + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + p_frame[0] = toupper(p_frame[0]); + mvprintw(3, 4, "Frame ID: %s Position: %s", p_frame, p_slot); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + mvprintw(3, 4, "DSA: %s UA: %s", p_dsa, p_ua); + } + else if (strlen(p_location) > 0) + { + mvprintw(3, 4, "Location: %s", p_location); + } + else + { + mvprintw(3, 4, "PCI Bus: %s PCI Device: %s", p_pci_bus, p_pci_device); + mvprintw(4, 4, "SCSI Channel: %s SCSI Id: %s SCSI Lun: %s", p_scsi_channel, + p_scsi_id, p_scsi_lun); + } + + if (strtoul(p_delay, NULL, 10) > 1) + mvprintw(6, 2, "You have %s minutes to perform the operation", p_delay); + else + mvprintw(6, 2, "You have %s minute to perform the operation", p_delay); + mvaddstr(8, 2, "During this time, your system may seem unresponsive"); + mvprintw(curses_info.max_y - 2, 0, + "c=Confirm "CANCEL_KEY_LABEL"=Cancel"); + set_current_field(p_confirm_form, p_input_fields[1]); + refresh(); + + while(1) + { + int ch = getch(); + if ((ch == 'c') || (ch == 'C')) + { + /* Issue Concurrent maintenance action */ + rc = issue_concurrent_maintenance(p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, + p_action, p_delay); + unpost_form(p_confirm_form); + free_form(p_confirm_form); + free_screen(NULL, NULL, p_confirm_fields); + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + unpost_form(p_confirm_form); + free_form(p_confirm_form); + free_screen(NULL, NULL, p_confirm_fields); + goto leave; + } + } + } + rc = RC_CANCEL; + break; + } + else if (ch == KEY_RIGHT) + form_driver(p_input_form, REQ_NEXT_CHAR); + else if (ch == KEY_LEFT) + form_driver(p_input_form, REQ_PREV_CHAR); + else if ((ch == KEY_BACKSPACE) || (ch == 127)) + form_driver(p_input_form, REQ_DEL_PREV); + else if (ch == KEY_DC) + form_driver(p_input_form, REQ_DEL_CHAR); + else if (ch == KEY_IC) + form_driver(p_input_form, REQ_INS_MODE); + else if (ch == KEY_EIC) + form_driver(p_input_form, REQ_OVL_MODE); + else if (ch == KEY_HOME) + form_driver(p_input_form, REQ_BEG_FIELD); + else if (ch == KEY_END) + form_driver(p_input_form, REQ_END_FIELD); + else if (ch == '\t') + form_driver(p_input_form, REQ_NEXT_FIELD); + else if (ch == KEY_UP) + form_driver(p_input_form, REQ_PREV_FIELD); + else if (ch == KEY_DOWN) + form_driver(p_input_form, REQ_NEXT_FIELD); + else if (isascii(ch)) + form_driver(p_input_form, ch); + refresh(); + } + + + leave: + free_form(p_input_form); + free_screen(NULL, NULL, p_input_fields); + curses_info.p_form = p_old_form; + flush_stdscr(); + return rc; +} + +int issue_concurrent_maintenance(char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, + char *p_action, char *p_delay) +{ + struct sis_ioa *p_cur_ioa = p_head_sis_ioa; + int frame = (strlen(p_frame) > 0) && (strlen(p_slot) > 0); + int frame_id; + int fd, rc, i; + u32 dsa, ua, delay; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + int res_found = 0; + u8 scsi_bus, scsi_id, scsi_lun; + u16 pci_bus, pci_device; + struct ibmsis_resource_entry *p_resource_entry; + + delay = strtoul(p_delay, NULL, 10); + + rc = RC_SUCCESS; + + if (frame) + { + frame_id = strtoul(p_frame, NULL, 10); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + dsa = strtoul(p_dsa, NULL, 16); + ua = strtoul(p_ua, NULL, 16); + } + else if (strlen(p_location) == 0) + { + pci_bus = strtoul(p_pci_bus, NULL, 10); + pci_device = strtoul(p_pci_device, NULL, 10); + scsi_bus = strtoul(p_scsi_channel, NULL, 10); + scsi_id = strtoul(p_scsi_id, NULL, 10); + scsi_lun = strtoul(p_scsi_lun, NULL, 10); + } + + check_current_config(false); + + /* Loop through the adapters on the system to find the adapter that + this physical resource belongs to */ + for (p_cur_ioa = p_head_sis_ioa; p_cur_ioa; p_cur_ioa = p_cur_ioa->p_next) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + + if (fd < 1) + { + syslog(LOG_ERR, "Cannot open %s. %m\n", p_cur_ioa->ioa.dev_name); + continue; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.cdb[0] = IBMSIS_CONC_MAINT; + ioa_cmd.cdb[1] = IBMSIS_CONC_MAINT_CHECK_ONLY; + ioa_cmd.buffer = NULL; + ioa_cmd.buffer_len = 0; + ioa_cmd.driver_cmd = 1; + + if (frame) + { + ioa_cmd.cdb[2] = IBMSIS_CONC_MAINT_FRAME_ID_FMT; + ioa_cmd.cdb[4] = (frame_id << 8) & 0xff; + ioa_cmd.cdb[5] = frame_id & 0xff; + + ioa_cmd.cdb[6] = p_slot[0]; + ioa_cmd.cdb[7] = p_slot[1]; + ioa_cmd.cdb[8] = p_slot[2]; + ioa_cmd.cdb[9] = p_slot[3]; + ioa_cmd.cdb[12] = delay; + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + ioa_cmd.cdb[2] = IBMSIS_CONC_MAINT_DSA_FMT; + ioa_cmd.cdb[4] = (dsa >> 24) & 0xff; + ioa_cmd.cdb[5] = (dsa >> 16) & 0xff; + ioa_cmd.cdb[6] = (dsa >> 8) & 0xff; + ioa_cmd.cdb[7] = dsa & 0xff; + + ioa_cmd.cdb[8] = (ua >> 24) & 0xff; + ioa_cmd.cdb[9] = (ua >> 16) & 0xff; + ioa_cmd.cdb[10] = (ua >> 8) & 0xff; + ioa_cmd.cdb[11] = ua & 0xff; + ioa_cmd.cdb[12] = delay; + } + else if (strlen(p_location) > 0) + { + ioa_cmd.cdb[2] = IBMSIS_CONC_MAINT_PSERIES_FMT; + ioa_cmd.cdb[12] = delay; + ioa_cmd.buffer = p_location; + ioa_cmd.buffer_len = strlen(p_location); + } + else + { + ioa_cmd.cdb[2] = IBMSIS_CONC_MAINT_XSERIES_FMT; + ioa_cmd.cdb[4] = (pci_bus >> 8) & 0xff; + ioa_cmd.cdb[5] = pci_bus & 0xff; + ioa_cmd.cdb[6] = (pci_device >> 8) & 0xff; + ioa_cmd.cdb[7] = pci_device & 0xff; + + ioa_cmd.cdb[8] = scsi_bus & 0xff; + ioa_cmd.cdb[9] = scsi_id & 0xff; + ioa_cmd.cdb[10] = scsi_lun & 0xff; + ioa_cmd.cdb[12] = delay; + } + + /* Issue a concurrent maintenance check command, which will tell us if this + device slot exists under this adapter */ + rc = sis_ioctl(fd, IBMSIS_CONC_MAINT, &ioa_cmd); + + if (rc != 0) + { + if (errno == ENXIO) + { + /* No such device or address - response which occurs when + the passed slot does not exist on this IOA - try another */ + close(fd); + continue; + } + else + { + /* An unexpected error occurred during the ioctl */ + syslog(LOG_ERR, "Concurrent maintenance to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + close(fd); + return rc; + } + } + else + { + /* Address exists on this adapter and we are allowed to do concurrent maintenance + to the slot (if this device is running hardware RAID, removal of the device + would not cause the array to go non-functional) */ + + for (i = 0; i < p_cur_ioa->num_devices; i++) + { + p_resource_entry = p_cur_ioa->dev[i].p_resource_entry; + + if (frame) + { + if ((strcasecmp(p_resource_entry->frame_id, p_frame) == 0) && + (strcasecmp(p_resource_entry->slot_label, p_slot) == 0)) + { + res_found = 1; + } + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + if ((p_resource_entry->dsa == dsa) && + (p_resource_entry->unit_address == ua)) + { + res_found = 1; + } + } + else if (strlen(p_location) > 0) + { + if (strcasecmp(p_location, p_resource_entry->pseries_location) == 0) + { + res_found = 1; + } + } + else + { + if ((p_resource_entry->pci_bus_number == pci_bus) && + (p_resource_entry->pci_slot == pci_device) && + (p_resource_entry->resource_address.bus == scsi_bus) && + (p_resource_entry->resource_address.target == scsi_id) && + (p_resource_entry->resource_address.lun == scsi_lun)) + { + res_found = 1; + } + } + + if (res_found && + (p_resource_entry->subtype == IBMSIS_SUBTYPE_AF_DASD) && + (!p_resource_entry->is_array_member) && + p_cur_ioa->dev[i].p_qac_entry && + (p_cur_ioa->dev[i].p_qac_entry->record_id == IBMSIS_RECORD_ID_DEVICE_RECORD)) + { + /* A device already exists at this location and it is not protected + by hardware RAID. Need to post a warning */ + rc = concurrent_maintenance_warning(p_cur_ioa, &p_cur_ioa->dev[i], + p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, + p_action, delay); + break; + } + else if (res_found) + { + if (p_action[0] == '1') /* Remove device */ + { + rc = do_dasd_conc_maintenance(p_cur_ioa, &p_cur_ioa->dev[i], + p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, + p_action, delay, 0); + } + else /* insert device */ + { + rc = do_dasd_conc_maintenance(p_cur_ioa, &p_cur_ioa->dev[i], + p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, + p_action, delay, 1); + } + break; + } + } + + if (res_found == 0) + { + rc = do_dasd_conc_maintenance(p_cur_ioa, NULL, + p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, + p_action, delay, 0); + } + return rc; + } + } + return RC_FAILED; +} + +int is_valid_device(char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun) +{ + struct sis_ioa *p_cur_ioa; + int frame = ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)); + int pseries_loc = (strlen(p_location) > 0); + int frame_id; + u8 scsi_bus, scsi_id, scsi_lun; + u16 pci_bus, pci_device; + int fd, rc, i, opens; + u32 dsa, ua, delay = 1; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + int res_found = 0; + struct ibmsis_resource_entry *p_resource_entry; + + rc = RC_SUCCESS; + + if (frame) + { + frame_id = strtoul(p_frame, NULL, 10); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + dsa = strtoul(p_dsa, NULL, 16); + ua = strtoul(p_ua, NULL, 16); + } + else if (!pseries_loc) + { + pci_bus = strtoul(p_pci_bus, NULL, 10); + pci_device = strtoul(p_pci_device, NULL, 10); + scsi_bus = strtoul(p_scsi_channel, NULL, 10); + scsi_id = strtoul(p_scsi_id, NULL, 10); + scsi_lun = strtoul(p_scsi_lun, NULL, 10); + } + + /* Loop through the adapters on the system to find the adapter that + this physical resource belongs to */ + for (p_cur_ioa = p_head_sis_ioa; p_cur_ioa; p_cur_ioa = p_cur_ioa->p_next) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + + if (fd < 1) + { + syslog(LOG_ERR, "Cannot open %s. %m\n", p_cur_ioa->ioa.dev_name); + continue; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.cdb[0] = IBMSIS_CONC_MAINT; + ioa_cmd.cdb[1] = IBMSIS_CONC_MAINT_CHECK_ONLY; + ioa_cmd.buffer = NULL; + ioa_cmd.buffer_len = 0; + ioa_cmd.driver_cmd = 1; + + if (frame) + { + ioa_cmd.cdb[2] = IBMSIS_CONC_MAINT_FRAME_ID_FMT; + ioa_cmd.cdb[4] = (frame_id << 8) & 0xff; + ioa_cmd.cdb[5] = frame_id & 0xff; + + ioa_cmd.cdb[6] = p_slot[0]; + ioa_cmd.cdb[7] = p_slot[1]; + ioa_cmd.cdb[8] = p_slot[2]; + ioa_cmd.cdb[9] = p_slot[3]; + ioa_cmd.cdb[12] = delay; + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + ioa_cmd.cdb[2] = IBMSIS_CONC_MAINT_DSA_FMT; + ioa_cmd.cdb[4] = (dsa >> 24) & 0xff; + ioa_cmd.cdb[5] = (dsa >> 16) & 0xff; + ioa_cmd.cdb[6] = (dsa >> 8) & 0xff; + ioa_cmd.cdb[7] = dsa & 0xff; + + ioa_cmd.cdb[8] = (ua >> 24) & 0xff; + ioa_cmd.cdb[9] = (ua >> 16) & 0xff; + ioa_cmd.cdb[10] = (ua >> 8) & 0xff; + ioa_cmd.cdb[11] = ua & 0xff; + ioa_cmd.cdb[12] = delay; + } + else if (pseries_loc) + { + ioa_cmd.cdb[2] = IBMSIS_CONC_MAINT_PSERIES_FMT; + ioa_cmd.cdb[12] = delay; + ioa_cmd.buffer = p_location; + ioa_cmd.buffer_len = strlen(p_location); + } + else + { + ioa_cmd.cdb[2] = IBMSIS_CONC_MAINT_XSERIES_FMT; + ioa_cmd.cdb[4] = (pci_bus >> 8) & 0xff; + ioa_cmd.cdb[5] = pci_bus & 0xff; + ioa_cmd.cdb[6] = (pci_device >> 8) & 0xff; + ioa_cmd.cdb[7] = pci_device & 0xff; + + ioa_cmd.cdb[8] = scsi_bus & 0xff; + ioa_cmd.cdb[9] = scsi_id & 0xff; + ioa_cmd.cdb[10] = scsi_lun & 0xff; + ioa_cmd.cdb[12] = delay; + } + + /* Issue a concurrent maintenance check command, which will tell us if this + device slot exists under this adapter */ + rc = sis_ioctl(fd, IBMSIS_CONC_MAINT, &ioa_cmd); + + if (rc != 0) + { + if (errno == ENXIO) + { + /* No such device or address - response which occurs when + the passed slot does not exist on this IOA - try another */ + close(fd); + continue; + } + else + { + if (errno != EACCES) + { + /* An unexpected error occurred during the ioctl */ + syslog(LOG_ERR, "Concurrent maintenance to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + } + close(fd); + return rc; + } + } + else + { + /* Address exists on this adapter and we are allowed to do concurrent maintenance + to the slot (if this device is running hardware RAID, removal of the device + would not cause the array to go non-functional) */ + + /* Check to see if a device exists at this resource and if so, make sure it + is not currently in use */ + for (i = 0; i < p_cur_ioa->num_devices; i++) + { + p_resource_entry = p_cur_ioa->dev[i].p_resource_entry; + + if (frame) + { + if ((strcasecmp(p_resource_entry->frame_id, p_frame) == 0) && + (strcasecmp(p_resource_entry->slot_label, p_slot) == 0)) + { + res_found = 1; + } + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + if ((p_resource_entry->dsa == dsa) && + (p_resource_entry->unit_address == ua)) + { + res_found = 1; + } + } + else if (pseries_loc) + { + if (strcasecmp(p_location, p_resource_entry->pseries_location) == 0) + { + res_found = 1; + } + } + else + { + if ((p_resource_entry->pci_bus_number == pci_bus) && + (p_resource_entry->pci_slot == pci_device) && + (p_resource_entry->resource_address.bus == scsi_bus) && + (p_resource_entry->resource_address.target == scsi_id) && + (p_resource_entry->resource_address.lun == scsi_lun)) + { + res_found = 1; + } + } + + if (res_found) + { + opens = num_device_opens(p_cur_ioa->host_num, + p_resource_entry->resource_address.bus, + p_resource_entry->resource_address.target, + p_resource_entry->resource_address.lun); + + if ((opens != 0) && (!p_resource_entry->is_array_member)) + rc = RC_IN_USE; + break; + } + } + + close(fd); + return rc; + } + } + return RC_FAILED; +} + +int concurrent_maintenance_warning(struct sis_ioa *p_ioa, + struct sis_device *p_sis_device, + char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, + char *p_action, u32 delay) +{ + /* + Device Concurrent Maintenance Action Warning + + The device currently located in: + Frame ID: 3 Position: D16 + + is not parity protected by the IOA. Removal of the device may + cause the system to HANG if it contains storage which is vital + for system operation. Proceed with extreme caution. + + Press r=Proceed with Concurrent remove + Press q=Cancel operation + + + + + q=Cancel r=Confirm remove + + + OR + + + Device Concurrent Maintenance Action Warning + + The device previously located in: + Frame ID: 3 Position: D16 + + was not parity protected by the IOA. Installation of a new device + in this slot will allow the adapter to discard any existing cache + data for the previously installed device. + + + + + Press i=Proceed with Concurrent install + Press q=Cancel operation + + + + + q=Cancel i=Confirm install + + + */ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + int rc; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Device Concurrent Maintenance Action Warning"); + + post_form(p_form); + + + if (p_action[0] == '1') /* Remove device */ + { + mvaddstr(2, 0, "The device currently located in:"); + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + mvprintw(3, 4, "Frame ID: %s Position: %s", p_frame, p_slot); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + mvprintw(3, 4, "DSA: %s UA: %s", p_dsa, p_ua); + } + else if (strlen(p_location) > 0) + { + mvprintw(3, 4, "Location: %s", p_location); + } + else + { + mvprintw(3, 4, "PCI Bus: %s PCI Device: %s", p_pci_bus, p_pci_device); + mvprintw(4, 4, "SCSI Channel: %s SCSI Id: %s SCSI Lun: %s", p_scsi_channel, + p_scsi_id, p_scsi_lun); + } + + mvaddstr(6, 0, "is not parity protected by the IOA. Removal of the device may"); + mvaddstr(7, 0, "cause the system to HANG if it contains storage which is vital"); + mvaddstr(8, 0, "for system operation. Proceed with extreme caution."); + mvaddstr(11, 0, "Press r=Proceed with Concurrent remove"); + mvaddstr(12, 0, "Press "CANCEL_KEY_LABEL"=Cancel operation"); + mvaddstr(curses_info.max_y - 2, 0, CANCEL_KEY_LABEL"=Cancel r=Confirm remove"); + } + else /* Insert device */ + { + mvaddstr(2, 0, "The device previously located in:"); + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + mvprintw(3, 4, "Frame ID: %s Position: %s", p_frame, p_slot); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + mvprintw(3, 4, "DSA: %s UA: %s", p_dsa, p_ua); + } + else if (strlen(p_location) > 0) + { + mvprintw(3, 4, "Location: %s", p_location); + } + else + { + mvprintw(3, 4, "PCI Bus: %s PCI Device: %s", p_pci_bus, p_pci_device); + mvprintw(4, 4, "SCSI Channel: %s SCSI Id: %s SCSI Lun: %s", p_scsi_channel, + p_scsi_id, p_scsi_lun); + } + + mvaddstr(6, 0, "was not parity protected by the IOA. Installation of a new device"); + mvaddstr(7, 0, "in this slot will allow the adapter to discard any existing cache"); + mvaddstr(8, 0, "data for the previously installed device."); + mvaddstr(11, 0, "Press i=Proceed with Concurrent install"); + mvaddstr(12, 0, "Press q=Cancel operation"); + mvaddstr(curses_info.max_y - 2, 0, CANCEL_KEY_LABEL"=Cancel i=Confirm install"); + } + + while(1) + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if ((p_action[0] == '1') && ((ch == 'r') || (ch == 'R'))) + { + rc = do_dasd_conc_maintenance(p_ioa, p_sis_device, + p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, + p_action, delay, 0); + goto leave; + } + else if ((p_action[0] == '2') && + ((ch == 'i') || (ch == 'I'))) + { + rc = do_dasd_conc_maintenance(p_ioa, p_sis_device, + p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, + p_action, delay, 1); + goto leave; + } + else + { + break; + } + } + } + + leave: + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int do_dasd_conc_maintenance(struct sis_ioa *p_ioa, + struct sis_device *p_sis_device, + char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, + char *p_action, u32 delay, int replace_dev) +{ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + int fd, j, rc, k, devfd; + struct ibmsis_discard_cache_data discard_data; + struct ibmsis_resource_entry *p_ref_resource_entry; + u32 dsa, ua; + u16 pci_bus, pci_device; + int frame_id, cmp; + int res_found = 0; + u8 scsi_bus, scsi_id, scsi_lun; + struct ibmsis_resource_entry resource_entry; + + if (p_sis_device) + { + ibmsis_memory_copy(&resource_entry, + p_sis_device->p_resource_entry, + sizeof(resource_entry)); + } + else + { + memset(&resource_entry, 0, sizeof(resource_entry)); + } + + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + frame_id = strtoul(p_frame, NULL, 10); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + dsa = strtoul(p_dsa, NULL, 16); + ua = strtoul(p_ua, NULL, 16); + } + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Device Concurrent Maintenance Action In Progress"); + + post_form(p_form); + + if (p_action[0] == '1') /* Remove device */ + { + mvaddstr(3, 0, "Please remove the device located in:"); + + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + mvprintw(4, 4, "Frame ID: %s Position: %s", p_frame, p_slot); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + mvprintw(4, 4, "DSA: %s UA: %s", p_dsa, p_ua); + } + else if (strlen(p_location) > 0) + { + mvprintw(4, 4, "Location: %s", p_location); + } + else + { + mvprintw(4, 4, "PCI Bus: %s PCI Device: %s", p_pci_bus, p_pci_device); + mvprintw(5, 4, "SCSI Channel: %s SCSI Id: %s SCSI Lun: %s", p_scsi_channel, + p_scsi_id, p_scsi_lun); + } + } + else /* Insert device */ + { + mvaddstr(3, 0, "Please insert the device located in:"); + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + mvprintw(4, 4, "Frame ID: %s Position: %s", p_frame, p_slot); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + mvprintw(4, 4, "DSA: %s UA: %s", p_dsa, p_ua); + } + else if (strlen(p_location) > 0) + { + mvprintw(4, 4, "Location: %s", p_location); + } + else + { + mvprintw(4, 4, "PCI Bus: %s PCI Device: %s", p_pci_bus, p_pci_device); + mvprintw(5, 4, "SCSI Channel: %s SCSI Id: %s SCSI Lun: %s", p_scsi_channel, + p_scsi_id, p_scsi_lun); + } + + } + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + + fd = open(p_ioa->ioa.dev_name, O_RDWR); + + if (fd <= 1) + { + rc = RC_FAILED; + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_ioa->ioa.dev_name); + goto leave; + } + + /* Build the Concurrent maintenance command */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.cdb[0] = IBMSIS_CONC_MAINT; + ioa_cmd.cdb[1] = IBMSIS_CONC_MAINT_CHECK_AND_QUIESCE; + ioa_cmd.buffer = NULL; + ioa_cmd.buffer_len = 0; + ioa_cmd.driver_cmd = 1; + + if (p_action[0] == '1') /* Remove device */ + { + ioa_cmd.cdb[2] = IBMSIS_CONC_MAINT_REMOVE << IBMSIS_CONC_MAINT_TYPE_SHIFT; + } + else if (p_action[0] == '2') /* Insert device */ + { + ioa_cmd.cdb[2] = IBMSIS_CONC_MAINT_INSERT << IBMSIS_CONC_MAINT_TYPE_SHIFT; + } + else + { + syslog(LOG_ERR, "Invalid action specified : %c."IBMSIS_EOL, p_action[0]); + rc = RC_FAILED; + goto leave; + } + + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + ioa_cmd.cdb[2] |= IBMSIS_CONC_MAINT_FRAME_ID_FMT; + ioa_cmd.cdb[4] = (frame_id << 8) & 0xff; + ioa_cmd.cdb[5] = frame_id & 0xff; + + ioa_cmd.cdb[6] = p_slot[0]; + ioa_cmd.cdb[7] = p_slot[1]; + ioa_cmd.cdb[8] = p_slot[2]; + ioa_cmd.cdb[9] = p_slot[3]; + ioa_cmd.cdb[12] = delay; + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + ioa_cmd.cdb[2] |= IBMSIS_CONC_MAINT_DSA_FMT; + ioa_cmd.cdb[4] = (dsa >> 24) & 0xff; + ioa_cmd.cdb[5] = (dsa >> 16) & 0xff; + ioa_cmd.cdb[6] = (dsa >> 8) & 0xff; + ioa_cmd.cdb[7] = dsa & 0xff; + + ioa_cmd.cdb[8] = (ua >> 24) & 0xff; + ioa_cmd.cdb[9] = (ua >> 16) & 0xff; + ioa_cmd.cdb[10] = (ua >> 8) & 0xff; + ioa_cmd.cdb[11] = ua & 0xff; + ioa_cmd.cdb[12] = delay; + } + else if (strlen(p_location) > 0) + { + ioa_cmd.cdb[2] |= IBMSIS_CONC_MAINT_PSERIES_FMT; + ioa_cmd.cdb[12] = delay; + ioa_cmd.buffer = p_location; + ioa_cmd.buffer_len = strlen(p_location); + } + else + { + pci_bus = strtoul(p_pci_bus, NULL, 10); + pci_device = strtoul(p_pci_device, NULL, 10); + scsi_bus = strtoul(p_scsi_channel, NULL, 10); + scsi_id = strtoul(p_scsi_id, NULL, 10); + scsi_lun = strtoul(p_scsi_lun, NULL, 10); + + ioa_cmd.cdb[2] |= IBMSIS_CONC_MAINT_XSERIES_FMT; + ioa_cmd.cdb[4] = (pci_bus >> 8) & 0xff; + ioa_cmd.cdb[5] = pci_bus & 0xff; + ioa_cmd.cdb[6] = (pci_device >> 8) & 0xff; + ioa_cmd.cdb[7] = pci_device & 0xff; + + ioa_cmd.cdb[8] = scsi_bus & 0xff; + ioa_cmd.cdb[9] = scsi_id & 0xff; + ioa_cmd.cdb[10] = scsi_lun & 0xff; + ioa_cmd.cdb[12] = delay; + } + + rc = sis_ioctl(fd, IBMSIS_CONC_MAINT, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Concurrent maintenance to %s failed. %m"IBMSIS_EOL, p_ioa->ioa.dev_name); + goto leave; + } + else + { + /* Concurrent maintenance was successful */ + /* Lets see if this was an insert of a new device */ + + if ((p_action[0] == '2') && + (!resource_entry.is_array_member)) + { + /* This was an insert. We may need to tell the system about it */ + res_found = 0; + + /* Wait for the new device to show up to the system for 1 minute, + looking every 5 seconds */ + for (k = 0; (k < 12) && !res_found; k++) + { + sleep(5); + check_current_config(false); + + for (j = 0; j < p_ioa->num_devices; j++) + { + p_ref_resource_entry = p_ioa->dev[j].p_resource_entry; + + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + if ((strcasecmp(p_ref_resource_entry->frame_id, p_frame) == 0) && + (strcasecmp(p_ref_resource_entry->slot_label, p_slot) == 0)) + { + res_found = 1; + } + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + if ((p_ref_resource_entry->dsa == dsa) && + (p_ref_resource_entry->unit_address == ua)) + { + res_found = 1; + } + } + else if (strlen(p_location) > 0) + { + if (strcasecmp(p_location, p_ref_resource_entry->pseries_location) == 0) + { + res_found = 1; + } + } + else + { + if ((p_ref_resource_entry->pci_bus_number == pci_bus) && + (p_ref_resource_entry->pci_slot == pci_device) && + (p_ref_resource_entry->resource_address.bus == scsi_bus) && + (p_ref_resource_entry->resource_address.target == scsi_id) && + (p_ref_resource_entry->resource_address.lun == scsi_lun)) + { + res_found = 1; + } + } + + if (res_found && replace_dev) + { + cmp = memcmp(&resource_entry.std_inq_data.vpids, + &p_ref_resource_entry->std_inq_data.vpids, + sizeof(struct ibmsis_std_inq_vpids)) || + memcmp(&resource_entry.std_inq_data.serial_num, + &p_ref_resource_entry->std_inq_data.serial_num, + IBMSIS_SERIAL_NUM_LEN); + } + + if (res_found && + (!replace_dev || cmp || p_ref_resource_entry->dev_changed || + (resource_entry.subtype != IBMSIS_SUBTYPE_AF_DASD))) + { + if (replace_dev && cmp) + { + /* Replacement device is different than original */ + /* We want to discard any cache data for the old device */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + discard_data.length = htosis32(0x20); + discard_data.data.vpids_sn.vpids = resource_entry.std_inq_data.vpids; + memcpy(&discard_data.data.vpids_sn.serial_num, + &resource_entry.std_inq_data.serial_num, + IBMSIS_SERIAL_NUM_LEN); + + ioa_cmd.buffer = &discard_data; + ioa_cmd.buffer_len = sizeof(struct ibmsis_discard_cache_data); + ioa_cmd.cdb[1] = IBMSIS_PROHIBIT_CORR_INFO_UPDATE; + rc = sis_ioctl(fd, IBMSIS_DISCARD_CACHE_DATA, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Discard cache data to %s failed. %m"IBMSIS_EOL, p_ioa->ioa.dev_name); + } + } + + /* A device now exists at this location */ + /* See if we can open it. */ + if (IBMSIS_IS_DASD_DEVICE(p_ref_resource_entry->std_inq_data)) + { + devfd = open_dev(p_ioa, &p_ioa->dev[j]); + + if (devfd > 1) + close(devfd); + } + + /* We may need to format the device to make it useable */ + /* Lets take the user to that screen */ + conc_maintenance_complt(p_ioa, + &p_ioa->dev[j], + p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, + p_action, delay, replace_dev); + goto leave; + } + else + res_found = 0; + } + } + syslog(LOG_ERR, "Timed out waiting for new device to show up\n"); + conc_maintenance_complt(p_ioa, + NULL, + p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, + p_action, delay, 0); + goto leave; + } + else + { + conc_maintenance_complt(p_ioa, + p_sis_device, + p_frame, p_slot, p_dsa, p_ua, + p_location, p_pci_bus, p_pci_device, + p_scsi_channel, p_scsi_id, p_scsi_lun, + p_action, delay, 0); + } + } + + leave: + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + close(fd); + return rc; +} + +int conc_maintenance_complt(struct sis_ioa *p_ioa, + struct sis_device *p_sis_device, + char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, + char *p_action, u32 delay, int replace_dev) +{ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + int rc, fd; + int frame = (strlen(p_frame) > 0) && (strlen(p_slot) > 0); + u32 dsa, ua, resource_handle; + int frame_id; + struct devs_to_init_t cur_dasd_init; + struct ibmsis_resource_entry *p_resource_entry = NULL; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + + if (p_sis_device) + p_resource_entry = p_sis_device->p_resource_entry; + + if (!frame) + { + dsa = strtoul(p_dsa, NULL, 16); + ua = strtoul(p_ua, NULL, 16); + } + else + { + frame_id = strtoul(p_frame, NULL, 10); + } + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Concurrent Maintenance Results"); + + refresh: + + post_form(p_form); + + mvaddstr(3, 0, "THE CONCURRENT MAINTENANCE PROCEDURE HAS COMPLETED SUCCESSFULLY."); + + if (p_action[0] == '1') /* Remove device */ + { + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + mvprintw(5, 6, "FRAME = %s POSITION: %s ACTION = REMOVE", p_frame, p_slot); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + mvprintw(5, 6, "DSA = %s UA = %s ACTION = REMOVE", p_dsa, p_ua); + } + else if (strlen(p_location) > 0) + { + mvprintw(5, 6, "Location = %s ACTION = REMOVE", p_location); + } + else + { + mvprintw(5, 4, "PCI Bus: %s PCI Device: %s", p_pci_bus, p_pci_device); + mvprintw(6, 4, "SCSI Channel: %s SCSI Id: %s SCSI Lun: %s ACTION = REMOVE", + p_scsi_channel, p_scsi_id, p_scsi_lun); + } + + if (p_resource_entry) + { + /* Remove the device from the midlayer */ + remove_device(p_resource_entry->resource_address, p_ioa); + + /* send evaluate device capabilities down */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = NULL; + ioa_cmd.buffer_len = 0; + resource_handle = sistoh32(p_resource_entry->resource_handle); + ioa_cmd.cdb[2] = (u8)(resource_handle >> 24); + ioa_cmd.cdb[3] = (u8)(resource_handle >> 16); + ioa_cmd.cdb[4] = (u8)(resource_handle >> 8); + ioa_cmd.cdb[5] = (u8)(resource_handle); + + fd = open(p_ioa->ioa.dev_name, O_RDWR); + if (fd != -1) + sis_ioctl(fd, IBMSIS_EVALUATE_DEVICE, &ioa_cmd); + } + } + else /* Insert device */ + { + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + mvprintw(5, 6, "FRAME = %s POSITION: %s ACTION = INSERT", p_frame, p_slot); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + mvprintw(5, 6, "DSA = %s UA = %s ACTION = INSERT", p_dsa, p_ua); + } + else if (strlen(p_location) > 0) + { + mvprintw(5, 6, "Location = %s ACTION = INSERT", p_location); + } + else + { + mvprintw(5, 4, "PCI Bus: %s PCI Device: %s", p_pci_bus, p_pci_device); + mvprintw(6, 4, "SCSI Channel: %s SCSI Id: %s SCSI Lun: %s ACTION = INSERT", + p_scsi_channel, p_scsi_id, p_scsi_lun); + } + } + + if (replace_dev && p_resource_entry && !p_resource_entry->is_array_member) + { + mvprintw(8, 4, "In order to make this device useable, it must be formatted."); + mvprintw(9, 4, "Press 'f' to proceed to the format screen."); + mvprintw(10, 4, "Or press 'c' to cancel."); + memset (&cur_dasd_init, 0, sizeof(struct devs_to_init_t)); + p_head_dev_to_init = p_tail_dev_to_init = &cur_dasd_init; + cur_dasd_init.p_sis_device = p_sis_device; + cur_dasd_init.p_ioa = p_ioa; + cur_dasd_init.do_init = 1; + cur_dasd_init.p_next = NULL; + } + else + { + mvprintw(11, 4, "Press 'c' to continue."); + } + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + unpost_form(p_form); + break; + } + else if (IS_CANCEL_KEY(ch) || (ch == 'c')) + { + rc = RC_CANCEL; + unpost_form(p_form); + break; + } + else if (((ch == 'f') || (ch == 'F')) && (replace_dev)) + { + unpost_form(p_form); + confirm_init_device(); + break; + } + else + { + unpost_form(p_form); + clear(); + goto refresh; + } + } + + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + p_head_dev_to_init = p_tail_dev_to_init = NULL; + return rc; +} + +int conc_maintenance_failed(char *p_frame, char *p_slot, char *p_dsa, char *p_ua, + char *p_location, char *p_pci_bus, char *p_pci_device, + char *p_scsi_channel, char *p_scsi_id, char *p_scsi_lun, char *p_action, int rc) +{ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form; + int frame = (strlen(p_frame) > 0) && (strlen(p_slot) > 0); + u32 dsa, ua; + int frame_id; + + if (!frame) + { + dsa = strtoul(p_dsa, NULL, 16); + ua = strtoul(p_ua, NULL, 16); + } + else + { + frame_id = strtoul(p_frame, NULL, 10); + } + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Concurrent Maintenance Results"); + + post_form(p_form); + + mvaddstr(3, 0, "THE CONCURRENT MAINTENANCE PROCEDURE HAS FAILED."); + + if (p_action[0] == '1') /* Remove device */ + { + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + mvprintw(5, 6, "FRAME = %s POSITION: %s ACTION = REMOVE", p_frame, p_slot); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + mvprintw(5, 6, "DSA = %s UA = %s ACTION = REMOVE", p_dsa, p_ua); + } + else if (strlen(p_location) > 0) + { + mvprintw(5, 6, "Location = %s ACTION = REMOVE", p_location); + } + else + { + mvprintw(5, 4, "PCI Bus: %s PCI Device: %s", p_pci_bus, p_pci_device); + mvprintw(6, 4, "SCSI Channel: %s SCSI Id: %s SCSI Lun: %s ACTION = REMOVE", + p_scsi_channel, p_scsi_id, p_scsi_lun); + } + } + else /* Insert device */ + { + if ((strlen(p_frame) > 0) && (strlen(p_slot) > 0)) + { + mvprintw(5, 6, "FRAME = %s POSITION: %s ACTION = INSERT", p_frame, p_slot); + } + else if ((strlen(p_dsa) > 0) && (strlen(p_ua) > 0)) + { + mvprintw(5, 6, "DSA = %s UA = %s ACTION = INSERT", p_dsa, p_ua); + } + else if (strlen(p_location) > 0) + { + mvprintw(5, 6, "Location = %s ACTION = INSERT", p_location); + } + else + { + mvprintw(5, 4, "PCI Bus: %s PCI Device: %s", p_pci_bus, p_pci_device); + mvprintw(6, 4, "SCSI Channel: %s SCSI Id: %s SCSI Lun: %s ACTION = INSERT", + p_scsi_channel, p_scsi_id, p_scsi_lun); + } + } + + + if (rc == RC_IN_USE) + mvaddstr(8, 0," Device concurrent maintenance failed, device in use"); + else if (rc == EACCES) + mvaddstr(8, 0," Device concurrent maintenance failed, device cannot be removed currently"); + + mvprintw(9, 4, "Press Enter to continue."); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + unpost_form(p_form); + break; + } + else if (IS_CANCEL_KEY(ch) || (ch == 'c')) + { + rc = RC_CANCEL; + unpost_form(p_form); + break; + } + else + { + rc = RC_CANCEL; + unpost_form(p_form); + break; + } + } + + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int battery_maint() +{ +#define BATTERY_HDR_SIZE 7 +#define BATTERY_MENU_SIZE 4 + /* + Work with Resources Containing Cache Battery Packs + + Type options, press Enter + 2=Force battery pack into error state 5=Display battery information + + Resource Frame Card + Opt Name Serial Number Type-Model ID Position + /dev/ibmsis5 02137002 2757-001 2 C02 + /dev/ibmsis4 03060044 5703-001 2 003 + /dev/ibmsis3 02127005 5703-001 1 C10 + /dev/ibmsis1 01205058 2778-001 2 C03 + /dev/ibmsis0 00103039 2748-001 2 002 + + e=Exit q=Cancel + + */ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form, *p_list_form; + int fd, rc, i, len, last_char; + struct ibmsis_reclaim_query_data *p_reclaim_buffer, *p_cur_reclaim_buffer; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + int num_lines = 0; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + struct sis_ioa *p_cur_ioa; + int max_size = curses_info.max_y - (BATTERY_HDR_SIZE + BATTERY_MENU_SIZE); + int num_needed = 0; + int ioa_num = 0, force_error; + char buffer[100], *p_char; + struct ibmsis_resource_entry *p_resource; + int show_battery_info(struct sis_ioa *p_ioa); + int confirm_force_battery_error(); + + rc = RC_SUCCESS; + + p_reclaim_buffer = (struct ibmsis_reclaim_query_data*)malloc(sizeof(struct ibmsis_reclaim_query_data) * num_ioas); + + p_title_win = newwin(BATTERY_HDR_SIZE, curses_info.max_x, 0, 0); + p_menu_win = newwin(BATTERY_MENU_SIZE, curses_info.max_x, max_size + BATTERY_HDR_SIZE, 0); + p_field_win = newwin(max_size, curses_info.max_x, BATTERY_HDR_SIZE, 0); + + clear(); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Work with Resources Containing Cache Battery Packs"); /* string value to set */ + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + mvwaddstr(p_title_win, 2, 0, + "Type options, press Enter"); + mvwaddstr(p_title_win, 3, 0, + " 2=Force battery pack into error state 5=Display battery information"); + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 5, 0, + " Resource Frame Card"); + mvwaddstr(p_title_win, 6, 0, + "Opt Name Serial Number Type-Model ID Position"); + } + else if (platform == SIS_PSERIES) + { + mvwaddstr(p_title_win, 5, 0, + " Resource PCI PCI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "Opt Name Serial Number Type-Model Location Bus Device Host"); + } + else + { + mvwaddstr(p_title_win, 5, 0, + " Resource PCI PCI SCSI"); + mvwaddstr(p_title_win, 6, 0, + "Opt Name Serial Number Type-Model Bus Device Host"); + } + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + for (p_cur_ioa = p_head_sis_ioa, p_cur_reclaim_buffer = p_reclaim_buffer; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next, p_cur_reclaim_buffer++) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + continue; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_reclaim_buffer; + ioa_cmd.buffer_len = sizeof(struct ibmsis_reclaim_query_data); + ioa_cmd.cdb[1] = IBMSIS_RECLAIM_QUERY | IBMSIS_RECLAIM_EXTENDED_INFO; + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_RECLAIM_CACHE_STORE, &ioa_cmd); + + if (rc != 0) + { + if (errno != EINVAL) + { + syslog(LOG_ERR, "Reclaim Query to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + } + close(fd); + p_cur_ioa->p_reclaim_data = NULL; + continue; + } + + close(fd); + + p_cur_ioa->p_reclaim_data = p_cur_reclaim_buffer; + + if (p_cur_reclaim_buffer->rechargeable_battery_type) + { + num_needed++; + } + } + + if (num_needed) + { + p_cur_ioa = p_head_sis_ioa; + + while(p_cur_ioa) + { + if ((p_cur_ioa->p_reclaim_data) && + (p_cur_ioa->p_reclaim_data->rechargeable_battery_type)) + { + start_y = ioa_num % (max_size - 1); + + if ((num_lines > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, 0, 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 2)); + pp_field[field_index] = new_field(1, 1, start_y, 1, 0, 0); + set_field_userptr(pp_field[field_index++], (char *)p_cur_ioa); + + /* Description field */ + pp_field[field_index] = new_field(1, curses_info.max_x - 4, + start_y, 4, 0, 0); + + p_resource = p_cur_ioa->ioa.p_resource_entry; + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, "%s %8s %x-001 %s %s", + p_cur_ioa->ioa.dev_name, + p_cur_ioa->serial_num, + p_cur_ioa->ccin, + p_resource->frame_id, + p_resource->slot_label); + } + else if (platform == SIS_PSERIES) + { + len = sprintf(buffer, "%s %8s %x-001 %s %d %d %d", + p_cur_ioa->ioa.dev_name, + p_cur_ioa->serial_num, + p_cur_ioa->ccin, + p_resource->pseries_location, + p_resource->pci_bus_number, + p_resource->pci_slot, + p_resource->host_no); + } + else + { + len = sprintf(buffer, "%s %8s %x-001 %d %d %d", + p_cur_ioa->ioa.dev_name, + p_cur_ioa->serial_num, + p_cur_ioa->ccin, + p_resource->pci_bus_number, + p_resource->pci_slot, + p_resource->host_no); + } + + set_field_buffer(pp_field[field_index], 0, buffer); + field_opts_off(pp_field[field_index], O_ACTIVE); + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + len = 0; + num_lines++; + ioa_num++; + } + p_cur_reclaim_buffer++; + p_cur_ioa = p_cur_ioa->p_next; + + } + + field_opts_off(p_fields[1], O_ACTIVE); + + ioa_num = ((max_size - 1) * 2) + 1; + for (i = ioa_num; i < field_index; i += ioa_num) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + form_driver(p_list_form, + REQ_FIRST_FIELD); + + while(1) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if (IS_PGUP_KEY(ch)) + { + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + break; + } + else if ((ch == KEY_DOWN) || + (ch == '\t')) + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + break; + } + else if (ch == KEY_UP) + { + form_driver(p_list_form, + REQ_PREV_FIELD); + break; + } + else if (IS_ENTER_KEY(ch)) + { + force_error = 0; + + for (i = 0; i < field_index; i++) + { + p_cur_ioa = (struct sis_ioa *)field_userptr(pp_field[i]); + if (p_cur_ioa != NULL) + { + p_char = field_buffer(pp_field[i], 0); + + if (strcmp(p_char, "2") == 0) + { + force_error++; + p_cur_ioa->ioa.is_reclaim_cand = 1; + } + else if (strcmp(p_char, "5") == 0) + { + rc = show_battery_info(p_cur_ioa); + if (rc == RC_CANCEL) + rc = RC_REFRESH; + goto leave; + } + else + { + p_cur_ioa->ioa.is_reclaim_cand = 0; + } + } + } + + if (force_error) + { + rc = confirm_force_battery_error(); + if (rc == RC_CANCEL) + rc = RC_REFRESH; + goto leave; + } + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + break; + } + } + } + } + else + { + rc = RC_NOOP; + goto leave; + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free(p_reclaim_buffer); + free(pp_field); + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int confirm_force_battery_error() +{ +#define BATTERY_CNF_HDR_SIZE 17 +#define BATTERY_CNF_MENU_SIZE 4 + /* + Force Battery Packs Into Error State + + ATTENTION: This service function should be run only under the direction + of the IBM Hardware Service Support + + You have selected to force a cache batter error on an IOA + + You will have to replace the Cache Battery Pack in each selected IOA to + resume normal operations. + + System performance could be significantly degraded until the cache battery + packs are replaced on the selected IOAs. + + Press c=Continue to force the following battery packs into an error state + + Resource Frame Card + Opt Name Serial Number Type-Model ID Position + 2 /dev/ibmsis5 02137002 2757-001 2 C02 + 2 /dev/ibmsis4 03060044 5703-001 2 003 + 2 /dev/ibmsis3 02127005 5703-001 1 C10 + More... + + e=Exit q=Cancel f=PageDn b=PageUp + + */ + FIELD *p_fields[3]; + FORM *p_form, *p_old_form, *p_list_form; + int fd, rc, i, len, last_char, reclaim_rc; + struct ibmsis_reclaim_query_data reclaim_buffer; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_resource_entry *p_resource; + int num_lines = 0; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + struct sis_ioa *p_cur_ioa; + int max_size = curses_info.max_y - (BATTERY_CNF_HDR_SIZE + BATTERY_CNF_MENU_SIZE); + int ioa_num = 0; + char buffer[100]; + int init_page, new_page; + + reclaim_rc = rc = RC_SUCCESS; + + p_title_win = newwin(BATTERY_CNF_HDR_SIZE, curses_info.max_x, 0, 0); + p_menu_win = newwin(BATTERY_CNF_MENU_SIZE, curses_info.max_x, max_size + BATTERY_CNF_HDR_SIZE, 0); + p_field_win = newwin(max_size, curses_info.max_x, BATTERY_CNF_HDR_SIZE, 0); + + clear(); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Force Battery Packs Into Error State"); /* string value to set */ + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + wattron(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 2, 0, "ATTENTION:"); + wattroff(p_title_win, A_BOLD); + mvwaddstr(p_title_win, 2, 10, + " This service function should be run only under the direction"); + mvwaddstr(p_title_win, 3, 0, + "of the IBM Hardware Service Support"); + mvwaddstr(p_title_win, 5, 0, + "You have selected to force a cache batter error on an IOA"); + mvwaddstr(p_title_win, 7, 0, + "You will have to replace the Cache Battery Pack in each selected IOA to"); + mvwaddstr(p_title_win, 8, 0, + "resume normal operations."); + mvwaddstr(p_title_win, 10, 0, + "System performance could be significantly degraded until the cache battery"); + mvwaddstr(p_title_win, 11, 0, + "packs are replaced on the selected IOAs."); + mvwaddstr(p_title_win, 13, 0, + "Press c=Continue to force the following battery packs into an error state"); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 15, 0, + " Resource Frame Card"); + mvwaddstr(p_title_win, 16, 0, + "Opt Name Serial Number Type-Model ID Position"); + } + else if (platform == SIS_PSERIES) + { + mvwaddstr(p_title_win, 15, 0, + " Resource PCI PCI SCSI"); + mvwaddstr(p_title_win, 16, 0, + "Opt Name Serial Number Type-Model Location Bus Device Host"); + } + else + { + mvwaddstr(p_title_win, 15, 0, + " Resource PCI PCI SCSI"); + mvwaddstr(p_title_win, 16, 0, + "Opt Name Serial Number Type-Model Bus Device Host"); + } + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + p_cur_ioa = p_head_sis_ioa; + + while(p_cur_ioa) + { + if ((p_cur_ioa->p_reclaim_data) && + (p_cur_ioa->ioa.is_reclaim_cand)) + { + start_y = ioa_num % (max_size - 1); + + if ((num_lines > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, 0, 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + start_y, 0, 0, 0); + + p_resource = p_cur_ioa->ioa.p_resource_entry; + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, " 2 %s %8s %x-001 %s %s", + p_cur_ioa->ioa.dev_name, + p_cur_ioa->serial_num, + p_cur_ioa->ccin, + p_resource->frame_id, + p_resource->slot_label); + } + else if (platform == SIS_PSERIES) + { + len = sprintf(buffer, " 2 %s %8s %x-001 %s %d %d %d", + p_cur_ioa->ioa.dev_name, + p_cur_ioa->serial_num, + p_cur_ioa->ccin, + p_resource->pseries_location, + p_resource->pci_bus_number, + p_resource->pci_slot, + p_resource->host_no); + } + else + { + len = sprintf(buffer, " 2 %s %8s %x-001 %d %d %d", + p_cur_ioa->ioa.dev_name, + p_cur_ioa->serial_num, + p_cur_ioa->ccin, + p_resource->pci_bus_number, + p_resource->pci_slot, + p_resource->host_no); + } + + set_field_buffer(pp_field[field_index], 0, buffer); + field_opts_off(pp_field[field_index], O_EDIT); + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + len = 0; + num_lines++; + ioa_num++; + } + p_cur_ioa = p_cur_ioa->p_next; + } + + field_opts_off(p_fields[1], O_ACTIVE); + + ioa_num = max_size; + for (i = ioa_num; i < field_index; i += ioa_num) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + + while(1) + { + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + init_page = form_page(p_list_form); + form_driver(p_list_form, + REQ_NEXT_PAGE); + + new_page = form_page(p_list_form); + + if (new_page > init_page) + { + } + else + { + form_driver(p_list_form, + REQ_PREV_PAGE); + } + break; + } + else if (IS_PGUP_KEY(ch)) + { + init_page = form_page(p_list_form); + form_driver(p_list_form, + REQ_PREV_PAGE); + + new_page = form_page(p_list_form); + + if (new_page < init_page) + { + } + else + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + } + break; + } + else if ((ch == 'c') || + (ch == 'C')) + { + while(p_cur_ioa) + { + if ((p_cur_ioa->p_reclaim_data) && + (p_cur_ioa->ioa.is_reclaim_cand)) + { + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + reclaim_rc = RC_FAILED; + continue; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &reclaim_buffer; + ioa_cmd.buffer_len = sizeof(struct ibmsis_reclaim_query_data); + ioa_cmd.cdb[1] = IBMSIS_RECLAIM_FORCE_BATTERY_ERROR; + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_RECLAIM_CACHE_STORE, &ioa_cmd); + + close(fd); + if (rc != 0) + { + if (errno != EINVAL) + { + syslog(LOG_ERR, + "Reclaim to %s for Battery Maintenance failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + reclaim_rc = RC_FAILED; + } + } + + if (reclaim_buffer.action_status != + IBMSIS_ACTION_SUCCESSFUL) + { + syslog(LOG_ERR, + "Battery Force Error to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + reclaim_rc = RC_FAILED; + } + } + p_cur_ioa = p_cur_ioa->p_next; + } + return reclaim_rc; + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + break; + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free(pp_field); + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int show_battery_info(struct sis_ioa *p_ioa) +{ + /* + Battery Information + + + Resource Name . . . . . . . . . . . : /dev/ibmsis5 + Serial Number . . . . . . . . . . . : 02137002 + Type-model . . . . . . . . . . . . : 2757-001 + Frame ID . . . . . . . . . . . . . : 2 + Card position . . . . . . . . . . . : C02 + Battery type . . . . . . . . . . . : Lithium Ion (LiIon) + Battery state . . . . . . . . . . . : No battery warning + Power on time (days) . . . . . . . : 3 + Adjusted power on time (days) . . . : 3 + Estimated time to warning (days) . : 939 + Estimated time to error (days) . . : 1030 + + Press Enter to continue. + + e=Exit q=Cancel + */ + + FIELD *p_fields[3]; + FORM *p_form; + FORM *p_old_form; + int rc; + struct ibmsis_resource_entry *p_resource = + p_ioa->ioa.p_resource_entry; + int field_index; + struct ibmsis_reclaim_query_data *p_reclaim_data = + p_ioa->p_reclaim_data; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], 0, "Battery Information"); + + post_form(p_form); + + field_index = 3; + + mvprintw(field_index++, 1, "Resource Name . . . . . . . . . . . : %s", p_ioa->ioa.dev_name); + mvprintw(field_index++, 1, "Serial Number . . . . . . . . . . . : %-8s", p_resource->serial_num); + mvprintw(field_index++, 1, "Type-model . . . . . . . . . . . . : %X-001", p_ioa->ccin); + + if (platform == SIS_ISERIES) + { + mvprintw(field_index++, 1, "Frame ID . . . . . . . . . . . . . : %s", p_resource->frame_id); + mvprintw(field_index++, 1, "Card position . . . . . . . . . . . : %s", p_resource->slot_label); + } + else + { + if (platform == SIS_PSERIES) + mvprintw(field_index++, 1, + "Location . . . . . . . . . . . . . : %s", p_resource->pseries_location); + + mvprintw(field_index++, 1, "PCI Bus . . . . . . . . . . . . . . : %d", p_resource->pci_bus_number); + mvprintw(field_index++, 1, "PCI Device . . . . . . . . . . . . : %d", p_resource->pci_slot); + mvprintw(field_index++, 1, "SCSI Host Number . . . . . . . . . : %d", p_resource->host_no); + } + + switch (p_reclaim_data->rechargeable_battery_type) + { + case IBMSIS_BATTERY_TYPE_NICD: + mvprintw(field_index++, 1, "Battery type . . . . . . . . . . . : Nickel Cadmium (NiCd)"); + break; + case IBMSIS_BATTERY_TYPE_NIMH: + mvprintw(field_index++, 1, "Battery type . . . . . . . . . . . : Nickel Metal Hydride (NiMH)"); + break; + case IBMSIS_BATTERY_TYPE_LIION: + mvprintw(field_index++, 1, "Battery type . . . . . . . . . . . : Lithium Ion (LiIon)"); + break; + default: + break; + } + + switch (p_reclaim_data->rechargeable_battery_error_state) + { + case IBMSIS_BATTERY_NO_ERROR_STATE: + mvprintw(field_index++, 1, "Battery state . . . . . . . . . . . : No battery warning"); + break; + case IBMSIS_BATTERY_WARNING_STATE: + mvprintw(field_index++, 1, "Battery state . . . . . . . . . . . : Battery warning issued"); + break; + case IBMSIS_BATTERY_ERROR_STATE: + mvprintw(field_index++, 1, "Battery state . . . . . . . . . . . : Battery error issued"); + break; + default: + break; + } + + mvprintw(field_index++, 1, "Power on time (days) . . . . . . . : %d", + p_reclaim_data->raw_power_on_time); + mvprintw(field_index++, 1, "Adjusted power on time (days) . . . : %d", + p_reclaim_data->adjusted_power_on_time); + mvprintw(field_index++, 1, "Estimated time to warning (days) . : %d", + p_reclaim_data->estimated_time_to_battery_warning); + mvprintw(field_index++, 1, "Estimated time to error (days) . . : %d", + p_reclaim_data->estimated_time_to_battery_failure); + + mvprintw(curses_info.max_y - 4, 1, "Press Enter to continue."); + mvprintw(curses_info.max_y - 2, 1, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + while(1) + { + form_driver(p_form, + REQ_LAST_FIELD); + refresh(); + + while(1) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + } + } + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free_screen(NULL, NULL, p_fields); + + flush_stdscr(); + return rc; +} + +void configure_options() +{ + /* + Work with Configuration + + Select one of the following: + + 1. Work with SCSI bus configuration + 2. Work with driver configuration + 3. Work with disk unit configuration + + + + + + Selection: + + e=Exit q=Cancel + */ + FIELD *p_fields[12]; + FORM *p_form, *p_old_form; + int invalid = 0; + int rc = RC_SUCCESS; + int j; + int bus_config(); + int driver_config(); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 2, /* new field size */ + 12, 12, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Work with Configuration"); /* string value to set */ + + flush_stdscr(); + + clear(); + + post_form(p_form); + + while(1) + { + mvaddstr(2, 0, "Select one of the following:"); + mvaddstr(4, 0, " 1. Work with SCSI bus configuration"); + mvaddstr(5, 0, " 2. Work with driver configuration"); + mvaddstr(6, 0, " 3. Work with disk unit configuration"); + mvaddstr(12, 0, "Selection: "); + mvaddstr(curses_info.max_y - 2, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + if (invalid) + { + invalid = 0; + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + } + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + refresh(); + for (;;) + { + int ch = getch(); + + if (IS_ENTER_KEY(ch)) + { + char *p_char; + refresh(); + unpost_form(p_form); + p_char = field_buffer(p_fields[1], 0); + + switch(p_char[0]) + { + case '1': /* Work with scsi bus attributes */ + while (RC_REFRESH == (rc = bus_config())) + if (RC_EXIT == rc) + goto leave; + clear(); + post_form(p_form); + if (rc == RC_FAILED) + mvaddstr(curses_info.max_y - 1, 0, + " Change SCSI Bus configurations failed"); + else if (rc == RC_SUCCESS) + mvaddstr(curses_info.max_y - 1, 0, + " Change SCSI Bus configurations completed successfully"); + break; + case '2': /* Work with device driver configuration */ + if (RC_EXIT == (rc = driver_config())) + goto leave; + clear(); + post_form(p_form); + if (rc == RC_FAILED) + mvaddstr(curses_info.max_y - 1, 0, + " Change Device Driver Configurations failed"); + else if (rc == RC_SUCCESS) + mvaddstr(curses_info.max_y - 1, 0, + " Change Device Driver Configurations completed successfully"); + break; + case '3': /* Work with device configuration */ + while (RC_REFRESH == (rc = configure_device())); + if (rc == RC_EXIT) + goto leave; + clear(); + post_form(p_form); + break; + case ' ': + clear(); + post_form(p_form); + break; + default: + clear(); + post_form(p_form); + mvaddstr(curses_info.max_y - 1, 0, "Invalid option specified."); + break; + } + form_driver(p_form, ' '); + refresh(); + break; + } + else if (IS_EXIT_KEY(ch)) + goto leave; + else if (IS_CANCEL_KEY(ch)) + goto leave; + else + { + form_driver(p_form, ch); + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + for (j=0; j < 2; j++) + free_field(p_fields[j]); + flush_stdscr(); + return; +} + + +int bus_config() +{ +/* iSeries + Work with SCSI Bus Configuration + +Select the subsystem to change scsi bus attribute. + +Type choice, press Enter. + 1=change scsi bus attribute + + Serial Resource +Option Number Type Model Name + 02137002 2757 001 /dev/ibmsis6 + 03060044 5703 001 /dev/ibmsis5 + 02127005 2782 001 /dev/ibmsis4 + 02123028 5702 001 /dev/ibmsis3 + +e=Exit q=Cancel f=PageDn b=PageUp +*/ +/* non-iSeries + Work with SCSI Bus Configuration + +Select the subsystem to change scsi bus attribute. + +Type choice, press Enter. + 1=change scsi bus attribute + + Vendor Product Serial PCI PCI +Option ID ID Number Bus Dev + IBM 2780001 3AFB348C 05 03 + IBM 5703001 A775915E 04 01 + +e=Exit q=Cancel f=PageDn b=PageUp +*/ + int rc, i, config_num, last_char; + struct array_cmd_data *p_cur_raid_cmd; + FIELD *p_fields[3]; + FORM *p_form, *p_list_form, *p_old_form; + char buffer[100]; + int array_index; + int max_size = curses_info.max_y - 12; + int num_lines = 0; + struct sis_ioa *p_cur_ioa; + u32 len; + WINDOW *p_title_win, *p_menu_win, *p_field_win; + FIELD **pp_field = NULL; + int start_y; + int field_index = 0; + int found = 0; + char *p_char; + int ch; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + u8 ioctl_buffer[255]; + struct ibmsis_mode_parm_hdr *p_mode_parm_header; + struct ibmsis_mode_page_28_header *p_modepage_28_header; + int fd; + + int change_bus_attr(struct sis_ioa *p_cur_ioa); + + rc = RC_SUCCESS; + + p_title_win = newwin(9, curses_info.max_x, 0, 0); + p_menu_win = newwin(3, curses_info.max_x, max_size + 9, 0); + p_field_win = newwin(max_size, curses_info.max_x, 9, 0); + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[1] = new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Work with SCSI Bus Configuration"); /* string value to set */ + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_form_win(p_form, p_title_win); + + post_form(p_form); + + config_num = 0; + + check_current_config(false); + + for(p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + /* mode sense page28 to focal point */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + p_mode_parm_header = (struct ibmsis_mode_parm_hdr *)ioctl_buffer; + + ioa_cmd.buffer = p_mode_parm_header; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0x28; + ioa_cmd.read_not_write = 1; + ioa_cmd.driver_cmd = 1; + + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + continue; + } + + rc = sis_ioctl(fd, IBMSIS_MODE_SENSE_PAGE_28, &ioa_cmd); + close(fd); + + if (rc != 0) + { + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + continue; + } + + p_modepage_28_header = (struct ibmsis_mode_page_28_header *) (p_mode_parm_header + 1); + + if (p_modepage_28_header->num_dev_entries == 0) + continue; + + start_y = (config_num) % (max_size - 1); + + if ((num_lines > 0) && (start_y == 0)) + { + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x, + max_size - 1, + 0, + 0, 0); + + set_field_just(pp_field[field_index], JUSTIFY_RIGHT); + set_field_buffer(pp_field[field_index], 0, "More... "); + set_field_userptr(pp_field[field_index], NULL); + field_opts_off(pp_field[field_index++], + O_ACTIVE); + } + + /* User entry field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, 1, start_y, 3, 0, 0); + + set_field_userptr(pp_field[field_index++], (char *)p_cur_ioa); + + /* Description field */ + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = new_field(1, curses_info.max_x - 9, start_y, 9, 0, 0); + + if (platform == SIS_ISERIES) + { + len = sprintf(buffer, "%8s %x 001 %s", + p_cur_ioa->serial_num, + p_cur_ioa->ccin, + p_cur_ioa->ioa.dev_name); + } + else + { + char buf[100]; + + memcpy(buf, p_cur_ioa->ioa.p_resource_entry->std_inq_data.vpids.vendor_id, + IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len = sprintf(buffer, "%-8s ", buf); + + memcpy(buf, p_cur_ioa->ioa.p_resource_entry->std_inq_data.vpids.product_id, + IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(buffer + len, "%-12s ", buf); + + len += sprintf(buffer + len, "%8s ", + p_cur_ioa->ioa.p_resource_entry->serial_num); + + len += sprintf(buffer + len, "%02d %02d", + p_cur_ioa->ioa.p_resource_entry->pci_bus_number, + p_cur_ioa->ioa.p_resource_entry->pci_slot); + } + + set_field_buffer(pp_field[field_index], 0, buffer); + field_opts_off(pp_field[field_index], O_ACTIVE); + set_field_userptr(pp_field[field_index++], NULL); + + memset(buffer, 0, 100); + + len = 0; + num_lines++; + config_num++; + } + + if (config_num == 0) + { + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Work with SCSI Bus Configuration Failed"); /* string value to set */ + + mvwaddstr(p_title_win, 2, 0, "There are no SCSI Buses eligible for the selected operation."); + mvwaddstr(p_title_win, 3, 0, "None of the installed adapters support the requested"); + mvwaddstr(p_title_win, 4, 0, "operation."); + mvwaddstr(p_field_win, max_size -1, 0, "Press Enter to continue."); + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD); /* form request code */ + + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + for (;;) + { + ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + } + } + + mvwaddstr(p_title_win, 2, 0, "Select the subsystem to change scsi bus attribute."); + mvwaddstr(p_title_win, 4, 0, "Type choice, press Enter."); + mvwaddstr(p_title_win, 5, 0, " 1=change scsi bus attribute"); + + if (platform == SIS_ISERIES) + { + mvwaddstr(p_title_win, 7, 0, " Serial Resource"); + mvwaddstr(p_title_win, 8, 0, "Option Number Type Model Name"); + } + else + { + mvwaddstr(p_title_win, 7, 0, " Vendor Product Serial PCI PCI"); + mvwaddstr(p_title_win, 8, 0, "Option ID ID Number Bus Dev"); + } + + mvwaddstr(p_menu_win, 1, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel f=PageDn b=PageUp"); + + + field_opts_off(p_fields[1], O_ACTIVE); + + array_index = ((max_size - 1) * 2) + 1; + for (i = array_index; i < field_index; i += array_index) + set_new_page(pp_field[i], TRUE); + + pp_field = realloc(pp_field, sizeof(FIELD **) * (field_index + 1)); + pp_field[field_index] = NULL; + + flush_stdscr(); + + p_list_form = new_form(pp_field); + + set_form_win(p_list_form, p_field_win); + + post_form(p_list_form); + + form_driver(p_list_form, + REQ_FIRST_FIELD); + + while(1) + { + wnoutrefresh(stdscr); + wnoutrefresh(p_menu_win); + wnoutrefresh(p_title_win); + wnoutrefresh(p_field_win); + doupdate(); + + ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (IS_PGDN_KEY(ch)) + { + form_driver(p_list_form, + REQ_NEXT_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + } + else if (IS_PGUP_KEY(ch)) + { + form_driver(p_list_form, + REQ_PREV_PAGE); + form_driver(p_list_form, + REQ_FIRST_FIELD); + } + else if ((ch == KEY_DOWN) || + (ch == '\t')) + { + form_driver(p_list_form, + REQ_NEXT_FIELD); + } + else if (ch == KEY_UP) + { + form_driver(p_list_form, + REQ_PREV_FIELD); + } + else if (IS_ENTER_KEY(ch)) + { + found = 0; + unpost_form(p_list_form); + + for (i = 0; i < field_index; i++) + { + p_cur_ioa = (struct sis_ioa *)field_userptr(pp_field[i]); + if (p_cur_ioa != NULL) + { + p_char = field_buffer(pp_field[i], 0); + if (strcmp(p_char, "1") == 0) + { + rc = change_bus_attr(p_cur_ioa); + + if (rc == RC_EXIT) + goto leave; + } + } + } + + if (rc == RC_CANCEL) + rc = RC_REFRESH; + goto leave; + } + else + { + /* Terminal is running under 5250 telnet */ + if (term_is_5250) + { + /* Send it to the form to be processed and flush this line */ + form_driver(p_list_form, ch); + last_char = flush_line(); + if (IS_5250_CHAR(last_char)) + ungetch(ENTER_KEY); + else if (last_char != ERR) + ungetch(last_char); + } + else + { + form_driver(p_list_form, ch); + } + } + } + + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + free(pp_field); + + p_cur_raid_cmd = p_head_raid_cmd; + while(p_cur_raid_cmd) + { + p_cur_raid_cmd = p_cur_raid_cmd->p_next; + free(p_head_raid_cmd); + p_head_raid_cmd = p_cur_raid_cmd; + } + + delwin(p_title_win); + delwin(p_menu_win); + delwin(p_field_win); + free_screen(NULL, NULL, p_fields); + flush_stdscr(); + return rc; +} + +int change_bus_attr(struct sis_ioa *p_cur_ioa) +{ + /* + Change SCSI Bus Configuration + + Current Bus configurations are shown. To change + setting hit "c" for options menu. Highlight desired + option then hit Enter + + c=Change Setting + + /dev/ibmsis1 + BUS 0 + Wide Enabled . . . . . . . . . . . . : Yes + Maximum Bus Throughput . . . . . . . : 40 MB/s + BUS 1 + Wide Enabled . . . . . . . . . . . . : Yes + Maximum Bus Throughput . . . . . . . : 40 MB/s + + Press Enter to Continue + + e=Exit q=Cancel + */ +#define DSP_FIELD_START_ROW 9 + int rc, j, i; + FORM *p_form, *p_old_form; + FORM *p_fields_form; + FIELD **p_input_fields, *p_cur_field; + FIELD *p_title_fields[3]; + WINDOW *p_field_pad; + int cur_field_index; + char buffer[100]; + int input_field_index = 0; + int num_lines = 0; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + u8 ioctl_buffer0[255]; + u8 ioctl_buffer1[255]; + u8 ioctl_buffer2[255]; + struct ibmsis_mode_parm_hdr *p_mode_parm_hdr; + int fd; + struct ibmsis_page_28 *p_page_28_sense; + struct sis_page_28 *p_page_28_cur, *p_page_28_chg, *p_page_28_dflt; + struct sis_page_28 page_28_sis; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_resource_table *p_res_table; + char scsi_id_str[5][16]; + char max_xfer_rate_str[5][16]; + int ch; + int form_rows, form_cols; + int field_start_row, field_end_row, field_num_rows; + int pad_start_row; + int form_adjust = 0; + int confirm = 0; + int is_reset_req; + int bus_attr_menu(struct sis_ioa *p_cur_ioa, + struct sis_page_28 *p_page_28_cur, + struct sis_page_28 *p_page_28_chg, + struct sis_page_28 *p_page_28_dflt, + struct sis_page_28 *p_page_28_sis, + int cur_field_index, + int offset); + + rc = RC_SUCCESS; + + /* zero out user page 28 page, this data is used to indicate + which fields the user changed */ + memset(&page_28_sis, 0, sizeof(struct sis_page_28)); + + /* mode sense page28 to get current parms */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer0; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0x28; + ioa_cmd.read_not_write = 1; + ioa_cmd.driver_cmd = 1; + + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + return RC_FAILED; + } + + rc = sis_ioctl(fd, IBMSIS_MODE_SENSE_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + close(fd); + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return RC_FAILED; + } + + p_page_28_sense = (struct ibmsis_page_28 *)p_mode_parm_hdr; + p_page_28_cur = (struct sis_page_28 *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + /* now issue mode sense to get changeable parms */ + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer1; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0x68; + + rc = sis_ioctl(fd, IBMSIS_MODE_SENSE_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + close(fd); + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return RC_FAILED; + } + + p_page_28_chg = (struct sis_page_28 *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + /* now Issue mode sense to get default parms */ + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)ioctl_buffer2; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0xA8; + + rc = sis_ioctl(fd, IBMSIS_MODE_SENSE_PAGE_28, &ioa_cmd); + close(fd); + + if (rc != 0) + { + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return RC_FAILED; + } + + p_page_28_dflt = (struct sis_page_28 *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + /* Title */ + p_title_fields[0] = + new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_title_fields[1] = + new_field(1, 1, /* new field size */ + 1, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_title_fields[2] = NULL; + + set_field_just(p_title_fields[0], JUSTIFY_CENTER); + + set_field_buffer(p_title_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Change SCSI Bus Configuration"); /* string value to set */ + + field_opts_off(p_title_fields[0], O_ACTIVE); + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_title_fields); + + p_input_fields = malloc(sizeof(FIELD *)); + + /* Loop for each device bus entry */ + for (j = 0, + num_lines = 0; + j < p_page_28_cur->page_hdr.num_dev_entries; + j++) + { + p_input_fields = realloc(p_input_fields, + sizeof(FIELD *) * (input_field_index + 1)); + p_input_fields[input_field_index] = + new_field(1, 6, + num_lines, 2, + 0, 0); + + field_opts_off(p_input_fields[input_field_index], O_ACTIVE); + memset(buffer, 0, 100); + sprintf(buffer,"BUS %d", + p_page_28_cur->attr[j].res_addr.bus); + + set_field_buffer(p_input_fields[input_field_index++], + 0, + buffer); + + num_lines++; + if (p_page_28_chg->attr[j].qas_capability) + { + /* options are ENABLED(10)/DISABLED(01) */ + p_input_fields = realloc(p_input_fields, + sizeof(FIELD *) * (input_field_index + 2)); + p_input_fields[input_field_index] = + new_field(1, 38, + num_lines, 4, + 0, 0); + + field_opts_off(p_input_fields[input_field_index], O_ACTIVE); + set_field_buffer(p_input_fields[input_field_index++], + 0, + "QAS Capability . . . . . . . . . . . :"); + + p_input_fields[input_field_index++] = + new_field(1, 9, /* new field size */ + num_lines, 44, /* */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + num_lines++; + } + if (p_page_28_chg->attr[j].scsi_id) + { + /* options are based on current scsi ids currently in use + value must be 15 or less */ + p_input_fields = realloc(p_input_fields, + sizeof(FIELD *) * (input_field_index + 2)); + p_input_fields[input_field_index] = + new_field(1, 38, + num_lines, 4, + 0, 0); + + field_opts_off(p_input_fields[input_field_index], O_ACTIVE); + set_field_buffer(p_input_fields[input_field_index++], + 0, + "Host SCSI ID . . . . . . . . . . . . :"); + + p_input_fields[input_field_index++] = + new_field(1, 3, /* new field size */ + num_lines, 44, /* */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + num_lines++; + } + if (p_page_28_chg->attr[j].bus_width) + { + /* check if 8 bit bus is allowable with current configuration before + enabling option */ + p_res_table = p_cur_ioa->p_resource_table; + + for (i=0; + i < p_res_table->hdr.num_entries; + i++) + { + p_resource_entry = &p_res_table->dev[i]; + if ((!p_resource_entry->is_ioa_resource) + && (p_resource_entry->resource_address.target & 0xF8) + && (p_page_28_cur->attr[j].res_addr.bus == + p_resource_entry->resource_address.bus)) + { + p_page_28_chg->attr[j].bus_width = 0; + break; + } + } + + } + if (p_page_28_chg->attr[j].bus_width) + { + /* options for "Wide Enabled" (bus width), No(8) or Yes(16) bits wide */ + p_input_fields = realloc(p_input_fields, + sizeof(FIELD *) * (input_field_index + 2)); + p_input_fields[input_field_index] = + new_field(1, 38, + num_lines, 4, + 0, 0); + + field_opts_off(p_input_fields[input_field_index], O_ACTIVE); + set_field_buffer(p_input_fields[input_field_index++], + 0, + "Wide Enabled . . . . . . . . . . . . :"); + + p_input_fields[input_field_index++] = + new_field(1, 4, /* new field size */ + num_lines, 44, /* */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + num_lines++; + } + if (p_page_28_chg->attr[j].max_xfer_rate) + { + /* options are 5, 10, 20, 40, 80, 160, 320 */ + p_input_fields = realloc(p_input_fields, + sizeof(FIELD *) * (input_field_index + 2)); + p_input_fields[input_field_index] = + new_field(1, 38, + num_lines, 4, + 0, 0); + + field_opts_off(p_input_fields[input_field_index], O_ACTIVE); + set_field_buffer(p_input_fields[input_field_index++], + 0, + "Maximum Bus Throughput . . . . . . . :"); + + p_input_fields[input_field_index++] = + new_field(1, 9, /* new field size */ + num_lines, 44, /* */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + num_lines++; + } + } + + p_input_fields[input_field_index] = NULL; + + p_fields_form = new_form(p_input_fields); + scale_form(p_fields_form, &form_rows, &form_cols); + p_field_pad = newpad(form_rows, form_cols); + set_form_win(p_fields_form, p_field_pad); + set_current_field(p_fields_form, p_input_fields[0]); + for (i = 0; i < input_field_index; i++) + { + field_opts_off(p_input_fields[i], O_EDIT); + } + + form_opts_off(p_fields_form, O_BS_OVERLOAD); + + flush_stdscr(); + clear(); + post_form(p_form); + post_form(p_fields_form); + + field_start_row = DSP_FIELD_START_ROW; + field_end_row = curses_info.max_y - 4; + field_num_rows = field_end_row - field_start_row + 1; + + mvaddstr(2, 1, "Current Bus configurations are shown. To change"); + mvaddstr(3, 1, "setting hit \"c\" for options menu. Highlight desired"); + mvaddstr(4, 1, "option then hit Enter"); + mvaddstr(6, 1, "c=Change Setting"); + if (field_num_rows < form_rows) + { + mvaddstr(field_end_row, 43, "More..."); + mvaddstr(curses_info.max_y - 2, 25, "f=PageDn"); + field_end_row--; + field_num_rows--; + } + mvaddstr(curses_info.max_y - 3, 1, "Press Enter to Continue"); + mvaddstr(curses_info.max_y - 2, 1, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + memset(buffer, 0, 100); + sprintf(buffer,"%s", + p_cur_ioa->ioa.dev_name); + mvaddstr(8, 1, buffer); + + refresh(); + pad_start_row = 0; + pnoutrefresh(p_field_pad, + pad_start_row, 0, + field_start_row, 0, + field_end_row, + curses_info.max_x); + doupdate(); + + form_driver(p_fields_form, + REQ_FIRST_FIELD); + + while(1) + { + /* Loop for each device bus entry */ + input_field_index = 0; + for (j = 0, + num_lines = 0; + j < p_page_28_cur->page_hdr.num_dev_entries; + j++) + { + num_lines++; + input_field_index++; + if (p_page_28_chg->attr[j].qas_capability) + { + input_field_index++; + if ((num_lines >= pad_start_row) && + (num_lines < (pad_start_row + field_num_rows))) + { + field_opts_on(p_input_fields[input_field_index], + O_ACTIVE); + } + else + { + field_opts_off(p_input_fields[input_field_index], + O_ACTIVE); + } + if (p_page_28_cur->attr[j].qas_capability == + IBMSIS_MODEPAGE28_QAS_CAPABILITY_DISABLE_ALL) + { + if (page_28_sis.attr[j].qas_capability) + set_field_buffer(p_input_fields[input_field_index++], + 0, + "Disable"); + else + set_field_buffer(p_input_fields[input_field_index++], + 0, + "Disabled"); + + } + else + { + if (page_28_sis.attr[j].qas_capability) + set_field_buffer(p_input_fields[input_field_index++], + 0, + "Enable"); + else + set_field_buffer(p_input_fields[input_field_index++], + 0, + "Enabled"); + } + num_lines++; + } + if (p_page_28_chg->attr[j].scsi_id) + { + input_field_index++; + if ((num_lines >= pad_start_row) && + (num_lines < (pad_start_row + field_num_rows))) + { + field_opts_on(p_input_fields[input_field_index], + O_ACTIVE); + } + else + { + field_opts_off(p_input_fields[input_field_index], + O_ACTIVE); + } + sprintf(scsi_id_str[j],"%d",p_page_28_cur->attr[j].scsi_id); + set_field_buffer(p_input_fields[input_field_index++], + 0, + scsi_id_str[j]); + num_lines++; + } + if (p_page_28_chg->attr[j].bus_width) + { + input_field_index++; + if ((num_lines >= pad_start_row) && + (num_lines < (pad_start_row + field_num_rows))) + { + field_opts_on(p_input_fields[input_field_index], + O_ACTIVE); + } + else + { + field_opts_off(p_input_fields[input_field_index], + O_ACTIVE); + } + if (p_page_28_cur->attr[j].bus_width == 16) + { + set_field_buffer(p_input_fields[input_field_index++], + 0, + "Yes"); + } + else + { + set_field_buffer(p_input_fields[input_field_index++], + 0, + "No"); + } + num_lines++; + } + if (p_page_28_chg->attr[j].max_xfer_rate) + { + input_field_index++; + if ((num_lines >= pad_start_row) && + (num_lines < (pad_start_row + field_num_rows))) + { + field_opts_on(p_input_fields[input_field_index], + O_ACTIVE); + } + else + { + field_opts_off(p_input_fields[input_field_index], + O_ACTIVE); + } + sprintf(max_xfer_rate_str[j],"%d MB/s", + (sistoh32(p_page_28_cur->attr[j].max_xfer_rate) * + p_page_28_cur->attr[j].bus_width)/(10 * 8)); + set_field_buffer(p_input_fields[input_field_index++], + 0, + max_xfer_rate_str[j]); + num_lines++; + } + } + + if (form_adjust) + { + form_driver(p_fields_form, + REQ_NEXT_FIELD); + form_adjust = 0; + refresh(); + } + + prefresh(p_field_pad, + pad_start_row, 0, + field_start_row, 0, + field_end_row, + curses_info.max_x); + doupdate(); + ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (ch == 'c') + { + if (!confirm) + { + p_cur_field = current_field(p_fields_form); + cur_field_index = field_index(p_cur_field); + + rc = bus_attr_menu(p_cur_ioa, + p_page_28_cur, + p_page_28_chg, + p_page_28_dflt, + &page_28_sis, + cur_field_index, + pad_start_row); + + if (rc == RC_EXIT) + goto leave; + } + else + { + clear(); + set_field_buffer(p_title_fields[0], + 0, + "Processing Change SCSI Bus Configuration"); + mvaddstr(curses_info.max_y - 2, 1, "Please wait for next screen"); + doupdate(); + refresh(); + + /* issue mode select and reset if necessary */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + ioa_cmd.buffer = p_page_28_sense; + ioa_cmd.buffer_len = sizeof(struct ibmsis_page_28); + ioa_cmd.read_not_write = 0; + ioa_cmd.driver_cmd = 1; + + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + return RC_FAILED; + } + + rc = sis_ioctl(fd, IBMSIS_MODE_SELECT_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + close(fd); + syslog(LOG_ERR, "Mode Select to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return RC_FAILED; + } + + sis_save_page_28(p_cur_ioa, + p_page_28_cur, + p_page_28_chg, + &page_28_sis); + + if (is_reset_req) + { + rc = sis_ioctl(fd, IBMSIS_RESET_HOST_ADAPTER, &ioa_cmd); + } + + close(fd); + goto leave; + } + + } + else if (IS_ENTER_KEY(ch)) + { + if (!confirm) + { + confirm = 1; + clear(); + for (j = 0, + is_reset_req = 0; + j < p_page_28_cur->page_hdr.num_dev_entries; + j++) + { + if (page_28_sis.attr[j].scsi_id) + is_reset_req = 1; + } + + set_field_buffer(p_title_fields[0], + 0, + "Confirm Change SCSI Bus Configuration"); + mvaddstr(1, 1, "Confirming this action will result in the following configuration to"); + mvaddstr(2, 1, "become active."); + if (is_reset_req) + { + mvaddstr(3, 1, "ATTENTION: This action requires a reset of the Host Adapter. Confirming"); + mvaddstr(4, 1, "this action may affect system performance while processing changes."); + } + mvaddstr(6, 1, "Press c=Confirm Change SCSI Bus Configuration "); + if (field_num_rows < form_rows) + { + mvaddstr(field_end_row + 1, 43, "More..."); + mvaddstr(curses_info.max_y - 2, 25, "f=PageDn"); + } + mvaddstr(curses_info.max_y - 3, 1, "c=Confirm"); + mvaddstr(curses_info.max_y - 2, 1, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + memset(buffer, 0, 100); + sprintf(buffer,"%s", + p_cur_ioa->ioa.dev_name); + mvaddstr(8, 1, buffer); + + doupdate(); + pad_start_row = 0; + form_adjust = 1; + } + } + else if ((ch == 'f') || + (ch == 'F')) + { + if ((form_rows - field_num_rows) > pad_start_row) + { + pad_start_row += field_num_rows; + if ((form_rows - field_num_rows) < pad_start_row) + { + pad_start_row = form_rows - field_num_rows; + mvaddstr(field_end_row + 1, 43, " "); + mvaddstr(curses_info.max_y - 2, 25, " "); + } + mvaddstr(curses_info.max_y - 2, 36, "b=PageUp"); + form_adjust = 1; + } + } + else if ((ch == 'b') || + (ch == 'B')) + { + if (pad_start_row != 0) + { + if ((form_rows - field_num_rows) <= pad_start_row) + { + mvaddstr(field_end_row + 1, 43, "More..."); + } + pad_start_row -= field_num_rows; + if (pad_start_row < 0) + { + pad_start_row = 0; + mvaddstr(curses_info.max_y - 2, 36, " "); + } + form_adjust = 1; + mvaddstr(curses_info.max_y - 2, 25, "f=PageDn"); + } + } + else if (ch == '\t') + form_driver(p_fields_form, REQ_NEXT_FIELD); + else if (ch == KEY_UP) + form_driver(p_fields_form, REQ_PREV_FIELD); + else if (ch == KEY_DOWN) + form_driver(p_fields_form, REQ_NEXT_FIELD); + } + + leave: + + free_form(p_form); + free_screen(NULL, NULL, p_input_fields); + curses_info.p_form = p_old_form; + + flush_stdscr(); + return rc; +} + +int bus_attr_menu(struct sis_ioa *p_cur_ioa, + struct sis_page_28 *p_page_28_cur, + struct sis_page_28 *p_page_28_chg, + struct sis_page_28 *p_page_28_dflt, + struct sis_page_28 *p_page_28_sis, + int cur_field_index, + int offset) +{ + int input_field_index; + int start_row; + int i, j, scsi_id, found; + int num_menu_items; + int menu_index; + ITEM **menu_item = NULL; + struct ibmsis_resource_entry *p_resource_entry; + int *userptr; + int *retptr; + int rc = RC_SUCCESS; + + /* Loop for each device bus entry */ + input_field_index = 1; + start_row = DSP_FIELD_START_ROW - offset; + for (j = 0; + j < p_page_28_cur->page_hdr.num_dev_entries; + j++) + { + /* start_row represents the row in which the top most + menu item will be placed. Ideally this will be on the + same line as the field in which the menu is opened for*/ + start_row++; + input_field_index += 1; + if ((p_page_28_chg->attr[j].qas_capability) && + (input_field_index == cur_field_index)) + { + num_menu_items = 2; + menu_item = malloc(sizeof(ITEM **) * (num_menu_items + 1)); + userptr = malloc(sizeof(int) * num_menu_items); + + menu_item[0] = new_item("Enable",""); + userptr[0] = 2; + set_item_userptr(menu_item[0], + (char *)&userptr[0]); + + menu_item[1] = new_item("Disable",""); + userptr[1] = 1; + set_item_userptr(menu_item[1], + (char *)&userptr[1]); + + menu_item[2] = (ITEM *)NULL; + + rc = display_menu(menu_item, start_row, menu_index, &retptr); + if ((rc == RC_SUCCESS) && + (p_page_28_cur->attr[j].qas_capability != *retptr)) + { + p_page_28_cur->attr[j].qas_capability = *retptr; + p_page_28_sis->attr[j].qas_capability = + p_page_28_chg->attr[j].qas_capability; + } + i=0; + while (menu_item[i] != NULL) + free_item(menu_item[i++]); + free(menu_item); + free(userptr); + menu_item = NULL; + break; + } + else if (p_page_28_chg->attr[j].qas_capability) + { + input_field_index += 2; + start_row++; + } + + if ((p_page_28_chg->attr[j].scsi_id) && + (input_field_index == cur_field_index)) + { + num_menu_items = 16; + menu_item = malloc(sizeof(ITEM **) * (num_menu_items + 1)); + userptr = malloc(sizeof(int) * num_menu_items); + + menu_index = 0; + for (scsi_id = 0, + found = 0; + scsi_id < 16; + scsi_id++, found = 0) + { + for (i=0; + i < p_cur_ioa->p_resource_table->hdr.num_entries; + i++) + { + p_resource_entry = &p_cur_ioa->p_resource_table->dev[i]; + if ((scsi_id == p_resource_entry->resource_address.target) && + (p_page_28_cur->attr[j].res_addr.bus == + p_resource_entry->resource_address.bus)) + { + found = 1; + break; + } + } + + if (!found) + { + switch (scsi_id) + { + case 0: + menu_item[menu_index] = new_item("0",""); + userptr[menu_index] = 0; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + break; + case 1: + menu_item[menu_index] = new_item("1",""); + userptr[menu_index] = 1; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + break; + case 2: + menu_item[menu_index] = new_item("2",""); + userptr[menu_index] = 2; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + break; + case 3: + menu_item[menu_index] = new_item("3",""); + userptr[menu_index] = 3; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + break; + case 4: + menu_item[menu_index] = new_item("4",""); + userptr[menu_index] = 4; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + break; + case 5: + menu_item[menu_index] = new_item("5",""); + userptr[menu_index] = 5; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + break; + case 6: + menu_item[menu_index] = new_item("6",""); + userptr[menu_index] = 6; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + break; + case 7: + menu_item[menu_index] = new_item("7",""); + userptr[menu_index] = 7; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + break; + default: + break; + } + } + } + menu_item[menu_index] = (ITEM *)NULL; + rc = display_menu(menu_item, start_row, menu_index, &retptr); + if ((rc == RC_SUCCESS) && + (p_page_28_cur->attr[j].scsi_id != *retptr)) + { + p_page_28_cur->attr[j].scsi_id = *retptr; + p_page_28_sis->attr[j].scsi_id = + p_page_28_chg->attr[j].scsi_id; + } + i=0; + while (menu_item[i] != NULL) + free_item(menu_item[i++]); + free(menu_item); + free(userptr); + menu_item = NULL; + break; + } + else if (p_page_28_chg->attr[j].scsi_id) + { + input_field_index += 2; + start_row++; + } + + if ((p_page_28_chg->attr[j].bus_width) && + (input_field_index == cur_field_index)) + { + num_menu_items = 2; + menu_item = malloc(sizeof(ITEM **) * (num_menu_items + 1)); + userptr = malloc(sizeof(int) * num_menu_items); + + menu_index = 0; + menu_item[menu_index] = new_item("No",""); + userptr[menu_index] = 8; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + + menu_index++; + if (p_page_28_dflt->attr[j].bus_width == 16) + { + menu_item[menu_index] = new_item("Yes",""); + userptr[menu_index] = 16; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + } + menu_item[menu_index] = (ITEM *)NULL; + rc = display_menu(menu_item, start_row, menu_index, &retptr); + if ((rc == RC_SUCCESS) && + (p_page_28_cur->attr[j].bus_width != *retptr)) + { + p_page_28_cur->attr[j].bus_width = *retptr; + p_page_28_sis->attr[j].bus_width = + p_page_28_chg->attr[j].bus_width; + } + i=0; + while (menu_item[i] != NULL) + free_item(menu_item[i++]); + free(menu_item); + free(userptr); + menu_item = NULL; + break; + } + else if (p_page_28_chg->attr[j].bus_width) + { + input_field_index += 2; + start_row++; + } + + if ((p_page_28_chg->attr[j].max_xfer_rate) && + (input_field_index == cur_field_index)) + { + num_menu_items = 7; + menu_item = malloc(sizeof(ITEM **) * (num_menu_items + 1)); + userptr = malloc(sizeof(int) * num_menu_items); + + menu_index = 0; + switch (((sistoh32(p_page_28_dflt->attr[j].max_xfer_rate)) * + p_page_28_cur->attr[j].bus_width)/(10 * 8)) + { + case 320: + menu_item[menu_index] = new_item("320 MB/s",""); + userptr[menu_index] = 3200; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + case 160: + menu_item[menu_index] = new_item("160 MB/s",""); + userptr[menu_index] = 1600; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + case 80: + menu_item[menu_index] = new_item(" 80 MB/s",""); + userptr[menu_index] = 800; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + case 40: + menu_item[menu_index] = new_item(" 40 MB/s",""); + userptr[menu_index] = 400; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + case 20: + menu_item[menu_index] = new_item(" 20 MB/s",""); + userptr[menu_index] = 200; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + case 10: + menu_item[menu_index] = new_item(" 10 MB/s",""); + userptr[menu_index] = 100; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + case 5: + menu_item[menu_index] = new_item(" 5 MB/s",""); + userptr[menu_index] = 50; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + break; + default: + menu_item[menu_index] = new_item(" ",""); + userptr[menu_index] = 0; + set_item_userptr(menu_item[menu_index], + (char *)&userptr[menu_index]); + menu_index++; + break; + } + menu_item[menu_index] = (ITEM *)NULL; + rc = display_menu(menu_item, start_row, menu_index, &retptr); + if ((rc == RC_SUCCESS) && + (sistoh32(p_page_28_cur->attr[j].max_xfer_rate) != + ((*retptr) * 8)/p_page_28_cur->attr[j].bus_width)) + { + p_page_28_cur->attr[j].max_xfer_rate = + htosis32(((*retptr) * 8)/p_page_28_cur->attr[j].bus_width); + p_page_28_sis->attr[j].max_xfer_rate = + p_page_28_chg->attr[j].max_xfer_rate; + } + i=0; + while (menu_item[i] != NULL) + free_item(menu_item[i++]); + free(menu_item); + free(userptr); + menu_item = NULL; + break; + } + else if (p_page_28_chg->attr[j].max_xfer_rate) + { + input_field_index += 2; + start_row++; + } + } + return rc; +} + +int display_menu(ITEM **menu_item, + int menu_start_row, + int menu_index_max, + int **userptrptr) +{ + ITEM *p_cur_item; + MENU *p_menu; + WINDOW *p_box1_win, *p_box2_win, *p_field_win; + int menu_rows, menu_cols, menu_rows_disp; + int menu_index; + int use_box2 = 0; + int cur_item_index; + int ch, i; + int rc = RC_SUCCESS; + + p_menu = new_menu(menu_item); + scale_menu(p_menu, &menu_rows, &menu_cols); + menu_rows_disp = menu_rows; + + /* check if fits in current screen, + 1 is added for + bottom border, +1 is added for buffer */ + if ((menu_start_row + menu_rows + 1 + 1) > curses_info.max_y) + { + menu_start_row = curses_info.max_y - (menu_rows + 1 + 1); + if (menu_start_row < (8 + 1)) + { + /* size is adjusted by 2 to allow for top + and bottom border, add +1 for buffer */ + menu_rows_disp = curses_info.max_y - (8 + 2 + 1); + menu_start_row = (8 + 1); + } + } + + if (menu_rows > menu_rows_disp) + { + set_menu_format(p_menu, menu_rows_disp, 1); + use_box2 = 1; + } + + set_menu_mark(p_menu, "*"); + scale_menu(p_menu, &menu_rows, &menu_cols); + p_box1_win = newwin(menu_rows + 2, menu_cols + 2, menu_start_row - 1, 54); + p_field_win = newwin(menu_rows, menu_cols, menu_start_row, 55); + set_menu_win(p_menu, p_field_win); + post_menu(p_menu); + box(p_box1_win,ACS_VLINE,ACS_HLINE); + if (use_box2) + { + p_box2_win = newwin(menu_rows + 2, 3, menu_start_row - 1, 54 + menu_cols + 1); + box(p_box2_win,ACS_VLINE,ACS_HLINE); + + /* initialize scroll bar */ + for (i = 0; + i < menu_rows_disp/2; + i++) + { + mvwaddstr(p_box2_win, i + 1, 1, "#"); + } + + /* put down arrows in */ + for (i = menu_rows_disp; + i > (menu_rows_disp - menu_rows_disp/2); + i--) + { + mvwaddstr(p_box2_win, i, 1, "v"); + } + } + wnoutrefresh(p_box1_win); + + menu_index = 0; + while (1) + { + if (use_box2) + wnoutrefresh(p_box2_win); + wnoutrefresh(p_field_win); + doupdate(); + ch = getch(); + if (IS_ENTER_KEY(ch)) + { + p_cur_item = current_item(p_menu); + cur_item_index = item_index(p_cur_item); + *userptrptr = item_userptr(menu_item[cur_item_index]); + break; + } + else if ((ch == KEY_DOWN) || (ch == '\t')) + { + if (use_box2 && + (menu_index < (menu_index_max - 1))) + { + menu_index++; + if (menu_index == menu_rows_disp) + { + /* put up arrows in */ + for (i = 0; + i < menu_rows_disp/2; + i++) + { + mvwaddstr(p_box2_win, i + 1, 1, "^"); + } + } + if (menu_index == (menu_index_max - 1)) + { + /* remove down arrows */ + for (i = menu_rows_disp; + i > (menu_rows_disp - menu_rows_disp/2); + i--) + { + mvwaddstr(p_box2_win, i, 1, "#"); + } + } + } + + menu_driver(p_menu,REQ_DOWN_ITEM); + } + else if (ch == KEY_UP) + { + if (use_box2 && + (menu_index != 0)) + { + menu_index--; + if (menu_index == (menu_index_max - menu_rows_disp - 1)) + { + /* put down arrows in */ + for (i = menu_rows_disp; + i > (menu_rows_disp - menu_rows_disp/2); + i--) + { + mvwaddstr(p_box2_win, i, 1, "v"); + } + } + if (menu_index == 0) + { + /* remove up arrows */ + for (i = 0; + i < menu_rows_disp/2; + i++) + { + mvwaddstr(p_box2_win, i + 1, 1, "#"); + } + } + } + menu_driver(p_menu,REQ_UP_ITEM); + } + else if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + break; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + break; + } + } + + unpost_menu(p_menu); + free_menu(p_menu); + wclear(p_field_win); + wrefresh(p_field_win); + delwin(p_field_win); + wclear(p_box1_win); + wrefresh(p_box1_win); + delwin(p_box1_win); + if (use_box2) + { + wclear(p_box2_win); + wrefresh(p_box2_win); + delwin(p_box2_win); + } + + return rc; +} + +int driver_config() +{ + /* + Change Driver Configuration + + Current Driver configurations are shown. To change + setting hit "c" for options menu. Highlight desired + option then hit Enter + + c=Change Setting + + + Verbosity . . . . . . . . . . . . . : 1 + Trace Level . . . . . . . . . . . . : 1 + + Press Enter to Enable Changes + + e=Exit q=Cancel + */ +#define DEBUG_INDEX 2 +#define TRACE_INDEX 4 + int rc; + FORM *p_old_form; + FORM *p_fields_form; + FIELD *p_input_fields[6], *p_cur_field; + ITEM **menu_item; + int cur_field_index; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + int fd; + struct ibmsis_driver_cfg driver_cfg; + int ch; + int i; + int form_adjust = 0; + char debug_level_str[4]; + char trace_level_str[4]; + int *userptr; + int *retptr; + struct text_str + { + char line[4]; + } *menu_str; + + rc = RC_SUCCESS; + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &driver_cfg; + ioa_cmd.buffer_len = sizeof(struct ibmsis_driver_cfg); + ioa_cmd.driver_cmd = 1; + ioa_cmd.read_not_write = 1; + + fd = open(p_head_sis_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_head_sis_ioa->ioa.dev_name); + return RC_FAILED; + } + + rc = sis_ioctl(fd, IBMSIS_READ_DRIVER_CFG, &ioa_cmd); + close(fd); + + if (rc != 0) + { + syslog(LOG_ERR, "Read driver configuration failed. %m"IBMSIS_EOL); + return RC_FAILED; + } + + /* Title */ + p_input_fields[0] = + new_field(1, curses_info.max_x - curses_info.start_x, + 0, 0, 0, 0); + set_field_just(p_input_fields[0], JUSTIFY_CENTER); + set_field_buffer(p_input_fields[0], 0, + "Change Driver Configuration"); + field_opts_off(p_input_fields[0], O_ACTIVE); + + p_input_fields[1] = new_field(1, 38, DSP_FIELD_START_ROW, 4, + 0, 0); + field_opts_off(p_input_fields[1], O_ACTIVE | O_EDIT); + set_field_buffer(p_input_fields[1], 0, + "Verbosity . . . . . . . . . . . . . :"); + + p_input_fields[DEBUG_INDEX] = new_field(1, 3, DSP_FIELD_START_ROW, 44, + 0, 0); + field_opts_off(p_input_fields[DEBUG_INDEX], O_EDIT); + + p_input_fields[3] = new_field(1, 38, DSP_FIELD_START_ROW + 1, 4, + 0, 0); + field_opts_off(p_input_fields[3], O_ACTIVE | O_EDIT); + set_field_buffer(p_input_fields[3], 0, + "Trace Level . . . . . . . . . . . . :"); + + p_input_fields[TRACE_INDEX] = new_field(1, 3, DSP_FIELD_START_ROW + 1, 44, + 0, 0); + field_opts_off(p_input_fields[TRACE_INDEX], O_EDIT); + + p_input_fields[5] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_fields_form = new_form(p_input_fields); + + set_current_field(p_fields_form, p_input_fields[2]); + + form_opts_off(p_fields_form, O_BS_OVERLOAD); + + flush_stdscr(); + clear(); + post_form(p_fields_form); + + mvaddstr(2, 1, "Current Driver configurations are shown. To change"); + mvaddstr(3, 1, "setting hit \"c\" for options menu. Highlight desired"); + mvaddstr(4, 1, "option then hit Enter"); + mvaddstr(6, 1, "c=Change Setting"); + mvaddstr(curses_info.max_y - 3, 1, "Press Enter to Enable Changes"); + mvaddstr(curses_info.max_y - 1, 1, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + refresh(); + doupdate(); + + form_driver(p_fields_form, + REQ_FIRST_FIELD); + + while(1) + { + if (driver_cfg.debug_level) + sprintf(debug_level_str,"%d",driver_cfg.debug_level); + else + sprintf(debug_level_str,"OFF"); + + set_field_buffer(p_input_fields[DEBUG_INDEX], + 0, + debug_level_str); + + if (driver_cfg.trace_level) + sprintf(trace_level_str,"%d",driver_cfg.trace_level); + else + sprintf(trace_level_str,"OFF"); + + set_field_buffer(p_input_fields[TRACE_INDEX], + 0, + trace_level_str); + + if (form_adjust) + { + form_driver(p_fields_form, + REQ_NEXT_FIELD); + form_adjust = 0; + refresh(); + } + + doupdate(); + ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else if (ch == 'c') + { + p_cur_field = current_field(p_fields_form); + cur_field_index = field_index(p_cur_field); + if (cur_field_index == DEBUG_INDEX) + { + menu_item = malloc(sizeof(ITEM **) * + (driver_cfg.debug_level_max + 2)); + menu_str = malloc(sizeof(struct text_str) * + (driver_cfg.debug_level_max + 2)); + userptr = malloc(sizeof(int) * + (driver_cfg.debug_level_max + 1)); + + menu_item[0] = new_item("OFF",""); + userptr[0] = 0; + set_item_userptr(menu_item[0], + (char *)&userptr[0]); + + for (i = 1; i <= driver_cfg.debug_level_max; i++) + { + sprintf(menu_str[i].line,"%d",i); + menu_item[i] = new_item(menu_str[i].line,""); + userptr[i] = i; + set_item_userptr(menu_item[i], + (char *)&userptr[i]); + } + + menu_item[driver_cfg.debug_level_max + 1] = (ITEM *)NULL; + rc = display_menu(menu_item, DSP_FIELD_START_ROW, + driver_cfg.debug_level_max + 1, &retptr); + if (rc == RC_SUCCESS) + driver_cfg.debug_level = *retptr; + + i=0; + while (menu_item[i] != NULL) + free_item(menu_item[i++]); + free(menu_item); + free(menu_str); + free(userptr); + menu_item = NULL; + } + else if (cur_field_index == TRACE_INDEX) + { + menu_item = malloc(sizeof(ITEM **) * + (driver_cfg.trace_level_max + 2)); + menu_str = malloc(sizeof(struct text_str) * + (driver_cfg.trace_level_max + 2)); + userptr = malloc(sizeof(int) * + (driver_cfg.trace_level_max + 1)); + + menu_item[0] = new_item("OFF",""); + userptr[0] = 0; + set_item_userptr(menu_item[0], + (char *)&userptr[0]); + + for (i = 1; i <= driver_cfg.trace_level_max; i++) + { + sprintf(menu_str[i].line,"%d",i); + menu_item[i] = new_item(menu_str[i].line,""); + userptr[i] = i; + set_item_userptr(menu_item[i], + (char *)&userptr[i]); + } + + menu_item[driver_cfg.trace_level_max + 1] = (ITEM *)NULL; + rc = display_menu(menu_item, DSP_FIELD_START_ROW + 1, + driver_cfg.trace_level_max + 1, &retptr); + if (rc == RC_SUCCESS) + driver_cfg.trace_level = *retptr; + + i=0; + while (menu_item[i] != NULL) + free_item(menu_item[i++]); + free(menu_item); + free(menu_str); + free(userptr); + menu_item = NULL; + } + + if (rc == RC_EXIT) + goto leave; + } + else if (IS_ENTER_KEY(ch)) + { + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &driver_cfg; + ioa_cmd.buffer_len = sizeof(struct ibmsis_driver_cfg); + ioa_cmd.driver_cmd = 1; + + fd = open(p_head_sis_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_head_sis_ioa->ioa.dev_name); + return RC_FAILED; + } + + rc = sis_ioctl(fd, IBMSIS_WRITE_DRIVER_CFG, &ioa_cmd); + close(fd); + + if (rc != 0) + { + syslog(LOG_ERR, "Write driver configuration failed. %m"IBMSIS_EOL); + return RC_FAILED; + } + goto leave; + } + else if (ch == '\t') + form_driver(p_fields_form, REQ_NEXT_FIELD); + else if (ch == KEY_UP) + form_driver(p_fields_form, REQ_PREV_FIELD); + else if (ch == KEY_DOWN) + form_driver(p_fields_form, REQ_NEXT_FIELD); + } + + leave: + + free_form(p_fields_form); + free_screen(NULL, NULL, p_input_fields); + curses_info.p_form = p_old_form; + + flush_stdscr(); + return rc; +} + +char *strip_trailing_whitespace(char *p_str) +{ + int len; + char *p_tmp; + + len = strlen(p_str); + + if (len == 0) + return p_str; + + p_tmp = p_str + len - 1; + while(*p_tmp == ' ') + p_tmp--; + p_tmp++; + *p_tmp = '\0'; + return p_str; +} + +/* + Prints following to buffer: + + serial_num ccin model /dev/scsi/... + */ + +u16 print_dev(struct ibmsis_resource_entry *p_resource_entry, + char *p_buf, + char *dev_name) +{ + u16 len = 0; + u8 product_id[IBMSIS_PROD_ID_LEN+1]; + u8 vendor_id[IBMSIS_VENDOR_ID_LEN+1]; + + if (platform == SIS_ISERIES) + { + len += sprintf(p_buf, "%8s %X ", p_resource_entry->serial_num, p_resource_entry->type); + len += sprintf(p_buf + len, "%03d ", p_resource_entry->model); + len += sprintf(p_buf + len, "%-38s ", dev_name); + } + else + { + memcpy(vendor_id, p_resource_entry->std_inq_data.vpids.vendor_id, IBMSIS_VENDOR_ID_LEN); + vendor_id[IBMSIS_VENDOR_ID_LEN] = '\0'; + memcpy(product_id, p_resource_entry->std_inq_data.vpids.product_id, IBMSIS_PROD_ID_LEN); + product_id[IBMSIS_PROD_ID_LEN] = '\0'; + + len = sprintf(p_buf, "%8s %-8s %-18s %03d %-18s ", + p_resource_entry->serial_num, + vendor_id, product_id, + p_resource_entry->model, dev_name); + } + + return len; +} + +/* + Prints following to buffer: + serial_num ccin model /dev/scsi/... + */ +u16 print_dev2(struct ibmsis_resource_entry *p_resource_entry, + char *p_buf, + struct ibmsis_resource_flags *p_resource_flags, + char *dev_name) +{ + u16 len = 0; + + len += sprintf(p_buf, "%8s %X ", p_resource_entry->serial_num, p_resource_entry->type); + + len += sprintf(p_buf + len, "%03d ", get_model(p_resource_flags)); + + len += sprintf(p_buf + len, "%-38s", dev_name); + + return len; +} + +/* + Print device into buffer for a selection list + */ +u16 print_dev_sel(struct ibmsis_resource_entry *p_resource_entry, char *p_buf) +{ + u16 len = 0; + char buf[100]; + + if (platform == SIS_ISERIES) + { + len += sprintf(p_buf + len, "%X ", p_resource_entry->type); + } + else + { + memcpy(buf, p_resource_entry->std_inq_data.vpids.vendor_id, IBMSIS_VENDOR_ID_LEN); + buf[IBMSIS_VENDOR_ID_LEN] = '\0'; + + len += sprintf(p_buf + len, "%-8s ", buf); + + memcpy(buf, p_resource_entry->std_inq_data.vpids.product_id, IBMSIS_PROD_ID_LEN); + buf[IBMSIS_PROD_ID_LEN] = '\0'; + + len += sprintf(p_buf + len, "%-12s ", buf); + } + + len += sprintf(p_buf + len, "%8s ", p_resource_entry->serial_num); + + if (platform == SIS_ISERIES) + { + len += sprintf(p_buf + len, "%2s %3s ", + p_resource_entry->frame_id, + p_resource_entry->slot_label); + } + + len += sprintf(p_buf + len, "%02d %02d %2d %2d %2d", + p_resource_entry->pci_bus_number, + p_resource_entry->pci_slot, + p_resource_entry->resource_address.bus, + p_resource_entry->resource_address.target, + p_resource_entry->resource_address.lun); + + return len; +} + +/* + Print device into buffer for a selection list + */ +u16 print_dev_pty(struct ibmsis_resource_entry *p_resource_entry, char *p_buf, char *dev_name) +{ + u16 len = 0; + + len += sprintf(p_buf + len, "%8s ", p_resource_entry->serial_num); + + if (platform == SIS_ISERIES) + len += sprintf(p_buf + len, "%X ", p_resource_entry->type); + + len += sprintf(p_buf + len, "%03d ", p_resource_entry->model); + + if (platform == SIS_ISERIES) + { + len += sprintf(p_buf + len, "%-38s", dev_name); + } + else + { + len += sprintf(p_buf + len, "%-17s", dev_name); + len += sprintf(p_buf + len, "%02d %02d", + p_resource_entry->pci_bus_number, + p_resource_entry->pci_slot); + + if (p_resource_entry->is_af) + { + len += sprintf(p_buf + len, " %3d %2d %2d ", + p_resource_entry->resource_address.bus, + p_resource_entry->resource_address.target, + p_resource_entry->resource_address.lun); + } + else + { + len += sprintf(p_buf + len, " "); + } + } + + return len; +} + +/* + Print device into buffer for a selection list + */ +u16 print_dev_pty2(struct ibmsis_resource_entry *p_resource_entry, char *p_buf, char *dev_name) +{ + u16 len = 0; + + len += sprintf(p_buf + len, "%8s ", p_resource_entry->serial_num); + + if (platform == SIS_ISERIES) + len += sprintf(p_buf + len, "%X ", p_resource_entry->type); + + len += sprintf(p_buf + len, "%03d ", p_resource_entry->model); + + if (platform == SIS_ISERIES) + { + len += sprintf(p_buf + len, "%-38s", dev_name); + } + else + { + len += sprintf(p_buf + len, "%-16s", dev_name); + len += sprintf(p_buf + len, "%02d %02d", + p_resource_entry->pci_bus_number, + p_resource_entry->pci_slot); + + if (p_resource_entry->is_af) + { + len += sprintf(p_buf + len, " %3d %2d %2d ", + p_resource_entry->resource_address.bus, + p_resource_entry->resource_address.target, + p_resource_entry->resource_address.lun); + } + else + { + len += sprintf(p_buf + len, " "); + } + } + + return len; +} + +/* Can only be called for DASD devices */ +u16 get_model(struct ibmsis_resource_flags *p_resource_flags) +{ + u16 model; + + if (p_resource_flags->is_array_member) + model = 70; + else + model = 50; + + if (p_resource_flags->is_compressed) + model += 10; + + if (model > 60) + { + switch (IBMSIS_GET_CAP_REDUCTION(*p_resource_flags)) + { + case IBMSIS_HALF_REDUCTION: + model += 8; + break; + case IBMSIS_QUARTER_REDUCTION: + model += 4; + break; + case IBMSIS_EIGHTH_REDUCTION: + model += 2; + break; + case IBMSIS_SIXTEENTH_REDUCTION: + model += 1; + break; + case IBMSIS_UNKNOWN_REDUCTION: + model += 9; + break; + } + } + return model; +} + +int not_implemented() +{ + /* + Not Implemented + + + + + + + + + + + + This function is not yet implemented + + + + + + + + + + e=Exit q=Cancel + + */ + FIELD *p_fields[3]; + FORM *p_form; + FORM *p_old_form; + int rc = RC_SUCCESS; + int j; + + /* Title */ + p_fields[0] = new_field(1, curses_info.max_x - curses_info.start_x, /* new field size */ + 0, 0, /* upper left corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + /* User input field */ + p_fields[1] = new_field(1, 2, /* new field size */ + curses_info.max_y - 2, curses_info.max_x - 2, /* lower right corner */ + 0, /* number of offscreen rows */ + 0); /* number of working buffers */ + + p_fields[2] = NULL; + + p_old_form = curses_info.p_form; + curses_info.p_form = p_form = new_form(p_fields); + + set_field_just(p_fields[0], JUSTIFY_CENTER); + + field_opts_off(p_fields[0], /* field to alter */ + O_ACTIVE); /* attributes to turn off */ + + set_field_buffer(p_fields[0], /* field to alter */ + 0, /* number of buffer to alter */ + "Not Implemented"); /* string value to set */ + + while(1) + { + post_form(p_form); + + mvaddstr(curses_info.max_y/2, (curses_info.max_x - 36)/2 , "This function is not yet implemented"); + mvaddstr(curses_info.max_y - 2, 0, EXIT_KEY_LABEL"=Exit "CANCEL_KEY_LABEL"=Cancel"); + + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + + refresh(); + for (;;) + { + int ch = getch(); + + if (IS_EXIT_KEY(ch)) + { + rc = RC_EXIT; + goto leave; + } + else if (IS_CANCEL_KEY(ch) || IS_ENTER_KEY(ch)) + { + rc = RC_CANCEL; + goto leave; + } + else + { + form_driver(p_form, /* form to pass input to */ + REQ_LAST_FIELD ); /* form request code */ + refresh(); + } + } + } + leave: + + unpost_form(p_form); + free_form(p_form); + curses_info.p_form = p_old_form; + for (j=0; j < 2; j++) + free_field(p_fields[j]); + flush_stdscr(); + return rc; +} + +void handle_sig_int(int dummy) +{ + clear(); + refresh(); + endwin(); + printf(IBMSIS_EOL"Exit on signal...%d"IBMSIS_EOL, dummy); + exit(0); +} + +void handle_sig_term(int signal) +{ + clear(); + refresh(); + endwin(); + printf(IBMSIS_EOL"Exit on signal...%d"IBMSIS_EOL, signal); + exit(0); +} + +void handle_sig_winch(int dummy) +{ + /* xx Can I do a better job here? */ + signal(SIGWINCH, handle_sig_winch); + + endwin(); + refresh(); + + getmaxyx(curses_info.init_win, max_y, max_x); + getbegyx(curses_info.init_win, start_y, start_x); + curses_info.max_y = max_y; + curses_info.max_x = max_x; + curses_info.start_y = start_y; + curses_info.start_x = start_x; +} + +int open_dev(struct sis_ioa *p_ioa, struct sis_device *p_device) +{ + int fd; + + fd = open(p_device->dev_name, O_RDWR); + + if ((fd <= 1) && ((errno == ENOENT) || (errno == ENXIO))) + { + syslog(LOG_ERR, "Cannot open device %s. %m"IBMSIS_EOL, p_device->dev_name); + syslog(LOG_ERR, "Rescanning SCSI bus for device"IBMSIS_EOL); + scan_device(p_device->p_resource_entry->resource_address, p_ioa->host_num); + + fd = open(p_device->dev_name, O_RDWR); + } + + return fd; +} + +void free_screen(struct panel_l *p_panel, struct window_l *p_win, FIELD **p_fields) +{ + struct panel_l *p_cur_panel; + struct window_l *p_cur_win; + int i; + + p_cur_panel = p_panel; + while(p_cur_panel) + { + p_panel = p_panel->p_next; + del_panel(p_cur_panel->p_panel); + free(p_cur_panel); + p_cur_panel = p_panel; + } + p_cur_win = p_win; + while(p_cur_win) + { + p_win = p_win->p_next; + delwin(p_cur_win->p_win); + free(p_cur_win); + p_cur_win = p_win; + } + + if (p_fields) + { + for (i = 0; p_fields[i] != NULL; i++) + { + free_field(p_fields[i]); + } + } +} + +void revalidate_devs(struct sis_ioa *p_ioa) +{ + int rc, j; + struct sis_ioa *p_cur_ioa; + + rc = RC_SUCCESS; + + for (p_cur_ioa = p_head_sis_ioa; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next) + { + if (p_ioa && (p_ioa != p_cur_ioa)) + continue; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + /* If not a DASD, ignore entry */ + if (!IBMSIS_IS_DASD_DEVICE(p_cur_ioa->dev[j].p_resource_entry->std_inq_data)) + continue; + + revalidate_dev(&p_cur_ioa->dev[j], p_cur_ioa, + ((p_ioa != NULL) && p_cur_ioa->dev[j].p_resource_entry->is_af)); + } + } + + return; +} + +void evaluate_device(struct sis_device *p_sis_device, struct sis_ioa *p_ioa, int change_size) +{ + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_res_addr resource_address; + struct ibmsis_resource_table resource_table; + u32 resource_handle; + int j, rc, fd, device_converted; + int timeout = 60; + + /* send evaluate device down */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + p_resource_entry = p_sis_device->p_resource_entry; + + ioa_cmd.buffer = NULL; + ioa_cmd.buffer_len = 0; + resource_handle = sistoh32(p_resource_entry->resource_handle); + ioa_cmd.cdb[2] = (u8)(resource_handle >> 24); + ioa_cmd.cdb[3] = (u8)(resource_handle >> 16); + ioa_cmd.cdb[4] = (u8)(resource_handle >> 8); + ioa_cmd.cdb[5] = (u8)(resource_handle); + + fd = open(p_ioa->ioa.dev_name, O_RDWR); + if (fd < 0) + { + syslog(LOG_ERR, "Cannot open %s. %m\n", p_ioa->ioa.dev_name); + return; + } + + sis_ioctl(fd, IBMSIS_EVALUATE_DEVICE, &ioa_cmd); + + resource_address = p_resource_entry->resource_address; + device_converted = 0; + + while (!device_converted && timeout) + { + /* issue query ioa config here */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = &resource_table; + ioa_cmd.buffer_len = sizeof(struct ibmsis_resource_table); + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_QUERY_IOA_CONFIG, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Query IOA Config to %s failed. %m"IBMSIS_EOL, p_ioa->ioa.dev_name); + close(fd); + return; + } + + for (j = 0; j resource_address, + sizeof(resource_address)) == 0) && + (((p_resource_entry->is_hidden) && + (change_size == SIS_522_BLOCK)) || + ((!p_resource_entry->is_hidden) && + (change_size == SIS_512_BLOCK)))) + { + device_converted = 1; + break; + } + } + sleep(1); + timeout--; + } + close(fd); + + revalidate_dev(p_sis_device, p_ioa, 1); +} + +void revalidate_dev(struct sis_device *p_sis_device, struct sis_ioa *p_ioa, int force) +{ + char dev_name[50]; + int fd, rc; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_resource_entry *p_resource_entry; + + p_resource_entry = p_sis_device->p_resource_entry; + + if (!p_resource_entry->dev_changed && !force) + return; + + if (p_sis_device->opens != 0) + return; + + remove_device(p_resource_entry->resource_address, p_ioa); + + if (!p_resource_entry->is_hidden) + { + sleep(1); + scan_device(p_resource_entry->resource_address, p_ioa->host_num); + } + + /* Reset device changed bit */ + fd = open(p_ioa->ioa.dev_name, O_RDWR); + + if (fd < 0) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_ioa->ioa.dev_name); + return; + } + + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = NULL; + ioa_cmd.buffer_len = 0; + ioa_cmd.device_cmd = 1; + ioa_cmd.driver_cmd = 1; + ioa_cmd.resource_address = p_resource_entry->resource_address; + + rc = sis_ioctl(fd, IBMSIS_RESET_DEV_CHANGED, &ioa_cmd); + + if ((rc != 0) && !p_ioa) + syslog(LOG_ERR, "Reset dev changed bit to %s failed. %m"IBMSIS_EOL, dev_name); + close (fd); +} + +int is_array_in_use(struct sis_ioa *p_cur_ioa, + u8 array_id) +{ + int j, opens; + struct ibmsis_device_record *p_device_record; + struct ibmsis_array2_record *p_array2_record; + struct ibmsis_resource_entry *p_resource_entry; + + for (j = 0; j < p_cur_ioa->num_devices; j++) + { + p_device_record = (struct ibmsis_device_record *)p_cur_ioa->dev[j].p_qac_entry; + p_array2_record = (struct ibmsis_array2_record *)p_cur_ioa->dev[j].p_qac_entry; + + if (p_device_record == NULL) + continue; + + if (p_device_record->common.record_id == IBMSIS_RECORD_ID_DEVICE_RECORD) + { + if ((array_id == p_device_record->array_id) && + ((p_device_record->start_cand) || + (p_device_record->stop_cand))) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + opens = num_device_opens(p_cur_ioa->host_num, + p_resource_entry->resource_address.bus, + p_resource_entry->resource_address.target, + p_resource_entry->resource_address.lun); + + if (opens != 0) + return 1; + } + } + /* there is no need to check the devices for an array2 start candidate + as the devices are not accessible to linux. for stop candidate the + status of the volume set must be checked as this is the linux + accessible device which may be in use */ + else if (p_array2_record->common.record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD) + { + if (array_id == p_array2_record->array_id) + { + p_resource_entry = p_cur_ioa->dev[j].p_resource_entry; + opens = num_device_opens(p_cur_ioa->host_num, + p_resource_entry->resource_address.bus, + p_resource_entry->resource_address.target, + p_resource_entry->resource_address.lun); + + if (opens != 0) + return 1; + } + } + } + return 0; +} + diff --git a/iprdbg.c b/iprdbg.c new file mode 100644 index 0000000..81fca0a --- /dev/null +++ b/iprdbg.c @@ -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 +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/iprdump.8 b/iprdump.8 new file mode 100644 index 0000000..9df501b --- /dev/null +++ b/iprdump.8 @@ -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 +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/ diff --git a/iprdump.c b/iprdump.c new file mode 100644 index 0000000..d1fddf6 --- /dev/null +++ b/iprdump.c @@ -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 + +#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 "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; +} + + diff --git a/iprlib.c b/iprlib.c new file mode 100644 index 0000000..c1d9875 --- /dev/null +++ b/iprlib.c @@ -0,0 +1,2170 @@ +/******************************************************************/ +/* Linux IBM SIS utility library */ +/* Description: IBM Storage IOA Interface Specification (SIS) */ +/* Linux utility library */ +/* */ +/* (C) Copyright 2000, 2001 */ +/* International Business Machines Corporation and others. */ +/* All Rights Reserved. */ +/******************************************************************/ + +/* + * $Header: /cvsroot/iprdd/iprutils/iprlib.c,v 1.1 2003/10/22 22:21:02 manderso Exp $ + */ + +#ifndef iprlib_h +#include "iprlib.h" +#endif + +struct ibmsis_array_query_data *p_sis_array_query_data = NULL; +struct ibmsis_resource_table *p_res_table = NULL; +u32 num_ioas = 0; +struct sis_ioa *p_head_sis_ioa = NULL; +struct sis_ioa *p_last_sis_ioa = NULL; +int driver_major = 0; +int driver_minor = 0; +enum sis_platform platform = SIS_UNKNOWN_PLATFORM; + +/* This table includes both unsupported 522 disks and disks that support + being formatted to 522, but require a minimum microcode level. The disks + that require a minimum level of microcode will be marked by the + supported_with_min_ucode_level flag set to true. */ +struct unsupported_af_dasd unsupported_af[] = +{ + { + /* 00 Mako & Hammerhead */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"DRVS "}, + compare_product_id_byte: {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: false, + min_ucode_level: {" "}, + min_ucode_mask: {0, 0, 0, 0} + }, + { + /* 01 Swordfish */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"DRHS "}, + compare_product_id_byte: {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: false, + min_ucode_level: {" "}, + min_ucode_mask: {0, 0, 0, 0} + }, + { + /* 02 Neptune */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"DNES "}, + compare_product_id_byte: {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: false, + min_ucode_level: {" "}, + min_ucode_mask: {0, 0, 0, 0} + }, + { + /* 03 Thornback, Stingray, & Manta */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"DMVS "}, + compare_product_id_byte: {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: false, + min_ucode_level: {" "}, + min_ucode_mask: {0, 0, 0, 0} + }, + { + /* 04 Discovery I */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"DDYS "}, + compare_product_id_byte: {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: false, + min_ucode_level: {" "}, + min_ucode_mask: {0, 0, 0, 0} + }, + { + /* 05 US73 (Discovery II) - fixme - are we supporting this drive? */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"IC35L D2 "}, + compare_product_id_byte: {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: true, + min_ucode_level: {"S5DE"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 06 Apollo (Ext. Scallop 9GB) - LID: SC09 */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST318305L "}, + compare_product_id_byte: {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + lid: {"SC09"}, + lid_mask: {1, 1, 1, 1}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C749"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 07 Apollo (Ext. Scallop 18GB) - LID: SC18 */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST318305L "}, + compare_product_id_byte: {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + lid: {"SC18"}, + lid_mask: {1, 1, 1, 1}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C709"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 08 Apollo (Ext. Scallop 36GB) - LID: SC36 */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST336605L "}, + compare_product_id_byte: {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + lid: {"SC36"}, + lid_mask: {1, 1, 1, 1}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C709"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 09 Apollo (Ext. Scallop 73GB) - LID: SC73 */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST373405L "}, + compare_product_id_byte: {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + lid: {"SC73"}, + lid_mask: {1, 1, 1, 1}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C709"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 10 Apollo (non-external 9GB) - LID: AT1x */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST318305L "}, + compare_product_id_byte: {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + lid: {"AT1 "}, + lid_mask: {1, 1, 1, 0}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C54E"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 11 Apollo (non-external 18GB) - LID: AT0x */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST318305L "}, + compare_product_id_byte: {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + lid: {"AT0 "}, + lid_mask: {1, 1, 1, 0}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C50E"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 12 Apollo (non-external 36GB) - LID: AT0x */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST336605L "}, + compare_product_id_byte: {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + lid: {"AT0 "}, + lid_mask: {1, 1, 1, 0}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C50E"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 13 Apollo (non-external 73GB) - LID: AT0x */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST373405L "}, + compare_product_id_byte: {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + lid: {"AT0 "}, + lid_mask: {1, 1, 1, 0}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C50E"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 14 Odyssey (18, 36, 73GB) */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST3 53L "}, + compare_product_id_byte: {1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C51A"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 15 Odyssey (146+GB) - fixme - not in drive list; remove from table? */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST3 53L "}, + compare_product_id_byte: {1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C51A"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 16 Gemini (18, 36, 73GB) */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST3 07L "}, + compare_product_id_byte: {1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C50F"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 17 Gemini (146+GB) */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"ST3 07L "}, + compare_product_id_byte: {1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: true, + min_ucode_level: {"C50F"}, + min_ucode_mask: {1, 1, 1, 1} + }, + { + /* 18 Daytona */ + vendor_id: {"IBM "}, + compare_vendor_id_byte: {1, 1, 1, 1, 1, 1, 1, 1}, + product_id: {"IC35L DY "}, + compare_product_id_byte: {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + lid: {" "}, + lid_mask: {0, 0, 0, 0}, + supported_with_min_ucode_level: true, + min_ucode_level: {"S28C"}, + min_ucode_mask: {1, 1, 1, 1} + } +}; + +void tool_init(char *tool_name) +{ + DIR *proc_dir; + struct dirent *dir_entry; + char line[100], temp[100], proc_fname[100], *p_char, *p_temp, *p_temp2; + int ccin; + struct sis_ioa *p_sis_ioa; + int main_menu(); + int rc, minor_num, major_num; + dev_t major_minor; + struct stat file_stat; + char platform_str[100]; + + /* Find all the SIS IOAs attached and save away vital info about them */ + proc_dir = opendir("/proc/scsi/ipr"); + + if (proc_dir != NULL) + { + for (dir_entry = readdir(proc_dir); + dir_entry != NULL; + dir_entry = readdir(proc_dir)) + { + if (dir_entry->d_name[0] == '.') + continue; + + sprintf(proc_fname, "/proc/scsi/ipr/%s", dir_entry->d_name); + + /* Driver Version */ + if (get_proc_string(proc_fname, "Driver Version:", line) == 0) + { + exit_on_error("%s incompatible with current driver"IBMSIS_EOL,tool_name); + } + + p_sis_ioa = (struct sis_ioa*)malloc(sizeof(struct sis_ioa)); + memset(p_sis_ioa,0,sizeof(struct sis_ioa)); + + p_temp = &line[16]; + + p_temp2 = strchr(p_temp, '\n'); + if (p_temp2) + *p_temp2 = '\0'; + strcpy(p_sis_ioa->driver_version, p_temp); + + if ((driver_major = get_major_version(proc_fname)) == -1) + { + exit_on_error("%s incompatible with current driver"IBMSIS_EOL,tool_name); + } + + if ((driver_minor = get_minor_version(proc_fname)) == -1) + { + exit_on_error("%s incompatible with current driver"IBMSIS_EOL,tool_name); + } + + if (driver_major != IPR_MAJOR_RELEASE) + { + sprintf(temp,"%s incompatible with current driver"IBMSIS_EOL,tool_name); + exit_on_error("%sDriver Supported Version: %d, %s version: %d"IBMSIS_EOL, + temp, driver_major, tool_name, IPR_MAJOR_RELEASE); + } + + /* Get the CCIN */ + if (get_proc_string(proc_fname, "IBM", line) == 0) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + rc = sscanf(line, "IBM %x", &ccin); + + if (rc < 1) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + /* Firmware Version */ + if (get_proc_string(proc_fname, "Firmware Version:", line) == 0) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + p_temp = &line[18]; + + p_temp2 = strchr(p_temp, '\n'); + if (p_temp2) + *p_temp2 = '\0'; + strcpy(p_sis_ioa->firmware_version, p_temp); + + /* Get the resource name */ + if (get_proc_string(proc_fname, "Resource Name:", line) == 0) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + rc = sscanf(line, "Resource Name: %s", p_sis_ioa->ioa.dev_name); + + if (rc < 1) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + strcpy(p_sis_ioa->ioa.gen_name, p_sis_ioa->ioa.dev_name); + p_sis_ioa->ccin = ccin; + + p_sis_ioa->p_next = NULL; + p_sis_ioa->num_raid_cmds = 0; + + p_sis_ioa->host_num = strtoul(dir_entry->d_name, NULL, 10); + + /* get major number here */ + if (get_proc_string(proc_fname, "Major Number:", line) == 0) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + else + { + rc = sscanf(line, "Major Number: %d", &major_num); + + if (rc < 1) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + } + + /* if /dev file exists verify major number */ + rc = stat(p_sis_ioa->ioa.dev_name, &file_stat); + if (rc || (MAJOR(file_stat.st_rdev) != major_num)) + { + if (!rc) + { + /* remove all ibmsis* files with old major number */ + sprintf(temp,"rm %s",p_sis_ioa->ioa.dev_name); + p_char = strstr(temp, "ipr"); + p_char[6] = '*'; + p_char[7] = '\0'; + system(temp); + } + p_char = strstr(p_sis_ioa->ioa.dev_name, "ipr"); + p_char += 6; + minor_num = strtoul(p_char, NULL, 10); + major_minor = MKDEV( major_num, minor_num); + + mknod(p_sis_ioa->ioa.dev_name, S_IFCHR|S_IRUSR|S_IWUSR, major_minor); + } + + /* Host address */ + if (get_proc_string(proc_fname, "Host Address:", line) == 0) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + rc = sscanf(line, "Host Address: %X", &p_sis_ioa->host_addr); + + if (rc < 1) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + /* Get the serial number */ + if (get_proc_string(proc_fname, "Serial Number:", line) == 0) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + rc = sscanf(line, "Serial Number: %s", p_sis_ioa->serial_num); + + if (rc < 1) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + /* Part Number */ + if (get_proc_string(proc_fname, "Card Part Number:", line) == 0) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + rc = sscanf(line, "Card Part Number: %s", p_sis_ioa->part_num); + + if (rc < 1) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + /* Platform */ + if (get_proc_string(proc_fname, "Platform:", line) == 0) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + rc = sscanf(line, "Platform: %s", platform_str); + + if (rc < 1) + { + exit_on_error("%s: %s incompatible with driver %s"IBMSIS_EOL, + tool_name, IPR_VERSION_STR, p_sis_ioa->driver_version); + } + + if (strcmp(platform_str, "iSeries") == 0) + platform = SIS_ISERIES; + else if (strcmp(platform_str, "pSeries") == 0) + platform = SIS_PSERIES; + else + platform = SIS_GENERIC; + + if (p_last_sis_ioa) + { + p_last_sis_ioa->p_next = p_sis_ioa; + p_last_sis_ioa = p_sis_ioa; + } + else + { + p_last_sis_ioa = p_head_sis_ioa = p_sis_ioa; + } + num_ioas++; + } + } + + closedir(proc_dir); + + return; +} + +int get_proc_string(char *proc_file_name, char *label, char *buffer) +{ + FILE *proc_file; + char line[100]; + char old_line[100]; + int lines_different; + + memset(old_line, 0, 100); + memset(line, 0, 100); + proc_file = fopen(proc_file_name, "r"); + + if (proc_file == NULL) + { + exit_on_error("Fatal Error! /proc entry unreadable"IBMSIS_EOL); + } + + do + { + strcpy(old_line, line); + fgets(line, 100, proc_file); + lines_different = strcmp(line,old_line); + }while(strncmp(label, line, strlen(label)) && (line[0] != '\0') && lines_different); + + strncpy(buffer, line, strlen(line)); + fclose(proc_file); + + return ((line[0] != '\0') && lines_different); +} + +/* Try to dynamically add this device */ +int scan_device(struct ibmsis_res_addr resource_addr, u32 host_num) +{ + char cmd[200]; + + sprintf(cmd, "echo \"scsi add-single-device %d %d %d %d\" > /proc/scsi/scsi", + host_num, + resource_addr.bus, + resource_addr.target, + resource_addr.lun); + system(cmd); + return 0; +} + +/* Try to dynamically remove this device */ +int remove_device(struct ibmsis_res_addr resource_addr, struct sis_ioa *p_ioa) +{ + char cmd[200]; + + sprintf(cmd, "echo \"scsi remove-single-device %d %d %d %d\" > /proc/scsi/scsi", + p_ioa->host_num, + resource_addr.bus, + resource_addr.target, + resource_addr.lun); + system(cmd); + return 0; +} + +int sis_ioctl(int fd, u32 cmd, struct ibmsis_ioctl_cmd_internal *p_ioctl_cmd) +{ + struct ibmsis_ioctl_cmd_type2 *p_cmd; + int rc; + + p_cmd = malloc(sizeof(struct ibmsis_ioctl_cmd_type2) + p_ioctl_cmd->buffer_len); + memset(p_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_type2) + p_ioctl_cmd->buffer_len); + + if (!p_ioctl_cmd->read_not_write) + memcpy(p_cmd->buffer, p_ioctl_cmd->buffer, p_ioctl_cmd->buffer_len); + + p_cmd->driver_cmd = p_ioctl_cmd->driver_cmd; + p_cmd->device_cmd = p_ioctl_cmd->device_cmd; + p_cmd->resource_address = p_ioctl_cmd->resource_address; + p_cmd->buffer_len = p_ioctl_cmd->buffer_len; + p_cmd->read_not_write = p_ioctl_cmd->read_not_write; + + memcpy(p_cmd->cdb, p_ioctl_cmd->cdb, IBMSIS_CDB_LEN); + p_cmd->cdb[0] = cmd; + + p_cmd->type = IBMSIS_IOCTL_TYPE_2; + p_cmd->reserved = 0; + + rc = ioctl(fd, IBMSIS_IOCTL_SEND_COMMAND, p_cmd); + + if (p_ioctl_cmd->read_not_write) + memcpy(p_ioctl_cmd->buffer, p_cmd->buffer, p_ioctl_cmd->buffer_len); + + free(p_cmd); + + return rc; +}; + +#define SIS_MAX_XFER 0x8000 +int sg_ioctl(int fd, u8 cdb[IBMSIS_CCB_CDB_LEN], + void *p_data, u32 xfer_len, u32 data_direction, + struct sense_data_t *p_sense_data, + u32 timeout_in_sec) +{ + int rc; + sg_io_hdr_t io_hdr_t; + sg_iovec_t *p_iovec; + int iovec_count; + int i; + int buff_len, segment_size; + void *dxferp; + + /* check if scatter gather should be used */ + if (xfer_len > SIS_MAX_XFER) + { + iovec_count = xfer_len/SIS_MAX_XFER + 1; + p_iovec = malloc(iovec_count * sizeof(sg_iovec_t)); + + buff_len = xfer_len; + segment_size = SIS_MAX_XFER; + + for (i = 0; (i < iovec_count) && (buff_len != 0); i++) + { + + p_iovec[i].iov_base = malloc(SIS_MAX_XFER); + memcpy(p_iovec[i].iov_base, p_data + SIS_MAX_XFER * i, SIS_MAX_XFER); + p_iovec[i].iov_len = segment_size; + + buff_len -= segment_size; + if (buff_len < segment_size) + segment_size = buff_len; + } + iovec_count = i; + dxferp = (void *)p_iovec; + } + else + { + iovec_count = 0; + dxferp = p_data; + } + + for (i = 0; i < 2; i++) + { + memset(&io_hdr_t, 0, sizeof(io_hdr_t)); + memset(p_sense_data, 0, sizeof(struct sense_data_t)); + + io_hdr_t.interface_id = 'S'; + if (cdb[0] == WRITE_BUFFER) + io_hdr_t.cmd_len = 10; + else + io_hdr_t.cmd_len = 6; + io_hdr_t.iovec_count = iovec_count; + io_hdr_t.flags = 0; + io_hdr_t.pack_id = 0; + io_hdr_t.usr_ptr = 0; + io_hdr_t.sbp = (unsigned char *)p_sense_data; + io_hdr_t.mx_sb_len = sizeof(struct sense_data_t); + io_hdr_t.timeout = timeout_in_sec * 1000; + io_hdr_t.cmdp = cdb; + io_hdr_t.dxfer_direction = data_direction; + io_hdr_t.dxfer_len = xfer_len; + io_hdr_t.dxferp = dxferp; + + rc = ioctl(fd, SG_IO, &io_hdr_t); + + if ((rc == 0) && (io_hdr_t.masked_status == CHECK_CONDITION)) + rc = CHECK_CONDITION; + + if ((rc != CHECK_CONDITION) || (p_sense_data->sense_key != UNIT_ATTENTION)) + break; + } + + if (iovec_count) + { + for (i = 0; i < iovec_count; i++) + free(p_iovec[i].iov_base); + free(p_iovec); + } + + return rc; +}; + +/* Will return -1 on error */ +int get_major_version(char *proc_file_name) +{ + char line[100]; + char *p_temp, *p_temp2; + + if (get_proc_string(proc_file_name, "Driver Version:", line) == 0) + return -1; + + p_temp = &line[16]; + + p_temp2 = strchr(p_temp, '\n'); + if (p_temp2) + *p_temp2 = '\0'; + + /* Advance pointer to start of version number */ + p_temp += 5; + + p_temp2 = strchr(p_temp, ' '); + + *p_temp2 = '\0'; + + return strtoul(p_temp, NULL, 10); +} + +/* Will return -1 on error */ +int get_minor_version(char *proc_file_name) +{ + char line[100]; + char *p_temp, *p_temp2; + + if (get_proc_string(proc_file_name, "Driver Version:", line) == 0) + return -1; + + p_temp = &line[16]; + + p_temp2 = strchr(p_temp, '\n'); + if (p_temp2) + *p_temp2 = '\0'; + + p_temp2 = strstr(p_temp, "Rev."); + + /* Advance pointer to start of revision number */ + p_temp2 += 5; + + p_temp = p_temp2; + + p_temp2 = strchr(p_temp, '.'); + + *p_temp2 = '\0'; + + return strtoul(p_temp, NULL, 10); +} + +#define MAX_SG_DEVS 128 +#define MAX_SD_DEVS 128 + +static void make_dev_name(char * fname, const char * leadin, int k, + int do_numeric) +{ + char buff[64]; + int big,little; + + strcpy(fname, leadin ? leadin : "/dev/sg"); + if (do_numeric) { + sprintf(buff, "%d", k); + strcat(fname, buff); + } + else { + if (k < 26) { + buff[0] = 'a' + (char)k; + buff[1] = '\0'; + strcat(fname, buff); + } + else if (k <= 255) { /* assumes sequence goes x,y,z,aa,ab,ac etc */ + big = k/26; + little = k - (26 * big); + big = big - 1; + + buff[0] = 'a' + (char)big; + buff[1] = 'a' + (char)little; + buff[2] = '\0'; + strcat(fname, buff); + } + else + strcat(fname, "xxxx"); + } +} + +/* returns 0 on success, 1 on failure to find major and minor + number for the given device name */ +int get_sd_proc_data(char *sd_name, int *major_num, int *minor_num) +{ + FILE *proc_file; + char proc_file_name[] = "/proc/partitions"; + int rc; + int local_major_num, local_minor_num; + char line[100]; + char old_line[100]; + int lines_different; + + proc_file = fopen(proc_file_name, "r"); + + if (proc_file == NULL) + return 1; + do + { + strcpy(old_line,line); + fgets(line, 100, proc_file); + lines_different = strcmp(line,old_line); + if (strstr(line, sd_name)) + { + sscanf(line,"%d %d", + &local_major_num, + &local_minor_num); + *major_num = local_major_num; + *minor_num = local_minor_num; + fclose(proc_file); + return 0; + } + }while ((rc != EOF) && (lines_different)); + + fclose(proc_file); + return 1; +} + +void get_sg_ioctl_data(struct sg_map_info *p_sg_map_info, int num_devs) +{ + int sg_index, sd_index, fd, rc; + int num_sg_devices = 0; + struct sg_map_info *temp; + char tmp_dev_name[64]; + struct + { + u32 dev_id; + u32 unique_id; + } dev_idlun; + int sd_major, sd_minor; + char *sd_name; + struct stat sda_stat; + int max_sd_devs = MAX_SD_DEVS; + int temp_max_sd_devs; + int used_sd[MAX_SD_DEVS]; + + memset(used_sd, 0, sizeof(used_sd)); + + for (sg_index = 0; + (sg_index < MAX_SG_DEVS) && (num_sg_devices < num_devs); + sg_index++) + { + temp = &p_sg_map_info[num_sg_devices]; + + memset(p_sg_map_info[num_sg_devices].gen_name, 0, sizeof(p_sg_map_info[num_sg_devices].gen_name)); + make_dev_name(p_sg_map_info[num_sg_devices].gen_name, "/dev/sg", sg_index, 1); + fd = open(p_sg_map_info[num_sg_devices].gen_name, O_RDONLY | O_NONBLOCK); + + if (fd < 0) + { + if (errno == ENOENT) + { + mknod(p_sg_map_info[num_sg_devices].gen_name, + S_IFCHR|0660, + makedev(21,sg_index)); + + /* change permissions and owner to be identical to + /dev/sg0's */ + stat("/dev/sg0", &sda_stat); + chown(p_sg_map_info[num_sg_devices].gen_name, + sda_stat.st_uid, + sda_stat.st_gid); + chmod(p_sg_map_info[num_sg_devices].gen_name, + sda_stat.st_mode); + + fd = open(p_sg_map_info[num_sg_devices].gen_name, O_RDONLY | O_NONBLOCK); + if (fd < 0) + continue; + } + else + continue; + } + + rc = ioctl(fd, SG_GET_SCSI_ID, &p_sg_map_info[num_sg_devices].sg_dat); + + close(fd); + if ((rc >= 0) && + (p_sg_map_info[num_sg_devices].sg_dat.scsi_type == TYPE_DISK)) + { + temp_max_sd_devs = 0; + + memset(p_sg_map_info[num_sg_devices].dev_name, 0, sizeof(p_sg_map_info[num_sg_devices].dev_name)); + for (sd_index = 0; sd_index < max_sd_devs; sd_index++) + { + if (used_sd[sd_index]) + continue; + + memset(tmp_dev_name, 0, sizeof(tmp_dev_name)); + make_dev_name(tmp_dev_name, "/dev/sd", sd_index, 0); + + fd = open(tmp_dev_name, O_RDONLY | O_NONBLOCK); + if (fd < 0) + { + if (errno == ENOENT) + { + /* find major and minor number from /proc/partitions */ + sd_name = strstr(tmp_dev_name, "sd"); + rc = get_sd_proc_data(sd_name, &sd_major, &sd_minor); + + if (rc) + continue; + + mknod(tmp_dev_name, + S_IFBLK|0660, + makedev(sd_major,sd_minor)); + + /* change permissions and owner to be identical to + /dev/sda's */ + stat("/dev/sda", &sda_stat); + chown(tmp_dev_name, + sda_stat.st_uid, + sda_stat.st_gid); + chmod(tmp_dev_name, + sda_stat.st_mode); + + fd = open(tmp_dev_name, O_RDONLY | O_NONBLOCK); + if (fd < 0) + continue; + } + else + continue; + } + temp_max_sd_devs = sd_index + 1; + + rc = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &dev_idlun); + close(fd); + if (rc < 0) + { + continue; + } + + if ((p_sg_map_info[num_sg_devices].sg_dat.host_no == ((dev_idlun.dev_id >> 24) & 0xFF)) && + (p_sg_map_info[num_sg_devices].sg_dat.channel == ((dev_idlun.dev_id >> 16) & 0xFF)) && + (p_sg_map_info[num_sg_devices].sg_dat.scsi_id == (dev_idlun.dev_id & 0xFF)) && + (p_sg_map_info[num_sg_devices].sg_dat.lun == ((dev_idlun.dev_id >> 8) & 0xFF))) + { + strcpy(p_sg_map_info[num_sg_devices].dev_name, tmp_dev_name); + temp_max_sd_devs = max_sd_devs; + used_sd[sd_index] = 1; + break; + } + } + max_sd_devs = temp_max_sd_devs; + num_sg_devices++; + } + } + return; +} + +int get_sg_proc_data(struct sg_proc_info *p_sg_proc_info) +{ + FILE *proc_file; + char proc_file_name[] = "/proc/scsi/sg/devices"; + int rc; + int num_devs = 0; + + proc_file = fopen(proc_file_name, "r"); + + if (proc_file == NULL) + { + system("modprobe sg"); + proc_file = fopen(proc_file_name, "r"); + } + + if (proc_file == NULL) + return 0; + do + { + rc = fscanf(proc_file,"%d %d %d %d %d %d %d %d %d", + &p_sg_proc_info->host, &p_sg_proc_info->channel, + &p_sg_proc_info->id, &p_sg_proc_info->lun, + &p_sg_proc_info->type, &p_sg_proc_info->opens, + &p_sg_proc_info->qdepth,&p_sg_proc_info->busy, + &p_sg_proc_info->online); + if (rc > 0) + { + if (p_sg_proc_info->type == TYPE_DISK) + { + p_sg_proc_info++; + num_devs++; + } + } + } while(rc != EOF); + + fclose(proc_file); + return num_devs; +} + +void check_current_config(bool allow_rebuild_refresh) +{ + struct sg_map_info *p_sg_map_info; + struct sg_proc_info *p_sg_proc_info; + int num_sg_devices, fd, rc, device_count, j, k; + struct sis_ioa *p_cur_ioa; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + struct ibmsis_array_query_data *p_cur_array_query_data; + struct ibmsis_resource_table *p_cur_res_table; + struct ibmsis_resource_entry res_entry; + struct ibmsis_record_common *p_common_record; + struct ibmsis_device_record *p_device_record; + struct ibmsis_array_record *p_array_record; + int found, tried_scsi_add, tried_everything; + + /* Allocate memory on init */ + if (p_res_table == NULL) + { + p_res_table = + (struct ibmsis_resource_table *) + malloc((sizeof(struct ibmsis_resource_table) + + sizeof(struct ibmsis_resource_entry) * + IBMSIS_MAX_PHYSICAL_DEVS) * num_ioas); + } + + if (p_sis_array_query_data == NULL) + { + p_sis_array_query_data = + (struct ibmsis_array_query_data *) + malloc(sizeof(struct ibmsis_array_query_data) * num_ioas); + } + + p_sg_map_info = (struct sg_map_info *)malloc(sizeof(struct sg_map_info) * MAX_SG_DEVS); + p_sg_proc_info = (struct sg_proc_info *)malloc(sizeof(struct sg_proc_info) * MAX_SG_DEVS); + + /* Get sg data via sg proc file system */ + num_sg_devices = get_sg_proc_data(p_sg_proc_info); + get_sg_ioctl_data(p_sg_map_info, num_sg_devices); + + for(p_cur_ioa = p_head_sis_ioa, + p_cur_res_table = p_res_table, + p_cur_array_query_data = p_sis_array_query_data; + p_cur_ioa != NULL; + p_cur_ioa = p_cur_ioa->p_next, + p_cur_res_table++, + p_cur_array_query_data++) + { + p_cur_ioa->num_devices = 0; + + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + p_cur_ioa->num_devices = 0; + continue; + } + + /* Get Query Array Config Data */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_array_query_data; + ioa_cmd.buffer_len = sizeof(struct ibmsis_array_query_data); + if (allow_rebuild_refresh) + ioa_cmd.cdb[1] = 0; + else + ioa_cmd.cdb[1] = 0x80; /* Prohibit Rebuild Candidate Refresh */ + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_QUERY_ARRAY_CONFIG, &ioa_cmd); + + if (rc != 0) + { + if (errno != EINVAL) + syslog(LOG_ERR,"Query Array Config to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + + p_cur_array_query_data->num_records = 0; + } + + p_cur_ioa->p_qac_data = p_cur_array_query_data; + + /* Get Query IOA Config Data */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + + ioa_cmd.buffer = p_cur_res_table; + ioa_cmd.buffer_len = sizeof(struct ibmsis_resource_table); + ioa_cmd.read_not_write = 1; + + rc = sis_ioctl(fd, IBMSIS_QUERY_IOA_CONFIG, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Query IOA Config to %s failed. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + close(fd); + continue; + } + p_cur_ioa->p_resource_table = p_cur_res_table; + close(fd); + + device_count = 0; + p_cur_ioa->dev = (struct sis_device *) + realloc(p_cur_ioa->dev, + p_cur_res_table->hdr.num_entries * sizeof(struct sis_device)); + memset(p_cur_ioa->dev, 0, p_cur_res_table->hdr.num_entries * sizeof(struct sis_device)); + + /* now assemble data pertaining to each individual device */ + for (j = 0; j < p_cur_res_table->hdr.num_entries; j++) + { + if ((IBMSIS_IS_DASD_DEVICE(p_cur_res_table->dev[j].std_inq_data)) + && !p_cur_res_table->dev[j].is_ioa_resource) + { + p_cur_ioa->dev[device_count].p_resource_entry = &p_cur_res_table->dev[j]; + p_cur_ioa->dev[device_count].p_qac_entry = NULL; + strcpy(p_cur_ioa->dev[device_count].dev_name, ""); + strcpy(p_cur_ioa->dev[device_count].gen_name, ""); + p_cur_ioa->dev[device_count].opens = 0; + + res_entry = p_cur_res_table->dev[j]; + + /* find array config data matching resource entry */ + p_common_record = (struct ibmsis_record_common *)p_cur_array_query_data->data; + for (k = 0; k < p_cur_array_query_data->num_records; k++) + { + p_device_record = (struct ibmsis_device_record *)p_common_record; + if (p_device_record->resource_handle == res_entry.resource_handle) + { + p_cur_ioa->dev[device_count].p_qac_entry = p_common_record; + break; + } + + p_common_record = (struct ibmsis_record_common *) + ((unsigned long)p_common_record + sistoh16(p_common_record->record_len)); + } + + /* find sg_map_info matching resource entry */ + found = 0; + tried_scsi_add = 0; + tried_everything = 0; + while (!found && !tried_everything && !res_entry.is_hidden) + { + for (k = 0; k < num_sg_devices; k++) + { + if ((p_cur_ioa->host_num == p_sg_map_info[k].sg_dat.host_no) && + (res_entry.resource_address.bus == p_sg_map_info[k].sg_dat.channel) && + (res_entry.resource_address.target == p_sg_map_info[k].sg_dat.scsi_id) && + (res_entry.resource_address.lun == p_sg_map_info[k].sg_dat.lun)) + { + /* copy device name to main structure */ + strcpy(p_cur_ioa->dev[device_count].dev_name, p_sg_map_info[k].dev_name); + strcpy(p_cur_ioa->dev[device_count].gen_name, p_sg_map_info[k].gen_name); + + found = 1; + break; + } + } + + if (!found) + { + if (!tried_scsi_add) + { + /* try adding scsi device then rechecking */ + remove_device(res_entry.resource_address, p_cur_ioa); + scan_device(res_entry.resource_address, + p_cur_ioa->host_num); + /* sleep(1); give mid-layer a moment to process */ + + /* Re-Get sg data via SG_GET_SCSI_ID ioctl + get_sg_ioctl_data(p_sg_map_info, num_sg_devices); */ + + tried_scsi_add = 1; + } + else + { + tried_everything = 1; + + /* log error + syslog(LOG_ERR,"Device not found host %d, bus %d, target %d, lun %d", + p_cur_ioa->host_num, + res_entry.resource_address.bus, + res_entry.resource_address.target, + res_entry.resource_address.lun); */ + } + } + } + + /* find usage counts in sg_proc_info */ + found = 0; + for (k=0; k < num_sg_devices; k++) + { + if ((p_cur_ioa->host_num == p_sg_proc_info[k].host) && + (res_entry.resource_address.bus == p_sg_proc_info[k].channel) && + (res_entry.resource_address.target == p_sg_proc_info[k].id) && + (res_entry.resource_address.lun == p_sg_proc_info[k].lun)) + { + p_cur_ioa->dev[device_count].opens = p_sg_proc_info[k].opens; + found = 1; + break; + } + } + device_count++; + } + else if (p_cur_res_table->dev[j].is_ioa_resource) + { + p_cur_ioa->ioa.p_resource_entry = &p_cur_res_table->dev[j]; + } + } + + /* now go through query array data inserting Array Record Type 1 and 2 + data putting the IOA as the resource owner */ + p_array_record = (struct ibmsis_array_record *)p_cur_array_query_data->data; + for (k = 0; k < p_cur_array_query_data->num_records; k++) + { + if ((p_array_record->common.record_id == IBMSIS_RECORD_ID_ARRAY_RECORD) || + ((p_array_record->common.record_id == IBMSIS_RECORD_ID_ARRAY2_RECORD) && + (p_array_record->start_cand))) + { + strcpy(p_cur_ioa->dev[device_count].dev_name, p_cur_ioa->ioa.dev_name); + strcpy(p_cur_ioa->dev[device_count].gen_name, p_cur_ioa->ioa.gen_name); + p_cur_ioa->dev[device_count].p_resource_entry = p_cur_ioa->ioa.p_resource_entry; + p_cur_ioa->dev[device_count].p_qac_entry = (struct ibmsis_record_common *)p_array_record; + p_cur_ioa->dev[device_count].opens = 0; + device_count++; + } + else if (p_array_record->common.record_id == IBMSIS_RECORD_ID_SUPPORTED_ARRAYS) + { + p_cur_ioa->p_supported_arrays = (struct ibmsis_supported_arrays *)p_array_record; + } + + p_array_record = (struct ibmsis_array_record *) + ((unsigned long)p_array_record + sistoh16(p_array_record->common.record_len)); + } + + p_cur_ioa->num_devices = device_count; + } + free(p_sg_map_info); + free(p_sg_proc_info); +} + +int num_device_opens(int host_num, int channel, int id, int lun) +{ + struct sg_proc_info *p_sg_proc_info; + int opens = 0; + int k, num_sg_devices; + + p_sg_proc_info = (struct sg_proc_info *)malloc(sizeof(struct sg_proc_info) * MAX_SG_DEVS); + + /* Get sg data via sg proc file system */ + num_sg_devices = get_sg_proc_data(p_sg_proc_info); + + /* find usage counts in sg_proc_info */ + for (k=0; k < num_sg_devices; k++) + { + if ((host_num == p_sg_proc_info[k].host) && + (channel == p_sg_proc_info[k].channel) && + (id == p_sg_proc_info[k].id) && + (lun == p_sg_proc_info[k].lun)) + { + opens = p_sg_proc_info[k].opens; + break; + } + } + + free(p_sg_proc_info); + return opens; +} + +void exit_on_error(char *s, ...) +{ + va_list args; + char usr_str[256]; + + va_start(args, s); + vsprintf(usr_str, s, args); + va_end(args); + + closelog(); + openlog("sisconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + syslog(LOG_ERR,"%s",usr_str); + closelog(); + openlog("sisconfig", LOG_PID | LOG_CONS, LOG_USER); + + exit(1); +} + +void sis_config_file_hdr(char *file_name) +{ + FILE *fd; + char cmd_str[64]; + + /* check if file currently exists */ + fd = fopen(file_name, "r"); + if (fd) + { + fclose(fd); + return; + } + + /* be sure directory is present */ + sprintf(cmd_str,"install -d %s",SIS_CONFIG_DIR); + system(cmd_str); + + /* otherwise, create new file */ + fd = fopen(file_name, "w"); + if (fd == NULL) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, file_name); + return; + } + + fprintf(fd,"# DO NOT EDIT! Software generated configuration file for"IBMSIS_EOL"# ipr SCSI device subsystem"IBMSIS_EOL); + fprintf(fd, IBMSIS_EOL); + fprintf(fd,"# Use sisconfig to configure"IBMSIS_EOL); + fprintf(fd,"# See \"man sisconfig\" for more information"IBMSIS_EOL); + fprintf(fd, IBMSIS_EOL); + fclose(fd); +} + +void sis_config_file_entry(char *usr_file_name, + char *category, + char *field, + char *value, + int update) +{ + FILE *fd, *temp_fd; + char file_name[64]; + char temp_file_name[64]; + char line[64]; + int category_found = 0; + int field_found = 0; + + sprintf(file_name,"%s%s",SIS_CONFIG_DIR, usr_file_name); + + /* verify common header comments */ + sis_config_file_hdr(file_name); + + fd = fopen(file_name, "r"); + + if (fd == NULL) + return; + + sprintf(temp_file_name,"%s.1",file_name); + temp_fd = fopen(temp_file_name, "w"); + if (temp_fd == NULL) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, temp_file_name); + return; + } + + while (NULL != fgets(line,64,fd)) + { + if ((strstr(line, category)) && + (line[0] != '#')) + { + category_found = 1; + } + else + { + if (category_found) + { + if (line[0] == '[') + { + category_found = 0; + if (!field_found) + { + if (!update) + fprintf(temp_fd, "# "); + + fprintf(temp_fd,"%s %s"IBMSIS_EOL,field,value); + } + } + + if (strstr(line, field)) + { + if (update) + sprintf(line,"%s %s"IBMSIS_EOL,field,value); + + field_found = 1; + } + } + } + + fputs(line, temp_fd); + } + + if (!field_found) + { + if (!category_found) + { + fprintf(temp_fd,IBMSIS_EOL"%s"IBMSIS_EOL, category); + } + + if (!update) + fprintf(temp_fd, "# "); + + fprintf(temp_fd,"%s %s"IBMSIS_EOL, field, value); + } + + sprintf(line,"mv %s %s", temp_file_name, file_name); + system(line); + + fclose(fd); + fclose(temp_fd); +} + +int sis_config_file_read(char *usr_file_name, + char *category, + char *field, + char *value) +{ + FILE *fd; + char file_name[64]; + char line[64]; + char *str_ptr; + int category_found; + int rc = RC_FAILED; + + sprintf(file_name,"%s%s",SIS_CONFIG_DIR, usr_file_name); + + fd = fopen(file_name, "r"); + if (fd == NULL) + { + return RC_FAILED; + } + + while (NULL != fgets(line,64,fd)) + { + if (line[0] != '#') + { + if (strstr(line, category)) + { + category_found = 1; + } + else + { + if (category_found) + { + if (line[0] == '[') + { + category_found = 0; + } + + if ((str_ptr = strstr(line, field))) + { + str_ptr += strlen(field); + while (str_ptr[0] == ' ') + str_ptr++; + sprintf(value,"%s"IBMSIS_EOL,str_ptr); + rc = RC_SUCCESS; + break; + } + } + } + } + } + + fclose(fd); + return rc; +} + +int sis_config_file_valid(char *usr_file_name) +{ + FILE *fd; + char file_name[64]; + + sprintf(file_name,"%s%s",SIS_CONFIG_DIR, usr_file_name); + + fd = fopen(file_name, "r"); + if (fd == NULL) + { + return RC_FAILED; + } + + fclose(fd); + return RC_SUCCESS; +} + +void sis_save_page_28(struct sis_ioa *p_ioa, + struct sis_page_28 *p_page_28_cur, + struct sis_page_28 *p_page_28_chg, + struct sis_page_28 *p_page_28_sis) +{ + char file_name[64]; + char category[16]; + char value_str[16]; + void sis_config_file_hdr(char *file_name); + int i; + int update_entry; + + /* gets Host Address to create file_name */ + sprintf(file_name,"%x_%x", + p_ioa->ccin, p_ioa->host_addr); + + for (i = 0; + i < p_page_28_cur->page_hdr.num_dev_entries; + i++) + { + if (p_page_28_chg->attr[i].qas_capability) + { + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + sprintf(value_str,"%d", + p_page_28_cur->attr[i].qas_capability); + + if (p_page_28_sis->attr[i].qas_capability) + update_entry = 1; + else + update_entry = 0; + + sis_config_file_entry(file_name, + category, + SIS_QAS_CAPABILITY, + value_str, + update_entry); + } + + if (p_page_28_chg->attr[i].scsi_id) + { + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + sprintf(value_str,"%d", + p_page_28_cur->attr[i].scsi_id); + + if (p_page_28_sis->attr[i].scsi_id) + update_entry = 1; + else + update_entry = 0; + + sis_config_file_entry(file_name, + category, + SIS_HOST_SCSI_ID, + value_str, + update_entry); + } + + if (p_page_28_chg->attr[i].bus_width) + { + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + sprintf(value_str,"%d", + p_page_28_cur->attr[i].bus_width); + + if (p_page_28_sis->attr[i].bus_width) + update_entry = 1; + else + update_entry = 0; + + sis_config_file_entry(file_name, + category, + SIS_BUS_WIDTH, + value_str, + update_entry); + } + + if (p_page_28_chg->attr[i].max_xfer_rate) + { + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + sprintf(value_str,"%d", + (sistoh32(p_page_28_cur->attr[i].max_xfer_rate) * + (p_page_28_cur->attr[i].bus_width / 8))/10); + + if (p_page_28_sis->attr[i].max_xfer_rate) + update_entry = 1; + else + update_entry = 0; + + sis_config_file_entry(file_name, + category, + SIS_MAX_XFER_RATE, + value_str, + update_entry); + } + + if (p_page_28_chg->attr[i].min_time_delay) + { + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + sprintf(value_str,"%d", + p_page_28_cur->attr[i].min_time_delay); + + sis_config_file_entry(file_name, + category, + SIS_MIN_TIME_DELAY, + value_str, + 0); + } + } +} + +void sis_set_page_28(struct sis_ioa *p_cur_ioa, + int limited_config, + int reset_scheduled) +{ + int rc, i; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + char current_mode_settings[255]; + char changeable_mode_settings[255]; + char default_mode_settings[255]; + struct ibmsis_mode_parm_hdr *p_mode_parm_hdr; + int fd; + struct ibmsis_page_28 *p_page_28_sense; + struct sis_page_28 *p_page_28_cur, *p_page_28_chg, *p_page_28_dflt; + int is_reset_req = 0; + char value_str[64]; + char file_name[64]; + char category[16]; + int new_value; + u32 max_xfer_rate; + + /* mode sense page28 to get current parms */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)current_mode_settings; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0x28; + ioa_cmd.read_not_write = 1; + ioa_cmd.driver_cmd = 1; + + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + return; + } + + rc = sis_ioctl(fd, IBMSIS_MODE_SENSE_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + close(fd); + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return; + } + + p_page_28_sense = (struct ibmsis_page_28 *)p_mode_parm_hdr; + p_page_28_cur = (struct sis_page_28 *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + /* now issue mode sense to get changeable parms */ + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)changeable_mode_settings; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0x68; + + rc = sis_ioctl(fd, IBMSIS_MODE_SENSE_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + close(fd); + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return; + } + + p_page_28_chg = (struct sis_page_28 *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + /* Now issue mode sense to get default parms */ + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)default_mode_settings; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0xA8; + + rc = sis_ioctl(fd, IBMSIS_MODE_SENSE_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + close(fd); + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return; + } + + p_page_28_dflt = (struct sis_page_28 *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + /* extract data from saved file to send in mode select */ + sprintf(file_name,"%x_%x", + p_cur_ioa->ccin, p_cur_ioa->host_addr); + + for (i = 0; + i < p_page_28_cur->page_hdr.num_dev_entries; + i++) + { + if (p_page_28_chg->attr[i].qas_capability) + { + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + + rc = sis_config_file_read(file_name, + category, + SIS_QAS_CAPABILITY, + value_str); + if (rc == RC_SUCCESS) + { + sscanf(value_str,"%d", &new_value); + p_page_28_cur->attr[i].qas_capability = new_value; + } + } + + if (p_page_28_chg->attr[i].scsi_id) + { + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + + rc = sis_config_file_read(file_name, + category, + SIS_HOST_SCSI_ID, + value_str); + if (rc == RC_SUCCESS) + { + sscanf(value_str,"%d", &new_value); + if (p_page_28_cur->attr[i].scsi_id != new_value) + { + is_reset_req = 1; + p_page_28_cur->attr[i].scsi_id = new_value; + } + } + } + + if (p_page_28_chg->attr[i].bus_width) + { + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + + rc = sis_config_file_read(file_name, + category, + SIS_BUS_WIDTH, + value_str); + if (rc == RC_SUCCESS) + { + sscanf(value_str,"%d", &new_value); + p_page_28_cur->attr[i].bus_width = new_value; + } + } + + if (p_page_28_chg->attr[i].max_xfer_rate) + { + if (limited_config & (1 << p_page_28_cur->attr[i].res_addr.bus)) + { + max_xfer_rate = ((sistoh32(p_page_28_cur->attr[i].max_xfer_rate)) * + p_page_28_cur->attr[i].bus_width)/(10 * 8); + + if (SIS_LIMITED_MAX_XFER_RATE < max_xfer_rate) + { + p_page_28_cur->attr[i].max_xfer_rate = + htosis32(SIS_LIMITED_MAX_XFER_RATE * 10 / + (p_page_28_cur->attr[i].bus_width / 8)); + } + + if (limited_config & SIS_SAVE_LIMITED_CONFIG) + { + /* update config file to indicate present restriction */ + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + sprintf(value_str,"%d", + (sistoh32(p_page_28_cur->attr[i].max_xfer_rate) * + (p_page_28_cur->attr[i].bus_width / 8))/10); + + sis_config_file_entry(file_name, + category, + SIS_MAX_XFER_RATE, + value_str, + 1); + } + } + else + { + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + + rc = sis_config_file_read(file_name, + category, + SIS_MAX_XFER_RATE, + value_str); + + if (rc == RC_SUCCESS) + { + sscanf(value_str,"%d", &new_value); + + max_xfer_rate = ((sistoh32(p_page_28_dflt->attr[i].max_xfer_rate)) * + p_page_28_cur->attr[i].bus_width)/(10 * 8); + + if (new_value <= max_xfer_rate) + { + p_page_28_cur->attr[i].max_xfer_rate = + htosis32(new_value * 10 / + (p_page_28_cur->attr[i].bus_width / 8)); + } + else + { + p_page_28_cur->attr[i].max_xfer_rate = + p_page_28_dflt->attr[i].max_xfer_rate; + + /* update config file to indicate present restriction */ + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + sprintf(value_str,"%d", + (sistoh32(p_page_28_cur->attr[i].max_xfer_rate) * + (p_page_28_cur->attr[i].bus_width / 8))/10); + + sis_config_file_entry(file_name, + category, + SIS_MAX_XFER_RATE, + value_str, + 1); + } + } + else + { + p_page_28_cur->attr[i].max_xfer_rate = + p_page_28_dflt->attr[i].max_xfer_rate; + } + } + } + + if (p_page_28_chg->attr[i].min_time_delay) + { + sprintf(category,"[%s%d]", + SIS_CATEGORY_BUS, + p_page_28_cur->attr[i].res_addr.bus); + + rc = sis_config_file_read(file_name, + category, + SIS_MIN_TIME_DELAY, + value_str); + if (rc == RC_SUCCESS) + { + sscanf(value_str,"%d", &new_value); + p_page_28_cur->attr[i].min_time_delay = new_value; + } + else + { + p_page_28_cur->attr[i].min_time_delay = IBMSIS_INIT_SPINUP_DELAY; + } + } + } + + /* issue mode sense and reset if necessary */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + ioa_cmd.buffer = p_page_28_sense; + ioa_cmd.buffer_len = sizeof(struct ibmsis_page_28); + ioa_cmd.read_not_write = 0; + ioa_cmd.driver_cmd = 1; + + rc = sis_ioctl(fd, IBMSIS_MODE_SELECT_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + close(fd); + syslog(LOG_ERR, "Mode Select to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return; + } + + if ((is_reset_req) && + (!reset_scheduled)) + { + rc = sis_ioctl(fd, IBMSIS_RESET_HOST_ADAPTER, &ioa_cmd); + } + + close(fd); +} + +void sis_set_page_28_init(struct sis_ioa *p_cur_ioa, + int limited_config) +{ + int rc, i; + struct ibmsis_ioctl_cmd_internal ioa_cmd; + char current_mode_settings[255]; + char changeable_mode_settings[255]; + char default_mode_settings[255]; + struct ibmsis_mode_parm_hdr *p_mode_parm_hdr; + int fd; + int issue_mode_select = 0; + struct ibmsis_page_28 *p_page_28_sense; + struct sis_page_28 *p_page_28_cur, *p_page_28_chg, *p_page_28_dflt; + struct sis_page_28 page_28_sis; + u32 max_xfer_rate; + + /* Mode sense page28 to get current parms */ + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)current_mode_settings; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0x28; + ioa_cmd.read_not_write = 1; + ioa_cmd.driver_cmd = 1; + + fd = open(p_cur_ioa->ioa.dev_name, O_RDWR); + if (fd <= 1) + { + syslog(LOG_ERR, "Could not open %s. %m"IBMSIS_EOL, p_cur_ioa->ioa.dev_name); + return; + } + + rc = sis_ioctl(fd, IBMSIS_MODE_SENSE_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + close(fd); + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return; + } + + p_page_28_sense = (struct ibmsis_page_28 *)p_mode_parm_hdr; + p_page_28_cur = (struct sis_page_28 *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + /* Now issue mode sense to get changeable parms */ + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)changeable_mode_settings; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0x68; + + rc = sis_ioctl(fd, IBMSIS_MODE_SENSE_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + close(fd); + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return; + } + + p_page_28_chg = (struct sis_page_28 *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + /* Now issue mode sense to get default parms */ + p_mode_parm_hdr = (struct ibmsis_mode_parm_hdr *)default_mode_settings; + + ioa_cmd.buffer = p_mode_parm_hdr; + ioa_cmd.buffer_len = 255; + ioa_cmd.cdb[2] = 0xA8; + + rc = sis_ioctl(fd, IBMSIS_MODE_SENSE_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + close(fd); + syslog(LOG_ERR, "Mode Sense to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + return; + } + + p_page_28_dflt = (struct sis_page_28 *) + (((u8 *)(p_mode_parm_hdr+1)) + p_mode_parm_hdr->block_desc_len); + + for (i = 0; + i < p_page_28_cur->page_hdr.num_dev_entries; + i++) + { + if (p_page_28_chg->attr[i].min_time_delay) + p_page_28_cur->attr[i].min_time_delay = IBMSIS_INIT_SPINUP_DELAY; + + if ((limited_config & (1 << p_page_28_cur->attr[i].res_addr.bus))) + { + max_xfer_rate = ((sistoh32(p_page_28_cur->attr[i].max_xfer_rate)) * + p_page_28_cur->attr[i].bus_width)/(10 * 8); + + if (SIS_LIMITED_MAX_XFER_RATE < max_xfer_rate) + { + p_page_28_cur->attr[i].max_xfer_rate = + htosis32(SIS_LIMITED_MAX_XFER_RATE * 10 / + (p_page_28_cur->attr[i].bus_width / 8)); + } + } + else + { + p_page_28_cur->attr[i].max_xfer_rate = + p_page_28_dflt->attr[i].max_xfer_rate; + } + + issue_mode_select++; + } + + /* Issue mode select */ + if (issue_mode_select) + { + memset(&ioa_cmd, 0, sizeof(struct ibmsis_ioctl_cmd_internal)); + ioa_cmd.buffer = p_page_28_sense; + ioa_cmd.buffer_len = sizeof(struct ibmsis_page_28); + ioa_cmd.read_not_write = 0; + ioa_cmd.driver_cmd = 1; + + rc = sis_ioctl(fd, IBMSIS_MODE_SELECT_PAGE_28, &ioa_cmd); + + if (rc != 0) + { + syslog(LOG_ERR, "Mode Select to %s failed. %m"IBMSIS_EOL, + p_cur_ioa->ioa.dev_name); + } + + /* Zero out user page 28 page, this data is used to indicate + that no values are being changed, this routine is called + to create and initialize the file if it does not already + exist */ + memset(&page_28_sis, 0, sizeof(struct ibmsis_page_28)); + + sis_save_page_28(p_cur_ioa, p_page_28_cur, p_page_28_chg, + &page_28_sis); + } + + close(fd); +} + +void sislog_location(struct ibmsis_resource_entry *p_resource) +{ + if (platform == SIS_ISERIES) + { + syslog(LOG_ERR," Frame ID: %s, Card position: %s", + p_resource->frame_id, p_resource->slot_label); + } + else + { + if (platform == SIS_PSERIES) + syslog(LOG_ERR, + " Location: %s, Bus: %d, Device: %d, Host num: %d", + p_resource->pseries_location, p_resource->pci_bus_number, + p_resource->pci_slot, p_resource->host_no); + else + syslog(LOG_ERR, + " Bus: %d, Device: %d, Host num: %d", + p_resource->pci_bus_number, + p_resource->pci_slot, p_resource->host_no); + } +} + +bool is_af_blocked(struct sis_device *p_sis_device, int silent) +{ + int i, j, rc, fd; + u8 cdb[IBMSIS_CCB_CDB_LEN]; + struct sense_data_t sense_data; + struct ibmsis_std_inq_data std_inq_data; + struct ibmsis_dasd_inquiry_page3 dasd_page3_inq; + u32 ros_rcv_ram_rsvd, min_ucode_level; + + fd = open(p_sis_device->gen_name, O_RDWR); + + if (fd != -1) + { + /* Zero out inquiry data */ + memset(&std_inq_data, 0, sizeof(std_inq_data)); + memset(cdb, 0, IBMSIS_CCB_CDB_LEN); + + cdb[0] = INQUIRY; + cdb[4] = sizeof(std_inq_data); + + rc = sg_ioctl(fd, cdb, + &std_inq_data, sizeof(std_inq_data), + SG_DXFER_FROM_DEV, + &sense_data, 30); + + if (rc != 0) + { + syslog(LOG_ERR,"standard inquiry failed to %s.", + p_sis_device->gen_name); + close(fd); + return false; + } + + 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(fd, cdb, &dasd_page3_inq, + sizeof(dasd_page3_inq), + SG_DXFER_FROM_DEV, &sense_data, 30); + + close(fd); + if (rc != 0) + { + syslog(LOG_ERR,"Page 3 inquiry failed to %s.", p_sis_device->dev_name); + return false; + } + + /* Is this device in the table? */ + for (i=0; + i < sizeof(unsupported_af)/ + sizeof(struct unsupported_af_dasd); + i++) + { + /* check vendor id */ + for (j = 0; j < IBMSIS_VENDOR_ID_LEN; j++) + { + if (unsupported_af[i].compare_vendor_id_byte[j]) + { + if (unsupported_af[i].vendor_id[j] != + std_inq_data.vpids.vendor_id[j]) + { + /* not a match */ + break; + } + } + } + + if (j != IBMSIS_VENDOR_ID_LEN) + continue; + + /* check product ID */ + for (j = 0; j < IBMSIS_PROD_ID_LEN; j++) + { + if (unsupported_af[i].compare_product_id_byte[j]) + { + if (unsupported_af[i].product_id[j] != + std_inq_data.vpids.product_id[j]) + { + /* not a match */ + break; + } + } + } + + if (j != IBMSIS_PROD_ID_LEN) + continue; + + /* Compare LID Level */ + for (j = 0; j < 4; j++) + { + if (unsupported_af[i].lid_mask[j]) + { + if (unsupported_af[i].lid[j] != + dasd_page3_inq.load_id[j]) + { + /* not a match */ + break; + } + } + } + + if (j != 4) + continue; + + /* If we make it this far, we have a match into the table. Now, + determine if we need a certain level of microcode or if this + disk is not supported all together. */ + if (unsupported_af[i].supported_with_min_ucode_level) + { + /* Check microcode level in std inquiry data */ + /* If it's less than the minimum required level, we will + tell the user to upgrade microcode. */ + min_ucode_level = 0; + ros_rcv_ram_rsvd = 0; + + for (j = 0; j < 4; j++) + { + if (unsupported_af[i].min_ucode_mask[j]) + { + min_ucode_level = (min_ucode_level << 8) | + unsupported_af[i].min_ucode_level[j]; + ros_rcv_ram_rsvd = (ros_rcv_ram_rsvd << 8) | + std_inq_data.ros_rsvd_ram_rsvd[j]; + } + } + + if (min_ucode_level > ros_rcv_ram_rsvd) + { + if (!silent) + syslog(LOG_ERR,"Disk %s needs updated microcode " + "before transitioning to 522 bytes/sector " + "format.", p_sis_device->dev_name); + return true; + } + else + { + return false; + } + } + else /* disk is not supported at all */ + { + if (!silent) + syslog(LOG_ERR,"Disk %s not supported for transition " + "to 522 bytes/sector format.", p_sis_device->dev_name); + return true; + } + } + } + return false; +} diff --git a/iprlib.h b/iprlib.h new file mode 100644 index 0000000..fd49d7f --- /dev/null +++ b/iprlib.h @@ -0,0 +1,1456 @@ +#ifndef iprlib_h +#define iprlib_h +/******************************************************************/ +/* Linux IBM SIS utility library */ +/* Description: IBM Storage IOA Interface Specification (SIS) */ +/* Linux utility library */ +/* */ +/* (C) Copyright 2000, 2001 */ +/* International Business Machines Corporation and others. */ +/* All Rights Reserved. */ +/******************************************************************/ + +/* + * $Header: /cvsroot/iprdd/iprutils/iprlib.h,v 1.1 2003/10/22 22:21:02 manderso Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IOCTL_BUFFER_SIZE 512 +#define IBMSIS_MAX_NUM_BUSES 4 +#define IBMSIS_VENDOR_ID_LEN 8 +#define IBMSIS_PROD_ID_LEN 16 +#define IBMSIS_SERIAL_NUM_LEN 8 +#define IBMSIS_CCB_CDB_LEN 16 +#define IBMSIS_EOL "\n" +#define IBMSIS_IOCTL_SEND_COMMAND 0xf1f1 +#define IBMSIS_MAX_PSERIES_LOCATION_LEN 24 +#define IBMSIS_MAX_PHYSICAL_DEVS 192 +#define IBMSIS_QAC_BUFFER_SIZE 16000 +#define IBMSIS_VSET_MODEL_NUMBER 200 +#define IBMSIS_INVALID_ARRAY_ID 0xFFu +#define IBMSIS_RECLAIM_NUM_BLOCKS_MULTIPLIER 256 +#define IBMSIS_SDB_CHECK_AND_QUIESCE 0x00u +#define IBMSIS_SDB_CHECK_ONLY 0x40u +#define IBMSIS_MAX_NUM_SUPP_INQ_PAGES 8 +#define IBMSIS_DUMP_TRACE_ENTRY_SIZE 8192 + +#define IBMSIS_IOA_DEBUG 0xDDu +#define IBMSIS_IOA_DEBUG_READ_IOA_MEM 0x00u +#define IBMSIS_IOA_DEBUG_WRITE_IOA_MEM 0x01u +#define IBMSIS_IOA_DEBUG_READ_FLIT 0x03u + +#define IBMSIS_STD_INQ_Z0_TERM_LEN 8 +#define IBMSIS_STD_INQ_Z1_TERM_LEN 12 +#define IBMSIS_STD_INQ_Z2_TERM_LEN 4 +#define IBMSIS_STD_INQ_Z3_TERM_LEN 5 +#define IBMSIS_STD_INQ_Z4_TERM_LEN 4 +#define IBMSIS_STD_INQ_Z5_TERM_LEN 2 +#define IBMSIS_STD_INQ_Z6_TERM_LEN 10 +#define IBMSIS_STD_INQ_PART_NUM_LEN 12 +#define IBMSIS_STD_INQ_EC_LEVEL_LEN 10 +#define IBMSIS_STD_INQ_FRU_NUM_LEN 12 + +#define IBMSIS_START_STOP_STOP 0x00u +#define IBMSIS_START_STOP_START 0x01u +#define IBMSIS_READ_CAPACITY_16 0x10u +#define IBMSIS_SERVICE_ACTION_IN 0x9Eu +#define IBMSIS_QUERY_RESOURCE_STATE 0xC2u +#define IBMSIS_QUERY_IOA_CONFIG 0xC5u +#define IBMSIS_QUERY_COMMAND_STATUS 0xCBu +#define IBMSIS_EVALUATE_DEVICE 0xE4u +#define IBMSIS_QUERY_ARRAY_CONFIG 0xF0u +#define IBMSIS_START_ARRAY_PROTECTION 0xF1u +#define IBMSIS_STOP_ARRAY_PROTECTION 0xF2u +#define IBMSIS_RESYNC_ARRAY_PROTECTION 0xF3u +#define IBMSIS_ADD_ARRAY_DEVICE 0xF4u +#define IBMSIS_REMOVE_ARRAY_DEVICE 0xF5u +#define IBMSIS_REBUILD_DEVICE_DATA 0xF6u +#define IBMSIS_RECLAIM_CACHE_STORE 0xF8u +#define IBMSIS_RECLAIM_ACTION 0x60u +#define IBMSIS_RECLAIM_PERFORM 0x00u +#define IBMSIS_RECLAIM_EXTENDED_INFO 0x10u +#define IBMSIS_RECLAIM_QUERY 0x20u +#define IBMSIS_RECLAIM_RESET 0x40u +#define IBMSIS_RECLAIM_FORCE_BATTERY_ERROR 0x60u +#define IBMSIS_RECLAIM_UNKNOWN_PERM 0x80u +#define IBMSIS_DISCARD_CACHE_DATA 0xF9u +#define IBMSIS_PROHIBIT_CORR_INFO_UPDATE 0x80u + +#define IBMSIS_NO_REDUCTION 0 +#define IBMSIS_HALF_REDUCTION 1 +#define IBMSIS_QUARTER_REDUCTION 2 +#define IBMSIS_EIGHTH_REDUCTION 4 +#define IBMSIS_SIXTEENTH_REDUCTION 6 +#define IBMSIS_UNKNOWN_REDUCTION 7 + +#define IBMSIS_SUBTYPE_AF_DASD 0x0 +#define IBMSIS_SUBTYPE_GENERIC_SCSI 0x1 +#define IBMSIS_SUBTYPE_VOLUME_SET 0x2 + +#define IBMSIS_IS_DASD_DEVICE(std_inq_data) \ + ((((std_inq_data).peri_dev_type) == IBMSIS_PERI_TYPE_DISK) && !((std_inq_data).removeable_medium)) + +#define IBMSIS_GET_CAP_REDUCTION(res_flags) \ +(((res_flags).capacity_reduction_hi << 1) | (res_flags).capacity_reduction_lo) + +#define ibmsis_memory_copy memcpy +#define ibmsis_memory_set memset + +#define IBMSIS_SET_MODE(change_mask, cur_val, new_val) \ +{ \ +int mod_bits = (cur_val ^ new_val); \ +if ((change_mask & mod_bits) == mod_bits) \ +{ \ +cur_val = new_val; \ +} \ +} + +#define IBMSIS_CONC_MAINT 0xC8u +#define IBMSIS_CONC_MAINT_CHECK_AND_QUIESCE IBMSIS_SDB_CHECK_AND_QUIESCE +#define IBMSIS_CONC_MAINT_CHECK_ONLY IBMSIS_SDB_CHECK_ONLY +#define IBMSIS_CONC_MAINT_QUIESE_ONLY IBMSIS_SDB_QUIESE_ONLY + +#define IBMSIS_CONC_MAINT_FMT_MASK 0x0Fu +#define IBMSIS_CONC_MAINT_FMT_SHIFT 0 +#define IBMSIS_CONC_MAINT_GET_FMT(fmt) \ +((fmt & IBMSIS_CONC_MAINT_FMT_MASK) >> IBMSIS_CONC_MAINT_FMT_SHIFT) +#define IBMSIS_CONC_MAINT_DSA_FMT 0x00u +#define IBMSIS_CONC_MAINT_FRAME_ID_FMT 0x01u +#define IBMSIS_CONC_MAINT_PSERIES_FMT 0x02u +#define IBMSIS_CONC_MAINT_XSERIES_FMT 0x03u + +#define IBMSIS_CONC_MAINT_TYPE_MASK 0x30u +#define IBMSIS_CONC_MAINT_TYPE_SHIFT 4 +#define IBMSIS_CONC_MAINT_GET_TYPE(type) \ +((type & IBMSIS_CONC_MAINT_TYPE_MASK) >> IBMSIS_CONC_MAINT_TYPE_SHIFT) +#define IBMSIS_CONC_MAINT_INSERT 0x0u +#define IBMSIS_CONC_MAINT_REMOVE 0x1u + +#define IBMSIS_RECORD_ID_SUPPORTED_ARRAYS _i16((u16)0) +#define IBMSIS_RECORD_ID_ARRAY_RECORD _i16((u16)1) +#define IBMSIS_RECORD_ID_DEVICE_RECORD _i16((u16)2) +#define IBMSIS_RECORD_ID_COMP_RECORD _i16((u16)3) +#define IBMSIS_RECORD_ID_ARRAY2_RECORD _i16((u16)4) +#define IBMSIS_RECORD_ID_DEVICE2_RECORD _i16((u16)5) + +/******************************************************************/ +/* Driver Commands */ +/******************************************************************/ +#define IBMSIS_GET_TRACE 0xE1u +#define IBMSIS_RESET_DEV_CHANGED 0xE8u +#define IBMSIS_DUMP_IOA 0xD7u +#define IBMSIS_MODE_SENSE_PAGE_28 0xD8u +#define IBMSIS_MODE_SELECT_PAGE_28 0xD9u +#define IBMSIS_RESET_HOST_ADAPTER 0xDAu +#define IBMSIS_READ_DRIVER_CFG 0xDBu +#define IBMSIS_WRITE_DRIVER_CFG 0xDCu + + +#define IBMSIS_PERI_TYPE_DISK 0x00u + +enum sis_platform +{ + SIS_ISERIES, + SIS_PSERIES, + SIS_GENERIC, + SIS_UNKNOWN_PLATFORM +}; + +extern struct ibmsis_array_query_data *p_sis_array_query_data; +extern struct ibmsis_resource_table *p_res_table; +extern u32 num_ioas; +extern struct sis_ioa *p_head_sis_ioa; +extern struct sis_ioa *p_last_sis_ioa; +extern int driver_major; +extern int driver_minor; +extern enum sis_platform platform; + +struct ibmsis_res_addr +{ + u8 reserved; + u8 bus; + u8 target; + u8 lun; +#define IBMSIS_GET_PHYSICAL_LOCATOR(res_addr) \ +(((res_addr).bus << 16) | ((res_addr).target << 8) | (res_addr).lun) +}; + +struct ibmsis_std_inq_vpids +{ + u8 vendor_id[IBMSIS_VENDOR_ID_LEN]; /* Vendor ID */ + u8 product_id[IBMSIS_PROD_ID_LEN]; /* Product ID */ +}; + +struct ibmsis_record_common +{ + u16 record_id; + u16 record_len; +}; + +#if (defined(__KERNEL__) && defined(__LITTLE_ENDIAN)) || \ +(!defined(__KERNEL__) && (__BYTE_ORDER == __LITTLE_ENDIAN)) +#ifdef IBMSIS_IBMSISDD +#define htosis16(x) swab16(x) +#define htosis32(x) swab32(x) +#define sistoh16(x) swab16(x) +#define sistoh32(x) swab32(x) +#else +#define htosis16(x) bswap16(x) +#define htosis32(x) bswap32(x) +#define sistoh16(x) bswap16(x) +#define sistoh32(x) bswap32(x) +#endif + +#define _i16(x) _sw16(x) +#define _i32(x) _sw32(x) + +#define IBMSIS_BIG_ENDIAN 0 +#define IBMSIS_LITTLE_ENDIAN 1 + +struct ibmsis_mode_page_hdr +{ + u8 parms_saveable:1; + u8 reserved1:1; + u8 page_code:6; + u8 page_length; +}; + +struct ibmsis_control_mode_page +{ + /* Mode page 0x0A */ + struct ibmsis_mode_page_hdr header; + u8 rlec:1; + u8 gltsd:1; + u8 reserved1:3; + u8 tst:3; + u8 dque:1; + u8 qerr:2; + u8 reserved2:1; + u8 queue_algorithm_modifier:4; + u8 eaerp:1; + u8 uaaerp:1; + u8 raerp:1; + u8 swp:1; + u8 reserved4:2; + u8 rac:1; + u8 reserved3:1; + + u8 reserved5; + u16 ready_aen_holdoff_period; + u16 busy_timeout_period; + u16 reserved6; +}; + +struct ibmsis_reclaim_query_data +{ + u8 action_status; +#define IBMSIS_ACTION_SUCCESSFUL 0 +#define IBMSIS_ACTION_NOT_REQUIRED 1 +#define IBMSIS_ACTION_NOT_PERFORMED 2 + u8 num_blocks_needs_multiplier:1; + u8 reserved3:1; + u8 reclaim_unknown_performed:1; + u8 reclaim_known_performed:1; + u8 reserved2:2; + u8 reclaim_unknown_needed:1; + u8 reclaim_known_needed:1; + + u16 num_blocks; + + u8 rechargeable_battery_type; +#define IBMSIS_BATTERY_TYPE_NO_BATTERY 0 +#define IBMSIS_BATTERY_TYPE_NICD 1 +#define IBMSIS_BATTERY_TYPE_NIMH 2 +#define IBMSIS_BATTERY_TYPE_LIION 3 + + u8 rechargeable_battery_error_state; +#define IBMSIS_BATTERY_NO_ERROR_STATE 0 +#define IBMSIS_BATTERY_WARNING_STATE 1 +#define IBMSIS_BATTERY_ERROR_STATE 2 + + u8 reserved4[2]; + + u16 raw_power_on_time; + u16 adjusted_power_on_time; + u16 estimated_time_to_battery_warning; + u16 estimated_time_to_battery_failure; + + u8 reserved5[240]; +}; + +/* IBM's SIS smart dump table structures */ +struct ibmsis_sdt_entry +{ + u32 bar_str_offset; + u32 end_offset; + u8 entry_byte; + u8 reserved[3]; + u8 reserved2:5; + u8 valid_entry:1; + u8 reserved1:1; + u8 endian:1; + u8 resv; + u16 priority; +}; + +struct ibmsis_vset_res_state +{ + u16 stripe_size; + u8 prot_level; + u8 num_devices_in_vset; + u32 reserved6; +}; + +struct ibmsis_dasd_res_state +{ + u32 data_path_width; /* bits */ + u32 data_xfer_rate; /* 100 KBytes/second */ +}; + +struct ibmsis_query_res_state +{ + u8 reserved2:4; + u8 not_func:1; + u8 not_ready:1; + u8 not_oper:1; + u8 reserved1:1; + + u8 reserved3:7; + u8 read_write_prot:1; + + u8 reserved4:3; + u8 service_req:1; + u8 degraded_oper:1; + u8 prot_resuming:1; + u8 prot_suspended:1; + u8 prot_dev_failed:1; + + u8 reserved5; + + union + { + struct ibmsis_vset_res_state vset; + struct ibmsis_dasd_res_state dasd; + }dev; + + u32 ilid; + u32 failing_dev_ioasc; + struct ibmsis_res_addr failing_dev_res_addr; + u32 failing_dev_res_handle; + u8 protection_level_str[8]; +}; + +struct ibmsis_array_cap_entry +{ + u8 prot_level; +#define IBMSIS_DEFAULT_RAID_LVL "5" + u8 reserved:7; + u8 include_allowed:1; + u16 reserved2; + u8 reserved3; + u8 max_num_array_devices; + u8 min_num_array_devices; + u8 min_mult_array_devices; + u16 reserved4; + u16 supported_stripe_sizes; + u16 reserved5; + u16 recommended_stripe_size; + u8 prot_level_str[8]; +}; + +struct ibmsis_array_record +{ + struct ibmsis_record_common common; + u8 reserved:6; + u8 known_zeroed:1; + u8 issue_cmd:1; + u8 reserved1; + + u8 reserved2:5; + u8 non_func:1; + u8 exposed:1; + u8 established:1; + + u8 reserved3:5; + u8 resync_cand:1; + u8 stop_cand:1; + u8 start_cand:1; + + u8 reserved4[3]; + u8 array_id; + u32 reserved5; +}; + +struct ibmsis_array2_record +{ + struct ibmsis_record_common common; + + u8 reserved1:6; + u8 known_zeroed:1; + u8 issue_cmd:1; + + u8 reserved2; + + u8 reserved3:3; + u8 no_config_entry:1; + u8 high_avail:1; + u8 non_func:1; + u8 exposed:1; + u8 established:1; + + u8 reserved4:5; + u8 resync_cand:1; + u8 stop_cand:1; + u8 start_cand:1; + + u16 stripe_size; + + u8 raid_level; + u8 array_id; + u32 resource_handle; + u32 resource_address; + struct ibmsis_res_addr last_resource_address; + u8 vendor_id[8]; + u8 product_id[16]; + u8 serial_number[8]; + u32 reserved; +}; + +struct ibmsis_resource_flags +{ + u8 capacity_reduction_hi:2; + u8 reserved2:1; + u8 aff:1; + u8 reserved1:1; + u8 is_array_member:1; + u8 is_compressed:1; + u8 is_ioa_resource:1; + + u8 reserved3:7; + u8 capacity_reduction_lo:1; +}; + +struct ibmsis_device_record +{ + struct ibmsis_record_common common; + u8 reserved:6; + u8 known_zeroed:1; + u8 issue_cmd:1; + + u8 reserved1; + + u8 reserved2:2; + u8 no_cfgte_dev:1; + u8 no_cfgte_vol:1; + u8 is_hot_spare:1; + u8 is_exposed_device:1; + u8 has_parity:1; + u8 array_member:1; + + u8 zero_cand:1; + u8 rebuild_cand:1; + u8 exclude_cand:1; + u8 include_cand:1; + u8 resync_cand:1; + u8 stop_cand:1; + u8 parity_cand:1; + u8 start_cand:1; + + u8 reserved3:6; + u8 rmv_hot_spare_cand:1; + u8 add_hot_spare_cand:1; + + u8 reserved4[2]; + u8 array_id; + u32 resource_handle; + u16 reserved5; + struct ibmsis_resource_flags resource_flags_to_become; + u32 user_area_size_to_become; +}; + +/* 44 bytes */ +struct ibmsis_std_inq_data{ + u8 peri_dev_type:5; + u8 peri_qual:3; + + u8 reserved1:7; + u8 removeable_medium:1; + + u8 version; + + u8 resp_data_fmt:4; + u8 hi_sup:1; + u8 norm_aca:1; + u8 obsolete1:1; + u8 aen:1; + + u8 additional_len; + + u8 reserved2:7; + u8 sccs:1; + + u8 addr16:1; + u8 obsolete2:2; + u8 mchngr:1; + u8 multi_port:1; + u8 vs:1; + u8 enc_serv:1; + u8 bque:1; + + u8 vs2:1; + u8 cmd_que:1; + u8 trans_dis:1; + u8 linked:1; + u8 sync:1; + u8 wbus16:1; + u8 obsolete3:1; + u8 rel_adr:1; + + /* Vendor and Product ID */ + struct ibmsis_std_inq_vpids vpids; + + /* ROS and RAM levels */ + u8 ros_rsvd_ram_rsvd[4]; + + /* Serial Number */ + u8 serial_num[IBMSIS_SERIAL_NUM_LEN]; +}; + +struct ibmsis_std_inq_data_long +{ + struct ibmsis_std_inq_data std_inq_data; + u8 z1_term[IBMSIS_STD_INQ_Z1_TERM_LEN]; + u8 ius:1; + u8 qas:1; + u8 clocking:2; + u8 reserved:4; + u8 reserved1[41]; + u8 z2_term[IBMSIS_STD_INQ_Z2_TERM_LEN]; + u8 z3_term[IBMSIS_STD_INQ_Z3_TERM_LEN]; + u8 reserved2; + u8 z4_term[IBMSIS_STD_INQ_Z4_TERM_LEN]; + u8 z5_term[IBMSIS_STD_INQ_Z5_TERM_LEN]; + u8 part_number[IBMSIS_STD_INQ_PART_NUM_LEN]; + u8 ec_level[IBMSIS_STD_INQ_EC_LEVEL_LEN]; + u8 fru_number[IBMSIS_STD_INQ_FRU_NUM_LEN]; + u8 z6_term[IBMSIS_STD_INQ_Z6_TERM_LEN]; +}; + +struct ibmsis_mode_page_28_scsi_dev_bus_attr +{ + struct ibmsis_res_addr res_addr; + + u8 reserved2:2; + u8 lvd_to_se_transition_not_allowed:1; + u8 target_mode_supported:1; + u8 term_power_absent:1; + u8 enable_target_mode:1; + u8 qas_capability:2; +#define IBMSIS_MODEPAGE28_QAS_CAPABILITY_NO_CHANGE 0 +#define IBMSIS_MODEPAGE28_QAS_CAPABILITY_DISABLE_ALL 1 +#define IBMSIS_MODEPAGE28_QAS_CAPABILITY_ENABLE_ALL 2 +/* NOTE: Due to current operation conditions QAS should + never be enabled so the change mask will be set to 0 */ +#define IBMSIS_MODEPAGE28_QAS_CAPABILITY_CHANGE_MASK 0 + + u8 scsi_id; +#define IBMSIS_MODEPAGE28_SCSI_ID_NO_CHANGE 0x80u +#define IBMSIS_MODEPAGE28_SCSI_ID_NO_ID 0xFFu + + u8 bus_width; +#define IBMSIS_MODEPAGE28_BUS_WIDTH_NO_CHANGE 0 + + u8 extended_reset_delay; +#define IBMSIS_EXTENDED_RESET_DELAY 7 + + u32 max_xfer_rate; +#define IBMSIS_MODEPAGE28_MAX_XFR_RATE_NO_CHANGE 0 + + u8 min_time_delay; +#define IBMSIS_DEFAULT_SPINUP_DELAY 0xFFu +#define IBMSIS_INIT_SPINUP_DELAY 5 + u8 reserved3; + u16 reserved4; +}; + +#elif (defined(__KERNEL__) && defined(__BIG_ENDIAN)) || \ +(!defined(__KERNEL__) && (__BYTE_ORDER == __BIG_ENDIAN)) +#define htosis16(x) (x) +#define htosis32(x) (x) +#define sistoh16(x) (x) +#define sistoh32(x) (x) +#define _i16(x) (x) +#define _i32(x) (x) + +#define IBMSIS_BIG_ENDIAN 1 +#define IBMSIS_LITTLE_ENDIAN 0 + +struct ibmsis_mode_page_hdr +{ + u8 page_code:6; + u8 reserved1:1; + u8 parms_saveable:1; + u8 page_length; +}; + +struct ibmsis_control_mode_page +{ + /* Mode page 0x0A */ + struct ibmsis_mode_page_hdr header; + u8 tst:3; + u8 reserved1:3; + u8 gltsd:1; + u8 rlec:1; + u8 queue_algorithm_modifier:4; + u8 reserved2:1; + u8 qerr:2; + u8 dque:1; + u8 reserved3:1; + u8 rac:1; + u8 reserved4:2; + u8 swp:1; + u8 raerp:1; + u8 uaaerp:1; + u8 eaerp:1; + u8 reserved5; + u16 ready_aen_holdoff_period; + u16 busy_timeout_period; + u16 reserved6; +}; + +struct ibmsis_reclaim_query_data +{ + u8 action_status; +#define IBMSIS_ACTION_SUCCESSFUL 0 +#define IBMSIS_ACTION_NOT_REQUIRED 1 +#define IBMSIS_ACTION_NOT_PERFORMED 2 + u8 reclaim_known_needed:1; + u8 reclaim_unknown_needed:1; + u8 reserved2:2; + u8 reclaim_known_performed:1; + u8 reclaim_unknown_performed:1; + u8 reserved3:1; + u8 num_blocks_needs_multiplier:1; + + u16 num_blocks; + + u8 rechargeable_battery_type; +#define IBMSIS_BATTERY_TYPE_NO_BATTERY 0 +#define IBMSIS_BATTERY_TYPE_NICD 1 +#define IBMSIS_BATTERY_TYPE_NIMH 2 +#define IBMSIS_BATTERY_TYPE_LIION 3 + + u8 rechargeable_battery_error_state; +#define IBMSIS_BATTERY_NO_ERROR_STATE 0 +#define IBMSIS_BATTERY_WARNING_STATE 1 +#define IBMSIS_BATTERY_ERROR_STATE 2 + + u8 reserved4[2]; + + u16 raw_power_on_time; + u16 adjusted_power_on_time; + u16 estimated_time_to_battery_warning; + u16 estimated_time_to_battery_failure; + + u8 reserved5[240]; +}; + +/* IBM's SIS smart dump table structures */ +struct ibmsis_sdt_entry +{ + u32 bar_str_offset; + u32 end_offset; + u8 entry_byte; + u8 reserved[3]; + u8 endian:1; + u8 reserved1:1; + u8 valid_entry:1; + u8 reserved2:5; + u8 resv; + u16 priority; +}; + +struct ibmsis_vset_res_state +{ + u16 stripe_size; + u8 prot_level; + u8 num_devices_in_vset; + u32 reserved6; +}; + +struct ibmsis_dasd_res_state +{ + u32 data_path_width; /* bits */ + u32 data_xfer_rate; /* 100 KBytes/second */ +}; + +struct ibmsis_query_res_state +{ + u8 reserved1:1; + u8 not_oper:1; + u8 not_ready:1; + u8 not_func:1; + u8 reserved2:4; + + u8 read_write_prot:1; + u8 reserved3:7; + + u8 prot_dev_failed:1; + u8 prot_suspended:1; + u8 prot_resuming:1; + u8 degraded_oper:1; + u8 service_req:1; + u8 reserved4:3; + + u8 reserved5; + + union + { + struct ibmsis_vset_res_state vset; + struct ibmsis_dasd_res_state dasd; + }dev; + + u32 ilid; + u32 failing_dev_ioasc; + struct ibmsis_res_addr failing_dev_res_addr; + u32 failing_dev_res_handle; + u8 protection_level_str[8]; +}; + +struct ibmsis_array_cap_entry +{ + u8 prot_level; +#define IBMSIS_DEFAULT_RAID_LVL "5" + u8 include_allowed:1; + u8 reserved:7; + u16 reserved2; + u8 reserved3; + u8 max_num_array_devices; + u8 min_num_array_devices; + u8 min_mult_array_devices; + u16 reserved4; + u16 supported_stripe_sizes; + u16 reserved5; + u16 recommended_stripe_size; + u8 prot_level_str[8]; +}; + +struct ibmsis_array_record +{ + struct ibmsis_record_common common; + u8 issue_cmd:1; + u8 known_zeroed:1; + u8 reserved:6; + u8 reserved1; + u8 established:1; + u8 exposed:1; + u8 non_func:1; + u8 reserved2:5; + u8 start_cand:1; + u8 stop_cand:1; + u8 resync_cand:1; + u8 reserved3:5; + u8 reserved4[3]; + u8 array_id; + u32 reserved5; +}; + +struct ibmsis_array2_record +{ + struct ibmsis_record_common common; + + u8 issue_cmd:1; + u8 known_zeroed:1; + u8 reserved1:6; + + u8 reserved2; + + u8 established:1; + u8 exposed:1; + u8 non_func:1; + u8 high_avail:1; + u8 no_config_entry:1; + u8 reserved3:3; + + u8 start_cand:1; + u8 stop_cand:1; + u8 resync_cand:1; + u8 reserved4:5; + + u16 stripe_size; + + u8 raid_level; + u8 array_id; + u32 resource_handle; + u32 resource_address; + struct ibmsis_res_addr last_resource_address; + u8 vendor_id[8]; + u8 product_id[16]; + u8 serial_number[8]; + u32 reserved; +}; + +struct ibmsis_resource_flags +{ + u8 is_ioa_resource:1; + u8 is_compressed:1; + u8 is_array_member:1; + u8 reserved1:1; + u8 aff:1; + u8 reserved2:1; + u8 capacity_reduction_hi:2; + + u8 capacity_reduction_lo:1; + u8 reserved3:7; +}; + +struct ibmsis_device_record +{ + struct ibmsis_record_common common; + u8 issue_cmd:1; + u8 known_zeroed:1; + u8 reserved:6; + + u8 reserved1; + + u8 array_member:1; + u8 has_parity:1; + u8 is_exposed_device:1; + u8 is_hot_spare:1; + u8 no_cfgte_vol:1; + u8 no_cfgte_dev:1; + u8 reserved2:2; + + u8 start_cand:1; + u8 parity_cand:1; + u8 stop_cand:1; + u8 resync_cand:1; + u8 include_cand:1; + u8 exclude_cand:1; + u8 rebuild_cand:1; + u8 zero_cand:1; + + u8 add_hot_spare_cand:1; + u8 rmv_hot_spare_cand:1; + u8 reserved3:6; + + u8 reserved4[2]; + u8 array_id; + u32 resource_handle; + u16 reserved5; + struct ibmsis_resource_flags resource_flags_to_become; + u32 user_area_size_to_become; +}; + +/* 44 bytes */ +struct ibmsis_std_inq_data{ + u8 peri_qual:3; + u8 peri_dev_type:5; + + u8 removeable_medium:1; + u8 reserved1:7; + + u8 version; + + u8 aen:1; + u8 obsolete1:1; + u8 norm_aca:1; + u8 hi_sup:1; + u8 resp_data_fmt:4; + + u8 additional_len; + + u8 sccs:1; + u8 reserved2:7; + + u8 bque:1; + u8 enc_serv:1; + u8 vs:1; + u8 multi_port:1; + u8 mchngr:1; + u8 obsolete2:2; + u8 addr16:1; + + u8 rel_adr:1; + u8 obsolete3:1; + u8 wbus16:1; + u8 sync:1; + u8 linked:1; + u8 trans_dis:1; + u8 cmd_que:1; + u8 vs2:1; + + /* Vendor and Product ID */ + struct ibmsis_std_inq_vpids vpids; + + /* ROS and RAM levels */ + u8 ros_rsvd_ram_rsvd[4]; + + /* Serial Number */ + u8 serial_num[IBMSIS_SERIAL_NUM_LEN]; +}; + +struct ibmsis_std_inq_data_long +{ + struct ibmsis_std_inq_data std_inq_data; + u8 z1_term[IBMSIS_STD_INQ_Z1_TERM_LEN]; + u8 reserved:4; + u8 clocking:2; + u8 qas:1; + u8 ius:1; + u8 reserved1[41]; + u8 z2_term[IBMSIS_STD_INQ_Z2_TERM_LEN]; + u8 z3_term[IBMSIS_STD_INQ_Z3_TERM_LEN]; + u8 reserved2; + u8 z4_term[IBMSIS_STD_INQ_Z4_TERM_LEN]; + u8 z5_term[IBMSIS_STD_INQ_Z5_TERM_LEN]; + u8 part_number[IBMSIS_STD_INQ_PART_NUM_LEN]; + u8 ec_level[IBMSIS_STD_INQ_EC_LEVEL_LEN]; + u8 fru_number[IBMSIS_STD_INQ_FRU_NUM_LEN]; + u8 z6_term[IBMSIS_STD_INQ_Z6_TERM_LEN]; +}; + +struct ibmsis_mode_page_28_scsi_dev_bus_attr +{ + struct ibmsis_res_addr res_addr; + u8 qas_capability:2; +#define IBMSIS_MODEPAGE28_QAS_CAPABILITY_NO_CHANGE 0 +#define IBMSIS_MODEPAGE28_QAS_CAPABILITY_DISABLE_ALL 1 +#define IBMSIS_MODEPAGE28_QAS_CAPABILITY_ENABLE_ALL 2 +/* NOTE: Due to current operation conditions QAS should + never be enabled so the change mask will be set to 0 */ +#define IBMSIS_MODEPAGE28_QAS_CAPABILITY_CHANGE_MASK 0 + + u8 enable_target_mode:1; + u8 term_power_absent:1; + u8 target_mode_supported:1; + u8 lvd_to_se_transition_not_allowed:1; + u8 reserved2:2; + + u8 scsi_id; +#define IBMSIS_MODEPAGE28_SCSI_ID_NO_CHANGE 0x80u +#define IBMSIS_MODEPAGE28_SCSI_ID_NO_ID 0xFFu + + u8 bus_width; +#define IBMSIS_MODEPAGE28_BUS_WIDTH_NO_CHANGE 0 + + u8 extended_reset_delay; +#define IBMSIS_EXTENDED_RESET_DELAY 7 + + u32 max_xfer_rate; +#define IBMSIS_MODEPAGE28_MAX_XFR_RATE_NO_CHANGE 0 + + u8 min_time_delay; +#define IBMSIS_DEFAULT_SPINUP_DELAY 0xFFu +#define IBMSIS_INIT_SPINUP_DELAY 5 + u8 reserved3; + u16 reserved4; +}; +#else +#error "Neither __LITTLE_ENDIAN nor __BIG_ENDIAN defined" +#endif + +#define SIS_CONFIG_DIR "/etc/ibmsis/" +#define SIS_QAS_CAPABILITY "QAS_CAPABILITY" +#define SIS_HOST_SCSI_ID "HOST_SCSI_ID" +#define SIS_BUS_WIDTH "BUS_WIDTH" +#define SIS_MAX_XFER_RATE "MAX_BUS_SPEED" +#define SIS_MIN_TIME_DELAY "MIN_TIME_DELAY" +#define SIS_CATEGORY_BUS "Bus" +#define SIS_LIMITED_MAX_XFER_RATE 80 +/* SIS_LIMITED_CONFIG is used to compensate for + a set of devices which will not allow firmware + udpates when operating at high max transfer rates. + Selecting the LIMITED_CONFIG adjusts the max + transfer rate allowing successfull firmware update + operations to be performed */ +#define SIS_LIMITED_CONFIG 0x7FFF +#define SIS_SAVE_LIMITED_CONFIG 0x8000 +#define SIS_NORMAL_CONFIG 0 + +/* Internal return codes */ +#define RC_SUCCESS 0 +#define RC_FAILED -1 +#define RC_NOOP -2 +#define RC_NOT_PERFORMED -3 +#define RC_IN_USE -4 +#define RC_CANCEL 12 +#define RC_REFRESH 1 +#define RC_EXIT 3 + +struct sis_device{ + char dev_name[64]; + char gen_name[64]; + int opens; + u32 is_start_cand:1; + u32 is_reclaim_cand:1; + u32 reserved:30; + struct ibmsis_resource_entry *p_resource_entry; + struct ibmsis_record_common *p_qac_entry; +}; + +struct sis_ioa{ + struct sis_device ioa; + u16 ccin; + u32 host_num; + u32 host_addr; + char serial_num[9]; + u32 num_raid_cmds; + char driver_version[50]; + char firmware_version[40]; + char part_num[20]; + u16 num_devices; + struct sis_device *dev; + struct ibmsis_resource_table *p_resource_table; + struct ibmsis_array_query_data *p_qac_data; + struct ibmsis_supported_arrays *p_supported_arrays; + struct ibmsis_reclaim_query_data *p_reclaim_data; + struct sis_ioa *p_next; + struct sis_ioa *p_cmd_next; +}; + +struct sg_proc_info +{ + int host; + int channel; + int id; + int lun; + int type; + int opens; + int qdepth; + int busy; + int online; +}; + +struct sg_map_info +{ + char dev_name[64]; + char gen_name[64]; + struct sg_scsi_id sg_dat; +}; + +struct ibmsis_dasd_inquiry_page3 +{ + u8 peri_qual_dev_type; + u8 page_code; + u8 reserved1; + u8 page_length; + u8 ascii_len; + u8 reserved2[3]; + u8 load_id[4]; + u8 release_level[4]; +}; + +struct ibmsis_array_query_data +{ + u16 resp_len; + u8 reserved; + u8 num_records; + u8 data[IBMSIS_QAC_BUFFER_SIZE]; +}; + +struct ibmsis_block_desc { + u8 num_blocks[4]; + u8 density_code; + u8 block_length[3]; +}; + +struct ibmsis_mode_parm_hdr +{ + u8 length; + u8 medium_type; + u8 device_spec_parms; + u8 block_desc_len; +}; + +struct sense_data_t { + u8 error_code; + u8 segment_numb; + u8 sense_key; + u8 info[4]; + u8 add_sense_len; + u8 cmd_spec_info[4]; + u8 add_sense_code; + u8 add_sense_code_qual; + u8 field_rep_unit_code; + u8 sense_key_spec[3]; + u8 add_sense_bytes[0]; +}; + +struct ibmsis_resource_entry +{ + u8 is_ioa_resource:1; + u8 is_compressed:1; + u8 is_array_member:1; + u8 format_allowed:1; + u8 dev_changed:1; + u8 in_init:1; + u8 redo_init:1; + u8 rw_protected:1; + + u8 level; + u8 array_id; + u8 subtype; + + struct ibmsis_res_addr resource_address; + + u16 type; + + u16 model; + + /* The following two fields are used only for DASD */ + u32 sw_load_id; + + u32 sw_release_level; + + char serial_num[IBMSIS_SERIAL_NUM_LEN+1]; /* Null terminated ascii */ + + u8 is_hidden:1; + u8 is_af:1; + u8 is_hot_spare:1; + u8 supports_qas:1; + u8 nr_ioa_microcode:1; + u8 ioa_dead:1; + u8 reserved4:2; + + u16 host_no; + + u32 resource_handle; /* In big endian byteorder */ + + /* NOTE: DSA/UA and frame_id/slot_label are only valid in iSeries Linux */ + /* In other architectures, DSA/UA will be set to zero and */ + /* frame_id/slot_label will be initialized to ASCII spaces */ + u32 dsa; +#define IBMSIS_SYS_IBMSIS_BUS_MASK 0xffff0000 +#define IBMSIS_SYS_CARD_MASK 0x0000ff00 +#define IBMSIS_IO_ADAPTER_MASK 0x000000ff +#define IBMSIS_GET_SYS_BUS(dsa) \ + ((dsa & IBMSIS_SYS_IBMSIS_BUS_MASK) >> 16) +#define IBMSIS_GET_SYS_CARD(dsa) \ + ((dsa & IBMSIS_SYS_CARD_MASK) >> 8) +#define IBMSIS_GET_IO_ADAPTER(dsa) \ + (dsa & IBMSIS_IO_ADAPTER_MASK) + + u32 unit_address; +#define IBMSIS_IO_BUS_MASK 0x0f000000 +#define IBMSIS_CTL_MASK 0x00ff0000 +#define IBMSIS_DEV_MASK 0x0000ff00 +#define IBMSIS_GET_IO_BUS(ua) \ + ((ua & IBMSIS_IO_BUS_MASK) >> 24) +#define IBMSIS_GET_CTL(ua) \ + ((ua & IBMSIS_CTL_MASK) >> 16) +#define IBMSIS_GET_DEV(ua) \ + ((ua & IBMSIS_DEV_MASK) >> 8) + + u32 pci_bus_number; + u32 pci_slot; + + u8 frame_id[3]; + u8 slot_label[4]; + u8 pseries_location[IBMSIS_MAX_PSERIES_LOCATION_LEN+1]; + + u8 part_number[IBMSIS_STD_INQ_PART_NUM_LEN+1]; + u8 ec_level[IBMSIS_STD_INQ_EC_LEVEL_LEN+1]; + u8 fru_number[IBMSIS_STD_INQ_FRU_NUM_LEN+1]; + u8 z1_term[IBMSIS_STD_INQ_Z1_TERM_LEN+1]; + u8 z2_term[IBMSIS_STD_INQ_Z2_TERM_LEN+1]; + u8 z3_term[IBMSIS_STD_INQ_Z3_TERM_LEN+1]; + u8 z4_term[IBMSIS_STD_INQ_Z4_TERM_LEN+1]; + u8 z5_term[IBMSIS_STD_INQ_Z5_TERM_LEN+1]; + u8 z6_term[IBMSIS_STD_INQ_Z6_TERM_LEN+1]; + + struct ibmsis_std_inq_data std_inq_data; +}; + +struct ibmsis_resource_hdr +{ + u16 num_entries; + u16 reserved; +}; + +struct ibmsis_resource_table +{ + struct ibmsis_resource_hdr hdr; + struct ibmsis_resource_entry dev[IBMSIS_MAX_PHYSICAL_DEVS]; +}; + +struct ibmsis_mode_page_28_header +{ + struct ibmsis_mode_page_hdr header; + u8 num_dev_entries; + u8 dev_entry_length; +}; + +struct sis_page_28 +{ + struct ibmsis_mode_page_28_header page_hdr; + struct ibmsis_mode_page_28_scsi_dev_bus_attr attr[IBMSIS_MAX_NUM_BUSES]; +}; + +struct ibmsis_page_28 +{ + struct ibmsis_mode_parm_hdr parm_hdr; + struct ibmsis_mode_page_28_header page_hdr; + struct ibmsis_mode_page_28_scsi_dev_bus_attr attr[IBMSIS_MAX_NUM_BUSES]; +}; + +struct ibmsis_supported_arrays +{ + struct ibmsis_record_common common; + u16 num_entries; + u16 entry_length; + u8 data[0]; +}; + +struct ibmsis_read_cap +{ + u32 max_user_lba; + u32 block_length; +}; + +struct ibmsis_read_cap16 +{ + u32 max_user_lba_hi; + u32 max_user_lba_lo; + u32 block_length; +}; + +/* Struct for disks that are unsupported or require a minimum microcode + level prior to formatting to 522-byte sectors. */ +struct unsupported_af_dasd +{ + char vendor_id[IBMSIS_VENDOR_ID_LEN + 1]; + char compare_vendor_id_byte[IBMSIS_VENDOR_ID_LEN]; + char product_id[IBMSIS_PROD_ID_LEN + 1]; + char compare_product_id_byte[IBMSIS_PROD_ID_LEN]; + struct ibmsis_std_inq_vpids vpid; /* vpid - meaningful bits */ + struct ibmsis_std_inq_vpids vpid_mask; /* mask don't cares in the vpid */ + char lid[5]; /* Load ID - Bytes 8-11 of Inquiry Page 3 */ + char lid_mask[4]; /* Mask for certain bytes of the LID */ + uint supported_with_min_ucode_level; + char min_ucode_level[5]; + char min_ucode_mask[4]; /* used to mask don't cares in the ucode level */ +}; + +struct ibmsis_cmd_status_record +{ + u16 reserved1; + u16 length; + u8 array_id; + u8 command_code; + u8 status; +#define IBMSIS_CMD_STATUS_SUCCESSFUL 0 +#define IBMSIS_CMD_STATUS_IN_PROGRESS 2 +#define IBMSIS_CMD_STATUS_ATTRIB_CHANGE 3 +#define IBMSIS_CMD_STATUS_FAILED 4 +#define IBMSIS_CMD_STATUS_INSUFF_DATA_MOVED 5 + + u8 percent_complete; + struct ibmsis_res_addr failing_dev_res_addr; + u32 failing_dev_res_handle; + u32 failing_dev_ioasc; + u32 ilid; + u32 resource_handle; +}; + +struct ibmsis_cmd_status +{ + u16 resp_len; + u8 reserved; + u8 num_records; + struct ibmsis_cmd_status_record record[100]; +}; + +struct ibmsis_std_inq_vpids_sn +{ + struct ibmsis_std_inq_vpids vpids; + u8 serial_num[IBMSIS_SERIAL_NUM_LEN]; +}; + +struct ibmsis_discard_cache_data +{ + u32 length; + union { + struct ibmsis_std_inq_vpids_sn vpids_sn; + u32 add_cmd_parms[10]; + }data; +}; + +struct ibmsis_software_inq_lid_info +{ + u32 load_id; + u32 timestamp[3]; +}; + +struct ibmsis_inquiry_page0 /* Supported Vital Product Data Pages */ +{ + u8 peri_qual_dev_type; + u8 page_code; + u8 reserved1; + u8 page_length; + u8 supported_page_codes[IBMSIS_MAX_NUM_SUPP_INQ_PAGES]; +}; + +struct ibmsis_inquiry_page3 +{ + u8 peri_qual_dev_type; + u8 page_code; + u8 reserved1; + u8 page_length; + u8 ascii_len; + u8 reserved2[3]; + u8 load_id[4]; + u8 major_release; + u8 card_type; + u8 minor_release[2]; + u8 ptf_number[4]; + u8 patch_number[4]; +}; + +struct ibmsis_dasd_ucode_header +{ + u8 length[3]; + u8 load_id[4]; + u8 modification_level[4]; + u8 ptf_number[4]; + u8 patch_number[4]; +}; + +struct ibmsis_inquiry_page_cx /* Extended Software Inquiry */ +{ + u8 peri_qual_dev_type; + u8 page_code; + u8 reserved1; + u8 page_length; + u8 ascii_length; + u8 reserved2[3]; + + struct ibmsis_software_inq_lid_info lidinfo[15]; +}; + +struct ibmsis_driver_cfg +{ + u16 debug_level; + u16 trace_level; + u16 debug_level_max; + u16 trace_level_max; +}; + +/* NOTE: The structure below is a shared structure with user-land tools */ +/* We need to make sure we don't put pointers in here as the + utilities could be running in 32 bit mode on a 64 bit kernel. */ +struct ibmsis_ioctl_cmd_type2 +{ + u32 type:8; /* type is used to distinguish between ioctl_cmd structure formats */ +#define IBMSIS_IOCTL_TYPE_2 0x03 + u32 reserved:21; + u32 read_not_write:1; /* data direction */ + u32 device_cmd:1; /* used to pass commands to specific devices identified by resource address */ + u32 driver_cmd:1; /* used exclusively to pass commands to the device driver, 0 otherwise */ + struct ibmsis_res_addr resource_address; +#define IBMSIS_CDB_LEN 16 + u8 cdb[IBMSIS_CDB_LEN]; + u32 buffer_len; + u8 buffer[0]; +}; + +/* The structures below are deprecated and should not be used. Use the + structure above to send ioctls instead */ +struct ibmsis_ioctl_cmd_internal +{ + u32 read_not_write:1; + u32 device_cmd:1; + u32 driver_cmd:1; + u32 reserved:29; + struct ibmsis_res_addr resource_address; +#define IBMSIS_CDB_LEN 16 + u8 cdb[IBMSIS_CDB_LEN]; + void *buffer; + u32 buffer_len; +}; + +int get_proc_string(char *proc_file_name, char *label, char *buffer); +int scan_device(struct ibmsis_res_addr resource_addr, u32 host_num); +int remove_device(struct ibmsis_res_addr resource_addr, struct sis_ioa *p_ioa); +int sis_ioctl(int fd, u32 cmd, struct ibmsis_ioctl_cmd_internal *p_ioctl_cmd); +int sg_ioctl(int fd, u8 cdb[IBMSIS_CCB_CDB_LEN], + void *p_data, u32 xfer_len, u32 data_direction, + struct sense_data_t *p_sense_data, + u32 timeout_in_sec); +int get_major_version(char *proc_file_name); +int get_minor_version(char *proc_file_name); +void check_current_config(bool allow_rebuild_refresh); +void get_sg_ioctl_data(struct sg_map_info *p_sg_map_info, int num_devs); +int get_sg_proc_data(struct sg_proc_info *p_sg_proc_info); +int num_device_opens(int host_num, int channel, int id, int lun); +void tool_init(); +void exit_on_error(char *, ...); +int sis_config_file_valid(char *usr_file_name); +int sis_config_file_read(char *usr_file_name, + char *category, + char *field, + char *value); +void sis_config_file_entry(char *usr_file_name, + char *category, + char *field, + char *value, + int update); +void sis_save_page_28(struct sis_ioa *p_ioa, + struct sis_page_28 *p_page_28_cur, + struct sis_page_28 *p_page_28_chg, + struct sis_page_28 *p_page_28_sis); +void sis_set_page_28(struct sis_ioa *p_cur_ioa, + int limited_config, + int reset_scheduled); +void sis_set_page_28_init(struct sis_ioa *p_cur_ioa, + int limited_config); +void sislog_location(struct ibmsis_resource_entry *); +bool is_af_blocked(struct sis_device *p_sis_device, int silent); + +/*--------------------------------------------------------------------------- + * Purpose: Identify Advanced Function DASD present + * Lock State: N/A + * Returns: 0 if not AF DASD + * 1 if AF DASD + *---------------------------------------------------------------------------*/ +static inline int ibmsis_is_af_dasd_device(struct ibmsis_resource_entry *p_resource_entry) +{ + if (IBMSIS_IS_DASD_DEVICE(p_resource_entry->std_inq_data) && + (!p_resource_entry->is_ioa_resource) && + (p_resource_entry->subtype == IBMSIS_SUBTYPE_AF_DASD)) + return 1; + else + return 0; +} + +#if (IBMSIS_DEBUG > 0) +#define syslog_dbg(...) syslog(__VA_ARGS__) +#else +#define syslog_dbg(...) +#endif + +#endif diff --git a/iprtrace.c b/iprtrace.c new file mode 100644 index 0000000..ba461da --- /dev/null +++ b/iprtrace.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} + diff --git a/iprupdate.8 b/iprupdate.8 new file mode 100644 index 0000000..897748c --- /dev/null +++ b/iprupdate.8 @@ -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/ diff --git a/iprupdate.c b/iprupdate.c new file mode 100644 index 0000000..a3b3e21 --- /dev/null +++ b/iprupdate.c @@ -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 +#include +#include +#include + +#ifndef iprlib_h +#include "iprlib.h" +#endif + +#include + +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; +} + diff --git a/spec/iprutils.spec b/spec/iprutils.spec new file mode 100644 index 0000000..1593c38 --- /dev/null +++ b/spec/iprutils.spec @@ -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 diff --git a/version.mk b/version.mk new file mode 100644 index 0000000..14aa1d9 --- /dev/null +++ b/version.mk @@ -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)"'