]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - usr.sbin/bsdconfig/share/device.subr
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / usr.sbin / bsdconfig / share / device.subr
1 if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1
2 #
3 # Copyright (c) 2012-2014 Devin Teske
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 # SUCH DAMAGE.
26 #
27 # $FreeBSD$
28 #
29 ############################################################ INCLUDES
30
31 BSDCFG_SHARE="/usr/share/bsdconfig"
32 . $BSDCFG_SHARE/common.subr || exit 1
33 f_dprintf "%s: loading includes..." device.subr
34 f_include $BSDCFG_SHARE/dialog.subr
35 f_include $BSDCFG_SHARE/geom.subr
36 f_include $BSDCFG_SHARE/strings.subr
37 f_include $BSDCFG_SHARE/struct.subr
38
39 BSDCFG_LIBE="/usr/libexec/bsdconfig"
40 f_include_lang $BSDCFG_LIBE/include/messages.subr
41
42 ############################################################ GLOBALS
43
44 NDEVICES=0 # Set by f_device_register(), used by f_device_*()
45
46 #
47 # A "device" from legacy sysinstall's point of view (mostly)
48 #
49 # NB: Disk devices have their `private' property set to GEOM ident
50 # NB: USB devices have their `private' property set to USB disk device name
51 #
52 f_struct_define DEVICE \
53         capacity        \
54         desc            \
55         devname         \
56         enabled         \
57         flags           \
58         get             \
59         init            \
60         name            \
61         private         \
62         shutdown        \
63         type            \
64         volume  
65
66 # Network devices have their `private' property set to this
67 f_struct_define DEVICE_INFO \
68         extras          \
69         ipaddr          \
70         ipv6addr        \
71         netmask         \
72         use_dhcp        \
73         use_rtsol
74
75 #
76 # Device types for f_device_register(), f_device_find(), et al.
77 #
78 setvar DEVICE_TYPE_ANY          "any"           # Any
79 setvar DEVICE_TYPE_NONE         "NONE"          # Unknown
80 setvar DEVICE_TYPE_DISK         "DISK"          # GEOM `DISK'
81 setvar DEVICE_TYPE_FLOPPY       "FD"            # GEOM `FD'
82 setvar DEVICE_TYPE_FTP          "FTP"           # Dynamic network device
83 setvar DEVICE_TYPE_NETWORK      "NETWORK"       # See f_device_get_all_network
84 setvar DEVICE_TYPE_CDROM        "CDROM"         # GEOM `DISK'
85 setvar DEVICE_TYPE_USB          "USB"           # GEOM `PART'
86 setvar DEVICE_TYPE_DOS          "DOS"           # GEOM `DISK' `PART' or `LABEL'
87 setvar DEVICE_TYPE_UFS          "UFS"           # GEOM `DISK' `PART' or `LABEL'
88 setvar DEVICE_TYPE_NFS          "NFS"           # Dynamic network device
89 setvar DEVICE_TYPE_HTTP_PROXY   "HTTP_PROXY"    # Dynamic network device
90 setvar DEVICE_TYPE_HTTP         "HTTP"          # Dynamic network device
91
92 # Network devices have the following flags available
93 setvar IF_ETHERNET      1
94 setvar IF_WIRELESS      2
95 setvar IF_ACTIVE        4
96
97 #
98 # Default behavior is to call f_device_get_all() automatically when loaded.
99 #
100 : ${DEVICE_SELF_SCAN_ALL=1}
101
102 #
103 # Device Catalog variables
104 #
105 DEVICE_CATALOG_APPEND_ONLY= # Used by f_device_catalog_set()
106 NCATALOG_DEVICES=0          # Used by f_device_catalog_*() and MAIN
107
108 #
109 # A ``catalog'' device is for mapping GEOM devices to media devices (for
110 # example, determining if a $GEOM_CLASS_DISK geom is $DEVICE_TYPE_CDROM or
111 # $DEVICE_TYPE_DISK) and also getting default descriptions for devices that
112 # either lack a GEOM provided description or lack a presence in GEOM)
113 #
114 f_struct_define CATALOG_DEVICE \
115         desc    \
116         name    \
117         type
118
119 ############################################################ FUNCTIONS
120
121 # f_device_register $var_to_set $name $desc $devname $type $enabled
122 #                   $init_function $get_function $shutdown_function
123 #                   $private $capacity
124 #
125 # Register a device. A `structure' (see struct.subr) is created and if
126 # $var_to_set is non-NULL, upon success holds the name of the struct created.
127 # The remaining positional arguments correspond to the properties of the
128 # `DEVICE' structure-type to be assigned (defined above).
129 #
130 # If not already registered (based on $name and $type), a new device is created
131 # and $NDEVICES is incremented.
132 #
133 f_device_register()
134 {
135         local __var_to_set="$1" __name="$2" __desc="$3" __devname="$4"
136         local __type="$5" __enabled="$6" __init_func="$7" __get_func="$8"
137         local __shutdown_func="$9" __private="${10}" __capacity="${11}"
138
139         # Required parameter(s)
140         [ "$__name" ] || return $FAILURE
141         if [ "$__var_to_set" ]; then
142                 setvar "$__var_to_set" "" || return $FAILURE
143         fi
144
145         local __device
146         if f_device_find -1 "$__name" "$__type" __device; then
147                 f_struct_free "$__device"
148                 f_struct_new DEVICE "$__device" || return $FAILURE
149         else
150                 __device=device_$(( NDEVICES + 1 ))
151                 f_struct_new DEVICE "$__device" || return $FAILURE
152                 NDEVICES=$(( $NDEVICES + 1 ))
153         fi
154         $__device set name     "$__name"
155         $__device set desc     "$__desc"
156         $__device set devname  "$__devname"
157         $__device set type     "$__type"
158         $__device set enabled  "$__enabled"
159         $__device set init     "$__init_func"
160         $__device set get      "$__get_func"
161         $__device set shutdown "$__shutdown_func"
162         $__device set private  "$__private"
163         $__device set capacity "$__capacity"
164
165         [ "$__var_to_set" ] && setvar "$__var_to_set" "$__device"
166         return $SUCCESS
167 }
168
169 # f_device_reset
170 #
171 # Reset the registered device chain.
172 #
173 f_device_reset()
174 {
175         local n=1
176         while [ $n -le $NDEVICES ]; do
177                 f_device_shutdown device_$n
178
179                 #
180                 # XXX This potentially leaks $dev->private if it's being
181                 # used to point to something dynamic, but you're not supposed
182                 # to call this routine at such times that some open instance
183                 # has its private member pointing somewhere anyway.
184                 #
185                 f_struct_free device_$n
186
187                 n=$(( $n + 1 ))
188         done
189         NDEVICES=0
190 }
191
192 # f_device_reset_network
193 #
194 # Reset the registered network device chain.
195 #
196 f_device_reset_network()
197 {
198         local n=1 device type private i
199         while [ $n -le $NDEVICES ]; do
200                 device=device_$n
201                 f_struct $device || continue
202                 $device get type type
203                 [ "$type" = "$DEVICE_TYPE_NETWORK" ] || continue
204
205                 #
206                 # Leave the device up (don't call shutdown routine)
207                 #
208
209                 # Network devices may have DEVICE_INFO private member
210                 $device get private private
211                 [ "$private" ] && f_struct_free "$private"
212
213                 # Free the network device
214                 f_struct_free $device
215
216                 # Fill the gap we just created
217                 i=$n
218                 while [ $i -lt $NDEVICES ]; do
219                         f_struct_copy device_$(( $i + 1 )) device_$i
220                 done
221                 f_struct_free device_$NDEVICES
222
223                 # Finally decrement the number of devices
224                 NDEVICES=$(( $NDEVICES - 1 ))
225
226                 n=$(( $n + 1 ))
227         done
228 }
229
230 # f_device_get_all
231 #
232 # Get all device information for all devices.
233 #
234 f_device_get_all()
235 {
236         local devname type desc capacity
237
238         f_dprintf "f_device_get_all: Probing devices..."
239         f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while"
240
241         # First go for the network interfaces
242         f_device_get_all_network
243
244         # Next, go for the GEOM devices we might want to use as media
245         local geom geoms geom_name
246         debug= f_geom_find "" $GEOM_CLASS_DEV geoms
247         for geom in $geoms; do
248                 if ! f_device_probe_geom $geom; then
249                         debug= $geom get name geom_name
250                         f_dprintf "WARNING! Unable to classify %s as %s" \
251                                   "GEOM device $geom_name" "media source"
252                 fi
253         done
254 }
255
256 # f_device_get_all_network
257 #
258 # Get all network device information for attached network devices.
259 #
260 f_device_get_all_network()
261 {
262         local devname desc device flags
263         for devname in $( ifconfig -l ); do
264                 # Eliminate network devices that don't make sense
265                 case "$devname" in
266                 lo*) continue ;;
267                 esac
268
269                 # Try and find its description
270                 f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc
271
272                 f_dprintf "Found network device named %s" "$devname"
273                 debug= f_device_register device $devname "$desc" \
274                         "$devname" $DEVICE_TYPE_NETWORK 1 \
275                         f_media_init_network "" f_media_shutdown_network "" -1
276
277                 # Set flags based on media and status
278                 flags=0
279                 eval "$( ifconfig $devname 2> /dev/null | awk -v var=flags '
280                 function _or(var, mask) {
281                         printf "%s=$(( $%s | $%s ))\n", var, var, mask
282                 }
283                 BEGIN { S = "[[:space:]]+" }
284                 {
285                         if (!match($0, "^" S "(media|status):" S)) next
286                         value = substr($0, RLENGTH + 1)
287                         if ($1 == "media:") {
288                                 if (value ~ /Ethernet/) _or(var, "IF_ETHERNET")
289                                 if (value ~ /802\.11/) _or(var, "IF_WIRELESS")
290                         } else if ($1 == "status:") {
291                                 if (value ~ /^active/) _or(var, "IF_ACTIVE")
292                         }
293                 }' )"
294                 $device set flags $flags
295         done
296 }
297
298 # f_device_rescan
299 #
300 # Rescan all devices, after closing previous set - convenience function.
301 #
302 f_device_rescan()
303 {
304         f_device_reset
305         f_geom_rescan
306         f_device_get_all
307 }
308
309 # f_device_rescan_network
310 #
311 # Rescan all network devices, after closing previous set - for convenience.
312 #
313 f_device_rescan_network()
314 {
315         f_device_reset_network
316         f_device_get_all_network
317 }
318
319 # f_device_probe_geom $geom
320 #
321 # Probe a single GEOM device and if it can be classified as a media source,
322 # register it using f_device_register() with known type-specific arguments.
323 #
324 f_device_probe_geom()
325 {
326         local geom="$1"
327
328         f_struct "$geom" || return $FAILURE
329
330         # geom associated variables
331         local geom_name geom_consumer provider_ref geom_provider=
332         local provider_geom provider_config provider_class=
333         local provider_config_type catalog_struct catalog_type
334         local disk_ident
335
336         # gnop(8)/geli(8) associated variables (p for `parent device')
337         local p_devname p_geom p_consumer p_provider_ref p_provider 
338         local p_provider_config p_provider_geom p_provider_class
339
340         # md(4) associated variables
341         local config config_type config_file magic=
342
343         # Temporarily disable debugging to keep debug output light
344         local old_debug="$debug" debug=
345
346         #
347         # Get the GEOM name (for use below in device registration)
348         #
349         $geom get name devname || continue
350
351         #
352         # Attempt to get the consumer, provider, provider config, and
353         # provider class for this geom (errors ignored).
354         #
355         # NB: Each GEOM in the `DEV' class should have one consumer.
356         #     That consumer should have a reference to its provider.
357         #
358         $geom get consumer1 geom_consumer
359         f_struct "$geom_consumer" get provider_ref provider_ref &&
360                 f_geom_find_by id "$provider_ref" provider geom_provider
361         if f_struct "$geom_provider"; then
362                 $geom_provider get config provider_config
363                 f_geom_parent $geom_provider provider_geom &&
364                         f_geom_parent $provider_geom provider_class
365         fi
366
367         #
368         # Get values for device registration (errors ignored)
369         #
370         f_struct "$provider_class"  get name      type
371         f_struct "$geom_provider"   get mediasize capacity
372         f_struct "$provider_config" get descr     desc
373
374         #
375         # For gnop(8), geli(8), or combination thereof, change device type to
376         # that of the consumer
377         #
378         p_devname= p_geom= p_provider= p_provider_config=
379         case "$devname" in
380         *.nop.eli) p_devname="${devname%.nop.eli}" ;;
381         *.eli.nop) p_devname="${devname%.eli.nop}" ;;
382         *.eli)     p_devname="${devname%.eli}" ;;
383         *.nop)     p_devname="${devname%.nop}" ;;
384         esac
385         [ "$p_devname" ] && f_geom_find "$p_devname" $GEOM_CLASS_DEV p_geom
386         if [ "${p_geom:-$geom}" != "$geom" ]; then
387                 f_struct "$p_geom" get consumer1 p_consumer
388                 f_struct "$p_consumer" get provider_ref p_provider_ref &&
389                         f_geom_find_by id "$p_provider_ref" provider p_provider
390                 if f_struct "$p_provider"; then
391                         $p_provider get config p_provider_config
392                         f_geom_parent $p_provider p_provider_geom &&
393                                 f_geom_parent $p_provider_geom p_provider_class
394                 fi
395                 f_struct "$p_provider_class" get name type
396         fi
397
398         # Look up geom device in device catalog for default description
399         f_device_catalog_get \
400                 $DEVICE_TYPE_ANY "${p_devname:-$devname}" catalog_struct
401         [ "$desc" ] || f_struct "catalog_device_$catalog_struct" get desc desc
402
403         # Use device catalog entry for potential re-classification(s)
404         f_struct "catalog_device_$catalog_struct" get type catalog_type
405
406         # Restore debugging for this next part (device registration)
407         debug="$old_debug"
408
409         #
410         # Register the device
411         #
412         local retval device
413         case "$type" in
414         $GEOM_CLASS_DISK)
415                 # First attempt to classify by device catalog (see MAIN)
416                 case "$catalog_type" in
417                 $DEVICE_TYPE_CDROM)
418                         f_dprintf "Found CDROM device for disk %s" "$devname"
419                         debug= f_device_register device "$devname" "$desc" \
420                                 "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
421                                 f_media_init_cdrom f_media_get_cdrom \
422                                 f_media_shutdown_cdrom "" "$capacity" &&
423                                 return $SUCCESS
424                         ;;
425                 esac
426
427                 # Fall back to register label device as a disk and taste it
428                 f_dprintf "Found disk device named %s" "$devname"
429                 debug= f_struct "$p_provider_config" get \
430                         ident disk_ident ||
431                         debug= f_struct "$provider_config" get \
432                                 ident disk_ident
433                 debug= f_device_register device "$devname" "$desc" \
434                         "/dev/$devname" $DEVICE_TYPE_DISK 1 \
435                         "" "" "" "$disk_ident" "$capacity"
436                 retval=$?
437
438                 # Detect ``dangerously dedicated'' filesystems (errors ignored)
439                 f_device_probe_disk_fs device "$devname" "$capacity" &&
440                         retval=$SUCCESS
441
442                 return $retval
443                 ;;
444         $GEOM_CLASS_FD)
445                 f_dprintf "Found floppy device named %s" "$devname"
446                 debug= f_device_register device "$devname" "$desc" \
447                         "/dev/$devname" $DEVICE_TYPE_FLOPPY 1 \
448                         f_media_init_floppy f_media_get_floppy \
449                         f_media_shutdown_floppy "" "$capacity"
450                 return $?
451                 ;;
452         $GEOM_CLASS_LABEL)
453                 : fall through to below section # reduces indentation level
454                 ;;
455         $GEOM_CLASS_MD)
456                 f_dprintf "Found disk device named %s" "$devname"
457                 debug= f_device_register device "$devname" "$desc" \
458                         "/dev/$devname" $DEVICE_TYPE_DISK 1 \
459                         "" "" "" "" "$capacity"
460                 retval=$?
461
462                 #
463                 # Attempt to get file(1) magic to potentially classify as
464                 # alternate media type. If unable to get magic, fall back to
465                 # md(4) characteristics (such as vnode filename).
466                 #
467                 [ -r "/dev/$devname" ] &&
468                         magic=$( file -bs "/dev/$devname" 2> /dev/null )
469                 if [ ! "$magic" ]; then
470                         # Fall back to md(4) characteristics
471                         if f_struct "$p_provider_config"; then
472                                 config="$p_provider_config"
473                         else
474                                 config="$provider_config"
475                         fi
476                         debug= f_struct "$config" get type config_type
477                         debug= f_struct "$config" get file config_file
478
479                         # Substitute magic for below based on type and file
480                         case "$config_type=$config_file" in
481                         vnode=*.iso) magic="ISO 9660" ;;
482                         esac
483                 fi
484                 f_device_probe_disk_fs device \
485                         "$devname" "$capacity" "$magic" &&
486                         retval=$SUCCESS # Errors ignored
487
488                 return $retval
489                 ;;
490         $GEOM_CLASS_PART)
491                 if f_struct "$p_provider_config"; then
492                         config="$p_provider_config"
493                 else
494                         config="$provider_config"
495                 fi
496                 debug= f_struct "$config" get type provider_config_type
497                 f_device_probe_geom_part device \
498                         "$provider_config_type" "$devname" "$capacity"
499                 retval=$?
500                 device_type=$DEVICE_TYPE_NONE
501                 [ $retval -eq $SUCCESS ] &&
502                         debug= f_struct "$device" get type device_type
503
504                 # Potentially re-classify as USB device
505                 if [ "$device_type" = "$DEVICE_TYPE_UFS" -a \
506                      "$catalog_type" = "$DEVICE_TYPE_USB" ]
507                 then
508                         f_dprintf "Found USB device for partition %s" \
509                                   "$devname"
510                         debug= f_struct "$p_provider_geom" get \
511                                 name disk_name ||
512                                 debug= f_struct "$provider_geom" get \
513                                         name disk_name
514                         debug= f_device_register device "$devname" "$desc" \
515                                 "/dev/$devname" $DEVICE_TYPE_USB 1 \
516                                 f_media_init_usb f_media_get_usb \
517                                 f_media_shutdown_usb "$disk_name" "$capacity"
518                         retval=$?
519                 fi
520
521                 return $retval
522                 ;;
523         $GEOM_CLASS_RAID)
524                 # Use the provider geom name as the description
525                 if [ ! "$desc" ]; then
526                         f_struct "$p_provider_geom" get name desc ||
527                                 f_struct "$provider_geom" get name desc
528                 fi
529
530                 f_dprintf "Found disk device named %s" "$devname"
531                 debug= f_device_register device \
532                         "$devname" "${desc:-GEOM RAID device}" \
533                         "/dev/$devname" $DEVICE_TYPE_DISK 1 \
534                         "" "" "" "" "$capacity"
535                 retval=$?
536                 
537                 # Detect ``dangerously dedicated'' filesystems
538                 f_device_probe_disk_fs device "$devname" "$capacity" &&
539                         retval=$SUCCESS # Errors ignored
540
541                 return $retval
542                 ;;
543         $GEOM_CLASS_ZFS_ZVOL)
544                 f_dprintf "Found disk device named %s" "$devname"
545                 debug= f_device_register device \
546                         "$devname" "${desc:-GEOM ZFS::ZVOL device}" \
547                         "/dev/$devname" $DEVICE_TYPE_DISK 1 \
548                         "" "" "" "" "$capacity"
549                 retval=$?
550                 
551                 # Detect ``dangerously dedicated'' filesystems
552                 f_device_probe_disk_fs device "$devname" "$capacity" &&
553                         retval=$SUCCESS # Errors ignored
554
555                 return $retval
556                 ;;
557         *)
558                 return $FAILURE # Unknown GEOM class
559         esac
560
561         #
562         # Still here? Must be $GEOM_CLASS_LABEL
563         #
564
565         local label_geom label_devname label_devgeom= label_devconsumer
566         local label_devprovider= label_devprovider_ref label_devprovider_config
567         local label_gpart_type
568
569         if f_struct "$p_provider"; then
570                 label_geom="$p_provider_geom"
571         else
572                 label_geom="$provider_geom"
573         fi
574
575         case "$devname" in
576         gpt/*|gptid/*)
577                 #
578                 # Attempt to get the partition type by getting the `config'
579                 # member of the provider for our device (which is named in the
580                 # parent geom of our current provider).
581                 #
582                 debug= f_struct "$label_geom" get name label_devname &&
583                         debug= f_geom_find "$label_devname" $GEOM_CLASS_DEV \
584                                 label_devgeom
585                 debug= f_struct "$label_devgeom" get \
586                         consumer1 label_devconsumer
587                 debug= f_struct "$label_devconsumer" get \
588                         provider_ref label_devprovider_ref &&
589                         debug= f_geom_find_by id "$label_devprovider_ref" \
590                                 provider label_devprovider
591                 debug= f_struct "$label_devprovider" get \
592                         config label_devprovider_config
593                 debug= f_struct "$label_devprovider_config" get \
594                         type label_gpart_type
595
596                 #
597                 # Register device label based on partition type
598                 #
599                 f_device_probe_geom_part device \
600                         "$label_gpart_type" "$devname" "$capacity"
601                 return $?
602                 ;;
603         iso9660/*)
604                 f_dprintf "Found CDROM device labeled %s" "$devname"
605                 debug= f_device_register device \
606                         "$devname" "ISO9660 file system" \
607                         "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
608                         f_media_init_cdrom f_media_get_cdrom \
609                         f_media_shutdown_cdrom "" "$capacity"
610                 return $?
611                 ;;
612         label/*)
613                 # For generic labels, use provider geom name as real device
614                 debug= f_struct "$label_geom" get name label_devname
615
616                 # Look up label geom device in device catalog for default desc
617                 debug= f_device_catalog_get \
618                         $DEVICE_TYPE_ANY "$label_devname" catalog_struct
619                 [ "$desc" ] || debug= f_struct \
620                         "catalog_device_$catalog_struct" get desc desc
621
622                 # Use device catalog entry for potential re-classification(s)
623                 debug= f_struct "catalog_device_$catalog_struct" get \
624                         type catalog_type
625
626                 # First attempt to classify by device catalog (see MAIN)
627                 case "$catalog_type" in
628                 $DEVICE_TYPE_CDROM)
629                         f_dprintf "Found CDROM device for disk %s" "$devname"
630                         debug= f_device_register device "$devname" "$desc" \
631                                 "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
632                                 f_media_init_cdrom f_media_get_cdrom \
633                                 f_media_shutdown_cdrom "" "$capacity" &&
634                                 return $SUCCESS
635                         ;;
636                 esac
637
638                 # Fall back to register label device as a disk and taste it
639                 f_dprintf "Found disk device labeled %s" "$devname"
640                 debug= f_device_register device \
641                         "$devname" "GEOM LABEL device" \
642                         "/dev/$devname" $DEVICE_TYPE_DISK 1 \
643                         "" "" "" "" "$capacity"
644                 retval=$?
645
646                 # Detect ``dangerously dedicated'' filesystems (errors ignored)
647                 f_device_probe_disk_fs device "$devname" "$capacity" &&
648                         retval=$SUCCESS
649
650                 return $retval
651                 ;;
652         msdosfs/*)
653                 f_dprintf "Found DOS partition labeled %s" "$devname"
654                 debug= f_device_register device "$devname" "DOS file system" \
655                         "/dev/$devname" $DEVICE_TYPE_DOS 1 \
656                         f_media_init_dos f_media_get_dos \
657                         f_media_shutdown_dos "" "$capacity"
658                 return $?
659                 ;;
660         ufs/*|ufsid/*)
661                 f_dprintf "Found UFS partition labeled %s" "$devname"
662                 debug= f_device_register device "$devname" "UFS file system" \
663                         "/dev/$devname" $DEVICE_TYPE_UFS 1 \
664                         f_media_init_ufs f_media_get_ufs \
665                         f_media_shutdown_ufs "" "$capacity"
666                 return $?
667                 ;;
668         ext2fs/*|ntfs/*|reiserfs/*)
669                 return $FAILURE # No media device handlers for these labels
670                 ;;
671         esac
672
673         # Unable to classify GEOM label
674         return $FAILURE
675 }
676
677 # f_device_probe_geom_part $var_to_set $gpart_type $devname $capacity [$magic]
678 #
679 # Given a gpart(8) partition type and a device name, register the device if it
680 # is a known partition type that we can handle. If $var_to_set is non-NULL,
681 # upon success holds the DEVICE struct name of the registered device.
682 #
683 # Returns success if the device was successfully registered, failure otherwise.
684 #
685 f_device_probe_geom_part()
686 {
687         local __var_to_set="$1" __gpart_type="$2" __devname="$3"
688         local __capacity="${4:--1}" __magic="$5"
689
690         #
691         # Register device based on partition type
692         # NB: !0 equates to `unused' bsdlabel
693         #
694         case "$__gpart_type" in
695         fat16|fat32)
696                 f_dprintf "Found DOS partition named %s" "$__devname"
697                 debug= f_device_register "$__var_to_set" \
698                         "$__devname" "DOS file system" \
699                         "/dev/$__devname" $DEVICE_TYPE_DOS 1 \
700                         f_media_init_dos f_media_get_dos \
701                         f_media_shutdown_dos "" "$__capacity"
702                 return $?
703                 ;;
704         freebsd|!0) # Commonly used inappropriately, taste for FreeBSD
705                 [ -r "/dev/$__devname" -a ! "$__magic" ] &&
706                         __magic=$( file -bs "/dev/$__devname" 2> /dev/null )
707                 case "$__magic" in
708                 *"Unix Fast File system"*)
709                         f_dprintf "Found UFS partition named %s" "$__devname"
710                         debug= f_device_register "$__var_to_set" \
711                                 "$__devname" "UFS file system" \
712                                 "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
713                                 f_media_init_ufs f_media_get_ufs \
714                                 f_media_shutdown_ufs "" "$__capacity"
715                         return $?
716                 esac
717                 return $FAILURE
718                 ;;
719         freebsd-ufs)
720                 f_dprintf "Found UFS partition named %s" "$__devname"
721                 debug= f_device_register "$__var_to_set" \
722                         "$__devname" "UFS file system" \
723                         "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
724                         f_media_init_ufs f_media_get_ufs \
725                         f_media_shutdown_ufs "" "$__capacity"
726                 return $?
727                 ;;
728         apple-*|linux-*|ms-*|netbsd-*|ntfs|vmware-*)
729                 return $FAILURE # No device types for these
730                 ;;
731         bios-*|ebr|efi|mbr|freebsd-boot|freebsd-swap)
732                 return $FAILURE # Not a source for media
733                 ;;
734         freebsd-nandfs|freebsd-vinum|freebsd-zfs)
735                 return $FAILURE # Unsupported as media source
736                 ;;
737         esac
738
739         return $FAILURE # Unknown partition type
740 }
741
742 # f_device_probe_disk_fs $var_to_set $devname [$capacity [$magic]]
743 #
744 # Given a device name, taste it and register the device if it is a so-called
745 # ``dangerously dedicated'' file system written without a partition table.
746 # Tasting is done using file(1) (specifically `file -bs') but if $magic is
747 # present and non-NULL it is used instead. If $var_to_set is non-NULL, upon
748 # success holds the DEVICE struct name of the registered device.
749 #
750 # Returns success if the device was successfully registered, failure otherwise.
751 #
752 f_device_probe_disk_fs()
753 {
754         local __var_to_set="$1" __devname="$2" __capacity="${3:--1}"
755         local __magic="$4"
756
757         [ -r "/dev/${__devname#/dev/}" -a ! "$__magic" ] &&
758                 __magic=$( file -bs "/dev/$__devname" 2> /dev/null )
759
760         case "$__magic" in
761         *"ISO 9660"*)
762                 f_dprintf "Found CDROM device for disk %s" "$__devname"
763                 debug= f_device_register "$__var_to_set" \
764                         "$__devname" "ISO9660 file system" \
765                         "/dev/$__devname" $DEVICE_TYPE_CDROM 1 \
766                         f_media_init_cdrom f_media_get_cdrom \
767                         f_media_shutdown_cdrom "" "$__capacity"
768                 return $?
769                 ;;
770         *"Unix Fast File system"*)
771                 f_dprintf "Found UFS device for disk %s" "$__devname"
772                 debug= f_device_register "$__var_to_set" \
773                         "$__devname" "UFS file system" \
774                         "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
775                         f_media_init_ufs f_media_get_ufs \
776                         f_media_shutdown_ufs "" "$__capacity"
777                 return $?
778                 ;;
779         *"FAT (12 bit)"*|*"FAT (16 bit)"*|*"FAT (32 bit)"*)
780                 f_dprintf "Found DOS device for disk %s" "$__devname"
781                 debug= f_device_register "$__var_to_set" \
782                         "$__devname" "DOS file system" \
783                         "/dev/$__devname" $DEVICE_TYPE_DOS 1 \
784                         f_media_init_dos f_media_get_dos \
785                         f_media_shutdown_dos "" "$__capacity"
786                 return $?
787                 ;;
788         esac
789
790         return $FAILURE # Unknown file system type
791 }
792
793 # f_device_catalog_get $type $name [$var_to_set]
794 #
795 # Fetch the struct name of the catalog device matching device $name. If $type
796 # is either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used.
797 # Returns success if a match was found, otherwise failure.
798 #
799 # If $var_to_set is missing or NULL, the struct name is printed to standard out
800 # for capturing in a sub-shell (which is less-recommended because of
801 # performance degredation; for example, when called in a loop).
802 #
803 f_device_catalog_get()
804 {
805         local __type="$1" __name="$2" __var_to_set="$3"
806         local __dname=
807
808         # Return failure if no $name
809         [ "$__name" ] || return $FAILURE
810
811         # Disable debugging to keep debug output light
812         local debug=
813
814         #
815         # Attempt to create an alternate-form of $__name that contains the
816         # first contiguous string of numbers replaced with `%d' for comparison
817         # against stored pattern names (see MAIN).
818         #
819         local __left="${__name%%[0-9]*}" __right="${__name#*[0-9]}"
820         if [ "$__left" != "$__name" ]; then
821                 # Chop leading digits from right 'til we hit first non-digit
822                 while :; do
823                         case "$__right" in
824                         [0-9]*) __right="${__right#[0-9]}" ;;
825                              *) break
826                         esac
827                 done
828                 __dname="${__left}%d$__right"
829         fi
830
831         [ "$__type" = "$DEVICE_TYPE_ANY" ] && __type=
832         local __dev __dev_name __dev_type
833         for __dev in $DEVICE_CATALOG; do
834                 catalog_device_$__dev get name __dev_name
835                 [ "$__dev_name" = "$__name" -o "$__dev_name" = "$__dname" ] ||
836                         continue
837                 catalog_device_$__dev get type __dev_type
838                 [ "${__type:-$__dev_type}" = "$__dev_type" ] || continue
839                 if [ "$__var_to_set" ]; then
840                         setvar "$__var_to_set" $__dev
841                 else
842                         echo $__dev
843                 fi
844                 return $?
845         done
846
847         [ "$__var_to_set" ] && setvar "$__var_to_set" ""
848         return $FAILURE
849 }
850
851 # f_device_catalog_set $type $name $desc
852 #
853 # Store a description (desc) in-association with device $type and $name.
854 # Returns success unless $name is NULL or missing. Use f_device_catalog_get()
855 # routine with the same $name and optionally $type to retrieve catalog device
856 # structure (see CATALOG_DEVICE struct definition in GLOBALS section).
857 #
858 f_device_catalog_set()
859 {
860         local type="$1" name="$2" desc="$3"
861         local struct dev dev_type found=
862
863         [ "$name" ] || return $FAILURE
864
865         # Disable debugging to keep debug output light
866         local debug=
867
868         f_str2varname "$name" struct
869         if [ ! "$DEVICE_CATALOG_APPEND_ONLY" ]; then
870                 for dev in $DEVICE_CATALOG; do
871                         [ "$dev" = "$struct" ] || continue
872                         found=1 break
873                 done
874         fi
875         if [ "$found" ]; then
876                 f_struct_free "catalog_device_$struct"
877         else
878                 DEVICE_CATALOG="$DEVICE_CATALOG $struct"
879         fi
880         f_struct_new CATALOG_DEVICE "catalog_device_$struct" || return $FAILURE
881         catalog_device_$struct set type "$type"
882         catalog_device_$struct set name "$name"
883         catalog_device_$struct set desc "$desc"
884         return $SUCCESS
885 }
886
887 # f_device_desc $device_name $device_type [$var_to_set]
888 #
889 # Print a description for a device name (eg., `fxp0') given a specific device
890 # type/class.
891 #
892 # If $var_to_set is missing or NULL, the device description is printed to
893 # standard out for capturing in a sub-shell (which is less-recommended because
894 # of performance degredation; for example, when called in a loop).
895 #
896 f_device_desc()
897 {
898         local __name="$1" __type="$2" __var_to_set="$3"
899         local __devname __devunit __cp
900
901         # Check variables
902         [ "$__name" ] || return $SUCCESS
903         [ "$__type" = "$DEVICE_TYPE_ANY" ] && type=
904         [ "$__var_to_set" ] && { setvar "$__var_to_set" "" || return; }
905
906         #
907         # Return sysctl MIB dev.NAME.UNIT.%desc if it exists, otherwise fall
908         # through to further alternate methods.
909         #
910         if f_have sysctl; then
911                 __devname="${__name%%[0-9]*}"
912                 __devunit="${__name#$__devname}"
913                 __devunit="${__devunit%%[!0-9]*}"
914                 if [ "$__var_to_set" ]; then
915                         if __cp=$(
916                                 sysctl -n "dev.$__devname.$__devunit.%desc" \
917                                 2> /dev/null
918                         ); then
919                                 setvar "$__var_to_set" "$__cp" &&
920                                         return $SUCCESS
921                         fi
922                 else
923                         sysctl -n "dev.$__devname.$__devunit.%desc" \
924                                 2> /dev/null && return $SUCCESS
925                 fi
926         fi
927
928         # Look up device in catalog for default description
929         local __catalog_struct
930         debug= f_device_catalog_get "$__type" "$__name" __catalog_struct
931         debug= f_struct "catalog_device_$__catalog_struct" get \
932                 desc "$__var_to_set" && return $SUCCESS
933
934         #
935         # Sensible fall-backs for specific types
936         #
937         case "$__type" in
938         $DEVICE_TYPE_CDROM)   __cp="<unknown cdrom device type>" ;;
939         $DEVICE_TYPE_DISK)    __cp="<unknown disk device type>" ;;
940         $DEVICE_TYPE_FLOPPY)  __cp="<unknown floppy device type>" ;;
941         $DEVICE_TYPE_USB)     __cp="<unknown USB storage device type>" ;;
942         $DEVICE_TYPE_NETWORK) __cp="<unknown network interface type>" ;;
943         *)
944                 __cp="<unknown device type>"
945         esac
946
947         if [ "$__var_to_set" ]; then
948                 setvar "$__var_to_set" "$__cp"
949         else
950                 echo "$__cp"
951         fi
952
953         return $FAILURE
954 }
955
956 # f_device_is_ethernet $device
957 #
958 # Returns true if $device is a wired Ethernet network interface. Otherwise
959 # returns false. Example wired interfaces include: fxp0 em0 bge0 rl0 etc.
960 #
961 f_device_is_ethernet()
962 {
963         local dev="$1" type flags
964
965         # Make sure we have an actual device by that name
966         f_struct "$dev" || return $FAILURE
967
968         # Make sure that the device is a network device
969         $dev get type type
970         [ "$type" = "$DEVICE_TYPE_NETWORK" ] || return $FAILURE
971
972         # Make sure that the media flags indicate that it is Ethernet
973         $dev get flags flags
974         [ $(( ${flags:-0} & $IF_ETHERNET )) -eq $IF_ETHERNET ]
975 }
976
977 # f_device_is_wireless $device
978 #
979 # Returns true if $device is a Wireless network interface. Otherwise returns
980 # false. Examples of wireless interfaces include: iwn0
981 #
982 f_device_is_wireless()
983 {
984         local dev="$1" type flags
985
986         # Make sure we have an actual device by that name
987         f_struct "$dev" || return $FAILURE
988
989         # Make sure that the device is a network device
990         $dev get type type
991         [ "$type" = "$DEVICE_TYPE_NETWORK" ] || return $FAILURE
992
993         # Make sure that the media flags indicate that it is 802.11 wireless
994         $dev get flags flags
995         [ $(( ${flags:-0} & $IF_WIRELESS )) -eq $IF_WIRELESS ]
996 }
997
998 # f_device_is_active $device
999 #
1000 # Returns true if $device is active. Otherwise returns false. Currently this
1001 # only works for network interfaces.
1002 #
1003 f_device_is_active()
1004 {
1005         local dev="$1" type flags=0
1006
1007         # Make sure we have an actual device by that name
1008         f_struct "$dev" || return $FAILURE
1009
1010         $dev get type type
1011         case "$type" in
1012         $DEVICE_TYPE_NETWORK)
1013                 # Make sure that the media flags indicate that it is active
1014                 $dev get flags flags
1015                 [ $(( ${flags:-0} & $IF_ACTIVE )) -eq $IF_ACTIVE ]
1016                 ;;
1017         *)
1018                 return $FAILURE
1019         esac
1020 }
1021
1022 # f_device_find [-1] $name [$type [$var_to_set]] 
1023 #
1024 # Find one or more registered devices by name, type, or both. Returns a space-
1025 # separated list of devices matching the search criterion.
1026 #
1027 # If `-1' option flag is given, only the first matching device is returned.
1028 #
1029 # If $var_to_set is missing or NULL, the device name(s) are printed to standard
1030 # out for capturing in a sub-shell (which is less-recommended because of
1031 # performance degredation; for example, when called in a loop).
1032 #
1033 f_device_find()
1034 {
1035         local OPTIND OPTARG flag only_one=
1036         while getopts 1 flag; do
1037                 case "$flag" in
1038                 1) only_one=1 ;;
1039                 esac
1040         done
1041         shift $(( $OPTIND - 1 ))
1042
1043         local __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3"
1044         local __n=1 __devname __devtype __found=
1045         while [ $__n -le $NDEVICES ]; do
1046                 device_$__n get name __devname
1047                 device_$__n get type __devtype
1048                 if [ "$__name" = "$__devname" -o ! "$__name" ] &&
1049                    [ "$__type" = "$DEVICE_TYPE_ANY" -o \
1050                      "$__type" = "$__devtype" ]
1051                 then
1052                         __found="$__found device_$__n"
1053                         [ "$only_one" ] && break
1054                 fi
1055                 __n=$(( $__n + 1 ))
1056         done
1057
1058         if [ "$__var_to_set" ]; then
1059                 setvar "$__var_to_set" "${__found# }"
1060         else
1061                 echo $__found
1062         fi
1063         [ "$__found" ] # Return status
1064 }
1065
1066 # f_device_init $device
1067 #
1068 # Initialize a device by evaluating its `init' function. The $device argument
1069 # is a DEVICE struct name.
1070 #
1071 f_device_init()
1072 {
1073         local device="$1" init_func
1074         f_struct "$device" || return $?
1075         $device get init init_func
1076         ${init_func:-:} "$device"
1077 }
1078
1079 # f_device_get $device $file [$probe]
1080 #
1081 # Read $file by evaluating the device's `get' function. The file is commonly
1082 # produced on standard output (but it truly depends on the function called).
1083 # The $device argument is a DEVICE struct name.
1084 #
1085 f_device_get()
1086 {
1087         local device="$1" file="$2" probe="$3" get_func
1088         f_struct "$device" || return $?
1089         $device get get get_func
1090         ${get_func:-:} "$device" "$file" ${3+"$probe"}
1091 }
1092
1093 # f_device_shutdown $device
1094 #
1095 # Shutdown a device by evaluating its `shutdown' function. The $device argument
1096 # is a DEVICE struct name.
1097 #
1098 f_device_shutdown()
1099 {
1100         local device="$1" shutdown_func
1101         f_struct "$device" || return $?
1102         $device get shutdown shutdown_func
1103         ${shutdown_func:-:} "$device"
1104 }
1105
1106 # f_devices_sort_by $property $var_to_get [$var_to_set]
1107 #
1108 # Take list of devices from $var_to_get (separated by whitespace, newline
1109 # included) and sort them by $property (e.g., `name'). The sorted list of
1110 # DEVICE struct names is returned on standard output separated by whitespace
1111 # (newline to be specific) unless $var_to_set is present and non-NULL.
1112 #
1113 # This function is a two-parter. Below is the awk(1) portion of the function,
1114 # afterward is the sh(1) function which utilizes the below awk script.
1115 #
1116 f_device_sort_by_awk='
1117 # Variables that should be defined on the invocation line:
1118 #       -v prop="property"
1119 function _asorti(src, dest)
1120 {
1121         k = nitems = 0
1122         for (i in src) dest[++nitems] = i
1123         for (i = 1; i <= nitems; k = i++) {
1124                 idx = dest[i]
1125                 while ((k > 0) && (dest[k] > idx)) {
1126                         dest[k+1] = dest[k]; k--
1127                 }
1128                 dest[k+1] = idx
1129         }
1130         return nitems
1131 }
1132 {
1133         split($0, devs, FS)
1134         for (d in devs) {
1135                 name = ENVIRON["_struct_value_" devs[d] "_" prop]
1136                 devices[name] = devs[d]
1137         }
1138 }
1139 END {
1140         nitems = _asorti(devices, devices_sorted)
1141         for (i = 1; i <= nitems; i++) print devices[devices_sorted[i]]
1142 }
1143 '
1144 f_device_sort_by()
1145 {
1146         local __property="${1:-name}" __var_to_get="$2" __var_to_set="$3"
1147
1148         f_isset "$__var_to_get" || return $FAILURE
1149
1150         local __dev
1151         for __dev in $( f_getvar "$__var_to_get" ); do
1152                 export _struct_value_${__dev}_$__property
1153         done
1154
1155         local __cp
1156         setvar "${__var_to_set:-__cp}" "$(
1157                 f_getvar "$__var_to_get" |
1158                         awk -v prop="$__property" "$f_device_sort_by_awk"
1159         )"
1160         [ "$__var_to_set" ] || echo "$__cp"
1161 }
1162
1163 # f_device_menu $title $prompt $hline $device_type [$helpfile]
1164 #
1165 # Display a menu listing all the devices of a certain type in the system.
1166 #
1167 f_device_menu()
1168 {
1169         f_dialog_title "$1"
1170         local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
1171         f_dialog_title_restore
1172
1173         local prompt="$2" hline="$3" type="$4" helpfile="$5"
1174
1175         local devs
1176         f_device_find "" "$type" devs || return $DIALOG_CANCEL
1177
1178         local name desc menu_list=
1179         f_device_sort_by name devs devs
1180         for dev in $devs; do
1181                 $dev get name name
1182                 $dev get desc desc
1183                 f_shell_escape "$name" name
1184                 f_shell_escape "$desc" desc
1185                 menu_list="$menu_list
1186                         '$name' '$desc'" # END-QUOTE
1187         done
1188         menu_list="${menu_list#$NL}"
1189
1190         local height width rows
1191         eval f_dialog_menu_size height width rows \
1192                                 \"\$title\"  \
1193                                 \"\$btitle\" \
1194                                 \"\$prompt\" \
1195                                 \"\$hline\"  \
1196                                 $menu_list
1197
1198         local errexit=
1199         case $- in *e*) errexit=1; esac
1200         set +e
1201
1202         local mtag
1203         while :; do
1204                 mtag=$( eval $DIALOG \
1205                         --title \"\$title\"             \
1206                         --backtitle \"\$btitle\"        \
1207                         --hline \"\$hline\"             \
1208                         --ok-label \"\$msg_ok\"         \
1209                         --cancel-label \"\$msg_cancel\" \
1210                         ${helpfile:+                    \
1211                           --help-button                 \
1212                           --help-label \"\$msg_help\"   \
1213                           ${USE_XDIALOG:+--help \"\"}   \
1214                         }                               \
1215                         --menu \"\$prompt\"             \
1216                         $height $width $rows            \
1217                         $menu_list                      \
1218                         2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
1219                 )
1220                 local retval=$?
1221
1222                 [ $retval -ne $DIALOG_HELP ] && break
1223                         # Otherwise, the Help button was pressed
1224                 f_show_help "$helpfile"
1225                         # ...then loop back to menu
1226         done
1227         f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
1228
1229         [ "$errexit" ] && set -e
1230
1231         if [ $retval -eq $DIALOG_OK ]; then
1232                 # Clean up the output of [X]dialog(1)
1233                 f_dialog_data_sanitize mtag
1234
1235                 # Map the user's choice back to a struct name
1236                 local index device
1237                 index=$( eval f_dialog_menutag2index \"\$mtag\" $menu_list )
1238                 device=$( set -- $devs; eval echo \${$index} )
1239
1240                 echo "$device" >&2
1241         fi
1242
1243         return $retval
1244 }
1245
1246 #
1247 # Short-hand
1248 #
1249 f_cdrom()   { f_device_catalog_set $DEVICE_TYPE_CDROM   "$1" "$2"; }
1250 f_disk()    { f_device_catalog_set $DEVICE_TYPE_DISK    "$1" "$2"; }
1251 f_floppy()  { f_device_catalog_set $DEVICE_TYPE_FLOPPY  "$1" "$2"; }
1252 f_usb()     { f_device_catalog_set $DEVICE_TYPE_USB     "$1" "$2"; }
1253 f_network() { f_device_catalog_set $DEVICE_TYPE_NETWORK "$1" "$2"; }
1254
1255 ############################################################ MAIN
1256
1257 #
1258 # The below classifications allow us to re-group the GEOM devices from the
1259 # `DEV' GEOM class appropriately while providing fall-back descriptions both
1260 # for making the below code more maintainable and handling the rare case the
1261 # GEOM device lacks a description.
1262 #
1263
1264 DEVICE_CATALOG_APPEND_ONLY=1 # Make initial loading faster
1265
1266 # CDROM, Disk, Floppy, and USB devices/names
1267 f_cdrom  "cd%d"   "SCSI CDROM drive"
1268 f_cdrom  "mcd%d"  "Mitsumi (old model) CDROM drive"
1269 f_cdrom  "scd%d"  "Sony CDROM drive - CDU31/33A type"
1270 f_disk   "aacd%d" "Adaptec FSA RAID array"
1271 f_disk   "ada%d"  "ATA/SATA disk device"
1272 f_disk   "amrd%d" "AMI MegaRAID drive"
1273 f_disk   "da%d"   "SCSI disk device"
1274 f_disk   "idad%d" "Compaq RAID array"
1275 f_disk   "ipsd%d" "IBM ServeRAID RAID array"
1276 f_disk   "md%d"   "md(4) disk device"
1277 f_disk   "mfid%d" "LSI MegaRAID SAS array"
1278 f_disk   "mlxd%d" "Mylex RAID disk"
1279 f_disk   "twed%d" "3ware ATA RAID array"
1280 f_disk   "vtbd%d" "VirtIO Block Device"
1281 f_floppy "fd%d"   "Floppy Drive unit A"
1282 f_usb    "da%da"  "USB Mass Storage Device"
1283
1284 # Network interfaces/names
1285 f_network "ae%d"    "Attansic/Atheros L2 Fast Ethernet"
1286 f_network "age%d"   "Attansic/Atheros L1 Gigabit Ethernet"
1287 f_network "alc%d"   "Atheros AR8131/AR8132 PCIe Ethernet"
1288 f_network "ale%d"   "Atheros AR8121/AR8113/AR8114 PCIe Ethernet"
1289 f_network "an%d"    "Aironet 4500/4800 802.11 wireless adapter"
1290 f_network "ath%d"   "Atheros IEEE 802.11 wireless adapter"
1291 f_network "aue%d"   "ADMtek USB Ethernet adapter"
1292 f_network "axe%d"   "ASIX Electronics USB Ethernet adapter"
1293 f_network "bce%d"   "Broadcom NetXtreme II Gigabit Ethernet card"
1294 f_network "bfe%d"   "Broadcom BCM440x PCI Ethernet card"
1295 f_network "bge%d"   "Broadcom BCM570x PCI Gigabit Ethernet card"
1296 f_network "bm%d"    "Apple BMAC Built-in Ethernet"
1297 f_network "bwn%d"   "Broadcom BCM43xx IEEE 802.11 wireless adapter"
1298 f_network "cas%d"   "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet"
1299 f_network "cc3i%d"  "SDL HSSI sync serial PCI card"
1300 f_network "cue%d"   "CATC USB Ethernet adapter"
1301 f_network "cxgb%d"  "Chelsio T3 10Gb Ethernet card"
1302 f_network "dc%d"    "DEC/Intel 21143 (and clones) PCI Fast Ethernet card"
1303 f_network "de%d"    "DEC DE435 PCI NIC or other DC21040-AA based card"
1304 f_network "disc%d"  "Software discard network interface"
1305 f_network "ed%d"    "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA"
1306 f_network "el%d"    "3Com 3C501 Ethernet card"
1307 f_network "em%d"    "Intel(R) PRO/1000 Ethernet card"
1308 f_network "en%d"    "Efficient Networks ATM PCI card"
1309 f_network "ep%d"    "3Com 3C509 Ethernet card/3C589 PCMCIA"
1310 f_network "et%d"    "Agere ET1310 based PCI Express Gigabit Ethernet card"
1311 f_network "ex%d"    "Intel EtherExpress Pro/10 Ethernet card"
1312 f_network "fe%d"    "Fujitsu MB86960A/MB86965A Ethernet card"
1313 f_network "fpa%d"   "DEC DEFPA PCI FDDI card"
1314 f_network "fwe%d"   "FireWire Ethernet emulation"
1315 f_network "fwip%d"  "IP over FireWire"
1316 f_network "fxp%d"   "Intel EtherExpress Pro/100B PCI Fast Ethernet card"
1317 f_network "gem%d"   "Apple GMAC or Sun ERI/GEM Ethernet adapter"
1318 f_network "hme%d"   "Sun HME (Happy Meal Ethernet) Ethernet adapter"
1319 f_network "ie%d"    "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210"
1320 f_network "igb%d"   "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card"
1321 f_network "ipw%d"   "Intel PRO/Wireless 2100 IEEE 802.11 adapter"
1322 f_network "iwi%d"   "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter"
1323 f_network "iwn%d"   "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter"
1324 f_network "ix%d"    "Intel Etherexpress Ethernet card"
1325 f_network "ixgb%d"  "Intel(R) PRO/10Gb Ethernet card"
1326 f_network "ixgbe%d" "Intel(R) PRO/10Gb Ethernet card"
1327 f_network "jme%d"   "JMicron JMC250 Gigabit/JMC260 Fast Ethernet"
1328 f_network "kue%d"   "Kawasaki LSI USB Ethernet adapter"
1329 f_network "le%d"    "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter"
1330 f_network "lge%d"   "Level 1 LXT1001 Gigabit Ethernet card"
1331 f_network "lnc%d"   "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet"
1332 f_network "lo%d"    "Loop-back (local) network interface"
1333 f_network "lp%d"    "Parallel Port IP (PLIP) peer connection"
1334 f_network "malo%d"  "Marvell Libertas 88W8335 802.11 wireless adapter"
1335 f_network "msk%d"   "Marvell/SysKonnect Yukon II Gigabit Ethernet"
1336 f_network "mxge%d"  "Myricom Myri10GE 10Gb Ethernet card"
1337 f_network "nfe%d"   "NVIDIA nForce MCP Ethernet"
1338 f_network "ng%d"    "Vimage netgraph(4) bridged Ethernet device"
1339 f_network "nge%d"   "NatSemi PCI Gigabit Ethernet card"
1340 f_network "nve%d"   "NVIDIA nForce MCP Ethernet"
1341 f_network "nxge%d"  "Neterion Xframe 10GbE Server/Storage adapter"
1342 f_network "pcn%d"   "AMD Am79c79x PCI Ethernet card"
1343 f_network "plip%d"  "Parallel Port IP (PLIP) peer connection"
1344 f_network "ral%d"   "Ralink Technology IEEE 802.11 wireless adapter"
1345 f_network "ray%d"   "Raytheon Raylink 802.11 wireless adapter"
1346 f_network "re%d"    "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter"
1347 f_network "rl%d"    "RealTek 8129/8139 PCI Ethernet card"
1348 f_network "rue%d"   "RealTek USB Ethernet card"
1349 f_network "rum%d"   "Ralink Technology USB IEEE 802.11 wireless adapter"
1350 f_network "sf%d"    "Adaptec AIC-6915 PCI Ethernet card"
1351 f_network "sge%d"   "Silicon Integrated Systems SiS190/191 Ethernet"
1352 f_network "sis%d"   "SiS 900/SiS 7016 PCI Ethernet card"
1353 f_network "sk%d"    "SysKonnect PCI Gigabit Ethernet card"
1354 f_network "sn%d"    "SMC/Megahertz Ethernet card"
1355 f_network "snc%d"   "SONIC Ethernet card"
1356 f_network "sr%d"    "SDL T1/E1 sync serial PCI card"
1357 f_network "ste%d"   "Sundance ST201 PCI Ethernet card"
1358 f_network "stge%d"  "Sundance/Tamarack TC9021 Gigabit Ethernet"
1359 f_network "ti%d"    "Alteon Networks PCI Gigabit Ethernet card"
1360 f_network "tl%d"    "Texas Instruments ThunderLAN PCI Ethernet card"
1361 f_network "tx%d"    "SMC 9432TX Ethernet card"
1362 f_network "txp%d"   "3Com 3cR990 Ethernet card"
1363 f_network "uath%d"  "Atheros AR5005UG and AR5005UX USB wireless adapter"
1364 f_network "upgt%d"  "Conexant/Intersil PrismGT USB wireless adapter"
1365 f_network "ural%d"  "Ralink Technology RT2500USB 802.11 wireless adapter"
1366 f_network "urtw%d"  "Realtek 8187L USB wireless adapter"
1367 f_network "vge%d"   "VIA VT612x PCI Gigabit Ethernet card"
1368 f_network "vlan%d"  "IEEE 802.1Q VLAN network interface"
1369 f_network "vr%d"    "VIA VT3043/VT86C100A Rhine PCI Ethernet card"
1370 f_network "vx%d"    "3COM 3c590 / 3c595 Ethernet card"
1371 f_network "wb%d"    "Winbond W89C840F PCI Ethernet card"
1372 f_network "wi%d"    "Lucent WaveLAN/IEEE 802.11 wireless adapter"
1373 f_network "wpi%d"   "Intel 3945ABG IEEE 802.11 wireless adapter"
1374 f_network "wx%d"    "Intel Gigabit Ethernet (82452) card"
1375 f_network "xe%d"    "Xircom/Intel EtherExpress Pro100/16 Ethernet card"
1376 f_network "xl%d"    "3COM 3c90x / 3c90xB PCI Ethernet card"
1377 f_network "zyd%d"   "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter"
1378
1379 DEVICE_CATALOG_APPEND_ONLY= # Additional loading modifies existing devices
1380
1381 f_count NCATALOG_DEVICES $DEVICE_CATALOG
1382 f_dprintf "%s: Initialized device catalog with %u names/descriptions." \
1383           device.subr $NCATALOG_DEVICES
1384
1385 #
1386 # Scan for the above devices unless requeted otherwise
1387 #
1388 f_dprintf "%s: DEVICE_SELF_SCAN_ALL=[%s]" device.subr "$DEVICE_SELF_SCAN_ALL"
1389 case "$DEVICE_SELF_SCAN_ALL" in
1390 ""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
1391 *) f_device_get_all
1392 esac
1393
1394 f_dprintf "%s: Successfully loaded." device.subr
1395
1396 fi # ! $_DEVICE_SUBR