struct hw * hw_create (struct sim_state *sd, struct hw *parent, const char *family, const char *name, const char *unit, const char *args) { /* NOTE: HW must be allocated using ZALLOC, others use HW_ZALLOC */ struct hw *hw = ZALLOC (struct hw); /* our identity */ hw->family_of_hw = hw_strdup (hw, family); hw->name_of_hw = hw_strdup (hw, name); hw->args_of_hw = hw_strdup (hw, args); /* a hook into the system */ if (sd != NULL) hw->system_of_hw = sd; else if (parent != NULL) hw->system_of_hw = hw_system (parent); else hw_abort (parent, "No system found"); /* in a tree */ if (parent != NULL) { struct hw **sibling = &parent->child_of_hw; while ((*sibling) != NULL) sibling = &(*sibling)->sibling_of_hw; *sibling = hw; hw->parent_of_hw = parent; } /* top of tree */ if (parent != NULL) { struct hw *root = parent; while (root->parent_of_hw != NULL) root = root->parent_of_hw; hw->root_of_hw = root; } /* a unique identifier for the device on the parents bus */ if (parent != NULL) { hw_unit_decode (parent, unit, &hw->unit_address_of_hw); } /* Determine our path */ if (parent != NULL) hw->path_of_hw = full_name_of_hw (hw, NULL, 0); else hw->path_of_hw = "/"; /* create our base type */ hw->base_of_hw = HW_ZALLOC (hw, struct hw_base_data); hw->base_of_hw->finished_p = 0; /* our callbacks */ set_hw_io_read_buffer (hw, panic_hw_io_read_buffer); set_hw_io_write_buffer (hw, panic_hw_io_write_buffer); set_hw_dma_read_buffer (hw, passthrough_hw_dma_read_buffer); set_hw_dma_write_buffer (hw, passthrough_hw_dma_write_buffer); set_hw_unit_decode (hw, generic_hw_unit_decode); set_hw_unit_encode (hw, generic_hw_unit_encode); set_hw_unit_address_to_attach_address (hw, generic_hw_unit_address_to_attach_address); set_hw_unit_size_to_attach_size (hw, generic_hw_unit_size_to_attach_size); set_hw_attach_address (hw, passthrough_hw_attach_address); set_hw_detach_address (hw, passthrough_hw_detach_address); set_hw_delete (hw, ignore_hw_delete); /* locate a descriptor */ { const struct hw_descriptor **table; for (table = hw_descriptors; *table != NULL; table++) { const struct hw_descriptor *entry; for (entry = *table; entry->family != NULL; entry++) { if (strcmp (family, entry->family) == 0) { hw->base_of_hw->descriptor = entry; break; } } } if (hw->base_of_hw->descriptor == NULL) { hw_abort (parent, "Unknown device `%s'", family); } } /* Attach dummy ports */ create_hw_alloc_data (hw); create_hw_property_data (hw); create_hw_port_data (hw); create_hw_event_data (hw); create_hw_handle_data (hw); create_hw_instance_data (hw); return hw; }
int main (int argc, char **argv) { host_callback *cb = ZALLOC (host_callback); struct sim_state *sd = sim_state_alloc (0, cb); struct hw *me = ZALLOC (struct hw); sim_pre_argv_init (sd, "test-hw-events"); sim_post_argv_init (sd); me->system_of_hw = sd; printf ("Create hw-event-data\n"); { create_hw_alloc_data (me); create_hw_event_data (me); delete_hw_event_data (me); delete_hw_alloc_data (me); } printf ("Create hw-events\n"); { struct hw_event *a; struct hw_event *b; struct hw_event *c; struct hw_event *d; create_hw_alloc_data (me); create_hw_event_data (me); a = hw_event_queue_schedule (me, 0, NULL, NULL); b = hw_event_queue_schedule (me, 1, NULL, NULL); c = hw_event_queue_schedule (me, 2, NULL, NULL); d = hw_event_queue_schedule (me, 1, NULL, NULL); hw_event_queue_deschedule (me, c); hw_event_queue_deschedule (me, b); hw_event_queue_deschedule (me, a); hw_event_queue_deschedule (me, d); c = HW_ZALLOC (me, struct hw_event); hw_event_queue_deschedule (me, b); /* OOPS! */ hw_free (me, c); delete_hw_event_data (me); delete_hw_alloc_data (me); } printf ("Schedule hw-events\n"); { struct hw_event **e; int *n; int i; int nr = 4; e = HW_NZALLOC (me, struct hw_event *, nr); n = HW_NZALLOC (me, int, nr); create_hw_alloc_data (me); create_hw_event_data (me); for (i = 0; i < nr; i++) { n[i] = i; e[i] = hw_event_queue_schedule (me, i, test_handler, &n[i]); } sim_events_preprocess (sd, 1, 1); for (i = 0; i < nr; i++) { if (sim_events_tick (sd)) sim_events_process (sd); } for (i = 0; i < nr; i++) { if (n[i] != -i) abort (); hw_event_queue_deschedule (me, e[i]); } hw_free (me, n); hw_free (me, e); delete_hw_event_data (me); delete_hw_alloc_data (me); } return 0; }