162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*lcs.h*/
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/interrupt.h>
562306a36Sopenharmony_ci#include <linux/netdevice.h>
662306a36Sopenharmony_ci#include <linux/skbuff.h>
762306a36Sopenharmony_ci#include <linux/workqueue.h>
862306a36Sopenharmony_ci#include <linux/refcount.h>
962306a36Sopenharmony_ci#include <asm/ccwdev.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define LCS_DBF_TEXT(level, name, text) \
1262306a36Sopenharmony_ci	do { \
1362306a36Sopenharmony_ci		debug_text_event(lcs_dbf_##name, level, text); \
1462306a36Sopenharmony_ci	} while (0)
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define LCS_DBF_HEX(level,name,addr,len) \
1762306a36Sopenharmony_cido { \
1862306a36Sopenharmony_ci	debug_event(lcs_dbf_##name,level,(void*)(addr),len); \
1962306a36Sopenharmony_ci} while (0)
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define LCS_DBF_TEXT_(level,name,text...) \
2262306a36Sopenharmony_ci	do { \
2362306a36Sopenharmony_ci		if (debug_level_enabled(lcs_dbf_##name, level)) { \
2462306a36Sopenharmony_ci			scnprintf(debug_buffer, sizeof(debug_buffer), text); \
2562306a36Sopenharmony_ci			debug_text_event(lcs_dbf_##name, level, debug_buffer); \
2662306a36Sopenharmony_ci		} \
2762306a36Sopenharmony_ci	} while (0)
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/**
3062306a36Sopenharmony_ci *	sysfs related stuff
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci#define CARD_FROM_DEV(cdev) \
3362306a36Sopenharmony_ci	(struct lcs_card *) dev_get_drvdata( \
3462306a36Sopenharmony_ci		&((struct ccwgroup_device *)dev_get_drvdata(&cdev->dev))->dev);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci/**
3762306a36Sopenharmony_ci * Enum for classifying detected devices.
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_cienum lcs_channel_types {
4062306a36Sopenharmony_ci	/* Device is not a channel  */
4162306a36Sopenharmony_ci	lcs_channel_type_none,
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	/* Device is a 2216 channel */
4462306a36Sopenharmony_ci	lcs_channel_type_parallel,
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	/* Device is a 2216 channel */
4762306a36Sopenharmony_ci	lcs_channel_type_2216,
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	/* Device is a OSA2 card */
5062306a36Sopenharmony_ci	lcs_channel_type_osa2
5162306a36Sopenharmony_ci};
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/**
5462306a36Sopenharmony_ci * CCW commands used in this driver
5562306a36Sopenharmony_ci */
5662306a36Sopenharmony_ci#define LCS_CCW_WRITE		0x01
5762306a36Sopenharmony_ci#define LCS_CCW_READ		0x02
5862306a36Sopenharmony_ci#define LCS_CCW_TRANSFER	0x08
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/**
6162306a36Sopenharmony_ci * LCS device status primitives
6262306a36Sopenharmony_ci */
6362306a36Sopenharmony_ci#define LCS_CMD_STARTLAN	0x01
6462306a36Sopenharmony_ci#define LCS_CMD_STOPLAN		0x02
6562306a36Sopenharmony_ci#define LCS_CMD_LANSTAT		0x04
6662306a36Sopenharmony_ci#define LCS_CMD_STARTUP		0x07
6762306a36Sopenharmony_ci#define LCS_CMD_SHUTDOWN	0x08
6862306a36Sopenharmony_ci#define LCS_CMD_QIPASSIST	0xb2
6962306a36Sopenharmony_ci#define LCS_CMD_SETIPM		0xb4
7062306a36Sopenharmony_ci#define LCS_CMD_DELIPM		0xb5
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#define LCS_INITIATOR_TCPIP	0x00
7362306a36Sopenharmony_ci#define LCS_INITIATOR_LGW	0x01
7462306a36Sopenharmony_ci#define LCS_STD_CMD_SIZE	16
7562306a36Sopenharmony_ci#define LCS_MULTICAST_CMD_SIZE	404
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/**
7862306a36Sopenharmony_ci * LCS IPASSIST MASKS,only used when multicast is switched on
7962306a36Sopenharmony_ci */
8062306a36Sopenharmony_ci/* Not supported by LCS */
8162306a36Sopenharmony_ci#define LCS_IPASS_ARP_PROCESSING	0x0001
8262306a36Sopenharmony_ci#define LCS_IPASS_IN_CHECKSUM_SUPPORT	0x0002
8362306a36Sopenharmony_ci#define LCS_IPASS_OUT_CHECKSUM_SUPPORT	0x0004
8462306a36Sopenharmony_ci#define LCS_IPASS_IP_FRAG_REASSEMBLY	0x0008
8562306a36Sopenharmony_ci#define LCS_IPASS_IP_FILTERING		0x0010
8662306a36Sopenharmony_ci/* Supported by lcs 3172 */
8762306a36Sopenharmony_ci#define LCS_IPASS_IPV6_SUPPORT		0x0020
8862306a36Sopenharmony_ci#define LCS_IPASS_MULTICAST_SUPPORT	0x0040
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/**
9162306a36Sopenharmony_ci * LCS sense byte definitions
9262306a36Sopenharmony_ci */
9362306a36Sopenharmony_ci#define LCS_SENSE_BYTE_0 		0
9462306a36Sopenharmony_ci#define LCS_SENSE_BYTE_1 		1
9562306a36Sopenharmony_ci#define LCS_SENSE_BYTE_2 		2
9662306a36Sopenharmony_ci#define LCS_SENSE_BYTE_3 		3
9762306a36Sopenharmony_ci#define LCS_SENSE_INTERFACE_DISCONNECT	0x01
9862306a36Sopenharmony_ci#define LCS_SENSE_EQUIPMENT_CHECK	0x10
9962306a36Sopenharmony_ci#define LCS_SENSE_BUS_OUT_CHECK		0x20
10062306a36Sopenharmony_ci#define LCS_SENSE_INTERVENTION_REQUIRED 0x40
10162306a36Sopenharmony_ci#define LCS_SENSE_CMD_REJECT		0x80
10262306a36Sopenharmony_ci#define LCS_SENSE_RESETTING_EVENT	0x80
10362306a36Sopenharmony_ci#define LCS_SENSE_DEVICE_ONLINE		0x20
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/**
10662306a36Sopenharmony_ci * LCS packet type definitions
10762306a36Sopenharmony_ci */
10862306a36Sopenharmony_ci#define LCS_FRAME_TYPE_CONTROL		0
10962306a36Sopenharmony_ci#define LCS_FRAME_TYPE_ENET		1
11062306a36Sopenharmony_ci#define LCS_FRAME_TYPE_TR		2
11162306a36Sopenharmony_ci#define LCS_FRAME_TYPE_FDDI		7
11262306a36Sopenharmony_ci#define LCS_FRAME_TYPE_AUTO		-1
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/**
11562306a36Sopenharmony_ci * some more definitions,we will sort them later
11662306a36Sopenharmony_ci */
11762306a36Sopenharmony_ci#define LCS_ILLEGAL_OFFSET		0xffff
11862306a36Sopenharmony_ci#define LCS_IOBUFFERSIZE		0x5000
11962306a36Sopenharmony_ci#define LCS_NUM_BUFFS			32	/* needs to be power of 2 */
12062306a36Sopenharmony_ci#define LCS_MAC_LENGTH			6
12162306a36Sopenharmony_ci#define LCS_INVALID_PORT_NO		-1
12262306a36Sopenharmony_ci#define LCS_LANCMD_TIMEOUT_DEFAULT      5
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci/**
12562306a36Sopenharmony_ci * Multicast state
12662306a36Sopenharmony_ci */
12762306a36Sopenharmony_ci#define	 LCS_IPM_STATE_SET_REQUIRED	0
12862306a36Sopenharmony_ci#define	 LCS_IPM_STATE_DEL_REQUIRED	1
12962306a36Sopenharmony_ci#define	 LCS_IPM_STATE_ON_CARD		2
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci/**
13262306a36Sopenharmony_ci * LCS IP Assist declarations
13362306a36Sopenharmony_ci * seems to be only used for multicast
13462306a36Sopenharmony_ci */
13562306a36Sopenharmony_ci#define	 LCS_IPASS_ARP_PROCESSING	0x0001
13662306a36Sopenharmony_ci#define	 LCS_IPASS_INBOUND_CSUM_SUPP	0x0002
13762306a36Sopenharmony_ci#define	 LCS_IPASS_OUTBOUND_CSUM_SUPP	0x0004
13862306a36Sopenharmony_ci#define	 LCS_IPASS_IP_FRAG_REASSEMBLY	0x0008
13962306a36Sopenharmony_ci#define	 LCS_IPASS_IP_FILTERING		0x0010
14062306a36Sopenharmony_ci#define	 LCS_IPASS_IPV6_SUPPORT		0x0020
14162306a36Sopenharmony_ci#define	 LCS_IPASS_MULTICAST_SUPPORT	0x0040
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci/**
14462306a36Sopenharmony_ci * LCS Buffer states
14562306a36Sopenharmony_ci */
14662306a36Sopenharmony_cienum lcs_buffer_states {
14762306a36Sopenharmony_ci	LCS_BUF_STATE_EMPTY,	/* buffer is empty */
14862306a36Sopenharmony_ci	LCS_BUF_STATE_LOCKED,	/* buffer is locked, don't touch */
14962306a36Sopenharmony_ci	LCS_BUF_STATE_READY,	/* buffer is ready for read/write */
15062306a36Sopenharmony_ci	LCS_BUF_STATE_PROCESSED,
15162306a36Sopenharmony_ci};
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci/**
15462306a36Sopenharmony_ci * LCS Channel State Machine declarations
15562306a36Sopenharmony_ci */
15662306a36Sopenharmony_cienum lcs_channel_states {
15762306a36Sopenharmony_ci	LCS_CH_STATE_INIT,
15862306a36Sopenharmony_ci	LCS_CH_STATE_HALTED,
15962306a36Sopenharmony_ci	LCS_CH_STATE_STOPPED,
16062306a36Sopenharmony_ci	LCS_CH_STATE_RUNNING,
16162306a36Sopenharmony_ci	LCS_CH_STATE_SUSPENDED,
16262306a36Sopenharmony_ci	LCS_CH_STATE_CLEARED,
16362306a36Sopenharmony_ci	LCS_CH_STATE_ERROR,
16462306a36Sopenharmony_ci};
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci/**
16762306a36Sopenharmony_ci * LCS device state machine
16862306a36Sopenharmony_ci */
16962306a36Sopenharmony_cienum lcs_dev_states {
17062306a36Sopenharmony_ci	DEV_STATE_DOWN,
17162306a36Sopenharmony_ci	DEV_STATE_UP,
17262306a36Sopenharmony_ci	DEV_STATE_RECOVER,
17362306a36Sopenharmony_ci};
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cienum lcs_threads {
17662306a36Sopenharmony_ci	LCS_SET_MC_THREAD 	= 1,
17762306a36Sopenharmony_ci	LCS_RECOVERY_THREAD 	= 2,
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci/**
18162306a36Sopenharmony_ci * LCS struct declarations
18262306a36Sopenharmony_ci */
18362306a36Sopenharmony_cistruct lcs_header {
18462306a36Sopenharmony_ci	__u16  offset;
18562306a36Sopenharmony_ci	__u8   type;
18662306a36Sopenharmony_ci	__u8   slot;
18762306a36Sopenharmony_ci}  __attribute__ ((packed));
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistruct lcs_ip_mac_pair {
19062306a36Sopenharmony_ci	__be32  ip_addr;
19162306a36Sopenharmony_ci	__u8   mac_addr[LCS_MAC_LENGTH];
19262306a36Sopenharmony_ci	__u8   reserved[2];
19362306a36Sopenharmony_ci}  __attribute__ ((packed));
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistruct lcs_ipm_list {
19662306a36Sopenharmony_ci	struct list_head list;
19762306a36Sopenharmony_ci	struct lcs_ip_mac_pair ipm;
19862306a36Sopenharmony_ci	__u8 ipm_state;
19962306a36Sopenharmony_ci};
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistruct lcs_cmd {
20262306a36Sopenharmony_ci	__u16  offset;
20362306a36Sopenharmony_ci	__u8   type;
20462306a36Sopenharmony_ci	__u8   slot;
20562306a36Sopenharmony_ci	__u8   cmd_code;
20662306a36Sopenharmony_ci	__u8   initiator;
20762306a36Sopenharmony_ci	__u16  sequence_no;
20862306a36Sopenharmony_ci	__u16  return_code;
20962306a36Sopenharmony_ci	union {
21062306a36Sopenharmony_ci		struct {
21162306a36Sopenharmony_ci			__u8   lan_type;
21262306a36Sopenharmony_ci			__u8   portno;
21362306a36Sopenharmony_ci			__u16  parameter_count;
21462306a36Sopenharmony_ci			__u8   operator_flags[3];
21562306a36Sopenharmony_ci			__u8   reserved[3];
21662306a36Sopenharmony_ci		} lcs_std_cmd;
21762306a36Sopenharmony_ci		struct {
21862306a36Sopenharmony_ci			__u16  unused1;
21962306a36Sopenharmony_ci			__u16  buff_size;
22062306a36Sopenharmony_ci			__u8   unused2[6];
22162306a36Sopenharmony_ci		} lcs_startup;
22262306a36Sopenharmony_ci		struct {
22362306a36Sopenharmony_ci			__u8   lan_type;
22462306a36Sopenharmony_ci			__u8   portno;
22562306a36Sopenharmony_ci			__u8   unused[10];
22662306a36Sopenharmony_ci			__u8   mac_addr[LCS_MAC_LENGTH];
22762306a36Sopenharmony_ci			__u32  num_packets_deblocked;
22862306a36Sopenharmony_ci			__u32  num_packets_blocked;
22962306a36Sopenharmony_ci			__u32  num_packets_tx_on_lan;
23062306a36Sopenharmony_ci			__u32  num_tx_errors_detected;
23162306a36Sopenharmony_ci			__u32  num_tx_packets_disgarded;
23262306a36Sopenharmony_ci			__u32  num_packets_rx_from_lan;
23362306a36Sopenharmony_ci			__u32  num_rx_errors_detected;
23462306a36Sopenharmony_ci			__u32  num_rx_discarded_nobuffs_avail;
23562306a36Sopenharmony_ci			__u32  num_rx_packets_too_large;
23662306a36Sopenharmony_ci		} lcs_lanstat_cmd;
23762306a36Sopenharmony_ci#ifdef CONFIG_IP_MULTICAST
23862306a36Sopenharmony_ci		struct {
23962306a36Sopenharmony_ci			__u8   lan_type;
24062306a36Sopenharmony_ci			__u8   portno;
24162306a36Sopenharmony_ci			__u16  num_ip_pairs;
24262306a36Sopenharmony_ci			__u16  ip_assists_supported;
24362306a36Sopenharmony_ci			__u16  ip_assists_enabled;
24462306a36Sopenharmony_ci			__u16  version;
24562306a36Sopenharmony_ci			struct {
24662306a36Sopenharmony_ci				struct lcs_ip_mac_pair
24762306a36Sopenharmony_ci				ip_mac_pair[32];
24862306a36Sopenharmony_ci				__u32	  response_data;
24962306a36Sopenharmony_ci			} lcs_ipass_ctlmsg __attribute ((packed));
25062306a36Sopenharmony_ci		} lcs_qipassist __attribute__ ((packed));
25162306a36Sopenharmony_ci#endif /*CONFIG_IP_MULTICAST */
25262306a36Sopenharmony_ci	} cmd __attribute__ ((packed));
25362306a36Sopenharmony_ci}  __attribute__ ((packed));
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci/**
25662306a36Sopenharmony_ci * Forward declarations.
25762306a36Sopenharmony_ci */
25862306a36Sopenharmony_cistruct lcs_card;
25962306a36Sopenharmony_cistruct lcs_channel;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci/**
26262306a36Sopenharmony_ci * Definition of an lcs buffer.
26362306a36Sopenharmony_ci */
26462306a36Sopenharmony_cistruct lcs_buffer {
26562306a36Sopenharmony_ci	enum lcs_buffer_states state;
26662306a36Sopenharmony_ci	void *data;
26762306a36Sopenharmony_ci	int count;
26862306a36Sopenharmony_ci	/* Callback for completion notification. */
26962306a36Sopenharmony_ci	void (*callback)(struct lcs_channel *, struct lcs_buffer *);
27062306a36Sopenharmony_ci};
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cistruct lcs_reply {
27362306a36Sopenharmony_ci	struct list_head list;
27462306a36Sopenharmony_ci	__u16 sequence_no;
27562306a36Sopenharmony_ci	refcount_t refcnt;
27662306a36Sopenharmony_ci	/* Callback for completion notification. */
27762306a36Sopenharmony_ci	void (*callback)(struct lcs_card *, struct lcs_cmd *);
27862306a36Sopenharmony_ci	wait_queue_head_t wait_q;
27962306a36Sopenharmony_ci	struct lcs_card *card;
28062306a36Sopenharmony_ci	struct timer_list timer;
28162306a36Sopenharmony_ci	int received;
28262306a36Sopenharmony_ci	int rc;
28362306a36Sopenharmony_ci};
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci/**
28662306a36Sopenharmony_ci * Definition of an lcs channel
28762306a36Sopenharmony_ci */
28862306a36Sopenharmony_cistruct lcs_channel {
28962306a36Sopenharmony_ci	enum lcs_channel_states state;
29062306a36Sopenharmony_ci	struct ccw_device *ccwdev;
29162306a36Sopenharmony_ci	struct ccw1 ccws[LCS_NUM_BUFFS + 1];
29262306a36Sopenharmony_ci	wait_queue_head_t wait_q;
29362306a36Sopenharmony_ci	struct tasklet_struct irq_tasklet;
29462306a36Sopenharmony_ci	struct lcs_buffer iob[LCS_NUM_BUFFS];
29562306a36Sopenharmony_ci	int io_idx;
29662306a36Sopenharmony_ci	int buf_idx;
29762306a36Sopenharmony_ci};
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci/**
30162306a36Sopenharmony_ci * definition of the lcs card
30262306a36Sopenharmony_ci */
30362306a36Sopenharmony_cistruct lcs_card {
30462306a36Sopenharmony_ci	spinlock_t lock;
30562306a36Sopenharmony_ci	spinlock_t ipm_lock;
30662306a36Sopenharmony_ci	enum lcs_dev_states state;
30762306a36Sopenharmony_ci	struct net_device *dev;
30862306a36Sopenharmony_ci	struct net_device_stats stats;
30962306a36Sopenharmony_ci	__be16 (*lan_type_trans)(struct sk_buff *skb,
31062306a36Sopenharmony_ci					 struct net_device *dev);
31162306a36Sopenharmony_ci	struct ccwgroup_device *gdev;
31262306a36Sopenharmony_ci	struct lcs_channel read;
31362306a36Sopenharmony_ci	struct lcs_channel write;
31462306a36Sopenharmony_ci	struct lcs_buffer *tx_buffer;
31562306a36Sopenharmony_ci	int tx_emitted;
31662306a36Sopenharmony_ci	struct list_head lancmd_waiters;
31762306a36Sopenharmony_ci	int lancmd_timeout;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	struct work_struct kernel_thread_starter;
32062306a36Sopenharmony_ci	spinlock_t mask_lock;
32162306a36Sopenharmony_ci	unsigned long thread_start_mask;
32262306a36Sopenharmony_ci	unsigned long thread_running_mask;
32362306a36Sopenharmony_ci	unsigned long thread_allowed_mask;
32462306a36Sopenharmony_ci	wait_queue_head_t wait_q;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci#ifdef CONFIG_IP_MULTICAST
32762306a36Sopenharmony_ci	struct list_head ipm_list;
32862306a36Sopenharmony_ci#endif
32962306a36Sopenharmony_ci	__u8 mac[LCS_MAC_LENGTH];
33062306a36Sopenharmony_ci	__u16 ip_assists_supported;
33162306a36Sopenharmony_ci	__u16 ip_assists_enabled;
33262306a36Sopenharmony_ci	__s8 lan_type;
33362306a36Sopenharmony_ci	__u32 pkt_seq;
33462306a36Sopenharmony_ci	__u16 sequence_no;
33562306a36Sopenharmony_ci	__s16 portno;
33662306a36Sopenharmony_ci	/* Some info copied from probeinfo */
33762306a36Sopenharmony_ci	u8 device_forced;
33862306a36Sopenharmony_ci	u8 max_port_no;
33962306a36Sopenharmony_ci	u8 hint_port_no;
34062306a36Sopenharmony_ci	s16 port_protocol_no;
34162306a36Sopenharmony_ci}  __attribute__ ((aligned(8)));
34262306a36Sopenharmony_ci
343