Browse Source

Merge pull request #178 from nelisky/ztex-120417

Firmware 15d4 support
nfactor-troky
Con Kolivas 13 years ago
parent
commit
ab764da472
  1. BIN
      bitstreams/ztex_ufm1_15d4.bit
  2. BIN
      bitstreams/ztex_ufm1_15y1.bit
  3. 86
      driver-ztex.c
  4. 143
      libztex.c
  5. 11
      libztex.h

BIN
bitstreams/ztex_ufm1_15d4.bit

Binary file not shown.

BIN
bitstreams/ztex_ufm1_15y1.bit

Binary file not shown.

86
driver-ztex.c

@ -87,13 +87,16 @@ static bool ztex_updateFreq(struct libztex_device* ztex)
} }
} }
if (bestM != ztex->freqM) if (bestM != ztex->freqM) {
libztex_selectFpga(ztex, 0);
libztex_setFreq(ztex, bestM); libztex_setFreq(ztex, bestM);
}
maxM = ztex->freqMDefault; maxM = ztex->freqMDefault;
while (maxM < ztex->freqMaxM && ztex->errorWeight[maxM + 1] > 100) while (maxM < ztex->freqMaxM && ztex->errorWeight[maxM + 1] > 100)
maxM++; maxM++;
if ((bestM < (1.0 - LIBZTEX_OVERHEATTHRESHOLD) * maxM) && bestM < maxM - 1) { if ((bestM < (1.0 - LIBZTEX_OVERHEATTHRESHOLD) * maxM) && bestM < maxM - 1) {
libztex_selectFpga(ztex, 0);
libztex_resetFpga(ztex); libztex_resetFpga(ztex);
applog(LOG_ERR, "%s: frequency drop of %.1f%% detect. This may be caused by overheating. FPGA is shut down to prevent damage.", applog(LOG_ERR, "%s: frequency drop of %.1f%% detect. This may be caused by overheating. FPGA is shut down to prevent damage.",
ztex->repr, (1.0 - 1.0 * bestM / maxM) * 100); ztex->repr, (1.0 - 1.0 * bestM / maxM) * 100);
@ -147,10 +150,11 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work,
{ {
struct libztex_device *ztex; struct libztex_device *ztex;
unsigned char sendbuf[44]; unsigned char sendbuf[44];
int i, j; int i, j, k;
uint32_t backlog[GOLDEN_BACKLOG]; uint32_t *backlog;
int backlog_p = 0; int backlog_p = 0, backlog_max;
uint32_t lastnonce[GOLDEN_BACKLOG], nonce, noncecnt = 0; uint32_t *lastnonce;
uint32_t nonce, noncecnt = 0;
bool overflow, found, rv; bool overflow, found, rv;
struct libztex_hash_data hdata[GOLDEN_BACKLOG]; struct libztex_hash_data hdata[GOLDEN_BACKLOG];
@ -158,7 +162,8 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work,
memcpy(sendbuf, work->data + 64, 12); memcpy(sendbuf, work->data + 64, 12);
memcpy(sendbuf + 12, work->midstate, 32); memcpy(sendbuf + 12, work->midstate, 32);
memset(backlog, 0, sizeof(backlog));
libztex_selectFpga(ztex, 0);
i = libztex_sendHashData(ztex, sendbuf); i = libztex_sendHashData(ztex, sendbuf);
if (i < 0) { if (i < 0) {
// Something wrong happened in send // Something wrong happened in send
@ -173,19 +178,33 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work,
} }
} }
applog(LOG_DEBUG, "sent hashdata"); applog(LOG_DEBUG, "%s: sent hashdata", ztex->repr);
for (i = 0; i < ztex->numNonces; i++)
lastnonce[i] = 0;
lastnonce = malloc(sizeof(uint32_t)*ztex->numNonces);
if (lastnonce == NULL) {
applog(LOG_ERR, "%s: failed to allocate lastnonce[%d]", ztex->repr, ztex->numNonces);
return 0;
}
memset(lastnonce, 0, sizeof(uint32_t)*ztex->numNonces);
backlog_max = ztex->numNonces * (1 + ztex->extraSolutions);
backlog = malloc(sizeof(uint32_t) * backlog_max);
if (backlog == NULL) {
applog(LOG_ERR, "%s: failed to allocate backlog[%d]", ztex->repr, backlog_max);
return 0;
}
memset(backlog, 0, sizeof(uint32_t) * backlog_max);
overflow = false; overflow = false;
applog(LOG_DEBUG, "%s: entering poll loop", ztex->repr);
while (!(overflow || work_restart[thr->id].restart)) { while (!(overflow || work_restart[thr->id].restart)) {
usleep(250000); usleep(250000);
if (work_restart[thr->id].restart) { if (work_restart[thr->id].restart) {
applog(LOG_DEBUG, "%s: New work detected", ztex->repr); applog(LOG_DEBUG, "%s: New work detected", ztex->repr);
break; break;
} }
libztex_selectFpga(ztex, 0);
i = libztex_readHashData(ztex, &hdata[0]); i = libztex_readHashData(ztex, &hdata[0]);
if (i < 0) { if (i < 0) {
// Something wrong happened in read // Something wrong happened in read
@ -196,6 +215,8 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work,
// And there's nothing we can do about it // And there's nothing we can do about it
ztex_disable(thr); ztex_disable(thr);
applog(LOG_ERR, "%s: Failed to read hash data with err %d, giving up", ztex->repr, i); applog(LOG_ERR, "%s: Failed to read hash data with err %d, giving up", ztex->repr, i);
free(lastnonce);
free(backlog);
return 0; return 0;
} }
} }
@ -227,26 +248,28 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work,
thr->cgpu->hw_errors++; thr->cgpu->hw_errors++;
continue; continue;
} }
nonce = hdata[i].goldenNonce; for (j=0; j<=ztex->extraSolutions; j++) {
if (nonce > 0) { nonce = hdata[i].goldenNonce[j];
found = false; if (nonce > 0) {
for (j = 0; j < GOLDEN_BACKLOG; j++) { found = false;
if (backlog[j] == nonce) { for (k = 0; k < backlog_max; k++) {
found = true; if (backlog[k] == nonce) {
break; found = true;
break;
}
} }
} if (!found) {
if (!found) { applog(LOG_DEBUG, "%s: Share found N%dE%d", ztex->repr, i, j);
applog(LOG_DEBUG, "%s: Share found", ztex->repr); backlog[backlog_p++] = nonce;
backlog[backlog_p++] = nonce; if (backlog_p >= backlog_max)
if (backlog_p >= GOLDEN_BACKLOG) backlog_p = 0;
backlog_p = 0;
#if defined(__BIGENDIAN__) || defined(MIPSEB) #if defined(__BIGENDIAN__) || defined(MIPSEB)
nonce = swab32(nonce); nonce = swab32(nonce);
#endif #endif
work->blk.nonce = 0xffffffff; work->blk.nonce = 0xffffffff;
rv = submit_nonce(thr, work, nonce); rv = submit_nonce(thr, work, nonce);
applog(LOG_DEBUG, "%s: submitted %0.8x %d", ztex->repr, nonce, rv); applog(LOG_DEBUG, "%s: submitted %0.8x %d", ztex->repr, nonce, rv);
}
} }
} }
@ -258,14 +281,21 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work,
if (ztex->errorRate[ztex->freqM] > ztex->maxErrorRate[ztex->freqM]) if (ztex->errorRate[ztex->freqM] > ztex->maxErrorRate[ztex->freqM])
ztex->maxErrorRate[ztex->freqM] = ztex->errorRate[ztex->freqM]; ztex->maxErrorRate[ztex->freqM] = ztex->errorRate[ztex->freqM];
if (!ztex_updateFreq(ztex)) if (!ztex_updateFreq(ztex)) {
// Something really serious happened, so mark this thread as dead! // Something really serious happened, so mark this thread as dead!
free(lastnonce);
free(backlog);
return 0; return 0;
}
applog(LOG_DEBUG, "%s: exit %1.8X", ztex->repr, noncecnt); applog(LOG_DEBUG, "%s: exit %1.8X", ztex->repr, noncecnt);
work->blk.nonce = 0xffffffff; work->blk.nonce = 0xffffffff;
free(lastnonce);
free(backlog);
return noncecnt > 0? noncecnt: 1; return noncecnt > 0? noncecnt: 1;
} }

143
libztex.c

@ -41,7 +41,8 @@
#define CAPABILITY_HS_FPGA 0,5 #define CAPABILITY_HS_FPGA 0,5
//* Capability index for AVR XMEGA support. //* Capability index for AVR XMEGA support.
#define CAPABILITY_MAC_EEPROM 0,6 #define CAPABILITY_MAC_EEPROM 0,6
//* Capability index for multi FPGA support.
#define CAPABILITY_MULTI_FPGA 0,7
static bool libztex_checkDevice(struct libusb_device *dev) static bool libztex_checkDevice(struct libusb_device *dev)
@ -65,7 +66,7 @@ static bool libztex_checkCapability(struct libztex_device *ztex, int i, int j)
{ {
if (!((i >= 0) && (i <= 5) && (j >= 0) && (j < 8) && if (!((i >= 0) && (i <= 5) && (j >= 0) && (j < 8) &&
(((ztex->interfaceCapabilities[i] & 255) & (1 << j)) != 0))) { (((ztex->interfaceCapabilities[i] & 255) & (1 << j)) != 0))) {
applog(LOG_ERR, "%s: capability missing: %d %d", ztex->repr, i, i); applog(LOG_ERR, "%s: capability missing: %d %d", ztex->repr, i, j);
return false; return false;
} }
return true; return true;
@ -223,9 +224,48 @@ int libztex_configureFpga(struct libztex_device *ztex)
return libztex_configureFpgaLS(ztex, buf, true, 2); return libztex_configureFpgaLS(ztex, buf, true, 2);
} }
int libztex_setFreq(struct libztex_device *ztex, uint16_t freq) int libztex_numberOfFpgas(struct libztex_device *ztex) {
{
int cnt; int cnt;
unsigned char buf[3];
if (ztex->numberOfFpgas < 0) {
if (libztex_checkCapability(ztex, CAPABILITY_MULTI_FPGA)) {
cnt = libusb_control_transfer(ztex->hndl, 0xc0, 0x50, 0, 0, buf, 3, 1000);
if (unlikely(cnt < 0)) {
applog(LOG_ERR, "%s: Failed getMultiFpgaInfo with err %d", ztex->repr, cnt);
return cnt;
}
ztex->numberOfFpgas = buf[0] + 1;
ztex->selectedFpga = buf[1];
ztex->parallelConfigSupport = (buf[2] == 1);
} else {
ztex->numberOfFpgas = 1;
ztex->selectedFpga = 0;
ztex->parallelConfigSupport = false;
}
}
return ztex->numberOfFpgas;
}
int libztex_selectFpga(struct libztex_device *ztex, int number) {
int cnt, fpgacnt = libztex_numberOfFpgas(ztex);
if (number < 0 || number >= fpgacnt) {
applog(LOG_WARNING, "%s: Trying to select wrong fpga (%d in %d)", ztex->repr, number, fpgacnt);
return 1;
}
if (ztex->selectedFpga != number && libztex_checkCapability(ztex, CAPABILITY_MULTI_FPGA)) {
cnt = libusb_control_transfer(ztex->hndl, 0x40, 0x51, number, 0, NULL, 0, 500);
if (unlikely(cnt < 0)) {
applog(LOG_ERR, "Ztex check device: Failed to set fpga with err %d", cnt);
return cnt;
}
ztex->selectedFpga = number;
}
return 0;
}
int libztex_setFreq(struct libztex_device *ztex, uint16_t freq) {
int cnt;
uint16_t oldfreq = ztex->freqM;
if (freq > ztex->freqMaxM) if (freq > ztex->freqMaxM)
freq = ztex->freqMaxM; freq = ztex->freqMaxM;
@ -236,7 +276,8 @@ int libztex_setFreq(struct libztex_device *ztex, uint16_t freq)
return cnt; return cnt;
} }
ztex->freqM = freq; ztex->freqM = freq;
applog(LOG_WARNING, "%s: Frequency change to %0.2f Mhz", ztex->repr, ztex->freqM1 * (ztex->freqM + 1)); applog(LOG_WARNING, "%s: Frequency change from %0.2f to %0.2f Mhz",
ztex->repr, ztex->freqM1 * (oldfreq + 1), ztex->freqM1 * (ztex->freqM + 1));
return 0; return 0;
} }
@ -246,14 +287,22 @@ int libztex_resetFpga(struct libztex_device *ztex)
return libusb_control_transfer(ztex->hndl, 0x40, 0x31, 0, 0, NULL, 0, 1000); return libusb_control_transfer(ztex->hndl, 0x40, 0x31, 0, 0, NULL, 0, 1000);
} }
int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** ztex) int libztex_suspend(struct libztex_device *ztex) {
{ if (ztex->suspendSupported) {
return libusb_control_transfer(ztex->hndl, 0x40, 0x84, 0, 0, NULL, 0, 1000);
} else {
return 0;
}
}
int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** ztex) {
struct libztex_device *newdev; struct libztex_device *newdev;
int i, cnt, err;
unsigned char buf[64]; unsigned char buf[64];
int cnt, err;
newdev = malloc(sizeof(struct libztex_device)); newdev = malloc(sizeof(struct libztex_device));
newdev->bitFileName = NULL; newdev->bitFileName = NULL;
newdev->numberOfFpgas = -1;
newdev->valid = false; newdev->valid = false;
newdev->hndl = NULL; newdev->hndl = NULL;
*ztex = newdev; *ztex = newdev;
@ -266,7 +315,7 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt
// Check vendorId and productId // Check vendorId and productId
if (!(newdev->descriptor.idVendor == LIBZTEX_IDVENDOR && if (!(newdev->descriptor.idVendor == LIBZTEX_IDVENDOR &&
newdev->descriptor.idProduct == LIBZTEX_IDPRODUCT)) { newdev->descriptor.idProduct == LIBZTEX_IDPRODUCT)) {
applog(LOG_ERR, "Not a ztex device? %0.4X, %0.4X", newdev->descriptor.idVendor, newdev->descriptor.idProduct); applog(LOG_ERR, "Not a ztex device? %0.4X, %0.4X", newdev->descriptor.idVendor, newdev->descriptor.idProduct);
return 1; return 1;
} }
@ -290,7 +339,7 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt
return cnt; return cnt;
} }
if ( buf[0] != 40 || buf[1] != 1 || buf[2] != 'Z' || buf[3] != 'T' || buf[4] != 'E' || buf[5] != 'X' ) { if (buf[0] != 40 || buf[1] != 1 || buf[2] != 'Z' || buf[3] != 'T' || buf[4] != 'E' || buf[5] != 'X') {
applog(LOG_ERR, "Ztex check device: Error reading ztex descriptor"); applog(LOG_ERR, "Ztex check device: Error reading ztex descriptor");
return 2; return 2;
} }
@ -327,20 +376,46 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt
return cnt; return cnt;
} }
if (unlikely(buf[0] != 4)) { if (unlikely(buf[0] != 5)) {
if (unlikely(buf[0] != 2)) { if (unlikely(buf[0] != 2 && buf[0] != 4)) {
applog(LOG_ERR, "Invalid BTCMiner descriptor version. Firmware must be updated (%d).", buf[0]); applog(LOG_ERR, "Invalid BTCMiner descriptor version. Firmware must be updated (%d).", buf[0]);
return 3; return 3;
} }
applog(LOG_WARNING, "Firmware out of date"); applog(LOG_WARNING, "Firmware out of date (%d).", buf[0]);
}
i = buf[0] > 4? 11: (buf[0] > 2? 10: 8);
while (cnt < 64 && buf[cnt] != 0)
cnt++;
if (cnt < i + 1) {
applog(LOG_ERR, "Invalid bitstream file name .");
return 4;
} }
newdev->bitFileName = malloc(sizeof(char) * (cnt + 1));
memcpy(newdev->bitFileName, &buf[i], cnt);
newdev->bitFileName[cnt] = 0;
newdev->numNonces = buf[1] + 1; newdev->numNonces = buf[1] + 1;
newdev->offsNonces = ((buf[2] & 255) | ((buf[3] & 255) << 8)) - 10000; newdev->offsNonces = ((buf[2] & 255) | ((buf[3] & 255) << 8)) - 10000;
newdev->freqM1 = ((buf[4] & 255) | ((buf[5] & 255) << 8) ) * 0.01; newdev->freqM1 = ((buf[4] & 255) | ((buf[5] & 255) << 8) ) * 0.01;
newdev->freqMaxM = (buf[7] & 255); newdev->freqMaxM = (buf[7] & 255);
newdev->freqM = (buf[6] & 255); newdev->freqM = (buf[6] & 255);
newdev->freqMDefault = newdev->freqM; newdev->freqMDefault = newdev->freqM;
newdev->suspendSupported = (buf[0] == 5);
newdev->hashesPerClock = buf[0] > 2? (((buf[8] & 255) | ((buf[9] & 255) << 8)) + 1) / 128.0: 1.0;
newdev->extraSolutions = buf[0] > 4? buf[10]: 0;
applog(LOG_DEBUG, "PID: %d numNonces: %d offsNonces: %d freqM1: %f freqMaxM: %d freqM: %d suspendSupported: %s hashesPerClock: %f extraSolutions: %d",
buf[0], newdev->numNonces, newdev->offsNonces, newdev->freqM1, newdev->freqMaxM, newdev->freqM, newdev->suspendSupported ? "T": "F",
newdev->hashesPerClock, newdev->extraSolutions);
if (buf[0] < 4) {
if (strncmp(newdev->bitFileName, "ztex_ufm1_15b", 13) != 0)
newdev->hashesPerClock = 0.5;
applog(LOG_WARNING, "HASHES_PER_CLOCK not defined, assuming %0.2f", newdev->hashesPerClock);
}
for (cnt=0; cnt < 255; cnt++) { for (cnt=0; cnt < 255; cnt++) {
newdev->errorCount[cnt] = 0; newdev->errorCount[cnt] = 0;
@ -349,10 +424,6 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt
newdev->maxErrorRate[cnt] = 0; newdev->maxErrorRate[cnt] = 0;
} }
cnt = strlen((char *)&buf[buf[0] == 4? 10: 8]);
newdev->bitFileName = malloc(sizeof(char) * (cnt + 1));
memcpy(newdev->bitFileName, &buf[buf[0] == 4? 10: 8], cnt + 1);
newdev->usbbus = libusb_get_bus_number(dev); newdev->usbbus = libusb_get_bus_number(dev);
newdev->usbaddress = libusb_get_device_address(dev); newdev->usbaddress = libusb_get_device_address(dev);
sprintf(newdev->repr, "ZTEX %.3d:%.3d-%s", newdev->usbbus, newdev->usbaddress, newdev->snString); sprintf(newdev->repr, "ZTEX %.3d:%.3d-%s", newdev->usbbus, newdev->usbaddress, newdev->snString);
@ -437,29 +508,43 @@ int libztex_sendHashData(struct libztex_device *ztex, unsigned char *sendbuf)
return cnt; return cnt;
} }
int libztex_readHashData(struct libztex_device *ztex, struct libztex_hash_data nonces[]) int libztex_readHashData(struct libztex_device *ztex, struct libztex_hash_data nonces[]) {
{ int bufsize = 12 + ztex->extraSolutions * 4;
// length of buf must be 8 * (numNonces + 1) unsigned char *rbuf;
unsigned char rbuf[12 * 8]; int cnt, i, j;
int cnt, i;
if (ztex->hndl == NULL) if (ztex->hndl == NULL)
return 0; return 0;
cnt = libusb_control_transfer(ztex->hndl, 0xc0, 0x81, 0, 0, rbuf, 12 * ztex->numNonces, 1000); rbuf = malloc(sizeof(unsigned char) * (ztex->numNonces * bufsize));
if (rbuf == NULL) {
applog(LOG_ERR, "%s: Failed to allocate memory for reading nonces", ztex->repr);
return 0;
}
cnt = libusb_control_transfer(ztex->hndl, 0xc0, 0x81, 0, 0, rbuf, bufsize * ztex->numNonces, 1000);
if (unlikely(cnt < 0)) { if (unlikely(cnt < 0)) {
applog(LOG_ERR, "%s: Failed readHashData with err %d", ztex->repr, cnt); applog(LOG_ERR, "%s: Failed readHashData with err %d", ztex->repr, cnt);
free(rbuf);
return cnt; return cnt;
} }
for (i = 0; i < ztex->numNonces; i++) { for (i=0; i<ztex->numNonces; i++) {
memcpy((char*)&nonces[i].goldenNonce, &rbuf[i * 12], 4); memcpy((char*)&nonces[i].goldenNonce[0], &rbuf[i*bufsize], 4);
nonces[i].goldenNonce -= ztex->offsNonces; nonces[i].goldenNonce[0] -= ztex->offsNonces;
memcpy((char*)&nonces[i].nonce, &rbuf[(i * 12) + 4], 4); //applog(LOG_DEBUG, "W %d:0 %0.8x", i, nonces[i].goldenNonce[0]);
memcpy((char*)&nonces[i].nonce, &rbuf[(i*bufsize)+4], 4);
nonces[i].nonce -= ztex->offsNonces; nonces[i].nonce -= ztex->offsNonces;
memcpy((char*)&nonces[i].hash7, &rbuf[(i * 12) + 8], 4); memcpy((char*)&nonces[i].hash7, &rbuf[(i*bufsize)+8], 4);
for (j=0; j<ztex->extraSolutions; j++) {
memcpy((char*)&nonces[i].goldenNonce[j+1], &rbuf[(i*bufsize)+12+(j*4)], 4);
nonces[i].goldenNonce[j+1] -= ztex->offsNonces;
//applog(LOG_DEBUG, "W %d:%d %0.8x", i, j+1, nonces[i].goldenNonce[j+1]);
}
} }
free(rbuf);
return cnt; return cnt;
} }

11
libztex.h

@ -32,7 +32,7 @@
#define LIBZTEX_MAXMAXERRORRATE 0.05 #define LIBZTEX_MAXMAXERRORRATE 0.05
#define LIBZTEX_ERRORHYSTERESIS 0.1 #define LIBZTEX_ERRORHYSTERESIS 0.1
#define LIBZTEX_OVERHEATTHRESHOLD 0.5 #define LIBZTEX_OVERHEATTHRESHOLD 0.4
struct libztex_fpgastate { struct libztex_fpgastate {
bool fpgaConfigured; bool fpgaConfigured;
@ -62,12 +62,19 @@ struct libztex_device {
uint8_t freqMaxM; uint8_t freqMaxM;
uint8_t freqMDefault; uint8_t freqMDefault;
char* bitFileName; char* bitFileName;
bool suspendSupported;
double hashesPerClock;
uint8_t extraSolutions;
double errorCount[256]; double errorCount[256];
double errorWeight[256]; double errorWeight[256];
double errorRate[256]; double errorRate[256];
double maxErrorRate[256]; double maxErrorRate[256];
int numberOfFpgas;
int selectedFpga;
bool parallelConfigSupport;
char repr[64]; char repr[64];
}; };
@ -77,7 +84,7 @@ struct libztex_dev_list {
}; };
struct libztex_hash_data { struct libztex_hash_data {
uint32_t goldenNonce; uint32_t goldenNonce[2];
uint32_t nonce; uint32_t nonce;
uint32_t hash7; uint32_t hash7;
}; };

Loading…
Cancel
Save