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