1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun #ifndef _SBP_BASE_H 3*4882a593Smuzhiyun #define _SBP_BASE_H 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun #include <linux/firewire.h> 6*4882a593Smuzhiyun #include <linux/spinlock.h> 7*4882a593Smuzhiyun #include <linux/types.h> 8*4882a593Smuzhiyun #include <linux/workqueue.h> 9*4882a593Smuzhiyun #include <target/target_core_base.h> 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun #define SBP_VERSION "v0.1" 12*4882a593Smuzhiyun #define SBP_NAMELEN 32 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun #define SBP_ORB_FETCH_SIZE 8 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun #define MANAGEMENT_AGENT_STATE_IDLE 0 17*4882a593Smuzhiyun #define MANAGEMENT_AGENT_STATE_BUSY 1 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun #define ORB_NOTIFY(v) (((v) >> 31) & 0x01) 20*4882a593Smuzhiyun #define ORB_REQUEST_FORMAT(v) (((v) >> 29) & 0x03) 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun #define MANAGEMENT_ORB_FUNCTION(v) (((v) >> 16) & 0x0f) 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun #define MANAGEMENT_ORB_FUNCTION_LOGIN 0x0 25*4882a593Smuzhiyun #define MANAGEMENT_ORB_FUNCTION_QUERY_LOGINS 0x1 26*4882a593Smuzhiyun #define MANAGEMENT_ORB_FUNCTION_RECONNECT 0x3 27*4882a593Smuzhiyun #define MANAGEMENT_ORB_FUNCTION_SET_PASSWORD 0x4 28*4882a593Smuzhiyun #define MANAGEMENT_ORB_FUNCTION_LOGOUT 0x7 29*4882a593Smuzhiyun #define MANAGEMENT_ORB_FUNCTION_ABORT_TASK 0xb 30*4882a593Smuzhiyun #define MANAGEMENT_ORB_FUNCTION_ABORT_TASK_SET 0xc 31*4882a593Smuzhiyun #define MANAGEMENT_ORB_FUNCTION_LOGICAL_UNIT_RESET 0xe 32*4882a593Smuzhiyun #define MANAGEMENT_ORB_FUNCTION_TARGET_RESET 0xf 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun #define LOGIN_ORB_EXCLUSIVE(v) (((v) >> 28) & 0x01) 35*4882a593Smuzhiyun #define LOGIN_ORB_RESERVED(v) (((v) >> 24) & 0x0f) 36*4882a593Smuzhiyun #define LOGIN_ORB_RECONNECT(v) (((v) >> 20) & 0x0f) 37*4882a593Smuzhiyun #define LOGIN_ORB_LUN(v) (((v) >> 0) & 0xffff) 38*4882a593Smuzhiyun #define LOGIN_ORB_PASSWORD_LENGTH(v) (((v) >> 16) & 0xffff) 39*4882a593Smuzhiyun #define LOGIN_ORB_RESPONSE_LENGTH(v) (((v) >> 0) & 0xffff) 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun #define RECONNECT_ORB_LOGIN_ID(v) (((v) >> 0) & 0xffff) 42*4882a593Smuzhiyun #define LOGOUT_ORB_LOGIN_ID(v) (((v) >> 0) & 0xffff) 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun #define CMDBLK_ORB_DIRECTION(v) (((v) >> 27) & 0x01) 45*4882a593Smuzhiyun #define CMDBLK_ORB_SPEED(v) (((v) >> 24) & 0x07) 46*4882a593Smuzhiyun #define CMDBLK_ORB_MAX_PAYLOAD(v) (((v) >> 20) & 0x0f) 47*4882a593Smuzhiyun #define CMDBLK_ORB_PG_TBL_PRESENT(v) (((v) >> 19) & 0x01) 48*4882a593Smuzhiyun #define CMDBLK_ORB_PG_SIZE(v) (((v) >> 16) & 0x07) 49*4882a593Smuzhiyun #define CMDBLK_ORB_DATA_SIZE(v) (((v) >> 0) & 0xffff) 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun #define STATUS_BLOCK_SRC(v) (((v) & 0x03) << 30) 52*4882a593Smuzhiyun #define STATUS_BLOCK_RESP(v) (((v) & 0x03) << 28) 53*4882a593Smuzhiyun #define STATUS_BLOCK_DEAD(v) (((v) ? 1 : 0) << 27) 54*4882a593Smuzhiyun #define STATUS_BLOCK_LEN(v) (((v) & 0x07) << 24) 55*4882a593Smuzhiyun #define STATUS_BLOCK_SBP_STATUS(v) (((v) & 0xff) << 16) 56*4882a593Smuzhiyun #define STATUS_BLOCK_ORB_OFFSET_HIGH(v) (((v) & 0xffff) << 0) 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun #define STATUS_SRC_ORB_CONTINUING 0 59*4882a593Smuzhiyun #define STATUS_SRC_ORB_FINISHED 1 60*4882a593Smuzhiyun #define STATUS_SRC_UNSOLICITED 2 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun #define STATUS_RESP_REQUEST_COMPLETE 0 63*4882a593Smuzhiyun #define STATUS_RESP_TRANSPORT_FAILURE 1 64*4882a593Smuzhiyun #define STATUS_RESP_ILLEGAL_REQUEST 2 65*4882a593Smuzhiyun #define STATUS_RESP_VENDOR_DEPENDENT 3 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun #define SBP_STATUS_OK 0 68*4882a593Smuzhiyun #define SBP_STATUS_REQ_TYPE_NOTSUPP 1 69*4882a593Smuzhiyun #define SBP_STATUS_SPEED_NOTSUPP 2 70*4882a593Smuzhiyun #define SBP_STATUS_PAGE_SIZE_NOTSUPP 3 71*4882a593Smuzhiyun #define SBP_STATUS_ACCESS_DENIED 4 72*4882a593Smuzhiyun #define SBP_STATUS_LUN_NOTSUPP 5 73*4882a593Smuzhiyun #define SBP_STATUS_PAYLOAD_TOO_SMALL 6 74*4882a593Smuzhiyun /* 7 is reserved */ 75*4882a593Smuzhiyun #define SBP_STATUS_RESOURCES_UNAVAIL 8 76*4882a593Smuzhiyun #define SBP_STATUS_FUNCTION_REJECTED 9 77*4882a593Smuzhiyun #define SBP_STATUS_LOGIN_ID_UNKNOWN 10 78*4882a593Smuzhiyun #define SBP_STATUS_DUMMY_ORB_COMPLETE 11 79*4882a593Smuzhiyun #define SBP_STATUS_REQUEST_ABORTED 12 80*4882a593Smuzhiyun #define SBP_STATUS_UNSPECIFIED_ERROR 0xff 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun #define AGENT_STATE_RESET 0 83*4882a593Smuzhiyun #define AGENT_STATE_ACTIVE 1 84*4882a593Smuzhiyun #define AGENT_STATE_SUSPENDED 2 85*4882a593Smuzhiyun #define AGENT_STATE_DEAD 3 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun struct sbp2_pointer { 88*4882a593Smuzhiyun __be32 high; 89*4882a593Smuzhiyun __be32 low; 90*4882a593Smuzhiyun }; 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun struct sbp_command_block_orb { 93*4882a593Smuzhiyun struct sbp2_pointer next_orb; 94*4882a593Smuzhiyun struct sbp2_pointer data_descriptor; 95*4882a593Smuzhiyun __be32 misc; 96*4882a593Smuzhiyun u8 command_block[12]; 97*4882a593Smuzhiyun }; 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun struct sbp_page_table_entry { 100*4882a593Smuzhiyun __be16 segment_length; 101*4882a593Smuzhiyun __be16 segment_base_hi; 102*4882a593Smuzhiyun __be32 segment_base_lo; 103*4882a593Smuzhiyun }; 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun struct sbp_management_orb { 106*4882a593Smuzhiyun struct sbp2_pointer ptr1; 107*4882a593Smuzhiyun struct sbp2_pointer ptr2; 108*4882a593Smuzhiyun __be32 misc; 109*4882a593Smuzhiyun __be32 length; 110*4882a593Smuzhiyun struct sbp2_pointer status_fifo; 111*4882a593Smuzhiyun }; 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun struct sbp_status_block { 114*4882a593Smuzhiyun __be32 status; 115*4882a593Smuzhiyun __be32 orb_low; 116*4882a593Smuzhiyun u8 data[24]; 117*4882a593Smuzhiyun }; 118*4882a593Smuzhiyun 119*4882a593Smuzhiyun struct sbp_login_response_block { 120*4882a593Smuzhiyun __be32 misc; 121*4882a593Smuzhiyun struct sbp2_pointer command_block_agent; 122*4882a593Smuzhiyun __be32 reconnect_hold; 123*4882a593Smuzhiyun }; 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun struct sbp_login_descriptor { 126*4882a593Smuzhiyun struct sbp_session *sess; 127*4882a593Smuzhiyun struct list_head link; 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun u32 login_lun; 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun u64 status_fifo_addr; 132*4882a593Smuzhiyun int exclusive; 133*4882a593Smuzhiyun u16 login_id; 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun struct sbp_target_agent *tgt_agt; 136*4882a593Smuzhiyun }; 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun struct sbp_session { 139*4882a593Smuzhiyun spinlock_t lock; 140*4882a593Smuzhiyun struct se_session *se_sess; 141*4882a593Smuzhiyun struct list_head login_list; 142*4882a593Smuzhiyun struct delayed_work maint_work; 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun u64 guid; /* login_owner_EUI_64 */ 145*4882a593Smuzhiyun int node_id; /* login_owner_ID */ 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun struct fw_card *card; 148*4882a593Smuzhiyun int generation; 149*4882a593Smuzhiyun int speed; 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun int reconnect_hold; 152*4882a593Smuzhiyun u64 reconnect_expires; 153*4882a593Smuzhiyun }; 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun struct sbp_tpg { 156*4882a593Smuzhiyun /* Target portal group tag for TCM */ 157*4882a593Smuzhiyun u16 tport_tpgt; 158*4882a593Smuzhiyun /* Pointer back to sbp_tport */ 159*4882a593Smuzhiyun struct sbp_tport *tport; 160*4882a593Smuzhiyun /* Returned by sbp_make_tpg() */ 161*4882a593Smuzhiyun struct se_portal_group se_tpg; 162*4882a593Smuzhiyun }; 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun struct sbp_tport { 165*4882a593Smuzhiyun /* Target Unit Identifier (EUI-64) */ 166*4882a593Smuzhiyun u64 guid; 167*4882a593Smuzhiyun /* Target port name */ 168*4882a593Smuzhiyun char tport_name[SBP_NAMELEN]; 169*4882a593Smuzhiyun /* Returned by sbp_make_tport() */ 170*4882a593Smuzhiyun struct se_wwn tport_wwn; 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun struct sbp_tpg *tpg; 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun /* FireWire unit directory */ 175*4882a593Smuzhiyun struct fw_descriptor unit_directory; 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun /* SBP Management Agent */ 178*4882a593Smuzhiyun struct sbp_management_agent *mgt_agt; 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun /* Parameters */ 181*4882a593Smuzhiyun int enable; 182*4882a593Smuzhiyun s32 directory_id; 183*4882a593Smuzhiyun int mgt_orb_timeout; 184*4882a593Smuzhiyun int max_reconnect_timeout; 185*4882a593Smuzhiyun int max_logins_per_lun; 186*4882a593Smuzhiyun }; 187*4882a593Smuzhiyun sbp2_pointer_to_addr(const struct sbp2_pointer * ptr)188*4882a593Smuzhiyunstatic inline u64 sbp2_pointer_to_addr(const struct sbp2_pointer *ptr) 189*4882a593Smuzhiyun { 190*4882a593Smuzhiyun return (u64)(be32_to_cpu(ptr->high) & 0x0000ffff) << 32 | 191*4882a593Smuzhiyun (be32_to_cpu(ptr->low) & 0xfffffffc); 192*4882a593Smuzhiyun } 193*4882a593Smuzhiyun addr_to_sbp2_pointer(u64 addr,struct sbp2_pointer * ptr)194*4882a593Smuzhiyunstatic inline void addr_to_sbp2_pointer(u64 addr, struct sbp2_pointer *ptr) 195*4882a593Smuzhiyun { 196*4882a593Smuzhiyun ptr->high = cpu_to_be32(addr >> 32); 197*4882a593Smuzhiyun ptr->low = cpu_to_be32(addr); 198*4882a593Smuzhiyun } 199*4882a593Smuzhiyun 200*4882a593Smuzhiyun struct sbp_target_agent { 201*4882a593Smuzhiyun spinlock_t lock; 202*4882a593Smuzhiyun struct fw_address_handler handler; 203*4882a593Smuzhiyun struct sbp_login_descriptor *login; 204*4882a593Smuzhiyun int state; 205*4882a593Smuzhiyun struct work_struct work; 206*4882a593Smuzhiyun u64 orb_pointer; 207*4882a593Smuzhiyun bool doorbell; 208*4882a593Smuzhiyun }; 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun struct sbp_target_request { 211*4882a593Smuzhiyun struct sbp_login_descriptor *login; 212*4882a593Smuzhiyun u64 orb_pointer; 213*4882a593Smuzhiyun struct sbp_command_block_orb orb; 214*4882a593Smuzhiyun struct sbp_status_block status; 215*4882a593Smuzhiyun struct work_struct work; 216*4882a593Smuzhiyun 217*4882a593Smuzhiyun struct se_cmd se_cmd; 218*4882a593Smuzhiyun struct sbp_page_table_entry *pg_tbl; 219*4882a593Smuzhiyun void *cmd_buf; 220*4882a593Smuzhiyun 221*4882a593Smuzhiyun unsigned char sense_buf[TRANSPORT_SENSE_BUFFER]; 222*4882a593Smuzhiyun }; 223*4882a593Smuzhiyun 224*4882a593Smuzhiyun struct sbp_management_agent { 225*4882a593Smuzhiyun spinlock_t lock; 226*4882a593Smuzhiyun struct sbp_tport *tport; 227*4882a593Smuzhiyun struct fw_address_handler handler; 228*4882a593Smuzhiyun int state; 229*4882a593Smuzhiyun struct work_struct work; 230*4882a593Smuzhiyun u64 orb_offset; 231*4882a593Smuzhiyun struct sbp_management_request *request; 232*4882a593Smuzhiyun }; 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun struct sbp_management_request { 235*4882a593Smuzhiyun struct sbp_management_orb orb; 236*4882a593Smuzhiyun struct sbp_status_block status; 237*4882a593Smuzhiyun struct fw_card *card; 238*4882a593Smuzhiyun int generation; 239*4882a593Smuzhiyun int node_addr; 240*4882a593Smuzhiyun int speed; 241*4882a593Smuzhiyun }; 242*4882a593Smuzhiyun 243*4882a593Smuzhiyun #endif 244