summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mvumi.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/mvumi.h')
-rw-r--r--drivers/scsi/mvumi.h573
1 files changed, 573 insertions, 0 deletions
diff --git a/drivers/scsi/mvumi.h b/drivers/scsi/mvumi.h
new file mode 100644
index 000000000..41f168702
--- /dev/null
+++ b/drivers/scsi/mvumi.h
@@ -0,0 +1,573 @@
+/*
+ * Marvell UMI head file
+ *
+ * Copyright 2011 Marvell. <jyli@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef MVUMI_H
+#define MVUMI_H
+
+#define MAX_BASE_ADDRESS 6
+
+#define VER_MAJOR 1
+#define VER_MINOR 1
+#define VER_OEM 0
+#define VER_BUILD 1500
+
+#define MV_DRIVER_NAME "mvumi"
+#define PCI_DEVICE_ID_MARVELL_MV9143 0x9143
+#define PCI_DEVICE_ID_MARVELL_MV9580 0x9580
+
+#define MVUMI_INTERNAL_CMD_WAIT_TIME 45
+#define MVUMI_INQUIRY_LENGTH 44
+#define MVUMI_INQUIRY_UUID_OFF 36
+#define MVUMI_INQUIRY_UUID_LEN 8
+
+#define IS_DMA64 (sizeof(dma_addr_t) == 8)
+
+enum mvumi_qc_result {
+ MV_QUEUE_COMMAND_RESULT_SENT = 0,
+ MV_QUEUE_COMMAND_RESULT_NO_RESOURCE,
+};
+
+struct mvumi_hw_regs {
+ /* For CPU */
+ void *main_int_cause_reg;
+ void *enpointa_mask_reg;
+ void *enpointb_mask_reg;
+ void *rstoutn_en_reg;
+ void *ctrl_sts_reg;
+ void *rstoutn_mask_reg;
+ void *sys_soft_rst_reg;
+
+ /* For Doorbell */
+ void *pciea_to_arm_drbl_reg;
+ void *arm_to_pciea_drbl_reg;
+ void *arm_to_pciea_mask_reg;
+ void *pciea_to_arm_msg0;
+ void *pciea_to_arm_msg1;
+ void *arm_to_pciea_msg0;
+ void *arm_to_pciea_msg1;
+
+ /* reset register */
+ void *reset_request;
+ void *reset_enable;
+
+ /* For Message Unit */
+ void *inb_list_basel;
+ void *inb_list_baseh;
+ void *inb_aval_count_basel;
+ void *inb_aval_count_baseh;
+ void *inb_write_pointer;
+ void *inb_read_pointer;
+ void *outb_list_basel;
+ void *outb_list_baseh;
+ void *outb_copy_basel;
+ void *outb_copy_baseh;
+ void *outb_copy_pointer;
+ void *outb_read_pointer;
+ void *inb_isr_cause;
+ void *outb_isr_cause;
+ void *outb_coal_cfg;
+ void *outb_coal_timeout;
+
+ /* Bit setting for HW */
+ u32 int_comaout;
+ u32 int_comaerr;
+ u32 int_dl_cpu2pciea;
+ u32 int_mu;
+ u32 int_drbl_int_mask;
+ u32 int_main_int_mask;
+ u32 cl_pointer_toggle;
+ u32 cl_slot_num_mask;
+ u32 clic_irq;
+ u32 clic_in_err;
+ u32 clic_out_err;
+};
+
+struct mvumi_dyn_list_entry {
+ u32 src_low_addr;
+ u32 src_high_addr;
+ u32 if_length;
+ u32 reserve;
+};
+
+#define SCSI_CMD_MARVELL_SPECIFIC 0xE1
+#define CDB_CORE_MODULE 0x1
+#define CDB_CORE_SHUTDOWN 0xB
+
+enum {
+ DRBL_HANDSHAKE = 1 << 0,
+ DRBL_SOFT_RESET = 1 << 1,
+ DRBL_BUS_CHANGE = 1 << 2,
+ DRBL_EVENT_NOTIFY = 1 << 3,
+ DRBL_MU_RESET = 1 << 4,
+ DRBL_HANDSHAKE_ISR = DRBL_HANDSHAKE,
+
+ /*
+ * Command flag is the flag for the CDB command itself
+ */
+ /* 1-non data; 0-data command */
+ CMD_FLAG_NON_DATA = 1 << 0,
+ CMD_FLAG_DMA = 1 << 1,
+ CMD_FLAG_PIO = 1 << 2,
+ /* 1-host read data */
+ CMD_FLAG_DATA_IN = 1 << 3,
+ /* 1-host write data */
+ CMD_FLAG_DATA_OUT = 1 << 4,
+ CMD_FLAG_PRDT_IN_HOST = 1 << 5,
+};
+
+#define APICDB0_EVENT 0xF4
+#define APICDB1_EVENT_GETEVENT 0
+#define APICDB1_HOST_GETEVENT 1
+#define MAX_EVENTS_RETURNED 6
+
+#define DEVICE_OFFLINE 0
+#define DEVICE_ONLINE 1
+
+struct mvumi_hotplug_event {
+ u16 size;
+ u8 dummy[2];
+ u8 bitmap[0];
+};
+
+struct mvumi_driver_event {
+ u32 time_stamp;
+ u32 sequence_no;
+ u32 event_id;
+ u8 severity;
+ u8 param_count;
+ u16 device_id;
+ u32 params[4];
+ u8 sense_data_length;
+ u8 Reserved1;
+ u8 sense_data[30];
+};
+
+struct mvumi_event_req {
+ unsigned char count;
+ unsigned char reserved[3];
+ struct mvumi_driver_event events[MAX_EVENTS_RETURNED];
+};
+
+struct mvumi_events_wq {
+ struct work_struct work_q;
+ struct mvumi_hba *mhba;
+ unsigned int event;
+ void *param;
+};
+
+#define HS_CAPABILITY_SUPPORT_COMPACT_SG (1U << 4)
+#define HS_CAPABILITY_SUPPORT_PRD_HOST (1U << 5)
+#define HS_CAPABILITY_SUPPORT_DYN_SRC (1U << 6)
+#define HS_CAPABILITY_NEW_PAGE_IO_DEPTH_DEF (1U << 14)
+
+#define MVUMI_MAX_SG_ENTRY 32
+#define SGD_EOT (1L << 27)
+#define SGD_EOT_CP (1L << 22)
+
+struct mvumi_sgl {
+ u32 baseaddr_l;
+ u32 baseaddr_h;
+ u32 flags;
+ u32 size;
+};
+struct mvumi_compact_sgl {
+ u32 baseaddr_l;
+ u32 baseaddr_h;
+ u32 flags;
+};
+
+#define GET_COMPACT_SGD_SIZE(sgd) \
+ ((((struct mvumi_compact_sgl *)(sgd))->flags) & 0x3FFFFFL)
+
+#define SET_COMPACT_SGD_SIZE(sgd, sz) do { \
+ (((struct mvumi_compact_sgl *)(sgd))->flags) &= ~0x3FFFFFL; \
+ (((struct mvumi_compact_sgl *)(sgd))->flags) |= (sz); \
+} while (0)
+#define sgd_getsz(_mhba, sgd, sz) do { \
+ if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG) \
+ (sz) = GET_COMPACT_SGD_SIZE(sgd); \
+ else \
+ (sz) = (sgd)->size; \
+} while (0)
+
+#define sgd_setsz(_mhba, sgd, sz) do { \
+ if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG) \
+ SET_COMPACT_SGD_SIZE(sgd, sz); \
+ else \
+ (sgd)->size = (sz); \
+} while (0)
+
+#define sgd_inc(_mhba, sgd) do { \
+ if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG) \
+ sgd = (struct mvumi_sgl *)(((unsigned char *) (sgd)) + 12); \
+ else \
+ sgd = (struct mvumi_sgl *)(((unsigned char *) (sgd)) + 16); \
+} while (0)
+
+struct mvumi_res {
+ struct list_head entry;
+ dma_addr_t bus_addr;
+ void *virt_addr;
+ unsigned int size;
+ unsigned short type; /* enum Resource_Type */
+};
+
+/* Resource type */
+enum resource_type {
+ RESOURCE_CACHED_MEMORY = 0,
+ RESOURCE_UNCACHED_MEMORY
+};
+
+struct mvumi_sense_data {
+ u8 error_code:7;
+ u8 valid:1;
+ u8 segment_number;
+ u8 sense_key:4;
+ u8 reserved:1;
+ u8 incorrect_length:1;
+ u8 end_of_media:1;
+ u8 file_mark:1;
+ u8 information[4];
+ u8 additional_sense_length;
+ u8 command_specific_information[4];
+ u8 additional_sense_code;
+ u8 additional_sense_code_qualifier;
+ u8 field_replaceable_unit_code;
+ u8 sense_key_specific[3];
+};
+
+/* Request initiator must set the status to REQ_STATUS_PENDING. */
+#define REQ_STATUS_PENDING 0x80
+
+struct mvumi_cmd {
+ struct list_head queue_pointer;
+ struct mvumi_msg_frame *frame;
+ dma_addr_t frame_phys;
+ struct scsi_cmnd *scmd;
+ atomic_t sync_cmd;
+ void *data_buf;
+ unsigned short request_id;
+ unsigned char cmd_status;
+};
+
+/*
+ * the function type of the in bound frame
+ */
+#define CL_FUN_SCSI_CMD 0x1
+
+struct mvumi_msg_frame {
+ u16 device_id;
+ u16 tag;
+ u8 cmd_flag;
+ u8 req_function;
+ u8 cdb_length;
+ u8 sg_counts;
+ u32 data_transfer_length;
+ u16 request_id;
+ u16 reserved1;
+ u8 cdb[MAX_COMMAND_SIZE];
+ u32 payload[1];
+};
+
+/*
+ * the respond flag for data_payload of the out bound frame
+ */
+#define CL_RSP_FLAG_NODATA 0x0
+#define CL_RSP_FLAG_SENSEDATA 0x1
+
+struct mvumi_rsp_frame {
+ u16 device_id;
+ u16 tag;
+ u8 req_status;
+ u8 rsp_flag; /* Indicates the type of Data_Payload.*/
+ u16 request_id;
+ u32 payload[1];
+};
+
+struct mvumi_ob_data {
+ struct list_head list;
+ unsigned char data[0];
+};
+
+struct version_info {
+ u32 ver_major;
+ u32 ver_minor;
+ u32 ver_oem;
+ u32 ver_build;
+};
+
+#define FW_MAX_DELAY 30
+#define MVUMI_FW_BUSY (1U << 0)
+#define MVUMI_FW_ATTACH (1U << 1)
+#define MVUMI_FW_ALLOC (1U << 2)
+
+/*
+ * State is the state of the MU
+ */
+#define FW_STATE_IDLE 0
+#define FW_STATE_STARTING 1
+#define FW_STATE_HANDSHAKING 2
+#define FW_STATE_STARTED 3
+#define FW_STATE_ABORT 4
+
+#define HANDSHAKE_SIGNATURE 0x5A5A5A5AL
+#define HANDSHAKE_READYSTATE 0x55AA5AA5L
+#define HANDSHAKE_DONESTATE 0x55AAA55AL
+
+/* HandShake Status definition */
+#define HS_STATUS_OK 1
+#define HS_STATUS_ERR 2
+#define HS_STATUS_INVALID 3
+
+/* HandShake State/Cmd definition */
+#define HS_S_START 1
+#define HS_S_RESET 2
+#define HS_S_PAGE_ADDR 3
+#define HS_S_QUERY_PAGE 4
+#define HS_S_SEND_PAGE 5
+#define HS_S_END 6
+#define HS_S_ABORT 7
+#define HS_PAGE_VERIFY_SIZE 128
+
+#define HS_GET_STATE(a) (a & 0xFFFF)
+#define HS_GET_STATUS(a) ((a & 0xFFFF0000) >> 16)
+#define HS_SET_STATE(a, b) (a |= (b & 0xFFFF))
+#define HS_SET_STATUS(a, b) (a |= ((b & 0xFFFF) << 16))
+
+/* handshake frame */
+struct mvumi_hs_frame {
+ u16 size;
+ /* host information */
+ u8 host_type;
+ u8 reserved_1[1];
+ struct version_info host_ver; /* bios or driver version */
+
+ /* controller information */
+ u32 system_io_bus;
+ u32 slot_number;
+ u32 intr_level;
+ u32 intr_vector;
+
+ /* communication list configuration */
+ u32 ib_baseaddr_l;
+ u32 ib_baseaddr_h;
+ u32 ob_baseaddr_l;
+ u32 ob_baseaddr_h;
+
+ u8 ib_entry_size;
+ u8 ob_entry_size;
+ u8 ob_depth;
+ u8 ib_depth;
+
+ /* system time */
+ u64 seconds_since1970;
+};
+
+struct mvumi_hs_header {
+ u8 page_code;
+ u8 checksum;
+ u16 frame_length;
+ u32 frame_content[1];
+};
+
+/*
+ * the page code type of the handshake header
+ */
+#define HS_PAGE_FIRM_CAP 0x1
+#define HS_PAGE_HOST_INFO 0x2
+#define HS_PAGE_FIRM_CTL 0x3
+#define HS_PAGE_CL_INFO 0x4
+#define HS_PAGE_TOTAL 0x5
+
+#define HSP_SIZE(i) sizeof(struct mvumi_hs_page##i)
+
+#define HSP_MAX_SIZE ({ \
+ int size, m1, m2; \
+ m1 = max(HSP_SIZE(1), HSP_SIZE(3)); \
+ m2 = max(HSP_SIZE(2), HSP_SIZE(4)); \
+ size = max(m1, m2); \
+ size; \
+})
+
+/* The format of the page code for Firmware capability */
+struct mvumi_hs_page1 {
+ u8 pagecode;
+ u8 checksum;
+ u16 frame_length;
+
+ u16 number_of_ports;
+ u16 max_devices_support;
+ u16 max_io_support;
+ u16 umi_ver;
+ u32 max_transfer_size;
+ struct version_info fw_ver;
+ u8 cl_in_max_entry_size;
+ u8 cl_out_max_entry_size;
+ u8 cl_inout_list_depth;
+ u8 total_pages;
+ u16 capability;
+ u16 reserved1;
+};
+
+/* The format of the page code for Host information */
+struct mvumi_hs_page2 {
+ u8 pagecode;
+ u8 checksum;
+ u16 frame_length;
+
+ u8 host_type;
+ u8 host_cap;
+ u8 reserved[2];
+ struct version_info host_ver;
+ u32 system_io_bus;
+ u32 slot_number;
+ u32 intr_level;
+ u32 intr_vector;
+ u64 seconds_since1970;
+};
+
+/* The format of the page code for firmware control */
+struct mvumi_hs_page3 {
+ u8 pagecode;
+ u8 checksum;
+ u16 frame_length;
+ u16 control;
+ u8 reserved[2];
+ u32 host_bufferaddr_l;
+ u32 host_bufferaddr_h;
+ u32 host_eventaddr_l;
+ u32 host_eventaddr_h;
+};
+
+struct mvumi_hs_page4 {
+ u8 pagecode;
+ u8 checksum;
+ u16 frame_length;
+ u32 ib_baseaddr_l;
+ u32 ib_baseaddr_h;
+ u32 ob_baseaddr_l;
+ u32 ob_baseaddr_h;
+ u8 ib_entry_size;
+ u8 ob_entry_size;
+ u8 ob_depth;
+ u8 ib_depth;
+};
+
+struct mvumi_tag {
+ unsigned short *stack;
+ unsigned short top;
+ unsigned short size;
+};
+
+struct mvumi_device {
+ struct list_head list;
+ struct scsi_device *sdev;
+ u64 wwid;
+ u8 dev_type;
+ int id;
+};
+
+struct mvumi_hba {
+ void *base_addr[MAX_BASE_ADDRESS];
+ u32 pci_base[MAX_BASE_ADDRESS];
+ void *mmio;
+ struct list_head cmd_pool;
+ struct Scsi_Host *shost;
+ wait_queue_head_t int_cmd_wait_q;
+ struct pci_dev *pdev;
+ unsigned int unique_id;
+ atomic_t fw_outstanding;
+ struct mvumi_instance_template *instancet;
+
+ void *ib_list;
+ dma_addr_t ib_list_phys;
+
+ void *ib_frame;
+ dma_addr_t ib_frame_phys;
+
+ void *ob_list;
+ dma_addr_t ob_list_phys;
+
+ void *ib_shadow;
+ dma_addr_t ib_shadow_phys;
+
+ void *ob_shadow;
+ dma_addr_t ob_shadow_phys;
+
+ void *handshake_page;
+ dma_addr_t handshake_page_phys;
+
+ unsigned int global_isr;
+ unsigned int isr_status;
+
+ unsigned short max_sge;
+ unsigned short max_target_id;
+ unsigned char *target_map;
+ unsigned int max_io;
+ unsigned int list_num_io;
+ unsigned int ib_max_size;
+ unsigned int ob_max_size;
+ unsigned int ib_max_size_setting;
+ unsigned int ob_max_size_setting;
+ unsigned int max_transfer_size;
+ unsigned char hba_total_pages;
+ unsigned char fw_flag;
+ unsigned char request_id_enabled;
+ unsigned char eot_flag;
+ unsigned short hba_capability;
+ unsigned short io_seq;
+
+ unsigned int ib_cur_slot;
+ unsigned int ob_cur_slot;
+ unsigned int fw_state;
+ struct mutex sas_discovery_mutex;
+
+ struct list_head ob_data_list;
+ struct list_head free_ob_list;
+ struct list_head res_list;
+ struct list_head waiting_req_list;
+
+ struct mvumi_tag tag_pool;
+ struct mvumi_cmd **tag_cmd;
+ struct mvumi_hw_regs *regs;
+ struct mutex device_lock;
+ struct list_head mhba_dev_list;
+ struct list_head shost_dev_list;
+ struct task_struct *dm_thread;
+ atomic_t pnp_count;
+};
+
+struct mvumi_instance_template {
+ void (*fire_cmd) (struct mvumi_hba *, struct mvumi_cmd *);
+ void (*enable_intr) (struct mvumi_hba *);
+ void (*disable_intr) (struct mvumi_hba *);
+ int (*clear_intr) (void *);
+ unsigned int (*read_fw_status_reg) (struct mvumi_hba *);
+ unsigned int (*check_ib_list) (struct mvumi_hba *);
+ int (*check_ob_list) (struct mvumi_hba *, unsigned int *,
+ unsigned int *);
+ int (*reset_host) (struct mvumi_hba *);
+};
+
+extern struct timezone sys_tz;
+#endif