}
memcpy(hw, mod->template, sizeof *hw);
hw->vm = vm;
+ hw->mod = mod;
if (mod->data_init(hw, data)) {
vm->warn_cb_("failed to init hw module data");
free(hw);
return NULL;
}
- hw->data_free = mod->data_free;
return hw;
}
void dcpu16_hw_del(struct dcpu16_hw **hw) {
if (hw) {
if (*hw) {
- if ((*hw)->data_free) {
- (*hw)->data_free(*hw);
+ if ((*hw)->mod->data_free) {
+ (*hw)->mod->data_free(*hw);
}
free(*hw);
*hw = NULL;
}
}
-/* dcpu16_hw_add
+/* dcpu16_hw_ctl
+ * invokes per-module controls for hw device
+ */
+int dcpu16_hw_ctl(struct dcpu16_hw *hw, const char *cmd, void *data_in, void *data_out) {
+ if (hw) {
+ if (hw->mod) {
+ if (hw->mod->ctl) {
+ if (cmd) {
+ return hw->mod->ctl(hw, cmd, data_in, data_out);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+/* dcpu16_hw_attach
* registers new 'hardware' device with system
*/
int dcpu16_hw_attach(struct dcpu16 *vm, struct dcpu16_hw *hw) {