device.subr revision 251190
1169695Skanif [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1
2169695Skan#
3169695Skan# Copyright (c) 2012-2013 Devin Teske
4169695Skan# All Rights Reserved.
5169695Skan#
6169695Skan# Redistribution and use in source and binary forms, with or without
7169695Skan# modification, are permitted provided that the following conditions
8169695Skan# are met:
9169695Skan# 1. Redistributions of source code must retain the above copyright
10169695Skan#    notice, this list of conditions and the following disclaimer.
11169695Skan# 2. Redistributions in binary form must reproduce the above copyright
12169695Skan#    notice, this list of conditions and the following disclaimer in the
13169695Skan#    documentation and/or other materials provided with the distribution.
14169695Skan#
15169695Skan# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16169695Skan# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
17169695Skan# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18169695Skan# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19169695Skan# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20169695Skan# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21169695Skan# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22169695Skan# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23169695Skan# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24169695Skan# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25169695Skan# SUCH DAMAGE.
26169695Skan#
27169695Skan# $FreeBSD: head/usr.sbin/bsdconfig/share/device.subr 251190 2013-05-31 19:07:17Z dteske $
28169695Skan#
29169695Skan############################################################ INCLUDES
30169695Skan
31169695SkanBSDCFG_SHARE="/usr/share/bsdconfig"
32169695Skan. $BSDCFG_SHARE/common.subr || exit 1
33169695Skanf_dprintf "%s: loading includes..." device.subr
34169695Skanf_include $BSDCFG_SHARE/dialog.subr
35169695Skanf_include $BSDCFG_SHARE/strings.subr
36169695Skanf_include $BSDCFG_SHARE/struct.subr
37169695Skan
38169695SkanBSDCFG_LIBE="/usr/libexec/bsdconfig"
39169695Skanf_include_lang $BSDCFG_LIBE/include/messages.subr
40169695Skan
41169695Skan############################################################ GLOBALS
42169695Skan
43169695SkanDEVICES=
44169695SkanDEVICE_NAMES=
45169695Skan
46169695Skan# A "device" from sysinstall's point of view
47169695Skanf_struct_define DEVICE \
48169695Skan	name		\
49169695Skan	desc		\
50169695Skan	devname		\
51169695Skan	type		\
52169695Skan	enabled		\
53169695Skan	init		\
54169695Skan	get		\
55169695Skan	shutdown	\
56169695Skan	flags		\
57169695Skan	private		\
58169695Skan	volume	
59169695Skan
60169695Skan# Network devices have their `private' property set to this
61169695Skanf_struct_define DEVICE_INFO \
62169695Skan	use_rtsol use_dhcp ipaddr ipv6addr netmask extras
63169695Skan
64169695Skansetvar DEVICE_TYPE_NONE		1
65169695Skansetvar DEVICE_TYPE_DISK		2
66169695Skansetvar DEVICE_TYPE_FLOPPY	3
67169695Skansetvar DEVICE_TYPE_FTP		4
68169695Skansetvar DEVICE_TYPE_NETWORK	5
69169695Skansetvar DEVICE_TYPE_CDROM	6
70169695Skansetvar DEVICE_TYPE_USB		7
71169695Skansetvar DEVICE_TYPE_DOS		8
72169695Skansetvar DEVICE_TYPE_UFS		9
73169695Skansetvar DEVICE_TYPE_NFS		10
74169695Skansetvar DEVICE_TYPE_ANY		11
75169695Skansetvar DEVICE_TYPE_HTTP_PROXY	12
76169695Skan
77169695Skan#
78169695Skan# Default behavior is to call f_device_get_all() automatically when loaded.
79169695Skan#
80169695Skan: ${DEVICE_SELF_SCAN_ALL=1}
81169695Skan
82169695Skan############################################################ FUNCTIONS
83
84# f_device_try $name [$i [$var_path]]
85#
86# Test a particular device. If $i is given, then $name is expected to contain a
87# single "%d" where $i will be inserted using printf. If $var_path is given,
88# it is used as a variable name to provide the caller the device pathname.
89#
90# Returns success if the device path exists and is a cdev.
91#
92f_device_try()
93{
94	local name="$1" i="$2" var_path="$3" unit
95	if [ "$i" ]; then
96		unit=$( printf "$name" "$i" )
97	else
98		unit="$name"
99	fi
100	case "$unit" in
101	/dev/*) : good ;; # already qualified
102	*) unit="/dev/$unit" ;;
103	esac
104	[ "$var_path" ] && setvar "$var_path" "$unit"
105	f_dprintf "f_device_try: making sure %s is a device node" "$unit"
106	if [ -c "$unit" ]; then
107		f_dprintf "f_device_try: %s is a cdev [good]" "$unit"
108		return $SUCCESS
109	else
110		f_dprintf "f_device_try: %s is not a cdev [skip]" "$unit"
111		return $FAILURE
112	fi
113}
114
115# f_device_register $name $desc $devname $type $enabled $init_function \
116#                   $get_function $shutdown_function $private
117#
118# Register a device. A `structure' (see struct.subr) is created with the name
119# device_$name (so make sure $name contains only alpha-numeric characters or
120# the underscore, `_'). The remaining arguments after $name correspond to the
121# properties of the `DEVICE' structure-type (defined above).
122#
123# If not already registered, the device is then appended to the DEVICES
124# environment variable, a space-separated list of all registered devices.
125#
126f_device_register()
127{
128	local name="$1" desc="$2" devname="$3" type="$4" enabled="$5"
129	local init_func="$6" get_func="$7" shutdown_func="$8" private="$9"
130
131	f_struct_new DEVICE "device_$name" || return $FAILURE
132	device_$name set name     "$name"
133	device_$name set desc     "$desc"
134	device_$name set devname  "$devname"
135	device_$name set type     "$type"
136	device_$name set enabled  "$enabled"
137	device_$name set init     "$init_func"
138	device_$name set get      "$get_func"
139	device_$name set shutdown "$shutdown_func"
140	device_$name set private  "$private"
141
142	# Scan our global register to see if it needs ammending
143	local dev found=
144	for dev in $DEVICES; do
145		[ "$dev" = "$name" ] || continue
146		found=1 && break
147	done
148	[ "$found" ] || DEVICES="$DEVICES $name"
149
150	return $SUCCESS
151}
152
153# f_device_reset
154#
155# Reset the registered device chain.
156#
157f_device_reset()
158{
159	local dev
160	for dev in $DEVICES; do
161		f_device_shutdown $dev
162
163		#
164		# XXX this potentially leaks $dev->private if it's being
165		# used to point to something dynamic, but you're not supposed
166		# to call this routine at such times that some open instance
167		# has its private member pointing somewhere anyway. XXX
168		#
169		f_struct_free device_$dev
170	done
171	DEVICES=
172}
173
174# f_device_get_all
175#
176# Get all device information for devices we have attached.
177#
178f_device_get_all()
179{
180	local devname desc
181
182	f_dprintf "f_device_get_all: Probing devices..."
183	f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while"
184
185	# First go for the network interfaces
186	for devname in $( ifconfig -l ); do
187		# Eliminate network devices that don't make sense
188		case "$devname" in
189		lo*) continue ;;
190		esac
191
192		# Try and find its description
193		f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc
194
195		f_dprintf "Found a network device named %s" "$devname"
196		f_device_register $devname \
197			"$desc" "$devname" $DEVICE_TYPE_NETWORK 1 \
198			f_media_init_network "" f_media_shutdown_network ""
199	done
200
201	# Next, try to find all the types of devices one might use
202	# as a media source for content
203	#
204
205	local dev desc type max n=0
206	for dev in $DEVICE_NAMES; do
207		n=$(( $n + 1 ))
208		# Get the desc, type, and max (with debugging disabled)
209		# NOTE: Bypassing f_device_name_get() for efficiency
210		debug= f_getvar _device_desc$n desc
211		debug= f_getvar _device_type$n type
212		debug= f_getvar _device_max$n max
213
214		local k=0
215		while [ $k -lt ${max:-0} ]; do
216			i=$k k=$(( $k + 1 ))
217			devname=""
218			case "$type" in
219			$DEVICE_TYPE_CDROM)
220				f_device_try "$dev" "$i" devname || continue
221				f_device_register "${devname##*/}" "$desc" \
222					"$devname" $DEVICE_TYPE_CDROM 1 \
223					f_media_init_cdrom f_media_get_cdrom \
224					f_media_shutdown_cdrom ""
225				f_dprintf "Found a CDROM device for %s" \
226				          "$devname"
227				;;
228			$DEVICE_TYPE_FLOPPY)
229				f_device_try "$dev" "$i" devname || continue
230				f_device_register "${devname##*/}" "$desc" \
231					"$devname" $DEVICE_TYPE_FLOPPY 1 \
232					f_media_init_floppy \
233					f_media_get_floppy \
234					f_media_shutdown_floppy ""
235				f_dprintf "Found a floppy device for %s" \
236				          "$devname"
237				;;
238			$DEVICE_TYPE_USB)
239				f_device_try "$dev" "$i" devname || continue
240				f_device_register "${devname##*/}" "$desc" \
241					"$devname" $DEVICE_TYPE_USB 1 \
242					f_media_init_usb f_media_get_usb \
243					f_media_shutdown_usb ""
244				f_dprintf "Found a USB disk for %s" "$devname"
245				;;
246			esac
247		done
248	done
249
250	# Register ISO9660 providers as CDROM devices
251	for devname in /dev/iso9660/*; do
252		f_device_try "$devname" || continue
253		f_device_register "${devname##*/}" "ISO9660 file system" \
254			"$devname" $DEVICE_TYPE_CDROM 1 \
255			f_media_init_cdrom f_media_get_cdrom \
256			f_media_shutdown_cdrom ""
257		f_dprintf "Found a CDROM device for %s" "$devname"
258	done
259
260	# Scan for mdconfig(8)-created md(4) devices
261	local filename
262	for devname in /dev/md[0-9] /dev/md[0-9][0-9]; do
263		f_device_try "$devname" || continue
264
265		# See if the md(4) device is a vnode type backed by a file
266		filename=$( sysctl kern.geom.conftxt |
267			awk -v devname="${devname##*/}" \
268			'
269				( $2 == "MD" ) && \
270				( $3 == devname ) && \
271				( $(NF-2) == "vnode" ) && \
272				( $(NF-1) == "file" ) \
273				{
274					print $NF
275				}
276			' )
277		case "$filename" in
278		*.iso) # Register the device as an ISO9660 provider
279			f_device_register "${devname##*/}" \
280				"md(4) vnode file system" \
281				"$devname" $DEVICE_TYPE_CDROM 1 \
282				f_media_init_cdrom f_media_get_cdrom \
283				f_media_shutdown_cdrom ""
284			f_dprintf "Found a CDROM device for %s" "$devname"
285			;;
286		esac
287	done
288
289	# Finally go get the disks and look for partitions to register
290	local diskname slices index type rest slice part
291	for diskname in $( sysctl -n kern.disks ); do
292
293		case "$diskname" in
294		cd*)
295			# XXX
296			#  Due to unknown reasons, kern.disks returns SCSI
297			# CDROM as a valid disk. This will prevent bsdconfig
298			# from presenting SCSI CDROMs as available disks in
299			# various menus. Why GEOM treats SCSI CDROM as a disk
300			# is beyond me and that should be investigated.
301			# For temporary workaround, ignore SCSI CDROM device.
302			#
303			continue ;;
304		esac
305
306		# Try to create a list of partitions and their types,
307		# consisting of "N,typeN ..." (e.g., "1,0xa5 2,0x06").
308		if ! slices=$( fdisk -p "$diskname" 2> /dev/null |
309			awk '( $1 == "p" ) { print $2","$3 }' )
310		then
311			f_dprintf "Unable to open disk %s" "$diskname"
312			continue
313		fi
314
315		f_device_register "$diskname" "" \
316		                  "/dev/$diskname" $DEVICE_TYPE_DISK 0
317		f_dprintf "Found a disk device named %s" "$diskname"
318
319		# Look for existing partitions to register
320		for slice in $slices; do
321			index="${slice%%,*}" type="${slice#*,}"
322			slice=${diskname}s$index
323			case "$type" in
324			0x01|0x04|0x06|0x0b|0x0c|0x0e|0xef)
325				# DOS partitions to add as "DOS media devices"
326				f_device_register "$slice" "" \
327					"/dev/$slice" $DEVICE_TYPE_DOS 1 \
328					f_media_init_dos f_media_get_dos \
329					f_media_shutdown_dos ""
330				f_dprintf "Found a DOS partition %s" "$slice"
331				;;
332			0xa5) # FreeBSD partition
333				for part in $(
334					bsdlabel -r $slice 2> /dev/null |
335						awk -v slice="$slice" '
336						( $1 ~ /[abdefgh]:/ ) {
337							printf "%s%s\n",
338							       slice,
339							       substr($1,1,1)
340						}'
341				); do
342					f_quietly dumpfs -m /dev/$part ||
343						continue
344					f_device_register \
345						"$part" "" "/dev/$part" \
346						$DEVICE_TYPE_UFS 1 \
347						f_media_init_ufs \
348						f_media_get_ufs \
349						f_media_shutdown_ufs ""
350					f_dprintf "Found a UFS partition %s" \
351					          "$part"
352				done # parts
353				;;
354			esac
355		done # slices
356
357	done # disks
358}
359
360# f_device_name_get $type $name type|desc|max [$var_to_set]
361#
362# Fetch the device type (type), description (desc), or maximum number of
363# devices to scan for (max) associated with device $name and $type. If $type is
364# either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used.
365# Returns success if a match was found, otherwise failure.
366#
367# If $var_to_set is missing or NULL, the device name is printed to standard out
368# for capturing in a sub-shell (which is less-recommended because of
369# performance degredation; for example, when called in a loop).
370#
371f_device_name_get()
372{
373	local __type="$1" __name="$2" __prop="$3" __var_to_set="$4"
374	local __dev __devtype __n=0
375
376	# Return failure if no $name or $prop is an unknown property
377	[ "$__name" ] || return $FAILURE
378	case "$__prop" in type|desc|max) : good ;;
379	*) return $FAILURE; esac
380
381	[ "$__type" = "$DEVICE_TYPE_ANY" ] && __type=
382	for __dev in $DEVICE_NAMES; do
383		__n=$(( $__n + 1 ))
384		[ "$__dev" = "$__name" ] || continue
385		f_getvar _device_type$__n __devtype
386		[ "${__type:-$__devtype}" = "$__devtype" ] || continue
387		f_getvar _device_$__prop$__n $__var_to_set
388		return $?
389	done
390	return $FAILURE
391}
392
393# f_device_name_set $type $name $desc [$max]
394#
395# Store a description (desc) and [optionally] maximum number of devices to scan
396# for (max) in-association with device $type and $name. Returns success unless
397# $name is NULL or missing. Use the f_device_name_get() routine with the same
398# $name and optionally $type to retrieve one of type, desc, or max properties.
399#
400f_device_name_set()
401{
402	local type="$1" name="$2" desc="$3" max="$4"
403	local dev devtype n=0 found=
404	[ "$name" ] || return $FAILURE
405	for dev in $DEVICE_NAMES; do
406		n=$(( $n + 1 ))
407		[ "$dev" = "$name" ] || continue
408		if f_getvar _device_type$n devtype; then
409			# Allow multiple entries with same name but diff type
410			[ "$devtype" = "$type" ] || continue
411		fi
412		found=1 && break
413	done
414	if [ ! "$found" ]; then
415		DEVICE_NAMES="$DEVICE_NAMES $name"
416		n=$(( $n + 1 ))
417	fi
418	setvar _device_type$n "$type"
419	setvar _device_desc$n "$desc"
420	[ "${4+set}" ] && setvar _device_max$n "$max"
421	return $SUCCESS
422}
423
424# f_device_desc $device_name $device_type [$var_to_set]
425#
426# Print a description for a device name (eg., `fxp0') given a specific device
427# type/class.
428#
429# If $var_to_set is missing or NULL, the device description is printed to
430# standard out for capturing in a sub-shell (which is less-recommended because
431# of performance degredation; for example, when called in a loop).
432#
433f_device_desc()
434{
435	local __name="$1" __type="$2" __var_to_set="$3"
436	local __devname __devunit __cp
437
438	# Check variables
439	[ "$__name" ] || return $SUCCESS
440	[ "$__type" = "$DEVICE_TYPE_ANY" ] && type=
441	[ "$__var_to_set" ] && { setvar "$__var_to_set" "" || return; }
442
443	#
444	# Return sysctl MIB dev.NAME.UNIT.%desc if it exists,
445	# otherwise fall through to below static list.
446	#
447	if f_have sysctl; then
448		__devname="${__name%%[0-9]*}"
449		__devunit="${__name#$__devname}"
450		__devunit="${__devunit%%[!0-9]*}"
451		if [ "$__var_to_set" ]; then
452			if __cp=$(
453				sysctl -n "dev.$__devname.$__devunit.%desc" \
454				2> /dev/null
455			); then
456				setvar "$__var_to_set" "$__cp" &&
457					return $SUCCESS
458			fi
459		else
460			sysctl -n "dev.$__devname.$__devunit.%desc" \
461				2> /dev/null && return $SUCCESS
462		fi
463	fi
464
465	local __dev __devtype __n=0
466	for __dev in $DEVICE_NAMES; do
467		__n=$(( $__n + 1 ))
468		debug= f_getvar _device_type$__n __devtype
469		[ "${__type:-$__devtype}" = "$__devtype" ] || continue
470		if [ "$__devtype" = "$DEVICE_TYPE_NETWORK" ]; then
471			__devname=$( f_substr "$__name" 0 ${#__dev} )
472			[ "$__devname" = "$__dev" ] || continue
473		else
474			__devname="${__name%%[0-9]*}"
475			__devunit="${__name#$__devname}"
476			__devunit="${__devunit%%[!0-9]*}"
477			__devname=$( printf "$__dev" $__devunit )
478			[ "$__devname" = "$__name" ] || continue
479		fi
480		debug= f_getvar _device_desc$__n $__var_to_set
481		return $?
482	done
483
484	#
485	# Sensible fall-backs for specific types
486	#
487	case "$__type" in
488	$DEVICE_TYPE_CDROM)   __cp="<unknown cdrom device type>";;
489	$DEVICE_TYPE_DISK)    __cp="<unknown disk device type>";;
490	$DEVICE_TYPE_FLOPPY)  __cp="<unknown floppy device type>";;
491	$DEVICE_TYPE_USB)     __cp="<unknown usb storage device type>";;
492	$DEVICE_TYPE_NETWORK) __cp="<unknown network interface type>";;
493	*)
494		__cp="<unknown device type>"
495	esac
496
497	if [ "$__var_to_set" ]; then
498		setvar "$__var_to_set" "$__cp"
499	else
500		echo "$__cp"
501	fi
502
503	return $FAILURE
504}
505
506# f_device_rescan
507#
508# Rescan all devices, after closing previous set - convenience function.
509#
510f_device_rescan()
511{
512	f_device_reset
513	f_device_get_all
514}
515
516# f_device_find $name [$type [$var_to_set]] 
517#
518# Find one or more registered devices by name, type, or both. Returns a space-
519# separated list of devices matching the search criterion.
520#
521# If $var_to_set is missing or NULL, the device name(s) are printed to standard
522# out for capturing in a sub-shell (which is less-recommended because of
523# performance degredation; for example, when called in a loop).
524#
525f_device_find()
526{
527	local __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3"
528	local __dev __devname __devtype __found=
529	for __dev in $DEVICES; do
530		device_$__dev get name __devname
531		device_$__dev get type __devtype
532		if [ "$__name" = "$__devname" -o ! "$__name" ] &&
533		   [ "$__type" = "$DEVICE_TYPE_ANY" -o \
534		     "$__type" = "$__devtype" ]
535		then
536			__found="$__found $__dev"
537		fi
538	done
539	if [ "$__var_to_set" ]; then
540		setvar "$__var_to_set" "${__found# }"
541	else
542		echo $__found
543	fi
544	[ "$__found" ] # Return status
545}
546
547# f_device_init $name
548#
549# Initialize a device by evaluating its `init' function.
550#
551f_device_init()
552{
553	local name="$1" init_func
554	device_$name get init init_func || return
555	${init_func:-:} $name
556}
557
558# f_device_get $name $file [$probe]
559#
560# Read $file by evaluating the device's `get' function. The file is commonly
561# produced on standard output (but it truly depends on the function called).
562#
563f_device_get()
564{
565	local name="$1" file="$2" probe="$3" get_func
566	device_$name get get get_func || return
567	${get_func:-:} $name "$file" ${3+"$probe"}
568}
569
570# f_device_shutdown $name
571#
572# Shutdown a device by evaluating its `shutdown' function.
573#
574f_device_shutdown()
575{
576	local name="$1" shutdown_func
577	device_$name get shutdown shutdown_func || return
578	${shutdown_func:-:} $name
579}
580
581# f_device_menu $title $prompt $hline $device_type [$helpfile]
582#
583# Display a menu listing all the devices of a certain type in the system.
584#
585f_device_menu()
586{
587	f_dialog_title "$1"
588	local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
589	f_dialog_title_restore
590
591	local prompt="$2" hline="$3" type="$4" helpfile="$5"
592
593	local dev devtype devs=
594	for dev in $DEVICES; do
595		device_$dev get type devtype || continue
596		[ "$devtype" = "$type" ] || continue
597		devs="$devs $dev"
598	done
599	[ "$devs" ] || return $FAILURE
600
601	local sanitize_awk="{ gsub(/'/, \"'\\\\''\"); print }"
602
603	local desc menu_list=
604	for dev in $devs; do
605		device_$dev get desc desc
606		desc=$( echo "$desc" | awk "$sanitize_awk" )
607		menu_list="$menu_list '$dev' '$desc'"
608	done
609
610	local height width rows
611	eval f_dialog_menu_size height width rows \
612	                        \"\$title\"  \
613	                        \"\$btitle\" \
614	                        \"\$prompt\" \
615	                        \"\$hline\"  \
616	                        $menu_list
617
618	local errexit=
619	case $- in *e*) errexit=1; esac
620	set +e
621
622	while :; do
623		mtag=$( eval $DIALOG \
624			--title \"\$title\"             \
625			--backtitle \"\$btitle\"        \
626			--ok-label \"\$msg_ok\"         \
627			--cancel-label \"\$msg_cancel\" \
628			${helpfile:+                    \
629			  --help-button                 \
630			  --help-label \"\$msg_help\"   \
631			  ${USE_XDIALOG:+--help \"\"}   \
632			}                               \
633			--menu \"\$prompt\"             \
634			$height $width $rows            \
635			$menu_list                      \
636			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
637		)
638		local retval=$?
639
640		[ $retval -ne 2 ] && break
641			# Otherwise, the Help button was pressed
642		f_show_help "$helpfile"
643			# ...then loop back to menu
644	done
645	f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
646
647	[ "$errexit" ] && set -e
648
649	if [ $retval -eq 0 ]; then
650		# Clean up the output of [X]dialog(1) and return it
651		setvar DIALOG_MENU_$$ "$mtag"
652		mtag=$( f_dialog_menutag )
653		echo "$mtag" >&2
654	fi
655
656	return $retval
657}
658
659#
660# Short-hand
661#
662f_cdrom()   {  f_device_name_set $DEVICE_TYPE_CDROM   "$1" "$2" "$3";  }
663f_disk()    {  f_device_name_set $DEVICE_TYPE_DISK    "$1" "$2" "$3";  }
664f_floppy()  {  f_device_name_set $DEVICE_TYPE_FLOPPY  "$1" "$2" "$3";  }
665f_serial()  {  f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2" "$3";  }
666f_usb()     {  f_device_name_set $DEVICE_TYPE_USB     "$1" "$2" "$3";  }
667f_network() {  f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2";       }
668
669############################################################ MAIN
670
671# CDROM, Disk, Floppy, Serial, and USB devices/names
672f_cdrom  "cd%d"   "SCSI CDROM drive"                  4
673f_cdrom  "mcd%d"  "Mitsumi (old model) CDROM drive"   4
674f_cdrom  "scd%d"  "Sony CDROM drive - CDU31/33A type" 4
675f_disk   "aacd%d" "Adaptec FSA RAID array"            4
676f_disk   "ada%d"  "ATA/SATA disk device"              16
677f_disk   "amrd%d" "AMI MegaRAID drive"                4
678f_disk   "da%d"   "SCSI disk device"                  16
679f_disk   "idad%d" "Compaq RAID array"                 4
680f_disk   "ipsd%d" "IBM ServeRAID RAID array"          4
681f_disk   "mfid%d" "LSI MegaRAID SAS array"            4
682f_disk   "mlxd%d" "Mylex RAID disk"                   4
683f_disk   "twed%d" "3ware ATA RAID array"              4
684f_floppy "fd%d"   "Floppy Drive unit A"               4
685f_serial "cuau%d" "%s on device %s (COM%d)"           16
686f_usb    "da%da"  "USB Mass Storage Device"           16
687
688# Network interfaces/names
689f_network "ae"    "Attansic/Atheros L2 Fast Ethernet"
690f_network "age"   "Attansic/Atheros L1 Gigabit Ethernet"
691f_network "alc"   "Atheros AR8131/AR8132 PCIe Ethernet"
692f_network "ale"   "Atheros AR8121/AR8113/AR8114 PCIe Ethernet"
693f_network "an"    "Aironet 4500/4800 802.11 wireless adapter"
694f_network "ath"   "Atheros IEEE 802.11 wireless adapter"
695f_network "aue"   "ADMtek USB Ethernet adapter"
696f_network "axe"   "ASIX Electronics USB Ethernet adapter"
697f_network "bce"   "Broadcom NetXtreme II Gigabit Ethernet card"
698f_network "bfe"   "Broadcom BCM440x PCI Ethernet card"
699f_network "bge"   "Broadcom BCM570x PCI Gigabit Ethernet card"
700f_network "bm"    "Apple BMAC Built-in Ethernet"
701f_network "bwn"   "Broadcom BCM43xx IEEE 802.11 wireless adapter"
702f_network "cas"   "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet"
703f_network "cc3i"  "SDL HSSI sync serial PCI card"
704f_network "cue"   "CATC USB Ethernet adapter"
705f_network "cxgb"  "Chelsio T3 10Gb Ethernet card"
706f_network "dc"    "DEC/Intel 21143 (and clones) PCI Fast Ethernet card"
707f_network "de"    "DEC DE435 PCI NIC or other DC21040-AA based card"
708f_network "disc"  "Software discard network interface"
709f_network "ed"    "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA"
710f_network "el"    "3Com 3C501 Ethernet card"
711f_network "em"    "Intel(R) PRO/1000 Ethernet card"
712f_network "en"    "Efficient Networks ATM PCI card"
713f_network "ep"    "3Com 3C509 Ethernet card/3C589 PCMCIA"
714f_network "et"    "Agere ET1310 based PCI Express Gigabit Ethernet card"
715f_network "ex"    "Intel EtherExpress Pro/10 Ethernet card"
716f_network "fe"    "Fujitsu MB86960A/MB86965A Ethernet card"
717f_network "fpa"   "DEC DEFPA PCI FDDI card"
718f_network "fwe"   "FireWire Ethernet emulation"
719f_network "fwip"  "IP over FireWire"
720f_network "fxp"   "Intel EtherExpress Pro/100B PCI Fast Ethernet card"
721f_network "gem"   "Apple GMAC or Sun ERI/GEM Ethernet adapter"
722f_network "hme"   "Sun HME (Happy Meal Ethernet) Ethernet adapter"
723f_network "ie"    "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210"
724f_network "igb"   "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card"
725f_network "ipw"   "Intel PRO/Wireless 2100 IEEE 802.11 adapter"
726f_network "iwi"   "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter"
727f_network "iwn"   "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter"
728f_network "ixgbe" "Intel(R) PRO/10Gb Ethernet card"
729f_network "ixgb"  "Intel(R) PRO/10Gb Ethernet card"
730f_network "ix"    "Intel Etherexpress Ethernet card"
731	# Maintain sequential order of above(3): ixgbe ixgb ix
732f_network "jme"   "JMicron JMC250 Gigabit/JMC260 Fast Ethernet"
733f_network "kue"   "Kawasaki LSI USB Ethernet adapter"
734f_network "le"    "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter"
735f_network "lge"   "Level 1 LXT1001 Gigabit Ethernet card"
736f_network "lnc"   "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet"
737f_network "lo"    "Loop-back (local) network interface"
738f_network "lp"    "Parallel Port IP (PLIP) peer connection"
739f_network "malo"  "Marvell Libertas 88W8335 802.11 wireless adapter"
740f_network "msk"   "Marvell/SysKonnect Yukon II Gigabit Ethernet"
741f_network "mxge"  "Myricom Myri10GE 10Gb Ethernet card"
742f_network "nfe"   "NVIDIA nForce MCP Ethernet"
743f_network "nge"   "NatSemi PCI Gigabit Ethernet card"
744f_network "ng"    "Vimage netgraph(4) bridged Ethernet device"
745	# Maintain sequential order of above(2): nge ng
746f_network "nve"   "NVIDIA nForce MCP Ethernet"
747f_network "nxge"  "Neterion Xframe 10GbE Server/Storage adapter"
748f_network "pcn"   "AMD Am79c79x PCI Ethernet card"
749f_network "plip"  "Parallel Port IP (PLIP) peer connection"
750f_network "ral"   "Ralink Technology IEEE 802.11 wireless adapter"
751f_network "ray"   "Raytheon Raylink 802.11 wireless adapter"
752f_network "re"    "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter"
753f_network "rl"    "RealTek 8129/8139 PCI Ethernet card"
754f_network "rue"   "RealTek USB Ethernet card"
755f_network "rum"   "Ralink Technology USB IEEE 802.11 wireless adapter"
756f_network "sf"    "Adaptec AIC-6915 PCI Ethernet card"
757f_network "sge"   "Silicon Integrated Systems SiS190/191 Ethernet"
758f_network "sis"   "SiS 900/SiS 7016 PCI Ethernet card"
759f_network "sk"    "SysKonnect PCI Gigabit Ethernet card"
760f_network "snc"   "SONIC Ethernet card"
761f_network "sn"    "SMC/Megahertz Ethernet card"
762	# Maintain sequential order of above(2): snc sn
763f_network "sr"    "SDL T1/E1 sync serial PCI card"
764f_network "ste"   "Sundance ST201 PCI Ethernet card"
765f_network "stge"  "Sundance/Tamarack TC9021 Gigabit Ethernet"
766f_network "ti"    "Alteon Networks PCI Gigabit Ethernet card"
767f_network "tl"    "Texas Instruments ThunderLAN PCI Ethernet card"
768f_network "txp"   "3Com 3cR990 Ethernet card"
769f_network "tx"    "SMC 9432TX Ethernet card"
770	# Maintain sequential order of above(2): txp tx
771f_network "uath"  "Atheros AR5005UG and AR5005UX USB wireless adapter"
772f_network "upgt"  "Conexant/Intersil PrismGT USB wireless adapter"
773f_network "ural"  "Ralink Technology RT2500USB 802.11 wireless adapter"
774f_network "urtw"  "Realtek 8187L USB wireless adapter"
775f_network "vge"   "VIA VT612x PCI Gigabit Ethernet card"
776f_network "vlan"  "IEEE 802.1Q VLAN network interface"
777f_network "vr"    "VIA VT3043/VT86C100A Rhine PCI Ethernet card"
778f_network "vx"    "3COM 3c590 / 3c595 Ethernet card"
779f_network "wb"    "Winbond W89C840F PCI Ethernet card"
780f_network "wi"    "Lucent WaveLAN/IEEE 802.11 wireless adapter"
781f_network "wpi"   "Intel 3945ABG IEEE 802.11 wireless adapter"
782f_network "wx"    "Intel Gigabit Ethernet (82452) card"
783f_network "xe"    "Xircom/Intel EtherExpress Pro100/16 Ethernet card"
784f_network "xl"    "3COM 3c90x / 3c90xB PCI Ethernet card"
785f_network "zyd"   "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter"
786
787f_dprintf "%s: Initialized %u known device names/descriptions." device.subr \
788	  "$( set -- $DEVICE_NAMES; echo $# )"
789
790#
791# Scan for the above devices unless requeted otherwise
792#
793f_dprintf "%s: DEVICE_SELF_SCAN_ALL=[%s]" device.subr "$DEVICE_SELF_SCAN_ALL"
794case "$DEVICE_SELF_SCAN_ALL" in
795""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
796*) f_device_get_all
797esac
798
799f_dprintf "%s: Successfully loaded." device.subr
800
801fi # ! $_DEVICE_SUBR
802