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
/*	$NetBSD: arcmsrvar.h,v 1.15 2016/06/12 02:16:15 christos Exp $ */
/*	Derived from $OpenBSD: arc.c,v 1.68 2007/10/27 03:28:27 dlg Exp $ */

/*
 * Copyright (c) 2007 Juan Romero Pardines <xtraeme@netbsd.org>
 * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _PCI_ARCMSRVAR_H_
#define _PCI_ARCMSRVAR_H_

#define ARC_PCI_BAR			PCI_MAPREG_START

#define ARC_REG_INB_MSG0		0x0010
#define  ARC_REG_INB_MSG0_NOP			(0x00000000)
#define  ARC_REG_INB_MSG0_GET_CONFIG		(0x00000001)
#define  ARC_REG_INB_MSG0_SET_CONFIG		(0x00000002)
#define  ARC_REG_INB_MSG0_ABORT_CMD		(0x00000003)
#define  ARC_REG_INB_MSG0_STOP_BGRB		(0x00000004)
#define  ARC_REG_INB_MSG0_FLUSH_CACHE		(0x00000005)
#define  ARC_REG_INB_MSG0_START_BGRB		(0x00000006)
#define  ARC_REG_INB_MSG0_CHK331PENDING		(0x00000007)
#define  ARC_REG_INB_MSG0_SYNC_TIMER		(0x00000008)
#define ARC_REG_INB_MSG1		0x0014
#define ARC_REG_OUTB_ADDR0		0x0018
#define ARC_REG_OUTB_ADDR1		0x001c
#define  ARC_REG_OUTB_ADDR1_FIRMWARE_OK		(1<<31)
#define ARC_REG_INB_DOORBELL		0x0020
#define  ARC_REG_INB_DOORBELL_WRITE_OK		(1<<0)
#define  ARC_REG_INB_DOORBELL_READ_OK		(1<<1)
#define ARC_REG_OUTB_DOORBELL		0x002c
#define  ARC_REG_OUTB_DOORBELL_WRITE_OK		(1<<0)
#define  ARC_REG_OUTB_DOORBELL_READ_OK		(1<<1)
#define ARC_REG_INTRSTAT		0x0030
#define  ARC_REG_INTRSTAT_MSG0			(1<<0)
#define  ARC_REG_INTRSTAT_MSG1			(1<<1)
#define  ARC_REG_INTRSTAT_DOORBELL		(1<<2)
#define  ARC_REG_INTRSTAT_POSTQUEUE		(1<<3)
#define  ARC_REG_INTRSTAT_PCI			(1<<4)
#define ARC_REG_INTRMASK		0x0034
#define  ARC_REG_INTRMASK_MSG0			(1<<0)
#define  ARC_REG_INTRMASK_MSG1			(1<<1)
#define  ARC_REG_INTRMASK_DOORBELL		(1<<2)
#define  ARC_REG_INTRMASK_POSTQUEUE		(1<<3)
#define  ARC_REG_INTRMASK_PCI			(1<<4)
#define ARC_REG_POST_QUEUE		0x0040
#define  ARC_REG_POST_QUEUE_ADDR_SHIFT		5
#define  ARC_REG_POST_QUEUE_IAMBIOS		(1<<30)
#define  ARC_REG_POST_QUEUE_BIGFRAME		(1<<31)
#define ARC_REG_REPLY_QUEUE		0x0044
#define  ARC_REG_REPLY_QUEUE_ADDR_SHIFT		5
#define  ARC_REG_REPLY_QUEUE_ERR		(1<<28)
#define  ARC_REG_REPLY_QUEUE_IAMBIOS		(1<<30)
#define ARC_REG_MSGBUF			0x0a00
#define  ARC_REG_MSGBUF_LEN		1024
#define ARC_REG_IOC_WBUF_LEN		0x0e00
#define ARC_REG_IOC_WBUF		0x0e04
#define ARC_REG_IOC_RBUF_LEN		0x0f00
#define ARC_REG_IOC_RBUF		0x0f04
#define  ARC_REG_IOC_RWBUF_MAXLEN	124 /* for both RBUF and WBUF */

struct arc_msg_firmware_info {
	uint32_t	signature;
#define ARC_FWINFO_SIGNATURE_GET_CONFIG		(0x87974060)
	uint32_t	request_len;
	uint32_t	queue_len;
	uint32_t	sdram_size;
	uint32_t	sata_ports;
	uint8_t		vendor[40];
	uint8_t		model[8];
	uint8_t		fw_version[16];
	uint8_t		device_map[16];
} __packed;

struct arc_msg_scsicmd {
	uint8_t		bus;
	uint8_t		target;
	uint8_t		lun;
	uint8_t		function;

	uint8_t		cdb_len;
	uint8_t		sgl_len;
	uint8_t		flags;
#define ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512	(1<<0)
#define ARC_MSG_SCSICMD_FLAG_FROM_BIOS		(1<<1)
#define ARC_MSG_SCSICMD_FLAG_WRITE		(1<<2)
#define ARC_MSG_SCSICMD_FLAG_SIMPLEQ		(0x00)
#define ARC_MSG_SCSICMD_FLAG_HEADQ		(0x08)
#define ARC_MSG_SCSICMD_FLAG_ORDERQ		(0x10)
	uint8_t		reserved;

	uint32_t	context;
	uint32_t	data_len;

#define ARC_MSG_CDBLEN				16
	uint8_t		cdb[ARC_MSG_CDBLEN];

	uint8_t		status;
#define ARC_MSG_STATUS_SELTIMEOUT		0xf0
#define ARC_MSG_STATUS_ABORTED			0xf1
#define ARC_MSG_STATUS_INIT_FAIL		0xf2
#define ARC_MSG_SENSELEN			15
	uint8_t		sense_data[ARC_MSG_SENSELEN];

	/* followed by an sgl */
} __packed;

struct arc_sge {
	uint32_t	sg_hdr;
#define ARC_SGE_64BIT				(1<<24)
	uint32_t	sg_lo_addr;
	uint32_t	sg_hi_addr;
} __packed;

#define ARC_MAX_TARGET		16
#define ARC_MAX_LUN		8
#define ARC_MAX_IOCMDLEN	512
#define ARC_BLOCKSIZE		512

/* 
 * the firmware deals with up to 256 or 512 byte command frames.
 */

/* 
 * sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 38) == 508.
 */
#define ARC_SGL_MAXLEN		38
/* 
 * sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 17) == 252.
 */
#define ARC_SGL_256LEN		17

struct arc_io_cmd {
	struct arc_msg_scsicmd	cmd;
	struct arc_sge		sgl[ARC_SGL_MAXLEN];
} __packed;

/* 
 * definitions of the firmware commands sent via the doorbells.
 */
struct arc_fw_hdr {
	uint8_t		byte1;
	uint8_t		byte2;
	uint8_t		byte3;
} __packed;

struct arc_fw_bufhdr {
	struct arc_fw_hdr	hdr;
	uint16_t		len;
} __packed;

/* Firmware command codes */
#define ARC_FW_CHECK_PASS	0x14	/* opcode + 1 byte length + password */
#define ARC_FW_GETEVENTS	0x1a	/* opcode + 1 byte for page 0/1/2/3 */
#define ARC_FW_GETHWMON		0x1b	/* opcode + arc_fw_hwmon */
#define ARC_FW_RAIDINFO		0x20	/* opcode + raid# */
#define ARC_FW_VOLINFO		0x21	/* opcode + vol# */
#define ARC_FW_DISKINFO		0x22	/* opcode + physdisk# */
#define ARC_FW_SYSINFO		0x23	/* opcode. reply is fw_sysinfo */
#define ARC_FW_CLEAREVENTS	0x24	/* opcode only */
#define ARC_FW_MUTE_ALARM	0x30	/* opcode only */
#define ARC_FW_SET_ALARM	0x31	/* opcode + 1 byte for setting */
#define  ARC_FW_SET_ALARM_DISABLE		0x00
#define  ARC_FW_SET_ALARM_ENABLE		0x01
#define ARC_FW_SET_PASS		0x32	/* opcode + 1 byte length + password */
#define ARC_FW_REBUILD_PRIO	0x34	/* Rebuild priority for disks */
#define  ARC_FW_REBUILD_PRIO_ULTRALOW		(1<<0)
#define  ARC_FW_REBUILD_PRIO_LOW		(1<<1)
#define  ARC_FW_REBUILD_PRIO_NORMAL		(1<<2)
#define  ARC_FW_REBUILD_PRIO_HIGH		(1<<3)
#define ARC_FW_SET_MAXATA_MODE	0x35	/* opcode + 1 byte mode */
#define  ARC_FW_SET_MAXATA_MODE_133		(1<<0)
#define  ARC_FW_SET_MAXATA_MODE_100		(1<<1)
#define  ARC_FW_SET_MAXATA_MODE_66		(1<<2)
#define  ARC_FW_SET_MAXATA_MODE_33		(1<<3)
#define ARC_FW_NOP		0x38	/* opcode only */
/*
 * Structure for ARC_FW_CREATE_PASSTHRU:
 *
 * byte 2	command code 0x40
 * byte 3	device #
 * byte 4	scsi channel (0/1)
 * byte 5	scsi id (0/15)
 * byte 6	scsi lun (0/7)
 * byte 7	tagged queue (1 enabled)
 * byte 8	cache mode (1 enabled)
 * byte 9	max speed ((0/1/2/3/4 -> 33/66/100/133/150)
 */
#define ARC_FW_CREATE_PASSTHRU	0x40
#define ARC_FW_DELETE_PASSTHRU	0x42	/* opcode + device# */

/*
 * Structure for ARC_FW_CREATE_RAIDSET:
 *
 * byte 2	command code 0x50
 * byte 3-6	device mask
 * byte 7-22	raidset name (byte 7 == 0 use default)
 */	
#define ARC_FW_CREATE_RAIDSET	0x50
#define ARC_FW_DELETE_RAIDSET	0x51	/* opcode + raidset# */
#define ARC_FW_CREATE_HOTSPARE	0x54	/* opcode + 4 bytes device mask */
#define ARC_FW_DELETE_HOTSPARE	0x55	/* opcode + 4 bytes device mask */

/*
 * Structure for ARC_FW_CREATE_VOLUME/ARC_FW_MODIFY_VOLUME:
 *
 * byte 2 	command code 0x60
 * byte 3 	raidset#
 * byte 4-19 	volume set name (byte 4 == 0 use default)
 * byte 20-27	volume capacity in blocks
 * byte 28	raid level
 * byte 29	stripe size
 * byte 30	channel
 * byte 31	ID
 * byte 32	LUN
 * byte 33	1 enable tag queuing
 * byte 33	1 enable cache
 * byte 35	speed 0/1/2/3/4 -> 33/66/100/133/150
 * byte 36	1 for quick init (only for CREATE_VOLUME)
 */
#define ARC_FW_CREATE_VOLUME	0x60
#define ARC_FW_MODIFY_VOLUME 	0x61
#define ARC_FW_DELETE_VOLUME	0x62	/* opcode + vol# */
#define ARC_FW_START_CHECKVOL	0x63	/* opcode + vol# */
#define ARC_FW_STOP_CHECKVOL	0x64	/* opcode only */

/* Status codes for the firmware command codes */
#define ARC_FW_CMD_OK		0x41
#define ARC_FW_CMD_RAIDINVAL	0x42
#define ARC_FW_CMD_VOLINVAL	0x43
#define ARC_FW_CMD_NORAID	0x44
#define ARC_FW_CMD_NOVOLUME	0x45
#define ARC_FW_CMD_NOPHYSDRV	0x46
#define ARC_FW_CMD_PARAM_ERR	0x47
#define ARC_FW_CMD_UNSUPPORTED	0x48
#define ARC_FW_CMD_DISKCFG_CHGD	0x49
#define ARC_FW_CMD_PASS_INVAL	0x4a
#define ARC_FW_CMD_NODISKSPACE	0x4b
#define ARC_FW_CMD_CHECKSUM_ERR	0x4c
#define ARC_FW_CMD_PASS_REQD	0x4d

struct arc_fw_hwmon {
	uint8_t 	nfans;
	uint8_t 	nvoltages;
	uint8_t 	ntemps;
	uint8_t 	npower;
	uint16_t 	fan0;		/* RPM */
	uint16_t 	fan1;		/* RPM */
	uint16_t 	voltage_orig0;	/* original value * 1000 */
	uint16_t 	voltage_val0;	/* value */
	uint16_t 	voltage_orig1;	/* original value * 1000 */
	uint16_t 	voltage_val1;	/* value */
	uint16_t 	voltage_orig2;
	uint16_t 	voltage_val2;
	uint8_t 	temp0;
	uint8_t 	temp1;
	uint8_t 	pwr_indicator;	/* (bit0 : power#0, bit1 : power#1) */
	uint8_t 	ups_indicator;
} __packed;

struct arc_fw_comminfo {
	uint8_t		baud_rate;
	uint8_t		data_bits;
	uint8_t		stop_bits;
	uint8_t		parity;
	uint8_t		flow_control;
} __packed;

struct arc_fw_scsiattr {
	uint8_t		channel;	/* channel for SCSI target (0/1) */
	uint8_t		target;
	uint8_t		lun;
	uint8_t		tagged;
	uint8_t		cache;
	uint8_t		speed;
} __packed;

struct arc_fw_raidinfo {
	uint8_t		set_name[16];
	uint32_t	capacity;
	uint32_t	capacity2;
	uint32_t	fail_mask;
	uint8_t		device_array[32];
	uint8_t		member_devices;
	uint8_t		new_member_devices;
	uint8_t		raid_state;
	uint8_t		volumes;
	uint8_t		volume_list[16];
	uint8_t		reserved1[3];
	uint8_t		free_segments;
	uint32_t	raw_stripes[8];
	uint8_t		reserved2[12];
} __packed;

struct arc_fw_volinfo {
	uint8_t		set_name[16];
	uint32_t	capacity;
	uint32_t	capacity2;
	uint32_t	fail_mask;
	uint32_t	stripe_size;	/* in blocks */
	uint32_t	new_fail_mask;
	uint32_t	new_stripe_size;
	uint32_t	volume_status;
#define ARC_FW_VOL_STATUS_NORMAL	0x00
#define ARC_FW_VOL_STATUS_INITTING	(1<<0)
#define ARC_FW_VOL_STATUS_FAILED	(1<<1)
#define ARC_FW_VOL_STATUS_MIGRATING	(1<<2)
#define ARC_FW_VOL_STATUS_REBUILDING	(1<<3)
#define ARC_FW_VOL_STATUS_NEED_INIT	(1<<4)
#define ARC_FW_VOL_STATUS_NEED_MIGRATE	(1<<5)
#define ARC_FW_VOL_STATUS_INIT_FLAG	(1<<6)
#define ARC_FW_VOL_STATUS_NEED_REGEN	(1<<7)
#define ARC_FW_VOL_STATUS_CHECKING	(1<<8)
#define ARC_FW_VOL_STATUS_NEED_CHECK	(1<<9)
	uint32_t	progress;
	struct arc_fw_scsiattr	scsi_attr;
	uint8_t		member_disks;
	uint8_t		raid_level;
#define ARC_FW_VOL_RAIDLEVEL_0		0x00
#define ARC_FW_VOL_RAIDLEVEL_1		0x01
#define ARC_FW_VOL_RAIDLEVEL_3		0x02
#define ARC_FW_VOL_RAIDLEVEL_5		0x03
#define ARC_FW_VOL_RAIDLEVEL_6		0x04
#define ARC_FW_VOL_RAIDLEVEL_PASSTHRU	0x05
	uint8_t		new_member_disks;
	uint8_t		new_raid_level;
	uint8_t		raid_set_number;
	uint8_t		reserved[5];
} __packed;

struct arc_fw_diskinfo {
	uint8_t		model[40];
	uint8_t		serial[20];
	uint8_t		firmware_rev[8];
	uint32_t	capacity;
	uint32_t	capacity2;
	uint8_t		device_state;
#define ARC_FW_DISK_NORMAL	0x88	/* disk attached/initialized */
#define ARC_FW_DISK_PASSTHRU	0x8a	/* pass through disk in normal state */
#define ARC_FW_DISK_HOTSPARE	0xa8	/* hotspare disk in normal state */
#define ARC_FW_DISK_UNUSED	0xc8	/* free/unused disk in normal state */
#define ARC_FW_DISK_FAILED	0x10	/* disk in failed state */
	uint8_t		pio_mode;
	uint8_t		current_udma_mode;
	uint8_t		udma_mode;
	uint8_t		drive_select;
	uint8_t		raid_number;	/* 0xff unowned */
	struct arc_fw_scsiattr	scsi_attr;
	uint8_t		reserved[40];
} __packed;

struct arc_fw_sysinfo {
	uint8_t		vendor_name[40];
	uint8_t		serial_number[16];
	uint8_t		firmware_version[16];
	uint8_t		boot_version[16];
	uint8_t		mb_version[16];
	uint8_t		model_name[8];

	uint8_t		local_ip[4];
	uint8_t		current_ip[4];

	uint32_t	time_tick;
	uint32_t	cpu_speed;
	uint32_t	icache;
	uint32_t	dcache;
	uint32_t	scache;
	uint32_t	memory_size;
	uint32_t	memory_speed;
	uint32_t	events;

	uint8_t		gsiMacAddress[6];
	uint8_t		gsiDhcp;

	uint8_t		alarm;
	uint8_t		channel_usage;
	uint8_t		max_ata_mode;
	uint8_t		sdram_ecc;
	uint8_t		rebuild_priority;
	struct arc_fw_comminfo	comm_a;
	struct arc_fw_comminfo	comm_b;
	uint8_t		ide_channels;
	uint8_t		scsi_host_channels;
	uint8_t		ide_host_channels;
	uint8_t		max_volume_set;
	uint8_t		max_raid_set;
	uint8_t		ether_port;
	uint8_t		raid6_engine;
	uint8_t		reserved[75];
} __packed;

/*
 * autconf(9) glue.
 */
struct arc_ccb;
TAILQ_HEAD(arc_ccb_list, arc_ccb);

typedef struct arc_edata {
	envsys_data_t	arc_sensor;
	int		arc_diskid;
	int		arc_volid;
} arc_edata_t;

struct arc_softc {
	struct scsipi_channel	sc_chan;
	struct scsipi_adapter	sc_adapter;

	pci_chipset_tag_t	sc_pc;
	pcitag_t		sc_tag;

	bus_space_tag_t		sc_iot;
	bus_space_handle_t	sc_ioh;
	bus_size_t		sc_ios;
	bus_dma_tag_t		sc_dmat;

	void			*sc_ih;

	int			sc_req_count;

	struct arc_dmamem	*sc_requests;
	struct arc_ccb		*sc_ccbs;
	struct arc_ccb_list	sc_ccb_free;

	struct lwp		*sc_lwp;
	volatile int		sc_talking;
	kmutex_t		sc_mutex;
	kcondvar_t		sc_condvar;
	krwlock_t		sc_rwlock;

	struct sysmon_envsys	*sc_sme;
	arc_edata_t		*sc_arc_sensors;
	int			sc_nsensors;

	size_t			sc_maxraidset;	/* max raid sets */
	size_t 			sc_maxvolset;	/* max volume sets */
	size_t 			sc_cchans;	/* connected channels */

	device_t		sc_dev;		/* self */
	device_t		sc_scsibus_dv;
};

/* 
 * wrap up the bus_dma api.
 */
struct arc_dmamem {
	bus_dmamap_t		adm_map;
	bus_dma_segment_t	adm_seg;
	size_t			adm_size;
	void			*adm_kva;
};
#define ARC_DMA_MAP(_adm)	((_adm)->adm_map)
#define ARC_DMA_DVA(_adm)	((_adm)->adm_map->dm_segs[0].ds_addr)
#define ARC_DMA_KVA(_adm)	((void *)(_adm)->adm_kva)

/* 
 * stuff to manage a scsi command.
 */
struct arc_ccb {
	struct arc_softc	*ccb_sc;
	int			ccb_id;

	struct scsipi_xfer	*ccb_xs;

	bus_dmamap_t		ccb_dmamap;
	bus_addr_t		ccb_offset;
	struct arc_io_cmd	*ccb_cmd;
	uint32_t		ccb_cmd_post;

	TAILQ_ENTRY(arc_ccb)	ccb_link;
};

#endif /* ! _PCI_ARCMSRVAR_H_ */