18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *	Copyright IBM Corp. 2001, 2007
48c2ecf20Sopenharmony_ci *	Authors:	Fritz Elfert (felfert@millenux.com)
58c2ecf20Sopenharmony_ci *			Peter Tiedemann (ptiedem@de.ibm.com)
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef _CTCM_MAIN_H_
98c2ecf20Sopenharmony_ci#define _CTCM_MAIN_H_
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <asm/ccwdev.h>
128c2ecf20Sopenharmony_ci#include <asm/ccwgroup.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
158c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include "fsm.h"
188c2ecf20Sopenharmony_ci#include "ctcm_dbug.h"
198c2ecf20Sopenharmony_ci#include "ctcm_mpc.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#define CTC_DRIVER_NAME	"ctcm"
228c2ecf20Sopenharmony_ci#define CTC_DEVICE_NAME	"ctc"
238c2ecf20Sopenharmony_ci#define MPC_DEVICE_NAME	"mpc"
248c2ecf20Sopenharmony_ci#define CTC_DEVICE_GENE CTC_DEVICE_NAME "%d"
258c2ecf20Sopenharmony_ci#define MPC_DEVICE_GENE	MPC_DEVICE_NAME "%d"
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#define CHANNEL_FLAGS_READ	0
288c2ecf20Sopenharmony_ci#define CHANNEL_FLAGS_WRITE	1
298c2ecf20Sopenharmony_ci#define CHANNEL_FLAGS_INUSE	2
308c2ecf20Sopenharmony_ci#define CHANNEL_FLAGS_BUFSIZE_CHANGED	4
318c2ecf20Sopenharmony_ci#define CHANNEL_FLAGS_FAILED	8
328c2ecf20Sopenharmony_ci#define CHANNEL_FLAGS_WAITIRQ	16
338c2ecf20Sopenharmony_ci#define CHANNEL_FLAGS_RWMASK	1
348c2ecf20Sopenharmony_ci#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define LOG_FLAG_ILLEGALPKT	1
378c2ecf20Sopenharmony_ci#define LOG_FLAG_ILLEGALSIZE	2
388c2ecf20Sopenharmony_ci#define LOG_FLAG_OVERRUN	4
398c2ecf20Sopenharmony_ci#define LOG_FLAG_NOMEM		8
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define ctcm_pr_debug(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define CTCM_PR_DEBUG(fmt, arg...) \
448c2ecf20Sopenharmony_ci	do { \
458c2ecf20Sopenharmony_ci		if (do_debug) \
468c2ecf20Sopenharmony_ci			printk(KERN_DEBUG fmt, ##arg); \
478c2ecf20Sopenharmony_ci	} while (0)
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define	CTCM_PR_DBGDATA(fmt, arg...) \
508c2ecf20Sopenharmony_ci	do { \
518c2ecf20Sopenharmony_ci		if (do_debug_data) \
528c2ecf20Sopenharmony_ci			printk(KERN_DEBUG fmt, ##arg); \
538c2ecf20Sopenharmony_ci	} while (0)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define	CTCM_D3_DUMP(buf, len) \
568c2ecf20Sopenharmony_ci	do { \
578c2ecf20Sopenharmony_ci		if (do_debug_data) \
588c2ecf20Sopenharmony_ci			ctcmpc_dumpit(buf, len); \
598c2ecf20Sopenharmony_ci	} while (0)
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#define	CTCM_CCW_DUMP(buf, len) \
628c2ecf20Sopenharmony_ci	do { \
638c2ecf20Sopenharmony_ci		if (do_debug_ccw) \
648c2ecf20Sopenharmony_ci			ctcmpc_dumpit(buf, len); \
658c2ecf20Sopenharmony_ci	} while (0)
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci/**
688c2ecf20Sopenharmony_ci * Enum for classifying detected devices
698c2ecf20Sopenharmony_ci */
708c2ecf20Sopenharmony_cienum ctcm_channel_types {
718c2ecf20Sopenharmony_ci	/* Device is not a channel  */
728c2ecf20Sopenharmony_ci	ctcm_channel_type_none,
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/* Device is a CTC/A */
758c2ecf20Sopenharmony_ci	ctcm_channel_type_parallel,
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	/* Device is a FICON channel */
788c2ecf20Sopenharmony_ci	ctcm_channel_type_ficon,
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	/* Device is a ESCON channel */
818c2ecf20Sopenharmony_ci	ctcm_channel_type_escon
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/*
858c2ecf20Sopenharmony_ci * CCW commands, used in this driver.
868c2ecf20Sopenharmony_ci */
878c2ecf20Sopenharmony_ci#define CCW_CMD_WRITE		0x01
888c2ecf20Sopenharmony_ci#define CCW_CMD_READ		0x02
898c2ecf20Sopenharmony_ci#define CCW_CMD_NOOP		0x03
908c2ecf20Sopenharmony_ci#define CCW_CMD_TIC             0x08
918c2ecf20Sopenharmony_ci#define CCW_CMD_SENSE_CMD	0x14
928c2ecf20Sopenharmony_ci#define CCW_CMD_WRITE_CTL	0x17
938c2ecf20Sopenharmony_ci#define CCW_CMD_SET_EXTENDED	0xc3
948c2ecf20Sopenharmony_ci#define CCW_CMD_PREPARE		0xe3
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#define CTCM_PROTO_S390		0
978c2ecf20Sopenharmony_ci#define CTCM_PROTO_LINUX	1
988c2ecf20Sopenharmony_ci#define CTCM_PROTO_LINUX_TTY	2
998c2ecf20Sopenharmony_ci#define CTCM_PROTO_OS390	3
1008c2ecf20Sopenharmony_ci#define CTCM_PROTO_MPC		4
1018c2ecf20Sopenharmony_ci#define CTCM_PROTO_MAX		4
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci#define CTCM_BUFSIZE_LIMIT	65535
1048c2ecf20Sopenharmony_ci#define CTCM_BUFSIZE_DEFAULT	32768
1058c2ecf20Sopenharmony_ci#define MPC_BUFSIZE_DEFAULT	CTCM_BUFSIZE_LIMIT
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci#define CTCM_TIME_1_SEC		1000
1088c2ecf20Sopenharmony_ci#define CTCM_TIME_5_SEC		5000
1098c2ecf20Sopenharmony_ci#define CTCM_TIME_10_SEC	10000
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci#define CTCM_INITIAL_BLOCKLEN	2
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci#define CTCM_READ		0
1148c2ecf20Sopenharmony_ci#define CTCM_WRITE		1
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci#define CTCM_ID_SIZE		20+3
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistruct ctcm_profile {
1198c2ecf20Sopenharmony_ci	unsigned long maxmulti;
1208c2ecf20Sopenharmony_ci	unsigned long maxcqueue;
1218c2ecf20Sopenharmony_ci	unsigned long doios_single;
1228c2ecf20Sopenharmony_ci	unsigned long doios_multi;
1238c2ecf20Sopenharmony_ci	unsigned long txlen;
1248c2ecf20Sopenharmony_ci	unsigned long tx_time;
1258c2ecf20Sopenharmony_ci	unsigned long send_stamp;
1268c2ecf20Sopenharmony_ci};
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci/*
1298c2ecf20Sopenharmony_ci * Definition of one channel
1308c2ecf20Sopenharmony_ci */
1318c2ecf20Sopenharmony_cistruct channel {
1328c2ecf20Sopenharmony_ci	struct channel *next;
1338c2ecf20Sopenharmony_ci	char id[CTCM_ID_SIZE];
1348c2ecf20Sopenharmony_ci	struct ccw_device *cdev;
1358c2ecf20Sopenharmony_ci	/*
1368c2ecf20Sopenharmony_ci	 * Type of this channel.
1378c2ecf20Sopenharmony_ci	 * CTC/A or Escon for valid channels.
1388c2ecf20Sopenharmony_ci	 */
1398c2ecf20Sopenharmony_ci	enum ctcm_channel_types type;
1408c2ecf20Sopenharmony_ci	/*
1418c2ecf20Sopenharmony_ci	 * Misc. flags. See CHANNEL_FLAGS_... below
1428c2ecf20Sopenharmony_ci	 */
1438c2ecf20Sopenharmony_ci	__u32 flags;
1448c2ecf20Sopenharmony_ci	__u16 protocol;		/* protocol of this channel (4 = MPC) */
1458c2ecf20Sopenharmony_ci	/*
1468c2ecf20Sopenharmony_ci	 * I/O and irq related stuff
1478c2ecf20Sopenharmony_ci	 */
1488c2ecf20Sopenharmony_ci	struct ccw1 *ccw;
1498c2ecf20Sopenharmony_ci	struct irb *irb;
1508c2ecf20Sopenharmony_ci	/*
1518c2ecf20Sopenharmony_ci	 * RX/TX buffer size
1528c2ecf20Sopenharmony_ci	 */
1538c2ecf20Sopenharmony_ci	int max_bufsize;
1548c2ecf20Sopenharmony_ci	struct sk_buff *trans_skb;	/* transmit/receive buffer */
1558c2ecf20Sopenharmony_ci	struct sk_buff_head io_queue;	/* universal I/O queue */
1568c2ecf20Sopenharmony_ci	struct tasklet_struct ch_tasklet;	/* MPC ONLY */
1578c2ecf20Sopenharmony_ci	/*
1588c2ecf20Sopenharmony_ci	 * TX queue for collecting skb's during busy.
1598c2ecf20Sopenharmony_ci	 */
1608c2ecf20Sopenharmony_ci	struct sk_buff_head collect_queue;
1618c2ecf20Sopenharmony_ci	/*
1628c2ecf20Sopenharmony_ci	 * Amount of data in collect_queue.
1638c2ecf20Sopenharmony_ci	 */
1648c2ecf20Sopenharmony_ci	int collect_len;
1658c2ecf20Sopenharmony_ci	/*
1668c2ecf20Sopenharmony_ci	 * spinlock for collect_queue and collect_len
1678c2ecf20Sopenharmony_ci	 */
1688c2ecf20Sopenharmony_ci	spinlock_t collect_lock;
1698c2ecf20Sopenharmony_ci	/*
1708c2ecf20Sopenharmony_ci	 * Timer for detecting unresposive
1718c2ecf20Sopenharmony_ci	 * I/O operations.
1728c2ecf20Sopenharmony_ci	 */
1738c2ecf20Sopenharmony_ci	fsm_timer timer;
1748c2ecf20Sopenharmony_ci	/* MPC ONLY section begin */
1758c2ecf20Sopenharmony_ci	__u32	th_seq_num;	/* SNA TH seq number */
1768c2ecf20Sopenharmony_ci	__u8	th_seg;
1778c2ecf20Sopenharmony_ci	__u32	pdu_seq;
1788c2ecf20Sopenharmony_ci	struct sk_buff		*xid_skb;
1798c2ecf20Sopenharmony_ci	char			*xid_skb_data;
1808c2ecf20Sopenharmony_ci	struct th_header	*xid_th;
1818c2ecf20Sopenharmony_ci	struct xid2		*xid;
1828c2ecf20Sopenharmony_ci	char			*xid_id;
1838c2ecf20Sopenharmony_ci	struct th_header	*rcvd_xid_th;
1848c2ecf20Sopenharmony_ci	struct xid2		*rcvd_xid;
1858c2ecf20Sopenharmony_ci	char			*rcvd_xid_id;
1868c2ecf20Sopenharmony_ci	__u8			in_mpcgroup;
1878c2ecf20Sopenharmony_ci	fsm_timer		sweep_timer;
1888c2ecf20Sopenharmony_ci	struct sk_buff_head	sweep_queue;
1898c2ecf20Sopenharmony_ci	struct th_header	*discontact_th;
1908c2ecf20Sopenharmony_ci	struct tasklet_struct	ch_disc_tasklet;
1918c2ecf20Sopenharmony_ci	/* MPC ONLY section end */
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	int retry;		/* retry counter for misc. operations */
1948c2ecf20Sopenharmony_ci	fsm_instance *fsm;	/* finite state machine of this channel */
1958c2ecf20Sopenharmony_ci	struct net_device *netdev;	/* corresponding net_device */
1968c2ecf20Sopenharmony_ci	struct ctcm_profile prof;
1978c2ecf20Sopenharmony_ci	__u8 *trans_skb_data;
1988c2ecf20Sopenharmony_ci	__u16 logflags;
1998c2ecf20Sopenharmony_ci	__u8  sense_rc; /* last unit check sense code report control */
2008c2ecf20Sopenharmony_ci};
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistruct ctcm_priv {
2038c2ecf20Sopenharmony_ci	struct net_device_stats	stats;
2048c2ecf20Sopenharmony_ci	unsigned long	tbusy;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	/* The MPC group struct of this interface */
2078c2ecf20Sopenharmony_ci	struct	mpc_group	*mpcg;	/* MPC only */
2088c2ecf20Sopenharmony_ci	struct	xid2		*xid;	/* MPC only */
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	/* The finite state machine of this interface */
2118c2ecf20Sopenharmony_ci	fsm_instance *fsm;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	/* The protocol of this device */
2148c2ecf20Sopenharmony_ci	__u16 protocol;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	/* Timer for restarting after I/O Errors */
2178c2ecf20Sopenharmony_ci	fsm_timer	restart_timer;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	int buffer_size;	/* ctc only */
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	struct channel *channel[2];
2228c2ecf20Sopenharmony_ci};
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ciint ctcm_open(struct net_device *dev);
2258c2ecf20Sopenharmony_ciint ctcm_close(struct net_device *dev);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ciextern const struct attribute_group *ctcm_attr_groups[];
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci/*
2308c2ecf20Sopenharmony_ci * Compatibility macros for busy handling
2318c2ecf20Sopenharmony_ci * of network devices.
2328c2ecf20Sopenharmony_ci */
2338c2ecf20Sopenharmony_cistatic inline void ctcm_clear_busy_do(struct net_device *dev)
2348c2ecf20Sopenharmony_ci{
2358c2ecf20Sopenharmony_ci	clear_bit(0, &(((struct ctcm_priv *)dev->ml_priv)->tbusy));
2368c2ecf20Sopenharmony_ci	netif_wake_queue(dev);
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cistatic inline void ctcm_clear_busy(struct net_device *dev)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	struct mpc_group *grp;
2428c2ecf20Sopenharmony_ci	grp = ((struct ctcm_priv *)dev->ml_priv)->mpcg;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	if (!(grp && grp->in_sweep))
2458c2ecf20Sopenharmony_ci		ctcm_clear_busy_do(dev);
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic inline int ctcm_test_and_set_busy(struct net_device *dev)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	netif_stop_queue(dev);
2528c2ecf20Sopenharmony_ci	return test_and_set_bit(0,
2538c2ecf20Sopenharmony_ci			&(((struct ctcm_priv *)dev->ml_priv)->tbusy));
2548c2ecf20Sopenharmony_ci}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ciextern int loglevel;
2578c2ecf20Sopenharmony_ciextern struct channel *channels;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_civoid ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb);
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci/*
2628c2ecf20Sopenharmony_ci * Functions related to setup and device detection.
2638c2ecf20Sopenharmony_ci */
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistatic inline int ctcm_less_than(char *id1, char *id2)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	unsigned long dev1, dev2;
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	id1 = id1 + 5;
2708c2ecf20Sopenharmony_ci	id2 = id2 + 5;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	dev1 = simple_strtoul(id1, &id1, 16);
2738c2ecf20Sopenharmony_ci	dev2 = simple_strtoul(id2, &id2, 16);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	return (dev1 < dev2);
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ciint ctcm_ch_alloc_buffer(struct channel *ch);
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic inline int ctcm_checkalloc_buffer(struct channel *ch)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	if (ch->trans_skb == NULL)
2838c2ecf20Sopenharmony_ci		return ctcm_ch_alloc_buffer(ch);
2848c2ecf20Sopenharmony_ci	if (ch->flags & CHANNEL_FLAGS_BUFSIZE_CHANGED) {
2858c2ecf20Sopenharmony_ci		dev_kfree_skb(ch->trans_skb);
2868c2ecf20Sopenharmony_ci		return ctcm_ch_alloc_buffer(ch);
2878c2ecf20Sopenharmony_ci	}
2888c2ecf20Sopenharmony_ci	return 0;
2898c2ecf20Sopenharmony_ci}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cistruct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci/* test if protocol attribute (of struct ctcm_priv or struct channel)
2948c2ecf20Sopenharmony_ci * has MPC protocol setting. Type is not checked
2958c2ecf20Sopenharmony_ci */
2968c2ecf20Sopenharmony_ci#define IS_MPC(p) ((p)->protocol == CTCM_PROTO_MPC)
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci/* test if struct ctcm_priv of struct net_device has MPC protocol setting */
2998c2ecf20Sopenharmony_ci#define IS_MPCDEV(dev) IS_MPC((struct ctcm_priv *)dev->ml_priv)
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_cistatic inline gfp_t gfp_type(void)
3028c2ecf20Sopenharmony_ci{
3038c2ecf20Sopenharmony_ci	return in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci/*
3078c2ecf20Sopenharmony_ci * Definition of our link level header.
3088c2ecf20Sopenharmony_ci */
3098c2ecf20Sopenharmony_cistruct ll_header {
3108c2ecf20Sopenharmony_ci	__u16 length;
3118c2ecf20Sopenharmony_ci	__u16 type;
3128c2ecf20Sopenharmony_ci	__u16 unused;
3138c2ecf20Sopenharmony_ci};
3148c2ecf20Sopenharmony_ci#define LL_HEADER_LENGTH (sizeof(struct ll_header))
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci#endif
317