18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _SBP_BASE_H
38c2ecf20Sopenharmony_ci#define _SBP_BASE_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/firewire.h>
68c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
78c2ecf20Sopenharmony_ci#include <linux/types.h>
88c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
98c2ecf20Sopenharmony_ci#include <target/target_core_base.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define SBP_VERSION  "v0.1"
128c2ecf20Sopenharmony_ci#define SBP_NAMELEN 32
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define SBP_ORB_FETCH_SIZE	8
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define MANAGEMENT_AGENT_STATE_IDLE	0
178c2ecf20Sopenharmony_ci#define MANAGEMENT_AGENT_STATE_BUSY	1
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define ORB_NOTIFY(v)			(((v) >> 31) & 0x01)
208c2ecf20Sopenharmony_ci#define ORB_REQUEST_FORMAT(v)		(((v) >> 29) & 0x03)
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION(v)	(((v) >> 16) & 0x0f)
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_LOGIN			0x0
258c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_QUERY_LOGINS		0x1
268c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_RECONNECT		0x3
278c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_SET_PASSWORD		0x4
288c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_LOGOUT			0x7
298c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_ABORT_TASK		0xb
308c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_ABORT_TASK_SET		0xc
318c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_LOGICAL_UNIT_RESET	0xe
328c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION_TARGET_RESET		0xf
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define LOGIN_ORB_EXCLUSIVE(v)		(((v) >> 28) &   0x01)
358c2ecf20Sopenharmony_ci#define LOGIN_ORB_RESERVED(v)		(((v) >> 24) &   0x0f)
368c2ecf20Sopenharmony_ci#define LOGIN_ORB_RECONNECT(v)		(((v) >> 20) &   0x0f)
378c2ecf20Sopenharmony_ci#define LOGIN_ORB_LUN(v)		(((v) >>  0) & 0xffff)
388c2ecf20Sopenharmony_ci#define LOGIN_ORB_PASSWORD_LENGTH(v)	(((v) >> 16) & 0xffff)
398c2ecf20Sopenharmony_ci#define LOGIN_ORB_RESPONSE_LENGTH(v)	(((v) >>  0) & 0xffff)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define RECONNECT_ORB_LOGIN_ID(v)	(((v) >>  0) & 0xffff)
428c2ecf20Sopenharmony_ci#define LOGOUT_ORB_LOGIN_ID(v)		(((v) >>  0) & 0xffff)
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#define CMDBLK_ORB_DIRECTION(v)		(((v) >> 27) &   0x01)
458c2ecf20Sopenharmony_ci#define CMDBLK_ORB_SPEED(v)		(((v) >> 24) &   0x07)
468c2ecf20Sopenharmony_ci#define CMDBLK_ORB_MAX_PAYLOAD(v)	(((v) >> 20) &   0x0f)
478c2ecf20Sopenharmony_ci#define CMDBLK_ORB_PG_TBL_PRESENT(v)	(((v) >> 19) &   0x01)
488c2ecf20Sopenharmony_ci#define CMDBLK_ORB_PG_SIZE(v)		(((v) >> 16) &   0x07)
498c2ecf20Sopenharmony_ci#define CMDBLK_ORB_DATA_SIZE(v)		(((v) >>  0) & 0xffff)
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define STATUS_BLOCK_SRC(v)		(((v) &   0x03) << 30)
528c2ecf20Sopenharmony_ci#define STATUS_BLOCK_RESP(v)		(((v) &   0x03) << 28)
538c2ecf20Sopenharmony_ci#define STATUS_BLOCK_DEAD(v)		(((v) ? 1 : 0)  << 27)
548c2ecf20Sopenharmony_ci#define STATUS_BLOCK_LEN(v)		(((v) &   0x07) << 24)
558c2ecf20Sopenharmony_ci#define STATUS_BLOCK_SBP_STATUS(v)	(((v) &   0xff) << 16)
568c2ecf20Sopenharmony_ci#define STATUS_BLOCK_ORB_OFFSET_HIGH(v)	(((v) & 0xffff) <<  0)
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#define STATUS_SRC_ORB_CONTINUING	0
598c2ecf20Sopenharmony_ci#define STATUS_SRC_ORB_FINISHED		1
608c2ecf20Sopenharmony_ci#define STATUS_SRC_UNSOLICITED		2
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define STATUS_RESP_REQUEST_COMPLETE	0
638c2ecf20Sopenharmony_ci#define STATUS_RESP_TRANSPORT_FAILURE	1
648c2ecf20Sopenharmony_ci#define STATUS_RESP_ILLEGAL_REQUEST	2
658c2ecf20Sopenharmony_ci#define STATUS_RESP_VENDOR_DEPENDENT	3
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#define SBP_STATUS_OK			0
688c2ecf20Sopenharmony_ci#define SBP_STATUS_REQ_TYPE_NOTSUPP	1
698c2ecf20Sopenharmony_ci#define SBP_STATUS_SPEED_NOTSUPP	2
708c2ecf20Sopenharmony_ci#define SBP_STATUS_PAGE_SIZE_NOTSUPP	3
718c2ecf20Sopenharmony_ci#define SBP_STATUS_ACCESS_DENIED	4
728c2ecf20Sopenharmony_ci#define SBP_STATUS_LUN_NOTSUPP		5
738c2ecf20Sopenharmony_ci#define SBP_STATUS_PAYLOAD_TOO_SMALL	6
748c2ecf20Sopenharmony_ci/* 7 is reserved */
758c2ecf20Sopenharmony_ci#define SBP_STATUS_RESOURCES_UNAVAIL	8
768c2ecf20Sopenharmony_ci#define SBP_STATUS_FUNCTION_REJECTED	9
778c2ecf20Sopenharmony_ci#define SBP_STATUS_LOGIN_ID_UNKNOWN	10
788c2ecf20Sopenharmony_ci#define SBP_STATUS_DUMMY_ORB_COMPLETE	11
798c2ecf20Sopenharmony_ci#define SBP_STATUS_REQUEST_ABORTED	12
808c2ecf20Sopenharmony_ci#define SBP_STATUS_UNSPECIFIED_ERROR	0xff
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci#define AGENT_STATE_RESET	0
838c2ecf20Sopenharmony_ci#define AGENT_STATE_ACTIVE	1
848c2ecf20Sopenharmony_ci#define AGENT_STATE_SUSPENDED	2
858c2ecf20Sopenharmony_ci#define AGENT_STATE_DEAD	3
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistruct sbp2_pointer {
888c2ecf20Sopenharmony_ci	__be32 high;
898c2ecf20Sopenharmony_ci	__be32 low;
908c2ecf20Sopenharmony_ci};
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistruct sbp_command_block_orb {
938c2ecf20Sopenharmony_ci	struct sbp2_pointer next_orb;
948c2ecf20Sopenharmony_ci	struct sbp2_pointer data_descriptor;
958c2ecf20Sopenharmony_ci	__be32 misc;
968c2ecf20Sopenharmony_ci	u8 command_block[12];
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistruct sbp_page_table_entry {
1008c2ecf20Sopenharmony_ci	__be16 segment_length;
1018c2ecf20Sopenharmony_ci	__be16 segment_base_hi;
1028c2ecf20Sopenharmony_ci	__be32 segment_base_lo;
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistruct sbp_management_orb {
1068c2ecf20Sopenharmony_ci	struct sbp2_pointer ptr1;
1078c2ecf20Sopenharmony_ci	struct sbp2_pointer ptr2;
1088c2ecf20Sopenharmony_ci	__be32 misc;
1098c2ecf20Sopenharmony_ci	__be32 length;
1108c2ecf20Sopenharmony_ci	struct sbp2_pointer status_fifo;
1118c2ecf20Sopenharmony_ci};
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistruct sbp_status_block {
1148c2ecf20Sopenharmony_ci	__be32 status;
1158c2ecf20Sopenharmony_ci	__be32 orb_low;
1168c2ecf20Sopenharmony_ci	u8 data[24];
1178c2ecf20Sopenharmony_ci};
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistruct sbp_login_response_block {
1208c2ecf20Sopenharmony_ci	__be32 misc;
1218c2ecf20Sopenharmony_ci	struct sbp2_pointer command_block_agent;
1228c2ecf20Sopenharmony_ci	__be32 reconnect_hold;
1238c2ecf20Sopenharmony_ci};
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistruct sbp_login_descriptor {
1268c2ecf20Sopenharmony_ci	struct sbp_session *sess;
1278c2ecf20Sopenharmony_ci	struct list_head link;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	u32 login_lun;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	u64 status_fifo_addr;
1328c2ecf20Sopenharmony_ci	int exclusive;
1338c2ecf20Sopenharmony_ci	u16 login_id;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	struct sbp_target_agent *tgt_agt;
1368c2ecf20Sopenharmony_ci};
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistruct sbp_session {
1398c2ecf20Sopenharmony_ci	spinlock_t lock;
1408c2ecf20Sopenharmony_ci	struct se_session *se_sess;
1418c2ecf20Sopenharmony_ci	struct list_head login_list;
1428c2ecf20Sopenharmony_ci	struct delayed_work maint_work;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	u64 guid; /* login_owner_EUI_64 */
1458c2ecf20Sopenharmony_ci	int node_id; /* login_owner_ID */
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	struct fw_card *card;
1488c2ecf20Sopenharmony_ci	int generation;
1498c2ecf20Sopenharmony_ci	int speed;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	int reconnect_hold;
1528c2ecf20Sopenharmony_ci	u64 reconnect_expires;
1538c2ecf20Sopenharmony_ci};
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistruct sbp_tpg {
1568c2ecf20Sopenharmony_ci	/* Target portal group tag for TCM */
1578c2ecf20Sopenharmony_ci	u16 tport_tpgt;
1588c2ecf20Sopenharmony_ci	/* Pointer back to sbp_tport */
1598c2ecf20Sopenharmony_ci	struct sbp_tport *tport;
1608c2ecf20Sopenharmony_ci	/* Returned by sbp_make_tpg() */
1618c2ecf20Sopenharmony_ci	struct se_portal_group se_tpg;
1628c2ecf20Sopenharmony_ci};
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistruct sbp_tport {
1658c2ecf20Sopenharmony_ci	/* Target Unit Identifier (EUI-64) */
1668c2ecf20Sopenharmony_ci	u64 guid;
1678c2ecf20Sopenharmony_ci	/* Target port name */
1688c2ecf20Sopenharmony_ci	char tport_name[SBP_NAMELEN];
1698c2ecf20Sopenharmony_ci	/* Returned by sbp_make_tport() */
1708c2ecf20Sopenharmony_ci	struct se_wwn tport_wwn;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	struct sbp_tpg *tpg;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	/* FireWire unit directory */
1758c2ecf20Sopenharmony_ci	struct fw_descriptor unit_directory;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	/* SBP Management Agent */
1788c2ecf20Sopenharmony_ci	struct sbp_management_agent *mgt_agt;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	/* Parameters */
1818c2ecf20Sopenharmony_ci	int enable;
1828c2ecf20Sopenharmony_ci	s32 directory_id;
1838c2ecf20Sopenharmony_ci	int mgt_orb_timeout;
1848c2ecf20Sopenharmony_ci	int max_reconnect_timeout;
1858c2ecf20Sopenharmony_ci	int max_logins_per_lun;
1868c2ecf20Sopenharmony_ci};
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_cistatic inline u64 sbp2_pointer_to_addr(const struct sbp2_pointer *ptr)
1898c2ecf20Sopenharmony_ci{
1908c2ecf20Sopenharmony_ci	return (u64)(be32_to_cpu(ptr->high) & 0x0000ffff) << 32 |
1918c2ecf20Sopenharmony_ci		(be32_to_cpu(ptr->low) & 0xfffffffc);
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic inline void addr_to_sbp2_pointer(u64 addr, struct sbp2_pointer *ptr)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	ptr->high = cpu_to_be32(addr >> 32);
1978c2ecf20Sopenharmony_ci	ptr->low = cpu_to_be32(addr);
1988c2ecf20Sopenharmony_ci}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistruct sbp_target_agent {
2018c2ecf20Sopenharmony_ci	spinlock_t lock;
2028c2ecf20Sopenharmony_ci	struct fw_address_handler handler;
2038c2ecf20Sopenharmony_ci	struct sbp_login_descriptor *login;
2048c2ecf20Sopenharmony_ci	int state;
2058c2ecf20Sopenharmony_ci	struct work_struct work;
2068c2ecf20Sopenharmony_ci	u64 orb_pointer;
2078c2ecf20Sopenharmony_ci	bool doorbell;
2088c2ecf20Sopenharmony_ci};
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistruct sbp_target_request {
2118c2ecf20Sopenharmony_ci	struct sbp_login_descriptor *login;
2128c2ecf20Sopenharmony_ci	u64 orb_pointer;
2138c2ecf20Sopenharmony_ci	struct sbp_command_block_orb orb;
2148c2ecf20Sopenharmony_ci	struct sbp_status_block status;
2158c2ecf20Sopenharmony_ci	struct work_struct work;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	struct se_cmd se_cmd;
2188c2ecf20Sopenharmony_ci	struct sbp_page_table_entry *pg_tbl;
2198c2ecf20Sopenharmony_ci	void *cmd_buf;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	unsigned char sense_buf[TRANSPORT_SENSE_BUFFER];
2228c2ecf20Sopenharmony_ci};
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistruct sbp_management_agent {
2258c2ecf20Sopenharmony_ci	spinlock_t lock;
2268c2ecf20Sopenharmony_ci	struct sbp_tport *tport;
2278c2ecf20Sopenharmony_ci	struct fw_address_handler handler;
2288c2ecf20Sopenharmony_ci	int state;
2298c2ecf20Sopenharmony_ci	struct work_struct work;
2308c2ecf20Sopenharmony_ci	u64 orb_offset;
2318c2ecf20Sopenharmony_ci	struct sbp_management_request *request;
2328c2ecf20Sopenharmony_ci};
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cistruct sbp_management_request {
2358c2ecf20Sopenharmony_ci	struct sbp_management_orb orb;
2368c2ecf20Sopenharmony_ci	struct sbp_status_block status;
2378c2ecf20Sopenharmony_ci	struct fw_card *card;
2388c2ecf20Sopenharmony_ci	int generation;
2398c2ecf20Sopenharmony_ci	int node_addr;
2408c2ecf20Sopenharmony_ci	int speed;
2418c2ecf20Sopenharmony_ci};
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci#endif
244