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