Before trying to attach a child device driver, make sure the GPIO pins can

be mapped.  This prevents drivers from later failing in the attach routine.
Problem found by me, solution suggested by jmcneill.
This commit is contained in:
mbalmer 2009-08-21 12:53:42 +00:00
parent d97471da96
commit adac122864
2 changed files with 34 additions and 4 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: gpio.c,v 1.26 2009/08/17 12:44:44 mbalmer Exp $ */
/* $NetBSD: gpio.c,v 1.27 2009/08/21 12:53:42 mbalmer Exp $ */
/* $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */
/*
@ -19,7 +19,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.26 2009/08/17 12:44:44 mbalmer Exp $");
__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.27 2009/08/21 12:53:42 mbalmer Exp $");
/*
* General Purpose Input/Output framework.
@ -217,6 +217,30 @@ gpiobus_print(void *aux, const char *pnp)
return UNCONF;
}
/* return 1 if all pins can be mapped, 0 if not */
int
gpio_pin_can_map(void *gpio, int offset, u_int32_t mask)
{
struct gpio_softc *sc = gpio;
int npins, pin, i;
npins = gpio_npins(mask);
if (npins > sc->sc_npins)
return 0;
for (npins = 0, i = 0; i < 32; i++)
if (mask & (1 << i)) {
pin = offset + i;
if (pin < 0 || pin >= sc->sc_npins)
return 0;
if (sc->sc_pins[pin].pin_mapped)
return 0;
}
return 1;
}
int
gpio_pin_map(void *gpio, int offset, u_int32_t mask, struct gpio_pinmap *map)
{
@ -483,8 +507,13 @@ gpioioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
NULL, NULL, NULL, NULL))
return EPERM;
attach = (struct gpio_attach *)data;
/* do not try to attach if the pins are already mapped */
if (!gpio_pin_can_map(sc, attach->ga_offset, attach->ga_mask))
return EBUSY;
ga.ga_gpio = sc;
ga.ga_dvname = attach->ga_dvname;
ga.ga_offset = attach->ga_offset;

View File

@ -1,4 +1,4 @@
/* $NetBSD: gpiovar.h,v 1.9 2009/07/25 16:30:44 mbalmer Exp $ */
/* $NetBSD: gpiovar.h,v 1.10 2009/08/21 12:53:42 mbalmer Exp $ */
/* $OpenBSD: gpiovar.h,v 1.3 2006/01/14 12:33:49 grange Exp $ */
/*
@ -88,6 +88,7 @@ struct gpio_name {
LIST_ENTRY(gpio_name) gp_next;
};
int gpio_pin_can_map(void *, int, u_int32_t);
int gpio_pin_map(void *, int, u_int32_t, struct gpio_pinmap *);
void gpio_pin_unmap(void *, struct gpio_pinmap *);
int gpio_pin_read(void *, struct gpio_pinmap *, int);