Exemplo n.º 1
0
static int Open(DC_ProcedureCtx *ctx) {
    int r;
    int open_flags;
    ReadPriv *priv = ctx->priv;

    // Setting context
    if (!strcmp(priv->api_str, "ata"))
        priv->api = Api_eAta;
    else if (!strcmp(priv->api_str, "posix"))
        priv->api = Api_ePosix;
    else
        return 1;
    if (priv->api == Api_eAta && !ctx->dev->ata_capable)
        return 1;
    ctx->blk_size = BLK_SIZE;
    priv->current_lba = priv->start_lba;
    priv->end_lba = ctx->dev->capacity / 512;
    priv->lba_to_process = priv->end_lba - priv->start_lba;
    if (priv->lba_to_process <= 0)
        return 1;
    ctx->progress.den = priv->lba_to_process / SECTORS_AT_ONCE;
    if (priv->lba_to_process % SECTORS_AT_ONCE)
        ctx->progress.den++;

    if (priv->api == Api_eAta) {
        open_flags = O_RDWR;
    } else {
        r = posix_memalign(&priv->buf, sysconf(_SC_PAGESIZE), ctx->blk_size);
        if (r)
            return 1;

        open_flags = O_RDONLY | O_DIRECT | O_LARGEFILE | O_NOATIME;
    }

    priv->fd = open(ctx->dev->dev_path, open_flags);
    if (priv->fd == -1) {
        dc_log(DC_LOG_FATAL, "open %s fail\n", ctx->dev->dev_path);
        return 1;
    }

    lseek(priv->fd, 512 * priv->start_lba, SEEK_SET);
    r = ioctl(priv->fd, BLKFLSBUF, NULL);
    if (r == -1)
      dc_log(DC_LOG_WARNING, "Flushing block device buffers failed\n");
    r = ioctl(priv->fd, BLKRAGET, &priv->old_readahead);
    if (r == -1)
      dc_log(DC_LOG_WARNING, "Getting block device readahead setting failed\n");
    r = ioctl(priv->fd, BLKRASET, 0);
    if (r == -1)
      dc_log(DC_LOG_WARNING, "Disabling block device readahead setting failed\n");

    return 0;
}
Exemplo n.º 2
0
void debug_console::init()
{
        initscr();
	start_color();
        keypad(stdscr, TRUE);
        intrflush(stdscr, FALSE);
        noecho();
        nonl();
        refresh();
        nodelay(stdscr, FALSE);
        meta(stdscr, TRUE);     /* enable 8-bit input */
        idlok(stdscr, TRUE);    /* may give a little clunky screenredraw */
        idcok(stdscr, TRUE);    /* may give a little clunky screenredraw */
        leaveok(stdscr, FALSE);

	init_pair(C_WHITE, COLOR_WHITE, COLOR_BLACK);
	init_pair(C_CYAN, COLOR_CYAN, COLOR_BLACK);
	init_pair(C_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
	init_pair(C_BLUE, COLOR_BLUE, COLOR_BLACK);
	init_pair(C_YELLOW, COLOR_YELLOW, COLOR_BLACK);
	init_pair(C_GREEN, COLOR_GREEN, COLOR_BLACK);
	init_pair(C_RED, COLOR_RED, COLOR_BLACK);

	recreate_terminal();

	dc_log("Calibrating...");
	wnoutrefresh(win_logs);
	doupdate();

	nc = true;
}
Exemplo n.º 3
0
static void Close(DC_ProcedureCtx *ctx) {
    ReadPriv *priv = ctx->priv;
    int r = ioctl(priv->fd, BLKRASET, priv->old_readahead);
    if (r == -1)
      dc_log(DC_LOG_WARNING, "Restoring block device readahead setting failed\n");
    free(priv->buf);
    close(priv->fd);
}
Exemplo n.º 4
0
static int Open(DC_ProcedureCtx *ctx) {
    HpaSetPriv *priv = ctx->priv;

    dc_dev_set_max_lba(ctx->dev->dev_path, ctx->dev->native_capacity / 512 - 1);
    int ret = dc_dev_set_max_lba(ctx->dev->dev_path, priv->max_lba);
    if (ret)
        dc_log(DC_LOG_ERROR, "Command SET MAX ADDRESS EXT failed");
    return 0;
}
Exemplo n.º 5
0
int dc_init(void) {
    int r;
    DC_Ctx *ctx = calloc(1, sizeof(*ctx));
    if (!ctx)
        return 1;
    dc_ctx_global = ctx;

    dc_log_set_callback(dc_log_default_func, NULL);
    dc_log_set_level(DC_LOG_INFO);

    struct timespec dummy;
#ifdef CLOCK_MONOTONIC_RAW
    /* determine best available clock */
    DC_BEST_CLOCK = CLOCK_MONOTONIC_RAW;
    r = clock_gettime(DC_BEST_CLOCK, &dummy);
    if (r) {
        dc_log(DC_LOG_WARNING, "CLOCK_MONOTONIC_RAW unavailable, using CLOCK_MONOTONIC\n");
        DC_BEST_CLOCK = CLOCK_MONOTONIC;
    }
#else
    DC_BEST_CLOCK = CLOCK_MONOTONIC;
#endif
    r = clock_gettime(DC_BEST_CLOCK, &dummy);
    if (r) {
        dc_log(DC_LOG_ERROR, "Monotonic POSIX clock unavailable\n");
        return 1;
    }

    dc_realtime_scheduling_enable_with_prio(0);

#define PROCEDURE_REGISTER(x) { \
        extern DC_Procedure x; \
        dc_procedure_register(&x); }
    PROCEDURE_REGISTER(hpa_set);
    PROCEDURE_REGISTER(posix_write_zeros);
    PROCEDURE_REGISTER(copy);
    PROCEDURE_REGISTER(read_test);
    PROCEDURE_REGISTER(smart_show);
#undef PROCEDURE_REGISTER
    return 0;
}
Exemplo n.º 6
0
        void
        Splitter::load (const SettingFile& file)
        {
            Droplet::load(file);

            // 部品となる Droplet の情報を読み込む
            std::list<std::string> name_list = file.get_string_list(get_name(), "Parts");
            std::list<std::string>::iterator it;
            for( it = name_list.begin(); it != name_list.end(); ++it )
            {
                dc_log("物体 '%s'('Droplet') を 'Splitter' の部品として構築します", it->c_str());

                Droplet *dp = new Droplet (get_manager());
                dp->set_name(*it); // オブジェクト名を設定する
                dp->load(file); // データを読み込む

                add(dp);
            }
        }
Exemplo n.º 7
0
static void dev_modelname_fill(DC_Dev *dev) {
    // fill model name, if exists
    char *model_file_name;
    int ret;
    ret = asprintf(&model_file_name, "/sys/block/%s/device/model", dev->dev_fs_name);
    assert(ret != -1 && model_file_name);

    FILE *model_file = fopen(model_file_name, "r");
    free(model_file_name);
    if (!model_file)
        return;
    char model[256];
    int r;
    r = fscanf(model_file, "%256[^\n]", model);
    if (r != 1) {
        dc_log(DC_LOG_ERROR, "Outrageous error at scanning model name\n");
        return;
    }
    dev->model_str = strdup(model);
    assert(dev->model_str);
}
Exemplo n.º 8
0
/*
 * try all things in /proc/partitions that look like a full disk
 * Taken from util-linux-2.19.1/fdisk/fdisk.c tryprocpt()
 */
static void dev_list_build(DC_DevList *dc_devlist) {

    int is_whole_disk(const char *name) {
        // taken from util-linux-2.19.1/lib/wholedisk.c
        while (*name)
            name++;
        return !isdigit(name[-1]);
    }

	FILE *procpt;
	char line[128], ptname[128];
	int ma, mi;
	unsigned long long sz;
	int ret;

	procpt = fopen("/proc/partitions", "r");
	if (procpt == NULL) {
		dc_log(DC_LOG_FATAL, "cannot open /proc/partitions\n");
		return;
	}

	while (fgets(line, sizeof(line), procpt)) {
		if (sscanf (line, " %d %d %llu %128[^\n ]",
			    &ma, &mi, &sz, ptname) != 4)
			continue;
		if (is_whole_disk(ptname)) {
            DC_Dev *dc_dev = calloc(1, sizeof(*dc_dev));
            assert(dc_dev);
            dc_dev->dev_fs_name = strdup(ptname);
            assert(dc_dev->dev_fs_name);
            ret = asprintf(&dc_dev->dev_path, "/dev/%s", ptname);
            assert(ret != -1 && dc_dev->dev_path);
            dc_dev->capacity = sz * 1024;
            dc_dev->next = dc_devlist->arr;
            dc_devlist->arr = dc_dev;
            dc_devlist->arr_size++;
		}
	}
	fclose(procpt);
}
Exemplo n.º 9
0
int datacore_prio (const char *dev, int sg_fd, char * args)
{
	int k;
	char vendor[8];
	char product[32];
	char luname[32];
	char wwpn[32];
	char sdsname[32];
	unsigned char inqCmdBlk[INQ_CMD_LEN] = { INQ_CMD_CODE, 0, 0, 0, INQ_REPLY_LEN, 0 };
	unsigned char inqBuff[INQ_REPLY_LEN];
	unsigned char *inqBuffp = inqBuff;
	unsigned char sense_buffer[32];
	sg_io_hdr_t io_hdr;

	int timeout = 2000;
	char preferredsds_buff[255] = "";
	char * preferredsds = &preferredsds_buff[0];

	if (!args) {
		dc_log(0, "need prio_args with preferredsds set");
		return 0;
	}

	if (sscanf(args, "timeout=%i preferredsds=%s",
		   &timeout, preferredsds) == 2) {}
	else if (sscanf(args, "preferredsds=%s timeout=%i",
			preferredsds, &timeout) == 2) {}
	else if (sscanf(args, "preferredsds=%s",
			preferredsds) == 1) {}
	else {
		dc_log(0, "unexpected prio_args format");
		return 0;
	}

	// on error just return prio 0
	if (strlen(preferredsds) <= 1) {
		dc_log(0, "prio args: preferredsds too short (1 character min)");
		return 0;
	}
	if ((timeout < 500) || (timeout > 20000)) {
		dc_log(0, "prio args: timeout out of bounds [500:20000]");
		return 0;
	}
	if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000))
		return 0;

	memset (&io_hdr, 0, sizeof (sg_io_hdr_t));
	io_hdr.interface_id = 'S';
	io_hdr.cmd_len = sizeof (inqCmdBlk);
	io_hdr.mx_sb_len = sizeof (sense_buffer);
	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
	io_hdr.dxfer_len = INQ_REPLY_LEN;
	io_hdr.dxferp = inqBuff;
	io_hdr.cmdp = inqCmdBlk;
	io_hdr.sbp = sense_buffer;
	io_hdr.timeout = timeout;

	// on error just return prio 0
	if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
		return 0;
	if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
		return 0;

	snprintf(vendor, 8, "%.8s\n", inqBuffp + 8);
	snprintf(product, 17, "%.16s", inqBuffp + 16);
	snprintf(luname, 21, "%.19s", inqBuffp + 36);
	snprintf(wwpn, 17, "%.16s", inqBuffp + 96);
	snprintf(sdsname, 17, "%.16s", inqBuffp + 112);

	if (strstr(sdsname , preferredsds))
		return 1;
	return 0;
}
Exemplo n.º 10
0
Arquivo: main.c Projeto: fillods/whdd
int main() {
    int r;
    r = global_init();
    if (r) {
        fprintf(stderr, "init fail\n");
        return r;
    }
    // get list of devices
    DC_DevList *devlist = dc_dev_list();
    assert(devlist);

    while (1) {
        // draw menu of device choice
        DC_Dev *chosen_dev = menu_choose_device(devlist);
        if (!chosen_dev) {
            break;
        }
        // draw procedures menu
        DC_Procedure *act = menu_choose_procedure(chosen_dev);
        if (!act)
            continue;
        if (act->flags & DC_PROC_FLAG_INVASIVE) {
            char *ask;
            r = asprintf(&ask, "This operation is invasive, i.e. it may make your data unreachable or even destroy it completely. Are you sure you want to proceed it on %s (%s)?",
                    chosen_dev->dev_fs_name, chosen_dev->model_str);
            assert(r != -1);
            dialog_vars.default_button = 1;  // Focus on "No"
            r = dialog_yesno("Confirmation", ask, 0, 0);
            // Yes = 0 (FALSE), No = 1, Escape = -1
            free(ask);
            if (/* No */ r)
                continue;
            if (chosen_dev->mounted) {
                dialog_vars.default_button = 1;  // Focus on "No"
                r = dialog_yesno("Confirmation", "This disk is mounted. Are you really sure you want to proceed?", 0, 0);
                if (r)
                    continue;
            }
        }
        DC_OptionSetting *option_set = calloc(act->options_num + 1, sizeof(DC_OptionSetting));
        int i;
        r = 0;
        for (i = 0; i < act->options_num; i++) {
            option_set[i].name = act->options[i].name;
            r = act->suggest_default_value(chosen_dev, &option_set[i]);
            if (r) {
                dc_log(DC_LOG_ERROR, "Failed to get default value suggestion on '%s'", option_set[i].name);
                break;
            }
            r = ask_option_value(act, &option_set[i], &act->options[i]);
            if (r)
                break;
        }
        if (r)
            continue;
        // Show relaxing banner when copying with journal. Copy journal processing takes some time.
        if (!strcmp(act->name, "copy")) {
            int uses_journal = 0;
            for (i = 0; i < act->options_num; i++) {
                if (!strcmp(option_set[i].name, "use_journal")) {
                    uses_journal = 1;
                    break;
                }
            }
            if (uses_journal)
                dialog_msgbox("Info", "Please wait while operation journal is processed", 0, 0, 0 /* non-pausing */);
        }
        DC_ProcedureCtx *actctx;
        r = dc_procedure_open(act, chosen_dev, &actctx, option_set);
        if (r) {
            dialog_msgbox("Error", "Procedure init fail", 0, 0, 1);
            continue;
        }
        if (!act->perform)
            continue;
        DC_Renderer *renderer;
        if (!strcmp(act->name, "copy"))
            renderer = dc_find_renderer("whole_space");
        else
            renderer = dc_find_renderer("sliding_window");
        render_procedure(actctx, renderer);
    } // while(1)

    return 0;
}
Exemplo n.º 11
0
//
// name: inet_prio
// @param
// @return prio
int iet_prio(const char *dev, char * args)
{
	char preferredip_buff[255] = "";
	char *preferredip = &preferredip_buff[0];
	// Phase 1 : checks. If anyone fails, return prio 0.
	// check if args exists
	if (!args) {
		dc_log(0, "need prio_args with preferredip set");
		return 0;
	}
	// check if args format is OK
	if (sscanf(args, "preferredip=%s", preferredip) ==1) {}
	else {
		dc_log(0, "unexpected prio_args format");
		return 0;
	}
	// check if ip is not too short
	if (strlen(preferredip) <= 7) {
		dc_log(0, "prio args: preferredip too short");
		return 0;
	}
	// Phase 2 : find device in /dev/disk/by-path to match device/ip
	DIR           *dir_p;
	struct dirent *dir_entry_p;
	enum { BUFFERSIZE = 1024 };
	char buffer[BUFFERSIZE];
	char fullpath[BUFFERSIZE] = "/dev/disk/by-path/";
	dir_p = opendir(fullpath);

	// loop to find device in /dev/disk/by-path
	while( NULL != (dir_entry_p = readdir(dir_p))) {
		if (dir_entry_p->d_name[0] != '.') {
			char path[BUFFERSIZE] = "/dev/disk/by-path/";
			strcat(path,dir_entry_p->d_name);
			ssize_t nchars = readlink(path, buffer, sizeof(buffer)-1);
			if (nchars != -1) {
				char *device;
				buffer[nchars] = '\0';
				device = find_regex(buffer,"(sd[a-z]+)");
				// if device parsed is the right one
				if (device!=NULL && strncmp(device, dev, strlen(device)) == 0) {
					char *ip;
					ip = find_regex(dir_entry_p->d_name,"([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})");
					// if prefferedip and ip fetched matches
					if (ip!=NULL && strncmp(ip, preferredip, strlen(ip)) == 0) {
						// high prio
						free(ip);
						free(device);
						closedir(dir_p);
						return 20;
					}
					free(ip);
				}
				free(device);
			}
			else {
				printf("error\n");
			}
		}
	}
	// nothing found, low prio
	closedir(dir_p);
	return 10;
}
Exemplo n.º 12
0
Arquivo: main.c Projeto: Baltix/whdd
int main() {
    printf(WHDD_ABOUT);
    printf("\nATTENTION! whdd-cli utility is purposed for development debugging, and as a fallback if whdd utility somehow fails to work. In other cases, consider using whdd utility, which should provide better usage experience.\n");
    int r;
    char *char_ret;
    // init libdevcheck
    r = dc_init();
    assert(!r);
    // get list of devices
    DC_DevList *devlist = dc_dev_list();
    assert(devlist);
    // show list of devices
    if (dc_dev_list_size(devlist) == 0) {
        printf("No devices found, go buy some :)\n");
        return 0;
    }

    while (1) {
        DC_Dev *chosen_dev = request_and_get_device();
        if (!chosen_dev) {
            printf("Invalid choice\n");
            break;
        }
        DC_Procedure *act = request_and_get_cli_action();
        if (!act)
            break;
        printf("Going to perform test %s (%s)\n", act->name, act->display_name);
        if (act->flags & DC_PROC_FLAG_INVASIVE) {
            printf("This operation is invasive, i.e. it may make your data unreachable or even destroy it completely. Are you sure you want to proceed it on %s (%s)? (y/n)\n",
                    chosen_dev->dev_fs_name, chosen_dev->model_str);
            char ans[10] = "n";
            char_ret = fgets(ans, sizeof(ans), stdin);
            if (!char_ret || ans[0] != 'y')
                continue;

            if (chosen_dev->mounted) {
                printf("This disk is mounted. Are you really sure you want to proceed? (y/n)");
                char_ret = fgets(ans, sizeof(ans), stdin);
                if (!char_ret || ans[0] != 'y')
                    continue;
            }
        }
        DC_OptionSetting *option_set = calloc(act->options_num + 1, sizeof(DC_OptionSetting));
        int i;
        r = 0;
        for (i = 0; i < act->options_num; i++) {
            option_set[i].name = act->options[i].name;
            r = act->suggest_default_value(chosen_dev, &option_set[i]);
            if (r) {
                dc_log(DC_LOG_ERROR, "Failed to get default value suggestion on '%s'", option_set[i].name);
                break;
            }
            r = ask_option_value(&option_set[i], &act->options[i]);
            if (r)
                break;
        }
        if (r)
            continue;
        DC_ProcedureCtx *actctx;
        r = dc_procedure_open(act, chosen_dev, &actctx, option_set);
        if (r) {
            printf("Procedure init fail\n");
            continue;
        }
        if (!act->perform)
            continue;
        printf("Performing on device %s with block size %"PRId64"\n",
                chosen_dev->dev_path, actctx->blk_size);
        procedure_perform_until_interrupt(actctx, proc_render_cb, NULL);
    } // while(1)

    return 0;
}
Exemplo n.º 13
0
void debug_console::tick(processor *p)
{
	n_ticks++;

	if (!refresh_limit_valid)
	{
		double now_ts = get_ts();
		double t_diff = now_ts - start_ts;

		// first second: ignore as the cpu might need to come out of
		// reduced clock frequency (linux: "ondemand" scaling governor)
		if (t_diff >= 1.0)
			refresh_limit++;

		if (t_diff >= 1.0 + 1.0 / double(SCREEN_REFRESHES_PER_SECOND))
		{
			dc_log("Refresh screen every %d instructions", refresh_limit);
			refresh_limit_valid = true;
		}
	}

	uint64_t PC = p -> is_delay_slot() ? p -> get_delay_slot_PC() : p -> get_PC();

	uint32_t instruction = -1;
	bool r_ok = true;
	try
	{
		p -> get_mem_32b(PC, &instruction);
	}
	catch(processor_exception & pe)
	{
		dc_log("EXCEPTION %d at/for %016llx, PC: %016llx (3), sr: %08x", pe.get_cause(), pe.get_BadVAddr(), pe.get_EPC(), pe.get_status());

		r_ok = false;
	}

	std::string logline = p -> da_logline(instruction);
	dolog(logline.c_str());

	std::string decoded = p -> decode_to_text(instruction);

#ifdef _DEBUG
	unsigned int space = decoded.find(' ');
	if (space == std::string::npos)
		space = decoded.length();

	std::string instruction_name = decoded.substr(0, space);

	std::map<std::string, long int>::iterator found = instruction_counts.find(instruction_name);

	if (found != instruction_counts.end())
		found -> second++;
	else
		instruction_counts.insert(std::pair<std::string, long int>(instruction_name, 1));
#endif

	if ((++refresh_counter >= refresh_limit && refresh_limit_valid == true) || single_step)
	{
		double now_ts = get_ts();

		if (term_change)
			recreate_terminal();

		int x = -1, y = -1;
		for(int registers=0; registers<32; registers++)
		{
			if (registers < 16)
			{
				x = 0;
				y = registers;
			}
			else
			{
				x = 22;
				y = registers - 16;
			}

			mvwprintw(win_regs, y, x, "%s %016llx", registers == 0 ? "0  " : processor::reg_to_name(registers), p -> get_register_64b_unsigned(registers));
		}

		mvwprintw(win_regs, 0, 44, "PC: %016llx %c", PC, p -> is_delay_slot() ? 'D' : '.');
		mvwprintw(win_regs, 1, 44, "LO: %016llx", p -> get_LO());
		mvwprintw(win_regs, 2, 44, "HI: %016llx", p -> get_HI());
		mvwprintw(win_regs, 3, 44, "SR: %016llx", p -> get_SR());

		mvwprintw(win_regs, 4, 44, "mem: %d/%08x", r_ok, instruction);

		int opcode = (instruction >> 26) & MASK_6B;
		int function = instruction & MASK_6B;
		int sa = processor::get_SA(instruction);
		int rd = processor::get_RD(instruction);
		int rt = processor::get_RT(instruction);
		int rs = processor::get_RS(instruction);
		int immediate = processor::get_immediate(instruction);
		int b18_signed_offset = processor::get_SB18(instruction);
		mvwprintw(win_regs,  5, 44, "op: %02x  rs: %02x", opcode, rs);
		mvwprintw(win_regs,  6, 44, "rt: %02x  rd: %02x", rt, rd);
		mvwprintw(win_regs,  7, 44, "sa: %02x  fu: %02d", sa, function);
		mvwprintw(win_regs,  8, 44, "im: %04x  of: %d", immediate, b18_signed_offset);

		mvwprintw(win_regs,  9, 44, ">                       ");
		mvwprintw(win_regs,  9, 44, "> %s", decoded.c_str());

		double t_diff = now_ts - start_ts;
		if (t_diff)
		{
			double i_per_s = double(n_ticks) / t_diff;

			if (i_per_s >= 1000000000.0)
				mvwprintw(win_regs, 10, 44, "I/S: %6.2fG", i_per_s / 1000000000.0);
			else if (i_per_s >= 1000000.0)
				mvwprintw(win_regs, 10, 44, "I/S: %6.2fM", i_per_s / 1000000.0);
			else if (i_per_s >= 1000.0)
				mvwprintw(win_regs, 10, 44, "I/S: %6.2fk", i_per_s / 1000.0);
			else
				mvwprintw(win_regs, 10, 44, "I/S: %6.2f", i_per_s);
		}

		if (n_ticks >= 1000000000)
			mvwprintw(win_regs, 11, 44, "cnt: %7.2fG", double(n_ticks) / 1000000000.0);
		else if (n_ticks >= 1000000)
			mvwprintw(win_regs, 11, 44, "cnt: %7.2fM", double(n_ticks) / 1000000.0);
		else if (n_ticks >= 1000)
			mvwprintw(win_regs, 11, 44, "cnt: %7.2fk", double(n_ticks) / 1000.0);
		else
			mvwprintw(win_regs, 11, 44, "cnt: %lld", n_ticks);

			mvwprintw(win_regs, 11, 44, "cnt: %lld", n_ticks);

		const memory_bus *pmb = p -> get_memory_bus();
		mvwprintw(win_regs, 12, 44, "I_S: %016x", pmb -> get_cur_segment_i());
		mvwprintw(win_regs, 13, 44, "D_S: %016x", pmb -> get_cur_segment());

		if (had_logging)
		{
			wnoutrefresh(win_logs);
			had_logging = false;
		}

		wnoutrefresh(win_regs);
		doupdate();

		if (refresh_limit_valid)
			refresh_counter = 0;
	}