/* * The thread start routine for pipe stage threads. * Each will wait for a data item passed from the caller or the previous stage, * modify the data and pass it along to the next (or final) stage. */ void *pipe_stage(void *arg) { stage_t *stage = (stage_t *)arg; stage_t *next_stage = stage->next; int status; status = pthread_mutex_lock(&stage->mutex); status_check(status, "Lock pipe stage"); while (1) { while (!stage->data_ready) { status = pthread_cond_wait(&stage->avail, &stage->mutex); status_check(status, "Wait for previous stage"); } pipe_send(next_stage, stage->data + 1); stage->data_ready = false; status = pthread_cond_signal(&stage->ready); status_check(status, "Wake next stage"); } /* * Notice that the routine never unlocks the stage->mutex. * The call to pthread_cond_wait implicitly unlocks the mutex * while the thread is waiting, allowing other threads to make progress. * Because the loop never terminates, this function has no need to unlock * the mutex explicitly. */ return NULL; }
/* * Collect the result of the pipeline. Wait for a result if the pipeline * hasn't produced one. * return true when get result, false when does not get a result. */ bool pipe_result(pipe_t *pipe, long *result) { stage_t *tail = pipe->tail; bool empyt = false; int status; status = pthread_mutex_lock(&pipe->mutex); status_check(status, "Lock pipe mutex"); if (pipe->active <= 0) { empyt = true; } else { pipe->active--; } status = pthread_mutex_unlock(&pipe->mutex); status_check(status, "Unlock pipe mutex"); if (empyt) { return false; } status = pthread_mutex_lock(&tail->mutex); status_check(status, "Lock tail mutex"); while (!tail->data_ready) { pthread_cond_wait(&tail->avail, &tail->mutex); } *result = tail->data; tail->data_ready = false; status = pthread_cond_signal(&tail->ready); status_check(status, "Signal tail ready"); status = pthread_mutex_unlock(&tail->mutex); status_check(status, "Unlock tail mutex"); return true; }
void SensorResource::activeCheck() { bool sensor_changed = false; sensor_changed = status_check(m_gas) || status_check(m_fan) || status_check(m_led) || status_check(m_pri); if (sensor_changed) { ChangeSensorRepresentation(); } }
void finished_quantum_post_process() { printf(ANSI_COLOR_RED); log_info(cpu_log, "=== Finished Quantum ==="); printf(ANSI_COLOR_RESET); if(status_check() == EXECUTING) { status_update(READY); } if(status_check() == BLOCKED || status_check() == WAITING) { return; } send_quantum_end_notif(); }
int post_process_operations() { actual_kernel_data->Q--; actual_pcb->program_counter++; if(status_check() != WAITING && status_check() != BROKEN) { printf(ANSI_COLOR_BLUE); log_info(cpu_log, "Remaining Quantum : %d", actual_kernel_data->Q); printf(ANSI_COLOR_RESET); printf(ANSI_COLOR_YELLOW); log_info(cpu_log, "Next execution line :%d", actual_pcb->program_counter); printf(ANSI_COLOR_RESET); } return SUCCESS; }
/* * External function to create a pipeline. All the data is initialized * and the threads created. They'll wait for data. */ int pipe_create(pipe_t *pipe, int stages) { int pipe_index; stage_t **link = &pipe->head, *new_stage = NULL, *stage; int status; status = pthread_mutex_init(&pipe->mutex, NULL); status_check(status, "Init pipe mutex"); pipe->stages = stages; pipe->active = 0; /* * Create (stages + 1) stage, final stage is for stash result */ for (pipe_index = 0; pipe_index <= stages; pipe_index++) { new_stage = (stage_t *)malloc(sizeof(stage_t)); condition_check(new_stage != NULL, "Allocate stage"); status = pthread_mutex_init(&new_stage->mutex, NULL); status_check(status, "Init stage mutex"); status = pthread_cond_init(&new_stage->avail, NULL); status_check(status, "Init avail condition"); status = pthread_cond_init(&new_stage->ready, NULL); status_check(status, "Init ready condition"); new_stage->data_ready = false; *link = new_stage; link = &new_stage->next; } *link = (stage_t *)NULL; /* Terminate list */ pipe->tail = new_stage; /* Record the tail */ /* * Create the threads for the pipe stage only after all the data is * initialized (including all links). Note that the last stage doesn't get * thread, it's just a receptacle for the final pipeline value. * * At this point, proper cleanup on an error would take up more space * than worthwhile in a "simple example", so instead of cancelling and * detaching all the threads already created, plus the synchronization * object and memory cleanup done for earlier errors, it will simply abort. */ for (stage = pipe->head; stage->next != NULL; stage = stage->next) { status = pthread_create(&stage->thread, NULL, pipe_stage, (void *)stage); status_check(status, "Create pipe stage"); } return 0; }
t_valor_variable obtenerValorCompartida(t_nombre_compartida variable){ if(status_check() != EXECUTING) return ERROR; //5 + 0 + nameSize + name (1+1+4+nameSize bytes) void* buffer = NULL; int value = 0, variable_name_length = (int) strlen(variable), buffer_index = 0; char operation = SHARED_VAR_ID, action = GET_VAR; // asprintf(&buffer, "%d%d%04d%s", atoi(SHARED_VAR_ID), atoi(GET_VAR), strlen(variable), variable); serialize_data(&operation, sizeof(char), &buffer, &buffer_index); serialize_data(&action, sizeof(char), &buffer, &buffer_index); serialize_data(&variable_name_length, sizeof(int), &buffer, &buffer_index); serialize_data(variable, (size_t) variable_name_length, &buffer, &buffer_index); if(send(kernelSocketClient, buffer, (size_t) buffer_index, 0) < 0) { log_error(cpu_log, "send of obtener variable compartida of %s failed", variable); free(buffer); return ERROR; } free(buffer); buffer = calloc(1, sizeof(int)); if(recv(kernelSocketClient, buffer, sizeof(int), 0) <= 0) { log_error(cpu_log, "recv of obtener variable compartida failed"); return ERROR; } int deserialize_index = 0; deserialize_data(&value, sizeof(int), buffer, &deserialize_index); log_info(cpu_log, "recv value %d of obtener variable %s", value, variable); free(buffer); return value; }
static void impl_setLineStatus(PortableServer_Servant servant, GNOME_Evolution_ShellState shell_state, GNOME_Evolution_Listener listener, CORBA_Environment *ev) { struct _setline_data *sd; int status = status_check(shell_state); /* This will dis/enable further auto-mail-check action. */ /* FIXME: If send/receive active, wait for it to finish? */ if (status) camel_session_set_online(session, status); sd = g_malloc0(sizeof(*sd)); sd->status = status; sd->listener = CORBA_Object_duplicate(listener, ev); if (ev->_major == CORBA_NO_EXCEPTION) mail_component_stores_foreach(mail_component_peek(), setline_check, sd); else CORBA_exception_free(ev); if (sd->pending == 0) { if (sd->listener) { CORBA_Object_release(sd->listener, ev); CORBA_exception_free(ev); } g_free(sd); if (!status) camel_session_set_online(session, status); GNOME_Evolution_Listener_complete(listener, ev); } }
void la_wait (t_nombre_semaforo identificador_semaforo){ if(status_check() != EXECUTING) return; void * buffer = NULL, *response_buffer = calloc(1,sizeof(char)); int buffer_index = 0, identificador_semaforo_length = (int) strlen(identificador_semaforo); char operation = SEMAPHORE_ID, action = WAIT_ID; // asprintf(&buffer, "%d%d%04d%s", atoi(SEMAPHORE_ID), atoi(WAIT_ID), strlen(identificador_semaforo), identificador_semaforo); serialize_data(&operation, sizeof(char), &buffer, &buffer_index); serialize_data(&action, sizeof(char), &buffer, &buffer_index); serialize_data(&identificador_semaforo_length, sizeof(int), &buffer, &buffer_index); serialize_data(identificador_semaforo, (size_t) identificador_semaforo_length, &buffer, &buffer_index); if(send(kernelSocketClient, buffer, (size_t) buffer_index, 0) < 0) { log_error(cpu_log, "wait(%s) failed", identificador_semaforo); return; } status_update(WAITING); log_info(cpu_log, "Starting wait"); //me quedo esperando activamente a que kernel me responda // recv(kernelSocketClient, response_buffer, sizeof(char), 0); //kernel_response debería ser '0' // log_info(cpu_log, "Finished wait"); free(buffer); free(response_buffer); }
/* * External interface to start a pipeline by passing data to the first stage. * The routine returns while the pipeline processes in parallel. Call the * pipe_result return to collect the final stage values (note that the pipeline * will stall when each stage fills, until the result is collected). */ int pipe_start(pipe_t *pipe, long value) { int status; status = pthread_mutex_lock(&pipe->mutex); status_check(status, "Lock pipe mutex"); if (pipe->active >= pipe->stages) { fprintf(stdout, "Pipeline is fully, please try later.\n"); status = pthread_mutex_unlock(&pipe->mutex); status_check(status, "Unlock pipe mutex"); return 1; } pipe->active++; status = pthread_mutex_unlock(&pipe->mutex); status_check(status, "Unlock pipe mutex"); pipe_send(pipe->head, value); return 0; }
void llamarSinRetorno (t_nombre_etiqueta etiqueta){ if(status_check() != EXECUTING) return; t_ret_var * ret_var_addr = calloc(1, sizeof(t_ret_var)); t_stack * stack_index = actual_pcb->stack_index; //1) Creo la nueva entrada del stack t_stack_entry* new_stack_entry = create_new_stack_entry(); //2) Guardo la posicion de PC actual como retpos de la nueva entrada new_stack_entry->ret_pos = actual_pcb->program_counter; //3) Agrego la strack entry a la queue de stack queue_push(actual_pcb->stack_index, new_stack_entry); //4) Asigno el PC a la etiqueta objetivo irAlLabel(etiqueta); }
void retornar(t_valor_variable retorno) { if(status_check() != EXECUTING) return; //1) Obtengo el stack index t_stack * actual_stack_index = actual_pcb->stack_index; //2) Obtengo la entrada actual t_stack_entry *last_entry = get_last_entry(actual_stack_index); //3) Actualizo el PC a la posicion de retorno de la entrada actual actual_pcb->program_counter = last_entry->ret_pos; //4) Asigno el valor de retorno de la entrada actual a la variable de retorno asignar(obtener_t_posicion(last_entry->ret_vars), retorno); //5) Libero la ultima entrada del indice de stack free(pop_stack(actual_stack_index)); }
int check_execution_state() { switch(status_check()) { case EXIT: case BROKEN: case ABORTED: program_end_notification(); return EXIT; case BLOCKED: case WAITING: return EXIT; default: break; } return SUCCESS; }
static status_check parse_status_check_arg(const std::string& arg) { const std::string::size_type delimiter = arg.find(':'); bool negated = (arg.compare(0, 4, "not-") == 0); const std::string action_str = arg.substr(0, delimiter); const std::string action = negated ? action_str.substr(4) : action_str; const std::string value_str = ( delimiter == std::string::npos ? "" : arg.substr(delimiter + 1)); int value; status_check_t type; if (action == "eq") { // Deprecated; use exit instead. TODO: Remove after 0.10. type = sc_exit; if (negated) throw atf::application::usage_error("Cannot negate eq checker"); negated = false; value = parse_exit_code(value_str); } else if (action == "exit") { type = sc_exit; if (value_str.empty()) value = INT_MIN; else value = parse_exit_code(value_str); } else if (action == "ignore") { if (negated) throw atf::application::usage_error("Cannot negate ignore checker"); type = sc_ignore; value = INT_MIN; } else if (action == "ne") { // Deprecated; use not-exit instead. TODO: Remove after 0.10. type = sc_exit; if (negated) throw atf::application::usage_error("Cannot negate ne checker"); negated = true; value = parse_exit_code(value_str); } else if (action == "signal") { type = sc_signal; if (value_str.empty()) value = INT_MIN; else value = parse_signal(value_str); } else throw atf::application::usage_error("Invalid output checker"); return status_check(type, negated, value); }
void imprimir(t_valor_variable valor) { if(status_check() != EXECUTING) return; void * buffer = NULL; int buffer_index = 0; char operation = IMPRIMIR_ID; // asprintf(&buffer, "%d%04d", atoi(IMPRIMIR_ID), valor); serialize_data(&operation , sizeof(char), &buffer, &buffer_index); serialize_data(&valor, sizeof(int), &buffer, &buffer_index); if(send(kernelSocketClient, buffer, (size_t) buffer_index, 0) < 0) { log_error(cpu_log, "imprimir value %d send to KERNEL failed", valor); return ; } log_info(cpu_log, "imprimir value %d sent to KERNEL"); free(buffer); }
t_valor_variable dereferenciar(t_posicion direccion_variable) { if(status_check() != EXECUTING) return ERROR; //Hacemos el request a la UMC con el codigo 2 t_list *pedidos = NULL; construir_operaciones_lectura(&pedidos, direccion_variable); void * variable_buffer = calloc(1, ANSISOP_VAR_SIZE), *umc_request_buffer = NULL; int variable_buffer_index = 0; char response_status; logical_addr * current_address = NULL; while(list_size(pedidos) > 0) { current_address = list_remove(pedidos, 0); // asprintf(&umc_request_buffer, "3%04d%04d%04d", current_address->page_number, // current_address->offset, current_address->tamanio); int umc_request_buffer_index = 0; char operation = PEDIDO_BYTES; serialize_data(&operation, sizeof(char), &umc_request_buffer, &umc_request_buffer_index); serialize_data(¤t_address->page_number, sizeof(int), &umc_request_buffer, &umc_request_buffer_index); serialize_data(¤t_address->offset, sizeof(int), &umc_request_buffer, &umc_request_buffer_index); serialize_data(¤t_address->tamanio, sizeof(int), &umc_request_buffer, &umc_request_buffer_index); log_info(cpu_log, "sending request : op:%c (%d,%d,%d) for direccion variable %d",operation, current_address->page_number, current_address->offset, current_address->tamanio, direccion_variable); // log_info(cpu_log, "sending request : %s for direccion variable %d", &umc_request_buffer, direccion_variable); if( send(umcSocketClient, umc_request_buffer, (size_t) umc_request_buffer_index, 0) < 0) { log_error(cpu_log, "UMC expected addr send failed"); return ERROR; } if(check_umc_response(recv_umc_response_status()) != SUCCESS) { return ERROR; } if( recv(umcSocketClient , ((char*) variable_buffer) + variable_buffer_index , (size_t) current_address->tamanio, 0) <= 0) { log_error(cpu_log, "UMC response recv failed"); break; } variable_buffer_index += current_address->tamanio; } free(umc_request_buffer); log_info(cpu_log, "Valor variable obtained : %d", *(int*)variable_buffer); return (t_valor_variable) *(t_valor_variable*)variable_buffer; }
void asignar(t_posicion direccion_variable, t_valor_variable valor) { if(status_check() != EXECUTING) return; t_list * pedidos = NULL; obtener_lista_operaciones_escritura(&pedidos, direccion_variable, ANSISOP_VAR_SIZE, valor); char * umc_response_buffer = calloc(1, sizeof(char)); if(umc_response_buffer == NULL) { log_error(cpu_log, "asignar umc_response_buffer mem alloc failed"); return; } int index = 0; t_nodo_send * nodo = NULL; int page, offset, size, print_index = 0; char operation; while (list_size(pedidos) > 0) { nodo = list_remove(pedidos, index); if(nodo != NULL) { deserialize_data(&operation, sizeof(char), nodo->data, &print_index); deserialize_data(&page, sizeof(int), nodo->data, &print_index); deserialize_data(&offset, sizeof(int), nodo->data, &print_index); deserialize_data(&size, sizeof(int), nodo->data, &print_index); log_info(cpu_log, "Sending request op:%c (%d,%d,%d) for direccion variable %d with value %d", operation, page, offset, size, direccion_variable, valor); // log_info(cpu_log, "sending request : %s for direccion variable %d with value %d", nodo->data , direccion_variable, valor); if( send(umcSocketClient, nodo->data , (size_t ) nodo->data_length, 0) < 0) { log_error(cpu_log, "UMC expected addr send failed"); break; } //EXITO (Se podria loggear de que la operacion fue exitosa) if(check_umc_response(recv_umc_response_status()) == SUCCESS){ log_info(cpu_log, "Asignar variable operation to UMC with value %d was successful", valor); } else { log_error(cpu_log, "Asignar variable operation to UMC with value %d failed", valor); break; } free(nodo); } } list_destroy(pedidos); //Liberamos la estructura de lista reservada free(umc_response_buffer); log_info(cpu_log, "Finished asignar variable operations"); }
void la_signal (t_nombre_semaforo identificador_semaforo){ if(status_check() != EXECUTING) return; void * buffer = NULL; int buffer_index = 0, identificador_semaforo_length = (int) strlen(identificador_semaforo); char operation = SEMAPHORE_ID, action = SIGNAL_ID; // asprintf(&buffer, "%d%d%04d%s", atoi(SEMAPHORE_ID), atoi(SIGNAL_ID), strlen(identificador_semaforo), identificador_semaforo); serialize_data(&operation, sizeof(char), &buffer, &buffer_index); serialize_data(&action, sizeof(char), &buffer, &buffer_index); serialize_data(&identificador_semaforo_length, sizeof(int), &buffer, &buffer_index); serialize_data(identificador_semaforo, identificador_semaforo_length, &buffer, &buffer_index); if(send(kernelSocketClient, buffer, (size_t) buffer_index, 0) < 0) { log_error(cpu_log, "signal(%s) failed", identificador_semaforo); return; } }
void imprimirTexto(char* texto) { if(status_check() != EXECUTING) return; void * buffer = NULL; int texto_len = (int) strlen(texto), buffer_index = 0; char operation = IMPRIMIR_TEXTO_ID; // asprintf(&buffer, "%d%04d%s", atoi(IMPRIMIR_TEXTO_ID), texto_len, texto); serialize_data(&operation, sizeof(char), &buffer, &buffer_index); serialize_data(&texto_len, sizeof(int), &buffer, &buffer_index); serialize_data(texto, (size_t) texto_len, &buffer, &buffer_index); if(send(kernelSocketClient, buffer, (size_t) buffer_index, 0) < 0) { log_error(cpu_log, "imprimirTexto with texto : %s , send failed", texto); return; } log_info(cpu_log, "imprimirTexto with texto : %s , sent to KERNEL", texto); free(buffer); }
t_posicion obtenerPosicionVariable(t_nombre_variable variable) { if(status_check() != EXECUTING) return ERROR; logical_addr * direccion_logica = NULL; int i = 0; //1) Obtener el stack index actual t_stack_entry* current_stack_index = get_last_entry(actual_pcb->stack_index); //2) Obtener puntero a las variables t_var* indice_variable = current_stack_index->vars; for (i = 0; i < current_stack_index->cant_vars ; i++) { if( (indice_variable + i)->var_id == variable ) { return get_t_posicion(indice_variable + i); // (t_posicion) (indice_variable->page_number * setup->PAGE_SIZE) + indice_variable->offset; } } return ERROR; }
void llamarConRetorno(t_nombre_etiqueta etiqueta, t_puntero donde_retornar) { if(status_check() != EXECUTING) return; t_ret_var * ret_var_addr = calloc(1, sizeof(t_ret_var)); //1) Obtengo la direccion a donde apunta la variable de retorno ret_var_addr = armar_direccion_logica_variable(donde_retornar, setup->PAGE_SIZE); t_stack_entry * actual_stack_entry = get_last_entry(actual_pcb->stack_index); //2) Creo la nueva entrada del stack t_stack_entry* new_stack_entry = create_new_stack_entry(); //3) Guardo la posicion de PC actual como retpos de la nueva entrada new_stack_entry->pos = actual_stack_entry->pos + 1; new_stack_entry->ret_pos = actual_pcb->program_counter; //4) Agrego la retvar a la entrada add_ret_var(&new_stack_entry, ret_var_addr); //5) Agrego la strack entry a la queue de stack queue_push(actual_pcb->stack_index, new_stack_entry); // (t_stack_entry*) list_get(actual_pcb->stack_index->elements, 1) //6) Asigno el PC a la etiqueta objetivo irAlLabel(etiqueta); }
t_valor_variable asignarValorCompartida(t_nombre_compartida variable, t_valor_variable valor){ if(status_check() != EXECUTING) return ERROR; //5 + 1 + nameSize + name + value (1+1+4+nameSize+4 bytes) void* buffer = NULL; int buffer_index = 0, variable_length = (int) strlen(variable); char operation = SHARED_VAR_ID, action = SET_VAR; // asprintf(&buffer, "%d%d%04d%s%04d", atoi(SHARED_VAR_ID), atoi(SET_VAR), strlen(variable), variable, valor); serialize_data(&operation, sizeof(char), &buffer, &buffer_index); serialize_data(&action, sizeof(char), &buffer, &buffer_index); serialize_data(&variable_length, sizeof(int), &buffer, &buffer_index); serialize_data(variable, (size_t) variable_length, &buffer, &buffer_index); serialize_data(&valor, sizeof(int), &buffer, &buffer_index); if(send(kernelSocketClient, buffer, (size_t) buffer_index, 0) < 0) { log_error(cpu_log, "set value of %s failed", variable); return ERROR; } log_info(cpu_log, "asignarValorCompartida of %s with value %d was successful", variable, valor); free(buffer); return valor; }
void entradaSalida(t_nombre_dispositivo dispositivo, int tiempo) { if(status_check() != EXECUTING) return; //cambio el estado del pcb status_update(BLOCKED); //3+ ioNameSize + ioName + io_units (1+4+ioNameSize+4 bytes) void * buffer = NULL; char operation = ENTRADA_SALIDA_ID; int dispositivo_length = (int) strlen(dispositivo), buffer_index = 0; //Armo paquete de I/O operation // asprintf(&buffer, "%d%04d%s%04d", atoi(ENTRADA_SALIDA_ID), strlen(dispositivo), dispositivo, tiempo); serialize_data(&operation, sizeof(char), &buffer, &buffer_index); serialize_data(&dispositivo_length, sizeof(int), &buffer, &buffer_index); serialize_data(dispositivo, (size_t) dispositivo_length, &buffer, &buffer_index); serialize_data(&tiempo, sizeof(int), &buffer, &buffer_index); //Envio el paquete a KERNEL if(send(kernelSocketClient, buffer, (size_t) buffer_index, 0) < 0) { log_error(cpu_log, "entrada salida of dispositivo %s %d time send to KERNEL failed", dispositivo, tiempo); } free(buffer); }
int main() { unsigned char status_reg = 0, error_reg = 1; char ptr[512]={0}; printf("%x\n",get_drive_head(0,0)); printf("%x\n",test(0xAB)); printf("%x\n",test1(0xBA)); printf("%x\n",test2(0xCA)); printf("ptr=%x %x\n",ptr,pio_read(0xA,0xB,0xC,0xD,ptr)); printf("%x\n",0xC+0x4); printf("%x\n",0x10+0x4); status_reg = 1; // status_reg |= (1<<7); // Set BSY if(status_check(0, error_reg, status_reg) == 0) { printf("status_check:: no error\n"); } if(bit_test(status_reg)==1) { printf("bit_test:: error\n"); } else { printf("bit_test:: no error\n"); } return 0; }
int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op *mop) { int rc; struct arch_domain *ad = &d->arch; uint32_t capabilities = get_capabilities(d); rc = xsm_vm_event_control(XSM_PRIV, d, mop->op, mop->event); if ( rc ) return rc; switch ( mop->op ) { case XEN_DOMCTL_MONITOR_OP_GET_CAPABILITIES: mop->event = capabilities; return 0; case XEN_DOMCTL_MONITOR_OP_EMULATE_EACH_REP: d->arch.mem_access_emulate_each_rep = !!mop->event; return 0; } /* * Sanity check */ if ( mop->op != XEN_DOMCTL_MONITOR_OP_ENABLE && mop->op != XEN_DOMCTL_MONITOR_OP_DISABLE ) return -EOPNOTSUPP; /* Check if event type is available. */ if ( !(capabilities & (1 << mop->event)) ) return -EOPNOTSUPP; switch ( mop->event ) { case XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG: { unsigned int ctrlreg_bitmask = monitor_ctrlreg_bitmask(mop->u.mov_to_cr.index); bool_t status = !!(ad->monitor.write_ctrlreg_enabled & ctrlreg_bitmask); struct vcpu *v; rc = status_check(mop, status); if ( rc ) return rc; if ( mop->u.mov_to_cr.sync ) ad->monitor.write_ctrlreg_sync |= ctrlreg_bitmask; else ad->monitor.write_ctrlreg_sync &= ~ctrlreg_bitmask; if ( mop->u.mov_to_cr.onchangeonly ) ad->monitor.write_ctrlreg_onchangeonly |= ctrlreg_bitmask; else ad->monitor.write_ctrlreg_onchangeonly &= ~ctrlreg_bitmask; domain_pause(d); if ( !status ) ad->monitor.write_ctrlreg_enabled |= ctrlreg_bitmask; else ad->monitor.write_ctrlreg_enabled &= ~ctrlreg_bitmask; domain_unpause(d); if ( mop->u.mov_to_cr.index == VM_EVENT_X86_CR3 ) /* Latches new CR3 mask through CR0 code */ for_each_vcpu ( d, v ) hvm_update_guest_cr(v, 0); break; } case XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR: { bool_t status = ad->monitor.mov_to_msr_enabled; rc = status_check(mop, status); if ( rc ) return rc; if ( mop->op == XEN_DOMCTL_MONITOR_OP_ENABLE && mop->u.mov_to_msr.extended_capture ) { if ( hvm_enable_msr_exit_interception(d) ) ad->monitor.mov_to_msr_extended = 1; else return -EOPNOTSUPP; } else ad->monitor.mov_to_msr_extended = 0; domain_pause(d); ad->monitor.mov_to_msr_enabled = !status; domain_unpause(d); break; } case XEN_DOMCTL_MONITOR_EVENT_SINGLESTEP: { bool_t status = ad->monitor.singlestep_enabled; rc = status_check(mop, status); if ( rc ) return rc; domain_pause(d); ad->monitor.singlestep_enabled = !status; domain_unpause(d); break; } case XEN_DOMCTL_MONITOR_EVENT_SOFTWARE_BREAKPOINT: { bool_t status = ad->monitor.software_breakpoint_enabled; rc = status_check(mop, status); if ( rc ) return rc; domain_pause(d); ad->monitor.software_breakpoint_enabled = !status; domain_unpause(d); break; } case XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST: { bool_t status = ad->monitor.guest_request_enabled; rc = status_check(mop, status); if ( rc ) return rc; ad->monitor.guest_request_sync = mop->u.guest_request.sync; domain_pause(d); ad->monitor.guest_request_enabled = !status; domain_unpause(d); break; } default: return -EOPNOTSUPP; }; return 0; }
static pwr_tStatus IoAgentInit(io_tCtx ctx, io_sAgent* ap) { int sts; io_sLocalHilscher_cifX_PnController* local; pwr_sClass_Hilscher_cifX_PnController* op = (pwr_sClass_Hilscher_cifX_PnController*)ap->op; local = (io_sLocalHilscher_cifX_PnController*)calloc( 1, sizeof(io_sLocalHilscher_cifX_PnController)); ap->Local = local; strcpy(op->ErrorStr, ""); op->Status = 0; if (driver == 0) { struct CIFX_LINUX_INIT init; memset(&init, 0, sizeof(init)); init.init_options = CIFX_DRIVER_INIT_AUTOSCAN; init.trace_level = 255; sts = cifXDriverInit(&init); if (!status_check(op, ap, sts, "cifXDriverInit")) return IO__INITFAIL; sts = xDriverOpen(&driver); if (!status_check(op, ap, sts, "xDriverOpen")) return IO__INITFAIL; } // Find the board unsigned long board = 0; BOARD_INFORMATION boardinfo; boardinfo.lBoardError = 0; int found = 0; while (xDriverEnumBoards(driver, board, sizeof(boardinfo), &boardinfo) == CIFX_NO_ERROR) { if (str_NoCaseStrcmp(boardinfo.abBoardAlias, op->Alias) == 0) { found = 1; break; } board++; } if (!found) { sprintf(op->ErrorStr, "Board with alias \"%s\" not found", op->Alias); errh_Error("IO init %s, '%s'", ap->Name, op->ErrorStr); return IO__INITFAIL; } op->Diag.DeviceNumber = boardinfo.tSystemInfo.ulDeviceNumber; op->Diag.SerialNumber = boardinfo.tSystemInfo.ulSerialNumber; op->Diag.SystemError = boardinfo.ulSystemError; // op->Diag.VendorId = boardinfo.tSystemInfo.usManufacturer; local->channel = 0; local->chan = NULL; sts = xChannelOpen(NULL, (char*)CIFX_DEV, local->channel, &local->chan); if (!status_check(op, ap, sts, "xChannelOpen")) return IO__INITFAIL; uint32_t state; strcpy(op->ErrorStr, "Device host state not ready"); for (;;) { sts = xChannelHostState(local->chan, CIFX_HOST_STATE_READY, &state, 100); if (sts != CIFX_DEV_NOT_READY) break; sleep(1); } strcpy(op->ErrorStr, ""); sts = xChannelReset(local->chan, CIFX_SYSTEMSTART, 2000); if (sts != CIFX_NO_ERROR) { printf("xChannelReset: 0x%08x\n", sts); } for (;;) { sts = xChannelHostState(local->chan, CIFX_HOST_STATE_READY, &state, 100); if (sts != CIFX_DEV_NOT_READY) break; sleep(1); } CHANNEL_INFORMATION channelinfo = { { 0 } }; sts = xDriverEnumChannels( driver, board, local->channel, sizeof(channelinfo), &channelinfo); if (sts == CIFX_NO_ERROR) { strncpy(op->Diag.FirmwareName, (char*)channelinfo.abFWName, sizeof(op->Diag.FirmwareName)); snprintf(op->Diag.FirmwareVersion, sizeof(op->Diag.FirmwareVersion), "%u.%u.%u-%u (%4u-%02hu-%02hu)", channelinfo.usFWMajor, channelinfo.usFWMinor, channelinfo.usFWBuild, channelinfo.usFWRevision, channelinfo.usFWYear, channelinfo.bFWMonth, channelinfo.bFWDay); } RCX_LOCK_UNLOCK_CONFIG_REQ_T unlock = { { 0 } }; RCX_LOCK_UNLOCK_CONFIG_CNF_T unlock_cnf = { { 0 } }; unlock.tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); unlock.tHead.ulLen = HOST_TO_LE32(sizeof(unlock.tData)); unlock.tHead.ulCmd = HOST_TO_LE32(RCX_LOCK_UNLOCK_CONFIG_REQ); unlock.tHead.ulSrc = HOST_TO_LE32(PN_SRC); unlock.tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); unlock.tData.ulParam = 2; // Unlock sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)&unlock, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket( local->chan, sizeof(unlock_cnf), (CIFX_PACKET*)&unlock_cnf, 20000); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, unlock_cnf.tHead.ulCmd, RCX_LOCK_UNLOCK_CONFIG_CNF) || !status_check(op, ap, unlock_cnf.tHead.ulSta, "Unlock channel")) return IO__INITFAIL; t_addr ipaddress; t_addr subnetmask; int num; num = sscanf(op->IP_Address, "%hhu.%hhu.%hhu.%hhu", &ipaddress.b[3], &ipaddress.b[2], &ipaddress.b[1], &ipaddress.b[0]); if (num != 4) { sprintf(op->ErrorStr, "IP Address syntax error, %s", ap->Name); return IO__INITFAIL; } num = sscanf(op->SubnetMask, "%hhu.%hhu.%hhu.%hhu", &subnetmask.b[3], &subnetmask.b[2], &subnetmask.b[1], &subnetmask.b[0]); if (num != 4) { sprintf(op->ErrorStr, "SubnetMask syntax error, %s", ap->Name); return IO__INITFAIL; } PNM_APCFG_CFG_PNM_REQ_T pnm_config = { { 0 } }; PNM_APCFG_CFG_PNM_CNF_T pnm_config_cnf; memset(&pnm_config, 0, sizeof(pnm_config)); memset(&pnm_config_cnf, 0, sizeof(pnm_config_cnf)); pnm_config.tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); pnm_config.tHead.ulDestId = 0; pnm_config.tHead.ulLen = HOST_TO_LE32(sizeof(pnm_config.tData)); pnm_config.tHead.ulId = HOST_TO_LE32(msg_id++); pnm_config.tHead.ulCmd = HOST_TO_LE32(PNM_APCTL_CMD_SET_CONFIG_PNM_REQ); pnm_config.tHead.ulSrc = HOST_TO_LE32(PN_SRC); pnm_config.tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); pnm_config.tData.tSubHead.ulTrCntrId = 0; pnm_config.tData.tSubHead.ulTrDevId = 0; pnm_config.tData.tSubHead.ulTrApId = 0; pnm_config.tData.tSubHead.ulTrModId = 0; pnm_config.tData.tSubHead.ulTrSubModId = 0; pnm_config.tData.tSubHead.ulTrIdCnt = 1; pnm_config.tData.atData[0].ulTrId = 1; pnm_config.tData.atData[0].ulSystemFlags = PNM_APCFG_STARTMODE_APPLICATION; pnm_config.tData.atData[0].ulWdgTime = 1000; strncpy((char*)pnm_config.tData.atData[0].abTypeOfStation, op->DeviceType, sizeof(pnm_config.tData.atData[0].abTypeOfStation)); pnm_config.tData.atData[0].usTypeOfStationLen = strlen((char*)pnm_config.tData.atData[0].abTypeOfStation); strncpy((char*)pnm_config.tData.atData[0].abNameOfStation, op->DeviceName, sizeof(pnm_config.tData.atData[0].abNameOfStation)); pnm_config.tData.atData[0].usNameOfStationLen = strlen((char*)pnm_config.tData.atData[0].abNameOfStation); pnm_config.tData.atData[0].usVendorID = 0x011E; /* Hilscher Profinet VendorID */ pnm_config.tData.atData[0].usDeviceID = 0x0203; /* Hilscher cifX DeviceID for IO-Controller */ pnm_config.tData.atData[0].ulIPAddr = ipaddress.m; pnm_config.tData.atData[0].ulNetmask = subnetmask.m; pnm_config.tData.atData[0].ulGateway = 0; pnm_config.tData.atData[0].ulIPFlags = 0; // These are in the 'EXT' message // pnm_config.tData.atData[0].usMAUTypePort0 = PNM_APCFG_PNM_MAUTYPE_AUTO; // pnm_config.tData.atData[0].usMAUTypePort1 = PNM_APCFG_PNM_MAUTYPE_AUTO; // pnm_config.tData.atData[0].ulStructVersion = // PNM_APCFG_CFG_PNM_STRUCT_VERS_1; sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)&pnm_config, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket( local->chan, sizeof(pnm_config_cnf), (CIFX_PACKET*)&pnm_config_cnf, 20); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, pnm_config_cnf.tHead.ulCmd, PNM_APCTL_CMD_SET_CONFIG_PNM_CNF) || !status_check(op, ap, pnm_config_cnf.tHead.ulSta, "Controller Config")) return IO__INITFAIL; // Device loop int device = 0; int input_dpm_offset = 0; int output_dpm_offset = 0; int prev_input_dpm_offset = 0; int prev_output_dpm_offset = 0; io_sRack* rp; io_sCard* cp; int dev_cnt = 0; for (rp = ap->racklist; rp; rp = rp->next) { io_sPnRackLocal* rp_local; dev_cnt++; rp_local = (io_sPnRackLocal*)calloc(1, sizeof(io_sPnRackLocal)); rp->Local = rp_local; rp_local->userdata = calloc(1, sizeof(cifx_sDeviceUserData)); for (cp = rp->cardlist; cp; cp = cp->next) cp->Local = calloc(1, sizeof(io_sPnCardLocal)); GsdmlDeviceData* dev_data; dev_data = new GsdmlDeviceData; pwr_tFileName fname; sprintf(fname, "$pwrp_load/pwr_pn_%s.xml", cdh_ObjidToFnString(NULL, rp->Objid)); dcli_translate_filename(fname, fname); sts = dev_data->read(fname); if (EVEN(sts)) { snprintf(op->ErrorStr, sizeof(op->ErrorStr), "Missing device xml file, %s", rp->Name); return IO__INITFAIL; } ((cifx_sDeviceUserData*)rp_local->userdata)->dev_data = dev_data; } // PNM_IOD PNM_APCFG_CFG_IOD_REQ_T* iod_config = (PNM_APCFG_CFG_IOD_REQ_T*)calloc(1, sizeof(*iod_config) + (dev_cnt - 1) * sizeof(iod_config->tData.atData)); PNM_APCFG_CFG_IOD_CNF_T iod_config_cnf = { { 0 } }; iod_config->tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); iod_config->tHead.ulLen = HOST_TO_LE32(sizeof(iod_config->tData) + (dev_cnt - 1) * sizeof(iod_config->tData.atData)); iod_config->tHead.ulId = HOST_TO_LE32(msg_id++); iod_config->tHead.ulCmd = HOST_TO_LE32(PNM_APCTL_CMD_SET_CONFIG_IOD_REQ); iod_config->tHead.ulSrc = HOST_TO_LE32(PN_SRC); iod_config->tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); iod_config->tData.tSubHead.ulTrCntrId = 1; iod_config->tData.tSubHead.ulTrDevId = 0; iod_config->tData.tSubHead.ulTrApId = 0; iod_config->tData.tSubHead.ulTrModId = 0; iod_config->tData.tSubHead.ulTrSubModId = 0; iod_config->tData.tSubHead.ulTrIdCnt = dev_cnt; device = 0; for (rp = ap->racklist; rp; rp = rp->next) { t_addr ipaddress; t_addr subnetmask; io_sPnRackLocal* rp_local = (io_sPnRackLocal*)rp->Local; GsdmlDeviceData* dev_data = ((cifx_sDeviceUserData*)rp_local->userdata)->dev_data; sscanf(dev_data->ip_address, "%hhu.%hhu.%hhu.%hhu", &ipaddress.b[3], &ipaddress.b[2], &ipaddress.b[1], &ipaddress.b[0]); sscanf(dev_data->subnet_mask, "%hhu.%hhu.%hhu.%hhu", &subnetmask.b[3], &subnetmask.b[2], &subnetmask.b[1], &subnetmask.b[0]); iod_config->tData.atData[device].ulTrId = device + 1; iod_config->tData.atData[device].ulFlags = PNM_APCFG_IOD_FLAG_IOD_ACTIVE; strncpy((char*)iod_config->tData.atData[device].abNameOfStation, dev_data->device_name, sizeof(iod_config->tData.atData[device].abNameOfStation)); iod_config->tData.atData[device].usNameOfStationLen = strlen((char*)iod_config->tData.atData[device].abNameOfStation); iod_config->tData.atData[device].usVendorID = dev_data->vendor_id; iod_config->tData.atData[device].usDeviceID = dev_data->device_id; iod_config->tData.atData[device].ulIPAddr = ipaddress.m; iod_config->tData.atData[device].ulNetworkMask = subnetmask.m; iod_config->tData.atData[device].ulGatewayAddr = 0; iod_config->tData.atData[device].ulArUuidData1 = device + 1; iod_config->tData.atData[device].usArUuidData2 = device + 1; iod_config->tData.atData[device].usArUuidData3 = device + 1; iod_config->tData.atData[device].usARType = PNIO_API_AR_TYPE_SINGLE; iod_config->tData.atData[device].ulARProp = PNIO_API_AR_PROP_SUPERVISOR_NONE | PNIO_API_AR_PROP_STATE_PRIMARY | PNIO_API_AR_PROP_SINGLE_AR | (1 << 4) | (1 << 5); iod_config->tData.atData[device].usAlarmCRType = PNIO_API_ALCR_TYPE_ALARM; iod_config->tData.atData[device].ulAlarmCRProp = PNIO_API_ALCR_PROP_PRIO_DEFAULT; iod_config->tData.atData[device].usAlarmCRVLANID = 0; iod_config->tData.atData[device].ulIPFlags = 0; iod_config->tData.atData[device].usRTATimeoutFact = 1; iod_config->tData.atData[device].usRTARetries = PNIO_API_RTA_RETRIES_MIN; iod_config->tData.atData[device].usObjUUIDInst = dev_data->instance; device++; } sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)iod_config, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket( local->chan, sizeof(iod_config_cnf), (CIFX_PACKET*)&iod_config_cnf, 20); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, iod_config_cnf.tHead.ulCmd, PNM_APCTL_CMD_SET_CONFIG_IOD_CNF) || !status_check(op, ap, pnm_config_cnf.tHead.ulSta, "Device Config")) return IO__INITFAIL; device = 0; for (rp = ap->racklist; rp; rp = rp->next) { // Read device xml-file io_sPnRackLocal* rp_local = (io_sPnRackLocal*)rp->Local; GsdmlDeviceData* dev_data = ((cifx_sDeviceUserData*)rp_local->userdata)->dev_data; unsigned char macaddr[6]; // PNM_IOCR // Calculate data length unsigned int io_input_length = 0; unsigned int io_output_length = 0; unsigned int io_iocr_input_length = 0; unsigned int io_iocr_output_length = 0; for (unsigned int i = 0; i < dev_data->slot_data.size(); i++) { for (unsigned int j = 0; j < dev_data->slot_data[i]->subslot_data.size(); j++) { if (dev_data->slot_data[i]->subslot_data[j]->io_input_length > 0) { io_input_length += dev_data->slot_data[i]->subslot_data[j]->io_input_length + 1; io_iocr_input_length += 1; } if (dev_data->slot_data[i]->subslot_data[j]->io_output_length > 0) { io_output_length += dev_data->slot_data[i]->subslot_data[j]->io_output_length + 1; io_iocr_output_length += 1; } if (dev_data->slot_data[i]->subslot_data[j]->io_input_length == 0 && dev_data->slot_data[i]->subslot_data[j]->io_output_length == 0) { io_input_length += 1; io_iocr_input_length += 1; } } } PNM_APCFG_CFG_IOCR_REQ_T* iocr_config = (PNM_APCFG_CFG_IOCR_REQ_T*)calloc( 1, sizeof(*iocr_config) + sizeof(iocr_config->tData.atData)); PNM_APCFG_CFG_IOCR_CNF_T iocr_config_cnf = { { 0 } }; sscanf(dev_data->mac_address, "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx", &macaddr[0], &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], &macaddr[5]); iocr_config->tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); iocr_config->tHead.ulLen = HOST_TO_LE32( sizeof(iocr_config->tData) + sizeof(iocr_config->tData.atData)); iocr_config->tHead.ulId = HOST_TO_LE32(msg_id++); iocr_config->tHead.ulCmd = HOST_TO_LE32(PNM_APCTL_CMD_SET_CONFIG_IOD_IOCR_REQ); iocr_config->tHead.ulSrc = HOST_TO_LE32(PN_SRC); iocr_config->tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); iocr_config->tData.tSubHead.ulTrCntrId = 1; iocr_config->tData.tSubHead.ulTrDevId = device + 1; iocr_config->tData.tSubHead.ulTrApId = 0; iocr_config->tData.tSubHead.ulTrModId = 0; iocr_config->tData.tSubHead.ulTrSubModId = 0; iocr_config->tData.tSubHead.ulTrIdCnt = 2; for (int i = 0; i < 2; i++) { iocr_config->tData.atData[i].ulTrId = i + 1; iocr_config->tData.atData[i].usType = dev_data->iocr_data[i ? 0 : 1]->type; iocr_config->tData.atData[i].usVLANID = 0; iocr_config->tData.atData[i].ulProp = PNIO_API_IOCR_PROP_RTCLASS_DATA1; // strncpy( (char *)iocr_config->tData.atData[i].abMcastMACAddr, (char // *)macaddr, // sizeof(iocr_config->tData.atData[i].abMcastMACAddr)); memset((char*)iocr_config->tData.atData[i].abMcastMACAddr, 0, sizeof(iocr_config->tData.atData[i].abMcastMACAddr)); if (iocr_config->tData.atData[i].usType == 1) iocr_config->tData.atData[i].usDataLen = io_input_length + io_iocr_output_length; else iocr_config->tData.atData[i].usDataLen = io_output_length + io_iocr_input_length; iocr_config->tData.atData[i].usSendClockFact = dev_data->iocr_data[i ? 0 : 1]->send_clock_factor; iocr_config->tData.atData[i].usReductRatio = dev_data->iocr_data[i ? 0 : 1]->reduction_ratio; iocr_config->tData.atData[i].usPhase = dev_data->iocr_data[i ? 0 : 1]->phase; iocr_config->tData.atData[i].usSequ = 0; iocr_config->tData.atData[i].ulFrameSendOffs = PNIO_API_FRAME_SEND_OFFSET_DEFAULT; iocr_config->tData.atData[i].usWatchdogFact = PNIO_API_CYCLIC_WATCHDOG_DEFAULT; iocr_config->tData.atData[i].usDataHoldFact = PNIO_API_CYCLIC_DATAHOLD_DEFAULT; } sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)iocr_config, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket(local->chan, sizeof(iocr_config_cnf), (CIFX_PACKET*)&iocr_config_cnf, 20); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, iocr_config_cnf.tHead.ulCmd, PNM_APCTL_CMD_SET_CONFIG_IOD_IOCR_CNF) || !status_check(op, ap, pnm_config_cnf.tHead.ulSta, "IOCR Config")) return IO__INITFAIL; free(iocr_config); // PNM_IOD_AP PNM_APCFG_CFG_AP_REQ_T ap_config = { { 0 } }; PNM_APCFG_CFG_AP_CNF_T ap_config_cnf = { { 0 } }; ap_config.tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); ap_config.tHead.ulLen = HOST_TO_LE32(sizeof(ap_config.tData)); ap_config.tHead.ulId = HOST_TO_LE32(msg_id++); ap_config.tHead.ulCmd = HOST_TO_LE32(PNM_APCTL_CMD_SET_CONFIG_IOD_AP_REQ); ap_config.tHead.ulSrc = HOST_TO_LE32(PN_SRC); ap_config.tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); ap_config.tData.tSubHead.ulTrCntrId = 1; ap_config.tData.tSubHead.ulTrDevId = device + 1; ap_config.tData.tSubHead.ulTrApId = 0; ap_config.tData.tSubHead.ulTrModId = 0; ap_config.tData.tSubHead.ulTrSubModId = 0; ap_config.tData.tSubHead.ulTrIdCnt = 1; ap_config.tData.atData[0].ulTrId = 1; ap_config.tData.atData[0].ulAPI = 0; sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)&ap_config, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket( local->chan, sizeof(ap_config_cnf), (CIFX_PACKET*)&ap_config_cnf, 20); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, ap_config_cnf.tHead.ulCmd, PNM_APCTL_CMD_SET_CONFIG_IOD_AP_CNF) || !status_check( op, ap, ap_config_cnf.tHead.ulSta, "Application Process")) return IO__INITFAIL; // PNM_MODULE // Check number of configured slots int slots = 0; for (unsigned int i = 0; i < dev_data->slot_data.size(); i++) { if (dev_data->slot_data[i]->module_ident_number == 0) break; slots++; } PNM_APCFG_CFG_MODULE_REQ_T* module_config = (PNM_APCFG_CFG_MODULE_REQ_T*)calloc(1, sizeof(*module_config) + (slots - 1) * sizeof(module_config->tData.atData)); PNM_APCFG_CFG_MODULE_CNF_T module_config_cnf = { { 0 } }; module_config->tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); module_config->tHead.ulLen = HOST_TO_LE32(sizeof(module_config->tData) + (slots - 1) * sizeof(module_config->tData.atData)); module_config->tHead.ulId = HOST_TO_LE32(msg_id++); module_config->tHead.ulCmd = HOST_TO_LE32(PNM_APCTL_CMD_SET_CONFIG_IOD_MODULE_REQ); module_config->tHead.ulSrc = HOST_TO_LE32(PN_SRC); module_config->tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); module_config->tData.tSubHead.ulTrCntrId = 1; module_config->tData.tSubHead.ulTrDevId = device + 1; module_config->tData.tSubHead.ulTrApId = 1; module_config->tData.tSubHead.ulTrModId = 0; module_config->tData.tSubHead.ulTrSubModId = 0; module_config->tData.tSubHead.ulTrIdCnt = slots; for (int i = 0; i < slots; i++) { module_config->tData.atData[i].ulTrId = i + 1; module_config->tData.atData[i].ulModuleID = dev_data->slot_data[i]->module_ident_number; module_config->tData.atData[i].usModuleProp = 0; module_config->tData.atData[i].usSlotNumber = dev_data->slot_data[i]->slot_number; } sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)module_config, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket(local->chan, sizeof(module_config_cnf), (CIFX_PACKET*)&module_config_cnf, 20); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, module_config_cnf.tHead.ulCmd, PNM_APCTL_CMD_SET_CONFIG_IOD_MODULE_CNF) || !status_check( op, ap, module_config_cnf.tHead.ulSta, "Module Config")) return IO__INITFAIL; free(module_config); // PNM_SUBMODULE for (int i = 0; i < slots; i++) { int subslots = dev_data->slot_data[i]->subslot_data.size(); PNM_APCFG_CFG_SUBMODULE_REQ_T* submodule_config = (PNM_APCFG_CFG_SUBMODULE_REQ_T*)calloc(1, sizeof(*submodule_config) + (subslots - 1) * sizeof(submodule_config->tData.atData)); PNM_APCFG_CFG_SUBMODULE_CNF_T submodule_config_cnf = { { 0 } }; submodule_config->tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); submodule_config->tHead.ulLen = HOST_TO_LE32(sizeof(submodule_config->tData) + (subslots - 1) * sizeof(submodule_config->tData.atData)); submodule_config->tHead.ulId = HOST_TO_LE32(msg_id++); submodule_config->tHead.ulCmd = HOST_TO_LE32(PNM_APCTL_CMD_SET_CONFIG_IOD_SUBMODULE_REQ); submodule_config->tHead.ulSrc = HOST_TO_LE32(PN_SRC); submodule_config->tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); submodule_config->tData.tSubHead.ulTrCntrId = 1; submodule_config->tData.tSubHead.ulTrDevId = device + 1; submodule_config->tData.tSubHead.ulTrApId = 1; submodule_config->tData.tSubHead.ulTrModId = i + 1; submodule_config->tData.tSubHead.ulTrSubModId = 0; submodule_config->tData.tSubHead.ulTrIdCnt = subslots; for (int j = 0; j < subslots; j++) { submodule_config->tData.atData[j].ulTrId = j + 1; submodule_config->tData.atData[j].ulSubmoduleID = dev_data->slot_data[i]->subslot_data[j]->submodule_ident_number; submodule_config->tData.atData[j].usSubmoduleProp = 0; if (dev_data->slot_data[i]->subslot_data[j]->io_input_length > 0 && dev_data->slot_data[i]->subslot_data[j]->io_output_length > 0) submodule_config->tData.atData[j].usSubmoduleProp = PNIO_API_SUBM_PROP_TYPE_BOTH; else if (dev_data->slot_data[i]->subslot_data[j]->io_input_length > 0) submodule_config->tData.atData[j].usSubmoduleProp = PNIO_API_SUBM_PROP_TYPE_INPUT; else if (dev_data->slot_data[i]->subslot_data[j]->io_output_length > 0) submodule_config->tData.atData[j].usSubmoduleProp = PNIO_API_SUBM_PROP_TYPE_OUTPUT; else submodule_config->tData.atData[j].usSubmoduleProp = PNIO_API_SUBM_PROP_TYPE_NONE; submodule_config->tData.atData[j].usSubslotNumber = dev_data->slot_data[i]->subslot_data[j]->subslot_number; // printf( "Submodule %d %d\n", i+1, j+1); } sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)submodule_config, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket(local->chan, sizeof(submodule_config_cnf), (CIFX_PACKET*)&submodule_config_cnf, 20); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, submodule_config_cnf.tHead.ulCmd, PNM_APCTL_CMD_SET_CONFIG_IOD_SUBMODULE_CNF) || !status_check( op, ap, submodule_config_cnf.tHead.ulSta, "Submodule Config")) return IO__INITFAIL; free(submodule_config); } // PNM_SUBMDESCR int input_frame_offset = 0; int output_frame_offset = 0; int input_iocs_frame_offset = io_output_length; int output_iocs_frame_offset = io_input_length; for (int i = 0; i < slots; i++) { int subslots = dev_data->slot_data[i]->subslot_data.size(); int prev_slot_input_dpm_offset = input_dpm_offset; int prev_slot_output_dpm_offset = output_dpm_offset; for (int j = 0; j < subslots; j++) { int io_input_length = dev_data->slot_data[i]->subslot_data[j]->io_input_length; int io_output_length = dev_data->slot_data[i]->subslot_data[j]->io_output_length; int size = 1; if (io_input_length > 0 && io_output_length > 0) size = 2; PNM_APCFG_CFG_SUBMDESCR_REQ_T* submdescr_config = (PNM_APCFG_CFG_SUBMDESCR_REQ_T*)calloc( 1, sizeof(*submdescr_config) + (size - 1) * sizeof(submdescr_config->tData.atData)); PNM_APCFG_CFG_SUBMDESCR_CNF_T submdescr_config_cnf = { { 0 } }; submdescr_config->tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); submdescr_config->tHead.ulLen = HOST_TO_LE32(sizeof(submdescr_config->tData) + (size - 1) * sizeof(submdescr_config->tData.atData)); submdescr_config->tHead.ulId = HOST_TO_LE32(msg_id++); submdescr_config->tHead.ulCmd = HOST_TO_LE32(PNM_APCTL_CMD_SET_CONFIG_IOD_SUBMDESCR_REQ); submdescr_config->tHead.ulSrc = HOST_TO_LE32(PN_SRC); submdescr_config->tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); submdescr_config->tData.tSubHead.ulTrCntrId = 1; submdescr_config->tData.tSubHead.ulTrDevId = device + 1; submdescr_config->tData.tSubHead.ulTrApId = 1; submdescr_config->tData.tSubHead.ulTrModId = i + 1; submdescr_config->tData.tSubHead.ulTrSubModId = j + 1; submdescr_config->tData.tSubHead.ulTrIdCnt = size; for (int k = 0; k < size; k++) { submdescr_config->tData.atData[k].ulTrId = k + 1; if (io_input_length == 0 && io_output_length == 0) { submdescr_config->tData.atData[k].usDataDescr = PNIO_API_SUBMDESCR_DATA_DESCR_INPUT; submdescr_config->tData.atData[k].usSubmDataLen = 0; submdescr_config->tData.atData[k].usFrameOffs = input_frame_offset; submdescr_config->tData.atData[k].usIOCSFrameOffs = input_iocs_frame_offset; submdescr_config->tData.atData[k].ulIO_Block = 0; submdescr_config->tData.atData[k].ulDPM_Offset = 0; // printf( "%d %d None: iocsoffs %d offs %d len %d\n", i+1, j+1, // input_iocs_frame_offset, input_frame_offset, io_input_length); } else if ((size == 1 && io_input_length > 0) || (size == 2 && k == 0)) { submdescr_config->tData.atData[k].usDataDescr = PNIO_API_SUBMDESCR_DATA_DESCR_INPUT; submdescr_config->tData.atData[k].usSubmDataLen = io_input_length; submdescr_config->tData.atData[k].usFrameOffs = input_frame_offset; submdescr_config->tData.atData[k].usIOCSFrameOffs = input_iocs_frame_offset; submdescr_config->tData.atData[k].ulIO_Block = 0; submdescr_config->tData.atData[k].ulDPM_Offset = input_dpm_offset; // printf( "%d %d Input: iocsoffs %d offs %d len %d\n", i+1, j+1, // input_iocs_frame_offset, input_frame_offset, io_input_length); } else { submdescr_config->tData.atData[k].usDataDescr = PNIO_API_SUBMDESCR_DATA_DESCR_OUTPUT; submdescr_config->tData.atData[k].usSubmDataLen = io_output_length; submdescr_config->tData.atData[k].usFrameOffs = output_frame_offset; submdescr_config->tData.atData[k].usIOCSFrameOffs = output_iocs_frame_offset; submdescr_config->tData.atData[k].ulIO_Block = 0; submdescr_config->tData.atData[k].ulDPM_Offset = output_dpm_offset; // printf( "%d %d Output: iocsoffs %d offs %d len %d\n", i+1, j+1, // output_iocs_frame_offset, output_frame_offset, io_output_length); } submdescr_config->tData.atData[k].bIOPSLen = 1; submdescr_config->tData.atData[k].bIOCSLen = 1; submdescr_config->tData.atData[k].ulIOCRIdProd = 1; submdescr_config->tData.atData[k].ulIOCRIdCons = 2; submdescr_config->tData.atData[k].ulSignla_Attrib = 0; } sts = xChannelPutPacket( local->chan, (CIFX_PACKET*)submdescr_config, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket(local->chan, sizeof(submdescr_config_cnf), (CIFX_PACKET*)&submdescr_config_cnf, 20); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, submdescr_config_cnf.tHead.ulCmd, PNM_APCTL_CMD_SET_CONFIG_IOD_SUBMDESCR_CNF) || !status_check(op, ap, submdescr_config_cnf.tHead.ulSta, "Submodule Description")) return IO__INITFAIL; if (io_input_length > 0) { input_frame_offset += io_input_length + 1; input_iocs_frame_offset += 1; input_dpm_offset += io_input_length; } if (io_output_length > 0) { output_frame_offset += io_output_length + 1; output_iocs_frame_offset += 1; output_dpm_offset += io_output_length; } if (io_input_length == 0 && io_output_length == 0) { input_frame_offset += 1; input_iocs_frame_offset += 1; } free(submdescr_config); } if (i > 0) { // First slot is the device and has no card if (i == 1) cp = rp->cardlist; else cp = cp->next; if (!cp) { snprintf(op->ErrorStr, sizeof(op->ErrorStr), "Module config mismatch in xml-file, %s", rp->Name); errh_Error("IO init %s, '%s'", ap->Name, op->ErrorStr); return IO__INITFAIL; } io_sPnCardLocal* cp_local = (io_sPnCardLocal*)cp->Local; cp_local->input_area_size = input_dpm_offset - prev_slot_input_dpm_offset; cp_local->output_area_size = output_dpm_offset - prev_slot_output_dpm_offset; } prev_slot_input_dpm_offset = input_dpm_offset; prev_slot_output_dpm_offset = output_dpm_offset; } rp_local->bytes_of_input = input_dpm_offset - prev_input_dpm_offset; rp_local->bytes_of_output = output_dpm_offset - prev_output_dpm_offset; prev_input_dpm_offset = input_dpm_offset; prev_output_dpm_offset = output_dpm_offset; // PNM_RECORD for (int i = 0; i < slots; i++) { int subslots = dev_data->slot_data[i]->subslot_data.size(); for (int j = 0; j < subslots; j++) { int records = dev_data->slot_data[i]->subslot_data[j]->data_record.size(); if (!records) continue; int size = sizeof(PNM_APCFG_CFG_RECORD_REQ_T) + (records - 1) * (sizeof(PNM_APCFG_CFG_RECORD_DATA_T) - 1); for (int k = 0; k < records; k++) size += dev_data->slot_data[i] ->subslot_data[j] ->data_record[k] ->data_length; PNM_APCFG_CFG_RECORD_REQ_T* record_config = (PNM_APCFG_CFG_RECORD_REQ_T*)calloc(1, size); PNM_APCFG_CFG_RECORD_CNF_T record_config_cnf = { { 0 } }; record_config->tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); record_config->tHead.ulLen = HOST_TO_LE32(size); record_config->tHead.ulId = HOST_TO_LE32(msg_id++); record_config->tHead.ulCmd = HOST_TO_LE32(PNM_APCTL_CMD_SET_CONFIG_IOD_RECDATA_REQ); record_config->tHead.ulSrc = HOST_TO_LE32(PN_SRC); record_config->tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); record_config->tData.tSubHead.ulTrCntrId = 1; record_config->tData.tSubHead.ulTrDevId = device + 1; record_config->tData.tSubHead.ulTrApId = 1; record_config->tData.tSubHead.ulTrModId = i + 1; record_config->tData.tSubHead.ulTrSubModId = j + 1; record_config->tData.tSubHead.ulTrIdCnt = records; PNM_APCFG_CFG_RECORD_DATA_T* rp = &record_config->tData.tRecord; for (int k = 0; k < records; k++) { rp->ulTrId = k + 1; rp->usIndex = k + 1; rp->ulDataLen = dev_data->slot_data[i] ->subslot_data[j] ->data_record[k] ->data_length; memcpy(rp->abRecordData, dev_data->slot_data[i]->subslot_data[j]->data_record[k]->data, rp->ulDataLen); rp = (PNM_APCFG_CFG_RECORD_DATA_T*)((char*)rp + sizeof(*rp) + rp->ulDataLen - 1); } sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)record_config, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket(local->chan, sizeof(record_config_cnf), (CIFX_PACKET*)&record_config_cnf, 20); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, record_config_cnf.tHead.ulCmd, PNM_APCTL_CMD_SET_CONFIG_IOD_RECDATA_CNF) || !status_check( op, ap, record_config_cnf.tHead.ulSta, "Record Data")) return IO__INITFAIL; free(record_config); } } delete dev_data; ((cifx_sDeviceUserData*)rp_local->userdata)->dev_data = 0; device++; } // PNM_FIN PNM_APCFG_DWNL_FIN_REQ_T dwnl_fin_config = { { 0 } }; PNM_APCFG_DWNL_FIN_CNF_T dwnl_fin_config_cnf = { { 0 } }; dwnl_fin_config.tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); dwnl_fin_config.tHead.ulLen = 0; dwnl_fin_config.tHead.ulId = HOST_TO_LE32(msg_id++); dwnl_fin_config.tHead.ulCmd = HOST_TO_LE32(PNM_APCTL_CMD_SET_CONFIG_DWNL_FIN_REQ); dwnl_fin_config.tHead.ulSrc = HOST_TO_LE32(PN_SRC); dwnl_fin_config.tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)&dwnl_fin_config, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket(local->chan, sizeof(dwnl_fin_config_cnf), (CIFX_PACKET*)&dwnl_fin_config_cnf, 20); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, dwnl_fin_config_cnf.tHead.ulCmd, PNM_APCTL_CMD_SET_CONFIG_DWNL_FIN_CNF) || !status_check( op, ap, dwnl_fin_config_cnf.tHead.ulSta, "Controller Config")) return IO__INITFAIL; // LOCK RCX_LOCK_UNLOCK_CONFIG_REQ_T lock = { { 0 } }; RCX_LOCK_UNLOCK_CONFIG_CNF_T lock_cnf = { { 0 } }; lock.tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); lock.tHead.ulLen = HOST_TO_LE32(sizeof(lock.tData)); lock.tHead.ulCmd = HOST_TO_LE32(RCX_LOCK_UNLOCK_CONFIG_REQ); lock.tHead.ulSrc = HOST_TO_LE32(PN_SRC); lock.tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); lock.tData.ulParam = 1; // Lock sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)&lock, 10); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket( local->chan, sizeof(lock_cnf), (CIFX_PACKET*)&lock_cnf, 20); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, lock_cnf.tHead.ulCmd, RCX_LOCK_UNLOCK_CONFIG_CNF) || !status_check(op, ap, lock_cnf.tHead.ulSta, "Unlock channel")) return IO__INITFAIL; // Register application RCX_REGISTER_APP_REQ_T regapp = { { 0 } }; RCX_REGISTER_APP_CNF_T regapp_cnf = { { 0 } }; regapp.tHead.ulDest = HOST_TO_LE32(PNM_APPLICATION); regapp.tHead.ulLen = 0; regapp.tHead.ulCmd = HOST_TO_LE32(RCX_REGISTER_APP_REQ); regapp.tHead.ulSrc = HOST_TO_LE32(PN_SRC); regapp.tHead.ulSrcId = HOST_TO_LE32(PN_SRCID); sts = xChannelPutPacket(local->chan, (CIFX_PACKET*)®app, 1000); if (!status_check(op, ap, sts, "xChannelPutPacket")) return IO__INITFAIL; sts = xChannelGetPacket( local->chan, sizeof(regapp_cnf), (CIFX_PACKET*)®app_cnf, 10000); if (!status_check(op, ap, sts, "xChannelGetPacket") || !cmd_check(op, ap, regapp_cnf.tHead.ulCmd, RCX_REGISTER_APP_CNF) || !status_check(op, ap, regapp_cnf.tHead.ulSta, "Register Application")) return IO__INITFAIL; // Create input/output area local->input_area_size = input_dpm_offset; local->output_area_size = output_dpm_offset; local->input_area = calloc(1, MAX(local->input_area_size, 4)); local->output_area = calloc(1, MAX(local->output_area_size, 4)); int input_offset = 0; int output_offset = 0; for (rp = ap->racklist; rp; rp = rp->next) { io_sPnRackLocal* rp_local = (io_sPnRackLocal*)rp->Local; rp_local->inputs = (unsigned char*)local->input_area + input_offset; rp_local->outputs = (unsigned char*)local->output_area + output_offset; int slot_input_offset = input_offset; int slot_output_offset = output_offset; for (cp = rp->cardlist; cp; cp = cp->next) { io_sPnCardLocal* cp_local = (io_sPnCardLocal*)cp->Local; cp_local->input_area = (unsigned char*)local->input_area + slot_input_offset; cp_local->output_area = (unsigned char*)local->output_area + slot_output_offset; slot_input_offset += cp_local->input_area_size; slot_output_offset += cp_local->output_area_size; } input_offset += rp_local->bytes_of_input; output_offset += rp_local->bytes_of_output; // Set OK status on device ((pwr_sClass_PnDevice*)rp->op)->Status = PB__NORMAL; ((pwr_sClass_PnDevice*)rp->op)->State = pwr_ePnDeviceStateEnum_Connected; } for (;;) { sts = xChannelHostState(local->chan, CIFX_HOST_STATE_READY, &state, 100); if (sts != CIFX_DEV_NOT_RUNNING) break; sleep(1); } sts = xChannelHostState(local->chan, CIFX_HOST_STATE_READ, &state, 0); // printf( "Host state: %d\n", state); sts = xChannelBusState(local->chan, CIFX_BUS_STATE_GETSTATE, &state, 0); // printf( "Bus state: %d\n", state); sts = xChannelBusState( local->chan, CIFX_BUS_STATE_ON, &state, 5000 /* 20000 */); // printf( "Set bus state: 0x%08x\n", sts); sts = xChannelBusState(local->chan, CIFX_BUS_STATE_GETSTATE, &state, 0); // printf( "Bus state: %d\n", state); // It takes ~20 s to get COM-flag local->dev_init = 1; local->dev_init_limit = (unsigned int)(30.0 / ctx->ScanTime + 0.5); errh_Info("Init of Hilscher cifX Profinet Controller '%s'", ap->Name); return IO__SUCCESS; }
void irAlLabel(t_nombre_etiqueta etiqueta) { if(status_check() != EXECUTING) return; actual_pcb->program_counter = metadata_buscar_etiqueta(etiqueta, actual_pcb->etiquetas, (size_t) actual_pcb->etiquetas_size) - 1; }
t_posicion definirVariable(t_nombre_variable variable) { if(status_check() != EXECUTING) return ERROR; //1) Obtener el stack index actual t_stack* actual_stack_index = actual_pcb->stack_index; //2) Obtengo la primera posicion libre del stack t_posicion actual_stack_pointer = (t_posicion) actual_pcb->stack_pointer; //3) Armamos la logical address requerida logical_addr* direccion_espectante = armar_direccion_logica_variable(actual_stack_pointer, setup->PAGE_SIZE); int valor = 0; t_list * pedidos = NULL; //TODO: CAMBIAR ESTO PARA QUE LA LISTA DE PEDIDOS SEA DE NUMEROS, NO DE SPRINTF obtener_lista_operaciones_escritura(&pedidos, actual_stack_pointer, ANSISOP_VAR_SIZE, valor); int index = 0; t_nodo_send * nodo = NULL; char * umc_response_buffer = calloc(1, sizeof(char)); if(umc_response_buffer == NULL) { log_error(cpu_log, "definirVariable umc_response_buffer mem alloc failed"); return ERROR; } char operation; int page, offset, size, print_index = 0; while (list_size(pedidos) > 0) { nodo = list_remove(pedidos, index); deserialize_data(&operation, sizeof(char), nodo->data, &print_index); deserialize_data(&page, sizeof(int), nodo->data, &print_index); deserialize_data(&offset, sizeof(int), nodo->data, &print_index); deserialize_data(&size, sizeof(int), nodo->data, &print_index); log_info(cpu_log, "Sending request op:%c (%d,%d,%d) to define variable '%c' with value %d", operation, page, offset, size, variable, valor); if( send(umcSocketClient, nodo->data , (size_t ) nodo->data_length, 0) < 0) { log_error(cpu_log, "UMC expected addr send failed"); return ERROR; } if(check_umc_response(recv_umc_response_status()) != SUCCESS) { return ERROR; } } list_destroy(pedidos); //Liberamos la estructura de lista reservada free(umc_response_buffer); //5) Si esta bien, agregamos la nueva t_var al stack t_var * nueva_variable = calloc(1, sizeof(t_var)); nueva_variable->var_id = variable; nueva_variable->page_number = direccion_espectante->page_number; nueva_variable->offset = direccion_espectante->offset; nueva_variable->tamanio = direccion_espectante->tamanio; //6) Actualizo el stack pointer actual_pcb->stack_pointer += nueva_variable->tamanio; free(direccion_espectante); t_stack_entry *last_entry = get_last_entry(actual_stack_index); add_var( &last_entry, nueva_variable); //7) y retornamos la t_posicion asociada t_posicion posicion_nueva_variable = get_t_posicion(nueva_variable); return posicion_nueva_variable; }