Skip to content

Commit

Permalink
antminer: Initial support for the Bitmain AntMiner U1 ASIC
Browse files Browse the repository at this point in the history
Includes support for identifying the U1 separately from Icarus and Block Erupter
Also includes overclocking via --set-device antminer:clock=xHEX
  • Loading branch information
nwoolls committed Jan 13, 2014
1 parent 638e4b0 commit 4556d14
Show file tree
Hide file tree
Showing 8 changed files with 343 additions and 27 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ if HAS_ICARUS
bfgminer_SOURCES += driver-icarus.c icarus-common.h
bfgminer_SOURCES += driver-cairnsmore.c
bfgminer_SOURCES += driver-erupter.c
bfgminer_SOURCES += driver-antminer.c
endif

if HAS_AVALON
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ if test "x$bitforce" = xyes; then
fi
AM_CONDITIONAL([HAS_BITFORCE], [test x$bitforce = xyes])

driverlist="$driverlist icarus cairnsmore/icarus erupter/icarus"
driverlist="$driverlist icarus cairnsmore/icarus erupter/icarus antminer/icarus"
AC_ARG_ENABLE([icarus],
[AC_HELP_STRING([--disable-icarus],[Compile support for Icarus (default enabled)])],
[icarus=$enableval],
Expand Down
188 changes: 188 additions & 0 deletions driver-antminer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/*
* Copyright 2013 Luke Dashjr
* Copyright 2013 Nate Woolls
* Copyright 2013 Lingchao Xu
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version. See COPYING for more details.
*/

#include "config.h"

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "miner.h"
#include "icarus-common.h"
#include "lowlevel.h"
#include "lowl-vcom.h"
#include "deviceapi.h"
#include "logging.h"
#include "util.h"

#define ANTMINER_IO_SPEED 115200
#define ANTMINER_HASH_TIME 0.0000000004761

#define ANTMINER_STATUS_LEN 5

BFG_REGISTER_DRIVER(antminer_drv)

static
bool antminer_detect_one(const char *devpath)
{
struct device_drv *drv = &antminer_drv;

struct ICARUS_INFO *info = calloc(1, sizeof(struct ICARUS_INFO));
if (unlikely(!info))
quit(1, "Failed to malloc ICARUS_INFO");

*info = (struct ICARUS_INFO){
.baud = ANTMINER_IO_SPEED,
.Hs = ANTMINER_HASH_TIME,
.timing_mode = MODE_DEFAULT,
.read_size = 5,
};

if (!icarus_detect_custom(devpath, drv, info))
{
free(info);
return false;
}

info->read_count = 15;

return true;
}

static
bool antminer_lowl_probe(const struct lowlevel_device_info * const info)
{
return vcom_lowl_probe_wrapper(info, antminer_detect_one);
}

static
char *antminer_get_clock(struct cgpu_info *cgpu, char *replybuf)
{
uint8_t rdreg_buf[4] = {0};
unsigned char rebuf[ANTMINER_STATUS_LEN] = {0};

struct timeval tv_now;

rdreg_buf[0] = 4;
rdreg_buf[0] |= 0x80;
rdreg_buf[1] = 0; //16-23
rdreg_buf[2] = 0x04; // 8-15
rdreg_buf[3] = crc5usb(rdreg_buf, 27);

applog(LOG_DEBUG, "%"PRIpreprv": Get clock: %02x%02x%02x%02x", cgpu->proc_repr, rdreg_buf[0], rdreg_buf[1], rdreg_buf[2], rdreg_buf[3]);

timer_set_now(&tv_now);
int err = icarus_write(cgpu->device_fd, rdreg_buf, sizeof(rdreg_buf));

if (err != 0)
{
sprintf(replybuf, "invalid send get clock: comms error (err=%d)", err);
return replybuf;
}

applog(LOG_DEBUG, "%"PRIpreprv": Get clock: OK", cgpu->proc_repr);

memset(rebuf, 0, sizeof(rebuf));
err = icarus_gets(rebuf, cgpu->device_fd, &tv_now, NULL, 10, ANTMINER_STATUS_LEN);

// Timeout is ok - checking specifically for an error here
if (err == ICA_GETS_ERROR)
{
sprintf(replybuf, "invalid recv get clock: comms error (err=%d)", err);
return replybuf;
}

applog(LOG_DEBUG, "%"PRIpreprv": Get clock: %02x%02x%02x%02x%02x", cgpu->proc_repr, rebuf[0], rebuf[1], rebuf[2], rebuf[3], rebuf[4]);

return NULL;
}

static
char *antminer_set_clock(struct cgpu_info *cgpu, char *setting, char *replybuf)
{
if (!setting || !*setting)
return "missing clock setting";

// For now we only allow hex values that use BITMAINtech's lookup table
// This means values should be prefixed with an x so that later we can
// accept and distinguish decimal values
if (setting[0] != 'x')
{
sprintf(replybuf, "invalid clock: '%s' data must be prefixed with an x", setting);
return replybuf;
}

//remove leading character
char *hex_setting = setting + 1;

uint8_t reg_data[4] = {0};

if (!hex2bin(reg_data, hex_setting, strlen(hex_setting) / 2))
{
sprintf(replybuf, "invalid clock: '%s' data must be a hexidecimal value", hex_setting);
return replybuf;
}

uint8_t cmd_buf[4] = {0};

cmd_buf[0] = 2;
cmd_buf[0] |= 0x80;
cmd_buf[1] = reg_data[0]; //16-23
cmd_buf[2] = reg_data[1]; // 8-15
cmd_buf[3] = crc5usb(cmd_buf, 27);

applog(LOG_DEBUG, "%"PRIpreprv": Set clock: %02x%02x%02x%02x", cgpu->proc_repr, cmd_buf[0], cmd_buf[1], cmd_buf[2], cmd_buf[3]);

int err = icarus_write(cgpu->device_fd, cmd_buf, sizeof(cmd_buf));

if (err != 0)
{
sprintf(replybuf, "invalid send clock: '%s' comms error (err=%d)", setting, err);
return replybuf;
}

applog(LOG_DEBUG, "%"PRIpreprv": Set clock: OK", cgpu->proc_repr);

// This is confirmed required in order for the clock change to "take"
cgsleep_ms(500);

return antminer_get_clock(cgpu, replybuf);
}

static
char *antminer_set_device(struct cgpu_info *cgpu, char *option, char *setting, char *replybuf)
{
if (strcasecmp(option, "clock") == 0)
{
return antminer_set_clock(cgpu, setting, replybuf);
}

sprintf(replybuf, "Unknown option: %s", option);
return replybuf;
}

static
void antminer_drv_init()
{
antminer_drv = icarus_drv;
antminer_drv.dname = "antminer";
antminer_drv.name = "AMU";
antminer_drv.lowl_probe = antminer_lowl_probe;
antminer_drv.set_device = antminer_set_device,
++antminer_drv.probe_priority;
}

struct device_drv antminer_drv = {
.drv_init = antminer_drv_init,
};
2 changes: 1 addition & 1 deletion driver-cairnsmore.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ bool cairnsmore_supports_dynclock(int fd)
.work_restart = false,
.work_restart_notifier = {-1, -1},
};
icarus_gets((unsigned char*)&nonce, fd, &tv_finish, &dummy, 1);
icarus_gets((unsigned char*)&nonce, fd, &tv_finish, &dummy, 1, ICARUS_DEFAULT_READ_SIZE);
}
applog(LOG_DEBUG, "Cairnsmore dynclock detection... Got %08x", nonce);
switch (nonce) {
Expand Down
Loading

0 comments on commit 4556d14

Please sign in to comment.