Files
OpenTXW81X/sdk/hal/dev.c
T
2025-08-27 09:51:58 +01:00

186 lines
4.1 KiB
C

#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "osal/string.h"
#include "osal/mutex.h"
#include "osal/sleep.h"
#include "osal/task.h"
#include "osal/irq.h"
struct dev_mgr {
struct dev_obj *next;
struct os_mutex mutex;
};
__bobj static struct dev_mgr s_dev_mgr;
__init int32 dev_init()
{
os_mutex_init(&s_dev_mgr.mutex);
s_dev_mgr.next = NULL;
return RET_OK;
}
struct dev_obj *dev_get(int32 dev_id)
{
struct dev_obj *dev = NULL;
os_mutex_lock(&s_dev_mgr.mutex, osWaitForever);
dev = s_dev_mgr.next;
while (dev) {
if (dev->dev_id == dev_id) {
break;
}
dev = dev->next;
}
os_mutex_unlock(&s_dev_mgr.mutex);
return dev;
}
void dev_busy(struct dev_obj *dev, uint8 busy, uint8 set)
{
uint32 flag = disable_irq();
if (set) {
dev->busy |= busy;
} else {
dev->busy &= ~ busy;
}
enable_irq(flag);
}
__init int32 dev_register(uint32 dev_id, struct dev_obj *device)
{
struct dev_obj *dev = dev_get(dev_id);
if (dev) {
return -EEXIST;
}
device->dev_id = dev_id;
#ifdef CONFIG_SLEEP
os_blklist_init(&device->blklist);
#endif
os_mutex_lock(&s_dev_mgr.mutex, osWaitForever);
device->next = s_dev_mgr.next;
s_dev_mgr.next = device;
os_mutex_unlock(&s_dev_mgr.mutex);
return RET_OK;
}
int32 dev_unregister(struct dev_obj *device)
{
struct dev_obj *dev = NULL;
struct dev_obj *last = NULL;
os_mutex_lock(&s_dev_mgr.mutex, osWaitForever);
dev = s_dev_mgr.next;
while (dev) {
if (dev == device) {
// check first dev
if (device == s_dev_mgr.next) {
s_dev_mgr.next = device->next;
} else {
last->next = device->next;
}
#ifdef CONFIG_SLEEP
os_blklist_del(&device->blklist);
#endif
break;
}
last = dev;
dev = dev->next;
}
os_mutex_unlock(&s_dev_mgr.mutex);
return RET_OK;
}
#ifdef CONFIG_SLEEP
int32 dev_suspended(struct dev_obj *dev, uint8 suspend)
{
if (dev->suspend && suspend && !__in_interrupt()) { /* 非中断上下文,直接挂起当前task */
os_blklist_suspend(&dev->blklist, NULL);
}
return dev->suspend;
}
__weak int32 dev_suspend_hook(struct dev_obj *dev, uint16 type)
{
return 1;
}
int32 dev_suspend(uint16 type)
{
int32 loop;
struct dev_obj *dev = NULL;
os_mutex_lock(&s_dev_mgr.mutex, osWaitForever);
dev = s_dev_mgr.next;
while (dev) {
if (dev->ops && dev->ops->suspend && !dev->suspend) {
if (dev_suspend_hook(dev, type)) {
loop = 0;
dev->suspend = 1;
while (dev->busy) {
os_sleep_ms(1);
if (loop++ > 100) {
loop = 0;
os_printf(KERN_WARNING"device %d busy !!!!\r\n", dev->dev_id);
}
}
dev->ops->suspend(dev);
}
}
dev = dev->next;
}
os_mutex_unlock(&s_dev_mgr.mutex);
return RET_OK;
}
__weak int32 dev_resume_hook(struct dev_obj *dev, uint16 type, uint32 wkreason)
{
return 1;
}
int32 dev_resume(uint16 type, uint32 wkreason)
{
struct dev_obj *dev = NULL;
os_mutex_lock(&s_dev_mgr.mutex, osWaitForever);
dev = s_dev_mgr.next;
while (dev) {
if (dev->ops && dev->ops->resume && dev->suspend) {
if (dev_resume_hook(dev, type, wkreason)) {
dev->ops->resume(dev);
dev->suspend = 0;
os_blklist_resume(&dev->blklist);//唤醒所有被挂起的task
}
}
dev = dev->next;
}
os_mutex_unlock(&s_dev_mgr.mutex);
return RET_OK;
}
#else
int32 dev_suspended(struct dev_obj *dev, uint8 suspend)
{
return 0;
}
__weak int32 dev_suspend_hook(struct dev_obj *dev, uint16 type)
{
return 1;
}
int32 dev_suspend(uint16 type)
{
return RET_ERR;
}
__weak int32 dev_resume_hook(struct dev_obj *dev, uint16 type, uint32 wkreason)
{
return 1;
}
int32 dev_resume(uint16 type, uint32 wkreason)
{
return RET_ERR;
}
#endif