| /* | 
 |  * Copyright (c) 2012 Corey Tabaka | 
 |  * | 
 |  * Permission is hereby granted, free of charge, to any person obtaining | 
 |  * a copy of this software and associated documentation files | 
 |  * (the "Software"), to deal in the Software without restriction, | 
 |  * including without limitation the rights to use, copy, modify, merge, | 
 |  * publish, distribute, sublicense, and/or sell copies of the Software, | 
 |  * and to permit persons to whom the Software is furnished to do so, | 
 |  * subject to the following conditions: | 
 |  * | 
 |  * The above copyright notice and this permission notice shall be | 
 |  * included in all copies or substantial portions of the Software. | 
 |  * | 
 |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
 |  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
 |  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | 
 |  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | 
 |  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | 
 |  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | 
 |  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 
 |  */ | 
 |  | 
 | #include <dev/driver.h> | 
 | #include <assert.h> | 
 | #include <err.h> | 
 | #include <trace.h> | 
 |  | 
 | extern struct device __devices[]; | 
 | extern struct device __devices_end[]; | 
 |  | 
 | status_t device_init_all(void) | 
 | { | 
 | 	status_t res = NO_ERROR; | 
 |  | 
 | 	struct device *dev = __devices; | 
 | 	while (dev != __devices_end) { | 
 | 		status_t code = device_init(dev); | 
 |  | 
 | 		if (code < 0) { | 
 | 			TRACEF("Driver init failed for driver \"%s\", device \"%s\", reason %d\n", | 
 | 					dev->driver->type, dev->name, code); | 
 |  | 
 | 			res = code; | 
 | 		} | 
 |  | 
 | 		dev++; | 
 | 	} | 
 |  | 
 | 	return res; | 
 | } | 
 |  | 
 | status_t device_fini_all(void) | 
 | { | 
 | 	status_t res = NO_ERROR; | 
 |  | 
 | 	struct device *dev = __devices; | 
 | 	while (dev != __devices_end) { | 
 | 		status_t code = device_fini(dev); | 
 |  | 
 | 		if (code < 0) { | 
 | 			TRACEF("Driver fini failed for driver \"%s\", device \"%s\", reason %d\n", | 
 | 					dev->driver->type, dev->name, code); | 
 |  | 
 | 			res = code; | 
 | 		} | 
 |  | 
 | 		dev++; | 
 | 	} | 
 |  | 
 | 	return res; | 
 | } | 
 |  | 
 | status_t device_init(struct device *dev) | 
 | { | 
 | 	if (!dev) | 
 | 		return ERR_INVALID_ARGS; | 
 |  | 
 | 	DEBUG_ASSERT(dev->driver); | 
 | 	 | 
 | 	const struct driver_ops *ops = dev->driver->ops; | 
 |  | 
 | 	if (ops && ops->init) | 
 | 		return ops->init(dev); | 
 | 	else | 
 | 		return ERR_NOT_SUPPORTED; | 
 | } | 
 |  | 
 | status_t device_fini(struct device *dev) | 
 | { | 
 | 	if (!dev) | 
 | 		return ERR_INVALID_ARGS; | 
 | 	 | 
 | 	DEBUG_ASSERT(dev->driver); | 
 |  | 
 | 	const struct driver_ops *ops = dev->driver->ops; | 
 |  | 
 | 	if (ops && ops->fini) | 
 | 		return ops->fini(dev); | 
 | 	else | 
 | 		return ERR_NOT_SUPPORTED; | 
 | } | 
 |  | 
 | status_t device_suspend(struct device *dev) | 
 | { | 
 | 	if (!dev) | 
 | 		return ERR_NOT_SUPPORTED; | 
 | 	 | 
 | 	DEBUG_ASSERT(dev->driver); | 
 |  | 
 | 	const struct driver_ops *ops = dev->driver->ops; | 
 |  | 
 | 	if (ops && ops->suspend) | 
 | 		return ops->suspend(dev); | 
 | 	else | 
 | 		return ERR_NOT_SUPPORTED; | 
 | } | 
 |  | 
 | status_t device_resume(struct device *dev) | 
 | { | 
 | 	if (!dev) | 
 | 		return ERR_NOT_SUPPORTED; | 
 | 	 | 
 | 	DEBUG_ASSERT(dev->driver); | 
 |  | 
 | 	const struct driver_ops *ops = dev->driver->ops; | 
 |  | 
 | 	if (ops && ops->resume) | 
 | 		return ops->resume(dev); | 
 | 	else | 
 | 		return ERR_NOT_SUPPORTED; | 
 | } | 
 |  |