summaryrefslogtreecommitdiffstats
path: root/os_freebsd.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--os_freebsd.h769
1 files changed, 769 insertions, 0 deletions
diff --git a/os_freebsd.h b/os_freebsd.h
new file mode 100644
index 0000000..d7191ea
--- /dev/null
+++ b/os_freebsd.h
@@ -0,0 +1,769 @@
+/*
+ * os_freebsd.h
+ *
+ * Home page of code is: http://www.smartmontools.org
+ *
+ * Copyright (C) 2003-8 Eduard Martinescu
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2003 Paul Saab
+ * Copyright (c) 2003 Vinod Kashyap
+ * Copyright (c) 2000 BSDi
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Copyright (c) 2004-05 Applied Micro Circuits Corporation.
+ * Copyright (c) 2004-05 Vinod Kashyap
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef OS_FREEBSD_H_
+#define OS_FREEBSD_H_
+
+#define OS_FREEBSD_H_CVSID "$Id: os_freebsd.h 5247 2021-11-23 12:08:56Z samm2 $"
+
+#define MAX_NUM_DEV 26
+
+#ifdef HAVE_SYS_TWEREG_H
+#include <sys/twereg.h>
+#else
+/**
+ * The following cut out of twereg.h
+ *
+ */
+#if __FreeBSD_version < 500040
+#define __packed __attribute__((__packed__))
+#endif
+
+#define TWE_MAX_SGL_LENGTH 62
+#define TWE_MAX_ATA_SGL_LENGTH 60
+#define TWE_OP_ATA_PASSTHROUGH 0x11
+
+/* scatter/gather list entry */
+typedef struct
+{
+ u_int32_t address;
+ u_int32_t length;
+} __packed TWE_SG_Entry;
+
+typedef struct {
+ u_int8_t opcode:5; /* TWE_OP_INITCONNECTION */
+ u_int8_t res1:3;
+ u_int8_t size;
+ u_int8_t request_id;
+ u_int8_t res2:4;
+ u_int8_t host_id:4;
+ u_int8_t status;
+ u_int8_t flags;
+ u_int16_t message_credits;
+ u_int32_t response_queue_pointer;
+} __packed TWE_Command_INITCONNECTION;
+
+typedef struct
+{
+ u_int8_t opcode:5; /* TWE_OP_READ/TWE_OP_WRITE */
+ u_int8_t res1:3;
+ u_int8_t size;
+ u_int8_t request_id;
+ u_int8_t unit:4;
+ u_int8_t host_id:4;
+ u_int8_t status;
+ u_int8_t flags;
+ u_int16_t block_count;
+ u_int32_t lba;
+ TWE_SG_Entry sgl[TWE_MAX_SGL_LENGTH];
+} __packed TWE_Command_IO;
+
+typedef struct
+{
+ u_int8_t opcode:5; /* TWE_OP_HOTSWAP */
+ u_int8_t res1:3;
+ u_int8_t size;
+ u_int8_t request_id;
+ u_int8_t unit:4;
+ u_int8_t host_id:4;
+ u_int8_t status;
+ u_int8_t flags;
+ u_int8_t action;
+#define TWE_OP_HOTSWAP_REMOVE 0x00 /* remove assumed-degraded unit */
+#define TWE_OP_HOTSWAP_ADD_CBOD 0x01 /* add CBOD to empty port */
+#define TWE_OP_HOTSWAP_ADD_SPARE 0x02 /* add spare to empty port */
+ u_int8_t aport;
+} __packed TWE_Command_HOTSWAP;
+
+typedef struct
+{
+ u_int8_t opcode:5; /* TWE_OP_SETATAFEATURE */
+ u_int8_t res1:3;
+ u_int8_t size;
+ u_int8_t request_id;
+ u_int8_t unit:4;
+ u_int8_t host_id:4;
+ u_int8_t status;
+ u_int8_t flags;
+ u_int8_t feature;
+#define TWE_OP_SETATAFEATURE_WCE 0x02
+#define TWE_OP_SETATAFEATURE_DIS_WCE 0x82
+ u_int8_t feature_mode;
+ u_int16_t all_units;
+ u_int16_t persistence;
+} __packed TWE_Command_SETATAFEATURE;
+
+typedef struct
+{
+ u_int8_t opcode:5; /* TWE_OP_CHECKSTATUS */
+ u_int8_t res1:3;
+ u_int8_t size;
+ u_int8_t request_id;
+ u_int8_t unit:4;
+ u_int8_t res2:4;
+ u_int8_t status;
+ u_int8_t flags;
+ u_int16_t target_status; /* set low byte to target request's ID */
+} __packed TWE_Command_CHECKSTATUS;
+
+typedef struct
+{
+ u_int8_t opcode:5; /* TWE_OP_GETPARAM, TWE_OP_SETPARAM */
+ u_int8_t res1:3;
+ u_int8_t size;
+ u_int8_t request_id;
+ u_int8_t unit:4;
+ u_int8_t host_id:4;
+ u_int8_t status;
+ u_int8_t flags;
+ u_int16_t param_count;
+ TWE_SG_Entry sgl[TWE_MAX_SGL_LENGTH];
+} __packed TWE_Command_PARAM;
+
+typedef struct
+{
+ u_int8_t opcode:5; /* TWE_OP_REBUILDUNIT */
+ u_int8_t res1:3;
+ u_int8_t size;
+ u_int8_t request_id;
+ u_int8_t src_unit:4;
+ u_int8_t host_id:4;
+ u_int8_t status;
+ u_int8_t flags;
+ u_int8_t action:7;
+#define TWE_OP_REBUILDUNIT_NOP 0
+#define TWE_OP_REBUILDUNIT_STOP 2 /* stop all rebuilds */
+#define TWE_OP_REBUILDUNIT_START 4 /* start rebuild with lowest unit */
+#define TWE_OP_REBUILDUNIT_STARTUNIT 5 /* rebuild src_unit (not supported) */
+ u_int8_t cs:1; /* request state change on src_unit */
+ u_int8_t logical_subunit; /* for RAID10 rebuild of logical subunit */
+} __packed TWE_Command_REBUILDUNIT;
+
+typedef struct
+{
+ u_int8_t opcode:5;
+ u_int8_t sgl_offset:3;
+ u_int8_t size;
+ u_int8_t request_id;
+ u_int8_t unit;
+ u_int8_t status;
+ u_int8_t flags;
+ u_int16_t param;
+ u_int16_t features;
+ u_int16_t sector_count;
+ u_int16_t sector_num;
+ u_int16_t cylinder_lo;
+ u_int16_t cylinder_hi;
+ u_int8_t drive_head;
+ u_int8_t command;
+ TWE_SG_Entry sgl[TWE_MAX_ATA_SGL_LENGTH];
+} __packed TWE_Command_ATA;
+
+typedef struct
+{
+ u_int8_t opcode:5;
+ u_int8_t sgl_offset:3;
+ u_int8_t size;
+ u_int8_t request_id;
+ u_int8_t unit:4;
+ u_int8_t host_id:4;
+ u_int8_t status;
+ u_int8_t flags;
+#define TWE_FLAGS_SUCCESS 0x00
+#define TWE_FLAGS_INFORMATIONAL 0x01
+#define TWE_FLAGS_WARNING 0x02
+#define TWE_FLAGS_FATAL 0x03
+#define TWE_FLAGS_PERCENTAGE (1<<8) /* bits 0-6 indicate completion percentage */
+ u_int16_t count; /* block count, parameter count, message credits */
+} __packed TWE_Command_Generic;
+
+/* command packet - must be TWE_ALIGNMENT aligned */
+typedef union
+{
+ TWE_Command_INITCONNECTION initconnection;
+ TWE_Command_IO io;
+ TWE_Command_PARAM param;
+ TWE_Command_CHECKSTATUS checkstatus;
+ TWE_Command_REBUILDUNIT rebuildunit;
+ TWE_Command_SETATAFEATURE setatafeature;
+ TWE_Command_ATA ata;
+ TWE_Command_Generic generic;
+ u_int8_t pad[512];
+} TWE_Command;
+
+/* response queue entry */
+typedef union
+{
+ struct
+ {
+ u_int32_t undefined_1:4;
+ u_int32_t response_id:8;
+ u_int32_t undefined_2:20;
+ } u;
+ u_int32_t value;
+} TWE_Response_Queue;
+
+#endif
+
+#ifdef HAVE_SYS_TWEIO_H
+#include <sys/tweio.h>
+#else
+/*
+ * Following cut out of tweio.h
+ *
+ */
+/*
+ * User-space command
+ *
+ * Note that the command's scatter/gather list will be computed by the
+ * driver, and cannot be filled in by the consumer.
+ */
+struct twe_usercommand {
+ TWE_Command tu_command; /* command ready for the controller */
+ void *tu_data; /* pointer to data in userspace */
+ size_t tu_size; /* userspace data length */
+};
+
+#define TWEIO_COMMAND _IOWR('T', 100, struct twe_usercommand)
+
+#endif
+
+#ifdef HAVE_SYS_TW_OSL_IOCTL_H
+#include <sys/tw_osl_ioctl.h>
+#else
+/*
+ * Following cut out of tw_osl_types.h
+ *
+ */
+
+typedef void TW_VOID;
+typedef char TW_INT8;
+typedef unsigned char TW_UINT8;
+typedef short TW_INT16;
+typedef unsigned short TW_UINT16;
+typedef int TW_INT32;
+typedef unsigned int TW_UINT32;
+typedef long long TW_INT64;
+typedef unsigned long long TW_UINT64;
+
+/*
+ * Following cut out of tw_cl_share.h
+ *
+ */
+
+#pragma pack(1)
+
+struct tw_cl_event_packet {
+ TW_UINT32 sequence_id;
+ TW_UINT32 time_stamp_sec;
+ TW_UINT16 aen_code;
+ TW_UINT8 severity;
+ TW_UINT8 retrieved;
+ TW_UINT8 repeat_count;
+ TW_UINT8 parameter_len;
+ TW_UINT8 parameter_data[98];
+ TW_UINT32 event_src;
+ TW_UINT8 severity_str[20];
+};
+
+#pragma pack()
+
+/*
+ * Following cut out of tw_cl_fwif.h
+ *
+ */
+
+#define TWA_FW_CMD_ATA_PASSTHROUGH 0x11
+
+#define TWA_SENSE_DATA_LENGTH 18
+
+#pragma pack(1)
+/* 7000 structures. */
+struct tw_cl_command_init_connect {
+ TW_UINT8 res1__opcode; /* 3:5 */
+ TW_UINT8 size;
+ TW_UINT8 request_id;
+ TW_UINT8 res2;
+ TW_UINT8 status;
+ TW_UINT8 flags;
+ TW_UINT16 message_credits;
+ TW_UINT32 features;
+ TW_UINT16 fw_srl;
+ TW_UINT16 fw_arch_id;
+ TW_UINT16 fw_branch;
+ TW_UINT16 fw_build;
+ TW_UINT32 result;
+};
+
+
+/* Structure for downloading firmware onto the controller. */
+struct tw_cl_command_download_firmware {
+ TW_UINT8 sgl_off__opcode;/* 3:5 */
+ TW_UINT8 size;
+ TW_UINT8 request_id;
+ TW_UINT8 unit;
+ TW_UINT8 status;
+ TW_UINT8 flags;
+ TW_UINT16 param;
+ TW_UINT8 sgl[1];
+};
+
+
+/* Structure for hard resetting the controller. */
+struct tw_cl_command_reset_firmware {
+ TW_UINT8 res1__opcode; /* 3:5 */
+ TW_UINT8 size;
+ TW_UINT8 request_id;
+ TW_UINT8 unit;
+ TW_UINT8 status;
+ TW_UINT8 flags;
+ TW_UINT8 res2;
+ TW_UINT8 param;
+};
+
+
+/* Structure for sending get/set param commands. */
+struct tw_cl_command_param {
+ TW_UINT8 sgl_off__opcode;/* 3:5 */
+ TW_UINT8 size;
+ TW_UINT8 request_id;
+ TW_UINT8 host_id__unit; /* 4:4 */
+ TW_UINT8 status;
+ TW_UINT8 flags;
+ TW_UINT16 param_count;
+ TW_UINT8 sgl[1];
+};
+
+
+/* Generic command packet. */
+struct tw_cl_command_generic {
+ TW_UINT8 sgl_off__opcode;/* 3:5 */
+ TW_UINT8 size;
+ TW_UINT8 request_id;
+ TW_UINT8 host_id__unit; /* 4:4 */
+ TW_UINT8 status;
+ TW_UINT8 flags;
+ TW_UINT16 count; /* block cnt, parameter cnt, message credits */
+};
+
+
+/* Command packet header. */
+struct tw_cl_command_header {
+ TW_UINT8 sense_data[TWA_SENSE_DATA_LENGTH];
+ struct {
+ TW_INT8 reserved[4];
+ TW_UINT16 error;
+ TW_UINT8 padding;
+ TW_UINT8 res__severity; /* 5:3 */
+ } status_block;
+ TW_UINT8 err_specific_desc[98];
+ struct {
+ TW_UINT8 size_header;
+ TW_UINT16 reserved;
+ TW_UINT8 size_sense;
+ } header_desc;
+};
+
+
+/* 7000 Command packet. */
+union tw_cl_command_7k {
+ struct tw_cl_command_init_connect init_connect;
+ struct tw_cl_command_download_firmware download_fw;
+ struct tw_cl_command_reset_firmware reset_fw;
+ struct tw_cl_command_param param;
+ struct tw_cl_command_generic generic;
+ TW_UINT8 padding[1024 - sizeof(struct tw_cl_command_header)];
+};
+
+
+/* 9000 Command Packet. */
+struct tw_cl_command_9k {
+ TW_UINT8 res__opcode; /* 3:5 */
+ TW_UINT8 unit;
+ TW_UINT16 lun_l4__req_id; /* 4:12 */
+ TW_UINT8 status;
+ TW_UINT8 sgl_offset; /* offset (in bytes) to sg_list, from the
+ end of sgl_entries */
+ TW_UINT16 lun_h4__sgl_entries;
+ TW_UINT8 cdb[16];
+ TW_UINT8 sg_list[872];/* total struct size =
+ 1024-sizeof(cmd_hdr) */
+};
+
+
+/* Full command packet. */
+struct tw_cl_command_packet {
+ struct tw_cl_command_header cmd_hdr;
+ union {
+ union tw_cl_command_7k cmd_pkt_7k;
+ struct tw_cl_command_9k cmd_pkt_9k;
+ } command;
+};
+
+#pragma pack()
+
+/*
+ * Following cut out of tw_cl_ioctl.h
+ *
+ */
+
+#pragma pack(1)
+
+/* Structure used to handle GET/RELEASE LOCK ioctls. */
+struct tw_cl_lock_packet {
+ TW_UINT32 timeout_msec;
+ TW_UINT32 time_remaining_msec;
+ TW_UINT32 force_flag;
+};
+
+
+/* Structure used to handle GET COMPATIBILITY INFO ioctl. */
+struct tw_cl_compatibility_packet {
+ TW_UINT8 driver_version[32];/* driver version */
+ TW_UINT16 working_srl; /* driver & firmware negotiated srl */
+ TW_UINT16 working_branch; /* branch # of the firmware that the
+ driver is compatible with */
+ TW_UINT16 working_build; /* build # of the firmware that the
+ driver is compatible with */
+};
+
+
+/* Driver understandable part of the ioctl packet built by the API. */
+struct tw_cl_driver_packet {
+ TW_UINT32 control_code;
+ TW_UINT32 status;
+ TW_UINT32 unique_id;
+ TW_UINT32 sequence_id;
+ TW_UINT32 os_status;
+ TW_UINT32 buffer_length;
+};
+
+#pragma pack()
+
+/*
+ * Following cut out of tw_osl_ioctl.h
+ *
+ */
+
+#pragma pack(1)
+/*
+ * We need the structure below to ensure that the first byte of
+ * data_buf is not overwritten by the kernel, after we return
+ * from the ioctl call. Note that cmd_pkt has been reduced
+ * to an array of 1024 bytes even though it's actually 2048 bytes
+ * in size. This is because, we don't expect requests from user
+ * land requiring 2048 (273 sg elements) byte cmd pkts.
+ */
+typedef struct tw_osli_ioctl_no_data_buf {
+ struct tw_cl_driver_packet driver_pkt;
+ TW_VOID *pdata; /* points to data_buf */
+ TW_INT8 padding[488 - sizeof(TW_VOID *)];
+ struct tw_cl_command_packet cmd_pkt;
+} TW_OSLI_IOCTL_NO_DATA_BUF;
+
+#pragma pack()
+
+#define TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH \
+ _IOWR('T', 202, TW_OSLI_IOCTL_NO_DATA_BUF)
+
+#pragma pack(1)
+
+typedef struct tw_osli_ioctl_with_payload {
+ struct tw_cl_driver_packet driver_pkt;
+ TW_INT8 padding[488];
+ struct tw_cl_command_packet cmd_pkt;
+ union {
+ struct tw_cl_event_packet event_pkt;
+ struct tw_cl_lock_packet lock_pkt;
+ struct tw_cl_compatibility_packet compat_pkt;
+ TW_INT8 data_buf[1];
+ } payload;
+} TW_OSLI_IOCTL_WITH_PAYLOAD;
+
+#pragma pack()
+
+#endif
+
+#define HPT_CTL_CODE(x) (x+0xFF00)
+#define HPT_IOCTL_GET_CHANNEL_INFO HPT_CTL_CODE(3)
+#define HPT_IOCTL_GET_CHANNEL_INFO_V2 HPT_CTL_CODE(53)
+#define HPT_IOCTL_IDE_PASS_THROUGH HPT_CTL_CODE(24)
+
+#define HPT_READ 1
+#define HPT_WRITE 2
+
+#define HPT_IOCTL_MAGIC 0xA1B2C3D4
+
+#define MAXDEV_PER_CHANNEL 2
+#define PMPORT_PER_CHANNEL 15 /* max devices connected to this channel via pmport */
+
+#pragma pack(1)
+typedef struct _HPT_CHANNEL_INFO {
+ unsigned int reserve1;
+ unsigned int reserve2;
+ unsigned int devices[MAXDEV_PER_CHANNEL];
+} HPT_CHANNEL_INFO, *PHPT_CHANNEL_INFO;
+
+typedef struct _HPT_CHANNEL_INFO_V2 {
+ unsigned int reserve1;
+ unsigned int reserve2;
+ unsigned int devices[PMPORT_PER_CHANNEL];
+} HPT_CHANNEL_INFO_V2, *PHPT_CHANNEL_INFO_V2;
+
+typedef struct _HPT_IOCTL_PARAM {
+ unsigned int magic; /* used to check if it's a valid ioctl packet */
+ unsigned int ctrl_code; /* operation control code */
+ void* in; /* input data buffer */
+ unsigned int in_size; /* size of input data buffer */
+ void* out; /* output data buffer */
+ unsigned int out_size; /* size of output data buffer */
+ void* returned_size; /* count of chars returned */
+} HPT_IOCTL_PARAM, *PHPT_IOCTL_PARAM;
+#define HPT_DO_IOCONTROL _IOW('H', 0, HPT_IOCTL_PARAM)
+
+typedef struct _HPT_PASS_THROUGH_HEADER {
+ unsigned int id; /* disk ID */
+ unsigned char feature;
+ unsigned char sectorcount;
+ unsigned char lbalow;
+ unsigned char lbamid;
+ unsigned char lbahigh;
+ unsigned char driverhead;
+ unsigned char command;
+ unsigned char sectors; /* data size in sectors, if the command has data transfer */
+ unsigned char protocol; /* HPT_(READ,WRITE) or zero for non-DATA */
+ unsigned char reserve[3];
+}
+HPT_PASS_THROUGH_HEADER, *PHPT_PASS_THROUGH_HEADER;
+#pragma pack()
+
+#ifndef __unused
+#define __unused __attribute__ ((__unused__))
+#endif
+
+// MFI definition from the kernel sources, see sys/dev/mfi
+
+#define MFI_STAT_OK 0x00
+#define MFI_DCMD_PD_GET_LIST 0x02010000
+
+#define MFI_CTRLR_PREFIX "/dev/mfi"
+#define MRSAS_CTRLR_PREFIX "/dev/mrsas"
+
+/*
+ * MFI Frame flags
+ */
+#define MFI_FRAME_POST_IN_REPLY_QUEUE 0x0000
+#define MFI_FRAME_DONT_POST_IN_REPLY_QUEUE 0x0001
+#define MFI_FRAME_SGL32 0x0000
+#define MFI_FRAME_SGL64 0x0002
+#define MFI_FRAME_SENSE32 0x0000
+#define MFI_FRAME_SENSE64 0x0004
+#define MFI_FRAME_DIR_NONE 0x0000
+#define MFI_FRAME_DIR_WRITE 0x0008
+#define MFI_FRAME_DIR_READ 0x0010
+#define MFI_FRAME_DIR_BOTH 0x0018
+#define MFI_FRAME_IEEE_SGL 0x0020
+#define MFI_FRAME_FMT "\20" \
+ "\1NOPOST" \
+ "\2SGL64" \
+ "\3SENSE64" \
+ "\4WRITE" \
+ "\5READ" \
+ "\6IEEESGL"
+
+/* MFI Commands */
+typedef enum {
+ MFI_CMD_INIT = 0x00,
+ MFI_CMD_LD_READ,
+ MFI_CMD_LD_WRITE,
+ MFI_CMD_LD_SCSI_IO,
+ MFI_CMD_PD_SCSI_IO,
+ MFI_CMD_DCMD,
+ MFI_CMD_ABORT,
+ MFI_CMD_SMP,
+ MFI_CMD_STP
+} mfi_cmd_t;
+
+/* Scatter Gather elements */
+struct mfi_sg32 {
+ uint32_t addr;
+ uint32_t len;
+} __packed;
+
+struct mfi_sg64 {
+ uint64_t addr;
+ uint32_t len;
+} __packed;
+
+struct mfi_sg_skinny {
+ uint64_t addr;
+ uint32_t len;
+ uint32_t flag;
+} __packed;
+
+union mfi_sgl {
+ struct mfi_sg32 sg32[1];
+ struct mfi_sg64 sg64[1];
+ struct mfi_sg_skinny sg_skinny[1];
+} __packed;
+
+/* Message frames. All messages have a common header */
+struct mfi_frame_header {
+ uint8_t cmd;
+ uint8_t sense_len;
+ uint8_t cmd_status;
+ uint8_t scsi_status;
+ uint8_t target_id;
+ uint8_t lun_id;
+ uint8_t cdb_len;
+ uint8_t sg_count;
+ uint32_t context;
+ /*
+ * pad0 is MSI Specific. Not used by Driver. Zero the value before
+ * sending the command to f/w.
+ */
+ uint32_t pad0;
+ uint16_t flags;
+#define MFI_FRAME_DATAOUT 0x08
+#define MFI_FRAME_DATAIN 0x10
+ uint16_t timeout;
+ uint32_t data_len;
+} __packed;
+
+#define MFI_PASS_FRAME_SIZE 48
+struct mfi_pass_frame {
+ struct mfi_frame_header header;
+ uint32_t sense_addr_lo;
+ uint32_t sense_addr_hi;
+ uint8_t cdb[16];
+ union mfi_sgl sgl;
+} __packed;
+
+#define MFI_DCMD_FRAME_SIZE 40
+#define MFI_MBOX_SIZE 12
+
+struct mfi_dcmd_frame {
+ struct mfi_frame_header header;
+ uint32_t opcode;
+ uint8_t mbox[MFI_MBOX_SIZE];
+ union mfi_sgl sgl;
+} __packed;
+
+#define MAX_IOCTL_SGE 16
+struct mfi_ioc_packet {
+ uint16_t mfi_adapter_no;
+ uint16_t mfi_pad1;
+ uint32_t mfi_sgl_off;
+ uint32_t mfi_sge_count;
+ uint32_t mfi_sense_off;
+ uint32_t mfi_sense_len;
+ union {
+ uint8_t raw[128];
+ struct mfi_frame_header hdr;
+ } mfi_frame;
+
+ struct iovec mfi_sgl[MAX_IOCTL_SGE];
+} __packed;
+
+#ifdef COMPAT_FREEBSD32
+struct mfi_ioc_packet32 {
+ uint16_t mfi_adapter_no;
+ uint16_t mfi_pad1;
+ uint32_t mfi_sgl_off;
+ uint32_t mfi_sge_count;
+ uint32_t mfi_sense_off;
+ uint32_t mfi_sense_len;
+ union {
+ uint8_t raw[128];
+ struct mfi_frame_header hdr;
+ } mfi_frame;
+
+ struct iovec32 mfi_sgl[MAX_IOCTL_SGE];
+} __packed;
+#endif
+
+struct mfi_pd_address {
+ uint16_t device_id;
+ uint16_t encl_device_id;
+ uint8_t encl_index;
+ uint8_t slot_number;
+ uint8_t scsi_dev_type; /* 0 = disk */
+ uint8_t connect_port_bitmap;
+ uint64_t sas_addr[2];
+} __packed;
+
+#define MAX_SYS_PDS 240
+struct mfi_pd_list {
+ uint32_t size;
+ uint32_t count;
+ struct mfi_pd_address addr[MAX_SYS_PDS];
+} __packed;
+
+#define MFI_CMD _IOWR('M', 1, struct mfi_ioc_packet)
+
+#endif /* OS_FREEBSD_H_ */