Driver Spondoolies Sp30
Driver Spondoolies Sp30
/*
This driver communicates the job requests via Unix socket to the minergate
process, that is responsible for controlling the Spondoolies Dawson SP10 miner.
The jobs sent each with unique ID and returned asynchronously in one of the next
transactions. REQUEST_PERIOD and REQUEST_SIZE define the communication rate with
minergate.
*/
#include <float.h>
#include <limits.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <strings.h>
#include <sys/time.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include "config.h"
#include "compat.h"
#include "miner.h"
#include "driver-spondoolies-sp30-p.h"
#include "driver-spondoolies-sp30.h"
#ifdef WORDS_BIGENDIAN
# define swap32tobe(out, in, sz) ((out == in) ? (void)0 : memmove(out, in, sz))
# define LOCAL_swap32be(type, var, sz) ;
# define swap32tole(out, in, sz) swap32yes(out, in, sz)
# define LOCAL_swap32le(type, var, sz) LOCAL_swap32(type, var, sz)
#else
# define swap32tobe(out, in, sz) swap32yes(out, in, sz)
# define LOCAL_swap32be(type, var, sz) LOCAL_swap32(type, var, sz)
# define swap32tole(out, in, sz) ((out == in) ? (void)0 : memmove(out, in, sz))
# define LOCAL_swap32le(type, var, sz) ;
#endif
static inline void swap32yes(void *out, const void *in, size_t sz)
{
size_t swapcounter;
nbytes = sizeof(minergate_req_packet_sp30);
nwrote = write(socket_fd, (const void *)mp_req, nbytes);
if (unlikely(nwrote != nbytes))
_quit(-1);
nbytes = sizeof(minergate_rsp_packet_sp30);
nread = read(socket_fd, (void *)mp_rsp, nbytes);
if (unlikely(nread != nbytes))
_quit(-1);
assert(mp_rsp->magic == 0xcaf4);
}
assert(spondoolies_sp30);
cgtime(&now);
/* FIXME: Vladik */
#if NEED_FIX
get_datestamp(spondoolies_sp30->init, &now);
#endif
return true;
}
address.sun_family = AF_UNIX;
sprintf(address.sun_path, MINERGATE_SOCKET_FILE_SP30);
return socket_fd;
}
static bool spondoolies_flush_queue(struct spond_adapter* a, bool flush_queue)
{
if (!a->parse_resp) {
static int i = 0;
a->mp_next_req->req_count = 0;
a->parse_resp = 1;
a->works_in_minergate_and_pending_tx += a->works_pending_tx;
a->works_pending_tx = 0;
}
return true;
}
#if NEED_FIX
nDevs = 1;
#endif
assert(cgpu);
cgpu->drv = drv;
cgpu->deven = DEV_ENABLED;
cgpu->threads = 1;
cgpu->device_data = calloc(sizeof(struct spond_adapter), 1);
if (unlikely(!(cgpu->device_data)))
quit(1, "Failed to calloc cgpu_info data");
a = cgpu->device_data;
a->cgpu = (void *)cgpu;
a->adapter_state = ADAPTER_STATE_OPERATIONAL;
a->mp_next_req = allocate_minergate_packet_req_sp30(0xca, 0xfe);
a->mp_last_rsp = allocate_minergate_packet_rsp_sp30(0xca, 0xfe);
pthread_mutex_init(&a->lock, NULL);
a->socket_fd = init_socket();
if (a->socket_fd < 1) {
applog(LOG_ERR, "SP30: Failed to connect to minergate server");
_quit(-1);
}
assert(add_cgpu(cgpu));
// Clean MG socket
spondoolies_flush_queue(a, true);
spondoolies_flush_queue(a, true);
spondoolies_flush_queue(a, true);
applog(LOG_DEBUG, "SP30: SPOND spondoolies_detect_sp30 done");
}
return root;
}
#if 0
static unsigned char get_leading_zeroes(const unsigned char *target)
{
unsigned char leading = 0;
int first_non_zero_chr;
uint8_t m;
// j = first non-zero
m = target[first_non_zero_chr];
while ((m & 0x80) == 0) {
leading++;
m = m << 1;
}
return leading;
}
#endif
memset(work, 0, sizeof(minergate_do_job_req_sp30));
//work->
LOCAL_swap32le(unsigned char, cg_work->midstate, 32 / 4)
LOCAL_swap32le(unsigned char, cg_work->data + 64, 64 / 4)
swap32yes(x, cg_work->data + 64, 64 / 4);
memcpy(work->midstate, cg_work->midstate, 32);
work->mrkle_root = ntohl(x[0]);
work->timestamp = ntohl(x[1]);
work->difficulty = ntohl(x[2]);
//work->leading_zeroes = get_leading_zeroes(cg_work->target);
// Is there no better way to get leading zeroes?
work->leading_zeroes = 31;
wd = round(cg_work->device_diff);
while (wd) {
work->leading_zeroes++;
wd = wd >> 1;
}
//printf("%d %d\n",work->leading_zeroes, (int)round(cg_work-
>work_difficulty));
work->work_id_in_sw = cg_work->subid;
work->ntime_limit = max_offset;
//printf("ID:%d, TS:%x\n",work->work_id_in_sw,work->timestamp);
//work->ntime_offset = ntime_offset;
}
cgtime(&tv);
curr_usec = tv.tv_sec * 1000000 + tv.tv_usec;
if (first_usec == 0) {
first_usec = curr_usec;
curr_usec = 0;
} else
curr_usec -= first_usec;
return curr_usec;
}
if (!((bla++)%500)) {
printf("FAKE TEST FLUSH T:%d!\n",usec_stamp());
a->reset_mg_queue = 3;
}
#endif
// Only once every 1/10 second do work.
bool ret = false, do_sleep = false;
int next_job_id;
struct timeval tv;
struct work *work;
unsigned int usec;
mutex_lock(&a->lock);
assert(a->works_pending_tx <= REQUEST_SIZE);
gettimeofday(&tv, NULL);
work->thr = cgpu->thr[0];
work->thr_id = cgpu->thr[0]->id;
assert(work->thr);
a->current_job_id = next_job_id;
work->subid = a->current_job_id;
// Get pointer for the request
a->my_jobs[a->current_job_id].cgminer_work = work;
a->my_jobs[a->current_job_id].state = SPONDWORK_STATE_IN_BUSY;
//printf("Push: %d\n", a->current_job_id);
return_unlock:
//printf("D:P.TX:%d inD:%d\n", a->works_pending_tx, a->works_in_driver);
mutex_unlock(&a->lock);
if (do_sleep)
cgsleep_ms(10);
return ret;
}
if (!fp) {
applog(LOG_DEBUG, "SP30: SPOND unable to open mg_rate_temp");
a->temp_rate = a->front_temp = a->rear_temp_top = a->rear_temp_bot = 0;
} else {
int ret = fscanf(fp, "%d %d %d %d", &a->temp_rate, &a->front_temp , &a-
>rear_temp_top , &a->rear_temp_bot);
if (ret != 4)
a->temp_rate = a->front_temp = a->rear_temp_top = a->rear_temp_bot = 0;
fclose(fp);
}
applog(LOG_DEBUG, "SP30: SPOND poll_stats rate: %d front: %d rear(T/B):
%d/%d",
a->temp_rate, a->front_temp , a->rear_temp_top, a->rear_temp_bot);
/* Use the rear temperature as the dev temperature for now */
spond->temp = (a->rear_temp_top + a->rear_temp_bot)/2;
}
cgsleep_prepare_r(&cgt);
now_t = time(NULL);
/* Poll stats only once per second */
if (now_t != a->last_stats) {
a->last_stats = now_t;
spond_poll_stats(cgpu, a);
}
if (a->parse_resp) {
int array_size, i;
mutex_lock(&a->lock);
//ghashes = (a->mp_last_rsp->gh_div_50_rate);
//ghashes = ghashes * 50000 * REQUEST_PERIOD;
array_size = a->mp_last_rsp->rsp_count;
for (i = 0; i < array_size; i++) { // walk the jobs
int job_id;
if (work->winner_nonce) {
struct work *cg_work = a-
>my_jobs[job_id].cgminer_work;
bool ok;
ok = submit_noffset_nonce(cg_work->thr,
cg_work, work->winner_nonce, work->ntime_offset);
if (ok)
ghashes += 0xffffffffull * cg_work-
>device_diff;
/*printf("WIn on %d (+%d), none=%x = %d\n",
* work->work_id_in_sw, work-
>ntime_offset, htole32(work->winner_nonce), ok);*/
a->wins++;
}
a->parse_resp = 0;
}
cgsleep_ms_r(&cgt, 40);
return ghashes;
}
//printf("GOT FLUSH!%d\n");
mutex_lock(&a->lock);
a->reset_mg_queue = 3;
mutex_unlock(&a->lock);
}