📄 device.c
字号:
} return me->nr_size_cells;}/* device-instance: */INLINE_DEVICE\(device_instance *)device_create_instance_from(device *me, device_instance *parent, void *data, const char *path, const char *args, const device_instance_callbacks *callbacks){ device_instance *instance = ZALLOC(device_instance); if ((me == NULL) == (parent == NULL)) device_error(me, "can't have both parent instance and parent device"); /*instance->unit*/ /* link this instance into the devices list */ if (me != NULL) { ASSERT(parent == NULL); instance->owner = me; instance->parent = NULL; /* link this instance into the front of the devices instance list */ instance->next = me->instances; me->instances = instance; } if (parent != NULL) { device_instance **previous; ASSERT(parent->child == NULL); parent->child = instance; ASSERT(me == NULL); instance->owner = parent->owner; instance->parent = parent; /* in the devices instance list replace the parent instance with this one */ instance->next = parent->next; /* replace parent with this new node */ previous = &instance->owner->instances; while (*previous != parent) { ASSERT(*previous != NULL); previous = &(*previous)->next; } *previous = instance; } instance->data = data; instance->args = (args == NULL ? NULL : (char *) strdup(args)); instance->path = (path == NULL ? NULL : (char *) strdup(path)); instance->callback = callbacks; cap_add(instance->owner->ihandles, instance); return instance;}INLINE_DEVICE\(device_instance *)device_create_instance(device *me, const char *path, const char *args){ /* create the instance */ if (me->callback->instance_create == NULL) device_error(me, "no instance_create method"); return me->callback->instance_create(me, path, args);}STATIC_INLINE_DEVICE\(void)clean_device_instances(device *me){ device_instance **instance = &me->instances; while (*instance != NULL) { device_instance *old_instance = *instance; device_instance_delete(old_instance); instance = &me->instances; }}INLINE_DEVICE\(void)device_instance_delete(device_instance *instance){ device *me = instance->owner; if (instance->callback->delete == NULL) device_error(me, "no delete method"); instance->callback->delete(instance); if (instance->args != NULL) zfree(instance->args); if (instance->path != NULL) zfree(instance->path); if (instance->child == NULL) { /* only remove leaf nodes */ device_instance **curr = &me->instances; while (*curr != instance) { ASSERT(*curr != NULL); curr = &(*curr)->next; } *curr = instance->next; } else { /* check it isn't in the instance list */ device_instance *curr = me->instances; while (curr != NULL) { ASSERT(curr != instance); curr = curr->next; } /* unlink the child */ ASSERT(instance->child->parent == instance); instance->child->parent = NULL; } cap_remove(me->ihandles, instance); zfree(instance);}INLINE_DEVICE\(int)device_instance_read(device_instance *instance, void *addr, unsigned_word len){ device *me = instance->owner; if (instance->callback->read == NULL) device_error(me, "no read method"); return instance->callback->read(instance, addr, len);}INLINE_DEVICE\(int)device_instance_write(device_instance *instance, const void *addr, unsigned_word len){ device *me = instance->owner; if (instance->callback->write == NULL) device_error(me, "no write method"); return instance->callback->write(instance, addr, len);}INLINE_DEVICE\(int)device_instance_seek(device_instance *instance, unsigned_word pos_hi, unsigned_word pos_lo){ device *me = instance->owner; if (instance->callback->seek == NULL) device_error(me, "no seek method"); return instance->callback->seek(instance, pos_hi, pos_lo);}INLINE_DEVICE\(int)device_instance_call_method(device_instance *instance, const char *method_name, int n_stack_args, unsigned_cell stack_args[/*n_stack_args*/], int n_stack_returns, unsigned_cell stack_returns[/*n_stack_args*/]){ device *me = instance->owner; const device_instance_methods *method = instance->callback->methods; if (method == NULL) { device_error(me, "no methods (want %s)", method_name); } while (method->name != NULL) { if (strcmp(method->name, method_name) == 0) { return method->method(instance, n_stack_args, stack_args, n_stack_returns, stack_returns); } method++; } device_error(me, "no %s method", method_name); return 0;}INLINE_DEVICE\(device *)device_instance_device(device_instance *instance){ return instance->owner;}INLINE_DEVICE\(const char *)device_instance_path(device_instance *instance){ return instance->path;}INLINE_DEVICE\(void *)device_instance_data(device_instance *instance){ return instance->data;}/* Device Properties: */STATIC_INLINE_DEVICE\(device_property_entry *)find_property_entry(device *me, const char *property){ device_property_entry *entry; ASSERT(property != NULL); entry = me->properties; while (entry != NULL) { if (strcmp(entry->value->name, property) == 0) return entry; entry = entry->next; } return NULL;}STATIC_INLINE_DEVICE\(void)device_add_property(device *me, const char *property, device_property_type type, const void *init_array, unsigned sizeof_init_array, const void *array, unsigned sizeof_array, const device_property *original, object_disposition disposition){ device_property_entry *new_entry = NULL; device_property *new_value = NULL; /* find the list end */ device_property_entry **insertion_point = &me->properties; while (*insertion_point != NULL) { if (strcmp((*insertion_point)->value->name, property) == 0) return; insertion_point = &(*insertion_point)->next; } /* create a new value */ new_value = ZALLOC(device_property); new_value->name = (char *) strdup(property); new_value->type = type; if (sizeof_array > 0) { void *new_array = zalloc(sizeof_array); memcpy(new_array, array, sizeof_array); new_value->array = new_array; new_value->sizeof_array = sizeof_array; } new_value->owner = me; new_value->original = original; new_value->disposition = disposition; /* insert the value into the list */ new_entry = ZALLOC(device_property_entry); *insertion_point = new_entry; if (sizeof_init_array > 0) { void *new_init_array = zalloc(sizeof_init_array); memcpy(new_init_array, init_array, sizeof_init_array); new_entry->init_array = new_init_array; new_entry->sizeof_init_array = sizeof_init_array; } new_entry->value = new_value;}/* local - not available externally */STATIC_INLINE_DEVICE\(void)device_set_property(device *me, const char *property, device_property_type type, const void *array, int sizeof_array){ /* find the property */ device_property_entry *entry = find_property_entry(me, property); if (entry != NULL) { /* existing property - update it */ void *new_array = 0; device_property *value = entry->value; /* check the type matches */ if (value->type != type) device_error(me, "conflict between type of new and old value for property %s", property); /* replace its value */ if (value->array != NULL) zfree((void*)value->array); new_array = (sizeof_array > 0 ? zalloc(sizeof_array) : (void*)0); value->array = new_array; value->sizeof_array = sizeof_array; if (sizeof_array > 0) memcpy(new_array, array, sizeof_array); return; } else { /* new property - create it */ device_add_property(me, property, type, NULL, 0, array, sizeof_array, NULL, tempoary_object); }}STATIC_INLINE_DEVICE\(void)clean_device_properties(device *me){ device_property_entry **delete_point = &me->properties; while (*delete_point != NULL) { device_property_entry *current = *delete_point; switch (current->value->disposition) { case permenant_object: /* zap the current value, will be initialized later */ ASSERT(current->init_array != NULL); if (current->value->array != NULL) { zfree((void*)current->value->array); current->value->array = NULL; } delete_point = &(*delete_point)->next; break; case tempoary_object: /* zap the actual property, was created during simulation run */ ASSERT(current->init_array == NULL); *delete_point = current->next; if (current->value->array != NULL) zfree((void*)current->value->array); zfree(current->value); zfree(current); break; } }}INLINE_DEVICE\(void)device_init_static_properties(device *me, void *data){ device_property_entry *property; for (property = me->properties; property != NULL; property = property->next) { ASSERT(property->init_array != NULL); ASSERT(property->value->array == NULL); ASSERT(property->value->disposition == permenant_object); switch (property->value->type) { case array_property: case boolean_property: case range_array_property: case reg_array_property: case string_property: case string_array_property: case integer_property: /* delete the property, and replace it with the original */ device_set_property(me, property->value->name, property->value->type, property->init_array, property->sizeof_init_array); break; case ihandle_property: break; } }}INLINE_DEVICE\(void)device_init_runtime_properties(device *me, void *data){ device_property_entry *property; for (property = me->properties; property != NULL; property = property->next) { switch (property->value->disposition) { case permenant_object: switch (property->value->type) { case ihandle_property: { device_instance *ihandle; ihandle_runtime_property_spec spec; ASSERT(property->init_array != NULL); ASSERT(property->value->array == NULL); device_find_ihandle_runtime_property(me, property->value->name, &spec); ihandle = tree_instance(me, spec.full_path); device_set_ihandle_property(me, property->value->name, ihandle); break; } case array_property: case boolean_property: case range_array_property: case integer_property: case reg_array_property: case string_property: case string_array_property: ASSERT(property->init_array != NULL); ASSERT(property->value->array != NULL); break; } break; case tempoary_object: ASSERT(property->init_array == NULL); ASSERT(property->value->array != NULL); break; } }}INLINE_DEVICE\(const device_property *)device_next_property(const device_property *property){ /* find the property in the list */ device *owner = property->owner; device_property_entry *entry = owner->properties; while (entry != NULL && entry->value != property) entry = entry->next; /* now return the following property */ ASSERT(entry != NULL); /* must be a member! */ if (entry->next != NULL) return entry->next->value; else return NULL;}INLINE_DEVICE\(const device_property *)device_find_property(device *me, const char *property){ if (me == NULL) { return NULL; } else if (property == NULL || strcmp(property, "") == 0) { if (me->properties == NULL) return NULL; else return me->properties->value; } else { device_property_entry *entry = find_property_entry(me, property); if (entry != NULL) return entry->value; } return NULL;}INLINE_DEVICE\(void)device_add_array_property(device *me, const char *property, const void *array, int sizeof_array){ device_add_property(me, property, array_property, array, sizeof_array, array, sizeof_array, NULL, permenant_object);}INLINE_DEVICE\(void)device_set_array_property(device *me, const char *property, const void *array, int sizeof_array){ device_set_property(me, property, array_property, array, sizeof_array);}INLINE_DEVICE\(const device_property *)device_find_array_property(device *me, const char *property){ const device_property *node; node = device_find_property(me, property); if (node == (device_property*)0 || node->type != array_property) device_error(me, "property %s not found or of wrong type", property); return node;}INLINE_DEVICE\(void)device_add_boolean_property(device *me,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -