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:freq=HEX
  • Loading branch information
nwoolls committed Jan 9, 2014
1 parent 638e4b0 commit 892de74
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 28 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
171 changes: 171 additions & 0 deletions driver-antminer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* Copyright 2013 Luke Dashjr
* Copyright 2013 Nate Woolls
* Copyright 2013 Lingchao Xu <lingchao.xu@bitmaintech.com>
*
* 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 "miner.h"
#include "icarus-common.h"
#include "lowlevel.h"
#include "lowl-vcom.h"

#define ANTMINER_IO_SPEED 115200
#define ANTMINER_HASH_TIME 0.0000000004761

#define ANTMINER_STATUS_LEN 8192

BFG_REGISTER_DRIVER(antminer_drv)

unsigned char antminer_crc5(unsigned char *ptr, unsigned char len)
{
unsigned char i, j, k;
unsigned char crc = 0x1f;

unsigned char crcin[5] = {1, 1, 1, 1, 1};
unsigned char crcout[5] = {1, 1, 1, 1, 1};
unsigned char din = 0;

j = 0x80;
k = 0;
for (i = 0; i < len; i++)
{
if (*ptr & j) {
din = 1;
} else {
din = 0;
}
crcout[0] = crcin[4] ^ din;
crcout[1] = crcin[0];
crcout[2] = crcin[1] ^ crcin[4] ^ din;
crcout[3] = crcin[2];
crcout[4] = crcin[3];

j = j >> 1;
k++;
if (k == 8)
{
j = 0x80;
k = 0;
ptr++;
}
memcpy(crcin, crcout, 5);
}
crc = 0;
if(crcin[4]) {
crc |= 0x10;
}
if(crcin[3]) {
crc |= 0x08;
}
if(crcin[2]) {
crc |= 0x04;
}
if(crcin[1]) {
crc |= 0x02;
}
if(crcin[0]) {
crc |= 0x01;
}
return crc;
}

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_set_frequency(struct cgpu_info *cgpu, char *setting, char *replybuf)
{
unsigned char reg_data[4] = {0};
unsigned char cmd_buf[4] = {0};

if (!hex2bin(reg_data, setting, strlen(setting) / 2)) {
sprintf(replybuf, "invalid set freq: '%s' hex2bin error", setting);
return replybuf;
}

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] = antminer_crc5(cmd_buf, 27);

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

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

return NULL;
}

static
char *antminer_set_device(struct cgpu_info *cgpu, char *option, char *setting, char *replybuf)
{
if (strcasecmp(option, "freq") == 0) {

if (!setting || !*setting)
return "missing freq setting";

if (strlen(setting) > 8 || strlen(setting) % 2 != 0 || strlen(setting) / 2 == 0) {
sprintf(replybuf, "invalid freq: '%s' data must be hex", setting);
return replybuf;
}

return antminer_set_frequency(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 = "ANT";
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,
};
12 changes: 8 additions & 4 deletions driver-cairnsmore.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,25 @@ static bool cairnsmore_send_cmd(int fd, uint8_t cmd, uint8_t data, bool probe)
return write(fd, pkt, sizeof(pkt)) == sizeof(pkt);
}

bool cairnsmore_supports_dynclock(int fd)
bool cairnsmore_supports_dynclock(int fd, int read_size)
{
if (!cairnsmore_send_cmd(fd, 0, 1, true))
return false;
if (!cairnsmore_send_cmd(fd, 0, 1, true))
return false;


// For reading the nonce from Icarus
unsigned char nonce_bin[read_size];
// For storing the 32-bit nonce
uint32_t nonce = 0;
{
struct timeval tv_finish;
struct thr_info dummy = {
.work_restart = false,
.work_restart_notifier = {-1, -1},
};
icarus_gets((unsigned char*)&nonce, fd, &tv_finish, &dummy, 1);
icarus_gets(nonce_bin, fd, &tv_finish, &dummy, 1, read_size);
memcpy((char *)&nonce, nonce_bin, sizeof(nonce));
}
applog(LOG_DEBUG, "Cairnsmore dynclock detection... Got %08x", nonce);
switch (nonce) {
Expand Down Expand Up @@ -133,7 +137,7 @@ static bool cairnsmore_init(struct thr_info *thr)
struct ICARUS_INFO *info = cm1->device_data;
struct icarus_state *state = thr->cgpu_data;

if (cairnsmore_supports_dynclock(cm1->device_fd)) {
if (cairnsmore_supports_dynclock(cm1->device_fd, info->read_size)) {
info->dclk_change_clock_func = cairnsmore_change_clock_func;

dclk_prepare(&info->dclk);
Expand Down
1 change: 1 addition & 0 deletions driver-erupter.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ static bool _erupter_detect_one(const char *devpath, struct device_drv *drv)
.Hs = ERUPTER_HASH_TIME,
.timing_mode = MODE_DEFAULT,
.continue_search = true,
.read_size = 4,
};

if (!icarus_detect_custom(devpath, drv, info)) {
Expand Down
Loading

4 comments on commit 892de74

@locutus918
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im going to cut to the point i know hardware not programing but i bought 2 antminers 1.6 ghsh and i need somone to tell me what i am supposed to do with what you all have typed so i can use this im on a windows platform and when i put in -s antminer in the device management area it did nothing

@peter3126
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems, the overclock, "--set-device antminer:freq=HEX" doesn't work. Any suggestion?

@nwoolls
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The format is now --set-device antminer:clock=xHEX

@peter3126
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--set-device antminer:clock=x0981

It works now on OSX 10.9.1. Thanks.

screen shot 2014-01-13 at 4 52 22 am

Please sign in to comment.