/* * iicbus_request_bus() * * Allocate the device to perform transfers. * * how : IIC_WAIT or IIC_DONTWAIT */ int iicbus_request_bus(device_t bus, device_t dev, int how) { struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); int error = 0; /* first, ask the underlying layers if the request is ok */ IICBUS_LOCK(sc); do { error = IICBUS_CALLBACK(device_get_parent(bus), IIC_REQUEST_BUS, (caddr_t)&how); if (error) error = iicbus_poll(sc, how); } while (error == EWOULDBLOCK); while (!error) { if (sc->owner && sc->owner != dev) { error = iicbus_poll(sc, how); } else { sc->owner = dev; IICBUS_UNLOCK(sc); return (0); } /* free any allocated resource */ if (error) IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, (caddr_t)&how); } IICBUS_UNLOCK(sc); return (error); }
/* * iicbus_release_bus() * * Release the device allocated with iicbus_request_dev() */ int iicbus_release_bus(device_t bus, device_t dev) { struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); int error; /* first, ask the underlying layers if the release is ok */ error = IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL); if (error) return (error); IICBUS_LOCK(sc); if (sc->owner != dev) { IICBUS_UNLOCK(sc); return (EACCES); } sc->owner = NULL; /* wakeup waiting processes */ wakeup(sc); IICBUS_UNLOCK(sc); return (0); }
/* * iicbus_release_bus() * * Release the device allocated with iicbus_request_dev() */ int iicbus_release_bus(device_t bus, device_t dev) { struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); int error; IICBUS_LOCK(sc); if (sc->owner != dev) { IICBUS_UNLOCK(sc); return (EACCES); } /* * Drop the lock around the call to the bus driver. * This call should be allowed to sleep in the IIC_WAIT case. * Drivers might also need to grab locks that would cause LOR * if our lock is held. */ IICBUS_UNLOCK(sc); /* Ask the underlying layers if the release is ok */ error = IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL); if (error == 0) { IICBUS_LOCK(sc); sc->owner = NULL; /* wakeup a waiting thread */ wakeup_one(sc); IICBUS_UNLOCK(sc); } return (error); }
/* * iicbus_request_bus() * * Allocate the device to perform transfers. * * how : IIC_WAIT or IIC_DONTWAIT */ int iicbus_request_bus(device_t bus, device_t dev, int how) { struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); int error = 0; IICBUS_LOCK(sc); while ((error == 0) && (sc->owner != NULL)) error = iicbus_poll(sc, how); if (error == 0) { sc->owner = dev; /* * Drop the lock around the call to the bus driver. * This call should be allowed to sleep in the IIC_WAIT case. * Drivers might also need to grab locks that would cause LOR * if our lock is held. */ IICBUS_UNLOCK(sc); /* Ask the underlying layers if the request is ok */ error = IICBUS_CALLBACK(device_get_parent(bus), IIC_REQUEST_BUS, (caddr_t)&how); IICBUS_LOCK(sc); if (error != 0) { sc->owner = NULL; wakeup_one(sc); } } IICBUS_UNLOCK(sc); return (error); }