// ----------------------------------------------------------------------- struct cmem_unit_proto_t * cmem_m9425_create(struct cfg_arg *args) { char *image_name[2] = { NULL, NULL }; struct cmem_unit_m9425_t *unit = calloc(1, sizeof(struct cmem_unit_m9425_t)); int res; if (!unit) { goto fail; } if ((image_name[0] || image_name[1]) && !strcmp(image_name[0], image_name[1])) { fprintf(stderr, "Error opening image: Trying to use the same image for fixed and removable disk"); res = E_IMAGE; goto fail; } res = cfg_args_decode(args, "ss", &image_name[0], &image_name[1]); if (res != E_OK) { gerr = res; goto fail; } for (int i=0 ; i<=1 ; i++) { UNIT->disk[i] = e4i_open(image_name[i]); if (!UNIT->disk[i]) { fprintf(stderr, "Error opening image %s: %s\n", image_name[i], e4i_get_err(e4i_err)); res = E_IMAGE; goto fail; } if (UNIT->disk[i]->img_type != E4I_T_HDD) { fprintf(stderr, "Error opening image %s: wrong image type, expecting hdd\n", image_name[i]); res = E_IMAGE; goto fail; } if ((UNIT->disk[i]->cylinders != 203) || (UNIT->disk[i]->heads != 2) || (UNIT->disk[i]->spt != 12) || (UNIT->disk[i]->block_size != 512)) { fprintf(stderr, "Error opening image %s: wrong geometry\n", image_name[i]); res = E_IMAGE; goto fail; } LOG(L_9425, 1, "MERA 9425 (plate %i): cyl=%i, head=%i, sectors=%i, spt=%i, image=%s", i, UNIT->disk[i]->cylinders, UNIT->disk[i]->heads, UNIT->disk[i]->spt, UNIT->disk[i]->block_size, image_name[i]); free(image_name[i]); image_name[i] = NULL; } res = pthread_create(&unit->worker, NULL, cmem_m9425_worker, (void*) unit); if (res != 0) { gerr = E_THREAD; goto fail; } return (struct cmem_unit_proto_t *) unit; fail: for (int i=0 ; i<=1 ; i++) { free(image_name[i]); } cmem_m9425_shutdown((struct cmem_unit_proto_t*) unit); return NULL; }
// ----------------------------------------------------------------------- struct cchar_unit_proto_t * cchar_term_create(struct cfg_arg_t *args) { char *type = NULL; int port; int res; struct cchar_unit_term_t *unit = calloc(1, sizeof(struct cchar_unit_term_t)); if (!unit) { goto fail; } res = cfg_args_decode(args, "s", &type); if (res != E_OK) { gerr = res; goto fail; } if (!strcasecmp(type, "tcp")) { res = cfg_args_decode(args, "si", &type, &port); if (res != E_OK) { gerr = res; goto fail; } unit->term = term_open_tcp(port, 100); if (!unit->term) { gerr = E_TERM; goto fail; } } else if (!strcasecmp(type, "console")) { if (em400_console == CONSOLE_DEBUGGER) { gerr = E_TERM_CONSOLE_DEBUG; goto fail; } else if (em400_console == CONSOLE_TERMINAL) { gerr = E_TERM_CONSOLE_TERM; goto fail; } else { em400_console = CONSOLE_TERMINAL; unit->term = term_open_console(); if (!unit->term) { gerr = E_TERM; goto fail; } } printf("Console connected as system terminal.\n"); } else { gerr = E_TERM_UNKNOWN; goto fail; } unit->buf = malloc(TERM_BUF_LEN); if (!unit->buf) { goto fail; } eprint(" Terminal (%s), port: %i\n", type, port); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutex_init(&unit->buf_mutex, &attr); res = pthread_create(&unit->worker, NULL, cchar_term_worker, (void *)unit); if (res != 0) { goto fail; } return (struct cchar_unit_proto_t *) unit; fail: cchar_term_shutdown((struct cchar_unit_proto_t*) unit); return NULL; }
// ----------------------------------------------------------------------- void * dev_terminal_create(struct cfg_arg *args) { int res; char *type = NULL; int port; struct dev_terminal *terminal = (struct dev_terminal *) malloc(sizeof(struct dev_terminal)); if (!terminal) { goto cleanup; } res = cfg_args_decode(args, "s", &type); if (res != E_OK) { LOGERR("Failed to parse terminal type: \"%s\".", args->text); goto cleanup; } if (!strcasecmp(type, "tcp")) { res = cfg_args_decode(args->next, "i", &port); if (res != E_OK) { LOGERR("Failed to parse terminal TCP port: \"%s\".", args->next->text); goto cleanup; } if (dev_terminal_open_tcp(terminal, port, 100)) { LOGERR("Failed to open TCP terminal on port: %i.", port); goto cleanup; } } else if (!strcasecmp(type, "console")) { if (dev_terminal_open_console(terminal)) { LOGERR("Failed to open console terminal."); goto cleanup; } } else { LOGERR("Unknown terminal type: %s.", type); goto cleanup; } terminal->cmd = CMD_NONE; if (pthread_mutex_init(&terminal->cmd_mutex, NULL)) { LOGERR("Failed to initialize terminal mutex."); goto cleanup; } if (pthread_cond_init(&terminal->cmd_cond, NULL)) { LOGERR("Failed to initialize terminal cmd conditional."); goto cleanup; } if (pthread_create(&terminal->th, NULL, dev_terminal_controller, terminal)) { LOGERR("Failed to spawn terminal thread."); goto cleanup; } pthread_setname_np(terminal->th, "term"); free(type); return terminal; cleanup: dev_terminal_destroy(terminal); free(type); return NULL; }
// ----------------------------------------------------------------------- struct cchar_unit_proto_t * cchar_term_create(struct cfg_arg *args) { char *type = NULL; int port; int res; char *device = NULL; int speed; struct cchar_unit_term_t *unit = (struct cchar_unit_term_t *) calloc(1, sizeof(struct cchar_unit_term_t)); if (!unit) { LOGERR("Failed to allocate memory for unit: %s.", args->text); goto fail; } res = cfg_args_decode(args, "s", &type); if (res != E_OK) { LOGERR("Failed to parse terminal type: \"%s\".", args->text); goto fail; } if (!strcasecmp(type, "tcp")) { res = cfg_args_decode(args->next, "i", &port); if (res != E_OK) { LOGERR("Failed to parse terminal TCP port: \"%s\".", args->next->text); goto fail; } unit->term = term_open_tcp(port, 100); if (!unit->term) { LOGERR("Failed to open TCP terminal on port %i.", port); goto fail; } } else if (!strcasecmp(type, "serial")) { res = cfg_args_decode(args->next, "s", &device); if (res != E_OK) { LOGERR("Failed to parse terminal serial device: \"%s\".", args->next->text); goto fail; } res = cfg_args_decode(args->next->next, "i", &speed); if (res != E_OK) { LOGERR("Failed to parse terminal serial speed: \"%i\".", args->next->next->text); goto fail; } unit->term = term_open_serial(device, speed, 100); if (!unit->term) { LOGERR("Failed to open serial terminal at %s, speed: %i).", device, speed); goto fail; } } else if (!strcasecmp(type, "console")) { if (em400_console == CONSOLE_DEBUGGER) { LOGERR("Failed to initialize console terminal; console is being used by the debugger."); goto fail; } else if (em400_console == CONSOLE_TERMINAL) { LOGERR("Failed to initialize console terminal; console is being used by another terminal."); goto fail; } else { em400_console = CONSOLE_TERMINAL; unit->term = term_open_console(); if (!unit->term) { LOGERR("Failed to initialize console."); goto fail; } } fprintf(stderr, "Console connected as system terminal.\n"); } else { LOGERR("Unknown terminal type: %s.", type); goto fail; } unit->buf = (char *) malloc(TERM_BUF_LEN); if (!unit->buf) { LOGERR("Failed to allocate memory for terminal buffer."); goto fail; } LOG(L_TERM, "Terminal (%s), port: %i", type, port); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutex_init(&unit->buf_mutex, &attr); res = pthread_create(&unit->worker, NULL, cchar_term_worker, (void *)unit); if (res != 0) { LOGERR("Failed to spawn terminal thread."); goto fail; } pthread_setname_np(unit->worker, "term"); free(type); return (struct cchar_unit_proto_t *) unit; fail: free(type); cchar_term_shutdown((struct cchar_unit_proto_t*) unit); return NULL; }