diff options
-rw-r--r-- | sys/kern/bus_if.m | 18 | ||||
-rw-r--r-- | sys/kern/device_if.m | 43 | ||||
-rw-r--r-- | sys/kern/makedevops.pl | 58 | ||||
-rw-r--r-- | sys/kern/subr_bus.c | 61 | ||||
-rw-r--r-- | sys/sys/bus_private.h | 14 |
5 files changed, 160 insertions, 34 deletions
diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m index d7c9cd4a8501..33383ff6c2bd 100644 --- a/sys/kern/bus_if.m +++ b/sys/kern/bus_if.m @@ -23,12 +23,26 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# $Id: bus_if.m,v 1.7 1999/04/16 21:22:37 peter Exp $ +# $Id: bus_if.m,v 1.8 1999/05/08 21:59:34 dfr Exp $ # INTERFACE bus; # +# Default implementations of some methods. +# +CODE { + static struct resource * + null_alloc_resource(device_t dev, device_t child, + int type, int *rid, + u_long start, u_long end, + u_long count, u_int flags) + { + return 0; + } +}; + +# # This is called from system code which prints out a description of a # device. It should describe the attachment that the child has with # the parent. For instance the TurboLaser bus prints which node the @@ -112,7 +126,7 @@ METHOD struct resource * alloc_resource { u_long end; u_long count; u_int flags; -}; +} DEFAULT null_alloc_resource; METHOD int activate_resource { device_t dev; diff --git a/sys/kern/device_if.m b/sys/kern/device_if.m index f429e67759a0..0d8e8f425111 100644 --- a/sys/kern/device_if.m +++ b/sys/kern/device_if.m @@ -23,14 +23,47 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# $Id: device_if.m,v 1.2 1998/11/08 18:35:53 nsouch Exp $ +# $Id: device_if.m,v 1.3 1998/11/14 21:58:51 wollman Exp $ # INTERFACE device; # +# Default implementations of some methods. +# +CODE { + static int null_shutdown(device_t dev) + { + return 0; + } + + static int null_suspend(device_t dev) + { + return 0; + } + + static int null_resume(device_t dev) + { + return 0; + } +}; + +# # Probe to see if the device is present. Return 0 if the device exists, -# ENXIO if it cannot be found. +# ENXIO if it cannot be found. For cases where more than one driver +# matches a device, a priority value can be returned. In this case, +# success codes are values less than or equal to zero with the highest +# value representing the best match. Failure codes are represented by +# positive values and the regular unix error codes should be used for +# the purpose. +# +# If a driver returns a success code which is less than zero, it must +# not assume that it will be the same driver which is attached to the +# device. In particular, it must not assume that any values stored in +# the softc structure will be available for its attach method and any +# resources allocated during probe must be released and re-allocated +# if the attach method is called. If a success code of zero is +# returned, the driver can assume that it will be the one attached. # # Devices which implement busses should use this method to probe for # the existence of devices attached to the bus and add them as @@ -66,7 +99,7 @@ METHOD int detach { # METHOD int shutdown { device_t dev; -}; +} DEFAULT null_shutdown; # # This is called by the power-management subsystem when a suspend has been @@ -76,8 +109,8 @@ METHOD int shutdown { # METHOD int suspend { device_t dev; -}; +} DEFAULT null_suspend; METHOD int resume { device_t dev; -}; +} DEFAULT null_resume; diff --git a/sys/kern/makedevops.pl b/sys/kern/makedevops.pl index 8b991b7984b8..0ab8e69a5916 100644 --- a/sys/kern/makedevops.pl +++ b/sys/kern/makedevops.pl @@ -35,7 +35,7 @@ # From @(#)makedevops.sh 1.1 1998/06/14 13:53:12 dfr Exp $ # From @(#)makedevops.sh ?.? 1998/10/05 # -# $Id$ +# $Id: makedevops.pl,v 1.6 1999/05/02 08:55:27 markm Exp $ # # Script to produce device front-end sugar. @@ -219,7 +219,18 @@ foreach $src ( @filenames ) { print CFILE '#include "'.$intname.'_if.h"'."\n\n" if $cfile; - } elsif ( $line =~ m/^METHOD/i ) { + } elsif ( $line =~ m/^CODE\s*{$/i ) { + $code = ""; + $line = <SRC>; + while ( $line !~ m/^}/ ) { + $code .= $line; + $line = <SRC>; + $lineno++ + } + if ( $cfile ) { + print CFILE $code; + } + } elsif ( $line =~ m/^(STATIC|)METHOD/i ) { # Get the return type function name and delete that from # the line. What is left is the possibly first function argument # if it is on the same line. @@ -231,8 +242,9 @@ foreach $src ( @filenames ) { $error = 1; last LINE; } - $line =~ s/^METHODE?\s+([^{]+?)\s*{\s*//i; - @ret = split m/\s+/, $1; + $line =~ s/^(STATIC|)METHODE?\s+([^{]+?)\s*{\s*//i; + $static = $1; + @ret = split m/\s+/, $2; $name = pop @ret; # last element is name of method $ret = join(" ", @ret); # return type @@ -267,14 +279,20 @@ foreach $src ( @filenames ) { $lineno++ } - if ( $line !~ s/};?(.*)// ) { # remove first '}' and trailing garbage - # The '}' was not there (the rest is optional), so complain - warn "$src:$lineno: Premature end of file"; - $error = 1; - last LINE; - } - warn "$src:$lineno: Ignored '$1'" # warn about garbage at end of line - if $debug and $1; + $default = ""; + if ( $line !~ s/};?(.*)// ) { # remove first '}' and trailing garbage + # The '}' was not there (the rest is optional), so complain + warn "$src:$lineno: Premature end of file"; + $error = 1; + last LINE; + } + $extra = $1; + if ( $extra =~ /\s*DEFAULT\s*([a-zA-Z_][a-zA-Z_0-9]*)\s*;/ ) { + $default = $1; + } else { + warn "$src:$lineno: Ignored '$1'" # warn about garbage at end of line + if $debug and $1; + } # Create a list of variables without the types prepended # @@ -308,6 +326,8 @@ foreach $src ( @filenames ) { $arguments = join(", ", @arguments); $varnames = join(", ", @varnames); + $default = "0" if $default eq ""; + if ( $hfile ) { # the method description print HFILE "extern struct device_op_desc $mname\_desc;\n"; @@ -323,7 +343,7 @@ foreach $src ( @filenames ) { if ( $cfile ) { # Print out the method desc print CFILE "struct device_op_desc $mname\_desc = {\n"; - print CFILE "\t0, 0, \"$mname\"\n"; + print CFILE "\t0, 0, (devop_t) $default, \"$mname\"\n"; print CFILE "};\n\n"; # Print out the method itself @@ -336,9 +356,15 @@ foreach $src ( @filenames ) { ',', ' ' x length("$ret $umname(")) . "\n"; } print CFILE "{\n"; - print CFILE &format_line("\t$mname\_t *m = ($mname\_t *) DEVOPMETH(dev, $mname);", - $line_width-8, ' = ', ' =', "\t\t") - . "\n"; + if ($static) { + print CFILE &format_line("\t$mname\_t *m = ($mname\_t *) DRVOPMETH(driver, $mname);", + $line_width-8, ' = ', ' =', "\t\t") + . "\n"; + } else { + print CFILE &format_line("\t$mname\_t *m = ($mname\_t *) DEVOPMETH(dev, $mname);", + $line_width-8, ' = ', ' =', "\t\t") + . "\n"; + } print CFILE "\t".($ret eq 'void'? '':'return ') . "m($varnames);\n"; print CFILE "}\n\n"; } diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index c9281f5d6924..8224b4a8c8c0 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: subr_bus.c,v 1.19 1999/05/08 18:08:59 peter Exp $ + * $Id: subr_bus.c,v 1.20 1999/05/08 21:59:35 dfr Exp $ */ #include <sys/param.h> @@ -100,6 +100,7 @@ struct method { LIST_ENTRY(method) link; /* linked list of methods */ int offset; /* offset in method table */ int refs; /* count of device_op_desc users */ + devop_t deflt; /* default implementation */ char* name; /* unique name of method */ }; @@ -132,6 +133,7 @@ register_method(struct device_op_desc *desc) bzero(m, sizeof(struct method) + strlen(desc->name) + 1); m->offset = next_method_offset++; m->refs = 1; + m->deflt = desc->deflt; m->name = (char*) (m + 1); strcpy(m->name, desc->name); LIST_INSERT_HEAD(&methods, m, link); @@ -167,6 +169,7 @@ compile_methods(driver_t *driver) { device_ops_t ops; struct device_method *m; + struct method *cm; int i; /* @@ -185,8 +188,13 @@ compile_methods(driver_t *driver) bzero(ops, sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t)); ops->maxoffset = next_method_offset; + /* Fill in default methods and then overwrite with driver methods */ for (i = 0; i < next_method_offset; i++) ops->methods[i] = error_method; + for (cm = LIST_FIRST(&methods); cm; cm = LIST_NEXT(cm, link)) { + if (cm->deflt) + ops->methods[cm->offset] = cm->deflt; + } for (i = 0, m = driver->methods; m->desc; i++, m++) ops->methods[m->desc->offset] = m->func; PDEBUG(("%s has %d method%s, wasting %d bytes", @@ -723,7 +731,9 @@ static int device_probe_child(device_t dev, device_t child) { devclass_t dc; + driverlink_t best = 0; driverlink_t dl; + int result, pri = 0; dc = dev->devclass; if (dc == NULL) @@ -737,14 +747,53 @@ device_probe_child(device_t dev, device_t child) dl = next_matching_driver(dc, child, dl)) { PDEBUG(("Trying %s", DRIVERNAME(dl->driver))); device_set_driver(child, dl->driver); - if (DEVICE_PROBE(child) == 0) { - if (!child->devclass) - device_set_devclass(child, dl->driver->name); - child->state = DS_ALIVE; - return 0; + result = DEVICE_PROBE(child); + + /* + * If the driver returns SUCCESS, there can be no higher match + * for this device. + */ + if (result == 0) { + best = dl; + pri = 0; + break; + } + + /* + * The driver returned an error so it certainly doesn't match. + */ + if (result > 0) + continue; + + /* + * A priority lower than SUCCESS, remember the best matching + * driver. Initialise the value of pri for the first match. + */ + if (best == 0 || result > pri) { + best = dl; + pri = result; + continue; } } + /* + * If we found a driver, change state and initialise the devclass. + */ + if (best) { + if (!child->devclass) + device_set_devclass(child, best->driver->name); + device_set_driver(child, best->driver); + if (pri < 0) { + /* + * A bit bogus. Call the probe method again to make sure + * that we have the right description. + */ + DEVICE_PROBE(child); + } + child->state = DS_ALIVE; + return 0; + } + return ENXIO; } diff --git a/sys/sys/bus_private.h b/sys/sys/bus_private.h index 9c138c592386..cbc2872141cd 100644 --- a/sys/sys/bus_private.h +++ b/sys/sys/bus_private.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bus_private.h,v 1.5 1999/03/29 08:54:19 dfr Exp $ + * $Id: bus_private.h,v 1.6 1999/04/16 21:22:54 peter Exp $ */ #ifndef _SYS_BUS_PRIVATE_H_ @@ -93,12 +93,15 @@ struct device_ops { */ #define DEVOPDESC(OP) (&OP##_##desc) -#define DEVOPOFF(DEV, OP) \ - ((DEVOPDESC(OP)->offset >= DEV->ops->maxoffset \ - || !DEV->ops->methods[DEVOPDESC(OP)->offset]) \ +#define DEVOPOFF(OPS, OP) \ + ((DEVOPDESC(OP)->offset >= OPS->maxoffset \ + || !OPS->methods[DEVOPDESC(OP)->offset]) \ ? 0 : DEVOPDESC(OP)->offset) -#define DEVOPMETH(DEV, OP) (DEV->ops->methods[DEVOPOFF(DEV, OP)]) +#define DEVOPS(DEV) (DEV->ops) +#define DEVOPMETH(DEV, OP) (DEVOPS(DEV)->methods[DEVOPOFF(DEVOPS(DEV), OP)]) +#define DRVOPS(DRV) ((struct device_ops *)DRV->ops) +#define DRVOPMETH(DRV, OP) (DRVOPS(DRV)->methods[DEVOPOFF(DRVOPS(DRV), OP)]) /* * Implementation of device. @@ -139,6 +142,7 @@ struct device { struct device_op_desc { unsigned int offset; /* offset in driver ops */ struct method* method; /* internal method implementation */ + devop_t deflt; /* default implementation */ const char* name; /* unique name (for registration) */ }; |