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; }
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; }
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(¤t_stratum); if (tdiff(¤t_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; }