initial api changes to support hw_ devices as more-generic attachable modules
authorJustin Wind <justin.wind@gmail.com>
Thu, 17 May 2012 23:06:59 +0000 (16:06 -0700)
committerJustin Wind <justin.wind@gmail.com>
Thu, 17 May 2012 23:06:59 +0000 (16:06 -0700)
generalizing hw handling routines

dcpu16.c
dcpu16.h
hw_spc2000.c
hw_spc2000.h

index ac052d59887a148f62f5195db9ac8c2c08557063..6ab689888d70a28587f07a47560adf1130d254cd 100644 (file)
--- a/dcpu16.c
+++ b/dcpu16.c
@@ -1358,6 +1358,41 @@ void dcpu16_dump_ram(struct dcpu16 *vm, DCPU16_WORD start, DCPU16_WORD end) {
         printf("\n");
 }
 
+/* instantiate a new 'hardware' device */
+struct dcpu16_hw *dcpu16_hw_new(struct dcpu16 *vm, struct dcpu16_hw_module *mod, void *data) {
+    struct dcpu16_hw *hw;
+
+    hw = calloc(1, sizeof *hw);
+    if (hw == NULL) {
+        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
+        return NULL;
+    }
+    memcpy(hw, mod->template, sizeof *hw);
+    hw->vm = vm;
+
+    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;
+}
+
+/* destroy a 'hardware' device */
+void dcpu16_hw_del(struct dcpu16_hw **hw) {
+    if (hw) {
+        if (*hw) {
+            if ((*hw)->data_free) {
+                (*hw)->data_free(*hw);
+            }
+            free(*hw);
+            *hw = NULL;
+        }
+    }
+}
+
 /*  dcpu16_hw_add
  *  registers new 'hardware' device with system
  */
index 38203edfc52eee41553f9d28a1f9812d4b4c648f..ebf20721051e11823f4113735d443a13541d56bd 100644 (file)
--- a/dcpu16.h
+++ b/dcpu16.h
@@ -68,6 +68,7 @@ struct dcpu16_acct_cb {
 };
 
 typedef void (dcpu16_hw_signal_t)(struct dcpu16 *, void *);
+typedef void (dcpu16_hw_data_free_t)(struct dcpu16_hw *);
 /* these are used to define hardware attached to the system */
 struct dcpu16_hw {
     struct dcpu16 *vm;  /* which system do I belong to */
@@ -82,9 +83,18 @@ struct dcpu16_hw {
     dcpu16_hw_signal_t *hwi;
     dcpu16_hw_signal_t *cycle;
     dcpu16_hw_signal_t *reset;
+
+    dcpu16_hw_data_free_t *data_free;
     void *data;
 };
 
+typedef int (dcpu16_hw_data_init_t)(struct dcpu16_hw *, void *);
+struct dcpu16_hw_module {
+    struct dcpu16_hw *template;
+    dcpu16_hw_data_init_t *data_init;
+    dcpu16_hw_data_free_t *data_free;
+};
+
 /* instantiate a new core */
 struct dcpu16 *dcpu16_new(void);
 
index 49ba35042c5ace4360c7eca649617c52b5cecb20..402a1d7949a2e150b768365cdc742a604d50e15a 100644 (file)
@@ -9,6 +9,7 @@ static dcpu16_hw_signal_t spc2000_reset_;
 static dcpu16_hw_signal_t spc2000_cycle_;
 static dcpu16_hw_signal_t spc2000_hwi_;
 static struct dcpu16_hw hw_ = {
+    .vm     = NULL,
     .name_  = "SPC2000 - Suspension Chamber 2000",
     .id_l   = 0x1d9d,
     .id_h   = 0x40e4,
@@ -21,11 +22,41 @@ static struct dcpu16_hw hw_ = {
     .data   = (struct spc2000_ *)NULL
 };
 
+static dcpu16_hw_data_init_t spc2000_data_init_;
+static dcpu16_hw_data_free_t spc2000_data_free_;
+struct dcpu16_hw_module dcpu16_hw_module_spc2000 = {
+    .template = &hw_,
+    .data_init = spc2000_data_init_,
+    .data_free = spc2000_data_free_,
+};
+
 struct spc2000_ {
     DCPU16_WORD skip_unit;
     long long skip;
 };
 
+static
+int spc2000_data_init_(struct dcpu16_hw *hw, void *extra) {
+    (void)extra;
+
+    hw->data = calloc(1, sizeof(struct spc2000_));
+    if (hw->data == NULL) {
+        hw->vm->warn_cb_("%s():%s", "calloc", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+static
+void spc2000_data_free_(struct dcpu16_hw *hw) {
+    if (hw) {
+        if (hw->data) {
+            free(hw->data);
+            hw->data = NULL;
+        }
+    }
+}
+
 static
 void spc2000_reset_(struct dcpu16 *vm, void *data) {
     struct spc2000_ *spc2000 = (struct spc2000_ *)data;
index 44cc015175379f0116d5105d255ac213c9a9167b..2171ba3eb014587676f391b92db7e4c12128a901 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef SPC2000_H_IE4EG0MO
 #define SPC2000_H_IE4EG0MO
 
-struct dcpu16_hw *spc2000_new(struct dcpu16 *);
-void spc2000_del(struct dcpu16_hw **);
+extern struct dcpu16_hw_module dcpu16_hw_module_spc2000;
 
 #endif /* SPC2000_H_IE4EG0MO */