162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _SBP_BASE_H 362306a36Sopenharmony_ci#define _SBP_BASE_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/firewire.h> 662306a36Sopenharmony_ci#include <linux/spinlock.h> 762306a36Sopenharmony_ci#include <linux/types.h> 862306a36Sopenharmony_ci#include <linux/workqueue.h> 962306a36Sopenharmony_ci#include <target/target_core_base.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define SBP_VERSION "v0.1" 1262306a36Sopenharmony_ci#define SBP_NAMELEN 32 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define SBP_ORB_FETCH_SIZE 8 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define MANAGEMENT_AGENT_STATE_IDLE 0 1762306a36Sopenharmony_ci#define MANAGEMENT_AGENT_STATE_BUSY 1 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define ORB_NOTIFY(v) (((v) >> 31) & 0x01) 2062306a36Sopenharmony_ci#define ORB_REQUEST_FORMAT(v) (((v) >> 29) & 0x03) 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION(v) (((v) >> 16) & 0x0f) 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_LOGIN 0x0 2562306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_QUERY_LOGINS 0x1 2662306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_RECONNECT 0x3 2762306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_SET_PASSWORD 0x4 2862306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_LOGOUT 0x7 2962306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_ABORT_TASK 0xb 3062306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_ABORT_TASK_SET 0xc 3162306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_LOGICAL_UNIT_RESET 0xe 3262306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_TARGET_RESET 0xf 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define LOGIN_ORB_EXCLUSIVE(v) (((v) >> 28) & 0x01) 3562306a36Sopenharmony_ci#define LOGIN_ORB_RESERVED(v) (((v) >> 24) & 0x0f) 3662306a36Sopenharmony_ci#define LOGIN_ORB_RECONNECT(v) (((v) >> 20) & 0x0f) 3762306a36Sopenharmony_ci#define LOGIN_ORB_LUN(v) (((v) >> 0) & 0xffff) 3862306a36Sopenharmony_ci#define LOGIN_ORB_PASSWORD_LENGTH(v) (((v) >> 16) & 0xffff) 3962306a36Sopenharmony_ci#define LOGIN_ORB_RESPONSE_LENGTH(v) (((v) >> 0) & 0xffff) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define RECONNECT_ORB_LOGIN_ID(v) (((v) >> 0) & 0xffff) 4262306a36Sopenharmony_ci#define LOGOUT_ORB_LOGIN_ID(v) (((v) >> 0) & 0xffff) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define CMDBLK_ORB_DIRECTION(v) (((v) >> 27) & 0x01) 4562306a36Sopenharmony_ci#define CMDBLK_ORB_SPEED(v) (((v) >> 24) & 0x07) 4662306a36Sopenharmony_ci#define CMDBLK_ORB_MAX_PAYLOAD(v) (((v) >> 20) & 0x0f) 4762306a36Sopenharmony_ci#define CMDBLK_ORB_PG_TBL_PRESENT(v) (((v) >> 19) & 0x01) 4862306a36Sopenharmony_ci#define CMDBLK_ORB_PG_SIZE(v) (((v) >> 16) & 0x07) 4962306a36Sopenharmony_ci#define CMDBLK_ORB_DATA_SIZE(v) (((v) >> 0) & 0xffff) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define STATUS_BLOCK_SRC(v) (((v) & 0x03) << 30) 5262306a36Sopenharmony_ci#define STATUS_BLOCK_RESP(v) (((v) & 0x03) << 28) 5362306a36Sopenharmony_ci#define STATUS_BLOCK_DEAD(v) (((v) ? 1 : 0) << 27) 5462306a36Sopenharmony_ci#define STATUS_BLOCK_LEN(v) (((v) & 0x07) << 24) 5562306a36Sopenharmony_ci#define STATUS_BLOCK_SBP_STATUS(v) (((v) & 0xff) << 16) 5662306a36Sopenharmony_ci#define STATUS_BLOCK_ORB_OFFSET_HIGH(v) (((v) & 0xffff) << 0) 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define STATUS_SRC_ORB_CONTINUING 0 5962306a36Sopenharmony_ci#define STATUS_SRC_ORB_FINISHED 1 6062306a36Sopenharmony_ci#define STATUS_SRC_UNSOLICITED 2 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define STATUS_RESP_REQUEST_COMPLETE 0 6362306a36Sopenharmony_ci#define STATUS_RESP_TRANSPORT_FAILURE 1 6462306a36Sopenharmony_ci#define STATUS_RESP_ILLEGAL_REQUEST 2 6562306a36Sopenharmony_ci#define STATUS_RESP_VENDOR_DEPENDENT 3 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define SBP_STATUS_OK 0 6862306a36Sopenharmony_ci#define SBP_STATUS_REQ_TYPE_NOTSUPP 1 6962306a36Sopenharmony_ci#define SBP_STATUS_SPEED_NOTSUPP 2 7062306a36Sopenharmony_ci#define SBP_STATUS_PAGE_SIZE_NOTSUPP 3 7162306a36Sopenharmony_ci#define SBP_STATUS_ACCESS_DENIED 4 7262306a36Sopenharmony_ci#define SBP_STATUS_LUN_NOTSUPP 5 7362306a36Sopenharmony_ci#define SBP_STATUS_PAYLOAD_TOO_SMALL 6 7462306a36Sopenharmony_ci/* 7 is reserved */ 7562306a36Sopenharmony_ci#define SBP_STATUS_RESOURCES_UNAVAIL 8 7662306a36Sopenharmony_ci#define SBP_STATUS_FUNCTION_REJECTED 9 7762306a36Sopenharmony_ci#define SBP_STATUS_LOGIN_ID_UNKNOWN 10 7862306a36Sopenharmony_ci#define SBP_STATUS_DUMMY_ORB_COMPLETE 11 7962306a36Sopenharmony_ci#define SBP_STATUS_REQUEST_ABORTED 12 8062306a36Sopenharmony_ci#define SBP_STATUS_UNSPECIFIED_ERROR 0xff 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#define AGENT_STATE_RESET 0 8362306a36Sopenharmony_ci#define AGENT_STATE_ACTIVE 1 8462306a36Sopenharmony_ci#define AGENT_STATE_SUSPENDED 2 8562306a36Sopenharmony_ci#define AGENT_STATE_DEAD 3 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistruct sbp2_pointer { 8862306a36Sopenharmony_ci __be32 high; 8962306a36Sopenharmony_ci __be32 low; 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistruct sbp_command_block_orb { 9362306a36Sopenharmony_ci struct sbp2_pointer next_orb; 9462306a36Sopenharmony_ci struct sbp2_pointer data_descriptor; 9562306a36Sopenharmony_ci __be32 misc; 9662306a36Sopenharmony_ci u8 command_block[12]; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistruct sbp_page_table_entry { 10062306a36Sopenharmony_ci __be16 segment_length; 10162306a36Sopenharmony_ci __be16 segment_base_hi; 10262306a36Sopenharmony_ci __be32 segment_base_lo; 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistruct sbp_management_orb { 10662306a36Sopenharmony_ci struct sbp2_pointer ptr1; 10762306a36Sopenharmony_ci struct sbp2_pointer ptr2; 10862306a36Sopenharmony_ci __be32 misc; 10962306a36Sopenharmony_ci __be32 length; 11062306a36Sopenharmony_ci struct sbp2_pointer status_fifo; 11162306a36Sopenharmony_ci}; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistruct sbp_status_block { 11462306a36Sopenharmony_ci __be32 status; 11562306a36Sopenharmony_ci __be32 orb_low; 11662306a36Sopenharmony_ci u8 data[24]; 11762306a36Sopenharmony_ci}; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistruct sbp_login_response_block { 12062306a36Sopenharmony_ci __be32 misc; 12162306a36Sopenharmony_ci struct sbp2_pointer command_block_agent; 12262306a36Sopenharmony_ci __be32 reconnect_hold; 12362306a36Sopenharmony_ci}; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistruct sbp_login_descriptor { 12662306a36Sopenharmony_ci struct sbp_session *sess; 12762306a36Sopenharmony_ci struct list_head link; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci u32 login_lun; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci u64 status_fifo_addr; 13262306a36Sopenharmony_ci int exclusive; 13362306a36Sopenharmony_ci u16 login_id; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci struct sbp_target_agent *tgt_agt; 13662306a36Sopenharmony_ci}; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistruct sbp_session { 13962306a36Sopenharmony_ci spinlock_t lock; 14062306a36Sopenharmony_ci struct se_session *se_sess; 14162306a36Sopenharmony_ci struct list_head login_list; 14262306a36Sopenharmony_ci struct delayed_work maint_work; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci u64 guid; /* login_owner_EUI_64 */ 14562306a36Sopenharmony_ci int node_id; /* login_owner_ID */ 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci struct fw_card *card; 14862306a36Sopenharmony_ci int generation; 14962306a36Sopenharmony_ci int speed; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci int reconnect_hold; 15262306a36Sopenharmony_ci u64 reconnect_expires; 15362306a36Sopenharmony_ci}; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistruct sbp_tpg { 15662306a36Sopenharmony_ci /* Target portal group tag for TCM */ 15762306a36Sopenharmony_ci u16 tport_tpgt; 15862306a36Sopenharmony_ci /* Pointer back to sbp_tport */ 15962306a36Sopenharmony_ci struct sbp_tport *tport; 16062306a36Sopenharmony_ci /* Returned by sbp_make_tpg() */ 16162306a36Sopenharmony_ci struct se_portal_group se_tpg; 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistruct sbp_tport { 16562306a36Sopenharmony_ci /* Target Unit Identifier (EUI-64) */ 16662306a36Sopenharmony_ci u64 guid; 16762306a36Sopenharmony_ci /* Target port name */ 16862306a36Sopenharmony_ci char tport_name[SBP_NAMELEN]; 16962306a36Sopenharmony_ci /* Returned by sbp_make_tport() */ 17062306a36Sopenharmony_ci struct se_wwn tport_wwn; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci struct sbp_tpg *tpg; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* FireWire unit directory */ 17562306a36Sopenharmony_ci struct fw_descriptor unit_directory; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* SBP Management Agent */ 17862306a36Sopenharmony_ci struct sbp_management_agent *mgt_agt; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci /* Parameters */ 18162306a36Sopenharmony_ci int enable; 18262306a36Sopenharmony_ci s32 directory_id; 18362306a36Sopenharmony_ci int mgt_orb_timeout; 18462306a36Sopenharmony_ci int max_reconnect_timeout; 18562306a36Sopenharmony_ci int max_logins_per_lun; 18662306a36Sopenharmony_ci}; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic inline u64 sbp2_pointer_to_addr(const struct sbp2_pointer *ptr) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci return (u64)(be32_to_cpu(ptr->high) & 0x0000ffff) << 32 | 19162306a36Sopenharmony_ci (be32_to_cpu(ptr->low) & 0xfffffffc); 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic inline void addr_to_sbp2_pointer(u64 addr, struct sbp2_pointer *ptr) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci ptr->high = cpu_to_be32(addr >> 32); 19762306a36Sopenharmony_ci ptr->low = cpu_to_be32(addr); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistruct sbp_target_agent { 20162306a36Sopenharmony_ci spinlock_t lock; 20262306a36Sopenharmony_ci struct fw_address_handler handler; 20362306a36Sopenharmony_ci struct sbp_login_descriptor *login; 20462306a36Sopenharmony_ci int state; 20562306a36Sopenharmony_ci struct work_struct work; 20662306a36Sopenharmony_ci u64 orb_pointer; 20762306a36Sopenharmony_ci bool doorbell; 20862306a36Sopenharmony_ci}; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistruct sbp_target_request { 21162306a36Sopenharmony_ci struct sbp_login_descriptor *login; 21262306a36Sopenharmony_ci u64 orb_pointer; 21362306a36Sopenharmony_ci struct sbp_command_block_orb orb; 21462306a36Sopenharmony_ci struct sbp_status_block status; 21562306a36Sopenharmony_ci struct work_struct work; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci struct se_cmd se_cmd; 21862306a36Sopenharmony_ci struct sbp_page_table_entry *pg_tbl; 21962306a36Sopenharmony_ci void *cmd_buf; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci unsigned char sense_buf[TRANSPORT_SENSE_BUFFER]; 22262306a36Sopenharmony_ci}; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistruct sbp_management_agent { 22562306a36Sopenharmony_ci spinlock_t lock; 22662306a36Sopenharmony_ci struct sbp_tport *tport; 22762306a36Sopenharmony_ci struct fw_address_handler handler; 22862306a36Sopenharmony_ci int state; 22962306a36Sopenharmony_ci struct work_struct work; 23062306a36Sopenharmony_ci u64 orb_offset; 23162306a36Sopenharmony_ci struct sbp_management_request *request; 23262306a36Sopenharmony_ci}; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistruct sbp_management_request { 23562306a36Sopenharmony_ci struct sbp_management_orb orb; 23662306a36Sopenharmony_ci struct sbp_status_block status; 23762306a36Sopenharmony_ci struct fw_card *card; 23862306a36Sopenharmony_ci int generation; 23962306a36Sopenharmony_ci int node_addr; 24062306a36Sopenharmony_ci int speed; 24162306a36Sopenharmony_ci}; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci#endif 244