162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _SPARC64_VIO_H
362306a36Sopenharmony_ci#define _SPARC64_VIO_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/kernel.h>
662306a36Sopenharmony_ci#include <linux/device.h>
762306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
862306a36Sopenharmony_ci#include <linux/timer.h>
962306a36Sopenharmony_ci#include <linux/spinlock.h>
1062306a36Sopenharmony_ci#include <linux/completion.h>
1162306a36Sopenharmony_ci#include <linux/list.h>
1262306a36Sopenharmony_ci#include <linux/log2.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <asm/ldc.h>
1562306a36Sopenharmony_ci#include <asm/mdesc.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistruct vio_msg_tag {
1862306a36Sopenharmony_ci	u8			type;
1962306a36Sopenharmony_ci#define VIO_TYPE_CTRL		0x01
2062306a36Sopenharmony_ci#define VIO_TYPE_DATA		0x02
2162306a36Sopenharmony_ci#define VIO_TYPE_ERR		0x04
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	u8			stype;
2462306a36Sopenharmony_ci#define VIO_SUBTYPE_INFO	0x01
2562306a36Sopenharmony_ci#define VIO_SUBTYPE_ACK		0x02
2662306a36Sopenharmony_ci#define VIO_SUBTYPE_NACK	0x04
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	u16			stype_env;
2962306a36Sopenharmony_ci#define VIO_VER_INFO		0x0001
3062306a36Sopenharmony_ci#define VIO_ATTR_INFO		0x0002
3162306a36Sopenharmony_ci#define VIO_DRING_REG		0x0003
3262306a36Sopenharmony_ci#define VIO_DRING_UNREG		0x0004
3362306a36Sopenharmony_ci#define VIO_RDX			0x0005
3462306a36Sopenharmony_ci#define VIO_PKT_DATA		0x0040
3562306a36Sopenharmony_ci#define VIO_DESC_DATA		0x0041
3662306a36Sopenharmony_ci#define VIO_DRING_DATA		0x0042
3762306a36Sopenharmony_ci#define VNET_MCAST_INFO		0x0101
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	u32		sid;
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistruct vio_rdx {
4362306a36Sopenharmony_ci	struct vio_msg_tag	tag;
4462306a36Sopenharmony_ci	u64			resv[6];
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistruct vio_ver_info {
4862306a36Sopenharmony_ci	struct vio_msg_tag	tag;
4962306a36Sopenharmony_ci	u16			major;
5062306a36Sopenharmony_ci	u16			minor;
5162306a36Sopenharmony_ci	u8			dev_class;
5262306a36Sopenharmony_ci#define VDEV_NETWORK		0x01
5362306a36Sopenharmony_ci#define VDEV_NETWORK_SWITCH	0x02
5462306a36Sopenharmony_ci#define VDEV_DISK		0x03
5562306a36Sopenharmony_ci#define VDEV_DISK_SERVER	0x04
5662306a36Sopenharmony_ci#define VDEV_CONSOLE_CON	0x05
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	u8			resv1[3];
5962306a36Sopenharmony_ci	u64			resv2[5];
6062306a36Sopenharmony_ci};
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistruct vio_dring_register {
6362306a36Sopenharmony_ci	struct vio_msg_tag	tag;
6462306a36Sopenharmony_ci	u64			dring_ident;
6562306a36Sopenharmony_ci	u32			num_descr;
6662306a36Sopenharmony_ci	u32			descr_size;
6762306a36Sopenharmony_ci	u16			options;
6862306a36Sopenharmony_ci#define VIO_TX_DRING		0x0001
6962306a36Sopenharmony_ci#define VIO_RX_DRING		0x0002
7062306a36Sopenharmony_ci#define VIO_RX_DRING_DATA	0x0004
7162306a36Sopenharmony_ci	u16			resv;
7262306a36Sopenharmony_ci	u32			num_cookies;
7362306a36Sopenharmony_ci	struct ldc_trans_cookie	cookies[];
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistruct vio_dring_unregister {
7762306a36Sopenharmony_ci	struct vio_msg_tag	tag;
7862306a36Sopenharmony_ci	u64			dring_ident;
7962306a36Sopenharmony_ci	u64			resv[5];
8062306a36Sopenharmony_ci};
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/* Data transfer modes */
8362306a36Sopenharmony_ci#define VIO_PKT_MODE		0x01 /* Packet based transfer	*/
8462306a36Sopenharmony_ci#define VIO_DESC_MODE		0x02 /* In-band descriptors	*/
8562306a36Sopenharmony_ci#define VIO_DRING_MODE		0x03 /* Descriptor rings	*/
8662306a36Sopenharmony_ci/* in vers >= 1.2, VIO_DRING_MODE is 0x04 and transfer mode is a bitmask */
8762306a36Sopenharmony_ci#define VIO_NEW_DRING_MODE	0x04
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistruct vio_dring_data {
9062306a36Sopenharmony_ci	struct vio_msg_tag	tag;
9162306a36Sopenharmony_ci	u64			seq;
9262306a36Sopenharmony_ci	u64			dring_ident;
9362306a36Sopenharmony_ci	u32			start_idx;
9462306a36Sopenharmony_ci	u32			end_idx;
9562306a36Sopenharmony_ci	u8			state;
9662306a36Sopenharmony_ci#define VIO_DRING_ACTIVE	0x01
9762306a36Sopenharmony_ci#define VIO_DRING_STOPPED	0x02
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	u8			__pad1;
10062306a36Sopenharmony_ci	u16			__pad2;
10162306a36Sopenharmony_ci	u32			__pad3;
10262306a36Sopenharmony_ci	u64			__par4[2];
10362306a36Sopenharmony_ci};
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistruct vio_dring_hdr {
10662306a36Sopenharmony_ci	u8			state;
10762306a36Sopenharmony_ci#define VIO_DESC_FREE		0x01
10862306a36Sopenharmony_ci#define VIO_DESC_READY		0x02
10962306a36Sopenharmony_ci#define VIO_DESC_ACCEPTED	0x03
11062306a36Sopenharmony_ci#define VIO_DESC_DONE		0x04
11162306a36Sopenharmony_ci	u8			ack;
11262306a36Sopenharmony_ci#define VIO_ACK_ENABLE		0x01
11362306a36Sopenharmony_ci#define VIO_ACK_DISABLE		0x00
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	u16			__pad1;
11662306a36Sopenharmony_ci	u32			__pad2;
11762306a36Sopenharmony_ci};
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci/* VIO disk specific structures and defines */
12062306a36Sopenharmony_cistruct vio_disk_attr_info {
12162306a36Sopenharmony_ci	struct vio_msg_tag	tag;
12262306a36Sopenharmony_ci	u8			xfer_mode;
12362306a36Sopenharmony_ci	u8			vdisk_type;
12462306a36Sopenharmony_ci#define VD_DISK_TYPE_SLICE	0x01 /* Slice in block device	*/
12562306a36Sopenharmony_ci#define VD_DISK_TYPE_DISK	0x02 /* Entire block device	*/
12662306a36Sopenharmony_ci	u8			vdisk_mtype;		/* v1.1 */
12762306a36Sopenharmony_ci#define VD_MEDIA_TYPE_FIXED	0x01 /* Fixed device */
12862306a36Sopenharmony_ci#define VD_MEDIA_TYPE_CD	0x02 /* CD Device    */
12962306a36Sopenharmony_ci#define VD_MEDIA_TYPE_DVD	0x03 /* DVD Device   */
13062306a36Sopenharmony_ci	u8			resv1;
13162306a36Sopenharmony_ci	u32			vdisk_block_size;
13262306a36Sopenharmony_ci	u64			operations;
13362306a36Sopenharmony_ci	u64			vdisk_size;		/* v1.1 */
13462306a36Sopenharmony_ci	u64			max_xfer_size;
13562306a36Sopenharmony_ci	u32			phys_block_size;	/* v1.2 */
13662306a36Sopenharmony_ci	u32			resv2;
13762306a36Sopenharmony_ci	u64			resv3[1];
13862306a36Sopenharmony_ci};
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistruct vio_disk_desc {
14162306a36Sopenharmony_ci	struct vio_dring_hdr	hdr;
14262306a36Sopenharmony_ci	u64			req_id;
14362306a36Sopenharmony_ci	u8			operation;
14462306a36Sopenharmony_ci#define VD_OP_BREAD		0x01 /* Block read			*/
14562306a36Sopenharmony_ci#define VD_OP_BWRITE		0x02 /* Block write			*/
14662306a36Sopenharmony_ci#define VD_OP_FLUSH		0x03 /* Flush disk contents		*/
14762306a36Sopenharmony_ci#define VD_OP_GET_WCE		0x04 /* Get write-cache status		*/
14862306a36Sopenharmony_ci#define VD_OP_SET_WCE		0x05 /* Enable/disable write-cache	*/
14962306a36Sopenharmony_ci#define VD_OP_GET_VTOC		0x06 /* Get VTOC			*/
15062306a36Sopenharmony_ci#define VD_OP_SET_VTOC		0x07 /* Set VTOC			*/
15162306a36Sopenharmony_ci#define VD_OP_GET_DISKGEOM	0x08 /* Get disk geometry		*/
15262306a36Sopenharmony_ci#define VD_OP_SET_DISKGEOM	0x09 /* Set disk geometry		*/
15362306a36Sopenharmony_ci#define VD_OP_SCSICMD		0x0a /* SCSI control command		*/
15462306a36Sopenharmony_ci#define VD_OP_GET_DEVID		0x0b /* Get device ID			*/
15562306a36Sopenharmony_ci#define VD_OP_GET_EFI		0x0c /* Get EFI				*/
15662306a36Sopenharmony_ci#define VD_OP_SET_EFI		0x0d /* Set EFI				*/
15762306a36Sopenharmony_ci	u8			slice;
15862306a36Sopenharmony_ci	u16			resv1;
15962306a36Sopenharmony_ci	u32			status;
16062306a36Sopenharmony_ci	u64			offset;
16162306a36Sopenharmony_ci	u64			size;
16262306a36Sopenharmony_ci	u32			ncookies;
16362306a36Sopenharmony_ci	u32			resv2;
16462306a36Sopenharmony_ci	struct ldc_trans_cookie	cookies[];
16562306a36Sopenharmony_ci};
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci#define VIO_DISK_VNAME_LEN	8
16862306a36Sopenharmony_ci#define VIO_DISK_ALABEL_LEN	128
16962306a36Sopenharmony_ci#define VIO_DISK_NUM_PART	8
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistruct vio_disk_vtoc {
17262306a36Sopenharmony_ci	u8			volume_name[VIO_DISK_VNAME_LEN];
17362306a36Sopenharmony_ci	u16			sector_size;
17462306a36Sopenharmony_ci	u16			num_partitions;
17562306a36Sopenharmony_ci	u8			ascii_label[VIO_DISK_ALABEL_LEN];
17662306a36Sopenharmony_ci	struct {
17762306a36Sopenharmony_ci		u16		id;
17862306a36Sopenharmony_ci		u16		perm_flags;
17962306a36Sopenharmony_ci		u32		resv;
18062306a36Sopenharmony_ci		u64		start_block;
18162306a36Sopenharmony_ci		u64		num_blocks;
18262306a36Sopenharmony_ci	} partitions[VIO_DISK_NUM_PART];
18362306a36Sopenharmony_ci};
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistruct vio_disk_geom {
18662306a36Sopenharmony_ci	u16			num_cyl; /* Num data cylinders		*/
18762306a36Sopenharmony_ci	u16			alt_cyl; /* Num alternate cylinders	*/
18862306a36Sopenharmony_ci	u16			beg_cyl; /* Cyl off of fixed head area	*/
18962306a36Sopenharmony_ci	u16			num_hd;  /* Num heads			*/
19062306a36Sopenharmony_ci	u16			num_sec; /* Num sectors			*/
19162306a36Sopenharmony_ci	u16			ifact;   /* Interleave factor		*/
19262306a36Sopenharmony_ci	u16			apc;     /* Alts per cylinder (SCSI)	*/
19362306a36Sopenharmony_ci	u16			rpm;	 /* Revolutions per minute	*/
19462306a36Sopenharmony_ci	u16			phy_cyl; /* Num physical cylinders	*/
19562306a36Sopenharmony_ci	u16			wr_skip; /* Num sects to skip, writes	*/
19662306a36Sopenharmony_ci	u16			rd_skip; /* Num sects to skip, writes	*/
19762306a36Sopenharmony_ci};
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_cistruct vio_disk_devid {
20062306a36Sopenharmony_ci	u16			resv;
20162306a36Sopenharmony_ci	u16			type;
20262306a36Sopenharmony_ci	u32			len;
20362306a36Sopenharmony_ci	char			id[];
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistruct vio_disk_efi {
20762306a36Sopenharmony_ci	u64			lba;
20862306a36Sopenharmony_ci	u64			len;
20962306a36Sopenharmony_ci	char			data[];
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci/* VIO net specific structures and defines */
21362306a36Sopenharmony_cistruct vio_net_attr_info {
21462306a36Sopenharmony_ci	struct vio_msg_tag	tag;
21562306a36Sopenharmony_ci	u8			xfer_mode;
21662306a36Sopenharmony_ci	u8			addr_type;
21762306a36Sopenharmony_ci#define VNET_ADDR_ETHERMAC	0x01
21862306a36Sopenharmony_ci	u16			ack_freq;
21962306a36Sopenharmony_ci	u8			plnk_updt;
22062306a36Sopenharmony_ci#define PHYSLINK_UPDATE_NONE		0x00
22162306a36Sopenharmony_ci#define PHYSLINK_UPDATE_STATE		0x01
22262306a36Sopenharmony_ci#define PHYSLINK_UPDATE_STATE_ACK	0x02
22362306a36Sopenharmony_ci#define PHYSLINK_UPDATE_STATE_NACK	0x03
22462306a36Sopenharmony_ci	u8			options;
22562306a36Sopenharmony_ci	u16			resv1;
22662306a36Sopenharmony_ci	u64			addr;
22762306a36Sopenharmony_ci	u64			mtu;
22862306a36Sopenharmony_ci	u16			cflags;
22962306a36Sopenharmony_ci#define VNET_LSO_IPV4_CAPAB		0x0001
23062306a36Sopenharmony_ci	u16			ipv4_lso_maxlen;
23162306a36Sopenharmony_ci	u32			resv2;
23262306a36Sopenharmony_ci	u64			resv3[2];
23362306a36Sopenharmony_ci};
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci#define VNET_NUM_MCAST		7
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistruct vio_net_mcast_info {
23862306a36Sopenharmony_ci	struct vio_msg_tag	tag;
23962306a36Sopenharmony_ci	u8			set;
24062306a36Sopenharmony_ci	u8			count;
24162306a36Sopenharmony_ci	u8			mcast_addr[VNET_NUM_MCAST * 6];
24262306a36Sopenharmony_ci	u32			resv;
24362306a36Sopenharmony_ci};
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_cistruct vio_net_desc {
24662306a36Sopenharmony_ci	struct vio_dring_hdr	hdr;
24762306a36Sopenharmony_ci	u32			size;
24862306a36Sopenharmony_ci	u32			ncookies;
24962306a36Sopenharmony_ci	struct ldc_trans_cookie	cookies[];
25062306a36Sopenharmony_ci};
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_cistruct vio_net_dext {
25362306a36Sopenharmony_ci	u8		flags;
25462306a36Sopenharmony_ci#define VNET_PKT_HASH			0x01
25562306a36Sopenharmony_ci#define	VNET_PKT_HCK_IPV4_HDRCKSUM	0x02
25662306a36Sopenharmony_ci#define	VNET_PKT_HCK_FULLCKSUM		0x04
25762306a36Sopenharmony_ci#define	VNET_PKT_IPV4_LSO		0x08
25862306a36Sopenharmony_ci#define	VNET_PKT_HCK_IPV4_HDRCKSUM_OK	0x10
25962306a36Sopenharmony_ci#define	VNET_PKT_HCK_FULLCKSUM_OK	0x20
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	u8		vnet_hashval;
26262306a36Sopenharmony_ci	u16		ipv4_lso_mss;
26362306a36Sopenharmony_ci	u32		resv3;
26462306a36Sopenharmony_ci};
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic inline struct vio_net_dext *vio_net_ext(struct vio_net_desc *desc)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	return (struct vio_net_dext *)&desc->cookies[2];
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci#define VIO_MAX_RING_COOKIES	24
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistruct vio_dring_state {
27462306a36Sopenharmony_ci	u64			ident;
27562306a36Sopenharmony_ci	void			*base;
27662306a36Sopenharmony_ci	u64			snd_nxt;
27762306a36Sopenharmony_ci	u64			rcv_nxt;
27862306a36Sopenharmony_ci	u32			entry_size;
27962306a36Sopenharmony_ci	u32			num_entries;
28062306a36Sopenharmony_ci	u32			prod;
28162306a36Sopenharmony_ci	u32			cons;
28262306a36Sopenharmony_ci	u32			pending;
28362306a36Sopenharmony_ci	int			ncookies;
28462306a36Sopenharmony_ci	struct ldc_trans_cookie	cookies[VIO_MAX_RING_COOKIES];
28562306a36Sopenharmony_ci};
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci#define VIO_TAG_SIZE		(sizeof(struct vio_msg_tag))
28862306a36Sopenharmony_ci#define VIO_VCC_MTU_SIZE	(LDC_PACKET_SIZE - VIO_TAG_SIZE)
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistruct vio_vcc {
29162306a36Sopenharmony_ci	struct vio_msg_tag	tag;
29262306a36Sopenharmony_ci	char			data[VIO_VCC_MTU_SIZE];
29362306a36Sopenharmony_ci};
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cistatic inline void *vio_dring_cur(struct vio_dring_state *dr)
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	return dr->base + (dr->entry_size * dr->prod);
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic inline void *vio_dring_entry(struct vio_dring_state *dr,
30162306a36Sopenharmony_ci				    unsigned int index)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	return dr->base + (dr->entry_size * index);
30462306a36Sopenharmony_ci}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_cistatic inline u32 vio_dring_avail(struct vio_dring_state *dr,
30762306a36Sopenharmony_ci				  unsigned int ring_size)
30862306a36Sopenharmony_ci{
30962306a36Sopenharmony_ci	return (dr->pending -
31062306a36Sopenharmony_ci		((dr->prod - dr->cons) & (ring_size - 1)) - 1);
31162306a36Sopenharmony_ci}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_cistatic inline u32 vio_dring_next(struct vio_dring_state *dr, u32 index)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	if (++index == dr->num_entries)
31662306a36Sopenharmony_ci		index = 0;
31762306a36Sopenharmony_ci	return index;
31862306a36Sopenharmony_ci}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cistatic inline u32 vio_dring_prev(struct vio_dring_state *dr, u32 index)
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	if (index == 0)
32362306a36Sopenharmony_ci		return dr->num_entries - 1;
32462306a36Sopenharmony_ci	else
32562306a36Sopenharmony_ci		return index - 1;
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci#define VIO_MAX_TYPE_LEN	32
32962306a36Sopenharmony_ci#define VIO_MAX_NAME_LEN	32
33062306a36Sopenharmony_ci#define VIO_MAX_COMPAT_LEN	64
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_cistruct vio_dev {
33362306a36Sopenharmony_ci	u64			mp;
33462306a36Sopenharmony_ci	struct device_node	*dp;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	char			node_name[VIO_MAX_NAME_LEN];
33762306a36Sopenharmony_ci	char			type[VIO_MAX_TYPE_LEN];
33862306a36Sopenharmony_ci	char			compat[VIO_MAX_COMPAT_LEN];
33962306a36Sopenharmony_ci	int			compat_len;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	u64			dev_no;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	unsigned long		port_id;
34462306a36Sopenharmony_ci	unsigned long		channel_id;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	unsigned int		tx_irq;
34762306a36Sopenharmony_ci	unsigned int		rx_irq;
34862306a36Sopenharmony_ci	u64			rx_ino;
34962306a36Sopenharmony_ci	u64			tx_ino;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	/* Handle to the root of "channel-devices" sub-tree in MDESC */
35262306a36Sopenharmony_ci	u64			cdev_handle;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	/* MD specific data used to identify the vdev in MD */
35562306a36Sopenharmony_ci	union md_node_info	md_node_info;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	struct device		dev;
35862306a36Sopenharmony_ci};
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_cistruct vio_driver {
36162306a36Sopenharmony_ci	const char			*name;
36262306a36Sopenharmony_ci	struct list_head		node;
36362306a36Sopenharmony_ci	const struct vio_device_id	*id_table;
36462306a36Sopenharmony_ci	int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
36562306a36Sopenharmony_ci	void (*remove)(struct vio_dev *dev);
36662306a36Sopenharmony_ci	void (*shutdown)(struct vio_dev *dev);
36762306a36Sopenharmony_ci	unsigned long			driver_data;
36862306a36Sopenharmony_ci	struct device_driver		driver;
36962306a36Sopenharmony_ci	bool				no_irq;
37062306a36Sopenharmony_ci};
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cistruct vio_version {
37362306a36Sopenharmony_ci	u16		major;
37462306a36Sopenharmony_ci	u16		minor;
37562306a36Sopenharmony_ci};
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_cistruct vio_driver_state;
37862306a36Sopenharmony_cistruct vio_driver_ops {
37962306a36Sopenharmony_ci	int	(*send_attr)(struct vio_driver_state *vio);
38062306a36Sopenharmony_ci	int	(*handle_attr)(struct vio_driver_state *vio, void *pkt);
38162306a36Sopenharmony_ci	void	(*handshake_complete)(struct vio_driver_state *vio);
38262306a36Sopenharmony_ci};
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistruct vio_completion {
38562306a36Sopenharmony_ci	struct completion	com;
38662306a36Sopenharmony_ci	int			err;
38762306a36Sopenharmony_ci	int			waiting_for;
38862306a36Sopenharmony_ci};
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_cistruct vio_driver_state {
39162306a36Sopenharmony_ci	/* Protects VIO handshake and, optionally, driver private state.  */
39262306a36Sopenharmony_ci	spinlock_t		lock;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	struct ldc_channel	*lp;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	u32			_peer_sid;
39762306a36Sopenharmony_ci	u32			_local_sid;
39862306a36Sopenharmony_ci	struct vio_dring_state	drings[2];
39962306a36Sopenharmony_ci#define VIO_DRIVER_TX_RING	0
40062306a36Sopenharmony_ci#define VIO_DRIVER_RX_RING	1
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	u8			hs_state;
40362306a36Sopenharmony_ci#define VIO_HS_INVALID		0x00
40462306a36Sopenharmony_ci#define VIO_HS_GOTVERS		0x01
40562306a36Sopenharmony_ci#define VIO_HS_GOT_ATTR		0x04
40662306a36Sopenharmony_ci#define VIO_HS_SENT_DREG	0x08
40762306a36Sopenharmony_ci#define VIO_HS_SENT_RDX		0x10
40862306a36Sopenharmony_ci#define VIO_HS_GOT_RDX_ACK	0x20
40962306a36Sopenharmony_ci#define VIO_HS_GOT_RDX		0x40
41062306a36Sopenharmony_ci#define VIO_HS_SENT_RDX_ACK	0x80
41162306a36Sopenharmony_ci#define VIO_HS_COMPLETE		(VIO_HS_GOT_RDX_ACK | VIO_HS_SENT_RDX_ACK)
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	u8			dev_class;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	u8			dr_state;
41662306a36Sopenharmony_ci#define VIO_DR_STATE_TXREG	0x01
41762306a36Sopenharmony_ci#define VIO_DR_STATE_RXREG	0x02
41862306a36Sopenharmony_ci#define VIO_DR_STATE_TXREQ	0x10
41962306a36Sopenharmony_ci#define VIO_DR_STATE_RXREQ	0x20
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	u8			debug;
42262306a36Sopenharmony_ci#define VIO_DEBUG_HS		0x01
42362306a36Sopenharmony_ci#define VIO_DEBUG_DATA		0x02
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	void			*desc_buf;
42662306a36Sopenharmony_ci	unsigned int		desc_buf_len;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	struct vio_completion	*cmp;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	struct vio_dev		*vdev;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	struct timer_list	timer;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	struct vio_version	ver;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	struct vio_version	*ver_table;
43762306a36Sopenharmony_ci	int			ver_table_entries;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	char			*name;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	struct vio_driver_ops	*ops;
44262306a36Sopenharmony_ci};
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_cistatic inline bool vio_version_before(struct vio_driver_state *vio,
44562306a36Sopenharmony_ci				      u16 major, u16 minor)
44662306a36Sopenharmony_ci{
44762306a36Sopenharmony_ci	u32 have = (u32)vio->ver.major << 16 | vio->ver.minor;
44862306a36Sopenharmony_ci	u32 want = (u32)major << 16 | minor;
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	return have < want;
45162306a36Sopenharmony_ci}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_cistatic inline bool vio_version_after(struct vio_driver_state *vio,
45462306a36Sopenharmony_ci				      u16 major, u16 minor)
45562306a36Sopenharmony_ci{
45662306a36Sopenharmony_ci	u32 have = (u32)vio->ver.major << 16 | vio->ver.minor;
45762306a36Sopenharmony_ci	u32 want = (u32)major << 16 | minor;
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	return have > want;
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cistatic inline bool vio_version_after_eq(struct vio_driver_state *vio,
46362306a36Sopenharmony_ci					u16 major, u16 minor)
46462306a36Sopenharmony_ci{
46562306a36Sopenharmony_ci	u32 have = (u32)vio->ver.major << 16 | vio->ver.minor;
46662306a36Sopenharmony_ci	u32 want = (u32)major << 16 | minor;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	return have >= want;
46962306a36Sopenharmony_ci}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci#define viodbg(TYPE, f, a...) \
47262306a36Sopenharmony_cido {	if (vio->debug & VIO_DEBUG_##TYPE) \
47362306a36Sopenharmony_ci		printk(KERN_INFO "vio: ID[%lu] " f, \
47462306a36Sopenharmony_ci		       vio->vdev->channel_id, ## a); \
47562306a36Sopenharmony_ci} while (0)
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ciint __vio_register_driver(struct vio_driver *drv, struct module *owner,
47862306a36Sopenharmony_ci				 const char *mod_name);
47962306a36Sopenharmony_ci/*
48062306a36Sopenharmony_ci * vio_register_driver must be a macro so that KBUILD_MODNAME can be expanded
48162306a36Sopenharmony_ci */
48262306a36Sopenharmony_ci#define vio_register_driver(driver)		\
48362306a36Sopenharmony_ci	__vio_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
48462306a36Sopenharmony_civoid vio_unregister_driver(struct vio_driver *drv);
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_cistatic inline struct vio_driver *to_vio_driver(struct device_driver *drv)
48762306a36Sopenharmony_ci{
48862306a36Sopenharmony_ci	return container_of(drv, struct vio_driver, driver);
48962306a36Sopenharmony_ci}
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci#define to_vio_dev(__dev)	container_of_const(__dev, struct vio_dev, dev)
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ciint vio_ldc_send(struct vio_driver_state *vio, void *data, int len);
49462306a36Sopenharmony_civoid vio_link_state_change(struct vio_driver_state *vio, int event);
49562306a36Sopenharmony_civoid vio_conn_reset(struct vio_driver_state *vio);
49662306a36Sopenharmony_ciint vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt);
49762306a36Sopenharmony_ciint vio_validate_sid(struct vio_driver_state *vio,
49862306a36Sopenharmony_ci		     struct vio_msg_tag *tp);
49962306a36Sopenharmony_ciu32 vio_send_sid(struct vio_driver_state *vio);
50062306a36Sopenharmony_ciint vio_ldc_alloc(struct vio_driver_state *vio,
50162306a36Sopenharmony_ci		  struct ldc_channel_config *base_cfg, void *event_arg);
50262306a36Sopenharmony_civoid vio_ldc_free(struct vio_driver_state *vio);
50362306a36Sopenharmony_ciint vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
50462306a36Sopenharmony_ci		    u8 dev_class, struct vio_version *ver_table,
50562306a36Sopenharmony_ci		    int ver_table_size, struct vio_driver_ops *ops,
50662306a36Sopenharmony_ci		    char *name);
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_civoid vio_port_up(struct vio_driver_state *vio);
50962306a36Sopenharmony_ciint vio_set_intr(unsigned long dev_ino, int state);
51062306a36Sopenharmony_ciu64 vio_vdev_node(struct mdesc_handle *hp, struct vio_dev *vdev);
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci#endif /* _SPARC64_VIO_H */
513