Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (C) 2010 - 2016 UNISYS CORPORATION
 * All rights reserved.
 */

#ifndef __IOCHANNEL_H__
#define __IOCHANNEL_H__

/*
 * Everything needed for IOPart-GuestPart communication is define in
 * this file. Note: Everything is OS-independent because this file is
 * used by Windows, Linux and possible EFI drivers.
 *
 * Communication flow between the IOPart and GuestPart uses the channel headers
 * channel state. The following states are currently being used:
 *       UNINIT(All Zeroes), CHANNEL_ATTACHING, CHANNEL_ATTACHED, CHANNEL_OPENED
 *
 * Additional states will be used later. No locking is needed to switch between
 * states due to the following rules:
 *
 *      1.  IOPart is only the only partition allowed to change from UNIT
 *      2.  IOPart is only the only partition allowed to change from
 *		CHANNEL_ATTACHING
 *      3.  GuestPart is only the only partition allowed to change from
 *		CHANNEL_ATTACHED
 *
 * The state changes are the following: IOPart sees the channel is in UNINIT,
 *        UNINIT -> CHANNEL_ATTACHING (performed only by IOPart)
 *        CHANNEL_ATTACHING -> CHANNEL_ATTACHED (performed only by IOPart)
 *        CHANNEL_ATTACHED -> CHANNEL_OPENED (performed only by GuestPart)
 */

#include <linux/uuid.h>
#include <linux/skbuff.h>
#include <linux/visorbus.h>

/*
 * Must increment these whenever you insert or delete fields within this channel
 * struct. Also increment whenever you change the meaning of fields within this
 * channel struct so as to break pre-existing software. Note that you can
 * usually add fields to the END of the channel struct without needing to
 * increment this.
 */
#define VISOR_VHBA_CHANNEL_VERSIONID 2
#define VISOR_VNIC_CHANNEL_VERSIONID 2

/*
 * Everything necessary to handle SCSI & NIC traffic between Guest Partition and
 * IO Partition is defined below.
 */

/*
 * Define the two queues per data channel between iopart and ioguestparts.
 *	IOCHAN_TO_IOPART -- used by guest to 'insert' signals to iopart.
 *	IOCHAN_FROM_IOPART -- used by guest to 'remove' signals from IO part.
 */
#define IOCHAN_TO_IOPART 0
#define IOCHAN_FROM_IOPART 1

/* Size of cdb - i.e., SCSI cmnd */
#define MAX_CMND_SIZE 16

/* Unisys-specific DMA direction values */
enum uis_dma_data_direction {
	UIS_DMA_BIDIRECTIONAL = 0,
	UIS_DMA_TO_DEVICE = 1,
	UIS_DMA_FROM_DEVICE = 2,
	UIS_DMA_NONE = 3
};

#define MAX_SENSE_SIZE 64
#define MAX_PHYS_INFO 64

/*
 * enum net_types - Various types of network packets that can be sent in cmdrsp.
 * @NET_RCV_POST:	Submit buffer to hold receiving incoming packet.
 * @NET_RCV:		visornic -> uisnic. Incoming packet received.
 * @NET_XMIT:		uisnic -> visornic. For outgoing packet.
 * @NET_XMIT_DONE:	visornic -> uisnic. Outgoing packet xmitted.
 * @NET_RCV_ENBDIS:	uisnic -> visornic. Enable/Disable packet reception.
 * @NET_RCV_ENBDIS_ACK:	visornic -> uisnic. Acknowledge enable/disable packet.
 * @NET_RCV_PROMISC:	uisnic -> visornic. Enable/Disable promiscuous mode.
 * @NET_CONNECT_STATUS:	visornic -> uisnic. Indicate the loss or restoration of
 *			a network connection.
 * @NET_MACADDR:	uisnic -> visornic. Indicates the client has requested
 *			to update it's MAC address.
 * @NET_MACADDR_ACK:	MAC address acknowledge.
 */
enum net_types {
	NET_RCV_POST = 0,
	NET_RCV,
	NET_XMIT,
	NET_XMIT_DONE,
	NET_RCV_ENBDIS,
	NET_RCV_ENBDIS_ACK,
	/* Reception */
	NET_RCV_PROMISC,
	NET_CONNECT_STATUS,
	NET_MACADDR,
	NET_MACADDR_ACK,
};

/* Minimum eth data size */
#define ETH_MIN_DATA_SIZE 46
#define ETH_MIN_PACKET_SIZE (ETH_HLEN + ETH_MIN_DATA_SIZE)

/* Maximum data size */
#define VISOR_ETH_MAX_MTU 16384

#ifndef MAX_MACADDR_LEN
/* Number of bytes in MAC address */
#define MAX_MACADDR_LEN 6
#endif

/* Various types of scsi task mgmt commands. */
enum task_mgmt_types {
	TASK_MGMT_ABORT_TASK = 1,
	TASK_MGMT_BUS_RESET,
	TASK_MGMT_LUN_RESET,
	TASK_MGMT_TARGET_RESET,
};

/* Various types of vdisk mgmt commands. */
enum vdisk_mgmt_types {
	VDISK_MGMT_ACQUIRE = 1,
	VDISK_MGMT_RELEASE,
};

struct phys_info {
	u64 pi_pfn;
	u16 pi_off;
	u16 pi_len;
} __packed;

#define MIN_NUMSIGNALS 64

/* Structs with pragma pack. */

struct guest_phys_info {
	u64 address;
	u64 length;
} __packed;

/*
 * struct uisscsi_dest
 * @channel: Bus number.
 * @id:      Target number.
 * @lun:     Logical unit number.
 */
struct uisscsi_dest {
	u32 channel;
	u32 id;
	u32 lun;
} __packed;

struct vhba_wwnn {
	u32 wwnn1;
	u32 wwnn2;
} __packed;

/*
 * struct vhba_config_max
 * @max_channel: Maximum channel for devices attached to this bus.
 * @max_id:	 Maximum SCSI ID for devices attached to bus.
 * @max_lun:	 Maximum SCSI LUN for devices attached to bus.
 * @cmd_per_lun: Maximum number of outstanding commands per LUN.
 * @max_io_size: Maximum io size for devices attached to this bus. Max io size
 *		 is often determined by the resource of the hba.
 *		 e.g Max scatter gather list length * page size / sector size.
 *
 * WARNING: Values stored in this structure must contain maximum counts (not
 * maximum values).
 *
 * 20 bytes
 */
struct vhba_config_max {
	u32 max_channel;
	u32 max_id;
	u32 max_lun;
	u32 cmd_per_lun;
	u32 max_io_size;
} __packed;

/*
 * struct uiscmdrsp_scsi
 *
 * @handle:		The handle to the cmd that was received. Send it back as
 *			is in the rsp packet.
 * @cmnd:		The cdb for the command.
 * @bufflen:		Length of data to be transferred out or in.
 * @guest_phys_entries:	Number of entries in scatter-gather list.
 * @struct gpi_list:	Physical address information for each fragment.
 * @data_dir:		Direction of the data, if any.
 * @struct vdest:	Identifies the virtual hba, id, channel, lun to which
 *			cmd was sent.
 * @linuxstat:		Original Linux status used by Linux vdisk.
 * @scsistat:		The scsi status.
 * @addlstat:		Non-scsi status.
 * @sensebuf:		Sense info in case cmd failed. sensebuf holds the
 *			sense_data struct. See sense_data struct for more
 *			details.
 * @*vdisk:		Pointer to the vdisk to clean up when IO completes.
 * @no_disk_result:	Used to return no disk inquiry result when
 *			no_disk_result is set to 1
 *			scsi.scsistat is SAM_STAT_GOOD
 *			scsi.addlstat is 0
 *			scsi.linuxstat is SAM_STAT_GOOD
 *			That is, there is NO error.
 */
struct uiscmdrsp_scsi {
	u64 handle;
	u8 cmnd[MAX_CMND_SIZE];
	u32 bufflen;
	u16 guest_phys_entries;
	struct guest_phys_info gpi_list[MAX_PHYS_INFO];
	u32 data_dir;
	struct uisscsi_dest vdest;
	/* Needed to queue the rsp back to cmd originator. */
	int linuxstat;
	u8 scsistat;
	u8 addlstat;
#define ADDL_SEL_TIMEOUT 4
	/* The following fields are need to determine the result of command. */
	u8 sensebuf[MAX_SENSE_SIZE];
	void *vdisk;
	int no_disk_result;
} __packed;

/*
 * Defines to support sending correct inquiry result when no disk is
 * configured.
 *
 * From SCSI SPC2 -
 *
 * If the target is not capable of supporting a device on this logical unit, the
 * device server shall set this field to 7Fh (PERIPHERAL QUALIFIER set to 011b
 * and PERIPHERAL DEVICE TYPE set to 1Fh).
 *
 * The device server is capable of supporting the specified peripheral device
 * type on this logical unit. However, the physical device is not currently
 * connected to this logical unit.
 */

/*
 * Peripheral qualifier of 0x3
 * Peripheral type of 0x1f
 * Specifies no device but target present
 */
#define DEV_NOT_CAPABLE 0x7f
/*
 * Peripheral qualifier of 0x1
 * Peripheral type of 0 - disk
 * Specifies device capable, but not present
 */
#define DEV_DISK_CAPABLE_NOT_PRESENT 0x20
/* HiSup = 1; shows support for report luns must be returned for lun 0. */
#define DEV_HISUPPORT 0x10

/*
 * Peripheral qualifier of 0x3
 * Peripheral type of 0x1f
 * Specifies no device but target present
 */
#define DEV_NOT_CAPABLE 0x7f
/*
 * Peripheral qualifier of 0x1
 * Peripheral type of 0 - disk
 * Specifies device capable, but not present
 */
#define DEV_DISK_CAPABLE_NOT_PRESENT 0x20
/* HiSup = 1; shows support for report luns must be returned for lun 0. */
#define DEV_HISUPPORT 0x10

/*
 * NOTE: Linux code assumes inquiry contains 36 bytes. Without checking length
 * in buf[4] some Linux code accesses bytes beyond 5 to retrieve vendor, product
 * and revision. Yikes! So let us always send back 36 bytes, the minimum for
 * inquiry result.
 */
#define NO_DISK_INQUIRY_RESULT_LEN 36
/* 5 bytes minimum for inquiry result */
#define MIN_INQUIRY_RESULT_LEN 5

/* SCSI device version for no disk inquiry result */
/* indicates SCSI SPC2 (SPC3 is 5) */
#define SCSI_SPC2_VER 4

/* Struct and Defines to support sense information. */

/*
 * The following struct is returned in sensebuf field in uiscmdrsp_scsi. It is
 * initialized in exactly the manner that is recommended in Windows (hence the
 * odd values).
 * When set, these fields will have the following values:
 * ErrorCode = 0x70		indicates current error
 * Valid = 1			indicates sense info is valid
 * SenseKey			contains sense key as defined by SCSI specs.
 * AdditionalSenseCode		contains sense key as defined by SCSI specs.
 * AdditionalSenseCodeQualifier	contains qualifier to sense code as defined by
 *				scsi docs.
 * AdditionalSenseLength	contains will be sizeof(sense_data)-8=10.
 */
struct sense_data {
	u8 errorcode:7;
	u8 valid:1;
	u8 segment_number;
	u8 sense_key:4;
	u8 reserved:1;
	u8 incorrect_length:1;
	u8 end_of_media:1;
	u8 file_mark:1;
	u8 information[4];
	u8 additional_sense_length;
	u8 command_specific_information[4];
	u8 additional_sense_code;
	u8 additional_sense_code_qualifier;
	u8 fru_code;
	u8 sense_key_specific[3];
} __packed;

/*
 * struct net_pkt_xmt
 * @len:		    Full length of data in the packet.
 * @num_frags:		    Number of fragments in frags containing data.
 * @struct phys_info frags: Physical page information.
 * @ethhdr:		    The ethernet header.
 * @struct lincsum:	    These are needed for csum at uisnic end.
 *      @valid:	    1 = struct is valid - else ignore.
 *      @hrawoffv:  1 = hwrafoff is valid.
 *      @nhrawoffv: 1 = nhwrafoff is valid.
 *      @protocol:  Specifies packet protocol.
 *      @csum:	    Value used to set skb->csum at IOPart.
 *      @hrawoff:   Value used to set skb->h.raw at IOPart. hrawoff points to
 *		    the start of the TRANSPORT LAYER HEADER.
 *      @nhrawoff:  Value used to set skb->nh.raw at IOPart. nhrawoff points to
 *		    the start of the NETWORK LAYER HEADER.
 *
 * NOTE:
 * The full packet is described in frags but the ethernet header is separately
 * kept in ethhdr so that uisnic doesn't have "MAP" the guest memory to get to
 * the header. uisnic needs ethhdr to determine how to route the packet.
 */
struct net_pkt_xmt {
	int len;
	int num_frags;
	struct phys_info frags[MAX_PHYS_INFO];
	char ethhdr[ETH_HLEN];
	struct {
		u8 valid;
		u8 hrawoffv;
		u8 nhrawoffv;
		__be16 protocol;
		__wsum csum;
		u32 hrawoff;
		u32 nhrawoff;
	} lincsum;
} __packed;

struct net_pkt_xmtdone {
	/* Result of NET_XMIT */
	u32 xmt_done_result;
} __packed;

/*
 * RCVPOST_BUF_SIZE must be at most page_size(4096) - cache_line_size (64) The
 * reason is because dev_skb_alloc which is used to generate RCV_POST skbs in
 * visornic requires that there is "overhead" in the buffer, and pads 16 bytes.
 * Use 1 full cache line size for "overhead" so that transfers are optimized.
 * IOVM requires that a buffer be represented by 1 phys_info structure
 * which can only cover page_size.
 */
#define RCVPOST_BUF_SIZE 4032
#define MAX_NET_RCV_CHAIN \
	((VISOR_ETH_MAX_MTU + ETH_HLEN + RCVPOST_BUF_SIZE - 1) \
	 / RCVPOST_BUF_SIZE)

/* rcv buf size must be large enough to include ethernet data len + ethernet
 * header len - we are choosing 2K because it is guaranteed to be describable.
 */
struct net_pkt_rcvpost {
	/* Physical page information for the single fragment 2K rcv buf */
	struct phys_info frag;
	/*
	 * Ensures that receive posts are returned to the adapter which we sent
	 * them from originally.
	 */
	u64 unique_num;

} __packed;

/*
 * struct net_pkt_rcv
 * @rcv_done_len:	Length of the received data.
 * @numrcvbufs:		Contains the incoming data. Guest side MUST chain these
 *			together.
 * @*rcvbuf:		List of chained rcvbufa. Each entry is a receive buffer
 *			provided by NET_RCV_POST. NOTE: First rcvbuf in the
 *			chain will also be provided in net.buf.
 * @unique_num:
 * @rcvs_dropped_delta:
 *
 * The number of rcvbuf that can be chained is based on max mtu and size of each
 * rcvbuf.
 */
struct net_pkt_rcv {
	u32 rcv_done_len;
	u8 numrcvbufs;
	void *rcvbuf[MAX_NET_RCV_CHAIN];
	u64 unique_num;
	u32 rcvs_dropped_delta;
} __packed;

struct net_pkt_enbdis {
	void *context;
	/* 1 = enable, 0 = disable */
	u16 enable;
} __packed;

struct net_pkt_macaddr {
	void *context;
	/* 6 bytes */
	u8 macaddr[MAX_MACADDR_LEN];
} __packed;

/*
 * struct uiscmdrsp_net - cmd rsp packet used for VNIC network traffic.
 * @enum type:
 * @*buf:
 * @union:
 *	@struct xmt:	 Used for NET_XMIT.
 *	@struct xmtdone: Used for NET_XMIT_DONE.
 *	@struct rcvpost: Used for NET_RCV_POST.
 *	@struct rcv:	 Used for NET_RCV.
 *	@struct enbdis:	 Used for NET_RCV_ENBDIS, NET_RCV_ENBDIS_ACK,
 *			 NET_RCV_PROMSIC, and NET_CONNECT_STATUS.
 *	@struct macaddr:
 */
struct uiscmdrsp_net {
	enum net_types type;
	void *buf;
	union {
		struct net_pkt_xmt xmt;
		struct net_pkt_xmtdone xmtdone;
		struct net_pkt_rcvpost rcvpost;
		struct net_pkt_rcv rcv;
		struct net_pkt_enbdis enbdis;
		struct net_pkt_macaddr macaddr;
	};
} __packed;

/*
 * struct uiscmdrsp_scsitaskmgmt
 * @enum tasktype:	 The type of task.
 * @struct vdest:	 The vdisk for which this task mgmt is generated.
 * @handle:		 This is a handle that the guest has saved off for its
 *			 own use. The handle value is preserved by iopart and
 *			 returned as in task mgmt rsp.
 * @notify_handle:	 For Linux guests, this is a pointer to wait_queue_head
 *			 that a thread is waiting on to see if the taskmgmt
 *			 command has completed. When the rsp is received by
 *			 guest, the thread receiving the response uses this to
 *			 notify the thread waiting for taskmgmt command
 *			 completion. It's value is preserved by iopart and
 *			 returned as in the task mgmt rsp.
 * @notifyresult_handle: This is a handle to the location in the guest where
 *			 the result of the taskmgmt command (result field) is
 *			 saved to when the response is handled. It's value is
 *			 preserved by iopart and returned as is in the task mgmt
 *			 rsp.
 * @result:		 Result of taskmgmt command - set by IOPart.
 */
struct uiscmdrsp_scsitaskmgmt {
	enum task_mgmt_types tasktype;
	struct uisscsi_dest vdest;
	u64 handle;
	u64 notify_handle;
	u64 notifyresult_handle;
	char result;

#define TASK_MGMT_FAILED 0
} __packed;

/*
 * struct uiscmdrsp_disknotify - Used by uissd to send disk add/remove
 *				 notifications to Guest.
 * @add:     0-remove, 1-add.
 * @*v_hba:  Channel info to route msg.
 * @channel: SCSI Path of Disk to added or removed.
 * @id:	     SCSI Path of Disk to added or removed.
 * @lun:     SCSI Path of Disk to added or removed.
 *
 * Note that the vHba pointer is not used by the Client/Guest side.
 */
struct uiscmdrsp_disknotify {
	u8 add;
	void *v_hba;
	u32 channel, id, lun;
} __packed;

/* Keeping cmd and rsp info in one structure for now cmd rsp packet for SCSI */
struct uiscmdrsp {
	char cmdtype;
	/* Describes what type of information is in the struct */
#define CMD_SCSI_TYPE	      1
#define CMD_NET_TYPE	      2
#define CMD_SCSITASKMGMT_TYPE 3
#define CMD_NOTIFYGUEST_TYPE  4
	union {
		struct uiscmdrsp_scsi scsi;
		struct uiscmdrsp_net net;
		struct uiscmdrsp_scsitaskmgmt scsitaskmgmt;
		struct uiscmdrsp_disknotify disknotify;
	};
	/* Send the response when the cmd is done (scsi and scsittaskmgmt). */
	void *private_data;
	/* General Purpose Queue Link */
	struct uiscmdrsp *next;
	/* Pointer to the nextactive commands */
	struct uiscmdrsp *activeQ_next;
	/* Pointer to the prevactive commands */
	struct uiscmdrsp *activeQ_prev;
} __packed;

/* total = 28 bytes */
struct iochannel_vhba {
	/* 8 bytes */
	struct vhba_wwnn wwnn;
	/* 20 bytes */
	struct vhba_config_max max;
} __packed;

struct iochannel_vnic {
	/* 6 bytes */
	u8 macaddr[6];
	/* 4 bytes */
	u32 num_rcv_bufs;
	/* 4 bytes */
	u32 mtu;
	/* 16 bytes */
	guid_t zone_guid;
} __packed;

/*
 * This is just the header of the IO channel. It is assumed that directly after
 * this header there is a large region of memory which contains the command and
 * response queues as specified in cmd_q and rsp_q SIGNAL_QUEUE_HEADERS.
 */
struct visor_io_channel {
	struct channel_header channel_header;
	struct signal_queue_header cmd_q;
	struct signal_queue_header rsp_q;
	union {
		struct iochannel_vhba vhba;
		struct iochannel_vnic vnic;
	} __packed;

#define MAX_CLIENTSTRING_LEN 1024
	/* client_string is NULL termimated so holds max-1 bytes */
	 u8 client_string[MAX_CLIENTSTRING_LEN];
} __packed;

/* INLINE functions for initializing and accessing I/O data channels. */
#define SIZEOF_CMDRSP (64 * DIV_ROUND_UP(sizeof(struct uiscmdrsp), 64))

/* Use 4K page sizes when passing page info between Guest and IOPartition. */
#define PI_PAGE_SIZE 0x1000
#define PI_PAGE_MASK 0x0FFF

/* __IOCHANNEL_H__ */
#endif