diff --git a/binary/Linux/lsiutil.x86_64 b/binary/Linux/lsiutil.x86_64 new file mode 100644 index 0000000..40225a0 Binary files /dev/null and b/binary/Linux/lsiutil.x86_64 differ diff --git a/binary/Solaris/lsiutil.i386 b/binary/Solaris/lsiutil.i386 new file mode 100644 index 0000000..3f65f77 Binary files /dev/null and b/binary/Solaris/lsiutil.i386 differ diff --git a/binary/Solaris/lsiutil.sparc b/binary/Solaris/lsiutil.sparc new file mode 100644 index 0000000..928bf79 Binary files /dev/null and b/binary/Solaris/lsiutil.sparc differ diff --git a/binary/dos/lsiutil.exe b/binary/dos/lsiutil.exe new file mode 100644 index 0000000..7f9de97 Binary files /dev/null and b/binary/dos/lsiutil.exe differ diff --git a/binary/efi/lsiutil.efi b/binary/efi/lsiutil.efi new file mode 100644 index 0000000..64eaa98 Binary files /dev/null and b/binary/efi/lsiutil.efi differ diff --git a/binary/efi/lsiutil32.efi b/binary/efi/lsiutil32.efi new file mode 100644 index 0000000..8534328 Binary files /dev/null and b/binary/efi/lsiutil32.efi differ diff --git a/binary/efi/lsiutil64.efi b/binary/efi/lsiutil64.efi new file mode 100644 index 0000000..b1e9194 Binary files /dev/null and b/binary/efi/lsiutil64.efi differ diff --git a/binary/windows/LSIUtil.exe b/binary/windows/LSIUtil.exe new file mode 100644 index 0000000..dae429c Binary files /dev/null and b/binary/windows/LSIUtil.exe differ diff --git a/binary/windows/LSIUtil_amd64.exe b/binary/windows/LSIUtil_amd64.exe new file mode 100644 index 0000000..8a701fd Binary files /dev/null and b/binary/windows/LSIUtil_amd64.exe differ diff --git a/binary/windows/LSIUtil_ia64.exe b/binary/windows/LSIUtil_ia64.exe new file mode 100644 index 0000000..662a999 Binary files /dev/null and b/binary/windows/LSIUtil_ia64.exe differ diff --git a/changes.txt b/changes.txt new file mode 100644 index 0000000..1bd32de --- /dev/null +++ b/changes.txt @@ -0,0 +1,861 @@ +Changes for 1.70: + +Enhancement Request: +- SCGCQ00440706 LSIUTIL Utility modification for New Gen3 Product name labels and fixing for incorrect Gen3 SAS uEFI version reporting. +- SCGCQ00438328 lsiutil - add support for inband expander CLI +- SCGCQ00468538 NetApp functionality to limit LUN Scan +- SCGCQ00467946 LSIUTIL on SPARC support + +Defects : +- SCGCQ00425049 LSIUTIL: EFI BIOS Erase Hang +- SCGCQ00438322 lsiutil 1.69 does not report the correct Device ID information for Gen 3 adapters + +----------------------------------------------------------------------------- + +Changes for 1.69: + +- Added Support for SAS3 Linux Drivers +- Fixed bug were OS names for drives > sdz were not displayed (on Linux) + +----------------------------------------------------------------------------- + +Changes for 1.68: + +- Fix in option 16 output. Added device type decode of STP target and added + fix to make sure undecoded device types will print nothing in the 'type' + field rather than the value from the last successfully decoded device. +- Added support for creating raid volumes on drives greater than 2TB + Modified method docreatevolume2() +- Added support for creating raid volumes with 4k drives on MPI2 and MPI2.5 + controllers. StripSize will be set to zero to let firmware calculate it. +- Modified source file copyright information + +----------------------------------------------------------------------------- + +Changes for 1.67: + +- Updated to MPI2 2.00.XX header files (MPI2.5 rev B). Includes support + for identifying SAS3XXXX devices. MPI2.5 support for DOS and EFI are not + supported at this time. +- Added option 25 for Power Management settings to contain the MPI control + message, get IOUnitPage7, and get/set SasIoUnitPage8. +- Added sub-option 60 (change RAID rate) to the RAID actions menu (option 21) +- Added option 71 to decode Flags and DeviceInfo for SASDevicePage0 + for each device attached to the adapter. +- Modified the Alta programming/display algorithm (Option 58, sub-option 1 & 2) + to allow for 16 character serial number and part numbers (per the spec). + Also added the global flag option to prompt for errors created by a + non-existent SAS Address in the parameter file. (use lsiutil -g to turn it on). +- Fixed SAS Address programming in option 44 to program a sequential address + for each PHY (as opposed to only programming PHY[0]). +- Add support for the LSI SAS3 expander in the following areas: + - Support for resetting the expander (main menu option 20 (diagnostic menu) + -> option 98 (Reset Expander)) + - Support for firmware image signature checking to help validate a firmware + download image matches the correct expander type (main menu option 20 + (diagnostic menu) -> option 20 (Expander firmware download)) + - Support for the SAS3 expander when specifying 'all' as the expander to + update in the expander firmware download option (allows update of all + expanders (of the same type) in a domain at once). + - Support when doing a manufacturing image update via the expander firmware + download option or when using the option to modify expander mfg image + fields (main menu option 20 (diagnostic menu) -> option 27 (Change + SAS2/SAS3 Expander Manufacturing Data Fields)). +- Added WarpDrive recognition +- Added support for new Windows XP driver name. +- Added option 72 to store SC information (MPI2.0-only) + +----------------------------------------------------------------------------- + +Changes for 1.66: + +- Updated to MPI2 2.00.18 header files (MPI2 rev Q). Includes support in + option 67 and 100 for newly refined config pages as well as device ID + recognition updates. +- Added the ability to decode the raw timestamps in option 35 (display HBA + firmware logs) into a readable format. The default behavior is unchanged + from previous releases. Invoke lsiutil with the '-g' flag to enable a + prompt in option 35 for doing the decoding. +- Modified command line argument checking to return appropriate error codes + (EINVAL, ENODEV) for incorrect parameters rather than success. +- Modified doIndentify() for SAS to upload the firmware from the backup region + rather than active. This allows for image verification after firmware + download without first resetting adapter. +- For read/write tests replaced the NCR pattern with a random one. +- added some improvements to SCSI error handling, especially check conditions + to be more generic and catch more errors. +- Updated option 20, sub-option 16 (Issue product-specific SAS IO Unit Control) + to work with SAS GEN2 HBAS. +- For DOS/EFI, fixed the startup error message seen with recent SAS GEN2 HBA + HBA firmware (mpt_receive_data failed, IOCStatus = 0020 (Invalid Action)) +- Improved HBA detection under EFI for some platforms without PCI dual + address cycle support. +- For option 65 (SAS UART Debug Console), changed the default buffer size to + 1MB (on Windows default is now calculated based on the MaxSGList driver + registry parameter). The user is no longer prompted for a buffer size to + allocate by default. To enable the prompt for buffer size invoke lsiutil + with the '-g' flag. +- fixed an issue with displaying hidden RAID devices (in option 8 output) + for inactive volumes +- In option 43 (Diagnostic Buffer actions), updated the ProductSpecific + parameters (debug masks) in the Register option to support 64-bit values + for MPI2. +- In option 21, sub-option 1 (Show Volumes in the RAID actions menu) fixed + interpretation of data scrub to properly indicate whether it is allowed + rather than to mean that it is "in progress". +- Under Linux resolved the warnings to the system log indicating lsiutil + 'tainting' the system due to mmap() slowpath on kernels 2.6.27 and later. +- Fixed an issue with a SAS2308 HBA being reported as a SAS2208. +- For option 20, sub-option 30 (Inject media error in the Diagnostics menu), + improved the error handling and added support for sending WRITE LONG(10) + with WR_UNCOR set which will get translated to ATA WRITE UNCORRECTABLE EXT + for SATA drives. +- Removed menu item 6 (Download SEEPROM) and menu item 7 (Upload SEEPROM) for + SAS products since they were not applicable. + +----------------------------------------------------------------------------- + +Changes for 1.65: + +- For SAS2 HBAs, add support for target IDs greater than 255. Also optimized + option 8 (scan for devices) under Linux and Windows to only scan for devices + in the range of targets the firmware indicates exists based on devhandles. +- Added a -8 command line argument to limit the number of LUNs scanned to 8 + instead of the default of 256. +- Fixed option 42 (Display OS device names) for both Linux and Solaris for + SAS2 HBAs. +- Fixed option 42 (Display OS device names) under Linux when using kernels + 2.6.31 and later. +- Fixed option 42 (Display OS device names) for IR RAID Volumes under Linux. +- Fixed a display bug in the output of 'Show physical disks' (RAID Action menu + item 2). The devhandles for the disk paths should now be output correctly. +- Increased the chip reset delay under DOS and EFI to 50ms (up from 20ms). +- Changed the DOS/EFI driver to correctly use the default descriptor rather + than SCSI IO descriptor for RAID passthrough requests. +- Fixed the NVDATA "wrong board" warning for SAS2 HBAs when downloading + firmware. + +----------------------------------------------------------------------------- + +Changes for 1.64: + +- Updated to MPI2 2.00.13 header files. Includes support in option 67 and + 100 to print the newly defined config pages. Also includes the 2208 + device ID recognition. +- Updated to MPI1 01.05.20 header files. Minor changes only, this has no + functional impact. +- Added a new expert main menu option 65 ("SAS UART Debug Console") which is + available for SAS2 HBAs. Running this option prompts the user for how + large a buffer to reserve for command responses as well as whether they + would like to log the output to a file. After this, the user is given a + '%' prompt to enter commands, mimic'ing the UART console. The user can + type 'exit' to return to the normal lsiutil menu. + Standard '-a' scripting of this console feature is available as well. For + example, the following command line will start lsiutil using the second + HBA port found, start the UART console, and execute the "iop show diag" + and "exit" commands before quitting: + # lsiutil -p 2 -a 65,,,"iop show diag","exit",0 +- Added a few improvements for working with LSI SAS2 expanders (Bobcat): + o Recognize the buffer IDs for bobcat firmware images and manufacturing + data so a warning is no longer printed when updating. + o Enhanced the expander firmware download (diagnostic menu option 20) to + distinguish between LSI SAS1 and SAS2 expanders if the 'all' option + is used to update all expanders in the domain and there is a mix of SAS1 + and SAS2 expanders. In this case, the user is given the option of which + type of expander to perform the update on. NOTE: that there is no + support to differentiate between different platforms within the SAS1 or + SAS2 space. So, for example, if there is a mix of SAS1 expanders that + require different firmware images, the 'all' option will provide no + protection against putting the same firmware image in all the expanders. + o When using expander firmware download (diagnostic menu option 20) to + update the manufacturing image for an LSI SAS2 expander, lsiutil will + fetch the current SAS address, Enclosure Logical ID, and Ethernet MAC + Address from the expander as well as from the image file provided by the + user and then for each field, prompt the user on whether they would like + to use the value in the supplied manufacturing image (the default), + preserve the existing value already in the expander, or override the value + on the spot. + o Added a new expert level menu option 27 under the diagnostic menu + (option 20 from the main menu) called "Change SAS2 Expander Manufacturing + Data Fields". This option will retrieve the current manufacturing data + from the selected LSI SAS2 expander and then display to the user the + current SAS Address, Enclosure Logical ID, and Ethernet MAC Address and + allow the user to enter new values for any of these fields. The new + values are then written back to the expander, to take effect after the + expander is reset. +- updated the chip recognition for all current LSI MPT chips/revisions. +- Fixed event reporting (option 43) for SAS1 HBAs under SPARC Solaris. +- updated the vi settings to reflect use of spaces rather than tabs. +- minor change to the max target calcuation to make it more accurate. +- For option 17 (show expander route tables) added a check for whether + PHY_VACANT was returned and if so print a 'V' instead of a routing + attribute since the actual routing attribute is not available. +- For option 67/100 (Dump all port state) added a check for config pages + returning more than 255 DWORDs. For such config pages, truncate the output + and print a message indicating that the output was truncated. +- miscellaneous formatting and minor display bug fixes +- changed the DOS/EFI MPT driver to register as a BIOS rather than HOST + driver for SAS2 HBAs. This causes the HBA firmware to handle device + registration and events without help from the driver. This change allows + for things like RAID volume re-sync to restart after a drive hotplug. + +----------------------------------------------------------------------------- + +Changes for 1.63: + +- All tabs in the source code have been changed to spaces. For this release + only, *_tabified.c variants of the source code are provided which include + all of the changes since 1.62 except for the tab->space conversion. +- Moved the Solaris binaries to a single directory. lsiutil.sparc is the + SPARC binary and lsiutil.i386 is the X86 binary. +- updated MPI headers to 2.00.11. +- Added support for the magic number change in the SAS gen2 Linux driver. + This means that version mpt2sas-01.255.01.00 or later is required to + work with this release of lsiutil. +- Fixed display current events (option 40) for gen2 SAS HBAs. +- Added new menu option 58 (SAS only) for Alta diagnostics. +- Added support for the lsi_gen2 Windows XP driver. +- Added support for the mpt_sas Solaris gen2 SAS driver. +- Added support in the expander firmware download option to accept 'all' as + a valid value when prompted for the expander to operate on. This will + cause the image to be sent and verified for all expanders in the list. +- Added support in the expander firmware download option to poll for interim + completion statuses when download microcode used as well as include + the additional status if the update fails. +- Added two new expert mode options to the diagnostics menu, + 'Display expander log entries' (option 25), and 'Clear (erase) expander + log entries' (option 26). Currently only gen1 (Yeti) expanders are supported. +- For all SMP requests, now setting 'Allocated Response Length' to 0xFF. +- Added support for the 'Show Volumes' and 'Get Volume State' options for SAS + gen2 IR to display inactive volume reason. +- Fixed a bug when printing Incompatible and Offline Reasons for gen2 SAS IR + phys disks. +- Made changes to routines that use RaidConfigPage0. Fixes segmentation fault + when activating a foreign volume with gen2 SAS HBAs. +- Added a retry mechanism when config page requests return MPI_IOCSTATUS_BUSY. +- Fixed a bug in displaying log entries (option 35) in which one DWORD was + not being displayed. +- In diagnostic menu option 2 (WriteBuffer/ReadBuffer/Compare Test) added + support for all the same patterns that the Write/Read/Compare test (option 4) + supports and added expected/actual printing when miscompares found. +- Fix handling of devices with T10 DIF (EEDP) enabled. +- In doIdentify, don't use the "actual image length" returned by the SCSI + firmware since it is not trustworthy. +- In doDisplayLoggedInDevices, if the port device is not returned when reading + device pages, use the port page to provide the missing information. +- When displaying OS device names under Linux, add use of O_NONBLOCK to the + opens() to avoids hanging in some situations. +- For option 56 (Read/write expander memory), added support for the x12 + expander via support for the ring format LSI SMP. +----------------------------------------------------------------------------- + +Changes for 1.62: + +- Updated to use MPI2 header files 2.0.0.10. This means the minimum + requirements for using this version of lsiutil with gen2 SAS HBAs is + firmware version 00.250.16.00, Windows driver 2.00.00.17 and Linux driver + 00.255.05.00. +- Added support for diagnostic trace buffers (option 43) for gen2 SAS HBAs. +- Fixed a bug with displaying log entries (option 35) for gen2 SAS HBAs. +- Added three new RAID actions (option 21) for gen2 HBAs. Volume consistency + check, Stop volume consistency check, and Online Capacity Expansion. These + are RAID Action menu options 34, 35, and 36 respectively. +- Added support for in-band resetting of bobcat (gen2 SAS) expanders (menu + option 20, sub-option 98). +- For gen2 IR changed coerced size to come from firmware. +- For gen2 changed port->maxTargets to be based on MaxDevhandle+MaxVolumes + rather than MaxTargets. +- Fixed a bug with processing VPD files under EFI. The sscanf() routine in + helper.c was missing support for %c. + +----------------------------------------------------------------------------- + +Changes for 1.61: + +- Update the data structures for bus/target to devhandle mapping to use 32-bit + target and bus IDs. This affects SAS gen2 driver interaction. This release + requires at least version 2.0.0.16 of the LSI_SAS2 Windows driver and version + 00.00.02.19 of the Linux mpt2sas driver. +- Increase timeout for task management requests from 30 to 60 seconds +- Fix a bug that could lead to attempting to double close the log file and + cause a call to free() to fail. +- Fix option 18 for SAS gen2 HBAS (changing the wwn). +- Fix link speed detection for SAS gen2. +- Fixed bug for SAS gen2 that could cause lsiutil to send requests with a + devhandle of 0xffff. + +----------------------------------------------------------------------------- + +Changes for 1.60: + +- fix bug in doDeleteVolume2 for setting the volume dev handle in the RAID + action request. +- Add option to use default settings on volume creation. +- Changed default stripe size to 128K +- fixed a build error that occurred if REGISTER_ACCESS was set to 0 at + compile time. + +----------------------------------------------------------------------------- + +Changes for 1.59: + +- Add code that determines BIOS/FCode compatibility for first MPI 2.0 chips. +- Add "Dump PCI config space". +- Modify code that allows changing SAS persistent entries, to handle changing + a set of mappings from one EnclosureId to another EnclosureId. +- Enhance display of expander routing tables to accommodate the SAS 2.0 + committee changing the opcode for REPORT EXPANDER ROUTE TABLE LIST from + 17h to 22h. +- After displaying diagnostic pages, don't ask about making changes except for + page numbers that are known to be writable. +- Make modifications to the RAID volume creation code to take drive minimums + from config pages, rather than hard-coding them. Also, allow selecting a + stripe size for any volume type except for mirrored (RAID1) volumes. +- Add ability to send QUERY TASK and ABORT TASK to the "Reset target" routine; + this is not the ideal place to put them, but it's the best of the current + alternatives. No allowance is made for specifying the identity of the task + to be queried or aborted; the intent is that these will be used merely to + verify that such requests can be issued (not that they'll be successful). +- Add some missing config pages to "Dump all port state". +- After resetting the chip (DOS/EFI), wait 20 milliseconds before making any + chip accesses, per the MPT specification. + +----------------------------------------------------------------------------- + +Changes for 1.58: + +- Add option 66, "Show SAS discovery errors". +- Fix bug introduced in 1.57 that broke option 13 for SAS. +- Fix bug introduced in 1.56 that made diagnostic buffer actions appear to + fail for Windows, when in fact they had actually succeeded. +- Fix options 8, 13, 16, 18, 33, 35, 44, 68, 80, and 81, to accommodate + differences between MPI 1.x and MPI 2.0 (the new link speed of 6.0 Gbps + being the most prominent one). +- Modify expander firmware download to allow boot records (BufferID 10) to + be headerless. If a header is needed (mode 2), but is not present, add it. + If a header is not needed (mode 6), but is present, remove it. Also fix + verification code to be more robust. +- Fix MPI 2.0 bug that caused duplicate devices to be shown on Windows during + a device scan. + +----------------------------------------------------------------------------- + +Changes for 1.57: + +- Implement RAID actions for MPI 2.0, and implement "Delete hot spare". +- Add Linux support for MPI 2.0. +- Modify NVDATA concatenation code for latest MPI 2.0 firmware changes. +- When downloading expander firmware, if mode is 2, use Write Buffer, but if + mode is 6 or 7, use SES Download Microcode. Before downloading, verify the + image for Buffer IDs 0, 2, and 10. +- For SAS, add "Force full discovery". +- Add "Identify FLASH device". +- Fix more endian problems, by adding code that allows the compiler to detect + them automatically. +- Skip verification after firmware download when the special bridge firmware + (1.18.99) is being used. +- Fix the multi-path detection code (used when creating volumes), which was + reading enclosure pages incorrectly. +- Fix the code that handles metadata size, to use ManufacturingPage4 instead + of IOCPage6 (the former can be modified, while the latter cannot). +- After reading diagnostic pages, allow the data to be modified and the page + written back. + +----------------------------------------------------------------------------- + +Changes for 1.56: + +- Implement -k flag to suppress the "select a device" mechanism for many + diagnostic functions, and instead allow directly entering bus and target + numbers. +- Fix the -h (help) display, which got broken when paging was implemented. +- Add some routines to help debug expanders (read/write expander memory, + read/write expander ISTWI devices, expander firmware download, expander + reset). +- Implement all of the diagnostic buffer actions for Solaris (a new driver is + required). Also, when any diagnostic buffer action fails, display detailed + information if it's available. +- Don't try to verify a firmware download for SAS if only a bootloader image + is active; the required "firmware upload" support is not implemented. +- Fix endian issues in various places. +- Fix the code that was trying to detect multi-pathed disks when creating RAID + volumes; it was not correctly determining whether two enclosures were in fact + the same enclosure. +- In the "Log Sense" and "Diagnostic Page" tests, make the buffer larger, and + check for the device returning more data than requested. +- When working with RAID physical disks, consistently use the physical disk + count that is in IOCPage3, vs. the one in IOCPage2. +- Add path information to the display of RAID physical disks, whenever there + is more than one path. +- Enhance "Scan for devices" to also show (hidden) RAID physical disks. +- Fix the Solaris code that determines device names, to handle SCSI Enclosure + Services (SES) devices, and to handle SAS disks with long GUID-based names. +- For "Send SMP request", if the handle entered is 0, prompt for SAS WWID and + physical port to be entered manually. +- Fix bug in "Send SCSI CDB" that caused loss of detailed failure information + (including SCSI status and, if there was a Check Condition, any sense data). +- More MPI 2.0 work: add a real list of supported devices, fix the expander + routing table display code, fix the SATA Clear Affiliation code, fix SCSI I/O + reply handling to correctly obtain sense data. +- Fix a bug in the EFI implementation of scanf(): %n did not work correctly. + +----------------------------------------------------------------------------- + +Changes for 1.55: + +- Extend paged output in menus to cover all output in all circumstances. +- Make the maximum number of devices shown in menus compile-time configurable, + with the default remaining at 99. +- Add the ability to turn off MPT register access at compile time, since this + causes crashes on some Linux standalone platforms. +- Accommodate more differences between MPI 1.5 and MPI 2.0 (in SCSI I/O replies + and event handling). Also, for MPI 2.0, use the BTDH IOCTL to get the driver + mapping between bus/target and device handle. +- When the -g flag is used, ask if the fwdiagtool header should be added when + doing diagnostic buffer reads. +- Have options 15, 17, and 20 automatically bring the port online under DOS and + EFI. +- Expand the PCI information printed to include the segment number. +- Add verification after firmware downloads (read the image back, and compare + with what was written). +- When creating RAID volumes, correctly enforce rules about mixing SAS and + SATA drives, and SSD and non-SSD drives. Also, use the metadata size that + is specified in IOC Page 6. +- Fix code that implements setting the volume name (string length check was + wrong, and volume addressing was wrong). +- When deleting a the last volume, delete any hot spares that remain; otherwise + those physical disks are left stranded. +- For Solaris, use an IOCTL to get the driver name and version. Use that same + IOCTL to get PCI information; only if that fails should the "reg" property be + used to get PCI information. +- When dumping config pages, dump SAS Expander Page 1 correctly (there is one + page per expander phy), and fix its name (it was called "SASDevicePage1"!). +- Implement the new changes for MPI 2.0 NVDATA concatenation. Add IOC Page 8, + BIOS Page 4, and Driver Mapping Page 0. +- Add MPI 2.0 support to the DOS/EFI driver. +- Add "Read Buffer (for firmware upload)" to allow reading back device or + expander firmware and saving into a file. + +----------------------------------------------------------------------------- + +Changes for 1.54: + +- Fix concatenation bug that caused invalid SAS firmware files to be generated +- Catch error if no file name is entered for option 15, suboption 8 +- Add ability to issue product-specific SAS IO Unit Control and Diag Data + Upload requests +- When modifying SAS IO Unit settings, if "all phys" is selected, the default + should be to preserve existing settings per phy, rather than overwrite with + new settings +- Handle self-configuring expanders when displaying expander route tables +- When setting a volume name, use the new RAID action +- Change the display of PCI location information to include the segment number +- Allow SMP requests and responses to be up to 1024 bytes (per the SAS spec) +- Fix problem where the maximum target allowed is less than expected, so some + targets can be missed in a scan +- Add preliminary parsing of MPI 2.0 NVDATA + +----------------------------------------------------------------------------- + +Changes for 1.53: + +- Add initial support for MPI 2.0 +- Add -q switch, to query files for version information +- Add -g switch, to guarantee asking of questions that otherwise would be + suppressed (such as the bus number, when there's only one bus); this makes + it easier to script lsiutil from Perl +- Rework the way that ports are found under Solaris, to eliminate what are + sometimes lengthy delays waiting for prtconf to run -- the new code uses + the devinfo library to directly walk the device tree +- Fix memory leaks when using the -j switch (ports not selected were not + being closed), and when using options 18 or 44 +- Add "Set SAS phy offline/online" +- Add ability to save persistent mappings to a file, then later restore them +- Add "Diagnostic Page Test", which reads any SCSI diagnostic pages +- Add code to enable or disable the read or write caches in SCSI devices +- Fix incomplete implementation of "Force firmware to fault (with C0FFEE)" +- Add verification of internal FCode checksum +- Add verification of PCIR image length +- Extend "Inject/Repair media error" test so that it works for SATA devices +- When downloading drive firmware, set default mode to 5 for SATA devices +- Fix bug in "Show physical disks" that assumed physdisk numbers were dense +- Detect multi-pathed disks when creating RAID volumes, and suppress their + inclusion in the device list +- Add code to allow binary files to be written when dumping chip locations + (the -g switch must be used for force the question) +- Fix an endian bug when dumping chip locations below 0x10000000 +- Modified SAS phy/link reset code to ask for a device handle, so that remote + phys or links (i.e., on expanders) can be reset +- For DOS/EFI, avoid issuing Port Enable if possible, since that request can + take a long time to complete +- Change method of checking for "context reply" after SCSI request passthrough + under Windows, from looking for a specific MsgContext value, to looking for + the reply's MsgLength being zero +- Add retries under Linux if an IOCTL fails with EAGAIN +- Increase size of DOS/EFI scratch buffer to 1 MB (from 64 KB) to accommodate + large drive firmware downloads +- When exiting on DOS/EFI, don't reset a port that was not brought online + +----------------------------------------------------------------------------- + +Changes for 1.52: + +- Make changes required to allow an EBC version for EFI +- Make changes required to allow native 64-bit IA64 and AMD64 versions + for Windows +- Modify Linux workarounds for IOC_INIT (needed to write Manufacturing + config pages) +- For Solaris, modify findPorts() to first use "prtconf -D", and then as + a fallback, use /etc/path_to_inst, so that working ports can be more + accurately identified +- Fix several big-endian bugs in the RAID-related options +- Don't print a stripe size for IM volumes (it's not valid like it is for + IME and IS volumes) +- Add support for a few new FC Management toolbox functions +- Rewrite getOsDeviceName() for Solaris, so that FCA devices are handled + as well as SCSA devices +- Fix an off-by-one message when complaining about incorrect VPD end tags +- Enhance SAS NVDATA parser to handle version 2D +- Support NPIV for FC by adding a -v switch (to identify which virtual + port to masquerade as) + +----------------------------------------------------------------------------- + +Changes for 1.51: + +- Add date/time stamp when logging to lsiutil.log +- Add "SEP (SCSI Enclosure Processor) Test" +- Add "FC management tools" +- Add "Force firmware to fault (with C0FFEE)" for SAS +- Add "Report LUNs Test" +- Fix dumping of memory regions to work with FC919/FC929 +- Increase chunk size for firmware download/upload, for DOS only +- Allow Sun's mpt driver to work (for Solaris) +- Fix endian bugs in firmware download when checking for 1MB/2MB issues +- Dump enclosure pages when displaying attached devices for SAS +- Add checks for maximum physical disks in a volume +- When creating a volume, allow user to specify "no initial sync" +- Display FC WWNs and SAS WWID as part of -i (aka option 68) +- Add FC949E A2, 53C1030T A2, SAS1064E B3, SAS1068E B3, and 1078 C2 chips + +----------------------------------------------------------------------------- + +Changes for 1.50: + +- Rearrange some source files to allow easier building on Windows + and Solaris +- Add ability to set individual bits, bytes, words, when modifying config + pages (e.g., when prompted for a value, type "bit3=1", or "bits7:4=2", + or "byte2=17") +- Add "Show expander routing tables" +- Add "Disable/Enable drive firmware update mode" to RAID actions +- Add "Display Log entries" and "Clear (erase) Log entries" +- Add "Upload FLASH section" +- Add "Display version information" +- Add "Display/Program chip VPD information" +- Add back deleting of persistent entries for SAS, and add "Change + Bus/Target of a existing mapping" +- Add code to firmware download that handles the SAS phase 8 to phase 8 + bridge firmware image (version 1.18.99) +- When erasing the BIOS, fill with FF rather than 00 to match the FLASH + erase pattern +- Add ability to control booting under EFI for "Change FC Port settings" +- Modify "Change WWID" code to allow for variable-sized config page +- Under DOS or EFI, after any RAID action, sleep for 5 seconds to allow + drive metadata to be updated (if necessary) +- Use the Memory Move toolbox tool to allow "Dump chip memory regions" to + be able to dump tightly-couple memory for SAS and FC +- Beef up the display of SAS control settings in "Dump all port state" +- Display IOCLogInfo value for any RAID action request that fails +- Enhance concatenation to handle NVDATA versions 25, 28, 29, and 2B +- Properly return Check Condition Sense Data under DOS and EFI +- Switch DOS code to use memory space instead of I/O space, whenever + possible + +----------------------------------------------------------------------------- + +Changes for 1.49: + +- Fix build issues with latest SLES10/RHEL5 drivers +- Add -j to allow selecting just FC, SCSI or SAS ports +- Add doWaitForResync (RAID action) +- Add doRemoveSasDevice +- Fix -b and -r to obey -p, -0, and -1 +- Fix port and driver naming under Windows StorPort drivers +- Add 1 MB to 2 MB migration code for SAS (phase 9), DOS and EFI only +- Fix doCreateVolume to obey volume member limits +- Remove all tabs from output, replace with spaces +- Add parsing of NVDATA version 28 + +----------------------------------------------------------------------------- + +Changes for 1.48: + +- Add -w, -ww, and -www flags to capture debug output +- Add -x flag to concatenate SAS firmware and NVDATA files +- Switch from using PortType as a selector, to ProductIdType +- For DOS and EFI, make sure port is ready for each new option +- For ports stuck in reset, don't prompt for a firmware file unless and + until the port is selected +- For EFI, do a firmware upload to handle FWDLB cases (no FLASH) +- Add paged menu mode +- Move "Beacon on/off" to be FC-specific +- Add "Erase non-volatile adapter storage" +- Add "Diagnostic Buffer actions" +- Add "Program manufacturing information" for FC and SAS +- Add "Set personal WWNN/WWPN" for FC +- Add "Send SCSI CDB" +- Remove most persistence actions for SAS, as they no longer are supported + by firmware +- Add "Inject/Repair media error" +- Add "Set/Clear write protect" +- When downloading SAS firmware, make sure the attached NVDATA is correct + for the port's board type +- Fix SAS firmware validity checking to correctly detect wrong chip type + and wrong chip revision +- Allow setting/clearing Native Command Queue Disable and SATA Write Cache + Disable for SAS +- Allow "Read/Write/Verify Logical Blocks" to touch individual volume + members, just like "Inject/Repair media error" +- Fix incorrect ordering of LBA High/Middle/Low parts in "Send SATA + request" +- Add dumping of VPD data (Manufacturing Page 1), if non-zero, to board + info display +- Fix incorrect defaulting of FC's HostSCSIID (15 is no longer correct) +- Fix EFI code to truncate files properly +- Fix EFI code to use I/O space properly, if required (1030/1030T) +- Fix DOS code to not enable chip interrupts (caused a hang while exiting + on some platforms) + +----------------------------------------------------------------------------- + +Changes for 1.47: + +- Add support for EFI +- Add a workaround for older Linux mptbase drivers (fix IOC_INIT failing) +- Add doWriteLogicalBlocks and doVerifyLogicalBlocks +- Add generic SATA passthrough +- Allow -b (showBoardInfo) in combination with any other arguments +- Increase range of Initiator Device Timeout value, by using the + supported scale factor (x16) if necessary +- Allow setting the Device Missing Report Delay and Device Missing + I/O Delay values +- Fix a bug in configuring wide ports +- Add support for RAID Volumes of size > 2 TB +- Add missing config pages to doPortStateDump (-d) + +----------------------------------------------------------------------------- + +Changes for 1.46: + +- Add -0 and -1 options, to skip IOC numbers 0 and 1, for certain + operations (so, lsiutil -1 99 would only reset each chip once) +- Enhance display to show IOC number (same as PCI function number) +- Check to see if the firmware is in Operational state before trying the + first MPT command, to avoid causing a chip reset if the firmware is in + Fault state (if so, option 99 will perform a chip reset, if desired) +- Fix code that obtains MPT register addresses for Linux (was broken for + some systems with 2.6 kernels) +- Fix code that displays operating system device names for Linux (was + displaying incorrect names for some SAS and FC devices whose SCSI + bus/target numbers were not equal to their MPT bus/target numbers) +- Move code that enables MPT register access inside the loops for options + 51 and 52, so that access continues to work even if the chip is reset +- Add display of IOCFactsReply and PortFactsReply to port state that is + dumped by -d, and only display FC Port Page 3 pages that are valid + +----------------------------------------------------------------------------- + +Changes for 1.45: + +- Fixed get2bytes/get3bytes/get4bytes macros to properly truncate +- Fixed formats for 64-bit integers when printed (Windows is different) +- Added doDriveFirmwareDownload +- Added doDisplaySfpPages +- Added doDefaultPhyRegsSettings +- Extended event displaying to Linux and Solaris +- Added some control over port configuration in doSasIoUnitSettings +- Reworked getOsDeviceName slightly for Linux and Solaris +- Fixed bug in doPortStateSummary which reversed Yes and No for + SSP Initiator Enabled and SSP Target Enabled displays +- Added support for FC949E A1 +- Fixed Linux version of doMptCommand to correctly gather Sense Data + +----------------------------------------------------------------------------- + +Changes for 1.44: + +- Upgrade to 1.05.13 MPI headers +- Add doReadLogicalBlocks and doDisplayOsDeviceNames +- Add EEDP support +- Add an optional duration to the monitor frequency (-m f,d) +- Add "reset port" option to all submenus too +- Don't send quiesce/unquiesce RAID actions to SAS IR (not supported) +- Don't coerce RAID volume size if it's small (less than 1 GB) +- Add SAS1068E B1 as a known device + +----------------------------------------------------------------------------- + +Changes for 1.43: + +- Add Clear ACA (option 24) +- Fix a Linux buffer overrun that caused only the first port to be + discovered for some architectures +- Fix ManufacturingPage2 checksum offset for FC949E +- Guard against divide-by-zero when displaying volume resync percent +- Prevent a target from being chosen twice when creating a volume +- Add the flag that deletes PhysDisks when deleting a Volume +- Fix a DOS bug (internal buffer corruption) by rearranging the order + of operations when starting a new command -- bring the chip online + first, before loading the scratch buffers +- Correctly set RequestDataLength to NOT include the CRC bytes, when + sending hand-built SMP Passthrough commands +- Add a hardware workaround for the FC949E to the Firmware Download Boot + code for DOS +- Fix Adapter Reset for SAS1078 (DOS only) + +----------------------------------------------------------------------------- + +Changes for 1.42: + +- Add Log Sense Test +- Add SATA SMART Read Test +- Add Create Hot Spare +- Add Send SMP Request +- Add support for the 1078 +- Change number of LUNs probed to 64 for FC and SAS (leave SCSI alone) +- In doFcPortSettings, preserve original HardALPA setting if user quits +- Fix endian issue when creating volumes (default settings were incorrect + for SPARC and PowerPC) +- Fix typo in doPhysDiskSettings that used the wrong Action value +- Ignore IOC Page 3 in doShowNonDefaultSettings +- Ignore LOG pages in doRestoreDefaultSettings +- Fix DOS MPT driver to not poll the Doorbell while DMA is active + +----------------------------------------------------------------------------- + +Changes for 1.41: + +- Fix build errors on some Linux systems +- Filter out bad "what" strings (any of the first 4 characters are bogus) +- Fix missing 50/51/52/53 from main menu on Linux systems +- Add checking for 1064 A3 SAS firmware images +- Use current config page data if non-volatile data is invalid +- Add "Read Default Write NVRAM" to "Test configuration page actions" +- Resolve SAS firmware hang by not reading LOG page types +- Remove IO Unit Page 3 from "Restore default settings" + +----------------------------------------------------------------------------- + +Changes for 1.40: + +- Added MPT and chip register access for Linux +- Added doShowNonDefaultSettings and doRestoreDefaultSettings +- Fixed commands to consistently check for errors +- Added check for overflow of volume size when creating a volume +- Fixed "free" calls in doDisplayCurrentEvents +- Added retries around Windows IOCTL calls, to handle BUSY status +- Added warning message if any Linux IOCTL call is rejected +- Added speed/width negotiation to DOS driver for SCSI +- Added a watchdog timer routine to DOS driver to catch faults +- Fixed firmware download boot for 929X in DOS driver + +----------------------------------------------------------------------------- + +Changes for 1.39: + +- Add DOS support +- Add 949E support +- Add MPT register access and chip register access +- Move diag_targets[99] from stack storage to global storage +- Add Read Block Limits (like Read Capacity but for tapes) +- Initialize memory after allocation, always +- When menu options are picked from -a, don't print the menu itself +- When showing current firmware version, print both hex and decimal +- Fix bug in displaying phy error counters that nearly always hid errors +- Allow 2-member IS volumes (previously, 2-member volumes were always IM) +- Zero errno (the last error that occurred) prior to each syscall +- Fixed bug that made "lsiutil -e" (or "lsiutil -u") just exit + +----------------------------------------------------------------------------- + +Changes for 1.38: + +- Update to latest header files, 1.05.10 +- Display chip rev as well as chip name +- Add Display Phy Counters and Clear Phy Counters +- Make display of firmware version be accurate, always +- Add Trigger Analyzer with Echo + +----------------------------------------------------------------------------- + +Changes for 1.37: + +- Fixed all mallocs that did not have frees +- Added Read Capacity and Mode Page tests +- Added -n (companion to -y) to answer questions automatically +- In Identify, print current running firmware version as well as FLASH + versions +- If mptscsih is not loaded, quit (from Scan for Devices) early +- Increase metadata size for SAS IR volumes + +----------------------------------------------------------------------------- + +Changes for 1.36: + +- Simplify menus using "expert mode", which is enabled with -e on the + command line, or by typing "e" at any menu prompt +- Add display of transfer statistics for FC (-m, for "monitor") +- Allow -h to print help even if no ports found +- Fix firmware download and config page reads for old versions of MPT (1.00) +- Allow easier erasing of BIOS/FCode images +- Add an explicit error message for Linux if a SCSI I/O fails due to the + mptscsih driver not being loaded + +----------------------------------------------------------------------------- + +Changes for 1.35: + +- Check for new Windows split-driver names (lsi_fc, lsi_scsi, lsi_sas) +- Display all "what" strings that are found +- Add SATA Clear Affiliation test +- Add ability to monitor current events (Linux only so far) + +----------------------------------------------------------------------------- + +Changes for 1.34: + +- Add -b option, which gets board info (from manufacturing config pages) +- Add SATA Identify Drive test +- Fix bug in -p where ranges didn't quite work right +- Add routine to get the length of a variable config page, and use it +- Add warning for trying to use an old FC929X firmware image on an FC929XL +- When setting FC devices persistent, set SCAN_ID and SCAN_LUNS flags too +- Add display of what phys are connected to what, in Display Attached Devices +- Remove all knowledge of EEDP for now + +----------------------------------------------------------------------------- + +Changes for 1.33: + +- On Linux, try "modprobe mptctl" and "mknod /dev/mptctl c 10 220" if + IOCTLs don't work +- Fix bug when manually setting SAS persistence +- Add additional checking to distinguish 929X from 929XL + +----------------------------------------------------------------------------- + +Changes for 1.32: + +- Added coercion of disk size when making an IR volume + +----------------------------------------------------------------------------- + +Changes for 1.31: + +- Added -a to allow arguments to be entered on the command line +- Added Beacon on/off +- Detected Sun FCode for 1030 (and hopefully for 1064 too) +- Fixed bug when manually entering more than one SAS persistent address +- Fixed bug when underrun occurs but some data is transferred (NOT an error!) + diff --git a/source/Makefile_Linux b/source/Makefile_Linux new file mode 100755 index 0000000..543d9d4 --- /dev/null +++ b/source/Makefile_Linux @@ -0,0 +1,3 @@ +lsiutil: lsiutil.c + gcc -Wall -O lsiutil.c -o lsiutil + cp -p lsiutil /usr/bin diff --git a/source/Makefile_Solaris b/source/Makefile_Solaris new file mode 100755 index 0000000..06b60fa --- /dev/null +++ b/source/Makefile_Solaris @@ -0,0 +1,3 @@ +lsiutil: lsiutil.c + gcc -Wall -O lsiutil.c -o lsiutil -D__sparc__ -ldevinfo + cp -p lsiutil /usr/bin diff --git a/source/Makefile_Windows b/source/Makefile_Windows new file mode 100755 index 0000000..d724a25 --- /dev/null +++ b/source/Makefile_Windows @@ -0,0 +1,2 @@ +lsiutil: lsiutil.c + gcc -Wall -O lsiutil.c -o lsiutil.exe -DWIN32 diff --git a/source/getopt.c b/source/getopt.c new file mode 100755 index 0000000..5fefd36 --- /dev/null +++ b/source/getopt.c @@ -0,0 +1,108 @@ +/*************************************************************************** + * * + * Copyright 2012 LSI Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Corporation. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Corporation. * + * * + *************************************************************************** +*/ +#include "inc/getopt.h" + +/* This function gets the next option letter from the console input. + It is supposed to be equivalent to the UNIX getopt function. + Options are preceeded by a dash, currently a slash is not allowed. + Multiple options after one dash are valid, and arguments after + the option with a colon between are supported.*/ + +/* Common varibles. */ + +int opterr = 1, /* error messages printed? default: yes */ + optind = 1, /* index into parent argv vector */ + optopt; /* character checked for validity */ + +char *optarg; /* argument associated with option */ + +#define EMSG "" + +char *progname; /* may also be defined elsewhere */ + + +static void +error(char *pch) /* error message routine */ +{ + if (!opterr) + return; /* without printing */ + + fprintf(stderr, "%s: %s: %c\n", + ((NULL != progname) ? progname : "getopt"), pch, optopt); +} + + +int +getopt(int argc, char *argv[], char *ostr) +{ + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + + progname = argv[0]; + + if (!*place) + { /* update scanning pointer */ + if (optind >= argc || + (*(place = argv[optind]) != '-' && + *(place = argv[optind]) != '/') || + !*++place) + { + return EOF; + } + if (*place == '-') + { /* found "--"; ignore; (end of options) */ + ++optind; + return EOF; + } + } + + /* option letter okay? */ + optopt = (int)*place; + ++place; + oli = strchr(ostr, optopt); + if ((optopt == (int)':') || + !(oli = strchr(ostr, optopt))) + { + if (!*place) + ++optind; + + error("illegal option"); + return BADCH; + } + + if (*++oli != ':') /* Check for argument after option */ + { /* don't need argument */ + optarg = NULL; + if (!*place) + ++optind; + } + else + { /* need an argument */ + if (*place) + optarg = place; /* no white space */ + else + if (argc <= ++optind) + { /* no arg */ + place = EMSG; + error("option requires an argument"); + return BADCH; + } + else + optarg = argv[optind]; /* white space */ + place = EMSG; + ++optind; + } + return optopt; /* return option letter */ +} + +/* vi: set sw=4 ts=4 sts=4 et :iv */ diff --git a/source/helper.c b/source/helper.c new file mode 100755 index 0000000..b84b852 --- /dev/null +++ b/source/helper.c @@ -0,0 +1,1241 @@ +/*************************************************************************** + * * + * Copyright 2012 LSI Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Corporation. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Corporation. * + * * + *************************************************************************** +*/ +/* + * helper -- EFI helper routines commonly found in a CRTL + * + * Written by Stephen F. Shirron, September 15, 2006 + */ + +EFI_STATUS last_efi_status; +int errno; +int optind; +char *optarg; + +EFI_HANDLE gImageHandle; + +EFI_LOADED_IMAGE *gLoadedImage; + +EFI_EVENT gSleepEvent; + +size_t strlen(const char *s) +{ + const char *c = s; + + while (*c++); + + return c - s - 1; +} + +char *strcpy(char *s1, const char *s2) +{ + char *c1 = s1; + const char *c2 = s2; + + while (*c1++ = *c2++); + + return s1; +} + +char *strncpy(char *s1, const char *s2, size_t n) +{ + unsigned char *c1 = s1; + const char *c2 = s2; + size_t t = 0; + + while (t++ < n && (*c1++ = *c2++)); + while (t++ < n) *c1++ = 0; + + return s1; +} + +char *strcat(char *s1, const char *s2) +{ + char *c1 = s1; + const char *c2 = s2; + + while (*c1) c1++; + while (*c1++ = *c2++); + + return s1; +} + +char *strncat(char *s1, const char *s2, size_t n) +{ + char *c1 = s1; + const char *c2 = s2; + size_t t; + + while (*c1) c1++; + t = 0; + while (t++ < n && (*c1++ = *c2++)); + if (t >= n && *(c1-1)) *c1 = 0; + + return s1; +} + +char *strchr(const char *s1, int t) +{ + while (*s1) if (*s1++ == t) return (char *)--s1; + return NULL; +} + +int strcmp(const char *s1, const char *s2) +{ + while (*s1 && *s1 == *s2) s1++, s2++; + if (*s1 < *s2) return -1; + if (*s1 > *s2) return 1; + return 0; +} + +int strncmp(const char *s1, const char *s2, size_t n) +{ + while (n && *s1 && *s1 == *s2) n--, s1++, s2++; + if (n == 0) return 0; + if (*s1 < *s2) return -1; + if (*s1 > *s2) return 1; + return 0; +} + +int toupper(int c) +{ + if (c >= 'a' && c <= 'z') return c - 'a' + 'A'; + return c; +} + +int tolower(int c) +{ + if (c >= 'A' && c <= 'Z') return c - 'A' + 'a'; + return c; +} + +int strcasecmp(const char *s1, const char *s2) +{ + while (*s1 && tolower(*s1) == tolower(*s2)) s1++, s2++; + if (tolower(*s1) < tolower(*s2)) return -1; + if (tolower(*s1) > tolower(*s2)) return 1; + return 0; +} + +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + while (n && *s1 && tolower(*s1) == tolower(*s2)) n--, s1++, s2++; + if (n == 0) return 0; + if (tolower(*s1) < tolower(*s2)) return -1; + if (tolower(*s1) > tolower(*s2)) return 1; + return 0; +} + +void *memset(void *s, int t, size_t n) +{ + char *c = s; + + while (n) n--, *c++ = t; + return s; +} + +void *memcpy(void *s2, const void *s1, size_t n) +{ + const char *c1 = s1; + char *c2 = s2; + + while (n) n--, *c2++ = *c1++; + return s2; +} + +int memcmp(const void *s1, const void *s2, size_t n) +{ + const char *c1 = s1; + const char *c2 = s2; + + while (n && *c1 == *c2) n--, c1++, c2++; + if (n == 0) return 0; + if (*c1 < *c2) return -1; + if (*c1 > *c2) return 1; + return 0; +} + +void bzero(void *s, size_t n) +{ + char *c = s; + + while (n) + { + *c++ = 0; + n--; + } +} + +void bcopy(const void *s1, void *s2, size_t n) +{ + const char *c1 = s1; + char *c2 = s2; + + while (n) + { + *c2++ = *c1++; + n--; + } +} + +int isdigit(int c) +{ + if (c >= '0' && c <= '9') return 1; + return 0; +} + +int isxdigit(int c) +{ + if (c >= '0' && c <= '9') return 1; + if (c >= 'a' && c <= 'f') return 1; + if (c >= 'A' && c <= 'F') return 1; + return 0; +} + +int isalpha(int c) +{ + if (c >= 'a' && c <= 'z') return 1; + if (c >= 'A' && c <= 'Z') return 1; + return 0; +} + +int isalnum(int c) +{ + if (c >= '0' && c <= '9') return 1; + if (c >= 'a' && c <= 'z') return 1; + if (c >= 'A' && c <= 'Z') return 1; + return 0; +} + +int isprint(int c) +{ + if (c >= ' ' && c <= '~') return 1; + return 0; +} + +void *malloc(size_t size) +{ + return AllocatePool(size); +} + +void *realloc(void *oldp, size_t size) +{ + void *newp = malloc(size); + + memcpy(newp, oldp, size); + + free(oldp); + + return newp; +} + +void free(void *p) +{ + FreePool(p); +} + +static void convert_unicode_ascii(const CHAR16 *s1, char *s2, int n) +{ + int i; + char c; + + for (i = 0; i < n; i++) + { + c = (char)*s1++; + *s2++ = c; + + if (c == 0) + break; + } +} + +static int convert_dtoi(const char *s, int *r, int w) +{ + int n = 0; + char c; + + *r = 0; + while (isdigit(c = *s++)) + { + *r *= 10; + *r += c - '0'; + n++; + if (n == w) + return n; + } + + return n; +} + +static int convert_xtoi(const char *s, int *r, int w) +{ + int n = 0; + char c; + + *r = 0; + while (isxdigit(c = *s++)) + { + *r *= 16; + if (isdigit(c)) + *r += c - '0'; + else + *r += tolower(c) - 'a' + 10; + n++; + if (n == w) + return n; + } + + return n; +} + +static int convert_itod(char *s, int64_t r) +{ + char c; + char buffer[32]; + int i; + int n = 0; + int negative = 0; + + if (r < 0) + { + r = -r; + *s++ = '-'; + negative = 1; + } + + do + { + c = (char)(r % 10); + r /= 10; + buffer[n] = c + '0'; + n++; + } + while (r); + + for (i = 0; i < n; i++) + s[i] = buffer[n - i - 1]; + + s[n] = 0; + + return n + negative; +} + +static int convert_itox(char *s, uint64_t r) +{ + char c; + char buffer[32]; + int i; + int n = 0; + uint64_t r0 = r; + + do + { + c = (char)(r % 16); + r /= 16; + if (c < 10) + buffer[n] = c + '0'; + else + buffer[n] = c + 'a' - 10; + n++; + } + while (r); + + for (i = 0; i < n; i++) + s[i] = buffer[n - i - 1]; + + s[n] = 0; + + return n; +} + +char *fgets(char *s, int size, FILE *stream) +{ + CHAR16 buffer[256]; + + if (stream == stdin) + { + Input(NULL, buffer, sizeof buffer / 2); + convert_unicode_ascii(buffer, s, size); + APrint("\n"); + + return s; + } + + printf("fgets from a file not implemented yet!\n"); + + return NULL; +} + +int sscanf(const char *s, const char *format, ...) +{ + va_list args; + char c; + int n = 0; + int w; + char *as; + int *ad; + int *ax; + int t; + const char *b; + + va_start(args, format); + + b = s; + while ((c = *format++)) + { + while (*s == ' ') + *s++; + if (c == '%') + { + c = *format++; + w = 0; + if (isdigit(c)) + { + format += convert_dtoi(--format, &w, 0); + c = *format++; + } + if (!c) + break; + switch (c) + { + case 's': + if (!*s) + break; + as = va_arg(args, char *); + while ((c = *s)) + { + s++; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + break; + *as++ = c; + } + *as = 0; + n++; + break; + case 'c': + if (!*s) + break; + as = va_arg(args, char *); + *as = *s++; + n++; + break; + case 'd': + if (!*s) + break; + ad = va_arg(args, int *); + t = convert_dtoi(s, ad, w); + if (t) + { + s += t; + n++; + } + break; + case 'x': + if (!*s) + break; + ax = va_arg(args, int *); + t = convert_xtoi(s, ax, w); + if (t) + { + s += t; + n++; + } + break; + case 'n': + ad = va_arg(args, int *); + *ad = (int)(s - b); + break; + } + } + else if (c != ' ') + { + if (*s++ != c) + break; + } + } + + va_end(args); + + return n; +} + +int vsprintf(char *s1, const char *format, va_list args) +{ + char c; + char *s; + char s2[256]; + char b[32]; + int len; + int n = 0; + int t = 0; + int i; + int w; + char ac; + char *as; + int64_t ad; + int64_t ax; +#if !EFIEBC + double af; +#endif + int left; + char pad; + int minw; + int maxw; + int longint; + + if (!s1) + s = s2; + else + s = s1; + + while ((c = *format++)) + { + if (c == '%') + { + c = *format++; + left = 0; + pad = ' '; + minw = 1; + maxw = 100; + longint = 0; + if (c == '-') + { + left = 1; + c = *format++; + } + if (c == '0') + { + pad = '0'; + c = *format++; + } + if (isdigit(c)) + { + format += convert_dtoi(--format, &minw, 0); + c = *format++; + } + if (c == '.') + { + c = *format++; + if (isdigit(c)) + { + format += convert_dtoi(--format, &maxw, 0); + c = *format++; + } + } + if (c == 'l') + { + c = *format++; + if (c == 'l') + c = *format++; + longint = 1; + } + if (!c) + break; + switch (c) + { + case 'c': + ac = (char)va_arg(args, int); + b[0] = ac; + b[1] = 0; + as = b; + break; + case 's': + as = va_arg(args, char *); + break; + case 'd': + if (longint) + ad = (int64_t)va_arg(args, int64_t); + else + ad = (int)va_arg(args, int); + convert_itod(b, ad); + as = b; + break; + case 'x': + if (longint) + ax = (uint64_t)va_arg(args, uint64_t); + else + ax = (unsigned int)va_arg(args, unsigned int); + convert_itox(b, ax); + as = b; + break; + case 'X': + if (longint) + ax = (uint64_t)va_arg(args, uint64_t); + else + ax = (unsigned int)va_arg(args, unsigned int); + convert_itox(b, ax); + for (i = 0; i < (int)strlen(b); i++) + b[i] = toupper(b[i]); + as = b; + break; + case 'p': + ax = (uint64_t)va_arg(args, void *); + convert_itox(b, ax); + as = b; + break; +#if !EFIEBC + case 'f': + af = (double)va_arg(args, double); + for (i = 0, ax = 1; i < maxw; i++, ax *= 10); + ad = (int64_t)(af * ax + 0.5); + convert_itod(b, ad); + if (maxw) + { + len = (int)strlen(b); + if (len < maxw + 1) + { + for (i = maxw + 1; i > maxw - len; i--) + b[i] = b[i-maxw-1+len]; + for (i = 0; i < maxw + 1 - len; i++) + b[i] = '0'; + len = maxw + 1; + } + for (i = len + 1; i > len - maxw; i--) + b[i] = b[i-1]; + b[i] = '.'; + } + as = b; + maxw = 100; + break; +#endif + default: + s[n++] = c; + as = NULL; + minw = 0; + break; + } + if (minw) + { + len = (int)strlen(as); + if (as != b) + { + if (len > maxw) + len = maxw; + } + w = minw - len; + if (!left && w > 0) + { + memset(s + n, pad, w); + n += w; + } + memcpy(s + n, as, len); + n += len; + if (left && w > 0) + { + memset(s + n, pad, w); + n += w; + } + } + } + else + { + s[n++] = c; + } + if (c == '\n' && !s1) + { + s[n] = 0; + t += n; + + if (n) + APrint("%a", s); + + n = 0; + } + } + + s[n] = 0; + t += n; + + if (n && !s1) + APrint("%a", s); + + return n; +} + +#if sfs +int printf(const char *format, ...) +{ + va_list args; + int n; + + va_start(args, format); + + n = vsprintf(NULL, format, args); + + va_end(args); + + return n; +} +#endif + +int sprintf(char *s, const char *format, ...) +{ + va_list args; + int n; + + va_start(args, format); + + n = vsprintf(s, format, args); + + va_end(args); + + return n; +} + +#define MAX_HANDLES 32 + +EFI_FILE_HANDLE gFileHandles[MAX_HANDLES]; + +FILE *fopen(const char *name, const char *mode) +{ + int flags; + int fd; + + if (strchr(mode, 'r')) + flags = O_RDONLY; + else if (strchr(mode, 'w')) + flags = O_RDWR | O_CREAT | O_TRUNC; + else if (strchr(mode, 'a')) + flags = O_RDWR | O_CREAT; + + fd = open(name, flags); + if (fd < 0) + return NULL; + + return (FILE *)fd; +} + +int fclose(FILE *stream) +{ + return close((int)stream); +} + +#if sfs +int fprintf(FILE *stream, const char *format, ...) +{ + va_list args; + char *s; + char s2[256]; + int n; + + if (stream == stdout || stream == stderr) + s = NULL; + else + s = s2; + + va_start(args, format); + + n = vsprintf(s, format, args); + + va_end(args); + + if (s) + n = write((int)stream, s, n); + + return n; +} +#endif + +int fflush(FILE *stream) +{ + EFI_FILE_HANDLE file; + EFI_STATUS status; + int fd = (int)stream; + + if (fd < 4) + return -1; + fd -= 4; + if (fd > MAX_HANDLES) + return -1; + + file = gFileHandles[fd]; + if (!file) + return -1; + + status = file->Flush(file); + if (EFI_ERROR(status)) + { + last_efi_status = status; + printf("Flush failed!\n"); + } + + return 0; +} + +int fputs(const char *s, FILE *stream) +{ + int n; + + n = (int)strlen(s); + if (stream == stdout || stream == stderr) + APrint("%a", s); + else + write((int)stream, s, n); + + return n; +} + +int fputc(int c, FILE *stream) +{ + if (stream == stdout || stream == stderr) + APrint("%c", (UINTN)c); + else + write((int)stream, (void *)&c, 1); + + return 1; +} + +int open(const char *name, int flags, ...) +{ + EFI_FILE_IO_INTERFACE *fileIo; + EFI_FILE_HANDLE root; + EFI_FILE_HANDLE file; + EFI_FILE_INFO *info; + EFI_GUID SimpleFileSystemProtocol = SIMPLE_FILE_SYSTEM_PROTOCOL; + EFI_STATUS status; + CHAR16 *path; + CHAR16 filename[128]; + UINTN i; + UINT64 mode; + int fd; + + for (fd = 0; fd < MAX_HANDLES; fd++) + if (!gFileHandles[fd]) + break; + if (fd == MAX_HANDLES) + return -1; + + if (*name == '.' || (isalnum(*name) && !strchr(name, ':'))) + { + path = DevicePathToStr(gLoadedImage->FilePath); + +// APrint("loaded image = <%s>\n", path); + + for (i = StrLen(path) - 1; i > 0; i--) + if (path[i] == L'/') + break; + // if the path contains "/." at the end, remove it + if (i >= 2 && path[i-2] == '/' && path[i-1] == '.') + i -= 2; + // if the path doesn't end with "\", add one + if (!(i >= 1 && path[i-1] == '\\')) + path[i++] = '\\'; + // throw away the rest of the string + path[i] = 0; + StrCpy(filename, path); + + FreePool(path); + } else + filename[0] = 0; + + for (i = StrLen(filename); *name; i++) + filename[i] = (CHAR16)*name++; + filename[i] = 0; + +// APrint("filename = <%s>\n", filename); + + status = BS->HandleProtocol(gLoadedImage->DeviceHandle, + &SimpleFileSystemProtocol, &fileIo); + if (EFI_ERROR(status)) + { + last_efi_status = status; + printf("HandleProtocol(SimpleFileSystem) failed!\n"); + return -1; + } + + status = fileIo->OpenVolume(fileIo, &root); + if (EFI_ERROR(status)) + { + last_efi_status = status; + printf("OpenVolume failed!\n"); + return -1; + } + + mode = EFI_FILE_MODE_READ; + if (flags & O_RDWR) + mode |= EFI_FILE_MODE_WRITE; + if (flags & O_CREAT) + mode |= EFI_FILE_MODE_CREATE; + + status = root->Open(root, &file, filename, mode, 0); + if (EFI_ERROR(status)) + { + last_efi_status = status; + APrint("Open of <%s> failed!\n", filename); + return -1; + } + + if (flags & O_CREAT) + { + info = LibFileInfo(file); + if (info) + { + if (flags & O_TRUNC) + { + info->FileSize = 0; + info->PhysicalSize = 0; + status = file->SetInfo(file, &GenericFileInfo, (UINTN)info->Size, info); + if (EFI_ERROR(status)) + { + last_efi_status = status; + APrint("SetInfo of <%s> failed!\n", filename); + } + } + else + { + status = file->SetPosition(file, info->FileSize); + if (EFI_ERROR(status)) + { + last_efi_status = status; + APrint("SetPosition of <%s> failed!\n", filename); + } + } + + FreePool(info); + } + } + + gFileHandles[fd] = file; + + fd += 4; + + return fd; +} + +int close(int fd) +{ + EFI_FILE_HANDLE file; + EFI_STATUS status; + + if (fd < 4) + return -1; + fd -= 4; + if (fd > MAX_HANDLES) + return -1; + + file = gFileHandles[fd]; + if (!file) + return -1; + + status = file->Close(file); + if (EFI_ERROR(status)) + { + last_efi_status = status; + printf("Close failed!\n"); + } + + return 0; +} + +ssize_t read(int fd, void *buf, size_t count) +{ + EFI_FILE_HANDLE file; + EFI_STATUS status; + UINTN size = count; + + if (fd < 4) + return -1; + fd -= 4; + if (fd > MAX_HANDLES) + return -1; + + file = gFileHandles[fd]; + if (!file) + return -1; + + status = file->Read(file, &size, buf); + if (EFI_ERROR(status)) + { + last_efi_status = status; + printf("Read failed!\n"); + return -1; + } + + return (ssize_t)size; +} + +ssize_t write(int fd, const void *buf, size_t count) +{ + EFI_FILE_HANDLE file; + EFI_STATUS status; + UINTN size = count; + + if (fd < 4) + return -1; + fd -= 4; + if (fd > MAX_HANDLES) + return -1; + + file = gFileHandles[fd]; + if (!file) + return -1; + + status = file->Write(file, &size, (void *)buf); + if (EFI_ERROR(status)) + { + last_efi_status = status; + printf("Write failed!\n"); + return -1; + } + + return (ssize_t)size; +} + +int fstat(int fd, struct stat *buf) +{ + EFI_FILE_HANDLE file; + EFI_FILE_INFO *info; + + if (fd < 4) + return -1; + fd -= 4; + if (fd > MAX_HANDLES) + return -1; + + file = gFileHandles[fd]; + if (!file) + return -1; + + info = LibFileInfo(file); + if (!info) + { + printf("GetInfo failed!\n"); + return -1; + } + + buf->st_size = (size_t)info->FileSize; + + FreePool(info); + + return 0; +} + +static int rand_seed = 152L; + +int rand(void) +{ + rand_seed = rand_seed * 69069L + 1; + + return ((rand_seed >> 16) + (rand_seed << 16)); +} + +void perror(const char *s) +{ + if (s && *s) + APrint("%a: ", s); + APrint("%r\n", last_efi_status); +} + +static int dpm[] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 +}; + +#ifndef DISABLE_TIMEOUTS +time_t time(time_t *t) +{ + EFI_TIME et; + time_t local_t; + int days; + + RT->GetTime(&et, NULL); + + days = dpm[et.Month - 1] + et.Day - 1; + + if (et.Year >= 1970) + { + days += (et.Year - 1970) * 365; + + // all modulo-4 years since 1970 are leap years, up until 2100 + days += (et.Year - 1969) / 4; + } + + local_t = ((days * 24 + et.Hour) * 60 + et.Minute) * 60 + et.Second; + if (t) + *t = local_t; + + return local_t; +} +#endif + +static const char *day_name[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +static const char *mon_name[] = { + "Mar", "Apr", "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec", "Jan", "Feb" +}; + +static const int days_per[12] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +static char ctime_result[26]; + +char *ctime(const time_t *seconds) +{ + int f, k, m, D, C, d; // going to use Zeller's Rule to derive the weekday + int days, leap, year, month, day, hours, mins, secs, t; + + days = *seconds / 86400; + t = days; + year = 1970; + // if it's already past 2004, get that out of the way quick + if (t >= 12418) + { + t -= 12418; + year += 34; + } + for (; ; year++) + { + // this simple rule is good until 2100 + leap = (year % 4) == 0; + if (t < 365 + leap) + break; + t -= 365 + leap; + } + month = 0; + // if it's already past June, get that out of the way quick + if (t >= 181 + leap) + { + t -= 181 + leap; + month += 6; + } + for (; ; month++) + { + if (t < days_per[month]) + break; + t -= days_per[month]; + if (month == 1) + { + if (t < leap) + break; + t -= leap; + } + } + day = t + 1; + t = *seconds - days * 86400; + hours = t / 3600; + t -= hours * 3600; + mins = t / 60; + t -= mins * 60; + secs = t; + + k = day; + m = month - 1; + D = year % 100; + C = year / 100; + + if (m < 1) + { + m += 12; + D -= 1; + } + + f = k + (13*m-1)/5 + D + D/4 + C/4 - 2*C; + + d = f % 7; + if (d < 0) + d += 7; + + sprintf(ctime_result, "%.3s %.3s%3d %02d:%02d:%02d %d\n", + day_name[d], mon_name[m-1], + day, hours, mins, secs, year); + + return ctime_result; +} + +VOID EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_TIME et; + EFI_STATUS status; + int i; + int argc; + char **argv; + int n; + + InitializeShellApplication(ImageHandle, SystemTable); + + gImageHandle = ImageHandle; + + status = BS->HandleProtocol(gImageHandle, &LoadedImageProtocol, &gLoadedImage); + if (EFI_ERROR(status)) + { + last_efi_status = status; + printf("HandleProtocol(LoadedImage) failed!\n"); + gLoadedImage = NULL; + } + + status = BS->CreateEvent(EVT_TIMER, 0, NULL, NULL, &gSleepEvent); + if (EFI_ERROR(status)) + gSleepEvent = NULL; + + RT->GetTime(&et, NULL); + if (et.Year % 4 == 0 && et.Year % 100 != 0 && et.Year % 400 == 0) + dpm[3]++; + + argc = (int)SI->Argc; + argv = malloc(sizeof argv * argc); + + for (i = 0; i < argc; i++) + { + n = (int)StrLen(SI->Argv[i]) + 1; + argv[i] = malloc(n); + convert_unicode_ascii(SI->Argv[i], argv[i], n); + } + + main(argc, argv); +} + +void exit(int status) +{ + if (gSleepEvent) + BS->CloseEvent(gSleepEvent); + + if (status == 0) + BS->Exit(gImageHandle, EFI_SUCCESS, 0, NULL); + else + BS->Exit(gImageHandle, EFIERR_OEM(status), 0, NULL); +} + +unsigned int sleep(unsigned int seconds) +{ + UINTN unused; + + if (gSleepEvent) + { + BS->SetTimer(gSleepEvent, TimerRelative, seconds * 10000000); + BS->WaitForEvent(1, &gSleepEvent, &unused); + } + else + { + BS->Stall(seconds * 1000000); + } + + return 0; +} + +void mdelay(int milliseconds) +{ + BS->Stall(milliseconds * 1000); +} + +void udelay(int microseconds) +{ + BS->Stall(microseconds); +} + +int _fltused; + +#include "getopt.c" + +/* vi: set sw=4 ts=4 sts=4 et :iv */ diff --git a/source/inc/ata.h b/source/inc/ata.h new file mode 100755 index 0000000..7781f3e --- /dev/null +++ b/source/inc/ata.h @@ -0,0 +1,869 @@ +/*************************************************************************** + * * + * Copyright 2003 LSI Logic Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Logic. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Logic Corporation. * + * * + *************************************************************************** + * + * Name: ATA.H + * Title: ATA and SATA Device structures and definitions + * Programmer: ---------------- + * Creation Date: February 26, 2002 + * + * Version History + * --------------- + * + * Last Updated + * ------------- + * Version %version: 24 % + * Date Updated %date_modified: % + * Programmer %created_by: mfry % + * + * Date Who Description + * -------- --- ------------------------------------------------------- + * 02/26/02 GWK Initial version + * 01/24/03 GWK Updated for SAS 1064 + * 08/20/08 KAM updated for SDM big endian platform and gcc bitfields + * + * + * Description + * ------------ + * This include file contains generic ATA and SATA structures and definitions. + * + *------------------------------------------------------------------------- + */ + +/* If this header file has not been included yet */ +#ifndef ATA_H_SOURCE +#define ATA_H_SOURCE + + + +/* Status Register Bit Definitions */ +#define ATA_STATUS_ERR (0x01) +#define ATA_STATUS_DRQ (0x08) +#define ATA_STATUS_CMD_DEP (0x10) +#define ATA_STATUS_DF (0x20) +#define ATA_STATUS_DRDY (0x40) +#define ATA_STATUS_BSY (0x80) +#define ATA_STATUS_ERR_DF (ATA_STATUS_ERR | ATA_STATUS_DF) +/* Atapi Status Register Bit Definitions */ +#define ATAPI_STATUS_CHK (0x01) +#define ATAPI_STATUS_DRQ (0x08) +#define ATAPI_STATUS_SERV (0x10) +#define ATAPI_STATUS_DMRD (0x20) +#define ATAPI_STATUS_DRDY (0x40) +#define ATAPI_STATUS_BSY (0x80) + +/* Atapi Interrupt Reason Register Bit Definitions */ +#define ATAPI_INTERRUPT_REASON_CD (0x01) +#define ATAPI_INTERRUPT_REASON_IO (0x02) +#define ATAPI_INTERRUPT_REASON_REL (0x04) +#define ATAPI_INTERRUPT_REASON_TAG_SHIFT (3) +#define ATAPI_INTERRUPT_REASON_TAG_MASK (0xF8) + +/* Error Register Bit Definitions */ +#define ATA_ERR_ICRC (0x80) /* ultra DMA CRC */ +#define ATA_ERR_UNC (0x40) /* uncorrectable error */ +#define ATA_ERR_WP (0x40) /* write-protect bit */ +#define ATA_ERR_MC (0x20) /* media changed */ +#define ATA_ERR_IDNF (0x10) /* id not found */ +#define ATA_ERR_MCR (0x08) /* media change requested */ +#define ATA_ERR_ABRT (0x04) /* aborted command */ +#define ATA_ERR_NM (0x02) /* no media present */ + +/* Atapi Error Register Bit Definitions */ +#define ATAPI_ERR_ILI (0x01) +#define ATAPI_ERR_EOM (0x02) +#define ATAPI_ERR_ABRT (0x04) +#define ATAPI_ERR_SENSE_KEY_SHIFT (3) +#define ATAPI_ERR_SENSE_KEY_TAG_MASK (0xF8) + +/* Device & Device/Head Register Bit Definitions */ +#define ATA_DEVICE_LBA (0x40) + +/* Device Control Register Bit Definitions */ +#define ATA_DEVICE_CONTROL_SRST (0x04) +#define ATA_DEVICE_CONTROL_NIEN (0x02) + +/* + * define the ATA command set + */ +#define ATA_CMD_CHECK_POWER_MODE 0xE5 +#define ATA_CMD_DEVICE_CONFIGURATION 0xB1 +#define ATA_CMD_DOWNLOAD_MICROCODE 0x92 +#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90 +#define ATA_CMD_FLUSH_CACHE 0xE7 +#define ATA_CMD_FLUSH_CACHE_EXT 0xEA +#define ATA_CMD_GET_MEDIA_STATUS 0xDA +#define ATA_CMD_IDENTIFY_DEVICE 0xEC +#define ATA_CMD_IDENTIFY_PACKET_DEVICE 0xA1 +#define ATA_CMD_IDLE 0xE3 +#define ATA_CMD_IDLE_IMMEDIATE 0xE1 +#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91 +#define ATA_CMD_MEDIA_EJECT 0xED +#define ATA_CMD_MEDIA_LOCK 0xDE +#define ATA_CMD_MEDIA_UNLOCK 0xDF +#define ATA_CMD_NATIVE_MAX_ADDRESS 0xF8 +#define ATA_CMD_NATIVE_MAX_ADDRESS_EXT 0x27 +#define ATA_CMD_NOP 0x00 +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_READ_BUFFER 0xE4 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_READ_DMA_QUEUED 0xC7 +#define ATA_CMD_READ_DMA_QUEUED_EXT 0x26 +#define ATA_CMD_READ_FPDMA_QUEUED 0x60 +#define ATA_CMD_READ_MULTIPLE 0xC4 +#define ATA_CMD_READ_MULTIPLE_EXT 0x29 +#define ATA_CMD_READ_LOG_EXT 0x2F +#define ATA_CMD_READ_SECTORS 0x20 +#define ATA_CMD_READ_SECTORS_EXT 0x24 +#define ATA_CMD_READ_LONG 0x22 /* Obsoleted in ATA-4 */ +#define ATA_CMD_READ_VERIFY_SECTORS 0x40 +#define ATA_CMD_READ_VERIFY_SECTORS_EXT 0x42 +#define ATA_CMD_SECURITY_DISABLE_PASSWORD 0xF6 +#define ATA_CMD_SECURITY_ERASE_PREPARE 0xF3 +#define ATA_CMD_SECURITY_ERASE_UNIT 0xF4 +#define ATA_CMD_SECURITY_FREEZE_LOCK 0xF5 +#define ATA_CMD_SECURITY_SET_PASSWORD 0xF1 +#define ATA_CMD_SECURITY_UNLOCK 0xF2 +#define ATA_CMD_SEEK 0x70 +#define ATA_CMD_SET_FEATURES 0xEF +#define ATA_CMD_SET_MAX 0xF9 +#define ATA_CMD_SET_MAX_EXT 0x37 +#define ATA_CMD_SET_MULTIPLE_MODE 0xC6 +#define ATA_CMD_SLEEP 0xE6 +#define ATA_CMD_SMART 0xB0 +#define ATA_CMD_SMART_READ_DATA 0xD0 +#define ATA_CMD_SMART_ENABLE_DISABLE_AUTOSAVE 0xD2 +#define ATA_CMD_SMART_SAVE_ATTRIBUTE_VALUES 0xD3 +#define ATA_CMD_SMART_EXECUTE_OFFLINE_IMMEDIATE 0xD4 +#define ATA_CMD_SMART_READ_LOG 0xD5 +#define ATA_CMD_SMART_WRITE_LOG 0xD6 +#define ATA_CMD_SMART_ENABLE_OPERATIONS 0xD8 +#define ATA_CMD_SMART_DISABLE_OPERATIONS 0xD9 +#define ATA_CMD_SMART_RETURN_STATUS 0xDA +#define ATA_CMD_STANDBY 0xE2 +#define ATA_CMD_STANDBY_IMMEDIATE 0xE0 +#define ATA_CMD_WRITE_BUFFER 0xE8 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_WRITE_DMA_QUEUED 0xCC +#define ATA_CMD_WRITE_DMA_QUEUED_EXT 0x36 +#define ATA_CMD_WRITE_FPDMA_QUEUED 0x61 +#define ATA_CMD_WRITE_MULTIPLE 0xC5 +#define ATA_CMD_WRITE_MULTIPLE_EXT 0x39 +#define ATA_CMD_WRITE_SECTORS 0x30 +#define ATA_CMD_WRITE_SECTORS_EXT 0x34 +#define ATA_CMD_WRITE_LONG 0x32 /* Obsoleted in ATA-4 */ + + +/* + * define SET_FEATURES sub-commands + */ +#define ATA_CMD_SF_SET_TRANSFER_MODE 0x03 +#define ATA_CMD_SF_WRITE_CACHE_ENABLE 0x02 +#define ATA_CMD_SF_WRITE_CACHE_DISABLE 0x82 +#define ATA_CMD_SF_ENABLE_READ_LOOK_AHEAD 0xAA +#define ATA_CMD_SF_DISABLE_READ_LOOK_AHEAD 0x55 +#define ATA_CMD_SF_ENABLE_REVERT_PWR_ON_DFLTS 0xCC +#define ATA_CMD_SF_DISABLE_REVERT_PWR_ON_DFLTS 0x66 +#define ATA_CMD_SF_ENABLE_SATA_FEATURE 0x10 +#define ATA_CMD_SF_DISABLE_SATA_FEATURE 0x90 + +#define SATA_CMD_SF_NON_ZERO_BUFF_OFST_IN_DMA_SETUP_FIS 0x01 +#define SATA_CMD_SF_DMA_SETUP_FIS_AUTO_ACTV_OPTIMIZATION 0x02 +#define SATA_CMD_SF_GUARANTEED_IN_ORDER_DATA_DELIVERY 0x04 +#define SATA_CMD_SF_ASYNC_NOTIFICATION 0x05 +#define SATA_CMD_SF_SOFTWARE_SETTINGS_PRESERVATION 0x06 + + +/* Transfer mode settings for SET_FEATURES command */ +#define PIO_DEFAULT 0x0 +#define PIO_MODE3 0xB +#define PIO_MODE4 0xC + +#define MDMA_MODE0 0x20 +#define MDMA_MODE1 0x21 +#define MDMA_MODE2 0x22 + +#define UDMA_MODE0 0x40 +#define UDMA_MODE1 0x41 +#define UDMA_MODE2 0x42 +#define UDMA_MODE3 0x43 +#define UDMA_MODE4 0x44 +#define UDMA_MODE5 0x45 +#define UDMA_MODE6 0x46 + +/* Error register definitions for the EXECUTE DEVICE DIAGNOSTIC command */ +#define ATA_ERROR_DIAGNOSTIC_CODE_DEVICE0_PASSED 0x01 + +/* These signatures are left in the task file registers after an + * EXECUTE DEVICE DIAGNOSTIC command, and at a few other times + */ +#define COMMAND_BLOCK_SIGNATURE_ATAPI (0x00EB1401) +#define SECTOR_COUNT_SIGNATURE_ATAPI (0x01) +#define COMMAND_BLOCK_SIGNATURE_ATA (0x00000001) +#define SECTOR_COUNT_SIGNATURE_ATA (0x01) + + +/* CHECK POWER MODE results in Sector Count register */ +#define ATA_CHECK_POWER_MODE_STANDBY (0x00) +#define ATA_CHECK_POWER_MODE_IDLE (0x80) +#define ATA_CHECK_POWER_MODE_ACTIVE_OR_IDLE (0xFF) + +/* DOWNLOAD MICROCODE SUB COMMANDS */ +#define ATA_DNLD_MIC_CODE_IMMED_TEMP (0x01) +#define ATA_DNLD_MIC_CODE_IMMED_FUTURE (0x07) + +/* + * define typical IDE timeout values + * + * GES 02/09/01: These values will need some tweaking!! + */ +#define ATA_TIMEOUT_GEN 30 /* generic timeout is 30 seconds */ +#define ATA_TIMEOUT_IDENTIFY 2 /* timeout for IDENTIFY commands */ +#define ATA_TIMEOUT_READ_BUFFER 2 /* timeout for read buffer */ +#define ATA_TIMEOUT_DIAG 5 /* timeout for diagnostics command */ +#define ATA_TIMEOUT_STANDBY_IDLE 30 /* timeout for start/stop unit commands */ +#define ATA_TIMEOUT_FLUSH_CACHE 30 /* cache flush timeout */ +#define ATA_TIMEOUT_CHECK_POWER 2 /* timeout for CHECK POWER MODE */ +#define ATA_TIMEOUT_DOWNLOAD_MICROCODE 120 /* wait up to 2 minute */ + + +/* + * define the IDENTIFY DEVICE structure + */ +typedef struct _ATA_IDENTIFY_DEVICE_DATA +{ + U16 GeneralConfiguration; /* 0 */ + U16 LogicalCylinders; /* 1 */ + U16 SpecificConfiguration; /* 2 */ + U16 LogicalHeads; /* 3 */ + U16 Retired4to5[2]; /* 4-5 */ + U16 LogicalSectorsPerLogicalTrack; /* 6 */ + U16 Reserved7to8[2]; /* 7-8 */ + U16 Retired3; /* 9 */ + U16 SerialNumber[10]; /* 10-19 */ + U16 Retired20to21[2]; /* 20-21 */ + U16 Obsolete22; /* 22 */ + U16 FirmwareRevision[4]; /* 23-26 */ + U16 ModelNumber[20]; /* 27-46*/ + U16 MaxMultipleSize; /* 47 */ + U16 Reserved48; /* 48 */ + U16 Capabilities[2]; /* 49-50 */ + U16 Obsolete51to52[2]; /* 51-52 */ + U16 ValidWords; /* 53 */ + U16 CurrentLogicalCylinders; /* 54 */ + U16 CurrentLogicalHeads; /* 55 */ + U16 CurrentLogicalSectorsPerTrack; /* 56 */ + U16 CurrentCapacityInSectors[2]; /* 57-58 */ + U16 CurrentMultipleSize; /* 59 */ + U16 TotalUserSectors[2]; /* 60-61 */ + U16 Obsolete62; /* 62 */ + U16 MultiwordDmaMode; /* 63 */ + U16 PioModesSupported; /* 64 */ + U16 MinimumMultiwordDmaTransferCycleTime; /* 65 */ + U16 ManufacturerRecommendedMultiwordDmaTransferCycleTime; /* 66 */ + U16 MinumumPioTransferCycleTimeWithoutFlowControl; /* 67 */ + U16 MinumumPioTransferCycleTimeWithFlowControl; /* 68 */ + U16 Reserved69to70[2]; /* 69-70 */ + U16 Reserved71to74[4]; /* 71-74 */ + U16 QueueDepth; /* 75 */ + U16 SerialATACapabilities; /* 76 */ + U16 Reserved77; /* 77 */ + U16 SerialFeaturesSupported[2]; /* 78-79 */ + U16 MajorVersionNumber; /* 80 */ + U16 MinorVersionNumber; /* 81 */ + U16 CommandSetsSupported[3]; /* 82-84 */ + U16 CommandSetsEnabled[2]; /* 85-86 */ + U16 CommandSetDefaults; /* 87 */ + U16 UltraDmaModes; /* 88 */ + U16 TimeForSecurityErase; /* 89 */ + U16 TimeForEnahncedSecurityErase; /* 90 */ + U16 CurrentAdvancedPowerManagementValue; /* 91 */ + U16 MasterPasswordRevisionCode; /* 92 */ + U16 HardwareResetResult; /* 93 */ + U16 AcousticManagement; /* 94 */ /* GWK Reserved in ATA-5 */ + U16 Reserved95to99[5]; /* 95-99 */ + U16 MaximumLBAfor48bitAddressing[4]; /* 100-103 */ /* GWK Reserved in ATA-5 */ + U16 Reserved104to107[4]; /* 104-107 */ + U16 WorldWideName[4]; /* 108-111 */ + U16 Reserved112to126[15]; /* 112-126 */ + U16 RemovableMediaStatusNotification; /* 127 */ + U16 SecurityStatus; /* 128 */ + U16 VendorSpecific[31]; /* 129-159 */ + U16 CFApowerMode; /* 160 */ + U16 Reserved161to175[15]; /* 161-175 */ + U16 Reserves176to254[79]; /* 176-254 */ + U16 IntegrityWord; /* 255 */ +} ATA_IDENTIFY_DEVICE_DATA, *PTR_ATA_IDENTIFY_DEVICE_DATA; + +#define ATA_IDENTIFY_DATA_FIRMWARE_REVISION_LENGTH_IN_BYTES 8 +#define ATA_IDENTIFY_DATA_MODEL_NUMBER_LENGTH_IN_BYTES 40 +#define ATA_IDENTIFY_DATA_SERIAL_NUMBER_LENGTH_IN_BYTES 20 + +#define ATA_IDENTIFY_DATA_MAJOR_VERSION_ATA_ATAPI_7 (0x0080) +#define ATA_IDENTIFY_DATA_MAJOR_VERSION_ATA_ATAPI_8 (0x0100) + +#define ATA_IDENTIFY_DATA_COMMAND_SET_DEFAULT_WWN (0x0100) +#define ATA_IDENTIFY_DATA_WRITE_CACHE_ENABLED (0x0020) +#define ATA_IDENTIFY_DATA_LOOK_AHEAD_ENABLED (0x0040) +#define ATA_IDENTIFY_DATA_SMART_FEATURE_ENABLED (0x0001) +#define ATA_IDENTIFY_DATA_SATA_SUP_FEAT_SFT_SET_PRES (0x0040) + +/* + * define the IDENTIFY PACKET DEVICE structure for ATAPI + */ +typedef struct _ATA_IDENTIFY_PACKET_DEVICE_DATA +{ + U16 GeneralConfiguration; /* 0 */ + U16 Reserved01; /* 1 */ + U16 UniqueConfiguration; /* 2 */ + U16 Reserved03to09[7]; /* 3-9 */ + U16 SerialNumber[10]; /* 10-19 */ + U16 Retired20to22[3]; /* 20-22 */ + U16 FirmwareRevision[4]; /* 23-26 */ + U16 ModelNumber[20]; /* 27-46*/ + U16 Reserved47to48[2]; /* 47-48 */ + U16 Capabilities[2]; /* 49-50 */ + U16 Obsolete51to52[2]; /* 51-52 */ + U16 ValidWords; /* 53 */ + U16 Reserved54to62[9]; /* 54-62 */ + U16 MultiwordDmaMode; /* 63 */ + U16 PioModesSupported; /* 64 */ + U16 MinimumMultiwordDmaTransferCycleTime; /* 65 */ + U16 ManufacturerRecommendedMultiwordDmaTransferCycleTime; /* 66 */ + U16 MinumumPioTransferCycleTimeWithoutFlowControl; /* 67 */ + U16 MinumumPioTransferCycleTimeWithFlowControl; /* 68 */ + U16 Reserved69to70[2]; /* 69-70 */ + U16 TypicalTimePacketCmdToBusRelease; /* 71 */ + U16 TypicalTimeServiceToBSYCleared; /* 72 */ + U16 Reserved73to74[2]; /* 73-74 */ + U16 QueueDepth; /* 75 */ + U16 SerialATACapabilities; /* 76 */ + U16 Reserved77to79[3]; /* 77-79 */ + U16 MajorVersionNumber; /* 80 */ + U16 MinorVersionNumber; /* 81 */ + U16 CommandSetsSupported[3]; /* 82-84 */ + U16 CommandSetsEnabled[2]; /* 85-86 */ + U16 CommandSetDefaults; /* 87 */ + U16 UltraDmaModes; /* 88 */ + U16 Reserved89to92[4]; /* 89-92 */ + U16 HardwareResetResult; /* 93 */ + U16 AcousticManagement; /* 94 */ /* GWK Reserved in ATA-5 */ + U16 Reserved95to124[30]; /* 95-124 */ + U16 AtapeByteCount0Behavior; /* 125 */ + U16 Obsolete126; /* 126 */ + U16 RemovableMediaStatusNotification; /* 127 */ + U16 SecurityStatus; /* 128 */ + U16 VendorSpecific129to159[31]; /* 129-159 */ + U16 ReservedForCFA160to175[16]; /* 160-175 */ + U16 Reserved176to254[79]; /* 176-254 */ + U16 IntegrityWord; /* 255 */ +} ATA_IDENTIFY_PACKET_DEVICE_DATA, *PTR_ATA_IDENTIFY_PACKET_DEVICE_DATA; + +#define ATA_IDENTIFY_PACKET_DATA_FIRMWARE_REVISION_LENGTH_IN_BYTES 8 +#define ATA_IDENTIFY_PACKET_DATA_MODEL_NUMBER_LENGTH_IN_BYTES 40 +#define ATA_IDENTIFY_PACKET_DATA_SERIAL_NUMBER_LENGTH_IN_BYTES 20 + + + + +/******************************************************************************/ +/* */ +/* S A T A S P E C I F I C D E F I N I T I O N S */ +/* */ +/******************************************************************************/ + +/* FIS Types */ +#define FIS_TYPE_REGISTER_HOST_TO_DEVICE 0x27 +#define FIS_TYPE_REGISTER_DEVICE_TO_HOST 0x34 +#define FIS_TYPE_SET_DEVICE_BITS_DEVICE_TO_HOST 0xA1 +#define FIS_TYPE_DMA_ACTIVATE_DEVICE_TO_HOST 0x39 +#define FIS_TYPE_DMA_SETUP_BIDIRECTIONAL 0x41 +#define FIS_TYPE_BIST_ACTIVATE_BIDIRECTIONAL 0x58 +#define FIS_TYPE_PIO_SETUP_DEVICE_TO_HOST 0x5F +#define FIS_TYPE_DATA_BIDIRECTIONAL 0x46 + +/* FIS Command/Control Bit Definitions */ +#define FIS_COMMAND_CONTROL_COMMAND 0x1 +#define FIS_COMMAND_CONTROL_CONTROL 0x0 + +/* FIS Interrupt Bit Definitions */ +#define FIS_INTERRUPT_TRUE 0x1 +#define FIS_INTERRUPT_FALSE 0x0 + +/* FIS Direction Bit Definitions */ +#define FIS_DIRECTION_TRANSMITTER_TO_RECEIVER 0x1 +#define FIS_DIRECTION_RECEIVER_TO_TRANSMITTER 0x0 + +/* + * This is the mapping of how the various fields in the host to device FIS are used + * for CHS, LBA28-bit,and LBA48-bit modes. Use the union on the register FIS + * types to select. + * + * + * CHS LBA28 LBAEXP48 + * --- ----- -------- + * 0x00 U8 FISType; U8 FISType; U8 FISType; + * 0x01 U32 Reserved01Bits0to6 :7; U32 Reserved01Bits0to6 :7; U32 Reserved01Bits0to6 :7; + * U32 CommandBit :1; U32 CommandBit :1; U32 CommandBit :1; + * 0x02 U8 Command; U8 Command; U8 Command; + * 0x03 U8 Features; U8 Features; U8 Features; + * 0x04 U8 SectorNumber; U8 LBALow_0_7; U8 LBALow_0_7; + * 0x05 U8 CylLow; U8 LBAMid_8_15; U8 LBAMid_8_15; + * 0x06 U8 CylHigh; U8 LBAHigh_16_23; U8 LBAHigh_16_23; + * 0x07 U8 DeviceHead; U8 DeviceAndLBA24_27; U8 Device; + * 0x08 U8 SectorNumberExp; U8 SectorNumberExp; U8 LBALowExp_24_31; + * 0x09 U8 CylLowExp; U8 CylLowExp; U8 LBAMidExp_32_39; + * 0x0A U8 CylHighExp; U8 CylHighExp; U8 LBAHighExp_40_47; + * 0x0B U8 FeaturesExp; U8 FeaturesExp; U8 FeaturesExp; + * 0x0C U8 SectorCount; U8 SectorCount; U8 SectorCount0_7; + * 0x0D U8 SectorCountExp; U8 SectorCountExp; U8 SectorCountExp8_15; + * 0x0E U8 Reserved0E; U8 Reserved0E; U8 Reserved0E; + * 0x0F U8 Control; U8 Control; U8 Control; + * 0x10 U32 Reserved10to14; U32 Reserved10to14; U32 Reserved10to14; + */ + +/* + * SATA Register - Host To Device FIS for CHS addressing + */ +typedef struct _REGISTER_HOST_TO_DEVICE_FIS_CHS +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 CommandBit :1; /* 0x01 */ + U8 Reserved01Bits0to6 :7; +#else /* little endian */ + U8 Reserved01Bits0to6 :7; /* 0x01 */ + U8 CommandBit :1; +#endif + U8 Command; /* 0x02 */ + U8 Features; /* 0x03 */ + U8 SectorNumber; /* 0x04 */ + U8 CylLow; /* 0x05 */ + U8 CylHigh; /* 0x06 */ + U8 DeviceHead; /* 0x07 */ + U8 SectorNumberExp; /* 0x08 */ + U8 CylLowExp; /* 0x09 */ + U8 CylHighExp; /* 0x0A */ + U8 FeaturesExp; /* 0x0B */ + U8 SectorCount; /* 0x0C */ + U8 SectorCountExp; /* 0x0D */ + U8 Reserved0E; /* 0x0E */ + U8 Control; /* 0x0F */ + U32 Reserved10to14; /* 0x10 */ +} REGISTER_HOST_TO_DEVICE_FIS_CHS, *PTR_REGISTER_HOST_TO_DEVICE_FIS_CHS; + +/* + * SATA Register - Host To Device FIS for LBA 28-bit addressing + */ +typedef struct _REGISTER_HOST_TO_DEVICE_FIS_LBA28 +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 CommandBit :1; /* 0x01 */ + U8 Reserved01Bits0to6 :7; +#else /* little endian */ + U8 Reserved01Bits0to6 :7; /* 0x01 */ + U8 CommandBit :1; +#endif + U8 Command; /* 0x02 */ + U8 Features; /* 0x03 */ + U8 LBALow_0_7; /* 0x04 */ + U8 LBAMid_8_15; /* 0x05 */ + U8 LBAHigh_16_23; /* 0x06 */ + U8 DeviceAndLBA24_27; /* 0x07 */ + U8 SectorNumberExp; /* 0x08 */ + U8 CylLowExp; /* 0x09 */ + U8 CylHighExp; /* 0x0A */ + U8 FeaturesExp; /* 0x0B */ + U8 SectorCount; /* 0x0C */ + U8 SectorCountExp; /* 0x0D */ + U8 Reserved0E; /* 0x0E */ + U8 Control; /* 0x0F */ + U32 Reserved10to14; /* 0x10 */ +} REGISTER_HOST_TO_DEVICE_FIS_LBA28, *PTR_REGISTER_HOST_TO_DEVICE_FIS_LBA28; + +/* + * SATA Register - Host To Device FIS for LBA 48-bit addressing + */ +typedef struct _REGISTER_HOST_TO_DEVICE_FIS_LBA48 +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 CommandBit :1; /* 0x01 */ + U8 Reserved01Bits0to6 :7; +#else /* little endian */ + U8 Reserved01Bits0to6 :7; /* 0x01 */ + U8 CommandBit :1; +#endif + U8 Command; /* 0x02 */ + U8 Features; /* 0x03 */ + U8 LBALow_0_7; /* 0x04 */ + U8 LBAMid_8_15; /* 0x05 */ + U8 LBAHigh_16_23; /* 0x06 */ + U8 Device; /* 0x07 */ + U8 LBALowExp_24_31; /* 0x08 */ + U8 LBAMidExp_32_39; /* 0x09 */ + U8 LBAHighExp_40_47; /* 0x0A */ + U8 FeaturesExp; /* 0x0B */ + U8 SectorCount0_7; /* 0x0C */ + U8 SectorCountExp8_15; /* 0x0D */ + U8 Reserved0E; /* 0x0E */ + U8 Control; /* 0x0F */ + U32 Reserved10to14; /* 0x10 */ +} REGISTER_HOST_TO_DEVICE_FIS_LBA48, *PTR_REGISTER_HOST_TO_DEVICE_FIS_LBA48; + +/* + * SATA Register - Host To Device FIS for Packet (ATAPI) Commands + */ +typedef struct REGISTER_HOST_TO_DEVICE_FIS_PACKET +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 CommandBit :1; /* 0x01 */ + U8 Reserved01Bits0to6 :7; +#else /* little endian */ + U8 Reserved01Bits0to6 :7; /* 0x01 */ + U8 CommandBit :1; +#endif + U8 Command; /* 0x02 */ + U8 Features; /* 0x03 */ + U8 LBALow_0_7; /* 0x04 */ + U8 ByteCountLow; /* 0x05 */ + U8 ByteCountHigh; /* 0x06 */ + U8 DeviceSelect; /* 0x07 */ + U8 LBALowExp_24_31; /* 0x08 */ + U8 LBAMidExp_32_39; /* 0x09 */ + U8 LBAHighExp_40_47; /* 0x0A */ + U8 FeaturesExp; /* 0x0B */ + U8 SectorCount0_7; /* 0x0C */ + U8 SectorCountExp8_15; /* 0x0D */ + U8 Reserved0E; /* 0x0E */ + U8 Control; /* 0x0F */ + U32 Reserved10to14; /* 0x10 */ +} REGISTER_HOST_TO_DEVICE_FIS_PACKET, *PTR_REGISTER_HOST_TO_DEVICE_FIS_PACKET; + +/* + * SATA Register - Host To Device FIS + */ +typedef union _REGISTER_HOST_TO_DEVICE_FIS +{ + REGISTER_HOST_TO_DEVICE_FIS_CHS Chs; + REGISTER_HOST_TO_DEVICE_FIS_LBA28 Lba28; + REGISTER_HOST_TO_DEVICE_FIS_LBA48 Lba48; + REGISTER_HOST_TO_DEVICE_FIS_PACKET Packet; +} REGISTER_HOST_TO_DEVICE_FIS, *PTR_REGISTER_HOST_TO_DEVICE_FIS; + + +/* + * SATA Register - Device To Host FIS for Chs addressing + */ +typedef struct _REGISTER_DEVICE_TO_HOST_FIS_CHS +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved01Bit7 :1; /* 0x01 */ + U8 Interrupt :1; + U8 Reserved01Bits0to5 :6; +#else /* little endian */ + U8 Reserved01Bits0to5 :6; /* 0x01 */ + U8 Interrupt :1; + U8 Reserved01Bit7 :1; +#endif + U8 Status; /* 0x02 */ + U8 Error; /* 0x03 */ + U8 SectorNumber; /* 0x04 */ + U8 CylLow; /* 0x05 */ + U8 CylHigh; /* 0x06 */ + U8 DeviceHead; /* 0x07 */ + U8 SectorNumberExp; /* 0x08 */ + U8 CylLowExp; /* 0x09 */ + U8 CylHighExp; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ + U8 SectorCount; /* 0x0C */ + U8 SectorCountExp; /* 0x0D */ + U8 Reserved0E; /* 0x0E */ + U8 Reseved0F; /* 0x0F */ + U32 Reserved10to14; /* 0x10 */ +} REGISTER_DEVICE_TO_HOST_FIS_CHS, *PTR_REGISTER_DEVICE_TO_HOST_FIS_CHS; + +/* + * SATA Register - Device To Host FIS for LBA 28-bit + */ +typedef struct _REGISTER_DEVICE_TO_HOST_FIS_LBA28 +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved01Bit7 :1; /* 0x01 */ + U8 Interrupt :1; + U8 Reserved01Bits0to5 :6; +#else /* little endian */ + U8 Reserved01Bits0to5 :6; /* 0x01 */ + U8 Interrupt :1; + U8 Reserved01Bit7 :1; +#endif + U8 Status; /* 0x02 */ + U8 Error; /* 0x03 */ + U8 LBALow_0_7; /* 0x04 */ + U8 LBAMid_8_15; /* 0x05 */ + U8 LBAHigh_16_23; /* 0x06 */ + U8 DeviceAndLBA24_27; /* 0x07 */ + U8 SectorNumberExp; /* 0x08 */ + U8 CylLowExp; /* 0x09 */ + U8 CylHighExp; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ + U8 SectorCount; /* 0x0C */ + U8 SectorCountExp; /* 0x0D */ + U8 Reserved0E; /* 0x0E */ + U8 Reseved0F; /* 0x0F */ + U32 Reserved10to14; /* 0x10 */ +} REGISTER_DEVICE_TO_HOST_FIS_LBA28, *PTR_REGISTER_DEVICE_TO_HOST_FIS_LBA28; + +/* + * SATA Register - Device To Host FIS for LBA 48-bit + */ +typedef struct _REGISTER_DEVICE_TO_HOST_FIS_LBA48 +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved01Bit7 :1; /* 0x01 */ + U8 Interrupt :1; + U8 Reserved01Bits0to5 :6; +#else /* little endian */ + U8 Reserved01Bits0to5 :6; /* 0x01 */ + U8 Interrupt :1; + U8 Reserved01Bit7 :1; +#endif + U8 Status; /* 0x02 */ + U8 Error; /* 0x03 */ + U8 LBALow_0_7; /* 0x04 */ + U8 LBAMid_8_15; /* 0x05 */ + U8 LBAHigh_16_23; /* 0x06 */ + U8 Device; /* 0x07 */ + U8 LBALowExp_24_31; /* 0x08 */ + U8 LBAMidExp_32_39; /* 0x09 */ + U8 LBAHighExp_40_47; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ + U8 SectorCount0_7; /* 0x0C */ + U8 SectorCountExp8_15; /* 0x0D */ + U8 Reserved0E; /* 0x0E */ + U8 Reseved0F; /* 0x0F */ + U32 Reserved10to14; /* 0x10 */ +} REGISTER_DEVICE_TO_HOST_FIS_LBA48, *PTR_REGISTER_DEVICE_TO_HOST_FIS_LBA48; + +/* + * SATA Register - Device To Host FIS for Packet (ATAPI) Commands + */ +typedef struct _REGISTER_DEVICE_TO_HOST_FIS_PACKET +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved01Bit7 :1; /* 0x01 */ + U8 Interrupt :1; + U8 Reserved01Bits0to5 :6; +#else /* little endian */ + U8 Reserved01Bits0to5 :6; /* 0x01 */ + U8 Interrupt :1; + U8 Reserved01Bit7 :1; +#endif + U8 AtapiStatus; /* 0x02 */ + U8 Error; /* 0x03 */ + U8 LBALow_0_7; /* 0x04 */ + U8 ByteCountLow; /* 0x05 */ + U8 ByteCountHigh; /* 0x06 */ + U8 DeviceSelect; /* 0x07 */ + U8 LBALowExp_24_31; /* 0x08 */ + U8 LBAMidExp_32_39; /* 0x09 */ + U8 LBAHighExp_40_47; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ + U8 InterruptReason; /* 0x0C */ + U8 SectorCountExp8_15; /* 0x0D */ + U8 Reserved0E; /* 0x0E */ + U8 Reseved0F; /* 0x0F */ + U32 Reserved10to14; /* 0x10 */ +} REGISTER_DEVICE_TO_HOST_FIS_PACKET, *PTR_REGISTER_DEVICE_TO_HOST_FIS_PACKET; + +/* + * SATA Register - Device To Host FIS + */ +typedef union _REGISTER_DEVICE_TO_HOST_FIS +{ + REGISTER_DEVICE_TO_HOST_FIS_CHS Chs; + REGISTER_DEVICE_TO_HOST_FIS_LBA28 Lba28; + REGISTER_DEVICE_TO_HOST_FIS_LBA48 Lba48; + REGISTER_DEVICE_TO_HOST_FIS_PACKET Packet; +} REGISTER_DEVICE_TO_HOST_FIS, *PTR_REGISTER_DEVICE_TO_HOST_FIS; + +/* + * SATA Set Device Bits - Device To Host FIS + */ +typedef struct _SET_DEVICE_BITS_DEVICE_TO_HOST_FIS +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Notification :1; /* 0x01 */ + U8 Interrupt :1; + U8 Reserved01Bits0to5 :6; + U8 Reserved02Bit7 :1; /* 0x02 */ + U8 StatusHi :3; + U8 Reserved02Bit3 :1; + U8 StatusLo :3; +#else /* little endian */ + U8 Reserved01Bits0to5 :6; /* 0x01 */ + U8 Interrupt :1; + U8 Notification :1; + U8 StatusLo :3; /* 0x02 */ + U8 Reserved02Bit3 :1; + U8 StatusHi :3; + U8 Reserved02Bit7 :1; +#endif + U8 Error; /* 0x03 */ + U32 SActive; /* 0x04 */ +} SET_DEVICE_BITS_DEVICE_TO_HOST_FIS, *PTR_SET_DEVICE_BITS_DEVICE_TO_HOST_FIS; + +/* + * SATA DMA Activate - Device To Host FIS + */ +typedef struct _DMA_ACTIVATE_DEVICE_TO_HOST_FIS +{ + U8 FISType; /* 0x00 */ + U8 Reserved01; /* 0x01 */ + U8 Reserved02; /* 0x02 */ + U8 Reserved03; /* 0x03 */ +} DMA_ACTIVATE_DEVICE_TO_HOST_FIS, *PTR_DMA_ACTIVATE_DEVICE_TO_HOST_FIS; + +/* + * SATA DMA Setup (Bi-directional) FIS + */ +typedef struct _DMA_SETUP_FIS +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved01Bit7 :1; /* 0x01 */ + U8 Interrupt :1; + U8 Direction :1; + U8 Reserved01Bits0to4 :5; +#else /* little endian */ + U8 Reserved01Bits0to4 :5; /* 0x01 */ + U8 Direction :1; + U8 Interrupt :1; + U8 Reserved01Bit7 :1; +#endif + U8 Reserved02; /* 0x02 */ + U8 Reserved03; /* 0x03 */ + U32 DMABufferIdentifierLow; /* 0x04 */ + U32 DMABufferIdentifierHigh; /* 0x08 */ + U32 Reserved0Cto0F; /* 0x0C */ + U32 DMABufferOffset; /* 0x10 */ + U32 DMATransferCount; /* 0x14 */ + U32 Reserved18; /* 0x18 */ +} DMA_SETUP_FIS, *PTR_DMA_SETUP_FIS; + +/* + * SATA BIST Activate FIS - I don't believe we suppor this ? + */ + +/* + * SATA PIO Setup - Device To Host FIS + */ +typedef struct _PIO_SETUP_DEVICE_TO_HOST_FIS +{ + U8 FISType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved01Bit7 :1; /* 0x01 */ + U8 Interrupt :1; + U8 Direction :1; + U8 Reserved01Bits0to4 :5; +#else /* little endian */ + U8 Reserved01Bits0to4 :5; /* 0x01 */ + U8 Direction :1; + U8 Interrupt :1; + U8 Reserved01Bit7 :1; +#endif + U8 Status; /* 0x02 */ + U8 Error; /* 0x03 */ + U8 SectorNumber; /* 0x04 */ + U8 CylLow; /* 0x05 */ + U8 CylHigh; /* 0x06 */ + U8 DeviceHead; /* 0x07 */ + U8 SectorNumberExp; /* 0x08 */ + U8 CylLowExp; /* 0x09 */ + U8 CylHighExp; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ + U8 SectorCount; /* 0x0C */ + U8 SectorCountExp; /* 0x0D */ + U8 Reserved0E; /* 0x0E */ + U8 E_Status; /* 0x0F */ + U16 TransferCount; /* 0x10 */ + U16 Reserved12to13; /* 0x12 */ +} PIO_SETUP_DEVICE_TO_HOST_FIS, *PTR_PIO_SETUP_DEVICE_TO_HOST_FIS; + +/* PIO Setup Direction Bit */ +#define PIO_SETUP_DIRECTION_HOST_TO_DEVICE (0) +#define PIO_SETUP_DIRECTION_DEVICE_TO_HOST (1) + +/* + * SATA Data - (Bi-directional) FIS + */ +typedef struct _DATA_FIS +{ + U8 FISType; /* 0x00 */ + U8 Reserved01; /* 0x01 */ + U8 Reserved02; /* 0x02 */ + U8 Reserved03; /* 0x03 */ + U32 Data[1]; /* 0x04 */ + /* Note the data is variable in length */ +} DATA_FIS, *PTR_DATA_FIS; + +/* This is a union of all the SATA FIS's */ +typedef union _PL_SATA_FIS_UNION +{ + REGISTER_HOST_TO_DEVICE_FIS HtoDFIS; + REGISTER_DEVICE_TO_HOST_FIS DtoHFIS; + SET_DEVICE_BITS_DEVICE_TO_HOST_FIS SetDeviceDtoHFIS; + DMA_ACTIVATE_DEVICE_TO_HOST_FIS DmaActivateDtoHFIS; + DMA_SETUP_FIS DmaSetupFIS; + PIO_SETUP_DEVICE_TO_HOST_FIS PioSetupDtoHFIS; + DATA_FIS DataFIS; +} PL_SATA_FIS_UNION, * PTR_PL_SATA_FIS_UNION; + + +typedef struct _READ_LOG_EXT_PAGE_10_DATA +{ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 NQ :1; /* 0x00 */ + U8 Reserved00Bit5to6 :2; + U8 Tag :5; +#else /* little endian */ + U8 Tag :5; /* 0x00 */ + U8 Reserved00Bit5to6 :2; + U8 NQ :1; +#endif + U8 Reserved01; /* 0x01 */ + U8 Status; /* 0x02 */ + U8 Error; /* 0x03 */ + U8 SectorNumber; /* 0x04 */ + U8 CylinderLow; /* 0x05 */ + U8 CylinderHigh; /* 0x06 */ + U8 DevHead; /* 0x07 */ + U8 SectorNumberExp; /* 0x08 */ + U8 CylinderLowExp; /* 0x09 */ + U8 CylinderHighExp; /* 0x0A */ + U8 Reserved11; /* 0x0B */ + U8 SectorCount; /* 0x0C */ + U8 SectorCountExp; /* 0x0D */ + U8 Reserved14to511[1]; /* 0x0E */ +} READ_LOG_EXT_PAGE_10_DATA, *PTR_READ_LOG_EXT_PAGE_10_DATA; + + +#endif /* End of #if ATA_H_SOURCE */ + diff --git a/source/inc/devioctl.h b/source/inc/devioctl.h new file mode 100755 index 0000000..b879826 --- /dev/null +++ b/source/inc/devioctl.h @@ -0,0 +1,145 @@ +/*++ BUILD Version: 0004 // Increment this if a change has global effects + +Copyright (c) 1992-1999 Microsoft Corporation + +Module Name: + + devioctl.h + +Abstract: + + This module contains + +Author: + + Andre Vachon (andreva) 21-Feb-1992 + + +Revision History: + + +--*/ + +// begin_winioctl + +#ifndef _DEVIOCTL_ +#define _DEVIOCTL_ + +// begin_ntddk begin_wdm begin_nthal begin_ntifs +// +// Define the various device type values. Note that values used by Microsoft +// Corporation are in the range 0-32767, and 32768-65535 are reserved for use +// by customers. +// + +#define DEVICE_TYPE ULONG + +#define FILE_DEVICE_BEEP 0x00000001 +#define FILE_DEVICE_CD_ROM 0x00000002 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 +#define FILE_DEVICE_CONTROLLER 0x00000004 +#define FILE_DEVICE_DATALINK 0x00000005 +#define FILE_DEVICE_DFS 0x00000006 +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#define FILE_DEVICE_INPORT_PORT 0x0000000a +#define FILE_DEVICE_KEYBOARD 0x0000000b +#define FILE_DEVICE_MAILSLOT 0x0000000c +#define FILE_DEVICE_MIDI_IN 0x0000000d +#define FILE_DEVICE_MIDI_OUT 0x0000000e +#define FILE_DEVICE_MOUSE 0x0000000f +#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 +#define FILE_DEVICE_NAMED_PIPE 0x00000011 +#define FILE_DEVICE_NETWORK 0x00000012 +#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 +#define FILE_DEVICE_NULL 0x00000015 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016 +#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 +#define FILE_DEVICE_PRINTER 0x00000018 +#define FILE_DEVICE_SCANNER 0x00000019 +#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a +#define FILE_DEVICE_SERIAL_PORT 0x0000001b +#define FILE_DEVICE_SCREEN 0x0000001c +#define FILE_DEVICE_SOUND 0x0000001d +#define FILE_DEVICE_STREAMS 0x0000001e +#define FILE_DEVICE_TAPE 0x0000001f +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 +#define FILE_DEVICE_TRANSPORT 0x00000021 +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_VIDEO 0x00000023 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 +#define FILE_DEVICE_WAVE_IN 0x00000025 +#define FILE_DEVICE_WAVE_OUT 0x00000026 +#define FILE_DEVICE_8042_PORT 0x00000027 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 +#define FILE_DEVICE_BATTERY 0x00000029 +#define FILE_DEVICE_BUS_EXTENDER 0x0000002a +#define FILE_DEVICE_MODEM 0x0000002b +#define FILE_DEVICE_VDM 0x0000002c +#define FILE_DEVICE_MASS_STORAGE 0x0000002d +#define FILE_DEVICE_SMB 0x0000002e +#define FILE_DEVICE_KS 0x0000002f +#define FILE_DEVICE_CHANGER 0x00000030 +#define FILE_DEVICE_SMARTCARD 0x00000031 +#define FILE_DEVICE_ACPI 0x00000032 +#define FILE_DEVICE_DVD 0x00000033 +#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 +#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 +#define FILE_DEVICE_DFS_VOLUME 0x00000036 +#define FILE_DEVICE_SERENUM 0x00000037 +#define FILE_DEVICE_TERMSRV 0x00000038 +#define FILE_DEVICE_KSEC 0x00000039 +#define FILE_DEVICE_FIPS 0x0000003A + +// +// Macro definition for defining IOCTL and FSCTL function control codes. Note +// that function codes 0-2047 are reserved for Microsoft Corporation, and +// 2048-4095 are reserved for customers. +// + +#define CTL_CODE( DeviceType, Function, Method, Access ) ( \ + ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ +) + +// +// Macro to extract device type out of the device io control code +// +#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0xffff0000)) >> 16) + +// +// Define the method codes for how buffers are passed for I/O and FS controls +// + +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 + +// +// Define the access check value for any access +// +// +// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in +// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these +// constants *MUST* always be in sync. +// +// +// FILE_SPECIAL_ACCESS is checked by the NT I/O system the same as FILE_ANY_ACCESS. +// The file systems, however, may add additional access checks for I/O and FS controls +// that use this value. +// + + +#define FILE_ANY_ACCESS 0 +#define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS) +#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe +#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe + +// end_ntddk end_wdm end_nthal end_ntifs + +#endif // _DEVIOCTL_ + +// end_winioctl + diff --git a/source/inc/dmi_ioctl.h b/source/inc/dmi_ioctl.h new file mode 100755 index 0000000..f897cf6 --- /dev/null +++ b/source/inc/dmi_ioctl.h @@ -0,0 +1,443 @@ +#ifndef _DMI_IOCTL_H_ +#define _DMI_IOCTL_H_ + +/*************************************************************************** + * * + * Copyright 1998 LSI Logic Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Logic. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Logic Corporation. * + * * + ***************************************************************************/ + +/* Name: DMI_IOCTL.H + * Title: Solaris O/S Character mode IOCTL definitions + * Programmer: Russell A. Johnson + * Creation Date: May 26, 1998 + * + * Version History + * --------------- + * + * Date Who? Description + * -------- ---- ------------------------------------------------------- +#BeginRevision + * 05/17/00 RAJ Added bus mode support for fibre channel devices. + * 12/19/99 RAJ Added new flags for scsi-3 options. + * 11/09/98 RAJ Changed copyright notice to LSI Logic. +#EndRevision + * Version 4.02.01 + * 07/22/98 RAJ Added some more data to the DMI data structure. This + * includes the PCI bus number, device number, and function + * number. Also added a major version number for the data + * structure. That version number indicates major changes. + * When it changes then the entire data format may have + * changed. See the comments below for more details. +#EndRevision + * Version 4.00.04 + * 05/26/98 RAJ Initial version. +#EndRevision + * +#BeginDescription + * + * This file contains the Solaris 2.6 character mode driver interface + * definitions needed in order to provide IOCTL's for our SCSI HBA driver. + * +#EndDescription + * + *------------------------------------------------------------------------- + */ + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * HEADER FILE DEPENDANCIES + *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * This file is dependent on the following files: + * + * SALIOS.H - type defintions UINT8, UINT16, UINT32, UINT64 + */ + +/* The following data is for our character mode ioctl interface. Per the + * Solaris standard mechanism, we define SYMIOCTL as a unique number in the + * upper 8 bits and a command value in the lower 8 bits. + */ +#define SYMIOCTL ('H' << 8) +#define SYMIOCTL_GET_DMI_DATA (SYMIOCTL | 1) +#define SYMIOCTL_GET_TIMERS (SYMIOCTL | 2) +#define SYMIOCTL_UPDATE_FLASH (SYMIOCTL | 3) +#define SYMIOCTL_RESET_ADAPTER (SYMIOCTL | 4) +#define SYMIOCTL_GET_PROPERTY (SYMIOCTL | 5) +#define SYMIOCTL_PASS_THRU (SYMIOCTL | 6) +#define SYMIOCTL_REG_ACCESS (SYMIOCTL | 7) +#define SYMIOCTL_EVENT_QUERY (SYMIOCTL | 8) +#define SYMIOCTL_EVENT_ENABLE (SYMIOCTL | 9) +#define SYMIOCTL_EVENT_REPORT (SYMIOCTL | 10) +#define SYMIOCTL_GET_PCI_INFO (SYMIOCTL | 11) +#define SYMIOCTL_BTDH_MAPPING (SYMIOCTL | 12) +#define SYMIOCTL_DIAG_ACTION (SYMIOCTL | 13) +#define SYMIOCTL_PASS_THRU_TIMEOUT (SYMIOCTL | 14) + +/* The following are our ioctl() return status values. If everything went + * well, we return good status. If the buffer length sent to us is too short + * we return a status to tell the user. + */ +#define SYMIOCTL_STATUS_GOOD 0 +#define SYMIOCTL_STATUS_LEN_TOO_SHORT 1 + +/* The data structures defined in this file are marked with a data structure + * length and data structure version. The length value is the first value in + * the structure and is used to make sure the buffer is large enough for + * communication between the driver and the application. The version number is + * a major version number. If the data structure changes and only has a new + * element appended, then the version number will remain the same but the + * length will increase. If the data structure changes in any other way, such + * as re-arranging all of its elements, then the version number will increase. + * + * The following macro defines the current version number of the data + * structure. + */ +#define SYMHI_DMI_DATA_VERSION 1 + +/* The following is the SYMIOCTL_GET_DMI_DATA data structure. This data + * structure is setup so that we hopefully are properly aligned for both 32-bit + * and 64-bit mode applications. + * + * StructureLength - This value is the amount of data the caller has allocated + * for the structure when they first call us. After we have filled in the + * structure, this indicates the length our data structure is. + * + * MajorVersion - This value is used by the driver to tell the application what + * version of the data structure is being provided. It only changes if the + * data ordering of the data below is changed. + * + * MinSyncPeriodNs - This is the minimum period in nano-seconds (ns) that we + * will negotiate for on this adapter. The smaller value the faster + * synchronous speed except if this value is zero then asynchronous transfers + * is all we support. + * + * MaxWidth - This value indicates the maximum width this bus can be used as. + * If the PciDeviceId indicates a width capability of 16 devices and this is + * set to 8 devices then the PCI Subsystem ID value has limited our use of this + * adapter to 8 devices. This value also indicates the number of valid + * elements in the DevSpeed[] and DevWidth[] array's. + * + * HostScsiId - This is the host adapter SCSI ID being used by this adapter. + * + * PciBusNumber - The number of the PCI bus this adapter is on. If for some + * reason the driver is unable to determine the bus number, device number, or + * function number, these values will be set to 0xFF. + * + * PciDeviceNumber - The PCI device number for this device. + * + * PciFunctionNumber - The PCI function number for this device. + * + * PciDeviceId - This is the PCI device ID from PCI configuration space for + * this adapter. + * + * PciRevision - This is the PCI revision value from PCI configuration space + * for this adapter. + * + * HwBusMode - This value indicates the mode the bus is currently in. See the + * SYM_HW_BUS_MODE_xx macros. + * + * DevSpeed - This array is indexed by the target ID and indicates the + * currently negotiated synchronous speed in nano-seconds (ns). A value of + * zero ns indicates asynchronous mode. + * + * DevWidth - This array is indexed by the target ID and indicates the + * currently negotiated width in bits. A value of 8 indicates narrow mode, a + * value of 16 indicates wide. + * + * DriverVersion - This is an ascii null-terminated string indicating the + * version of this driver. + * + * DevFlags - This array is indexed by the target ID and indicates the + * currently negotiated options such as DT and async protection capabilities. + */ +#pragma pack(1) +typedef struct _SYMHI_DMI_DATA +{ /* Offset */ + UINT32 StructureLength; /* 0x00..0x03 */ + UINT32 Reserved1; /* 0x04..0x07 */ + UINT32 MajorVersion; /* 0x08..0x0B */ + UINT16 MinSyncPeriodNs; /* 0x0C..0x0D */ + UINT8 MaxWidth; /* 0x0E */ + UINT8 HostScsiId; /* 0x0F */ + UINT8 PciBusNumber; /* 0x10 */ + UINT8 PciDeviceNumber; /* 0x11 */ + UINT8 PciFunctionNumber; /* 0x12 */ + UINT8 Reserved2; /* 0x13 */ + UINT16 PciDeviceId; /* 0x14..0x15 */ + UINT8 PciRevision; /* 0x16 */ + UINT8 HwBusMode; /* 0x17 */ + UINT8 Reserved3[8]; /* 0x18..0x1F */ +#if defined TARGET_MPTx + /* MPI adapters can have many more devices per SCSI bus than non-MPI + * adapters. + */ + UINT16 DevSpeed[256]; /* 0x20..0x21F */ + UINT8 DevWidth[256]; /* 0x220..0x31F */ + UINT32 DevFlags[256]; /* 0x320..0x71F */ + char DriverVersion[80]; /* 0x720..0x76F */ +#elif defined TARGET_HIHW || defined TARGET_SRHW + UINT16 DevSpeed[16]; /* 0x20..0x3F */ + UINT8 DevWidth[16]; /* 0x40..0x4F */ + char DriverVersion[80]; /* 0x50..0x9F */ + UINT32 DevFlags[16]; /* 0xA0..0xDF */ +#else +#error "Unknown hardware type" +#endif /* defined TARGET_xxx */ +} SYMHI_DMI_DATA, * PTR_SYMHI_DMI_DATA; +#pragma pack() + +/* The following are definitions for the value of HwBusMode in the + * SYMHI_DMI_DATA data structure. + * + * SYM_HW_BUS_MODE_UNKNOWN - The bus mode is not known yet + * SYM_HW_BUS_MODE_SINGLE - The bus is in single ended mode + * SYM_HW_BUS_MODE_HVD - The bus is in high voltage differential mode + * SYM_HW_BUS_MODE_LVD - The bus is in low voltage differential mode + * SYM_HW_BUS_MODE_FC - The bus is a fibre channel bus + */ +#define SYM_HW_BUS_MODE_UNKNOWN (0x00) +#define SYM_HW_BUS_MODE_SINGLE (0x01) +#define SYM_HW_BUS_MODE_HVD (0x02) +#define SYM_HW_BUS_MODE_LVD (0x03) +#define SYM_HW_BUS_MODE_FC (0x04) + +/* The following are definitions for the DevFlags[] array. Each bit is set + * only when the feature is currently in use for the given device. + * + * SYM_DEV_DT - Set when Dual Transfers (ie. dual edge clock in use) enabled + * SYM_DEV_ASYNC_PROT - Set when asynchronous phase protection is enabled + */ +#define SYM_DEV_DT (0x00000001) +#define SYM_DEV_ASYNC_PROT (0x00000002) + +#pragma pack(1) +typedef struct _SYM_UPDATE_FLASH +{ + UINT64 PtrBuffer; + UINT32 ImageChecksum; + UINT32 ImageOffset; + UINT32 ImageSize; + UINT32 ImageType; +} SYM_UPDATE_FLASH, * PTR_SYM_UPDATE_FLASH; +#pragma pack() + +#pragma pack(1) +typedef struct _SYM_GET_PROPERTY +{ + UINT64 PtrName; + UINT64 PtrBuffer; + UINT32 NameLen; + UINT32 BufferLen; + UINT32 PropertyLen; +} SYM_GET_PROPERTY, * PTR_SYM_GET_PROPERTY; +#pragma pack() + +#define SYM_PASS_THRU_NONE 0 +#define SYM_PASS_THRU_READ 1 +#define SYM_PASS_THRU_WRITE 2 +#define SYM_PASS_THRU_BOTH 3 + +#pragma pack(1) +typedef struct _SYM_PASS_THRU +{ + UINT64 PtrRequest; + UINT64 PtrReply; + UINT64 PtrData; + UINT32 RequestSize; + UINT32 ReplySize; + UINT32 DataSize; + UINT32 DataDirection; + UINT64 PtrDataOut; + UINT32 DataOutSize; +} SYM_PASS_THRU, * PTR_SYM_PASS_THRU; +#pragma pack() + +#pragma pack(1) +typedef struct _SYM_PASS_THRU_TIMEOUT +{ + UINT64 PtrRequest; + UINT64 PtrReply; + UINT64 PtrData; + UINT32 RequestSize; + UINT32 ReplySize; + UINT32 DataSize; + UINT32 DataDirection; + UINT64 PtrDataOut; + UINT32 DataOutSize; + UINT32 Timeout; +} SYM_PASS_THRU_TIMEOUT, * PTR_SYM_PASS_THRU_TIMEOUT; +#pragma pack() + +#define REG_IO_READ 1 +#define REG_IO_WRITE 2 +#define REG_MEM_READ 3 +#define REG_MEM_WRITE 4 + +#pragma pack(1) +typedef struct _SYM_REG_ACCESS +{ + UINT32 Command; + UINT32 RegOffset; + UINT32 RegData; +} SYM_REG_ACCESS, * PTR_SYM_REG_ACCESS; +#pragma pack() + +#pragma pack(1) +typedef struct _SYM_EVENT_QUERY +{ + UINT32 Entries; + UINT32 Types; +} SYM_EVENT_QUERY, * PTR_SYM_EVENT_QUERY; +#pragma pack() + +#pragma pack(1) +typedef struct _SYM_EVENT_ENABLE +{ + UINT32 Types; +} SYM_EVENT_ENABLE, * PTR_SYM_EVENT_ENABLE; +#pragma pack() + +#if defined TARGET_MPT2 +#define EVENT_ENTRY_NUM 48 +#else +#define EVENT_ENTRY_NUM 2 +#endif + +#pragma pack(1) +typedef struct _SYM_EVENT_ENTRY +{ + UINT32 Type; + UINT32 Number; + UINT32 Data[EVENT_ENTRY_NUM]; +} SYM_EVENT_ENTRY, * PTR_SYM_EVENT_ENTRY; +#pragma pack() + +#pragma pack(1) +typedef struct _SYM_EVENT_REPORT +{ + UINT32 Size; + SYM_EVENT_ENTRY Events[1]; +} SYM_EVENT_REPORT, * PTR_SYM_EVENT_REPORT; +#pragma pack() + +#pragma pack(1) +typedef struct _SYM_PCI_INFO +{ + UINT32 BusNumber; + UINT8 DeviceNumber; + UINT8 FunctionNumber; + UINT16 InterruptVector; + UINT8 PciHeader[256]; +} SYM_PCI_INFO, * PTR_SYM_PCI_INFO; +#pragma pack() + +#pragma pack(1) +typedef struct _SYM_BTDH_MAPPING +{ + UINT16 TargetID; + UINT16 Bus; + UINT16 DevHandle; + UINT16 Reserved; +} SYM_BTDH_MAPPING, * PTR_SYM_BTDH_MAPPING; +#pragma pack() + +#pragma pack(1) +typedef struct _SYM_DIAG_ACTION +{ + UINT32 Action; + UINT32 Length; + UINT64 PtrDiagAction; + UINT32 ReturnCode; +} SYM_DIAG_ACTION, * PTR_SYM_DIAG_ACTION; +#pragma pack() + +#define FW_DIAGNOSTIC_BUFFER_COUNT (3) +#define FW_DIAGNOSTIC_UID_NOT_FOUND (0xFF) + +#define MPI_FW_DIAG_NEW (0x806E6577) + +#define MPI_FW_DIAG_TYPE_REGISTER (0x00000001) +#define MPI_FW_DIAG_TYPE_UNREGISTER (0x00000002) +#define MPI_FW_DIAG_TYPE_QUERY (0x00000003) +#define MPI_FW_DIAG_TYPE_READ_BUFFER (0x00000004) +#define MPI_FW_DIAG_TYPE_RELEASE (0x00000005) + +#define MPI_FW_DIAG_INVALID_UID (0x00000000) + +#define MPI_FW_DIAG_ERROR_SUCCESS (0x00000000) +#define MPI_FW_DIAG_ERROR_FAILURE (0x00000001) +#define MPI_FW_DIAG_ERROR_INVALID_PARAMETER (0x00000002) +#define MPI_FW_DIAG_ERROR_POST_FAILED (0x00000010) +#define MPI_FW_DIAG_ERROR_INVALID_UID (0x00000011) +#define MPI_FW_DIAG_ERROR_RELEASE_FAILED (0x00000012) +#define MPI_FW_DIAG_ERROR_NO_BUFFER (0x00000013) +#define MPI_FW_DIAG_ERROR_ALREADY_RELEASED (0x00000014) + +#pragma pack(1) +typedef struct _MPI_FW_DIAG_REGISTER +{ + UINT8 TraceLevel; + UINT8 BufferType; + UINT16 Flags; + UINT32 ExtendedType; + UINT32 ProductSpecific[4]; + UINT32 RequestedBufferSize; + UINT32 UniqueId; +} MPI_FW_DIAG_REGISTER, * PTR_MPI_FW_DIAG_REGISTER; +#pragma pack() + +#pragma pack(1) +typedef struct _MPI_FW_DIAG_UNREGISTER +{ + UINT32 UniqueId; +} MPI_FW_DIAG_UNREGISTER, * PTR_MPI_FW_DIAG_UNREGISTER; +#pragma pack() + +#define MPI_FW_DIAG_FLAG_APP_OWNED (0x0001) +#define MPI_FW_DIAG_FLAG_BUFFER_VALID (0x0002) +#define MPI_FW_DIAG_FLAG_FW_BUFFER_ACCESS (0x0004) + +#pragma pack(1) +typedef struct _MPI_FW_DIAG_QUERY +{ + UINT8 TraceLevel; + UINT8 BufferType; + UINT16 Flags; + UINT32 ExtendedType; + UINT32 ProductSpecific[4]; + UINT32 TotalBufferSize; + UINT32 DriverAddedBufferSize; + UINT32 UniqueId; +} MPI_FW_DIAG_QUERY, * PTR_MPI_FW_DIAG_QUERY; +#pragma pack() + +#pragma pack(1) +typedef struct _MPI_FW_DIAG_RELEASE +{ + UINT32 UniqueId; +} MPI_FW_DIAG_RELEASE, * PTR_MPI_FW_DIAG_RELEASE; +#pragma pack() + +#define MPI_FW_DIAG_FLAG_REREGISTER (0x0001) +#define MPI_FW_DIAG_FLAG_FORCE_RELEASE (0x0002) + +#pragma pack(1) +typedef struct _MPI_FW_DIAG_READ_BUFFER +{ + UINT8 Status; + UINT8 Reserved; + UINT16 Flags; + UINT32 StartingOffset; + UINT32 BytesToRead; + UINT32 UniqueId; + UINT32 DataBuffer[1]; +} MPI_FW_DIAG_READ_BUFFER, * PTR_MPI_FW_DIAG_READ_BUFFER; +#pragma pack() + +#endif diff --git a/source/inc/getopt.h b/source/inc/getopt.h new file mode 100755 index 0000000..0d3c6e2 --- /dev/null +++ b/source/inc/getopt.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * * + * Copyright 2012 LSI Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Corporation. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Corporation. * + * * + *************************************************************************** +*/ + +#if !EFI +#include +#include +#include +#endif + +#ifndef _GETOPT_ +#define _GETOPT_ + +int getopt(int argc, char *argv[], char *optstring); + +extern char *optarg; /* returned arg to go with this option */ +extern int optind; /* index to next argv element to process */ +extern int opterr; /* should error messages be printed? */ +extern int optopt; + +#define BADCH ('?') + +#endif /* _GETOPT */ diff --git a/source/inc/helper.h b/source/inc/helper.h new file mode 100755 index 0000000..ae6043d --- /dev/null +++ b/source/inc/helper.h @@ -0,0 +1,146 @@ +/*************************************************************************** + * * + * Copyright 2012 LSI Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Corporation. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Corporation. * + * * + *************************************************************************** +*/ + +#if EFIEBC +#define EFI_SPECIFICATION_VERSION 0x0001000A +#define TIANO_RELEASE_VERSION 0x00080006 +#include "efibind.h" +#include "efitypes.h" +#include "eficommon.h" +#include "efiapi.h" +#include "efierror.h" +#include "efistdarg.h" +#include "efishelllib.h" +#define DevicePathToStr LibDevicePathToStr +#define LibFileInfo LibGetFileInfo +#define GenericFileInfo gEfiFileInfoGuid +#define InitializeShellApplication LibInitializeShellApplication +#define LoadedImageProtocol gEfiLoadedImageProtocolGuid +#define EFIERR_OEM(x) EFIERR(x+1000) +#define EFI_LOADED_IMAGE EFI_LOADED_IMAGE_PROTOCOL +#define EFI_FILE_IO_INTERFACE EFI_SIMPLE_FILE_SYSTEM_PROTOCOL +#define SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID +#define EVT_TIMER EFI_EVENT_TIMER +#define va_start VA_START +#define va_arg VA_ARG +#define va_end VA_END +#define va_list VA_LIST +#else +#include "efi.h" +#include "efilib.h" +#include "efistdarg.h" +#include "shell.h" +#endif +#if EFI32 +typedef unsigned int size_t; +#endif +// ctype.h +int isalnum(int c); +int isalpha(int c); +int isascii(int c); +int isblank(int c); +int iscntrl(int c); +int isdigit(int c); +int isgraph(int c); +int islower(int c); +int isprint(int c); +int ispunct(int c); +int isspace(int c); +int isupper(int c); +int isxdigit(int c); +int toupper(int c); +int tolower(int c); +// errno.h +extern int errno; +#define EFAULT 14 +#define ENODEV 19 +#define EINVAL 22 + +// fcntl.h +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +// sttdef.h +#define offsetof(s, m) (size_t)(&(((s *)0)->m)) +// stdio.h +#define EOF 0 +typedef void * FILE; +#define stdin (void *)1 +#define stdout (void *)2 +#define stderr (void *)3 +int fgetc(FILE *stream); +char *fgets(char *s, int size, FILE *stream); +int getc(FILE *stream); +int getchar(void); +char *gets(char *s); +int ungetc(int c, FILE *stream); +int vsprintf(char *s, const char *format, va_list args); +int printf(const char *format, ...); +int fprintf(FILE *stream, const char *format, ...); +int sprintf(char *str, const char *format, ...); +int scanf(const char *format, ...); +int fscanf(FILE *stream, const char *format, ...); +int sscanf(const char *str, const char *format, ...); +FILE *fopen(const char *path, const char *mode); +int fclose(FILE *stream); +int fputs(const char *s, FILE *stream); +int fputc(int c, FILE *stream); +void perror(const char *s); +int fflush(FILE *stream); +// stdlib.h +void *malloc(size_t size); +void free(void *ptr); +void *realloc(void *ptr, size_t size); +void exit(int status); +int rand(void); +// string.h +void *memset(void *s, int c, size_t n); +void *memcpy(void *dest, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t n); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +size_t strlen(const char *s); +char *strcat(char *dest, const char *src); +char *strncat(char *dest, const char *src, size_t n); +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); +// strings.h +int strcasecmp(const char *s1, const char *s2); +int strncasecmp(const char *s1, const char *s2, size_t n); +void bzero(void *s, size_t n); +void bcopy(const void *src, void *dest, size_t n); +// sys/stat.h +typedef size_t off_t; +struct stat { + off_t st_size; /* total size, in bytes */ +}; +int stat(const char *file_name, struct stat *buf); +int fstat(int filedes, struct stat *buf); +// time.h +typedef unsigned long time_t; +time_t time(time_t *t); +char *ctime(const time_t *t); +void mdelay(int milliseconds); +void udelay(int microseconds); +// unistd.h +typedef int ssize_t; +typedef int mode_t; +unsigned int sleep(unsigned int seconds); +int open(const char *pathname, int flags, ...); +int close(int fd); +ssize_t read(int fd, void *buf, size_t count); +ssize_t write(int fd, const void *buf, size_t count); diff --git a/source/inc/mpt2sas_ctl.h b/source/inc/mpt2sas_ctl.h new file mode 100755 index 0000000..ba87fb4 --- /dev/null +++ b/source/inc/mpt2sas_ctl.h @@ -0,0 +1,398 @@ +/*************************************************************************** + * * + * Copyright 2012 LSI Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Corporation. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Corporation. * + * * + *************************************************************************** +*/ + +#ifndef MPT2SAS_CTL_H_INCLUDED +#define MPT2SAS_CTL_H_INCLUDED + +#ifdef __KERNEL__ +#include +#endif + +/** + * NOTE + * FWDOWNLOAD - PR is let me know if we need to implement this + * DIAGBUFFER - PR said hold off + */ + +/** + * HACK - changeme (MPT_MINOR = 220 ) + */ +#ifndef MPT2SAS_MINOR +#define MPT2SAS_MINOR (MPT_MINOR + 1) +#endif +#define MPT2SAS_DEV_NAME "mpt2ctl" +#define MPT2_MAGIC_NUMBER 'L' +#define MPT2_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */ + +/** + * IOCTL opcodes + */ +#define MPT2IOCINFO _IOWR(MPT2_MAGIC_NUMBER, 17, \ + struct mpt2_ioctl_iocinfo) +#define MPT2COMMAND _IOWR(MPT2_MAGIC_NUMBER, 20, \ + struct mpt2_ioctl_command) +#ifdef CONFIG_COMPAT +#define MPT2COMMAND32 _IOWR(MPT2_MAGIC_NUMBER, 20, \ + struct mpt2_ioctl_command32) +#endif +#define MPT2EVENTQUERY _IOWR(MPT2_MAGIC_NUMBER, 21, \ + struct mpt2_ioctl_eventquery) +#define MPT2EVENTENABLE _IOWR(MPT2_MAGIC_NUMBER, 22, \ + struct mpt2_ioctl_eventenable) +#define MPT2EVENTREPORT _IOWR(MPT2_MAGIC_NUMBER, 23, \ + struct mpt2_ioctl_eventreport) +#define MPT2HARDRESET _IOWR(MPT2_MAGIC_NUMBER, 24, \ + struct mpt2_ioctl_diag_reset) +#define MPT2BTDHMAPPING _IOWR(MPT2_MAGIC_NUMBER, 31, \ + struct mpt2_ioctl_btdh_mapping) + +/* diag buffer support */ +#define MPT2DIAGREGISTER _IOWR(MPT2_MAGIC_NUMBER, 26, \ + struct mpt2_diag_register) +#define MPT2DIAGRELEASE _IOWR(MPT2_MAGIC_NUMBER, 27, \ + struct mpt2_diag_release) +#define MPT2DIAGUNREGISTER _IOWR(MPT2_MAGIC_NUMBER, 28, \ + struct mpt2_diag_unregister) +#define MPT2DIAGQUERY _IOWR(MPT2_MAGIC_NUMBER, 29, \ + struct mpt2_diag_query) +#define MPT2DIAGREADBUFFER _IOWR(MPT2_MAGIC_NUMBER, 30, \ + struct mpt2_diag_read_buffer) + +/** + * struct mpt2_ioctl_header - main header structure + * @ioc_number - IOC unit number + * @port_number - IOC port number + * @max_data_size - maximum number bytes to transfer on read + */ +struct mpt2_ioctl_header { + uint32_t ioc_number; + uint32_t port_number; + uint32_t max_data_size; +}; + +/** + * struct mpt2_ioctl_diag_reset - diagnostic reset + * @hdr - generic header + */ +struct mpt2_ioctl_diag_reset { + struct mpt2_ioctl_header hdr; +}; + + +/** + * struct mpt2_ioctl_pci_info - pci device info + * @device - pci device id + * @function - pci function id + * @bus - pci bus id + * @segment_id - pci segment id + */ +struct mpt2_ioctl_pci_info { + union { + struct { + uint32_t device:5; + uint32_t function:3; + uint32_t bus:24; + } bits; + uint32_t word; + } u; + uint32_t segment_id; +}; + + +#define MPT2_IOCTL_INTERFACE_SCSI (0x00) +#define MPT2_IOCTL_INTERFACE_FC (0x01) +#define MPT2_IOCTL_INTERFACE_FC_IP (0x02) +#define MPT2_IOCTL_INTERFACE_SAS (0x03) +#define MPT2_IOCTL_INTERFACE_SAS2 (0x04) +#define MPT2_IOCTL_VERSION_LENGTH (32) + +/** + * struct mpt2_ioctl_iocinfo - generic controller info + * @hdr - generic header + * @adapter_type - type of adapter (spi, fc, sas) + * @port_number - port number + * @pci_id - PCI Id + * @hw_rev - hardware revision + * @sub_system_device - PCI subsystem Device ID + * @sub_system_vendor - PCI subsystem Vendor ID + * @rsvd0 - reserved + * @firmware_version - firmware version + * @bios_version - BIOS version + * @driver_version - driver version - 32 ASCII characters + * @rsvd1 - reserved + * @scsi_id - scsi id of adapter 0 + * @rsvd2 - reserved + * @pci_information - pci info (2nd revision) + */ +struct mpt2_ioctl_iocinfo { + struct mpt2_ioctl_header hdr; + uint32_t adapter_type; + uint32_t port_number; + uint32_t pci_id; + uint32_t hw_rev; + uint32_t subsystem_device; + uint32_t subsystem_vendor; + uint32_t rsvd0; + uint32_t firmware_version; + uint32_t bios_version; + uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH]; + uint8_t rsvd1; + uint8_t scsi_id; + uint16_t rsvd2; + struct mpt2_ioctl_pci_info pci_information; +}; + + +/* number of event log entries */ +#define MPT2SAS_CTL_EVENT_LOG_SIZE (50) + +/** + * struct mpt2_ioctl_eventquery - query event count and type + * @hdr - generic header + * @event_entries - number of events returned by get_event_report + * @rsvd - reserved + * @event_types - type of events currently being captured + */ +struct mpt2_ioctl_eventquery { + struct mpt2_ioctl_header hdr; + uint16_t event_entries; + uint16_t rsvd; + uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; +}; + +/** + * struct mpt2_ioctl_eventenable - enable/disable event capturing + * @hdr - generic header + * @event_types - toggle off/on type of events to be captured + */ +struct mpt2_ioctl_eventenable { + struct mpt2_ioctl_header hdr; + uint32_t event_types[4]; +}; + +#define MPT2_EVENT_DATA_SIZE (192) +/** + * struct MPT2_IOCTL_EVENTS - + * @event - the event that was reported + * @context - unique value for each event assigned by driver + * @data - event data returned in fw reply message + */ +struct MPT2_IOCTL_EVENTS { + uint32_t event; + uint32_t context; + uint8_t data[MPT2_EVENT_DATA_SIZE]; +}; + +/** + * struct mpt2_ioctl_eventreport - returing event log + * @hdr - generic header + * @event_data - (see struct MPT2_IOCTL_EVENTS) + */ +struct mpt2_ioctl_eventreport { + struct mpt2_ioctl_header hdr; + struct MPT2_IOCTL_EVENTS event_data[1]; +}; + +/** + * struct mpt2_ioctl_command - generic mpt firmware passthru ioclt + * @hdr - generic header + * @timeout - command timeout in seconds. (if zero then use driver default + * value). + * @reply_frame_buf_ptr - reply location + * @data_in_buf_ptr - destination for read + * @data_out_buf_ptr - data source for write + * @sense_data_ptr - sense data location + * @max_reply_bytes - maximum number of reply bytes to be sent to app. + * @data_in_size - number bytes for data transfer in (read) + * @data_out_size - number bytes for data transfer out (write) + * @max_sense_bytes - maximum number of bytes for auto sense buffers + * @data_sge_offset - offset in words from the start of the request message to + * the first SGL + * @mf[1]; + */ +struct mpt2_ioctl_command { + struct mpt2_ioctl_header hdr; + uint32_t timeout; + void __user *reply_frame_buf_ptr; + void __user *data_in_buf_ptr; + void __user *data_out_buf_ptr; + void __user *sense_data_ptr; + uint32_t max_reply_bytes; + uint32_t data_in_size; + uint32_t data_out_size; + uint32_t max_sense_bytes; + uint32_t data_sge_offset; + uint8_t mf[1]; +}; + +#ifdef CONFIG_COMPAT +struct mpt2_ioctl_command32 { + struct mpt2_ioctl_header hdr; + uint32_t timeout; + uint32_t reply_frame_buf_ptr; + uint32_t data_in_buf_ptr; + uint32_t data_out_buf_ptr; + uint32_t sense_data_ptr; + uint32_t max_reply_bytes; + uint32_t data_in_size; + uint32_t data_out_size; + uint32_t max_sense_bytes; + uint32_t data_sge_offset; + uint8_t mf[1]; +}; +#endif + +/** + * struct mpt2_ioctl_btdh_mapping - mapping info + * @hdr - generic header + * @id - target device identification number + * @bus - SCSI bus number that the target device exists on + * @handle - device handle for the target device + * @rsvd - reserved + * + * To obtain a bus/id the application sets + * handle to valid handle, and bus/id to 0xFFFF. + * + * To obtain the device handle the application sets + * bus/id valid value, and the handle to 0xFFFF. + */ +struct mpt2_ioctl_btdh_mapping { + struct mpt2_ioctl_header hdr; + uint32_t id; + uint32_t bus; + uint16_t handle; + uint16_t rsvd; +}; + + +/* status bits for ioc->diag_buffer_status */ +#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01) +#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02) +#define MPT2_DIAG_BUFFER_IS_DIAG_RESET (0x04) + +/* application flags for mpt2_diag_register, mpt2_diag_query */ +#define MPT2_APP_FLAGS_APP_OWNED (0x0001) +#define MPT2_APP_FLAGS_BUFFER_VALID (0x0002) +#define MPT2_APP_FLAGS_FW_BUFFER_ACCESS (0x0004) + +/* flags for mpt2_diag_read_buffer */ +#define MPT2_FLAGS_REREGISTER (0x0001) + +#define MPT2_PRODUCT_SPECIFIC_DWORDS 23 + +/** + * struct mpt2_diag_register - application register with driver + * @hdr - generic header + * @reserved - + * @buffer_type - specifies either TRACE or SNAPSHOT + * @application_flags - misc flags + * @diagnostic_flags - specifies flags affecting command processing + * @product_specific - product specific information + * @requested_buffer_size - buffers size in bytes + * @unique_id - tag specified by application that is used to signal ownership + * of the buffer. + * + * This will allow the driver to setup any required buffers that will be + * needed by firmware to communicate with the driver. + */ +struct mpt2_diag_register { + struct mpt2_ioctl_header hdr; + uint8_t reserved; + uint8_t buffer_type; + uint16_t application_flags; + uint32_t diagnostic_flags; + uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS]; + uint32_t requested_buffer_size; + uint32_t unique_id; +}; + +/** + * struct mpt2_diag_unregister - application unregister with driver + * @hdr - generic header + * @unique_id - tag uniquely identifies the buffer to be unregistered + * + * This will allow the driver to cleanup any memory allocated for diag + * messages and to free up any resources. + */ +struct mpt2_diag_unregister { + struct mpt2_ioctl_header hdr; + uint32_t unique_id; +}; + +/** + * struct mpt2_diag_query - query relevant info associated with diag buffers + * @hdr - generic header + * @reserved - + * @buffer_type - specifies either TRACE or SNAPSHOT + * @application_flags - misc flags + * @diagnostic_flags - specifies flags affecting command processing + * @product_specific - product specific information + * @total_buffer_size - diag buffer size in bytes + * @driver_added_buffer_size - size of extra space appended to end of buffer + * @unique_id - unique id associated with this buffer. + * + * The application will send only buffer_type and unique_id. Driver will + * inspect unique_id first, if valid, fill in all the info. If unique_id is + * 0x00, the driver will return info specified by Buffer Type. + */ +struct mpt2_diag_query { + struct mpt2_ioctl_header hdr; + uint8_t reserved; + uint8_t buffer_type; + uint16_t application_flags; + uint32_t diagnostic_flags; + uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS]; + uint32_t total_buffer_size; + uint32_t driver_added_buffer_size; + uint32_t unique_id; +}; + +/** + * struct mpt2_diag_release - request to send Diag Release Message to firmware + * @hdr - generic header + * @unique_id - tag uniquely identifies the buffer to be released + * + * This allows ownership of the specified buffer to returned to the driver, + * allowing an application to read the buffer without fear that firmware is + * overwritting information in the buffer. + */ +struct mpt2_diag_release { + struct mpt2_ioctl_header hdr; + uint32_t unique_id; +}; + +/** + * struct mpt2_diag_read_buffer - request for copy of the diag buffer + * @hdr - generic header + * @status - + * @reserved - + * @flags - misc flags + * @starting_offset - starting offset within drivers buffer where to start + * reading data at into the specified application buffer + * @bytes_to_read - number of bytes to copy from the drivers buffer into the + * application buffer starting at starting_offset. + * @unique_id - unique id associated with this buffer. + * @diagnostic_data - data payload + */ +struct mpt2_diag_read_buffer { + struct mpt2_ioctl_header hdr; + uint8_t status; + uint8_t reserved; + uint16_t flags; + uint32_t starting_offset; + uint32_t bytes_to_read; + uint32_t unique_id; + uint32_t diagnostic_data[1]; +}; + +#endif /* MPT2SAS_CTL_H_INCLUDED */ diff --git a/source/inc/mptctl.h b/source/inc/mptctl.h new file mode 100755 index 0000000..1765698 --- /dev/null +++ b/source/inc/mptctl.h @@ -0,0 +1,567 @@ +/*************************************************************************** + * * + * Copyright 2012 LSI Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Corporation. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Corporation. * + * * + *************************************************************************** +*/ + +#ifndef MPTCTL_H_INCLUDED +#define MPTCTL_H_INCLUDED +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +#include "linux/version.h" +#include "../lsi/mpi_ioc.h" + + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * + */ +#define MPT_MISCDEV_BASENAME "mptctl" +#define MPT_MISCDEV_PATHNAME "/dev/" MPT_MISCDEV_BASENAME +#define MPT_CSMI_DESCRIPTION "LSI Logic Corporation: Fusion MPT Driver " MPT_LINUX_VERSION_COMMON + +#define MPT_PRODUCT_LENGTH 12 + +/* + * Generic MPT Control IOCTLs and structures + */ +#define MPT_MAGIC_NUMBER 'm' + +#define MPTRWPERF _IOWR(MPT_MAGIC_NUMBER,0,struct mpt_raw_r_w) + +#define MPTFWDOWNLOAD _IOWR(MPT_MAGIC_NUMBER,15,struct mpt_fw_xfer) +#define MPTFWDOWNLOADBOOT _IOWR(MPT_MAGIC_NUMBER,16,struct mpt_fw_xfer) +#define MPTCOMMAND _IOWR(MPT_MAGIC_NUMBER,20,struct mpt_ioctl_command) + +#if defined(__KERNEL__) && defined(MPT_CONFIG_COMPAT) +#define MPTFWDOWNLOAD32 _IOWR(MPT_MAGIC_NUMBER,15,struct mpt_fw_xfer32) +#define MPTCOMMAND32 _IOWR(MPT_MAGIC_NUMBER,20,struct mpt_ioctl_command32) +#endif + +#define MPTIOCINFO _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo) +#define MPTIOCINFO1 _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo_rev0) +#define MPTIOCINFO2 _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo_rev1) +#define MPTTARGETINFO _IOWR(MPT_MAGIC_NUMBER,18,struct mpt_ioctl_targetinfo) +#define MPTTEST _IOWR(MPT_MAGIC_NUMBER,19,struct mpt_ioctl_test) +#define MPTEVENTQUERY _IOWR(MPT_MAGIC_NUMBER,21,struct mpt_ioctl_eventquery) +#define MPTEVENTENABLE _IOWR(MPT_MAGIC_NUMBER,22,struct mpt_ioctl_eventenable) +#define MPTEVENTREPORT _IOWR(MPT_MAGIC_NUMBER,23,struct mpt_ioctl_eventreport) +#define MPTHARDRESET _IOWR(MPT_MAGIC_NUMBER,24,struct mpt_ioctl_diag_reset) +#define MPTFWREPLACE _IOWR(MPT_MAGIC_NUMBER,25,struct mpt_ioctl_replace_fw) +#define MPTDIAGREGISTER _IOWR(MPT_MAGIC_NUMBER,26,mpt_diag_register_t) +#define MPTDIAGRELEASE _IOWR(MPT_MAGIC_NUMBER,27,mpt_diag_release_t) +#define MPTDIAGUNREGISTER _IOWR(MPT_MAGIC_NUMBER,28,mpt_diag_unregister_t) +#define MPTDIAGQUERY _IOWR(MPT_MAGIC_NUMBER,29,mpt_diag_query_t) +#define MPTDIAGREADBUFFER _IOWR(MPT_MAGIC_NUMBER,30,mpt_diag_read_buffer_t) +#define MPTHBAPCIINFO _IOWR(MPT_MAGIC_NUMBER,31,struct mpt_ioctl_hbapciinfo) +#define MPTDIAGRESET _IOWR(MPT_MAGIC_NUMBER,32,struct mpt_ioctl_diag_reset) + +/* + * SPARC PLATFORM REMARKS: + * IOCTL data structures that contain pointers + * will have different sizes in the driver and applications + * (as the app. will not use 8-byte pointers). + * Apps should use MPTFWDOWNLOAD and MPTCOMMAND. + * The driver will convert data from + * mpt_fw_xfer32 (mpt_ioctl_command32) to mpt_fw_xfer (mpt_ioctl_command) + * internally. + * + * If data structures change size, must handle as in IOCGETINFO. + */ +struct mpt_fw_xfer { + unsigned int iocnum; /* IOC unit number */ + unsigned int fwlen; + void *bufp; /* Pointer to firmware buffer */ +}; + +#if defined(__KERNEL__) && defined(MPT_CONFIG_COMPAT) +struct mpt_fw_xfer32 { + unsigned int iocnum; + unsigned int fwlen; + U32 bufp; +}; +#endif /*}*/ + +/* + * IOCTL header structure. + * iocnum - must be defined. + * port - must be defined for all IOCTL commands other than MPTIOCINFO + * maxDataSize - ignored on MPTCOMMAND commands + * - ignored on MPTFWREPLACE commands + * - on query commands, reports the maximum number of bytes to be returned + * to the host driver (count includes the header). + * That is, set to sizeof(struct mpt_ioctl_iocinfo) for fixed sized commands. + * Set to sizeof(struct mpt_ioctl_targetinfo) + datasize for variable + * sized commands. (MPTTARGETINFO, MPTEVENTREPORT) + */ +typedef struct _mpt_ioctl_header { + unsigned int iocnum; /* IOC unit number */ + unsigned int port; /* IOC port number */ + int maxDataSize; /* Maximum Num. bytes to transfer on read */ +} mpt_ioctl_header; + +/* + * Issue a diagnostic reset + */ +struct mpt_ioctl_diag_reset { + mpt_ioctl_header hdr; +}; + + +/* + * PCI bus/device/function information structure. + */ +struct mpt_ioctl_pci_info { + union { + struct { + unsigned int deviceNumber : 5; + unsigned int functionNumber : 3; + unsigned int busNumber : 24; + } bits; + unsigned int asUlong; + } u; +}; + +struct mpt_ioctl_pci_info2 { + union { + struct { + unsigned int deviceNumber : 5; + unsigned int functionNumber : 3; + unsigned int busNumber : 24; + } bits; + unsigned int asUlong; + } u; + int segmentID; +}; + +/* + * Adapter Information Page + * Read only. + * Data starts at offset 0xC + */ +#define MPT_IOCTL_INTERFACE_SCSI (0x00) +#define MPT_IOCTL_INTERFACE_FC (0x01) +#define MPT_IOCTL_INTERFACE_SAS (0x03) +#define MPT_IOCTL_VERSION_LENGTH (32) + +struct mpt_ioctl_iocinfo { + mpt_ioctl_header hdr; + int adapterType; /* SCSI or FCP */ + int port; /* port number */ + int pciId; /* PCI Id. */ + int hwRev; /* hardware revision */ + int subSystemDevice; /* PCI subsystem Device ID */ + int subSystemVendor; /* PCI subsystem Vendor ID */ + int numDevices; /* number of devices */ + int FWVersion; /* FW Version (integer) */ + int BIOSVersion; /* BIOS Version (integer) */ + char driverVersion[MPT_IOCTL_VERSION_LENGTH]; /* Driver Version (string) */ + char busChangeEvent; + char hostId; + char rsvd[2]; + struct mpt_ioctl_pci_info2 pciInfo; /* Added Rev 2 */ +}; + +struct mpt_ioctl_iocinfo_rev1 { + mpt_ioctl_header hdr; + int adapterType; /* SCSI or FCP */ + int port; /* port number */ + int pciId; /* PCI Id. */ + int hwRev; /* hardware revision */ + int subSystemDevice; /* PCI subsystem Device ID */ + int subSystemVendor; /* PCI subsystem Vendor ID */ + int numDevices; /* number of devices */ + int FWVersion; /* FW Version (integer) */ + int BIOSVersion; /* BIOS Version (integer) */ + char driverVersion[MPT_IOCTL_VERSION_LENGTH]; /* Driver Version (string) */ + char busChangeEvent; + char hostId; + char rsvd[2]; + struct mpt_ioctl_pci_info pciInfo; /* Added Rev 1 */ +}; + +/* Original structure, must always accept these + * IOCTLs. 4 byte pads can occur based on arch with + * above structure. Wish to re-align, but cannot. + */ +struct mpt_ioctl_iocinfo_rev0 { + mpt_ioctl_header hdr; + int adapterType; /* SCSI or FCP */ + int port; /* port number */ + int pciId; /* PCI Id. */ + int hwRev; /* hardware revision */ + int subSystemDevice; /* PCI subsystem Device ID */ + int subSystemVendor; /* PCI subsystem Vendor ID */ + int numDevices; /* number of devices */ + int FWVersion; /* FW Version (integer) */ + int BIOSVersion; /* BIOS Version (integer) */ + char driverVersion[MPT_IOCTL_VERSION_LENGTH]; /* Driver Version (string) */ + char busChangeEvent; + char hostId; + char rsvd[2]; +}; + +/* + * Device Information Page + * Report the number of, and ids of, all targets + * on this IOC. The ids array is a packed structure + * of the known targetInfo. + * bits 31-24: reserved + * 23-16: LUN + * 15- 8: Bus Number + * 7- 0: Target ID + */ +struct mpt_ioctl_targetinfo { + mpt_ioctl_header hdr; + int numDevices; /* Num targets on this ioc */ + int targetInfo[1]; +}; + + +/* + * Event reporting IOCTL's. These IOCTL's will + * use the following defines: + */ +struct mpt_ioctl_eventquery { + mpt_ioctl_header hdr; + unsigned short eventEntries; + unsigned short reserved; + unsigned int eventTypes; +}; + +struct mpt_ioctl_eventenable { + mpt_ioctl_header hdr; + unsigned int eventTypes; +}; + +#ifndef __KERNEL__ +typedef struct { + uint event; + uint eventContext; + uint data[2]; +} MPT_IOCTL_EVENTS; +#endif + +struct mpt_ioctl_eventreport { + mpt_ioctl_header hdr; + MPT_IOCTL_EVENTS eventData[1]; +}; + +#define MPT_MAX_NAME 32 +struct mpt_ioctl_test { + mpt_ioctl_header hdr; + U8 name[MPT_MAX_NAME]; + int chip_type; + U8 product [MPT_PRODUCT_LENGTH]; +}; + +/* Replace the FW image cached in host driver memory + * newImageSize - image size in bytes + * newImage - first byte of the new image + */ +typedef struct mpt_ioctl_replace_fw { + mpt_ioctl_header hdr; + int newImageSize; + U8 newImage[1]; +} mpt_ioctl_replace_fw_t; + + +struct mpt_ioctl_mptpciinfo { + U8 iocNumber; + U8 iocState; + U8 revisionID; + U8 reserved1; + U16 vendorID; + U16 deviceID; + U16 subSystemVendorID; + U16 subSystemID; +}; + + +struct mpt_ioctl_hbapciinfo { + mpt_ioctl_header hdr; + U8 totalIOC; + U8 reserved[3]; + struct mpt_ioctl_mptpciinfo hbapciinfo[18]; +}; + + +/* General MPT Pass through data structure + * + * iocnum + * timeout - in seconds, command timeout. If 0, set by driver to + * default value. + * replyFrameBufPtr - reply location + * dataInBufPtr - destination for read + * dataOutBufPtr - data source for write + * senseDataPtr - sense data location + * maxReplyBytes - maximum number of reply bytes to be sent to app. + * dataInSize - num bytes for data transfer in (read) + * dataOutSize - num bytes for data transfer out (write) + * dataSgeOffset - offset in words from the start of the request message + * to the first SGL + * MF[1]; + * + * Remark: Some config pages have bi-directional transfer, + * both a read and a write. The basic structure allows for + * a bidirectional set up. Normal messages will have one or + * both of these buffers NULL. + */ +struct mpt_ioctl_command { + mpt_ioctl_header hdr; + int timeout; /* optional (seconds) */ + char *replyFrameBufPtr; + char *dataInBufPtr; + char *dataOutBufPtr; + char *senseDataPtr; + int maxReplyBytes; + int dataInSize; + int dataOutSize; + int maxSenseBytes; + int dataSgeOffset; + char MF[1]; +}; + +/* + * SPARC PLATFORM: See earlier remark. + */ +#if defined(__KERNEL__) && defined(MPT_CONFIG_COMPAT) +struct mpt_ioctl_command32 { + mpt_ioctl_header hdr; + int timeout; + U32 replyFrameBufPtr; + U32 dataInBufPtr; + U32 dataOutBufPtr; + U32 senseDataPtr; + int maxReplyBytes; + int dataInSize; + int dataOutSize; + int maxSenseBytes; + int dataSgeOffset; + char MF[1]; +}; +#endif /*}*/ + + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * HP Specific IOCTL Defines and Structures + */ + +#define CPQFCTS_IOC_MAGIC 'Z' +#define HP_IOC_MAGIC 'Z' +#define HP_GETHOSTINFO _IOR(HP_IOC_MAGIC, 20, hp_host_info_t) +#define HP_GETHOSTINFO1 _IOR(HP_IOC_MAGIC, 20, hp_host_info_rev0_t) +#define HP_GETTARGETINFO _IOR(HP_IOC_MAGIC, 21, hp_target_info_t) + +/* All HP IOCTLs must include this header + */ +typedef struct _hp_header { + unsigned int iocnum; + unsigned int host; + unsigned int channel; + unsigned int id; + unsigned int lun; +} hp_header_t; + +/* + * Header: + * iocnum required (input) + * host ignored + * channe ignored + * id ignored + * lun ignored + */ +typedef struct _hp_host_info { + hp_header_t hdr; + U16 vendor; + U16 device; + U16 subsystem_vendor; + U16 subsystem_id; + U8 devfn; + U8 bus; + ushort host_no; /* SCSI Host number, if scsi driver not loaded*/ + U8 fw_version[16]; /* string */ + U8 serial_number[24]; /* string */ + U32 ioc_status; + U32 bus_phys_width; + U32 base_io_addr; + U32 rsvd; + unsigned int hard_resets; /* driver initiated resets */ + unsigned int soft_resets; /* ioc, external resets */ + unsigned int timeouts; /* num timeouts */ +} hp_host_info_t; + +/* replace ulongs with uints, need to preserve backwards + * compatibility. + */ +typedef struct _hp_host_info_rev0 { + hp_header_t hdr; + U16 vendor; + U16 device; + U16 subsystem_vendor; + U16 subsystem_id; + U8 devfn; + U8 bus; + ushort host_no; /* SCSI Host number, if scsi driver not loaded*/ + U8 fw_version[16]; /* string */ + U8 serial_number[24]; /* string */ + U32 ioc_status; + U32 bus_phys_width; + U32 base_io_addr; + U32 rsvd; + unsigned long hard_resets; /* driver initiated resets */ + unsigned long soft_resets; /* ioc, external resets */ + unsigned long timeouts; /* num timeouts */ +} hp_host_info_rev0_t; + +/* + * Header: + * iocnum required (input) + * host required + * channel required (bus number) + * id required + * lun ignored + * + * All error values between 0 and 0xFFFF in size. + */ +typedef struct _hp_target_info { + hp_header_t hdr; + U32 parity_errors; + U32 phase_errors; + U32 select_timeouts; + U32 message_rejects; + U32 negotiated_speed; + U8 negotiated_width; + U8 rsvd[7]; /* 8 byte alignment */ +} hp_target_info_t; + +#define HP_STATUS_OTHER 1 +#define HP_STATUS_OK 2 +#define HP_STATUS_FAILED 3 + +#define HP_BUS_WIDTH_UNK 1 +#define HP_BUS_WIDTH_8 2 +#define HP_BUS_WIDTH_16 3 +#define HP_BUS_WIDTH_32 4 + +#define HP_DEV_SPEED_ASYNC 2 +#define HP_DEV_SPEED_FAST 3 +#define HP_DEV_SPEED_ULTRA 4 +#define HP_DEV_SPEED_ULTRA2 5 +#define HP_DEV_SPEED_ULTRA160 6 +#define HP_DEV_SPEED_SCSI1 7 +#define HP_DEV_SPEED_ULTRA320 8 + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +#define MPI_FW_DIAG_IOCTL (0x80646961) // dia +#define MPI_FW_DIAG_TYPE_REGISTER (0x00000001) +#define MPI_FW_DIAG_TYPE_UNREGISTER (0x00000002) +#define MPI_FW_DIAG_TYPE_QUERY (0x00000003) +#define MPI_FW_DIAG_TYPE_READ_BUFFER (0x00000004) +#define MPI_FW_DIAG_TYPE_RELEASE (0x00000005) + +#define MPI_FW_DIAG_INVALID_UID (0x00000000) +#define FW_DIAGNOSTIC_BUFFER_COUNT (3) +#define FW_DIAGNOSTIC_UID_NOT_FOUND (0xFF) + +#define MPI_FW_DIAG_ERROR_SUCCESS (0x00000000) +#define MPI_FW_DIAG_ERROR_FAILURE (0x00000001) +#define MPI_FW_DIAG_ERROR_INVALID_PARAMETER (0x00000002) +#define MPI_FW_DIAG_ERROR_POST_FAILED (0x00000010) +#define MPI_FW_DIAG_ERROR_INVALID_UID (0x00000011) +#define MPI_FW_DIAG_ERROR_RELEASE_FAILED (0x00000012) +#define MPI_FW_DIAG_ERROR_NO_BUFFER (0x00000013) +#define MPI_FW_DIAG_ERROR_ALREADY_RELEASED (0x00000014) + +#define MPT_DIAG_CAPABILITY(bufftype) (MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER << bufftype) + +typedef struct _MPI_FW_DIAG_REGISTER +{ + U8 TraceLevel; + U8 BufferType; + U16 Flags; + U32 ExtendedType; + U32 ProductSpecific[4]; + U32 RequestedBufferSize; + U32 UniqueId; +} MPI_FW_DIAG_REGISTER, *PTR_MPI_FW_DIAG_REGISTER; + +typedef struct _mpt_diag_register { + mpt_ioctl_header hdr; + MPI_FW_DIAG_REGISTER data; +} mpt_diag_register_t; + +typedef struct _MPI_FW_DIAG_UNREGISTER +{ + U32 UniqueId; +} MPI_FW_DIAG_UNREGISTER, *PTR_MPI_FW_DIAG_UNREGISTER; + +typedef struct _mpt_diag_unregister { + mpt_ioctl_header hdr; + MPI_FW_DIAG_UNREGISTER data; +} mpt_diag_unregister_t; + +#define MPI_FW_DIAG_FLAG_APP_OWNED (0x0001) +#define MPI_FW_DIAG_FLAG_BUFFER_VALID (0x0002) +#define MPI_FW_DIAG_FLAG_FW_BUFFER_ACCESS (0x0004) + +typedef struct _MPI_FW_DIAG_QUERY +{ + U8 TraceLevel; + U8 BufferType; + U16 Flags; + U32 ExtendedType; + U32 ProductSpecific[4]; + U32 DataSize; + U32 DriverAddedBufferSize; + U32 UniqueId; +} MPI_FW_DIAG_QUERY, *PTR_MPI_FW_DIAG_QUERY; + +typedef struct _mpt_diag_query { + mpt_ioctl_header hdr; + MPI_FW_DIAG_QUERY data; +} mpt_diag_query_t; + +typedef struct _MPI_FW_DIAG_RELEASE +{ + U32 UniqueId; +} MPI_FW_DIAG_RELEASE, *PTR_MPI_FW_DIAG_RELEASE; + +typedef struct _mpt_diag_release { + mpt_ioctl_header hdr; + MPI_FW_DIAG_RELEASE data; +} mpt_diag_release_t; + +#define MPI_FW_DIAG_FLAG_REREGISTER (0x0001) + +typedef struct _MPI_FW_DIAG_READ_BUFFER +{ + U8 Status; + U8 Reserved; + U16 Flags; + U32 StartingOffset; + U32 BytesToRead; + U32 UniqueId; + U32 DiagnosticData[1]; +} MPI_FW_DIAG_READ_BUFFER, *PTR_MPI_FW_DIAG_READ_BUFFER; + +typedef struct _mpt_diag_read_buffer { + mpt_ioctl_header hdr; + MPI_FW_DIAG_READ_BUFFER data; +} mpt_diag_read_buffer_t; + +typedef struct _mpt_FWDownload_MF { + FWDownload_t FWMessage; + U32 SGL_Word; +} mpt_FWDownload_MF_t; + +#endif diff --git a/source/inc/mptsas_ioctl.h b/source/inc/mptsas_ioctl.h new file mode 100755 index 0000000..46760d8 --- /dev/null +++ b/source/inc/mptsas_ioctl.h @@ -0,0 +1,260 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright 1998 LSI Logic Corporation. All rights reserved. + * + * This file is confidential and a trade secret of LSI Logic. The + * receipt of or possession of this file does not convey any rights to + * reproduce or disclose its contents or to manufacture, use, or sell + * anything it may describe, in whole, or in part, without the specific + * written consent of LSI Logic Corporation. + */ + +#ifndef _MPTSAS_IOCTL_H +#define _MPTSAS_IOCTL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define MPTIOCTL ('I' << 8) +#define MPTIOCTL_GET_ADAPTER_DATA (MPTIOCTL | 1) +#define MPTIOCTL_UPDATE_FLASH (MPTIOCTL | 2) +#define MPTIOCTL_RESET_ADAPTER (MPTIOCTL | 3) +#define MPTIOCTL_PASS_THRU (MPTIOCTL | 4) +#define MPTIOCTL_EVENT_QUERY (MPTIOCTL | 5) +#define MPTIOCTL_EVENT_ENABLE (MPTIOCTL | 6) +#define MPTIOCTL_EVENT_REPORT (MPTIOCTL | 7) +#define MPTIOCTL_GET_PCI_INFO (MPTIOCTL | 8) +#define MPTIOCTL_DIAG_ACTION (MPTIOCTL | 9) + +/* + * The following are our ioctl() return status values. If everything went + * well, we return good status. If the buffer length sent to us is too short + * we return a status to tell the user. + */ +#define MPTIOCTL_STATUS_GOOD 0 +#define MPTIOCTL_STATUS_LEN_TOO_SHORT 1 + +/* + * The following is the MPTIOCTL_GET_ADAPTER_DATA data structure. This data + * structure is setup so that we hopefully are properly aligned for both + * 32-bit and 64-bit mode applications. + * + * Adapter Type - Value = 4 = SCSI Protocol through SAS-2 adapter + * + * MPI Port Number - The PCI Function number for this device + * + * PCI Device HW Id - The PCI device number for this device + * + */ +#define MPTIOCTL_ADAPTER_TYPE_SAS2 4 +typedef struct mptsas_adapter_data +{ + uint32_t StructureLength; + uint32_t AdapterType; + uint32_t MpiPortNumber; + uint32_t PCIDeviceHwId; + uint32_t PCIDeviceHwRev; + uint32_t SubSystemId; + uint32_t SubsystemVendorId; + uint32_t Reserved1; + uint32_t MpiFirmwareVersion; + uint32_t BiosVersion; + uint8_t DriverVersion[32]; + uint8_t Reserved2; + uint8_t ScsiId; + uint16_t Reserved3; + uint32_t PciInformation; + uint32_t PciSegmentId; +} mptsas_adapter_data_t; + + +typedef struct mptsas_update_flash +{ + uint64_t PtrBuffer; + uint32_t ImageChecksum; + uint32_t ImageOffset; + uint32_t ImageSize; + uint32_t ImageType; +} mptsas_update_flash_t; + + +#define MPTSAS_PASS_THRU_DIRECTION_NONE 0 +#define MPTSAS_PASS_THRU_DIRECTION_READ 1 +#define MPTSAS_PASS_THRU_DIRECTION_WRITE 2 +#define MPTSAS_PASS_THRU_DIRECTION_BOTH 3 + +typedef struct mptsas_pass_thru +{ + uint64_t PtrRequest; + uint64_t PtrReply; + uint64_t PtrData; + uint32_t RequestSize; + uint32_t ReplySize; + uint32_t DataSize; + uint32_t DataDirection; + uint64_t PtrDataOut; + uint32_t DataOutSize; + uint32_t Timeout; +} mptsas_pass_thru_t; + + +/* + * Event queue defines + */ +#define MPTSAS_EVENT_QUEUE_SIZE (50) /* Max Events stored in driver */ +#define MPTSAS_MAX_EVENT_DATA_LENGTH (48) /* Size of each event in Dwords */ + +typedef struct mptsas_event_query +{ + uint16_t Entries; + uint16_t Reserved; + uint32_t Types[4]; +} mptsas_event_query_t; + +typedef struct mptsas_event_enable +{ + uint32_t Types[4]; +} mptsas_event_enable_t; + +/* + * Event record entry for ioctl. + */ +typedef struct mptsas_event_entry +{ + uint32_t Type; + uint32_t Number; + uint32_t Data[MPTSAS_MAX_EVENT_DATA_LENGTH]; +} mptsas_event_entry_t; + +typedef struct mptsas_event_report +{ + uint32_t Size; + mptsas_event_entry_t Events[1]; +} mptsas_event_report_t; + + +typedef struct mptsas_pci_info +{ + uint32_t BusNumber; + uint8_t DeviceNumber; + uint8_t FunctionNumber; + uint16_t InterruptVector; + uint8_t PciHeader[256]; +} mptsas_pci_info_t; + + +typedef struct mptsas_diag_action +{ + uint32_t Action; + uint32_t Length; + uint64_t PtrDiagAction; + uint32_t ReturnCode; +} mptsas_diag_action_t; + +#define MPTSAS_FW_DIAGNOSTIC_BUFFER_COUNT (3) +#define MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND (0xFF) + +#define MPTSAS_FW_DIAG_NEW (0x806E6577) + +#define MPTSAS_FW_DIAG_TYPE_REGISTER (0x00000001) +#define MPTSAS_FW_DIAG_TYPE_UNREGISTER (0x00000002) +#define MPTSAS_FW_DIAG_TYPE_QUERY (0x00000003) +#define MPTSAS_FW_DIAG_TYPE_READ_BUFFER (0x00000004) +#define MPTSAS_FW_DIAG_TYPE_RELEASE (0x00000005) + +#define MPTSAS_FW_DIAG_INVALID_UID (0x00000000) + +#define MPTSAS_FW_DIAG_ERROR_SUCCESS (0x00000000) +#define MPTSAS_FW_DIAG_ERROR_FAILURE (0x00000001) +#define MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER (0x00000002) +#define MPTSAS_FW_DIAG_ERROR_POST_FAILED (0x00000010) +#define MPTSAS_FW_DIAG_ERROR_INVALID_UID (0x00000011) +#define MPTSAS_FW_DIAG_ERROR_RELEASE_FAILED (0x00000012) +#define MPTSAS_FW_DIAG_ERROR_NO_BUFFER (0x00000013) +#define MPTSAS_FW_DIAG_ERROR_ALREADY_RELEASED (0x00000014) + + +typedef struct mptsas_fw_diag_register +{ + uint8_t Reserved1; + uint8_t BufferType; + uint16_t ApplicationFlags; + uint32_t DiagnosticFlags; + uint32_t ProductSpecific[23]; + uint32_t RequestedBufferSize; + uint32_t UniqueId; +} mptsas_fw_diag_register_t; + +typedef struct mptsas_fw_diag_unregister +{ + uint32_t UniqueId; +} mptsas_fw_diag_unregister_t; + +#define MPTSAS_FW_DIAG_FLAG_APP_OWNED (0x0001) +#define MPTSAS_FW_DIAG_FLAG_BUFFER_VALID (0x0002) +#define MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS (0x0004) + +typedef struct mptsas_fw_diag_query +{ + uint8_t Reserved1; + uint8_t BufferType; + uint16_t ApplicationFlags; + uint32_t DiagnosticFlags; + uint32_t ProductSpecific[23]; + uint32_t TotalBufferSize; + uint32_t DriverAddedBufferSize; + uint32_t UniqueId; +} mptsas_fw_diag_query_t; + +typedef struct mptsas_fw_diag_release +{ + uint32_t UniqueId; +} mptsas_fw_diag_release; + +#define MPTSAS_FW_DIAG_FLAG_REREGISTER (0x0001) +#define MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE (0x0002) + +typedef struct mptsas_diag_read_buffer +{ + uint8_t Status; + uint8_t Reserved; + uint16_t Flags; + uint32_t StartingOffset; + uint32_t BytesToRead; + uint32_t UniqueId; + uint32_t DataBuffer[1]; +} mptsas_diag_read_buffer_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _MPTSAS_IOCTL_H */ diff --git a/source/inc/ntddscsi.h b/source/inc/ntddscsi.h new file mode 100755 index 0000000..81a390a --- /dev/null +++ b/source/inc/ntddscsi.h @@ -0,0 +1,313 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) 1990-1999 Microsoft Corporation + +Module Name: + + ntddscsi.h + +Abstract: + + This is the include file that defines all constants and types for + accessing the SCSI port adapters. + +Author: + + Jeff Havens + +Revision History: + +--*/ + + +// +// Interface GUIDs +// +// need these GUIDs outside conditional includes so that user can +// #include in precompiled header +// #include in a single source file +// #include in that source file a second time to instantiate the GUIDs +// +#ifdef DEFINE_GUID +// +// Make sure FAR is defined... +// +#ifndef FAR +#ifdef _WIN32 +#define FAR +#else +#define FAR _far +#endif +#endif + +DEFINE_GUID(ScsiRawInterfaceGuid, 0x53f56309L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(WmiScsiAddressGuid, 0x53f5630fL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +#endif + +#ifndef _NTDDSCSIH_ +#define _NTDDSCSIH_ + +#ifdef __cplusplus +extern "C" { +#endif + +// +// Device Name - this string is the name of the device. It is the name +// that should be passed to NtOpenFile when accessing the device. +// +// Note: For devices that support multiple units, it should be suffixed +// with the Ascii representation of the unit number. +// + +#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER + +#define DD_SCSI_DEVICE_NAME "\\Device\\ScsiPort" + + +// +// NtDeviceIoControlFile IoControlCode values for this device. +// +// Warning: Remember that the low two bits of the code specify how the +// buffers are passed to the driver! +// + +#define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_RESCAN_BUS CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_GET_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0408, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_FREE_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0409, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_IDE_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x040a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +// +// Define the SCSI pass through structure. +// + +typedef struct _SCSI_PASS_THROUGH { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + ULONG_PTR DataBufferOffset; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +}SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; + +// +// Define the SCSI pass through direct structure. +// + +typedef struct _SCSI_PASS_THROUGH_DIRECT { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + PVOID DataBuffer; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +}SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; + + +// +// Define the SCSI pass through direct structure for Win64 (thunking). +// +#if defined(_WIN64) +typedef struct _SCSI_PASS_THROUGH32 { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + ULONG32 DataBufferOffset; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +}SCSI_PASS_THROUGH32, *PSCSI_PASS_THROUGH32; + +// +// Define the SCSI pass through direct structure. +// + +typedef struct _SCSI_PASS_THROUGH_DIRECT32 { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + VOID * POINTER_32 DataBuffer; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +}SCSI_PASS_THROUGH_DIRECT32, *PSCSI_PASS_THROUGH_DIRECT32; + +#endif + +// +// Define SCSI information. +// Used with the IOCTL_SCSI_GET_INQUIRY_DATA IOCTL. +// + +typedef struct _SCSI_BUS_DATA { + UCHAR NumberOfLogicalUnits; + UCHAR InitiatorBusId; + ULONG InquiryDataOffset; +}SCSI_BUS_DATA, *PSCSI_BUS_DATA; + +// +// Define SCSI adapter bus information structure.. +// Used with the IOCTL_SCSI_GET_INQUIRY_DATA IOCTL. +// + +typedef struct _SCSI_ADAPTER_BUS_INFO { + UCHAR NumberOfBuses; + SCSI_BUS_DATA BusData[1]; +} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; + +// +// Define SCSI adapter bus information. +// Used with the IOCTL_SCSI_GET_INQUIRY_DATA IOCTL. +// + +typedef struct _SCSI_INQUIRY_DATA { + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + BOOLEAN DeviceClaimed; + ULONG InquiryDataLength; + ULONG NextInquiryDataOffset; + UCHAR InquiryData[1]; +}SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; + +// +// Define header for I/O control SRB. +// + +typedef struct _SRB_IO_CONTROL { + ULONG HeaderLength; + UCHAR Signature[8]; + ULONG Timeout; + ULONG ControlCode; + ULONG ReturnCode; + ULONG Length; +} SRB_IO_CONTROL, *PSRB_IO_CONTROL; + +// +// SCSI port driver capabilities structure. +// + +typedef struct _IO_SCSI_CAPABILITIES { + + // + // Length of this structure + // + + ULONG Length; + + // + // Maximum transfer size in single SRB + // + + ULONG MaximumTransferLength; + + // + // Maximum number of physical pages per data buffer + // + + ULONG MaximumPhysicalPages; + + // + // Async calls from port to class + // + + ULONG SupportedAsynchronousEvents; + + // + // Alignment mask for data transfers. + // + + ULONG AlignmentMask; + + // + // Supports tagged queuing + // + + BOOLEAN TaggedQueuing; + + // + // Host adapter scans down for bios devices. + // + + BOOLEAN AdapterScansDown; + + // + // The host adapter uses programmed I/O. + // + + BOOLEAN AdapterUsesPio; + +} IO_SCSI_CAPABILITIES, *PIO_SCSI_CAPABILITIES; + +typedef struct _SCSI_ADDRESS { + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; +}SCSI_ADDRESS, *PSCSI_ADDRESS; + +// +// Define structure for returning crash dump pointers. +// + +struct _ADAPTER_OBJECT; + +typedef struct _DUMP_POINTERS { + struct _ADAPTER_OBJECT *AdapterObject; + PVOID MappedRegisterBase; + PVOID DumpData; + PVOID CommonBufferVa; + LARGE_INTEGER CommonBufferPa; + ULONG CommonBufferSize; + BOOLEAN AllocateCommonBuffers; + BOOLEAN UseDiskDump; + UCHAR Spare1[2]; + PVOID DeviceObject; +} DUMP_POINTERS, *PDUMP_POINTERS; + +// +// Define values for pass-through DataIn field. +// + +#define SCSI_IOCTL_DATA_OUT 0 +#define SCSI_IOCTL_DATA_IN 1 +#define SCSI_IOCTL_DATA_UNSPECIFIED 2 + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/inc/sas.h b/source/inc/sas.h new file mode 100755 index 0000000..a7297ca --- /dev/null +++ b/source/inc/sas.h @@ -0,0 +1,1886 @@ +/*************************************************************************** + * * + * Copyright 2008 LSI Logic Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Logic. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Logic Corporation. * + * * + *************************************************************************** + * + * Name: SAS.H + * Title: SAS Protocol Structures and Definitions + * Programmer: ------------- + * Creation Date: January 20, 2003 + * + * Version History + * --------------- + * + * Last Updated + * ------------- + * Version %version: 52 % + * Date Updated %date_modified: % + * Programmer %created_by: mjwang % + * + * Date Who Description + * -------- --- ------------------------------------------------------- + * 01/20/03 GWK Initial version + * 10/24/04 BDB Updated to SAS 1.1 Revision 6 + * 08/20/08 KAM updated for SDM big endian platform and gcc bitfields + * 12/09/08 RTS updated to SAS 2.0 Revision 15 + * + * + * Description + * ------------ + * This include file contains SAS protocol structures and definitions. This + * file only should include structures and definitions specific to SAS. SCSI + * CDBs used in SAS belong in scsi.h. + * + * NOTE: This version is current as of version 2.0 Rev 15 of the SAS specification. + * + * NOTE: This file is dependant on ata.h, so include ata.h before sas.h. + * + *------------------------------------------------------------------------- + */ + +/* If this header file has not been included yet */ +#ifndef SAS_H_SOURCE +#define SAS_H_SOURCE + +/* None of the frames defined included CRC. The HW deals with + * CRC and we can't access it. + */ + + +/******************************************************************************/ +/* */ +/* S A S A D D R E S S D E F I N I T I O N S */ +/* */ +/******************************************************************************/ + +/* + * SAS Address (full 8 byte WWID) + * This structure is in little endian, so a SAS address of 0x50(MSB) 08 05 EF FF FF 80 00(LSB) + * would show up here as High = 0xEF050850, Low = 0x0080FFFF + */ +#if 1 //KAM +#define SAS_WWID_LENGTH (8) +typedef union _SAS_ADDRESS +{ + U8 WWID[SAS_WWID_LENGTH]; /* 0x00 */ + struct + { + U32 High; + U32 Low; + }Word; + +} SAS_ADDRESS, *PTR_SAS_ADDRESS; +#endif + +/******************************************************************************/ +/* */ +/* S A S L U N D E F I N I T I O N */ +/* */ +/******************************************************************************/ +typedef union _SAS_LOGICAL_UNIT +{ + U8 Byte[8]; + U16 LevelAddressing[4]; + U32 Dword[2]; + struct { + U8 Reserved1; + U8 Lun; + U8 Reserved2[6]; + } SingleLevel; +} SAS_LOGICAL_UNIT, *PTR_SAS_LOGICAL_UNIT; + +/* SAS Device Type field */ +#define SAS_DEVICE_TYPE_END_DEVICE (0x01) +#define SAS_DEVICE_TYPE_EDGE_EXPANDER (0x02) +#define SAS_DEVICE_TYPE_FANOUT_EXPANDER (0x03) + + +/******************************************************************************/ +/* */ +/* S S P F R A M E D E F I N I T I O N S */ +/* */ +/******************************************************************************/ + +/* + * COMMAND Information Unit + */ +#define SAS_COMMAND_IU_CDB_LENGTH (16) +typedef struct _COMMAND_IU +{ + SAS_LOGICAL_UNIT LogicalUnitNumber; /* 0x00 */ + U8 Reserved08; /* 0x08 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 EnableFirstBurst :1; /* 0x09 */ + U8 Reserved09Bits3to6 :4; + U8 TaskAttribute :3; + U8 Reserved0A; /* 0x0A */ + U8 AdditionalCDBLength :6; /* 0x0B */ + U8 Reserved0BBits0to1 :2; +#else /* little endian */ + U8 TaskAttribute :3; /* 0x09 */ + U8 Reserved09Bits3to6 :4; + U8 EnableFirstBurst :1; + U8 Reserved0A; /* 0x0A */ + U8 Reserved0BBits0to1 :2; /* 0x0B */ + U8 AdditionalCDBLength :6; +#endif + U8 CDB[SAS_COMMAND_IU_CDB_LENGTH]; /* 0x0C */ + U32 AdditionalCDBBytes[1]; /* 0x1C */ + /* Note: AdditionalCDBBytes is variable and may really be 0 to 0x3F dwords */ +} COMMAND_IU, *PTR_COMMAND_IU; + +/* Task Attribute field */ +#define SSP_COMMAND_IU_TASK_ATTRIBUTE_SIMPLE (0x0) +#define SSP_COMMAND_IU_TASK_ATTRIBUTE_HEAD_OF_QUEUE (0x1) +#define SSP_COMMAND_IU_TASK_ATTRIBUTE_ORDERED (0x2) +#define SSP_COMMAND_IU_TASK_ATTRIBUTE_ACA (0x4) + +/* + * TASK Information Unit + */ +typedef struct _TASK_IU +{ + SAS_LOGICAL_UNIT LogicalUnitNumber; /* 0x00 */ + U8 Reserved08; /* 0x08 */ + U8 Reserved09; /* 0x09 */ + U8 TaskManagementFunction; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ + U16 TagOfTaskToBeManaged; /* 0x0C */ + U8 Reserved0Eto1B[14]; /* 0x0E */ +} TASK_IU, *PTR_TASK_IU; + +/* Task Management Function field */ +#define SSP_TASK_IU_TASK_MANAGEMENT_FUNCTION_ABORT_TASK (0x01) +#define SSP_TASK_IU_TASK_MANAGEMENT_FUNCTION_ABORT_TASK_SET (0x02) +#define SSP_TASK_IU_TASK_MANAGEMENT_FUNCTION_CLEAR_TASK_SET (0x04) +#define SSP_TASK_IU_TASK_MANAGEMENT_FUNCTION_LOGICAL_UNIT_RESET (0x08) +#define SSP_TASK_IU_TASK_MANAGEMENT_FUNCTION_CLEAR_ACA (0x40) +#define SSP_TASK_IU_TASK_MANAGEMENT_FUNCTION_QUERY_TASK (0x80) + +/* + * XFER_RDY Information Unit + */ +typedef struct _XFER_RDY_IU +{ + U32 RequestedOffset; /* 0x00 */ + U32 WriteDataLength; /* 0x04 */ + U8 Reserved08to0B[4]; /* 0x08 */ +} XFER_RDY_IU, *PTR_XFER_RDY_IU; + +/* + * DATA Information Unit + */ +typedef struct _DATA_IU +{ + U8 Data[1]; /* 0x00 - ?? */ + /* Note the data length is variable */ +} DATA_IU, *PTR_DATA_IU; + +/* + * RESPONSE Data field + */ +typedef struct _RESPONSE_DATA +{ + U8 Reserved00; /* 0x00 */ + U8 Reserved01; /* 0x01 */ + U8 Reserved02; /* 0x02 */ + U8 ResponseCode; /* 0x03 */ +} RESPONSE_DATA, *PTR_RESPONSE_DATA; + +/* Response Code field */ +#define SSP_RESPONSE_CODE_NO_FAILURE (0x00) +#define SSP_RESPONSE_CODE_TASK_MGMT_FUNCTION_COMPLETE (0x00) +#define SSP_RESPONSE_CODE_INVALID_FRAME (0x02) +#define SSP_RESPONSE_CODE_TASK_MGMT_FUNCTION_NOT_SUPPORTED (0x04) +#define SSP_RESPONSE_CODE_TASK_MGMT_FUNCTION_FAILED (0x05) +#define SSP_RESPONSE_CODE_TASK_MGMT_FUNCTION_SUCCEEDED (0x08) +#define SSP_RESPONSE_CODE_INVALID_LOGICAL_UNIT_NUMBER (0x09) + +/* + * RESPONSE Information Unit + */ +typedef struct _RESPONSE_IU +{ + U8 Reserved00to09[10]; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved0ABits2to7 :6; + U8 DataPres :2; /* 0x0A */ +#else /* little endian */ + U8 DataPres :2; /* 0x0A */ + U8 Reserved0ABits2to7 :6; +#endif + U8 Status; /* 0x0B */ + U32 Reserved0Cto0F; /* 0x0C */ + U32 SenseDataListLength; /* 0x10 */ + U32 ResponseDataListLength; /* 0x14 */ + union + { + RESPONSE_DATA ResponseData; + U8 SenseData[1]; + /* Note sense data length is variable */ + } ResponseOrSenseData; +} RESPONSE_IU, *PTR_RESPONSE_IU; + +/* DataPres field */ +#define SSP_RESPONSE_IU_DATAPRES_NO_DATA (0x00) +#define SSP_RESPONSE_IU_DATAPRES_RESPONSE_DATA (0x01) +#define SSP_RESPONSE_IU_DATAPRES_SENSE_DATA (0x02) + +/* + * Union of all IUs + */ +typedef union _SAS_IU +{ + COMMAND_IU CommandIU; + TASK_IU TaskIU; + XFER_RDY_IU XferRdyIU; + DATA_IU DataIU; + RESPONSE_IU ResponseIU; +} SAS_IU, *PTR_SAS_IU; + +/******************************************************************************/ +/* */ +/* S T P F R A M E D E F I N I T I O N S */ +/* */ +/******************************************************************************/ + +/* STP frames are identical to SATA FIS's, so these are defined in ata.h */ + + +/******************************************************************************/ +/* */ +/* S M P F R A M E D E F I N I T I O N S */ +/* */ +/******************************************************************************/ + +/* + * SMP Request + */ +typedef struct _SMP_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U8 AdditionalRequestBytes[1]; /* 0x04 */ + /* Note AdditionalRequestBytes is of variable length based on function */ +} SMP_REQUEST, *PTR_SMP_REQUEST; + +/* SMP Frame Types */ +#define SMP_FRAME_TYPE_SMP_REQUEST (0x40) +#define SMP_FRAME_TYPE_SMP_RESPONSE (0x41) + +/* SMP Functions */ +#define SMP_FUNCTION_REPORT_GENERAL (0x00) +#define SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION (0x01) +#define SMP_FUNCTION_READ_GPIO (0x02) +#define SMP_FUNCTION_REPORT_SELF_CONFIG_STATUS (0x03) +#define SMP_FUNCTION_DISCOVER (0x10) +#define SMP_FUNCTION_REPORT_PHY_ERROR_LOG (0x11) +#define SMP_FUNCTION_REPORT_PHY_SATA (0x12) +#define SMP_FUNCTION_REPORT_ROUTE_INFORMATION (0x13) +#define SMP_FUNCTION_REPORT_EXP_ROUTE_TABLE (0x17) +#define SMP_FUNCTION_WRITE_GPIO (0x82) +#define SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION (0x90) +#define SMP_FUNCTION_PHY_CONTROL (0x91) +/* These are vendor unique functions for LSI expanders */ +#define SMP_FUNCTION_RING_WRITE_N_REGISTERS (0xC0) +#define SMP_FUNCTION_RING_READ_N_REGISTERS (0x40) +#define SMP_FUNCTION_ICL_DISCOVER (0x41) + +#define SMP_FUNCTION_AHB_WRITE_N_REGISTERS (0xC2) +#define SMP_FUNCTION_AHB_READ_N_REGISTERS (0x42) + +/* These are for SGPIO use */ +#define SMP_FUNCTION_READ_GPIO_REGISTERS (0x02) +#define SMP_FUNCTION_WRITE_GPIO_REGISTERS (0x82) + +/* Zoning SMPs */ +#define SMP_FUNCTION_CONFIGURE_ZONE_PHY (0x8a) +#define SMP_FUNCTION_CONFIGURE_ZONE_PERMISSION (0x8b) +#define SMP_FUNCTION_REPORT_ZONE_PERMISSION (0x04) +#define SMP_FUNCTION_ENABLE_DISABLE_ZONING (0x81) +#define SMP_FUNCTION_ZONE_ACTIVATE (0x87) +#define SMP_FUNCTION_ZONE_LOCK (0x86) +#define SMP_FUNCTION_ZONE_UNLOCK (0x88) +#define SMP_FUNCTION_CONFIGURE_ZONE_MANAGER_PASSWORD (0x89) + +/* + * SMP Response + */ +typedef struct _SMP_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U8 AdditionalResponseBytes[1]; /* 0x04 */ + /* Note AdditionalResponseBytes is of variable length based on function */ +} SMP_RESPONSE, *PTR_SMP_RESPONSE; + +/* SMP Function Result field */ +#define SMP_RESPONSE_FUNCTION_RESULT_ACCEPTED (0x00) +#define SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_SMP_FUNCTION (0x01) +#define SMP_RESPONSE_FUNCTION_RESULT_SMP_FUNCTION_FAILED (0x02) +#define SMP_RESPONSE_FUNCTION_RESULT_INVALID_REQUEST_LENGTH (0x03) +#define SMP_RESPONSE_FUNCTION_RESULT_INVALID_EXP_CHANGE_COUNT (0x04) +#define SMP_RESPONSE_FUNCTION_RESULT_BUSY (0x05) +#define SMP_RESPONSE_FUNCTION_RESULT_INCOMPLETE_DESCRIPTOR_LIST (0x06) + +#define SMP_RESPONSE_FUNCTION_RESULT_PHY_DOES_NOT_EXIST (0x10) +#define SMP_RESPONSE_FUNCTION_RESULT_INDEX_DOES_NOT_EXIST (0x11) +#define SMP_RESPONSE_FUNCTION_RESULT_PHY_DOES_NOT_SUPPORT_SATA (0x12) +#define SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_PHY_OPERATION (0x13) +#define SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_PHY_TEST_FUNCTION (0x14) +#define SMP_RESPONSE_FUNCTION_RESULT_PHY_TEST_FUNCTION_IN_PROG (0x15) +#define SMP_RESPONSE_FUNCTION_RESULT_PHY_VACANT (0x16) +#define SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_PHY_EVENT_SOURCE (0x17) +#define SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_DESCRIPTOR_TYPE (0x18) +#define SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_PHY_FILTER (0x19) +#define SMP_RESPONSE_FUNCTION_RESULT_AFFILIATION_VIOLATION (0x1a) + +#define SMP_RESPONSE_FUNCTION_RESULT_SMP_ZONE_VIOLATION (0x20) +#define SMP_RESPONSE_FUNCTION_RESULT_NO_MANAGEMENT_ACCESS_RIGHTS (0x21) +#define SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_ENABLE_DISABLE_ZONING_VALUE (0x22) +#define SMP_RESPONSE_FUNCTION_RESULT_ZONE_LOCK_VIOLATION (0x23) +#define SMP_RESPONSE_FUNCTION_RESULT_NOT_ACTIVATED (0x24) +#define SMP_RESPONSE_FUNCTION_RESULT_ZONE_GROUP_OUT_OF_RANGE (0x25) +#define SMP_RESPONSE_FUNCTION_RESULT_NO_PHYSICAL_PRESENCE (0x26) +#define SMP_RESPONSE_FUNCTION_RESULT_SAVING_NOT_SUPPORTED (0x27) +#define SMP_RESPONSE_FUNCTION_RESULT_SOURCE_ZONE_GROUP_DOES_NOT_EXIST (0x28) +#define SMP_RESPONSE_FUNCTION_RESULT_DISABLED_PASSWORD_NOT_SUPPORTED (0x29) + + +/* + * SMP Report General request + */ +typedef struct _SMP_REPORT_GENERAL_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ +} SMP_REPORT_GENERAL_REQUEST, *PTR_SMP_REPORT_GENERAL_REQUEST; + +/* + * SMP Report General response + */ +typedef struct _SMP_REPORT_GENERAL_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U16 ExpanderRouteIndexes; /* 0x06 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 LongResponse :1; + U8 Reserved08 :7; /* 0x08 */ +#else + U8 Reserved08 :7; + U8 LongResponse :1; /* 0x08 */ +#endif + U8 NumberOfPhys; /* 0x09 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 TableToTableSup :1; /* 0x0A */ + U8 ZoneConfiguring :1; + U8 SelfConfiguring :1; + U8 StpContinueAWT :1; + U8 OpenRejectRetrySupported :1; + U8 ConfiguresOthers :1; + U8 Configuring :1; + U8 ConfigurableRouteTable :1; +#else /* little endian */ + U8 ConfigurableRouteTable :1; /* 0x0A */ + U8 Configuring :1; + U8 ConfiguresOthers :1; + U8 OpenRejectRetrySupported :1; + U8 StpContinueAWT :1; + U8 SelfConfiguring :1; + U8 ZoneConfiguring :1; + U8 TableToTableSup :1; +#endif + U8 Reserved0B; /* 0x0B */ + SAS_ADDRESS EnclosureLogicalIdentifier; /* 0x0C */ + U8 Reserved14to1B[8]; /* 0x14 */ + U16 Reserved1C; /* 0x1c */ + U16 StpBusInactivityTimeLimit; /* 0x1e */ + U16 StpMaxConnectTimeLimit; /* 0x20 */ + U16 StpNexusLossTime; /* 0x22 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 NoOfZoneGroups :2; /* 0x24 */ + U8 Reserved24 :1; + U8 ZoneLocked :1; + U8 PhysPresenceSupported :1; + U8 PhysPresenceAsserted :1; + U8 ZoningSupported :1; + U8 ZoningEnabled :1; +#else /* little endian */ + U8 ZoningEnabled :1; /* 0x24 */ + U8 ZoningSupported :1; + U8 PhysPresenceAsserted :1; + U8 PhysPresenceSupported :1; + U8 ZoneLocked :1; + U8 Reserved24 :1; + U8 NoOfZoneGroups :2; +#endif +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved25 :3; /* 0x25 */ + U8 Saving :1; + U8 SavingZoneMgrPasswdSupported :1; + U8 SavingZonePhyInfoSupported :1; + U8 SavingZonePermTableSupported :1; + U8 SavingZoningEnabledSupported :1; +#else /* little endian */ + U8 SavingZoningEnabledSupported :1; /* 0x25 */ + U8 SavingZonePermTableSupported :1; + U8 SavingZonePhyInfoSupported :1; + U8 SavingZoneMgrPasswdSupported :1; + U8 Saving :1; + U8 Reserved25 :3; +#endif + U16 MaxRoutedSasAddresses; /* 0x26 */ + SAS_ADDRESS ActiveZoneManager; /* 0x28 */ + U16 ZoneLockInactiveTime; /* 0x30 */ + U16 Reserved32; /* 0x32 */ + U8 Reserved34; /* 0x34 */ + U8 FirstEnclosureConnectorIndex; /* 0x35 */ + U8 EnclosureConnectorIndexes; /* 0x36 */ + U8 Reserved37; /* 0x37 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 ReducedFunctionality :1; /* 0x38 */ + U8 Reserved38 :7; +#else /* little endian */ + U8 Reserved38 :7; /* 0x38 */ + U8 ReducedFunctionality :1; +#endif + U8 TimeToReducedFunc; /* 0x39 */ + U8 InitTimeReducedFunc; /* 0x3a */ + U8 MaxReducedFuncTime; /* 0x3b */ + + U16 LastSelfConfigStatus; /* 0x3c - 0x3d */ + U16 MaxStoredSelfConfigStatus; /* 0x3e - 0x3f */ + U16 LastPhyEventDesc; /* 0x40 - 0x41 */ + U16 MaxStoredPhyEventDesc; /* 0x43 - 0x42 */ + U16 STPRejectLimit; /* 0x44 - 0x45 */ + U16 Reserved47; /* 0x47 - 0x46 */ + U32 CRC; +} SMP_REPORT_GENERAL_RESPONSE, *PTR_SMP_REPORT_GENERAL_RESPONSE; + +/* + * SMP Report Manufacturer Information request + */ +typedef struct _SMP_REPORT_MANUFACTURER_INFO_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ +} SMP_REPORT_MANUFACTURER_INFO_REQUEST, *PTR_SMP_REPORT_MANUFACTURER_INFO_REQUEST; + +/* + * SMP Report Manufacturer Information response + */ +#define VEND_ID_LEN (8) +#define PROD_ID_LEN (16) + +#define PROD_REV_LEN (4) + +#define VEND_SPEC_LEN (8) +#define COMP_VEND_ID_LEN (8) + +typedef struct _SMP_REPORT_MANUFACTURER_INFO_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 - 0x05 */ + U16 Reserved06; /* 0x06 - 0x07 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved0ABits1to7 :7; /* 0x08 */ + U8 SAS11Format :1; +#else /* little endian */ + U8 SAS11Format :1; /* 0x08 */ + U8 Reserved0ABits1to7 :7; +#endif + U8 Reserved09; /* 0x09 */ + U8 Reserved0A; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ + U8 VendorIdentification[VEND_ID_LEN]; /* 0x0C */ + U8 ProductIdentification[PROD_ID_LEN]; /* 0x14 */ + U8 ProductRevisionLevel[PROD_REV_LEN]; /* 0x24 */ + U8 ComponentVendorId[COMP_VEND_ID_LEN];/* 0x28 */ + U16 ComponentId; /* 0x30 */ + U8 ComponentRevisionId; /* 0x32 */ + U8 Reserved51; /* 0x33 */ + union + { + struct + { + U8 VuX12TruncatedEnclosureId[5]; /* 0x34 */ + U8 OEMVendorUnique57to50[3]; /* 0x39 */ + }Enclosure; + U8 VendorSpecific[VEND_SPEC_LEN]; /* 0x34 */ + }u; + U32 CRC; +} SMP_REPORT_MANUFACTURER_INFO_RESPONSE, *PTR_SMP_REPORT_MANUFACTURER_INFO_RESPONSE; + + +/* + * SMP Report Self-Configuration request + */ +typedef struct _SMP_REPORT_SELF_CONFIG_STATUS_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 Reserved04to05; /* 0x04 - 0x05 */ + U16 StartingStatusIndex; /* 0x06 - 0x07 */ +} SMP_REPORT_SELF_CONFIG_STATUS_REQUEST, *PTR_SMP_REPORT_SELF_CONFIG_STATUS_REQUEST; + + +/* + * SMP Report Self-Configuration response descriptor + */ +typedef struct _SMP_REPORT_SELF_CONFIG_STATUS_DESCRIPTOR +{ + U8 StatusType; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved01Bits1to7 :7; /* 0x01 */ + U8 Final :1; +#else /* little endian */ + U8 Final :1; /* 0x01 */ + U8 Reserved01Bits1to7 :7; +#endif + U8 Reserved02; /* 0x02 */ + U8 PhyIdentifier; /* 0x03 */ + U32 Reserved04to07; /* 0x04 - 0x07 */ + SAS_ADDRESS SASAddress; /* 0x08 - 0x0f */ +} SMP_REPORT_SELF_CONFIG_STATUS_DESCRIPTOR, *PTR_SMP_REPORT_SELF_CONFIG_STATUS_DESCRIPTOR; + + +/* + * SMP Report Self-Configuration response + */ +typedef struct _SMP_REPORT_SELF_CONFIG_STATUS_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 - 0x05 */ + U16 StartingStatusIndex; /* 0x06 - 0x07 */ + U16 TotalNumStatusDescriptors; /* 0x08 - 0x09 */ + U16 LastStatusIndex; /* 0x0a - 0x0b */ + U8 StatusDescriptorLength; /* 0x0c */ + U8 Reserved0D; /* 0x0d */ + U16 Reserved0Eto0F; /* 0x0e - 0x0f */ + U16 Reserved10to11; /* 0x10 - 0x11 */ + U8 Reserved12; /* 0x12 */ + U8 NumberStatusDescriptors; /* 0x13 */ + SMP_REPORT_SELF_CONFIG_STATUS_DESCRIPTOR StatusDescriptors[1]; /* 0x14... */ +} SMP_REPORT_SELF_CONFIG_STATUS_RESPONSE, *PTR_SMP_REPORT_SELF_CONFIG_STATUS_RESPONSE; + + +/* + * SMP Discover request + */ +typedef struct _SMP_DISCOVER_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U32 Reserved04to07; /* 0x04 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved08 :7; /* 0x08 */ + U8 NoZoneMask :1; +#else /* little endian */ + U8 NoZoneMask :1; /* 0x08 */ + U8 Reserved08 :7; +#endif + U8 PhyIdentifier; /* 0x09 */ + U16 Reserved0Ato0B; /* 0x0A */ +} SMP_DISCOVER_REQUEST, *PTR_SMP_DISCOVER_REQUEST; + +/* + * SMP Discover response + */ + + +// If type = 20h - 23h then this format is valid +typedef struct _SMP_X12_VU_SLOT_DISCOVER_REPSONSE +{ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 ConnectorFieldsValid :2; + U8 ConnectorType :6; +#else /* little endian */ + U8 ConnectorType :6; + U8 ConnectorFieldsValid :2; +#endif + U8 ConnectorElementIndex; +} SMP_X12_VU_SLOT_DISCOVER_REPSONSE, * PTR_SMP_X12_VU_SLOT_DISCOVER_REPSONSE; + +// if type != 20h - 23h then this format is valid +typedef struct _SMP_X12_VU_DISCOVER_REPSONSE +{ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 ConnectorFieldsValid :2; + U8 ConnectorType :6; + U8 ConnectorElementIndex :4; + U8 ConnectorPhysicalLink :4; +#else /* little endian */ + U8 ConnectorType :6; + U8 ConnectorFieldsValid :2; + U8 ConnectorPhysicalLink :4; + U8 ConnectorElementIndex :4; +#endif +} SMP_X12_VU_DISCOVER_REPSONSE, * PTR_SMP_X12_VU_DISCOVER_REPSONSE; + +typedef struct _SMP_DISCOVER_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U16 Reserved06; /* 0x06 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U8 Reserved0A; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved0CBit7 :1; /* 0x0C */ + U8 AttachedDeviceType :3; + U8 AttachedReason :4; + U8 Reserved0DBits4to7 :4; /* 0x0D */ + U8 NegotiatedPhysLinkRate :4; + U8 Reserved0EBits4to7 :4; /* 0x0E */ + U8 AttachedSSPInitiator :1; + U8 AttachedSTPInitiator :1; + U8 AttachedSMPInitiator :1; + U8 AttachedSATAHost :1; + U8 AttachedSATAPortSelector :1; /* 0x0F */ + U8 Reserved0FBits4to6 :3; + U8 AttachedSSPTarget :1; + U8 AttachedSTPTarget :1; + U8 AttachedSMPTarget :1; + U8 AttachedSATATarget :1; +#else /* little endian */ + U8 AttachedReason :4; /* 0x0C */ + U8 AttachedDeviceType :3; + U8 Reserved0CBit7 :1; + U8 NegotiatedPhysLinkRate :4; /* 0x0D */ + U8 Reserved0DBits4to7 :4; + U8 AttachedSATAHost :1; /* 0x0E */ + U8 AttachedSMPInitiator :1; + U8 AttachedSTPInitiator :1; + U8 AttachedSSPInitiator :1; + U8 Reserved0EBits4to7 :4; + U8 AttachedSATATarget :1; /* 0x0F */ + U8 AttachedSMPTarget :1; + U8 AttachedSTPTarget :1; + U8 AttachedSSPTarget :1; + U8 Reserved0FBits4to6 :3; + U8 AttachedSATAPortSelector :1; +#endif + SAS_ADDRESS SASAddress; /* 0x10 */ + SAS_ADDRESS AttachedSASAddress; /* 0x18 */ + U8 AttachedPhyIdentifier; /* 0x20 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved21Bits3to7 :5; /* 0x21 */ + U8 AttachedInsideZpsdsPersistent :1; + U8 AttachedRequestedInsideZpsds :1; + U8 AttachedBreakReplyCapable :1; +#else /* little endian */ + U8 AttachedBreakReplyCapable :1; /* 0x21 */ + U8 AttachedRequestedInsideZpsds :1; + U8 AttachedInsideZpsdsPersistent :1; + U8 Reserved21Bits3to7 :5; +#endif + U8 Reserved22; /* 0x22 */ + U8 Reserved23; /* 0x23 */ + U32 Reserved24to27; /* 0x24 - 0x27 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 ProgMinPhysLinkRate :4; /* 0x28 */ + U8 HardwareMinPhysLinkRate :4; + U8 ProgMaxPhysLinkRate :4; /* 0x29 */ + U8 HardwareMaxPhysLinkRate :4; + U8 PhyChangeCount; /* 0x2A */ + U8 VirtualPhy :1; /* 0x2B */ + U8 Reserved2BBits4to6 :3; + U8 PartialPathTimeoutValue :4; + U8 Reserved2CBits4to7 :4; /* 0x2C */ + U8 RoutingAttribute :4; + U8 Reserved2DBit7 :1; /* 0x2D */ + U8 ConnectorType :7; +#else /* little endian */ + U8 HardwareMinPhysLinkRate :4; /* 0x28 */ + U8 ProgMinPhysLinkRate :4; + U8 HardwareMaxPhysLinkRate :4; /* 0x29 */ + U8 ProgMaxPhysLinkRate :4; + U8 PhyChangeCount; /* 0x2A */ + U8 PartialPathTimeoutValue :4; /* 0x2B */ + U8 Reserved2BBits4to6 :3; + U8 VirtualPhy :1; + U8 RoutingAttribute :4; /* 0x2C */ + U8 Reserved2CBits4to7 :4; + U8 ConnectorType :7; /* 0x2D */ + U8 Reserved2DBit7 :1; +#endif + U8 ConnectorElementIndex; /* 0x2E */ + U8 ConnectorPhysicalLink; /* 0x2F */ + U8 Reserved30; /* 0x30 */ + U8 Reserved31; /* 0x31 */ + union + { + SMP_X12_VU_DISCOVER_REPSONSE VuX12Connector; /* 0x32 */ + SMP_X12_VU_SLOT_DISCOVER_REPSONSE VuX12Slot; + U16 VendorSpecific; /* 0x32 */ + } u; + SAS_ADDRESS AttachedDeviceName; /* 0x34 - 3B*/ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved3cBit7 :1; /* 0x3c */ + U8 ReqInsideZpsdsByExp :1; + U8 InsideZpsdsPersistent :1; + U8 RequestedInsideZpsds :1; + U8 Reserved3cBit3 :1; + U8 ZoneGroupPersistent :1; + U8 InsideZpsds :1; + U8 ZoningEnabled :1; +#else /* little endian */ + U8 ZoningEnabled :1; /* 0x3c */ + U8 InsideZpsds :1; + U8 ZoneGroupPersistent :1; + U8 Reserved3cBit3 :1; + U8 RequestedInsideZpsds :1; + U8 InsideZpsdsPersistent :1; + U8 ReqInsideZpsdsByExp :1; + U8 Reserved3cBit7 :1; +#endif + U16 Reserved3d; /* 0x3d */ + U8 ZoneGroup; /* 0x3f */ + U8 SelfConfigurationStatus; /* 0x40 */ + U8 SelfConfigLevelsCompleted; /* 0x41 */ + U16 Reserved42; /* 0x42 */ + SAS_ADDRESS SelfConfigSasAddress; /* 0x44 */ + U32 ProgrammedPhyCapabilities; /* 0x4C - 0x4F */ + U32 CurrentPhyCapabilities; /* 0x50 - 0x53 */ + U32 AttachedPhyCapabilities; /* 0x54 - 0x57 */ + U32 Reserved58; /* 0x58 - 0x5B */ + U16 Reserved5C; /* 0x5C - 0x5D */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reason :4; /* 0x5E */ + U8 NegotiatedPhysicalLinkRate :4; + + U8 Reserved5FBits2to7 :6; /* 0x5F */ + U8 NegotiatedSSC :1; + U8 HardwareMuxingSupported :1; + + U8 Reserved60Bits6to7 :2; /* 0x60 Bits 6 - 7 */ + U8 DefaultInsideZpsdsPersistent :1; /* 0x60 Bit 5 */ + U8 DefaultRequestedInsideZpsds :1; /* 0x60 Bit 4 */ + U8 Reserved60Bit3 :1; /* 0x60 Bit 3 */ + U8 DefaultZoneGroupPersistent :1; /* 0x60 Bit 2 */ + U8 Reserved60Bit1 :1; /* 0x60 Bit 1 */ + U8 DefaultZoningEnabled :1; /* 0x60 Bit 0 */ +#else /* little endian */ + U8 NegotiatedPhysicalLinkRate :4; /* 0x5E */ + U8 Reason :4; + + U8 HardwareMuxingSupported :1; /* 0x5F */ + U8 NegotiatedSSC :1; + U8 Reserved5FBits2to7 :6; + + U8 DefaultZoningEnabled :1; /* 0x60 Bit 0 */ + U8 Reserved60Bit1 :1; /* 0x60 Bit 1 */ + U8 DefaultZoneGroupPersistent :1; /* 0x60 Bit 2 */ + U8 Reserved60Bit3 :1; /* 0x60 Bit 3 */ + U8 DefaultRequestedInsideZpsds :1; /* 0x60 Bit 4 */ + U8 DefaultInsideZpsdsPersistent :1; /* 0x60 Bit 5 */ + U8 Reserved60Bits6to7 :2; /* 0x60 Bits 6 - 7 */ +#endif + U8 Reserved61; /* 0x61 */ + U8 Reserved62; /* 0x62 */ + U8 DefaultZoneGroup; /* 0x63 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved64Bits6to7 :2; /* 0x64 Bits 6 - 7 */ + U8 SavedInsideZpsdsPersistent :1; /* 0x64 Bit 5 */ + U8 SavedRequestedInsideZpsds :1; /* 0x64 Bit 4 */ + U8 Reserved64Bit3 :1; /* 0x64 Bit 3 */ + U8 SavedZoneGroupPersistent :1; /* 0x64 Bit 2 */ + U8 Reserved64Bit1 :1; /* 0x64 Bit 1 */ + U8 SavedZoningEnabled :1; /* 0x64 Bit 0 */ +#else /* little endian */ + U8 SavedZoningEnabled :1; /* 0x64 Bit 0 */ + U8 Reserved64Bit1 :1; /* 0x64 Bit 1 */ + U8 SavedZoneGroupPersistent :1; /* 0x64 Bit 2 */ + U8 Reserved64Bit3 :1; /* 0x64 Bit 3 */ + U8 SavedRequestedInsideZpsds :1; /* 0x64 Bit 4 */ + U8 SavedInsideZpsdsPersistent :1; /* 0x64 Bit 5 */ + U8 Reserved64Bits6to7 :2; /* 0x64 Bits 6 - 7 */ +#endif + U8 Reserved65; /* 0x65 */ + U8 Reserved66; /* 0x66 */ + U8 SavedZoneGroup; /* 0x67 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved68Bits6to7 :2; /* 0x68 Bits 6 - 7 */ + U8 ShadowInsideZpsdsPersistent :1; /* 0x68 Bit 5 */ + U8 ShadowRequestedInsideZpsds :1; /* 0x68 Bit 4 */ + U8 Reserved68Bit3 :1; /* 0x68 Bit 3 */ + U8 ShadowZoneGroupPersistent :1; /* 0x68 Bit 2 */ + U8 Reserved68Bit0to1 :2; /* 0x68 Bits 0 -1 */ +#else /* little endian */ + U8 Reserved68Bit0to1 :2; /* 0x68 Bits 0 -1 */ + U8 ShadowZoneGroupPersistent :1; /* 0x68 Bit 2 */ + U8 Reserved68Bit3 :1; /* 0x68 Bit 3 */ + U8 ShadowRequestedInsideZpsds :1; /* 0x68 Bit 4 */ + U8 ShadowInsideZpsdsPersistent :1; /* 0x68 Bit 5 */ + U8 Reserved68Bits6to7 :2; /* 0x68 Bits 6 - 7 */ +#endif + U8 Reserved69; /* 0x69 */ + U8 Reserved6A; /* 0x6A */ + U8 ShadowZoneGroup; /* 0x6B */ + U8 DeviceSlotNumber; /* 0x6C */ + U8 GroupNumber; /* 0x6D */ + U16 PathToEnclosure[3]; /* 0x6E */ + U32 CRC; +} SMP_DISCOVER_RESPONSE, *PTR_SMP_DISCOVER_RESPONSE; + +/* Discover attached device types */ +#define SMP_DISCOVER_ATTACHED_DEVICE_TYPE_NO_DEVICES_ATTACHED (0x0) +#define SMP_DISCOVER_ATTACHED_DEVICE_TYPE_END_DEVICE_ONLY (0x1) +#define SMP_DISCOVER_ATTACHED_DEVICE_TYPE_EDGE_EXPANDER (0x2) +#define SMP_DISCOVER_ATTACHED_DEVICE_TYPE_FANOUT_EXPANDER (0x3) + +/* Discover negotiated physical link rate */ +#define SMP_NEG_PHYS_LINK_RATE_PHY_ENABLED_UNKNOWN_RATE (0x0) +#define SMP_NEG_PHYS_LINK_RATE_PHY_DISABLED (0x1) +#define SMP_NEG_PHYS_LINK_RATE_PHY_ENABLED_SPEED_NEG_FAILED (0x2) +#define SMP_NEG_PHYS_LINK_RATE_PHY_ENABLED_IN_SATA_SPINUP_HOLD (0x3) +#define SMP_NEG_PHYS_LINK_RATE_PHY_ENABLED_PORT_SELECTOR (0x4) +#define SMP_NEG_PHYS_LINK_RATE_PHY_ENABLED_RESET_IN_PROGRESS (0x5) +#define SMP_NEG_PHYS_LINK_RATE_PHY_ENABLED_AT_1_5_GBPS (0x8) +#define SMP_NEG_PHYS_LINK_RATE_PHY_ENABLED_AT_3_0_GBPS (0x9) +#define SMP_NEG_PHYS_LINK_RATE_PHY_ENABLED_AT_6_0_GBPS (0xA) + +/* Discover hardware and programmed physical link rates */ +#define SMP_DISCOVER_PHYSICAL_LINK_RATE_NOT_PROGRAMMABLE (0x0) +#define SMP_DISCOVER_PHYSICAL_LINK_RATE_1_5_GBPS (0x8) +#define SMP_DISCOVER_PHYSICAL_LINK_RATE_3_0_GBPS (0x9) +#define SMP_DISCOVER_PHYSICAL_LINK_RATE_6_0_GBPS (0xA) + +/* Discover routing attributes */ +#define SMP_DISCOVER_ROUTING_ATTRIBUTE_DIRECT_ROUTING (0x0) +#define SMP_DISCOVER_ROUTING_ATTRIBUTE_SUBTRACTIVE_ROUTING (0x1) +#define SMP_DISCOVER_ROUTING_ATTRIBUTE_TABLE_ROUTING (0x2) + +#define SMP_DISCOVER_CONNECTOR_FIELDS_VALID (0x2) +/* Valid Connector Types*/ +#define SMP_DISCOVER_CONNECTOR_TYPE_UNKNOWN (0X00) +#define SMP_DISCOVER_CONNECTOR_TYPE_SAS_EXTERNAL (0X01) +#define SMP_DISCOVER_CONNECTOR_TYPE_SAS_INTERNAL (0X10) +#define SMP_DISCOVER_CONNECTOR_TYPE_SAS_BACKPLANE_RECEPTACLE (0X20) +#define SMP_DISCOVER_CONNECTOR_TYPE_SATA_HOST_PLUG (0X21) +#define SMP_DISCOVER_CONNECTOR_TYPE_SAS_PLUG (0X22) +#define SMP_DISCOVER_CONNECTOR_TYPE_SATA_DEVICE_PLUG (0X23) + + +/* + * SMP Report Phy Error Log request + */ +typedef struct _SMP_REPORT_PHY_ERROR_LOG_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U32 Reserved04to07; /* 0x04 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U16 Reserved0Ato0B; /* 0x0A */ +} SMP_REPORT_PHY_ERROR_LOG_REQUEST, *PTR_SMP_REPORT_PHY_ERROR_LOG_REQUEST; + +/* + * SMP Report Phy Error Log response + */ +typedef struct _SMP_REPORT_PHY_ERROR_LOG_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U16 Reserved06; /* 0x06 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U8 Reserved0A; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ + U32 InvalidDwordCount; /* 0x0C */ + U32 RunningDisparityErrorCount; /* 0x10 */ + U32 LossOfDwordSynchronizationCount; /* 0x14 */ + U32 PhyResetProblemCount; /* 0x18 */ + U32 CRC; +} SMP_REPORT_PHY_ERROR_LOG_RESPONSE, *PTR_SMP_REPORT_PHY_ERROR_LOG_RESPONSE; + +/* + * SMP Report Phy SATA request + */ +typedef struct _SMP_REPORT_PHY_SATA_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U32 Reserved04to07; /* 0x04 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U8 AffiliationContext; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ +} SMP_REPORT_PHY_SATA_REQUEST, *PTR_SMP_REPORT_PHY_SATA_REQUEST; + +/* + * SMP Report Phy SATA response + */ +typedef struct _SMP_REPORT_PHY_SATA_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U16 Reserved06; /* 0x06 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U8 Reserved0A; /* 0x0A */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved0BBits3to7 :5; /* 0x0B */ + U8 StpITNexusLossOccurred :1; + U8 AffiliationsSupported :1; + U8 AffiliationValid :1; +#else /* little endian */ + U8 AffiliationValid :1; /* 0x0B */ + U8 AffiliationsSupported :1; + U8 StpITNexusLossOccurred :1; + U8 Reserved0BBits3to7 :5; +#endif + U32 Reserved0Cto0F; /* 0x0C */ + SAS_ADDRESS STPSASAddress; /* 0x10 */ + REGISTER_DEVICE_TO_HOST_FIS RegisterDeviceToHostFIS; /* 0x18 */ /* Defined in ata.h */ + U32 Reserved2Cto2F; /* 0x2C */ + SAS_ADDRESS AffiliatedSTPInitiatorSASAddress; /* 0x30 */ + SAS_ADDRESS StpITNexusLossSASAddress; /* 0x38 - 0x3F */ + U8 Reserved46; /* 0x40 */ + U8 AffiliationContext; /* 0x41 */ + U8 CurrentAffiliationContexts; /* 0x42 */ + U8 MaximumAffiliationContexts; /* 0x43 */ + U32 CRC; +} SMP_REPORT_PHY_SATA_RESPONSE, *PTR_SMP_REPORT_PHY_SATA_RESPONSE; + +/* + * SMP Report Route Information request + */ +typedef struct _SMP_REPORT_ROUTE_INFO_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 Reserved04to05; /* 0x04 */ + U16 ExpanderRouteIndex; /* 0x06 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U16 Reserved0Ato0B; /* 0x0A */ +} SMP_REPORT_ROUTE_INFO_REQUEST, *PTR_SMP_REPORT_ROUTE_INFO_REQUEST; + +/* + * SMP Report Route Information response + */ +typedef struct _SMP_REPORT_ROUTE_INFO_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U16 ExpanderRouteIndex; /* 0x06 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U8 Reserved0A; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 RouteEntryDisabled :1; /* 0x0C */ + U8 Reserved0CBits0to6 :7; +#else /* little endian */ + U8 Reserved0CBits0to6 :7; /* 0x0C */ + U8 RouteEntryDisabled :1; +#endif + U8 Reserved0Dto0F[3]; /* 0x0D */ + SAS_ADDRESS RoutedSASAddress; /* 0x10 */ + U8 Reserved18to23[12]; /* 0x18 */ + U32 Reserved24to27; /* 0x24 */ + U32 CRC; +} SMP_REPORT_ROUTE_INFO_RESPONSE, *PTR_SMP_REPORT_ROUTE_INFO_RESPONSE; + +/* + * SMP Configure Route Information request + */ +typedef struct _SMP_CONFIGURE_ROUTE_INFO_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U16 ExpanderRouteIndex; /* 0x06 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U16 Reserved0Aand0B; /* 0x0A */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 DisableRouteEntry :1; /* 0x0C */ + U8 Reserved0CBits0to6 :7; +#else /* little endian */ + U8 Reserved0CBits0to6 :7; /* 0x0C */ + U8 DisableRouteEntry :1; +#endif + U8 Reserved0Dto0F[3]; /* 0x0D */ + SAS_ADDRESS RoutedSASAddress; /* 0x10 */ + U8 Reserved18to23[12]; /* 0x18 */ + U32 Reserved24to27; /* 0x24 */ +} SMP_CONFIGURE_ROUTE_INFO_REQUEST, *PTR_SMP_CONFIGURE_ROUTE_INFO_REQUEST; + +/* + * SMP Configure Route Information response + */ + +typedef struct _SMP_CONFIGURE_ROUTE_INFO_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U32 CRC; +} SMP_CONFIGURE_ROUTE_INFO_RESPONSE, *PTR_SMP_CONFIGURE_ROUTE_INFO_RESPONSE; + +/* + * SMP Report Expander Route Table request + */ +typedef struct _SMP_REPORT_EXP_ROUTE_TABLE_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U32 Reserved04to07; /* 0x04 */ + U16 MaxNumDescriptors; /* 0x08 */ + U16 StartingRoutedSASAddressIdx; /* 0x0A */ + U32 Reserved0Cto0F; /* 0x0C */ + U16 Reserved10and11; /* 0x10 */ + U8 Reserved12; /* 0x12 */ + U8 StartingPhyId; /* 0x13 */ + U32 Reserved14to17; /* 0x14 */ + U32 Reserved18to1B; /* 0x18 */ +} SMP_REPORT_EXP_ROUTE_TABLE_REQUEST, *PTR_SMP_REPORT_EXP_ROUTE_TABLE_REQUEST; + +#define SMP_REPORT_EXP_ROUTE_TABLE_REQUEST_LENGTH (0x06) + +typedef struct _SMP_REPORT_EXP_ROUTE_TABLE_DESCRIPTOR +{ + SAS_ADDRESS RoutedSASAddress; /* 0x00 */ + U32 PhyBitMapBit16to47; /* 0x08 */ + U16 PhyBitMapBit0to15; /* 0x0C */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 ZoneGroupValid :1; /* 0x0E */ + U8 Reserved0EBit0to6 :7; +#else + U8 Reserved0EBit0to6 :7; /* 0x0E */ + U8 ZoneGroupValid :1; +#endif + U8 ZoneGroup; /* 0x0F */ +} SMP_REPORT_EXP_ROUTE_TABLE_DESCRIPTOR, *PTR_SMP_REPORT_EXP_ROUTE_TABLE_DESCRIPTOR; + +/* + * SMP Report Expander Route Table response + */ +typedef struct _SMP_REPORT_EXP_ROUTE_TABLE_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U16 ExpRouteTableChangeCnt; /* 0x06 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved08Bit4to7 :4; /* 0x08 */ + U8 SelfConfiguring :1; + U8 ZoneConfiguring :1; + U8 Configuring :1; + U8 Reserved08Bit0 :1; +#else + U8 Reserved08Bit0 :1; /* 0x08 */ + U8 Configuring :1; + U8 ZoneConfiguring :1; + U8 SelfConfiguring :1; + U8 Reserved08Bit4to7 :4; +#endif + U8 Reserved09; /* 0x09 */ + U8 ExpanderRouteTableDescriptorLength; /* 0x0A */ + U8 NumDescriptors; /* 0x0B */ + U16 FirstRoutedSASAddrIdx; /* 0x0C */ + U16 LastRoutedSASAddrIdx; /* 0x0E */ + U16 Reserved10and11; /* 0x10 */ + U8 Reserved12; /* 0x12 */ + U8 StartingPhyIdentifier; /* 0x13 */ + U32 Reserved20to23; /* 0x14 */ + U32 Reserved24to27; /* 0x18 */ + U32 Reserved28to31; /* 0x1c */ + SMP_REPORT_EXP_ROUTE_TABLE_DESCRIPTOR ExpRouteTableDesc[1]; /* 0x20 */ +}SMP_REPORT_EXP_ROUTE_TABLE_RESPONSE, *PTR_SMP_REPORT_EXP_ROUTE_TABLE_RESPONSE; + +/* This define was calculated by taking the maximum response size of 1024 + * subtracting the non-descriptor response size of 32 bytes and dividing + * by the descriptor size + */ +#define MAX_REPORT_EXP_ROUTE_TABLE_DESCRIPTOR (1024 - 32)/sizeof(SMP_REPORT_EXP_ROUTE_TABLE_DESCRIPTOR) + +/* + * SMP Phy Control request + */ +typedef struct _SMP_PHY_CONTROL_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U16 Reserved06to07; /* 0x06 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U8 PhyOperation; /* 0x0A */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved0BBits1to7 :7; /* 0x0B */ + U8 UpdatePartialPathTimeoutValue :1; +#else /* little endian */ + U8 UpdatePartialPathTimeoutValue :1; /* 0x0B */ + U8 Reserved0BBits1to7 :7; +#endif + + U32 Reserved0C; /* 0x0C - 0x0F */ + U32 Reserved10; /* 0x10 - 0x13 */ + U32 Reserved14; /* 0x14 - 0x17 */ + SAS_ADDRESS AttachedDeviceName; /* 0x18 - 0x1F */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 ProgMinPhysLinkRate :4; /* 0x20 */ + U8 Reserved20Bits0to3 :4; + U8 ProgMaxPhysLinkRate :4; /* 0x21 */ + U8 Reserved21Bits0to3 :4; + U16 Reserved22to23; /* 0x22 */ + U8 Reserved24Bits4to7 :4; /* 0x24 */ + U8 PartialPathTimeoutValue :4; +#else /* little endian */ + U8 Reserved20Bits0to3 :4; /* 0x20 */ + U8 ProgMinPhysLinkRate :4; + U8 Reserved21Bits0to3 :4; /* 0x21 */ + U8 ProgMaxPhysLinkRate :4; + U16 Reserved22to23; /* 0x22 */ + U8 PartialPathTimeoutValue :4; /* 0x24 */ + U8 Reserved24Bits4to7 :4; +#endif + U8 Reserved25; /* 0x25 */ + U16 Reserved26and27; /* 0x26 */ +} SMP_PHY_CONTROL_REQUEST, *PTR_SMP_PHY_CONTROL_REQUEST; + +/* Phy Control Phy operation field */ +#define SMP_PHY_CONTROL_PHY_OPERATION_NOP (0x00) +#define SMP_PHY_CONTROL_PHY_OPERATION_LINK_RESET (0x01) +#define SMP_PHY_CONTROL_PHY_OPERATION_HARD_RESET (0x02) +#define SMP_PHY_CONTROL_PHY_OPERATION_DISABLE (0x03) +#define SMP_PHY_CONTROL_PHY_OPERATION_CLEAR_ERROR_LOG (0x05) +#define SMP_PHY_CONTROL_PHY_OPERATION_CLEAR_AFFILIATION (0x06) +#define SMP_PHY_CONTROL_TRANSMIT_SATA_PORT_SEL_SIGNAL (0x07) + +/* Phy Control programmed physical link rates */ +#define SMP_PHY_CONTROL_PHYSICAL_LINK_RATE_DONT_CHANGE (0x0) +#define SMP_PHY_CONTROL_PHYSICAL_LINK_RATE_1_5_GBPS (0x8) +#define SMP_PHY_CONTROL_PHYSICAL_LINK_RATE_3_0_GBPS (0x9) + +/* + * SMP Phy Control response + */ + +typedef struct _SMP_PHY_CONTROL_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U32 CRC; +} SMP_PHY_CONTROL_RESPONSE, *PTR_SMP_PHY_CONTROL_RESPONSE; + + +/* set allowable vendor unique write size to maximum - SDE12 EDS shows + * granularity as double dwords, but just treat as dwords here + */ +#define MAX_SMP_REGISTERS (254) + + +/* + * This section contains generic SGPIO R/W SMP commands + */ + +typedef struct _SMP_READ_N_GPIO_REGISTERS_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 RegisterType; /* 0x02 */ + U8 RegisterIndex; /* 0x03 */ + U8 RegisterCount; /* 0x04 */ + U8 Reserved05[3]; /* 0x05 */ +} SMP_READ_N_GPIO_REGISTERS_REQUEST, *PTR_SMP_READ_N_GPIO_REGISTERS_REQUEST; + +typedef struct _SMP_READ_N_GPIO_REGISTERS_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 Reserved03; /* 0x03 */ + U32 ReadData[1]; /* 0x08-... */ + /* Note this field can actually be up to MAX_SMP_REGISTERS dwords long */ +} SMP_READ_N_GPIO_REGISTERS_RESPONSE, *PTR_SMP_READ_N_GPIO_REGISTERS_RESPONSE; + +typedef struct _SMP_WRITE_N_GPIO_REGISTERS_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 RegisterType; /* 0x02 */ + U8 RegisterIndex; /* 0x03 */ + U8 RegisterCount; /* 0x04 */ + U8 Reserved05[3]; /* 0x05 */ + U32 WriteData[1]; /* 0x08-... */ + /* Note this field can actually be up to MAX_SMP_REGISTERS dwords long */ +} SMP_WRITE_N_GPIO_REGISTERS_REQUEST, *PTR_SMP_WRITE_N_GPIO_REGISTERS_REQUEST; + +typedef struct _SMP_WRITE_N_REGISTERS_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 Reserved03; /* 0x03 */ + U32 CRC; +} SMP_WRITE_N_GPIO_REGISTERS_RESPONSE, *PTR_SMP_WRITE_N_GPIO_REGISTERS_RESPONSE; + +/* This section contains vendor unique SMP commands for the LSI expander */ + +#define LSI_AHB_WRITE_N_BYTE_WRITE (0x08000000) +#define LSI_AHB_WRITE_N_ADDR_MASK (0xf7ffffff) + +typedef struct _SMP_LSI_AHB_WRITE_N_REGISTERS_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 Reserved02; /* 0x02 */ + U8 N; /* 0x03 */ + U32 StartAddr; /* 0x04 - 0x07 */ + U32 WriteData[1]; /* 0x08-... */ +} SMP_LSI_AHB_WRITE_N_REGISTERS_REQUEST, *PTR_SMP_LSI_AHB_WRITE_N_REGISTERS_REQUEST; + +typedef struct _SMP_LSI_AHB_WRITE_N_REGISTERS_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 Reserved03; /* 0x03 */ + U32 CRC; +} SMP_LSI_AHB_WRITE_N_REGISTERS_RESPONSE, *PTR_SMP_LSI_AHB_WRITE_N_REGISTERS_RESPONSE; + +typedef struct _SMP_LSI_AHB_READ_N_REGISTERS_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 Reserved02; /* 0x02 */ + U8 N; /* 0x03 */ + U32 StartAddr; /* 0x04 - 0x07 */ +} SMP_LSI_AHB_READ_N_REGISTERS_REQUEST, *PTR_SMP_LSI_AHB_READ_N_REGISTERS_REQUEST; + +typedef struct _SMP_LSI_AHB_READ_N_REGISTERS_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 Reserved03; /* 0x03 */ + U32 ReadData[1]; /* 0x04-... */ +} SMP_LSI_AHB_READ_N_REGISTERS_RESPONSE, *PTR_SMP_LSI_AHB_READ_N_REGISTERS_RESPONSE; + +typedef struct _SMP_LSIX12_WRITE_N_REGISTERS_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 Reserved02; /* 0x02 */ + U8 N; /* 0x03 */ + U16 StartAdr; /* 0x04 */ + U8 StartByteEnables; /* 0x06 */ + U8 EndByteEnables; /* 0x07 */ + U32 WriteData[2]; /* 0x08-... */ + /* Note this field can actually be up to MAX_SMP_REGISTERS dwords long */ +} SMP_LSIX12_WRITE_N_REGISTERS_REQUEST, *PTR_SMP_LSIX12_WRITE_N_REGISTERS_REQUEST; + +typedef struct _SMP_LSIX12_WRITE_N_REGISTERS_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 Reserved03; /* 0x03 */ + U32 CRC; +} SMP_LSIX12_WRITE_N_REGISTERS_RESPONSE, *PTR_SMP_LSIX12_WRITE_N_REGISTERS_RESPONSE; + +typedef struct _SMP_LSIX12_READ_N_REGISTERS_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 Reserved02; /* 0x02 */ + U8 N; /* 0x03 */ + U16 StartAdr; /* 0x04 */ + U16 Reserved06and07; /* 0x06 */ + +} SMP_LSIX12_READ_N_REGISTERS_REQUEST, *PTR_SMP_LSIX12_READ_N_REGISTERS_REQUEST; + +typedef struct _SMP_LSIX12_READ_N_REGISTERS_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 Reserved03; /* 0x03 */ + U32 ReadData[1]; /* 0x04-... */ + /* Note this field can actually be up to MAX_SMP_REGISTERS dwords long */ +} SMP_LSIX12_READ_N_REGISTERS_RESPONSE, *PTR_SMP_LSIX12_READ_N_REGISTERS_RESPONSE; + + +#define SMP_SGPIO_REGISTER_TYPE_CFG (0) +#define SMP_SGPIO_REGISTER_TYPE_RX (1) +#define SMP_SGPIO_REGISTER_TYPE_RX_GP (2) +#define SMP_SGPIO_REGISTER_TYPE_TX (3) +#define SMP_SGPIO_REGISTER_TYPE_TX_GP (4) + +/* + * SMP ICL Discover request + */ +typedef struct _SMP_ICL_DISCOVER_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U16 Reserved02and03; /* 0x02 */ + U32 Ignored04to07; /* 0x04 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U8 Ignored0A; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ +} SMP_ICL_DISCOVER_REQUEST, *PTR_SMP_ICL_DISCOVER_REQUEST; + +/* + * SMP ICL Discover response + */ + +typedef struct _SMP_ICL_DISCOVER_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 Reserved03; /* 0x03 */ + U32 Ignored04to07; /* 0x04 */ + U8 Reserved08; /* 0x08 */ + U8 PhyIdentifier; /* 0x09 */ + U8 Ignored0A; /* 0x0A */ + U8 Reserved0B; /* 0x0B */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved0CBit7 :1; /* 0x0C */ + U8 AttachedDeviceType :3; + U8 Ignored0CBits0to3 :4; + U8 Reserved0DBits4to7 :4; /* 0x0D */ + U8 NegotiatedPhysLinkRate :4; + U8 Reserved0EBits4to7 :4; /* 0x0E */ + U8 AttachedSSPInitiator :1; + U8 AttachedSTPInitiator :1; + U8 AttachedSMPInitiator :1; + U8 AttachedSATAHost :1; + U8 Reserved0FBits4to7 :4; /* 0x0F */ + U8 AttachedSSPTarget :1; + U8 AttachedSTPTarget :1; + U8 AttachedSMPTarget :1; + U8 AttachedSATATarget :1; + SAS_ADDRESS SASAddress; /* 0x10 */ + SAS_ADDRESS AttachedSASAddress; /* 0x18 */ + U8 AttachedPhyIdentifier; /* 0x20 */ + U8 Reserved21to27[7]; /* 0x21 */ + U8 ProgMinPhysLinkRate :4; /* 0x28 */ + U8 HardwareMinPhysLinkRate :4; + U8 ProgMaxPhysLinkRate :4; /* 0x29 */ + U8 HardwareMaxPhysLinkRate :4; + U8 PhyChangeCount; /* 0x2A */ + U8 VirtualPhy :1; /* 0x2B */ + U8 Reserved2BBits4to6 :3; + U8 PartialPathTimeoutValue :4; + U8 Reserved2CBits4to7 :4; /* 0x2C */ + U8 RoutingAttribute :4; + U8 Reserved2DBit7 :1; /* 0x2D */ + U8 ConnectorType :7; +#else /* little endian */ + U8 Ignored0CBits0to3 :4; /* 0x0C */ + U8 AttachedDeviceType :3; + U8 Reserved0CBit7 :1; + U8 NegotiatedPhysLinkRate :4; /* 0x0D */ + U8 Reserved0DBits4to7 :4; + U8 AttachedSATAHost :1; /* 0x0E */ + U8 AttachedSMPInitiator :1; + U8 AttachedSTPInitiator :1; + U8 AttachedSSPInitiator :1; + U8 Reserved0EBits4to7 :4; + U8 AttachedSATATarget :1; /* 0x0F */ + U8 AttachedSMPTarget :1; + U8 AttachedSTPTarget :1; + U8 AttachedSSPTarget :1; + U8 Reserved0FBits4to7 :4; + SAS_ADDRESS SASAddress; /* 0x10 */ + SAS_ADDRESS AttachedSASAddress; /* 0x18 */ + U8 AttachedPhyIdentifier; /* 0x20 */ + U8 Reserved21to27[7]; /* 0x21 */ + U8 HardwareMinPhysLinkRate :4; /* 0x28 */ + U8 ProgMinPhysLinkRate :4; + U8 HardwareMaxPhysLinkRate :4; /* 0x29 */ + U8 ProgMaxPhysLinkRate :4; + U8 PhyChangeCount; /* 0x2A */ + U8 PartialPathTimeoutValue :4; /* 0x2B */ + U8 Reserved2BBits4to6 :3; + U8 VirtualPhy :1; + U8 RoutingAttribute :4; /* 0x2C */ + U8 Reserved2CBits4to7 :4; + U8 ConnectorType :7; /* 0x2D */ + U8 Reserved2DBit7 :1; +#endif + + U8 ConnectorElementIndex; + U8 ConnectorPhysicalLink; + U16 Reserved30to31; + + /* Vendor Unique */ + union + { + SMP_X12_VU_DISCOVER_REPSONSE VuX12Connector; /* 0x32 */ + SMP_X12_VU_SLOT_DISCOVER_REPSONSE VuX12Slot; + U16 VendorSpecific; /* 0x32 */ + }u; + U32 CRC; + +} SMP_ICL_DISCOVER_RESPONSE, *PTR_SMP_ICL_DISCOVER_RESPONSE; + +/* + * SMP Configure Zone Phy request + */ +typedef struct _SMP_CONFIGURE_ZONE_PHY_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 ZonePhyConfigDescriptorLength :6; /* 0x06 */ + U8 Save :2; /* 0x06 */ +#else /* little endian */ + U8 Save :2; /* 0x06 */ + U8 ZonePhyConfigDescriptorLength :6; /* 0x06 */ +#endif + U8 NumberOfZonePhyEntries; /* 0x07 */ + /* note: zone phy entry data follows... */ +} SMP_CONFIGURE_ZONE_PHY_REQUEST, *PTR_SMP_CONFIGURE_ZONE_PHY_REQUEST; + +typedef struct _SMP_ZONE_PHY_CONFIG_DESCRIPTOR +{ + U8 PhyIdentifier; /* 0x00 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved01a :2; /* 0x01 */ + U8 InsideZpsdsPersistent :1; + U8 ReqInsideZpsds :1; + U8 Reserved01b :1; + U8 ZoneGroupPersistent :1; + U8 Reserved01 :2; +#else /* little endian */ + U8 Reserved01 :2; /* 0x01 */ + U8 ZoneGroupPersistent :1; + U8 Reserved01b :1; + U8 ReqInsideZpsds :1; + U8 InsideZpsdsPersistent :1; + U8 Reserved01a :2; +#endif + U8 Reserved02; /* 0x02 */ + U8 ZoneGroup; /* 0x03 */ +} SMP_ZONE_PHY_CONFIG_DESCRIPTOR, *PTR_SMP_ZONE_PHY_CONFIG_DESCRIPTOR; + +/* + * SMP Configure Zone Phy response + */ + +typedef struct _SMP_CONFIGURE_ZONE_PHY_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U32 CRC; +} SMP_CONFIGURE_ZONE_PHY_RESPONSE, *PTR_SMP_CONFIGURE_ZONE_PHY_RESPONSE; + +/* + * SMP Configure Zone Permission request + */ +typedef struct _SMP_CONFIGURE_ZONE_PERMISSION_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U8 StartSrcZoneGroup; /* 0x06 */ + U8 NumberOfZoneDescr; /* 0x07 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 NumberOfZoneGroups :2; /* 0x08 */ + U8 Reserved07 :4; + U8 Save :2; +#else /* little endian */ + U8 Save :2; /* 0x08 */ + U8 Reserved07 :4; + U8 NumberOfZoneGroups :2; +#endif + U8 ZonePermCfgDescLen; /* 0x09 */ + U16 Reserved0Ato0B; /* 0x0A - 0x0B */ + U32 Reserved0Cto0F; /* 0x0C - 0x0F */ + /* note: zone permission data follows... */ +} SMP_CONFIGURE_ZONE_PERMISSION_REQUEST, *PTR_SMP_CONFIGURE_ZONE_PERMISSION_REQUEST; + +typedef struct _SMP_ZONE_PERMISSION_DESCRIPTOR +{ + U8 PermBits[32]; +} SMP_ZONE_PERMISSION_DESCRIPTOR, *PTR_SMP_ZONE_PERMISSION_DESCRIPTOR; + +typedef struct _SMP_ZONE_PERMISSION_DESCRIPTOR_YETI +{ + U8 PermBits[16]; +} SMP_ZONE_PERMISSION_DESCRIPTOR_YETI, *PTR_SMP_ZONE_PERMISSION_DESCRIPTOR_YETI; + +/* + * SMP Configure Zone Phy response + */ + +typedef struct _SMP_CONFIGURE_ZONE_PERMISSION_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U32 CRC; +} SMP_CONFIGURE_ZONE_PERMISSION_RESPONSE, *PTR_SMP_CONFIGURE_ZONE_PERMISSION_RESPONSE; + +/* + * SMP Report Zone Permission request + */ +typedef struct _SMP_REPORT_ZONE_PERMISSION_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved04 :6; /* 0x04 */ + U8 ReportType :2; +#else /* little endian */ + U8 ReportType :2; /* 0x04 */ + U8 Reserved04 :6; +#endif + U8 Reserved05; /* 0x05 */ + U8 StartSrcZoneGroup; /* 0x06 */ + U8 MaxNumberOfZoneDescr; /* 0x07 */ +} SMP_REPORT_ZONE_PERMISSION_REQUEST, *PTR_SMP_REPORT_ZONE_PERMISSION_REQUEST; + +/* + * SMP Report Zone Permission Response + */ + +typedef struct _SMP_REPORT_ZONE_PERMISSION_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 ZoneLocked :1; /* 0x06 */ + U8 Reserved06 :5; + U8 ReportType :2; + + U8 NumberOfZoneGroups :2; /* 0x07 Bits 6 - 7 */ + U8 Reserved07Bit0to5 :6; /* 0x07 Bits 0 - 5 */ + +#else /* little endian */ + U8 ReportType :2; /* 0x06 */ + U8 Reserved06 :5; + U8 ZoneLocked :1; + + U8 Reserved07Bit0to5 :6; /* 0x07 Bits 0 - 5 */ + U8 NumberOfZoneGroups :2; /* 0x07 Bits 6 - 7 */ +#endif + U32 Reserved08; /* 0x08 */ + U8 Reserved0c; /* 0x0c */ + U8 ZonePermissionDescriptorLength; /* 0x0d */ + U8 StartSrcZoneGroup; /* 0x0e */ + U8 NumberZonePermissionDescr; /* 0x0f */ + /* zone permission descriptors start here ... */ +} SMP_REPORT_ZONE_PERMISSION_RESPONSE, *PTR_SMP_REPORT_ZONE_PERMISSION_RESPONSE; + +/* + * SMP Enable / Disable Zoning request + */ +typedef struct _SMP_ENABLE_DISABLE_ZONING_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved06 :6; /* 0x06 */ + U8 Save :2; +#else /* little endian */ + U8 Save :2; /* 0x06 */ + U8 Reserved06 :6; +#endif + U8 Reserved07; /* 0x07 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved08 :6; /* 0x08 */ + U8 EnableDisableZoning :2; +#else /* little endian */ + U8 EnableDisableZoning :2; /* 0x08 */ + U8 Reserved08 :6; +#endif + U8 Reserved09; /* 0x09 */ + U16 Reserved0a; /* 0x0a */ +} SMP_ENABLE_DISABLE_ZONING_REQUEST, *PTR_SMP_ENABLE_DISABLE_ZONING_REQUEST; + +#define SMP_ENABLE_NO_CHANGE (0x00) +#define SMP_ENABLE_ENABLE (0x01) +#define SMP_ENABLE_DISABLE (0x02) +#define SMP_ENABLE_DISABLE_RESERVED (0x03) + +/* + * SMP Enable / Disable Zoning response + */ + +typedef struct _SMP_ENABLE_DISABLE_ZONING_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U32 CRC; +} SMP_ENABLE_DISABLE_ZONING_RESPONSE, *PTR_SMP_ENABLE_DISABLE_ZONING_RESPONSE; + +/* + * SMP Zone Activate request + */ +typedef struct _SMP_ZONE_ACTIVATE_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U16 Reserved06; /* 0x06 */ +} SMP_ZONE_ACTIVATE_REQUEST, *PTR_SMP_ZONE_ACTIVATE_REQUEST; + +/* + * SMP Zone Activate response + */ + +typedef struct _SMP_ZONE_ACTIVATE_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U32 CRC; +} SMP_ZONE_ACTIVATE_RESPONSE, *PTR_SMP_ZONE_ACTIVATE_RESPONSE; + + +/* + * SMP Configure Zone Manager Password request */ + +#define SMP_ZONE_PASSWORD_LEN (32) + +typedef struct _SMP_CONFIGURE_ZONE_MANAGER_PASSWORD_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved06 :6; /* 0x06 */ + U8 Save :2; +#else /* little endian */ + U8 Save :2; /* 0x06 */ + U8 Reserved06 :6; +#endif + U8 Reserved07; /* 0x07 */ + U8 ZoneManagerPassword[SMP_ZONE_PASSWORD_LEN]; /* 0x08 - 0x27 */ + U8 NewZoneManagerPassword[SMP_ZONE_PASSWORD_LEN]; /* 0x28 - 0x47 */ + +} SMP_CONFIGURE_ZONE_MANAGER_PASSWORD_REQUEST, *PTR_SMP_CONFIGURE_ZONE_MANAGER_PASSWORD_REQUEST; + +/* + * SMP Configure Zone Manager Password response */ + +typedef struct _SMP_CONFIGURE_ZONE_MANAGER_PASSWORD_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U32 CRC; +} SMP_CONFIGURE_ZONE_MANAGER_PASSWORD_RESPONSE, *PTR_SMP_CONFIGURE_ZONE_MANAGER_PASSWORD_RESPONSE; + + +/* + * SMP Zone Lock request + */ + +typedef struct _SMP_ZONE_LOCK_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 ExpanderChangeCount; /* 0x04 */ + U16 ZoneLockInactivityTimeLimit; /* 0x06 */ + U8 ZonePassword[SMP_ZONE_PASSWORD_LEN];/* 0x08 */ +} SMP_ZONE_LOCK_REQUEST, *PTR_SMP_ZONE_LOCK_REQUEST; + +/* + * SMP Zone Lock response + */ +typedef struct _SMP_ZONE_LOCK_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U32 Reserved04; /* 0x04 */ + SAS_ADDRESS ActiveZoneManager; /* 0x08 */ + U32 CRC; +} SMP_ZONE_LOCK_RESPONSE, *PTR_SMP_ZONE_LOCK_RESPONSE; + +/* + * SMP Zone Unlock request + */ +typedef struct _SMP_ZONE_UNLOCK_REQUEST +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 ResponseLength; /* 0x02 */ + U8 RequestLength; /* 0x03 */ + U16 Reserved04; /* 0x04 */ +#if defined( __LSIUTIL_BIG_ENDIAN__ ) + U8 Reserved06 :7; /* 0x06 */ + U8 ActivateRequired :1; +#else /* little endian */ + U8 ActivateRequired :1; /* 0x06 */ + U8 Reserved06 :7; +#endif + U8 Reserved07; /* 0x07 */ +} SMP_ZONE_UNLOCK_REQUEST, *PTR_SMP_ZONE_UNLOCK_REQUEST; + +/* + * SMP Zone Unlock response + */ +typedef struct _SMP_ZONE_UNLOCK_RESPONSE +{ + U8 SMPFrameType; /* 0x00 */ + U8 Function; /* 0x01 */ + U8 FunctionResult; /* 0x02 */ + U8 ResponseLength; /* 0x03 */ + U32 CRC; +} SMP_ZONE_UNLOCK_RESPONSE, *PTR_SMP_ZONE_UNLOCK_RESPONSE; + +/* Union of all the SMP Request Frames */ +typedef union _SMP_REQUEST_UNION +{ + SMP_REQUEST SMPRequestGeneric; + SMP_REPORT_GENERAL_REQUEST SMPReportGeneralRequest; + SMP_REPORT_MANUFACTURER_INFO_REQUEST SMPReportManufacturerInfoRequest; + SMP_REPORT_SELF_CONFIG_STATUS_REQUEST SMPReportSelfConfigStatusRequest; + SMP_DISCOVER_REQUEST SMPDiscoverRequest; + SMP_REPORT_PHY_ERROR_LOG_REQUEST SMPReportPhyErrorLogRequest; + SMP_REPORT_PHY_SATA_REQUEST SMPReportPhySataRequest; + SMP_REPORT_ROUTE_INFO_REQUEST SMPReportRouteInfoRequest; + SMP_CONFIGURE_ROUTE_INFO_REQUEST SMPConfigureRouteInfoRequest; + SMP_REPORT_EXP_ROUTE_TABLE_REQUEST SMPReportExpRouteTableRequest; + SMP_PHY_CONTROL_REQUEST SMPPhyControlRequest; + /* These are generic SGPIO Register R/W */ + SMP_WRITE_N_GPIO_REGISTERS_REQUEST SMPWriteNGpioRegistersRequest; + SMP_READ_N_GPIO_REGISTERS_REQUEST SMPReadNGpioRegistersRequest; + /* These are vendor unique for Sasquatch expander */ + SMP_LSIX12_WRITE_N_REGISTERS_REQUEST SMPLsiX12WriteNRegistersRequest; + SMP_LSIX12_READ_N_REGISTERS_REQUEST SMPLsiX12ReadNRegistersRequest; + SMP_ICL_DISCOVER_REQUEST SMPIclDiscoverRequest; + SMP_LSI_AHB_WRITE_N_REGISTERS_REQUEST SMPLsiAhbWriteNRegistersRequest; + SMP_LSI_AHB_READ_N_REGISTERS_REQUEST SMPLsiAhbReadNRegistersRequest; + /* Zoning Requests */ + SMP_CONFIGURE_ZONE_PHY_REQUEST SMPConfigureZonePhyRequest; + SMP_CONFIGURE_ZONE_PERMISSION_REQUEST SMPConfigureZonePermissionRequest; + SMP_REPORT_ZONE_PERMISSION_REQUEST SMPReportZonePermissionRequest; + SMP_ENABLE_DISABLE_ZONING_REQUEST SMPEnableDisableZoningRequest; + SMP_ZONE_ACTIVATE_REQUEST SMPZoneActivateRequest; + SMP_ZONE_LOCK_REQUEST SMPZoneLockRequest; + SMP_ZONE_UNLOCK_REQUEST SMPZoneUnlockRequest; +} SMP_REQUEST_UNION, * PTR_SMP_REQUEST_UNION; + +/* Union of all the SMP Response Frames */ +typedef union _SMP_RESPONSE_UNION +{ + SMP_RESPONSE SMPResponseGeneric; + SMP_REPORT_GENERAL_RESPONSE SMPReportGeneralResponse; + SMP_REPORT_MANUFACTURER_INFO_RESPONSE SMPReportManufacturerInfoResponse; + SMP_REPORT_SELF_CONFIG_STATUS_RESPONSE SMPReportSelfConfigStatusResponse; + SMP_DISCOVER_RESPONSE SMPDiscoverResponse; + SMP_REPORT_PHY_ERROR_LOG_RESPONSE SMPReportPhyErrorLogResponse; + SMP_REPORT_PHY_SATA_RESPONSE SMPReportPhySataResponse; + SMP_REPORT_ROUTE_INFO_RESPONSE SMPReportRouteInfoResponse; + SMP_CONFIGURE_ROUTE_INFO_RESPONSE SMPConfigureRouteInfoResponse; + SMP_REPORT_EXP_ROUTE_TABLE_RESPONSE SMPReportExpRouteTableResponse; + SMP_PHY_CONTROL_RESPONSE SMPPhyControlResponse; + /* These are vendor unique for Sasquatch expander */ + SMP_WRITE_N_GPIO_REGISTERS_RESPONSE SMPWriteNGpioRegistersResponse; + SMP_READ_N_GPIO_REGISTERS_RESPONSE SMPReadNGpioRegistersResponse; + /* These are vendor unique for Sasquatch expander */ + SMP_LSIX12_WRITE_N_REGISTERS_RESPONSE SMPLsiX12WriteNRegistersResponse; + SMP_LSIX12_READ_N_REGISTERS_RESPONSE SMPLsiX12ReadNRegistersResponse; + SMP_ICL_DISCOVER_RESPONSE SMPIclDiscoverResponse; + SMP_LSI_AHB_WRITE_N_REGISTERS_RESPONSE SMPLsiAhbWriteNRegistersResponse; + SMP_LSI_AHB_READ_N_REGISTERS_RESPONSE SMPLsiAhbReadNRegistersResponse; + /* Zoning */ + SMP_CONFIGURE_ZONE_PHY_RESPONSE SMPConfigureZonePhyResponse; + SMP_CONFIGURE_ZONE_PERMISSION_RESPONSE SMPConfigureZonePermissionResponse; + SMP_REPORT_ZONE_PERMISSION_RESPONSE SMPReportZonePermissionResponse; + SMP_ENABLE_DISABLE_ZONING_RESPONSE SMPEnableDisableZoningResponse; + SMP_ZONE_ACTIVATE_RESPONSE SMPZoneActivateResponse; + SMP_ZONE_LOCK_RESPONSE SMPZoneLockResponse; + SMP_ZONE_UNLOCK_RESPONSE SMPZoneUnlockResponse; +} SMP_RESPONSE_UNION, * PTR_SMP_RESPONSE_UNION; + +#endif /* End of #ifndef SAS_H_SOURCE */ + diff --git a/source/inc/sym_dmi.h b/source/inc/sym_dmi.h new file mode 100755 index 0000000..a4cfa80 --- /dev/null +++ b/source/inc/sym_dmi.h @@ -0,0 +1,268 @@ +/* FILE: sym_dmi.h - MPT/Fusion Driver IOCTL Support header file +* +************************************************************************* +* * +* Copyright 2001 LSI Logic. All rights reserved. * +* * +* This file is confidential and a trade secret of LSI Logic. * +* The receipt of or possession of this file does not convey any * +* rights to reproduce or disclose its contents or to manufacture, * +* use, or sell anything is may describe, in whole, or in part, * +* without the specific written consent of LSI Logic. * +* * +************************************************************************/ + +/*+++HDR + * + * Version History + * --------------- + * + * Date Who? Description + * -------- ---- ------------------------------------------------------- + * 03/20/00 SAM Initial version + * 02/14/01 SCH Added Domain Validation + * 05/14/01 SCH Added MPI Event logging + * 07/09/01 SCH Changed MAX_VERSION_STRING from 80 to 32 + * 01/02/02 SCH Added MPI diagnostic reset IOCTL + * 10/30/03 SCH Added InBand IOCTL support + * 03/24/04 BJH Added Diagnostic IOCTL support + * 09/10/08 SCH Added ADAPTER_TYPE_SAS2 define + * 10/20/08 SCH Modified diag buffer structures for Gen2 +---*/ + +#ifndef SYM_DMI_H +#define SYM_DMI_H + +#define VERSION_SIZE 4 +#define MAX_VERSION_STRING 32 + +// support for MPI messages via an application or service IOCTL + +#define MPI_MSG_IOCTL 0x806D7069 // mpi +#define DATA_FROM_APP 0x01 +#define SCSI_IO 0x4000 +#define DUAL_SGLS 0x8000 + +typedef struct _IOCTL_DETAILS { + U16 Dir; // data xfer direction + U16 MsgSize; // size in 32 bit words + U32 DataSize; // data xfer size in bytes + U32 FormattedMsg[1]; +} IOCTL_DETAILS, *pIOCTL_DETAILS; + + +// support for host driver info / MPI event logging IOCTL + +#define DRVR_INFO_IOCTL 0x8043494D // CIM + +/* Adapter Types */ +#define ADAPTER_TYPE_SCSI 0 +#define ADAPTER_TYPE_SCSI_OVER_FC 1 +#define ADAPTER_TYPE_IP_OVER_FC 2 +#define ADAPTER_TYPE_SAS 3 +#define ADAPTER_TYPE_SAS2 4 + +/* Page Codes */ +#define ADAPTER_INFO_PAGE 1 +#define PCI_CONFIG_SPACE_PAGE 3 +#define EVENT_QUERY 10 +#define EVENT_ENABLE 11 +#define GET_EVENTS 12 + +/* Event Queue Defines */ +#define EVENT_QUEUE_SIZE 50 +#define MAX_EVENT_DATA_LENGTH 48 + +// structure to hold PCI bus/device/function information +typedef struct _MPI_PCI_INFO { + union { + struct { + ULONG DeviceNumber:5; + ULONG FunctionNumber:3; + ULONG BusNumber:24; + } bits; + ULONG AsULONG; + } u; +} MPI_PCI_INFO, *PMPI_PCI_INFO; + +// Adapter Info structure +typedef struct _DRVR_ADAPTER_INFO_OUT +{ + int AdapterType; + int MpiPortNumber; + int PciDeviceId; + int PciDeviceHwRev; + int SubSystem; + int SubSystemVendorId; + int NumDevicesAttached; + int MpiVersion; + U32 BiosVersion; + char DriverVersion[MAX_VERSION_STRING]; + BOOLEAN BusChangeEvent; + U8 HostId; + U16 Reserved1; + MPI_PCI_INFO PciInfo; + U32 PciSegmentId; +} DRVR_ADAPTER_INFO_OUT, *PTR_DRVR_ADAPTER_INFO_OUT; + +typedef struct _DRVR_INFO_SRB +{ + SRB_IO_CONTROL Sic; + int PageCode; // [IN] + char PageVersion[VERSION_SIZE]; // [OUT] + DRVR_ADAPTER_INFO_OUT AdapterPageOut; +} DRVR_INFO_SRB, *PTR_DRVR_INFO_SRB; + +typedef struct _PCI_CONFIG_SPACE_SRB +{ + SRB_IO_CONTROL Sic; + int PageCode; // [IN] + char PageVersion[VERSION_SIZE]; // [OUT] + U32 reserved[3]; + U8 PciConfigSpace[256]; +} PCI_CONFIG_SPACE_SRB, *PTR_PCI_CONFIG_SPACE_SRB; + +// support for MPI Event Queue + +typedef struct _MPI_EVENTS_SRB +{ + SRB_IO_CONTROL Sic; + int PageCode; // [IN] + char PageVersion[VERSION_SIZE]; // [OUT] + U32 EventData[1]; // page code dependent +} MPI_EVENTS_SRB, *PTR_MPI_EVENTS_SRB; + +typedef struct _MPI_EVENTS_QUEUE +{ + U32 EventType; // from reply frame + U32 EventNumber; // from DevExt->EventNum + U32 EventData[MAX_EVENT_DATA_LENGTH]; // from reply frame +} MPI_EVENTS_QUEUE, *PTR_MPI_EVENTS_QUEUE; + +// support for MPI Diagnostic Reset IOCTL + +#define MPI_DIAG_RESET 0x80727374 // rst + +typedef struct _MPI_DIAG_RESET_SRB +{ + SRB_IO_CONTROL Sic; + U32 NewImageSize; // replacement image size + U32 NewFWImage[1]; // new FW image to save +} MPI_DIAG_RESET_SRB, *PTR_MPI_DIAG_RESET_SRB; +// A NewImageSize of 0 indicates that no new FW image is being downloaded + +// MPI register reae/write access IOCTL +#define MPI_REG_ACCESS 0x80771959 // magic number +#define REG_IO_READ 1 +#define REG_IO_WRITE 2 +#define REG_MEM_READ 3 +#define REG_MEM_WRITE 4 + +typedef struct _MPI_REG_ACCESS_SRB +{ + SRB_IO_CONTROL Sic; + U32 Command; // command (read/write) + U32 RegOffset; // register offset + U32 RegData; // register data +} MPI_REG_ACCESS_SRB, *PTR_MPI_REG_ACCESS_SRB; + +// support for bus/target - DevHandle mapping IOCTL +// application can suppy bus/target and get devHandle or +// supply devHandle and get bus/target + +#define MPI_BTDH_MAPPING 0x804D4150 // MAP + +typedef struct _MPI_BTDH_MAP_SRB +{ + SRB_IO_CONTROL Sic; + U32 TargetID; // target ID + U32 Bus; // bus + U16 DevHandle; // device handle + U16 Reserved; +} MPI_BTDH_MAP_SRB, *PTR_MPI_BTDH_MAP_SRB; + + + +#define MPI_FW_DIAG_IOCTL (0x80646961) // dia +#define MPI_FW_DIAG_NEW (0x806E6577) // new +#define MPI_FW_DIAG_TYPE_REGISTER (0x00000001) +#define MPI_FW_DIAG_TYPE_UNREGISTER (0x00000002) +#define MPI_FW_DIAG_TYPE_QUERY (0x00000003) +#define MPI_FW_DIAG_TYPE_READ_BUFFER (0x00000004) +#define MPI_FW_DIAG_TYPE_RELEASE (0x00000005) + +#define MPI_FW_DIAG_INVALID_UID (0x00000000) +#define FW_DIAGNOSTIC_BUFFER_COUNT (3) +#define FW_DIAGNOSTIC_UID_NOT_FOUND (0xFF) + +#define MPI_FW_DIAG_ERROR_SUCCESS (0x00000000) +#define MPI_FW_DIAG_ERROR_FAILURE (0x00000001) +#define MPI_FW_DIAG_ERROR_INVALID_PARAMETER (0x00000003) +#define MPI_FW_DIAG_ERROR_POST_FAILED (0x00000010) +#define MPI_FW_DIAG_ERROR_INVALID_UID (0x00000011) +#define MPI_FW_DIAG_ERROR_RELEASE_FAILED (0x00000012) +#define MPI_FW_DIAG_ERROR_NO_BUFFER (0x00000013) +#define MPI_FW_DIAG_ERROR_ALREADY_RELEASED (0x00000014) + +typedef struct _MPI_FW_DIAG_IOCTL_SRB +{ + SRB_IO_CONTROL Sic; + U32 MpiDiagType; + U8 PageVersion[4]; + U32 MpiDiagData[1]; +} MPI_FW_DIAG_IOCTL_SRB, *PTR_MPI_FW_DIAG_IOCTL_SRB; + +/* diag register for gen 1 */ +typedef struct _MPI_FW_DIAG_REGISTER +{ + U8 TraceLevel; + U8 BufferType; + U16 Flags; + U32 ExtendedType; + U32 ProductSpecific[4]; + U32 RequestedBufferSize; + U32 UniqueId; +} MPI_FW_DIAG_REGISTER, *PTR_MPI_FW_DIAG_REGISTER; + +typedef struct _MPI_FW_DIAG_UNREGISTER +{ + U32 UniqueId; +} MPI_FW_DIAG_UNREGISTER, *PTR_MPI_FW_DIAG_UNREGISTER; + +#define MPI_FW_DIAG_FLAG_APP_OWNED (0x0001) +#define MPI_FW_DIAG_FLAG_BUFFER_VALID (0x0002) +#define MPI_FW_DIAG_FLAG_FW_BUFFER_ACCESS (0x0004) + +/* diag query for gen 1 */ +typedef struct _MPI_FW_DIAG_QUERY +{ + U8 TraceLevel; + U8 BufferType; + U16 Flags; + U32 ExtendedType; + U32 ProductSpecific[4]; + U32 TotalBufferSize; + U32 DriverAddedBufferSize; + U32 UniqueId; +} MPI_FW_DIAG_QUERY, *PTR_MPI_FW_DIAG_QUERY; + +typedef struct _MPI_FW_DIAG_RELEASE +{ + U32 UniqueId; +} MPI_FW_DIAG_RELEASE, *PTR_MPI_FW_DIAG_RELEASE; + +#define MPI_FW_DIAG_FLAG_REREGISTER (0x0001) +#define MPI_FW_DIAG_FLAG_FORCE_RELEASE (0x0002) + +typedef struct _MPI_FW_DIAG_READ_BUFFER +{ + U8 Status; + U8 Reserved; + U16 Flags; + U32 StartingOffset; + U32 BytesToRead; + U32 UniqueId; + U32 DataBuffer[1]; +} MPI_FW_DIAG_READ_BUFFER, *PTR_MPI_FW_DIAG_READ_BUFFER; + +#endif diff --git a/source/lsi/mpi.h b/source/lsi/mpi.h new file mode 100755 index 0000000..d5e9f67 --- /dev/null +++ b/source/lsi/mpi.h @@ -0,0 +1,800 @@ +/* + * Copyright (c) 2000-2008 LSI Corporation. + * + * + * Name: mpi.h + * Title: MPI Message independent structures and definitions + * Creation Date: July 27, 2000 + * + * mpi.h Version: 01.05.17 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. + * 05-24-00 00.10.02 Added MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH definition. + * 06-06-00 01.00.01 Update MPI_VERSION_MAJOR and MPI_VERSION_MINOR. + * 06-22-00 01.00.02 Added MPI_IOCSTATUS_LAN_ definitions. + * Removed LAN_SUSPEND function definition. + * Added MPI_MSGFLAGS_CONTINUATION_REPLY definition. + * 06-30-00 01.00.03 Added MPI_CONTEXT_REPLY_TYPE_LAN definition. + * Added MPI_GET/SET_CONTEXT_REPLY_TYPE macros. + * 07-27-00 01.00.04 Added MPI_FAULT_ definitions. + * Removed MPI_IOCSTATUS_MSG/DATA_XFER_ERROR definitions. + * Added MPI_IOCSTATUS_INTERNAL_ERROR definition. + * Added MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH. + * 11-02-00 01.01.01 Original release for post 1.0 work. + * 12-04-00 01.01.02 Added new function codes. + * 01-09-01 01.01.03 Added more definitions to the system interface section + * Added MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT. + * 01-25-01 01.01.04 Changed MPI_VERSION_MINOR from 0x00 to 0x01. + * 02-20-01 01.01.05 Started using MPI_POINTER. + * Fixed value for MPI_DIAG_RW_ENABLE. + * Added defines for MPI_DIAG_PREVENT_IOC_BOOT and + * MPI_DIAG_CLEAR_FLASH_BAD_SIG. + * Obsoleted MPI_IOCSTATUS_TARGET_FC_ defines. + * 02-27-01 01.01.06 Removed MPI_HOST_INDEX_REGISTER define. + * Added function codes for RAID. + * 04-09-01 01.01.07 Added alternate define for MPI_DOORBELL_ACTIVE, + * MPI_DOORBELL_USED, to better match the spec. + * 08-08-01 01.02.01 Original release for v1.2 work. + * Changed MPI_VERSION_MINOR from 0x01 to 0x02. + * Added define MPI_FUNCTION_TOOLBOX. + * 09-28-01 01.02.02 New function code MPI_SCSI_ENCLOSURE_PROCESSOR. + * 11-01-01 01.02.03 Changed name to MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR. + * 03-14-02 01.02.04 Added MPI_HEADER_VERSION_ defines. + * 05-31-02 01.02.05 Bumped MPI_HEADER_VERSION_UNIT. + * 07-12-02 01.02.06 Added define for MPI_FUNCTION_MAILBOX. + * 09-16-02 01.02.07 Bumped value for MPI_HEADER_VERSION_UNIT. + * 11-15-02 01.02.08 Added define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX and + * obsoleted define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX. + * 04-01-03 01.02.09 New IOCStatus code: MPI_IOCSTATUS_FC_EXCHANGE_CANCELED + * 06-26-03 01.02.10 Bumped MPI_HEADER_VERSION_UNIT value. + * 01-16-04 01.02.11 Added define for MPI_IOCLOGINFO_TYPE_SHIFT. + * 04-29-04 01.02.12 Added function codes for MPI_FUNCTION_DIAG_BUFFER_POST + * and MPI_FUNCTION_DIAG_RELEASE. + * Added MPI_IOCSTATUS_DIAGNOSTIC_RELEASED define. + * Bumped MPI_HEADER_VERSION_UNIT value. + * 05-11-04 01.03.01 Bumped MPI_VERSION_MINOR for MPI v1.3. + * Added codes for Inband. + * 08-19-04 01.05.01 Added defines for Host Buffer Access Control doorbell. + * Added define for offset of High Priority Request Queue. + * Added new function codes and new IOCStatus codes. + * Added a IOCLogInfo type of SAS. + * 12-07-04 01.05.02 Bumped MPI_HEADER_VERSION_UNIT. + * 12-09-04 01.05.03 Bumped MPI_HEADER_VERSION_UNIT. + * 01-15-05 01.05.04 Bumped MPI_HEADER_VERSION_UNIT. + * 02-09-05 01.05.05 Bumped MPI_HEADER_VERSION_UNIT. + * 02-22-05 01.05.06 Bumped MPI_HEADER_VERSION_UNIT. + * 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and + * TargetAssistExtended requests. + * Removed EEDP IOCStatus codes. + * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and + * TargetAssistExtended requests. + * Added EEDP IOCStatus codes. + * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT. + * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target. + * 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT. + * 10-11-06 01.05.12 Bumped MPI_HEADER_VERSION_UNIT. + * 05-24-07 01.05.13 Bumped MPI_HEADER_VERSION_UNIT. + * 08-07-07 01.05.14 Bumped MPI_HEADER_VERSION_UNIT. + * 01-15-08 01.05.15 Bumped MPI_HEADER_VERSION_UNIT. + * 03-28-08 01.05.16 Bumped MPI_HEADER_VERSION_UNIT. + * 07-11-08 01.05.17 Bumped MPI_HEADER_VERSION_UNIT. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_H +#define MPI_H + + +/***************************************************************************** +* +* M P I V e r s i o n D e f i n i t i o n s +* +*****************************************************************************/ + +#define MPI_VERSION_MAJOR (0x01) +#define MPI_VERSION_MINOR (0x05) +#define MPI_VERSION_MAJOR_MASK (0xFF00) +#define MPI_VERSION_MAJOR_SHIFT (8) +#define MPI_VERSION_MINOR_MASK (0x00FF) +#define MPI_VERSION_MINOR_SHIFT (0) +#define MPI_VERSION ((MPI_VERSION_MAJOR << MPI_VERSION_MAJOR_SHIFT) | \ + MPI_VERSION_MINOR) + +#define MPI_VERSION_01_00 (0x0100) +#define MPI_VERSION_01_01 (0x0101) +#define MPI_VERSION_01_02 (0x0102) +#define MPI_VERSION_01_03 (0x0103) +#define MPI_VERSION_01_05 (0x0105) +/* Note: The major versions of 0xe0 through 0xff are reserved */ + +/* versioning for this MPI header set */ +#define MPI_HEADER_VERSION_UNIT (0x14) +#define MPI_HEADER_VERSION_DEV (0x00) +#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) +#define MPI_HEADER_VERSION_UNIT_SHIFT (8) +#define MPI_HEADER_VERSION_DEV_MASK (0x00FF) +#define MPI_HEADER_VERSION_DEV_SHIFT (0) +#define MPI_HEADER_VERSION ((MPI_HEADER_VERSION_UNIT << 8) | MPI_HEADER_VERSION_DEV) + +/***************************************************************************** +* +* I O C S t a t e D e f i n i t i o n s +* +*****************************************************************************/ + +#define MPI_IOC_STATE_RESET (0x00000000) +#define MPI_IOC_STATE_READY (0x10000000) +#define MPI_IOC_STATE_OPERATIONAL (0x20000000) +#define MPI_IOC_STATE_FAULT (0x40000000) + +#define MPI_IOC_STATE_MASK (0xF0000000) +#define MPI_IOC_STATE_SHIFT (28) + +/* Fault state codes (product independent range 0x8000-0xFFFF) */ + +#define MPI_FAULT_REQUEST_MESSAGE_PCI_PARITY_ERROR (0x8111) +#define MPI_FAULT_REQUEST_MESSAGE_PCI_BUS_FAULT (0x8112) +#define MPI_FAULT_REPLY_MESSAGE_PCI_PARITY_ERROR (0x8113) +#define MPI_FAULT_REPLY_MESSAGE_PCI_BUS_FAULT (0x8114) +#define MPI_FAULT_DATA_SEND_PCI_PARITY_ERROR (0x8115) +#define MPI_FAULT_DATA_SEND_PCI_BUS_FAULT (0x8116) +#define MPI_FAULT_DATA_RECEIVE_PCI_PARITY_ERROR (0x8117) +#define MPI_FAULT_DATA_RECEIVE_PCI_BUS_FAULT (0x8118) + + +/***************************************************************************** +* +* P C I S y s t e m I n t e r f a c e R e g i s t e r s +* +*****************************************************************************/ + +/* + * Defines for working with the System Doorbell register. + * Values for doorbell function codes are included in the section that defines + * all the function codes (further on in this file). + */ +#define MPI_DOORBELL_OFFSET (0x00000000) +#define MPI_DOORBELL_ACTIVE (0x08000000) /* DoorbellUsed */ +#define MPI_DOORBELL_USED (MPI_DOORBELL_ACTIVE) +#define MPI_DOORBELL_ACTIVE_SHIFT (27) +#define MPI_DOORBELL_WHO_INIT_MASK (0x07000000) +#define MPI_DOORBELL_WHO_INIT_SHIFT (24) +#define MPI_DOORBELL_FUNCTION_MASK (0xFF000000) +#define MPI_DOORBELL_FUNCTION_SHIFT (24) +#define MPI_DOORBELL_ADD_DWORDS_MASK (0x00FF0000) +#define MPI_DOORBELL_ADD_DWORDS_SHIFT (16) +#define MPI_DOORBELL_DATA_MASK (0x0000FFFF) +#define MPI_DOORBELL_FUNCTION_SPECIFIC_MASK (0x0000FFFF) + +/* values for Host Buffer Access Control doorbell function */ +#define MPI_DB_HPBAC_VALUE_MASK (0x0000F000) +#define MPI_DB_HPBAC_ENABLE_ACCESS (0x01) +#define MPI_DB_HPBAC_DISABLE_ACCESS (0x02) +#define MPI_DB_HPBAC_FREE_BUFFER (0x03) + + +#define MPI_WRITE_SEQUENCE_OFFSET (0x00000004) +#define MPI_WRSEQ_KEY_VALUE_MASK (0x0000000F) +#define MPI_WRSEQ_1ST_KEY_VALUE (0x04) +#define MPI_WRSEQ_2ND_KEY_VALUE (0x0B) +#define MPI_WRSEQ_3RD_KEY_VALUE (0x02) +#define MPI_WRSEQ_4TH_KEY_VALUE (0x07) +#define MPI_WRSEQ_5TH_KEY_VALUE (0x0D) + +#define MPI_DIAGNOSTIC_OFFSET (0x00000008) +#define MPI_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400) +#define MPI_DIAG_PREVENT_IOC_BOOT (0x00000200) +#define MPI_DIAG_DRWE (0x00000080) +#define MPI_DIAG_FLASH_BAD_SIG (0x00000040) +#define MPI_DIAG_RESET_HISTORY (0x00000020) +#define MPI_DIAG_RW_ENABLE (0x00000010) +#define MPI_DIAG_RESET_ADAPTER (0x00000004) +#define MPI_DIAG_DISABLE_ARM (0x00000002) +#define MPI_DIAG_MEM_ENABLE (0x00000001) + +#define MPI_TEST_BASE_ADDRESS_OFFSET (0x0000000C) + +#define MPI_DIAG_RW_DATA_OFFSET (0x00000010) + +#define MPI_DIAG_RW_ADDRESS_OFFSET (0x00000014) + +#define MPI_HOST_INTERRUPT_STATUS_OFFSET (0x00000030) +#define MPI_HIS_IOP_DOORBELL_STATUS (0x80000000) +#define MPI_HIS_REPLY_MESSAGE_INTERRUPT (0x00000008) +#define MPI_HIS_DOORBELL_INTERRUPT (0x00000001) + +#define MPI_HOST_INTERRUPT_MASK_OFFSET (0x00000034) +#define MPI_HIM_RIM (0x00000008) +#define MPI_HIM_DIM (0x00000001) + +#define MPI_REQUEST_QUEUE_OFFSET (0x00000040) +#define MPI_REQUEST_POST_FIFO_OFFSET (0x00000040) + +#define MPI_REPLY_QUEUE_OFFSET (0x00000044) +#define MPI_REPLY_POST_FIFO_OFFSET (0x00000044) +#define MPI_REPLY_FREE_FIFO_OFFSET (0x00000044) + +#define MPI_HI_PRI_REQUEST_QUEUE_OFFSET (0x00000048) + + + +/***************************************************************************** +* +* M e s s a g e F r a m e D e s c r i p t o r s +* +*****************************************************************************/ + +#define MPI_REQ_MF_DESCRIPTOR_NB_MASK (0x00000003) +#define MPI_REQ_MF_DESCRIPTOR_F_BIT (0x00000004) +#define MPI_REQ_MF_DESCRIPTOR_ADDRESS_MASK (0xFFFFFFF8) + +#define MPI_ADDRESS_REPLY_A_BIT (0x80000000) +#define MPI_ADDRESS_REPLY_ADDRESS_MASK (0x7FFFFFFF) + +#define MPI_CONTEXT_REPLY_A_BIT (0x80000000) +#define MPI_CONTEXT_REPLY_TYPE_MASK (0x60000000) +#define MPI_CONTEXT_REPLY_TYPE_SCSI_INIT (0x00) +#define MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET (0x01) +#define MPI_CONTEXT_REPLY_TYPE_LAN (0x02) +#define MPI_CONTEXT_REPLY_TYPE_SHIFT (29) +#define MPI_CONTEXT_REPLY_CONTEXT_MASK (0x1FFFFFFF) + + +/****************************************************************************/ +/* Context Reply macros */ +/****************************************************************************/ + +#define MPI_GET_CONTEXT_REPLY_TYPE(x) (((x) & MPI_CONTEXT_REPLY_TYPE_MASK) \ + >> MPI_CONTEXT_REPLY_TYPE_SHIFT) + +#define MPI_SET_CONTEXT_REPLY_TYPE(x, typ) \ + ((x) = ((x) & ~MPI_CONTEXT_REPLY_TYPE_MASK) | \ + (((typ) << MPI_CONTEXT_REPLY_TYPE_SHIFT) & \ + MPI_CONTEXT_REPLY_TYPE_MASK)) + + +/***************************************************************************** +* +* M e s s a g e F u n c t i o n s +* 0x80 -> 0x8F reserved for private message use per product +* +* +*****************************************************************************/ + +#define MPI_FUNCTION_SCSI_IO_REQUEST (0x00) +#define MPI_FUNCTION_SCSI_TASK_MGMT (0x01) +#define MPI_FUNCTION_IOC_INIT (0x02) +#define MPI_FUNCTION_IOC_FACTS (0x03) +#define MPI_FUNCTION_CONFIG (0x04) +#define MPI_FUNCTION_PORT_FACTS (0x05) +#define MPI_FUNCTION_PORT_ENABLE (0x06) +#define MPI_FUNCTION_EVENT_NOTIFICATION (0x07) +#define MPI_FUNCTION_EVENT_ACK (0x08) +#define MPI_FUNCTION_FW_DOWNLOAD (0x09) +#define MPI_FUNCTION_TARGET_CMD_BUFFER_POST (0x0A) +#define MPI_FUNCTION_TARGET_ASSIST (0x0B) +#define MPI_FUNCTION_TARGET_STATUS_SEND (0x0C) +#define MPI_FUNCTION_TARGET_MODE_ABORT (0x0D) +#define MPI_FUNCTION_FC_LINK_SRVC_BUF_POST (0x0E) +#define MPI_FUNCTION_FC_LINK_SRVC_RSP (0x0F) +#define MPI_FUNCTION_FC_EX_LINK_SRVC_SEND (0x10) +#define MPI_FUNCTION_FC_ABORT (0x11) +#define MPI_FUNCTION_FW_UPLOAD (0x12) +#define MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND (0x13) +#define MPI_FUNCTION_FC_PRIMITIVE_SEND (0x14) + +#define MPI_FUNCTION_RAID_ACTION (0x15) +#define MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) + +#define MPI_FUNCTION_TOOLBOX (0x17) + +#define MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) + +#define MPI_FUNCTION_MAILBOX (0x19) + +#define MPI_FUNCTION_SMP_PASSTHROUGH (0x1A) +#define MPI_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) +#define MPI_FUNCTION_SATA_PASSTHROUGH (0x1C) + +#define MPI_FUNCTION_DIAG_BUFFER_POST (0x1D) +#define MPI_FUNCTION_DIAG_RELEASE (0x1E) + +#define MPI_FUNCTION_SCSI_IO_32 (0x1F) + +#define MPI_FUNCTION_LAN_SEND (0x20) +#define MPI_FUNCTION_LAN_RECEIVE (0x21) +#define MPI_FUNCTION_LAN_RESET (0x22) + +#define MPI_FUNCTION_TARGET_ASSIST_EXTENDED (0x23) +#define MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) +#define MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) + +#define MPI_FUNCTION_INBAND_BUFFER_POST (0x28) +#define MPI_FUNCTION_INBAND_SEND (0x29) +#define MPI_FUNCTION_INBAND_RSP (0x2A) +#define MPI_FUNCTION_INBAND_ABORT (0x2B) + +#define MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40) +#define MPI_FUNCTION_IO_UNIT_RESET (0x41) +#define MPI_FUNCTION_HANDSHAKE (0x42) +#define MPI_FUNCTION_REPLY_FRAME_REMOVAL (0x43) +#define MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL (0x44) + + +/* standard version format */ +typedef struct _MPI_VERSION_STRUCT +{ + U8 Dev; /* 00h */ + U8 Unit; /* 01h */ + U8 Minor; /* 02h */ + U8 Major; /* 03h */ +} MPI_VERSION_STRUCT, MPI_POINTER PTR_MPI_VERSION_STRUCT, + MpiVersionStruct_t, MPI_POINTER pMpiVersionStruct; + +typedef union _MPI_VERSION_FORMAT +{ + MPI_VERSION_STRUCT Struct; + U32 Word; +} MPI_VERSION_FORMAT, MPI_POINTER PTR_MPI_VERSION_FORMAT, + MpiVersionFormat_t, MPI_POINTER pMpiVersionFormat_t; + + +/***************************************************************************** +* +* S c a t t e r G a t h e r E l e m e n t s +* +*****************************************************************************/ + +/****************************************************************************/ +/* Simple element structures */ +/****************************************************************************/ + +typedef struct _SGE_SIMPLE32 +{ + U32 FlagsLength; + U32 Address; +} SGE_SIMPLE32, MPI_POINTER PTR_SGE_SIMPLE32, + SGESimple32_t, MPI_POINTER pSGESimple32_t; + +typedef struct _SGE_SIMPLE64 +{ + U32 FlagsLength; + U64 Address; +} SGE_SIMPLE64, MPI_POINTER PTR_SGE_SIMPLE64, + SGESimple64_t, MPI_POINTER pSGESimple64_t; + +typedef struct _SGE_SIMPLE_UNION +{ + U32 FlagsLength; + union + { + U32 Address32; + U64 Address64; + }u; +} SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION, + SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t; + +/****************************************************************************/ +/* Chain element structures */ +/****************************************************************************/ + +typedef struct _SGE_CHAIN32 +{ + U16 Length; + U8 NextChainOffset; + U8 Flags; + U32 Address; +} SGE_CHAIN32, MPI_POINTER PTR_SGE_CHAIN32, + SGEChain32_t, MPI_POINTER pSGEChain32_t; + +typedef struct _SGE_CHAIN64 +{ + U16 Length; + U8 NextChainOffset; + U8 Flags; + U64 Address; +} SGE_CHAIN64, MPI_POINTER PTR_SGE_CHAIN64, + SGEChain64_t, MPI_POINTER pSGEChain64_t; + +typedef struct _SGE_CHAIN_UNION +{ + U16 Length; + U8 NextChainOffset; + U8 Flags; + union + { + U32 Address32; + U64 Address64; + }u; +} SGE_CHAIN_UNION, MPI_POINTER PTR_SGE_CHAIN_UNION, + SGEChainUnion_t, MPI_POINTER pSGEChainUnion_t; + +/****************************************************************************/ +/* Transaction Context element */ +/****************************************************************************/ + +typedef struct _SGE_TRANSACTION32 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[1]; + U32 TransactionDetails[1]; +} SGE_TRANSACTION32, MPI_POINTER PTR_SGE_TRANSACTION32, + SGETransaction32_t, MPI_POINTER pSGETransaction32_t; + +typedef struct _SGE_TRANSACTION64 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[2]; + U32 TransactionDetails[1]; +} SGE_TRANSACTION64, MPI_POINTER PTR_SGE_TRANSACTION64, + SGETransaction64_t, MPI_POINTER pSGETransaction64_t; + +typedef struct _SGE_TRANSACTION96 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[3]; + U32 TransactionDetails[1]; +} SGE_TRANSACTION96, MPI_POINTER PTR_SGE_TRANSACTION96, + SGETransaction96_t, MPI_POINTER pSGETransaction96_t; + +typedef struct _SGE_TRANSACTION128 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[4]; + U32 TransactionDetails[1]; +} SGE_TRANSACTION128, MPI_POINTER PTR_SGE_TRANSACTION128, + SGETransaction_t128, MPI_POINTER pSGETransaction_t128; + +typedef struct _SGE_TRANSACTION_UNION +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + union + { + U32 TransactionContext32[1]; + U32 TransactionContext64[2]; + U32 TransactionContext96[3]; + U32 TransactionContext128[4]; + }u; + U32 TransactionDetails[1]; +} SGE_TRANSACTION_UNION, MPI_POINTER PTR_SGE_TRANSACTION_UNION, + SGETransactionUnion_t, MPI_POINTER pSGETransactionUnion_t; + + +/****************************************************************************/ +/* SGE IO types union for IO SGL's */ +/****************************************************************************/ + +typedef struct _SGE_IO_UNION +{ + union + { + SGE_SIMPLE_UNION Simple; + SGE_CHAIN_UNION Chain; + } u; +} SGE_IO_UNION, MPI_POINTER PTR_SGE_IO_UNION, + SGEIOUnion_t, MPI_POINTER pSGEIOUnion_t; + +/****************************************************************************/ +/* SGE union for SGL's with Simple and Transaction elements */ +/****************************************************************************/ + +typedef struct _SGE_TRANS_SIMPLE_UNION +{ + union + { + SGE_SIMPLE_UNION Simple; + SGE_TRANSACTION_UNION Transaction; + } u; +} SGE_TRANS_SIMPLE_UNION, MPI_POINTER PTR_SGE_TRANS_SIMPLE_UNION, + SGETransSimpleUnion_t, MPI_POINTER pSGETransSimpleUnion_t; + +/****************************************************************************/ +/* All SGE types union */ +/****************************************************************************/ + +typedef struct _SGE_MPI_UNION +{ + union + { + SGE_SIMPLE_UNION Simple; + SGE_CHAIN_UNION Chain; + SGE_TRANSACTION_UNION Transaction; + } u; +} SGE_MPI_UNION, MPI_POINTER PTR_SGE_MPI_UNION, + MPI_SGE_UNION_t, MPI_POINTER pMPI_SGE_UNION_t, + SGEAllUnion_t, MPI_POINTER pSGEAllUnion_t; + + +/****************************************************************************/ +/* SGE field definition and masks */ +/****************************************************************************/ + +/* Flags field bit definitions */ + +#define MPI_SGE_FLAGS_LAST_ELEMENT (0x80) +#define MPI_SGE_FLAGS_END_OF_BUFFER (0x40) +#define MPI_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30) +#define MPI_SGE_FLAGS_LOCAL_ADDRESS (0x08) +#define MPI_SGE_FLAGS_DIRECTION (0x04) +#define MPI_SGE_FLAGS_ADDRESS_SIZE (0x02) +#define MPI_SGE_FLAGS_END_OF_LIST (0x01) + +#define MPI_SGE_FLAGS_SHIFT (24) + +#define MPI_SGE_LENGTH_MASK (0x00FFFFFF) +#define MPI_SGE_CHAIN_LENGTH_MASK (0x0000FFFF) + +/* Element Type */ + +#define MPI_SGE_FLAGS_TRANSACTION_ELEMENT (0x00) +#define MPI_SGE_FLAGS_SIMPLE_ELEMENT (0x10) +#define MPI_SGE_FLAGS_CHAIN_ELEMENT (0x30) +#define MPI_SGE_FLAGS_ELEMENT_MASK (0x30) + +/* Address location */ + +#define MPI_SGE_FLAGS_SYSTEM_ADDRESS (0x00) + +/* Direction */ + +#define MPI_SGE_FLAGS_IOC_TO_HOST (0x00) +#define MPI_SGE_FLAGS_HOST_TO_IOC (0x04) + +/* Address Size */ + +#define MPI_SGE_FLAGS_32_BIT_ADDRESSING (0x00) +#define MPI_SGE_FLAGS_64_BIT_ADDRESSING (0x02) + +/* Context Size */ + +#define MPI_SGE_FLAGS_32_BIT_CONTEXT (0x00) +#define MPI_SGE_FLAGS_64_BIT_CONTEXT (0x02) +#define MPI_SGE_FLAGS_96_BIT_CONTEXT (0x04) +#define MPI_SGE_FLAGS_128_BIT_CONTEXT (0x06) + +#define MPI_SGE_CHAIN_OFFSET_MASK (0x00FF0000) +#define MPI_SGE_CHAIN_OFFSET_SHIFT (16) + + +/****************************************************************************/ +/* SGE operation Macros */ +/****************************************************************************/ + + /* SIMPLE FlagsLength manipulations... */ +#define MPI_SGE_SET_FLAGS(f) ((U32)(f) << MPI_SGE_FLAGS_SHIFT) +#define MPI_SGE_GET_FLAGS(fl) (((fl) & ~MPI_SGE_LENGTH_MASK) >> MPI_SGE_FLAGS_SHIFT) +#define MPI_SGE_LENGTH(fl) ((fl) & MPI_SGE_LENGTH_MASK) +#define MPI_SGE_CHAIN_LENGTH(fl) ((fl) & MPI_SGE_CHAIN_LENGTH_MASK) + +#define MPI_SGE_SET_FLAGS_LENGTH(f,l) (MPI_SGE_SET_FLAGS(f) | MPI_SGE_LENGTH(l)) + +#define MPI_pSGE_GET_FLAGS(psg) MPI_SGE_GET_FLAGS((psg)->FlagsLength) +#define MPI_pSGE_GET_LENGTH(psg) MPI_SGE_LENGTH((psg)->FlagsLength) +#define MPI_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI_SGE_SET_FLAGS_LENGTH(f,l) + /* CAUTION - The following are READ-MODIFY-WRITE! */ +#define MPI_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI_SGE_SET_FLAGS(f) +#define MPI_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI_SGE_LENGTH(l) + +#define MPI_GET_CHAIN_OFFSET(x) ((x&MPI_SGE_CHAIN_OFFSET_MASK)>>MPI_SGE_CHAIN_OFFSET_SHIFT) + + + +/***************************************************************************** +* +* S t a n d a r d M e s s a g e S t r u c t u r e s +* +*****************************************************************************/ + +/****************************************************************************/ +/* Standard message request header for all request messages */ +/****************************************************************************/ + +typedef struct _MSG_REQUEST_HEADER +{ + U8 Reserved[2]; /* function specific */ + U8 ChainOffset; + U8 Function; + U8 Reserved1[3]; /* function specific */ + U8 MsgFlags; + U32 MsgContext; +} MSG_REQUEST_HEADER, MPI_POINTER PTR_MSG_REQUEST_HEADER, + MPIHeader_t, MPI_POINTER pMPIHeader_t; + + +/****************************************************************************/ +/* Default Reply */ +/****************************************************************************/ + +typedef struct _MSG_DEFAULT_REPLY +{ + U8 Reserved[2]; /* function specific */ + U8 MsgLength; + U8 Function; + U8 Reserved1[3]; /* function specific */ + U8 MsgFlags; + U32 MsgContext; + U8 Reserved2[2]; /* function specific */ + U16 IOCStatus; + U32 IOCLogInfo; +} MSG_DEFAULT_REPLY, MPI_POINTER PTR_MSG_DEFAULT_REPLY, + MPIDefaultReply_t, MPI_POINTER pMPIDefaultReply_t; + + +/* MsgFlags definition for all replies */ + +#define MPI_MSGFLAGS_CONTINUATION_REPLY (0x80) + + +/***************************************************************************** +* +* I O C S t a t u s V a l u e s +* +*****************************************************************************/ + +/****************************************************************************/ +/* Common IOCStatus values for all replies */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_SUCCESS (0x0000) +#define MPI_IOCSTATUS_INVALID_FUNCTION (0x0001) +#define MPI_IOCSTATUS_BUSY (0x0002) +#define MPI_IOCSTATUS_INVALID_SGL (0x0003) +#define MPI_IOCSTATUS_INTERNAL_ERROR (0x0004) +#define MPI_IOCSTATUS_RESERVED (0x0005) +#define MPI_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) +#define MPI_IOCSTATUS_INVALID_FIELD (0x0007) +#define MPI_IOCSTATUS_INVALID_STATE (0x0008) +#define MPI_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009) + +/****************************************************************************/ +/* Config IOCStatus values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) +#define MPI_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) +#define MPI_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) +#define MPI_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) +#define MPI_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) +#define MPI_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) + +/****************************************************************************/ +/* SCSIIO Reply (SPI & FCP) initiator values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) +#define MPI_IOCSTATUS_SCSI_INVALID_BUS (0x0041) +#define MPI_IOCSTATUS_SCSI_INVALID_TARGETID (0x0042) +#define MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) +#define MPI_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) +#define MPI_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) +#define MPI_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) +#define MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) +#define MPI_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) +#define MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) +#define MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) +#define MPI_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) +#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) + +/****************************************************************************/ +/* For use by SCSI Initiator and SCSI Target end-to-end data protection */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) +#define MPI_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) +#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) + + +/****************************************************************************/ +/* SCSI Target values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_TARGET_PRIORITY_IO (0x0060) +#define MPI_IOCSTATUS_TARGET_INVALID_PORT (0x0061) +#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX (0x0062) /* obsolete name */ +#define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) +#define MPI_IOCSTATUS_TARGET_ABORTED (0x0063) +#define MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) +#define MPI_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) +#define MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) +#define MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT (0x006B) +#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) +#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) +#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) +#define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) +#define MPI_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) + +/****************************************************************************/ +/* Additional FCP target values (obsolete) */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_TARGET_FC_ABORTED (0x0066) /* obsolete */ +#define MPI_IOCSTATUS_TARGET_FC_RX_ID_INVALID (0x0067) /* obsolete */ +#define MPI_IOCSTATUS_TARGET_FC_DID_INVALID (0x0068) /* obsolete */ +#define MPI_IOCSTATUS_TARGET_FC_NODE_LOGGED_OUT (0x0069) /* obsolete */ + +/****************************************************************************/ +/* Fibre Channel Direct Access values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_FC_ABORTED (0x0066) +#define MPI_IOCSTATUS_FC_RX_ID_INVALID (0x0067) +#define MPI_IOCSTATUS_FC_DID_INVALID (0x0068) +#define MPI_IOCSTATUS_FC_NODE_LOGGED_OUT (0x0069) +#define MPI_IOCSTATUS_FC_EXCHANGE_CANCELED (0x006C) + +/****************************************************************************/ +/* LAN values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND (0x0080) +#define MPI_IOCSTATUS_LAN_DEVICE_FAILURE (0x0081) +#define MPI_IOCSTATUS_LAN_TRANSMIT_ERROR (0x0082) +#define MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED (0x0083) +#define MPI_IOCSTATUS_LAN_RECEIVE_ERROR (0x0084) +#define MPI_IOCSTATUS_LAN_RECEIVE_ABORTED (0x0085) +#define MPI_IOCSTATUS_LAN_PARTIAL_PACKET (0x0086) +#define MPI_IOCSTATUS_LAN_CANCELED (0x0087) + +/****************************************************************************/ +/* Serial Attached SCSI values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) +#define MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) + +/****************************************************************************/ +/* Inband values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_INBAND_ABORTED (0x0098) +#define MPI_IOCSTATUS_INBAND_NO_CONNECTION (0x0099) + +/****************************************************************************/ +/* Diagnostic Tools values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) + + +/****************************************************************************/ +/* IOCStatus flag to indicate that log info is available */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000) +#define MPI_IOCSTATUS_MASK (0x7FFF) + +/****************************************************************************/ +/* LogInfo Types */ +/****************************************************************************/ + +#define MPI_IOCLOGINFO_TYPE_MASK (0xF0000000) +#define MPI_IOCLOGINFO_TYPE_SHIFT (28) +#define MPI_IOCLOGINFO_TYPE_NONE (0x0) +#define MPI_IOCLOGINFO_TYPE_SCSI (0x1) +#define MPI_IOCLOGINFO_TYPE_FC (0x2) +#define MPI_IOCLOGINFO_TYPE_SAS (0x3) +#define MPI_IOCLOGINFO_TYPE_ISCSI (0x4) +#define MPI_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) + + +#endif diff --git a/source/lsi/mpi2.h b/source/lsi/mpi2.h new file mode 100755 index 0000000..55b3557 --- /dev/null +++ b/source/lsi/mpi2.h @@ -0,0 +1,1200 @@ +/* + * Copyright (c) 2000-2011 LSI Corporation. + * + * + * Name: mpi2.h + * Title: MPI Message independent structures and definitions + * including System Interface Register Set and + * scatter/gather formats. + * Creation Date: June 21, 2006 + * + * mpi2.h Version: 02.00.xx + * + * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 + * prefix are for use only on MPI v2.5 products, and must not be used + * with MPI v2.0 products. Unless otherwise noted, names beginning with + * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT. + * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT. + * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT. + * Moved ReplyPostHostIndex register to offset 0x6C of the + * MPI2_SYSTEM_INTERFACE_REGS and modified the define for + * MPI2_REPLY_POST_HOST_INDEX_OFFSET. + * Added union of request descriptors. + * Added union of reply descriptors. + * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT. + * Added define for MPI2_VERSION_02_00. + * Fixed the size of the FunctionDependent5 field in the + * MPI2_DEFAULT_REPLY structure. + * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT. + * Removed the MPI-defined Fault Codes and extended the + * product specific codes up to 0xEFFF. + * Added a sixth key value for the WriteSequence register + * and changed the flush value to 0x0. + * Added message function codes for Diagnostic Buffer Post + * and Diagnsotic Release. + * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED + * Moved MPI2_VERSION_UNION from mpi2_ioc.h. + * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT. + * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT. + * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT. + * Added #defines for marking a reply descriptor as unused. + * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT. + * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT. + * Moved LUN field defines from mpi2_init.h. + * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT. + * 05-06-09 02.00.12 Bumped MPI2_HEADER_VERSION_UNIT. + * In all request and reply descriptors, replaced VF_ID + * field with MSIxIndex field. + * Removed DevHandle field from + * MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those + * bytes reserved. + * Added RAID Accelerator functionality. + * 07-30-09 02.00.13 Bumped MPI2_HEADER_VERSION_UNIT. + * 10-28-09 02.00.14 Bumped MPI2_HEADER_VERSION_UNIT. + * Added MSI-x index mask and shift for Reply Post Host + * Index register. + * Added function code for Host Based Discovery Action. + * 02-10-10 02.00.15 Bumped MPI2_HEADER_VERSION_UNIT. + * Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL. + * Added defines for product-specific range of message + * function codes, 0xF0 to 0xFF. + * 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT. + * Added alternative defines for the SGE Direction bit. + * 08-11-10 02.00.17 Bumped MPI2_HEADER_VERSION_UNIT. + * 11-10-10 02.00.18 Bumped MPI2_HEADER_VERSION_UNIT. + * Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define. + * 02-23-11 02.00.19 Bumped MPI2_HEADER_VERSION_UNIT. + * Added MPI2_FUNCTION_SEND_HOST_MESSAGE. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_H +#define MPI2_H + + +/***************************************************************************** +* +* MPI Version Definitions +* +*****************************************************************************/ + +#define MPI2_VERSION_MAJOR_MASK (0xFF00) +#define MPI2_VERSION_MAJOR_SHIFT (8) +#define MPI2_VERSION_MINOR_MASK (0x00FF) +#define MPI2_VERSION_MINOR_SHIFT (0) + +/* major version for all MPI v2.x */ +#define MPI2_VERSION_MAJOR (0x02) + +/* minor version for MPI v2.0 compatible products */ +#define MPI2_VERSION_MINOR (0x00) +#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ + MPI2_VERSION_MINOR) +#define MPI2_VERSION_02_00 (0x0200) + + +/* minor version for MPI v2.5 compatible products */ +#define MPI25_VERSION_MINOR (0x05) +#define MPI25_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ + MPI25_VERSION_MINOR) +#define MPI2_VERSION_02_05 (0x0205) + + +/* Unit and Dev versioning for this MPI header set */ +#define MPI2_HEADER_VERSION_UNIT (0x13) +#define MPI2_HEADER_VERSION_DEV (0x00) +#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) +#define MPI2_HEADER_VERSION_UNIT_SHIFT (8) +#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF) +#define MPI2_HEADER_VERSION_DEV_SHIFT (0) +#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | MPI2_HEADER_VERSION_DEV) + + +/***************************************************************************** +* +* IOC State Definitions +* +*****************************************************************************/ + +#define MPI2_IOC_STATE_RESET (0x00000000) +#define MPI2_IOC_STATE_READY (0x10000000) +#define MPI2_IOC_STATE_OPERATIONAL (0x20000000) +#define MPI2_IOC_STATE_FAULT (0x40000000) + +#define MPI2_IOC_STATE_MASK (0xF0000000) +#define MPI2_IOC_STATE_SHIFT (28) + +/* Fault state range for prodcut specific codes */ +#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN (0x0000) +#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX (0xEFFF) + + +/***************************************************************************** +* +* System Interface Register Definitions +* +*****************************************************************************/ + +typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS +{ + U32 Doorbell; /* 0x00 */ + U32 WriteSequence; /* 0x04 */ + U32 HostDiagnostic; /* 0x08 */ + U32 Reserved1; /* 0x0C */ + U32 DiagRWData; /* 0x10 */ + U32 DiagRWAddressLow; /* 0x14 */ + U32 DiagRWAddressHigh; /* 0x18 */ + U32 Reserved2[5]; /* 0x1C */ + U32 HostInterruptStatus; /* 0x30 */ + U32 HostInterruptMask; /* 0x34 */ + U32 DCRData; /* 0x38 */ + U32 DCRAddress; /* 0x3C */ + U32 Reserved3[2]; /* 0x40 */ + U32 ReplyFreeHostIndex; /* 0x48 */ + U32 Reserved4[8]; /* 0x4C */ + U32 ReplyPostHostIndex; /* 0x6C */ + U32 Reserved5; /* 0x70 */ + U32 HCBSize; /* 0x74 */ + U32 HCBAddressLow; /* 0x78 */ + U32 HCBAddressHigh; /* 0x7C */ + U32 Reserved6[16]; /* 0x80 */ + U32 RequestDescriptorPostLow; /* 0xC0 */ + U32 RequestDescriptorPostHigh; /* 0xC4 */ + U32 Reserved7[14]; /* 0xC8 */ +} MPI2_SYSTEM_INTERFACE_REGS, MPI2_POINTER PTR_MPI2_SYSTEM_INTERFACE_REGS, + Mpi2SystemInterfaceRegs_t, MPI2_POINTER pMpi2SystemInterfaceRegs_t; + +/* + * Defines for working with the Doorbell register. + */ +#define MPI2_DOORBELL_OFFSET (0x00000000) + +/* IOC --> System values */ +#define MPI2_DOORBELL_USED (0x08000000) +#define MPI2_DOORBELL_WHO_INIT_MASK (0x07000000) +#define MPI2_DOORBELL_WHO_INIT_SHIFT (24) +#define MPI2_DOORBELL_FAULT_CODE_MASK (0x0000FFFF) +#define MPI2_DOORBELL_DATA_MASK (0x0000FFFF) + +/* System --> IOC values */ +#define MPI2_DOORBELL_FUNCTION_MASK (0xFF000000) +#define MPI2_DOORBELL_FUNCTION_SHIFT (24) +#define MPI2_DOORBELL_ADD_DWORDS_MASK (0x00FF0000) +#define MPI2_DOORBELL_ADD_DWORDS_SHIFT (16) + + +/* + * Defines for the WriteSequence register + */ +#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004) +#define MPI2_WRSEQ_KEY_VALUE_MASK (0x0000000F) +#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0) +#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF) +#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4) +#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB) +#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2) +#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7) +#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD) + +/* + * Defines for the HostDiagnostic register + */ +#define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008) + +#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800) +#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000) +#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800) + +#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400) +#define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200) +#define MPI2_DIAG_HCB_MODE (0x00000100) +#define MPI2_DIAG_DIAG_WRITE_ENABLE (0x00000080) +#define MPI2_DIAG_FLASH_BAD_SIG (0x00000040) +#define MPI2_DIAG_RESET_HISTORY (0x00000020) +#define MPI2_DIAG_DIAG_RW_ENABLE (0x00000010) +#define MPI2_DIAG_RESET_ADAPTER (0x00000004) +#define MPI2_DIAG_HOLD_IOC_RESET (0x00000002) + +/* + * Offsets for DiagRWData and address + */ +#define MPI2_DIAG_RW_DATA_OFFSET (0x00000010) +#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET (0x00000014) +#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00000018) + +/* + * Defines for the HostInterruptStatus register + */ +#define MPI2_HOST_INTERRUPT_STATUS_OFFSET (0x00000030) +#define MPI2_HIS_SYS2IOC_DB_STATUS (0x80000000) +#define MPI2_HIS_IOP_DOORBELL_STATUS MPI2_HIS_SYS2IOC_DB_STATUS +#define MPI2_HIS_RESET_IRQ_STATUS (0x40000000) +#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT (0x00000008) +#define MPI2_HIS_IOC2SYS_DB_STATUS (0x00000001) +#define MPI2_HIS_DOORBELL_INTERRUPT MPI2_HIS_IOC2SYS_DB_STATUS + +/* + * Defines for the HostInterruptMask register + */ +#define MPI2_HOST_INTERRUPT_MASK_OFFSET (0x00000034) +#define MPI2_HIM_RESET_IRQ_MASK (0x40000000) +#define MPI2_HIM_REPLY_INT_MASK (0x00000008) +#define MPI2_HIM_RIM MPI2_HIM_REPLY_INT_MASK +#define MPI2_HIM_IOC2SYS_DB_MASK (0x00000001) +#define MPI2_HIM_DIM MPI2_HIM_IOC2SYS_DB_MASK + +/* + * Offsets for DCRData and address + */ +#define MPI2_DCR_DATA_OFFSET (0x00000038) +#define MPI2_DCR_ADDRESS_OFFSET (0x0000003C) + +/* + * Offset for the Reply Free Queue + */ +#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET (0x00000048) + +/* + * Defines for the Reply Descriptor Post Queue + */ +#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C) +#define MPI2_REPLY_POST_HOST_INDEX_MASK (0x00FFFFFF) +#define MPI2_RPHI_MSIX_INDEX_MASK (0xFF000000) +#define MPI2_RPHI_MSIX_INDEX_SHIFT (24) + +/* + * Defines for the HCBSize and address + */ +#define MPI2_HCB_SIZE_OFFSET (0x00000074) +#define MPI2_HCB_SIZE_SIZE_MASK (0xFFFFF000) +#define MPI2_HCB_SIZE_HCB_ENABLE (0x00000001) + +#define MPI2_HCB_ADDRESS_LOW_OFFSET (0x00000078) +#define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C) + +/* + * Offsets for the Request Queue + */ +#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0) +#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4) + + +/***************************************************************************** +* +* Message Descriptors +* +*****************************************************************************/ + +/* Request Descriptors */ + +/* Default Request Descriptor */ +typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR +{ + U8 RequestFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 LMID; /* 0x04 */ + U16 DescriptorTypeDependent; /* 0x06 */ +} MPI2_DEFAULT_REQUEST_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR, + Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t; + +/* defines for the RequestFlags field */ +#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E) +#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00) +#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02) +#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06) +#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08) +#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR (0x0A) +#define MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO (0x0C) + +#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01) + + +/* High Priority Request Descriptor */ +typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR +{ + U8 RequestFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 LMID; /* 0x04 */ + U16 Reserved1; /* 0x06 */ +} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR, + Mpi2HighPriorityRequestDescriptor_t, + MPI2_POINTER pMpi2HighPriorityRequestDescriptor_t; + + +/* SCSI IO Request Descriptor */ +typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR +{ + U8 RequestFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 LMID; /* 0x04 */ + U16 DevHandle; /* 0x06 */ +} MPI2_SCSI_IO_REQUEST_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR, + Mpi2SCSIIORequestDescriptor_t, MPI2_POINTER pMpi2SCSIIORequestDescriptor_t; + + +/* SCSI Target Request Descriptor */ +typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR +{ + U8 RequestFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 LMID; /* 0x04 */ + U16 IoIndex; /* 0x06 */ +} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR, + Mpi2SCSITargetRequestDescriptor_t, + MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t; + + +/* RAID Accelerator Request Descriptor */ +typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR +{ + U8 RequestFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 LMID; /* 0x04 */ + U16 Reserved; /* 0x06 */ +} MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR, + Mpi2RAIDAcceleratorRequestDescriptor_t, + MPI2_POINTER pMpi2RAIDAcceleratorRequestDescriptor_t; + + +/* Fast Path SCSI IO Request Descriptor */ +typedef MPI2_SCSI_IO_REQUEST_DESCRIPTOR + MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR, + MPI2_POINTER PTR_MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR, + Mpi25FastPathSCSIIORequestDescriptor_t, + MPI2_POINTER pMpi25FastPathSCSIIORequestDescriptor_t; + + +/* union of Request Descriptors */ +typedef union _MPI2_REQUEST_DESCRIPTOR_UNION +{ + MPI2_DEFAULT_REQUEST_DESCRIPTOR Default; + MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority; + MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO; + MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget; + MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator; + MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR FastPathSCSIIO; + U64 Words; +} MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION, + Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t; + + +/* Reply Descriptors */ + +/* Default Reply Descriptor */ +typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U16 DescriptorTypeDependent1; /* 0x02 */ + U32 DescriptorTypeDependent2; /* 0x04 */ +} MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR, + Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t; + +/* defines for the ReplyFlags field */ +#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F) +#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00) +#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01) +#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02) +#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03) +#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS (0x05) +#define MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS (0x06) +#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F) + +/* values for marking a reply descriptor as unused */ +#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF) +#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK (0xFFFFFFFF) + +/* Address Reply Descriptor */ +typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U16 SMID; /* 0x02 */ + U32 ReplyFrameAddress; /* 0x04 */ +} MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR, + Mpi2AddressReplyDescriptor_t, MPI2_POINTER pMpi2AddressReplyDescriptor_t; + +#define MPI2_ADDRESS_REPLY_SMID_INVALID (0x00) + + +/* SCSI IO Success Reply Descriptor */ +typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 TaskTag; /* 0x04 */ + U16 Reserved1; /* 0x06 */ +} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, + Mpi2SCSIIOSuccessReplyDescriptor_t, + MPI2_POINTER pMpi2SCSIIOSuccessReplyDescriptor_t; + + +/* TargetAssist Success Reply Descriptor */ +typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U16 SMID; /* 0x02 */ + U8 SequenceNumber; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 IoIndex; /* 0x06 */ +} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR, + Mpi2TargetAssistSuccessReplyDescriptor_t, + MPI2_POINTER pMpi2TargetAssistSuccessReplyDescriptor_t; + + +/* Target Command Buffer Reply Descriptor */ +typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U8 VP_ID; /* 0x02 */ + U8 Flags; /* 0x03 */ + U16 InitiatorDevHandle; /* 0x04 */ + U16 IoIndex; /* 0x06 */ +} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, + Mpi2TargetCommandBufferReplyDescriptor_t, + MPI2_POINTER pMpi2TargetCommandBufferReplyDescriptor_t; + +/* defines for Flags field */ +#define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F) + + +/* RAID Accelerator Success Reply Descriptor */ +typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 MSIxIndex; /* 0x01 */ + U16 SMID; /* 0x02 */ + U32 Reserved; /* 0x04 */ +} MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR, + Mpi2RAIDAcceleratorSuccessReplyDescriptor_t, + MPI2_POINTER pMpi2RAIDAcceleratorSuccessReplyDescriptor_t; + + +/* Fast Path SCSI IO Success Reply Descriptor */ +typedef MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR + MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, + MPI2_POINTER PTR_MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, + Mpi25FastPathSCSIIOSuccessReplyDescriptor_t, + MPI2_POINTER pMpi25FastPathSCSIIOSuccessReplyDescriptor_t; + + +/* union of Reply Descriptors */ +typedef union _MPI2_REPLY_DESCRIPTORS_UNION +{ + MPI2_DEFAULT_REPLY_DESCRIPTOR Default; + MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply; + MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess; + MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess; + MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; + MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess; + MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR FastPathSCSIIOSuccess; + U64 Words; +} MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION, + Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t; + + + +/***************************************************************************** +* +* Message Functions +* +*****************************************************************************/ + +#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */ +#define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) /* SCSI Task Management */ +#define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */ +#define MPI2_FUNCTION_IOC_FACTS (0x03) /* IOC Facts */ +#define MPI2_FUNCTION_CONFIG (0x04) /* Configuration */ +#define MPI2_FUNCTION_PORT_FACTS (0x05) /* Port Facts */ +#define MPI2_FUNCTION_PORT_ENABLE (0x06) /* Port Enable */ +#define MPI2_FUNCTION_EVENT_NOTIFICATION (0x07) /* Event Notification */ +#define MPI2_FUNCTION_EVENT_ACK (0x08) /* Event Acknowledge */ +#define MPI2_FUNCTION_FW_DOWNLOAD (0x09) /* FW Download */ +#define MPI2_FUNCTION_TARGET_ASSIST (0x0B) /* Target Assist */ +#define MPI2_FUNCTION_TARGET_STATUS_SEND (0x0C) /* Target Status Send */ +#define MPI2_FUNCTION_TARGET_MODE_ABORT (0x0D) /* Target Mode Abort */ +#define MPI2_FUNCTION_FW_UPLOAD (0x12) /* FW Upload */ +#define MPI2_FUNCTION_RAID_ACTION (0x15) /* RAID Action */ +#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) /* SCSI IO RAID Passthrough */ +#define MPI2_FUNCTION_TOOLBOX (0x17) /* Toolbox */ +#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) /* SCSI Enclosure Processor */ +#define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A) /* SMP Passthrough */ +#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) /* SAS IO Unit Control */ +#define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C) /* SATA Passthrough */ +#define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D) /* Diagnostic Buffer Post */ +#define MPI2_FUNCTION_DIAG_RELEASE (0x1E) /* Diagnostic Release */ +#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) /* Target Command Buffer Post Base */ +#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) /* Target Command Buffer Post List */ +#define MPI2_FUNCTION_RAID_ACCELERATOR (0x2C) /* RAID Accelerator */ +#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F) /* Host Based Discovery Action */ +#define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30) /* Power Management Control */ +#define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31) /* Send Host Message */ +#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0) /* beginning of product-specific range */ +#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF) /* end of product-specific range */ + + + +/* Doorbell functions */ +#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40) +#define MPI2_FUNCTION_HANDSHAKE (0x42) + + +/***************************************************************************** +* +* IOC Status Values +* +*****************************************************************************/ + +/* mask for IOCStatus status value */ +#define MPI2_IOCSTATUS_MASK (0x7FFF) + +/**************************************************************************** +* Common IOCStatus values for all replies +****************************************************************************/ + +#define MPI2_IOCSTATUS_SUCCESS (0x0000) +#define MPI2_IOCSTATUS_INVALID_FUNCTION (0x0001) +#define MPI2_IOCSTATUS_BUSY (0x0002) +#define MPI2_IOCSTATUS_INVALID_SGL (0x0003) +#define MPI2_IOCSTATUS_INTERNAL_ERROR (0x0004) +#define MPI2_IOCSTATUS_INVALID_VPID (0x0005) +#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) +#define MPI2_IOCSTATUS_INVALID_FIELD (0x0007) +#define MPI2_IOCSTATUS_INVALID_STATE (0x0008) +#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009) + +/**************************************************************************** +* Config IOCStatus values +****************************************************************************/ + +#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) +#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) +#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) +#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) +#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) +#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) + +/**************************************************************************** +* SCSI IO Reply +****************************************************************************/ + +#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) +#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042) +#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) +#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) +#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) +#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) +#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) +#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) +#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) +#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) +#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) +#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) + +/**************************************************************************** +* For use by SCSI Initiator and SCSI Target end-to-end data protection +****************************************************************************/ + +#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) +#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) +#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) + +/**************************************************************************** +* SCSI Target values +****************************************************************************/ + +#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) +#define MPI2_IOCSTATUS_TARGET_ABORTED (0x0063) +#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) +#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) +#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) +#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) +#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) +#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) +#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) +#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) + +/**************************************************************************** +* Serial Attached SCSI values +****************************************************************************/ + +#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) +#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) + +/**************************************************************************** +* Diagnostic Buffer Post / Diagnostic Release values +****************************************************************************/ + +#define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) + +/**************************************************************************** +* RAID Accelerator values +****************************************************************************/ + +#define MPI2_IOCSTATUS_RAID_ACCEL_ERROR (0x00B0) + +/**************************************************************************** +* IOCStatus flag to indicate that log info is available +****************************************************************************/ + +#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000) + +/**************************************************************************** +* IOCLogInfo Types +****************************************************************************/ + +#define MPI2_IOCLOGINFO_TYPE_MASK (0xF0000000) +#define MPI2_IOCLOGINFO_TYPE_SHIFT (28) +#define MPI2_IOCLOGINFO_TYPE_NONE (0x0) +#define MPI2_IOCLOGINFO_TYPE_SCSI (0x1) +#define MPI2_IOCLOGINFO_TYPE_FC (0x2) +#define MPI2_IOCLOGINFO_TYPE_SAS (0x3) +#define MPI2_IOCLOGINFO_TYPE_ISCSI (0x4) +#define MPI2_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) + + +/***************************************************************************** +* +* Standard Message Structures +* +*****************************************************************************/ + +/**************************************************************************** +* Request Message Header for all request messages +****************************************************************************/ + +typedef struct _MPI2_REQUEST_HEADER +{ + U16 FunctionDependent1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 FunctionDependent2; /* 0x04 */ + U8 FunctionDependent3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ +} MPI2_REQUEST_HEADER, MPI2_POINTER PTR_MPI2_REQUEST_HEADER, + MPI2RequestHeader_t, MPI2_POINTER pMPI2RequestHeader_t; + + +/**************************************************************************** +* Default Reply +****************************************************************************/ + +typedef struct _MPI2_DEFAULT_REPLY +{ + U16 FunctionDependent1; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 FunctionDependent2; /* 0x04 */ + U8 FunctionDependent3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U16 FunctionDependent5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_DEFAULT_REPLY, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY, + MPI2DefaultReply_t, MPI2_POINTER pMPI2DefaultReply_t; + + +/* common version structure/union used in messages and configuration pages */ + +typedef struct _MPI2_VERSION_STRUCT +{ + U8 Dev; /* 0x00 */ + U8 Unit; /* 0x01 */ + U8 Minor; /* 0x02 */ + U8 Major; /* 0x03 */ +} MPI2_VERSION_STRUCT; + +typedef union _MPI2_VERSION_UNION +{ + MPI2_VERSION_STRUCT Struct; + U32 Word; +} MPI2_VERSION_UNION; + + +/* LUN field defines, common to many structures */ +#define MPI2_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF) +#define MPI2_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000) +#define MPI2_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF) +#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000) +#define MPI2_LUN_LEVEL_1_WORD (0xFF00) +#define MPI2_LUN_LEVEL_1_DWORD (0x0000FF00) + + +/***************************************************************************** +* +* Fusion-MPT MPI Scatter Gather Elements +* +*****************************************************************************/ + +/**************************************************************************** +* MPI Simple Element structures +****************************************************************************/ + +typedef struct _MPI2_SGE_SIMPLE32 +{ + U32 FlagsLength; + U32 Address; +} MPI2_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_SGE_SIMPLE32, + Mpi2SGESimple32_t, MPI2_POINTER pMpi2SGESimple32_t; + +typedef struct _MPI2_SGE_SIMPLE64 +{ + U32 FlagsLength; + U64 Address; +} MPI2_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_SGE_SIMPLE64, + Mpi2SGESimple64_t, MPI2_POINTER pMpi2SGESimple64_t; + +typedef struct _MPI2_SGE_SIMPLE_UNION +{ + U32 FlagsLength; + union + { + U32 Address32; + U64 Address64; + } u; +} MPI2_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_SIMPLE_UNION, + Mpi2SGESimpleUnion_t, MPI2_POINTER pMpi2SGESimpleUnion_t; + + +/**************************************************************************** +* MPI Chain Element structures - for MPI v2.0 products only +****************************************************************************/ + +typedef struct _MPI2_SGE_CHAIN32 +{ + U16 Length; + U8 NextChainOffset; + U8 Flags; + U32 Address; +} MPI2_SGE_CHAIN32, MPI2_POINTER PTR_MPI2_SGE_CHAIN32, + Mpi2SGEChain32_t, MPI2_POINTER pMpi2SGEChain32_t; + +typedef struct _MPI2_SGE_CHAIN64 +{ + U16 Length; + U8 NextChainOffset; + U8 Flags; + U64 Address; +} MPI2_SGE_CHAIN64, MPI2_POINTER PTR_MPI2_SGE_CHAIN64, + Mpi2SGEChain64_t, MPI2_POINTER pMpi2SGEChain64_t; + +typedef struct _MPI2_SGE_CHAIN_UNION +{ + U16 Length; + U8 NextChainOffset; + U8 Flags; + union + { + U32 Address32; + U64 Address64; + } u; +} MPI2_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_SGE_CHAIN_UNION, + Mpi2SGEChainUnion_t, MPI2_POINTER pMpi2SGEChainUnion_t; + + +/**************************************************************************** +* MPI Transaction Context Element structures - for MPI v2.0 products only +****************************************************************************/ + +typedef struct _MPI2_SGE_TRANSACTION32 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[1]; + U32 TransactionDetails[1]; +} MPI2_SGE_TRANSACTION32, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION32, + Mpi2SGETransaction32_t, MPI2_POINTER pMpi2SGETransaction32_t; + +typedef struct _MPI2_SGE_TRANSACTION64 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[2]; + U32 TransactionDetails[1]; +} MPI2_SGE_TRANSACTION64, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION64, + Mpi2SGETransaction64_t, MPI2_POINTER pMpi2SGETransaction64_t; + +typedef struct _MPI2_SGE_TRANSACTION96 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[3]; + U32 TransactionDetails[1]; +} MPI2_SGE_TRANSACTION96, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION96, + Mpi2SGETransaction96_t, MPI2_POINTER pMpi2SGETransaction96_t; + +typedef struct _MPI2_SGE_TRANSACTION128 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[4]; + U32 TransactionDetails[1]; +} MPI2_SGE_TRANSACTION128, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION128, + Mpi2SGETransaction_t128, MPI2_POINTER pMpi2SGETransaction_t128; + +typedef struct _MPI2_SGE_TRANSACTION_UNION +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + union + { + U32 TransactionContext32[1]; + U32 TransactionContext64[2]; + U32 TransactionContext96[3]; + U32 TransactionContext128[4]; + } u; + U32 TransactionDetails[1]; +} MPI2_SGE_TRANSACTION_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION_UNION, + Mpi2SGETransactionUnion_t, MPI2_POINTER pMpi2SGETransactionUnion_t; + + +/**************************************************************************** +* MPI SGE union for IO SGL's - for MPI v2.0 products only +****************************************************************************/ + +typedef struct _MPI2_MPI_SGE_IO_UNION +{ + union + { + MPI2_SGE_SIMPLE_UNION Simple; + MPI2_SGE_CHAIN_UNION Chain; + } u; +} MPI2_MPI_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_IO_UNION, + Mpi2MpiSGEIOUnion_t, MPI2_POINTER pMpi2MpiSGEIOUnion_t; + + +/**************************************************************************** +* MPI SGE union for SGL's with Simple and Transaction elements - for MPI v2.0 products only +****************************************************************************/ + +typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION +{ + union + { + MPI2_SGE_SIMPLE_UNION Simple; + MPI2_SGE_TRANSACTION_UNION Transaction; + } u; +} MPI2_SGE_TRANS_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANS_SIMPLE_UNION, + Mpi2SGETransSimpleUnion_t, MPI2_POINTER pMpi2SGETransSimpleUnion_t; + + +/**************************************************************************** +* All MPI SGE types union +****************************************************************************/ + +typedef struct _MPI2_MPI_SGE_UNION +{ + union + { + MPI2_SGE_SIMPLE_UNION Simple; + MPI2_SGE_CHAIN_UNION Chain; + MPI2_SGE_TRANSACTION_UNION Transaction; + } u; +} MPI2_MPI_SGE_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_UNION, + Mpi2MpiSgeUnion_t, MPI2_POINTER pMpi2MpiSgeUnion_t; + + +/**************************************************************************** +* MPI SGE field definition and masks +****************************************************************************/ + +/* Flags field bit definitions */ + +#define MPI2_SGE_FLAGS_LAST_ELEMENT (0x80) +#define MPI2_SGE_FLAGS_END_OF_BUFFER (0x40) +#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30) +#define MPI2_SGE_FLAGS_LOCAL_ADDRESS (0x08) +#define MPI2_SGE_FLAGS_DIRECTION (0x04) +#define MPI2_SGE_FLAGS_ADDRESS_SIZE (0x02) +#define MPI2_SGE_FLAGS_END_OF_LIST (0x01) + +#define MPI2_SGE_FLAGS_SHIFT (24) + +#define MPI2_SGE_LENGTH_MASK (0x00FFFFFF) +#define MPI2_SGE_CHAIN_LENGTH_MASK (0x0000FFFF) + +/* Element Type */ + +#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT (0x00) /* for MPI v2.0 products only */ +#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT (0x10) +#define MPI2_SGE_FLAGS_CHAIN_ELEMENT (0x30) /* for MPI v2.0 products only */ +#define MPI2_SGE_FLAGS_ELEMENT_MASK (0x30) + +/* Address location */ + +#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS (0x00) + +/* Direction */ + +#define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00) +#define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04) + +#define MPI2_SGE_FLAGS_DEST (MPI2_SGE_FLAGS_IOC_TO_HOST) +#define MPI2_SGE_FLAGS_SOURCE (MPI2_SGE_FLAGS_HOST_TO_IOC) + +/* Address Size */ + +#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00) +#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02) + +/* Context Size */ + +#define MPI2_SGE_FLAGS_32_BIT_CONTEXT (0x00) +#define MPI2_SGE_FLAGS_64_BIT_CONTEXT (0x02) +#define MPI2_SGE_FLAGS_96_BIT_CONTEXT (0x04) +#define MPI2_SGE_FLAGS_128_BIT_CONTEXT (0x06) + +#define MPI2_SGE_CHAIN_OFFSET_MASK (0x00FF0000) +#define MPI2_SGE_CHAIN_OFFSET_SHIFT (16) + +/**************************************************************************** +* MPI SGE operation Macros +****************************************************************************/ + +/* SIMPLE FlagsLength manipulations... */ +#define MPI2_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_SGE_FLAGS_SHIFT) +#define MPI2_SGE_GET_FLAGS(f) (((f) & ~MPI2_SGE_LENGTH_MASK) >> MPI2_SGE_FLAGS_SHIFT) +#define MPI2_SGE_LENGTH(f) ((f) & MPI2_SGE_LENGTH_MASK) +#define MPI2_SGE_CHAIN_LENGTH(f) ((f) & MPI2_SGE_CHAIN_LENGTH_MASK) + +#define MPI2_SGE_SET_FLAGS_LENGTH(f,l) (MPI2_SGE_SET_FLAGS(f) | MPI2_SGE_LENGTH(l)) + +#define MPI2_pSGE_GET_FLAGS(psg) MPI2_SGE_GET_FLAGS((psg)->FlagsLength) +#define MPI2_pSGE_GET_LENGTH(psg) MPI2_SGE_LENGTH((psg)->FlagsLength) +#define MPI2_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_SGE_SET_FLAGS_LENGTH(f,l) + +/* CAUTION - The following are READ-MODIFY-WRITE! */ +#define MPI2_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_SGE_SET_FLAGS(f) +#define MPI2_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_SGE_LENGTH(l) + +#define MPI2_GET_CHAIN_OFFSET(x) ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> MPI2_SGE_CHAIN_OFFSET_SHIFT) + + +/***************************************************************************** +* +* Fusion-MPT IEEE Scatter Gather Elements +* +*****************************************************************************/ + +/**************************************************************************** +* IEEE Simple Element structures +****************************************************************************/ + +/* MPI2_IEEE_SGE_SIMPLE32 is for MPI v2.0 products only */ +typedef struct _MPI2_IEEE_SGE_SIMPLE32 +{ + U32 Address; + U32 FlagsLength; +} MPI2_IEEE_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE32, + Mpi2IeeeSgeSimple32_t, MPI2_POINTER pMpi2IeeeSgeSimple32_t; + +typedef struct _MPI2_IEEE_SGE_SIMPLE64 +{ + U64 Address; + U32 Length; + U16 Reserved1; + U8 Reserved2; + U8 Flags; +} MPI2_IEEE_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE64, + Mpi2IeeeSgeSimple64_t, MPI2_POINTER pMpi2IeeeSgeSimple64_t; + +typedef union _MPI2_IEEE_SGE_SIMPLE_UNION +{ + MPI2_IEEE_SGE_SIMPLE32 Simple32; + MPI2_IEEE_SGE_SIMPLE64 Simple64; +} MPI2_IEEE_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE_UNION, + Mpi2IeeeSgeSimpleUnion_t, MPI2_POINTER pMpi2IeeeSgeSimpleUnion_t; + + +/**************************************************************************** +* IEEE Chain Element structures +****************************************************************************/ + +/* MPI2_IEEE_SGE_CHAIN32 is for MPI v2.0 products only */ +typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32; + +/* MPI2_IEEE_SGE_CHAIN64 is for MPI v2.0 products only */ +typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64; + +typedef union _MPI2_IEEE_SGE_CHAIN_UNION +{ + MPI2_IEEE_SGE_CHAIN32 Chain32; + MPI2_IEEE_SGE_CHAIN64 Chain64; +} MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION, + Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t; + +/* MPI25_IEEE_SGE_CHAIN64 is for MPI v2.5 products only */ +typedef struct _MPI25_IEEE_SGE_CHAIN64 +{ + U64 Address; + U32 Length; + U16 Reserved1; + U8 NextChainOffset; + U8 Flags; +} MPI25_IEEE_SGE_CHAIN64, MPI2_POINTER PTR_MPI25_IEEE_SGE_CHAIN64, + Mpi25IeeeSgeChain64_t, MPI2_POINTER pMpi25IeeeSgeChain64_t; + + +/**************************************************************************** +* All IEEE SGE types union +****************************************************************************/ + +/* MPI2_IEEE_SGE_UNION is for MPI v2.0 products only */ +typedef struct _MPI2_IEEE_SGE_UNION +{ + union + { + MPI2_IEEE_SGE_SIMPLE_UNION Simple; + MPI2_IEEE_SGE_CHAIN_UNION Chain; + } u; +} MPI2_IEEE_SGE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_UNION, + Mpi2IeeeSgeUnion_t, MPI2_POINTER pMpi2IeeeSgeUnion_t; + + +/**************************************************************************** +* IEEE SGE union for IO SGL's +****************************************************************************/ + +typedef union _MPI25_SGE_IO_UNION +{ + MPI2_IEEE_SGE_SIMPLE64 IeeeSimple; + MPI25_IEEE_SGE_CHAIN64 IeeeChain; +} MPI25_SGE_IO_UNION, MPI2_POINTER PTR_MPI25_SGE_IO_UNION, + Mpi25SGEIOUnion_t, MPI2_POINTER pMpi25SGEIOUnion_t; + + +/**************************************************************************** +* IEEE SGE field definitions and masks +****************************************************************************/ + +/* Flags field bit definitions */ + +#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK (0x80) +#define MPI25_IEEE_SGE_FLAGS_END_OF_LIST (0x40) + +#define MPI2_IEEE32_SGE_FLAGS_SHIFT (24) + +#define MPI2_IEEE32_SGE_LENGTH_MASK (0x00FFFFFF) + +/* Element Type */ + +#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00) +#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80) + +/* Data Location Address Space */ + +#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03) +#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) /* IEEE Simple Element only */ +#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01) /* IEEE Simple Element only */ +#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02) +#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) /* IEEE Simple Element only */ +#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR (0x03) /* IEEE Chain Element only */ + +/**************************************************************************** +* IEEE SGE operation Macros +****************************************************************************/ + +/* SIMPLE FlagsLength manipulations... */ +#define MPI2_IEEE32_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT) +#define MPI2_IEEE32_SGE_GET_FLAGS(f) (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) >> MPI2_IEEE32_SGE_FLAGS_SHIFT) +#define MPI2_IEEE32_SGE_LENGTH(f) ((f) & MPI2_IEEE32_SGE_LENGTH_MASK) + +#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_IEEE32_SGE_SET_FLAGS(f) | MPI2_IEEE32_SGE_LENGTH(l)) + +#define MPI2_IEEE32_pSGE_GET_FLAGS(psg) MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength) +#define MPI2_IEEE32_pSGE_GET_LENGTH(psg) MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength) +#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f,l) + +/* CAUTION - The following are READ-MODIFY-WRITE! */ +#define MPI2_IEEE32_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_IEEE32_SGE_SET_FLAGS(f) +#define MPI2_IEEE32_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_IEEE32_SGE_LENGTH(l) + + + + +/***************************************************************************** +* +* Fusion-MPT MPI/IEEE Scatter Gather Unions +* +*****************************************************************************/ + +typedef union _MPI2_SIMPLE_SGE_UNION +{ + MPI2_SGE_SIMPLE_UNION MpiSimple; + MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; +} MPI2_SIMPLE_SGE_UNION, MPI2_POINTER PTR_MPI2_SIMPLE_SGE_UNION, + Mpi2SimpleSgeUntion_t, MPI2_POINTER pMpi2SimpleSgeUntion_t; + + +typedef union _MPI2_SGE_IO_UNION +{ + MPI2_SGE_SIMPLE_UNION MpiSimple; + MPI2_SGE_CHAIN_UNION MpiChain; + MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; + MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; +} MPI2_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_SGE_IO_UNION, + Mpi2SGEIOUnion_t, MPI2_POINTER pMpi2SGEIOUnion_t; + + +/**************************************************************************** +* +* Values for SGLFlags field, used in many request messages with an SGL +* +****************************************************************************/ + +/* values for MPI SGL Data Location Address Space subfield */ +#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK (0x0C) +#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00) +#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04) +#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08) +#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C) +/* values for SGL Type subfield */ +#define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03) +#define MPI2_SGLFLAGS_SGL_TYPE_MPI (0x00) +#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32 (0x01) +#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64 (0x02) + + +#endif + diff --git a/source/lsi/mpi2_cnfg.h b/source/lsi/mpi2_cnfg.h new file mode 100755 index 0000000..5396fad --- /dev/null +++ b/source/lsi/mpi2_cnfg.h @@ -0,0 +1,3071 @@ +/* + * Copyright (c) 2000-2011 LSI Corporation. + * + * + * Name: mpi2_cnfg.h + * Title: MPI Configuration messages and pages + * Creation Date: November 10, 2006 + * + * mpi2_cnfg.h Version: 02.00.xx + * + * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 + * prefix are for use only on MPI v2.5 products, and must not be used + * with MPI v2.0 products. Unless otherwise noted, names beginning with + * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags. + * Added Manufacturing Page 11. + * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE + * define. + * 06-26-07 02.00.02 Adding generic structure for product-specific + * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS. + * Rework of BIOS Page 2 configuration page. + * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the + * forms. + * Added configuration pages IOC Page 8 and Driver + * Persistent Mapping Page 0. + * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated + * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1, + * RAID Physical Disk Pages 0 and 1, RAID Configuration + * Page 0). + * Added new value for AccessStatus field of SAS Device + * Page 0 (_SATA_NEEDS_INITIALIZATION). + * 10-31-07 02.00.04 Added missing SEPDevHandle field to + * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. + * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for + * NVDATA. + * Modified IOC Page 7 to use masks and added field for + * SASBroadcastPrimitiveMasks. + * Added MPI2_CONFIG_PAGE_BIOS_4. + * Added MPI2_CONFIG_PAGE_LOG_0. + * 02-29-08 02.00.06 Modified various names to make them 32-character unique. + * Added SAS Device IDs. + * Updated Integrated RAID configuration pages including + * Manufacturing Page 4, IOC Page 6, and RAID Configuration + * Page 0. + * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA. + * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION. + * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING. + * Added missing MaxNumRoutedSasAddresses field to + * MPI2_CONFIG_PAGE_EXPANDER_0. + * Added SAS Port Page 0. + * Modified structure layout for + * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0. + * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use + * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array. + * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF + * to 0x000000FF. + * Added two new values for the Physical Disk Coercion Size + * bits in the Flags field of Manufacturing Page 4. + * Added product-specific Manufacturing pages 16 to 31. + * Modified Flags bits for controlling write cache on SATA + * drives in IO Unit Page 1. + * Added new bit to AdditionalControlFlags of SAS IO Unit + * Page 1 to control Invalid Topology Correction. + * Added additional defines for RAID Volume Page 0 + * VolumeStatusFlags field. + * Modified meaning of RAID Volume Page 0 VolumeSettings + * define for auto-configure of hot-swap drives. + * Added SupportedPhysDisks field to RAID Volume Page 1 and + * added related defines. + * Added PhysDiskAttributes field (and related defines) to + * RAID Physical Disk Page 0. + * Added MPI2_SAS_PHYINFO_PHY_VACANT define. + * Added three new DiscoveryStatus bits for SAS IO Unit + * Page 0 and SAS Expander Page 0. + * Removed multiplexing information from SAS IO Unit pages. + * Added BootDeviceWaitTime field to SAS IO Unit Page 4. + * Removed Zone Address Resolved bit from PhyInfo and from + * Expander Page 0 Flags field. + * Added two new AccessStatus values to SAS Device Page 0 + * for indicating routing problems. Added 3 reserved words + * to this page. + * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3. + * Inserted missing reserved field into structure for IOC + * Page 6. + * Added more pending task bits to RAID Volume Page 0 + * VolumeStatusFlags defines. + * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define. + * Added a new DiscoveryStatus bit for SAS IO Unit Page 0 + * and SAS Expander Page 0 to flag a downstream initiator + * when in simplified routing mode. + * Removed SATA Init Failure defines for DiscoveryStatus + * fields of SAS IO Unit Page 0 and SAS Expander Page 0. + * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define. + * Added PortGroups, DmaGroup, and ControlGroup fields to + * SAS Device Page 0. + * 05-06-09 02.00.11 Added structures and defines for IO Unit Page 5 and IO + * Unit Page 6. + * Added expander reduced functionality data to SAS + * Expander Page 0. + * Added SAS PHY Page 2 and SAS PHY Page 3. + * 07-30-09 02.00.12 Added IO Unit Page 7. + * Added new device ids. + * Added SAS IO Unit Page 5. + * Added partial and slumber power management capable flags + * to SAS Device Page 0 Flags field. + * Added PhyInfo defines for power condition. + * Added Ethernet configuration pages. + * 10-28-09 02.00.13 Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY. + * Added SAS PHY Page 4 structure and defines. + * 02-10-10 02.00.14 Modified the comments for the configuration page + * structures that contain an array of data. The host + * should use the "count" field in the page data (e.g. the + * NumPhys field) to determine the number of valid elements + * in the array. + * Added/modified some MPI2_MFGPAGE_DEVID_SAS defines. + * Added PowerManagementCapabilities to IO Unit Page 7. + * Added PortWidthModGroup field to + * MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS. + * Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines. + * Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines. + * Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines. + * 05-12-10 02.00.15 Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT + * define. + * Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define. + * Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define. + * 08-11-10 02.00.16 Removed IO Unit Page 1 device path (multi-pathing) + * defines. + * 11-10-10 02.00.17 Added ReceptacleID field (replacing Reserved1) to + * MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for + * the Pinout field. + * Added BoardTemperature and BoardTemperatureUnits fields + * to MPI2_CONFIG_PAGE_IO_UNIT_7. + * Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define + * and MPI2_CONFIG_PAGE_EXT_MAN_PS structure. + * 02-23-11 02.00.18 Added ProxyVF_ID field to MPI2_CONFIG_REQUEST. + * Added IO Unit Page 8, IO Unit Page 9, + * and IO Unit Page 10. + * Added SASNotifyPrimitiveMasks field to + * MPI2_CONFIG_PAGE_IOC_7. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_CNFG_H +#define MPI2_CNFG_H + +/***************************************************************************** +* Configuration Page Header and defines +*****************************************************************************/ + +/* Config Page Header */ +typedef struct _MPI2_CONFIG_PAGE_HEADER +{ + U8 PageVersion; /* 0x00 */ + U8 PageLength; /* 0x01 */ + U8 PageNumber; /* 0x02 */ + U8 PageType; /* 0x03 */ +} MPI2_CONFIG_PAGE_HEADER, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER, + Mpi2ConfigPageHeader_t, MPI2_POINTER pMpi2ConfigPageHeader_t; + +typedef union _MPI2_CONFIG_PAGE_HEADER_UNION +{ + MPI2_CONFIG_PAGE_HEADER Struct; + U8 Bytes[4]; + U16 Word16[2]; + U32 Word32; +} MPI2_CONFIG_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER_UNION, + Mpi2ConfigPageHeaderUnion, MPI2_POINTER pMpi2ConfigPageHeaderUnion; + +/* Extended Config Page Header */ +typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER +{ + U8 PageVersion; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 PageNumber; /* 0x02 */ + U8 PageType; /* 0x03 */ + U16 ExtPageLength; /* 0x04 */ + U8 ExtPageType; /* 0x06 */ + U8 Reserved2; /* 0x07 */ +} MPI2_CONFIG_EXTENDED_PAGE_HEADER, + MPI2_POINTER PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER, + Mpi2ConfigExtendedPageHeader_t, MPI2_POINTER pMpi2ConfigExtendedPageHeader_t; + +typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION +{ + MPI2_CONFIG_PAGE_HEADER Struct; + MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext; + U8 Bytes[8]; + U16 Word16[4]; + U32 Word32[2]; +} MPI2_CONFIG_EXT_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION, + Mpi2ConfigPageExtendedHeaderUnion, MPI2_POINTER pMpi2ConfigPageExtendedHeaderUnion; + + +/* PageType field values */ +#define MPI2_CONFIG_PAGEATTR_READ_ONLY (0x00) +#define MPI2_CONFIG_PAGEATTR_CHANGEABLE (0x10) +#define MPI2_CONFIG_PAGEATTR_PERSISTENT (0x20) +#define MPI2_CONFIG_PAGEATTR_MASK (0xF0) + +#define MPI2_CONFIG_PAGETYPE_IO_UNIT (0x00) +#define MPI2_CONFIG_PAGETYPE_IOC (0x01) +#define MPI2_CONFIG_PAGETYPE_BIOS (0x02) +#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME (0x08) +#define MPI2_CONFIG_PAGETYPE_MANUFACTURING (0x09) +#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A) +#define MPI2_CONFIG_PAGETYPE_EXTENDED (0x0F) +#define MPI2_CONFIG_PAGETYPE_MASK (0x0F) + +#define MPI2_CONFIG_TYPENUM_MASK (0x0FFF) + + +/* ExtPageType field values */ +#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10) +#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11) +#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12) +#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY (0x13) +#define MPI2_CONFIG_EXTPAGETYPE_LOG (0x14) +#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15) +#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG (0x16) +#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17) +#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18) +#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19) +#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A) + + +/***************************************************************************** +* PageAddress defines +*****************************************************************************/ + +/* RAID Volume PageAddress format */ +#define MPI2_RAID_VOLUME_PGAD_FORM_MASK (0xF0000000) +#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE (0x10000000) + +#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK (0x0000FFFF) + + +/* RAID Physical Disk PageAddress format */ +#define MPI2_PHYSDISK_PGAD_FORM_MASK (0xF0000000) +#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM (0x00000000) +#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM (0x10000000) +#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE (0x20000000) + +#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF) +#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK (0x0000FFFF) + + +/* SAS Expander PageAddress format */ +#define MPI2_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000) +#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL (0x00000000) +#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM (0x10000000) +#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL (0x20000000) + +#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF) +#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000) +#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16) + + +/* SAS Device PageAddress format */ +#define MPI2_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000) +#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE (0x20000000) + +#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF) + + +/* SAS PHY PageAddress format */ +#define MPI2_SAS_PHY_PGAD_FORM_MASK (0xF0000000) +#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000) +#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x10000000) + +#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF) +#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF) + + +/* SAS Port PageAddress format */ +#define MPI2_SASPORT_PGAD_FORM_MASK (0xF0000000) +#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000) +#define MPI2_SASPORT_PGAD_FORM_PORT_NUM (0x10000000) + +#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK (0x00000FFF) + + +/* SAS Enclosure PageAddress format */ +#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000) +#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE (0x10000000) + +#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF) + + +/* RAID Configuration PageAddress format */ +#define MPI2_RAID_PGAD_FORM_MASK (0xF0000000) +#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM (0x00000000) +#define MPI2_RAID_PGAD_FORM_CONFIGNUM (0x10000000) +#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG (0x20000000) + +#define MPI2_RAID_PGAD_CONFIGNUM_MASK (0x000000FF) + + +/* Driver Persistent Mapping PageAddress format */ +#define MPI2_DPM_PGAD_FORM_MASK (0xF0000000) +#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE (0x00000000) + +#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK (0x0FFF0000) +#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT (16) +#define MPI2_DPM_PGAD_START_ENTRY_MASK (0x0000FFFF) + + +/* Ethernet PageAddress format */ +#define MPI2_ETHERNET_PGAD_FORM_MASK (0xF0000000) +#define MPI2_ETHERNET_PGAD_FORM_IF_NUM (0x00000000) + +#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK (0x000000FF) + + + +/**************************************************************************** +* Configuration messages +****************************************************************************/ + +/* Configuration Request Message */ +typedef struct _MPI2_CONFIG_REQUEST +{ + U8 Action; /* 0x00 */ + U8 SGLFlags; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 ExtPageLength; /* 0x04 */ + U8 ExtPageType; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U8 Reserved2; /* 0x0C */ + U8 ProxyVF_ID; /* 0x0D */ + U16 Reserved4; /* 0x0E */ + U32 Reserved3; /* 0x10 */ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */ + U32 PageAddress; /* 0x18 */ + MPI2_SGE_IO_UNION PageBufferSGE; /* 0x1C */ +} MPI2_CONFIG_REQUEST, MPI2_POINTER PTR_MPI2_CONFIG_REQUEST, + Mpi2ConfigRequest_t, MPI2_POINTER pMpi2ConfigRequest_t; + +/* values for the Action field */ +#define MPI2_CONFIG_ACTION_PAGE_HEADER (0x00) +#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT (0x01) +#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02) +#define MPI2_CONFIG_ACTION_PAGE_DEFAULT (0x03) +#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04) +#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05) +#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06) +#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07) + +/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ + + +/* Config Reply Message */ +typedef struct _MPI2_CONFIG_REPLY +{ + U8 Action; /* 0x00 */ + U8 SGLFlags; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 ExtPageLength; /* 0x04 */ + U8 ExtPageType; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U16 Reserved2; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */ +} MPI2_CONFIG_REPLY, MPI2_POINTER PTR_MPI2_CONFIG_REPLY, + Mpi2ConfigReply_t, MPI2_POINTER pMpi2ConfigReply_t; + + + +/***************************************************************************** +* +* C o n f i g u r a t i o n P a g e s +* +*****************************************************************************/ + +/**************************************************************************** +* Manufacturing Config pages +****************************************************************************/ + +#define MPI2_MFGPAGE_VENDORID_LSI (0x1000) + +/* MPI v2.0 SAS products */ +#define MPI2_MFGPAGE_DEVID_SAS2004 (0x0070) +#define MPI2_MFGPAGE_DEVID_SAS2008 (0x0072) +#define MPI2_MFGPAGE_DEVID_SAS2108_1 (0x0074) +#define MPI2_MFGPAGE_DEVID_SAS2108_2 (0x0076) +#define MPI2_MFGPAGE_DEVID_SAS2108_3 (0x0077) +#define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064) +#define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065) + +#define MPI2_MFGPAGE_DEVID_SSS6200 (0x007E) + +#define MPI2_MFGPAGE_DEVID_SAS2208_1 (0x0080) +#define MPI2_MFGPAGE_DEVID_SAS2208_2 (0x0081) +#define MPI2_MFGPAGE_DEVID_SAS2208_3 (0x0082) +#define MPI2_MFGPAGE_DEVID_SAS2208_4 (0x0083) +#define MPI2_MFGPAGE_DEVID_SAS2208_5 (0x0084) +#define MPI2_MFGPAGE_DEVID_SAS2208_6 (0x0085) +#define MPI2_MFGPAGE_DEVID_SAS2308_1 (0x0086) +#define MPI2_MFGPAGE_DEVID_SAS2308_2 (0x0087) +#define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E) + +/* MPI v2.5 SAS products */ +#define MPI25_MFGPAGE_DEVID_SAS3004 (0x0096) +#define MPI25_MFGPAGE_DEVID_SAS3008 (0x0097) +#define MPI25_MFGPAGE_DEVID_SAS3108_1 (0x0090) +#define MPI25_MFGPAGE_DEVID_SAS3108_2 (0x0091) +#define MPI25_MFGPAGE_DEVID_SAS3108_5 (0x0094) +#define MPI25_MFGPAGE_DEVID_SAS3108_6 (0x0095) + + + + +/* Manufacturing Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_MAN_0 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 ChipName[16]; /* 0x04 */ + U8 ChipRevision[8]; /* 0x14 */ + U8 BoardName[16]; /* 0x1C */ + U8 BoardAssembly[16]; /* 0x2C */ + U8 BoardTracerNumber[16]; /* 0x3C */ +} MPI2_CONFIG_PAGE_MAN_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_0, + Mpi2ManufacturingPage0_t, MPI2_POINTER pMpi2ManufacturingPage0_t; + +#define MPI2_MANUFACTURING0_PAGEVERSION (0x00) + + +/* Manufacturing Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_MAN_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 VPD[256]; /* 0x04 */ +} MPI2_CONFIG_PAGE_MAN_1, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_1, + Mpi2ManufacturingPage1_t, MPI2_POINTER pMpi2ManufacturingPage1_t; + +#define MPI2_MANUFACTURING1_PAGEVERSION (0x00) + + +typedef struct _MPI2_CHIP_REVISION_ID +{ + U16 DeviceID; /* 0x00 */ + U8 PCIRevisionID; /* 0x02 */ + U8 Reserved; /* 0x03 */ +} MPI2_CHIP_REVISION_ID, MPI2_POINTER PTR_MPI2_CHIP_REVISION_ID, + Mpi2ChipRevisionId_t, MPI2_POINTER pMpi2ChipRevisionId_t; + + +/* Manufacturing Page 2 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS +#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_MAN_2 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */ + U32 HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 0x08 */ +} MPI2_CONFIG_PAGE_MAN_2, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_2, + Mpi2ManufacturingPage2_t, MPI2_POINTER pMpi2ManufacturingPage2_t; + +#define MPI2_MANUFACTURING2_PAGEVERSION (0x00) + + +/* Manufacturing Page 3 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI2_MAN_PAGE_3_INFO_WORDS +#define MPI2_MAN_PAGE_3_INFO_WORDS (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_MAN_3 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */ + U32 Info[MPI2_MAN_PAGE_3_INFO_WORDS];/* 0x08 */ +} MPI2_CONFIG_PAGE_MAN_3, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_3, + Mpi2ManufacturingPage3_t, MPI2_POINTER pMpi2ManufacturingPage3_t; + +#define MPI2_MANUFACTURING3_PAGEVERSION (0x00) + + +/* Manufacturing Page 4 */ + +typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS +{ + U8 PowerSaveFlags; /* 0x00 */ + U8 InternalOperationsSleepTime; /* 0x01 */ + U8 InternalOperationsRunTime; /* 0x02 */ + U8 HostIdleTime; /* 0x03 */ +} MPI2_MANPAGE4_PWR_SAVE_SETTINGS, + MPI2_POINTER PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS, + Mpi2ManPage4PwrSaveSettings_t, MPI2_POINTER pMpi2ManPage4PwrSaveSettings_t; + +/* defines for the PowerSaveFlags field */ +#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE (0x03) +#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED (0x00) +#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE (0x01) +#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE (0x02) + +typedef struct _MPI2_CONFIG_PAGE_MAN_4 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Flags; /* 0x08 */ + U8 InquirySize; /* 0x0C */ + U8 Reserved2; /* 0x0D */ + U16 Reserved3; /* 0x0E */ + U8 InquiryData[56]; /* 0x10 */ + U32 RAID0VolumeSettings; /* 0x48 */ + U32 RAID1EVolumeSettings; /* 0x4C */ + U32 RAID1VolumeSettings; /* 0x50 */ + U32 RAID10VolumeSettings; /* 0x54 */ + U32 Reserved4; /* 0x58 */ + U32 Reserved5; /* 0x5C */ + MPI2_MANPAGE4_PWR_SAVE_SETTINGS PowerSaveSettings; /* 0x60 */ + U8 MaxOCEDisks; /* 0x64 */ + U8 ResyncRate; /* 0x65 */ + U16 DataScrubDuration; /* 0x66 */ + U8 MaxHotSpares; /* 0x68 */ + U8 MaxPhysDisksPerVol; /* 0x69 */ + U8 MaxPhysDisks; /* 0x6A */ + U8 MaxVolumes; /* 0x6B */ +} MPI2_CONFIG_PAGE_MAN_4, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_4, + Mpi2ManufacturingPage4_t, MPI2_POINTER pMpi2ManufacturingPage4_t; + +#define MPI2_MANUFACTURING4_PAGEVERSION (0x0A) + +/* Manufacturing Page 4 Flags field */ +#define MPI2_MANPAGE4_METADATA_SIZE_MASK (0x00030000) +#define MPI2_MANPAGE4_METADATA_512MB (0x00000000) + +#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA (0x00008000) +#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD (0x00004000) +#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR (0x00002000) + +#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION (0x00001C00) +#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB (0x00000000) +#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION (0x00000400) +#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION (0x00000800) +#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION (0x00000C00) + +#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING (0x00000300) +#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING (0x00000000) +#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING (0x00000100) +#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING (0x00000200) + +#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x00000080) +#define MPI2_MANPAGE4_RAID10_DISABLE (0x00000040) +#define MPI2_MANPAGE4_RAID1E_DISABLE (0x00000020) +#define MPI2_MANPAGE4_RAID1_DISABLE (0x00000010) +#define MPI2_MANPAGE4_RAID0_DISABLE (0x00000008) +#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE (0x00000004) +#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x00000002) +#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA (0x00000001) + + +/* Manufacturing Page 5 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhys at runtime. + */ +#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES +#define MPI2_MAN_PAGE_5_PHY_ENTRIES (1) +#endif + +typedef struct _MPI2_MANUFACTURING5_ENTRY +{ + U64 WWID; /* 0x00 */ + U64 DeviceName; /* 0x08 */ +} MPI2_MANUFACTURING5_ENTRY, MPI2_POINTER PTR_MPI2_MANUFACTURING5_ENTRY, + Mpi2Manufacturing5Entry_t, MPI2_POINTER pMpi2Manufacturing5Entry_t; + +typedef struct _MPI2_CONFIG_PAGE_MAN_5 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 NumPhys; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U32 Reserved3; /* 0x08 */ + U32 Reserved4; /* 0x0C */ + MPI2_MANUFACTURING5_ENTRY Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/* 0x08 */ +} MPI2_CONFIG_PAGE_MAN_5, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_5, + Mpi2ManufacturingPage5_t, MPI2_POINTER pMpi2ManufacturingPage5_t; + +#define MPI2_MANUFACTURING5_PAGEVERSION (0x03) + + +/* Manufacturing Page 6 */ + +typedef struct _MPI2_CONFIG_PAGE_MAN_6 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 ProductSpecificInfo;/* 0x04 */ +} MPI2_CONFIG_PAGE_MAN_6, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_6, + Mpi2ManufacturingPage6_t, MPI2_POINTER pMpi2ManufacturingPage6_t; + +#define MPI2_MANUFACTURING6_PAGEVERSION (0x00) + + +/* Manufacturing Page 7 */ + +typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO +{ + U32 Pinout; /* 0x00 */ + U8 Connector[16]; /* 0x04 */ + U8 Location; /* 0x14 */ + U8 ReceptacleID; /* 0x15 */ + U16 Slot; /* 0x16 */ + U32 Reserved2; /* 0x18 */ +} MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO, + Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t; + +/* defines for the Pinout field */ +#define MPI2_MANPAGE7_PINOUT_LANE_MASK (0x0000FF00) +#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT (8) + +#define MPI2_MANPAGE7_PINOUT_TYPE_MASK (0x000000FF) +#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN (0x00) +#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE (0x01) +#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x02) +#define MPI2_MANPAGE7_PINOUT_SFF_8486 (0x03) +#define MPI2_MANPAGE7_PINOUT_SFF_8484 (0x04) +#define MPI2_MANPAGE7_PINOUT_SFF_8087 (0x05) +#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I (0x06) +#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I (0x07) +#define MPI2_MANPAGE7_PINOUT_SFF_8470 (0x08) +#define MPI2_MANPAGE7_PINOUT_SFF_8088 (0x09) +#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X (0x0A) +#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B) +#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C) +#define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D) + +/* defines for the Location field */ +#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01) +#define MPI2_MANPAGE7_LOCATION_INTERNAL (0x02) +#define MPI2_MANPAGE7_LOCATION_EXTERNAL (0x04) +#define MPI2_MANPAGE7_LOCATION_SWITCHABLE (0x08) +#define MPI2_MANPAGE7_LOCATION_AUTO (0x10) +#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT (0x20) +#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED (0x80) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhys at runtime. + */ +#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX +#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_MAN_7 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Reserved2; /* 0x08 */ + U32 Flags; /* 0x0C */ + U8 EnclosureName[16]; /* 0x10 */ + U8 NumPhys; /* 0x20 */ + U8 Reserved3; /* 0x21 */ + U16 Reserved4; /* 0x22 */ + MPI2_MANPAGE7_CONNECTOR_INFO ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /* 0x24 */ +} MPI2_CONFIG_PAGE_MAN_7, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7, + Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t; + +#define MPI2_MANUFACTURING7_PAGEVERSION (0x01) + +/* defines for the Flags field */ +#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) + + +/* + * Generic structure to use for product-specific manufacturing pages + * (currently Manufacturing Page 8 through Manufacturing Page 31). + */ + +typedef struct _MPI2_CONFIG_PAGE_MAN_PS +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 ProductSpecificInfo;/* 0x04 */ +} MPI2_CONFIG_PAGE_MAN_PS, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_PS, + Mpi2ManufacturingPagePS_t, MPI2_POINTER pMpi2ManufacturingPagePS_t; + +#define MPI2_MANUFACTURING8_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING9_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING10_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING11_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING12_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING13_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING14_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING15_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING16_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING17_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING18_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING19_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING20_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING21_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING22_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING23_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING24_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING25_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING26_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING27_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING28_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING29_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING30_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING31_PAGEVERSION (0x00) + + +/**************************************************************************** +* IO Unit Config Pages +****************************************************************************/ + +/* IO Unit Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U64 UniqueValue; /* 0x04 */ + MPI2_VERSION_UNION NvdataVersionDefault; /* 0x08 */ + MPI2_VERSION_UNION NvdataVersionPersistent; /* 0x0A */ +} MPI2_CONFIG_PAGE_IO_UNIT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_0, + Mpi2IOUnitPage0_t, MPI2_POINTER pMpi2IOUnitPage0_t; + +#define MPI2_IOUNITPAGE0_PAGEVERSION (0x02) + + +/* IO Unit Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Flags; /* 0x04 */ +} MPI2_CONFIG_PAGE_IO_UNIT_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_1, + Mpi2IOUnitPage1_t, MPI2_POINTER pMpi2IOUnitPage1_t; + +#define MPI2_IOUNITPAGE1_PAGEVERSION (0x04) + +/* IO Unit Page 1 Flags defines */ +#define MPI25_IOUNITPAGE1_NEW_DEVICE_FAST_PATH_DISABLE (0x00002000) +#define MPI25_IOUNITPAGE1_DISABLE_FAST_PATH (0x00001000) +#define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY (0x00000800) +#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600) +#define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT (9) +#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000) +#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200) +#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400) +#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) +#define MPI2_IOUNITPAGE1_DISABLE_IR (0x00000040) +#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020) +#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004) + + +/* IO Unit Page 3 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for GPIOCount at runtime. + */ +#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX +#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 GPIOCount; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U16 GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/* 0x08 */ +} MPI2_CONFIG_PAGE_IO_UNIT_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_3, + Mpi2IOUnitPage3_t, MPI2_POINTER pMpi2IOUnitPage3_t; + +#define MPI2_IOUNITPAGE3_PAGEVERSION (0x01) + +/* defines for IO Unit Page 3 GPIOVal field */ +#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFFFC) +#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2) +#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF (0x0000) +#define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001) + + +/* IO Unit Page 5 */ + +/* + * Upper layer code (drivers, utilities, etc.) should leave this define set to + * one and check the value returned for NumDmaEngines at runtime. + */ +#ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES +#define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U64 RaidAcceleratorBufferBaseAddress; /* 0x04 */ + U64 RaidAcceleratorBufferSize; /* 0x0C */ + U64 RaidAcceleratorControlBaseAddress; /* 0x14 */ + U8 RAControlSize; /* 0x1C */ + U8 NumDmaEngines; /* 0x1D */ + U8 RAMinControlSize; /* 0x1E */ + U8 RAMaxControlSize; /* 0x1F */ + U32 Reserved1; /* 0x20 */ + U32 Reserved2; /* 0x24 */ + U32 Reserved3; /* 0x28 */ + U32 DmaEngineCapabilities[MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /* 0x2C */ +} MPI2_CONFIG_PAGE_IO_UNIT_5, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_5, + Mpi2IOUnitPage5_t, MPI2_POINTER pMpi2IOUnitPage5_t; + +#define MPI2_IOUNITPAGE5_PAGEVERSION (0x00) + +/* defines for IO Unit Page 5 DmaEngineCapabilities field */ +#define MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS (0xFF00) +#define MPI2_IOUNITPAGE5_DMA_CAP_SHIFT_MAX_REQUESTS (16) + +#define MPI2_IOUNITPAGE5_DMA_CAP_EEDP (0x0008) +#define MPI2_IOUNITPAGE5_DMA_CAP_PARITY_GENERATION (0x0004) +#define MPI2_IOUNITPAGE5_DMA_CAP_HASHING (0x0002) +#define MPI2_IOUNITPAGE5_DMA_CAP_ENCRYPTION (0x0001) + + +/* IO Unit Page 6 */ + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_6 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U16 Flags; /* 0x04 */ + U8 RAHostControlSize; /* 0x06 */ + U8 Reserved0; /* 0x07 */ + U64 RaidAcceleratorHostControlBaseAddress; /* 0x08 */ + U32 Reserved1; /* 0x10 */ + U32 Reserved2; /* 0x14 */ + U32 Reserved3; /* 0x18 */ +} MPI2_CONFIG_PAGE_IO_UNIT_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_6, + Mpi2IOUnitPage6_t, MPI2_POINTER pMpi2IOUnitPage6_t; + +#define MPI2_IOUNITPAGE6_PAGEVERSION (0x00) + +/* defines for IO Unit Page 6 Flags field */ +#define MPI2_IOUNITPAGE6_FLAGS_ENABLE_RAID_ACCELERATOR (0x0001) + + +/* IO Unit Page 7 */ + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 CurrentPowerMode; /* 0x04 */ /* reserved in MPI 2.0 */ + U8 PreviousPowerMode; /* 0x05 */ /* reserved in MPI 2.0 */ + U8 PCIeWidth; /* 0x06 */ + U8 PCIeSpeed; /* 0x07 */ + U32 ProcessorState; /* 0x08 */ + U32 PowerManagementCapabilities; /* 0x0C */ + U16 IOCTemperature; /* 0x10 */ + U8 IOCTemperatureUnits; /* 0x12 */ + U8 IOCSpeed; /* 0x13 */ + U16 BoardTemperature; /* 0x14 */ + U8 BoardTemperatureUnits; /* 0x16 */ + U8 Reserved3; /* 0x17 */ +} MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7, + Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t; + +#define MPI2_IOUNITPAGE7_PAGEVERSION (0x02) + +/* defines for IO Unit Page 7 CurrentPowerMode and PreviousPowerMode fields */ +#define MPI25_IOUNITPAGE7_PM_INIT_MASK (0xC0) +#define MPI25_IOUNITPAGE7_PM_INIT_UNAVAILABLE (0x00) +#define MPI25_IOUNITPAGE7_PM_INIT_HOST (0x40) +#define MPI25_IOUNITPAGE7_PM_INIT_IO_UNIT (0x80) +#define MPI25_IOUNITPAGE7_PM_INIT_PCIE_DPA (0xC0) + +#define MPI25_IOUNITPAGE7_PM_MODE_MASK (0x07) +#define MPI25_IOUNITPAGE7_PM_MODE_UNAVAILABLE (0x00) +#define MPI25_IOUNITPAGE7_PM_MODE_UNKNOWN (0x01) +#define MPI25_IOUNITPAGE7_PM_MODE_FULL_POWER (0x04) +#define MPI25_IOUNITPAGE7_PM_MODE_REDUCED_POWER (0x05) +#define MPI25_IOUNITPAGE7_PM_MODE_STANDBY (0x06) + + +/* defines for IO Unit Page 7 PCIeWidth field */ +#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1 (0x01) +#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2 (0x02) +#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4 (0x04) +#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8 (0x08) + +/* defines for IO Unit Page 7 PCIeSpeed field */ +#define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS (0x00) +#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS (0x01) +#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS (0x02) + +/* defines for IO Unit Page 7 ProcessorState field */ +#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND (0x0000000F) +#define MPI2_IOUNITPAGE7_PSTATE_SHIFT_SECOND (0) + +#define MPI2_IOUNITPAGE7_PSTATE_NOT_PRESENT (0x00) +#define MPI2_IOUNITPAGE7_PSTATE_DISABLED (0x01) +#define MPI2_IOUNITPAGE7_PSTATE_ENABLED (0x02) + +/* defines for IO Unit Page 7 PowerManagementCapabilities field */ +#define MPI25_IOUNITPAGE7_PMCAP_DPA_FULL_PWR_MODE (0x00400000) +#define MPI25_IOUNITPAGE7_PMCAP_DPA_REDUCED_PWR_MODE (0x00200000) +#define MPI25_IOUNITPAGE7_PMCAP_DPA_STANDBY_MODE (0x00100000) +#define MPI25_IOUNITPAGE7_PMCAP_HOST_FULL_PWR_MODE (0x00040000) +#define MPI25_IOUNITPAGE7_PMCAP_HOST_REDUCED_PWR_MODE (0x00020000) +#define MPI25_IOUNITPAGE7_PMCAP_HOST_STANDBY_MODE (0x00010000) +#define MPI25_IOUNITPAGE7_PMCAP_IO_FULL_PWR_MODE (0x00004000) +#define MPI25_IOUNITPAGE7_PMCAP_IO_REDUCED_PWR_MODE (0x00002000) +#define MPI25_IOUNITPAGE7_PMCAP_IO_STANDBY_MODE (0x00001000) +#define MPI2_IOUNITPAGE7_PMCAP_HOST_12_5_PCT_IOCSPEED (0x00000400) +#define MPI2_IOUNITPAGE7_PMCAP_HOST_25_0_PCT_IOCSPEED (0x00000200) +#define MPI2_IOUNITPAGE7_PMCAP_HOST_50_0_PCT_IOCSPEED (0x00000100) +#define MPI25_IOUNITPAGE7_PMCAP_IO_12_5_PCT_IOCSPEED (0x00000040) +#define MPI25_IOUNITPAGE7_PMCAP_IO_25_0_PCT_IOCSPEED (0x00000020) +#define MPI25_IOUNITPAGE7_PMCAP_IO_50_0_PCT_IOCSPEED (0x00000010) +#define MPI2_IOUNITPAGE7_PMCAP_HOST_WIDTH_CHANGE_PCIE (0x00000008) +#define MPI2_IOUNITPAGE7_PMCAP_HOST_SPEED_CHANGE_PCIE (0x00000004) +#define MPI25_IOUNITPAGE7_PMCAP_IO_WIDTH_CHANGE_PCIE (0x00000002) +#define MPI25_IOUNITPAGE7_PMCAP_IO_SPEED_CHANGE_PCIE (0x00000001) + +/* obsolete names for the PowerManagementCapabilities bits (above) */ +#define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED (0x00000400) +#define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED (0x00000200) +#define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED (0x00000100) +#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008) +#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004) + + +/* defines for IO Unit Page 7 IOCTemperatureUnits field */ +#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00) +#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01) +#define MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS (0x02) + +/* defines for IO Unit Page 7 IOCSpeed field */ +#define MPI2_IOUNITPAGE7_IOC_SPEED_FULL (0x01) +#define MPI2_IOUNITPAGE7_IOC_SPEED_HALF (0x02) +#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER (0x04) +#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH (0x08) + +/* defines for IO Unit Page 7 BoardTemperatureUnits field */ +#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT (0x00) +#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01) +#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02) + + +/* IO Unit Page 8 */ + +#define MPI2_IOUNIT8_NUM_THRESHOLDS (4) + +typedef struct _MPI2_IOUNIT8_SENSOR +{ + U16 Flags; /* 0x00 */ + U16 Reserved1; /* 0x02 */ + U16 Threshold[MPI2_IOUNIT8_NUM_THRESHOLDS]; /* 0x04 */ + U32 Reserved2; /* 0x0C */ + U32 Reserved3; /* 0x10 */ + U32 Reserved4; /* 0x14 */ +} MPI2_IOUNIT8_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT8_SENSOR, + Mpi2IOUnit8Sensor_t, MPI2_POINTER pMpi2IOUnit8Sensor_t; + +/* defines for IO Unit Page 8 Sensor Flags field */ +#define MPI2_IOUNIT8_SENSOR_FLAGS_T3_ENABLE (0x0008) +#define MPI2_IOUNIT8_SENSOR_FLAGS_T2_ENABLE (0x0004) +#define MPI2_IOUNIT8_SENSOR_FLAGS_T1_ENABLE (0x0002) +#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE (0x0001) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumSensors at runtime. + */ +#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES +#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Reserved2; /* 0x08 */ + U8 NumSensors; /* 0x0C */ + U8 PollingInterval; /* 0x0D */ + U16 Reserved3; /* 0x0E */ + MPI2_IOUNIT8_SENSOR Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/* 0x10 */ +} MPI2_CONFIG_PAGE_IO_UNIT_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_8, + Mpi2IOUnitPage8_t, MPI2_POINTER pMpi2IOUnitPage8_t; + +#define MPI2_IOUNITPAGE8_PAGEVERSION (0x00) + + +/* IO Unit Page 9 */ + +typedef struct _MPI2_IOUNIT9_SENSOR +{ + U16 CurrentTemperature; /* 0x00 */ + U16 Reserved1; /* 0x02 */ + U8 Flags; /* 0x04 */ + U8 Reserved2; /* 0x05 */ + U16 Reserved3; /* 0x06 */ + U32 Reserved4; /* 0x08 */ + U32 Reserved5; /* 0x0C */ +} MPI2_IOUNIT9_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT9_SENSOR, + Mpi2IOUnit9Sensor_t, MPI2_POINTER pMpi2IOUnit9Sensor_t; + +/* defines for IO Unit Page 9 Sensor Flags field */ +#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID (0x01) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumSensors at runtime. + */ +#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES +#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Reserved2; /* 0x08 */ + U8 NumSensors; /* 0x0C */ + U8 Reserved4; /* 0x0D */ + U16 Reserved3; /* 0x0E */ + MPI2_IOUNIT9_SENSOR Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/* 0x10 */ +} MPI2_CONFIG_PAGE_IO_UNIT_9, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_9, + Mpi2IOUnitPage9_t, MPI2_POINTER pMpi2IOUnitPage9_t; + +#define MPI2_IOUNITPAGE9_PAGEVERSION (0x00) + + +/* IO Unit Page 10 */ + +typedef struct _MPI2_IOUNIT10_FUNCTION +{ + U8 CreditPercent; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ +} MPI2_IOUNIT10_FUNCTION, MPI2_POINTER PTR_MPI2_IOUNIT10_FUNCTION, + Mpi2IOUnit10Function_t, MPI2_POINTER pMpi2IOUnit10Function_t; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumFunctions at runtime. + */ +#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES +#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 NumSensors; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U32 Reserved3; /* 0x08 */ + U16 Reserved4; /* 0x0C */ + MPI2_IOUNIT10_FUNCTION Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES]; /* 0x10 */ +} MPI2_CONFIG_PAGE_IO_UNIT_10, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_10, + Mpi2IOUnitPage10_t, MPI2_POINTER pMpi2IOUnitPage10_t; + +#define MPI2_IOUNITPAGE10_PAGEVERSION (0x00) + + + +/**************************************************************************** +* IOC Config Pages +****************************************************************************/ + +/* IOC Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_IOC_0 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Reserved2; /* 0x08 */ + U16 VendorID; /* 0x0C */ + U16 DeviceID; /* 0x0E */ + U8 RevisionID; /* 0x10 */ + U8 Reserved3; /* 0x11 */ + U16 Reserved4; /* 0x12 */ + U32 ClassCode; /* 0x14 */ + U16 SubsystemVendorID; /* 0x18 */ + U16 SubsystemID; /* 0x1A */ +} MPI2_CONFIG_PAGE_IOC_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_0, + Mpi2IOCPage0_t, MPI2_POINTER pMpi2IOCPage0_t; + +#define MPI2_IOCPAGE0_PAGEVERSION (0x02) + + +/* IOC Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_IOC_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Flags; /* 0x04 */ + U32 CoalescingTimeout; /* 0x08 */ + U8 CoalescingDepth; /* 0x0C */ + U8 PCISlotNum; /* 0x0D */ + U8 PCIBusNum; /* 0x0E */ + U8 PCIDomainSegment; /* 0x0F */ + U32 Reserved1; /* 0x10 */ + U32 Reserved2; /* 0x14 */ +} MPI2_CONFIG_PAGE_IOC_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_1, + Mpi2IOCPage1_t, MPI2_POINTER pMpi2IOCPage1_t; + +#define MPI2_IOCPAGE1_PAGEVERSION (0x05) + +/* defines for IOC Page 1 Flags field */ +#define MPI2_IOCPAGE1_REPLY_COALESCING (0x00000001) + +#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF) +#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN (0xFF) +#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN (0xFF) + +/* IOC Page 6 */ + +typedef struct _MPI2_CONFIG_PAGE_IOC_6 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 CapabilitiesFlags; /* 0x04 */ + U8 MaxDrivesRAID0; /* 0x08 */ + U8 MaxDrivesRAID1; /* 0x09 */ + U8 MaxDrivesRAID1E; /* 0x0A */ + U8 MaxDrivesRAID10; /* 0x0B */ + U8 MinDrivesRAID0; /* 0x0C */ + U8 MinDrivesRAID1; /* 0x0D */ + U8 MinDrivesRAID1E; /* 0x0E */ + U8 MinDrivesRAID10; /* 0x0F */ + U32 Reserved1; /* 0x10 */ + U8 MaxGlobalHotSpares; /* 0x14 */ + U8 MaxPhysDisks; /* 0x15 */ + U8 MaxVolumes; /* 0x16 */ + U8 MaxConfigs; /* 0x17 */ + U8 MaxOCEDisks; /* 0x18 */ + U8 Reserved2; /* 0x19 */ + U16 Reserved3; /* 0x1A */ + U32 SupportedStripeSizeMapRAID0; /* 0x1C */ + U32 SupportedStripeSizeMapRAID1E; /* 0x20 */ + U32 SupportedStripeSizeMapRAID10; /* 0x24 */ + U32 Reserved4; /* 0x28 */ + U32 Reserved5; /* 0x2C */ + U16 DefaultMetadataSize; /* 0x30 */ + U16 Reserved6; /* 0x32 */ + U16 MaxBadBlockTableEntries; /* 0x34 */ + U16 Reserved7; /* 0x36 */ + U32 IRNvsramVersion; /* 0x38 */ +} MPI2_CONFIG_PAGE_IOC_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_6, + Mpi2IOCPage6_t, MPI2_POINTER pMpi2IOCPage6_t; + +#define MPI2_IOCPAGE6_PAGEVERSION (0x04) + +/* defines for IOC Page 6 CapabilitiesFlags */ +#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT (0x00000010) +#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT (0x00000008) +#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT (0x00000004) +#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT (0x00000002) +#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001) + + +/* IOC Page 7 */ + +#define MPI2_IOCPAGE7_EVENTMASK_WORDS (4) + +typedef struct _MPI2_CONFIG_PAGE_IOC_7 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/* 0x08 */ + U16 SASBroadcastPrimitiveMasks; /* 0x18 */ + U16 SASNotifyPrimitiveMasks; /* 0x1A */ + U32 Reserved3; /* 0x1C */ +} MPI2_CONFIG_PAGE_IOC_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_7, + Mpi2IOCPage7_t, MPI2_POINTER pMpi2IOCPage7_t; + +#define MPI2_IOCPAGE7_PAGEVERSION (0x02) + + +/* IOC Page 8 */ + +typedef struct _MPI2_CONFIG_PAGE_IOC_8 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 NumDevsPerEnclosure; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U16 MaxPersistentEntries; /* 0x08 */ + U16 MaxNumPhysicalMappedIDs; /* 0x0A */ + U16 Flags; /* 0x0C */ + U16 Reserved3; /* 0x0E */ + U16 IRVolumeMappingFlags; /* 0x10 */ + U16 Reserved4; /* 0x12 */ + U32 Reserved5; /* 0x14 */ +} MPI2_CONFIG_PAGE_IOC_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_8, + Mpi2IOCPage8_t, MPI2_POINTER pMpi2IOCPage8_t; + +#define MPI2_IOCPAGE8_PAGEVERSION (0x00) + +/* defines for IOC Page 8 Flags field */ +#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1 (0x00000020) +#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0 (0x00000010) + +#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE (0x0000000E) +#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING (0x00000000) +#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING (0x00000002) + +#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING (0x00000001) +#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING (0x00000000) + +/* defines for IOC Page 8 IRVolumeMappingFlags */ +#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE (0x00000003) +#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING (0x00000000) +#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING (0x00000001) + + +/**************************************************************************** +* BIOS Config Pages +****************************************************************************/ + +/* BIOS Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_BIOS_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 BiosOptions; /* 0x04 */ + U32 IOCSettings; /* 0x08 */ + U32 Reserved1; /* 0x0C */ + U32 DeviceSettings; /* 0x10 */ + U16 NumberOfDevices; /* 0x14 */ + U16 Reserved2; /* 0x16 */ + U16 IOTimeoutBlockDevicesNonRM; /* 0x18 */ + U16 IOTimeoutSequential; /* 0x1A */ + U16 IOTimeoutOther; /* 0x1C */ + U16 IOTimeoutBlockDevicesRM; /* 0x1E */ +} MPI2_CONFIG_PAGE_BIOS_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_1, + Mpi2BiosPage1_t, MPI2_POINTER pMpi2BiosPage1_t; + +#define MPI2_BIOSPAGE1_PAGEVERSION (0x04) + +/* values for BIOS Page 1 BiosOptions field */ +#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) + +/* values for BIOS Page 1 IOCSettings field */ +#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) +#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) +#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) + +#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0) +#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000) +#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040) +#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080) + +#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030) +#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000) +#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010) +#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020) +#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030) + +#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008) + +/* values for BIOS Page 1 DeviceSettings field */ +#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING (0x00000010) +#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008) +#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004) +#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) +#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) + + +/* BIOS Page 2 */ + +typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER +{ + U32 Reserved1; /* 0x00 */ + U32 Reserved2; /* 0x04 */ + U32 Reserved3; /* 0x08 */ + U32 Reserved4; /* 0x0C */ + U32 Reserved5; /* 0x10 */ + U32 Reserved6; /* 0x14 */ +} MPI2_BOOT_DEVICE_ADAPTER_ORDER, + MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER, + Mpi2BootDeviceAdapterOrder_t, MPI2_POINTER pMpi2BootDeviceAdapterOrder_t; + +typedef struct _MPI2_BOOT_DEVICE_SAS_WWID +{ + U64 SASAddress; /* 0x00 */ + U8 LUN[8]; /* 0x08 */ + U32 Reserved1; /* 0x10 */ + U32 Reserved2; /* 0x14 */ +} MPI2_BOOT_DEVICE_SAS_WWID, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_SAS_WWID, + Mpi2BootDeviceSasWwid_t, MPI2_POINTER pMpi2BootDeviceSasWwid_t; + +typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT +{ + U64 EnclosureLogicalID; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 Reserved2; /* 0x0C */ + U16 SlotNumber; /* 0x10 */ + U16 Reserved3; /* 0x12 */ + U32 Reserved4; /* 0x14 */ +} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT, + MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT, + Mpi2BootDeviceEnclosureSlot_t, MPI2_POINTER pMpi2BootDeviceEnclosureSlot_t; + +typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME +{ + U64 DeviceName; /* 0x00 */ + U8 LUN[8]; /* 0x08 */ + U32 Reserved1; /* 0x10 */ + U32 Reserved2; /* 0x14 */ +} MPI2_BOOT_DEVICE_DEVICE_NAME, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_DEVICE_NAME, + Mpi2BootDeviceDeviceName_t, MPI2_POINTER pMpi2BootDeviceDeviceName_t; + +typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE +{ + MPI2_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder; + MPI2_BOOT_DEVICE_SAS_WWID SasWwid; + MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot; + MPI2_BOOT_DEVICE_DEVICE_NAME DeviceName; +} MPI2_BIOSPAGE2_BOOT_DEVICE, MPI2_POINTER PTR_MPI2_BIOSPAGE2_BOOT_DEVICE, + Mpi2BiosPage2BootDevice_t, MPI2_POINTER pMpi2BiosPage2BootDevice_t; + +typedef struct _MPI2_CONFIG_PAGE_BIOS_2 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Reserved2; /* 0x08 */ + U32 Reserved3; /* 0x0C */ + U32 Reserved4; /* 0x10 */ + U32 Reserved5; /* 0x14 */ + U32 Reserved6; /* 0x18 */ + U8 ReqBootDeviceForm; /* 0x1C */ + U8 Reserved7; /* 0x1D */ + U16 Reserved8; /* 0x1E */ + MPI2_BIOSPAGE2_BOOT_DEVICE RequestedBootDevice; /* 0x20 */ + U8 ReqAltBootDeviceForm; /* 0x38 */ + U8 Reserved9; /* 0x39 */ + U16 Reserved10; /* 0x3A */ + MPI2_BIOSPAGE2_BOOT_DEVICE RequestedAltBootDevice; /* 0x3C */ + U8 CurrentBootDeviceForm; /* 0x58 */ + U8 Reserved11; /* 0x59 */ + U16 Reserved12; /* 0x5A */ + MPI2_BIOSPAGE2_BOOT_DEVICE CurrentBootDevice; /* 0x58 */ +} MPI2_CONFIG_PAGE_BIOS_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_2, + Mpi2BiosPage2_t, MPI2_POINTER pMpi2BiosPage2_t; + +#define MPI2_BIOSPAGE2_PAGEVERSION (0x04) + +/* values for BIOS Page 2 BootDeviceForm fields */ +#define MPI2_BIOSPAGE2_FORM_MASK (0x0F) +#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED (0x00) +#define MPI2_BIOSPAGE2_FORM_SAS_WWID (0x05) +#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06) +#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME (0x07) + + +/* BIOS Page 3 */ + +typedef struct _MPI2_ADAPTER_INFO +{ + U8 PciBusNumber; /* 0x00 */ + U8 PciDeviceAndFunctionNumber; /* 0x01 */ + U16 AdapterFlags; /* 0x02 */ +} MPI2_ADAPTER_INFO, MPI2_POINTER PTR_MPI2_ADAPTER_INFO, + Mpi2AdapterInfo_t, MPI2_POINTER pMpi2AdapterInfo_t; + +#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001) +#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002) + +typedef struct _MPI2_CONFIG_PAGE_BIOS_3 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 GlobalFlags; /* 0x04 */ + U32 BiosVersion; /* 0x08 */ + MPI2_ADAPTER_INFO AdapterOrder[4]; /* 0x0C */ + U32 Reserved1; /* 0x1C */ +} MPI2_CONFIG_PAGE_BIOS_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_3, + Mpi2BiosPage3_t, MPI2_POINTER pMpi2BiosPage3_t; + +#define MPI2_BIOSPAGE3_PAGEVERSION (0x00) + +/* values for BIOS Page 3 GlobalFlags */ +#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002) +#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE (0x00000004) +#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE (0x00000010) + +#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0) +#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000) +#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY (0x00000020) +#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040) + + +/* BIOS Page 4 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhys at runtime. + */ +#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES +#define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1) +#endif + +typedef struct _MPI2_BIOS4_ENTRY +{ + U64 ReassignmentWWID; /* 0x00 */ + U64 ReassignmentDeviceName; /* 0x08 */ +} MPI2_BIOS4_ENTRY, MPI2_POINTER PTR_MPI2_BIOS4_ENTRY, + Mpi2MBios4Entry_t, MPI2_POINTER pMpi2Bios4Entry_t; + +typedef struct _MPI2_CONFIG_PAGE_BIOS_4 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 NumPhys; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + MPI2_BIOS4_ENTRY Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /* 0x08 */ +} MPI2_CONFIG_PAGE_BIOS_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_4, + Mpi2BiosPage4_t, MPI2_POINTER pMpi2BiosPage4_t; + +#define MPI2_BIOSPAGE4_PAGEVERSION (0x01) + + +/**************************************************************************** +* RAID Volume Config Pages +****************************************************************************/ + +/* RAID Volume Page 0 */ + +typedef struct _MPI2_RAIDVOL0_PHYS_DISK +{ + U8 RAIDSetNum; /* 0x00 */ + U8 PhysDiskMap; /* 0x01 */ + U8 PhysDiskNum; /* 0x02 */ + U8 Reserved; /* 0x03 */ +} MPI2_RAIDVOL0_PHYS_DISK, MPI2_POINTER PTR_MPI2_RAIDVOL0_PHYS_DISK, + Mpi2RaidVol0PhysDisk_t, MPI2_POINTER pMpi2RaidVol0PhysDisk_t; + +/* defines for the PhysDiskMap field */ +#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY (0x01) +#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY (0x02) + +typedef struct _MPI2_RAIDVOL0_SETTINGS +{ + U16 Settings; /* 0x00 */ + U8 HotSparePool; /* 0x01 */ + U8 Reserved; /* 0x02 */ +} MPI2_RAIDVOL0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDVOL0_SETTINGS, + Mpi2RaidVol0Settings_t, MPI2_POINTER pMpi2RaidVol0Settings_t; + +/* RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */ +#define MPI2_RAID_HOT_SPARE_POOL_0 (0x01) +#define MPI2_RAID_HOT_SPARE_POOL_1 (0x02) +#define MPI2_RAID_HOT_SPARE_POOL_2 (0x04) +#define MPI2_RAID_HOT_SPARE_POOL_3 (0x08) +#define MPI2_RAID_HOT_SPARE_POOL_4 (0x10) +#define MPI2_RAID_HOT_SPARE_POOL_5 (0x20) +#define MPI2_RAID_HOT_SPARE_POOL_6 (0x40) +#define MPI2_RAID_HOT_SPARE_POOL_7 (0x80) + +/* RAID Volume Page 0 VolumeSettings defines */ +#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0008) +#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004) + +#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING (0x0003) +#define MPI2_RAIDVOL0_SETTING_UNCHANGED (0x0000) +#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING (0x0001) +#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhysDisks at runtime. + */ +#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX +#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U16 DevHandle; /* 0x04 */ + U8 VolumeState; /* 0x06 */ + U8 VolumeType; /* 0x07 */ + U32 VolumeStatusFlags; /* 0x08 */ + MPI2_RAIDVOL0_SETTINGS VolumeSettings; /* 0x0C */ + U64 MaxLBA; /* 0x10 */ + U32 StripeSize; /* 0x18 */ + U16 BlockSize; /* 0x1C */ + U16 Reserved1; /* 0x1E */ + U8 SupportedPhysDisks; /* 0x20 */ + U8 ResyncRate; /* 0x21 */ + U16 DataScrubDuration; /* 0x22 */ + U8 NumPhysDisks; /* 0x24 */ + U8 Reserved2; /* 0x25 */ + U8 Reserved3; /* 0x26 */ + U8 InactiveStatus; /* 0x27 */ + MPI2_RAIDVOL0_PHYS_DISK PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /* 0x28 */ +} MPI2_CONFIG_PAGE_RAID_VOL_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_0, + Mpi2RaidVolPage0_t, MPI2_POINTER pMpi2RaidVolPage0_t; + +#define MPI2_RAIDVOLPAGE0_PAGEVERSION (0x0A) + +/* values for RAID VolumeState */ +#define MPI2_RAID_VOL_STATE_MISSING (0x00) +#define MPI2_RAID_VOL_STATE_FAILED (0x01) +#define MPI2_RAID_VOL_STATE_INITIALIZING (0x02) +#define MPI2_RAID_VOL_STATE_ONLINE (0x03) +#define MPI2_RAID_VOL_STATE_DEGRADED (0x04) +#define MPI2_RAID_VOL_STATE_OPTIMAL (0x05) + +/* values for RAID VolumeType */ +#define MPI2_RAID_VOL_TYPE_RAID0 (0x00) +#define MPI2_RAID_VOL_TYPE_RAID1E (0x01) +#define MPI2_RAID_VOL_TYPE_RAID1 (0x02) +#define MPI2_RAID_VOL_TYPE_RAID10 (0x05) +#define MPI2_RAID_VOL_TYPE_UNKNOWN (0xFF) + +/* values for RAID Volume Page 0 VolumeStatusFlags field */ +#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC (0x02000000) +#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING (0x01000000) +#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING (0x00800000) +#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING (0x00400000) +#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT (0x00200000) +#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB (0x00100000) +#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK (0x00080000) +#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000) +#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000) +#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000) +#define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT (0x00000080) +#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040) +#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020) +#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000) +#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR (0x00000010) +#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x00000008) +#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x00000004) +#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED (0x00000002) +#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED (0x00000001) + +/* values for RAID Volume Page 0 SupportedPhysDisks field */ +#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS (0x08) +#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS (0x04) +#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL (0x02) +#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL (0x01) + +/* values for RAID Volume Page 0 InactiveStatus field */ +#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00) +#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01) +#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02) +#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03) +#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04) +#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05) +#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06) + + +/* RAID Volume Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U16 DevHandle; /* 0x04 */ + U16 Reserved0; /* 0x06 */ + U8 GUID[24]; /* 0x08 */ + U8 Name[16]; /* 0x20 */ + U64 WWID; /* 0x30 */ + U32 Reserved1; /* 0x38 */ + U32 Reserved2; /* 0x3C */ +} MPI2_CONFIG_PAGE_RAID_VOL_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_1, + Mpi2RaidVolPage1_t, MPI2_POINTER pMpi2RaidVolPage1_t; + +#define MPI2_RAIDVOLPAGE1_PAGEVERSION (0x03) + + +/**************************************************************************** +* RAID Physical Disk Config Pages +****************************************************************************/ + +/* RAID Physical Disk Page 0 */ + +typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS +{ + U16 Reserved1; /* 0x00 */ + U8 HotSparePool; /* 0x02 */ + U8 Reserved2; /* 0x03 */ +} MPI2_RAIDPHYSDISK0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_SETTINGS, + Mpi2RaidPhysDisk0Settings_t, MPI2_POINTER pMpi2RaidPhysDisk0Settings_t; + +/* use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */ + +typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA +{ + U8 VendorID[8]; /* 0x00 */ + U8 ProductID[16]; /* 0x08 */ + U8 ProductRevLevel[4]; /* 0x18 */ + U8 SerialNum[32]; /* 0x1C */ +} MPI2_RAIDPHYSDISK0_INQUIRY_DATA, + MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA, + Mpi2RaidPhysDisk0InquiryData_t, MPI2_POINTER pMpi2RaidPhysDisk0InquiryData_t; + +typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U16 DevHandle; /* 0x04 */ + U8 Reserved1; /* 0x06 */ + U8 PhysDiskNum; /* 0x07 */ + MPI2_RAIDPHYSDISK0_SETTINGS PhysDiskSettings; /* 0x08 */ + U32 Reserved2; /* 0x0C */ + MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData; /* 0x10 */ + U32 Reserved3; /* 0x4C */ + U8 PhysDiskState; /* 0x50 */ + U8 OfflineReason; /* 0x51 */ + U8 IncompatibleReason; /* 0x52 */ + U8 PhysDiskAttributes; /* 0x53 */ + U32 PhysDiskStatusFlags; /* 0x54 */ + U64 DeviceMaxLBA; /* 0x58 */ + U64 HostMaxLBA; /* 0x60 */ + U64 CoercedMaxLBA; /* 0x68 */ + U16 BlockSize; /* 0x70 */ + U16 Reserved5; /* 0x72 */ + U32 Reserved6; /* 0x74 */ +} MPI2_CONFIG_PAGE_RD_PDISK_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_0, + Mpi2RaidPhysDiskPage0_t, MPI2_POINTER pMpi2RaidPhysDiskPage0_t; + +#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION (0x05) + +/* PhysDiskState defines */ +#define MPI2_RAID_PD_STATE_NOT_CONFIGURED (0x00) +#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE (0x01) +#define MPI2_RAID_PD_STATE_OFFLINE (0x02) +#define MPI2_RAID_PD_STATE_ONLINE (0x03) +#define MPI2_RAID_PD_STATE_HOT_SPARE (0x04) +#define MPI2_RAID_PD_STATE_DEGRADED (0x05) +#define MPI2_RAID_PD_STATE_REBUILDING (0x06) +#define MPI2_RAID_PD_STATE_OPTIMAL (0x07) + +/* OfflineReason defines */ +#define MPI2_PHYSDISK0_ONLINE (0x00) +#define MPI2_PHYSDISK0_OFFLINE_MISSING (0x01) +#define MPI2_PHYSDISK0_OFFLINE_FAILED (0x03) +#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING (0x04) +#define MPI2_PHYSDISK0_OFFLINE_REQUESTED (0x05) +#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED (0x06) +#define MPI2_PHYSDISK0_OFFLINE_OTHER (0xFF) + +/* IncompatibleReason defines */ +#define MPI2_PHYSDISK0_COMPATIBLE (0x00) +#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL (0x01) +#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE (0x02) +#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03) +#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04) +#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05) +#define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE (0x06) +#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF) + +/* PhysDiskAttributes defines */ +#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK (0x0C) +#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08) +#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04) + +#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK (0x03) +#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02) +#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01) + +/* PhysDiskStatusFlags defines */ +#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED (0x00000040) +#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET (0x00000020) +#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED (0x00000010) +#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00000000) +#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008) +#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x00000004) +#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED (0x00000002) +#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x00000001) + + +/* RAID Physical Disk Page 1 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhysDiskPaths at runtime. + */ +#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX +#define MPI2_RAID_PHYS_DISK1_PATH_MAX (1) +#endif + +typedef struct _MPI2_RAIDPHYSDISK1_PATH +{ + U16 DevHandle; /* 0x00 */ + U16 Reserved1; /* 0x02 */ + U64 WWID; /* 0x04 */ + U64 OwnerWWID; /* 0x0C */ + U8 OwnerIdentifier; /* 0x14 */ + U8 Reserved2; /* 0x15 */ + U16 Flags; /* 0x16 */ +} MPI2_RAIDPHYSDISK1_PATH, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK1_PATH, + Mpi2RaidPhysDisk1Path_t, MPI2_POINTER pMpi2RaidPhysDisk1Path_t; + +/* RAID Physical Disk Page 1 Physical Disk Path Flags field defines */ +#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY (0x0004) +#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN (0x0002) +#define MPI2_RAID_PHYSDISK1_FLAG_INVALID (0x0001) + +typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 NumPhysDiskPaths; /* 0x04 */ + U8 PhysDiskNum; /* 0x05 */ + U16 Reserved1; /* 0x06 */ + U32 Reserved2; /* 0x08 */ + MPI2_RAIDPHYSDISK1_PATH PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/* 0x0C */ +} MPI2_CONFIG_PAGE_RD_PDISK_1, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_1, + Mpi2RaidPhysDiskPage1_t, MPI2_POINTER pMpi2RaidPhysDiskPage1_t; + +#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION (0x02) + + +/**************************************************************************** +* values for fields used by several types of SAS Config Pages +****************************************************************************/ + +/* values for NegotiatedLinkRates fields */ +#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL (0xF0) +#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL (4) +#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL (0x0F) +/* link rates used for Negotiated Physical and Logical Link Rate */ +#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00) +#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01) +#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02) +#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03) +#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04) +#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05) +#define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY (0x06) +#define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08) +#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09) +#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A) +#define MPI25_SAS_NEG_LINK_RATE_12_0 (0x0B) + + +/* values for AttachedPhyInfo fields */ +#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040) +#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020) +#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010) + +#define MPI2_SAS_APHYINFO_REASON_MASK (0x0000000F) +#define MPI2_SAS_APHYINFO_REASON_UNKNOWN (0x00000000) +#define MPI2_SAS_APHYINFO_REASON_POWER_ON (0x00000001) +#define MPI2_SAS_APHYINFO_REASON_HARD_RESET (0x00000002) +#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003) +#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004) +#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005) +#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006) +#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007) +#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008) + + +/* values for PhyInfo fields */ +#define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000) + +#define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK (0x18000000) +#define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION (27) +#define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE (0x00000000) +#define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL (0x08000000) +#define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER (0x10000000) + +#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS (0x04000000) +#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT (0x02000000) +#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS (0x01000000) +#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000) +#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS (0x00200000) +#define MPI2_SAS_PHYINFO_ZONING_ENABLED (0x00100000) + +#define MPI2_SAS_PHYINFO_REASON_MASK (0x000F0000) +#define MPI2_SAS_PHYINFO_REASON_UNKNOWN (0x00000000) +#define MPI2_SAS_PHYINFO_REASON_POWER_ON (0x00010000) +#define MPI2_SAS_PHYINFO_REASON_HARD_RESET (0x00020000) +#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000) +#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000) +#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000) +#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000) +#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000) +#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000) + +#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED (0x00008000) +#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000) +#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000) +#define MPI2_SAS_PHYINFO_VIRTUAL_PHY (0x00001000) + +#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00) +#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8) + +#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0) +#define MPI2_SAS_PHYINFO_DIRECT_ROUTING (0x00000000) +#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010) +#define MPI2_SAS_PHYINFO_TABLE_ROUTING (0x00000020) + + +/* values for SAS ProgrammedLinkRate fields */ +#define MPI2_SAS_PRATE_MAX_RATE_MASK (0xF0) +#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00) +#define MPI2_SAS_PRATE_MAX_RATE_1_5 (0x80) +#define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90) +#define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0) +#define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F) +#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00) +#define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08) +#define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09) +#define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A) +#define MPI25_SAS_PRATE_MIN_RATE_12_0 (0x0B) + + +/* values for SAS HwLinkRate fields */ +#define MPI2_SAS_HWRATE_MAX_RATE_MASK (0xF0) +#define MPI2_SAS_HWRATE_MAX_RATE_1_5 (0x80) +#define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90) +#define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0) +#define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F) +#define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08) +#define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09) +#define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A) +#define MPI25_SAS_HWRATE_MIN_RATE_12_0 (0x0B) + + + +/**************************************************************************** +* SAS IO Unit Config Pages +****************************************************************************/ + +/* SAS IO Unit Page 0 */ + +typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA +{ + U8 Port; /* 0x00 */ + U8 PortFlags; /* 0x01 */ + U8 PhyFlags; /* 0x02 */ + U8 NegotiatedLinkRate; /* 0x03 */ + U32 ControllerPhyDeviceInfo;/* 0x04 */ + U16 AttachedDevHandle; /* 0x08 */ + U16 ControllerDevHandle; /* 0x0A */ + U32 DiscoveryStatus; /* 0x0C */ + U32 Reserved; /* 0x10 */ +} MPI2_SAS_IO_UNIT0_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT0_PHY_DATA, + Mpi2SasIOUnit0PhyData_t, MPI2_POINTER pMpi2SasIOUnit0PhyData_t; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhys at runtime. + */ +#ifndef MPI2_SAS_IOUNIT0_PHY_MAX +#define MPI2_SAS_IOUNIT0_PHY_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U8 NumPhys; /* 0x0C */ + U8 Reserved2; /* 0x0D */ + U16 Reserved3; /* 0x0E */ + MPI2_SAS_IO_UNIT0_PHY_DATA PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /* 0x10 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0, + Mpi2SasIOUnitPage0_t, MPI2_POINTER pMpi2SasIOUnitPage0_t; + +#define MPI2_SASIOUNITPAGE0_PAGEVERSION (0x05) + +/* values for SAS IO Unit Page 0 PortFlags */ +#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS (0x08) +#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01) + +/* values for SAS IO Unit Page 0 PhyFlags */ +#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10) +#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) + +/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ + +/* see mpi2_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */ + +/* values for SAS IO Unit Page 0 DiscoveryStatus */ +#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) +#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED (0x40000000) +#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED (0x20000000) +#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) +#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR (0x08000000) +#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) +#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) +#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN (0x00002000) +#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) +#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800) +#define MPI2_SASIOUNIT0_DS_TABLE_LINK (0x00000400) +#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR (0x00000100) +#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT (0x00000010) +#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS (0x00000004) +#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED (0x00000001) + + +/* SAS IO Unit Page 1 */ + +typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA +{ + U8 Port; /* 0x00 */ + U8 PortFlags; /* 0x01 */ + U8 PhyFlags; /* 0x02 */ + U8 MaxMinLinkRate; /* 0x03 */ + U32 ControllerPhyDeviceInfo; /* 0x04 */ + U16 MaxTargetPortConnectTime; /* 0x08 */ + U16 Reserved1; /* 0x0A */ +} MPI2_SAS_IO_UNIT1_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT1_PHY_DATA, + Mpi2SasIOUnit1PhyData_t, MPI2_POINTER pMpi2SasIOUnit1PhyData_t; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhys at runtime. + */ +#ifndef MPI2_SAS_IOUNIT1_PHY_MAX +#define MPI2_SAS_IOUNIT1_PHY_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 ControlFlags; /* 0x08 */ + U16 SASNarrowMaxQueueDepth; /* 0x0A */ + U16 AdditionalControlFlags; /* 0x0C */ + U16 SASWideMaxQueueDepth; /* 0x0E */ + U8 NumPhys; /* 0x10 */ + U8 SATAMaxQDepth; /* 0x11 */ + U8 ReportDeviceMissingDelay; /* 0x12 */ + U8 IODeviceMissingDelay; /* 0x13 */ + MPI2_SAS_IO_UNIT1_PHY_DATA PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /* 0x14 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_1, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1, + Mpi2SasIOUnitPage1_t, MPI2_POINTER pMpi2SasIOUnitPage1_t; + +#define MPI2_SASIOUNITPAGE1_PAGEVERSION (0x09) + +/* values for SAS IO Unit Page 1 ControlFlags */ +#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) +#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) +#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) +#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) + +#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) +#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) +#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x0) +#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x1) +#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x2) + +#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) +#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) +#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) +#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) +#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008) +#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) +#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) +#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) + +/* values for SAS IO Unit Page 1 AdditionalControlFlags */ +#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080) +#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) +#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020) +#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010) +#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008) +#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004) +#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002) +#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) + +/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */ +#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F) +#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16 (0x80) + +/* values for SAS IO Unit Page 1 PortFlags */ +#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) + +/* values for SAS IO Unit Page 1 PhyFlags */ +#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10) +#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) + +/* values for SAS IO Unit Page 1 MaxMinLinkRate */ +#define MPI2_SASIOUNIT1_MAX_RATE_MASK (0xF0) +#define MPI2_SASIOUNIT1_MAX_RATE_1_5 (0x80) +#define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90) +#define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0) +#define MPI25_SASIOUNIT1_MAX_RATE_12_0 (0xB0) +#define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F) +#define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08) +#define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09) +#define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A) +#define MPI25_SASIOUNIT1_MIN_RATE_12_0 (0x0B) + +/* see mpi2_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ + + +/* SAS IO Unit Page 4 */ + +typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP +{ + U8 MaxTargetSpinup; /* 0x00 */ + U8 SpinupDelay; /* 0x01 */ + U16 Reserved1; /* 0x02 */ +} MPI2_SAS_IOUNIT4_SPINUP_GROUP, MPI2_POINTER PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP, + Mpi2SasIOUnit4SpinupGroup_t, MPI2_POINTER pMpi2SasIOUnit4SpinupGroup_t; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhys at runtime. + */ +#ifndef MPI2_SAS_IOUNIT4_PHY_MAX +#define MPI2_SAS_IOUNIT4_PHY_MAX (4) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + MPI2_SAS_IOUNIT4_SPINUP_GROUP SpinupGroupParameters[4]; /* 0x08 */ + U32 Reserved1; /* 0x18 */ + U32 Reserved2; /* 0x1C */ + U32 Reserved3; /* 0x20 */ + U8 BootDeviceWaitTime; /* 0x24 */ + U8 Reserved4; /* 0x25 */ + U16 Reserved5; /* 0x26 */ + U8 NumPhys; /* 0x28 */ + U8 PEInitialSpinupDelay; /* 0x29 */ + U8 PEReplyDelay; /* 0x2A */ + U8 Flags; /* 0x2B */ + U8 PHY[MPI2_SAS_IOUNIT4_PHY_MAX]; /* 0x2C */ +} MPI2_CONFIG_PAGE_SASIOUNIT_4, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4, + Mpi2SasIOUnitPage4_t, MPI2_POINTER pMpi2SasIOUnitPage4_t; + +#define MPI2_SASIOUNITPAGE4_PAGEVERSION (0x02) + +/* defines for Flags field */ +#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE (0x01) + +/* defines for PHY field */ +#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK (0x03) + + +/* SAS IO Unit Page 5 */ + +typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS +{ + U8 ControlFlags; /* 0x00 */ + U8 PortWidthModGroup; /* 0x01 */ + U16 InactivityTimerExponent; /* 0x02 */ + U8 SATAPartialTimeout; /* 0x04 */ + U8 Reserved2; /* 0x05 */ + U8 SATASlumberTimeout; /* 0x06 */ + U8 Reserved3; /* 0x07 */ + U8 SASPartialTimeout; /* 0x08 */ + U8 Reserved4; /* 0x09 */ + U8 SASSlumberTimeout; /* 0x0A */ + U8 Reserved5; /* 0x0B */ +} MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS, + MPI2_POINTER PTR_MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS, + Mpi2SasIOUnit5PhyPmSettings_t, MPI2_POINTER pMpi2SasIOUnit5PhyPmSettings_t; + +/* defines for ControlFlags field */ +#define MPI2_SASIOUNIT5_CONTROL_SAS_SLUMBER_ENABLE (0x08) +#define MPI2_SASIOUNIT5_CONTROL_SAS_PARTIAL_ENABLE (0x04) +#define MPI2_SASIOUNIT5_CONTROL_SATA_SLUMBER_ENABLE (0x02) +#define MPI2_SASIOUNIT5_CONTROL_SATA_PARTIAL_ENABLE (0x01) + +/* defines for PortWidthModeGroup field */ +#define MPI2_SASIOUNIT5_PWMG_DISABLE (0xFF) + +/* defines for InactivityTimerExponent field */ +#define MPI2_SASIOUNIT5_ITE_MASK_SAS_SLUMBER (0x7000) +#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_SLUMBER (12) +#define MPI2_SASIOUNIT5_ITE_MASK_SAS_PARTIAL (0x0700) +#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_PARTIAL (8) +#define MPI2_SASIOUNIT5_ITE_MASK_SATA_SLUMBER (0x0070) +#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_SLUMBER (4) +#define MPI2_SASIOUNIT5_ITE_MASK_SATA_PARTIAL (0x0007) +#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_PARTIAL (0) + +#define MPI2_SASIOUNIT5_ITE_TEN_SECONDS (7) +#define MPI2_SASIOUNIT5_ITE_ONE_SECOND (6) +#define MPI2_SASIOUNIT5_ITE_HUNDRED_MILLISECONDS (5) +#define MPI2_SASIOUNIT5_ITE_TEN_MILLISECONDS (4) +#define MPI2_SASIOUNIT5_ITE_ONE_MILLISECOND (3) +#define MPI2_SASIOUNIT5_ITE_HUNDRED_MICROSECONDS (2) +#define MPI2_SASIOUNIT5_ITE_TEN_MICROSECONDS (1) +#define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND (0) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhys at runtime. + */ +#ifndef MPI2_SAS_IOUNIT5_PHY_MAX +#define MPI2_SAS_IOUNIT5_PHY_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 NumPhys; /* 0x08 */ + U8 Reserved1; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U32 Reserved3; /* 0x0C */ + MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS SASPhyPowerManagementSettings[MPI2_SAS_IOUNIT5_PHY_MAX]; /* 0x10 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_5, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5, + Mpi2SasIOUnitPage5_t, MPI2_POINTER pMpi2SasIOUnitPage5_t; + +#define MPI2_SASIOUNITPAGE5_PAGEVERSION (0x01) + + +/* SAS IO Unit Page 6 */ + +typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS +{ + U8 CurrentStatus; /* 0x00 */ + U8 CurrentModulation; /* 0x01 */ + U8 CurrentUtilization; /* 0x02 */ + U8 Reserved1; /* 0x03 */ + U32 Reserved2; /* 0x04 */ +} MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS, + MPI2_POINTER PTR_MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS, + Mpi2SasIOUnit6PortWidthModGroupStatus_t, + MPI2_POINTER pMpi2SasIOUnit6PortWidthModGroupStatus_t; + +/* defines for CurrentStatus field */ +#define MPI2_SASIOUNIT6_STATUS_UNAVAILABLE (0x00) +#define MPI2_SASIOUNIT6_STATUS_UNCONFIGURED (0x01) +#define MPI2_SASIOUNIT6_STATUS_INVALID_CONFIG (0x02) +#define MPI2_SASIOUNIT6_STATUS_LINK_DOWN (0x03) +#define MPI2_SASIOUNIT6_STATUS_OBSERVATION_ONLY (0x04) +#define MPI2_SASIOUNIT6_STATUS_INACTIVE (0x05) +#define MPI2_SASIOUNIT6_STATUS_ACTIVE_IOUNIT (0x06) +#define MPI2_SASIOUNIT6_STATUS_ACTIVE_HOST (0x07) + +/* defines for CurrentModulation field */ +#define MPI2_SASIOUNIT6_MODULATION_25_PERCENT (0x00) +#define MPI2_SASIOUNIT6_MODULATION_50_PERCENT (0x01) +#define MPI2_SASIOUNIT6_MODULATION_75_PERCENT (0x02) +#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT (0x03) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumGroups at runtime. + */ +#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX +#define MPI2_SAS_IOUNIT6_GROUP_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 Reserved2; /* 0x0C */ + U8 NumGroups; /* 0x10 */ + U8 Reserved3; /* 0x11 */ + U16 Reserved4; /* 0x12 */ + MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS + PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /* 0x14 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_6, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6, + Mpi2SasIOUnitPage6_t, MPI2_POINTER pMpi2SasIOUnitPage6_t; + +#define MPI2_SASIOUNITPAGE6_PAGEVERSION (0x00) + + +/* SAS IO Unit Page 7 */ + +typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS +{ + U8 Flags; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U8 Threshold75Pct; /* 0x04 */ + U8 Threshold50Pct; /* 0x05 */ + U8 Threshold25Pct; /* 0x06 */ + U8 Reserved3; /* 0x07 */ +} MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS, + MPI2_POINTER PTR_MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS, + Mpi2SasIOUnit7PortWidthModGroupSettings_t, + MPI2_POINTER pMpi2SasIOUnit7PortWidthModGroupSettings_t; + +/* defines for Flags field */ +#define MPI2_SASIOUNIT7_FLAGS_ENABLE_PORT_WIDTH_MODULATION (0x01) + + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumGroups at runtime. + */ +#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX +#define MPI2_SAS_IOUNIT7_GROUP_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 SamplingInterval; /* 0x08 */ + U8 WindowLength; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U32 Reserved2; /* 0x0C */ + U32 Reserved3; /* 0x10 */ + U8 NumGroups; /* 0x14 */ + U8 Reserved4; /* 0x15 */ + U16 Reserved5; /* 0x16 */ + MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS + PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX]; /* 0x18 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_7, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7, + Mpi2SasIOUnitPage7_t, MPI2_POINTER pMpi2SasIOUnitPage7_t; + +#define MPI2_SASIOUNITPAGE7_PAGEVERSION (0x00) + + +/* SAS IO Unit Page 8 */ + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 PowerManagementCapabilities; /* 0x0C */ + U8 TxRxSleepStatus; /* 0x10 */ /* reserved in MPI 2.0 */ + U8 Reserved2; /* 0x11 */ + U16 Reserved3; /* 0x12 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_8, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_8, + Mpi2SasIOUnitPage8_t, MPI2_POINTER pMpi2SasIOUnitPage8_t; + +#define MPI2_SASIOUNITPAGE8_PAGEVERSION (0x00) + +/* defines for PowerManagementCapabilities field */ +#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD (0x00001000) +#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE (0x00000800) +#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE (0x00000400) +#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE (0x00000200) +#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE (0x00000100) +#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD (0x00000010) +#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE (0x00000008) +#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE (0x00000004) +#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE (0x00000002) +#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE (0x00000001) + +/* defines for TxRxSleepStatus field */ +#define MPI25_SASIOUNIT8_TXRXSLEEP_UNSUPPORTED (0x00) +#define MPI25_SASIOUNIT8_TXRXSLEEP_DISENGAGED (0x01) +#define MPI25_SASIOUNIT8_TXRXSLEEP_ACTIVE (0x02) +#define MPI25_SASIOUNIT8_TXRXSLEEP_SHUTDOWN (0x03) + + + +/* SAS IO Unit Page 16 */ + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT16 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U64 TimeStamp; /* 0x08 */ + U32 Reserved1; /* 0x10 */ + U32 Reserved2; /* 0x14 */ + U32 FastPathPendedRequests; /* 0x18 */ + U32 FastPathUnPendedRequests; /* 0x1C */ + U32 FastPathHostRequestStarts; /* 0x20 */ + U32 FastPathFirmwareRequestStarts; /* 0x24 */ + U32 FastPathHostCompletions; /* 0x28 */ + U32 FastPathFirmwareCompletions; /* 0x2C */ + U32 NonFastPathRequestStarts; /* 0x30 */ + U32 NonFastPathHostCompletions; /* 0x30 */ +} MPI2_CONFIG_PAGE_SASIOUNIT16, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT16, + Mpi2SasIOUnitPage16_t, MPI2_POINTER pMpi2SasIOUnitPage16_t; + +#define MPI2_SASIOUNITPAGE16_PAGEVERSION (0x00) + + +/**************************************************************************** +* SAS Expander Config Pages +****************************************************************************/ + +/* SAS Expander Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 PhysicalPort; /* 0x08 */ + U8 ReportGenLength; /* 0x09 */ + U16 EnclosureHandle; /* 0x0A */ + U64 SASAddress; /* 0x0C */ + U32 DiscoveryStatus; /* 0x14 */ + U16 DevHandle; /* 0x18 */ + U16 ParentDevHandle; /* 0x1A */ + U16 ExpanderChangeCount; /* 0x1C */ + U16 ExpanderRouteIndexes; /* 0x1E */ + U8 NumPhys; /* 0x20 */ + U8 SASLevel; /* 0x21 */ + U16 Flags; /* 0x22 */ + U16 STPBusInactivityTimeLimit; /* 0x24 */ + U16 STPMaxConnectTimeLimit; /* 0x26 */ + U16 STP_SMP_NexusLossTime; /* 0x28 */ + U16 MaxNumRoutedSasAddresses; /* 0x2A */ + U64 ActiveZoneManagerSASAddress;/* 0x2C */ + U16 ZoneLockInactivityLimit; /* 0x34 */ + U16 Reserved1; /* 0x36 */ + U8 TimeToReducedFunc; /* 0x38 */ + U8 InitialTimeToReducedFunc; /* 0x39 */ + U8 MaxReducedFuncTime; /* 0x3A */ + U8 Reserved2; /* 0x3B */ +} MPI2_CONFIG_PAGE_EXPANDER_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_0, + Mpi2ExpanderPage0_t, MPI2_POINTER pMpi2ExpanderPage0_t; + +#define MPI2_SASEXPANDER0_PAGEVERSION (0x06) + +/* values for SAS Expander Page 0 DiscoveryStatus field */ +#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) +#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED (0x40000000) +#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED (0x20000000) +#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) +#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR (0x08000000) +#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) +#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) +#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN (0x00002000) +#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) +#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800) +#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400) +#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100) +#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010) +#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004) +#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) + +/* values for SAS Expander Page 0 Flags field */ +#define MPI2_SAS_EXPANDER0_FLAGS_REDUCED_FUNCTIONALITY (0x2000) +#define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000) +#define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800) +#define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400) +#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT (0x0200) +#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING (0x0100) +#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080) +#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010) +#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG (0x0004) +#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002) +#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001) + + +/* SAS Expander Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 PhysicalPort; /* 0x08 */ + U8 Reserved1; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U8 NumPhys; /* 0x0C */ + U8 Phy; /* 0x0D */ + U16 NumTableEntriesProgrammed; /* 0x0E */ + U8 ProgrammedLinkRate; /* 0x10 */ + U8 HwLinkRate; /* 0x11 */ + U16 AttachedDevHandle; /* 0x12 */ + U32 PhyInfo; /* 0x14 */ + U32 AttachedDeviceInfo; /* 0x18 */ + U16 ExpanderDevHandle; /* 0x1C */ + U8 ChangeCount; /* 0x1E */ + U8 NegotiatedLinkRate; /* 0x1F */ + U8 PhyIdentifier; /* 0x20 */ + U8 AttachedPhyIdentifier; /* 0x21 */ + U8 Reserved3; /* 0x22 */ + U8 DiscoveryInfo; /* 0x23 */ + U32 AttachedPhyInfo; /* 0x24 */ + U8 ZoneGroup; /* 0x28 */ + U8 SelfConfigStatus; /* 0x29 */ + U16 Reserved4; /* 0x2A */ +} MPI2_CONFIG_PAGE_EXPANDER_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_1, + Mpi2ExpanderPage1_t, MPI2_POINTER pMpi2ExpanderPage1_t; + +#define MPI2_SASEXPANDER1_PAGEVERSION (0x02) + +/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ + +/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ + +/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */ + +/* see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines used for the AttachedDeviceInfo field */ + +/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ + +/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ + +/* values for SAS Expander Page 1 DiscoveryInfo field */ +#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04) +#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) +#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) + + +/**************************************************************************** +* SAS Device Config Pages +****************************************************************************/ + +/* SAS Device Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 Slot; /* 0x08 */ + U16 EnclosureHandle; /* 0x0A */ + U64 SASAddress; /* 0x0C */ + U16 ParentDevHandle; /* 0x14 */ + U8 PhyNum; /* 0x16 */ + U8 AccessStatus; /* 0x17 */ + U16 DevHandle; /* 0x18 */ + U8 AttachedPhyIdentifier; /* 0x1A */ + U8 ZoneGroup; /* 0x1B */ + U32 DeviceInfo; /* 0x1C */ + U16 Flags; /* 0x20 */ + U8 PhysicalPort; /* 0x22 */ + U8 MaxPortConnections; /* 0x23 */ + U64 DeviceName; /* 0x24 */ + U8 PortGroups; /* 0x2C */ + U8 DmaGroup; /* 0x2D */ + U8 ControlGroup; /* 0x2E */ + U8 Reserved1; /* 0x2F */ + U32 Reserved2; /* 0x30 */ + U32 Reserved3; /* 0x34 */ +} MPI2_CONFIG_PAGE_SAS_DEV_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_0, + Mpi2SasDevicePage0_t, MPI2_POINTER pMpi2SasDevicePage0_t; + +#define MPI2_SASDEVICE0_PAGEVERSION (0x08) + +/* values for SAS Device Page 0 AccessStatus field */ +#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) +#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) +#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) +#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03) +#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04) +#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x05) +#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x06) +#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x07) +/* specific values for SATA Init failures */ +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F) + +/* see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */ + +/* values for SAS Device Page 0 Flags field */ +#define MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH (0x4000) +#define MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE (0x2000) +#define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE (0x1000) +#define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE (0x0800) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) +#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) +#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) +#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) + + +/* SAS Device Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U64 SASAddress; /* 0x0C */ + U32 Reserved2; /* 0x14 */ + U16 DevHandle; /* 0x18 */ + U16 Reserved3; /* 0x1A */ + U8 InitialRegDeviceFIS[20];/* 0x1C */ +} MPI2_CONFIG_PAGE_SAS_DEV_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_1, + Mpi2SasDevicePage1_t, MPI2_POINTER pMpi2SasDevicePage1_t; + +#define MPI2_SASDEVICE1_PAGEVERSION (0x01) + + +/**************************************************************************** +* SAS PHY Config Pages +****************************************************************************/ + +/* SAS PHY Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 OwnerDevHandle; /* 0x08 */ + U16 Reserved1; /* 0x0A */ + U16 AttachedDevHandle; /* 0x0C */ + U8 AttachedPhyIdentifier; /* 0x0E */ + U8 Reserved2; /* 0x0F */ + U32 AttachedPhyInfo; /* 0x10 */ + U8 ProgrammedLinkRate; /* 0x14 */ + U8 HwLinkRate; /* 0x15 */ + U8 ChangeCount; /* 0x16 */ + U8 Flags; /* 0x17 */ + U32 PhyInfo; /* 0x18 */ + U8 NegotiatedLinkRate; /* 0x1C */ + U8 Reserved3; /* 0x1D */ + U16 Reserved4; /* 0x1E */ +} MPI2_CONFIG_PAGE_SAS_PHY_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_0, + Mpi2SasPhyPage0_t, MPI2_POINTER pMpi2SasPhyPage0_t; + +#define MPI2_SASPHY0_PAGEVERSION (0x03) + +/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ + +/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ + +/* values for SAS PHY Page 0 Flags field */ +#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01) + +/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ + +/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ + +/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */ + + +/* SAS PHY Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 InvalidDwordCount; /* 0x0C */ + U32 RunningDisparityErrorCount; /* 0x10 */ + U32 LossDwordSynchCount; /* 0x14 */ + U32 PhyResetProblemCount; /* 0x18 */ +} MPI2_CONFIG_PAGE_SAS_PHY_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_1, + Mpi2SasPhyPage1_t, MPI2_POINTER pMpi2SasPhyPage1_t; + +#define MPI2_SASPHY1_PAGEVERSION (0x01) + + +/* SAS PHY Page 2 */ + +typedef struct _MPI2_SASPHY2_PHY_EVENT +{ + U8 PhyEventCode; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U32 PhyEventInfo; /* 0x04 */ +} MPI2_SASPHY2_PHY_EVENT, MPI2_POINTER PTR_MPI2_SASPHY2_PHY_EVENT, + Mpi2SasPhy2PhyEvent_t, MPI2_POINTER pMpi2SasPhy2PhyEvent_t; + +/* use MPI2_SASPHY3_EVENT_CODE_ for the PhyEventCode field */ + + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhyEvents at runtime. + */ +#ifndef MPI2_SASPHY2_PHY_EVENT_MAX +#define MPI2_SASPHY2_PHY_EVENT_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U8 NumPhyEvents; /* 0x0C */ + U8 Reserved2; /* 0x0D */ + U16 Reserved3; /* 0x0E */ + MPI2_SASPHY2_PHY_EVENT PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX]; /* 0x10 */ +} MPI2_CONFIG_PAGE_SAS_PHY_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_2, + Mpi2SasPhyPage2_t, MPI2_POINTER pMpi2SasPhyPage2_t; + +#define MPI2_SASPHY2_PAGEVERSION (0x00) + + +/* SAS PHY Page 3 */ + +typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG +{ + U8 PhyEventCode; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U8 CounterType; /* 0x04 */ + U8 ThresholdWindow; /* 0x05 */ + U8 TimeUnits; /* 0x06 */ + U8 Reserved3; /* 0x07 */ + U32 EventThreshold; /* 0x08 */ + U16 ThresholdFlags; /* 0x0C */ + U16 Reserved4; /* 0x0E */ +} MPI2_SASPHY3_PHY_EVENT_CONFIG, MPI2_POINTER PTR_MPI2_SASPHY3_PHY_EVENT_CONFIG, + Mpi2SasPhy3PhyEventConfig_t, MPI2_POINTER pMpi2SasPhy3PhyEventConfig_t; + +/* values for PhyEventCode field */ +#define MPI2_SASPHY3_EVENT_CODE_NO_EVENT (0x00) +#define MPI2_SASPHY3_EVENT_CODE_INVALID_DWORD (0x01) +#define MPI2_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR (0x02) +#define MPI2_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC (0x03) +#define MPI2_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM (0x04) +#define MPI2_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW (0x05) +#define MPI2_SASPHY3_EVENT_CODE_RX_ERROR (0x06) +#define MPI2_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR (0x20) +#define MPI2_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT (0x21) +#define MPI2_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT (0x22) +#define MPI2_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT (0x23) +#define MPI2_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT (0x24) +#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON (0x25) +#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON (0x26) +#define MPI2_SASPHY3_EVENT_CODE_TX_BREAK (0x27) +#define MPI2_SASPHY3_EVENT_CODE_RX_BREAK (0x28) +#define MPI2_SASPHY3_EVENT_CODE_BREAK_TIMEOUT (0x29) +#define MPI2_SASPHY3_EVENT_CODE_CONNECTION (0x2A) +#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED (0x2B) +#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME (0x2C) +#define MPI2_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME (0x2D) +#define MPI2_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME (0x2E) +#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_FRAMES (0x40) +#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_FRAMES (0x41) +#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES (0x42) +#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES (0x43) +#define MPI2_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED (0x44) +#define MPI2_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED (0x45) +#define MPI2_SASPHY3_EVENT_CODE_TX_SATA_FRAMES (0x50) +#define MPI2_SASPHY3_EVENT_CODE_RX_SATA_FRAMES (0x51) +#define MPI2_SASPHY3_EVENT_CODE_SATA_OVERFLOW (0x52) +#define MPI2_SASPHY3_EVENT_CODE_TX_SMP_FRAMES (0x60) +#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_FRAMES (0x61) +#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES (0x63) +#define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT (0xD0) +#define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1) +#define MPI2_SASPHY3_EVENT_CODE_RX_AIP (0xD2) + +/* values for the CounterType field */ +#define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING (0x00) +#define MPI2_SASPHY3_COUNTER_TYPE_SATURATING (0x01) +#define MPI2_SASPHY3_COUNTER_TYPE_PEAK_VALUE (0x02) + +/* values for the TimeUnits field */ +#define MPI2_SASPHY3_TIME_UNITS_10_MICROSECONDS (0x00) +#define MPI2_SASPHY3_TIME_UNITS_100_MICROSECONDS (0x01) +#define MPI2_SASPHY3_TIME_UNITS_1_MILLISECOND (0x02) +#define MPI2_SASPHY3_TIME_UNITS_10_MILLISECONDS (0x03) + +/* values for the ThresholdFlags field */ +#define MPI2_SASPHY3_TFLAGS_PHY_RESET (0x0002) +#define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumPhyEvents at runtime. + */ +#ifndef MPI2_SASPHY3_PHY_EVENT_MAX +#define MPI2_SASPHY3_PHY_EVENT_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U8 NumPhyEvents; /* 0x0C */ + U8 Reserved2; /* 0x0D */ + U16 Reserved3; /* 0x0E */ + MPI2_SASPHY3_PHY_EVENT_CONFIG PhyEventConfig[MPI2_SASPHY3_PHY_EVENT_MAX]; /* 0x10 */ +} MPI2_CONFIG_PAGE_SAS_PHY_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_3, + Mpi2SasPhyPage3_t, MPI2_POINTER pMpi2SasPhyPage3_t; + +#define MPI2_SASPHY3_PAGEVERSION (0x00) + + +/* SAS PHY Page 4 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_4 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 Reserved1; /* 0x08 */ + U8 Reserved2; /* 0x0A */ + U8 Flags; /* 0x0B */ + U8 InitialFrame[28]; /* 0x0C */ +} MPI2_CONFIG_PAGE_SAS_PHY_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_4, + Mpi2SasPhyPage4_t, MPI2_POINTER pMpi2SasPhyPage4_t; + +#define MPI2_SASPHY4_PAGEVERSION (0x00) + +/* values for the Flags field */ +#define MPI2_SASPHY4_FLAGS_FRAME_VALID (0x02) +#define MPI2_SASPHY4_FLAGS_SATA_FRAME (0x01) + + + + +/**************************************************************************** +* SAS Port Config Pages +****************************************************************************/ + +/* SAS Port Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 PortNumber; /* 0x08 */ + U8 PhysicalPort; /* 0x09 */ + U8 PortWidth; /* 0x0A */ + U8 PhysicalPortWidth; /* 0x0B */ + U8 ZoneGroup; /* 0x0C */ + U8 Reserved1; /* 0x0D */ + U16 Reserved2; /* 0x0E */ + U64 SASAddress; /* 0x10 */ + U32 DeviceInfo; /* 0x18 */ + U32 Reserved3; /* 0x1C */ + U32 Reserved4; /* 0x20 */ +} MPI2_CONFIG_PAGE_SAS_PORT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PORT_0, + Mpi2SasPortPage0_t, MPI2_POINTER pMpi2SasPortPage0_t; + +#define MPI2_SASPORT0_PAGEVERSION (0x00) + +/* see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */ + + +/**************************************************************************** +* SAS Enclosure Config Pages +****************************************************************************/ + +/* SAS Enclosure Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U64 EnclosureLogicalID; /* 0x0C */ + U16 Flags; /* 0x14 */ + U16 EnclosureHandle; /* 0x16 */ + U16 NumSlots; /* 0x18 */ + U16 StartSlot; /* 0x1A */ + U16 Reserved2; /* 0x1C */ + U16 SEPDevHandle; /* 0x1E */ + U32 Reserved3; /* 0x20 */ + U32 Reserved4; /* 0x24 */ +} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, + Mpi2SasEnclosurePage0_t, MPI2_POINTER pMpi2SasEnclosurePage0_t; + +#define MPI2_SASENCLOSURE0_PAGEVERSION (0x03) + +/* values for SAS Enclosure Page 0 Flags field */ +#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005) + + +/**************************************************************************** +* Log Config Page +****************************************************************************/ + +/* Log Page 0 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumLogEntries at runtime. + */ +#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES +#define MPI2_LOG_0_NUM_LOG_ENTRIES (1) +#endif + +#define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C) + +typedef struct _MPI2_LOG_0_ENTRY +{ + U64 TimeStamp; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U16 LogSequence; /* 0x0C */ + U16 LogEntryQualifier; /* 0x0E */ + U8 VP_ID; /* 0x10 */ + U8 VF_ID; /* 0x11 */ + U16 Reserved2; /* 0x12 */ + U8 LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/* 0x14 */ +} MPI2_LOG_0_ENTRY, MPI2_POINTER PTR_MPI2_LOG_0_ENTRY, + Mpi2Log0Entry_t, MPI2_POINTER pMpi2Log0Entry_t; + +/* values for Log Page 0 LogEntry LogEntryQualifier field */ +#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000) +#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001) +#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE (0x0002) +#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC (0x8000) +#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC (0xFFFF) + +typedef struct _MPI2_CONFIG_PAGE_LOG_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 Reserved2; /* 0x0C */ + U16 NumLogEntries; /* 0x10 */ + U16 Reserved3; /* 0x12 */ + MPI2_LOG_0_ENTRY LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /* 0x14 */ +} MPI2_CONFIG_PAGE_LOG_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_LOG_0, + Mpi2LogPage0_t, MPI2_POINTER pMpi2LogPage0_t; + +#define MPI2_LOG_0_PAGEVERSION (0x02) + + +/**************************************************************************** +* RAID Config Page +****************************************************************************/ + +/* RAID Page 0 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumElements at runtime. + */ +#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS +#define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1) +#endif + +typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT +{ + U16 ElementFlags; /* 0x00 */ + U16 VolDevHandle; /* 0x02 */ + U8 HotSparePool; /* 0x04 */ + U8 PhysDiskNum; /* 0x05 */ + U16 PhysDiskDevHandle; /* 0x06 */ +} MPI2_RAIDCONFIG0_CONFIG_ELEMENT, + MPI2_POINTER PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT, + Mpi2RaidConfig0ConfigElement_t, MPI2_POINTER pMpi2RaidConfig0ConfigElement_t; + +/* values for the ElementFlags field */ +#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE (0x000F) +#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT (0x0000) +#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT (0x0001) +#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT (0x0002) +#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT (0x0003) + + +typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 NumHotSpares; /* 0x08 */ + U8 NumPhysDisks; /* 0x09 */ + U8 NumVolumes; /* 0x0A */ + U8 ConfigNum; /* 0x0B */ + U32 Flags; /* 0x0C */ + U8 ConfigGUID[24]; /* 0x10 */ + U32 Reserved1; /* 0x28 */ + U8 NumElements; /* 0x2C */ + U8 Reserved2; /* 0x2D */ + U16 Reserved3; /* 0x2E */ + MPI2_RAIDCONFIG0_CONFIG_ELEMENT ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /* 0x30 */ +} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0, + Mpi2RaidConfigurationPage0_t, MPI2_POINTER pMpi2RaidConfigurationPage0_t; + +#define MPI2_RAIDCONFIG0_PAGEVERSION (0x00) + +/* values for RAID Configuration Page 0 Flags field */ +#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG (0x00000001) + + +/**************************************************************************** +* Driver Persistent Mapping Config Pages +****************************************************************************/ + +/* Driver Persistent Mapping Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY +{ + U64 PhysicalIdentifier; /* 0x00 */ + U16 MappingInformation; /* 0x08 */ + U16 DeviceIndex; /* 0x0A */ + U32 PhysicalBitsMapping; /* 0x0C */ + U32 Reserved1; /* 0x10 */ +} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY, + Mpi2DriverMap0Entry_t, MPI2_POINTER pMpi2DriverMap0Entry_t; + +typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY Entry; /* 0x08 */ +} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0, + Mpi2DriverMappingPage0_t, MPI2_POINTER pMpi2DriverMappingPage0_t; + +#define MPI2_DRIVERMAPPING0_PAGEVERSION (0x00) + +/* values for Driver Persistent Mapping Page 0 MappingInformation field */ +#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK (0x07F0) +#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT (4) +#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK (0x000F) + + +/**************************************************************************** +* Ethernet Config Pages +****************************************************************************/ + +/* Ethernet Page 0 */ + +/* IP address (union of IPv4 and IPv6) */ +typedef union _MPI2_ETHERNET_IP_ADDR +{ + U32 IPv4Addr; + U32 IPv6Addr[4]; +} MPI2_ETHERNET_IP_ADDR, MPI2_POINTER PTR_MPI2_ETHERNET_IP_ADDR, + Mpi2EthernetIpAddr_t, MPI2_POINTER pMpi2EthernetIpAddr_t; + +#define MPI2_ETHERNET_HOST_NAME_LENGTH (32) + +typedef struct _MPI2_CONFIG_PAGE_ETHERNET_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 NumInterfaces; /* 0x08 */ + U8 Reserved0; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U32 Status; /* 0x0C */ + U8 MediaState; /* 0x10 */ + U8 Reserved2; /* 0x11 */ + U16 Reserved3; /* 0x12 */ + U8 MacAddress[6]; /* 0x14 */ + U8 Reserved4; /* 0x1A */ + U8 Reserved5; /* 0x1B */ + MPI2_ETHERNET_IP_ADDR IpAddress; /* 0x1C */ + MPI2_ETHERNET_IP_ADDR SubnetMask; /* 0x2C */ + MPI2_ETHERNET_IP_ADDR GatewayIpAddress; /* 0x3C */ + MPI2_ETHERNET_IP_ADDR DNS1IpAddress; /* 0x4C */ + MPI2_ETHERNET_IP_ADDR DNS2IpAddress; /* 0x5C */ + MPI2_ETHERNET_IP_ADDR DhcpIpAddress; /* 0x6C */ + U8 HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/* 0x7C */ +} MPI2_CONFIG_PAGE_ETHERNET_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_ETHERNET_0, + Mpi2EthernetPage0_t, MPI2_POINTER pMpi2EthernetPage0_t; + +#define MPI2_ETHERNETPAGE0_PAGEVERSION (0x00) + +/* values for Ethernet Page 0 Status field */ +#define MPI2_ETHPG0_STATUS_IPV6_CAPABLE (0x80000000) +#define MPI2_ETHPG0_STATUS_IPV4_CAPABLE (0x40000000) +#define MPI2_ETHPG0_STATUS_CONSOLE_CONNECTED (0x20000000) +#define MPI2_ETHPG0_STATUS_DEFAULT_IF (0x00000100) +#define MPI2_ETHPG0_STATUS_FW_DWNLD_ENABLED (0x00000080) +#define MPI2_ETHPG0_STATUS_TELNET_ENABLED (0x00000040) +#define MPI2_ETHPG0_STATUS_SSH2_ENABLED (0x00000020) +#define MPI2_ETHPG0_STATUS_DHCP_CLIENT_ENABLED (0x00000010) +#define MPI2_ETHPG0_STATUS_IPV6_ENABLED (0x00000008) +#define MPI2_ETHPG0_STATUS_IPV4_ENABLED (0x00000004) +#define MPI2_ETHPG0_STATUS_IPV6_ADDRESSES (0x00000002) +#define MPI2_ETHPG0_STATUS_ETH_IF_ENABLED (0x00000001) + +/* values for Ethernet Page 0 MediaState field */ +#define MPI2_ETHPG0_MS_DUPLEX_MASK (0x80) +#define MPI2_ETHPG0_MS_HALF_DUPLEX (0x00) +#define MPI2_ETHPG0_MS_FULL_DUPLEX (0x80) + +#define MPI2_ETHPG0_MS_CONNECT_SPEED_MASK (0x07) +#define MPI2_ETHPG0_MS_NOT_CONNECTED (0x00) +#define MPI2_ETHPG0_MS_10MBIT (0x01) +#define MPI2_ETHPG0_MS_100MBIT (0x02) +#define MPI2_ETHPG0_MS_1GBIT (0x03) + + +/* Ethernet Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved0; /* 0x08 */ + U32 Flags; /* 0x0C */ + U8 MediaState; /* 0x10 */ + U8 Reserved1; /* 0x11 */ + U16 Reserved2; /* 0x12 */ + U8 MacAddress[6]; /* 0x14 */ + U8 Reserved3; /* 0x1A */ + U8 Reserved4; /* 0x1B */ + MPI2_ETHERNET_IP_ADDR StaticIpAddress; /* 0x1C */ + MPI2_ETHERNET_IP_ADDR StaticSubnetMask; /* 0x2C */ + MPI2_ETHERNET_IP_ADDR StaticGatewayIpAddress; /* 0x3C */ + MPI2_ETHERNET_IP_ADDR StaticDNS1IpAddress; /* 0x4C */ + MPI2_ETHERNET_IP_ADDR StaticDNS2IpAddress; /* 0x5C */ + U32 Reserved5; /* 0x6C */ + U32 Reserved6; /* 0x70 */ + U32 Reserved7; /* 0x74 */ + U32 Reserved8; /* 0x78 */ + U8 HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/* 0x7C */ +} MPI2_CONFIG_PAGE_ETHERNET_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_ETHERNET_1, + Mpi2EthernetPage1_t, MPI2_POINTER pMpi2EthernetPage1_t; + +#define MPI2_ETHERNETPAGE1_PAGEVERSION (0x00) + +/* values for Ethernet Page 1 Flags field */ +#define MPI2_ETHPG1_FLAG_SET_DEFAULT_IF (0x00000100) +#define MPI2_ETHPG1_FLAG_ENABLE_FW_DOWNLOAD (0x00000080) +#define MPI2_ETHPG1_FLAG_ENABLE_TELNET (0x00000040) +#define MPI2_ETHPG1_FLAG_ENABLE_SSH2 (0x00000020) +#define MPI2_ETHPG1_FLAG_ENABLE_DHCP_CLIENT (0x00000010) +#define MPI2_ETHPG1_FLAG_ENABLE_IPV6 (0x00000008) +#define MPI2_ETHPG1_FLAG_ENABLE_IPV4 (0x00000004) +#define MPI2_ETHPG1_FLAG_USE_IPV6_ADDRESSES (0x00000002) +#define MPI2_ETHPG1_FLAG_ENABLE_ETH_IF (0x00000001) + +/* values for Ethernet Page 1 MediaState field */ +#define MPI2_ETHPG1_MS_DUPLEX_MASK (0x80) +#define MPI2_ETHPG1_MS_HALF_DUPLEX (0x00) +#define MPI2_ETHPG1_MS_FULL_DUPLEX (0x80) + +#define MPI2_ETHPG1_MS_DATA_RATE_MASK (0x07) +#define MPI2_ETHPG1_MS_DATA_RATE_AUTO (0x00) +#define MPI2_ETHPG1_MS_DATA_RATE_10MBIT (0x01) +#define MPI2_ETHPG1_MS_DATA_RATE_100MBIT (0x02) +#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT (0x03) + + +/**************************************************************************** +* Extended Manufacturing Config Pages +****************************************************************************/ + +/* + * Generic structure to use for product-specific extended manufacturing pages + * (currently Extended Manufacturing Page 40 through Extended Manufacturing + * Page 60). + */ + +typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 ProductSpecificInfo; /* 0x08 */ +} MPI2_CONFIG_PAGE_EXT_MAN_PS, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS, + Mpi2ExtManufacturingPagePS_t, MPI2_POINTER pMpi2ExtManufacturingPagePS_t; + +/* PageVersion should be provided by product-specific code */ + +#endif + diff --git a/source/lsi/mpi2_hbd.h b/source/lsi/mpi2_hbd.h new file mode 100755 index 0000000..137d67f --- /dev/null +++ b/source/lsi/mpi2_hbd.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2009-2010 LSI Corporation. + * + * + * Name: mpi2_hbd.h + * Title: MPI Host Based Discovery messages and structures + * Creation Date: October 21, 2009 + * + * mpi2_hbd.h Version: 02.00.xx + * + * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 + * prefix are for use only on MPI v2.5 products, and must not be used + * with MPI v2.0 products. Unless otherwise noted, names beginning with + * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 10-28-09 02.00.00 Initial version. + * 08-11-10 02.00.01 Removed PortGroups, DmaGroup, and ControlGroup from + * HBD Action request, replaced by AdditionalInfo field. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_HBD_H +#define MPI2_HBD_H + +/**************************************************************************** +* Host Based Discovery Action messages +****************************************************************************/ + +/* Host Based Discovery Action Request Message */ +typedef struct _MPI2_HBD_ACTION_REQUEST +{ + U8 Operation; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 DevHandle; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U32 Reserved4; /* 0x0C */ + U64 SASAddress; /* 0x10 */ + U32 Reserved5; /* 0x18 */ + U32 HbdDeviceInfo; /* 0x1C */ + U16 ParentDevHandle; /* 0x20 */ + U16 MaxQDepth; /* 0x22 */ + U8 FirstPhyIdentifier; /* 0x24 */ + U8 Port; /* 0x25 */ + U8 MaxConnections; /* 0x26 */ + U8 MaxRate; /* 0x27 */ + U32 AdditionalInfo; /* 0x28 */ + U16 InitialAWT; /* 0x2C */ + U16 Reserved7; /* 0x2E */ + U32 Reserved8; /* 0x30 */ +} MPI2_HBD_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_HBD_ACTION_REQUEST, + Mpi2HbdActionRequest_t, MPI2_POINTER pMpi2HbdActionRequest_t; + +/* values for the Operation field */ +#define MPI2_HBD_OP_ADD_DEVICE (0x01) +#define MPI2_HBD_OP_REMOVE_DEVICE (0x02) +#define MPI2_HBD_OP_UPDATE_DEVICE (0x03) + +/* values for the HbdDeviceInfo field */ +#define MPI2_HBD_DEVICE_INFO_VIRTUAL_DEVICE (0x00004000) +#define MPI2_HBD_DEVICE_INFO_ATAPI_DEVICE (0x00002000) +#define MPI2_HBD_DEVICE_INFO_DIRECT_ATTACH (0x00000800) +#define MPI2_HBD_DEVICE_INFO_SSP_TARGET (0x00000400) +#define MPI2_HBD_DEVICE_INFO_STP_TARGET (0x00000200) +#define MPI2_HBD_DEVICE_INFO_SMP_TARGET (0x00000100) +#define MPI2_HBD_DEVICE_INFO_SATA_DEVICE (0x00000080) +#define MPI2_HBD_DEVICE_INFO_SSP_INITIATOR (0x00000040) +#define MPI2_HBD_DEVICE_INFO_STP_INITIATOR (0x00000020) +#define MPI2_HBD_DEVICE_INFO_SMP_INITIATOR (0x00000010) +#define MPI2_HBD_DEVICE_INFO_SATA_HOST (0x00000008) + +#define MPI2_HBD_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007) +#define MPI2_HBD_DEVICE_INFO_NO_DEVICE (0x00000000) +#define MPI2_HBD_DEVICE_INFO_END_DEVICE (0x00000001) +#define MPI2_HBD_DEVICE_INFO_EDGE_EXPANDER (0x00000002) +#define MPI2_HBD_DEVICE_INFO_FANOUT_EXPANDER (0x00000003) + +/* values for the MaxRate field */ +#define MPI2_HBD_MAX_RATE_MASK (0x0F) +#define MPI2_HBD_MAX_RATE_1_5 (0x08) +#define MPI2_HBD_MAX_RATE_3_0 (0x09) +#define MPI2_HBD_MAX_RATE_6_0 (0x0A) +#define MPI25_HBD_MAX_RATE_12_0 (0x0B) + + +/* Host Based Discovery Action Reply Message */ +typedef struct _MPI2_HBD_ACTION_REPLY +{ + U8 Operation; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 DevHandle; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_HBD_ACTION_REPLY, MPI2_POINTER PTR_MPI2_HBD_ACTION_REPLY, + Mpi2HbdActionReply_t, MPI2_POINTER pMpi2HbdActionReply_t; + + +#endif + + diff --git a/source/lsi/mpi2_history.txt b/source/lsi/mpi2_history.txt new file mode 100755 index 0000000..91e06d4 --- /dev/null +++ b/source/lsi/mpi2_history.txt @@ -0,0 +1,460 @@ + ============================== + Fusion-MPT MPI 2.0 Header File Change History + ============================== + + Copyright (c) 2000-2011 LSI Corporation. + + --------------------------------------- + Header Set Release Version: 02.00.19 + Header Set Release Date: 02-23-11 + --------------------------------------- + + Filename Current version Prior version + ---------- --------------- ------------- + mpi2.h 02.00.19 02.00.18 + mpi2_cnfg.h 02.00.18 02.00.17 + mpi2_init.h 02.00.11 02.00.11 + mpi2_ioc.h 02.00.17 02.00.16 + mpi2_raid.h 02.00.05 02.00.05 + mpi2_sas.h 02.00.05 02.00.05 + mpi2_targ.h 02.00.04 02.00.04 + mpi2_tool.h 02.00.06 02.00.06 + mpi2_type.h 02.00.00 02.00.00 + mpi2_ra.h 02.00.00 02.00.00 + mpi2_hbd.h 02.00.01 02.00.01 + mpi2_history.txt 02.00.19 02.00.18 + + + * Date Version Description + * -------- -------- ------------------------------------------------------ + +mpi2.h + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT. + * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT. + * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT. + * Moved ReplyPostHostIndex register to offset 0x6C of the + * MPI2_SYSTEM_INTERFACE_REGS and modified the define for + * MPI2_REPLY_POST_HOST_INDEX_OFFSET. + * Added union of request descriptors. + * Added union of reply descriptors. + * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT. + * Added define for MPI2_VERSION_02_00. + * Fixed the size of the FunctionDependent5 field in the + * MPI2_DEFAULT_REPLY structure. + * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT. + * Removed the MPI-defined Fault Codes and extended the + * product specific codes up to 0xEFFF. + * Added a sixth key value for the WriteSequence register + * and changed the flush value to 0x0. + * Added message function codes for Diagnostic Buffer Post + * and Diagnsotic Release. + * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED + * Moved MPI2_VERSION_UNION from mpi2_ioc.h. + * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT. + * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT. + * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT. + * Added #defines for marking a reply descriptor as unused. + * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT. + * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT. + * Moved LUN field defines from mpi2_init.h. + * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT. + * 05-06-09 02.00.12 Bumped MPI2_HEADER_VERSION_UNIT. + * In all request and reply descriptors, replaced VF_ID + * field with MSIxIndex field. + * Removed DevHandle field from + * MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those + * bytes reserved. + * Added RAID Accelerator functionality. + * 07-30-09 02.00.13 Bumped MPI2_HEADER_VERSION_UNIT. + * 10-28-09 02.00.14 Bumped MPI2_HEADER_VERSION_UNIT. + * Added MSI-x index mask and shift for Reply Post Host + * Index register. + * Added function code for Host Based Discovery Action. + * 02-10-10 02.00.15 Bumped MPI2_HEADER_VERSION_UNIT. + * Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL. + * Added defines for product-specific range of message + * function codes, 0xF0 to 0xFF. + * 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT. + * Added alternative defines for the SGE Direction bit. + * 08-11-10 02.00.17 Bumped MPI2_HEADER_VERSION_UNIT. + * 11-10-10 02.00.18 Bumped MPI2_HEADER_VERSION_UNIT. + * Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define. + * 02-23-11 02.00.19 Bumped MPI2_HEADER_VERSION_UNIT. + * Added MPI2_FUNCTION_SEND_HOST_MESSAGE. + * -------------------------------------------------------------------------- + +mpi2_cnfg.h + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags. + * Added Manufacturing Page 11. + * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE + * define. + * 06-26-07 02.00.02 Adding generic structure for product-specific + * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS. + * Rework of BIOS Page 2 configuration page. + * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the + * forms. + * Added configuration pages IOC Page 8 and Driver + * Persistent Mapping Page 0. + * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated + * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1, + * RAID Physical Disk Pages 0 and 1, RAID Configuration + * Page 0). + * Added new value for AccessStatus field of SAS Device + * Page 0 (_SATA_NEEDS_INITIALIZATION). + * 10-31-07 02.00.04 Added missing SEPDevHandle field to + * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. + * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for + * NVDATA. + * Modified IOC Page 7 to use masks and added field for + * SASBroadcastPrimitiveMasks. + * Added MPI2_CONFIG_PAGE_BIOS_4. + * Added MPI2_CONFIG_PAGE_LOG_0. + * 02-29-08 02.00.06 Modified various names to make them 32-character unique. + * Added SAS Device IDs. + * Updated Integrated RAID configuration pages including + * Manufacturing Page 4, IOC Page 6, and RAID Configuration + * Page 0. + * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA. + * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION. + * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING. + * Added missing MaxNumRoutedSasAddresses field to + * MPI2_CONFIG_PAGE_EXPANDER_0. + * Added SAS Port Page 0. + * Modified structure layout for + * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0. + * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use + * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array. + * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF + * to 0x000000FF. + * Added two new values for the Physical Disk Coercion Size + * bits in the Flags field of Manufacturing Page 4. + * Added product-specific Manufacturing pages 16 to 31. + * Modified Flags bits for controlling write cache on SATA + * drives in IO Unit Page 1. + * Added new bit to AdditionalControlFlags of SAS IO Unit + * Page 1 to control Invalid Topology Correction. + * Added SupportedPhysDisks field to RAID Volume Page 1 and + * added related defines. + * Added additional defines for RAID Volume Page 0 + * VolumeStatusFlags field. + * Modified meaning of RAID Volume Page 0 VolumeSettings + * define for auto-configure of hot-swap drives. + * Added PhysDiskAttributes field (and related defines) to + * RAID Physical Disk Page 0. + * Added MPI2_SAS_PHYINFO_PHY_VACANT define. + * Added three new DiscoveryStatus bits for SAS IO Unit + * Page 0 and SAS Expander Page 0. + * Removed multiplexing information from SAS IO Unit pages. + * Added BootDeviceWaitTime field to SAS IO Unit Page 4. + * Removed Zone Address Resolved bit from PhyInfo and from + * Expander Page 0 Flags field. + * Added two new AccessStatus values to SAS Device Page 0 + * for indicating routing problems. Added 3 reserved words + * to this page. + * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3. + * Inserted missing reserved field into structure for IOC + * Page 6. + * Added more pending task bits to RAID Volume Page 0 + * VolumeStatusFlags defines. + * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define. + * Added a new DiscoveryStatus bit for SAS IO Unit Page 0 + * and SAS Expander Page 0 to flag a downstream initiator + * when in simplified routing mode. + * Removed SATA Init Failure defines for DiscoveryStatus + * fields of SAS IO Unit Page 0 and SAS Expander Page 0. + * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define. + * Added PortGroups, DmaGroup, and ControlGroup fields to + * SAS Device Page 0. + * 05-06-09 02.00.11 Added structures and defines for IO Unit Page 5 and IO + * Unit Page 6. + * Added expander reduced functionality data to SAS + * Expander Page 0. + * Added SAS PHY Page 2 and SAS PHY Page 3. + * 07-30-09 02.00.12 Added IO Unit Page 7. + * Added new device ids. + * Added SAS IO Unit Page 5. + * Added partial and slumber power management capable flags + * to SAS Device Page 0 Flags field. + * Added PhyInfo defines for power condition. + * Added Ethernet configuration pages. + * 10-28-09 02.00.13 Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY. + * Added SAS PHY Page 4 structure and defines. + * 02-10-10 02.00.14 Modified the comments for the configuration page + * structures that contain an array of data. The host + * should use the "count" field in the page data (e.g. the + * NumPhys field) to determine the number of valid elements + * in the array. + * Added/modified some MPI2_MFGPAGE_DEVID_SAS defines. + * Added PowerManagementCapabilities to IO Unit Page 7. + * Added PortWidthModGroup field to + * MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS. + * Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines. + * Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines. + * Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines. + * 05-12-10 02.00.15 Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT + * define. + * Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define. + * Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define. + * 08-11-10 02.00.16 Removed IO Unit Page 1 device path (multi-pathing) + * defines. + * 11-10-10 02.00.17 Added ReceptacleID field (replacing Reserved1) to + * MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for + * the Pinout field. + * Added BoardTemperature and BoardTemperatureUnits fields + * to MPI2_CONFIG_PAGE_IO_UNIT_7. + * Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define + * and MPI2_CONFIG_PAGE_EXT_MAN_PS structure. + * 02-23-11 02.00.18 Added ProxyVF_ID field to MPI2_CONFIG_REQUEST. + * Added IO Unit Page 8, IO Unit Page 9, + * and IO Unit Page 10. + * Added SASNotifyPrimitiveMasks field to + * MPI2_CONFIG_PAGE_IOC_7. + * -------------------------------------------------------------------------- + +mpi2_init.h + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t. + * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines. + * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention. + * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY. + * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t. + * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO + * Control field Task Attribute flags. + * Moved LUN field defines to mpi2.h becasue they are + * common to many structures. + * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to + * Query Asynchronous Event. + * Defined two new bits in the SlotStatus field of the SCSI + * Enclosure Processor Request and Reply. + * 10-28-09 02.00.08 Added defines for decoding the ResponseInfo bytes for + * both SCSI IO Error Reply and SCSI Task Management Reply. + * Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY. + * Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define. + * 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it. + * 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request. + * 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define. + * -------------------------------------------------------------------------- + +mpi2_ioc.h + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to + * MaxTargets. + * Added TotalImageSize field to FWDownload Request. + * Added reserved words to FWUpload Request. + * 06-26-07 02.00.02 Added IR Configuration Change List Event. + * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit + * request and replaced it with + * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth. + * Replaced the MinReplyQueueDepth field of the IOCFacts + * reply with MaxReplyDescriptorPostQueueDepth. + * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum + * depth for the Reply Descriptor Post Queue. + * Added SASAddress field to Initiator Device Table + * Overflow Event data. + * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING + * for SAS Initiator Device Status Change Event data. + * Modified Reason Code defines for SAS Topology Change + * List Event data, including adding a bit for PHY Vacant + * status, and adding a mask for the Reason Code. + * Added define for + * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING. + * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID. + * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of + * the IOCFacts Reply. + * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. + * Moved MPI2_VERSION_UNION to mpi2.h. + * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks + * instead of enables, and added SASBroadcastPrimitiveMasks + * field. + * Added Log Entry Added Event and related structure. + * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID. + * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET. + * Added MaxVolumes and MaxPersistentEntries fields to + * IOCFacts reply. + * Added ProtocalFlags and IOCCapabilities fields to + * MPI2_FW_IMAGE_HEADER. + * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT. + * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to + * a U16 (from a U32). + * Removed extra 's' from EventMasks name. + * 06-27-08 02.00.08 Fixed an offset in a comment. + * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST. + * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and + * renamed MinReplyFrameSize to ReplyFrameSize. + * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX. + * Added two new RAIDOperation values for Integrated RAID + * Operations Status Event data. + * Added four new IR Configuration Change List Event data + * ReasonCode values. + * Added two new ReasonCode defines for SAS Device Status + * Change Event data. + * Added three new DiscoveryStatus bits for the SAS + * Discovery event data. + * Added Multiplexing Status Change bit to the PhyStatus + * field of the SAS Topology Change List event data. + * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY. + * BootFlags are now product-specific. + * Added defines for the indivdual signature bytes + * for MPI2_INIT_IMAGE_FOOTER. + * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define. + * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR + * define. + * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE + * define. + * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define. + * 05-06-09 02.00.11 Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define. + * Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define. + * Added two new reason codes for SAS Device Status Change + * Event. + * Added new event: SAS PHY Counter. + * 07-30-09 02.00.12 Added GPIO Interrupt event define and structure. + * Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. + * Added new product id family for 2208. + * 10-28-09 02.00.13 Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST. + * Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY. + * Added MinDevHandle field to MPI2_IOC_FACTS_REPLY. + * Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY. + * Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define. + * Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define. + * Added Host Based Discovery Phy Event data. + * Added defines for ProductID Product field + * (MPI2_FW_HEADER_PID_). + * Modified values for SAS ProductID Family + * (MPI2_FW_HEADER_PID_FAMILY_). + * 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines. + * Added PowerManagementControl Request structures and + * defines. + * 05-12-10 02.00.15 Marked Task Set Full Event as obsolete. + * Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define. + * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC. + * 02-23-11 02.00.17 Added SAS NOTIFY Primitive event, and added + * SASNotifyPrimitiveMasks field to + * MPI2_EVENT_NOTIFICATION_REQUEST. + * Added Temperature Threshold Event. + * Added Host Message Event. + * Added Send Host Message request and reply. + * -------------------------------------------------------------------------- + +mpi2_raid.h + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 08-31-07 02.00.01 Modifications to RAID Action request and reply, + * including the Actions and ActionData. + * 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD. + * 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that + * the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT + * can be sized by the build environment. + * 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of + * VolumeCreationFlags and marked the old one as obsolete. + * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define. + * -------------------------------------------------------------------------- + +mpi2_sas.h + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit + * Control Request. + * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control + * Request. + * 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST + * to MPI2_SGE_IO_UNION since it supports chained SGLs. + * 05-12-10 02.00.04 Modified some comments. + * 08-11-10 02.00.05 Added NCQ operations to SAS IO Unit Control. + * -------------------------------------------------------------------------- + +mpi2_targ.h + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 08-31-07 02.00.01 Added Command Buffer Data Location Address Space bits to + * BufferPostFlags field of CommandBufferPostBase Request. + * 02-29-08 02.00.02 Modified various names to make them 32-character unique. + * 10-02-08 02.00.03 Removed NextCmdBufferOffset from + * MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST. + * Target Status Send Request only takes a single SGE for + * response data. + * 02-10-10 02.00.04 Added comment to MPI2_TARGET_SSP_RSP_IU structure. + * -------------------------------------------------------------------------- + +mpi2_tool.h + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release + * structures and defines. + * 02-29-08 02.00.02 Modified various names to make them 32-character unique. + * 05-06-09 02.00.03 Added ISTWI Read Write Tool and Diagnostic CLI Tool. + * 07-30-09 02.00.04 Added ExtendedType field to DiagnosticBufferPost request + * and reply messages. + * Added MPI2_DIAG_BUF_TYPE_EXTENDED. + * Incremented MPI2_DIAG_BUF_TYPE_COUNT. + * 05-12-10 02.00.05 Added Diagnostic Data Upload tool. + * 08-11-10 02.00.06 Added defines that were missing for Diagnostic Buffer + * Post Request. + * -------------------------------------------------------------------------- + +mpi2_type.h + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * -------------------------------------------------------------------------- + +mpi2_ra.h + * 05-06-09 02.00.00 Initial version. + * -------------------------------------------------------------------------- + +mpi2_hbd.h + * 10-28-09 02.00.00 Initial version. + * 08-11-10 02.00.01 Removed PortGroups, DmaGroup, and ControlGroup from + * HBD Action request, replaced by AdditionalInfo field. + * -------------------------------------------------------------------------- + + +mpi2_history.txt Parts list history + +Filename 02.00.19 02.00.18 +---------- -------- -------- +mpi2.h 02.00.19 02.00.18 +mpi2_cnfg.h 02.00.18 02.00.17 +mpi2_init.h 02.00.11 02.00.11 +mpi2_ioc.h 02.00.17 02.00.16 +mpi2_raid.h 02.00.05 02.00.05 +mpi2_sas.h 02.00.05 02.00.05 +mpi2_targ.h 02.00.04 02.00.04 +mpi2_tool.h 02.00.06 02.00.06 +mpi2_type.h 02.00.00 02.00.00 +mpi2_ra.h 02.00.00 02.00.00 +mpi2_hbd.h 02.00.01 02.00.01 + +Filename 02.00.17 02.00.16 02.00.15 02.00.14 02.00.13 02.00.12 +---------- -------- -------- -------- -------- -------- -------- +mpi2.h 02.00.17 02.00.16 02.00.15 02.00.14 02.00.13 02.00.12 +mpi2_cnfg.h 02.00.16 02.00.15 02.00.14 02.00.13 02.00.12 02.00.11 +mpi2_init.h 02.00.10 02.00.10 02.00.09 02.00.08 02.00.07 02.00.07 +mpi2_ioc.h 02.00.15 02.00.15 02.00.14 02.00.13 02.00.12 02.00.11 +mpi2_raid.h 02.00.05 02.00.05 02.00.04 02.00.04 02.00.04 02.00.03 +mpi2_sas.h 02.00.05 02.00.04 02.00.03 02.00.03 02.00.02 02.00.02 +mpi2_targ.h 02.00.04 02.00.04 02.00.04 02.00.03 02.00.03 02.00.03 +mpi2_tool.h 02.00.06 02.00.05 02.00.04 02.00.04 02.00.04 02.00.03 +mpi2_type.h 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 +mpi2_ra.h 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 +mpi2_hbd.h 02.00.01 02.00.00 02.00.00 02.00.00 + +Filename 02.00.11 02.00.10 02.00.09 02.00.08 02.00.07 02.00.06 +---------- -------- -------- -------- -------- -------- -------- +mpi2.h 02.00.11 02.00.10 02.00.09 02.00.08 02.00.07 02.00.06 +mpi2_cnfg.h 02.00.10 02.00.09 02.00.08 02.00.07 02.00.06 02.00.06 +mpi2_init.h 02.00.06 02.00.06 02.00.05 02.00.05 02.00.04 02.00.03 +mpi2_ioc.h 02.00.10 02.00.09 02.00.08 02.00.07 02.00.07 02.00.06 +mpi2_raid.h 02.00.03 02.00.03 02.00.03 02.00.03 02.00.02 02.00.02 +mpi2_sas.h 02.00.02 02.00.02 02.00.01 02.00.01 02.00.01 02.00.01 +mpi2_targ.h 02.00.03 02.00.03 02.00.02 02.00.02 02.00.02 02.00.02 +mpi2_tool.h 02.00.02 02.00.02 02.00.02 02.00.02 02.00.02 02.00.02 +mpi2_type.h 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 + +Filename 02.00.05 02.00.04 02.00.03 02.00.02 02.00.01 02.00.00 +---------- -------- -------- -------- -------- -------- -------- +mpi2.h 02.00.05 02.00.04 02.00.03 02.00.02 02.00.01 02.00.00 +mpi2_cnfg.h 02.00.05 02.00.04 02.00.03 02.00.02 02.00.01 02.00.00 +mpi2_init.h 02.00.02 02.00.01 02.00.00 02.00.00 02.00.00 02.00.00 +mpi2_ioc.h 02.00.05 02.00.04 02.00.03 02.00.02 02.00.01 02.00.00 +mpi2_raid.h 02.00.01 02.00.01 02.00.01 02.00.00 02.00.00 02.00.00 +mpi2_sas.h 02.00.01 02.00.01 02.00.01 02.00.01 02.00.00 02.00.00 +mpi2_targ.h 02.00.01 02.00.01 02.00.01 02.00.00 02.00.00 02.00.00 +mpi2_tool.h 02.00.01 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 +mpi2_type.h 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 + diff --git a/source/lsi/mpi2_init.h b/source/lsi/mpi2_init.h new file mode 100755 index 0000000..25671d8 --- /dev/null +++ b/source/lsi/mpi2_init.h @@ -0,0 +1,571 @@ +/* + * Copyright (c) 2000-2010 LSI Corporation. + * + * + * Name: mpi2_init.h + * Title: MPI SCSI initiator mode messages and structures + * Creation Date: June 23, 2006 + * + * mpi2_init.h Version: 02.00.xx + * + * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 + * prefix are for use only on MPI v2.5 products, and must not be used + * with MPI v2.0 products. Unless otherwise noted, names beginning with + * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t. + * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines. + * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention. + * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY. + * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t. + * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO + * Control field Task Attribute flags. + * Moved LUN field defines to mpi2.h becasue they are + * common to many structures. + * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to + * Query Asynchronous Event. + * Defined two new bits in the SlotStatus field of the SCSI + * Enclosure Processor Request and Reply. + * 10-28-09 02.00.08 Added defines for decoding the ResponseInfo bytes for + * both SCSI IO Error Reply and SCSI Task Management Reply. + * Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY. + * Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define. + * 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it. + * 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request. + * 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_INIT_H +#define MPI2_INIT_H + +/***************************************************************************** +* +* SCSI Initiator Messages +* +*****************************************************************************/ + +/**************************************************************************** +* SCSI IO messages and associated structures +****************************************************************************/ + +typedef struct _MPI2_SCSI_IO_CDB_EEDP32 +{ + U8 CDB[20]; /* 0x00 */ + U32 PrimaryReferenceTag; /* 0x14 */ + U16 PrimaryApplicationTag; /* 0x18 */ + U16 PrimaryApplicationTagMask; /* 0x1A */ + U32 TransferLength; /* 0x1C */ +} MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32, + Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t; + +/* MPI v2.0 CDB field */ +typedef union _MPI2_SCSI_IO_CDB_UNION +{ + U8 CDB32[32]; + MPI2_SCSI_IO_CDB_EEDP32 EEDP32; + MPI2_SGE_SIMPLE_UNION SGE; +} MPI2_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_UNION, + Mpi2ScsiIoCdb_t, MPI2_POINTER pMpi2ScsiIoCdb_t; + +/* MPI v2.0 SCSI IO Request Message */ +typedef struct _MPI2_SCSI_IO_REQUEST +{ + U16 DevHandle; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U32 SenseBufferLowAddress; /* 0x0C */ + U16 SGLFlags; /* 0x10 */ + U8 SenseBufferLength; /* 0x12 */ + U8 Reserved4; /* 0x13 */ + U8 SGLOffset0; /* 0x14 */ + U8 SGLOffset1; /* 0x15 */ + U8 SGLOffset2; /* 0x16 */ + U8 SGLOffset3; /* 0x17 */ + U32 SkipCount; /* 0x18 */ + U32 DataLength; /* 0x1C */ + U32 BidirectionalDataLength; /* 0x20 */ + U16 IoFlags; /* 0x24 */ + U16 EEDPFlags; /* 0x26 */ + U32 EEDPBlockSize; /* 0x28 */ + U32 SecondaryReferenceTag; /* 0x2C */ + U16 SecondaryApplicationTag; /* 0x30 */ + U16 ApplicationTagTranslationMask; /* 0x32 */ + U8 LUN[8]; /* 0x34 */ + U32 Control; /* 0x3C */ + MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */ + +#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /* typically this is left undefined */ + MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion; +#endif + + MPI2_SGE_IO_UNION SGL; /* 0x60 */ + +} MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST, + Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t; + +/* SCSI IO MsgFlags bits */ + +/* MsgFlags for SenseBufferAddressSpace */ +#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR (0x0C) +#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR (0x00) +#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04) +#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08) +#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C) + +/* SCSI IO SGLFlags bits */ + +/* base values for Data Location Address Space */ +#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK (0x0C) +#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR (0x00) +#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR (0x04) +#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR (0x08) +#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR (0x0C) + +/* base values for Type */ +#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK (0x03) +#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI (0x00) +#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32 (0x01) +#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64 (0x02) + +/* shift values for each sub-field */ +#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT (12) +#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT (8) +#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4) +#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0) + +/* number of SGLOffset fields */ +#define MPI2_SCSIIO_NUM_SGLOFFSETS (4) + +/* SCSI IO IoFlags bits */ + +/* Large CDB Address Space */ +#define MPI2_SCSIIO_CDB_ADDR_MASK (0x6000) +#define MPI2_SCSIIO_CDB_ADDR_SYSTEM (0x0000) +#define MPI2_SCSIIO_CDB_ADDR_IOCDDR (0x2000) +#define MPI2_SCSIIO_CDB_ADDR_IOCPLB (0x4000) +#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA (0x6000) + +#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB (0x1000) +#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800) +#define MPI2_SCSIIO_IOFLAGS_MULTICAST (0x0400) +#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200) +#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF) + +/* SCSI IO EEDPFlags bits */ + +#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000) +#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG (0x4000) +#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG (0x2000) +#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG (0x1000) + +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100) + +#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG (0x0008) + +#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP (0x0007) +#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP (0x0000) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP (0x0001) +#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP (0x0002) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003) +#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004) +#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP (0x0006) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP (0x0007) + +/* SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */ + +/* SCSI IO Control bits */ +#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK (0xFC000000) +#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26) + +#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000) +#define MPI2_SCSIIO_CONTROL_NODATATRANSFER (0x00000000) +#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000) +#define MPI2_SCSIIO_CONTROL_READ (0x02000000) +#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL (0x03000000) + +#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK (0x00007800) +#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT (11) + +#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700) +#define MPI2_SCSIIO_CONTROL_SIMPLEQ (0x00000000) +#define MPI2_SCSIIO_CONTROL_HEADOFQ (0x00000100) +#define MPI2_SCSIIO_CONTROL_ORDEREDQ (0x00000200) +#define MPI2_SCSIIO_CONTROL_ACAQ (0x00000400) + +#define MPI2_SCSIIO_CONTROL_TLR_MASK (0x000000C0) +#define MPI2_SCSIIO_CONTROL_NO_TLR (0x00000000) +#define MPI2_SCSIIO_CONTROL_TLR_ON (0x00000040) +#define MPI2_SCSIIO_CONTROL_TLR_OFF (0x00000080) + + +/* MPI v2.5 CDB field */ +typedef union _MPI25_SCSI_IO_CDB_UNION +{ + U8 CDB32[32]; + MPI2_SCSI_IO_CDB_EEDP32 EEDP32; + MPI2_IEEE_SGE_SIMPLE64 SGE; +} MPI25_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI25_SCSI_IO_CDB_UNION, + Mpi25ScsiIoCdb_t, MPI2_POINTER pMpi25ScsiIoCdb_t; + +/* MPI v2.5 SCSI IO Request Message */ +typedef struct _MPI25_SCSI_IO_REQUEST +{ + U16 DevHandle; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U32 SenseBufferLowAddress; /* 0x0C */ + U8 DMAFlags; /* 0x10 */ + U8 Reserved5; /* 0x11 */ + U8 SenseBufferLength; /* 0x12 */ + U8 Reserved4; /* 0x13 */ + U8 SGLOffset0; /* 0x14 */ + U8 SGLOffset1; /* 0x15 */ + U8 SGLOffset2; /* 0x16 */ + U8 SGLOffset3; /* 0x17 */ + U32 SkipCount; /* 0x18 */ + U32 DataLength; /* 0x1C */ + U32 BidirectionalDataLength; /* 0x20 */ + U16 IoFlags; /* 0x24 */ + U16 EEDPFlags; /* 0x26 */ + U16 EEDPBlockSize; /* 0x28 */ + U16 Reserved6; /* 0x2A */ + U32 SecondaryReferenceTag; /* 0x2C */ + U16 SecondaryApplicationTag; /* 0x30 */ + U16 ApplicationTagTranslationMask; /* 0x32 */ + U8 LUN[8]; /* 0x34 */ + U32 Control; /* 0x3C */ + MPI25_SCSI_IO_CDB_UNION CDB; /* 0x40 */ + +#ifdef MPI25_SCSI_IO_VENDOR_UNIQUE_REGION /* typically this is left undefined */ + MPI25_SCSI_IO_VENDOR_UNIQUE VendorRegion; +#endif + + MPI25_SGE_IO_UNION SGL; /* 0x60 */ + +} MPI25_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI25_SCSI_IO_REQUEST, + Mpi25SCSIIORequest_t, MPI2_POINTER pMpi25SCSIIORequest_t; + +/* use MPI2_SCSIIO_MSGFLAGS_ defines for the MsgFlags field */ + +/* Defines for the DMAFlags field + * Each setting affects 4 SGLS, from SGL0 to SGL3. + * D = Data + * C = Cache DIF + * I = Interleaved + * H = Host DIF + */ +#define MPI25_SCSIIO_DMAFLAGS_OP_MASK (0x0F) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_D (0x00) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_C (0x01) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_I (0x02) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_C_C (0x03) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_C_I (0x04) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_I_I (0x05) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_C_C (0x06) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_C_I (0x07) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_I_I (0x08) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_I_I_I (0x09) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_D (0x0A) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_C (0x0B) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_I (0x0C) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_C_C (0x0D) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_C_I (0x0E) +#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_I_I (0x0F) + +/* number of SGLOffset fields */ +#define MPI25_SCSIIO_NUM_SGLOFFSETS (4) + +/* defines for the IoFlags field */ +#define MPI25_SCSIIO_IOFLAGS_IO_PATH_MASK (0xC000) +#define MPI25_SCSIIO_IOFLAGS_NORMAL_PATH (0x0000) +#define MPI25_SCSIIO_IOFLAGS_FAST_PATH (0x4000) + +#define MPI25_SCSIIO_IOFLAGS_LARGE_CDB (0x1000) +#define MPI25_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800) +#define MPI25_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200) +#define MPI25_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF) + +/* MPI v2.5 defines for the EEDPFlags bits */ +/* use MPI2_SCSIIO_EEDPFLAGS_ defines for the other EEDPFlags bits */ +#define MPI25_SCSIIO_EEDPFLAGS_ESCAPE_MODE_MASK (0x00C0) +#define MPI25_SCSIIO_EEDPFLAGS_COMPATIBLE_MODE (0x0000) +#define MPI25_SCSIIO_EEDPFLAGS_DO_NOT_DISABLE_MODE (0x0040) +#define MPI25_SCSIIO_EEDPFLAGS_APPTAG_DISABLE_MODE (0x0080) +#define MPI25_SCSIIO_EEDPFLAGS_APPTAG_REFTAG_DISABLE_MODE (0x00C0) + +#define MPI25_SCSIIO_EEDPFLAGS_HOST_GUARD_METHOD_MASK (0x0030) +#define MPI25_SCSIIO_EEDPFLAGS_T10_CRC_HOST_GUARD (0x0000) +#define MPI25_SCSIIO_EEDPFLAGS_IP_CHKSUM_HOST_GUARD (0x0010) + +/* use MPI2_LUN_ defines from mpi2.h for the LUN field */ + +/* use MPI2_SCSIIO_CONTROL_ defines for the Control field */ + + +/* NOTE: The SCSI IO Reply is the same for MPI 2.0 and MPI 2.5, so + * MPI2_SCSI_IO_REPLY is used for both. + */ + +/* SCSI IO Error Reply Message */ +typedef struct _MPI2_SCSI_IO_REPLY +{ + U16 DevHandle; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U8 SCSIStatus; /* 0x0C */ + U8 SCSIState; /* 0x0D */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 TransferCount; /* 0x14 */ + U32 SenseCount; /* 0x18 */ + U32 ResponseInfo; /* 0x1C */ + U16 TaskTag; /* 0x20 */ + U16 Reserved4; /* 0x22 */ + U32 BidirectionalTransferCount; /* 0x24 */ + U32 Reserved5; /* 0x28 */ + U32 Reserved6; /* 0x2C */ +} MPI2_SCSI_IO_REPLY, MPI2_POINTER PTR_MPI2_SCSI_IO_REPLY, + Mpi2SCSIIOReply_t, MPI2_POINTER pMpi2SCSIIOReply_t; + +/* SCSI IO Reply SCSIStatus values (SAM-4 status codes) */ + +#define MPI2_SCSI_STATUS_GOOD (0x00) +#define MPI2_SCSI_STATUS_CHECK_CONDITION (0x02) +#define MPI2_SCSI_STATUS_CONDITION_MET (0x04) +#define MPI2_SCSI_STATUS_BUSY (0x08) +#define MPI2_SCSI_STATUS_INTERMEDIATE (0x10) +#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14) +#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT (0x18) +#define MPI2_SCSI_STATUS_COMMAND_TERMINATED (0x22) /* obsolete */ +#define MPI2_SCSI_STATUS_TASK_SET_FULL (0x28) +#define MPI2_SCSI_STATUS_ACA_ACTIVE (0x30) +#define MPI2_SCSI_STATUS_TASK_ABORTED (0x40) + +/* SCSI IO Reply SCSIState flags */ + +#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID (0x10) +#define MPI2_SCSI_STATE_TERMINATED (0x08) +#define MPI2_SCSI_STATE_NO_SCSI_STATUS (0x04) +#define MPI2_SCSI_STATE_AUTOSENSE_FAILED (0x02) +#define MPI2_SCSI_STATE_AUTOSENSE_VALID (0x01) + +/* masks and shifts for the ResponseInfo field */ + +#define MPI2_SCSI_RI_MASK_REASONCODE (0x000000FF) +#define MPI2_SCSI_RI_SHIFT_REASONCODE (0) + +#define MPI2_SCSI_TASKTAG_UNKNOWN (0xFFFF) + + +/**************************************************************************** +* SCSI Task Management messages +****************************************************************************/ + +/* SCSI Task Management Request Message */ +typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST +{ + U16 DevHandle; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 Reserved1; /* 0x04 */ + U8 TaskType; /* 0x05 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U8 LUN[8]; /* 0x0C */ + U32 Reserved4[7]; /* 0x14 */ + U16 TaskMID; /* 0x30 */ + U16 Reserved5; /* 0x32 */ +} MPI2_SCSI_TASK_MANAGE_REQUEST, + MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REQUEST, + Mpi2SCSITaskManagementRequest_t, + MPI2_POINTER pMpi2SCSITaskManagementRequest_t; + +/* TaskType values */ + +#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) +#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02) +#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) +#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) +#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) +#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) +#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08) +#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09) +#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT (0x0A) + +/* obsolete TaskType name */ +#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT) + +/* MsgFlags bits */ + +#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18) +#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00) +#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08) +#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10) + +#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01) + + + +/* SCSI Task Management Reply Message */ +typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY +{ + U16 DevHandle; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 ResponseCode; /* 0x04 */ + U8 TaskType; /* 0x05 */ + U8 Reserved1; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U16 Reserved3; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 TerminationCount; /* 0x14 */ + U32 ResponseInfo; /* 0x18 */ +} MPI2_SCSI_TASK_MANAGE_REPLY, + MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REPLY, + Mpi2SCSITaskManagementReply_t, MPI2_POINTER pMpi2SCSIManagementReply_t; + +/* ResponseCode values */ + +#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE (0x00) +#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME (0x02) +#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04) +#define MPI2_SCSITASKMGMT_RSP_TM_FAILED (0x05) +#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08) +#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09) +#define MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG (0x0A) +#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80) + +/* masks and shifts for the ResponseInfo field */ + +#define MPI2_SCSITASKMGMT_RI_MASK_REASONCODE (0x000000FF) +#define MPI2_SCSITASKMGMT_RI_SHIFT_REASONCODE (0) +#define MPI2_SCSITASKMGMT_RI_MASK_ARI2 (0x0000FF00) +#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI2 (8) +#define MPI2_SCSITASKMGMT_RI_MASK_ARI1 (0x00FF0000) +#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI1 (16) +#define MPI2_SCSITASKMGMT_RI_MASK_ARI0 (0xFF000000) +#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI0 (24) + + +/**************************************************************************** +* SCSI Enclosure Processor messages +****************************************************************************/ + +/* SCSI Enclosure Processor Request Message */ +typedef struct _MPI2_SEP_REQUEST +{ + U16 DevHandle; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 Action; /* 0x04 */ + U8 Flags; /* 0x05 */ + U8 Reserved1; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U32 SlotStatus; /* 0x0C */ + U32 Reserved3; /* 0x10 */ + U32 Reserved4; /* 0x14 */ + U32 Reserved5; /* 0x18 */ + U16 Slot; /* 0x1C */ + U16 EnclosureHandle; /* 0x1E */ +} MPI2_SEP_REQUEST, MPI2_POINTER PTR_MPI2_SEP_REQUEST, + Mpi2SepRequest_t, MPI2_POINTER pMpi2SepRequest_t; + +/* Action defines */ +#define MPI2_SEP_REQ_ACTION_WRITE_STATUS (0x00) +#define MPI2_SEP_REQ_ACTION_READ_STATUS (0x01) + +/* Flags defines */ +#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS (0x00) +#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01) + +/* SlotStatus defines */ +#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000) +#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) +#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200) +#define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) +#define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) +#define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040) +#define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) +#define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) +#define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004) +#define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) +#define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) + + +/* SCSI Enclosure Processor Reply Message */ +typedef struct _MPI2_SEP_REPLY +{ + U16 DevHandle; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 Action; /* 0x04 */ + U8 Flags; /* 0x05 */ + U8 Reserved1; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U16 Reserved3; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 SlotStatus; /* 0x14 */ + U32 Reserved4; /* 0x18 */ + U16 Slot; /* 0x1C */ + U16 EnclosureHandle; /* 0x1E */ +} MPI2_SEP_REPLY, MPI2_POINTER PTR_MPI2_SEP_REPLY, + Mpi2SepReply_t, MPI2_POINTER pMpi2SepReply_t; + +/* SlotStatus defines */ +#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000) +#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) +#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200) +#define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100) +#define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080) +#define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040) +#define MPI2_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) +#define MPI2_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) +#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004) +#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002) +#define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001) + + +#endif + + diff --git a/source/lsi/mpi2_ioc.h b/source/lsi/mpi2_ioc.h new file mode 100755 index 0000000..b37fe03 --- /dev/null +++ b/source/lsi/mpi2_ioc.h @@ -0,0 +1,1721 @@ +/* + * Copyright (c) 2000-2011 LSI Corporation. + * + * + * Name: mpi2_ioc.h + * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages + * Creation Date: October 11, 2006 + * + * mpi2_ioc.h Version: 02.00.xx + * + * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 + * prefix are for use only on MPI v2.5 products, and must not be used + * with MPI v2.0 products. Unless otherwise noted, names beginning with + * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to + * MaxTargets. + * Added TotalImageSize field to FWDownload Request. + * Added reserved words to FWUpload Request. + * 06-26-07 02.00.02 Added IR Configuration Change List Event. + * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit + * request and replaced it with + * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth. + * Replaced the MinReplyQueueDepth field of the IOCFacts + * reply with MaxReplyDescriptorPostQueueDepth. + * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum + * depth for the Reply Descriptor Post Queue. + * Added SASAddress field to Initiator Device Table + * Overflow Event data. + * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING + * for SAS Initiator Device Status Change Event data. + * Modified Reason Code defines for SAS Topology Change + * List Event data, including adding a bit for PHY Vacant + * status, and adding a mask for the Reason Code. + * Added define for + * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING. + * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID. + * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of + * the IOCFacts Reply. + * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. + * Moved MPI2_VERSION_UNION to mpi2.h. + * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks + * instead of enables, and added SASBroadcastPrimitiveMasks + * field. + * Added Log Entry Added Event and related structure. + * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID. + * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET. + * Added MaxVolumes and MaxPersistentEntries fields to + * IOCFacts reply. + * Added ProtocalFlags and IOCCapabilities fields to + * MPI2_FW_IMAGE_HEADER. + * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT. + * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to + * a U16 (from a U32). + * Removed extra 's' from EventMasks name. + * 06-27-08 02.00.08 Fixed an offset in a comment. + * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST. + * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and + * renamed MinReplyFrameSize to ReplyFrameSize. + * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX. + * Added two new RAIDOperation values for Integrated RAID + * Operations Status Event data. + * Added four new IR Configuration Change List Event data + * ReasonCode values. + * Added two new ReasonCode defines for SAS Device Status + * Change Event data. + * Added three new DiscoveryStatus bits for the SAS + * Discovery event data. + * Added Multiplexing Status Change bit to the PhyStatus + * field of the SAS Topology Change List event data. + * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY. + * BootFlags are now product-specific. + * Added defines for the indivdual signature bytes + * for MPI2_INIT_IMAGE_FOOTER. + * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define. + * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR + * define. + * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE + * define. + * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define. + * 05-06-09 02.00.11 Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define. + * Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define. + * Added two new reason codes for SAS Device Status Change + * Event. + * Added new event: SAS PHY Counter. + * 07-30-09 02.00.12 Added GPIO Interrupt event define and structure. + * Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. + * Added new product id family for 2208. + * 10-28-09 02.00.13 Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST. + * Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY. + * Added MinDevHandle field to MPI2_IOC_FACTS_REPLY. + * Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY. + * Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define. + * Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define. + * Added Host Based Discovery Phy Event data. + * Added defines for ProductID Product field + * (MPI2_FW_HEADER_PID_). + * Modified values for SAS ProductID Family + * (MPI2_FW_HEADER_PID_FAMILY_). + * 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines. + * Added PowerManagementControl Request structures and + * defines. + * 05-12-10 02.00.15 Marked Task Set Full Event as obsolete. + * Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define. + * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC. + * 02-23-11 02.00.17 Added SAS NOTIFY Primitive event, and added + * SASNotifyPrimitiveMasks field to + * MPI2_EVENT_NOTIFICATION_REQUEST. + * Added Temperature Threshold Event. + * Added Host Message Event. + * Added Send Host Message request and reply. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_IOC_H +#define MPI2_IOC_H + +/***************************************************************************** +* +* IOC Messages +* +*****************************************************************************/ + +/**************************************************************************** +* IOCInit message +****************************************************************************/ + +/* IOCInit Request message */ +typedef struct _MPI2_IOC_INIT_REQUEST +{ + U8 WhoInit; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 MsgVersion; /* 0x0C */ + U16 HeaderVersion; /* 0x0E */ + U32 Reserved5; /* 0x10 */ + U16 Reserved6; /* 0x14 */ + U8 Reserved7; /* 0x16 */ + U8 HostMSIxVectors; /* 0x17 */ + U16 Reserved8; /* 0x18 */ + U16 SystemRequestFrameSize; /* 0x1A */ + U16 ReplyDescriptorPostQueueDepth; /* 0x1C */ + U16 ReplyFreeQueueDepth; /* 0x1E */ + U32 SenseBufferAddressHigh; /* 0x20 */ + U32 SystemReplyAddressHigh; /* 0x24 */ + U64 SystemRequestFrameBaseAddress; /* 0x28 */ + U64 ReplyDescriptorPostQueueAddress;/* 0x30 */ + U64 ReplyFreeQueueAddress; /* 0x38 */ + U64 TimeStamp; /* 0x40 */ +} MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST, + Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t; + +/* WhoInit values */ +#define MPI2_WHOINIT_NOT_INITIALIZED (0x00) +#define MPI2_WHOINIT_SYSTEM_BIOS (0x01) +#define MPI2_WHOINIT_ROM_BIOS (0x02) +#define MPI2_WHOINIT_PCI_PEER (0x03) +#define MPI2_WHOINIT_HOST_DRIVER (0x04) +#define MPI2_WHOINIT_MANUFACTURER (0x05) + +/* MsgVersion */ +#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00) +#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT (8) +#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF) +#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT (0) + +/* HeaderVersion */ +#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK (0xFF00) +#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT (8) +#define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF) +#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0) + +/* minimum depth for the Reply Descriptor Post Queue */ +#define MPI2_RDPQ_DEPTH_MIN (16) + + +/* IOCInit Reply message */ +typedef struct _MPI2_IOC_INIT_REPLY +{ + U8 WhoInit; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_IOC_INIT_REPLY, MPI2_POINTER PTR_MPI2_IOC_INIT_REPLY, + Mpi2IOCInitReply_t, MPI2_POINTER pMpi2IOCInitReply_t; + + +/**************************************************************************** +* IOCFacts message +****************************************************************************/ + +/* IOCFacts Request message */ +typedef struct _MPI2_IOC_FACTS_REQUEST +{ + U16 Reserved1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ +} MPI2_IOC_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_IOC_FACTS_REQUEST, + Mpi2IOCFactsRequest_t, MPI2_POINTER pMpi2IOCFactsRequest_t; + + +/* IOCFacts Reply message */ +typedef struct _MPI2_IOC_FACTS_REPLY +{ + U16 MsgVersion; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 HeaderVersion; /* 0x04 */ + U8 IOCNumber; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U16 IOCExceptions; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U8 MaxChainDepth; /* 0x14 */ + U8 WhoInit; /* 0x15 */ + U8 NumberOfPorts; /* 0x16 */ + U8 MaxMSIxVectors; /* 0x17 */ + U16 RequestCredit; /* 0x18 */ + U16 ProductID; /* 0x1A */ + U32 IOCCapabilities; /* 0x1C */ + MPI2_VERSION_UNION FWVersion; /* 0x20 */ + U16 IOCRequestFrameSize; /* 0x24 */ + U16 IOCMaxChainSegmentSize; /* 0x26 */ /* MPI 2.5 only; Reserved in MPI 2.0 */ + U16 MaxInitiators; /* 0x28 */ + U16 MaxTargets; /* 0x2A */ + U16 MaxSasExpanders; /* 0x2C */ + U16 MaxEnclosures; /* 0x2E */ + U16 ProtocolFlags; /* 0x30 */ + U16 HighPriorityCredit; /* 0x32 */ + U16 MaxReplyDescriptorPostQueueDepth; /* 0x34 */ + U8 ReplyFrameSize; /* 0x36 */ + U8 MaxVolumes; /* 0x37 */ + U16 MaxDevHandle; /* 0x38 */ + U16 MaxPersistentEntries; /* 0x3A */ + U16 MinDevHandle; /* 0x3C */ + U16 Reserved4; /* 0x3E */ +} MPI2_IOC_FACTS_REPLY, MPI2_POINTER PTR_MPI2_IOC_FACTS_REPLY, + Mpi2IOCFactsReply_t, MPI2_POINTER pMpi2IOCFactsReply_t; + +/* MsgVersion */ +#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00) +#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8) +#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF) +#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT (0) + +/* HeaderVersion */ +#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00) +#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT (8) +#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF) +#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0) + +/* IOCExceptions */ +#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100) + +#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0) +#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD (0x0000) +#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP (0x0020) +#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED (0x0040) +#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP (0x0060) + +#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010) +#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0008) +#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004) +#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) +#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001) + +/* defines for WhoInit field are after the IOCInit Request */ + +/* ProductID field uses MPI2_FW_HEADER_PID_ */ + +/* IOCCapabilities */ +#define MPI25_IOCFACTS_CAPABILITY_FAST_PATH_CAPABLE (0x00020000) +#define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY (0x00010000) +#define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX (0x00008000) +#define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR (0x00004000) +#define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000) +#define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000) +#define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800) +#define MPI2_IOCFACTS_CAPABILITY_MULTICAST (0x00000100) +#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET (0x00000080) +#define MPI2_IOCFACTS_CAPABILITY_EEDP (0x00000040) +#define MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020) +#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010) +#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008) +#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004) + +/* ProtocolFlags */ +#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001) +#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002) + + +/**************************************************************************** +* PortFacts message +****************************************************************************/ + +/* PortFacts Request message */ +typedef struct _MPI2_PORT_FACTS_REQUEST +{ + U16 Reserved1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 PortNumber; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ +} MPI2_PORT_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_PORT_FACTS_REQUEST, + Mpi2PortFactsRequest_t, MPI2_POINTER pMpi2PortFactsRequest_t; + +/* PortFacts Reply message */ +typedef struct _MPI2_PORT_FACTS_REPLY +{ + U16 Reserved1; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 PortNumber; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U8 Reserved5; /* 0x14 */ + U8 PortType; /* 0x15 */ + U16 Reserved6; /* 0x16 */ + U16 MaxPostedCmdBuffers; /* 0x18 */ + U16 Reserved7; /* 0x1A */ +} MPI2_PORT_FACTS_REPLY, MPI2_POINTER PTR_MPI2_PORT_FACTS_REPLY, + Mpi2PortFactsReply_t, MPI2_POINTER pMpi2PortFactsReply_t; + +/* PortType values */ +#define MPI2_PORTFACTS_PORTTYPE_INACTIVE (0x00) +#define MPI2_PORTFACTS_PORTTYPE_FC (0x10) +#define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20) +#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30) +#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31) + + +/**************************************************************************** +* PortEnable message +****************************************************************************/ + +/* PortEnable Request message */ +typedef struct _MPI2_PORT_ENABLE_REQUEST +{ + U16 Reserved1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 Reserved2; /* 0x04 */ + U8 PortFlags; /* 0x05 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ +} MPI2_PORT_ENABLE_REQUEST, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REQUEST, + Mpi2PortEnableRequest_t, MPI2_POINTER pMpi2PortEnableRequest_t; + + +/* PortEnable Reply message */ +typedef struct _MPI2_PORT_ENABLE_REPLY +{ + U16 Reserved1; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 Reserved2; /* 0x04 */ + U8 PortFlags; /* 0x05 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_PORT_ENABLE_REPLY, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REPLY, + Mpi2PortEnableReply_t, MPI2_POINTER pMpi2PortEnableReply_t; + + +/**************************************************************************** +* EventNotification message +****************************************************************************/ + +/* EventNotification Request message */ +#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS (4) + +typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST +{ + U16 Reserved1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 Reserved5; /* 0x0C */ + U32 Reserved6; /* 0x10 */ + U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */ + U16 SASBroadcastPrimitiveMasks; /* 0x24 */ + U16 SASNotifyPrimitiveMasks; /* 0x26 */ + U32 Reserved8; /* 0x28 */ +} MPI2_EVENT_NOTIFICATION_REQUEST, + MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST, + Mpi2EventNotificationRequest_t, MPI2_POINTER pMpi2EventNotificationRequest_t; + + +/* EventNotification Reply message */ +typedef struct _MPI2_EVENT_NOTIFICATION_REPLY +{ + U16 EventDataLength; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 AckRequired; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U16 Reserved3; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U16 Event; /* 0x14 */ + U16 Reserved4; /* 0x16 */ + U32 EventContext; /* 0x18 */ + U32 EventData[1]; /* 0x1C */ +} MPI2_EVENT_NOTIFICATION_REPLY, MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REPLY, + Mpi2EventNotificationReply_t, MPI2_POINTER pMpi2EventNotificationReply_t; + +/* AckRequired */ +#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00) +#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED (0x01) + +/* Event */ +#define MPI2_EVENT_LOG_DATA (0x0001) +#define MPI2_EVENT_STATE_CHANGE (0x0002) +#define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005) +#define MPI2_EVENT_EVENT_CHANGE (0x000A) +#define MPI2_EVENT_TASK_SET_FULL (0x000E) /* obsolete */ +#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F) +#define MPI2_EVENT_IR_OPERATION_STATUS (0x0014) +#define MPI2_EVENT_SAS_DISCOVERY (0x0016) +#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE (0x0017) +#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x0018) +#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019) +#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C) +#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D) +#define MPI2_EVENT_IR_VOLUME (0x001E) +#define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F) +#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020) +#define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021) +#define MPI2_EVENT_SAS_PHY_COUNTER (0x0022) +#define MPI2_EVENT_GPIO_INTERRUPT (0x0023) +#define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY (0x0024) +#define MPI2_EVENT_SAS_QUIESCE (0x0025) +#define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE (0x0026) +#define MPI2_EVENT_TEMP_THRESHOLD (0x0027) +#define MPI2_EVENT_HOST_MESSAGE (0x0028) + + +/* Log Entry Added Event data */ + +/* the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */ +#define MPI2_EVENT_DATA_LOG_DATA_LENGTH (0x1C) + +typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED +{ + U64 TimeStamp; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U16 LogSequence; /* 0x0C */ + U16 LogEntryQualifier; /* 0x0E */ + U8 VP_ID; /* 0x10 */ + U8 VF_ID; /* 0x11 */ + U16 Reserved2; /* 0x12 */ + U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH];/* 0x14 */ +} MPI2_EVENT_DATA_LOG_ENTRY_ADDED, + MPI2_POINTER PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED, + Mpi2EventDataLogEntryAdded_t, MPI2_POINTER pMpi2EventDataLogEntryAdded_t; + + +/* GPIO Interrupt Event data */ + +typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT +{ + U8 GPIONum; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ +} MPI2_EVENT_DATA_GPIO_INTERRUPT, + MPI2_POINTER PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT, + Mpi2EventDataGpioInterrupt_t, MPI2_POINTER pMpi2EventDataGpioInterrupt_t; + + +/* Temperature Threshold Event data */ + +typedef struct _MPI2_EVENT_DATA_TEMPERATURE +{ + U16 Status; /* 0x00 */ + U8 SensorNum; /* 0x02 */ + U8 Reserved1; /* 0x03 */ + U16 CurrentTemperature; /* 0x04 */ + U16 Reserved2; /* 0x06 */ + U32 Reserved3; /* 0x08 */ + U32 Reserved4; /* 0x0C */ +} MPI2_EVENT_DATA_TEMPERATURE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_TEMPERATURE, + Mpi2EventDataTemperature_t, MPI2_POINTER pMpi2EventDataTemperature_t; + +/* Temperature Threshold Event data Status bits */ +#define MPI2_EVENT_TEMPERATURE3_EXCEEDED (0x0008) +#define MPI2_EVENT_TEMPERATURE2_EXCEEDED (0x0004) +#define MPI2_EVENT_TEMPERATURE1_EXCEEDED (0x0002) +#define MPI2_EVENT_TEMPERATURE0_EXCEEDED (0x0001) + + +/* Host Message Event data */ + +typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE +{ + U8 SourceVF_ID; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U32 Reserved3; /* 0x04 */ + U32 HostData[1]; /* 0x08 */ +} MPI2_EVENT_DATA_HOST_MESSAGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_HOST_MESSAGE, + Mpi2EventDataHostMessage_t, MPI2_POINTER pMpi2EventDataHostMessage_t; + + +/* Hard Reset Received Event data */ + +typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED +{ + U8 Reserved1; /* 0x00 */ + U8 Port; /* 0x01 */ + U16 Reserved2; /* 0x02 */ +} MPI2_EVENT_DATA_HARD_RESET_RECEIVED, + MPI2_POINTER PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED, + Mpi2EventDataHardResetReceived_t, + MPI2_POINTER pMpi2EventDataHardResetReceived_t; + + +/* Task Set Full Event data */ +/* this event is obsolete */ + +typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL +{ + U16 DevHandle; /* 0x00 */ + U16 CurrentDepth; /* 0x02 */ +} MPI2_EVENT_DATA_TASK_SET_FULL, MPI2_POINTER PTR_MPI2_EVENT_DATA_TASK_SET_FULL, + Mpi2EventDataTaskSetFull_t, MPI2_POINTER pMpi2EventDataTaskSetFull_t; + + +/* SAS Device Status Change Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE +{ + U16 TaskTag; /* 0x00 */ + U8 ReasonCode; /* 0x02 */ + U8 Reserved1; /* 0x03 */ + U8 ASC; /* 0x04 */ + U8 ASCQ; /* 0x05 */ + U16 DevHandle; /* 0x06 */ + U32 Reserved2; /* 0x08 */ + U64 SASAddress; /* 0x0C */ + U8 LUN[8]; /* 0x14 */ +} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, + Mpi2EventDataSasDeviceStatusChange_t, + MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t; + +/* SAS Device Status Change Event data ReasonCode values */ +#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) +#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) +#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) +#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09) +#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) +#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) +#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) +#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) +#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E) +#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F) +#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10) +#define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY (0x11) +#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY (0x12) + + +/* Integrated RAID Operation Status Event data */ + +typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS +{ + U16 VolDevHandle; /* 0x00 */ + U16 Reserved1; /* 0x02 */ + U8 RAIDOperation; /* 0x04 */ + U8 PercentComplete; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U32 Resereved3; /* 0x08 */ +} MPI2_EVENT_DATA_IR_OPERATION_STATUS, + MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS, + Mpi2EventDataIrOperationStatus_t, + MPI2_POINTER pMpi2EventDataIrOperationStatus_t; + +/* Integrated RAID Operation Status Event data RAIDOperation values */ +#define MPI2_EVENT_IR_RAIDOP_RESYNC (0x00) +#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION (0x01) +#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK (0x02) +#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT (0x03) +#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT (0x04) + + +/* Integrated RAID Volume Event data */ + +typedef struct _MPI2_EVENT_DATA_IR_VOLUME +{ + U16 VolDevHandle; /* 0x00 */ + U8 ReasonCode; /* 0x02 */ + U8 Reserved1; /* 0x03 */ + U32 NewValue; /* 0x04 */ + U32 PreviousValue; /* 0x08 */ +} MPI2_EVENT_DATA_IR_VOLUME, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_VOLUME, + Mpi2EventDataIrVolume_t, MPI2_POINTER pMpi2EventDataIrVolume_t; + +/* Integrated RAID Volume Event data ReasonCode values */ +#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED (0x01) +#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED (0x02) +#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED (0x03) + + +/* Integrated RAID Physical Disk Event data */ + +typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK +{ + U16 Reserved1; /* 0x00 */ + U8 ReasonCode; /* 0x02 */ + U8 PhysDiskNum; /* 0x03 */ + U16 PhysDiskDevHandle; /* 0x04 */ + U16 Reserved2; /* 0x06 */ + U16 Slot; /* 0x08 */ + U16 EnclosureHandle; /* 0x0A */ + U32 NewValue; /* 0x0C */ + U32 PreviousValue; /* 0x10 */ +} MPI2_EVENT_DATA_IR_PHYSICAL_DISK, + MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK, + Mpi2EventDataIrPhysicalDisk_t, MPI2_POINTER pMpi2EventDataIrPhysicalDisk_t; + +/* Integrated RAID Physical Disk Event data ReasonCode values */ +#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED (0x01) +#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED (0x02) +#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED (0x03) + + +/* Integrated RAID Configuration Change List Event data */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumElements at runtime. + */ +#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT +#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1) +#endif + +typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT +{ + U16 ElementFlags; /* 0x00 */ + U16 VolDevHandle; /* 0x02 */ + U8 ReasonCode; /* 0x04 */ + U8 PhysDiskNum; /* 0x05 */ + U16 PhysDiskDevHandle; /* 0x06 */ +} MPI2_EVENT_IR_CONFIG_ELEMENT, MPI2_POINTER PTR_MPI2_EVENT_IR_CONFIG_ELEMENT, + Mpi2EventIrConfigElement_t, MPI2_POINTER pMpi2EventIrConfigElement_t; + +/* IR Configuration Change List Event data ElementFlags values */ +#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK (0x000F) +#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT (0x0000) +#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001) +#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT (0x0002) + +/* IR Configuration Change List Event data ReasonCode values */ +#define MPI2_EVENT_IR_CHANGE_RC_ADDED (0x01) +#define MPI2_EVENT_IR_CHANGE_RC_REMOVED (0x02) +#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE (0x03) +#define MPI2_EVENT_IR_CHANGE_RC_HIDE (0x04) +#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE (0x05) +#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED (0x06) +#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED (0x07) +#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED (0x08) +#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED (0x09) + +typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST +{ + U8 NumElements; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 Reserved2; /* 0x02 */ + U8 ConfigNum; /* 0x03 */ + U32 Flags; /* 0x04 */ + MPI2_EVENT_IR_CONFIG_ELEMENT ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT]; /* 0x08 */ +} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, + MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, + Mpi2EventDataIrConfigChangeList_t, + MPI2_POINTER pMpi2EventDataIrConfigChangeList_t; + +/* IR Configuration Change List Event data Flags values */ +#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG (0x00000001) + + +/* SAS Discovery Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY +{ + U8 Flags; /* 0x00 */ + U8 ReasonCode; /* 0x01 */ + U8 PhysicalPort; /* 0x02 */ + U8 Reserved1; /* 0x03 */ + U32 DiscoveryStatus; /* 0x04 */ +} MPI2_EVENT_DATA_SAS_DISCOVERY, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DISCOVERY, + Mpi2EventDataSasDiscovery_t, MPI2_POINTER pMpi2EventDataSasDiscovery_t; + +/* SAS Discovery Event data Flags values */ +#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE (0x02) +#define MPI2_EVENT_SAS_DISC_IN_PROGRESS (0x01) + +/* SAS Discovery Event data ReasonCode values */ +#define MPI2_EVENT_SAS_DISC_RC_STARTED (0x01) +#define MPI2_EVENT_SAS_DISC_RC_COMPLETED (0x02) + +/* SAS Discovery Event data DiscoveryStatus values */ +#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED (0x80000000) +#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED (0x40000000) +#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED (0x20000000) +#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) +#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR (0x08000000) +#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) +#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) +#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN (0x00002000) +#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) +#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE (0x00000800) +#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK (0x00000400) +#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR (0x00000100) +#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT (0x00000010) +#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS (0x00000004) +#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED (0x00000001) + + +/* SAS Broadcast Primitive Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE +{ + U8 PhyNum; /* 0x00 */ + U8 Port; /* 0x01 */ + U8 PortWidth; /* 0x02 */ + U8 Primitive; /* 0x03 */ +} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, + Mpi2EventDataSasBroadcastPrimitive_t, + MPI2_POINTER pMpi2EventDataSasBroadcastPrimitive_t; + +/* defines for the Primitive field */ +#define MPI2_EVENT_PRIMITIVE_CHANGE (0x01) +#define MPI2_EVENT_PRIMITIVE_SES (0x02) +#define MPI2_EVENT_PRIMITIVE_EXPANDER (0x03) +#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04) +#define MPI2_EVENT_PRIMITIVE_RESERVED3 (0x05) +#define MPI2_EVENT_PRIMITIVE_RESERVED4 (0x06) +#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07) +#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08) + + +/* SAS Notify Primitive Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE +{ + U8 PhyNum; /* 0x00 */ + U8 Port; /* 0x01 */ + U8 Reserved1; /* 0x02 */ + U8 Primitive; /* 0x03 */ +} MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, + Mpi2EventDataSasNotifyPrimitive_t, + MPI2_POINTER pMpi2EventDataSasNotifyPrimitive_t; + +/* defines for the Primitive field */ +#define MPI2_EVENT_NOTIFY_ENABLE_SPINUP (0x01) +#define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED (0x02) +#define MPI2_EVENT_NOTIFY_RESERVED1 (0x03) +#define MPI2_EVENT_NOTIFY_RESERVED2 (0x04) + + +/* SAS Initiator Device Status Change Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE +{ + U8 ReasonCode; /* 0x00 */ + U8 PhysicalPort; /* 0x01 */ + U16 DevHandle; /* 0x02 */ + U64 SASAddress; /* 0x04 */ +} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, + Mpi2EventDataSasInitDevStatusChange_t, + MPI2_POINTER pMpi2EventDataSasInitDevStatusChange_t; + +/* SAS Initiator Device Status Change event ReasonCode values */ +#define MPI2_EVENT_SAS_INIT_RC_ADDED (0x01) +#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02) + + +/* SAS Initiator Device Table Overflow Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW +{ + U16 MaxInit; /* 0x00 */ + U16 CurrentInit; /* 0x02 */ + U64 SASAddress; /* 0x04 */ +} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, + Mpi2EventDataSasInitTableOverflow_t, + MPI2_POINTER pMpi2EventDataSasInitTableOverflow_t; + + +/* SAS Topology Change List Event data */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumEntries at runtime. + */ +#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT +#define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1) +#endif + +typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY +{ + U16 AttachedDevHandle; /* 0x00 */ + U8 LinkRate; /* 0x02 */ + U8 PhyStatus; /* 0x03 */ +} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, MPI2_POINTER PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY, + Mpi2EventSasTopoPhyEntry_t, MPI2_POINTER pMpi2EventSasTopoPhyEntry_t; + +typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST +{ + U16 EnclosureHandle; /* 0x00 */ + U16 ExpanderDevHandle; /* 0x02 */ + U8 NumPhys; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U8 NumEntries; /* 0x08 */ + U8 StartPhyNum; /* 0x09 */ + U8 ExpStatus; /* 0x0A */ + U8 PhysicalPort; /* 0x0B */ + MPI2_EVENT_SAS_TOPO_PHY_ENTRY PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C*/ +} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, + Mpi2EventDataSasTopologyChangeList_t, + MPI2_POINTER pMpi2EventDataSasTopologyChangeList_t; + +/* values for the ExpStatus field */ +#define MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER (0x00) +#define MPI2_EVENT_SAS_TOPO_ES_ADDED (0x01) +#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02) +#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING (0x03) +#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04) + +/* defines for the LinkRate field */ +#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0) +#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4) +#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F) +#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT (0) + +#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00) +#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01) +#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02) +#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03) +#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04) +#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05) +#define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06) +#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08) +#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09) +#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A) +#define MPI25_EVENT_SAS_TOPO_LR_RATE_12_0 (0x0B) + +/* values for the PhyStatus field */ +#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80) +#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE (0x10) +/* values for the PhyStatus ReasonCode sub-field */ +#define MPI2_EVENT_SAS_TOPO_RC_MASK (0x0F) +#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED (0x01) +#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING (0x02) +#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED (0x03) +#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE (0x04) +#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING (0x05) + + +/* SAS Enclosure Device Status Change Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE +{ + U16 EnclosureHandle; /* 0x00 */ + U8 ReasonCode; /* 0x02 */ + U8 PhysicalPort; /* 0x03 */ + U64 EnclosureLogicalID; /* 0x04 */ + U16 NumSlots; /* 0x0C */ + U16 StartSlot; /* 0x0E */ + U32 PhyBits; /* 0x10 */ +} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, + Mpi2EventDataSasEnclDevStatusChange_t, + MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t; + +/* SAS Enclosure Device Status Change event ReasonCode values */ +#define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01) +#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02) + + +/* SAS PHY Counter Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER +{ + U64 TimeStamp; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U8 PhyEventCode; /* 0x0C */ + U8 PhyNum; /* 0x0D */ + U16 Reserved2; /* 0x0E */ + U32 PhyEventInfo; /* 0x10 */ + U8 CounterType; /* 0x14 */ + U8 ThresholdWindow; /* 0x15 */ + U8 TimeUnits; /* 0x16 */ + U8 Reserved3; /* 0x17 */ + U32 EventThreshold; /* 0x18 */ + U16 ThresholdFlags; /* 0x1C */ + U16 Reserved4; /* 0x1E */ +} MPI2_EVENT_DATA_SAS_PHY_COUNTER, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER, + Mpi2EventDataSasPhyCounter_t, MPI2_POINTER pMpi2EventDataSasPhyCounter_t; + +/* use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h for the PhyEventCode field */ + +/* use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h for the CounterType field */ + +/* use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h for the TimeUnits field */ + +/* use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h for the ThresholdFlags field */ + + +/* SAS Quiesce Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE +{ + U8 ReasonCode; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U32 Reserved3; /* 0x04 */ +} MPI2_EVENT_DATA_SAS_QUIESCE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_QUIESCE, + Mpi2EventDataSasQuiesce_t, MPI2_POINTER pMpi2EventDataSasQuiesce_t; + +/* SAS Quiesce Event data ReasonCode values */ +#define MPI2_EVENT_SAS_QUIESCE_RC_STARTED (0x01) +#define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED (0x02) + + +/* Host Based Discovery Phy Event data */ + +typedef struct _MPI2_EVENT_HBD_PHY_SAS +{ + U8 Flags; /* 0x00 */ + U8 NegotiatedLinkRate; /* 0x01 */ + U8 PhyNum; /* 0x02 */ + U8 PhysicalPort; /* 0x03 */ + U32 Reserved1; /* 0x04 */ + U8 InitialFrame[28]; /* 0x08 */ +} MPI2_EVENT_HBD_PHY_SAS, MPI2_POINTER PTR_MPI2_EVENT_HBD_PHY_SAS, + Mpi2EventHbdPhySas_t, MPI2_POINTER pMpi2EventHbdPhySas_t; + +/* values for the Flags field */ +#define MPI2_EVENT_HBD_SAS_FLAGS_FRAME_VALID (0x02) +#define MPI2_EVENT_HBD_SAS_FLAGS_SATA_FRAME (0x01) + +/* use MPI2_SAS_NEG_LINK_RATE_ defines from mpi2_cnfg.h for the NegotiatedLinkRate field */ + +typedef union _MPI2_EVENT_HBD_DESCRIPTOR +{ + MPI2_EVENT_HBD_PHY_SAS Sas; +} MPI2_EVENT_HBD_DESCRIPTOR, MPI2_POINTER PTR_MPI2_EVENT_HBD_DESCRIPTOR, + Mpi2EventHbdDescriptor_t, MPI2_POINTER pMpi2EventHbdDescriptor_t; + +typedef struct _MPI2_EVENT_DATA_HBD_PHY +{ + U8 DescriptorType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U32 Reserved3; /* 0x04 */ + MPI2_EVENT_HBD_DESCRIPTOR Descriptor; /* 0x08 */ +} MPI2_EVENT_DATA_HBD_PHY, MPI2_POINTER PTR_MPI2_EVENT_DATA_HBD_PHY, + Mpi2EventDataHbdPhy_t, MPI2_POINTER pMpi2EventDataMpi2EventDataHbdPhy_t; + +/* values for the DescriptorType field */ +#define MPI2_EVENT_HBD_DT_SAS (0x01) + + + +/**************************************************************************** +* EventAck message +****************************************************************************/ + +/* EventAck Request message */ +typedef struct _MPI2_EVENT_ACK_REQUEST +{ + U16 Reserved1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Event; /* 0x0C */ + U16 Reserved5; /* 0x0E */ + U32 EventContext; /* 0x10 */ +} MPI2_EVENT_ACK_REQUEST, MPI2_POINTER PTR_MPI2_EVENT_ACK_REQUEST, + Mpi2EventAckRequest_t, MPI2_POINTER pMpi2EventAckRequest_t; + + +/* EventAck Reply message */ +typedef struct _MPI2_EVENT_ACK_REPLY +{ + U16 Reserved1; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_EVENT_ACK_REPLY, MPI2_POINTER PTR_MPI2_EVENT_ACK_REPLY, + Mpi2EventAckReply_t, MPI2_POINTER pMpi2EventAckReply_t; + + +/**************************************************************************** +* SendHostMessage message +****************************************************************************/ + +/* SendHostMessage Request message */ +typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST +{ + U16 HostDataLength; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U8 Reserved4; /* 0x0C */ + U8 DestVF_ID; /* 0x0D */ + U16 Reserved5; /* 0x0E */ + U32 Reserved6; /* 0x10 */ + U32 Reserved7; /* 0x14 */ + U32 Reserved8; /* 0x18 */ + U32 Reserved9; /* 0x1C */ + U32 Reserved10; /* 0x20 */ + U32 HostData[1]; /* 0x24 */ +} MPI2_SEND_HOST_MESSAGE_REQUEST, + MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REQUEST, + Mpi2SendHostMessageRequest_t, MPI2_POINTER pMpi2SendHostMessageRequest_t; + + +/* SendHostMessage Reply message */ +typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY +{ + U16 HostDataLength; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_SEND_HOST_MESSAGE_REPLY, MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REPLY, + Mpi2SendHostMessageReply_t, MPI2_POINTER pMpi2SendHostMessageReply_t; + + +/**************************************************************************** +* FWDownload message +****************************************************************************/ + +/* MPI v2.0 FWDownload Request message */ +typedef struct _MPI2_FW_DOWNLOAD_REQUEST +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 TotalImageSize; /* 0x0C */ + U32 Reserved5; /* 0x10 */ + MPI2_MPI_SGE_UNION SGL; /* 0x14 */ +} MPI2_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REQUEST, + Mpi2FWDownloadRequest, MPI2_POINTER pMpi2FWDownloadRequest; + +#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01) + +#define MPI2_FW_DOWNLOAD_ITYPE_FW (0x01) +#define MPI2_FW_DOWNLOAD_ITYPE_BIOS (0x02) +#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06) +#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07) +#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08) +#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09) +#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A) +#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) +#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0) + +/* MPI v2.0 FWDownload TransactionContext Element */ +typedef struct _MPI2_FW_DOWNLOAD_TCSGE +{ + U8 Reserved1; /* 0x00 */ + U8 ContextSize; /* 0x01 */ + U8 DetailsLength; /* 0x02 */ + U8 Flags; /* 0x03 */ + U32 Reserved2; /* 0x04 */ + U32 ImageOffset; /* 0x08 */ + U32 ImageSize; /* 0x0C */ +} MPI2_FW_DOWNLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_TCSGE, + Mpi2FWDownloadTCSGE_t, MPI2_POINTER pMpi2FWDownloadTCSGE_t; + + +/* MPI v2.5 FWDownload Request message */ +typedef struct _MPI25_FW_DOWNLOAD_REQUEST +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 TotalImageSize; /* 0x0C */ + U32 Reserved5; /* 0x10 */ + U32 Reserved6; /* 0x14 */ + U32 ImageOffset; /* 0x18 */ + U32 ImageSize; /* 0x1C */ + MPI25_SGE_IO_UNION SGL; /* 0x20 */ +} MPI25_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI25_FW_DOWNLOAD_REQUEST, + Mpi25FWDownloadRequest, MPI2_POINTER pMpi25FWDownloadRequest; + + +/* FWDownload Reply message */ +typedef struct _MPI2_FW_DOWNLOAD_REPLY +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_FW_DOWNLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REPLY, + Mpi2FWDownloadReply_t, MPI2_POINTER pMpi2FWDownloadReply_t; + + +/**************************************************************************** +* FWUpload message +****************************************************************************/ + +/* MPI v2.0 FWUpload Request message */ +typedef struct _MPI2_FW_UPLOAD_REQUEST +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 Reserved5; /* 0x0C */ + U32 Reserved6; /* 0x10 */ + MPI2_MPI_SGE_UNION SGL; /* 0x14 */ +} MPI2_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REQUEST, + Mpi2FWUploadRequest_t, MPI2_POINTER pMpi2FWUploadRequest_t; + +#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT (0x00) +#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH (0x01) +#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) +#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) +#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING (0x06) +#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1 (0x07) +#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2 (0x08) +#define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09) +#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A) +#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) + +/* MPI v2.0 FWUpload TransactionContext Element */ +typedef struct _MPI2_FW_UPLOAD_TCSGE +{ + U8 Reserved1; /* 0x00 */ + U8 ContextSize; /* 0x01 */ + U8 DetailsLength; /* 0x02 */ + U8 Flags; /* 0x03 */ + U32 Reserved2; /* 0x04 */ + U32 ImageOffset; /* 0x08 */ + U32 ImageSize; /* 0x0C */ +} MPI2_FW_UPLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_UPLOAD_TCSGE, + Mpi2FWUploadTCSGE_t, MPI2_POINTER pMpi2FWUploadTCSGE_t; + + +/* MPI v2.5 FWUpload Request message */ +typedef struct _MPI25_FW_UPLOAD_REQUEST +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 Reserved5; /* 0x0C */ + U32 Reserved6; /* 0x10 */ + U32 Reserved7; /* 0x14 */ + U32 ImageOffset; /* 0x18 */ + U32 ImageSize; /* 0x1C */ + MPI25_SGE_IO_UNION SGL; /* 0x20 */ +} MPI25_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI25_FW_UPLOAD_REQUEST, + Mpi25FWUploadRequest_t, MPI2_POINTER pMpi25FWUploadRequest_t; + + +/* FWUpload Reply message */ +typedef struct _MPI2_FW_UPLOAD_REPLY +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 ActualImageSize; /* 0x14 */ +} MPI2_FW_UPLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REPLY, + Mpi2FWUploadReply_t, MPI2_POINTER pMPi2FWUploadReply_t; + + +/* FW Image Header */ +typedef struct _MPI2_FW_IMAGE_HEADER +{ + U32 Signature; /* 0x00 */ + U32 Signature0; /* 0x04 */ + U32 Signature1; /* 0x08 */ + U32 Signature2; /* 0x0C */ + MPI2_VERSION_UNION MPIVersion; /* 0x10 */ + MPI2_VERSION_UNION FWVersion; /* 0x14 */ + MPI2_VERSION_UNION NVDATAVersion; /* 0x18 */ + MPI2_VERSION_UNION PackageVersion; /* 0x1C */ + U16 VendorID; /* 0x20 */ + U16 ProductID; /* 0x22 */ + U16 ProtocolFlags; /* 0x24 */ + U16 Reserved26; /* 0x26 */ + U32 IOCCapabilities; /* 0x28 */ + U32 ImageSize; /* 0x2C */ + U32 NextImageHeaderOffset; /* 0x30 */ + U32 Checksum; /* 0x34 */ + U32 Reserved38; /* 0x38 */ + U32 Reserved3C; /* 0x3C */ + U32 Reserved40; /* 0x40 */ + U32 Reserved44; /* 0x44 */ + U32 Reserved48; /* 0x48 */ + U32 Reserved4C; /* 0x4C */ + U32 Reserved50; /* 0x50 */ + U32 Reserved54; /* 0x54 */ + U32 Reserved58; /* 0x58 */ + U32 Reserved5C; /* 0x5C */ + U32 Reserved60; /* 0x60 */ + U32 FirmwareVersionNameWhat; /* 0x64 */ + U8 FirmwareVersionName[32]; /* 0x68 */ + U32 VendorNameWhat; /* 0x88 */ + U8 VendorName[32]; /* 0x8C */ + U32 PackageNameWhat; /* 0x88 */ + U8 PackageName[32]; /* 0x8C */ + U32 ReservedD0; /* 0xD0 */ + U32 ReservedD4; /* 0xD4 */ + U32 ReservedD8; /* 0xD8 */ + U32 ReservedDC; /* 0xDC */ + U32 ReservedE0; /* 0xE0 */ + U32 ReservedE4; /* 0xE4 */ + U32 ReservedE8; /* 0xE8 */ + U32 ReservedEC; /* 0xEC */ + U32 ReservedF0; /* 0xF0 */ + U32 ReservedF4; /* 0xF4 */ + U32 ReservedF8; /* 0xF8 */ + U32 ReservedFC; /* 0xFC */ +} MPI2_FW_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_FW_IMAGE_HEADER, + Mpi2FWImageHeader_t, MPI2_POINTER pMpi2FWImageHeader_t; + +/* Signature field */ +#define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00) +#define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000) +#define MPI2_FW_HEADER_SIGNATURE (0xEA000000) + +/* Signature0 field */ +#define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04) +#define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A) + +/* Signature1 field */ +#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08) +#define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5) + +/* Signature2 field */ +#define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C) +#define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA) + + +/* defines for using the ProductID field */ +#define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000) +#define MPI2_FW_HEADER_PID_TYPE_SAS (0x2000) + +#define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00) +#define MPI2_FW_HEADER_PID_PROD_A (0x0000) +#define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI (0x0200) +#define MPI2_FW_HEADER_PID_PROD_IR_SCSI (0x0700) + + +#define MPI2_FW_HEADER_PID_FAMILY_MASK (0x00FF) +/* SAS ProductID Family bits */ +#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0013) +#define MPI2_FW_HEADER_PID_FAMILY_2208_SAS (0x0014) +#define MPI25_FW_HEADER_PID_FAMILY_3108_SAS (0x0021) + +/* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */ + +/* use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */ + + +#define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C) +#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30) +#define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64) + +#define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840) + +#define MPI2_FW_HEADER_SIZE (0x100) + + +/* Extended Image Header */ +typedef struct _MPI2_EXT_IMAGE_HEADER + +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U32 Checksum; /* 0x04 */ + U32 ImageSize; /* 0x08 */ + U32 NextImageHeaderOffset; /* 0x0C */ + U32 PackageVersion; /* 0x10 */ + U32 Reserved3; /* 0x14 */ + U32 Reserved4; /* 0x18 */ + U32 Reserved5; /* 0x1C */ + U8 IdentifyString[32]; /* 0x20 */ +} MPI2_EXT_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_EXT_IMAGE_HEADER, + Mpi2ExtImageHeader_t, MPI2_POINTER pMpi2ExtImageHeader_t; + +/* useful offsets */ +#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET (0x00) +#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET (0x08) +#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C) + +#define MPI2_EXT_IMAGE_HEADER_SIZE (0x40) + +/* defines for the ImageType field */ +#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) +#define MPI2_EXT_IMAGE_TYPE_FW (0x01) +#define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03) +#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04) +#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05) +#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06) +#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07) +#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08) + +#define MPI2_EXT_IMAGE_TYPE_MAX (MPI2_EXT_IMAGE_TYPE_MEGARAID) + + + +/* FLASH Layout Extended Image Data */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check RegionsPerLayout at runtime. + */ +#ifndef MPI2_FLASH_NUMBER_OF_REGIONS +#define MPI2_FLASH_NUMBER_OF_REGIONS (1) +#endif + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumberOfLayouts at runtime. + */ +#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS +#define MPI2_FLASH_NUMBER_OF_LAYOUTS (1) +#endif + +typedef struct _MPI2_FLASH_REGION +{ + U8 RegionType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U32 RegionOffset; /* 0x04 */ + U32 RegionSize; /* 0x08 */ + U32 Reserved3; /* 0x0C */ +} MPI2_FLASH_REGION, MPI2_POINTER PTR_MPI2_FLASH_REGION, + Mpi2FlashRegion_t, MPI2_POINTER pMpi2FlashRegion_t; + +typedef struct _MPI2_FLASH_LAYOUT +{ + U32 FlashSize; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Reserved2; /* 0x08 */ + U32 Reserved3; /* 0x0C */ + MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS];/* 0x10 */ +} MPI2_FLASH_LAYOUT, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT, + Mpi2FlashLayout_t, MPI2_POINTER pMpi2FlashLayout_t; + +typedef struct _MPI2_FLASH_LAYOUT_DATA +{ + U8 ImageRevision; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 SizeOfRegion; /* 0x02 */ + U8 Reserved2; /* 0x03 */ + U16 NumberOfLayouts; /* 0x04 */ + U16 RegionsPerLayout; /* 0x06 */ + U16 MinimumSectorAlignment; /* 0x08 */ + U16 Reserved3; /* 0x0A */ + U32 Reserved4; /* 0x0C */ + MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS];/* 0x10 */ +} MPI2_FLASH_LAYOUT_DATA, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT_DATA, + Mpi2FlashLayoutData_t, MPI2_POINTER pMpi2FlashLayoutData_t; + +/* defines for the RegionType field */ +#define MPI2_FLASH_REGION_UNUSED (0x00) +#define MPI2_FLASH_REGION_FIRMWARE (0x01) +#define MPI2_FLASH_REGION_BIOS (0x02) +#define MPI2_FLASH_REGION_NVDATA (0x03) +#define MPI2_FLASH_REGION_FIRMWARE_BACKUP (0x05) +#define MPI2_FLASH_REGION_MFG_INFORMATION (0x06) +#define MPI2_FLASH_REGION_CONFIG_1 (0x07) +#define MPI2_FLASH_REGION_CONFIG_2 (0x08) +#define MPI2_FLASH_REGION_MEGARAID (0x09) +#define MPI2_FLASH_REGION_INIT (0x0A) + +/* ImageRevision */ +#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00) + + + +/* Supported Devices Extended Image Data */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumberOfDevices at runtime. + */ +#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES +#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1) +#endif + +typedef struct _MPI2_SUPPORTED_DEVICE +{ + U16 DeviceID; /* 0x00 */ + U16 VendorID; /* 0x02 */ + U16 DeviceIDMask; /* 0x04 */ + U16 Reserved1; /* 0x06 */ + U8 LowPCIRev; /* 0x08 */ + U8 HighPCIRev; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U32 Reserved3; /* 0x0C */ +} MPI2_SUPPORTED_DEVICE, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICE, + Mpi2SupportedDevice_t, MPI2_POINTER pMpi2SupportedDevice_t; + +typedef struct _MPI2_SUPPORTED_DEVICES_DATA +{ + U8 ImageRevision; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 NumberOfDevices; /* 0x02 */ + U8 Reserved2; /* 0x03 */ + U32 Reserved3; /* 0x04 */ + MPI2_SUPPORTED_DEVICE SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES]; /* 0x08 */ +} MPI2_SUPPORTED_DEVICES_DATA, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICES_DATA, + Mpi2SupportedDevicesData_t, MPI2_POINTER pMpi2SupportedDevicesData_t; + +/* ImageRevision */ +#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION (0x00) + + +/* Init Extended Image Data */ + +typedef struct _MPI2_INIT_IMAGE_FOOTER + +{ + U32 BootFlags; /* 0x00 */ + U32 ImageSize; /* 0x04 */ + U32 Signature0; /* 0x08 */ + U32 Signature1; /* 0x0C */ + U32 Signature2; /* 0x10 */ + U32 ResetVector; /* 0x14 */ +} MPI2_INIT_IMAGE_FOOTER, MPI2_POINTER PTR_MPI2_INIT_IMAGE_FOOTER, + Mpi2InitImageFooter_t, MPI2_POINTER pMpi2InitImageFooter_t; + +/* defines for the BootFlags field */ +#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET (0x00) + +/* defines for the ImageSize field */ +#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET (0x04) + +/* defines for the Signature0 field */ +#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET (0x08) +#define MPI2_INIT_IMAGE_SIGNATURE0 (0x5AA55AEA) + +/* defines for the Signature1 field */ +#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET (0x0C) +#define MPI2_INIT_IMAGE_SIGNATURE1 (0xA55AEAA5) + +/* defines for the Signature2 field */ +#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET (0x10) +#define MPI2_INIT_IMAGE_SIGNATURE2 (0x5AEAA55A) + +/* Signature fields as individual bytes */ +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0 (0xEA) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1 (0x5A) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2 (0xA5) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3 (0x5A) + +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4 (0xA5) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5 (0xEA) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6 (0x5A) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7 (0xA5) + +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8 (0x5A) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9 (0xA5) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A (0xEA) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B (0x5A) + +/* defines for the ResetVector field */ +#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14) + + +/**************************************************************************** +* PowerManagementControl message +****************************************************************************/ + +/* PowerManagementControl Request message */ +typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST +{ + U8 Feature; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U8 Parameter1; /* 0x0C */ + U8 Parameter2; /* 0x0D */ + U8 Parameter3; /* 0x0E */ + U8 Parameter4; /* 0x0F */ + U32 Reserved5; /* 0x10 */ + U32 Reserved6; /* 0x14 */ +} MPI2_PWR_MGMT_CONTROL_REQUEST, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REQUEST, + Mpi2PwrMgmtControlRequest_t, MPI2_POINTER pMpi2PwrMgmtControlRequest_t; + +/* defines for the Feature field */ +#define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND (0x01) +#define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION (0x02) +#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK (0x03) +#define MPI2_PM_CONTROL_FEATURE_IOC_SPEED (0x04) +#define MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE (0x05) /* reserved in MPI 2.0 */ +#define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC (0x80) +#define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC (0xFF) + +/* parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */ +/* Parameter1 contains a PHY number */ +/* Parameter2 indicates power condition action using these defines */ +#define MPI2_PM_CONTROL_PARAM2_PARTIAL (0x01) +#define MPI2_PM_CONTROL_PARAM2_SLUMBER (0x02) +#define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT (0x03) +/* Parameter3 and Parameter4 are reserved */ + +/* parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION Feature */ +/* Parameter1 contains SAS port width modulation group number */ +/* Parameter2 indicates IOC action using these defines */ +#define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP (0x01) +#define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION (0x02) +#define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP (0x03) +/* Parameter3 indicates desired modulation level using these defines */ +#define MPI2_PM_CONTROL_PARAM3_25_PERCENT (0x00) +#define MPI2_PM_CONTROL_PARAM3_50_PERCENT (0x01) +#define MPI2_PM_CONTROL_PARAM3_75_PERCENT (0x02) +#define MPI2_PM_CONTROL_PARAM3_100_PERCENT (0x03) +/* Parameter4 is reserved */ + +/* parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */ +/* Parameter1 indicates desired PCIe link speed using these defines */ +#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS (0x00) +#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS (0x01) +#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS (0x02) +/* Parameter2 indicates desired PCIe link width using these defines */ +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1 (0x01) +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2 (0x02) +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4 (0x04) +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8 (0x08) +/* Parameter3 and Parameter4 are reserved */ + +/* parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */ +/* Parameter1 indicates desired IOC hardware clock speed using these defines */ +#define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED (0x01) +#define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED (0x02) +#define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED (0x04) +#define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED (0x08) +/* Parameter2, Parameter3, and Parameter4 are reserved */ + +/* parameter usage for the MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE Feature */ +/* Parameter1 indicates host action regarding global power management mode */ +#define MPI2_PM_CONTROL_PARAM1_TAKE_CONTROL (0x01) +#define MPI2_PM_CONTROL_PARAM1_CHANGE_GLOBAL_MODE (0x02) +#define MPI2_PM_CONTROL_PARAM1_RELEASE_CONTROL (0x03) +/* Parameter2 indicates the requested global power management mode */ +#define MPI2_PM_CONTROL_PARAM2_FULL_PWR_PERF (0x01) +#define MPI2_PM_CONTROL_PARAM2_REDUCED_PWR_PERF (0x08) +#define MPI2_PM_CONTROL_PARAM2_STANDBY (0x40) +/* Parameter3 and Parameter4 are reserved */ + + +/* PowerManagementControl Reply message */ +typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY +{ + U8 Feature; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_PWR_MGMT_CONTROL_REPLY, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REPLY, + Mpi2PwrMgmtControlReply_t, MPI2_POINTER pMpi2PwrMgmtControlReply_t; + + +#endif + diff --git a/source/lsi/mpi2_ra.h b/source/lsi/mpi2_ra.h new file mode 100755 index 0000000..d88cfd2 --- /dev/null +++ b/source/lsi/mpi2_ra.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2009 LSI Corporation. + * + * + * Name: mpi2_ra.h + * Title: MPI RAID Accelerator messages and structures + * Creation Date: April 13, 2009 + * + * mpi2_ra.h Version: 02.00.00 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 05-06-09 02.00.00 Initial version. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_RA_H +#define MPI2_RA_H + +/* generic structure for RAID Accelerator Control Block */ +typedef struct _MPI2_RAID_ACCELERATOR_CONTROL_BLOCK +{ + U32 Reserved[8]; /* 0x00 */ + U32 RaidAcceleratorCDB[1]; /* 0x20 */ +} MPI2_RAID_ACCELERATOR_CONTROL_BLOCK, + MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_CONTROL_BLOCK, + Mpi2RAIDAcceleratorControlBlock_t, + MPI2_POINTER pMpi2RAIDAcceleratorControlBlock_t; + + +/****************************************************************************** +* +* RAID Accelerator Messages +* +*******************************************************************************/ + +/* RAID Accelerator Request Message */ +typedef struct _MPI2_RAID_ACCELERATOR_REQUEST +{ + U16 Reserved0; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U64 RaidAcceleratorControlBlockAddress; /* 0x0C */ + U8 DmaEngineNumber; /* 0x14 */ + U8 Reserved4; /* 0x15 */ + U16 Reserved5; /* 0x16 */ + U32 Reserved6; /* 0x18 */ + U32 Reserved7; /* 0x1C */ + U32 Reserved8; /* 0x20 */ +} MPI2_RAID_ACCELERATOR_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_REQUEST, + Mpi2RAIDAcceleratorRequest_t, MPI2_POINTER pMpi2RAIDAcceleratorRequest_t; + + +/* RAID Accelerator Error Reply Message */ +typedef struct _MPI2_RAID_ACCELERATOR_REPLY +{ + U16 Reserved0; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 ProductSpecificData[3]; /* 0x14 */ +} MPI2_RAID_ACCELERATOR_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_REPLY, + Mpi2RAIDAcceleratorReply_t, MPI2_POINTER pMpi2RAIDAcceleratorReply_t; + + +#endif + + diff --git a/source/lsi/mpi2_raid.h b/source/lsi/mpi2_raid.h new file mode 100755 index 0000000..d33dd6b --- /dev/null +++ b/source/lsi/mpi2_raid.h @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2000-2010 LSI Corporation. + * + * + * Name: mpi2_raid.h + * Title: MPI Integrated RAID messages and structures + * Creation Date: April 26, 2007 + * + * mpi2_raid.h Version: 02.00.05 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 08-31-07 02.00.01 Modifications to RAID Action request and reply, + * including the Actions and ActionData. + * 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD. + * 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that + * the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT + * can be sized by the build environment. + * 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of + * VolumeCreationFlags and marked the old one as obsolete. + * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_RAID_H +#define MPI2_RAID_H + +/***************************************************************************** +* +* Integrated RAID Messages +* +*****************************************************************************/ + +/**************************************************************************** +* RAID Action messages +****************************************************************************/ + +/* ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */ +#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000) +#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001) + +/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */ + +/* ActionDataWord defines for use with MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */ +#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001) + +/* ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */ +typedef struct _MPI2_RAID_ACTION_RATE_DATA +{ + U8 RateToChange; /* 0x00 */ + U8 RateOrMode; /* 0x01 */ + U16 DataScrubDuration; /* 0x02 */ +} MPI2_RAID_ACTION_RATE_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_RATE_DATA, + Mpi2RaidActionRateData_t, MPI2_POINTER pMpi2RaidActionRateData_t; + +#define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00) +#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01) +#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02) + +/* ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */ +typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION +{ + U8 RAIDFunction; /* 0x00 */ + U8 Flags; /* 0x01 */ + U16 Reserved1; /* 0x02 */ +} MPI2_RAID_ACTION_START_RAID_FUNCTION, + MPI2_POINTER PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION, + Mpi2RaidActionStartRaidFunction_t, + MPI2_POINTER pMpi2RaidActionStartRaidFunction_t; + +/* defines for the RAIDFunction field */ +#define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00) +#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01) +#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02) + +/* defines for the Flags field */ +#define MPI2_RAID_ACTION_START_NEW (0x00) +#define MPI2_RAID_ACTION_START_RESUME (0x01) + +/* ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */ +typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION +{ + U8 RAIDFunction; /* 0x00 */ + U8 Flags; /* 0x01 */ + U16 Reserved1; /* 0x02 */ +} MPI2_RAID_ACTION_STOP_RAID_FUNCTION, + MPI2_POINTER PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION, + Mpi2RaidActionStopRaidFunction_t, + MPI2_POINTER pMpi2RaidActionStopRaidFunction_t; + +/* defines for the RAIDFunction field */ +#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00) +#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01) +#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02) + +/* defines for the Flags field */ +#define MPI2_RAID_ACTION_STOP_ABORT (0x00) +#define MPI2_RAID_ACTION_STOP_PAUSE (0x01) + +/* ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */ +typedef struct _MPI2_RAID_ACTION_HOT_SPARE +{ + U8 HotSparePool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 DevHandle; /* 0x02 */ +} MPI2_RAID_ACTION_HOT_SPARE, MPI2_POINTER PTR_MPI2_RAID_ACTION_HOT_SPARE, + Mpi2RaidActionHotSpare_t, MPI2_POINTER pMpi2RaidActionHotSpare_t; + +/* ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */ +typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE +{ + U8 Flags; /* 0x00 */ + U8 DeviceFirmwareUpdateModeTimeout; /* 0x01 */ + U16 Reserved1; /* 0x02 */ +} MPI2_RAID_ACTION_FW_UPDATE_MODE, + MPI2_POINTER PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE, + Mpi2RaidActionFwUpdateMode_t, MPI2_POINTER pMpi2RaidActionFwUpdateMode_t; + +/* ActionDataWord defines for use with MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */ +#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00) +#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01) + +typedef union _MPI2_RAID_ACTION_DATA +{ + U32 Word; + MPI2_RAID_ACTION_RATE_DATA Rates; + MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction; + MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction; + MPI2_RAID_ACTION_HOT_SPARE HotSpare; + MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode; +} MPI2_RAID_ACTION_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_DATA, + Mpi2RaidActionData_t, MPI2_POINTER pMpi2RaidActionData_t; + + +/* RAID Action Request Message */ +typedef struct _MPI2_RAID_ACTION_REQUEST +{ + U8 Action; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 VolDevHandle; /* 0x04 */ + U8 PhysDiskNum; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U32 Reserved3; /* 0x0C */ + MPI2_RAID_ACTION_DATA ActionDataWord; /* 0x10 */ + MPI2_SGE_SIMPLE_UNION ActionDataSGE; /* 0x14 */ +} MPI2_RAID_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACTION_REQUEST, + Mpi2RaidActionRequest_t, MPI2_POINTER pMpi2RaidActionRequest_t; + +/* RAID Action request Action values */ + +#define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01) +#define MPI2_RAID_ACTION_CREATE_VOLUME (0x02) +#define MPI2_RAID_ACTION_DELETE_VOLUME (0x03) +#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04) +#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05) +#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A) +#define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B) +#define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F) +#define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11) +#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15) +#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17) +#define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18) +#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19) +#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C) +#define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D) +#define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E) +#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20) +#define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21) +#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22) + + +/* RAID Volume Creation Structure */ + +/* + * The following define can be customized for the targeted product. + */ +#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS +#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1) +#endif + +typedef struct _MPI2_RAID_VOLUME_PHYSDISK +{ + U8 RAIDSetNum; /* 0x00 */ + U8 PhysDiskMap; /* 0x01 */ + U16 PhysDiskDevHandle; /* 0x02 */ +} MPI2_RAID_VOLUME_PHYSDISK, MPI2_POINTER PTR_MPI2_RAID_VOLUME_PHYSDISK, + Mpi2RaidVolumePhysDisk_t, MPI2_POINTER pMpi2RaidVolumePhysDisk_t; + +/* defines for the PhysDiskMap field */ +#define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01) +#define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02) + +typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT +{ + U8 NumPhysDisks; /* 0x00 */ + U8 VolumeType; /* 0x01 */ + U16 Reserved1; /* 0x02 */ + U32 VolumeCreationFlags; /* 0x04 */ + U32 VolumeSettings; /* 0x08 */ + U8 Reserved2; /* 0x0C */ + U8 ResyncRate; /* 0x0D */ + U16 DataScrubDuration; /* 0x0E */ + U64 VolumeMaxLBA; /* 0x10 */ + U32 StripeSize; /* 0x18 */ + U8 Name[16]; /* 0x1C */ + MPI2_RAID_VOLUME_PHYSDISK PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS];/* 0x2C */ +} MPI2_RAID_VOLUME_CREATION_STRUCT, + MPI2_POINTER PTR_MPI2_RAID_VOLUME_CREATION_STRUCT, + Mpi2RaidVolumeCreationStruct_t, MPI2_POINTER pMpi2RaidVolumeCreationStruct_t; + +/* use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */ + +/* defines for the VolumeCreationFlags field */ +#define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS (0x80000000) +#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x00000004) /* MPI 2.0 only */ +#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x00000002) +#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x00000001) +/* The following is an obsolete define. + * It must be shifted left 24 bits in order to set the proper bit. + */ +#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80) + + +/* RAID Online Capacity Expansion Structure */ + +typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION +{ + U32 Flags; /* 0x00 */ + U16 DevHandle0; /* 0x04 */ + U16 Reserved1; /* 0x06 */ + U16 DevHandle1; /* 0x08 */ + U16 Reserved2; /* 0x0A */ +} MPI2_RAID_ONLINE_CAPACITY_EXPANSION, + MPI2_POINTER PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION, + Mpi2RaidOnlineCapacityExpansion_t, + MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t; + + +/* RAID Volume Indicator Structure */ + +typedef struct _MPI2_RAID_VOL_INDICATOR +{ + U64 TotalBlocks; /* 0x00 */ + U64 BlocksRemaining; /* 0x08 */ + U32 Flags; /* 0x10 */ +} MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR, + Mpi2RaidVolIndicator_t, MPI2_POINTER pMpi2RaidVolIndicator_t; + +/* defines for RAID Volume Indicator Flags field */ +#define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F) +#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000) +#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001) +#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002) +#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003) +#define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004) + + +/* RAID Action Reply ActionData union */ +typedef union _MPI2_RAID_ACTION_REPLY_DATA +{ + U32 Word[5]; + MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator; + U16 VolDevHandle; + U8 VolumeState; + U8 PhysDiskNum; +} MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA, + Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t; + +/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */ + + +/* RAID Action Reply Message */ +typedef struct _MPI2_RAID_ACTION_REPLY +{ + U8 Action; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 VolDevHandle; /* 0x04 */ + U8 PhysDiskNum; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U16 Reserved3; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + MPI2_RAID_ACTION_REPLY_DATA ActionData; /* 0x14 */ +} MPI2_RAID_ACTION_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY, + Mpi2RaidActionReply_t, MPI2_POINTER pMpi2RaidActionReply_t; + + +#endif + diff --git a/source/lsi/mpi2_sas.h b/source/lsi/mpi2_sas.h new file mode 100755 index 0000000..d2482be --- /dev/null +++ b/source/lsi/mpi2_sas.h @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2000-2010 LSI Corporation. + * + * + * Name: mpi2_sas.h + * Title: MPI Serial Attached SCSI structures and definitions + * Creation Date: February 9, 2007 + * + * mpi2_sas.h Version: 02.00.xx + * + * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 + * prefix are for use only on MPI v2.5 products, and must not be used + * with MPI v2.0 products. Unless otherwise noted, names beginning with + * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit + * Control Request. + * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control + * Request. + * 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST + * to MPI2_SGE_IO_UNION since it supports chained SGLs. + * 05-12-10 02.00.04 Modified some comments. + * 08-11-10 02.00.05 Added NCQ operations to SAS IO Unit Control. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_SAS_H +#define MPI2_SAS_H + +/* + * Values for SASStatus. + */ +#define MPI2_SASSTATUS_SUCCESS (0x00) +#define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01) +#define MPI2_SASSTATUS_INVALID_FRAME (0x02) +#define MPI2_SASSTATUS_UTC_BAD_DEST (0x03) +#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04) +#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05) +#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06) +#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07) +#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08) +#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09) +#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A) +#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B) +#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C) +#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D) +#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E) +#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F) +#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10) +#define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11) +#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12) +#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13) +#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14) + + +/* + * Values for the SAS DeviceInfo field used in SAS Device Status Change Event + * data and SAS Configuration pages. + */ +#define MPI2_SAS_DEVICE_INFO_SEP (0x00004000) +#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) +#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) +#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) +#define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400) +#define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200) +#define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100) +#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080) +#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040) +#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020) +#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010) +#define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008) + +#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007) +#define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000) +#define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001) +#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002) +#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003) + + +/***************************************************************************** +* +* SAS Messages +* +*****************************************************************************/ + +/**************************************************************************** +* SMP Passthrough messages +****************************************************************************/ + +/* SMP Passthrough Request Message */ +typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST +{ + U8 PassthroughFlags; /* 0x00 */ + U8 PhysicalPort; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 RequestDataLength; /* 0x04 */ + U8 SGLFlags; /* 0x06 */ /* MPI v2.0 only. Reserved on MPI v2.5. */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U32 Reserved2; /* 0x0C */ + U64 SASAddress; /* 0x10 */ + U32 Reserved3; /* 0x18 */ + U32 Reserved4; /* 0x1C */ + MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */ /* MPI v2.5: IEEE Simple 64 elements only */ +} MPI2_SMP_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REQUEST, + Mpi2SmpPassthroughRequest_t, MPI2_POINTER pMpi2SmpPassthroughRequest_t; + +/* values for PassthroughFlags field */ +#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80) + +/* MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ + + +/* SMP Passthrough Reply Message */ +typedef struct _MPI2_SMP_PASSTHROUGH_REPLY +{ + U8 PassthroughFlags; /* 0x00 */ + U8 PhysicalPort; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 ResponseDataLength; /* 0x04 */ + U8 SGLFlags; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U8 Reserved2; /* 0x0C */ + U8 SASStatus; /* 0x0D */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 Reserved3; /* 0x14 */ + U8 ResponseData[4]; /* 0x18 */ +} MPI2_SMP_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REPLY, + Mpi2SmpPassthroughReply_t, MPI2_POINTER pMpi2SmpPassthroughReply_t; + +/* values for PassthroughFlags field */ +#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80) + +/* values for SASStatus field are at the top of this file */ + + +/**************************************************************************** +* SATA Passthrough messages +****************************************************************************/ + +/* SATA Passthrough Request Message */ +typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST +{ + U16 DevHandle; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 PassthroughFlags; /* 0x04 */ + U8 SGLFlags; /* 0x06 */ /* MPI v2.0 only. Reserved on MPI v2.5. */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U32 Reserved2; /* 0x0C */ + U32 Reserved3; /* 0x10 */ + U32 Reserved4; /* 0x14 */ + U32 DataLength; /* 0x18 */ + U8 CommandFIS[20]; /* 0x1C */ + MPI2_SGE_IO_UNION SGL; /* 0x30 */ /* MPI v2.5: IEEE 64 elements only */ +} MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST, + Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t; + +/* values for PassthroughFlags field */ +#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100) +#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020) +#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010) +#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004) +#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002) +#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001) + +/* MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ + + +/* SATA Passthrough Reply Message */ +typedef struct _MPI2_SATA_PASSTHROUGH_REPLY +{ + U16 DevHandle; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 PassthroughFlags; /* 0x04 */ + U8 SGLFlags; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U8 Reserved2; /* 0x0C */ + U8 SASStatus; /* 0x0D */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U8 StatusFIS[20]; /* 0x14 */ + U32 StatusControlRegisters; /* 0x28 */ + U32 TransferCount; /* 0x2C */ +} MPI2_SATA_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REPLY, + Mpi2SataPassthroughReply_t, MPI2_POINTER pMpi2SataPassthroughReply_t; + +/* values for SASStatus field are at the top of this file */ + + +/**************************************************************************** +* SAS IO Unit Control messages +****************************************************************************/ + +/* SAS IO Unit Control Request Message */ +typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST +{ + U8 Operation; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 DevHandle; /* 0x04 */ + U8 IOCParameter; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U8 PhyNum; /* 0x0E */ + U8 PrimFlags; /* 0x0F */ + U32 Primitive; /* 0x10 */ + U8 LookupMethod; /* 0x14 */ + U8 Reserved5; /* 0x15 */ + U16 SlotNumber; /* 0x16 */ + U64 LookupAddress; /* 0x18 */ + U32 IOCParameterValue; /* 0x20 */ + U32 Reserved7; /* 0x24 */ + U32 Reserved8; /* 0x28 */ +} MPI2_SAS_IOUNIT_CONTROL_REQUEST, + MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST, + Mpi2SasIoUnitControlRequest_t, MPI2_POINTER pMpi2SasIoUnitControlRequest_t; + +/* values for the Operation field */ +#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) +#define MPI2_SAS_OP_PHY_LINK_RESET (0x06) +#define MPI2_SAS_OP_PHY_HARD_RESET (0x07) +#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) +#define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A) +#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B) +#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C) +#define MPI2_SAS_OP_REMOVE_DEVICE (0x0D) +#define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E) +#define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F) +#define MPI25_SAS_OP_ENABLE_FP_DEVICE (0x10) +#define MPI25_SAS_OP_DISABLE_FP_DEVICE (0x11) +#define MPI25_SAS_OP_ENABLE_FP_ALL (0x12) +#define MPI25_SAS_OP_DISABLE_FP_ALL (0x13) +#define MPI2_SAS_OP_DEV_ENABLE_NCQ (0x14) +#define MPI2_SAS_OP_DEV_DISABLE_NCQ (0x15) +#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80) + +/* values for the PrimFlags field */ +#define MPI2_SAS_PRIMFLAGS_SINGLE (0x08) +#define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02) +#define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01) + +/* values for the LookupMethod field */ +#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01) +#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02) +#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03) + + +/* SAS IO Unit Control Reply Message */ +typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY +{ + U8 Operation; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 DevHandle; /* 0x04 */ + U8 IOCParameter; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_SAS_IOUNIT_CONTROL_REPLY, + MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY, + Mpi2SasIoUnitControlReply_t, MPI2_POINTER pMpi2SasIoUnitControlReply_t; + + +#endif + + diff --git a/source/lsi/mpi2_targ.h b/source/lsi/mpi2_targ.h new file mode 100755 index 0000000..42afc66 --- /dev/null +++ b/source/lsi/mpi2_targ.h @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2000-2010 LSI Corporation. + * + * + * Name: mpi2_targ.h + * Title: MPI Target mode messages and structures + * Creation Date: September 8, 2006 + * + * mpi2_targ.h Version: 02.00.xx + * + * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 + * prefix are for use only on MPI v2.5 products, and must not be used + * with MPI v2.0 products. Unless otherwise noted, names beginning with + * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 08-31-07 02.00.01 Added Command Buffer Data Location Address Space bits to + * BufferPostFlags field of CommandBufferPostBase Request. + * 02-29-08 02.00.02 Modified various names to make them 32-character unique. + * 10-02-08 02.00.03 Removed NextCmdBufferOffset from + * MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST. + * Target Status Send Request only takes a single SGE for + * response data. + * 02-10-10 02.00.04 Added comment to MPI2_TARGET_SSP_RSP_IU structure. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_TARG_H +#define MPI2_TARG_H + + +/****************************************************************************** +* +* SCSI Target Messages +* +*******************************************************************************/ + +/**************************************************************************** +* Target Command Buffer Post Base Request +****************************************************************************/ + +typedef struct _MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST +{ + U8 BufferPostFlags; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 TotalCmdBuffers; /* 0x04 */ + U8 Reserved; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U32 Reserved3; /* 0x0C */ + U16 CmdBufferLength; /* 0x10 */ + U16 Reserved4; /* 0x12 */ + U32 BaseAddressLow; /* 0x14 */ + U32 BaseAddressHigh; /* 0x18 */ +} MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST, + MPI2_POINTER PTR_MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST, + Mpi2TargetCmdBufferPostBaseRequest_t, + MPI2_POINTER pMpi2TargetCmdBufferPostBaseRequest_t; + +/* values for the BufferPostflags field */ +#define MPI2_CMD_BUF_POST_BASE_ADDRESS_SPACE_MASK (0x0C) +#define MPI2_CMD_BUF_POST_BASE_SYSTEM_ADDRESS_SPACE (0x00) +#define MPI2_CMD_BUF_POST_BASE_IOCDDR_ADDRESS_SPACE (0x04) +#define MPI2_CMD_BUF_POST_BASE_IOCPLB_ADDRESS_SPACE (0x08) +#define MPI2_CMD_BUF_POST_BASE_IOCPLBNTA_ADDRESS_SPACE (0x0C) + +#define MPI2_CMD_BUF_POST_BASE_FLAGS_AUTO_POST_ALL (0x01) + + +/**************************************************************************** +* Target Command Buffer Post List Request +****************************************************************************/ + +typedef struct _MPI2_TARGET_CMD_BUF_POST_LIST_REQUEST +{ + U16 Reserved; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 CmdBufferCount; /* 0x04 */ + U8 Reserved1; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U32 Reserved3; /* 0x0C */ + U16 IoIndex[2]; /* 0x10 */ +} MPI2_TARGET_CMD_BUF_POST_LIST_REQUEST, + MPI2_POINTER PTR_MPI2_TARGET_CMD_BUF_POST_LIST_REQUEST, + Mpi2TargetCmdBufferPostListRequest_t, + MPI2_POINTER pMpi2TargetCmdBufferPostListRequest_t; + +/**************************************************************************** +* Target Command Buffer Post Base List Reply +****************************************************************************/ + +typedef struct _MPI2_TARGET_BUF_POST_BASE_LIST_REPLY +{ + U8 Flags; /* 0x00 */ + U8 Reserved; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U16 IoIndex; /* 0x14 */ + U16 Reserved5; /* 0x16 */ + U32 Reserved6; /* 0x18 */ +} MPI2_TARGET_BUF_POST_BASE_LIST_REPLY, + MPI2_POINTER PTR_MPI2_TARGET_BUF_POST_BASE_LIST_REPLY, + Mpi2TargetCmdBufferPostBaseListReply_t, + MPI2_POINTER pMpi2TargetCmdBufferPostBaseListReply_t; + +/* Flags defines */ +#define MPI2_CMD_BUF_POST_REPLY_IOINDEX_VALID (0x01) + + +/**************************************************************************** +* Command Buffer Formats (with 16 byte CDB) +****************************************************************************/ + +typedef struct _MPI2_TARGET_SSP_CMD_BUFFER +{ + U8 FrameType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 InitiatorConnectionTag; /* 0x02 */ + U32 HashedSourceSASAddress; /* 0x04 */ + U16 Reserved2; /* 0x08 */ + U16 Flags; /* 0x0A */ + U32 Reserved3; /* 0x0C */ + U16 Tag; /* 0x10 */ + U16 TargetPortTransferTag; /* 0x12 */ + U32 DataOffset; /* 0x14 */ + /* COMMAND information unit starts here */ + U8 LogicalUnitNumber[8]; /* 0x18 */ + U8 Reserved4; /* 0x20 */ + U8 TaskAttribute; /* lower 3 bits */ /* 0x21 */ + U8 Reserved5; /* 0x22 */ + U8 AdditionalCDBLength; /* upper 5 bits */ /* 0x23 */ + U8 CDB[16]; /* 0x24 */ + /* Additional CDB bytes extend past the CDB field */ +} MPI2_TARGET_SSP_CMD_BUFFER, MPI2_POINTER PTR_MPI2_TARGET_SSP_CMD_BUFFER, + Mpi2TargetSspCmdBuffer, MPI2_POINTER pMp2iTargetSspCmdBuffer; + +typedef struct _MPI2_TARGET_SSP_TASK_BUFFER +{ + U8 FrameType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 InitiatorConnectionTag; /* 0x02 */ + U32 HashedSourceSASAddress; /* 0x04 */ + U16 Reserved2; /* 0x08 */ + U16 Flags; /* 0x0A */ + U32 Reserved3; /* 0x0C */ + U16 Tag; /* 0x10 */ + U16 TargetPortTransferTag; /* 0x12 */ + U32 DataOffset; /* 0x14 */ + /* TASK information unit starts here */ + U8 LogicalUnitNumber[8]; /* 0x18 */ + U16 Reserved4; /* 0x20 */ + U8 TaskManagementFunction; /* 0x22 */ + U8 Reserved5; /* 0x23 */ + U16 ManagedTaskTag; /* 0x24 */ + U16 Reserved6; /* 0x26 */ + U32 Reserved7; /* 0x28 */ + U32 Reserved8; /* 0x2C */ + U32 Reserved9; /* 0x30 */ +} MPI2_TARGET_SSP_TASK_BUFFER, MPI2_POINTER PTR_MPI2_TARGET_SSP_TASK_BUFFER, + Mpi2TargetSspTaskBuffer, MPI2_POINTER pMpi2TargetSspTaskBuffer; + +/* mask and shift for HashedSourceSASAddress field */ +#define MPI2_TARGET_HASHED_SAS_ADDRESS_MASK (0xFFFFFF00) +#define MPI2_TARGET_HASHED_SAS_ADDRESS_SHIFT (8) + + +/**************************************************************************** +* MPI v2.0 Target Assist Request +****************************************************************************/ + +typedef struct _MPI2_TARGET_ASSIST_REQUEST +{ + U8 Reserved1; /* 0x00 */ + U8 TargetAssistFlags; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 QueueTag; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 IoIndex; /* 0x0C */ + U16 InitiatorConnectionTag; /* 0x0E */ + U16 SGLFlags; /* 0x10 */ + U8 SequenceNumber; /* 0x12 */ + U8 Reserved4; /* 0x13 */ + U8 SGLOffset0; /* 0x14 */ + U8 SGLOffset1; /* 0x15 */ + U8 SGLOffset2; /* 0x16 */ + U8 SGLOffset3; /* 0x17 */ + U32 SkipCount; /* 0x18 */ + U32 DataLength; /* 0x1C */ + U32 BidirectionalDataLength; /* 0x20 */ + U16 IoFlags; /* 0x24 */ + U16 EEDPFlags; /* 0x26 */ + U32 EEDPBlockSize; /* 0x28 */ + U32 SecondaryReferenceTag; /* 0x2C */ + U16 SecondaryApplicationTag; /* 0x30 */ + U16 ApplicationTagTranslationMask; /* 0x32 */ + U32 PrimaryReferenceTag; /* 0x34 */ + U16 PrimaryApplicationTag; /* 0x38 */ + U16 PrimaryApplicationTagMask; /* 0x3A */ + U32 RelativeOffset; /* 0x3C */ + U32 Reserved5; /* 0x40 */ + U32 Reserved6; /* 0x44 */ + U32 Reserved7; /* 0x48 */ + U32 Reserved8; /* 0x4C */ + MPI2_SGE_IO_UNION SGL[1]; /* 0x50 */ +} MPI2_TARGET_ASSIST_REQUEST, MPI2_POINTER PTR_MPI2_TARGET_ASSIST_REQUEST, + Mpi2TargetAssistRequest_t, MPI2_POINTER pMpi2TargetAssistRequest_t; + +/* Target Assist TargetAssistFlags bits */ + +#define MPI2_TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER (0x80) +#define MPI2_TARGET_ASSIST_FLAGS_TLR (0x10) +#define MPI2_TARGET_ASSIST_FLAGS_RETRANSMIT (0x04) +#define MPI2_TARGET_ASSIST_FLAGS_AUTO_STATUS (0x02) +#define MPI2_TARGET_ASSIST_FLAGS_DATA_DIRECTION (0x01) + +/* Target Assist SGLFlags bits */ + +/* base values for Data Location Address Space */ +#define MPI2_TARGET_ASSIST_SGLFLAGS_ADDR_MASK (0x0C) +#define MPI2_TARGET_ASSIST_SGLFLAGS_SYSTEM_ADDR (0x00) +#define MPI2_TARGET_ASSIST_SGLFLAGS_IOCDDR_ADDR (0x04) +#define MPI2_TARGET_ASSIST_SGLFLAGS_IOCPLB_ADDR (0x08) +#define MPI2_TARGET_ASSIST_SGLFLAGS_PLBNTA_ADDR (0x0C) + +/* base values for Type */ +#define MPI2_TARGET_ASSIST_SGLFLAGS_TYPE_MASK (0x03) +#define MPI2_TARGET_ASSIST_SGLFLAGS_MPI_TYPE (0x00) +#define MPI2_TARGET_ASSIST_SGLFLAGS_32IEEE_TYPE (0x01) +#define MPI2_TARGET_ASSIST_SGLFLAGS_64IEEE_TYPE (0x02) + +/* shift values for each sub-field */ +#define MPI2_TARGET_ASSIST_SGLFLAGS_SGL3_SHIFT (12) +#define MPI2_TARGET_ASSIST_SGLFLAGS_SGL2_SHIFT (8) +#define MPI2_TARGET_ASSIST_SGLFLAGS_SGL1_SHIFT (4) +#define MPI2_TARGET_ASSIST_SGLFLAGS_SGL0_SHIFT (0) + +/* Target Assist IoFlags bits */ + +#define MPI2_TARGET_ASSIST_IOFLAGS_BIDIRECTIONAL (0x0800) +#define MPI2_TARGET_ASSIST_IOFLAGS_MULTICAST (0x0400) +#define MPI2_TARGET_ASSIST_IOFLAGS_RECEIVE_FIRST (0x0200) + +/* Target Assist EEDPFlags bits */ + +#define MPI2_TA_EEDPFLAGS_INC_PRI_REFTAG (0x8000) +#define MPI2_TA_EEDPFLAGS_INC_SEC_REFTAG (0x4000) +#define MPI2_TA_EEDPFLAGS_INC_PRI_APPTAG (0x2000) +#define MPI2_TA_EEDPFLAGS_INC_SEC_APPTAG (0x1000) + +#define MPI2_TA_EEDPFLAGS_CHECK_REFTAG (0x0400) +#define MPI2_TA_EEDPFLAGS_CHECK_APPTAG (0x0200) +#define MPI2_TA_EEDPFLAGS_CHECK_GUARD (0x0100) + +#define MPI2_TA_EEDPFLAGS_PASSTHRU_REFTAG (0x0008) + +#define MPI2_TA_EEDPFLAGS_MASK_OP (0x0007) +#define MPI2_TA_EEDPFLAGS_NOOP_OP (0x0000) +#define MPI2_TA_EEDPFLAGS_CHECK_OP (0x0001) +#define MPI2_TA_EEDPFLAGS_STRIP_OP (0x0002) +#define MPI2_TA_EEDPFLAGS_CHECK_REMOVE_OP (0x0003) +#define MPI2_TA_EEDPFLAGS_INSERT_OP (0x0004) +#define MPI2_TA_EEDPFLAGS_REPLACE_OP (0x0006) +#define MPI2_TA_EEDPFLAGS_CHECK_REGEN_OP (0x0007) + + +/**************************************************************************** +* MPI v2.5 Target Assist Request +****************************************************************************/ + +typedef struct _MPI25_TARGET_ASSIST_REQUEST +{ + U8 Reserved1; /* 0x00 */ + U8 TargetAssistFlags; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 QueueTag; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 IoIndex; /* 0x0C */ + U16 InitiatorConnectionTag; /* 0x0E */ + U8 DMAFlags; /* 0x10 */ + U8 Reserved9; /* 0x11 */ + U8 SequenceNumber; /* 0x12 */ + U8 Reserved4; /* 0x13 */ + U8 SGLOffset0; /* 0x14 */ + U8 SGLOffset1; /* 0x15 */ + U8 SGLOffset2; /* 0x16 */ + U8 SGLOffset3; /* 0x17 */ + U32 SkipCount; /* 0x18 */ + U32 DataLength; /* 0x1C */ + U32 BidirectionalDataLength; /* 0x20 */ + U16 IoFlags; /* 0x24 */ + U16 EEDPFlags; /* 0x26 */ + U16 EEDPBlockSize; /* 0x28 */ + U16 Reserved10; /* 0x2A */ + U32 SecondaryReferenceTag; /* 0x2C */ + U16 SecondaryApplicationTag; /* 0x30 */ + U16 ApplicationTagTranslationMask; /* 0x32 */ + U32 PrimaryReferenceTag; /* 0x34 */ + U16 PrimaryApplicationTag; /* 0x38 */ + U16 PrimaryApplicationTagMask; /* 0x3A */ + U32 RelativeOffset; /* 0x3C */ + U32 Reserved5; /* 0x40 */ + U32 Reserved6; /* 0x44 */ + U32 Reserved7; /* 0x48 */ + U32 Reserved8; /* 0x4C */ + MPI25_SGE_IO_UNION SGL; /* 0x50 */ +} MPI25_TARGET_ASSIST_REQUEST, MPI2_POINTER PTR_MPI25_TARGET_ASSIST_REQUEST, + Mpi25TargetAssistRequest_t, MPI2_POINTER pMpi25TargetAssistRequest_t; + +/* use MPI2_TARGET_ASSIST_FLAGS_ defines for the Flags field */ + +/* Defines for the DMAFlags field + * Each setting affects 4 SGLS, from SGL0 to SGL3. + * D = Data + * C = Cache DIF + * I = Interleaved + * H = Host DIF + */ +#define MPI25_TA_DMAFLAGS_OP_MASK (0x0F) +#define MPI25_TA_DMAFLAGS_OP_D_D_D_D (0x00) +#define MPI25_TA_DMAFLAGS_OP_D_D_D_C (0x01) +#define MPI25_TA_DMAFLAGS_OP_D_D_D_I (0x02) +#define MPI25_TA_DMAFLAGS_OP_D_D_C_C (0x03) +#define MPI25_TA_DMAFLAGS_OP_D_D_C_I (0x04) +#define MPI25_TA_DMAFLAGS_OP_D_D_I_I (0x05) +#define MPI25_TA_DMAFLAGS_OP_D_C_C_C (0x06) +#define MPI25_TA_DMAFLAGS_OP_D_C_C_I (0x07) +#define MPI25_TA_DMAFLAGS_OP_D_C_I_I (0x08) +#define MPI25_TA_DMAFLAGS_OP_D_I_I_I (0x09) +#define MPI25_TA_DMAFLAGS_OP_D_H_D_D (0x0A) +#define MPI25_TA_DMAFLAGS_OP_D_H_D_C (0x0B) +#define MPI25_TA_DMAFLAGS_OP_D_H_D_I (0x0C) +#define MPI25_TA_DMAFLAGS_OP_D_H_C_C (0x0D) +#define MPI25_TA_DMAFLAGS_OP_D_H_C_I (0x0E) +#define MPI25_TA_DMAFLAGS_OP_D_H_I_I (0x0F) + +/* defines for the IoFlags field */ +#define MPI25_TARGET_ASSIST_IOFLAGS_BIDIRECTIONAL (0x0800) +#define MPI25_TARGET_ASSIST_IOFLAGS_RECEIVE_FIRST (0x0200) + +/* defines for the EEDPFlags field */ +#define MPI25_TA_EEDPFLAGS_INC_PRI_REFTAG (0x8000) +#define MPI25_TA_EEDPFLAGS_INC_SEC_REFTAG (0x4000) +#define MPI25_TA_EEDPFLAGS_INC_PRI_APPTAG (0x2000) +#define MPI25_TA_EEDPFLAGS_INC_SEC_APPTAG (0x1000) + +#define MPI25_TA_EEDPFLAGS_CHECK_REFTAG (0x0400) +#define MPI25_TA_EEDPFLAGS_CHECK_APPTAG (0x0200) +#define MPI25_TA_EEDPFLAGS_CHECK_GUARD (0x0100) + +#define MPI25_TA_EEDPFLAGS_ESCAPE_MODE_MASK (0x00C0) +#define MPI25_TA_EEDPFLAGS_COMPATIBLE_MODE (0x0000) +#define MPI25_TA_EEDPFLAGS_DO_NOT_DISABLE_MODE (0x0040) +#define MPI25_TA_EEDPFLAGS_APPTAG_DISABLE_MODE (0x0080) +#define MPI25_TA_EEDPFLAGS_APPTAG_REFTAG_DISABLE_MODE (0x00C0) + +#define MPI25_TA_EEDPFLAGS_HOST_GUARD_METHOD_MASK (0x0030) +#define MPI25_TA_EEDPFLAGS_T10_CRC_HOST_GUARD (0x0000) +#define MPI25_TA_EEDPFLAGS_IP_CHKSUM_HOST_GUARD (0x0010) + +#define MPI25_TA_EEDPFLAGS_PASSTHRU_REFTAG (0x0008) + +#define MPI25_TA_EEDPFLAGS_MASK_OP (0x0007) +#define MPI25_TA_EEDPFLAGS_NOOP_OP (0x0000) +#define MPI25_TA_EEDPFLAGS_CHECK_OP (0x0001) +#define MPI25_TA_EEDPFLAGS_STRIP_OP (0x0002) +#define MPI25_TA_EEDPFLAGS_CHECK_REMOVE_OP (0x0003) +#define MPI25_TA_EEDPFLAGS_INSERT_OP (0x0004) +#define MPI25_TA_EEDPFLAGS_REPLACE_OP (0x0006) +#define MPI25_TA_EEDPFLAGS_CHECK_REGEN_OP (0x0007) + + +/**************************************************************************** +* Target Status Send Request +****************************************************************************/ + +typedef struct _MPI2_TARGET_STATUS_SEND_REQUEST +{ + U8 Reserved1; /* 0x00 */ + U8 StatusFlags; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 QueueTag; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 IoIndex; /* 0x0C */ + U16 InitiatorConnectionTag; /* 0x0E */ + U16 SGLFlags; /* 0x10 */ /* MPI v2.0 only. Reserved on MPI v2.5. */ + U16 Reserved4; /* 0x12 */ + U8 SGLOffset0; /* 0x14 */ + U8 Reserved5; /* 0x15 */ + U16 Reserved6; /* 0x16 */ + U32 Reserved7; /* 0x18 */ + U32 Reserved8; /* 0x1C */ + MPI2_SIMPLE_SGE_UNION StatusDataSGE; /* 0x20 */ /* MPI v2.5: This must be an IEEE Simple Element 64. */ +} MPI2_TARGET_STATUS_SEND_REQUEST, + MPI2_POINTER PTR_MPI2_TARGET_STATUS_SEND_REQUEST, + Mpi2TargetStatusSendRequest_t, MPI2_POINTER pMpi2TargetStatusSendRequest_t; + +/* Target Status Send StatusFlags bits */ + +#define MPI2_TSS_FLAGS_REPOST_CMD_BUFFER (0x80) +#define MPI2_TSS_FLAGS_RETRANSMIT (0x04) +#define MPI2_TSS_FLAGS_AUTO_GOOD_STATUS (0x01) + +/* Target Status Send SGLFlags bits - MPI v2.0 only */ +/* Data Location Address Space */ +#define MPI2_TSS_SGLFLAGS_ADDR_MASK (0x0C) +#define MPI2_TSS_SGLFLAGS_SYSTEM_ADDR (0x00) +#define MPI2_TSS_SGLFLAGS_IOCDDR_ADDR (0x04) +#define MPI2_TSS_SGLFLAGS_IOCPLB_ADDR (0x08) +#define MPI2_TSS_SGLFLAGS_IOCPLBNTA_ADDR (0x0C) +/* Type */ +#define MPI2_TSS_SGLFLAGS_TYPE_MASK (0x03) +#define MPI2_TSS_SGLFLAGS_MPI_TYPE (0x00) +#define MPI2_TSS_SGLFLAGS_IEEE32_TYPE (0x01) +#define MPI2_TSS_SGLFLAGS_IEEE64_TYPE (0x02) + + + +/* + * NOTE: The SSP status IU is big-endian. When used on a little-endian system, + * this structure properly orders the bytes. + */ +typedef struct _MPI2_TARGET_SSP_RSP_IU +{ + U32 Reserved0[6]; /* reserved for SSP header */ /* 0x00 */ + + /* start of RESPONSE information unit */ + U32 Reserved1; /* 0x18 */ + U32 Reserved2; /* 0x1C */ + U16 Reserved3; /* 0x20 */ + U8 DataPres; /* lower 2 bits */ /* 0x22 */ + U8 Status; /* 0x23 */ + U32 Reserved4; /* 0x24 */ + U32 SenseDataLength; /* 0x28 */ + U32 ResponseDataLength; /* 0x2C */ + + /* start of Response or Sense Data (size may vary dynamically) */ + U8 ResponseSenseData[4]; /* 0x30 */ +} MPI2_TARGET_SSP_RSP_IU, MPI2_POINTER PTR_MPI2_TARGET_SSP_RSP_IU, + Mpi2TargetSspRspIu_t, MPI2_POINTER pMpi2TargetSspRspIu_t; + + +/**************************************************************************** +* Target Standard Reply - used with Target Assist or Target Status Send +****************************************************************************/ + +typedef struct _MPI2_TARGET_STANDARD_REPLY +{ + U16 Reserved; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U16 IoIndex; /* 0x14 */ + U16 Reserved5; /* 0x16 */ + U32 TransferCount; /* 0x18 */ + U32 BidirectionalTransferCount; /* 0x1C */ +} MPI2_TARGET_STANDARD_REPLY, MPI2_POINTER PTR_MPI2_TARGET_STANDARD_REPLY, + Mpi2TargetErrorReply_t, MPI2_POINTER pMpi2TargetErrorReply_t; + + +/**************************************************************************** +* Target Mode Abort Request +****************************************************************************/ + +typedef struct _MPI2_TARGET_MODE_ABORT_REQUEST +{ + U8 AbortType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 IoIndexToAbort; /* 0x0C */ + U16 Reserved6; /* 0x0E */ + U32 MidToAbort; /* 0x10 */ +} MPI2_TARGET_MODE_ABORT, MPI2_POINTER PTR_MPI2_TARGET_MODE_ABORT, + Mpi2TargetModeAbort_t, MPI2_POINTER pMpi2TargetModeAbort_t; + +/* Target Mode Abort AbortType values */ + +#define MPI2_TARGET_MODE_ABORT_ALL_CMD_BUFFERS (0x00) +#define MPI2_TARGET_MODE_ABORT_ALL_IO (0x01) +#define MPI2_TARGET_MODE_ABORT_EXACT_IO (0x02) +#define MPI2_TARGET_MODE_ABORT_EXACT_IO_REQUEST (0x03) +#define MPI2_TARGET_MODE_ABORT_IO_REQUEST_AND_IO (0x04) + + +/**************************************************************************** +* Target Mode Abort Reply +****************************************************************************/ + +typedef struct _MPI2_TARGET_MODE_ABORT_REPLY +{ + U16 Reserved; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 AbortCount; /* 0x14 */ +} MPI2_TARGET_MODE_ABORT_REPLY, MPI2_POINTER PTR_MPI2_TARGET_MODE_ABORT_REPLY, + Mpi2TargetModeAbortReply_t, MPI2_POINTER pMpi2TargetModeAbortReply_t; + + +#endif + diff --git a/source/lsi/mpi2_tool.h b/source/lsi/mpi2_tool.h new file mode 100755 index 0000000..41c546e --- /dev/null +++ b/source/lsi/mpi2_tool.h @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2000-2010 LSI Corporation. + * + * + * Name: mpi2_tool.h + * Title: MPI diagnostic tool structures and definitions + * Creation Date: March 26, 2007 + * + * mpi2_tool.h Version: 02.00.06 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release + * structures and defines. + * 02-29-08 02.00.02 Modified various names to make them 32-character unique. + * 05-06-09 02.00.03 Added ISTWI Read Write Tool and Diagnostic CLI Tool. + * 07-30-09 02.00.04 Added ExtendedType field to DiagnosticBufferPost request + * and reply messages. + * Added MPI2_DIAG_BUF_TYPE_EXTENDED. + * Incremented MPI2_DIAG_BUF_TYPE_COUNT. + * 05-12-10 02.00.05 Added Diagnostic Data Upload tool. + * 08-11-10 02.00.06 Added defines that were missing for Diagnostic Buffer + * Post Request. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_TOOL_H +#define MPI2_TOOL_H + +/***************************************************************************** +* +* Toolbox Messages +* +*****************************************************************************/ + +/* defines for the Tools */ +#define MPI2_TOOLBOX_CLEAN_TOOL (0x00) +#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01) +#define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02) +#define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03) +#define MPI2_TOOLBOX_BEACON_TOOL (0x05) +#define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL (0x06) + + +/**************************************************************************** +* Toolbox reply +****************************************************************************/ + +typedef struct _MPI2_TOOLBOX_REPLY +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_TOOLBOX_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_REPLY, + Mpi2ToolboxReply_t, MPI2_POINTER pMpi2ToolboxReply_t; + + +/**************************************************************************** +* Toolbox Clean Tool request +****************************************************************************/ + +typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 Flags; /* 0x0C */ + } MPI2_TOOLBOX_CLEAN_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_CLEAN_REQUEST, + Mpi2ToolboxCleanRequest_t, MPI2_POINTER pMpi2ToolboxCleanRequest_t; + +/* values for the Flags field */ +#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000) +#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000) +#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000) +#define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000) +#define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000) +#define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000) +#define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000) +#define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004) +#define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002) +#define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001) + + +/**************************************************************************** +* Toolbox Memory Move request +****************************************************************************/ + +typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + MPI2_SGE_SIMPLE_UNION SGL; /* 0x0C */ +} MPI2_TOOLBOX_MEM_MOVE_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST, + Mpi2ToolboxMemMoveRequest_t, MPI2_POINTER pMpi2ToolboxMemMoveRequest_t; + + +/**************************************************************************** +* Toolbox Diagnostic Data Upload request +****************************************************************************/ + +typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U8 SGLFlags; /* 0x0C */ + U8 Reserved5; /* 0x0D */ + U16 Reserved6; /* 0x0E */ + U32 Flags; /* 0x10 */ + U32 DataLength; /* 0x14 */ + MPI2_SGE_SIMPLE_UNION SGL; /* 0x18 */ +} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, + MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, + Mpi2ToolboxDiagDataUploadRequest_t, + MPI2_POINTER pMpi2ToolboxDiagDataUploadRequest_t; + +/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ + + +typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER +{ + U32 DiagDataLength; /* 00h */ + U8 FormatCode; /* 04h */ + U8 Reserved1; /* 05h */ + U16 Reserved2; /* 06h */ +} MPI2_DIAG_DATA_UPLOAD_HEADER, MPI2_POINTER PTR_MPI2_DIAG_DATA_UPLOAD_HEADER, + Mpi2DiagDataUploadHeader_t, MPI2_POINTER pMpi2DiagDataUploadHeader_t; + + +/**************************************************************************** +* Toolbox ISTWI Read Write Tool +****************************************************************************/ + +/* Toolbox ISTWI Read Write Tool request message */ +typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 Reserved5; /* 0x0C */ + U32 Reserved6; /* 0x10 */ + U8 DevIndex; /* 0x14 */ + U8 Action; /* 0x15 */ + U8 SGLFlags; /* 0x16 */ + U8 Reserved7; /* 0x17 */ + U16 TxDataLength; /* 0x18 */ + U16 RxDataLength; /* 0x1A */ + U32 Reserved8; /* 0x1C */ + U32 Reserved9; /* 0x20 */ + U32 Reserved10; /* 0x24 */ + U32 Reserved11; /* 0x28 */ + U32 Reserved12; /* 0x2C */ + MPI2_SGE_SIMPLE_UNION SGL; /* 0x30 */ +} MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST, + MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST, + Mpi2ToolboxIstwiReadWriteRequest_t, + MPI2_POINTER pMpi2ToolboxIstwiReadWriteRequest_t; + +/* values for the Action field */ +#define MPI2_TOOL_ISTWI_ACTION_READ_DATA (0x01) +#define MPI2_TOOL_ISTWI_ACTION_WRITE_DATA (0x02) +#define MPI2_TOOL_ISTWI_ACTION_SEQUENCE (0x03) +#define MPI2_TOOL_ISTWI_ACTION_RESERVE_BUS (0x10) +#define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS (0x11) +#define MPI2_TOOL_ISTWI_ACTION_RESET (0x12) + +/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ + + +/* Toolbox ISTWI Read Write Tool reply message */ +typedef struct _MPI2_TOOLBOX_ISTWI_REPLY +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U8 DevIndex; /* 0x14 */ + U8 Action; /* 0x15 */ + U8 IstwiStatus; /* 0x16 */ + U8 Reserved6; /* 0x17 */ + U16 TxDataCount; /* 0x18 */ + U16 RxDataCount; /* 0x1A */ +} MPI2_TOOLBOX_ISTWI_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_REPLY, + Mpi2ToolboxIstwiReply_t, MPI2_POINTER pMpi2ToolboxIstwiReply_t; + + +/**************************************************************************** +* Toolbox Beacon Tool request +****************************************************************************/ + +typedef struct _MPI2_TOOLBOX_BEACON_REQUEST +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U8 Reserved5; /* 0x0C */ + U8 PhysicalPort; /* 0x0D */ + U8 Reserved6; /* 0x0E */ + U8 Flags; /* 0x0F */ +} MPI2_TOOLBOX_BEACON_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_BEACON_REQUEST, + Mpi2ToolboxBeaconRequest_t, MPI2_POINTER pMpi2ToolboxBeaconRequest_t; + +/* values for the Flags field */ +#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF (0x00) +#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01) + + +/**************************************************************************** +* Toolbox Diagnostic CLI Tool +****************************************************************************/ + +#define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH (0x5C) + +/* Toolbox Diagnostic CLI Tool request message */ +typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U8 SGLFlags; /* 0x0C */ + U8 Reserved5; /* 0x0D */ + U16 Reserved6; /* 0x0E */ + U32 DataLength; /* 0x10 */ + U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH]; /* 0x14 */ + MPI2_SGE_SIMPLE_UNION SGL; /* 0x70 */ +} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, + MPI2_POINTER PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, + Mpi2ToolboxDiagnosticCliRequest_t, + MPI2_POINTER pMpi2ToolboxDiagnosticCliRequest_t; + +/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ + + +/* Toolbox Diagnostic CLI Tool reply message */ +typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 ReturnedDataLength; /* 0x14 */ +} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY, + MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_CLI_REPLY, + Mpi2ToolboxDiagnosticCliReply_t, + MPI2_POINTER pMpi2ToolboxDiagnosticCliReply_t; + + +/***************************************************************************** +* +* Diagnostic Buffer Messages +* +*****************************************************************************/ + + +/**************************************************************************** +* Diagnostic Buffer Post request +****************************************************************************/ + +typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST +{ + U8 ExtendedType; /* 0x00 */ + U8 BufferType; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U64 BufferAddress; /* 0x0C */ + U32 BufferLength; /* 0x14 */ + U32 Reserved5; /* 0x18 */ + U32 Reserved6; /* 0x1C */ + U32 Flags; /* 0x20 */ + U32 ProductSpecific[23]; /* 0x24 */ +} MPI2_DIAG_BUFFER_POST_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REQUEST, + Mpi2DiagBufferPostRequest_t, MPI2_POINTER pMpi2DiagBufferPostRequest_t; + +/* values for the ExtendedType field */ +#define MPI2_DIAG_EXTENDED_TYPE_UTILIZATION (0x02) + +/* values for the BufferType field */ +#define MPI2_DIAG_BUF_TYPE_TRACE (0x00) +#define MPI2_DIAG_BUF_TYPE_SNAPSHOT (0x01) +#define MPI2_DIAG_BUF_TYPE_EXTENDED (0x02) +/* count of the number of buffer types */ +#define MPI2_DIAG_BUF_TYPE_COUNT (0x03) + +/* values for the Flags field */ +#define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL (0x00000002) /* for MPI v2.0 products only */ +#define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE (0x00000001) + + +/**************************************************************************** +* Diagnostic Buffer Post reply +****************************************************************************/ + +typedef struct _MPI2_DIAG_BUFFER_POST_REPLY +{ + U8 ExtendedType; /* 0x00 */ + U8 BufferType; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 TransferLength; /* 0x14 */ +} MPI2_DIAG_BUFFER_POST_REPLY, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REPLY, + Mpi2DiagBufferPostReply_t, MPI2_POINTER pMpi2DiagBufferPostReply_t; + + +/**************************************************************************** +* Diagnostic Release request +****************************************************************************/ + +typedef struct _MPI2_DIAG_RELEASE_REQUEST +{ + U8 Reserved1; /* 0x00 */ + U8 BufferType; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ +} MPI2_DIAG_RELEASE_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REQUEST, + Mpi2DiagReleaseRequest_t, MPI2_POINTER pMpi2DiagReleaseRequest_t; + + +/**************************************************************************** +* Diagnostic Buffer Post reply +****************************************************************************/ + +typedef struct _MPI2_DIAG_RELEASE_REPLY +{ + U8 Reserved1; /* 0x00 */ + U8 BufferType; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_DIAG_RELEASE_REPLY, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REPLY, + Mpi2DiagReleaseReply_t, MPI2_POINTER pMpi2DiagReleaseReply_t; + + +#endif + diff --git a/source/lsi/mpi2_type.h b/source/lsi/mpi2_type.h new file mode 100755 index 0000000..12dc94e --- /dev/null +++ b/source/lsi/mpi2_type.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2000-2007 LSI Corporation. + * + * + * Name: mpi2_type.h + * Title: MPI basic type definitions + * Creation Date: August 16, 2006 + * + * mpi2_type.h Version: 02.00.00 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_TYPE_H +#define MPI2_TYPE_H + + +/******************************************************************************* + * Define MPI2_POINTER if it hasn't already been defined. By default + * MPI2_POINTER is defined to be a near pointer. MPI2_POINTER can be defined as + * a far pointer by defining MPI2_POINTER as "far *" before this header file is + * included. + */ +#ifndef MPI2_POINTER +#define MPI2_POINTER * +#endif + +/* the basic types may have already been included by mpi_type.h */ +#ifndef MPI_TYPE_H +/***************************************************************************** +* +* Basic Types +* +*****************************************************************************/ + +typedef signed char S8; +typedef unsigned char U8; +typedef signed short S16; +typedef unsigned short U16; + + +#if defined(unix) || defined(__arm) || defined(ALPHA) || defined(__PPC__) || defined(__ppc) + + typedef signed int S32; + typedef unsigned int U32; + +#else + + typedef signed long S32; + typedef unsigned long U32; + +#endif + + +typedef struct _S64 +{ + U32 Low; + S32 High; +} S64; + +typedef struct _U64 +{ + U32 Low; + U32 High; +} U64; + + +/***************************************************************************** +* +* Pointer Types +* +*****************************************************************************/ + +typedef S8 *PS8; +typedef U8 *PU8; +typedef S16 *PS16; +typedef U16 *PU16; +typedef S32 *PS32; +typedef U32 *PU32; +typedef S64 *PS64; +typedef U64 *PU64; + +#endif + +#endif + diff --git a/source/lsi/mpi_cnfg.h b/source/lsi/mpi_cnfg.h new file mode 100755 index 0000000..1621d04 --- /dev/null +++ b/source/lsi/mpi_cnfg.h @@ -0,0 +1,3129 @@ +/* + * Copyright (c) 2000-2008 LSI Corporation. + * + * + * Name: mpi_cnfg.h + * Title: MPI Config message, structures, and Pages + * Creation Date: July 27, 2000 + * + * mpi_cnfg.h Version: 01.05.19 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. + * 06-06-00 01.00.01 Update version number for 1.0 release. + * 06-08-00 01.00.02 Added _PAGEVERSION definitions for all pages. + * Added FcPhLowestVersion, FcPhHighestVersion, Reserved2 + * fields to FC_DEVICE_0 page, updated the page version. + * Changed _FREE_RUNNING_CLOCK to _PACING_TRANSFERS in + * SCSI_PORT_0, SCSI_DEVICE_0 and SCSI_DEVICE_1 pages + * and updated the page versions. + * Added _RESPONSE_ID_MASK definition to SCSI_PORT_1 + * page and updated the page version. + * Added Information field and _INFO_PARAMS_NEGOTIATED + * definitionto SCSI_DEVICE_0 page. + * 06-22-00 01.00.03 Removed batch controls from LAN_0 page and updated the + * page version. + * Added BucketsRemaining to LAN_1 page, redefined the + * state values, and updated the page version. + * Revised bus width definitions in SCSI_PORT_0, + * SCSI_DEVICE_0 and SCSI_DEVICE_1 pages. + * 06-30-00 01.00.04 Added MaxReplySize to LAN_1 page and updated the page + * version. + * Moved FC_DEVICE_0 PageAddress description to spec. + * 07-27-00 01.00.05 Corrected the SubsystemVendorID and SubsystemID field + * widths in IOC_0 page and updated the page version. + * 11-02-00 01.01.01 Original release for post 1.0 work + * Added Manufacturing pages, IO Unit Page 2, SCSI SPI + * Port Page 2, FC Port Page 4, FC Port Page 5 + * 11-15-00 01.01.02 Interim changes to match proposals + * 12-04-00 01.01.03 Config page changes to match MPI rev 1.00.01. + * 12-05-00 01.01.04 Modified config page actions. + * 01-09-01 01.01.05 Added defines for page address formats. + * Data size for Manufacturing pages 2 and 3 no longer + * defined here. + * Io Unit Page 2 size is fixed at 4 adapters and some + * flags were changed. + * SCSI Port Page 2 Device Settings modified. + * New fields added to FC Port Page 0 and some flags + * cleaned up. + * Removed impedance flash from FC Port Page 1. + * Added FC Port pages 6 and 7. + * 01-25-01 01.01.06 Added MaxInitiators field to FcPortPage0. + * 01-29-01 01.01.07 Changed some defines to make them 32 character unique. + * Added some LinkType defines for FcPortPage0. + * 02-20-01 01.01.08 Started using MPI_POINTER. + * 02-27-01 01.01.09 Replaced MPI_CONFIG_PAGETYPE_SCSI_LUN with + * MPI_CONFIG_PAGETYPE_RAID_VOLUME. + * Added definitions and structures for IOC Page 2 and + * RAID Volume Page 2. + * 03-27-01 01.01.10 Added CONFIG_PAGE_FC_PORT_8 and CONFIG_PAGE_FC_PORT_9. + * CONFIG_PAGE_FC_PORT_3 now supports persistent by DID. + * Added VendorId and ProductRevLevel fields to + * RAIDVOL2_IM_PHYS_ID struct. + * Modified values for MPI_FCPORTPAGE0_FLAGS_ATTACH_ + * defines to make them compatible to MPI version 1.0. + * Added structure offset comments. + * 04-09-01 01.01.11 Added some new defines for the PageAddress field and + * removed some obsolete ones. + * Added IO Unit Page 3. + * Modified defines for Scsi Port Page 2. + * Modified RAID Volume Pages. + * 08-08-01 01.02.01 Original release for v1.2 work. + * Added SepID and SepBus to RVP2 IMPhysicalDisk struct. + * Added defines for the SEP bits in RVP2 VolumeSettings. + * Modified the DeviceSettings field in RVP2 to use the + * proper structure. + * Added defines for SES, SAF-TE, and cross channel for + * IOCPage2 CapabilitiesFlags. + * Removed define for MPI_IOUNITPAGE2_FLAGS_RAID_DISABLE. + * Removed define for + * MPI_SCSIPORTPAGE2_PORT_FLAGS_PARITY_ENABLE. + * Added define for MPI_CONFIG_PAGEATTR_RO_PERSISTENT. + * 08-29-01 01.02.02 Fixed value for MPI_MANUFACTPAGE_DEVID_53C1035. + * Added defines for MPI_FCPORTPAGE1_FLAGS_HARD_ALPA_ONLY + * and MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY. + * Removed MPI_SCSIPORTPAGE0_CAP_PACING_TRANSFERS, + * MPI_SCSIDEVPAGE0_NP_PACING_TRANSFERS, and + * MPI_SCSIDEVPAGE1_RP_PACING_TRANSFERS, and + * MPI_SCSIDEVPAGE1_CONF_PPR_ALLOWED. + * Added defines for MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED + * and MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED. + * Added OnBusTimerValue to CONFIG_PAGE_SCSI_PORT_1. + * Added rejected bits to SCSI Device Page 0 Information. + * Increased size of ALPA array in FC Port Page 2 by one + * and removed a one byte reserved field. + * 09-28-01 01.02.03 Swapped NegWireSpeedLow and NegWireSpeedLow in + * CONFIG_PAGE_LAN_1 to match preferred 64-bit ordering. + * Added structures for Manufacturing Page 4, IO Unit + * Page 3, IOC Page 3, IOC Page 4, RAID Volume Page 0, and + * RAID PhysDisk Page 0. + * 10-04-01 01.02.04 Added define for MPI_CONFIG_PAGETYPE_RAID_PHYSDISK. + * Modified some of the new defines to make them 32 + * character unique. + * Modified how variable length pages (arrays) are defined. + * Added generic defines for hot spare pools and RAID + * volume types. + * 11-01-01 01.02.05 Added define for MPI_IOUNITPAGE1_DISABLE_IR. + * 03-14-02 01.02.06 Added PCISlotNum field to CONFIG_PAGE_IOC_1 along with + * related define, and bumped the page version define. + * 05-31-02 01.02.07 Added a Flags field to CONFIG_PAGE_IOC_2_RAID_VOL in a + * reserved byte and added a define. + * Added define for + * MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE. + * Added new config page: CONFIG_PAGE_IOC_5. + * Added MaxAliases, MaxHardAliases, and NumCurrentAliases + * fields to CONFIG_PAGE_FC_PORT_0. + * Added AltConnector and NumRequestedAliases fields to + * CONFIG_PAGE_FC_PORT_1. + * Added new config page: CONFIG_PAGE_FC_PORT_10. + * 07-12-02 01.02.08 Added more MPI_MANUFACTPAGE_DEVID_ defines. + * Added additional MPI_SCSIDEVPAGE0_NP_ defines. + * Added more MPI_SCSIDEVPAGE1_RP_ defines. + * Added define for + * MPI_SCSIDEVPAGE1_CONF_EXTENDED_PARAMS_ENABLE. + * Added new config page: CONFIG_PAGE_SCSI_DEVICE_3. + * Modified MPI_FCPORTPAGE5_FLAGS_ defines. + * 09-16-02 01.02.09 Added MPI_SCSIDEVPAGE1_CONF_FORCE_PPR_MSG define. + * 11-15-02 01.02.10 Added ConnectedID defines for CONFIG_PAGE_SCSI_PORT_0. + * Added more Flags defines for CONFIG_PAGE_FC_PORT_1. + * Added more Flags defines for CONFIG_PAGE_FC_DEVICE_0. + * 04-01-03 01.02.11 Added RR_TOV field and additional Flags defines for + * CONFIG_PAGE_FC_PORT_1. + * Added define MPI_FCPORTPAGE5_FLAGS_DISABLE to disable + * an alias. + * Added more device id defines. + * 06-26-03 01.02.12 Added MPI_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID define. + * Added TargetConfig and IDConfig fields to + * CONFIG_PAGE_SCSI_PORT_1. + * Added more PortFlags defines for CONFIG_PAGE_SCSI_PORT_2 + * to control DV. + * Added more Flags defines for CONFIG_PAGE_FC_PORT_1. + * In CONFIG_PAGE_FC_DEVICE_0, replaced Reserved1 field + * with ADISCHardALPA. + * Added MPI_FC_DEVICE_PAGE0_PROT_FCP_RETRY define. + * 01-16-04 01.02.13 Added InitiatorDeviceTimeout and InitiatorIoPendTimeout + * fields and related defines to CONFIG_PAGE_FC_PORT_1. + * Added define for + * MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK. + * Added new fields to the substructures of + * CONFIG_PAGE_FC_PORT_10. + * 04-29-04 01.02.14 Added define for IDP bit for CONFIG_PAGE_SCSI_PORT_0, + * CONFIG_PAGE_SCSI_DEVICE_0, and + * CONFIG_PAGE_SCSI_DEVICE_1. Also bumped Page Version for + * these pages. + * 05-11-04 01.03.01 Added structure for CONFIG_PAGE_INBAND_0. + * 08-19-04 01.05.01 Modified MSG_CONFIG request to support extended config + * pages. + * Added a new structure for extended config page header. + * Added new extended config pages types and structures for + * SAS IO Unit, SAS Expander, SAS Device, and SAS PHY. + * Replaced a reserved byte in CONFIG_PAGE_MANUFACTURING_4 + * to add a Flags field. + * Two new Manufacturing config pages (5 and 6). + * Two new bits defined for IO Unit Page 1 Flags field. + * Modified CONFIG_PAGE_IO_UNIT_2 to add three new fields + * to specify the BIOS boot device. + * Four new Flags bits defined for IO Unit Page 2. + * Added IO Unit Page 4. + * Added EEDP Flags settings to IOC Page 1. + * Added new BIOS Page 1 config page. + * 10-05-04 01.05.02 Added define for + * MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE. + * Added new Flags field to CONFIG_PAGE_MANUFACTURING_5 and + * associated defines. + * Added more defines for SAS IO Unit Page 0 + * DiscoveryStatus field. + * Added define for MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK + * and MPI_SAS_IOUNIT0_DS_TABLE_LINK. + * Added defines for Physical Mapping Modes to SAS IO Unit + * Page 2. + * Added define for + * MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH. + * 10-27-04 01.05.03 Added defines for new SAS PHY page addressing mode. + * Added defines for MaxTargetSpinUp to BIOS Page 1. + * Added 5 new ControlFlags defines for SAS IO Unit + * Page 1. + * Added MaxNumPhysicalMappedIDs field to SAS IO Unit + * Page 2. + * Added AccessStatus field to SAS Device Page 0 and added + * new Flags bits for supported SATA features. + * 12-07-04 01.05.04 Added config page structures for BIOS Page 2, RAID + * Volume Page 1, and RAID Physical Disk Page 1. + * Replaced IO Unit Page 1 BootTargetID,BootBus, and + * BootAdapterNum with reserved field. + * Added DataScrubRate and ResyncRate to RAID Volume + * Page 0. + * Added MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT + * define. + * 12-09-04 01.05.05 Added Target Mode Large CDB Enable to FC Port Page 1 + * Flags field. + * Added Auto Port Config flag define for SAS IOUNIT + * Page 1 ControlFlags. + * Added Disabled bad Phy define to Expander Page 1 + * Discovery Info field. + * Added SAS/SATA device support to SAS IOUnit Page 1 + * ControlFlags. + * Added Unsupported device to SAS Dev Page 0 Flags field + * Added disable use SATA Hash Address for SAS IOUNIT + * page 1 in ControlFields. + * 01-15-05 01.05.06 Added defaults for data scrub rate and resync rate to + * Manufacturing Page 4. + * Added new defines for BIOS Page 1 IOCSettings field. + * Added ExtDiskIdentifier field to RAID Physical Disk + * Page 0. + * Added new defines for SAS IO Unit Page 1 ControlFlags + * and to SAS Device Page 0 Flags to control SATA devices. + * Added defines and structures for the new Log Page 0, a + * new type of configuration page. + * 02-09-05 01.05.07 Added InactiveStatus field to RAID Volume Page 0. + * Added WWID field to RAID Volume Page 1. + * Added PhysicalPort field to SAS Expander pages 0 and 1. + * 03-11-05 01.05.08 Removed the EEDP flags from IOC Page 1. + * Added Enclosure/Slot boot device format to BIOS Page 2. + * New status value for RAID Volume Page 0 VolumeStatus + * (VolumeState subfield). + * New value for RAID Physical Page 0 InactiveStatus. + * Added Inactive Volume Member flag RAID Physical Disk + * Page 0 PhysDiskStatus field. + * New physical mapping mode in SAS IO Unit Page 2. + * Added CONFIG_PAGE_SAS_ENCLOSURE_0. + * Added Slot and Enclosure fields to SAS Device Page 0. + * 06-24-05 01.05.09 Added EEDP defines to IOC Page 1. + * Added more RAID type defines to IOC Page 2. + * Added Port Enable Delay settings to BIOS Page 1. + * Added Bad Block Table Full define to RAID Volume Page 0. + * Added Previous State defines to RAID Physical Disk + * Page 0. + * Added Max Sata Targets define for DiscoveryStatus field + * of SAS IO Unit Page 0. + * Added Device Self Test to Control Flags of SAS IO Unit + * Page 1. + * Added Direct Attach Starting Slot Number define for SAS + * IO Unit Page 2. + * Added new fields in SAS Device Page 2 for enclosure + * mapping. + * Added OwnerDevHandle and Flags field to SAS PHY Page 0. + * Added IOC GPIO Flags define to SAS Enclosure Page 0. + * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. + * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from + * Manufacturing Page 4. + * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit. + * Added NumDevsPerEnclosure field to SAS IO Unit page 2. + * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP + * define. + * Added EnclosureHandle field to SAS Expander page 0. + * Removed redundant NumTableEntriesProg field from SAS + * Expander Page 1. + * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for + * SAS1078. + * Added more defines for Manufacturing Page 4 Flags field. + * Added more defines for IOCSettings and added + * ExpanderSpinup field to Bios Page 1. + * Added postpone SATA Init bit to SAS IO Unit Page 1 + * ControlFlags. + * Changed LogEntry format for Log Page 0. + * 03-27-06 01.05.12 Added two new Flags defines for Manufacturing Page 4. + * Added Manufacturing Page 7. + * Added MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING. + * Added IOC Page 6. + * Added PrevBootDeviceForm field to CONFIG_PAGE_BIOS_2. + * Added MaxLBAHigh field to RAID Volume Page 0. + * Added Nvdata version fields to SAS IO Unit Page 0. + * Added AdditionalControlFlags, MaxTargetPortConnectTime, + * ReportDeviceMissingDelay, and IODeviceMissingDelay + * fields to SAS IO Unit Page 1. + * 10-11-06 01.05.13 Added NumForceWWID field and ForceWWID array to + * Manufacturing Page 5. + * Added Manufacturing pages 8 through 10. + * Added defines for supported metadata size bits in + * CapabilitiesFlags field of IOC Page 6. + * Added defines for metadata size bits in VolumeSettings + * field of RAID Volume Page 0. + * Added SATA Link Reset settings, Enable SATA Asynchronous + * Notification bit, and HideNonZeroAttachedPhyIdentifiers + * bit to AdditionalControlFlags field of SAS IO Unit + * Page 1. + * Added defines for Enclosure Devices Unmapped and + * Device Limit Exceeded bits in Status field of SAS IO + * Unit Page 2. + * Added more AccessStatus values for SAS Device Page 0. + * Added bit for SATA Asynchronous Notification Support in + * Flags field of SAS Device Page 0. + * 02-28-07 01.05.14 Added ExtFlags field to Manufacturing Page 4. + * Added Disable SMART Polling for CapabilitiesFlags of + * IOC Page 6. + * Added Disable SMART Polling to DeviceSettings of BIOS + * Page 1. + * Added Multi-Port Domain bit for DiscoveryStatus field + * of SAS IO Unit Page. + * Added Multi-Port Domain Illegal flag for SAS IO Unit + * Page 1 AdditionalControlFlags field. + * 05-24-07 01.05.15 Added Hide Physical Disks with Non-Integrated RAID + * Metadata bit to Manufacturing Page 4 ExtFlags field. + * Added Internal Connector to End Device Present bit to + * Expander Page 0 Flags field. + * Fixed define for + * MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED. + * 08-07-07 01.05.16 Added MPI_IOCPAGE6_CAP_FLAGS_MULTIPORT_DRIVE_SUPPORT + * define. + * Added BIOS Page 4 structure. + * Added MPI_RAID_PHYS_DISK1_PATH_MAX define for RAID + * Physcial Disk Page 1. + * 01-15-07 01.05.17 Added additional bit defines for ExtFlags field of + * Manufacturing Page 4. + * Added Solid State Drives Supported bit to IOC Page 6 + * Capabilities Flags. + * Added new value for AccessStatus field of SAS Device + * Page 0 (_SATA_NEEDS_INITIALIZATION). + * 03-28-08 01.05.18 Defined new bits in Manufacturing Page 4 ExtFlags field + * to control coercion size and the mixing of SAS and SATA + * SSD drives. + * 07-11-08 01.05.19 Added defines MPI_MANPAGE4_EXTFLAGS_RAID0_SINGLE_DRIVE + * and MPI_MANPAGE4_EXTFLAGS_SSD_SCRUB_DISABLE for ExtFlags + * field of Manufacturing Page 4. + * Added defines for a new bit in BIOS Page 1 BiosOptions + * field to control adapter scan order. + * Added BootDeviceWaitTime field to SAS IO Unit Page 2. + * Added MPI_SAS_PHY0_PHYINFO_PHY_VACANT for use in PhyInfo + * field of SAS Expander Page 1. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_CNFG_H +#define MPI_CNFG_H + + +/***************************************************************************** +* +* C o n f i g M e s s a g e a n d S t r u c t u r e s +* +*****************************************************************************/ + +typedef struct _CONFIG_PAGE_HEADER +{ + U8 PageVersion; /* 00h */ + U8 PageLength; /* 01h */ + U8 PageNumber; /* 02h */ + U8 PageType; /* 03h */ +} CONFIG_PAGE_HEADER, MPI_POINTER PTR_CONFIG_PAGE_HEADER, + ConfigPageHeader_t, MPI_POINTER pConfigPageHeader_t; + +typedef union _CONFIG_PAGE_HEADER_UNION +{ + ConfigPageHeader_t Struct; + U8 Bytes[4]; + U16 Word16[2]; + U32 Word32; +} ConfigPageHeaderUnion, MPI_POINTER pConfigPageHeaderUnion, + CONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION; + +typedef struct _CONFIG_EXTENDED_PAGE_HEADER +{ + U8 PageVersion; /* 00h */ + U8 Reserved1; /* 01h */ + U8 PageNumber; /* 02h */ + U8 PageType; /* 03h */ + U16 ExtPageLength; /* 04h */ + U8 ExtPageType; /* 06h */ + U8 Reserved2; /* 07h */ +} CONFIG_EXTENDED_PAGE_HEADER, MPI_POINTER PTR_CONFIG_EXTENDED_PAGE_HEADER, + ConfigExtendedPageHeader_t, MPI_POINTER pConfigExtendedPageHeader_t; + + + +/**************************************************************************** +* PageType field values +****************************************************************************/ +#define MPI_CONFIG_PAGEATTR_READ_ONLY (0x00) +#define MPI_CONFIG_PAGEATTR_CHANGEABLE (0x10) +#define MPI_CONFIG_PAGEATTR_PERSISTENT (0x20) +#define MPI_CONFIG_PAGEATTR_RO_PERSISTENT (0x30) +#define MPI_CONFIG_PAGEATTR_MASK (0xF0) + +#define MPI_CONFIG_PAGETYPE_IO_UNIT (0x00) +#define MPI_CONFIG_PAGETYPE_IOC (0x01) +#define MPI_CONFIG_PAGETYPE_BIOS (0x02) +#define MPI_CONFIG_PAGETYPE_SCSI_PORT (0x03) +#define MPI_CONFIG_PAGETYPE_SCSI_DEVICE (0x04) +#define MPI_CONFIG_PAGETYPE_FC_PORT (0x05) +#define MPI_CONFIG_PAGETYPE_FC_DEVICE (0x06) +#define MPI_CONFIG_PAGETYPE_LAN (0x07) +#define MPI_CONFIG_PAGETYPE_RAID_VOLUME (0x08) +#define MPI_CONFIG_PAGETYPE_MANUFACTURING (0x09) +#define MPI_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A) +#define MPI_CONFIG_PAGETYPE_INBAND (0x0B) +#define MPI_CONFIG_PAGETYPE_EXTENDED (0x0F) +#define MPI_CONFIG_PAGETYPE_MASK (0x0F) + +#define MPI_CONFIG_TYPENUM_MASK (0x0FFF) + + +/**************************************************************************** +* ExtPageType field values +****************************************************************************/ +#define MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10) +#define MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11) +#define MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12) +#define MPI_CONFIG_EXTPAGETYPE_SAS_PHY (0x13) +#define MPI_CONFIG_EXTPAGETYPE_LOG (0x14) +#define MPI_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15) + + +/**************************************************************************** +* PageAddress field values +****************************************************************************/ +#define MPI_SCSI_PORT_PGAD_PORT_MASK (0x000000FF) + +#define MPI_SCSI_DEVICE_FORM_MASK (0xF0000000) +#define MPI_SCSI_DEVICE_FORM_BUS_TID (0x00000000) +#define MPI_SCSI_DEVICE_TARGET_ID_MASK (0x000000FF) +#define MPI_SCSI_DEVICE_TARGET_ID_SHIFT (0) +#define MPI_SCSI_DEVICE_BUS_MASK (0x0000FF00) +#define MPI_SCSI_DEVICE_BUS_SHIFT (8) +#define MPI_SCSI_DEVICE_FORM_TARGET_MODE (0x10000000) +#define MPI_SCSI_DEVICE_TM_RESPOND_ID_MASK (0x000000FF) +#define MPI_SCSI_DEVICE_TM_RESPOND_ID_SHIFT (0) +#define MPI_SCSI_DEVICE_TM_BUS_MASK (0x0000FF00) +#define MPI_SCSI_DEVICE_TM_BUS_SHIFT (8) +#define MPI_SCSI_DEVICE_TM_INIT_ID_MASK (0x00FF0000) +#define MPI_SCSI_DEVICE_TM_INIT_ID_SHIFT (16) + +#define MPI_FC_PORT_PGAD_PORT_MASK (0xF0000000) +#define MPI_FC_PORT_PGAD_PORT_SHIFT (28) +#define MPI_FC_PORT_PGAD_FORM_MASK (0x0F000000) +#define MPI_FC_PORT_PGAD_FORM_INDEX (0x01000000) +#define MPI_FC_PORT_PGAD_INDEX_MASK (0x0000FFFF) +#define MPI_FC_PORT_PGAD_INDEX_SHIFT (0) + +#define MPI_FC_DEVICE_PGAD_PORT_MASK (0xF0000000) +#define MPI_FC_DEVICE_PGAD_PORT_SHIFT (28) +#define MPI_FC_DEVICE_PGAD_FORM_MASK (0x0F000000) +#define MPI_FC_DEVICE_PGAD_FORM_NEXT_DID (0x00000000) +#define MPI_FC_DEVICE_PGAD_ND_PORT_MASK (0xF0000000) +#define MPI_FC_DEVICE_PGAD_ND_PORT_SHIFT (28) +#define MPI_FC_DEVICE_PGAD_ND_DID_MASK (0x00FFFFFF) +#define MPI_FC_DEVICE_PGAD_ND_DID_SHIFT (0) +#define MPI_FC_DEVICE_PGAD_FORM_BUS_TID (0x01000000) +#define MPI_FC_DEVICE_PGAD_BT_BUS_MASK (0x0000FF00) +#define MPI_FC_DEVICE_PGAD_BT_BUS_SHIFT (8) +#define MPI_FC_DEVICE_PGAD_BT_TID_MASK (0x000000FF) +#define MPI_FC_DEVICE_PGAD_BT_TID_SHIFT (0) + +#define MPI_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF) +#define MPI_PHYSDISK_PGAD_PHYSDISKNUM_SHIFT (0) + +#define MPI_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000) +#define MPI_SAS_EXPAND_PGAD_FORM_SHIFT (28) +#define MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM (0x00000001) +#define MPI_SAS_EXPAND_PGAD_FORM_HANDLE (0x00000002) +#define MPI_SAS_EXPAND_PGAD_GNH_MASK_HANDLE (0x0000FFFF) +#define MPI_SAS_EXPAND_PGAD_GNH_SHIFT_HANDLE (0) +#define MPI_SAS_EXPAND_PGAD_HPN_MASK_PHY (0x00FF0000) +#define MPI_SAS_EXPAND_PGAD_HPN_SHIFT_PHY (16) +#define MPI_SAS_EXPAND_PGAD_HPN_MASK_HANDLE (0x0000FFFF) +#define MPI_SAS_EXPAND_PGAD_HPN_SHIFT_HANDLE (0) +#define MPI_SAS_EXPAND_PGAD_H_MASK_HANDLE (0x0000FFFF) +#define MPI_SAS_EXPAND_PGAD_H_SHIFT_HANDLE (0) + +#define MPI_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000) +#define MPI_SAS_DEVICE_PGAD_FORM_SHIFT (28) +#define MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID (0x00000001) +#define MPI_SAS_DEVICE_PGAD_FORM_HANDLE (0x00000002) +#define MPI_SAS_DEVICE_PGAD_GNH_HANDLE_MASK (0x0000FFFF) +#define MPI_SAS_DEVICE_PGAD_GNH_HANDLE_SHIFT (0) +#define MPI_SAS_DEVICE_PGAD_BT_BUS_MASK (0x0000FF00) +#define MPI_SAS_DEVICE_PGAD_BT_BUS_SHIFT (8) +#define MPI_SAS_DEVICE_PGAD_BT_TID_MASK (0x000000FF) +#define MPI_SAS_DEVICE_PGAD_BT_TID_SHIFT (0) +#define MPI_SAS_DEVICE_PGAD_H_HANDLE_MASK (0x0000FFFF) +#define MPI_SAS_DEVICE_PGAD_H_HANDLE_SHIFT (0) + +#define MPI_SAS_PHY_PGAD_FORM_MASK (0xF0000000) +#define MPI_SAS_PHY_PGAD_FORM_SHIFT (28) +#define MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x0) +#define MPI_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x1) +#define MPI_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF) +#define MPI_SAS_PHY_PGAD_PHY_NUMBER_SHIFT (0) +#define MPI_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF) +#define MPI_SAS_PHY_PGAD_PHY_TBL_INDEX_SHIFT (0) + +#define MPI_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000) +#define MPI_SAS_ENCLOS_PGAD_FORM_SHIFT (28) +#define MPI_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI_SAS_ENCLOS_PGAD_FORM_HANDLE (0x00000001) +#define MPI_SAS_ENCLOS_PGAD_GNH_HANDLE_MASK (0x0000FFFF) +#define MPI_SAS_ENCLOS_PGAD_GNH_HANDLE_SHIFT (0) +#define MPI_SAS_ENCLOS_PGAD_H_HANDLE_MASK (0x0000FFFF) +#define MPI_SAS_ENCLOS_PGAD_H_HANDLE_SHIFT (0) + + + +/**************************************************************************** +* Config Request Message +****************************************************************************/ +typedef struct _MSG_CONFIG +{ + U8 Action; /* 00h */ + U8 AliasIndex; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 ExtPageLength; /* 04h */ + U8 ExtPageType; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2[8]; /* 0Ch */ + CONFIG_PAGE_HEADER Header; /* 14h */ + U32 PageAddress; /* 18h */ + SGE_IO_UNION PageBufferSGE; /* 1Ch */ +} MSG_CONFIG, MPI_POINTER PTR_MSG_CONFIG, + Config_t, MPI_POINTER pConfig_t; + + +/**************************************************************************** +* Action field values +****************************************************************************/ +#define MPI_CONFIG_ACTION_PAGE_HEADER (0x00) +#define MPI_CONFIG_ACTION_PAGE_READ_CURRENT (0x01) +#define MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02) +#define MPI_CONFIG_ACTION_PAGE_DEFAULT (0x03) +#define MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04) +#define MPI_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05) +#define MPI_CONFIG_ACTION_PAGE_READ_NVRAM (0x06) + + +/* Config Reply Message */ +typedef struct _MSG_CONFIG_REPLY +{ + U8 Action; /* 00h */ + U8 AliasIndex; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 ExtPageLength; /* 04h */ + U8 ExtPageType; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2[2]; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + CONFIG_PAGE_HEADER Header; /* 14h */ +} MSG_CONFIG_REPLY, MPI_POINTER PTR_MSG_CONFIG_REPLY, + ConfigReply_t, MPI_POINTER pConfigReply_t; + + + +/***************************************************************************** +* +* C o n f i g u r a t i o n P a g e s +* +*****************************************************************************/ + +/**************************************************************************** +* Manufacturing Config pages +****************************************************************************/ +#define MPI_MANUFACTPAGE_VENDORID_LSILOGIC (0x1000) +/* Fibre Channel */ +#define MPI_MANUFACTPAGE_DEVICEID_FC909 (0x0621) +#define MPI_MANUFACTPAGE_DEVICEID_FC919 (0x0624) +#define MPI_MANUFACTPAGE_DEVICEID_FC929 (0x0622) +#define MPI_MANUFACTPAGE_DEVICEID_FC919X (0x0628) +#define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626) +#define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642) +#define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640) +#define MPI_MANUFACTPAGE_DEVICEID_FC949E (0x0646) +/* SCSI */ +#define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030) +#define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031) +#define MPI_MANUFACTPAGE_DEVID_1030_53C1035 (0x0032) +#define MPI_MANUFACTPAGE_DEVID_1030ZC_53C1035 (0x0033) +#define MPI_MANUFACTPAGE_DEVID_53C1035 (0x0040) +#define MPI_MANUFACTPAGE_DEVID_53C1035ZC (0x0041) +/* SAS */ +#define MPI_MANUFACTPAGE_DEVID_SAS1064 (0x0050) +#define MPI_MANUFACTPAGE_DEVID_SAS1064A (0x005C) +#define MPI_MANUFACTPAGE_DEVID_SAS1064E (0x0056) +#define MPI_MANUFACTPAGE_DEVID_SAS1066 (0x005E) +#define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A) +#define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054) +#define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058) +#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0062) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_0 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 ChipName[16]; /* 04h */ + U8 ChipRevision[8]; /* 14h */ + U8 BoardName[16]; /* 1Ch */ + U8 BoardAssembly[16]; /* 2Ch */ + U8 BoardTracerNumber[16]; /* 3Ch */ + +} CONFIG_PAGE_MANUFACTURING_0, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_0, + ManufacturingPage0_t, MPI_POINTER pManufacturingPage0_t; + +#define MPI_MANUFACTURING0_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 VPD[256]; /* 04h */ +} CONFIG_PAGE_MANUFACTURING_1, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_1, + ManufacturingPage1_t, MPI_POINTER pManufacturingPage1_t; + +#define MPI_MANUFACTURING1_PAGEVERSION (0x00) + + +typedef struct _MPI_CHIP_REVISION_ID +{ + U16 DeviceID; /* 00h */ + U8 PCIRevisionID; /* 02h */ + U8 Reserved; /* 03h */ +} MPI_CHIP_REVISION_ID, MPI_POINTER PTR_MPI_CHIP_REVISION_ID, + MpiChipRevisionId_t, MPI_POINTER pMpiChipRevisionId_t; + + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_MAN_PAGE_2_HW_SETTINGS_WORDS +#define MPI_MAN_PAGE_2_HW_SETTINGS_WORDS (1) +#endif + +typedef struct _CONFIG_PAGE_MANUFACTURING_2 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + MPI_CHIP_REVISION_ID ChipId; /* 04h */ + U32 HwSettings[MPI_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 08h */ +} CONFIG_PAGE_MANUFACTURING_2, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_2, + ManufacturingPage2_t, MPI_POINTER pManufacturingPage2_t; + +#define MPI_MANUFACTURING2_PAGEVERSION (0x00) + + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_MAN_PAGE_3_INFO_WORDS +#define MPI_MAN_PAGE_3_INFO_WORDS (1) +#endif + +typedef struct _CONFIG_PAGE_MANUFACTURING_3 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + MPI_CHIP_REVISION_ID ChipId; /* 04h */ + U32 Info[MPI_MAN_PAGE_3_INFO_WORDS];/* 08h */ +} CONFIG_PAGE_MANUFACTURING_3, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_3, + ManufacturingPage3_t, MPI_POINTER pManufacturingPage3_t; + +#define MPI_MANUFACTURING3_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_4 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 04h */ + U8 InfoOffset0; /* 08h */ + U8 InfoSize0; /* 09h */ + U8 InfoOffset1; /* 0Ah */ + U8 InfoSize1; /* 0Bh */ + U8 InquirySize; /* 0Ch */ + U8 Flags; /* 0Dh */ + U16 ExtFlags; /* 0Eh */ + U8 InquiryData[56]; /* 10h */ + U32 ISVolumeSettings; /* 48h */ + U32 IMEVolumeSettings; /* 4Ch */ + U32 IMVolumeSettings; /* 50h */ + U32 Reserved3; /* 54h */ + U32 Reserved4; /* 58h */ + U32 Reserved5; /* 5Ch */ + U8 IMEDataScrubRate; /* 60h */ + U8 IMEResyncRate; /* 61h */ + U16 Reserved6; /* 62h */ + U8 IMDataScrubRate; /* 64h */ + U8 IMResyncRate; /* 65h */ + U16 Reserved7; /* 66h */ + U32 Reserved8; /* 68h */ + U32 Reserved9; /* 6Ch */ +} CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4, + ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t; + +#define MPI_MANUFACTURING4_PAGEVERSION (0x05) + +/* defines for the Flags field */ +#define MPI_MANPAGE4_FORCE_BAD_BLOCK_TABLE (0x80) +#define MPI_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x40) +#define MPI_MANPAGE4_IME_DISABLE (0x20) +#define MPI_MANPAGE4_IM_DISABLE (0x10) +#define MPI_MANPAGE4_IS_DISABLE (0x08) +#define MPI_MANPAGE4_IR_MODEPAGE8_DISABLE (0x04) +#define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x02) +#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01) + +/* defines for the ExtFlags field */ +#define MPI_MANPAGE4_EXTFLAGS_RAID0_SINGLE_DRIVE (0x0400) +#define MPI_MANPAGE4_EXTFLAGS_SSD_SCRUB_DISABLE (0x0200) +#define MPI_MANPAGE4_EXTFLAGS_MASK_COERCION_SIZE (0x0180) +#define MPI_MANPAGE4_EXTFLAGS_SHIFT_COERCION_SIZE (7) +#define MPI_MANPAGE4_EXTFLAGS_1GB_COERCION_SIZE (0) +#define MPI_MANPAGE4_EXTFLAGS_128MB_COERCION_SIZE (1) + +#define MPI_MANPAGE4_EXTFLAGS_NO_MIX_SSD_SAS_SATA (0x0040) +#define MPI_MANPAGE4_EXTFLAGS_MIX_SSD_AND_NON_SSD (0x0020) +#define MPI_MANPAGE4_EXTFLAGS_DUAL_PORT_SUPPORT (0x0010) +#define MPI_MANPAGE4_EXTFLAGS_HIDE_NON_IR_METADATA (0x0008) +#define MPI_MANPAGE4_EXTFLAGS_SAS_CACHE_DISABLE (0x0004) +#define MPI_MANPAGE4_EXTFLAGS_SATA_CACHE_DISABLE (0x0002) +#define MPI_MANPAGE4_EXTFLAGS_LEGACY_MODE (0x0001) + + +#ifndef MPI_MANPAGE5_NUM_FORCEWWID +#define MPI_MANPAGE5_NUM_FORCEWWID (1) +#endif + +typedef struct _CONFIG_PAGE_MANUFACTURING_5 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U64 BaseWWID; /* 04h */ + U8 Flags; /* 0Ch */ + U8 NumForceWWID; /* 0Dh */ + U16 Reserved2; /* 0Eh */ + U32 Reserved3; /* 10h */ + U32 Reserved4; /* 14h */ + U64 ForceWWID[MPI_MANPAGE5_NUM_FORCEWWID]; /* 18h */ +} CONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5, + ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t; + +#define MPI_MANUFACTURING5_PAGEVERSION (0x02) + +/* defines for the Flags field */ +#define MPI_MANPAGE5_TWO_WWID_PER_PHY (0x01) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_6 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} CONFIG_PAGE_MANUFACTURING_6, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_6, + ManufacturingPage6_t, MPI_POINTER pManufacturingPage6_t; + +#define MPI_MANUFACTURING6_PAGEVERSION (0x00) + + +typedef struct _MPI_MANPAGE7_CONNECTOR_INFO +{ + U32 Pinout; /* 00h */ + U8 Connector[16]; /* 04h */ + U8 Location; /* 14h */ + U8 Reserved1; /* 15h */ + U16 Slot; /* 16h */ + U32 Reserved2; /* 18h */ +} MPI_MANPAGE7_CONNECTOR_INFO, MPI_POINTER PTR_MPI_MANPAGE7_CONNECTOR_INFO, + MpiManPage7ConnectorInfo_t, MPI_POINTER pMpiManPage7ConnectorInfo_t; + +/* defines for the Pinout field */ +#define MPI_MANPAGE7_PINOUT_SFF_8484_L4 (0x00080000) +#define MPI_MANPAGE7_PINOUT_SFF_8484_L3 (0x00040000) +#define MPI_MANPAGE7_PINOUT_SFF_8484_L2 (0x00020000) +#define MPI_MANPAGE7_PINOUT_SFF_8484_L1 (0x00010000) +#define MPI_MANPAGE7_PINOUT_SFF_8470_L4 (0x00000800) +#define MPI_MANPAGE7_PINOUT_SFF_8470_L3 (0x00000400) +#define MPI_MANPAGE7_PINOUT_SFF_8470_L2 (0x00000200) +#define MPI_MANPAGE7_PINOUT_SFF_8470_L1 (0x00000100) +#define MPI_MANPAGE7_PINOUT_SFF_8482 (0x00000002) +#define MPI_MANPAGE7_PINOUT_CONNECTION_UNKNOWN (0x00000001) + +/* defines for the Location field */ +#define MPI_MANPAGE7_LOCATION_UNKNOWN (0x01) +#define MPI_MANPAGE7_LOCATION_INTERNAL (0x02) +#define MPI_MANPAGE7_LOCATION_EXTERNAL (0x04) +#define MPI_MANPAGE7_LOCATION_SWITCHABLE (0x08) +#define MPI_MANPAGE7_LOCATION_AUTO (0x10) +#define MPI_MANPAGE7_LOCATION_NOT_PRESENT (0x20) +#define MPI_MANPAGE7_LOCATION_NOT_CONNECTED (0x80) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumPhys at runtime. + */ +#ifndef MPI_MANPAGE7_CONNECTOR_INFO_MAX +#define MPI_MANPAGE7_CONNECTOR_INFO_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_MANUFACTURING_7 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 04h */ + U32 Reserved2; /* 08h */ + U32 Flags; /* 0Ch */ + U8 EnclosureName[16]; /* 10h */ + U8 NumPhys; /* 20h */ + U8 Reserved3; /* 21h */ + U16 Reserved4; /* 22h */ + MPI_MANPAGE7_CONNECTOR_INFO ConnectorInfo[MPI_MANPAGE7_CONNECTOR_INFO_MAX]; /* 24h */ +} CONFIG_PAGE_MANUFACTURING_7, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_7, + ManufacturingPage7_t, MPI_POINTER pManufacturingPage7_t; + +#define MPI_MANUFACTURING7_PAGEVERSION (0x00) + +/* defines for the Flags field */ +#define MPI_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_8 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} CONFIG_PAGE_MANUFACTURING_8, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_8, + ManufacturingPage8_t, MPI_POINTER pManufacturingPage8_t; + +#define MPI_MANUFACTURING8_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_9 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} CONFIG_PAGE_MANUFACTURING_9, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_9, + ManufacturingPage9_t, MPI_POINTER pManufacturingPage9_t; + +#define MPI_MANUFACTURING9_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_10 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} CONFIG_PAGE_MANUFACTURING_10, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_10, + ManufacturingPage10_t, MPI_POINTER pManufacturingPage10_t; + +#define MPI_MANUFACTURING10_PAGEVERSION (0x00) + + +/**************************************************************************** +* IO Unit Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_IO_UNIT_0 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U64 UniqueValue; /* 04h */ +} CONFIG_PAGE_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_0, + IOUnitPage0_t, MPI_POINTER pIOUnitPage0_t; + +#define MPI_IOUNITPAGE0_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_IO_UNIT_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Flags; /* 04h */ +} CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1, + IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t; + +#define MPI_IOUNITPAGE1_PAGEVERSION (0x02) + +/* IO Unit Page 1 Flags defines */ +#define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000) +#define MPI_IOUNITPAGE1_SINGLE_FUNCTION (0x00000001) +#define MPI_IOUNITPAGE1_MULTI_PATHING (0x00000002) +#define MPI_IOUNITPAGE1_SINGLE_PATHING (0x00000000) +#define MPI_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004) +#define MPI_IOUNITPAGE1_DISABLE_QUEUE_FULL_HANDLING (0x00000020) +#define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040) +#define MPI_IOUNITPAGE1_FORCE_32 (0x00000080) +#define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) +#define MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE (0x00000200) + +typedef struct _MPI_ADAPTER_INFO +{ + U8 PciBusNumber; /* 00h */ + U8 PciDeviceAndFunctionNumber; /* 01h */ + U16 AdapterFlags; /* 02h */ +} MPI_ADAPTER_INFO, MPI_POINTER PTR_MPI_ADAPTER_INFO, + MpiAdapterInfo_t, MPI_POINTER pMpiAdapterInfo_t; + +#define MPI_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001) +#define MPI_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002) + +typedef struct _CONFIG_PAGE_IO_UNIT_2 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Flags; /* 04h */ + U32 BiosVersion; /* 08h */ + MPI_ADAPTER_INFO AdapterOrder[4]; /* 0Ch */ + U32 Reserved1; /* 1Ch */ +} CONFIG_PAGE_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_2, + IOUnitPage2_t, MPI_POINTER pIOUnitPage2_t; + +#define MPI_IOUNITPAGE2_PAGEVERSION (0x02) + +#define MPI_IOUNITPAGE2_FLAGS_PAUSE_ON_ERROR (0x00000002) +#define MPI_IOUNITPAGE2_FLAGS_VERBOSE_ENABLE (0x00000004) +#define MPI_IOUNITPAGE2_FLAGS_COLOR_VIDEO_DISABLE (0x00000008) +#define MPI_IOUNITPAGE2_FLAGS_DONT_HOOK_INT_40 (0x00000010) + +#define MPI_IOUNITPAGE2_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0) +#define MPI_IOUNITPAGE2_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000) +#define MPI_IOUNITPAGE2_FLAGS_ADAPTER_DISPLAY (0x00000020) +#define MPI_IOUNITPAGE2_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040) + + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_IO_UNIT_PAGE_3_GPIO_VAL_MAX +#define MPI_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_IO_UNIT_3 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 GPIOCount; /* 04h */ + U8 Reserved1; /* 05h */ + U16 Reserved2; /* 06h */ + U16 GPIOVal[MPI_IO_UNIT_PAGE_3_GPIO_VAL_MAX]; /* 08h */ +} CONFIG_PAGE_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_3, + IOUnitPage3_t, MPI_POINTER pIOUnitPage3_t; + +#define MPI_IOUNITPAGE3_PAGEVERSION (0x01) + +#define MPI_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFC) +#define MPI_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2) +#define MPI_IOUNITPAGE3_GPIO_SETTING_OFF (0x00) +#define MPI_IOUNITPAGE3_GPIO_SETTING_ON (0x01) + + +typedef struct _CONFIG_PAGE_IO_UNIT_4 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 04h */ + SGE_SIMPLE_UNION FWImageSGE; /* 08h */ +} CONFIG_PAGE_IO_UNIT_4, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_4, + IOUnitPage4_t, MPI_POINTER pIOUnitPage4_t; + +#define MPI_IOUNITPAGE4_PAGEVERSION (0x00) + + +/**************************************************************************** +* IOC Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_IOC_0 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 TotalNVStore; /* 04h */ + U32 FreeNVStore; /* 08h */ + U16 VendorID; /* 0Ch */ + U16 DeviceID; /* 0Eh */ + U8 RevisionID; /* 10h */ + U8 Reserved[3]; /* 11h */ + U32 ClassCode; /* 14h */ + U16 SubsystemVendorID; /* 18h */ + U16 SubsystemID; /* 1Ah */ +} CONFIG_PAGE_IOC_0, MPI_POINTER PTR_CONFIG_PAGE_IOC_0, + IOCPage0_t, MPI_POINTER pIOCPage0_t; + +#define MPI_IOCPAGE0_PAGEVERSION (0x01) + + +typedef struct _CONFIG_PAGE_IOC_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Flags; /* 04h */ + U32 CoalescingTimeout; /* 08h */ + U8 CoalescingDepth; /* 0Ch */ + U8 PCISlotNum; /* 0Dh */ + U8 Reserved[2]; /* 0Eh */ +} CONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1, + IOCPage1_t, MPI_POINTER pIOCPage1_t; + +#define MPI_IOCPAGE1_PAGEVERSION (0x03) + +/* defines for the Flags field */ +#define MPI_IOCPAGE1_EEDP_MODE_MASK (0x07000000) +#define MPI_IOCPAGE1_EEDP_MODE_OFF (0x00000000) +#define MPI_IOCPAGE1_EEDP_MODE_T10 (0x01000000) +#define MPI_IOCPAGE1_EEDP_MODE_LSI_1 (0x02000000) +#define MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE (0x00000010) +#define MPI_IOCPAGE1_REPLY_COALESCING (0x00000001) + +#define MPI_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF) + + +typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL +{ + U8 VolumeID; /* 00h */ + U8 VolumeBus; /* 01h */ + U8 VolumeIOC; /* 02h */ + U8 VolumePageNumber; /* 03h */ + U8 VolumeType; /* 04h */ + U8 Flags; /* 05h */ + U16 Reserved3; /* 06h */ +} CONFIG_PAGE_IOC_2_RAID_VOL, MPI_POINTER PTR_CONFIG_PAGE_IOC_2_RAID_VOL, + ConfigPageIoc2RaidVol_t, MPI_POINTER pConfigPageIoc2RaidVol_t; + +/* IOC Page 2 Volume RAID Type values, also used in RAID Volume pages */ + +#define MPI_RAID_VOL_TYPE_IS (0x00) +#define MPI_RAID_VOL_TYPE_IME (0x01) +#define MPI_RAID_VOL_TYPE_IM (0x02) +#define MPI_RAID_VOL_TYPE_RAID_5 (0x03) +#define MPI_RAID_VOL_TYPE_RAID_6 (0x04) +#define MPI_RAID_VOL_TYPE_RAID_10 (0x05) +#define MPI_RAID_VOL_TYPE_RAID_50 (0x06) +#define MPI_RAID_VOL_TYPE_UNKNOWN (0xFF) + +/* IOC Page 2 Volume Flags values */ + +#define MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE (0x08) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_IOC_PAGE_2_RAID_VOLUME_MAX +#define MPI_IOC_PAGE_2_RAID_VOLUME_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_IOC_2 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 CapabilitiesFlags; /* 04h */ + U8 NumActiveVolumes; /* 08h */ + U8 MaxVolumes; /* 09h */ + U8 NumActivePhysDisks; /* 0Ah */ + U8 MaxPhysDisks; /* 0Bh */ + CONFIG_PAGE_IOC_2_RAID_VOL RaidVolume[MPI_IOC_PAGE_2_RAID_VOLUME_MAX];/* 0Ch */ +} CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2, + IOCPage2_t, MPI_POINTER pIOCPage2_t; + +#define MPI_IOCPAGE2_PAGEVERSION (0x04) + +/* IOC Page 2 Capabilities flags */ + +#define MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT (0x00000001) +#define MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT (0x00000002) +#define MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT (0x00000004) +#define MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT (0x00000008) +#define MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT (0x00000010) +#define MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT (0x00000020) +#define MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT (0x00000040) +#define MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING (0x10000000) +#define MPI_IOCPAGE2_CAP_FLAGS_SES_SUPPORT (0x20000000) +#define MPI_IOCPAGE2_CAP_FLAGS_SAFTE_SUPPORT (0x40000000) +#define MPI_IOCPAGE2_CAP_FLAGS_CROSS_CHANNEL_SUPPORT (0x80000000) + + +typedef struct _IOC_3_PHYS_DISK +{ + U8 PhysDiskID; /* 00h */ + U8 PhysDiskBus; /* 01h */ + U8 PhysDiskIOC; /* 02h */ + U8 PhysDiskNum; /* 03h */ +} IOC_3_PHYS_DISK, MPI_POINTER PTR_IOC_3_PHYS_DISK, + Ioc3PhysDisk_t, MPI_POINTER pIoc3PhysDisk_t; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_IOC_PAGE_3_PHYSDISK_MAX +#define MPI_IOC_PAGE_3_PHYSDISK_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_IOC_3 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 NumPhysDisks; /* 04h */ + U8 Reserved1; /* 05h */ + U16 Reserved2; /* 06h */ + IOC_3_PHYS_DISK PhysDisk[MPI_IOC_PAGE_3_PHYSDISK_MAX]; /* 08h */ +} CONFIG_PAGE_IOC_3, MPI_POINTER PTR_CONFIG_PAGE_IOC_3, + IOCPage3_t, MPI_POINTER pIOCPage3_t; + +#define MPI_IOCPAGE3_PAGEVERSION (0x00) + + +typedef struct _IOC_4_SEP +{ + U8 SEPTargetID; /* 00h */ + U8 SEPBus; /* 01h */ + U16 Reserved; /* 02h */ +} IOC_4_SEP, MPI_POINTER PTR_IOC_4_SEP, + Ioc4Sep_t, MPI_POINTER pIoc4Sep_t; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_IOC_PAGE_4_SEP_MAX +#define MPI_IOC_PAGE_4_SEP_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_IOC_4 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 ActiveSEP; /* 04h */ + U8 MaxSEP; /* 05h */ + U16 Reserved1; /* 06h */ + IOC_4_SEP SEP[MPI_IOC_PAGE_4_SEP_MAX]; /* 08h */ +} CONFIG_PAGE_IOC_4, MPI_POINTER PTR_CONFIG_PAGE_IOC_4, + IOCPage4_t, MPI_POINTER pIOCPage4_t; + +#define MPI_IOCPAGE4_PAGEVERSION (0x00) + + +typedef struct _IOC_5_HOT_SPARE +{ + U8 PhysDiskNum; /* 00h */ + U8 Reserved; /* 01h */ + U8 HotSparePool; /* 02h */ + U8 Flags; /* 03h */ +} IOC_5_HOT_SPARE, MPI_POINTER PTR_IOC_5_HOT_SPARE, + Ioc5HotSpare_t, MPI_POINTER pIoc5HotSpare_t; + +/* IOC Page 5 HotSpare Flags */ +#define MPI_IOC_PAGE_5_HOT_SPARE_ACTIVE (0x01) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_IOC_PAGE_5_HOT_SPARE_MAX +#define MPI_IOC_PAGE_5_HOT_SPARE_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_IOC_5 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 04h */ + U8 NumHotSpares; /* 08h */ + U8 Reserved2; /* 09h */ + U16 Reserved3; /* 0Ah */ + IOC_5_HOT_SPARE HotSpare[MPI_IOC_PAGE_5_HOT_SPARE_MAX]; /* 0Ch */ +} CONFIG_PAGE_IOC_5, MPI_POINTER PTR_CONFIG_PAGE_IOC_5, + IOCPage5_t, MPI_POINTER pIOCPage5_t; + +#define MPI_IOCPAGE5_PAGEVERSION (0x00) + +typedef struct _CONFIG_PAGE_IOC_6 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 CapabilitiesFlags; /* 04h */ + U8 MaxDrivesIS; /* 08h */ + U8 MaxDrivesIM; /* 09h */ + U8 MaxDrivesIME; /* 0Ah */ + U8 Reserved1; /* 0Bh */ + U8 MinDrivesIS; /* 0Ch */ + U8 MinDrivesIM; /* 0Dh */ + U8 MinDrivesIME; /* 0Eh */ + U8 Reserved2; /* 0Fh */ + U8 MaxGlobalHotSpares; /* 10h */ + U8 Reserved3; /* 11h */ + U16 Reserved4; /* 12h */ + U32 Reserved5; /* 14h */ + U32 SupportedStripeSizeMapIS; /* 18h */ + U32 SupportedStripeSizeMapIME; /* 1Ch */ + U32 Reserved6; /* 20h */ + U8 MetadataSize; /* 24h */ + U8 Reserved7; /* 25h */ + U16 Reserved8; /* 26h */ + U16 MaxBadBlockTableEntries; /* 28h */ + U16 Reserved9; /* 2Ah */ + U16 IRNvsramUsage; /* 2Ch */ + U16 Reserved10; /* 2Eh */ + U32 IRNvsramVersion; /* 30h */ + U32 Reserved11; /* 34h */ + U32 Reserved12; /* 38h */ +} CONFIG_PAGE_IOC_6, MPI_POINTER PTR_CONFIG_PAGE_IOC_6, + IOCPage6_t, MPI_POINTER pIOCPage6_t; + +#define MPI_IOCPAGE6_PAGEVERSION (0x01) + +/* IOC Page 6 Capabilities Flags */ + +#define MPI_IOCPAGE6_CAP_FLAGS_SSD_SUPPORT (0x00000020) +#define MPI_IOCPAGE6_CAP_FLAGS_MULTIPORT_DRIVE_SUPPORT (0x00000010) +#define MPI_IOCPAGE6_CAP_FLAGS_DISABLE_SMART_POLLING (0x00000008) + +#define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE (0x00000006) +#define MPI_IOCPAGE6_CAP_FLAGS_64MB_METADATA_SIZE (0x00000000) +#define MPI_IOCPAGE6_CAP_FLAGS_512MB_METADATA_SIZE (0x00000002) + +#define MPI_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001) + + +/**************************************************************************** +* BIOS Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_BIOS_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 BiosOptions; /* 04h */ + U32 IOCSettings; /* 08h */ + U32 Reserved1; /* 0Ch */ + U32 DeviceSettings; /* 10h */ + U16 NumberOfDevices; /* 14h */ + U8 ExpanderSpinup; /* 16h */ + U8 Reserved2; /* 17h */ + U16 IOTimeoutBlockDevicesNonRM; /* 18h */ + U16 IOTimeoutSequential; /* 1Ah */ + U16 IOTimeoutOther; /* 1Ch */ + U16 IOTimeoutBlockDevicesRM; /* 1Eh */ +} CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1, + BIOSPage1_t, MPI_POINTER pBIOSPage1_t; + +#define MPI_BIOSPAGE1_PAGEVERSION (0x03) + +/* values for the BiosOptions field */ +#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400) +#define MPI_BIOSPAGE1_OPTIONS_FC_ENABLE (0x00000200) +#define MPI_BIOSPAGE1_OPTIONS_SAS_ENABLE (0x00000100) + +#define MPI_BIOSPAGE1_OPTIONS_SCAN_HIGH_TO_LOW (0x00000002) +#define MPI_BIOSPAGE1_OPTIONS_SCAN_LOW_TO_HIGH (0x00000000) + +#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) + +/* values for the IOCSettings field */ +#define MPI_BIOSPAGE1_IOCSET_MASK_INITIAL_SPINUP_DELAY (0x0F000000) +#define MPI_BIOSPAGE1_IOCSET_SHIFT_INITIAL_SPINUP_DELAY (24) + +#define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000) +#define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20) + +#define MPI_BIOSPAGE1_IOCSET_AUTO_PORT_ENABLE (0x00080000) +#define MPI_BIOSPAGE1_IOCSET_DIRECT_ATTACH_SPINUP_MODE (0x00040000) + +#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) +#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) +#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) + +#define MPI_BIOSPAGE1_IOCSET_MASK_MAX_TARGET_SPIN_UP (0x0000F000) +#define MPI_BIOSPAGE1_IOCSET_SHIFT_MAX_TARGET_SPIN_UP (12) + +#define MPI_BIOSPAGE1_IOCSET_MASK_SPINUP_DELAY (0x00000F00) +#define MPI_BIOSPAGE1_IOCSET_SHIFT_SPINUP_DELAY (8) + +#define MPI_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0) +#define MPI_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000) +#define MPI_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040) +#define MPI_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080) + +#define MPI_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030) +#define MPI_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000) +#define MPI_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010) +#define MPI_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020) +#define MPI_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030) + +#define MPI_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008) + +/* values for the DeviceSettings field */ +#define MPI_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING (0x00000010) +#define MPI_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008) +#define MPI_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004) +#define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) +#define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) + +/* defines for the ExpanderSpinup field */ +#define MPI_BIOSPAGE1_EXPSPINUP_MASK_MAX_TARGET (0xF0) +#define MPI_BIOSPAGE1_EXPSPINUP_SHIFT_MAX_TARGET (4) +#define MPI_BIOSPAGE1_EXPSPINUP_MASK_DELAY (0x0F) + +typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER +{ + U32 Reserved1; /* 00h */ + U32 Reserved2; /* 04h */ + U32 Reserved3; /* 08h */ + U32 Reserved4; /* 0Ch */ + U32 Reserved5; /* 10h */ + U32 Reserved6; /* 14h */ + U32 Reserved7; /* 18h */ + U32 Reserved8; /* 1Ch */ + U32 Reserved9; /* 20h */ + U32 Reserved10; /* 24h */ + U32 Reserved11; /* 28h */ + U32 Reserved12; /* 2Ch */ + U32 Reserved13; /* 30h */ + U32 Reserved14; /* 34h */ + U32 Reserved15; /* 38h */ + U32 Reserved16; /* 3Ch */ + U32 Reserved17; /* 40h */ +} MPI_BOOT_DEVICE_ADAPTER_ORDER, MPI_POINTER PTR_MPI_BOOT_DEVICE_ADAPTER_ORDER; + +typedef struct _MPI_BOOT_DEVICE_ADAPTER_NUMBER +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 AdapterNumber; /* 02h */ + U8 Reserved1; /* 03h */ + U32 Reserved2; /* 04h */ + U32 Reserved3; /* 08h */ + U32 Reserved4; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 Reserved5; /* 18h */ + U32 Reserved6; /* 1Ch */ + U32 Reserved7; /* 20h */ + U32 Reserved8; /* 24h */ + U32 Reserved9; /* 28h */ + U32 Reserved10; /* 2Ch */ + U32 Reserved11; /* 30h */ + U32 Reserved12; /* 34h */ + U32 Reserved13; /* 38h */ + U32 Reserved14; /* 3Ch */ + U32 Reserved15; /* 40h */ +} MPI_BOOT_DEVICE_ADAPTER_NUMBER, MPI_POINTER PTR_MPI_BOOT_DEVICE_ADAPTER_NUMBER; + +typedef struct _MPI_BOOT_DEVICE_PCI_ADDRESS +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U16 PCIAddress; /* 02h */ + U32 Reserved1; /* 04h */ + U32 Reserved2; /* 08h */ + U32 Reserved3; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 Reserved4; /* 18h */ + U32 Reserved5; /* 1Ch */ + U32 Reserved6; /* 20h */ + U32 Reserved7; /* 24h */ + U32 Reserved8; /* 28h */ + U32 Reserved9; /* 2Ch */ + U32 Reserved10; /* 30h */ + U32 Reserved11; /* 34h */ + U32 Reserved12; /* 38h */ + U32 Reserved13; /* 3Ch */ + U32 Reserved14; /* 40h */ +} MPI_BOOT_DEVICE_PCI_ADDRESS, MPI_POINTER PTR_MPI_BOOT_DEVICE_PCI_ADDRESS; + +typedef struct _MPI_BOOT_DEVICE_SLOT_NUMBER +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 PCISlotNumber; /* 02h */ + U8 Reserved1; /* 03h */ + U32 Reserved2; /* 04h */ + U32 Reserved3; /* 08h */ + U32 Reserved4; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 Reserved5; /* 18h */ + U32 Reserved6; /* 1Ch */ + U32 Reserved7; /* 20h */ + U32 Reserved8; /* 24h */ + U32 Reserved9; /* 28h */ + U32 Reserved10; /* 2Ch */ + U32 Reserved11; /* 30h */ + U32 Reserved12; /* 34h */ + U32 Reserved13; /* 38h */ + U32 Reserved14; /* 3Ch */ + U32 Reserved15; /* 40h */ +} MPI_BOOT_DEVICE_PCI_SLOT_NUMBER, MPI_POINTER PTR_MPI_BOOT_DEVICE_PCI_SLOT_NUMBER; + +typedef struct _MPI_BOOT_DEVICE_FC_WWN +{ + U64 WWPN; /* 00h */ + U32 Reserved1; /* 08h */ + U32 Reserved2; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 Reserved3; /* 18h */ + U32 Reserved4; /* 1Ch */ + U32 Reserved5; /* 20h */ + U32 Reserved6; /* 24h */ + U32 Reserved7; /* 28h */ + U32 Reserved8; /* 2Ch */ + U32 Reserved9; /* 30h */ + U32 Reserved10; /* 34h */ + U32 Reserved11; /* 38h */ + U32 Reserved12; /* 3Ch */ + U32 Reserved13; /* 40h */ +} MPI_BOOT_DEVICE_FC_WWN, MPI_POINTER PTR_MPI_BOOT_DEVICE_FC_WWN; + +typedef struct _MPI_BOOT_DEVICE_SAS_WWN +{ + U64 SASAddress; /* 00h */ + U32 Reserved1; /* 08h */ + U32 Reserved2; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 Reserved3; /* 18h */ + U32 Reserved4; /* 1Ch */ + U32 Reserved5; /* 20h */ + U32 Reserved6; /* 24h */ + U32 Reserved7; /* 28h */ + U32 Reserved8; /* 2Ch */ + U32 Reserved9; /* 30h */ + U32 Reserved10; /* 34h */ + U32 Reserved11; /* 38h */ + U32 Reserved12; /* 3Ch */ + U32 Reserved13; /* 40h */ +} MPI_BOOT_DEVICE_SAS_WWN, MPI_POINTER PTR_MPI_BOOT_DEVICE_SAS_WWN; + +typedef struct _MPI_BOOT_DEVICE_ENCLOSURE_SLOT +{ + U64 EnclosureLogicalID; /* 00h */ + U32 Reserved1; /* 08h */ + U32 Reserved2; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U16 SlotNumber; /* 18h */ + U16 Reserved3; /* 1Ah */ + U32 Reserved4; /* 1Ch */ + U32 Reserved5; /* 20h */ + U32 Reserved6; /* 24h */ + U32 Reserved7; /* 28h */ + U32 Reserved8; /* 2Ch */ + U32 Reserved9; /* 30h */ + U32 Reserved10; /* 34h */ + U32 Reserved11; /* 38h */ + U32 Reserved12; /* 3Ch */ + U32 Reserved13; /* 40h */ +} MPI_BOOT_DEVICE_ENCLOSURE_SLOT, + MPI_POINTER PTR_MPI_BOOT_DEVICE_ENCLOSURE_SLOT; + +typedef union _MPI_BIOSPAGE2_BOOT_DEVICE +{ + MPI_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder; + MPI_BOOT_DEVICE_ADAPTER_NUMBER AdapterNumber; + MPI_BOOT_DEVICE_PCI_ADDRESS PCIAddress; + MPI_BOOT_DEVICE_PCI_SLOT_NUMBER PCISlotNumber; + MPI_BOOT_DEVICE_FC_WWN FcWwn; + MPI_BOOT_DEVICE_SAS_WWN SasWwn; + MPI_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot; +} MPI_BIOSPAGE2_BOOT_DEVICE, MPI_POINTER PTR_MPI_BIOSPAGE2_BOOT_DEVICE; + +typedef struct _CONFIG_PAGE_BIOS_2 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 04h */ + U32 Reserved2; /* 08h */ + U32 Reserved3; /* 0Ch */ + U32 Reserved4; /* 10h */ + U32 Reserved5; /* 14h */ + U32 Reserved6; /* 18h */ + U8 BootDeviceForm; /* 1Ch */ + U8 PrevBootDeviceForm; /* 1Ch */ + U16 Reserved8; /* 1Eh */ + MPI_BIOSPAGE2_BOOT_DEVICE BootDevice; /* 20h */ +} CONFIG_PAGE_BIOS_2, MPI_POINTER PTR_CONFIG_PAGE_BIOS_2, + BIOSPage2_t, MPI_POINTER pBIOSPage2_t; + +#define MPI_BIOSPAGE2_PAGEVERSION (0x02) + +#define MPI_BIOSPAGE2_FORM_MASK (0x0F) +#define MPI_BIOSPAGE2_FORM_ADAPTER_ORDER (0x00) +#define MPI_BIOSPAGE2_FORM_ADAPTER_NUMBER (0x01) +#define MPI_BIOSPAGE2_FORM_PCI_ADDRESS (0x02) +#define MPI_BIOSPAGE2_FORM_PCI_SLOT_NUMBER (0x03) +#define MPI_BIOSPAGE2_FORM_FC_WWN (0x04) +#define MPI_BIOSPAGE2_FORM_SAS_WWN (0x05) +#define MPI_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06) + +typedef struct _CONFIG_PAGE_BIOS_4 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U64 ReassignmentBaseWWID; /* 04h */ +} CONFIG_PAGE_BIOS_4, MPI_POINTER PTR_CONFIG_PAGE_BIOS_4, + BIOSPage4_t, MPI_POINTER pBIOSPage4_t; + +#define MPI_BIOSPAGE4_PAGEVERSION (0x00) + + +/**************************************************************************** +* SCSI Port Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_SCSI_PORT_0 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Capabilities; /* 04h */ + U32 PhysicalInterface; /* 08h */ +} CONFIG_PAGE_SCSI_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_0, + SCSIPortPage0_t, MPI_POINTER pSCSIPortPage0_t; + +#define MPI_SCSIPORTPAGE0_PAGEVERSION (0x02) + +#define MPI_SCSIPORTPAGE0_CAP_IU (0x00000001) +#define MPI_SCSIPORTPAGE0_CAP_DT (0x00000002) +#define MPI_SCSIPORTPAGE0_CAP_QAS (0x00000004) +#define MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK (0x0000FF00) +#define MPI_SCSIPORTPAGE0_SYNC_ASYNC (0x00) +#define MPI_SCSIPORTPAGE0_SYNC_5 (0x32) +#define MPI_SCSIPORTPAGE0_SYNC_10 (0x19) +#define MPI_SCSIPORTPAGE0_SYNC_20 (0x0C) +#define MPI_SCSIPORTPAGE0_SYNC_33_33 (0x0B) +#define MPI_SCSIPORTPAGE0_SYNC_40 (0x0A) +#define MPI_SCSIPORTPAGE0_SYNC_80 (0x09) +#define MPI_SCSIPORTPAGE0_SYNC_160 (0x08) +#define MPI_SCSIPORTPAGE0_SYNC_UNKNOWN (0xFF) + +#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD (8) +#define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap) \ + ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK) \ + >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD \ + ) +#define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000) +#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET (16) +#define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap) \ + ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK) \ + >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \ + ) +#define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000) +#define MPI_SCSIPORTPAGE0_CAP_WIDE (0x20000000) +#define MPI_SCSIPORTPAGE0_CAP_AIP (0x80000000) + +#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK (0x00000003) +#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD (0x01) +#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE (0x02) +#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_LVD (0x03) +#define MPI_SCSIPORTPAGE0_PHY_MASK_CONNECTED_ID (0xFF000000) +#define MPI_SCSIPORTPAGE0_PHY_SHIFT_CONNECTED_ID (24) +#define MPI_SCSIPORTPAGE0_PHY_BUS_FREE_CONNECTED_ID (0xFE) +#define MPI_SCSIPORTPAGE0_PHY_UNKNOWN_CONNECTED_ID (0xFF) + + +typedef struct _CONFIG_PAGE_SCSI_PORT_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Configuration; /* 04h */ + U32 OnBusTimerValue; /* 08h */ + U8 TargetConfig; /* 0Ch */ + U8 Reserved1; /* 0Dh */ + U16 IDConfig; /* 0Eh */ +} CONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1, + SCSIPortPage1_t, MPI_POINTER pSCSIPortPage1_t; + +#define MPI_SCSIPORTPAGE1_PAGEVERSION (0x03) + +/* Configuration values */ +#define MPI_SCSIPORTPAGE1_CFG_PORT_SCSI_ID_MASK (0x000000FF) +#define MPI_SCSIPORTPAGE1_CFG_PORT_RESPONSE_ID_MASK (0xFFFF0000) +#define MPI_SCSIPORTPAGE1_CFG_SHIFT_PORT_RESPONSE_ID (16) + +/* TargetConfig values */ +#define MPI_SCSIPORTPAGE1_TARGCONFIG_TARG_ONLY (0x01) +#define MPI_SCSIPORTPAGE1_TARGCONFIG_INIT_TARG (0x02) + + +typedef struct _MPI_DEVICE_INFO +{ + U8 Timeout; /* 00h */ + U8 SyncFactor; /* 01h */ + U16 DeviceFlags; /* 02h */ +} MPI_DEVICE_INFO, MPI_POINTER PTR_MPI_DEVICE_INFO, + MpiDeviceInfo_t, MPI_POINTER pMpiDeviceInfo_t; + +typedef struct _CONFIG_PAGE_SCSI_PORT_2 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 PortFlags; /* 04h */ + U32 PortSettings; /* 08h */ + MPI_DEVICE_INFO DeviceSettings[16]; /* 0Ch */ +} CONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2, + SCSIPortPage2_t, MPI_POINTER pSCSIPortPage2_t; + +#define MPI_SCSIPORTPAGE2_PAGEVERSION (0x02) + +/* PortFlags values */ +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_SCAN_HIGH_TO_LOW (0x00000001) +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET (0x00000004) +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_ALTERNATE_CHS (0x00000008) +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_TERMINATION_DISABLE (0x00000010) + +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK (0x00000060) +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_FULL_DV (0x00000000) +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY (0x00000020) +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV (0x00000060) + + +/* PortSettings values */ +#define MPI_SCSIPORTPAGE2_PORT_HOST_ID_MASK (0x0000000F) +#define MPI_SCSIPORTPAGE2_PORT_MASK_INIT_HBA (0x00000030) +#define MPI_SCSIPORTPAGE2_PORT_DISABLE_INIT_HBA (0x00000000) +#define MPI_SCSIPORTPAGE2_PORT_BIOS_INIT_HBA (0x00000010) +#define MPI_SCSIPORTPAGE2_PORT_OS_INIT_HBA (0x00000020) +#define MPI_SCSIPORTPAGE2_PORT_BIOS_OS_INIT_HBA (0x00000030) +#define MPI_SCSIPORTPAGE2_PORT_REMOVABLE_MEDIA (0x000000C0) +#define MPI_SCSIPORTPAGE2_PORT_RM_NONE (0x00000000) +#define MPI_SCSIPORTPAGE2_PORT_RM_BOOT_ONLY (0x00000040) +#define MPI_SCSIPORTPAGE2_PORT_RM_WITH_MEDIA (0x00000080) +#define MPI_SCSIPORTPAGE2_PORT_SPINUP_DELAY_MASK (0x00000F00) +#define MPI_SCSIPORTPAGE2_PORT_SHIFT_SPINUP_DELAY (8) +#define MPI_SCSIPORTPAGE2_PORT_MASK_NEGO_MASTER_SETTINGS (0x00003000) +#define MPI_SCSIPORTPAGE2_PORT_NEGO_MASTER_SETTINGS (0x00000000) +#define MPI_SCSIPORTPAGE2_PORT_NONE_MASTER_SETTINGS (0x00001000) +#define MPI_SCSIPORTPAGE2_PORT_ALL_MASTER_SETTINGS (0x00003000) + +#define MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE (0x0001) +#define MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE (0x0002) +#define MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE (0x0004) +#define MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE (0x0008) +#define MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE (0x0010) +#define MPI_SCSIPORTPAGE2_DEVICE_BOOT_CHOICE (0x0020) + + +/**************************************************************************** +* SCSI Target Device Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_SCSI_DEVICE_0 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 NegotiatedParameters; /* 04h */ + U32 Information; /* 08h */ +} CONFIG_PAGE_SCSI_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_0, + SCSIDevicePage0_t, MPI_POINTER pSCSIDevicePage0_t; + +#define MPI_SCSIDEVPAGE0_PAGEVERSION (0x04) + +#define MPI_SCSIDEVPAGE0_NP_IU (0x00000001) +#define MPI_SCSIDEVPAGE0_NP_DT (0x00000002) +#define MPI_SCSIDEVPAGE0_NP_QAS (0x00000004) +#define MPI_SCSIDEVPAGE0_NP_HOLD_MCS (0x00000008) +#define MPI_SCSIDEVPAGE0_NP_WR_FLOW (0x00000010) +#define MPI_SCSIDEVPAGE0_NP_RD_STRM (0x00000020) +#define MPI_SCSIDEVPAGE0_NP_RTI (0x00000040) +#define MPI_SCSIDEVPAGE0_NP_PCOMP_EN (0x00000080) +#define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK (0x0000FF00) +#define MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD (8) +#define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK (0x00FF0000) +#define MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET (16) +#define MPI_SCSIDEVPAGE0_NP_IDP (0x08000000) +#define MPI_SCSIDEVPAGE0_NP_WIDE (0x20000000) +#define MPI_SCSIDEVPAGE0_NP_AIP (0x80000000) + +#define MPI_SCSIDEVPAGE0_INFO_PARAMS_NEGOTIATED (0x00000001) +#define MPI_SCSIDEVPAGE0_INFO_SDTR_REJECTED (0x00000002) +#define MPI_SCSIDEVPAGE0_INFO_WDTR_REJECTED (0x00000004) +#define MPI_SCSIDEVPAGE0_INFO_PPR_REJECTED (0x00000008) + + +typedef struct _CONFIG_PAGE_SCSI_DEVICE_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 RequestedParameters; /* 04h */ + U32 Reserved; /* 08h */ + U32 Configuration; /* 0Ch */ +} CONFIG_PAGE_SCSI_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_1, + SCSIDevicePage1_t, MPI_POINTER pSCSIDevicePage1_t; + +#define MPI_SCSIDEVPAGE1_PAGEVERSION (0x05) + +#define MPI_SCSIDEVPAGE1_RP_IU (0x00000001) +#define MPI_SCSIDEVPAGE1_RP_DT (0x00000002) +#define MPI_SCSIDEVPAGE1_RP_QAS (0x00000004) +#define MPI_SCSIDEVPAGE1_RP_HOLD_MCS (0x00000008) +#define MPI_SCSIDEVPAGE1_RP_WR_FLOW (0x00000010) +#define MPI_SCSIDEVPAGE1_RP_RD_STRM (0x00000020) +#define MPI_SCSIDEVPAGE1_RP_RTI (0x00000040) +#define MPI_SCSIDEVPAGE1_RP_PCOMP_EN (0x00000080) +#define MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK (0x0000FF00) +#define MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD (8) +#define MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK (0x00FF0000) +#define MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET (16) +#define MPI_SCSIDEVPAGE1_RP_IDP (0x08000000) +#define MPI_SCSIDEVPAGE1_RP_WIDE (0x20000000) +#define MPI_SCSIDEVPAGE1_RP_AIP (0x80000000) + +#define MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED (0x00000002) +#define MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED (0x00000004) +#define MPI_SCSIDEVPAGE1_CONF_EXTENDED_PARAMS_ENABLE (0x00000008) +#define MPI_SCSIDEVPAGE1_CONF_FORCE_PPR_MSG (0x00000010) + + +typedef struct _CONFIG_PAGE_SCSI_DEVICE_2 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 DomainValidation; /* 04h */ + U32 ParityPipeSelect; /* 08h */ + U32 DataPipeSelect; /* 0Ch */ +} CONFIG_PAGE_SCSI_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_2, + SCSIDevicePage2_t, MPI_POINTER pSCSIDevicePage2_t; + +#define MPI_SCSIDEVPAGE2_PAGEVERSION (0x01) + +#define MPI_SCSIDEVPAGE2_DV_ISI_ENABLE (0x00000010) +#define MPI_SCSIDEVPAGE2_DV_SECONDARY_DRIVER_ENABLE (0x00000020) +#define MPI_SCSIDEVPAGE2_DV_SLEW_RATE_CTRL (0x00000380) +#define MPI_SCSIDEVPAGE2_DV_PRIM_DRIVE_STR_CTRL (0x00001C00) +#define MPI_SCSIDEVPAGE2_DV_SECOND_DRIVE_STR_CTRL (0x0000E000) +#define MPI_SCSIDEVPAGE2_DV_XCLKH_ST (0x10000000) +#define MPI_SCSIDEVPAGE2_DV_XCLKS_ST (0x20000000) +#define MPI_SCSIDEVPAGE2_DV_XCLKH_DT (0x40000000) +#define MPI_SCSIDEVPAGE2_DV_XCLKS_DT (0x80000000) + +#define MPI_SCSIDEVPAGE2_PPS_PPS_MASK (0x00000003) + +#define MPI_SCSIDEVPAGE2_DPS_BIT_0_PL_SELECT_MASK (0x00000003) +#define MPI_SCSIDEVPAGE2_DPS_BIT_1_PL_SELECT_MASK (0x0000000C) +#define MPI_SCSIDEVPAGE2_DPS_BIT_2_PL_SELECT_MASK (0x00000030) +#define MPI_SCSIDEVPAGE2_DPS_BIT_3_PL_SELECT_MASK (0x000000C0) +#define MPI_SCSIDEVPAGE2_DPS_BIT_4_PL_SELECT_MASK (0x00000300) +#define MPI_SCSIDEVPAGE2_DPS_BIT_5_PL_SELECT_MASK (0x00000C00) +#define MPI_SCSIDEVPAGE2_DPS_BIT_6_PL_SELECT_MASK (0x00003000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_7_PL_SELECT_MASK (0x0000C000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_8_PL_SELECT_MASK (0x00030000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_9_PL_SELECT_MASK (0x000C0000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_10_PL_SELECT_MASK (0x00300000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_11_PL_SELECT_MASK (0x00C00000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_12_PL_SELECT_MASK (0x03000000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_13_PL_SELECT_MASK (0x0C000000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_14_PL_SELECT_MASK (0x30000000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_15_PL_SELECT_MASK (0xC0000000) + + +typedef struct _CONFIG_PAGE_SCSI_DEVICE_3 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U16 MsgRejectCount; /* 04h */ + U16 PhaseErrorCount; /* 06h */ + U16 ParityErrorCount; /* 08h */ + U16 Reserved; /* 0Ah */ +} CONFIG_PAGE_SCSI_DEVICE_3, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_3, + SCSIDevicePage3_t, MPI_POINTER pSCSIDevicePage3_t; + +#define MPI_SCSIDEVPAGE3_PAGEVERSION (0x00) + +#define MPI_SCSIDEVPAGE3_MAX_COUNTER (0xFFFE) +#define MPI_SCSIDEVPAGE3_UNSUPPORTED_COUNTER (0xFFFF) + + +/**************************************************************************** +* FC Port Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_FC_PORT_0 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Flags; /* 04h */ + U8 MPIPortNumber; /* 08h */ + U8 LinkType; /* 09h */ + U8 PortState; /* 0Ah */ + U8 Reserved; /* 0Bh */ + U32 PortIdentifier; /* 0Ch */ + U64 WWNN; /* 10h */ + U64 WWPN; /* 18h */ + U32 SupportedServiceClass; /* 20h */ + U32 SupportedSpeeds; /* 24h */ + U32 CurrentSpeed; /* 28h */ + U32 MaxFrameSize; /* 2Ch */ + U64 FabricWWNN; /* 30h */ + U64 FabricWWPN; /* 38h */ + U32 DiscoveredPortsCount; /* 40h */ + U32 MaxInitiators; /* 44h */ + U8 MaxAliasesSupported; /* 48h */ + U8 MaxHardAliasesSupported; /* 49h */ + U8 NumCurrentAliases; /* 4Ah */ + U8 Reserved1; /* 4Bh */ +} CONFIG_PAGE_FC_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_0, + FCPortPage0_t, MPI_POINTER pFCPortPage0_t; + +#define MPI_FCPORTPAGE0_PAGEVERSION (0x02) + +#define MPI_FCPORTPAGE0_FLAGS_PROT_MASK (0x0000000F) +#define MPI_FCPORTPAGE0_FLAGS_PROT_FCP_INIT (MPI_PORTFACTS_PROTOCOL_INITIATOR) +#define MPI_FCPORTPAGE0_FLAGS_PROT_FCP_TARG (MPI_PORTFACTS_PROTOCOL_TARGET) +#define MPI_FCPORTPAGE0_FLAGS_PROT_LAN (MPI_PORTFACTS_PROTOCOL_LAN) +#define MPI_FCPORTPAGE0_FLAGS_PROT_LOGBUSADDR (MPI_PORTFACTS_PROTOCOL_LOGBUSADDR) + +#define MPI_FCPORTPAGE0_FLAGS_ALIAS_ALPA_SUPPORTED (0x00000010) +#define MPI_FCPORTPAGE0_FLAGS_ALIAS_WWN_SUPPORTED (0x00000020) +#define MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID (0x00000040) + +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK (0x00000F00) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT (0x00000000) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT (0x00000100) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP (0x00000200) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT (0x00000400) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP (0x00000800) + +#define MPI_FCPORTPAGE0_LTYPE_RESERVED (0x00) +#define MPI_FCPORTPAGE0_LTYPE_OTHER (0x01) +#define MPI_FCPORTPAGE0_LTYPE_UNKNOWN (0x02) +#define MPI_FCPORTPAGE0_LTYPE_COPPER (0x03) +#define MPI_FCPORTPAGE0_LTYPE_SINGLE_1300 (0x04) +#define MPI_FCPORTPAGE0_LTYPE_SINGLE_1500 (0x05) +#define MPI_FCPORTPAGE0_LTYPE_50_LASER_MULTI (0x06) +#define MPI_FCPORTPAGE0_LTYPE_50_LED_MULTI (0x07) +#define MPI_FCPORTPAGE0_LTYPE_62_LASER_MULTI (0x08) +#define MPI_FCPORTPAGE0_LTYPE_62_LED_MULTI (0x09) +#define MPI_FCPORTPAGE0_LTYPE_MULTI_LONG_WAVE (0x0A) +#define MPI_FCPORTPAGE0_LTYPE_MULTI_SHORT_WAVE (0x0B) +#define MPI_FCPORTPAGE0_LTYPE_LASER_SHORT_WAVE (0x0C) +#define MPI_FCPORTPAGE0_LTYPE_LED_SHORT_WAVE (0x0D) +#define MPI_FCPORTPAGE0_LTYPE_1300_LONG_WAVE (0x0E) +#define MPI_FCPORTPAGE0_LTYPE_1500_LONG_WAVE (0x0F) + +#define MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN (0x01) /*(SNIA)HBA_PORTSTATE_UNKNOWN 1 Unknown */ +#define MPI_FCPORTPAGE0_PORTSTATE_ONLINE (0x02) /*(SNIA)HBA_PORTSTATE_ONLINE 2 Operational */ +#define MPI_FCPORTPAGE0_PORTSTATE_OFFLINE (0x03) /*(SNIA)HBA_PORTSTATE_OFFLINE 3 User Offline */ +#define MPI_FCPORTPAGE0_PORTSTATE_BYPASSED (0x04) /*(SNIA)HBA_PORTSTATE_BYPASSED 4 Bypassed */ +#define MPI_FCPORTPAGE0_PORTSTATE_DIAGNOST (0x05) /*(SNIA)HBA_PORTSTATE_DIAGNOSTICS 5 In diagnostics mode */ +#define MPI_FCPORTPAGE0_PORTSTATE_LINKDOWN (0x06) /*(SNIA)HBA_PORTSTATE_LINKDOWN 6 Link Down */ +#define MPI_FCPORTPAGE0_PORTSTATE_ERROR (0x07) /*(SNIA)HBA_PORTSTATE_ERROR 7 Port Error */ +#define MPI_FCPORTPAGE0_PORTSTATE_LOOPBACK (0x08) /*(SNIA)HBA_PORTSTATE_LOOPBACK 8 Loopback */ + +#define MPI_FCPORTPAGE0_SUPPORT_CLASS_1 (0x00000001) +#define MPI_FCPORTPAGE0_SUPPORT_CLASS_2 (0x00000002) +#define MPI_FCPORTPAGE0_SUPPORT_CLASS_3 (0x00000004) + +#define MPI_FCPORTPAGE0_SUPPORT_SPEED_UKNOWN (0x00000000) /* (SNIA)HBA_PORTSPEED_UNKNOWN 0 Unknown - transceiver incapable of reporting */ +#define MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED (0x00000001) /* (SNIA)HBA_PORTSPEED_1GBIT 1 1 GBit/sec */ +#define MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED (0x00000002) /* (SNIA)HBA_PORTSPEED_2GBIT 2 2 GBit/sec */ +#define MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED (0x00000004) /* (SNIA)HBA_PORTSPEED_10GBIT 4 10 GBit/sec */ +#define MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED (0x00000008) /* (SNIA)HBA_PORTSPEED_4GBIT 8 4 GBit/sec */ + +#define MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN MPI_FCPORTPAGE0_SUPPORT_SPEED_UKNOWN +#define MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED +#define MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED +#define MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED +#define MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED +#define MPI_FCPORTPAGE0_CURRENT_SPEED_NOT_NEGOTIATED (0x00008000) /* (SNIA)HBA_PORTSPEED_NOT_NEGOTIATED (1<<15) Speed not established */ + + +typedef struct _CONFIG_PAGE_FC_PORT_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Flags; /* 04h */ + U64 NoSEEPROMWWNN; /* 08h */ + U64 NoSEEPROMWWPN; /* 10h */ + U8 HardALPA; /* 18h */ + U8 LinkConfig; /* 19h */ + U8 TopologyConfig; /* 1Ah */ + U8 AltConnector; /* 1Bh */ + U8 NumRequestedAliases; /* 1Ch */ + U8 RR_TOV; /* 1Dh */ + U8 InitiatorDeviceTimeout; /* 1Eh */ + U8 InitiatorIoPendTimeout; /* 1Fh */ +} CONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1, + FCPortPage1_t, MPI_POINTER pFCPortPage1_t; + +#define MPI_FCPORTPAGE1_PAGEVERSION (0x06) + +#define MPI_FCPORTPAGE1_FLAGS_EXT_FCP_STATUS_EN (0x08000000) +#define MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY (0x04000000) +#define MPI_FCPORTPAGE1_FLAGS_FORCE_USE_NOSEEPROM_WWNS (0x02000000) +#define MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS (0x01000000) +#define MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID (0x00800000) +#define MPI_FCPORTPAGE1_FLAGS_PORT_OFFLINE (0x00400000) +#define MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK (0x00200000) +#define MPI_FCPORTPAGE1_FLAGS_TARGET_LARGE_CDB_ENABLE (0x00000080) +#define MPI_FCPORTPAGE1_FLAGS_MASK_RR_TOV_UNITS (0x00000070) +#define MPI_FCPORTPAGE1_FLAGS_SUPPRESS_PROT_REG (0x00000008) +#define MPI_FCPORTPAGE1_FLAGS_PLOGI_ON_LOGO (0x00000004) +#define MPI_FCPORTPAGE1_FLAGS_MAINTAIN_LOGINS (0x00000002) +#define MPI_FCPORTPAGE1_FLAGS_SORT_BY_DID (0x00000001) +#define MPI_FCPORTPAGE1_FLAGS_SORT_BY_WWN (0x00000000) + +#define MPI_FCPORTPAGE1_FLAGS_PROT_MASK (0xF0000000) +#define MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT (28) +#define MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT ((U32)MPI_PORTFACTS_PROTOCOL_INITIATOR << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT) +#define MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG ((U32)MPI_PORTFACTS_PROTOCOL_TARGET << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT) +#define MPI_FCPORTPAGE1_FLAGS_PROT_LAN ((U32)MPI_PORTFACTS_PROTOCOL_LAN << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT) +#define MPI_FCPORTPAGE1_FLAGS_PROT_LOGBUSADDR ((U32)MPI_PORTFACTS_PROTOCOL_LOGBUSADDR << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT) + +#define MPI_FCPORTPAGE1_FLAGS_NONE_RR_TOV_UNITS (0x00000000) +#define MPI_FCPORTPAGE1_FLAGS_THOUSANDTH_RR_TOV_UNITS (0x00000010) +#define MPI_FCPORTPAGE1_FLAGS_TENTH_RR_TOV_UNITS (0x00000030) +#define MPI_FCPORTPAGE1_FLAGS_TEN_RR_TOV_UNITS (0x00000050) + +#define MPI_FCPORTPAGE1_HARD_ALPA_NOT_USED (0xFF) + +#define MPI_FCPORTPAGE1_LCONFIG_SPEED_MASK (0x0F) +#define MPI_FCPORTPAGE1_LCONFIG_SPEED_1GIG (0x00) +#define MPI_FCPORTPAGE1_LCONFIG_SPEED_2GIG (0x01) +#define MPI_FCPORTPAGE1_LCONFIG_SPEED_4GIG (0x02) +#define MPI_FCPORTPAGE1_LCONFIG_SPEED_10GIG (0x03) +#define MPI_FCPORTPAGE1_LCONFIG_SPEED_AUTO (0x0F) + +#define MPI_FCPORTPAGE1_TOPOLOGY_MASK (0x0F) +#define MPI_FCPORTPAGE1_TOPOLOGY_NLPORT (0x01) +#define MPI_FCPORTPAGE1_TOPOLOGY_NPORT (0x02) +#define MPI_FCPORTPAGE1_TOPOLOGY_AUTO (0x0F) + +#define MPI_FCPORTPAGE1_ALT_CONN_UNKNOWN (0x00) + +#define MPI_FCPORTPAGE1_INITIATOR_DEV_TIMEOUT_MASK (0x7F) +#define MPI_FCPORTPAGE1_INITIATOR_DEV_UNIT_16 (0x80) + + +typedef struct _CONFIG_PAGE_FC_PORT_2 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 NumberActive; /* 04h */ + U8 ALPA[127]; /* 05h */ +} CONFIG_PAGE_FC_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_2, + FCPortPage2_t, MPI_POINTER pFCPortPage2_t; + +#define MPI_FCPORTPAGE2_PAGEVERSION (0x01) + + +typedef struct _WWN_FORMAT +{ + U64 WWNN; /* 00h */ + U64 WWPN; /* 08h */ +} WWN_FORMAT, MPI_POINTER PTR_WWN_FORMAT, + WWNFormat, MPI_POINTER pWWNFormat; + +typedef union _FC_PORT_PERSISTENT_PHYSICAL_ID +{ + WWN_FORMAT WWN; + U32 Did; +} FC_PORT_PERSISTENT_PHYSICAL_ID, MPI_POINTER PTR_FC_PORT_PERSISTENT_PHYSICAL_ID, + PersistentPhysicalId_t, MPI_POINTER pPersistentPhysicalId_t; + +typedef struct _FC_PORT_PERSISTENT +{ + FC_PORT_PERSISTENT_PHYSICAL_ID PhysicalIdentifier; /* 00h */ + U8 TargetID; /* 10h */ + U8 Bus; /* 11h */ + U16 Flags; /* 12h */ +} FC_PORT_PERSISTENT, MPI_POINTER PTR_FC_PORT_PERSISTENT, + PersistentData_t, MPI_POINTER pPersistentData_t; + +#define MPI_PERSISTENT_FLAGS_SHIFT (16) +#define MPI_PERSISTENT_FLAGS_ENTRY_VALID (0x0001) +#define MPI_PERSISTENT_FLAGS_SCAN_ID (0x0002) +#define MPI_PERSISTENT_FLAGS_SCAN_LUNS (0x0004) +#define MPI_PERSISTENT_FLAGS_BOOT_DEVICE (0x0008) +#define MPI_PERSISTENT_FLAGS_BY_DID (0x0080) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_FC_PORT_PAGE_3_ENTRY_MAX +#define MPI_FC_PORT_PAGE_3_ENTRY_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_FC_PORT_3 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + FC_PORT_PERSISTENT Entry[MPI_FC_PORT_PAGE_3_ENTRY_MAX]; /* 04h */ +} CONFIG_PAGE_FC_PORT_3, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_3, + FCPortPage3_t, MPI_POINTER pFCPortPage3_t; + +#define MPI_FCPORTPAGE3_PAGEVERSION (0x01) + + +typedef struct _CONFIG_PAGE_FC_PORT_4 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 PortFlags; /* 04h */ + U32 PortSettings; /* 08h */ +} CONFIG_PAGE_FC_PORT_4, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_4, + FCPortPage4_t, MPI_POINTER pFCPortPage4_t; + +#define MPI_FCPORTPAGE4_PAGEVERSION (0x00) + +#define MPI_FCPORTPAGE4_PORT_FLAGS_ALTERNATE_CHS (0x00000008) + +#define MPI_FCPORTPAGE4_PORT_MASK_INIT_HBA (0x00000030) +#define MPI_FCPORTPAGE4_PORT_DISABLE_INIT_HBA (0x00000000) +#define MPI_FCPORTPAGE4_PORT_BIOS_INIT_HBA (0x00000010) +#define MPI_FCPORTPAGE4_PORT_OS_INIT_HBA (0x00000020) +#define MPI_FCPORTPAGE4_PORT_BIOS_OS_INIT_HBA (0x00000030) +#define MPI_FCPORTPAGE4_PORT_REMOVABLE_MEDIA (0x000000C0) +#define MPI_FCPORTPAGE4_PORT_SPINUP_DELAY_MASK (0x00000F00) + + +typedef struct _CONFIG_PAGE_FC_PORT_5_ALIAS_INFO +{ + U8 Flags; /* 00h */ + U8 AliasAlpa; /* 01h */ + U16 DomainArea; /* 02h */ + U64 AliasWWNN; /* 04h */ + U64 AliasWWPN; /* 0Ch */ +} CONFIG_PAGE_FC_PORT_5_ALIAS_INFO, + MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5_ALIAS_INFO, + FcPortPage5AliasInfo_t, MPI_POINTER pFcPortPage5AliasInfo_t; + +typedef struct _CONFIG_PAGE_FC_PORT_5 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_FC_PORT_5_ALIAS_INFO AliasInfo; /* 04h */ +} CONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5, + FCPortPage5_t, MPI_POINTER pFCPortPage5_t; + +#define MPI_FCPORTPAGE5_PAGEVERSION (0x02) + +#define MPI_FCPORTPAGE5_FLAGS_ALPA_ACQUIRED (0x01) +#define MPI_FCPORTPAGE5_FLAGS_HARD_ALPA (0x02) +#define MPI_FCPORTPAGE5_FLAGS_HARD_WWNN (0x04) +#define MPI_FCPORTPAGE5_FLAGS_HARD_WWPN (0x08) +#define MPI_FCPORTPAGE5_FLAGS_DISABLE (0x10) + +typedef struct _CONFIG_PAGE_FC_PORT_6 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved; /* 04h */ + U64 TimeSinceReset; /* 08h */ + U64 TxFrames; /* 10h */ + U64 RxFrames; /* 18h */ + U64 TxWords; /* 20h */ + U64 RxWords; /* 28h */ + U64 LipCount; /* 30h */ + U64 NosCount; /* 38h */ + U64 ErrorFrames; /* 40h */ + U64 DumpedFrames; /* 48h */ + U64 LinkFailureCount; /* 50h */ + U64 LossOfSyncCount; /* 58h */ + U64 LossOfSignalCount; /* 60h */ + U64 PrimativeSeqErrCount; /* 68h */ + U64 InvalidTxWordCount; /* 70h */ + U64 InvalidCrcCount; /* 78h */ + U64 FcpInitiatorIoCount; /* 80h */ +} CONFIG_PAGE_FC_PORT_6, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_6, + FCPortPage6_t, MPI_POINTER pFCPortPage6_t; + +#define MPI_FCPORTPAGE6_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_FC_PORT_7 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved; /* 04h */ + U8 PortSymbolicName[256]; /* 08h */ +} CONFIG_PAGE_FC_PORT_7, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_7, + FCPortPage7_t, MPI_POINTER pFCPortPage7_t; + +#define MPI_FCPORTPAGE7_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_FC_PORT_8 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 BitVector[8]; /* 04h */ +} CONFIG_PAGE_FC_PORT_8, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_8, + FCPortPage8_t, MPI_POINTER pFCPortPage8_t; + +#define MPI_FCPORTPAGE8_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_FC_PORT_9 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved; /* 04h */ + U64 GlobalWWPN; /* 08h */ + U64 GlobalWWNN; /* 10h */ + U32 UnitType; /* 18h */ + U32 PhysicalPortNumber; /* 1Ch */ + U32 NumAttachedNodes; /* 20h */ + U16 IPVersion; /* 24h */ + U16 UDPPortNumber; /* 26h */ + U8 IPAddress[16]; /* 28h */ + U16 Reserved1; /* 38h */ + U16 TopologyDiscoveryFlags; /* 3Ah */ +} CONFIG_PAGE_FC_PORT_9, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_9, + FCPortPage9_t, MPI_POINTER pFCPortPage9_t; + +#define MPI_FCPORTPAGE9_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA +{ + U8 Id; /* 10h */ + U8 ExtId; /* 11h */ + U8 Connector; /* 12h */ + U8 Transceiver[8]; /* 13h */ + U8 Encoding; /* 1Bh */ + U8 BitRate_100mbs; /* 1Ch */ + U8 Reserved1; /* 1Dh */ + U8 Length9u_km; /* 1Eh */ + U8 Length9u_100m; /* 1Fh */ + U8 Length50u_10m; /* 20h */ + U8 Length62p5u_10m; /* 21h */ + U8 LengthCopper_m; /* 22h */ + U8 Reseverved2; /* 22h */ + U8 VendorName[16]; /* 24h */ + U8 Reserved3; /* 34h */ + U8 VendorOUI[3]; /* 35h */ + U8 VendorPN[16]; /* 38h */ + U8 VendorRev[4]; /* 48h */ + U16 Wavelength; /* 4Ch */ + U8 Reserved4; /* 4Eh */ + U8 CC_BASE; /* 4Fh */ +} CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA, + MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA, + FCPortPage10BaseSfpData_t, MPI_POINTER pFCPortPage10BaseSfpData_t; + +#define MPI_FCPORT10_BASE_ID_UNKNOWN (0x00) +#define MPI_FCPORT10_BASE_ID_GBIC (0x01) +#define MPI_FCPORT10_BASE_ID_FIXED (0x02) +#define MPI_FCPORT10_BASE_ID_SFP (0x03) +#define MPI_FCPORT10_BASE_ID_SFP_MIN (0x04) +#define MPI_FCPORT10_BASE_ID_SFP_MAX (0x7F) +#define MPI_FCPORT10_BASE_ID_VEND_SPEC_MASK (0x80) + +#define MPI_FCPORT10_BASE_EXTID_UNKNOWN (0x00) +#define MPI_FCPORT10_BASE_EXTID_MODDEF1 (0x01) +#define MPI_FCPORT10_BASE_EXTID_MODDEF2 (0x02) +#define MPI_FCPORT10_BASE_EXTID_MODDEF3 (0x03) +#define MPI_FCPORT10_BASE_EXTID_SEEPROM (0x04) +#define MPI_FCPORT10_BASE_EXTID_MODDEF5 (0x05) +#define MPI_FCPORT10_BASE_EXTID_MODDEF6 (0x06) +#define MPI_FCPORT10_BASE_EXTID_MODDEF7 (0x07) +#define MPI_FCPORT10_BASE_EXTID_VNDSPC_MASK (0x80) + +#define MPI_FCPORT10_BASE_CONN_UNKNOWN (0x00) +#define MPI_FCPORT10_BASE_CONN_SC (0x01) +#define MPI_FCPORT10_BASE_CONN_COPPER1 (0x02) +#define MPI_FCPORT10_BASE_CONN_COPPER2 (0x03) +#define MPI_FCPORT10_BASE_CONN_BNC_TNC (0x04) +#define MPI_FCPORT10_BASE_CONN_COAXIAL (0x05) +#define MPI_FCPORT10_BASE_CONN_FIBERJACK (0x06) +#define MPI_FCPORT10_BASE_CONN_LC (0x07) +#define MPI_FCPORT10_BASE_CONN_MT_RJ (0x08) +#define MPI_FCPORT10_BASE_CONN_MU (0x09) +#define MPI_FCPORT10_BASE_CONN_SG (0x0A) +#define MPI_FCPORT10_BASE_CONN_OPT_PIGT (0x0B) +#define MPI_FCPORT10_BASE_CONN_RSV1_MIN (0x0C) +#define MPI_FCPORT10_BASE_CONN_RSV1_MAX (0x1F) +#define MPI_FCPORT10_BASE_CONN_HSSDC_II (0x20) +#define MPI_FCPORT10_BASE_CONN_CPR_PIGT (0x21) +#define MPI_FCPORT10_BASE_CONN_RSV2_MIN (0x22) +#define MPI_FCPORT10_BASE_CONN_RSV2_MAX (0x7F) +#define MPI_FCPORT10_BASE_CONN_VNDSPC_MASK (0x80) + +#define MPI_FCPORT10_BASE_ENCODE_UNSPEC (0x00) +#define MPI_FCPORT10_BASE_ENCODE_8B10B (0x01) +#define MPI_FCPORT10_BASE_ENCODE_4B5B (0x02) +#define MPI_FCPORT10_BASE_ENCODE_NRZ (0x03) +#define MPI_FCPORT10_BASE_ENCODE_MANCHESTER (0x04) + + +typedef struct _CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA +{ + U8 Options[2]; /* 50h */ + U8 BitRateMax; /* 52h */ + U8 BitRateMin; /* 53h */ + U8 VendorSN[16]; /* 54h */ + U8 DateCode[8]; /* 64h */ + U8 DiagMonitoringType; /* 6Ch */ + U8 EnhancedOptions; /* 6Dh */ + U8 SFF8472Compliance; /* 6Eh */ + U8 CC_EXT; /* 6Fh */ +} CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA, + MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA, + FCPortPage10ExtendedSfpData_t, MPI_POINTER pFCPortPage10ExtendedSfpData_t; + +#define MPI_FCPORT10_EXT_OPTION1_RATESEL (0x20) +#define MPI_FCPORT10_EXT_OPTION1_TX_DISABLE (0x10) +#define MPI_FCPORT10_EXT_OPTION1_TX_FAULT (0x08) +#define MPI_FCPORT10_EXT_OPTION1_LOS_INVERT (0x04) +#define MPI_FCPORT10_EXT_OPTION1_LOS (0x02) + + +typedef struct _CONFIG_PAGE_FC_PORT_10 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 Flags; /* 04h */ + U8 Reserved1; /* 05h */ + U16 Reserved2; /* 06h */ + U32 HwConfig1; /* 08h */ + U32 HwConfig2; /* 0Ch */ + CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA Base; /* 10h */ + CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA Extended; /* 50h */ + U8 VendorSpecific[32]; /* 70h */ +} CONFIG_PAGE_FC_PORT_10, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10, + FCPortPage10_t, MPI_POINTER pFCPortPage10_t; + +#define MPI_FCPORTPAGE10_PAGEVERSION (0x01) + +/* standard MODDEF pin definitions (from GBIC spec.) */ +#define MPI_FCPORTPAGE10_FLAGS_MODDEF_MASK (0x00000007) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF2 (0x00000001) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF1 (0x00000002) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF0 (0x00000004) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF_NOGBIC (0x00000007) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF_CPR_IEEE_CX (0x00000006) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF_COPPER (0x00000005) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF_OPTICAL_LW (0x00000004) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF_SEEPROM (0x00000003) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF_SW_OPTICAL (0x00000002) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF_LX_IEEE_OPT_LW (0x00000001) +#define MPI_FCPORTPAGE10_FLAGS_MODDEF_SX_IEEE_OPT_SW (0x00000000) + +#define MPI_FCPORTPAGE10_FLAGS_CC_BASE_OK (0x00000010) +#define MPI_FCPORTPAGE10_FLAGS_CC_EXT_OK (0x00000020) + + +/**************************************************************************** +* FC Device Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_FC_DEVICE_0 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U64 WWNN; /* 04h */ + U64 WWPN; /* 0Ch */ + U32 PortIdentifier; /* 14h */ + U8 Protocol; /* 18h */ + U8 Flags; /* 19h */ + U16 BBCredit; /* 1Ah */ + U16 MaxRxFrameSize; /* 1Ch */ + U8 ADISCHardALPA; /* 1Eh */ + U8 PortNumber; /* 1Fh */ + U8 FcPhLowestVersion; /* 20h */ + U8 FcPhHighestVersion; /* 21h */ + U8 CurrentTargetID; /* 22h */ + U8 CurrentBus; /* 23h */ +} CONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0, + FCDevicePage0_t, MPI_POINTER pFCDevicePage0_t; + +#define MPI_FC_DEVICE_PAGE0_PAGEVERSION (0x03) + +#define MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID (0x01) +#define MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID (0x02) +#define MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID (0x04) + +#define MPI_FC_DEVICE_PAGE0_PROT_IP (0x01) +#define MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET (0x02) +#define MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR (0x04) +#define MPI_FC_DEVICE_PAGE0_PROT_FCP_RETRY (0x08) + +#define MPI_FC_DEVICE_PAGE0_PGAD_PORT_MASK (MPI_FC_DEVICE_PGAD_PORT_MASK) +#define MPI_FC_DEVICE_PAGE0_PGAD_FORM_MASK (MPI_FC_DEVICE_PGAD_FORM_MASK) +#define MPI_FC_DEVICE_PAGE0_PGAD_FORM_NEXT_DID (MPI_FC_DEVICE_PGAD_FORM_NEXT_DID) +#define MPI_FC_DEVICE_PAGE0_PGAD_FORM_BUS_TID (MPI_FC_DEVICE_PGAD_FORM_BUS_TID) +#define MPI_FC_DEVICE_PAGE0_PGAD_DID_MASK (MPI_FC_DEVICE_PGAD_ND_DID_MASK) +#define MPI_FC_DEVICE_PAGE0_PGAD_BUS_MASK (MPI_FC_DEVICE_PGAD_BT_BUS_MASK) +#define MPI_FC_DEVICE_PAGE0_PGAD_BUS_SHIFT (MPI_FC_DEVICE_PGAD_BT_BUS_SHIFT) +#define MPI_FC_DEVICE_PAGE0_PGAD_TID_MASK (MPI_FC_DEVICE_PGAD_BT_TID_MASK) + +#define MPI_FC_DEVICE_PAGE0_HARD_ALPA_UNKNOWN (0xFF) + +/**************************************************************************** +* RAID Volume Config Pages +****************************************************************************/ + +typedef struct _RAID_VOL0_PHYS_DISK +{ + U16 Reserved; /* 00h */ + U8 PhysDiskMap; /* 02h */ + U8 PhysDiskNum; /* 03h */ +} RAID_VOL0_PHYS_DISK, MPI_POINTER PTR_RAID_VOL0_PHYS_DISK, + RaidVol0PhysDisk_t, MPI_POINTER pRaidVol0PhysDisk_t; + +#define MPI_RAIDVOL0_PHYSDISK_PRIMARY (0x01) +#define MPI_RAIDVOL0_PHYSDISK_SECONDARY (0x02) + +typedef struct _RAID_VOL0_STATUS +{ + U8 Flags; /* 00h */ + U8 State; /* 01h */ + U16 Reserved; /* 02h */ +} RAID_VOL0_STATUS, MPI_POINTER PTR_RAID_VOL0_STATUS, + RaidVol0Status_t, MPI_POINTER pRaidVol0Status_t; + +/* RAID Volume Page 0 VolumeStatus defines */ +#define MPI_RAIDVOL0_STATUS_FLAG_ENABLED (0x01) +#define MPI_RAIDVOL0_STATUS_FLAG_QUIESCED (0x02) +#define MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x04) +#define MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x08) +#define MPI_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x10) + +#define MPI_RAIDVOL0_STATUS_STATE_OPTIMAL (0x00) +#define MPI_RAIDVOL0_STATUS_STATE_DEGRADED (0x01) +#define MPI_RAIDVOL0_STATUS_STATE_FAILED (0x02) +#define MPI_RAIDVOL0_STATUS_STATE_MISSING (0x03) + +typedef struct _RAID_VOL0_SETTINGS +{ + U16 Settings; /* 00h */ + U8 HotSparePool; /* 01h */ /* MPI_RAID_HOT_SPARE_POOL_ */ + U8 Reserved; /* 02h */ +} RAID_VOL0_SETTINGS, MPI_POINTER PTR_RAID_VOL0_SETTINGS, + RaidVol0Settings, MPI_POINTER pRaidVol0Settings; + +/* RAID Volume Page 0 VolumeSettings defines */ +#define MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE (0x0001) +#define MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART (0x0002) +#define MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE (0x0004) +#define MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC (0x0008) +#define MPI_RAIDVOL0_SETTING_FAST_DATA_SCRUBBING_0102 (0x0020) /* obsolete */ + +#define MPI_RAIDVOL0_SETTING_MASK_METADATA_SIZE (0x00C0) +#define MPI_RAIDVOL0_SETTING_64MB_METADATA_SIZE (0x0000) +#define MPI_RAIDVOL0_SETTING_512MB_METADATA_SIZE (0x0040) + +#define MPI_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0010) +#define MPI_RAIDVOL0_SETTING_USE_DEFAULTS (0x8000) + +/* RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */ +#define MPI_RAID_HOT_SPARE_POOL_0 (0x01) +#define MPI_RAID_HOT_SPARE_POOL_1 (0x02) +#define MPI_RAID_HOT_SPARE_POOL_2 (0x04) +#define MPI_RAID_HOT_SPARE_POOL_3 (0x08) +#define MPI_RAID_HOT_SPARE_POOL_4 (0x10) +#define MPI_RAID_HOT_SPARE_POOL_5 (0x20) +#define MPI_RAID_HOT_SPARE_POOL_6 (0x40) +#define MPI_RAID_HOT_SPARE_POOL_7 (0x80) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX +#define MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_RAID_VOL_0 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 VolumeID; /* 04h */ + U8 VolumeBus; /* 05h */ + U8 VolumeIOC; /* 06h */ + U8 VolumeType; /* 07h */ /* MPI_RAID_VOL_TYPE_ */ + RAID_VOL0_STATUS VolumeStatus; /* 08h */ + RAID_VOL0_SETTINGS VolumeSettings; /* 0Ch */ + U32 MaxLBA; /* 10h */ + U32 MaxLBAHigh; /* 14h */ + U32 StripeSize; /* 18h */ + U32 Reserved2; /* 1Ch */ + U32 Reserved3; /* 20h */ + U8 NumPhysDisks; /* 24h */ + U8 DataScrubRate; /* 25h */ + U8 ResyncRate; /* 26h */ + U8 InactiveStatus; /* 27h */ + RAID_VOL0_PHYS_DISK PhysDisk[MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX];/* 28h */ +} CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0, + RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t; + +#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x07) + +/* values for RAID Volume Page 0 InactiveStatus field */ +#define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00) +#define MPI_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01) +#define MPI_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02) +#define MPI_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03) +#define MPI_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04) +#define MPI_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05) +#define MPI_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06) + + +typedef struct _CONFIG_PAGE_RAID_VOL_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 VolumeID; /* 04h */ + U8 VolumeBus; /* 05h */ + U8 VolumeIOC; /* 06h */ + U8 Reserved0; /* 07h */ + U8 GUID[24]; /* 08h */ + U8 Name[32]; /* 20h */ + U64 WWID; /* 40h */ + U32 Reserved1; /* 48h */ + U32 Reserved2; /* 4Ch */ +} CONFIG_PAGE_RAID_VOL_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_1, + RaidVolumePage1_t, MPI_POINTER pRaidVolumePage1_t; + +#define MPI_RAIDVOLPAGE1_PAGEVERSION (0x01) + + +/**************************************************************************** +* RAID Physical Disk Config Pages +****************************************************************************/ + +typedef struct _RAID_PHYS_DISK0_ERROR_DATA +{ + U8 ErrorCdbByte; /* 00h */ + U8 ErrorSenseKey; /* 01h */ + U16 Reserved; /* 02h */ + U16 ErrorCount; /* 04h */ + U8 ErrorASC; /* 06h */ + U8 ErrorASCQ; /* 07h */ + U16 SmartCount; /* 08h */ + U8 SmartASC; /* 0Ah */ + U8 SmartASCQ; /* 0Bh */ +} RAID_PHYS_DISK0_ERROR_DATA, MPI_POINTER PTR_RAID_PHYS_DISK0_ERROR_DATA, + RaidPhysDisk0ErrorData_t, MPI_POINTER pRaidPhysDisk0ErrorData_t; + +typedef struct _RAID_PHYS_DISK_INQUIRY_DATA +{ + U8 VendorID[8]; /* 00h */ + U8 ProductID[16]; /* 08h */ + U8 ProductRevLevel[4]; /* 18h */ + U8 Info[32]; /* 1Ch */ +} RAID_PHYS_DISK0_INQUIRY_DATA, MPI_POINTER PTR_RAID_PHYS_DISK0_INQUIRY_DATA, + RaidPhysDisk0InquiryData, MPI_POINTER pRaidPhysDisk0InquiryData; + +typedef struct _RAID_PHYS_DISK0_SETTINGS +{ + U8 SepID; /* 00h */ + U8 SepBus; /* 01h */ + U8 HotSparePool; /* 02h */ /* MPI_RAID_HOT_SPARE_POOL_ */ + U8 PhysDiskSettings; /* 03h */ +} RAID_PHYS_DISK0_SETTINGS, MPI_POINTER PTR_RAID_PHYS_DISK0_SETTINGS, + RaidPhysDiskSettings_t, MPI_POINTER pRaidPhysDiskSettings_t; + +typedef struct _RAID_PHYS_DISK0_STATUS +{ + U8 Flags; /* 00h */ + U8 State; /* 01h */ + U16 Reserved; /* 02h */ +} RAID_PHYS_DISK0_STATUS, MPI_POINTER PTR_RAID_PHYS_DISK0_STATUS, + RaidPhysDiskStatus_t, MPI_POINTER pRaidPhysDiskStatus_t; + +/* RAID Physical Disk PhysDiskStatus flags */ + +#define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x01) +#define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED (0x02) +#define MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x04) +#define MPI_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00) +#define MPI_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x08) + +#define MPI_PHYSDISK0_STATUS_ONLINE (0x00) +#define MPI_PHYSDISK0_STATUS_MISSING (0x01) +#define MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE (0x02) +#define MPI_PHYSDISK0_STATUS_FAILED (0x03) +#define MPI_PHYSDISK0_STATUS_INITIALIZING (0x04) +#define MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED (0x05) +#define MPI_PHYSDISK0_STATUS_FAILED_REQUESTED (0x06) +#define MPI_PHYSDISK0_STATUS_OTHER_OFFLINE (0xFF) + +typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_0 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 PhysDiskID; /* 04h */ + U8 PhysDiskBus; /* 05h */ + U8 PhysDiskIOC; /* 06h */ + U8 PhysDiskNum; /* 07h */ + RAID_PHYS_DISK0_SETTINGS PhysDiskSettings; /* 08h */ + U32 Reserved1; /* 0Ch */ + U8 ExtDiskIdentifier[8]; /* 10h */ + U8 DiskIdentifier[16]; /* 18h */ + RAID_PHYS_DISK0_INQUIRY_DATA InquiryData; /* 28h */ + RAID_PHYS_DISK0_STATUS PhysDiskStatus; /* 64h */ + U32 MaxLBA; /* 68h */ + RAID_PHYS_DISK0_ERROR_DATA ErrorData; /* 6Ch */ +} CONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0, + RaidPhysDiskPage0_t, MPI_POINTER pRaidPhysDiskPage0_t; + +#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x02) + + +typedef struct _RAID_PHYS_DISK1_PATH +{ + U8 PhysDiskID; /* 00h */ + U8 PhysDiskBus; /* 01h */ + U16 Reserved1; /* 02h */ + U64 WWID; /* 04h */ + U64 OwnerWWID; /* 0Ch */ + U8 OwnerIdentifier; /* 14h */ + U8 Reserved2; /* 15h */ + U16 Flags; /* 16h */ +} RAID_PHYS_DISK1_PATH, MPI_POINTER PTR_RAID_PHYS_DISK1_PATH, + RaidPhysDisk1Path_t, MPI_POINTER pRaidPhysDisk1Path_t; + +/* RAID Physical Disk Page 1 Flags field defines */ +#define MPI_RAID_PHYSDISK1_FLAG_BROKEN (0x0002) +#define MPI_RAID_PHYSDISK1_FLAG_INVALID (0x0001) + + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength or NumPhysDiskPaths at runtime. + */ +#ifndef MPI_RAID_PHYS_DISK1_PATH_MAX +#define MPI_RAID_PHYS_DISK1_PATH_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 NumPhysDiskPaths; /* 04h */ + U8 PhysDiskNum; /* 05h */ + U16 Reserved2; /* 06h */ + U32 Reserved1; /* 08h */ + RAID_PHYS_DISK1_PATH Path[MPI_RAID_PHYS_DISK1_PATH_MAX];/* 0Ch */ +} CONFIG_PAGE_RAID_PHYS_DISK_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_1, + RaidPhysDiskPage1_t, MPI_POINTER pRaidPhysDiskPage1_t; + +#define MPI_RAIDPHYSDISKPAGE1_PAGEVERSION (0x00) + + +/**************************************************************************** +* LAN Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_LAN_0 +{ + ConfigPageHeader_t Header; /* 00h */ + U16 TxRxModes; /* 04h */ + U16 Reserved; /* 06h */ + U32 PacketPrePad; /* 08h */ +} CONFIG_PAGE_LAN_0, MPI_POINTER PTR_CONFIG_PAGE_LAN_0, + LANPage0_t, MPI_POINTER pLANPage0_t; + +#define MPI_LAN_PAGE0_PAGEVERSION (0x01) + +#define MPI_LAN_PAGE0_RETURN_LOOPBACK (0x0000) +#define MPI_LAN_PAGE0_SUPPRESS_LOOPBACK (0x0001) +#define MPI_LAN_PAGE0_LOOPBACK_MASK (0x0001) + +typedef struct _CONFIG_PAGE_LAN_1 +{ + ConfigPageHeader_t Header; /* 00h */ + U16 Reserved; /* 04h */ + U8 CurrentDeviceState; /* 06h */ + U8 Reserved1; /* 07h */ + U32 MinPacketSize; /* 08h */ + U32 MaxPacketSize; /* 0Ch */ + U32 HardwareAddressLow; /* 10h */ + U32 HardwareAddressHigh; /* 14h */ + U32 MaxWireSpeedLow; /* 18h */ + U32 MaxWireSpeedHigh; /* 1Ch */ + U32 BucketsRemaining; /* 20h */ + U32 MaxReplySize; /* 24h */ + U32 NegWireSpeedLow; /* 28h */ + U32 NegWireSpeedHigh; /* 2Ch */ +} CONFIG_PAGE_LAN_1, MPI_POINTER PTR_CONFIG_PAGE_LAN_1, + LANPage1_t, MPI_POINTER pLANPage1_t; + +#define MPI_LAN_PAGE1_PAGEVERSION (0x03) + +#define MPI_LAN_PAGE1_DEV_STATE_RESET (0x00) +#define MPI_LAN_PAGE1_DEV_STATE_OPERATIONAL (0x01) + + +/**************************************************************************** +* Inband Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_INBAND_0 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + MPI_VERSION_FORMAT InbandVersion; /* 04h */ + U16 MaximumBuffers; /* 08h */ + U16 Reserved1; /* 0Ah */ +} CONFIG_PAGE_INBAND_0, MPI_POINTER PTR_CONFIG_PAGE_INBAND_0, + InbandPage0_t, MPI_POINTER pInbandPage0_t; + +#define MPI_INBAND_PAGEVERSION (0x00) + + + +/**************************************************************************** +* SAS IO Unit Config Pages +****************************************************************************/ + +typedef struct _MPI_SAS_IO_UNIT0_PHY_DATA +{ + U8 Port; /* 00h */ + U8 PortFlags; /* 01h */ + U8 PhyFlags; /* 02h */ + U8 NegotiatedLinkRate; /* 03h */ + U32 ControllerPhyDeviceInfo;/* 04h */ + U16 AttachedDeviceHandle; /* 08h */ + U16 ControllerDevHandle; /* 0Ah */ + U32 DiscoveryStatus; /* 0Ch */ +} MPI_SAS_IO_UNIT0_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT0_PHY_DATA, + SasIOUnit0PhyData, MPI_POINTER pSasIOUnit0PhyData; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_SAS_IOUNIT0_PHY_MAX +#define MPI_SAS_IOUNIT0_PHY_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U16 NvdataVersionDefault; /* 08h */ + U16 NvdataVersionPersistent; /* 0Ah */ + U8 NumPhys; /* 0Ch */ + U8 Reserved2; /* 0Dh */ + U16 Reserved3; /* 0Eh */ + MPI_SAS_IO_UNIT0_PHY_DATA PhyData[MPI_SAS_IOUNIT0_PHY_MAX]; /* 10h */ +} CONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0, + SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t; + +#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x04) + +/* values for SAS IO Unit Page 0 PortFlags */ +#define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS (0x08) +#define MPI_SAS_IOUNIT0_PORT_FLAGS_0_TARGET_IOC_NUM (0x00) +#define MPI_SAS_IOUNIT0_PORT_FLAGS_1_TARGET_IOC_NUM (0x04) +#define MPI_SAS_IOUNIT0_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) + +/* values for SAS IO Unit Page 0 PhyFlags */ +#define MPI_SAS_IOUNIT0_PHY_FLAGS_PHY_DISABLED (0x04) +#define MPI_SAS_IOUNIT0_PHY_FLAGS_TX_INVERT (0x02) +#define MPI_SAS_IOUNIT0_PHY_FLAGS_RX_INVERT (0x01) + +/* values for SAS IO Unit Page 0 NegotiatedLinkRate */ +#define MPI_SAS_IOUNIT0_RATE_UNKNOWN (0x00) +#define MPI_SAS_IOUNIT0_RATE_PHY_DISABLED (0x01) +#define MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION (0x02) +#define MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE (0x03) +#define MPI_SAS_IOUNIT0_RATE_1_5 (0x08) +#define MPI_SAS_IOUNIT0_RATE_3_0 (0x09) + +/* see mpi_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */ + +/* values for SAS IO Unit Page 0 DiscoveryStatus */ +#define MPI_SAS_IOUNIT0_DS_LOOP_DETECTED (0x00000001) +#define MPI_SAS_IOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI_SAS_IOUNIT0_DS_MULTIPLE_PORTS (0x00000004) +#define MPI_SAS_IOUNIT0_DS_EXPANDER_ERR (0x00000008) +#define MPI_SAS_IOUNIT0_DS_SMP_TIMEOUT (0x00000010) +#define MPI_SAS_IOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI_SAS_IOUNIT0_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI_SAS_IOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI_SAS_IOUNIT0_DS_SMP_CRC_ERROR (0x00000100) +#define MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI_SAS_IOUNIT0_DS_TABLE_LINK (0x00000400) +#define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800) +#define MPI_SAS_IOUNIT0_DS_MAX_SATA_TARGETS (0x00001000) +#define MPI_SAS_IOUNIT0_DS_MULTI_PORT_DOMAIN (0x00002000) + + +typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA +{ + U8 Port; /* 00h */ + U8 PortFlags; /* 01h */ + U8 PhyFlags; /* 02h */ + U8 MaxMinLinkRate; /* 03h */ + U32 ControllerPhyDeviceInfo; /* 04h */ + U16 MaxTargetPortConnectTime; /* 08h */ + U16 Reserved1; /* 0Ah */ +} MPI_SAS_IO_UNIT1_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT1_PHY_DATA, + SasIOUnit1PhyData, MPI_POINTER pSasIOUnit1PhyData; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_SAS_IOUNIT1_PHY_MAX +#define MPI_SAS_IOUNIT1_PHY_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U16 ControlFlags; /* 08h */ + U16 MaxNumSATATargets; /* 0Ah */ + U16 AdditionalControlFlags; /* 0Ch */ + U16 Reserved1; /* 0Eh */ + U8 NumPhys; /* 10h */ + U8 SATAMaxQDepth; /* 11h */ + U8 ReportDeviceMissingDelay; /* 12h */ + U8 IODeviceMissingDelay; /* 13h */ + MPI_SAS_IO_UNIT1_PHY_DATA PhyData[MPI_SAS_IOUNIT1_PHY_MAX]; /* 14h */ +} CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1, + SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t; + +#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x07) + +/* values for SAS IO Unit Page 1 ControlFlags */ +#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) +#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800) + +#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) +#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) +#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00) +#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01) +#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02) + +#define MPI_SAS_IOUNIT1_CONTROL_POSTPONE_SATA_INIT (0x0100) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) +#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008) +#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) +#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) +#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) + +/* values for SAS IO Unit Page 1 AdditionalControlFlags */ +#define MPI_SAS_IOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080) +#define MPI_SAS_IOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) +#define MPI_SAS_IOUNIT1_ACONTROL_HIDE_NONZERO_ATTACHED_PHY_IDENT (0x0020) +#define MPI_SAS_IOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010) +#define MPI_SAS_IOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008) +#define MPI_SAS_IOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004) +#define MPI_SAS_IOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002) +#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) + +/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */ +#define MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F) +#define MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16 (0x80) + +/* values for SAS IO Unit Page 1 PortFlags */ +#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00) +#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04) +#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) + +/* values for SAS IO Unit Page 0 PhyFlags */ +#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04) +#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02) +#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01) + +/* values for SAS IO Unit Page 0 MaxMinLinkRate */ +#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0) +#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80) +#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90) +#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F) +#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08) +#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09) + +/* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ + + +typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U8 NumDevsPerEnclosure; /* 08h */ + U8 BootDeviceWaitTime; /* 09h */ + U16 Reserved2; /* 0Ah */ + U16 MaxPersistentIDs; /* 0Ch */ + U16 NumPersistentIDsUsed; /* 0Eh */ + U8 Status; /* 10h */ + U8 Flags; /* 11h */ + U16 MaxNumPhysicalMappedIDs;/* 12h */ +} CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2, + SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t; + +#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x07) + +/* values for SAS IO Unit Page 2 Status field */ +#define MPI_SAS_IOUNIT2_STATUS_DEVICE_LIMIT_EXCEEDED (0x08) +#define MPI_SAS_IOUNIT2_STATUS_ENCLOSURE_DEVICES_UNMAPPED (0x04) +#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02) +#define MPI_SAS_IOUNIT2_STATUS_FULL_PERSISTENT_MAPPINGS (0x01) + +/* values for SAS IO Unit Page 2 Flags field */ +#define MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS (0x01) +/* Physical Mapping Modes */ +#define MPI_SAS_IOUNIT2_FLAGS_MASK_PHYS_MAP_MODE (0x0E) +#define MPI_SAS_IOUNIT2_FLAGS_SHIFT_PHYS_MAP_MODE (1) +#define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00) +#define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01) +#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02) +#define MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP (0x07) + +#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10) +#define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20) + + +typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U32 MaxInvalidDwordCount; /* 0Ch */ + U32 InvalidDwordCountTime; /* 10h */ + U32 MaxRunningDisparityErrorCount; /* 14h */ + U32 RunningDisparityErrorTime; /* 18h */ + U32 MaxLossDwordSynchCount; /* 1Ch */ + U32 LossDwordSynchCountTime; /* 20h */ + U32 MaxPhyResetProblemCount; /* 24h */ + U32 PhyResetProblemTime; /* 28h */ +} CONFIG_PAGE_SAS_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_3, + SasIOUnitPage3_t, MPI_POINTER pSasIOUnitPage3_t; + +#define MPI_SASIOUNITPAGE3_PAGEVERSION (0x00) + + +/**************************************************************************** +* SAS Expander Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_SAS_EXPANDER_0 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U8 PhysicalPort; /* 08h */ + U8 Reserved1; /* 09h */ + U16 EnclosureHandle; /* 0Ah */ + U64 SASAddress; /* 0Ch */ + U32 DiscoveryStatus; /* 14h */ + U16 DevHandle; /* 18h */ + U16 ParentDevHandle; /* 1Ah */ + U16 ExpanderChangeCount; /* 1Ch */ + U16 ExpanderRouteIndexes; /* 1Eh */ + U8 NumPhys; /* 20h */ + U8 SASLevel; /* 21h */ + U8 Flags; /* 22h */ + U8 Reserved3; /* 23h */ +} CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0, + SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t; + +#define MPI_SASEXPANDER0_PAGEVERSION (0x03) + +/* values for SAS Expander Page 0 DiscoveryStatus field */ +#define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) +#define MPI_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004) +#define MPI_SAS_EXPANDER0_DS_EXPANDER_ERR (0x00000008) +#define MPI_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010) +#define MPI_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100) +#define MPI_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400) +#define MPI_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800) + +/* values for SAS Expander Page 0 Flags field */ +#define MPI_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x04) +#define MPI_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x02) +#define MPI_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x01) + + +typedef struct _CONFIG_PAGE_SAS_EXPANDER_1 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U8 PhysicalPort; /* 08h */ + U8 Reserved1; /* 09h */ + U16 Reserved2; /* 0Ah */ + U8 NumPhys; /* 0Ch */ + U8 Phy; /* 0Dh */ + U16 NumTableEntriesProgrammed; /* 0Eh */ + U8 ProgrammedLinkRate; /* 10h */ + U8 HwLinkRate; /* 11h */ + U16 AttachedDevHandle; /* 12h */ + U32 PhyInfo; /* 14h */ + U32 AttachedDeviceInfo; /* 18h */ + U16 OwnerDevHandle; /* 1Ch */ + U8 ChangeCount; /* 1Eh */ + U8 NegotiatedLinkRate; /* 1Fh */ + U8 PhyIdentifier; /* 20h */ + U8 AttachedPhyIdentifier; /* 21h */ + U8 Reserved3; /* 22h */ + U8 DiscoveryInfo; /* 23h */ + U32 Reserved4; /* 24h */ +} CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1, + SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t; + +#define MPI_SASEXPANDER1_PAGEVERSION (0x01) + +/* use MPI_SAS_PHY0_PRATE_ defines for ProgrammedLinkRate */ + +/* use MPI_SAS_PHY0_HWRATE_ defines for HwLinkRate */ + +/* use MPI_SAS_PHY0_PHYINFO_ defines for PhyInfo */ + +/* see mpi_sas.h for values for SAS Expander Page 1 AttachedDeviceInfo values */ + +/* values for SAS Expander Page 1 DiscoveryInfo field */ +#define MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04) +#define MPI_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) +#define MPI_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) + +/* values for SAS Expander Page 1 NegotiatedLinkRate field */ +#define MPI_SAS_EXPANDER1_NEG_RATE_UNKNOWN (0x00) +#define MPI_SAS_EXPANDER1_NEG_RATE_PHY_DISABLED (0x01) +#define MPI_SAS_EXPANDER1_NEG_RATE_FAILED_NEGOTIATION (0x02) +#define MPI_SAS_EXPANDER1_NEG_RATE_SATA_OOB_COMPLETE (0x03) +#define MPI_SAS_EXPANDER1_NEG_RATE_1_5 (0x08) +#define MPI_SAS_EXPANDER1_NEG_RATE_3_0 (0x09) + + +/**************************************************************************** +* SAS Device Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_SAS_DEVICE_0 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U16 Slot; /* 08h */ + U16 EnclosureHandle; /* 0Ah */ + U64 SASAddress; /* 0Ch */ + U16 ParentDevHandle; /* 14h */ + U8 PhyNum; /* 16h */ + U8 AccessStatus; /* 17h */ + U16 DevHandle; /* 18h */ + U8 TargetID; /* 1Ah */ + U8 Bus; /* 1Bh */ + U32 DeviceInfo; /* 1Ch */ + U16 Flags; /* 20h */ + U8 PhysicalPort; /* 22h */ + U8 Reserved2; /* 23h */ +} CONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0, + SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t; + +#define MPI_SASDEVICE0_PAGEVERSION (0x05) + +/* values for SAS Device Page 0 AccessStatus field */ +#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04) +/* specific values for SATA Init failures */ +#define MPI_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F) + +/* values for SAS Device Page 0 Flags field */ +#define MPI_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400) +#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) +#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) +#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) +#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) +#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) +#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) +#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) +#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x0004) +#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x0002) +#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) + +/* see mpi_sas.h for values for SAS Device Page 0 DeviceInfo values */ + + +typedef struct _CONFIG_PAGE_SAS_DEVICE_1 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U64 SASAddress; /* 0Ch */ + U32 Reserved2; /* 14h */ + U16 DevHandle; /* 18h */ + U8 TargetID; /* 1Ah */ + U8 Bus; /* 1Bh */ + U8 InitialRegDeviceFIS[20];/* 1Ch */ +} CONFIG_PAGE_SAS_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_1, + SasDevicePage1_t, MPI_POINTER pSasDevicePage1_t; + +#define MPI_SASDEVICE1_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_SAS_DEVICE_2 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U64 PhysicalIdentifier; /* 08h */ + U32 EnclosureMapping; /* 10h */ +} CONFIG_PAGE_SAS_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_2, + SasDevicePage2_t, MPI_POINTER pSasDevicePage2_t; + +#define MPI_SASDEVICE2_PAGEVERSION (0x01) + +/* defines for SAS Device Page 2 EnclosureMapping field */ +#define MPI_SASDEVICE2_ENC_MAP_MASK_MISSING_COUNT (0x0000000F) +#define MPI_SASDEVICE2_ENC_MAP_SHIFT_MISSING_COUNT (0) +#define MPI_SASDEVICE2_ENC_MAP_MASK_NUM_SLOTS (0x000007F0) +#define MPI_SASDEVICE2_ENC_MAP_SHIFT_NUM_SLOTS (4) +#define MPI_SASDEVICE2_ENC_MAP_MASK_START_INDEX (0x001FF800) +#define MPI_SASDEVICE2_ENC_MAP_SHIFT_START_INDEX (11) + + +/**************************************************************************** +* SAS PHY Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_SAS_PHY_0 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U16 OwnerDevHandle; /* 08h */ + U16 Reserved1; /* 0Ah */ + U64 SASAddress; /* 0Ch */ + U16 AttachedDevHandle; /* 14h */ + U8 AttachedPhyIdentifier; /* 16h */ + U8 Reserved2; /* 17h */ + U32 AttachedDeviceInfo; /* 18h */ + U8 ProgrammedLinkRate; /* 1Ch */ + U8 HwLinkRate; /* 1Dh */ + U8 ChangeCount; /* 1Eh */ + U8 Flags; /* 1Fh */ + U32 PhyInfo; /* 20h */ +} CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0, + SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t; + +#define MPI_SASPHY0_PAGEVERSION (0x01) + +/* values for SAS PHY Page 0 ProgrammedLinkRate field */ +#define MPI_SAS_PHY0_PRATE_MAX_RATE_MASK (0xF0) +#define MPI_SAS_PHY0_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00) +#define MPI_SAS_PHY0_PRATE_MAX_RATE_1_5 (0x80) +#define MPI_SAS_PHY0_PRATE_MAX_RATE_3_0 (0x90) +#define MPI_SAS_PHY0_PRATE_MIN_RATE_MASK (0x0F) +#define MPI_SAS_PHY0_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00) +#define MPI_SAS_PHY0_PRATE_MIN_RATE_1_5 (0x08) +#define MPI_SAS_PHY0_PRATE_MIN_RATE_3_0 (0x09) + +/* values for SAS PHY Page 0 HwLinkRate field */ +#define MPI_SAS_PHY0_HWRATE_MAX_RATE_MASK (0xF0) +#define MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5 (0x80) +#define MPI_SAS_PHY0_HWRATE_MAX_RATE_3_0 (0x90) +#define MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK (0x0F) +#define MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5 (0x08) +#define MPI_SAS_PHY0_HWRATE_MIN_RATE_3_0 (0x09) + +/* values for SAS PHY Page 0 Flags field */ +#define MPI_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01) + +/* values for SAS PHY Page 0 PhyInfo field */ +#define MPI_SAS_PHY0_PHYINFO_PHY_VACANT (0x80000000) +#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_ACTIVE (0x00004000) +#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_SELECTOR (0x00002000) +#define MPI_SAS_PHY0_PHYINFO_VIRTUAL_PHY (0x00001000) + +#define MPI_SAS_PHY0_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00) +#define MPI_SAS_PHY0_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8) + +#define MPI_SAS_PHY0_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0) +#define MPI_SAS_PHY0_PHYINFO_DIRECT_ROUTING (0x00000000) +#define MPI_SAS_PHY0_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010) +#define MPI_SAS_PHY0_PHYINFO_TABLE_ROUTING (0x00000020) + +#define MPI_SAS_PHY0_PHYINFO_MASK_LINK_RATE (0x0000000F) +#define MPI_SAS_PHY0_PHYINFO_UNKNOWN_LINK_RATE (0x00000000) +#define MPI_SAS_PHY0_PHYINFO_PHY_DISABLED (0x00000001) +#define MPI_SAS_PHY0_PHYINFO_NEGOTIATION_FAILED (0x00000002) +#define MPI_SAS_PHY0_PHYINFO_SATA_OOB_COMPLETE (0x00000003) +#define MPI_SAS_PHY0_PHYINFO_RATE_1_5 (0x00000008) +#define MPI_SAS_PHY0_PHYINFO_RATE_3_0 (0x00000009) + + +typedef struct _CONFIG_PAGE_SAS_PHY_1 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U32 InvalidDwordCount; /* 0Ch */ + U32 RunningDisparityErrorCount; /* 10h */ + U32 LossDwordSynchCount; /* 14h */ + U32 PhyResetProblemCount; /* 18h */ +} CONFIG_PAGE_SAS_PHY_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_1, + SasPhyPage1_t, MPI_POINTER pSasPhyPage1_t; + +#define MPI_SASPHY1_PAGEVERSION (0x00) + + +/**************************************************************************** +* SAS Enclosure Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U64 EnclosureLogicalID; /* 0Ch */ + U16 Flags; /* 14h */ + U16 EnclosureHandle; /* 16h */ + U16 NumSlots; /* 18h */ + U16 StartSlot; /* 1Ah */ + U8 StartTargetID; /* 1Ch */ + U8 StartBus; /* 1Dh */ + U8 SEPTargetID; /* 1Eh */ + U8 SEPBus; /* 1Fh */ + U32 Reserved2; /* 20h */ + U32 Reserved3; /* 24h */ +} CONFIG_PAGE_SAS_ENCLOSURE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_ENCLOSURE_0, + SasEnclosurePage0_t, MPI_POINTER pSasEnclosurePage0_t; + +#define MPI_SASENCLOSURE0_PAGEVERSION (0x01) + +/* values for SAS Enclosure Page 0 Flags field */ +#define MPI_SAS_ENCLS0_FLAGS_SEP_BUS_ID_VALID (0x0020) +#define MPI_SAS_ENCLS0_FLAGS_START_BUS_ID_VALID (0x0010) + +#define MPI_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F) +#define MPI_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) +#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) +#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002) +#define MPI_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003) +#define MPI_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004) +#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005) + + +/**************************************************************************** +* Log Config Pages +****************************************************************************/ +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumLogEntries at runtime. + */ +#ifndef MPI_LOG_0_NUM_LOG_ENTRIES +#define MPI_LOG_0_NUM_LOG_ENTRIES (1) +#endif + +#define MPI_LOG_0_LOG_DATA_LENGTH (0x1C) + +typedef struct _MPI_LOG_0_ENTRY +{ + U32 TimeStamp; /* 00h */ + U32 Reserved1; /* 04h */ + U16 LogSequence; /* 08h */ + U16 LogEntryQualifier; /* 0Ah */ + U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 0Ch */ +} MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY, + MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t; + +/* values for Log Page 0 LogEntry LogEntryQualifier field */ +#define MPI_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000) +#define MPI_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001) + +typedef struct _CONFIG_PAGE_LOG_0 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U32 Reserved2; /* 0Ch */ + U16 NumLogEntries; /* 10h */ + U16 Reserved3; /* 12h */ + MPI_LOG_0_ENTRY LogEntry[MPI_LOG_0_NUM_LOG_ENTRIES]; /* 14h */ +} CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0, + LogPage0_t, MPI_POINTER pLogPage0_t; + +#define MPI_LOG_0_PAGEVERSION (0x01) + + +#endif + diff --git a/source/lsi/mpi_fc.h b/source/lsi/mpi_fc.h new file mode 100755 index 0000000..9acd920 --- /dev/null +++ b/source/lsi/mpi_fc.h @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2000-2008 LSI Corporation. + * + * + * Name: mpi_fc.h + * Title: MPI Fibre Channel messages and structures + * Creation Date: June 12, 2000 + * + * mpi_fc.h Version: 01.05.01 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. + * 06-06-00 01.00.01 Update version number for 1.0 release. + * 06-12-00 01.00.02 Added _MSG_FC_ABORT_REPLY structure. + * 11-02-00 01.01.01 Original release for post 1.0 work + * 12-04-00 01.01.02 Added messages for Common Transport Send and + * Primitive Send. + * 01-09-01 01.01.03 Modifed some of the new flags to have an MPI prefix + * and modified the FcPrimitiveSend flags. + * 01-25-01 01.01.04 Move InitiatorIndex in LinkServiceRsp reply to a larger + * field. + * Added FC_ABORT_TYPE_CT_SEND_REQUEST and + * FC_ABORT_TYPE_EXLINKSEND_REQUEST for FcAbort request. + * Added MPI_FC_PRIM_SEND_FLAGS_STOP_SEND. + * 02-20-01 01.01.05 Started using MPI_POINTER. + * 03-27-01 01.01.06 Added Flags field to MSG_LINK_SERVICE_BUFFER_POST_REPLY + * and defined MPI_LS_BUF_POST_REPLY_FLAG_NO_RSP_NEEDED. + * Added MPI_FC_PRIM_SEND_FLAGS_RESET_LINK define. + * Added structure offset comments. + * 04-09-01 01.01.07 Added RspLength field to MSG_LINK_SERVICE_RSP_REQUEST. + * 08-08-01 01.02.01 Original release for v1.2 work. + * 09-28-01 01.02.02 Change name of reserved field in + * MSG_LINK_SERVICE_RSP_REPLY. + * 05-31-02 01.02.03 Adding AliasIndex to FC Direct Access requests. + * 01-16-04 01.02.04 Added define for MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_FC_H +#define MPI_FC_H + + +/***************************************************************************** +* +* F C D i r e c t A c c e s s M e s s a g e s +* +*****************************************************************************/ + +/****************************************************************************/ +/* Link Service Buffer Post messages */ +/****************************************************************************/ + +typedef struct _MSG_LINK_SERVICE_BUFFER_POST_REQUEST +{ + U8 BufferPostFlags; /* 00h */ + U8 BufferCount; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved; /* 04h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + SGE_TRANS_SIMPLE_UNION SGL; +} MSG_LINK_SERVICE_BUFFER_POST_REQUEST, + MPI_POINTER PTR_MSG_LINK_SERVICE_BUFFER_POST_REQUEST, + LinkServiceBufferPostRequest_t, MPI_POINTER pLinkServiceBufferPostRequest_t; + +#define LINK_SERVICE_BUFFER_POST_FLAGS_PORT_MASK (0x01) + +typedef struct _WWNFORMAT +{ + U32 PortNameHigh; /* 00h */ + U32 PortNameLow; /* 04h */ + U32 NodeNameHigh; /* 08h */ + U32 NodeNameLow; /* 0Ch */ +} WWNFORMAT, + WwnFormat_t; + +/* Link Service Buffer Post Reply */ +typedef struct _MSG_LINK_SERVICE_BUFFER_POST_REPLY +{ + U8 Flags; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TransferLength; /* 14h */ + U32 TransactionContext; /* 18h */ + U32 Rctl_Did; /* 1Ch */ + U32 Csctl_Sid; /* 20h */ + U32 Type_Fctl; /* 24h */ + U16 SeqCnt; /* 28h */ + U8 Dfctl; /* 2Ah */ + U8 SeqId; /* 2Bh */ + U16 Rxid; /* 2Ch */ + U16 Oxid; /* 2Eh */ + U32 Parameter; /* 30h */ + WWNFORMAT Wwn; /* 34h */ +} MSG_LINK_SERVICE_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_LINK_SERVICE_BUFFER_POST_REPLY, + LinkServiceBufferPostReply_t, MPI_POINTER pLinkServiceBufferPostReply_t; + +#define MPI_LS_BUF_POST_REPLY_FLAG_NO_RSP_NEEDED (0x80) + +#define MPI_FC_DID_MASK (0x00FFFFFF) +#define MPI_FC_DID_SHIFT (0) +#define MPI_FC_RCTL_MASK (0xFF000000) +#define MPI_FC_RCTL_SHIFT (24) +#define MPI_FC_SID_MASK (0x00FFFFFF) +#define MPI_FC_SID_SHIFT (0) +#define MPI_FC_CSCTL_MASK (0xFF000000) +#define MPI_FC_CSCTL_SHIFT (24) +#define MPI_FC_FCTL_MASK (0x00FFFFFF) +#define MPI_FC_FCTL_SHIFT (0) +#define MPI_FC_TYPE_MASK (0xFF000000) +#define MPI_FC_TYPE_SHIFT (24) + +/* obsolete name for the above */ +#define FCP_TARGET_DID_MASK (0x00FFFFFF) +#define FCP_TARGET_DID_SHIFT (0) +#define FCP_TARGET_RCTL_MASK (0xFF000000) +#define FCP_TARGET_RCTL_SHIFT (24) +#define FCP_TARGET_SID_MASK (0x00FFFFFF) +#define FCP_TARGET_SID_SHIFT (0) +#define FCP_TARGET_CSCTL_MASK (0xFF000000) +#define FCP_TARGET_CSCTL_SHIFT (24) +#define FCP_TARGET_FCTL_MASK (0x00FFFFFF) +#define FCP_TARGET_FCTL_SHIFT (0) +#define FCP_TARGET_TYPE_MASK (0xFF000000) +#define FCP_TARGET_TYPE_SHIFT (24) + + +/****************************************************************************/ +/* Link Service Response messages */ +/****************************************************************************/ + +typedef struct _MSG_LINK_SERVICE_RSP_REQUEST +{ + U8 RspFlags; /* 00h */ + U8 RspLength; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Rctl_Did; /* 0Ch */ + U32 Csctl_Sid; /* 10h */ + U32 Type_Fctl; /* 14h */ + U16 SeqCnt; /* 18h */ + U8 Dfctl; /* 1Ah */ + U8 SeqId; /* 1Bh */ + U16 Rxid; /* 1Ch */ + U16 Oxid; /* 1Eh */ + U32 Parameter; /* 20h */ + SGE_SIMPLE_UNION SGL; /* 24h */ +} MSG_LINK_SERVICE_RSP_REQUEST, MPI_POINTER PTR_MSG_LINK_SERVICE_RSP_REQUEST, + LinkServiceRspRequest_t, MPI_POINTER pLinkServiceRspRequest_t; + +#define LINK_SERVICE_RSP_FLAGS_IMMEDIATE (0x80) +#define LINK_SERVICE_RSP_FLAGS_PORT_MASK (0x01) + + +/* Link Service Response Reply */ +typedef struct _MSG_LINK_SERVICE_RSP_REPLY +{ + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved_0100_InitiatorIndex; /* 06h */ /* obsolete InitiatorIndex */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 InitiatorIndex; /* 14h */ +} MSG_LINK_SERVICE_RSP_REPLY, MPI_POINTER PTR_MSG_LINK_SERVICE_RSP_REPLY, + LinkServiceRspReply_t, MPI_POINTER pLinkServiceRspReply_t; + + +/****************************************************************************/ +/* Extended Link Service Send messages */ +/****************************************************************************/ + +typedef struct _MSG_EXLINK_SERVICE_SEND_REQUEST +{ + U8 SendFlags; /* 00h */ + U8 AliasIndex; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U32 MsgFlags_Did; /* 04h */ + U32 MsgContext; /* 08h */ + U32 ElsCommandCode; /* 0Ch */ + SGE_SIMPLE_UNION SGL; /* 10h */ +} MSG_EXLINK_SERVICE_SEND_REQUEST, MPI_POINTER PTR_MSG_EXLINK_SERVICE_SEND_REQUEST, + ExLinkServiceSendRequest_t, MPI_POINTER pExLinkServiceSendRequest_t; + +#define EX_LINK_SERVICE_SEND_DID_MASK (0x00FFFFFF) +#define EX_LINK_SERVICE_SEND_DID_SHIFT (0) +#define EX_LINK_SERVICE_SEND_MSGFLAGS_MASK (0xFF000000) +#define EX_LINK_SERVICE_SEND_MSGFLAGS_SHIFT (24) + + +/* Extended Link Service Send Reply */ +typedef struct _MSG_EXLINK_SERVICE_SEND_REPLY +{ + U8 Reserved; /* 00h */ + U8 AliasIndex; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 ResponseLength; /* 14h */ +} MSG_EXLINK_SERVICE_SEND_REPLY, MPI_POINTER PTR_MSG_EXLINK_SERVICE_SEND_REPLY, + ExLinkServiceSendReply_t, MPI_POINTER pExLinkServiceSendReply_t; + +/****************************************************************************/ +/* FC Abort messages */ +/****************************************************************************/ + +typedef struct _MSG_FC_ABORT_REQUEST +{ + U8 AbortFlags; /* 00h */ + U8 AbortType; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 TransactionContextToAbort; /* 0Ch */ +} MSG_FC_ABORT_REQUEST, MPI_POINTER PTR_MSG_FC_ABORT_REQUEST, + FcAbortRequest_t, MPI_POINTER pFcAbortRequest_t; + +#define FC_ABORT_FLAG_PORT_MASK (0x01) + +#define FC_ABORT_TYPE_ALL_FC_BUFFERS (0x00) +#define FC_ABORT_TYPE_EXACT_FC_BUFFER (0x01) +#define FC_ABORT_TYPE_CT_SEND_REQUEST (0x02) +#define FC_ABORT_TYPE_EXLINKSEND_REQUEST (0x03) + +/* FC Abort Reply */ +typedef struct _MSG_FC_ABORT_REPLY +{ + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_FC_ABORT_REPLY, MPI_POINTER PTR_MSG_FC_ABORT_REPLY, + FcAbortReply_t, MPI_POINTER pFcAbortReply_t; + + +/****************************************************************************/ +/* FC Common Transport Send messages */ +/****************************************************************************/ + +typedef struct _MSG_FC_COMMON_TRANSPORT_SEND_REQUEST +{ + U8 SendFlags; /* 00h */ + U8 AliasIndex; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U32 MsgFlags_Did; /* 04h */ + U32 MsgContext; /* 08h */ + U16 CTCommandCode; /* 0Ch */ + U8 FsType; /* 0Eh */ + U8 Reserved1; /* 0Fh */ + SGE_SIMPLE_UNION SGL; /* 10h */ +} MSG_FC_COMMON_TRANSPORT_SEND_REQUEST, + MPI_POINTER PTR_MSG_FC_COMMON_TRANSPORT_SEND_REQUEST, + FcCommonTransportSendRequest_t, MPI_POINTER pFcCommonTransportSendRequest_t; + +#define MPI_FC_CT_SEND_DID_MASK (0x00FFFFFF) +#define MPI_FC_CT_SEND_DID_SHIFT (0) +#define MPI_FC_CT_SEND_MSGFLAGS_MASK (0xFF000000) +#define MPI_FC_CT_SEND_MSGFLAGS_SHIFT (24) + + +/* FC Common Transport Send Reply */ +typedef struct _MSG_FC_COMMON_TRANSPORT_SEND_REPLY +{ + U8 Reserved; /* 00h */ + U8 AliasIndex; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 ResponseLength; /* 14h */ +} MSG_FC_COMMON_TRANSPORT_SEND_REPLY, MPI_POINTER PTR_MSG_FC_COMMON_TRANSPORT_SEND_REPLY, + FcCommonTransportSendReply_t, MPI_POINTER pFcCommonTransportSendReply_t; + + +/****************************************************************************/ +/* FC Primitive Send messages */ +/****************************************************************************/ + +typedef struct _MSG_FC_PRIMITIVE_SEND_REQUEST +{ + U8 SendFlags; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 FcPrimitive[4]; /* 0Ch */ +} MSG_FC_PRIMITIVE_SEND_REQUEST, MPI_POINTER PTR_MSG_FC_PRIMITIVE_SEND_REQUEST, + FcPrimitiveSendRequest_t, MPI_POINTER pFcPrimitiveSendRequest_t; + +#define MPI_FC_PRIM_SEND_FLAGS_PORT_MASK (0x01) +#define MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK (0x02) +#define MPI_FC_PRIM_SEND_FLAGS_RESET_LINK (0x04) +#define MPI_FC_PRIM_SEND_FLAGS_STOP_SEND (0x08) +#define MPI_FC_PRIM_SEND_FLAGS_SEND_ONCE (0x10) +#define MPI_FC_PRIM_SEND_FLAGS_SEND_AROUND (0x20) +#define MPI_FC_PRIM_SEND_FLAGS_UNTIL_FULL (0x40) +#define MPI_FC_PRIM_SEND_FLAGS_FOREVER (0x80) + +/* FC Primitive Send Reply */ +typedef struct _MSG_FC_PRIMITIVE_SEND_REPLY +{ + U8 SendFlags; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_FC_PRIMITIVE_SEND_REPLY, MPI_POINTER PTR_MSG_FC_PRIMITIVE_SEND_REPLY, + FcPrimitiveSendReply_t, MPI_POINTER pFcPrimitiveSendReply_t; + +#endif + diff --git a/source/lsi/mpi_init.h b/source/lsi/mpi_init.h new file mode 100755 index 0000000..7d2ec74 --- /dev/null +++ b/source/lsi/mpi_init.h @@ -0,0 +1,580 @@ +/* + * Copyright (c) 2000-2008 LSI Corporation. + * + * + * Name: mpi_init.h + * Title: MPI initiator mode messages and structures + * Creation Date: June 8, 2000 + * + * mpi_init.h Version: 01.05.09 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. + * 05-24-00 00.10.02 Added SenseBufferLength to _MSG_SCSI_IO_REPLY. + * 06-06-00 01.00.01 Update version number for 1.0 release. + * 06-08-00 01.00.02 Added MPI_SCSI_RSP_INFO_ definitions. + * 11-02-00 01.01.01 Original release for post 1.0 work. + * 12-04-00 01.01.02 Added MPI_SCSIIO_CONTROL_NO_DISCONNECT. + * 02-20-01 01.01.03 Started using MPI_POINTER. + * 03-27-01 01.01.04 Added structure offset comments. + * 04-10-01 01.01.05 Added new MsgFlag for MSG_SCSI_TASK_MGMT. + * 08-08-01 01.02.01 Original release for v1.2 work. + * 08-29-01 01.02.02 Added MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET. + * Added MPI_SCSI_STATE_QUEUE_TAG_REJECTED for + * MSG_SCSI_IO_REPLY. + * 09-28-01 01.02.03 Added structures and defines for SCSI Enclosure + * Processor messages. + * 10-04-01 01.02.04 Added defines for SEP request Action field. + * 05-31-02 01.02.05 Added MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR define + * for SCSI IO requests. + * 11-15-02 01.02.06 Added special extended SCSI Status defines for FCP. + * 06-26-03 01.02.07 Added MPI_SCSI_STATUS_FCPEXT_UNASSIGNED define. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Added MsgFlags defines for EEDP to SCSI IO request. + * Added new word to MSG_SCSI_IO_REPLY to add TaskTag field + * and a reserved U16. + * Added new MSG_SCSI_IO32_REQUEST structure. + * Added a TaskType of Clear Task Set to SCSI + * Task Management request. + * 12-07-04 01.05.02 Added support for Task Management Query Task. + * 01-15-05 01.05.03 Modified SCSI Enclosure Processor Request to support + * WWID addressing. + * 03-11-05 01.05.04 Removed EEDP flags from SCSI IO Request. + * Removed SCSI IO 32 Request. + * Modified SCSI Enclosure Processor Request and Reply to + * support Enclosure/Slot addressing rather than WWID + * addressing. + * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. + * Added four new defines for SEP SlotStatus. + * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them + * unique in the first 32 characters. + * 03-27-06 01.05.07 Added Task Management type of Clear ACA. + * 10-11-06 01.05.08 Shortened define for Task Management type of Clear ACA. + * 02-28-07 01.05.09 Defined two new MsgFlags bits for SCSI Task Management + * Request: Do Not Send Task IU and Soft Reset Option. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_INIT_H +#define MPI_INIT_H + + +/***************************************************************************** +* +* S C S I I n i t i a t o r M e s s a g e s +* +*****************************************************************************/ + +/****************************************************************************/ +/* SCSI IO messages and associated structures */ +/****************************************************************************/ + +typedef struct _MSG_SCSI_IO_REQUEST +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 AliasIndex; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 LUN[8]; /* 0Ch */ + U32 Control; /* 14h */ + U8 CDB[16]; /* 18h */ + U32 DataLength; /* 28h */ + U32 SenseBufferLowAddr; /* 2Ch */ + SGE_IO_UNION SGL; /* 30h */ +} MSG_SCSI_IO_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO_REQUEST, + SCSIIORequest_t, MPI_POINTER pSCSIIORequest_t; + + +/* SCSI IO MsgFlags bits */ + +#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH (0x01) +#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32 (0x00) +#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 (0x01) + +#define MPI_SCSIIO_MSGFLGS_SENSE_LOCATION (0x02) +#define MPI_SCSIIO_MSGFLGS_SENSE_LOC_HOST (0x00) +#define MPI_SCSIIO_MSGFLGS_SENSE_LOC_IOC (0x02) + +#define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04) + +/* SCSI IO LUN fields */ + +#define MPI_SCSIIO_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF) +#define MPI_SCSIIO_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000) +#define MPI_SCSIIO_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF) +#define MPI_SCSIIO_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000) +#define MPI_SCSIIO_LUN_LEVEL_1_WORD (0xFF00) +#define MPI_SCSIIO_LUN_LEVEL_1_DWORD (0x0000FF00) + +/* SCSI IO Control bits */ + +#define MPI_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000) +#define MPI_SCSIIO_CONTROL_NODATATRANSFER (0x00000000) +#define MPI_SCSIIO_CONTROL_WRITE (0x01000000) +#define MPI_SCSIIO_CONTROL_READ (0x02000000) + +#define MPI_SCSIIO_CONTROL_ADDCDBLEN_MASK (0x3C000000) +#define MPI_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26) + +#define MPI_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700) +#define MPI_SCSIIO_CONTROL_SIMPLEQ (0x00000000) +#define MPI_SCSIIO_CONTROL_HEADOFQ (0x00000100) +#define MPI_SCSIIO_CONTROL_ORDEREDQ (0x00000200) +#define MPI_SCSIIO_CONTROL_ACAQ (0x00000400) +#define MPI_SCSIIO_CONTROL_UNTAGGED (0x00000500) +#define MPI_SCSIIO_CONTROL_NO_DISCONNECT (0x00000700) + +#define MPI_SCSIIO_CONTROL_TASKMANAGE_MASK (0x00FF0000) +#define MPI_SCSIIO_CONTROL_OBSOLETE (0x00800000) +#define MPI_SCSIIO_CONTROL_CLEAR_ACA_RSV (0x00400000) +#define MPI_SCSIIO_CONTROL_TARGET_RESET (0x00200000) +#define MPI_SCSIIO_CONTROL_LUN_RESET_RSV (0x00100000) +#define MPI_SCSIIO_CONTROL_RESERVED (0x00080000) +#define MPI_SCSIIO_CONTROL_CLR_TASK_SET_RSV (0x00040000) +#define MPI_SCSIIO_CONTROL_ABORT_TASK_SET (0x00020000) +#define MPI_SCSIIO_CONTROL_RESERVED2 (0x00010000) + + +/* SCSI IO reply structure */ +typedef struct _MSG_SCSI_IO_REPLY +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 AliasIndex; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 SCSIStatus; /* 0Ch */ + U8 SCSIState; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TransferCount; /* 14h */ + U32 SenseCount; /* 18h */ + U32 ResponseInfo; /* 1Ch */ + U16 TaskTag; /* 20h */ + U16 Reserved1; /* 22h */ +} MSG_SCSI_IO_REPLY, MPI_POINTER PTR_MSG_SCSI_IO_REPLY, + SCSIIOReply_t, MPI_POINTER pSCSIIOReply_t; + + +/* SCSI IO Reply SCSIStatus values (SAM-2 status codes) */ + +#define MPI_SCSI_STATUS_SUCCESS (0x00) +#define MPI_SCSI_STATUS_CHECK_CONDITION (0x02) +#define MPI_SCSI_STATUS_CONDITION_MET (0x04) +#define MPI_SCSI_STATUS_BUSY (0x08) +#define MPI_SCSI_STATUS_INTERMEDIATE (0x10) +#define MPI_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14) +#define MPI_SCSI_STATUS_RESERVATION_CONFLICT (0x18) +#define MPI_SCSI_STATUS_COMMAND_TERMINATED (0x22) +#define MPI_SCSI_STATUS_TASK_SET_FULL (0x28) +#define MPI_SCSI_STATUS_ACA_ACTIVE (0x30) + +#define MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT (0x80) +#define MPI_SCSI_STATUS_FCPEXT_NO_LINK (0x81) +#define MPI_SCSI_STATUS_FCPEXT_UNASSIGNED (0x82) + + +/* SCSI IO Reply SCSIState values */ + +#define MPI_SCSI_STATE_AUTOSENSE_VALID (0x01) +#define MPI_SCSI_STATE_AUTOSENSE_FAILED (0x02) +#define MPI_SCSI_STATE_NO_SCSI_STATUS (0x04) +#define MPI_SCSI_STATE_TERMINATED (0x08) +#define MPI_SCSI_STATE_RESPONSE_INFO_VALID (0x10) +#define MPI_SCSI_STATE_QUEUE_TAG_REJECTED (0x20) + +/* SCSI IO Reply ResponseInfo values */ +/* (FCP-1 RSP_CODE values and SPI-3 Packetized Failure codes) */ + +#define MPI_SCSI_RSP_INFO_FUNCTION_COMPLETE (0x00000000) +#define MPI_SCSI_RSP_INFO_FCP_BURST_LEN_ERROR (0x01000000) +#define MPI_SCSI_RSP_INFO_CMND_FIELDS_INVALID (0x02000000) +#define MPI_SCSI_RSP_INFO_FCP_DATA_RO_ERROR (0x03000000) +#define MPI_SCSI_RSP_INFO_TASK_MGMT_UNSUPPORTED (0x04000000) +#define MPI_SCSI_RSP_INFO_TASK_MGMT_FAILED (0x05000000) +#define MPI_SCSI_RSP_INFO_SPI_LQ_INVALID_TYPE (0x06000000) + +#define MPI_SCSI_TASKTAG_UNKNOWN (0xFFFF) + + +/****************************************************************************/ +/* SCSI IO 32 messages and associated structures */ +/****************************************************************************/ + +typedef struct +{ + U8 CDB[20]; /* 00h */ + U32 PrimaryReferenceTag; /* 14h */ + U16 PrimaryApplicationTag; /* 18h */ + U16 PrimaryApplicationTagMask; /* 1Ah */ + U32 TransferLength; /* 1Ch */ +} MPI_SCSI_IO32_CDB_EEDP32, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_EEDP32, + MpiScsiIo32CdbEedp32_t, MPI_POINTER pMpiScsiIo32CdbEedp32_t; + +typedef struct +{ + U8 CDB[16]; /* 00h */ + U32 DataLength; /* 10h */ + U32 PrimaryReferenceTag; /* 14h */ + U16 PrimaryApplicationTag; /* 18h */ + U16 PrimaryApplicationTagMask; /* 1Ah */ + U32 TransferLength; /* 1Ch */ +} MPI_SCSI_IO32_CDB_EEDP16, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_EEDP16, + MpiScsiIo32CdbEedp16_t, MPI_POINTER pMpiScsiIo32CdbEedp16_t; + +typedef union +{ + U8 CDB32[32]; + MPI_SCSI_IO32_CDB_EEDP32 EEDP32; + MPI_SCSI_IO32_CDB_EEDP16 EEDP16; + SGE_SIMPLE_UNION SGE; +} MPI_SCSI_IO32_CDB_UNION, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_UNION, + MpiScsiIo32Cdb_t, MPI_POINTER pMpiScsiIo32Cdb_t; + +typedef struct +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U16 Reserved1; /* 02h */ + U32 Reserved2; /* 04h */ +} MPI_SCSI_IO32_BUS_TARGET_ID_FORM, MPI_POINTER PTR_MPI_SCSI_IO32_BUS_TARGET_ID_FORM, + MpiScsiIo32BusTargetIdForm_t, MPI_POINTER pMpiScsiIo32BusTargetIdForm_t; + +typedef union +{ + MPI_SCSI_IO32_BUS_TARGET_ID_FORM SCSIID; + U64 WWID; +} MPI_SCSI_IO32_ADDRESS, MPI_POINTER PTR_MPI_SCSI_IO32_ADDRESS, + MpiScsiIo32Address_t, MPI_POINTER pMpiScsiIo32Address_t; + +typedef struct _MSG_SCSI_IO32_REQUEST +{ + U8 Port; /* 00h */ + U8 AliasIndex; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 Flags; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 LUN[8]; /* 0Ch */ + U32 Control; /* 14h */ + MPI_SCSI_IO32_CDB_UNION CDB; /* 18h */ + U32 DataLength; /* 38h */ + U32 BidirectionalDataLength; /* 3Ch */ + U32 SecondaryReferenceTag; /* 40h */ + U16 SecondaryApplicationTag; /* 44h */ + U16 Reserved2; /* 46h */ + U16 EEDPFlags; /* 48h */ + U16 ApplicationTagTranslationMask; /* 4Ah */ + U32 EEDPBlockSize; /* 4Ch */ + MPI_SCSI_IO32_ADDRESS DeviceAddress; /* 50h */ + U8 SGLOffset0; /* 58h */ + U8 SGLOffset1; /* 59h */ + U8 SGLOffset2; /* 5Ah */ + U8 SGLOffset3; /* 5Bh */ + U32 Reserved3; /* 5Ch */ + U32 Reserved4; /* 60h */ + U32 SenseBufferLowAddr; /* 64h */ + SGE_IO_UNION SGL; /* 68h */ +} MSG_SCSI_IO32_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO32_REQUEST, + SCSIIO32Request_t, MPI_POINTER pSCSIIO32Request_t; + +/* SCSI IO 32 MsgFlags bits */ +#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH (0x01) +#define MPI_SCSIIO32_MSGFLGS_32_SENSE_WIDTH (0x00) +#define MPI_SCSIIO32_MSGFLGS_64_SENSE_WIDTH (0x01) + +#define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02) +#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00) +#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_IOC (0x02) + +#define MPI_SCSIIO32_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04) +#define MPI_SCSIIO32_MSGFLGS_SGL_OFFSETS_CHAINS (0x08) +#define MPI_SCSIIO32_MSGFLGS_MULTICAST (0x10) +#define MPI_SCSIIO32_MSGFLGS_BIDIRECTIONAL (0x20) +#define MPI_SCSIIO32_MSGFLGS_LARGE_CDB (0x40) + +/* SCSI IO 32 Flags bits */ +#define MPI_SCSIIO32_FLAGS_FORM_MASK (0x03) +#define MPI_SCSIIO32_FLAGS_FORM_SCSIID (0x00) +#define MPI_SCSIIO32_FLAGS_FORM_WWID (0x01) + +/* SCSI IO 32 LUN fields */ +#define MPI_SCSIIO32_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF) +#define MPI_SCSIIO32_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000) +#define MPI_SCSIIO32_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF) +#define MPI_SCSIIO32_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000) +#define MPI_SCSIIO32_LUN_LEVEL_1_WORD (0xFF00) +#define MPI_SCSIIO32_LUN_LEVEL_1_DWORD (0x0000FF00) + +/* SCSI IO 32 Control bits */ +#define MPI_SCSIIO32_CONTROL_DATADIRECTION_MASK (0x03000000) +#define MPI_SCSIIO32_CONTROL_NODATATRANSFER (0x00000000) +#define MPI_SCSIIO32_CONTROL_WRITE (0x01000000) +#define MPI_SCSIIO32_CONTROL_READ (0x02000000) +#define MPI_SCSIIO32_CONTROL_BIDIRECTIONAL (0x03000000) + +#define MPI_SCSIIO32_CONTROL_ADDCDBLEN_MASK (0xFC000000) +#define MPI_SCSIIO32_CONTROL_ADDCDBLEN_SHIFT (26) + +#define MPI_SCSIIO32_CONTROL_TASKATTRIBUTE_MASK (0x00000700) +#define MPI_SCSIIO32_CONTROL_SIMPLEQ (0x00000000) +#define MPI_SCSIIO32_CONTROL_HEADOFQ (0x00000100) +#define MPI_SCSIIO32_CONTROL_ORDEREDQ (0x00000200) +#define MPI_SCSIIO32_CONTROL_ACAQ (0x00000400) +#define MPI_SCSIIO32_CONTROL_UNTAGGED (0x00000500) +#define MPI_SCSIIO32_CONTROL_NO_DISCONNECT (0x00000700) + +#define MPI_SCSIIO32_CONTROL_TASKMANAGE_MASK (0x00FF0000) +#define MPI_SCSIIO32_CONTROL_OBSOLETE (0x00800000) +#define MPI_SCSIIO32_CONTROL_CLEAR_ACA_RSV (0x00400000) +#define MPI_SCSIIO32_CONTROL_TARGET_RESET (0x00200000) +#define MPI_SCSIIO32_CONTROL_LUN_RESET_RSV (0x00100000) +#define MPI_SCSIIO32_CONTROL_RESERVED (0x00080000) +#define MPI_SCSIIO32_CONTROL_CLR_TASK_SET_RSV (0x00040000) +#define MPI_SCSIIO32_CONTROL_ABORT_TASK_SET (0x00020000) +#define MPI_SCSIIO32_CONTROL_RESERVED2 (0x00010000) + +/* SCSI IO 32 EEDPFlags */ +#define MPI_SCSIIO32_EEDPFLAGS_MASK_OP (0x0007) +#define MPI_SCSIIO32_EEDPFLAGS_NOOP_OP (0x0000) +#define MPI_SCSIIO32_EEDPFLAGS_CHK_OP (0x0001) +#define MPI_SCSIIO32_EEDPFLAGS_STRIP_OP (0x0002) +#define MPI_SCSIIO32_EEDPFLAGS_CHKRM_OP (0x0003) +#define MPI_SCSIIO32_EEDPFLAGS_INSERT_OP (0x0004) +#define MPI_SCSIIO32_EEDPFLAGS_REPLACE_OP (0x0006) +#define MPI_SCSIIO32_EEDPFLAGS_CHKREGEN_OP (0x0007) + +#define MPI_SCSIIO32_EEDPFLAGS_PASS_REF_TAG (0x0008) +#define MPI_SCSIIO32_EEDPFLAGS_8_9THS_MODE (0x0010) + +#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_MASK (0x0700) +#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_GUARD (0x0100) +#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_REFTAG (0x0200) +#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_LBATAG (0x0400) +#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_SHIFT (8) + +#define MPI_SCSIIO32_EEDPFLAGS_INC_SEC_APPTAG (0x1000) +#define MPI_SCSIIO32_EEDPFLAGS_INC_PRI_APPTAG (0x2000) +#define MPI_SCSIIO32_EEDPFLAGS_INC_SEC_REFTAG (0x4000) +#define MPI_SCSIIO32_EEDPFLAGS_INC_PRI_REFTAG (0x8000) + + +/* SCSIIO32 IO reply structure */ +typedef struct _MSG_SCSIIO32_IO_REPLY +{ + U8 Port; /* 00h */ + U8 AliasIndex; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 Flags; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 SCSIStatus; /* 0Ch */ + U8 SCSIState; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TransferCount; /* 14h */ + U32 SenseCount; /* 18h */ + U32 ResponseInfo; /* 1Ch */ + U16 TaskTag; /* 20h */ + U16 Reserved2; /* 22h */ + U32 BidirectionalTransferCount; /* 24h */ +} MSG_SCSIIO32_IO_REPLY, MPI_POINTER PTR_MSG_SCSIIO32_IO_REPLY, + SCSIIO32Reply_t, MPI_POINTER pSCSIIO32Reply_t; + + +/****************************************************************************/ +/* SCSI Task Management messages */ +/****************************************************************************/ + +typedef struct _MSG_SCSI_TASK_MGMT +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved; /* 04h */ + U8 TaskType; /* 05h */ + U8 AliasIndex; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 LUN[8]; /* 0Ch */ + U32 Reserved2[7]; /* 14h */ + U32 TaskMsgContext; /* 30h */ +} MSG_SCSI_TASK_MGMT, MPI_POINTER PTR_SCSI_TASK_MGMT, + SCSITaskMgmt_t, MPI_POINTER pSCSITaskMgmt_t; + +/* TaskType values */ + +#define MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) +#define MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02) +#define MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) +#define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS (0x04) +#define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) +#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) +#define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) +#define MPI_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08) + +/* MsgFlags bits */ +#define MPI_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01) + +#define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00) +#define MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION (0x02) +#define MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION (0x04) + +#define MPI_SCSITASKMGMT_MSGFLAGS_SOFT_RESET_OPTION (0x08) + +/* SCSI Task Management Reply */ +typedef struct _MSG_SCSI_TASK_MGMT_REPLY +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 ResponseCode; /* 04h */ + U8 TaskType; /* 05h */ + U8 AliasIndex; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2[2]; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TerminationCount; /* 14h */ +} MSG_SCSI_TASK_MGMT_REPLY, MPI_POINTER PTR_MSG_SCSI_TASK_MGMT_REPLY, + SCSITaskMgmtReply_t, MPI_POINTER pSCSITaskMgmtReply_t; + +/* ResponseCode values */ +#define MPI_SCSITASKMGMT_RSP_TM_COMPLETE (0x00) +#define MPI_SCSITASKMGMT_RSP_INVALID_FRAME (0x02) +#define MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04) +#define MPI_SCSITASKMGMT_RSP_TM_FAILED (0x05) +#define MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08) +#define MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09) +#define MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80) + + +/****************************************************************************/ +/* SCSI Enclosure Processor messages */ +/****************************************************************************/ + +typedef struct _MSG_SEP_REQUEST +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Action; /* 04h */ + U8 Flags; /* 05h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 SlotStatus; /* 0Ch */ + U32 Reserved2; /* 10h */ + U32 Reserved3; /* 14h */ + U32 Reserved4; /* 18h */ + U16 Slot; /* 1Ch */ + U16 EnclosureHandle; /* 1Eh */ +} MSG_SEP_REQUEST, MPI_POINTER PTR_MSG_SEP_REQUEST, + SEPRequest_t, MPI_POINTER pSEPRequest_t; + +/* Action defines */ +#define MPI_SEP_REQ_ACTION_WRITE_STATUS (0x00) +#define MPI_SEP_REQ_ACTION_READ_STATUS (0x01) + +/* Flags defines */ +#define MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01) +#define MPI_SEP_REQ_FLAGS_BUS_TARGETID_ADDRESS (0x00) + +/* SlotStatus bits for MSG_SEP_REQUEST */ +#define MPI_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) +#define MPI_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) +#define MPI_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004) +#define MPI_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) +#define MPI_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) +#define MPI_SEP_REQ_SLOTSTATUS_PARITY_CHECK (0x00000020) +#define MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040) +#define MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) +#define MPI_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) +#define MPI_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200) +#define MPI_SEP_REQ_SLOTSTATUS_REQ_CONSISTENCY_CHECK (0x00001000) +#define MPI_SEP_REQ_SLOTSTATUS_DISABLE (0x00002000) +#define MPI_SEP_REQ_SLOTSTATUS_REQ_RESERVED_DEVICE (0x00004000) +#define MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) +#define MPI_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000) +#define MPI_SEP_REQ_SLOTSTATUS_REQUEST_INSERT (0x00080000) +#define MPI_SEP_REQ_SLOTSTATUS_DO_NOT_MOVE (0x00400000) +#define MPI_SEP_REQ_SLOTSTATUS_ACTIVE (0x00800000) +#define MPI_SEP_REQ_SLOTSTATUS_B_ENABLE_BYPASS (0x04000000) +#define MPI_SEP_REQ_SLOTSTATUS_A_ENABLE_BYPASS (0x08000000) +#define MPI_SEP_REQ_SLOTSTATUS_DEV_OFF (0x10000000) +#define MPI_SEP_REQ_SLOTSTATUS_SWAP_RESET (0x80000000) + + +typedef struct _MSG_SEP_REPLY +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Action; /* 04h */ + U8 Reserved1; /* 05h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 SlotStatus; /* 14h */ + U32 Reserved4; /* 18h */ + U16 Slot; /* 1Ch */ + U16 EnclosureHandle; /* 1Eh */ +} MSG_SEP_REPLY, MPI_POINTER PTR_MSG_SEP_REPLY, + SEPReply_t, MPI_POINTER pSEPReply_t; + +/* SlotStatus bits for MSG_SEP_REPLY */ +#define MPI_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001) +#define MPI_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002) +#define MPI_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004) +#define MPI_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) +#define MPI_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) +#define MPI_SEP_REPLY_SLOTSTATUS_PARITY_CHECK (0x00000020) +#define MPI_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040) +#define MPI_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080) +#define MPI_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100) +#define MPI_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200) +#define MPI_SEP_REPLY_SLOTSTATUS_CONSISTENCY_CHECK (0x00001000) +#define MPI_SEP_REPLY_SLOTSTATUS_DISABLE (0x00002000) +#define MPI_SEP_REPLY_SLOTSTATUS_RESERVED_DEVICE (0x00004000) +#define MPI_SEP_REPLY_SLOTSTATUS_REPORT (0x00010000) +#define MPI_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) +#define MPI_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000) +#define MPI_SEP_REPLY_SLOTSTATUS_INSERT_READY (0x00080000) +#define MPI_SEP_REPLY_SLOTSTATUS_DO_NOT_REMOVE (0x00400000) +#define MPI_SEP_REPLY_SLOTSTATUS_ACTIVE (0x00800000) +#define MPI_SEP_REPLY_SLOTSTATUS_B_BYPASS_ENABLED (0x01000000) +#define MPI_SEP_REPLY_SLOTSTATUS_A_BYPASS_ENABLED (0x02000000) +#define MPI_SEP_REPLY_SLOTSTATUS_B_ENABLE_BYPASS (0x04000000) +#define MPI_SEP_REPLY_SLOTSTATUS_A_ENABLE_BYPASS (0x08000000) +#define MPI_SEP_REPLY_SLOTSTATUS_DEV_OFF (0x10000000) +#define MPI_SEP_REPLY_SLOTSTATUS_FAULT_SENSED (0x40000000) +#define MPI_SEP_REPLY_SLOTSTATUS_SWAPPED (0x80000000) + +#endif diff --git a/source/lsi/mpi_ioc.h b/source/lsi/mpi_ioc.h new file mode 100755 index 0000000..fc561fe --- /dev/null +++ b/source/lsi/mpi_ioc.h @@ -0,0 +1,1206 @@ +/* + * Copyright (c) 2000-2008 LSI Corporation. + * + * + * Name: mpi_ioc.h + * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages + * Creation Date: August 11, 2000 + * + * mpi_ioc.h Version: 01.05.16 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. + * 05-24-00 00.10.02 Added _MSG_IOC_INIT_REPLY structure. + * 06-06-00 01.00.01 Added CurReplyFrameSize field to _MSG_IOC_FACTS_REPLY. + * 06-12-00 01.00.02 Added _MSG_PORT_ENABLE_REPLY structure. + * Added _MSG_EVENT_ACK_REPLY structure. + * Added _MSG_FW_DOWNLOAD_REPLY structure. + * Added _MSG_TOOLBOX_REPLY structure. + * 06-30-00 01.00.03 Added MaxLanBuckets to _PORT_FACT_REPLY structure. + * 07-27-00 01.00.04 Added _EVENT_DATA structure definitions for _SCSI, + * _LINK_STATUS, _LOOP_STATE and _LOGOUT. + * 08-11-00 01.00.05 Switched positions of MsgLength and Function fields in + * _MSG_EVENT_ACK_REPLY structure to match specification. + * 11-02-00 01.01.01 Original release for post 1.0 work. + * Added a value for Manufacturer to WhoInit. + * 12-04-00 01.01.02 Modified IOCFacts reply, added FWUpload messages, and + * removed toolbox message. + * 01-09-01 01.01.03 Added event enabled and disabled defines. + * Added structures for FwHeader and DataHeader. + * Added ImageType to FwUpload reply. + * 02-20-01 01.01.04 Started using MPI_POINTER. + * 02-27-01 01.01.05 Added event for RAID status change and its event data. + * Added IocNumber field to MSG_IOC_FACTS_REPLY. + * 03-27-01 01.01.06 Added defines for ProductId field of MPI_FW_HEADER. + * Added structure offset comments. + * 04-09-01 01.01.07 Added structure EVENT_DATA_EVENT_CHANGE. + * 08-08-01 01.02.01 Original release for v1.2 work. + * New format for FWVersion and ProductId in + * MSG_IOC_FACTS_REPLY and MPI_FW_HEADER. + * 08-31-01 01.02.02 Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and + * related structure and defines. + * Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED. + * Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE. + * Replaced a reserved field in MSG_IOC_FACTS_REPLY with + * IOCExceptions and changed DataImageSize to reserved. + * Added MPI_FW_DOWNLOAD_ITYPE_NVSTORE_DATA and + * MPI_FW_UPLOAD_ITYPE_NVDATA. + * 09-28-01 01.02.03 Modified Event Data for Integrated RAID. + * 11-01-01 01.02.04 Added defines for MPI_EXT_IMAGE_HEADER ImageType field. + * 03-14-02 01.02.05 Added HeaderVersion field to MSG_IOC_FACTS_REPLY. + * 05-31-02 01.02.06 Added define for + * MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID. + * Added AliasIndex to EVENT_DATA_LOGOUT structure. + * 04-01-03 01.02.07 Added defines for MPI_FW_HEADER_SIGNATURE_. + * 06-26-03 01.02.08 Added new values to the product family defines. + * 04-29-04 01.02.09 Added IOCCapabilities field to MSG_IOC_FACTS_REPLY and + * added related defines. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Added four new fields to MSG_IOC_INIT. + * Added three new fields to MSG_IOC_FACTS_REPLY. + * Defined four new bits for the IOCCapabilities field of + * the IOCFacts reply. + * Added two new PortTypes for the PortFacts reply. + * Added six new events along with their EventData + * structures. + * Added a new MsgFlag to the FwDownload request to + * indicate last segment. + * Defined a new image type of boot loader. + * Added FW family codes for SAS product families. + * 10-05-04 01.05.02 Added ReplyFifoHostSignalingAddr field to + * MSG_IOC_FACTS_REPLY. + * 12-07-04 01.05.03 Added more defines for SAS Discovery Error event. + * 12-09-04 01.05.04 Added Unsupported device to SAS Device event. + * 01-15-05 01.05.05 Added event data for SAS SES Event. + * 02-09-05 01.05.06 Added MPI_FW_UPLOAD_ITYPE_FW_BACKUP define. + * 02-22-05 01.05.07 Added Host Page Buffer Persistent flag to IOC Facts + * Reply and IOC Init Request. + * 03-11-05 01.05.08 Added family code for 1068E family. + * Removed IOCFacts Reply EEDP Capability bit. + * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. + * Added Max SATA Targets to SAS Discovery Error event. + * 08-30-05 01.05.10 Added 4 new events and their event data structures. + * Added new ReasonCode value for SAS Device Status Change + * event. + * Added new family code for FC949E. + * 03-27-06 01.05.11 Added MPI_IOCFACTS_CAPABILITY_TLR. + * Added additional Reason Codes and more event data fields + * to EVENT_DATA_SAS_DEVICE_STATUS_CHANGE. + * Added EVENT_DATA_SAS_BROADCAST_PRIMITIVE structure and + * new event. + * Added MPI_EVENT_SAS_SMP_ERROR and event data structure. + * Added MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE and event + * data structure. + * Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event + * data structure. + * Added MPI_EXT_IMAGE_TYPE_INITIALIZATION. + * 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED. + * Added MaxInitiators field to PortFacts reply. + * Added SAS Device Status Change ReasonCode for + * asynchronous notificaiton. + * Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event + * data structure. + * Added new ImageType values for FWDownload and FWUpload + * requests. + * 02-28-07 01.05.13 Added MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT for SAS + * Broadcast Event Data (replacing _RESERVED2). + * For Discovery Error Event Data DiscoveryStatus field, + * replaced _MULTPL_PATHS with _UNSUPPORTED_DEVICE and + * added _MULTI_PORT_DOMAIN. + * 05-24-07 01.05.14 Added Common Boot Block type to FWDownload Request. + * Added Common Boot Block type to FWUpload Request. + * 08-07-07 01.05.15 Added MPI_EVENT_SAS_INIT_RC_REMOVED define. + * Added MPI_EVENT_IR2_RC_DUAL_PORT_ADDED and + * MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED for IR2 event data. + * Added SASAddress field to SAS Initiator Device Table + * Overflow event data structure. + * 03-28-08 01.05.16 Added two new ReasonCode values to SAS Device Status + * Change Event data to indicate completion of internally + * generated task management. + * Added MPI_EVENT_DSCVRY_ERR_DS_SATA_INIT_FAILURE define. + * Added MPI_EVENT_SAS_INIT_RC_INACCESSIBLE define. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_IOC_H +#define MPI_IOC_H + + +/***************************************************************************** +* +* I O C M e s s a g e s +* +*****************************************************************************/ + +/****************************************************************************/ +/* IOCInit message */ +/****************************************************************************/ + +typedef struct _MSG_IOC_INIT +{ + U8 WhoInit; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Flags; /* 04h */ + U8 MaxDevices; /* 05h */ + U8 MaxBuses; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 ReplyFrameSize; /* 0Ch */ + U8 Reserved1[2]; /* 0Eh */ + U32 HostMfaHighAddr; /* 10h */ + U32 SenseBufferHighAddr; /* 14h */ + U32 ReplyFifoHostSignalingAddr; /* 18h */ + SGE_SIMPLE_UNION HostPageBufferSGE; /* 1Ch */ + U16 MsgVersion; /* 28h */ + U16 HeaderVersion; /* 2Ah */ +} MSG_IOC_INIT, MPI_POINTER PTR_MSG_IOC_INIT, + IOCInit_t, MPI_POINTER pIOCInit_t; + +/* WhoInit values */ +#define MPI_WHOINIT_NO_ONE (0x00) +#define MPI_WHOINIT_SYSTEM_BIOS (0x01) +#define MPI_WHOINIT_ROM_BIOS (0x02) +#define MPI_WHOINIT_PCI_PEER (0x03) +#define MPI_WHOINIT_HOST_DRIVER (0x04) +#define MPI_WHOINIT_MANUFACTURER (0x05) + +/* Flags values */ +#define MPI_IOCINIT_FLAGS_HOST_PAGE_BUFFER_PERSISTENT (0x04) +#define MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02) +#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE (0x01) + +/* MsgVersion */ +#define MPI_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00) +#define MPI_IOCINIT_MSGVERSION_MAJOR_SHIFT (8) +#define MPI_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF) +#define MPI_IOCINIT_MSGVERSION_MINOR_SHIFT (0) + +/* HeaderVersion */ +#define MPI_IOCINIT_HEADERVERSION_UNIT_MASK (0xFF00) +#define MPI_IOCINIT_HEADERVERSION_UNIT_SHIFT (8) +#define MPI_IOCINIT_HEADERVERSION_DEV_MASK (0x00FF) +#define MPI_IOCINIT_HEADERVERSION_DEV_SHIFT (0) + + +typedef struct _MSG_IOC_INIT_REPLY +{ + U8 WhoInit; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Flags; /* 04h */ + U8 MaxDevices; /* 05h */ + U8 MaxBuses; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_IOC_INIT_REPLY, MPI_POINTER PTR_MSG_IOC_INIT_REPLY, + IOCInitReply_t, MPI_POINTER pIOCInitReply_t; + + + +/****************************************************************************/ +/* IOC Facts message */ +/****************************************************************************/ + +typedef struct _MSG_IOC_FACTS +{ + U8 Reserved[2]; /* 00h */ + U8 ChainOffset; /* 01h */ + U8 Function; /* 02h */ + U8 Reserved1[3]; /* 03h */ + U8 MsgFlags; /* 04h */ + U32 MsgContext; /* 08h */ +} MSG_IOC_FACTS, MPI_POINTER PTR_IOC_FACTS, + IOCFacts_t, MPI_POINTER pIOCFacts_t; + +typedef struct _MPI_FW_VERSION_STRUCT +{ + U8 Dev; /* 00h */ + U8 Unit; /* 01h */ + U8 Minor; /* 02h */ + U8 Major; /* 03h */ +} MPI_FW_VERSION_STRUCT; + +typedef union _MPI_FW_VERSION +{ + MPI_FW_VERSION_STRUCT Struct; + U32 Word; +} MPI_FW_VERSION; + +/* IOC Facts Reply */ +typedef struct _MSG_IOC_FACTS_REPLY +{ + U16 MsgVersion; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 HeaderVersion; /* 04h */ + U8 IOCNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 IOCExceptions; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U8 MaxChainDepth; /* 14h */ + U8 WhoInit; /* 15h */ + U8 BlockSize; /* 16h */ + U8 Flags; /* 17h */ + U16 ReplyQueueDepth; /* 18h */ + U16 RequestFrameSize; /* 1Ah */ + U16 Reserved_0101_FWVersion; /* 1Ch */ /* obsolete 16-bit FWVersion */ + U16 ProductID; /* 1Eh */ + U32 CurrentHostMfaHighAddr; /* 20h */ + U16 GlobalCredits; /* 24h */ + U8 NumberOfPorts; /* 26h */ + U8 EventState; /* 27h */ + U32 CurrentSenseBufferHighAddr; /* 28h */ + U16 CurReplyFrameSize; /* 2Ch */ + U8 MaxDevices; /* 2Eh */ + U8 MaxBuses; /* 2Fh */ + U32 FWImageSize; /* 30h */ + U32 IOCCapabilities; /* 34h */ + MPI_FW_VERSION FWVersion; /* 38h */ + U16 HighPriorityQueueDepth; /* 3Ch */ + U16 Reserved2; /* 3Eh */ + SGE_SIMPLE_UNION HostPageBufferSGE; /* 40h */ + U32 ReplyFifoHostSignalingAddr; /* 4Ch */ +} MSG_IOC_FACTS_REPLY, MPI_POINTER PTR_MSG_IOC_FACTS_REPLY, + IOCFactsReply_t, MPI_POINTER pIOCFactsReply_t; + +#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00) +#define MPI_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8) +#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF) +#define MPI_IOCFACTS_MSGVERSION_MINOR_SHIFT (0) + +#define MPI_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00) +#define MPI_IOCFACTS_HDRVERSION_UNIT_SHIFT (8) +#define MPI_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF) +#define MPI_IOCFACTS_HDRVERSION_DEV_SHIFT (0) + +#define MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001) +#define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) +#define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004) +#define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL (0x0008) +#define MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010) + +#define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT (0x01) +#define MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02) +#define MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT (0x04) + +#define MPI_IOCFACTS_EVENTSTATE_DISABLED (0x00) +#define MPI_IOCFACTS_EVENTSTATE_ENABLED (0x01) + +#define MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q (0x00000001) +#define MPI_IOCFACTS_CAPABILITY_REPLY_HOST_SIGNAL (0x00000002) +#define MPI_IOCFACTS_CAPABILITY_QUEUE_FULL_HANDLING (0x00000004) +#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008) +#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010) +#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020) +#define MPI_IOCFACTS_CAPABILITY_EEDP (0x00000040) +#define MPI_IOCFACTS_CAPABILITY_BIDIRECTIONAL (0x00000080) +#define MPI_IOCFACTS_CAPABILITY_MULTICAST (0x00000100) +#define MPI_IOCFACTS_CAPABILITY_SCSIIO32 (0x00000200) +#define MPI_IOCFACTS_CAPABILITY_NO_SCSIIO16 (0x00000400) +#define MPI_IOCFACTS_CAPABILITY_TLR (0x00000800) + + +/***************************************************************************** +* +* P o r t M e s s a g e s +* +*****************************************************************************/ + +/****************************************************************************/ +/* Port Facts message and Reply */ +/****************************************************************************/ + +typedef struct _MSG_PORT_FACTS +{ + U8 Reserved[2]; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[2]; /* 04h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ +} MSG_PORT_FACTS, MPI_POINTER PTR_MSG_PORT_FACTS, + PortFacts_t, MPI_POINTER pPortFacts_t; + +typedef struct _MSG_PORT_FACTS_REPLY +{ + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U8 Reserved3; /* 14h */ + U8 PortType; /* 15h */ + U16 MaxDevices; /* 16h */ + U16 PortSCSIID; /* 18h */ + U16 ProtocolFlags; /* 1Ah */ + U16 MaxPostedCmdBuffers; /* 1Ch */ + U16 MaxPersistentIDs; /* 1Eh */ + U16 MaxLanBuckets; /* 20h */ + U8 MaxInitiators; /* 22h */ + U8 Reserved4; /* 23h */ + U32 Reserved5; /* 24h */ +} MSG_PORT_FACTS_REPLY, MPI_POINTER PTR_MSG_PORT_FACTS_REPLY, + PortFactsReply_t, MPI_POINTER pPortFactsReply_t; + + +/* PortTypes values */ + +#define MPI_PORTFACTS_PORTTYPE_INACTIVE (0x00) +#define MPI_PORTFACTS_PORTTYPE_SCSI (0x01) +#define MPI_PORTFACTS_PORTTYPE_FC (0x10) +#define MPI_PORTFACTS_PORTTYPE_ISCSI (0x20) +#define MPI_PORTFACTS_PORTTYPE_SAS (0x30) + +/* ProtocolFlags values */ + +#define MPI_PORTFACTS_PROTOCOL_LOGBUSADDR (0x01) +#define MPI_PORTFACTS_PROTOCOL_LAN (0x02) +#define MPI_PORTFACTS_PROTOCOL_TARGET (0x04) +#define MPI_PORTFACTS_PROTOCOL_INITIATOR (0x08) + + +/****************************************************************************/ +/* Port Enable Message */ +/****************************************************************************/ + +typedef struct _MSG_PORT_ENABLE +{ + U8 Reserved[2]; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[2]; /* 04h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ +} MSG_PORT_ENABLE, MPI_POINTER PTR_MSG_PORT_ENABLE, + PortEnable_t, MPI_POINTER pPortEnable_t; + +typedef struct _MSG_PORT_ENABLE_REPLY +{ + U8 Reserved[2]; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[2]; /* 04h */ + U8 PortNumber; /* 05h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_PORT_ENABLE_REPLY, MPI_POINTER PTR_MSG_PORT_ENABLE_REPLY, + PortEnableReply_t, MPI_POINTER pPortEnableReply_t; + + +/***************************************************************************** +* +* E v e n t M e s s a g e s +* +*****************************************************************************/ + +/****************************************************************************/ +/* Event Notification messages */ +/****************************************************************************/ + +typedef struct _MSG_EVENT_NOTIFY +{ + U8 Switch; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ +} MSG_EVENT_NOTIFY, MPI_POINTER PTR_MSG_EVENT_NOTIFY, + EventNotification_t, MPI_POINTER pEventNotification_t; + +/* Event Notification Reply */ + +typedef struct _MSG_EVENT_NOTIFY_REPLY +{ + U16 EventDataLength; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[2]; /* 04h */ + U8 AckRequired; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2[2]; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 Event; /* 14h */ + U32 EventContext; /* 18h */ + U32 Data[1]; /* 1Ch */ +} MSG_EVENT_NOTIFY_REPLY, MPI_POINTER PTR_MSG_EVENT_NOTIFY_REPLY, + EventNotificationReply_t, MPI_POINTER pEventNotificationReply_t; + +/* Event Acknowledge */ + +typedef struct _MSG_EVENT_ACK +{ + U8 Reserved[2]; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Event; /* 0Ch */ + U32 EventContext; /* 10h */ +} MSG_EVENT_ACK, MPI_POINTER PTR_MSG_EVENT_ACK, + EventAck_t, MPI_POINTER pEventAck_t; + +typedef struct _MSG_EVENT_ACK_REPLY +{ + U8 Reserved[2]; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_EVENT_ACK_REPLY, MPI_POINTER PTR_MSG_EVENT_ACK_REPLY, + EventAckReply_t, MPI_POINTER pEventAckReply_t; + +/* Switch */ + +#define MPI_EVENT_NOTIFICATION_SWITCH_OFF (0x00) +#define MPI_EVENT_NOTIFICATION_SWITCH_ON (0x01) + +/* Event */ + +#define MPI_EVENT_NONE (0x00000000) +#define MPI_EVENT_LOG_DATA (0x00000001) +#define MPI_EVENT_STATE_CHANGE (0x00000002) +#define MPI_EVENT_UNIT_ATTENTION (0x00000003) +#define MPI_EVENT_IOC_BUS_RESET (0x00000004) +#define MPI_EVENT_EXT_BUS_RESET (0x00000005) +#define MPI_EVENT_RESCAN (0x00000006) +#define MPI_EVENT_LINK_STATUS_CHANGE (0x00000007) +#define MPI_EVENT_LOOP_STATE_CHANGE (0x00000008) +#define MPI_EVENT_LOGOUT (0x00000009) +#define MPI_EVENT_EVENT_CHANGE (0x0000000A) +#define MPI_EVENT_INTEGRATED_RAID (0x0000000B) +#define MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE (0x0000000C) +#define MPI_EVENT_ON_BUS_TIMER_EXPIRED (0x0000000D) +#define MPI_EVENT_QUEUE_FULL (0x0000000E) +#define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE (0x0000000F) +#define MPI_EVENT_SAS_SES (0x00000010) +#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011) +#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012) +#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013) +#define MPI_EVENT_IR_RESYNC_UPDATE (0x00000014) +#define MPI_EVENT_IR2 (0x00000015) +#define MPI_EVENT_SAS_DISCOVERY (0x00000016) +#define MPI_EVENT_SAS_BROADCAST_PRIMITIVE (0x00000017) +#define MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x00000018) +#define MPI_EVENT_SAS_INIT_TABLE_OVERFLOW (0x00000019) +#define MPI_EVENT_SAS_SMP_ERROR (0x0000001A) +#define MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE (0x0000001B) +#define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021) + +/* AckRequired field values */ + +#define MPI_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00) +#define MPI_EVENT_NOTIFICATION_ACK_REQUIRED (0x01) + +/* EventChange Event data */ + +typedef struct _EVENT_DATA_EVENT_CHANGE +{ + U8 EventState; /* 00h */ + U8 Reserved; /* 01h */ + U16 Reserved1; /* 02h */ +} EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE, + EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t; + +/* LogEntryAdded Event data */ + +/* this structure matches MPI_LOG_0_ENTRY in mpi_cnfg.h */ +#define MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH (0x1C) +typedef struct _EVENT_DATA_LOG_ENTRY +{ + U32 TimeStamp; /* 00h */ + U32 Reserved1; /* 04h */ + U16 LogSequence; /* 08h */ + U16 LogEntryQualifier; /* 0Ah */ + U8 LogData[MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH]; /* 0Ch */ +} EVENT_DATA_LOG_ENTRY, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY, + MpiEventDataLogEntry_t, MPI_POINTER pMpiEventDataLogEntry_t; + +typedef struct _EVENT_DATA_LOG_ENTRY_ADDED +{ + U16 LogSequence; /* 00h */ + U16 Reserved1; /* 02h */ + U32 Reserved2; /* 04h */ + EVENT_DATA_LOG_ENTRY LogEntry; /* 08h */ +} EVENT_DATA_LOG_ENTRY_ADDED, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY_ADDED, + MpiEventDataLogEntryAdded_t, MPI_POINTER pMpiEventDataLogEntryAdded_t; + +/* SCSI Event data for Port, Bus and Device forms */ + +typedef struct _EVENT_DATA_SCSI +{ + U8 TargetID; /* 00h */ + U8 BusPort; /* 01h */ + U16 Reserved; /* 02h */ +} EVENT_DATA_SCSI, MPI_POINTER PTR_EVENT_DATA_SCSI, + EventDataScsi_t, MPI_POINTER pEventDataScsi_t; + +/* SCSI Device Status Change Event data */ + +typedef struct _EVENT_DATA_SCSI_DEVICE_STATUS_CHANGE +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ReasonCode; /* 02h */ + U8 LUN; /* 03h */ + U8 ASC; /* 04h */ + U8 ASCQ; /* 05h */ + U16 Reserved; /* 06h */ +} EVENT_DATA_SCSI_DEVICE_STATUS_CHANGE, + MPI_POINTER PTR_EVENT_DATA_SCSI_DEVICE_STATUS_CHANGE, + MpiEventDataScsiDeviceStatusChange_t, + MPI_POINTER pMpiEventDataScsiDeviceStatusChange_t; + +/* MPI SCSI Device Status Change Event data ReasonCode values */ +#define MPI_EVENT_SCSI_DEV_STAT_RC_ADDED (0x03) +#define MPI_EVENT_SCSI_DEV_STAT_RC_NOT_RESPONDING (0x04) +#define MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA (0x05) + +/* SAS Device Status Change Event data */ + +typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ReasonCode; /* 02h */ + U8 Reserved; /* 03h */ + U8 ASC; /* 04h */ + U8 ASCQ; /* 05h */ + U16 DevHandle; /* 06h */ + U32 DeviceInfo; /* 08h */ + U16 ParentDevHandle; /* 0Ch */ + U8 PhyNum; /* 0Eh */ + U8 Reserved1; /* 0Fh */ + U64 SASAddress; /* 10h */ + U8 LUN[8]; /* 18h */ + U16 TaskTag; /* 20h */ + U16 Reserved2; /* 22h */ +} EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, + MPI_POINTER PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, + MpiEventDataSasDeviceStatusChange_t, + MPI_POINTER pMpiEventDataSasDeviceStatusChange_t; + +/* MPI SAS Device Status Change Event data ReasonCode values */ +#define MPI_EVENT_SAS_DEV_STAT_RC_ADDED (0x03) +#define MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING (0x04) +#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) +#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06) +#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) +#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) +#define MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09) +#define MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) +#define MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) +#define MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) +#define MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) +#define MPI_EVENT_SAS_DEV_STAT_RC_CMPL_INTERNAL_DEV_RESET (0x0E) +#define MPI_EVENT_SAS_DEV_STAT_RC_CMPL_TASK_ABORT_INTERNAL (0x0F) + + +/* SCSI Event data for Queue Full event */ + +typedef struct _EVENT_DATA_QUEUE_FULL +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U16 CurrentDepth; /* 02h */ +} EVENT_DATA_QUEUE_FULL, MPI_POINTER PTR_EVENT_DATA_QUEUE_FULL, + EventDataQueueFull_t, MPI_POINTER pEventDataQueueFull_t; + +/* MPI Integrated RAID Event data */ + +typedef struct _EVENT_DATA_RAID +{ + U8 VolumeID; /* 00h */ + U8 VolumeBus; /* 01h */ + U8 ReasonCode; /* 02h */ + U8 PhysDiskNum; /* 03h */ + U8 ASC; /* 04h */ + U8 ASCQ; /* 05h */ + U16 Reserved; /* 06h */ + U32 SettingsStatus; /* 08h */ +} EVENT_DATA_RAID, MPI_POINTER PTR_EVENT_DATA_RAID, + MpiEventDataRaid_t, MPI_POINTER pMpiEventDataRaid_t; + +/* MPI Integrated RAID Event data ReasonCode values */ +#define MPI_EVENT_RAID_RC_VOLUME_CREATED (0x00) +#define MPI_EVENT_RAID_RC_VOLUME_DELETED (0x01) +#define MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED (0x02) +#define MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED (0x03) +#define MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED (0x04) +#define MPI_EVENT_RAID_RC_PHYSDISK_CREATED (0x05) +#define MPI_EVENT_RAID_RC_PHYSDISK_DELETED (0x06) +#define MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED (0x07) +#define MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED (0x08) +#define MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED (0x09) +#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A) +#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B) + + +/* MPI Integrated RAID Resync Update Event data */ + +typedef struct _MPI_EVENT_DATA_IR_RESYNC_UPDATE +{ + U8 VolumeID; /* 00h */ + U8 VolumeBus; /* 01h */ + U8 ResyncComplete; /* 02h */ + U8 Reserved1; /* 03h */ + U32 Reserved2; /* 04h */ +} MPI_EVENT_DATA_IR_RESYNC_UPDATE, + MPI_POINTER PTR_MPI_EVENT_DATA_IR_RESYNC_UPDATE, + MpiEventDataIrResyncUpdate_t, MPI_POINTER pMpiEventDataIrResyncUpdate_t; + +/* MPI IR2 Event data */ + +/* MPI_LD_STATE or MPI_PD_STATE */ +typedef struct _IR2_STATE_CHANGED +{ + U16 PreviousState; /* 00h */ + U16 NewState; /* 02h */ +} IR2_STATE_CHANGED, MPI_POINTER PTR_IR2_STATE_CHANGED; + +typedef struct _IR2_PD_INFO +{ + U16 DeviceHandle; /* 00h */ + U8 TruncEnclosureHandle; /* 02h */ + U8 TruncatedSlot; /* 03h */ +} IR2_PD_INFO, MPI_POINTER PTR_IR2_PD_INFO; + +typedef union _MPI_IR2_RC_EVENT_DATA +{ + IR2_STATE_CHANGED StateChanged; + U32 Lba; + IR2_PD_INFO PdInfo; +} MPI_IR2_RC_EVENT_DATA, MPI_POINTER PTR_MPI_IR2_RC_EVENT_DATA; + +typedef struct _MPI_EVENT_DATA_IR2 +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ReasonCode; /* 02h */ + U8 PhysDiskNum; /* 03h */ + MPI_IR2_RC_EVENT_DATA IR2EventData; /* 04h */ +} MPI_EVENT_DATA_IR2, MPI_POINTER PTR_MPI_EVENT_DATA_IR2, + MpiEventDataIR2_t, MPI_POINTER pMpiEventDataIR2_t; + +/* MPI IR2 Event data ReasonCode values */ +#define MPI_EVENT_IR2_RC_LD_STATE_CHANGED (0x01) +#define MPI_EVENT_IR2_RC_PD_STATE_CHANGED (0x02) +#define MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL (0x03) +#define MPI_EVENT_IR2_RC_PD_INSERTED (0x04) +#define MPI_EVENT_IR2_RC_PD_REMOVED (0x05) +#define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED (0x06) +#define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR (0x07) +#define MPI_EVENT_IR2_RC_DUAL_PORT_ADDED (0x08) +#define MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED (0x09) + +/* defines for logical disk states */ +#define MPI_LD_STATE_OPTIMAL (0x00) +#define MPI_LD_STATE_DEGRADED (0x01) +#define MPI_LD_STATE_FAILED (0x02) +#define MPI_LD_STATE_MISSING (0x03) +#define MPI_LD_STATE_OFFLINE (0x04) + +/* defines for physical disk states */ +#define MPI_PD_STATE_ONLINE (0x00) +#define MPI_PD_STATE_MISSING (0x01) +#define MPI_PD_STATE_NOT_COMPATIBLE (0x02) +#define MPI_PD_STATE_FAILED (0x03) +#define MPI_PD_STATE_INITIALIZING (0x04) +#define MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST (0x05) +#define MPI_PD_STATE_FAILED_AT_HOST_REQUEST (0x06) +#define MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON (0xFF) + +/* MPI Link Status Change Event data */ + +typedef struct _EVENT_DATA_LINK_STATUS +{ + U8 State; /* 00h */ + U8 Reserved; /* 01h */ + U16 Reserved1; /* 02h */ + U8 Reserved2; /* 04h */ + U8 Port; /* 05h */ + U16 Reserved3; /* 06h */ +} EVENT_DATA_LINK_STATUS, MPI_POINTER PTR_EVENT_DATA_LINK_STATUS, + EventDataLinkStatus_t, MPI_POINTER pEventDataLinkStatus_t; + +#define MPI_EVENT_LINK_STATUS_FAILURE (0x00000000) +#define MPI_EVENT_LINK_STATUS_ACTIVE (0x00000001) + +/* MPI Loop State Change Event data */ + +typedef struct _EVENT_DATA_LOOP_STATE +{ + U8 Character4; /* 00h */ + U8 Character3; /* 01h */ + U8 Type; /* 02h */ + U8 Reserved; /* 03h */ + U8 Reserved1; /* 04h */ + U8 Port; /* 05h */ + U16 Reserved2; /* 06h */ +} EVENT_DATA_LOOP_STATE, MPI_POINTER PTR_EVENT_DATA_LOOP_STATE, + EventDataLoopState_t, MPI_POINTER pEventDataLoopState_t; + +#define MPI_EVENT_LOOP_STATE_CHANGE_LIP (0x0001) +#define MPI_EVENT_LOOP_STATE_CHANGE_LPE (0x0002) +#define MPI_EVENT_LOOP_STATE_CHANGE_LPB (0x0003) + +/* MPI LOGOUT Event data */ + +typedef struct _EVENT_DATA_LOGOUT +{ + U32 NPortID; /* 00h */ + U8 AliasIndex; /* 04h */ + U8 Port; /* 05h */ + U16 Reserved1; /* 06h */ +} EVENT_DATA_LOGOUT, MPI_POINTER PTR_EVENT_DATA_LOGOUT, + EventDataLogout_t, MPI_POINTER pEventDataLogout_t; + +#define MPI_EVENT_LOGOUT_ALL_ALIASES (0xFF) + +/* SAS SES Event data */ + +typedef struct _EVENT_DATA_SAS_SES +{ + U8 PhyNum; /* 00h */ + U8 Port; /* 01h */ + U8 PortWidth; /* 02h */ + U8 Reserved1; /* 04h */ +} EVENT_DATA_SAS_SES, MPI_POINTER PTR_EVENT_DATA_SAS_SES, + MpiEventDataSasSes_t, MPI_POINTER pMpiEventDataSasSes_t; + +/* SAS Broadcast Primitive Event data */ + +typedef struct _EVENT_DATA_SAS_BROADCAST_PRIMITIVE +{ + U8 PhyNum; /* 00h */ + U8 Port; /* 01h */ + U8 PortWidth; /* 02h */ + U8 Primitive; /* 04h */ +} EVENT_DATA_SAS_BROADCAST_PRIMITIVE, + MPI_POINTER PTR_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, + MpiEventDataSasBroadcastPrimitive_t, + MPI_POINTER pMpiEventDataSasBroadcastPrimitive_t; + +#define MPI_EVENT_PRIMITIVE_CHANGE (0x01) +#define MPI_EVENT_PRIMITIVE_EXPANDER (0x03) +#define MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04) +#define MPI_EVENT_PRIMITIVE_RESERVED3 (0x05) +#define MPI_EVENT_PRIMITIVE_RESERVED4 (0x06) +#define MPI_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07) +#define MPI_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08) + +/* SAS Phy Link Status Event data */ + +typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS +{ + U8 PhyNum; /* 00h */ + U8 LinkRates; /* 01h */ + U16 DevHandle; /* 02h */ + U64 SASAddress; /* 04h */ +} EVENT_DATA_SAS_PHY_LINK_STATUS, MPI_POINTER PTR_EVENT_DATA_SAS_PHY_LINK_STATUS, + MpiEventDataSasPhyLinkStatus_t, MPI_POINTER pMpiEventDataSasPhyLinkStatus_t; + +/* defines for the LinkRates field of the SAS PHY Link Status event */ +#define MPI_EVENT_SAS_PLS_LR_CURRENT_MASK (0xF0) +#define MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT (4) +#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_MASK (0x0F) +#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_SHIFT (0) +#define MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN (0x00) +#define MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED (0x01) +#define MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION (0x02) +#define MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE (0x03) +#define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08) +#define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09) + +/* SAS Discovery Event data */ + +typedef struct _EVENT_DATA_SAS_DISCOVERY +{ + U32 DiscoveryStatus; /* 00h */ + U32 Reserved1; /* 04h */ +} EVENT_DATA_SAS_DISCOVERY, MPI_POINTER PTR_EVENT_DATA_SAS_DISCOVERY, + EventDataSasDiscovery_t, MPI_POINTER pEventDataSasDiscovery_t; + +#define MPI_EVENT_SAS_DSCVRY_COMPLETE (0x00000000) +#define MPI_EVENT_SAS_DSCVRY_IN_PROGRESS (0x00000001) +#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_MASK (0xFFFF0000) +#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_SHIFT (16) + +/* SAS Discovery Errror Event data */ + +typedef struct _EVENT_DATA_DISCOVERY_ERROR +{ + U32 DiscoveryStatus; /* 00h */ + U8 Port; /* 04h */ + U8 Reserved1; /* 05h */ + U16 Reserved2; /* 06h */ +} EVENT_DATA_DISCOVERY_ERROR, MPI_POINTER PTR_EVENT_DATA_DISCOVERY_ERROR, + EventDataDiscoveryError_t, MPI_POINTER pEventDataDiscoveryError_t; + +#define MPI_EVENT_DSCVRY_ERR_DS_LOOP_DETECTED (0x00000001) +#define MPI_EVENT_DSCVRY_ERR_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI_EVENT_DSCVRY_ERR_DS_MULTIPLE_PORTS (0x00000004) +#define MPI_EVENT_DSCVRY_ERR_DS_EXPANDER_ERR (0x00000008) +#define MPI_EVENT_DSCVRY_ERR_DS_SMP_TIMEOUT (0x00000010) +#define MPI_EVENT_DSCVRY_ERR_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI_EVENT_DSCVRY_ERR_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI_EVENT_DSCVRY_ERR_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI_EVENT_DSCVRY_ERR_DS_SMP_CRC_ERROR (0x00000100) +#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE (0x00000200) +#define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE (0x00000400) +#define MPI_EVENT_DSCVRY_ERR_DS_UNSUPPORTED_DEVICE (0x00000800) +#define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS (0x00001000) +#define MPI_EVENT_DSCVRY_ERR_DS_MULTI_PORT_DOMAIN (0x00002000) +#define MPI_EVENT_DSCVRY_ERR_DS_SATA_INIT_FAILURE (0x00004000) + +/* SAS SMP Error Event data */ + +typedef struct _EVENT_DATA_SAS_SMP_ERROR +{ + U8 Status; /* 00h */ + U8 Port; /* 01h */ + U8 SMPFunctionResult; /* 02h */ + U8 Reserved1; /* 03h */ + U64 SASAddress; /* 04h */ +} EVENT_DATA_SAS_SMP_ERROR, MPI_POINTER PTR_EVENT_DATA_SAS_SMP_ERROR, + MpiEventDataSasSmpError_t, MPI_POINTER pMpiEventDataSasSmpError_t; + +/* defines for the Status field of the SAS SMP Error event */ +#define MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID (0x00) +#define MPI_EVENT_SAS_SMP_CRC_ERROR (0x01) +#define MPI_EVENT_SAS_SMP_TIMEOUT (0x02) +#define MPI_EVENT_SAS_SMP_NO_DESTINATION (0x03) +#define MPI_EVENT_SAS_SMP_BAD_DESTINATION (0x04) + +/* SAS Initiator Device Status Change Event data */ + +typedef struct _EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE +{ + U8 ReasonCode; /* 00h */ + U8 Port; /* 01h */ + U16 DevHandle; /* 02h */ + U64 SASAddress; /* 04h */ +} EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, + MPI_POINTER PTR_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, + MpiEventDataSasInitDevStatusChange_t, + MPI_POINTER pMpiEventDataSasInitDevStatusChange_t; + +/* defines for the ReasonCode field of the SAS Initiator Device Status Change event */ +#define MPI_EVENT_SAS_INIT_RC_ADDED (0x01) +#define MPI_EVENT_SAS_INIT_RC_REMOVED (0x02) +#define MPI_EVENT_SAS_INIT_RC_INACCESSIBLE (0x03) + +/* SAS Initiator Device Table Overflow Event data */ + +typedef struct _EVENT_DATA_SAS_INIT_TABLE_OVERFLOW +{ + U8 MaxInit; /* 00h */ + U8 CurrentInit; /* 01h */ + U16 Reserved1; /* 02h */ + U64 SASAddress; /* 04h */ +} EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, + MPI_POINTER PTR_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, + MpiEventDataSasInitTableOverflow_t, + MPI_POINTER pMpiEventDataSasInitTableOverflow_t; + +/* SAS Expander Status Change Event data */ + +typedef struct _EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE +{ + U8 ReasonCode; /* 00h */ + U8 Reserved1; /* 01h */ + U16 Reserved2; /* 02h */ + U8 PhysicalPort; /* 04h */ + U8 Reserved3; /* 05h */ + U16 EnclosureHandle; /* 06h */ + U64 SASAddress; /* 08h */ + U32 DiscoveryStatus; /* 10h */ + U16 DevHandle; /* 14h */ + U16 ParentDevHandle; /* 16h */ + U16 ExpanderChangeCount; /* 18h */ + U16 ExpanderRouteIndexes; /* 1Ah */ + U8 NumPhys; /* 1Ch */ + U8 SASLevel; /* 1Dh */ + U8 Flags; /* 1Eh */ + U8 Reserved4; /* 1Fh */ +} EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE, + MPI_POINTER PTR_EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE, + MpiEventDataSasExpanderStatusChange_t, + MPI_POINTER pMpiEventDataSasExpanderStatusChange_t; + +/* values for ReasonCode field of SAS Expander Status Change Event data */ +#define MPI_EVENT_SAS_EXP_RC_ADDED (0x00) +#define MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING (0x01) + +/* values for DiscoveryStatus field of SAS Expander Status Change Event data */ +#define MPI_EVENT_SAS_EXP_DS_LOOP_DETECTED (0x00000001) +#define MPI_EVENT_SAS_EXP_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI_EVENT_SAS_EXP_DS_MULTIPLE_PORTS (0x00000004) +#define MPI_EVENT_SAS_EXP_DS_EXPANDER_ERR (0x00000008) +#define MPI_EVENT_SAS_EXP_DS_SMP_TIMEOUT (0x00000010) +#define MPI_EVENT_SAS_EXP_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI_EVENT_SAS_EXP_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI_EVENT_SAS_EXP_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI_EVENT_SAS_EXP_DS_SMP_CRC_ERROR (0x00000100) +#define MPI_EVENT_SAS_EXP_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI_EVENT_SAS_EXP_DS_TABLE_LINK (0x00000400) +#define MPI_EVENT_SAS_EXP_DS_UNSUPPORTED_DEVICE (0x00000800) + +/* values for Flags field of SAS Expander Status Change Event data */ +#define MPI_EVENT_SAS_EXP_FLAGS_ROUTE_TABLE_CONFIG (0x02) +#define MPI_EVENT_SAS_EXP_FLAGS_CONFIG_IN_PROGRESS (0x01) + + + +/***************************************************************************** +* +* F i r m w a r e L o a d M e s s a g e s +* +*****************************************************************************/ + +/****************************************************************************/ +/* Firmware Download message and associated structures */ +/****************************************************************************/ + +typedef struct _MSG_FW_DOWNLOAD +{ + U8 ImageType; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + SGE_MPI_UNION SGL; /* 0Ch */ +} MSG_FW_DOWNLOAD, MPI_POINTER PTR_MSG_FW_DOWNLOAD, + FWDownload_t, MPI_POINTER pFWDownload_t; + +#define MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01) + +#define MPI_FW_DOWNLOAD_ITYPE_RESERVED (0x00) +#define MPI_FW_DOWNLOAD_ITYPE_FW (0x01) +#define MPI_FW_DOWNLOAD_ITYPE_BIOS (0x02) +#define MPI_FW_DOWNLOAD_ITYPE_NVDATA (0x03) +#define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER (0x04) +#define MPI_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06) +#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07) +#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08) +#define MPI_FW_DOWNLOAD_ITYPE_MEGARAID (0x09) +#define MPI_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) + + +typedef struct _FWDownloadTCSGE +{ + U8 Reserved; /* 00h */ + U8 ContextSize; /* 01h */ + U8 DetailsLength; /* 02h */ + U8 Flags; /* 03h */ + U32 Reserved_0100_Checksum; /* 04h */ /* obsolete Checksum */ + U32 ImageOffset; /* 08h */ + U32 ImageSize; /* 0Ch */ +} FW_DOWNLOAD_TCSGE, MPI_POINTER PTR_FW_DOWNLOAD_TCSGE, + FWDownloadTCSGE_t, MPI_POINTER pFWDownloadTCSGE_t; + +/* Firmware Download reply */ +typedef struct _MSG_FW_DOWNLOAD_REPLY +{ + U8 ImageType; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_FW_DOWNLOAD_REPLY, MPI_POINTER PTR_MSG_FW_DOWNLOAD_REPLY, + FWDownloadReply_t, MPI_POINTER pFWDownloadReply_t; + + +/****************************************************************************/ +/* Firmware Upload message and associated structures */ +/****************************************************************************/ + +typedef struct _MSG_FW_UPLOAD +{ + U8 ImageType; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + SGE_MPI_UNION SGL; /* 0Ch */ +} MSG_FW_UPLOAD, MPI_POINTER PTR_MSG_FW_UPLOAD, + FWUpload_t, MPI_POINTER pFWUpload_t; + +#define MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM (0x00) +#define MPI_FW_UPLOAD_ITYPE_FW_FLASH (0x01) +#define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) +#define MPI_FW_UPLOAD_ITYPE_NVDATA (0x03) +#define MPI_FW_UPLOAD_ITYPE_BOOTLOADER (0x04) +#define MPI_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) +#define MPI_FW_UPLOAD_ITYPE_MANUFACTURING (0x06) +#define MPI_FW_UPLOAD_ITYPE_CONFIG_1 (0x07) +#define MPI_FW_UPLOAD_ITYPE_CONFIG_2 (0x08) +#define MPI_FW_UPLOAD_ITYPE_MEGARAID (0x09) +#define MPI_FW_UPLOAD_ITYPE_COMPLETE (0x0A) +#define MPI_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) + +typedef struct _FWUploadTCSGE +{ + U8 Reserved; /* 00h */ + U8 ContextSize; /* 01h */ + U8 DetailsLength; /* 02h */ + U8 Flags; /* 03h */ + U32 Reserved1; /* 04h */ + U32 ImageOffset; /* 08h */ + U32 ImageSize; /* 0Ch */ +} FW_UPLOAD_TCSGE, MPI_POINTER PTR_FW_UPLOAD_TCSGE, + FWUploadTCSGE_t, MPI_POINTER pFWUploadTCSGE_t; + +/* Firmware Upload reply */ +typedef struct _MSG_FW_UPLOAD_REPLY +{ + U8 ImageType; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 ActualImageSize; /* 14h */ +} MSG_FW_UPLOAD_REPLY, MPI_POINTER PTR_MSG_FW_UPLOAD_REPLY, + FWUploadReply_t, MPI_POINTER pFWUploadReply_t; + + +typedef struct _MPI_FW_HEADER +{ + U32 ArmBranchInstruction0; /* 00h */ + U32 Signature0; /* 04h */ + U32 Signature1; /* 08h */ + U32 Signature2; /* 0Ch */ + U32 ArmBranchInstruction1; /* 10h */ + U32 ArmBranchInstruction2; /* 14h */ + U32 Reserved; /* 18h */ + U32 Checksum; /* 1Ch */ + U16 VendorId; /* 20h */ + U16 ProductId; /* 22h */ + MPI_FW_VERSION FWVersion; /* 24h */ + U32 SeqCodeVersion; /* 28h */ + U32 ImageSize; /* 2Ch */ + U32 NextImageHeaderOffset; /* 30h */ + U32 LoadStartAddress; /* 34h */ + U32 IopResetVectorValue; /* 38h */ + U32 IopResetRegAddr; /* 3Ch */ + U32 VersionNameWhat; /* 40h */ + U8 VersionName[32]; /* 44h */ + U32 VendorNameWhat; /* 64h */ + U8 VendorName[32]; /* 68h */ +} MPI_FW_HEADER, MPI_POINTER PTR_MPI_FW_HEADER, + MpiFwHeader_t, MPI_POINTER pMpiFwHeader_t; + +#define MPI_FW_HEADER_WHAT_SIGNATURE (0x29232840) + +/* defines for using the ProductId field */ +#define MPI_FW_HEADER_PID_TYPE_MASK (0xF000) +#define MPI_FW_HEADER_PID_TYPE_SCSI (0x0000) +#define MPI_FW_HEADER_PID_TYPE_FC (0x1000) +#define MPI_FW_HEADER_PID_TYPE_SAS (0x2000) + +#define MPI_FW_HEADER_SIGNATURE_0 (0x5AEAA55A) +#define MPI_FW_HEADER_SIGNATURE_1 (0xA55AEAA5) +#define MPI_FW_HEADER_SIGNATURE_2 (0x5AA55AEA) + +#define MPI_FW_HEADER_PID_PROD_MASK (0x0F00) +#define MPI_FW_HEADER_PID_PROD_INITIATOR_SCSI (0x0100) +#define MPI_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI (0x0200) +#define MPI_FW_HEADER_PID_PROD_TARGET_SCSI (0x0300) +#define MPI_FW_HEADER_PID_PROD_IM_SCSI (0x0400) +#define MPI_FW_HEADER_PID_PROD_IS_SCSI (0x0500) +#define MPI_FW_HEADER_PID_PROD_CTX_SCSI (0x0600) +#define MPI_FW_HEADER_PID_PROD_IR_SCSI (0x0700) + +#define MPI_FW_HEADER_PID_FAMILY_MASK (0x00FF) +/* SCSI */ +#define MPI_FW_HEADER_PID_FAMILY_1030A0_SCSI (0x0001) +#define MPI_FW_HEADER_PID_FAMILY_1030B0_SCSI (0x0002) +#define MPI_FW_HEADER_PID_FAMILY_1030B1_SCSI (0x0003) +#define MPI_FW_HEADER_PID_FAMILY_1030C0_SCSI (0x0004) +#define MPI_FW_HEADER_PID_FAMILY_1020A0_SCSI (0x0005) +#define MPI_FW_HEADER_PID_FAMILY_1020B0_SCSI (0x0006) +#define MPI_FW_HEADER_PID_FAMILY_1020B1_SCSI (0x0007) +#define MPI_FW_HEADER_PID_FAMILY_1020C0_SCSI (0x0008) +#define MPI_FW_HEADER_PID_FAMILY_1035A0_SCSI (0x0009) +#define MPI_FW_HEADER_PID_FAMILY_1035B0_SCSI (0x000A) +#define MPI_FW_HEADER_PID_FAMILY_1030TA0_SCSI (0x000B) +#define MPI_FW_HEADER_PID_FAMILY_1020TA0_SCSI (0x000C) +/* Fibre Channel */ +#define MPI_FW_HEADER_PID_FAMILY_909_FC (0x0000) +#define MPI_FW_HEADER_PID_FAMILY_919_FC (0x0001) /* 919 and 929 */ +#define MPI_FW_HEADER_PID_FAMILY_919X_FC (0x0002) /* 919X and 929X */ +#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */ +#define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */ +#define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005) +#define MPI_FW_HEADER_PID_FAMILY_949E_FC (0x0006) +/* SAS */ +#define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001) +#define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002) +#define MPI_FW_HEADER_PID_FAMILY_1078_SAS (0x0003) +#define MPI_FW_HEADER_PID_FAMILY_106xE_SAS (0x0004) /* 1068E, 1066E, and 1064E */ + +typedef struct _MPI_EXT_IMAGE_HEADER +{ + U8 ImageType; /* 00h */ + U8 Reserved; /* 01h */ + U16 Reserved1; /* 02h */ + U32 Checksum; /* 04h */ + U32 ImageSize; /* 08h */ + U32 NextImageHeaderOffset; /* 0Ch */ + U32 LoadStartAddress; /* 10h */ + U32 Reserved2; /* 14h */ +} MPI_EXT_IMAGE_HEADER, MPI_POINTER PTR_MPI_EXT_IMAGE_HEADER, + MpiExtImageHeader_t, MPI_POINTER pMpiExtImageHeader_t; + +/* defines for the ImageType field */ +#define MPI_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) +#define MPI_EXT_IMAGE_TYPE_FW (0x01) +#define MPI_EXT_IMAGE_TYPE_NVDATA (0x03) +#define MPI_EXT_IMAGE_TYPE_BOOTLOADER (0x04) +#define MPI_EXT_IMAGE_TYPE_INITIALIZATION (0x05) + +#endif diff --git a/source/lsi/mpi_raid.h b/source/lsi/mpi_raid.h new file mode 100755 index 0000000..df91c41 --- /dev/null +++ b/source/lsi/mpi_raid.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2001-2008 LSI Corporation. + * + * + * Name: mpi_raid.h + * Title: MPI RAID message and structures + * Creation Date: February 27, 2001 + * + * mpi_raid.h Version: 01.05.05 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 02-27-01 01.01.01 Original release for this file. + * 03-27-01 01.01.02 Added structure offset comments. + * 08-08-01 01.02.01 Original release for v1.2 work. + * 09-28-01 01.02.02 Major rework for MPI v1.2 Integrated RAID changes. + * 10-04-01 01.02.03 Added ActionData defines for + * MPI_RAID_ACTION_DELETE_VOLUME action. + * 11-01-01 01.02.04 Added define for MPI_RAID_ACTION_ADATA_DO_NOT_SYNC. + * 03-14-02 01.02.05 Added define for MPI_RAID_ACTION_ADATA_LOW_LEVEL_INIT. + * 05-07-02 01.02.06 Added define for MPI_RAID_ACTION_ACTIVATE_VOLUME, + * MPI_RAID_ACTION_INACTIVATE_VOLUME, and + * MPI_RAID_ACTION_ADATA_INACTIVATE_ALL. + * 07-12-02 01.02.07 Added structures for Mailbox request and reply. + * 11-15-02 01.02.08 Added missing MsgContext field to MSG_MAILBOX_REQUEST. + * 04-01-03 01.02.09 New action data option flag for + * MPI_RAID_ACTION_DELETE_VOLUME. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. + * 01-15-05 01.05.02 Added defines for the two new RAID Actions for + * _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE. + * 02-28-07 01.05.03 Added new RAID Action, Device FW Update Mode, and + * associated defines. + * 08-07-07 01.05.04 Added Disable Full Rebuild bit to the ActionDataWord + * for the RAID Action MPI_RAID_ACTION_DISABLE_VOLUME. + * 01-15-08 01.05.05 Added define for MPI_RAID_ACTION_SET_VOLUME_NAME. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_RAID_H +#define MPI_RAID_H + + +/****************************************************************************** +* +* R A I D M e s s a g e s +* +*******************************************************************************/ + + +/****************************************************************************/ +/* RAID Action Request */ +/****************************************************************************/ + +typedef struct _MSG_RAID_ACTION +{ + U8 Action; /* 00h */ + U8 Reserved1; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 VolumeID; /* 04h */ + U8 VolumeBus; /* 05h */ + U8 PhysDiskNum; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved2; /* 0Ch */ + U32 ActionDataWord; /* 10h */ + SGE_SIMPLE_UNION ActionDataSGE; /* 14h */ +} MSG_RAID_ACTION_REQUEST, MPI_POINTER PTR_MSG_RAID_ACTION_REQUEST, + MpiRaidActionRequest_t , MPI_POINTER pMpiRaidActionRequest_t; + + +/* RAID Action request Action values */ + +#define MPI_RAID_ACTION_STATUS (0x00) +#define MPI_RAID_ACTION_INDICATOR_STRUCT (0x01) +#define MPI_RAID_ACTION_CREATE_VOLUME (0x02) +#define MPI_RAID_ACTION_DELETE_VOLUME (0x03) +#define MPI_RAID_ACTION_DISABLE_VOLUME (0x04) +#define MPI_RAID_ACTION_ENABLE_VOLUME (0x05) +#define MPI_RAID_ACTION_QUIESCE_PHYS_IO (0x06) +#define MPI_RAID_ACTION_ENABLE_PHYS_IO (0x07) +#define MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS (0x08) +#define MPI_RAID_ACTION_PHYSDISK_OFFLINE (0x0A) +#define MPI_RAID_ACTION_PHYSDISK_ONLINE (0x0B) +#define MPI_RAID_ACTION_CHANGE_PHYSDISK_SETTINGS (0x0C) +#define MPI_RAID_ACTION_CREATE_PHYSDISK (0x0D) +#define MPI_RAID_ACTION_DELETE_PHYSDISK (0x0E) +#define MPI_RAID_ACTION_FAIL_PHYSDISK (0x0F) +#define MPI_RAID_ACTION_REPLACE_PHYSDISK (0x10) +#define MPI_RAID_ACTION_ACTIVATE_VOLUME (0x11) +#define MPI_RAID_ACTION_INACTIVATE_VOLUME (0x12) +#define MPI_RAID_ACTION_SET_RESYNC_RATE (0x13) +#define MPI_RAID_ACTION_SET_DATA_SCRUB_RATE (0x14) +#define MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15) +#define MPI_RAID_ACTION_SET_VOLUME_NAME (0x16) + +/* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */ +#define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC (0x00000001) +#define MPI_RAID_ACTION_ADATA_LOW_LEVEL_INIT (0x00000002) + +/* ActionDataWord defines for use with MPI_RAID_ACTION_DELETE_VOLUME action */ +#define MPI_RAID_ACTION_ADATA_KEEP_PHYS_DISKS (0x00000000) +#define MPI_RAID_ACTION_ADATA_DEL_PHYS_DISKS (0x00000001) + +#define MPI_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000) +#define MPI_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000002) + +/* ActionDataWord defines for use with MPI_RAID_ACTION_DISABLE_VOLUME action */ +#define MPI_RAID_ACTION_ADATA_DISABLE_FULL_REBUILD (0x00000001) + +/* ActionDataWord defines for use with MPI_RAID_ACTION_ACTIVATE_VOLUME action */ +#define MPI_RAID_ACTION_ADATA_INACTIVATE_ALL (0x00000001) + +/* ActionDataWord defines for use with MPI_RAID_ACTION_SET_RESYNC_RATE action */ +#define MPI_RAID_ACTION_ADATA_RESYNC_RATE_MASK (0x000000FF) + +/* ActionDataWord defines for use with MPI_RAID_ACTION_SET_DATA_SCRUB_RATE action */ +#define MPI_RAID_ACTION_ADATA_DATA_SCRUB_RATE_MASK (0x000000FF) + +/* ActionDataWord defines for use with MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */ +#define MPI_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x00000001) +#define MPI_RAID_ACTION_ADATA_MASK_FW_UPDATE_TIMEOUT (0x0000FF00) +#define MPI_RAID_ACTION_ADATA_SHIFT_FW_UPDATE_TIMEOUT (8) + + +/* RAID Action reply message */ + +typedef struct _MSG_RAID_ACTION_REPLY +{ + U8 Action; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 VolumeID; /* 04h */ + U8 VolumeBus; /* 05h */ + U8 PhysDiskNum; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 ActionStatus; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 VolumeStatus; /* 14h */ + U32 ActionData; /* 18h */ +} MSG_RAID_ACTION_REPLY, MPI_POINTER PTR_MSG_RAID_ACTION_REPLY, + MpiRaidActionReply_t, MPI_POINTER pMpiRaidActionReply_t; + + +/* RAID Volume reply ActionStatus values */ + +#define MPI_RAID_ACTION_ASTATUS_SUCCESS (0x0000) +#define MPI_RAID_ACTION_ASTATUS_INVALID_ACTION (0x0001) +#define MPI_RAID_ACTION_ASTATUS_FAILURE (0x0002) +#define MPI_RAID_ACTION_ASTATUS_IN_PROGRESS (0x0003) + + +/* RAID Volume reply RAID Volume Indicator structure */ + +typedef struct _MPI_RAID_VOL_INDICATOR +{ + U64 TotalBlocks; /* 00h */ + U64 BlocksRemaining; /* 08h */ +} MPI_RAID_VOL_INDICATOR, MPI_POINTER PTR_MPI_RAID_VOL_INDICATOR, + MpiRaidVolIndicator_t, MPI_POINTER pMpiRaidVolIndicator_t; + + +/****************************************************************************/ +/* SCSI IO RAID Passthrough Request */ +/****************************************************************************/ + +typedef struct _MSG_SCSI_IO_RAID_PT_REQUEST +{ + U8 PhysDiskNum; /* 00h */ + U8 Reserved1; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 LUN[8]; /* 0Ch */ + U32 Control; /* 14h */ + U8 CDB[16]; /* 18h */ + U32 DataLength; /* 28h */ + U32 SenseBufferLowAddr; /* 2Ch */ + SGE_IO_UNION SGL; /* 30h */ +} MSG_SCSI_IO_RAID_PT_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO_RAID_PT_REQUEST, + SCSIIORaidPassthroughRequest_t, MPI_POINTER pSCSIIORaidPassthroughRequest_t; + + +/* SCSI IO RAID Passthrough reply structure */ + +typedef struct _MSG_SCSI_IO_RAID_PT_REPLY +{ + U8 PhysDiskNum; /* 00h */ + U8 Reserved1; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 SCSIStatus; /* 0Ch */ + U8 SCSIState; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TransferCount; /* 14h */ + U32 SenseCount; /* 18h */ + U32 ResponseInfo; /* 1Ch */ +} MSG_SCSI_IO_RAID_PT_REPLY, MPI_POINTER PTR_MSG_SCSI_IO_RAID_PT_REPLY, + SCSIIORaidPassthroughReply_t, MPI_POINTER pSCSIIORaidPassthroughReply_t; + + +/****************************************************************************/ +/* Mailbox reqeust structure */ +/****************************************************************************/ + +typedef struct _MSG_MAILBOX_REQUEST +{ + U16 Reserved1; + U8 ChainOffset; + U8 Function; + U16 Reserved2; + U8 Reserved3; + U8 MsgFlags; + U32 MsgContext; + U8 Command[10]; + U16 Reserved4; + SGE_IO_UNION SGL; +} MSG_MAILBOX_REQUEST, MPI_POINTER PTR_MSG_MAILBOX_REQUEST, + MailboxRequest_t, MPI_POINTER pMailboxRequest_t; + + +/* Mailbox reply structure */ +typedef struct _MSG_MAILBOX_REPLY +{ + U16 Reserved1; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 MailboxStatus; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 Reserved4; /* 14h */ +} MSG_MAILBOX_REPLY, MPI_POINTER PTR_MSG_MAILBOX_REPLY, + MailboxReply_t, MPI_POINTER pMailboxReply_t; + +#endif + + + diff --git a/source/lsi/mpi_sas.h b/source/lsi/mpi_sas.h new file mode 100755 index 0000000..1f0e63f --- /dev/null +++ b/source/lsi/mpi_sas.h @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2004-2008 LSI Corporation. + * + * + * Name: mpi_sas.h + * Title: MPI Serial Attached SCSI structures and definitions + * Creation Date: August 19, 2004 + * + * mpi_sas.h Version: 01.05.05 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 08-19-04 01.05.01 Original release. + * 08-30-05 01.05.02 Added DeviceInfo bit for SEP. + * Added PrimFlags and Primitive field to SAS IO Unit + * Control request, and added a new operation code. + * 03-27-06 01.05.03 Added Force Full Discovery, Transmit Port Select Signal, + * and Remove Device operations to SAS IO Unit Control. + * Added DevHandle field to SAS IO Unit Control request and + * reply. + * 10-11-06 01.05.04 Fixed the name of a define for Operation field of SAS IO + * Unit Control request. + * 01-15-08 01.05.05 Added support for MPI_SAS_OP_SET_IOC_PARAMETER, + * including adding IOCParameter and IOCParameter value + * fields to SAS IO Unit Control Request. + * Added MPI_SAS_DEVICE_INFO_PRODUCT_SPECIFIC define. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_SAS_H +#define MPI_SAS_H + + +/* + * Values for SASStatus. + */ +#define MPI_SASSTATUS_SUCCESS (0x00) +#define MPI_SASSTATUS_UNKNOWN_ERROR (0x01) +#define MPI_SASSTATUS_INVALID_FRAME (0x02) +#define MPI_SASSTATUS_UTC_BAD_DEST (0x03) +#define MPI_SASSTATUS_UTC_BREAK_RECEIVED (0x04) +#define MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05) +#define MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06) +#define MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07) +#define MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08) +#define MPI_SASSTATUS_UTC_WRONG_DESTINATION (0x09) +#define MPI_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A) +#define MPI_SASSTATUS_LONG_INFORMATION_UNIT (0x0B) +#define MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C) +#define MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D) +#define MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E) +#define MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F) +#define MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10) +#define MPI_SASSTATUS_DATA_OFFSET_ERROR (0x11) +#define MPI_SASSTATUS_SDSF_NAK_RECEIVED (0x12) +#define MPI_SASSTATUS_SDSF_CONNECTION_FAILED (0x13) +#define MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14) + + +/* + * Values for the SAS DeviceInfo field used in SAS Device Status Change Event + * data and SAS IO Unit Configuration pages. + */ +#define MPI_SAS_DEVICE_INFO_PRODUCT_SPECIFIC (0xF0000000) + +#define MPI_SAS_DEVICE_INFO_SEP (0x00004000) +#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) +#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) +#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) +#define MPI_SAS_DEVICE_INFO_SSP_TARGET (0x00000400) +#define MPI_SAS_DEVICE_INFO_STP_TARGET (0x00000200) +#define MPI_SAS_DEVICE_INFO_SMP_TARGET (0x00000100) +#define MPI_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080) +#define MPI_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040) +#define MPI_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020) +#define MPI_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010) +#define MPI_SAS_DEVICE_INFO_SATA_HOST (0x00000008) + +#define MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007) +#define MPI_SAS_DEVICE_INFO_NO_DEVICE (0x00000000) +#define MPI_SAS_DEVICE_INFO_END_DEVICE (0x00000001) +#define MPI_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002) +#define MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003) + + + +/***************************************************************************** +* +* S e r i a l A t t a c h e d S C S I M e s s a g e s +* +*****************************************************************************/ + +/****************************************************************************/ +/* Serial Management Protocol Passthrough Request */ +/****************************************************************************/ + +typedef struct _MSG_SMP_PASSTHROUGH_REQUEST +{ + U8 PassthroughFlags; /* 00h */ + U8 PhysicalPort; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 RequestDataLength; /* 04h */ + U8 ConnectionRate; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved1; /* 0Ch */ + U64 SASAddress; /* 10h */ + U32 Reserved2; /* 18h */ + U32 Reserved3; /* 1Ch */ + SGE_SIMPLE_UNION SGL; /* 20h */ +} MSG_SMP_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REQUEST, + SmpPassthroughRequest_t, MPI_POINTER pSmpPassthroughRequest_t; + +/* values for PassthroughFlags field */ +#define MPI_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80) + +/* values for ConnectionRate field */ +#define MPI_SMP_PT_REQ_CONNECT_RATE_NEGOTIATED (0x00) +#define MPI_SMP_PT_REQ_CONNECT_RATE_1_5 (0x08) +#define MPI_SMP_PT_REQ_CONNECT_RATE_3_0 (0x09) + + +/* Serial Management Protocol Passthrough Reply */ +typedef struct _MSG_SMP_PASSTHROUGH_REPLY +{ + U8 PassthroughFlags; /* 00h */ + U8 PhysicalPort; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 ResponseDataLength; /* 04h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2; /* 0Ch */ + U8 SASStatus; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 Reserved3; /* 14h */ + U8 ResponseData[4]; /* 18h */ +} MSG_SMP_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REPLY, + SmpPassthroughReply_t, MPI_POINTER pSmpPassthroughReply_t; + +#define MPI_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80) + + +/****************************************************************************/ +/* SATA Passthrough Request */ +/****************************************************************************/ + +typedef struct _MSG_SATA_PASSTHROUGH_REQUEST +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 PassthroughFlags; /* 04h */ + U8 ConnectionRate; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved1; /* 0Ch */ + U32 Reserved2; /* 10h */ + U32 Reserved3; /* 14h */ + U32 DataLength; /* 18h */ + U8 CommandFIS[20]; /* 1Ch */ + SGE_SIMPLE_UNION SGL; /* 30h */ +} MSG_SATA_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SATA_PASSTHROUGH_REQUEST, + SataPassthroughRequest_t, MPI_POINTER pSataPassthroughRequest_t; + +/* values for PassthroughFlags field */ +#define MPI_SATA_PT_REQ_PT_FLAGS_RESET_DEVICE (0x0200) +#define MPI_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100) +#define MPI_SATA_PT_REQ_PT_FLAGS_DMA_QUEUED (0x0080) +#define MPI_SATA_PT_REQ_PT_FLAGS_PACKET_COMMAND (0x0040) +#define MPI_SATA_PT_REQ_PT_FLAGS_DMA (0x0020) +#define MPI_SATA_PT_REQ_PT_FLAGS_PIO (0x0010) +#define MPI_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004) +#define MPI_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002) +#define MPI_SATA_PT_REQ_PT_FLAGS_READ (0x0001) + +/* values for ConnectionRate field */ +#define MPI_SATA_PT_REQ_CONNECT_RATE_NEGOTIATED (0x00) +#define MPI_SATA_PT_REQ_CONNECT_RATE_1_5 (0x08) +#define MPI_SATA_PT_REQ_CONNECT_RATE_3_0 (0x09) + + +/* SATA Passthrough Reply */ +typedef struct _MSG_SATA_PASSTHROUGH_REPLY +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 PassthroughFlags; /* 04h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2; /* 0Ch */ + U8 SASStatus; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U8 StatusFIS[20]; /* 14h */ + U32 StatusControlRegisters; /* 28h */ + U32 TransferCount; /* 2Ch */ +} MSG_SATA_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SATA_PASSTHROUGH_REPLY, + SataPassthroughReply_t, MPI_POINTER pSataPassthroughReply_t; + + + + +/****************************************************************************/ +/* SAS IO Unit Control Request */ +/****************************************************************************/ + +typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST +{ + U8 Operation; /* 00h */ + U8 Reserved1; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 DevHandle; /* 04h */ + U8 IOCParameter; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 TargetID; /* 0Ch */ + U8 Bus; /* 0Dh */ + U8 PhyNum; /* 0Eh */ + U8 PrimFlags; /* 0Fh */ + U32 Primitive; /* 10h */ + U64 SASAddress; /* 14h */ + U32 IOCParameterValue; /* 1Ch */ +} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST, + SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t; + +/* values for the Operation field */ +#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01) +#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) +#define MPI_SAS_OP_PHY_LINK_RESET (0x06) +#define MPI_SAS_OP_PHY_HARD_RESET (0x07) +#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) +#define MPI_SAS_OP_MAP_CURRENT (0x09) +#define MPI_SAS_OP_SEND_PRIMITIVE (0x0A) +#define MPI_SAS_OP_FORCE_FULL_DISCOVERY (0x0B) +#define MPI_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C) +#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE (0x0D) /* obsolete name */ +#define MPI_SAS_OP_REMOVE_DEVICE (0x0D) +#define MPI_SAS_OP_SET_IOC_PARAMETER (0x0E) +#define MPI_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80) + +/* values for the PrimFlags field */ +#define MPI_SAS_PRIMFLAGS_SINGLE (0x08) +#define MPI_SAS_PRIMFLAGS_TRIPLE (0x02) +#define MPI_SAS_PRIMFLAGS_REDUNDANT (0x01) + + +/* SAS IO Unit Control Reply */ +typedef struct _MSG_SAS_IOUNIT_CONTROL_REPLY +{ + U8 Operation; /* 00h */ + U8 Reserved1; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 DevHandle; /* 04h */ + U8 IOCParameter; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved4; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_SAS_IOUNIT_CONTROL_REPLY, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REPLY, + SasIoUnitControlReply_t, MPI_POINTER pSasIoUnitControlReply_t; + +#endif + + diff --git a/source/lsi/mpi_tool.h b/source/lsi/mpi_tool.h new file mode 100755 index 0000000..1d8e37b --- /dev/null +++ b/source/lsi/mpi_tool.h @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2001-2008 LSI Corporation. + * + * + * Name: mpi_tool.h + * Title: MPI Toolbox structures and definitions + * Creation Date: July 30, 2001 + * + * mpi_tool.h Version: 01.05.03 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 08-08-01 01.02.01 Original release. + * 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines. + * 01-16-04 01.02.03 Added defines and structures for new tools + *. MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL and + * MPI_TOOLBOX_FC_MANAGEMENT_TOOL. + * 04-29-04 01.02.04 Added message structures for Diagnostic Buffer Post and + * Diagnostic Release requests and replies. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. + * 10-06-04 01.05.02 Added define for MPI_DIAG_BUF_TYPE_COUNT. + * 02-09-05 01.05.03 Added frame size option to FC management tool. + * Added Beacon tool to the Toolbox. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_TOOL_H +#define MPI_TOOL_H + +#define MPI_TOOLBOX_CLEAN_TOOL (0x00) +#define MPI_TOOLBOX_MEMORY_MOVE_TOOL (0x01) +#define MPI_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02) +#define MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03) +#define MPI_TOOLBOX_FC_MANAGEMENT_TOOL (0x04) +#define MPI_TOOLBOX_BEACON_TOOL (0x05) + + +/****************************************************************************/ +/* Toolbox reply */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_REPLY +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_TOOLBOX_REPLY, MPI_POINTER PTR_MSG_TOOLBOX_REPLY, + ToolboxReply_t, MPI_POINTER pToolboxReply_t; + + +/****************************************************************************/ +/* Toolbox Clean Tool request */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_CLEAN_REQUEST +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Flags; /* 0Ch */ +} MSG_TOOLBOX_CLEAN_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_CLEAN_REQUEST, + ToolboxCleanRequest_t, MPI_POINTER pToolboxCleanRequest_t; + +#define MPI_TOOLBOX_CLEAN_NVSRAM (0x00000001) +#define MPI_TOOLBOX_CLEAN_SEEPROM (0x00000002) +#define MPI_TOOLBOX_CLEAN_FLASH (0x00000004) +#define MPI_TOOLBOX_CLEAN_BOOTLOADER (0x04000000) +#define MPI_TOOLBOX_CLEAN_FW_BACKUP (0x08000000) +#define MPI_TOOLBOX_CLEAN_FW_CURRENT (0x10000000) +#define MPI_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000) +#define MPI_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000) +#define MPI_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000) + + +/****************************************************************************/ +/* Toolbox Memory Move request */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_MEM_MOVE_REQUEST +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + SGE_SIMPLE_UNION SGL; /* 0Ch */ +} MSG_TOOLBOX_MEM_MOVE_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_MEM_MOVE_REQUEST, + ToolboxMemMoveRequest_t, MPI_POINTER pToolboxMemMoveRequest_t; + + +/****************************************************************************/ +/* Toolbox Diagnostic Data Upload request */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Flags; /* 0Ch */ + U32 Reserved3; /* 10h */ + SGE_SIMPLE_UNION SGL; /* 14h */ +} MSG_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, + ToolboxDiagDataUploadRequest_t, MPI_POINTER pToolboxDiagDataUploadRequest_t; + +typedef struct _DIAG_DATA_UPLOAD_HEADER +{ + U32 DiagDataLength; /* 00h */ + U8 FormatCode; /* 04h */ + U8 Reserved; /* 05h */ + U16 Reserved1; /* 06h */ +} DIAG_DATA_UPLOAD_HEADER, MPI_POINTER PTR_DIAG_DATA_UPLOAD_HEADER, + DiagDataUploadHeader_t, MPI_POINTER pDiagDataUploadHeader_t; + +#define MPI_TB_DIAG_FORMAT_SCSI_PRINTF_1 (0x01) +#define MPI_TB_DIAG_FORMAT_SCSI_2 (0x02) +#define MPI_TB_DIAG_FORMAT_SCSI_3 (0x03) +#define MPI_TB_DIAG_FORMAT_FC_TRACE_1 (0x04) + + +/****************************************************************************/ +/* Toolbox ISTWI Read Write request */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_ISTWI_READ_WRITE_REQUEST +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Flags; /* 0Ch */ + U8 BusNum; /* 0Dh */ + U16 Reserved3; /* 0Eh */ + U8 NumAddressBytes; /* 10h */ + U8 Reserved4; /* 11h */ + U16 DataLength; /* 12h */ + U8 DeviceAddr; /* 14h */ + U8 Addr1; /* 15h */ + U8 Addr2; /* 16h */ + U8 Addr3; /* 17h */ + U32 Reserved5; /* 18h */ + SGE_SIMPLE_UNION SGL; /* 1Ch */ +} MSG_TOOLBOX_ISTWI_READ_WRITE_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_ISTWI_READ_WRITE_REQUEST, + ToolboxIstwiReadWriteRequest_t, MPI_POINTER pToolboxIstwiReadWriteRequest_t; + +#define MPI_TB_ISTWI_FLAGS_WRITE (0x00) +#define MPI_TB_ISTWI_FLAGS_READ (0x01) + + +/****************************************************************************/ +/* Toolbox FC Management request */ +/****************************************************************************/ + +/* ActionInfo for Bus and TargetId */ +typedef struct _MPI_TB_FC_MANAGE_BUS_TID_AI +{ + U16 Reserved; /* 00h */ + U8 Bus; /* 02h */ + U8 TargetId; /* 03h */ +} MPI_TB_FC_MANAGE_BUS_TID_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_BUS_TID_AI, + MpiTbFcManageBusTidAi_t, MPI_POINTER pMpiTbFcManageBusTidAi_t; + +/* ActionInfo for port identifier */ +typedef struct _MPI_TB_FC_MANAGE_PID_AI +{ + U32 PortIdentifier; /* 00h */ +} MPI_TB_FC_MANAGE_PID_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_PID_AI, + MpiTbFcManagePidAi_t, MPI_POINTER pMpiTbFcManagePidAi_t; + +/* ActionInfo for set max frame size */ +typedef struct _MPI_TB_FC_MANAGE_FRAME_SIZE_AI +{ + U16 FrameSize; /* 00h */ + U8 PortNum; /* 02h */ + U8 Reserved1; /* 03h */ +} MPI_TB_FC_MANAGE_FRAME_SIZE_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_FRAME_SIZE_AI, + MpiTbFcManageFrameSizeAi_t, MPI_POINTER pMpiTbFcManageFrameSizeAi_t; + +/* ActionInfo for set login parameters */ +typedef struct _MPI_TB_FC_MANAGE_LOGIN_PARAMS_AI +{ + U8 Count; /* 00h */ + U8 Period; /* 01h */ + U8 PortNum; /* 02h */ + U8 Reserved1; /* 03h */ + U8 FlogiBurst; /* 04h */ + U8 FlogiExchanges; /* 05h */ + U8 PlogiBurst; /* 06h */ + U8 PlogiExchanges; /* 07h */ +} MPI_TB_FC_MANAGE_LOGIN_PARAMS_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_LOGIN_PARAMS_AI, + MpiTbFcManageLoginParamsAi_t, MPI_POINTER pMpiTbFcManageLoginParamsAi_t; + +/* ActionInfo for create virtual port */ +typedef struct _MPI_TB_FC_MANAGE_CREATE_VP_AI +{ + U32 PortIdentifier; /* 00h */ + U64 WWNN; /* 04h */ + U64 WWPN; /* 0Ch */ +} MPI_TB_FC_MANAGE_CREATE_VP_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_CREATE_VP_AI, + MpiTbFcManageCreateVpAi_t, MPI_POINTER pMpiTbFcManageCreateVp_t; + +/* union of ActionInfo */ +typedef union _MPI_TB_FC_MANAGE_AI_UNION +{ + MPI_TB_FC_MANAGE_BUS_TID_AI BusTid; + MPI_TB_FC_MANAGE_PID_AI Port; + MPI_TB_FC_MANAGE_FRAME_SIZE_AI FrameSize; + MPI_TB_FC_MANAGE_LOGIN_PARAMS_AI LoginParams; + MPI_TB_FC_MANAGE_CREATE_VP_AI CreateVp; +} MPI_TB_FC_MANAGE_AI_UNION, MPI_POINTER PTR_MPI_TB_FC_MANAGE_AI_UNION, + MpiTbFcManageAiUnion_t, MPI_POINTER pMpiTbFcManageAiUnion_t; + +typedef struct _MSG_TOOLBOX_FC_MANAGE_REQUEST +{ + U8 Tool; /* 00h */ + U8 AliasIndex; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Action; /* 0Ch */ + U8 Flags; /* 0Dh */ + U16 Reserved4; /* 0Eh */ + MPI_TB_FC_MANAGE_AI_UNION ActionInfo; /* 10h */ +} MSG_TOOLBOX_FC_MANAGE_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_FC_MANAGE_REQUEST, + ToolboxFcManageRequest_t, MPI_POINTER pToolboxFcManageRequest_t; + +/* defines for the Action field */ +#define MPI_TB_FC_MANAGE_ACTION_DISC_ALL (0x00) +#define MPI_TB_FC_MANAGE_ACTION_DISC_PID (0x01) +#define MPI_TB_FC_MANAGE_ACTION_DISC_BUS_TID (0x02) +#define MPI_TB_FC_MANAGE_ACTION_SET_MAX_FRAME_SIZE (0x03) +#define MPI_TB_FC_MANAGE_ACTION_LOGOUT_PID (0x04) +#define MPI_TB_FC_MANAGE_ACTION_LOGOUT_BUS_TID (0x05) +#define MPI_TB_FC_MANAGE_ACTION_SET_LOGIN_PARAMS (0x06) +#define MPI_TB_FC_MANAGE_ACTION_GET_LOGIN_PARAMS (0x07) +#define MPI_TB_FC_MANAGE_ACTION_CREATE_VP (0x08) +#define MPI_TB_FC_MANAGE_ACTION_DELETE_VP (0x09) + +/* defines for the Flags field */ +#define MPI_TB_FC_MANAGE_FLAGS_KEEP_LOGGED_OUT (0x01) +#define MPI_TB_FC_MANAGE_FLAGS_AUTO_RETRY (0x02) + +typedef struct _MSG_TOOLBOX_FC_MANAGE_REPLY +{ + U8 Tool; /* 00h */ + U8 AliasIndex; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 Reserved4[3]; /* 14h */ + MPI_TB_FC_MANAGE_AI_UNION ActionInfo; /* 20h */ +} MSG_TOOLBOX_FC_MANAGE_REPLY, MPI_POINTER PTR_MSG_TOOLBOX_FC_MANAGE_REPLY, + ToolboxFcManageReply_t, MPI_POINTER pToolboxFcManageReply_t; + + +/****************************************************************************/ +/* Toolbox Beacon Tool request */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_BEACON_REQUEST +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 ConnectNum; /* 0Ch */ + U8 PortNum; /* 0Dh */ + U8 Reserved3; /* 0Eh */ + U8 Flags; /* 0Fh */ +} MSG_TOOLBOX_BEACON_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_BEACON_REQUEST, + ToolboxBeaconRequest_t, MPI_POINTER pToolboxBeaconRequest_t; + +#define MPI_TOOLBOX_FLAGS_BEACON_MODE_OFF (0x00) +#define MPI_TOOLBOX_FLAGS_BEACON_MODE_ON (0x01) + + +/****************************************************************************/ +/* Diagnostic Buffer Post request */ +/****************************************************************************/ + +typedef struct _MSG_DIAG_BUFFER_POST_REQUEST +{ + U8 TraceLevel; /* 00h */ + U8 BufferType; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 ExtendedType; /* 0Ch */ + U32 BufferLength; /* 10h */ + U32 ProductSpecific[4]; /* 14h */ + U32 Reserved3; /* 24h */ + U64 BufferAddress; /* 28h */ +} MSG_DIAG_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_DIAG_BUFFER_POST_REQUEST, + DiagBufferPostRequest_t, MPI_POINTER pDiagBufferPostRequest_t; + +#define MPI_DIAG_BUF_TYPE_TRACE (0x00) +#define MPI_DIAG_BUF_TYPE_SNAPSHOT (0x01) +#define MPI_DIAG_BUF_TYPE_EXTENDED (0x02) +/* count of the number of buffer types */ +#define MPI_DIAG_BUF_TYPE_COUNT (0x03) + +#define MPI_DIAG_EXTENDED_QTAG (0x00000001) + + +/* Diagnostic Buffer Post reply */ +typedef struct _MSG_DIAG_BUFFER_POST_REPLY +{ + U8 Reserved1; /* 00h */ + U8 BufferType; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved4; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TransferLength; /* 14h */ +} MSG_DIAG_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_DIAG_BUFFER_POST_REPLY, + DiagBufferPostReply_t, MPI_POINTER pDiagBufferPostReply_t; + + +/****************************************************************************/ +/* Diagnostic Release request */ +/****************************************************************************/ + +typedef struct _MSG_DIAG_RELEASE_REQUEST +{ + U8 Reserved1; /* 00h */ + U8 BufferType; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ +} MSG_DIAG_RELEASE_REQUEST, MPI_POINTER PTR_MSG_DIAG_RELEASE_REQUEST, + DiagReleaseRequest_t, MPI_POINTER pDiagReleaseRequest_t; + + +/* Diagnostic Release reply */ +typedef struct _MSG_DIAG_RELEASE_REPLY +{ + U8 Reserved1; /* 00h */ + U8 BufferType; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved4; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_DIAG_RELEASE_REPLY, MPI_POINTER PTR_MSG_DIAG_RELEASE_REPLY, + DiagReleaseReply_t, MPI_POINTER pDiagReleaseReply_t; + + +#endif + + diff --git a/source/lsi/mpi_type.h b/source/lsi/mpi_type.h new file mode 100755 index 0000000..6e71c00 --- /dev/null +++ b/source/lsi/mpi_type.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2000-2008 LSI Corporation. + * + * + * Name: mpi_type.h + * Title: MPI Basic type definitions + * Creation Date: June 6, 2000 + * + * mpi_type.h Version: 01.05.02 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. + * 06-06-00 01.00.01 Update version number for 1.0 release. + * 11-02-00 01.01.01 Original release for post 1.0 work + * 02-20-01 01.01.02 Added define and ifdef for MPI_POINTER. + * 08-08-01 01.02.01 Original release for v1.2 work. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. + * 08-30-05 01.05.02 Added PowerPC option to #ifdef's. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_TYPE_H +#define MPI_TYPE_H + + +/******************************************************************************* + * Define MPI_POINTER if it hasn't already been defined. By default MPI_POINTER + * is defined to be a near pointer. MPI_POINTER can be defined as a far pointer + * by defining MPI_POINTER as "far *" before this header file is included. + */ +#ifndef MPI_POINTER +#define MPI_POINTER * +#endif + + +/***************************************************************************** +* +* B a s i c T y p e s +* +*****************************************************************************/ + +typedef signed char S8; +typedef unsigned char U8; +typedef signed short S16; +typedef unsigned short U16; + + +#if defined(unix) || defined(__arm) || defined(ALPHA) || defined(__PPC__) || defined(__ppc) + + typedef signed int S32; + typedef unsigned int U32; + +#else + + typedef signed long S32; + typedef unsigned long U32; + +#endif + + +typedef struct _S64 +{ + U32 Low; + S32 High; +} S64; + +typedef struct _U64 +{ + U32 Low; + U32 High; +} U64; + + +/****************************************************************************/ +/* Pointers */ +/****************************************************************************/ + +typedef S8 *PS8; +typedef U8 *PU8; +typedef S16 *PS16; +typedef U16 *PU16; +typedef S32 *PS32; +typedef U32 *PU32; +typedef S64 *PS64; +typedef U64 *PU64; + + +#endif + diff --git a/source/lsiutil.c b/source/lsiutil.c new file mode 100755 index 0000000..04f6c8b --- /dev/null +++ b/source/lsiutil.c @@ -0,0 +1,43217 @@ +/*************************************************************************** + * * + * Copyright (c) 2002-2013 LSI Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Corporation. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Corporation. * + * * + *************************************************************************** + * LSIUtil -- configuration utility for MPT adapters (FC, SCSI, and SAS/SATA) + * + * Written by Stephen F. Shirron, October 11, 2002 +*/ + +#define LSIUTIL_VERSION "Version 1.72, Sep 09, 2014" + + +char what[] = "@(#)LSI Logic MPT Configuration Utility, " LSIUTIL_VERSION; + +/* SAS3108 FPGA-specific defines*/ +#define SAS3108_FPGA_WORKAROUND (1) +#define SAS3108_FPGA_VENDORID (0x702) + + +#ifndef MAX_DEVICES +#define MAX_DEVICES 99 +#endif + + +#ifndef REGISTER_ACCESS +#define REGISTER_ACCESS 1 +#endif + + +#ifndef VERIFY_ENDIANNESS +#define VERIFY_ENDIANNESS 0 +#endif + + +#if !EFI +#include +#if WIN32 +#include +#else +#define _cdecl +#endif +#include +#include +#include +#include +#include +#include +#if WIN32 +#include +#include "inc/devioctl.h" +#include +#include +#ifdef _CONSOLE +#pragma warning(disable:4242) +#include "inc/getopt.h" +#define sleep(x) _sleep(x*1000) +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#if !_WIN64 +typedef unsigned long ULONG_PTR; +#endif +#define stricmp _stricmp +#define strnicmp _strnicmp +#define open _open +#define close _close +#define read _read +#define write _write +#define stat _stat +#define fstat _fstat +#define INT64_FMT "I64" +#else +#define INT64_FMT "ll" +#include +#include +int optopt; +int optind; +#endif +#define strcasecmp stricmp +#define strncasecmp strnicmp +#include "inc/ntddscsi.h" +/* MINGW is a little different from the DDK */ +#if __MINGW32__ +#define offsetof(type,member) ((size_t)&((type *)0)->member) +#define sleep(x) Sleep(x*1000) +#endif +#endif +#if __linux__ || __sparc__ || __irix__ || __alpha__ +#include +#include +#include +#include +#include +#include +#include +#define FALSE 0 +#define TRUE 1 +typedef int HANDLE; +#define O_BINARY 0 +#define min(x,y) ((int)(x) < (int)(y) ? (x) : (y)) +#define max(x,y) ((int)(x) > (int)(y) ? (x) : (y)) +#define INT64_FMT "ll" +#endif +#if __linux__ +#include +#ifndef offsetof +#define offsetof(type,member) ((size_t)&((type *)0)->member) +#endif +#define TotalBufferSize DataSize +#define DataBuffer DiagnosticData +#include +#if i386 +#include +#endif +#define LINUX_MOD_DEVICETABLE_H +#include +#include +#define REG_IO_READ 1 +#define REG_IO_WRITE 2 +#define REG_MEM_READ 3 +#define REG_MEM_WRITE 4 +#define REG_DIAG_READ 5 +#define REG_DIAG_WRITE 6 +#define REG_DIAG_WRITE_BYTE 7 +#endif +#if __sparc__ +#include +#include +#include +#include +typedef struct +{ + caddr_t client; + caddr_t phci; + caddr_t addr; + uint_t buf_elem; + void *ret_buf; + uint_t *ret_elem; +} sv_iocdata_t; +#define SCSI_VHCI_GET_CLIENT_NAME (('x' << 8) + 0x03) +#define NAME_MAX MAXNAMLEN +#define getmajor(x) (((x)>>NBITSMINOR)&MAXMAJ) +#define getminor(x) ((x)&MAXMIN) +#define MINOR2INST(x) ((x)>>6) +#endif +#if DOS +#include +#include +#include +#include +#include +#include +#include +#include "inc/getopt.h" +#define FALSE 0 +#define TRUE 1 +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef unsigned int PHYSICAL_ADDRESS; +typedef unsigned int mpt_bus_addr_t; +typedef struct mpt_adap *HANDLE; +#define strcasecmp stricmp +#define strncasecmp strnicmp +#define DELAY(n) mpt_delay(adap, n) +#define REG_IO_READ 1 +#define REG_IO_WRITE 2 +#define REG_MEM_READ 3 +#define REG_MEM_WRITE 4 +#define REG_DIAG_READ 5 +#define REG_DIAG_WRITE 6 +#define REG_DIAG_WRITE_BYTE 7 +#define INT64_FMT "I64" +#endif +#endif +#if EFI +#if EFIEBC +#pragma warning(disable:175) +#endif +#define _cdecl +#include "helper.h" +#include "getopt.h" +#define O_BINARY 0 +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef EFI_PHYSICAL_ADDRESS mpt_bus_addr_t; +typedef struct mpt_adap *HANDLE; +#define min(x,y) ((int)(x) < (int)(y) ? (x) : (y)) +#define max(x,y) ((int)(x) > (int)(y) ? (x) : (y)) +#define DELAY(n) mpt_delay(adap, n) +#define REG_IO_READ 1 +#define REG_IO_WRITE 2 +#define REG_MEM_READ 3 +#define REG_MEM_WRITE 4 +#define REG_DIAG_READ 5 +#define REG_DIAG_WRITE 6 +#define REG_DIAG_WRITE_BYTE 7 +#define INT64_FMT "ll" +extern EFI_HANDLE gImageHandle; +extern EFI_LOADED_IMAGE *gLoadedImage; +#endif +#if DOS || EFI +#define CHUNK_SIZE 0x10000 +#else +#define CHUNK_SIZE 0x4000 +#endif + + +typedef unsigned char U8; +typedef unsigned short U16; +typedef unsigned int U32; +typedef struct { U32 Low; U32 High; } U64; +#define MPI_POINTER * +#define MPI2_POINTER * + + +#if VERIFY_ENDIANNESS +typedef U16 * _U16; +typedef U32 * _U32; +typedef struct { _U32 Low; _U32 High; } _U64; +#else +typedef U16 _U16; +typedef U32 _U32; +typedef U64 _U64; +#endif + + +#if VERIFY_ENDIANNESS +#define U16 _U16 +#define U32 _U32 +#define U64 _U64 +#endif +#if WIN32 || __linux__ || __sparc__ || DOS || EFI +#pragma pack(1) +#include "lsi/mpi.h" +#include "lsi/mpi_ioc.h" +#include "lsi/mpi_cnfg.h" +#include "lsi/mpi_init.h" +#include "lsi/mpi_fc.h" +#include "lsi/mpi_sas.h" +#include "lsi/mpi_raid.h" +#include "lsi/mpi_tool.h" +#include "lsi/mpi2.h" +#include "lsi/mpi2_ioc.h" +#include "lsi/mpi2_cnfg.h" +#include "lsi/mpi2_init.h" +#include "lsi/mpi2_sas.h" +#include "lsi/mpi2_raid.h" +#include "lsi/mpi2_tool.h" +#pragma pack() +#endif +#if VERIFY_ENDIANNESS +#undef U16 +#undef U32 +#undef U64 +#endif + + +#if WIN32 +#include "inc/sym_dmi.h" +#define ISSUE_BUS_RESET 0x800000FF +typedef struct +{ + SRB_IO_CONTROL Sic; + UCHAR Buf[8+128+1024]; +} SRB_BUFFER; +typedef struct +{ + SRB_IO_CONTROL Sic; + ULONG DiagType; + UCHAR PageVersion[4]; + UCHAR Buf[64+32768]; +} SRB_DIAG_BUFFER; +#endif +#if __linux__ +#ifndef __user +#define __user +#endif +typedef unsigned long long uint64_t; +typedef U8 u8; +typedef U16 u16; +typedef U32 u32; +#include "inc/mptctl.h" +typedef U8 uint8_t; +typedef U16 uint16_t; +typedef U32 uint32_t; +#include "inc/mpt2sas_ctl.h" +#define IOCTL_NAME "/dev/" MPT_MISCDEV_BASENAME +#define IOCTL_NAME2 "/dev/" MPT2SAS_DEV_NAME +#define IOCTL_NAME3 "/dev/mpt3ctl" +#ifdef MPI_FW_DIAG_IOCTL +#define LINUX_DIAG 1 +typedef struct +{ + struct mpt2_ioctl_header hdr; + unsigned char buf[64+32768]; +} IOCTL_DIAG_BUFFER; +#endif +#endif +#if __sparc__ +#define TARGET_MPTx +typedef uint8_t UINT8; +typedef uint16_t UINT16; +typedef uint32_t UINT32; +typedef uint64_t UINT64; +#include "inc/dmi_ioctl.h" +#include "inc/mptsas_ioctl.h" +#endif +#if __irix__ +#define MPI_POINTER * +typedef uint8_t U8; +typedef uint16_t U16; +typedef uint32_t U32; +typedef struct +{ + U32 Low; + U32 High; +} mpiU64; +#pragma pack(1) +#define U64 mpiU64 +#include "mpi.h" +#include "mpi_ioc.h" +#include "mpi_cnfg.h" +#include "mpi_init.h" +#include "mpi_fc.h" +#include "mpi_sas.h" +#include "mpi_raid.h" +#include "mpi_tool.h" +#pragma pack(0) +#undef U64 +#define TARGET_MPT +typedef uint8_t UINT8; +typedef uint16_t UINT16; +typedef uint32_t UINT32; +typedef uint64_t UINT64; +#include "dmi_ioctl.h" +#include +#endif +#if __alpha__ +typedef unsigned __int64 uint64_t; +#define MPI_POINTER * +typedef unsigned char U8; +typedef unsigned short U16; +typedef unsigned int U32; +typedef unsigned long U64; +typedef struct +{ + U32 Low; + U32 High; +} mpiU64; +#pragma pack(1) +#define U64 mpiU64 +#include "mpi.h" +#include "mpi_ioc.h" +#include "mpi_cnfg.h" +#include "mpi_init.h" +#include "mpi_fc.h" +#include "mpi_sas.h" +#include "mpi_raid.h" +#include "mpi_tool.h" +#pragma pack(0) +#undef U64 +typedef U8 u8; +typedef U16 u16; +typedef U32 u32; +typedef U64 u64; +#include "mptctl.h" +#endif +#if DOS +#include "pcidefs.h" +#include "pcilib.h" +#include "dpmilib.h" +#endif + + +#if !VERIFY_ENDIANNESS +#define printf printfPaged +#define fprintf fprintfPaged +#endif + + +#undef __LSIUTIL_BIG_ENDIAN__ +#define swap16(x) \ + ((((U16)(x)>>8)&0xff) | \ + (((U16)(x)&0xff)<<8)) +#define swap32(x) \ + ((((U32)(x)>>24)&0xff) | \ + ((((U32)(x)>>16)&0xff)<<8) | \ + ((((U32)(x)>>8)&0xff)<<16) | \ + (((U32)(x)&0xff)<<24)) +#if WIN32 || __alpha__ || DOS || EFI +#define get16(x) (x) +#define get32(x) (x) +#define set16(x) (x) +#define set32(x) (x) +#define get16x(x) (x) +#define get32x(x) (x) +#define set16x(x) (x) +#define set32x(x) (x) +#define get16x_be(x) swap16(x) +#define get32x_be(x) swap32(x) +#define set16x_be(x) swap16(x) +#define set32x_be(x) swap32(x) +#endif +#if __linux__ +#include +#include +#if __BYTE_ORDER == __BIG_ENDIAN +#include +#define __LSIUTIL_BIG_ENDIAN__ 1 +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN +#include +#endif +#define get16(x) __le16_to_cpu(x) +#define get32(x) __le32_to_cpu(x) +#define set16(x) __cpu_to_le16(x) +#define set32(x) __cpu_to_le32(x) +#define get16x(x) __le16_to_cpu(x) +#define get32x(x) __le32_to_cpu(x) +#define set16x(x) __cpu_to_le16(x) +#define set32x(x) __cpu_to_le32(x) +#define get16x_be(x) __be16_to_cpu(x) +#define get32x_be(x) __be32_to_cpu(x) +#define set16x_be(x) __cpu_to_be16(x) +#define set32x_be(x) __cpu_to_be32(x) +#endif +#if __sparc__ || __irix__ +#if i386 +#define get16(x) (x) +#define get32(x) (x) +#define set16(x) (x) +#define set32(x) (x) +#define get16x(x) (x) +#define get32x(x) (x) +#define set16x(x) (x) +#define set32x(x) (x) +#define get16x_be(x) swap16(x) +#define get32x_be(x) swap32(x) +#define set16x_be(x) swap16(x) +#define set32x_be(x) swap32(x) +#else +#define get16(x) swap16(x) +#define get32(x) swap32(x) +#define set16(x) swap16(x) +#define set32(x) swap32(x) +#define get16x(x) swap16(x) +#define get32x(x) swap32(x) +#define set16x(x) swap16(x) +#define set32x(x) swap32(x) +#define get16x_be(x) (x) +#define get32x_be(x) (x) +#define set16x_be(x) (x) +#define set32x_be(x) (x) +#define __LSIUTIL_BIG_ENDIAN__ 1 +#endif +#endif +#define get64(x) (((uint64_t)get32x(((U32 *)&(x))[1])<<32) | get32x(((U32 *)&(x))[0])) +#define get64x(x) (((uint64_t)get32x(((U32 *)&(x))[1])<<32) | get32x(((U32 *)&(x))[0])) + + +/* These need to be included after the __LSIUTIL_BIG_ENDIAN__ define as they rely on it */ +#include "inc/ata.h" +#include "inc/sas.h" + + +#if VERIFY_ENDIANNESS +#undef get16 +#undef get32 +#undef set16 +#undef set32 +U16 get16(U16 *x) { return 0; } +U32 get32(U32 *x) { return 0; } +U16 *set16(int x) { return NULL; } +U32 *set32(int x) { return NULL; } +#endif + + +#define get2bytes(x, y) (((x[y] << 8) + x[y+1]) & 0xffff) +#define get3bytes(x, y) (((x[y] << 16) + (x[y+1] << 8) + x[y+2]) & 0xffffff) +#define get4bytes(x, y) (((x[y] << 24) + (x[y+1] << 16) + (x[y+2] << 8) + x[y+3]) & 0xffffffff) +#define get8bytes(x, y) (((uint64_t)get4bytes(x, y) << 32) + get4bytes(x, y+4)) +#define put2bytes(x, y, z) \ + x[y] = (U8)((z) >> 8); \ + x[y+1] = (U8)(z) +#define put3bytes(x, y, z) \ + x[y] = (U8)((z) >> 16); \ + x[y+1] = (U8)((z) >> 8); \ + x[y+2] = (U8)(z) +#define put4bytes(x, y, z) \ + x[y] = (U8)((z) >> 24); \ + x[y+1] = (U8)((z) >> 16); \ + x[y+2] = (U8)((z) >> 8); \ + x[y+3] = (U8)(z) + + +#if REGISTER_ACCESS +#define readl(addr, data) \ + { \ + U32 temp; \ + if (doReadRegister(port, MPI_##addr##_OFFSET, &temp) != 1) \ + { \ + printf("Failed to read register!\n"); \ + return 0; \ + } \ + data = temp; \ + } + + +#define writel(addr, data) \ + { \ + U32 temp = data; \ + if (doWriteRegister(port, MPI_##addr##_OFFSET, &temp) != 1) \ + { \ + printf("Failed to write register!\n"); \ + return 0; \ + } \ + } +#endif + + +#define IO_TIME 20 +#define RESET_TIME 60 +#define SHORT_TIME 10 +#define LONG_TIME 120 + + +#define BOBCAT_FW_HEADER_SIGNATURE_0 ( 0xB0EABCA7 ) +#define BOBCAT_FW_HEADER_SIGNATURE_1 ( 0xB0BCEAA7 ) +#define BOBCAT_FW_HEADER_SIGNATURE_2 ( 0xB0BCA7EA ) + +#define COBRA_FW_HEADER_SIGNATURE_0 ( 0xC0EABAA0 ) +#define COBRA_FW_HEADER_SIGNATURE_1 ( 0xC0BAEAA0 ) +#define COBRA_FW_HEADER_SIGNATURE_2 ( 0xC0BAA0EA ) + + +#define ALLOCATED_RESP_LEN 0xff + + +#if DEBUG_MALLOC_FREE + +int my_mallocs; +int my_frees; + + +int _cdecl main(int argc, char *argv[]) +{ + int t; + int _cdecl my_main(int argc, char *argv[]); + + my_mallocs = 0; + my_frees = 0; + + t = my_main(argc, argv); + + if (my_mallocs != my_frees) + printf("mallocs = %d, frees = %d\n", my_mallocs, my_frees); + + return t; +} + + +void *my_malloc(size_t x) +{ + my_mallocs++; + return malloc(x); +} + + +void my_free(void *x) +{ + my_frees++; + free(x); +} + + +#define main my_main +#define malloc my_malloc +#define free my_free + +#endif + + +#define NUM_PORTS 64 + + +typedef struct +{ + U8 signature[4]; + _U16 vendorId; + _U16 deviceId; + U8 reserved1[2]; + _U16 pcirLength; + U8 pcirRevision; + U8 classCode[3]; + _U16 imageLength; + _U16 imageRevision; + U8 type; + U8 indicator; + U8 reserved2[2]; +} PCIR; + + +typedef struct +{ + int portNumber; + char portName[16]; +#if WIN32 + char driverName[32]; +#endif +#if __sparc__ + char pathName[PATH_MAX]; + U32 portPhyMap[32]; +#endif + HANDLE fileHandle; + int ioctlValue; + int iocNumber; + int hostNumber; + int mptVersion; + int fwVersion; + int whoInit; + U16 deviceIdRaw; + U16 deviceId; + U8 revisionId; + U16 productId; + int pidType; + U32 capabilities; + U8 flags; + U32 fwImageSize; + char *chipName; + char *chipNameRev; + char *pciType; + U32 seqCodeVersion; + int payOff; + int portType; + int maxPersistentIds; + int maxBuses; + int minTargets; + int maxTargets; + int maxLuns; + int maxDevHandle; + int numPhys; + int hostScsiId; + int protocolFlags; + int lastEvent; +#if LINUX_DIAG + int diagBufferSizes[MPI_DIAG_BUF_TYPE_COUNT]; +#endif +#if __linux__ + off_t ioPhys; + off_t memPhys; + U32 *memVirt; + off_t diagPhys; + U32 *diagVirt; +#endif + int notOperational; + int pciSegment; + int pciBus; + int pciDevice; + int pciFunction; + int raidPassthru; + int raidBus; + int raidTarget; + int raidPhysdisk; + int fastpathCapable; + U16 ioc_status; // Currently only updated during (get|set)ConfigPage() +} MPT_PORT; + + +typedef struct +{ + SCSIIOReply_t reply; + U8 sense[32]; +} SCSI_REPLY; + + +typedef struct +{ + Mpi2SCSIIOReply_t reply; + U8 sense[32]; +} SCSI_REPLY2; + + +typedef struct +{ + int slot; + int encl_id_l; + int encl_id_h; +} PATH; + + +typedef struct +{ + int bus; + int target; + int lun; + PATH path; + int mode; + unsigned int size; + uint64_t size64; + int eedp; +} DIAG_TARGET; + + +#define EXPANDER_TYPE_LSI_GEN1_YETI 1 +#define EXPANDER_TYPE_LSI_GEN1_X12 2 +#define EXPANDER_TYPE_LSI_GEN2_BOBCAT 3 +#define EXPANDER_TYPE_LSI_GEN3_COBRA 4 +#define EXPANDER_TYPE_3RD_PARTY 8 +#define EXPANDER_TYPE_UNKNOWN 9 + +typedef struct +{ + int bus; + int target; + int handle; + _U64 sas_address; + U8 physical_port; + int expanderType; +} EXP_TARGET; + + +typedef struct +{ + int type; + int number; + int data[2]; +} EVENT; + + +typedef struct +{ + int type; + int number; + int data[48]; +} EVENT2; + + +typedef struct +{ + _U32 Size; + _U32 DiagVersion; + U8 BufferType; + U8 Reserved[3]; + _U32 Reserved1; + _U32 Reserved2; + _U32 Reserved3; +} DIAG_BUFFER_START; + + +typedef struct +{ + _U32 Size; + _U16 Type; + U8 Version; + U8 Reserved; + _U32 CapabilitiesFlags; + _U32 FWVersion; + _U16 ProductId; + _U16 Reserved1; +} DIAG_HEADER_FIRM_IDENTIFICATION; + + +typedef struct +{ + _U32 Size; + _U16 Type; + U8 Version; + U8 Reserved; + U8 HostInfo[256]; +} DIAG_HEADER_HOST_IDENTIFICATION; + + +/* diag register for gen 2 */ +typedef struct _MPI2_FW_DIAG_REGISTER +{ + U8 Reserved; + U8 BufferType; + U16 AppFlags; + U32 DiagFlags; + U32 ProductSpecific[23]; + U32 RequestedBufferSize; + U32 UniqueId; +} MPI2_FW_DIAG_REGISTER, *PTR_MPI2_FW_DIAG_REGISTER; + + +/* diag query for gen 2 */ +typedef struct _MPI2_FW_DIAG_QUERY +{ + U8 Reserved; + U8 BufferType; + U16 AppFlags; + U32 DiagFlags; + U32 ProductSpecific[23]; + U32 TotalBufferSize; + U32 DriverAddedBufferSize; + U32 UniqueId; +} MPI2_FW_DIAG_QUERY, *PTR_MPI2_FW_DIAG_QUERY; + + +#if WIN32 +#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE +#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +typedef struct _STORAGE_ADAPTER_DESCRIPTOR { + ULONG Version; + ULONG Size; + ULONG MaximumTransferLength; + ULONG MaximumPhysicalPages; + ULONG AlignmentMask; + BOOLEAN AdapterUsesPio; + BOOLEAN AdapterScansDown; + BOOLEAN CommandQueueing; + BOOLEAN AcceleratedTransfer; + UCHAR BusType; + USHORT BusMajorVersion; + USHORT BusMinorVersion; +} STORAGE_ADAPTER_DESCRIPTOR, *PSTORAGE_ADAPTER_DESCRIPTOR; + + +typedef enum _STORAGE_PROPERTY_ID { + StorageDeviceProperty = 0, + StorageAdapterProperty, + StorageDeviceIdProperty, + StorageDeviceUniqueIdProperty, + StorageDeviceWriteCacheProperty, + StorageMiniportProperty, + StorageAccessAlignmentProperty, + StorageDeviceSeekPenaltyProperty, + StorageDeviceTrimProperty, + StorageDeviceWriteAggregationProperty +} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID; + + +typedef enum _STORAGE_QUERY_TYPE { + PropertyStandardQuery = 0, + PropertyExistsQuery, + PropertyMaskQuery, + PropertyQueryMaxDefined +} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE; + + +typedef struct _STORAGE_PROPERTY_QUERY { + STORAGE_PROPERTY_ID PropertyId; + STORAGE_QUERY_TYPE QueryType; + UCHAR AdditionalParameters[1]; +} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY; +#endif //WIN32 + + +MPT_PORT *mptPorts[NUM_PORTS]; + + +DIAG_TARGET diag_targets[MAX_DEVICES]; +EXP_TARGET exp_targets[MAX_DEVICES]; + + +MPT_PORT *mappedPort; +int mappedBus; +int mappedTarget; +int mappedDevHandle; +int mappedValue; + + +#if __sparc__ +int scsi_vhci_fd; + + +typedef struct +{ + char name[NAME_MAX]; + char link[PATH_MAX]; +} NAME_LINK; + + +NAME_LINK *dev_rdsk_cache; +int dev_rdsk_count = 0; +NAME_LINK *dev_rmt_cache; +int dev_rmt_count = 0; +NAME_LINK *dev_es_cache; +int dev_es_count = 0; + + +int device_caches_initialized = 0; +#endif + + +char *args; +char *argsCurr; + + +char *fileNames[3]; +int numFileNames; +int yesFlag; +int noFlag; +int xFlag; +int gFlag; +int qFlag; +int kFlag; + + +int wFlag; +FILE *logFile; + + +int tagType; + + +int expert; +int paged; +int lines; + + +void *osDeviceState = NULL; + + +int iocMask = 0; + + +int maxLuns = 256; + + +#if __linux__ +int workaroundsTried = FALSE; +int oldMptBaseDetected = 0; +int newMptBaseDetected = 0; +#endif + + +int diagReturnCode = 0; + + +#if __linux__ || __alpha__ +HANDLE globalFileHandle; +HANDLE globalFileHandle2; +HANDLE globalFileHandle3; +#endif + + +#define JUST_FC 1 +#define JUST_SCSI 2 +#define JUST_SAS 4 +#define JUST_ALL (JUST_FC | JUST_SCSI | JUST_SAS) + +int just = 0; + + +int virtInit = 0; + + +char logPrefixBuffer[64]; +char pagedBuffer[1024]; + + +#if WIN32 +U32 gRetDataLen = 0; +#endif + + +#define MPI1 if (mpi1) +#define MPI2 if (mpi2) +#define MPI20 if (mpi20) +#define MPI25 if (mpi25) +#define EXP if (expert) + +#define FLASH_RESET_INTEL 0xff +#define FLASH_RESET_AMD 0xf0 +#define FLASH_IDENTIFY 0x90 +#define FLASH_CFI_QUERY 0x98 + + +// MPI2 2.0.10 header file retired CurReplyFrameSize field +// in IOC Facts reply. Define OldReplyFrameSize to use as +// backward compatible reference +#define OldReplyFrameSize IOCMaxChainSegmentSize + + +/* user command line arguments */ +typedef struct +{ + int portNums[NUM_PORTS]; /* port numbers specified */ + int numPortNums; /* number of port numbers specified */ + int boardInfo; /* board info wanted */ + int scan; /* boolean */ + int info; /* boolean */ + int dump; /* boolean */ + char linkspeed; /* desired link speed ('a', '1', '2', or '4') */ + char topology; /* desired topology ('a', '1', or '2') */ + int reset; /* boolean for chip reset */ + int linkReset; /* boolean for link reset */ + int linkResetFlag; /* boolean for link reset type */ + int coalescing; /* boolean */ + int ic_depth; /* desired interrupt coalescing depth */ + int ic_timeout; /* desired interrupt coalescing timeout */ + int monitorInterval; /* desired monitoring interval */ + int monitorDuration; /* desired monitoring duration */ +} CMNDLINE_ARGS; + + +unsigned char LoopIdToAlpa[126] = +{ + 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6, /* 0 to 9 */ + 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca, /* 10 to 19 */ + 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, /* 20 to 29 */ + 0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, /* 30 to 39 */ + 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97, /* 40 to 49 */ + 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79, /* 50 to 59 */ + 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, /* 60 to 69 */ + 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56, /* 70 to 79 */ + 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, /* 80 to 89 */ + 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35, /* 90 to 99 */ + 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, /* 100 to 109 */ + 0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, /* 110 to 119 */ + 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01 /* 120 to 125 */ +}; + + +unsigned char AlpaToLoopId[256] = +{ + 0x7e, 0x7d, 0x7c, 0xff, 0x7b, 0xff, 0xff, 0xff, /* 0x00 to 0x07 */ + 0x7a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79, /* 0x08 to 0x0f */ + 0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x77, /* 0x10 to 0x17 */ + 0x76, 0xff, 0xff, 0x75, 0xff, 0x74, 0x73, 0x72, /* 0x18 to 0x1f */ + 0xff, 0xff, 0xff, 0x71, 0xff, 0x70, 0x6f, 0x6e, /* 0x20 to 0x27 */ + 0xff, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0xff, /* 0x28 to 0x2f */ + 0xff, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0xff, /* 0x30 to 0x37 */ + 0xff, 0x61, 0x60, 0xff, 0x5f, 0xff, 0xff, 0xff, /* 0x38 to 0x3f */ + 0xff, 0xff, 0xff, 0x5e, 0xff, 0x5d, 0x5c, 0x5b, /* 0x40 to 0x47 */ + 0xff, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0xff, /* 0x48 to 0x4f */ + 0xff, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0xff, /* 0x50 to 0x57 */ + 0xff, 0x4e, 0x4d, 0xff, 0x4c, 0xff, 0xff, 0xff, /* 0x58 to 0x5f */ + 0xff, 0xff, 0xff, 0x4b, 0xff, 0x4a, 0x49, 0x48, /* 0x60 to 0x67 */ + 0xff, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0xff, /* 0x68 to 0x6f */ + 0xff, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0xff, /* 0x70 to 0x77 */ + 0xff, 0x3b, 0x3a, 0xff, 0x39, 0xff, 0xff, 0xff, /* 0x78 to 0x7f */ + 0x38, 0x37, 0x36, 0xff, 0x35, 0xff, 0xff, 0xff, /* 0x80 to 0x87 */ + 0x34, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33, /* 0x88 to 0x8f */ + 0x32, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, /* 0x90 to 0x97 */ + 0x30, 0xff, 0xff, 0x2f, 0xff, 0x2e, 0x2d, 0x2c, /* 0x98 to 0x9f */ + 0xff, 0xff, 0xff, 0x2b, 0xff, 0x2a, 0x29, 0x28, /* 0xa0 to 0xa7 */ + 0xff, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0xff, /* 0xa8 to 0xaf */ + 0xff, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0xff, /* 0xb0 to 0xb7 */ + 0xff, 0x1b, 0x1a, 0xff, 0x19, 0xff, 0xff, 0xff, /* 0xb8 to 0xbf */ + 0xff, 0xff, 0xff, 0x18, 0xff, 0x17, 0x16, 0x15, /* 0xc0 to 0xc7 */ + 0xff, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0xff, /* 0xc8 to 0xcf */ + 0xff, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0xff, /* 0xd0 to 0xd7 */ + 0xff, 0x08, 0x07, 0xff, 0x06, 0xff, 0xff, 0xff, /* 0xd8 to 0xdf */ + 0x05, 0x04, 0x03, 0xff, 0x02, 0xff, 0xff, 0xff, /* 0xe0 to 0xe7 */ + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, /* 0xe8 to 0xef */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xf0 to 0xf7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* 0xf8 to 0xff */ +}; + + +void outputPaged(FILE *fp, char *buffer); +int printfPaged(const char *format, ...); +int fprintfPaged(FILE *fp, const char *format, ...); +char *logPrefix(MPT_PORT *port); +#if __sparc__ +int getNodeInfo(di_node_t node, void *arg); +#endif +int checkReady(MPT_PORT *port); +int checkOperational(MPT_PORT *port, int flag); +int bringOnline(MPT_PORT *port); +int findPorts(void); +int closePorts(int numPorts); +int closePort(MPT_PORT *port); +int getFileName(char *buf, int len, FILE *file, char *fileString, int fileType); +int getString(char *buf, int len, FILE *file); +int getStringFromArgs(char *buf, int len, FILE *file); +int getYesNoAnswer(int defvalue); +int getNumberAnswer(int low, int high, int defvalue); +int getNumberAnswerHex(int low, int high, int defvalue); +int getHexNumberAnswer(U32 *value); +int getHexDoubleNumberAnswer(U32 *value1, U32 *value2); +int parseHexNumberChange(U32 *value); +int readFile(char *name, unsigned char **outBuf, int *outLen); +int queryFile(char *name); +int printWhatString(char *type, unsigned char *buf, int len); +int getCompatible(int deviceId, int type); +int checkCompatible(int deviceId1, int deviceId2, int type); +int doPort(MPT_PORT *port); +int doPortOption(MPT_PORT *port, int option); +int doIdentify(MPT_PORT *port); +int doFirmwareDownload(MPT_PORT *port); +int doFirmwareUpload(MPT_PORT *port); +int doBiosFcodeDownload(MPT_PORT *port); +int doBiosFcodeUpload(MPT_PORT *port, unsigned char **outBuf, int *outLen, int type); +int verifyBiosFcodeImage(MPT_PORT *port, unsigned char *buf, int len, int type); +int splitBiosImage(MPT_PORT *port, unsigned char **buf1, int *len1, unsigned char **buf2, int *len2); +int fixupBiosFcodeImage(MPT_PORT *port, unsigned char *buf, int len, int last); +int doSeepromDownload(MPT_PORT *port); +int doSeepromUpload(MPT_PORT *port); +int doScanForDevices(MPT_PORT *port, int flag); +int doScanForLuns(MPT_PORT *port, int flag , int option); +int doConfigPage(MPT_PORT *port); +int doInterruptCoalescingValues(MPT_PORT *port, int timeout, int depth); +int doIocSettings(MPT_PORT *port); +int doScsiInitiatorSettings(MPT_PORT *port); +char *syncToMt(int sync); +char *syncToMb(int sync, int wide); +int doScsiTargetSettings(MPT_PORT *port); +int doFcLinkSpeedValue(MPT_PORT *port, int t); +int doFcTopologyValue(MPT_PORT *port, int t); +int doFcPortOffline(MPT_PORT *port); +int doFcPortOnline(MPT_PORT *port); +int doFcTopologyNLPort(MPT_PORT *port); +int doFcTopologyNPort(MPT_PORT *port); +int doFcSpecialMode(MPT_PORT *port, int enable, int permanent); +int doFcPortSettings(MPT_PORT *port); +int doFcChangeWwn(MPT_PORT *port); +int doSasPhyOnOffline(MPT_PORT *port, int onoff); +int doSasIoUnitSettings(MPT_PORT *port); +int doSasChangeWwid(MPT_PORT *port, int checkZero); +int doIoUnitSettings(MPT_PORT *port); +int doFcPersistentMappings(MPT_PORT *port, int command); +int doSasPersistentMappings(MPT_PORT *port, int command); +int doDisplayLoggedInDevices(MPT_PORT *port); +int doDisplayAttachedDevices(MPT_PORT *port); +int showSasDiscoveryErrors(MPT_PORT *port); +int doShowPortAliases(MPT_PORT *port); +int doShowExpanderRoutingTables(MPT_PORT *port); +int doTestConfigPageActions(MPT_PORT *port); +int selectDevice(MPT_PORT *port, int *dev_bus, int *dev_target); +int selectDeviceRWMedia(MPT_PORT *port); +int selectDeviceRWBuffer(MPT_PORT *port); +int getExpanderType(int componentId, U8 *componentVendorId, U8 *vendorId); +char *printExpanderType(int expanderType); +int selectExpander(MPT_PORT *port, int *ses_bus, int *ses_target, U8 *phys_port, _U64 *sas_addr, int *expanderType); +int doDiagnostics(MPT_PORT *port, int command); +void generatePattern(int pattern, void *buf, int len); +void format64bitDecimal(uint64_t number, char *buf, int len); +int doInquiryTest(MPT_PORT *port); +int doWriteBufferReadBufferCompareTest(MPT_PORT *port); +int getEedpMode(MPT_PORT *port, int eedp); +int doReadTest(MPT_PORT *port); +int doWriteReadCompareTest(MPT_PORT *port); +int doWriteTest(MPT_PORT *port); +int doReadCompareTest(MPT_PORT *port); +int doTestUnitReadyTest(MPT_PORT *port); +int doLogSenseTest(MPT_PORT *port); +int doReadCapacityTest(MPT_PORT *port); +int doModePageTest(MPT_PORT *port); +int doEchoTest(MPT_PORT *port); +int doReadLinkErrorStatusTest(MPT_PORT *port); +int doDisplayPortCounters(MPT_PORT *port); +int doClearPortCounters(MPT_PORT *port); +int doTriggerAnalyzerWithEcho(MPT_PORT *port); +int isSata(MPT_PORT *port, int bus, int target); +int isSsd(MPT_PORT *port, int bus, int target); +int getPath(MPT_PORT *port, int bus, int target, PATH *path); +int getParent(MPT_PORT *port, int bus, int target, int *parent); +int isRaidPhysDisk(MPT_PORT *port, int bus, int target, int *physdisk); +int isRaidPhysDisk2(MPT_PORT *port, int bus, int target, int *physdisk); +int doReadLogicalBlocks(MPT_PORT *port); +int doWriteLogicalBlocks(MPT_PORT *port); +int doVerifyLogicalBlocks(MPT_PORT *port); +int doDiagnosticPageTest(MPT_PORT *port); +int doInjectRepairMediaError(MPT_PORT *port, int inject); +int doSoftwareWriteProtect(MPT_PORT *port, int flag); +int doReadWriteCache(MPT_PORT *port, int flag); +int doDisplayPhyCounters(MPT_PORT *port); +int doClearPhyCounters(MPT_PORT *port); +int doSataIdentifyDeviceTest(MPT_PORT *port); +int doSataClearAffiliationTest(MPT_PORT *port); +int doSataSmartReadTest(MPT_PORT *port); +int doSepTest(MPT_PORT *port); +int doProdSpecSasIoUnitControl(MPT_PORT *port); +int doProdSpecSasIoUnitControl2(MPT_PORT *port); +int doDiagDataUpload(MPT_PORT *port); +int doReportLunsTest(MPT_PORT *port); +int doDriveFirmwareDownload(MPT_PORT *port); +int doSesDownloadMicrocode(MPT_PORT *port, int bus, int target, int lun, + int mode, int id, int offset, int size, unsigned char *buf, int len); +int doExpanderChangeMfgDataFields(MPT_PORT *port); +int doExpanderGetSetMfgDataFields(MPT_PORT *port, int bus, int target, U64 *sasAddr, U64 *enclLogId, U8 *macAddr); +int doExpanderFirmwareDownload(MPT_PORT *port); +int doReadBufferFirmwareUpload(MPT_PORT *port); +int doRaidActions(MPT_PORT *port, int command); +int selectVolume(MPT_PORT *port, IOCPage2_t *IOCPage2, int *volumeOut); +int doShowVolumes(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3); +int doShowPhysDisks(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3); +int doGetVolumeState(MPT_PORT *port, IOCPage2_t *IOCPage2); +int doWaitForResync(MPT_PORT *port, IOCPage2_t *IOCPage2); +int doModifyVolume(MPT_PORT *port, IOCPage2_t *IOCPage2, int action, char *string); +int doCreateVolume(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3); +int doDeleteVolume(MPT_PORT *port, IOCPage2_t *IOCPage2); +int doVolumeSettings(MPT_PORT *port, IOCPage2_t *IOCPage2); +int doVolumeName(MPT_PORT *port, IOCPage2_t *IOCPage2); +int doDriveFirmwareUpdateMode(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3, int flag); +int doModifyPhysDisk(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3, int action, char *string); +int doCreatePhysDisk(MPT_PORT *port, IOCPage2_t *IOCPage2); +int doPhysDiskSettings(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3); +int doCreateHotSpare(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3); +int doDeleteHotSpare(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3); +int showHiddenDevices(MPT_PORT *port); +int doRaidActions2(MPT_PORT *port, int command); +int selectVolume2(MPT_PORT *port, int *volumeOut, int *handleOut); +void doShowVolumeState2(int volume, int volState, int volFlag, int useVolume); +int doShowVolumes2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6); +int doShowPhysDisks2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6); +int doGetVolumeState2(MPT_PORT *port); +int doWaitForResync2(MPT_PORT *port); +int doModifyVolume2(MPT_PORT *port, int action, char *string); +int doCreateVolume2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6); +int doDeleteVolume2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6); +int doVolumeSettings2(MPT_PORT *port); +int doVolumeName2(MPT_PORT *port); +int doVolumeIRCC2(MPT_PORT *port); +int doVolumeStopIRCC2(MPT_PORT *port); +int doVolumeOCE(MPT_PORT *port); +int doDriveFirmwareUpdateMode2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6, int flag); +int doModifyPhysDisk2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6, int action, char *string); +int doCreateHotSpare2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6); +int doDeleteHotSpare2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6); +int showHiddenDevices2(MPT_PORT *port); +int getRaidCounts(MPT_PORT *port, int activeOnly, int *numVolumes, int *numPhysDisks, int *numHotSpares); +int getRaidConfig(MPT_PORT *port, int elementType, int devHandle, int physDiskNum, Mpi2RaidConfigurationPage0_t **RaidConfigPage0); +int doResetBus(MPT_PORT *port); +int doResetTarget(MPT_PORT *port); +int doClearAca(MPT_PORT *port); +int doBeacon(MPT_PORT *port, int on_off); +int doDisplaySfpPages(MPT_PORT *port); +int doClean(MPT_PORT *port); +int doFcManagementTools(MPT_PORT *port); +int doRemoveSasDevice(MPT_PORT *port); +int doDisplayLogEntries(MPT_PORT *port); +int doClearLogEntries(MPT_PORT *port); +int doSasForceFullDiscovery(MPT_PORT *port); +int doFirmwareDownloadBoot(MPT_PORT *port); +int eventQuery(MPT_PORT *port, int *entries, int *types); +int eventEnable(MPT_PORT *port, int *types); +int eventReport(MPT_PORT *port, int entries, EVENT2 *events); +int doDisplayCurrentEvents(MPT_PORT *port); +int doDisplayTransferStatistics(MPT_PORT *port); +int doDisplayTransferStatisticsAll(int numPorts, MPT_PORT *ports[], int interval, int duration); +int isRaidVolume(MPT_PORT *port, int bus, int target); +int isRaidVolume2(MPT_PORT *port, int bus, int target); +void convertBusTarget(MPT_PORT *port, int *bus, int *target, int lun); +#if __sparc__ +void cachePathLinks(char *prefix, char *suffix, NAME_LINK **cacheOut, int *countOut); +int findPathLink(MPT_PORT *port, char *prefix, NAME_LINK *cache, int count, char *path, char *buf); +int getPortPhyMap(MPT_PORT *port); +#endif +int getOsDeviceName(MPT_PORT *port, int bus, int target, int lun, char *buf, int len, int type); +int doDisplayOsDeviceNames(MPT_PORT *port); +int diagBufferAction(MPT_PORT *port, int action, void *buf, int size); +int diagBufferAction2(MPT_PORT *port, int action, void *buf, int size); +int diagBufferRegister(MPT_PORT *port, int type, int id, int size); +int diagBufferRegister2(MPT_PORT *port, int type, int id, int size); +int diagBufferUnregister(MPT_PORT *port, int id); +int diagBufferQuery(MPT_PORT *port, int type, int id, int *flags, int *size); +int diagBufferQuery2(MPT_PORT *port, int type, int id, int *flags, int *size); +int diagBufferReadBuffer(MPT_PORT *port, int id, char *name, int file, int *sizeIn, int header); +int diagBufferRelease(MPT_PORT *port, int type, int id); +int doDiagBuffer(MPT_PORT *port); +int doFlashUpload(MPT_PORT *port); +int doDisplayVersionInfo(MPT_PORT *port); +void showVpdData(MPT_PORT *port, ManufacturingPage1_t *ManufacturingPage1); +int doDisplayVpdInfo(MPT_PORT *port); +int doProgramVpdInfo(MPT_PORT *port); +int doReadChipMemoryRegions(MPT_PORT *port, U32 addr, U32 *buf, int num); +int doWriteChipMemoryRegions(MPT_PORT *port, U32 addr, U32 *buf, int num); +int doDumpRegisters(MPT_PORT *port); +int doEnableDiagAccess(MPT_PORT *port, U32 *diagOrig); +int readLocalMemory(MPT_PORT *port, U32 addr, U32 *data, U32 temp); +int doDumpChipMemoryRegions(MPT_PORT *port); +int doReadModifyChipMemoryLocations(MPT_PORT *port); +int doDumpFcTraceBuffer(MPT_PORT *port); +int doForceFirmwareFault(MPT_PORT *port); +int doReadWriteExpanderMemory(MPT_PORT *port); +int doReadWriteExpanderIstwiDevice(MPT_PORT *port); +int doResetExpander(MPT_PORT *port); +int sendResetExpander(MPT_PORT *port, U8 physical_port, _U64 sas_address, U32 addr, U32 data); +int setFlashWrite(MPT_PORT *port, U32 flash_csr, U32 flash_csr_wr_en, int on); +U32 readFlash(MPT_PORT *port, U32 flash_add, int offset); +int writeFlash(MPT_PORT *port, U32 flash_add, int offset, U32 data); +void resetFlash(MPT_PORT *port, U32 flash_csr, U32 flash_csr_wr_en, U32 flash_add, int intel); +int doFlashInfo(MPT_PORT *port); +int doReadRegister(MPT_PORT *port, U32 offset, U32 *data); +int doWriteRegister(MPT_PORT *port, U32 offset, U32 *data); +int doReadWriteRegister(MPT_PORT *port, U32 offset, U32 *data, int command); +int doDumpPciConfigSpace(MPT_PORT *port); +int doShowNonDefaultSettings(MPT_PORT *port); +int doRestoreDefaultSettings(MPT_PORT *port); +int doDefaultPhyRegsSettings(MPT_PORT *port); +int doFcChangePersonalWwn(MPT_PORT *port); +int doGIEL(MPT_PORT *port); +int doGID_FT(MPT_PORT *port); +int doGA_NXT(MPT_PORT *port); +int doExLinkServiceSend(MPT_PORT *port); +int doResetFcLink(MPT_PORT *port, int flag); +int doScsiCdb(MPT_PORT *port); +int doSataPassthroughSend(MPT_PORT *port); +int doSmpPassthroughSend(MPT_PORT *port); +int doResetSasLink(MPT_PORT *port, int flag); +int doDumpPortState(MPT_PORT *port, int flag); +int doPortStateSummary(MPT_PORT *port); +int getChipName(MPT_PORT *port); +int getPortInfo(MPT_PORT *port); +int getPortInfo2(MPT_PORT *port); +int updatePortInfo(MPT_PORT *port); +int updatePortInfo2(MPT_PORT *port); +int getBoardInfo(MPT_PORT *port); +int showBoardInfo(MPT_PORT *port, int flag); +int dumpFcDevicePages(MPT_PORT *port); +int dumpSasDevicePages(MPT_PORT *port); +int showPortInfo(MPT_PORT *port); +int showPortInfoHeader(MPT_PORT *port); +int getDeviceInfo(MPT_PORT *port, int bus, int target, char *buf, int len); +int getDeviceInfoHeader(MPT_PORT *port, char *buf, int len); +int getIocFacts(MPT_PORT *port, IOCFactsReply_t *rep); +int getIocFacts2(MPT_PORT *port, Mpi2IOCFactsReply_t *rep); +int getPortFacts(MPT_PORT *port, PortFactsReply_t *rep); +int getPortFacts2(MPT_PORT *port, Mpi2PortFactsReply_t *rep); +int doConfigPageRequest(MPT_PORT *port, void *req, int reqSize, void *rep, int repSize, + void *payIn, int payInSize, void *payOut, int payOutSize, int timeOut); +int getConfigPageHeader(MPT_PORT *port, int type, int number, int address, ConfigReply_t *repOut); +int getConfigPageLength(MPT_PORT *port, int type, int number, int address, int *length); +int getConfigPageAction(MPT_PORT *port, int action, int type, int number, int address, void *page, int pageSize); +int getConfigPage(MPT_PORT *port, int type, int number, int address, void *page, int pageSize); +void *getConfigPageActionAlloc(MPT_PORT *port, int action, int type, int number, int address, int *length); +void *getConfigPageAlloc(MPT_PORT *port, int type, int number, int address, int *length); +int setConfigPageAction(MPT_PORT *port, int action, int type, int number, int address, void *page, int pageSize); +int setConfigPage(MPT_PORT *port, int type, int number, int address, void *page, int pageSize); +int showConfigPage(MPT_PORT *port, char *string, void *page, int length); +int getProperty(MPT_PORT *port, char *name, char *buf, int bufLen); +void setName(MPT_PORT *port, int bus, int target, void *req); +int setMaxBusTarget(MPT_PORT *port); +int mapDevHandleToBusTarget(MPT_PORT *port, int dev_handle, int *bus, int *target); +int mapBusTargetToDevHandle(MPT_PORT *port, int bus, int target, int *dev_handle); +int mapBTDH(MPT_PORT *port, int *bus, int *target, int *dev_handle); +int mapOsToHwTarget(MPT_PORT *port, int target); +int doTestUnitReady(MPT_PORT *port, int bus, int target, int lun); +int doInquiry(MPT_PORT *port, int bus, int target, int lun, unsigned char *buf, int len); +int doInquiryVpdPage(MPT_PORT *port, int bus, int target, int lun, int page, unsigned char *buf, int len); +int doLogSense(MPT_PORT *port, int bus, int target, int lun, int page, int pc, unsigned char *buf, int len); +int doLogSelect(MPT_PORT *port, int bus, int target, int lun, int pc, int save, unsigned char *buf, int len); +int doReadBlockLimits(MPT_PORT *port, int bus, int target, int lun, unsigned char *buf, int len); +int doReadCapacity(MPT_PORT *port, int bus, int target, int lun, unsigned char *buf, int len); +int doReadCapacity16(MPT_PORT *port, int bus, int target, int lun, unsigned char *buf, int len); +int doModeSense(MPT_PORT *port, int bus, int target, int lun, int page, int control, int dbd, unsigned char *buf, int len); +int doModeSelect(MPT_PORT *port, int bus, int target, int lun, int save, unsigned char *buf, int len); +int doReadBuffer(MPT_PORT *port, int bus, int target, int lun, int mode, unsigned char *buf, int len); +int doWriteBuffer(MPT_PORT *port, int bus, int target, int lun, int mode, unsigned char *buf, int len); +int doReadBufferFull(MPT_PORT *port, int bus, int target, int lun, int mode, int id, int offset, unsigned char *buf, int len); +int doWriteBufferFull(MPT_PORT *port, int bus, int target, int lun, int mode, int id, int offset, unsigned char *buf, int len); +int doRead(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int lbns, int mode, unsigned char *buf, int len); +int doWrite(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int lbns, int mode, unsigned char *buf, int len); +int doVerify(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int lbns, int mode, unsigned char *buf, int len); +int doRead32(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int lbns, int mode, unsigned char *buf, int len); +int doWrite32(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int lbns, int mode, unsigned char *buf, int len); +int doReadLong(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int mode, unsigned char *buf, int len, int *resid); +int doWriteLong(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int mode, unsigned char *buf, int len, int *resid); +int doReportLuns(MPT_PORT *port, int bus, int target, unsigned char *buf, int len); +int doReceiveDiagnosticResults(MPT_PORT *port, int bus, int target, int lun, int page, unsigned char *buf, int len); +int doSendDiagnostic(MPT_PORT *port, int bus, int target, int lun, unsigned char *buf, int len); +int doScsiIo(MPT_PORT *port, int bus, int target, int raid, void *req, int reqSize, SCSI_REPLY *rep, int repSize, + void *payIn, int payInSize, void *payOut, int payOutSize, int timeOut); +int doReadLongSata(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int mode, unsigned char *buf, int len); +int doWriteLongSata(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int mode, unsigned char *buf, int len); +int doFwDownload(MPT_PORT *port, int type, unsigned char *buf, int len, int offset); +int doFwUpload(MPT_PORT *port, int type, unsigned char *buf, int len, int offset, int *outLen); +int doIocInit(MPT_PORT *port, int WhoInit); +char *translateSmpFunctionResult(int functionResult); +int doSmpReportMfg(MPT_PORT *port, _U64 SASAddress, U8 physicalPort, PTR_SMP_REPORT_MANUFACTURER_INFO_RESPONSE smpResp, int *respDataLenth); +int doSmpPassthrough(MPT_PORT *port, U8 smpPort, _U64 smpAddr, void *smpReq, int smpReqSize, void *smpRsp, int smpRspSize, int *respDataLength); +int doResetPort(MPT_PORT *port); +void doLogMptCommandReq(MPT_PORT *port, void *req, int reqSize); +void doLogMptCommandRep(MPT_PORT *port, void *rep, int repSize, int status); +void logMptCommandReq(MPT_PORT *port, void *req, int reqSize); +void logMptCommandRep(MPT_PORT *port, void *req, int reqSize, void *rep, int repSize, int status); +int doMptCommand(MPT_PORT *port, void *req, int reqSize, void *rep, int repSize, + void *payIn, int payInSize, void *payOut, int payOutSize, int timeOut); +int doMptCommandCheck(MPT_PORT *port, void *req, int reqSize, void *rep, int repSize, + void *payIn, int payInSize, void *payOut, int payOutSize, int timeOut); +char *translateIocStatus(int ioc_status); +void displayByteData(unsigned char *buf, int len); +void dumpMemory(void *buf, int len, char *string); +void dumpMemoryWide(void *buf, int len, char *string); +void initT10Crc(void); +unsigned int genT10Crc(unsigned char *buf); +unsigned int genLbCrc(unsigned char *buf, int len); +int checkRemoveT10(MPT_PORT *port, unsigned int lbn, int lbns, unsigned char *buf_in, unsigned char *buf_out, int len); +int checkRemoveLb(MPT_PORT *port, unsigned int lbn, int lbns, unsigned char *buf_in, unsigned char *buf_out, int len, int do_crc); +int insertT10(MPT_PORT *port, unsigned int lbn, int lbns, unsigned char *buf_in, unsigned char *buf_out, int len); +int insertLb(MPT_PORT *port, unsigned int lbn, int lbns, unsigned char *buf_in, unsigned char *buf_out, int len, int do_crc); +void waitForFile(char *name); +char *skipLine(char *buf); +void removeLine(char *buf); +int getNamedItem(MPT_PORT *port, char *name, char *buf, int type, void *address); +int updateConfigPage(MPT_PORT *port, char *string, void *page); +int doWriteFcManufacturingInfo(MPT_PORT *port); +int doWriteSasManufacturingInfo(MPT_PORT *port); +int concatenateSasFirmwareNvdata(void); +char *getSasProductId(char *nvdata); +int selectAltaDevice(MPT_PORT *port, int *dev_bus, int *dev_target); +int doAltaDiagnostics(MPT_PORT *port, int command); +int doAltaProgramManufacturingInfo(MPT_PORT *port); +int doAltaDisplayManufacturingInfo(MPT_PORT *port); +int doResetAlta(MPT_PORT *port); +char *translateExpanderEventCode(int code); +int decodeExpanderLogEntries(FILE *file, unsigned char *buf, int length); +int doDisplayExpanderLogEntries(MPT_PORT *port); +int doClearExpanderLogEntries(MPT_PORT *port); +int doUartDebugConsole(MPT_PORT *port); +int getAdapterPropertiesMaxPages(MPT_PORT *port, int *maxPages); +int doSendPowerManagementControlMPI(MPT_PORT *port); +int doIoUnit7Settings(MPT_PORT *port); +int doSasIoUnit8Settings(MPT_PORT *port); +int dumpSasDevicePage0sLong(MPT_PORT *port); +int doExpanderUart(MPT_PORT *port); + + +#if LSIINTERNAL +#include "internal/sc.c" +#endif + + +#if DOS || EFI +#include "mpt.c" +#undef mpi1 +#undef mpi2 +#undef mpi20 +#undef mpi25 +#endif + + +#define mpi1 (port->mptVersion < MPI2_VERSION_02_00) +#define mpi2 (port->mptVersion >= MPI2_VERSION_02_00) +#define mpi20 ((port->mptVersion >= MPI2_VERSION_02_00) && (port->mptVersion < MPI2_VERSION_02_05)) +#define mpi25 (port->mptVersion >= MPI2_VERSION_02_05) + + +void +outputPaged(FILE *fp, char *buffer) +{ + char buf[16]; + char c; + + fputs(buffer, fp); + + if (paged && fp == stdout) + { + while ((c = *buffer++) != '\0') + { + if (c == '\n') + lines++; + } + + if (lines >= paged) + { + fputs("--more, hit RETURN--", stdout); + if (fgets(buf, sizeof buf, stdin)); + lines = 0; + } + } +} + + +int +printfPaged(const char *format, ...) +{ + va_list args; + int n; + + va_start(args, format); + + n = vsprintf(pagedBuffer, format, args); + + va_end(args); + + outputPaged(stdout, pagedBuffer); + + return n; +} + + +int +fprintfPaged(FILE *fp, const char *format, ...) +{ + va_list args; + int n; + + va_start(args, format); + + n = vsprintf(pagedBuffer, format, args); + + va_end(args); + + outputPaged(fp, pagedBuffer); + + return n; +} + + +char * +logPrefix(MPT_PORT *port) +{ + time_t now; + + time(&now); + if (port) + sprintf(logPrefixBuffer, "%s %s", ctime(&now), port->portName); + else + sprintf(logPrefixBuffer, "%s", ctime(&now)); + if (logPrefixBuffer[8] == ' ') + logPrefixBuffer[8] = '0'; + if (port) + logPrefixBuffer[24]= ':'; + else + logPrefixBuffer[24]= '\0'; + + return logPrefixBuffer; +} + + +int _cdecl +main(int argc, char *argv[]) +{ + int portNumber; + MPT_PORT *port; + int numPorts; + int i; + int arg; + CMNDLINE_ARGS cargs; + char *pArg; + char *type; + int n; + int t; + extern int optind; + extern int optopt; + +#if DOS + setvbuf(stdout, NULL, _IONBF, 0); +#endif + + memset(mptPorts, 0, sizeof mptPorts); + + initT10Crc(); + + args = NULL; + argsCurr = NULL; + + pArg = NULL; + + numFileNames = 0; + yesFlag = FALSE; + noFlag = FALSE; + xFlag = FALSE; + gFlag = FALSE; + qFlag = FALSE; + kFlag = FALSE; + + wFlag = 0; + logFile = NULL; + + tagType = MPI_SCSIIO_CONTROL_SIMPLEQ; + + expert = FALSE; + paged = 0; + + memset(&cargs, 0, sizeof(CMNDLINE_ARGS)); + + printf("\nLSI Logic MPT Configuration Utility, %s\n", LSIUTIL_VERSION); + + if (argc > 1) + { + while ((arg = getopt(argc, argv, "?a:bc:def:ghij:kl:m:np:qrst:uv:wxyz018")) != EOF) + { + switch (arg) + { + case '?': + if (optopt) + { + optopt = 0; + break; + } + + case 'h': + printf( +"\nHelp Usage\n" +"Invoking lsiutil with no arguments will start an interactive session.\n\n" +" -e Turn on Expert Mode (more menu options).\n" +" -w, -ww, -www Log internal operations to lsiutil.log, for debug.\n" +" -y Answer yes to yes/no questions whose default is yes.\n" +" -n Answer no to yes/no questions whose default is no.\n" +" -j type[,type] Include just ports of type 'type' (FC, SCSI, SAS).\n" +" -x Concatenate SAS firmware and NVDATA files.\n\n"); + printf( +"Display Options\n" +"usage: lsiutil [ -p portNumber ] [ -u ][ -s ] [ -d ] [ -i ] [ -b ]\n" +" -p portNumber Specify the port number to operate on.\n" +" If not specified, all ports are used.\n" +" -u Use untagged, rather than tagged, SCSI commands.\n" +" -s Scan for and display all targets.\n" +" -d Dump all config pages.\n" +" -i Display port settings.\n" +" -b Show board manufacturing information.\n" +" -m freq[,time] Monitor port performance, updating the display\n" +" every 'freq' seconds, for 'time' seconds.\n\n"); + printf( +"Examples:\n" +"1. to display the port settings and targets for port 1:\n" +" lsiutil -p 1 -i -s\n" +"2. to display the targets found on all known ports:\n" +" lsiutil -s\n\n"); + printf( +"Operational Options\n" +"usage: lsiutil -p portNumber [ -l linkSpeed ] [ -t topology ]\n" +" [ -c timeout,depth ] [ -r ]\n" +" -p portNumber Specify the port number to operate on.\n" +" Required parameter for operational options.\n" +" -l linkSpeed Set link speed. Valid options for linkSpeed are:\n" +" 'a' Auto link speed negotiation\n" +" '1' Force 1Gb link speed\n" +" '2' Force 2Gb link speed\n" +" '4' Force 4Gb link speed\n"); + printf( +" -t topology Set topology. Valid options for topology are:\n" +" 'a' Auto topology negotiation\n" +" '1' Force NL_Port topology\n" +" '2' Force N_Port topology\n" +" -c timeout,depth Set interrupt coalescing values.\n" +" Timeout is a value in microseconds between\n" +" 1 and 1000. Depth is a value between 1 and 128.\n" +" Setting either or both values to zero will\n" +" disable interrupt coalescing for that port.\n" +" -r Perform a chip reset on the given port.\n" +" -z Perform an FC link reset on the given port.\n"); + printf( +"NOTE: In order for linkSpeed, topology, or interrupt coalescing\n" +" settings to take effect, a chip reset is necessary.\n\n" +"Examples:\n" +"1. to force linkspeed to 1Gb on port 2:\n" +" lsiutil -p 2 -l 1\n" +"2. to set interrupt coalescing to a timeout of 200ms with\n" +" a depth of 9 and to force N_Port topology on port 1:\n" +" lsiutil -p 1 -c 200,9 -t 2\n\n" +); + return 0; + + case 'a': + args = optarg; + break; + + case 'b': + cargs.boardInfo = TRUE; + break; + + case 'c': + if (sscanf(optarg, "%d,%d", &cargs.ic_timeout, &cargs.ic_depth) != 2) + { + printf("ERROR: Invalid argument %s for interrupt coalescing.\n", optarg); + printf("Must specify two decimal numbers -- timeout,depth\n"); + return EINVAL; + } + else + { + if (cargs.ic_timeout < 0) + cargs.ic_timeout = 0; + if (cargs.ic_timeout > 1000) + cargs.ic_timeout = 1000; + if (cargs.ic_depth < 0) + cargs.ic_depth = 0; + if (cargs.ic_depth > 128) + cargs.ic_depth = 128; + + cargs.coalescing = TRUE; + } + break; + + case 'd': + cargs.dump = TRUE; + break; + + case 'e': + expert = TRUE; + break; + + case 'f': + while (TRUE) + { + if (numFileNames < 3) + { + fileNames[numFileNames++] = optarg; + } + else + { + printf("ERROR: At most, three filenames may be supplied\n"); + return EINVAL; + } + + optarg = strchr(optarg, ','); + if (optarg) + *optarg++ = '\0'; + else + break; + } + break; + + case 'g': + gFlag = TRUE; + break; + + case 'i': + cargs.info = TRUE; + break; + + case 'j': + while (TRUE) + { + type = optarg; + if (type == NULL) + break; + optarg = strchr(optarg, ','); + if (optarg) + *optarg++ = '\0'; + if (strcasecmp(type, "good") == 0) + just |= JUST_ALL; + else if (strcasecmp(type, "fc") == 0) + just |= JUST_FC; + else if (strcasecmp(type, "scsi") == 0) + just |= JUST_SCSI; + else if (strcasecmp(type, "sas") == 0) + just |= JUST_SAS; + else + { + printf("ERROR: Invalid type %s.\n", type); + printf("Valid types are FC, SCSI, and SAS\n"); + return EINVAL; + } + } + break; + + case 'k': + kFlag = TRUE; + break; + + case 'l': + if (*optarg == 'a' || *optarg == '1' || *optarg == '2' || *optarg == '4') + cargs.linkspeed = *optarg; + else + { + printf("ERROR: Invalid link speed %s.\n", optarg); + printf("Valid link speeds are: 'a' for Auto, '1', '2', or '4' for 1Gb, 2Gb, or 4Gb\n"); + return EINVAL; + } + break; + + case 'm': + cargs.monitorDuration = 0; + if (sscanf(optarg, "%d,%d", &cargs.monitorInterval, &cargs.monitorDuration) != 2 && + sscanf(optarg, "%d", &cargs.monitorInterval) != 1) + { + printf("ERROR: Invalid argument %s for monitoring interval (and duration).\n", optarg); + printf("Must specify a decimal number and optionally a second decimal number\n"); + return EINVAL; + } + else + { + if (cargs.monitorInterval < 0) + cargs.monitorInterval = 0; + if (cargs.monitorDuration < 0) + cargs.monitorDuration = 0; + } + break; + + case 'n': + noFlag = TRUE; + break; + + case 'p': + pArg = optarg; + break; + + case 'q': + qFlag = TRUE; + break; + + case 'r': + cargs.reset = TRUE; + break; + + case 's': + cargs.scan = TRUE; + break; + + case 't': + if (*optarg == 'a' || *optarg == '1' || *optarg == '2') + cargs.topology = *optarg; + else + { + printf("ERROR: Invalid topology %s.\n", optarg); + printf("Valid topologys are: 'a' for Auto, '1' for NL_Port, or '2' for N_Port\n"); + return EINVAL; + } + break; + + case 'u': + tagType = MPI_SCSIIO_CONTROL_UNTAGGED; + break; + + case 'v': + if (sscanf(optarg, "%d", &virtInit) != 1) + { + printf("ERROR: Invalid argument %s for virtual initiator.\n", optarg); + printf("Must specify a decimal number\n"); + return EINVAL; + } + break; + + case 'w': + wFlag++; + break; + + case 'x': + xFlag = TRUE; + break; + + case 'y': + yesFlag = TRUE; + break; + + case 'z': + cargs.linkReset = TRUE; + cargs.linkResetFlag = FALSE; + break; + + case '0': + iocMask |= (1<<0); + break; + + case '1': + iocMask |= (1<<1); + break; + + case '8': + maxLuns = 8; + break; + + default: + return EINVAL; + } + } + + if (wFlag) + { + logFile = fopen("lsiutil.log", "a"); + if (logFile) + { + fprintf(logFile, "%s: Logging started at level %d\n", logPrefix(NULL), wFlag); + } + else + { + printf("Open failure for file lsiutil.log!\n"); + perror("Error is"); + logFile = stderr; + } + } + + if (xFlag) + { + if (pArg || args || cargs.info || cargs.scan || cargs.dump || cargs.boardInfo || + cargs.linkspeed || cargs.topology || cargs.coalescing || cargs.reset || cargs.linkReset || + cargs.monitorInterval || iocMask) + { + printf("-x can be mixed with -f, -n, and -y, only\n"); + return EINVAL; + } + + if (numFileNames == 0) + { + if (optind == argc - 3) + { + while (optind < argc) + fileNames[numFileNames++] = argv[optind++]; + } + + else if (optind < argc) + { + optarg = argv[optind++]; + + while (TRUE) + { + if (numFileNames < 3) + { + fileNames[numFileNames++] = optarg; + } + else + { + printf("ERROR: At most, three filenames may be supplied\n"); + return EINVAL; + } + + optarg = strchr(optarg, ','); + if (optarg) + *optarg++ = '\0'; + else + break; + } + } + } + + while (optind < argc) + printf("%s: invalid argument -- %s\n", argv[0], argv[optind++]); + + printf("\n"); + concatenateSasFirmwareNvdata(); + return 0; + } + + if (qFlag) + { + char *name; + + if (pArg || args || cargs.info || cargs.scan || cargs.dump || cargs.boardInfo || + cargs.linkspeed || cargs.topology || cargs.coalescing || cargs.reset || cargs.linkReset || + cargs.monitorInterval || iocMask) + { + printf("-q can be mixed with -f only\n"); + return EINVAL; + } + + if (numFileNames == 0) + { + while (optind < argc) + { + optarg = argv[optind++]; + + while (TRUE) + { + name = optarg; + optarg = strchr(optarg, ','); + if (optarg) + *optarg++ = '\0'; + + queryFile(name); + + if (!optarg) + break; + } + } + } + else + { + while (optind < argc) + printf("%s: invalid argument -- %s\n", argv[0], argv[optind++]); + + for (i = 0; i < numFileNames; i++) + { + queryFile(fileNames[i]); + } + } + + return 0; + } + + numPorts = findPorts(); + + printf("\n%d MPT Port%s found\n", numPorts, numPorts == 1 ? "" : "s"); + + if (pArg) + { + optarg = pArg; + + if (numPorts) + { + t = 0; + while (sscanf(optarg, "%d%n", &i, &n) >= 1) + { + if (i <= 0) + { + cargs.numPortNums = 0; + break; + } + if (t == 1) + { + if (i < cargs.portNums[cargs.numPortNums - 1]) + { + cargs.numPortNums = 0; + break; + } + while (i > cargs.portNums[cargs.numPortNums - 1]) + { + t = cargs.portNums[cargs.numPortNums - 1] + 1; + if (t <= numPorts && cargs.numPortNums < NUM_PORTS) + { + cargs.portNums[cargs.numPortNums] = t; + cargs.numPortNums++; + } + else + break; + } + t = 0; + } + else + { + if (i <= numPorts && cargs.numPortNums < NUM_PORTS) + { + cargs.portNums[cargs.numPortNums] = i; + cargs.numPortNums++; + } + } + if (optarg[n] == '\0') + { + optarg += n; + break; + } + else if (optarg[n] == ',') + { + optarg += n + 1; + } + else if (optarg[n] == '-' && t == 0) + { + optarg += n + 1; + t = 1; + } + else + { + cargs.numPortNums = 0; + break; + } + } + if (optarg[0] != '\0') + cargs.numPortNums = 0; + if (cargs.numPortNums == 0) + { + printf("ERROR: No such port. Valid ports are:\n"); + printf("\n Port Name Chip Vendor/Type/Rev MPT Rev Firmware Rev IOC\n"); + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + if (port->notOperational) + printf("%2d. %-16s\n", i+1, port->portName); + else + printf("%2d. %-16s LSI Logic %-12s %03x %08x %x\n", + i+1, port->portName, port->chipNameRev, + port->mptVersion, port->fwVersion, port->iocNumber); + } + closePorts(numPorts); + return ENODEV; + } + } + } + + if (cargs.monitorInterval) + { + if (args || cargs.info || cargs.scan || cargs.dump || cargs.boardInfo || + cargs.linkspeed || cargs.topology || cargs.coalescing || cargs.reset || cargs.linkReset || + optind < argc) + { + printf("WARNING: -m being ignored (other options given)\n"); + } + else + { + if (numPorts) + { + MPT_PORT *ports[NUM_PORTS]; + + memset(ports, 0, sizeof ports); + if (cargs.numPortNums) + { + for (i = 0; i < cargs.numPortNums; i++) + { + ports[cargs.portNums[i]] = mptPorts[cargs.portNums[i] - 1]; + } + } + else + { + for (i = 0; i < numPorts; i++) + { + ports[i] = mptPorts[i]; + } + } + doDisplayTransferStatisticsAll(NUM_PORTS, ports, cargs.monitorInterval, cargs.monitorDuration); + closePorts(numPorts); + return 0; + } + } + } + + if ((cargs.info || cargs.scan || cargs.dump || cargs.boardInfo) && + (cargs.linkspeed || cargs.topology || cargs.coalescing || cargs.reset || cargs.linkReset)) + { + printf("ERROR: -s -i -d and -b (display options) can't be mixed\n"); + printf("with -l -t and -c (set options) or -r and -z (reset options)\n"); + closePorts(numPorts); + return EINVAL; + } + + if (cargs.info || cargs.scan || cargs.dump) + { + if (cargs.numPortNums) + { + for (i = 0; i < cargs.numPortNums; i++) + { + port = mptPorts[cargs.portNums[i] - 1]; + + printf("\n==============================================================================\n"); + if (port->notOperational) + { + printf("\n%-16s\n", port->portName); + continue; + } + + printf("\n%-16s LSI Logic %-12s MPT %03x Firmware %08x IOC %x\n", + port->portName, port->chipNameRev, port->mptVersion, port->fwVersion, port->iocNumber); + + if (cargs.info || cargs.dump) + { + printf("\n"); + showBoardInfo(port, 1); + } + + t = !cargs.info; + + if (cargs.info) + { + printf("\n"); + doPortStateSummary(port); + } + + if (cargs.scan) + { + printf("\n"); + doScanForDevices(port, t); + } + + if (cargs.dump) + { + if (t) + printf("\n"); + doDumpPortState(port, t); + } + } + } + else if (numPorts) + { + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + + printf("\n==============================================================================\n"); + if (port->notOperational) + { + printf("\n%-16s\n", port->portName); + continue; + } + + printf("\n%-16s LSI Logic %-12s MPT %03x Firmware %08x IOC %x\n", + port->portName, port->chipNameRev, port->mptVersion, port->fwVersion, port->iocNumber); + + if (cargs.info || cargs.dump) + { + printf("\n"); + showBoardInfo(port, 1); + } + + t = !cargs.info; + + if (cargs.info) + { + printf("\n"); + doPortStateSummary(port); + } + + if (cargs.scan) + { + printf("\n"); + doScanForDevices(port, t); + } + + if (cargs.dump) + { + if (t) + printf("\n"); + doDumpPortState(port, t); + } + } + } + } + else if (cargs.boardInfo) + { + if (numPorts) + { + printf("\nPort Name Seg/Bus/Dev Board Name Board Assembly Board Tracer\n"); + if (cargs.numPortNums) + { + for (i = 0; i < cargs.numPortNums; i++) + { + port = mptPorts[cargs.portNums[i] - 1]; + if (port->notOperational) + continue; + if (iocMask & (1 << port->iocNumber)) + continue; + showBoardInfo(port, 0); + } + } + else + { + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + if (port->notOperational) + continue; + if (port->iocNumber) + continue; + showBoardInfo(port, 0); + } + } + } + } + + if (cargs.linkspeed) + { + if (cargs.numPortNums) + { + for (i = 0; i < cargs.numPortNums; i++) + { + port = mptPorts[cargs.portNums[i] - 1]; + if (port->notOperational) + continue; + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + switch (cargs.linkspeed) + { + default: + case 'a': t = MPI_FCPORTPAGE1_LCONFIG_SPEED_AUTO; type = "Auto"; break; + case '1': t = MPI_FCPORTPAGE1_LCONFIG_SPEED_1GIG; type = "1 Gb"; break; + case '2': t = MPI_FCPORTPAGE1_LCONFIG_SPEED_2GIG; type = "2 Gb"; break; + case '4': t = MPI_FCPORTPAGE1_LCONFIG_SPEED_4GIG; type = "4 Gb"; break; + } + printf("Setting link speed to %s on port %d\n", type, cargs.portNums[i]); + doFcLinkSpeedValue(port, t); + } + else + { + printf("ERROR: Link speed supported only on FC ports.\n"); + } + } + } + else if (numPorts) + { + printf("ERROR: Must specify a port to set link speed. Valid ports are:\n"); + printf("\n Port Name Chip Vendor/Type/Rev MPT Rev Firmware Rev IOC\n"); + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + if (port->notOperational) + printf("%2d. %-16s\n", i+1, port->portName); + else + printf("%2d. %-16s LSI Logic %-12s %03x %08x %x\n", + i+1, port->portName, port->chipNameRev, + port->mptVersion, port->fwVersion, port->iocNumber); + } + closePorts(numPorts); + return ENODEV; + } + } + + if (cargs.topology) + { + if (cargs.numPortNums) + { + for (i = 0; i < cargs.numPortNums; i++) + { + port = mptPorts[cargs.portNums[i] - 1]; + if (port->notOperational) + continue; + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + switch (cargs.topology) + { + default: + case 'a': t = MPI_FCPORTPAGE1_TOPOLOGY_AUTO; type = "Auto"; break; + case '1': t = MPI_FCPORTPAGE1_TOPOLOGY_NLPORT; type = "NL_Port"; break; + case '2': t = MPI_FCPORTPAGE1_TOPOLOGY_NPORT; type = "N_Port"; break; + } + printf("Setting topology to %s on port %d\n", type, cargs.portNums[i]); + doFcTopologyValue(port, t); + } + else + { + printf("ERROR: Topology change supported only on FC ports.\n"); + } + } + } + else if (numPorts) + { + printf("ERROR: Must specify a port to set topology. Valid ports are:\n"); + printf("\n Port Name Chip Vendor/Type/Rev MPT Rev Firmware Rev IOC\n"); + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + if (port->notOperational) + printf("%2d. %-16s\n", i+1, port->portName); + else + printf("%2d. %-16s LSI Logic %-12s %03x %08x %x\n", + i+1, port->portName, port->chipNameRev, + port->mptVersion, port->fwVersion, port->iocNumber); + } + closePorts(numPorts); + return ENODEV; + } + } + + if (cargs.coalescing) + { + if (cargs.numPortNums) + { + for (i = 0; i < cargs.numPortNums; i++) + { + port = mptPorts[cargs.portNums[i] - 1]; + if (port->notOperational) + continue; + + if (cargs.ic_timeout != 0 && cargs.ic_depth != 0) + { + printf("Setting interrupt coalescing to timeout of %d microseconds\n", + cargs.ic_timeout); + printf("with depth of %d on port %d\n", cargs.ic_depth, cargs.portNums[i]); + } + else + printf("Disabling interrupt coalescing on port %d\n", cargs.portNums[i]); + + doInterruptCoalescingValues(port, cargs.ic_timeout, cargs.ic_depth); + } + } + else if (numPorts) + { + printf("ERROR: Must specify a port to set interrupt coalescing. Valid ports are:\n"); + printf("\n Port Name Chip Vendor/Type/Rev MPT Rev Firmware Rev IOC\n"); + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + if (port->notOperational) + printf("%2d. %-16s\n", i+1, port->portName); + else + printf("%2d. %-16s LSI Logic %-12s %03x %08x %x\n", + i+1, port->portName, port->chipNameRev, + port->mptVersion, port->fwVersion, port->iocNumber); + } + closePorts(numPorts); + return ENODEV; + } + } + + if (cargs.reset) + { + if (cargs.numPortNums) + { + for (i = 0; i < cargs.numPortNums; i++) + { + port = mptPorts[cargs.portNums[i] - 1]; + if (iocMask & (1 << port->iocNumber)) + continue; + doResetPort(port); + } + } + else if (numPorts) + { + printf("ERROR: Must specify a port to reset. Valid ports are:\n"); + printf("\n Port Name Chip Vendor/Type/Rev MPT Rev Firmware Rev IOC\n"); + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + if (port->notOperational) + printf("%2d. %-16s\n", i+1, port->portName); + else + printf("%2d. %-16s LSI Logic %-12s %03x %08x %x\n", + i+1, port->portName, port->chipNameRev, + port->mptVersion, port->fwVersion, port->iocNumber); + } + closePorts(numPorts); + return ENODEV; + } + } + + if (cargs.linkReset) + { + if (cargs.numPortNums) + { + for (i = 0; i < cargs.numPortNums; i++) + { + port = mptPorts[cargs.portNums[i] - 1]; + if (port->notOperational) + continue; + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doResetFcLink(port, cargs.linkResetFlag); + } + else + { + printf("ERROR: Link reset supported only on FC ports.\n"); + } + } + } + else if (numPorts) + { + printf("ERROR: Must specify a port to reset. Valid ports are:\n"); + printf("\n Port Name Chip Vendor/Type/Rev MPT Rev Firmware Rev IOC\n"); + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + if (port->notOperational) + printf("%2d. %-16s\n", i+1, port->portName); + else + printf("%2d. %-16s LSI Logic %-12s %03x %08x %x\n", + i+1, port->portName, port->chipNameRev, + port->mptVersion, port->fwVersion, port->iocNumber); + } + closePorts(numPorts); + return ENODEV; + } + } + + if (cargs.info || cargs.scan || cargs.dump || cargs.boardInfo || + cargs.linkspeed || cargs.topology || cargs.coalescing || cargs.reset || cargs.linkReset) + { + closePorts(numPorts); + return 0; + } + + if (cargs.numPortNums) + { + if (optind < argc) + { + while (optind < argc) + { + if (sscanf(argv[optind], "%d", &t) == 1) + { + for (i = 0; i < cargs.numPortNums; i++) + { + printf("\n Port Name Chip Vendor/Type/Rev MPT Rev Firmware Rev IOC\n"); + + port = mptPorts[cargs.portNums[i] - 1]; + updatePortInfo(port); + + if (port->notOperational) + printf("%2d. %-16s\n", cargs.portNums[i], port->portName); + else + printf("%2d. %-16s LSI Logic %-12s %03x %08x %x\n", + cargs.portNums[i], port->portName, port->chipNameRev, + port->mptVersion, port->fwVersion, port->iocNumber); + + argsCurr = args; + doPortOption(port, t); + } + } + else + printf("\n%s: invalid argument -- %s\n", argv[0], argv[optind]); + optind++; + } + } + else + { + iocMask = 0; + + for (i = 0; i < cargs.numPortNums; i++) + { + printf("\n Port Name Chip Vendor/Type/Rev MPT Rev Firmware Rev IOC\n"); + + port = mptPorts[cargs.portNums[i] - 1]; + updatePortInfo(port); + + if (port->notOperational) + printf("%2d. %-16s\n", cargs.portNums[i], port->portName); + else + printf("%2d. %-16s LSI Logic %-12s %03x %08x %x\n", + cargs.portNums[i], port->portName, port->chipNameRev, + port->mptVersion, port->fwVersion, port->iocNumber); + + argsCurr = args; + doPort(port); + } + } + + closePorts(numPorts); + return 0; + } + else if (numPorts) + { + if (optind < argc) + { + while (optind < argc) + { + if (sscanf(argv[optind], "%d", &t) == 1) + { + for (i = 0; i < numPorts; i++) + { + printf("\n Port Name Chip Vendor/Type/Rev MPT Rev Firmware Rev IOC\n"); + + port = mptPorts[i]; + updatePortInfo(port); + + if (port->notOperational) + printf("%2d. %-16s\n", i+1, port->portName); + else + printf("%2d. %-16s LSI Logic %-12s %03x %08x %x\n", + i+1, port->portName, port->chipNameRev, + port->mptVersion, port->fwVersion, port->iocNumber); + + argsCurr = args; + doPortOption(port, t); + } + } + else + printf("\n%s: invalid argument -- %s\n", argv[0], argv[optind]); + optind++; + } + + closePorts(numPorts); + return 0; + } + } + } + else + { + if (wFlag) + { + logFile = fopen("lsiutil.log", "a"); + if (logFile) + { + fprintf(logFile, "%s: Logging started at level %d\n", logPrefix(NULL), wFlag); + } + else + { + printf("Open failure for file lsiutil.log!\n"); + perror("Error is"); + logFile = stderr; + } + } + + numPorts = findPorts(); + + printf("\n%d MPT Port%s found\n", numPorts, numPorts == 1 ? "" : "s"); + } + + if (numPorts) + { + iocMask = 0; + + while (TRUE) + { + printf("\n Port Name Chip Vendor/Type/Rev MPT Rev Firmware Rev IOC\n"); + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + updatePortInfo(port); + + if (port->notOperational) + printf("%2d. %-16s\n", i+1, port->portName); + else + printf("%2d. %-16s LSI Logic %-12s %03x %08x %x\n", + i+1, port->portName, port->chipNameRev, + port->mptVersion, port->fwVersion, port->iocNumber); + } + + printf("\nSelect a device: [1-%d or 0 to quit] ", numPorts); + portNumber = getNumberAnswer(0, numPorts, -1); + + if (portNumber < 0) + continue; + + if (portNumber == 0) + break; + + doPort(mptPorts[portNumber-1]); + } + } + + closePorts(numPorts); + + return 0; +} + + +#if __sparc__ +int +getNodeInfo(di_node_t node, void *arg) +{ + int *numPorts = (int *)arg; + char *driverName; + char *pathName; + int portNumber; + char path[PATH_MAX]; + HANDLE fileHandle; + MPT_PORT *port; + + driverName = di_driver_name(node); + pathName = di_devfs_path(node); + portNumber = di_instance(node); + if (driverName != NULL && pathName != NULL && portNumber >= 0) + { + if (strcasecmp("itmpt", driverName) == 0 || + strcasecmp("itmptfc", driverName) == 0 || + strcasecmp("lsimpt", driverName) == 0 || + strcasecmp("mpt", driverName) == 0 || + strcasecmp("mpt_sas", driverName) == 0 || + strcasecmp("lsc", driverName) == 0) + { + sprintf(path, "/devices%s:devctl", pathName); + + if ((fileHandle = open(path, O_RDWR)) >= 0) + { + port = (MPT_PORT *)malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + port->portNumber = portNumber; + port->hostNumber = -1; + port->fileHandle = fileHandle; + + if (strcasecmp("mpt_sas", driverName) == 0 || strcasecmp("lsc", driverName) == 0 ) + { + /* since the global 'mpi2' is based on mptVersion, seed it with an MPI2 base value + * so it can be used until we get the real value from IOCFacts + */ + port->mptVersion = MPI2_VERSION_02_00; + port->ioctlValue = MPTIOCTL_PASS_THRU; + } + else + port->ioctlValue = SYMIOCTL_PASS_THRU_TIMEOUT; + + sprintf(port->portName, "%s%d", driverName, portNumber); + if (strstr(driverName, "fc")) + sprintf(port->pathName, "%s/fp@0,0", pathName); + else + sprintf(port->pathName, "%s", pathName); + + if (getPortInfo(port) == 1) + { + mptPorts[(*numPorts)++] = port; + } + else + { + close(fileHandle); + free(port); + } + } + } + } + + return DI_WALK_CONTINUE; +} +#endif + + +int +checkReady(MPT_PORT *port) +{ +#if DOS || EFI + HANDLE adap = port->fileHandle; + int t; + + if (mpt_verify_ready(adap) || mpt_verify_operational(adap)) + { + return 1; + } + + mpt_stop(adap, TRUE); + + if (adap->ioc_online == TRUE) + { + adap->ioc_online = mpt_verify_operational(adap); + + if (adap->ioc_online == TRUE) + { + return 1; + } + + t = mpt_get_doorbell(adap); + + printf("\n%s is not in Operational state! Doorbell is %08x\n", + port->portName, t); + if (wFlag) + fprintf(logFile, "%s: Firmware State is not Operational! Doorbell is %08x\n", + logPrefix(port), t); + + return 0; + } + + if (mpt_verify_ready(adap) || mpt_verify_operational(adap)) + { + return 1; + } + + t = mpt_get_state(adap); + + printf("\n%s (%s) is in %s state, Doorbell is %08x\n", + port->portName, port->chipNameRev, + t == MPI_IOC_STATE_RESET ? "RESET" : + t == MPI_IOC_STATE_FAULT ? "FAULT" : + "UNKNOWN", mpt_get_doorbell(adap)); + + return 0; +#else + return 1; +#endif +} + + +int +checkOperational(MPT_PORT *port, int flag) +{ +#if REGISTER_ACCESS +#if WIN32 || __linux__ || __sparc__ + U32 data; + + if (doReadRegister(port, MPI_DOORBELL_OFFSET, &data) == 1) + { + if ((data & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) + { + if (!port->notOperational) + { + port->notOperational = 1; + printf("\n%s is not in Operational state! Doorbell is %08x\n", + port->portName, data); + if (wFlag) + fprintf(logFile, "%s: Firmware State is not Operational! Doorbell is %08x\n", + logPrefix(port), data); + } + + return 0; + } + + port->notOperational = 0; + } + + return 1; +#endif +#if DOS || EFI + HANDLE adap = port->fileHandle; + + if (flag) + return mpt_verify_operational(adap); + + return 1; +#endif +#else + return 1; +#endif +} + + +int +bringOnline(MPT_PORT *port) +{ +#if DOS || EFI + if (port->fileHandle->bootloader == TRUE) + { + return 0; + } + + if (port->fileHandle->ioc_online != TRUE) + { + port->fileHandle->port_enable_needed = TRUE; + + port->fileHandle->ioc_online = mpt_restart(port->fileHandle); + } + else if (port->fileHandle->port_online == FALSE) + { + port->fileHandle->port_online = mpt_port_online(port->fileHandle); + } +#endif + + return 1; +} + + +int +findPorts(void) +{ +#if WIN32 + int status; + HKEY hKeyScsi; + HKEY hKeyPort; + const LPSTR NamesKey = TEXT("HARDWARE\\DEVICEMAP\\Scsi"); + DWORD portIndex; + DWORD portNameSize; + DWORD valueType; + DWORD driverNameSize; + char portName[16]; + char driverName[16]; + char fileName[16]; + FILETIME lastWriteTime; + int portNumber; + HANDLE fileHandle; + MPT_PORT *port; + int numPorts; + + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NamesKey, 0L, KEY_READ, &hKeyScsi); + + // if can't open this registry key, there are no scsi drivers installed + if (status != ERROR_SUCCESS) + { + printf("Couldn't get Scsi key from registry\n"); + return 0; + } + + // enumerate all SCSI ports under the Scsi key + portIndex = 0; + numPorts = 0; + while (TRUE) + { + portNameSize = sizeof portName; + status = RegEnumKeyEx(hKeyScsi, portIndex++, portName, + &portNameSize, NULL, NULL, NULL, &lastWriteTime); + + if (status != ERROR_SUCCESS) + break; + + // open this port key to check the driver name + status = RegOpenKeyEx(hKeyScsi, portName, 0L, KEY_READ, &hKeyPort); + + if (status == ERROR_SUCCESS) + { + driverNameSize = sizeof driverName; + status = RegQueryValueEx(hKeyPort, "Driver", NULL, &valueType, + driverName, &driverNameSize); + + if (status == ERROR_SUCCESS) + { + if (strcasecmp("symmpi", driverName) == 0 || + strcasecmp("lsimpt", driverName) == 0 || + strcasecmp("lsi_fc", driverName) == 0 || + strcasecmp("lsi_scsi", driverName) == 0 || + strcasecmp("lsi_sas", driverName) == 0 || + strcasecmp("lsi_sas2", driverName) == 0 || + strcasecmp("lsi_sas3", driverName) == 0 || + strcasecmp("lsi_gen2", driverName) == 0 || + strcasecmp("sas2xp86", driverName) == 0 || // new name for lsi_gen2 + strcasecmp("lsi_sss", driverName) == 0 || + strcasecmp("dcssp", driverName) == 0) + { + portNumber = atoi(&portName[10]); + sprintf(fileName, "\\\\.\\Scsi%d:", portNumber); + fileHandle = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (fileHandle != INVALID_HANDLE_VALUE) + { + port = malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + port->portNumber = portNumber; + port->fileHandle = fileHandle; + port->ioctlValue = IOCTL_SCSI_MINIPORT; + sprintf(port->portName, "Scsi Port %d", portNumber); + sprintf(fileName, "Scsi%d:", portNumber); + QueryDosDevice(fileName, port->driverName, sizeof port->driverName); + + if (getPortInfo(port) == 1) + { + mptPorts[numPorts++] = port; + } + else + { + port->ioctlValue |= 0x2000; + if (getPortInfo(port) == 1) + { + mptPorts[numPorts++] = port; + } + else + { + CloseHandle(fileHandle); + free(port); + } + } + } + } + } + + // close SCSI port key + RegCloseKey(hKeyPort); + } + } + + // close Scsi key + RegCloseKey(hKeyScsi); + + for (portNumber = 0; portNumber < 32; portNumber++) + { + sprintf(fileName, "\\\\.\\DcsMPT%d", portNumber); + fileHandle = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (fileHandle != INVALID_HANDLE_VALUE) + { + port = malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + port->portNumber = portNumber; + port->fileHandle = fileHandle; + port->ioctlValue = IOCTL_SCSI_MINIPORT; + sprintf(port->portName, "DcsMPT%d", portNumber); + + if (getPortInfo(port) == 1) + { + mptPorts[numPorts++] = port; + } + else + { + CloseHandle(fileHandle); + free(port); + } + } + } + + for (portNumber = 0; portNumber < 32; portNumber++) + { + sprintf(fileName, "\\\\.\\MPTstm%d", portNumber); + fileHandle = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (fileHandle != INVALID_HANDLE_VALUE) + { + port = malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + port->portNumber = portNumber; + port->fileHandle = fileHandle; + port->ioctlValue = IOCTL_SCSI_MINIPORT; + sprintf(port->portName, "MPTstm%d", portNumber); + + if (getPortInfo(port) == 1) + { + mptPorts[numPorts++] = port; + } + else + { + CloseHandle(fileHandle); + free(port); + } + } + } + + for (portNumber = 0; portNumber < 32; portNumber++) + { + sprintf(fileName, "\\\\.\\MPTstm%02x", portNumber); + fileHandle = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (fileHandle != INVALID_HANDLE_VALUE) + { + port = malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + port->portNumber = portNumber; + port->fileHandle = fileHandle; + port->ioctlValue = IOCTL_SCSI_MINIPORT; + sprintf(port->portName, "MPTstm%02x", portNumber); + + if (getPortInfo(port) == 1) + { + mptPorts[numPorts++] = port; + } + else + { + CloseHandle(fileHandle); + free(port); + } + } + } +#endif +#if __linux__ + int numPorts; + int status; + HANDLE fileHandle; + HANDLE fileHandle2; + HANDLE fileHandle3; + FILE *portFile; + char portName[64]; + int portNumber; + char pathName[PATH_MAX]; + MPT_PORT *port; + struct mpt_ioctl_eventquery eventquery; + struct mpt2_ioctl_eventquery eventquery2; + struct mpt_ioctl_iocinfo *iocinfo; + struct mpt_ioctl_iocinfo_rev1 *iocinfo2; + int domain = 0; + int bus = 0; + int device = 0; + int function = 0; + HANDLE pciHandle; + unsigned char config[64]; + char *p; + char *q; + char iocEntry[64]; + FILE *iocFile; + int i; + U16 deviceIdRaw; + U16 deviceId; +#if REGISTER_ACCESS + char resource[64]; + uint64_t t, ts; + off_t bar0; + off_t bar1; + off_t bar2; + size_t bar0size; + size_t bar1size; + size_t bar2size; + char portName1[64]; + char portName2[64]; + HANDLE pciHandle1; + HANDLE pciHandle2; +#endif + + if ((fileHandle = open(IOCTL_NAME, O_RDWR)) < 0) + { + if (system("/sbin/modprobe mptctl")); + if ((fileHandle = open(IOCTL_NAME, O_RDWR)) < 0) + { + if (system("/bin/mknod /dev/mptctl c 10 220")); + fileHandle = open(IOCTL_NAME, O_RDWR); + } + } + + fileHandle2 = open(IOCTL_NAME2, O_RDWR); + fileHandle3 = open(IOCTL_NAME3, O_RDWR); + + if (fileHandle < 0 && fileHandle2 < 0 && fileHandle3 < 0) + { + printf("Couldn't open " IOCTL_NAME " or " IOCTL_NAME2 " or " IOCTL_NAME3 "!\n"); + return 0; + } + + globalFileHandle = fileHandle; + globalFileHandle2 = fileHandle2; + globalFileHandle3 = fileHandle3; + + memset(&eventquery, 0, sizeof eventquery); + eventquery.hdr.maxDataSize = sizeof eventquery; + + memset(&eventquery2, 0, sizeof eventquery2); + eventquery2.hdr.max_data_size = sizeof eventquery2; + + iocinfo = (struct mpt_ioctl_iocinfo *)malloc(sizeof *iocinfo); + memset(iocinfo, 0, sizeof *iocinfo); + iocinfo->hdr.maxDataSize = sizeof *iocinfo; + + iocinfo2 = (struct mpt_ioctl_iocinfo_rev1 *)malloc(sizeof *iocinfo2); + memset(iocinfo2, 0, sizeof *iocinfo2); + iocinfo2->hdr.maxDataSize = sizeof *iocinfo2; + + numPorts = 0; + fileHandle = globalFileHandle; + if (fileHandle < 0) + fileHandle = globalFileHandle2; + if (fileHandle < 0) + fileHandle = globalFileHandle3; +probe_again: + for (portNumber = 0; portNumber < NUM_PORTS; portNumber++) + { + sprintf(portName, "/proc/mpt/ioc%d", portNumber); + portFile = fopen(portName, "r"); + if (portFile == NULL) + sprintf(portName, "ioc%d", portNumber); + else + fclose(portFile); + + eventquery.hdr.iocnum = portNumber; + eventquery2.hdr.ioc_number = portNumber; + + if ( (fileHandle == globalFileHandle2) || (fileHandle == globalFileHandle3) ) + status = ioctl(fileHandle, MPT2EVENTQUERY, &eventquery2); + else + status = ioctl(fileHandle, MPTEVENTQUERY, &eventquery); + + if (status == 0) + { + port = (MPT_PORT *)malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + /* since the global 'mpi2' is based on mptVersion, seed it with an MPI2 base value + * so it can be used until we get the real value from IOCFacts + */ + if ( (fileHandle == globalFileHandle2) || (fileHandle == globalFileHandle3) ) + port->mptVersion = MPI2_VERSION_02_00; + + port->portNumber = portNumber; + port->hostNumber = -1; + port->fileHandle = fileHandle; + strcpy(port->portName, portName); + + for (i = 0; i < 32; i++) + { + if (mpi2) + { + sprintf(pathName, "/sys/class/scsi_host/host%d/proc_name", i); + iocFile = fopen(pathName, "r"); + if (!iocFile) + continue; + p = fgets(iocEntry, sizeof iocEntry, iocFile); + fclose(iocFile); + if (!p) + continue; + if (strncmp(p, "mpt2sas", 7)) + continue; + sprintf(pathName, "/sys/class/scsi_host/host%d/unique_id", i); + iocFile = fopen(pathName, "r"); + if (!iocFile) + continue; + p = fgets(iocEntry, sizeof iocEntry, iocFile); + fclose(iocFile); + if (!p) + continue; + } + else + { + sprintf(pathName, "/proc/scsi/mptscsih/%d", i); + iocFile = fopen(pathName, "r"); + if (!iocFile) + { + sprintf(pathName, "/proc/scsi/mptfc/%d", i); + iocFile = fopen(pathName, "r"); + } + if (!iocFile) + { + sprintf(pathName, "/proc/scsi/mptsas/%d", i); + iocFile = fopen(pathName, "r"); + } + if (!iocFile) + { + sprintf(pathName, "/proc/scsi/mptspi/%d", i); + iocFile = fopen(pathName, "r"); + } + if (!iocFile) + continue; + p = fgets(iocEntry, sizeof iocEntry, iocFile); + fclose(iocFile); + if (!p) + continue; + p = strstr(iocEntry, "ioc"); + if (!p) + continue; + p += 3; + q = strstr(p, ":"); + if (!q) + continue; + q[0] = '\0'; + } + if (portNumber == atoi(p)) + { + port->hostNumber = i; + break; + } + } + + iocinfo->hdr.iocnum = portNumber; + + if (mpi2) + status = ioctl(fileHandle, MPT2IOCINFO, iocinfo); + else + status = ioctl(fileHandle, MPTIOCINFO, iocinfo); + + if (status == 0) + { + domain = iocinfo->pciInfo.segmentID; + bus = iocinfo->pciInfo.u.bits.busNumber; + device = iocinfo->pciInfo.u.bits.deviceNumber; + function = iocinfo->pciInfo.u.bits.functionNumber; + } + else + { + iocinfo2->hdr.iocnum = portNumber; + + status = ioctl(fileHandle, MPTIOCINFO2, iocinfo2); + + if (status == 0) + { + domain = 0; + bus = iocinfo->pciInfo.u.bits.busNumber; + device = iocinfo->pciInfo.u.bits.deviceNumber; + function = iocinfo->pciInfo.u.bits.functionNumber; + } + } + + if (status == 0) + { + sprintf(portName, "/proc/bus/pci/%04x:%02x/%02x.%d", + domain, bus, device, function); + + pciHandle = open(portName, O_RDWR); + + if (pciHandle < 0) + { + sprintf(portName, "/proc/bus/pci/%02x/%02x.%d", + bus, device, function); + + pciHandle = open(portName, O_RDWR); + } + + if (pciHandle >= 0) + { + if (read(pciHandle, config, sizeof config) == sizeof config) + { + deviceIdRaw = get16x(*(U16 *)&config[2]); + + /* the following three want to be set to the device ID that doesnt include ZC*/ + if ( (deviceIdRaw == MPI_MANUFACTPAGE_DEVID_53C1030ZC) || + (deviceIdRaw == MPI_MANUFACTPAGE_DEVID_1030ZC_53C1035) || + (deviceIdRaw == MPI_MANUFACTPAGE_DEVID_53C1035ZC)) + { + deviceId = deviceIdRaw & ~1; + } + else + { + deviceId = deviceIdRaw; + } + + port->deviceId = deviceId; + port->deviceIdRaw = deviceIdRaw; + +#if REGISTER_ACCESS + sprintf(portName, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/resource", + domain, bus, device, function); + + portFile = fopen(portName, "r"); + + if (portFile == NULL) + { + sprintf(portName, "/sys/bus/pci/devices/%02x:%02x.%d/resource", + bus, device, function); + + portFile = fopen(portName, "r"); + } + + if (portFile) + { + bar0 = 0; + bar1 = 0; + bar2 = 0; + bar0size = 0; + bar1size = 0; + bar2size = 0; + + if (fgets(resource, sizeof resource, portFile)) + { + if (sscanf(resource, "%llx %llx", &t, &ts) == 2) + { + if (deviceId == MPI_MANUFACTPAGE_DEVID_SAS1078) + { + bar1 = t; + bar1size = ts - t + 1; + } + else + { + bar0 = t; + bar0size = ts - t + 1; + } + } + if (fgets(resource, sizeof resource, portFile)) + { + if (sscanf(resource, "%llx %llx", &t, &ts) == 2) + { + if (deviceId == MPI_MANUFACTPAGE_DEVID_SAS1078) + { + bar0 = t; + bar0size = ts - t + 1; + } + else + { + bar1 = t; + bar1size = ts - t + 1; + } + } + if (fgets(resource, sizeof resource, portFile)) + { + if (fgets(resource, sizeof resource, portFile)) + { + if (sscanf(resource, "%llx %llx", &t, &ts) == 2) + { + bar2 = t; + bar2size = ts - t + 1; + } + } + } + } + } + + fclose(portFile); + } + else + { + if (deviceId == MPI_MANUFACTPAGE_DEVID_SAS1078) + { + bar1 = get64x( config[0x10]) & ~0xF; + bar0 = get32x(*(U32 *)&config[0x18]) & ~0xF; + } + else + { + bar0 = get32x(*(U32 *)&config[0x10]) & ~0xF; + bar1 = get64x( config[0x14]) & ~0xF; + } + bar2 = get64x( config[0x1c]) & ~0xF; + bar0size = 256; + bar1size = 256; + bar2size = 65536; + } + + port->ioPhys = bar0; + port->memPhys = bar1; + port->diagPhys = bar2; + + ioctl(pciHandle, PCIIOC_MMAP_IS_MEM); + + if (deviceId == MPI_MANUFACTPAGE_DEVID_SAS1078) + sprintf(portName1, "%s0", portName); + else + sprintf(portName1, "%s1", portName); + sprintf(portName2, "%s3", portName); + + pciHandle1 = open(portName1, O_RDWR); + if (pciHandle1) + { + errno = 0; + port->memVirt = mmap(NULL, bar1size, PROT_READ | PROT_WRITE, + MAP_SHARED, pciHandle1, 0); + if (errno) + port->memVirt = NULL; + } + + if (!port->memVirt && bar1 && bar1size) + { + errno = 0; + port->memVirt = mmap(NULL, bar1size, PROT_READ | PROT_WRITE, + MAP_SHARED, pciHandle, bar1); + if (errno) + port->memVirt = NULL; + } + + if (!port->memVirt) + port->memPhys = 0; + + pciHandle2 = open(portName2, O_RDWR); + if (pciHandle2) + { + errno = 0; + port->diagVirt = mmap(NULL, bar2size, PROT_READ | PROT_WRITE, + MAP_SHARED, pciHandle2, 0); + if (errno) + port->diagVirt = NULL; + } + + if (!port->diagVirt && bar2 && bar2size) + { + errno = 0; + port->diagVirt = mmap(NULL, bar2size, PROT_READ | PROT_WRITE, + MAP_SHARED, pciHandle, bar2); + if (errno) + port->diagVirt = NULL; + } + + if (!port->diagVirt) + port->diagPhys = 0; + +#if i386 + if (deviceId == MPI_MANUFACTPAGE_DEVID_53C1030) + { + iopl(3); + + if (!(config[0x04] & 1)) + { + config[0x04] |= 1; + lseek(pciHandle, 0x04, SEEK_SET); + write(pciHandle, config + 0x04, 1); + } + } +#endif +#endif + } + } + } + + if (getPortInfo(port) == 1) + { + mptPorts[numPorts++] = port; + + } + else + { + free(port); + } + } + } + if (fileHandle == globalFileHandle) + { + fileHandle = globalFileHandle2; + if (fileHandle >= 0) + goto probe_again; + } + if (fileHandle == globalFileHandle2) + { + fileHandle = globalFileHandle3; + if (fileHandle >= 0) + goto probe_again; + } + + free(iocinfo); + free(iocinfo2); + + if (numPorts == 0) + { + if (globalFileHandle >= 0) + close(globalFileHandle); + if (globalFileHandle2 >= 0) + close(globalFileHandle2); + if (globalFileHandle3 >= 0) + close(globalFileHandle3); + } +#endif +#if __sparc__ + int numPorts; + FILE *pathFile; + char pathEntry[PATH_MAX]; + char *o; + char *p; + char *q; + char path[PATH_MAX]; + HANDLE fileHandle; + int portNumber; + MPT_PORT *port; + int i; + int j; + int n; + DIR *dirp; + struct dirent *direntp; + char pathName[PATH_MAX]; + char linkName[PATH_MAX]; + struct stat stat; + di_node_t root_node; + + numPorts = 0; + + root_node = di_init("/", DINFOSUBTREE); + + if (root_node != DI_NODE_NIL) + { + di_walk_node(root_node, DI_WALK_CLDFIRST, &numPorts, getNodeInfo); + + di_fini(root_node); + } + + if (numPorts == 0) + { + pathFile = fopen("/etc/path_to_inst", "r"); + if (pathFile == NULL) + { + printf("Couldn't open /etc/path_to_inst!\n"); + perror("Error is"); + return 0; + } + + while (fgets(pathEntry, sizeof pathEntry, pathFile) != NULL) + { + if ((o = strstr(pathEntry, "\"itmpt\"")) == NULL && + (o = strstr(pathEntry, "\"itmptfc\"")) == NULL && + (o = strstr(pathEntry, "\"mpt\"")) == NULL) + continue; + + p = strchr(pathEntry, (int)'"'); + if (p == NULL) + continue; + p += 1; + if (strncmp(p, "/node@", 6) == 0) + { + p += 6; + p = strchr(p, '/'); + if (p == NULL) + continue; + } + q = strchr(p, '"'); + if (q == NULL) + continue; + *q = '\0'; + q += 1; + + portNumber = atoi(q); + o += 1; + q = strchr(o, '"'); + *q = '\0'; + + sprintf(path, "/devices%s:devctl", p); + if ((fileHandle = open(path, O_RDWR)) < 0) + continue; + + if (fstat(fileHandle, &stat) < 0) + continue; + + if (portNumber != MINOR2INST(getminor(stat.st_rdev))) + continue; + + port = (MPT_PORT *)malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + port->portNumber = portNumber; + port->hostNumber = -1; + port->fileHandle = fileHandle; + port->ioctlValue = SYMIOCTL_PASS_THRU_TIMEOUT; + sprintf(port->portName, "%s%d", o, portNumber); + if (strstr(o, "fc")) + sprintf(port->pathName, "%s/fp@0,0", p); + else + sprintf(port->pathName, "%s", p); + + if (getPortInfo(port) == 1) + { + mptPorts[numPorts++] = port; + } + else + { + close(fileHandle); + free(port); + } + } + + fclose(pathFile); + } + + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + + dirp = opendir("/dev/cfg/"); + while (dirp) + { + direntp = readdir(dirp); + if (!direntp) + break; + strcpy(pathName, "/dev/cfg/"); + strcat(pathName, direntp->d_name); + n = readlink(pathName, linkName, sizeof linkName); + if (n <= 0) + continue; + linkName[n] = '\0'; + p = strstr(linkName, "/devices"); + if (!p) + continue; + p += 8; + q = strrchr(p, ':'); + if (q) + *q = '\0'; + if (strcmp(port->pathName, p) == 0) + { + port->hostNumber = atoi(direntp->d_name + 1); + break; + } + } + if (dirp) + closedir(dirp); + } + + for (i = 0; i < numPorts - 1; i++) + { + for (j = i + 1; j < numPorts; j++) + { + if (strcmp(mptPorts[i]->portName, mptPorts[j]->portName) > 0) + { + port = mptPorts[i]; + mptPorts[i] = mptPorts[j]; + mptPorts[j] = port; + } + } + } +#endif +#if __irix__ + int numPorts; + HANDLE fileHandle; + char portName[24]; + int portNumber; + MPT_PORT *port; + + numPorts = 0; + for (portNumber = 0; portNumber < NUM_PORTS; portNumber++) + { + sprintf(portName, "/hw/scsi_ctlr/%d/bus", portNumber); + if ((fileHandle = open(portName, O_RDWR)) < 0) + continue; + + port = (MPT_PORT *)malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + port->portNumber = portNumber; + port->fileHandle = fileHandle; + sprintf(port->portName, "scsi_ctlr%d", portNumber); + + if (getPortInfo(port) == 1) + { + mptPorts[numPorts++] = port; + } + else + { + free(port); + } + } +#endif +#if __alpha__ + int numPorts; + HANDLE fileHandle; + int portNumber; + MPT_PORT *port; + + if ((fileHandle = open("/dev/itmpt", O_RDWR)) < 0) + { + printf("Couldn't open /dev/itmpt!\n"); + perror("Error is"); + return 0; + } + + globalFileHandle = fileHandle; + + numPorts = 0; + for (portNumber = 0; portNumber < 8; portNumber++) + { + port = (MPT_PORT *)malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + port->portNumber = portNumber; + port->fileHandle = fileHandle; + sprintf(port->portName, "itmpt%d", portNumber); + + if (getPortInfo(port) == 1) + { + mptPorts[numPorts++] = port; + } + else + { + free(port); + } + } + + if (numPorts == 0) + close(fileHandle); +#endif +#if DOS + int numPorts; + HANDLE adap; + MPT_PORT *port; + U8 pciMajorRevision; + U8 pciMinorRevision; + U8 maxPciBusNumber; + U8 busNumber; + U8 deviceNumber; + U8 functionNumber; + U8 deviceFunction; + U16 vendorId; + U16 deviceIdRaw; + U16 deviceId; + U8 command; + int io; + int mem; + int diagmem; + int t; + + if (PciIsBiosPresent(&pciMajorRevision, &pciMinorRevision, &maxPciBusNumber) != 1) + { + printf("\nThe PCI System BIOS is not present!\n"); + return 0; + } + + numPorts = 0; + for (busNumber = 0; busNumber <= maxPciBusNumber; busNumber++) + { + for (deviceNumber = 0; deviceNumber < 32; deviceNumber++) + { + for (functionNumber = 0; functionNumber < 8; functionNumber++) + { + deviceFunction = (deviceNumber << 3) | functionNumber; + + // have to do this twice for some PCI BIOS implementations! + + vendorId = PciReadConfigWord(busNumber, deviceFunction, PCI_CONFIG_VENDOR_ID); + deviceIdRaw = PciReadConfigWord(busNumber, deviceFunction, PCI_CONFIG_DEVICE_ID); + + vendorId = PciReadConfigWord(busNumber, deviceFunction, PCI_CONFIG_VENDOR_ID); + deviceIdRaw = PciReadConfigWord(busNumber, deviceFunction, PCI_CONFIG_DEVICE_ID); + + if (vendorId != MPI_MANUFACTPAGE_VENDORID_LSILOGIC) + break; + + /* the following three want to be set to the device ID that doesnt include ZC*/ + if ( (deviceIdRaw == MPI_MANUFACTPAGE_DEVID_53C1030ZC) || + (deviceIdRaw == MPI_MANUFACTPAGE_DEVID_1030ZC_53C1035) || + (deviceIdRaw == MPI_MANUFACTPAGE_DEVID_53C1035ZC)) + { + deviceId = deviceIdRaw & ~1; + } + else + { + deviceId = deviceIdRaw; + } + + + if (deviceId == MPI_MANUFACTPAGE_DEVICEID_FC909 || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC919 || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC929 || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC919X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC929X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC939X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC949X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC949E || + deviceId == MPI_MANUFACTPAGE_DEVID_53C1030 || + deviceId == MPI_MANUFACTPAGE_DEVID_1030_53C1035 || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1064 || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1064E || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1066 || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1066E || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1068 || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1068E || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1078 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2004 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2008 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2108_1 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2108_2 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2108_3 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2116_1 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2116_2 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_1 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_2 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_3 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_4 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_5 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_6 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2308_1 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2308_2 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2308_3 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3004 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3008 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3108_1 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3108_2 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3108_5 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3108_6 || + deviceId == MPI2_MFGPAGE_DEVID_SSS6200 ) + { + adap = malloc(sizeof *adap); + + memset(adap, 0, sizeof *adap); + + if (deviceId == MPI_MANUFACTPAGE_DEVID_SAS1078) + { + io = PCI_CONFIG0_BASE_ADDRESS2; + mem = PCI_CONFIG0_BASE_ADDRESS0; + diagmem = PCI_CONFIG0_BASE_ADDRESS3; + } + else + { + io = PCI_CONFIG0_BASE_ADDRESS0; + mem = PCI_CONFIG0_BASE_ADDRESS1; + diagmem = PCI_CONFIG0_BASE_ADDRESS3; + } + + if (deviceId != MPI_MANUFACTPAGE_DEVID_53C1030) + { + io = mem; // no need to use I/O space, so don't (it's safer not to) + } + + adap->bus_number = busNumber; + adap->device_function = deviceFunction; + adap->revision_id = PciReadConfigByte(busNumber, deviceFunction, + PCI_CONFIG_REVISION_ID); + adap->io = io; + adap->mem = mem; + adap->diagmem = diagmem; + + adap->io_addr = PciReadConfigDword(busNumber, deviceFunction, io) & ~0xF; + adap->mem_addr = PciReadConfigDword(busNumber, deviceFunction, mem) & ~0xF; + PciWriteConfigDword(busNumber, deviceFunction, mem, 0xFFFFFFFF); + adap->mem_size = ~(PciReadConfigDword(busNumber, deviceFunction, mem) & ~0xF) + 1; + PciWriteConfigDword(busNumber, deviceFunction, mem, adap->mem_addr); + adap->mem_virt = MapPhysicalToLinear(adap->mem_addr, adap->mem_size); + adap->diagmem_addr = PciReadConfigDword(busNumber, deviceFunction, diagmem) & ~0xF; + PciWriteConfigDword(busNumber, deviceFunction, diagmem, 0xFFFFFFFF); + adap->diagmem_size = ~(PciReadConfigDword(busNumber, deviceFunction, diagmem) & ~0xF) + 1; + PciWriteConfigDword(busNumber, deviceFunction, diagmem, adap->diagmem_addr); + adap->diagmem_virt = MapPhysicalToLinear(adap->diagmem_addr, adap->diagmem_size); + + PtrAllocateContiguousMemory(sizeof(mpt_shared_t), &adap->shared_contig_mem); + + command = PciReadConfigByte(busNumber, deviceFunction, PCI_CONFIG_COMMAND); + command |= PCI_COMMAND_IO; + command |= PCI_COMMAND_MEMORY; + command |= PCI_COMMAND_BUS_MASTER; + PciWriteConfigByte(busNumber, deviceFunction, PCI_CONFIG_COMMAND, command); + + port = (MPT_PORT *)malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + port->portNumber = (busNumber << 8) | deviceFunction; + port->fileHandle = adap; + sprintf(port->portName, "%02x/%02x/%d", busNumber, deviceNumber, functionNumber); + + adap->port = port; + adap->name = port->portName; + adap->vendor_id = vendorId; + adap->device_id = deviceId; + adap->shared = adap->shared_contig_mem.PtrContiguous; + adap->shared_ba = adap->shared_contig_mem.PhyPtrContiguous; + adap->max_targets = 256; + adap->restart_needed = FALSE; + adap->bus_reset_needed = FALSE; + + memset(adap->shared, 0, sizeof(mpt_shared_t)); + + port->deviceIdRaw = deviceIdRaw; + port->deviceId = deviceId; + port->revisionId = adap->revision_id; + port->iocNumber = functionNumber; + getChipName(port); + + if (functionNumber == 1) + { + MPT_PORT *partner_port = mptPorts[numPorts - 1]; + HANDLE partner_adap = partner_port->fileHandle; + + adap->partner_adap = partner_adap; + partner_adap->partner_adap = adap; + + adap->fw_image = partner_adap->fw_image; + } + + if (mpt_verify_enabled(adap) && + (mpt_verify_ready(adap) || mpt_verify_operational(adap))) + { + getPortInfo(port); + } + else + { + t = mpt_get_state(adap); + + printf("\n%s (%s) is in %s state, Doorbell is %08x\n", + port->portName, port->chipNameRev, + t == MPI_IOC_STATE_RESET ? "RESET" : + t == MPI_IOC_STATE_FAULT ? "FAULT" : + "UNKNOWN", mpt_get_doorbell(adap)); + } + + mptPorts[numPorts++] = port; + } + else + break; + } + } + } +#endif +#if EFI + EFI_DEVICE_PATH_PROTOCOL *ourDevicePath; + EFI_DEVICE_PATH_PROTOCOL *pciDevicePath; + EFI_STATUS status; + EFI_HANDLE handle; + EFI_HANDLE *handles; + UINTN numHandles; + EFI_PCI_IO_PROTOCOL *pciIo; + PCI_TYPE00 pci; + int i; + int numPorts; + HANDLE adap; + MPT_PORT *port; + UINTN segmentNumber; + UINTN busNumber; + UINTN deviceNumber; + UINTN functionNumber; + U8 deviceFunction; + U16 vendorId; + U16 deviceIdRaw; + U16 deviceId; + int io; + int mem; + int diagmem; + U32 bar; + U32 data; + UINTN buffer_size; + void *buffer; + mpt_bus_addr_t buffer_dma; + void *buffer_mapping; + U32 actualImageLen; + int t; + + status = BS->HandleProtocol(gLoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, &ourDevicePath); + if (EFI_ERROR(status)) + return 0; + + status = BS->LocateHandleBuffer(ByProtocol, &gEfiPciIoProtocolGuid, + NULL, &numHandles, &handles); + if (EFI_ERROR(status)) + return 0; + + numPorts = 0; + for (i = 0; i < (int)numHandles; i++) + { + handle = handles[i]; + + status = BS->OpenProtocol(handle, &gEfiPciIoProtocolGuid, + &pciIo, gImageHandle, handle, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + if (EFI_ERROR(status)) + continue; + + status = pciIo->Pci.Read(pciIo, EfiPciIoWidthUint8, 0, + sizeof pci, &pci); + if (EFI_ERROR(status)) + { + BS->CloseProtocol(handle, &gEfiPciIoProtocolGuid, gImageHandle, handle); + continue; + } + + vendorId = pci.Hdr.VendorId; + deviceIdRaw = pci.Hdr.DeviceId; + /* the following three want to be set to the device ID that doesnt include ZC*/ + if ( (deviceIdRaw == MPI_MANUFACTPAGE_DEVID_53C1030ZC) || + (deviceIdRaw == MPI_MANUFACTPAGE_DEVID_1030ZC_53C1035) || + (deviceIdRaw == MPI_MANUFACTPAGE_DEVID_53C1035ZC)) + { + deviceId = deviceIdRaw & ~1; + } + else + { + deviceId = deviceIdRaw; + } + + + status = BS->HandleProtocol(handle, &gEfiDevicePathProtocolGuid, &pciDevicePath); + if (EFI_ERROR(status)) + { + BS->CloseProtocol(handle, &gEfiPciIoProtocolGuid, gImageHandle, handle); + continue; + } + + if (vendorId != MPI_MANUFACTPAGE_VENDORID_LSILOGIC) + { + BS->CloseProtocol(handle, &gEfiPciIoProtocolGuid, gImageHandle, handle); + continue; + } + + if (deviceId == MPI_MANUFACTPAGE_DEVICEID_FC909 || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC919 || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC929 || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC919X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC929X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC939X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC949X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC949E || + deviceId == MPI_MANUFACTPAGE_DEVID_53C1030 || + deviceId == MPI_MANUFACTPAGE_DEVID_1030_53C1035 || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1064 || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1064E || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1066 || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1066E || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1068 || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1068E || + deviceId == MPI_MANUFACTPAGE_DEVID_SAS1078 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2004 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2008 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2108_1 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2108_2 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2108_3 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2116_1 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2116_2 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_1 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_2 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_3 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_4 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_5 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2208_6 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2308_1 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2308_2 || + deviceId == MPI2_MFGPAGE_DEVID_SAS2308_3 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3004 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3008 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3108_1 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3108_2 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3108_5 || + deviceId == MPI25_MFGPAGE_DEVID_SAS3108_6 || + deviceId == MPI2_MFGPAGE_DEVID_SSS6200 ) + { + adap = malloc(sizeof *adap); + + memset(adap, 0, sizeof *adap); + + if (deviceId == MPI_MANUFACTPAGE_DEVID_SAS1078) + { + io = 2; + mem = 0; + diagmem = 3; + } + else + { + io = 0; + mem = 1; + diagmem = 3; + } + + if (deviceId != MPI_MANUFACTPAGE_DEVID_53C1030) + { + io = mem; // no need to use I/O space, so don't (it's safer not to) + } + + pciIo->GetLocation(pciIo, &segmentNumber, &busNumber, &deviceNumber, &functionNumber); + + deviceFunction = ((U8)deviceNumber << 3) | (U8)functionNumber; + + adap->handle = handle; + adap->pci_io = pciIo; + + adap->segment_number = (U8)segmentNumber; + adap->bus_number = (U8)busNumber; + adap->device_function = deviceFunction; + adap->revision_id = pci.Hdr.RevisionID; + adap->io = io; + adap->mem = mem; + adap->diagmem = diagmem; + + data = 0xFFFFFFFF; + pciIo->Pci.Read(pciIo, EfiPciIoWidthUint32, 0x10 + diagmem * 4, 1, &bar); + pciIo->Pci.Write(pciIo, EfiPciIoWidthUint32, 0x10 + diagmem * 4, 1, &data); + pciIo->Pci.Read(pciIo, EfiPciIoWidthUint32, 0x10 + diagmem * 4, 1, &data); + pciIo->Pci.Write(pciIo, EfiPciIoWidthUint32, 0x10 + diagmem * 4, 1, &bar); + + adap->diagmem_size = ~(data & ~0xF) + 1; + + status = pciIo->Attributes(pciIo, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IO | + EFI_PCI_IO_ATTRIBUTE_MEMORY | + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | + EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE, NULL); + + if (status == EFI_UNSUPPORTED) + { + status = pciIo->Attributes(pciIo, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IO | + EFI_PCI_IO_ATTRIBUTE_MEMORY | + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL); + } + + if (EFI_ERROR(status)) + { + BS->CloseProtocol(handle, &gEfiPciIoProtocolGuid, gImageHandle, handle); + continue; + } + + status = pciIo->AllocateBuffer(pciIo, 0, EfiBootServicesData, + EFI_SIZE_TO_PAGES(sizeof(mpt_shared_t)), &buffer, 0); + if (EFI_ERROR(status)) + { + BS->CloseProtocol(handle, &gEfiPciIoProtocolGuid, gImageHandle, handle); + continue; + } + + buffer_size = sizeof(mpt_shared_t); + if (pciIo->Map) + { + status = pciIo->Map(pciIo, EfiPciIoOperationBusMasterCommonBuffer, + buffer, &buffer_size, &buffer_dma, &buffer_mapping); + } + else + { + buffer_dma = (mpt_bus_addr_t)buffer; + buffer_mapping = NULL; + } + + adap->buffer_mapping = buffer_mapping; + + port = (MPT_PORT *)malloc(sizeof *port); + + memset(port, 0, sizeof *port); + + port->portNumber = ((U8)segmentNumber << 16) | ((U8)busNumber << 8) | deviceFunction; + port->fileHandle = adap; + sprintf(port->portName, "%02x/%02x/%02x/%d", segmentNumber, busNumber, deviceNumber, functionNumber); + + adap->port = port; + adap->name = port->portName; + adap->vendor_id = vendorId; + adap->device_id = deviceId; + adap->shared = buffer; + adap->shared_ba = buffer_dma; + adap->max_targets = 256; + adap->restart_needed = FALSE; + adap->bus_reset_needed = FALSE; + + memset(adap->shared, 0, sizeof(mpt_shared_t)); + + port->deviceIdRaw = deviceIdRaw; + port->deviceId = deviceId; + port->revisionId = adap->revision_id; + port->iocNumber = (U8)functionNumber; + getChipName(port); + + if (functionNumber == 1) + { + MPT_PORT *partner_port = mptPorts[numPorts - 1]; + HANDLE partner_adap = partner_port->fileHandle; + + adap->partner_adap = partner_adap; + partner_adap->partner_adap = adap; + + adap->fw_image = partner_adap->fw_image; + adap->loaddevice = partner_adap->loaddevice; + } + + if (memcmp(pciDevicePath, ourDevicePath, 12+6) == 0) + { + adap->loaddevice = TRUE; + if (adap->partner_adap) + adap->partner_adap->loaddevice = TRUE; + } + + if (mpt_verify_enabled(adap) && + (mpt_verify_ready(adap) || mpt_verify_operational(adap))) + { + getPortInfo(port); + + if (port->flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) + { + if (adap->fw_image == NULL && port->fwImageSize != 0) + { + buffer = malloc(port->fwImageSize); + + if (doFwUpload(port, MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM, + buffer, port->fwImageSize, 0, &actualImageLen) == 1) + { + adap->fw_image = buffer; + adap->fw_image_size = actualImageLen; + + if (actualImageLen != port->fwImageSize) + printf("\nFW_UPLOAD of IOC_MEM returned %d bytes (expected %d bytes)\n", + actualImageLen, port->fwImageSize); + } + else + { + printf("\nFW_UPLOAD of IOC_MEM failed!\n"); + free(buffer); + } + } + } + } + else + { + t = mpt_get_state(adap); + + printf("\n%s (%s) is in %s state, Doorbell is %08x\n", + port->portName, port->chipNameRev, + t == MPI_IOC_STATE_RESET ? "RESET" : + t == MPI_IOC_STATE_FAULT ? "FAULT" : + "UNKNOWN", mpt_get_doorbell(adap)); + } + + mptPorts[numPorts++] = port; + } + } + + if (numHandles) + FreePool(handles); +#endif + + if (just) + { + int i; + int j; + + for (i = 0, j = 0; i < numPorts; i++) + { + port = mptPorts[i]; + mptPorts[j] = port; + + if (port->mptVersion == 0) + continue; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (just & JUST_FC) + { + j++; + continue; + } + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + if (just & JUST_SCSI) + { + j++; + continue; + } + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (just & JUST_SAS) + { + j++; + continue; + } + } + + closePort(port); + } + + numPorts = j; + } + + return numPorts; +} + + +int +closePorts(int numPorts) +{ + MPT_PORT *port; + int i; + + for (i = 0; i < numPorts; i++) + { + port = mptPorts[i]; + + if (port) + closePort(port); + } + +#if __linux__ || __alpha__ + if (globalFileHandle >= 0) + close(globalFileHandle); + if (globalFileHandle2 >= 0) + close(globalFileHandle2); +#endif + + if (osDeviceState) + free(osDeviceState); + +#if __sparc__ + if (scsi_vhci_fd >= 0) + close(scsi_vhci_fd); + + if (dev_rdsk_count) + free(dev_rdsk_cache); + + if (dev_rmt_count) + free(dev_rmt_cache); + + if (dev_es_count) + free(dev_es_cache); +#endif + + if (logFile) + { + fprintf(logFile, "%s: Logging ended\n", logPrefix(NULL)); + fclose(logFile); + } + + return 1; +} + + +int +closePort(MPT_PORT *port) +{ +#if DOS || EFI + HANDLE adap; +#endif + +#if WIN32 + CloseHandle(port->fileHandle); +#endif +#if __sparc__ || __irix__ + close(port->fileHandle); +#endif +#if DOS + adap = port->fileHandle; + + mpt_stop(adap, FALSE); + if (adap->fw_image != NULL && adap->fw_image_size != 0) + free(adap->fw_image); + UnmapPhysicalToLinear(adap->mem_addr); + UnmapPhysicalToLinear(adap->diagmem_addr); + FreeContiguousMemory(adap->shared_contig_mem.PtrFree); + free(adap); +#endif +#if EFI + adap = port->fileHandle; + + if (adap->disconnected == TRUE || adap->loaddevice == FALSE || + ((port->flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) && adap->fw_image != NULL)) + { + adap->loaddevice = FALSE; + mpt_stop(adap, FALSE); + } + if (adap->fw_image != NULL && adap->fw_image_size != 0) + free(adap->fw_image); + if (adap->pci_io->Unmap && adap->buffer_mapping) + adap->pci_io->Unmap(adap->pci_io, adap->buffer_mapping); + adap->pci_io->FreeBuffer(adap->pci_io, EFI_SIZE_TO_PAGES(sizeof(mpt_shared_t)), adap->shared); + BS->CloseProtocol(adap->handle, &gEfiPciIoProtocolGuid, gImageHandle, adap->handle); + if (adap->disconnected == TRUE) + BS->ConnectController(adap->handle, NULL, NULL, TRUE); + free(adap); +#endif + free(port->chipName); + free(port->chipNameRev); + free(port); + + return 1; +} + + +int +getFileName(char *buf, int len, FILE *file, char *fileString, int fileType) +{ + int n; + + if (numFileNames > fileType && strcmp(fileNames[fileType], "?") != 0) + { + strncpy(buf, fileNames[fileType], len); + } + else + { + printf("Enter %s filename: ", fileString); + + if (fgets(buf, len, file) == NULL) + exit(0); + } + + if (file == stdin) + lines = 0; + + buf[len - 1] = '\0'; + n = (int)strlen(buf); + + while (n != 0 && (buf[n-1] == ' ' || buf[n-1] == '\n')) + buf[--n] = '\0'; + + return n; +} + + +int +getString(char *buf, int len, FILE *file) +{ + int n; + + if (fgets(buf, len, file) == NULL) + exit(0); + + if (file == stdin) + lines = 0; + + buf[len - 1] = '\0'; + n = (int)strlen(buf); + + while (n != 0 && (buf[n-1] == ' ' || buf[n-1] == '\n')) + buf[--n] = '\0'; + + return n; +} + + +int +getStringFromArgs(char *buf, int len, FILE *file) +{ + int n; + char c; + + if (argsCurr == NULL) + return getString(buf, len, file); + + n = 0; + while (TRUE) + { + c = argsCurr[n]; + + if (c == '\0' || c == ',') + break; + + if (n < len - 1) + buf[n++] = c; + } + buf[n] = '\0'; + + if (c == '\0') + argsCurr = NULL; + else + argsCurr += n + 1; + + printf("%s\n", buf); + + return n; +} + + +int +getYesNoAnswer(int defvalue) +{ + char buf[64]; + int n; + + n = getStringFromArgs(buf, sizeof buf, stdin); + + if (n == 0) + return defvalue; + + if (strncasecmp(buf, "no", n) == 0) + return 0; + + if (strncasecmp(buf, "yes", n) == 0) + return 1; + + return defvalue; +} + + +int +getNumberAnswer(int low, int high, int defvalue) +{ + char buf[64]; + int i; + int n; + int answer; + + while (TRUE) + { + n = getStringFromArgs(buf, sizeof buf, stdin); + + if (n == 0) + return defvalue; + + if (defvalue == -999) + { + if (strncasecmp(buf, "expert", n) == 0) + { + if (expert) + printf("\nDisabled expert mode in menus\n"); + else + printf("\nEnabled expert mode in menus\n"); + expert = !expert; + return defvalue; + } + + if (strncasecmp(buf, "paged", n) == 0) + { + if (paged) + { + printf("\nDisabled paged mode\n"); + paged = 0; + } + else + { + printf("\nEnabled paged mode, 24 lines\n"); + paged = 22; + } + return 999; + } + + if (sscanf(buf, "p%d", &i) == 1) + { + if (i >= 4) + { + printf("\nEnabled paged mode, %d lines\n", i); + paged = i - 2; + } + else + { + printf("\nDisabled paged mode\n"); + paged = 0; + } + return 999; + } + + if (strncasecmp(buf, "wwwwwwww", n) == 0) + { + if (wFlag) + { + wFlag = 0; + printf("\nDisabled logging\n"); + fprintf(logFile, "%s: Logging ended\n", logPrefix(NULL)); + fclose(logFile); + logFile = NULL; + } + else + { + wFlag = n; + printf("\nEnabled logging (level %d)\n", wFlag); + logFile = fopen("lsiutil.log", "a"); + if (logFile) + { + fprintf(logFile, "%s: Logging started at level %d\n", logPrefix(NULL), wFlag); + } + else + { + printf("Open failure for file lsiutil.log!\n"); + perror("Error is"); + logFile = stderr; + } + } + return 999; + } + + if (strncasecmp(buf, "g", n) == 0) + { + gFlag = !gFlag; + return 999; + } + + if (strncasecmp(buf, "k", n) == 0) + { + kFlag = !kFlag; + return 999; + } + } + else if (defvalue == -888) + { + if (strncasecmp(buf, "all", n) == 0) + { + return 888; + } + } + + for (i = 0; i < n; i++) + if (!isdigit((int)buf[i])) + break; + + if (i == n) + { + if (sscanf(buf, "%d", &answer) == 1) + if (answer >= low && answer <= high) + return answer; + } + + printf("Invalid answer, try again: "); + } +} + + +int +getNumberAnswerHex(int low, int high, int defvalue) +{ + char buf[64]; + int i; + int n; + int answer; + + while (TRUE) + { + n = getStringFromArgs(buf, sizeof buf, stdin); + + if (n == 0) + return defvalue; + + for (i = 0; i < n; i++) + if (!isxdigit((int)buf[i])) + break; + + if (i == n) + { + if (sscanf(buf, "%x", &answer) == 1) + if (answer >= low && answer <= high) + return answer; + } + + printf("Invalid answer, try again: "); + } +} + + +int +getHexNumberAnswer(U32 *value) +{ + char buf[64]; + int i; + int n; + U32 answer; + + while (TRUE) + { + n = getStringFromArgs(buf, sizeof buf, stdin); + + if (n == 0) + return 0; + + for (i = 0; i < n; i++) + if (!isxdigit((int)buf[i])) + break; + + if (i == n) + { + if (sscanf(buf, "%x", &answer) == 1) + { + *value = answer; + return 1; + } + } + + printf("Invalid answer, try again: "); + } +} + + +int +getHexDoubleNumberAnswer(U32 *value1, U32 *value2) +{ + char buf[64]; + int i; + int n; + U32 answer1; + U32 answer2; + + while (TRUE) + { + n = getStringFromArgs(buf, sizeof buf, stdin); + + if (n == 0) + return 0; + + if (n == 16) + { + for (i = 0; i < n; i++) + if (!isxdigit((int)buf[i])) + break; + + if (i == n) + { + if (sscanf(buf, "%8x%8x", &answer1, &answer2) == 2) + { + *value1 = answer1; + *value2 = answer2; + return 1; + } + } + } + + printf("Invalid answer, try again: "); + } +} + + +int +parseHexNumberChange(U32 *value) +{ + char buf[64]; + int i; + int j; + int k; + int n; + U32 answer; + int skip; + U32 shift = 0; + U32 mask = 0xffffffff; + U32 oldvalue; + U32 newvalue; + + while (TRUE) + { + skip = 0; + shift = 0; + mask = 0xffffffff; + + n = getStringFromArgs(buf, sizeof buf, stdin); + + if (n == 0) + return 0; + + if (sscanf(buf, "word%d=%n", &i, &k) == 1) + { + if (i <= 1) + { + skip = k; + shift = i * 16; + mask = 0xffff; + } + } + else if (sscanf(buf, "byte%d=%n", &i, &k) == 1) + { + if (i <= 3) + { + skip = k; + shift = i * 8; + mask = 0xff; + } + } + else if (sscanf(buf, "bit%d=%n", &i, &k) == 1) + { + if (i <= 31) + { + skip = k; + shift = i; + mask = 0x1; + } + } + else if (sscanf(buf, "bits%d:%d=%n", &i, &j, &k) == 2) + { + if (i <= 31 && i >= j) + { + skip = k; + shift = j; + mask = 0xffffffff >> (31 - i + j); + } + } + + for (i = skip; i < n; i++) + if (!isxdigit((int)buf[i])) + break; + + if (i == n) + { + if (sscanf(buf + skip, "%x", &answer) == 1) + { + if ((answer & mask) == answer) + { + oldvalue = *value; + newvalue = (oldvalue & ~(mask << shift)) | (answer << shift); + if (skip) + printf("Old value was %08x, new value is %08x\n", oldvalue, newvalue); + *value = newvalue; + return 1; + } + } + } + + printf("Invalid answer, try again: "); + } +} + + +int +readFile(char *name, unsigned char **outBuf, int *outLen) +{ + int file; + struct stat stat; + unsigned char *buf = NULL; + int len; + int t; + + file = open(name, O_RDONLY | O_BINARY); + if (file < 0) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + + t = fstat(file, &stat); + if (t < 0) + { + printf("Couldn't get size of file %s\n", name); + perror("Error is"); + close(file); + return 0; + } + + len = (int)stat.st_size; + + buf = (unsigned char *)malloc(len + 1); + + t = read(file, buf, len); + if (t != len) + { + printf("Read failed for file %s\n", name); + perror("Error is"); + free(buf); + close(file); + return 0; + } + + close(file); + + *outBuf = buf; + *outLen = len; + + buf[len] = 0; + + return 1; +} + + +int +queryFile(char *name) +{ + unsigned char *imageBuf = NULL; + int imageLen; + MpiFwHeader_t *fwHeader; + U32 checksum; + int i; + + if (readFile(name, &imageBuf, &imageLen) == 1) + { + + printf("\nQuerying file %s...\n", name); + + printWhatString("This", imageBuf, imageLen); + + fwHeader = (pMpiFwHeader_t)imageBuf; + + if ((get32(fwHeader->Signature0) == MPI_FW_HEADER_SIGNATURE_0 && + get32(fwHeader->Signature1) == MPI_FW_HEADER_SIGNATURE_1 && + get32(fwHeader->Signature2) == MPI_FW_HEADER_SIGNATURE_2) || + (get32(fwHeader->Signature0) == MPI2_FW_HEADER_SIGNATURE0 && + get32(fwHeader->Signature1) == MPI2_FW_HEADER_SIGNATURE1 && + get32(fwHeader->Signature2) == MPI2_FW_HEADER_SIGNATURE2)) + { + checksum = 0; + for (i = 0; i < imageLen / 4; i++) + checksum += get32x(((U32 *)imageBuf)[i]); + + if (checksum != 0) + printf("\nThis image's checksum (%08x) is invalid!\n", checksum); + } + + free(imageBuf); + } + + return 1; +} + + +int +printWhatString(char *type, unsigned char *buf, int len) +{ + int i; + int j; + char c = 0; + + for (i = 0; i < len - 3; i++) + if (buf[i] == '@' && buf[i+1] == '(' && buf[i+2] == '#' && buf[i+3] == ')') + break; + + if (i >= len - 3) + { + if (buf[1] == 0xaa && buf[0] == 0x55) + { + PCIR *pcir; + int n; + unsigned short rev, rev1; + + n = (buf[0x19]<<8) + buf[0x18]; + + if (n + (int)sizeof *pcir < len) + { + pcir = (PCIR *)(buf + n); + + if (pcir->signature[0] == 'P' && + pcir->signature[1] == 'C' && + pcir->signature[2] == 'I' && + pcir->signature[3] == 'R') + { + if (pcir->type == 1) /* maybe Sun FCode? */ + { + for (i = 0; i < len; i++) + if (buf[i] == 0x12 && buf[i+2] == 'L' && buf[i+3] == 'S' && buf[i+4] == 'I') + break; + + if (i < len) + { + j = i + buf[i+1] + 2; + + c = buf[j]; + + buf[j] = '\0'; + + printf("%s image's version is %s\n", type, buf + i + 2); + + buf[j] = c; + + return len; + } + } + if (pcir->type == 3 && + buf[5] == 0x0e && buf[4] == 0xf1) /* "efi", how cute */ + { + /* SAS2 stored EFI version in 16 bits of imageRevision */ + /* SAS3 stored EFI version in imageRevision and reserved field, similar to Legacy BIOS */ + /* this is to allow a 32-bit version string */ + + if ((pcir->deviceId == MPI25_MFGPAGE_DEVID_SAS3004) || /* SAS3 Controllers */ + (pcir->deviceId == MPI25_MFGPAGE_DEVID_SAS3008) || + (pcir->deviceId == MPI25_MFGPAGE_DEVID_SAS3108_1) || + (pcir->deviceId == MPI25_MFGPAGE_DEVID_SAS3108_2) || + (pcir->deviceId == MPI25_MFGPAGE_DEVID_SAS3108_5) || + (pcir->deviceId == MPI25_MFGPAGE_DEVID_SAS3108_6)) + { + rev = get16(pcir->imageRevision); + rev1 = get16(get2bytes(pcir->reserved2, 0)); + printf("%s image's version is %d.%02d.%02d.%02d\n", type, + (rev >> 8) & 0xff , rev & 0xff, (rev1 >> 8) & 0xff, rev1 & 0xff); + } + else /* everything else */ + { + rev = get16(pcir->imageRevision); + printf("%s image's version is %d.%02d.%02d.%02d\n", type, + (rev >> 13) & 0x7, (rev >> 8) & 0x1f, (rev >> 4) & 0xf, (rev >> 0) & 0xf); + } + } + } + } + } + return 0; + } + + for (j = i + 4; j < len; j++) + { + if ((c = buf[j]) == '\0' || c == '"' || c == '>' || c == '\n') + break; + } + + buf[j] = '\0'; + + printf("%s image's version is %s\n", type, buf + i + 4); + + buf[j] = c; + + for (i = j; i < len - 3; i++) + if (buf[i] == '@' && buf[i+1] == '(' && buf[i+2] == '#' && buf[i+3] == ')') + { + for (j = i + 4; j < len; j++) + { + if ((c = buf[j]) == '\0' || c == '"' || c == '>' || c == '\n') + break; + if (j < i + 8) + { + if (!isprint((int)c)) + { + i = j; + break; + } + } + else if (c == ' ') + { + if (buf[j-3] == ' ' && buf[j-2] == ' ' && buf[j-1] == ' ') + { + j -= 3; + break; + } + } + } + if (i == j) + continue; + + buf[j] = '\0'; + + if (strcmp((char *)buf + i + 4, "QRY") != 0) + printf(" %s\n", buf + i + 4); + + buf[j] = c; + + i = j; + } + + return len; +} + + +int +getCompatible(int deviceId, int type) +{ + switch (deviceId & ~1) + { + case MPI_MANUFACTPAGE_DEVICEID_FC909: return 1; break; + case MPI_MANUFACTPAGE_DEVICEID_FC919: return 2; break; + case MPI_MANUFACTPAGE_DEVICEID_FC929: return 2; break; + case MPI_MANUFACTPAGE_DEVICEID_FC919X: return 2; break; + case MPI_MANUFACTPAGE_DEVICEID_FC929X: return 2; break; + case MPI_MANUFACTPAGE_DEVICEID_FC939X: return 2; break; + case MPI_MANUFACTPAGE_DEVICEID_FC949X: return 2; break; + case MPI_MANUFACTPAGE_DEVICEID_FC949E: return 2; break; + case MPI_MANUFACTPAGE_DEVID_53C1030: return 3; break; + case MPI_MANUFACTPAGE_DEVID_1030_53C1035: return 3; break; + case MPI_MANUFACTPAGE_DEVID_SAS1064: return 4; break; + case MPI_MANUFACTPAGE_DEVID_SAS1064E: return 4; break; + case MPI_MANUFACTPAGE_DEVID_SAS1066: return 4; break; + case MPI_MANUFACTPAGE_DEVID_SAS1066E: return 4; break; + case MPI_MANUFACTPAGE_DEVID_SAS1068: return 4; break; + case MPI_MANUFACTPAGE_DEVID_SAS1068E: return 4; break; + case MPI_MANUFACTPAGE_DEVID_SAS1078: return 4; break; + case MPI2_MFGPAGE_DEVID_SAS2004: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2008: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2108_1: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2108_2: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2108_3: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2116_1: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2116_2: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2208_1: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2208_2: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2208_3: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2208_4: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2208_5: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2208_6: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2308_1: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2308_2: return 5; break; + case MPI2_MFGPAGE_DEVID_SAS2308_3: return 5; break; + case MPI2_MFGPAGE_DEVID_SSS6200: return 5; break; + case MPI25_MFGPAGE_DEVID_SAS3004: return 6; break; + case MPI25_MFGPAGE_DEVID_SAS3008: return 6; break; + case MPI25_MFGPAGE_DEVID_SAS3108_1: return 6; break; + case MPI25_MFGPAGE_DEVID_SAS3108_2: return 6; break; + case MPI25_MFGPAGE_DEVID_SAS3108_5: return 6; break; + case MPI25_MFGPAGE_DEVID_SAS3108_6: return 6; break; + } + + return deviceId + 100; +} + + +int +checkCompatible(int deviceId1, int deviceId2, int type) +{ + int id1; + int id2; + + id1 = getCompatible(deviceId1, type); + id2 = getCompatible(deviceId2, type); + + if (type == 3) + { + /* everything is compatible (one image serves all) */ + return 1; + } + + return id1 == id2; +} + + +int +doPort(MPT_PORT *port) +{ + int ready; + int option; + + ready = checkReady(port); + + printf("\n"); + option = argsCurr == NULL ? -1 : 0; + while (TRUE) + { + if (!ready || port->notOperational) + { +#if (WIN32 || __linux__ || __sparc__ || DOS || EFI) && REGISTER_ACCESS + printf("50. Dump MPT registers\n"); + printf("51. Dump chip memory regions\n"); + printf("52. Read/modify chip memory locations\n"); + printf("54. Identify FLASH device\n"); +#endif + printf("99. Reset port\n"); + printf("\n"); + + option = 0; + } + + if (option < 0) + { + printf(" 1. Identify firmware, BIOS, and/or FCode\n"); + printf(" 2. Download firmware (update the FLASH)\n"); +EXP printf(" 3. Upload firmware\n"); + printf(" 4. Download/erase BIOS and/or FCode (update the FLASH)\n"); +EXP printf(" 5. Upload BIOS and/or FCode\n"); + + if (port->pidType != MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf(" 6. Download SEEPROM\n"); +EXP printf(" 7. Upload SEEPROM\n"); + } + printf(" 8. Scan for devices\n"); + printf(" 801. Scan for 1 LUN\n"); +EXP printf(" 802. Scan for 2 LUN's\n"); +EXP printf(" 803. Scan for 3 LUN's\n"); +EXP printf(" 804. Scan for 4 LUN's\n"); +EXP printf(" 805. Scan for 5 LUN's\n"); +EXP printf(" 806. Scan for 6 LUN's\n"); +EXP printf(" 807. Scan for 7 LUN's\n"); +EXP printf(" 808. Scan for 8 LUN's\n"); +EXP printf(" 809. Scan for 9 LUN's\n"); + printf(" 810. Scan for 10 LUN's\n"); +EXP printf(" 9. Read/change configuration pages\n"); + switch (port->deviceId) + { + case MPI_MANUFACTPAGE_DEVICEID_FC939X: + case MPI_MANUFACTPAGE_DEVICEID_FC949X: + case MPI_MANUFACTPAGE_DEVICEID_FC949E: + printf("10. Change IOC settings (interrupt coalescing, EEDP)\n"); + break; + default: + printf("10. Change IOC settings (interrupt coalescing)\n"); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + printf("11. Change SCSI Initiator settings\n"); + printf("12. Change SCSI Target settings\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + printf("13. Change FC Port settings\n"); +EXP printf("14. Change IO Unit settings (multi-pathing)\n"); +EXP printf("15. Change persistent mappings\n"); + printf("16. Display logged-in devices\n"); +EXP printf("17. Show port aliases\n"); +#if DOS || EFI + printf("18. Change FC WWNN/WWPN\n"); +#else +EXP printf("18. Change FC WWNN/WWPN\n"); +#endif + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + printf("13. Change SAS IO Unit settings\n"); +EXP printf("14. Change IO Unit settings (multi-pathing, queuing, caching)\n"); +EXP MPI1 printf("15. Change persistent mappings\n"); + printf("16. Display attached devices\n"); +EXP printf("17. Show expander routing tables\n"); +#if DOS || EFI + printf("18. Change SAS WWID\n"); +#else +EXP printf("18. Change SAS WWID\n"); +#endif + } +EXP printf("19. Test configuration page actions\n"); + printf("20. Diagnostics\n"); + printf("21. RAID actions\n"); + MPI1 printf("22. Reset bus\n"); + printf("23. Reset target\n"); +EXP printf("24. Clear ACA\n"); +EXP MPI2 printf("25. Power Management Control\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + printf("30. Beacon on\n"); + printf("31. Beacon off\n"); +EXP printf("32. Display SFP pages\n"); + } +EXP printf("33. Erase non-volatile adapter storage\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { +EXP printf("34. FC management tools\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("34. Remove device from initiator table\n"); +EXP printf("35. Display HBA firmware Log entries\n"); +EXP printf("36. Clear (erase) HBA firmware Log entries\n"); +EXP printf("37. Force full discovery\n"); + } +#if DOS || EFI + printf("39. Force firmware download boot\n"); +#endif +#if WIN32 || __linux__ || __sparc__ +EXP printf("40. Display current events\n"); +#endif + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { +EXP printf("41. Display transfer statistics\n"); + } +#if WIN32 || __linux__ || __sparc__ + printf("42. Display operating system names for devices\n"); +#endif +#if WIN32 || LINUX_DIAG || __sparc__ + if (port->capabilities & (MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER | + MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)) + { + printf("43. Diagnostic Buffer actions\n"); + } +#endif + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { +EXP printf("44. Program manufacturing information\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("44. Program manufacturing information\n"); + printf("45. Concatenate SAS firmware and NVDATA files\n"); + } +EXP printf("46. Upload FLASH section\n"); +EXP printf("47. Display version information\n"); +EXP printf("48. Display chip VPD information\n"); +EXP printf("49. Program chip VPD information\n"); +#if (WIN32 || __linux__ || __sparc__ || DOS || EFI) && REGISTER_ACCESS +EXP printf("50. Dump MPT registers\n"); +EXP printf("51. Dump chip memory regions\n"); +EXP printf("52. Read/modify chip memory locations\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { +EXP printf("53. Dump FC trace buffer\n"); + } +EXP printf("54. Identify FLASH device\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("55. Force firmware to fault (with C0FFEE)\n"); +EXP printf("56. Read/write expander memory\n"); +EXP printf("57. Read/write expander ISTWI device\n"); + } +#endif + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("58. Alta diagnostics\n"); + } + + printf("59. Dump PCI config space\n"); + printf("60. Show non-default settings\n"); + printf("61. Restore default settings\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { +EXP printf("62. Update default PhyRegs settings\n"); +EXP printf("63. Set personal WWNN/WWPN\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("64. SAS Expander UART Console\n"); +EXP MPI2 printf("65. SAS UART Debug Console\n"); + printf("66. Show SAS discovery errors\n"); + } +EXP printf("67. Dump all port state\n"); +EXP printf("68. Show port state summary\n"); + printf("69. Show board manufacturing information\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC || + port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("70. Dump all device pages\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP MPI2 printf("71. Dump all SAS device page 0's\n"); +#if LSIINTERNAL +EXP MPI20 printf("72. Store SC Information\n"); +#endif + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { +EXP printf("80. Set port offline\n"); +EXP printf("81. Set port online\n"); +EXP printf("82. Set port to NL_Port\n"); +EXP printf("83. Set port to N_Port\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("80. Set SAS phy offline\n"); +EXP printf("81. Set SAS phy online\n"); + } +EXP printf("90. Send SCSI CDB\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { +EXP printf("93. Send GIEL\n"); +EXP printf("94. Send GID_FT\n"); +EXP printf("95. Send GA_NXT\n"); +EXP printf("96. Send ELS request\n"); +EXP printf("97. Reset FC link, Maintain Logins\n"); + printf("98. Reset FC link\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("95. Send SATA request\n"); +EXP printf("96. Send SMP request\n"); + printf("97. Reset SAS link, HARD RESET\n"); + printf("98. Reset SAS link\n"); + } + printf("99. Reset port\n"); + if (expert) + printf(" e Disable expert mode in menus\n"); + else + printf(" e Enable expert mode in menus\n"); + if (paged) + printf(" p Disable paged mode\n"); + else + printf(" p Enable paged mode\n"); + if (wFlag) + printf(" w Disable logging\n"); + else + printf(" w Enable logging\n"); + printf("\n"); + } + + printf("Main menu, select an option: [1-99 or e/p/w or 0 to quit] "); + option = getNumberAnswer(0, 999, -999); + if (option < 0 || option == 999) + { + printf("\n"); + continue; + } + + if (option == 0) + break; + + doPortOption(port, option); + + printf("\n"); + } + + return 1; +} + + +int +doPortOption(MPT_PORT *port, int option) +{ + int ready; + int t; + + ready = checkReady(port); + + if (option == 0 || option == 111) + return 1; + + printf("\n"); + + if (iocMask & (1 << port->iocNumber)) + { + switch (option) + { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 14: + case 33: + case 39: + case 44: + case 48: + case 49: + case 51: + case 52: + case 54: + case 53: + case 55: + case 62: + case 99: + printf("Option %d skipped for %s\n", option, port->portName); + return 1; + } + } + + if (!ready || port->notOperational) + { + switch (option) + { +#if (WIN32 || __linux__ || __sparc__ || DOS || EFI) && REGISTER_ACCESS + case 50: + doDumpRegisters(port); + break; + case 51: + doDumpChipMemoryRegions(port); + break; + case 52: + doReadModifyChipMemoryLocations(port); + break; + case 54: + doFlashInfo(port); + break; +#endif + case 99: + doResetPort(port); + break; + default: + printf("Invalid selection!\n"); + break; + } + + return 1; + } + + updatePortInfo(port); + + switch (option) + { + case 1: + doIdentify(port); + break; + case 2: + doFirmwareDownload(port); + break; + case 3: + doFirmwareUpload(port); + break; + case 4: + doBiosFcodeDownload(port); + break; + case 5: + doBiosFcodeUpload(port, NULL, NULL, 0); + break; + case 6: + if (port->pidType != MPI_FW_HEADER_PID_TYPE_SAS) + { + doSeepromDownload(port); + break; + } + printf("Invalid selection!\n"); + break; + case 7: + if (port->pidType != MPI_FW_HEADER_PID_TYPE_SAS) + { + doSeepromUpload(port); + break; + } + printf("Invalid selection!\n"); + break; + case 8: + doScanForDevices(port, 1); + break; + case 801: + doScanForLuns(port, 1 , option); + break; + case 802: + doScanForLuns(port, 1 , option); + break; + case 803: + doScanForLuns(port, 1 , option); + break; + case 804: + doScanForLuns(port, 1 , option); + break; + case 805: + doScanForLuns(port, 1 , option); + break; + case 806: + doScanForLuns(port, 1 , option); + break; + case 807: + doScanForLuns(port, 1 , option); + break; + case 808: + doScanForLuns(port, 1 , option); + break; + case 809: + doScanForLuns(port, 1 , option); + break; + case 810: + doScanForLuns(port, 1 , option); + break; + case 9: + doConfigPage(port); + break; + case 10: + doIocSettings(port); + break; + case 11: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + doScsiInitiatorSettings(port); + break; + } + printf("Invalid selection!\n"); + break; + case 12: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + doScsiTargetSettings(port); + break; + } + printf("Invalid selection!\n"); + break; + case 13: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcPortSettings(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSasIoUnitSettings(port); + break; + } + printf("Invalid selection!\n"); + break; + case 14: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC || + port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doIoUnitSettings(port); + break; + } + printf("Invalid selection!\n"); + break; + case 15: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC || + port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + option = argsCurr == NULL ? -1 : 0; + while (TRUE) + { + if (option < 0) + { + printf(" 1. Show persistent mappings\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + printf(" 2. Automatically add persistent mappings for ALL targets\n"); +EXP printf(" 3. Automatically add persistent mappings for SOME targets\n"); + printf(" 4. Delete persistent mappings for ALL targets\n"); +EXP printf(" 5. Delete persistent mappings for SOME targets\n"); +EXP printf(" 6. Manually add persistent mappings for targets\n"); +EXP printf(" 7. Automatically add persistent mappings for ALL LoopIDs\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf(" 4. Delete persistent mappings for ALL targets\n"); +EXP printf(" 5. Delete persistent mappings for SOME targets\n"); + printf(" 6. Change Bus/Target or EnclosureId of an existing mapping\n"); + printf(" 7. Save persistent mappings to a file\n"); + printf(" 8. Load persistent mappings from a file\n"); + printf("10. Clear all persistent mappings\n"); + printf("11. Clear all non-present persistent mappings\n"); + printf("12. Change (enable/disable) persistence\n"); + } + printf("99. Reset port\n"); + if (expert) + printf(" e Disable expert mode in menus\n"); + else + printf(" e Enable expert mode in menus\n"); + if (paged) + printf(" p Disable paged mode\n"); + else + printf(" p Enable paged mode\n"); + if (wFlag) + printf(" w Disable logging\n"); + else + printf(" w Enable logging\n"); + printf("\n"); + } + + printf("Persistence menu, select an option: [1-99 or e/p/w or 0 to quit] "); + option = getNumberAnswer(0, 99, -999); + if (option < 0 || option == 999) + { + printf("\n"); + continue; + } + + if (option == 0) + break; + + printf("\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (option <= 7) + { + doFcPersistentMappings(port, option); + } + else if (option == 99) + { + doResetPort(port); + } + else + { + printf("Invalid selection!\n"); + } + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS && mpi1) + { + if (option == 1 || (option >= 4 && option <= 8) || (option >= 10 && option <= 12)) + { + doSasPersistentMappings(port, option); + } + else if (option == 99) + { + doResetPort(port); + } + else + { + printf("Invalid selection!\n"); + } + } + printf("\n"); + } + option = -1; + break; + } + printf("Invalid selection!\n"); + break; + case 16: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doDisplayLoggedInDevices(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doDisplayAttachedDevices(port); + break; + } + printf("Invalid selection!\n"); + break; + case 17: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doShowPortAliases(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doShowExpanderRoutingTables(port); + break; + } + printf("Invalid selection!\n"); + break; + case 18: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcChangeWwn(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSasChangeWwid(port, 0); + break; + } + printf("Invalid selection!\n"); + break; + case 19: + doTestConfigPageActions(port); + break; + case 20: + option = argsCurr == NULL ? -1 : 0; + while (TRUE) + { + if (option < 0) + { + printf(" 1. Inquiry Test\n"); + printf(" 2. WriteBuffer/ReadBuffer/Compare Test\n"); + printf(" 3. Read Test\n"); + printf(" 4. Write/Read/Compare Test\n"); +EXP printf(" 5. Write Test\n"); +EXP printf(" 6. Read/Compare Test\n"); +#if 0 +EXP printf(" 7. Test Unit Ready Test\n"); +#else +EXP printf(" 7. Log Sense Test\n"); +#endif + printf(" 8. Read Capacity / Read Block Limits Test\n"); +EXP printf(" 9. Mode Page Test\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + printf("10. Echo ELS Test\n"); +EXP printf("11. Read Link Error Status ELS Test\n"); + printf("12. Display port counters\n"); + printf("13. Clear port counters\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("10. SATA Identify Device Test\n"); +EXP printf("11. SATA Clear Affiliation Test\n"); + printf("12. Display phy counters\n"); + printf("13. Clear phy counters\n"); + printf("14. SATA SMART Read Test\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI || + port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + printf("15. SEP (SCSI Enclosure Processor) Test\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("16. Issue product-specific SAS IO Unit Control\n"); + } +EXP printf("17. Diag data upload\n"); + printf("18. Report LUNs Test\n"); + printf("19. Drive firmware download\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { +EXP printf("20. Trigger FC Analyzer With Echo ELS\n"); + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + printf("20. Expander firmware download\n"); + } + printf("21. Read Logical Blocks\n"); +EXP printf("22. Write Logical Blocks\n"); +EXP printf("23. Verify Logical Blocks\n"); +EXP printf("24. Read Buffer (for firmware upload)\n"); +EXP printf("25. Display Expander Log entries\n"); +EXP printf("26. Clear (erase) Expander Log entries\n"); +EXP printf("27. Change SAS2/SAS3 Expander Manufacturing Data Fields\n"); +EXP printf("29. Diagnostic Page Test\n"); +EXP printf("30. Inject media error\n"); +EXP printf("31. Repair media error\n"); +EXP printf("32. Set software write protect\n"); +EXP printf("33. Clear software write protect\n"); +EXP printf("34. Enable read cache\n"); +EXP printf("35. Disable read cache\n"); +EXP printf("36. Enable write cache\n"); +EXP printf("37. Disable write cache\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP printf("98. Reset expander\n"); + } + printf("99. Reset port\n"); + if (expert) + printf(" e Disable expert mode in menus\n"); + else + printf(" e Enable expert mode in menus\n"); + if (paged) + printf(" p Disable paged mode\n"); + else + printf(" p Enable paged mode\n"); + if (wFlag) + printf(" w Disable logging\n"); + else + printf(" w Enable logging\n"); + printf("\n"); + } + + printf("Diagnostics menu, select an option: [1-99 or e/p/w or 0 to quit] "); + option = getNumberAnswer(0, 99, -999); + if (option < 0 || option == 999) + { + printf("\n"); + continue; + } + + if (option == 0) + break; + + printf("\n"); + if (option == 99) + doResetPort(port); + else + doDiagnostics(port, option); + printf("\n"); + } + option = -1; + break; + case 21: + option = argsCurr == NULL ? -1 : 0; + while (TRUE) + { + if (option < 0) + { + printf(" 1. Show volumes\n"); + printf(" 2. Show physical disks\n"); + printf(" 3. Get volume state\n"); + printf(" 4. Wait for volume resync to complete\n"); +EXP printf("10. Disable all volumes\n"); +EXP printf("11. Enable all volumes\n"); +EXP MPI1 printf("12. Inactivate volume\n"); +EXP printf("13. Activate volume\n"); +EXP printf("20. Offline physical disk\n"); +EXP printf("21. Online physical disk\n"); +EXP printf("22. Fail physical disk\n"); + MPI1 printf("23. Replace physical disk\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { +EXP MPI1 printf("24. Quiesce physical disk I/Os\n"); +EXP MPI1 printf("25. Unquiesce physical disk I/Os\n"); + } + printf("26. Disable drive firmware update mode\n"); + printf("27. Enable drive firmware update mode\n"); + printf("30. Create volume\n"); + printf("31. Delete volume\n"); + printf("32. Change volume settings\n"); + printf("33. Change volume name\n"); + MPI2 printf("34. Volume consistency check\n"); + MPI2 printf("35. Stop volume consistency check\n"); + MPI2 printf("36. Online Capacity Expansion\n"); +// MPI1 printf("40. Create physical disk\n"); +EXP MPI1 printf("41. Delete physical disk\n"); +EXP MPI1 printf("42. Change physical disk settings\n"); + printf("50. Create hot spare\n"); + printf("51. Delete hot spare\n"); +EXP MPI2 printf("60. Change RAID rate\n"); + printf("99. Reset port\n"); + if (expert) + printf(" e Disable expert mode in menus\n"); + else + printf(" e Enable expert mode in menus\n"); + if (paged) + printf(" p Disable paged mode\n"); + else + printf(" p Enable paged mode\n"); + if (wFlag) + printf(" w Disable logging\n"); + else + printf(" w Enable logging\n"); + printf("\n"); + } + + printf("RAID actions menu, select an option: [1-99 or e/p/w or 0 to quit] "); + option = getNumberAnswer(0, 99, -999); + if (option < 0 || option == 999) + { + printf("\n"); + continue; + } + + if (option == 0) + break; + + printf("\n"); + if (option == 99) + doResetPort(port); + else + doRaidActions(port, option); + printf("\n"); + } + option = -1; + break; + case 22: + if (mpi1) + { + doResetBus(port); + break; + } + printf("Invalid selection!\n"); + break; + case 23: + doResetTarget(port); + break; + case 24: + doClearAca(port); + break; + case 25: + // Power Management Control + option = argsCurr == NULL ? -1 : 0; + while (TRUE) + { + if (option < 0) + { + printf(" 1. Send Power Management Control MPI message\n"); + printf(" 2. Display IOUnit7 Config Page\n"); + printf(" 3. Get/Set SASIoUnit8 Config Page\n"); + printf("\n"); + } + + printf("Power Management actions menu, select an option: [1-99 or e/p/w or 0 to quit] "); + option = getNumberAnswer(0, 99, -999); + if (option < 0 || option == 999) + { + printf("\n"); + continue; + } + + if (option == 0) + break; + + printf("\n"); + switch (option) + { + case 1: + doSendPowerManagementControlMPI(port); + break; + case 2: + doIoUnit7Settings(port); + break; + case 3: + doSasIoUnit8Settings(port); + break; + } + printf("\n"); + } + option = -1; + break; + case 30: + doBeacon(port, 1); + break; + case 31: + doBeacon(port, 0); + break; + case 32: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doDisplaySfpPages(port); + break; + } + printf("Invalid selection!\n"); + break; + case 33: + doClean(port); + break; + case 34: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcManagementTools(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doRemoveSasDevice(port); + break; + } + printf("Invalid selection!\n"); + break; + case 35: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doDisplayLogEntries(port); + break; + } + printf("Invalid selection!\n"); + break; + case 36: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doClearLogEntries(port); + break; + } + printf("Invalid selection!\n"); + break; + case 37: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSasForceFullDiscovery(port); + break; + } + printf("Invalid selection!\n"); + break; +#if DOS || EFI + case 39: + doFirmwareDownloadBoot(port); + break; +#endif +#if WIN32 || __linux__ || __sparc__ + case 40: + doDisplayCurrentEvents(port); + break; +#endif + case 41: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doDisplayTransferStatistics(port); + break; + } + printf("Invalid selection!\n"); + break; +#if WIN32 || __linux__ || __sparc__ + case 42: + doDisplayOsDeviceNames(port); + break; +#endif +#if WIN32 || LINUX_DIAG || __sparc__ + case 43: + if (port->capabilities & (MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER | + MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)) + { + doDiagBuffer(port); + break; + } + printf("Invalid selection!\n"); + break; +#endif + case 44: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + t = doWriteFcManufacturingInfo(port); + if (wFlag) + fprintf(logFile, "%s: Program Manufacturing Information: %s\n", + logPrefix(port), t ? "PASS" : "FAIL"); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + t = doWriteSasManufacturingInfo(port); + if (wFlag) + fprintf(logFile, "%s: Program Manufacturing Information: %s\n", + logPrefix(port), t ? "PASS" : "FAIL"); + break; + } + printf("Invalid selection!\n"); + break; + case 45: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + concatenateSasFirmwareNvdata(); + break; + } + printf("Invalid selection!\n"); + break; + case 46: + doFlashUpload(port); + break; + case 47: + doDisplayVersionInfo(port); + break; + case 48: + doDisplayVpdInfo(port); + break; + case 49: + t = doProgramVpdInfo(port); + if (wFlag) + fprintf(logFile, "%s: Program VPD Information: %s\n", + logPrefix(port), t ? "PASS" : "FAIL"); + break; +#if (WIN32 || __linux__ || __sparc__ || DOS || EFI) && REGISTER_ACCESS + case 50: + doDumpRegisters(port); + break; + case 51: + doDumpChipMemoryRegions(port); + break; + case 52: + doReadModifyChipMemoryLocations(port); + break; + case 53: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doDumpFcTraceBuffer(port); + break; + } + printf("Invalid selection!\n"); + break; + case 54: + doFlashInfo(port); + break; + case 55: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doForceFirmwareFault(port); + break; + } + printf("Invalid selection!\n"); + break; +#endif + case 56: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doReadWriteExpanderMemory(port); + break; + } + printf("Invalid selection!\n"); + break; + case 57: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doReadWriteExpanderIstwiDevice(port); + break; + } + printf("Invalid selection!\n"); + break; + case 58: + option = argsCurr == NULL ? -1 : 0; + while (TRUE) + { + if (option < 0) + { + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + printf(" 1. Program manufacturing information\n"); + printf(" 2. Display manufacturing information\n"); + printf(" 3. Reset Alta\n"); + } + if (expert) + printf(" e Disable expert mode in menus\n"); + else + printf(" e Enable expert mode in menus\n"); + if (paged) + printf(" p Disable paged mode\n"); + else + printf(" p Enable paged mode\n"); + if (wFlag) + printf(" w Disable logging\n"); + else + printf(" w Enable logging\n"); + printf("\n"); + } + + printf("Alta diagnostics menu, select an option: [1-99 or e/p/w or 0 to quit] "); + option = getNumberAnswer(0, 99, -999); + if (option < 0 || option == 999) + { + printf("\n"); + continue; + } + + if (option == 0) + break; + + printf("\n"); + doAltaDiagnostics(port, option); + printf("\n"); + } + option = -1; + break; + case 59: + doDumpPciConfigSpace(port); + break; + case 60: + doShowNonDefaultSettings(port); + break; + case 61: + doRestoreDefaultSettings(port); + break; + case 62: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doDefaultPhyRegsSettings(port); + break; + } + printf("Invalid selection!\n"); + break; + case 63: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcChangePersonalWwn(port); + break; + } + printf("Invalid selection!\n"); + break; + case 64: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doExpanderUart(port); + break; + } + printf("Invalid selection!\n"); + break; + case 65: + if (mpi2 && port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doUartDebugConsole(port); + break; + } + printf("Invalid selection!\n"); + break; + case 66: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + showSasDiscoveryErrors(port); + break; + } + printf("Invalid selection!\n"); + break; + case 67: + doDumpPortState(port, 1); + break; + case 68: + doPortStateSummary(port); + break; + case 69: + showBoardInfo(port, 1); + break; + case 70: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + dumpFcDevicePages(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + dumpSasDevicePages(port); + break; + } + printf("Invalid selection!\n"); + break; + case 71: + if (mpi2 && port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + dumpSasDevicePage0sLong(port); + break; + } + printf("Invalid selection!\n"); + break; + case 72: +#if LSIINTERNAL + if (mpi2 && port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSCProgram(port); + break; + } +#endif + printf("Invalid selection!\n"); + break; + case 80: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcPortOffline(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSasPhyOnOffline(port, 0); + break; + } + printf("Invalid selection!\n"); + break; + case 81: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcPortOnline(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSasPhyOnOffline(port, 1); + break; + } + printf("Invalid selection!\n"); + break; + case 82: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcTopologyNLPort(port); + break; + } + printf("Invalid selection!\n"); + break; + case 83: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcTopologyNPort(port); + break; + } + printf("Invalid selection!\n"); + break; + case 86: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcSpecialMode(port, 1, 0); + break; + } + printf("Invalid selection!\n"); + break; + case 87: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcSpecialMode(port, 0, 0); + break; + } + printf("Invalid selection!\n"); + break; + case 88: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcSpecialMode(port, 1, 1); + break; + } + printf("Invalid selection!\n"); + break; + case 89: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doFcSpecialMode(port, 0, 1); + break; + } + printf("Invalid selection!\n"); + break; + case 90: + doScsiCdb(port); + break; + case 93: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doGIEL(port); + break; + } + printf("Invalid selection!\n"); + break; + case 94: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doGID_FT(port); + break; + } + printf("Invalid selection!\n"); + break; + case 95: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doGA_NXT(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSataPassthroughSend(port); + break; + } + printf("Invalid selection!\n"); + break; + case 96: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doExLinkServiceSend(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSmpPassthroughSend(port); + break; + } + printf("Invalid selection!\n"); + break; + case 97: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doResetFcLink(port, 1); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doResetSasLink(port, 1); + break; + } + printf("Invalid selection!\n"); + break; + case 98: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doResetFcLink(port, 0); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doResetSasLink(port, 0); + break; + } + printf("Invalid selection!\n"); + break; + case 99: + doResetPort(port); + break; + case 100: + doDumpPortState(port, 1); + break; + case 101: + doPortStateSummary(port); + break; + case 102: + showBoardInfo(port, 1); + break; + default: + printf("Invalid selection!\n"); + break; + } + + return 1; +} + + +int +doIdentify(MPT_PORT *port) +{ + unsigned char *imageBuf; + int imageLen; + int actualImageLen; + int offset; + unsigned char *buf; + int len; + int i; + int n; + PCIR *pcir; + char *type; + + i = port->fwVersion; + if (port->mptVersion < MPI_VERSION_01_02) + { + printf("Current active firmware version is %08x (%d.%02d.%02d)\n", + i, (i >> 12) & 0xf, (i >> 8) & 0xf, i & 0xff); + } + else + { + if (i & 0xff) + { + printf("Current active firmware version is %08x (%d.%02d.%02d.%02d)\n", + i, (i >> 24) & 0xff, (i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff); + } + else + { + printf("Current active firmware version is %08x (%d.%02d.%02d)\n", + i, (i >> 24) & 0xff, (i >> 16) & 0xff, (i >> 8) & 0xff); + } + } + + imageLen = 0x10000; + imageBuf = (unsigned char *)malloc(imageLen); + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + i = MPI_FW_UPLOAD_ITYPE_FW_BACKUP; + else + i = MPI_FW_UPLOAD_ITYPE_FW_FLASH; + + if (doFwUpload(port, i, imageBuf, imageLen, 0, &actualImageLen) == 1) + { + printWhatString("Firmware", imageBuf, imageLen); + } + + offset = 0; + while (offset < 0x80000) + { + if (doFwUpload(port, MPI_FW_UPLOAD_ITYPE_BIOS_FLASH, imageBuf, imageLen, offset, &actualImageLen) != 1) + break; + + if (port->pidType != MPI_FW_HEADER_PID_TYPE_SCSI) + { + if (offset >= actualImageLen) + break; + } + + for (i = 0; i < imageLen; i += 512) + { + buf = imageBuf + i; + + n = (buf[0x01]<<8) + buf[0x00]; + if (n != 0xaa55) + continue; + + n = (buf[0x19]<<8) + buf[0x18]; + + if (i + n + (int)sizeof *pcir > imageLen) + { + // not all of the image is in the buffer, so quit now and read more of the image + break; + } + + pcir = (PCIR *)(buf + n); + + if (pcir->signature[0] != 'P' || + pcir->signature[1] != 'C' || + pcir->signature[2] != 'I' || + pcir->signature[3] != 'R') + { + printf("Image's PCIR signature is invalid!\n"); + type = "Unknown"; + len = 512; + } + else + { + len = get16(pcir->imageLength) * 512; + if (i + len > imageLen) + { + // not all of the image is in the buffer, so quit now and read more of the image + if (len > imageLen) + { + free(imageBuf); + imageLen = len; + imageBuf = (unsigned char *)malloc(len); + } + break; + } + + switch (pcir->type) + { + case 0: type = "x86 BIOS"; break; + case 1: type = "FCode"; break; + case 3: type = "EFI BIOS"; break; + default: type = "Unknown"; break; + } + + if (pcir->type == 255) + { + if (buf[4] == 'L' && buf[5] == 'S' && buf[6] == 'I' && buf[7] == 'L' && buf[0x34] == 0x02) + type = NULL; + } + + if (pcir->indicator & 0x80) + { + // last image, so make sure we quit after this + i += 0x80000; + } + } + + if (type) + printWhatString(type, buf, len); + i += len - 512; + } + + offset += i; + } + + free(imageBuf); + + return 1; +} + + +int +doFirmwareDownload(MPT_PORT *port) +{ + ManufacturingPage0_t ManufacturingPage0; + char name[256]; + unsigned char *imageBuf = NULL; + int imageLen; + int len; + int n; + int warn = 0; + MpiFwHeader_t *fwHeader; + MpiExtImageHeader_t *fwExtImageHeader; + Mpi2ExtImageHeader_t *fwExtImageHeader2; + Mpi2SupportedDevicesData_t *fwSupportedDevices; + U32 fwNextImage; + int i; + U32 t; + U32 checksum; + char *productId; + int cur2MB; + int new2MB; + U32 buf0[16]; +#if REGISTER_ACCESS + U32 buf1[16]; + U32 buf2[16]; + U32 buf4[16]; + U32 zeros[16]; + int romSize; +#endif +#if DOS || EFI + HANDLE adap = port->fileHandle; + int mustExit = 0; +#endif + unsigned char *imageBufUpload; + int imageLenUpload; + int actualImageLenUpload; + int offset; + int type; + int skip_verify = 0; + + n = getFileName(name, sizeof name, stdin, "firmware", 0); + if (n > 0) + { + if (readFile(name, &imageBuf, &imageLen) != 1) + return 0; + } + else + { + printf("Image won't be downloaded\n"); + return 1; + } + + printWhatString("Firmware", imageBuf, imageLen); + + checksum = 0; + for (i = 0; i < imageLen / 4; i++) + checksum += get32x(((U32 *)imageBuf)[i]); + + if (checksum != 0) + { + if (!warn) + printf("\n"); + printf("Image's checksum is invalid!\n"); + printf(" The image appears to be corrupted, proceed with caution\n"); + warn = 1; + } + + if (port->mptVersion > MPI_VERSION_01_00) + { + fwHeader = (pMpiFwHeader_t)imageBuf; + + if (get16(fwHeader->VendorId) != MPI_MANUFACTPAGE_VENDORID_LSILOGIC) + { + if (!warn) + printf("\n"); + printf("Image's Vendor ID appears to be wrong!\n"); + printf(" Current hardware Vendor ID is %04x\n", MPI_MANUFACTPAGE_VENDORID_LSILOGIC); + printf(" Image's hardware Vendor ID is %04x\n", get16(fwHeader->VendorId)); + warn = 1; + } + + if (get16(fwHeader->ProductId) != port->productId) + { + if (!warn) + printf("\n"); + printf("Image's Product ID appears to be wrong!\n"); + printf(" Current firmware Product ID is %04x\n", port->productId); + printf(" Image's firmware Product ID is %04x\n", get16(fwHeader->ProductId)); + warn = 1; + } + + len = get32(fwHeader->ImageSize); + fwNextImage = get32(fwHeader->NextImageHeaderOffset); + while (fwNextImage != 0) + { + if (fwNextImage > imageLen - sizeof *fwExtImageHeader) + { + if (!warn) + printf("\n"); + printf("Image's NextImageHeaderOffset field is invalid!\n"); + printf(" The image appears to be corrupted, proceed with caution\n"); + warn = 1; + break; + } + + fwExtImageHeader = (pMpiExtImageHeader_t)(imageBuf + fwNextImage); + fwExtImageHeader2 = (pMpi2ExtImageHeader_t)fwExtImageHeader; + + if (fwExtImageHeader->ImageType == MPI_EXT_IMAGE_TYPE_NVDATA) + { + if (get32(fwExtImageHeader->ImageSize) <= sizeof *fwExtImageHeader) + { + if (!warn) + printf("\n"); + printf("Image's attached NVDATA is invalid!\n"); + printf(" Using this image is likely to cause pain and suffering\n"); + warn = 1; + } + else if (mpi1) + { + productId = getSasProductId(mpi2 ? (char *)(fwExtImageHeader2 + 1) + : (char *)(fwExtImageHeader + 1)); + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, + &ManufacturingPage0, sizeof ManufacturingPage0) == 1) + { + if (strcmp(productId, (char *)ManufacturingPage0.BoardName) != 0) + { + if (!warn) + printf("\n"); + printf("Image's attached NVDATA appears to be for the wrong board!\n"); + printf(" Current Board Name is %-16s\n", ManufacturingPage0.BoardName); + printf(" Image's Board Name is %-16s\n", productId); + warn = 1; + } + } + } + } + + if (fwExtImageHeader->ImageType == MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES) + { + fwSupportedDevices = (pMpi2SupportedDevicesData_t)(fwExtImageHeader2 + 1); + + for (i = 0; i < fwSupportedDevices->NumberOfDevices; i++) + { + t = port->deviceIdRaw & ~get16(fwSupportedDevices->SupportedDevice[i].DeviceIDMask); + if (t == get16(fwSupportedDevices->SupportedDevice[i].DeviceID) && + port->revisionId >= fwSupportedDevices->SupportedDevice[i].LowPCIRev && + port->revisionId <= fwSupportedDevices->SupportedDevice[i].HighPCIRev) + { + break; + } + } + + if (i == fwSupportedDevices->NumberOfDevices) + { + if (!warn) + printf("\n"); + printf("Image's Supported Device List appears to be wrong!\n"); + printf(" Current hardware Device ID is %04x, Revision ID is %02x\n", + port->deviceIdRaw, port->revisionId); + for (i = 0; i < fwSupportedDevices->NumberOfDevices; i++) + { + if (fwSupportedDevices->SupportedDevice[i].LowPCIRev == + fwSupportedDevices->SupportedDevice[i].HighPCIRev) + { + printf(" Image's hardware Device ID is %04x, Revision ID is %02x\n", + get16(fwSupportedDevices->SupportedDevice[i].DeviceID), + fwSupportedDevices->SupportedDevice[i].LowPCIRev); + } + else + { + printf(" Image's hardware Device ID is %04x, Revision ID is %02x to %02x\n", + get16(fwSupportedDevices->SupportedDevice[i].DeviceID), + fwSupportedDevices->SupportedDevice[i].LowPCIRev, + fwSupportedDevices->SupportedDevice[i].HighPCIRev); + } + } + warn = 1; + } + } + + len += get32(fwExtImageHeader->ImageSize); + fwNextImage = get32(fwExtImageHeader->NextImageHeaderOffset); + } + + if (len != imageLen) + { + if (!warn) + printf("\n"); + printf("Image's length is invalid!\n"); + printf(" The image appears to be corrupted, proceed with caution\n"); + warn = 1; + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + t = get16(fwHeader->ProductId); + + if ((port->deviceId == MPI_MANUFACTPAGE_DEVICEID_FC919X || + port->deviceId == MPI_MANUFACTPAGE_DEVICEID_FC929X) && + port->revisionId >= 0x80 && + t == (MPI_FW_HEADER_PID_TYPE_FC|MPI_FW_HEADER_PID_FAMILY_919X_FC)) + { + t = get32(fwHeader->FWVersion.Word); + + if (t < 0x0102090d) + { + if (!warn) + printf("\n"); + printf("Image is for FC929X, port is FC929XL, image is not compatible!\n"); + warn = 1; + } + } + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS && mpi1) + { + t = get32(fwHeader->SeqCodeVersion); + + if (t != port->seqCodeVersion) + { + if (!warn) + printf("\n"); + printf("Image is for %X, port is %X, image is not compatible!\n", t, port->seqCodeVersion); + warn = 1; + } + +#if DOS || EFI + if (adap->bootloader) + cur2MB = get32x(((U32 *)adap->fw_image)[5]) & 1; + else +#endif + if (doFwUpload(port, MPI_FW_UPLOAD_ITYPE_FW_FLASH, (unsigned char *)buf0, sizeof buf0, 0, &i) == 1) + cur2MB = get32x(buf0[5]) & 1; + else + cur2MB = 0; + + new2MB = get32x(((U32 *)imageBuf)[5]) & 1; + + if (cur2MB != new2MB) + { + if (new2MB) + { +#if REGISTER_ACCESS + doReadChipMemoryRegions(port, 0x3e000000, buf0, sizeof buf0 / 4); + doReadChipMemoryRegions(port, 0x3e100000, buf1, sizeof buf1 / 4); + doReadChipMemoryRegions(port, 0x3e200000, buf2, sizeof buf2 / 4); + doReadChipMemoryRegions(port, 0x3e400000, buf4, sizeof buf4 / 4); + memset(zeros, 0, sizeof zeros); + + if (memcmp(buf0, zeros, sizeof buf0) == 0) + romSize = 0; + else if (memcmp(buf0, buf1, sizeof buf0) == 0) + romSize = 1; + else if (memcmp(buf0, buf2, sizeof buf0) == 0) + romSize = 2; + else if (memcmp(buf0, buf4, sizeof buf0) == 0) + romSize = 4; + else + romSize = 0; + + if (romSize == 1) + { + printf("\nImage requires 2 MB FLASH ROM, current FLASH ROM is 1 MB\n"); + printf("\nFirmware download cannot be performed!\n"); + free(imageBuf); + return 0; + } +#endif + } + } + + t = port->fwVersion; + if (t == 0x01126300) // 1.18.99, "bridge" from phase 8 to phase 9 + { + if (new2MB) + { + printf("\nVersion 1.18.99 is being used to upgrade to Phase 9 firmware\n"); + cur2MB = 1; + skip_verify = 1; + } + else + { + printf("\nVersion 1.18.99 can only be used to upgrade to Phase 9 firmware\n"); + printf("\nFirmware download cannot be performed!\n"); + free(imageBuf); + return 0; + } + } + + t = get32(fwHeader->FWVersion.Word); + if (t == 0x01126300) // 1.18.99, "bridge" from phase 8 to phase 9 + { + if (cur2MB) + { + printf("\nVersion 1.18.99 cannot be used to downgrade to Phase 8 firmware\n"); + printf("\nFirmware download cannot be performed!\n"); + free(imageBuf); + return 0; + } + else + { + printf("\nVersion 1.18.99 can only be used to upgrade to Phase 9 firmware\n"); + printf("\nMake sure to do the second firmware download as soon as possible\n"); + skip_verify = 1; + } + } + + if (cur2MB != new2MB) + { +#if DOS || EFI + if (adap->fw_image != NULL) + free(adap->fw_image); + + adap->fw_image = malloc(imageLen); + adap->fw_image_size = imageLen; + + memcpy(adap->fw_image, imageBuf, imageLen); + + adap->ioc_online = FALSE; + + if (adap->partner_adap != NULL) + { + adap->partner_adap->ioc_online = FALSE; + + adap->partner_adap->fw_image = adap->fw_image; + adap->partner_adap->fw_image_size = 0; + } + + if (mpt_fwdownloadboot(adap) != 1) + { + printf("\nThe chip was not made operational with this firmware!\n"); + printf("\nFirmware download cannot be performed!\n"); + mpt_stop(adap, TRUE); + return 0; + } + + mustExit = 1; +#else + if (new2MB) + { + printf("\nSwitching from a 1 MB to a 2 MB FLASH ROM image requires special actions\n"); + printf("\nIt can either be done using the 1.18.99 bridge firmware image, or...\n"); + printf("\nUse the DOS or EFI version of lsiutil to perform the firmware download\n"); + free(imageBuf); + return 0; + } + else + { + printf("\nSwitching from a 2 MB to a 1 MB FLASH ROM image cannot be done online!\n"); + printf("\nUse the DOS or EFI version of lsiutil to perform the firmware download\n"); + free(imageBuf); + return 0; + } +#endif + } + } + } + + if (warn && noFlag == TRUE) + { + free(imageBuf); + return 0; + } + + if (warn || yesFlag == FALSE) + { + if (warn) + printf("\nAre you sure you want to continue? [Yes or No, default is No] "); + else + printf("\nDo you want to continue? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + { + free(imageBuf); + return 0; + } + } + +retry: + t = doFwDownload(port, MPI_FW_DOWNLOAD_ITYPE_FW, imageBuf, imageLen, 0); + if (t != 1) + goto no_verify; + +#if DOS || EFI + if (adap->bootloader) + goto no_verify; +#endif + + if (skip_verify) + goto no_verify; + + printf("\nVerifying download...\n"); + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + type = MPI_FW_UPLOAD_ITYPE_FW_BACKUP; + else + type = MPI_FW_UPLOAD_ITYPE_FW_FLASH; + + imageLenUpload = 0x10000; + imageBufUpload = (unsigned char *)malloc(imageLenUpload); + + offset = 0; + while (TRUE) + { + if (doFwUpload(port, type, imageBufUpload, imageLenUpload, offset, &actualImageLenUpload) != 1) + break; + + if (offset + imageLenUpload > actualImageLenUpload) + imageLenUpload = actualImageLenUpload - offset; + + if (memcmp(imageBuf + offset, imageBufUpload, imageLenUpload) != 0) + { + t = 0; + break; + } + + offset += imageLenUpload; + if (offset >= actualImageLenUpload) + break; + } + if (t && imageLen == actualImageLenUpload) + printf("Verification succeeded\n"); + else + { + printf("Verification failed!\n"); + + if (noFlag != TRUE) + { + printf("\nAt a minimum, to recover, the download operation should be retried\n"); + printf("\nWould you like to retry the download now? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) == 1) + goto retry; + } + } + free(imageBufUpload); +no_verify: + + free(imageBuf); +#if DOS || EFI + if (mustExit) + { + if (adap->fw_image != NULL) + free(adap->fw_image); + + adap->fw_image = NULL; + + doResetPort(port); + + closePorts(NUM_PORTS); + + exit(0); + } +#endif + + return t; +} + + +int +doFirmwareUpload(MPT_PORT *port) +{ + char name[256]; + int file; + unsigned char *imageBuf = NULL; + int imageLen; + int actualImageLen; + int offset; + int n; + int t; + + n = getFileName(name, sizeof name, stdin, "firmware", 0); + if (n > 0) + { + file = open(name, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + if (file < 0) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + } + else + { + printf("Image won't be uploaded\n"); + return 1; + } + + imageLen = 0x10000; + imageBuf = (unsigned char *)malloc(imageLen); + + offset = 0; + while (TRUE) + { + if (doFwUpload(port, MPI_FW_UPLOAD_ITYPE_FW_FLASH, imageBuf, imageLen, offset, &actualImageLen) != 1) + break; + + if (offset + imageLen > actualImageLen) + imageLen = actualImageLen - offset; + + t = write(file, imageBuf, imageLen); + if (t != imageLen) + { + printf("Write failed for file %s, t = %x\n", name, t); + perror("Error is"); + break; + } + + offset += imageLen; + if (offset >= actualImageLen) + break; + } + + printf("\nWrote %d bytes to file %s\n", offset, name); + + close(file); + + free(imageBuf); + + return 1; +} + + +int +doBiosFcodeDownload(MPT_PORT *port) +{ + char name[256]; + unsigned char *imageBuf = NULL; + unsigned char *image1Buf = NULL; + unsigned char *image2Buf = NULL; + unsigned char *image3Buf = NULL; + unsigned char *image4Buf = NULL; + unsigned char *image5Buf = NULL; + int imageLen; + int image1Len; + int image2Len; + int image3Len; + int image4Len = 0; + int image5Len = 0; + int imageOff; + int n; + int warn = 0; + int last; + int valid = 0; + + printf("To erase an image:\n"); + printf(" 1. hit RETURN when asked for a image file name\n"); + printf(" 2. answer No if asked to preserve an existing image\n\n"); + + n = getFileName(name, sizeof name, stdin, "x86 BIOS", 0); + if (n > 0) + { + if (readFile(name, &image1Buf, &image1Len) != 1) + return 0; + + printWhatString("x86 BIOS", image1Buf, image1Len); + + warn |= verifyBiosFcodeImage(port, image1Buf, image1Len, 0); + } + else + { + if (doBiosFcodeUpload(port, &image1Buf, &image1Len, 0) == 1 && image1Buf != NULL) + { + valid = 1; + + printWhatString("Current x86 BIOS", image1Buf, image1Len); + + if (yesFlag == FALSE) + { + printf("\nDo you want to preserve the current x86 BIOS? [Yes or No, default is Yes] "); + + if (getYesNoAnswer(1) != 1) + { + free(image1Buf); + image1Buf = NULL; + } + } + } + else + { + printf("No x86 BIOS image exists in FLASH, and image won't be downloaded\n"); + + if (gFlag == TRUE && yesFlag == FALSE) + { + printf("\nYou realize there is nothing to preserve, right? [Yes or No] "); + getYesNoAnswer(1); + } + } + } + + printf("\n"); + + n = getFileName(name, sizeof name, stdin, "FCode", 1); + if (n > 0) + { + if (readFile(name, &image2Buf, &image2Len) != 1) + return 0; + + printWhatString("FCode", image2Buf, image2Len); + + warn |= verifyBiosFcodeImage(port, image2Buf, image2Len, 1); + } + else + { + if (doBiosFcodeUpload(port, &image2Buf, &image2Len, 1) == 1 && image2Buf != NULL) + { + valid = 1; + + printWhatString("Current FCode", image2Buf, image2Len); + + if (yesFlag == FALSE) + { + printf("\nDo you want to preserve the current FCode? [Yes or No, default is Yes] "); + + if (getYesNoAnswer(1) != 1) + { + free(image2Buf); + image2Buf = NULL; + } + } + } + else + { + printf("No FCode image exists in FLASH, and image won't be downloaded\n"); + + if (gFlag == TRUE && yesFlag == FALSE) + { + printf("\nYou realize there is nothing to preserve, right? [Yes or No] "); + getYesNoAnswer(1); + } + } + } + + printf("\n"); + + n = getFileName(name, sizeof name, stdin, "EFI BIOS", 2); + if (n > 0) + { + if (readFile(name, &image3Buf, &image3Len) != 1) + return 0; + + printWhatString("EFI BIOS", image3Buf, image3Len); + + warn |= verifyBiosFcodeImage(port, image3Buf, image3Len, 3); + } + else + { + if (doBiosFcodeUpload(port, &image3Buf, &image3Len, 3) == 1 && image3Buf != NULL) + { + valid = 1; + + printWhatString("Current EFI BIOS", image3Buf, image3Len); + + if (yesFlag == FALSE) + { + printf("\nDo you want to preserve the current EFI BIOS? [Yes or No, default is Yes] "); + + if (getYesNoAnswer(1) != 1) + { + free(image3Buf); + image3Buf = NULL; + } + } + } + else + { + printf("No EFI BIOS image exists in FLASH, and image won't be downloaded\n"); + + if (gFlag == TRUE && yesFlag == FALSE) + { + printf("\nYou realize there is nothing to preserve, right? [Yes or No] "); + getYesNoAnswer(1); + } + } + } + + if (image1Buf != NULL) + { + last = image2Buf == NULL && image3Buf == NULL; + splitBiosImage(port, &image1Buf, &image1Len, &image4Buf, &image4Len); + fixupBiosFcodeImage(port, image1Buf, image1Len, last); + } + else + image1Len = 0; + + if (image2Buf != NULL) + { + last = image3Buf == NULL; + fixupBiosFcodeImage(port, image2Buf, image2Len, last); + } + else + image2Len = 0; + + if (image3Buf != NULL) + { + last = 1; + splitBiosImage(port, &image3Buf, &image3Len, &image5Buf, &image5Len); + fixupBiosFcodeImage(port, image3Buf, image3Len, last); + } + else + image3Len = 0; + + imageLen = image1Len + image2Len + image3Len + image4Len + image5Len; + if (imageLen == 0) + { + if (valid) + { + image1Len = 512; + image1Buf = malloc(image1Len); + memset(image1Buf, 0xff, image1Len); + imageLen = image1Len; + } + else + return 1; + } + + imageBuf = (unsigned char *)malloc(imageLen); + imageOff = 0; + if (image1Buf != NULL) + { + memcpy(imageBuf + imageOff, image1Buf, image1Len); + imageOff += image1Len; + free(image1Buf); + } + if (image2Buf != NULL) + { + memcpy(imageBuf + imageOff, image2Buf, image2Len); + imageOff += image2Len; + free(image2Buf); + } + if (image3Buf != NULL) + { + memcpy(imageBuf + imageOff, image3Buf, image3Len); + imageOff += image3Len; + free(image3Buf); + } + if (image4Buf != NULL) + { + memcpy(imageBuf + imageOff, image4Buf, image4Len); + imageOff += image4Len; + free(image4Buf); + } + if (image5Buf != NULL) + { + memcpy(imageBuf + imageOff, image5Buf, image5Len); + imageOff += image5Len; + free(image5Buf); + } + + if (warn && noFlag == TRUE) + { + free(imageBuf); + return 0; + } + + if (warn || yesFlag == FALSE) + { + if (warn) + printf("\nAre you sure you want to continue? [Yes or No, default is No] "); + else + printf("\nDo you want to continue? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + { + free(imageBuf); + return 0; + } + } + + doFwDownload(port, MPI_FW_DOWNLOAD_ITYPE_BIOS, imageBuf, imageLen, 0); + + free(imageBuf); + + return 1; +} + + +int +doBiosFcodeUpload(MPT_PORT *port, unsigned char **outBuf, int *outLen, int type) +{ + char name[4][256]; + int file[4]; + int who; + unsigned char *imageBuf = NULL; + int imageLen; + int actualImageLen; + int offset; + unsigned char *buf; + int len; + int i; + int n; + PCIR *pcir; + int t; + int last; + + if (outBuf == NULL || outLen == NULL) + printf("Searching for BIOS and/or FCode images\n"); + + for (i = 0; i < 4; i++) + file[i] = -1; + + imageLen = 0x10000; + imageBuf = (unsigned char *)malloc(imageLen); + + offset = 0; + while (offset < 0x80000) + { + if (doFwUpload(port, MPI_FW_UPLOAD_ITYPE_BIOS_FLASH, imageBuf, imageLen, offset, &actualImageLen) != 1) + break; + + buf = imageBuf; + + n = (buf[0x01]<<8) + buf[0x00]; + if (n != 0xaa55 && n != 0xbb55) + { + break; + } + + n = (buf[0x19]<<8) + buf[0x18]; + + if (n + (int)sizeof *pcir >= imageLen) + { + // not all of the image is in the buffer, so quit now and read more of the image + free(imageBuf); + imageLen = n + (int)sizeof *pcir; + imageBuf = (unsigned char *)malloc(imageLen); + continue; + } + + pcir = (PCIR *)(buf + n); + + if (pcir->signature[0] != 'P' || + pcir->signature[1] != 'C' || + pcir->signature[2] != 'I' || + pcir->signature[3] != 'R') + { + break; + } + + len = get16(pcir->imageLength) * 512; + if (len > imageLen) + { + // not all of the image is in the buffer, so quit now and read more of the image + free(imageBuf); + imageLen = len; + imageBuf = (unsigned char *)malloc(imageLen); + continue; + } + + last = pcir->indicator & 0x80; + + if (outBuf == NULL || outLen == NULL) + { + printf("\n"); + + switch (pcir->type) + { + case 0: + n = getFileName(name[0], sizeof name[0], stdin, "x86 BIOS", 0); + who = 0; + break; + case 1: + n = getFileName(name[1], sizeof name[1], stdin, "FCode", 1); + who = 1; + break; + case 3: + n = getFileName(name[2], sizeof name[2], stdin, "EFI BIOS", 2); + who = 2; + break; + case 255: + if (buf[4] == 'L' && buf[5] == 'S' && buf[6] == 'I' && buf[7] == 'L' && buf[0x34] == 0x02) + { + if ((buf[0x3b] & 0xf0) == 0x10) + { + printf("Found x86 BIOS extended image\n"); + n = -1; + who = 0; + break; + } + if ((buf[0x3b] & 0xf0) == 0x30) + { + printf("Found EFI BIOS extended image\n"); + n = -1; + who = 2; + break; + } + } + default: + printf("Image type is unknown, enter filename: "); + n = getString(name[3], sizeof name[3], stdin); + who = 3; + break; + } + + if (n > 0) + { + fixupBiosFcodeImage(port, buf, len, 1); + + file[who] = open(name[who], O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + if (file[who] < 0) + { + printf("Open failure for file %s\n", name[who]); + perror("Error is"); + } + + t = write(file[who], buf, len); + if (t != len) + { + printf("Write failed for file %s, t = %x\n", name[who], t); + perror("Error is"); + } + else + printf("\nWrote %d bytes to file %s\n", len, name[who]); + } + + else if (n < 0) + { + if (file[who] >= 0) + { + fixupBiosFcodeImage(port, buf, len, 0); + + t = write(file[who], buf, len); + if (t != len) + { + printf("Write failed for file %s, t = %x\n", name[who], t); + perror("Error is"); + } + else + printf("\nWrote %d bytes to file %s\n", len, name[who]); + } + } + + else + { + printf("Image won't be uploaded\n"); + } + } + else + { + if (pcir->type == type) + { + *outBuf = (unsigned char *)malloc(len); + *outLen = len; + memcpy(*outBuf, buf, len); + } + else if (pcir->type == 255) + { + if (buf[4] == 'L' && buf[5] == 'S' && buf[6] == 'I' && buf[7] == 'L' && buf[0x34] == 0x02) + { + if (type == 0 && (buf[0x3b] & 0xf0) == 0x10) + { + *outBuf = (unsigned char *)realloc(*outBuf, *outLen + len); + memcpy(*outBuf + *outLen, buf, len); + *outLen = *outLen + len; + } + if (type == 3 && (buf[0x3b] & 0xf0) == 0x30) + { + *outBuf = (unsigned char *)realloc(*outBuf, *outLen + len); + memcpy(*outBuf + *outLen, buf, len); + *outLen = *outLen + len; + } + } + } + } + + offset += len; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + if (last) + { + // last image, so make sure we quit after this + break; + } + } + else + { + if (offset >= actualImageLen) + { + // last image, so make sure we quit after this + break; + } + } + } + + for (i = 0; i < 4; i++) + if (file[i] >= 0) + close(file[i]); + + free(imageBuf); + + return 1; +} + + +int +verifyBiosFcodeImage(MPT_PORT *port, unsigned char *buf, int len, int type) +{ + int n; + int n1; + int warn = 0; + PCIR *pcir; + int i; + U8 checksum; + + n = (buf[0x01]<<8) + buf[0x00]; + if (n != 0xaa55) + { + if (n == 0xbb55) + { + printf("\nThis appears to be the special non-functional (blank) image!\n"); + return 0; + } + if (!warn) + printf("\n"); + printf("Image's ROM signature %04x is invalid!\n", n); + warn = 1; + } + + if ((len % 512) != 0) + { + if (!warn) + printf("\n"); + printf("Image's length is not a multiple of 512 bytes!\n"); + printf(" The image appears to be corrupted, proceed with caution\n"); + warn = 1; + } + + /* if there's a what string, we will check the checksum even if it's not BIOS */ + for (i = 0; i < len; i++) + if (buf[i] == '@' && buf[i+1] == '(' && buf[i+2] == '#' && buf[i+3] == ')') + break; + + if (type == 0 || i < len) + { + checksum = 0; + for (i = 0; i < len; i++) + checksum += buf[i]; + + if (checksum != 0) + { + if (!warn) + printf("\n"); + printf("Image's checksum is invalid!\n"); + printf(" The image appears to be corrupted, proceed with caution\n"); + warn = 1; + } + } + + if (type == 1) + { + int len; + U32 checksum; + + len = get4bytes(buf, 0x38); + checksum = 0; + for (i = 0x3c; i < len + 0x34; i++) + checksum += buf[i]; + + while (checksum > 0xffff) + checksum -= 0xffff; + + checksum -= get2bytes(buf, 0x36); + + if (checksum != 0) + { + if (!warn) + printf("\n"); + printf("Image's FCode checksum is invalid!\n"); + printf(" The image appears to be corrupted, proceed with caution\n"); + warn = 1; + } + } + + n = (buf[0x19]<<8) + buf[0x18]; + + if (n + (int)sizeof *pcir < len) + { + pcir = (PCIR *)(buf + n); + + if (pcir->signature[0] != 'P' || + pcir->signature[1] != 'C' || + pcir->signature[2] != 'I' || + pcir->signature[3] != 'R') + { + if (!warn) + printf("\n"); + printf("Image's PCIR signature is invalid!\n"); + warn = 1; + } + + if (get16(pcir->vendorId) != MPI_MANUFACTPAGE_VENDORID_LSILOGIC) + { + if (!warn) + printf("\n"); + printf("Image's PCI Vendor ID %04x is not correct!\n", get16(pcir->vendorId)); + warn = 1; + } + + if (checkCompatible(get16(pcir->deviceId), port->deviceId, type) != 1) + { + if (!warn) + printf("\n"); + printf("Image's PCI Device ID %04x is not compatible!\n", get16(pcir->deviceId)); + warn = 1; + } + + if (pcir->type != type) + { + if (!warn) + printf("\n"); + printf("Image's PCI Type %d is not correct!\n", pcir->type); + warn = 1; + } + + n = get16(pcir->imageLength) * 512; + if (n < len) + { + n1 = (buf[0x01]<<8) + buf[0x00]; + if (n1 == 0xaa55) + { + n1 = (buf[n+0x19]<<8) + buf[n+0x18]; + + if (n + n1 + (int)sizeof *pcir < len) + { + pcir = (PCIR *)(buf + n + n1); + + if (pcir->signature[0] == 'P' || + pcir->signature[1] == 'C' || + pcir->signature[2] == 'I' || + pcir->signature[3] == 'R') + { +// printf("Image is in multiple parts, length check circumvented\n"); + n = len; + } + } + } + } + if (n != len) + { + if (!warn) + printf("\n"); + printf("Image's PCI Image Length %04x is not correct!\n", get16(pcir->imageLength)); + warn = 1; + } + } + else + { + if (!warn) + printf("\n"); + printf("Image's PCIR offset %04x is invalid!\n", n); + warn = 1; + } + + return warn; +} + + +int +splitBiosImage(MPT_PORT *port, unsigned char **buf1, int *len1, unsigned char **buf2, int *len2) +{ + int n; + PCIR *pcir; + + n = ((*buf1)[0x19]<<8) + (*buf1)[0x18]; + + if (n + (int)sizeof *pcir < *len1) + { + pcir = (PCIR *)(*buf1 + n); + + if (pcir->signature[0] == 'P' && + pcir->signature[1] == 'C' && + pcir->signature[2] == 'I' && + pcir->signature[3] == 'R') + { + n = get16(pcir->imageLength) * 512; + if (n < *len1) + { + *buf2 = (unsigned char *)malloc(*len1 - n); + *len2 = *len1 - n; + memcpy(*buf2, *buf1 + n, *len1 - n); + *buf1 = (unsigned char *)realloc(*buf1, n); + *len1 = n; + } + } + } + + return 1; +} + + +int +fixupBiosFcodeImage(MPT_PORT *port, unsigned char *buf, int len, int last) +{ + int n; + PCIR *pcir; + int type = 0; + int i; + U8 checksum; + + n = (buf[0x19]<<8) + buf[0x18]; + + if (n + (int)sizeof *pcir < len) + { + pcir = (PCIR *)(buf + n); + + if (pcir->signature[0] == 'P' && + pcir->signature[1] == 'C' && + pcir->signature[2] == 'I' && + pcir->signature[3] == 'R') + { + type = pcir->type; + if (type != 255) + pcir->deviceId = set16(port->deviceIdRaw); + + if (last) + pcir->indicator |= 0x80; + else + pcir->indicator &= ~0x80; + } + + n = get16(pcir->imageLength) * 512; + } + else + { + n = len; + } + + /* if there's a what string, we will fix up the checksum as long as it's not FCode */ + for (i = 0; i < len; i++) + if (buf[i] == '@' && buf[i+1] == '(' && buf[i+2] == '#' && buf[i+3] == ')') + break; + + if (type != 1 || i < len) + { + checksum = 0; + for (i = 0; i < n - 1; i++) + checksum += buf[i]; + buf[i] = -checksum; + } + + return 1; +} + + +int +doSeepromDownload(MPT_PORT *port) +{ + char name[256]; + unsigned char *imageBuf = NULL; + int imageLen; + int n; + + n = getFileName(name, sizeof name, stdin, "SEEPROM", 0); + if (n > 0) + { + if (readFile(name, &imageBuf, &imageLen) != 1) + return 0; + } + else + { + printf("Image won't be downloaded\n"); + return 1; + } + + if (doFwDownload(port, MPI_FW_DOWNLOAD_ITYPE_NVDATA, imageBuf, imageLen, 0) == 1) + { + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + printf("\n"); + printf("WARNING! The SEEPROM contains information (World Wide Names) that must\n"); + printf(" be unique for each port. Each port on a host adapter must have\n"); + printf(" its own WWNs, not copied from another host adapter. Please use\n"); + printf(" Manufacturing Page 3 to verify that the WWNs assigned to this\n"); + printf(" port are unique, and modify them if necessary.\n"); + } + } + + free(imageBuf); + + return 1; +} + + +int +doSeepromUpload(MPT_PORT *port) +{ + char name[256]; + int file; + unsigned char *imageBuf = NULL; + int imageLen; + int actualImageLen; + int offset; + int n; + int t; + + n = getFileName(name, sizeof name, stdin, "SEEPROM", 0); + if (n > 0) + { + file = open(name, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + if (file < 0) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + } + else + { + printf("Image won't be uploaded\n"); + return 1; + } + + imageLen = CHUNK_SIZE; + imageBuf = (unsigned char *)malloc(imageLen); + + offset = 0; + while (TRUE) + { + if (doFwUpload(port, MPI_FW_UPLOAD_ITYPE_NVDATA, imageBuf, imageLen, offset, &actualImageLen) != 1) + break; + + if (offset + imageLen > actualImageLen) + imageLen = actualImageLen - offset; + + t = write(file, imageBuf, imageLen); + if (t != imageLen) + { + printf("Write failed for file %s, t = %x\n", name, t); + perror("Error is"); + break; + } + + offset += imageLen; + if (offset >= actualImageLen) + break; + } + + printf("\nWrote %d bytes to file %s\n", offset, name); + + close(file); + + free(imageBuf); + + return 1; +} + + +char *deviceType[32] = +{ + "Disk", + "Tape", + "Printer", + "Processor", + "WriteOnce", + "CDROM", + "Scanner", + "Optical", + "Jukebox", + "Comm", + "0Ah", + "0Bh", + "RAIDArray", + "EnclServ", + "0Eh", + "0Fh", + "10h", + "11h", + "12h", + "13h", + "14h", + "15h", + "16h", + "17h", + "18h", + "19h", + "1Ah", + "1Bh", + "1Ch", + "1Dh", + "1Eh", + "" +}; + + +int +doScanForLuns(MPT_PORT *port, int flag , int option) +{ + int bus; + int target; + int lun; + unsigned char inq[36]; + char buf[32]; + int i; + int version; + int max_lun; + //int option; + + //printf("Number of LUN's to scan for, select an option: [1-10] "); + printf("Number of LUN's to scan for is %d \n", option- 800); + //option = getNumberAnswer(0, 10, 10); + //printf("option value %d \n", option); + + if (flag) + showPortInfoHeader(port); + + getDeviceInfoHeader(port, buf, sizeof buf); + + printf(" B___T___L Type Vendor Product Rev %s\n", buf); + + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + max_lun = 1; + + for (lun = 0; lun < max_lun; lun++) + { + if (doInquiry(port, bus, target, lun, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + if (lun == 0) + break; + else + continue; + } + + if (lun == 0) + { + getDeviceInfo(port, bus, target, buf, sizeof buf); + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + version = inq[2] & 0x07; + if (version > 1) + max_lun = option - 800; + //printf("option1 value %d \n", option); + if (version > 3) + max_lun = option - 800; + //printf("option2 value %d \n", option); + } + else + { + max_lun = option - 800; + //printf("option3 value %d \n", option); + } + //printf("max_lun value %d \n", max_lun); + } + else + { + if ((inq[0] & 0x1f) == 0x1f) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + if ((inq[0] & 0x1f) == 0x0d) + continue; + } + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + //printf("debug the max lun number \n"); + printf("%2d %3d %3d %-9s %-8.8s %-16.16s %-4.4s %s\n", + bus, target, lun, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32, lun == 0 ? buf : ""); + } /* next lun */ + } /* next target */ + } /* next bus */ + + showPortInfo(port); + + showHiddenDevices(port); + + return 1; +} + +int +doScanForDevices(MPT_PORT *port, int flag) +{ + int bus; + int target; + int lun; + unsigned char inq[36]; + char buf[32]; + int i; + int version; + int max_lun; + + if (flag) + showPortInfoHeader(port); + + getDeviceInfoHeader(port, buf, sizeof buf); + + printf(" B___T___L Type Vendor Product Rev %s\n", buf); + + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + max_lun = 1; + + for (lun = 0; lun < max_lun; lun++) + { + if (doInquiry(port, bus, target, lun, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + if (lun == 0) + break; + else + continue; + } + + if (lun == 0) + { + getDeviceInfo(port, bus, target, buf, sizeof buf); + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + version = inq[2] & 0x07; + if (version > 1) + max_lun = 8; + if (version > 3) + max_lun = 64; + } + else + { + max_lun = port->maxLuns; + } + } + else + { + if ((inq[0] & 0x1f) == 0x1f) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + if ((inq[0] & 0x1f) == 0x0d) + continue; + } + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + printf("%2d %3d %3d %-9s %-8.8s %-16.16s %-4.4s %s\n", + bus, target, lun, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32, lun == 0 ? buf : ""); + } /* next lun */ + } /* next target */ + } /* next bus */ + + showPortInfo(port); + + showHiddenDevices(port); + + return 1; +} + + +int +doConfigPage(MPT_PORT *port) +{ + ConfigReply_t rep; + U32 buf[256]; + int type; + int number; + U32 address; + U32 offset; + U32 value; + int i; + int n; + int t; + int attributes; + int action; + int changed; + + while (TRUE) + { + printf("Enter page type: [0-255 or RETURN to quit] "); + type = getNumberAnswer(0, 255, -1); + if (type < 0) + break; + + if (type == 15) + { + printf("\nPage type 15 is reserved!\n\n"); + continue; + } + + printf("Enter page number: [0-255 or RETURN to quit] "); + number = getNumberAnswer(0, 255, -1); + if (number < 0) + break; + + if ((type == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && (number == 0 || number == 1)) || + (type == MPI_CONFIG_PAGETYPE_FC_PORT && (number == 3 || number == 5)) || + (type == MPI_CONFIG_PAGETYPE_FC_DEVICE && number == 0) || + (type == MPI_CONFIG_PAGETYPE_RAID_VOLUME && (number == 0 || number == 1)) || + (type == MPI_CONFIG_PAGETYPE_RAID_PHYSDISK && (number == 0 || number == 1)) || + (type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER && (number == 0 || number == 1)) || + (type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE && (number == 0 || number == 1 || number == 2)) || + (type == MPI_CONFIG_EXTPAGETYPE_SAS_PHY && (number == 0 || number == 1 || number == 2 || number == 3 || number == 4)) || + (type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE && number == 0) || + (type == MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG && number == 0) || + (type == MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING && number == 0) || + (type == MPI2_CONFIG_EXTPAGETYPE_SAS_PORT && number == 0)) + { + printf("Enter page address: [00000000-FFFFFFFF or RETURN to quit] "); + if (getHexNumberAnswer(&address) == 0) + break; + } + else + address = 0; + + if (getConfigPageHeader(port, type, number, address, &rep) != 1) + { + printf("\nFailed to read page header -- that page might not exist\n\n"); + continue; + } + + attributes = rep.Header.PageType & MPI_CONFIG_PAGEATTR_MASK; + + if (attributes == MPI_CONFIG_PAGEATTR_PERSISTENT || + attributes == MPI_CONFIG_PAGEATTR_RO_PERSISTENT) + { + printf("Read NVRAM or current values? [0=NVRAM, 1=Current, default is 0] "); + t = getNumberAnswer(0, 1, 0); + if (t == 0) + action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM; + else + action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + } + else + action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + t = getConfigPageAction(port, action, type, number, address, buf, sizeof buf); + + if (t != 1 && action == MPI_CONFIG_ACTION_PAGE_READ_NVRAM) + { + printf("The current values for this page will be used instead\n"); + t = getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, type, number, address, buf, sizeof buf); + } + + if (t == 1) + { + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + n = get16(((pConfigExtendedPageHeader_t)buf)->ExtPageLength); + else + n = ((pConfigPageHeader_t)buf)->PageLength; + + if (n == 0) + { + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + n = get16(rep.ExtPageLength); + else + n = rep.Header.PageLength; + } + + printf("\n"); + for (i = 0; i < n; i++) + printf("%04x : %08x\n", i*4, get32x(buf[i])); + + if (attributes == MPI_CONFIG_PAGEATTR_CHANGEABLE || + attributes == MPI_CONFIG_PAGEATTR_PERSISTENT || + attributes == MPI_CONFIG_PAGEATTR_RO_PERSISTENT) + { + printf("\nDo you want to make changes? [Yes or No, default is No] "); + if (getYesNoAnswer(0) == 1) + { + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + i = sizeof(ConfigExtendedPageHeader_t); + else + i = sizeof(ConfigPageHeader_t); + + changed = FALSE; + + while (TRUE) + { + printf("Enter offset of value to change: [%04x-%04x or RETURN to quit] ", i, (n - 1) * 4); + while (TRUE) + { + t = getHexNumberAnswer(&offset); + if (t == 0) + break; + + if ((offset % 4) == 0) + { + offset /= 4; + if (offset >= (U32)(i / 4) && offset < (U32)n) + break; + } + + printf("Invalid answer, try again: "); + } + if (t == 0) + break; + + printf("Enter value: [00000000-FFFFFFFF or RETURN to not change] "); + + value = get32x(buf[offset]); + + if (parseHexNumberChange(&value) == 0) + continue; + + buf[offset] = set32x(value); + + changed = TRUE; + } + + if (changed == TRUE) + { + printf("\nDo you want to write your changes? [Yes or No, default is No] "); + if (getYesNoAnswer(0) == 1) + { + if (action == MPI_CONFIG_ACTION_PAGE_READ_NVRAM) + action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM; + else + action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + + if (type == MPI_CONFIG_PAGETYPE_MANUFACTURING && number == 2) + { + U8 checksum = 0xa5; + U8 *p = (U8 *)buf; + + p += 8; + t = n * 4 - 8; + switch (port->deviceId) + { + case MPI_MANUFACTPAGE_DEVICEID_FC919: t -= 4; break; + case MPI_MANUFACTPAGE_DEVICEID_FC929: t -= 4; break; + case MPI_MANUFACTPAGE_DEVICEID_FC919X: t -= 3; break; + case MPI_MANUFACTPAGE_DEVICEID_FC929X: t -= 3; break; + case MPI_MANUFACTPAGE_DEVICEID_FC939X: t -= 3; break; + case MPI_MANUFACTPAGE_DEVICEID_FC949X: t -= 3; break; + case MPI_MANUFACTPAGE_DEVICEID_FC949E: t -= 4; break; + default: t = 0; break; + } + if (t != 0) + { + for (i = 0; i < t; i++) + { + checksum += *p++; + } + *p = -checksum; + } + } + + if (type == MPI_CONFIG_PAGETYPE_MANUFACTURING) + doIocInit(port, MPI_WHOINIT_MANUFACTURER); + + if (setConfigPageAction(port, action, type, number, address, buf, sizeof buf) != 1) + printf("Failed to write changes!\n"); + else + printf("Changes have been written\n"); + + if (type == MPI_CONFIG_PAGETYPE_MANUFACTURING) + doIocInit(port, port->whoInit); + } + } + } + } + } + + printf("\n"); + } + + return 1; +} + + +int +doInterruptCoalescingValues(MPT_PORT *port, int timeout, int depth) +{ + IOCPage1_t *IOCPage1; + int length; + int flags; + + IOCPage1 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_IOC, 1, 0, &length); + if (IOCPage1 == NULL) + return 0; + + flags = get32(IOCPage1->Flags); + if (timeout != 0 && depth != 0) + { + flags |= MPI_IOCPAGE1_REPLY_COALESCING; + IOCPage1->Flags = set32(flags); + IOCPage1->CoalescingTimeout = set32(timeout); + IOCPage1->CoalescingDepth = depth; + } + else + { + flags &= ~MPI_IOCPAGE1_REPLY_COALESCING; + IOCPage1->Flags = set32(flags); + IOCPage1->CoalescingTimeout = 0; + IOCPage1->CoalescingDepth = 0; + } + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 1, 0, IOCPage1, length) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + free(IOCPage1); + return 0; + } + + free(IOCPage1); + + return 1; +} + + +int +doIocSettings(MPT_PORT *port) +{ + IOCPage1_t *IOCPage1; + int length; + int flags; + int timeout; + int depth; + int on; + int mode; + + IOCPage1 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_IOC, 1, 0, &length); + if (IOCPage1 == NULL) + return 0; + + flags = get32(IOCPage1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING; + timeout = get32(IOCPage1->CoalescingTimeout); + depth = IOCPage1->CoalescingDepth; + + if (timeout < 0) + timeout = 0; + if (timeout > 1000) + timeout = 1000; + if (depth < 0) + depth = 0; + if (depth > 128) + depth = 128; + + on = flags != 0 && timeout != 0 && depth != 0; + if (on) + printf("Interrupt Coalescing is enabled, timeout is %d microseconds, depth is %d\n", + timeout, depth); + else + printf("Interrupt Coalescing is disabled\n"); + + printf("Enable interrupt coalescing: [0=No, 1=Yes, default is %d] ", on); + on = getNumberAnswer(0, 1, on); + + if (on) + { + printf("Enter timeout: [1-1000, 0=disable, default is %d] ", timeout); + timeout = getNumberAnswer(0, 1000, timeout); + + printf("Enter depth: [1-128, 0=disable, default is %d] ", depth); + depth = getNumberAnswer(0, 128, depth); + } + else + { + timeout = 0; + depth = 0; + } + + flags = get32(IOCPage1->Flags); + if (on && timeout != 0 && depth != 0) + { + flags |= MPI_IOCPAGE1_REPLY_COALESCING; + IOCPage1->Flags = set32(flags); + IOCPage1->CoalescingTimeout = set32(timeout); + IOCPage1->CoalescingDepth = depth; + } + else + { + flags &= ~MPI_IOCPAGE1_REPLY_COALESCING; + IOCPage1->Flags = set32(flags); + IOCPage1->CoalescingTimeout = 0; + IOCPage1->CoalescingDepth = 0; + } + + switch (port->deviceId) + { + case MPI_MANUFACTPAGE_DEVICEID_FC939X: + case MPI_MANUFACTPAGE_DEVICEID_FC949X: + case MPI_MANUFACTPAGE_DEVICEID_FC949E: + flags = get32(IOCPage1->Flags); + mode = (flags & MPI_IOCPAGE1_EEDP_MODE_MASK) >> 24; + printf("\nEnd-to-End Data Protection Mode: [0=Disabled, 1=T10, 2=LB, default is %d] ", mode); + mode = getNumberAnswer(0, 2, mode); + flags &= ~MPI_IOCPAGE1_EEDP_MODE_MASK; + flags |= mode << 24; + IOCPage1->Flags = set32(flags); + break; + } + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 1, 0, IOCPage1, length) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + free(IOCPage1); + return 0; + } + + free(IOCPage1); + + return 1; +} + + +int +doScsiInitiatorSettings(MPT_PORT *port) +{ + SCSIPortPage1_t SCSIPortPage1; + SCSIPortPage2_t SCSIPortPage2; + int flags; + int settings; + int id; + int t; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 0, &SCSIPortPage2, sizeof SCSIPortPage2) != 1) + return 0; + + flags = get32(SCSIPortPage2.PortFlags); + settings = get32(SCSIPortPage2.PortSettings); + + id = settings & MPI_SCSIPORTPAGE2_PORT_HOST_ID_MASK; + printf("Host SCSI ID: [0-15, default is %d] ", id); + id = getNumberAnswer(0, 15, id); + settings &= ~MPI_SCSIPORTPAGE2_PORT_HOST_ID_MASK; + settings |= id; + + t = (flags & MPI_SCSIPORTPAGE2_PORT_FLAGS_SCAN_HIGH_TO_LOW) != 0; + printf("Bus scan order: [0=LowToHigh, 1=HighToLow, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + flags &= ~MPI_SCSIPORTPAGE2_PORT_FLAGS_SCAN_HIGH_TO_LOW; + else + flags |= MPI_SCSIPORTPAGE2_PORT_FLAGS_SCAN_HIGH_TO_LOW; + + t = (flags & MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) != 0; + printf("Avoid SCSI bus reset: [0=No, 1=Yes, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + flags &= ~MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET; + else + flags |= MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET; + + t = (flags & MPI_SCSIPORTPAGE2_PORT_FLAGS_ALTERNATE_CHS) != 0; + printf("CHS mapping: [0=PlugAndPlay, 1=AlternateCHS, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + flags &= ~MPI_SCSIPORTPAGE2_PORT_FLAGS_ALTERNATE_CHS; + else + flags |= MPI_SCSIPORTPAGE2_PORT_FLAGS_ALTERNATE_CHS; + + t = (settings & MPI_SCSIPORTPAGE2_PORT_REMOVABLE_MEDIA) >> 6; + printf("Removable media support: [0=None, 1=BootDrive, 2=AnyWithMedia, default is %d] ", t); + t = getNumberAnswer(0, 2, t); + settings &= ~MPI_SCSIPORTPAGE2_PORT_REMOVABLE_MEDIA; + settings |= t << 6; // what, no nice symbolic name I can use here? + + t = (settings & MPI_SCSIPORTPAGE2_PORT_SPINUP_DELAY_MASK) >> 8; + printf("Spinup delay (in seconds): [0-15, default is %d] ", t); + t = getNumberAnswer(0, 15, t); + settings &= ~MPI_SCSIPORTPAGE2_PORT_SPINUP_DELAY_MASK; + settings |= t << 8; // what, no nice symbolic name I can use here? + + SCSIPortPage2.PortFlags = set32(flags); + SCSIPortPage2.PortSettings = set32(settings); + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 0, &SCSIPortPage2, sizeof SCSIPortPage2) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, 0, &SCSIPortPage1, sizeof SCSIPortPage1) != 1) + return 0; + + SCSIPortPage1.Configuration = set32((1 << (id + 16)) | id); + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, 0, &SCSIPortPage1, sizeof SCSIPortPage1) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +char * +syncToMt(int sync) +{ + if (sync == 0) + return "Async"; + if (sync == 8) + return "160"; + if (sync == 9) + return "80"; + if (sync == 10) + return "40"; + if (sync == 12) + return "20"; + if (sync == 25) + return "10"; + if (sync == 50) + return "5"; + return ""; +} + + +char * +syncToMb(int sync, int wide) +{ + if (wide == 0) + return syncToMt(sync); + if (sync == 0) + return "Async"; + if (sync == 8) + return "320"; + if (sync == 9) + return "160"; + if (sync == 10) + return "80"; + if (sync == 12) + return "40"; + if (sync == 25) + return "20"; + if (sync == 50) + return "10"; + return ""; +} + + +int +doScsiTargetSettings(MPT_PORT *port) +{ + SCSIPortPage2_t SCSIPortPage2; + U8 timeout[16]; + U8 sync_factor[16]; + U16 device_flags[16]; + int id; + int sync; + int i; + int t; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 0, &SCSIPortPage2, sizeof SCSIPortPage2) != 1) + return 0; + + id = get32(SCSIPortPage2.PortSettings) & MPI_SCSIPORTPAGE2_PORT_HOST_ID_MASK; + + for (i = 0; i < 16; i++) + { + timeout[i] = SCSIPortPage2.DeviceSettings[i].Timeout; + sync_factor[i] = SCSIPortPage2.DeviceSettings[i].SyncFactor; + device_flags[i] = get16(SCSIPortPage2.DeviceSettings[i].DeviceFlags); + } + + while (TRUE) + { + printf("Target MB/sec | MT/sec Wide ScanID ScanLUNs Disconnect Timeout QueueTag Boot\n"); + for (i = 0; i < 16; i++) + printf(" %2d %5s | %5s %3s %3s %3s %3s %3d %3s %3s\n", + i, + syncToMb(sync_factor[i], + device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE ? 0 : 1), + syncToMt(sync_factor[i]), + device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE ? "No" : "Yes", + device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE ? "Yes" : "No", + device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE ? "Yes" : "No", + device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE ? "Yes" : "No", + timeout[i], + device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE ? "Yes" : "No", + device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_BOOT_CHOICE ? "Yes" : "No"); + printf("\nSelect a Target: [0-15, %d=AllTargets, RETURN to quit] ", id); + i = getNumberAnswer(0, 15, -1); + + if (i < 0) + break; + + switch (sync_factor[i]) + { + case 8: sync = 160; break; + case 9: sync = 80; break; + case 10: sync = 40; break; + case 12: sync = 20; break; + case 25: sync = 10; break; + case 50: sync = 5; break; + default: + case 0: sync = 0; break; + } + printf("\nMT/sec: [160, 80, 40, 20, 10, 5, 0=Async, default is %d] ", sync); + while (TRUE) + { + t = getNumberAnswer(0, 160, sync); + switch (t) + { + case 160: t = 8; break; + case 80: t = 9; break; + case 40: t = 10; break; + case 20: t = 12; break; + case 10: t = 25; break; + case 5: t = 50; break; + case 0: t = 0; break; + default: + printf("Invalid response, try again: "); + t = -1; + break; + } + if (t >= 0) + break; + } + sync_factor[i] = t; + + if (sync_factor[i] > 9 || sync_factor[i] == 0) + { + t = (device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE) == 0; + printf("Enable Wide: [0=No, 1=Yes, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 1) + device_flags[i] &= ~MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE; + else + device_flags[i] |= MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE; + } + else + device_flags[i] &= ~MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE; + + t = (device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE) != 0; + printf("Enable ScanID: [0=No, 1=Yes, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + device_flags[i] &= ~MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE; + else + device_flags[i] |= MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE; + + t = (device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE) != 0; + printf("Enable ScanLUNs: [0=No, 1=Yes, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + device_flags[i] &= ~MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE; + else + device_flags[i] |= MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE; + + t = (device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE) != 0; + printf("Enable Disconnect: [0=No, 1=Yes, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + device_flags[i] &= ~MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE; + else + device_flags[i] |= MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE; + + t = timeout[i]; + printf("Timeout: [0-255, default is %d] ", t); + t = getNumberAnswer(0, 255, t); + timeout[i] = t; + + t = (device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE) != 0; + printf("Enable QueueTag: [0=No, 1=Yes, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + device_flags[i] &= ~MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE; + else + device_flags[i] |= MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE; + + t = (device_flags[i] & MPI_SCSIPORTPAGE2_DEVICE_BOOT_CHOICE) != 0; + printf("Enable Boot: [0=No, 1=Yes, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + device_flags[i] &= ~MPI_SCSIPORTPAGE2_DEVICE_BOOT_CHOICE; + else + device_flags[i] |= MPI_SCSIPORTPAGE2_DEVICE_BOOT_CHOICE; + + if (i == id) + { + for (i = 0; i < 16; i++) + { + if (i != id) + { + timeout[i] = timeout[id]; + sync_factor[i] = sync_factor[id]; + device_flags[i] = device_flags[id]; + } + } + } + + printf("\n"); + } + + for (i = 0; i < 16; i++) + { + SCSIPortPage2.DeviceSettings[i].Timeout = timeout[i]; + SCSIPortPage2.DeviceSettings[i].SyncFactor = sync_factor[i]; + SCSIPortPage2.DeviceSettings[i].DeviceFlags = set16(device_flags[i]); + } + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 0, &SCSIPortPage2, sizeof SCSIPortPage2) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +int +doFcLinkSpeedValue(MPT_PORT *port, int t) +{ + FCPortPage0_t FCPortPage0; + FCPortPage1_t FCPortPage1; + int speeds; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, &FCPortPage0, sizeof FCPortPage0) != 1) + return 0; + + speeds = get32(FCPortPage0.SupportedSpeeds); + + switch (t) + { + case MPI_FCPORTPAGE1_LCONFIG_SPEED_1GIG: + speeds &= MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED; + break; + case MPI_FCPORTPAGE1_LCONFIG_SPEED_2GIG: + speeds &= MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED; + break; + case MPI_FCPORTPAGE1_LCONFIG_SPEED_4GIG: + speeds &= MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED; + break; + } + + if (speeds == 0) + { + printf("That link speed is not supported on this port!\n"); + return 0; + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + FCPortPage1.LinkConfig &= ~MPI_FCPORTPAGE1_LCONFIG_SPEED_MASK; + FCPortPage1.LinkConfig |= t; + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +int +doFcTopologyValue(MPT_PORT *port, int t) +{ + FCPortPage1_t FCPortPage1; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + FCPortPage1.TopologyConfig &= ~MPI_FCPORTPAGE1_TOPOLOGY_MASK; + FCPortPage1.TopologyConfig |= t; + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +int +doFcPortOffline(MPT_PORT *port) +{ + FCPortPage1_t FCPortPage1; + int flags; + + printf("Setting port offline\n"); + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + flags = get32(FCPortPage1.Flags); + flags |= MPI_FCPORTPAGE1_FLAGS_PORT_OFFLINE; + FCPortPage1.Flags = set32(flags); + + if (setConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to write changes!\n"); + return 0; + } + + return 1; +} + + +int +doFcPortOnline(MPT_PORT *port) +{ + FCPortPage1_t FCPortPage1; + int flags; + + printf("Setting port online\n"); + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + flags = get32(FCPortPage1.Flags); + flags &= ~MPI_FCPORTPAGE1_FLAGS_PORT_OFFLINE; + FCPortPage1.Flags = set32(flags); + + if (setConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to write changes!\n"); + return 0; + } + + return 1; +} + + +int +doFcTopologyNLPort(MPT_PORT *port) +{ + FCPortPage1_t FCPortPage1; + + printf("Setting port to NL_Port\n"); + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + FCPortPage1.TopologyConfig &= ~MPI_FCPORTPAGE1_TOPOLOGY_MASK; + FCPortPage1.TopologyConfig |= MPI_FCPORTPAGE1_TOPOLOGY_NLPORT; + + if (setConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to write changes!\n"); + return 0; + } + + return 1; +} + + +int +doFcTopologyNPort(MPT_PORT *port) +{ + FCPortPage1_t FCPortPage1; + + printf("Setting port to N_Port\n"); + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + FCPortPage1.TopologyConfig &= ~MPI_FCPORTPAGE1_TOPOLOGY_MASK; + FCPortPage1.TopologyConfig |= MPI_FCPORTPAGE1_TOPOLOGY_NPORT; + + if (setConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to write changes!\n"); + return 0; + } + + return 1; +} + + +int +doFcSpecialMode(MPT_PORT *port, int enable, int permanent) +{ + FCPortPage1_t FCPortPage1; + int flags; + + printf("%s special mode on port\n", enable ? "Enabling" : "Disabling"); + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + flags = get32(FCPortPage1.Flags); + if (enable) + flags |= 0x1000; + else + flags &= ~0x1000; + FCPortPage1.Flags = set32(flags); + + if (setConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to write changes!\n"); + return 0; + } + + if (permanent) + { + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_NVRAM, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + flags = get32(FCPortPage1.Flags); + if (enable) + flags |= 0x1000; + else + flags &= ~0x1000; + FCPortPage1.Flags = set32(flags); + + if (setConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to write changes!\n"); + return 0; + } + } + + return 1; +} + + +int +doFcPortSettings(MPT_PORT *port) +{ + FCPortPage0_t FCPortPage0; + FCPortPage1_t FCPortPage1; + FCPortPage4_t FCPortPage4; + int flags; + int speed; + int speeds; + int t; + U32 alpa; + int settings; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, &FCPortPage0, sizeof FCPortPage0) != 1) + return 0; + + speeds = get32(FCPortPage0.SupportedSpeeds); + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + t = FCPortPage1.TopologyConfig & MPI_FCPORTPAGE1_TOPOLOGY_MASK; + if (t == MPI_FCPORTPAGE1_TOPOLOGY_AUTO) + t = 0; + printf("Link topology: [0=Auto, 1=NL_Port, 2=N_Port, default is %d] ", t); + t = getNumberAnswer(0, 2, t); + if (t == 0) + t = MPI_FCPORTPAGE1_TOPOLOGY_AUTO; + FCPortPage1.TopologyConfig &= ~MPI_FCPORTPAGE1_TOPOLOGY_MASK; + FCPortPage1.TopologyConfig |= t; + + t = FCPortPage1.LinkConfig & MPI_FCPORTPAGE1_LCONFIG_SPEED_MASK; + if (t == MPI_FCPORTPAGE1_LCONFIG_SPEED_AUTO) + speed = 0; + else + speed = t + 1; + if (speeds & MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED) + { + if (speed == 4) + speed = 10; + else if (speed == 3) + speed = 4; + else if (speed > 3) + speed = 0; + printf("Link speed: [0=Auto, 1=1Gb, 2=2Gb, 4=4Gb, 10=10Gb, default is %d] ", speed); + while (TRUE) + { + t = getNumberAnswer(0, 10, speed); + if (t < 3 || t == 4 || t == 10) + break; + printf("Invalid response, try again: "); + } + if (t == 10) + t = 4; + else if (t == 4) + t = 3; + } + else if (speeds & MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED) + { + if (speed == 3) + speed = 4; + else if (speed > 3) + speed = 0; + printf("Link speed: [0=Auto, 1=1Gb, 2=2Gb, 4=4Gb, default is %d] ", speed); + while (TRUE) + { + t = getNumberAnswer(0, 4, speed); + if (t < 3 || t == 4) + break; + printf("Invalid response, try again: "); + } + if (t == 4) + t = 3; + } + else if (speeds & MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED) + { + if (speed > 2) + speed = 0; + printf("Link speed: [0=Auto, 1=1Gb, 2=2Gb, default is %d] ", speed); + t = getNumberAnswer(0, 2, speed); + } + else if (speeds & MPI_FCPORTPAGE1_LCONFIG_SPEED_1GIG) + { + t = 1; + } + else + { + t = 0; + } + if (t == 0) + t = MPI_FCPORTPAGE1_LCONFIG_SPEED_AUTO; + else + t--; + FCPortPage1.LinkConfig &= ~MPI_FCPORTPAGE1_LCONFIG_SPEED_MASK; + FCPortPage1.LinkConfig |= t; + + flags = get32(FCPortPage1.Flags); + + t = (flags & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT) != 0; + printf("FCP Initiator protocol: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + flags &= ~MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT; + else + flags |= MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT; + + t = (flags & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG) != 0; + printf("FCP Target protocol: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + flags &= ~MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG; + else + flags |= MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG; + + t = (flags & MPI_FCPORTPAGE1_FLAGS_PROT_LAN) != 0; + printf("LAN protocol: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + flags &= ~MPI_FCPORTPAGE1_FLAGS_PROT_LAN; + else + flags |= MPI_FCPORTPAGE1_FLAGS_PROT_LAN; + + t = (flags & MPI_FCPORTPAGE1_FLAGS_SORT_BY_DID) != 0; + printf("Assignment of Bus/Target IDs: [0=SortByWWN, 1=SortByDID, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + flags &= ~MPI_FCPORTPAGE1_FLAGS_SORT_BY_DID; + else + flags |= MPI_FCPORTPAGE1_FLAGS_SORT_BY_DID; + + t = (flags & MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY) != 0; + printf("Immediate Error Reply: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + flags &= ~MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY; + else + flags |= MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY; + + t = (flags & MPI_FCPORTPAGE1_FLAGS_MAINTAIN_LOGINS) != 0; + printf("Maintain Logins: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + flags &= ~MPI_FCPORTPAGE1_FLAGS_MAINTAIN_LOGINS; + else + flags |= MPI_FCPORTPAGE1_FLAGS_MAINTAIN_LOGINS; + + FCPortPage1.Flags = set32(flags); + + t = FCPortPage1.HardALPA; + printf("Hard AL_PA: [01 to EF, or FF for Soft AL_PA, default is %02x] ", t); + alpa = t; + while (TRUE) + { + t = getHexNumberAnswer(&alpa); + if (t == 0) + { + alpa = FCPortPage1.HardALPA; + break; + } + + if (alpa == 0xff) + break; + + if (alpa > 0x00 && alpa < 0xff && AlpaToLoopId[alpa] != 0xff) + break; + + printf("Invalid answer, try again: "); + } + FCPortPage1.HardALPA = (U8)alpa; + + t = FCPortPage1.InitiatorDeviceTimeout; + if (t == 0) + t = 60; + if (t & MPI_FCPORTPAGE1_INITIATOR_DEV_UNIT_16) + t = (t & ~MPI_FCPORTPAGE1_INITIATOR_DEV_UNIT_16) * 16; + printf("Initiator Device Timeout: [0 to 2047, default is %d] ", t); + t = getNumberAnswer(0, 2047, t); + if (t >= MPI_FCPORTPAGE1_INITIATOR_DEV_UNIT_16) + t = (t / 16) | MPI_FCPORTPAGE1_INITIATOR_DEV_UNIT_16; + if (t == 60) + t = 0; + FCPortPage1.InitiatorDeviceTimeout = t; + + t = FCPortPage1.InitiatorIoPendTimeout; + if (t == 0) + t = 8; + printf("Initiator I/O Pending Timeout: [0 to 127, default is %d] ", t); + t = getNumberAnswer(0, 127, t); + if (t == 8) + t = 0; + FCPortPage1.InitiatorIoPendTimeout = t; + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 4, 0, &FCPortPage4, sizeof FCPortPage4) != 1) + return 0; + + settings = get32(FCPortPage4.PortSettings); + + t = settings & MPI_FCPORTPAGE4_PORT_MASK_INIT_HBA; + printf("Enable booting under EFI BIOS: [Yes or No, default is %s] ", + t != MPI_FCPORTPAGE4_PORT_DISABLE_INIT_HBA ? "Yes" : "No"); + if (getYesNoAnswer(t != MPI_FCPORTPAGE4_PORT_DISABLE_INIT_HBA) == 0) + t = MPI_FCPORTPAGE4_PORT_DISABLE_INIT_HBA; + else if (t == MPI_FCPORTPAGE4_PORT_DISABLE_INIT_HBA) + t = MPI_FCPORTPAGE4_PORT_BIOS_OS_INIT_HBA; + + FCPortPage4.PortSettings = set32((settings & ~MPI_FCPORTPAGE4_PORT_MASK_INIT_HBA) | t); + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 4, 0, &FCPortPage4, sizeof FCPortPage4) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +int +doFcChangeWwn(MPT_PORT *port) +{ + ManufacturingPage3_t *ManufacturingPage3; + int length; + int t; + U32 *p; + U32 wwnn_l; + U32 wwnn_h; + U32 wwpn_l; + U32 wwpn_h; + + ManufacturingPage3 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 3, 0, &length); + if (ManufacturingPage3 == NULL) + return 0; + + p = (U32 *)ManufacturingPage3 + 2 + port->iocNumber * 8; + + wwnn_l = get32x(p[2]); + wwnn_h = get32x(p[3]); + wwpn_l = get32x(p[0]); + wwpn_h = get32x(p[1]); + + printf("Current FC WWNN = %08x%08x, WWPN = %08x%08x\n\n", wwnn_h, wwnn_l, wwpn_h, wwpn_l); + + printf("Enter new WWNN: [16 hex digits or RETURN to quit] "); + t = getHexDoubleNumberAnswer(&wwnn_h, &wwnn_l); + if (t == 0) + { + free(ManufacturingPage3); + return 1; + } + + printf("Enter new WWPN: [16 hex digits or RETURN to quit] "); + t = getHexDoubleNumberAnswer(&wwpn_h, &wwpn_l); + if (t == 0) + { + free(ManufacturingPage3); + return 1; + } + + p[2] = set32x(wwnn_l); + p[3] = set32x(wwnn_h); + p[0] = set32x(wwpn_l); + p[1] = set32x(wwpn_h); + + doIocInit(port, MPI_WHOINIT_MANUFACTURER); + + t = setConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 3, 0, ManufacturingPage3, length); + + doIocInit(port, port->whoInit); + + free(ManufacturingPage3); + + if (t != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +int +doSasPhyOnOffline(MPT_PORT *port, int onoff) +{ + SasDevicePage0_t SASDevicePage0; + SasExpanderPage0_t SASExpanderPage0; + SasExpanderPage1_t SASExpanderPage1; + SasIOUnitPage1_t *SASIOUnitPage1; + SasIoUnitControlRequest_t req; + SasIoUnitControlReply_t rep; + int length; + int handle; + int phy; + int min_phy; + int max_phy; + int dev_info; + int dev_type; + unsigned char phy_control_req[40]; + unsigned char phy_control_rsp[4]; + int parent; + int attached; + int t; + + printf("Enter handle: [0000-FFFF or RETURN to quit] "); + handle = getNumberAnswerHex(0x0000, 0xffff, -1); + if (handle < 0) + return 0; + + if (handle == 0) + { + min_phy = 0; + max_phy = port->numPhys - 1; + parent = 0; + } + else + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE + <PhyData[phy].PhyFlags &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; + else + SASIOUnitPage1->PhyData[phy].PhyFlags |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; + } + else + { + if (onoff) + SASIOUnitPage1->PhyData[phy].PhyFlags &= ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; + else + SASIOUnitPage1->PhyData[phy].PhyFlags |= MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; + } + + t = setConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, + MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 1, 0, SASIOUnitPage1, length); + + free(SASIOUnitPage1); + + if (t != 1) + { + printf("Failed to write changes!\n"); + return 0; + } + + if (!onoff) + { + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; + req.Operation = MPI_SAS_OP_PHY_LINK_RESET; + req.PhyNum = phy; + + doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); + } + } + else + { + if (!onoff && yesFlag == FALSE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 1, + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM + <NumPhys; + + t = SASIOUnitPage1->SATAMaxQDepth; + printf("SATA Maximum Queue Depth: [0 to 255, default is %d] ", t); + t = getNumberAnswer(0, 255, t); + SASIOUnitPage1->SATAMaxQDepth = t; + + if (mpi2) + { + SASIOUnitPage1_2 = (pMpi2SasIOUnitPage1_t)SASIOUnitPage1; + + t = get16(SASIOUnitPage1_2->SASNarrowMaxQueueDepth); + printf("SAS Max Queue Depth, Narrow: [0 to 65535, default is %d] ", t); + t = getNumberAnswer(0, 65535, t); + SASIOUnitPage1_2->SASNarrowMaxQueueDepth = set16(t); + + t = get16(SASIOUnitPage1_2->SASWideMaxQueueDepth); + printf("SAS Max Queue Depth, Wide: [0 to 65535, default is %d] ", t); + t = getNumberAnswer(0, 65535, t); + SASIOUnitPage1_2->SASWideMaxQueueDepth = set16(t); + } + + t = SASIOUnitPage1->ReportDeviceMissingDelay; + if (t & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) + t = (t & ~MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) * 16; + printf("Device Missing Report Delay: [0 to 2047, default is %d] ", t); + t = getNumberAnswer(0, 2047, t); + if (t >= MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) + t = (t / 16) | MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16; + SASIOUnitPage1->ReportDeviceMissingDelay = t; + + t = SASIOUnitPage1->IODeviceMissingDelay; + printf("Device Missing I/O Delay: [0 to 255, default is %d] ", t); + t = getNumberAnswer(0, 127, t); + SASIOUnitPage1->IODeviceMissingDelay = t; + + while (TRUE) + { + printf("\nPhyNum Link MinRate MaxRate Initiator Target Port\n"); + for (i = 0; i < num_phys; i++) + { + if (mpi2) + flags = SASIOUnitPage1->PhyData[i].PhyFlags & MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; + else + flags = SASIOUnitPage1->PhyData[i].PhyFlags & MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; + min = SASIOUnitPage1->PhyData[i].MaxMinLinkRate & MPI_SAS_IOUNIT1_MIN_RATE_MASK; + max = SASIOUnitPage1->PhyData[i].MaxMinLinkRate & MPI_SAS_IOUNIT1_MAX_RATE_MASK; + dev_info = get32(SASIOUnitPage1->PhyData[i].ControllerPhyDeviceInfo); + if (SASIOUnitPage1->PhyData[i].PortFlags & MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG) + sprintf(sas_port, "Auto"); + else + sprintf(sas_port, " %d ", SASIOUnitPage1->PhyData[i].Port); + printf(" %2d %s %s %s %s %s %s\n", i, + flags ? "Disabled" : "Enabled ", + min == MPI25_SASIOUNIT1_MIN_RATE_12_0 ? "12.0" : + min == MPI2_SASIOUNIT1_MIN_RATE_6_0 ? "6.0" : + min == MPI_SAS_IOUNIT1_MIN_RATE_3_0 ? "3.0" : "1.5", + max == MPI25_SASIOUNIT1_MAX_RATE_12_0 ? "12.0" : + max == MPI2_SASIOUNIT1_MAX_RATE_6_0 ? "6.0" : + max == MPI_SAS_IOUNIT1_MAX_RATE_3_0 ? "3.0" : "1.5", + dev_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR ? "Enabled " : "Disabled", + dev_info & MPI_SAS_DEVICE_INFO_SSP_TARGET ? "Enabled " : "Disabled", + sas_port); + } + printf("\nSelect a Phy: [0-%d, %d=AllPhys, RETURN to quit] ", num_phys - 1, num_phys); + i = getNumberAnswer(0, num_phys, -1); + + if (i < 0) + break; + + if (i < num_phys) + { + if (mpi2) + flags = SASIOUnitPage1->PhyData[i].PhyFlags & MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; + else + flags = SASIOUnitPage1->PhyData[i].PhyFlags & MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; + min = SASIOUnitPage1->PhyData[i].MaxMinLinkRate & MPI_SAS_IOUNIT1_MIN_RATE_MASK; + max = SASIOUnitPage1->PhyData[i].MaxMinLinkRate & MPI_SAS_IOUNIT1_MAX_RATE_MASK; + dev_info = get32(SASIOUnitPage1->PhyData[i].ControllerPhyDeviceInfo); + + t = flags == 0; + printf("Link: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (mpi2) + { + if (t == 1) + SASIOUnitPage1->PhyData[i].PhyFlags &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; + else + SASIOUnitPage1->PhyData[i].PhyFlags |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; + } + else + { + if (t == 1) + SASIOUnitPage1->PhyData[i].PhyFlags &= ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; + else + SASIOUnitPage1->PhyData[i].PhyFlags |= MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; + } + + switch (min) + { + default: + case MPI_SAS_IOUNIT1_MIN_RATE_1_5: t = 0; break; + case MPI_SAS_IOUNIT1_MIN_RATE_3_0: t = 1; break; + case MPI2_SASIOUNIT1_MIN_RATE_6_0: t = 2; break; + case MPI25_SASIOUNIT1_MIN_RATE_12_0: t = 3; break; + } + if (mpi20) + { + printf("MinRate: [0=1.5 Gbps, 1=3.0 Gbps, 2=6.0 Gbps, default is %d] ", t); + t = getNumberAnswer(0, 2, t); + } + else if (mpi25) + { + printf("MinRate: [0=1.5 Gbps, 1=3.0 Gbps, 2=6.0 Gbps, 3=12.0 Gbps, default is %d] ", t); + t = getNumberAnswer(0, 3, t); + } + else + { + printf("MinRate: [0=1.5 Gbps, 1=3.0 Gbps, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + } + switch (t) + { + case 0: min = MPI_SAS_IOUNIT1_MIN_RATE_1_5; break; + case 1: min = MPI_SAS_IOUNIT1_MIN_RATE_3_0; break; + case 2: min = MPI2_SASIOUNIT1_MIN_RATE_6_0; break; + case 3: min = MPI25_SASIOUNIT1_MIN_RATE_12_0; break; + } + SASIOUnitPage1->PhyData[i].MaxMinLinkRate &= ~MPI_SAS_IOUNIT1_MIN_RATE_MASK; + SASIOUnitPage1->PhyData[i].MaxMinLinkRate |= min; + + switch (max) + { + default: + case MPI_SAS_IOUNIT1_MAX_RATE_1_5: t = 0; break; + case MPI_SAS_IOUNIT1_MAX_RATE_3_0: t = 1; break; + case MPI2_SASIOUNIT1_MAX_RATE_6_0: t = 2; break; + case MPI25_SASIOUNIT1_MAX_RATE_12_0: t = 3; break; + } + if (mpi20) + { + printf("MaxRate: [0=1.5 Gbps, 1=3.0 Gbps, 2=6.0 Gbps, default is %d] ", t); + t = getNumberAnswer(0, 2, t); + } + else if (mpi25) + { + printf("MaxRate: [0=1.5 Gbps, 1=3.0 Gbps, 2=6.0 Gbps, 3=12.0 Gbps, default is %d] ", t); + t = getNumberAnswer(0, 3, t); + } + else + { + printf("MaxRate: [0=1.5 Gbps, 1=3.0 Gbps, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + } + switch (t) + { + case 0: max = MPI_SAS_IOUNIT1_MAX_RATE_1_5; break; + case 1: max = MPI_SAS_IOUNIT1_MAX_RATE_3_0; break; + case 2: max = MPI2_SASIOUNIT1_MAX_RATE_6_0; break; + case 3: max = MPI25_SASIOUNIT1_MAX_RATE_12_0; break; + } + SASIOUnitPage1->PhyData[i].MaxMinLinkRate &= ~MPI_SAS_IOUNIT1_MAX_RATE_MASK; + SASIOUnitPage1->PhyData[i].MaxMinLinkRate |= max; + + t = (dev_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR) != 0; + printf("Initiator: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 1) + dev_info |= (MPI_SAS_DEVICE_INFO_SSP_INITIATOR | + MPI_SAS_DEVICE_INFO_STP_INITIATOR | + MPI_SAS_DEVICE_INFO_SMP_INITIATOR); + else + dev_info &= ~(MPI_SAS_DEVICE_INFO_SSP_INITIATOR | + MPI_SAS_DEVICE_INFO_STP_INITIATOR | + MPI_SAS_DEVICE_INFO_SMP_INITIATOR); + + t = (dev_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) != 0; + printf("Target: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 1) + dev_info |= MPI_SAS_DEVICE_INFO_SSP_TARGET; + else + dev_info &= ~MPI_SAS_DEVICE_INFO_SSP_TARGET; + + SASIOUnitPage1->PhyData[i].ControllerPhyDeviceInfo = set32(dev_info); + + if (SASIOUnitPage1->PhyData[i].PortFlags & MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG) + t = num_phys; + else + t = SASIOUnitPage1->PhyData[i].Port; + printf("Port: [0 to %d for manual config, %d for auto config, default is %d] ", + num_phys - 1, num_phys, t); + t = getNumberAnswer(0, num_phys, t); + if (t == num_phys) + { + SASIOUnitPage1->PhyData[i].PortFlags |= MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG; + SASIOUnitPage1->PhyData[i].Port = 0; + } + else + { + SASIOUnitPage1->PhyData[i].PortFlags &= ~MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG; + SASIOUnitPage1->PhyData[i].Port = t; + } + } + else + { + printf("Link: [0=Disabled, 1=Enabled, or RETURN to not change] "); + flags = getNumberAnswer(0, 1, -1); + + if (mpi20) + { + printf("MinRate: [0=1.5 Gbps, 1=3.0 Gbps, 2=6.0 Gbps, or RETURN to not change] "); + min = getNumberAnswer(0, 2, -1); + + printf("MaxRate: [0=1.5 Gbps, 1=3.0 Gbps, 2=6.0 Gbps, or RETURN to not change] "); + max = getNumberAnswer(0, 2, -1); + } + if (mpi25) + { + printf("MinRate: [0=1.5 Gbps, 1=3.0 Gbps, 2=6.0 Gbps, 3=12.0 Gbps, or RETURN to not change] "); + min = getNumberAnswer(0, 3, -1); + + printf("MaxRate: [0=1.5 Gbps, 1=3.0 Gbps, 2=6.0 Gbps, 3=12.0 Gpbs, or RETURN to not change] "); + max = getNumberAnswer(0, 3, -1); + } + else + { + printf("MinRate: [0=1.5 Gbps, 1=3.0 Gbps, or RETURN to not change] "); + min = getNumberAnswer(0, 1, -1); + + printf("MaxRate: [0=1.5 Gbps, 1=3.0 Gbps, or RETURN to not change] "); + max = getNumberAnswer(0, 1, -1); + } + switch (min) + { + case 0: min = MPI_SAS_IOUNIT1_MIN_RATE_1_5; break; + case 1: min = MPI_SAS_IOUNIT1_MIN_RATE_3_0; break; + case 2: min = MPI2_SASIOUNIT1_MIN_RATE_6_0; break; + case 3: min = MPI25_SASIOUNIT1_MIN_RATE_12_0; break; + } + switch (max) + { + case 0: max = MPI_SAS_IOUNIT1_MAX_RATE_1_5; break; + case 1: max = MPI_SAS_IOUNIT1_MAX_RATE_3_0; break; + case 2: max = MPI2_SASIOUNIT1_MAX_RATE_6_0; break; + case 3: max = MPI25_SASIOUNIT1_MAX_RATE_12_0; break; + } + + printf("Initiator: [0=Disabled, 1=Enabled, or RETURN to not change] "); + init = getNumberAnswer(0, 1, -1); + + printf("Target: [0=Disabled, 1=Enabled, or RETURN to not change] "); + targ = getNumberAnswer(0, 1, -1); + if (t == 1) + dev_info |= MPI_SAS_DEVICE_INFO_SSP_TARGET; + + printf("Port configuration: [1=Auto, 2=Narrow, 3=Wide, or RETURN to not change] "); + port_config = getNumberAnswer(0, 3, -1); + + for (i = 0; i < num_phys; i++) + { + if (mpi2) + { + if (flags == 0) + SASIOUnitPage1->PhyData[i].PhyFlags |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; + if (flags == 1) + SASIOUnitPage1->PhyData[i].PhyFlags &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; + } + else + { + if (flags == 0) + SASIOUnitPage1->PhyData[i].PhyFlags |= MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; + if (flags == 1) + SASIOUnitPage1->PhyData[i].PhyFlags &= ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; + } + + if (min != -1) + { + SASIOUnitPage1->PhyData[i].MaxMinLinkRate &= ~MPI_SAS_IOUNIT1_MIN_RATE_MASK; + SASIOUnitPage1->PhyData[i].MaxMinLinkRate |= min; + } + + if (max != -1) + { + SASIOUnitPage1->PhyData[i].MaxMinLinkRate &= ~MPI_SAS_IOUNIT1_MAX_RATE_MASK; + SASIOUnitPage1->PhyData[i].MaxMinLinkRate |= max; + } + + t = get32(SASIOUnitPage1->PhyData[i].ControllerPhyDeviceInfo); + if (init == 0) + t &= ~(MPI_SAS_DEVICE_INFO_SSP_INITIATOR | + MPI_SAS_DEVICE_INFO_STP_INITIATOR | + MPI_SAS_DEVICE_INFO_SMP_INITIATOR); + if (init == 1) + t |= (MPI_SAS_DEVICE_INFO_SSP_INITIATOR | + MPI_SAS_DEVICE_INFO_STP_INITIATOR | + MPI_SAS_DEVICE_INFO_SMP_INITIATOR); + if (targ == 0) + t &= ~MPI_SAS_DEVICE_INFO_SSP_TARGET; + if (targ == 1) + t |= MPI_SAS_DEVICE_INFO_SSP_TARGET; + SASIOUnitPage1->PhyData[i].ControllerPhyDeviceInfo = set32(t); + + if (port_config == 1) + { + SASIOUnitPage1->PhyData[i].PortFlags |= MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG; + SASIOUnitPage1->PhyData[i].Port = 0; + } + if (port_config == 2) + { + SASIOUnitPage1->PhyData[i].PortFlags &= ~MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG; + SASIOUnitPage1->PhyData[i].Port = i; + } + if (port_config == 3) + { + SASIOUnitPage1->PhyData[i].PortFlags &= ~MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG; + SASIOUnitPage1->PhyData[i].Port = i / 4; + } + } + } + } + + if (setConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 1, 0, SASIOUnitPage1, length) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + free(SASIOUnitPage1); + return 0; + } + + if (mpi1) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 2, 0, + &SASIOUnitPage2, sizeof SASIOUnitPage2) != 1) + { + free(SASIOUnitPage1); + return 0; + } + + flags = SASIOUnitPage2.Flags; + + t = (flags & MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS) == 0; + printf("\nPersistence: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 1) + flags &= ~MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS; + else + flags |= MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS; + + t = (flags & MPI_SAS_IOUNIT2_FLAGS_MASK_PHYS_MAP_MODE) >> MPI_SAS_IOUNIT2_FLAGS_SHIFT_PHYS_MAP_MODE; + printf("Physical mapping: [0=None, 1=DirectAttach, 2=EnclosureSlot, default is %d] ", t); + t = getNumberAnswer(0, 2, t); + flags &= ~MPI_SAS_IOUNIT2_FLAGS_MASK_PHYS_MAP_MODE; + flags |= t << MPI_SAS_IOUNIT2_FLAGS_SHIFT_PHYS_MAP_MODE; + + SASIOUnitPage2.Flags = flags; + + if (t != MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP) + { + t = get16(SASIOUnitPage2.MaxNumPhysicalMappedIDs); + if (t == 0) + t = num_phys; + if (t > 32) + t = 32; + printf("Number of Target IDs to reserve: [0 to 32, default is %d] ", t); + t = getNumberAnswer(0, 32, t); + + SASIOUnitPage2.MaxNumPhysicalMappedIDs = set16(t); + } + + if (setConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 2, 0, + &SASIOUnitPage2, sizeof SASIOUnitPage2) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + free(SASIOUnitPage1); + return 0; + } + } + + free(SASIOUnitPage1); + + return 1; +} + + +int +doSasChangeWwid(MPT_PORT *port, int checkZero) +{ + ManufacturingPage5_t *ManufacturingPage5; + Mpi2ManufacturingPage5_t *ManufacturingPage5_2; + int length; + int t; + int i; + U32 wwid_l; + U32 wwid_h; + + ManufacturingPage5 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 5, 0, &length); + if (ManufacturingPage5 == NULL) + return 0; + + ManufacturingPage5_2 = (pMpi2ManufacturingPage5_t)ManufacturingPage5; + + if (mpi2) + { + wwid_l = get32(ManufacturingPage5_2->Phy[0].WWID.Low); + wwid_h = get32(ManufacturingPage5_2->Phy[0].WWID.High); + } + else + { + wwid_l = get32(ManufacturingPage5->BaseWWID.Low); + wwid_h = get32(ManufacturingPage5->BaseWWID.High); + } + + if (checkZero) + { + free(ManufacturingPage5); + + return wwid_l == 0 && wwid_h == 0; + } + + printf("Current SAS WWID = %08x%08x\n\n", wwid_h, wwid_l); + + printf("Enter new WWID: [16 hex digits or RETURN to quit] "); + t = getHexDoubleNumberAnswer(&wwid_h, &wwid_l); + if (t == 0) + { + free(ManufacturingPage5); + return 0; + } + + if (mpi2) + { + for(i = 0; i < port->numPhys; i++) + { + ManufacturingPage5_2->Phy[i].WWID.Low = set32(wwid_l + i); + ManufacturingPage5_2->Phy[i].WWID.High = set32(wwid_h); + } + } + else + { + ManufacturingPage5->BaseWWID.Low = set32(wwid_l); + ManufacturingPage5->BaseWWID.High = set32(wwid_h); + } + + doIocInit(port, MPI_WHOINIT_MANUFACTURER); + + t = setConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 5, 0, ManufacturingPage5, length); + + doIocInit(port, port->whoInit); + + free(ManufacturingPage5); + + if (t != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +int +doIoUnitSettings(MPT_PORT *port) +{ + IOUnitPage1_t IOUnitPage1; + int flags; + int t; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 1, 0, &IOUnitPage1, sizeof IOUnitPage1) != 1) + return 0; + + flags = get32(IOUnitPage1.Flags); + + t = (flags & MPI_IOUNITPAGE1_MULTI_PATHING) != 0; + printf("Multi-pathing: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 0) + flags &= ~MPI_IOUNITPAGE1_MULTI_PATHING; + else + flags |= MPI_IOUNITPAGE1_MULTI_PATHING; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + t = (flags & MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE) == 0; + printf("SATA Native Command Queuing: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 1) + flags &= ~MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE; + else + flags |= MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE; + + t = (flags & MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE) == 0; + printf("SATA Write Caching: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 1) + flags &= ~MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE; + else + flags |= MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE; + } + + IOUnitPage1.Flags = set32(flags); + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 1, 0, &IOUnitPage1, sizeof IOUnitPage1) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +int +doFcPersistentMappings(MPT_PORT *port, int command) +{ + FCPortPage1_t FCPortPage1; + FCPortPage3_t *FCPortPage3; + FCDevicePage0_t FCDevicePage0; + int sort_by_did; + int do_by_entry; + int i; + int j; + int loop_id; + int t; + int flags; + int bus; + int target; + int b_t; + int n; + int *changed; + int n_changed; + char *type; + int d_id = 0; + U32 wwnn_l; + U32 wwnn_h; + U32 wwpn_l; + U32 wwpn_h; + + if (bringOnline(port) != 1) + return 0; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + sort_by_did = get32(FCPortPage1.Flags) & MPI_FCPORTPAGE1_FLAGS_SORT_BY_DID; + + n = port->maxPersistentIds * sizeof(PersistentData_t) + sizeof(ConfigPageHeader_t); + FCPortPage3 = (pFCPortPage3_t)malloc(n); + changed = (int *)malloc(port->maxPersistentIds * sizeof *changed); + + if (n > 255 * 4) + { + FCPortPage3_t tempFCPortPage3; + + do_by_entry = 1; + + for (i = 0; i < port->maxPersistentIds; i++) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 3, + MPI_FC_PORT_PGAD_FORM_INDEX + i, + &tempFCPortPage3, sizeof tempFCPortPage3) != 1) + { + free(FCPortPage3); + free(changed); + return 0; + } + + FCPortPage3->Entry[i] = tempFCPortPage3.Entry[0]; + } + + FCPortPage3->Header = tempFCPortPage3.Header; + + n = port->maxPersistentIds; + } + else + { + do_by_entry = 0; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 3, 0, FCPortPage3, n) != 1) + { + free(FCPortPage3); + free(changed); + return 0; + } + + n = (FCPortPage3->Header.PageLength * 4 - sizeof(ConfigPageHeader_t)) / sizeof(PersistentData_t); + } + memset(changed, 0, port->maxPersistentIds * sizeof *changed); + n_changed = 0; + + if (command == 1 || command == 4 || command == 5) + { + j = 0; + for (i = 0; i < n; i++) + { + flags = get16(FCPortPage3->Entry[i].Flags); + if (flags & MPI_PERSISTENT_FLAGS_ENTRY_VALID) + { + j++; + if (flags & MPI_PERSISTENT_FLAGS_BY_DID) + { + printf("Persistent entry %d is valid, Bus %d Target %d is DID %06x\n", i, + FCPortPage3->Entry[i].Bus, + FCPortPage3->Entry[i].TargetID, + get32(FCPortPage3->Entry[i].PhysicalIdentifier.Did)); + if (!sort_by_did) + printf(" Since the port is in SortByWWN mode, this entry is being ignored\n"); + } + else + { + printf("Persistent entry %d is valid, Bus %d Target %d is WWN %08x%08x\n", i, + FCPortPage3->Entry[i].Bus, + FCPortPage3->Entry[i].TargetID, + get32(FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWPN.High), + get32(FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWPN.Low)); + if (sort_by_did) + printf(" Since the port is in SortByDID mode, this entry is being ignored\n"); + } + if (command == 5) + { + printf(" Delete the entry for this target? [Yes or No, default is No] "); + if (getYesNoAnswer(0) != 1) + continue; + } + if (command == 4 || command == 5) + { + printf(" Deleting persistent entry %d\n", i); + flags &= ~MPI_PERSISTENT_FLAGS_ENTRY_VALID; + FCPortPage3->Entry[i].Flags = set16(flags); + changed[i] = 1; + n_changed++; + } + } + } + + if (j == 0) + printf("No persistent entries found\n"); + } + + if (command == 2 || command == 3) + { + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + b_t = (bus << 8) + target; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, + MPI_FC_DEVICE_PGAD_FORM_BUS_TID + b_t, + &FCDevicePage0, sizeof FCDevicePage0) != 1) + continue; + + if (sort_by_did) + printf("Bus %d Target %d is DID %06x\n", bus, target, + get32(FCDevicePage0.PortIdentifier)); + else + printf("Bus %d Target %d is WWN %08x%08x\n", bus, target, + get32(FCDevicePage0.WWPN.High), get32(FCDevicePage0.WWPN.Low)); + for (i = 0; i < n; i++) + { + if (get16(FCPortPage3->Entry[i].Flags) & MPI_PERSISTENT_FLAGS_ENTRY_VALID) + { + if (FCPortPage3->Entry[i].Bus != bus || + FCPortPage3->Entry[i].TargetID != target) + { + continue; + } + + if (sort_by_did) + { + if (FCPortPage3->Entry[i].PhysicalIdentifier.Did == FCDevicePage0.PortIdentifier) + { + break; + } + } + else + { + if (FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWPN.High == FCDevicePage0.WWPN.High && + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWPN.Low == FCDevicePage0.WWPN.Low && + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWNN.High == FCDevicePage0.WWNN.High && + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWNN.Low == FCDevicePage0.WWNN.Low) + { + break; + } + } + } + } + if (i < n) + { + printf(" Persistent entry %d is already valid for this target!\n", i); + continue; + } + + for (i = 0; i < n; i++) + { + if (!(get16(FCPortPage3->Entry[i].Flags) & MPI_PERSISTENT_FLAGS_ENTRY_VALID)) + { + break; + } + } + if (i < n) + { + if (command == 3) + { + printf(" Add an entry for this target? [Yes or No, default is No] "); + if (getYesNoAnswer(0) != 1) + continue; + } + + printf(" Adding persistent entry %d\n", i); + + flags = MPI_PERSISTENT_FLAGS_ENTRY_VALID | + MPI_PERSISTENT_FLAGS_SCAN_ID | + MPI_PERSISTENT_FLAGS_SCAN_LUNS; + FCPortPage3->Entry[i].Flags = set16(flags); + FCPortPage3->Entry[i].Bus = bus; + FCPortPage3->Entry[i].TargetID = target; + if (sort_by_did) + { + flags |= MPI_PERSISTENT_FLAGS_BY_DID; + FCPortPage3->Entry[i].Flags = set16(flags); + FCPortPage3->Entry[i].PhysicalIdentifier.Did = FCDevicePage0.PortIdentifier; + } + else + { + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWPN.High = FCDevicePage0.WWPN.High; + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWPN.Low = FCDevicePage0.WWPN.Low; + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWNN.High = FCDevicePage0.WWNN.High; + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWNN.Low = FCDevicePage0.WWNN.Low; + } + changed[i] = 1; + n_changed++; + } + else + { + printf(" No persistent entry available for this target!\n"); + } + } + } + } + + if (command == 6) + { + if (sort_by_did) + { + printf("The port is in SortByDID mode, enter Port IDs\n"); + type = "DID"; + } + else + { + printf("The port is in SortByWWN mode, enter World Wide Node and Port Names\n"); + type = "WWN"; + } + + for (i = 0; i < n; i++) + { + if (get16(FCPortPage3->Entry[i].Flags) & MPI_PERSISTENT_FLAGS_ENTRY_VALID) + continue; + + printf("\n"); + + if (sort_by_did) + { + printf("Enter DID: [000000-FFFFFF or RETURN to quit] "); + d_id = getNumberAnswerHex(0x000000, 0xFFFFFF, -1); + if (d_id < 0) + break; + } + else + { + printf("Enter WWNN: [16 hex digits or RETURN to quit] "); + t = getHexDoubleNumberAnswer(&wwnn_h, &wwnn_l); + if (t == 0) + break; + + printf("Enter WWPN: [16 hex digits or RETURN to quit] "); + t = getHexDoubleNumberAnswer(&wwpn_h, &wwpn_l); + if (t == 0) + break; + } + + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Enter desired Bus for this %s: [0-%d or RETURN to quit] ", type, port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + break; + } + else + { + bus = 0; + } + + printf("Enter desired Target for this %s: [0-%d or RETURN to quit] ", type, port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + break; + + for (j = 0; j < n; j++) + { + if (i == j) + continue; + + if (get16(FCPortPage3->Entry[j].Flags) & MPI_PERSISTENT_FLAGS_ENTRY_VALID) + { + if (sort_by_did) + { + if (get32(FCPortPage3->Entry[j].PhysicalIdentifier.Did) == (U32)d_id) + { + printf("\nPersistent entry %d is already valid for this DID!\n", j); + break; + } + } + else + { + if (get32(FCPortPage3->Entry[j].PhysicalIdentifier.WWN.WWPN.High) == wwpn_h && + get32(FCPortPage3->Entry[j].PhysicalIdentifier.WWN.WWPN.Low) == wwpn_l && + get32(FCPortPage3->Entry[j].PhysicalIdentifier.WWN.WWNN.High) == wwnn_h && + get32(FCPortPage3->Entry[j].PhysicalIdentifier.WWN.WWNN.Low) == wwnn_l) + { + printf("\nPersistent entry %d is already valid for this WWN!\n", j); + break; + } + } + + if (FCPortPage3->Entry[j].Bus == bus && + FCPortPage3->Entry[j].TargetID == target) + { + printf("\nPersistent entry %d is already valid for this Bus & Target!\n", j); + break; + } + } + } + if (j < n) + { + i--; + continue; + } + + printf("\nAdding persistent entry %d\n", i); + + flags = MPI_PERSISTENT_FLAGS_ENTRY_VALID | + MPI_PERSISTENT_FLAGS_SCAN_ID | + MPI_PERSISTENT_FLAGS_SCAN_LUNS; + FCPortPage3->Entry[i].Flags = set16(flags); + FCPortPage3->Entry[i].Bus = bus; + FCPortPage3->Entry[i].TargetID = target; + if (sort_by_did) + { + flags |= MPI_PERSISTENT_FLAGS_BY_DID; + FCPortPage3->Entry[i].Flags = set16(flags); + FCPortPage3->Entry[i].PhysicalIdentifier.Did = set32(d_id); + } + else + { + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWPN.High = set32(wwpn_h); + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWPN.Low = set32(wwpn_l); + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWNN.High = set32(wwnn_h); + FCPortPage3->Entry[i].PhysicalIdentifier.WWN.WWNN.Low = set32(wwnn_l); + } + changed[i] = 1; + n_changed++; + } + } + + if (command == 7) + { + if (!sort_by_did) + { + printf("The port is not in SortByDID mode!\n"); + + printf("\nDo you want to switch to SortByDID mode? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) == 1) + { + flags = get32(FCPortPage1.Flags); + flags |= MPI_FCPORTPAGE1_FLAGS_SORT_BY_DID; + FCPortPage1.Flags = set32(flags); + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + free(FCPortPage3); + free(changed); + return 0; + } + else + { + sort_by_did = 1; + printf("\n"); + } + } + } + + loop_id = 0; + for (i = 0; i < n; i++) + { + if (get16(FCPortPage3->Entry[i].Flags) & MPI_PERSISTENT_FLAGS_ENTRY_VALID) + continue; + + d_id = LoopIdToAlpa[loop_id]; + bus = 0; + target = loop_id; + + t = n; + for (j = 0; j < n; j++) + { + if (i == j) + continue; + + if (get16(FCPortPage3->Entry[j].Flags) & MPI_PERSISTENT_FLAGS_ENTRY_VALID) + { + if (get32(FCPortPage3->Entry[j].PhysicalIdentifier.Did) == (U32)d_id && + FCPortPage3->Entry[j].Bus == bus && + FCPortPage3->Entry[j].TargetID == target) + { + printf("Persistent entry %d exists for LoopID %d: Bus %d Target %d is DID %02x\n", + j, loop_id, bus, target, d_id); + t = j; + break; + } + else + { + if (get32(FCPortPage3->Entry[j].PhysicalIdentifier.Did) == (U32)d_id) + { + printf("\nPersistent entry %d is already valid for DID %02x!\n", j, d_id); + break; + } + + if (FCPortPage3->Entry[j].Bus == bus && + FCPortPage3->Entry[j].TargetID == target) + { + printf("\nPersistent entry %d is already valid for Bus %d Target %d!\n", j, bus, target); + break; + } + } + } + } + if (j < n) + { + if (t == n) + { + printf("\nDo you want to continue? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + break; + + printf("\n"); + } + i--; + } + else + { + printf("Adding persistent entry %d for LoopID %d: Bus %d Target %d is DID %02x\n", + i, loop_id, bus, target, d_id); + + flags = MPI_PERSISTENT_FLAGS_ENTRY_VALID | + MPI_PERSISTENT_FLAGS_SCAN_ID | + MPI_PERSISTENT_FLAGS_SCAN_LUNS | + MPI_PERSISTENT_FLAGS_BY_DID; + FCPortPage3->Entry[i].Flags = set16(flags); + FCPortPage3->Entry[i].Bus = bus; + FCPortPage3->Entry[i].TargetID = target; + FCPortPage3->Entry[i].PhysicalIdentifier.Did = set32(d_id); + changed[i] = 1; + n_changed++; + } + + loop_id++; + if (loop_id == 126) + break; + } + } + + if (n_changed != 0) + { + if (do_by_entry) + { + FCPortPage3_t tempFCPortPage3; + + tempFCPortPage3.Header = FCPortPage3->Header; + + for (i = 0; i < port->maxPersistentIds; i++) + { + if (changed[i]) + { + tempFCPortPage3.Entry[0] = FCPortPage3->Entry[i]; + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 3, + MPI_FC_PORT_PGAD_FORM_INDEX + i, + &tempFCPortPage3, sizeof tempFCPortPage3) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + free(FCPortPage3); + free(changed); + return 0; + } + } + } + } + else + { + n = FCPortPage3->Header.PageLength * 4; + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 3, 0, FCPortPage3, n) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + free(FCPortPage3); + free(changed); + return 0; + } + } + } + + free(FCPortPage3); + free(changed); + + return 1; +} + + +int +doSasPersistentMappings(MPT_PORT *port, int command) +{ + ConfigReply_t configRep; + SasDevicePage2_t *SASDevicePage2; + SasDevicePage2_t tempSASDevicePage2; + SasIOUnitPage2_t SASIOUnitPage2; + SasIoUnitControlRequest_t req; + SasIoUnitControlReply_t rep; + int flags; + int encl_slot; + int start_slot; + int num_slots; + U32 encl_id_l; + U32 encl_id_h; + int i; + int j; + int k; + int t; + int bus; + int target; + int b_t; + int max_b_t; + int n; + int *changed; + int n_changed; + int *i_to_b_t; + int old_i; + char name[256]; + FILE *file; + unsigned char *mappingBuf = NULL; + int mappingLen; + char *c; + U32 phys_id_l; + U32 phys_id_h; + U32 encl_map; + int warn = 0; + + if (bringOnline(port) != 1) + return 0; + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 2, 0, + &SASIOUnitPage2, sizeof SASIOUnitPage2) != 1) + return 0; + + flags = SASIOUnitPage2.Flags; + + encl_slot = (flags & MPI_SAS_IOUNIT2_FLAGS_MASK_PHYS_MAP_MODE) == + (MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP << MPI_SAS_IOUNIT2_FLAGS_SHIFT_PHYS_MAP_MODE); + + if (command == 10 || command == 11) + { + if (flags & MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS) + { + printf("Persistent mapping is disabled, no entries will be cleared\n"); + return 1; + } + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; + + if (command == 10) + { + req.Operation = MPI_SAS_OP_CLEAR_ALL_PERSISTENT; + + printf("Clearing all persistent entries...\n"); + } + if (command == 11) + { + req.Operation = MPI_SAS_OP_CLEAR_NOT_PRESENT; + + printf("Clearing all non-present persistent entries...\n"); + } + + t = doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); + + if (t != 1) + printf("Clear failed!\n"); + + if (wFlag) + fprintf(logFile, "%s: Clear (SAS_IO_UNIT_CONTROL) of type %d: %s\n", + logPrefix(port), command, t ? "PASS" : "FAIL"); + + return t; + } + + if (command == 12) + { + t = (flags & MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS) == 0; + printf("Persistence: [0=Disabled, 1=Enabled, default is %d] ", t); + t = getNumberAnswer(0, 1, t); + if (t == 1) + flags &= ~MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS; + else + flags |= MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS; + + SASIOUnitPage2.Flags = flags; + + if (setConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 2, 0, + &SASIOUnitPage2, sizeof SASIOUnitPage2) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; + } + + max_b_t = (port->maxBuses << 8) + port->maxTargets; + n = port->maxPersistentIds; + SASDevicePage2 = (pSasDevicePage2_t)malloc(n * sizeof *SASDevicePage2); + changed = (int *)malloc(n * sizeof *changed); + i_to_b_t = (int *)malloc(n * sizeof *i_to_b_t); + + if (getConfigPageHeader(port, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 2, 0, &configRep) != 1) + { + free(SASDevicePage2); + free(changed); + free(i_to_b_t); + return 0; + } + + memset(&tempSASDevicePage2, 0, sizeof tempSASDevicePage2); + tempSASDevicePage2.Header.ExtPageType = configRep.ExtPageType; + tempSASDevicePage2.Header.ExtPageLength = configRep.ExtPageLength; + tempSASDevicePage2.Header.PageType = configRep.Header.PageType; + tempSASDevicePage2.Header.PageNumber = configRep.Header.PageNumber; + tempSASDevicePage2.Header.PageVersion = configRep.Header.PageVersion; + + for (i = 0, j = 0; i < max_b_t && j < n; i++) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 2, + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID + <> + MPI_SASDEVICE2_ENC_MAP_SHIFT_START_INDEX; + num_slots = (encl_map & MPI_SASDEVICE2_ENC_MAP_MASK_NUM_SLOTS) >> + MPI_SASDEVICE2_ENC_MAP_SHIFT_NUM_SLOTS; + if (num_slots == 1) + printf("Persistent entry %d is valid, EnclosureId %08x%08x, Slot %d\n", + i, + get32(SASDevicePage2[i].PhysicalIdentifier.High), + get32(SASDevicePage2[i].PhysicalIdentifier.Low), + start_slot); + else + printf("Persistent entry %d is valid, EnclosureId %08x%08x, Slots %d to %d\n", + i, + get32(SASDevicePage2[i].PhysicalIdentifier.High), + get32(SASDevicePage2[i].PhysicalIdentifier.Low), + start_slot, start_slot + num_slots - 1); + } + else + { + b_t = i_to_b_t[i]; + printf("Persistent entry %d is valid, Bus %d Target %d is PhysId %08x%08x\n", + i, b_t >> 8, b_t & 255, + get32(SASDevicePage2[i].PhysicalIdentifier.High), + get32(SASDevicePage2[i].PhysicalIdentifier.Low)); + } + if (command == 5) + { + printf(" Delete the entry for this %s? [Yes or No, default is No] ", + encl_slot ? "enclosure" : "target"); + if (getYesNoAnswer(0) != 1) + continue; + } + if (command == 4 || command == 5) + { + printf(" Deleting persistent entry\n"); + SASDevicePage2[i].PhysicalIdentifier.High = 0; + SASDevicePage2[i].PhysicalIdentifier.Low = 0; + SASDevicePage2[i].EnclosureMapping = 0; + changed[i] = 1; + n_changed++; + } + } + + if (j == 0) + printf("No persistent entries found\n"); + } + + if (command == 6) + { + while (j < n) + { + if (encl_slot) + { + printf("Enter current EnclosureId: [16 hex digits or RETURN to quit] "); + t = getHexDoubleNumberAnswer(&encl_id_h, &encl_id_l); + if (t == 0) + break; + + k = 0; + for (i = 0; i < j; i++) + { + if (get32(SASDevicePage2[i].PhysicalIdentifier.High) == encl_id_h && + get32(SASDevicePage2[i].PhysicalIdentifier.Low) == encl_id_l) + { + printf("\nPersistent entry %d is valid for the current EnclosureId\n\n", i); + k++; + } + } + if (k == 0) + { + printf("\nNo persistent entries are valid for the current EnclosureId!\n\n"); + continue; + } + + old_i = i; + + printf("Enter desired EnclosureId: [16 hex digits or RETURN to quit] "); + t = getHexDoubleNumberAnswer(&phys_id_h, &phys_id_l); + if (t == 0) + break; + + if (phys_id_h == encl_id_h && phys_id_l == encl_id_l) + { + printf("\nDesired EnclosureId is equal to Current EnclosureId!\n\n"); + continue; + } + + for (i = 0; i < j; i++) + { + if (get32(SASDevicePage2[i].PhysicalIdentifier.High) == phys_id_h && + get32(SASDevicePage2[i].PhysicalIdentifier.Low) == phys_id_l) + { + printf("\nPersistent entry %d is valid for the desired EnclosureId\n\n", i); + } + } + + for (i = 0; i < j; i++) + { + if (get32(SASDevicePage2[i].PhysicalIdentifier.High) == encl_id_h && + get32(SASDevicePage2[i].PhysicalIdentifier.Low) == encl_id_l) + { + printf("Modifying persistent entry %d!\n", i); + + SASDevicePage2[i].PhysicalIdentifier.High = set32(phys_id_h); + SASDevicePage2[i].PhysicalIdentifier.Low = set32(phys_id_l); + changed[i] = 1; + n_changed++; + continue; + } + + if (get32(SASDevicePage2[i].PhysicalIdentifier.High) == phys_id_h && + get32(SASDevicePage2[i].PhysicalIdentifier.Low) == phys_id_l) + { + printf("Deleting persistent entry %d!\n", i); + + SASDevicePage2[i].PhysicalIdentifier.High = 0; + SASDevicePage2[i].PhysicalIdentifier.Low = 0; + SASDevicePage2[i].EnclosureMapping = 0; + changed[i] = 1; + n_changed++; + continue; + } + } + + printf("\n"); + } + else + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Enter current Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + break; + } + else + { + bus = 0; + } + + printf("Enter current Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + break; + + b_t = (bus << 8) + target; + + for (i = 0; i < j; i++) + { + if (i_to_b_t[i] == b_t && + (SASDevicePage2[i].PhysicalIdentifier.High != 0 || + SASDevicePage2[i].PhysicalIdentifier.Low != 0)) + { +// printf("\nPersistent entry %d is valid for this Bus/Target\n\n", i); + break; + } + } + if (i == j) + { + printf("\nNo persistent entry is valid for this Bus/Target!\n\n"); + continue; + } + + old_i = i; + + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Enter desired Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + break; + } + else + { + bus = 0; + } + + printf("Enter desired Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + break; + + b_t = (bus << 8) + target; + + for (i = 0; i < j; i++) + { + if (i_to_b_t[i] == b_t && + (SASDevicePage2[i].PhysicalIdentifier.High != 0 || + SASDevicePage2[i].PhysicalIdentifier.Low != 0)) + { + if (i == old_i) + printf("\nDesired Bus/Target is equal to Current Bus/Target!\n\n"); + else + printf("\nPersistent entry %d is already valid for this Bus/Target!\n\n", i); + break; + } + } + if (i < j) + continue; + + printf("\nDeleting persistent entry %d!\n", old_i); + printf("Creating persistent entry %d!\n\n", j); + + printf("Persistent entry %d is valid, Bus %d Target %d is PhysId %08x%08x\n\n", + j, bus, target, + get32(SASDevicePage2[old_i].PhysicalIdentifier.High), + get32(SASDevicePage2[old_i].PhysicalIdentifier.Low)); + + SASDevicePage2[j] = SASDevicePage2[old_i]; + changed[j] = 1; + n_changed++; + i_to_b_t[j] = b_t; + j++; + + SASDevicePage2[old_i].PhysicalIdentifier.High = 0; + SASDevicePage2[old_i].PhysicalIdentifier.Low = 0; + SASDevicePage2[old_i].EnclosureMapping = 0; + changed[old_i] = 1; + n_changed++; + } + } + } + + if (command == 7) + { + n = getFileName(name, sizeof name, stdin, "persistent mapping", 0); + if (n > 0) + { + file = fopen(name, "w"); + if (file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + } + else + { + for (i = 0; i < j; i++) + { + b_t = i_to_b_t[i]; + fprintf(file, "Bus %d Target %d is PhysId %08x%08x EnclMap %08x\n", + b_t >> 8, b_t & 255, + get32(SASDevicePage2[i].PhysicalIdentifier.High), + get32(SASDevicePage2[i].PhysicalIdentifier.Low), + get32(SASDevicePage2[i].EnclosureMapping)); + } + + fclose(file); + + if (j) + printf("%d persistent entries saved\n", j); + else + printf("No persistent entries found\n"); + } + } + else + { + printf("Persistent mappings won't be saved\n"); + } + } + + if (command == 8) + { + n = getFileName(name, sizeof name, stdin, "persistent mapping", 0); + if (n > 0) + { + if (readFile(name, &mappingBuf, &mappingLen) != 1) + return 0; + + t = 0; + + c = (char *)mappingBuf; + + while (*c != '\0') + { + if (sscanf(c, "Bus %d Target %d is PhysId %8x%8x EnclMap %8x%n", + &bus, &target, &phys_id_h, &phys_id_l, &encl_map, &n) != 5) + { + printf("Incorrectly formatted file!\n"); + break; + } + + c += n; + + while (*c == '\r' || *c == '\n') + c++; + + b_t = (bus << 8) + target; + + k = ~MPI_SASDEVICE2_ENC_MAP_MASK_MISSING_COUNT; + + for (i = 0; i < j; i++) + { + if (i_to_b_t[i] == b_t && + get32(SASDevicePage2[i].PhysicalIdentifier.High) == phys_id_h && + get32(SASDevicePage2[i].PhysicalIdentifier.Low) == phys_id_l && + (get32(SASDevicePage2[i].EnclosureMapping) & k) == (encl_map & k)) + { + break; + } + if (i_to_b_t[i] == b_t) + { + printf("Bus %d Target %d is already valid with PhysId %08x%08x EnclMap %08x\n", + bus, target, + get32(SASDevicePage2[i].PhysicalIdentifier.High), + get32(SASDevicePage2[i].PhysicalIdentifier.Low), + get32(SASDevicePage2[i].EnclosureMapping)); + warn = 1; + break; + } + if (get32(SASDevicePage2[i].PhysicalIdentifier.High) == phys_id_h && + get32(SASDevicePage2[i].PhysicalIdentifier.Low) == phys_id_l && + (get32(SASDevicePage2[i].EnclosureMapping) & k) == (encl_map & k)) + { + printf("PhysId %08x%08x EnclMap %08x is already valid with Bus %d Target %d\n", + get32(SASDevicePage2[i].PhysicalIdentifier.High), + get32(SASDevicePage2[i].PhysicalIdentifier.Low), + get32(SASDevicePage2[i].EnclosureMapping), + i_to_b_t[i] >> 8, i_to_b_t[i] & 255); + warn = 1; + break; + } + } + + if (i == j) + { + t++; + + SASDevicePage2[j] = tempSASDevicePage2; + SASDevicePage2[j].PhysicalIdentifier.High = set32(phys_id_h); + SASDevicePage2[j].PhysicalIdentifier.Low = set32(phys_id_l); + SASDevicePage2[j].EnclosureMapping = set32(encl_map); + changed[j] = 1; + n_changed++; + i_to_b_t[j] = b_t; + j++; + } + } + + if (t) + printf("%d persistent entries loaded\n", t); + else + printf("No persistent entries loaded\n"); + + if (warn) + printf("\nSome persistent mappings were not loaded; clear persistent entries first!\n"); + + free(mappingBuf); + } + else + { + printf("Persistent mappings won't be loaded\n"); + } + } + + if (n_changed != 0) + { + for (i = 0; i < j; i++) + { + if (changed[i]) + { + if (setConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 2, + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID + <NumPhys); + + n = 0; + for (i = 0; i < SASIOUnitPage0->NumPhys; i++) + { + if (mpi2) + { + SASIOUnit0PhyData = (pSasIOUnit0PhyData)&SASIOUnitPage0_2->PhyData[i]; + rate = (SASIOUnit0PhyData->NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL) >> + MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL; + } + else + { + SASIOUnit0PhyData = (pSasIOUnit0PhyData)&SASIOUnitPage0->PhyData[i]; + rate = SASIOUnit0PhyData->NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL; + } + + + if (rate == MPI_SAS_IOUNIT0_RATE_1_5 || + rate == MPI_SAS_IOUNIT0_RATE_3_0 || + rate == MPI2_SAS_NEG_LINK_RATE_6_0 || + rate == MPI25_SAS_NEG_LINK_RATE_12_0) + { + if (mpi2) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 0, i, + &SASPhyPage0_2, sizeof SASPhyPage0_2) != 1) + continue; + + // convert from MPI 2.x format to MPI 1.x format (only a couple fields are needed) + SASPhyPage0.AttachedPhyIdentifier = SASPhyPage0_2.AttachedPhyIdentifier; + SASPhyPage0.AttachedDevHandle = SASPhyPage0_2.AttachedDevHandle; + } + else + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 0, i, + &SASPhyPage0, sizeof SASPhyPage0) != 1) + continue; + } + + if (rate == MPI_SAS_IOUNIT0_RATE_1_5) + speed = "1.5"; + else if (rate == MPI_SAS_IOUNIT0_RATE_3_0) + speed = "3.0"; + else if (rate == MPI2_SAS_NEG_LINK_RATE_6_0) + speed = "6.0"; + else if (rate == MPI25_SAS_NEG_LINK_RATE_12_0) + speed = "12.0"; + else + speed = "???"; + + if (n++) + printf(" "); + printf(" %2d %04x --> %2d %04x %2d %s\n", + i, get16(SASIOUnit0PhyData->ControllerDevHandle), + SASPhyPage0.AttachedPhyIdentifier, + get16(SASPhyPage0.AttachedDevHandle), + SASIOUnit0PhyData->Port, speed); + } + } //next phy + if (n == 0) + printf("\n"); + + free(SASIOUnitPage0); + + handle = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, handle, + &SASExpanderPage0, sizeof SASExpanderPage0) != 1) + break; + + handle = get16(SASExpanderPage0.DevHandle); + + printf("\nExpander %2d", SASExpanderPage0.NumPhys); + + n = 0; + for (i = 0; i < SASExpanderPage0.NumPhys; i++) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 1, + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM + <> + MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL; + else + rate = SASExpanderPage1.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL; + + if (rate == MPI_SAS_EXPANDER1_NEG_RATE_1_5 || + rate == MPI_SAS_EXPANDER1_NEG_RATE_3_0 || + rate == MPI2_SAS_NEG_LINK_RATE_6_0 || + rate == MPI25_SAS_NEG_LINK_RATE_12_0) + { + if (rate == MPI_SAS_IOUNIT0_RATE_1_5) + speed = "1.5"; + else if (rate == MPI_SAS_EXPANDER1_NEG_RATE_3_0) + speed = "3.0"; + else if (rate == MPI25_SAS_NEG_LINK_RATE_12_0) + speed = "12.0"; + else + speed = "6.0"; + + if (n++) + printf(" "); + printf(" %2d %04x --> %2d %04x %2d %s\n", + i, handle, + SASExpanderPage1.AttachedPhyIdentifier, + get16(SASExpanderPage1.AttachedDevHandle), + SASExpanderPage1.PhysicalPort, speed); + } + } + if (n == 0) + printf("\n"); + } + + printf("\nEnclosure Handle Slots SASAddress B___T (SEP)\n"); + + handle = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_ENCLOSURE, 0, handle, + &SASEnclosurePage0, sizeof SASEnclosurePage0) != 1) + break; + + handle = get16(SASEnclosurePage0.EnclosureHandle); + flags = get16(SASEnclosurePage0.Flags); + + if (handle == 1) + { + mapped = 0; + } + else if (mpi1) + { + mapped = flags & MPI_SAS_ENCLS0_FLAGS_SEP_BUS_ID_VALID; + bus = SASEnclosurePage0.SEPBus; + target = SASEnclosurePage0.SEPTargetID; + } + else + { + Mpi2SasEnclosurePage0_t *SASEnclosurePage0_2; + int handle; + + SASEnclosurePage0_2 = (pMpi2SasEnclosurePage0_t)&SASEnclosurePage0; + handle = get16(SASEnclosurePage0_2->SEPDevHandle); + + mapped = mapDevHandleToBusTarget(port, handle, &bus, &target); + } + + if (mapped) + { + printf(" %04x %5d %08x%08x %2d %3d\n", + handle, get16(SASEnclosurePage0.NumSlots), + get32(SASEnclosurePage0.EnclosureLogicalID.High), + get32(SASEnclosurePage0.EnclosureLogicalID.Low), + bus, target); + } + else + { + printf(" %04x %5d %08x%08x\n", + handle, get16(SASEnclosurePage0.NumSlots), + get32(SASEnclosurePage0.EnclosureLogicalID.High), + get32(SASEnclosurePage0.EnclosureLogicalID.Low)); + } + } + + return 1; +} + + +int +showSasDiscoveryErrors(MPT_PORT *port) +{ + SasIOUnitPage0_t *SASIOUnitPage0; + Mpi2SasIOUnitPage0_t *SASIOUnitPage0_2; + SasIOUnit0PhyData *SASIOUnit0PhyData; + SasExpanderPage0_t SASExpanderPage0; + Mpi2ExpanderPage0_t *SASExpanderPage0_2; + int handle; + int length; + int i; + int n; + int t; + int disc_stat; + + n = 0; + + SASIOUnitPage0 = getConfigPageAlloc(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0, &length); + if (SASIOUnitPage0 == NULL) + return 0; + + SASIOUnitPage0_2 = (pMpi2SasIOUnitPage0_t)SASIOUnitPage0; + + for (i = 0; i < SASIOUnitPage0->NumPhys; i++) + { + if (mpi2) + SASIOUnit0PhyData = (pSasIOUnit0PhyData)&SASIOUnitPage0_2->PhyData[i]; + else + SASIOUnit0PhyData = (pSasIOUnit0PhyData)&SASIOUnitPage0->PhyData[i]; + + if (SASIOUnit0PhyData->PortFlags & MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS) + { + if (n++) + printf("\n"); + + printf("Discovery is in progress for adapter phy %d!\n", i); + } + + disc_stat = get32(SASIOUnit0PhyData->DiscoveryStatus); + + if (disc_stat) + { + if (n++) + printf("\n"); + + printf("Discovery errors for adapter phy %d:\n", i); + if (mpi1) + { + if (disc_stat & MPI_SAS_IOUNIT0_DS_LOOP_DETECTED) + printf(" Loop detected\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_UNADDRESSABLE_DEVICE) + printf(" Unaddressable device detected\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_MULTIPLE_PORTS) + printf(" Multiple ports with same SAS address detected\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_EXPANDER_ERR) + printf(" Expander error\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_SMP_TIMEOUT) + printf(" SMP timeout\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_OUT_ROUTE_ENTRIES) + printf(" Expander route table out of entries\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_INDEX_NOT_EXIST) + printf(" Route table index does not exist\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_SMP_FUNCTION_FAILED) + printf(" SMP function failed\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_SMP_CRC_ERROR) + printf(" SMP CRC error\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK) + printf(" Subtractive-to-subtractive link detected\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_TABLE_LINK) + printf(" Table-to-table link detected\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE) + printf(" Unsupported device detected\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_MAX_SATA_TARGETS) + printf(" Maximum number of supported SATA targets reached\n"); + if (disc_stat & MPI_SAS_IOUNIT0_DS_MULTI_PORT_DOMAIN) + printf(" Multiple ports attached to the same domain\n"); + } + else + { + if (disc_stat & MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED) + printf(" Maximum number of enclosures exceeded\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED) + printf(" Maximum number of expanders exceeded\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED) + printf(" Maximum number of devices exceeded\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED) + printf(" Maximum number of phys exceeded\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR ) + printf(" Downstream initiator detected in simplified routing mode\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE ) + printf(" Multiple subtractive-to-subtractive ports detected\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE ) + printf(" Multiple subtractive ports within an expander detected\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN) + printf(" Multiple ports attached to the same domain\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK) + printf(" Table-to-subtractive link detected\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE) + printf(" Unsupported device detected\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_TABLE_LINK) + printf(" Table-to-table link detected\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK) + printf(" Subtractive-to-subtractive link detected\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR) + printf(" SMP CRC error\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED) + printf(" SMP function failed\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST) + printf(" Route table index does not exist\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES) + printf(" Expander route table out of entries\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_SMP_TIMEOUT) + printf(" SMP timeout\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS) + printf(" Multiple ports with same SAS address detected\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE) + printf(" Unaddressable device detected\n"); + if (disc_stat & MPI2_SASIOUNIT0_DS_LOOP_DETECTED) + printf(" Loop detected\n"); + } + } + } + + free(SASIOUnitPage0); + + handle = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, handle, + &SASExpanderPage0, sizeof SASExpanderPage0) != 1) + break; + + handle = get16(SASExpanderPage0.DevHandle); + + if (mpi2) + { + SASExpanderPage0_2 = (pMpi2ExpanderPage0_t)&SASExpanderPage0; + + t = get16(SASExpanderPage0_2->Flags) & MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS; + } + else + { + t = SASExpanderPage0.Flags & MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS; + } + + if (t) + { + if (n++) + printf("\n"); + + printf("Configuration is in progress for expander %04x!\n", handle); + } + + disc_stat = get32(SASExpanderPage0.DiscoveryStatus); + + if (disc_stat) + { + if (n++) + printf("\n"); + + printf("Discovery errors for expander %04x:\n", handle); + if (mpi1) + { + if (disc_stat & MPI_SAS_EXPANDER0_DS_LOOP_DETECTED) + printf(" Loop detected\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE) + printf(" Unaddressable device detected\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_MULTIPLE_PORTS) + printf(" Multiple ports with same SAS address detected\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_EXPANDER_ERR) + printf(" Expander error\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_SMP_TIMEOUT) + printf(" SMP timeout\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES) + printf(" Expander route table out of entries\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_INDEX_NOT_EXIST) + printf(" Route table index does not exist\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED) + printf(" SMP function failed\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_SMP_CRC_ERROR) + printf(" SMP CRC error\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK) + printf(" Subtractive-to-subtractive link detected\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_TABLE_LINK) + printf(" Table-to-table link detected\n"); + if (disc_stat & MPI_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE) + printf(" Unsupported device detected\n"); + } + else + { + if (disc_stat & MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED) + printf(" Maximum number of enclosures exceeded\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED) + printf(" Maximum number of expanders exceeded\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED) + printf(" Maximum number of devices exceeded\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED) + printf(" Maximum number of phys exceeded\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR) + printf(" Downstream initiator detected in simplified routing mode\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE ) + printf(" Multiple subtractive-to-subtractive ports detected\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE ) + printf(" Multiple subtractive ports within an expander detected\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN) + printf(" Multiple ports attached to the same domain\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK) + printf(" Table-to-subtractive link detected\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE) + printf(" Unsupported device detected\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_TABLE_LINK) + printf(" Table-to-table link detected\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK) + printf(" Subtractive-to-subtractive link detected\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR) + printf(" SMP CRC error\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED) + printf(" SMP function failed\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST) + printf(" Route table index does not exist\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES) + printf(" Expander route table out of entries\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT) + printf(" SMP timeout\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS) + printf(" Multiple ports with same SAS address detected\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE) + printf(" Unaddressable device detected\n"); + if (disc_stat & MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED) + printf(" Loop detected\n"); + } + } + } + + if (n == 0) + printf("No discovery errors found\n"); + + return 1; +} + + +int +doShowPortAliases(MPT_PORT *port) +{ + FCPortPage0_t FCPortPage0; + FCPortPage1_t FCPortPage1; + FCPortPage5_t FCPortPage5; + int i; + + if (bringOnline(port) != 1) + return 0; + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, &FCPortPage0, sizeof FCPortPage0) != 1) + return 0; + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + if (FCPortPage0.MaxAliasesSupported == 0) + { + printf("Aliases are not supported on this port\n"); + return 1; + } + + printf("%d aliases requested, %d aliases active\n", FCPortPage1.NumRequestedAliases, FCPortPage0.NumCurrentAliases); + + if (FCPortPage1.NumRequestedAliases == 0) + return 1; + + printf("\n WWNN WWPN PortId Flags\n"); + + for (i = 1; i <= FCPortPage1.NumRequestedAliases; i++) + { + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, MPI_CONFIG_PAGETYPE_FC_PORT, 5, + MPI_FC_PORT_PGAD_FORM_INDEX + i, &FCPortPage5, sizeof FCPortPage5) != 1) + continue; + + printf("%3d %08x%08x %08x%08x %04x%02x %02x (%s%s)\n", i, + get32(FCPortPage5.AliasInfo.AliasWWNN.High), get32(FCPortPage5.AliasInfo.AliasWWNN.Low), + get32(FCPortPage5.AliasInfo.AliasWWPN.High), get32(FCPortPage5.AliasInfo.AliasWWPN.Low), + get16(FCPortPage5.AliasInfo.DomainArea), + FCPortPage5.AliasInfo.AliasAlpa, + FCPortPage5.AliasInfo.Flags, + (FCPortPage5.AliasInfo.Flags & MPI_FCPORTPAGE5_FLAGS_DISABLE) ? "Disabled, " : "", + (FCPortPage5.AliasInfo.Flags & MPI_FCPORTPAGE5_FLAGS_ALPA_ACQUIRED) ? "Active" : "Inactive"); + } + + return 1; +} + + +int +doShowExpanderRoutingTables(MPT_PORT *port) +{ + SasExpanderPage0_t SASExpanderPage0; + SasExpanderPage1_t SASExpanderPage1; + Mpi2ExpanderPage0_t *SASExpanderPage0_2; + int exp_handle; + int handle; + int phy_info; + int i; + int j; + int t; + int flags; + int route_table_config; + int n1; + int n2; + unsigned char report_route_information_req[12]; + unsigned char report_route_information_rsp[40]; + unsigned char report_expander_route_table_req[28]; + unsigned char report_expander_route_table_rsp[48]; + U32 wwid_l = 0; + U32 wwid_h = 0; + char types[49]; + + if (bringOnline(port) != 1) + return 0; + + if (gFlag == TRUE) + { + printf("Enter expander handle: [0000-FFFF or RETURN for all expanders] "); + exp_handle = getNumberAnswerHex(0x0000, 0xffff, -1); + + printf("\n"); + } + else + exp_handle = -1; + + memset(report_route_information_req, 0, sizeof report_route_information_req); + + report_route_information_req[0] = 0x40; + report_route_information_req[1] = 0x13; + report_route_information_req[2] = 0xff; + + memset(report_expander_route_table_req, 0, sizeof report_expander_route_table_req); + + report_expander_route_table_req[0] = 0x40; +// report_expander_route_table_req[1] = + report_expander_route_table_req[2] = 0xff; + report_expander_route_table_req[3] = 6; + report_expander_route_table_req[9] = 1; + + n1 = 0; + handle = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, handle, + &SASExpanderPage0, sizeof SASExpanderPage0) != 1) + break; + + handle = get16(SASExpanderPage0.DevHandle); + + if (exp_handle >= 0 && exp_handle != handle) + continue; + + if (n1++) + printf("\n"); + + for (i = 0; i < SASExpanderPage0.NumPhys; i++) + { + if (i >= sizeof types - 1) + break; + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 1, + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM + <Flags); + route_table_config = flags & MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG; + } + else + { + flags = SASExpanderPage0.Flags; + route_table_config = flags & MPI_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG; + } + + if (route_table_config) + { + printf("Sending Report Route Information\n"); + n2 = 0; + for (i = 0; i < SASExpanderPage0.NumPhys; i++) + { + if (types[i] == 'T') + { + report_route_information_req[9] = i; + + for (j = 0; j < get16(SASExpanderPage0.ExpanderRouteIndexes); j++) + { + report_route_information_req[6] = j >> 8; + report_route_information_req[7] = j; + + if (doSmpPassthrough(port, SASExpanderPage0.PhysicalPort, SASExpanderPage0.SASAddress, + report_route_information_req, sizeof report_route_information_req, + report_route_information_rsp, sizeof report_route_information_rsp, NULL) == 1) + { + if (report_route_information_rsp[2] == 0x01) + break; + if (report_route_information_rsp[2] == 0x11) + break; + + if (report_route_information_rsp[2] != 0) + { + printf("Report Route Information failed with result %02x\n", + report_route_information_rsp[2]); + continue; + } + + if (report_route_information_rsp[12] & 0x80) + continue; + + wwid_h = get4bytes(report_route_information_rsp, 16); + wwid_l = get4bytes(report_route_information_rsp, 20); + + if (n2++ == 0) + printf("Phy Index SASAddress\n"); + + printf("%3d %5d %08x%08x\n", i, j, wwid_h, wwid_l); + } + else + { + printf("Report Route Information failed!\n"); + break; + } + } + } + } + } + else + { + n2 = 0; + printf("Sending Report Expander Route Table\n"); + report_expander_route_table_req[1] = 0x22; + for (j = 0; j < 65536; j++) + { + report_expander_route_table_req[10] = j >> 8; + report_expander_route_table_req[11] = j; + + t = doSmpPassthrough(port, SASExpanderPage0.PhysicalPort, SASExpanderPage0.SASAddress, + report_expander_route_table_req, sizeof report_expander_route_table_req, + report_expander_route_table_rsp, sizeof report_expander_route_table_rsp, NULL); + if (t == 1) + { + if (report_expander_route_table_rsp[2] == 0x01 && j == 0) + { + report_expander_route_table_req[1] = 0x17; + t = doSmpPassthrough(port, SASExpanderPage0.PhysicalPort, SASExpanderPage0.SASAddress, + report_expander_route_table_req, sizeof report_expander_route_table_req, + report_expander_route_table_rsp, sizeof report_expander_route_table_rsp, NULL); + } + } + if (t == 1) + { + if (report_expander_route_table_rsp[2] == 0x01) + break; + if (report_expander_route_table_rsp[2] == 0x11) + break; + + if (report_expander_route_table_rsp[2] != 0) + { + printf("Report Expander Route Table failed with result %02x\n", + report_expander_route_table_rsp[2]); + continue; + } + + if (report_expander_route_table_rsp[11] == 0) + break; + + j = get2bytes(report_expander_route_table_rsp, 12); + + wwid_h = get4bytes(report_expander_route_table_rsp, 32); + wwid_l = get4bytes(report_expander_route_table_rsp, 36); + + if (n2++ == 0) + printf("Index SASAddress Zone Phy Bitmask\n"); + + printf("%5d %08x%08x ", j, wwid_h, wwid_l); + if (report_expander_route_table_rsp[46] & 0x80) + printf(" %3d ", report_expander_route_table_rsp[47]); + else + printf(" "); + for (i = 40; i < 46; i++) + printf("%02x", report_expander_route_table_rsp[i]); + printf("\n"); + } + else + { + printf("Report Expander Route Table failed!\n"); + break; + } + } + } + } + if (n1 == 0) + { + if (exp_handle < 0) + printf("No expanders found\n"); + else + printf("Expander %04x not found\n", exp_handle); + } + + return 1; +} + + +int +doTestConfigPageActions(MPT_PORT *port) +{ + Config_t req; + ConfigReply_t rep; + char name[256]; + FILE *in_file; + FILE *out_file; + char str[80]; + char act[80]; + U32 buf[256]; + int action; + int type; + int number; + int length; + int ioc_status; + U32 address; + U32 offset; + U32 value; + int i; + int j; + int n; + int t; + char *action_string[7] = {"H", "RC", "WC", "D", "WN", "RD", "RN"}; + + printf("Enter input file, or RETURN to enter commands interactively: "); + n = getString(name, sizeof name, stdin); + + if (n > 0) + { + in_file = fopen(name, "r"); + if (in_file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + } + else + { + in_file = stdin; + } + + printf("Enter output file, or RETURN to send output to the screen: "); + n = getString(name, sizeof name, stdin); + + if (n > 0) + { + out_file = fopen(name, "w"); + if (out_file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + if (in_file != stdin) + fclose(in_file); + return 0; + } + } + else + { + out_file = stdout; + } + + while (TRUE) + { + while (TRUE) + { + if (in_file == stdin) + { + printf("\nEnter command, or ? for help, or RETURN to quit: "); + n = getString(str, sizeof str, stdin); + lines = 0; + } + else + { + if (fgets(str, sizeof str, in_file) == NULL) + { + n = 0; + } + else + { + str[sizeof str - 1] = '\0'; + n = (int)strlen(str); + if (n >= 1 && str[n-1] == '\n') + { + str[n-1] = '\0'; + n -= 1; + } + + if (n == 0) + continue; + + printf("Executing \"%s\"...\n", str); + } + } + + if (n == 0) + { + if (in_file != stdin) + fclose(in_file); + if (out_file != stdout) + fclose(out_file); + return 1; + } + + act[0] = '\0'; + type = 0; + number = 0; + address = 0; + i = sscanf(str, "%s %d %d %x%n\n", act, &type, &number, &address, &j); + if (i >= 4 && j < n && str[j] != ' ') + i = 0; + + if (i >= 3) + { + if (sscanf(act, "%d", &action) == 1) + ; + else if (strcasecmp(act, "h") == 0) + action = 0; + else if (strcasecmp(act, "rc") == 0) + action = 1; + else if (strcasecmp(act, "wc") == 0) + action = 2; + else if (strcasecmp(act, "d") == 0) + action = 3; + else if (strcasecmp(act, "wn") == 0) + action = 4; + else if (strcasecmp(act, "rd") == 0) + action = 5; + else if (strcasecmp(act, "rn") == 0) + action = 6; + + else if (strcasecmp(act, "rdwn") == 0) + action = 5; + + else + action = -1; + + if (action >= 0 && action <= 6 && + type >= 0 && type <= 255 && type != 15 && + number >= 0 && number <= 255) + { + break; + } + } + + if (in_file == stdin) + { + if (n != 1 || str[0] != '?') + printf("\nInvalid response!\n"); + printf("\nValid input is: []\n"); + printf(" Action is:\n"); + printf(" 0 or H display page Header only\n"); + printf(" 1 or RC display page after Read Current\n"); + printf(" 2 or WC enter page and do Write Current\n"); + printf(" 3 or D set current page to Default values\n"); + printf(" 4 or WN enter page and do Write NVRAM\n"); + printf(" 5 or RD display page after Read Default\n"); + printf(" 6 or RN display page after Read NVRAM\n"); + printf(" RDWN do Read Default then Write NVRAM\n"); + printf(" PageType is a decimal number beteen 0 and 255, but not 15\n"); + printf(" PageNumber is a decimal number between 0 and 255\n"); + printf(" PageAddress is an optional hex number\n"); + } + } + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_CONFIG; + req.AliasIndex = virtInit; + req.Action = MPI_CONFIG_ACTION_PAGE_HEADER; + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + { + req.Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + req.ExtPageType = type; + } + else + { + req.Header.PageType = type; + } + req.Header.PageNumber = number; + req.PageAddress = set32(address); + + if (doMptCommand(port, &req, sizeof req - sizeof req.PageBufferSGE, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + { + printf("\nFailed to get Header for page %d/%d/%x\n", type, number, address); + continue; + } + + if (action == 0) + { + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + fprintf(out_file, "\n%s %d %d %x -- IOCStatus = %04x (%s)\n", + action_string[action], type, number, address, + ioc_status, translateIocStatus(ioc_status)); + + if (ioc_status == MPI_IOCSTATUS_SUCCESS) + { + fprintf(out_file, "0000 : %08x\n", get32x(*(U32 *)&rep.Header)); + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + fprintf(out_file, "0004 : 00%02x%04x\n", rep.ExtPageType, get16(rep.ExtPageLength)); + } + } + + if (action == 1 || action == 5 || action == 6) + { + req.Action = action; + req.ExtPageType = rep.ExtPageType; + req.ExtPageLength = rep.ExtPageLength; + req.Header = rep.Header; + + if (doMptCommand(port, &req, sizeof req - sizeof req.PageBufferSGE, &rep, sizeof rep, + buf, sizeof buf, NULL, 0, SHORT_TIME) != 1) + { + printf("\nFailed to read page %d/%d/%x\n", type, number, address); + continue; + } + + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + fprintf(out_file, "\n%s %d %d %x -- IOCStatus = %04x (%s)\n", + action_string[action], type, number, address, + ioc_status, translateIocStatus(ioc_status)); + + if (ioc_status == MPI_IOCSTATUS_SUCCESS) + { + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + n = get16(rep.ExtPageLength); + else + n = rep.Header.PageLength; + + for (i = 0; i < n; i++) + fprintf(out_file, "%04x : %08x\n", i*4, get32x(buf[i])); + } + } + + if (action == 2 || action == 4) + { + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status == MPI_IOCSTATUS_SUCCESS) + { + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + length = get16(rep.ExtPageLength) * 4; + else + length = rep.Header.PageLength * 4; + } + else + length = sizeof buf; + + memset (buf, 0, sizeof buf); + ((pConfigPageHeader_t)buf)->PageVersion = rep.Header.PageVersion; + ((pConfigPageHeader_t)buf)->PageLength = rep.Header.PageLength; + ((pConfigPageHeader_t)buf)->PageNumber = rep.Header.PageNumber; + ((pConfigPageHeader_t)buf)->PageType = rep.Header.PageType; + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + { + ((pConfigExtendedPageHeader_t)buf)->ExtPageLength = rep.ExtPageLength; + ((pConfigExtendedPageHeader_t)buf)->ExtPageType = rep.ExtPageType; + t = 8; + } + else + t = 4; + + while (TRUE) + { + if (in_file == stdin) + { + printf("Enter offset (%04x) and value, or ? for help, or RETURN to quit: ", t); + n = getString(str, sizeof str, stdin); + lines = 0; + } + else + { + if (fgets(str, sizeof str, in_file) == NULL) + { + n = 0; + } + else + { + str[sizeof str - 1] = '\0'; + n = (int)strlen(str); + if (n >= 1 && str[n-1] == '\n') + { + str[n-1] = '\0'; + n -= 1; + } + } + } + + if (n == 0) + break; + + offset = 0; + value = 0; + i = sscanf(str, "%x : %x%n\n", &offset, &value, &j); + if (i == 1 && strchr(str, ':') == NULL) + { + i = sscanf(str, "%x %x%n\n", &offset, &value, &j); + if (i == 1 && strchr(str, ' ') == NULL) + { + offset = t; + sscanf(str, "%x%n", &value, &j); + i = 2; + } + } + + if (i == 2 && j == n) + { + if (offset < (U32)length && (offset % 4) == 0) + { + buf[offset / 4] = value; + t = offset + 4; + + if (t == length) + break; + + continue; + } + } + + if (in_file == stdin) + { + if (n != 1 || str[0] != '?') + printf("\nInvalid response!\n"); + printf("\nValid input is: [ [:]] \n"); + printf(" Offset is an optional hex number between 0000 and %04x (multiple of 4 only)\n", length - 4); + printf(" Value is a hex number\n\n"); + } + } + } + + if (strcasecmp(act, "rdwn") == 0) + action = 4; + + if (action == 2 || action == 3 || action == 4) + { + req.Action = action; + req.ExtPageType = rep.ExtPageType; + req.ExtPageLength = rep.ExtPageLength; + req.Header = rep.Header; + + if (action != 3 && type == MPI_CONFIG_PAGETYPE_MANUFACTURING && number == 2) + { + U8 checksum = 0xa5; + U8 *p = (U8 *)buf; + + p += 8; + t = n * 4 - 8; + switch (port->deviceId) + { + case MPI_MANUFACTPAGE_DEVICEID_FC919: t -= 4; break; + case MPI_MANUFACTPAGE_DEVICEID_FC929: t -= 4; break; + case MPI_MANUFACTPAGE_DEVICEID_FC919X: t -= 3; break; + case MPI_MANUFACTPAGE_DEVICEID_FC929X: t -= 3; break; + case MPI_MANUFACTPAGE_DEVICEID_FC939X: t -= 3; break; + case MPI_MANUFACTPAGE_DEVICEID_FC949X: t -= 3; break; + case MPI_MANUFACTPAGE_DEVICEID_FC949E: t -= 4; break; + default: t = 0; break; + } + if (t != 0) + { + for (i = 0; i < t; i++) + { + checksum += *p++; + } + *p = -checksum; + } + } + + if (type == MPI_CONFIG_PAGETYPE_MANUFACTURING) + doIocInit(port, MPI_WHOINIT_MANUFACTURER); + + if (doMptCommand(port, &req, sizeof req - sizeof req.PageBufferSGE, &rep, sizeof rep, + NULL, 0, buf, sizeof buf, SHORT_TIME) != 1) + { + if (type == MPI_CONFIG_PAGETYPE_MANUFACTURING) + doIocInit(port, port->whoInit); + + printf("\nFailed to write page %d/%d/%x\n", type, number, address); + continue; + } + + if (type == MPI_CONFIG_PAGETYPE_MANUFACTURING) + doIocInit(port, port->whoInit); + + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + fprintf(out_file, "\n%s %d %d %x -- IOCStatus = %04x (%s)\n", + action_string[action], type, number, address, + ioc_status, translateIocStatus(ioc_status)); + } + } +} + + +int +selectDevice(MPT_PORT *port, int *dev_bus, int *dev_target) +{ + int bus; + int target; + unsigned char inq[36]; + int i; + int n; + + if (kFlag == TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 0; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 0; + + *dev_bus = bus; + *dev_target = target; + + return 1; + } + + showPortInfoHeader(port); + + printf(" B___T Type Vendor Product Rev\n"); + + n = 0; + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + if (doInquiry(port, bus, target, 0, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + continue; + } + + if ((inq[0] & 0x1f) == 0x1f) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + diag_targets[n].bus = bus; + diag_targets[n].target = target; + + n++; + + printf("%2d. %2d %3d %-9s %-8.8s %-16.16s %-4.4s\n", + n, bus, target, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32); + + if (n == MAX_DEVICES) + break; + } + if (n == MAX_DEVICES) + break; + } + + if (n == 0) + { + printf("\nNo devices are available for this test\n"); + return 0; + } + + printf("\nSelect a device: [1-%d or RETURN to quit] ", n); + n = getNumberAnswer(1, n, 0); + if (n == 0) + return 0; + n--; + + bus = diag_targets[n].bus; + target = diag_targets[n].target; + + *dev_bus = bus; + *dev_target = target; + + return 1; +} + + +int +selectDeviceRWMedia(MPT_PORT *port) +{ + int bus; + int target; + int lun; + unsigned char inq[36]; + unsigned char cap[8]; + unsigned char cap16[32]; + int i; + int n; + unsigned int mode; + unsigned int size; + int eedp; + + if (kFlag == TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 0; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 0; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 0; + + if (doInquiry(port, bus, target, lun, inq, sizeof inq) != 1) + return 0; + + if (doReadCapacity(port, bus, target, lun, cap, sizeof cap) != 1) + return 0; + + mode = get4bytes(cap, 4); + size = get4bytes(cap, 0); + eedp = 0; + + if (mode == 512 && (inq[5] & 1)) + { + if (doReadCapacity16(port, bus, target, lun, cap16, sizeof cap16) == 1) + { + if (cap16[12] && 1) + { + mode = 520; + eedp = 1; + } + } + } + else if (mode == 520) + { + eedp = 2; + } + + diag_targets[0].bus = bus; + diag_targets[0].target = target; + diag_targets[0].lun = lun; + diag_targets[0].mode = mode; + diag_targets[0].size = size; + diag_targets[0].eedp = eedp; + + return 1; + } + + showPortInfoHeader(port); + + printf(" B___T___L Type Vendor Product Rev Mode Disk Blocks\n"); + + n = 0; + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + for (lun = 0; lun < port->maxLuns; lun++) + { + if (doInquiry(port, bus, target, lun, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + if (lun == 0) + break; + else + continue; + } + + if ((inq[0] & 0x1f) != 0x00) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + if (doReadCapacity(port, bus, target, lun, cap, sizeof cap) != 1) + continue; + + mode = get4bytes(cap, 4); + size = get4bytes(cap, 0); + eedp = 0; + + if (mode == 512 && (inq[5] & 1)) + { + if (doReadCapacity16(port, bus, target, lun, cap16, sizeof cap16) == 1) + { + if (cap16[12] && 1) + { + mode = 520; + eedp = 1; + } + } + } + else if (mode == 520) + { + eedp = 2; + } + + diag_targets[n].bus = bus; + diag_targets[n].target = target; + diag_targets[n].lun = lun; + diag_targets[n].mode = mode; + diag_targets[n].size = size; + diag_targets[n].eedp = eedp; + + n++; + + printf("%2d. %2d %3d %3d %-9s %-8.8s %-16.16s %-4.4s %4d %10d\n", + n, bus, target, lun, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32, mode, size + 1); + + if (n == MAX_DEVICES) + break; + } + if (n == MAX_DEVICES) + break; + } + if (n == MAX_DEVICES) + break; + } + + if (n == 0) + { + printf("\nNo devices are available for this test\n"); + return 0; + } + + printf("\nSelect a device: [1-%d or RETURN to quit] ", n); + n = getNumberAnswer(1, n, 0); + + return n; +} + + +int +selectDeviceRWBuffer(MPT_PORT *port) +{ + int bus; + int target; + unsigned char inq[36]; + unsigned char buf[4]; + int i; + int n; + int mode; + unsigned int size; + + if (kFlag == TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 0; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 0; + + printf("Buffer: [0=Data, 1=Echo, or RETURN to quit] "); + i = getNumberAnswer(0, 1, -1); + if (i < 0) + return 0; + + switch (i) + { + case 0: mode = 0x2; break; + case 1: mode = 0xa; break; + default: return 0; + } + + if (doReadBuffer(port, bus, target, 0, mode + 1, buf, sizeof buf) != 1) + return 0; + + size = min(0x4000, get3bytes(buf, 1)); + if (size < 4) + return 0; + + diag_targets[0].bus = bus; + diag_targets[0].target = target; + diag_targets[0].mode = mode; + diag_targets[0].size = size; + + return 1; + } + + showPortInfoHeader(port); + + printf(" B___T Type Vendor Product Rev Buffer & Size\n"); + + n = 0; + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + if (doInquiry(port, bus, target, 0, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + continue; + } + + if ((inq[0] & 0x1f) == 0x1f) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + mode = 0x2; + if (doReadBuffer(port, bus, target, 0, mode + 1, buf, sizeof buf) == 1) + { + size = min(0x4000, get3bytes(buf, 1)); + if (size < 4) + continue; + + diag_targets[n].bus = bus; + diag_targets[n].target = target; + diag_targets[n].mode = mode; + diag_targets[n].size = size; + + n++; + + printf("%2d. %2d %3d %-9s %-8.8s %-16.16s %-4.4s Data %5d\n", + n, bus, target, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32, size); + + if (n == MAX_DEVICES) + break; + } + + mode = 0xa; + if (doReadBuffer(port, bus, target, 0, mode + 1, buf, sizeof buf) == 1) + { + size = min(0x4000, get3bytes(buf, 1)); + if (size < 4) + continue; + + diag_targets[n].bus = bus; + diag_targets[n].target = target; + diag_targets[n].mode = mode; + diag_targets[n].size = size; + + n++; + + printf("%2d. %2d %3d %-9s %-8.8s %-16.16s %-4.4s Echo %5d\n", + n, bus, target, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32, size); + + if (n == MAX_DEVICES) + break; + } + } + if (n == MAX_DEVICES) + break; + } + + if (n == 0) + { + printf("\nNo devices are available for this test\n"); + return 0; + } + + printf("\nSelect a device: [1-%d or RETURN to quit] ", n); + n = getNumberAnswer(1, n, 0); + + return n; +} + + +int +getExpanderType(int componentId, U8 *componentVendorId, U8 *vendorId) +{ + if ( (strncmp((char *)componentVendorId, "LSI", 3) != 0) && + (strncmp((char *)vendorId, "LSI", 3) != 0) ) + return EXPANDER_TYPE_3RD_PARTY; + else + { + switch(componentId) + { + case 0x0211: + case 0x0213: + return EXPANDER_TYPE_LSI_GEN1_YETI; + case 0x0220: + case 0x0221: + case 0x0223: + case 0x0224: + case 0x0225: + case 0x0226: + case 0x0227: + return EXPANDER_TYPE_LSI_GEN2_BOBCAT; + case 0x0230: + case 0x0231: + case 0x0232: + case 0x0233: + case 0x0235: + case 0x0236: + return EXPANDER_TYPE_LSI_GEN3_COBRA; + default: + return EXPANDER_TYPE_3RD_PARTY; + } + } +} + + +char * +printExpanderType(int expanderType) +{ + switch(expanderType) + { + case EXPANDER_TYPE_LSI_GEN1_YETI: return "LSI SAS1 (Yeti)"; + case EXPANDER_TYPE_LSI_GEN2_BOBCAT: return "LSI SAS2 (Bobcat)"; + case EXPANDER_TYPE_LSI_GEN3_COBRA: return "LSI SAS3 (Cobra)"; + case EXPANDER_TYPE_LSI_GEN1_X12: return "LSI SAS1 (X12)"; + case EXPANDER_TYPE_3RD_PARTY: return "non LSI expander"; + case EXPANDER_TYPE_UNKNOWN: + default: return "unknown expander"; + } +} + + +int +selectExpander(MPT_PORT *port, int *ses_bus, int *ses_target, U8 *phys_port, _U64 *sas_addr, int *expanderType) +{ + SasExpanderPage0_t SASExpanderPage0; + int handle = -1; + U32 wwid_l; + U32 wwid_h; + _U64 sas_address; + U8 physical_port; + int bus; + int target = 0; + unsigned char inq[36]; + char buf[32]; + int i; + int n; + int t; + int numDev; + int multipleSelect = FALSE; + int curr; + SMP_REPORT_MANUFACTURER_INFO_RESPONSE smpResp; + int respDataLength; + + t = ses_bus && ses_target; + + if (kFlag == TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + { + if (t) + return 0; + + goto getHandle; + } + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + { + if (t) + return 0; + + goto getHandle; + } + + if (t) + { + *ses_bus = bus; + *ses_target = target; + } + + getParent(port, bus, target, &handle); + + goto getHandle; + } + + showPortInfoHeader(port); + + getDeviceInfoHeader(port, buf, sizeof buf); + + printf(" B___T Type Vendor Product Rev %s\n", buf); + + n = 0; + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + if (doInquiry(port, bus, target, 0, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + continue; + } + + if ((inq[0] & 0x1f) != 0x0d) + continue; + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + diag_targets[n].bus = bus; + diag_targets[n].target = target; + + n++; + + getDeviceInfo(port, bus, target, buf, sizeof buf); + + printf("%2d. %2d %3d %-9s %-8.8s %-16.16s %-4.4s %s\n", + n, bus, target, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32, buf); + + if (n == MAX_DEVICES) + break; + } + if (n == MAX_DEVICES) + break; + } + + if (n == 0) + { + if (t) + { + printf("\nNo expanders are available for this test\n"); + return 0; + } + goto getHandle; + } + + numDev = n; + printf("\nSelect an expander: [1-%d or RETURN to quit] ", numDev); + n = getNumberAnswer(1, numDev, -888); + + if (n > 0) + { + if (n == 888) + { + for (i = 0; i < numDev; i++) + { + bus = exp_targets[i].bus = diag_targets[i].bus; + target = exp_targets[i].target = diag_targets[i].target; + getParent(port, bus, target, &exp_targets[i].handle); + } + exp_targets[i].bus = -1; + exp_targets[i].target = -1; + exp_targets[i].handle = -1; + + if (t) + { + *ses_bus = -1; + *ses_target = -1; + } + + handle = 0xffff; // dummy value to indicate we need a list of handles + multipleSelect = TRUE; + } + else + { + n--; + + bus = diag_targets[n].bus; + target = diag_targets[n].target; + + if (t) + { + *ses_bus = bus; + *ses_target = target; + } + + getParent(port, bus, target, &handle); + } + } + +getHandle: + if (handle < 0) + { + printf("\nExpander Handle SASAddress Port Phys\n"); + + handle = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, handle, + &SASExpanderPage0, sizeof SASExpanderPage0) != 1) + break; + + handle = get16(SASExpanderPage0.DevHandle); + + printf(" %04x %08x%08x %2d %2d\n", handle, + get32(SASExpanderPage0.SASAddress.High), + get32(SASExpanderPage0.SASAddress.Low), + SASExpanderPage0.PhysicalPort, + SASExpanderPage0.NumPhys); + } + + printf("\nEnter handle: [0000-FFFF or RETURN to quit] "); + handle = getNumberAnswerHex(0x0000, 0xffff, -1); + if (handle < 0) + return 0; + } + + if (handle == 0) + { + printf("Enter SASAddress: [16 hex digits or RETURN to quit] "); + t = getHexDoubleNumberAnswer(&wwid_h, &wwid_l); + if (t == 0) + return 0; + + printf("Enter port: [0 to %d or RETURN to leave unspecified] ", port->numPhys - 1); + physical_port = (U8)getNumberAnswer(0, port->numPhys - 1, 255); + sas_address.Low = set32(wwid_l); + sas_address.High = set32(wwid_h); + } + else + { + curr = -1; + while (TRUE) + { + if (multipleSelect) + { + curr++; + handle = exp_targets[curr].handle; + + if (handle == -1) + { + physical_port = -1; + sas_address.Low = 0; + sas_address.High = 0; + break; + } + } + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE + <pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doEchoTest(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSataIdentifyDeviceTest(port); + break; + } + printf("Invalid selection!\n"); + break; + case 11: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doReadLinkErrorStatusTest(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSataClearAffiliationTest(port); + break; + } + printf("Invalid selection!\n"); + break; + case 12: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doDisplayPortCounters(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doDisplayPhyCounters(port); + break; + } + printf("Invalid selection!\n"); + break; + case 13: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doClearPortCounters(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doClearPhyCounters(port); + break; + } + printf("Invalid selection!\n"); + break; + case 14: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSataSmartReadTest(port); + break; + } + printf("Invalid selection!\n"); + break; + case 15: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI || + port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doSepTest(port); + break; + } + printf("Invalid selection!\n"); + break; + case 16: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doProdSpecSasIoUnitControl(port); + break; + } + printf("Invalid selection!\n"); + break; + case 17: + doDiagDataUpload(port); + break; + case 18: + doReportLunsTest(port); + break; + case 19: + doDriveFirmwareDownload(port); + break; + case 20: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + doTriggerAnalyzerWithEcho(port); + break; + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doExpanderFirmwareDownload(port); + break; + } + printf("Invalid selection!\n"); + break; + case 21: + doReadLogicalBlocks(port); + break; + case 22: + doWriteLogicalBlocks(port); + break; + case 23: + doVerifyLogicalBlocks(port); + break; + case 24: + doReadBufferFirmwareUpload(port); + break; + case 25: + doDisplayExpanderLogEntries(port); + break; + case 26: + doClearExpanderLogEntries(port); + break; + case 27: + doExpanderChangeMfgDataFields(port); + break; + case 29: + doDiagnosticPageTest(port); + break; + case 30: + doInjectRepairMediaError(port, 1); + break; + case 31: + doInjectRepairMediaError(port, 0); + break; + case 32: + doSoftwareWriteProtect(port, 1); + break; + case 33: + doSoftwareWriteProtect(port, 0); + break; + case 34: + doReadWriteCache(port, 1); + break; + case 35: + doReadWriteCache(port, 0); + break; + case 36: + doReadWriteCache(port, 3); + break; + case 37: + doReadWriteCache(port, 2); + break; + case 98: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doResetExpander(port); + break; + } + printf("Invalid selection!\n"); + break; + default: + printf("Invalid selection!\n"); + break; + } + + return 1; +} + + +void +generatePattern(int pattern, void *buf, int len) +{ + int i; + int j; + unsigned char *buf1 = (unsigned char *)buf; + unsigned short *buf2 = (unsigned short *)buf; + + switch (pattern) + { + case 1: + for (i = 0; i < len / 2; i++) + { + *buf1++ = 0x00; + *buf1++ = 0xff; + } + break; + + case 2: + for (i = 0; i < len / 2; i++) + { + *buf1++ = 0x55; + *buf1++ = 0xaa; + } + break; + + case 3: + for (i = 0; i < len; i++) + { + *buf1++ = i; + } + break; + + case 4: + for (i = 0; i < len / 2; i++) + { + *buf1++ = 1 << (i & 7); + *buf1++ = ~(1 << (i & 7)); + } + break; + + case 5: + for (i = 0; i < len / 4; i++) + { + *buf2++ = 0x0000; + *buf2++ = 0xffff; + } + break; + + case 6: + for (i = 0; i < len / 4; i++) + { + *buf2++ = 0x5555; + *buf2++ = 0xaaaa; + } + break; + + case 7: + for (i = 0; i < len / 2; i++) + { + *buf2++ = i; + } + break; + + case 8: + for (i = 0; i < len / 4; i++) + { + *buf2++ = 1 << (i & 15); + *buf2++ = ~(1 << (i & 15)); + } + break; + + case 9: + for (i = 0; i < len; i++) + { + *buf1++ = rand(); + } + break; + + case 10: + for (j = 0; j < len / 0x200; j++) + { + for (i = 0x0; i < 0x200; i++) + *buf1++ = 0xb5; + } + break; + + case 11: + for (j = 0; j < len / 0x200; j++) + { + for (i = 0x0; i < 0x200; i++) + *buf1++ = 0x4a; + } + break; + } +} + + +void +format64bitDecimal(uint64_t number, char *buf, int len) +{ + int i; + int part; + char temp[4]; + + memset(buf, ' ', len); + + i = len - 1; + + while (TRUE) + { + part = (int)(number % 1000); + number /= 1000; + + if (number == 0) + { + sprintf(temp, "%3d", part); + buf[--i] = temp[2]; + buf[--i] = temp[1]; + buf[--i] = temp[0]; + break; + } + + sprintf(temp, "%03d", part); + + buf[--i] = temp[2]; + buf[--i] = temp[1]; + buf[--i] = temp[0]; + buf[--i] = ','; + } + + buf[len - 1] = '\0'; +} + + +int +doInquiryTest(MPT_PORT *port) +{ + int bus; + int target; + int lun; + int vpd; + int page; + unsigned char inq[255]; + int i; + int n; + int t; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("VPD Page: [00-FF or RETURN for normal Inquiry] "); + page = getNumberAnswerHex(0x00, 0xff, -1); + vpd = page != -1; + + printf("\n"); + + if (vpd) + { + t = doInquiryVpdPage(port, bus, target, lun, page, inq, sizeof inq); + n = inq[3] + 4; + } + else + { + t = doInquiry(port, bus, target, lun, inq, sizeof inq); + n = inq[4] + 5; + } + + if (t == 1) + { + if (vpd) + { + printf(" B___T___L Page\n"); + printf("%2d %3d %3d %02x\n\n", + bus, target, lun, page); + } + else + { + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + printf(" B___T___L Type Vendor Product Rev\n"); + printf("%2d %3d %3d %-9s %-8.8s %-16.16s %-4.4s\n\n", + bus, target, lun, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32); + } + + printf("%d bytes of Inquiry Data returned\n\n", n); + + displayByteData(inq, n); + } + else + { + printf("Inquiry failed\n"); + } + + printf("\n"); + } +} + + +int +doWriteBufferReadBufferCompareTest(MPT_PORT *port) +{ + int bus; + int target; + unsigned char *data_in; + unsigned char *data_out; + unsigned char *p; + unsigned char *q; + int i; + unsigned int j; + int n; + int mode; + unsigned int size; + int pattern; + int passes; + int progress; + + n = selectDeviceRWBuffer(port); + if (n == 0) + return 0; + n--; + + bus = diag_targets[n].bus; + target = diag_targets[n].target; + mode = diag_targets[n].mode; + + while (TRUE) + { + size = diag_targets[n].size; + + printf("\n"); + printf(" 1. Alternating, 8-Bit, 00 and FF\n"); + printf(" 2. Alternating, 8-Bit, 55 and AA\n"); + printf(" 3. Incrementing, 8-Bit\n"); + printf(" 4. Walking 1s and 0s, 8-Bit\n"); + printf(" 5. Alternating, 16-Bit, 0000 and FFFF\n"); + printf(" 6. Alternating, 16-Bit, 5555 and AAAA\n"); + printf(" 7. Incrementing, 16-Bit\n"); + printf(" 8. Walking 1s and 0s, 16-Bit\n"); + printf(" 9: Random\n"); + printf("10: All B5\n"); + printf("11: All 4A\n"); + + printf("\nSelect a data pattern: [1-11 or RETURN to quit] "); + pattern = getNumberAnswer(1, 11, 0); + if (pattern == 0) + return 1; + + printf("Pattern length: [1-%d or RETURN to quit] ", size); + size = getNumberAnswer(1, size, 0); + if (size == 0) + return 1; + + printf("Number of iterations: [1-1000000 or 0 for infinite or RETURN to quit] "); + passes = getNumberAnswer(0, 1000000, -1); + if (passes < 0) + return 1; + + data_in = malloc(size); + data_out = malloc(size); + + generatePattern(pattern, data_out, size); + + progress = max(10, passes / 10); + + printf("Testing started...\n"); + for (i = 1; i <= passes || passes == 0; i++) + { + if (doWriteBuffer(port, bus, target, 0, mode, data_out, size) != 1) + { + printf("W "); + continue; + } + + if (doReadBuffer(port, bus, target, 0, mode, data_in, size) != 1) + { + printf("R "); + continue; + } + + if (memcmp(data_in, data_out, size) != 0) + { + p = data_out; + q = data_in; + + for (j = 0; j < size; j++) + { + if (*p != *q) + printf("\nMiscompare at buffer offset %02x expected %02x actual %02x\n", j, *p, *q); + p++; q++; + } + break; + } + +// printf("."); + + if (passes == 0) + { + if (i % 100000 == 0) + { + printf(" %d", i); + if (i == 1000000) + { + i = 0; + printf("\n"); + } + fflush(stdout); + } + } + else if (i % progress == 0) + { + printf(" %d%% ", i * 100 / passes); + fflush(stdout); + } + } + printf("\nTesting ended...\n"); + + free(data_in); + free(data_out); + } +} + + +int +getEedpMode(MPT_PORT *port, int eedp) +{ + IOCPage1_t IOCPage1; + int flags = 0; + int eedp_mode = -1; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 1, 0, &IOCPage1, sizeof IOCPage1) == 1) + { + flags = get32(IOCPage1.Flags); + + switch (flags & MPI_IOCPAGE1_EEDP_MODE_MASK) + { + case MPI_IOCPAGE1_EEDP_MODE_OFF: + printf("\nEnd-to-End Data Protection Mode is disabled\n"); + break; + case MPI_IOCPAGE1_EEDP_MODE_T10: + printf("\nEnd-to-End Data Protection Mode is set to T10\n"); + eedp_mode = 0x1; + break; + case MPI_IOCPAGE1_EEDP_MODE_LSI_1: + printf("\nEnd-to-End Data Protection Mode is set to LB\n"); + eedp_mode = 0x2; + break; + default: + printf("\nEnd-to-End Data Protection Mode is unknown, ignoring\n"); + break; + } + } + + if (eedp_mode > 0) + { + printf("\nIs firmware/hardware going to handle EEDP? [Yes or No, default is Yes] "); + + if (getYesNoAnswer(1) != 1) + { + printf("This utility will manage the Data Integrity Fields\n"); + eedp_mode += 0x100; + } + else + { + printf("Firmware/Hardware will manage the Data Integrity Fields\n"); + } + } + else + { + printf("\nShould software T10 EEDP be implemented? [Yes or No, default is Yes] "); + if (getYesNoAnswer(1) == 1) + { + printf("This utility will manage the Data Integrity Fields\n"); + eedp_mode = 0x201; + } + else if (eedp == 2) + { + printf("No EEDP will be provided\n"); + eedp_mode = 0; + } + else + { + printf("Disk cannot be used in this test\n"); + } + } + + return eedp_mode; +} + + +int +doReadTest(MPT_PORT *port) +{ + int bus; + int target; + int lun; + unsigned char *data_in; + int i; + int n; + unsigned int mode; + unsigned int size; + int eedp; + unsigned int lbn; + int lbns; + int len; + int passes; + int random; + int progress; + int eedp_mode = 0; + + n = selectDeviceRWMedia(port); + if (n == 0) + return 0; + n--; + + bus = diag_targets[n].bus; + target = diag_targets[n].target; + lun = diag_targets[n].lun; + mode = diag_targets[n].mode; + size = diag_targets[n].size; + eedp = diag_targets[n].eedp; + + if (eedp) + { + eedp_mode = getEedpMode(port, eedp); + + if (eedp_mode < 0) + return 0; + } + + while (TRUE) + { + printf("\n"); + printf("Number of blocks per I/O: [1-64 or RETURN to quit] "); + lbns = getNumberAnswer(1, 64, 0); + if (lbns == 0) + return 1; + + printf("Number of iterations: [1-1000000 or 0 for infinite or RETURN to quit] "); + passes = getNumberAnswer(0, 1000000, -1); + if (passes < 0) + return 1; + + printf("Type of I/O: [0=Sequential, 1=Random, default is 0] "); + random = getNumberAnswer(0, 1, 0); + + len = lbns * ((eedp_mode == 0) ? mode : 512); + + data_in = malloc(lbns * mode); + + progress = max(10, passes / 10); + + lbn = 128; + printf("Testing started...\n"); + for (i = 1; i <= passes || passes == 0; i++, lbn += lbns) + { + if (random) + { + lbn = rand(); + while (lbn + lbns >= size) + { + lbn /= 2; + } + } + else + { + if (lbn + lbns >= size) + { + lbn = 128; + } + } + + if (doRead(port, bus, target, lun, lbn, lbns, eedp_mode, data_in, len) != 1) + { + printf("R "); + continue; + } + +// printf("."); + + if (passes == 0) + { + if (i % 100000 == 0) + { + printf(" %d", i); + if (i == 1000000) + { + i = 0; + printf("\n"); + } + fflush(stdout); + } + } + else if (i % progress == 0) + { + printf(" %d%% ", i * 100 / passes); + fflush(stdout); + } + } + printf("\nTesting ended...\n"); + + free(data_in); + } +} + + +int +doWriteReadCompareTest(MPT_PORT *port) +{ + int bus; + int target; + int lun; + unsigned char *data_in; + unsigned char *data_out; + int i; + int n; + unsigned int mode; + unsigned int size; + int eedp; + int pattern; + unsigned int lbn; + int lbns; + int len; + int passes; + int random; + int progress; + int eedp_mode = 0; + int quit; + + n = selectDeviceRWMedia(port); + if (n == 0) + return 0; + n--; + + bus = diag_targets[n].bus; + target = diag_targets[n].target; + lun = diag_targets[n].lun; + mode = diag_targets[n].mode; + size = diag_targets[n].size; + eedp = diag_targets[n].eedp; + + if (eedp) + { + eedp_mode = getEedpMode(port, eedp); + + if (eedp_mode < 0) + return 0; + } + + while (TRUE) + { + printf("\n"); + printf(" 1. Alternating, 8-Bit, 00 and FF\n"); + printf(" 2. Alternating, 8-Bit, 55 and AA\n"); + printf(" 3. Incrementing, 8-Bit\n"); + printf(" 4. Walking 1s and 0s, 8-Bit\n"); + printf(" 5. Alternating, 16-Bit, 0000 and FFFF\n"); + printf(" 6. Alternating, 16-Bit, 5555 and AAAA\n"); + printf(" 7. Incrementing, 16-Bit\n"); + printf(" 8. Walking 1s and 0s, 16-Bit\n"); + printf(" 9: Random\n"); + printf("10: All B5\n"); + printf("11: All 4A\n"); + printf("12: Incrementing across iterations (00 through FF)\n"); + printf("\nSelect a data pattern: [1-12 or RETURN to quit] "); + pattern = getNumberAnswer(1, 12, 0); + if (pattern == 0) + return 1; + + printf("Number of blocks per I/O: [1-64 or RETURN to quit] "); + lbns = getNumberAnswer(1, 64, 0); + if (lbns == 0) + return 1; + + if (pattern == 12) + printf("Number of iterations per pattern: [1-1000000 or RETURN to quit] "); + else + printf("Number of iterations: [1-1000000 or 0 for infinite or RETURN to quit] "); + passes = getNumberAnswer(0, 1000000, -1); + if (passes < 0) + return 1; + if (passes == 0 && pattern == 12) + return 1; + + printf("Type of I/O: [0=Sequential, 1=Random, default is 0] "); + random = getNumberAnswer(0, 1, 0); + + len = lbns * ((eedp_mode == 0) ? mode : 512); + + data_in = malloc(lbns * mode); + data_out = malloc(lbns * mode); + + if (pattern == 12) + { + int j; + int quit_test = 0; + + printf("Stop pattern on Write, Read, or Compare error? [Yes or No, default is Yes] "); + quit = getYesNoAnswer(1); + + if (quit) + { + printf("Stop test on Write, Read, or Compare error? [Yes or No, default is Yes] "); + quit_test = getYesNoAnswer(1); + } + + lbn = 128; + printf("Testing started...\n"); + for (j = 0x00; j <= 0xff; j++) + { + FCPortPage6_t FCPortPage6; + uint64_t LipCount = 0; + uint64_t LossOfSyncCount = 0; + uint64_t LipCountDiff; + uint64_t LossOfSyncCountDiff; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &FCPortPage6, sizeof FCPortPage6) == 1) + { + LipCount = get64(FCPortPage6.LipCount); + LossOfSyncCount = get64(FCPortPage6.LossOfSyncCount); + } + } + + printf(" %02X ", j); + fflush(stdout); + + memset(data_out, j, len); + + for (i = 1; i <= passes; i++, lbn += lbns) + { + if (random) + { + lbn = rand(); + while (lbn + lbns >= size) + { + lbn /= 2; + } + } + else + { + if (lbn + lbns >= size) + { + lbn = 128; + } + } + + if (doWrite(port, bus, target, lun, lbn, lbns, eedp_mode, data_out, len) != 1) + { + if (quit) + { + printf("W at pass %d", i); + if (quit_test) + j = 256; + break; + } + else + { + printf("W "); + continue; + } + } + + if (doRead(port, bus, target, lun, lbn, lbns, eedp_mode, data_in, len) != 1) + { + if (quit) + { + printf("R at pass %d", i); + if (quit_test) + j = 256; + break; + } + else + { + printf("R "); + continue; + } + } + + if (memcmp(data_in, data_out, len) != 0) + { + if (quit) + { + printf("C at pass %d", i); + if (quit_test) + j = 256; + break; + } + else + { + printf("C "); + continue; + } + } + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &FCPortPage6, sizeof FCPortPage6) == 1) + { + LipCountDiff = get64(FCPortPage6.LipCount) - LipCount; + LossOfSyncCountDiff = get64(FCPortPage6.LossOfSyncCount) - LossOfSyncCount; + if (LipCountDiff != 0 || LossOfSyncCountDiff != 0) + { + printf("\nPattern %02X caused %s%d LIP%s and %s%d Loss%sOfSync\n", data_out[0], + LipCountDiff > 1000 ? ">" : "", + LipCountDiff > 1000 ? 1000 : (int)LipCountDiff, + LipCountDiff != 1 ? "s" : "", + LossOfSyncCountDiff > 1000 ? ">" : "", + LossOfSyncCountDiff > 1000 ? 1000 : (int)LossOfSyncCountDiff, + LossOfSyncCountDiff != 1 ? "es" : ""); + } + } + } + } + printf("\nTesting ended...\n"); + } + else + { + generatePattern(pattern, data_out, len); + + printf("Stop test on Write, Read, or Compare error? [Yes or No, default is Yes] "); + quit = getYesNoAnswer(1); + + progress = max(10, passes / 10); + + lbn = 128; + printf("Testing started...\n"); + for (i = 1; i <= passes || passes == 0; i++, lbn += lbns) + { + if (random) + { + lbn = rand(); + while (lbn + lbns >= size) + { + lbn /= 2; + } + } + else + { + if (lbn + lbns >= size) + { + lbn = 128; + } + } + + if (doWrite(port, bus, target, lun, lbn, lbns, eedp_mode, data_out, len) != 1) + { + if (quit) + { + printf("W at pass %d", i); + break; + } + else + { + printf("W "); + continue; + } + } + + if (doRead(port, bus, target, lun, lbn, lbns, eedp_mode, data_in, len) != 1) + { + if (quit) + { + printf("R at pass %d", i); + break; + } + else + { + printf("R "); + continue; + } + } + + if (memcmp(data_in, data_out, len) != 0) + { + if (quit) + { + printf("C at pass %d", i); + break; + } + else + { + printf("C "); + continue; + } + } + +// printf("."); + + if (passes == 0) + { + if (i % 100000 == 0) + { + printf(" %d", i); + if (i == 1000000) + { + i = 0; + printf("\n"); + } + fflush(stdout); + } + } + else if (i % progress == 0) + { + printf(" %d%% ", i * 100 / passes); + fflush(stdout); + } + } + printf("\nTesting ended...\n"); + } + + free(data_in); + free(data_out); + } +} + + +int +doWriteTest(MPT_PORT *port) +{ + int bus; + int target; + int lun; + unsigned char *data_in; + unsigned char *data_out; + int i; + int j; + int n; + unsigned int mode; + unsigned int size; + int eedp; + U32 tag; + unsigned int lbn; + int lbns; + int len; + int progress; + int eedp_mode = 0; + int quit; + U32 *p; + + n = selectDeviceRWMedia(port); + if (n == 0) + return 0; + n--; + + bus = diag_targets[n].bus; + target = diag_targets[n].target; + lun = diag_targets[n].lun; + mode = diag_targets[n].mode; + size = diag_targets[n].size; + eedp = diag_targets[n].eedp; + + if (eedp) + { + eedp_mode = getEedpMode(port, eedp); + + if (eedp_mode < 0) + return 0; + } + + printf("\nTagging data value: [00000000-FFFFFFFF or RETURN to quit] "); + if (getHexNumberAnswer(&tag) == 0) + return 1; + + printf("Number of blocks per I/O: [1-64 or RETURN to quit] "); + lbns = getNumberAnswer(1, 64, 0); + if (lbns == 0) + return 1; + + len = lbns * ((eedp_mode == 0) ? mode : 512); + + data_in = malloc(lbns * mode); + data_out = malloc(lbns * mode); + + printf("Stop pattern on Write error? [Yes or No, default is Yes] "); + quit = getYesNoAnswer(1); + + progress = ((size - 128) / 10) / lbns * lbns; + + printf("Testing started...\n"); + for (lbn = 128; lbn < size; i++, lbn += lbns) + { + p = (U32 *)data_out; + + for (i = 0; i < lbns; i++) + { + *p++ = set32x(tag); + for (j = 4; j < (int)((eedp_mode == 0) ? mode : 512); j += 4) + { + *p++ = set32x(lbn + i); + } + } + + if (doWrite(port, bus, target, lun, lbn, lbns, eedp_mode, data_out, len) != 1) + { + if (quit) + { + printf("W at lbn %d", lbn); + break; + } + else + { + printf("W "); + continue; + } + } + +// printf("."); + + if (lbn > 128 && (lbn - 128) % progress == 0) + { + printf(" %d%% ", (lbn - 128) * 10 / progress); + fflush(stdout); + } + } + printf("\nTesting ended...\n"); + + free(data_in); + free(data_out); + + return 1; +} + + +int +doReadCompareTest(MPT_PORT *port) +{ + int bus; + int target; + int lun; + unsigned char *data_in; + unsigned char *data_out; + int i; + int j; + int n; + unsigned int mode; + unsigned int size; + int eedp; + U32 tag; + unsigned int lbn; + int lbns; + int len; + int progress; + int eedp_mode = 0; + int quit; + U32 *p; + U32 *q; + + n = selectDeviceRWMedia(port); + if (n == 0) + return 0; + n--; + + bus = diag_targets[n].bus; + target = diag_targets[n].target; + lun = diag_targets[n].lun; + mode = diag_targets[n].mode; + size = diag_targets[n].size; + eedp = diag_targets[n].eedp; + + if (eedp) + { + eedp_mode = getEedpMode(port, eedp); + + if (eedp_mode < 0) + return 0; + } + + printf("\nTagging data value: [00000000-FFFFFFFF or RETURN to quit] "); + if (getHexNumberAnswer(&tag) == 0) + return 1; + + printf("Number of blocks per I/O: [1-64 or RETURN to quit] "); + lbns = getNumberAnswer(1, 64, 0); + if (lbns == 0) + return 1; + + len = lbns * ((eedp_mode == 0) ? mode : 512); + + data_in = malloc(lbns * mode); + data_out = malloc(lbns * mode); + + printf("Stop pattern on Read or Compare error? [Yes or No, default is Yes] "); + quit = getYesNoAnswer(1); + + progress = ((size - 128) / 10) / lbns * lbns; + + printf("Testing started...\n"); + for (lbn = 128; lbn < size; i++, lbn += lbns) + { + p = (U32 *)data_out; + + for (i = 0; i < lbns; i++) + { + *p++ = set32x(tag); + for (j = 4; j < (int)((eedp_mode == 0) ? mode : 512); j += 4) + { + *p++ = set32x(lbn + i); + } + } + + if (doRead(port, bus, target, lun, lbn, lbns, eedp_mode, data_in, len) != 1) + { + if (quit) + { + printf("R at lbn %d", lbn); + break; + } + else + { + printf("R "); + continue; + } + } + + if (memcmp(data_in, data_out, len) != 0) + { + if (quit) + { + p = (U32 *)data_out; + q = (U32 *)data_in; + + for (i = 0; i < lbns; i++) + { + for (j = 0; j < (int)((eedp_mode == 0) ? mode : 512); j += 4) + { + if (*p++ != *q++) + { + printf("C at lbn %d offset %x", lbn + i, j); + i = lbns - 1; + break; + } + } + } + break; + } + else + { + printf("C "); + continue; + } + } + +// printf("."); + + if (lbn > 128 && (lbn - 128) % progress == 0) + { + printf(" %d%% ", (lbn - 128) * 10 / progress); + fflush(stdout); + } + } + printf("\nTesting ended...\n"); + + free(data_in); + free(data_out); + + return 1; +} + + +int +doTestUnitReadyTest(MPT_PORT *port) +{ + int bus; + int target; + int lun; + unsigned char data[512]; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + if (doTestUnitReady(port, bus, target, lun) == 1) + { + printf("\nTest Unit Ready successful\n"); + } + else + { + printf("\nTest Unit Ready failed\n"); + } + + if (doRead(port, bus, target, lun, 0, 1, 0, data, sizeof data) == 1) + { + printf("\nRead successful\n"); + } + else + { + printf("\nRead failed\n"); + } + + + if (doTestUnitReady(port, bus, target, lun) == 1) + { + printf("\nTest Unit Ready successful\n"); + } + else + { + printf("\nTest Unit Ready failed\n"); + } + + printf("\n"); + } +} + + +int +doLogSenseTest(MPT_PORT *port) +{ + int bus; + int target; + int lun; + int page; + unsigned char log[1024]; + int n; + int t; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("Page: [00-3F or RETURN to quit] "); + page = getNumberAnswerHex(0x00, 0x3f, -1); + if (page < 0) + return 1; + + printf("\n"); + + t = doLogSense(port, bus, target, lun, page, 1, log, sizeof log); + n = get2bytes(log, 2) + 4; + + if (t == 1) + { + printf(" B___T___L Page\n"); + printf("%2d %3d %3d %02x\n\n", + bus, target, lun, page); + + printf("%d bytes of Log Sense Data returned\n\n", n); + + if (n > sizeof log) + { + printf("Too much data received, only %d bytes will be displayed\n\n", (int)sizeof log); + n = sizeof log; + } + + displayByteData(log, n); + } + else + { + printf("Log Sense failed\n"); + } + + printf("\n"); + } +} + + +int +doReadCapacityTest(MPT_PORT *port) +{ + int bus; + int target; + int lun; + unsigned char inq[36]; + unsigned char cap[8]; + unsigned char bl[6]; + unsigned int min_size; + unsigned int max_size; + unsigned int gran; + unsigned int mode; + unsigned int size; + unsigned char cap16[32]; + uint64_t size16; + uint64_t capacity; + int t; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("\n"); + + if (doInquiry(port, bus, target, lun, inq, sizeof inq) == 1) + { + if ((inq[0] & 0x1f) == 0x01) + { + if (doReadBlockLimits(port, bus, target, lun, bl, sizeof bl) == 1) + { + min_size = get2bytes(bl, 4); + max_size = get3bytes(bl, 1); + gran = 1 << (bl[0] & 0x1f); + + printf("Min Block Size = %d, Max Block Size = %d, Granularity = %d\n", + min_size, max_size, gran); + } + else + { + printf("Read Block Limits failed\n"); + } + + printf("\n"); + + continue; + } + } + + if (doReadCapacity16(port, bus, target, lun, cap16, sizeof cap16) == 1) + { + mode = get4bytes(cap16, 8); + size16 = get8bytes(cap16, 0); + + capacity = (uint64_t)mode * (size16 + 1); + + printf("Block Size = %08x, Last Block = %016" INT64_FMT "x", mode, size16); + } + else if (doReadCapacity(port, bus, target, lun, cap, sizeof cap) == 1) + { + mode = get4bytes(cap, 4); + size = get4bytes(cap, 0); + + capacity = (uint64_t)mode * (size + 1); + + printf("Block Size = %08x, Last Block = %08x", mode, size); + } + else + { + capacity = 0; + + printf("Read Capacity failed\n"); + } + + if (capacity == 0) + { + } + else if (capacity > (uint64_t)1000*1000*1000*1000) + { + t = (int)(capacity / ((uint64_t)100*1000*1000*1000)); + printf(" -- Capacity is %d.%d TB\n", t / 10, t % 10); + } + else if (capacity > (uint64_t)1000*1000*1000) + { + t = (int)(capacity / ((uint64_t)100*1000*1000)); + printf(" -- Capacity is %d.%d GB\n", t / 10, t % 10); + } + else if (capacity > (uint64_t)1000*1000) + { + t = (int)(capacity / ((uint64_t)100*1000)); + printf(" -- Capacity is %d.%d MB\n", t / 10, t % 10); + } + else + { + t = (int)(capacity / ((uint64_t)100)); + printf(" -- Capacity is %d.%d KB\n", t / 10, t % 10); + } + + printf("\n"); + } +} + + +int +doModePageTest(MPT_PORT *port) +{ + int bus; + int target; + int lun; + int control; + int page; + unsigned char data[255]; + int n; + int t; + char *control_strings[4] = {"Current", "Changeable", "Default", "Saved"}; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("Mode Page: [00-3F or RETURN to quit] "); + page = getNumberAnswerHex(0x00, 0x3f, -1); + if (page < 0) + return 1; + + printf("\n"); + + for (control = 0; control < 4; control++) + { + t = doModeSense(port, bus, target, lun, page, control, 0, data, sizeof data); + n = data[0] + 1; + + if (t == 1) + { + printf("%d bytes of Page %x %s Data returned\n\n", + n, page, control_strings[control]); + + displayByteData(data, n); + } + else + { + printf("Mode Sense (Page %x %s) failed\n", page, control_strings[control]); + } + + printf("\n"); + } + } +} + + +int +doEchoTest(MPT_PORT *port) +{ + FCPortPage0_t FCPortPage0; + FCDevicePage0_t FCDevicePage0; + ExLinkServiceSendRequest_t req; + ExLinkServiceSendReply_t rep; + U32 buf_in[32]; + U32 buf_out[32]; + U32 els; + U32 d_id; + U32 port_id; + int len; + int n; + int i; + char *type; + U32 port_ids[MAX_DEVICES]; + int pattern; + int passes; + int progress; + int ioc_status; + U32 code; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, &FCPortPage0, sizeof FCPortPage0) != 1) + return 0; + + port_id = get32(FCPortPage0.PortIdentifier); + + printf(" Type WWNN WWPN PortId\n"); + + n = 0; + d_id = 0xffffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, d_id, + &FCDevicePage0, sizeof FCDevicePage0) != 1) + break; + + d_id = get32(FCDevicePage0.PortIdentifier); + + if (d_id == port_id) + { + type = port->chipName; + } + else if (FCDevicePage0.Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR) + { + if (FCDevicePage0.Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET) + type = "FCP Initiator & Target"; + else + type = "FCP Initiator"; + } + else + { + if (FCDevicePage0.Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET) + type = "FCP Target"; + else + type = "Non-FCP"; + } + + port_ids[n] = d_id; + + n++; + + printf("%2d. %-24s %08x%08x %08x%08x %06x\n", n, type, + get32(FCDevicePage0.WWNN.High), get32(FCDevicePage0.WWNN.Low), + get32(FCDevicePage0.WWPN.High), get32(FCDevicePage0.WWPN.Low), + d_id); + + if (n == MAX_DEVICES) + break; + } + + if (n == 0) + { + printf("\nNo devices are available for this test\n"); + return 1; + } + + printf("\nSelect a device: [1-%d or RETURN to quit] ", n); + n = getNumberAnswer(1, n, 0); + if (n == 0) + return 1; + n--; + + d_id = port_ids[n]; + + els = 0x10; + + while (TRUE) + { + printf("\n"); + printf(" 1. Alternating, 8-Bit, 00 and FF\n"); + printf(" 2. Alternating, 8-Bit, 55 and AA\n"); + printf(" 3. Incrementing, 8-Bit\n"); + printf(" 4. Walking 1s and 0s, 8-Bit\n"); + printf(" 5. Alternating, 16-Bit, 0000 and FFFF\n"); + printf(" 6. Alternating, 16-Bit, 5555 and AAAA\n"); + printf(" 7. Incrementing, 16-Bit\n"); + printf(" 8. Walking 1s and 0s, 16-Bit\n"); + printf("\nSelect a data pattern: [1-8 or RETURN to quit] "); + pattern = getNumberAnswer(1, 8, 0); + if (pattern == 0) + return 1; + + printf("Pattern length in words: [2-32 or RETURN to quit] "); + len = getNumberAnswer(2, 32, 0); + if (len == 0) + return 1; + len *= 4; + + printf("Number of iterations: [1-1000000 or 0 for infinite or RETURN to quit] "); + passes = getNumberAnswer(0, 1000000, -1); + if (passes < 0) + return 1; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_FC_EX_LINK_SRVC_SEND; + req.AliasIndex = virtInit; + req.MsgFlags_Did = set32(d_id); + req.ElsCommandCode = set32(els); + + generatePattern(pattern, buf_out, len); + + buf_out[0] = set32x(els); + + progress = max(10, passes / 10); + + printf("Testing started...\n"); + for (i = 1; i <= passes || passes == 0; i++) + { + buf_in[0] = 0; + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf_in, sizeof buf_in, buf_out, len, SHORT_TIME) != 1) + { + printf("E"); + continue; + } + + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + printf("\nSendELS failed, IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); + return 0; + } + + code = (get32x_be(buf_in[0]) >> 24) & 0xff; + + if (code == 0x01) + { + printf("\nECHO ELS rejected\n"); + return 0; + } + + if (code != 0x02) + { + printf("\nECHO ELS not accepted, code is %02x\n", code); + return 0; + } + + if (memcmp(buf_in + 1, buf_out + 1, len - 4) != 0) + { + printf("C "); + continue; + } + +// printf("."); + + if (passes == 0) + { + if (i % 100000 == 0) + { + printf(" %d", i); + if (i == 1000000) + { + i = 0; + printf("\n"); + } + fflush(stdout); + } + } + else if (i % progress == 0) + { + printf(" %d%% ", i * 100 / passes); + fflush(stdout); + } + } + printf("\nTesting ended...\n"); + } +} + + +int +doReadLinkErrorStatusTest(MPT_PORT *port) +{ + FCPortPage0_t FCPortPage0; + FCDevicePage0_t FCDevicePage0; + ExLinkServiceSendRequest_t req; + ExLinkServiceSendReply_t rep; + U32 buf_in[7]; + U32 buf_out[2]; + U32 els; + U32 d_id; + U32 port_id; + int n; + char *type; + U32 port_ids[MAX_DEVICES]; + int ioc_status; + U32 code; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, &FCPortPage0, sizeof FCPortPage0) != 1) + return 0; + + port_id = get32(FCPortPage0.PortIdentifier); + + printf(" Type WWNN WWPN PortId\n"); + + n = 0; + d_id = 0xffffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, d_id, + &FCDevicePage0, sizeof FCDevicePage0) != 1) + break; + + d_id = get32(FCDevicePage0.PortIdentifier); + + if (d_id == port_id) + { + type = port->chipName; + } + else if (FCDevicePage0.Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR) + { + if (FCDevicePage0.Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET) + type = "FCP Initiator & Target"; + else + type = "FCP Initiator"; + } + else + { + if (FCDevicePage0.Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET) + type = "FCP Target"; + else + type = "Non-FCP"; + } + + port_ids[n] = d_id; + + n++; + + printf("%2d. %-24s %08x%08x %08x%08x %06x\n", n, type, + get32(FCDevicePage0.WWNN.High), get32(FCDevicePage0.WWNN.Low), + get32(FCDevicePage0.WWPN.High), get32(FCDevicePage0.WWPN.Low), + d_id); + + if (n == MAX_DEVICES) + break; + } + + if (n == 0) + { + printf("\nNo devices are available for this test\n"); + return 1; + } + + printf("\nSelect a device: [1-%d or RETURN to quit] ", n); + n = getNumberAnswer(1, n, 0); + if (n == 0) + return 1; + n--; + + printf("\n"); + + d_id = port_ids[n]; + + els = 0x0f; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_FC_EX_LINK_SRVC_SEND; + req.AliasIndex = virtInit; + req.MsgFlags_Did = set32(d_id); + req.ElsCommandCode = set32(els); + + buf_out[0] = set32x(els); + buf_out[1] = set32x_be(d_id); + + buf_in[0] = 0; + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf_in, sizeof buf_in, buf_out, sizeof buf_out, SHORT_TIME) == 1) + { + char buf[32]; + + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + printf("SendELS failed, IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); + return 0; + } + + code = (get32x_be(buf_in[0]) >> 24) & 0xff; + + if (code == 0x01) + { + printf("RLS ELS rejected\n"); + return 0; + } + + if (code != 0x02) + { + printf("RLS ELS not accepted, code is %02x\n", code); + return 0; + } + + format64bitDecimal(get32x_be(buf_in[1]), buf, sizeof buf); + printf("Link Failure Count %32s\n", buf); + + format64bitDecimal(get32x_be(buf_in[2]), buf, sizeof buf); + printf("Loss Of Sync Count %32s\n", buf); + + format64bitDecimal(get32x_be(buf_in[3]), buf, sizeof buf); + printf("Loss Of Signal Count %32s\n", buf); + + format64bitDecimal(get32x_be(buf_in[4]), buf, sizeof buf); + printf("Primitive Sequence Error Count %32s\n", buf); + + format64bitDecimal(get32x_be(buf_in[5]), buf, sizeof buf); + printf("Invalid Tx Word Count %32s\n", buf); + + format64bitDecimal(get32x_be(buf_in[6]), buf, sizeof buf); + printf("Invalid CRC Count %32s\n", buf); + } + + return 1; +} + + +int +doDisplayPortCounters(MPT_PORT *port) +{ + FCPortPage6_t FCPortPage6; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &FCPortPage6, sizeof FCPortPage6) == 1) + { + char buf[32]; + uint64_t time; + int seconds; + int minutes; + int hours; + int days; + + time = get64(FCPortPage6.TimeSinceReset); + seconds = (int)(time / 1000000) % 60; + minutes = (int)(time / 1000000 / 60) % 60; + hours = (int)(time / 1000000 / 60 / 60) % 24; + days = (int)(time / 1000000 / 60 / 60 / 24); + sprintf(buf, "%d day%s + %02d:%02d:%02d", days, days == 1 ? "" : "s", hours, minutes, seconds); + printf("Time Since Reset %32s\n\n", buf); + + format64bitDecimal(get64(FCPortPage6.TxFrames), buf, sizeof buf); + printf("Tx Frames %32s\n", buf); + + format64bitDecimal(get64(FCPortPage6.RxFrames), buf, sizeof buf); + printf("Rx Frames %32s\n\n", buf); + + format64bitDecimal(get64(FCPortPage6.TxWords), buf, sizeof buf); + printf("Tx Words %32s\n", buf); + + format64bitDecimal(get64(FCPortPage6.RxWords), buf, sizeof buf); + printf("Rx Words %32s\n\n", buf); + + format64bitDecimal(get64(FCPortPage6.LipCount), buf, sizeof buf); + printf("LIP Count %32s\n", buf); + + format64bitDecimal(get64(FCPortPage6.NosCount), buf, sizeof buf); + printf("NOS Count %32s\n\n", buf); + + format64bitDecimal(get64(FCPortPage6.ErrorFrames), buf, sizeof buf); + printf("Error Frames %32s\n", buf); + + format64bitDecimal(get64(FCPortPage6.DumpedFrames), buf, sizeof buf); + printf("Dumped Frames %32s\n\n", buf); + + format64bitDecimal(get64(FCPortPage6.LinkFailureCount), buf, sizeof buf); + printf("Link Failure Count %32s\n", buf); + + format64bitDecimal(get64(FCPortPage6.LossOfSyncCount), buf, sizeof buf); + printf("Loss Of Sync Count %32s\n", buf); + + format64bitDecimal(get64(FCPortPage6.LossOfSignalCount), buf, sizeof buf); + printf("Loss Of Signal Count %32s\n", buf); + + format64bitDecimal(get64(FCPortPage6.PrimativeSeqErrCount), buf, sizeof buf); + printf("Primitive Sequence Error Count %32s\n", buf); + + format64bitDecimal(get64(FCPortPage6.InvalidTxWordCount), buf, sizeof buf); + printf("Invalid Tx Word Count %32s\n", buf); + + format64bitDecimal(get64(FCPortPage6.InvalidCrcCount), buf, sizeof buf); + printf("Invalid CRC Count %32s\n\n", buf); + + format64bitDecimal(get64(FCPortPage6.FcpInitiatorIoCount), buf, sizeof buf); + printf("FCP Initiator I/O Count %32s\n", buf); + } + + return 1; +} + + +int +doClearPortCounters(MPT_PORT *port) +{ + ConfigReply_t rep; + FCPortPage6_t FCPortPage6; + + if (getConfigPageHeader(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &rep) != 1) + return 0; + + memset(&FCPortPage6, 0, sizeof FCPortPage6); + + FCPortPage6.Header = rep.Header; + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &FCPortPage6, sizeof FCPortPage6) != 1) + printf("Failed to clear port counters!\n"); + else + printf("Port counters have been cleared\n"); + + return 1; +} + + +int +doTriggerAnalyzerWithEcho(MPT_PORT *port) +{ + FCPortPage0_t FCPortPage0; + ExLinkServiceSendRequest_t req; + ExLinkServiceSendReply_t rep; + U32 buf_in[32]; + U32 buf_out[32]; + U32 els; + U32 d_id; + char name[256]; + int n; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, &FCPortPage0, sizeof FCPortPage0) != 1) + return 0; + + d_id = get32(FCPortPage0.PortIdentifier); + + els = 0x10; + + n = getFileName(name, sizeof name, stdin, "analyzer trigger", 0); + if (n > 0) + { + printf("Waiting for \"%s\" to be created...", name); + waitForFile(name); + printf("\nFile created, sending ECHO ELS\n"); + } + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_FC_EX_LINK_SRVC_SEND; + req.AliasIndex = virtInit; + req.MsgFlags_Did = set32(d_id); + req.ElsCommandCode = set32(els); + + memset(buf_out, 0, sizeof buf_out); + + buf_out[0] = set32x(els); + + memset(buf_in, 0, sizeof buf_in); + + return doMptCommandCheck(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf_in, sizeof buf_in, buf_out, sizeof buf_out, SHORT_TIME); +} + + +int +isSata(MPT_PORT *port, int bus, int target) +{ + int b_t; + int dev_handle; + int address; + SasDevicePage0_t SASDevicePage0; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (mpi2) + { + if (mapBusTargetToDevHandle(port, bus, target, &dev_handle) != 1) + dev_handle = 0; + address = MPI2_SAS_DEVICE_PGAD_FORM_HANDLE + dev_handle; + } + else + { + b_t = (bus << 8) + target; + address = (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID + <= 6) + { + t = get2bytes(vpd, 4); + if (t == 0x0001) + { + return 1; + } + } + } + } + } + } + } + + return 0; +} + + +int +getPath(MPT_PORT *port, int bus, int target, PATH *path) +{ + int b_t; + int dev_handle; + int address; + int handle; + SasDevicePage0_t SASDevicePage0; + SasEnclosurePage0_t SASEnclosurePage0; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (mpi2) + { + if (mapBusTargetToDevHandle(port, bus, target, &dev_handle) != 1) + dev_handle = 0; + address = MPI2_SAS_DEVICE_PGAD_FORM_HANDLE + dev_handle; + } + else + { + b_t = (bus << 8) + target; + address = (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID + <slot = get16(SASDevicePage0.Slot); + path->encl_id_l = get32(SASEnclosurePage0.EnclosureLogicalID.Low); + path->encl_id_h = get32(SASEnclosurePage0.EnclosureLogicalID.High); + return 1; + } + } + } + + return 0; +} + + +int +getParent(MPT_PORT *port, int bus, int target, int *parent) +{ + int b_t; + int dev_handle; + int address; + int handle; + SasDevicePage0_t SASDevicePage0; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (mpi2) + { + if (mapBusTargetToDevHandle(port, bus, target, &dev_handle) != 1) + dev_handle = 0; + address = MPI2_SAS_DEVICE_PGAD_FORM_HANDLE + dev_handle; + } + else + { + b_t = (bus << 8) + target; + address = (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID + <iocNumber; + + if (mpi2) + return isRaidPhysDisk2(port, bus, target, physdisk); + + IOCPage3 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_IOC, 3, 0, &length); + if (IOCPage3 == NULL) + return 0; + + for (i = 0; i < IOCPage3->NumPhysDisks; i++) + { + if (bus == IOCPage3->PhysDisk[i].PhysDiskBus && + target == IOCPage3->PhysDisk[i].PhysDiskID && + ioc == IOCPage3->PhysDisk[i].PhysDiskIOC) + { + *physdisk = IOCPage3->PhysDisk[i].PhysDiskNum; + free(IOCPage3); + return 1; + } + } + + free(IOCPage3); + return 0; +} + + +int +isRaidPhysDisk2(MPT_PORT *port, int bus, int target, int *physdisk) +{ + Mpi2RaidConfigurationPage0_t *RaidConfigPage0; + int i; + int handle; + int flags; + int type; + + if (!mapBusTargetToDevHandle(port, bus, target, &handle)) + return 0; + + getRaidConfig(port, MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT, handle, -1, &RaidConfigPage0); + + if (RaidConfigPage0 == NULL) + return 0; + + for (i = 0; i < RaidConfigPage0->NumElements; i++) + { + flags = get16(RaidConfigPage0->ConfigElement[i].ElementFlags); + type = flags & MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; + + if (type == MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT) + { + if (handle == get16(RaidConfigPage0->ConfigElement[i].PhysDiskDevHandle)) + { + if (physdisk) + *physdisk = RaidConfigPage0->ConfigElement[i].PhysDiskNum; + free(RaidConfigPage0); + return 1; + } + } + } + + free(RaidConfigPage0); + return 0; +} + + +int +doReadLogicalBlocks(MPT_PORT *port) +{ + int bus; + int target; + int lun; + int physdisk; + U32 lbn; + int lbns; + unsigned char *buf; + int i; + int j; + int n; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("Logical block: [00000000-FFFFFFFF or RETURN to quit] "); + if (getHexNumberAnswer(&lbn) == 0) + return 1; + + printf("Number of logical blocks: [1-64 or RETURN to quit] "); + lbns = getNumberAnswer(1, 64, 0); + if (lbns == 0) + return 1; + + n = lbns * 512; + buf = malloc(n); + + printf("\n"); + + if (isRaidPhysDisk(port, bus, target, &physdisk)) + { + + if (isRaidVolume(port, bus, target)) + { + printf("The device selected is part of a RAID Volume (PhysDisk %d)\n\n", physdisk); + printf("Do you want to directly access the PhysDisk? [Yes or No, default is No] "); + port->raidPassthru = getYesNoAnswer(0); + printf("\n"); + } + else + { + printf("The device selected is RAID PhysDisk %d\n\n", physdisk); + port->raidPassthru = 1; + } + port->raidBus = bus; + port->raidTarget = target; + port->raidPhysdisk = physdisk; + } + + if (doRead(port, bus, target, lun, lbn, lbns, 0, buf, n) == 1) + { + for (i = 0, j = 0; i < n/4; i++, j++) + { + if (j == 0) + printf("%04x : ", i*4); + + printf("%08x ", get32x(((unsigned int *)buf)[i])); + + if (j == 7) + { + printf("\n"); + j = -1; + } + + if ((i % 128) == 127) + printf("\n"); + } + } + else + { + printf("Read failed\n\n"); + } + + free(buf); + } + + return 1; +} + + +int +doWriteLogicalBlocks(MPT_PORT *port) +{ + int bus; + int target; + int lun; + int physdisk; + U32 lbn; + int lbns; + unsigned char *buf; + int n; + int pattern; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("Logical block: [00000000-FFFFFFFF or RETURN to quit] "); + if (getHexNumberAnswer(&lbn) == 0) + return 1; + + printf("Number of logical blocks: [1-64 or RETURN to quit] "); + lbns = getNumberAnswer(1, 64, 0); + if (lbns == 0) + return 1; + + printf("Data to write: [0=Zeros, 1=Ones, 2=Preserve (read first), default is 2] "); + pattern = getNumberAnswer(0, 2, 2); + + n = lbns * 512; + buf = malloc(n); + + printf("\n"); + + if (isRaidPhysDisk(port, bus, target, &physdisk)) + { + + if (isRaidVolume(port, bus, target)) + { + printf("The device selected is part of a RAID Volume (PhysDisk %d)\n\n", physdisk); + printf("Do you want to directly access the PhysDisk? [Yes or No, default is No] "); + port->raidPassthru = getYesNoAnswer(0); + printf("\n"); + } + else + { + printf("The device selected is RAID PhysDisk %d\n\n", physdisk); + port->raidPassthru = 1; + } + port->raidBus = bus; + port->raidTarget = target; + port->raidPhysdisk = physdisk; + } + + if (pattern == 2) + { + if (doRead(port, bus, target, lun, lbn, lbns, 0, buf, n) != 1) + { + printf("Read failed\n\n"); + continue; + } + } + else if (pattern == 0) + { + memset(buf, 0x00, n); + } + else if (pattern == 1) + { + memset(buf, 0xff, n); + } + + if (doWrite(port, bus, target, lun, lbn, lbns, 0, buf, n) == 1) + { + printf("Write successful\n\n"); + } + else + { + printf("Write failed\n\n"); + } + + free(buf); + } + + return 1; +} + + +int +doVerifyLogicalBlocks(MPT_PORT *port) +{ + int bus; + int target; + int lun; + int physdisk; + U32 lbn; + int lbns; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("Logical block: [00000000-FFFFFFFF or RETURN to quit] "); + if (getHexNumberAnswer(&lbn) == 0) + return 1; + + printf("Number of logical blocks: [1-1024 or RETURN to quit] "); + lbns = getNumberAnswer(1, 1024, 0); + if (lbns == 0) + return 1; + + printf("\n"); + + if (isRaidPhysDisk(port, bus, target, &physdisk)) + { + + if (isRaidVolume(port, bus, target)) + { + printf("The device selected is part of a RAID Volume (PhysDisk %d)\n\n", physdisk); + printf("Do you want to directly access the PhysDisk? [Yes or No, default is No] "); + port->raidPassthru = getYesNoAnswer(0); + printf("\n"); + } + else + { + printf("The device selected is RAID PhysDisk %d\n\n", physdisk); + port->raidPassthru = 1; + } + port->raidBus = bus; + port->raidTarget = target; + port->raidPhysdisk = physdisk; + } + + if (doVerify(port, bus, target, lun, lbn, lbns, 0, NULL, 0) == 1) + { + printf("Verify successful\n\n"); + } + else + { + printf("Verify failed\n\n"); + } + } + + return 1; +} + + +int +doDiagnosticPageTest(MPT_PORT *port) +{ + int bus; + int target; + int lun; + int page; + unsigned char data[1024]; + int i; + int n; + int t; + int value; + int changed; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("Diagnostic Page: [00-FF or RETURN to quit] "); + page = getNumberAnswerHex(0x00, 0xff, -1); + if (page < 0) + return 1; + + printf("\n"); + + t = doReceiveDiagnosticResults(port, bus, target, lun, page, data, sizeof data); + n = get2bytes(data, 2) + 4; + + if (t == 1) + { + printf("%d bytes of Page %x Data returned\n\n", n, page); + + if (n > sizeof data) + { + printf("Too much data received, only %d bytes will be displayed\n\n", (int)sizeof data); + n = sizeof data; + + t = 0; + } + + displayByteData(data, n); + + if (t && (page == 0x02 || + page == 0x04 || + page == 0x0c || + page == 0x0e || + page == 0x0f || + page >= 0x10)) + { + printf("\nDo you want to make changes? [Yes or No, default is No] "); + if (getYesNoAnswer(0) == 1) + { + changed = FALSE; + + while (TRUE) + { + printf("\nEnter offset of value to change: [00-%02x or RETURN to quit] ", n - 1); + i = getNumberAnswerHex(0, n - 1, -1); + if (i < 0) + break; + + printf("Enter value: [00-FF or RETURN to not change] "); + value = getNumberAnswerHex(0x00, 0xff, -1); + if (value < 0) + continue; + + data[i] = (unsigned char)value; + + changed = TRUE; + + printf("\n"); + + displayByteData(data, n); + } + + if (changed == TRUE) + { + printf("\nDo you want to write your changes? [Yes or No, default is No] "); + if (getYesNoAnswer(0) == 1) + { + if (doSendDiagnostic(port, bus, target, lun, data, n) != 1) + { + printf("Send Diagnostic (Page %x) failed\n", page); + } + } + } + } + } + } + else + { + printf("Receive Diagnostic Results (Page %x) failed\n", page); + } + + printf("\n"); + } +} + + +int +doInjectRepairMediaError(MPT_PORT *port, int inject) +{ + int bus; + int target; + int lun; + int physdisk; + int sata; + U32 lbn; + unsigned char *buf; + int i; + int j; + int n; + int t; + int resid; + + buf = malloc(1024); + + while (TRUE) + { + port->raidPassthru = 0; + + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + break; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + break; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + break; + + printf("Logical block: [00000000-FFFFFFFF or RETURN to quit] "); + if (getHexNumberAnswer(&lbn) == 0) + break; + + if (isRaidPhysDisk(port, bus, target, &physdisk)) + { + printf("\nThe device selected is RAID PhysDisk %d\n", physdisk); + port->raidPassthru = 1; + port->raidBus = bus; + port->raidTarget = target; + port->raidPhysdisk = physdisk; + } + + /* first try using WRITE LONG(10) with the WR_UNCOR bit set. For SATA devices + * this should get translated to WRITE UNCORRECTABLE EXT + * If a SATA device supports WRITE UNCORRECTABLE EXT, then word 120, bit 2 of + * the IDENTIFY data should be set + */ + if (inject) + { + printf("Attempting error injection via WRITE LONG(10) / ATA WRITE UNCORRECTABLE EXT\n"); + if (doWriteLong(port, bus, target, lun, lbn, 0, NULL, 0, &resid) == 1 && resid == 0) + { + printf("\nWrite (inject) successful\n\n"); + continue; + } + } + + sata = isSata(port, bus, target); + + if (sata) + { + n = 1024; + + printf("Attempting error %s via SATA SCT / Long Sector Read/Write\n", inject ? "injection" : "repair"); + if (doReadLongSata(port, bus, target, lun, lbn, 0, buf, n) != 1) + { + if (inject) + { + printf("\nRead failed\n\n"); + continue; + } + printf("\nRead failed, can't preserve data\n"); + n = 0; + } + } + else + { + n = 512; + + if (doReadLong(port, bus, target, lun, lbn, 0, buf, n, &resid) != 1) + { + if (inject) + { + printf("\nRead failed\n\n"); + continue; + } + printf("\nRead failed, can't preserve data\n"); + n = 0; + } + else + { + n -= resid; + + printf("\nActual block size is %d bytes\n", n); + + if (doReadLong(port, bus, target, lun, lbn, 0, buf, n, &resid) != 1 || resid != 0) + { + if (inject) + { + printf("\nRead failed\n\n"); + continue; + } + printf("\nRead failed, can't preserve data\n"); + n = 0; + } + } + } + + for (i = 0, j = 0; i < n/4; i++, j++) + { + if ((i % 128) == 0) + printf("\n"); + + if (j == 0) + printf("%04x : ", i*4); + + printf("%08x ", get32x(((unsigned int *)buf)[i])); + + if (j == 7) + { + printf("\n"); + j = -1; + } + } + + if (j != 0) + printf("\n"); + + if (inject) + { + for (i = 512; i < n; i++) + if (buf[i]) + buf[i] = 0; + else + buf[i] = 1; + + if (sata) + { + t = doWriteLongSata(port, bus, target, lun, lbn, 0, buf, n); + } + else + { + t = doWriteLong(port, bus, target, lun, lbn, 0, buf, n, &resid) == 1 && resid == 0; + } + } + else + { + t = doWrite(port, bus, target, lun, lbn, 1, 0, buf, 512) == 1; + } + + if (t) + { + printf("\nWrite (%s) successful\n\n", inject ? "inject" : "repair"); + } + else + { + printf("Write (%s) failed\n\n", inject ? "inject" : "repair"); + } + } + + free(buf); + + return 1; +} + + +int +doSoftwareWriteProtect(MPT_PORT *port, int flag) +{ + int bus; + int target; + int lun; + unsigned char data[4+12]; + int n; + int t; + int offset = 4 + 4; + int bit = 3; + int mask; + char *mode = flag ? "set" : "clear"; + + mask = 1 << bit; + flag <<= bit; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("\n"); + + t = doModeSense(port, bus, target, lun, 0x0a, 1, 1, data, sizeof data); + n = data[0] + 1; + + if (t == 1 && n == sizeof data) + { + if (!(data[offset] & mask)) + { + printf("Software Write Protect is not changeable!\n\n"); + continue; + } + } + else + { + printf("Mode Sense (Changeable Control Mode Page) failed\n\n"); + continue; + } + + t = doModeSense(port, bus, target, lun, 0x0a, 0, 1, data, sizeof data); + n = data[0] + 1; + + if (t == 1 && n == sizeof data) + { + if ((data[offset] & mask) == flag) + { + printf("Software Write Protect is already %s\n\n", mode); + continue; + } + else + { + data[0] = 0; + data[1] = 0; + data[2] = 0; + + data[4] &= 0x3f; + + data[offset] &= ~mask; + data[offset] |= flag; + + if (doModeSelect(port, bus, target, lun, 0, data, sizeof data) != 1) + { + printf("Mode Select (Current Control Mode Page) failed\n\n"); + continue; + } + } + } + else + { + printf("Mode Sense (Current Control Mode Page) failed\n\n"); + continue; + } + + printf("Software Write Protect is now %s\n\n", mode); + } +} + + +int +doReadWriteCache(MPT_PORT *port, int flag) +{ + int bus; + int target; + int lun; + unsigned char data[4+20]; + int n; + int t; + int offset = 4 + 2; + int bit = (flag & 2) ? 2 : 0; + int mask; + char *type = (flag & 2) ? "Write" : "Read"; + char *mode = (flag & 1) ? "enabled" : "disabled"; + + flag &= 1; + + mask = 1 << bit; + flag <<= bit; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("\n"); + + t = doModeSense(port, bus, target, lun, 0x08, 1, 1, data, sizeof data); + n = data[0] + 1; + + if (t == 1 && n == sizeof data) + { + if (!(data[offset] & mask)) + { + printf("%s Cache is not changeable!\n\n", type); + continue; + } + } + else + { + printf("Mode Sense (Changeable Caching Mode Page) failed\n\n"); + continue; + } + + t = doModeSense(port, bus, target, lun, 0x08, 0, 1, data, sizeof data); + n = data[0] + 1; + + if (t == 1 && n == sizeof data) + { + if ((data[offset] & mask) == flag) + { + printf("%s Cache is already %s\n\n", type, mode); + continue; + } + else + { + data[0] = 0; + data[1] = 0; + data[2] = 0; + + data[4] &= 0x3f; + + data[offset] &= ~mask; + data[offset] |= flag; + + if (doModeSelect(port, bus, target, lun, 0, data, sizeof data) != 1) + { + printf("Mode Select (Current Caching Mode Page) failed\n\n"); + continue; + } + } + } + else + { + printf("Mode Sense (Current Caching Mode Page) failed\n\n"); + continue; + } + + printf("%s Cache is now %s\n\n", type, mode); + } +} + + +int +doDisplayPhyCounters(MPT_PORT *port) +{ + SasIOUnitPage0_t *SASIOUnitPage0; + Mpi2SasIOUnitPage0_t *SASIOUnitPage0_2; + SasIOUnit0PhyData *SASIOUnit0PhyData; + SasPhyPage1_t SASPhyPage1; + SasExpanderPage0_t SASExpanderPage0; + SasExpanderPage1_t SASExpanderPage1; + U32 handle; + int length; + int phy; + int rate; + int link_up; + uint64_t count1; + uint64_t count2; + uint64_t count3; + uint64_t count4; + char buf[32]; + unsigned char report_phy_error_log_req[12]; + unsigned char report_phy_error_log_rsp[28]; + + SASIOUnitPage0 = getConfigPageAlloc(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0, &length); + if (SASIOUnitPage0 == NULL) + return 0; + + SASIOUnitPage0_2 = (pMpi2SasIOUnitPage0_t)SASIOUnitPage0; + + for (phy = 0; phy < SASIOUnitPage0->NumPhys; phy++) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 1, phy, &SASPhyPage1, sizeof SASPhyPage1) == 1) + { + if (phy != 0) + printf("\n"); + + if (mpi2) + { + SASIOUnit0PhyData = (pSasIOUnit0PhyData)&SASIOUnitPage0_2->PhyData[phy]; + rate = (SASIOUnit0PhyData->NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL) >> + MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL; + } + else + { + SASIOUnit0PhyData = (pSasIOUnit0PhyData)&SASIOUnitPage0->PhyData[phy]; + rate = SASIOUnit0PhyData->NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL; + } + + link_up = rate == MPI_SAS_IOUNIT0_RATE_1_5 || + rate == MPI_SAS_IOUNIT0_RATE_3_0 || + rate == MPI2_SAS_NEG_LINK_RATE_6_0 || + rate == MPI25_SAS_NEG_LINK_RATE_12_0; + printf("Adapter Phy %d: Link %s", phy, link_up ? "Up" : "Down"); + count1 = get32(SASPhyPage1.InvalidDwordCount); + count2 = get32(SASPhyPage1.RunningDisparityErrorCount); + count3 = get32(SASPhyPage1.LossDwordSynchCount); + count4 = get32(SASPhyPage1.PhyResetProblemCount); + if (count1 || count2 || count3 || (link_up ? count4 : 0)) + { + printf("\n"); + format64bitDecimal(count1, buf, sizeof buf); + printf(" Invalid DWord Count %32s\n", buf); + format64bitDecimal(count2, buf, sizeof buf); + printf(" Running Disparity Error Count %32s\n", buf); + format64bitDecimal(count3, buf, sizeof buf); + printf(" Loss of DWord Synch Count %32s\n", buf); + format64bitDecimal(count4, buf, sizeof buf); + printf(" Phy Reset Problem Count %32s\n", buf); + } + else + { + printf(", No Errors\n"); + } + } + } + + handle = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, handle, + &SASExpanderPage0, sizeof SASExpanderPage0) != 1) + break; + + handle = get16(SASExpanderPage0.DevHandle); + + for (phy = 0; phy < SASExpanderPage0.NumPhys; phy++) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 1, + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM + <> + MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL; + else + rate = SASExpanderPage1.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL; + + link_up = rate == MPI_SAS_IOUNIT0_RATE_1_5 || + rate == MPI_SAS_IOUNIT0_RATE_3_0 || + rate == MPI2_SAS_NEG_LINK_RATE_6_0 || + rate == MPI25_SAS_NEG_LINK_RATE_12_0; + printf("Expander (Handle %04x) Phy %d: Link %s", handle, phy, link_up ? "Up" : "Down"); + count1 = get4bytes(report_phy_error_log_rsp, 12); + count2 = get4bytes(report_phy_error_log_rsp, 16); + count3 = get4bytes(report_phy_error_log_rsp, 20); + count4 = get4bytes(report_phy_error_log_rsp, 24); + if (count1 || count2 || count3 || (link_up ? count4 : 0)) + { + printf("\n"); + format64bitDecimal(count1, buf, sizeof buf); + printf(" Invalid DWord Count %32s\n", buf); + format64bitDecimal(count2, buf, sizeof buf); + printf(" Running Disparity Error Count %32s\n", buf); + format64bitDecimal(count3, buf, sizeof buf); + printf(" Loss of DWord Synch Count %32s\n", buf); + format64bitDecimal(count4, buf, sizeof buf); + printf(" Phy Reset Problem Count %32s\n", buf); + } + else + { + printf(", No Errors\n"); + } + } + else + { + printf("Report Phy Error Log failed\n"); + break; + } + } + } + + free(SASIOUnitPage0); + + return 1; +} + + +int +doClearPhyCounters(MPT_PORT *port) +{ + SasIoUnitControlRequest_t req; + SasIoUnitControlReply_t rep; + SasIOUnitPage0_t *SASIOUnitPage0; + SasExpanderPage0_t SASExpanderPage0; + SasExpanderPage1_t SASExpanderPage1; + U32 handle; + int length; + int phy; + unsigned char phy_control_req[40]; + unsigned char phy_control_rsp[4]; + + SASIOUnitPage0 = getConfigPageAlloc(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0, &length); + if (SASIOUnitPage0 == NULL) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; + req.Operation = MPI_SAS_OP_PHY_CLEAR_ERROR_LOG; + + for (phy = 0; phy < SASIOUnitPage0->NumPhys; phy++) + { + req.PhyNum = phy; + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME) != 1) + printf("Failed to clear phy %d counters!\n", phy); + else + printf("Adapter Phy %d counters have been cleared\n", phy); + } + + handle = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, handle, + &SASExpanderPage0, sizeof SASExpanderPage0) != 1) + break; + + handle = get16(SASExpanderPage0.DevHandle); + + for (phy = 0; phy < SASExpanderPage0.NumPhys; phy++) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 1, + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM + <maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + if (!isSata(port, bus, target)) + { + printf("\nCan't do Identify Device, device is not SATA!\n\n"); + continue; + } + +{ + SataPassthroughRequest_t req; + SataPassthroughReply_t rep; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SATA_PASSTHROUGH; + req.PassthroughFlags = set16(MPI_SATA_PT_REQ_PT_FLAGS_PIO | MPI_SATA_PT_REQ_PT_FLAGS_READ); + req.DataLength = set32(sizeof id); + req.CommandFIS[0] = 0x27; + req.CommandFIS[1] = 0x80; + req.CommandFIS[2] = 0xec; + + setName(port, bus, target, &req); + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + id, sizeof id, NULL, 0, SHORT_TIME) != 1) + { + printf("SataPassThrough failed!\n"); + t = 0; + } + + else + t = 1; +} + + if (t == 1) + { + printf("\n%d words of Identify Device Data returned\n\n", (int)(sizeof id / 2)); + + for (i = 0, j = 0; i < sizeof id; i++, j++) + { + if (j == 0) + printf("%3d : ", i / 2); + + if (i & 1) + printf("%02x ", id[i^1]); + else + printf("%02x", id[i^1]); + + if (!isprint(id[i^1])) + c[j] = ' '; + else + c[j] = id[i^1]; + + if (j == sizeof c - 2) + { + c[j+1] = 0; + printf(" %s\n", c); + j = -1; + } + } + + if (j != 0) + { + c[j] = 0; + for (i = j; i < sizeof c - 1; i++) + if (i & 1) + printf(" "); + else + printf(" "); + + printf(" %s\n", c); + } + } + else + { + printf("Identify Device failed\n"); + } + + printf("\n"); + } +} + + +int +doSataClearAffiliationTest(MPT_PORT *port) +{ + SasDevicePage0_t SASDevicePage0; + SasExpanderPage0_t SASExpanderPage0; + int bus; + int target; + int b_t; + int dev_handle; + int address; + int info; + int parent; + unsigned char report_phy_sata_req[12]; + unsigned char report_phy_sata_rsp[56]; + unsigned char phy_control_req[40]; + unsigned char phy_control_rsp[4]; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("\n"); + + if (mpi2) + { + if (mapBusTargetToDevHandle(port, bus, target, &dev_handle) != 1) + dev_handle = 0; + address = MPI2_SAS_DEVICE_PGAD_FORM_HANDLE + dev_handle; + } + else + { + b_t = (bus << 8) + target; + address = (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID + <maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + if (!isSata(port, bus, target)) + { + printf("\nCan't do SMART Read, device is not SATA!\n\n"); + continue; + } + +{ + SataPassthroughRequest_t req; + SataPassthroughReply_t rep; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SATA_PASSTHROUGH; + req.PassthroughFlags = set16(MPI_SATA_PT_REQ_PT_FLAGS_PIO | MPI_SATA_PT_REQ_PT_FLAGS_READ); + req.DataLength = set32(sizeof data); + req.CommandFIS[0] = 0x27; + req.CommandFIS[1] = 0x80; + req.CommandFIS[2] = 0xb0; + req.CommandFIS[3] = 0xd0; + req.CommandFIS[5] = 0x4f; + req.CommandFIS[6] = 0xc2; + + setName(port, bus, target, &req); + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + data, sizeof data, NULL, 0, SHORT_TIME) != 1) + { + printf("SataPassThrough failed!\n"); + t = 0; + } + + else + t = 1; +} + + if (t == 1) + { + printf("\n%d words of SMART Read Data returned\n\n", (int)(sizeof data / 2)); + + for (i = 0, j = 0; i < sizeof data; i++, j++) + { + if (j == 0) + printf("%3d : ", i / 2); + + if (i & 1) + printf("%02x ", data[i^1]); + else + printf("%02x", data[i^1]); + + if (!isprint(data[i^1])) + c[j] = ' '; + else + c[j] = data[i^1]; + + if (j == sizeof c - 2) + { + c[j+1] = 0; + printf(" %s\n", c); + j = -1; + } + } + + if (j != 0) + { + c[j+1] = 0; + for (i = j; i < sizeof c - 1; i++) + if (i & 1) + printf(" "); + else + printf(" "); + + printf(" %s\n", c); + } + } + else + { + printf("SMART Read failed\n"); + } + + printf("\n"); + } +} + + +int +doSepTest(MPT_PORT *port) +{ + SEPRequest_t req; + SEPReply_t rep; + int bus; + int target; + int handle; + int slot; + int flags = MPI_SEP_REQ_FLAGS_BUS_TARGETID_ADDRESS; + U32 status; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + printf("Use Enclosure/Slot, not Bus/Target, addressing? [Yes or No, default is Yes] "); + if (getYesNoAnswer(1) == 1) + { + flags = MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS; + } + } + + while (TRUE) + { + if (flags == MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS) + { + printf("Enclosure handle: [0000-FFFF or RETURN to quit] "); + handle = getNumberAnswerHex(0x0000, 0xffff, -1); + if (handle < 0) + return 1; + + printf("Slot: [0-255 or RETURN to quit] "); + slot = getNumberAnswer(0, 255, -1); + if (slot < 0) + return 1; + + bus = 0; + target = 0; + } + else + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + handle = 0; + slot = 0; + } + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; + req.Flags = flags; + req.EnclosureHandle = set16(handle); + req.Slot = set16(slot); + + setName(port, bus, target, &req); + + req.Action = MPI_SEP_REQ_ACTION_READ_STATUS; + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + { + printf("SCSI Enclosure Processor Read Status failed!\n"); + } + else + { + status = get32(rep.SlotStatus); + + printf("\nSlot Status = %08x\n", status); + + printf("\nDo you want to change the Slot Status? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) == 1) + { + printf("Enter value: [00000000-FFFFFFFF or RETURN to skip] "); + if (parseHexNumberChange(&status) == 1) + { + req.Action = MPI_SEP_REQ_ACTION_WRITE_STATUS; + req.SlotStatus = set32(status); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + { + printf("SCSI Enclosure Processor Write Status failed!\n"); + } + } + } + } + + printf("\n"); + } +} + + +int +doProdSpecSasIoUnitControl(MPT_PORT *port) +{ + SasIoUnitControlRequest_t req; + SasIoUnitControlReply_t rep; + int iocparameter; + U32 iocparametervalue; + int devhandle; + + if (mpi2) + { + return doProdSpecSasIoUnitControl2(port); + } + + while (TRUE) + { + printf("Enter IOC Parameter: [80-FF or RETURN to quit] "); + iocparameter = getNumberAnswerHex(0x80, 0xff, -1); + if (iocparameter < 0) + return 1; + + printf("Enter IOC Parameter: [00000000-FFFFFFFF or RETURN if not needed] "); + if (getHexNumberAnswer(&iocparametervalue) == 0) + iocparametervalue = 0; + + printf("Enter DevHandle: [0000-FFFF or RETURN if not needed] "); + devhandle = getNumberAnswerHex(0x0000, 0xffff, 0); + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; + req.Operation = MPI_SAS_OP_SET_IOC_PARAMETER; + req.IOCParameter = iocparameter; + req.IOCParameterValue = set32(iocparametervalue); + req.DevHandle = set16(devhandle); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + printf("Failed to issue product-specific SAS IO Unit Control request!\n"); + + printf("\n"); + } +} + + +int +doProdSpecSasIoUnitControl2(MPT_PORT *port) +{ + Mpi2SasIoUnitControlRequest_t req; + Mpi2SasIoUnitControlReply_t rep; + int iocparameter; + U32 iocparametervalue; + int devhandle; + + while (TRUE) + { + printf("Enter IOC Parameter: [80-FF or RETURN to quit] "); + iocparameter = getNumberAnswerHex(0x80, 0xff, -1); + if (iocparameter < 0) + return 1; + + printf("Enter IOC Parameter: [00000000-FFFFFFFF or RETURN if not needed] "); + if (getHexNumberAnswer(&iocparametervalue) == 0) + iocparametervalue = 0; + + printf("Enter DevHandle: [0000-FFFF or RETURN if not needed] "); + devhandle = getNumberAnswerHex(0x0000, 0xffff, 0); + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; + req.Operation = MPI2_SAS_OP_SET_IOC_PARAMETER; + req.IOCParameter = iocparameter; + req.IOCParameterValue = set32(iocparametervalue); + req.DevHandle = set16(devhandle); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + printf("Failed to issue product-specific SAS IO Unit Control request!\n"); + + printf("\n"); + } +} + + +int +doDiagDataUpload(MPT_PORT *port) +{ + ToolboxDiagDataUploadRequest_t req; + ToolboxReply_t rep; + U32 flags; + DiagDataUploadHeader_t *header; + unsigned char *buf; + int length; + FILE *file; + char name[256]; + int n; + int binary = 0; + int binfile; + int i; + int j; + + printf("Enter flags: [00000000-FFFFFFFF or RETURN if not needed] "); + if (getHexNumberAnswer(&flags) == 0) + flags = 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_TOOLBOX; + req.Tool = MPI_TOOLBOX_DIAG_DATA_UPLOAD_TOOL; + req.Flags = set32(flags); + + printf("\nUploading diagnostic data...\n"); + + length = 16384 + sizeof *header; + buf = malloc(length); + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf, length, NULL, 0, SHORT_TIME) != 1) + { + printf("Failed to upload diagnostic data!\n"); + return 0; + } + + header = (pDiagDataUploadHeader_t)buf; + length = get32(header->DiagDataLength); + + printf("%d bytes of data uploaded\n", length); + + if (length) + { + if (numFileNames) + { + n = getFileName(name, sizeof name, stdin, "output", 0); + } + else + { + printf("\nEnter output filename, or RETURN to send output to the screen: "); + n = getString(name, sizeof name, stdin); + } + if (n > 0) + { + if (gFlag == TRUE) + { + printf("File type: [0=ASCII, 1=Binary, default is 0] "); + binary = getNumberAnswer(0, 1, 0); + } + if (binary) + { + binfile = open(name, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + if (binfile < 0) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + if (write(binfile, buf, length)); + close(binfile); + return 1; + } + else + { + file = fopen(name, "w"); + if (file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + } + } + else + { + file = stdout; + printf("\n"); + } + + for (i = 0, j = 0; i < length/4; i++, j++) + { + if (j == 0) + fprintf(file, "%04x : ", i*4); + + fprintf(file, "%08x ", get32x(((unsigned int *)buf)[i])); + + if (j == 7) + { + fprintf(file, "\n"); + j = -1; + } + } + + if (j != 0) + fprintf(file, "\n"); + + if (file != stdout) + fclose(file); + } + + free(buf); + + return 1; +} + + +int +doReportLunsTest(MPT_PORT *port) +{ + int bus; + int target; + int len; + unsigned char *luns; + int i; + int n; + int t; + + len = 8 + 256 + 8; + luns = malloc(len); + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + break; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + break; + + printf("\n"); + + t = doReportLuns(port, bus, target, luns, len); + n = get4bytes(luns, 0) / 8; + + if (t == 1) + { + if (n > 256) + { + printf("%d LUNs reported for this device, only 256 LUNs will be displayed\n\n", n); + n = 256; + } + + printf("LUN List: "); + for (i = 0; i < n; i++) + { + printf(" %d", get2bytes(luns, (i + 1) * 8)); + } + printf("\n"); + } + else + { + printf("Report LUNs failed\n"); + } + + printf("\n"); + } + + free(luns); + + return 1; +} + + +int +doDriveFirmwareDownload(MPT_PORT *port) +{ + int bus; + int target; + int n; + char name[256]; + unsigned char *imageBuf = NULL; + int imageLen; + int size; + unsigned char *buf; + int len; + int offset; + int mode; + int id; + + if (selectDevice(port, &bus, &target) != 1) + return 0; + + n = getFileName(name, sizeof name, stdin, "drive firmware", 0); + if (n > 0) + { + if (readFile(name, &imageBuf, &imageLen) != 1) + return 0; + } + else + { + printf("Image won't be downloaded\n"); + return 1; + } + + mode = isSata(port, bus, target) ? 5 : 7; + printf("Mode: [0-31, default is %d] ", mode); + mode = getNumberAnswer(0, 31, mode); + + printf("BufferID: [0-255, default is 0] "); + id = getNumberAnswer(0, 255, 0); + + if (yesFlag == FALSE) + { + printf("\nDo you want to continue? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + { + free(imageBuf); + return 0; + } + } + + printf("\nDownloading image...\n"); + + buf = imageBuf; + len = imageLen; + offset = 0; + + while (len > 0) + { + if (mode == 5) + size = len; + else + size = min(len, 0x20000); + + if (doWriteBufferFull(port, bus, target, 0, mode, id, offset, buf, size) != 1) + { + printf("Download failed\n"); + if (wFlag) + fprintf(logFile, "%s: Drive Firmware Download (DRIVE_FW_DOWNLOAD): FAIL\n", + logPrefix(port)); + return 0; + } + + buf += size; + len -= size; + offset += size; + } + + printf("Download succeeded\n"); + if (wFlag) + fprintf(logFile, "%s: Drive Firmware Download (DRIVE_FW_DOWNLOAD) of size %x: PASS\n", + logPrefix(port), imageLen); + + free(imageBuf); + + return 1; +} + + +int +doSesDownloadMicrocode(MPT_PORT *port, int bus, int target, int lun, + int mode, int id, int offset, int size, unsigned char *buf, int len) +{ + unsigned char *data; + int n; + int t; + + n = ((len + 3) & ~3) + 24; + data = malloc(n); + t = n - 4; + + memset(data, 0, 24); + + data[0] = 0x0e; + data[2] = t >> 8; + data[3] = t; + data[8] = mode; + data[11] = id; + data[12] = offset >> 24; + data[13] = offset >> 16; + data[14] = offset >> 8; + data[15] = offset; + data[16] = size >> 24; + data[17] = size >> 16; + data[18] = size >> 8; + data[19] = size; + data[20] = len >> 24; + data[21] = len >> 16; + data[22] = len >> 8; + data[23] = len; + + memcpy(data + 24, buf, len); + + t = doSendDiagnostic(port, bus, target, lun, data, n); + + free(data); + + return t; +} + + +int +doExpanderChangeMfgDataFields(MPT_PORT *port) +{ + int bus; + int target; + int expanderType; + + if (selectExpander(port, &bus, &target, NULL, NULL, &expanderType) != 1) + return 0; + + if (bus == -1 && target == -1) + { + printf("Sorry, 'all' is not a valid selection for this operation\n"); + return 0; + } + + if (expanderType != EXPANDER_TYPE_LSI_GEN2_BOBCAT && + expanderType != EXPANDER_TYPE_LSI_GEN3_COBRA) + { + printf("This option is only supported on LSI SAS2/SAS3 expanders (Bobcat/Cobra).\n"); + return 0; + } + + return doExpanderGetSetMfgDataFields(port, bus, target, NULL, NULL, NULL); +} + + +/* fetch the expander SAS address, enclosure logical ID, and ethernet MAC address from + * the bobcat or cobra expander manufacturing data and return in sasAddr, enclLogId, and macAddr. + * If sasAddr, enclLogId, and macAddr are all NULL then interactively prompt for new + * addresses and program them into the expander's manufacturing data + */ +int +doExpanderGetSetMfgDataFields(MPT_PORT *port, int bus, int target, U64 *sasAddr, U64 *enclLogId, U8 *macAddr) +{ + unsigned char desc[4]; + unsigned char *imageBuf = NULL; + unsigned char *buf; + int imageLen; + int offset; + U16 pageId; + U16 pageLength; + U8 checksum8; + int i, x; + U64 sas_address; + U64 logical_id; + U8 mac_address[6]; + int mac_address_int[6]; + char mac_address_ascii[32]; + int prompt; + int enclIdPageOffset = 0; + int addrPageOffset = 0; + int etherPageOffset = 0; + int haveChange; + + if (!sasAddr && !enclLogId && !macAddr) + prompt = TRUE; + else + prompt = FALSE; + + haveChange = FALSE; + sas_address.High = 0; + sas_address.Low = 0; + logical_id.High = 0; + logical_id.Low = 0; + memset(mac_address, 0, sizeof mac_address); + + if (doReadBufferFull(port, bus, target, 0, 3, 1, 0, desc, sizeof desc) == 1) + { + imageLen = get3bytes(desc, 1); + } + else + { + printf("Can't read current manufacturing data, unknown buffer length.\n"); + return 0; + } + + imageBuf = (unsigned char *)malloc(imageLen); + + if (doReadBufferFull(port, bus, target, 0, 2, 1, 0, imageBuf, imageLen) == 1) + { + buf = imageBuf; + + offset = buf[3]; //get the start offset of the first config page from the region header + + if ( offset == 0xFF ) + { + printf("WARNING: The expander's manufacturing region does not appear to have valid data\n"); + free(imageBuf); + return 0; + } + + buf += offset; + while ( offset+8 < imageLen ) + { + checksum8 = 0; + pageLength = get16x(((U16 *)buf)[2]); + pageId = get16x(((U16 *)buf)[3]); + + if (pageLength == 0xFFFF && pageId == 0xFFFF) + break; + + for( i=0; i= 0x24) + { + if (checksum8 == buf[1]) + { + memcpy(mac_address, &buf[20], sizeof mac_address ); + etherPageOffset = offset; + } + else + { + printf("Found Ethernet config page, but checksum is invalid!\n"); + } + } + + // unit specific ethernet config page + if (pageId == 0xFE05 && pageLength == 0xC) + { + if (checksum8 == buf[1]) + { + memcpy(mac_address, &buf[8], sizeof mac_address ); + etherPageOffset = offset; + } + else + { + printf("Found unit specific Ethernet config page, but checksum is invalid!\n"); + } + } + + offset += pageLength + 4; + buf += pageLength + 4; + } + + if (prompt) + { + printf("Current SAS Address is %08x%08x\n", sas_address.High, sas_address.Low); + printf("Enter new SAS Address: [16 hex digits or RETURN to skip] "); + i = getHexDoubleNumberAnswer(&(sas_address.High), &(sas_address.Low)); + if (i != 0) + { + haveChange = TRUE; + buf = imageBuf + addrPageOffset; + checksum8 = 0; + pageLength = get16x(((U16 *)buf)[2]); +// displayByteData(buf, pageLength+4); + + ((U32 *)buf)[2] = set32x(sas_address.High); + ((U32 *)buf)[3] = set32x(sas_address.Low); + + for( i=0; i < pageLength; i++ ) + { + checksum8 += buf[i+4]; + } + buf[1] = checksum8; +// displayByteData(buf, pageLength+4); + } + printf("Current Enclosure Logical ID is %08x%08x\n", logical_id.High, logical_id.Low); + printf("Enter new Enclosure Logical ID: [16 hex digits or RETURN to skip] "); + i = getHexDoubleNumberAnswer(&(logical_id.High), &(logical_id.Low)); + if (i != 0) + { + haveChange = TRUE; + buf = imageBuf + enclIdPageOffset; + checksum8 = 0; + pageLength = get16x(((U16 *)buf)[2]); +// displayByteData(buf, pageLength+4); + + ((U32 *)buf)[2] = set32x(logical_id.High); + ((U32 *)buf)[3] = set32x(logical_id.Low); + + for( i=0; i < pageLength; i++ ) + { + checksum8 += buf[i+4]; + } + buf[1] = checksum8; +// displayByteData(buf, pageLength+4); + } + printf("Current Ethernet MAC Address is %02x-%02x-%02x-%02x-%02x-%02x\n", + mac_address[0],mac_address[1],mac_address[2], + mac_address[3],mac_address[4],mac_address[5]); + i = 0; + while ( TRUE ) + { + printf("Enter new MAC Address: [or RETURN to skip] "); + i = getStringFromArgs(mac_address_ascii, sizeof mac_address_ascii, stdin); + if (i == 0) + break; + + if ((sscanf(mac_address_ascii, "%x-%x-%x-%x-%x-%x", + &mac_address_int[0],&mac_address_int[1],&mac_address_int[2], + &mac_address_int[3],&mac_address_int[4],&mac_address_int[5]) == 6) && + mac_address_int[0] <= 0xFF && mac_address_int[1] <= 0xFF && + mac_address_int[2] <= 0xFF && mac_address_int[3] <= 0xFF && + mac_address_int[4] <= 0xFF && mac_address_int[5] <= 0xFF && + i <= 17) + { + for (x = 0; x < 6; x++) + mac_address[x] = mac_address_int[x]; + + break; + } + else + printf("Invalid MAC Address. Please enter a MAC Address in the form xx-xx-xx-xx-xx-xx\n"); + } + + if (i != 0) + { + haveChange = TRUE; + buf = imageBuf + etherPageOffset; + checksum8 = 0; + pageLength = get16x(((U16 *)buf)[2]); + pageId = get16x(((U16 *)buf)[3]); + +// displayByteData(buf, pageLength+4); + + if (pageId == 0xFF10) + memcpy(&buf[20], mac_address, sizeof mac_address); + else // pageId == 0xFE05 + memcpy(&buf[8], mac_address, sizeof mac_address); + + for( i=0; i < pageLength; i++ ) + { + checksum8 += buf[i+4]; + } + buf[1] = checksum8; +// displayByteData(buf, pageLength+4); + } + + if (haveChange) + { + if (yesFlag == FALSE) + { + printf("\nDo you want to continue? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + { + free(imageBuf); + return 0; + } + } + i = doWriteBufferFull(port, bus, target, 0, 2, 1, 0, imageBuf, imageLen); + } + else + i = 2; + + if (i == 1) + { + printf("\nWriting changes...Success!\n"); + } + else if (i == 2) + { + printf("\nNothing to do, no changes made.\n"); + } + else + { + printf("Writing changes failed\n"); + free(imageBuf); + return 0; + } + } + else + { + if (sasAddr) + *sasAddr = sas_address; + if (enclLogId) + *enclLogId = logical_id; + if (macAddr) + memcpy(macAddr, mac_address, sizeof mac_address); + } + + free(imageBuf); + return 1; + } + else + { + printf("Error reading manufacturing data from expander.\n"); + free(imageBuf); + return 0; + } +} + + +int +doExpanderFirmwareDownload(MPT_PORT *port) +{ + int bus; + int target; + int n; + int t; + char name[256]; + unsigned char *imageBuf = NULL; + int imageLen; + int size; + unsigned char *buf; + int len; + int offset; + int mode; + int id; + unsigned char *imageBufUpload = NULL; + int imageLenUpload; + MpiFwHeader_t *fwHeader; + U32 checksum32; + U8 checksum8; + int i, x; + int warn = 0; + int updateAll = FALSE; + int curr; + int expanderType; + int imageType; + int foundYeti; + int foundBobcat; + int foundCobra; + int foundOther; + int updateChoice; + int skip; + U64 currMfgSasAddr; + U64 currMfgEnclLogId; + U8 currMfgMACAddr[6]; + U64 newMfgSasAddr; + U64 newMfgEnclLogId; + U8 newMfgMACAddr[6]; + U64 mfgSasAddr; + U64 mfgEnclLogId; + U8 mfgMACAddr[6]; + U16 pageLength; + U16 pageId; + int enclIdPageOffset; + int addrPageOffset; + int etherPageOffset; + int choice; + int mac_address_int[6]; + char mac_address_ascii[32]; + + if (selectExpander(port, &bus, &target, NULL, NULL, &expanderType) != 1) + return 0; + + if (bus == -1 && target == -1) + updateAll = TRUE; + + if (updateAll) + { + curr = -1; + foundYeti = FALSE; + foundBobcat = FALSE; + foundCobra = FALSE; + foundOther = FALSE; + while (TRUE) + { + curr++; + + if (exp_targets[curr].bus == -1 && exp_targets[curr].target == -1) + break; + + if (exp_targets[curr].expanderType == EXPANDER_TYPE_LSI_GEN1_YETI) + foundYeti = TRUE; + else if (exp_targets[curr].expanderType == EXPANDER_TYPE_LSI_GEN2_BOBCAT) + foundBobcat = TRUE; + else if (exp_targets[curr].expanderType == EXPANDER_TYPE_LSI_GEN3_COBRA) + foundCobra = TRUE; + else + foundOther = TRUE; + } + + if (!foundYeti && !foundBobcat && !foundCobra) + { + printf("No supported LSI expanders found to update. The 'all' option to update all\n"); + printf("expanders is only supported for LSI SAS1 (Yeti) and SAS2 (Bobcat) expanders.\n"); + return 0; + } + + if (foundYeti + foundBobcat + foundCobra > 1) + { + printf("More than one type of LSI expander was found. Only one type can be updated.\n"); + printf("Which do you want to update? [0=SAS1 (Yeti), 1=SAS2 (Bobcat), 2=SAS3 (Cobra), default is 0] "); + updateChoice = getNumberAnswer(0, 2, 0); + if (updateChoice == 0) + expanderType = EXPANDER_TYPE_LSI_GEN1_YETI; + else if (updateChoice == 1) + expanderType = EXPANDER_TYPE_LSI_GEN2_BOBCAT; + else + expanderType = EXPANDER_TYPE_LSI_GEN3_COBRA; + } + else if (foundYeti) + expanderType = EXPANDER_TYPE_LSI_GEN1_YETI; + else if (foundBobcat) + expanderType = EXPANDER_TYPE_LSI_GEN2_BOBCAT; + else + expanderType = EXPANDER_TYPE_LSI_GEN3_COBRA; + + if (foundOther) + { + printf("The 'all' option to update all expanders is only supported for LSI SAS1 (Yeti)\n"); + printf("SAS2 (Bobcat), and SAS3 (Cobra) expanders. All other expanders will be ignored.\n"); + } + } + + n = getFileName(name, sizeof name, stdin, "expander firmware", 0); + if (n > 0) + { + if (readFile(name, &imageBuf, &imageLen) != 1) + return 0; + } + else + { + printf("Image won't be downloaded\n"); + return 1; + } + + printf("Mode: [0-31, default is 2] "); + mode = getNumberAnswer(0, 31, 2); + + printf("BufferID: [0-255, default is 2] "); + id = getNumberAnswer(0, 255, 2); + + if (id == 0 || id == 2 || + (id == 0xe2 && (expanderType == EXPANDER_TYPE_LSI_GEN2_BOBCAT || + expanderType == EXPANDER_TYPE_LSI_GEN3_COBRA))) + { + printWhatString("\nFirmware", imageBuf, imageLen); + + fwHeader = (pMpiFwHeader_t)imageBuf; + + if (get32(fwHeader->Signature0) == MPI_FW_HEADER_SIGNATURE_0 && + get32(fwHeader->Signature1) == MPI_FW_HEADER_SIGNATURE_1 && + get32(fwHeader->Signature2) == MPI_FW_HEADER_SIGNATURE_2) + { + imageType = EXPANDER_TYPE_LSI_GEN1_YETI; + } + else if (get32(fwHeader->Signature0) == BOBCAT_FW_HEADER_SIGNATURE_0 && + get32(fwHeader->Signature1) == BOBCAT_FW_HEADER_SIGNATURE_1 && + get32(fwHeader->Signature2) == BOBCAT_FW_HEADER_SIGNATURE_2) + { + imageType = EXPANDER_TYPE_LSI_GEN2_BOBCAT; + } + else if (get32(fwHeader->Signature0) == COBRA_FW_HEADER_SIGNATURE_0 && + get32(fwHeader->Signature1) == COBRA_FW_HEADER_SIGNATURE_1 && + get32(fwHeader->Signature2) == COBRA_FW_HEADER_SIGNATURE_2) + { + imageType = EXPANDER_TYPE_LSI_GEN3_COBRA; + } + else + { + if (!warn) + printf("\n"); + printf("Image's signature is not valid!\n"); + warn = 1; + imageType = EXPANDER_TYPE_UNKNOWN; + } + + checksum32 = 0; + for (i = 0; i < imageLen / 4; i++) + checksum32 += get32x(((U32 *)imageBuf)[i]); + + if (checksum32 != 0) + { + if (!warn) + printf("\n"); + printf("Image's checksum is invalid!\n"); + warn = 1; + } + + if (imageType != expanderType) + { + if (!warn) + printf("\n"); + printf("Image mismatch detected. The expander selected for updating is <%s>\n", printExpanderType(expanderType)); + printf("and the firmware image is for <%s>!\n", printExpanderType(imageType)); + warn = 1; + } + } + + if (id == 10) + { + int header_okay = 0; + int record_okay = 0; + + buf = imageBuf; + + if (buf[0] == 0x01 && buf[1] == 0x21 && buf[2] == 0x41 && buf[3] == 0x61) + { + header_okay = 1; + buf += 64; + } + + if (buf[0] == 'Y' && buf[1] == 'e' && buf[2] == 't' && buf[3] == 'i') + { + record_okay = 1; + } + + if (!record_okay) + { + if (!warn) + printf("\n"); + printf("Image's signature is not valid!\n"); + warn = 1; + } + else + { + if (mode == 2) + { + if (!header_okay) + { + printf("\nImage header not found, creating it...\n"); + + buf = malloc(imageLen + 64); + memset(buf, 0, 64); + buf[0] = 0x01; + buf[1] = 0x21; + buf[2] = 0x41; + buf[3] = 0x61; + memcpy(buf + 64, imageBuf, imageLen); + free(imageBuf); + + header_okay = 1; + + imageBuf = buf; + imageLen += 64; + } + } + + if (mode == 6 || mode == 7) + { + if (header_okay) + { + printf("\nImage header found, stripping it...\n"); + buf = malloc(imageLen - 64); + memcpy(buf, imageBuf + 64, imageLen - 64); + free(imageBuf); + + header_okay = 0; + + imageBuf = buf; + imageLen -= 64; + } + } + } + + t = header_okay ? 64 : 0; + + checksum8 = 0; + for (i = t; i < t + 220; i++) + checksum8 += imageBuf[i]; + + if (checksum8 != 0) + { + if (!warn) + printf("\n"); + printf("Image's checksum is invalid!\n"); + checksum8 = imageBuf[i-1] - checksum8; + printf(" At offset %04x, value %02x should be %02x\n", i-1, imageBuf[i-1], checksum8); + warn = 1; + } + } + + if ((expanderType == EXPANDER_TYPE_LSI_GEN2_BOBCAT || expanderType == EXPANDER_TYPE_LSI_GEN3_COBRA) && + (id == 1 || id == 0xE3)) + { + if (updateAll) + { + printf("Sorry, 'all' is not currently supported for updating LSI SAS2/SAS3 expander\n"); + printf("manufacturing data.\n"); + free(imageBuf); + return 0; + } + + if (imageBuf[2] != 0x10) + { + printf("This image does not appear to be a valid manufacturing image for an LSI SAS2/SAS3 expander!\n"); + warn = 1; + } + else + { + currMfgSasAddr.High = 0; + currMfgSasAddr.Low = 0; + currMfgEnclLogId.High = 0; + currMfgEnclLogId.Low = 0; + memset(currMfgMACAddr, 0, sizeof currMfgMACAddr); + + /* get the current SAS address, enclosure logical ID, and ethernet MAC address from the Bobcat or Cobra mfg data */ + doExpanderGetSetMfgDataFields(port, bus, target, &currMfgSasAddr, &currMfgEnclLogId, currMfgMACAddr); + newMfgSasAddr.High = 0; + newMfgSasAddr.Low = 0; + newMfgEnclLogId.High = 0; + newMfgEnclLogId.Low = 0; + memset(newMfgMACAddr, 0, sizeof newMfgMACAddr); + + buf = imageBuf; + offset = buf[3]; + buf += offset; + addrPageOffset = enclIdPageOffset = etherPageOffset = 0; + while ( offset+8 < imageLen ) + { + checksum8 = 0; + pageLength = get16x(((U16 *)buf)[2]); + pageId = get16x(((U16 *)buf)[3]); + + if (pageLength == 0xFFFF && pageId == 0xFFFF) + break; + if (pageLength == 0) + break; + + for( i=0; i < pageLength; i++ ) + { + checksum8 += buf[i+4]; + } + + //sas address config page + if (pageId == 0xFF00 && pageLength == 0xC) + { + if (checksum8 == buf[1]) + { + newMfgSasAddr.High = get32x(((U32 *)buf)[2]); + newMfgSasAddr.Low = get32x(((U32 *)buf)[3]); + addrPageOffset = offset; + } + else + { + printf("Found SAS address config page in image, but checksum is invalid!\n"); + } + } + + //unit specific sas address page + if (pageId == 0xFE00 && pageLength == 0xC) + { + if (checksum8 == buf[1]) + { + newMfgSasAddr.High = get32x(((U32 *)buf)[2]); + newMfgSasAddr.Low = get32x(((U32 *)buf)[3]); + addrPageOffset = offset; + } + else + { + printf("Found unit specific SAS address config page, but checksum is invalid!\n"); + } + } + + // report general config page + if (pageId == 0xFF02 && pageLength == 0xC) + { + if (checksum8 == buf[1]) + { + newMfgEnclLogId.High = get32x(((U32 *)buf)[2]); + newMfgEnclLogId.Low = get32x(((U32 *)buf)[3]); + enclIdPageOffset = offset; + } + else + { + printf("Found Report General config page in image, but checksum is invalid!\n"); + } + } + + // unit specific report general config page + if (pageId == 0xFE01 && pageLength == 0xC) + { + if (checksum8 == buf[1]) + { + newMfgEnclLogId.High = get32x(((U32 *)buf)[2]); + newMfgEnclLogId.Low = get32x(((U32 *)buf)[3]); + enclIdPageOffset = offset; + } + else + { + printf("Found unit specific Report General config page, but checksum is invalid!\n"); + } + } + + // ethernet config page + if (pageId == 0xFF10 && pageLength >= 0x24) + { + if (checksum8 == buf[1]) + { + memcpy(newMfgMACAddr, &buf[20], sizeof newMfgMACAddr); + etherPageOffset = offset; + } + else + { + printf("Found Ethernet config page in image, but checksum is invalid!\n"); + } + } + + // unit specific ethernet config page + if (pageId == 0xFE05 && pageLength == 0xC) + { + if (checksum8 == buf[1]) + { + memcpy(newMfgMACAddr, &buf[8], sizeof newMfgMACAddr); + etherPageOffset = offset; + } + else + { + printf("Found unit specific Ethernet config page, but checksum is invalid!\n"); + } + } + + offset += pageLength + 4; + buf += pageLength + 4; + } + + if (addrPageOffset) + { + printf("Current SAS Address programmed in expander mfg data is %08x%08x\n", + currMfgSasAddr.High, currMfgSasAddr.Low); + printf("New SAS Address in supplied mfg image is %08x%08x\n", + newMfgSasAddr.High, newMfgSasAddr.Low); + while (TRUE) + { + printf("Use which SAS Address? [1=from supplied image, 2=preserve existing, 3=override, default is 1] "); + choice = getNumberAnswer(1, 3, 1); + if (choice == 3) + { + printf("Enter SAS Address: [16 hex digits or RETURN to quit] "); + i = getHexDoubleNumberAnswer(&(mfgSasAddr.High), &(mfgSasAddr.Low)); + if (i == 0) + continue; + } + break; + } + if (choice == 2) + mfgSasAddr = currMfgSasAddr; + + if (choice == 2 || choice == 3) + { + buf = imageBuf + addrPageOffset; + checksum8 = 0; + pageLength = get16x(((U16 *)buf)[2]); +// displayByteData(buf, pageLength+4); + + ((U32 *)buf)[2] = set32x(mfgSasAddr.High); + ((U32 *)buf)[3] = set32x(mfgSasAddr.Low); + + for( i=0; i < pageLength; i++ ) + { + checksum8 += buf[i+4]; + } + buf[1] = checksum8; +// displayByteData(buf, pageLength+4); + } + } + else + { + printf("Unable to locate the SAS address config page in the image!\n"); + warn = 1; + } + + if (enclIdPageOffset) + { + printf("Current Enclosure Logical ID programmed in expander mfg data is %08x%08x\n", + currMfgEnclLogId.High, currMfgEnclLogId.Low); + printf("New Enclosure Logical ID in supplied mfg image is %08x%08x\n", + newMfgEnclLogId.High, newMfgEnclLogId.Low); + while (TRUE) + { + printf("Use which Enclosure Logical ID? [1=from supplied image, 2=preserve existing, 3=override, default is 1] "); + choice = getNumberAnswer(1, 3, 1); + if (choice == 3) + { + printf("Enter SAS Address: [16 hex digits or RETURN to quit] "); + i = getHexDoubleNumberAnswer(&(mfgEnclLogId.High), &(mfgEnclLogId.Low)); + if (i == 0) + continue; + } + break; + } + if (choice == 2) + mfgEnclLogId = currMfgEnclLogId; + + if (choice == 2 || choice == 3) + { + buf = imageBuf + enclIdPageOffset; + checksum8 = 0; + pageLength = get16x(((U16 *)buf)[2]); +// displayByteData(buf, pageLength+4); + + ((U32 *)buf)[2] = set32x(mfgEnclLogId.High); + ((U32 *)buf)[3] = set32x(mfgEnclLogId.Low); + + for( i=0; i < pageLength; i++ ) + { + checksum8 += buf[i+4]; + } + buf[1] = checksum8; +// displayByteData(buf, pageLength+4); + } + } + else + { + printf("Unable to locate the Report General config page in the image!\n"); + warn = 1; + } + + if (etherPageOffset) + { + printf("Current Ethernet MAC Address programmed in expander mfg data is %02x-%02x-%02x-%02x-%02x-%02x\n", + currMfgMACAddr[0], currMfgMACAddr[1], currMfgMACAddr[2], + currMfgMACAddr[3], currMfgMACAddr[4], currMfgMACAddr[5]); + printf("New Ethernet MAC Address in supplied mfg image is %02x-%02x-%02x-%02x-%02x-%02x\n", + newMfgMACAddr[0], newMfgMACAddr[1], newMfgMACAddr[2], + newMfgMACAddr[3], newMfgMACAddr[4], newMfgMACAddr[5]); + while (TRUE) + { + printf("Use which MAC Address? [1=from supplied image, 2=preserve existing, 3=override, default is 1] "); + choice = getNumberAnswer(1, 3, 1); + if (choice == 3) + { + while ( TRUE ) + { + printf("Enter new MAC Address: [or RETURN to quit] "); + i = getStringFromArgs(mac_address_ascii, sizeof mac_address_ascii, stdin); + if (i == 0) + break; + + if ((sscanf(mac_address_ascii, "%x-%x-%x-%x-%x-%x", + &mac_address_int[0],&mac_address_int[1],&mac_address_int[2], + &mac_address_int[3],&mac_address_int[4],&mac_address_int[5]) == 6) && + mac_address_int[0] <= 0xFF && mac_address_int[1] <= 0xFF && + mac_address_int[2] <= 0xFF && mac_address_int[3] <= 0xFF && + mac_address_int[4] <= 0xFF && mac_address_int[5] <= 0xFF && + i <= 17) + { + for (x = 0; x < 6; x++) + mfgMACAddr[x] = mac_address_int[x]; + + break; + } + else + printf("Invalid MAC Address. Please enter a MAC Address in the form xx-xx-xx-xx-xx-xx\n"); + } + if (i == 0) + continue; + } + break; + } + if (choice == 2) + memcpy(mfgMACAddr, currMfgMACAddr, sizeof mfgMACAddr); + + if (choice == 2 || choice == 3) + { + buf = imageBuf + etherPageOffset; + checksum8 = 0; + pageLength = get16x(((U16 *)buf)[2]); + pageId = get16x(((U16 *)buf)[3]); +// displayByteData(buf, pageLength+4); + + if (pageId == 0xFF10) + memcpy(&buf[20], mfgMACAddr, sizeof mfgMACAddr); + else // pageId == 0xFE05 + memcpy(&buf[8], mfgMACAddr, sizeof mfgMACAddr); + + for( i=0; i < pageLength; i++ ) + { + checksum8 += buf[i+4]; + } + buf[1] = checksum8; +// displayByteData(buf, pageLength+4); + } + } + else + { + printf("Unable to locate the Ethernet config page in the image!\n"); + warn = 1; + } + } + } + + if (warn && noFlag == TRUE) + { + free(imageBuf); + return 0; + } + + if (warn || yesFlag == FALSE) + { + if (warn) + printf("\nAre you sure you want to continue? [Yes or No, default is No] "); + else + printf("\nDo you want to continue? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + { + free(imageBuf); + return 0; + } + } + + curr = -1; + while (TRUE) + { + skip = FALSE; + if (updateAll) + { + curr++; + bus = exp_targets[curr].bus; + target = exp_targets[curr].target; + + if (bus == -1 && target == -1) + break; + + if (curr == 0) + printf("\n"); + + if (expanderType != exp_targets[curr].expanderType) + { + printf("Skipping image download to %d/%d...\n", bus, target); + skip = TRUE; + } + else + printf("Downloading image to %d/%d...\n", bus, target); + } + else + printf("\nDownloading image...\n"); + + if (skip) + len = 0; + else + len = imageLen; + + buf = imageBuf; + offset = 0; + + while (len > 0) + { + if (mode == 2 && (id == 0 || id == 2 || + (id == 0xe2 && (expanderType == EXPANDER_TYPE_LSI_GEN2_BOBCAT || + expanderType == EXPANDER_TYPE_LSI_GEN3_COBRA)))) + size = len; + else + size = min(len, CHUNK_SIZE); + + if (mode == 6 || mode == 7) + t = doSesDownloadMicrocode(port, bus, target, 0, mode, id, offset, imageLen, buf, size); + else + t = doWriteBufferFull(port, bus, target, 0, mode, id, offset, buf, size); + + if (t != 1) + { + printf("Download failed\n"); + return 0; + } + + buf += size; + len -= size; + offset += size; + + if (len > 0) + { + printf("."); + fflush(stdout); + } + else if (size != imageLen) + { + printf("\n"); + } + } + + if (!skip) + printf("Download succeeded\n"); + + if (!updateAll) + break; + } + + if (mode == 6 || mode == 7) + { + unsigned char data[24]; + int inProg; + + curr = -1; + while (TRUE) + { + skip = FALSE; + if (updateAll) + { + curr++; + bus = exp_targets[curr].bus; + target = exp_targets[curr].target; + + if (bus == -1 && target == -1) + break; + + if (expanderType != exp_targets[curr].expanderType) + skip = TRUE; + } + + inProg = FALSE; + while (!skip && TRUE) + { + if (doReceiveDiagnosticResults(port, bus, target, 0, 0x0e, data, sizeof data) == 1) + { + if (data[10] == mode + 10) + { + if (inProg) printf("\n"); + + if (updateAll) + printf("\nSES Download Microcode to %d/%d succeeded\n", bus, target); + else + printf("\nSES Download Microcode succeeded\n"); + + if (mode == 6) + printf("\nExpander will automatically reset itself\n"); + + break; + } + else + { + /* on some expander platforms 0x70 and 0x71 are used as interim statuses */ + if (((data[10] > 0) && (data[10] <= 3)) || data[10] == 0x70 || data[10] == 0x71) + { + if (!inProg) + { + if (updateAll) + printf("SES Download Microcode update to %d/%d in progress.", bus, target); + else + printf("SES Download Microcode update in progress."); + + inProg = TRUE; + } + else + { + printf("."); + fflush(stdout); + } + + sleep(1); + } + else + { + if ( inProg ) printf("\n"); + + if (updateAll) + printf("\nSES Download Microcode to %d/%d failed, status/additional status is %02x/%02x\n", + bus, target, data[10], data[11]); + else + printf("\nSES Download Microcode failed, status/additional status is %02x/%02x\n", + data[10], data[11]); + + break; + } + } + } + } + if (!updateAll) + break; + } + free(imageBuf); + + return 1; + } + + curr = -1; + while ( TRUE ) + { + skip = FALSE; + if (updateAll) + { + curr++; + bus = exp_targets[curr].bus; + target = exp_targets[curr].target; + + if (bus == -1 && target == -1) + break; + + if (expanderType != exp_targets[curr].expanderType) + skip = TRUE; + else + printf("\nVerifying download for %d/%d...\n", bus, target); + } + else + printf("\nVerifying download...\n"); + + imageLenUpload = CHUNK_SIZE; + imageBufUpload = (unsigned char *)malloc(imageLenUpload); + + if (skip) + len = 0; + else + len = imageLen; + + buf = imageBufUpload; + offset = 0; + + t = 1; + i = 1; + while (len > 0) + { + size = min(len, CHUNK_SIZE); + + if (doReadBufferFull(port, bus, target, 0, mode, id, offset, buf, size) != 1) + { + t = 0; + i = 0; + break; + } + + if (memcmp(imageBuf + offset, buf, size) != 0) + { + t = 0; + break; + } + + len -= size; + offset += size; + } + + if (!skip) + { + if (t == 1) + printf("Verification succeeded\n"); + else + { + if (offset == 0 && i == 0) + printf("Verification not supported!\n"); + else + printf("Verification failed!\n"); + } + } + + if (!updateAll) + break; + } + + free(imageBuf); + free(imageBufUpload); + + return 1; +} + + +int +doReadBufferFirmwareUpload(MPT_PORT *port) +{ + int bus; + int target; + unsigned char desc[4]; + int n; + int t; + char name[256]; + int file; + unsigned char *imageBuf = NULL; + int imageLen; + int length; + int offset; + int id; + + if (selectDevice(port, &bus, &target) != 1) + return 0; + + while (TRUE) + { + printf("\nBufferID: [0-255 or RETURN to quit] "); + id = getNumberAnswer(0, 255, -1); + if (id < 0) + return 1; + + if (doReadBufferFull(port, bus, target, 0, 3, id, 0, desc, sizeof desc) == 1) + { + length = get3bytes(desc, 1); + printf("Buffer length is %d\n", length); + } + else + { + length = 0; + printf("Buffer length is unknown\n"); + } + + n = getFileName(name, sizeof name, stdin, "output", 0); + if (n > 0) + { + file = open(name, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + if (file < 0) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + } + else + { + printf("Buffer won't be saved\n"); + return 1; + } + + imageLen = CHUNK_SIZE; + if (length) + if (imageLen > length) + imageLen = length; + imageBuf = (unsigned char *)malloc(imageLen); + + offset = 0; + while (TRUE) + { + if (doReadBufferFull(port, bus, target, 0, 2, id, offset, imageBuf, imageLen) != 1) + { + if (length) + break; + if (imageLen == 0x200) + break; + imageLen /= 2; + continue; + } + + t = write(file, imageBuf, imageLen); + if (t != imageLen) + { + printf("Write failed for file %s, t = %x\n", name, t); + perror("Error is"); + break; + } + + offset += imageLen; + if (length) + if (offset >= length) + break; + } + + printf("\nWrote %d bytes to file %s\n", offset, name); + + close(file); + + free(imageBuf); + } + + return 1; +} + + +int +doRaidActions(MPT_PORT *port, int command) +{ + IOCPage2_t *IOCPage2; + IOCPage3_t *IOCPage3; + int length; + + if (bringOnline(port) != 1) + return 0; + + if (mpi2) + return doRaidActions2(port, command); + + IOCPage2 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_IOC, 2, 0, &length); + if (IOCPage2 == NULL || IOCPage2->MaxVolumes == 0) + { + printf("RAID is not supported on this port\n"); + if (IOCPage2) + free(IOCPage2); + return 0; + } + + IOCPage3 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_IOC, 3, 0, &length); + if (IOCPage3 == NULL) + { + printf("RAID is not supported on this port\n"); + free(IOCPage2); + return 0; + } + + switch (command) + { + case 1: + doShowVolumes(port, IOCPage2, IOCPage3); + break; + case 2: + doShowPhysDisks(port, IOCPage2, IOCPage3); + break; + case 3: + doGetVolumeState(port, IOCPage2); + break; + case 4: + doWaitForResync(port, IOCPage2); + break; + case 10: + doModifyVolume(port, IOCPage2, MPI_RAID_ACTION_DISABLE_VOLUME, "disabled"); + break; + case 11: + doModifyVolume(port, IOCPage2, MPI_RAID_ACTION_ENABLE_VOLUME, "enabled"); + break; + case 12: + doModifyVolume(port, IOCPage2, MPI_RAID_ACTION_INACTIVATE_VOLUME, "inactivated"); + break; + case 13: + doModifyVolume(port, IOCPage2, MPI_RAID_ACTION_ACTIVATE_VOLUME, "activated"); + break; + case 20: + doModifyPhysDisk(port, IOCPage2, IOCPage3, MPI_RAID_ACTION_PHYSDISK_OFFLINE, "offlined"); + break; + case 21: + doModifyPhysDisk(port, IOCPage2, IOCPage3, MPI_RAID_ACTION_PHYSDISK_ONLINE, "onlined"); + break; + case 22: + doModifyPhysDisk(port, IOCPage2, IOCPage3, MPI_RAID_ACTION_FAIL_PHYSDISK, "failed"); + break; + case 23: + doModifyPhysDisk(port, IOCPage2, IOCPage3, MPI_RAID_ACTION_REPLACE_PHYSDISK, "replaced"); + break; + case 24: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doModifyPhysDisk(port, IOCPage2, IOCPage3, MPI_RAID_ACTION_QUIESCE_PHYS_IO, "quiesced"); + } + else + { + printf("Invalid selection!\n"); + } + break; + case 25: + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + doModifyPhysDisk(port, IOCPage2, IOCPage3, MPI_RAID_ACTION_ENABLE_PHYS_IO, "unquiesced"); + } + else + { + printf("Invalid selection!\n"); + } + break; + case 26: + doDriveFirmwareUpdateMode(port, IOCPage2, IOCPage3, 0); + break; + case 27: + doDriveFirmwareUpdateMode(port, IOCPage2, IOCPage3, 1); + break; + case 30: + doCreateVolume(port, IOCPage2, IOCPage3); + break; + case 31: + doDeleteVolume(port, IOCPage2); + break; + case 32: + doVolumeSettings(port, IOCPage2); + break; + case 33: + doVolumeName(port, IOCPage2); + break; + case 40: + doCreatePhysDisk(port, IOCPage2); + break; + case 41: + doModifyPhysDisk(port, IOCPage2, IOCPage3, MPI_RAID_ACTION_DELETE_PHYSDISK, "deleted"); + break; + case 42: + doPhysDiskSettings(port, IOCPage2, IOCPage3); + break; + case 50: + doCreateHotSpare(port, IOCPage2, IOCPage3); + break; + case 51: + doDeleteHotSpare(port, IOCPage2, IOCPage3); + break; + default: + printf("Invalid selection!\n"); + break; + } + + free(IOCPage2); + free(IOCPage3); + +#if DOS || EFI + // give the firmware a chance to update the volume metadata + sleep(5); +#endif + + return 1; +} + + +int +selectVolume(MPT_PORT *port, IOCPage2_t *IOCPage2, int *volumeOut) +{ + int volume; + int i; + + if (IOCPage2->NumActiveVolumes == 0) + { + printf("No active volumes\n"); + return 0; + } + + for (i = 0; i < IOCPage2->NumActiveVolumes; i++) + { + printf("Volume %d is Bus %d Target %d, Type %s%s\n", + i, IOCPage2->RaidVolume[i].VolumeBus, IOCPage2->RaidVolume[i].VolumeID, + IOCPage2->RaidVolume[i].VolumeType == MPI_RAID_VOL_TYPE_IS ? "IS (Integrated Striping)" : + IOCPage2->RaidVolume[i].VolumeType == MPI_RAID_VOL_TYPE_IME ? "IME (Integrated Mirroring Extended)" : + IOCPage2->RaidVolume[i].VolumeType == MPI_RAID_VOL_TYPE_IM ? "IM (Integrated Mirroring)" : "Unknown", + IOCPage2->RaidVolume[i].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ? ", inactive" : ""); + } + printf("\n"); + + if (IOCPage2->NumActiveVolumes > 1 || gFlag == TRUE) + { + printf("Volume: [0-%d or RETURN to quit] ", IOCPage2->NumActiveVolumes - 1); + volume = getNumberAnswer(0, IOCPage2->NumActiveVolumes - 1, -1); + if (volume < 0) + return 0; + printf("\n"); + } + else + { + volume = 0; + } + + *volumeOut = volume; + + return 1; +} + + +int +doShowVolumes(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3) +{ + RaidVolumePage0_t *RaidVolumePage0; + RaidVolumePage1_t RaidVolumePage1; + int b_t; + int i; + int j; + int k; + int nv; + int nd; + int t1; + int t2; + int length; + + nv = IOCPage2->NumActiveVolumes; + nd = IOCPage3->NumPhysDisks; + printf("%d volume%s active, %d physical disk%s active\n", + nv, nv == 1 ? " is" : "s are", nd, nd == 1 ? " is" : "s are"); + + for (i = 0; i < nv; i++) + { + printf("\nVolume %d is Bus %d Target %d, Type %s%s\n", + i, IOCPage2->RaidVolume[i].VolumeBus, IOCPage2->RaidVolume[i].VolumeID, + IOCPage2->RaidVolume[i].VolumeType == MPI_RAID_VOL_TYPE_IS ? "IS (Integrated Striping)" : + IOCPage2->RaidVolume[i].VolumeType == MPI_RAID_VOL_TYPE_IME ? "IME (Integrated Mirroring Extended)" : + IOCPage2->RaidVolume[i].VolumeType == MPI_RAID_VOL_TYPE_IM ? "IM (Integrated Mirroring)" : "Unknown", + IOCPage2->RaidVolume[i].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ? ", inactive" : ""); + + if (IOCPage2->RaidVolume[i].VolumePageNumber == 0) + { + b_t = (IOCPage2->RaidVolume[i].VolumeBus << 8) + IOCPage2->RaidVolume[i].VolumeID; + + RaidVolumePage0 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0, b_t, &length); + if (RaidVolumePage0 == NULL) + continue; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 1, b_t, + &RaidVolumePage1, sizeof RaidVolumePage1) == 1) + { + printf(" Volume Name: %-32s\n", + RaidVolumePage1.Name); + printf(" Volume WWID: %08x%08x\n", + get32(RaidVolumePage1.WWID.High), get32(RaidVolumePage1.WWID.Low)); + } + + t1 = RaidVolumePage0->VolumeStatus.State; + t2 = RaidVolumePage0->VolumeStatus.Flags; + printf(" Volume State: %s%s%s%s%s\n", + t1 == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL ? "optimal" : + t1 == MPI_RAIDVOL0_STATUS_STATE_DEGRADED ? "degraded" : + t1 == MPI_RAIDVOL0_STATUS_STATE_FAILED ? "failed" : + t1 == MPI_RAIDVOL0_STATUS_STATE_MISSING ? "missing" : "unknown", + t2 & MPI_RAIDVOL0_STATUS_FLAG_ENABLED ? ", enabled" : ", disabled", + t2 & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED ? ", quiesced" : "", + t2 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ? ", resync in progress" : "", + t2 & MPI_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL ? ", bad block table full" : ""); + + t1 = get16(RaidVolumePage0->VolumeSettings.Settings); + t2 = RaidVolumePage0->VolumeSettings.HotSparePool; + printf(" Volume Settings: write caching %s%s%s%s\n", + t1 & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE ? "enabled" : "disabled", + t1 & MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART ? ", offline on SMART data" : "", + t1 & MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE ? ", auto configure" : "", + t1 & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC ? ", priority resync" : ""); + if (t2 != 0) + printf(" Volume draws from Hot Spare Pools: %s%s%s%s%s%s%s%s\n", + t2 & MPI_RAID_HOT_SPARE_POOL_0 ? " 0" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_1 ? " 1" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_2 ? " 2" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_3 ? " 3" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_4 ? " 4" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_5 ? " 5" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_6 ? " 6" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_7 ? " 7" : ""); + + if (IOCPage2->RaidVolume[i].VolumeType == MPI_RAID_VOL_TYPE_IM) + printf(" Volume Size %" INT64_FMT "d MB, %d Members\n", + (get64(RaidVolumePage0->MaxLBA) + 1) / 2048, RaidVolumePage0->NumPhysDisks); + else + printf(" Volume Size %" INT64_FMT "d MB, Stripe Size %d KB, %d Members\n", + (get64(RaidVolumePage0->MaxLBA) + 1) / 2048, get32(RaidVolumePage0->StripeSize) / 2, + RaidVolumePage0->NumPhysDisks); + + for (j = 0; j < RaidVolumePage0->NumPhysDisks; j++) + { + for (k = 0; k < nd; k++) + { + if (IOCPage3->PhysDisk[k].PhysDiskNum == RaidVolumePage0->PhysDisk[j].PhysDiskNum) + { + if (IOCPage2->RaidVolume[i].VolumeType == MPI_RAID_VOL_TYPE_IM) + printf(" %s is PhysDisk %d (Bus %d Target %d)\n", + RaidVolumePage0->PhysDisk[j].PhysDiskMap == MPI_RAIDVOL0_PHYSDISK_PRIMARY ? "Primary" : + RaidVolumePage0->PhysDisk[j].PhysDiskMap == MPI_RAIDVOL0_PHYSDISK_SECONDARY ? "Secondary" : + "Member", RaidVolumePage0->PhysDisk[j].PhysDiskNum, + IOCPage3->PhysDisk[k].PhysDiskBus, IOCPage3->PhysDisk[k].PhysDiskID); + else + printf(" Member %d is PhysDisk %d (Bus %d Target %d)\n", + RaidVolumePage0->PhysDisk[j].PhysDiskMap, RaidVolumePage0->PhysDisk[j].PhysDiskNum, + IOCPage3->PhysDisk[k].PhysDiskBus, IOCPage3->PhysDisk[k].PhysDiskID); + break; + } + } + if (k < nd) + continue; + + if (IOCPage2->RaidVolume[i].VolumeType == MPI_RAID_VOL_TYPE_IM) + printf(" %s is PhysDisk %d\n", + RaidVolumePage0->PhysDisk[j].PhysDiskMap == MPI_RAIDVOL0_PHYSDISK_PRIMARY ? "Primary" : + RaidVolumePage0->PhysDisk[j].PhysDiskMap == MPI_RAIDVOL0_PHYSDISK_SECONDARY ? "Secondary" : + "Member", RaidVolumePage0->PhysDisk[j].PhysDiskNum); + else + printf(" Member %d is PhysDisk %d\n", + RaidVolumePage0->PhysDisk[j].PhysDiskMap, RaidVolumePage0->PhysDisk[j].PhysDiskNum); + } + + free(RaidVolumePage0); + } + } + + return 1; +} + + +int +doShowPhysDisks(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3) +{ + RaidPhysDiskPage0_t RaidPhysDiskPage0; + RaidPhysDiskPage1_t *RaidPhysDiskPage1; + int i; + int j; + int physdisk; + int nv; + int nd; + int np; + int t1; + int t2; + int length; + + nv = IOCPage2->NumActiveVolumes; + nd = IOCPage3->NumPhysDisks; + if (nd == 0 && nv) + { + nv = IOCPage2->MaxVolumes; + nd = IOCPage2->MaxPhysDisks; + printf("%d volume%s defined, %d physical disk%s possible\n", + nv, nv == 1 ? " is" : "s are", nd, nd == 1 ? " is" : "s are"); + } + else + { + printf("%d volume%s active, %d physical disk%s active\n", + nv, nv == 1 ? " is" : "s are", nd, nd == 1 ? " is" : "s are"); + } + + for (i = 0; i < nd; i++) + { + if (IOCPage3->NumPhysDisks) + physdisk = IOCPage3->PhysDisk[i].PhysDiskNum; + else + physdisk = i; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, physdisk, + &RaidPhysDiskPage0, sizeof RaidPhysDiskPage0) != 1) + continue; + + printf("\nPhysDisk %d is Bus %d Target %d\n", + physdisk, RaidPhysDiskPage0.PhysDiskBus, RaidPhysDiskPage0.PhysDiskID); + + t1 = RaidPhysDiskPage0.PhysDiskStatus.State; + t2 = RaidPhysDiskPage0.PhysDiskStatus.Flags; + printf(" PhysDisk State: %s%s%s%s\n", + t1 == MPI_PHYSDISK0_STATUS_ONLINE ? "online" : + t1 == MPI_PHYSDISK0_STATUS_MISSING ? "missing" : + t1 == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE ? "not compatible" : + t1 == MPI_PHYSDISK0_STATUS_FAILED ? "failed" : + t1 == MPI_PHYSDISK0_STATUS_INITIALIZING ? "initializing" : + t1 == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED ? "offline requested" : + t1 == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED ? "failed requested" : + t1 == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE ? "offline" : "unknown", + t2 & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC ? ", out of sync" : "", + t2 & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED ? ", quiesced" : "", + t2 & MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME ? ", inactive volume" : ""); + + t1 = RaidPhysDiskPage0.PhysDiskSettings.PhysDiskSettings; + t2 = RaidPhysDiskPage0.PhysDiskSettings.HotSparePool; +// printf(" PhysDisk Settings: \n"); + if (t2 != 0) + printf(" PhysDisk belongs to Hot Spare Pools: %s%s%s%s%s%s%s%s\n", + t2 & MPI_RAID_HOT_SPARE_POOL_0 ? " 0" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_1 ? " 1" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_2 ? " 2" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_3 ? " 3" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_4 ? " 4" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_5 ? " 5" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_6 ? " 6" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_7 ? " 7" : ""); + + printf(" PhysDisk Size %d MB, Inquiry Data: %-8.8s %-16.16s %-4.4s\n", + (get32(RaidPhysDiskPage0.MaxLBA) + 1) / 2048, RaidPhysDiskPage0.InquiryData.VendorID, + RaidPhysDiskPage0.InquiryData.ProductID, RaidPhysDiskPage0.InquiryData.ProductRevLevel); + + t1 = get16(RaidPhysDiskPage0.ErrorData.ErrorCount); + t2 = get16(RaidPhysDiskPage0.ErrorData.SmartCount); + if (t1 != 0) + printf(" Error Count %d, Last Error: Command = %02Xh, Key = %d, ASC/ASCQ = %02Xh/%02Xh\n", + t1, RaidPhysDiskPage0.ErrorData.ErrorCdbByte, + RaidPhysDiskPage0.ErrorData.ErrorSenseKey, + RaidPhysDiskPage0.ErrorData.ErrorASC, RaidPhysDiskPage0.ErrorData.ErrorASCQ); + if (t2 != 0) + printf(" SMART Data Count %d, Last SMART Data: ASC/ASCQ = %02Xh/%02Xh\n", + t2, RaidPhysDiskPage0.ErrorData.SmartASC, RaidPhysDiskPage0.ErrorData.SmartASCQ); + + if (RaidPhysDiskPage0.PhysDiskStatus.Flags & MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) + continue; + + RaidPhysDiskPage1 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 1, physdisk, &length); + if (RaidPhysDiskPage1 == NULL) + continue; + + np = RaidPhysDiskPage1->NumPhysDiskPaths; + + if (np > 1) + { + for (j = 0; j < np; j++) + { + t1 = get16(RaidPhysDiskPage1->Path[j].Flags); + printf(" Path %d is Bus %d Target %d, %s\n", j, + RaidPhysDiskPage1->Path[j].PhysDiskBus, + RaidPhysDiskPage1->Path[j].PhysDiskID, + t1 & MPI_RAID_PHYSDISK1_FLAG_INVALID ? "invalid" : + t1 & MPI_RAID_PHYSDISK1_FLAG_BROKEN ? "broken" : + "online"); + } + } + + free(RaidPhysDiskPage1); + } + + return 1; +} + + +int +doGetVolumeState(MPT_PORT *port, IOCPage2_t *IOCPage2) +{ + MpiRaidActionRequest_t req; + struct + { + MpiRaidActionReply_t rep; + MpiRaidVolIndicator_t data; + } rep; + MpiRaidVolIndicator_t *data; + RaidVol0Status_t *status; + int volume; + uint64_t size; + uint64_t done; + int t1; + int t2; + + if (selectVolume(port, IOCPage2, &volume) != 1) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_INDICATOR_STRUCT; + req.VolumeBus = IOCPage2->RaidVolume[volume].VolumeBus; + req.VolumeID = IOCPage2->RaidVolume[volume].VolumeID; + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME) == 1) + { + data = (pMpiRaidVolIndicator_t)&rep.rep.ActionData; + status = (pRaidVol0Status_t)&rep.rep.VolumeStatus; + + t1 = status->State; + t2 = status->Flags; + printf("Volume %d State: %s%s%s%s\n", volume, + t1 == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL ? "optimal" : + t1 == MPI_RAIDVOL0_STATUS_STATE_DEGRADED ? "degraded" : + t1 == MPI_RAIDVOL0_STATUS_STATE_FAILED ? "failed" : "unknown", + t2 & MPI_RAIDVOL0_STATUS_FLAG_ENABLED ? ", enabled" : ", disabled", + t2 & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED ? ", quiesced" : "", + t2 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ? ", resync in progress" : ""); + + if (t2 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) + { + size = get64(data->TotalBlocks); + done = get64(data->BlocksRemaining); + + if (size) + { + printf("Resync Progress: total blocks %" INT64_FMT "d, blocks remaining %" INT64_FMT "d, %d%%\n", + size, done, (int)(done / (size / 100))); + } + } + } + + return 1; +} + + +int +doWaitForResync(MPT_PORT *port, IOCPage2_t *IOCPage2) +{ + MpiRaidActionRequest_t req; + struct + { + MpiRaidActionReply_t rep; + MpiRaidVolIndicator_t data; + } rep; + MpiRaidVolIndicator_t *data; + RaidVol0Status_t *status; + int volume; + uint64_t size; + uint64_t done; + int t1; + int t2; + int percent; + int last_percent = -1; + int n; + + if (selectVolume(port, IOCPage2, &volume) != 1) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_INDICATOR_STRUCT; + req.VolumeBus = IOCPage2->RaidVolume[volume].VolumeBus; + req.VolumeID = IOCPage2->RaidVolume[volume].VolumeID; + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + return 0; + + data = (pMpiRaidVolIndicator_t)&rep.rep.ActionData; + status = (pRaidVol0Status_t)&rep.rep.VolumeStatus; + + t1 = status->State; + t2 = status->Flags; + printf("Volume %d State: %s%s%s%s\n", volume, + t1 == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL ? "optimal" : + t1 == MPI_RAIDVOL0_STATUS_STATE_DEGRADED ? "degraded" : + t1 == MPI_RAIDVOL0_STATUS_STATE_FAILED ? "failed" : "unknown", + t2 & MPI_RAIDVOL0_STATUS_FLAG_ENABLED ? ", enabled" : ", disabled", + t2 & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED ? ", quiesced" : "", + t2 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ? ", resync in progress" : ""); + + if (t2 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) + { + size = get64(data->TotalBlocks); + done = get64(data->BlocksRemaining); + + if (size) + { + last_percent = (int)(done / (size / 100)); + printf("Resync Progress: total blocks %" INT64_FMT "d, blocks remaining %" INT64_FMT "d, %d%%\n", + size, done, last_percent); + } + } + else + return 1; + + n = 0; + while (TRUE) + { + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + return 0; + + data = (pMpiRaidVolIndicator_t)&rep.rep.ActionData; + status = (pRaidVol0Status_t)&rep.rep.VolumeStatus; + + t1 = status->State; + t2 = status->Flags; + + if (t2 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) + { + size = get64(data->TotalBlocks); + done = get64(data->BlocksRemaining); + + if (size) + { + percent = (int)(done / (size / 100)); + if (percent != last_percent) + { + last_percent = percent; + n += printf(" %d%%", last_percent); + if (n >= 75) + { + printf("\n"); + n = 0; + } + } + } + } + else + break; + + sleep(1); + } + if (n) + printf("\n"); + + printf("Volume %d State: %s%s%s%s\n", volume, + t1 == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL ? "optimal" : + t1 == MPI_RAIDVOL0_STATUS_STATE_DEGRADED ? "degraded" : + t1 == MPI_RAIDVOL0_STATUS_STATE_FAILED ? "failed" : "unknown", + t2 & MPI_RAIDVOL0_STATUS_FLAG_ENABLED ? ", enabled" : ", disabled", + t2 & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED ? ", quiesced" : "", + t2 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ? ", resync in progress" : ""); + + return 1; +} + + +int +doModifyVolume(MPT_PORT *port, IOCPage2_t *IOCPage2, int action, char *string) +{ + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + int volume; + int all; + + if (IOCPage2->NumActiveVolumes == 0) + { + printf("No active volumes\n"); + return 1; + } + + if (action == MPI_RAID_ACTION_DISABLE_VOLUME || + action == MPI_RAID_ACTION_ENABLE_VOLUME) + { + all = 1; + volume = 0; + } + else + { + all = 0; + if (selectVolume(port, IOCPage2, &volume) != 1) + return 0; + } + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = action; + req.VolumeBus = IOCPage2->RaidVolume[volume].VolumeBus; + req.VolumeID = IOCPage2->RaidVolume[volume].VolumeID; + + if (all) + printf("Volumes are being %s\n", string); + else + printf("Volume %d is being %s\n", volume, string); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doCreateVolume(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3) +{ + RaidVolumePage0_t *RaidVolumePage0; + RaidPhysDiskPage0_t RaidPhysDiskPage0; + ManufacturingPage4_t ManufacturingPage4; + IOCPage6_t IOCPage6; + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + ConfigReply_t config_rep; + int bus; + int target; + PATH path; + int no_mix_sas_sata; + int no_mix_ssd_non_ssd; + int sata = 0; + int ssd = 0; + int num_physdisks; + int physdisks[MAX_DEVICES]; + int chosen[MAX_DEVICES]; + unsigned char inq[36]; + unsigned char cap[8]; + unsigned int size; + unsigned int metadata_size = 0; + unsigned int coerced_size; + unsigned int min_size = 0; + uint64_t volume_size; + uint64_t max_volume_size; + uint64_t max_lba; + int first_bus = 0; + int first_target = 0; + int length; + int i; + int n; + int t; + int settings = 0; + int flags; + int min_disks; + int stripe_map = 0; + int min_stripe; + int max_stripe; + int def_stripe; + + if (IOCPage2->NumActiveVolumes >= IOCPage2->MaxVolumes) + { + printf("Cannot create another active volume\n"); + return 0; + } + + if (IOCPage3->NumPhysDisks + 2 > IOCPage2->MaxPhysDisks) + { + printf("Cannot create at least 2 physical disks\n"); + return 0; + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 6, 0, &IOCPage6, sizeof IOCPage6) != 1) + { + memset(&IOCPage6, 0, sizeof IOCPage6); + IOCPage6.MinDrivesIS = 2; + IOCPage6.MinDrivesIM = 2; + IOCPage6.MinDrivesIME = 3; + IOCPage6.MaxDrivesIS = IOCPage2->MaxPhysDisks; + IOCPage6.MaxDrivesIM = 2; + IOCPage6.MaxDrivesIME = IOCPage2->MaxPhysDisks; + if (IOCPage2->MaxVolumes > 1) + { + IOCPage6.MaxDrivesIS -= 2; + IOCPage6.MaxDrivesIME -= 2; + } + IOCPage6.MaxGlobalHotSpares = 1; + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + IOCPage6.SupportedStripeSizeMapIS = set32(0x3f8); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + IOCPage6.SupportedStripeSizeMapIS = set32(0x80); + } + + min_disks = min(2, min(IOCPage6.MinDrivesIS, IOCPage6.MinDrivesIME)); + + printf(" B___T___L Type Vendor Product Rev Disk Blocks Disk MB\n"); + + n = 0; + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + if (isRaidVolume(port, bus, target)) + continue; + + if (doInquiry(port, bus, target, 0, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + continue; + } + + if ((inq[0] & 0x1f) != 0x00) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + if (doReadCapacity(port, bus, target, 0, cap, sizeof cap) != 1) + continue; + + size = get4bytes(cap, 0); + + if (getPath(port, bus, target, &path) == 1) + { + for (i = 0; i < n; i++) + { + if (diag_targets[i].path.slot == path.slot && + diag_targets[i].path.encl_id_l == path.encl_id_l && + diag_targets[i].path.encl_id_h == path.encl_id_h) + { + printf("Bus %d Target %d is another path to Bus %d Target %d, ignoring\n", + bus, target, diag_targets[i].bus, diag_targets[i].target); + break; + } + } + if (i < n) + continue; + } + + diag_targets[n].bus = bus; + diag_targets[n].target = target; + diag_targets[n].size = size; + diag_targets[n].path = path; + + n++; + + printf("%2d. %2d %3d %3d %-9s %-8.8s %-16.16s %-4.4s %10d %7d\n", + n, bus, target, 0, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32, size + 1, (size + 1) / 2048); + + if (n == MAX_DEVICES) + break; + } + if (n == MAX_DEVICES) + break; + } + + if (n < min_disks) + { + printf("\nNot enough available targets found\n"); + return 1; + } + + flags = get32(IOCPage2->CapabilitiesFlags); + + printf("\nTo create a volume, select %d or more of the available targets\n", min_disks); + if (flags & MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT) + printf(" select %d to %d targets for a mirrored volume\n", + IOCPage6.MinDrivesIME, IOCPage6.MaxDrivesIME); + else if (flags & MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT) + printf(" select 2 targets for a mirrored volume\n"); + if (flags & MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT) + printf(" select %d to %d targets for a striped volume\n", + IOCPage6.MinDrivesIS, IOCPage6.MaxDrivesIS); + printf("\n"); + + num_physdisks = 0; + + if (getConfigPageHeader(port, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, 0, &config_rep) != 1) + return 0; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 4, 0, + &ManufacturingPage4, sizeof ManufacturingPage4) != 1) + return 0; + + no_mix_sas_sata = (ManufacturingPage4.Flags & MPI_MANPAGE4_IR_NO_MIX_SAS_SATA) != 0; + no_mix_ssd_non_ssd = (get16(ManufacturingPage4.ExtFlags) & MPI_MANPAGE4_EXTFLAGS_MIX_SSD_AND_NON_SSD) == 0; + + while (TRUE) + { + printf("Select a target: [1-%d or RETURN to quit] ", n); + i = getNumberAnswer(1, n, 0); + if (i == 0) + break; + i--; + + for (t = 0; t < num_physdisks; t++) + { + if (i == chosen[t]) + { + printf("\nThis target has already been chosen!\n\n"); + break; + } + } + if (t < num_physdisks) + continue; + + chosen[num_physdisks] = i; + + bus = diag_targets[i].bus; + target = diag_targets[i].target; + + if (no_mix_sas_sata) + { + if (num_physdisks == 0) + { + sata = isSata(port, bus, target); + } + else if (sata != isSata(port, bus, target)) + { + printf("\nThis %s target cannot be mixed with the %s target%s already chosen!\n\n", + sata ? "SAS" : "SATA", sata ? "SATA" : "SAS", + num_physdisks == 1 ? "" : "s"); + continue; + } + } + + if (no_mix_ssd_non_ssd) + { + if (num_physdisks == 0) + { + ssd = isSsd(port, bus, target); + } + else if (ssd != isSsd(port, bus, target)) + { + printf("\nThis %s target cannot be mixed with the %s target%s already chosen!\n\n", + ssd ? "non-SSD" : "SSD", ssd ? "SSD" : "non-SSD", + num_physdisks == 1 ? "" : "s"); + continue; + } + } + + memset(&RaidPhysDiskPage0, 0, sizeof RaidPhysDiskPage0); + + RaidPhysDiskPage0.Header.PageType = config_rep.Header.PageType; + RaidPhysDiskPage0.Header.PageNumber = config_rep.Header.PageNumber; + RaidPhysDiskPage0.Header.PageLength = config_rep.Header.PageLength; + RaidPhysDiskPage0.Header.PageVersion = config_rep.Header.PageVersion; + + RaidPhysDiskPage0.PhysDiskIOC = port->iocNumber; + RaidPhysDiskPage0.PhysDiskBus = bus; + RaidPhysDiskPage0.PhysDiskID = target; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_CREATE_PHYSDISK; + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.ActionDataSGE, &rep, sizeof rep, + NULL, 0, &RaidPhysDiskPage0, sizeof RaidPhysDiskPage0, SHORT_TIME) != 1) + return 0; + + physdisks[num_physdisks] = get32(rep.ActionData); + +// printf("PhysDisk %d was created\n", physdisks[num_physdisks]); + + if (num_physdisks == 0) + { + first_bus = bus; + first_target = target; + } + num_physdisks++; + + if (num_physdisks >= n && gFlag != TRUE) + break; + + if (IOCPage3->NumPhysDisks + num_physdisks >= IOCPage2->MaxPhysDisks) + { + printf(" no more physical disks can be created, exiting loop\n"); + break; + } + + if (num_physdisks >= max(IOCPage6.MaxDrivesIS, IOCPage6.MaxDrivesIME)) + { + printf(" no more physical disks allowed in a volume, exiting loop\n"); + break; + } + } + + printf("\n%d physical disks were created\n\n", num_physdisks); + + if (num_physdisks < min_disks) + { + printf("Volumes must have at least %d physical disks!\n", min_disks); + return 0; + } + + if (getConfigPageHeader(port, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0, 0, &config_rep) != 1) + return 0; + + length = sizeof *RaidVolumePage0 + sizeof RaidVolumePage0->PhysDisk * (num_physdisks - 1); + if (length < config_rep.Header.PageLength * 4) + length = config_rep.Header.PageLength * 4; + RaidVolumePage0 = malloc(length); + + memset(RaidVolumePage0, 0, length); + + RaidVolumePage0->Header.PageType = config_rep.Header.PageType; + RaidVolumePage0->Header.PageNumber = config_rep.Header.PageNumber; + RaidVolumePage0->Header.PageLength = length / 4; + RaidVolumePage0->Header.PageVersion = config_rep.Header.PageVersion; + + RaidVolumePage0->VolumeIOC = port->iocNumber; + RaidVolumePage0->VolumeBus = first_bus; + RaidVolumePage0->VolumeID = first_target; + + RaidVolumePage0->NumPhysDisks = num_physdisks; + + if (flags & (MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT | MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT) && + flags & MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT) + { + printf("Select volume type: [0=Mirroring, 1=Striping, default is 0] "); + if (getNumberAnswer(0, 1, 0) == 0) + if (num_physdisks == 2 && flags & MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT) + RaidVolumePage0->VolumeType = MPI_RAID_VOL_TYPE_IM; + else + RaidVolumePage0->VolumeType = MPI_RAID_VOL_TYPE_IME; + else + RaidVolumePage0->VolumeType = MPI_RAID_VOL_TYPE_IS; + } + else if (flags & (MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT | MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT)) + { + if (num_physdisks == 2 && flags & MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT) + RaidVolumePage0->VolumeType = MPI_RAID_VOL_TYPE_IM; + else + RaidVolumePage0->VolumeType = MPI_RAID_VOL_TYPE_IME; + } + else if (flags & MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT) + { + RaidVolumePage0->VolumeType = MPI_RAID_VOL_TYPE_IS; + } + + if (RaidVolumePage0->VolumeType == MPI_RAID_VOL_TYPE_IM) + { + settings = get32(ManufacturingPage4.IMVolumeSettings); + } + + if (RaidVolumePage0->VolumeType == MPI_RAID_VOL_TYPE_IME) + { + settings = get32(ManufacturingPage4.IMEVolumeSettings); + stripe_map = get32(IOCPage6.SupportedStripeSizeMapIME); + } + + if (RaidVolumePage0->VolumeType == MPI_RAID_VOL_TYPE_IS) + { + settings = get32(ManufacturingPage4.ISVolumeSettings); + stripe_map = get32(IOCPage6.SupportedStripeSizeMapIS); + } + + if (flags & MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING) + max_volume_size = ((uint64_t)1 << (64 - 11)); // in MB + else + max_volume_size = ((uint64_t)1 << (32 - 11)); // in MB + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + metadata_size = 32; // 32 blocks + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + switch (settings & MPI_RAIDVOL0_SETTING_MASK_METADATA_SIZE) + { + default: + case MPI_RAIDVOL0_SETTING_64MB_METADATA_SIZE: + metadata_size = 64 * 2048; // 64 MB + break; + case MPI_RAIDVOL0_SETTING_512MB_METADATA_SIZE: + metadata_size = 512 * 2048; // 512 MB + break; + } + } + + if (metadata_size > 2048) + printf("Required metadata size is %d MB, plus 2 MB\n", metadata_size / 2048); + else + printf("Required metadata size is %d blocks, plus 2 MB\n", metadata_size); + + max_volume_size -= metadata_size; + + t = 0; + for (i = 0; i < num_physdisks; i++) + { + size = diag_targets[chosen[i]].size + 1; + if (size <= metadata_size) + { + printf("Target %d is smaller than the required metadata size!\n", chosen[i]); + free(RaidVolumePage0); + return 0; + } + + size = (size - metadata_size) / 2048; + + if (size > 1000) + { + coerced_size = ((((size + 127) / 128) * 128) / 10) * 10; + if (coerced_size > size) + { + coerced_size = (((size / 128) * 128) / 10) * 10; + } + + size = coerced_size; + } + + if (size <= 2) + { + printf("Target %d is smaller than the required metadata size!\n", chosen[i]); + free(RaidVolumePage0); + return 0; + } + + size -= 2; + +// printf("Usable size of member %d is %d MB\n", i, size); + + if (i == 0) + { + min_size = size; + } + else + { + if (size != min_size) + t = 1; + if (size < min_size) + { +// printf(" reducing volume member size from %d MB to %d MB\n", min_size, size); + min_size = size; + } + } + } + if (t) + { + printf("Not all physical disks are the same size!\n"); + printf("A common size of %d MB will be used for each physical disk\n", min_size); + } + + volume_size = (uint64_t)min_size * num_physdisks; + if (RaidVolumePage0->VolumeType != MPI_RAID_VOL_TYPE_IS) + volume_size /= 2; + + if (volume_size > max_volume_size) + { + printf("Maximum volume size exceeded; reducing size from %" INT64_FMT "d MB to %" INT64_FMT "d MB\n", + volume_size, max_volume_size); + volume_size = max_volume_size; + } + + printf("Select volume size: [1 to %" INT64_FMT "d MB, default is %" INT64_FMT "d] ", + volume_size, volume_size); + max_lba = (uint64_t)getNumberAnswer(1, (int)volume_size, (int)volume_size) * 2048 - 1; + + t = (U32)max_lba; + RaidVolumePage0->MaxLBA = set32(t); + t = (U32)(max_lba >> 32); + RaidVolumePage0->MaxLBAHigh = set32(t); + + if (stripe_map) + { + if (stripe_map & (stripe_map - 1)) + { + t = stripe_map / 2; + min_stripe = t & (-t); + t = ((t | (min_stripe - 1)) + 1) / 2; + max_stripe = t & (-t); + def_stripe = min(max(64, min_stripe), max_stripe); + printf("Select stripe size: [%d to %d KB, default is %d] ", min_stripe, max_stripe, def_stripe); + size = getNumberAnswer(min_stripe, max_stripe, def_stripe); + } + else + { + size = stripe_map / 2; + printf("A stripe size of %d KB will be used\n", size); + } + RaidVolumePage0->StripeSize = set32(size * 2); + } + + for (i = 0; i < num_physdisks; i++) + { + RaidVolumePage0->PhysDisk[i].PhysDiskNum = physdisks[i]; + RaidVolumePage0->PhysDisk[i].PhysDiskMap = i; + } + + if (RaidVolumePage0->VolumeType == MPI_RAID_VOL_TYPE_IM) + { + RaidVolumePage0->PhysDisk[0].PhysDiskMap = MPI_RAIDVOL0_PHYSDISK_PRIMARY; + RaidVolumePage0->PhysDisk[1].PhysDiskMap = MPI_RAIDVOL0_PHYSDISK_SECONDARY; + } + + t = settings & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE ? 1 : 0; + printf("Enable write caching: [Yes or No, default is %s] ", t == 0 ? "No" : "Yes"); + if (getYesNoAnswer(t)) + settings |= MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; + else + settings &= ~MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; + + RaidVolumePage0->VolumeSettings.Settings = set16(settings); + + flags = 0; + + printf("Zero the first and last blocks of the volume? [Yes or No, default is No] "); + if (getYesNoAnswer(0) == 1) + flags |= MPI_RAID_ACTION_ADATA_LOW_LEVEL_INIT; + + printf("Skip initial volume resync? [Yes or No, default is No] "); + if (getYesNoAnswer(0) == 1) + flags |= MPI_RAID_ACTION_ADATA_DO_NOT_SYNC; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_CREATE_VOLUME; + req.VolumeBus = first_bus; + req.VolumeID = first_target; + req.ActionDataWord = set32(flags); + + t = doMptCommandCheck(port, &req, sizeof req - sizeof req.ActionDataSGE, &rep, sizeof rep, + NULL, 0, RaidVolumePage0, length, LONG_TIME); + + if (t) + printf("\nVolume was created\n"); + + free(RaidVolumePage0); + + return t; +} + +int +doDeleteVolume(MPT_PORT *port, IOCPage2_t *IOCPage2) +{ + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + IOCPage5_t IOCPage5; + int volume; + int i; + int flags; + + if (selectVolume(port, IOCPage2, &volume) != 1) + return 0; + + printf("All data on Volume %d will be lost!\n", volume); + printf("\nAre you sure you want to continue? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + return 1; + + flags = MPI_RAID_ACTION_ADATA_DEL_PHYS_DISKS; + + printf("Zero the first block of all volume members? [Yes or No, default is No] "); + if (getYesNoAnswer(0) == 1) + flags |= MPI_RAID_ACTION_ADATA_ZERO_LBA0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_DELETE_VOLUME; + req.VolumeBus = IOCPage2->RaidVolume[volume].VolumeBus; + req.VolumeID = IOCPage2->RaidVolume[volume].VolumeID; + req.ActionDataWord = set32(flags); + + printf("\nVolume %d is being deleted\n", volume); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + { + printf("\nVolume delete operation failed!\n"); + return 0; + } + + if (IOCPage2->NumActiveVolumes > 1) + return 1; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 5, 0, &IOCPage5, sizeof IOCPage5) != 1) + return 1; + + for (i = 0; i < IOCPage5.NumHotSpares; i++) + { + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_DELETE_PHYSDISK; + req.PhysDiskNum = IOCPage5.HotSpare[i].PhysDiskNum; + + printf("\nHot Spare %d (PhysDisk %d) is being deleted\n", + i, IOCPage5.HotSpare[i].PhysDiskNum); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + { + printf("\nHot Spare delete operation failed!\n"); + } + } + + return 1; +} + +int +doVolumeSettings(MPT_PORT *port, IOCPage2_t *IOCPage2) +{ + RaidVolumePage0_t *RaidVolumePage0; + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + int length; + int b_t; + int volume; + int t1; + int t2; + int t; + + if (selectVolume(port, IOCPage2, &volume) != 1) + return 0; + + b_t = (IOCPage2->RaidVolume[volume].VolumeBus << 8) + IOCPage2->RaidVolume[volume].VolumeID; + + RaidVolumePage0 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0, b_t, &length); + if (RaidVolumePage0 == NULL) + return 0; + + t1 = get16(RaidVolumePage0->VolumeSettings.Settings); + t2 = RaidVolumePage0->VolumeSettings.HotSparePool; + printf("Volume %d Settings: write caching %s%s%s%s\n", volume, + t1 & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE ? "enabled" : "disabled", + t1 & MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART ? ", offline on SMART data" : "", + t1 & MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE ? ", auto configure" : "", + t1 & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC ? ", priority resync" : ""); + if (t2 != 0) + printf("Volume %d draws from Hot Spare Pools: %s%s%s%s%s%s%s%s\n", volume, + t2 & MPI_RAID_HOT_SPARE_POOL_0 ? " 0" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_1 ? " 1" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_2 ? " 2" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_3 ? " 3" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_4 ? " 4" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_5 ? " 5" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_6 ? " 6" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_7 ? " 7" : ""); + printf("\n"); + + t = t1 & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE ? 1 : 0; + printf("Enable write caching: [Yes or No, default is %s] ", t == 0 ? "No" : "Yes"); + if (getYesNoAnswer(t)) + t1 |= MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; + else + t1 &= ~MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; + + t = t1 & MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART ? 1 : 0; + printf("Offline on SMART data: [Yes or No, default is %s] ", t == 0 ? "No" : "Yes"); + if (getYesNoAnswer(t)) + t1 |= MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART; + else + t1 &= ~MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART; + + t = t1 & MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE ? 1 : 0; + printf("Auto configuration: [Yes or No, default is %s] ", t == 0 ? "No" : "Yes"); + if (getYesNoAnswer(t)) + t1 |= MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE; + else + t1 &= ~MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE; + + t = t1 & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC ? 1 : 0; + printf("Priority resync: [Yes or No, default is %s] ", t == 0 ? "No" : "Yes"); + if (getYesNoAnswer(t)) + t1 |= MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; + else + t1 &= ~MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; + + printf("Hot Spare Pools (bitmask of pool numbers): [00 to FF, default is %02x] ", t2); + t2 = getNumberAnswerHex(0x00, 0xff, t2); + + RaidVolumePage0->VolumeSettings.Settings = set16(t1); + RaidVolumePage0->VolumeSettings.HotSparePool = (U8)t2; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS; + req.VolumeBus = IOCPage2->RaidVolume[volume].VolumeBus; + req.VolumeID = IOCPage2->RaidVolume[volume].VolumeID; + + memcpy(&req.ActionDataWord, &RaidVolumePage0->VolumeSettings, sizeof req.ActionDataWord); + + free(RaidVolumePage0); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doVolumeName(MPT_PORT *port, IOCPage2_t *IOCPage2) +{ + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + RaidVolumePage1_t RaidVolumePage1; + int b_t; + int volume; + char name[16]; + int n; + + if (selectVolume(port, IOCPage2, &volume) != 1) + return 0; + + b_t = (IOCPage2->RaidVolume[volume].VolumeBus << 8) + IOCPage2->RaidVolume[volume].VolumeID; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 1, b_t, + &RaidVolumePage1, sizeof RaidVolumePage1) != 1) + return 0; + + printf("Enter a volume name: [0 to %d characters, current is \"%s\"] ", + (int)sizeof name - 1, RaidVolumePage1.Name); + + n = getStringFromArgs(name, sizeof name, stdin); + if (n == 0) + { + return 0; + } + if (n >= sizeof name) + { + printf("\nThe name is too long, current name not changed!\n"); + return 0; + } + + memset(name + n, '\0', sizeof name - n); + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_SET_VOLUME_NAME; + req.VolumeBus = IOCPage2->RaidVolume[volume].VolumeBus; + req.VolumeID = IOCPage2->RaidVolume[volume].VolumeID; + + printf("\nVolume %d's name is being changed...\n", volume); + + return doMptCommandCheck(port, &req, sizeof req - sizeof req.ActionDataSGE, &rep, sizeof rep, + NULL, 0, name, sizeof name, SHORT_TIME); +} + + +int +doDriveFirmwareUpdateMode(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3, int flag) +{ + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + int physdisk; + int timeout; + + if (IOCPage3->NumPhysDisks == 0) + { + printf("No active physical disks\n"); + return 1; + } + + printf("PhysDisk: [0-%d or RETURN to quit] ", IOCPage2->MaxPhysDisks - 1); + physdisk = getNumberAnswer(0, IOCPage2->MaxPhysDisks - 1, -1); + if (physdisk < 0) + return 1; + + printf("Timeout in seconds: [0-255 or RETURN to quit] "); + timeout = getNumberAnswer(0, 255, -1); + if (timeout < 0) + return 1; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE; + req.PhysDiskNum = physdisk; + req.ActionDataWord = set32((timeout << MPI_RAID_ACTION_ADATA_SHIFT_FW_UPDATE_TIMEOUT) | flag); + + printf("\nDrive Firmware Update Mode on PhysDisk %d is being %s\n", physdisk, flag ? "enabled" : "disabled"); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doModifyPhysDisk(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3, int action, char *string) +{ + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + int physdisk; + int physdisk2; + + if (IOCPage3->NumPhysDisks == 0) + { + printf("No active physical disks\n"); + return 1; + } + + printf("PhysDisk: [0-%d or RETURN to quit] ", IOCPage2->MaxPhysDisks - 1); + physdisk = getNumberAnswer(0, IOCPage2->MaxPhysDisks - 1, -1); + if (physdisk < 0) + return 1; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = action; + req.PhysDiskNum = physdisk; + + if (action == MPI_RAID_ACTION_REPLACE_PHYSDISK) + { + printf("Replacement PhysDisk: [0-%d or RETURN to quit] ", IOCPage2->MaxPhysDisks - 1); + physdisk2 = getNumberAnswer(0, IOCPage2->MaxPhysDisks - 1, -1); + if (physdisk2 < 0) + return 1; + + req.ActionDataWord = set32(physdisk2); + } + + printf("\nPhysDisk %d is being %s\n", physdisk, string); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doCreatePhysDisk(MPT_PORT *port, IOCPage2_t *IOCPage2) +{ + RaidPhysDiskPage0_t RaidPhysDiskPage0; + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + ConfigReply_t config_rep; + int bus; + int target; + int physdisk; + + if (getConfigPageHeader(port, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, 0, &config_rep) != 1) + return 0; + + while (TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + break; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + break; + + memset(&RaidPhysDiskPage0, 0, sizeof RaidPhysDiskPage0); + + RaidPhysDiskPage0.Header.PageType = config_rep.Header.PageType; + RaidPhysDiskPage0.Header.PageNumber = config_rep.Header.PageNumber; + RaidPhysDiskPage0.Header.PageLength = config_rep.Header.PageLength; + RaidPhysDiskPage0.Header.PageVersion = config_rep.Header.PageVersion; + + RaidPhysDiskPage0.PhysDiskIOC = port->iocNumber; + RaidPhysDiskPage0.PhysDiskBus = bus; + RaidPhysDiskPage0.PhysDiskID = target; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_CREATE_PHYSDISK; + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.ActionDataSGE, &rep, sizeof rep, + NULL, 0, &RaidPhysDiskPage0, sizeof RaidPhysDiskPage0, SHORT_TIME) != 1) + return 0; + + physdisk = get32(rep.ActionData); + + printf("PhysDisk %d was created\n", physdisk); + } + + return 1; +} + + +int +doPhysDiskSettings(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3) +{ + RaidPhysDiskPage0_t RaidPhysDiskPage0; + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + int physdisk; + int t2; + + if (IOCPage3->NumPhysDisks == 0) + { + printf("No active physical disks\n"); + return 1; + } + + printf("PhysDisk: [0-%d or RETURN to quit] ", IOCPage2->MaxPhysDisks - 1); + physdisk = getNumberAnswer(0, IOCPage2->MaxPhysDisks - 1, -1); + if (physdisk < 0) + return 1; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, physdisk, + &RaidPhysDiskPage0, sizeof RaidPhysDiskPage0) != 1) + return 0; + + t2 = RaidPhysDiskPage0.PhysDiskSettings.HotSparePool; + if (t2 != 0) + printf("PhysDisk %d belongs to Hot Spare Pools: %s%s%s%s%s%s%s%s\n", physdisk, + t2 & MPI_RAID_HOT_SPARE_POOL_0 ? " 0" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_1 ? " 1" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_2 ? " 2" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_3 ? " 3" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_4 ? " 4" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_5 ? " 5" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_6 ? " 6" : "", + t2 & MPI_RAID_HOT_SPARE_POOL_7 ? " 7" : ""); + printf("\n"); + + printf("Hot Spare Pools (bitmask of pool numbers): [00 to FF, default is %02x] ", t2); + t2 = getNumberAnswerHex(0x00, 0xff, t2); + + RaidPhysDiskPage0.PhysDiskSettings.HotSparePool = (U8)t2; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_CHANGE_PHYSDISK_SETTINGS; + req.PhysDiskNum = physdisk; + + memcpy(&req.ActionDataWord, &RaidPhysDiskPage0.PhysDiskSettings, sizeof req.ActionDataWord); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doCreateHotSpare(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3) +{ + RaidPhysDiskPage0_t RaidPhysDiskPage0; + IOCPage5_t IOCPage5; + IOCPage6_t IOCPage6; + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + ConfigReply_t config_rep; + int bus; + int target; + unsigned char inq[36]; + unsigned char cap[8]; + unsigned int size; + int i; + int n; + int t; + + if (IOCPage3->NumPhysDisks == IOCPage2->MaxPhysDisks) + { + printf("Cannot create another active physical disk\n"); + return 1; + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 6, 0, &IOCPage6, sizeof IOCPage6) != 1) + { + memset(&IOCPage6, 0, sizeof IOCPage6); + IOCPage6.MaxDrivesIS = IOCPage2->MaxPhysDisks; + IOCPage6.MaxDrivesIM = 2; + IOCPage6.MaxDrivesIME = IOCPage2->MaxPhysDisks; + if (IOCPage2->MaxVolumes > 1) + { + IOCPage6.MaxDrivesIS -= 2; + IOCPage6.MaxDrivesIME -= 2; + } + IOCPage6.MaxGlobalHotSpares = 1; + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 5, 0, &IOCPage5, sizeof IOCPage5) == 1) + { + if (IOCPage5.NumHotSpares >= IOCPage6.MaxGlobalHotSpares) + { + printf("Cannot create another hot spare\n"); + return 1; + } + } + + printf(" B___T___L Type Vendor Product Rev Disk Blocks Disk MB\n"); + + n = 0; + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + if (isRaidVolume(port, bus, target)) + continue; + + if (doInquiry(port, bus, target, 0, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + continue; + } + + if ((inq[0] & 0x1f) != 0x00) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + if (doReadCapacity(port, bus, target, 0, cap, sizeof cap) != 1) + continue; + + size = get4bytes(cap, 0); + + diag_targets[n].bus = bus; + diag_targets[n].target = target; + diag_targets[n].size = size; + + n++; + + printf("%2d. %2d %3d %3d %-9s %-8.8s %-16.16s %-4.4s %10d %7d\n", + n, bus, target, 0, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32, size + 1, (size + 1) / 2048); + + if (n == MAX_DEVICES) + break; + } + if (n == MAX_DEVICES) + break; + } + + if (n < 1) + { + printf("\nNo available targets found\n"); + return 1; + } + + printf("\nTo create a hot spare, select one of the available targets\n\n"); + + if (getConfigPageHeader(port, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, 0, &config_rep) != 1) + return 0; + + printf("Select a target: [1-%d or RETURN to quit] ", n); + i = getNumberAnswer(1, n, 0); + if (i == 0) + return 1; + i--; + + bus = diag_targets[i].bus; + target = diag_targets[i].target; + + printf("Hot Spare Pool: [0-7 or RETURN to quit] "); + t = getNumberAnswer(0, 7, -1); + if (t < 0) + return 1; + + memset(&RaidPhysDiskPage0, 0, sizeof RaidPhysDiskPage0); + + RaidPhysDiskPage0.Header.PageType = config_rep.Header.PageType; + RaidPhysDiskPage0.Header.PageNumber = config_rep.Header.PageNumber; + RaidPhysDiskPage0.Header.PageLength = config_rep.Header.PageLength; + RaidPhysDiskPage0.Header.PageVersion = config_rep.Header.PageVersion; + + RaidPhysDiskPage0.PhysDiskIOC = port->iocNumber; + RaidPhysDiskPage0.PhysDiskBus = bus; + RaidPhysDiskPage0.PhysDiskID = target; + + RaidPhysDiskPage0.PhysDiskSettings.HotSparePool = (U8)(1 << t); + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_CREATE_PHYSDISK; + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.ActionDataSGE, &rep, sizeof rep, + NULL, 0, &RaidPhysDiskPage0, sizeof RaidPhysDiskPage0, SHORT_TIME) != 1) + return 0; + + printf("\nHot Spare was created\n"); + + return 1; +} + + +int +doDeleteHotSpare(MPT_PORT *port, IOCPage2_t *IOCPage2, IOCPage3_t *IOCPage3) +{ + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + IOCPage5_t IOCPage5; + int physdisk; + int i; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 5, 0, &IOCPage5, sizeof IOCPage5) != 1) + return 1; + + if (IOCPage5.NumHotSpares == 0) + { + printf("No active hot spares\n"); + return 1; + } + + printf("PhysDisk: [0-%d or RETURN to quit] ", IOCPage2->MaxPhysDisks - 1); + physdisk = getNumberAnswer(0, IOCPage2->MaxPhysDisks - 1, -1); + if (physdisk < 0) + return 1; + + for (i = 0; i < IOCPage5.NumHotSpares; i++) + { + if (physdisk == IOCPage5.HotSpare[i].PhysDiskNum) + { + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_RAID_ACTION; + req.Action = MPI_RAID_ACTION_DELETE_PHYSDISK; + req.PhysDiskNum = IOCPage5.HotSpare[i].PhysDiskNum; + + printf("\nHot Spare %d (PhysDisk %d) is being deleted\n", + i, IOCPage5.HotSpare[i].PhysDiskNum); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + { + printf("\nHot Spare delete operation failed!\n"); + } + + return 1; + } + } + + printf("PhysDisk %d is not a valid hot spare!\n", physdisk); + + return 0; +} + + +int +showHiddenDevices(MPT_PORT *port) +{ + IOCPage2_t *IOCPage2; + IOCPage3_t *IOCPage3; + RaidPhysDiskPage0_t RaidPhysDiskPage0; + int i; + int physdisk; + int nd; + int length; + int bus; + int target; + char buf[32]; + + if (mpi2) + return showHiddenDevices2(port); + + IOCPage2 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_IOC, 2, 0, &length); + if (IOCPage2 == NULL || IOCPage2->MaxVolumes == 0) + { + if (IOCPage2) + free(IOCPage2); + return 0; + } + + IOCPage3 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_IOC, 3, 0, &length); + if (IOCPage3 == NULL) + { + free(IOCPage2); + return 0; + } + + nd = IOCPage3->NumPhysDisks; + if (nd == 0 && IOCPage2->NumActiveVolumes) + nd = IOCPage2->MaxPhysDisks; + + if (nd) + { + printf("\nHidden RAID Devices:\n\n"); + + getDeviceInfoHeader(port, buf, sizeof buf); + + printf(" B___T Device Vendor Product Rev %s\n", buf); + + for (i = 0; i < nd; i++) + { + if (IOCPage3->NumPhysDisks) + physdisk = IOCPage3->PhysDisk[i].PhysDiskNum; + else + physdisk = i; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, physdisk, + &RaidPhysDiskPage0, sizeof RaidPhysDiskPage0) != 1) + continue; + + if (!IOCPage3->NumPhysDisks) + if (RaidPhysDiskPage0.PhysDiskStatus.State & MPI_PHYSDISK0_STATUS_MISSING) + continue; + + bus = RaidPhysDiskPage0.PhysDiskBus; + target = RaidPhysDiskPage0.PhysDiskID; + + getDeviceInfo(port, bus, target, buf, sizeof buf); + + printf("%2d %3d PhysDisk %-4d %-8.8s %-16.16s %-4.4s %s\n", + bus, target, physdisk, + RaidPhysDiskPage0.InquiryData.VendorID, + RaidPhysDiskPage0.InquiryData.ProductID, + RaidPhysDiskPage0.InquiryData.ProductRevLevel, buf); + } + } + + free(IOCPage2); + free(IOCPage3); + + return 1; +} + + +int +doRaidActions2(MPT_PORT *port, int command) +{ + Mpi2IOCPage6_t *IOCPage6; + int length; + + if (!(port->capabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)) + { + printf("INTEGRATED_RAID capability is not set!\n"); + printf("RAID is not supported on this port\n"); + return 0; + } + + IOCPage6 = getConfigPageAlloc(port, MPI2_CONFIG_PAGETYPE_IOC, 6, 0, &length); + if (IOCPage6 == NULL) + { + printf("Failed to read IOCPage6!\n"); + printf("RAID is not supported on this port\n"); + return 0; + } + + if (IOCPage6->MaxVolumes == 0) + { + printf("MaxVolumes is zero!\n"); + printf("RAID is not supported on this port\n"); + return 0; + } + + switch (command) + { + case 1: + doShowVolumes2(port, IOCPage6); + break; + case 2: + doShowPhysDisks2(port, IOCPage6); + break; + case 3: + doGetVolumeState2(port); + break; + case 4: + doWaitForResync2(port); + break; + case 10: + doModifyVolume2(port, MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES, "disabled"); + break; + case 11: + doModifyVolume2(port, MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES, "enabled"); + break; + case 13: + doModifyVolume2(port, MPI2_RAID_ACTION_ACTIVATE_VOLUME, "activated"); + break; + case 20: + doModifyPhysDisk2(port, IOCPage6, MPI2_RAID_ACTION_PHYSDISK_OFFLINE, "offlined"); + break; + case 21: + doModifyPhysDisk2(port, IOCPage6, MPI2_RAID_ACTION_PHYSDISK_ONLINE, "onlined"); + break; + case 22: + doModifyPhysDisk2(port, IOCPage6, MPI2_RAID_ACTION_FAIL_PHYSDISK, "failed"); + break; + case 26: + doDriveFirmwareUpdateMode2(port, IOCPage6, 0); + break; + case 27: + doDriveFirmwareUpdateMode2(port, IOCPage6, 1); + break; + case 30: + doCreateVolume2(port, IOCPage6); + break; + case 31: + doDeleteVolume2(port, IOCPage6); + break; + case 32: + doVolumeSettings2(port); + break; + case 33: + doVolumeName2(port); + break; + case 34: + doVolumeIRCC2(port); + break; + case 35: + doVolumeStopIRCC2(port); + break; + case 36: + doVolumeOCE(port); + break; + case 50: + doCreateHotSpare2(port, IOCPage6); + break; + case 51: + doDeleteHotSpare2(port, IOCPage6); + break; + case 60: + doModifyVolume2(port, MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE, "modified"); + break; + default: + printf("Invalid selection!\n"); + break; + } + + free(IOCPage6); + +#if DOS || EFI + // give the firmware a chance to update the volume metadata + sleep(5); +#endif + + return 1; +} + + +int +selectVolume2(MPT_PORT *port, int *volumeOut, int *handleOut) +{ + Mpi2RaidVolPage0_t *RaidVolumePage0; + int volume; + int volumes[MAX_DEVICES]; + int i; + int length; + int handle; + int type; + int flags; + int bus; + int target; + + handle = 0xffff; + for (i = 0; ; i++) + { + RaidVolumePage0 = getConfigPageAlloc(port, MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, + MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE + handle, + &length); + if (RaidVolumePage0 == NULL) + break; + + handle = get16(RaidVolumePage0->DevHandle); + type = RaidVolumePage0->VolumeType; + flags = get32(RaidVolumePage0->VolumeStatusFlags); + + if (mapDevHandleToBusTarget(port, handle, &bus, &target)) + { + printf("Volume %d is DevHandle %04x, Bus %d Target %d, Type %s%s\n", + i, handle, bus, target, + type == MPI2_RAID_VOL_TYPE_RAID0 ? "RAID0 (Striping)" : + type == MPI2_RAID_VOL_TYPE_RAID1E ? "RAID1E (Mirroring Extended)" : + type == MPI2_RAID_VOL_TYPE_RAID1 ? "RAID1 (Mirroring)" : + type == MPI2_RAID_VOL_TYPE_RAID10 ? "RAID10 (Striped Mirroring)" : "Unknown", + flags & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ? ", inactive" : ""); + } + else + { + printf("Volume %d is DevHandle %04x, Type %s%s\n", + i, handle, + type == MPI2_RAID_VOL_TYPE_RAID0 ? "RAID0 (Striping)" : + type == MPI2_RAID_VOL_TYPE_RAID1E ? "RAID1E (Mirroring Extended)" : + type == MPI2_RAID_VOL_TYPE_RAID1 ? "RAID1 (Mirroring)" : + type == MPI2_RAID_VOL_TYPE_RAID10 ? "RAID10 (Striped Mirroring)" : "Unknown", + flags & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ? ", inactive" : ""); + } + + volumes[i] = handle; + + free(RaidVolumePage0); + } + printf("\n"); + + if (i == 0) + { + printf("No volumes found.\n"); + return 0; + } + else + { + if (i > 1 || gFlag == TRUE) + { + printf("Volume: [0-%d or RETURN to quit] ", i - 1); + volume = getNumberAnswer(0, i - 1, -1); + if (volume < 0) + return 0; + printf("\n"); + } + else + { + volume = 0; + } + } + + *volumeOut = volume; + *handleOut = volumes[volume]; + + return 1; +} + + +int +doShowVolumes2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6) +{ + Mpi2RaidVolPage0_t *RaidVolumePage0; + Mpi2RaidVolPage1_t RaidVolumePage1; + Mpi2RaidPhysDiskPage0_t RaidPhysDiskPage0; + int i; + int j; + int t1; + int t2; + int t3; + int length; + int handle2; + int handle; + int physdisk; + int type; + int flags; + int bus; + int target; + + handle = 0xffff; + for (i = 0; ; i++) + { + RaidVolumePage0 = getConfigPageAlloc(port, MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, + MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE + handle, + &length); + if (RaidVolumePage0 == NULL) + break; + + if (i) + printf("\n"); + + handle = get16(RaidVolumePage0->DevHandle); + type = RaidVolumePage0->VolumeType; + flags = get32(RaidVolumePage0->VolumeStatusFlags); + + if (mapDevHandleToBusTarget(port, handle, &bus, &target)) + { + printf("Volume %d is DevHandle %04x, Bus %d Target %d, Type %s%s\n", + i, handle, bus, target, + type == MPI2_RAID_VOL_TYPE_RAID0 ? "RAID0 (Striping)" : + type == MPI2_RAID_VOL_TYPE_RAID1E ? "RAID1E (Mirroring Extended)" : + type == MPI2_RAID_VOL_TYPE_RAID1 ? "RAID1 (Mirroring)" : + type == MPI2_RAID_VOL_TYPE_RAID10 ? "RAID10 (Striped Mirroring)" : "Unknown", + flags & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ? ", inactive" : ""); + } + else + { + printf("Volume %d is DevHandle %04x, Type %s%s\n", + i, handle, + type == MPI2_RAID_VOL_TYPE_RAID0 ? "RAID0 (Striping)" : + type == MPI2_RAID_VOL_TYPE_RAID1E ? "RAID1E (Mirroring Extended)" : + type == MPI2_RAID_VOL_TYPE_RAID1 ? "RAID1 (Mirroring)" : + type == MPI2_RAID_VOL_TYPE_RAID10 ? "RAID10 (Striped Mirroring)" : "Unknown", + flags & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ? ", inactive" : ""); + } + + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 1, + MPI2_RAID_VOLUME_PGAD_FORM_HANDLE + handle, + &RaidVolumePage1, sizeof RaidVolumePage1) == 1) + { + printf(" Volume Name: %-32s\n", + RaidVolumePage1.Name); + printf(" Volume WWID: %08x%08x\n", + get32(RaidVolumePage1.WWID.High), get32(RaidVolumePage1.WWID.Low)); + } + + t1 = RaidVolumePage0->VolumeState; + t2 = flags; + + doShowVolumeState2(i, t1, t2, FALSE); + + if ( flags & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ) + { + t3 = RaidVolumePage0->InactiveStatus; + printf(" Volume Inactive Reason: %s\n", + t3 == MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE ? "stale metadata" : + t3 == MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE ? "foreign volume" : + t3 == MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE ? "insufficient resources" : + t3 == MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE ? "clone of volume found" : + t3 == MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE ? "insufficent valid metadata" : + t3 == MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED ? "volume previously deleted" : "unknown"); + } + + t1 = get16(RaidVolumePage0->VolumeSettings.Settings); + t2 = RaidVolumePage0->VolumeSettings.HotSparePool; + printf(" Volume Settings: write caching %s, auto configure hot swap %s%s\n", + t1 & MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING ? "enabled" : + t1 & MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING ? "disabled" : "controlled by members", + t1 & MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE ? "disabled" : "enabled", + flags & MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB ? ", data scrub allowed" : ""); + + if (t2 != 0) + printf(" Volume draws from Hot Spare Pools: %s%s%s%s%s%s%s%s\n", + t2 & MPI2_RAID_HOT_SPARE_POOL_0 ? " 0" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_1 ? " 1" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_2 ? " 2" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_3 ? " 3" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_4 ? " 4" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_5 ? " 5" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_6 ? " 6" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_7 ? " 7" : ""); + + if (type == MPI2_RAID_VOL_TYPE_RAID1) + printf(" Volume Size %" INT64_FMT "d MB, %d Members\n", + (get64(RaidVolumePage0->MaxLBA) + 1) / 2048, RaidVolumePage0->NumPhysDisks); + else + printf(" Volume Size %" INT64_FMT "d MB, Stripe Size %d KB, %d Members\n", + (get64(RaidVolumePage0->MaxLBA) + 1) / 2048, get32(RaidVolumePage0->StripeSize) / 2, + RaidVolumePage0->NumPhysDisks); + + for (j = 0; j < RaidVolumePage0->NumPhysDisks; j++) + { + physdisk = RaidVolumePage0->PhysDisk[j].PhysDiskNum; + + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, + MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM + physdisk, + &RaidPhysDiskPage0, sizeof RaidPhysDiskPage0) == 1) + { + handle2 = get16(RaidPhysDiskPage0.DevHandle); + + if (mapDevHandleToBusTarget(port, handle2, &bus, &target)) + { + if (type == MPI2_RAID_VOL_TYPE_RAID1) + printf(" %s is PhysDisk %d (DevHandle %04x, Bus %d Target %d)\n", + RaidVolumePage0->PhysDisk[j].PhysDiskMap == MPI2_RAIDVOL0_PHYSDISK_PRIMARY ? "Primary" : + RaidVolumePage0->PhysDisk[j].PhysDiskMap == MPI2_RAIDVOL0_PHYSDISK_SECONDARY ? "Secondary" : + "Member", RaidVolumePage0->PhysDisk[j].PhysDiskNum, handle2, bus, target); + else + printf(" Member %d is PhysDisk %d (DevHandle %04x, Bus %d Target %d)\n", + RaidVolumePage0->PhysDisk[j].PhysDiskMap, RaidVolumePage0->PhysDisk[j].PhysDiskNum, + handle2, bus, target); + } + else + { + if (type == MPI2_RAID_VOL_TYPE_RAID1) + printf(" %s is PhysDisk %d (DevHandle %04x)\n", + RaidVolumePage0->PhysDisk[j].PhysDiskMap == MPI2_RAIDVOL0_PHYSDISK_PRIMARY ? "Primary" : + RaidVolumePage0->PhysDisk[j].PhysDiskMap == MPI2_RAIDVOL0_PHYSDISK_SECONDARY ? "Secondary" : + "Member", RaidVolumePage0->PhysDisk[j].PhysDiskNum, handle2); + else + printf(" Member %d is PhysDisk %d (DevHandle %04x)\n", + RaidVolumePage0->PhysDisk[j].PhysDiskMap, RaidVolumePage0->PhysDisk[j].PhysDiskNum, + handle2); + } + } + } + + free(RaidVolumePage0); + } + + if (i == 0) + printf("No volumes active\n"); + + return 1; +} + + +int +doShowPhysDisks2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6) +{ + Mpi2RaidPhysDiskPage0_t RaidPhysDiskPage0; + Mpi2RaidPhysDiskPage1_t *RaidPhysDiskPage1; + int i; + int j; + int physdisk; + int np; + int t1; + int t2; + int length; + int handle; + int handle2; + int bus; + int target; + + physdisk = 0xff; + for (i = 0; ; i++) + { + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, + MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM + physdisk, + &RaidPhysDiskPage0, sizeof RaidPhysDiskPage0) != 1) + break; + + if (i) + printf("\n"); + + physdisk = RaidPhysDiskPage0.PhysDiskNum; + handle = get16(RaidPhysDiskPage0.DevHandle); + + if (mapDevHandleToBusTarget(port, handle, &bus, &target)) + { + printf("PhysDisk %d is DevHandle %04x, Bus %d Target %d\n", + physdisk, handle, bus, target); + } + else + { + printf("PhysDisk %d is DevHandle %04x\n", + physdisk, handle); + } + + t1 = RaidPhysDiskPage0.PhysDiskState; + t2 = get32(RaidPhysDiskPage0.PhysDiskStatusFlags); + printf(" PhysDisk State: %s%s%s%s%s%s%s\n", + t1 == MPI2_RAID_PD_STATE_NOT_CONFIGURED ? "not configured" : + t1 == MPI2_RAID_PD_STATE_NOT_COMPATIBLE ? "not compatible" : + t1 == MPI2_RAID_PD_STATE_OFFLINE ? "offline" : + t1 == MPI2_RAID_PD_STATE_ONLINE ? "online" : + t1 == MPI2_RAID_PD_STATE_HOT_SPARE ? "hot spare" : + t1 == MPI2_RAID_PD_STATE_DEGRADED ? "degraded" : + t1 == MPI2_RAID_PD_STATE_REBUILDING ? "rebuilding" : + t1 == MPI2_RAID_PD_STATE_OPTIMAL ? "optimal" : "unknown", + t2 & MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC ? ", out of sync" : "", + t2 & MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED ? ", quiesced" : "", + t2 & MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME ? ", member of inactive volume" : "", + t2 & MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED ? ", write cache enabled" : "", + t2 & MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET ? ", online capacity expansion target" : "", + t2 & MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED ? ", disk not certified" : ""); + + + if (t1 == MPI2_RAID_PD_STATE_NOT_COMPATIBLE) + { + t2 = RaidPhysDiskPage0.IncompatibleReason; + printf(" PhysDisk Incompatible Reason: %s\n", + t2 == MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL ? "incorrect protocol" : + t2 == MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE ? "block size mismatch" : + t2 == MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA ? "disk too small" : + t2 == MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD ? "SATA extended command set not supported" : + t2 == MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA ? "disk media is removable" : "unknown"); + } + + if (t1 == MPI2_RAID_PD_STATE_OFFLINE) + { + t2 = RaidPhysDiskPage0.OfflineReason; + printf(" PhysDisk Offline Reason: %s\n", + t2 == MPI2_PHYSDISK0_OFFLINE_MISSING ? "missing" : + t2 == MPI2_PHYSDISK0_OFFLINE_FAILED ? "failed" : + t2 == MPI2_PHYSDISK0_OFFLINE_INITIALIZING ? "initializing" : + t2 == MPI2_PHYSDISK0_OFFLINE_REQUESTED ? "offline at host request" : + t2 == MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED ? "failed at host request" : "unknown"); + } + +// t1 = RaidPhysDiskPage0.PhysDiskSettings.PhysDiskSettings; + t2 = RaidPhysDiskPage0.PhysDiskSettings.HotSparePool; +// printf(" PhysDisk Settings: \n"); + if (t2 != 0) + printf(" PhysDisk belongs to Hot Spare Pools: %s%s%s%s%s%s%s%s\n", + t2 & MPI2_RAID_HOT_SPARE_POOL_0 ? " 0" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_1 ? " 1" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_2 ? " 2" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_3 ? " 3" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_4 ? " 4" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_5 ? " 5" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_6 ? " 6" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_7 ? " 7" : ""); + + printf(" PhysDisk Size %" INT64_FMT "d MB, Inquiry Data: %-8.8s %-16.16s %-4.4s\n", + (get64(RaidPhysDiskPage0.CoercedMaxLBA) + 1) / 2048, RaidPhysDiskPage0.InquiryData.VendorID, + RaidPhysDiskPage0.InquiryData.ProductID, RaidPhysDiskPage0.InquiryData.ProductRevLevel); + + RaidPhysDiskPage1 = getConfigPageAlloc(port, MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK, 1, + MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM + physdisk, + &length); + if (RaidPhysDiskPage1 == NULL) + continue; + + np = RaidPhysDiskPage1->NumPhysDiskPaths; + + if (np > 1) + { + for (j = 0; j < np; j++) + { + handle2 = get16(RaidPhysDiskPage1->PhysicalDiskPath[j].DevHandle); + t1 = get16(RaidPhysDiskPage1->PhysicalDiskPath[j].Flags); + + if (mapDevHandleToBusTarget(port, handle2, &bus, &target)) + { + printf(" Path %d is DevHandle %04x, Bus %d Target %d, %s\n", j, + handle2, bus, target, + t1 & MPI2_RAID_PHYSDISK1_FLAG_INVALID ? "invalid" : + t1 & MPI2_RAID_PHYSDISK1_FLAG_BROKEN ? "broken" : + t1 & MPI2_RAID_PHYSDISK1_FLAG_PRIMARY ? "online, primary" : + "online"); + } + else + { + printf(" Path %d is DevHandle %04x, %s\n", j, + handle2, + t1 & MPI2_RAID_PHYSDISK1_FLAG_INVALID ? "invalid" : + t1 & MPI2_RAID_PHYSDISK1_FLAG_BROKEN ? "broken" : + t1 & MPI2_RAID_PHYSDISK1_FLAG_PRIMARY ? "online, primary" : + "online"); + } + printf(" WWID %" INT64_FMT "x\tOwner WWID %" INT64_FMT "x\tOwner ID %x\n", + get64(RaidPhysDiskPage1->PhysicalDiskPath[j].WWID), + get64(RaidPhysDiskPage1->PhysicalDiskPath[j].OwnerWWID), + RaidPhysDiskPage1->PhysicalDiskPath[j].OwnerIdentifier); + } + } + + free(RaidPhysDiskPage1); + } + + if (i == 0) + printf("No physical disks active\n"); + + return 1; +} + + +void +doShowVolumeState2(int volume, int volState, int volFlag, int useVolume) +{ + char volStr[5]; + int gotOne; + + memset(volStr, 0, sizeof(volStr)); + + if (useVolume) + { + sprintf(volStr, "%d ", volume); + } + + printf("%sVolume %sState: %s%s%s%s%s%s\n", useVolume ? "" : " ", volStr, + volState == MPI2_RAID_VOL_STATE_OPTIMAL ? "optimal" : + volState == MPI2_RAID_VOL_STATE_DEGRADED ? "degraded" : + volState == MPI2_RAID_VOL_STATE_ONLINE ? "online" : + volState == MPI2_RAID_VOL_STATE_INITIALIZING ? "initializing" : + volState == MPI2_RAID_VOL_STATE_FAILED ? "failed" : + volState == MPI2_RAID_VOL_STATE_MISSING ? "missing" : "unknown", + volFlag & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED ? ", enabled" : ", disabled", + volFlag & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED ? ", quiesced" : "", + volFlag & MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL ? ", bad block table full" : "", + volFlag & MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED ? ", online capacity expansion allowed" : "", + volFlag & MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE ? ", background init complete" : ""); + + if (volFlag & (MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS | + MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT | + MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION | + MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK | + MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT)) + { + printf("%s [In Progress: ", useVolume ? "" : " "); + gotOne = 0; + + if (volFlag & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) + { + printf("resync"); + gotOne = 1; + } + if (volFlag & MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT) + { + printf("%sbackground init", gotOne ? ", " : ""); + gotOne = 1; + } + if (volFlag & MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION) + { + printf("%scapacity expansion", gotOne ? ", " : ""); + gotOne = 1; + } + if (volFlag & MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK) + { + printf("%suser initiated consistency check", gotOne ? ", " : ""); + gotOne = 1; + } + if (volFlag & MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT) + { + printf("%smake data consistent", gotOne ? ", " : ""); + gotOne = 1; + } + printf("]\n"); + } + + if (volFlag & (MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING | + MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING | + MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING | + MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC)) + { + printf("%s [Pending: ", useVolume ? "" : " "); + + gotOne = 0; + if (volFlag & MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING) + { + printf("user initiated consistency check"); + gotOne = 1; + } + if (volFlag & MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING) + { + printf("%smake data consistent", gotOne ? ", " : ""); + gotOne = 1; + } + if (volFlag & MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING) + { + printf("%sbackground init", gotOne ? ", " : ""); + gotOne = 1; + } + if (volFlag & MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC) + { + printf("%sresync", gotOne ? ", " : ""); + gotOne = 1; + } + printf("]\n"); + } +} + + +int +doGetVolumeState2(MPT_PORT *port) +{ + Mpi2RaidVolPage0_t *RaidVolumePage0; + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + Mpi2RaidVolIndicator_t *data; + int volume; + int handle; + int length; + int t1; + int t2; + int t3; + uint64_t size; + uint64_t done; + + if (selectVolume2(port, &volume, &handle) != 1) + return 0; + + RaidVolumePage0 = getConfigPageAlloc(port, MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, + MPI2_RAID_VOLUME_PGAD_FORM_HANDLE + handle, + &length); + if (RaidVolumePage0 == NULL) + { + printf("Failed to read RaidVolumePage0!\n"); + return 0; + } + + t1 = RaidVolumePage0->VolumeState; + t2 = get32(RaidVolumePage0->VolumeStatusFlags); + + doShowVolumeState2(volume, t1, t2, TRUE); + + if (t2 & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE) + { + t3 = RaidVolumePage0->InactiveStatus; + printf("Volume %d Inactive Reason: %s\n", volume, + t3 == MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE ? "stale metadata" : + t3 == MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE ? "foreign volume" : + t3 == MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE ? "insufficient resources" : + t3 == MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE ? "clone of volume found" : + t3 == MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE ? "insufficent valid metadata" : + t3 == MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED ? "volume previously deleted" : "unknown"); + } + + if (t2 & (MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS | + MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT | + MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION | + MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK | + MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT)) + { + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_INDICATOR_STRUCT; + req.VolDevHandle = set16(handle); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME) != 1) + return 0; + + data = (pMpi2RaidVolIndicator_t)&rep.ActionData.RaidVolumeIndicator; + + size = get64(data->TotalBlocks); + done = get64(data->BlocksRemaining); + + if (size && done) + { + printf("Progress: total blocks %" INT64_FMT "d, blocks remaining %" INT64_FMT "d, %d%%\n", + size, done, (int)(done / (size / 100))); + } + } + + free (RaidVolumePage0); + + return 1; +} + + +int +doWaitForResync2(MPT_PORT *port) +{ + Mpi2RaidVolPage0_t *RaidVolumePage0; + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + Mpi2RaidVolIndicator_t *data; + int volume; + int handle; + int length; + uint64_t size; + uint64_t done; + int t1; + int t2; + int percent; + int last_percent = -1; + int n; + + if (selectVolume2(port, &volume, &handle) != 1) + return 0; + + RaidVolumePage0 = getConfigPageAlloc(port, MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, + MPI2_RAID_VOLUME_PGAD_FORM_HANDLE + handle, + &length); + if (RaidVolumePage0 == NULL) + { + printf("Failed to read RaidVolumePage0!\n"); + return 0; + } + + t1 = RaidVolumePage0->VolumeState; + t2 = get32(RaidVolumePage0->VolumeStatusFlags); + + doShowVolumeState2(volume, t1, t2, TRUE); + + if (t2 & (MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS | + MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT | + MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION | + MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK | + MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT)) + { + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_INDICATOR_STRUCT; + req.VolDevHandle = set16(handle); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + return 0; + + data = (pMpi2RaidVolIndicator_t)&rep.ActionData.RaidVolumeIndicator; + + size = get64(data->TotalBlocks); + done = get64(data->BlocksRemaining); + + if (size && done) + { + last_percent = (int)(done / (size / 100)); + printf("Progress: total blocks %" INT64_FMT "d, blocks remaining %" INT64_FMT "d, %d%%\n", + size, done, last_percent); + } + } + else + return 1; + + n = 0; + while (TRUE) + { + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + return 0; + + data = (pMpi2RaidVolIndicator_t)&rep.ActionData.RaidVolumeIndicator; + + size = get64(data->TotalBlocks); + done = get64(data->BlocksRemaining); + + if (size && done) + { + percent = (int)(done / (size / 100)); + if (percent != last_percent) + { + last_percent = percent; + n += printf(" %d%%", last_percent); + fflush(stdout); + if (n >= 75) + { + printf("\n"); + n = 0; + } + } + } + else + break; + + sleep(1); + } + if (n) + printf("\n"); + + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, + MPI2_RAID_VOLUME_PGAD_FORM_HANDLE + handle, + RaidVolumePage0, length) != 1) + { + free(RaidVolumePage0); + return 0; + } + + t1 = RaidVolumePage0->VolumeState; + t2 = get32(RaidVolumePage0->VolumeStatusFlags); + + doShowVolumeState2(volume, t1, t2, TRUE); + + free(RaidVolumePage0); + + return 1; +} + + +int +doModifyVolume2(MPT_PORT *port, int action, char *string) +{ + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + int volume; + int handle; + int all; + int nv; + int rate; + int interval; + int actionWord; + + all = 0; + nv = 0; + handle = 0; + + /* get the current number of volumes across all configs */ + getRaidCounts(port, FALSE, &nv, NULL, NULL); + + if (nv == 0) + { + printf("No volumes available\n"); + return 1; + } + + if (action == MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES || + action == MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES) + { + all = 1; + volume = 0; + } + else + { + all = 0; + if (selectVolume2(port, &volume, &handle) != 1) + return 0; + + if (action == MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE) + { + printf("Enter rate to modify (0 = Resync, 1 = Data Scrub Duration, 2 = Power Save Mode): "); + rate = getNumberAnswer(0, 2, -1); + + printf("Enter new rate: "); + interval = getNumberAnswer(0, 999, -1); + + if(rate == 1) + { + actionWord = ((interval << 16) | rate); // For data scrub only + } + else + { + actionWord = ((interval << 8) | rate); // For resync and powersave modes + } + } /* if MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE */ + } + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = action; + req.VolDevHandle = set16(handle); + + if(action == MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE) + { + req.ActionDataWord.Word = set32(actionWord); + } + + if (all) + printf("Volumes are being %s\n", string); + else + printf("Volume %d is being %s\n", volume, string); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doCreateVolume2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6) +{ + Mpi2ManufacturingPage4_t ManufacturingPage4; + Mpi2RaidPhysDiskPage0_t RaidPhysDiskPage0; + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + Mpi2RaidVolumeCreationStruct_t *RaidVolumeCreate; + int bus; + int target; + PATH path; + int no_mix_sas_sata; + int no_mix_ssd_non_ssd; + int no_mix_ssd_sas_sata; + int sata = 0; + int ssd = 0; + int num_physdisks; + int physdisks[MAX_DEVICES]; + int chosen[MAX_DEVICES]; + unsigned char inq[36]; + unsigned char cap[8]; + uint64_t size; + uint64_t coerced_size; + uint64_t min_size = 0; + uint64_t volume_size; + uint64_t max_volume_size; + uint64_t max_lba; + int length; + int i; + int n; + int t; + int settings = 0; + int nd; + int nv; + int cap_flags; + int man_flags; + int type; + int handle; + char name[16]; + int raid0_okay; + int raid1_okay; + int raid1e_okay; + int raid10_okay; + int flags; + int min_disks; + + /* get the current number of volumes and phys disks in the active config */ + getRaidCounts(port, TRUE, &nv, &nd, NULL); + + if (nv >= IOCPage6->MaxVolumes) + { + printf("Cannot create another active volume\n"); + return 0; + } + + min_disks = min(2, min(IOCPage6->MinDrivesRAID0, min(IOCPage6->MinDrivesRAID1E, IOCPage6->MinDrivesRAID10))); + + if (nd + min_disks > IOCPage6->MaxPhysDisks) + { + printf("Cannot create at least %d physical disk%s\n", + min_disks, min_disks == 1 ? "" : "s"); + return 0; + } + + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_MANUFACTURING, 4, 0, + &ManufacturingPage4, sizeof ManufacturingPage4) != 1) + return 0; + + if (nv >= ManufacturingPage4.MaxVolumes) + { + printf("Cannot create another active volume\n"); + return 0; + } + + if (nd + min_disks > ManufacturingPage4.MaxPhysDisks) + { + printf("Cannot create at least %d physical disk%s\n", + min_disks, min_disks == 1 ? "" : "s"); + return 0; + } + + printf(" B___T___L Type Vendor Product Rev Disk Blocks Disk MB\n"); + + n = 0; + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + if (isRaidVolume(port, bus, target)) + continue; + + if (doInquiry(port, bus, target, 0, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + continue; + } + + if ((inq[0] & 0x1f) != 0x00) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + if (doReadCapacity(port, bus, target, 0, cap, sizeof cap) != 1) + continue; + + size = get4bytes(cap, 0); + + if (size == 0xffffffff) + { + if (doReadCapacity16(port, bus, target, 0, cap, sizeof cap) == 1) + { + size = get8bytes(cap, 0); + } + } + + if (getPath(port, bus, target, &path) == 1) + { + for (i = 0; i < n; i++) + { + if (diag_targets[i].path.slot == path.slot && + diag_targets[i].path.encl_id_l == path.encl_id_l && + diag_targets[i].path.encl_id_h == path.encl_id_h) + { + printf("Bus %d Target %d is another path to Bus %d Target %d, ignoring\n", + bus, target, diag_targets[i].bus, diag_targets[i].target); + break; + } + } + if (i < n) + continue; + } + + if (!mapBusTargetToDevHandle(port, bus, target, &handle)) + { + printf("Failed to get DevHandle for Bus %d Target %d\n", bus, target); + continue; + } + + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, + MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE + handle, + &RaidPhysDiskPage0, sizeof RaidPhysDiskPage0) != 1) + { + printf("Failed to get DevHandle for Bus %d Target %d\n", bus, target); + continue; + } + + coerced_size = get64(RaidPhysDiskPage0.CoercedMaxLBA); + + printf("%2d. %2d %3d %3d %-9s %-8.8s %-16.16s %-4.4s %10"INT64_FMT"d %7"INT64_FMT"d\n", + n+1, bus, target, 0, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32, size + 1, (size + 1) / 2048); + + if (coerced_size > size) // unsigned arithmetic, checking for underflow (that is, disk too small) + { + printf("Bus %d Target %d is %d blocks (%d MB), too small to be a volume member\n", + bus, target, size + 1, (size + 1) / 2048); + continue; + } + + diag_targets[n].bus = bus; + diag_targets[n].target = target; + diag_targets[n].size64 = coerced_size; + diag_targets[n].path = path; + + n++; + + if (n == MAX_DEVICES) + break; + } + if (n == MAX_DEVICES) + break; + } + + if (n < min_disks) + { + printf("\nNot enough available targets found\n"); + return 1; + } + + cap_flags = get32(IOCPage6->CapabilitiesFlags); + + printf("\nTo create a volume, select %d or more of the available targets\n", min_disks); + if (cap_flags & MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT) + printf(" select %d to %d targets for a RAID0 volume\n", + IOCPage6->MinDrivesRAID0, IOCPage6->MaxDrivesRAID0); + if (cap_flags & MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT) + printf(" select 2 targets for a RAID1 volume\n"); + if (cap_flags & MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT) + printf(" select %d to %d targets for a RAID1E volume\n", + IOCPage6->MinDrivesRAID1E, IOCPage6->MaxDrivesRAID1E); + if (cap_flags & MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT) + { + printf(" select %d to %d targets for a RAID10 volume\n", + IOCPage6->MinDrivesRAID10, IOCPage6->MaxDrivesRAID10); + printf("\nNote: for a RAID10, the number of targets must be even\n"); + } + printf("\n"); + + num_physdisks = 0; + + man_flags = get32(ManufacturingPage4.Flags); + no_mix_sas_sata = (man_flags & MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA) != 0; + no_mix_ssd_non_ssd = (man_flags & MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD) == 0; + no_mix_ssd_sas_sata = (man_flags & MPI2_MANPAGE4_MIX_SSD_SAS_SATA) == 0; + + while (TRUE) + { + printf("Select a target: [1-%d or RETURN to quit] ", n); + i = getNumberAnswer(1, n, 0); + if (i == 0) + break; + i--; + + for (t = 0; t < num_physdisks; t++) + { + if (i == chosen[t]) + { + printf("\nThis target has already been chosen!\n\n"); + break; + } + } + if (t < num_physdisks) + continue; + + chosen[num_physdisks] = i; + + bus = diag_targets[i].bus; + target = diag_targets[i].target; + + if (num_physdisks == 0) + { + sata = isSata(port, bus, target); + ssd = isSsd(port, bus, target); + } + else + { + if (no_mix_sas_sata) + { + if (sata != isSata(port, bus, target)) + { + printf("\nThis %s target cannot be mixed with the %s target%s already chosen!\n\n", + sata ? "SAS" : "SATA", sata ? "SATA" : "SAS", + num_physdisks == 1 ? "" : "s"); + continue; + } + } + + if (no_mix_ssd_non_ssd) + { + if (ssd != isSsd(port, bus, target)) + { + printf("\nThis %s target cannot be mixed with the %s target%s already chosen!\n\n", + ssd ? "non-SSD" : "SSD", ssd ? "SSD" : "non-SSD", + num_physdisks == 1 ? "" : "s"); + continue; + } + } + + if (no_mix_ssd_sas_sata) + { + if (ssd && isSsd(port, bus, target) && sata != isSata(port, bus, target)) + { + printf("\nThis %s SSD target cannot be mixed with the %s SSD target%s already chosen!\n\n", + sata ? "SAS" : "SATA", sata ? "SATA" : "SAS", + num_physdisks == 1 ? "" : "s"); + continue; + } + } + } + + if (!mapBusTargetToDevHandle(port, bus, target, &handle)) + { + printf("\nFailed to get DevHandle for Bus %d Target %d\n", bus, target); + continue; + } + + physdisks[num_physdisks] = handle; + + num_physdisks++; + + if (num_physdisks >= n && gFlag != TRUE) + break; + + if (nd + num_physdisks >= ManufacturingPage4.MaxPhysDisks) + { + printf(" no more physical disks can be created, exiting loop\n"); + break; + } + + if (num_physdisks >= ManufacturingPage4.MaxPhysDisksPerVol) + { + printf(" no more physical disks allowed in a volume, exiting loop\n"); + break; + } + } + + printf("\n%d physical disks were selected\n\n", num_physdisks); + + if (num_physdisks < min_disks) + { + printf("Volumes must have at least %d physical disks!\n", min_disks); + return 0; + } + + raid0_okay = num_physdisks >= IOCPage6->MinDrivesRAID0 && cap_flags & MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT; + raid1_okay = num_physdisks == 2 && cap_flags & MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT; + raid1e_okay = num_physdisks >= IOCPage6->MinDrivesRAID1E && cap_flags & MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT; + raid10_okay = num_physdisks >= IOCPage6->MinDrivesRAID10 && num_physdisks % 2 == 0 && cap_flags & MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT; + + if (!raid0_okay && !raid1_okay && !raid1e_okay && !raid10_okay) + { + printf("No suitable RAID volume type could be found for the targets selected!\n"); + return 0; + } + + printf("Select volume type: [%s%s%s%sor RETURN to quit] ", + raid0_okay ? "0=RAID0, " : "", + raid1_okay ? "1=RAID1, " : "", + raid1e_okay ? "2=RAID1E, " : "", + raid10_okay ? "3=RAID10, " : ""); + while (TRUE) + { + type = getNumberAnswer(0, 3, -1); + if (type < 0) + return 0; + if ((type == 0 && raid0_okay) || + (type == 1 && raid1_okay) || + (type == 2 && raid1e_okay) || + (type == 3 && raid10_okay)) + { + break; + } + printf("Invalid answer, try again: "); + } + + switch (type) + { + case 0: + type = MPI2_RAID_VOL_TYPE_RAID0; + settings = get32(ManufacturingPage4.RAID0VolumeSettings); + break; + case 1: + type = MPI2_RAID_VOL_TYPE_RAID1; + settings = get32(ManufacturingPage4.RAID1VolumeSettings); + break; + case 2: + type = MPI2_RAID_VOL_TYPE_RAID1E; + settings = get32(ManufacturingPage4.RAID1EVolumeSettings); + break; + case 3: + type = MPI2_RAID_VOL_TYPE_RAID10; + settings = get32(ManufacturingPage4.RAID10VolumeSettings); + break; + } + + length = sizeof *RaidVolumeCreate + sizeof RaidVolumeCreate->PhysDisk * (num_physdisks - 1); + + RaidVolumeCreate = malloc(length); + + memset(RaidVolumeCreate, 0, length); + + RaidVolumeCreate->NumPhysDisks = num_physdisks; + RaidVolumeCreate->VolumeType = type; + RaidVolumeCreate->ResyncRate = ManufacturingPage4.ResyncRate; + RaidVolumeCreate->DataScrubDuration = ManufacturingPage4.DataScrubDuration; + + max_volume_size = ((uint64_t)1 << (64 - 11)); // in MB + + t = 0; + for (i = 0; i < num_physdisks; i++) + { + size = (diag_targets[chosen[i]].size64 + 1) / 2048; + + printf("Usable size of member %d is %"INT64_FMT"d MB\n", i, size); + + if (i == 0) + { + min_size = size; + } + else + { + if (size != min_size) + t = 1; + if (size < min_size) + { + printf(" reducing volume member size from %d MB to %d MB\n", min_size, size); + min_size = size; + } + } + } + if (t) + { + printf("Not all physical disks are the same size!\n"); + printf("A common size of %d MB will be used for each physical disk\n", min_size); + } + + volume_size = (uint64_t)min_size * num_physdisks; + + if (type != MPI2_RAID_VOL_TYPE_RAID0) + volume_size /= 2; + + if (volume_size > max_volume_size) + { + printf("Maximum volume size exceeded; reducing size from %" INT64_FMT "d MB to %" INT64_FMT "d MB\n", + volume_size, max_volume_size); + volume_size = max_volume_size; + } + + printf("Select volume size: [1 to %" INT64_FMT "d MB, default is %" INT64_FMT "d] ", + volume_size, volume_size); + max_lba = (uint64_t)getNumberAnswer(1, (int)volume_size, (int)volume_size) * 2048 - 1; + + t = (U32)max_lba; + RaidVolumeCreate->VolumeMaxLBA.Low = set32(t); + t = (U32)(max_lba >> 32); + RaidVolumeCreate->VolumeMaxLBA.High = set32(t); + + // Volumes can be made up of 512b sector and 4Kb sector drives. As such, + // we can no longer simply use the IOCPage6 map. We really should get + // the drive information and calculate the size based on that. However, + // the firmware only supports one block size. We can tell the FW to use + // its only supported size by setting StripeSize to 0. + RaidVolumeCreate->StripeSize = set32(0); +#if 0 + if (stripe_map) + { + if (stripe_map & (stripe_map - 1)) + { + t = stripe_map / 2; + min_stripe = t & (-t); + t = ((t | (min_stripe - 1)) + 1) / 2; + max_stripe = t & (-t); + def_stripe = min(max(128, min_stripe), max_stripe); + printf("Select stripe size: [%d to %d KB, default is %d] ", min_stripe, max_stripe, def_stripe); + size = getNumberAnswer(min_stripe, max_stripe, def_stripe); + } + else + { + size = stripe_map / 2; + printf("A stripe size of %d KB will be used\n", size); + } + RaidVolumeCreate->StripeSize = set32((unsigned int)size * 2); + } +#endif + while (TRUE) + { + printf("Enter a volume name: [0 to %d characters] ", (int)sizeof name - 1); + + n = getStringFromArgs(name, sizeof name, stdin); + if (n < sizeof name) + break; + + printf("Invalid answer, try again: "); + } + + memcpy(RaidVolumeCreate->Name, name, n); + + for (i = 0; i < num_physdisks; i++) + { + RaidVolumeCreate->PhysDisk[i].PhysDiskDevHandle = set16(physdisks[i]); + RaidVolumeCreate->PhysDisk[i].PhysDiskMap = i; + } + + if (type == MPI2_RAID_VOL_TYPE_RAID1) + { + RaidVolumeCreate->PhysDisk[0].PhysDiskMap = MPI2_RAIDVOL0_PHYSDISK_PRIMARY; + RaidVolumeCreate->PhysDisk[1].PhysDiskMap = MPI2_RAIDVOL0_PHYSDISK_SECONDARY; + } + + RaidVolumeCreate->VolumeSettings = set32(settings); + + flags = 0; + + printf("Use default settings? [Yes or No, default is Yes] "); + if (getYesNoAnswer(1) == 1) + flags |= MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS; + + printf("Zero the first and last blocks of the volume? [Yes or No, default is No] "); + if (getYesNoAnswer(0) == 1) + flags |= MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT; + + if (type == MPI2_RAID_VOL_TYPE_RAID1) + { + printf("Copy all data from primary to secondary? [Yes or No, default is Yes] "); + if (getYesNoAnswer(1) == 1) + flags |= MPI2_RAID_VOL_CREATION_MIGRATE_DATA; + } + + if (type != MPI2_RAID_VOL_TYPE_RAID0) + { + flags |= MPI2_RAID_VOL_CREATION_BACKGROUND_INIT; + } + + RaidVolumeCreate->VolumeCreationFlags = set32(flags); + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_CREATE_VOLUME; + + t = doMptCommandCheck(port, &req, sizeof req - sizeof req.ActionDataSGE, &rep, sizeof rep, + NULL, 0, RaidVolumeCreate, length, LONG_TIME); + + if (t == 1) + printf("\nVolume was created\n"); + + free(RaidVolumeCreate); + + return t; +} + + +int +doDeleteVolume2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6) +{ + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + Mpi2RaidConfigurationPage0_t *RaidConfigPage0; + int volume; + int i; + int handle; + int type; + int flags; + int configNum; + int length; + + if (selectVolume2(port, &volume, &handle) != 1) + return 0; + + if (getRaidConfig(port, MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT, handle, -1, &RaidConfigPage0) == 1) + { + /* save the RAID config this volume resides in so we can check for hot spares after it is deleted */ + configNum = RaidConfigPage0->ConfigNum; + free(RaidConfigPage0); + } + else + { + printf("\nUnable to determine raid configuration volume resides in!\n"); + return 1; + } + + printf("All data on Volume %d will be lost!\n", volume); + printf("\nAre you sure you want to continue? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + return 1; + + flags = 0; + + printf("Zero the first block of all volume members? [Yes or No, default is No] "); + if (getYesNoAnswer(0) == 1) + flags |= MPI2_RAID_ACTION_ADATA_ZERO_LBA0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_DELETE_VOLUME; + req.VolDevHandle = set16(handle); + req.ActionDataWord.Word = set32(flags); + + printf("\nVolume %d is being deleted\n", volume); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + { + printf("\nVolume delete operation failed!\n"); + return 0; + } + + RaidConfigPage0 = getConfigPageAlloc(port, MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG, 0, + MPI2_RAID_PGAD_FORM_CONFIGNUM + configNum, &length); + + if (RaidConfigPage0 == NULL) + { + return 1; + } + + if (RaidConfigPage0->NumVolumes > 0) + { + free(RaidConfigPage0); + return 1; + } + + for (i = 0; i < RaidConfigPage0->NumElements; i++) + { + flags = get16(RaidConfigPage0->ConfigElement[i].ElementFlags); + type = flags & MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; + + if (type == MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) + { + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_DELETE_HOT_SPARE; + req.PhysDiskNum = RaidConfigPage0->ConfigElement[i].PhysDiskNum; + + printf("\nHot Spare (PhysDisk %d) is being deleted\n", + RaidConfigPage0->ConfigElement[i].PhysDiskNum); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + { + printf("\nHot Spare delete operation failed!\n"); + } + } + } + + free(RaidConfigPage0); + return 1; +} + + +int +doVolumeSettings2(MPT_PORT *port) +{ + Mpi2RaidVolPage0_t *RaidVolumePage0; + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + int length; + int volume; + int handle; + int t1; + int t2; + int t; + + if (selectVolume2(port, &volume, &handle) != 1) + return 0; + + RaidVolumePage0 = getConfigPageAlloc(port, MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, + MPI2_RAID_VOLUME_PGAD_FORM_HANDLE + handle, + &length); + if (RaidVolumePage0 == NULL) + { + printf("Failed to read RaidVolumePage0!\n"); + return 0; + } + + t1 = get16(RaidVolumePage0->VolumeSettings.Settings); + t2 = RaidVolumePage0->VolumeSettings.HotSparePool; + printf(" Volume %d Settings: write caching %s, auto configure hot swap %s\n", volume, + t1 & MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING ? "enabled" : + t1 & MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING ? "disabled" : "controlled by members", + t1 & MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE ? "disabled" : "enabled"); + if (t2 != 0) + printf("Volume %d draws from Hot Spare Pools: %s%s%s%s%s%s%s%s\n", volume, + t2 & MPI2_RAID_HOT_SPARE_POOL_0 ? " 0" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_1 ? " 1" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_2 ? " 2" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_3 ? " 3" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_4 ? " 4" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_5 ? " 5" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_6 ? " 6" : "", + t2 & MPI2_RAID_HOT_SPARE_POOL_7 ? " 7" : ""); + printf("\n"); + + t = t1 & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING; + switch (t) + { + case MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING: + t = 0; + break; + case MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING: + t = 1; + break; + default: + case MPI2_RAIDVOL0_SETTING_UNCHANGED: + t = 2; + break; + } + printf("Write caching: [0=Disabled, 1=Enabled, 2=MemberControlled, default is %d] ", t); + t = getNumberAnswer(0, 2, t); + switch (t) + { + case 0: + t = MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING; + break; + case 1: + t = MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING; + break; + case 2: + t = MPI2_RAIDVOL0_SETTING_UNCHANGED; + break; + } + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE; + req.VolDevHandle = set16(handle); + req.ActionDataWord.Word = set32(t); + + free(RaidVolumePage0); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doVolumeName2(MPT_PORT *port) +{ + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + Mpi2RaidVolPage1_t RaidVolumePage1; + int volume; + int handle; + char name[16]; + int n; + + if (selectVolume2(port, &volume, &handle) != 1) + return 0; + + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 1, + MPI2_RAID_VOLUME_PGAD_FORM_HANDLE + handle, + &RaidVolumePage1, sizeof RaidVolumePage1) != 1) + return 0; + + printf("Enter a volume name: [0 to %d characters, current is \"%s\"] ", + (int)sizeof name - 1, RaidVolumePage1.Name); + + n = getStringFromArgs(name, sizeof name, stdin); + if (n == 0) + { + return 0; + } + if (n >= sizeof name) + { + printf("\nThe name is too long, current name not changed!\n"); + return 0; + } + + memset(name + n, '\0', sizeof name - n); + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_SET_VOLUME_NAME; + req.VolDevHandle = set16(handle); + + printf("\nVolume %d's name is being changed...\n", volume); + + return doMptCommandCheck(port, &req, sizeof req - sizeof req.ActionDataSGE, &rep, sizeof rep, + NULL, 0, name, sizeof name, SHORT_TIME); +} + + +int +doVolumeIRCC2(MPT_PORT *port) +{ + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + int volume; + int handle; + + if (selectVolume2(port, &volume, &handle) != 1) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_START_RAID_FUNCTION; + req.VolDevHandle = set16(handle); + req.ActionDataWord.StartRaidFunction.RAIDFunction = MPI2_RAID_ACTION_START_CONSISTENCY_CHECK; + + printf("\nIRCC started on volume %d...\n", volume); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doVolumeStopIRCC2(MPT_PORT *port) +{ + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + int volume; + int handle; + + if (selectVolume2(port, &volume, &handle) != 1) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_STOP_RAID_FUNCTION; + req.VolDevHandle = set16(handle); + req.ActionDataWord.StopRaidFunction.RAIDFunction = MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK; + + printf("\nStopping IRCC on volume %d...\n", volume); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doVolumeOCE(MPT_PORT *port) +{ + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + int volume; + int handle; + + if (selectVolume2(port, &volume, &handle) != 1) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_START_RAID_FUNCTION; + req.VolDevHandle = set16(handle); + req.ActionDataWord.StartRaidFunction.RAIDFunction = MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION; + + printf("\nOCE is being performed on volume %d...\n", volume); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doDriveFirmwareUpdateMode2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6, int flag) +{ + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + int physdisk; + int timeout; + int nd; + + /* get the current number of phys disks in the active config */ + getRaidCounts(port, TRUE, NULL, &nd, NULL); + + if (nd == 0) + { + printf("No active physical disks\n"); + return 1; + } + + printf("PhysDisk: [0-%d or RETURN to quit] ", IOCPage6->MaxPhysDisks - 1); + physdisk = getNumberAnswer(0, IOCPage6->MaxPhysDisks - 1, -1); + if (physdisk < 0) + return 1; + + printf("Timeout in seconds: [0-255 or RETURN to quit] "); + timeout = getNumberAnswer(0, 255, -1); + if (timeout < 0) + return 1; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE; + req.PhysDiskNum = physdisk; + req.ActionDataWord. + FwUpdateMode.Flags = flag; + req.ActionDataWord.FwUpdateMode. + DeviceFirmwareUpdateModeTimeout = timeout; + + printf("\nDrive Firmware Update Mode on PhysDisk %d is being %s\n", physdisk, flag ? "enabled" : "disabled"); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doModifyPhysDisk2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6, int action, char *string) +{ + MpiRaidActionRequest_t req; + MpiRaidActionReply_t rep; + int physdisk; + int nd; + + /* get the current number of phys disks across all configs */ + getRaidCounts(port, FALSE, NULL, &nd, NULL); + + if (nd == 0) + { + printf("No active physical disks\n"); + return 1; + } + + printf("PhysDisk: [0-%d or RETURN to quit] ", IOCPage6->MaxPhysDisks - 1); + physdisk = getNumberAnswer(0, IOCPage6->MaxPhysDisks - 1, -1); + if (physdisk < 0) + return 1; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = action; + req.PhysDiskNum = physdisk; + + printf("\nPhysDisk %d is being %s\n", physdisk, string); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doCreateHotSpare2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6) +{ + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + int bus; + int target; + unsigned char inq[36]; + unsigned char cap[8]; + unsigned int size; + int i; + int n; + int t; + int handle; + int nd; + int ns; + + /* get the current number of phys disks and hot spares in the active config */ + getRaidCounts(port, TRUE, NULL, &nd, &ns); + + if (nd >= IOCPage6->MaxPhysDisks) + { + printf("Cannot create another active physical disk\n"); + return 0; + } + + if (ns >= IOCPage6->MaxGlobalHotSpares) + { + printf("Cannot create another hot spare\n"); + return 0; + } + + printf(" B___T___L Type Vendor Product Rev Disk Blocks Disk MB\n"); + + n = 0; + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + if (isRaidVolume(port, bus, target)) + continue; + + if (doInquiry(port, bus, target, 0, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + continue; + } + + if ((inq[0] & 0x1f) != 0x00) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + if (doReadCapacity(port, bus, target, 0, cap, sizeof cap) != 1) + continue; + + size = get4bytes(cap, 0); + + diag_targets[n].bus = bus; + diag_targets[n].target = target; + diag_targets[n].size = size; + + n++; + + printf("%2d. %2d %3d %3d %-9s %-8.8s %-16.16s %-4.4s %10d %7d\n", + n, bus, target, 0, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32, size + 1, (size + 1) / 2048); + + if (n == MAX_DEVICES) + break; + } + if (n == MAX_DEVICES) + break; + } + + if (n < 1) + { + printf("\nNo available targets found\n"); + return 1; + } + + printf("\nTo create a hot spare, select one of the available targets\n\n"); + + printf("Select a target: [1-%d or RETURN to quit] ", n); + i = getNumberAnswer(1, n, 0); + if (i == 0) + return 1; + i--; + + bus = diag_targets[i].bus; + target = diag_targets[i].target; + + if (!mapBusTargetToDevHandle(port, bus, target, &handle)) + { + printf("\nFailed to get DevHandle for Bus %d Target %d\n", bus, target); + return 0; + } + + printf("Hot Spare Pool: [0-7 or RETURN to quit] "); + t = getNumberAnswer(0, 7, -1); + if (t < 0) + return 1; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_CREATE_HOT_SPARE; + + req.ActionDataWord.HotSpare.HotSparePool = (U8)(1 << t); + req.ActionDataWord.HotSpare.DevHandle = set16(handle); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME) != 1) + return 0; + + printf("\nHot Spare was created\n"); + + return 1; +} + + +int +doDeleteHotSpare2(MPT_PORT *port, Mpi2IOCPage6_t *IOCPage6) +{ + Mpi2RaidActionRequest_t req; + Mpi2RaidActionReply_t rep; + int physdisk; + int ns; + + /* get the current number of hot spares across all configs */ + getRaidCounts(port, FALSE, NULL, NULL, &ns); + + if (ns == 0) + { + printf("No hot spares\n"); + return 0; + } + + printf("PhysDisk: [0-%d or RETURN to quit] ", IOCPage6->MaxPhysDisks - 1); + physdisk = getNumberAnswer(0, IOCPage6->MaxPhysDisks - 1, -1); + if (physdisk < 0) + return 1; + + if (getRaidConfig(port, MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT, -1, physdisk, NULL) == 1) + { + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI2_FUNCTION_RAID_ACTION; + req.Action = MPI2_RAID_ACTION_DELETE_HOT_SPARE; + req.PhysDiskNum = physdisk; + + printf("\nHot Spare (PhysDisk %d) is being deleted\n", physdisk); + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + { + printf("\nHot Spare delete operation failed!\n"); + } + + return 1; + } + + printf("PhysDisk %d is not a valid hot spare!\n", physdisk); + return 0; +} + + +int +showHiddenDevices2(MPT_PORT *port) +{ + Mpi2RaidPhysDiskPage0_t RaidPhysDiskPage0; + int i; + int physdisk; + int nd; + int handle; + int bus; + int target; + char buf[32]; + + getRaidCounts(port, FALSE, NULL, &nd, NULL); + + if (nd) + { + printf("\nHidden RAID Devices:\n\n"); + + getDeviceInfoHeader(port, buf, sizeof buf); + + printf(" B___T Device Vendor Product Rev %s\n", buf); + + physdisk = 0xff; + for (i = 0; ; i++) + { + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, + MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM + physdisk, + &RaidPhysDiskPage0, sizeof RaidPhysDiskPage0) != 1) + break; + + physdisk = RaidPhysDiskPage0.PhysDiskNum; + handle = get16(RaidPhysDiskPage0.DevHandle); + + if (mapDevHandleToBusTarget(port, handle, &bus, &target)) + { + getDeviceInfo(port, bus, target, buf, sizeof buf); + + printf("%2d %3d PhysDisk %-4d %-8.8s %-16.16s %-4.4s %s\n", + bus, target, physdisk, + RaidPhysDiskPage0.InquiryData.VendorID, + RaidPhysDiskPage0.InquiryData.ProductID, + RaidPhysDiskPage0.InquiryData.ProductRevLevel, buf); + } + } + } + + return 1; +} + + +int +getRaidCounts(MPT_PORT *port, int activeOnly, int *numVolumes, int *numPhysDisks, int *numHotSpares) +{ + Mpi2RaidConfigurationPage0_t *RaidConfigPage0; + int length; + int i; + int address; + + if (numVolumes) + *numVolumes = 0; + if (numPhysDisks) + *numPhysDisks = 0; + if (numHotSpares) + *numHotSpares = 0; + + if (mpi2 && port->capabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) + { + i = 0xff; + while (TRUE) + { + if (activeOnly) + address = MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG; + else + address = MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM + i; + + RaidConfigPage0 = getConfigPageAlloc(port, MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG, 0, + address, &length); + + if (RaidConfigPage0 == NULL) + break; + + i = RaidConfigPage0->ConfigNum; + + if (numVolumes) + *numVolumes += RaidConfigPage0->NumVolumes; + + if (numPhysDisks) + *numPhysDisks += RaidConfigPage0->NumPhysDisks; + + if (numHotSpares) + *numHotSpares += RaidConfigPage0->NumHotSpares; + + free(RaidConfigPage0); + + if (activeOnly) + break; + } + } + + return 1; +} + + +/* + * getRaidConfig - Look for a raid config that contains an element matching the inputs. + * + * Inputs: elementType (required) - A MPI2_RAIDCONFIG0_EFLAGS_* value used to match + * a devHandle or physDiskNum + * devHandle - If elementType is VOLUME_ELEMENT then this is matched + * against VolDevHandle. If elementType is any other value + * then elementType is matched against PhysDiskDevHandle. + * If this field is used then physDiskNum should be -1. + * physDiskNum - Valid for any elementType except VOLUME_ELEMENT, it is + * the value to match against PhysDiskNum in the ConfigElement + * list. If this field is used then devHandle should be -1. + * + * Outputs: RaidConfigPage0 (optional) - If not NULL then an allocated RaidConfigPage0 is returned + * which contains the matched input or NULL if no match found. + * + * Return: 1 if a match is found, 0 otherwise. + * + * Note: If both devHandle and physDiskNum are not -1 then devHandle will be used and physDiskNum ignored. +*/ +int +getRaidConfig(MPT_PORT *port, int elementType, int devHandle, int physDiskNum, Mpi2RaidConfigurationPage0_t **RaidConfigPage0) +{ + Mpi2RaidConfigurationPage0_t *rcp0; + int i; + int j; + int length; + int flags; + int currType; + int currDevHandle; + + if (devHandle == -1 && physDiskNum == -1) + { + if (RaidConfigPage0) + *RaidConfigPage0 = NULL; + return 0; + } + + if (mpi2 && port->capabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) + { + i = 0xff; + while (TRUE) + { + rcp0 = getConfigPageAlloc(port, MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG, 0, + MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM + i, &length); + if (rcp0 != NULL) + { + i = rcp0->ConfigNum; + + for (j = 0; j < rcp0->NumElements; j++) + { + flags = get16(rcp0->ConfigElement[j].ElementFlags); + currType = flags & MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; + + if (devHandle != -1) + { + if (elementType == MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT) + currDevHandle = get16(rcp0->ConfigElement[j].VolDevHandle); + else + currDevHandle = get16(rcp0->ConfigElement[j].PhysDiskDevHandle); + + if (currType == elementType && currDevHandle == devHandle) + { + if (RaidConfigPage0) + *RaidConfigPage0 = rcp0; + + return 1; + } + } + else + { + if (currType != MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT && + currType == elementType && + physDiskNum == rcp0->ConfigElement[j].PhysDiskNum) + { + if (RaidConfigPage0) + *RaidConfigPage0 = rcp0; + + return 1; + } + } + } + } + else + break; + + free(rcp0); + } + } + + if (RaidConfigPage0) + *RaidConfigPage0 = NULL; + + return 0; +} + + +int +doResetBus(MPT_PORT *port) +{ +#if WIN32 + int status; + SRB_BUFFER srb; + int inLen; + int outLen; + DWORD retLen; + + memset(&srb, 0, sizeof srb); + + srb.Sic.Length = sizeof srb - sizeof srb.Sic; + srb.Sic.ControlCode = ISSUE_BUS_RESET; + srb.Sic.HeaderLength = sizeof srb.Sic; + srb.Sic.Timeout = RESET_TIME; + + inLen = sizeof srb; + outLen = sizeof srb; + retLen = 0; + + printf("Resetting bus...\n"); + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + &srb, inLen, &srb, outLen, &retLen, NULL); + + return status; +#else + SCSITaskMgmt_t req; + SCSITaskMgmtReply_t rep; + int bus; + + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SCSI_TASK_MGMT; + req.TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; + + printf("Resetting bus...\n"); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, RESET_TIME); +#endif +} + + +int +doResetTarget(MPT_PORT *port) +{ + SCSITaskMgmt_t req; + SCSITaskMgmtReply_t rep; + int bus; + int target; + int lun; + int type; + + printf(" 1. Target Reset\n"); + printf(" 2. Logical Unit Reset\n"); + printf(" 3. Abort Task Set\n"); + printf(" 4. Clear Task Set\n"); + printf(" 5. Query Task\n"); + printf(" 6. Abort Task\n"); + printf("\nSelect a reset type: [1-6 or RETURN to quit] "); + type = getNumberAnswer(1, 6, 0); + if (type == 0) + return 1; + + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + if (type != 1) + { + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + } + else + { + lun = 0; + } + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SCSI_TASK_MGMT; + switch(type) + { + case 1: req.TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; break; + case 2: req.TaskType = MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET; break; + case 3: req.TaskType = MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET; break; + case 4: req.TaskType = MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET; break; + case 5: req.TaskType = MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK; break; + case 6: req.TaskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK; break; + } + req.LUN[1] = lun; + + setName(port, bus, target, &req); + + if (type == 5) + printf("\nSending Query Task...\n"); + else if (type == 6) + printf("\nSending Abort Task...\n"); + else + printf("\nResetting target...\n"); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, RESET_TIME); +} + + +int +doClearAca(MPT_PORT *port) +{ + SCSITaskMgmt_t req; + SCSITaskMgmtReply_t rep; + int bus; + int target; + int lun; + + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SCSI_TASK_MGMT; + req.TaskType = MPI_SCSITASKMGMT_TASKTYPE_CLR_ACA; + req.LUN[1] = lun; + + setName(port, bus, target, &req); + + printf("\nClearing ACA...\n"); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doBeacon(MPT_PORT *port, int on_off) +{ + ToolboxBeaconRequest_t req; + ToolboxReply_t rep; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_TOOLBOX; + req.Tool = MPI_TOOLBOX_BEACON_TOOL; + req.ConnectNum = 0; + req.Flags = on_off ? MPI_TOOLBOX_FLAGS_BEACON_MODE_ON : MPI_TOOLBOX_FLAGS_BEACON_MODE_OFF; + + printf("Turning beacon %s...\n", on_off ? "on" : "off"); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doDisplaySfpPages(MPT_PORT *port) +{ + ToolboxIstwiReadWriteRequest_t req; + ToolboxReply_t rep; + unsigned char buf[256]; + int i; + int j; + char c[16]; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_TOOLBOX; + req.Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL; + req.Flags = MPI_TB_ISTWI_FLAGS_READ; + req.NumAddressBytes = 1; + req.DataLength = set16(sizeof buf); + + req.DeviceAddr = 0xa0; + + printf("Reading SFP Page 0 (ISTWI address A0)...\n"); + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf, sizeof buf, NULL, 0, SHORT_TIME) == 1) + { + printf("\n"); + for (i = 0, j = 0; i < sizeof buf; i++, j++) + { + if (j == 0) + printf("%04x : ", i); + + printf("%02x ", buf[i]); + + if (!isprint(buf[i])) + c[j] = ' '; + else + c[j] = buf[i]; + + if (j == sizeof c - 1) + { + printf(" "); + for (j = 0; j < sizeof c; j++) + { + printf("%c", c[j]); + } + printf("\n"); + j = -1; + } + if (i == 127) + break; // last part is unused (reserved) + } + } + + printf("\n"); + + req.DeviceAddr = 0xa2; + + printf("Reading SFP Page 1 (ISTWI address A2)...\n"); + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf, sizeof buf, NULL, 0, SHORT_TIME) == 1) + { + printf("\n"); + for (i = 0, j = 0; i < sizeof buf; i++, j++) + { + if (j == 0) + printf("%04x : ", i); + + printf("%02x ", buf[i]); + + if (!isprint(buf[i])) + c[j] = ' '; + else + c[j] = buf[i]; + + if (j == sizeof c - 1) + { + printf(" "); + for (j = 0; j < sizeof c; j++) + { + printf("%c", c[j]); + } + printf("\n"); + j = -1; + } + } + } + + return 1; +} + + +int +doClean(MPT_PORT *port) +{ + ToolboxCleanRequest_t req; + ToolboxReply_t rep; + int type; + int flags; + char name[256]; + FILE *file; + int n; + int t; + + while (TRUE) + { + printf(" 1. NVSRAM\n"); + printf(" 2. SEEPROM\n"); + printf(" 3. FLASH\n"); + printf(" 4. BootLoader\n"); + printf(" 5. Firmware (backup copy)\n"); + printf(" 6. Firmware (current copy)\n"); + printf(" 7. Persistent non-manufacturing config pages\n"); + printf(" 8. Persistent manufacturing config pages\n"); + printf(" 9. Boot services (BIOS/FCode)\n"); + printf("\nSelect what to erase: [1-9 or RETURN to quit] "); + type = getNumberAnswer(1, 9, 0); + if (type == 0) + return 1; + + switch(type) + { + case 1: flags = MPI_TOOLBOX_CLEAN_NVSRAM; break; + case 2: flags = MPI_TOOLBOX_CLEAN_SEEPROM; break; + case 3: flags = MPI_TOOLBOX_CLEAN_FLASH; break; + case 4: flags = MPI_TOOLBOX_CLEAN_BOOTLOADER; break; + case 5: flags = MPI_TOOLBOX_CLEAN_FW_BACKUP; break; + case 6: flags = MPI_TOOLBOX_CLEAN_FW_CURRENT; break; + case 7: flags = MPI_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES; break; + case 8: flags = MPI_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES; break; + case 9: flags = MPI_TOOLBOX_CLEAN_BOOT_SERVICES; break; + default: flags = 0; break; + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC && + flags == MPI_TOOLBOX_CLEAN_SEEPROM) + { + ManufacturingPage0_t ManufacturingPage0; + ManufacturingPage3_t *ManufacturingPage3; + int length; + U32 *p; + U32 wwnn_l; + U32 wwnn_h; + U32 wwpn_l; + U32 wwpn_h; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, + &ManufacturingPage0, sizeof ManufacturingPage0) == 1) + { + printf("\n"); + printf("BoardName = %-16s\n", ManufacturingPage0.BoardName); + printf("BoardAssembly = %-16s\n", ManufacturingPage0.BoardAssembly); + printf("BoardTracerNumber = %-16s\n", ManufacturingPage0.BoardTracerNumber); + + ManufacturingPage3 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 3, 0, &length); + if (ManufacturingPage3 != NULL) + { + p = (U32 *)ManufacturingPage3 + 2; + + wwnn_l = get32x(p[2]); + wwnn_h = get32x(p[3]); + wwpn_l = get32x(p[0]); + wwpn_h = get32x(p[1]); + + printf("FC WWNN = %08x%08x\n", wwnn_h, wwnn_l); + printf("FC WWPN = %08x%08x\n", wwpn_h, wwpn_l); + + if (numFileNames) + { + n = getFileName(name, sizeof name, stdin, "board identity", 0); + } + else + { + printf("\nEnter board identity filename, or RETURN for none: "); + n = getString(name, sizeof name, stdin); + } + if (n > 0) + { + file = fopen(name, "w"); + if (file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + } + else + { + fprintf(file, "BoardName = %-16s\n", ManufacturingPage0.BoardName); + fprintf(file, "BoardAssembly = %-16s\n", ManufacturingPage0.BoardAssembly); + fprintf(file, "BoardTracerNumber = %-16s\n", ManufacturingPage0.BoardTracerNumber); + fprintf(file, "FC WWNN = %08x%08x\n", wwnn_h, wwnn_l); + fprintf(file, "FC WWPN = %08x%08x\n", wwpn_h, wwpn_l); + fclose(file); + } + } + + free (ManufacturingPage3); + } + } + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS && + flags == MPI_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES) + { + ManufacturingPage0_t ManufacturingPage0; + ManufacturingPage5_t *ManufacturingPage5; + Mpi2ManufacturingPage5_t *ManufacturingPage5_2; + U32 wwid_l; + U32 wwid_h; + int length; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, + &ManufacturingPage0, sizeof ManufacturingPage0) == 1) + { + printf("\n"); + printf("BoardName = %-16s\n", ManufacturingPage0.BoardName); + printf("BoardAssembly = %-16s\n", ManufacturingPage0.BoardAssembly); + printf("BoardTracerNumber = %-16s\n", ManufacturingPage0.BoardTracerNumber); + + ManufacturingPage5 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 5, 0, + &length); + if (ManufacturingPage5) + { + ManufacturingPage5_2 = (pMpi2ManufacturingPage5_t)ManufacturingPage5; + + if (mpi2) + { + wwid_l = get32(ManufacturingPage5_2->Phy[0].WWID.Low); + wwid_h = get32(ManufacturingPage5_2->Phy[0].WWID.High); + } + else + { + wwid_l = get32(ManufacturingPage5->BaseWWID.Low); + wwid_h = get32(ManufacturingPage5->BaseWWID.High); + } + + free (ManufacturingPage5); + + printf("SAS WWID = %08x%08x\n", wwid_h, wwid_l); + + if (numFileNames) + { + n = getFileName(name, sizeof name, stdin, "board identity", 0); + } + else + { + printf("\nEnter board identity filename, or RETURN for none: "); + n = getString(name, sizeof name, stdin); + } + if (n > 0) + { + file = fopen(name, "w"); + if (file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + } + else + { + fprintf(file, "BoardName = %-16s\n", ManufacturingPage0.BoardName); + fprintf(file, "BoardAssembly = %-16s\n", ManufacturingPage0.BoardAssembly); + fprintf(file, "BoardTracerNumber = %-16s\n", ManufacturingPage0.BoardTracerNumber); + fprintf(file, "SAS WWID = %08x%08x\n", wwid_h, wwid_l); + fclose(file); + } + } + } + } + } + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_TOOLBOX; + req.Tool = MPI_TOOLBOX_CLEAN_TOOL; + req.Flags = set32(flags); + + printf("\nErasing...\n"); + + t = doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, LONG_TIME); + + if (t != 1) + printf("\nErase failed\n"); + + if (wFlag) + fprintf(logFile, "%s: Erase (TOOLBOX CLEAN_TOOL) of type %d: %s\n", + logPrefix(port), type, t ? "PASS" : "FAIL"); + + printf("\n"); + } +} + + +int +doFcManagementTools(MPT_PORT *port) +{ + ToolboxFcManageRequest_t req; + ToolboxFcManageReply_t rep; + int type; + int bus; + int target; + int portid; + int index; + int flags; + int count; + int period; + int temp[4]; + int t; + + if (bringOnline(port) != 1) + return 0; + + while (TRUE) + { + printf(" 1. Discover all targets\n"); + printf(" 2. Discover one target by PortId\n"); + printf(" 3. Discover one target by Bus/Target\n"); + printf(" 4. Set maximum frame size\n"); + printf(" 5. Log out target by PortId\n"); + printf(" 6. Log out target by Bus/Target\n"); + printf(" 7. Set login parameters\n"); + printf(" 8. Get login parameters\n"); + t = 8; + if (virtInit == 0) + { + printf(" 9. Create a virtual port\n"); + printf("10. Delete a virtual port\n"); + t = 10; + } + printf("\nSelect a tool: [1-%d or RETURN to quit] ", t); + type = getNumberAnswer(1, t, 0); + if (type == 0) + return 1; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_TOOLBOX; + req.Tool = MPI_TOOLBOX_FC_MANAGEMENT_TOOL; + req.AliasIndex = virtInit; + + switch(type) + { + case 1: + printf("\nDiscovering all targets...\n"); + req.Action = MPI_TB_FC_MANAGE_ACTION_DISC_ALL; + break; + + case 2: + printf("PortId: [000000-FFFFFF or RETURN to quit] "); + portid = getNumberAnswerHex(0x000000, 0xffffff, -1); + if (portid < 0) + return 1; + + printf("\nDiscovering PortId %06x...\n", portid); + req.Action = MPI_TB_FC_MANAGE_ACTION_DISC_PID; + req.ActionInfo.Port.PortIdentifier = set32(portid); + break; + + case 3: + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("\nDiscovering Bus %d Target %d...\n", bus, target); + req.Action = MPI_TB_FC_MANAGE_ACTION_DISC_BUS_TID; + req.ActionInfo.BusTid.Bus = bus; + req.ActionInfo.BusTid.TargetId = target; + break; + + case 4: + printf("Maximum frame size: [128-2048 or RETURN to quit] "); + t = getNumberAnswer(128, 2048, -1); + if (t < 0) + return 1; + + printf("\nSetting maximum frame size to %d...\n", t); + req.Action = MPI_TB_FC_MANAGE_ACTION_SET_MAX_FRAME_SIZE; + req.ActionInfo.FrameSize.FrameSize = set16(t); + break; + + case 5: + printf("PortId: [000000-FFFFFF or RETURN to quit] "); + portid = getNumberAnswerHex(0x000000, 0xffffff, -1); + if (portid < 0) + return 1; + + printf("Keep this target logged out? [Yes or No, default is No] "); + flags = getYesNoAnswer(0) == 1 ? MPI_TB_FC_MANAGE_FLAGS_KEEP_LOGGED_OUT : 0; + + printf("\nLogging out PortId %06x...\n", portid); + req.Action = MPI_TB_FC_MANAGE_ACTION_LOGOUT_PID; + req.ActionInfo.Port.PortIdentifier = set32(portid); + req.Flags = flags; + break; + + case 6: + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("Keep this target logged out? [Yes or No, default is No] "); + flags = getYesNoAnswer(0) == 1 ? MPI_TB_FC_MANAGE_FLAGS_KEEP_LOGGED_OUT : 0; + + printf("\nLogging out Bus %d Target %d...\n", bus, target); + req.Action = MPI_TB_FC_MANAGE_ACTION_LOGOUT_BUS_TID; + req.ActionInfo.BusTid.Bus = bus; + req.ActionInfo.BusTid.TargetId = target; + req.Flags = flags; + break; + + case 7: + printf("Number of PLOGI attempts: [1-255 or 0 for default or RETURN to quit] "); + count = getNumberAnswer(0, 255, -1); + if (count < 0) + return 1; + + printf("Seconds between PLOGI attempts: [1-255 or 0 for default or RETURN to quit] "); + period = getNumberAnswer(0, 255, -1); + if (period < 0) + return 1; + + printf("Maximum FLOGI burst: [1-255 or 0 for default or RETURN to quit] "); + temp[0] = getNumberAnswer(0, 255, -1); + if (temp[0] < 0) + return 1; + + printf("Percent of resources for FLOGI: [1-99 or 0 for default or RETURN to quit] "); + temp[1] = getNumberAnswer(0, 99, -1); + if (temp[1] < 0) + return 1; + + printf("Maximum PLOGI burst: [1-255 or 0 for default or RETURN to quit] "); + temp[2] = getNumberAnswer(0, 255, -1); + if (temp[2] < 0) + return 1; + + printf("Percent of resources for PLOGI: [1-99 or 0 for default or RETURN to quit] "); + temp[3] = getNumberAnswer(0, 99, -1); + if (temp[3] < 0) + return 1; + + printf("\nSetting login parameters...\n"); + req.Action = MPI_TB_FC_MANAGE_ACTION_SET_LOGIN_PARAMS; + req.ActionInfo.LoginParams.Count = count; + req.ActionInfo.LoginParams.Period = period; + req.ActionInfo.LoginParams.FlogiBurst = temp[0]; + req.ActionInfo.LoginParams.FlogiExchanges = temp[1]; + req.ActionInfo.LoginParams.PlogiBurst = temp[2]; + req.ActionInfo.LoginParams.PlogiExchanges = temp[3]; + break; + + case 8: + printf("\nGetting login parameters...\n"); + req.Action = MPI_TB_FC_MANAGE_ACTION_GET_LOGIN_PARAMS; + break; + + case 9: + printf("\nCreating VP...\n"); + req.Action = MPI_TB_FC_MANAGE_ACTION_CREATE_VP; + req.Flags = MPI_TB_FC_MANAGE_FLAGS_AUTO_RETRY; + break; + + case 10: + printf("VP to delete: [1-125 or RETURN to quit] "); + index = getNumberAnswer(1, 125, -1); + if (index < 0) + return 1; + + printf("\nDeleting VP %d...\n", index); + req.Action = MPI_TB_FC_MANAGE_ACTION_DELETE_VP; + req.AliasIndex = index; + break; + } + + if (doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, + NULL, 0, NULL, 0, LONG_TIME) != 1) + { + printf("FcManagment tool failed\n"); + } + else if (type == 8) + { + printf("\nNumber of PLOGI attempts: %d\n", + rep.ActionInfo.LoginParams.Count); + printf("Seconds between PLOGI attempts: %d\n", + rep.ActionInfo.LoginParams.Period); + printf("Maximum FLOGI burst: %d\n", + rep.ActionInfo.LoginParams.FlogiBurst); + printf("Percent of resources for FLOGI: %d\n", + rep.ActionInfo.LoginParams.FlogiExchanges); + printf("Maximum PLOGI burst: %d\n", + rep.ActionInfo.LoginParams.PlogiBurst); + printf("Percent of resources for PLOGI: %d\n", + rep.ActionInfo.LoginParams.PlogiExchanges); + } + else if (type == 9) + { + printf("\nVP %d created, PortId = %06x, WWNN = %08x%08x, WWPN = %08x%08x\n", + rep.AliasIndex, get32(rep.ActionInfo.CreateVp.PortIdentifier), + get32(rep.ActionInfo.CreateVp.WWNN.High), get32(rep.ActionInfo.CreateVp.WWNN.Low), + get32(rep.ActionInfo.CreateVp.WWPN.High), get32(rep.ActionInfo.CreateVp.WWPN.Low)); + } + + printf("\n"); + } +} + + +int +doRemoveSasDevice(MPT_PORT *port) +{ + SasIoUnitControlRequest_t req; + SasIoUnitControlReply_t rep; + int handle; + + printf("Enter the DevHandle to remove: [0000-FFFF or RETURN to quit] "); + handle = getNumberAnswerHex(0x0000, 0xffff, -1); + if (handle < 0) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; + req.Operation = MPI_SAS_OP_REMOVE_DEVICE; + req.DevHandle = set16(handle); + + printf("\nRemoving SAS DevHandle %04x...\n", handle); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doDisplayLogEntries(MPT_PORT *port) +{ + LogPage0_t *LogPage0; + Mpi2LogPage0_t *LogPage0_2; + int length; + int i; + int j; + int k; + int n; + U32 *p; + int dataLen; + int decodeTime; + char timeString[64]; + time_t timestamp; + + decodeTime = FALSE; + if (mpi2 && gFlag == TRUE) + { + printf("\nDo you want to decode timestamps? [Yes or No, default is Yes] "); + if (getYesNoAnswer(1) == 1) + decodeTime = TRUE; + } + + LogPage0 = getConfigPageAlloc(port, MPI_CONFIG_EXTPAGETYPE_LOG, 0, 0, &length); + if (LogPage0 == NULL) + return 0; + + LogPage0_2 = (pMpi2LogPage0_t)LogPage0; + + n = get16(LogPage0->NumLogEntries); + + printf("%d Log entr%s found\n", n, n == 1 ? "y" : "ies"); + + if (n) + { + printf("\n"); + if (mpi2) + { + dataLen = MPI2_LOG_0_LOG_DATA_LENGTH; + if (decodeTime) + printf("SeqN Type Time Data\n"); + else + printf("SeqN Type Time Data\n"); + } + else + { + dataLen = MPI_LOG_0_LOG_DATA_LENGTH; + printf("SeqN Type Time Data\n"); + } + + for (i = 0; i < n; i++) + { + if (mpi2) + { + p = (U32 *)LogPage0_2->LogEntry[i].LogData; + + if (decodeTime) + { + timestamp = (time_t)(((uint64_t)get64(LogPage0_2->LogEntry[i].TimeStamp)) / 1000); + strcpy(timeString, ctime(×tamp)); + timeString[strlen(timeString) - 1] = '\0'; + printf("%04x %04x [%s]", + get16(LogPage0_2->LogEntry[i].LogSequence), + get16(LogPage0_2->LogEntry[i].LogEntryQualifier), + timeString); + } + else + { + printf("%04x %04x %08x%08x", + get16(LogPage0_2->LogEntry[i].LogSequence), + get16(LogPage0_2->LogEntry[i].LogEntryQualifier), + get32(LogPage0_2->LogEntry[i].TimeStamp.High), + get32(LogPage0_2->LogEntry[i].TimeStamp.Low)); + } + } + else + { + p = (U32 *)LogPage0->LogEntry[i].LogData; + printf("%04x %04x %08x", + get16(LogPage0->LogEntry[i].LogSequence), + get16(LogPage0->LogEntry[i].LogEntryQualifier), + get32(LogPage0->LogEntry[i].TimeStamp)); + } + + for (k = dataLen / 4 - 1; k > 0; k--) + if (p[k] != 0) + break; + for (j = 0; j <= k; j++) + printf(" %08x", get32x(p[j])); + printf("\n"); + } + } + + free(LogPage0); + + return 0; +} + + +int +doClearLogEntries(MPT_PORT *port) +{ + LogPage0_t *LogPage0; + int length; + int n; + + LogPage0 = getConfigPageAlloc(port, MPI_CONFIG_EXTPAGETYPE_LOG, 0, 0, &length); + if (LogPage0 == NULL) + return 0; + + n = get16(LogPage0->NumLogEntries); + + printf("%d Log entr%s found, will be cleared\n", n, n == 1 ? "y" : "ies"); + if (yesFlag == FALSE) + { + printf("\nAre you sure you want to continue? [Yes or No, default is Yes] "); + } + + if (yesFlag == TRUE || getYesNoAnswer(1) == 1) + { + LogPage0->NumLogEntries = 0; + + if (setConfigPage(port, MPI_CONFIG_EXTPAGETYPE_LOG, 0, 0, LogPage0, length) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + } + + free(LogPage0); + + return 0; +} + + +int +doSasForceFullDiscovery(MPT_PORT *port) +{ + SasIoUnitControlRequest_t req; + SasIoUnitControlReply_t rep; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; + req.Operation = MPI_SAS_OP_FORCE_FULL_DISCOVERY; + + printf("Forcing full discovery...\n"); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doFirmwareDownloadBoot(MPT_PORT *port) +{ +#if DOS || EFI + HANDLE adap = port->fileHandle; + HANDLE partner_adap = adap->partner_adap; + char name[256]; + int n; + + printf("A valid firmware image can be temporarily loaded into this chip...\n\n"); + + n = getFileName(name, sizeof name, stdin, "firmware", 99); + if (n > 0) + { + if (adap->fw_image != NULL) + { + free(adap->fw_image); + adap->fw_image = NULL; + adap->fw_image_size = 0; + if (partner_adap != NULL) + { + partner_adap->fw_image = NULL; + partner_adap->fw_image_size = 0; + } + } + + if (readFile(name, &adap->fw_image, &adap->fw_image_size) == 1) + { + adap->ioc_online = FALSE; + + if (partner_adap != NULL) + { + partner_adap->ioc_online = FALSE; + + partner_adap->fw_image = adap->fw_image; + } + + if (mpt_fwdownloadboot(adap) == 1) + { + printf("\nThe chip was made operational, remember that this is temporary!\n"); + } + else + { + printf("\nThe chip was not made operational with this firmware!\n"); + mpt_stop(adap, TRUE); + return 0; + } + } + } + else + { + printf("Image won't be download booted\n"); + return 1; + } +#endif + + return 1; +} + + +int +eventQuery(MPT_PORT *port, int *entries, int *types) +{ +#if WIN32 + int len; + int status; + MPI_EVENTS_SRB *srb; + int inLen; + int outLen; + DWORD retLen; + + if (mpi2) + len = sizeof *srb + (sizeof(U32) * 4); + else + len = sizeof *srb + sizeof(U32); + + srb = malloc(len); + + memset(srb, 0, len); + + srb->Sic.Length = len - sizeof srb->Sic; + srb->Sic.ControlCode = DRVR_INFO_IOCTL; + srb->Sic.HeaderLength = sizeof srb->Sic; + srb->Sic.Timeout = SHORT_TIME; + + memcpy((char *)&srb->Sic.Signature, "4.00 ", 8); + + srb->PageCode = EVENT_QUERY; + + inLen = len; + outLen = len; + retLen = 0; + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + srb, inLen, srb, outLen, &retLen, NULL); + + if (status != 1) + { + free(srb); + return 0; + } + + *entries = srb->EventData[0]; + types[0] = srb->EventData[1]; + + if (mpi2) + { + types[1] = srb->EventData[2]; + types[2] = srb->EventData[3]; + types[3] = srb->EventData[4]; + } + + free(srb); +#endif +#if __linux__ + struct mpt2_ioctl_eventquery eventquery; + int status; + + memset(&eventquery, 0, sizeof eventquery); + + if (mpi2) + eventquery.hdr.max_data_size = sizeof (struct mpt2_ioctl_eventquery); + else + eventquery.hdr.max_data_size = sizeof (struct mpt_ioctl_eventquery); + + eventquery.hdr.ioc_number = port->portNumber; + + if (mpi2) + status = ioctl(port->fileHandle, MPT2EVENTQUERY, &eventquery); + else + status = ioctl(port->fileHandle, MPTEVENTQUERY, &eventquery); + + if (status != 0) + return 0; + + *entries = eventquery.event_entries; + types[0] = eventquery.event_types[0]; + + if (mpi2) + { + types[1] = eventquery.event_types[1]; + types[2] = eventquery.event_types[2]; + types[3] = eventquery.event_types[3]; + } +#endif +#if __sparc__ + int status; + mptsas_event_query_t eventquery; + + if (mpi2) + status = ioctl(port->fileHandle, MPTIOCTL_EVENT_QUERY, &eventquery); + else + status = ioctl(port->fileHandle, SYMIOCTL_EVENT_QUERY, &eventquery); + + if (status != 0) + return 0; + + if (mpi2) + { + *entries = eventquery.Entries; + types[0] = eventquery.Types[0]; + types[1] = eventquery.Types[1]; + types[2] = eventquery.Types[2]; + types[3] = eventquery.Types[3]; + } + else + { + /* Entries was a U32 (now a U16) in the gen1 data structure, so cast it here to + * avoid any endian problems + */ + *entries = *(U32 *)&(eventquery.Entries); + types[0] = eventquery.Types[0]; + } + +#endif + + return 1; +} + + +int +eventEnable(MPT_PORT *port, int *types) +{ +#if WIN32 + int len; + int status; + MPI_EVENTS_SRB *srb; + int inLen; + int outLen; + DWORD retLen; + + if (mpi2) + len = sizeof *srb + (sizeof(U32) * 3); + else + len = sizeof *srb; + + srb = malloc(len); + + memset(srb, 0, len); + + srb->Sic.Length = len - sizeof srb->Sic; + srb->Sic.ControlCode = DRVR_INFO_IOCTL; + srb->Sic.HeaderLength = sizeof srb->Sic; + srb->Sic.Timeout = SHORT_TIME; + + memcpy((char *)&srb->Sic.Signature, "4.00 ", 8); + + srb->PageCode = EVENT_ENABLE; + srb->EventData[0] = types[0]; + + if (mpi2) + { + srb->EventData[1] = types[1]; + srb->EventData[2] = types[2]; + srb->EventData[3] = types[3]; + } + + inLen = len; + outLen = len; + retLen = 0; + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + srb, inLen, srb, outLen, &retLen, NULL); + + free(srb); + + if (status != 1) + return 0; +#endif +#if __linux__ + struct mpt2_ioctl_eventenable eventenable; + int status; + + memset(&eventenable, 0, sizeof eventenable); + + eventenable.event_types[0] = types[0]; + eventenable.hdr.ioc_number = port->portNumber; + + if (mpi2) + { + eventenable.event_types[1] = types[1]; + eventenable.event_types[2] = types[2]; + eventenable.event_types[3] = types[3]; + eventenable.hdr.max_data_size = sizeof (struct mpt2_ioctl_eventenable); + } + else + eventenable.hdr.max_data_size = sizeof (struct mpt_ioctl_eventenable); + + if (mpi2) + status = ioctl(port->fileHandle, MPT2EVENTENABLE, &eventenable); + else + status = ioctl(port->fileHandle, MPTEVENTENABLE, &eventenable); + + if (status != 0) + return 0; +#endif +#if __sparc__ + int status; + mptsas_event_enable_t eventenable; + + eventenable.Types[0] = types[0]; + + if (mpi2) + { + eventenable.Types[1] = types[1]; + eventenable.Types[2] = types[2]; + eventenable.Types[3] = types[3]; + status = ioctl(port->fileHandle, MPTIOCTL_EVENT_ENABLE, &eventenable); + } + else + status = ioctl(port->fileHandle, SYMIOCTL_EVENT_ENABLE, &eventenable); + + + if (status != 0) + return 0; +#endif + + + return 1; +} + + +int +eventReport(MPT_PORT *port, int entries, EVENT2 *events) +{ +#if WIN32 + int len; + int status; + MPI_EVENTS_SRB *srb; + int inLen; + int outLen; + DWORD retLen; + + len = sizeof *srb - sizeof srb->EventData + (mpi2 ? sizeof(EVENT2) : sizeof(EVENT)) * entries; + + srb = malloc(len); + + memset(srb, 0, len); + + srb->Sic.Length = len - sizeof srb->Sic; + srb->Sic.ControlCode = DRVR_INFO_IOCTL; + srb->Sic.HeaderLength = sizeof srb->Sic; + srb->Sic.Timeout = SHORT_TIME; + + memcpy((char *)&srb->Sic.Signature, "4.00 ", 8); + + srb->PageCode = GET_EVENTS; + + inLen = len; + outLen = len; + retLen = 0; + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + srb, inLen, srb, outLen, &retLen, NULL); + + if (status != 1) + { + free(srb); + return 0; + } + + if (mpi2) + { + memcpy(events, srb->EventData, entries * sizeof *events); + } + else + { + EVENT *events1 = (EVENT *)srb->EventData; + int i; + + memset(events, 0, entries * sizeof *events); + for (i = 0; i < entries; i++) + { + memcpy(events + i, events1 + i, sizeof(EVENT)); + } + } + + free(srb); +#endif +#if __linux__ + struct mpt_ioctl_eventreport *eventreport; + int len; + int status; + + len = sizeof *eventreport - sizeof eventreport->eventData + (mpi2 ? sizeof(EVENT2) : sizeof(EVENT)) * entries; + + eventreport = (struct mpt_ioctl_eventreport *)malloc(len); + + memset(eventreport, 0, len); + + eventreport->hdr.maxDataSize = len; + eventreport->hdr.iocnum = port->portNumber; + + if (mpi2) + status = ioctl(port->fileHandle, MPT2EVENTREPORT, eventreport); + else + status = ioctl(port->fileHandle, MPTEVENTREPORT, eventreport); + + if (status != 0) + { + free(eventreport); + return 0; + } + + if (mpi2) + { + memcpy(events, eventreport->eventData, entries * sizeof *events); + } + else + { + EVENT *events1 = (EVENT *)eventreport->eventData; + int i; + + memset(events, 0, entries * sizeof *events); + for (i = 0; i < entries; i++) + { + memcpy(events + i, events1 + i, sizeof(EVENT)); + } + } + + free(eventreport); +#endif +#if __sparc__ + int len; + int status; + SYM_EVENT_REPORT *eventreport; + + len = sizeof *eventreport - sizeof eventreport->Events + (mpi2 ? sizeof(EVENT2) : sizeof(EVENT)) * entries; + + eventreport = malloc(len); + + memset(eventreport, 0, len); + + eventreport->Size = len; + + if (mpi2) + status = ioctl(port->fileHandle, MPTIOCTL_EVENT_REPORT, eventreport); + else + status = ioctl(port->fileHandle, SYMIOCTL_EVENT_REPORT, eventreport); + + if (status != 0) + return 0; + + if (mpi2) + { + memcpy(events, eventreport->Events, entries * sizeof *events); + } + else + { + EVENT *events1 = (EVENT *)eventreport->Events; + int i; + + memset(events, 0, entries * sizeof *events); + for (i = 0; i < entries; i++) + { + memcpy(events + i, events1 + i, sizeof(EVENT)); + } + } + + free(eventreport); +#endif + + return 1; +} + + +int +doDisplayCurrentEvents(MPT_PORT *port) +{ + int entries; + int types[4] = { 0, 0, 0, 0 }; + EVENT2 *events; + int i; + int j; + int k; + int l; + int n; + int t; + + if (eventQuery(port, &entries, types) != 1) + { + printf("Failed to query events!\n"); + return 0; + } + + if ( (types[0] != 0xffffffff) || + (mpi2 && ((types[1] != 0xffffffff) || + (types[2] != 0xffffffff) || + (types[3] != 0xffffffff))) ) + { + memset(types, 0xffffffff, sizeof(types)); + if (eventEnable(port, types) != 1) + { + printf("Failed to enable events!\n"); + return 0; + } + + if (eventQuery(port, &entries, types) != 1) + { + printf("Failed to query events!\n"); + return 0; + } + + if (entries < 1) + return 0; + + port->lastEvent = -1; + } + + events = malloc(entries * sizeof *events); + + memset(events, 0, sizeof *events); + + if (eventReport(port, entries, events) != 1) + return 0; + + for (j = 0; j < entries - 1; j++) + { + if (events[j].number > events[j+1].number) + { + j++; + break; + } + } + + printf("Sequence Event Event Data\n"); + for (i = 0; i < entries; i++) + { + k = (i + j) % entries; + if (events[k].type) + { + t = events[k].number; + + if (port->lastEvent < t) + { + for (n = 47; n >= 2; n--) + if (events[k].data[n] != 0) + break; + printf("%08x %2x ", events[k].number, events[k].type); + for (l = 0; l <= n; l++) + printf(" %08x", events[k].data[l]); + printf("\n"); + + port->lastEvent = t; + } + } + } + + return 1; +} + + +int +doDisplayTransferStatistics(MPT_PORT *port) +{ + ConfigReply_t rep; + FCPortPage6_t FCPortPage6; + int i; + + if (getConfigPageHeader(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &rep) != 1) + return 0; + + FCPortPage6.Header = rep.Header; + + printf("Port Name Tx Frames Rx Frames Tx MB Rx MB Total MB\n\n"); + + for (i = 0; i < 10; i++) + { + setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &FCPortPage6, sizeof FCPortPage6); + + sleep(1); + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &FCPortPage6, sizeof FCPortPage6) == 1) + { +#if !EFIEBC + double time; + double tx_frames; + double rx_frames; + double tx_words; + double rx_words; + + time = (int64_t)get64(FCPortPage6.TimeSinceReset) / 1000000.; + + tx_frames = (int64_t)get64(FCPortPage6.TxFrames) / time; + rx_frames = (int64_t)get64(FCPortPage6.RxFrames) / time; + + tx_words = (int64_t)get64(FCPortPage6.TxWords) * 4. / time / 1000000.; + rx_words = (int64_t)get64(FCPortPage6.RxWords) * 4. / time / 1000000.; + + printf("%-16s %8.0f %8.0f %8.2f %8.2f %8.2f\n", + port->portName, tx_frames, rx_frames, tx_words, rx_words, tx_words + rx_words); +#endif + } + } + + return 1; +} + + +int +doDisplayTransferStatisticsAll(int numPorts, MPT_PORT *ports[], int interval, int duration) +{ + MPT_PORT *port; + ConfigReply_t rep; + FCPortPage6_t FCPortPage6; + int i; + int n; + int p; + + n = 0; + for (i = 0; i < numPorts; i++) + { + port = ports[i]; + if (port) + { + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (getConfigPageHeader(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &rep) == 1) + n++; + else + { + printf("%s can't be monitored, failed to read FCPortPage6\n", port->portName); + ports[i] = NULL; + } + } + else + { + printf("%s can't be monitored, only FC ports implement performance counters\n", port->portName); + ports[i] = NULL; + } + } + } + if (n == 0) + { + printf("There are no eligible ports to monitor!\n"); + return 0; + } + + FCPortPage6.Header = rep.Header; + + p = 0; + + while (TRUE) + { + for (i = 0; i < numPorts; i++) + { + port = ports[i]; + if (port) + { + setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &FCPortPage6, sizeof FCPortPage6); + } + } + + sleep(interval); + + if (p == 0) + printf("\nPort Name Tx Frames Rx Frames Tx MB Rx MB Total MB\n\n"); + if (n == 1) + { + p++; + if (p >= 10) + p = 0; + } + + for (i = 0; i < numPorts; i++) + { + port = ports[i]; + if (port) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, &FCPortPage6, sizeof FCPortPage6) == 1) + { +#if !EFIEBC + double time; + double tx_frames; + double rx_frames; + double tx_words; + double rx_words; + + time = (int64_t)get64(FCPortPage6.TimeSinceReset) / 1000000.; + + tx_frames = (int64_t)get64(FCPortPage6.TxFrames) / time; + rx_frames = (int64_t)get64(FCPortPage6.RxFrames) / time; + + tx_words = (int64_t)get64(FCPortPage6.TxWords) * 4. / time / 1000000.; + rx_words = (int64_t)get64(FCPortPage6.RxWords) * 4. / time / 1000000.; + + printf("%-16s %8.0f %8.0f %8.2f %8.2f %8.2f\n", + port->portName, tx_frames, rx_frames, tx_words, rx_words, tx_words + rx_words); +#endif + } + } + } + + if (duration) + { + duration -= interval; + if (duration <= 0) + break; + } + } + + return 1; +} + + +int +isRaidVolume(MPT_PORT *port, int bus, int target) +{ + IOCPage2_t *IOCPage2; + int length; + int i; + int ioc = port->iocNumber; + + if (mpi2) + return isRaidVolume2(port, bus, target); + + IOCPage2 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_IOC, 2, 0, &length); + if (IOCPage2 == NULL || IOCPage2->MaxVolumes == 0 || IOCPage2->NumActiveVolumes == 0) + { + if (IOCPage2) + free(IOCPage2); + return 0; + } + + for (i = 0; i < IOCPage2->NumActiveVolumes; i++) + { + if (bus == IOCPage2->RaidVolume[i].VolumeBus && + target == IOCPage2->RaidVolume[i].VolumeID && + ioc == IOCPage2->RaidVolume[i].VolumeIOC) + { + free(IOCPage2); + return 1; + } + } + + free(IOCPage2); + + return 0; +} + + +int +isRaidVolume2(MPT_PORT *port, int bus, int target) +{ + int handle; + + if (!mapBusTargetToDevHandle(port, bus, target, &handle)) + return 0; + + return getRaidConfig(port, MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT, handle, -1, NULL); +} + + +#if WIN32 || __linux__ || __sparc__ + + +#if __linux__ +void +convertBusTarget(MPT_PORT *port, int *bus, int *target, int lun) +{ + char pathName[PATH_MAX]; + char linkName[PATH_MAX]; + char pathName2[PATH_MAX]; + char linkName2[PATH_MAX]; + int n; + int n2; + int i; + int j; + DIR *dirp; + struct dirent *direntp = NULL; + FCDevicePage0_t FCDevicePage0; + SasDevicePage0_t SASDevicePage0; + FILE *filep; + char deviceName[64]; + char deviceName2[64]; + char *p; + int t1; + int t2; + int t3; + int t4; + char matchName[64]; + char *typeString; + char *nameString; + int b_t; + int dev_handle; + int address; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, + MPI_FC_DEVICE_PGAD_FORM_BUS_TID + (*bus << 8) + *target, + &FCDevicePage0, sizeof FCDevicePage0) != 1) + return; + + i = sprintf(deviceName, "0x%08x%08x\n", + get32(FCDevicePage0.WWPN.High), get32(FCDevicePage0.WWPN.Low)); + + j = sprintf(matchName, "target%d:", port->hostNumber); + + typeString = "fc_transport"; + nameString = "port_name"; + } + + else if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (mpi1 && *bus == 0 && lun == 0 && isRaidVolume(port, *bus, *target)) + { + *bus = 1; + + return; + } + + if (mpi2) + { + if (mapBusTargetToDevHandle(port, *bus, *target, &dev_handle) != 1) + dev_handle = 0; + address = MPI2_SAS_DEVICE_PGAD_FORM_HANDLE + dev_handle; + } + else + { + b_t = (*bus << 8) + *target; + address = (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID + <hostNumber); + + typeString = "sas_device"; + nameString = "sas_address"; + } + + else + return; + + sprintf(pathName, "/sys/class/%s/", typeString); + dirp = opendir(pathName); + while (dirp) + { + direntp = readdir(dirp); + if (!direntp) + break; + if (strncmp(direntp->d_name, matchName, j) == 0) + { + sprintf(pathName, + "/sys/class/%s/%s/%s", + typeString, direntp->d_name, nameString); + + filep = fopen(pathName, "r"); + if (filep) + { + p = fgets(deviceName2, sizeof deviceName2, filep); + fclose(filep); + + if (p) + { + if (memcmp(deviceName, deviceName2, i) == 0) + { + closedir(dirp); + + sprintf(pathName, + "/sys/class/%s/%s/device", + typeString, direntp->d_name); + + n = readlink(pathName, linkName, sizeof linkName); + if (n > 0) + { + dirp = opendir("/sys/class/scsi_device/"); + while (dirp) + { + direntp = readdir(dirp); + if (!direntp) + break; + + sprintf(pathName2, + "/sys/class/scsi_device/%s/device", + direntp->d_name); + + memset(linkName2, 0, sizeof linkName2); + n2 = readlink(pathName2, linkName2, sizeof linkName2); + if (n2 > 0) + { + if (memcmp(linkName, linkName2, n) == 0) + { +// printf("matched SCSI %s with MPT %d/%d/%d/%d\n", +// direntp->d_name, port->hostNumber, *bus, *target, lun); + + sscanf(direntp->d_name, "%d:%d:%d:%d", &t1, bus, target, &t2); + + closedir(dirp); + return; + } + } + } + + if (dirp) + closedir(dirp); + } + + dirp = opendir(pathName); + while (dirp) + { + direntp = readdir(dirp); + if (!direntp) + break; + n = sscanf(direntp->d_name, "%d:%d:%d:%d", &t1, &t2, &t3, &t4); + if (n == 4 && t1 == port->hostNumber) + { + *bus = t2; + *target = t3; + closedir(dirp); + return; + } + n = sscanf(direntp->d_name, "target%d:%d:%d", &t1, &t2, &t3); + if (n == 3 && t1 == port->hostNumber) + { + *bus = t2; + *target = t3; + closedir(dirp); + return; + } + } + if (dirp) + closedir(dirp); + + return; + } + } + } + } + } + + if (dirp) + closedir(dirp); +} +#endif + + +#if __sparc__ +void +cachePathLinks(char *prefix, char *suffix, NAME_LINK **cacheOut, int *countOut) +{ + char *p; + char *q; + int n; + int count; + int limit; + DIR *dirp; + struct dirent *direntp; + char pathName[PATH_MAX]; + char linkName[PATH_MAX]; + NAME_LINK *cache; + + limit = 0; + count = 0; + cache = NULL; + + dirp = opendir(prefix); + while (dirp) + { + direntp = readdir(dirp); + if (!direntp) + break; + strcpy(pathName, prefix); + strcat(pathName, direntp->d_name); + n = readlink(pathName, linkName, sizeof linkName); + if (n <= 0) + continue; + linkName[n] = '\0'; + p = strstr(linkName, "/devices"); + if (p) + { + p += 8; + q = strchr(p, ':'); + if (q) + { + if (strcmp(q, suffix) != 0) + continue; + *q = '\0'; + } + if (count == limit) + { + limit += 100; + cache = realloc(cache, limit * sizeof *cache); + } + strcpy(cache[count].name, direntp->d_name); + strcpy(cache[count].link, p); + count++; + } + } + if (dirp) + closedir(dirp); + + *cacheOut = cache; + *countOut = count; +} + + +int +findPathLink(MPT_PORT *port, char *prefix, NAME_LINK *cache, int count, char *path, char *buf) +{ + int i; + int n; + + n = 0; + buf[0] = '\0'; + + for (i = 0; i < count; i++) + { + if (strcmp(path, cache[i].link) == 0) + { + sprintf(buf, "%s%s", prefix, cache[i].name); + n++; + } + } + + return n; +} + + +int +getVhciName(char *phci_buf, char *addr_buf, char *vhci_buf) +{ + sv_iocdata_t ioc; + + bzero(&ioc, sizeof(sv_iocdata_t)); + ioc.phci = phci_buf; + ioc.addr = addr_buf; + ioc.client = vhci_buf; + vhci_buf[0] = '\0'; + + return scsi_vhci_fd >= 0 && ioctl(scsi_vhci_fd, SCSI_VHCI_GET_CLIENT_NAME, &ioc) == 0; +} + + +int +getPortPhyMap(MPT_PORT *port) +{ + Mpi2SasIOUnitPage0_t *SASIOUnitPage0; + int length; + int i; + int j; + + SASIOUnitPage0 = getConfigPageAlloc(port, MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0, &length); + if (SASIOUnitPage0 == NULL) + return 0; + + memset(port->portPhyMap, 0, sizeof port->portPhyMap); + + for (i = 0; i < SASIOUnitPage0->NumPhys; i++) + { + if (SASIOUnitPage0->PhyData[i].AttachedDevHandle) + { + j = SASIOUnitPage0->PhyData[i].Port; + port->portPhyMap[j] |= (1 << i); + } + } + + return 0; +} +#endif + + +int +getOsDeviceName(MPT_PORT *port, int bus, int target, int lun, char *buf, int len, int type) +{ +#if WIN32 + char name[512]; + char *p; + int t; + char device[32]; + HANDLE handle; + DWORD retLen; + SCSI_ADDRESS scsiAddress; + + if (osDeviceState == NULL) + { + t = 4096; + do + { + t *= 2; + if (osDeviceState) + osDeviceState = realloc(osDeviceState, t); + else + osDeviceState = malloc(t); + + QueryDosDevice(NULL, osDeviceState, t); + + } while (GetLastError() == ERROR_INSUFFICIENT_BUFFER); + } + + for (p = osDeviceState; *p; p += (int)strlen(p) + 1) + { + if (strlen(p) == 2 && p[1] == ':' && p[0] >= 'C' && p[0] <= 'Z') + { + QueryDosDevice (p, name, sizeof name); + if (strncmp(name,"\\Device\\CdRom",13)) + { + continue; + } + } + + if (strncmp(p, "PhysicalDrive", 13) && strncmp(p, "TAPE", 4) && + strncmp(p, "Scanner", 7) && strncmp(p, "Changer", 7) ) + { + continue; + } + + sprintf(device, "\\\\.\\%s", p); + + handle = CreateFile(device, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION) + { + handle = CreateFile(device, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + } + + if (handle == INVALID_HANDLE_VALUE) + { + continue; + } + + t = DeviceIoControl(handle, IOCTL_SCSI_GET_ADDRESS, NULL, 0, + &scsiAddress, sizeof scsiAddress, &retLen, NULL); + + CloseHandle(handle); + + if (t) + { + if (port->portNumber == scsiAddress.PortNumber && + bus == scsiAddress.PathId && + target == scsiAddress.TargetId && + lun == scsiAddress.Lun) + { + QueryDosDevice (p, name, sizeof name); + name[len - 21] = '\0'; + sprintf(buf, "%-18s %s", p, name); + + return 1; + } + } + } +#endif +#if __linux__ + char pathName[PATH_MAX]; + char linkName[PATH_MAX]; + int n; + char *c = NULL; + int i; + int fd; + int id[2]; + int match; + int fail; + DIR *dirp; + struct dirent *direntp = NULL; + + convertBusTarget(port, &bus, &target, lun); + + sprintf(pathName, + "/sys/class/scsi_device/%d:%d:%d:%d/device/", + port->hostNumber, bus, target, lun); + + dirp = opendir(pathName); + while (dirp) + { + direntp = readdir(dirp); + if (!direntp) + break; + if (strncmp(direntp->d_name, "block", 5) == 0) + break; + if (strncmp(direntp->d_name, "tape", 4) == 0) + break; + } + + if (direntp) + { + strcat(pathName, direntp->d_name); + + n = readlink(pathName, linkName, sizeof linkName); + if (n > 0) + { + linkName[n] = '\0'; + c = strrchr(linkName, '/'); + } + if (c) + { + sprintf(buf, "/dev%-8s[%d:%d:%d:%d]", + c, port->hostNumber, bus, target, lun); + return 1; + } + } + + if (dirp) + closedir(dirp); + + match = (port->hostNumber << 24) | (bus << 16) | (lun << 8) | target; + + fail = 0; + for (i = 0; i < 256; i++) + { + if (i < 26) + { + sprintf(pathName, "/dev/sd%c", 'a' + i); + } + else + { + sprintf(pathName, "/dev/sd%c%c", 'a' + ((i-26) / 26), 'a' + (i % 26)); + } + fd = open(pathName, O_RDONLY | O_NONBLOCK); + if (fd < 0) + { + if (fail++ > 32) + break; + else + continue; + } + fail = 0; + n = ioctl(fd, SCSI_IOCTL_GET_IDLUN, id); + close(fd); + if (n == 0) + { + if (match == id[0]) + { + sprintf(buf, "%-12s[%d:%d:%d:%d]", + pathName, port->hostNumber, bus, target, lun); + return 1; + } + } + } + + fail = 0; + for (i = 0; i < 32; i++) + { + sprintf(pathName, "/dev/sr%d", i); + fd = open(pathName, O_RDONLY | O_NONBLOCK); + if (fd < 0) + { + if (fail++ > 4) + break; + else + continue; + } + fail = 0; + n = ioctl(fd, SCSI_IOCTL_GET_IDLUN, id); + close(fd); + if (n == 0) + { + if (match == id[0]) + { + sprintf(buf, "%-12s[%d:%d:%d:%d]", + pathName, port->hostNumber, bus, target, lun); + return 1; + } + } + } + + fail = 0; + for (i = 0; i < 32; i++) + { + sprintf(pathName, "/dev/st%d", i); + fd = open(pathName, O_RDONLY | O_NONBLOCK); + if (fd < 0) + { + if (fail++ > 4) + break; + else + continue; + } + fail = 0; + n = ioctl(fd, SCSI_IOCTL_GET_IDLUN, id); + close(fd); + if (n == 0) + { + if (match == id[0]) + { + sprintf(buf, "%-12s[%d:%d:%d:%d]", + pathName, port->hostNumber, bus, target, lun); + return 1; + } + } + } +#endif +#if __sparc__ + FCDevicePage0_t FCDevicePage0; + int fd; + int n; + char path[PATH_MAX]; + char phci_buf[MAXNAMELEN]; + char addr_buf[MAXNAMELEN]; + char vhci_buf[MAXNAMELEN]; + U32 wwpn_l; + U32 wwpn_h; + char *name; + int b_t; + int dev_handle; + Mpi2RaidVolPage1_t RaidVolumePage1; + Mpi2SasDevicePage0_t SASDevicePage0; + unsigned char vpd[255]; + U32 wwid_l; + U32 wwid_h; + U32 map; + + if (device_caches_initialized == 0) + { + device_caches_initialized = 1; + + scsi_vhci_fd = open("/devices/scsi_vhci:devctl", O_RDWR); + + cachePathLinks("/dev/rdsk/", ":c,raw", &dev_rdsk_cache, &dev_rdsk_count); + + cachePathLinks("/dev/rmt/", ":", &dev_rmt_cache, &dev_rmt_count); + + cachePathLinks("/dev/es/", ":0", &dev_es_cache, &dev_es_count); + } + + if (strstr(port->portName, "fc") && + getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, + MPI_FC_DEVICE_PGAD_FORM_BUS_TID + mapOsToHwTarget(port, target), + &FCDevicePage0, sizeof FCDevicePage0) == 1) + { + wwpn_l = get32(FCDevicePage0.WWPN.Low); + wwpn_h = get32(FCDevicePage0.WWPN.High); + + sprintf(addr_buf, "w%08x%08x,%x", wwpn_h, wwpn_l, lun); + + if (type == 0 || type == 5 || type == 7 || type == 13) + { + if (getVhciName(port->pathName, addr_buf, vhci_buf) == 1) + { + sprintf(path, "%s", vhci_buf); + } + else + { + if (type == 13) + { + name = "ses"; + } + else + { +#if i386 + name = "disk"; +#else + name = "ssd"; +#endif + } + sprintf(path, "%s/%s@%s", port->pathName, name, addr_buf); + } + if (type == 13) + n = findPathLink(port, "/dev/es/", dev_es_cache, dev_es_count, path, buf); + else + n = findPathLink(port, "/dev/rdsk/", dev_rdsk_cache, dev_rdsk_count, path, buf); + if (n == 0) + { + if (strlen(vhci_buf)) + sprintf(buf, "/devices%s", vhci_buf); + return 0; + } + } + else if (type == 1) + { + sprintf(path, "%s/st@%s", port->pathName, addr_buf); + n = findPathLink(port, "/dev/rmt/", dev_rmt_cache, dev_rmt_count, path, buf); + return n > 0; + } + else + { + buf[0] = '\0'; + return 0; + } + } + else if (mpi2 && port->ioctlValue == MPTIOCTL_PASS_THRU) + { + if (mapBusTargetToDevHandle(port, bus, target, &dev_handle) != 1) + { + buf[0] = '\0'; + return 0; + } + + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 1, + MPI2_RAID_VOLUME_PGAD_FORM_HANDLE + dev_handle, + &RaidVolumePage1, sizeof RaidVolumePage1) == 1) + { + wwid_l = get32(RaidVolumePage1.WWID.Low); + wwid_h = get32(RaidVolumePage1.WWID.High); + wwid_h &= 0x0fffffff; + wwid_h |= 0x30000000; + + sprintf(phci_buf, "%s/iport@v0", port->pathName); + sprintf(addr_buf, "w%08x%08x,%x", wwid_h, wwid_l, lun); + } + else if (getConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0, + MPI2_SAS_DEVICE_PGAD_FORM_HANDLE + dev_handle, + &SASDevicePage0, sizeof SASDevicePage0) == 1) + { + if (get32(SASDevicePage0.DeviceInfo) & MPI_SAS_DEVICE_INFO_SATA_DEVICE) + { + if (doInquiryVpdPage(port, bus, target, 0, 0x83, vpd, sizeof vpd) == 1 && + vpd[3] >= 12 && vpd[4] == 1 && vpd[5] == 3 && vpd[7] == 8) + { + wwid_h = get4bytes(vpd, 8); + wwid_l = get4bytes(vpd, 12); + } + else if (get16(SASDevicePage0.ParentDevHandle) >= port->numPhys) + { + wwid_l = get32(SASDevicePage0.SASAddress.Low); + wwid_h = get32(SASDevicePage0.SASAddress.High); + } + else + { + wwid_l = 0; + wwid_h = 0; + } + } + else + { + wwid_l = get32(SASDevicePage0.SASAddress.Low); + wwid_h = get32(SASDevicePage0.SASAddress.High); + } + + map = port->portPhyMap[SASDevicePage0.PhysicalPort]; + sprintf(phci_buf, "%s/iport@%x", port->pathName, map); + + if (wwid_l || wwid_h) + sprintf(addr_buf, "w%08x%08x,%x", wwid_h, wwid_l, lun); + else + sprintf(addr_buf, "p%x,%x", SASDevicePage0.PhyNum, lun); + } + else + { + buf[0] = '\0'; + return 0; + } + + if (getVhciName(phci_buf, addr_buf, vhci_buf) == 1) + { + sprintf(path, "%s", vhci_buf); + } + else + { + if (type == 13) + name = "enclosure"; + else + name = "disk"; + sprintf(path, "%s/%s@%s", phci_buf, name, addr_buf); + } + if (type == 13) + n = findPathLink(port, "/dev/es/", dev_es_cache, dev_es_count, path, buf); + else + n = findPathLink(port, "/dev/rdsk/", dev_rdsk_cache, dev_rdsk_count, path, buf); + if (n == 0) + { + if (strlen(vhci_buf)) + sprintf(buf, "/devices%s", vhci_buf); + return 0; + } + } + else + { + b_t = (bus << 8) + target; + + if (type == 0 || type == 5 || type == 7 || type == 13) + { + sprintf(addr_buf, "%x,%x", b_t, lun); + if (getVhciName(port->pathName, addr_buf, vhci_buf) == 1) + { + sprintf(path, "%s", vhci_buf); + } + else + { + if (type == 13) + { + name = "ses"; + } + else + { +#if i386 + name = "sd"; +#else + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + name = "ssd"; + else + name = "sd"; +#endif + } + sprintf(path, "%s/%s@%s", port->pathName, name, addr_buf); + } + if (type == 13) + n = findPathLink(port, "/dev/es/", dev_es_cache, dev_es_count, path, buf); + else + n = findPathLink(port, "/dev/rdsk/", dev_rdsk_cache, dev_rdsk_count, path, buf); + if (n == 0) + return 0; + } + else if (type == 1) + { + sprintf(path, "%s/st@%x,%x", port->pathName, b_t, lun); + n = findPathLink(port, "/dev/rmt/", dev_rmt_cache, dev_rmt_count, path, buf); + return n > 0; + } + else + { + buf[0] = '\0'; + return 0; + } + } + + fd = open(buf, O_RDONLY | O_NDELAY); + if (fd >= 0) + { + close(fd); + return 1; + } + else + { + strcat(buf, " (?)"); + return 1; + } +#endif + + buf[0] = '\0'; + + return 0; +} + + +int +doDisplayOsDeviceNames(MPT_PORT *port) +{ + int bus; + int target; + int lun; + int type; + unsigned char inq[36]; + char buf[80]; + int version; + int max_lun; + +#if WIN32 + if (strlen(port->driverName)) + printf("%s is %s\n\n", port->portName, port->driverName); +#endif +#if __linux__ + if (port->hostNumber >= 0) + printf("%s is SCSI host %d\n\n", port->portName, port->hostNumber); +#endif +#if __sparc__ + if (mpi2) + getPortPhyMap(port); + if (port->hostNumber >= 0) + printf("%s is /dev/cfg/c%d\n\n", port->portName, port->hostNumber); +#endif + + printf(" B___T___L Type Operating System Device Name\n"); + + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + max_lun = 1; + + for (lun = 0; lun < max_lun; lun++) + { + if (doInquiry(port, bus, target, lun, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + if (lun == 0) + break; + else + continue; + } + + if (lun == 0) + { + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + version = inq[2] & 0x07; + if (version > 1) + max_lun = 8; + if (version > 3) + max_lun = 64; + } + else + { + max_lun = port->maxLuns; + } + } + else + { + if ((inq[0] & 0x1f) == 0x1f) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + if ((inq[0] & 0x1f) == 0x0d) + continue; + } + + type = inq[0] & 0x1f; + + getOsDeviceName(port, bus, target, lun, buf, sizeof buf, type); + + printf("%2d %3d %3d %-9s %s\n", + bus, target, lun, deviceType[type], buf); + } + } + } + + return 1; +} + + +#endif + + +#if WIN32 || LINUX_DIAG || __sparc__ + + +int +diagBufferAction(MPT_PORT *port, int action, void *buf, int size) +{ +#if WIN32 + int status; + SRB_DIAG_BUFFER srb; + int inLen; + int outLen; + DWORD retLen; + + memset(&srb, 0, sizeof srb); + + srb.Sic.Length = sizeof srb - sizeof srb.Buf + size - sizeof srb.Sic; + srb.Sic.ControlCode = MPI_FW_DIAG_IOCTL; + srb.Sic.HeaderLength = sizeof srb.Sic; + srb.Sic.Timeout = LONG_TIME; + srb.Sic.ReturnCode = MPI_FW_DIAG_NEW; + + memcpy((char *)&srb.Sic.Signature, "FwDiag ", 8); + + srb.DiagType = action; + memcpy(srb.Buf, buf, size); + + inLen = sizeof srb - sizeof srb.Buf + size; + outLen = sizeof srb - sizeof srb.Buf + size; + retLen = 0; + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + &srb, inLen, &srb, outLen, &retLen, NULL); + + if (mpi1 && srb.Sic.ReturnCode == 2) // old drivers can return this bogus value + diagReturnCode = 0; + else + diagReturnCode = srb.Sic.ReturnCode; + + if (status != 1 || diagReturnCode != 0) + return 0; + + memcpy(buf, srb.Buf, size); + + return 1; +#endif +#if __linux__ + IOCTL_DIAG_BUFFER diagbuffer; + int status; + int ioctl_code; + + if (mpi2) + return diagBufferAction2(port, action, buf, size); + + switch (action) + { + case MPI_FW_DIAG_TYPE_REGISTER: ioctl_code = MPTDIAGREGISTER; break; + case MPI_FW_DIAG_TYPE_UNREGISTER: ioctl_code = MPTDIAGUNREGISTER; break; + case MPI_FW_DIAG_TYPE_QUERY: ioctl_code = MPTDIAGQUERY; break; + case MPI_FW_DIAG_TYPE_READ_BUFFER: ioctl_code = MPTDIAGREADBUFFER; break; + case MPI_FW_DIAG_TYPE_RELEASE: ioctl_code = MPTDIAGRELEASE; break; + default: return 0; + } + + memset(&diagbuffer, 0, sizeof diagbuffer); + + diagbuffer.hdr.max_data_size = sizeof diagbuffer - sizeof diagbuffer.buf + size; + diagbuffer.hdr.ioc_number = port->portNumber; + + memcpy(diagbuffer.buf, buf, size); + + // mptctl bug, remember size for later workaround + if (action == MPI_FW_DIAG_TYPE_REGISTER) + { + MPI_FW_DIAG_REGISTER *diagRegister = (MPI_FW_DIAG_REGISTER *)diagbuffer.buf; + + port->diagBufferSizes[diagRegister->BufferType] = diagRegister->RequestedBufferSize; + } + if (action == MPI_FW_DIAG_TYPE_UNREGISTER) + { + MPI_FW_DIAG_UNREGISTER *diagUnregister = (MPI_FW_DIAG_UNREGISTER *)diagbuffer.buf; + + port->diagBufferSizes[diagUnregister->UniqueId & 0xff] = 0; + } + + // mptctl bug, poison field for later workaround + if (action == MPI_FW_DIAG_TYPE_QUERY) + { + MPI_FW_DIAG_QUERY *diagQuery = (MPI_FW_DIAG_QUERY *)diagbuffer.buf; + + diagQuery->DriverAddedBufferSize = 0x07071959; + + errno = 0; + } + + status = ioctl(port->fileHandle, ioctl_code, &diagbuffer); + + // mptctl bug, MPTDIAGQUERY returns EFAULT even in success! + if (status != 0 && errno == EFAULT && action == MPI_FW_DIAG_TYPE_QUERY) + { + MPI_FW_DIAG_QUERY *diagQuery = (MPI_FW_DIAG_QUERY *)diagbuffer.buf; + + if (diagQuery->DriverAddedBufferSize != 0x07071959) + { + status = 0; + errno = 0; + } + } + + if (status != 0) + { + return 0; + } + + // mptctl bug, MPTDIAGQUERY returns 0 for TotalBufferSize! + if (action == MPI_FW_DIAG_TYPE_QUERY) + { + MPI_FW_DIAG_QUERY *diagQuery = (MPI_FW_DIAG_QUERY *)diagbuffer.buf; + + if (diagQuery->TotalBufferSize == 0) + { + diagQuery->TotalBufferSize = port->diagBufferSizes[diagQuery->BufferType]; + } + } + + memcpy(buf, diagbuffer.buf, size); + + return 1; +#endif +#if __sparc__ + SYM_DIAG_ACTION diagAction; + int status; + + diagAction.Action = action; + diagAction.Length = size; + diagAction.PtrDiagAction = (UINT64)(UINT32)buf; + diagAction.ReturnCode = MPI_FW_DIAG_NEW; + + if (mpi2) + status = ioctl(port->fileHandle, MPTIOCTL_DIAG_ACTION, &diagAction); + else + status = ioctl(port->fileHandle, SYMIOCTL_DIAG_ACTION, &diagAction); + + diagReturnCode = diagAction.ReturnCode; + + return status == 0 && diagReturnCode == 0; +#endif +} + + +int +diagBufferAction2(MPT_PORT *port, int action, void *buf, int size) +{ +#if __linux__ + IOCTL_DIAG_BUFFER diagbuffer; + int status; + int ioctl_code; + + switch (action) + { + case MPI_FW_DIAG_TYPE_REGISTER: ioctl_code = MPT2DIAGREGISTER; break; + case MPI_FW_DIAG_TYPE_UNREGISTER: ioctl_code = MPT2DIAGUNREGISTER; break; + case MPI_FW_DIAG_TYPE_QUERY: ioctl_code = MPT2DIAGQUERY; break; + case MPI_FW_DIAG_TYPE_READ_BUFFER: ioctl_code = MPT2DIAGREADBUFFER; break; + case MPI_FW_DIAG_TYPE_RELEASE: ioctl_code = MPT2DIAGRELEASE; break; + default: return 0; + } + + memset(&diagbuffer, 0, sizeof diagbuffer); + + diagbuffer.hdr.max_data_size = sizeof diagbuffer - sizeof diagbuffer.buf + size; + diagbuffer.hdr.ioc_number = port->portNumber; + + memcpy(diagbuffer.buf, buf, size); + + status = ioctl(port->fileHandle, ioctl_code, &diagbuffer); + + if (status != 0) + { + return 0; + } + + memcpy(buf, diagbuffer.buf, size); + +#endif + + return 1; +} + + +int +diagBufferRegister(MPT_PORT *port, int type, int id, int size) +{ + MPI_FW_DIAG_REGISTER diagRegister; + + if (mpi2) + return diagBufferRegister2(port, type, id, size); + + memset(&diagRegister, 0, sizeof diagRegister); + + diagRegister.BufferType = type; + diagRegister.UniqueId = id; + diagRegister.RequestedBufferSize = size; + + printf("\nUse default settings? [Yes or No, default is Yes] "); + if (getYesNoAnswer(1) != 1) + { + printf("Buffer posting options (ProductSpecific[0]): [00000000-FFFFFFFF, default is 00000000] "); + if (getHexNumberAnswer(&diagRegister.ProductSpecific[0]) == 0) + diagRegister.ProductSpecific[0] = 0x00000000; + printf("IOP Debug Mask (ProductSpecific[1]): [00000000-FFFFFFFF, default is FFFFEFFF] "); + if (getHexNumberAnswer(&diagRegister.ProductSpecific[1]) == 0) + diagRegister.ProductSpecific[1] = 0xFFFFEFFF; + printf("PL debug mask (ProductSpecific[2]): [00000000-FFFFFFFF, default is FFF3FFFF] "); + if (getHexNumberAnswer(&diagRegister.ProductSpecific[2]) == 0) + diagRegister.ProductSpecific[2] = 0xFFF3FFFF; + printf("IR debug mask (ProductSpecific[3]): [00000000-FFFFFFFF, default is FFFFFFFF] "); + if (getHexNumberAnswer(&diagRegister.ProductSpecific[3]) == 0) + diagRegister.ProductSpecific[3] = 0xFFFFFFFF; + } + + return diagBufferAction(port, MPI_FW_DIAG_TYPE_REGISTER, &diagRegister, sizeof diagRegister); +} + + +/* diag buffer register routine for gen2 */ +int +diagBufferRegister2(MPT_PORT *port, int type, int id, int size) +{ + MPI2_FW_DIAG_REGISTER diagRegister; + + memset(&diagRegister, 0, sizeof diagRegister); + + diagRegister.BufferType = type; + diagRegister.UniqueId = id; + diagRegister.RequestedBufferSize = size; + + printf("\nUse default settings? [Yes or No, default is Yes] "); + if (getYesNoAnswer(1) != 1) + { + printf("Buffer Posting Options (ProductSpecific[0]): [00000000-FFFFFFFF, default is 00000000] "); + if (getHexNumberAnswer(&diagRegister.ProductSpecific[0]) == 0) + diagRegister.ProductSpecific[0] = 0x00000000; + printf("IOP Debug Mask (ProductSpecific[2:1]): [16 hex digits (no dashes), default is FFFFCFFF-FFFFFFFF] "); + if (getHexDoubleNumberAnswer(&diagRegister.ProductSpecific[2], &diagRegister.ProductSpecific[1]) == 0) + { + diagRegister.ProductSpecific[1] = 0xFFFFFFFF; + diagRegister.ProductSpecific[2] = 0xFFFFCFFF; + } + printf("PL Debug Mask (ProductSpecific[4:3]): [16 hex digits (no dashes), default is FFFFEFFF-EFFFFFFF] "); + if (getHexDoubleNumberAnswer(&diagRegister.ProductSpecific[4], &diagRegister.ProductSpecific[3]) == 0) + { + diagRegister.ProductSpecific[3] = 0xEFFFFFFF; + diagRegister.ProductSpecific[4] = 0xFFFFEFFF; + } + printf("IR Debug Mask (ProductSpecific[6:5]): [16 hex digits (no dashes), default is FFFFEFFF-FFFFFFFF] "); + if (getHexDoubleNumberAnswer(&diagRegister.ProductSpecific[6], &diagRegister.ProductSpecific[5]) == 0) + { + diagRegister.ProductSpecific[5] = 0xFFFFFFFF; + diagRegister.ProductSpecific[6] = 0xFFFFEFFF; + } + } + + return diagBufferAction(port, MPI_FW_DIAG_TYPE_REGISTER, &diagRegister, sizeof diagRegister); +} + + +int +diagBufferUnregister(MPT_PORT *port, int id) +{ + MPI_FW_DIAG_UNREGISTER diagUnregister; + + memset(&diagUnregister, 0, sizeof diagUnregister); + + diagUnregister.UniqueId = id; + + return diagBufferAction(port, MPI_FW_DIAG_TYPE_UNREGISTER, &diagUnregister, sizeof diagUnregister); +} + + +/* diag buffer query routine for gen1 */ +int +diagBufferQuery(MPT_PORT *port, int type, int id, int *flags, int *size) +{ + MPI_FW_DIAG_QUERY diagQuery; + + if (mpi2) + return diagBufferQuery2(port, type, id, flags, size); + + memset(&diagQuery, 0, sizeof diagQuery); + + diagQuery.BufferType = type; + diagQuery.UniqueId = id; + + if (diagBufferAction(port, MPI_FW_DIAG_TYPE_QUERY, &diagQuery, sizeof diagQuery) != 1) + return 0; + + *flags = diagQuery.Flags; + *size = diagQuery.TotalBufferSize; + + return 1; +} + + +/* diag buffer query routine for gen2 */ +int +diagBufferQuery2(MPT_PORT *port, int type, int id, int *flags, int *size) +{ + MPI2_FW_DIAG_QUERY diagQuery; + + memset(&diagQuery, 0, sizeof diagQuery); + + diagQuery.BufferType = type; + diagQuery.UniqueId = id; + + if (diagBufferAction(port, MPI_FW_DIAG_TYPE_QUERY, &diagQuery, sizeof diagQuery) != 1) + return 0; + + *flags = diagQuery.AppFlags; + *size = diagQuery.TotalBufferSize; + + return 1; +} + + +int +diagBufferReadBuffer(MPT_PORT *port, int id, char *name, int file, int *sizeIn, int header) +{ + MPI_FW_DIAG_READ_BUFFER *diagReadBuffer; + DIAG_BUFFER_START *diagBufferStart; + DIAG_HEADER_FIRM_IDENTIFICATION diagHeaderFirm; + DIAG_HEADER_HOST_IDENTIFICATION diagHeaderHost; + int size = *sizeIn; + int offset = 0; + int length; + int t; + int actual; + + t = sizeof *diagReadBuffer - sizeof diagReadBuffer->DataBuffer + 32768; + diagReadBuffer = malloc(t); + + memset(diagReadBuffer, 0, t); + + diagReadBuffer->UniqueId = id; + + while (size) + { + length = min(size, 32768); + + diagReadBuffer->StartingOffset = offset; + diagReadBuffer->BytesToRead = length; + + t = sizeof *diagReadBuffer - sizeof diagReadBuffer->DataBuffer + length; + if (diagBufferAction(port, MPI_FW_DIAG_TYPE_READ_BUFFER, diagReadBuffer, t) != 1) + { + free(diagReadBuffer); + return 0; + } + + if (offset == 0) + { + diagBufferStart = (DIAG_BUFFER_START *)diagReadBuffer->DataBuffer; + if ((get32(diagBufferStart->DiagVersion) == 0x00000000 || + get32(diagBufferStart->DiagVersion) == 0x01000000) && + get32(diagBufferStart->Reserved3) == 0x4742444c) + { + if (diagBufferStart->BufferType == 0) + printf("Current trace pointer = %x\n", get32x(((U32 *)(diagBufferStart + 1))[3])); + + actual = get32(diagBufferStart->Size); + + if (size > actual) + { + size = actual; + *sizeIn = actual; + } + + if (length > actual) + length = actual; + + if (header) + { + memset(&diagHeaderFirm, 0, sizeof diagHeaderFirm); + diagHeaderFirm.Size = set32(sizeof diagHeaderFirm); + diagHeaderFirm.Type = set16(1); + diagHeaderFirm.Version = 1; +// diagHeaderFirm.CapabilitiesFlags = set32(port->capabilities); + diagHeaderFirm.FWVersion = set32(port->fwVersion); + diagHeaderFirm.ProductId = set16(port->productId); + + memset(&diagHeaderHost, 0, sizeof diagHeaderHost); + diagHeaderHost.Size = set32(sizeof diagHeaderHost); + diagHeaderHost.Type = set16(2); + diagHeaderHost.Version = 1; + + t = write(file, diagBufferStart, sizeof *diagBufferStart); + t += write(file, &diagHeaderFirm, sizeof diagHeaderFirm); + t += write(file, &diagHeaderHost, sizeof diagHeaderHost); + t += write(file, diagBufferStart + 1, length - sizeof *diagBufferStart); + if (t != length + (int)sizeof diagHeaderFirm + (int)sizeof diagHeaderHost) + { + printf("Write failed for file %s, t = %x\n", name, t); + perror("Error is"); + free(diagReadBuffer); + return 0; + } + + *sizeIn += sizeof diagHeaderFirm + sizeof diagHeaderHost; + + size -= length; + offset += length; + continue; + } + } + } + + t = write(file, diagReadBuffer->DataBuffer, length); + if (t != length) + { + printf("Write failed for file %s, t = %x\n", name, t); + perror("Error is"); + free(diagReadBuffer); + return 0; + } + + size -= length; + offset += length; + } + + free(diagReadBuffer); + + return 1; +} + + +int +diagBufferRelease(MPT_PORT *port, int type, int id) +{ + MPI_FW_DIAG_RELEASE diagRelease; + + memset(&diagRelease, 0, sizeof diagRelease); + + diagRelease.UniqueId = id; + + return diagBufferAction(port, MPI_FW_DIAG_TYPE_RELEASE, &diagRelease, sizeof diagRelease); +} + + +int +doDiagBuffer(MPT_PORT *port) +{ + int type; + int id; + int action; + int flags; + int size; + char name[256]; + int file; + int n; + int header = 0; + char *string; + + printf("Buffer type: [0=Trace, 1=Snapshot, or RETURN to quit] "); + type = getNumberAnswer(0, 1, -1); + if (type < 0) + return 1; + + switch (type) + { + case 0: type = MPI_DIAG_BUF_TYPE_TRACE; string = "trace"; break; + case 1: type = MPI_DIAG_BUF_TYPE_SNAPSHOT; string = "snapsot"; break; + default: return 0; + } + + id = 0x07075900 + type; + + printf("\nNOTE: the expected sequence is Register, Release, Read Buffer, Unregister\n"); + while (TRUE) + { + printf("\n"); + printf(" 1. Register\n"); + printf(" 2. Query\n"); + printf(" 3. Read Buffer\n"); + printf(" 4. Release\n"); + printf(" 5. Unregister\n"); + printf("\nSelect an action: [1-5 or RETURN to quit] "); + action = getNumberAnswer(1, 5, 0); + if (action == 0) + return 1; + + switch (action) + { + case 1: + if (type == MPI_DIAG_BUF_TYPE_TRACE) + size = 128; + else + size = 5*1024; + printf("\nRequested size in KB: [8 to 8192, default is %d] ", size); + size = getNumberAnswer(8, 8192, size) * 1024; + if (type == MPI_DIAG_BUF_TYPE_TRACE) + size += 64; + + printf("\nRegistering...\n"); + + if (diagBufferRegister(port, type, id, size) != 1) + { + printf("Register failed!\n"); + switch (diagReturnCode) + { + case MPI_FW_DIAG_ERROR_INVALID_UID: + printf("\nA %s buffer is already registered\n", string); + break; + case MPI_FW_DIAG_ERROR_NO_BUFFER: +#if WIN32 + printf("\nDriver support for a %s buffer is not enabled\n", string); +#else + printf("\nA %s buffer could not be allocated due to insufficient memory\n", string); +#endif + break; + case MPI_FW_DIAG_ERROR_POST_FAILED: + printf("\nThe %s buffer could not be posted\n", string); + break; + } + break; + } + + if (diagBufferQuery(port, type, id, &flags, &size) != 1) + { + printf("Query failed\n"); + break; + } + + printf("\nActual size is %d KB (0x%x bytes)\n", size / 1024, size); + break; + + case 2: + printf("\nQuerying...\n"); + + if (diagBufferQuery(port, type, id, &flags, &size) != 1) + { + if (diagReturnCode == MPI_FW_DIAG_ERROR_INVALID_UID) + printf("\nNo %s buffer is currently registered\n", string); + else + printf("Query failed\n"); + break; + } + + printf("\nA %d KB %s buffer is currently registered\n", size / 1024, string); + if (flags & MPI_FW_DIAG_FLAG_APP_OWNED) + printf(" buffer was registered by an application\n"); + if (flags & MPI_FW_DIAG_FLAG_BUFFER_VALID) + printf(" buffer contains valid data\n"); + if (flags & MPI_FW_DIAG_FLAG_FW_BUFFER_ACCESS) + printf(" buffer is being accessed by firmware\n"); + break; + + case 3: + if (diagBufferQuery(port, type, id, &flags, &size) != 1) + { + if (diagReturnCode == MPI_FW_DIAG_ERROR_INVALID_UID) + printf("\nNo %s buffer is currently registered\n", string); + else + printf("Query failed\n"); + break; + } + + if (!(flags & MPI_FW_DIAG_FLAG_BUFFER_VALID)) + { + printf("The %s buffer does not contain valid data\n", string); + break; + } + + n = getFileName(name, sizeof name, stdin, "trace", 0); + if (n > 0) + { + file = open(name, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + if (file < 0) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + break; + } + } + else + { + printf("Read Buffer will not be done\n"); + break; + } + + if (gFlag == TRUE) + { + printf("Add tool header? [Yes or No, default is No] "); + header = getYesNoAnswer(0); + } + + printf("\nReading Buffer...\n"); + + if (diagBufferReadBuffer(port, id, name, file, &size, header) != 1) + printf("Read Buffer failed\n"); + else + printf("\nWrote %d bytes to file %s\n", size, name); + + close(file); + break; + + case 4: + printf("\nReleasing...\n"); + + if (diagBufferRelease(port, type, id) != 1) + { + printf("Release failed!\n"); + switch (diagReturnCode) + { + case MPI_FW_DIAG_ERROR_INVALID_UID: + printf("\nNo %s buffer is currently registered\n", string); + break; + case MPI_FW_DIAG_ERROR_ALREADY_RELEASED: + printf("\nThe %s buffer is already released\n", string); + break; + case MPI_FW_DIAG_ERROR_RELEASE_FAILED: + printf("\nThe %s buffer could not be released\n", string); + break; + } + } + break; + + case 5: + printf("\nUnregistering...\n"); + + if (diagBufferUnregister(port, id) != 1) + { + printf("Unregister failed\n"); + switch (diagReturnCode) + { + case MPI_FW_DIAG_ERROR_INVALID_UID: + printf("\nNo %s buffer is currently registered\n", string); + break; + case MPI_FW_DIAG_ERROR_RELEASE_FAILED: + printf("\nThe %s buffer could not be released\n", string); + break; + } + } + break; + + } + } + + return 1; +} + + +#endif + + +int +doFlashUpload(MPT_PORT *port) +{ + char name[256]; + int file; + unsigned char *imageBuf = NULL; + int imageLen; + int actualImageLen; + int offset; + int type; + int n; + int t; + + printf(" 1. Firmware\n"); + printf(" 2. BIOS/FCode\n"); + printf(" 3. BootLoader\n"); + printf(" 4. Firmware (backup copy)\n"); + printf(" 5. Complete (all sections)\n"); + t = 5; + if (port->deviceId == MPI_MANUFACTPAGE_DEVID_SAS1078) + { + printf(" 6. MegaRAID\n"); + t = 6; + } + printf("\nSelect what to upload: [1-%d or RETURN to quit] ", t); + type = getNumberAnswer(1, t, 0); + if (type == 0) + return 1; + + switch(type) + { + case 1: type = MPI_FW_UPLOAD_ITYPE_FW_FLASH; break; + case 2: type = MPI_FW_UPLOAD_ITYPE_BIOS_FLASH; break; + case 3: type = MPI_FW_UPLOAD_ITYPE_BOOTLOADER; break; + case 4: type = MPI_FW_UPLOAD_ITYPE_FW_BACKUP; break; + case 5: type = MPI_FW_UPLOAD_ITYPE_COMPLETE; break; + case 6: type = MPI_FW_UPLOAD_ITYPE_MEGARAID; break; + default: type = 0; break; + } + + printf("\n"); + + n = getFileName(name, sizeof name, stdin, "FLASH section", 0); + if (n > 0) + { + file = open(name, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + if (file < 0) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + } + else + { + printf("Image won't be uploaded\n"); + return 1; + } + + imageLen = 0x10000; + imageBuf = (unsigned char *)malloc(imageLen); + + printf("\nUploading image...\n"); + + offset = 0; + while (TRUE) + { + if (doFwUpload(port, type, imageBuf, imageLen, offset, &actualImageLen) != 1) + break; + + if (offset + imageLen > actualImageLen) + imageLen = actualImageLen - offset; + + t = write(file, imageBuf, imageLen); + if (t != imageLen) + { + printf("Write failed for file %s, t = %x\n", name, t); + perror("Error is"); + break; + } + + offset += imageLen; + if (offset >= actualImageLen) + break; + } + + printf("\nWrote %d bytes to file %s\n", offset, name); + + close(file); + + free(imageBuf); + + return 1; +} + + +int +doDisplayVersionInfo(MPT_PORT *port) +{ + Mpi2IOUnitPage0_t IOUnitPage0; + SasIOUnitPage0_t SASIOUnitPage0; + ManufacturingPage0_t ManufacturingPage0; +#if WIN32 + int status; + DRVR_INFO_SRB srb; + int inLen; + int outLen; + DWORD retLen; +#endif +#if __linux__ + int status; + struct mpt_ioctl_iocinfo iocinfo; + char *c; +#endif +#if __sparc__ + SYMHI_DMI_DATA dmiData; + mptsas_adapter_data_t adapterData; +#endif + int i; + +#if WIN32 + memset(&srb, 0, sizeof srb); + + srb.Sic.Length = sizeof srb - sizeof srb.Sic; + srb.Sic.ControlCode = DRVR_INFO_IOCTL; + srb.Sic.HeaderLength = sizeof srb.Sic; + srb.Sic.Timeout = SHORT_TIME; + + memcpy((char *)&srb.Sic.Signature, "4.00 ", 8); + + srb.PageCode = ADAPTER_INFO_PAGE; + + inLen = sizeof srb; + outLen = sizeof srb; + retLen = 0; + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + &srb, inLen, &srb, outLen, &retLen, NULL); + + if (status == 1) + { + if (strlen(port->driverName)) + printf("%s is %s, Version %s\n\n", port->portName, + port->driverName, srb.AdapterPageOut.DriverVersion); + } +#endif +#if __linux__ + memset(&iocinfo, 0, sizeof iocinfo); + + iocinfo.hdr.maxDataSize = sizeof iocinfo; + + iocinfo.hdr.iocnum = port->portNumber; + + if (mpi2) + status = ioctl(port->fileHandle, MPT2IOCINFO, &iocinfo); + else + status = ioctl(port->fileHandle, MPTIOCINFO, &iocinfo); + + if (status == 0) + { + c = iocinfo.driverVersion; + if (c[0] == '@' && c[1] == '(' && c[2] == '#' && c[3] == ')') + c += 4; + + if (port->hostNumber >= 0) + printf("%s is SCSI host %d, Driver is %s\n\n", + port->portName, port->hostNumber, c); + else + printf("%s, Driver is %s\n\n", + port->portName, c); + } +#endif +#if __sparc__ + + if (mpi2) + { + memset(&adapterData, 0, sizeof adapterData); + adapterData.StructureLength = sizeof adapterData; + + if (ioctl(port->fileHandle, MPTIOCTL_GET_ADAPTER_DATA, &adapterData) == 0 && + strlen(adapterData.DriverVersion) != 0) + { + if (port->hostNumber >= 0) + printf("%s is /dev/cfg/c%d, Driver is %s\n\n", + port->portName, port->hostNumber, adapterData.DriverVersion); + else + printf("%s, Driver is %s\n\n", + port->portName, adapterData.DriverVersion); + } + else + { + if (port->hostNumber >= 0) + printf("%s is /dev/cfg/c%d\n\n", + port->portName, port->hostNumber); + } + } + else + { + memset(&dmiData, 0, sizeof dmiData); + dmiData.StructureLength = sizeof dmiData; + + if (ioctl(port->fileHandle, SYMIOCTL_GET_DMI_DATA, &dmiData) == 0 && + strlen(dmiData.DriverVersion) != 0) + { + if (port->hostNumber >= 0) + printf("%s is /dev/cfg/c%d, Driver is %s\n\n", + port->portName, port->hostNumber, dmiData.DriverVersion); + else + printf("%s, Driver is %s\n\n", + port->portName, dmiData.DriverVersion); + } + else + { + if (port->hostNumber >= 0) + printf("%s is /dev/cfg/c%d\n\n", + port->portName, port->hostNumber); + } + } +#endif + + i = port->fwVersion; + if (port->mptVersion < MPI_VERSION_01_02) + { + printf("Firmware version is %08x (%d.%02d.%02d)\n", + i, (i >> 12) & 0xf, (i >> 8) & 0xf, i & 0xff); + } + else + { + if (i & 0xff) + { + printf("Firmware version is %08x (%d.%02d.%02d.%02d)\n", + i, (i >> 24) & 0xff, (i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff); + } + else + { + printf("Firmware version is %08x (%d.%02d.%02d)\n", + i, (i >> 24) & 0xff, (i >> 16) & 0xff, (i >> 8) & 0xff); + } + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (mpi2) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 0, 0, + &IOUnitPage0, sizeof IOUnitPage0) == 1) + { + if (IOUnitPage0.NvdataVersionDefault.Word == IOUnitPage0.NvdataVersionPersistent.Word) + printf("NVDATA version is %08x\n", + get32(IOUnitPage0.NvdataVersionDefault.Word)); + else + printf("NVDATA version is %08x (default), %08x (persistent)\n", + get32(IOUnitPage0.NvdataVersionDefault.Word), + get32(IOUnitPage0.NvdataVersionPersistent.Word)); + } + } + else + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0, + &SASIOUnitPage0, sizeof SASIOUnitPage0) == 1) + { + if (SASIOUnitPage0.NvdataVersionDefault == SASIOUnitPage0.NvdataVersionPersistent) + printf("NVDATA version is %04x\n", + get16(SASIOUnitPage0.NvdataVersionDefault)); + else + printf("NVDATA version is %04x (default), %04x (persistent)\n", + get16(SASIOUnitPage0.NvdataVersionDefault), + get16(SASIOUnitPage0.NvdataVersionPersistent)); + } + } + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, + &ManufacturingPage0, sizeof ManufacturingPage0) == 1) + { + for (i = 0; i < sizeof ManufacturingPage0.BoardName; i++) + if (!isprint(ManufacturingPage0.BoardName[i])) + break; + if (i >= 4) + printf("Board name is %-16s\n", ManufacturingPage0.BoardName); + } + + if (port->pciType) + printf("Chip is %s, %s\n", port->chipNameRev, port->pciType); + else + printf("Chip is %s\n", port->chipNameRev); + + if (getBoardInfo(port) == 1) + { + printf("PCI location is Segment %d, Bus %d, Device %d, Function %d (combined: %02x%02x%02x)\n", + port->pciSegment, port->pciBus, port->pciDevice, port->pciFunction, + port->pciSegment, port->pciBus, (port->pciDevice << 3) | port->pciFunction); + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + printf("Initiator Mode is %s, Target Mode is %s\n", + port->protocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR ? "enabled" : "disabled", + port->protocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET ? "enabled" : "disabled"); + } + + return 1; +} + + +void +showVpdData(MPT_PORT *port, ManufacturingPage1_t *ManufacturingPage1) +{ + int i; + int j; + char c[16]; + + printf("\nRaw VPD Data:\n"); + + for (i = 0, j = 0; i < sizeof ManufacturingPage1->VPD; i++, j++) + { + if (j == 0) + printf("%04x : ", i); + + printf("%02x ", ManufacturingPage1->VPD[i]); + + if (!isprint(ManufacturingPage1->VPD[i])) + c[j] = ' '; + else + c[j] = ManufacturingPage1->VPD[i]; + + if (j == sizeof c - 1) + { + printf(" "); + for (j = 0; j < sizeof c; j++) + { + printf("%c", c[j]); + } + printf("\n"); + j = -1; + } + } +} + + +int +doDisplayVpdInfo(MPT_PORT *port) +{ + ManufacturingPage1_t ManufacturingPage1; + U8 *p; + U8 *q; + U8 tag; + int item; + int length; + int i; + int j; + int l; + int n; + char c; + int error; + int got_end; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 1, 0, + &ManufacturingPage1, sizeof ManufacturingPage1) == 1) + { + if (ManufacturingPage1.VPD[0] == 0x82) + { + printf("VPD Data is valid\n\n"); + + error = 0; + got_end = 0; + + p = ManufacturingPage1.VPD; + for (i = 0; i < sizeof ManufacturingPage1.VPD; i += length, p += length) + { + tag = p[0]; + + if (tag == 0) + break; + + if (tag & 0x80) + { + item = tag & 0x7f; + length = (p[2] << 8) + p[1]; + switch (item) + { + case 2: + l = 3 + length; + c = p[l]; + p[l] = '\0'; + printf("%02x %02x %s\n", tag, length, p + 3); + p[l] = c; + break; + + case 16: + case 17: + printf("%02x %02x\n", tag, length); + q = p + 3; + for (j = 0; j < length; j += n + 3, q += n + 3) + { + n = q[2]; + if (q[0] == 'R' && q[1] == 'W') + { + printf(" %02x RW\n", n); + continue; + } + if (q[0] == 'R' && q[1] == 'V') + { + printf(" %02x RV %02x\n", n, q[3]); + continue; + } + l = 3 + n; + c = q[l]; + q[l] = '\0'; + printf(" %02x %c%c %s\n", n, q[0], q[1], q + 3); + q[l] = c; + } + if (j != length) + { + printf(" Incorrect large resource length, should be %02x!\n", j); + error = 1; + } + break; + + default: + printf("%02x %02x Unknown large resource type!\n", tag, length); + error = 1; + break; + } + length += 3; + } + else + { + item = (tag & 0x78) >> 3; + length = tag & 0x07; + switch (item) + { + case 15: + printf("%02x %02x\n", tag, length); + if (i + 1 != sizeof ManufacturingPage1.VPD) + { + printf(" Incorrect end tag placement, is at offset %02x, should be at offset %02x\n", + i, (int)sizeof ManufacturingPage1.VPD - 1); + error = 1; + } + if (length != 0) + { + printf(" Incorrect end tag length, should be 00\n"); + error = 1; + } + got_end = 1; + break; + + default: + printf("%02x %02x Unknown small resource type!\n", tag, length); + error = 1; + break; + } + length += 1; + } + } + + if (!got_end) + { + printf("Missing end tag, expected at offset %02x!\n", i); + error = 1; + } + + if (error) + { + showVpdData(port, &ManufacturingPage1); + } + } + else + { + printf("VPD Data is not valid\n"); + } + } + + return 1; +} + + +int +doProgramVpdInfo(MPT_PORT *port) +{ + ManufacturingPage1_t ManufacturingPage1; + char name[256]; + unsigned char *vpdinfoBuf = NULL; + int vpdinfoLen; + int n; + int i; + int t; + char *buf; + int after_equals; + int in_quotes; + char serial[64]; + char *c; + int tag; + int length; + char key1; + char key2; + int lr_n; + int lr_length; + + n = getFileName(name, sizeof name, stdin, "VPD information", 0); + if (n > 0) + { + if (readFile(name, &vpdinfoBuf, &vpdinfoLen) != 1) + return 0; + } + else + { + printf("VPD information won't be programmed\n"); + return 0; + } + + printf("%d bytes read from %s\n\n", vpdinfoLen, name); + + n = vpdinfoLen; + buf = realloc(vpdinfoBuf, n + 2); + if (n && buf[n-1] != '\n') + { + vpdinfoLen++; + buf[n++] = '\n'; + } + buf[n] = '\0'; + + n = 0; + after_equals = 0; + in_quotes = 0; + for (i = 0; i < vpdinfoLen; i++) + { + if (buf[i] == '\0' || buf[i] == '\r') // NUL and CR are ignored + continue; + + if (buf[i] == ';') // lines starting with ; are ignored + { + while (buf[i] != '\n' && i < vpdinfoLen) + i++; + } + + if (n) + { + if (buf[i] == '\n' && buf[n-1] == '\n') // blank lines are ignored + continue; + } + else + { + if (buf[i] == '\n') // blank lines are ignored + continue; + } + + if (buf[i] == '=') + after_equals = 1; + + if (buf[i] == '\n') + after_equals = 0; + + if (buf[i] == '"') + in_quotes ^= 1; + + if (!in_quotes && buf[i] == ' ') + continue; + + buf[n++] = after_equals ? buf[i] : toupper(buf[i]); + } + buf[n] = '\0'; + + memset(&ManufacturingPage1, 0, sizeof ManufacturingPage1); + + ManufacturingPage1.Header.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING | + MPI_CONFIG_PAGEATTR_PERSISTENT; + ManufacturingPage1.Header.PageNumber = 1; + ManufacturingPage1.Header.PageLength = sizeof(ManufacturingPage1_t) / 4; + ManufacturingPage1.Header.PageVersion = MPI_MANUFACTURING1_PAGEVERSION; + + c = buf; + n = 0; + lr_n = 0; + lr_length = 0; + + if (sscanf(c, "LR_ID_STRING_TAG=0x%x\n%n", &tag, &t) != 1) + { + printf("LR_ID_STRING_TAG not found or invalid!\n"); + goto error; + } + ManufacturingPage1.VPD[n++] = tag; + c += t; + if (sscanf(c, "LR_ID_STRING_LENGTH=0x%x\n%n", &length, &t) != 1) + { + printf("LR_ID_STRING_LENGTH not found or invalid!\n"); + goto error; + } + ManufacturingPage1.VPD[n++] = length; + ManufacturingPage1.VPD[n++] = length >> 8; + c += t; + if (strncmp(c, "LR_ID_STRING=", 13) != 0 || c[13] != '"' || c[14+length] != '"' || c[15+length] != '\n') + { + printf("LR_ID_STRING not found or invalid!\n"); + goto error; + } + memcpy(ManufacturingPage1.VPD + n, c + 14, length); + n += length; + c += 16 + length; + + while (c[0] != '\0') + { + if (c[0] == 'S') + break; + + else if (c[0] == 'L') + { + if (lr_n && lr_n + lr_length != n) + { + printf("VPD large resource tag %02x length is incorrect, is %02x, should be %02x\n", + ManufacturingPage1.VPD[lr_n-3], lr_length, n - lr_n); + } + + if (sscanf(c, "LR_VPD_TAG=0x%x\n%n", &tag, &t) != 1) + { + printf("LR_VPD_TAG not found or invalid!\n"); + goto error; + } + ManufacturingPage1.VPD[n++] = tag; + c += t; + if (sscanf(c, "LR_VPD_LENGTH=0x%x\n%n", &length, &t) != 1) + { + printf("LR_VPD_LENGTH not found or invalid!\n"); + goto error; + } + ManufacturingPage1.VPD[n++] = length; + ManufacturingPage1.VPD[n++] = length >> 8; + c += t; + lr_n = n; + lr_length = length; + } + + else if (c[0] == 'V') + { + if (sscanf(c, "VPD_KEYWORD=\"%c%c\"\n%n", &key1, &key2, &t) != 2) + { + printf("VPD_KEYWORD not found or invalid!\n"); + goto error; + } + key1 = toupper(key1); + key2 = toupper(key2); + ManufacturingPage1.VPD[n++] = key1; + ManufacturingPage1.VPD[n++] = key2; + c += t; + if (sscanf(c, "VPD_LENGTH=0x%x\n%n", &length, &t) != 1) + { + printf("VPD_LENGTH not found or invalid!\n"); + goto error; + } + ManufacturingPage1.VPD[n++] = length; + c += t; + if (strncmp(c, "VPD_DATA=", 9) != 0) + { + printf("VPD_DATA not found or invalid!\n"); + goto error; + } + c += 9; + if (key1 == 'R' && key2 == 'V') + { + if (strncasecmp(c, "\"CHECKSUM\"\n", 11) != 0) + { + printf("VPD_DATA not found or invalid!\n"); + c -= 11; + goto error; + } + memset(ManufacturingPage1.VPD + n, 0, length); + for (i = 0, t = 0; i < n; i++) + t += ManufacturingPage1.VPD[i]; + ManufacturingPage1.VPD[n] = -t; + n += length; + c += 11; + } + else if (key1 == 'R' && key2 == 'W') + { + if (strncasecmp(c, "\"RESERVED\"\n", 11) != 0) + { + printf("VPD_DATA not found or invalid!\n"); + c -= 11; + goto error; + } + memset(ManufacturingPage1.VPD + n, 0, length); + n += length; + c += 11; + } + else if (key1 == 'S' && key2 == 'N') + { + printf("Enter serial number: [%d characters or RETURN to quit] ", length); + while (TRUE) + { + t = getStringFromArgs(serial, sizeof serial, stdin); + + if (t == 0) + { + free(buf); + return 0; + } + + if (t == length) + { + printf("\n"); + break; + } + + printf("Invalid response, try again: "); + } + memcpy(ManufacturingPage1.VPD + n, serial, length); + n += length; + while (*c != '\0') + if (*c++ == '\n') + break; + } + else + { + if (c[0] != '"' || c[1+length] != '"' || c[2+length] != '\n') + { + printf("VPD_DATA not found or invalid!\n"); + c -= 11; + goto error; + } + memcpy(ManufacturingPage1.VPD + n, c + 1, length); + n += length; + c += 3 + length; + } + } + + else + break; + } + + if (lr_n && lr_n + lr_length != n) + { + printf("VPD large resource tag %02x length is incorrect, is %02x, should be %02x\n", + ManufacturingPage1.VPD[lr_n-3], lr_length, n - lr_n); + } + + if (sscanf(c, "SR_END_TAG=0x%x\n%n", &tag, &t) != 1) + { + printf("SR_END_TAG not found or invalid!\n"); + goto error; + } + ManufacturingPage1.VPD[n++] = tag; + c += t; + + if (tag != 0x78) + { + printf("VPD end tag value is incorrect, is %02x, should be 78\n", tag); + } + + if (n != sizeof ManufacturingPage1.VPD) + { + printf("VPD end tag is misplaced, is at offset %02x, should be at offset %02x\n", + n - 1, (int)sizeof ManufacturingPage1.VPD - 1); + } + +error: + if (c[0] != '\0') + { + printf("\nExtra lines found in VPD information file!\n"); + printf("----\n%s----\n", c); + } + + free(buf); + + printf("Writing VPD Data to ManufacturingPage1...\n"); + +// showVpdData(port, &ManufacturingPage1); + + doIocInit(port, MPI_WHOINIT_MANUFACTURER); + + t = setConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 1, 0, + &ManufacturingPage1, sizeof ManufacturingPage1); + + doIocInit(port, port->whoInit); + + if (t != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +#if (WIN32 || __linux__ || __sparc__ || DOS || EFI) && REGISTER_ACCESS + + +int +doEnableDiagAccess(MPT_PORT *port, U32 *diagOrig) +{ + U32 diag; + U32 data; + + readl(DIAGNOSTIC, diag); + if ((diag & MPI_DIAG_DRWE) == 0) + { + writel(WRITE_SEQUENCE, 0); + writel(WRITE_SEQUENCE, MPI_WRSEQ_KEY_VALUE_MASK); + writel(WRITE_SEQUENCE, MPI_WRSEQ_1ST_KEY_VALUE); + writel(WRITE_SEQUENCE, MPI_WRSEQ_2ND_KEY_VALUE); + writel(WRITE_SEQUENCE, MPI_WRSEQ_3RD_KEY_VALUE); + writel(WRITE_SEQUENCE, MPI_WRSEQ_4TH_KEY_VALUE); + writel(WRITE_SEQUENCE, MPI_WRSEQ_5TH_KEY_VALUE); + } + readl(DIAGNOSTIC, data); + + if (port->notOperational) + { + writel(DIAGNOSTIC, data | MPI_DIAG_RW_ENABLE | MPI_DIAG_MEM_ENABLE | MPI_DIAG_DISABLE_ARM); + } + else + { + writel(DIAGNOSTIC, data | MPI_DIAG_RW_ENABLE | MPI_DIAG_MEM_ENABLE); + } + + *diagOrig = diag; + + return 1; +} + + +int +doReadChipMemoryRegions(MPT_PORT *port, U32 addr, U32 *buf, int num) +{ + U32 flush; + U32 diag; + U32 data; +#ifdef REG_DIAG_READ + U32 base; +#endif + int i; + + if (doEnableDiagAccess(port, &diag) != 1) + return 0; + +#ifdef REG_DIAG_READ + if (port->deviceId == MPI_MANUFACTPAGE_DEVICEID_FC919 || + port->deviceId == MPI_MANUFACTPAGE_DEVICEID_FC929) + { + for (i = 0; i < num; i++) + { + writel(TEST_BASE_ADDRESS, addr); + readl(TEST_BASE_ADDRESS, base); + + doReadWriteRegister(port, addr - base, &data, REG_DIAG_READ); + + buf[i] = data; + } + } + else +#endif + { + writel(DIAG_RW_ADDRESS, addr); + readl(DIAG_RW_ADDRESS, flush); + for (i = 0; i < num; i++) + { + readl(DIAG_RW_DATA, data); + + buf[i] = data; + } + + writel(DIAG_RW_ADDRESS, 0); + } + + writel(DIAGNOSTIC, diag); + + return 1; +} + + +int +doWriteChipMemoryRegions(MPT_PORT *port, U32 addr, U32 *buf, int num) +{ + U32 flush; + U32 diag; + U32 data; +#ifdef REG_DIAG_WRITE + U32 base; +#endif + int i; + + if (doEnableDiagAccess(port, &diag) != 1) + return 0; + +#ifdef REG_DIAG_WRITE + if (port->deviceId == MPI_MANUFACTPAGE_DEVICEID_FC919 || + port->deviceId == MPI_MANUFACTPAGE_DEVICEID_FC929) + { + for (i = 0; i < num; i++) + { + writel(TEST_BASE_ADDRESS, addr); + readl(TEST_BASE_ADDRESS, base); + + data = buf[i]; + + doReadWriteRegister(port, addr - base, &data, REG_DIAG_WRITE); + } + } + else +#endif + { + writel(DIAG_RW_ADDRESS, addr); + readl(DIAG_RW_ADDRESS, flush); + for (i = 0; i < num; i++) + { + data = buf[i]; + + writel(DIAG_RW_DATA, data); + readl(DIAG_RW_ADDRESS, flush); + } + + writel(DIAG_RW_ADDRESS, 0); + } + + writel(DIAGNOSTIC, diag); + + return 1; +} + + +int +doDumpRegisters(MPT_PORT *port) +{ + U32 data; + + readl(DOORBELL, data); + printf("Doorbell %08x\n", data); + + readl(DIAGNOSTIC, data); + printf("Diagnostic %08x\n", data); + + readl(HOST_INTERRUPT_STATUS, data); + printf("Interrupt Status %08x\n", data); + + readl(HOST_INTERRUPT_MASK, data); + printf("Interrupt Mask %08x\n", data); + + return 1; +} + + +int +readLocalMemory(MPT_PORT *port, U32 addr, U32 *data, U32 temp) +{ + ToolboxMemMoveRequest_t req; + ToolboxReply_t rep; + SGESimple32_t *simple32; + + if (checkOperational(port, 1) != 1) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_TOOLBOX; + req.Tool = MPI_TOOLBOX_MEMORY_MOVE_TOOL; + + simple32 = (pSGESimple32_t)&req.SGL; + + simple32[0].FlagsLength = set32(4 | + MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_LAST_ELEMENT | + MPI_SGE_FLAGS_32_BIT_ADDRESSING | + MPI_SGE_FLAGS_HOST_TO_IOC | + MPI_SGE_FLAGS_LOCAL_ADDRESS | + MPI_SGE_FLAGS_END_OF_BUFFER)); + simple32[0].Address = set32(addr); + simple32[1].FlagsLength = set32(4 | + MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_LAST_ELEMENT | + MPI_SGE_FLAGS_32_BIT_ADDRESSING | + MPI_SGE_FLAGS_LOCAL_ADDRESS | + MPI_SGE_FLAGS_IOC_TO_HOST | + MPI_SGE_FLAGS_END_OF_BUFFER | + MPI_SGE_FLAGS_END_OF_LIST)); + simple32[1].Address = set32(temp); + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL + 2 * sizeof *simple32, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + return 0; + + req.SGL.FlagsLength = set32(4 | + MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_LAST_ELEMENT | + MPI_SGE_FLAGS_32_BIT_ADDRESSING | + MPI_SGE_FLAGS_LOCAL_ADDRESS | + MPI_SGE_FLAGS_HOST_TO_IOC | + MPI_SGE_FLAGS_END_OF_BUFFER)); + req.SGL.u.Address32 = set32(temp); + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL + 1 * sizeof *simple32, &rep, sizeof rep, + data, 4, NULL, 0, SHORT_TIME) != 1) + return 0; + + *data = get32x(*data); + + return 1; +} + + +int +doDumpChipMemoryRegions(MPT_PORT *port) +{ + FILE *file; + char name[256]; + int n; + U32 diag; + U32 start; + U32 end; + U32 data; + int i; + U32 tempaddr; + U32 tempdata; + int binary = 0; + int binfile; + + readl(DIAGNOSTIC, diag); // this will return if register access does not work + + while (TRUE) + { + printf("Enter starting address: [00000000-FFFFFFFF or RETURN to quit] "); + if (getHexNumberAnswer(&start) == 0) + break; + + printf("Enter ending address: [%08x-FFFFFFFF or RETURN to skip] ", start); + while (TRUE) + { + if (getHexNumberAnswer(&end) == 0) + { + printf("Enter number of locations: [1-1000000, default is 1] "); + n = getNumberAnswer(1, 1000000, 1); + end = start + (n - 1) * 4; + break; + } + if (start <= end) + break; + + printf("Invalid answer, try again: "); + } + + if (numFileNames) + { + n = getFileName(name, sizeof name, stdin, "output", 0); + } + else + { + printf("Enter output filename, or RETURN to send output to the screen: "); + n = getString(name, sizeof name, stdin); + } + if (n > 0) + { + if (gFlag == TRUE) + { + printf("File type: [0=ASCII, 1=Binary, default is 0] "); + binary = getNumberAnswer(0, 1, 0); + } + if (binary) + { + binfile = open(name, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + if (binfile < 0) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + file = NULL; + } + else + { + file = fopen(name, "a"); + if (file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + binfile = -1; + } + } + else + { + file = stdout; + binfile = -1; + printf("\n"); + } + + start &= ~3; + end &= ~3; + + i = 0; + + if (end <= 0x10000000 && !port->notOperational) + { + tempaddr = 0; + tempdata = 0; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + switch (port->deviceId) + { + case MPI_MANUFACTPAGE_DEVICEID_FC919X: + case MPI_MANUFACTPAGE_DEVICEID_FC929X: + if (port->fwVersion >= 0x01021404) // 1.02.20.04 or later... + tempaddr = 0x21000000; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC939X: + case MPI_MANUFACTPAGE_DEVICEID_FC949X: + if (port->fwVersion >= 0x01031101) // 1.03.17.01 or later... + tempaddr = 0x21fc0000; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC949E: + if (port->fwVersion >= 0x01031101) // 1.03.17.01 or later... + tempaddr = 0x21f80000; + break; + } + } + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + tempaddr = 0x21fffffc; + } + + if (tempaddr != 0) + { + doReadChipMemoryRegions(port, tempaddr, &tempdata, 1); + } + + while (start <= end) + { + if (tempaddr != 0 && readLocalMemory(port, start, &data, tempaddr) == 1) + { + if (binary) + { + data = set32x(data); + i += write(binfile, &data, 4); + } + else + i += fprintf(file, "%08x: %08x\n", start, data); + start += 4; + } + else + { + printf("Unable to read local memory!\n"); + break; + } + } + + if (tempaddr != 0) + { + doWriteChipMemoryRegions(port, tempaddr, &tempdata, 1); + } + } + else + { + while (start <= end) + { + doReadChipMemoryRegions(port, start, &data, 1); + + if (binary) + { + data = set32x(data); + i += write(binfile, &data, 4); + } + else + i += fprintf(file, "%08x: %08x\n", start, data); + start += 4; + } + } + + if (n > 0) + { + printf("\nWrote %d bytes to file %s\n", i, name); + + if (binary) + close(binfile); + else if (file != stdout) + fclose(file); + } + + printf("\n"); + } + + return 1; +} + + +int +doReadModifyChipMemoryLocations(MPT_PORT *port) +{ + U32 diag; + U32 addr; + U32 data; + + while (TRUE) + { + readl(DIAGNOSTIC, diag); // this will return if register access does not work + + printf("Enter address: [00000000-FFFFFFFF or RETURN to quit] "); + if (getHexNumberAnswer(&addr) == 0) + break; + + addr &= ~3; + + doReadChipMemoryRegions(port, addr, &data, 1); + + printf("%08x: %08x\n", addr, data); + + printf("Enter value: [00000000-FFFFFFFF or RETURN to skip] "); + if (parseHexNumberChange(&data) == 1) + { + doWriteChipMemoryRegions(port, addr, &data, 1); + } + + printf("\n"); + } + + return 1; +} + + +int +doDumpFcTraceBuffer(MPT_PORT *port) +{ + FILE *file; + char name[256]; + int n; + int i = 0; + U32 diag; + U32 addr; + U32 data; + U32 ptr1; + U32 len1; + U32 ptr2; + U32 len2; + + switch (port->deviceId) + { + case MPI_MANUFACTPAGE_DEVICEID_FC919: addr = 0x01000000; break; + case MPI_MANUFACTPAGE_DEVICEID_FC929: addr = 0x01000000; break; + case MPI_MANUFACTPAGE_DEVICEID_FC919X: addr = 0x21000000; break; + case MPI_MANUFACTPAGE_DEVICEID_FC929X: addr = 0x21000000; break; + case MPI_MANUFACTPAGE_DEVICEID_FC939X: addr = 0x21fc0000; break; + case MPI_MANUFACTPAGE_DEVICEID_FC949X: addr = 0x21fc0000; break; + case MPI_MANUFACTPAGE_DEVICEID_FC949E: addr = 0x21f80000; break; + default: + printf("Unsupported chip type!\n"); + return 0; + } + + readl(DIAGNOSTIC, diag); // this will return if register access does not work + + doReadChipMemoryRegions(port, addr, &data, 1); + + if (data <= addr || data & 3) + { + printf("FC trace buffer address is invalid\n"); + + return 0; + } + else + { + addr = data; + + doReadChipMemoryRegions(port, addr, &data, 1); + + if (data != ('T' << 24) + ('R' << 16) + ('A' << 8) + ('C' << 0)) + { + printf("FC trace buffer signature is invalid\n"); + + return 0; + } + } + + n = getFileName(name, sizeof name, stdin, "output", 0); + if (n > 0) + { + file = fopen(name, "w"); + if (file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + } + else + { + printf("Trace buffer won't be dumped\n"); + return 1; + } + + printf("\n"); + printf("TraceInfo %08x\n", addr); + printf("TraceSignature %08x\n", data); + + doReadChipMemoryRegions(port, addr + 4, &data, 1); + printf("TraceIndex %08x\n", data); + + doReadChipMemoryRegions(port, addr + 8, &data, 1); + printf("TraceHistoryBuf %08x\n", data); + ptr1 = data; + + doReadChipMemoryRegions(port, addr + 12, &data, 1); + printf("TraceHistoryBufSize %08x\n", data); + len1 = data; + + doReadChipMemoryRegions(port, addr + 16, &data, 1); + printf("TraceCounters %08x\n", data); + ptr2 = data; + + doReadChipMemoryRegions(port, addr + 20, &data, 1); + printf("NumTraceCounters %08x\n", data); + len2 = data; + + while (len1) + { + doReadChipMemoryRegions(port, ptr1, &data, 1); + i += fprintf(file, "%08x: %08x\n", ptr1, data); + ptr1 += 4; + len1 -= 1; + } + + while (len2) + { + doReadChipMemoryRegions(port, ptr2, &data, 1); + i += fprintf(file, "%08x: %08x\n", ptr2, data); + ptr2 += 4; + len2 -= 1; + } + + printf("\nWrote %d bytes to file %s\n", i, name); + + fclose(file); + + return 1; +} + + +int +doForceFirmwareFault(MPT_PORT *port) +{ + printf("Writing C0FFEE to Doorbell...\n"); + + writel(DOORBELL, 0xc0ffee00); + + return 1; +} + + +#endif + + +int +doReadWriteExpanderMemory(MPT_PORT *port) +{ + int i; + int j; + _U64 sas_address; + U8 physical_port; + U32 addr; + U32 data; + int n; + int action; + int ringFormat; + U16 ringAddr = 0; + int numDwords; + + if (selectExpander(port, NULL, NULL, &physical_port, &sas_address, NULL) != 1) + return 0; + + printf("\nDo you want to use the AHB (x28/x36/Bobcat/Cobra)\n"); + printf("or Ring (x12) format SMP? [0=AHB, 1=Ring, default is 0] "); + ringFormat = getNumberAnswer(0, 1, 0); + + while (TRUE) + { + if (ringFormat) + { + printf("\nEnter address: [00000-7FFFF or RETURN to quit] "); + addr = getNumberAnswerHex(0, 0x7FFFF, 0xFFFFFFFF); + if (addr == 0xFFFFFFFF) + break; + } + else + { + printf("\nEnter address: [00000000-FFFFFFFF or RETURN to quit] "); + if (getHexNumberAnswer(&addr) == 0) + break; + } + + while (TRUE) + { + printf("\nDo you want to read or write? [0=Read, 1=Write, or RETURN for new address] "); + action = getNumberAnswer(0, 1, -1); + if (action < 0) + break; + + printf("\n"); + + if (action == 0) + { + unsigned char smp_req[8]; + unsigned char smp_rsp[1024]; + + if (ringFormat) + { + printf("Enter number of locations: [1-127, default is 1] "); + n = getNumberAnswer(1, 127, 1); + } + else + { + printf("Enter number of locations: [1-128, default is 1] "); + n = getNumberAnswer(1, 128, 1); + } + + addr &= ~3; + + memset(smp_req, 0, sizeof smp_req); + + smp_req[0] = 0x40; + + if (ringFormat) + smp_req[1] = 0x40; + else + smp_req[1] = 0x42; + + smp_req[2] = 0xff; + smp_req[3] = n; + + if (ringFormat) + { + /* starting address must be on an 8-byte boundary */ + ringAddr = (addr >> 3) & 0xFFFF; + put2bytes(smp_req, 4, ringAddr); + } + else + { + put4bytes(smp_req, 4, addr); + } + + if (doSmpPassthrough(port, physical_port, sas_address, + smp_req, sizeof smp_req, smp_rsp, sizeof smp_rsp, NULL) == 1) + { + if (smp_rsp[2] != 0) + { + printf("\nRead Memory failed with result %02x\n\n", smp_rsp[2]); + continue; + } + + printf("\n"); + + if (ringFormat) + { + /* this SMP returns 2 DWORDS for each requested location. The + * starting address for returned data is the user supplied address + * with bits 0-2 cleared (i.e. the 8-byte boundary) + */ + numDwords = n*2; + addr = ringAddr << 3; + } + else + numDwords = n; + + for (i = 0, j = 0; i < numDwords; i++, j += 4) + { + data = get4bytes(smp_rsp, j + 4); + + printf("%08x: %08x\n", addr + j, data); + } + } + } + + if (action == 1) + { + unsigned char smp_req[16]; + unsigned char smp_rsp[4]; + + printf("Enter value: [00000000-FFFFFFFF or RETURN to not change] "); + if (getHexNumberAnswer(&data) == 0) + continue; + + addr &= ~3; + + memset(smp_req, 0, sizeof smp_req); + + smp_req[0] = 0x40; + if (ringFormat) + smp_req[1] = 0xc0; + else + smp_req[1] = 0xc2; + smp_req[2] = 0xff; + smp_req[3] = 1; + + if (ringFormat) + { + int firstDword; + int byteEnables; + int dataOffset; + + /* starting address must be on an 8-byte boundary */ + ringAddr = (addr >> 3) & 0xFFFF; + put2bytes(smp_req, 4, ringAddr); + + /* determine whether the data is going in the first or second + * dword and which byte enables are needed + */ + firstDword = (addr & 0x04) == 0 ? 1 : 0; + byteEnables = firstDword ? 0x0F : 0xF0; + dataOffset = firstDword ? 8 : 12; + + smp_req[6] = byteEnables; + smp_req[7] = byteEnables; + put4bytes(smp_req, dataOffset, data); + } + else + { + put4bytes(smp_req, 4, addr); + put4bytes(smp_req, 8, data); + } + + if (doSmpPassthrough(port, physical_port, sas_address, + smp_req, sizeof smp_req, smp_rsp, sizeof smp_rsp, NULL) == 1) + { + if (smp_rsp[2] != 0) + { + printf("\nWrite Memory failed with result %02x\n\n", smp_rsp[2]); + continue; + } + } + } + } + } + + return 1; +} + + +int +doReadWriteExpanderIstwiDevice(MPT_PORT *port) +{ + int bus; + int target; + unsigned char desc[4]; + unsigned char scan[1]; + int i; + int j; + int n; + int t; + char name[256]; + FILE *file; + unsigned char *buffer = NULL; + int length; + int offset; + int id; + int channel; + int address; + int size; + int action; + char c[16]; + + if (selectExpander(port, &bus, &target, NULL, NULL, NULL) != 1) + return 0; + + while (TRUE) + { + printf("\nEnter ISTWI device channel: [0-2 or RETURN to quit] "); + channel = getNumberAnswerHex(0, 2, -1); + if (channel < 0) + break; + + printf("Enter ISTWI device address: [00-FF or RETURN to quit] "); + address = getNumberAnswerHex(0x00, 0xff, -1); + if (address < 0) + break; + + if (address <= 1) + { + j = address == 0; + if (j) + printf("\nScanning for ISTWI devices...\n"); + else + printf("\nReading ISTWI devices...\n"); + fflush(stdout); + + for (i = 0; i < 128; i++) + { + if ((i & 15) == 0) + printf("\n"); + + address = i << 17; + id = 12 + channel; + + if (doReadBufferFull(port, bus, target, 0, 2, id, address, scan, sizeof scan) == 1) + { + if (j) + printf(" %02x", i << 1); + else + printf(" %02x", scan[0]); + } + else + { + printf(" --"); + } + + fflush(stdout); + } + + printf("\n"); + + continue; + } + + address &= ~1; + + printf("Enter ISTWI device size in bytes: [0=1, 1=256, 2=8192, or RETURN to quit] "); + size = getNumberAnswer(0, 2, -1); + if (size < 0) + break; + + address <<= 16; + id = 12 + channel + size * 3; + + if (doReadBufferFull(port, bus, target, 0, 3, id, address, desc, sizeof desc) == 1) + { + size = get3bytes(desc, 1); + } + else + { + printf("ISTWI device size could not be verified, cannot continue!\n"); + return 1; + } + + while (TRUE) + { + printf("\nDo you want to read or write? [0=Read, 1=Write, or RETURN for new device] "); + action = getNumberAnswer(0, 1, -1); + if (action < 0) + break; + + printf("\n"); + + if (action == 0) + { + if (size > 1) + { + printf("Enter read offset: [0-%X, default is 0] ", size - 1); + offset = getNumberAnswerHex(0, size - 1, 0); + + printf("Enter read length: [1-%X, default is %X] ", size - offset, size - offset); + length = getNumberAnswerHex(1, size - offset, size - offset); + } + else + { + offset = 0; + length = 1; + } + + buffer = (unsigned char *)malloc(length); + + if (doReadBufferFull(port, bus, target, 0, 2, id, address + offset, buffer, length) != 1) + { + printf("Failed to read ISTWI device!\n"); + break; + } + + if (length <= 16) + { + n = 0; + if (size > 1) + printf("\n"); + } + else if (numFileNames) + { + n = getFileName(name, sizeof name, stdin, "output", 0); + } + else + { + printf("Enter output filename, or RETURN to send output to the screen: "); + n = getString(name, sizeof name, stdin); + if (n == 0) + printf("\n"); + } + if (n > 0) + { + if (gFlag == TRUE) + { + printf("File type: [0=ASCII, 1=Binary, default is 0] "); + t = getNumberAnswer(0, 1, 0); + } + else + { + t = 0; + } + if (t) + { + int file; + + file = open(name, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + if (file < 0) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + } + else + { + t = write(file, buffer, length); + if (t != length) + { + printf("Write failed for file %s, t = %x\n", name, t); + perror("Error is"); + } + else + { + printf("\nWrote %d bytes to file %s\n", length, name); + } + + close(file); + } + + free(buffer); + continue; + } + else + { + file = fopen(name, "w"); + if (file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + + free(buffer); + continue; + } + } + } + else + { + file = stdout; + } + + for (i = 0, j = 0; i < length; i++, j++) + { + if (j == 0) + fprintf(file, "%04x : ", i); + + fprintf(file, "%02x ", buffer[i]); + + if (!isprint(buffer[i])) + c[j] = ' '; + else + c[j] = buffer[i]; + + if (j == sizeof c - 1) + { + fprintf(file, " "); + for (j = 0; j < sizeof c; j++) + { + fprintf(file, "%c", c[j]); + } + fprintf(file, "\n"); + j = -1; + } + } + + if (j != 0) + { + for (i = j; i < sizeof c; i++) + fprintf(file, " "); + + fprintf(file, " "); + for (i = 0; i < j; i++) + { + fprintf(file, "%c", c[i]); + } + fprintf(file, "\n"); + } + + if (file != stdout) + fclose(file); + + free(buffer); + } + + if (action == 1) + { + if (size > 1) + { + printf("Enter write offset: [0-%X, default is 0] ", size - 1); + offset = getNumberAnswerHex(0, size - 1, 0); + } + else + { + offset = 0; + } + + printf("Enter value: [00-FF or RETURN to not change] "); + t = getNumberAnswerHex(0x00, 0xff, -1); + if (t < 0) + continue; + + scan[0] = t; + + if (doWriteBufferFull(port, bus, target, 0, 2, id, address + offset, scan, 1) != 1) + { + printf("Failed to write ISTWI device!\n"); + break; + } + } + } + } + + return 1; +} + + +int +doResetExpander(MPT_PORT *port) +{ + _U64 sas_address; + U8 physical_port; + U32 addr; + U32 data; + int n; + + if (selectExpander(port, NULL, NULL, &physical_port, &sas_address, NULL) != 1) + return 0; + + printf("\nResetting expander...\n"); + + addr = 0xc3800200; // cobra reset address + data = 0x0c0b080a; // cobra reset value + + /* first attempt the reset using the cobra reset value (this write will go to + * reserved address space on bobcat and yeti) + */ + if ((n = sendResetExpander(port, physical_port, sas_address, addr, data)) == 2) + { + /* no good. now try yeti */ + addr = 0xc0000200; // yeti and bobcat reset address + data = 0x59455449; // yeti reset value + + /* attempt the reset using the yeti reset value */ + if ((n = sendResetExpander(port, physical_port, sas_address, addr, data)) == 2) + { + /* no good. Try using the bobcat reset value instead */ + data = 0x0b0bca70; // bobcat reset value + if ((n = sendResetExpander(port, physical_port, sas_address, addr, data)) != 1) + return 0; + } + } + + return n; +} + + +int +sendResetExpander(MPT_PORT *port, U8 physical_port, _U64 sas_address, U32 addr, U32 data) +{ + SmpPassthroughRequest_t req; + SmpPassthroughReply_t rep; + int ioc_status; + unsigned char smp_req[12]; + unsigned char smp_rsp[4]; + + memset(smp_req, 0, sizeof smp_req); + memset(smp_rsp, 0, sizeof smp_rsp); + + smp_req[0] = 0x40; + smp_req[1] = 0xc2; + smp_req[3] = 1; + put4bytes(smp_req, 4, addr); + put4bytes(smp_req, 8, data); + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SMP_PASSTHROUGH; + req.PhysicalPort = physical_port; + req.RequestDataLength = set16(sizeof smp_req); + req.SASAddress = sas_address; + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + smp_rsp, sizeof smp_rsp, smp_req, sizeof smp_req, SHORT_TIME) == 1) + { + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS && + ioc_status != MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED) + { + printf("\nSMPPassthrough failed, IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); + return 0; + } + + /* if the SMP function result is 0 (success) or 2 (function failed) then assume it is ok to move on and + * key off the ioc_status. Since writing the cobra values to a bobcat attempts to write to a reserved + * memory region, bobcat might return function failed in that case. + */ + if (smp_rsp[2] != 0 && smp_rsp[2] != 2) + { + printf("\nWrite Memory failed with result %02x\n\n", smp_rsp[2]); + return 0; + } + + /* successfully resetting the expander should result in an ioc_status of + * SAS_SMP_REQUEST_FAILED (because the reset happens immediately and an SMP response + * is not sent to the host). + * If we get SUCCESS then assume we sent the wrong reset (i.e. the yeti value to a bobcat) + * and return a 2, indicating to the caller to try a different reset value. + */ + if (ioc_status == MPI_IOCSTATUS_SUCCESS) + return 2; + } + + return 1; +} + + +#if (WIN32 || __linux__ || __sparc__ || DOS || EFI) && REGISTER_ACCESS + + +int +setFlashWrite(MPT_PORT *port, U32 flash_csr, U32 flash_csr_wr_en, int on) +{ + U32 flush; + U32 data; + + writel(DIAG_RW_ADDRESS, flash_csr); + readl(DIAG_RW_ADDRESS, flush); + readl(DIAG_RW_DATA, data); + + if (on) + data |= flash_csr_wr_en; + else + data &= ~flash_csr_wr_en; + + writel(DIAG_RW_ADDRESS, flash_csr); + readl(DIAG_RW_ADDRESS, flush); + writel(DIAG_RW_DATA, data); + readl(DIAG_RW_ADDRESS, flush); + + return 1; +} + + +U32 +readFlash(MPT_PORT *port, U32 flash_add, int offset) +{ + U32 flush; + U32 addr; + U32 data; + + addr = flash_add + offset; + + writel(DIAG_RW_ADDRESS, addr); + readl(DIAG_RW_ADDRESS, flush); + readl(DIAG_RW_DATA, data); + +// printf("rf %08x %08x\n", addr, data); + + return data; +} + + +int +writeFlash(MPT_PORT *port, U32 flash_add, int offset, U32 data) +{ + U32 flush; + U32 addr; +#ifdef REG_DIAG_WRITE_BYTE + U32 base; +#endif + int lane; + + lane = offset & 3; + addr = flash_add + offset; + +#ifdef REG_DIAG_WRITE_BYTE + switch (port->deviceId) + { + case MPI_MANUFACTPAGE_DEVID_53C1030: + case MPI_MANUFACTPAGE_DEVID_1030_53C1035: + writel(TEST_BASE_ADDRESS, addr); + readl(TEST_BASE_ADDRESS, base); + +// printf("wf %08x %02x\n", addr, data); + + doReadWriteRegister(port, addr - base, &data, REG_DIAG_WRITE_BYTE); + readl(TEST_BASE_ADDRESS, flush); + + return 1; + } +#endif + + addr -= lane; + data <<= 24; + data += lane; + +// printf("wf %08x %08x\n", addr, data); + + writel(DIAG_RW_ADDRESS, addr); + readl(DIAG_RW_ADDRESS, flush); + writel(DIAG_RW_DATA, data); + readl(DIAG_RW_ADDRESS, flush); + + return 1; +} + + +void +resetFlash(MPT_PORT *port, U32 flash_csr, U32 flash_csr_wr_en, U32 flash_add, int intel) +{ + setFlashWrite(port, flash_csr, flash_csr_wr_en, 1); + writeFlash(port, flash_add, 0, intel ? FLASH_RESET_INTEL : FLASH_RESET_AMD); + setFlashWrite(port, flash_csr, flash_csr_wr_en, 0); +} + + +int +doFlashInfo(MPT_PORT *port) +{ + U32 diag; + U32 data; + U32 flash_add; + U32 flash_csr; + U32 flash_csr_wr_en; + U32 id; + unsigned char cfi_query[128]; + int i; + int t; + + if (doEnableDiagAccess(port, &diag) != 1) // this will return if register access does not work + return 0; + + switch (port->deviceId) + { + case MPI_MANUFACTPAGE_DEVICEID_FC939X: + case MPI_MANUFACTPAGE_DEVICEID_FC949X: + case MPI_MANUFACTPAGE_DEVICEID_FC949E: + flash_add = 0x3d000000; + flash_csr = 0x3f000004; + flash_csr_wr_en = 1<<16; + break; + +#ifdef REG_DIAG_WRITE_BYTE + case MPI_MANUFACTPAGE_DEVID_53C1030: + case MPI_MANUFACTPAGE_DEVID_1030_53C1035: + flash_add = 0x3e000000; + flash_csr = 0x3f000000; + flash_csr_wr_en = 1<<11; + break; +#endif + + case MPI_MANUFACTPAGE_DEVICEID_FC919X: + case MPI_MANUFACTPAGE_DEVICEID_FC929X: + case MPI_MANUFACTPAGE_DEVID_SAS1064: + case MPI_MANUFACTPAGE_DEVID_SAS1064E: + case MPI_MANUFACTPAGE_DEVID_SAS1066: + case MPI_MANUFACTPAGE_DEVID_SAS1066E: + case MPI_MANUFACTPAGE_DEVID_SAS1068: + case MPI_MANUFACTPAGE_DEVID_SAS1068E: + flash_add = 0x3e000000; + flash_csr = 0x3f000004; + flash_csr_wr_en = 1<<16; + break; + + default: + printf("Unable to gather FLASH information\n"); + return 0; + } + + data = readFlash(port, flash_add, 0); + t = 0; + + if (t == 0) + { + setFlashWrite(port, flash_csr, flash_csr_wr_en, 1); + writeFlash(port, flash_add, 0, FLASH_RESET_INTEL); + writeFlash(port, flash_add, 0, FLASH_IDENTIFY); + setFlashWrite(port, flash_csr, flash_csr_wr_en, 0); + id = readFlash(port, flash_add, 0); + + if (id != data && id != 0) + { + printf("Intel-compatible FLASH device, Manufacturer ID = %02x and Device ID = %02x\n", + (id >> 0) & 0xff, (id >> 8) & 0xff); + resetFlash(port, flash_csr, flash_csr_wr_en, flash_add, 1); + t = 1; + } + } + + if (t == 0) + { + setFlashWrite(port, flash_csr, flash_csr_wr_en, 1); + writeFlash(port, flash_add, 0, FLASH_RESET_AMD); + writeFlash(port, flash_add, 0x555, 0xaa); + writeFlash(port, flash_add, 0x2aa, 0x55); + writeFlash(port, flash_add, 0x555, FLASH_IDENTIFY); + setFlashWrite(port, flash_csr, flash_csr_wr_en, 0); + id = readFlash(port, flash_add, 0); + + if (id != data && id != 0) + { + printf("AMD-compatible 8-bit FLASH device, Manufacturer ID = %02x and Device ID = %02x\n", + (id >> 0) & 0xff, (id >> 8) & 0xff); + resetFlash(port, flash_csr, flash_csr_wr_en, flash_add, 0); + t = 1; + } + } + + if (t == 0) + { + setFlashWrite(port, flash_csr, flash_csr_wr_en, 1); + writeFlash(port, flash_add, 0, FLASH_RESET_AMD); + writeFlash(port, flash_add, 0xaaa, 0xaa); + writeFlash(port, flash_add, 0x555, 0x55); + writeFlash(port, flash_add, 0xaaa, FLASH_IDENTIFY); + setFlashWrite(port, flash_csr, flash_csr_wr_en, 0); + id = readFlash(port, flash_add, 0); + + if (id != data && id != 0) + { + printf("AMD-compatible 16-bit FLASH device, Manufacturer ID = %02x and Device ID = %02x\n", + (id >> 0) & 0xff, (id >> 16) & 0xff); + resetFlash(port, flash_csr, flash_csr_wr_en, flash_add, 0); + t = 1; + } + } + + setFlashWrite(port, flash_csr, flash_csr_wr_en, 1); + writeFlash(port, flash_add, 0, FLASH_RESET_AMD); + writeFlash(port, flash_add, 0x55, FLASH_CFI_QUERY); + setFlashWrite(port, flash_csr, flash_csr_wr_en, 0); + for (i = 0; i < sizeof cfi_query; i += 4) + *((U32 *)(cfi_query + i)) = set32x(readFlash(port, flash_add, i)); + resetFlash(port, flash_csr, flash_csr_wr_en, flash_add, 0); + + if (cfi_query[16] == 'Q' && cfi_query[17] == 'R' && cfi_query[18] == 'Y') + { + printf("CFI-compatible 8-bit or 16-bit FLASH device\n\n"); + displayByteData((unsigned char *)cfi_query, sizeof cfi_query / 2); + writel(DIAGNOSTIC, diag); + return 1; + } + + setFlashWrite(port, flash_csr, flash_csr_wr_en, 1); + writeFlash(port, flash_add, 0, FLASH_RESET_AMD); + writeFlash(port, flash_add, 0xaa, FLASH_CFI_QUERY); + setFlashWrite(port, flash_csr, flash_csr_wr_en, 0); + for (i = 0; i < sizeof cfi_query; i += 4) + *((U32 *)(cfi_query + i)) = set32x(readFlash(port, flash_add, i)); + resetFlash(port, flash_csr, flash_csr_wr_en, flash_add, 0); + + if (cfi_query[32] == 'Q' && cfi_query[34] == 'R' && cfi_query[36] == 'Y') + { + printf("CFI-compatible 16-bit FLASH device in 8-bit mode\n\n"); + for (i = 0; i < sizeof cfi_query / 2; i++) + cfi_query[i] = cfi_query[i * 2]; + displayByteData((unsigned char *)cfi_query, sizeof cfi_query / 2); + writel(DIAGNOSTIC, diag); + return 1; + } + + if (t == 0) + printf("Could not detect FLASH type!\n"); + writel(DIAGNOSTIC, diag); + + return 0; +} + + +int +doReadRegister(MPT_PORT *port, U32 offset, U32 *data) +{ + int command = REG_MEM_READ; + + if (port->deviceId == MPI_MANUFACTPAGE_DEVID_53C1030 && + (offset == MPI_DIAG_RW_DATA_OFFSET || offset == MPI_DIAG_RW_ADDRESS_OFFSET)) + { + command = REG_IO_READ; + } + + return doReadWriteRegister(port, offset, data, command); +} + + +int +doWriteRegister(MPT_PORT *port, U32 offset, U32 *data) +{ + int command = REG_MEM_WRITE; + + if (port->deviceId == MPI_MANUFACTPAGE_DEVID_53C1030 && + (offset == MPI_DIAG_RW_DATA_OFFSET || offset == MPI_DIAG_RW_ADDRESS_OFFSET)) + { + command = REG_IO_WRITE; + } + + return doReadWriteRegister(port, offset, data, command); +} + + +int +doReadWriteRegister(MPT_PORT *port, U32 offset, U32 *data, int command) +{ +#if WIN32 + int status; + MPI_REG_ACCESS_SRB srb; + int inLen; + int outLen; + DWORD retLen; + + memset(&srb, 0, sizeof srb); + + srb.Sic.Length = sizeof srb - sizeof srb.Sic; + srb.Sic.ControlCode = MPI_REG_ACCESS; + srb.Sic.HeaderLength = sizeof srb.Sic; + srb.Sic.Timeout = SHORT_TIME; + + memcpy((char *)&srb.Sic.Signature, "4.00 ", 8); + + srb.Command = command; + srb.RegOffset = offset; + srb.RegData = *data; + + inLen = sizeof srb; + outLen = sizeof srb; + retLen = 0; + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + &srb, inLen, &srb, outLen, &retLen, NULL); + + *data = srb.RegData; + + return status; +#endif +#if __linux__ +#if i386 + if (command == REG_IO_READ) + { + if (port->ioPhys == 0) + return 0; + + *data = inl(port->ioPhys + offset); + return 1; + } + + if (command == REG_IO_WRITE) + { + if (port->ioPhys == 0) + return 0; + + outl(*data, port->ioPhys + offset); + return 1; + } +#endif + + if (command == REG_MEM_READ) + { + if (port->memPhys == 0) + return 0; + + *data = get32x(*(port->memVirt + offset / 4)); + return 1; + } + + if (command == REG_MEM_WRITE) + { + if (port->memPhys == 0) + return 0; + + *(port->memVirt + offset / 4) = set32x(*data); + return 1; + } + + if (command == REG_DIAG_READ) + { + if (port->diagPhys == 0) + return 0; + + *data = get32x(*(port->diagVirt + offset / 4)); + return 1; + } + + if (command == REG_DIAG_WRITE) + { + if (port->diagPhys == 0) + return 0; + + *(port->diagVirt + offset / 4) = set32x(*data); + return 1; + } + + if (command == REG_DIAG_WRITE_BYTE) + { + if (port->diagPhys == 0) + return 0; + + *((U8 *)port->diagVirt + offset) = (U8)*data; + return 1; + } + + return 0; +#endif +#if __sparc__ + int status; + SYM_REG_ACCESS regAccess; + + regAccess.Command = command; + regAccess.RegOffset = offset; + regAccess.RegData = *data; + + // Not implemented for gen2 SAS driver...just let it fail in that case + status = ioctl(port->fileHandle, SYMIOCTL_REG_ACCESS, ®Access); + + *data = regAccess.RegData; + + return status == 0; +#endif +#if DOS || EFI + HANDLE adap = port->fileHandle; + + if (command == REG_IO_READ) + { + *data = mpt_read32(adap, offset, adap->io); + return 1; + } + + if (command == REG_MEM_READ) + { + *data = mpt_read32(adap, offset, adap->mem); + return 1; + } + + if (command == REG_DIAG_READ) + { + *data = mpt_read32(adap, offset, adap->diagmem); + return 1; + } + + if (command == REG_IO_WRITE) + { + mpt_write32(adap, offset, *data, adap->io); + return 1; + } + + if (command == REG_MEM_WRITE) + { + mpt_write32(adap, offset, *data, adap->mem); + return 1; + } + + if (command == REG_DIAG_WRITE) + { + mpt_write32(adap, offset, *data, adap->diagmem); + return 1; + } + + if (command == REG_DIAG_WRITE_BYTE) + { + mpt_write8(adap, offset, (U8)*data); + return 1; + } + + return 0; +#endif +} + + +#endif + + +int +doDumpPciConfigSpace(MPT_PORT *port) +{ +#if WIN32 + int status; + PCI_CONFIG_SPACE_SRB srb; + int inLen; + int outLen; + DWORD retLen; + U8 *config; +#endif +#if __linux__ + char name[64]; + HANDLE handle; + U8 config[256]; +#endif +#if __sparc__ + SYM_PCI_INFO pciInfo; + int status; + U8 *config; +#endif +#if DOS + HANDLE adap = port->fileHandle; + U8 config[256]; + int i; +#endif +#if EFI + EFI_STATUS status; + HANDLE adap = port->fileHandle; + U8 config[256]; +#endif + + if (getBoardInfo(port) == 1) + { + printf("PCI location is Segment %d, Bus %d, Device %d, Function %d (combined: %02x%02x%02x)\n", + port->pciSegment, port->pciBus, port->pciDevice, port->pciFunction, + port->pciSegment, port->pciBus, (port->pciDevice << 3) | port->pciFunction); + } + +#if WIN32 + memset(&srb, 0, sizeof srb); + + srb.Sic.Length = sizeof srb - sizeof srb.Sic; + srb.Sic.ControlCode = DRVR_INFO_IOCTL; + srb.Sic.HeaderLength = sizeof srb.Sic; + srb.Sic.Timeout = SHORT_TIME; + + memcpy((char *)&srb.Sic.Signature, "4.00 ", 8); + + srb.PageCode = PCI_CONFIG_SPACE_PAGE; + + inLen = sizeof srb; + outLen = sizeof srb; + retLen = 0; + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + &srb, inLen, &srb, outLen, &retLen, NULL); + + if (status != 1) + return 0; + + config = srb.PciConfigSpace; +#endif +#if __linux__ + sprintf(name, "/proc/bus/pci/%04x:%02x/%02x.%d", + port->pciSegment, port->pciBus, port->pciDevice, port->pciFunction); + + handle = open(name, O_RDWR); + + if (handle < 0) + { + sprintf(name, "/proc/bus/pci/%02x/%02x.%d", + port->pciBus, port->pciDevice, port->pciFunction); + + handle = open(name, O_RDWR); + + if (handle < 0) + return 0; + } + + if (read(handle, config, sizeof config) != sizeof config) + return 0; +#endif +#if __sparc__ + memset(&pciInfo, 0, sizeof pciInfo); + + if (mpi2) + status = ioctl(port->fileHandle, MPTIOCTL_GET_PCI_INFO, &pciInfo); + else + status = ioctl(port->fileHandle, SYMIOCTL_GET_PCI_INFO, &pciInfo); + + if (status != 0) + return 0; + + config = pciInfo.PciHeader; +#endif +#if DOS + for (i = 0; i < 256; i++) + { + config[i] = PciReadConfigByte(adap->bus_number, adap->device_function, i); + } +#endif +#if EFI + status = adap->pci_io->Pci.Read(adap->pci_io, EfiPciIoWidthUint8, 0, + sizeof config, config); + if (EFI_ERROR(status)) + return 0; +#endif + + dumpMemoryWide(config, 256, "PCI Config Space"); + + return 1; +} + + +char *pageType[32] = +{ + "IO Unit", + "IOC", + "BIOS", + "SCSI Port", + "SCSI Device", + "FC Port", + "FC Device", + "LAN", + "RAID Volume", + "Manufacturing", + "RAID PhysDisk", + "Inband", + "Type 0Ch", + "Type 0Dh", + "Type 0Eh", + "Extended", + "SAS IO Unit", + "SAS Expander", + "SAS Device", + "SAS Phy", + "Log", + "Enclosure", + "Type 16h", + "Type 17h", + "Type 18h", + "Type 19h", + "Type 1Ah", + "Type 1Bh", + "Type 1Ch", + "Type 1Dh", + "Type 1Eh", + "Type 1Fh" +}; + + +int +doShowNonDefaultSettings(MPT_PORT *port) +{ + ConfigReply_t rep; + int type; + int number; + int attr; + U32 buf_def[255]; + U32 buf_cur[255]; + int len_def; + int len_cur; + int i; + int len; + + printf("Checking for non-default persistent settings...\n"); + + for (type = 0; type < 32; type++) + { + if (type == MPI_CONFIG_PAGETYPE_RAID_VOLUME || + type == MPI_CONFIG_PAGETYPE_MANUFACTURING || + type == MPI_CONFIG_PAGETYPE_RAID_PHYSDISK || + type == MPI_CONFIG_PAGETYPE_EXTENDED || + type == MPI_CONFIG_EXTPAGETYPE_LOG) + { + continue; + } + for (number = 0; number < 16; number++) + { + if (type == MPI_CONFIG_PAGETYPE_IO_UNIT && number == 2) + { + continue; + } + + if (type == MPI_CONFIG_PAGETYPE_IO_UNIT && number == 3) + { + continue; + } + + if (type == MPI_CONFIG_PAGETYPE_BIOS && number == 2) + { + continue; + } + + if (getConfigPageHeader(port, type, number, 0, &rep) != 1) + { + continue; + } + + attr = rep.Header.PageType & MPI_CONFIG_PAGEATTR_MASK; + if (attr != MPI_CONFIG_PAGEATTR_PERSISTENT) + { + continue; + } + + printf("\n%s Page %d is persistent\n", pageType[type], number); + + if (type == MPI_CONFIG_PAGETYPE_FC_PORT && number == 3) + { + doFcPersistentMappings(port, 1); + continue; + } + + if (type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE && number == 2) + { + if (mpi1) + doSasPersistentMappings(port, 1); + continue; + } + + memset(buf_def, 0, sizeof buf_def); + memset(buf_cur, 0, sizeof buf_cur); + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_DEFAULT, + type, number, 0, buf_def, sizeof buf_def) != 1) + { + continue; + } + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_NVRAM, + type, number, 0, buf_cur, sizeof buf_cur) != 1) + { + continue; + } + + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + { + len_def = get16(((pConfigExtendedPageHeader_t)buf_def)->ExtPageLength); + len_cur = get16(((pConfigExtendedPageHeader_t)buf_cur)->ExtPageLength); + } + else + { + len_def = ((pConfigPageHeader_t)buf_def)->PageLength; + len_cur = ((pConfigPageHeader_t)buf_cur)->PageLength; + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (type == MPI_CONFIG_PAGETYPE_IO_UNIT && number == 1) + { + IOUnitPage1_t *def_IOUnitPage1 = (pIOUnitPage1_t)buf_def; + int def_flags = get32(def_IOUnitPage1->Flags); + + // default for multi-pathing is ON from the factory, but OFF for older firmware + // flip it on, so the firmware default matches the factory default + def_IOUnitPage1->Flags = set32(def_flags | MPI_IOUNITPAGE1_MULTI_PATHING); + } + } + + len = max(len_def, len_cur); + + for (i = 0; i < len; i++) + { + if (buf_def[i] != buf_cur[i]) + { + printf("Mismatch at offset %04x: default = %08x, current = %08x\n", + i*4, get32x(buf_def[i]), get32x(buf_cur[i])); + } + } + } + } + + return 1; +} + + +int +doRestoreDefaultSettings(MPT_PORT *port) +{ + ConfigReply_t rep; + int type; + int number; + int attr; + U32 buf_def[255]; + U32 buf_cur[255]; + int len_def; + int len_cur; + int i; + int len; + + printf("Restoring default persistent settings...\n"); + + for (type = 0; type < 32; type++) + { + if (type == MPI_CONFIG_PAGETYPE_RAID_VOLUME || + type == MPI_CONFIG_PAGETYPE_MANUFACTURING || + type == MPI_CONFIG_PAGETYPE_RAID_PHYSDISK || + type == MPI_CONFIG_PAGETYPE_EXTENDED || + type == MPI_CONFIG_EXTPAGETYPE_LOG) + { + continue; + } + for (number = 0; number < 16; number++) + { + if (type == MPI_CONFIG_PAGETYPE_IO_UNIT && number == 2) + { + continue; + } + + if (type == MPI_CONFIG_PAGETYPE_IO_UNIT && number == 3) + { + continue; + } + + if (type == MPI_CONFIG_PAGETYPE_BIOS && number == 2) + { + continue; + } + + if (getConfigPageHeader(port, type, number, 0, &rep) != 1) + { + continue; + } + + attr = rep.Header.PageType & MPI_CONFIG_PAGEATTR_MASK; + if (attr != MPI_CONFIG_PAGEATTR_PERSISTENT) + { + continue; + } + + printf("\n%s Page %d is persistent\n", pageType[type], number); + + if (type == MPI_CONFIG_PAGETYPE_FC_PORT && number == 3) + { + if (yesFlag == FALSE) + { + printf("Do you want to remove all persistent mappings? [Yes or No, default is Yes] "); + } + + if (yesFlag == TRUE || getYesNoAnswer(1) == 1) + { + doFcPersistentMappings(port, 4); + } + continue; + } + + if (type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE && number == 2) + { + if (mpi2) + continue; + + if (yesFlag == FALSE) + { + printf("Do you want to remove all persistent mappings? [Yes or No, default is Yes] "); + } + + if (yesFlag == TRUE || getYesNoAnswer(1) == 1) + { + doSasPersistentMappings(port, 10); + } + continue; + } + + memset(buf_def, 0, sizeof buf_def); + memset(buf_cur, 0, sizeof buf_cur); + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_DEFAULT, + type, number, 0, buf_def, sizeof buf_def) != 1) + { + continue; + } + + if (getConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_READ_NVRAM, + type, number, 0, buf_cur, sizeof buf_cur) != 1) + { +// continue; + } + + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + { + len_def = get16(((pConfigExtendedPageHeader_t)buf_def)->ExtPageLength); + len_cur = get16(((pConfigExtendedPageHeader_t)buf_cur)->ExtPageLength); + } + else + { + len_def = ((pConfigPageHeader_t)buf_def)->PageLength; + len_cur = ((pConfigPageHeader_t)buf_cur)->PageLength; + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (type == MPI_CONFIG_PAGETYPE_IO_UNIT && number == 1) + { + IOUnitPage1_t *def_IOUnitPage1 = (pIOUnitPage1_t)buf_def; + IOUnitPage1_t *cur_IOUnitPage1 = (pIOUnitPage1_t)buf_cur; + int def_flags = get32(def_IOUnitPage1->Flags); + int cur_flags = get32(cur_IOUnitPage1->Flags); + + if (!(def_flags & MPI_IOUNITPAGE1_MULTI_PATHING)) + { + // default for multi-pathing is ON from the factory, but OFF for older firmware + // flip it on, so the firmware default matches the factory default + def_IOUnitPage1->Flags = set32(def_flags | MPI_IOUNITPAGE1_MULTI_PATHING); + if (!(cur_flags & MPI_IOUNITPAGE1_MULTI_PATHING)) + printf("restoring factory default for MULTI_PATHING\n"); + } + } + } + + len = max(len_def, len_cur); + + for (i = 0; i < len; i++) + { + if (buf_def[i] != buf_cur[i]) + { + if (setConfigPageAction(port, MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM, + type, number, 0, buf_def, len_def * 4) == 1) + { + printf("Defaults restored\n"); + } + else + { + printf("Failed to restore defaults!\n"); + } + break; + } + } + } + } + + return 1; +} + + +int +doDefaultPhyRegsSettings(MPT_PORT *port) +{ + ManufacturingPage3_t *CurManufacturingPage3; + ManufacturingPage3_t *DefManufacturingPage3; + int length; + int t; + int i; + int j; + U32 *p_cur; + U32 *p_def; + + printf("Updating default PhyRegs settings...\n"); + + if (port->deviceId == MPI_MANUFACTPAGE_DEVICEID_FC909) + { + return 0; + } + + CurManufacturingPage3 = getConfigPageActionAlloc(port, MPI_CONFIG_ACTION_PAGE_READ_NVRAM, + MPI_CONFIG_PAGETYPE_MANUFACTURING, 3, 0, + &length); + if (CurManufacturingPage3 == NULL) + { + printf("Failed to read non-volatile ManufacturingPage3!\n"); + return 0; + } + + DefManufacturingPage3 = getConfigPageActionAlloc(port, MPI_CONFIG_ACTION_PAGE_READ_DEFAULT, + MPI_CONFIG_PAGETYPE_MANUFACTURING, 3, 0, + &length); + if (DefManufacturingPage3 == NULL) + { + printf("Failed to read default ManufacturingPage3!\n"); + free(CurManufacturingPage3); + return 0; + } + + for (i = 0; i < 2; i++) + { + p_cur = (U32 *)CurManufacturingPage3 + 2 + i * 8; + p_def = (U32 *)DefManufacturingPage3 + 2 + i * 8; + + // preserve current WWNs for both channels! + for (j = 0; j < 4; j++) + p_def[j] = p_cur[j]; + + // preserve supported speeds / link type / connector type + p_def[j+3] = p_cur[j+3]; + } + + + doIocInit(port, MPI_WHOINIT_MANUFACTURER); + + t = setConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 3, 0, DefManufacturingPage3, length); + + doIocInit(port, port->whoInit); + + free(CurManufacturingPage3); + free(DefManufacturingPage3); + + if (t != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +int +doFcChangePersonalWwn(MPT_PORT *port) +{ + FCPortPage1_t FCPortPage1; + ManufacturingPage3_t *ManufacturingPage3; + int length; + int t1; + int t2; + int flags; + U32 *p; + U32 wwnn_l; + U32 wwnn_h; + U32 wwpn_l; + U32 wwpn_h; + + ManufacturingPage3 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 3, 0, &length); + if (ManufacturingPage3 == NULL) + return 0; + + p = (U32 *)ManufacturingPage3 + 2 + port->iocNumber * 8; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + wwnn_l = get32(FCPortPage1.NoSEEPROMWWNN.Low); + wwnn_h = get32(FCPortPage1.NoSEEPROMWWNN.High); + wwpn_l = get32(FCPortPage1.NoSEEPROMWWPN.Low); + wwpn_h = get32(FCPortPage1.NoSEEPROMWWPN.High); + + printf("Current Personal FC WWNN = %08x%08x, WWPN = %08x%08x\n\n", wwnn_h, wwnn_l, wwpn_h, wwpn_l); + + printf("Enter new WWNN: [16 hex digits or RETURN for none] "); + t1 = getHexDoubleNumberAnswer(&wwnn_h, &wwnn_l); + if (t1 == 0) + { + wwnn_l = get32x(p[2]); + wwnn_h = get32x(p[3]); + } + + printf("Enter new WWPN: [16 hex digits or RETURN for none] "); + t2 = getHexDoubleNumberAnswer(&wwpn_h, &wwpn_l); + if (t1 == 0) + { + wwpn_l = get32x(p[0]); + wwpn_h = get32x(p[1]); + } + + free(ManufacturingPage3); + + FCPortPage1.NoSEEPROMWWNN.Low = set32(wwnn_l); + FCPortPage1.NoSEEPROMWWNN.High = set32(wwnn_h); + FCPortPage1.NoSEEPROMWWPN.Low = set32(wwpn_l); + FCPortPage1.NoSEEPROMWWPN.High = set32(wwpn_h); + + flags = get32(FCPortPage1.Flags); + + if (t1 || t2) + flags |= MPI_FCPORTPAGE1_FLAGS_FORCE_USE_NOSEEPROM_WWNS; + else + flags &= ~MPI_FCPORTPAGE1_FLAGS_FORCE_USE_NOSEEPROM_WWNS; + + FCPortPage1.Flags = set32(flags); + + if (setConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &FCPortPage1, sizeof FCPortPage1) != 1) + { + printf("Failed to save changes to NVRAM!\n"); + return 0; + } + + return 1; +} + + +int +doGIEL(MPT_PORT *port) +{ + FcCommonTransportSendRequest_t req; + FcCommonTransportSendReply_t rep; + U32 buf_out[256]; + U32 buf_in[256]; + int ioc_status; + U32 code; + int i; + + if (bringOnline(port) != 1) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND; + req.AliasIndex = virtInit; + req.MsgFlags_Did = set32(0xfffffa); + req.CTCommandCode = set16(0x0101); + req.FsType = 0xfa; + + memset(buf_out, 0, sizeof buf_out); + + buf_out[0] = set32x_be(0x01000000); + buf_out[1] = set32x_be(0xfa0101fc); + buf_out[2] = set32x_be(0x01010000); + buf_out[3] = set32x_be(0x00000000); + + buf_in[2] = 0; + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf_in, sizeof buf_in, buf_out, 16, SHORT_TIME) == 1) + { + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + printf("CTSend failed, IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); + return 0; + } + + code = (get32x_be(buf_in[2]) >> 16) & 0xffff; + + if (code == 0x8001) + { + printf("GIEL rejected\n\n"); + for (i = 0; i < (int)get32(rep.ResponseLength) / 4; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_in[i])); + return 0; + } + + if (code != 0x8002) + { + printf("GIEL not accepted, code is %04x\n\n", code); + for (i = 0; i < (int)get32(rep.ResponseLength) / 4; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_in[i])); + return 0; + } + + for (i = 0; i < (int)get32(rep.ResponseLength) / 4; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_in[i])); + } + + return 1; +} + + +int +doGID_FT(MPT_PORT *port) +{ + FcCommonTransportSendRequest_t req; + FcCommonTransportSendReply_t rep; + U32 buf_out[256]; + U32 buf_in[256]; + int ioc_status; + U32 code; + int i; + + if (bringOnline(port) != 1) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND; + req.AliasIndex = virtInit; + req.MsgFlags_Did = set32(0xfffffc); + req.CTCommandCode = set16(0x0171); + req.FsType = 0xfc; + + memset(buf_out, 0, sizeof buf_out); + + buf_out[0] = set32x_be(0x01000000); + buf_out[1] = set32x_be(0xfc020000); + buf_out[2] = set32x_be(0x017101fc); + buf_out[3] = set32x_be(0x00000000); + buf_out[4] = set32x_be(0x00000008); + + buf_in[2] = 0; + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf_in, sizeof buf_in, buf_out, 20, SHORT_TIME) == 1) + { + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + printf("CTSend failed, IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); + return 0; + } + + code = (get32x_be(buf_in[2]) >> 16) & 0xffff; + + if (code == 0x8001) + { + printf("GID_FT rejected\n\n"); + for (i = 0; i < (int)get32(rep.ResponseLength) / 4; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_in[i])); + return 0; + } + + if (code != 0x8002) + { + printf("GID_FT not accepted, code is %04x\n\n", code); + for (i = 0; i < (int)get32(rep.ResponseLength) / 4; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_in[i])); + return 0; + } + + for (i = 0; i < (int)get32(rep.ResponseLength) / 4; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_in[i])); + } + + return 1; +} + + +int +doGA_NXT(MPT_PORT *port) +{ + FcCommonTransportSendRequest_t req; + FcCommonTransportSendReply_t rep; + U32 buf_out[256]; + U32 buf_in[256]; + int ioc_status; + U32 code; + int i; + int d_id; + + if (bringOnline(port) != 1) + return 0; + + printf("Enter D_ID: [000000-FFFFFF or RETURN to quit] "); + d_id = getNumberAnswerHex(0x000000, 0xffffff, -1); + if (d_id < 0) + return 0; + + printf("\n"); + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND; + req.AliasIndex = virtInit; + req.MsgFlags_Did = set32(0xfffffc); + req.CTCommandCode = set16(0x0100); + req.FsType = 0xfc; + + memset(buf_out, 0, sizeof buf_out); + + buf_out[0] = set32x_be(0x01000000); + buf_out[1] = set32x_be(0xfc020000); + buf_out[2] = set32x_be(0x010001fc); + buf_out[3] = set32x_be(0x00000000); + buf_out[4] = set32x_be(d_id); + + buf_in[2] = 0; + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf_in, sizeof buf_in, buf_out, 20, SHORT_TIME) == 1) + { + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + printf("CTSend failed, IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); + return 0; + } + + code = (get32x_be(buf_in[2]) >> 16) & 0xffff; + + if (code == 0x8001) + { + printf("GA_NXT rejected\n\n"); + for (i = 0; i < (int)get32(rep.ResponseLength) / 4; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_in[i])); + return 0; + } + + if (code != 0x8002) + { + printf("GA_NXT not accepted, code is %04x\n\n", code); + for (i = 0; i < (int)get32(rep.ResponseLength) / 4; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_in[i])); + return 0; + } + + for (i = 0; i < (int)get32(rep.ResponseLength) / 4; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_in[i])); + } + + return 1; +} + + +int +doExLinkServiceSend(MPT_PORT *port) +{ + ExLinkServiceSendRequest_t req; + ExLinkServiceSendReply_t rep; + U32 buf_out[256]; + U32 buf_in[256]; + int els; + int d_id; + int len; + U32 value; + int i; + int j; + int ioc_status; + U32 code; + int passes; + int delay; + + if (bringOnline(port) != 1) + return 0; + + printf("Enter ELS code: [00-FF or RETURN to quit] "); + els = getNumberAnswerHex(0x00, 0xff, -1); + if (els < 0) + return 0; + + printf("Enter D_ID: [000000-FFFFFF or RETURN to quit] "); + d_id = getNumberAnswerHex(0x000000, 0xffffff, -1); + if (d_id < 0) + return 0; + + printf("Enter payload length in words: [1-256 or RETURN to quit] "); + len = getNumberAnswer(0, 256, -1); + if (len < 0) + return 0; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_FC_EX_LINK_SRVC_SEND; + req.AliasIndex = virtInit; + req.MsgFlags_Did = set32(d_id); + req.ElsCommandCode = set32(els); + + memset(buf_out, 0, sizeof buf_out); + + buf_out[0] = set32x(els); + + if (len > 1) + { + while (TRUE) + { + printf("\n"); + for (i = 0; i < len; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_out[i])); + + printf("\nEnter word to change: [0-%d or RETURN to quit] ", len - 1); + i = getNumberAnswer(0, len - 1, -1); + if (i < 0) + break; + + printf("Enter value: [00000000-FFFFFFFF or RETURN to not change] "); + if (getHexNumberAnswer(&value) == 0) + continue; + + if (i == 0) + buf_out[0] = set32x_be((value & 0xffffff) | (els << 24)); + else + buf_out[i] = set32x_be(value); + } + } + + printf("\nNumber of iterations: [1-1000000, default is 1] "); + passes = getNumberAnswer(1, 1000000, 1); + if (passes > 1) + { + printf("Delay in seconds between iterations: [1-6000, default is 30] "); + delay = getNumberAnswer(1, 6000, 30); + } + else + delay = 0; + + for (j = 1; j <= passes; j++) + { + if (passes > 1) + { + if (j > 1) + sleep(delay); + printf("\nPass %d...\n", j); + } + + printf("\n"); + + buf_in[0] = 0; + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf_in, sizeof buf_in, buf_out, len * 4, SHORT_TIME) == 1) + { + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + printf("SendELS failed, IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); +#if WIN32 + continue; +#else + return 0; +#endif + } + + code = (get32x_be(buf_in[0]) >> 24) & 0xff; + + if (code == 0x01) + { + printf("ELS rejected\n"); +#if WIN32 + continue; +#else + return 0; +#endif + } + + if (code != 0x02) + { + printf("ELS not accepted, code is %02x\n", code); +#if WIN32 + continue; +#else + return 0; +#endif + } + + for (i = 0; i < (int)get32(rep.ResponseLength) / 4; i++) + printf("Word %04d = %08x\n", i, get32x_be(buf_in[i])); + } + } + + return 1; +} + + +int +doResetFcLink(MPT_PORT *port, int flag) +{ + FcPrimitiveSendRequest_t req; + FcPrimitiveSendReply_t rep; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_FC_PRIMITIVE_SEND; + if (flag) + req.SendFlags = MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK; + else + req.SendFlags = MPI_FC_PRIM_SEND_FLAGS_RESET_LINK; + + printf("Resetting FC link...\n"); + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doScsiCdb(MPT_PORT *port) +{ + SCSIIORequest_t req1; + Mpi2SCSIIORequest_t req2; + Mpi25SCSIIORequest_t req25; + SCSI_REPLY rep1; + SCSI_REPLY2 rep2; + void *req; + int req_size; + void *rep; + int rep_size; + int bus; + int target; + int lun; + unsigned char cdb[80]; + unsigned char buf_out[512]; + unsigned char buf_in[1024]; + int len_out; + int len_in; + int value; + int i; + int j; + int t; + int n; + int ioc_status; + char c[17]; + + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("LUN: [0-%d or RETURN to quit] ", port->maxLuns - 1); + lun = getNumberAnswer(0, port->maxLuns - 1, -1); + if (lun < 0) + return 1; + + printf("CDB: [hex string or RETURN to quit] "); + n = getStringFromArgs((char *)cdb, sizeof cdb, stdin); + switch (n) + { + case 6*2: + case 10*2: + case 12*2: + case 16*2: + break; + + default: + printf("CDB must be 6, 10, 12, or 16 bytes (12, 20, 24, or 32 characters)\n"); + return 0; + } + + for (i = 0; i < n; i++) + { + j = cdb[i]; + + if (isdigit(j)) + { + cdb[i] = j - '0'; + } + else if (isxdigit(j)) + { + cdb[i] = tolower(j) - 'a' + 10; + } + else + { + printf("invalid hex digit %c at offset %d\n", j, i); + return 0; + } + } + + printf("\nEnter input data length in bytes: [0-1024 or RETURN to quit] "); + len_in = getNumberAnswer(0, 1024, -1); + if (len_in < 0) + return 0; + + if (len_in) + len_out = 0; + else + { + printf("Enter output data length in bytes: [0-1024 or RETURN to quit] "); + len_out = getNumberAnswer(0, 1024, -1); + if (len_out < 0) + return 0; + } + + t = tagType; + if (len_in) + t |= MPI_SCSIIO_CONTROL_READ; + if (len_out) + t |= MPI_SCSIIO_CONTROL_WRITE; + + memset(&req1, 0, sizeof req1); + memset(&rep1, 0, sizeof rep1); + + req1.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req1.AliasIndex = virtInit; + req1.LUN[1] = lun; + req1.Control = set32(t); + req1.DataLength = set32(len_in + len_out); + + for (i = 0, j = 0; j < n; i++, j += 2) + req1.CDB[i] = (cdb[j] << 4) + cdb[j+1]; + + req1.CDBLength = i; + + setName(port, bus, target, &req1); + + if (mpi20) + { + memset(&req2, 0, sizeof req2); + memset(&rep2, 0, sizeof rep2); + + // convert from MPI 1.x format to MPI 2.x format + req2.Function = req1.Function; + req2.DevHandle = ((pMpi2SCSIIORequest_t)&req1)->DevHandle; + req2.Control = req1.Control; + req2.IoFlags = set16(req1.CDBLength); + req2.DataLength = req1.DataLength; + + memcpy(req2.LUN, req1.LUN, sizeof req1.LUN); + memcpy(req2.CDB.CDB32, req1.CDB, sizeof req1.CDB); + + req2.SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; + + req = &req2; + req_size = sizeof req2 - sizeof req2.SGL; + rep = &rep2; + rep_size = sizeof rep2; + } + else if (mpi25) + { + memset(&req25, 0, sizeof req25); + memset(&rep2, 0, sizeof rep2); + + // convert from MPI 1.x format to MPI 2.5 format + req25.Function = req1.Function; + req25.DevHandle = ((pMpi25SCSIIORequest_t)&req1)->DevHandle; + req25.Control = req1.Control; + req25.IoFlags = set16(req1.CDBLength); + req25.DataLength = req1.DataLength; + + memcpy(req25.LUN, req1.LUN, sizeof req1.LUN); + memcpy(req25.CDB.CDB32, req1.CDB, sizeof req1.CDB); + + req25.SGLOffset0 = offsetof(Mpi25SCSIIORequest_t, SGL) / 4; + + req = &req25; + req_size = sizeof req25 - sizeof req25.SGL; + rep = &rep2; + rep_size = sizeof rep2; + } + else + { + req = &req1; + req_size = sizeof req1 - sizeof req1.SGL; + rep = &rep1; + rep_size = sizeof rep1; + } + + memset(buf_out, 0, sizeof buf_out); + + if (len_out) + { + while (TRUE) + { + for (i = 0; i < len_out; i++) + { + if ((i % 16) == 0) + printf("\n%3d : ", i); + + printf("%02x ", buf_out[i]); + } + printf("\n"); + + printf("\nEnter byte to change: [0-%d or RETURN to quit] ", len_out - 1); + i = getNumberAnswer(0, len_out - 1, -1); + if (i < 0) + break; + + printf("Enter value: [00-FF or RETURN to not change] "); + value = getNumberAnswerHex(0x00, 0xff, -1); + if (value < 0) + continue; + + buf_out[i] = (unsigned char)value; + } + } + + memset(buf_in, 0, sizeof buf_in); + + if (doMptCommand(port, req, req_size, rep, rep_size, + buf_in, len_in, buf_out, len_out, SHORT_TIME) == 1) + { + if (mpi2) + { + memcpy(&rep1.reply, &rep2.reply, sizeof rep1.reply); + memcpy(&rep1.sense, &rep2.sense, sizeof rep1.sense); + } + + printf("\n"); + + ioc_status = get16(rep1.reply.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + printf("IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); + } + + t = rep1.reply.SCSIStatus; + if (t != MPI_SCSI_STATUS_SUCCESS) + { + if (t == MPI_SCSI_STATUS_CHECK_CONDITION) + { + printf("Check Condition, Key = %d, ASC/ASCQ = %02Xh/%02Xh\n", + rep1.sense[2] & 0x0f, rep1.sense[12], rep1.sense[13]); + t = get32(rep1.reply.SenseCount); + printf("%d bytes of Sense Data returned\n", t); + + printf("\n"); + + for (i = 0, j = 0; i < t; i++, j++) + { + if (j == 0) + printf("%3d : ", i); + + printf("%02x ", rep1.sense[i]); + + if (!isprint(rep1.sense[i])) + c[j] = ' '; + else + c[j] = rep1.sense[i]; + + if (j == sizeof c - 2) + { + c[j+1] = 0; + printf(" %s\n", c); + j = -1; + } + } + + if (j != 0) + { + c[j] = 0; + for (i = j; i < sizeof c - 1; i++) + printf(" "); + + printf(" %s\n", c); + } + } + else + printf("SCSIStatus = %02x\n", t); + + printf("\n"); + } + + if (ioc_status == MPI_IOCSTATUS_SUCCESS && rep1.reply.SCSIStatus == MPI_SCSI_STATUS_SUCCESS) + t = len_in + len_out; + else + t = get32(rep1.reply.TransferCount); + printf("%d bytes of data transferred\n", t); + + if (len_in && t) + { + printf("\n"); + + for (i = 0, j = 0; i < t; i++, j++) + { + if (j == 0) + printf("%3d : ", i); + + printf("%02x ", buf_in[i]); + + if (!isprint(buf_in[i])) + c[j] = ' '; + else + c[j] = buf_in[i]; + + if (j == sizeof c - 2) + { + c[j+1] = 0; + printf(" %s\n", c); + j = -1; + } + } + + if (j != 0) + { + c[j] = 0; + for (i = j; i < sizeof c - 1; i++) + printf(" "); + + printf(" %s\n", c); + } + } + } + + return 1; +} + + +int +doSataPassthroughSend(MPT_PORT *port) +{ + SataPassthroughRequest_t req; + SataPassthroughReply_t rep; + int bus; + int target; + int feature; + int count; + int lbah; + int lbam; + int lbal; + int device; + int command; + unsigned short buf_out[512]; + unsigned char buf_in[1024]; + int len_out; + int len_in; + int value; + int i; + int j; + int t; + int ioc_status; + char c[21]; + + if (bringOnline(port) != 1) + return 0; + + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 1; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 1; + + printf("\n"); + + if (!isSata(port, bus, target)) + { + printf("Can't do SATA Request Send, device is not SATA!\n"); + return 1; + } + + printf("ATA Word 00 Feature: [0000-FFFF or RETURN to quit] "); + feature = getNumberAnswerHex(0x0000, 0xffff, -1); + if (feature < 0) + return 0; + + printf("ATA Word 01 Count: [0000-FFFF or RETURN to quit] "); + count = getNumberAnswerHex(0x0000, 0xffff, -1); + if (count < 0) + return 0; + + printf("ATA Word 02 LBA H: [0000-FFFF or RETURN to quit] "); + lbah = getNumberAnswerHex(0x0000, 0xffff, -1); + if (lbah < 0) + return 0; + + printf("ATA Word 03 LBA M: [0000-FFFF or RETURN to quit] "); + lbam = getNumberAnswerHex(0x0000, 0xffff, -1); + if (lbam < 0) + return 0; + + printf("ATA Word 04 LBA L: [0000-FFFF or RETURN to quit] "); + lbal = getNumberAnswerHex(0x0000, 0xffff, -1); + if (lbal < 0) + return 0; + + printf("ATA Word 05 Device: [00-FF or RETURN to quit] "); + device = getNumberAnswerHex(0x0000, 0xffff, -1); + if (device < 0) + return 0; + + printf("ATA Word 05 Command: [00-FF or RETURN to quit] "); + command = getNumberAnswerHex(0x0000, 0xffff, -1); + if (command < 0) + return 0; + + printf("\nEnter input data length in words: [0-512 or RETURN to quit] "); + len_in = getNumberAnswer(0, 512, -1); + if (len_in < 0) + return 0; + + if (len_in) + len_out = 0; + else + { + printf("Enter output data length in words: [0-512 or RETURN to quit] "); + len_out = getNumberAnswer(0, 512, -1); + if (len_out < 0) + return 0; + } + + t = 0; + if (len_in) + t |= MPI_SATA_PT_REQ_PT_FLAGS_PIO | MPI_SATA_PT_REQ_PT_FLAGS_READ; + if (len_out) + t |= MPI_SATA_PT_REQ_PT_FLAGS_PIO | MPI_SATA_PT_REQ_PT_FLAGS_WRITE; + + printf("SATA PassThrough Flags: [0000-FFFF, default is %04x] ", t); + t = getNumberAnswerHex(0x0000, 0xffff, t); + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SATA_PASSTHROUGH; + req.PassthroughFlags = set16(t); + req.DataLength = set32((len_in + len_out) * 2); + req.CommandFIS[0] = 0x27; + req.CommandFIS[1] = 0x80; + req.CommandFIS[2] = (U8)command; + req.CommandFIS[3] = (U8)feature; + req.CommandFIS[4] = (U8)lbal; + req.CommandFIS[5] = (U8)lbam; + req.CommandFIS[6] = (U8)lbah; + req.CommandFIS[7] = (U8)device; + req.CommandFIS[8] = (U8)(lbal >> 8); + req.CommandFIS[9] = (U8)(lbam >> 8); + req.CommandFIS[10] = (U8)(lbah >> 8); + req.CommandFIS[11] = (U8)(feature >> 8); + req.CommandFIS[12] = (U8)count; + req.CommandFIS[13] = (U8)(count >> 8); + + setName(port, bus, target, &req); + + memset(buf_out, 0, sizeof buf_out); + + if (len_out) + { + while (TRUE) + { + for (i = 0; i < len_out; i++) + { + if ((i % 10) == 0) + printf("\n%3d : ", i / 2); + + printf("%04x ", get16x(buf_out[i])); + } + printf("\n"); + + printf("\nEnter word to change: [0-%d or RETURN to quit] ", len_out - 1); + i = getNumberAnswer(0, len_out - 1, -1); + if (i < 0) + break; + + printf("Enter value: [0000-FFFF or RETURN to not change] "); + value = getNumberAnswerHex(0x0000, 0xffff, -1); + if (value < 0) + continue; + + buf_out[i] = (unsigned short)set16x(value); + } + } + + memset(buf_in, 0, sizeof buf_in); + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf_in, len_in * 2, buf_out, len_out * 2, SHORT_TIME) == 1) + { + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + printf("\nSATAPassthrough failed, IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); + + dumpMemory(&req, sizeof req - sizeof req.SGL, "MPT Request"); + dumpMemory(&rep, sizeof rep, "MPT Reply"); + + return 0; + } + + printf("\n"); + + t = get32(rep.StatusControlRegisters); + if (t) + { + printf("StatusControlRegisters = %04x\n\n", t); + } + + t = 0; + for (i = 0; i < sizeof rep.StatusFIS; i++) + t += rep.StatusFIS[i]; + + if (t) + { + printf("ATA Word 00 Error: 00%02x\n", rep.StatusFIS[3]); + printf("ATA Word 01 Count: %02x%02x\n", rep.StatusFIS[13], rep.StatusFIS[12]); + printf("ATA Word 02 LBA H: %02x%02x\n", rep.StatusFIS[10], rep.StatusFIS[6]); + printf("ATA Word 03 LBA M: %02x%02x\n", rep.StatusFIS[9], rep.StatusFIS[5]); + printf("ATA Word 04 LBA L: %02x%02x\n", rep.StatusFIS[8], rep.StatusFIS[4]); + printf("ATA Word 05 Device: %02x \n", rep.StatusFIS[7]); + printf("ATA Word 05 Status: %02x\n\n", rep.StatusFIS[2]); + } + + t = get32(rep.TransferCount); + printf("%d words of data transferred\n", t / 2); + + if (len_in) + { + printf("\n"); + + for (i = 0, j = 0; i < t; i++, j++) + { + if (j == 0) + printf("%3d : ", i / 2); + + if (i & 1) + printf("%02x ", buf_in[i^1]); + else + printf("%02x", buf_in[i^1]); + + if (!isprint(buf_in[i^1])) + c[j] = ' '; + else + c[j] = buf_in[i^1]; + + if (j == sizeof c - 2) + { + c[j+1] = 0; + printf(" %s\n", c); + j = -1; + } + } + + if (j != 0) + { + c[j] = 0; + for (i = j; i < sizeof c - 1; i++) + if (i & 1) + printf(" "); + else + printf(" "); + + printf(" %s\n", c); + } + } + } + + return 1; +} + + +int +doSmpPassthroughSend(MPT_PORT *port) +{ + SmpPassthroughRequest_t req; + SmpPassthroughReply_t rep; + SasExpanderPage0_t SASExpanderPage0; + unsigned char buf_out[1032]; + unsigned char buf_in[1032]; + int smp; + int handle; + int len; + int value; + int i; + int j; + int t; + int ioc_status; + U32 result; + U32 wwid_l; + U32 wwid_h; + _U64 sas_address; + U8 physical_port; + + if (bringOnline(port) != 1) + return 0; + + printf("Enter SMP function code: [00-FF or RETURN to quit] "); + smp = getNumberAnswerHex(0x00, 0xff, -1); + if (smp < 0) + return 0; + + printf("Enter handle: [0000-FFFF or RETURN to quit] "); + handle = getNumberAnswerHex(0x0000, 0xffff, -1); + if (handle < 0) + return 0; + + if (handle == 0) + { + printf("Enter SASAddress: [16 hex digits or RETURN to quit] "); + t = getHexDoubleNumberAnswer(&wwid_h, &wwid_l); + if (t == 0) + return 0; + + printf("Enter port: [0 to %d or RETURN to leave unspecified] ", port->numPhys - 1); + physical_port = (U8)getNumberAnswer(0, port->numPhys - 1, 255); + sas_address.Low = set32(wwid_l); + sas_address.High = set32(wwid_h); + } + else + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE + < 1) + { + while (TRUE) + { + printf("\n"); + for (i = 0; i < len; i++) + printf("Byte %04d = %02x\n", i, buf_out[i]); + + printf("\nEnter byte to change: [2-%d or RETURN to quit] ", len - 5); + i = getNumberAnswer(2, len - 5, -1); + if (i < 0) + break; + + printf("Enter value: [00-FF or RETURN to not change] "); + value = getNumberAnswerHex(0x00, 0xff, -1); + if (value < 0) + continue; + + buf_out[i] = (unsigned char)value; + } + } + + printf("\n"); + + memset(buf_in, 0, sizeof buf_in); + + if (doMptCommand(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf_in, sizeof buf_in - 4, buf_out, len - 4, SHORT_TIME) == 1) + { + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + printf("SMPPassthrough failed, IOCStatus = %04x (%s), SASStatus = %02x, IOCLogInfo = %08x\n", + ioc_status, translateIocStatus(ioc_status), rep.SASStatus, get32(rep.IOCLogInfo)); + return 0; + } + + result = buf_in[2]; + + if (result != 0x00) + { + printf("SMP request not accepted, result is %02x (%s)\n", result, translateSmpFunctionResult(result)); + return 0; + } + + len = get16(rep.ResponseDataLength) + 4; + + /* zero anything that might be in the CRC bytes as the real CRC is not passed back */ + memset(buf_in + len - 4, 0, 4); + + printf("SMP request was accepted, and returned %d response bytes\n\n", len); + + for (i = 0, j = 0; i < len; i++, j++) + { + if (j == 0) + printf("%04x : ", i); + + printf("%02x ", buf_in[i]); + + if (j == 15) + { + printf("\n"); + j = -1; + } + } + + if (j != 0) + { + printf("\n"); + } + } + + return 1; +} + + +int +doResetSasLink(MPT_PORT *port, int flag) +{ + SasDevicePage0_t SASDevicePage0; + SasExpanderPage0_t SASExpanderPage0; + SasIoUnitControlRequest_t req; + SasIoUnitControlReply_t rep; + int handle; + int phy; + int min_phy; + int max_phy; + int dev_info; + int dev_type; + unsigned char phy_control_req[40]; + unsigned char phy_control_rsp[4]; + + printf("Enter handle: [0000-FFFF or RETURN to quit] "); + handle = getNumberAnswerHex(0x0000, 0xffff, -1); + if (handle < 0) + return 0; + + if (handle == 0) + { + min_phy = 0; + max_phy = port->numPhys - 1; + } + else + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE + <MsgLength * 4, "IOCFactsReply"); + + if (getPortFacts2(port, (pMpi2PortFactsReply_t)buf) == 1) + dumpMemory(buf, ((pMpi2PortFactsReply_t)buf)->MsgLength * 4, "PortFactsReply"); + } + else + { + if (getIocFacts(port, (pIOCFactsReply_t)buf) == 1) + dumpMemory(buf, ((pIOCFactsReply_t)buf)->MsgLength * 4, "IOCFactsReply"); + + if (getPortFacts(port, (pPortFactsReply_t)buf) == 1) + dumpMemory(buf, ((pPortFactsReply_t)buf)->MsgLength * 4, "PortFactsReply"); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage0", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 1, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage1", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 2, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage2", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 3, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage3", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 4, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage4", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 5, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage5", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 6, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage6", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 7, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage7", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 8, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage8", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 9, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage9", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 10, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage10", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 11, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage11", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 12, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage12", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 13, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage13", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 14, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage14", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 15, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage15", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 16, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage16", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 241, 0, buf, len) == 1) + { + showConfigPage(port, "ManufacturingPage241", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 0, 0, buf, len) == 1) + { + showConfigPage(port, "IOUnitPage0", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 1, 0, buf, len) == 1) + { + showConfigPage(port, "IOUnitPage1", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 2, 0, buf, len) == 1) + { + showConfigPage(port, "IOUnitPage2", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 3, 0, buf, len) == 1) + { + showConfigPage(port, "IOUnitPage3", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 4, 0, buf, len) == 1) + { + showConfigPage(port, "IOUnitPage4", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 5, 0, buf, len) == 1) + { + showConfigPage(port, "IOUnitPage5", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 6, 0, buf, len) == 1) + { + showConfigPage(port, "IOUnitPage6", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 7, 0, buf, len) == 1) + { + showConfigPage(port, "IOUnitPage7", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 0, 0, buf, len) == 1) + { + showConfigPage(port, "IOCPage0", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 1, 0, buf, len) == 1) + { + showConfigPage(port, "IOCPage1", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 2, 0, buf, len) == 1) + { + showConfigPage(port, "IOCPage2", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 3, 0, buf, len) == 1) + { + showConfigPage(port, "IOCPage3", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 4, 0, buf, len) == 1) + { + showConfigPage(port, "IOCPage4", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 5, 0, buf, len) == 1) + { + showConfigPage(port, "IOCPage5", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 6, 0, buf, len) == 1) + { + showConfigPage(port, "IOCPage6", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 7, 0, buf, len) == 1) + { + showConfigPage(port, "IOCPage7", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 8, 0, buf, len) == 1) + { + showConfigPage(port, "IOCPage8", buf, len); + } + + if (port->mptVersion >= MPI_VERSION_01_02) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_BIOS, 1, 0, buf, len) == 1) + { + showConfigPage(port, "BIOSPage1", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_BIOS, 2, 0, buf, len) == 1) + { + showConfigPage(port, "BIOSPage2", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_BIOS, 3, 0, buf, len) == 1) + { + showConfigPage(port, "BIOSPage3", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_BIOS, 4, 0, buf, len) == 1) + { + showConfigPage(port, "BIOSPage4", buf, len); + } + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0, 0, buf, len) == 1) + { + showConfigPage(port, "SCSIPortPage0", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, 0, buf, len) == 1) + { + showConfigPage(port, "SCSIPortPage1", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 0, buf, len) == 1) + { + showConfigPage(port, "SCSIPortPage2", buf, len); + } + + for (i = 0; i < 16; i++) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 0, i, buf, len) == 1) + { + sprintf(name, "SCSIDevicePage0 / %d", i); + showConfigPage(port, name, buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 1, i, buf, len) == 1) + { + sprintf(name, "SCSIDevicePage1 / %d", i); + showConfigPage(port, name, buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 2, i, buf, len) == 1) + { + sprintf(name, "SCSIDevicePage2 / %d", i); + showConfigPage(port, name, buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 3, i, buf, len) == 1) + { + sprintf(name, "SCSIDevicePage3 / %d", i); + showConfigPage(port, name, buf, len); + } + } + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, buf, len) == 1) + { + showConfigPage(port, "FCPortPage0", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, buf, len) == 1) + { + showConfigPage(port, "FCPortPage1", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 2, 0, buf, len) == 1) + { + showConfigPage(port, "FCPortPage2", buf, len); + } + + if (port->maxPersistentIds * (int)sizeof(PersistentData_t) + (int)sizeof(ConfigPageHeader_t) > len) + { + for (i = 0; i < port->maxPersistentIds; i++) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 3, + MPI_FC_PORT_PGAD_FORM_INDEX + i, buf, len) == 1) + { + if (get16(((pFCPortPage3_t)buf)->Entry->Flags) & MPI_PERSISTENT_FLAGS_ENTRY_VALID) + { + sprintf(name, "FCPortPage3 / %d", i); + showConfigPage(port, name, buf, len); + } + } + } + } + else + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 3, 0, buf, len) == 1) + { + showConfigPage(port, "FCPortPage3", buf, len); + } + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 4, 0, buf, len) == 1) + { + showConfigPage(port, "FCPortPage4", buf, len); + } + + for (i = 1; i <= 255; i++) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 5, + MPI_FC_PORT_PGAD_FORM_INDEX + i, buf, len) == 1) + { + if (((pFCPortPage5_t)buf)->AliasInfo.Flags != 0) + { + sprintf(name, "FCPortPage5 / %d", i); + showConfigPage(port, name, buf, len); + } + } + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 6, 0, buf, len) == 1) + { + showConfigPage(port, "FCPortPage6", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 7, 0, buf, len) == 1) + { + showConfigPage(port, "FCPortPage7", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 8, 0, buf, len) == 1) + { + showConfigPage(port, "FCPortPage8", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 9, 0, buf, len) == 1) + { + showConfigPage(port, "FCPortPage9", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 10, 0, buf, len) == 1) + { + showConfigPage(port, "FCPortPage10", buf, len); + } + + i = 0xffffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, i, buf, len) == 1) + { + i = get32(((pFCDevicePage0_t)buf)->PortIdentifier); + sprintf(name, "FCDevicePage0 / %06x", i); + showConfigPage(port, name, buf, len); + } + else + break; + } + } + + if (mpi1 && getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 2, 0, temp_buf, len) == 1) + { + IOCPage2 = (pIOCPage2_t)temp_buf; + + for (i = 0; i < IOCPage2->MaxVolumes; i++) + { + b = IOCPage2->RaidVolume[i].VolumeBus; + t = IOCPage2->RaidVolume[i].VolumeID; + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0, (b << 8) + t, buf, len) == 1) + { + sprintf(name, "RAIDVolumePage0 / %d,%d", b, t); + showConfigPage(port, name, buf, len); + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 1, i, buf, len) == 1) + { + sprintf(name, "RAIDVolumePage1 / %d,%d", b, t); + showConfigPage(port, name, buf, len); + } + } + } + + for (i = 0; i < IOCPage2->MaxPhysDisks; i++) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, i, buf, len) == 1) + { + sprintf(name, "RAIDPhysDiskPage0 / %d", i); + showConfigPage(port, name, buf, len); + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 1, i, buf, len) == 1) + { + sprintf(name, "RAIDPhysDiskPage1 / %d", i); + showConfigPage(port, name, buf, len); + } + } + } + } + + if (mpi2 && port->capabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) + { + i = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, + MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE + i, buf, len) == 1) + { + i = get16(((pMpi2RaidVolPage0_t)buf)->DevHandle); + sprintf(name, "RAIDVolumePage0 / %04x", i); + showConfigPage(port, name, buf, len); + } + else + break; + } + + i = 0xff; + while (TRUE) + { + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, + MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM + i, buf, len) == 1) + { + i = ((pMpi2RaidPhysDiskPage0_t)buf)->PhysDiskNum; + sprintf(name, "RAIDPhysDiskPage0 / %d", i); + showConfigPage(port, name, buf, len); + } + else + break; + } + + i = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG, 0, + MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM + i, buf, len) == 1) + { + i = ((pMpi2RaidConfigurationPage0_t)buf)->ConfigNum; + sprintf(name, "RAIDConfigurationPage0 / %d", i); + showConfigPage(port, name, buf, len); + } + else + break; + } + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_LAN, 0, 0, buf, len) == 1) + { + showConfigPage(port, "LANPage0", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_LAN, 1, 0, buf, len) == 1) + { + showConfigPage(port, "LANPage1", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_INBAND, 0, 0, buf, len) == 1) + { + showConfigPage(port, "InbandPage0", buf, len); + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0, buf, len) == 1) + { + showConfigPage(port, "SASIOUnitPage0", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 1, 0, buf, len) == 1) + { + showConfigPage(port, "SASIOUnitPage1", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 2, 0, buf, len) == 1) + { + showConfigPage(port, "SASIOUnitPage2", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 3, 0, buf, len) == 1) + { + showConfigPage(port, "SASIOUnitPage3", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 4, 0, buf, len) == 1) + { + showConfigPage(port, "SASIOUnitPage4", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 5, 0, buf, len) == 1) + { + showConfigPage(port, "SASIOUnitPage5", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 6, 0, buf, len) == 1) + { + showConfigPage(port, "SASIOUnitPage6", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 7, 0, buf, len) == 1) + { + showConfigPage(port, "SASIOUnitPage7", buf, len); + } + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 8, 0, buf, len) == 1) + { + showConfigPage(port, "SASIOUnitPage8", buf, len); + } + + i = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, i, buf, len) == 1) + { + i = get16(((pSasExpanderPage0_t)buf)->DevHandle); + sprintf(name, "SASExpanderPage0 / %04x", i); + showConfigPage(port, name, buf, len); + + n = ((pSasExpanderPage0_t)buf)->NumPhys; + for (j = 0; j < n; j++) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 1, + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM + <PortNumber; + sprintf(name, "SASPortPage0 / %02x", i); + showConfigPage(port, name, buf, len); + } + else + break; + } + } + + i = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0, i, buf, len) == 1) + { + i = get16(((pSasDevicePage0_t)buf)->DevHandle); + sprintf(name, "SASDevicePage0 / %04x", i); + showConfigPage(port, name, buf, len); + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 1, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE + <maxBuses << 8) + port->maxTargets; i++) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 2, + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID + <PhysicalIdentifier.High != 0 || + ((pSasDevicePage2_t)buf)->PhysicalIdentifier.Low != 0) + { + sprintf(name, "SASDevicePage2 / %d,%d", i >> 8, i & 255); + showConfigPage(port, name, buf, len); + } + } + } + } + + for (i = 0; i < 256; i++) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 0, i, buf, len) == 1) + { + sprintf(name, "SASPhyPage0 / %02x", i); + showConfigPage(port, name, buf, len); + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 1, i, buf, len) == 1) + { + sprintf(name, "SASPhyPage1 / %02x", i); + showConfigPage(port, name, buf, len); + } + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 2, i, buf, len) == 1) + { + sprintf(name, "SASPhyPage2 / %02x", i); + showConfigPage(port, name, buf, len); + } + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 3, i, buf, len) == 1) + { + sprintf(name, "SASPhyPage3 / %02x", i); + showConfigPage(port, name, buf, len); + } + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 4, i, buf, len) == 1) + { + sprintf(name, "SASPhyPage4 / %02x", i); + showConfigPage(port, name, buf, len); + } + } + else + break; + } + + i = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_ENCLOSURE, 0, i, buf, len) == 1) + { + i = get16(((pSasEnclosurePage0_t)buf)->EnclosureHandle); + sprintf(name, "SASEnclosurePage0 / %04x", i); + showConfigPage(port, name, buf, len); + } + else + break; + } + } + + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_LOG, 0, 0, buf, len) == 1) + { + showConfigPage(port, "LogPage0", buf, len); + } + + if (mpi2) + { + for (i = 0; i < port->maxPersistentIds; i++) + { + if (getConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING, 0, + (1<Entry.PhysicalIdentifier.High != 0 || + ((pMpi2DriverMappingPage0_t)buf)->Entry.PhysicalIdentifier.Low != 0) + { + sprintf(name, "DriverMappingPage0 / %04x", i); + showConfigPage(port, name, buf, len); + } + } + } + } + + if (mpi2) + { + if (getConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_ETHERNET, 0, 0, buf, len) == 1) + { + numInterfaces = ((pMpi2EthernetPage0_t)buf)->NumInterfaces; + for (i = 0; i < numInterfaces; i++) + { + if (getConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_ETHERNET, 0, i, buf, len) == 1) + { + sprintf(name, "EthernetPage0 / %02x", i); + showConfigPage(port, name, buf, len); + } + if (getConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_ETHERNET, 1, i, buf, len) == 1) + { + sprintf(name, "EthernetPage1 / %02x", i); + showConfigPage(port, name, buf, len); + } + } + } + } + + free(buf); + free(temp_buf); + + return 1; +} + + +int +doPortStateSummary(MPT_PORT *port) +{ + char *temp; + FCPortPage0_t FCPortPage0; + FCPortPage1_t FCPortPage1; + int flags; + int t; + IOCPage1_t IOCPage1; + int timeout; + int depth; + int on; + IOUnitPage1_t IOUnitPage1; + SCSIPortPage2_t SCSIPortPage2; + int settings; + int id; + SasIOUnitPage0_t SASIOUnitPage0; + SasIOUnitPage1_t *SASIOUnitPage1; + Mpi2SasIOUnitPage1_t *SASIOUnitPage1_2; + SasIOUnitPage2_t SASIOUnitPage2; + int length; + int i; + ManufacturingPage5_t *ManufacturingPage5; + Mpi2ManufacturingPage5_t *ManufacturingPage5_2; + int num_phys; + + printf("Current Port State\n------------------\n"); + showPortInfoHeader(port); + + printf("Software Version Information\n----------------------------\n"); + doIdentify(port); + + printf("\nFirmware Settings\n-----------------\n"); + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, + &FCPortPage0, sizeof FCPortPage0) != 1) + return 0; + + printf("FC WWNN: %08x%08x\n", + get32(FCPortPage0.WWNN.High), + get32(FCPortPage0.WWNN.Low)); + + printf("FC WWPN: %08x%08x\n", + get32(FCPortPage0.WWPN.High), + get32(FCPortPage0.WWPN.Low)); + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, + &FCPortPage1, sizeof FCPortPage1) != 1) + return 0; + + t = FCPortPage1.TopologyConfig & MPI_FCPORTPAGE1_TOPOLOGY_MASK; + switch (t) + { + case MPI_FCPORTPAGE1_TOPOLOGY_AUTO: temp = "Auto"; break; + case MPI_FCPORTPAGE1_TOPOLOGY_NLPORT: temp = "NL_Port"; break; + case MPI_FCPORTPAGE1_TOPOLOGY_NPORT: temp = "N_Port"; break; + default: temp = "Unknown"; break; + } + printf("Link Topology: %s\n", temp); + + if (port->mptVersion < MPI_VERSION_01_01) + temp = "1 Gb"; + else + { + t = FCPortPage1.LinkConfig & MPI_FCPORTPAGE1_LCONFIG_SPEED_MASK; + switch (t) + { + case MPI_FCPORTPAGE1_LCONFIG_SPEED_AUTO: temp = "Auto"; break; + case MPI_FCPORTPAGE1_LCONFIG_SPEED_1GIG: temp = "1 Gb"; break; + case MPI_FCPORTPAGE1_LCONFIG_SPEED_2GIG: temp = "2 Gb"; break; + case MPI_FCPORTPAGE1_LCONFIG_SPEED_4GIG: temp = "4 Gb"; break; + case MPI_FCPORTPAGE1_LCONFIG_SPEED_10GIG: temp = "10 Gb"; break; + default: temp = "Unknown"; break; + } + } + printf("Link Speed: %s\n", temp); + + flags = get32(FCPortPage1.Flags); + + t = (flags & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT) != 0; + printf("FCP Initiator protocol: %s\n", t == 0 ? "Disabled" : "Enabled"); + + t = (flags & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG) != 0; + printf("FCP Target protocol: %s\n", t == 0 ? "Disabled" : "Enabled"); + + t = (flags & MPI_FCPORTPAGE1_FLAGS_PROT_LAN) != 0; + printf("LAN protocol: %s\n", t == 0 ? "Disabled" : "Enabled"); + + t = (flags & MPI_FCPORTPAGE1_FLAGS_SORT_BY_DID) != 0; + printf("Assignment of Bus/Target IDs: %s\n", t == 0 ? "SortByWWN" : "SortByDID"); + + t = (flags & MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY) != 0; + printf("Immediate Error Reply: %s\n", t == 0 ? "Disabled" : "Enabled"); + + t = (flags & MPI_FCPORTPAGE1_FLAGS_MAINTAIN_LOGINS) != 0; + printf("Maintain Logins: %s\n", t == 0 ? "Disabled" : "Enabled"); + + t = FCPortPage1.HardALPA; + printf("Hard AL_PA: %02x\n", t); + + t = FCPortPage1.InitiatorDeviceTimeout; + if (t == 0) + t = 60; + printf("Initiator Device Timeout: %d\n", t); + + t = FCPortPage1.InitiatorIoPendTimeout; + if (t == 0) + t = 8; + printf("Initiator I/O Pending Timeout: %d\n", t); + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 1, 0, + &IOUnitPage1, sizeof IOUnitPage1) != 1) + return 0; + + flags = get32(IOUnitPage1.Flags); + + t = (flags & MPI_IOUNITPAGE1_MULTI_PATHING) != 0; + printf("Multi-pathing: %s\n", t == 0 ? "Disabled" : "Enabled"); + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 0, + &SCSIPortPage2, sizeof SCSIPortPage2) != 1) + return 0; + + flags = get32(SCSIPortPage2.PortFlags); + settings = get32(SCSIPortPage2.PortSettings); + + id = settings & MPI_SCSIPORTPAGE2_PORT_HOST_ID_MASK; + printf("Host SCSI ID: %d\n", id); + + t = (flags & MPI_SCSIPORTPAGE2_PORT_FLAGS_SCAN_HIGH_TO_LOW) != 0; + printf("Bus scan order: %s\n", t == 0 ? "LowToHigh" : "HighToLow"); + + t = (flags & MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) != 0; + printf("Avoid SCSI bus reset: %s\n", t == 0 ? "No" : "Yes"); + + t = (flags & MPI_SCSIPORTPAGE2_PORT_FLAGS_ALTERNATE_CHS) != 0; + printf("CHS mapping: %s\n", t == 0 ? "PlugAndPlay" : "AlternateCHS"); + + t = (settings & MPI_SCSIPORTPAGE2_PORT_REMOVABLE_MEDIA) >> 6; + switch (t) + { + case 0: temp = "None"; break; + case 1: temp = "BootDrive"; break; + case 2: temp = "AnyWithMedia"; break; + default: temp = "Unknown"; break; + } + printf("Removable media support: %s\n", temp); + + t = (settings & MPI_SCSIPORTPAGE2_PORT_SPINUP_DELAY_MASK) >> 8; + printf("Spinup delay (in seconds): %d\n", t); + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + ManufacturingPage5 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 5, 0, &length); + if (ManufacturingPage5 == NULL) + return 0; + + ManufacturingPage5_2 = (pMpi2ManufacturingPage5_t)ManufacturingPage5; + if (mpi2) + { + printf("SAS WWID: %08x%08x\n", + get32(ManufacturingPage5_2->Phy[0].WWID.High), + get32(ManufacturingPage5_2->Phy[0].WWID.Low)); + } + else + { + printf("SAS WWID: %08x%08x\n", + get32(ManufacturingPage5->BaseWWID.High), + get32(ManufacturingPage5->BaseWWID.Low)); + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IO_UNIT, 1, 0, + &IOUnitPage1, sizeof IOUnitPage1) != 1) + return 0; + + flags = get32(IOUnitPage1.Flags); + + t = (flags & MPI_IOUNITPAGE1_MULTI_PATHING) != 0; + printf("Multi-pathing: %s\n", t == 0 ? "Disabled" : "Enabled"); + + t = (flags & MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE) == 0; + printf("SATA Native Command Queuing: %s\n", t == 0 ? "Disabled" : "Enabled"); + + t = (flags & MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE) == 0; + printf("SATA Write Caching: %s\n", t == 0 ? "Disabled" : "Enabled"); + + SASIOUnitPage1 = getConfigPageAlloc(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 1, 0, &length); + if (SASIOUnitPage1 == NULL) + return 0; + + if (getConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0, + &SASIOUnitPage0, sizeof SASIOUnitPage0) == 1) + num_phys = SASIOUnitPage0.NumPhys; + else + num_phys = SASIOUnitPage1->NumPhys; + + t = SASIOUnitPage1->SATAMaxQDepth; + printf("SATA Maximum Queue Depth: %d\n", t); + + if (mpi2) + { + SASIOUnitPage1_2 = (pMpi2SasIOUnitPage1_t)SASIOUnitPage1; + + t = get16(SASIOUnitPage1_2->SASNarrowMaxQueueDepth); + printf("SAS Max Queue Depth, Narrow: %d\n", t); + + t = get16(SASIOUnitPage1_2->SASWideMaxQueueDepth); + printf("SAS Max Queue Depth, Wide: %d\n", t); + } + + t = SASIOUnitPage1->ReportDeviceMissingDelay; + if (t & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) + t = (t & ~MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) * 16; + printf("Device Missing Report Delay: %d seconds\n", t); + + t = SASIOUnitPage1->IODeviceMissingDelay; + printf("Device Missing I/O Delay: %d seconds\n", t); + + printf("Phy Parameters for Phynum: "); + for (i = 0; i < num_phys; i++) + printf("%-5d", i); + printf("\n"); + + printf(" Link Enabled: "); + for (i = 0; i < num_phys; i++) + { + if (mpi2) + t = SASIOUnitPage1->PhyData[i].PhyFlags & MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; + else + t = SASIOUnitPage1->PhyData[i].PhyFlags & MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; + printf("%-5s", t ? "No" : "Yes"); + } + printf("\n"); + + printf(" Link Min Rate: "); + for (i = 0; i < num_phys; i++) + { + t = SASIOUnitPage1->PhyData[i].MaxMinLinkRate & MPI_SAS_IOUNIT1_MIN_RATE_MASK; + printf("%-5s", + t == MPI25_SASIOUNIT1_MIN_RATE_12_0 ? "12.0" : + t == MPI2_SASIOUNIT1_MIN_RATE_6_0 ? "6.0" : + t == MPI_SAS_IOUNIT1_MIN_RATE_3_0 ? "3.0" : "1.5"); + } + printf("\n"); + + printf(" Link Max Rate: "); + for (i = 0; i < num_phys; i++) + { + t = SASIOUnitPage1->PhyData[i].MaxMinLinkRate & MPI_SAS_IOUNIT1_MAX_RATE_MASK; + printf("%-5s", + t == MPI25_SASIOUNIT1_MAX_RATE_12_0 ? "12.0" : + t == MPI2_SASIOUNIT1_MAX_RATE_6_0 ? "6.0" : + t == MPI_SAS_IOUNIT1_MAX_RATE_3_0 ? "3.0" : "1.5"); + } + printf("\n"); + + printf(" SSP Initiator Enabled: "); + for (i = 0; i < num_phys; i++) + { + t = get32(SASIOUnitPage1->PhyData[i].ControllerPhyDeviceInfo) & MPI_SAS_DEVICE_INFO_SSP_INITIATOR; + printf("%-5s", t ? "Yes" : "No"); + } + printf("\n"); + + printf(" SSP Target Enabled: "); + for (i = 0; i < num_phys; i++) + { + t = get32(SASIOUnitPage1->PhyData[i].ControllerPhyDeviceInfo) & MPI_SAS_DEVICE_INFO_SSP_TARGET; + printf("%-5s", t ? "Yes" : "No"); + } + printf("\n"); + printf(" Port Configuration: "); + for (i = 0; i < num_phys; i++) + { + if (SASIOUnitPage1->PhyData[i].PortFlags & MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG) + printf("%-5s", "Auto"); + else + printf("%-5d", SASIOUnitPage1->PhyData[i].Port); + } + printf("\n"); + + free(SASIOUnitPage1); + + if (mpi1) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 2, 0, + &SASIOUnitPage2, sizeof SASIOUnitPage2) != 1) + return 0; + + flags = SASIOUnitPage2.Flags; + + printf("Target IDs per enclosure: %d\n", SASIOUnitPage2.NumDevsPerEnclosure); + + t = (flags & MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS) == 0; + printf("Persistent mapping: %s\n", t == 0 ? "Disabled" : "Enabled"); + + t = (flags & MPI_SAS_IOUNIT2_FLAGS_MASK_PHYS_MAP_MODE) >> MPI_SAS_IOUNIT2_FLAGS_SHIFT_PHYS_MAP_MODE; + printf("Physical mapping type: %s\n", + t == MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP ? "None" : + t == MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP ? "Direct Attach" : + t == MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP ? "Enclosure/Slot" : + t == MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP ? "Host Assigned" : + "Unknown"); + + t = (flags & MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT) != 0; + printf("Target ID 0 reserved for boot: %s\n", t == 0 ? "No" : "Yes"); + + t = (flags & MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT) != 0; + printf("Starting slot (direct attach): %s\n", t == 0 ? "0" : "1"); + + printf("Target IDs (physical mapping): %d\n", get16(SASIOUnitPage2.MaxNumPhysicalMappedIDs)); + } + } + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 1, 0, &IOCPage1, sizeof IOCPage1) != 1) + return 0; + + flags = get32(IOCPage1.Flags) & MPI_IOCPAGE1_REPLY_COALESCING; + timeout = get32(IOCPage1.CoalescingTimeout); + depth = IOCPage1.CoalescingDepth; + + on = flags != 0 && timeout != 0 && depth != 0; + if (on) + printf("Interrupt Coalescing: Enabled, timeout is %d us, depth is %d\n", + timeout, depth); + else + printf("Interrupt Coalescing: Disabled\n"); + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + printf("\nPersistent Mappings\n-------------------\n"); + doFcPersistentMappings(port, 1); + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS && mpi1) + { + printf("\nPersistent Mappings\n-------------------\n"); + doSasPersistentMappings(port, 1); + } + + return 1; +} + + +int +getChipName(MPT_PORT *port) +{ + char *string; + char *chipName; + char *chipNameRev; + int family; + int revision; + char *type; + int i; + U32 seqcodeversion = 0; + + family = port->productId & MPI_FW_HEADER_PID_FAMILY_MASK; + revision = port->revisionId; + switch (port->deviceId) + { + case MPI_MANUFACTPAGE_DEVICEID_FC909: + string = "FC909 B1"; + type = "PCI"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC919: + string = "FC919 B0"; + type = "PCI"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC929: + string = "FC929 B0"; + type = "PCI"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC919X: + if (revision < 0x80) + string = "FC919X A0"; + else + string = "FC919XL A1"; + type = "PCI-X"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC929X: + if (revision < 0x80) + string = "FC929X A0"; + else + string = "FC929XL A1"; + type = "PCI-X"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC939X: + string = "FC939X A1"; + type = "PCI-X"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC949X: + string = "FC949X A1"; + type = "PCI-X"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC949E: + switch (revision) + { + case 0x00: + string = "FC949E A0"; + break; + case 0x01: + string = "FC949E A1"; + break; + case 0x02: + string = "FC949E A2"; + break; + default: + string = "FC949E xx"; + break; + } + type = "PCI-E"; + break; + case MPI_MANUFACTPAGE_DEVID_53C1030: + switch (revision) + { + case 0x00: + string = "53C1030 A0"; + break; + case 0x01: + string = "53C1030 B0"; + break; + case 0x03: + string = "53C1030 B1"; + break; + case 0x07: + string = "53C1030 B2"; + break; + case 0x08: + string = "53C1030 C0"; + break; + case 0x80: + string = "53C1030T A0"; + break; + case 0x83: + string = "53C1030T A2"; + break; + case 0x87: + string = "53C1030T A3"; + break; + case 0xc1: + string = "53C1020A A1"; + break; + default: + string = "53C1030 xx"; + break; + } + type = "PCI-X"; + break; + case MPI_MANUFACTPAGE_DEVID_1030_53C1035: + switch (revision) + { + case 0x03: + string = "53C1035 A2"; + break; + case 0x04: + string = "53C1035 B0"; + break; + default: + string = "53C1035 xx"; + break; + } + type = "PCI-X"; + break; + case MPI_MANUFACTPAGE_DEVID_SAS1064: + switch (revision) + { + case 0x00: + string = "SAS1064 A1"; seqcodeversion = 0x1064a1; + break; + case 0x01: + string = "SAS1064 A2"; seqcodeversion = 0x1064a2; + break; + case 0x02: + string = "SAS1064 A3"; seqcodeversion = 0x1064a3; + break; + case 0x03: + string = "SAS1064 A4"; seqcodeversion = 0x1064a4; + break; + default: + string = "SAS1064 xx"; seqcodeversion = 0x1064ff; + break; + } + type = "PCI-X"; + break; + case MPI_MANUFACTPAGE_DEVID_SAS1064E: + switch (revision) + { + case 0x00: + string = "SAS1064E A0"; seqcodeversion = 0x106ea0; + break; + case 0x01: + string = "SAS1064E B0"; seqcodeversion = 0x106eb0; + break; + case 0x02: + string = "SAS1064E B1"; seqcodeversion = 0x106eb1; + break; + case 0x04: + string = "SAS1064E B2"; seqcodeversion = 0x106eb2; + break; + case 0x08: + string = "SAS1064E B3"; seqcodeversion = 0x106eb3; + break; + case 0x10: + string = "SAS1064E C0"; seqcodeversion = 0x106ec0; + break; + default: + string = "SAS1064E xx"; seqcodeversion = 0x106eff; + break; + } + type = "PCI-E"; + break; + case MPI_MANUFACTPAGE_DEVID_SAS1066: + string = "SAS1066 xx"; + type = "PCI-X"; + break; + case MPI_MANUFACTPAGE_DEVID_SAS1066E: + string = "SAS1066E xx"; + type = "PCI-E"; + break; + case MPI_MANUFACTPAGE_DEVID_SAS1068: + switch (revision) + { + case 0x00: + string = "SAS1068 A0"; seqcodeversion = 0x1068a0; + break; + case 0x01: + string = "SAS1068 B0"; seqcodeversion = 0x1068b0; + break; + case 0x02: + string = "SAS1068 B1"; seqcodeversion = 0x1068b1; + break; + default: + string = "SAS1068 xx"; seqcodeversion = 0x1068ff; + break; + } + type = "PCI-X"; + break; + case MPI_MANUFACTPAGE_DEVID_SAS1068E: + switch (revision) + { + case 0x00: + string = "SAS1068E A0"; seqcodeversion = 0x106ea0; + break; + case 0x01: + string = "SAS1068E B0"; seqcodeversion = 0x106eb0; + break; + case 0x02: + string = "SAS1068E B1"; seqcodeversion = 0x106eb1; + break; + case 0x04: + string = "SAS1068E B2"; seqcodeversion = 0x106eb2; + break; + case 0x08: + string = "SAS1068E B3"; seqcodeversion = 0x106eb3; + break; + case 0x10: + string = "SAS1068E C0"; seqcodeversion = 0x106ec0; + break; + default: + string = "SAS1068E xx"; seqcodeversion = 0x106eff; + break; + } + type = "PCI-E"; + break; + case MPI_MANUFACTPAGE_DEVID_SAS1078: + switch (revision) + { + case 0x00: + string = "SAS1078 A0"; seqcodeversion = 0x1078a0; + break; + case 0x01: + string = "SAS1078 B0"; seqcodeversion = 0x1078b0; + break; + case 0x02: + string = "SAS1078 C0"; seqcodeversion = 0x1078c0; + break; + case 0x03: + string = "SAS1078 C1"; seqcodeversion = 0x1078c1; + break; + case 0x04: + string = "SAS1078 C2"; seqcodeversion = 0x1078c2; + break; + default: + string = "SAS1078 xx"; seqcodeversion = 0x1078ff; + break; + } + type = "PCI-E"; + break; + case MPI2_MFGPAGE_DEVID_SAS2004: + switch (revision) + { + case 0x00: + string = "SAS2004 A0"; + break; + case 0x01: + string = "SAS2004 B0"; + break; + case 0x02: + string = "SAS2004 B1"; + break; + case 0x03: + string = "SAS2004 B2"; + break; + default: + string = "SAS2004 xx"; + break; + } + type = "PCI-E"; + break; + case MPI2_MFGPAGE_DEVID_SAS2008: + switch (revision) + { + case 0x00: + string = "SAS2008 A0"; + break; + case 0x01: + string = "SAS2008 B0"; + break; + case 0x02: + string = "SAS2008 B1"; + break; + case 0x03: + string = "SAS2008 B2"; + break; + default: + string = "SAS2008 xx"; + break; + } + type = "PCI-E"; + break; + case MPI2_MFGPAGE_DEVID_SAS2108_1: + case MPI2_MFGPAGE_DEVID_SAS2108_2: + case MPI2_MFGPAGE_DEVID_SAS2108_3: + switch (revision) + { + case 0x00: + string = "SAS2108 A0"; + break; + case 0xFF: + string = "SAS2 FPGA A0"; + break; + /* the PCI Revision ID was not bumped between B0 and B1. Since B0 is not supported + * and had limited use (pre-production only), don't worry about identifying it. + * NOTE: PCI config space will always report a 1 for B0 or B1. The firmware + * (IOCPage0->RevisionID) is supposed to report a 1 for B0 and a 2 for B1 but it does not + * always do so. Therefore we consider either a 1 or 2 to be a B1 chip. + */ + case 0x01: + case 0x02: + string = "SAS2108 B1"; + break; + case 0x03: + string = "SAS2108 B2"; + break; + case 0x04: + string = "SAS2108 B3"; + break; + case 0x05: + string = "SAS2108 B4"; + break; + default: + string = "SAS2108 xx"; + break; + } + type = "PCI-E"; + break; + case MPI2_MFGPAGE_DEVID_SAS2116_1: + case MPI2_MFGPAGE_DEVID_SAS2116_2: + switch (revision) + { + case 0x00: + string = "SAS2116 A0"; + break; + case 0x01: + string = "SAS2116 B0"; + break; + case 0x02: + string = "SAS2116 B1"; + break; + default: + string = "SAS2116 xx"; + break; + } + type = "PCI-E"; + break; + case MPI2_MFGPAGE_DEVID_SAS2208_1: + case MPI2_MFGPAGE_DEVID_SAS2208_2: + case MPI2_MFGPAGE_DEVID_SAS2208_3: + case MPI2_MFGPAGE_DEVID_SAS2208_4: + case MPI2_MFGPAGE_DEVID_SAS2208_5: + case MPI2_MFGPAGE_DEVID_SAS2208_6: + switch (revision) + { + case 0x00: + string = "SAS2208 A0"; + break; + case 0x01: + string = "SAS2208 B0"; + break; + case 0x02: + string = "SAS2208 C0"; + break; + case 0x03: + string = "SAS2208 C1"; + break; + case 0x04: + string = "SAS2208 D0"; + break; + case 0x05: + string = "SAS2208 D1"; + break; + default: + string = "SAS2208 xx"; + break; + } + type = "PCI-E"; + break; + case MPI2_MFGPAGE_DEVID_SAS2308_1: + case MPI2_MFGPAGE_DEVID_SAS2308_2: + case MPI2_MFGPAGE_DEVID_SAS2308_3: + switch (revision) + { + case 0x00: + string = "SAS2308 A0"; + break; + case 0x01: + string = "SAS2308 B0"; + break; + case 0x02: + string = "SAS2308 C0"; + break; + case 0x03: + string = "SAS2308 C1"; + break; + case 0x04: + string = "SAS2308 D0"; + break; + case 0x05: + string = "SAS2308 D1"; + break; + default: + string = "SAS2308 xx"; + break; + } + type = "PCI-E"; + break; + case MPI25_MFGPAGE_DEVID_SAS3004: + switch (revision) + { + case 0x00: + string = "SA3004 A0"; + break; + case 0x01: + string = "SAS3004 B0"; + break; + case 0x02: + string = "SAS3004 C0"; + break; + default: + string = "SAS3004 xx"; + break; + } + type = "PCI-E"; + break; + case MPI25_MFGPAGE_DEVID_SAS3008: + switch (revision) + { + case 0x00: + string = "SA3008 A0"; + break; + case 0x01: + string = "SAS3008 B0"; + break; + case 0x02: + string = "SAS3008 C0"; + break; + default: + string = "SAS3008 xx"; + break; + } + type = "PCI-E"; + break; + case MPI25_MFGPAGE_DEVID_SAS3108_1: + case MPI25_MFGPAGE_DEVID_SAS3108_2: + case MPI25_MFGPAGE_DEVID_SAS3108_5: + case MPI25_MFGPAGE_DEVID_SAS3108_6: + switch (revision) + { + case 0x00: + string = "SAS3108 A0"; + break; + case 0x01: + string = "SAS3108 B0"; + break; + case 0x02: + string = "SAS3108 C0"; + break; + default: + string = "SAS3108 xx"; + break; + } + type = "PCI-E"; + break; +#ifdef SAS3108_FPGA_WORKAROUND + case 0x100: + case 0x092: + string = "SAS3108 FPGA"; + type = "PCI-E"; + break; +#endif + case MPI2_MFGPAGE_DEVID_SSS6200: + switch (revision) + { + case 0x00: + string = "SSS6200 A0"; + break; + case 0x01: + string = "SSS6200 B0"; + break; + case 0x02: + string = "SSS6200 C0"; + break; + default: + string = "SSS6200 xx"; + break; + } + type = "PCI-E"; + break; + default: + string = "xxxx xx"; + type = NULL; + break; + } + + port->seqCodeVersion = seqcodeversion; + + chipNameRev = malloc(strlen(string) + 1); + strcpy(chipNameRev, string); + + i = (int)strlen(chipNameRev) - 2; + + if (strncmp(chipNameRev + 0, "xxxx", 4) == 0) + sprintf(chipNameRev + 0, "%04x %02x", port->deviceId, port->revisionId); + else if (strncmp(chipNameRev + i, "xx", 2) == 0) + sprintf(chipNameRev + i, "%02x", port->revisionId); + + port->chipNameRev = chipNameRev; + + chipName = malloc(strlen(chipNameRev) + 1); + strcpy(chipName, chipNameRev); + + i = (int)strlen(chipNameRev) - 3; + chipName[i] = '\0'; + + port->chipName = chipName; + + port->pciType = type; + + return 1; +} + + +int +getPortInfo(MPT_PORT *port) +{ + IOCFactsReply_t IOCFacts; + PortFactsReply_t PortFacts; +#if !DOS && !EFI + IOCPage0_t IOCPage0; +#endif + SasIOUnitPage0_t SASIOUnitPage0; + + if (checkOperational(port, 0) != 1) + return 1; + + port->lastEvent = -1; + + port->payOff = 0; + + if (getIocFacts(port, &IOCFacts) != 1) + return 0; + +// dumpMemoryWide(&IOCFacts, sizeof IOCFacts, "IOCFactsReply"); + + port->mptVersion = get16(IOCFacts.MsgVersion); + + if (mpi2) + return getPortInfo2(port); + + port->iocNumber = IOCFacts.IOCNumber; + port->whoInit = IOCFacts.WhoInit; + port->productId = get16(IOCFacts.ProductID); + port->capabilities = get32(IOCFacts.IOCCapabilities); + port->flags = IOCFacts.Flags; + port->fwImageSize = get32(IOCFacts.FWImageSize); + port->payOff = get16(IOCFacts.CurReplyFrameSize); + port->maxBuses = IOCFacts.MaxBuses; + if (port->maxBuses == 0) + port->maxBuses = 1; + port->minTargets = 0; + port->maxTargets = IOCFacts.MaxDevices; + if (port->maxTargets == 0) + port->maxTargets = 255; /* Linux limit! */ + port->maxLuns = maxLuns; + + if (port->mptVersion < MPI_VERSION_01_02) + port->fwVersion = get16(IOCFacts.Reserved_0101_FWVersion); + else + port->fwVersion = get32(IOCFacts.FWVersion.Word); + + if (port->mptVersion < MPI_VERSION_01_02 && + port->productId == MPI_MANUFACTPAGE_DEVICEID_FC909) + port->productId = MPI_FW_HEADER_PID_FAMILY_909_FC | + MPI_FW_HEADER_PID_TYPE_FC; + + port->pidType = port->productId & MPI_FW_HEADER_PID_TYPE_MASK; + + if (getPortFacts(port, &PortFacts) != 1) + return 0; + +// dumpMemoryWide(&PortFacts, sizeof PortFacts, "PortFactsReply"); + + port->portType = PortFacts.PortType; + port->maxPersistentIds = get16(PortFacts.MaxPersistentIDs); + port->hostScsiId = get16(PortFacts.PortSCSIID); + port->protocolFlags = get16(PortFacts.ProtocolFlags); + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (port->maxTargets > port->hostScsiId + 1) + port->maxTargets = port->hostScsiId + 1; + } + else + { + if (port->maxTargets > get16(PortFacts.MaxDevices)) + port->maxTargets = get16(PortFacts.MaxDevices); + } + +#if !DOS && !EFI + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_IOC, 0, 0, &IOCPage0, sizeof IOCPage0) != 1) + return 0; + + if (get16(IOCPage0.VendorID) != MPI_MANUFACTPAGE_VENDORID_LSILOGIC) + return 0; + + port->deviceIdRaw = get16(IOCPage0.DeviceID); + + /* the following three want to be set to the device ID that doesnt include ZC*/ + if ( (port->deviceIdRaw == MPI_MANUFACTPAGE_DEVID_53C1030ZC) || + (port->deviceIdRaw == MPI_MANUFACTPAGE_DEVID_1030ZC_53C1035) || + (port->deviceIdRaw == MPI_MANUFACTPAGE_DEVID_53C1035ZC)) + { + port->deviceId = port->deviceIdRaw & ~1; + } + else + { + port->deviceId = port->deviceIdRaw; + } + + port->revisionId = IOCPage0.RevisionID; + + getChipName(port); +#endif + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0, + &SASIOUnitPage0, sizeof SASIOUnitPage0) == 1) + { + port->numPhys = SASIOUnitPage0.NumPhys; + } + else + { + switch (port->deviceId) + { + case MPI_MANUFACTPAGE_DEVID_SAS1064: + case MPI_MANUFACTPAGE_DEVID_SAS1064E: + port->numPhys = 4; + break; + case MPI_MANUFACTPAGE_DEVID_SAS1066: + case MPI_MANUFACTPAGE_DEVID_SAS1066E: + port->numPhys = 6; + break; + case MPI_MANUFACTPAGE_DEVID_SAS1068: + case MPI_MANUFACTPAGE_DEVID_SAS1068E: + case MPI_MANUFACTPAGE_DEVID_SAS1078: + port->numPhys = 8; + break; + } + } + } + + return 1; +} + + +int +getPortInfo2(MPT_PORT *port) +{ + Mpi2IOCFactsReply_t IOCFacts; + Mpi2PortFactsReply_t PortFacts; +#if !DOS && !EFI + Mpi2IOCPage0_t IOCPage0; +#endif + Mpi2SasIOUnitPage0_t SASIOUnitPage0; + + if (getIocFacts2(port, &IOCFacts) != 1) + return 0; + +// dumpMemoryWide(&IOCFacts, sizeof IOCFacts, "IOCFactsReply"); + + port->iocNumber = IOCFacts.IOCNumber; + port->whoInit = IOCFacts.WhoInit; + port->productId = get16(IOCFacts.ProductID); + port->capabilities = get32(IOCFacts.IOCCapabilities); + + // ReplyFrameSize moved within IOCFacts and went from + // indicating the number of bytes to indicating the + // number of dwords. Maintain backward compatibility + if (mpi25) + { + port->payOff = IOCFacts.ReplyFrameSize * 4; + } + else if (IOCFacts.OldReplyFrameSize) + { + port->payOff = get16(IOCFacts.OldReplyFrameSize); + } + else + { + port->payOff = IOCFacts.ReplyFrameSize * 4; + } + + port->maxDevHandle = get16(IOCFacts.MaxDevHandle) + 1; + + setMaxBusTarget(port); + + port->maxLuns = maxLuns; + port->protocolFlags = get16(IOCFacts.ProtocolFlags); + port->maxPersistentIds = get16(IOCFacts.MaxPersistentEntries); + + port->fwVersion = get32(IOCFacts.FWVersion.Word); + + port->fastpathCapable = port->capabilities & MPI25_IOCFACTS_CAPABILITY_FAST_PATH_CAPABLE ? 1 : 0; + + port->pidType = port->productId & MPI2_FW_HEADER_PID_TYPE_MASK; + + if (getPortFacts2(port, &PortFacts) != 1) + return 0; + +// dumpMemoryWide(&PortFacts, sizeof PortFacts, "PortFactsReply"); + + port->portType = PortFacts.PortType; + +#if !DOS && !EFI + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_IOC, 0, 0, &IOCPage0, sizeof IOCPage0) != 1) + return 0; + +#if SAS3108_FPGA_WORKAROUND + if (get16(IOCPage0.VendorID) != MPI2_MFGPAGE_VENDORID_LSI && get16(IOCPage0.VendorID) != SAS3108_FPGA_VENDORID) + return 0; +#else + if (get16(IOCPage0.VendorID) != MPI2_MFGPAGE_VENDORID_LSI) + return 0; +#endif + port->deviceIdRaw = get16(IOCPage0.DeviceID); + /* the following three want to be set to the device ID that doesnt include ZC*/ + if ( (port->deviceIdRaw == MPI_MANUFACTPAGE_DEVID_53C1030ZC) || + (port->deviceIdRaw == MPI_MANUFACTPAGE_DEVID_1030ZC_53C1035) || + (port->deviceIdRaw == MPI_MANUFACTPAGE_DEVID_53C1035ZC)) + { + port->deviceId = port->deviceIdRaw & ~1; + } + else + { + port->deviceId = port->deviceIdRaw; + } + port->revisionId = IOCPage0.RevisionID; + + getChipName(port); +#endif + + if (port->pidType == MPI2_FW_HEADER_PID_TYPE_SAS) + { + if (getConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0, + &SASIOUnitPage0, sizeof SASIOUnitPage0) == 1) + { + port->numPhys = SASIOUnitPage0.NumPhys; + } + else + { + switch (port->deviceId) + { + case MPI2_MFGPAGE_DEVID_SAS2004: + case MPI25_MFGPAGE_DEVID_SAS3004: + port->numPhys = 4; + break; + case MPI2_MFGPAGE_DEVID_SAS2008: + case MPI2_MFGPAGE_DEVID_SAS2108_1: + case MPI2_MFGPAGE_DEVID_SAS2108_2: + case MPI2_MFGPAGE_DEVID_SAS2108_3: + case MPI2_MFGPAGE_DEVID_SAS2208_1: + case MPI2_MFGPAGE_DEVID_SAS2208_2: + case MPI2_MFGPAGE_DEVID_SAS2208_3: + case MPI2_MFGPAGE_DEVID_SAS2208_4: + case MPI2_MFGPAGE_DEVID_SAS2208_5: + case MPI2_MFGPAGE_DEVID_SAS2208_6: + case MPI2_MFGPAGE_DEVID_SAS2308_1: + case MPI2_MFGPAGE_DEVID_SAS2308_2: + case MPI2_MFGPAGE_DEVID_SAS2308_3: + case MPI25_MFGPAGE_DEVID_SAS3008: + case MPI25_MFGPAGE_DEVID_SAS3108_1: + case MPI25_MFGPAGE_DEVID_SAS3108_2: + case MPI25_MFGPAGE_DEVID_SAS3108_5: + case MPI25_MFGPAGE_DEVID_SAS3108_6: + case MPI2_MFGPAGE_DEVID_SSS6200: + port->numPhys = 8; + break; + case MPI2_MFGPAGE_DEVID_SAS2116_1: + case MPI2_MFGPAGE_DEVID_SAS2116_2: + port->numPhys = 16; + break; + } + } + } + + return 1; +} + + +int +updatePortInfo(MPT_PORT *port) +{ + IOCFactsReply_t IOCFacts; + PortFactsReply_t PortFacts; + + if (port->mptVersion == 0) + return getPortInfo(port); + + if (getIocFacts(port, &IOCFacts) != 1) + return 0; + + port->mptVersion = get16(IOCFacts.MsgVersion); + + if (mpi2) + return updatePortInfo2(port); + + if (port->mptVersion < MPI_VERSION_01_02) + port->fwVersion = get16(IOCFacts.Reserved_0101_FWVersion); + else + port->fwVersion = get32(IOCFacts.FWVersion.Word); + port->capabilities = get32(IOCFacts.IOCCapabilities); + + if (port->portType == MPI_PORTFACTS_PORTTYPE_INACTIVE) + { + if (getPortFacts(port, &PortFacts) != 1) + return 0; + + port->portType = PortFacts.PortType; + port->maxPersistentIds = get16(PortFacts.MaxPersistentIDs); + port->hostScsiId = get16(PortFacts.PortSCSIID); + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (port->maxTargets > port->hostScsiId + 1) + port->maxTargets = port->hostScsiId + 1; + } + else + { + if (port->maxTargets > get16(PortFacts.MaxDevices)) + port->maxTargets = get16(PortFacts.MaxDevices); + } + } + + return 1; +} + + +int +updatePortInfo2(MPT_PORT *port) +{ + Mpi2IOCFactsReply_t IOCFacts; + Mpi2PortFactsReply_t PortFacts; + + if (getIocFacts2(port, &IOCFacts) != 1) + return 0; + + port->fwVersion = get32(IOCFacts.FWVersion.Word); + port->capabilities = get32(IOCFacts.IOCCapabilities); + + port->maxDevHandle = get16(IOCFacts.MaxDevHandle) + 1; + + setMaxBusTarget(port); + + port->maxPersistentIds = get16(IOCFacts.MaxPersistentEntries); + + if (port->portType == MPI_PORTFACTS_PORTTYPE_INACTIVE) + { + if (getPortFacts2(port, &PortFacts) != 1) + return 0; + + port->portType = PortFacts.PortType; + } + + return 1; +} + + +int +getBoardInfo(MPT_PORT *port) +{ + int segment = 0; + int bus = 0; + int device = 0; + int function = 0; +#if WIN32 + int status; + DRVR_INFO_SRB srb; + int inLen; + int outLen; + DWORD retLen; +#endif +#if __linux__ + int status; + struct mpt_ioctl_iocinfo iocinfo; +#endif +#if __sparc__ + SYMHI_DMI_DATA dmiData; + mptsas_pci_info_t pciInfo; + int status; + U32 reg[64]; +#endif +#if DOS || EFI + HANDLE adap = port->fileHandle; +#endif + + if (port->pciSegment != 0 || port->pciBus != 0 || port->pciDevice != 0 || port->pciFunction != 0) + return 1; + +#if WIN32 + memset(&srb, 0, sizeof srb); + + srb.Sic.Length = sizeof srb - sizeof srb.Sic; + srb.Sic.ControlCode = DRVR_INFO_IOCTL; + srb.Sic.HeaderLength = sizeof srb.Sic; + srb.Sic.Timeout = SHORT_TIME; + + memcpy((char *)&srb.Sic.Signature, "4.00 ", 8); + + srb.PageCode = ADAPTER_INFO_PAGE; + + inLen = sizeof srb; + outLen = sizeof srb; + retLen = 0; + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + &srb, inLen, &srb, outLen, &retLen, NULL); + + if (status != 1) + return 0; + + if (retLen >= sizeof srb) + segment = srb.AdapterPageOut.PciSegmentId; + else + segment = srb.AdapterPageOut.PciInfo.u.bits.BusNumber >> 8; + bus = srb.AdapterPageOut.PciInfo.u.bits.BusNumber & 0xff; + device = srb.AdapterPageOut.PciInfo.u.bits.DeviceNumber; + function = srb.AdapterPageOut.PciInfo.u.bits.FunctionNumber; +#endif +#if __linux__ + memset(&iocinfo, 0, sizeof iocinfo); + + iocinfo.hdr.maxDataSize = sizeof iocinfo; + + iocinfo.hdr.iocnum = port->portNumber; + + if (mpi2) + status = ioctl(port->fileHandle, MPT2IOCINFO, &iocinfo); + else + status = ioctl(port->fileHandle, MPTIOCINFO, &iocinfo); + + if (status != 0) + return 0; + + segment = iocinfo.pciInfo.segmentID; + bus = iocinfo.pciInfo.u.bits.busNumber; + device = iocinfo.pciInfo.u.bits.deviceNumber; + function = iocinfo.pciInfo.u.bits.functionNumber; +#endif +#if __sparc__ + if (mpi2) + { + memset(&pciInfo, 0, sizeof pciInfo); + status = ioctl(port->fileHandle, MPTIOCTL_GET_PCI_INFO, &pciInfo); + if (status == 0) + { + bus = pciInfo.BusNumber; + device = pciInfo.DeviceNumber; + function = pciInfo.FunctionNumber; + } + else + return 0; + } + else + { + memset(&dmiData, 0, sizeof dmiData); + dmiData.StructureLength = sizeof dmiData; + status = ioctl(port->fileHandle, SYMIOCTL_GET_DMI_DATA, &dmiData); + + if (status == 0) + { + bus = dmiData.PciBusNumber; + device = dmiData.PciDeviceNumber; + function = dmiData.PciFunctionNumber; + } + else + { + memset(reg, 0, sizeof reg); + + status = getProperty(port, "reg", (char *)reg, sizeof reg); + + if (status == 0) + return 0; + + bus = (reg[0] >> 16) & 0xff; + device = (reg[0] >> 11) & 0x1f; + function = (reg[0] >> 8) & 0x07; + } + } + +#endif +#if DOS || EFI + segment = adap->segment_number; + bus = adap->bus_number; + device = (adap->device_function >> 3) & 31; + function = (adap->device_function >> 0) & 7; +#endif + + port->pciSegment = segment; + port->pciBus = bus; + port->pciDevice = device; + port->pciFunction = function; + + return 1; +} + + +int +showBoardInfo(MPT_PORT *port, int flag) +{ + ManufacturingPage0_t ManufacturingPage0; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, + &ManufacturingPage0, sizeof ManufacturingPage0) != 1) + return 0; + + if (getBoardInfo(port) == 1) + { + if (flag) + { + printf("Seg/Bus/Dev/Fun Board Name Board Assembly Board Tracer\n"); + printf("%2d %2d %2d %2d %-16.16s %-16.16s %-16.16s\n", + port->pciSegment, port->pciBus, port->pciDevice, port->pciFunction, + ManufacturingPage0.BoardName, ManufacturingPage0.BoardAssembly, ManufacturingPage0.BoardTracerNumber); + + } + else + { + printf("%-16s %2d %2d %2d %-16.16s %-16.16s %-16.16s\n", + port->portName, port->pciSegment, port->pciBus, port->pciDevice, + ManufacturingPage0.BoardName, ManufacturingPage0.BoardAssembly, ManufacturingPage0.BoardTracerNumber); + } + } + else + { + if (flag) + { + printf("Seg/Bus/Dev/Fun Board Name Board Assembly Board Tracer\n"); + printf(" %-16.16s %-16.16s %-16.16s\n", + ManufacturingPage0.BoardName, ManufacturingPage0.BoardAssembly, ManufacturingPage0.BoardTracerNumber); + + } + else + { + printf("%-16s %-16.16s %-16.16s %-16.16s\n", + port->portName, + ManufacturingPage0.BoardName, ManufacturingPage0.BoardAssembly, ManufacturingPage0.BoardTracerNumber); + } + } + + return 1; +} + + +int +dumpFcDevicePages(MPT_PORT *port) +{ + FCDevicePage0_t FCDevicePage0; + U32 d_id; + + printf(" B___T WWNN WWPN PortId ALPA FrSize BBCr Prot Flag\n"); + + d_id = 0xffffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, d_id, + &FCDevicePage0, sizeof FCDevicePage0) != 1) + break; + + d_id = get32(FCDevicePage0.PortIdentifier); + + if (FCDevicePage0.Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID) + { + printf("%2d %3d %08x%08x %08x%08x %06x %02x %04x %02x %02x %02x\n", + FCDevicePage0.CurrentBus, FCDevicePage0.CurrentTargetID, + get32(FCDevicePage0.WWNN.High), get32(FCDevicePage0.WWNN.Low), + get32(FCDevicePage0.WWPN.High), get32(FCDevicePage0.WWPN.Low), + d_id, FCDevicePage0.ADISCHardALPA, get16(FCDevicePage0.MaxRxFrameSize), + get16(FCDevicePage0.BBCredit), FCDevicePage0.Protocol, FCDevicePage0.Flags); + } + else + { + printf(" %08x%08x %08x%08x %06x %02x %04x %02x %02x %02x\n", + get32(FCDevicePage0.WWNN.High), get32(FCDevicePage0.WWNN.Low), + get32(FCDevicePage0.WWPN.High), get32(FCDevicePage0.WWPN.Low), + d_id, FCDevicePage0.ADISCHardALPA, get16(FCDevicePage0.MaxRxFrameSize), + get16(FCDevicePage0.BBCredit), FCDevicePage0.Protocol, FCDevicePage0.Flags); + } + } + + return 1; +} + + +int +dumpSasDevicePages(MPT_PORT *port) +{ + SasDevicePage0_t SASDevicePage0; + U32 handle; + int bus; + int target; + int flags; + int mapped; + + printf(" B___T SASAddress Handle Encl/Slot DevInfo/Flag/Acc Port Parent PhyNum\n"); + + handle = 0xffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0, handle, + &SASDevicePage0, sizeof SASDevicePage0) != 1) + break; + + handle = get16(SASDevicePage0.DevHandle); + flags = get16(SASDevicePage0.Flags); + + if (mpi1) + { + mapped = flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED; + bus = SASDevicePage0.Bus; + target = SASDevicePage0.TargetID; + } + else + { + mapped = mapDevHandleToBusTarget(port, handle, &bus, &target); + } + + if (SASDevicePage0.ParentDevHandle == 0) + { + printf(" %08x%08x %04x\n", + get32(SASDevicePage0.SASAddress.High), get32(SASDevicePage0.SASAddress.Low), + handle); + } + else if (mapped) + { + printf("%2d %3d %08x%08x %04x %04x %2d %08x %04x %02x %2d %04x %2d\n", + bus, target, + get32(SASDevicePage0.SASAddress.High), get32(SASDevicePage0.SASAddress.Low), + handle, get16(SASDevicePage0.EnclosureHandle), get16(SASDevicePage0.Slot), + get32(SASDevicePage0.DeviceInfo), flags, SASDevicePage0.AccessStatus, + SASDevicePage0.PhysicalPort, get16(SASDevicePage0.ParentDevHandle), + SASDevicePage0.PhyNum); + } + else + { + printf(" %08x%08x %04x %04x %2d %08x %04x %02x %2d %04x %2d\n", + get32(SASDevicePage0.SASAddress.High), get32(SASDevicePage0.SASAddress.Low), + handle, get16(SASDevicePage0.EnclosureHandle), get16(SASDevicePage0.Slot), + get32(SASDevicePage0.DeviceInfo), flags, SASDevicePage0.AccessStatus, + SASDevicePage0.PhysicalPort, get16(SASDevicePage0.ParentDevHandle), + SASDevicePage0.PhyNum); + } + } + + return 1; +} + + +int +showPortInfo(MPT_PORT *port) +{ + FCPortPage0_t FCPortPage0; + FCDevicePage0_t FCDevicePage0; + int i; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + char buf[16]; + int portId; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, &FCPortPage0, sizeof FCPortPage0) != 1) + return 0; + + portId = get32(FCPortPage0.PortIdentifier); + + sprintf(buf, "%s Port", port->chipName); + printf(" %-24s %08x%08x %06x\n", buf, + get32(FCPortPage0.WWPN.High), get32(FCPortPage0.WWPN.Low), portId); + + i = 0xffffff; + while (TRUE) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, i, + &FCDevicePage0, sizeof FCDevicePage0) != 1) + break; + + i = get32(FCDevicePage0.PortIdentifier); + + if (i == portId) + continue; + + if (FCDevicePage0.Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET) + continue; + + if (FCDevicePage0.Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR) + printf(" FCP Initiator %08x%08x %06x\n", + get32(FCDevicePage0.WWPN.High), get32(FCDevicePage0.WWPN.Low), i); + else + printf(" Non-FCP %08x%08x %06x\n", + get32(FCDevicePage0.WWPN.High), get32(FCDevicePage0.WWPN.Low), i); + } + return 1; + } + + return 0; +} + + +int +showPortInfoHeader(MPT_PORT *port) +{ + FCPortPage0_t FCPortPage0; + SasIOUnitPage0_t *SASIOUnitPage0; + Mpi2SasIOUnitPage0_t *SASIOUnitPage0_2; + SasIOUnit0PhyData *SASIOUnit0PhyData; + int i; + + if (bringOnline(port) != 1) + return 0; + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + printf("%s's host SCSI ID is %d\n\n", port->chipName, port->hostScsiId); + return 1; + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + char *attach; + char *speed; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, &FCPortPage0, sizeof FCPortPage0) != 1) + return 0; + + switch (get32(FCPortPage0.Flags) & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK) + { + case MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT: attach = NULL; break; + case MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT: attach = "point to point"; break; + case MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP: attach = "private loop"; break; + case MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT: attach = "fabric direct attach"; break; + case MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP: attach = "public loop"; break; + default: attach = "unknown"; break; + } + + if (port->mptVersion < MPI_VERSION_01_01) + speed = "1 Gbps"; + else + switch (get32(FCPortPage0.CurrentSpeed)) + { + case MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT: speed = "1 Gbps"; break; + case MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT: speed = "2 Gbps"; break; + case MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT: speed = "4 Gbps"; break; + case MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT: speed = "10 Gbps"; break; + default: speed = "unknown"; break; + } + + if (attach != NULL) + printf("%s's link is online, type is %s, speed is %s\n\n", port->chipName, attach, speed); + else + printf("%s's link is offline\n\n", port->chipName); + return 1; + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + int length; + char *speed; + int rate; + + SASIOUnitPage0 = getConfigPageAlloc(port, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0, &length); + if (SASIOUnitPage0 == NULL) + return 0; + + SASIOUnitPage0_2 = (pMpi2SasIOUnitPage0_t)SASIOUnitPage0; + + if (SASIOUnitPage0->NumPhys == 1) + printf("%s's link is ", port->chipName); + else + printf("%s's links are ", port->chipName); + + for (i = 0; i < SASIOUnitPage0->NumPhys; i++) + { + if (i != 0) + printf(", "); + + if (mpi2) + { + SASIOUnit0PhyData = (pSasIOUnit0PhyData)&SASIOUnitPage0_2->PhyData[i]; + rate = (SASIOUnit0PhyData->NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL) >> + MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL; + } + else + { + SASIOUnit0PhyData = (pSasIOUnit0PhyData)&SASIOUnitPage0->PhyData[i]; + rate = SASIOUnit0PhyData->NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL; + } + + switch (rate) + { + case MPI_SAS_IOUNIT0_RATE_UNKNOWN: + speed = "down"; + break; + + case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: + speed = "off"; + break; + + case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: + speed = "failed"; + break; + + case MPI_SAS_IOUNIT0_RATE_1_5: + speed = "1.5 G"; + break; + + case MPI_SAS_IOUNIT0_RATE_3_0: + speed = "3.0 G"; + break; + + case MPI2_SAS_NEG_LINK_RATE_6_0: + speed = "6.0 G"; + break; + + case MPI25_SAS_NEG_LINK_RATE_12_0: + speed = "12.0 G"; + break; + + default: + speed = "unknown"; + break; + } + + printf(speed); + } + + printf("\n\n"); + + free(SASIOUnitPage0); + + return 1; + } + + return 0; +} + + +int +getDeviceInfo(MPT_PORT *port, int bus, int target, char *buf, int len) +{ + SCSIDevicePage0_t SCSIDevicePage0; + FCDevicePage0_t FCDevicePage0; + SasDevicePage0_t SASDevicePage0; + int b_t; + int dev_handle; + int address; + + buf[0] = '\0'; + + b_t = (bus << 8) + mapOsToHwTarget(port, target); + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 0, b_t, + &SCSIDevicePage0, sizeof SCSIDevicePage0) == 1) + { + int parameters = get32(SCSIDevicePage0.NegotiatedParameters); + int speed = parameters & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK; + int width = parameters & MPI_SCSIDEVPAGE0_NP_WIDE; + int mbps; + char *speed_string; + char *width_string; + + if ((parameters & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) == 0) + speed = 0; + + if (speed == 0) + { + speed_string = "Async"; + mbps = 0; + } + else if (speed <= 0x800) + { + speed_string = "Ultra4"; + mbps = 160; + } + else if (speed <= 0x900) + { + speed_string = "Ultra3"; + mbps = 80; + } + else if (speed <= 0xa00) + { + speed_string = "Ultra2"; + mbps = 40; + } + else if (speed <= 0xc00) + { + speed_string = "Ultra"; + mbps = 20; + } + else if (speed <= 0x1900) + { + speed_string = "Fast"; + mbps = 64000 / speed; + } + else + { + speed_string = "Sync"; + mbps = 64000 / speed; + } + + if (width == 0) + { + width_string = "Narrow"; + } + else + { + width_string = "Wide"; + mbps *= 2; + } + + if (get32(SCSIDevicePage0.Information) & MPI_SCSIDEVPAGE0_INFO_PARAMS_NEGOTIATED) + { + sprintf(buf, "%s %s", speed_string, width_string); + if (mbps > 0) + sprintf(buf+strlen(buf), ", %d MB/sec", mbps); + return 1; + } + } + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, + MPI_FC_DEVICE_PGAD_FORM_BUS_TID + b_t, + &FCDevicePage0, sizeof FCDevicePage0) == 1) + { + sprintf(buf, "%08x%08x %06x", + get32(FCDevicePage0.WWPN.High), get32(FCDevicePage0.WWPN.Low), + get32(FCDevicePage0.PortIdentifier)); + return 1; + } + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + if (mpi2) + { + if (mapBusTargetToDevHandle(port, bus, target, &dev_handle) != 1) + dev_handle = 0; + address = MPI2_SAS_DEVICE_PGAD_FORM_HANDLE + dev_handle; + } + else + { + b_t = (bus << 8) + target; + address = (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID + <pidType == MPI_FW_HEADER_PID_TYPE_SCSI) + { + sprintf(buf, "Negotiated Speed & Width"); + return 1; + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + sprintf(buf, " WWPN PortId"); + return 1; + } + + if (port->pidType == MPI_FW_HEADER_PID_TYPE_SAS) + { + sprintf(buf, " SASAddress PhyNum"); + return 1; + } + + return 0; +} + + +int +getIocFacts(MPT_PORT *port, IOCFactsReply_t *rep) +{ + IOCFacts_t req; + + memset(&req, 0, sizeof req); + memset(rep, 0, sizeof *rep); + + req.Function = MPI_FUNCTION_IOC_FACTS; + + return doMptCommand(port, &req, sizeof req, rep, sizeof *rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +getIocFacts2(MPT_PORT *port, Mpi2IOCFactsReply_t *rep) +{ + Mpi2IOCFactsRequest_t req; + + memset(&req, 0, sizeof req); + memset(rep, 0, sizeof *rep); + + req.Function = MPI2_FUNCTION_IOC_FACTS; + + return doMptCommand(port, &req, sizeof req, rep, sizeof *rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +getPortFacts(MPT_PORT *port, PortFactsReply_t *rep) +{ + PortFacts_t req; + + memset(&req, 0, sizeof req); + memset(rep, 0, sizeof *rep); + + req.Function = MPI_FUNCTION_PORT_FACTS; + + return doMptCommand(port, &req, sizeof req, rep, sizeof *rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +getPortFacts2(MPT_PORT *port, Mpi2PortFactsReply_t *rep) +{ + Mpi2PortFactsRequest_t req; + + memset(&req, 0, sizeof req); + memset(rep, 0, sizeof *rep); + + req.Function = MPI2_FUNCTION_PORT_FACTS; + + return doMptCommand(port, &req, sizeof req, rep, sizeof *rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +int +doConfigPageRequest(MPT_PORT *port, void *req, int reqSize, void *rep, int repSize, + void *payIn, int payInSize, void *payOut, int payOutSize, int timeOut) +{ + int i; + + for (i = 0; i < 120; i++) + { + if (doMptCommand(port, req, reqSize, rep, repSize, payIn, payInSize, payOut, payOutSize, timeOut) != 1) + return 0; + + if (get16(((ConfigReply_t *)rep)->IOCStatus) != MPI_IOCSTATUS_BUSY) + { + if (i > 0) + printf("SUCCESS\n"); + return 1; + } + + if (i == 0) + printf("Firmware returned busy status, retrying."); + else + printf("."); + + fflush(stdout); + + sleep(1); + } + + printf("\nRetries exhausted. Giving up request!\n"); + return 1; +} + + +int +getConfigPageHeader(MPT_PORT *port, int type, int number, int address, ConfigReply_t *repOut) +{ + Config_t req; + ConfigReply_t rep; + int ioc_status; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_CONFIG; + req.AliasIndex = virtInit; + req.Action = MPI_CONFIG_ACTION_PAGE_HEADER; + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + { + req.Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + req.ExtPageType = type; + } + else + { + req.Header.PageType = type; + } + req.Header.PageNumber = number; + req.PageAddress = set32(address); + + if (doConfigPageRequest(port, &req, sizeof req - sizeof req.PageBufferSGE, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + return 0; + + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + return 0; + + if (repOut != NULL) + memcpy(repOut, &rep, sizeof rep); + + return 1; +} + + +int +getConfigPageLength(MPT_PORT *port, int type, int number, int address, int *length) +{ + Config_t req; + ConfigReply_t rep; + int ioc_status; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_CONFIG; + req.AliasIndex = virtInit; + req.Action = MPI_CONFIG_ACTION_PAGE_HEADER; + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + { + req.Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + req.ExtPageType = type; + } + else + { + req.Header.PageType = type; + } + req.Header.PageNumber = number; + req.PageAddress = set32(address); + + if (doConfigPageRequest(port, &req, sizeof req - sizeof req.PageBufferSGE, &rep, sizeof rep, + NULL, 0, NULL, 0, SHORT_TIME) != 1) + return 0; + + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + return 0; + + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + *length = get16(rep.ExtPageLength) * 4; + else + *length = rep.Header.PageLength * 4; + + return 1; +} + + +int +getConfigPageAction(MPT_PORT *port, int action, int type, int number, int address, void *page, int pageSize) +{ + Config_t req; + ConfigReply_t rep, rep1; + ConfigPageHeader_t header; + int length; + int t; + int ioc_status; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + if (getConfigPageHeader(port, type, number, address, &rep) != 1) + return 0; + + memcpy(&rep1, &rep, sizeof rep); + + header = rep.Header; + length = get16(rep.ExtPageLength); + + req.Function = MPI_FUNCTION_CONFIG; + req.AliasIndex = virtInit; + if (action != -1) + req.Action = action; + else if ((rep.Header.PageType & MPI_CONFIG_PAGEATTR_MASK) == MPI_CONFIG_PAGEATTR_PERSISTENT || + (rep.Header.PageType & MPI_CONFIG_PAGEATTR_MASK) == MPI_CONFIG_PAGEATTR_RO_PERSISTENT) + req.Action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM; + else + req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + if (req.Action == MPI_CONFIG_ACTION_PAGE_READ_NVRAM && port->mptVersion < MPI_VERSION_01_01) + req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + req.ExtPageType = rep.ExtPageType; + req.ExtPageLength = rep.ExtPageLength; + req.Header = rep.Header; + req.PageAddress = set32(address); + + if (doConfigPageRequest(port, &req, sizeof req - sizeof req.PageBufferSGE, &rep, sizeof rep, + page, pageSize, NULL, 0, SHORT_TIME) != 1) + return 0; + + port->ioc_status = ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE || + ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_DATA) + { + if (action == MPI_CONFIG_ACTION_PAGE_READ_NVRAM) + { + printf("\nNon-volatile storage for this page is invalid!\n"); +#if 0 + printf("The current values for this page will be used instead\n"); + req.Action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM; +#else + return 0; +#endif + } + + if (req.Action == MPI_CONFIG_ACTION_PAGE_READ_NVRAM) + { + req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if (doConfigPageRequest(port, &req, sizeof req - sizeof req.PageBufferSGE, &rep, sizeof rep, + page, pageSize, NULL, 0, SHORT_TIME) != 1) + return 0; + + port->ioc_status = ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + } + } + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + return 0; + + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + { + if (get16(rep.ExtPageLength) == 0) + return 0; + if (memcmp(&header, &rep.Header, sizeof header) != 0) + printf("Warning, header in HEADER reply does not match header in READ reply\n (%08x vs. %08x)\n", + get32x(*(U32 *)&header), get32x(*(U32 *)&rep.Header)); + if (length != get16(rep.ExtPageLength)) + printf("Warning, length in HEADER reply does not match length in READ reply\n (%d vs. %d)\n", + length, get16(rep.ExtPageLength)); + t = get16(((pConfigExtendedPageHeader_t)page)->ExtPageLength); + if (t && get16(rep.ExtPageLength) != t) + printf("Warning, page length in reply does not match page length in buffer\n (%d vs. %d)\n", + get16(rep.ExtPageLength), t); + } + else + { + if (rep.Header.PageLength == 0) + return 0; + if (memcmp(&header, &rep.Header, sizeof header) != 0) + printf("Warning, header in HEADER reply does not match header in READ reply\n (%08x vs. %08x)\n", + get32x(*(U32 *)&header), get32x(*(U32 *)&rep.Header)); + t = ((pConfigPageHeader_t)page)->PageLength; + if (t && rep.Header.PageLength != t) + printf("Warning, page length in reply does not match page length in buffer\n (%d vs. %d)\n", + rep.Header.PageLength, t); + } + + return 1; +} + + +int +getConfigPage(MPT_PORT *port, int type, int number, int address, void *page, int pageSize) +{ + return getConfigPageAction(port, -1, type, number, address, page, pageSize); +} + + +void * +getConfigPageActionAlloc(MPT_PORT *port, int action, int type, int number, int address, int *length) +{ + void *page; + + if (getConfigPageLength(port, type, number, address, length) == 1) + { + page = malloc(*length); + + if (getConfigPageAction(port, action, type, number, address, page, *length) == 1) + { + return page; + } + + free(page); + } + + return NULL; +} + + +void * +getConfigPageAlloc(MPT_PORT *port, int type, int number, int address, int *length) +{ + return getConfigPageActionAlloc(port, -1, type, number, address, length); +} + + +int +setConfigPageAction(MPT_PORT *port, int action, int type, int number, int address, void *page, int pageSize) +{ + Config_t req; + ConfigReply_t rep; + ConfigPageHeader_t header; + int length; + int t; + int ioc_status; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + if (getConfigPageHeader(port, type, number, address, &rep) != 1) + return 0; + + header = rep.Header; + length = get16(rep.ExtPageLength); + + req.Function = MPI_FUNCTION_CONFIG; + req.AliasIndex = virtInit; + if (action != -1) + req.Action = action; + else if ((rep.Header.PageType & MPI_CONFIG_PAGEATTR_MASK) == MPI_CONFIG_PAGEATTR_PERSISTENT || + (rep.Header.PageType & MPI_CONFIG_PAGEATTR_MASK) == MPI_CONFIG_PAGEATTR_RO_PERSISTENT) + req.Action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM; + else + req.Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + req.ExtPageType = rep.ExtPageType; + req.ExtPageLength = rep.ExtPageLength; + req.Header = rep.Header; + req.PageAddress = set32(address); + + if (doConfigPageRequest(port, &req, sizeof req - sizeof req.PageBufferSGE, &rep, sizeof rep, + NULL, 0, page, pageSize, SHORT_TIME) != 1) + return 0; + + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + if(wFlag) + fprintf(logFile, "IOC Status returned from doConfigPageRequest = [%08X]", ioc_status); + port->ioc_status = ioc_status; + return 0; + } + + if (type > MPI_CONFIG_PAGETYPE_EXTENDED) + { + if (get16(rep.ExtPageLength) == 0) + return 0; + if (memcmp(&header, &rep.Header, sizeof header) != 0) + printf("Warning, header in HEADER reply does not match header in WRITE reply\n (%08x vs. %08x)\n", + get32x(*(U32 *)&header), get32x(*(U32 *)&rep.Header)); + if (length != get16(rep.ExtPageLength)) + printf("Warning, length in HEADER reply does not match length in WRITE reply\n (%d vs. %d)\n", + length, get16(rep.ExtPageLength)); + t = get16(((pConfigExtendedPageHeader_t)page)->ExtPageLength); + if (t && get16(rep.ExtPageLength) != t) + printf("Warning, page length in reply does not match page length in buffer\n (%d vs. %d)\n", + get16(rep.ExtPageLength), t); + } + else + { + if (rep.Header.PageLength == 0) + return 0; + if (memcmp(&header, &rep.Header, sizeof header) != 0) + printf("Warning, header in HEADER reply does not match header in WRITE reply\n (%08x vs. %08x)\n", + get32x(*(U32 *)&header), get32x(*(U32 *)&rep.Header)); + t = ((pConfigPageHeader_t)page)->PageLength; + if (t && rep.Header.PageLength != t) + printf("Warning, page length in reply does not match page length in buffer\n (%d vs. %d)\n", + rep.Header.PageLength, t); + } + + return 1; +} + + +int +setConfigPage(MPT_PORT *port, int type, int number, int address, void *page, int pageSize) +{ + int t; + + t = setConfigPageAction(port, -1, type, number, address, page, pageSize); + + if (t != 1) + if (wFlag) + fprintf(logFile, "%s: CONFIG write to NVRAM, type %x, number %x: FAIL\n", + logPrefix(port), type, number); + + return t; +} + + +int +showConfigPage(MPT_PORT *port, char *string, void *page, int length) +{ + ConfigPageHeader_t *header; + int n; + int numAvailDwords; + + header = (pConfigPageHeader_t)page; + + if ((header->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) + n = get16(((pConfigExtendedPageHeader_t)header)->ExtPageLength); + else + n = header->PageLength; + + numAvailDwords = min(n, length/4); + dumpMemory(page, numAvailDwords * 4, string); + + if (n > length/4) + printf("WARNING: %s Truncated. %d dwords printed but page contains %d dwords\n", string, length/4, n); + + return 1; +} + + +#if __sparc__ +int +getProperty(MPT_PORT *port, char *name, char *buf, int bufLen) +{ + SYM_GET_PROPERTY getProperty; + + getProperty.PtrName = (UINT64)(UINT32)name; + getProperty.PtrBuffer = (UINT64)(UINT32)buf; + getProperty.NameLen = strlen(name); + getProperty.BufferLen = bufLen; + getProperty.PropertyLen = 0; + + if (ioctl(port->fileHandle, SYMIOCTL_GET_PROPERTY, &getProperty) == 0) + return getProperty.PropertyLen; + + return 0; +} +#endif + + +void +setName(MPT_PORT *port, int bus, int target, void *req) +{ + SCSIIORequest_t *req1 = (pSCSIIORequest_t)req; + Mpi2SCSIIORequest_t *req2 = (pMpi2SCSIIORequest_t)req; + int dev_handle; + + + if (mpi2) + { + if (mapBusTargetToDevHandle(port, bus, target, &dev_handle) != 1) + dev_handle = 0; + + req2->DevHandle = set16(dev_handle); + } + else + { + req1->TargetID = mapOsToHwTarget(port, target); + req1->Bus = bus; + } +} + + +int +setMaxBusTarget(MPT_PORT *port) +{ + /* DOS, EFI, and SAS2 Solaris do not support devHandle to + * bus/target mapping so we "fudge" things here + */ +#if DOS || EFI || __sparc__ + int n; + + n = port->maxDevHandle; + if (n > 256) + { + port->maxBuses = (n + 255) / 256; + port->maxTargets = 256; + } + else + { + port->maxBuses = 1; + port->maxTargets = n; + } +#else + int maxBuses; + int minTargets; + int maxTargets; + int bus; + int target; + int devHandle; + + maxBuses = 0; + minTargets = 0xffff; + maxTargets = 0; + for (devHandle = 0; devHandle < port->maxDevHandle; devHandle++) + { + if (mapDevHandleToBusTarget(port, devHandle, &bus, &target) == 1) + { + if (bus > maxBuses) + maxBuses = bus; + if (target < minTargets) + minTargets = target; + if (target > maxTargets) + maxTargets = target; + } + } + port->maxBuses = maxBuses + 1; + port->minTargets = minTargets == 0xffff ? 0 : minTargets; + port->maxTargets = maxTargets + 1; +#endif + + return 1; +} + + +int +mapDevHandleToBusTarget(MPT_PORT *port, int dev_handle, int *bus, int *target) +{ + int t; + + if (port == mappedPort && dev_handle == mappedDevHandle) + { + *bus = mappedBus; + *target = mappedTarget; +#if __sparc__ + if (*bus == 0xffff || *target == 0xffff) + return 0; +#endif + if (*bus == 0xffffffff || *target == 0xffffffff) + return 0; + else + return 1; + } + + *bus = 0xffffffff; + *target = 0xffffffff; + + t = mapBTDH(port, bus, target, &dev_handle); + + if (t == 1) + { + mappedPort = port; + mappedBus = *bus; + mappedTarget = *target; + mappedDevHandle = dev_handle; + +#if __sparc__ + if (*bus == 0xffff || *target == 0xffff) + t = 0; +#endif + if (*bus == 0xffffffff || *target == 0xffffffff) + t = 0; + } + + return t; +} + + +int +mapBusTargetToDevHandle(MPT_PORT *port, int bus, int target, int *dev_handle) +{ + int t; + + if (port == mappedPort && bus == mappedBus && target == mappedTarget) + { + *dev_handle = mappedDevHandle; + if (*dev_handle == 0xffff) + return 0; + else + return 1; + } + + *dev_handle = 0xffff; + + t = mapBTDH(port, &bus, &target, dev_handle); + + if (t == 1) + { + mappedPort = port; + mappedBus = bus; + mappedTarget = target; + mappedDevHandle = *dev_handle; + + if (*dev_handle == 0xffff) + t = 0; + } + + return t; +} + + +int +mapBTDH(MPT_PORT *port, int *bus, int *target, int *dev_handle) +{ +#if WIN32 + int status; + MPI_BTDH_MAP_SRB srb; + int inLen; + int outLen; + DWORD retLen; + + memset(&srb, 0, sizeof srb); + + srb.Sic.Length = sizeof srb - sizeof srb.Sic; + srb.Sic.ControlCode = MPI_BTDH_MAPPING; + srb.Sic.HeaderLength = sizeof srb.Sic; + srb.Sic.Timeout = SHORT_TIME; + + memcpy((char *)&srb.Sic.Signature, "4.00 ", 8); + + srb.Bus = *bus; + srb.TargetID = *target; + srb.DevHandle = *dev_handle; + + inLen = sizeof srb; + outLen = sizeof srb; + retLen = 0; + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + &srb, inLen, &srb, outLen, &retLen, NULL); + + *bus = srb.Bus; + *target = srb.TargetID; + *dev_handle = srb.DevHandle; + + return status; +#endif +#if __linux__ + int status; + struct mpt2_ioctl_btdh_mapping btdh_mapping; + + memset(&btdh_mapping, 0, sizeof btdh_mapping); + + btdh_mapping.hdr.ioc_number = port->portNumber; + + btdh_mapping.bus = *bus; + btdh_mapping.id = *target; + btdh_mapping.handle = *dev_handle; + + status = ioctl(port->fileHandle, MPT2BTDHMAPPING, &btdh_mapping); + + *bus = btdh_mapping.bus; + *target = btdh_mapping.id; + *dev_handle = btdh_mapping.handle; + + return status == 0; +#endif +#if __sparc__ + int status; + SYM_BTDH_MAPPING btdhMapping; + + if (port->ioctlValue == MPTIOCTL_PASS_THRU) // this matches the mpt_sas driver + { + if (*bus == 0xffffffff && *target == 0xffffffff && *dev_handle != 0xffff) + { + *bus = (*dev_handle >> 8) & 0xff; + *target = (*dev_handle >> 0) & 0xff; + + return 1; + } + + if (*bus != 0xffffffff && *target != 0xffffffff && *dev_handle == 0xffff) + { + *dev_handle = ((*bus & 0xff) << 8) | ((*target & 0xff) << 0); + + return 1; + } + + return 0; + } + else // legacy support for the lsimpt SAS2 driver + { + btdhMapping.Bus = *bus; + btdhMapping.TargetID = *target; + btdhMapping.DevHandle = *dev_handle; + + status = ioctl(port->fileHandle, SYMIOCTL_BTDH_MAPPING, &btdhMapping); + + *bus = btdhMapping.Bus; + *target = btdhMapping.TargetID; + *dev_handle = btdhMapping.DevHandle; + + return status == 0; + } +#endif +#if DOS || EFI + if (*bus == 0xffffffff && *target == 0xffffffff && *dev_handle != 0xffff) + { + *bus = (*dev_handle >> 8) & 0xff; + *target = (*dev_handle >> 0) & 0xff; + + return 1; + } + + if (*bus != 0xffffffff && *target != 0xffffffff && *dev_handle == 0xffff) + { + *dev_handle = ((*bus & 0xff) << 8) | ((*target & 0xff) << 0); + + return 1; + } + + return 0; +#endif +} + + +int +mapOsToHwTarget(MPT_PORT *port, int target) +{ +#if __sparc__ + if (port->pidType == MPI_FW_HEADER_PID_TYPE_FC) + { + char name[32]; + char buffer[16]; + U32 wwnh; + U32 wwnl; + U32 port_id; + FCDevicePage0_t FCDevicePage0; + int i; + int t; + + if (port == mappedPort && target == mappedTarget) + return mappedValue; + + mappedPort = port; + mappedTarget = target; + mappedValue = port->hostScsiId; + + sprintf(name, "target-%d-wwn-nv", target); + t = getProperty(port, name, buffer, sizeof buffer); + + if (t != 8) + { + sprintf(name, "target-%d-wwn-cf", target); + t = getProperty(port, name, buffer, sizeof buffer); + } + + if (t != 8) + { + sprintf(name, "target-%d-wwn-hw", target); + t = getProperty(port, name, buffer, sizeof buffer); + } + + if (t == 8) + { +#if i386 + wwnl = ((U32 *)buffer)[0]; + wwnh = ((U32 *)buffer)[1]; +#else + wwnh = ((U32 *)buffer)[0]; + wwnl = ((U32 *)buffer)[1]; +#endif + for (i = 0; i < 256; i++) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, + MPI_FC_DEVICE_PGAD_FORM_BUS_TID + i, + &FCDevicePage0, sizeof FCDevicePage0) == 1) + { + if (wwnh == get32(FCDevicePage0.WWPN.High) && + wwnl == get32(FCDevicePage0.WWPN.Low)) + { + mappedValue = i; + return i; + } + } + } + + return mappedValue; + } + + sprintf(name, "target-%d-did-nv", target); + t = getProperty(port, name, buffer, sizeof buffer); + + if (t != 4) + { + sprintf(name, "target-%d-did-cf", target); + t = getProperty(port, name, buffer, sizeof buffer); + } + + if (t != 4) + { + sprintf(name, "target-%d-did-hw", target); + t = getProperty(port, name, buffer, sizeof buffer); + } + + if (t == 4) + { + port_id = ((U32 *)buffer)[0]; + + for (i = 0; i < 256; i++) + { + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_FC_DEVICE, 0, + MPI_FC_DEVICE_PGAD_FORM_BUS_TID + i, + &FCDevicePage0, sizeof FCDevicePage0) == 1) + { + if (port_id == get32(FCDevicePage0.PortIdentifier)) + { + mappedValue = i; + return i; + } + } + } + + return mappedValue; + } + + target = port->hostScsiId; + } +#endif + return target; +} + + +int +doTestUnitReady(MPT_PORT *port, int bus, int target, int lun) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 6; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(tagType); + req.CDB[0] = 0x00; + req.CDB[1] = 0; + req.CDB[2] = 0; + req.CDB[3] = 0; + req.CDB[4] = 0; + req.CDB[5] = 0; + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, NULL, 0, NULL, 0, IO_TIME); +} + + +int +doInquiry(MPT_PORT *port, int bus, int target, int lun, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 6; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x12; + req.CDB[1] = 0; + req.CDB[2] = 0; + req.CDB[3] = 0; + req.CDB[4] = len; + req.CDB[5] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); +} + + +int +doInquiryVpdPage(MPT_PORT *port, int bus, int target, int lun, int page, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 6; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x12; + req.CDB[1] = 1; + req.CDB[2] = page; + req.CDB[3] = 0; + req.CDB[4] = len; + req.CDB[5] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); +} + + +int +doLogSense(MPT_PORT *port, int bus, int target, int lun, int page, int pc, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x4d; + req.CDB[1] = 0; + req.CDB[2] = (pc << 6) | page; + req.CDB[3] = 0; + req.CDB[4] = 0; + req.CDB[5] = 0; + req.CDB[6] = 0; + req.CDB[7] = len >> 8; + req.CDB[8] = len; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); +} + + +int +doLogSelect(MPT_PORT *port, int bus, int target, int lun, int pc, int sp, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_WRITE | tagType); + req.CDB[0] = 0x4c; + req.CDB[1] = sp << 0; + req.CDB[2] = pc << 6; + req.CDB[3] = 0; + req.CDB[4] = 0; + req.CDB[5] = 0; + req.CDB[6] = 0; + req.CDB[7] = len >> 8; + req.CDB[8] = len; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, NULL, 0, buf, len, IO_TIME); +} + + +int +doReadBlockLimits(MPT_PORT *port, int bus, int target, int lun, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 6; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x05; + req.CDB[1] = 0; + req.CDB[2] = 0; + req.CDB[3] = 0; + req.CDB[4] = 0; + req.CDB[5] = 0; + req.CDB[6] = 0; + req.CDB[7] = 0; + req.CDB[8] = 0; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); +} + + +int +doReadCapacity(MPT_PORT *port, int bus, int target, int lun, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x25; + req.CDB[1] = 0; + req.CDB[2] = 0; + req.CDB[3] = 0; + req.CDB[4] = 0; + req.CDB[5] = 0; + req.CDB[6] = 0; + req.CDB[7] = 0; + req.CDB[8] = 0; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); +} + + +int +doReadCapacity16(MPT_PORT *port, int bus, int target, int lun, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 16; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x9e; + req.CDB[1] = 0x10; + req.CDB[2] = 0; + req.CDB[3] = 0; + req.CDB[4] = 0; + req.CDB[5] = 0; + req.CDB[6] = 0; + req.CDB[7] = 0; + req.CDB[8] = 0; + req.CDB[9] = 0; + req.CDB[10] = len >> 24; + req.CDB[11] = len >> 16; + req.CDB[12] = len >> 8; + req.CDB[13] = len; + req.CDB[14] = 0; + req.CDB[15] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); +} + + +int +doModeSense(MPT_PORT *port, int bus, int target, int lun, int page, int control, int dbd, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 6; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x1a; + req.CDB[1] = (dbd << 3); + req.CDB[2] = page | (control << 6); + req.CDB[3] = 0; + req.CDB[4] = len; + req.CDB[5] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); +} + + +int +doModeSelect(MPT_PORT *port, int bus, int target, int lun, int save, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 6; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_WRITE | tagType); + req.CDB[0] = 0x15; + req.CDB[1] = (1 << 4) | (save << 0); + req.CDB[2] = 0; + req.CDB[3] = 0; + req.CDB[4] = len; + req.CDB[5] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, NULL, 0, buf, len, IO_TIME); +} + + +int +doReadBuffer(MPT_PORT *port, int bus, int target, int lun, int mode, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x3c; + req.CDB[1] = mode; + req.CDB[2] = 0; + req.CDB[3] = 0; + req.CDB[4] = 0; + req.CDB[5] = 0; + req.CDB[6] = len >> 16; + req.CDB[7] = len >> 8; + req.CDB[8] = len; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); +} + + +int +doWriteBuffer(MPT_PORT *port, int bus, int target, int lun, int mode, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_WRITE | tagType); + req.CDB[0] = 0x3b; + req.CDB[1] = mode; + req.CDB[2] = 0; + req.CDB[3] = 0; + req.CDB[4] = 0; + req.CDB[5] = 0; + req.CDB[6] = len >> 16; + req.CDB[7] = len >> 8; + req.CDB[8] = len; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, NULL, 0, buf, len, IO_TIME); +} + + +int +doReadBufferFull(MPT_PORT *port, int bus, int target, int lun, int mode, int id, int offset, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.LUN[1] = lun; + req.AliasIndex = virtInit; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x3c; + req.CDB[1] = mode; + req.CDB[2] = id; + req.CDB[3] = offset >> 16; + req.CDB[4] = offset >> 8; + req.CDB[5] = offset; + req.CDB[6] = len >> 16; + req.CDB[7] = len >> 8; + req.CDB[8] = len; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, LONG_TIME); +} + + +int +doWriteBufferFull(MPT_PORT *port, int bus, int target, int lun, int mode, int id, int offset, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.LUN[1] = lun; + req.AliasIndex = virtInit; + req.Control = set32(MPI_SCSIIO_CONTROL_WRITE | tagType); + req.CDB[0] = 0x3b; + req.CDB[1] = mode; + req.CDB[2] = id; + req.CDB[3] = offset >> 16; + req.CDB[4] = offset >> 8; + req.CDB[5] = offset; + req.CDB[6] = len >> 16; + req.CDB[7] = len >> 8; + req.CDB[8] = len; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, NULL, 0, buf, len, LONG_TIME); +} + + +int +doRead(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int lbns, int mode, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + int raid = port->raidPassthru && bus == port->raidBus && target == port->raidTarget; + + if (mode & 0xf0f) + return doRead32(port, bus, target, lun, lbn, lbns, mode, buf, len); + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x28; + req.CDB[1] = mode & 0xf0; + req.CDB[2] = lbn >> 24; + req.CDB[3] = lbn >> 16; + req.CDB[4] = lbn >> 8; + req.CDB[5] = lbn; + req.CDB[6] = 0; + req.CDB[7] = lbns >> 8; + req.CDB[8] = lbns; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, raid, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); +} + + +int +doWrite(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int lbns, int mode, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + int raid = port->raidPassthru && bus == port->raidBus && target == port->raidTarget; + + if (mode & 0xf0f) + return doWrite32(port, bus, target, lun, lbn, lbns, mode, buf, len); + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_WRITE | tagType); + req.CDB[0] = 0x2a; + req.CDB[1] = mode & 0xf0; + req.CDB[2] = lbn >> 24; + req.CDB[3] = lbn >> 16; + req.CDB[4] = lbn >> 8; + req.CDB[5] = lbn; + req.CDB[6] = 0; + req.CDB[7] = lbns >> 8; + req.CDB[8] = lbns; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, raid, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, NULL, 0, buf, len, IO_TIME); +} + + +int +doVerify(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int lbns, int mode, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + int raid = port->raidPassthru && bus == port->raidBus && target == port->raidTarget; + +// if (mode) +// return doVerify32(port, bus, target, lun, lbn, lbns, mode, buf, len); + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_WRITE | tagType); + req.CDB[0] = 0x2f; + req.CDB[1] = len ? (1<<1) : 0; + req.CDB[2] = lbn >> 24; + req.CDB[3] = lbn >> 16; + req.CDB[4] = lbn >> 8; + req.CDB[5] = lbn; + req.CDB[6] = 0; + req.CDB[7] = lbns >> 8; + req.CDB[8] = lbns; + req.CDB[9] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, raid, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, NULL, 0, buf, len, IO_TIME); +} + + +int +doRead32(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int lbns, int mode, unsigned char *buf, int len) +{ + SCSIIO32Request_t req; + SCSI_REPLY rep; + unsigned char *buf2 = buf; + int len2 = len; + int t; + int flags; + + if (mode == 0x201) + { + len += lbns * 8; + buf = malloc(len); + + t = doRead(port, bus, target, lun, lbn, lbns, 0x20, buf, len); + + if (t == 1) + { + t = checkRemoveT10(port, lbn, lbns, buf, buf2, len2); + } + + free(buf); + + return t; + } + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_32; + req.AliasIndex = virtInit; + req.CDBLength = 10; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO32_CONTROL_READ | tagType); + req.CDB.EEDP16.CDB[0] = 0x28; + req.CDB.EEDP16.CDB[1] = 0; + req.CDB.EEDP16.CDB[2] = lbn >> 24; + req.CDB.EEDP16.CDB[3] = lbn >> 16; + req.CDB.EEDP16.CDB[4] = lbn >> 8; + req.CDB.EEDP16.CDB[5] = lbn; + req.CDB.EEDP16.CDB[6] = 0; + req.CDB.EEDP16.CDB[7] = lbns >> 8; + req.CDB.EEDP16.CDB[8] = lbns; + req.CDB.EEDP16.CDB[9] = 0; + req.CDB.EEDP16.PrimaryReferenceTag = set32(swap32(lbn)); + req.CDB.EEDP16.PrimaryApplicationTagMask = set16(0xffff); + req.DataLength = set32(len); + req.DeviceAddress.SCSIID.Bus = bus; + req.DeviceAddress.SCSIID.TargetID = mapOsToHwTarget(port, target); + + flags = MPI_SCSIIO32_EEDPFLAGS_INC_PRI_REFTAG | + MPI_SCSIIO32_EEDPFLAGS_T10_CHK_GUARD | + MPI_SCSIIO32_EEDPFLAGS_T10_CHK_REFTAG | + MPI_SCSIIO32_EEDPFLAGS_T10_CHK_LBATAG; + + if (mode == 0x101) + { + len += lbns * 8; + buf = malloc(len); + + flags |= MPI_SCSIIO32_EEDPFLAGS_CHK_OP; + + req.CDB.EEDP16.CDB[1] = 0x20; + req.DataLength = set32(len); + req.EEDPBlockSize = set32(512 + 8); + } + + if (mode == 0x1) + { + flags |= MPI_SCSIIO32_EEDPFLAGS_CHKRM_OP; + + req.CDB.EEDP16.CDB[1] = 0x20; + req.EEDPBlockSize = set32(512 + 8); + } + + if (mode == 0x102 || mode == 0x2) + { + len += lbns * 8; + buf = malloc(len); + + flags |= MPI_SCSIIO32_EEDPFLAGS_CHK_OP; + + req.CDB.EEDP16.CDB[5] = lbn & ~7; + req.DataLength = set32(len); + req.EEDPBlockSize = set32(4096 + 64); + } + + req.EEDPFlags = set16(flags); + + t = doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); + + if (mode == 0x101) + { + if (t == 1) + { + t = checkRemoveT10(port, lbn, lbns, buf, buf2, len2); + } + + free(buf); + } + + if (mode == 0x102) + { + if (t == 1) + { +// LB CRC not done yet... +// t = checkRemoveLb(port, lbn, lbns, buf, buf2, len2, 1); + t = checkRemoveLb(port, lbn, lbns, buf, buf2, len2, 0); + } + + free(buf); + } + + if (mode == 0x2) + { + if (t == 1) + { + t = checkRemoveLb(port, lbn, lbns, buf, buf2, len2, 0); + } + + free(buf); + } + + return t; +} + + +int +doWrite32(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int lbns, int mode, unsigned char *buf, int len) +{ + SCSIIO32Request_t req; + SCSI_REPLY rep; + unsigned char *buf2 = buf; + int t; + int flags; + + if (mode == 0x201) + { + len += lbns * 8; + buf = malloc(len); + + insertT10(port, lbn, lbns, buf2, buf, len); + + t = doWrite(port, bus, target, lun, lbn, lbns, 0x20, buf, len); + + free(buf); + + return t; + } + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_32; + req.AliasIndex = virtInit; + req.CDBLength = 10; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO32_CONTROL_WRITE | tagType); + req.CDB.EEDP16.CDB[0] = 0x2a; + req.CDB.EEDP16.CDB[1] = 0; + req.CDB.EEDP16.CDB[2] = lbn >> 24; + req.CDB.EEDP16.CDB[3] = lbn >> 16; + req.CDB.EEDP16.CDB[4] = lbn >> 8; + req.CDB.EEDP16.CDB[5] = lbn; + req.CDB.EEDP16.CDB[6] = 0; + req.CDB.EEDP16.CDB[7] = lbns >> 8; + req.CDB.EEDP16.CDB[8] = lbns; + req.CDB.EEDP16.CDB[9] = 0; + req.CDB.EEDP16.PrimaryReferenceTag = set32(swap32(lbn)); + req.CDB.EEDP16.PrimaryApplicationTagMask = set16(0xffff); + req.DataLength = set32(len); + req.DeviceAddress.SCSIID.Bus = bus; + req.DeviceAddress.SCSIID.TargetID = mapOsToHwTarget(port, target); + + flags = MPI_SCSIIO32_EEDPFLAGS_INC_PRI_REFTAG | + MPI_SCSIIO32_EEDPFLAGS_T10_CHK_GUARD | + MPI_SCSIIO32_EEDPFLAGS_T10_CHK_REFTAG | + MPI_SCSIIO32_EEDPFLAGS_T10_CHK_LBATAG; + + if (mode == 0x101) + { + len += lbns * 8; + buf = malloc(len); + + flags |= MPI_SCSIIO32_EEDPFLAGS_NOOP_OP; + + req.CDB.EEDP16.CDB[1] = 0x20; + req.DataLength = set32(len); +// req.EEDPFlags |= set16(MPI_SCSIIO32_EEDPFLAGS_CHK_OP); + req.EEDPBlockSize = set32(512 + 8); + + insertT10(port, lbn, lbns, buf2, buf, len); + } + + if (mode == 0x1) + { + flags |= MPI_SCSIIO32_EEDPFLAGS_INSERT_OP; + + req.CDB.EEDP16.CDB[1] = 0x20; + req.DataLength = set32(len); + req.EEDPBlockSize = set32(512 + 8); + } + + if (mode == 0x102) + { + len += lbns * 8; + buf = malloc(len); + +// LB CRC not done yet... +// flags |= MPI_SCSIIO32_EEDPFLAGS_CHKREGEN_OP; + flags |= MPI_SCSIIO32_EEDPFLAGS_REPLACE_OP; + + req.CDB.EEDP16.CDB[5] = lbn & ~7; + req.DataLength = set32(len); + req.EEDPBlockSize = set32(4096 + 64); + + insertLb(port, lbn, lbns, buf2, buf, len, 1); + } + + if (mode == 0x2) + { + len += lbns * 8; + buf = malloc(len); + + flags |= MPI_SCSIIO32_EEDPFLAGS_REPLACE_OP; + + req.CDB.EEDP16.CDB[5] = lbn & ~7; + req.DataLength = set32(len); + req.EEDPBlockSize = set32(4096 + 64); + + insertLb(port, lbn, lbns, buf2, buf, len, 0); + } + + req.EEDPFlags = set16(flags); + + t = doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, NULL, 0, buf, len, IO_TIME); + + if (mode == 0x101 || mode == 0x102 || mode == 0x2) + { + free(buf); + } + + return t; +} + + +int +doReadLong(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int mode, unsigned char *buf, int len, int *resid) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + int raid = port->raidPassthru && bus == port->raidBus && target == port->raidTarget; + int t; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x3e; + req.CDB[1] = 0; + req.CDB[2] = lbn >> 24; + req.CDB[3] = lbn >> 16; + req.CDB[4] = lbn >> 8; + req.CDB[5] = lbn; + req.CDB[6] = 0; + req.CDB[7] = len >> 8; + req.CDB[8] = len; + req.CDB[9] = 0; + req.DataLength = set32(len); + + t = doScsiIo(port, bus, target, raid, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); + + if (t == 1) + { + *resid = 0; + return 1; + } + else if (rep.reply.SCSIStatus == MPI_SCSI_STATUS_CHECK_CONDITION) + { + if (rep.sense[0] == 0xf0 && rep.sense[2] & 0x20) + { + *resid = get4bytes(rep.sense, 3); + return 1; + } + } + + return 0; +} + + +int +doWriteLong(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int mode, unsigned char *buf, int len, int *resid) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + int raid = port->raidPassthru && bus == port->raidBus && target == port->raidTarget; + int t; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 10; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_WRITE | tagType); + req.CDB[0] = 0x3f; + req.CDB[1] = len ? 0 : (unsigned char)(1<<6); + req.CDB[2] = lbn >> 24; + req.CDB[3] = lbn >> 16; + req.CDB[4] = lbn >> 8; + req.CDB[5] = lbn; + req.CDB[6] = 0; + req.CDB[7] = len >> 8; + req.CDB[8] = len; + req.CDB[9] = 0; + req.DataLength = set32(len); + + t = doScsiIo(port, bus, target, raid, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, NULL, 0, buf, len, IO_TIME); + + if (t == 1) + { + *resid = 0; + return 1; + } + else if (rep.reply.SCSIStatus == MPI_SCSI_STATUS_CHECK_CONDITION) + { + if (rep.sense[0] == 0xf0 && rep.sense[2] & 0x20) + { + *resid = get4bytes(rep.sense, 3); + return 1; + } + } + + return 0; +} + + +int +doReportLuns(MPT_PORT *port, int bus, int target, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + int t; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 12; + req.AliasIndex = virtInit; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0xa0; + req.CDB[1] = 0; + req.CDB[2] = 0; + req.CDB[3] = 0; + req.CDB[4] = 0; + req.CDB[5] = 0; + req.CDB[6] = len >> 24; + req.CDB[7] = len >> 16; + req.CDB[8] = len >> 8; + req.CDB[9] = len; + req.CDB[10] = 0; + req.CDB[11] = 0; + req.DataLength = set32(len); + + t = doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); + + if (t == 1) + { + return 1; + } + else if (rep.reply.SCSIStatus == MPI_SCSI_STATUS_CHECK_CONDITION) + { + if (rep.sense[0] == 0xf0 && rep.sense[2] & 0x20) + { + return 1; + } + } + + return 0; +} + + +int +doReceiveDiagnosticResults(MPT_PORT *port, int bus, int target, int lun, int page, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 6; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_READ | tagType); + req.CDB[0] = 0x1c; + req.CDB[1] = 1; + req.CDB[2] = page; + req.CDB[3] = len >> 8; + req.CDB[4] = len; + req.CDB[5] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, buf, len, NULL, 0, IO_TIME); +} + + +int +doSendDiagnostic(MPT_PORT *port, int bus, int target, int lun, unsigned char *buf, int len) +{ + SCSIIORequest_t req; + SCSI_REPLY rep; + + memset(&req, 0, sizeof req); + + req.Function = MPI_FUNCTION_SCSI_IO_REQUEST; + req.CDBLength = 6; + req.AliasIndex = virtInit; + req.LUN[1] = lun; + req.Control = set32(MPI_SCSIIO_CONTROL_WRITE | tagType); + req.CDB[0] = 0x1d; + req.CDB[1] = 1 << 4; + req.CDB[2] = 0; + req.CDB[3] = len >> 8; + req.CDB[4] = len; + req.CDB[5] = 0; + req.DataLength = set32(len); + + return doScsiIo(port, bus, target, 0, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, NULL, 0, buf, len, LONG_TIME); +} + + +int +doScsiIo(MPT_PORT *port, int bus, int target, int raid, void *req, int reqSize, SCSI_REPLY *rep1, int rep1Size, + void *payIn, int payInSize, void *payOut, int payOutSize, int timeOut) +{ + int ioc_status; + int ioc_loginfo; + SCSIIORequest_t *req1; + Mpi2SCSIIORequest_t req2; + Mpi25SCSIIORequest_t req25; + SCSI_REPLY2 rep2; + void *rep; + int repSize; + int command = -1; + + req1 = req; + if (req1->Function == MPI_FUNCTION_SCSI_IO_REQUEST) + { + command = req1->CDB[0]; + + setName(port, bus, target, req1); + if (raid) + { + req1->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; + if (mpi1) + setName(port, 0, port->raidPhysdisk, req1); + } + + if (mpi20) + { + memset(&req2, 0, sizeof req2); + + // convert from MPI 1.x format to MPI 2.x format + req2.Function = req1->Function; + req2.DevHandle = ((pMpi2SCSIIORequest_t)req1)->DevHandle; + req2.Control = req1->Control; + req2.IoFlags = set16(req1->CDBLength); + req2.DataLength = req1->DataLength; + + memcpy(req2.LUN, req1->LUN, sizeof req1->LUN); + memcpy(req2.CDB.CDB32, req1->CDB, sizeof req1->CDB); + + req2.SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; + + req = &req2; + reqSize = sizeof req2 - sizeof req2.SGL; + } + else if (mpi25) + { + memset(&req25, 0, sizeof req25); + + // convert from MPI 1.x format to MPI 2.5 format + req25.Function = req1->Function; + req25.DevHandle = ((pMpi25SCSIIORequest_t)req1)->DevHandle; + req25.Control = req1->Control; + req25.IoFlags = set16(req1->CDBLength); + req25.DataLength = req1->DataLength; + + memcpy(req25.LUN, req1->LUN, sizeof req1->LUN); + memcpy(req25.CDB.CDB32, req1->CDB, sizeof req1->CDB); + + req25.SGLOffset0 = offsetof(Mpi25SCSIIORequest_t, SGL) / 4; + + req = &req25; + reqSize = sizeof req25 - sizeof req25.SGL; + } + } + + if (mpi2) + { + rep = &rep2; + repSize = sizeof rep2; + } + else + { + rep = rep1; + repSize = rep1Size; + } + memset(rep, 0, repSize); + + if (doMptCommand(port, req, reqSize, rep, repSize, + payIn, payInSize, payOut, payOutSize, timeOut) != 1) + { +#if __linux__ + if (errno == EFAULT) + printf("SCSI command failed, mptscsih might not be loaded\n"); +#endif + return 0; + } + + if (mpi2) + { + memcpy(&rep1->reply, &rep2.reply, sizeof rep1->reply); + memcpy(&rep1->sense, &rep2.sense, sizeof rep1->sense); + } + + ioc_status = get16(rep1->reply.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status == MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE) + return 0; + + if (ioc_status == MPI_IOCSTATUS_BUSY || + ioc_status == MPI_IOCSTATUS_SCSI_IOC_TERMINATED || + ioc_status == MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH || + (rep1->reply.SCSIStatus == MPI_SCSI_STATUS_CHECK_CONDITION && !(rep1->sense[2] & 0xf0)) || + rep1->reply.SCSIStatus == MPI_SCSI_STATUS_BUSY || + rep1->reply.SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL) + { + memset(rep, 0, repSize); + + if (doMptCommand(port, req, reqSize, rep, repSize, + payIn, payInSize, payOut, payOutSize, timeOut) != 1) + return 0; + + if (mpi2) + { + memcpy(&rep1->reply, &rep2.reply, sizeof rep1->reply); + memcpy(&rep1->sense, &rep2.sense, sizeof rep1->sense); + } + + ioc_status = get16(rep1->reply.IOCStatus) & MPI_IOCSTATUS_MASK; + } + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + if (ioc_status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN || + ioc_status == MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH) + { + if (rep1->reply.SCSIStatus == MPI_SCSI_STATUS_SUCCESS) + { + if (rep1->reply.TransferCount == 0) + { +// printf("ScsiIo to Bus %d Target %d failed, IOCStatus = %04x (%s)\n", +// bus, target, ioc_status, translateIocStatus(ioc_status)); + return 0; + } + else + return 1; + } + } + else + { + if ((get16(rep1->reply.IOCStatus) & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) != 0) + { + ioc_loginfo = get32(rep1->reply.IOCLogInfo); + printf("ScsiIo to Bus %d Target %d failed, IOCStatus = %04x (%s), IOCLogInfo = %08x\n", + bus, target, ioc_status, translateIocStatus(ioc_status), ioc_loginfo); + } + else + printf("ScsiIo to Bus %d Target %d failed, IOCStatus = %04x (%s)\n", + bus, target, ioc_status, translateIocStatus(ioc_status)); + + return 0; + } + } + + if (rep1->reply.SCSIStatus != MPI_SCSI_STATUS_SUCCESS) + { + if (rep1->reply.SCSIStatus == MPI_SCSI_STATUS_CHECK_CONDITION) + { + if (rep1->sense[2] == 5 && rep1->sense[12] == 0x20 && rep1->sense[13] == 0x00) + if (payInSize == 36 || payInSize == 32) + return 0; + + if (rep1->sense[2] == 5 && rep1->sense[12] == 0x24 && rep1->sense[13] == 0x00) + if (payInSize == 36 || payInSize == 32 || (command == 0x3c && payInSize <= 4)) + return 0; + + if (rep1->sense[2] == 5 && rep1->sense[12] == 0x25 && rep1->sense[13] == 0x00) + if (payInSize == 36 || payInSize == 32 || (command == 0x3c && payInSize <= 4)) + return 0; + + if (rep1->sense[2] == 0 && rep1->sense[12] == 0x00 && rep1->sense[13] == 0x00) + return 0; + + if (rep1->sense[2] == 4 && rep1->sense[12] == 0x44 && rep1->sense[13] == 0x00) + return 0; + + if (rep1->sense[2] == 0x08) + return 0; + + if (rep1->sense[0] == 0xf0 && rep1->sense[2] & 0xf0) + return 0; + + if (rep1->sense[0] & 0x80) + printf("ScsiIo to Bus %d Target %d failed, Check Condition, Key = %d, ASC/ASCQ = %02Xh/%02Xh, Info = %08Xh (%d)\n", + bus, target, rep1->sense[2] & 0x0f, rep1->sense[12], rep1->sense[13], get4bytes(rep1->sense, 3), get4bytes(rep1->sense, 3)); + else + printf("ScsiIo to Bus %d Target %d failed, Check Condition, Key = %d, ASC/ASCQ = %02Xh/%02Xh\n", + bus, target, rep1->sense[2] & 0x0f, rep1->sense[12], rep1->sense[13]); + +// dumpMemory(rep1->sense, get32(rep1->reply.SenseCount), "Sense Data"); + } + else + { + printf("ScsiIo to Bus %d Target %d failed, SCSIStatus = %02x\n", + bus, target, rep1->reply.SCSIStatus); + } + return 0; + } + + return 1; +} + + +int +doReadLongSata(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int mode, unsigned char *buf, int len) +{ + SataPassthroughRequest_t req; + SataPassthroughReply_t rep; + unsigned char cmd[512]; + + memset(cmd, 0, sizeof cmd); + + cmd[0] = 1; + cmd[2] = 1; + cmd[4] = lbn; + cmd[5] = lbn >> 8; + cmd[6] = lbn >> 16; + cmd[7] = lbn >> 24; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SATA_PASSTHROUGH; + req.PassthroughFlags = set16(MPI_SATA_PT_REQ_PT_FLAGS_PIO | MPI_SATA_PT_REQ_PT_FLAGS_WRITE); + req.DataLength = set32(sizeof cmd); + req.CommandFIS[0] = 0x27; + req.CommandFIS[1] = 0x80; + req.CommandFIS[2] = 0xb0; + req.CommandFIS[3] = 0xd6; + req.CommandFIS[4] = 0xe0; + req.CommandFIS[5] = 0x4f; + req.CommandFIS[6] = 0xc2; + req.CommandFIS[12] = 0x01; + + setName(port, bus, target, &req); + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + NULL, 0, cmd, sizeof cmd, SHORT_TIME) != 1) + { + printf("SataPassThrough (SCT / Long Sector Read / E0) failed!\n"); + return 0; + } + + /* if the statusFIS error field has any bits set, then the request was not successful */ + if (rep.StatusFIS[3]) + { + printf("SataPassThrough (SCT / Long Sector Read / E0) failed!\n"); + return 0; + } +// printf("StatusFIS->Error: %02x\n", rep.StatusFIS[3]); +// printf("StatusFIS->Status: %02x\n", rep.StatusFIS[2]); + + req.PassthroughFlags = set16(MPI_SATA_PT_REQ_PT_FLAGS_PIO | MPI_SATA_PT_REQ_PT_FLAGS_READ); + req.DataLength = set32(len); + req.CommandFIS[3] = 0xd5; + req.CommandFIS[4] = 0xe1; + req.CommandFIS[12] = 0x02; + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + buf, len, NULL, 0, SHORT_TIME) != 1) + { + printf("SataPassThrough (SCT / Long Sector Read / E1) failed!\n"); + return 0; + } + + /* if the statusFIS error field has any bits set, then the request was not successful */ + if (rep.StatusFIS[3]) + { + printf("SataPassThrough (SCT / Long Sector Read / E1) failed!\n"); + return 0; + } +// printf("StatusFIS->Error: %02x\n", rep.StatusFIS[3]); +// printf("StatusFIS->Status: %02x\n", rep.StatusFIS[2]); + + return 1; +} + + +int +doWriteLongSata(MPT_PORT *port, int bus, int target, int lun, + unsigned int lbn, int mode, unsigned char *buf, int len) +{ + SataPassthroughRequest_t req; + SataPassthroughReply_t rep; + unsigned char cmd[512]; + + memset(cmd, 0, sizeof cmd); + + cmd[0] = 1; + cmd[2] = 2; + cmd[4] = lbn; + cmd[5] = lbn >> 8; + cmd[6] = lbn >> 16; + cmd[7] = lbn >> 24; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SATA_PASSTHROUGH; + req.PassthroughFlags = set16(MPI_SATA_PT_REQ_PT_FLAGS_PIO | MPI_SATA_PT_REQ_PT_FLAGS_WRITE); + req.DataLength = set32(sizeof cmd); + req.CommandFIS[0] = 0x27; + req.CommandFIS[1] = 0x80; + req.CommandFIS[2] = 0xb0; + req.CommandFIS[3] = 0xd6; + req.CommandFIS[4] = 0xe0; + req.CommandFIS[5] = 0x4f; + req.CommandFIS[6] = 0xc2; + req.CommandFIS[12] = 0x01; + + setName(port, bus, target, &req); + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + NULL, 0, cmd, sizeof cmd, SHORT_TIME) != 1) + { + printf("SataPassThrough (SCT / Long Sector Write / E0) failed!\n"); + return 0; + } + + /* if the statusFIS error field has any bits set, then the request was not successful */ + if (rep.StatusFIS[3]) + { + printf("SataPassThrough (SCT / Long Sector Write / E0) failed!\n"); + return 0; + } +// printf("StatusFIS->Error: %02x\n", rep.StatusFIS[3]); +// printf("StatusFIS->Status: %02x\n", rep.StatusFIS[2]); + + req.PassthroughFlags = set16(MPI_SATA_PT_REQ_PT_FLAGS_PIO | MPI_SATA_PT_REQ_PT_FLAGS_WRITE); + req.DataLength = set32(len); + req.CommandFIS[3] = 0xd6; + req.CommandFIS[4] = 0xe1; + req.CommandFIS[12] = 0x02; + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + NULL, 0, buf, len, SHORT_TIME) != 1) + { + printf("SataPassThrough (SCT / Long Sector Write / E1) failed!\n"); + return 0; + } + + /* if the statusFIS error field has any bits set, then the request was not successful */ + if (rep.StatusFIS[3]) + { + printf("SataPassThrough (SCT / Long Sector Write / E1) failed!\n"); + return 0; + } +// printf("StatusFIS->Error: %02x\n", rep.StatusFIS[3]); +// printf("StatusFIS->Status: %02x\n", rep.StatusFIS[2]); + + return 1; +} + + +int +doFwDownload(MPT_PORT *port, int type, unsigned char *buf, int len, int offset) +{ + FWDownload_t *req1; // the MPI 1.x request is a subset of the MPI 2.x request + Mpi2FWDownloadRequest req; + Mpi25FWDownloadRequest req25; + FWDownloadReply_t rep; + FWDownloadTCSGE_t *tc; + int req_size; + int size; + int ioc_status; + int inLen = len; + int mpt_return = 0; + + memset(&req, 0, sizeof req); + memset(&req25, 0, sizeof req25); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_FW_DOWNLOAD; + req25.Function = MPI2_FUNCTION_FW_DOWNLOAD; + req.ImageType = type; + req25.ImageType = type; + + if (mpi20) + { + tc = (pFWDownloadTCSGE_t)&req.SGL; + req_size = sizeof req - sizeof req.SGL + sizeof *tc; + + req.TotalImageSize = set32(len); + } + else if (mpi25) + { + req_size = sizeof req25 - sizeof req25.SGL; + req25.TotalImageSize = set32(len); + } + else + { + req1 = (pFWDownload_t)&req; + + tc = (pFWDownloadTCSGE_t)&req1->SGL; + req_size = sizeof *req1 - sizeof req1->SGL + sizeof *tc; + } + + if(port->mptVersion < MPI2_VERSION_02_05) + { + tc->ContextSize = 0; + tc->DetailsLength = 12; + tc->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT; + } + + if (port->mptVersion < MPI_VERSION_01_01 && type == MPI_FW_DOWNLOAD_ITYPE_BIOS) + { + int i; + U32 data_l; + U32 data_h; + U32 *p_data_l; + U32 *p_data_h; + + p_data_l = (U32 *)&buf[0]; + p_data_h = (U32 *)&buf[len] - 1; + + for (i = 0; i < len / 8; i++) + { + data_l = *p_data_l; + data_h = *p_data_h; + *p_data_l++ = data_h; + *p_data_h-- = data_l; + } + + offset += 0x100000; + buf += len; + } + + printf("\nDownloading image...\n"); + + while (len > 0) + { + if (port->mptVersion < MPI_VERSION_01_01) + { + int i; + U32 checksum; + + size = min(len, 0x10000); + + if (type == MPI_FW_DOWNLOAD_ITYPE_BIOS) + { + offset -= size; + buf -= size; + } + + checksum = 0; + for (i = 0; i < size / 4; i++) + checksum -= get32x(((U32 *)buf)[i]); + + tc->Reserved_0100_Checksum = set32(checksum); + } + else + { + size = min(len, CHUNK_SIZE); + if (size == len) + { + req.MsgFlags = MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT; + req25.MsgFlags = MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT; + } + } + + if ( port->mptVersion >= MPI2_VERSION_02_05 ) + { + req25.ImageSize = set32(size); + req25.ImageOffset = set32(offset); + mpt_return = doMptCommand(port, &req25, req_size, &rep, sizeof rep, + NULL, 0, buf, size, LONG_TIME); + } + else + { + tc->ImageSize = set32(size); + tc->ImageOffset = set32(offset); + mpt_return = doMptCommand(port, &req, req_size, &rep, sizeof rep, + NULL, 0, buf, size, LONG_TIME); + } + + if ( mpt_return != 1 ) + { + printf("Download failed\n"); + if (wFlag) + fprintf(logFile, "%s: Firmware Download (FW_DOWNLOAD) of type %d: FAIL\n", + logPrefix(port), type); + return 0; + } + + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + printf("Download failed, IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); + if (wFlag) + fprintf(logFile, "%s: Firmware Download (FW_DOWNLOAD) of type %d: FAIL\n", + logPrefix(port), type); + return 0; + } + + len -= size; + + if (!(port->mptVersion < MPI_VERSION_01_01 && type == MPI_FW_DOWNLOAD_ITYPE_BIOS)) + { + buf += size; + offset += size; + } + } //while(len>0) + + printf("Download succeeded\n"); + + if (wFlag) + fprintf(logFile, "%s: Firmware Download (FW_DOWNLOAD) of type %d size %x: PASS\n", + logPrefix(port), type, inLen); + return 1; +} + + +int +doFwUpload(MPT_PORT *port, int type, unsigned char *buf, int len, int offset, int *outLen) +{ + FWUpload_t *req1; + Mpi2FWUploadRequest_t req; + Mpi25FWUploadRequest_t req25; + FWUploadReply_t rep; + FWUploadTCSGE_t *tc; + int req_size; + int size; + int actual_size; + int ioc_status; + int mpt_return = 0; + + memset(&req, 0, sizeof req); + memset(&req25, 0, sizeof req25); + memset(&rep, 0, sizeof rep); + + req.Function = req25.Function = MPI_FUNCTION_FW_UPLOAD; + req.ImageType = req25.ImageType = type; + + if (mpi20) + { + tc = (pFWUploadTCSGE_t)&req.SGL; + req_size = sizeof req - sizeof req.SGL + sizeof *tc; + } + else if (mpi25) + { + req_size = sizeof(req25) - sizeof(req25.SGL); + } + else + { + req1 = (pFWUpload_t)&req; + tc = (pFWUploadTCSGE_t)&req1->SGL; + req_size = sizeof *req1 - sizeof req1->SGL + sizeof *tc; + } + + if(port->mptVersion < MPI2_VERSION_02_05) + { + tc->ContextSize = 0; + tc->DetailsLength = 12; + tc->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT; + } + + actual_size = 0; + while (len > 0) + { + size = min(len, CHUNK_SIZE); + + if (mpi25) + { + req25.ImageSize = set32(size); + req25.ImageOffset = set32(offset); + mpt_return = doMptCommand(port, &req25, req_size, &rep, sizeof rep, + buf, size, NULL, 0, LONG_TIME); + } + else + { + tc->ImageSize = set32(size); + tc->ImageOffset = set32(offset); + mpt_return = doMptCommand(port, &req, req_size, &rep, sizeof rep, + buf, size, NULL, 0, LONG_TIME); + } + + if (mpt_return != 1) + { + printf("Upload failed\n"); + if (wFlag) + fprintf(logFile, "%s: Firmware Upload (FW_UPLOAD) of type %d: FAIL\n", + logPrefix(port), type); + return 0; + } + + ioc_status = get16(rep.IOCStatus) & MPI_IOCSTATUS_MASK; + actual_size = get32(rep.ActualImageSize); + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + if (ioc_status == MPI_IOCSTATUS_INVALID_FIELD && actual_size != 0) + { + if (offset + size > actual_size) + { + len = actual_size - offset; + continue; + } + } + + printf("Upload failed, IOCStatus = %04x (%s)\n", ioc_status, translateIocStatus(ioc_status)); + if (wFlag) + fprintf(logFile, "%s: Firmware Upload (FW_UPLOAD) of type %d: FAIL\n", + logPrefix(port), type); + return 0; + } + + buf += size; + len -= size; + offset += size; + } + + *outLen = actual_size; + + if (wFlag) + fprintf(logFile, "%s: Firmware Upload (FW_UPLOAD) of type %d size %x: PASS\n", + logPrefix(port), type, *outLen); + return 1; +} + + +int +doIocInit(MPT_PORT *port, int WhoInit) +{ + IOCInit_t req; + IOCInitReply_t rep; + IOCFactsReply_t IOCFacts; + + if (mpi2) + return 1; + + if (getIocFacts(port, &IOCFacts) != 1) + return 0; + + if (IOCFacts.WhoInit == WhoInit) + return 1; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_IOC_INIT; + req.WhoInit = WhoInit; + req.Flags = 0; + req.MaxDevices = IOCFacts.MaxDevices; + req.MaxBuses = IOCFacts.MaxBuses; + req.ReplyFrameSize = IOCFacts.CurReplyFrameSize; + req.HostMfaHighAddr = IOCFacts.CurrentHostMfaHighAddr; + req.SenseBufferHighAddr = IOCFacts.CurrentSenseBufferHighAddr; + req.ReplyFifoHostSignalingAddr = IOCFacts.ReplyFifoHostSignalingAddr; + req.HostPageBufferSGE = IOCFacts.HostPageBufferSGE; + req.MsgVersion = set16(MPI_VERSION_01_05); + req.HeaderVersion = set16(MPI_HEADER_VERSION); + + if (IOCFacts.Flags & MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL) + req.Flags |= MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL; + +#if __linux__ + if (oldMptBaseDetected) + { + // make the Linux IOCTL driver a bit happier + if (req.MaxDevices > port->maxTargets) + req.MaxDevices = port->maxTargets; + if (req.MaxDevices == 0) + req.MaxDevices = 255; + } + if (newMptBaseDetected) + { + // make the Linux IOCTL driver a bit happier + req.MaxDevices = 0; + req.MaxBuses = 0; + } +#endif + + return doMptCommandCheck(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); +} + + +char * +translateSmpFunctionResult(int functionResult) +{ + switch (functionResult) + { + case SMP_RESPONSE_FUNCTION_RESULT_ACCEPTED: return "Function Accepted"; + case SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_SMP_FUNCTION: return "Unknown Function"; + case SMP_RESPONSE_FUNCTION_RESULT_SMP_FUNCTION_FAILED: return "Function Failed"; + case SMP_RESPONSE_FUNCTION_RESULT_INVALID_REQUEST_LENGTH: return "Invalid Request Length"; + case SMP_RESPONSE_FUNCTION_RESULT_INVALID_EXP_CHANGE_COUNT: return "Invalid Expander Change Count"; + case SMP_RESPONSE_FUNCTION_RESULT_BUSY: return "Busy"; + case SMP_RESPONSE_FUNCTION_RESULT_INCOMPLETE_DESCRIPTOR_LIST: return "Incomplete Descriptor List"; + case SMP_RESPONSE_FUNCTION_RESULT_PHY_DOES_NOT_EXIST: return "Phy Does Not Exist"; + case SMP_RESPONSE_FUNCTION_RESULT_INDEX_DOES_NOT_EXIST: return "Index Does Not Exist"; + case SMP_RESPONSE_FUNCTION_RESULT_PHY_DOES_NOT_SUPPORT_SATA: return "Phy Does Not Support SATA"; + case SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_PHY_OPERATION: return "Unknown Phy Operation"; + case SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_PHY_TEST_FUNCTION: return "Unknown Phy Test Function"; + case SMP_RESPONSE_FUNCTION_RESULT_PHY_TEST_FUNCTION_IN_PROG: return "Phy Test Function In Progress"; + case SMP_RESPONSE_FUNCTION_RESULT_PHY_VACANT: return "Phy Vacant (No Access)"; + case SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_PHY_EVENT_SOURCE: return "Unknown Phy Event Source"; + case SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_DESCRIPTOR_TYPE: return "Unknown Descriptor Type"; + case SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_PHY_FILTER: return "Unknown Phy Filter"; + case SMP_RESPONSE_FUNCTION_RESULT_AFFILIATION_VIOLATION: return "Affiliation Violation"; + case SMP_RESPONSE_FUNCTION_RESULT_SMP_ZONE_VIOLATION: return "Zone Violation"; + case SMP_RESPONSE_FUNCTION_RESULT_NO_MANAGEMENT_ACCESS_RIGHTS: return "No Management Access Rights"; + case SMP_RESPONSE_FUNCTION_RESULT_UNKNOWN_ENABLE_DISABLE_ZONING_VALUE: return "Unknown Enable Disable Zoning Value"; + case SMP_RESPONSE_FUNCTION_RESULT_ZONE_LOCK_VIOLATION: return "Zone Lock Violation"; + case SMP_RESPONSE_FUNCTION_RESULT_NOT_ACTIVATED: return "Not Activated"; + case SMP_RESPONSE_FUNCTION_RESULT_ZONE_GROUP_OUT_OF_RANGE: return "Zone Group Out Of Range"; + case SMP_RESPONSE_FUNCTION_RESULT_NO_PHYSICAL_PRESENCE: return "No Physical Presence"; + case SMP_RESPONSE_FUNCTION_RESULT_SAVING_NOT_SUPPORTED: return "Saving Not Supported"; + case SMP_RESPONSE_FUNCTION_RESULT_SOURCE_ZONE_GROUP_DOES_NOT_EXIST: return "Source Zone Group Does Not Exist"; + case SMP_RESPONSE_FUNCTION_RESULT_DISABLED_PASSWORD_NOT_SUPPORTED: return "Disabled Password Not Supported"; + } + + return ""; +} + + +int +doSmpReportMfg(MPT_PORT *port, _U64 SASAddress, U8 physicalPort, PTR_SMP_REPORT_MANUFACTURER_INFO_RESPONSE smpResp, int *respDataLength) +{ + SMP_REPORT_MANUFACTURER_INFO_REQUEST smpReq; + int len; + + memset((PTR_SMP_REQUEST_UNION)&smpReq, 0, sizeof smpReq); + + smpReq.SMPFrameType = SMP_FRAME_TYPE_SMP_REQUEST; + smpReq.Function = SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION; + smpReq.ResponseLength = ALLOCATED_RESP_LEN; + smpReq.RequestLength = 0; + + if (doSmpPassthrough(port, physicalPort, SASAddress, + (void *)&smpReq, sizeof smpReq, (void *)smpResp, sizeof *smpResp, &len) == 1) + { + if (respDataLength) + { + *respDataLength = len; + } + + return 1; + } + + return 0; +} + + +int +doSmpPassthrough(MPT_PORT *port, U8 smpPort, _U64 smpAddr, void *smpReq, int smpReqSize, void *smpRsp, int smpRspSize, int *respDataLen) +{ + SmpPassthroughRequest_t req; + SmpPassthroughReply_t rep; + + memset(&req, 0, sizeof req); + memset(&rep, 0, sizeof rep); + + req.Function = MPI_FUNCTION_SMP_PASSTHROUGH; + req.PhysicalPort = smpPort; + req.RequestDataLength = set16(smpReqSize); + req.SASAddress = smpAddr; + + memset(smpRsp, 0, smpRspSize); + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + smpRsp, smpRspSize, smpReq, smpReqSize, SHORT_TIME) == 1) + { + if (respDataLen) + { + *respDataLen = get16(rep.ResponseDataLength) + 4; + } + return 1; + } + else + return 0; +} + + +int +doResetPort(MPT_PORT *port) +{ + int t; +#if WIN32 + int status; + MPI_DIAG_RESET_SRB srb; + int inLen; + int outLen; + DWORD retLen; + + memset(&srb, 0, sizeof srb); + + srb.Sic.Length = sizeof srb - sizeof srb.Sic; + srb.Sic.ControlCode = MPI_DIAG_RESET; + srb.Sic.HeaderLength = sizeof srb.Sic; + srb.Sic.Timeout = RESET_TIME; + + memcpy((char *)&srb.Sic.Signature, "v93Ap6Q4", 8); + + inLen = sizeof srb; + outLen = sizeof srb; + retLen = 0; + + printf("Resetting port...\n"); + + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + &srb, inLen, &srb, outLen, &retLen, NULL); + + t = status; +#endif +#if __linux__ || __alpha__ + int status; + struct mpt_ioctl_diag_reset diag_reset; + + memset(&diag_reset, 0, sizeof diag_reset); + + diag_reset.hdr.iocnum = port->portNumber; + + printf("Resetting port...\n"); + + if (mpi2) + status = ioctl(port->fileHandle, MPT2HARDRESET, &diag_reset); + else + status = ioctl(port->fileHandle, MPTHARDRESET, &diag_reset); + + t = status == 0; +#endif +#if __sparc__ || __irix__ + int status; +#if __irix__ + struct scsi_ha_op scsiioctl; +#endif + + printf("Resetting port...\n"); + +#if __sparc__ + if (mpi2) + status = ioctl(port->fileHandle, MPTIOCTL_RESET_ADAPTER); + else + status = ioctl(port->fileHandle, SYMIOCTL_RESET_ADAPTER); +#endif +#if __irix__ + scsiioctl.sb_opt = SYMIOCTL_RESET_ADAPTER; + status = ioctl(port->fileHandle, SOP_GETDATA, &scsiioctl); +#endif + + t = status == 0; +#endif +#if DOS || EFI + printf("Resetting port...\n"); + + port->fileHandle->restart_needed = TRUE; + port->fileHandle->port_enable_needed = FALSE; + + port->fileHandle->ioc_online = mpt_restart(port->fileHandle); + + t = port->fileHandle->ioc_online; +#endif + + if (wFlag) + fprintf(logFile, "%s: Reset Adapter: %s\n", + logPrefix(port), t ? "PASS" : "FAIL"); + + if (t != 1) + printf("Failed to reset port!\n"); + + return t; +} + + +void +doLogMptCommandReq(MPT_PORT *port, void *req, int reqSize) +{ + int i; + + fprintf(logFile, "%s: MPT Req: ", logPrefix(port)); + for (i = 0; i < reqSize / 4; i++) + fprintf(logFile, " %08x", get32x(((U32 *)req)[i])); + fprintf(logFile, "\n"); +} + + +void +doLogMptCommandRep(MPT_PORT *port, void *rep, int repSize, int status) +{ + int i; + MPIDefaultReply_t *defaultRep; + + fprintf(logFile, "%s: MPT Rep: ", logPrefix(port)); + if (status == 1) + { + defaultRep = (pMPIDefaultReply_t)rep; + for (i = 0; i < defaultRep->MsgLength; i++) + fprintf(logFile, " %08x", get32x(((U32 *)rep)[i])); + if (defaultRep->Function == MPI_FUNCTION_SCSI_IO_REQUEST || + defaultRep->Function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || + defaultRep->Function == MPI_FUNCTION_SCSI_IO_32) + { + if (defaultRep->MsgLength == 0) + fprintf(logFile, " "); + if (mpi2) + { + SCSI_REPLY2 *scsiRep = (SCSI_REPLY2 *)rep; + + if (scsiRep->reply.SCSIStatus == MPI_SCSI_STATUS_CHECK_CONDITION) + { + fprintf(logFile, "\n%s: Sense Data: ", logPrefix(port)); + for (i = 0; i < (int)get32(scsiRep->reply.SenseCount); i++) + fprintf(logFile, " %02x", scsiRep->sense[i]); + } + } + else + { + SCSI_REPLY *scsiRep = (SCSI_REPLY *)rep; + + if (scsiRep->reply.SCSIStatus == MPI_SCSI_STATUS_CHECK_CONDITION) + { + fprintf(logFile, "\n%s: Sense Data: ", logPrefix(port)); + for (i = 0; i < (int)get32(scsiRep->reply.SenseCount); i++) + fprintf(logFile, " %02x", scsiRep->sense[i]); + } + } + } + } + else + { + fprintf(logFile, " "); + } + fprintf(logFile, "\n"); +} + + +void +logMptCommandReq(MPT_PORT *port, void *req, int reqSize) +{ + if (wFlag >= 3) + { + doLogMptCommandReq(port, req, reqSize); + } +} + + +void +logMptCommandRep(MPT_PORT *port, void *req, int reqSize, void *rep, int repSize, int status) +{ +#if DOS || EFI + MPIHeader_t *reqL = (pMPIHeader_t)req; +#endif + MPIDefaultReply_t *repL = (pMPIDefaultReply_t)rep; + int ioc_status = get16(repL->IOCStatus) & MPI_IOCSTATUS_MASK; + +#if DOS || EFI + if (req && reqSize && reqL->Function == repL->Function && repL->MsgLength != 0) + { + status = 1; // reply is initially zeroed, so if we get here we can trust it + } +#endif + + if (wFlag >= 3) + { + doLogMptCommandRep(port, rep, repSize, status); + } + else if (wFlag >= 2 && (status == 0 || ioc_status != MPI_IOCSTATUS_SUCCESS)) + { + if (req && reqSize) + { + doLogMptCommandReq(port, req, reqSize); + } + doLogMptCommandRep(port, rep, repSize, status); + } +} + + +int +doMptCommand(MPT_PORT *port, void *req, int reqSize, void *rep, int repSize, + void *payIn, int payInSize, void *payOut, int payOutSize, int timeOut) +{ +#if WIN32 + int cmd; + int status; + SRB_BUFFER srb_buffer; + SRB_BUFFER *srb; + int inLen; + int outLen; + DWORD retLen; + int size; + int retry; + int function = ((pMPIHeader_t)req)->Function; + + /* + * Add 8 for IoctlDetails, 128 for maximum request and reply, + * and 256 for maximum sense data (for SCSI I/O requests). + */ + size = 8 + 128 + 256 + max(payInSize, payOutSize); + if (size > sizeof srb->Buf) + srb = malloc(sizeof srb->Sic + size); + else + srb = &srb_buffer; + + memset(srb, 0, sizeof srb->Sic + size); + + srb->Sic.Length = size; + srb->Sic.ControlCode = MPI_MSG_IOCTL; + srb->Sic.HeaderLength = sizeof srb->Sic; + srb->Sic.Timeout = timeOut; + + memcpy((char *)&srb->Sic.Signature, "4.00 ", 8); + + if (payInSize != 0 && payOutSize != 0) + cmd = DUAL_SGLS; // data in and data out + else if (payInSize != 0) + cmd = 0; // data in + else if (payOutSize != 0) + cmd = DATA_FROM_APP; // data out + else + cmd = 0; // no data transfer, just say Read + + if (function == MPI_FUNCTION_SCSI_IO_REQUEST || + function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || + function == MPI_FUNCTION_SCSI_IO_32) + { + if (function == MPI_FUNCTION_SCSI_IO_REQUEST || + function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) + cmd |= SCSI_IO; // flag SCSI I/O, potentially get sense data + ((pMPIHeader_t)req)->MsgContext = 0; + } + + *(PUSHORT)&srb->Buf[0] = cmd; + *(PUSHORT)&srb->Buf[2] = reqSize / 4; + if (cmd & DATA_FROM_APP) + *(PULONG)&srb->Buf[4] = payOutSize; + else + *(PULONG)&srb->Buf[4] = payInSize; + + if (cmd & DUAL_SGLS) + { + if (payInSize > 0xffff || payOutSize > 0xffff) + { + printf("Payload sizes too large, max is 64 KB!\n"); + return 0; + } + *(PUSHORT)&srb->Buf[4] = payInSize; + *(PUSHORT)&srb->Buf[6] = payOutSize; + } + + memcpy(&srb->Buf[8], req, reqSize); + if (payOutSize != 0) + memcpy(&srb->Buf[8+reqSize], payOut, payOutSize); + + inLen = sizeof srb->Sic + size; + outLen = sizeof srb->Sic + size; + retLen = 0; + + logMptCommandReq(port, req, reqSize); + + for (retry = 0; retry < 10; retry++) + { + status = DeviceIoControl(port->fileHandle, port->ioctlValue, + srb, inLen, srb, outLen, &retLen, NULL); + + if (status == 1) + { + gRetDataLen = retLen - sizeof(SRB_IO_CONTROL) - port->payOff; + + memcpy(rep, &srb->Buf[0], repSize); + if (payInSize != 0) + memcpy(payIn, &srb->Buf[port->payOff], payInSize); + + if (function == MPI_FUNCTION_SCSI_IO_REQUEST || + function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || + function == MPI_FUNCTION_SCSI_IO_32) + { + if (mpi2) + { + Mpi2SCSIIOReply_t *scsiRep = (pMpi2SCSIIOReply_t)rep; + + if (scsiRep->MsgLength == 0) + memset(rep, 0, repSize); + + /* copy the sense data to where it is expected to be */ + memcpy(scsiRep + 1, &srb->Buf[port->payOff + payInSize], repSize - sizeof *scsiRep); + } + else + { + SCSIIOReply_t *scsiRep = (pSCSIIOReply_t)rep; + + if (scsiRep->MsgLength == 0) + memset(rep, 0, repSize); + + /* copy the sense data to where it is expected to be */ + memcpy(scsiRep + 1, &srb->Buf[port->payOff + payInSize], repSize - sizeof *scsiRep); + } + } + + break; + } + + if (GetLastError() == ERROR_BUSY) + { + sleep(1); + } + else + { + printf("IOCTL to %s failed due to error %ld\n", port->portName, GetLastError()); + break; + } + } + if (status != 1 && retry == 10) + printf("IOCTL to %s failed due to ERROR_BUSY %d times\n", port->portName, retry); + + logMptCommandRep(port, req, reqSize, rep, repSize, status); + + if (size > sizeof srb->Buf) + free(srb); + + return status; +#endif +#if __linux__ || __alpha__ + int status; + int extra; + struct mpt_ioctl_command *command; + int retry; + int function = ((pMPIHeader_t)req)->Function; + + extra = max(0, reqSize - sizeof command->MF); + command = (struct mpt_ioctl_command *)malloc(sizeof *command + extra); + + memset(command, 0, sizeof *command); + + command->hdr.iocnum = port->portNumber; + + command->timeout = timeOut; + command->replyFrameBufPtr = rep; + command->dataInBufPtr = payIn; + command->dataOutBufPtr = payOut; + command->maxReplyBytes = repSize; + command->dataInSize = payInSize; + command->dataOutSize = payOutSize; + command->dataSgeOffset = reqSize / 4; + + if (function == MPI_FUNCTION_SCSI_IO_REQUEST || + function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || + function == MPI_FUNCTION_SCSI_IO_32) + { + if (mpi2) + { + Mpi2SCSIIOReply_t *scsiRep = (pMpi2SCSIIOReply_t)rep; + + command->senseDataPtr = (char *)(scsiRep + 1); + command->maxSenseBytes = repSize - sizeof *scsiRep; + command->maxReplyBytes = sizeof *scsiRep; + } + else + { + SCSIIOReply_t *scsiRep = (pSCSIIOReply_t)rep; + + command->senseDataPtr = (char *)(scsiRep + 1); + command->maxSenseBytes = repSize - sizeof *scsiRep; + command->maxReplyBytes = sizeof *scsiRep; + } + } + + memcpy(command->MF, req, reqSize); + + logMptCommandReq(port, req, reqSize); + + for (retry = 0; retry < 10; retry++) + { + errno = 0; + + if (mpi2) + status = ioctl(port->fileHandle, MPT2COMMAND, command); + else + status = ioctl(port->fileHandle, MPTCOMMAND, command); + + if (status != 0 && errno == EAGAIN) + { + sleep(1); + } + else + { + break; + } + } + + logMptCommandRep(port, req, reqSize, rep, repSize, status == 0); + +#if __linux__ + if (status != 0) + { + if (errno == EFAULT) + { + if (((pMPIHeader_t)req)->Function == MPI_FUNCTION_IOC_INIT) + { + IOCInit_t *iocinitReq = (pIOCInit_t)req; + int maxDevices; + + free(command); + + if (workaroundsTried == TRUE) + return 0; + + workaroundsTried = TRUE; + + // try to make the Linux IOCTL driver a bit happier + + maxDevices = iocinitReq->MaxDevices; + if (iocinitReq->MaxDevices > port->maxTargets) + iocinitReq->MaxDevices = port->maxTargets; + if (iocinitReq->MaxDevices == 0) + iocinitReq->MaxDevices = 255; + if (iocinitReq->MaxDevices != maxDevices) + { + status = doMptCommand(port, req, reqSize, rep, repSize, + payIn, payInSize, payOut, payOutSize, timeOut); + + if (status == 1) + { + oldMptBaseDetected = 1; + return 1; + } + } + + if (iocinitReq->MaxDevices != 0 || iocinitReq->MaxBuses != 0) + { + iocinitReq->MaxDevices = 0; + iocinitReq->MaxBuses = 0; + + status = doMptCommand(port, req, reqSize, rep, repSize, + payIn, payInSize, payOut, payOutSize, timeOut); + + if (status == 1) + { + newMptBaseDetected = 1; + return 1; + } + } + + return 0; + } + + if (((pMPIHeader_t)req)->Function != MPI_FUNCTION_SCSI_IO_REQUEST) + { + printf("Command rejected by mptctl!\n"); + } + } + } +#endif + + free(command); + + return status == 0; +#endif +#if __sparc__ || __irix__ + int status; +#if __sparc__ + SYM_PASS_THRU_TIMEOUT passThru; +#endif +#if __irix__ + struct scsi_ha_op scsiioctl; + SYM_PASS_THRU passThru; +#endif + + passThru.PtrRequest = (UINT64)(UINT32)req; + passThru.RequestSize = reqSize; + passThru.PtrReply = (UINT64)(UINT32)rep; + passThru.ReplySize = repSize; + if (payInSize != 0 && payOutSize != 0) + { + passThru.PtrData = (UINT64)(UINT32)payIn; + passThru.DataSize = payInSize; + passThru.PtrDataOut = (UINT64)(UINT32)payOut; + passThru.DataOutSize = payOutSize; + passThru.DataDirection = SYM_PASS_THRU_BOTH; + } + else if (payInSize != 0) + { + passThru.PtrData = (UINT64)(UINT32)payIn; + passThru.DataSize = payInSize; + passThru.DataDirection = SYM_PASS_THRU_READ; + } + else if (payOutSize != 0) + { + passThru.PtrData = (UINT64)(UINT32)payOut; + passThru.DataSize = payOutSize; + passThru.DataDirection = SYM_PASS_THRU_WRITE; + } + else + { + passThru.PtrData = (UINT64)(UINT32)NULL; + passThru.DataSize = 0; + passThru.PtrDataOut = (UINT64)(UINT32)NULL; + passThru.DataOutSize = 0; + passThru.DataDirection = SYM_PASS_THRU_NONE; + } +#if __sparc__ + passThru.Timeout = timeOut; +#endif + + logMptCommandReq(port, req, reqSize); + +#if __sparc__ + status = ioctl(port->fileHandle, port->ioctlValue, &passThru); + if (port->ioctlValue == SYMIOCTL_PASS_THRU_TIMEOUT && status != 0) + { + port->ioctlValue = SYMIOCTL_PASS_THRU; + status = ioctl(port->fileHandle, port->ioctlValue, &passThru); + } +#endif +#if __irix__ + scsiioctl.sb_opt = SYMIOCTL_PASS_THRU; + scsiioctl.sb_addr = (uintptr_t)&passThru; + status = ioctl(port->fileHandle, SOP_GETDATA, &scsiioctl); +#endif + + logMptCommandRep(port, req, reqSize, rep, repSize, status == 0); + + return status == 0; +#endif +#if DOS || EFI + HANDLE adap = port->fileHandle; + SGESimple64_t *sgeSimple = (pSGESimple64_t)((U8 *)req + reqSize); + U8 function = ((pMPIHeader_t)req)->Function; + int handshake_okay; + int no_port_enable_okay; + int ioc_status; + int t; + U8 ieee_sgl; + Mpi2IeeeSgeSimple64_t *sgeIeeeSimple = (pMpi2IeeeSgeSimple64_t)((U8 *)req + reqSize); + + if (adap->restart_needed == TRUE) + { + mpt_stop(adap, TRUE); + } + + if (adap->ioc_online == TRUE) + { + adap->ioc_online = mpt_verify_operational(adap); + } + + handshake_okay = + function == MPI_FUNCTION_IOC_INIT || + function == MPI_FUNCTION_IOC_FACTS || + function == MPI_FUNCTION_PORT_FACTS || + function == MPI_FUNCTION_CONFIG || + ((function == MPI_FUNCTION_TOOLBOX || + function == MPI_FUNCTION_FW_DOWNLOAD) && adap->bootloader) || + (function == MPI_FUNCTION_FW_UPLOAD && (port->flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)); + + ieee_sgl = ((mpi25) && + (function == MPI2_FUNCTION_SCSI_IO_REQUEST || + function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || + function == MPI2_FUNCTION_SMP_PASSTHROUGH || + function == MPI2_FUNCTION_SATA_PASSTHROUGH || + function == MPI2_FUNCTION_FW_UPLOAD || + function == MPI2_FUNCTION_FW_DOWNLOAD || + function == MPI2_FUNCTION_TARGET_ASSIST || + function == MPI2_FUNCTION_TARGET_STATUS_SEND || + ((function == MPI2_FUNCTION_TOOLBOX) && (((pMPI2RequestHeader_t)req)->FunctionDependent1 == MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL)) + )); + + no_port_enable_okay = handshake_okay || + function == MPI_FUNCTION_TOOLBOX || + function == MPI_FUNCTION_FW_DOWNLOAD || + function == MPI_FUNCTION_FW_UPLOAD; + + if (adap->ioc_online == FALSE && !handshake_okay) + { + adap->port_enable_needed = !no_port_enable_okay; + + adap->ioc_online = mpt_restart(adap); + + if (adap->ioc_online == FALSE && + (adap->bootloader == TRUE || adap->loaddevice == TRUE)) + { + printf("MPT Function %02x not supported!\n", function); + errno = EFAULT; + return 0; + } + } + + if (adap->ioc_online == TRUE && adap->port_online == FALSE && !no_port_enable_okay) + { + adap->port_online = mpt_port_online(adap); + } + + if (payOut && payOutSize) + { + if (payOutSize > sizeof adap->shared->scratch) + { + printf("payOutSize (%x) too big!\n", payOutSize); + return 0; + } + + if (ieee_sgl) + { + sgeIeeeSimple->Flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | + MPI25_IEEE_SGE_FLAGS_END_OF_LIST | + MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; + sgeIeeeSimple->Length = set32(payOutSize); + sgeIeeeSimple->Address.Low = set32((U32)adap->shared_ba + offsetof(mpt_shared_t, scratch)); +#if DOS + sgeIeeeSimple->Address.High = 0; +#else + sgeIeeeSimple->Address.High = set32((U32)(adap->shared_ba >> 32)); +#endif + sgeIeeeSimple++; + reqSize += sizeof(Mpi2IeeeSgeSimple64_t); + } + else + { + sgeSimple->FlagsLength = set32(payOutSize | + MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_LAST_ELEMENT | + MPI_SGE_FLAGS_64_BIT_ADDRESSING | + MPI_SGE_FLAGS_HOST_TO_IOC | + MPI_SGE_FLAGS_END_OF_BUFFER | + MPI_SGE_FLAGS_END_OF_LIST)); + sgeSimple->Address.Low = set32((U32)adap->shared_ba + offsetof(mpt_shared_t, scratch)); +#if DOS + sgeSimple->Address.High = 0; +#else + sgeSimple->Address.High = set32((U32)(adap->shared_ba >> 32)); +#endif + sgeSimple++; + + reqSize += sizeof(SGESimple64_t); + + } + bcopy(payOut, adap->shared->scratch, payOutSize); + } + + if (payIn && payInSize) + { + if (payInSize > sizeof adap->shared->scratch) + { + printf("payInSize (%x) too big!\n", payInSize); + return 0; + } + if (ieee_sgl) + { + sgeIeeeSimple->Flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | + MPI25_IEEE_SGE_FLAGS_END_OF_LIST | + MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; + sgeIeeeSimple->Length = set32(payInSize); + sgeIeeeSimple->Address.Low = set32((U32)adap->shared_ba + offsetof(mpt_shared_t, scratch)); +#if DOS + sgeIeeeSimple->Address.High = 0; +#else + sgeIeeeSimple->Address.High = set32((U32)(adap->shared_ba >> 32)); +#endif + sgeIeeeSimple++; + reqSize += sizeof(Mpi2IeeeSgeSimple64_t); + } + else + { + sgeSimple->FlagsLength = set32(payInSize | + MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_LAST_ELEMENT | + MPI_SGE_FLAGS_64_BIT_ADDRESSING | + MPI_SGE_FLAGS_IOC_TO_HOST | + MPI_SGE_FLAGS_END_OF_BUFFER | + MPI_SGE_FLAGS_END_OF_LIST)); + sgeSimple->Address.Low = set32((U32)adap->shared_ba + offsetof(mpt_shared_t, scratch)); +#if DOS + sgeSimple->Address.High = 0; +#else + sgeSimple->Address.High = set32((U32)(adap->shared_ba >> 32)); +#endif + sgeSimple++; + + reqSize += sizeof(SGESimple64_t); + } + } + + if (mpi2 && !(payOut && payOutSize) && !(payIn && payInSize)) + { + if (function == MPI_FUNCTION_SCSI_IO_REQUEST || + function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || + function == MPI_FUNCTION_CONFIG) + { + if (ieee_sgl) + { + sgeIeeeSimple->Flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | + MPI25_IEEE_SGE_FLAGS_END_OF_LIST | + MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; + sgeIeeeSimple->Length = set32(payInSize); + sgeIeeeSimple->Address.Low = 0; + sgeIeeeSimple->Address.High = 0; + sgeIeeeSimple++; + reqSize += sizeof(Mpi2IeeeSgeSimple64_t); + } + else + { + sgeSimple->FlagsLength = set32(payInSize | + MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_LAST_ELEMENT | + MPI_SGE_FLAGS_32_BIT_ADDRESSING | + MPI_SGE_FLAGS_END_OF_BUFFER | + MPI_SGE_FLAGS_END_OF_LIST)); + sgeSimple->Address.Low = 0; + sgeSimple->Address.High = 0; + sgeSimple++; + + reqSize += sizeof(SGESimple64_t); + } + } + } + + if (mpi2) + adap->msg_context = PASS_THRU_CONTEXT; + else + ((pMPIHeader_t)req)->MsgContext = set32(PASS_THRU_CONTEXT); + + if (function == MPI_FUNCTION_SCSI_IO_REQUEST || + function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || + function == MPI_FUNCTION_SCSI_IO_32) + { + if (mpi20) + { + Mpi2SCSIIORequest_t *scsiReq = (pMpi2SCSIIORequest_t)req; + Mpi2SCSIIOReply_t *scsiRep = (pMpi2SCSIIOReply_t)rep; + + scsiReq->SenseBufferLowAddress = + set32((U32)adap->shared_ba + offsetof(mpt_shared_t, data) + sizeof *scsiRep); + scsiReq->SenseBufferLength = (U8)(repSize - sizeof *scsiRep); + } + else if (mpi25) + { + Mpi25SCSIIORequest_t *scsiReq = (pMpi25SCSIIORequest_t)req; + Mpi2SCSIIOReply_t *scsiRep = (pMpi2SCSIIOReply_t)rep; + + scsiReq->SenseBufferLowAddress = + set32((U32)adap->shared_ba + offsetof(mpt_shared_t, data) + sizeof *scsiRep); + scsiReq->SenseBufferLength = (U8)(repSize - sizeof *scsiRep); + } + else + { + SCSIIORequest_t *scsiReq = (pSCSIIORequest_t)req; + SCSIIOReply_t *scsiRep = (pSCSIIOReply_t)rep; + + scsiReq->SenseBufferLowAddr = + set32((U32)adap->shared_ba + offsetof(mpt_shared_t, data) + sizeof *scsiRep); + scsiReq->SenseBufferLength = (U8)(repSize - sizeof *scsiRep); + } + } + + bcopy(req, adap->shared->message, reqSize); + + logMptCommandReq(port, req, reqSize); + + if (adap->ioc_online == TRUE) + { + if (mpt_verify_operational(adap)) + { + t = mpt_issue_command_and_wait(adap, timeOut); + + if (t != 1) + { + printf("mpt_issue_command_and_wait failed\n"); + } + } + else + { + t = 0; + } + } + else + { + time_t limit = time(NULL) + timeOut; + + if (mpt_verify_ready(adap) || mpt_verify_operational(adap)) + { + t = mpt_send_message(adap, reqSize, limit); + + if (t != 1) + { + printf("mpt_send_message failed!\n"); + } + else + { + t = mpt_receive_data(adap, repSize, limit); + + if (t != 1) + { + if (adap->bootloader == FALSE || + !(function == MPI_FUNCTION_IOC_INIT || + function == MPI_FUNCTION_IOC_FACTS || + function == MPI_FUNCTION_PORT_FACTS || + function == MPI_FUNCTION_CONFIG)) + { + ioc_status = get16(((pMPIDefaultReply_t)adap->shared->data)->IOCStatus) & MPI_IOCSTATUS_MASK; + + printf("[%s] mpt_receive_data failed, function = %d, IOCStatus = %04x (%s)\n", + port->portName, function, ioc_status, translateIocStatus(ioc_status)); + } + } + } + } + else + { + t = 0; + } + } + + bcopy(adap->shared->data, rep, repSize); + + logMptCommandRep(port, req, reqSize, rep, repSize, t); + + if (payIn && payInSize) + { + bcopy(adap->shared->scratch, payIn, payInSize); + } + + return t; +#endif +} + + +int +doMptCommandCheck(MPT_PORT *port, void *req, int reqSize, void *rep, int repSize, + void *payIn, int payInSize, void *payOut, int payOutSize, int timeOut) +{ + MPIDefaultReply_t *defaultRep; + int ioc_status; + int ioc_loginfo; + + if (doMptCommand(port, req, reqSize, rep, repSize, + payIn, payInSize, payOut, payOutSize, timeOut) != 1) + { + printf("\nFailed to issue command\n"); + return 0; + } + + defaultRep = (pMPIDefaultReply_t)rep; + ioc_status = get16(defaultRep->IOCStatus) & MPI_IOCSTATUS_MASK; + + if (ioc_status != MPI_IOCSTATUS_SUCCESS) + { + if ((get16(defaultRep->IOCStatus) & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) != 0) + { + ioc_loginfo = get32(defaultRep->IOCLogInfo); + printf("\nCommand failed with IOCStatus = %04x (%s), IOCLogInfo = %08x\n", + ioc_status, translateIocStatus(ioc_status), ioc_loginfo); + } + else + printf("\nCommand failed with IOCStatus = %04x (%s)\n", + ioc_status, translateIocStatus(ioc_status)); + + return 0; + } + + if (defaultRep->Function == MPI_FUNCTION_RAID_ACTION) + { + ioc_loginfo = get32(defaultRep->IOCLogInfo); + if (ioc_loginfo) + { + printf("\nRAID ACTION returned IOCLogInfo = %08x\n", ioc_loginfo); + } + } + + return 1; +} + + +char * +translateIocStatus(int ioc_status) +{ + // Bit 15 means "Log Info Available". Therefore, + // we only want bits 0 through 14. Otherwise, + // this routine won't work when log info is available. + ioc_status &= MPI_IOCSTATUS_MASK; + + switch (ioc_status) + { + case MPI_IOCSTATUS_SUCCESS: return "Success"; + case MPI_IOCSTATUS_INVALID_FUNCTION: return "Invalid Function"; + case MPI_IOCSTATUS_BUSY: return "IOC Busy"; + case MPI_IOCSTATUS_INVALID_SGL: return "Invalid SGL"; + case MPI_IOCSTATUS_INTERNAL_ERROR: return "Internal Error"; + case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: return "Insufficient Resources"; + case MPI_IOCSTATUS_INVALID_FIELD: return "Invalid Field"; + case MPI_IOCSTATUS_INVALID_STATE: return "Invalid State"; + case MPI_IOCSTATUS_OP_STATE_NOT_SUPPORTED: return "Operational State Not Supported"; + case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: return "Invalid Action"; + case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: return "Invalid Type"; + case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: return "Invalid Page"; + case MPI_IOCSTATUS_CONFIG_INVALID_DATA: return "Invalid Data"; + case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: return "No Defaults"; + case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: return "Can't Commit"; + case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: return "Recovered Error"; + case MPI_IOCSTATUS_SCSI_INVALID_BUS: return "Invalid Bus"; + case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: return "Invalid Target"; + case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: return "Device Not There"; + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: return "Data Overrun"; + case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: return "Data Underrun"; + case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: return "I/O Data Error"; + case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: return "Protocol Error"; + case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: return "Task Terminated"; + case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: return "Residual Mismatch"; + case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: return "Task Managment Failed"; + case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: return "IOC Terminated"; + case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: return "Externally Terminated"; + case MPI_IOCSTATUS_EEDP_GUARD_ERROR: return "EEDP Guard Error"; + case MPI_IOCSTATUS_EEDP_REF_TAG_ERROR: return "EEDP Reference Tag Error"; + case MPI_IOCSTATUS_EEDP_APP_TAG_ERROR: return "EEDP Application Tag Error"; + case MPI_IOCSTATUS_TARGET_PRIORITY_IO: return "Target Priority I/O"; + case MPI_IOCSTATUS_TARGET_INVALID_PORT: return "Invalid Port"; + case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: return "Invalid I/O Index"; + case MPI_IOCSTATUS_TARGET_ABORTED: return "Target Aborted"; + case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: return "No Connection, Retryable"; + case MPI_IOCSTATUS_TARGET_NO_CONNECTION: return "No Connection"; + case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: return "Transfer Count Mismatch"; + case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: return "Status Data Not Sent"; + case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: return "Data Offset Error"; + case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: return "Too Much Write Data"; + case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: return "Target IU Too Short"; + case MPI_IOCSTATUS_FC_ABORTED: return "FC Aborted"; + case MPI_IOCSTATUS_FC_RX_ID_INVALID: return "RX_ID Invalid"; + case MPI_IOCSTATUS_FC_DID_INVALID: return "D_ID Invalid"; + case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: return "Node Logged Out"; + case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: return "Exchange Canceled"; + case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: return "LAN Device Not Found"; + case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: return "LAN Device Failure"; + case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: return "LAN Transmit Error"; + case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: return "LAN Transmit Aborted"; + case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: return "LAN Receive Error"; + case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: return "LAN Receive Aborted"; + case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: return "LAN Partial Packet"; + case MPI_IOCSTATUS_LAN_CANCELED: return "LAN Canceled"; + case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: return "SMP Request Failed"; + case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: return "SMP Data Overrun"; + case MPI_IOCSTATUS_INBAND_ABORTED: return "Inband Aborted"; + case MPI_IOCSTATUS_INBAND_NO_CONNECTION: return "Inband No Connection"; + case MPI_IOCSTATUS_DIAGNOSTIC_RELEASED: return "Diagnostic Buffer Released"; + case MPI2_IOCSTATUS_RAID_ACCEL_ERROR: return "RAID Accelerator Error"; + } + + return ""; +} + + +void +displayByteData(unsigned char *buf, int len) +{ + int i; + int j; + char c[16]; + + for (i = 0, j = 0; i < len; i++, j++) + { + if (j == 0) + printf("%04x : ", i); + + printf("%02x ", buf[i]); + + if (!isprint(buf[i])) + c[j] = ' '; + else + c[j] = buf[i]; + + if (j == sizeof c - 1) + { + printf(" "); + for (j = 0; j < sizeof c; j++) + { + printf("%c", c[j]); + } + printf("\n"); + j = -1; + } + } + + if (j != 0) + { + for (i = j; i < sizeof c; i++) + printf(" "); + + printf(" "); + for (i = 0; i < j; i++) + { + printf("%c", c[i]); + } + printf("\n"); + } +} + + +void +dumpMemory(void *buf, int len, char *string) +{ + U8 *p = (U8 *)buf; + int i; + + if (string != NULL) + printf("\n%s\n", string); + for (i = 0; i < len; i += 4) + printf("%04x : %02x%02x%02x%02x %c%c%c%c\n", i, + p[i+3], p[i+2], p[i+1], p[i+0], + isprint(p[i+0]) ? p[i+0] : '.', + isprint(p[i+1]) ? p[i+1] : '.', + isprint(p[i+2]) ? p[i+2] : '.', + isprint(p[i+3]) ? p[i+3] : '.'); +} + + +void +dumpMemoryWide(void *buf, int len, char *string) +{ + U32 *p = (U32 *)buf; + int i; + + if (string != NULL) + printf("\n%s", string); + for (i = 0; i < len/4; i++) + { + if ((i % 8) == 0) + printf("\n%04x : %08x", i * 4, get32x(p[i])); + else + printf(" %08x", get32x(p[i])); + } + printf("\n"); +} + + +#define POLY 0x8bb7 + +unsigned short polyTableT10[256]; + + +void +initT10Crc(void) +{ + unsigned int data; + unsigned int crc; + unsigned int r_mask; + unsigned int d_mask; + int i; + int j; + + r_mask = 1 << (16 - 1); + d_mask = 1 << (8 - 1); + + for (i = 0; i < 256; i++) + { + data = i; + + crc = 0; + + for (j = 0; j < 8; j++) + { + if (( (crc & r_mask) && !(data & d_mask)) || + (!(crc & r_mask) && (data & d_mask))) + { + crc = ((crc << 1) ^ POLY) & 0xffff; + } + else + { + crc = (crc << 1) & 0xffff; + } + + data = data << 1; + } + + polyTableT10[i] = crc; + } +} + + +unsigned int +genT10Crc(unsigned char *buf) +{ + unsigned int crc; + unsigned int data; + int i; + + crc = 0; + + for (i = 0; i < 512; i++) + { + data = buf[i]; + crc = ((crc << 8) ^ polyTableT10[data ^ (crc >> 8)]) & 0xffff; + } + + return crc; +} + + +unsigned int +genLbCrc(unsigned char *buf, int len) +{ + return 0; +} + + +int +checkRemoveT10(MPT_PORT *port, unsigned int lbn, int lbns, unsigned char *buf_in, unsigned char *buf_out, int len) +{ + int i; + unsigned char *in; + unsigned char *out; + unsigned int crc; + unsigned int crc_in; + unsigned int lba; + unsigned int lba_in; + + in = buf_in; + out = buf_out; + + for (i = 0, lba = lbn; i < lbns; i++, lba++) + { + if (in[512+2] != 0xff || in[512+3] != 0xff) + { + crc = genT10Crc(in) & 0xffff; + + crc_in = get2bytes(in, 512); + + if (crc != crc_in) + { + printf("CRC is incorrect: %04x vs %04x\n", crc, crc_in); + return 0; + } + + lba_in = get4bytes(in, 512+4); + + if (lba != lba_in) + { + printf("LBA Ref Tag is incorrect: %08x vs %08x\n", lba, lba_in); + return 0; + } + } + + memcpy(out, in, 512); + + in += 512+8; + out += 512; + } + +// dumpMemory(buf_out, len, "read with T10"); + + return 1; +} + + +int +checkRemoveLb(MPT_PORT *port, unsigned int lbn, int lbns, unsigned char *buf_in, unsigned char *buf_out, int len, int do_crc) +{ + int i; + unsigned char *in; + unsigned char *out; + unsigned int crc; + unsigned int crc_in; + unsigned int lba; + unsigned int lba_in; + unsigned int *dif; + unsigned int t; + + in = buf_in; + out = buf_out; + + for (i = 0, lba = lbn; i < lbns; i += 8, lba += 8) + { + dif = (unsigned int *)(in + 4096); + + if (do_crc) + { + crc = genLbCrc(in, 4096); + + crc_in = get32x(dif[1]); + + if (crc != crc_in) + { + printf("Data CRC is incorrect: %08x vs %08x\n", crc, crc_in); + return 0; + } + + t = dif[3]; + crc = genLbCrc(in + 4096, 64); + dif[3] = t; + + crc_in = get32x(dif[3]); + + if (crc != crc_in) + { + printf("DIF CRC is incorrect: %08x vs %08x\n", crc, crc_in); + return 0; + } + } + + lba_in = get32x(dif[2]); + + if (lba != lba_in) + { + printf("LBA Ref Tag is incorrect: %08x vs %08x\n", lba, lba_in); + return 0; + } + + memcpy(out, in, 4096); + + in += 4096+64; + out += 4096; + } + +// dumpMemory(buf_out, len, "read with LB"); + + return 1; +} + + +int +insertT10(MPT_PORT *port, unsigned int lbn, int lbns, unsigned char *buf_in, unsigned char *buf_out, int len) +{ + int i; + unsigned char *in; + unsigned char *out; + unsigned int crc; + unsigned int lba; + + in = buf_in + (lbns - 1) * 512; + out = buf_out + (lbns - 1) * (512+8); + + for (i = 0, lba = lbn + lbns - 1; i < lbns; i++, lba--) + { + crc = genT10Crc(in) & 0xffff; + + memcpy(out, in, 512); + + memset(out + 512, 0, 8); + + put2bytes(out, 512, crc); + put4bytes(out, 516, lba); + +// if (lba >= 128 + 12 && lba < 128 + 12 + 16) out[512 + lba - 128 - 12 - 8] ^= 0x69; + + in -= 512; + out -= 512+8; + } + +// dumpMemory(buf_out, len, "write with T10"); + + return 1; +} + + +int +insertLb(MPT_PORT *port, unsigned int lbn, int lbns, unsigned char *buf_in, unsigned char *buf_out, int len, int do_crc) +{ + int i; + unsigned char *in; + unsigned char *out; + unsigned int crc; + unsigned int lba; + unsigned int *dif; + + in = buf_in + (lbns - 8) * 512; + out = buf_out + (lbns - 8) * (512+8); + + for (i = 0, lba = lbn + lbns - 8; i < lbns; i += 8, lba -= 8) + { + dif = (unsigned int *)(out + 4096); + + if (do_crc) + crc = genLbCrc(in, 4096); + else + crc = 0; + + memcpy(out, in, 4096); + + memset(out + 4096, 0, 64); + + dif[1] = set32x(crc); + dif[2] = set32x(lba); + dif[4] = set32x(lba); + + if (do_crc) + crc = genLbCrc(in + 4096, 64); + else + crc = 0; + + dif[3] = crc; + + in -= 4096; + out -= 4096+64; + } + +// dumpMemory(buf_out, len, "write with LB"); + + return 1; +} + + +void +waitForFile(char *name) +{ + int file; + + while (TRUE) + { + file = open(name, O_RDONLY | O_BINARY); + if (file >= 0) + { + close(file); + break; + } + + sleep(1); + } +} + + +typedef struct +{ + CONFIG_PAGE_HEADER Header; + MPI_CHIP_REVISION_ID ChipId; + + U8 SubsystemVendorId_0[2]; + U8 SubsystemId_0[2]; + U8 ClassCode_0[3]; + U8 PciMemory; + U8 HardwareConfig[1]; + U8 SubsystemVendorId_1[2]; + U8 SubsystemId_1[2]; + U8 ClassCode_1[3]; + U8 Checksum; + U8 Filler[3]; +} ManufacturingPage2_929_t; + + +typedef struct +{ + CONFIG_PAGE_HEADER Header; + MPI_CHIP_REVISION_ID ChipId; + + U8 SubsystemVendorId_0[2]; + U8 SubsystemId_0[2]; + U8 ClassCode_0[3]; + U8 PciMemory; + U8 HardwareConfig[2]; + U8 SubsystemVendorId_1[2]; + U8 SubsystemId_1[2]; + U8 ClassCode_1[3]; + U8 Checksum; + U8 Filler[2]; +} ManufacturingPage2_929X_t; + + +typedef struct +{ + CONFIG_PAGE_HEADER Header; + MPI_CHIP_REVISION_ID ChipId; + + U8 SubsystemVendorId[2]; + U8 SubsystemId[2]; + U8 ClassCode[3]; + U8 PciMemory; + U8 PciPowerBudgetData[8][3]; + U8 Checksum; + U8 Filler[3]; +} ManufacturingPage2_949E_t; + + +typedef struct +{ + CONFIG_PAGE_HEADER Header; + MPI_CHIP_REVISION_ID ChipId; + + _U64 WWPN_0; + _U64 WWNN_0; + _U32 PhyRegs1_0; + _U32 PhyRegs2_0; + _U32 PhyRegs2_Alt_0; + U8 MfgSupportedSpeeds_0; + U8 MfgLinkType_0; + U8 MfgConnectorType_0; + U8 Filler_0; + _U64 WWPN_1; + _U64 WWNN_1; + _U32 PhyRegs1_1; + _U32 PhyRegs2_1; + _U32 PhyRegs2_Alt_1; + U8 MfgSupportedSpeeds_1; + U8 MfgLinkType_1; + U8 MfgConnectorType_1; + U8 Filler_1; +} ManufacturingPage3_929_t; + + +typedef struct +{ + CONFIG_PAGE_HEADER Header; + MPI_CHIP_REVISION_ID ChipId; + + _U64 WWPN_0; + _U64 WWNN_0; + _U32 PhyRegs1_0; + U32 Unused1_0; + U32 Unused2_0; + U8 MfgSupportedSpeeds_0; + U8 MfgLinkType_0; + U8 MfgConnectorType_0; + U8 Filler_0; + _U64 WWPN_1; + _U64 WWNN_1; + _U32 PhyRegs1_1; + U32 Unused1_1; + U32 Unused2_1; + U8 MfgSupportedSpeeds_1; + U8 MfgLinkType_1; + U8 MfgConnectorType_1; + U8 Filler_1; + _U32 PhyRegs234[3*2*3]; +} ManufacturingPage3_949_t; + + +char * +skipLine(char *buf) +{ + char *c = buf; + + while (*c != '\n') + c++; + + c++; + + return c; +} + + +void +removeLine(char *buf) +{ + char *c = skipLine(buf); + + while (*c) + *buf++ = *c++; + + *buf = '\0'; +} + + +int +getNamedItem(MPT_PORT *port, char *name, char *buf, int type, void *address) +{ + char *c; + int n; + int t; + + n = (int)strlen(name); + + while (*buf) + { + if (*buf == '#') + { + c = buf; + + c++; + + if (*c == ' ') + c++; + + if (strncasecmp(name, c, n) == 0) + { + c = skipLine(c); + + switch (type) + { + case 1: + t = sscanf(c, "%s", (char *)address); +// if (t == 1) printf("parsed item %s = <%s>\n", name, (char *)address); + break; + + case 2: + t = sscanf(c, "%d", (int *)address); +// if (t == 1) printf("parsed item %s = <%d>\n", name, *(int *)address); + break; + + case 3: + t = sscanf(c, "0x%x", (int *)address); +// if (t == 1) printf("parsed item %s = <0x%x>\n", name, *(int *)address); + break; + + default: + t = 0; + } + + if (t == 1) + { + removeLine(buf); + removeLine(buf); + + return 1; + } + + printf("Parse error on item %s!\n", name); + return 0; + } + } + + buf = skipLine(buf); + } + + printf("Item %s not found!\n", name); + return 0; +} + + +int +updateConfigPage(MPT_PORT *port, char *string, void *page) +{ + ConfigPageHeader_t *header = (pConfigPageHeader_t)page; + int t; + + t = setConfigPage(port, header->PageType & MPI_CONFIG_PAGETYPE_MASK, header->PageNumber, 0, + page, header->PageLength * 4); + + if (t != 1) + printf("Failed to save %s to NVRAM!\n", string); + + return t; +} + + +int +doWriteFcManufacturingInfo(MPT_PORT *port) +{ + char name[256]; + unsigned char *mfginfoBuf = NULL; + int mfginfoLen; + unsigned char *identityBuf = NULL; + int identityLen; + int n; + int i; + int t; + int version; + char *buf; + char temp[64]; + char wwn[64]; + char tracer[64]; + char assembly[64]; + char board[64]; + char chip[64]; + char revision[64]; + int wwnl; + int device; + int pcirevision; + int subsys0; + int subsys1; + int subven0; + int subven1; + int pcimemory; + int class0; + int class1; + int hwconfig; + int linkconfig0; + int linkconfig1; + int ieeeident; + int phyreg10; + int phyreg11; + int phyreg20; + int phyreg21; + int phyreg2a0; + int phyreg2a1; + int phyreg234[3*2*3]; + int conninfo0; + int conninfo1; + int connect0; + int connect1; + int flags; + int coalflags0; + int coaltime0; + int coaldepth0; + int coalflags1; + int coaltime1; + int coaldepth1; + ManufacturingPage0_t ManufacturingPage0; + ManufacturingPage2_929_t ManufacturingPage2_929; + ManufacturingPage2_929X_t ManufacturingPage2_929X; + ManufacturingPage2_949E_t ManufacturingPage2_949E; + ManufacturingPage3_929_t ManufacturingPage3_929; + ManufacturingPage3_949_t ManufacturingPage3_949; + IOUnitPage1_t IOUnitPage1; + IOCPage1_t IOCPage1; + FCPortPage1_t FCPortPage1; + U8 checksum; + U8 *mp2p; + MPT_PORT *temp_port; + MPT_PORT *partner_port; + char *c; + + n = getFileName(name, sizeof name, stdin, "manufacturing information", 0); + if (n > 0) + { + if (readFile(name, &mfginfoBuf, &mfginfoLen) != 1) + return 0; + } + else + { + printf("Manufacturing information won't be programmed\n"); + return 0; + } + + printf("%d bytes read from %s\n\n", mfginfoLen, name); + + *tracer = 0; + *assembly = 0; + *wwn = 0; + + n = getFileName(name, sizeof name, stdin, "board identity", 1); + if (n > 0) + { + if (readFile(name, &identityBuf, &identityLen) != 1) + return 0; + + printf("%d bytes read from %s\n\n", identityLen, name); + + c = strchr((char *)identityBuf, '='); + + if (c) + { + c = strchr((char *)identityBuf, '\n'); + if (c) + { + if (strncmp(c + 1, "BoardAssembly = ", 16) == 0) + { + sscanf(c + 17, "%s", assembly); + c = strchr(c + 1, '\n'); + } + } + if (c) + { + if (strncmp(c + 1, "BoardTracerNumber = ", 20) == 0) + { + sscanf(c + 21, "%s", tracer); + c = strchr(c + 1, '\n'); + } + } + if (c) + { + if (strncmp(c + 1, "FC WWNN = ", 10) == 0) + { + sscanf(c + 11 + 10, "%s", wwn); + c = strchr(c + 1, '\n'); + } + } + } + else + { + sscanf((char *)identityBuf, "%s", assembly); + c = strchr((char *)identityBuf, '\n'); + if (c) + { + sscanf(c + 1, "%s", tracer); + c = strchr(c + 1, '\n'); + } + if (c) + { + sscanf(c + 1, "%s", wwn); + c = strchr(c + 1, '\n'); + } + } + + if (strlen(tracer) != 10 && strlen(tracer) != 11) + { + printf("Board Tracer value <%s> is invalid!\n", tracer); + *tracer = 0; + } + if (strlen(assembly) != 12) + { + printf("Board Assembly value <%s> is invalid!\n", assembly); + *assembly = 0; + } + if (strlen(wwn) != 6 || sscanf(wwn, "%x", &wwnl) != 1) + { + printf("Board WWN value <%s> is invalid!\n", wwn); + *wwn = 0; + } + + free(identityBuf); + } + else + { + printf("The board's identity must be entered manually!\n\n"); + } + + while (!*tracer || !*assembly || !*wwn) + { + printf("Board Tracer ...... %s\n", *tracer ? tracer : "not entered yet, 10 or 11 characters"); + printf("Board Assembly .... %s\n", *assembly ? assembly : "not entered yet, 12 characters"); + printf("Board WWN ......... %s\n", *wwn ? wwn : "not entered yet, 6 characters"); + + printf("\nEnter a value: [Tracer, Assembly, WWN, or Quit to quit] "); + + while (TRUE) + { + n = getStringFromArgs(temp, sizeof temp, stdin); + + if (n == 10 || n == 11) + { + strcpy(tracer, temp); + break; + } + else if (n == 12) + { + strcpy(assembly, temp); + break; + } + else if (n == 6) + { + if (sscanf(temp, "%x", &wwnl) == 1) + strcpy(wwn, temp); + break; + } + else if (n <= 4) + { + if (strncasecmp(temp, "quit", n) == 0) + return 0; + } + + printf("Invalid response, try again: "); + } + } + + printf("Board Tracer ...... %s\n", tracer); + printf("Board Assembly .... %s\n", assembly); + printf("Board WWN ......... %s\n", wwn); + + if (yesFlag == FALSE) + { + printf("\nAre these values correct? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + return 0; + } + + if (wFlag) + { + fprintf(logFile, "%s: Board Tracer ...... %s\n", logPrefix(port), tracer); + fprintf(logFile, "%s: Board Assembly .... %s\n", logPrefix(port), assembly); + fprintf(logFile, "%s: Board WWN ......... %s\n", logPrefix(port), wwn); + } + + n = mfginfoLen; + buf = realloc(mfginfoBuf, n + 2); + if (n && buf[n-1] != '\n') + { + mfginfoLen++; + buf[n++] = '\n'; + } + buf[n] = '\0'; + + n = 0; + for (i = 0; i < mfginfoLen; i++) + { + if (buf[i] == '\0' || buf[i] == '\r') // NUL and CR are ignored + continue; + + if (buf[i] == '#' && buf[i+1] == '#') // lines starting with ## are ignored + { + while (buf[i] != '\n' && i < mfginfoLen) + i++; + } + + if (buf[i] == '(') // text after an open parenthesis is ignored + { + while (buf[i] != '\n' && i < mfginfoLen) + i++; + } + + if (buf[i] == ' ' && buf[i+1] == '-' && buf[i+2] == ' ') // turn " - " into " " + { + buf[i+1] = ' '; + } + + if (n) + { + if (buf[i] == '\n' && buf[n-1] == '\n') // blank lines are ignored + continue; + + if (buf[i] == ' ' && buf[n-1] == ' ') // multiple spaces are collapsed + continue; + } + else + { + if (buf[i] == '\n') // blank lines are ignored + continue; + + if (buf[i] == ' ') // leading spaces are collapsed + continue; + } + + buf[n++] = buf[i]; + } + buf[n] = '\0'; + + printf("\n"); + + t = getNamedItem(port, "Version", buf, 2, &version); + if (t != 1) + { + printf("Incorrectly formatted file, failed to find version\n"); + return 0; + } + if (version != 3 && version != 4) + { + printf("Incorrectly formatted file, version should be 3 or 4\n"); + return 0; + } + + printf("Version %d found, processing...\n", version); + + t += getNamedItem(port, "Assembly Number", buf, 1, temp); + t += getNamedItem(port, "PCI Device Id", buf, 3, &device); + t += getNamedItem(port, "Chip Revision Id", buf, 3, &pcirevision); + t += getNamedItem(port, "Board Name", buf, 1, board); + t += getNamedItem(port, "Chip Name", buf, 1, chip); + t += getNamedItem(port, "Chip Revision Name", buf, 1, revision); + + if (t != 7) + { + printf("Could not read all required manufacturing information from file!\n"); + return 0; + } + + printf("\nBoard is %s, Assembly is %s, Chip is %s\n", board, temp, chip); + if (wFlag) + fprintf(logFile, "%s: Board is %s, Assembly is %s, Chip is %s\n", + logPrefix(port), board, temp, chip); + + if (device != port->deviceIdRaw || pcirevision != port->revisionId || + (strcasecmp(chip, port->chipName) && strcasecmp(chip + 3, port->chipName)) || + strcasecmp(temp, assembly)) + { + printf("Manufacturing information file is not for this chip!\n"); + return 0; + } + + device &= ~1; + + if (strncmp(board, "LSI74", 5) == 0 || strncmp(board, "LSIFC74", 7) == 0) + { + getBoardInfo(port); + + if (port->pciDevice == 6) // this is the second chip on a quad pci-x board + wwnl += 2; + + if (port->pciDevice == 0) // this is either the first or second chip on a quad pci-e board + { + n = 1; + + partner_port = NULL; + for (i = 0; i < NUM_PORTS; i++) // count how many 949E chips there are + { + temp_port = mptPorts[i]; + + if (temp_port == NULL || temp_port == port) + continue; + + if (getBoardInfo(temp_port) == 1) + { + if (temp_port->deviceId == 0x646 && + temp_port->pciDevice == 0 && + temp_port->pciFunction == 0) + { + n++; + partner_port = temp_port; + } + } + } + + if (n == 2) // if just two chips, the one with the higher bus is the second chip + { + if (port->pciBus > partner_port->pciBus) + wwnl += 2; + } + else // not the simple case, so ask the user + { + printf("\nIs this the first or second chip on this quad? [1=1st, 2=2nd, default is 1] "); + if (getNumberAnswer(1, 2, 1) == 2) + wwnl += 2; + } + } + } + + t += getNamedItem(port, "PCI Memory", buf, 3, &pcimemory); + t += getNamedItem(port, "Subsystem Id 0", buf, 3, &subsys0); + t += getNamedItem(port, "Subsystem Vendor Id 0", buf, 3, &subven0); + t += getNamedItem(port, "Class Code 0", buf, 3, &class0); + if (device != 0x646) + { + t += getNamedItem(port, "Subsystem Id 1", buf, 3, &subsys1); + t += getNamedItem(port, "Subsystem Vendor Id 1", buf, 3, &subven1); + t += getNamedItem(port, "Class Code 1", buf, 3, &class1); + t += getNamedItem(port, "Hardware Config", buf, 3, &hwconfig); + } + t += getNamedItem(port, "IOUnit1Flags", buf, 3, &flags); + t += getNamedItem(port, "IEEE Ident", buf, 3, &ieeeident); + t += getNamedItem(port, "LinkConfig Port 0", buf, 3, &linkconfig0); + t += getNamedItem(port, "PhyReg1 Port 0", buf, 3, &phyreg10); + t += getNamedItem(port, "PhyReg2 Port 0", buf, 3, &phyreg20); + t += getNamedItem(port, "PhyReg2Alt Port 0", buf, 3, &phyreg2a0); + t += getNamedItem(port, "ConnectInfo Port 0", buf, 3, &conninfo0); + t += getNamedItem(port, "Connector Port 0", buf, 3, &connect0); + t += getNamedItem(port, "Coalescing Flags 0", buf, 3, &coalflags0); + t += getNamedItem(port, "Coalescing Microseconds 0", buf, 3, &coaltime0); + t += getNamedItem(port, "Coalescing Depth 0", buf, 3, &coaldepth0); + if (!(flags & MPI_IOUNITPAGE1_SINGLE_FUNCTION)) + { + t += getNamedItem(port, "LinkConfig Port 1", buf, 3, &linkconfig1); + t += getNamedItem(port, "PhyReg1 Port 1", buf, 3, &phyreg11); + t += getNamedItem(port, "PhyReg2 Port 1", buf, 3, &phyreg21); + t += getNamedItem(port, "PhyReg2Alt Port 1", buf, 3, &phyreg2a1); + t += getNamedItem(port, "ConnectInfo Port 1", buf, 3, &conninfo1); + t += getNamedItem(port, "Connector Port 1", buf, 3, &connect1); + t += getNamedItem(port, "Coalescing Flags 1", buf, 3, &coalflags1); + t += getNamedItem(port, "Coalescing Depth 1", buf, 3, &coaldepth1); + t += getNamedItem(port, "Coalescing Microseconds 1", buf, 3, &coaltime1); + } + + if (device == 0x640 || device == 0x642 || device == 0x646) + { + t += getNamedItem(port, "PhyReg2A1", buf, 3, &phyreg234[0]); + t += getNamedItem(port, "PhyReg3A1", buf, 3, &phyreg234[1]); + t += getNamedItem(port, "PhyReg4A1", buf, 3, &phyreg234[2]); + t += getNamedItem(port, "PhyReg2A2", buf, 3, &phyreg234[3]); + t += getNamedItem(port, "PhyReg3A2", buf, 3, &phyreg234[4]); + t += getNamedItem(port, "PhyReg4A2", buf, 3, &phyreg234[5]); + t += getNamedItem(port, "PhyReg2A4", buf, 3, &phyreg234[6]); + t += getNamedItem(port, "PhyReg3A4", buf, 3, &phyreg234[7]); + t += getNamedItem(port, "PhyReg4A4", buf, 3, &phyreg234[8]); + t += getNamedItem(port, "PhyReg2P1", buf, 3, &phyreg234[9]); + t += getNamedItem(port, "PhyReg3P1", buf, 3, &phyreg234[10]); + t += getNamedItem(port, "PhyReg4P1", buf, 3, &phyreg234[11]); + t += getNamedItem(port, "PhyReg2P2", buf, 3, &phyreg234[12]); + t += getNamedItem(port, "PhyReg3P2", buf, 3, &phyreg234[13]); + t += getNamedItem(port, "PhyReg4P2", buf, 3, &phyreg234[14]); + t += getNamedItem(port, "PhyReg2P4", buf, 3, &phyreg234[15]); + t += getNamedItem(port, "PhyReg3P4", buf, 3, &phyreg234[16]); + t += getNamedItem(port, "PhyReg4P4", buf, 3, &phyreg234[17]); + } + + n = 1000; + + if (device == 0x622 || device == 0x624) + n = 35; + + if (device == 0x626 || device == 0x628) + n = 35; + + if (device == 0x640 || device == 0x642) + n = 53; + + if (device == 0x646) + n = 49; + + if (flags & MPI_IOUNITPAGE1_SINGLE_FUNCTION) + n -= 9; + + if (t != n) + { + printf("\nCould not read all required manufacturing information from file!\n"); + printf("Parsed %d out of %d items\n", t, n); + return 0; + } + + if (strlen(buf)) + { + printf("\nExtra lines found in manufacturing information file!\n"); + printf("----\n%s----\n", buf); + if (wFlag) + { + fprintf(logFile, "%s: Extra lines found in manufacturing information file!\n", logPrefix(port)); + fprintf(logFile, "----\n%s----\n", buf); + } + } + + free(buf); + + doIocInit(port, MPI_WHOINIT_MANUFACTURER); + + memset(&ManufacturingPage0, 0, sizeof ManufacturingPage0); + + ManufacturingPage0.Header.PageVersion = MPI_MANUFACTURING0_PAGEVERSION; + ManufacturingPage0.Header.PageLength = sizeof ManufacturingPage0 / 4; + ManufacturingPage0.Header.PageNumber = 0; + ManufacturingPage0.Header.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING | + MPI_CONFIG_PAGEATTR_PERSISTENT; + strcpy((char *)ManufacturingPage0.ChipName, chip); + strcpy((char *)ManufacturingPage0.ChipRevision, revision); + strcpy((char *)ManufacturingPage0.BoardName, board); + strcpy((char *)ManufacturingPage0.BoardAssembly, assembly); + strcpy((char *)ManufacturingPage0.BoardTracerNumber, tracer); + + updateConfigPage(port, "ManufacturingPage0", &ManufacturingPage0); + + if (device == 0x622 || device == 0x624) + { + memset(&ManufacturingPage2_929, 0, sizeof ManufacturingPage2_929); + + ManufacturingPage2_929.Header.PageVersion = MPI_MANUFACTURING2_PAGEVERSION; + ManufacturingPage2_929.Header.PageLength = sizeof ManufacturingPage2_929 / 4; + ManufacturingPage2_929.Header.PageNumber = 2; + ManufacturingPage2_929.Header.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING | + MPI_CONFIG_PAGEATTR_PERSISTENT; + + ManufacturingPage2_929.ChipId.DeviceID = set16(port->deviceIdRaw); + ManufacturingPage2_929.ChipId.PCIRevisionID = port->revisionId; + + ManufacturingPage2_929.SubsystemVendorId_0[0] = (U8)(subven0 >> 8*0); + ManufacturingPage2_929.SubsystemVendorId_0[1] = (U8)(subven0 >> 8*1); + ManufacturingPage2_929.SubsystemId_0[0] = (U8)(subsys0 >> 8*0); + ManufacturingPage2_929.SubsystemId_0[1] = (U8)(subsys0 >> 8*1); + ManufacturingPage2_929.ClassCode_0[0] = (U8)(class0 >> 8*0); + ManufacturingPage2_929.ClassCode_0[1] = (U8)(class0 >> 8*1); + ManufacturingPage2_929.ClassCode_0[2] = (U8)(class0 >> 8*2); + ManufacturingPage2_929.PciMemory = (U8)(pcimemory >> 8*0); + ManufacturingPage2_929.HardwareConfig[0] = (U8)(hwconfig >> 8*0); + ManufacturingPage2_929.SubsystemVendorId_1[0] = (U8)(subven1 >> 8*0); + ManufacturingPage2_929.SubsystemVendorId_1[1] = (U8)(subven1 >> 8*1); + ManufacturingPage2_929.SubsystemId_1[0] = (U8)(subsys1 >> 8*0); + ManufacturingPage2_929.SubsystemId_1[1] = (U8)(subsys1 >> 8*1); + ManufacturingPage2_929.ClassCode_1[0] = (U8)(class1 >> 8*0); + ManufacturingPage2_929.ClassCode_1[1] = (U8)(class1 >> 8*1); + ManufacturingPage2_929.ClassCode_1[2] = (U8)(class1 >> 8*2); + + checksum = 0xa5; + mp2p = (U8 *)&ManufacturingPage2_929; + + for (i = sizeof ManufacturingPage2_929.Header + sizeof ManufacturingPage2_929.ChipId; + i < offsetof(ManufacturingPage2_929_t, Checksum); + i++) + { + checksum += mp2p[i]; + } + + ManufacturingPage2_929.Checksum = -checksum; + + updateConfigPage(port, "ManufacturingPage2", &ManufacturingPage2_929); + } + + if (device == 0x626 || device == 0x628 || device == 0x640 || device == 0x642) + { + memset(&ManufacturingPage2_929X, 0, sizeof ManufacturingPage2_929X); + + ManufacturingPage2_929X.Header.PageVersion = MPI_MANUFACTURING2_PAGEVERSION; + ManufacturingPage2_929X.Header.PageLength = sizeof ManufacturingPage2_929X / 4; + ManufacturingPage2_929X.Header.PageNumber = 2; + ManufacturingPage2_929X.Header.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING | + MPI_CONFIG_PAGEATTR_PERSISTENT; + + ManufacturingPage2_929X.ChipId.DeviceID = set16(port->deviceIdRaw); + ManufacturingPage2_929X.ChipId.PCIRevisionID = port->revisionId; + + ManufacturingPage2_929X.SubsystemVendorId_0[0] = (U8)(subven0 >> 8*0); + ManufacturingPage2_929X.SubsystemVendorId_0[1] = (U8)(subven0 >> 8*1); + ManufacturingPage2_929X.SubsystemId_0[0] = (U8)(subsys0 >> 8*0); + ManufacturingPage2_929X.SubsystemId_0[1] = (U8)(subsys0 >> 8*1); + ManufacturingPage2_929X.ClassCode_0[0] = (U8)(class0 >> 8*0); + ManufacturingPage2_929X.ClassCode_0[1] = (U8)(class0 >> 8*1); + ManufacturingPage2_929X.ClassCode_0[2] = (U8)(class0 >> 8*2); + ManufacturingPage2_929X.PciMemory = (U8)(pcimemory >> 8*0); + ManufacturingPage2_929X.HardwareConfig[0] = (U8)(hwconfig >> 8*0); + ManufacturingPage2_929X.HardwareConfig[1] = (U8)(hwconfig >> 8*1); + ManufacturingPage2_929X.SubsystemVendorId_1[0] = (U8)(subven1 >> 8*0); + ManufacturingPage2_929X.SubsystemVendorId_1[1] = (U8)(subven1 >> 8*1); + ManufacturingPage2_929X.SubsystemId_1[0] = (U8)(subsys1 >> 8*0); + ManufacturingPage2_929X.SubsystemId_1[1] = (U8)(subsys1 >> 8*1); + ManufacturingPage2_929X.ClassCode_1[0] = (U8)(class1 >> 8*0); + ManufacturingPage2_929X.ClassCode_1[1] = (U8)(class1 >> 8*1); + ManufacturingPage2_929X.ClassCode_1[2] = (U8)(class1 >> 8*2); + + checksum = 0xa5; + mp2p = (U8 *)&ManufacturingPage2_929X; + + for (i = sizeof ManufacturingPage2_929X.Header + sizeof ManufacturingPage2_929X.ChipId; + i < offsetof(ManufacturingPage2_929X_t, Checksum); + i++) + { + checksum += mp2p[i]; + } + + ManufacturingPage2_929X.Checksum = -checksum; + + updateConfigPage(port, "ManufacturingPage2", &ManufacturingPage2_929X); + } + + if (device == 0x646) + { + memset(&ManufacturingPage2_949E, 0, sizeof ManufacturingPage2_949E); + + ManufacturingPage2_949E.Header.PageVersion = MPI_MANUFACTURING2_PAGEVERSION; + ManufacturingPage2_949E.Header.PageLength = sizeof ManufacturingPage2_949E / 4; + ManufacturingPage2_949E.Header.PageNumber = 2; + ManufacturingPage2_949E.Header.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING | + MPI_CONFIG_PAGEATTR_PERSISTENT; + + ManufacturingPage2_949E.ChipId.DeviceID = set16(port->deviceIdRaw); + ManufacturingPage2_949E.ChipId.PCIRevisionID = port->revisionId; + + ManufacturingPage2_949E.SubsystemVendorId[0] = (U8)(subven0 >> 8*0); + ManufacturingPage2_949E.SubsystemVendorId[1] = (U8)(subven0 >> 8*1); + ManufacturingPage2_949E.SubsystemId[0] = (U8)(subsys0 >> 8*0); + ManufacturingPage2_949E.SubsystemId[1] = (U8)(subsys0 >> 8*1); + ManufacturingPage2_949E.ClassCode[0] = (U8)(class0 >> 8*0); + ManufacturingPage2_949E.ClassCode[1] = (U8)(class0 >> 8*1); + ManufacturingPage2_949E.ClassCode[2] = (U8)(class0 >> 8*2); + ManufacturingPage2_949E.PciMemory = (U8)(pcimemory >> 8*0); + + checksum = 0xa5; + mp2p = (U8 *)&ManufacturingPage2_949E; + + for (i = sizeof ManufacturingPage2_949E.Header + sizeof ManufacturingPage2_949E.ChipId; + i < offsetof(ManufacturingPage2_949E_t, Checksum); + i++) + { + checksum += mp2p[i]; + } + + ManufacturingPage2_949E.Checksum = -checksum; + + updateConfigPage(port, "ManufacturingPage2", &ManufacturingPage2_949E); + } + + if (device == 0x622 || device == 0x624 || device == 0x626 || device == 0x628) + { + memset(&ManufacturingPage3_929, 0, sizeof ManufacturingPage3_929); + + ManufacturingPage3_929.Header.PageVersion = MPI_MANUFACTURING3_PAGEVERSION; + ManufacturingPage3_929.Header.PageLength = sizeof ManufacturingPage3_929 / 4; + ManufacturingPage3_929.Header.PageNumber = 3; + ManufacturingPage3_929.Header.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING | + MPI_CONFIG_PAGEATTR_PERSISTENT; + + ManufacturingPage3_929.ChipId.DeviceID = set16(port->deviceIdRaw); + ManufacturingPage3_929.ChipId.PCIRevisionID = port->revisionId; + + ManufacturingPage3_929.WWPN_0.Low = set32((wwnl & 0xffffff) | ((ieeeident & 0xff) << 24)); + ManufacturingPage3_929.WWPN_0.High = set32(0x10000000 | ((ieeeident & 0xffff00) >> 8)); + ManufacturingPage3_929.WWNN_0.Low = set32((wwnl & 0xffffff) | ((ieeeident & 0xff) << 24)); + ManufacturingPage3_929.WWNN_0.High = set32(0x20000000 | ((ieeeident & 0xffff00) >> 8)); + ManufacturingPage3_929.PhyRegs1_0 = set32(phyreg10); + ManufacturingPage3_929.PhyRegs2_0 = set32(phyreg20); + ManufacturingPage3_929.PhyRegs2_Alt_0 = set32(phyreg2a0); + ManufacturingPage3_929.MfgSupportedSpeeds_0 = (U8)(conninfo0 >> 8*0); + ManufacturingPage3_929.MfgLinkType_0 = (U8)(conninfo0 >> 8*1); + ManufacturingPage3_929.MfgConnectorType_0 = (U8)(conninfo0 >> 8*2); + if (!(flags & MPI_IOUNITPAGE1_SINGLE_FUNCTION)) + { + ManufacturingPage3_929.WWPN_1.Low = set32(get32(ManufacturingPage3_929.WWPN_0.Low) + 1); + ManufacturingPage3_929.WWPN_1.High = ManufacturingPage3_929.WWPN_0.High; + ManufacturingPage3_929.WWNN_1.Low = set32(get32(ManufacturingPage3_929.WWNN_0.Low) + 1); + ManufacturingPage3_929.WWNN_1.High = ManufacturingPage3_929.WWNN_0.High; + ManufacturingPage3_929.PhyRegs1_1 = set32(phyreg11); + ManufacturingPage3_929.PhyRegs2_1 = set32(phyreg21); + ManufacturingPage3_929.PhyRegs2_Alt_1 = set32(phyreg2a1); + ManufacturingPage3_929.MfgSupportedSpeeds_1 = (U8)(conninfo1 >> 8*0); + ManufacturingPage3_929.MfgLinkType_1 = (U8)(conninfo1 >> 8*1); + ManufacturingPage3_929.MfgConnectorType_1 = (U8)(conninfo1 >> 8*2); + } + + updateConfigPage(port, "ManufacturingPage3", &ManufacturingPage3_929); + } + + if (device == 0x640 || device == 0x642 || device == 0x646) + { + memset(&ManufacturingPage3_949, 0, sizeof ManufacturingPage3_949); + + ManufacturingPage3_949.Header.PageVersion = MPI_MANUFACTURING3_PAGEVERSION; + ManufacturingPage3_949.Header.PageLength = sizeof ManufacturingPage3_949 / 4; + ManufacturingPage3_949.Header.PageNumber = 3; + ManufacturingPage3_949.Header.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING | + MPI_CONFIG_PAGEATTR_PERSISTENT; + + ManufacturingPage3_949.ChipId.DeviceID = set16(port->deviceIdRaw); + ManufacturingPage3_949.ChipId.PCIRevisionID = port->revisionId; + + ManufacturingPage3_949.WWPN_0.Low = set32((wwnl & 0xffffff) | ((ieeeident & 0xff) << 24)); + ManufacturingPage3_949.WWPN_0.High = set32(0x10000000 | ((ieeeident & 0xffff00) >> 8)); + ManufacturingPage3_949.WWNN_0.Low = set32((wwnl & 0xffffff) | ((ieeeident & 0xff) << 24)); + ManufacturingPage3_949.WWNN_0.High = set32(0x20000000 | ((ieeeident & 0xffff00) >> 8)); + ManufacturingPage3_949.PhyRegs1_0 = set32(phyreg10); + ManufacturingPage3_949.MfgSupportedSpeeds_0 = (U8)(conninfo0 >> 8*0); + ManufacturingPage3_949.MfgLinkType_0 = (U8)(conninfo0 >> 8*1); + ManufacturingPage3_949.MfgConnectorType_0 = (U8)(conninfo0 >> 8*2); + if (!(flags & MPI_IOUNITPAGE1_SINGLE_FUNCTION)) + { + ManufacturingPage3_949.WWPN_1.Low = set32(get32(ManufacturingPage3_949.WWPN_0.Low) + 1); + ManufacturingPage3_949.WWPN_1.High = ManufacturingPage3_949.WWPN_0.High; + ManufacturingPage3_949.WWNN_1.Low = set32(get32(ManufacturingPage3_949.WWNN_0.Low) + 1); + ManufacturingPage3_949.WWNN_1.High = ManufacturingPage3_949.WWNN_0.High; + ManufacturingPage3_949.PhyRegs1_1 = set32(phyreg11); + ManufacturingPage3_949.MfgSupportedSpeeds_1 = (U8)(conninfo1 >> 8*0); + ManufacturingPage3_949.MfgLinkType_1 = (U8)(conninfo1 >> 8*1); + ManufacturingPage3_949.MfgConnectorType_1 = (U8)(conninfo1 >> 8*2); + } + for (i = 0; i < 3*2*3; i++) + ManufacturingPage3_949.PhyRegs234[i] = set32(phyreg234[i]); + + updateConfigPage(port, "ManufacturingPage3", &ManufacturingPage3_949); + } + + doIocInit(port, port->whoInit); + + memset(&IOUnitPage1, 0, sizeof IOUnitPage1); + + IOUnitPage1.Header.PageVersion = MPI_IOUNITPAGE1_PAGEVERSION; + IOUnitPage1.Header.PageLength = sizeof IOUnitPage1 / 4; + IOUnitPage1.Header.PageNumber = 1; + IOUnitPage1.Header.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT | + MPI_CONFIG_PAGEATTR_PERSISTENT; + + IOUnitPage1.Flags = set32(flags); + + updateConfigPage(port, "IOUnitPage1", &IOUnitPage1); + + memset(&IOCPage1, 0, sizeof IOCPage1); + + IOCPage1.Header.PageVersion = MPI_IOCPAGE1_PAGEVERSION; + IOCPage1.Header.PageLength = sizeof IOCPage1 / 4; + IOCPage1.Header.PageNumber = 1; + IOCPage1.Header.PageType = MPI_CONFIG_PAGETYPE_IOC | + MPI_CONFIG_PAGEATTR_PERSISTENT; + + if (port->iocNumber == 0) + { + IOCPage1.Flags = set32(coalflags0); + IOCPage1.CoalescingTimeout = set32(coaltime0); + IOCPage1.CoalescingDepth = coaldepth0; + } + else + { + IOCPage1.Flags = set32(coalflags1); + IOCPage1.CoalescingTimeout = set32(coaltime1); + IOCPage1.CoalescingDepth = coaldepth1; + } + IOCPage1.PCISlotNum = MPI_IOCPAGE1_PCISLOTNUM_UNKNOWN; + + updateConfigPage(port, "IOCPage1", &IOCPage1); + + memset(&FCPortPage1, 0, sizeof FCPortPage1); + + FCPortPage1.Header.PageVersion = MPI_FCPORTPAGE1_PAGEVERSION; + FCPortPage1.Header.PageLength = sizeof FCPortPage1 / 4; + FCPortPage1.Header.PageNumber = 1; + FCPortPage1.Header.PageType = MPI_CONFIG_PAGETYPE_FC_PORT | + MPI_CONFIG_PAGEATTR_PERSISTENT; + + FCPortPage1.Flags = set32(MPI_FCPORTPAGE1_FLAGS_SORT_BY_WWN | + MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT | + MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG | + MPI_FCPORTPAGE1_FLAGS_PROT_LAN | + MPI_FCPORTPAGE1_FLAGS_PROT_LOGBUSADDR); + FCPortPage1.NoSEEPROMWWNN.Low = set32(0x10001000); + FCPortPage1.NoSEEPROMWWNN.High = set32(0x200000a0); + FCPortPage1.NoSEEPROMWWPN.Low = set32(0x10001000); + FCPortPage1.NoSEEPROMWWPN.High = set32(0x100000a0); + FCPortPage1.HardALPA = MPI_FCPORTPAGE1_HARD_ALPA_NOT_USED; + FCPortPage1.TopologyConfig = MPI_FCPORTPAGE1_TOPOLOGY_AUTO; + if (port->iocNumber == 0) + { + FCPortPage1.LinkConfig = linkconfig0; + FCPortPage1.AltConnector = connect0; + } + else + { + FCPortPage1.LinkConfig = linkconfig1; + FCPortPage1.AltConnector = connect1; + } + + updateConfigPage(port, "FCPortPage1", &FCPortPage1); + + if (flags & MPI_IOUNITPAGE1_SINGLE_FUNCTION) + return 1; + + if (getBoardInfo(port) != 1) + return 1; + + partner_port = NULL; + for (i = 0; i < NUM_PORTS; i++) + { + temp_port = mptPorts[i]; + + if (temp_port == NULL || temp_port == port) + continue; + + if (getBoardInfo(temp_port) == 1) + { + if (port->pciBus == temp_port->pciBus && + port->pciDevice == temp_port->pciDevice && + port->pciFunction == (temp_port->pciFunction ^ 1)) + { + partner_port = temp_port; + + printf("\nPartner of %s is %s\n", port->portName, partner_port->portName); + if (wFlag) + fprintf(logFile, "%s: Partner is %s\n", logPrefix(port), partner_port->portName); + break; + } + } + } + + if (i == NUM_PORTS) + return 1; + + temp_port = port; + port = partner_port; + + if (port->iocNumber == 0) + { + IOCPage1.Flags = set32(coalflags0); + IOCPage1.CoalescingTimeout = set32(coaltime0); + IOCPage1.CoalescingDepth = coaldepth0; + } + else + { + IOCPage1.Flags = set32(coalflags1); + IOCPage1.CoalescingTimeout = set32(coaltime1); + IOCPage1.CoalescingDepth = coaldepth1; + } + IOCPage1.PCISlotNum = MPI_IOCPAGE1_PCISLOTNUM_UNKNOWN; + + updateConfigPage(port, "IOCPage1", &IOCPage1); + + if (port->iocNumber == 0) + { + FCPortPage1.LinkConfig = linkconfig0; + FCPortPage1.AltConnector = connect0; + } + else + { + FCPortPage1.LinkConfig = linkconfig1; + FCPortPage1.AltConnector = connect1; + } + + updateConfigPage(port, "FCPortPage1", &FCPortPage1); + + return 1; +} + + +int +doWriteSasManufacturingInfo(MPT_PORT *port) +{ + char name[256]; + unsigned char *identityBuf = NULL; + int identityLen; + int length; + int n; + int t; + char temp[64]; + char wwid[64]; + char tracer[64]; + char assembly[64]; + char board[64]; + char chip[64]; + char revision[64]; + int wwidl; + int wwidh; + ManufacturingPage0_t ManufacturingPage0; + ManufacturingPage5_t *ManufacturingPage5; + Mpi2ManufacturingPage5_t *ManufacturingPage5_2; + char *c; + U32 prefix; + int phy_num; + + if (getConfigPage(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, + &ManufacturingPage0, sizeof ManufacturingPage0) != 1) + { + printf("ManufacturingPage0 is not valid!\n"); + return 0; + } + + strcpy(board, (char *)ManufacturingPage0.BoardName); + strcpy(chip, (char *)ManufacturingPage0.ChipName); + strcpy(revision, (char *)ManufacturingPage0.ChipRevision); + + ManufacturingPage5 = getConfigPageAlloc(port, MPI_CONFIG_PAGETYPE_MANUFACTURING, 5, 0, &length); + if (ManufacturingPage5 == NULL) + { + printf("ManufacturingPage5 is not valid!\n"); + return 0; + } + + ManufacturingPage5_2 = (pMpi2ManufacturingPage5_t)ManufacturingPage5; + + *tracer = 0; + *assembly = 0; + *wwid = 0; + + n = getFileName(name, sizeof name, stdin, "board identity", 0); + if (n > 0) + { + if (readFile(name, &identityBuf, &identityLen) != 1) + { + free(ManufacturingPage5); + return 0; + } + + printf("%d bytes read from %s\n\n", identityLen, name); + + c = strchr((char *)identityBuf, '='); + + if (c) + { + c = strchr((char *)identityBuf, '\n'); + if (c) + { + if (strncmp(c + 1, "BoardAssembly = ", 16) == 0) + { + sscanf(c + 17, "%s", assembly); + c = strchr(c + 1, '\n'); + } + } + if (c) + { + if (strncmp(c + 1, "BoardTracerNumber = ", 20) == 0) + { + sscanf(c + 21, "%s", tracer); + c = strchr(c + 1, '\n'); + } + } + if (c) + { + if (strncmp(c + 1, "SAS WWID = ", 11) == 0) + { + sscanf(c + 12, "%s", wwid); + c = strchr(c + 1, '\n'); + } + } + } + else + { + sscanf((char *)identityBuf, "%s", assembly); + c = strchr((char *)identityBuf, '\n'); + if (c) + { + sscanf(c + 1, "%s", tracer); + c = strchr(c + 1, '\n'); + } + if (c) + { + sscanf(c + 2, "%s", wwid); // skip the leading '1' digit! + c = strchr(c + 1, '\n'); + } + } + + if (strlen(tracer) != 10 && strlen(tracer) != 11 && strlen(tracer) != 14) + { + printf("Board Tracer value <%s> is invalid!\n", tracer); + *tracer = 0; + } + if (strlen(assembly) != 12) + { + printf("Board Assembly value <%s> is invalid!\n", assembly); + *assembly = 0; + } + if ((strlen(wwid) != 9 && strlen(wwid) != 16) || + sscanf(wwid, "%x", &t) != 1 || sscanf(wwid + 8, "%x", &t) != 1) + { + printf("Board WWID value <%s> is invalid!\n", wwid); + *wwid = 0; + } + + free(identityBuf); + } + else + { + printf("The board's identity must be entered manually!\n\n"); + } + + while (!*tracer || !*assembly || !*wwid) + { + printf("Board Tracer ...... %s\n", *tracer ? tracer : "not entered yet, 10, 11 or 14 characters"); + printf("Board Assembly .... %s\n", *assembly ? assembly : "not entered yet, 12 characters"); + printf("Board WWID ........ %s\n", *wwid ? wwid : "not entered yet, 9 or 16 characters"); + + printf("\nEnter a value: [Tracer, Assembly, WWID, or Quit to quit] "); + + while (TRUE) + { + n = getStringFromArgs(temp, sizeof temp, stdin); + + if (n == 10 || n == 11 || n == 14) + { + strcpy(tracer, temp); + break; + } + else if (n == 12) + { + strcpy(assembly, temp); + break; + } + else if (n == 9 || n == 16) + { + if (sscanf(temp, "%x", &wwidl) == 1 && sscanf(temp + 8, "%x", &wwidl) == 1) + strcpy(wwid, temp); + break; + } + else if (n <= 4) + { + if (strncasecmp(temp, "quit", n) == 0) + { + free(ManufacturingPage5); + return 0; + } + } + + printf("Invalid response, try again: "); + } + } + + printf("Board Tracer ...... %s\n", tracer); + printf("Board Assembly .... %s\n", assembly); + printf("Board WWID ........ %s\n", wwid); + + if (yesFlag == FALSE) + { + printf("\nAre these values correct? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + { + free(ManufacturingPage5); + return 0; + } + } + + if (wFlag) + { + fprintf(logFile, "%s: Board Tracer ...... %s\n", logPrefix(port), tracer); + fprintf(logFile, "%s: Board Assembly .... %s\n", logPrefix(port), assembly); + fprintf(logFile, "%s: Board WWID ........ %s\n", logPrefix(port), wwid); + } + + if (strlen(wwid) == 9) + { + sscanf(wwid + 1, "%x", &wwidl); + wwid[1] = '\0'; + sscanf(wwid, "%x", &wwidh); + + if (mpi2) + prefix = get32(ManufacturingPage5_2->Phy[0].WWID.High) >> 4; + else + prefix = get32(ManufacturingPage5->BaseWWID.High) >> 4; + if (prefix == 0) + { + if (port->deviceId == MPI_MANUFACTPAGE_DEVID_SAS1064 || + port->deviceId == MPI_MANUFACTPAGE_DEVID_SAS1064E) + { + prefix = 0x500062b; + } + else + { + prefix = 0x500605b; + } + + printf("Enter the SAS WWID prefix: [7 hex digits, default is %07x] ", prefix); + getHexNumberAnswer(&prefix); + } + + wwidh |= prefix << 4; + } + else + { + sscanf(wwid + 8, "%x", &wwidl); + wwid[8] = '\0'; + sscanf(wwid, "%x", &wwidh); + } + + printf("\nBoard is %s, Assembly is %s, Chip is %s\n", board, assembly, chip); + if (wFlag) + fprintf(logFile, "%s: Board is %s, Assembly is %s, Chip is %s\n", + logPrefix(port), board, temp, chip); + + strcpy((char *)ManufacturingPage0.BoardAssembly, assembly); + strcpy((char *)ManufacturingPage0.BoardTracerNumber, tracer); + + if (mpi2) + { + for(phy_num = 0; phy_num < port->numPhys; phy_num++) + { + ManufacturingPage5_2->Phy[phy_num].WWID.Low = set32(wwidl + phy_num); + ManufacturingPage5_2->Phy[phy_num].WWID.High = set32(wwidh); + } + } + else + { + ManufacturingPage5->BaseWWID.Low = set32(wwidl); + ManufacturingPage5->BaseWWID.High = set32(wwidh); + } + + doIocInit(port, MPI_WHOINIT_MANUFACTURER); + + updateConfigPage(port, "ManufacturingPage0", &ManufacturingPage0); + updateConfigPage(port, "ManufacturingPage5", ManufacturingPage5); + + doIocInit(port, port->whoInit); + + free(ManufacturingPage5); + + return 1; +} + + +#undef mpi1 +#undef mpi2 +#undef mpi20 +#undef mpi25 +#undef MPI1 +#undef MPI2 +#undef MPI20 +#undef MPI25 + + +typedef struct +{ + _U32 Signature; + U8 State; + U8 Checksum; + _U16 TotalBytes; + _U16 NvdataVersion; + _U16 MpiVersion; + U8 CdhSize; + U8 CdeSize; + U8 PphSize; + U8 ProdIdSize; + _U32 NbrDirEntries; + _U32 NbrPersistDirEntries; + _U32 SeepromFwVarsOffset; + _U32 SeepromBufferOffset; + U32 Reserved; +} CONFIG_DIR_HEADER; + +typedef struct +{ + _U32 Signature; + U8 State; + U8 Reserved1; + _U16 TotalBytes; + _U16 NvdataVersion; + _U16 MpiVersion; + U8 CdhSize; + U8 CdeSize; + U8 PphSize; + U8 ProdIdSize; + _U32 NbrDirEntries; + _U32 NbrPersistDirEntries; + U32 Reserved3; + _U16 ProductIdOffset; + _U16 DirEntryOffset; + _U32 VendorNvramVersion; +} CONFIG_DIR_HEADER2; + +#define CONFIG_DIR_HEADER_SIGNATURE (0x4E69636B) + +#define CONFIG_DIR_HEADER_STATE_ERASED (0xFF) +#define CONFIG_DIR_HEADER_STATE_INITIALIZATION (CONFIG_DIR_HEADER_STATE_ERASED & ~0x01) +#define CONFIG_DIR_HEADER_STATE_RCV_DATA (CONFIG_DIR_HEADER_STATE_INITIALIZATION & ~0x02) +#define CONFIG_DIR_HEADER_STATE_VALID (CONFIG_DIR_HEADER_STATE_RCV_DATA & ~0x04) +#define CONFIG_DIR_HEADER_STATE_XFER_COMPLETE (CONFIG_DIR_HEADER_STATE_VALID & ~0x08) + + +typedef struct +{ + _U32 Signature; + U8 VendorId[8]; + U8 ProductId[16]; + U8 ProductRevision[4]; + U32 Reserved1; + U32 Reserved2; + U32 Reserved3; + U32 Reserved4; + U32 Reserved5; + U32 Reserved6; + U32 Reserved7; + U32 Reserved8; +} CONFIG_PROD_ID; + +#define CONFIG_PROD_ID_SIGNATURE (0x4672617A) + + +typedef struct +{ + U32 State : 4; + U32 AllocUnits : 12; + U32 PageType : 8; + U32 PageNum : 4; + U32 ForceNvdataUpdate : 1; + U32 PersistPageUpdated : 1; + U32 FlagRsvd1 : 1; + U32 FlagRsvd2 : 1; + U32 DwordOffset : 15; + U32 IocNum : 1; + U32 PageAddress : 16; +} CONFIG_DIR_ENTRY; + +typedef struct +{ + U8 State; + U8 Reserved; + _U16 AllocUnits; + U8 PageType; + U8 PageNum; + U8 UpdateFlags; + U8 IocNum; + _U32 DwordOffset; + _U32 PageAddress; +} CONFIG_DIR_ENTRY2; + +#define CONFIG_DIR_ENTRY_STATE_ERASED (0xF) +#define CONFIG_DIR_ENTRY_STATE_BEGIN_UPDATE (CONFIG_DIR_ENTRY_STATE_ERASED & ~0x1) +#define CONFIG_DIR_ENTRY_STATE_IN_USE (CONFIG_DIR_ENTRY_STATE_BEGIN_UPDATE & ~0x2) + + +typedef struct +{ + U8 State; + U8 Checksum; + _U16 DwordOffset; +} PERSISTENT_PAGE_HEADER; + +typedef struct +{ + U8 State; + U8 Checksum; + U16 Reserved; + _U32 DwordOffset; +} PERSISTENT_PAGE_HEADER2; + +#define CONFIG_PERSISTENT_HEADER_STATE_ERASED (0xFF) +#define CONFIG_PERSISTENT_HEADER_STATE_BEGIN_UPATE (CONFIG_PERSISTENT_HEADER_STATE_ERASED & ~0x01) +#define CONFIG_PERSISTENT_HEADER_STATE_UPDATE_COMPLETE (CONFIG_PERSISTENT_HEADER_STATE_BEGIN_UPATE & ~0x02) +#define CONFIG_PERSISTENT_HEADER_STATE_USE_NEXT_COPY (CONFIG_PERSISTENT_HEADER_STATE_UPDATE_COMPLETE & ~0x04) + + +#if VERIFY_ENDIANNESS && EFIEBC + + +int +concatenateSasFirmwareNvdata(void) +{ + return 0; +} + + +#else + + +typedef struct +{ + CONFIG_PAGE_HEADER Header; + MPI_CHIP_REVISION_ID ChipId; + U16 SubSystemIDFunc0; + U16 SubSystemVendorIDFunc0; + U8 PCIMemDiagSize; + U8 Reserved05; + U16 SubSystemIDFunc1; + U16 SubSystemVendorIDFunc1; + U8 AutoDownloadChecksum; + U8 Reserved0B; + U8 VendorIDDeviceIDLock; + U8 Reserved0D; + U16 VendorID0; + U16 DeviceID0; + U16 VendorID1; + U16 DeviceID1; + U8 ClassCode0[3]; + U8 Reserved19; + U8 ClassCode1[3]; + U8 Reserved1D; + U16 HardwareConfig; + U32 OptionRomOffset0; + U32 OptionRomOffset1; +} ManufacturingPage2_SAS_t, *pManufacturingPage2_SAS_t; + + +typedef struct +{ + MPI2_CONFIG_PAGE_HEADER Header; + MPI2_CHIP_REVISION_ID ChipId; + U32 Foo[19]; +} ManufacturingPage2_SAS2_t, *pManufacturingPage2_SAS2_t; + + +#define IOC_MFG_PAGE3_GPIO_DEFS (8) +#define IOC_MFG_PAGE3_NUM_PHYS_PER_QUAD (4) +#define IOC_MFG_PAGE3_NUM_QUADS (2) + +typedef struct +{ + U32 GigablazeConfig[4]; + U32 Reserved[1]; +} IOC_PHY_CONFIG; + +typedef struct +{ + U8 HotPlugTimeout; + U8 MaxCmdFrames; + U16 Reserved1; + U32 Reserved2[4]; + IOC_PHY_CONFIG PhyConfig[IOC_MFG_PAGE3_NUM_PHYS_PER_QUAD]; +} IOC_QUAD_CONFIG; + +typedef struct +{ + CONFIG_PAGE_HEADER Header; + MPI_CHIP_REVISION_ID ChipId; + U16 GPIODefinition[IOC_MFG_PAGE3_GPIO_DEFS]; + U8 FlashTime; + U8 NVTime; + U8 Flag; + U8 RuntimeConfig; + U8 SGPIOType; + U8 SEPType; + U8 PCIELaneConfig; + U8 Reserved0; + U32 PCIEConfig2; + U32 Reserved2; + U8 Reserved3[2]; + U8 Reserved4; + U8 Reserved5; + IOC_QUAD_CONFIG QuadConfig[IOC_MFG_PAGE3_NUM_QUADS]; +} ManufacturingPage3_SAS_t, *pManufacturingPage3_SAS_t; + + +#define IOC_MFG_PAGE3_NUM_PHYS (16) + +typedef struct _IOC_PHY_GROUP +{ + U32 Misc; + U32 Sas1G1Low; + U32 Sas1G1High; + U32 Sas1G2Low; + U32 Sas1G2High; + U32 SasOobLow; + U32 SasOobHigh; + U32 Sas2G1Low; + U32 Sas2G1High; + U32 Sas2G2Low; + U32 Sas2G2High; + U32 Sas2G3Low; + U32 Sas2G3High; + U32 SataG1Low; + U32 SataG1High; + U32 SataG2Low; + U32 SataG2High; + U32 SataG3Low; + U32 SataG3High; + U32 SataOobLow; + U32 SataOobHigh; +} IOC_PHY_GROUP; + +typedef struct +{ + MPI2_CONFIG_PAGE_HEADER Header; + MPI2_CHIP_REVISION_ID ChipId; + U32 Reserved1; + U32 Reserved2; + U32 Reserved3; + U32 Reserved4; + IOC_PHY_GROUP PhyGroup[4]; + U8 NumPhys; + U8 Reserved5; + U8 Reserved6; + U8 Reserved7; + U32 Phy[IOC_MFG_PAGE3_NUM_PHYS]; +} ManufacturingPage3_SAS2_t, *pManufacturingPage3_SAS2_t; + + +#define IOC_MFG_PAGE6_GPIO_DEFS (32) + +typedef struct +{ + U8 FunctionCode; + U8 Flags; + U8 Param1; + U8 Param2; + U32 Param3; +} IOC_CFG_MFG_6_GPIO_DEF; + +typedef struct +{ + MPI2_CONFIG_PAGE_HEADER Header; + U8 NumGPIO; + U8 Reserved1[3]; + U32 Reserved2; + U32 Reserved3; + IOC_CFG_MFG_6_GPIO_DEF GPIODefinition[IOC_MFG_PAGE6_GPIO_DEFS]; +} ManufacturingPage6_SAS2_t, *pManufacturingPage6_SAS2_t; + + +#define IOC_CFG_MFG9_NUMBER_OF_RESOURCES (13) + +typedef struct +{ + U32 Maximum; + U32 Decrement; + U32 Minimum; + U32 Actual; +} IOC_CFG_MFG9_RESOURCE; + +typedef struct +{ + MPI2_CONFIG_PAGE_HEADER Header; + U32 MaxAttempts; + U32 NumResources; + U32 Reserved1; + U32 Reserved2; + IOC_CFG_MFG9_RESOURCE ResourceArray[IOC_CFG_MFG9_NUMBER_OF_RESOURCES]; +} ManufacturingPage9_SAS2_t, *pManufacturingPage9_SAS2_t; + + +typedef struct +{ + U8 Flags; + U8 MoreFlags; + U16 TO; + U32 BaudRate; +} IOC_CFG_UART_SETTINGS; + +typedef struct +{ + MPI2_CONFIG_PAGE_HEADER Header; + U8 FlashTime; + U8 NVTime; + U8 Flag; + U8 Reserved1; + U8 HotPlugTimeout; + U8 Reserved[3]; + U8 MaxCmdFrames[4]; + U32 SysRefClk; + U32 Reserved2; + U32 ExtUartClk; + IOC_CFG_UART_SETTINGS UartSettings[2]; +} ManufacturingPage11_SAS2_t, *pManufacturingPage11_SAS2_t; + + +#define IOC_MAN_PAGE_12_SGPIO_INFO_ENTRIES (4) + +typedef struct +{ + U32 Flags; + U32 BitOrderSelect[12]; +} SGPIO_CONFIG_INFO; + +typedef struct +{ + MPI2_CONFIG_PAGE_HEADER Header; + U32 Flags; + U32 Reserved1; + U32 Reserved2; + U32 SGPIOCfg1; + U8 NumSGPIO; + U8 SGPIOType; + U16 ClkDivide; + U32 DefaultTxCtrl; + U32 SGPIOPatDef0; + U32 SGPIOPatDef1; + U32 SGPIOPatDef2; + U32 SGPIOPatDef3; + SGPIO_CONFIG_INFO SGPIOInfo[IOC_MAN_PAGE_12_SGPIO_INFO_ENTRIES]; +} ManufacturingPage12_SAS2_t, *pManufacturingPage12_SAS2_t; + + +#define IOC_MAN_PAGE_13_SGPIO_ENTRIES (4) + +typedef struct _SGPIO_TRANSLATION_DATA +{ + U32 Mask; + U32 SlotStatus; + U8 TxControl[4]; +} SGPIO_TRANSLATION_DATA, *PTR_SGPIO_TRANSLATION_DATA; + +typedef struct +{ + MPI2_CONFIG_PAGE_HEADER Header; + U8 NumSgpioEntries; + U8 Reserved0; + U16 Reserved1; + U32 Reserved2; + SGPIO_TRANSLATION_DATA SGPIOData[IOC_MAN_PAGE_13_SGPIO_ENTRIES]; +} ManufacturingPage13_SAS2_t, *pManufacturingPage13_SAS2_t; + + +typedef struct +{ + SAS_ADDRESS SasAddress; + U32 Reserved; +} SAS_PERSISTENT_ID_ENTRY; + +#define SAS_NUM_PERSIST_IDS_PER_PAGE (0x01) + +typedef struct +{ + CONFIG_EXTENDED_PAGE_HEADER Header; + SAS_PERSISTENT_ID_ENTRY PersistId[SAS_NUM_PERSIST_IDS_PER_PAGE]; +} PersistentId_SAS_t, *pPersistentId_SAS_t; + + +#define STR (1<<0) // item is a string +#define OPT (1<<1) // item is optional +#define DUP (1<<2) // item is a duplicate +#define BIT (1<<3) // item size is in bits, not bytes +#define IGN (1<<4) // item should be ignored if zero +#define MPI1 (1<<5) // item only applies to MPI 1.x +#define MPI2 (1<<6) // item only applies to MPI 2.0 +//TMC: MPI2.5 TODO + +typedef struct +{ + char *name; + int offset; + int size; + int flags; +} ITEM; + +#define EXT (1<<0) // section is an extended config page +#define GEN (1<<1) // section is "General" +#define PID (1<<2) // section is "Persistent ID" +#define MP2 (1<<3) // section is "Manufacturing Page 2" + +typedef struct +{ + char *name; + ITEM *items; + int size; + int flags; +} SECTION; + +typedef struct +{ + U8 SasAddress[6]; + U8 UserVersion; + U8 VendorId[8]; + U8 ProductId[16]; + U8 ProductRevision[4]; +} GeneralData_t, *pGeneralData_t; + +#undef data +#define data(x) (int)(size_t)&((pGeneralData_t)0)->x, sizeof(((pGeneralData_t)0)->x) + +ITEM general_data_items[] = +{ + {"SAS_ADRS_PREFIX", data(SasAddress), STR | OPT}, + {"USER_VERSION", data(UserVersion), 0}, + {"NVDATA_VENDORID", data(VendorId), STR}, + {"NVDATA_PRODUCTID", data(ProductId), STR}, + {"NVDATA_PRODUCT_REVISION", data(ProductRevision), STR}, + {0} +}; + +ITEM special_item = +{ + " SPECIAL ", 0, 0, OPT +}; + +ITEM forceupdate_item = +{ + "FORCEUPDATE", 0, 1, BIT +}; + +#undef data +#define data(x) (int)(size_t)&((pConfigPageHeader_t)0)->x, sizeof(((pConfigPageHeader_t)0)->x) + +ITEM header_items[] = +{ + {"PAGE_VERSION", data(PageVersion), 0}, + {"PAGE_LENGTH", data(PageLength), 0}, + {"PAGE_NUMBER", data(PageNumber), 0}, + {"PAGE_TYPE", data(PageType), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pConfigExtendedPageHeader_t)0)->x, sizeof(((pConfigExtendedPageHeader_t)0)->x) + +ITEM ext_header_items[] = +{ + {"PAGE_VERSION", data(PageVersion), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"CONFIG_EXTENDED_PAGE_HEADER_RESERVED1", data(Reserved1), OPT}, + {"PAGE_NUMBER", data(PageNumber), 0}, + {"PAGE_TYPE", data(PageType), 0}, + {"EXT_PAGE_LENGTH", data(ExtPageLength), 0}, + {"EXT_PAGE_TYPE", data(ExtPageType), 0}, + {"RESERVED2", data(Reserved2), OPT}, + {"CONFIG_EXTENDED_PAGE_HEADER_RESERVED2", data(Reserved2), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage0_t)0)->x, sizeof(((pManufacturingPage0_t)0)->x) + +ITEM manufacturing_page_0_items[] = +{ + {"CHIP_NAME", data(ChipName), STR}, + {"CHIP_REVISION", data(ChipRevision), STR}, + {"BOARD_NAME", data(BoardName), STR}, + {"BOARD_ASSEMBLY", data(BoardAssembly), STR}, + {"BOARD_TRACER_NUMBER", data(BoardTracerNumber), STR}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage1_t)0)->x, sizeof(((pManufacturingPage1_t)0)->x) + +ITEM manufacturing_page_1_items[] = +{ + {"VPD", data(VPD), STR}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage2_SAS_t)0)->x, sizeof(((pManufacturingPage2_SAS_t)0)->x) + +ITEM manufacturing_page_2_items[] = +{ + {"DEVICE_ID", data(ChipId.DeviceID), 0}, + {"PCI_REVISION", data(ChipId.PCIRevisionID), 0}, + {"MPI_CHIP_REVISION_ID_RESERVED", data(ChipId.Reserved), OPT}, + {"RESERVED", data(ChipId.Reserved), OPT}, + {"SSID_FCN_0", data(SubSystemIDFunc0), 0}, + {"SSVID_FCN_0", data(SubSystemVendorIDFunc0), 0}, + {"PCI_MEM_DIAG_SIZE", data(PCIMemDiagSize), 0}, + {"RESERVED0", data(Reserved05), OPT}, + {"RESERVED05", data(Reserved05), OPT}, + {"SSID_FCN_1", data(SubSystemIDFunc1), 0}, + {"SSVID_FCN_1", data(SubSystemVendorIDFunc1), 0}, + {"AUTODOWNLOAD_CHECKSUM", data(AutoDownloadChecksum), 0}, + {"RESERVED1", data(Reserved0B), OPT}, + {"RESERVED0B", data(Reserved0B), OPT}, + {"VENDORIDDEVICEIDLOCK", data(VendorIDDeviceIDLock), 0}, + {"RESERVED2", data(Reserved0D), OPT}, + {"RESERVED0D", data(Reserved0D), OPT}, + {"VENDOR_ID_0", data(VendorID0), 0}, + {"DEVICE_ID_0", data(DeviceID0), 0}, + {"VENDOR_ID_1", data(VendorID1), 0}, + {"DEVICE_ID_1", data(DeviceID1), 0}, + {"CC_0_SPECIFIC_CLASS", data(ClassCode0[0]), 0}, + {"CC_0_SUB_CLASS", data(ClassCode0[1]), 0}, + {"CC_0_BASE_CLASS", data(ClassCode0[2]), 0}, + {"RESERVED3", data(Reserved19), OPT}, + {"RESERVED19", data(Reserved19), OPT}, + {"CC_1_SPECIFIC_CLASS", data(ClassCode1[0]), 0}, + {"CC_1_SUB_CLASS", data(ClassCode1[1]), 0}, + {"CC_1_BASE_CLASS", data(ClassCode1[2]), 0}, + {"RESERVED4", data(Reserved1D), OPT}, + {"RESERVED1D", data(Reserved1D), OPT}, + {"HARDWARECONFIG", data(HardwareConfig), 0}, + {"OPTIONROMOFFSETFUNC0", data(OptionRomOffset0), 0}, + {"OPTIONROMOFFSETFUNC1", data(OptionRomOffset1), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage2_SAS2_t)0)->x, sizeof(((pManufacturingPage2_SAS2_t)0)->x) + +ITEM manufacturing_page_2_items2[] = +{ + {"DEVICE_ID", data(ChipId.DeviceID), 0}, + {"PCI_REVISION", data(ChipId.PCIRevisionID), 0}, + {"MPI_CHIP_REVISION_ID_RESERVED", data(ChipId.Reserved), OPT}, +// {"FOO_0", data(Foo[0]), 0}, +// {"FOO_1", data(Foo[1]), 0}, +// {"FOO_2", data(Foo[2]), 0}, +// {"FOO_3", data(Foo[3]), 0}, +// {"FOO_4", data(Foo[4]), 0}, +// {"FOO_5", data(Foo[5]), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage3_SAS_t)0)->x, sizeof(((pManufacturingPage3_SAS_t)0)->x) + +ITEM manufacturing_page_3_items[] = +{ + {"DEVICE_ID", data(ChipId.DeviceID), 0}, + {"PCI_REVISION_ID", data(ChipId.PCIRevisionID), 0}, + {"RESERVED", data(ChipId.Reserved), OPT}, + {"MPI_CHIP_REVISION_ID_RESERVED", data(ChipId.Reserved), OPT}, + {"GPIODEFINITION_0", data(GPIODefinition[0]), 0}, + {"GPIODEFINITION_1", data(GPIODefinition[1]), 0}, + {"GPIODEFINITION_2", data(GPIODefinition[2]), 0}, + {"GPIODEFINITION_3", data(GPIODefinition[3]), 0}, + {"GPIODEFINITION_4", data(GPIODefinition[4]), 0}, + {"GPIODEFINITION_5", data(GPIODefinition[5]), 0}, + {"GPIODEFINITION_6", data(GPIODefinition[6]), 0}, + {"GPIODEFINITION_7", data(GPIODefinition[7]), 0}, + {"FLASH_TIME", data(FlashTime), 0}, + {"NVS_TIME", data(NVTime), 0}, + {"FLAG", data(Flag), 0}, + {"RUNTIMECONFIG", data(RuntimeConfig), 0}, + {"SGPIOTYPE", data(SGPIOType), 0}, + {"MP3_SEPTYPE", data(SEPType), 0}, + {"PCIELANECONFIG", data(PCIELaneConfig), OPT}, + {"RESERVED", data(PCIELaneConfig), OPT}, + {"RESERVED0", data(Reserved0), OPT}, + {"PCIECONFIG2", data(PCIEConfig2), OPT}, + {"RESERVED1", data(PCIEConfig2), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3_0", data(Reserved3[0]), OPT}, + {"RESERVED3_1", data(Reserved3[1]), OPT}, + {"RESERVED4", data(Reserved4), OPT}, + {"RESERVED5", data(Reserved5), OPT}, + {"HOT_PLUG_TIM_OUT", data(QuadConfig[0].HotPlugTimeout), DUP}, + {"IOC_QUAD_CONFIG0_HOT_PLUG_TIM_OUT", data(QuadConfig[0].HotPlugTimeout), 0}, + {"MAX_CMD_FRAMES", data(QuadConfig[0].MaxCmdFrames), DUP}, + {"IOC_QUAD_CONFIG0_MAX_CMD_FRAMES", data(QuadConfig[0].MaxCmdFrames), 0}, + {"RESERVED1", data(QuadConfig[0].Reserved1), OPT}, + {"IOC_QUAD_CONFIG0_RESERVED1", data(QuadConfig[0].Reserved1), OPT}, + {"RESERVED2", data(QuadConfig[0].Reserved2), OPT}, + {"IOC_QUAD_CONFIG0_RESERVED2_0", data(QuadConfig[0].Reserved2[0]), OPT}, + {"IOC_QUAD_CONFIG0_RESERVED2_1", data(QuadConfig[0].Reserved2[1]), OPT}, + {"IOC_QUAD_CONFIG0_RESERVED2_2", data(QuadConfig[0].Reserved2[2]), OPT}, + {"IOC_QUAD_CONFIG0_RESERVED2_3", data(QuadConfig[0].Reserved2[3]), OPT}, + {"QUAD0_PHY0_GIG_CONFIG0", data(QuadConfig[0].PhyConfig[0].GigablazeConfig[0]), 0}, + {"QUAD0_PHY0_GIG_CONFIG1", data(QuadConfig[0].PhyConfig[0].GigablazeConfig[1]), 0}, + {"QUAD0_PHY0_GIG_CONFIG2", data(QuadConfig[0].PhyConfig[0].GigablazeConfig[2]), 0}, + {"QUAD0_PHY0_GIG_CONFIG3", data(QuadConfig[0].PhyConfig[0].GigablazeConfig[3]), 0}, + {"RESERVED1", data(QuadConfig[0].PhyConfig[0].Reserved), OPT}, + {"QUAD0_PHY0_GIG_CONFIG3_RESERVED", data(QuadConfig[0].PhyConfig[0].Reserved), OPT}, + {"QUAD0_PHY1_GIG_CONFIG0", data(QuadConfig[0].PhyConfig[1].GigablazeConfig[0]), 0}, + {"QUAD0_PHY1_GIG_CONFIG1", data(QuadConfig[0].PhyConfig[1].GigablazeConfig[1]), 0}, + {"QUAD0_PHY1_GIG_CONFIG2", data(QuadConfig[0].PhyConfig[1].GigablazeConfig[2]), 0}, + {"QUAD0_PHY1_GIG_CONFIG3", data(QuadConfig[0].PhyConfig[1].GigablazeConfig[3]), 0}, + {"RESERVED1", data(QuadConfig[0].PhyConfig[1].Reserved), OPT}, + {"QUAD0_PHY1_GIG_CONFIG3_RESERVED", data(QuadConfig[0].PhyConfig[1].Reserved), OPT}, + {"QUAD0_PHY2_GIG_CONFIG0", data(QuadConfig[0].PhyConfig[2].GigablazeConfig[0]), 0}, + {"QUAD0_PHY2_GIG_CONFIG1", data(QuadConfig[0].PhyConfig[2].GigablazeConfig[1]), 0}, + {"QUAD0_PHY2_GIG_CONFIG2", data(QuadConfig[0].PhyConfig[2].GigablazeConfig[2]), 0}, + {"QUAD0_PHY2_GIG_CONFIG3", data(QuadConfig[0].PhyConfig[2].GigablazeConfig[3]), 0}, + {"RESERVED1", data(QuadConfig[0].PhyConfig[2].Reserved), OPT}, + {"QUAD0_PHY2_GIG_CONFIG3_RESERVED", data(QuadConfig[0].PhyConfig[2].Reserved), OPT}, + {"QUAD0_PHY3_GIG_CONFIG0", data(QuadConfig[0].PhyConfig[3].GigablazeConfig[0]), 0}, + {"QUAD0_PHY3_GIG_CONFIG1", data(QuadConfig[0].PhyConfig[3].GigablazeConfig[1]), 0}, + {"QUAD0_PHY3_GIG_CONFIG2", data(QuadConfig[0].PhyConfig[3].GigablazeConfig[2]), 0}, + {"QUAD0_PHY3_GIG_CONFIG3", data(QuadConfig[0].PhyConfig[3].GigablazeConfig[3]), 0}, + {"RESERVED1", data(QuadConfig[0].PhyConfig[3].Reserved), OPT}, + {"QUAD0_PHY3_GIG_CONFIG3_RESERVED", data(QuadConfig[0].PhyConfig[3].Reserved), OPT}, + {"HOT_PLUG_TIM_OUT", data(QuadConfig[1].HotPlugTimeout), DUP}, + {"IOC_QUAD_CONFIG1_HOT_PLUG_TIM_OUT", data(QuadConfig[1].HotPlugTimeout), 0}, + {"MAX_CMD_FRAMES", data(QuadConfig[1].MaxCmdFrames), DUP}, + {"IOC_QUAD_CONFIG1_MAX_CMD_FRAMES", data(QuadConfig[1].MaxCmdFrames), 0}, + {"RESERVED1", data(QuadConfig[1].Reserved1), OPT}, + {"IOC_QUAD_CONFIG1_RESERVED1", data(QuadConfig[1].Reserved1), OPT}, + {"RESERVED2", data(QuadConfig[1].Reserved2), OPT}, + {"IOC_QUAD_CONFIG1_RESERVED2_0", data(QuadConfig[1].Reserved2[0]), OPT}, + {"IOC_QUAD_CONFIG1_RESERVED2_1", data(QuadConfig[1].Reserved2[1]), OPT}, + {"IOC_QUAD_CONFIG1_RESERVED2_2", data(QuadConfig[1].Reserved2[2]), OPT}, + {"IOC_QUAD_CONFIG1_RESERVED2_3", data(QuadConfig[1].Reserved2[3]), OPT}, + {"QUAD1_PHY0_GIG_CONFIG0", data(QuadConfig[1].PhyConfig[0].GigablazeConfig[0]), 0}, + {"QUAD1_PHY0_GIG_CONFIG1", data(QuadConfig[1].PhyConfig[0].GigablazeConfig[1]), 0}, + {"QUAD1_PHY0_GIG_CONFIG2", data(QuadConfig[1].PhyConfig[0].GigablazeConfig[2]), 0}, + {"QUAD1_PHY0_GIG_CONFIG3", data(QuadConfig[1].PhyConfig[0].GigablazeConfig[3]), 0}, + {"RESERVED1", data(QuadConfig[1].PhyConfig[0].Reserved), OPT}, + {"QUAD1_PHY0_GIG_CONFIG3_RESERVED", data(QuadConfig[1].PhyConfig[0].Reserved), OPT}, + {"QUAD1_PHY1_GIG_CONFIG0", data(QuadConfig[1].PhyConfig[1].GigablazeConfig[0]), 0}, + {"QUAD1_PHY1_GIG_CONFIG1", data(QuadConfig[1].PhyConfig[1].GigablazeConfig[1]), 0}, + {"QUAD1_PHY1_GIG_CONFIG2", data(QuadConfig[1].PhyConfig[1].GigablazeConfig[2]), 0}, + {"QUAD1_PHY1_GIG_CONFIG3", data(QuadConfig[1].PhyConfig[1].GigablazeConfig[3]), 0}, + {"RESERVED1", data(QuadConfig[1].PhyConfig[1].Reserved), OPT}, + {"QUAD1_PHY1_GIG_CONFIG3_RESERVED", data(QuadConfig[1].PhyConfig[1].Reserved), OPT}, + {"QUAD1_PHY2_GIG_CONFIG0", data(QuadConfig[1].PhyConfig[2].GigablazeConfig[0]), 0}, + {"QUAD1_PHY2_GIG_CONFIG1", data(QuadConfig[1].PhyConfig[2].GigablazeConfig[1]), 0}, + {"QUAD1_PHY2_GIG_CONFIG2", data(QuadConfig[1].PhyConfig[2].GigablazeConfig[2]), 0}, + {"QUAD1_PHY2_GIG_CONFIG3", data(QuadConfig[1].PhyConfig[2].GigablazeConfig[3]), 0}, + {"RESERVED1", data(QuadConfig[1].PhyConfig[2].Reserved), OPT}, + {"QUAD1_PHY2_GIG_CONFIG3_RESERVED", data(QuadConfig[1].PhyConfig[2].Reserved), OPT}, + {"QUAD1_PHY3_GIG_CONFIG0", data(QuadConfig[1].PhyConfig[3].GigablazeConfig[0]), 0}, + {"QUAD1_PHY3_GIG_CONFIG1", data(QuadConfig[1].PhyConfig[3].GigablazeConfig[1]), 0}, + {"QUAD1_PHY3_GIG_CONFIG2", data(QuadConfig[1].PhyConfig[3].GigablazeConfig[2]), 0}, + {"QUAD1_PHY3_GIG_CONFIG3", data(QuadConfig[1].PhyConfig[3].GigablazeConfig[3]), 0}, + {"RESERVED1", data(QuadConfig[1].PhyConfig[3].Reserved), OPT}, + {"QUAD1_PHY3_GIG_CONFIG3_RESERVED", data(QuadConfig[1].PhyConfig[3].Reserved), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage3_SAS2_t)0)->x, sizeof(((pManufacturingPage3_SAS2_t)0)->x) + +ITEM manufacturing_page_3_items2[] = +{ + {"DEVICE_ID", data(ChipId.DeviceID), 0}, + {"PCI_REVISION_ID", data(ChipId.PCIRevisionID), 0}, + {"MPI_CHIP_REVISION_ID_RESERVED", data(ChipId.Reserved), OPT}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"RESERVED4", data(Reserved4), OPT}, + {"GROUP0_MISC", data(PhyGroup[0].Misc), 0}, + {"GROUP0_SAS1G1LOW", data(PhyGroup[0].Sas1G1Low), 0}, + {"GROUP0_SAS1G1HIGH", data(PhyGroup[0].Sas1G1High), 0}, + {"GROUP0_SAS1G2LOW", data(PhyGroup[0].Sas1G2Low), 0}, + {"GROUP0_SAS1G2HIGH", data(PhyGroup[0].Sas1G2High), 0}, + {"GROUP0_SASOOBLOW", data(PhyGroup[0].SasOobLow), 0}, + {"GROUP0_SASOOBHIGH", data(PhyGroup[0].SasOobHigh), 0}, + {"GROUP0_SAS2G1LOW", data(PhyGroup[0].Sas2G1Low), 0}, + {"GROUP0_SAS2G1HIGH", data(PhyGroup[0].Sas2G1High), 0}, + {"GROUP0_SAS2G2LOW", data(PhyGroup[0].Sas2G2Low), 0}, + {"GROUP0_SAS2G2HIGH", data(PhyGroup[0].Sas2G2High), 0}, + {"GROUP0_SAS2G3LOW", data(PhyGroup[0].Sas2G3Low), 0}, + {"GROUP0_SAS2G3HIGH", data(PhyGroup[0].Sas2G3High), 0}, + {"GROUP0_SATAG1LOW", data(PhyGroup[0].SataG1Low), 0}, + {"GROUP0_SATAG1HIGH", data(PhyGroup[0].SataG1High), 0}, + {"GROUP0_SATAG2LOW", data(PhyGroup[0].SataG2Low), 0}, + {"GROUP0_SATAG2HIGH", data(PhyGroup[0].SataG2High), 0}, + {"GROUP0_SATAG3LOW", data(PhyGroup[0].SataG3Low), 0}, + {"GROUP0_SATAG3HIGH", data(PhyGroup[0].SataG3High), 0}, + {"GROUP0_SATAOOBLOW", data(PhyGroup[0].SataOobLow), 0}, + {"GROUP0_SATAOOBHIGH", data(PhyGroup[0].SataOobHigh), 0}, + {"GROUP1_MISC", data(PhyGroup[1].Misc), 0}, + {"GROUP1_SAS1G1LOW", data(PhyGroup[1].Sas1G1Low), 0}, + {"GROUP1_SAS1G1HIGH", data(PhyGroup[1].Sas1G1High), 0}, + {"GROUP1_SAS1G2LOW", data(PhyGroup[1].Sas1G2Low), 0}, + {"GROUP1_SAS1G2HIGH", data(PhyGroup[1].Sas1G2High), 0}, + {"GROUP1_SASOOBLOW", data(PhyGroup[1].SasOobLow), 0}, + {"GROUP1_SASOOBHIGH", data(PhyGroup[1].SasOobHigh), 0}, + {"GROUP1_SAS2G1LOW", data(PhyGroup[1].Sas2G1Low), 0}, + {"GROUP1_SAS2G1HIGH", data(PhyGroup[1].Sas2G1High), 0}, + {"GROUP1_SAS2G2LOW", data(PhyGroup[1].Sas2G2Low), 0}, + {"GROUP1_SAS2G2HIGH", data(PhyGroup[1].Sas2G2High), 0}, + {"GROUP1_SAS2G3LOW", data(PhyGroup[1].Sas2G3Low), 0}, + {"GROUP1_SAS2G3HIGH", data(PhyGroup[1].Sas2G3High), 0}, + {"GROUP1_SATAG1LOW", data(PhyGroup[1].SataG1Low), 0}, + {"GROUP1_SATAG1HIGH", data(PhyGroup[1].SataG1High), 0}, + {"GROUP1_SATAG2LOW", data(PhyGroup[1].SataG2Low), 0}, + {"GROUP1_SATAG2HIGH", data(PhyGroup[1].SataG2High), 0}, + {"GROUP1_SATAG3LOW", data(PhyGroup[1].SataG3Low), 0}, + {"GROUP1_SATAG3HIGH", data(PhyGroup[1].SataG3High), 0}, + {"GROUP1_SATAOOBLOW", data(PhyGroup[1].SataOobLow), 0}, + {"GROUP1_SATAOOBHIGH", data(PhyGroup[1].SataOobHigh), 0}, + {"GROUP2_MISC", data(PhyGroup[2].Misc), 0}, + {"GROUP2_SAS1G1LOW", data(PhyGroup[2].Sas1G1Low), 0}, + {"GROUP2_SAS1G1HIGH", data(PhyGroup[2].Sas1G1High), 0}, + {"GROUP2_SAS1G2LOW", data(PhyGroup[2].Sas1G2Low), 0}, + {"GROUP2_SAS1G2HIGH", data(PhyGroup[2].Sas1G2High), 0}, + {"GROUP2_SASOOBLOW", data(PhyGroup[2].SasOobLow), 0}, + {"GROUP2_SASOOBHIGH", data(PhyGroup[2].SasOobHigh), 0}, + {"GROUP2_SAS2G1LOW", data(PhyGroup[2].Sas2G1Low), 0}, + {"GROUP2_SAS2G1HIGH", data(PhyGroup[2].Sas2G1High), 0}, + {"GROUP2_SAS2G2LOW", data(PhyGroup[2].Sas2G2Low), 0}, + {"GROUP2_SAS2G2HIGH", data(PhyGroup[2].Sas2G2High), 0}, + {"GROUP2_SAS2G3LOW", data(PhyGroup[2].Sas2G3Low), 0}, + {"GROUP2_SAS2G3HIGH", data(PhyGroup[2].Sas2G3High), 0}, + {"GROUP2_SATAG1LOW", data(PhyGroup[2].SataG1Low), 0}, + {"GROUP2_SATAG1HIGH", data(PhyGroup[2].SataG1High), 0}, + {"GROUP2_SATAG2LOW", data(PhyGroup[2].SataG2Low), 0}, + {"GROUP2_SATAG2HIGH", data(PhyGroup[2].SataG2High), 0}, + {"GROUP2_SATAG3LOW", data(PhyGroup[2].SataG3Low), 0}, + {"GROUP2_SATAG3HIGH", data(PhyGroup[2].SataG3High), 0}, + {"GROUP2_SATAOOBLOW", data(PhyGroup[2].SataOobLow), 0}, + {"GROUP2_SATAOOBHIGH", data(PhyGroup[2].SataOobHigh), 0}, + {"GROUP3_MISC", data(PhyGroup[3].Misc), 0}, + {"GROUP3_SAS1G1LOW", data(PhyGroup[3].Sas1G1Low), 0}, + {"GROUP3_SAS1G1HIGH", data(PhyGroup[3].Sas1G1High), 0}, + {"GROUP3_SAS1G2LOW", data(PhyGroup[3].Sas1G2Low), 0}, + {"GROUP3_SAS1G2HIGH", data(PhyGroup[3].Sas1G2High), 0}, + {"GROUP3_SASOOBLOW", data(PhyGroup[3].SasOobLow), 0}, + {"GROUP3_SASOOBHIGH", data(PhyGroup[3].SasOobHigh), 0}, + {"GROUP3_SAS2G1LOW", data(PhyGroup[3].Sas2G1Low), 0}, + {"GROUP3_SAS2G1HIGH", data(PhyGroup[3].Sas2G1High), 0}, + {"GROUP3_SAS2G2LOW", data(PhyGroup[3].Sas2G2Low), 0}, + {"GROUP3_SAS2G2HIGH", data(PhyGroup[3].Sas2G2High), 0}, + {"GROUP3_SAS2G3LOW", data(PhyGroup[3].Sas2G3Low), 0}, + {"GROUP3_SAS2G3HIGH", data(PhyGroup[3].Sas2G3High), 0}, + {"GROUP3_SATAG1LOW", data(PhyGroup[3].SataG1Low), 0}, + {"GROUP3_SATAG1HIGH", data(PhyGroup[3].SataG1High), 0}, + {"GROUP3_SATAG2LOW", data(PhyGroup[3].SataG2Low), 0}, + {"GROUP3_SATAG2HIGH", data(PhyGroup[3].SataG2High), 0}, + {"GROUP3_SATAG3LOW", data(PhyGroup[3].SataG3Low), 0}, + {"GROUP3_SATAG3HIGH", data(PhyGroup[3].SataG3High), 0}, + {"GROUP3_SATAOOBLOW", data(PhyGroup[3].SataOobLow), 0}, + {"GROUP3_SATAOOBHIGH", data(PhyGroup[3].SataOobHigh), 0}, + {"NUM_PHYS", data(NumPhys), 0}, + {"RESERVED5", data(Reserved5), OPT}, + {"RESERVED6", data(Reserved6), OPT}, + {"RESERVED7", data(Reserved7), OPT}, + {"PHY_0", data(Phy[0]), 0}, + {"PHY_1", data(Phy[1]), 0}, + {"PHY_2", data(Phy[2]), 0}, + {"PHY_3", data(Phy[3]), 0}, + {"PHY_4", data(Phy[4]), 0}, + {"PHY_5", data(Phy[5]), 0}, + {"PHY_6", data(Phy[6]), 0}, + {"PHY_7", data(Phy[7]), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage4_t)0)->x, sizeof(((pManufacturingPage4_t)0)->x) +#define off(x) (int)(size_t)&((pManufacturingPage4_t)0)->x + +ITEM manufacturing_page_4_items[] = +{ + {"RESERVED1", data(Reserved1), OPT}, + {"INFO_OFFSET_0", data(InfoOffset0), 0}, + {"INFO_SIZE_0", data(InfoSize0), 0}, + {"INFO_OFFSET_1", data(InfoOffset1), 0}, + {"INFO_SIZE_1", data(InfoSize1), 0}, + {"INQUIRY_SIZE", data(InquirySize), 0}, + {"MP4_FLAGS", data(Flags), 0}, + {"RESERVED2", data(ExtFlags), OPT}, + {"EXTENDED_FLAGS", data(ExtFlags), OPT}, + {"DEVICE_TYPE", off(InquiryData[0]), 1, 0}, + {"DEVICE_TYPE_MOD", off(InquiryData[1]), 1, 0}, + {"VERSIONS", off(InquiryData[2]), 1, 0}, + {"DATA_FORMAT", off(InquiryData[3]), 1, 0}, + {"ADDITIONAL_LENGTH", off(InquiryData[4]), 1, 0}, + {"CAPABILITY_BITS", off(InquiryData[7]), 1, 0}, + {"VENDOR_ID", off(InquiryData[8]), 8, STR}, + {"PRODUCT_ID", off(InquiryData[16]), 16, STR}, + {"PRODUCT_REV", off(InquiryData[32]), 4, STR}, + {"VENDOR_SPECIFIC", off(InquiryData[36]), 20, STR}, + {"ISVOLUMESETTINGS", data(ISVolumeSettings), 0}, + {"IMEVOLUMESETTINGS", data(IMEVolumeSettings), 0}, + {"IMVOLUMESETTINGS", data(IMVolumeSettings), 0}, + {"RESERVED3", data(Reserved3), OPT}, + {"RESERVED4", data(Reserved4), OPT}, + {"RESERVED5", data(Reserved5), OPT}, + {"IME_DATASCRUBRATE", data(IMEDataScrubRate), 0}, + {"IME_RESYNCRATE", data(IMEResyncRate), 0}, + {"RESERVED6", data(Reserved6), OPT}, + {"IM_DATASCRUBRATE", data(IMDataScrubRate), 0}, + {"IM_RESYNCRATE", data(IMResyncRate), 0}, + {"RESERVED7", data(Reserved7), OPT}, + {"RESERVED8", data(Reserved8), OPT}, + {"RESERVED9", data(Reserved9), OPT}, + {0} +}; + +#undef off +#undef data +#define data(x) (int)(size_t)&((pMpi2ManufacturingPage4_t)0)->x, sizeof(((pMpi2ManufacturingPage4_t)0)->x) +#define off(x) (int)(size_t)&((pMpi2ManufacturingPage4_t)0)->x + +ITEM manufacturing_page_4_items2[] = +{ + {"RESERVED1", data(Reserved1), OPT}, + {"FLAGS", data(Flags), 0}, + {"INQUIRY_SIZE", data(InquirySize), 0}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"DEVICE_TYPE", off(InquiryData[0]), 1, 0}, + {"DEVICE_TYPE_MOD", off(InquiryData[1]), 1, 0}, + {"VERSIONS", off(InquiryData[2]), 1, 0}, + {"DATA_FORMAT", off(InquiryData[3]), 1, 0}, + {"ADDITIONAL_LENGTH", off(InquiryData[4]), 1, 0}, + {"CAPABILITY_BITS", off(InquiryData[7]), 1, 0}, + {"VENDOR_ID", off(InquiryData[8]), 8, STR}, + {"PRODUCT_ID", off(InquiryData[16]), 16, STR}, + {"PRODUCT_REV", off(InquiryData[32]), 4, STR}, + {"VENDOR_SPECIFIC", off(InquiryData[36]), 20, STR}, + {"RAID0VOLUMESETTINGS", data(RAID0VolumeSettings), 0}, + {"RAID1EVOLUMESETTINGS", data(RAID1EVolumeSettings), 0}, + {"RAID1VOLUMESETTINGS", data(RAID1VolumeSettings), 0}, + {"RAID10VOLUMESETTINGS", data(RAID10VolumeSettings), 0}, + {"RESERVED4", data(Reserved4), OPT}, + {"RESERVED5", data(Reserved5), OPT}, + {"POWERSAVEFLAGS", data(PowerSaveSettings.PowerSaveFlags), 0}, + {"INTOPSLEEPTIME", data(PowerSaveSettings.InternalOperationsSleepTime), 0}, + {"INTOPRUNTIME", data(PowerSaveSettings.InternalOperationsRunTime), 0}, + {"HOSTIDLETIME", data(PowerSaveSettings.HostIdleTime), 0}, + {"MAXOCEDISKS", data(MaxOCEDisks), 0}, + {"RESYNCRATE", data(ResyncRate), 0}, + {"DATASCRUBDURATION", data(DataScrubDuration), 0}, + {"MAXHOTSPARES", data(MaxHotSpares), 0}, + {"MAXPHYSDISKSPERVOL", data(MaxPhysDisksPerVol), 0}, + {"MAXPHYSDISKS", data(MaxPhysDisks), 0}, + {"MAXVOLUMES", data(MaxVolumes), 0}, + {0} +}; + +#undef off +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage5_t)0)->x, sizeof(((pManufacturingPage5_t)0)->x) + +ITEM manufacturing_page_5_items_25[] = +{ + {"Base_WWID_Low", data(BaseWWID.Low), 0}, + {"Base_WWID_Hi", data(BaseWWID.High), 0}, + {"MANUFACT_5_FLAGS", data(Flags), 0}, + {0} +}; + +#define manufacturing_page_5_size_25 (int)(size_t)&((pManufacturingPage5_t)0)->Reserved3 + +ITEM manufacturing_page_5_items[] = +{ + {"Base_WWID_Low", data(BaseWWID.Low), 0}, + {"Base_WWID_Hi", data(BaseWWID.High), 0}, + {"MANUFACT_5_FLAGS", data(Flags), 0}, + {"MAN_5_NUM_FORCE_WWID", data(NumForceWWID), 0}, + {"MAN_5_RESERVED", data(Reserved2), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"RESERVED4", data(Reserved4), OPT}, + {"FORCE_WWID_0_LOW", data(ForceWWID[0].Low), 0}, + {"FORCE_WWID_0_HI", data(ForceWWID[0].High), 0}, + {"FORCE_WWID_1_LOW", data(ForceWWID[1].Low), 0}, + {"FORCE_WWID_1_HI", data(ForceWWID[1].High), 0}, + {"FORCE_WWID_2_LOW", data(ForceWWID[2].Low), 0}, + {"FORCE_WWID_2_HI", data(ForceWWID[2].High), 0}, + {"FORCE_WWID_3_LOW", data(ForceWWID[3].Low), 0}, + {"FORCE_WWID_3_HI", data(ForceWWID[3].High), 0}, + {"FORCE_WWID_4_LOW", data(ForceWWID[4].Low), 0}, + {"FORCE_WWID_4_HI", data(ForceWWID[4].High), 0}, + {"FORCE_WWID_5_LOW", data(ForceWWID[5].Low), 0}, + {"FORCE_WWID_5_HI", data(ForceWWID[5].High), 0}, + {"FORCE_WWID_6_LOW", data(ForceWWID[6].Low), 0}, + {"FORCE_WWID_6_HI", data(ForceWWID[6].High), 0}, + {"FORCE_WWID_7_LOW", data(ForceWWID[7].Low), 0}, + {"FORCE_WWID_7_HI", data(ForceWWID[7].High), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pMpi2ManufacturingPage5_t)0)->x, sizeof(((pMpi2ManufacturingPage5_t)0)->x) + +ITEM manufacturing_page_5_items2[] = +{ + {"NUM_PHYS", data(NumPhys), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"RESERVED4", data(Reserved4), OPT}, + {"PHY0_WWID_LOW", data(Phy[0].WWID.Low), 0}, + {"PHY0_WWID_HI", data(Phy[0].WWID.High), 0}, + {"PHY0_DEVICENAME_LOW", data(Phy[0].DeviceName.Low), 0}, + {"PHY0_DEVICENAME_HI", data(Phy[0].DeviceName.High), 0}, + {"PHY1_WWID_LOW", data(Phy[1].WWID.Low), 0}, + {"PHY1_WWID_HI", data(Phy[1].WWID.High), 0}, + {"PHY1_DEVICENAME_LOW", data(Phy[1].DeviceName.Low), 0}, + {"PHY1_DEVICENAME_HI", data(Phy[1].DeviceName.High), 0}, + {"PHY2_WWID_LOW", data(Phy[2].WWID.Low), 0}, + {"PHY2_WWID_HI", data(Phy[2].WWID.High), 0}, + {"PHY2_DEVICENAME_LOW", data(Phy[2].DeviceName.Low), 0}, + {"PHY2_DEVICENAME_HI", data(Phy[2].DeviceName.High), 0}, + {"PHY3_WWID_LOW", data(Phy[3].WWID.Low), 0}, + {"PHY3_WWID_HI", data(Phy[3].WWID.High), 0}, + {"PHY3_DEVICENAME_LOW", data(Phy[3].DeviceName.Low), 0}, + {"PHY3_DEVICENAME_HI", data(Phy[3].DeviceName.High), 0}, + {"PHY4_WWID_LOW", data(Phy[4].WWID.Low), 0}, + {"PHY4_WWID_HI", data(Phy[4].WWID.High), 0}, + {"PHY4_DEVICENAME_LOW", data(Phy[4].DeviceName.Low), 0}, + {"PHY4_DEVICENAME_HI", data(Phy[4].DeviceName.High), 0}, + {"PHY5_WWID_LOW", data(Phy[5].WWID.Low), 0}, + {"PHY5_WWID_HI", data(Phy[5].WWID.High), 0}, + {"PHY5_DEVICENAME_LOW", data(Phy[5].DeviceName.Low), 0}, + {"PHY5_DEVICENAME_HI", data(Phy[5].DeviceName.High), 0}, + {"PHY6_WWID_LOW", data(Phy[6].WWID.Low), 0}, + {"PHY6_WWID_HI", data(Phy[6].WWID.High), 0}, + {"PHY6_DEVICENAME_LOW", data(Phy[6].DeviceName.Low), 0}, + {"PHY6_DEVICENAME_HI", data(Phy[6].DeviceName.High), 0}, + {"PHY7_WWID_LOW", data(Phy[7].WWID.Low), 0}, + {"PHY7_WWID_HI", data(Phy[7].WWID.High), 0}, + {"PHY7_DEVICENAME_LOW", data(Phy[7].DeviceName.Low), 0}, + {"PHY7_DEVICENAME_HI", data(Phy[7].DeviceName.High), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage6_SAS2_t)0)->x, sizeof(((pManufacturingPage6_SAS2_t)0)->x) + +ITEM manufacturing_page_6_items2[] = +{ + {"NUM_GPIO", data(NumGPIO), 0}, + {"RESERVED1_0", data(Reserved1[0]), OPT}, + {"RESERVED1_1", data(Reserved1[1]), OPT}, + {"RESERVED1_2", data(Reserved1[2]), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"GPIO_0_FUNC_CODE", data(GPIODefinition[0].FunctionCode), 0}, + {"GPIO_0_FLAGS", data(GPIODefinition[0].Flags), 0}, + {"GPIO_0_PARAM1", data(GPIODefinition[0].Param1), 0}, + {"GPIO_0_PARAM2", data(GPIODefinition[0].Param2), 0}, + {"GPIO_0_PARAM3", data(GPIODefinition[0].Param3), 0}, + {"GPIO_1_FUNC_CODE", data(GPIODefinition[1].FunctionCode), 0}, + {"GPIO_1_FLAGS", data(GPIODefinition[1].Flags), 0}, + {"GPIO_1_PARAM1", data(GPIODefinition[1].Param1), 0}, + {"GPIO_1_PARAM2", data(GPIODefinition[1].Param2), 0}, + {"GPIO_1_PARAM3", data(GPIODefinition[1].Param3), 0}, + {"GPIO_2_FUNC_CODE", data(GPIODefinition[2].FunctionCode), 0}, + {"GPIO_2_FLAGS", data(GPIODefinition[2].Flags), 0}, + {"GPIO_2_PARAM1", data(GPIODefinition[2].Param1), 0}, + {"GPIO_2_PARAM2", data(GPIODefinition[2].Param2), 0}, + {"GPIO_2_PARAM3", data(GPIODefinition[2].Param3), 0}, + {"GPIO_3_FUNC_CODE", data(GPIODefinition[3].FunctionCode), 0}, + {"GPIO_3_FLAGS", data(GPIODefinition[3].Flags), 0}, + {"GPIO_3_PARAM1", data(GPIODefinition[3].Param1), 0}, + {"GPIO_3_PARAM2", data(GPIODefinition[3].Param2), 0}, + {"GPIO_3_PARAM3", data(GPIODefinition[3].Param3), 0}, + {"GPIO_4_FUNC_CODE", data(GPIODefinition[4].FunctionCode), 0}, + {"GPIO_4_FLAGS", data(GPIODefinition[4].Flags), 0}, + {"GPIO_4_PARAM1", data(GPIODefinition[4].Param1), 0}, + {"GPIO_4_PARAM2", data(GPIODefinition[4].Param2), 0}, + {"GPIO_4_PARAM3", data(GPIODefinition[4].Param3), 0}, + {"GPIO_5_FUNC_CODE", data(GPIODefinition[5].FunctionCode), 0}, + {"GPIO_5_FLAGS", data(GPIODefinition[5].Flags), 0}, + {"GPIO_5_PARAM1", data(GPIODefinition[5].Param1), 0}, + {"GPIO_5_PARAM2", data(GPIODefinition[5].Param2), 0}, + {"GPIO_5_PARAM3", data(GPIODefinition[5].Param3), 0}, + {"GPIO_6_FUNC_CODE", data(GPIODefinition[6].FunctionCode), 0}, + {"GPIO_6_FLAGS", data(GPIODefinition[6].Flags), 0}, + {"GPIO_6_PARAM1", data(GPIODefinition[6].Param1), 0}, + {"GPIO_6_PARAM2", data(GPIODefinition[6].Param2), 0}, + {"GPIO_6_PARAM3", data(GPIODefinition[6].Param3), 0}, + {"GPIO_7_FUNC_CODE", data(GPIODefinition[7].FunctionCode), 0}, + {"GPIO_7_FLAGS", data(GPIODefinition[7].Flags), 0}, + {"GPIO_7_PARAM1", data(GPIODefinition[7].Param1), 0}, + {"GPIO_7_PARAM2", data(GPIODefinition[7].Param2), 0}, + {"GPIO_7_PARAM3", data(GPIODefinition[7].Param3), 0}, + {"GPIO_8_FUNC_CODE", data(GPIODefinition[8].FunctionCode), 0}, + {"GPIO_8_FLAGS", data(GPIODefinition[8].Flags), 0}, + {"GPIO_8_PARAM1", data(GPIODefinition[8].Param1), 0}, + {"GPIO_8_PARAM2", data(GPIODefinition[8].Param2), 0}, + {"GPIO_8_PARAM3", data(GPIODefinition[8].Param3), 0}, + {"GPIO_9_FUNC_CODE", data(GPIODefinition[9].FunctionCode), 0}, + {"GPIO_9_FLAGS", data(GPIODefinition[9].Flags), 0}, + {"GPIO_9_PARAM1", data(GPIODefinition[9].Param1), 0}, + {"GPIO_9_PARAM2", data(GPIODefinition[9].Param2), 0}, + {"GPIO_9_PARAM3", data(GPIODefinition[9].Param3), 0}, + {"GPIO_10_FUNC_CODE", data(GPIODefinition[10].FunctionCode), 0}, + {"GPIO_10_FLAGS", data(GPIODefinition[10].Flags), 0}, + {"GPIO_10_PARAM1", data(GPIODefinition[10].Param1), 0}, + {"GPIO_10_PARAM2", data(GPIODefinition[10].Param2), 0}, + {"GPIO_10_PARAM3", data(GPIODefinition[10].Param3), 0}, + {"GPIO_11_FUNC_CODE", data(GPIODefinition[11].FunctionCode), 0}, + {"GPIO_11_FLAGS", data(GPIODefinition[11].Flags), 0}, + {"GPIO_11_PARAM1", data(GPIODefinition[11].Param1), 0}, + {"GPIO_11_PARAM2", data(GPIODefinition[11].Param2), 0}, + {"GPIO_11_PARAM3", data(GPIODefinition[11].Param3), 0}, + {"GPIO_12_FUNC_CODE", data(GPIODefinition[12].FunctionCode), 0}, + {"GPIO_12_FLAGS", data(GPIODefinition[12].Flags), 0}, + {"GPIO_12_PARAM1", data(GPIODefinition[12].Param1), 0}, + {"GPIO_12_PARAM2", data(GPIODefinition[12].Param2), 0}, + {"GPIO_12_PARAM3", data(GPIODefinition[12].Param3), 0}, + {"GPIO_13_FUNC_CODE", data(GPIODefinition[13].FunctionCode), 0}, + {"GPIO_13_FLAGS", data(GPIODefinition[13].Flags), 0}, + {"GPIO_13_PARAM1", data(GPIODefinition[13].Param1), 0}, + {"GPIO_13_PARAM2", data(GPIODefinition[13].Param2), 0}, + {"GPIO_13_PARAM3", data(GPIODefinition[13].Param3), 0}, + {"GPIO_14_FUNC_CODE", data(GPIODefinition[14].FunctionCode), 0}, + {"GPIO_14_FLAGS", data(GPIODefinition[14].Flags), 0}, + {"GPIO_14_PARAM1", data(GPIODefinition[14].Param1), 0}, + {"GPIO_14_PARAM2", data(GPIODefinition[14].Param2), 0}, + {"GPIO_14_PARAM3", data(GPIODefinition[14].Param3), 0}, + {"GPIO_15_FUNC_CODE", data(GPIODefinition[15].FunctionCode), 0}, + {"GPIO_15_FLAGS", data(GPIODefinition[15].Flags), 0}, + {"GPIO_15_PARAM1", data(GPIODefinition[15].Param1), 0}, + {"GPIO_15_PARAM2", data(GPIODefinition[15].Param2), 0}, + {"GPIO_15_PARAM3", data(GPIODefinition[15].Param3), 0}, + {"GPIO_16_FUNC_CODE", data(GPIODefinition[16].FunctionCode), 0}, + {"GPIO_16_FLAGS", data(GPIODefinition[16].Flags), 0}, + {"GPIO_16_PARAM1", data(GPIODefinition[16].Param1), 0}, + {"GPIO_16_PARAM2", data(GPIODefinition[16].Param2), 0}, + {"GPIO_16_PARAM3", data(GPIODefinition[16].Param3), 0}, + {"GPIO_17_FUNC_CODE", data(GPIODefinition[17].FunctionCode), 0}, + {"GPIO_17_FLAGS", data(GPIODefinition[17].Flags), 0}, + {"GPIO_17_PARAM1", data(GPIODefinition[17].Param1), 0}, + {"GPIO_17_PARAM2", data(GPIODefinition[17].Param2), 0}, + {"GPIO_17_PARAM3", data(GPIODefinition[17].Param3), 0}, + {"GPIO_18_FUNC_CODE", data(GPIODefinition[18].FunctionCode), 0}, + {"GPIO_18_FLAGS", data(GPIODefinition[18].Flags), 0}, + {"GPIO_18_PARAM1", data(GPIODefinition[18].Param1), 0}, + {"GPIO_18_PARAM2", data(GPIODefinition[18].Param2), 0}, + {"GPIO_18_PARAM3", data(GPIODefinition[18].Param3), 0}, + {"GPIO_19_FUNC_CODE", data(GPIODefinition[19].FunctionCode), 0}, + {"GPIO_19_FLAGS", data(GPIODefinition[19].Flags), 0}, + {"GPIO_19_PARAM1", data(GPIODefinition[19].Param1), 0}, + {"GPIO_19_PARAM2", data(GPIODefinition[19].Param2), 0}, + {"GPIO_19_PARAM3", data(GPIODefinition[19].Param3), 0}, + {"GPIO_20_FUNC_CODE", data(GPIODefinition[20].FunctionCode), 0}, + {"GPIO_20_FLAGS", data(GPIODefinition[20].Flags), 0}, + {"GPIO_20_PARAM1", data(GPIODefinition[20].Param1), 0}, + {"GPIO_20_PARAM2", data(GPIODefinition[20].Param2), 0}, + {"GPIO_20_PARAM3", data(GPIODefinition[20].Param3), 0}, + {"GPIO_21_FUNC_CODE", data(GPIODefinition[21].FunctionCode), 0}, + {"GPIO_21_FLAGS", data(GPIODefinition[21].Flags), 0}, + {"GPIO_21_PARAM1", data(GPIODefinition[21].Param1), 0}, + {"GPIO_21_PARAM2", data(GPIODefinition[21].Param2), 0}, + {"GPIO_21_PARAM3", data(GPIODefinition[21].Param3), 0}, + {"GPIO_22_FUNC_CODE", data(GPIODefinition[22].FunctionCode), 0}, + {"GPIO_22_FLAGS", data(GPIODefinition[22].Flags), 0}, + {"GPIO_22_PARAM1", data(GPIODefinition[22].Param1), 0}, + {"GPIO_22_PARAM2", data(GPIODefinition[22].Param2), 0}, + {"GPIO_22_PARAM3", data(GPIODefinition[22].Param3), 0}, + {"GPIO_23_FUNC_CODE", data(GPIODefinition[23].FunctionCode), 0}, + {"GPIO_23_FLAGS", data(GPIODefinition[23].Flags), 0}, + {"GPIO_23_PARAM1", data(GPIODefinition[23].Param1), 0}, + {"GPIO_23_PARAM2", data(GPIODefinition[23].Param2), 0}, + {"GPIO_23_PARAM3", data(GPIODefinition[23].Param3), 0}, + {"GPIO_24_FUNC_CODE", data(GPIODefinition[24].FunctionCode), 0}, + {"GPIO_24_FLAGS", data(GPIODefinition[24].Flags), 0}, + {"GPIO_24_PARAM1", data(GPIODefinition[24].Param1), 0}, + {"GPIO_24_PARAM2", data(GPIODefinition[24].Param2), 0}, + {"GPIO_24_PARAM3", data(GPIODefinition[24].Param3), 0}, + {"GPIO_25_FUNC_CODE", data(GPIODefinition[25].FunctionCode), 0}, + {"GPIO_25_FLAGS", data(GPIODefinition[25].Flags), 0}, + {"GPIO_25_PARAM1", data(GPIODefinition[25].Param1), 0}, + {"GPIO_25_PARAM2", data(GPIODefinition[25].Param2), 0}, + {"GPIO_25_PARAM3", data(GPIODefinition[25].Param3), 0}, + {"GPIO_26_FUNC_CODE", data(GPIODefinition[26].FunctionCode), 0}, + {"GPIO_26_FLAGS", data(GPIODefinition[26].Flags), 0}, + {"GPIO_26_PARAM1", data(GPIODefinition[26].Param1), 0}, + {"GPIO_26_PARAM2", data(GPIODefinition[26].Param2), 0}, + {"GPIO_26_PARAM3", data(GPIODefinition[26].Param3), 0}, + {"GPIO_27_FUNC_CODE", data(GPIODefinition[27].FunctionCode), 0}, + {"GPIO_27_FLAGS", data(GPIODefinition[27].Flags), 0}, + {"GPIO_27_PARAM1", data(GPIODefinition[27].Param1), 0}, + {"GPIO_27_PARAM2", data(GPIODefinition[27].Param2), 0}, + {"GPIO_27_PARAM3", data(GPIODefinition[27].Param3), 0}, + {"GPIO_28_FUNC_CODE", data(GPIODefinition[28].FunctionCode), 0}, + {"GPIO_28_FLAGS", data(GPIODefinition[28].Flags), 0}, + {"GPIO_28_PARAM1", data(GPIODefinition[28].Param1), 0}, + {"GPIO_28_PARAM2", data(GPIODefinition[28].Param2), 0}, + {"GPIO_28_PARAM3", data(GPIODefinition[28].Param3), 0}, + {"GPIO_29_FUNC_CODE", data(GPIODefinition[29].FunctionCode), 0}, + {"GPIO_29_FLAGS", data(GPIODefinition[29].Flags), 0}, + {"GPIO_29_PARAM1", data(GPIODefinition[29].Param1), 0}, + {"GPIO_29_PARAM2", data(GPIODefinition[29].Param2), 0}, + {"GPIO_29_PARAM3", data(GPIODefinition[29].Param3), 0}, + {"GPIO_30_FUNC_CODE", data(GPIODefinition[30].FunctionCode), 0}, + {"GPIO_30_FLAGS", data(GPIODefinition[30].Flags), 0}, + {"GPIO_30_PARAM1", data(GPIODefinition[30].Param1), 0}, + {"GPIO_30_PARAM2", data(GPIODefinition[30].Param2), 0}, + {"GPIO_30_PARAM3", data(GPIODefinition[30].Param3), 0}, + {"GPIO_31_FUNC_CODE", data(GPIODefinition[31].FunctionCode), 0}, + {"GPIO_31_FLAGS", data(GPIODefinition[31].Flags), 0}, + {"GPIO_31_PARAM1", data(GPIODefinition[31].Param1), 0}, + {"GPIO_31_PARAM2", data(GPIODefinition[31].Param2), 0}, + {"GPIO_31_PARAM3", data(GPIODefinition[31].Param3), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage7_t)0)->x, sizeof(((pManufacturingPage7_t)0)->x) + +ITEM manufacturing_page_7_items[] = +{ + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"MP7_FLAGS", data(Flags), 0}, + {"ENCLOSURE_NAME", data(EnclosureName), STR}, + {"NUM_PHYS", data(NumPhys), 0}, + {"RESERVED3", data(Reserved3), OPT}, + {"RESERVED4", data(Reserved4), OPT}, + {"CONN_INFO_0_PINOUT", data(ConnectorInfo[0].Pinout), 0}, + {"CONN_INFO_0_CONNECTOR", data(ConnectorInfo[0].Connector), STR}, + {"CONN_INFO_0_LOCATION", data(ConnectorInfo[0].Location), 0}, + {"CONN_INFO_0_RESERVED1", data(ConnectorInfo[0].Reserved1), OPT}, + {"CONN_INFO_0_SLOT", data(ConnectorInfo[0].Slot), 0}, + {"CONN_INFO_0_RESERVED2", data(ConnectorInfo[0].Reserved2), OPT}, + {"CONN_INFO_1_PINOUT", data(ConnectorInfo[1].Pinout), 0}, + {"CONN_INFO_1_CONNECTOR", data(ConnectorInfo[1].Connector), STR}, + {"CONN_INFO_1_LOCATION", data(ConnectorInfo[1].Location), 0}, + {"CONN_INFO_1_RESERVED1", data(ConnectorInfo[1].Reserved1), OPT}, + {"CONN_INFO_1_SLOT", data(ConnectorInfo[1].Slot), 0}, + {"CONN_INFO_1_RESERVED2", data(ConnectorInfo[1].Reserved2), OPT}, + {"CONN_INFO_2_PINOUT", data(ConnectorInfo[2].Pinout), 0}, + {"CONN_INFO_2_CONNECTOR", data(ConnectorInfo[2].Connector), STR}, + {"CONN_INFO_2_LOCATION", data(ConnectorInfo[2].Location), 0}, + {"CONN_INFO_2_RESERVED1", data(ConnectorInfo[2].Reserved1), OPT}, + {"CONN_INFO_2_SLOT", data(ConnectorInfo[2].Slot), 0}, + {"CONN_INFO_2_RESERVED2", data(ConnectorInfo[2].Reserved2), OPT}, + {"CONN_INFO_3_PINOUT", data(ConnectorInfo[3].Pinout), 0}, + {"CONN_INFO_3_CONNECTOR", data(ConnectorInfo[3].Connector), STR}, + {"CONN_INFO_3_LOCATION", data(ConnectorInfo[3].Location), 0}, + {"CONN_INFO_3_RESERVED1", data(ConnectorInfo[3].Reserved1), OPT}, + {"CONN_INFO_3_SLOT", data(ConnectorInfo[3].Slot), 0}, + {"CONN_INFO_3_RESERVED2", data(ConnectorInfo[3].Reserved2), OPT}, + {"CONN_INFO_4_PINOUT", data(ConnectorInfo[4].Pinout), 0}, + {"CONN_INFO_4_CONNECTOR", data(ConnectorInfo[4].Connector), STR}, + {"CONN_INFO_4_LOCATION", data(ConnectorInfo[4].Location), 0}, + {"CONN_INFO_4_RESERVED1", data(ConnectorInfo[4].Reserved1), OPT}, + {"CONN_INFO_4_SLOT", data(ConnectorInfo[4].Slot), 0}, + {"CONN_INFO_4_RESERVED2", data(ConnectorInfo[4].Reserved2), OPT}, + {"CONN_INFO_5_PINOUT", data(ConnectorInfo[5].Pinout), 0}, + {"CONN_INFO_5_CONNECTOR", data(ConnectorInfo[5].Connector), STR}, + {"CONN_INFO_5_LOCATION", data(ConnectorInfo[5].Location), 0}, + {"CONN_INFO_5_RESERVED1", data(ConnectorInfo[5].Reserved1), OPT}, + {"CONN_INFO_5_SLOT", data(ConnectorInfo[5].Slot), 0}, + {"CONN_INFO_5_RESERVED2", data(ConnectorInfo[5].Reserved2), OPT}, + {"CONN_INFO_6_PINOUT", data(ConnectorInfo[6].Pinout), 0}, + {"CONN_INFO_6_CONNECTOR", data(ConnectorInfo[6].Connector), STR}, + {"CONN_INFO_6_LOCATION", data(ConnectorInfo[6].Location), 0}, + {"CONN_INFO_6_RESERVED1", data(ConnectorInfo[6].Reserved1), OPT}, + {"CONN_INFO_6_SLOT", data(ConnectorInfo[6].Slot), 0}, + {"CONN_INFO_6_RESERVED2", data(ConnectorInfo[6].Reserved2), OPT}, + {"CONN_INFO_7_PINOUT", data(ConnectorInfo[7].Pinout), 0}, + {"CONN_INFO_7_CONNECTOR", data(ConnectorInfo[7].Connector), STR}, + {"CONN_INFO_7_LOCATION", data(ConnectorInfo[7].Location), 0}, + {"CONN_INFO_7_RESERVED1", data(ConnectorInfo[7].Reserved1), OPT}, + {"CONN_INFO_7_SLOT", data(ConnectorInfo[7].Slot), 0}, + {"CONN_INFO_7_RESERVED2", data(ConnectorInfo[7].Reserved2), OPT}, + {"CONN_INFO_8_PINOUT", data(ConnectorInfo[8].Pinout), OPT}, + {"CONN_INFO_8_CONNECTOR", data(ConnectorInfo[8].Connector), STR | OPT}, + {"CONN_INFO_8_LOCATION", data(ConnectorInfo[8].Location), OPT}, + {"CONN_INFO_8_RESERVED1", data(ConnectorInfo[8].Reserved1), OPT}, + {"CONN_INFO_8_SLOT", data(ConnectorInfo[8].Slot), OPT}, + {"CONN_INFO_8_RESERVED2", data(ConnectorInfo[8].Reserved2), OPT}, + {"CONN_INFO_9_PINOUT", data(ConnectorInfo[9].Pinout), OPT}, + {"CONN_INFO_9_CONNECTOR", data(ConnectorInfo[9].Connector), STR | OPT}, + {"CONN_INFO_9_LOCATION", data(ConnectorInfo[9].Location), OPT}, + {"CONN_INFO_9_RESERVED1", data(ConnectorInfo[9].Reserved1), OPT}, + {"CONN_INFO_9_SLOT", data(ConnectorInfo[9].Slot), OPT}, + {"CONN_INFO_9_RESERVED2", data(ConnectorInfo[9].Reserved2), OPT}, + {"CONN_INFO_10_PINOUT", data(ConnectorInfo[10].Pinout), OPT}, + {"CONN_INFO_10_CONNECTOR", data(ConnectorInfo[10].Connector), STR | OPT}, + {"CONN_INFO_10_LOCATION", data(ConnectorInfo[10].Location), OPT}, + {"CONN_INFO_10_RESERVED1", data(ConnectorInfo[10].Reserved1), OPT}, + {"CONN_INFO_10_SLOT", data(ConnectorInfo[10].Slot), OPT}, + {"CONN_INFO_10_RESERVED2", data(ConnectorInfo[10].Reserved2), OPT}, + {"CONN_INFO_11_PINOUT", data(ConnectorInfo[11].Pinout), OPT}, + {"CONN_INFO_11_CONNECTOR", data(ConnectorInfo[11].Connector), STR | OPT}, + {"CONN_INFO_11_LOCATION", data(ConnectorInfo[11].Location), OPT}, + {"CONN_INFO_11_RESERVED1", data(ConnectorInfo[11].Reserved1), OPT}, + {"CONN_INFO_11_SLOT", data(ConnectorInfo[11].Slot), OPT}, + {"CONN_INFO_11_RESERVED2", data(ConnectorInfo[11].Reserved2), OPT}, + {"CONN_INFO_12_PINOUT", data(ConnectorInfo[12].Pinout), OPT}, + {"CONN_INFO_12_CONNECTOR", data(ConnectorInfo[12].Connector), STR | OPT}, + {"CONN_INFO_12_LOCATION", data(ConnectorInfo[12].Location), OPT}, + {"CONN_INFO_12_RESERVED1", data(ConnectorInfo[12].Reserved1), OPT}, + {"CONN_INFO_12_SLOT", data(ConnectorInfo[12].Slot), OPT}, + {"CONN_INFO_12_RESERVED2", data(ConnectorInfo[12].Reserved2), OPT}, + {"CONN_INFO_13_PINOUT", data(ConnectorInfo[13].Pinout), OPT}, + {"CONN_INFO_13_CONNECTOR", data(ConnectorInfo[13].Connector), STR | OPT}, + {"CONN_INFO_13_LOCATION", data(ConnectorInfo[13].Location), OPT}, + {"CONN_INFO_13_RESERVED1", data(ConnectorInfo[13].Reserved1), OPT}, + {"CONN_INFO_13_SLOT", data(ConnectorInfo[13].Slot), OPT}, + {"CONN_INFO_13_RESERVED2", data(ConnectorInfo[13].Reserved2), OPT}, + {"CONN_INFO_14_PINOUT", data(ConnectorInfo[14].Pinout), OPT}, + {"CONN_INFO_14_CONNECTOR", data(ConnectorInfo[14].Connector), STR | OPT}, + {"CONN_INFO_14_LOCATION", data(ConnectorInfo[14].Location), OPT}, + {"CONN_INFO_14_RESERVED1", data(ConnectorInfo[14].Reserved1), OPT}, + {"CONN_INFO_14_SLOT", data(ConnectorInfo[14].Slot), OPT}, + {"CONN_INFO_14_RESERVED2", data(ConnectorInfo[14].Reserved2), OPT}, + {"CONN_INFO_15_PINOUT", data(ConnectorInfo[15].Pinout), OPT}, + {"CONN_INFO_15_CONNECTOR", data(ConnectorInfo[15].Connector), STR | OPT}, + {"CONN_INFO_15_LOCATION", data(ConnectorInfo[15].Location), OPT}, + {"CONN_INFO_15_RESERVED1", data(ConnectorInfo[15].Reserved1), OPT}, + {"CONN_INFO_15_SLOT", data(ConnectorInfo[15].Slot), OPT}, + {"CONN_INFO_15_RESERVED2", data(ConnectorInfo[15].Reserved2), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage8_t)0)->x, sizeof(((pManufacturingPage8_t)0)->x) + +ITEM manufacturing_page_8_items2[] = +{ + {"PRODSPECIFICINFO", data(ProductSpecificInfo), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage9_SAS2_t)0)->x, sizeof(((pManufacturingPage9_SAS2_t)0)->x) + +ITEM manufacturing_page_9_items2[] = +{ + {"MAX_ATTEMPTS", data(MaxAttempts), 0}, + {"NUM_RESOURCES", data(NumResources), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"NUM_VFS_MAX", data(ResourceArray[0].Maximum), 0}, + {"NUM_VFS_DEC", data(ResourceArray[0].Decrement), 0}, + {"NUM_VFS_MIN", data(ResourceArray[0].Minimum), 0}, + {"NUM_VFS_ACT", data(ResourceArray[0].Actual), 0}, + {"NUM_VPS_MAX", data(ResourceArray[1].Maximum), 0}, + {"NUM_VPS_DEC", data(ResourceArray[1].Decrement), 0}, + {"NUM_VPS_MIN", data(ResourceArray[1].Minimum), 0}, + {"NUM_VPS_ACT", data(ResourceArray[1].Actual), 0}, + {"HOST_CRED_PER_VF_MAX", data(ResourceArray[2].Maximum), 0}, + {"HOST_CRED_PER_VF_DEC", data(ResourceArray[2].Decrement), 0}, + {"HOST_CRED_PER_VF_MIN", data(ResourceArray[2].Minimum), 0}, + {"HOST_CRED_PER_VF_ACT", data(ResourceArray[2].Actual), 0}, + {"HIPRI_QDEPTH_PER_VF_MAX", data(ResourceArray[3].Maximum), 0}, + {"HIPRI_QDEPTH_PER_VF_DEC", data(ResourceArray[3].Decrement), 0}, + {"HIPRI_QDEPTH_PER_VF_MIN", data(ResourceArray[3].Minimum), 0}, + {"HIPRI_QDEPTH_PER_VF_ACT", data(ResourceArray[3].Actual), 0}, + {"TARGETS_MAX", data(ResourceArray[4].Maximum), 0}, + {"TARGETS_DEC", data(ResourceArray[4].Decrement), 0}, + {"TARGETS_MIN", data(ResourceArray[4].Minimum), 0}, + {"TARGETS_ACT", data(ResourceArray[4].Actual), 0}, + {"INITIATORS_MAX", data(ResourceArray[5].Maximum), 0}, + {"INITIATORS_DEC", data(ResourceArray[5].Decrement), 0}, + {"INITIATORS_MIN", data(ResourceArray[5].Minimum), 0}, + {"INITIATORS_ACT", data(ResourceArray[5].Actual), 0}, + {"TGT_CMD_BUFS_PER_VP_MAX", data(ResourceArray[6].Maximum), 0}, + {"TGT_CMD_BUFS_PER_VP_DEC", data(ResourceArray[6].Decrement), 0}, + {"TGT_CMD_BUFS_PER_VP_MIN", data(ResourceArray[6].Minimum), 0}, + {"TGT_CMD_BUFS_PER_VP_ACT", data(ResourceArray[6].Actual), 0}, + {"EXPANDERS_MAX", data(ResourceArray[7].Maximum), 0}, + {"EXPANDERS_DEC", data(ResourceArray[7].Decrement), 0}, + {"EXPANDERS_MIN", data(ResourceArray[7].Minimum), 0}, + {"EXPANDERS_ACT", data(ResourceArray[7].Actual), 0}, + {"PHYS_MAX", data(ResourceArray[8].Maximum), 0}, + {"PHYS_DEC", data(ResourceArray[8].Decrement), 0}, + {"PHYS_MIN", data(ResourceArray[8].Minimum), 0}, + {"PHYS_ACT", data(ResourceArray[8].Actual), 0}, + {"ENCLOSURES_MAX", data(ResourceArray[9].Maximum), 0}, + {"ENCLOSURES_DEC", data(ResourceArray[9].Decrement), 0}, + {"ENCLOSURES_MIN", data(ResourceArray[9].Minimum), 0}, + {"ENCLOSURES_ACT", data(ResourceArray[9].Actual), 0}, + {"RING_BUF_SIZE_MAX", data(ResourceArray[10].Maximum), 0}, + {"RING_BUF_SIZE_DEC", data(ResourceArray[10].Decrement), 0}, + {"RING_BUF_SIZE_MIN", data(ResourceArray[10].Minimum), 0}, + {"RING_BUF_SIZE_ACT", data(ResourceArray[10].Actual), 0}, + {"IR_BUFFER_SIZE_MAX", data(ResourceArray[11].Maximum), 0}, + {"IR_BUFFER_SIZE_DEC", data(ResourceArray[11].Decrement), 0}, + {"IR_BUFFER_SIZE_MIN", data(ResourceArray[11].Minimum), 0}, + {"IR_BUFFER_SIZE_ACT", data(ResourceArray[11].Actual), 0}, + {"NUM_ROUTE_TABLE_ENT_MAX", data(ResourceArray[12].Maximum), 0}, + {"NUM_ROUTE_TABLE_ENT_DEC", data(ResourceArray[12].Decrement), 0}, + {"NUM_ROUTE_TABLE_ENT_MIN", data(ResourceArray[12].Minimum), 0}, + {"NUM_ROUTE_TABLE_ENT_ACT", data(ResourceArray[12].Actual), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage10_t)0)->x, sizeof(((pManufacturingPage10_t)0)->x) + +ITEM manufacturing_page_10_items2[] = +{ + {"PRODSPECIFICINFO", data(ProductSpecificInfo), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage11_SAS2_t)0)->x, sizeof(((pManufacturingPage11_SAS2_t)0)->x) + +ITEM manufacturing_page_11_items2[] = +{ + {"FLASH_TIME", data(FlashTime), 0}, + {"NVS_TIME", data(NVTime), 0}, + {"FLAG", data(Flag), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"HOT_PLUG_TIM_OUT", data(HotPlugTimeout), 0}, + {"RESERVED_0", data(Reserved[0]), OPT}, + {"RESERVED_1", data(Reserved[1]), OPT}, + {"RESERVED_2", data(Reserved[2]), OPT}, + {"MAX_CMD_FRAMES_0", data(MaxCmdFrames[0]), 0}, + {"MAX_CMD_FRAMES_1", data(MaxCmdFrames[1]), 0}, + {"MAX_CMD_FRAMES_2", data(MaxCmdFrames[2]), 0}, + {"MAX_CMD_FRAMES_3", data(MaxCmdFrames[3]), 0}, + {"SYS_REF_CLK", data(SysRefClk), 0}, + {"RESERVED2", data(Reserved2), OPT}, + {"EXT_UART_CLK", data(ExtUartClk), 0}, + {"UART0_FLAGS", data(UartSettings[0].Flags), 0}, + {"UART0_MORE_FLAGS", data(UartSettings[0].MoreFlags), 0}, + {"UART0_TO", data(UartSettings[0].TO), 0}, + {"UART0_BAUD_RATE", data(UartSettings[0].BaudRate), 0}, + {"UART1_FLAGS", data(UartSettings[1].Flags), 0}, + {"UART1_MORE_FLAGS", data(UartSettings[1].MoreFlags), 0}, + {"UART1_TO", data(UartSettings[1].TO), 0}, + {"UART1_BAUD_RATE", data(UartSettings[1].BaudRate), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage12_SAS2_t)0)->x, sizeof(((pManufacturingPage12_SAS2_t)0)->x) + +ITEM manufacturing_page_12_items2[] = +{ + {"COMMON_FLAGS", data(Flags), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"SGPIO_CFG1", data(SGPIOCfg1), 0}, + {"NUM_SGPIO", data(NumSGPIO), 0}, + {"SGPIO_TYPE", data(SGPIOType), 0}, + {"CLK_DIVIDE", data(ClkDivide), 0}, + {"DEFAULT_TX_CTRL", data(DefaultTxCtrl), 0}, + {"SGPIO_PAT_DEF0", data(SGPIOPatDef0), 0}, + {"SGPIO_PAT_DEF1", data(SGPIOPatDef1), 0}, + {"SGPIO_PAT_DEF2", data(SGPIOPatDef2), 0}, + {"SGPIO_PAT_DEF3", data(SGPIOPatDef3), 0}, + {"SGPIO_0_FLAGS", data(SGPIOInfo[0].Flags), 0}, + {"SGPIO_0_BIT_ORDER_0", data(SGPIOInfo[0].BitOrderSelect[0]), 0}, + {"SGPIO_0_BIT_ORDER_1", data(SGPIOInfo[0].BitOrderSelect[1]), 0}, + {"SGPIO_0_BIT_ORDER_2", data(SGPIOInfo[0].BitOrderSelect[2]), 0}, + {"SGPIO_0_BIT_ORDER_3", data(SGPIOInfo[0].BitOrderSelect[3]), 0}, + {"SGPIO_0_BIT_ORDER_4", data(SGPIOInfo[0].BitOrderSelect[4]), 0}, + {"SGPIO_0_BIT_ORDER_5", data(SGPIOInfo[0].BitOrderSelect[5]), 0}, + {"SGPIO_0_BIT_ORDER_6", data(SGPIOInfo[0].BitOrderSelect[6]), 0}, + {"SGPIO_0_BIT_ORDER_7", data(SGPIOInfo[0].BitOrderSelect[7]), 0}, + {"SGPIO_0_BIT_ORDER_8", data(SGPIOInfo[0].BitOrderSelect[8]), 0}, + {"SGPIO_0_BIT_ORDER_9", data(SGPIOInfo[0].BitOrderSelect[9]), 0}, + {"SGPIO_0_BIT_ORDER_10", data(SGPIOInfo[0].BitOrderSelect[10]), 0}, + {"SGPIO_0_BIT_ORDER_11", data(SGPIOInfo[0].BitOrderSelect[11]), 0}, + {"SGPIO_1_FLAGS", data(SGPIOInfo[1].Flags), 0}, + {"SGPIO_1_BIT_ORDER_0", data(SGPIOInfo[1].BitOrderSelect[0]), 0}, + {"SGPIO_1_BIT_ORDER_1", data(SGPIOInfo[1].BitOrderSelect[1]), 0}, + {"SGPIO_1_BIT_ORDER_2", data(SGPIOInfo[1].BitOrderSelect[2]), 0}, + {"SGPIO_1_BIT_ORDER_3", data(SGPIOInfo[1].BitOrderSelect[3]), 0}, + {"SGPIO_1_BIT_ORDER_4", data(SGPIOInfo[1].BitOrderSelect[4]), 0}, + {"SGPIO_1_BIT_ORDER_5", data(SGPIOInfo[1].BitOrderSelect[5]), 0}, + {"SGPIO_1_BIT_ORDER_6", data(SGPIOInfo[1].BitOrderSelect[6]), 0}, + {"SGPIO_1_BIT_ORDER_7", data(SGPIOInfo[1].BitOrderSelect[7]), 0}, + {"SGPIO_1_BIT_ORDER_8", data(SGPIOInfo[1].BitOrderSelect[8]), 0}, + {"SGPIO_1_BIT_ORDER_9", data(SGPIOInfo[1].BitOrderSelect[9]), 0}, + {"SGPIO_1_BIT_ORDER_10", data(SGPIOInfo[1].BitOrderSelect[10]), 0}, + {"SGPIO_1_BIT_ORDER_11", data(SGPIOInfo[1].BitOrderSelect[11]), 0}, + {"SGPIO_2_FLAGS", data(SGPIOInfo[2].Flags), 0}, + {"SGPIO_2_BIT_ORDER_0", data(SGPIOInfo[2].BitOrderSelect[0]), 0}, + {"SGPIO_2_BIT_ORDER_1", data(SGPIOInfo[2].BitOrderSelect[1]), 0}, + {"SGPIO_2_BIT_ORDER_2", data(SGPIOInfo[2].BitOrderSelect[2]), 0}, + {"SGPIO_2_BIT_ORDER_3", data(SGPIOInfo[2].BitOrderSelect[3]), 0}, + {"SGPIO_2_BIT_ORDER_4", data(SGPIOInfo[2].BitOrderSelect[4]), 0}, + {"SGPIO_2_BIT_ORDER_5", data(SGPIOInfo[2].BitOrderSelect[5]), 0}, + {"SGPIO_2_BIT_ORDER_6", data(SGPIOInfo[2].BitOrderSelect[6]), 0}, + {"SGPIO_2_BIT_ORDER_7", data(SGPIOInfo[2].BitOrderSelect[7]), 0}, + {"SGPIO_2_BIT_ORDER_8", data(SGPIOInfo[2].BitOrderSelect[8]), 0}, + {"SGPIO_2_BIT_ORDER_9", data(SGPIOInfo[2].BitOrderSelect[9]), 0}, + {"SGPIO_2_BIT_ORDER_10", data(SGPIOInfo[2].BitOrderSelect[10]), 0}, + {"SGPIO_2_BIT_ORDER_11", data(SGPIOInfo[2].BitOrderSelect[11]), 0}, + {"SGPIO_3_FLAGS", data(SGPIOInfo[3].Flags), 0}, + {"SGPIO_3_BIT_ORDER_0", data(SGPIOInfo[3].BitOrderSelect[0]), 0}, + {"SGPIO_3_BIT_ORDER_1", data(SGPIOInfo[3].BitOrderSelect[1]), 0}, + {"SGPIO_3_BIT_ORDER_2", data(SGPIOInfo[3].BitOrderSelect[2]), 0}, + {"SGPIO_3_BIT_ORDER_3", data(SGPIOInfo[3].BitOrderSelect[3]), 0}, + {"SGPIO_3_BIT_ORDER_4", data(SGPIOInfo[3].BitOrderSelect[4]), 0}, + {"SGPIO_3_BIT_ORDER_5", data(SGPIOInfo[3].BitOrderSelect[5]), 0}, + {"SGPIO_3_BIT_ORDER_6", data(SGPIOInfo[3].BitOrderSelect[6]), 0}, + {"SGPIO_3_BIT_ORDER_7", data(SGPIOInfo[3].BitOrderSelect[7]), 0}, + {"SGPIO_3_BIT_ORDER_8", data(SGPIOInfo[3].BitOrderSelect[8]), 0}, + {"SGPIO_3_BIT_ORDER_9", data(SGPIOInfo[3].BitOrderSelect[9]), 0}, + {"SGPIO_3_BIT_ORDER_10", data(SGPIOInfo[3].BitOrderSelect[10]), 0}, + {"SGPIO_3_BIT_ORDER_11", data(SGPIOInfo[3].BitOrderSelect[11]), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pManufacturingPage13_SAS2_t)0)->x, sizeof(((pManufacturingPage13_SAS2_t)0)->x) + +ITEM manufacturing_page_13_items2[] = +{ + {"NUM_SGPIO_ENTRIES", data(NumSgpioEntries), 0}, + {"RESERVED0", data(Reserved0), OPT}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"SGPIO_0_MASK", data(SGPIOData[0].Mask), 0}, + {"SGPIO_0_SLOT_STATUS", data(SGPIOData[0].SlotStatus), 0}, + {"SGPIO_0_TX_CTRL_0", data(SGPIOData[0].TxControl[0]), 0}, + {"SGPIO_0_TX_CTRL_1", data(SGPIOData[0].TxControl[1]), 0}, + {"SGPIO_0_TX_CTRL_2", data(SGPIOData[0].TxControl[2]), 0}, + {"SGPIO_0_TX_CTRL_3", data(SGPIOData[0].TxControl[3]), 0}, + {"SGPIO_1_MASK", data(SGPIOData[0].Mask), 0}, + {"SGPIO_1_SLOT_STATUS", data(SGPIOData[1].SlotStatus), 0}, + {"SGPIO_1_TX_CTRL_0", data(SGPIOData[1].TxControl[0]), 0}, + {"SGPIO_1_TX_CTRL_1", data(SGPIOData[1].TxControl[1]), 0}, + {"SGPIO_1_TX_CTRL_2", data(SGPIOData[1].TxControl[2]), 0}, + {"SGPIO_1_TX_CTRL_3", data(SGPIOData[1].TxControl[3]), 0}, + {"SGPIO_2_MASK", data(SGPIOData[1].Mask), 0}, + {"SGPIO_2_SLOT_STATUS", data(SGPIOData[2].SlotStatus), 0}, + {"SGPIO_2_TX_CTRL_0", data(SGPIOData[2].TxControl[0]), 0}, + {"SGPIO_2_TX_CTRL_1", data(SGPIOData[2].TxControl[1]), 0}, + {"SGPIO_2_TX_CTRL_2", data(SGPIOData[2].TxControl[2]), 0}, + {"SGPIO_2_TX_CTRL_3", data(SGPIOData[2].TxControl[3]), 0}, + {"SGPIO_3_MASK", data(SGPIOData[3].Mask), 0}, + {"SGPIO_3_SLOT_STATUS", data(SGPIOData[3].SlotStatus), 0}, + {"SGPIO_3_TX_CTRL_0", data(SGPIOData[3].TxControl[0]), 0}, + {"SGPIO_3_TX_CTRL_1", data(SGPIOData[3].TxControl[1]), 0}, + {"SGPIO_3_TX_CTRL_2", data(SGPIOData[3].TxControl[2]), 0}, + {"SGPIO_3_TX_CTRL_3", data(SGPIOData[3].TxControl[3]), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOUnitPage0_t)0)->x, sizeof(((pIOUnitPage0_t)0)->x) + +ITEM io_unit_page_0_items[] = +{ + {"UNIQUE_VALUE", data(UniqueValue), DUP}, + {"UNIQUE_VALUE_LOW", data(UniqueValue.Low), 0}, + {"UNIQUE_VALUE_HI", data(UniqueValue.High), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOUnitPage1_t)0)->x, sizeof(((pIOUnitPage1_t)0)->x) + +ITEM io_unit_page_1_items[] = +{ + {"IO_UNIT_PAGE_1_FLAGS", data(Flags), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOUnitPage2_t)0)->x, sizeof(((pIOUnitPage2_t)0)->x) + +ITEM io_unit_page_2_items[] = +{ + {"IO_UNIT_PAGE_2_FLAGS", data(Flags), 0}, + {"BIOS_VERSION", data(BiosVersion), 0}, + {"PCI_BUS_NUMBER", data(AdapterOrder[0].PciBusNumber), DUP}, + {"PCI_BUS_NUMBER_0", data(AdapterOrder[0].PciBusNumber), 0}, + {"PCI_DEVICE_FUNCTION", data(AdapterOrder[0].PciDeviceAndFunctionNumber), DUP}, + {"PCI_DEVICE_FUNCTION_0", data(AdapterOrder[0].PciDeviceAndFunctionNumber), 0}, + {"ADAPTER_FLAGS", data(AdapterOrder[0].AdapterFlags), DUP}, + {"ADAPTER_FLAGS_0", data(AdapterOrder[0].AdapterFlags), 0}, + {"PCI_BUS_NUMBER_1", data(AdapterOrder[1].PciBusNumber), OPT}, + {"PCI_DEVICE_FUNCTION_1", data(AdapterOrder[1].PciDeviceAndFunctionNumber), OPT}, + {"ADAPTER_FLAGS_1", data(AdapterOrder[1].AdapterFlags), OPT}, + {"PCI_BUS_NUMBER_2", data(AdapterOrder[2].PciBusNumber), OPT}, + {"PCI_DEVICE_FUNCTION_2", data(AdapterOrder[2].PciDeviceAndFunctionNumber), OPT}, + {"ADAPTER_FLAGS_2", data(AdapterOrder[2].AdapterFlags), OPT}, + {"PCI_BUS_NUMBER_3", data(AdapterOrder[3].PciBusNumber), OPT}, + {"PCI_DEVICE_FUNCTION_3", data(AdapterOrder[3].PciDeviceAndFunctionNumber), OPT}, + {"ADAPTER_FLAGS_3", data(AdapterOrder[3].AdapterFlags), OPT}, + {"RESERVED1", data(Reserved1), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOUnitPage3_t)0)->x, sizeof(((pIOUnitPage3_t)0)->x) + +#define io_unit_page_3_size_25 (int)(size_t)&((pIOUnitPage3_t)0)->GPIOVal[8] + +ITEM io_unit_page_3_items[] = +{ + {"GPIOCOUNT", data(GPIOCount), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"GPIOVAL_0", data(GPIOVal[0]), 0}, + {"GPIOVAL_1", data(GPIOVal[1]), 0}, + {"GPIOVAL_2", data(GPIOVal[2]), 0}, + {"GPIOVAL_3", data(GPIOVal[3]), 0}, + {"GPIOVAL_4", data(GPIOVal[4]), 0}, + {"GPIOVAL_5", data(GPIOVal[5]), 0}, + {"GPIOVAL_6", data(GPIOVal[6]), 0}, + {"GPIOVAL_7", data(GPIOVal[7]), 0}, + {"GPIOVAL_8", data(GPIOVal[8]), OPT}, + {"GPIOVAL_9", data(GPIOVal[9]), OPT}, + {"GPIOVAL_10", data(GPIOVal[10]), OPT}, + {"GPIOVAL_11", data(GPIOVal[11]), OPT}, + {"GPIOVAL_12", data(GPIOVal[12]), OPT}, + {"GPIOVAL_13", data(GPIOVal[13]), OPT}, + {"GPIOVAL_14", data(GPIOVal[14]), OPT}, + {"GPIOVAL_15", data(GPIOVal[15]), OPT}, + {"GPIOVAL_16", data(GPIOVal[16]), OPT}, + {"GPIOVAL_17", data(GPIOVal[17]), OPT}, + {"GPIOVAL_18", data(GPIOVal[18]), OPT}, + {"GPIOVAL_19", data(GPIOVal[19]), OPT}, + {"GPIOVAL_20", data(GPIOVal[20]), OPT}, + {"GPIOVAL_21", data(GPIOVal[21]), OPT}, + {"GPIOVAL_22", data(GPIOVal[22]), OPT}, + {"GPIOVAL_23", data(GPIOVal[23]), OPT}, + {"GPIOVAL_24", data(GPIOVal[24]), OPT}, + {"GPIOVAL_25", data(GPIOVal[25]), OPT}, + {"GPIOVAL_26", data(GPIOVal[26]), OPT}, + {"GPIOVAL_27", data(GPIOVal[27]), OPT}, + {"GPIOVAL_28", data(GPIOVal[28]), OPT}, + {"GPIOVAL_29", data(GPIOVal[29]), OPT}, + {"GPIOVAL_30", data(GPIOVal[30]), OPT}, + {"GPIOVAL_31", data(GPIOVal[31]), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOUnitPage4_t)0)->x, sizeof(((pIOUnitPage4_t)0)->x) + +ITEM io_unit_page_4_items[] = +{ + {"IOUNIT_4_RESERVED1", data(Reserved1), OPT}, + {"FWIMAGE_FLAGS", data(FWImageSGE.FlagsLength), 0}, + {"FWIMAGE_64HIGH", data(FWImageSGE.u.Address64.High), 0}, + {"FWIMAGE_64LOW", data(FWImageSGE.u.Address64.Low), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOCPage0_t)0)->x, sizeof(((pIOCPage0_t)0)->x) + +ITEM ioc_page_0_items[] = +{ + {"TOTAL_NV_STORE", data(TotalNVStore), 0}, + {"FREE_NV_STORE", data(FreeNVStore), 0}, + {"VENDOR_ID", data(VendorID), 0}, + {"DEVICE_ID", data(DeviceID), 0}, + {"REVISION_ID", data(RevisionID), 0}, + {"RESERVED", data(Reserved), OPT}, + {"RESERVED_0", data(Reserved[0]), OPT}, + {"RESERVED_1", data(Reserved[1]), OPT}, + {"RESERVED_2", data(Reserved[2]), OPT}, + {"CLASS_CODE", data(ClassCode), 0}, + {"SS_VNDR_ID", data(SubsystemVendorID), 0}, + {"SS_ID", data(SubsystemID), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOCPage1_t)0)->x, sizeof(((pIOCPage1_t)0)->x) + +ITEM ioc_page_1_items[] = +{ + {"IOC_PAGE_1_FLAGS", data(Flags), 0}, + {"COALESCING_TIMEOUT", data(CoalescingTimeout), 0}, + {"COALESCING_DEPTH", data(CoalescingDepth), 0}, + {"PCI_SLOT_NUM", data(PCISlotNum), 0}, + {"RESERVED", data(Reserved), OPT}, + {"RESERVED_0", data(Reserved[0]), OPT}, + {"RESERVED_1", data(Reserved[1]), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pMpi2IOCPage1_t)0)->x, sizeof(((pMpi2IOCPage1_t)0)->x) + +ITEM ioc_page_1_items2[] = +{ + {"IOC_PAGE_1_FLAGS", data(Flags), 0}, + {"COALESCING_TIMEOUT", data(CoalescingTimeout), 0}, + {"COALESCING_DEPTH", data(CoalescingDepth), 0}, + {"PCI_SLOT_NUM", data(PCISlotNum), 0}, + {"PCI_BUS_NUM", data(PCIBusNum), 0}, + {"PCI_DOMAIN_SEGMENT", data(PCIDomainSegment), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOCPage2_t)0)->x, sizeof(((pIOCPage2_t)0)->x) + +ITEM ioc_page_2_items[] = +{ + {"CAP_FLAGS", data(CapabilitiesFlags), 0}, + {"NUM_ACTIVE_VOLS", data(NumActiveVolumes), 0}, + {"MAX_VOLS", data(MaxVolumes), 0}, + {"NUM_ACTIVE_PHYS_DSKS", data(NumActivePhysDisks), 0}, + {"MAX_PHYS_DSKS", data(MaxPhysDisks), 0}, + {"VOL_ID", data(RaidVolume[0].VolumeID), 0}, + {"VOL_BUS", data(RaidVolume[0].VolumeBus), 0}, + {"VOL_IOC", data(RaidVolume[0].VolumeIOC), 0}, + {"VOL_PAGE_NUM", data(RaidVolume[0].VolumePageNumber), 0}, + {"VOL_TYPE", data(RaidVolume[0].VolumeType), 0}, + {"FLAGS", data(RaidVolume[0].Flags), 0}, + {"RESERVED", data(RaidVolume[0].Reserved3), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOCPage3_t)0)->x, sizeof(((pIOCPage3_t)0)->x) + +ITEM ioc_page_3_items[] = +{ + {"NUM_PHYS_DSKS", data(NumPhysDisks), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"PHYS_DSK_ID", data(PhysDisk[0].PhysDiskID), 0}, + {"PHYS_DSK_BUS", data(PhysDisk[0].PhysDiskBus), 0}, + {"PHYS_DSK_IOC", data(PhysDisk[0].PhysDiskIOC), 0}, + {"PHYS_DSE_NUM", data(PhysDisk[0].PhysDiskNum), DUP}, + {"PHYS_DSK_NUM", data(PhysDisk[0].PhysDiskNum), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOCPage4_t)0)->x, sizeof(((pIOCPage4_t)0)->x) + +ITEM ioc_page_4_items[] = +{ + {"ACTIVE_SEP", data(ActiveSEP), 0}, + {"MAX_SEP", data(MaxSEP), 0}, + {"RESERVED", data(Reserved1), OPT}, + {"RESERVED1", data(Reserved1), OPT}, + {"SEP_TARGET_ID", data(SEP[0].SEPTargetID), 0}, + {"SEP_BUS", data(SEP[0].SEPBus), 0}, + {"RESERVED", data(SEP[0].Reserved), OPT}, + {"IOC_4_SEP_RESERVED", data(SEP[0].Reserved), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOCPage5_t)0)->x, sizeof(((pIOCPage5_t)0)->x) + +ITEM ioc_page_5_items[] = +{ + {"RESERVED1", data(Reserved1), OPT}, + {"NUM_HOT_SPARES", data(NumHotSpares), 0}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"PHYS_DSK_NUM", data(HotSpare[0].PhysDiskNum), 0}, + {"RESERVED", data(HotSpare[0].Reserved), OPT}, + {"IOC_5_HOT_SPARE_RESERVED", data(HotSpare[0].Reserved), OPT}, + {"HOT_SPARE_POOL", data(HotSpare[0].HotSparePool), 0}, + {"FLAGS", data(HotSpare[0].Flags), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pIOCPage6_t)0)->x, sizeof(((pIOCPage6_t)0)->x) + +ITEM ioc_page_6_items[] = +{ + {"CAPABILITIES_FLAGS", data(CapabilitiesFlags), OPT}, + {"MAX_DRIVES_IS", data(MaxDrivesIS), OPT}, + {"MAX_DRIVES_IM", data(MaxDrivesIM), OPT}, + {"MAX_DRIVES_IME", data(MaxDrivesIME), OPT}, + {"RESERVED1", data(Reserved1), OPT}, + {"MIN_DRIVES_IS", data(MinDrivesIS), OPT}, + {"MIN_DRIVES_IM", data(MinDrivesIM), OPT}, + {"MIN_DRIVES_IME", data(MinDrivesIME), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"MAX_GLOBAL_HOTSPARES", data(MaxGlobalHotSpares), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"RESERVED4", data(Reserved4), OPT}, + {"RESERVED5", data(Reserved5), OPT}, + {"SUPPORTED_STRIPE_SIZE_MAP_IS", data(SupportedStripeSizeMapIS), OPT}, + {"SUPPORTED_STRIPE_SIZE_MAP_IME", data(SupportedStripeSizeMapIME), OPT}, + {"RESERVED6", data(Reserved6), OPT}, + {"METADATA_SIZE", data(MetadataSize), OPT}, + {"RESERVED7", data(Reserved7), OPT}, + {"RESERVED8", data(Reserved8), OPT}, + {"MAX_BAD_BLOCK_TABLE_ENTRIES", data(MaxBadBlockTableEntries), OPT}, + {"RESERVED9", data(Reserved9), OPT}, + {"IR_NVSRAM_USAGE", data(IRNvsramUsage), OPT}, + {"RESERVED10", data(Reserved10), OPT}, + {"IR_NVSRAM_VERSION", data(IRNvsramVersion), OPT}, + {"RESERVED11", data(Reserved11), OPT}, + {"RESERVED12", data(Reserved12), OPT}, + {"ALL", sizeof(ConfigPageHeader_t), sizeof(IOCPage6_t) - sizeof(ConfigPageHeader_t), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pMpi2IOCPage8_t)0)->x, sizeof(((pMpi2IOCPage8_t)0)->x) + +ITEM ioc_page_8_items2[] = +{ + {"NUM_DEVS_PER_ENCL", data(NumDevsPerEnclosure), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"MAX_PERSIST_ENTRIES", data(MaxPersistentEntries), 0}, + {"MAX_NUM_PHYS_MAPPED_IDS", data(MaxNumPhysicalMappedIDs), 0}, + {"FLAGS", data(Flags), 0}, + {"RESERVED3", data(Reserved3), OPT}, + {"IR_VOLUME_MAPPING_FLAGS", data(IRVolumeMappingFlags), 0}, + {"RESERVED4", data(Reserved4), OPT}, + {"RESERVED5", data(Reserved5), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasIOUnitPage0_t)0)->x, sizeof(((pSasIOUnitPage0_t)0)->x) + +ITEM sas_io_unit_page_0_items[] = +{ + {"NVDATA_VER_DEFAULT", data(NvdataVersionDefault), 0}, + {"NVDATA_VER_PERSISTENT", data(NvdataVersionPersistent), 0}, + {"NUM_PHYS", data(NumPhys), 0}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED1", data(Reserved3), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"PORT", data(PhyData[0].Port), 0}, + {"PORT_FLGS", data(PhyData[0].PortFlags), 0}, + {"PHY_FLGS", data(PhyData[0].PhyFlags), 0}, + {"NEGOT_LINK_RATE", data(PhyData[0].NegotiatedLinkRate), 0}, + {"CNTLR_PHY_DEV_INFO", data(PhyData[0].ControllerPhyDeviceInfo), 0}, + {"ATTCH_DEV_HNDL", data(PhyData[0].AttachedDeviceHandle), 0}, + {"CNTLR_DEV_HNDL", data(PhyData[0].ControllerDevHandle), 0}, + {"SAS0_DISCOVERYSTATUS", data(PhyData[0].DiscoveryStatus), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasIOUnitPage1_t)0)->x, sizeof(((pSasIOUnitPage1_t)0)->x) + +ITEM sas_io_unit_page_1_items[] = +{ + {"CONTROLFLAGS", data(ControlFlags), 0}, + {"MAXSATATARGETS", data(MaxNumSATATargets), 0}, + {"ADDCONTROLFLAGS", data(AdditionalControlFlags), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"NUM_PHYS", data(NumPhys), 0}, + {"SATAMAXQDEPTH", data(SATAMaxQDepth), 0}, + {"REPDEVMISSINGDELAY", data(ReportDeviceMissingDelay), 0}, + {"IODEVMISSINGDELAY", data(IODeviceMissingDelay), 0}, + {"Port", data(PhyData[0].Port), DUP}, + {"SAS_IO_UNIT1_PHY_0_PORT", data(PhyData[0].Port), 0}, + {"Port_Flgs", data(PhyData[0].PortFlags), DUP}, + {"SAS_IO_UNIT1_PHY_0_PORT_FLGS", data(PhyData[0].PortFlags), 0}, + {"PHY_FLGS", data(PhyData[0].PhyFlags), DUP}, + {"SAS_IO_UNIT1_PHY_0_PHY_FLGS", data(PhyData[0].PhyFlags), 0}, + {"MIN_MAX_LINK_RATE", data(PhyData[0].MaxMinLinkRate), DUP}, + {"SAS_IO_UNIT1_PHY_0_MIN_MAX_LINK_RATE", data(PhyData[0].MaxMinLinkRate), 0}, + {"CNTLR_PHY_DEV_INFO", data(PhyData[0].ControllerPhyDeviceInfo), DUP}, + {"SAS_IO_UNIT1_PHY_0_CNTLR_PHY_DEV_INFO", data(PhyData[0].ControllerPhyDeviceInfo), 0}, + {"MAX_TARG_PORT_CONN_TIME", data(PhyData[0].MaxTargetPortConnectTime), DUP}, + {"SAS_IO_UNIT1_PHY_0_MAX_TARG_PORT_CONN_TIME", data(PhyData[0].MaxTargetPortConnectTime), 0}, + {"RESERVED", data(PhyData[0].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_0_RESERVED1", data(PhyData[0].Reserved1), OPT}, + {"Port", data(PhyData[1].Port), DUP}, + {"SAS_IO_UNIT1_PHY_1_PORT", data(PhyData[1].Port), 0}, + {"Port_Flgs", data(PhyData[1].PortFlags), DUP}, + {"SAS_IO_UNIT1_PHY_1_PORT_FLGS", data(PhyData[1].PortFlags), 0}, + {"PHY_FLGS", data(PhyData[1].PhyFlags), DUP}, + {"SAS_IO_UNIT1_PHY_1_PHY_FLGS", data(PhyData[1].PhyFlags), 0}, + {"MIN_MAX_LINK_RATE", data(PhyData[1].MaxMinLinkRate), DUP}, + {"SAS_IO_UNIT1_PHY_1_MIN_MAX_LINK_RATE", data(PhyData[1].MaxMinLinkRate), 0}, + {"CNTLR_PHY_DEV_INFO", data(PhyData[1].ControllerPhyDeviceInfo), DUP}, + {"SAS_IO_UNIT1_PHY_1_CNTLR_PHY_DEV_INFO", data(PhyData[1].ControllerPhyDeviceInfo), 0}, + {"MAX_TARG_PORT_CONN_TIME", data(PhyData[1].MaxTargetPortConnectTime), DUP}, + {"SAS_IO_UNIT1_PHY_1_MAX_TARG_PORT_CONN_TIME", data(PhyData[1].MaxTargetPortConnectTime), 0}, + {"RESERVED", data(PhyData[1].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_1_RESERVED1", data(PhyData[1].Reserved1), OPT}, + {"Port", data(PhyData[2].Port), DUP}, + {"SAS_IO_UNIT1_PHY_2_PORT", data(PhyData[2].Port), 0}, + {"Port_Flgs", data(PhyData[2].PortFlags), DUP}, + {"SAS_IO_UNIT1_PHY_2_PORT_FLGS", data(PhyData[2].PortFlags), 0}, + {"PHY_FLGS", data(PhyData[2].PhyFlags), DUP}, + {"SAS_IO_UNIT1_PHY_2_PHY_FLGS", data(PhyData[2].PhyFlags), 0}, + {"MIN_MAX_LINK_RATE", data(PhyData[2].MaxMinLinkRate), DUP}, + {"SAS_IO_UNIT1_PHY_2_MIN_MAX_LINK_RATE", data(PhyData[2].MaxMinLinkRate), 0}, + {"CNTLR_PHY_DEV_INFO", data(PhyData[2].ControllerPhyDeviceInfo), DUP}, + {"SAS_IO_UNIT1_PHY_2_CNTLR_PHY_DEV_INFO", data(PhyData[2].ControllerPhyDeviceInfo), 0}, + {"MAX_TARG_PORT_CONN_TIME", data(PhyData[2].MaxTargetPortConnectTime), DUP}, + {"SAS_IO_UNIT1_PHY_2_MAX_TARG_PORT_CONN_TIME", data(PhyData[2].MaxTargetPortConnectTime), 0}, + {"RESERVED", data(PhyData[2].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_2_RESERVED1", data(PhyData[2].Reserved1), OPT}, + {"Port", data(PhyData[3].Port), DUP}, + {"SAS_IO_UNIT1_PHY_3_PORT", data(PhyData[3].Port), 0}, + {"Port_Flgs", data(PhyData[3].PortFlags), DUP}, + {"SAS_IO_UNIT1_PHY_3_PORT_FLGS", data(PhyData[3].PortFlags), 0}, + {"PHY_FLGS", data(PhyData[3].PhyFlags), DUP}, + {"SAS_IO_UNIT1_PHY_3_PHY_FLGS", data(PhyData[3].PhyFlags), 0}, + {"MIN_MAX_LINK_RATE", data(PhyData[3].MaxMinLinkRate), DUP}, + {"SAS_IO_UNIT1_PHY_3_MIN_MAX_LINK_RATE", data(PhyData[3].MaxMinLinkRate), 0}, + {"CNTLR_PHY_DEV_INFO", data(PhyData[3].ControllerPhyDeviceInfo), DUP}, + {"SAS_IO_UNIT1_PHY_3_CNTLR_PHY_DEV_INFO", data(PhyData[3].ControllerPhyDeviceInfo), 0}, + {"MAX_TARG_PORT_CONN_TIME", data(PhyData[3].MaxTargetPortConnectTime), DUP}, + {"SAS_IO_UNIT1_PHY_3_MAX_TARG_PORT_CONN_TIME", data(PhyData[3].MaxTargetPortConnectTime), 0}, + {"RESERVED", data(PhyData[3].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_3_RESERVED1", data(PhyData[3].Reserved1), OPT}, + {"Port", data(PhyData[4].Port), DUP}, + {"SAS_IO_UNIT1_PHY_4_PORT", data(PhyData[4].Port), 0}, + {"Port_Flgs", data(PhyData[4].PortFlags), DUP}, + {"SAS_IO_UNIT1_PHY_4_PORT_FLGS", data(PhyData[4].PortFlags), 0}, + {"PHY_FLGS", data(PhyData[4].PhyFlags), DUP}, + {"SAS_IO_UNIT1_PHY_4_PHY_FLGS", data(PhyData[4].PhyFlags), 0}, + {"MIN_MAX_LINK_RATE", data(PhyData[4].MaxMinLinkRate), DUP}, + {"SAS_IO_UNIT1_PHY_4_MIN_MAX_LINK_RATE", data(PhyData[4].MaxMinLinkRate), 0}, + {"CNTLR_PHY_DEV_INFO", data(PhyData[4].ControllerPhyDeviceInfo), DUP}, + {"SAS_IO_UNIT1_PHY_4_CNTLR_PHY_DEV_INFO", data(PhyData[4].ControllerPhyDeviceInfo), 0}, + {"MAX_TARG_PORT_CONN_TIME", data(PhyData[4].MaxTargetPortConnectTime), DUP}, + {"SAS_IO_UNIT1_PHY_4_MAX_TARG_PORT_CONN_TIME", data(PhyData[4].MaxTargetPortConnectTime), 0}, + {"RESERVED", data(PhyData[4].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_4_RESERVED1", data(PhyData[4].Reserved1), OPT}, + {"Port", data(PhyData[5].Port), DUP}, + {"SAS_IO_UNIT1_PHY_5_PORT", data(PhyData[5].Port), 0}, + {"Port_Flgs", data(PhyData[5].PortFlags), DUP}, + {"SAS_IO_UNIT1_PHY_5_PORT_FLGS", data(PhyData[5].PortFlags), 0}, + {"PHY_FLGS", data(PhyData[5].PhyFlags), DUP}, + {"SAS_IO_UNIT1_PHY_5_PHY_FLGS", data(PhyData[5].PhyFlags), 0}, + {"MIN_MAX_LINK_RATE", data(PhyData[5].MaxMinLinkRate), DUP}, + {"SAS_IO_UNIT1_PHY_5_MIN_MAX_LINK_RATE", data(PhyData[5].MaxMinLinkRate), 0}, + {"CNTLR_PHY_DEV_INFO", data(PhyData[5].ControllerPhyDeviceInfo), DUP}, + {"SAS_IO_UNIT1_PHY_5_CNTLR_PHY_DEV_INFO", data(PhyData[5].ControllerPhyDeviceInfo), 0}, + {"MAX_TARG_PORT_CONN_TIME", data(PhyData[5].MaxTargetPortConnectTime), DUP}, + {"SAS_IO_UNIT1_PHY_5_MAX_TARG_PORT_CONN_TIME", data(PhyData[5].MaxTargetPortConnectTime), 0}, + {"RESERVED", data(PhyData[5].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_5_RESERVED1", data(PhyData[5].Reserved1), OPT}, + {"Port", data(PhyData[6].Port), DUP}, + {"SAS_IO_UNIT1_PHY_6_PORT", data(PhyData[6].Port), 0}, + {"Port_Flgs", data(PhyData[6].PortFlags), DUP}, + {"SAS_IO_UNIT1_PHY_6_PORT_FLGS", data(PhyData[6].PortFlags), 0}, + {"PHY_FLGS", data(PhyData[6].PhyFlags), DUP}, + {"SAS_IO_UNIT1_PHY_6_PHY_FLGS", data(PhyData[6].PhyFlags), 0}, + {"MIN_MAX_LINK_RATE", data(PhyData[6].MaxMinLinkRate), DUP}, + {"SAS_IO_UNIT1_PHY_6_MIN_MAX_LINK_RATE", data(PhyData[6].MaxMinLinkRate), 0}, + {"CNTLR_PHY_DEV_INFO", data(PhyData[6].ControllerPhyDeviceInfo), DUP}, + {"SAS_IO_UNIT1_PHY_6_CNTLR_PHY_DEV_INFO", data(PhyData[6].ControllerPhyDeviceInfo), 0}, + {"MAX_TARG_PORT_CONN_TIME", data(PhyData[6].MaxTargetPortConnectTime), DUP}, + {"SAS_IO_UNIT1_PHY_6_MAX_TARG_PORT_CONN_TIME", data(PhyData[6].MaxTargetPortConnectTime), 0}, + {"RESERVED", data(PhyData[6].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_6_RESERVED1", data(PhyData[6].Reserved1), OPT}, + {"Port", data(PhyData[7].Port), DUP}, + {"SAS_IO_UNIT1_PHY_7_PORT", data(PhyData[7].Port), 0}, + {"Port_Flgs", data(PhyData[7].PortFlags), DUP}, + {"SAS_IO_UNIT1_PHY_7_PORT_FLGS", data(PhyData[7].PortFlags), 0}, + {"PHY_FLGS", data(PhyData[7].PhyFlags), DUP}, + {"SAS_IO_UNIT1_PHY_7_PHY_FLGS", data(PhyData[7].PhyFlags), 0}, + {"MIN_MAX_LINK_RATE", data(PhyData[7].MaxMinLinkRate), DUP}, + {"SAS_IO_UNIT1_PHY_7_MIN_MAX_LINK_RATE", data(PhyData[7].MaxMinLinkRate), 0}, + {"CNTLR_PHY_DEV_INFO", data(PhyData[7].ControllerPhyDeviceInfo), DUP}, + {"SAS_IO_UNIT1_PHY_7_CNTLR_PHY_DEV_INFO", data(PhyData[7].ControllerPhyDeviceInfo), 0}, + {"MAX_TARG_PORT_CONN_TIME", data(PhyData[7].MaxTargetPortConnectTime), DUP}, + {"SAS_IO_UNIT1_PHY_7_MAX_TARG_PORT_CONN_TIME", data(PhyData[7].MaxTargetPortConnectTime), 0}, + {"RESERVED", data(PhyData[7].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_7_RESERVED1", data(PhyData[7].Reserved1), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pMpi2SasIOUnitPage1_t)0)->x, sizeof(((pMpi2SasIOUnitPage1_t)0)->x) + +ITEM sas_io_unit_page_1_items2[] = +{ + {"CONTROLFLAGS", data(ControlFlags), 0}, + {"SASNARROWMAXQDEPTH", data(SASNarrowMaxQueueDepth), 0}, + {"ADDCONTROLFLAGS", data(AdditionalControlFlags), 0}, + {"SASWIDEMAXQDEPTH", data(SASWideMaxQueueDepth), 0}, + {"NUM_PHYS", data(NumPhys), 0}, + {"SATAMAXQDEPTH", data(SATAMaxQDepth), 0}, + {"REPDEVMISSINGDELAY", data(ReportDeviceMissingDelay), 0}, + {"IODEVMISSINGDELAY", data(IODeviceMissingDelay), 0}, + {"SAS_IO_UNIT1_PHY_0_PORT", data(PhyData[0].Port), 0}, + {"SAS_IO_UNIT1_PHY_0_PORT_FLGS", data(PhyData[0].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_0_PHY_FLGS", data(PhyData[0].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_0_MIN_MAX_LINK_RATE", data(PhyData[0].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_0_CNTLR_PHY_DEV_INFO", data(PhyData[0].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_0_MAX_TARG_PORT_CONN_TIME", data(PhyData[0].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_0_RESERVED1", data(PhyData[0].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_1_PORT", data(PhyData[1].Port), 0}, + {"SAS_IO_UNIT1_PHY_1_PORT_FLGS", data(PhyData[1].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_1_PHY_FLGS", data(PhyData[1].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_1_MIN_MAX_LINK_RATE", data(PhyData[1].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_1_CNTLR_PHY_DEV_INFO", data(PhyData[1].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_1_MAX_TARG_PORT_CONN_TIME", data(PhyData[1].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_1_RESERVED1", data(PhyData[1].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_2_PORT", data(PhyData[2].Port), 0}, + {"SAS_IO_UNIT1_PHY_2_PORT_FLGS", data(PhyData[2].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_2_PHY_FLGS", data(PhyData[2].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_2_MIN_MAX_LINK_RATE", data(PhyData[2].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_2_CNTLR_PHY_DEV_INFO", data(PhyData[2].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_2_MAX_TARG_PORT_CONN_TIME", data(PhyData[2].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_2_RESERVED1", data(PhyData[2].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_3_PORT", data(PhyData[3].Port), 0}, + {"SAS_IO_UNIT1_PHY_3_PORT_FLGS", data(PhyData[3].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_3_PHY_FLGS", data(PhyData[3].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_3_MIN_MAX_LINK_RATE", data(PhyData[3].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_3_CNTLR_PHY_DEV_INFO", data(PhyData[3].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_3_MAX_TARG_PORT_CONN_TIME", data(PhyData[3].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_3_RESERVED1", data(PhyData[3].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_4_PORT", data(PhyData[4].Port), 0}, + {"SAS_IO_UNIT1_PHY_4_PORT_FLGS", data(PhyData[4].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_4_PHY_FLGS", data(PhyData[4].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_4_MIN_MAX_LINK_RATE", data(PhyData[4].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_4_CNTLR_PHY_DEV_INFO", data(PhyData[4].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_4_MAX_TARG_PORT_CONN_TIME", data(PhyData[4].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_4_RESERVED1", data(PhyData[4].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_5_PORT", data(PhyData[5].Port), 0}, + {"SAS_IO_UNIT1_PHY_5_PORT_FLGS", data(PhyData[5].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_5_PHY_FLGS", data(PhyData[5].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_5_MIN_MAX_LINK_RATE", data(PhyData[5].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_5_CNTLR_PHY_DEV_INFO", data(PhyData[5].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_5_MAX_TARG_PORT_CONN_TIME", data(PhyData[5].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_5_RESERVED1", data(PhyData[5].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_6_PORT", data(PhyData[6].Port), 0}, + {"SAS_IO_UNIT1_PHY_6_PORT_FLGS", data(PhyData[6].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_6_PHY_FLGS", data(PhyData[6].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_6_MIN_MAX_LINK_RATE", data(PhyData[6].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_6_CNTLR_PHY_DEV_INFO", data(PhyData[6].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_6_MAX_TARG_PORT_CONN_TIME", data(PhyData[6].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_6_RESERVED1", data(PhyData[6].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_7_PORT", data(PhyData[7].Port), 0}, + {"SAS_IO_UNIT1_PHY_7_PORT_FLGS", data(PhyData[7].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_7_PHY_FLGS", data(PhyData[7].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_7_MIN_MAX_LINK_RATE", data(PhyData[7].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_7_CNTLR_PHY_DEV_INFO", data(PhyData[7].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_7_MAX_TARG_PORT_CONN_TIME", data(PhyData[7].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_7_RESERVED1", data(PhyData[7].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_8_PORT", data(PhyData[8].Port), 0}, + {"SAS_IO_UNIT1_PHY_8_PORT_FLGS", data(PhyData[8].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_8_PHY_FLGS", data(PhyData[8].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_8_MIN_MAX_LINK_RATE", data(PhyData[8].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_8_CNTLR_PHY_DEV_INFO", data(PhyData[8].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_8_MAX_TARG_PORT_CONN_TIME", data(PhyData[8].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_8_RESERVED1", data(PhyData[8].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_9_PORT", data(PhyData[9].Port), 0}, + {"SAS_IO_UNIT1_PHY_9_PORT_FLGS", data(PhyData[9].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_9_PHY_FLGS", data(PhyData[9].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_9_MIN_MAX_LINK_RATE", data(PhyData[9].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_9_CNTLR_PHY_DEV_INFO", data(PhyData[9].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_9_MAX_TARG_PORT_CONN_TIME", data(PhyData[9].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_9_RESERVED1", data(PhyData[9].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_10_PORT", data(PhyData[10].Port), 0}, + {"SAS_IO_UNIT1_PHY_10_PORT_FLGS", data(PhyData[10].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_10_PHY_FLGS", data(PhyData[10].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_10_MIN_MAX_LINK_RATE", data(PhyData[10].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_10_CNTLR_PHY_DEV_INFO", data(PhyData[10].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_10_MAX_TARG_PORT_CONN_TIME", data(PhyData[10].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_10_RESERVED1", data(PhyData[10].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_11_PORT", data(PhyData[11].Port), 0}, + {"SAS_IO_UNIT1_PHY_11_PORT_FLGS", data(PhyData[11].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_11_PHY_FLGS", data(PhyData[11].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_11_MIN_MAX_LINK_RATE", data(PhyData[11].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_11_CNTLR_PHY_DEV_INFO", data(PhyData[11].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_11_MAX_TARG_PORT_CONN_TIME", data(PhyData[11].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_11_RESERVED1", data(PhyData[11].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_12_PORT", data(PhyData[12].Port), 0}, + {"SAS_IO_UNIT1_PHY_12_PORT_FLGS", data(PhyData[12].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_12_PHY_FLGS", data(PhyData[12].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_12_MIN_MAX_LINK_RATE", data(PhyData[12].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_12_CNTLR_PHY_DEV_INFO", data(PhyData[12].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_12_MAX_TARG_PORT_CONN_TIME", data(PhyData[12].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_12_RESERVED1", data(PhyData[12].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_13_PORT", data(PhyData[13].Port), 0}, + {"SAS_IO_UNIT1_PHY_13_PORT_FLGS", data(PhyData[13].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_13_PHY_FLGS", data(PhyData[13].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_13_MIN_MAX_LINK_RATE", data(PhyData[13].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_13_CNTLR_PHY_DEV_INFO", data(PhyData[13].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_13_MAX_TARG_PORT_CONN_TIME", data(PhyData[13].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_13_RESERVED1", data(PhyData[13].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_14_PORT", data(PhyData[14].Port), 0}, + {"SAS_IO_UNIT1_PHY_14_PORT_FLGS", data(PhyData[14].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_14_PHY_FLGS", data(PhyData[14].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_14_MIN_MAX_LINK_RATE", data(PhyData[14].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_14_CNTLR_PHY_DEV_INFO", data(PhyData[14].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_14_MAX_TARG_PORT_CONN_TIME", data(PhyData[14].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_14_RESERVED1", data(PhyData[14].Reserved1), OPT}, + {"SAS_IO_UNIT1_PHY_15_PORT", data(PhyData[15].Port), 0}, + {"SAS_IO_UNIT1_PHY_15_PORT_FLGS", data(PhyData[15].PortFlags), 0}, + {"SAS_IO_UNIT1_PHY_15_PHY_FLGS", data(PhyData[15].PhyFlags), 0}, + {"SAS_IO_UNIT1_PHY_15_MIN_MAX_LINK_RATE", data(PhyData[15].MaxMinLinkRate), 0}, + {"SAS_IO_UNIT1_PHY_15_CNTLR_PHY_DEV_INFO", data(PhyData[15].ControllerPhyDeviceInfo), 0}, + {"SAS_IO_UNIT1_PHY_15_MAX_TARG_PORT_CONN_TIME", data(PhyData[15].MaxTargetPortConnectTime), 0}, + {"SAS_IO_UNIT1_PHY_15_RESERVED1", data(PhyData[15].Reserved1), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasIOUnitPage2_t)0)->x, sizeof(((pSasIOUnitPage2_t)0)->x) + +ITEM sas_io_unit_page_2_items[] = +{ + {"SAS2_NUMDEVICESPERENCLOSURE", data(NumDevsPerEnclosure), 0}, + {"MAX_PERSIST_IDS", data(MaxPersistentIDs), 0}, + {"MAX_PERSIST_IDS_USED", data(NumPersistentIDsUsed), 0}, + {"STATUS", data(Status), 0}, + {"FLAGS", data(Flags), 0}, + {"SAS2_MAXNUMPHYMAPPEDID", data(MaxNumPhysicalMappedIDs), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasIOUnitPage3_t)0)->x, sizeof(((pSasIOUnitPage3_t)0)->x) + +ITEM sas_io_unit_page_3_items[] = +{ + {"RESERVED1", data(Reserved1), OPT}, + {"MAX_INVALID_DWRD_CNT", data(MaxInvalidDwordCount), 0}, + {"INVALID_DWRD_CNT_TIME", data(InvalidDwordCountTime), 0}, + {"MAX_RUNNING_DISPARE_ERR_CNT", data(MaxRunningDisparityErrorCount), 0}, + {"RUNNING_DISPARE_ERR_TIME", data(RunningDisparityErrorTime), 0}, + {"MAX_LOSS_DWRD_SYNC_CNT", data(MaxLossDwordSynchCount), 0}, + {"LOSS_DWRD_SYNC_CNT_TIME", data(LossDwordSynchCountTime), 0}, + {"MAX_PHY_RESET_PROB_CNT", data(MaxPhyResetProblemCount), 0}, + {"PHY_RESET_PROB_TIME", data(PhyResetProblemTime), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pMpi2SasIOUnitPage4_t)0)->x, sizeof(((pMpi2SasIOUnitPage4_t)0)->x) + +ITEM sas_io_unit_page_4_items2[] = +{ + {"GROUP0_MAX_TARGET_SPINUP", data(SpinupGroupParameters[0].MaxTargetSpinup), 0}, + {"GROUP0_SPINUP_DELAY", data(SpinupGroupParameters[0].SpinupDelay), 0}, + {"GROUP0_RESERVED1", data(SpinupGroupParameters[0].Reserved1), OPT}, + {"GROUP1_MAX_TARGET_SPINUP", data(SpinupGroupParameters[1].MaxTargetSpinup), 0}, + {"GROUP1_SPINUP_DELAY", data(SpinupGroupParameters[1].SpinupDelay), 0}, + {"GROUP1_RESERVED1", data(SpinupGroupParameters[1].Reserved1), OPT}, + {"GROUP2_MAX_TARGET_SPINUP", data(SpinupGroupParameters[2].MaxTargetSpinup), 0}, + {"GROUP2_SPINUP_DELAY", data(SpinupGroupParameters[2].SpinupDelay), 0}, + {"GROUP2_RESERVED1", data(SpinupGroupParameters[2].Reserved1), OPT}, + {"GROUP3_MAX_TARGET_SPINUP", data(SpinupGroupParameters[3].MaxTargetSpinup), 0}, + {"GROUP3_SPINUP_DELAY", data(SpinupGroupParameters[3].SpinupDelay), 0}, + {"GROUP3_RESERVED1", data(SpinupGroupParameters[3].Reserved1), OPT}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"RESERVED4", data(Reserved4), OPT}, + {"NUM_PHYS", data(NumPhys), 0}, + {"PE_INIT_SPINUP_DELAY", data(PEInitialSpinupDelay), 0}, + {"PE_REPLY_DELAY", data(PEReplyDelay), 0}, + {"FLAGS", data(Flags), 0}, + {"PHY_0", data(PHY[0]), 0}, + {"PHY_1", data(PHY[1]), 0}, + {"PHY_2", data(PHY[2]), 0}, + {"PHY_3", data(PHY[3]), 0}, + {"PHY_4", data(PHY[4]), 0}, + {"PHY_5", data(PHY[5]), 0}, + {"PHY_6", data(PHY[6]), 0}, + {"PHY_7", data(PHY[7]), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasExpanderPage0_t)0)->x, sizeof(((pSasExpanderPage0_t)0)->x) + +ITEM sas_expander_page_0_items[] = +{ + {"SAS_EXP0_PHYSICALPORT", data(PhysicalPort), 0}, + {"SAS_EXP0_ENCLOSUREHANDLE", data(EnclosureHandle), 0}, + {"SASADRSHIGH", data(SASAddress.High), 0}, + {"SASADRSLOW", data(SASAddress.Low), 0}, + {"SAS_EXP0_DISCOVERYSTATUS", data(DiscoveryStatus), 0}, + {"DEVHNDL", data(DevHandle), 0}, + {"PARENTDEVHNDL", data(ParentDevHandle), 0}, + {"EXPNDRCHGCNT", data(ExpanderChangeCount), 0}, + {"EXPNDRROUTEINDX", data(ExpanderRouteIndexes), 0}, + {"NUMPHYS", data(NumPhys), 0}, + {"SASLEVEL", data(SASLevel), 0}, + {"FLAGS", data(Flags), 0}, + {"DISCOVERYSTATUS", data(Reserved3), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasExpanderPage1_t)0)->x, sizeof(((pSasExpanderPage1_t)0)->x) + +ITEM sas_expander_page_1_items[] = +{ + {"SAS_EXP1_PHYSICALPORT", data(PhysicalPort), 0}, + {"NUMPHYS", data(NumPhys), 0}, + {"PHY", data(Phy), 0}, + {"SAS_EXP1_NUMTBLENTRIESPROG", data(NumTableEntriesProgrammed), 0}, + {"PROGLINKRATE", data(ProgrammedLinkRate), 0}, + {"HWLINKRATE", data(HwLinkRate), 0}, + {"ATTCHDDEVHANDLE", data(AttachedDevHandle), 0}, + {"PHYINFO", data(PhyInfo), 0}, + {"ATTCHDDEVINFO", data(AttachedDeviceInfo), 0}, + {"OWNERDEVHNDL", data(OwnerDevHandle), 0}, + {"CHGCNT", data(ChangeCount), 0}, + {"NEGLNKRATE", data(NegotiatedLinkRate), 0}, + {"PHYIDENTIFIER", data(PhyIdentifier), 0}, + {"ATTCHDPHYIDENT", data(AttachedPhyIdentifier), 0}, + {"RESERVED3", data(Reserved3), OPT}, + {"DISCOVERYInfo", data(DiscoveryInfo), DUP}, + {"DISCOVERYINFO", data(DiscoveryInfo), 0}, + {"RESERVED4", data(Reserved4), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasDevicePage0_t)0)->x, sizeof(((pSasDevicePage0_t)0)->x) + +ITEM sas_device_page_0_items[] = +{ + {"SLOT", data(Slot), 0}, + {"ENCLOSURE_HANDLE", data(EnclosureHandle), 0}, + {"SASADRSHIGH", data(SASAddress.High), 0}, + {"SASADRSLOW", data(SASAddress.Low), 0}, + {"SAS_DEV0_PARENTDEVHANDLE", data(ParentDevHandle), 0}, + {"SAS_DEV0_PHYNUM", data(PhyNum), 0}, + {"SAS_DEV0_ACCESSSTATUS", data(AccessStatus), 0}, + {"DEVHNDL", data(DevHandle), 0}, + {"TARGETID", data(TargetID), 0}, + {"BUS", data(Bus), 0}, + {"DEVICEINFO", data(DeviceInfo), 0}, + {"FLAGS", data(Flags), 0}, + {"RESERVED2", data(Reserved2), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasDevicePage1_t)0)->x, sizeof(((pSasDevicePage1_t)0)->x) + +ITEM sas_device_page_1_items[] = +{ + {"RESERVED1", data(Reserved1), OPT}, + {"SASADRSHIGH", data(SASAddress.High), 0}, + {"SASADRSLOW", data(SASAddress.Low), 0}, + {"RESERVED2", data(Reserved2), OPT}, + {"DEVHNDL", data(DevHandle), 0}, + {"TARGETID", data(TargetID), 0}, + {"BUS", data(Bus), 0}, + {"INITREGDEVICEFIS", data(InitialRegDeviceFIS), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasDevicePage2_t)0)->x, sizeof(((pSasDevicePage2_t)0)->x) + +ITEM sas_device_page_2_items[] = +{ + {"SAS_DEV2_PHYSICALIDHIGH", data(PhysicalIdentifier.High), 0}, + {"SAS_DEV2_PHYSICALIDLOW", data(PhysicalIdentifier.Low), 0}, + {"SAS_DEV2_ENCLOSURE_MAPPING", data(EnclosureMapping), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasPhyPage0_t)0)->x, sizeof(((pSasPhyPage0_t)0)->x) + +ITEM sas_phy_page_0_items[] = +{ + {"SAS_PHY0_OWNER_DEV_HANDLE", data(OwnerDevHandle), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"SASADRSHIGH", data(SASAddress.High), 0}, + {"SASADRSLOW", data(SASAddress.Low), 0}, + {"ATTCHDDEVHNDL", data(AttachedDevHandle), 0}, + {"ATTCHDPHYIDENTIFIER", data(AttachedPhyIdentifier), 0}, + {"RESERVED2", data(Reserved2), OPT}, + {"ATTCHDDEVINFO", data(AttachedDeviceInfo), 0}, + {"PRGMDLINKRATE", data(ProgrammedLinkRate), 0}, + {"HWLINKRATE", data(HwLinkRate), 0}, + {"CHNGCOUNT", data(ChangeCount), 0}, + {"SAS_PHY0_FLAGS", data(Flags), 0}, + {"PHYINFO", data(PhyInfo), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasPhyPage1_t)0)->x, sizeof(((pSasPhyPage1_t)0)->x) + +ITEM sas_phy_page_1_items[] = +{ + {"RESERVED1", data(Reserved1), OPT}, + {"INVALIDDWRDCNT", data(InvalidDwordCount), 0}, + {"RUNNGDISPARITYERRCNT", data(RunningDisparityErrorCount), 0}, + {"LOSSDWRDSYNCCNT", data(LossDwordSynchCount), 0}, + {"PHYRESETPROBCNT", data(PhyResetProblemCount), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pSasEnclosurePage0_t)0)->x, sizeof(((pSasEnclosurePage0_t)0)->x) + +ITEM sas_enclosure_page_0_items[] = +{ + {"RESERVED1", data(Reserved1), OPT}, + {"ENCLOSURELOGICALID_HIGH", data(EnclosureLogicalID.High), 0}, + {"ENCLOSURELOGICALID_LOW", data(EnclosureLogicalID.Low), 0}, + {"FLAGS", data(Flags), 0}, + {"ENCLOSUREHANDLE", data(EnclosureHandle), 0}, + {"NUMSLOTS", data(NumSlots), 0}, + {"STARTSLOT", data(StartSlot), 0}, + {"STARTTARGETID", data(StartTargetID), 0}, + {"STARTBUS", data(StartBus), 0}, + {"SEPTARGETID", data(SEPTargetID), 0}, + {"SEPBUS", data(SEPBus), 0}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pPersistentId_SAS_t)0)->x, sizeof(((pPersistentId_SAS_t)0)->x) + +ITEM sas_persistent_id_items[] = +{ + {"PERSISTID_SASADDRESS_HIGH_0", data(PersistId[0].SasAddress.Word.High), 0}, + {"PERSISTID_SASADDRESS_LOW_0", data(PersistId[0].SasAddress.Word.Low), 0}, + {"PERSISTID_RESERVED_0", data(PersistId[0].Reserved), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pRaidVolumePage0_t)0)->x, sizeof(((pRaidVolumePage0_t)0)->x) + +ITEM raid_volume_page_0_items[] = +{ + {"ALL", sizeof(ConfigPageHeader_t), sizeof(RaidVolumePage0_t) - sizeof(ConfigPageHeader_t), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pRaidVolumePage1_t)0)->x, sizeof(((pRaidVolumePage1_t)0)->x) + +ITEM raid_volume_page_1_items[] = +{ + {"RAIDVOL1_VOLUMEID", data(VolumeID), 0}, + {"RAIDVOL1_VOLUMEBUS", data(VolumeBus), 0}, + {"RAIDVOL1_VOLUMEIOC", data(VolumeIOC), 0}, + {"RAIDVOL1_WWID_HIGH", data(WWID.High), 0}, + {"RAIDVOL1_WWID_LOW", data(WWID.Low), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pRaidPhysDiskPage0_t)0)->x, sizeof(((pRaidPhysDiskPage0_t)0)->x) + +ITEM raid_physdisk_page_0_items[] = +{ + {"ALL", sizeof(ConfigPageHeader_t), sizeof(RaidPhysDiskPage0_t) - sizeof(ConfigPageHeader_t), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pRaidPhysDiskPage1_t)0)->x, sizeof(((pRaidPhysDiskPage1_t)0)->x) + +ITEM raid_physdisk_page_1_items[] = +{ + {"RAIDPHYDISK1_NUMPHYSDISKPATH", data(NumPhysDiskPaths), 0}, + {"RAIDPHYDISK1_PHYSDISKNUM", data(PhysDiskNum), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pBIOSPage1_t)0)->x, sizeof(((pBIOSPage1_t)0)->x) + +ITEM bios_page_1_items[] = +{ + {"BIOSOPTIONS", data(BiosOptions), 0}, + {"IOCSETTINGS", data(IOCSettings), 0}, + {"BIOS_RESERVED1", data(Reserved1), OPT}, + {"RESERVED1", data(Reserved1), OPT}, + {"DEVSETTINGS", data(DeviceSettings), 0}, + {"BIOS_NUMDEVS", data(NumberOfDevices), 0}, + {"BIOS1_EXPANDERSPINUP", data(ExpanderSpinup), MPI1}, + {"RESERVED2", data(Reserved2), OPT}, + {"IOTIMOUTBLKDEVSNONRM", data(IOTimeoutBlockDevicesNonRM), 0}, + {"IOTIMOUTSEQUENTIAL", data(IOTimeoutSequential), 0}, + {"IOTIMOUTOTHER", data(IOTimeoutOther), 0}, + {"IOTIMOUTBLKDEVSRM", data(IOTimeoutBlockDevicesRM), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pBIOSPage2_t)0)->x, sizeof(((pBIOSPage2_t)0)->x) + +ITEM bios_page_2_items[] = +{ + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"RESERVED4", data(Reserved4), OPT}, + {"RESERVED5", data(Reserved5), OPT}, + {"RESERVED6", data(Reserved6), OPT}, + {"BIOS2_BOOTDEVICEFORM", data(BootDeviceForm), 0}, + {"BIOS2_PREVBOOTDEVFORM", data(PrevBootDeviceForm), 0}, + {"RESERVED8", data(Reserved8), OPT}, + {"BIOS2_SASADDRESS_HIGH", data(BootDevice.SasWwn.SASAddress.High), 0}, + {"BIOS2_SASADDRESS_LOW", data(BootDevice.SasWwn.SASAddress.Low), 0}, + {"BIOS2_SASADDRESS_LUN", data(BootDevice.SasWwn.LUN[1]), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pMpi2BiosPage2_t)0)->x, sizeof(((pMpi2BiosPage2_t)0)->x) + +ITEM bios_page_2_items2[] = +{ + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"RESERVED3", data(Reserved3), OPT}, + {"RESERVED4", data(Reserved4), OPT}, + {"RESERVED5", data(Reserved5), OPT}, + {"RESERVED6", data(Reserved6), OPT}, + {"REQ_BOOTDEVICEFORM", data(ReqBootDeviceForm), 0}, + {"RESERVED7", data(Reserved7), OPT}, + {"RESERVED8", data(Reserved8), OPT}, + {"REQ_SASADDRESS_LOW", data(RequestedBootDevice.SasWwid.SASAddress.Low), IGN}, + {"REQ_SASADDRESS_HI", data(RequestedBootDevice.SasWwid.SASAddress.High), IGN}, + {"REQ_SASADDRESS_LUN", data(RequestedBootDevice.SasWwid.LUN[1]), IGN}, + {"REQ_DEVICENAME_LOW", data(RequestedBootDevice.DeviceName.DeviceName.Low), IGN}, + {"REQ_DEVICENAME_HI", data(RequestedBootDevice.DeviceName.DeviceName.High), IGN}, + {"REQ_DEVICENAME_LUN", data(RequestedBootDevice.DeviceName.LUN[1]), IGN}, + {"REQ_ENCLOSUREID_LOW", data(RequestedBootDevice.EnclosureSlot.EnclosureLogicalID.Low), IGN}, + {"REQ_ENCLOSUREID_HI", data(RequestedBootDevice.EnclosureSlot.EnclosureLogicalID.High), IGN}, + {"REQ_SLOTNUMBER", data(RequestedBootDevice.EnclosureSlot.SlotNumber), IGN}, + {"REQALT_BOOTDEVICEFORM", data(ReqAltBootDeviceForm), 0}, + {"RESERVED9", data(Reserved9), OPT}, + {"RESERVED10", data(Reserved10), OPT}, + {"REQALT_SASADDRESS_LOW", data(RequestedAltBootDevice.SasWwid.SASAddress.Low), IGN}, + {"REQALT_SASADDRESS_HI", data(RequestedAltBootDevice.SasWwid.SASAddress.High), IGN}, + {"REQALT_SASADDRESS_LUN", data(RequestedAltBootDevice.SasWwid.LUN[1]), IGN}, + {"REQALT_DEVICENAME_LOW", data(RequestedAltBootDevice.DeviceName.DeviceName.Low), IGN}, + {"REQALT_DEVICENAME_HI", data(RequestedAltBootDevice.DeviceName.DeviceName.High), IGN}, + {"REQALT_DEVICENAME_LUN", data(RequestedAltBootDevice.DeviceName.LUN[1]), IGN}, + {"REQALT_ENCLOSUREID_LOW", data(RequestedAltBootDevice.EnclosureSlot.EnclosureLogicalID.Low), IGN}, + {"REQALT_ENCLOSUREID_HI", data(RequestedAltBootDevice.EnclosureSlot.EnclosureLogicalID.High), IGN}, + {"REQALT_SLOTNUMBER", data(RequestedAltBootDevice.EnclosureSlot.SlotNumber), IGN}, + {"CURR_BOOTDEVICEFORM", data(CurrentBootDeviceForm), 0}, + {"RESERVED11", data(Reserved11), OPT}, + {"RESERVED12", data(Reserved12), OPT}, + {"CURR_SASADDRESS_LOW", data(CurrentBootDevice.SasWwid.SASAddress.Low), IGN}, + {"CURR_SASADDRESS_HI", data(CurrentBootDevice.SasWwid.SASAddress.High), IGN}, + {"CURR_SASADDRESS_LUN", data(CurrentBootDevice.SasWwid.LUN[1]), IGN}, + {"CURR_DEVICENAME_LOW", data(CurrentBootDevice.DeviceName.DeviceName.Low), IGN}, + {"CURR_DEVICENAME_HI", data(CurrentBootDevice.DeviceName.DeviceName.High), IGN}, + {"CURR_DEVICENAME_LUN", data(CurrentBootDevice.DeviceName.LUN[1]), IGN}, + {"CURR_ENCLOSUREID_LOW", data(CurrentBootDevice.EnclosureSlot.EnclosureLogicalID.Low), IGN}, + {"CURR_ENCLOSUREID_HI", data(CurrentBootDevice.EnclosureSlot.EnclosureLogicalID.High), IGN}, + {"CURR_SLOTNUMBER", data(CurrentBootDevice.EnclosureSlot.SlotNumber), IGN}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pMpi2BiosPage3_t)0)->x, sizeof(((pMpi2BiosPage3_t)0)->x) + +ITEM bios_page_3_items2[] = +{ + {"GLOBAL_FLAGS", data(GlobalFlags), 0}, + {"BIOS_VERSION", data(BiosVersion), 0}, + {"PCI_BUS_NUMBER_0", data(AdapterOrder[0].PciBusNumber), 0}, + {"PCI_DEVICE_FUNCTION_0", data(AdapterOrder[0].PciDeviceAndFunctionNumber), 0}, + {"ADAPTER_FLAGS_0", data(AdapterOrder[0].AdapterFlags), 0}, + {"PCI_BUS_NUMBER_1", data(AdapterOrder[1].PciBusNumber), OPT}, + {"PCI_DEVICE_FUNCTION_1", data(AdapterOrder[1].PciDeviceAndFunctionNumber), OPT}, + {"ADAPTER_FLAGS_1", data(AdapterOrder[1].AdapterFlags), OPT}, + {"PCI_BUS_NUMBER_2", data(AdapterOrder[2].PciBusNumber), OPT}, + {"PCI_DEVICE_FUNCTION_2", data(AdapterOrder[2].PciDeviceAndFunctionNumber), OPT}, + {"ADAPTER_FLAGS_2", data(AdapterOrder[2].AdapterFlags), OPT}, + {"PCI_BUS_NUMBER_3", data(AdapterOrder[3].PciBusNumber), OPT}, + {"PCI_DEVICE_FUNCTION_3", data(AdapterOrder[3].PciDeviceAndFunctionNumber), OPT}, + {"ADAPTER_FLAGS_3", data(AdapterOrder[3].AdapterFlags), OPT}, + {"RESERVED1", data(Reserved1), OPT}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pBIOSPage4_t)0)->x, sizeof(((pBIOSPage4_t)0)->x) + +ITEM bios_page_4_items[] = +{ + {"BIOS4_REASSIGNMENTBASEWWID_HIGH", data(ReassignmentBaseWWID.High), 0}, + {"BIOS4_REASSIGNMENTBASEWWID_LOW", data(ReassignmentBaseWWID.Low), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pMpi2BiosPage4_t)0)->x, sizeof(((pMpi2BiosPage4_t)0)->x) + +ITEM bios_page_4_items2[] = +{ + {"NUM_PHYS", data(NumPhys), 0}, + {"RESERVED1", data(Reserved1), OPT}, + {"RESERVED2", data(Reserved2), OPT}, + {"REASSIGN_WWID_LOW_0", data(Phy[0].ReassignmentWWID.Low), 0}, + {"REASSIGN_WWID_HIGH_0", data(Phy[0].ReassignmentWWID.High), 0}, + {"REASSIGN_DEVNAME_LOW_0", data(Phy[0].ReassignmentDeviceName.Low), 0}, + {"REASSIGN_DEVNAME_HIGH_0", data(Phy[0].ReassignmentDeviceName.High), 0}, + {"REASSIGN_WWID_LOW_1", data(Phy[1].ReassignmentWWID.Low), 0}, + {"REASSIGN_WWID_HIGH_1", data(Phy[1].ReassignmentWWID.High), 0}, + {"REASSIGN_DEVNAME_LOW_1", data(Phy[1].ReassignmentDeviceName.Low), 0}, + {"REASSIGN_DEVNAME_HIGH_1", data(Phy[1].ReassignmentDeviceName.High), 0}, + {"REASSIGN_WWID_LOW_2", data(Phy[2].ReassignmentWWID.Low), 0}, + {"REASSIGN_WWID_HIGH_2", data(Phy[2].ReassignmentWWID.High), 0}, + {"REASSIGN_DEVNAME_LOW_2", data(Phy[2].ReassignmentDeviceName.Low), 0}, + {"REASSIGN_DEVNAME_HIGH_2", data(Phy[2].ReassignmentDeviceName.High), 0}, + {"REASSIGN_WWID_LOW_3", data(Phy[3].ReassignmentWWID.Low), 0}, + {"REASSIGN_WWID_HIGH_3", data(Phy[3].ReassignmentWWID.High), 0}, + {"REASSIGN_DEVNAME_LOW_3", data(Phy[3].ReassignmentDeviceName.Low), 0}, + {"REASSIGN_DEVNAME_HIGH_3", data(Phy[3].ReassignmentDeviceName.High), 0}, + {"REASSIGN_WWID_LOW_4", data(Phy[4].ReassignmentWWID.Low), 0}, + {"REASSIGN_WWID_HIGH_4", data(Phy[4].ReassignmentWWID.High), 0}, + {"REASSIGN_DEVNAME_LOW_4", data(Phy[4].ReassignmentDeviceName.Low), 0}, + {"REASSIGN_DEVNAME_HIGH_4", data(Phy[4].ReassignmentDeviceName.High), 0}, + {"REASSIGN_WWID_LOW_5", data(Phy[5].ReassignmentWWID.Low), 0}, + {"REASSIGN_WWID_HIGH_5", data(Phy[5].ReassignmentWWID.High), 0}, + {"REASSIGN_DEVNAME_LOW_5", data(Phy[5].ReassignmentDeviceName.Low), 0}, + {"REASSIGN_DEVNAME_HIGH_5", data(Phy[5].ReassignmentDeviceName.High), 0}, + {"REASSIGN_WWID_LOW_6", data(Phy[6].ReassignmentWWID.Low), 0}, + {"REASSIGN_WWID_HIGH_6", data(Phy[6].ReassignmentWWID.High), 0}, + {"REASSIGN_DEVNAME_LOW_6", data(Phy[6].ReassignmentDeviceName.Low), 0}, + {"REASSIGN_DEVNAME_HIGH_6", data(Phy[6].ReassignmentDeviceName.High), 0}, + {"REASSIGN_WWID_LOW_7", data(Phy[7].ReassignmentWWID.Low), 0}, + {"REASSIGN_WWID_HIGH_7", data(Phy[7].ReassignmentWWID.High), 0}, + {"REASSIGN_DEVNAME_LOW_7", data(Phy[7].ReassignmentDeviceName.Low), 0}, + {"REASSIGN_DEVNAME_HIGH_7", data(Phy[7].ReassignmentDeviceName.High), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pLogPage0_t)0)->x, sizeof(((pLogPage0_t)0)->x) + +ITEM log_page_0_items[] = +{ + {"ALL", sizeof(ConfigExtendedPageHeader_t), sizeof(LogPage0_t) - sizeof(ConfigExtendedPageHeader_t), 0}, + {0} +}; + +#undef data +#define data(x) (int)(size_t)&((pMpi2DriverMappingPage0_t)0)->x, sizeof(((pMpi2DriverMappingPage0_t)0)->x) + +ITEM driver_mapping_page_0_items2[] = +{ + {"PHYSICAL_IDENTIFIER_LOW", data(Entry.PhysicalIdentifier.Low), 0}, + {"PHYSICAL_IDENTIFIER_HIGH", data(Entry.PhysicalIdentifier.High), 0}, + {"MAPPING_INFORMATION", data(Entry.MappingInformation), 0}, + {"DEVICE_INDEX", data(Entry.DeviceIndex), 0}, + {"PHYSICAL_BITS_MAPPING", data(Entry.PhysicalBitsMapping), 0}, + {"RESERVED1", data(Entry.Reserved1), OPT}, + {0} +}; + +#undef data +#define data(x) sizeof(x) +#define plus(x,y,z) data(x) + sizeof(((p##x)0)->y) * z + +SECTION sections[] = +{ + {"SECTION_GENERAL_DATA", general_data_items, data(GeneralData_t), GEN}, + {"SECTION_MANUFACTURING_PAGE_0", manufacturing_page_0_items, data(ManufacturingPage0_t), 0}, + {"SECTION_MANUFACTURING_PAGE_1", manufacturing_page_1_items, data(ManufacturingPage1_t), 0}, + {"SECTION_IOC_MFG_PAGE_2", manufacturing_page_2_items, data(ManufacturingPage2_SAS_t), MP2}, + {"SECTION_IOC_MFG_PAGE_3", manufacturing_page_3_items, data(ManufacturingPage3_SAS_t), 0}, + {"SECTION_MANUFACTURING_PAGE_4", manufacturing_page_4_items, data(ManufacturingPage4_t), 0}, + {"SECTION_MANUFACTURING_PAGE_5", manufacturing_page_5_items, plus(ManufacturingPage5_t, ForceWWID, 7), 0}, + {"SECTION_MANUFACTURING_PAGE_7", manufacturing_page_7_items, plus(ManufacturingPage7_t, ConnectorInfo, 7), 0}, + {"SECTION_IO_UNIT_PAGE_0", io_unit_page_0_items, data(IOUnitPage0_t), 0}, + {"SECTION_IO_UNIT_PAGE_1", io_unit_page_1_items, data(IOUnitPage1_t), 0}, + {"SECTION_IO_UNIT_PAGE_2", io_unit_page_2_items, data(IOUnitPage2_t), 0}, + {"SECTION_IO_UNIT_PAGE_3", io_unit_page_3_items, plus(IOUnitPage3_t, GPIOVal, 31), 0}, + {"SECTION_IO_UNIT_PAGE_4", io_unit_page_4_items, data(IOUnitPage4_t), 0}, + {"SECTION_IOC_PAGE_0", ioc_page_0_items, data(IOCPage0_t), 0}, + {"SECTION_IOC_PAGE_1", ioc_page_1_items, data(IOCPage1_t), 0}, + {"SECTION_IOC_PAGE_2", ioc_page_2_items, data(IOCPage2_t), 0}, + {"SECTION_IOC_PAGE_3", ioc_page_3_items, data(IOCPage3_t), 0}, + {"SECTION_IOC_PAGE_4", ioc_page_4_items, data(IOCPage4_t), 0}, + {"SECTION_IOC_PAGE_5", ioc_page_5_items, data(IOCPage5_t), 0}, + {"SECTION_IOC_PAGE_6", ioc_page_6_items, data(IOCPage6_t), 0}, + {"SECTION_SAS_IO_UNIT_0", sas_io_unit_page_0_items, plus(SasIOUnitPage0_t, PhyData, 7), EXT}, + {"SECTION_SAS_IO_UNIT_1", sas_io_unit_page_1_items, plus(SasIOUnitPage1_t, PhyData, 7), EXT}, + {"SECTION_SAS_IO_UNIT_2", sas_io_unit_page_2_items, data(SasIOUnitPage2_t), EXT}, + {"SECTION_SAS_IO_UNIT_3", sas_io_unit_page_3_items, data(SasIOUnitPage3_t), EXT}, + {"SECTION_SAS_EXPANDER_0", sas_expander_page_0_items, data(SasExpanderPage0_t), EXT}, + {"SECTION_SAS_EXPANDER_1", sas_expander_page_1_items, data(SasExpanderPage1_t), EXT}, + {"SECTION_SAS_DEVICE_0", sas_device_page_0_items, data(SasDevicePage0_t), EXT}, + {"SECTION_SAS_DEVICE_1", sas_device_page_1_items, data(SasDevicePage1_t), EXT}, + {"SECTION_SAS_DEVICE_2", sas_device_page_2_items, data(SasDevicePage2_t), EXT}, + {"SECTION_SAS_PHY_0", sas_phy_page_0_items, data(SasPhyPage0_t), EXT}, + {"SECTION_SAS_PHY_1", sas_phy_page_1_items, data(SasPhyPage1_t), EXT}, + {"SECTION_SAS_ENCLOSURE_0", sas_enclosure_page_0_items, data(SasEnclosurePage0_t), EXT}, + {"SECTION_PERSISTENT_ID", sas_persistent_id_items, data(PersistentId_SAS_t), EXT | PID}, + {"SECTION_RAID_VOL_PAGE_0", raid_volume_page_0_items, data(RaidVolumePage0_t), 0}, + {"SECTION_RAID_VOL_PAGE_1", raid_volume_page_1_items, data(RaidVolumePage1_t), 0}, + {"SECTION_RAID_PHYS_DISK_PAGE_0", raid_physdisk_page_0_items, data(RaidPhysDiskPage0_t), 0}, + {"SECTION_RAID_PHYS_DISK_PAGE_1", raid_physdisk_page_1_items, data(RaidPhysDiskPage1_t), 0}, + {"SECTION_BIOS_1", bios_page_1_items, data(BIOSPage1_t), 0}, + {"SECTION_BIOS_2", bios_page_2_items, data(BIOSPage2_t), 0}, + {"SECTION_BIOS_4", bios_page_4_items, data(BIOSPage4_t), 0}, + {"SECTION_LOG_0", log_page_0_items, data(LogPage0_t), EXT}, + {0} +}; + +SECTION sections2[] = +{ + {"SECTION_GENERAL_DATA", general_data_items, data(GeneralData_t), GEN}, + {"SECTION_MANUFACTURING_PAGE_0", manufacturing_page_0_items, data(ManufacturingPage0_t), 0}, + {"SECTION_MANUFACTURING_PAGE_1", manufacturing_page_1_items, data(ManufacturingPage1_t), 0}, + {"SECTION_IOC_MFG_PAGE_2", manufacturing_page_2_items2, data(ManufacturingPage2_SAS2_t), MP2}, + {"SECTION_IOC_MFG_PAGE_3", manufacturing_page_3_items2, data(ManufacturingPage3_SAS2_t), 0}, + {"SECTION_MANUFACTURING_PAGE_4", manufacturing_page_4_items2, data(Mpi2ManufacturingPage4_t), 0}, + {"SECTION_MANUFACTURING_PAGE_5", manufacturing_page_5_items2, plus(Mpi2ManufacturingPage5_t, Phy, 15), 0}, + {"SECTION_IOC_MFG_PAGE_6", manufacturing_page_6_items2, data(ManufacturingPage6_SAS2_t), 0}, + {"SECTION_MANUFACTURING_PAGE_7", manufacturing_page_7_items, plus(ManufacturingPage7_t, ConnectorInfo, 15), 0}, + {"SECTION_MANUFACTURING_PAGE_8", manufacturing_page_8_items2, data(ManufacturingPage8_t), 0}, + {"SECTION_IOC_MFG_PAGE_9", manufacturing_page_9_items2, data(ManufacturingPage9_SAS2_t), 0}, + {"SECTION_MANUFACTURING_PAGE_10", manufacturing_page_10_items2, data(ManufacturingPage10_t), 0}, + {"SECTION_IOC_MFG_PAGE_11", manufacturing_page_11_items2, data(ManufacturingPage11_SAS2_t), 0}, + {"SECTION_IOC_MFG_PAGE_12", manufacturing_page_12_items2, data(ManufacturingPage12_SAS2_t), 0}, + {"SECTION_IOC_MFG_PAGE_13", manufacturing_page_13_items2, data(ManufacturingPage13_SAS2_t), 0}, + {"SECTION_IO_UNIT_PAGE_1", io_unit_page_1_items, data(IOUnitPage1_t), 0}, + {"SECTION_IOC_PAGE_1", ioc_page_1_items2, data(Mpi2IOCPage1_t), 0}, + {"SECTION_IOC_PAGE_8", ioc_page_8_items2, data(Mpi2IOCPage8_t), 0}, + {"SECTION_BIOS_1", bios_page_1_items, data(BIOSPage1_t), 0}, + {"SECTION_BIOS_2", bios_page_2_items2, data(Mpi2BiosPage2_t), 0}, + {"SECTION_BIOS_3", bios_page_3_items2, data(Mpi2BiosPage3_t), 0}, + {"SECTION_BIOS_4", bios_page_4_items2, plus(Mpi2BiosPage4_t, Phy, 15), 0}, + {"SECTION_SAS_IO_UNIT_1", sas_io_unit_page_1_items2, plus(Mpi2SasIOUnitPage1_t, PhyData, 15), EXT}, + {"SECTION_SAS_IO_UNIT_4", sas_io_unit_page_4_items2, plus(Mpi2SasIOUnitPage4_t, PHY, 3), EXT}, + {"SECTION_DRIVER_MAPPING_0", driver_mapping_page_0_items2, data(Mpi2DriverMappingPage0_t), EXT}, + {0} +}; + +#undef data +#undef plus + + +int +getSectionItem(SECTION *section, ITEM *item, char *buf, U8 *page) +{ + char *c; + char x; + U8 *p; + int n; + int t; + int i; + int j; + int k; + + n = (int)strlen(section->name); + + while (*buf) + { + if (strncmp(buf, section->name, n) == 0) + break; + + buf = skipLine(buf); + } + + if (!*buf) + { + printf("%s not found!\n", section->name); + return 0; + } + + buf = skipLine(buf); + + if (item->size == 0) // special! + { + while (*buf) + { + if (strncmp(buf, "SECTION", 7) == 0) + return 1; + + if (strncmp(buf, "END_SECTION", 11) == 0) + return 1; + + c = NULL; + k = 0; + + if (sscanf(buf, "BYTE_%d=%n", &i, &n) == 1) + { + c = buf + n; + j = i; + k = 1; + } + + if (sscanf(buf, "BYTES_%d_%d=%n", &j, &i, &n) == 2) + { + c = buf + n; + if (j < i) + { + k = i; + i = j; + j = k; + } + k = j - i + 1; + if (k > 4) + { + c--; + x = *c; + *c = '\0'; + printf("Byte range too large for %s in %s!\n", buf, section->name); + *c = x; + buf = skipLine(buf); + continue; + } + } + + if (c == NULL) + { + buf = skipLine(buf); + continue; + } + + if (sscanf(c, "%x%n", &t, &n) == 1) + { + if (c[n] != '\n') + { + c--; + x = *c; + *c = '\0'; + printf("Incorrectly formed number for %s in %s!\n", buf, section->name); + *c = x; + buf = skipLine(buf); + continue; + } + if (n > 8 || (k < 4 && (U32)t > ((U32)1 << (k * 8)))) + { + c--; + x = *c; + *c = '\0'; + printf("Number too large for %s in %s!\n", buf, section->name); + *c = x; + buf = skipLine(buf); + continue; + } + + p = page + i; + + switch(k) + { + default: + case 4: + p[3] = (U8)(t >> 24); + case 3: + p[2] = (U8)(t >> 16); + case 2: + p[1] = (U8)(t >> 8); + case 1: + p[0] = (U8)t; + } + +// c--; +// x = *c; +// *c = '\0'; +// printf("%-32.32s %-28.28s %x\n", section->name, buf, t); +// *c = x; + + removeLine(buf); + continue; + } + } + } + + n = (int)strlen(item->name); + c = NULL; + + while (*buf) + { + if (strncmp(buf, "SECTION", 7) == 0) + break; + + if (strncmp(buf, "END_SECTION", 11) == 0) + break; + + if (strncmp(buf, item->name, n) == 0 && buf[n] == '=') + { + c = buf + n + 1; + break; + } + + buf = skipLine(buf); + } + + if (c == NULL) + { + if (item->flags & OPT) + return 1; + + if (item->flags & DUP) + return 0; + + printf("%s not found in %s\n", item->name, section->name); + return 0; + } + + p = page + item->offset; + + t = 0; + + if (item->flags & STR) + { + if (*c++ == '"') + { + n = 0; + while (*c != '\n' && *c != '\0') + { + if (*c == '"') + break; + p[n++] = *c++; + } + if (c[1] != '\n') + { + printf("Incorrectly formed string for %s in %s!\n", item->name, section->name); + return 0; + } + + if (n != 0 || !(item->flags & IGN)) + p[n] = '\0'; + +// printf("%-32.32s %-28.28s %s\n", section->name, item->name, p); + + removeLine(buf); + return 1; + } + } + else + { + if (sscanf(c, "%x%n", &t, &n) == 1) + { + if (c[n] != '\n') + { + printf("Incorrectly formed number for %s in %s!\n", item->name, section->name); + return 0; + } + k = item->size * ((item->flags & BIT) ? 1 : 8); + if (n > 8 || (k < 32 && (U32)t > ((U32)1 << k))) + { + printf("Number too large for %s in %s!\n", item->name, section->name); + return 0; + } + + if (t != 0 || !(item->flags & IGN)) + { + switch((k + 7) / 8) + { + default: + case 4: + p[3] = (U8)(t >> 24); + case 3: + p[2] = (U8)(t >> 16); + case 2: + p[1] = (U8)(t >> 8); + case 1: + p[0] = (U8)t; + } + +// printf("%-32.32s %-28.28s %x\n", section->name, item->name, t); + } + + removeLine(buf); + return 1; + } + } + + printf("Parse error on %s in %s!\n", item->name, section->name); + return 0; +} + + +U8 +pageChecksum(U8 *page, int size, int skip) +{ + int i; + int checksum; + + checksum = 0; + for (i = skip; i < size; i++) + checksum -= page[i]; + + return checksum & 0xff; +} + + +#define NVDATA_SIZE 4096 +#define NUM_CONFIG_PAGES (sizeof(sections)/sizeof(sections[0]) - 2) // ignore sentinel and GEN +#define NUM_CONFIG_PAGES2 (sizeof(sections2)/sizeof(sections2[0]) - 2) // ignore sentinel and GEN + + +int +concatenateSasFirmwareNvdata(void) +{ + int file; + char name[256]; + unsigned char *imageBuf = NULL; + int imageLen; + unsigned char *nvdataBuf = NULL; + int nvdataLen; + int len; + int n; + char *buf; + MpiFwHeader_t *fwHeader; + Mpi2FWImageHeader_t *fwHeader2; + MpiExtImageHeader_t *fwExtImageHeader; + Mpi2ExtImageHeader_t *fwExtImageHeader2; + Mpi2SupportedDevicesData_t *fwSupportedDevices = NULL; + MpiExtImageHeader_t *fwNvdataHeader = NULL; + Mpi2InitImageFooter_t *fwFooter; + U32 fwNextImage; + U32 fwLastImage = 0; + int i; + int t; + U32 checksum; + SECTION *section; + ITEM *item; + U8 *nvdata; + int length; + int headOff; + int pageOff; + CONFIG_DIR_HEADER *cdh; + CONFIG_DIR_HEADER2 *cdh2; + CONFIG_PROD_ID *cpi; + CONFIG_DIR_ENTRY *cde; + CONFIG_DIR_ENTRY2 *cde2; + PERSISTENT_PAGE_HEADER *pph; + PERSISTENT_PAGE_HEADER2 *pph2; + U8 page[512]; + U8 update; + int header; + char *c1; + char *c2; + int pageType; + int pageNumber; + int pageLength; + int offset; + int size; + int fwFamily; + int fwDeviceId1 = 0; + int fwDeviceId2 = 0; + int nvDeviceId; + int fwVersion; + int nvVersion; + int mpi1; + int mpi2; + int ncp; + int npcp; + ITEM *section_items; + int section_size; + + n = getFileName(name, sizeof name, stdin, "firmware", 0); + if (n > 0) + { + if (readFile(name, &imageBuf, &imageLen) != 1) + return 0; + } + else + { + printf("Image won't be processed\n"); + return 1; + } + + printf("Read %d bytes from file %s\n", imageLen, name); + + checksum = 0; + for (i = 0; i < imageLen / 4; i++) + checksum += get32x(((U32 *)imageBuf)[i]); + + if (checksum != 0) + { + printf("Image's checksum is invalid!\n"); + free(imageBuf); + return 0; + } + + fwHeader = (pMpiFwHeader_t)imageBuf; + fwHeader2 = (pMpi2FWImageHeader_t)fwHeader; + + mpi1 = get32(fwHeader->Signature0) == MPI_FW_HEADER_SIGNATURE_0 && + get32(fwHeader->Signature1) == MPI_FW_HEADER_SIGNATURE_1 && + get32(fwHeader->Signature2) == MPI_FW_HEADER_SIGNATURE_2; + + mpi2 = get32(fwHeader2->Signature0) == MPI2_FW_HEADER_SIGNATURE0 && + get32(fwHeader2->Signature1) == MPI2_FW_HEADER_SIGNATURE1 && + get32(fwHeader2->Signature2) == MPI2_FW_HEADER_SIGNATURE2; + + if (!mpi1 && !mpi2) + { + printf("Image's signatures are invalid!\n"); + free(imageBuf); + return 0; + } + + fwExtImageHeader = NULL; + + len = get32(fwHeader->ImageSize); + fwNextImage = get32(fwHeader->NextImageHeaderOffset); + while (fwNextImage != 0) + { + if (fwNextImage > imageLen - sizeof *fwExtImageHeader) + { + printf("Image's NextImageHeaderOffset field is invalid!\n"); + free(imageBuf); + return 0; + } + + fwExtImageHeader = (pMpiExtImageHeader_t)(imageBuf + fwNextImage); + fwExtImageHeader2 = (pMpi2ExtImageHeader_t)fwExtImageHeader; + + if (fwExtImageHeader->ImageType == MPI_EXT_IMAGE_TYPE_NVDATA) + { + if (mpi1) + fwLastImage = fwNextImage; + + fwNvdataHeader = fwExtImageHeader; + + if (get32(fwExtImageHeader->NextImageHeaderOffset) != 0 || + get32(fwExtImageHeader->ImageSize) != sizeof(MpiExtImageHeader_t)) + { + printf("Image's attached NVDATA is incorrectly formed!\n"); + free(imageBuf); + return 0; + } + } + + if (fwExtImageHeader->ImageType == MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES) + { + fwSupportedDevices = (pMpi2SupportedDevicesData_t)(fwExtImageHeader2 + 1); + } + + len += get32(fwExtImageHeader->ImageSize); + fwNextImage = get32(fwExtImageHeader->NextImageHeaderOffset); + + if (fwExtImageHeader->ImageType == MPI2_EXT_IMAGE_TYPE_BOOTLOADER) + { + if (mpi2) + fwLastImage = fwNextImage; + } + } + + if (len != imageLen) + { + printf("Image's length is invalid!\n"); + free(imageBuf); + return 0; + } + + if (mpi1) + { + if (fwNvdataHeader == NULL) + { + printf("Image's attached NVDATA is missing!\n"); + free(imageBuf); + return 0; + } + + printf("\nFirmware is %s for %X\n", fwHeader->VersionName, get32(fwHeader->SeqCodeVersion)); + + fwFamily = get16(fwHeader->ProductId) & MPI_FW_HEADER_PID_FAMILY_MASK; + + switch (fwFamily) + { + case MPI_FW_HEADER_PID_FAMILY_1064_SAS: + fwDeviceId1 = MPI_MANUFACTPAGE_DEVID_SAS1064; + break; + case MPI_FW_HEADER_PID_FAMILY_1068_SAS: + fwDeviceId1 = MPI_MANUFACTPAGE_DEVID_SAS1068; + break; + case MPI_FW_HEADER_PID_FAMILY_1078_SAS: + fwDeviceId1 = MPI_MANUFACTPAGE_DEVID_SAS1078; + break; + case MPI_FW_HEADER_PID_FAMILY_106xE_SAS: + fwDeviceId1 = MPI_MANUFACTPAGE_DEVID_SAS1064E; + fwDeviceId2 = MPI_MANUFACTPAGE_DEVID_SAS1068E; + break; + } + + if (fwDeviceId2) + printf("Firmware ProductId Family is %x, DeviceId is %X/%X\n", + get16(fwHeader->ProductId) & MPI_FW_HEADER_PID_FAMILY_MASK, fwDeviceId1, fwDeviceId2); + else + printf("Firmware ProductId Family is %x, DeviceId is %X\n", + get16(fwHeader->ProductId) & MPI_FW_HEADER_PID_FAMILY_MASK, fwDeviceId1); + + fwVersion = (get32(fwHeader->ArmBranchInstruction1) >> 8) & 0xff; + printf("Firmware NVDATA Version is %x\n", fwVersion); + + if (fwVersion != 0x25 && fwVersion != 0x28 && fwVersion != 0x29 && + fwVersion != 0x2b && fwVersion != 0x2d) + { + printf("Expecting Version 25, 28, 29, 2B, or 2D -- can't process this image!\n"); + free(imageBuf); + return 0; + } + } + else + { + if (fwNvdataHeader != NULL) + { + printf("Image's NVDATA is already attached!\n"); + free(imageBuf); + return 0; + } + + if (fwLastImage == 0) + { + printf("Image's BootLoader is missing!\n"); + free(imageBuf); + return 0; + } + + if (fwSupportedDevices == NULL) + { + printf("Image's Supported Device List is missing!\n"); + free(imageBuf); + return 0; + } + + if (fwSupportedDevices->NumberOfDevices == 0) + { + printf("Image's Supported Device List is empty!\n"); + free(imageBuf); + return 0; + } + + printf("\nFirmware is %s\n", fwHeader2->FirmwareVersionName); + for (i = 0; i < fwSupportedDevices->NumberOfDevices; i++) + { + if (fwSupportedDevices->SupportedDevice[i].LowPCIRev == + fwSupportedDevices->SupportedDevice[i].HighPCIRev) + { + printf("Firmware supports DeviceId %X, RevisionId %X\n", + get16(fwSupportedDevices->SupportedDevice[i].DeviceID), + fwSupportedDevices->SupportedDevice[i].LowPCIRev); + } + else + { + printf("Firmware supports DeviceId %X, RevisionId %X to %X\n", + get16(fwSupportedDevices->SupportedDevice[i].DeviceID), + fwSupportedDevices->SupportedDevice[i].LowPCIRev, + fwSupportedDevices->SupportedDevice[i].HighPCIRev); + } + } + + fwVersion = (get32(fwHeader2->NVDATAVersion.Word) >> 8) & 0xff; + if (fwVersion == 0x25) // sfs + { + printf("Expecting Version 30, found 25 -- you can slide for now\n"); + fwVersion = 0x30; + } + printf("Firmware NVDATA Version is %x\n", fwVersion); + + if (fwVersion != 0x30) + { + printf("Expecting Version 30 -- can't process this image!\n"); + free(imageBuf); + return 0; + } + } + + printf("\n"); + n = getFileName(name, sizeof name, stdin, "NVDATA", 1); + if (n > 0) + { + if (readFile(name, &nvdataBuf, &nvdataLen) != 1) + { + free(imageBuf); + return 0; + } + } + else + { + printf("Image won't be processed\n"); + free(imageBuf); + return 1; + } + + printf("Read %d bytes from file %s\n", nvdataLen, name); + + n = nvdataLen; + buf = realloc(nvdataBuf, n + 2); + if (n && buf[n-1] != '\n') + { + nvdataLen++; + buf[n++] = '\n'; + } + buf[n] = '\0'; + + n = 0; + for (i = 0; i < nvdataLen; i++) + { + if (buf[i] == '\0' || buf[i] == '\r') // NUL and CR are ignored + continue; + + if (buf[i] == ';') // lines starting with ; are ignored + { + while (buf[i] != '\n' && i < nvdataLen) + i++; + } + + if (n) + { + if (buf[i] == '\n' && buf[n-1] == '\n') // blank lines are ignored + continue; + + if (buf[i] == ' ' && buf[n-1] == '\n') // leading spaces are ignored + continue; + + while (buf[i] == '\n' && buf[n-1] == ' ') // trailing spaces are ignored + n--; + } + else + { + if (buf[i] == '\n') // blank lines are ignored + continue; + + if (buf[i] == ' ') // leading spaces are ignored + continue; + } + + buf[n++] = buf[i]; + } + buf[n] = '\0'; + + if (sscanf(buf, "SASDATA_VERSION_CHECK=%x", &nvVersion) == 1) + { + printf("\nNVDATA Version is %x\n", nvVersion); + if (fwVersion != nvVersion) + { + printf("Firmware Version does not match NVDATA Version, can't process this NVDATA file!\n"); + free(imageBuf); + free(buf); + return 0; + } + } + + removeLine(buf); + + nvdata = malloc(NVDATA_SIZE); + memset(nvdata, 0, NVDATA_SIZE); + + length = 0; + headOff = 0; + + cdh = (CONFIG_DIR_HEADER *)(nvdata + headOff); + if (mpi1) + { + cdh->Signature = set32(CONFIG_DIR_HEADER_SIGNATURE); + cdh->State = CONFIG_DIR_HEADER_STATE_VALID; + cdh->CdhSize = sizeof *cdh / 4; + cdh->CdeSize = sizeof *cde / 4; + cdh->PphSize = sizeof *pph / 4; + cdh->ProdIdSize = sizeof *cpi / 4; + + length += sizeof *cdh; + headOff += sizeof *cdh; + } + else + { + cdh2 = (CONFIG_DIR_HEADER2 *)cdh; + + cdh2->Signature = set32(CONFIG_DIR_HEADER_SIGNATURE); + cdh2->State = CONFIG_DIR_HEADER_STATE_VALID; + cdh2->CdhSize = sizeof *cdh2 / 4; + cdh2->CdeSize = sizeof *cde2 / 4; + cdh2->PphSize = sizeof *pph2 / 4; + cdh2->ProdIdSize = sizeof *cpi / 4; + cdh2->NvdataVersion = set16(MPI2_VERSION); + cdh2->ProductIdOffset = set16(cdh2->CdhSize); + cdh2->DirEntryOffset = set16(cdh2->CdhSize + cdh->ProdIdSize); + + length += sizeof *cdh2; + headOff += sizeof *cdh2; + } + + ncp = 0; + npcp = 0; + + n = mpi1 ? sizeof *cde * NUM_CONFIG_PAGES : sizeof *cde2 * NUM_CONFIG_PAGES2; + + pageOff = length + sizeof *cpi + n; + + if (nvVersion < 0x2d) + pageOff -= sizeof *cde; // skipping BIOSPage4 + + for (section = (mpi1 ? sections : sections2); section->name; section++) + { + section_items = section->items; + section_size = section->size; + + if (nvVersion < 0x28) + { + if (section_items == manufacturing_page_5_items) + { + section_items = manufacturing_page_5_items_25; + section_size = manufacturing_page_5_size_25; + } + } + + if (nvVersion < 0x29) + { + if (section_items == io_unit_page_3_items) + { + section_size = io_unit_page_3_size_25; + } + } + + if (nvVersion < 0x2d) + { + if (section_items == bios_page_4_items) + { + continue; + } + } + + memset(page, 0, sizeof page); + + if (section->flags & GEN) + { + for (item = section_items; item->name; item++) + { + getSectionItem(section, item, buf, page); + } + + cpi = (CONFIG_PROD_ID *)(nvdata + headOff); + memcpy(cpi->VendorId, ((pGeneralData_t)page)->VendorId, sizeof cpi->VendorId); + memcpy(cpi->ProductId, ((pGeneralData_t)page)->ProductId, sizeof cpi->ProductId); + memcpy(cpi->ProductRevision, ((pGeneralData_t)page)->ProductRevision, sizeof cpi->ProductRevision); + cpi->Signature = set32(CONFIG_PROD_ID_SIGNATURE); + + cdh->NvdataVersion = set16((nvVersion << 8) | ((pGeneralData_t)page)->UserVersion); + + length += sizeof *cpi; + headOff += sizeof *cpi; + + continue; + } + + getSectionItem(section, &forceupdate_item, buf, &update); + + if (section->flags & EXT) + { + for (item = ext_header_items; item->name; item++) + { + t = getSectionItem(section, item, buf, page); + } + } + else + { + for (item = header_items; item->name; item++) + { + t = getSectionItem(section, item, buf, page); + } + } + + for (item = section_items; item->name; item++) + { + if (item->flags & MPI1 && !mpi1) + continue; + if (item->flags & MPI2 && !mpi2) + continue; + t = getSectionItem(section, item, buf, page); + if (t == 1) + if (item->flags & DUP) + item++; + } + + getSectionItem(section, &special_item, buf, page); + + if (section->flags & EXT) + { + pageType = ((pConfigExtendedPageHeader_t)page)->ExtPageType; + pageNumber = ((pConfigExtendedPageHeader_t)page)->PageNumber; + pageLength = get16(((pConfigExtendedPageHeader_t)page)->ExtPageLength); + header = sizeof(ConfigExtendedPageHeader_t); + size = section_size / 4; + if (size != pageLength && yesFlag == TRUE) + printf("incorrect EXT_PAGE_LENGTH %x vs. %x for %s\n", pageLength, size, section->name); + } + else + { + pageType = ((pConfigPageHeader_t)page)->PageType & MPI_CONFIG_PAGETYPE_MASK; + pageNumber = ((pConfigPageHeader_t)page)->PageNumber; + pageLength = ((pConfigPageHeader_t)page)->PageLength; + header = sizeof(ConfigPageHeader_t); + size = section_size / 4; + if (size != pageLength && yesFlag == TRUE) + printf("incorrect PAGE_LENGTH %x vs. %x for %s\n", pageLength, size, section->name); + } + + if (section->flags & PID) + offset = 0x7fff; + else + offset = pageOff / 4; + + size = (section_size - header) / 4; + + cde = (CONFIG_DIR_ENTRY *)(nvdata + headOff); + if (mpi1) + { +#if !__linux__ && !__sparc__ + // safe to use bit field definitions on little-endian machines + cde->State = CONFIG_DIR_ENTRY_STATE_IN_USE; + cde->PageType = pageType; + cde->PageNum = pageNumber; + cde->AllocUnits = size; + cde->ForceNvdataUpdate = update; + cde->DwordOffset = offset; +#else + // can't use bit field definitions on big-endian machines + ((U8 *)cde)[0] = (U8)(CONFIG_DIR_ENTRY_STATE_IN_USE | ((size & 0x00f) << 4)); + ((U8 *)cde)[1] = (U8)((size & 0xff0) >> 4); + ((U8 *)cde)[2] = (U8)(pageType & 0xff); + ((U8 *)cde)[3] = (U8)(((update & 1) << 4) | (pageNumber & 0xf)); + ((U8 *)cde)[4] = (U8)(offset & 0x00ff); + ((U8 *)cde)[5] = (U8)((offset & 0x7f00) >> 8); +#endif + n = sizeof *cde; + } + else + { + cde2 = (CONFIG_DIR_ENTRY2 *)cde; + cde2->State = CONFIG_DIR_ENTRY_STATE_IN_USE; + cde2->PageType = pageType; + cde2->PageNum = pageNumber; + cde2->AllocUnits = set16(size); + cde2->UpdateFlags = update; + cde2->DwordOffset = set32(offset); + n = sizeof *cde2; + } + + length += n; + headOff += n; + + ncp++; + if (((pConfigPageHeader_t)page)->PageType & MPI_CONFIG_PAGEATTR_PERSISTENT) + npcp++; + + if (section->flags & PID) + { + continue; + } + + if (section->flags & MP2) + { + nvDeviceId = get16(((pManufacturingPage2_SAS_t)page)->ChipId.DeviceID); + + printf("NVDATA DeviceId is %X\n", nvDeviceId); + if (mpi1) + { + if (nvDeviceId != fwDeviceId1 && nvDeviceId != fwDeviceId2) + { + printf("\nNVDATA DeviceId does not match Firmware DeviceId!\n"); + free(imageBuf); + free(nvdata); + return 0; + } + } + else + { + for (i = 0; i < fwSupportedDevices->NumberOfDevices; i++) + { + if (nvDeviceId == get16(fwSupportedDevices->SupportedDevice[i].DeviceID)) + break; + } + if (i == fwSupportedDevices->NumberOfDevices) + { + printf("\nNVDATA DeviceId does not match any Firmware DeviceId!\n"); + free(imageBuf); + free(nvdata); + return 0; + } + } + + if (mpi1) + { + ((pManufacturingPage2_SAS_t)page)->AutoDownloadChecksum = 0xa5; + checksum = 0; + for (i = 8; i < 38; i++) + checksum -= page[i]; + ((pManufacturingPage2_SAS_t)page)->AutoDownloadChecksum = (U8)checksum; + } + } + + pph = (PERSISTENT_PAGE_HEADER *)(nvdata + pageOff); + pph->State = CONFIG_PERSISTENT_HEADER_STATE_UPDATE_COMPLETE; + pph->Checksum = pageChecksum(page, section_size, header); + + if (mpi1) + { + pph->DwordOffset = set16(0x7fff); + n = sizeof *pph; + } + else + { + pph2 = (PERSISTENT_PAGE_HEADER2 *)pph; + pph2->DwordOffset = set32(0xffffffff); + n = sizeof *pph2; + } + + length += n; + pageOff += n; + + memcpy(nvdata + pageOff, page + header, section_size - header); + + length += section_size - header; + pageOff += section_size - header; + } + + cdh->TotalBytes = set16(length); + cdh->NbrDirEntries = set32(ncp); + cdh->NbrPersistDirEntries = set32(npcp); + + c1 = buf; + while (*c1) + { + if (strncmp(c1, "SECTION", 7) == 0) + { + c2 = skipLine(c1); + + if (*c2 == '\0' || strncmp(c2, "SECTION", 7) == 0) + { + removeLine(c1); + continue; + } + + if (*c2 == '\0' || strncmp(c2, "END_SECTION", 11) == 0) + { + removeLine(c1); + removeLine(c1); + continue; + } + } + + c1 = skipLine(c1); + } + + if (strlen(buf)) + { + printf("\nExtra lines found in NVDATA file!\n"); + printf("----\n%s----\n", buf); + } + + free(buf); + + printf("\n"); + n = getFileName(name, sizeof name, stdin, "output", 2); + if (n > 0) + { + file = open(name, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + if (file < 0) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + free(imageBuf); + free(nvdata); + return 0; + } + } + else + { + printf("Image won't be saved\n"); + free(imageBuf); + free(nvdata); + return 1; + } + + if (mpi2) + n = sizeof(Mpi2ExtImageHeader_t); + else + n = 0; + + imageBuf = realloc(imageBuf, imageLen + length + n); + + fwExtImageHeader = (pMpiExtImageHeader_t)(imageBuf + fwLastImage); + + if (mpi2) + { + fwExtImageHeader2 = (pMpi2ExtImageHeader_t)fwExtImageHeader; + + for (i = imageLen - 1; i >= (int)fwLastImage; i--) + imageBuf[i + length + n] = imageBuf[i]; + + memset(fwExtImageHeader2, 0, n); + + fwExtImageHeader2->ImageType = MPI2_EXT_IMAGE_TYPE_NVDATA; + fwExtImageHeader2->ImageSize = set32(n); + fwExtImageHeader2->NextImageHeaderOffset = set32(fwLastImage); + strcpy((char *)fwExtImageHeader2->IdentifyString, "@(#)NVDATA"); + + checksum = 0; + for (i = 0; i < n / 4; i++) + checksum -= get32x(((U32 *)fwExtImageHeader2)[i]); + + fwExtImageHeader2->Checksum = set32(checksum); + + memcpy(imageBuf + fwLastImage + n, nvdata, length); + } + else + { + memcpy(imageBuf + imageLen, nvdata, length); + } + + checksum = get32(fwExtImageHeader->Checksum); + + len = get32(fwExtImageHeader->ImageSize); + fwExtImageHeader->ImageSize = set32(len + length); + + checksum -= length; + for (i = 0; i < (length + 3) / 4; i++) + checksum -= get32x(((U32 *)nvdata)[i]); + + fwExtImageHeader->Checksum = set32(checksum); + + while ((fwNextImage = get32(fwExtImageHeader->NextImageHeaderOffset)) != 0) + { + checksum = get32(fwExtImageHeader->Checksum); + + fwNextImage += length + n; + checksum -= length + n; + + fwExtImageHeader->NextImageHeaderOffset = set32(fwNextImage); + fwExtImageHeader->Checksum = set32(checksum); + + fwExtImageHeader = (pMpiExtImageHeader_t)(imageBuf + fwNextImage); + + fwLastImage = fwNextImage; + } + + if (fwExtImageHeader->ImageType == MPI2_EXT_IMAGE_TYPE_INITIALIZATION) + { + len = get32(fwExtImageHeader->ImageSize); + + fwFooter = (pMpi2InitImageFooter_t)(imageBuf + fwLastImage + len) - 1; + + len = get32(fwFooter->ImageSize); + checksum = get32(fwExtImageHeader->Checksum); + + checksum += len; + + // the footer's ImageSize is big-endian! + len = swap32(len); + len += length + n; + len = swap32(len); + checksum -= len; + + fwFooter->ImageSize = set32(len); + fwExtImageHeader->Checksum = set32(checksum); + } + + t = write(file, imageBuf, imageLen + length + n); + if (t != imageLen + length + n) + { + printf("Write failed for file %s, t = %x\n", name, t); + perror("Error is"); + close(file); + free(imageBuf); + free(nvdata); + return 0; + } + + printf("Wrote %d bytes to file %s\n", imageLen + length + n, name); + + close(file); + + free(imageBuf); + free(nvdata); + + return 1; +} + + +#endif + + +char * +getSasProductId(char *nvdata) +{ + CONFIG_DIR_HEADER *cdh; + CONFIG_PROD_ID *cpi; + + cdh = (CONFIG_DIR_HEADER *)nvdata; + + cpi = (CONFIG_PROD_ID *)((char *)cdh + cdh->CdhSize * 4); + + return (char *)cpi->ProductId; +} + + +int +selectAltaDevice(MPT_PORT *port, int *dev_bus, int *dev_target) +{ + int bus; + int target; + unsigned char inq[36]; + unsigned char inqvpd[600]; + int i; + int n; + + if (kFlag == TRUE) + { + if (port->maxBuses > 1 || gFlag == TRUE) + { + printf("Bus: [0-%d or RETURN to quit] ", port->maxBuses - 1); + bus = getNumberAnswer(0, port->maxBuses - 1, -1); + if (bus < 0) + return 0; + } + else + { + bus = 0; + } + + printf("Target: [0-%d or RETURN to quit] ", port->maxTargets - 1); + target = getNumberAnswer(0, port->maxTargets - 1, -1); + if (target < 0) + return 0; + + *dev_bus = bus; + *dev_target = target; + + return 1; + } + + showPortInfoHeader(port); + + printf(" B___T Type Vendor Product Rev\n"); + + n = 0; + for (bus = 0; bus < port->maxBuses; bus++) + { + for (target = port->minTargets; target < port->maxTargets; target++) + { + if (doInquiry(port, bus, target, 0, inq, sizeof inq) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + continue; + } + + if (doInquiryVpdPage(port, bus, target, 0, 0x89, inqvpd, sizeof inqvpd) != 1) + { +#if __linux__ || DOS || EFI + if (errno == EFAULT) + return 0; +#endif + continue; + } + + if ((inq[0] & 0x1f) == 0x1f) + continue; + + if ((inq[0] & 0xe0) == 0x20) + continue; + + if ((inq[0] & 0xe0) == 0x60) + continue; + + if ((strncmp((char *)inqvpd+8, "LSI", 3) != 0) || + (strncmp((char *)inqvpd+16, "LSISS25x0", 9) != 0)) + continue; + + for (i = 8; i < 36; i++) + if (!isprint(inq[i])) + inq[i] = ' '; + + diag_targets[n].bus = bus; + diag_targets[n].target = target; + + n++; + + printf("%2d. %2d %3d %-9s %-8.8s %-16.16s %-4.4s\n", + n, bus, target, deviceType[inq[0] & 0x1f], + inq+8, inq+16, inq+32); + + if (n == MAX_DEVICES) + break; + } + if (n == MAX_DEVICES) + break; + } + + if (n == 0) + { + printf("\nNo devices are available for this test\n"); + return 0; + } + + printf("\nSelect a device: [1-%d or RETURN to quit] ", n); + n = getNumberAnswer(1, n, 0); + if (n == 0) + return 0; + n--; + + bus = diag_targets[n].bus; + target = diag_targets[n].target; + + *dev_bus = bus; + *dev_target = target; + + return 1; +} + + +int +doAltaDiagnostics(MPT_PORT *port, int command) +{ + int t; + + if (bringOnline(port) != 1) + return 0; + + switch (command) + { + case 1: + t = doAltaProgramManufacturingInfo(port); + if (t == 1) + printf("Programming completed successfully.\n"); + else + printf("Programming completed with errors.\n"); + if (wFlag) + fprintf(logFile, "%s: Alta Program Manufacturing Information: %s\n", + logPrefix(port), t ? "PASS" : "FAIL"); + break; + case 2: + doAltaDisplayManufacturingInfo(port); + break; + case 3: + doResetAlta(port); + break; + default: + printf("Invalid selection!\n"); + break; + } + + return 1; +} + + +int +doAltaProgramManufacturingInfo(MPT_PORT *port) +{ + char name[256]; + unsigned char *identityBuf = NULL; + int identityLen; + int n; + int t; + char wwid[64]; + char serial[64]; + char mfgdate[64]; + char rwkdate[64]; + char partnum[64]; + char tmpstr[64]; + int skipmfg = FALSE; + int skiprwk = FALSE; + int skipwwid = FALSE; + unsigned char data[255]; + U32 wwidl; + U32 wwidh; + int bus; + int target; + char *c; + int foundOne; + int passed; + U32 wwidlChk; + U32 wwidhChk; + int wwidError = TRUE; + + *serial = 0; + *mfgdate = 0; + *rwkdate = 0; + *partnum = 0; + *wwid = 0; + + if (gFlag) + { + printf("\nError if WWID not found in config? [Yes or No, default is Yes] "); + n = getYesNoAnswer(1); + if (n==0) + { + wwidError = FALSE; + } + } + + if (selectAltaDevice(port, &bus, &target) != 1) + return 0; + + n = getFileName(name, sizeof name, stdin, "Alta parameters", 0); + if (n > 0) + { + if (readFile(name, &identityBuf, &identityLen) != 1) + { + return 0; + } + + printf("%d bytes read from %s\n\n", identityLen, name); + + /* start processing the file data one line at a time */ + c = (char *)identityBuf; + while (!*wwid || !*serial || !*partnum || !*mfgdate || !*rwkdate) + { + foundOne = FALSE; + if (strncmp(c, "WWN=", 4) == 0) + { + // Check to see if "WWN=" is in the file (null value). + // If that's the case, then we need to check + // line endings to move 'c' forward the appropriate + // amount. Otherwise, `sscanf(c + 4, "%s", wwid);` + // will simply load the next line, which is + // definitely not what we want. + if(strncmp(c,"WWN=\n", 5) == 0) + { + wwid[0] = '\0'; + c += 5; + } + else if (strncmp(c,"WWN=\r\n", 6) == 0) + { + wwid[0] = '\0'; + c += 6; + } + else + { + sscanf(c + 4, "%s", wwid); + c = strchr(c + 1, '\n'); + if (c) + c++; + else + break; + } + } + if (strncmp(c, "SN=", 3) == 0) + { + foundOne = TRUE; + sscanf(c + 3, "%s", serial); + c = strchr(c + 1, '\n'); + if (c) + c++; + else + break; + } + if (strncmp(c, "PARTNUM=", 8) == 0) + { + foundOne = TRUE; + // Fix for a customer to allow the format "PARTNUM=P/N TCA-00347-01-A" + if(strncmp(c + 8, "P/N ", 4) == 0) + { + sscanf(c + 8 + 4, "%s", partnum); + } + else + { + sscanf(c + 8, "%s", partnum); + } + + c = strchr(c + 1, '\n'); + if (c) + c++; + else + break; + } + if (strncmp(c, "MFGDATE=", 8) == 0) + { + foundOne = TRUE; + sscanf(c + 8, "%s", mfgdate); + c = strchr(c + 1, '\n'); + if (c) + c++; + else + break; + } + if (strncmp(c, "RWKDATE=", 8) == 0) + { + foundOne = TRUE; + sscanf(c + 8, "%s", rwkdate); + c = strchr(c + 1, '\n'); + if (c) + c++; + else + break; + } + + /* if we didn't find a required key, see if any more lines are available to check */ + if (!foundOne) + { + c = strchr(c, '\n'); + if (c) + c++; + else + break; + } + } + + if( (wwidError==FALSE) && (!*wwid || strlen(wwid) == 0 ) ) + skipwwid = TRUE; + + if ((!skipwwid && !wwid) || !*serial || !*partnum || !*mfgdate || !*rwkdate) + { + printf("Parameters file missing required keys:%s%s%s%s%s\n", + !skipwwid && !*wwid ? " WWN" : "", !*serial ? " SN" : "", + !*partnum ? " PARTNUM" : "", !*mfgdate ? " MFGDATE" : "", + !*rwkdate ? " RWKDATE" : ""); + if (wFlag) + fprintf(logFile, "%s: Parameters file missing required keys:%s%s%s%s%s\n", + logPrefix(port), !skipwwid && !*wwid ? " WWN" : "", !*serial ? " SN" : "", + !*partnum ? " PARTNUM" : "", !*mfgdate ? " MFGDATE" : "", + !*rwkdate ? " RWKDATE" : ""); + return 0; + } + + if (skipwwid == FALSE && (strlen(wwid) != 9 || + sscanf(wwid, "%x", &t) != 1 || sscanf(wwid + 8, "%x", &t) != 1)) + { + printf("Alta WWN value <%s> is invalid!\n", wwid); + if (wFlag) + fprintf(logFile, "%s: Alta WWN value <%s> is invalid: FAIL\n", + logPrefix(port), wwid); + *wwid = 0; + } + if (strlen(serial) > 16) + { + printf("Alta SN value <%s> is invalid!\n", serial); + if (wFlag) + fprintf(logFile, "%s: Alta SN value <%s> is invalid: FAIL\n", + logPrefix(port), serial); + *serial = 0; + } + if (strlen(mfgdate) != 8 || sscanf(mfgdate, "%x", &t) != 1) + { + printf("Alta MFGDATE value <%s> is invalid!\n", mfgdate); + if (wFlag) + fprintf(logFile, "%s: Alta MFGDATE value <%s> is invalid: FAIL\n", + logPrefix(port), mfgdate); + *mfgdate = 0; + } + if (strlen(rwkdate) != 8 || sscanf(rwkdate, "%x", &t) != 1) + { + printf("Alta RWKDATE value <%s> is invalid!\n", rwkdate); + if (wFlag) + fprintf(logFile, "%s: Alta RWKDATE value <%s> is invalid: FAIL\n", + logPrefix(port), rwkdate); + *rwkdate = 0; + } + if (strlen(partnum) > 16) + { + printf("Alta PARTNUM value <%s> is invalid!\n", partnum); + if (wFlag) + fprintf(logFile, "%s: Alta PARTNUM value <%s> is invalid: FAIL\n", + logPrefix(port), partnum); + *partnum = 0; + } + + free(identityBuf); + } + else + { + printf("The Alta's manufacturing information will not be updated!\n\n"); + } + + if ((!skipwwid && !*wwid) || !*serial || !*partnum || !*mfgdate || !*rwkdate) + return 0; + + if (strncmp(mfgdate, "00000000", 8) == 0) + skipmfg = TRUE; + if (strncmp(rwkdate, "00000000", 8) == 0) + skiprwk = TRUE; + + printf("Alta WWN .......... %s%s\n", wwid, skipwwid == TRUE ? " (Will not be changed)" : ""); + printf("Alta SN ........... %s\n", serial); + printf("Alta MFGDATE ...... %s%s\n", mfgdate, skipmfg == TRUE ? " (Will not be changed)" : ""); + printf("Alta RWKDATE ...... %s%s\n", rwkdate, skiprwk == TRUE ? " (Will not be changed)" : ""); + printf("Alta PARTNUM ...... %s\n", partnum); + + if (yesFlag == FALSE) + { + printf("\nAre these values correct? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + { + return 0; + } + } + + if (wFlag) + { + fprintf(logFile, "%s: Alta WWN .......... %s\n", logPrefix(port), wwid); + fprintf(logFile, "%s: Alta SN ........... %s\n", logPrefix(port), serial); + fprintf(logFile, "%s: Alta MFGDATE ...... %s%s\n", logPrefix(port), mfgdate, + skipmfg == TRUE ? " (Will not be changed)" : ""); + fprintf(logFile, "%s: Alta RWKDATE ...... %s%s\n", logPrefix(port), rwkdate, + skiprwk == TRUE ? " (Will not be changed)" : ""); + fprintf(logFile, "%s: Alta PARTNUM ...... %s\n", logPrefix(port), partnum); + } + + /* start by assuming success */ + passed = TRUE; + + printf("\nProgramming Alta...\n"); + + // The WWID may not need to be programmed + if(skipwwid == FALSE) + { + /* program wwn */ + sscanf(wwid + 1, "%x", &wwidl); + wwid[1] = '\0'; + sscanf(wwid, "%x", &wwidh); + /* add the LSI prefix to the WWN */ + wwidh |= 0x500605b << 4; + + t = doModeSense(port, bus, target, 0, 0x32, 0, 0, data, sizeof data); + n = data[0] + 1; + + if ((t == 1) && (n >= 31)) + { + /* replace the current WWN with the value we are programming */ + put4bytes(data, 12+11, wwidh); + put4bytes(data, 12+15, wwidl); + + /* update the WWN gen type field */ + data[12+5] = (unsigned char)(data[12+5] | 1<<5); + + if (doModeSelect(port, bus, target, 0, 1, data, n) != 1) + { + printf("Mode select page 0x32 for programmed WWN failed!\n"); + if (wFlag) + fprintf(logFile, "%s: Mode select page 0x32 for programmed WWN: FAIL\n", + logPrefix(port)); + passed = FALSE; + } + else + { + /* lets read it back and make sure it seems to have written correctly */ + memset(data, 0, sizeof data); + t = doModeSense(port, bus, target, 0, 0x32, 0, 0, data, sizeof data); + n = data[0] + 1; + + if ((t == 1) && (n >= 31)) + { + wwidhChk = get4bytes(data, 12+11); + wwidlChk = get4bytes(data, 12+15); + + if (wwidh != wwidhChk || wwidl != wwidlChk) + { + printf("Verify of programmed WWN failed! (found <%08x%08x>, expected <%08x%08x>)\n", + wwidhChk, wwidlChk, wwidh, wwidl); + if (wFlag) + fprintf(logFile, "%s: Mode sense verify of programmed WWN (found <%08x%08x>, expected <%08x%08x>): FAIL\n", + logPrefix(port), wwidhChk, wwidlChk, wwidh, wwidl); + passed = FALSE; + } + else + if (wFlag) + fprintf(logFile, "%s: Mode sense verify of programmed WWN: PASS\n", + logPrefix(port)); + } + else + { + printf("Mode sense page 0x32 for verify of programmed WWN failed!\n"); + if (wFlag) + fprintf(logFile, "%s: Mode sense page 0x32 for verify of programmed WWN: FAIL\n", + logPrefix(port)); + passed = FALSE; + } + } + } + else + { + printf("Mode sense page 0x32 for programmed WWN failed!\n"); + if (wFlag) + fprintf(logFile, "%s: Mode sense page 0x32 for programmed WWN: FAIL\n", + logPrefix(port)); + passed = FALSE; + } + } //skipwwid + + /* program serial number, part number, and dates */ + memset(data, 0, sizeof data); + + t = doLogSense(port, bus, target, 0, 0x35, 1, data, sizeof data); + n = get2bytes(data, 2) + 4; + + if ((t == 1) && (n >= 158)) + { + /* replace the current serial number with the value we are programming */ + strncpy((char *)(data+16), serial, strlen(serial)); // 16:31 + + /* pad the rest with spaces (20h) */ + memset((void *)(data+16+strlen(serial)), 0x20, 16 - strlen(serial)); + + /* replace the current part number with the value we are programming */ + strncpy((char *)(data+58), partnum, strlen(partnum)); // 58:73 + + /* pad the rest with spaces (20h) */ + memset((void *)(data+58+strlen(partnum)), 0x20, 16 - strlen(partnum)); + + if (skipmfg == FALSE) + { + /* mfg date is in ASCII in bytes 102-109 */ + strncpy((char *)(data+102), mfgdate, 8); + } + + if (skiprwk == FALSE) + { + /* rework date is in ASCII in bytes 118-125 */ + strncpy((char *)(data+118), rwkdate, 8); + } + + if (doLogSelect(port, bus, target, 0, 1, 1, data, n) != 1) + { + printf("Log select page 0x35 for programmed serial number, part number, and dates failed!\n"); + if (wFlag) + fprintf(logFile, "%s: Log select page 0x35 for programmed serial number, part number, and dates: FAIL\n", + logPrefix(port)); + passed = FALSE; + } + else + { + /* lets read it back and make sure it seems to have written correctly */ + memset(data, 0, sizeof data); + + t = doLogSense(port, bus, target, 0, 0x35, 1, data, sizeof data); + n = get2bytes(data, 2) + 4; + + if ((t == 1) && (n >= 158)) + { + /* check the serial number */ + if (strncmp((char *)data+16, serial, strlen(serial)) != 0) + { + printf("Verify of programmed serial number failed! (found <%16.16s>, expected <%16.16s>)\n", + data+16, serial); + if (wFlag) + fprintf(logFile, "%s: Log sense verify of programmed serial number (SN) (found <%10.10s>, expected <%10.10s>): FAIL\n", + logPrefix(port), data+16, serial); + passed = FALSE; + } + else + if (wFlag) + fprintf(logFile, "%s: Log sense verify of programmed serial number (SN): PASS\n", + logPrefix(port)); + + /* check the manufacture date */ + if (skipmfg == FALSE) + { + if (strncmp((char *)data+102, mfgdate, 8) != 0) + { + printf("Verify of programmed manufacture date failed! (found <%8.8s>, expected <%8.8s>)\n", + data+102, mfgdate); + if (wFlag) + fprintf(logFile, "%s: Log sense verify of programmed manufacture date (MFGDATE) (found <%8.8s>, expected <%8.8s>): FAIL\n", + logPrefix(port), data+102, mfgdate); + passed = FALSE; + } + else + if (wFlag) + fprintf(logFile, "%s: Log sense verify of programmed manufacture date (MFGDATE): PASS\n", + logPrefix(port)); + } + else + if (wFlag) + fprintf(logFile, "%s: Log sense verify of programmed manufacture date (unchanged) (MFGDATE): PASS\n", + logPrefix(port)); + + /* check the rework date */ + if (skiprwk == FALSE) + { + if (strncmp((char *)data+118, rwkdate, 8) != 0) + { + printf("Verify of programmed rework date failed! (found <%8.8s>, expected <%8.8s>)\n", + data+118, rwkdate); + if (wFlag) + fprintf(logFile, "%s: Log sense verify of programmed rework date (RWKDATE) (found <%8.8s>, expected <%8.8s>): FAIL\n", + logPrefix(port), data+118, rwkdate); + passed = FALSE; + } + else + if (wFlag) + fprintf(logFile, "%s: Log sense verify of programmed rework date (RWKDATE): PASS\n", + logPrefix(port)); + } + else + if (wFlag) + fprintf(logFile, "%s: Log sense verify of programmed rework date (unchanged) (RWKDATE): PASS\n", + logPrefix(port)); + + /* check the part number */ + if (strncmp((char *)data+58, partnum, strlen(partnum)) != 0) + { + strncpy(tmpstr, (char *)data+58, strlen(partnum)); + tmpstr[strlen(partnum)] = '\0'; + printf("Verify of programmed part number failed! (found <%s>, expected <%s>)\n", + tmpstr, partnum); + if (wFlag) + fprintf(logFile, "%s: Log sense verify of programmed part number (PARTNUM) (found <%s>, expected <%s>): FAIL\n", + logPrefix(port), tmpstr, partnum); + passed = FALSE; + } + else + if (wFlag) + fprintf(logFile, "%s: Log sense verify of programmed part number (PARTNUM): PASS\n", + logPrefix(port)); + } + else + { + printf("Log sense page 0x35 for verify of programmed serial number, part number, and dates failed!\n"); + if (wFlag) + fprintf(logFile, "%s: Log sense page 0x35 for verify of programmed serial number, part number, and dates: FAIL\n", + logPrefix(port)); + passed = FALSE; + } + } +#if 0 //debug + t = doLogSense(port, bus, target, 0, 0x35, 1, data, sizeof data); + n = get2bytes(data, 2) + 4; + printf("written new log sense buffer:\n"); + displayByteData(data, n); +#endif + } + else + { + printf("Log sense page 0x35 for programmed serial number, part number, and dates failed!\n"); + if (wFlag) + fprintf(logFile, "%s: Log sense page 0x35 for programmed serial number, part number, and dates: FAIL\n", + logPrefix(port)); + passed = FALSE; + } + + return passed; +} + + +int +doAltaDisplayManufacturingInfo(MPT_PORT *port) +{ + int bus; + int target; + unsigned char data[255]; + int t; + int n; + U32 wwn_h; + U32 wwn_l; + char tmpstr[64]; + int i; + + if (selectAltaDevice(port, &bus, &target) != 1) + return 0; + + t = doModeSense(port, bus, target, 0, 0x32, 0, 0, data, sizeof data); + n = data[0] + 1; + + if ((t == 1) && (n >= 12+19)) + { + wwn_h = get4bytes(data, 12+11); + wwn_l = get4bytes(data, 12+15); + } + else + { + wwn_h = 0; + wwn_l = 0; + printf("Read of mode page 0x32 for programmed WWN failed!\n"); + if (wFlag) + fprintf(logFile, "%s: read of mode page 0x32 for programmed WWN: FAIL\n", + logPrefix(port)); + } + + t = doLogSense(port, bus, target, 0, 0x35, 1, data, sizeof data); + n = get2bytes(data, 2) + 4; + + if ((t == 1) && (n >= 158)) + { + /* display the firmware version */ + strncpy(tmpstr, (char *)data+126, 12); + for (i = 0; i < 12; i++) + if ( tmpstr[i] == ' ') + break; + tmpstr[i] = '\0'; + + printf("Running firmware version is <%-s>\n", tmpstr); + if (wFlag) + fprintf(logFile, "%s: AltaDisplayManufacturingInfo - FWVERSION=%-s\n", + logPrefix(port), tmpstr); + + /* display the bootloader version */ + strncpy(tmpstr, (char *)data+138, 12); + for (i = 0; i < 12; i++) + if ( tmpstr[i] == ' ') + break; + tmpstr[i] = '\0'; + printf("Running bootloader version is <%-s>\n", tmpstr); + if (wFlag) + fprintf(logFile, "%s: AltaDisplayManufacturingInfo - BLVERSION=%-s\n", + logPrefix(port), tmpstr); + + /* display the WWN */ + printf("Programmed WWN is <%08x%08x>\n", wwn_h, wwn_l); + if (wFlag) + fprintf(logFile, "%s: AltaDisplayManufacturingInfo - WWN=%08x%08x\n", + logPrefix(port), wwn_h, wwn_l); + + /* display the serial number */ + printf("Programmed serial number is <%16.16s>\n", data+16); + if (wFlag) + fprintf(logFile, "%s: AltaDisplayManufacturingInfo - SN=%16.16s\n", + logPrefix(port), data+16); + + /* display the manufacturing date */ + printf("Programmed manufacture date is <%-8.8s>\n", data+102); + if (wFlag) + fprintf(logFile, "%s: AltaDisplayManufacturingInfo - MFGDATE=%-8.8s\n", + logPrefix(port), data+102); + + /* display the rework date */ + printf("Programmed rework date is <%-8.8s>\n", data+118); + if (wFlag) + fprintf(logFile, "%s: AltaDisplayManufacturingInfo - RWKDATE=%-8.8s\n", + logPrefix(port), data+118); + + /* display the part number */ + strncpy(tmpstr, (char *)data+58, 16); + for (i = 0; i < 16; i++) + if ( tmpstr[i] == ' ') + break; + tmpstr[i] = '\0'; + + printf("Programmed part number is <%-s>\n", tmpstr); + if (wFlag) + fprintf(logFile, "%s: AltaDisplayManufacturingInfo - PARTNUM=%-s\n", + logPrefix(port), tmpstr); + } + else + { + printf("Log sense page 0x35 for programmed serial number, part number, and dates failed!\n"); + if (wFlag) + fprintf(logFile, "%s: Log sense page 0x35 for programmed serial number, part number, and dates: FAIL\n", + logPrefix(port)); + } + + return 1; +} + + +int +doResetAlta(MPT_PORT *port) +{ + int bus; + int target; + unsigned char data[128]; + int t; + int n; + + if (selectAltaDevice(port, &bus, &target) != 1) + return 0; + + t = doModeSense(port, bus, target, 0, 0x32, 0, 0, data, sizeof data); + n = data[0] + 1; + + if ((t == 1) && (n >= 12+6)) + { + /* set the reboot bit */ + data[12+5] = (unsigned char)(data[12+5] | 1<<3); + } + else + { + printf("Read of mode page 0x32 failed!\n"); + if (wFlag) + fprintf(logFile, "%s: Read of mode page 0x32 for device reset: FAIL\n", + logPrefix(port)); + return 0; + } + + if (doModeSelect(port, bus, target, 0, 1, data, n) != 1) + { + printf("Write of mode select page 0x32 failed!\n"); + if (wFlag) + fprintf(logFile, "%s: Write of mode select page 0x32 for device reset: FAIL\n", + logPrefix(port)); + return 0; + } + + printf("Alta reset complete\n"); + return 1; +} + + +char * +translateExpanderEventCode(int code) +{ + switch (code) + { + case 1: return "POST_EVENT "; + case 2: return "SOD_EVENT "; + case 3: return "TSTAMP_RESET"; + case 4: return "FAULT_EVENT "; + case 5: return "WDOG_RESET "; + case 6: return "SES_EVENT "; + case 7: return "SCE_EVENT "; + case 0xFF: return "INVALID "; + } + + return "ERROR "; +} + + +int +decodeExpanderLogEntries(FILE *file, unsigned char *buf, int length) +{ + int offset; + U32 tstamp; + U32 eventid; + U8 size; + U8 pad; + int i; + + fprintf(file, "Timestamp Event Event Data\n"); + fprintf(file, "===============================================================================\n"); + + offset = 0; + while (offset < length) + { + /* timestamp is number of microseconds since start of day. This will wrap every 72 minutes or so. */ + tstamp = get32x(*(U32 *)&(buf[offset])); + if (tstamp == 0xffffffff) + break; + + offset += 4; + eventid = get32x(*(U32 *)&(buf[offset])); + offset += 4; + pad = (buf[offset] & 0xc0) >> 6; + /* data size is the size field minus the size field itself, the pad bytes, and the sizeClone field */ + size = ((buf[offset] & 0x3f) * 4) - 1 - pad - 1; + + /* move the offset to the start of the data bytes */ + offset++; + + fprintf(file, "%02d:%02d.%06d %12.12s ", tstamp / (60 * 1000 * 1000), + (tstamp % (60 * 1000 * 1000)) / (1000 * 1000), + tstamp % (1000 * 1000), + translateExpanderEventCode(eventid)); + + for (i=0; i < size; i++) + fprintf(file, "%c", buf[offset + i]); + + fprintf(file, "\n"); + offset += size + pad + 1; //the +1 is for the sizeClone field + } + return 1; +} + + +#define EXPANDER_LOG_SIGNATURE 0x74655065 + +int +doDisplayExpanderLogEntries(MPT_PORT *port) +{ + int bus; + int target; + FILE *file; + int n; + unsigned char desc[4]; + char name[256]; + int length; + int offset; + unsigned char *region1Buf = NULL; + int region1Len; + unsigned char *region2Buf = NULL; + int region2Len; + U32 r1Unused; + U32 r2Unused; + int r1Valid = TRUE; + int r2Valid = TRUE; + int firstEntryOffset; + int expanderType; + + if (selectExpander(port, &bus, &target, NULL, NULL, &expanderType) != 1) + return 0; + + if (expanderType != EXPANDER_TYPE_LSI_GEN1_YETI) + { + printf("This option is only supported on LSI SAS1 expanders (Yeti).\n"); + return 0; + } + + n = getFileName(name, sizeof name, stdin, "output", 0); + if (n > 0) + { + file = fopen(name, "w"); + if (file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + return 0; + } + } + else + { + printf("Event log won't be saved\n"); + return 1; + } + + /* read all the data from the first region */ + if (doReadBufferFull(port, bus, target, 0, 3, 6, 0, desc, sizeof desc) == 1) + { + region1Len = get3bytes(desc, 1); + if (region1Len == 0) + r1Valid = FALSE; + } + else + { + printf("Buffer 6 length is unknown, considering region 1 invalid\n"); + r1Valid = FALSE; + region1Len = 0; + } + + if (r1Valid) + { + length = CHUNK_SIZE; + + if (length > region1Len) + length = region1Len; + + region1Buf = (unsigned char *)malloc(region1Len); + + offset = 0; + while (TRUE) + { + if (doReadBufferFull(port, bus, target, 0, 2, 6, offset, region1Buf+offset, length) != 1) + { + printf("There as a problem reading buffer ID 6, considering region 1 invalid\n"); + r1Valid = FALSE; + break; + } + + offset += length; + if (offset >= region1Len) + break; + + if (length > region1Len - offset) + length = region1Len - offset; + } + } + + /* read all the data from the second region */ + if (doReadBufferFull(port, bus, target, 0, 3, 7, 0, desc, sizeof desc) == 1) + { + region2Len = get3bytes(desc, 1); + if (region2Len == 0) + r2Valid = FALSE; + } + else + { + printf("Buffer 7 length is unknown, considering region 2 invalid\n"); + r2Valid = FALSE; + region2Len = 0; + } + + if (r2Valid) + { + length = CHUNK_SIZE; + + if (length > region2Len) + length = region2Len; + + region2Buf = (unsigned char *)malloc(region2Len); + + offset = 0; + while (TRUE) + { + if (doReadBufferFull(port, bus, target, 0, 2, 7, offset, region2Buf+offset, length) != 1) + { + printf("There as a problem reading buffer ID 7, considering region 2 invalid\n"); + r2Valid = FALSE; + break; + } + + offset += length; + if (offset >= region2Len) + break; + + if (length > region2Len - offset) + length = region2Len - offset; + } + } + + if (!r1Valid || get32x(*(U32 *)&(region1Buf[0])) != EXPANDER_LOG_SIGNATURE) + { + printf("Region 1 does not have a valid event log signature\n"); + fprintf(file, "Region 1 does not have a valid event log signature\n"); + r1Valid = FALSE; + r1Unused = 0; + } + else + { + fprintf(file, "- Region 1 Details -\n"); + fprintf(file, " Region Length = %d bytes\n", region1Len); + fprintf(file, " Header Timestamp: %08x\n", get32x(*(U32 *)&(region1Buf[4]))); + r1Unused = get32x(*(U32 *)&(region1Buf[8])); + fprintf(file, " UnusedBytes: %08x\n", r1Unused); + fprintf(file, " SizeOfLog: %04x\n", get16x(*(U16 *)&(region1Buf[12]))); + fprintf(file, " FirstEntryOffset: %02x\n", region1Buf[14]); + fprintf(file, " RegionType: %02x\n", region1Buf[15]); + fprintf(file, " HeaderVersion: %02x\n", region1Buf[16]); + fprintf(file, " SequenceNumber: %02x\n\n", region1Buf[18]); + } + + if (!r2Valid || get32x(*(U32 *)&(region2Buf[0])) != EXPANDER_LOG_SIGNATURE) + { + printf("Region 2 does not have a valid event log signature\n"); + fprintf(file, "Region 2 does not have a valid event log signature\n"); + r2Valid = FALSE; + r2Unused = 0; + } + else + { + fprintf(file, "- Region 2 Details -\n"); + fprintf(file, " Region Length = %d bytes\n", region2Len); + fprintf(file, " Header Timestamp: %08x\n", get32x(*(U32 *)&(region2Buf[4]))); + r2Unused = get32x(*(U32 *)&(region2Buf[8])); + fprintf(file, " UnusedBytes: %08x\n", r2Unused); + fprintf(file, " SizeOfLog: %04x\n", get16x(*(U16 *)&(region1Buf[12]))); + fprintf(file, " FirstEntryOffset: %02x\n", region2Buf[14]); + fprintf(file, " RegionType: %02x\n", region2Buf[15]); + fprintf(file, " HeaderVersion: %02x\n", region2Buf[16]); + fprintf(file, " SequenceNumber: %02x\n\n", region2Buf[18]); + } + + if (r1Valid && r1Unused == 0xFFFFFFFF) + { + /* region 1 is actively in use, so if region 2 is valid then it + * contains the older entries so print it first + */ + if (r2Valid) + { + if (r2Unused == 0xFFFFFFFF) + { + printf("Strange, both regions appear to be active!!\n"); + fprintf(file, "Strange, both regions appear to be active!!\n"); + } + + fprintf(file, "\n-------------- Events from Region 2 -------------\n\n"); + firstEntryOffset = region2Buf[14]; + decodeExpanderLogEntries(file, ®ion2Buf[firstEntryOffset], region2Len - firstEntryOffset); + } + fprintf(file, "\n-------------- Events from Region 1 -------------\n\n"); + firstEntryOffset = region1Buf[14]; + decodeExpanderLogEntries(file, ®ion1Buf[firstEntryOffset], region1Len - firstEntryOffset); + } + else if (r2Valid && r2Unused == 0xFFFFFFFF) + { + /* region 2 is actively in use, so if region 1 is valid then it + * contains the older entries so print it first + */ + if (r1Valid) + { + fprintf(file, "\n-------------- Events from Region 1 -------------\n\n"); + firstEntryOffset = region1Buf[14]; + decodeExpanderLogEntries(file, ®ion1Buf[firstEntryOffset], region1Len - firstEntryOffset); + } + fprintf(file, "\n-------------- Events from Region 2 -------------\n\n"); + firstEntryOffset = region2Buf[14]; + decodeExpanderLogEntries(file, ®ion2Buf[firstEntryOffset], region2Len - firstEntryOffset); + } + else + { + printf("No valid log regions found!\n"); + fprintf(file, "No valid log regions found!\n"); + } + + if (r1Valid) + free(region1Buf); + if (r2Valid) + free(region2Buf); + + fclose(file); + + return 1; +} + + +int +doClearExpanderLogEntries(MPT_PORT *port) +{ + int bus; + int target; + unsigned char buf[4]; + int expanderType; + + if (selectExpander(port, &bus, &target, NULL, NULL, &expanderType) != 1) + return 0; + + if (expanderType != EXPANDER_TYPE_LSI_GEN1_YETI) + { + printf("This option is only supported on LSI SAS1 expanders (Yeti).\n"); + return 0; + } + + printf("\nAfter clearing the log regions, no logging will occur until the expander is reset\n"); + if (yesFlag == FALSE) + { + printf("\nAre you sure you want to continue? [Yes or No, default is No] "); + } + + if (getYesNoAnswer(0) != 1) + return 0; + + memset(buf, 0, sizeof buf); + + if (doWriteBufferFull(port, bus, target, 0, 2, 6, 0, buf, sizeof buf) != 1) + printf("Error clearing region 1 (buffer ID 6)\n"); + + if (doWriteBufferFull(port, bus, target, 0, 2, 7, 0, buf, sizeof buf) != 1) + printf("Error clearing region 2 (buffer ID 7)\n"); + + printf("Clearing expander log entries is complete.\n"); + return 1; +} + + +#define UART_DEFAULT_BUF_SIZE 1024 // 1MB + +#if DOS || EFI +#define UART_MAX_BUF_SIZE 1024 // 1MB - limited by mpt_shared_t's scratch[] buffer in mpt.c +#else +#define UART_MAX_BUF_SIZE 16384 // 16MB +#endif + +int +doUartDebugConsole(MPT_PORT *port) +{ + Mpi2ToolboxDiagnosticCliRequest_t req; + Mpi2ToolboxDiagnosticCliReply_t rep; + int n, m; + U32 x; + U8 *output; + char name[256]; + FILE *out_file; + char input[16]; + int lines; + U32 size; + U32 newsize; + int firstTime; + time_t now; + U32 dataLen; + U32 finalRetLength; +#if WIN32 + int maxPages; +#endif + + lines = 0; + + size = 0; + +#if WIN32 + getAdapterPropertiesMaxPages(port, &maxPages); + + if (maxPages) + { + /* calculate buffer size. generally expect maxPages to return 257. + * Subtract one page to account for possible partial page and + * assume a 4k page size + */ + size = ((maxPages - 1) * 4) * 1024; + } +#endif + + if (size == 0) + { + size = UART_DEFAULT_BUF_SIZE * 1024; + } + + output = NULL; + if (gFlag == FALSE) + { + output = (U8 *)malloc(size); + + if (output == NULL) + printf("ERROR: Unable to allocate a %d KB buffer\n", size/1024); + } + + if (gFlag == TRUE || output == NULL) + { + while (1) + { + printf("Allocated buffer size for displaying CLI command output: [in KB, max is %d, default is %d] ", + UART_MAX_BUF_SIZE, size/1024); + lines++; + newsize = getNumberAnswer(1, UART_MAX_BUF_SIZE, UART_DEFAULT_BUF_SIZE) * 1024; + + output = (U8 *)malloc(newsize); + + if (output == NULL) + printf("ERROR: Unable to allocate a %d KB buffer\n", newsize/1024); + else + break; + } + size = newsize; + } + + out_file = stdout; + while (1) + { + printf("Enter output file, or RETURN to send output to the screen: "); + lines++; + m = getStringFromArgs(name, sizeof name, stdin); + + if (m > 0) + { + out_file = fopen(name, "a"); + if (out_file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + continue; + } + } + break; + } + + printf("\n-- Starting UART Debug Console --\n(Type 'exit' to quit)\n\n"); + printf("NOTE: Messages asynchronously printed to the UART console\n"); + printf(" are NOT visible through this interface.\n\n"); + lines+=3; + + if (out_file != stdout) + { + time(&now); + fprintf(out_file, "\n%s\nStarting UART Debug Console\n(Type 'exit' to quit)\n\n", ctime(&now)); + fprintf(out_file, "NOTE: Messages asynchronously printed to the UART console\n"); + fprintf(out_file, " are NOT visible through this interface.\n\n"); + } + + firstTime = TRUE; + while (1) + { + memset(&req, 0, sizeof req); + if (firstTime) + { + strcpy((char *)req.DiagnosticCliCommand, "help"); + n = 4; + } + else + { + // print the console prompt and get the user input + printf("%%"); + n = getStringFromArgs((char *)(req.DiagnosticCliCommand), sizeof req.DiagnosticCliCommand, stdin); + } + + if (n > 0) + { + if ( strncmp((const char *)(req.DiagnosticCliCommand), "exit", 4) == 0 ) + { + break; + } + + /* if writing output to a file then echo the CLI command to the file */ + if (out_file != stdout && !firstTime) + fprintf(out_file, "%%%s\n", req.DiagnosticCliCommand); + + memset(&rep, 0, sizeof rep); + memset(output, 0, size); + + req.Function = MPI_FUNCTION_TOOLBOX; + req.Tool = MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL; + req.DataLength = set32(size); + + if (doMptCommandCheck(port, &req, sizeof req - sizeof req.SGL, &rep, sizeof rep, + output, size, NULL, 0, SHORT_TIME) == 1) + { + dataLen = get32(rep.ReturnedDataLength); +#if WIN32 + finalRetLength = min(dataLen, gRetDataLen); +#else + finalRetLength = dataLen; +#endif + lines = 0; + + for ( x=0; x < min(finalRetLength, size); x++ ) + { + fputc(output[x], out_file); + + if (paged && out_file == stdout) + { + if (output[x] == '\n') + lines++; + if (lines >= paged) + { + fputs("\n--more, hit RETURN ('p' then RETURN to stop paging, 'q' then RETURN to quit)--", stdout); + if (fgets(input, 15, stdin)); + printf("\n"); + if (input[0] == 'p') + { + paged = 0; + } + if (input[0] == 'q') + { + break; + } + lines = 0; + } + } + } + + if (!firstTime) + { + /* strictly speaking the following should just be a '>' comparison, but some + * revisions of the firmware set ReturnedDataLength as the number of bytes + * returned rather than the number of bytes that could be returned if the + * allocated buffer was large enough Using '>=' helps indicate a possible + * issue in the output. + */ + if (dataLen >= size) + { + /* print warnings to the screen as well as the output file if one is in use */ + printf("\n\nWARNING: The command output was truncated!\n"); + printf("The output contains %d bytes but the allocated buffer is only %d bytes\n", + dataLen, size); + lines+=2; + if (out_file != stdout) + { + printf("\n%d bytes of output written to %s\n", size, name); + lines++; + fprintf(out_file, "\n\nWARNING: The command output was truncated!\n"); + fprintf(out_file, "The output contains %d bytes but the allocated buffer is only %d bytes\n", + dataLen, size); + } + } +#if WIN32 + else if ( gRetDataLen < size ) + { + /* print warnings to the screen as well as the output file if one is in use */ + printf("\n\nWARNING: The command output was truncated!\n"); + printf("The output contains %d bytes and the allocated buffer is %d bytes\n", dataLen, size); + printf("however, the MPT driver was forced to truncate the output at %d bytes.\n", gRetDataLen); + printf("This was likely due to system memory fragmentation.\n"); + + lines+=4; + if (out_file != stdout) + { + printf("\n%d bytes of output written to %s\n", gRetDataLen, name); + lines++; + fprintf(out_file, "\n\nWARNING: The command output was truncated!\n"); + fprintf(out_file, "The output contains %d bytes and the allocated buffer is %d bytes\n", dataLen, size); + fprintf(out_file, "however, the MPT driver was forced to truncate the output at %d bytes.\n", gRetDataLen); + fprintf(out_file, "This was likely due to system memory fragmentation.\n"); + } + } +#endif + else + { + if (out_file != stdout) + { + printf("\n%d bytes of output written to %s\n", dataLen, name); + lines++; + } + } + } + } + else if (firstTime && + (get16(rep.IOCStatus) == MPI_IOCSTATUS_INVALID_FIELD || + get16(rep.IOCStatus) == MPI_IOCSTATUS_INVALID_FUNCTION)) + { + printf("There was a problem getting the UART console data.\n"); + printf("This firmware may not support the UART passthrough feature.\n"); + } + } + firstTime = FALSE; + } + if (out_file != stdout) + fclose(out_file); + + free(output); + return 1; +} + + +#if WIN32 +int +getAdapterPropertiesMaxPages(MPT_PORT *port, int *maxPages) +{ + int status; + STORAGE_PROPERTY_QUERY query; + DWORD retLen; + STORAGE_ADAPTER_DESCRIPTOR desc; + + memset(&query, 0, sizeof(query)); + memset(&desc, 0, sizeof(desc)); + query.PropertyId = StorageAdapterProperty; + query.QueryType = PropertyStandardQuery; + + retLen = 0; + + status = DeviceIoControl(port->fileHandle, IOCTL_STORAGE_QUERY_PROPERTY, + &query, sizeof(query), &desc, sizeof(desc), &retLen, NULL); + + if (status == 1) + { + *maxPages = desc.MaximumPhysicalPages; + return 1; + } + else + { + *maxPages = 0; + return 0; + } +} +#endif + + +int +doSendPowerManagementControlMPI(MPT_PORT *port) +{ + MPI2_PWR_MGMT_CONTROL_REQUEST req; + MPI2_PWR_MGMT_CONTROL_REPLY rep; + int input; + int mpt_return; + + memset( &req, 0, sizeof(req) ); + memset( &rep, 0, sizeof(rep) ); + + req.Function = MPI2_FUNCTION_PWR_MGMT_CONTROL; + + // Query for the data + input = 0x01; + printf("Feature: [1=DA_PHY, 2=Port Width Mod, 3=PCIE, 4=IOC, 5=Global, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Feature = input; + + input = 0x00; + printf("Chain Offset: [0 to 255, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.ChainOffset = input; + + switch (req.Feature) + { + case MPI2_PM_CONTROL_FEATURE_IOC_SPEED: + input = 0x01; + printf("IOC Speed (Parameter1): [1=100%%, 2=50%%, 4=25%%, 8=12.5%%, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter1 = input; + break; + case MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND: + input = 0x00; + printf("PHY number (Parameter1): [0 to 255, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter1 = input; + + input = 0x01; + printf("IOC Action (Parameter2): [1=Partial, 2=Slumber, 3=Exit, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter2 = input; + break; + case MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION: + input = 0x00; + printf("Modulation Group Number (Parameter1): [0 to 255, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter1 = input; + + input = 0x01; + printf("IOC Action (Parameter2): [1=Request, 2=Change, 3=Relinquish, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter2 = input; + + if ( req.Parameter2 == MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION ) + { + input = 0x03; + printf("New Level (Parameter3): [0=25%%, 1=50%%, 2=75%%, 3=100%%, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter3 = input; + } + break; + case MPI2_PM_CONTROL_FEATURE_PCIE_LINK: + input = 0x00; + printf("Speed (Parameter1): [0=2.5G, 1=5G, 2=8G, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter1 = input; + + input = 0x01; + printf("Width (Parameter2): [1=X1, 2=X2, 4=X4, 8=X8, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter2 = input; + break; + case MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE: + input = 0x01; + printf("Action (Parameter1): [1=Take, 2=Change, 3=Release, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter1 = input; + + if (req.Parameter1 == MPI2_PM_CONTROL_PARAM1_CHANGE_GLOBAL_MODE) + { + input = 0x01; + printf("Mode (Parameter2): [1=Full, 8=Reduced, 64=Standby, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter2 = input; + } + break; + default: + input = 0x00; + printf("Parameter1: [0 to 255, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter1 = input; + + input = 0x00; + printf("Parameter2: [0 to 255, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter2 = input; + + input = 0x00; + printf("Parameter3: [0 to 255, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter3 = input; + + input = 0x00; + printf("Parameter4: [0 to 255, default is %d] ", input); + input = getNumberAnswer(0, 255, input); + req.Parameter4 = input; + break; + } //switch(function) + + // Send the message + mpt_return = doMptCommand(port, &req, sizeof req, &rep, sizeof rep, NULL, 0, NULL, 0, SHORT_TIME); + if(mpt_return != 1) + { + printf("ERROR: Could not send MPI message\n"); + return -1; + } + + printf("\n\n Reply:\n"); + printf(" Feature: [0x%08X]\n", rep.Feature); + printf(" IOCStatus: [0x%08X] (%s)\n", get16(rep.IOCStatus), translateIocStatus(get16(rep.IOCStatus))); + printf(" IOCLogInfo: [0x%08X]\n", get32(rep.IOCLogInfo)); + + return 1; +} + + +// IoUnit7 is Read-only, so this function only displays the info contained in the page +int +doIoUnit7Settings(MPT_PORT *port) +{ + Mpi2IOUnitPage7_t page; + + if (getConfigPage(port, MPI2_CONFIG_PAGETYPE_IO_UNIT, 7, 0, &page, sizeof page) != 1) + { + printf("Couldn't get IOUnitPage7\n"); + printf(" IOC Status: %s", translateIocStatus(port->ioc_status) ); + return 0; + } + + printf(" CurrentPowerMode: 0x%02X\n", page.CurrentPowerMode ); + printf(" PreviousPowerMode: 0x%02X\n", page.PreviousPowerMode ); + printf(" PCIeWidth: 0x%02X\n", page.PCIeWidth ); + printf(" PCIeSpeed: 0x%02X\n", page.PCIeSpeed ); + printf(" ProcessorState: 0x%08X\n", get32(page.ProcessorState) ); + printf(" PowerManagementCapabilities: 0x%08X\n", get32(page.PowerManagementCapabilities) ); + printf(" IOCTemperature: 0x%04X\n", get16(page.IOCTemperature) ); + printf(" IOCTemperatureUnits: 0x%02X\n", page.IOCTemperatureUnits ); + printf(" IOCSpeed: 0x%02X\n", page.IOCSpeed ); + printf(" BoardTemperature: 0x%04X\n", get16(page.BoardTemperature) ); + printf(" BoardTemperatureUnits: 0x%02X\n", page.BoardTemperatureUnits ); + + return 1; +} + + +int +doSasIoUnit8Settings(MPT_PORT *port) +{ + Mpi2SasIOUnitPage8_t page; + int input; + + memset( &page, 0, sizeof(page) ); + if (getConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 8, 0, &page, sizeof page) != 1) + { + printf("\nCouldn't get SasIoUnitPage8\n"); + printf(" IOC Status: %s", translateIocStatus(port->ioc_status) ); + return 0; + } + + // Dump the page first + printf(" PowerManagementCapabilities: 0x%08X\n", get32(page.PowerManagementCapabilities) ); + printf(" TxRxSleepStatus: 0x%02X\n\n", page.TxRxSleepStatus ); + + printf("Edit this page? [0=no, 1=yes, default is %d] ", 0); + input = getNumberAnswer(0, 1, 0); + + if(input == 1) + { + input = page.PowerManagementCapabilities; + printf("PowerManagementCapabilities: [0 to 0xFFFFFFF, default is %x] ", input); + input = getNumberAnswerHex(0, 0xFFFFFFF, input); + page.PowerManagementCapabilities = set32(input); + + input = page.TxRxSleepStatus; + printf("TxRxSleepStatus: [0 to 0xFF, default is %x] ", input); + input = getNumberAnswerHex(0, 0xFF, input); + page.TxRxSleepStatus = input; + + if (setConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 8, 0, &page, sizeof page) != 1) + { + printf("\nFailed to save changes to NVRAM!\n"); + printf(" IOC Status: %s", translateIocStatus(port->ioc_status) ); + return 0; + } + } + + return 1; +} + + +int +dumpSasDevicePage0sLong(MPT_PORT *port) +{ + Mpi2SasDevicePage0_t SASDevicePage0; + U32 handle; + int flags; + int deviceIndex; + U32 info; + int bit; + + deviceIndex = 0; + handle = 0xffff; + + // Decode DeviceInfo first + printf(" | |S|S|S|S|S|S|S|S| | |A| |\n"); + printf(" |T|A|M|T|S|A|M|T|S| | |T| |\n"); + printf(" |y|T|P|P|P|T|P|P|P| |L|A|S|\n"); + printf(" |p|A|i|i|i|A|t|t|t|D|S|P|E|\n"); + printf("SASAddress PhyNum Handle |e|h|n|n|n|d|a|a|a|A|I|I|P|\n"); + printf("---------------------------------|-|-|-|-|-|-|-|-|-|-|-|-|-|\n"); + while (TRUE) + { + if (getConfigPage(port, MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0, handle, + &SASDevicePage0, sizeof SASDevicePage0) != 1) + break; + + handle = get16(SASDevicePage0.DevHandle); + info = get32(SASDevicePage0.DeviceInfo); + + printf("%08x%08x", get32(SASDevicePage0.SASAddress.High), get32(SASDevicePage0.SASAddress.Low)); + printf(" %04d", SASDevicePage0.PhyNum ); + printf(" %04d", handle ); + printf(" |%d|", info & 0x03); // Device type + for( bit = 3; bit <= 14; bit++) + { + printf("%d|", info & (1< 0) + { + out_file = fopen(name, "a"); + if (out_file == NULL) + { + printf("Open failure for file %s\n", name); + perror("Error is"); + out_file = stdout; + continue; + } + } + break; + } + + printf("\n-- Starting Expander UART Console --\n(Type 'exit' to quit)\n\n"); + printf("NOTE: Messages asynchronously printed to the UART console\n"); + printf(" are NOT visible through this interface.\n\n"); + lines+=3; + if (out_file != stdout) + { + time(&now); + fprintf(out_file, "\n%s\nStarting Expander UART Console --\n(Type 'exit' to quit)\n\n", ctime(&now)); + fprintf(out_file, "NOTE: Messages asynchronously printed to the UART console\n"); + fprintf(out_file, " are NOT visible through this interface.\n\n"); + } + + cmd_seq_id = (U16*)(&command[2]); + seq_id = 0; + command[0] = 0x0; + command[1] = 0x0; + + while (1) + { + drop_paged_output = 0; + printf("\n cmd >"); + + memset(&(command[4]), 0x0, 81); + n = getStringFromArgs((char*)&(command[4]), 80, stdin); + if (n > 0) + { + if (strncmp ((const char *)(&(command[4])), "exit", 5) == 0) + { + break; + } + /* if writing output to a file then echo the CLI command to the file */ + if (out_file != stdout) + fprintf(out_file, "\n cmd >%s\n", &(command[4])); + *cmd_seq_id = set16x(seq_id); + doWriteBufferFull(port, bus, target, 0, 1, 0xc4, 0, command, sizeof command); + transfer_complete = 0; + } + else + { + transfer_complete = 1; + } + + offset = 0; + lines = 0; + memset(output, 0, sizeof output); + while (!transfer_complete) + { + n = doReadBufferFull(port, bus, target, 0, 1, 0xc4, offset, output, sizeof output); + if (!n) + { + if (out_file != stdout && out_file != NULL) + { + fclose(out_file); + } + return 0; + } + + transfer_complete = output[0] & 0x8; + ret_seq_id = get16x(*(U16*)(&output[2])); + bytes_read = get16x(*(U16*)(&output[4])); + /* offset is incremented by the number of bytes of data plus the + read response header size + */ + offset += ( bytes_read + 6 ); + if (ret_seq_id != seq_id) + { + printf("Sequence ID mismatch \n"); + lines++; + } + + /* Output data starts at byte 6, only print if not dumping output + and index is within valid ranges for the response bytes and the + output buffer + */ + for ( index=6; + drop_paged_output == 0 && index < bytes_read + 6 && index < sizeof output; + index++ ) + { + fputc(output[index], out_file); + + if (paged && out_file == stdout) + { + if (output[index] == '\n') + lines++; + if (lines >= paged) + { + fputs("\n--more, hit RETURN ('p' then RETURN to stop paging, 'q' then RETURN to quit)--", stdout); + if (fgets(input, 15, stdin)); + printf("\n"); + if (input[0] == 'p') + { + paged = 0; + } + if (input[0] == 'q') + { + drop_paged_output = 1; + break; + } + lines = 0; + } + } + } + + if (out_file != stdout) + { + printf("\n%d bytes of output written to %s\n", bytes_read, name); + lines++; + } + + /* Sleep for a second if the expander didn't output anything + before checking again + */ + if (!transfer_complete && ( bytes_read == 0 )) + sleep(1); + } // keep getting more response data + seq_id++; + } // next command + + if (out_file != stdout && out_file != NULL) + fclose(out_file); + + return 1; + +} + + +#if EFI +#undef main +#undef malloc +#undef free +#include "helper.c" +#endif + +/* vi: set sw=4 ts=4 sts=4 et :iv */ diff --git a/source/mpt.c b/source/mpt.c new file mode 100755 index 0000000..1c9fc32 --- /dev/null +++ b/source/mpt.c @@ -0,0 +1,2680 @@ +/*************************************************************************** + * * + * Copyright 2012 LSI Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Corporation. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Corporation. * + * * + *************************************************************************** +*/ +/* + * mpt -- simple driver for MPT adapters (FC, SCSI, and SAS/SATA) + * + * Written by Stephen F. Shirron, August 9, 2005 + */ + + +#ifdef DISABLE_TIMEOUTS +static time_t local_time = 0; +#define time(x) (local_time) +#endif + + +#define NUM_REPLIES 7 +#define REPLY_FREE_SIZE 8 +#define REPLY_POST_SIZE 16 +#define COMMAND_CONTEXT 0x111111 +#define PASS_THRU_CONTEXT 0x555555 + + +#define mpi1 (adap->mpt_version < MPI2_VERSION_02_00) +#define mpi2 (adap->mpt_version >= MPI2_VERSION_02_00) +#define mpi20 ((adap->mpt_version >= MPI2_VERSION_02_00) && (adap->mpt_version < MPI2_VERSION_02_05)) +#define mpi25 (adap->mpt_version >= MPI2_VERSION_02_05) + + +typedef struct mpt_io_rep +{ + union + { + SCSIIOReply_t default_reply; + U32 reply[32]; + } mf; +} mpt_io_rep_t; + + +typedef struct mpt_shared +{ + mpt_io_rep_t replies[NUM_REPLIES]; + U32 message[32]; + U32 free_queue[REPLY_FREE_SIZE]; + MPI2_DEFAULT_REPLY_DESCRIPTOR + post_queue[REPLY_POST_SIZE]; + U16 data[64]; + U32 config[256]; + U8 scratch[1024*1024 + 1024]; // 1MB + 1K - big enough for 1MB payload plus request/response + U32 hrsm_value; +} mpt_shared_t; + + +typedef struct mpt_adap +{ + MPT_PORT *port; + HANDLE partner_adap; + char *name; + U16 vendor_id; + U16 device_id; + U8 revision_id; + U8 segment_number; + U8 bus_number; + U8 device_function; + int mpt_version; + int hrsm_capable; + U32 hrsm_value; + U32 msg_context; + int restart_needed; + int port_enable_needed; + int config_active; + int command_active; + mpt_shared_t *shared; + mpt_bus_addr_t shared_ba; + int message_size; + int reply_depth; + int credits; + int port_count; + int block_size; + int port_type; + int host_id; + U32 interrupt_mask; + int max_targets; + int bus_reset_needed; + U32 capabilities[16]; + int ioc_online; + int port_online; + int bootloader; + int loaddevice; + U8 *fw_image; + int fw_image_size; + int fw_image_asked; + U32 mem_size; + U32 diagmem_size; +#if DOS + U32 io_addr; + U32 mem_addr; + U32 mem_virt; + U32 diagmem_addr; + U32 diagmem_virt; + CONTIGUOUS_MEMORY shared_contig_mem; +#endif +#if EFI + EFI_HANDLE handle; + EFI_PCI_IO_PROTOCOL *pci_io; + void *buffer_mapping; + int disconnected; +#endif + int io; + int mem; + int diagmem; + int free_index; + int post_index; +} mpt_adap_t; + + +#define rl(x) mpt_read32(adap, MPI_##x##_OFFSET, adap->mem) +#define wl(x,y) mpt_write32(adap, MPI_##x##_OFFSET, y, adap->mem) +#define rl2(x) mpt_read32(adap, MPI2_##x##_OFFSET, adap->mem) +#define wl2(x,y) mpt_write32(adap, MPI2_##x##_OFFSET, y, adap->mem) +#define rlio(x) mpt_read32(adap, MPI_##x##_OFFSET, adap->io) +#define wlio(x,y) mpt_write32(adap, MPI_##x##_OFFSET, y, adap->io) +#define rldiag(x,y) wl(TEST_BASE_ADDRESS, x & ~mask); y = mpt_read32(adap, x & mask, adap->diagmem) +#define wldiag(x,y) wl(TEST_BASE_ADDRESS, x & ~mask); mpt_write32(adap, x & mask, y, adap->diagmem) +U32 mpt_read32(mpt_adap_t *adap, int offset, int bar) +{ + U32 data; + +#if DOS + if (bar == adap->mem) + data = *(U32 *)(adap->mem_virt + offset); + else if (bar == adap->diagmem) + data = *(U32 *)(adap->diagmem_virt + offset); + else + data = inpd(adap->io_addr + offset); +#endif +#if EFI + if (bar == adap->mem || bar == adap->diagmem) + adap->pci_io->Mem.Read(adap->pci_io, EfiPciIoWidthUint32, (char)bar, offset, 1, &data); + else + adap->pci_io->Io.Read(adap->pci_io, EfiPciIoWidthUint32, (char)bar, offset, 1, &data); +#endif + + return data; +} +void mpt_write32(mpt_adap_t *adap, int offset, U32 data, int bar) +{ +#if DOS + if (bar == adap->mem) + *(U32 *)(adap->mem_virt + offset) = data; + else if (bar == adap->diagmem) + *(U32 *)(adap->diagmem_virt + offset) = data; + else + outpd(adap->io_addr + offset, data); +#endif +#if EFI + if (bar == adap->mem || bar == adap->diagmem) + adap->pci_io->Mem.Write(adap->pci_io, EfiPciIoWidthUint32, (char)bar, offset, 1, &data); + else + adap->pci_io->Io.Write(adap->pci_io, EfiPciIoWidthUint32, (char)bar, offset, 1, &data); +#endif +} +void mpt_write8(mpt_adap_t *adap, int offset, U8 data) +{ +#if DOS + *(U8 *)(adap->diagmem_virt + offset) = data; +#endif +#if EFI + adap->pci_io->Mem.Write(adap->pci_io, EfiPciIoWidthUint8, (char)adap->diagmem, offset, 1, &data); +#endif +} +#define MPI_DEBUG_OFFSET 0x18 +#define MPI_FC909_BUG_OFFSET 0x90 +#define MPI_SAS1078_RESET_OFFSET 0x10FC + + +int mpt_adjust_delay(mpt_adap_t *adap, int n); +void mpt_delay(mpt_adap_t *adap, int n); +int mpt_get_doorbell(mpt_adap_t *adap); +int mpt_get_state(mpt_adap_t *adap); +int mpt_verify_enabled(mpt_adap_t *adap); +int mpt_verify_ready(mpt_adap_t *adap); +int mpt_verify_operational(mpt_adap_t *adap); +int mpt_wait_for_ready(mpt_adap_t *adap); +int mpt_restart(mpt_adap_t *adap); +int mpt_stop(mpt_adap_t *adap, int wait); +int mpt_start(mpt_adap_t *adap); +int mpt_port_online(mpt_adap_t *adap); +int mpt_wait_for_doorbell(mpt_adap_t *adap, time_t limit); +int mpt_wait_for_response(mpt_adap_t *adap, time_t limit); +int mpt_send_message(mpt_adap_t *adap, int length, time_t limit); +int mpt_receive_data(mpt_adap_t *adap, int length, time_t limit); +int mpt_issue_command_and_wait(mpt_adap_t *adap, int wait); +int mpt_issue_config_and_wait(mpt_adap_t *adap, int wait); +int mpt_issue_ioc_facts(mpt_adap_t *adap); +int mpt2_issue_ioc_facts(mpt_adap_t *adap); +int mpt_issue_ioc_init(mpt_adap_t *adap); +int mpt2_issue_ioc_init(mpt_adap_t *adap); +int mpt_initialize(mpt_adap_t *adap); +int mpt_issue_port_facts(mpt_adap_t *adap, int port); +int mpt2_issue_port_facts(mpt_adap_t *adap, int port); +int mpt_issue_port_enable(mpt_adap_t *adap, int port); +int mpt2_issue_port_enable(mpt_adap_t *adap, int port); +int mpt_issue_event_notification(mpt_adap_t *adap); +int mpt2_issue_event_notification(mpt_adap_t *adap); +int mpt_watchdog(mpt_adap_t *adap); +int mpt_init_device_capabilities(mpt_adap_t *adap); +int mpt_set_device_capabilities(mpt_adap_t *adap, int targ); +int mpt_set_on_bus_timer(mpt_adap_t *adap, int timeout); +int mpt_get_config_page(mpt_adap_t *adap, int type, int number, int address); +int mpt_set_config_page(mpt_adap_t *adap, int type, int number, int address); +int mpt_do_config_action(mpt_adap_t *adap, int action, int type, int number, int address, int length); +void mpt_bus_reset(mpt_adap_t *adap); +void mpt_interrupt(mpt_adap_t *adap); +void mpt2_interrupt(mpt_adap_t *adap); +int mpt_handle_reply(mpt_adap_t *adap, MPIDefaultReply_t *reply, U32 reply_ba); +void mpt2_handle_scsi_io_success(mpt_adap_t *adap, Mpi2DefaultReplyDescriptor_t *reply_desc); +void mpt2_handle_address_reply(mpt_adap_t *adap, Mpi2DefaultReplyDescriptor_t *reply_desc); +int mpt_fwdownloadboot(mpt_adap_t *adap); +int mpt_directdownload(mpt_adap_t *adap); + + +int +mpt_adjust_delay(mpt_adap_t *adap, int n) +{ + if (adap->revision_id == 0xff) + return n * 10; + + return n; +} + + +void +mpt_delay(mpt_adap_t *adap, int n) +{ +#if DOS + int i; + + for (i = 0; i < mpt_adjust_delay(adap, n); i++) + { + PciReadConfigWord(adap->bus_number, adap->device_function, PCI_CONFIG_DEVICE_ID); + } +#endif +#if EFI + udelay(mpt_adjust_delay(adap, n)); +#endif +} + + +int +mpt_get_doorbell(mpt_adap_t *adap) +{ + return rl(DOORBELL); +} + + +int +mpt_get_state(mpt_adap_t *adap) +{ + return rl(DOORBELL) & MPI_IOC_STATE_MASK; +} + + +int +mpt_verify_enabled(mpt_adap_t *adap) +{ + if (rl(DIAGNOSTIC) & MPI_DIAG_DISABLE_ARM) + if (mpt_stop(adap, TRUE)) + return mpt_restart(adap); + + return 1; +} + + +int +mpt_verify_ready(mpt_adap_t *adap) +{ + if (adap->restart_needed == TRUE) + return 0; + + if ((rl(DOORBELL) & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_READY) + return 0; + + return 1; +} + + +int +mpt_verify_operational(mpt_adap_t *adap) +{ + if (adap->restart_needed == TRUE) + return 0; + + if ((rl(DOORBELL) & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) + return 0; + + return 1; +} + + +int +mpt_wait_for_ready(mpt_adap_t *adap) +{ + U32 doorbell; + U32 diagnostic; + int state; + time_t limit = time(NULL) + mpt_adjust_delay(adap, 50); + + while (time(NULL) < limit) + { + doorbell = rl(DOORBELL); + state = doorbell & MPI_IOC_STATE_MASK; + if (state == MPI_IOC_STATE_FAULT) + { + printf("\n%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + if (wFlag) + fprintf(logFile, "%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + + printf("\nDo you want to continue? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + break; + + printf("\n"); + + adap->restart_needed = TRUE; + return 0; + } + if (state == MPI_IOC_STATE_READY) + { + adap->restart_needed = FALSE; + return 1; + } + diagnostic = rl(DIAGNOSTIC); + if (diagnostic & MPI_DIAG_FLASH_BAD_SIG) + { + if (adap->fw_image == NULL) + { + printf("\n%s: FLASH does not contain a valid image\n", adap->name); + if (wFlag) + fprintf(logFile, "%s: FLASH does not contain a valid image\n", + adap->name); + } + adap->restart_needed = TRUE; + return 0; + } + if (diagnostic & MPI_DIAG_DISABLE_ARM) + { + printf("\n%s: IOP ARM is disabled\n", adap->name); + if (wFlag) + fprintf(logFile, "%s: IOP ARM is disabled\n", + adap->name); + adap->restart_needed = TRUE; + return 0; + } + DELAY(1); + } + + return 0; +} + + +/* + * mpt_restart - completely restart the IOC and any outstanding commands. + */ +int +mpt_restart(mpt_adap_t *adap) +{ + int targ; + +// printf("mpt_restart called\n"); + + if (!mpt_verify_ready(adap)) + { + adap->restart_needed = FALSE; + adap->bus_reset_needed = FALSE; + + if (!mpt_stop(adap, TRUE)) + return 0; + } + + adap->config_active = FALSE; + adap->command_active = FALSE; + + if (!mpt_start(adap)) + return 0; + + if (adap->port_type == MPI_PORTFACTS_PORTTYPE_SCSI) + { + mpt_init_device_capabilities(adap); + + for (targ = 0; targ < adap->max_targets; targ++) + { + mpt_set_device_capabilities(adap, targ); + } + } + + return 1; +} + + +/* + * mpt_stop - stop the IOC (reset it). + */ +int +mpt_stop(mpt_adap_t *adap, int wait) +{ + time_t limit = time(NULL) + mpt_adjust_delay(adap, 30); + +// printf("mpt_stop called\n"); + +#if EFI + EFI_STATUS status; + + if (adap->disconnected == FALSE) + { + EFI_PCI_IO_PROTOCOL *pci_io; + + if (wait == FALSE) + { + return 1; + } + + if (adap->loaddevice == TRUE) + { + printf("This chip controls the device that this utility was loaded from.\n"); + printf("After this command, the load device cannot be accessed again\n"); + printf("to open files, until this utility has been exited and restarted.\n\n"); + } + + if (!EFI_ERROR(BS->DisconnectController(adap->handle, NULL, NULL))) + { + adap->disconnected = TRUE; + pci_io = adap->pci_io; + status = pci_io->Attributes(pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IO | + EFI_PCI_IO_ATTRIBUTE_MEMORY | + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | + EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE, NULL); + + if (status == EFI_UNSUPPORTED) + { + pci_io->Attributes(pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IO | + EFI_PCI_IO_ATTRIBUTE_MEMORY | + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL); + } + } + + if (adap->partner_adap) + { + if (!EFI_ERROR(BS->DisconnectController(adap->partner_adap->handle, NULL, NULL))) + { + adap->partner_adap->disconnected = TRUE; + pci_io = adap->partner_adap->pci_io; + status = pci_io->Attributes(pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IO | + EFI_PCI_IO_ATTRIBUTE_MEMORY | + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | + EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE, NULL); + + if (status == EFI_UNSUPPORTED) + { + pci_io->Attributes(pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IO | + EFI_PCI_IO_ATTRIBUTE_MEMORY | + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL); + } + } + } + } +#endif + + adap->port_online = FALSE; + + adap->interrupt_mask = MPI_HIM_RIM | MPI_HIM_DIM; + wl(HOST_INTERRUPT_MASK, rl(HOST_INTERRUPT_MASK) | adap->interrupt_mask); + + /* + * Reset the chip. + */ + if (adap->device_id == MPI_MANUFACTPAGE_DEVICEID_FC909) + { + rl(FC909_BUG); /* work around FC909 bug */ + } + + if (!(rl(DIAGNOSTIC) & MPI_DIAG_DRWE)) + { + wl(WRITE_SEQUENCE, 0); + wl(WRITE_SEQUENCE, MPI_WRSEQ_KEY_VALUE_MASK); + wl(WRITE_SEQUENCE, MPI_WRSEQ_1ST_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_2ND_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_3RD_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_4TH_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_5TH_KEY_VALUE); + DELAY(100); + } + + if (!(rl(DIAGNOSTIC) & MPI_DIAG_RESET_HISTORY) || + ((rl(DOORBELL) & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_RESET && + (rl(DOORBELL) & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_READY)) + { + if (adap->device_id == MPI_MANUFACTPAGE_DEVID_SAS1078) + { + wl(SAS1078_RESET, 0x7); + } + else + { + wl(DIAGNOSTIC, MPI_DIAG_RESET_ADAPTER); + } + DELAY(50000); + wl(WRITE_SEQUENCE, 0); + wl(WRITE_SEQUENCE, MPI_WRSEQ_KEY_VALUE_MASK); + wl(WRITE_SEQUENCE, MPI_WRSEQ_1ST_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_2ND_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_3RD_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_4TH_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_5TH_KEY_VALUE); + DELAY(100); + } + + wl(DIAGNOSTIC, 0); + + if (wait == FALSE) + { + while (time(NULL) < limit) + { + if (rl(DOORBELL) & MPI_IOC_STATE_MASK) + break; + if (rl(DIAGNOSTIC) & MPI_DIAG_DISABLE_ARM) + break; + DELAY(100); + } + + return 1; + } + + if (rl(DIAGNOSTIC) & MPI_DIAG_RESET_ADAPTER) + { + printf("\n%s: Failed to clear RESET ADAPTER\n", adap->name); + if (wFlag) + fprintf(logFile, "%s: Failed to clear RESET ADAPTER\n", + adap->name); + adap->restart_needed = TRUE; + return 0; + } + + adap->bootloader = FALSE; + + if (mpt_wait_for_ready(adap)) + return 1; + + if (mpt_fwdownloadboot(adap)) + return 1; + + if ((rl(DOORBELL) & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_RESET) + { + adap->restart_needed = FALSE; + + printf("\n%s: Failed to leave the RESET state\n", adap->name); + if (wFlag) + fprintf(logFile, "%s: Failed to leave the RESET state\n", + adap->name); + } + else + { + adap->restart_needed = TRUE; + + printf("\n%s: Failed to reset properly\n", adap->name); + if (wFlag) + fprintf(logFile, "%s: Failed to reset properly\n", + adap->name); + } + + return 0; +} + + +/* + * mpt_start - start the IOC (completely initialize it). + */ +int +mpt_start(mpt_adap_t *adap) +{ + int port; + +// printf("mpt_start called\n"); + + if (adap->bootloader == TRUE) + { + printf("\nBootLoader firmware cannot be made fully operational!\n"); + return 0; + } + + if (!mpt_issue_ioc_facts(adap)) + { + printf("%s: Failed to send IOCFacts\n", adap->name); + return 0; + } + + if (!mpt_issue_ioc_init(adap)) + { + printf("%s: Failed to send IOCInit\n", adap->name); + return 0; + } + + if (!mpt_initialize(adap)) + { + printf("%s: Failed to finish initialization of IOC\n", adap->name); + return 0; + } + + for (port = 0; port < adap->port_count; port++) + { + if (!mpt_issue_port_facts(adap, port)) + { + printf("%s: Failed to send PortFacts to port %d\n", adap->name, port); + continue; + } + } + + if (adap->port_enable_needed) + { + adap->port_online = mpt_port_online(adap); + } + +#if 0 // skip this for DOS and EFI, as it doesn't really help + if (!mpt_issue_event_notification(adap)) + { + printf("%s: failed to send EventNotification\n", adap->name); + } +#endif + + if (adap->port_type == MPI_PORTFACTS_PORTTYPE_SCSI) + { + if (!mpt_set_on_bus_timer(adap, 1000)) + { + printf("%s: Failed to set SCSI On Bus Timer\n", adap->name); + } + } + + return 1; +} + + +/* + * mpt_port_online - bring the port online. + */ +int +mpt_port_online(mpt_adap_t *adap) +{ + int port; + +// printf("mpt_port_online called\n"); + + for (port = 0; port < adap->port_count; port++) + { + if (adap->port_type == MPI_PORTFACTS_PORTTYPE_SAS) + { + //TODO: MPI12.5 - This is where it crashes + if (doSasChangeWwid(adap->port, 1) == 1) + { + printf("\nThe SAS WWID is zero -- the port will not be enabled\n"); + printf("\nUse menu option 18 then option 99 to fix this problem\n"); + continue; + } + } + + if (!mpt_issue_port_enable(adap, port)) + { + printf("%s: Failed to send PortEnable to port %d\n", adap->name, port); + continue; + } + } + + return 1; +} + + +int +mpt_wait_for_doorbell(mpt_adap_t *adap, time_t limit) +{ + U32 doorbell; + int state; + + while (time(NULL) < limit) + { + if (adap->restart_needed == TRUE) + { + return 0; + } + doorbell = rl(DOORBELL); + state = doorbell & MPI_IOC_STATE_MASK; + if (state == MPI_IOC_STATE_FAULT) + { + printf("\n%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + if (wFlag) + fprintf(logFile, "%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + + printf("\nDo you want to continue? [Yes or No, default is No] "); + + if (getYesNoAnswer(0) != 1) + break; + + printf("\n"); + + adap->restart_needed = TRUE; + return 0; + } + if (rl(HOST_INTERRUPT_STATUS) & MPI_HIS_DOORBELL_INTERRUPT) + { + return 1; + } + DELAY(1); + } + + printf("%s: Failed in mpt_wait_for_doorbell, Doorbell = %08x\n", + adap->name, doorbell); + return 0; +} + + +int +mpt_wait_for_response(mpt_adap_t *adap, time_t limit) +{ + U32 doorbell; + int state; + + while (time(NULL) < limit) + { + if (adap->restart_needed == TRUE) + { + return 0; + } + doorbell = rl(DOORBELL); + state = doorbell & MPI_IOC_STATE_MASK; + if (state == MPI_IOC_STATE_FAULT) + { + printf("\n%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + if (wFlag) + fprintf(logFile, "%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + + printf("\nHit Enter to continue "); + + getYesNoAnswer(0); + + printf("\n"); + + adap->restart_needed = TRUE; + return 0; + } + if (!(rl(HOST_INTERRUPT_STATUS) & MPI_HIS_IOP_DOORBELL_STATUS)) + { + return 1; + } + DELAY(1); + } + + printf("%s: Failed in mpt_wait_for_response, Doorbell = %08x\n", + adap->name, doorbell); + return 0; +} + + +int +mpt_send_message(mpt_adap_t *adap, int length, time_t limit) +{ + U32 doorbell; + U32 *message = adap->shared->message; + int state; + int i; + + doorbell = rl(DOORBELL); + state = doorbell & MPI_IOC_STATE_MASK; + if (state == MPI_IOC_STATE_FAULT) + { + printf("\n%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + if (wFlag) + fprintf(logFile, "%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + + printf("\nHit Enter to continue "); + + getYesNoAnswer(0); + + printf("\n"); + + adap->restart_needed = TRUE; + return 0; + } + if (state == MPI_IOC_STATE_RESET) + { + adap->restart_needed = TRUE; + return 0; + } + if (doorbell & MPI_DOORBELL_USED) + { + printf("%s: Doorbell already active\n", adap->name); + adap->restart_needed = TRUE; + return 0; + } + wl(HOST_INTERRUPT_STATUS, 0); + wl(DOORBELL, (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) | + ((length / 4) << MPI_DOORBELL_ADD_DWORDS_SHIFT)); + if (!mpt_wait_for_doorbell(adap, limit)) + return 0; + wl(HOST_INTERRUPT_STATUS, 0); + if (!mpt_wait_for_response(adap, limit)) + return 0; + for (i = 0; i < length / 4; i++) + { + wl(DOORBELL, get32x(message[i])); + if (!mpt_wait_for_response(adap, limit)) + return 0; + } + + return 1; +} + + +int +mpt_receive_data(mpt_adap_t *adap, int length, time_t limit) +{ + int i; + int real_length; + U16 value; + U16 *data = adap->shared->data; + MPIDefaultReply_t *reply = (MPIDefaultReply_t *)data; + U16 status; + + bzero(data, length); + real_length = 4; /* enough for the header to start, fix up later */ + for (i = 0; i < real_length / 2; i++) + { + if (!mpt_wait_for_doorbell(adap, limit)) + return 0; + value = (U16)rl(DOORBELL); + if (i == 1) + real_length = (value & ~0xff00) * 4; + if (i < length / 2) + data[i] = get16x(value); + wl(HOST_INTERRUPT_STATUS, 0); + } + if (!mpt_wait_for_doorbell(adap, limit)) + return 0; + wl(HOST_INTERRUPT_STATUS, 0); + + status = get16(reply->IOCStatus) & MPI_IOCSTATUS_MASK; + if (status == MPI_IOCSTATUS_SUCCESS || + status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE || + status == MPI_IOCSTATUS_CONFIG_INVALID_DATA || + status == MPI_IOCSTATUS_CONFIG_INVALID_ACTION) + return 1; + else + return 0; +} + + +int +mpt_issue_command_and_wait(mpt_adap_t *adap, int wait) +{ + U8 function = ((MPIHeader_t *)adap->shared->message)->Function; + int handle; + time_t limit = time(NULL) + wait; + + adap->command_active = TRUE; + + if (mpi1) + { + if (function == MPI_FUNCTION_SCSI_TASK_MGMT) + { + if (mpt_send_message(adap, sizeof(SCSITaskMgmt_t), limit) != 1) + { + printf("mpt_send_message failed!\n"); + return 0; + } + } + else + { + wl(REQUEST_QUEUE, (U32)adap->shared_ba + (U32)offsetof(mpt_shared_t, message)); + } + } + else + { + if (function == MPI_FUNCTION_SCSI_TASK_MGMT) + { + /* SCSI Task Mgmt requests have to use high priority */ + wl2(REQUEST_DESCRIPTOR_POST_LOW, (1 << 16) + MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY); + wl2(REQUEST_DESCRIPTOR_POST_HIGH, 0); + } + else if (function == MPI_FUNCTION_SCSI_IO_REQUEST) + { + handle = get16(((Mpi2SCSIIORequest_t *)adap->shared->message)->DevHandle); + + /* SCSI requests have to use SCSI IO and supply a handle */ + wl2(REQUEST_DESCRIPTOR_POST_LOW, (1 << 16) + MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO); + wl2(REQUEST_DESCRIPTOR_POST_HIGH, handle << 16); + } + else if (function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) + { + handle = get16(((Mpi2SCSIIORequest_t *)adap->shared->message)->DevHandle); + + /* RAID Passthru requests have to use default descriptor and supply a handle */ + wl2(REQUEST_DESCRIPTOR_POST_LOW, (1 << 16) + MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE); + wl2(REQUEST_DESCRIPTOR_POST_HIGH, handle << 16); + } + else + { + wl2(REQUEST_DESCRIPTOR_POST_LOW, (1 << 16) + MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE); + wl2(REQUEST_DESCRIPTOR_POST_HIGH, 0); + } + } + + while (time(NULL) < limit) + { + if (mpt_watchdog(adap)) + { + break; + } + mpt_interrupt(adap); + if (adap->command_active == TRUE) + { + DELAY(1); + } + else + { + break; + } + } + + if (adap->command_active == TRUE) + { + if (time(NULL) >= limit) + printf("timeout occurred!\n"); + return 0; + } + + return 1; +} + + +int +mpt_issue_config_and_wait(mpt_adap_t *adap, int wait) +{ + time_t limit = time(NULL) + wait; + + adap->config_active = TRUE; + + if (mpi1) + { + wl(REQUEST_QUEUE, (U32)adap->shared_ba + (U32)offsetof(mpt_shared_t, message)); + } + else + { + wl2(REQUEST_DESCRIPTOR_POST_LOW, (1 << 16) + MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE); + wl2(REQUEST_DESCRIPTOR_POST_HIGH, 0); + } + + while (time(NULL) < limit) + { + if (adap->restart_needed == TRUE) + { + return 0; + } + mpt_interrupt(adap); + if (adap->config_active == TRUE) + { + DELAY(1); + } + else + { + break; + } + } + + if (adap->config_active == TRUE) + return 0; + + return 1; +} + + +/* + * mpt_issue_ioc_facts - issue an IOCFacts command to the IOC. + */ +int +mpt_issue_ioc_facts(mpt_adap_t *adap) +{ + IOCFacts_t *request = (IOCFacts_t *)adap->shared->message; + IOCFactsReply_t *reply = (IOCFactsReply_t *)adap->shared->data; + time_t limit = time(NULL) + 10; + int t; + +// printf("%s: sending IOCFacts\n", adap->name); + + bzero(request, sizeof(*request)); + + request->Function = MPI_FUNCTION_IOC_FACTS; + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / IOCFacts failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + printf("%s: mpt_receive_data / IOCFacts failed\n", adap->name); + return 0; + } + + adap->mpt_version = get16(reply->MsgVersion); + + if (mpi2) + { + return mpt2_issue_ioc_facts(adap); + } + + if (reply->WhoInit == MPI_WHOINIT_PCI_PEER) + { + printf("%s: WhoInit is PCI Peer!\n", adap->name); + return 0; + } + +// printf("BlockSize = %x\n", reply->BlockSize); +// printf("ReplyQueueDepth = %x\n", get16(reply->ReplyQueueDepth)); +// printf("RequestFrameSize = %x\n", get16(reply->RequestFrameSize)); +// printf("GlobalCredits = %x\n", get16(reply->GlobalCredits)); +// printf("NumberOfPorts = %x\n", reply->NumberOfPorts); + +// if (get16(reply->MsgVersion) < MPI_VERSION_01_02) +// printf("%s: MPT Version = %04x, Firmware Version = %04x\n", +// adap->name, get16(reply->MsgVersion), +// get16(reply->Reserved_0101_FWVersion)); +// else +// printf("%s: MPT Version = %04x, Firmware Version = %08x\n", +// adap->name, get16(reply->MsgVersion), +// get32(reply->FWVersion.Word)); + + adap->message_size = get16(reply->RequestFrameSize) * 4; + adap->reply_depth = get16(reply->ReplyQueueDepth); + adap->credits = get16(reply->GlobalCredits); + adap->port_count = reply->NumberOfPorts; + adap->block_size = reply->BlockSize; + + adap->hrsm_capable = FALSE; + if (get16(reply->MsgVersion) >= MPI_VERSION_01_05) + if (get32(reply->IOCCapabilities) & MPI_IOCFACTS_CAPABILITY_REPLY_HOST_SIGNAL) + adap->hrsm_capable = TRUE; + if (adap->device_id == MPI_MANUFACTPAGE_DEVID_SAS1064 || + adap->device_id == MPI_MANUFACTPAGE_DEVID_SAS1064E || + adap->device_id == MPI_MANUFACTPAGE_DEVID_SAS1066 || + adap->device_id == MPI_MANUFACTPAGE_DEVID_SAS1066E || + adap->device_id == MPI_MANUFACTPAGE_DEVID_SAS1068 || + adap->device_id == MPI_MANUFACTPAGE_DEVID_SAS1068E) + { + U32 version = get32(reply->FWVersion.Word); + + if (version < 0x00040100) + adap->hrsm_capable = FALSE; + if (version >= 0x01000000 && version < 0x01050000) + adap->hrsm_capable = FALSE; + } + + if (reply->MaxDevices) + if (adap->max_targets > reply->MaxDevices) + adap->max_targets = reply->MaxDevices; + + if (adap->port_type == MPI_PORTFACTS_PORTTYPE_SCSI) + if (adap->max_targets > 16) + adap->max_targets = 16; + + return 1; +} + + +int +mpt2_issue_ioc_facts(mpt_adap_t *adap) +{ + Mpi2IOCFactsRequest_t *request = (Mpi2IOCFactsRequest_t *)adap->shared->message; + Mpi2IOCFactsReply_t *reply = (Mpi2IOCFactsReply_t *)adap->shared->data; + time_t limit = time(NULL) + 10; + int t; + + bzero(request, sizeof(*request)); + + request->Function = MPI2_FUNCTION_IOC_FACTS; + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / IOCFacts failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + printf("%s: mpt_receive_data / IOCFacts failed\n", adap->name); + return 0; + } + + if (reply->WhoInit == MPI2_WHOINIT_PCI_PEER) + { + printf("%s: WhoInit is PCI Peer!\n", adap->name); + return 0; + } + +// printf("MaxReplyDescriptorPostQueueDepth = %x\n", get16(reply->MaxReplyDescriptorPostQueueDepth)); +// printf("IOCRequestFrameSize = %x\n", get16(reply->IOCRequestFrameSize)); +// printf("RequestCredit = %x\n", get16(reply->RequestCredit)); +// printf("NumberOfPorts = %x\n", reply->NumberOfPorts); + +// printf("%s: MPT Version = %04x, Firmware Version = %08x\n", +// adap->name, get16(reply->MsgVersion), +// get32(reply->FWVersion.Word)); + + adap->message_size = get16(reply->IOCRequestFrameSize) * 4; + adap->reply_depth = get16(reply->MaxReplyDescriptorPostQueueDepth); + adap->credits = get16(reply->RequestCredit); + adap->port_count = reply->NumberOfPorts; + + adap->hrsm_capable = FALSE; + + if (get16(reply->MaxTargets)) + if (adap->max_targets > get16(reply->MaxTargets)) + adap->max_targets = get16(reply->MaxTargets); + + return 1; +} + + +/* + * mpt_issue_ioc_init - issue an IOCInit command to the IOC. + */ +int +mpt_issue_ioc_init(mpt_adap_t *adap) +{ + IOCInit_t *request = (IOCInit_t *)adap->shared->message; + IOCInitReply_t *reply = (IOCInitReply_t *)adap->shared->data; + time_t limit = time(NULL) + 30; + int t; +#if EFI + _U32 high = set32((U32)(adap->shared_ba >> 32)); +#endif + +// printf("%s: sending IOCInit\n", adap->name); + + if (mpi2) + { + return mpt2_issue_ioc_init(adap); + } + + bzero(request, sizeof(*request)); + + request->Function = MPI_FUNCTION_IOC_INIT; + request->WhoInit = MPI_WHOINIT_HOST_DRIVER; + request->MaxDevices = adap->max_targets; + request->MaxBuses = 1; + request->MsgContext = set32(COMMAND_CONTEXT); + request->ReplyFrameSize = set16(sizeof(adap->shared->replies[0])); +#if EFI + request->HostMfaHighAddr = high; + request->SenseBufferHighAddr = high; +#endif + request->MsgVersion = set16(MPI_VERSION); + request->HeaderVersion = set16(MPI_HEADER_VERSION); + + if (adap->hrsm_capable == TRUE) + { + adap->hrsm_value = 0; + request->Flags |= MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL; + request->ReplyFifoHostSignalingAddr = + set32((U32)adap->shared_ba + + (U32)offsetof(mpt_shared_t, hrsm_value)); + } + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / IOCInit failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + printf("%s: mpt_receive_data / IOCInit failed\n", adap->name); + return 0; + } + reply = reply; + + return 1; +} + + +int +mpt2_issue_ioc_init(mpt_adap_t *adap) +{ + Mpi2IOCInitRequest_t *request = (Mpi2IOCInitRequest_t *)adap->shared->message; + Mpi2IOCInitReply_t *reply = (Mpi2IOCInitReply_t *)adap->shared->data; + time_t limit = time(NULL) + 30; + int t; + time_t now; + uint64_t nowMsec; +#if EFI + _U32 high = set32((U32)(adap->shared_ba >> 32)); +#endif + + bzero(request, sizeof(*request)); + + request->Function = MPI2_FUNCTION_IOC_INIT; + request->WhoInit = MPI2_WHOINIT_SYSTEM_BIOS; + request->SystemRequestFrameSize = set16(sizeof(adap->shared->message) / 4); + request->ReplyDescriptorPostQueueDepth = set16(REPLY_POST_SIZE); + request->ReplyFreeQueueDepth = set16(REPLY_FREE_SIZE); + request->SystemRequestFrameBaseAddress.Low = + set32((U32)adap->shared_ba + offsetof(mpt_shared_t, message) - sizeof(adap->shared->message)); + request->ReplyDescriptorPostQueueAddress.Low = + set32((U32)adap->shared_ba + offsetof(mpt_shared_t, post_queue)); + request->ReplyFreeQueueAddress.Low = + set32((U32)adap->shared_ba + offsetof(mpt_shared_t, free_queue)); +#if EFI + request->SystemReplyAddressHigh = high; + request->SenseBufferAddressHigh = high; + request->SystemRequestFrameBaseAddress.High = high; + request->ReplyDescriptorPostQueueAddress.High = high; + request->ReplyFreeQueueAddress.High = high; +#endif + request->MsgVersion = set16(MPI2_VERSION); + request->HeaderVersion = set16(MPI2_HEADER_VERSION); + + time(&now); + nowMsec = ((uint64_t)(now)) * 1000; + request->TimeStamp.Low = set32((U32)(nowMsec & 0x00000000FFFFFFFF)); + request->TimeStamp.High = set32((U32)((nowMsec & 0xFFFFFFFF00000000) >> 32)); + + adap->free_index = 0; + adap->post_index = 0; + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / IOCInit failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + printf("%s: mpt_receive_data / IOCInit failed\n", adap->name); + return 0; + } + reply = reply; + + return 1; +} + + +/* + * mpt_initialize - finish initialization of IOC. + */ +int +mpt_initialize(mpt_adap_t *adap) +{ + U32 doorbell; + int i; + int state; + time_t limit = time(NULL) + 10; + +// printf("%s: initializing IOC\n", adap->name); + + while (time(NULL) < limit) + { + doorbell = rl(DOORBELL); + state = doorbell & MPI_IOC_STATE_MASK; + if (state == MPI_IOC_STATE_OPERATIONAL) + break; + DELAY(1); + } + + if (state != MPI_IOC_STATE_OPERATIONAL) + { + if (state == MPI_IOC_STATE_FAULT) + { + printf("\n%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + if (wFlag) + fprintf(logFile, "%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + + printf("\nHit Enter to continue "); + + getYesNoAnswer(0); + + printf("\n"); + } + adap->restart_needed = TRUE; + return 0; + } + + if (mpi1) + { + for (i = 0; i < NUM_REPLIES; i++) + { + wl(REPLY_QUEUE, (U32)adap->shared_ba + (U32)offsetof(mpt_shared_t, replies[i])); + } + } + else + { + for (i = 0; i < NUM_REPLIES; i++) + { + adap->shared->free_queue[i] = + (U32)adap->shared_ba + (U32)offsetof(mpt_shared_t, replies[i]); + } + adap->free_index = i; + wl2(REPLY_FREE_HOST_INDEX, i); + bzero(adap->shared->post_queue, sizeof(adap->shared->post_queue)); + for (i = 0; i < REPLY_POST_SIZE; i++) + { + adap->shared->post_queue[i].ReplyFlags = MPI2_RPY_DESCRIPT_FLAGS_UNUSED; + } + } + + adap->interrupt_mask &= ~MPI_HIM_RIM; +// wl(HOST_INTERRUPT_MASK, adap->interrupt_mask); + + return 1; +} + + +/* + * mpt_issue_port_facts - issue a PortFacts command to the IOC. + */ +int +mpt_issue_port_facts(mpt_adap_t *adap, int port) +{ + PortFacts_t *request = (PortFacts_t *)adap->shared->message; + PortFactsReply_t *reply = (PortFactsReply_t *)adap->shared->data; + time_t limit = time(NULL) + 10; + int t; + +// printf("%s: sending PortFacts to port %d\n", adap->name, port); + + if (mpi2) + { + return mpt2_issue_port_facts(adap, port); + } + + bzero(request, sizeof(*request)); + + request->Function = MPI_FUNCTION_PORT_FACTS; + request->PortNumber = port; + request->MsgContext = set32(COMMAND_CONTEXT); + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / PortFacts failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + printf("%s: mpt_receive_data / PortFacts failed\n", adap->name); + return 0; + } + + adap->port_type = reply->PortType; + adap->host_id = get16(reply->PortSCSIID); + + return 1; +} + + +int +mpt2_issue_port_facts(mpt_adap_t *adap, int port) +{ + Mpi2PortFactsRequest_t *request = (Mpi2PortFactsRequest_t *)adap->shared->message; + Mpi2PortFactsReply_t *reply = (Mpi2PortFactsReply_t *)adap->shared->data; + time_t limit = time(NULL) + 10; + int t; + + bzero(request, sizeof(*request)); + + request->Function = MPI2_FUNCTION_PORT_FACTS; + request->PortNumber = port; + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / PortFacts failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + printf("%s: mpt_receive_data / PortFacts failed\n", adap->name); + return 0; + } + + adap->port_type = reply->PortType; + + return 1; +} + + +/* + * mpt_issue_port_enable - issue a PortEnable command to the IOC. + */ +int +mpt_issue_port_enable(mpt_adap_t *adap, int port) +{ + PortEnable_t *request = (PortEnable_t *)adap->shared->message; + MPIDefaultReply_t *reply = (MPIDefaultReply_t *)adap->shared->data; + time_t limit = time(NULL) + 120; + int t; + +// printf("%s: sending PortEnable to port %d\n", adap->name, port); + + if (mpi2) + { + return mpt2_issue_port_enable(adap, port); + } + + bzero(request, sizeof(*request)); + + request->Function = MPI_FUNCTION_PORT_ENABLE; + request->PortNumber = port; + request->MsgContext = set32(COMMAND_CONTEXT); + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / PortEnable failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + printf("%s: mpt_receive_data / PortEnable failed\n", adap->name); + return 0; + } + reply = reply; + + return 1; +} + + +int +mpt2_issue_port_enable(mpt_adap_t *adap, int port) +{ + Mpi2PortEnableRequest_t *request = (Mpi2PortEnableRequest_t *)adap->shared->message; + Mpi2PortEnableReply_t *reply = (Mpi2PortEnableReply_t *)adap->shared->data; + time_t limit = time(NULL) + 120; + int t; + + bzero(request, sizeof(*request)); + + request->Function = MPI2_FUNCTION_PORT_ENABLE; + request->VP_ID = port; + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / PortEnable failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + printf("%s: mpt_receive_data / PortEnable failed\n", adap->name); + return 0; + } + reply = reply; + + return 1; +} + + +/* + * mpt_issue_event_notification - issue an EventNotification command to the IOC. + */ +int +mpt_issue_event_notification(mpt_adap_t *adap) +{ + EventNotification_t *request = (EventNotification_t *)adap->shared->message; + EventNotificationReply_t *reply = (EventNotificationReply_t *)adap->shared->data; + time_t limit = time(NULL) + 10; + int t; + +// printf("%s: sending EventNotification\n", adap->name); + + if (mpi2) + { + return mpt2_issue_event_notification(adap); + } + + bzero(request, sizeof(*request)); + + request->Function = MPI_FUNCTION_EVENT_NOTIFICATION; + request->Switch = MPI_EVENT_NOTIFICATION_SWITCH_ON; + request->MsgContext = set32(COMMAND_CONTEXT); + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / EventNotification failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + printf("%s: mpt_receive_data / EventNotification failed\n", adap->name); + return 0; + } + reply = reply; + + return 1; +} + + +int +mpt2_issue_event_notification(mpt_adap_t *adap) +{ + Mpi2EventNotificationRequest_t *request = (Mpi2EventNotificationRequest_t *)adap->shared->message; + Mpi2EventNotificationReply_t *reply = (Mpi2EventNotificationReply_t *)adap->shared->data; + time_t limit = time(NULL) + 10; + int t; + + bzero(request, sizeof(*request)); + + request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / EventNotification failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + printf("%s: mpt_receive_data / EventNotification failed\n", adap->name); + return 0; + } + reply = reply; + + return 1; +} + + +/* + * mpt_watchdog - routine that acts as a watchdog. + */ +int +mpt_watchdog(mpt_adap_t *adap) +{ + U32 doorbell; + int state; + + if (mpi2) // move code to mpt_interrupt, so we don't poll during DMA + { + doorbell = rl(DOORBELL); + state = doorbell & MPI_IOC_STATE_MASK; + if (state != MPI_IOC_STATE_OPERATIONAL) + { + if (state == MPI_IOC_STATE_FAULT) + { + printf("%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + if (wFlag) + fprintf(logFile, "%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + + printf("\nHit Enter to Continue "); + + getYesNoAnswer(0); + + printf("\n"); + } + adap->restart_needed = TRUE; + } + } + + if (adap->restart_needed == TRUE) + { + mpt_restart(adap); + return 1; + } + else if (adap->bus_reset_needed == TRUE) + { + adap->bus_reset_needed = FALSE; + mpt_bus_reset(adap); + } + + return 0; +} + + +/* + * mpt_init_device_capabilities - initialize SCSI device capabilities. + */ +int +mpt_init_device_capabilities(mpt_adap_t *adap) +{ + SCSIPortPage0_t *scsi_port_0 = (SCSIPortPage0_t *)adap->shared->config; + SCSIPortPage2_t *scsi_port_2 = (SCSIPortPage2_t *)adap->shared->config; + int init_capabilities; + int init_sync_period; + int targ_capabilities; + int targ_sync_period; + int targ_device_flags; + int targ; + + if (!mpt_get_config_page(adap, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0, 0)) + { + printf("%s: Failed to get SCSI Port Page 0\n", adap->name); + return 0; + } + + init_capabilities = get32(scsi_port_0->Capabilities); + + init_sync_period = MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(init_capabilities); + + if (!mpt_get_config_page(adap, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 0)) + { + printf("%s: Failed to get SCSI Port Page 2\n", adap->name); + return 0; + } + + for (targ = 0; targ < adap->max_targets; targ++) + { + targ_sync_period = scsi_port_2->DeviceSettings[targ].SyncFactor; + targ_device_flags = get16(scsi_port_2->DeviceSettings[targ].DeviceFlags); + targ_capabilities = init_capabilities; + if (targ_sync_period == 0 || targ_sync_period > init_sync_period) + { + targ_capabilities &= ~MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK; + targ_capabilities |= targ_sync_period << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD; + } + if (targ_device_flags & MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE) + { + targ_capabilities &= ~MPI_SCSIDEVPAGE1_RP_WIDE; + } + adap->capabilities[targ] = targ_capabilities; + } + + return 1; +} + + +/* + * mpt_set_device_capabilities - set SCSI device capabilities. + */ +int +mpt_set_device_capabilities(mpt_adap_t *adap, int targ) +{ + SCSIDevicePage1_t *scsi_device_1 = (SCSIDevicePage1_t *)adap->shared->config; + +// printf("%s: setting device capabilities\n", adap->name); + + bzero(scsi_device_1, sizeof(*scsi_device_1)); + + /* + * Set the control bits we know we want, as well as the maximum + * synchronous offset and minimum synchronous period. + */ + scsi_device_1->RequestedParameters = set32(adap->capabilities[targ]); + + if (!mpt_set_config_page(adap, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 1, targ)) + { + printf("%s: Failed to set SCSI Device Page 1 for %d\n", + adap->name, targ); + return 0; + } + + return 1; +} + + +/* + * mpt_set_on_bus_timer - set SCSI port on-bus-timer value. + */ +int +mpt_set_on_bus_timer(mpt_adap_t *adap, int timeout) +{ + SCSIPortPage1_t *scsi_port_1 = (SCSIPortPage1_t *)adap->shared->config; + U32 config; + +// printf("%s: setting on-bus-timer\n", adap->name); + + bzero(scsi_port_1, sizeof(*scsi_port_1)); + + config = adap->host_id | (1 << (adap->host_id + 16)); + scsi_port_1->Configuration = set32(config); + /* + * Convert from milliseconds to 1.6 microsecond units. + */ + scsi_port_1->OnBusTimerValue = set32(timeout * 1000*10/16); + + if (!mpt_set_config_page(adap, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, 0)) + { + printf("%s: Failed to set SCSI Port Page 1\n", adap->name); + } + + return 1; +} + + +/* + * mpt_get_config_page - get a configuration page. + */ +int +mpt_get_config_page(mpt_adap_t *adap, int type, int number, int address) +{ + ConfigReply_t *reply = (ConfigReply_t *)adap->shared->data; + int t; + int ioc_status; + int length; + + t = mpt_do_config_action(adap, MPI_CONFIG_ACTION_PAGE_HEADER, type, number, address, 0); + ioc_status = get16(reply->IOCStatus) & MPI_IOCSTATUS_MASK; + length = reply->Header.PageLength; + if (!t || ioc_status != MPI_IOCSTATUS_SUCCESS || length == 0) + { + if (ioc_status != MPI_IOCSTATUS_CONFIG_INVALID_PAGE) + { + printf("%s: Failed to get config page header\n", + adap->name); + printf("%s: IOCStatus = %04x, PageLength = %x\n", + adap->name, ioc_status, length); + printf("%s: type = %d, number = %d, address = %x\n", + adap->name, type, number, address); + } + return 0; + } + + t = mpt_do_config_action(adap, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, type, number, address, length); + ioc_status = get16(reply->IOCStatus) & MPI_IOCSTATUS_MASK; + if (!t || ioc_status != MPI_IOCSTATUS_SUCCESS) + { + if (ioc_status != MPI_IOCSTATUS_CONFIG_INVALID_PAGE) + { + printf("%s: Failed to get config page\n", + adap->name); + printf("%s: IOCStatus = %04x, PageLength = %x\n", + adap->name, ioc_status, length); + printf("%s: type = %d, number = %d, address = %x\n", + adap->name, type, number, address); + } + return 0; + } + + return 1; +} + + +/* + * mpt_set_config_page - set a configuration page. + */ +int +mpt_set_config_page(mpt_adap_t *adap, int type, int number, int address) +{ + ConfigReply_t *reply = (ConfigReply_t *)adap->shared->data; + int t; + int ioc_status; + int length; + + t = mpt_do_config_action(adap, MPI_CONFIG_ACTION_PAGE_HEADER, type, number, address, 0); + ioc_status = get16(reply->IOCStatus) & MPI_IOCSTATUS_MASK; + length = reply->Header.PageLength; + if (!t || ioc_status != MPI_IOCSTATUS_SUCCESS || length == 0) + { + if (ioc_status != MPI_IOCSTATUS_CONFIG_INVALID_PAGE) + { + printf("%s: Failed to get config page header\n", + adap->name); + printf("%s: IOCStatus = %04x, PageLength = %x\n", + adap->name, ioc_status, length); + printf("%s: type = %d, number = %d, address = %x\n", + adap->name, type, number, address); + } + return 0; + } + + *(ConfigPageHeader_t *)adap->shared->config= reply->Header; + + t = mpt_do_config_action(adap, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, type, number, address, length); + ioc_status = get16(reply->IOCStatus) & MPI_IOCSTATUS_MASK; + if (!t || ioc_status != MPI_IOCSTATUS_SUCCESS) + { + if (ioc_status != MPI_IOCSTATUS_CONFIG_INVALID_PAGE) + { + printf("%s: Failed to set config page\n", + adap->name); + printf("%s: IOCStatus = %04x, PageLength = %x\n", + adap->name, ioc_status, length); + printf("%s: type = %d, number = %d, address = %x\n", + adap->name, type, number, address); + } + return 0; + } + + return 1; +} + + +int +mpt_do_config_action(mpt_adap_t *adap, int action, int type, int number, int address, int length) +{ + Config_t *request = (Config_t *)adap->shared->message; + ConfigReply_t *reply = (ConfigReply_t *)adap->shared->data; + SGESimple64_t *sge_simple = (SGESimple64_t *)&request->PageBufferSGE; + time_t limit = time(NULL) + 10; + int t; + U32 flags; + + bzero(request, sizeof(*request)); + bzero(reply, sizeof(*reply)); + + request->Function = MPI_FUNCTION_CONFIG; + request->Action = action; + request->MsgContext = set32(COMMAND_CONTEXT); + if (action == MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT || + action == MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM) + { + request->Header = *(ConfigPageHeader_t *)adap->shared->config; + } + else + { + request->Header.PageType = type; + request->Header.PageNumber = number; + request->Header.PageLength = length; + } + request->PageAddress = set32(address); + if (length) + { + flags = (length * 4) | + MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_LAST_ELEMENT | + MPI_SGE_FLAGS_64_BIT_ADDRESSING | + MPI_SGE_FLAGS_END_OF_BUFFER | + MPI_SGE_FLAGS_END_OF_LIST); + if (action == MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT || + action == MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM) + { + flags |= MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_HOST_TO_IOC); + } + else + { + flags |= MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_IOC_TO_HOST); + } + sge_simple->FlagsLength = set32(flags); + sge_simple->Address.Low = set32((U32)adap->shared_ba + offsetof(mpt_shared_t, config)); +#if EFI + sge_simple->Address.High = set32((U32)(adap->shared_ba >> 32)); +#endif + } + else if (mpi2) + { + sge_simple->FlagsLength = set32( + MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_LAST_ELEMENT | + MPI_SGE_FLAGS_64_BIT_ADDRESSING | + MPI_SGE_FLAGS_END_OF_BUFFER | + MPI_SGE_FLAGS_END_OF_LIST)); + } + + + if (mpt_verify_operational(adap)) + { + logMptCommandReq(adap->port, request, sizeof(*request)); + + t = mpt_issue_config_and_wait(adap, 10); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + if ((get16(reply->IOCStatus) & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_CONFIG_INVALID_PAGE) + { + printf("%s: mpt_issue_config_and_wait / Config failed!\n", adap->name); + } + return 0; + } + + return 1; + } + + if (mpt_verify_ready(adap)) + { + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / Config failed\n", adap->name); + return 0; + } + + t = mpt_receive_data(adap, sizeof(*reply), limit); + + logMptCommandRep(adap->port, request, sizeof(*request), reply, sizeof(*reply), t); + + if (!t) + { + if ((get16(reply->IOCStatus) & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_CONFIG_INVALID_PAGE) + { + printf("%s: mpt_receive_data / Config failed\n", adap->name); + } + return 0; + } + + return 1; + } + + return 0; +} + + +void +mpt_bus_reset(mpt_adap_t *adap) +{ + SCSITaskMgmt_t *request = (SCSITaskMgmt_t *)adap->shared->message; + time_t limit = time(NULL) + 10; + +// printf("%s: sending SCSITaskMgmt (ResetBus)\n", adap->name); + + /* + * Use a SCSI Task Management request to reset the bus. + */ + bzero(request, sizeof(*request)); + + request->Function = MPI_FUNCTION_SCSI_TASK_MGMT; + request->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; + request->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION; + + logMptCommandReq(adap->port, request, sizeof(*request)); + + if (!mpt_send_message(adap, sizeof(*request), limit)) + { + printf("%s: mpt_send_message / SCSITaskMgmt failed\n", adap->name); + adap->restart_needed = TRUE; + } +} + + +void +mpt_interrupt(mpt_adap_t *adap) +{ + U32 context; + U32 reply_ba; + MPIDefaultReply_t *reply; + U32 doorbell; + int state; + +// printf("mpt_interrupt called\n"); + + if (mpi2) + { + mpt2_interrupt(adap); + return; + } + + if (adap->hrsm_capable) + { + if (adap->hrsm_value == adap->shared->hrsm_value) + return; + adap->hrsm_value = adap->shared->hrsm_value; + } + + doorbell = rl(DOORBELL); + state = doorbell & MPI_IOC_STATE_MASK; + if (state != MPI_IOC_STATE_OPERATIONAL) + { + if (state == MPI_IOC_STATE_FAULT) + { + printf("%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + if (wFlag) + fprintf(logFile, "%s: MPT Firmware Fault, code %04x\n", + adap->name, doorbell & MPI_DOORBELL_DATA_MASK); + + printf("\nHit Enter to continue "); + + getYesNoAnswer(0); + + printf("\n"); + } + adap->restart_needed = TRUE; + } + + while ((context = rl(REPLY_QUEUE)) != 0xffffffff) + { + if (context & MPI_CONTEXT_REPLY_A_BIT) + { + reply_ba = context << 1; + reply = (MPIDefaultReply_t *)((U8 *)adap->shared + reply_ba - (U32)adap->shared_ba); + if (mpt_handle_reply(adap, reply, reply_ba)) + wl(REPLY_QUEUE, reply_ba); + continue; + } + if (context == PASS_THRU_CONTEXT) + { + if (adap->command_active == TRUE) + { + SCSIIOReply_t *scsiRep = (SCSIIOReply_t *)adap->shared->data; + + adap->command_active = FALSE; + bzero(scsiRep, sizeof(*scsiRep)); + } + continue; + } + printf("%s: Invalid reply, Context = %08x\n", adap->name, reply); + } +} + + +void +mpt2_interrupt(mpt_adap_t *adap) +{ + int index; + Mpi2DefaultReplyDescriptor_t *reply_desc; + int reply_type; + int count; + + index = adap->post_index; + count = 0; + while (TRUE) + { + reply_desc = &adap->shared->post_queue[index]; + reply_type = reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; + if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) + { + mpt2_handle_scsi_io_success(adap, reply_desc); + } + else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) + { + mpt2_handle_address_reply(adap, reply_desc); + } + else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) + { + break; + } + else + { + printf("%s: Invalid reply, ReplyType = %x\n", adap->name, reply_type); + } + reply_desc->ReplyFlags = MPI2_RPY_DESCRIPT_FLAGS_UNUSED; + index++; + if (index == REPLY_POST_SIZE) + index = 0; + count++; + } + + if (count) + { + adap->post_index = index; + wl2(REPLY_POST_HOST_INDEX, index); + } +} + + +int +mpt_handle_reply(mpt_adap_t *adap, MPIDefaultReply_t *reply, U32 reply_ba) +{ + U32 context; + EventNotificationReply_t *event; + EventDataScsi_t *ed_scsi; + EventAckReply_t *event_ack; + int targ; + int repost; + + repost = 1; + context = get32(reply->MsgContext); + + if (get16(reply->IOCStatus) & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) + { + printf("%s: Function = %02x, IOCStatus = %04x, IOCLogInfo = %08x\n", + adap->name, reply->Function, get16(reply->IOCStatus), + get32(reply->IOCLogInfo)); + } + + if (context == PASS_THRU_CONTEXT) + { + if (adap->command_active == TRUE) + { + adap->command_active = FALSE; + bcopy(reply, adap->shared->data, reply->MsgLength * 4); + } + return repost; + } + + switch (reply->Function) + { + case MPI_FUNCTION_CONFIG: + if (adap->config_active == TRUE) + { + adap->config_active = FALSE; + bcopy(reply, adap->shared->data, reply->MsgLength * 4); + } + break; + case MPI_FUNCTION_EVENT_NOTIFICATION: + logMptCommandRep(adap->port, NULL, 0, reply, sizeof(*reply), 1); + event = (EventNotificationReply_t *)reply; + switch (get32(event->Event)) + { + case MPI_EVENT_NONE: + break; + case MPI_EVENT_STATE_CHANGE: + adap->restart_needed = TRUE; + break; + case MPI_EVENT_ON_BUS_TIMER_EXPIRED: + ed_scsi = (EventDataScsi_t *)event->Data; + targ = ed_scsi->TargetID; + printf("%s: ON BUS TIMER EXPIRED for SCSI target %d\n", adap->name, targ); + adap->bus_reset_needed = TRUE; + break; + } + if (event->AckRequired) + { + _U32 t1; + _U32 t2; + EventAck_t *event_ack; + + t1 = event->Event; + t2 = event->EventContext; + /* + * Use the EventNotify reply as the EventAck command. + */ + event_ack = (EventAck_t *)event; + bzero(event_ack, sizeof(*event_ack)); + event_ack->Function = MPI_FUNCTION_EVENT_ACK; + event_ack->MsgContext = set32(reply_ba); + event_ack->Event = t1; + event_ack->EventContext = t2; + wl(REQUEST_QUEUE, get32(event_ack->MsgContext)); + /* + * Signal that the reply should not be given back to + * the IOC yet, since it's being used as the EventAck + * command right now. + */ + repost = 0; + } + break; + case MPI_FUNCTION_EVENT_ACK: + event_ack = (EventAckReply_t *)reply; + wl(REPLY_QUEUE, get32(event_ack->MsgContext)); + break; + default: + printf("%s: Invalid reply, Function = %02x, IOCStatus = %04x\n", + adap->name, reply->Function, get16(reply->IOCStatus)); +#if 1 +{ + int i; + U32 *p = (U32 *)reply; + + for (i = 0; i < reply->MsgLength; i++) + printf("reply[%02x] = %08x\n", i*4, get32x(p[i])); +} +#endif + break; + } + + return repost; +} + + +void +mpt2_handle_scsi_io_success(mpt_adap_t *adap, Mpi2DefaultReplyDescriptor_t *reply_desc) +{ + Mpi2SCSIIOSuccessReplyDescriptor_t *scsi_io_success; + U32 context; + + scsi_io_success = (Mpi2SCSIIOSuccessReplyDescriptor_t *)reply_desc; + context = adap->msg_context; + if (get16(scsi_io_success->SMID) == 1) + adap->msg_context = 0; + + if (context == PASS_THRU_CONTEXT) + { + if (adap->command_active == TRUE) + { + Mpi2SCSIIOReply_t *scsiRep = (Mpi2SCSIIOReply_t *)adap->shared->data; + + adap->command_active = FALSE; + bzero(scsiRep, sizeof(*scsiRep)); + } + return; + } + printf("%s: Invalid SCSI IO SUCCESS reply, Context = %08x\n", adap->name, context); +} + + +void +mpt2_handle_address_reply(mpt_adap_t *adap, Mpi2DefaultReplyDescriptor_t *reply_desc) +{ + Mpi2AddressReplyDescriptor_t *address_reply; + MPI2DefaultReply_t *reply; + U32 context; + U32 reply_ba; + int index; + + address_reply = (Mpi2AddressReplyDescriptor_t *)reply_desc; + + reply_ba = get32(address_reply->ReplyFrameAddress); + reply = (MPI2DefaultReply_t *)((U8 *)adap->shared + reply_ba - (U32)adap->shared_ba); + context = adap->msg_context; + if (get16(address_reply->SMID) == 1) + adap->msg_context = 0; + + if (get16(reply->IOCStatus) & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) + { + printf("%s: Function = %02x, IOCStatus = %04x, IOCLogInfo = %08x\n", + adap->name, reply->Function, get16(reply->IOCStatus), + get32(reply->IOCLogInfo)); + } + + if (context == PASS_THRU_CONTEXT) + { + if (adap->command_active == TRUE) + { + adap->command_active = FALSE; + bcopy(reply, adap->shared->data, reply->MsgLength * 4); + } + goto repost; + } + + switch (reply->Function) + { + case MPI2_FUNCTION_CONFIG: + if (adap->config_active == TRUE) + { + adap->config_active = FALSE; + bcopy(reply, adap->shared->data, reply->MsgLength * 4); + } + break; + default: + printf("%s: Invalid reply, Function = %02x, IOCStatus = %04x\n", + adap->name, reply->Function, get16(reply->IOCStatus)); +#if 1 +{ + int i; + U32 *p = (U32 *)reply; + + for (i = 0; i < reply->MsgLength; i++) + printf("reply[%02x] = %08x\n", i*4, get32x(p[i])); +} +#endif + break; + } + +repost: + index = adap->free_index; + adap->shared->free_queue[index] = reply_ba; + index++; + if (index == REPLY_FREE_SIZE) + index = 0; + adap->free_index = index; + wl2(REPLY_FREE_HOST_INDEX, index); +} + + +int mpt_fwdownloadboot(mpt_adap_t *adap) +{ + U16 deviceId = adap->device_id; + MpiFwHeader_t *fwHeader; + MpiExtImageHeader_t *extImageHeader; + U32 *image; + U8 *nextImage; + U32 addr; + U32 size; + U32 next; + U32 data; + U32 resetAddr; + U32 resetData; + int t; + + if (adap->fw_image == NULL) + { + char name[256]; + int n; + + if (adap->fw_image_asked == TRUE) + return 0; + + adap->fw_image_asked = TRUE; + + printf("\nThe firmware on this %s appears broken!\n", adap->port->chipNameRev); + printf("A valid firmware image is required to make this chip operational...\n\n"); + + n = getFileName(name, sizeof name, stdin, "firmware", 99); + if (n > 0) + { + if (readFile(name, &adap->fw_image, &adap->fw_image_size) != 1) + { + printf("\nThe firmware image could not be read\n"); + return 0; + } + } + else + { + printf("\nThe chip cannot be made operational\n"); + return 0; + } + } + + if (deviceId == MPI_MANUFACTPAGE_DEVICEID_FC909 || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC919 || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC929) + { + return mpt_directdownload(adap); + } + + wl(WRITE_SEQUENCE, 0); + wl(WRITE_SEQUENCE, MPI_WRSEQ_KEY_VALUE_MASK); + wl(WRITE_SEQUENCE, MPI_WRSEQ_1ST_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_2ND_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_3RD_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_4TH_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_5TH_KEY_VALUE); + + wl(DIAGNOSTIC, MPI_DIAG_DISABLE_ARM | + MPI_DIAG_PREVENT_IOC_BOOT | + MPI_DIAG_CLEAR_FLASH_BAD_SIG); + DELAY(100); + + if (deviceId == MPI_MANUFACTPAGE_DEVICEID_FC949E) + { + wl(DIAGNOSTIC, MPI_DIAG_DISABLE_ARM | + MPI_DIAG_PREVENT_IOC_BOOT | + MPI_DIAG_CLEAR_FLASH_BAD_SIG | + MPI_DIAG_RW_ENABLE); + + wlio(DIAG_RW_ADDRESS, 0x40100064); + data = rlio(DIAG_RW_DATA); + + wlio(DIAG_RW_ADDRESS, 0x40100064); + wlio(DIAG_RW_DATA, data | 0x20000); + + DELAY(100); + } + + wl(DIAGNOSTIC, MPI_DIAG_DISABLE_ARM | + MPI_DIAG_PREVENT_IOC_BOOT | + MPI_DIAG_RESET_ADAPTER); + DELAY(50000); + + wl(WRITE_SEQUENCE, 0); + wl(WRITE_SEQUENCE, MPI_WRSEQ_KEY_VALUE_MASK); + wl(WRITE_SEQUENCE, MPI_WRSEQ_1ST_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_2ND_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_3RD_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_4TH_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_5TH_KEY_VALUE); + + wl(DIAGNOSTIC, MPI_DIAG_DISABLE_ARM | + MPI_DIAG_PREVENT_IOC_BOOT | + MPI_DIAG_CLEAR_FLASH_BAD_SIG | + MPI_DIAG_RW_ENABLE); + + if (deviceId == MPI_MANUFACTPAGE_DEVICEID_FC949E) + { + wlio(DIAG_RW_ADDRESS, 0x40100064); + wlio(DIAG_RW_DATA, data); + } + + fwHeader = (MpiFwHeader_t *)adap->fw_image; + + image = (U32 *)fwHeader; + + addr = get32(fwHeader->LoadStartAddress); + size = get32(fwHeader->ImageSize); + + next = get32(fwHeader->NextImageHeaderOffset); + + resetAddr = get32(fwHeader->IopResetRegAddr); + resetData = get32(fwHeader->IopResetVectorValue); + + while (next != 0) + { + nextImage = (U8 *)fwHeader + next; + + extImageHeader = (MpiExtImageHeader_t *)nextImage; + + if (extImageHeader->ImageType == MPI_EXT_IMAGE_TYPE_BOOTLOADER) + { + printf("Found a BootLoader, using only that part of the image!\n"); + + adap->bootloader = TRUE; + + image = (U32 *)extImageHeader; + + addr = get32(extImageHeader->LoadStartAddress); + size = get32(extImageHeader->ImageSize); + + next = 0; + + resetData = addr + sizeof(MpiExtImageHeader_t); + + break; + } + + next = get32(extImageHeader->NextImageHeaderOffset); + } + + if (addr == get32(fwHeader->LoadStartAddress) && + size == get32(fwHeader->ImageSize)) + { + next = get32(fwHeader->NextImageHeaderOffset); + } + + while (1) + { + wlio(DIAG_RW_ADDRESS, addr); + + while (size) + { + data = *image++; + + wlio(DIAG_RW_DATA, data); + + size -= 4; + } + + if (next == 0) + { + break; + } + + nextImage = (U8 *)fwHeader + next; + + extImageHeader = (MpiExtImageHeader_t *)nextImage; + + image = (U32 *)extImageHeader; + + addr = get32(extImageHeader->LoadStartAddress); + size = get32(extImageHeader->ImageSize); + + next = get32(extImageHeader->NextImageHeaderOffset); + } + + wlio(DIAG_RW_ADDRESS, resetAddr); + wlio(DIAG_RW_DATA, resetData); + + if (deviceId == MPI_MANUFACTPAGE_DEVID_53C1030) + { + wlio(DIAG_RW_ADDRESS, 0x3f000000); + data = rlio(DIAG_RW_DATA); + + data |= 0x40000000; + + wlio(DIAG_RW_ADDRESS, 0x3f000000); + wlio(DIAG_RW_DATA, data); + } + + if (deviceId == MPI_MANUFACTPAGE_DEVICEID_FC919X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC929X) + { + wlio(DIAG_RW_ADDRESS, 0x3e000000); + data = rlio(DIAG_RW_DATA); + } + + if (deviceId == MPI_MANUFACTPAGE_DEVICEID_FC939X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC949X || + deviceId == MPI_MANUFACTPAGE_DEVICEID_FC949E) + { + wlio(DIAG_RW_ADDRESS, 0x3d000000); + data = rlio(DIAG_RW_DATA); + } + + if (adap->bootloader) + { + wl(DIAGNOSTIC, MPI_DIAG_DISABLE_ARM | + MPI_DIAG_CLEAR_FLASH_BAD_SIG); + DELAY(100); + + wl(DIAGNOSTIC, 0); + DELAY(100); + + sleep(1); + } + + wl(DIAGNOSTIC, MPI_DIAG_DISABLE_ARM | + MPI_DIAG_CLEAR_FLASH_BAD_SIG); + DELAY(100); + + wl(DIAGNOSTIC, 0); + DELAY(100); + + t = mpt_wait_for_ready(adap); + + if (wFlag) + fprintf(logFile, "%s: Firmware Download Boot: %s\n", + adap->name, t ? "PASS" : "FAIL"); + + if (t) + return 1; + + printf("\n%s: FWDownloadBoot failed!\n", adap->name); + return 0; +} + + +int +mpt_directdownload(mpt_adap_t *adap) +{ + U16 deviceId = adap->device_id; + U32 mask = adap->diagmem_size - 1; + MpiFwHeader_t *fwHeader; + U32 *image; + U32 addr; + U32 size; + U32 data; + int t; + + wl(WRITE_SEQUENCE, 0); + wl(WRITE_SEQUENCE, MPI_WRSEQ_KEY_VALUE_MASK); + wl(WRITE_SEQUENCE, MPI_WRSEQ_1ST_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_2ND_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_3RD_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_4TH_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_5TH_KEY_VALUE); + + wl(DIAGNOSTIC, MPI_DIAG_DISABLE_ARM); + DELAY(100); + + /* If FlashBadSig is set, the download doesn't seem to work if we reset + * the chip here. + * + * If FlashBadSig isn't set, the download doesn't seem to work if we + * don't reset the chip here. + */ + data = rl(DIAGNOSTIC); + if (!(data & MPI_DIAG_FLASH_BAD_SIG)) + { + wl(DIAGNOSTIC, MPI_DIAG_DISABLE_ARM | MPI_DIAG_RESET_ADAPTER); + DELAY(50000); + + wl(WRITE_SEQUENCE, 0); + wl(WRITE_SEQUENCE, MPI_WRSEQ_KEY_VALUE_MASK); + wl(WRITE_SEQUENCE, MPI_WRSEQ_1ST_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_2ND_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_3RD_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_4TH_KEY_VALUE); + wl(WRITE_SEQUENCE, MPI_WRSEQ_5TH_KEY_VALUE); + } + + wl(DIAGNOSTIC, MPI_DIAG_DISABLE_ARM | MPI_DIAG_MEM_ENABLE); + + addr = 0x50004; + rldiag(addr, data); + data &= ~0x80000000; + wldiag(addr, data); + + if (deviceId == MPI_MANUFACTPAGE_DEVICEID_FC929) + { + addr = 0x51004; + rldiag(addr, data); + data &= ~0x80000000; + wldiag(addr, data); + } + + if (rl(DIAGNOSTIC) & MPI_DIAG_FLASH_BAD_SIG) + { + addr = 0x40000; + rldiag(addr, data); + data |= 0x40000000; + wldiag(addr, data); + } + + fwHeader = (MpiFwHeader_t *)adap->fw_image; + + image = (U32 *)fwHeader; + + addr = get32(fwHeader->LoadStartAddress); + size = get32(fwHeader->ImageSize); + + while (size) + { + data = *image++; + + wldiag(addr, data); + + addr += 4; + size -= 4; + } + + addr = get32(fwHeader->IopResetRegAddr); + data = get32(fwHeader->IopResetVectorValue); + + wldiag(addr, data); + + addr = 0x40000; + rldiag(addr, data); + data |= 0x40000000; + wldiag(addr, data); + + wl(DIAGNOSTIC, 0); + DELAY(100); + + t = mpt_wait_for_ready(adap); + + if (wFlag) + fprintf(logFile, "%s: Firmware Direct Download: %s\n", + adap->name, t ? "PASS" : "FAIL"); + + if (t) + return 1; + + printf("\n%s: DirectDownload failed!\n", adap->name); + return 0; +} + + +/* vi: set sw=4 ts=4 sts=4 et :iv */