| /*- |
| * Copyright (c) 2008, 2009 Yahoo!, Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. The names of the authors may not be used to endorse or promote |
| * products derived from this software without specific prior written |
| * permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * |
| * $FreeBSD: releng/11.1/usr.sbin/mfiutil/mfiutil.h 251516 2013-06-08 02:54:59Z sbruno $ |
| */ |
| |
| #ifndef __MFIUTIL_H__ |
| #define __MFIUTIL_H__ |
| |
| #include <sys/param.h> |
| #include <stdint.h> |
| #ifndef __packed |
| #define __packed __attribute__((__packed__)) |
| #endif |
| #ifndef __unused |
| #define __unused __attribute__((__unused__)) |
| #endif |
| #ifndef SPECNAMELEN |
| #define SPECNAMELEN 63 /* max length of devicename */ |
| #endif |
| #include <dev/mfi/mfireg.h> |
| |
| /* <sys/cdefs.h> */ |
| #ifndef __weak_symbol |
| #define __weak_symbol __attribute__((__weak__)) |
| #endif |
| #ifndef __used |
| #define __used __attribute__((__used__)) |
| #endif |
| #ifndef __section |
| #define __section(x) __attribute__((__section__(x))) |
| #endif |
| |
| #ifndef __CONCAT |
| #define __CONCAT1(A,B) A##B |
| #define __CONCAT(A,B) __CONCAT1(A,B) |
| #endif |
| |
| #ifndef __STRING |
| #define __STRING(E) #E |
| #endif |
| |
| #define __GLOBL1(sym) __asm__(".globl " #sym) |
| #define __GLOBL(sym) __GLOBL1(sym) |
| |
| #if defined __APPLE__ && defined __MACH__ |
| #include <mach-o/getsect.h> |
| #endif |
| |
| /* <sys/linker_set.h> */ |
| #undef __MAKE_SET |
| #undef DATA_SET |
| |
| #if defined __APPLE__ && defined __MACH__ |
| #define __MAKE_SET(set, sym) \ |
| static void const *const __section("__DATA," #set) __used __set_##set##_sym_##sym = &sym |
| #else |
| #define __MAKE_SET(set, sym) \ |
| __GLOBL(__CONCAT(__start_set_,set)); \ |
| __GLOBL(__CONCAT(__stop_set_,set)); \ |
| static void const *const __section("set_" #set) __used __set_##set##_sym_##sym = &sym |
| #endif |
| |
| #define DATA_SET(set, sym) __MAKE_SET(set, sym) |
| |
| #if defined __APPLE__ && defined __MACH__ |
| static inline void *init_set_pointers(void *begin, void *limit, const char *name) { |
| void ***set_begin_p = begin; |
| if(!*set_begin_p) { |
| #if 0 |
| uint32_t size; |
| *set_begin_p = (void **)getsectdatafromheader((const struct mach_header *)&_mh_execute_header, "__DATA", name, &size); |
| #else |
| unsigned long int size; |
| *set_begin_p = (void **)getsectdata("__DATA", name, &size); |
| #endif |
| void ***set_end_p = limit; |
| *set_end_p = (void **)((char *)*set_begin_p + size); |
| } |
| return *set_begin_p; |
| } |
| |
| #define SET_DECLARE(set, ptype) \ |
| static ptype **__CONCAT(__start_set_,set); \ |
| static ptype **__CONCAT(__stop_set_,set) |
| #define SET_BEGIN(set) \ |
| (init_set_pointers(&__CONCAT(__start_set_,set),&__CONCAT(__stop_set_,set),__STRING(set)),__CONCAT(__start_set_,set)) |
| #define SET_LIMIT(set) \ |
| (init_set_pointers(&__CONCAT(__start_set_,set),&__CONCAT(__stop_set_,set),__STRING(set)),__CONCAT(__stop_set_,set)) |
| #else |
| #define SET_DECLARE(set, ptype) \ |
| extern ptype *__weak_symbol __CONCAT(__start_set_,set); \ |
| extern ptype *__weak_symbol __CONCAT(__stop_set_,set) |
| |
| #define SET_BEGIN(set) \ |
| (&__CONCAT(__start_set_,set)) |
| #define SET_LIMIT(set) \ |
| (&__CONCAT(__stop_set_,set)) |
| #endif /* __APPLE__ && __MACH__ */ |
| |
| #define SET_FOREACH(pvar, set) \ |
| for (pvar = SET_BEGIN(set); pvar < SET_LIMIT(set); pvar++) |
| |
| #ifndef powerof2 |
| #define powerof2(x) ((((x)-1)&(x))==0) |
| #endif |
| |
| #if !defined __FreeBSD__ && !defined __DragonFly__ && !defined __APPLE__ |
| #include <stdlib.h> |
| |
| static inline void *reallocf(void *p, size_t size) { |
| void *new_p = realloc(p, size); |
| if(!new_p) free(p); |
| return new_p; |
| } |
| #endif |
| |
| extern long int human_readable_binary(unsigned long long int n, int *symbol, unsigned int scale); |
| extern int print_human_readable_binary(unsigned long long int n, int symbol, unsigned int scale_factor, int print_width, FILE *f); |
| |
| #if (defined __sun && defined __SVR4 && !defined HAVE_LIBDEVINFO) || defined __linux__ |
| #include <limits.h> |
| |
| static inline int fgetline(FILE *f, char *line, size_t len) { |
| size_t i = 0; |
| int c; |
| if(len > INT_MAX) len = INT_MAX; |
| while((c = fgetc(f)) != '\n') { |
| if(c == EOF) { |
| if(!i) return -1; |
| break; |
| } |
| if(i >= len - 1) return -2; |
| line[i++] = c; |
| } |
| line[i] = 0; |
| return i; |
| } |
| #endif |
| |
| #define LOCAL_VERSION "-rivoreo-r1" |
| |
| #if !defined __linux__ && !(defined __sun && defined __SVR4) |
| #define HAVE_MFI_DRIVER |
| #endif |
| |
| #if 0 && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4) |
| #define bswap16 __builtin_bswap16 |
| #define bswap32 __builtin_bswap32 |
| #define bswap64 __builtin_bswap64 |
| #elif defined __GLIBC__ |
| #include <byteswap.h> |
| #define bswap16 bswap_16 |
| #define bswap32 bswap_32 |
| #define bswap64 bswap_64 |
| #elif defined __SVR4 && defined __sun |
| #include <sys/byteorder.h> |
| #define bswap16 BSWAP_16 |
| #define bswap32 BSWAP_32 |
| #define bswap64 BSWAP_64 |
| #elif defined __FreeBSD__ || defined __DragonFly__ |
| #include <sys/endian.h> |
| #else |
| static inline uint16_t bswap16(uint16_t v) { |
| return ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8); |
| } |
| static inline uint32_t bswap32(uint32_t v) { |
| return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) | |
| ((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24); |
| } |
| static inline uint64_t bswap64(uint64_t v) { |
| return ((uint64_t)bswap32(v & 0xffffffff) << 32 ) | (uint64_t)bswap32(v >> 32); |
| } |
| #endif |
| |
| #ifdef __BYTE_ORDER__ |
| #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
| #if 0 |
| #define convle16(p) |
| #define convle32(p) |
| #define convle64(p) |
| #else |
| #define CONVLE16(P) (*(P)) |
| #define CONVLE32(P) (*(P)) |
| #define CONVLE64(P) (*(P)) |
| #endif |
| #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
| #if 0 |
| static inline void convle16(uint16_t *p) { |
| *p = bswap16(*p); |
| } |
| static inline void convle32(uint32_t *p) { |
| *p = bswap32(*p); |
| } |
| static inline void convle64(uint64_t *p) { |
| *p = bswap64(*p); |
| } |
| #else |
| #define CONVLE16(P) (*(P) = bswap16(*(P))) |
| #define CONVLE32(P) (*(P) = bswap32(*(P))) |
| #define CONVLE64(P) (*(P) = bswap64(*(P))) |
| #endif |
| #else |
| #error "Byte order not supported" |
| #endif |
| #else |
| #define MFI_CHECK_BIG_ENDIAN() (((union { uint8_t ba[2]; uint16_t i; }){ .ba = { 0, 1 } }).i == 1) |
| #if 0 |
| static inline void convle16(uint16_t *p) { |
| if(MFI_CHECK_BIG_ENDIAN()) *p = bswap16(*p); |
| } |
| static inline void convle32(uint32_t *p) { |
| if(MFI_CHECK_BIG_ENDIAN()) *p = bswap32(*p); |
| } |
| static inline void convle64(uint64_t *p) { |
| if(MFI_CHECK_BIG_ENDIAN()) *p = bswap64(*p); |
| } |
| #else |
| #define CONVLE16(P) (*(P) = MFI_CHECK_BIG_ENDIAN() ? bswap16(*(P)) : *(P)) |
| #define CONVLE32(P) (*(P) = MFI_CHECK_BIG_ENDIAN() ? bswap32(*(P)) : *(P)) |
| #define CONVLE64(P) (*(P) = MFI_CHECK_BIG_ENDIAN() ? bswap64(*(P)) : *(P)) |
| #endif |
| #endif |
| |
| #ifdef MFI_CHECK_BIG_ENDIAN |
| #elif defined MFI_BIG_ENDIAN |
| #else |
| #endif |
| |
| /* Seconds between Jan 1, 1970 and Jan 1, 2000 */ |
| #define MFI_TIME_BASE 946684800 |
| |
| /* Constants for DDF RAID levels. */ |
| #define DDF_RAID0 0x00 |
| #define DDF_RAID1 0x01 |
| #define DDF_RAID3 0x03 |
| #define DDF_RAID5 0x05 |
| #define DDF_RAID6 0x06 |
| #define DDF_RAID1E 0x11 |
| #define DDF_JBOD 0x0f |
| #define DDF_CONCAT 0x1f |
| #define DDF_RAID5E 0x15 |
| #define DDF_RAID5EE 0x25 |
| |
| struct mfiutil_command { |
| const char *name; |
| int (*handler)(int ac, char **av); |
| }; |
| |
| #define MFI_DATASET(name) mfiutil_ ## name |
| |
| #define MFI_COMMAND(set, name, function) \ |
| static struct mfiutil_command function ## _mfiutil_command = \ |
| { #name, function }; \ |
| DATA_SET(MFI_DATASET(set), function ## _mfiutil_command) |
| |
| #define MFI_TABLE(set, name) \ |
| SET_DECLARE(MFI_DATASET(name), struct mfiutil_command); \ |
| \ |
| static int \ |
| mfiutil_ ## name ## _table_handler(int ac, char **av) \ |
| { \ |
| return (mfi_table_handler(SET_BEGIN(MFI_DATASET(name)), \ |
| SET_LIMIT(MFI_DATASET(name)), ac, av)); \ |
| } \ |
| MFI_COMMAND(set, name, mfiutil_ ## name ## _table_handler) |
| |
| /* Drive name printing options */ |
| #define MFI_DNAME_ES 0x0001 /* E%u:S%u */ |
| #define MFI_DNAME_DEVICE_ID 0x0002 /* %u */ |
| #define MFI_DNAME_HONOR_OPTS 0x8000 /* Allow cmd line to override default */ |
| |
| #ifdef HAVE_MFI_DRIVER |
| extern int use_mfi; |
| #elif defined __sun && defined __SVR4 |
| extern size_t driver_name_length; |
| extern const char *driver_name; |
| #endif |
| extern int mfi_unit; |
| |
| extern int mfi_opts; |
| |
| /* We currently don't know the full details of the following struct */ |
| struct mfi_foreign_scan_cfg { |
| char data[24]; |
| }; |
| |
| struct mfi_foreign_scan_info { |
| uint32_t count; /* Number of foreign configs found */ |
| struct mfi_foreign_scan_cfg cfgs[8]; |
| }; |
| |
| void mbox_store_ldref(uint8_t *mbox, const union mfi_ld_ref *ref); |
| void mbox_store_pdref(uint8_t *mbox, const union mfi_pd_ref *ref); |
| void mfi_display_progress(const char *label, const struct mfi_progress *prog); |
| int mfi_table_handler(struct mfiutil_command **start, |
| struct mfiutil_command **end, int ac, char **av); |
| const char *mfi_raid_level(uint8_t primary_level, uint8_t secondary_level); |
| const char *mfi_ldstate(enum mfi_ld_state state); |
| const char *mfi_pdstate(enum mfi_pd_state state); |
| const char *mfi_pd_inq_string(const struct mfi_pd_info *info); |
| const char *mfi_volume_name(int fd, uint8_t target_id); |
| int mfi_volume_busy(int fd, uint8_t target_id); |
| int mfi_config_read(int fd, struct mfi_config_data **configp); |
| int mfi_config_read_opcode(int fd, union mfi_dcmd_opcode opcode, |
| struct mfi_config_data **configp, const uint8_t *mbox, size_t mboxlen); |
| int mfi_lookup_drive(int fd, char *drive, uint16_t *device_id); |
| int mfi_lookup_volume(int fd, const char *name, uint8_t *target_id); |
| int mfi_dcmd_command(int fd, union mfi_dcmd_opcode opcode, void *buf, size_t bufsize, |
| const uint8_t *mbox, size_t mboxlen, uint8_t *statusp); |
| int mfi_open(int unit, int acs); |
| int mfi_ctrl_get_info(int fd, struct mfi_ctrl_info *info, uint8_t *statusp); |
| int mfi_ld_get_info(int fd, uint8_t target_id, struct mfi_ld_info *info, |
| uint8_t *statusp); |
| int mfi_ld_get_list(int fd, struct mfi_ld_list *list, uint8_t *statusp); |
| int mfi_pd_get_info(int fd, uint16_t device_id, struct mfi_pd_info *info, |
| uint8_t *statusp); |
| int mfi_pd_get_list(int fd, struct mfi_pd_list **listp, uint8_t *statusp); |
| int mfi_reconfig_supported(void); |
| const char *mfi_status(uint8_t status_code); |
| const char *mfi_drive_name(const struct mfi_pd_info *pinfo, uint16_t device_id, |
| uint32_t def); |
| void format_stripe(char *buf, size_t buflen, uint8_t stripe); |
| void print_ld(const struct mfi_ld_info *info, int state_len); |
| void print_pd(const struct mfi_pd_info *info, int state_len); |
| void dump_config(int fd, const struct mfi_config_data *config, const char *msg_prefix); |
| int mfi_bbu_get_props(int fd, struct mfi_bbu_properties *props, |
| uint8_t *statusp); |
| int mfi_bbu_set_props(int fd, struct mfi_bbu_properties *props, |
| uint8_t *statusp); |
| void mfi_autolearn_period(uint32_t, char *, size_t); |
| void mfi_next_learn_time(uint32_t, char *, size_t); |
| void mfi_autolearn_mode(uint8_t, char *, size_t); |
| |
| void scan_firmware(const struct mfi_info_component *comp); |
| void display_firmware(const struct mfi_info_component *comp, const char *tag); |
| |
| int display_format(int ac, char **av, int diagnostic, mfi_dcmd_t display_cmd); |
| #endif /* !__MFIUTIL_H__ */ |