xref: /illumos-gate/usr/src/test/i2c-tests/tests/i2cadm/i2cadm-io.ksh (revision 0cbe48189888d02563dba9c90132ac391ba233b6)
1#! /usr/bin/ksh
2#
3# This file and its contents are supplied under the terms of the
4# Common Development and Distribution License ("CDDL"), version 1.0.
5# You may only use this file in accordance with the terms of version
6# 1.0 of the CDDL.
7#
8# A full copy of the text of the CDDL should have accompanied this
9# source.  A copy of the CDDL is also available via the Internet at
10# http://www.illumos.org/license/CDDL.
11#
12
13#
14# Copyright 2025 Oxide Computer Company
15#
16
17#
18# Perform various I/O tests against our virtual devices. Several of the at24c
19# devices have content pre-loaded into them with parts of Tolkienian rhymes. We
20# can only perform SMBus operations against the at24c08 as the others require a
21# two byte I/O pattern.
22#
23
24. $(dirname $0)/common.ksh
25
26#
27# Variable where the results of performing I/O will be sent.
28#
29io_data=
30io_eedev=
31io_dd=
32
33function i2c_at24c_to_eedev
34{
35	typeset path="$1"
36	typeset drv="$2"
37	typeset part=
38
39	part=$(i2cadm device list -Hpo instance $path | sed "s/$drv/$drv\//")
40	[[ -z "$part" ]] && fatal "failed to translate $path"
41	io_eedev="/dev/eeprom/$part/eeprom"
42}
43
44function do_io
45{
46	io_data=$($I2CADM io -o /dev/stdout $@)
47	if (( $? != 0 )); then
48		fatal "failed to perform I/O $@"
49	fi
50}
51
52function check_io
53{
54	typeset desc="$1"
55	typeset targ="$2"
56	shift
57	shift
58
59	do_io $@
60	if [[ "$targ" != "$io_data" ]]; then
61		warn "$desc: I/O mismatch: found [$io_data], expected [$targ]"
62	else
63		printf "TEST PASSED: %s\n" "$desc"
64	fi
65}
66
67function get_dd
68{
69	typeset off="$1"
70	typeset len="$2"
71
72	[[ -z "$io_eedev" ]] && fatal "missing required eedev path"
73
74	io_dd=$(dd iseek=$off bs=1 count="$len" if=$io_eedev of=/dev/stdout \
75	    status=none)
76	if (( $? != 0 )); then
77		fatal "failed to dd on $io_eedev"
78	fi
79}
80
81function compare_io_dd
82{
83	typeset desc="$1"
84
85	if [[ "$io_dd" != "$io_data" ]]; then
86		warn "$desc: dd and i2c disagree, found $io_dd (dd) and " \
87		"$io_data (i2c)"
88	else
89		printf "TEST PASSED: %s\n" "$desc"
90	fi
91}
92
93function write_io
94{
95	typeset desc="$1"
96	typeset targ="$2"
97	typeset len="$3"
98	typeset off="$4"
99	typeset dev="$5"
100	shift
101	shift
102	shift
103	shift
104	shift
105
106	#
107	# Bump len by one to write the offset
108	#
109	if ! $I2CADM io -d "$dev" $@; then
110		fatal "failed to perform I/O $@"
111	fi
112
113	check_io "$desc" "$targ" -d $dev -w 1 -r $len $off
114}
115
116#
117# First Verify that basic I/O makes sense.
118#
119check_io "Three Rings i2c" "Three rings" -d i2csim0/0/0x20 -r 11 -w 1 0x00
120check_io "Three Rings offset i2c" "rings" -d i2csim0/0/0x20 -r 5 -w 1 0x06
121check_io "Three Rings recv-u8 (1)" " " -d i2csim0/0/0x20 -m recv-u8
122check_io "Three Rings recv-u8 (2)" "f" -d i2csim0/0/0x20 -m recv-u8
123check_io "Three Rings read-u8 (1)" "E" -d i2csim0/0/0x20 -m read-u8 -c 0x10
124check_io "Three Rings read-u8 (2)" "-" -d i2csim0/0/0x20 -m read-u8 -c 0x15
125check_io "Three Rings read-u16" "El" -d i2csim0/0/0x20 -m read-u16 -c 0x10
126check_io "Three Rings read-u32" "king" -d i2csim0/0/0x20 -m read-u32 -c 0x16
127check_io "Three Rings read-u64" "the sky," -d i2csim0/0/0x20 -m read-u64 -c 0x23
128check_io "Three Rings read-block-i2c" "Elven-kings, und" -d i2csim0/0/0x20 \
129    -m read-block-i2c -c 0x10 -r 0x10
130check_io "Three Rings i2c (all)" "Three rings for Elven-kings, under the sky," \
131    -d i2csim0/0/0x20 -r 0x2b -w 1 0x00
132check_io "Three Rings block (all)" "Three rings for Elven-kings, under the sky," \
133    -d i2csim0/0/0x20 -m read-block-i2c -c 0x00 -r 0x2b
134
135#
136# Next, we want to verify that using /dev/eeprom and the io mechanism is
137# similar. First we'll verify reads across all the different segments of the
138# at24c08.
139#
140i2c_at24c_to_eedev i2csim0/0/0x20 at24c
141get_dd 0 43
142compare_io_dd "at24cs08 block 0 comparison"
143
144check_io "Seven i2c (all)" "Seven for the Dwarf-lords in their halls of stone," \
145    -d i2csim0/0 -a 0x21 -r 0x32 -w 1 0x00
146get_dd 256 50
147compare_io_dd "at24cs08 block 1 comparison"
148
149check_io "Nine i2c (all)" "Nine for Moral Men, doomed to die," \
150    -d i2csim0/0 -a 0x22 -r 0x22 -w 1 0x00
151get_dd 512 34
152compare_io_dd "at24cs08 block 2 comparison"
153
154check_io "One i2c (all)" "One for the dark Lord on his dark throne" \
155    -d i2csim0/0 -a 0x23 -r 0x28 -w 1 0x00
156get_dd 768 40
157compare_io_dd "at24cs08 block 3 comparison"
158
159#
160# Now it's time to do our write testing. One caveat with the at24c08 is that
161# writes that are larger than a 16-byte segment will wrap and start over at the
162# beginning. This means that we'll need to be a bit more mindful of our offsets.
163# We start an offset of 128 (0x80) to avoid our existing data.
164#
165write_io "i2c write" "All that is gold" 16 0x80 i2csim0/0/0x20 -w 17 0x80 0x41 \
166    0x6c 0x6c 0x20 0x74 0x68 0x61 0x74 0x20 0x69 0x73 0x20 0x67 0x6f 0x6c 0x64
167get_dd 128 16
168compare_io_dd "All that is gold i2c write"
169write_io "write-u8" " " 1 0x90 i2csim0/0/0x20 -m write-u8 -c 0x90 0x20
170write_io "write-u16" "do" 2 0x91 i2csim0/0/0x20 -m write-u16 -c 0x91 0x6f64
171write_io "write-u8" "e" 1 0x93 i2csim0/0/0x20 -m write-u8 -c 0x93 0x65
172write_io "write-u32" "s no" 4 0x94 i2csim0/0/0x20 -m write-u32 -c 0x94 \
173    0x6f6e2073
174write_io "write-u64" "t glitte" 8 0x98 i2csim0/0/0x20 -m write-u64 -c 0x98 \
175    0x657474696c672074
176check_io "write stanza 2 (block)" " does not glitte" -d i2csim0/0/0x20 \
177    -m read-block-i2c -c 0x90 -r 0x10
178get_dd 144 16
179compare_io_dd "does not glitter i2c write"
180
181#
182# Do a 16 byte block write over the existing portion and show that it
183# overwrites. Do this manually as the general I/O check logic is going to have
184# trouble with this. This takes the string 'r, Not all those' and offsets it 4
185# bytes.
186#
187if ! $I2CADM io -d i2csim0/0/0x20 -m write-block-i2c -c 0x94 -w 16 \
188    0x72 0x2c 0x20 0x4e 0x6f 0x74 0x20 0x61 0x6c 0x6c 0x20 0x74 0x68 0x6f 0x73 \
189    0x65; then
190	fatal "failed to perform i2c block write"
191fi
192check_io "write stanza 3 (block)" "hoser, Not all t" -d i2csim0/0/0x20 \
193    -m read-block-i2c -c 0x90 -r 0x10
194get_dd 144 16
195compare_io_dd "i2c block overwrite"
196
197if (( i2c_exit == 0 )); then
198	printf "All tests passed successfully!\n"
199fi
200
201exit $i2c_exit
202