static void fill_pxgate_request(pxgate_do_mrkljob_req* job, struct cgpu_info *cgpu)
{
    int i;
    uint32_t converted[2];
    uint8_t bytes[8]; // ntime 32 bit, nbits 32 bit  
    struct spond_adapter *device = cgpu->device_data;
    int sw_job_id = device->current_job_id;
    int job_id = get_array_id(sw_job_id);
    struct pool *pool = &device->my_jobs[job_id].pool;
    cg_rlock(&device->my_jobs[job_id].data_lock);
    /*
     * fill the job
     */
    memset(job, 0, sizeof(pxgate_do_mrkljob_req));
    job->work_id_in_sw = sw_job_id; 
    memcpy(
            bytes,
            pool->header_bin + 4 /*bbversion*/ + 32 /*prev_hash*/ + 32 /*blank_merkle*/,
            4 /*ntime*/ + 4 /*nbits*/
          );
    swap32yes(converted, bytes, 2);
    job->timestamp  = ntohl(converted[0]);
    job->difficulty = ntohl(converted[1]);
    memcpy(job->header_bin, pool->header_bin, sizeof(job->header_bin));
    /*
     * taking target and count leading zeros
     */
    unsigned char target[32];
    unsigned char target_swap[32];
    set_target(target, pool->sdiff);
    // order bytes, so we have bits from left to right
    swab256(target_swap, target);
    // set termination point
    target_swap[31] |= 0x01;
    job->leading_zeroes = 0;
    int pos = 0;
    while (((target_swap[pos / 8] >> (7 - (pos % 8))) & 0x1) == 0x0) {
        job->leading_zeroes++;
        pos++;
    }
    if (opt_debug) {
        char *target_str;
        target_str = bin2hex(target_swap, 32);
        SPONDLOG(LOG_DEBUG, "stratum target[%s] job->leading_zeroes[%d]\n",
                target_str,
                job->leading_zeroes
              );
        free(target_str);
    }
    job->ntime_limit = NTIME_LIMIT; 
    job->resr1 = 0;
    job->coinbase_len = pool->coinbase_len;
    memcpy(job->coinbase, pool->coinbase, job->coinbase_len);
    job->nonce2_offset = pool->nonce2_offset;
    if (pool->n2size < 8) {
        applog(LOG_ERR, "NONCE2 TOO SMALL (%d)!\n", pool->n2size);
        passert(0);
    }
    job->merkles = pool->merkles;
    // each merkle is 32 bytes size
    for (i = 0; i < pool->merkles; ++i) {
        memcpy(job->merkle + 32 * i, pool->swork.merkle_bin[i], 32);
    }
    cg_runlock(&device->my_jobs[job_id].data_lock);
}
static void spondoolies_update_work_sp50(struct cgpu_info *cgpu)
{
    struct spond_adapter *device = cgpu->device_data;
	struct thr_info *thr = cgpu->thr[0];
    struct work *work = NULL;
    struct pool *pool = NULL;

    // setup thread flags
    SPONDLOG(LOG_DEBUG, "New stratum: restart: %d, update: %d", thr->work_restart, thr->work_update);
	thr->work_update = false;
	thr->work_restart = false;

	work = get_work(thr, thr->id); /* Make sure pool is ready */
	discard_work(work); /* Don't leak memory */

    // lets check pool job parameters
    pool = current_pool();
    if (!pool->has_stratum) {
        quit(1, "%s: Miner Manager have to use stratum pool", sp50_drv.dname);
    }
    if (pool->coinbase_len > SPOND_MAX_COINBASE_LEN) {
        SPONDLOG(LOG_ERR, "Miner Manager pool coinbase length[%d] have to less then %d",
                pool->coinbase_len,
                SPOND_MAX_COINBASE_LEN);
        return;
    }
    if (pool->merkles > SPOND_MAX_MERKLES) {
        SPONDLOG(LOG_ERR, "Miner Manager merkles have to less then %d", SPOND_MAX_MERKLES);
        return;
    }
    // need to lock driver, since we may drop all jobs
    // #########   DEVICE LOCK
    //
    pthread_mutex_lock(&device->lock);
    // lock and copy pool data
    // in our case pool_no is always same number
    // but swork.job_id changes each job
    cg_rlock(&pool->data_lock);
    copy_pool_stratum(device, pool);
    cg_runlock(&pool->data_lock);
    /*
     * fill job and send it to miner
     */
    pxgate_req_packet req_packet;
    memset(&req_packet, 0, sizeof(req_packet));
    req_packet.header.protocol_version = pxgate_PROTOCOL_VERSION;
    req_packet.header.message_type = pxgate_MESSAGE_TYPE_JOB_REQ;
    req_packet.header.message_size = sizeof(req_packet)-sizeof(req_packet.header);
    // TODO: use MACRO
    req_packet.mask = 0x01; // 0x01 = first request, 0x2 = drop old work
    if (device->drop_old_jobs) {
        req_packet.mask |= 0x02; // drop old work
        device->drop_old_jobs  = 0;
    }
    // currently we will send only one job
    fill_pxgate_request(&req_packet.req, cgpu);
    // #########   DEVICE UNLOCK
    //
    pthread_mutex_unlock(&device->lock);
    do_write(device->socket_fd, &req_packet, sizeof(req_packet));
    /*
     * read the response from miner
     */
    pxgate_gen_packet rsp_packet;
    uint32_t size = 0;
    if ((size = do_read_packet(device->socket_fd, &rsp_packet, sizeof(rsp_packet))) != sizeof(rsp_packet)) {
        quit(1, "%s: critical error, packet sent from miner is bad received size[%u] expected [%u], quiting...",
                sp50_drv.dname,
                size,
                sizeof(rsp_packet)
            );
    }
    switch (rsp_packet.header.message_type) {
        case pxgate_MESSAGE_TYPE_JOB_REQ_ACK:
            SPONDLOG(LOG_DEBUG, "pxgate_MESSAGE_TYPE_JOB_REQ_ACK");
            break;
        case pxgate_MESSAGE_TYPE_JOB_REQ_REJ:
            SPONDLOG(LOG_DEBUG, "pxgate_MESSAGE_TYPE_JOB_REQ_REJ");
            break;
        default:
            SPONDLOG(LOG_ERR, "unexpected type[%x]", rsp_packet.header.message_type);
            return;
    }
    /*
     * everything is ok, we cache the job
     */
    device->current_job_id = (device->current_job_id++) % MAX_SW_JOB_INDEX_IN_MINERGATE;
}
示例#3
0
static void hashratio_update_work(struct cgpu_info *hashratio)
{
	struct hashratio_info *info = hashratio->device_data;
	struct thr_info *thr = hashratio->thr[0];
	struct hashratio_pkg send_pkg;
	uint32_t tmp, range, start;
	struct work *work;
	struct pool *pool;

	applog(LOG_DEBUG, "hashratio: New stratum: restart: %d, update: %d",
		thr->work_restart, thr->work_update);
	thr->work_update = false;
	thr->work_restart = false;

	work = get_work(thr, thr->id); /* Make sure pool is ready */
	discard_work(work); /* Don't leak memory */

	pool = current_pool();
	if (!pool->has_stratum)
		quit(1, "hashratio: Miner Manager have to use stratum pool");
	if (pool->coinbase_len > HRTO_P_COINBASE_SIZE)
		quit(1, "hashratio: Miner Manager pool coinbase length have to less then %d", HRTO_P_COINBASE_SIZE);
	if (pool->merkles > HRTO_P_MERKLES_COUNT)
		quit(1, "hashratio: Miner Manager merkles have to less then %d", HRTO_P_MERKLES_COUNT);

	info->pool_no = pool->pool_no;

	cgtime(&info->last_stratum);
	cg_rlock(&pool->data_lock);
	info->pool_no = pool->pool_no;
	copy_pool_stratum(info, pool);
	hashratio_stratum_pkgs(hashratio, pool);
	cg_runlock(&pool->data_lock);

	/* Configure the parameter from outside */
	memset(send_pkg.data, 0, HRTO_P_DATA_LEN);

	// fan. We're not measuring temperature so set a safe but not max value
	info->fan_pwm = HRTO_PWM_MAX * 2 / 3;
	tmp = be32toh(info->fan_pwm);
	memcpy(send_pkg.data, &tmp, 4);

	// freq
	tmp = be32toh(info->default_freq);
	memcpy(send_pkg.data + 4, &tmp, 4);
	applog(LOG_DEBUG, "set freq: %d", info->default_freq);

	/* Configure the nonce2 offset and range */
	range = 0xffffffff / (total_devices + 1);
	start = range * (hashratio->device_id + 1);

	tmp = be32toh(start);
	memcpy(send_pkg.data + 8, &tmp, 4);

	tmp = be32toh(range);
	memcpy(send_pkg.data + 12, &tmp, 4);

	/* Package the data */
	hashratio_init_pkg(&send_pkg, HRTO_P_SET, 1, 1);
	hashratio_send_pkgs(hashratio, &send_pkg);
}
static int polling_and_return_number_of_wins(struct thr_info *thr)
{
    struct cgpu_info *spondoolies = thr->cgpu;
    struct spond_adapter *device = spondoolies->device_data;
    /*
     * send request to miner gateway to get wins results
     */
    pxgate_gen_packet req_rsp;
    req_rsp.header.message_type = pxgate_MESSAGE_TYPE_RSP_REQ;
    req_rsp.header.message_size = sizeof(req_rsp)-sizeof(req_rsp.header);
    req_rsp.header.protocol_version = pxgate_PROTOCOL_VERSION;
    do_write(device->socket_fd, &req_rsp, sizeof(req_rsp)); 
    /* 
     * read result
     */
    // OK, since we don't know message size, lets take biggest
    void *message = calloc(1, sizeof(pxgate_rsp_packet));
    int size =  do_read_packet(device->socket_fd, message, sizeof(pxgate_rsp_packet));
    if (size == 0) {
        quit(1, "%s: Ooops returned bad packet from cgminer", sp50_drv.dname);
        free(message);
        return 0;
    }
    // lets check the header
    pxgate_packet_header *header = (pxgate_packet_header*) message;
    switch (header->message_type) {
        case pxgate_MESSAGE_TYPE_RSP_NODATA:
            {
                free(message);
                return 0;
            }
        case pxgate_MESSAGE_TYPE_RSP_DATA:
            {
                int i;
                int j;
                pxgate_rsp_packet *rsp = (pxgate_rsp_packet*) message;
                // TODO: handle rsp->gh_div_10_rate
                int results = rsp->rsp_count;
                for (i = 0; i < results; ++i) {
                    // get work object that requested mining
                    struct pool *real_pool = NULL;
                    struct pool *pool = NULL;
                    int job_id = get_array_id(rsp->rsp[i].work_id_in_sw);
                    // lets check that we can work with sw job_id and pool we cached
                    // CHECKING JOB VALIDITY
                    if (job_id < 0 || rsp->rsp[i].work_id_in_sw > MAX_SW_JOB_INDEX_IN_MINERGATE) {
                        free(message);
                        return 0;
                    }
                    cg_rlock(&(device->my_jobs[job_id].data_lock));
                    if (device->my_jobs[job_id].pool.swork.job_id == NULL) {
                        // it is stale job, we drop result
                        // it happens due to flush work, right before we received results from asic
                        SPONDLOG(LOG_ERR, "droping wins enonce2[0x%016llx] nonce[0x%08x] gate_job_id[%d] cgminer_job_id[%d], stale job",
                                rsp->rsp[i].nonce2,
                                rsp->rsp[i].winner_nonce,
                                rsp->rsp[i].work_id_in_sw,
                                device->my_jobs[job_id].sw_job_id
                                );
                        free(message);
                        cg_runlock(&(device->my_jobs[job_id].data_lock));
                        return 0;
                    }
                    if (device->my_jobs[job_id].sw_job_id != rsp->rsp[i].work_id_in_sw) {
                        // it is stale job, we drop result
                        SPONDLOG(LOG_ERR, "droping wins enonce2[0x%016llx] nonce[0x%08x] gate_job_id[%d] cgminer_job_id[%d], stale job",
                                rsp->rsp[i].nonce2,
                                rsp->rsp[i].winner_nonce,
                                rsp->rsp[i].work_id_in_sw,
                                device->my_jobs[job_id].sw_job_id
                                );
                        free(message);
                        cg_runlock(&(device->my_jobs[job_id].data_lock));
                        return 0;
                    }
                    pool = &device->my_jobs[job_id].pool;
                    real_pool = pools[device->my_jobs[job_id].pool.pool_no];
                    if (submit_nonce2_nonce(
                                thr,
                                pool,
                                real_pool,
                                rsp->rsp[i].nonce2,
                                ntohl(rsp->rsp[i].winner_nonce),
                                rsp->rsp[i].ntime_offset)){
                        SPONDLOG(LOG_ERR, "nonce::: %s: win [%d/%d] enonce[%016llx] nonce [%08x], ntime_offset %x",
                                sp50_drv.dname,
                                i+1,
                                results,
                                rsp->rsp[i].nonce2,
                                rsp->rsp[i].winner_nonce,
                                rsp->rsp[i].ntime_offset
                              );
                    }
                    cg_runlock(&(device->my_jobs[job_id].data_lock));
                }
                free(message);
                return results;
            };
        default:
            {
                SPONDLOG(LOG_ERR, "Ooops returned un expected message type [%08x]", header->message_type);
                free(message);
                return 0;
            }
    }
    return 0;
}
示例#5
0
static int64_t avalon2_scanhash(struct thr_info *thr)
{
	struct avalon2_pkg send_pkg;
	struct timeval current_stratum;

	struct pool *pool;
	struct cgpu_info *avalon2 = thr->cgpu;
	struct avalon2_info *info = avalon2->device_data;

	int64_t h;
	uint32_t tmp, range, start;
	int i;

	if (thr->work_restart || thr->work_update || !info->first) {
		applog(LOG_DEBUG, "Avalon2: New stratum: restart: %d, update: %d, first: %d",
		       thr->work_restart, thr->work_update, info->first);
		thr->work_update = false;
		thr->work_restart = false;
		get_work(thr, thr->id); /* Make sure pool is ready */

		pool = current_pool();
		if (!pool->has_stratum)
			quit(1, "Avalon2: Miner Manager have to use stratum pool");
		if (pool->coinbase_len > AVA2_P_COINBASE_SIZE) {
			applog(LOG_ERR, "Avalon2: Miner Manager pool coinbase length have to less then %d", AVA2_P_COINBASE_SIZE);
			return 0;
		}
		if (pool->merkles > AVA2_P_MERKLES_COUNT) {
			applog(LOG_ERR, "Avalon2: Miner Manager merkles have to less then %d", AVA2_P_MERKLES_COUNT);
			return 0;
		}

		cgtime(&info->last_stratum);
		cg_rlock(&pool->data_lock);
		info->pool_no = pool->pool_no;
		copy_pool_stratum(pool);
		avalon2_stratum_pkgs(info->fd, pool, thr);
		cg_runlock(&pool->data_lock);

		/* Configuer the parameter from outside */
		adjust_fan(info);
		info->set_voltage = opt_avalon2_voltage_min;
		info->set_frequency = opt_avalon2_freq_min;

		/* Set the Fan, Voltage and Frequency */
		memset(send_pkg.data, 0, AVA2_P_DATA_LEN);

		tmp = be32toh(info->fan_pwm);
		memcpy(send_pkg.data, &tmp, 4);

		applog(LOG_ERR, "Avalon2: Temp max: %d, Cut off temp: %d",
		       get_current_temp_max(info), opt_avalon2_overheat);
		if (get_current_temp_max(info) >= opt_avalon2_overheat)
			tmp = encode_voltage(0);
		else
			tmp = encode_voltage(info->set_voltage);
		tmp = be32toh(tmp);
		memcpy(send_pkg.data + 4, &tmp, 4);

		tmp = be32toh(info->set_frequency);
		memcpy(send_pkg.data + 8, &tmp, 4);

		/* Configure the nonce2 offset and range */
		range = 0xffffffff / total_devices;
		start = range * avalon2->device_id;

		tmp = be32toh(start);
		memcpy(send_pkg.data + 12, &tmp, 4);

		tmp = be32toh(range);
		memcpy(send_pkg.data + 16, &tmp, 4);

		/* Package the data */
		avalon2_init_pkg(&send_pkg, AVA2_P_SET, 1, 1);
		while (avalon2_send_pkg(info->fd, &send_pkg, thr) != AVA2_SEND_OK)
			;

		if (unlikely(info->first < 2))
			info->first++;
	}

	/* Stop polling the device if there is no stratum in 3 minutes, network is down */
	cgtime(&current_stratum);
	if (tdiff(&current_stratum, &(info->last_stratum)) > (double)(3.0 * 60.0))
		return 0;

	polling(thr);

	h = 0;
	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
		h += info->enable[i] ? (info->local_work[i] - info->hw_work[i]) : 0;
	}
	return h * 0xffffffff;
}