~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/gpio/gpio-sloppy-logic-analyzer.sh

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/gpio/gpio-sloppy-logic-analyzer.sh (Architecture i386) and /tools/gpio/gpio-sloppy-logic-analyzer.sh (Architecture sparc)


  1 #!/bin/sh -eu                                       1 #!/bin/sh -eu
  2 # SPDX-License-Identifier: GPL-2.0                  2 # SPDX-License-Identifier: GPL-2.0
  3 #                                                   3 #
  4 # Helper script for the Linux Kernel GPIO slop      4 # Helper script for the Linux Kernel GPIO sloppy logic analyzer
  5 #                                                   5 #
  6 # Copyright (C) Wolfram Sang <wsa@sang-engineer      6 # Copyright (C) Wolfram Sang <wsa@sang-engineering.com>
  7 # Copyright (C) Renesas Electronics Corporatio      7 # Copyright (C) Renesas Electronics Corporation
  8                                                     8 
  9 samplefreq=1000000                                  9 samplefreq=1000000
 10 numsamples=250000                                  10 numsamples=250000
 11 cpusetdefaultdir='/sys/fs/cgroup'                  11 cpusetdefaultdir='/sys/fs/cgroup'
 12 cpusetprefix='cpuset.'                             12 cpusetprefix='cpuset.'
 13 debugdir='/sys/kernel/debug'                       13 debugdir='/sys/kernel/debug'
 14 ladirname='gpio-sloppy-logic-analyzer'             14 ladirname='gpio-sloppy-logic-analyzer'
 15 outputdir="$PWD"                                   15 outputdir="$PWD"
 16 neededcmds='taskset zip'                           16 neededcmds='taskset zip'
 17 max_chans=8                                        17 max_chans=8
 18 duration=                                          18 duration=
 19 initcpu=                                           19 initcpu=
 20 listinstances=0                                    20 listinstances=0
 21 lainstance=                                        21 lainstance=
 22 lasysfsdir=                                        22 lasysfsdir=
 23 triggerdat=                                        23 triggerdat=
 24 trigger_bindat=                                    24 trigger_bindat=
 25 progname="${0##*/}"                                25 progname="${0##*/}"
 26 print_help()                                       26 print_help()
 27 {                                                  27 {
 28         cat << EOF                                 28         cat << EOF
 29 $progname - helper script for the Linux Kernel     29 $progname - helper script for the Linux Kernel Sloppy GPIO Logic Analyzer
 30 Available options:                                 30 Available options:
 31         -c|--cpu <n>: which CPU to isolate for     31         -c|--cpu <n>: which CPU to isolate for sampling. Only needed once. Default <1>.
 32                       Remember that a more pow     32                       Remember that a more powerful CPU gives you higher sampling speeds.
 33                       Also CPU0 is not recomme     33                       Also CPU0 is not recommended as it usually does extra bookkeeping.
 34         -d|--duration-us <SI-n>: number of mic     34         -d|--duration-us <SI-n>: number of microseconds to sample. Overrides -n, no default value.
 35         -h|--help: print this help                 35         -h|--help: print this help
 36         -i|--instance <str>: name of the logic     36         -i|--instance <str>: name of the logic analyzer in case you have multiple instances. Default
 37                              to first instance     37                              to first instance found
 38         -k|--kernel-debug-dir <str>: path to t     38         -k|--kernel-debug-dir <str>: path to the kernel debugfs mountpoint. Default: <$debugdir>
 39         -l|--list-instances: list all availabl     39         -l|--list-instances: list all available instances
 40         -n|--num_samples <SI-n>: number of sam     40         -n|--num_samples <SI-n>: number of samples to acquire. Default <$numsamples>
 41         -o|--output-dir <str>: directory to pu     41         -o|--output-dir <str>: directory to put the result files. Default: current dir
 42         -s|--sample_freq <SI-n>: desired sampl     42         -s|--sample_freq <SI-n>: desired sampling frequency. Might be capped if too large.
 43                                  Default: <100     43                                  Default: <1000000>
 44         -t|--trigger <str>: pattern to use as      44         -t|--trigger <str>: pattern to use as trigger. <str> consists of two-char pairs. First
 45                             char is channel nu     45                             char is channel number starting at "1". Second char is trigger level:
 46                             "L" - low; "H" - h     46                             "L" - low; "H" - high; "R" - rising; "F" - falling
 47                             These pairs can be     47                             These pairs can be combined with "+", so "1H+2F" triggers when probe 1
 48                             is high while prob     48                             is high while probe 2 has a falling edge. You can have multiple triggers
 49                             combined with ",".     49                             combined with ",". So, "1H+2F,1H+2R" is like the example before but it
 50                             waits for a rising     50                             waits for a rising edge on probe 2 while probe 1 is still high after the
 51                             first trigger has      51                             first trigger has been met.
 52                             Trigger data will      52                             Trigger data will only be used for the next capture and then be erased.
 53                                                    53 
 54 <SI-n> is an integer value where SI units "T",     54 <SI-n> is an integer value where SI units "T", "G", "M", "K" are recognized, e.g. '1M500K' is 1500000.
 55                                                    55 
 56 Examples:                                          56 Examples:
 57 Samples $numsamples values at 1MHz with an alr     57 Samples $numsamples values at 1MHz with an already prepared CPU or automatically prepares CPU1 if needed,
 58 use the first logic analyzer instance found:       58 use the first logic analyzer instance found:
 59         '$progname'                                59         '$progname'
 60 Samples 50us at 2MHz waiting for a falling edg     60 Samples 50us at 2MHz waiting for a falling edge on channel 2. CPU and instance as above:
 61         '$progname -d 50 -s 2M -t "2F"'            61         '$progname -d 50 -s 2M -t "2F"'
 62                                                    62 
 63 Note that the process exits after checking all     63 Note that the process exits after checking all parameters but a sub-process still works in
 64 the background. The result is only available o     64 the background. The result is only available once the sub-process finishes.
 65                                                    65 
 66 Result is a .sr file to be consumed with Pulse     66 Result is a .sr file to be consumed with PulseView from the free Sigrok project. It is
 67 a zip file which also contains the binary samp     67 a zip file which also contains the binary sample data which may be consumed by others.
 68 The filename is the logic analyzer instance na     68 The filename is the logic analyzer instance name plus a since-epoch timestamp.
 69 EOF                                                69 EOF
 70 }                                                  70 }
 71                                                    71 
 72 fail()                                             72 fail()
 73 {                                                  73 {
 74         echo "$1"                                  74         echo "$1"
 75         exit 1                                     75         exit 1
 76 }                                                  76 }
 77                                                    77 
 78 parse_si()                                         78 parse_si()
 79 {                                                  79 {
 80         conv_si="$(printf $1 | sed 's/[tT]+\?/     80         conv_si="$(printf $1 | sed 's/[tT]+\?/*1000G+/g; s/[gG]+\?/*1000M+/g; s/[mM]+\?/*1000K+/g; s/[kK]+\?/*1000+/g; s/+$//')"
 81         si_val="$((conv_si))"                      81         si_val="$((conv_si))"
 82 }                                                  82 }
 83 set_newmask()                                      83 set_newmask()
 84 {                                                  84 {
 85         for f in $(find "$1" -iname "$2"); do      85         for f in $(find "$1" -iname "$2"); do echo "$newmask" > "$f" 2>/dev/null || true; done
 86 }                                                  86 }
 87                                                    87 
 88 init_cpu()                                         88 init_cpu()
 89 {                                                  89 {
 90         isol_cpu="$1"                              90         isol_cpu="$1"
 91                                                    91 
 92         [ -d "$lacpusetdir" ] || mkdir "$lacpu     92         [ -d "$lacpusetdir" ] || mkdir "$lacpusetdir"
 93                                                    93 
 94         cur_cpu=$(cat "${lacpusetfile}cpus")       94         cur_cpu=$(cat "${lacpusetfile}cpus")
 95         [ "$cur_cpu" = "$isol_cpu" ] && return     95         [ "$cur_cpu" = "$isol_cpu" ] && return
 96         [ -z "$cur_cpu" ] || fail "CPU$isol_cp     96         [ -z "$cur_cpu" ] || fail "CPU$isol_cpu requested but CPU$cur_cpu already isolated"
 97                                                    97 
 98         echo "$isol_cpu" > "${lacpusetfile}cpu     98         echo "$isol_cpu" > "${lacpusetfile}cpus" || fail "Could not isolate CPU$isol_cpu. Does it exist?"
 99         echo 1 > "${lacpusetfile}cpu_exclusive     99         echo 1 > "${lacpusetfile}cpu_exclusive"
100         echo 0 > "${lacpusetfile}mems"            100         echo 0 > "${lacpusetfile}mems"
101                                                   101 
102         oldmask=$(cat /proc/irq/default_smp_af    102         oldmask=$(cat /proc/irq/default_smp_affinity)
103         newmask=$(printf "%x" $((0x$oldmask &     103         newmask=$(printf "%x" $((0x$oldmask & ~(1 << isol_cpu))))
104                                                   104 
105         set_newmask '/proc/irq' '*smp_affinity    105         set_newmask '/proc/irq' '*smp_affinity'
106         set_newmask '/sys/devices/virtual/work    106         set_newmask '/sys/devices/virtual/workqueue/' 'cpumask'
107                                                   107 
108         # Move tasks away from isolated CPU       108         # Move tasks away from isolated CPU
109         for p in $(ps -o pid | tail -n +2); do    109         for p in $(ps -o pid | tail -n +2); do
110                 mask=$(taskset -p "$p") || con    110                 mask=$(taskset -p "$p") || continue
111                 # Ignore tasks with a custom m    111                 # Ignore tasks with a custom mask, i.e. not equal $oldmask
112                 [ "${mask##*: }" = "$oldmask"     112                 [ "${mask##*: }" = "$oldmask" ] || continue
113                 taskset -p "$newmask" "$p" ||     113                 taskset -p "$newmask" "$p" || continue
114         done 2>/dev/null >/dev/null               114         done 2>/dev/null >/dev/null
115                                                   115 
116         # Big hammer! Working with 'rcu_moment    116         # Big hammer! Working with 'rcu_momentary_dyntick_idle()' for a more fine-grained solution
117         # still printed warnings. Same for re-    117         # still printed warnings. Same for re-enabling the stall detector after sampling.
118         echo 1 > /sys/module/rcupdate/paramete    118         echo 1 > /sys/module/rcupdate/parameters/rcu_cpu_stall_suppress
119                                                   119 
120         cpufreqgov="/sys/devices/system/cpu/cp    120         cpufreqgov="/sys/devices/system/cpu/cpu$isol_cpu/cpufreq/scaling_governor"
121         [ -w "$cpufreqgov" ] && echo 'performa    121         [ -w "$cpufreqgov" ] && echo 'performance' > "$cpufreqgov" || true
122 }                                                 122 }
123                                                   123 
124 parse_triggerdat()                                124 parse_triggerdat()
125 {                                                 125 {
126         oldifs="$IFS"                             126         oldifs="$IFS"
127         IFS=','; for trig in $1; do               127         IFS=','; for trig in $1; do
128                 mask=0; val1=0; val2=0            128                 mask=0; val1=0; val2=0
129                 IFS='+'; for elem in $trig; do    129                 IFS='+'; for elem in $trig; do
130                         chan=${elem%[lhfrLHFR]    130                         chan=${elem%[lhfrLHFR]}
131                         mode=${elem#$chan}        131                         mode=${elem#$chan}
132                         # Check if we could pa    132                         # Check if we could parse something and the channel number fits
133                         [ "$chan" != "$elem" ]    133                         [ "$chan" != "$elem" ] && [ "$chan" -le $max_chans ] || fail "Trigger syntax error: $elem"
134                         bit=$((1 << (chan - 1)    134                         bit=$((1 << (chan - 1)))
135                         mask=$((mask | bit))      135                         mask=$((mask | bit))
136                         case $mode in             136                         case $mode in
137                                 [hH]) val1=$((    137                                 [hH]) val1=$((val1 | bit)); val2=$((val2 | bit));;
138                                 [fF]) val1=$((    138                                 [fF]) val1=$((val1 | bit));;
139                                 [rR]) val2=$((    139                                 [rR]) val2=$((val2 | bit));;
140                         esac                      140                         esac
141                 done                              141                 done
142                 trigger_bindat="$trigger_binda    142                 trigger_bindat="$trigger_bindat$(printf '\\%o\\%o' $mask $val1)"
143                 [ $val1 -ne $val2 ] && trigger    143                 [ $val1 -ne $val2 ] && trigger_bindat="$trigger_bindat$(printf '\\%o\\%o' $mask $val2)"
144         done                                      144         done
145         IFS="$oldifs"                             145         IFS="$oldifs"
146 }                                                 146 }
147                                                   147 
148 do_capture()                                      148 do_capture()
149 {                                                 149 {
150         taskset "$1" echo 1 > "$lasysfsdir"/ca    150         taskset "$1" echo 1 > "$lasysfsdir"/capture || fail "Capture error! Check kernel log"
151                                                   151 
152         srtmp=$(mktemp -d)                        152         srtmp=$(mktemp -d)
153         echo 1 > "$srtmp"/version                 153         echo 1 > "$srtmp"/version
154         cp "$lasysfsdir"/sample_data "$srtmp"/    154         cp "$lasysfsdir"/sample_data "$srtmp"/logic-1-1
155         cat > "$srtmp"/metadata << EOF            155         cat > "$srtmp"/metadata << EOF
156 [global]                                          156 [global]
157 sigrok version=0.2.0                              157 sigrok version=0.2.0
158                                                   158 
159 [device 1]                                        159 [device 1]
160 capturefile=logic-1                               160 capturefile=logic-1
161 total probes=$(wc -l < "$lasysfsdir"/meta_data    161 total probes=$(wc -l < "$lasysfsdir"/meta_data)
162 samplerate=${samplefreq}Hz                        162 samplerate=${samplefreq}Hz
163 unitsize=1                                        163 unitsize=1
164 EOF                                               164 EOF
165         cat "$lasysfsdir"/meta_data >> "$srtmp    165         cat "$lasysfsdir"/meta_data >> "$srtmp"/metadata
166                                                   166 
167         zipname="$outputdir/${lasysfsdir##*/}-    167         zipname="$outputdir/${lasysfsdir##*/}-$(date +%s).sr"
168         zip -jq "$zipname" "$srtmp"/*             168         zip -jq "$zipname" "$srtmp"/*
169         rm -rf "$srtmp"                           169         rm -rf "$srtmp"
170         delay_ack=$(cat "$lasysfsdir"/delay_ns    170         delay_ack=$(cat "$lasysfsdir"/delay_ns_acquisition)
171         [ "$delay_ack" -eq 0 ] && delay_ack=1     171         [ "$delay_ack" -eq 0 ] && delay_ack=1
172         echo "Logic analyzer done. Saved '$zip    172         echo "Logic analyzer done. Saved '$zipname'"
173         echo "Max sample frequency this time:     173         echo "Max sample frequency this time: $((1000000000 / delay_ack))Hz."
174 }                                                 174 }
175                                                   175 
176 rep=$(getopt -a -l cpu:,duration-us:,help,inst    176 rep=$(getopt -a -l cpu:,duration-us:,help,instance:,list-instances,kernel-debug-dir:,num_samples:,output-dir:,sample_freq:,trigger: -o c:d:hi:k:ln:o:s:t: -- "$@") || exit 1
177 eval set -- "$rep"                                177 eval set -- "$rep"
178 while true; do                                    178 while true; do
179         case "$1" in                              179         case "$1" in
180         -c|--cpu) initcpu="$2"; shift;;           180         -c|--cpu) initcpu="$2"; shift;;
181         -d|--duration-us) parse_si $2; duratio    181         -d|--duration-us) parse_si $2; duration=$si_val; shift;;
182         -h|--help) print_help; exit 0;;           182         -h|--help) print_help; exit 0;;
183         -i|--instance) lainstance="$2"; shift;    183         -i|--instance) lainstance="$2"; shift;;
184         -k|--kernel-debug-dir) debugdir="$2";     184         -k|--kernel-debug-dir) debugdir="$2"; shift;;
185         -l|--list-instances) listinstances=1;;    185         -l|--list-instances) listinstances=1;;
186         -n|--num_samples) parse_si $2; numsamp    186         -n|--num_samples) parse_si $2; numsamples=$si_val; shift;;
187         -o|--output-dir) outputdir="$2"; shift    187         -o|--output-dir) outputdir="$2"; shift;;
188         -s|--sample_freq) parse_si $2; samplef    188         -s|--sample_freq) parse_si $2; samplefreq=$si_val; shift;;
189         -t|--trigger) triggerdat="$2"; shift;;    189         -t|--trigger) triggerdat="$2"; shift;;
190         --) break;;                               190         --) break;;
191         *) fail "error parsing command line: $    191         *) fail "error parsing command line: $*";;
192         esac                                      192         esac
193         shift                                     193         shift
194 done                                              194 done
195                                                   195 
196 for f in $neededcmds; do                          196 for f in $neededcmds; do
197         command -v "$f" >/dev/null || fail "Co    197         command -v "$f" >/dev/null || fail "Command '$f' not found"
198 done                                              198 done
199                                                   199 
200 # print cpuset mountpoint if any, errorcode >     200 # print cpuset mountpoint if any, errorcode > 0 if noprefix option was found
201 cpusetdir=$(awk '$3 == "cgroup" && $4 ~ /cpuse    201 cpusetdir=$(awk '$3 == "cgroup" && $4 ~ /cpuset/ { print $2; exit (match($4, /noprefix/) > 0) }' /proc/self/mounts) || cpusetprefix=''
202 if [ -z "$cpusetdir" ]; then                      202 if [ -z "$cpusetdir" ]; then
203         cpusetdir="$cpusetdefaultdir"             203         cpusetdir="$cpusetdefaultdir"
204         [ -d $cpusetdir ] || mkdir $cpusetdir     204         [ -d $cpusetdir ] || mkdir $cpusetdir
205         mount -t cgroup -o cpuset none $cpuset    205         mount -t cgroup -o cpuset none $cpusetdir || fail "Couldn't mount cpusets. Not in kernel or already in use?"
206 fi                                                206 fi
207                                                   207 
208 lacpusetdir="$cpusetdir/$ladirname"               208 lacpusetdir="$cpusetdir/$ladirname"
209 lacpusetfile="$lacpusetdir/$cpusetprefix"         209 lacpusetfile="$lacpusetdir/$cpusetprefix"
210 sysfsdir="$debugdir/$ladirname"                   210 sysfsdir="$debugdir/$ladirname"
211                                                   211 
212 [ "$samplefreq" -ne 0 ] || fail "Invalid sampl    212 [ "$samplefreq" -ne 0 ] || fail "Invalid sample frequency"
213                                                   213 
214 [ -d "$sysfsdir" ] || fail "Could not find log    214 [ -d "$sysfsdir" ] || fail "Could not find logic analyzer root dir '$sysfsdir'. Module loaded?"
215 [ -x "$sysfsdir" ] || fail "Could not access l    215 [ -x "$sysfsdir" ] || fail "Could not access logic analyzer root dir '$sysfsdir'. Need root?"
216                                                   216 
217 [ $listinstances -gt 0 ] && find "$sysfsdir" -    217 [ $listinstances -gt 0 ] && find "$sysfsdir" -mindepth 1 -type d | sed 's|.*/||' && exit 0
218                                                   218 
219 if [ -n "$lainstance" ]; then                     219 if [ -n "$lainstance" ]; then
220         lasysfsdir="$sysfsdir/$lainstance"        220         lasysfsdir="$sysfsdir/$lainstance"
221 else                                              221 else
222         lasysfsdir=$(find "$sysfsdir" -mindept    222         lasysfsdir=$(find "$sysfsdir" -mindepth 1 -type d -print -quit)
223 fi                                                223 fi
224 [ -d "$lasysfsdir" ] || fail "Logic analyzer d    224 [ -d "$lasysfsdir" ] || fail "Logic analyzer directory '$lasysfsdir' not found!"
225 [ -d "$outputdir" ] || fail "Output directory     225 [ -d "$outputdir" ] || fail "Output directory '$outputdir' not found!"
226                                                   226 
227 [ -n "$initcpu" ] && init_cpu "$initcpu"          227 [ -n "$initcpu" ] && init_cpu "$initcpu"
228 [ -d "$lacpusetdir" ] || { echo "Auto-Isolatin    228 [ -d "$lacpusetdir" ] || { echo "Auto-Isolating CPU1"; init_cpu 1; }
229                                                   229 
230 ndelay=$((1000000000 / samplefreq))               230 ndelay=$((1000000000 / samplefreq))
231 echo "$ndelay" > "$lasysfsdir"/delay_ns           231 echo "$ndelay" > "$lasysfsdir"/delay_ns
232                                                   232 
233 [ -n "$duration" ] && numsamples=$((samplefreq    233 [ -n "$duration" ] && numsamples=$((samplefreq * duration / 1000000))
234 echo $numsamples > "$lasysfsdir"/buf_size         234 echo $numsamples > "$lasysfsdir"/buf_size
235                                                   235 
236 if [ -n "$triggerdat" ]; then                     236 if [ -n "$triggerdat" ]; then
237         parse_triggerdat "$triggerdat"            237         parse_triggerdat "$triggerdat"
238         printf "$trigger_bindat" > "$lasysfsdi    238         printf "$trigger_bindat" > "$lasysfsdir"/trigger 2>/dev/null || fail "Trigger data '$triggerdat' rejected"
239 fi                                                239 fi
240                                                   240 
241 workcpu=$(cat "${lacpusetfile}effective_cpus")    241 workcpu=$(cat "${lacpusetfile}effective_cpus")
242 [ -n "$workcpu" ] || fail "No isolated CPU fou    242 [ -n "$workcpu" ] || fail "No isolated CPU found"
243 cpumask=$(printf '%x' $((1 << workcpu)))          243 cpumask=$(printf '%x' $((1 << workcpu)))
244 instance=${lasysfsdir##*/}                        244 instance=${lasysfsdir##*/}
245 echo "Setting up '$instance': $numsamples samp    245 echo "Setting up '$instance': $numsamples samples at ${samplefreq}Hz with ${triggerdat:-no} trigger using CPU$workcpu"
246 do_capture "$cpumask" &                           246 do_capture "$cpumask" &
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php