diff --git a/shared/hypercall_params.h b/shared/hypercall_params.h
index 6916bc63ce65406ae96b26bfe6fe112fbbdb40ba..c1338ad75713eb727bd9cd84166b8768e7454f84 100644
--- a/shared/hypercall_params.h
+++ b/shared/hypercall_params.h
@@ -14,6 +14,13 @@
 #define HYPERCALL_CODE_TIMER      2
 #define HYPERCALL_CODE_GFX_INIT   3
 
+#define REG_TIMER_CMD  0x43
+#define REG_TIMER_DATA 0x40
+
+#define REG_GFX_INIT_ST   0x4E700000
+#define REG_GFX_INIT_CMD  0x4E700100
+#define REG_GFX_INIT_DATA 0x4E700200
+
 // --- SHARED STRUCT ---
 
 typedef struct {
@@ -36,4 +43,4 @@ typedef struct {
 
 // ...
 
-#endif
+#endif // _HYPERCALL_PARAMS_H_
diff --git a/vmm/handler.c b/vmm/handler.c
index 00b058be194a4d8ed7ed67a5a078421d53ece341..65c476afad22c1a9a0bf29a4f97be0022792276b 100644
--- a/vmm/handler.c
+++ b/vmm/handler.c
@@ -4,7 +4,9 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <unistd.h>
+#include <stdbool.h>
 
+#include "operation.h"
 #include "shared/hypercall_params.h"
 
 // --- DEFINE ---
@@ -16,27 +18,13 @@ state_handler_t const STATE_HANDLERS[] = {
     [KVM_EXIT_MMIO] = handle_mmio,
 };
 
-static state_t const STATE_TIMER[] = {
-
-    { OP_WRITE_EQUAL, 0x43, 20, 2, NULL },
-    { OP_WRITE_EQUAL, 0x40, 0,  4, NULL },
-    { OP_WRITE_EQUAL, 0,    0,  0, NULL },
-};
-
-static state_t const STATE_VGA[] = {
-
-    { OP_WRITE_EQUAL, 0x3C2, 0x67,  1, NULL },
-    { OP_WRITE_EQUAL, 0x3C4, 0xF02, 2, NULL },
-    { OP_WRITE_EQUAL, 0x3CE, 0x506, 2, NULL },
-    { OP_WRITE_EQUAL, 0x3DA, 0x80,  1, NULL },
-    { OP_WRITE_EQUAL, 0x3C0, 0x20,  1, NULL },
-    { OP_WRITE_EQUAL, 0x3C5, 0x0F,  1, NULL },
-    { OP_WRITE_EQUAL, 0,     0,     0, NULL },
-};
+static state_t *current_state = NULL;
 
 // --- STATIC FUNCTION ---
 
-static uint32_t retrieve_value(uint8_t *addr, uint8_t size) {
+// - UTILS -
+
+static uint32_t retrieve_data(uint8_t *addr, uint8_t size) {
 
     uint32_t value;
 
@@ -55,13 +43,124 @@ static uint32_t retrieve_value(uint8_t *addr, uint8_t size) {
         break;
 
         default:
-            errx(1, "Unsupported size trying to retrieve value.\n");
+            errx(1, "Unsupported size trying to retrieve data.\n");
         break;
     }
 
     return value;
 }
 
+static void injecte_data(uint8_t *addr, uint8_t size, uint32_t value) {
+
+    switch (size) {
+
+        case 1:
+            *((uint8_t *)addr) = (uint8_t)value;
+        break;
+
+        case 2:
+            *((uint16_t *)addr) = (uint16_t)value;
+        break;
+
+        case 4:
+            *((uint32_t *)addr) = (uint32_t)value;
+        break;
+
+        default:
+            errx(1, "Unsupported size trying to inject data.\n");
+        break;
+    }
+}
+
+static state_t *state_check(uint64_t addr, uint8_t size, uint32_t value) {
+
+    for (uint32_t i = 0; i < STATE_MACHINE_NUM + 1; i++) {
+
+        // - get next state or first state of one of all state machine available -
+        if (i == 0 && current_state == NULL) continue;
+
+        state_t *next_state = (i == 0) ? current_state : STATE_ALL_STARTERS[i - 1];
+
+        // - check the validity of the next state -
+        switch (next_state->op) {
+
+            case OP_WRITE_EQUAL:
+
+                if (next_state->addr == addr && next_state->size == size && next_state->value == value)
+                    return next_state;
+            break;
+
+            case OP_WRITE_STORE:
+
+                if (next_state->addr == addr && next_state->size == size && next_state->callback != NULL)
+                    return next_state;
+            break;
+
+            case OP_EMUL_END:
+            case OP_READ_INJECT:
+                // nothing...
+            break;
+        }
+    }
+
+    return NULL;
+}
+
+static void state_compute(state_t *state, uint32_t value) {
+
+    switch (state->op) {
+
+        case OP_WRITE_STORE:
+
+            state->callback(&value);
+        break;
+
+        case OP_READ_INJECT:
+
+            injecte_data((uint8_t *)&state->addr, state->size, state->value);
+            printf("PMIO guest read: size=%d port=0x%x [value injected by VMM=0x%x]\n", 
+                   state->size * 8, state->addr, state->value);
+        break;
+
+        case OP_EMUL_END:
+        case OP_WRITE_EQUAL:
+            // nothing...
+        break;
+    }
+
+    // - check and compute last operation -
+    current_state = state + 1;
+    if (current_state->op == OP_EMUL_END) {
+
+        if (current_state->callback != NULL)
+            current_state->callback(NULL);
+
+        current_state = NULL; 
+    }
+}
+
+// - OPERATION WRAPPER -
+
+static void wrapper_op_console(uint8_t *shared_buf, uint8_t *mem) {
+
+    hyper_virtual_console_params_t *p_consol = (hyper_virtual_console_params_t *)shared_buf;
+    p_consol->msg = p_consol->msg + (uint64_t)mem;
+
+    op_callback_console_conclude(p_consol);
+}
+
+static void wrapper_op_timer(uint8_t *shared_buf) {
+
+    hyper_timer_sleep_params_t *p_timer = (hyper_timer_sleep_params_t *)shared_buf;
+    op_callback_timer_conclude(p_timer);
+}
+
+static void wrapper_op_gfx_init(uint8_t *shared_buf) {
+
+    hyper_init_gfx_params_t *p_init_gfx = (hyper_init_gfx_params_t *)shared_buf;
+    op_callback_gfx_init_conclude(p_init_gfx);
+}
+
 // --- FUNCTION ---
 
 // - VMM EXIT REASON HANDLER -
@@ -75,20 +174,19 @@ void handle_pmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem) {
 
     if (run->io.direction == KVM_EXIT_IO_OUT) {
 
-        uint32_t value = retrieve_value((uint8_t *)run + run->io.data_offset, run->io.size);
-        printf("PMIO guest write: \tsize=%d  \tport=0x%x \tvalue=%d\n", run->io.size * 8, run->io.port, value);
+        uint32_t value = retrieve_data((uint8_t *)run + run->io.data_offset, run->io.size);
+        printf("PMIO guest write: \tport=0x%x \tsize=%d  \tvalue=%d\n", run->io.port, run->io.size * 8, value);
 
-        switch (run->io.port) {
+        if (run->io.port == HYPERCALL_PMIO_ADDR) {
 
-            case HYPERCALL_PMIO_ADDR:
-                handle_hypercall(value, shared_buf, mem);
-            break;
+            handle_hypercall(value, shared_buf, mem);
 
-            case 0x43:
-            break;
+        } else {
 
-            case 0x40:
-            break;
+            current_state = state_check(run->io.port, run->io.size, value);
+
+            if (current_state != NULL)
+                state_compute(current_state, value);
         }
     }
 }
@@ -97,8 +195,13 @@ void handle_mmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem) {
 
     if (run->mmio.is_write) {
 
-        uint32_t value = retrieve_value((uint8_t *)run->mmio.data, run->mmio.len);
+        uint32_t value = retrieve_data((uint8_t *)run->mmio.data, run->mmio.len);
         printf("MMIO guest write: \taddr=0x%llx \tlen=%d \tvalue=%d\n", run->mmio.phys_addr, run->mmio.len * 8, value);
+
+        current_state = state_check(run->mmio.phys_addr, run->mmio.len, value);
+
+        if (current_state != NULL)
+            state_compute(current_state, value);
     }
 }
 
@@ -109,43 +212,20 @@ void handle_hypercall(uint32_t code, uint8_t *shared_buf, uint8_t *mem) {
     switch (code) {
 
         case HYPERCALL_CODE_CONSOLE:
-            handle_hypercall_console(shared_buf, mem);
+            wrapper_op_console(shared_buf, mem);
         break;
 
         case HYPERCALL_CODE_TIMER:
-            handle_hypercall_timer(shared_buf);
+            wrapper_op_timer(shared_buf);
         break;
 
         case HYPERCALL_CODE_GFX_INIT: 
-            handle_hypercall_gfx_init(shared_buf);
+            wrapper_op_gfx_init(shared_buf);
         break;
 
         default:
-            // TODO:
+            errx(1, "Unsupported hypercall code.\n");
         break;
     }
 }
 
-void handle_hypercall_console(uint8_t *shared_buf, uint8_t *mem) {
-
-    hyper_virtual_console_params_t *p_consol = (hyper_virtual_console_params_t *)shared_buf;
-
-    printf("hypercall : sending a message...\n");
-    printf("%s\n", p_consol->msg + mem);
-}
-
-void handle_hypercall_timer(uint8_t *shared_buf) {
-
-    hyper_timer_sleep_params_t *p_timer = (hyper_timer_sleep_params_t *)shared_buf;
-
-    printf("hypercall : setting up a %dus timer...\n", p_timer->us);
-    sleep(p_timer->us / 1e6);
-}
-
-void handle_hypercall_gfx_init(uint8_t *shared_buf) {
-
-    hyper_init_gfx_params_t *p_init_gfx = (hyper_init_gfx_params_t *)shared_buf;
-
-    printf("hypercall : initializing gfx...\n");
-    // TODO:
-}
diff --git a/vmm/handler.h b/vmm/handler.h
index 29ada075aeb57bf58497be0650d500a1c4751358..205bc24545566fb0cd4db364935ef808a3374e12 100644
--- a/vmm/handler.h
+++ b/vmm/handler.h
@@ -6,24 +6,8 @@
 
 // --- DEFINE ---
 
-typedef enum {
-
-    OP_WRITE_EQUAL,
-    OP_READ_INJECT,
-    OP_EMUL_END,
-} operation_t;
-
 typedef void (*state_handler_t)(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem);
 
-typedef struct {
-
-    operation_t op;       // the operation to perform
-    uint32_t addr;        // the address written to/read from
-    uint32_t value;       // the expected written value or value to inject
-    uint8_t size;         // the size of the operation (8, 16 or 32 bits)
-    void (*callback)();   // custom function that would be executed at the end of the state
-} state_t;
-
 extern state_handler_t const STATE_HANDLERS[];
 
 // --- FUNCITON ---
@@ -36,10 +20,4 @@ void handle_mmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem);
 
 void handle_hypercall(uint32_t code, uint8_t *shared_buf, uint8_t *mem);
 
-void handle_hypercall_console(uint8_t *shared_buf, uint8_t *mem);
-
-void handle_hypercall_timer(uint8_t *shared_buf);
-
-void handle_hypercall_gfx_init(uint8_t *shared_buf);
-
-#endif // !_STATES_H_
+#endif // _STATES_H_
diff --git a/vmm/operation.c b/vmm/operation.c
new file mode 100644
index 0000000000000000000000000000000000000000..471256fd52eca87574b9e7aa731aefccb81d20d3
--- /dev/null
+++ b/vmm/operation.c
@@ -0,0 +1,79 @@
+#include "operation.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "shared/hypercall_params.h"
+
+// --- DEFINE ---
+
+state_t STATE_TIMER[] = {
+
+    { OP_WRITE_EQUAL, REG_TIMER_CMD,  20, 2, NULL },
+    { OP_WRITE_STORE, REG_TIMER_DATA, 0,  4, op_callback_timer_store },
+    { OP_EMUL_END,    0,              0,  0, op_callback_timer_conclude },
+};
+
+state_t STATE_GFX_INIT[] = {
+
+    { OP_READ_INJECT, REG_GFX_INIT_ST,   0, 4, NULL },
+    { OP_WRITE_EQUAL, REG_GFX_INIT_CMD,  5, 4, NULL },
+    { OP_WRITE_STORE, REG_GFX_INIT_DATA, 0, 4, op_callback_gfx_init_store_w},
+    { OP_WRITE_STORE, REG_GFX_INIT_DATA, 0, 4, op_callback_gfx_init_store_h},
+    { OP_EMUL_END,    0,                 0, 0, op_callback_gfx_init_conclude},
+};
+
+state_t *STATE_ALL_STARTERS[] = {
+
+    &STATE_TIMER[0],
+    &STATE_GFX_INIT[0],
+};
+
+static hyper_timer_sleep_params_t param_timer;
+static hyper_init_gfx_params_t param_gfx_init;
+
+// --- STATIC FUNCTION ---
+
+// ...
+
+// --- FUNCTION ---
+
+void op_callback_console_conclude(void *addr) {
+
+    hyper_virtual_console_params_t *p_consol = (hyper_virtual_console_params_t *)addr;
+
+    printf("hypercall : sending a message...\n");
+    printf("%s\n", (char *)p_consol->msg);
+}
+
+void op_callback_timer_store(void *addr) {
+
+    param_timer.us = *(uint32_t *)addr;
+}
+
+void op_callback_timer_conclude(void *addr) {
+
+    hyper_timer_sleep_params_t *p_timer = (addr == NULL) ? &param_timer : (hyper_timer_sleep_params_t *)addr;
+
+    printf("hypercall : setting up a %dus timer...\n", p_timer->us);
+    sleep(p_timer->us / 1e6);
+}
+
+void op_callback_gfx_init_store_w(void *addr) {
+
+    param_gfx_init.width = *(uint32_t *)addr;
+}
+
+void op_callback_gfx_init_store_h(void *addr) {
+
+    param_gfx_init.height = *(uint32_t *)addr;
+}
+
+void op_callback_gfx_init_conclude(void *addr) {
+
+    hyper_init_gfx_params_t *p_gfx_init = (addr == NULL) ? &param_gfx_init : (hyper_init_gfx_params_t *)addr;
+
+    printf("hypercall : initializing gfx %dx%d...\n", p_gfx_init->width, p_gfx_init->height);
+    // TODO:
+}
diff --git a/vmm/operation.h b/vmm/operation.h
new file mode 100644
index 0000000000000000000000000000000000000000..e77ef141188a6d798fdadde90ada7ddd46cd4735
--- /dev/null
+++ b/vmm/operation.h
@@ -0,0 +1,51 @@
+#define _OPERATION_H_
+#ifdef _OPERATION_H_
+
+#include <stdint.h>
+#include <unistd.h>
+
+
+// --- DEFINE ---
+
+#define STATE_MACHINE_NUM 2
+
+typedef enum {
+
+    OP_WRITE_EQUAL,
+    OP_WRITE_STORE,
+    OP_READ_INJECT,
+    OP_EMUL_END,
+} operation_t;
+
+typedef struct {
+
+    operation_t op;                 // the operation to perform
+    uint32_t addr;                  // the address written to/read from
+    uint32_t value;                 // the expected written value or value to inject
+    uint8_t size;                   // the size of the operation (8, 16 or 32 bits)
+    void (*callback)(void *addr);   // custom function that would be executed at the end of the state
+} state_t;
+
+extern state_t *STATE_ALL_STARTERS[];
+
+extern state_t STATE_TIMER[];
+
+extern state_t STATE_GFX_INIT[];
+
+extern state_t STATE_VGA[];
+
+// --- FUNCITON ---
+
+void op_callback_console_conclude(void *addr);
+
+void op_callback_timer_store(void *addr);
+
+void op_callback_timer_conclude(void *addr);
+
+void op_callback_gfx_init_store_w(void *addr);
+
+void op_callback_gfx_init_store_h(void *addr);
+
+void op_callback_gfx_init_conclude(void *addr);
+
+#endif // _OPERATION_H_