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