| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872 |
- /*
- * Copyright 2013 Andrew Smith
- * Copyright 2013 bitfury
- *
- * Details for BitFury GPIO development of this driver are from
- * the chainminer code: https://github.com/bfsb/chainminer
- * (coz there seems to be no good documentation of it anywhere ...)
- * Thanks to the developer of chainminer for providing the source
- * to base the first version of the gpio/spi code in this BitFury chip
- * driver :)
- *
- * 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 "compat.h"
- #include "miner.h"
- #include "sha2.h"
- /*
- * This code has been tested on RPi running Raspbian
- * with a BlackArrow BitFury V1 16 chip GPIO board
- */
- #ifndef LINUX
- static void bab_detect(__maybe_unused bool hotplug)
- {
- }
- #else
- #include <unistd.h>
- #include <linux/spi/spidev.h>
- #include <sys/mman.h>
- #include <sys/ioctl.h>
- #include <fcntl.h>
- #define BAB_SPI_BUS 0
- #define BAB_SPI_CHIP 0
- #define BAB_SPI_SPEED 96000
- #define BAB_SPI_BUFSIZ 1024
- #define BAB_ADDR(_n) (*((babinfo->gpio) + (_n)))
- #define BAB_INP_GPIO(_n) BAB_ADDR((_n) / 10) &= (~(7 << (((_n) % 10) * 3)))
- #define BAB_OUT_GPIO(_n) BAB_ADDR((_n) / 10) |= (1 << (((_n) % 10) * 3))
- #define BAB_OUT_GPIO_V(_n, _v) BAB_ADDR((_n) / 10) |= (((_v) <= 3 ? (_v) + 4 : \
- ((_v) == 4 ? 3 : 2)) << (((_n) % 10) * 3))
- #define BAB_GPIO_SET BAB_ADDR(7)
- #define BAB_GPIO_CLR BAB_ADDR(10)
- #define BAB_GPIO_LEVEL BAB_ADDR(13)
- #define BAB_MAXCHIPS 256
- #define BAB_MAXBUF (BAB_MAXCHIPS * 512)
- #define BAB_MAXBANKS 4
- #define BAB_CORES 16
- #define BAB_X_COORD 21
- #define BAB_Y_COORD 36
- #define BAB_BREAK ((uint8_t *)"\04")
- #define BAB_ASYNC ((uint8_t *)"\05")
- #define BAB_SYNC ((uint8_t *)"\06")
- #define BAB_FFL " - from %s %s() line %d"
- #define BAB_FFL_HERE __FILE__, __func__, __LINE__
- #define BAB_FFL_PASS file, func, line
- #define bab_reset(_bank, _times) _bab_reset(babcgpu, babinfo, _bank, _times)
- #define bab_txrx(_buf, _siz, _det) _bab_txrx(babcgpu, babinfo, _buf, _siz, _det, BAB_FFL_HERE)
- #define bab_add_buf(_data) _bab_add_buf(babcgpu, babinfo, _data, sizeof(_data)-1, BAB_FFL_HERE)
- #define BAB_ADD_BREAK() _bab_add_buf(babcgpu, babinfo, BAB_BREAK, 1, BAB_FFL_HERE)
- #define BAB_ADD_ASYNC() _bab_add_buf(babcgpu, babinfo, BAB_ASYNC, 1, BAB_FFL_HERE)
- #define bab_config_reg(_reg, _ena) _bab_config_reg(babcgpu, babinfo, _reg, _ena, BAB_FFL_HERE)
- #define bab_add_data(_addr, _data, _siz) _bab_add_data(babcgpu, babinfo, _addr, (const uint8_t *)(_data), _siz, BAB_FFL_HERE)
- #define BAB_ADD_MIN 4
- #define BAB_ADD_MAX 128
- #define BAB_STATE_DONE 0
- #define BAB_STATE_READY 1
- #define BAB_STATE_SENDING 2
- #define BAB_STATE_SENT 3
- #define BAB_STATE_READING 4
- #define BAB_SPI_BUFFERS 2
- #define BAB_BASEA 4
- #define BAB_BASEB 61
- #define BAB_COUNTERS 16
- static const uint8_t bab_counters[BAB_COUNTERS] = {
- 64, 64,
- BAB_BASEA, BAB_BASEA+4,
- BAB_BASEA+2, BAB_BASEA+2+16,
- BAB_BASEA, BAB_BASEA+1,
- (BAB_BASEB)%65, (BAB_BASEB+1)%65,
- (BAB_BASEB+3)%65, (BAB_BASEB+3+16)%65,
- (BAB_BASEB+4)%65, (BAB_BASEB+4+4)%65,
- (BAB_BASEB+3+3)%65, (BAB_BASEB+3+1+3)%65
- };
- #define BAB_W1 16
- static const uint32_t bab_w1[BAB_W1] = {
- 0, 0, 0, 0xffffffff,
- 0x80000000, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0x00000280
- };
- #define BAB_W2 8
- static const uint32_t bab_w2[BAB_W2] = {
- 0x80000000, 0, 0, 0,
- 0, 0, 0, 0x00000100
- };
- #define BAB_TEST_DATA 19
- static const uint32_t bab_test_data[BAB_TEST_DATA] = {
- 0xb0e72d8e, 0x1dc5b862, 0xe9e7c4a6, 0x3050f1f5,
- 0x8a1a6b7e, 0x7ec384e8, 0x42c1c3fc, 0x8ed158a1,
- 0x8a1a6b7e, 0x6f484872, 0x4ff0bb9b, 0x12c97f07,
- 0xb0e72d8e, 0x55d979bc, 0x39403296, 0x40f09e84,
- 0x8a0bb7b7, 0x33af304f, 0x0b290c1a //, 0xf0c4e61f
- };
- //maximum number of chips on alternative bank
- // #define BANKCHIPS 64
- //maximum chip speed available for auto tuner
- //speed/nrate/hrate/watt
- // 53/ 97/ 100/ 84
- // 54/ 98/ 107/ 88
- // 55/ 99/ 115/ 93
- // 56/ 101/ 125/ 99
- #define BAB_MAXSPEED 57
- #define BAB_DEFSPEED 54
- #define BAB_MINSPEED 52
- #define MIDSTATE_BYTES 32
- #define MERKLE_OFFSET 64
- #define MERKLE_BYTES 12
- #define BLOCK_HEADER_BYTES 80
- #define MIDSTATE_UINTS (MIDSTATE_BYTES / sizeof(uint32_t))
- #define DATA_UINTS ((BLOCK_HEADER_BYTES / sizeof(uint32_t)) - 1)
- // Auto adjust
- #define BAB_AUTO_REG 0
- #define BAB_AUTO_VAL 0x01
- // iclk
- #define BAB_ICLK_REG 1
- #define BAB_ICLK_VAL 0x02
- // No fast clock
- #define BAB_FAST_REG 2
- #define BAB_FAST_VAL 0x04
- // Divide by 2
- #define BAB_DIV2_REG 3
- #define BAB_DIV2_VAL 0x08
- // Slow Clock
- #define BAB_SLOW_REG 4
- #define BAB_SLOW_VAL 0x10
- // No oclk
- #define BAB_OCLK_REG 6
- #define BAB_OCLK_VAL 0x20
- // Has configured
- #define BAB_CFGD_VAL 0x40
- #define BAB_DEFCONF (BAB_AUTO_VAL | \
- BAB_ICLK_VAL | \
- BAB_DIV2_VAL | \
- BAB_SLOW_VAL)
- #define BAB_REG_CLR_FROM 7
- #define BAB_REG_CLR_TO 11
- #define BAB_AUTO_SET(_c) ((_c) & BAB_AUTO_VAL)
- #define BAB_ICLK_SET(_c) ((_c) & BAB_ICLK_VAL)
- #define BAB_FAST_SET(_c) ((_c) & BAB_FAST_VAL)
- #define BAB_DIV2_SET(_c) ((_c) & BAB_DIV2_VAL)
- #define BAB_SLOW_SET(_c) ((_c) & BAB_SLOW_VAL)
- #define BAB_OCLK_SET(_c) ((_c) & BAB_OCLK_VAL)
- #define BAB_CFGD_SET(_c) ((_c) & BAB_CFGD_VAL)
- #define BAB_AUTO_BIT(_c) (BAB_AUTO_SET(_c) ? true : false)
- #define BAB_ICLK_BIT(_c) (BAB_ICLK_SET(_c) ? false : true)
- #define BAB_FAST_BIT(_c) (BAB_FAST_SET(_c) ? true : false)
- #define BAB_DIV2_BIT(_c) (BAB_DIV2_SET(_c) ? false : true)
- #define BAB_SLOW_BIT(_c) (BAB_SLOW_SET(_c) ? true : false)
- #define BAB_OCLK_BIT(_c) (BAB_OCLK_SET(_c) ? true : false)
- #define BAB_COUNT_ADDR 0x0100
- #define BAB_W1A_ADDR 0x1000
- #define BAB_W1B_ADDR 0x1400
- #define BAB_W2_ADDR 0x1900
- #define BAB_INP_ADDR 0x3000
- #define BAB_OSC_ADDR 0x6000
- #define BAB_REG_ADDR 0x7000
- // valid: 0x01 0x03 0x07 0x0F 0x1F 0x3F 0x7F 0xFF
- //max { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00 }
- //max { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00 }
- //avg { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00 }
- //slo { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00 }
- //min { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
- // good: 0x1F (97) 0x3F (104) 0x7F (109) 0xFF (104)
- #define BAB_OSC 8
- static const uint8_t bab_osc_bits[BAB_OSC] =
- { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
- static const uint8_t bab_reg_ena[4] = { 0xc1, 0x6a, 0x59, 0xe3 };
- static const uint8_t bab_reg_dis[4] = { 0x00, 0x00, 0x00, 0x00 };
- #define BAB_NONCE_OFFSETS 3
- static const uint32_t bab_nonce_offsets[] = {-0x800000, 0, -0x400000};
- struct bab_work_send {
- uint32_t midstate[MIDSTATE_UINTS];
- uint32_t ms3steps[MIDSTATE_UINTS];
- uint32_t merkle7;
- uint32_t ntime;
- uint32_t bits;
- };
- #define BAB_REPLY_NONCES 16
- struct bab_work_reply {
- uint32_t nonce[BAB_REPLY_NONCES];
- uint32_t jobsel;
- };
- #define MAX_BLISTS 4096
- typedef struct blist {
- struct blist *prev;
- struct blist *next;
- struct work *work;
- int nonces;
- } BLIST;
- #define MAX_RLISTS 256
- typedef struct rlist {
- struct rlist *prev;
- struct rlist *next;
- int chip;
- uint32_t nonce;
- bool first_second;
- } RLIST;
- struct bab_info {
- struct thr_info spi_thr;
- struct thr_info res_thr;
- pthread_mutex_t spi_lock;
- pthread_mutex_t res_lock;
- pthread_mutex_t did_lock;
- cglock_t blist_lock;
- // All GPIO goes through this
- volatile unsigned *gpio;
- int spifd;
- int chips;
- uint32_t chip_spis[BAB_MAXCHIPS+1];
- int buffer;
- int buf_status[BAB_SPI_BUFFERS];
- uint8_t buf_write[BAB_SPI_BUFFERS][BAB_MAXBUF];
- uint8_t buf_read[BAB_SPI_BUFFERS][BAB_MAXBUF];
- uint32_t buf_used[BAB_SPI_BUFFERS];
- uint32_t chip_off[BAB_SPI_BUFFERS][BAB_MAXCHIPS+1];
- uint32_t bank_off[BAB_SPI_BUFFERS][BAB_MAXBANKS+2];
- struct bab_work_send chip_input[BAB_MAXCHIPS];
- struct bab_work_reply chip_results[BAB_MAXCHIPS];
- struct bab_work_reply chip_prev[BAB_MAXCHIPS];
- uint8_t chip_fast[BAB_MAXCHIPS];
- uint8_t chip_conf[BAB_MAXCHIPS];
- uint8_t old_fast[BAB_MAXCHIPS];
- uint8_t old_conf[BAB_MAXCHIPS];
- uint8_t chip_bank[BAB_MAXCHIPS+1];
- uint8_t osc[BAB_OSC];
- int fixchip;
- /*
- * Ignore errors in the first work reply since
- * they may be from a previous run or random junk
- * There can be >100 with just a 16 chip board
- */
- uint32_t initial_ignored;
- bool nonce_before[BAB_MAXCHIPS];
- bool not_first_reply[BAB_MAXCHIPS];
- // Stats
- struct timeval chip_start[BAB_MAXCHIPS];
- int chip_busy[BAB_MAXCHIPS];
- uint64_t core_good[BAB_MAXCHIPS][BAB_CORES];
- uint64_t core_bad[BAB_MAXCHIPS][BAB_CORES];
- uint64_t chip_spie[BAB_MAXCHIPS]; // spi errors
- uint64_t chip_miso[BAB_MAXCHIPS]; // msio errors
- uint64_t chip_nonces[BAB_MAXCHIPS];
- uint64_t chip_good[BAB_MAXCHIPS];
- uint64_t chip_bad[BAB_MAXCHIPS];
- uint64_t chip_ncore[BAB_MAXCHIPS][BAB_X_COORD][BAB_Y_COORD];
- uint64_t untested_nonces;
- uint64_t tested_nonces;
- uint64_t new_nonces;
- uint64_t ok_nonces;
- uint64_t nonce_offset_count[BAB_NONCE_OFFSETS];
- uint64_t total_tests;
- uint64_t max_tests_per_nonce;
- uint64_t total_links;
- uint64_t max_links;
- int blist_count;
- int bfree_count;
- int work_count;
- int chip_count;
- BLIST *bfree_list;
- BLIST *work_list;
- BLIST *chip_list[BAB_MAXCHIPS];
- int rlist_count;
- int rfree_count;
- int res_count;
- RLIST *rfree_list;
- RLIST *res_list_head;
- RLIST *res_list_tail;
- struct timeval last_did;
- bool initialised;
- };
- static BLIST *new_blist_set(struct cgpu_info *babcgpu)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- BLIST *blist = NULL;
- int i;
- blist = calloc(MAX_BLISTS, sizeof(*blist));
- if (!blist)
- quithere(1, "Failed to calloc blist - when old count=%d", babinfo->blist_count);
- babinfo->blist_count += MAX_BLISTS;
- babinfo->bfree_count = MAX_BLISTS;
- blist[0].prev = NULL;
- blist[0].next = &(blist[1]);
- for (i = 1; i < MAX_BLISTS-1; i++) {
- blist[i].prev = &blist[i-1];
- blist[i].next = &blist[i+1];
- }
- blist[MAX_BLISTS-1].prev = &(blist[MAX_BLISTS-2]);
- blist[MAX_BLISTS-1].next = NULL;
- return blist;
- }
- static BLIST *next_work(struct cgpu_info *babcgpu, int chip)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- BLIST *bitem;
- cg_wlock(&babinfo->blist_lock);
- bitem = babinfo->work_list;
- if (bitem) {
- // Unlink it from work
- if (bitem->next)
- bitem->next->prev = NULL;
- babinfo->work_list = bitem->next;
- babinfo->work_count--;
- // Add it to the chip
- bitem->next = babinfo->chip_list[chip];
- bitem->prev = NULL;
- if (bitem->next)
- bitem->next->prev = bitem;
- babinfo->chip_list[chip] = bitem;
- babinfo->chip_count++;
- }
- cg_wunlock(&babinfo->blist_lock);
- return bitem;
- }
- static void discard_last(struct cgpu_info *babcgpu, int chip)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- BLIST *bitem;
- cg_wlock(&babinfo->blist_lock);
- bitem = babinfo->chip_list[chip];
- if (bitem) {
- // Unlink it from the chip
- if (bitem->next)
- bitem->next->prev = NULL;
- babinfo->chip_list[chip] = bitem->next;
- babinfo->chip_count--;
- // Put it in the free list
- bitem->next = babinfo->bfree_list;
- bitem->prev = NULL;
- if (bitem->next)
- bitem->next->prev = bitem;
- babinfo->bfree_list = bitem;
- babinfo->bfree_count++;
- }
- cg_wunlock(&babinfo->blist_lock);
- }
- static BLIST *store_work(struct cgpu_info *babcgpu, struct work *work)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- BLIST *bitem = NULL;
- int ran_out = 0;
- cg_wlock(&babinfo->blist_lock);
- if (babinfo->bfree_list == NULL) {
- ran_out = babinfo->blist_count;
- babinfo->bfree_list = new_blist_set(babcgpu);
- }
- // unlink from free
- bitem = babinfo->bfree_list;
- babinfo->bfree_list = babinfo->bfree_list->next;
- if (babinfo->bfree_list)
- babinfo->bfree_list->prev = NULL;
- babinfo->bfree_count--;
- // add to work
- bitem->next = babinfo->work_list;
- bitem->prev = NULL;
- if (bitem->next)
- bitem->next->prev = bitem;
- babinfo->work_list = bitem;
- babinfo->work_count++;
- bitem->work = work;
- bitem->nonces = 0;
- cg_wunlock(&babinfo->blist_lock);
- if (ran_out > 0) {
- applog(LOG_ERR, "%s%i: BLIST used count exceeded %d, now %d (work=%d chip=%d)",
- babcgpu->drv->name, babcgpu->device_id,
- ran_out, babinfo->blist_count,
- babinfo->work_count,
- babinfo->chip_count);
- }
- return bitem;
- }
- static void free_blist(struct cgpu_info *babcgpu, BLIST *bhead, int chip)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- struct work *work;
- BLIST *bitem;
- if (!bhead)
- return;
- // Unlink it from the chip
- cg_wlock(&babinfo->blist_lock);
- if (unlikely(bhead == babinfo->chip_list[chip])) {
- // Removing the chip head is an error
- bhead = bhead->next;
- babinfo->chip_list[chip]->next = NULL;
- } else
- bhead->prev->next = NULL;
- bitem = bhead;
- while (bitem) {
- babinfo->chip_count--;
- bitem = bitem->next;
- }
- cg_wunlock(&babinfo->blist_lock);
- while (bhead) {
- bitem = bhead;
- bhead = bitem->next;
- // add to free
- cg_wlock(&babinfo->blist_lock);
- bitem->next = babinfo->bfree_list;
- if (babinfo->bfree_list)
- babinfo->bfree_list->prev = bitem;
- bitem->prev = NULL;
- babinfo->bfree_list = bitem;
- babinfo->bfree_count++;
- work = bitem->work;
- cg_wunlock(&babinfo->blist_lock);
- work_completed(babcgpu, work);
- }
- }
- static RLIST *new_rlist_set(struct cgpu_info *babcgpu)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- RLIST *rlist = NULL;
- int i;
- rlist = calloc(MAX_RLISTS, sizeof(*rlist));
- if (!rlist)
- quithere(1, "Failed to calloc rlist - when old count=%d", babinfo->rlist_count);
- babinfo->rlist_count += MAX_RLISTS;
- babinfo->rfree_count = MAX_RLISTS;
- rlist[0].prev = NULL;
- rlist[0].next = &(rlist[1]);
- for (i = 1; i < MAX_RLISTS-1; i++) {
- rlist[i].prev = &rlist[i-1];
- rlist[i].next = &rlist[i+1];
- }
- rlist[MAX_RLISTS-1].prev = &(rlist[MAX_RLISTS-2]);
- rlist[MAX_RLISTS-1].next = NULL;
- return rlist;
- }
- static RLIST *store_nonce(struct cgpu_info *babcgpu, int chip, uint32_t nonce, bool first_second)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- RLIST *ritem = NULL;
- int ran_out = 0;
- mutex_lock(&(babinfo->res_lock));
- if (babinfo->rfree_list == NULL) {
- ran_out = babinfo->rlist_count;
- babinfo->rfree_list = new_rlist_set(babcgpu);
- }
- // unlink from rfree
- ritem = babinfo->rfree_list;
- babinfo->rfree_list = babinfo->rfree_list->next;
- if (babinfo->rfree_list)
- babinfo->rfree_list->prev = NULL;
- babinfo->rfree_count--;
- // add to head of results
- ritem->next = babinfo->res_list_head;
- ritem->prev = NULL;
- babinfo->res_list_head = ritem;
- if (ritem->next)
- ritem->next->prev = ritem;
- else
- babinfo->res_list_tail = ritem;
- babinfo->res_count++;
- ritem->chip = chip;
- ritem->nonce = nonce;
- ritem->first_second = first_second;
- mutex_unlock(&(babinfo->res_lock));
- if (ran_out > 0) {
- applog(LOG_ERR, "%s%i: RLIST used count exceeded %d, now %d (work=%d chip=%d)",
- babcgpu->drv->name, babcgpu->device_id,
- ran_out, babinfo->rlist_count,
- babinfo->work_count,
- babinfo->chip_count);
- }
- return ritem;
- }
- static bool oldest_nonce(struct cgpu_info *babcgpu, int *chip, uint32_t *nonce, bool *first_second)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- RLIST *ritem = NULL;
- bool found = false;
- mutex_lock(&(babinfo->res_lock));
- if (babinfo->res_list_tail) {
- // unlink from res
- ritem = babinfo->res_list_tail;
- if (ritem->prev) {
- ritem->prev->next = NULL;
- babinfo->res_list_tail = ritem->prev;
- } else
- babinfo->res_list_head = babinfo->res_list_tail = NULL;
- babinfo->res_count--;
- found = true;
- *chip = ritem->chip;
- *nonce = ritem->nonce;
- *first_second = ritem->first_second;
- // add to rfree
- ritem->next = babinfo->rfree_list;
- ritem->prev = NULL;
- if (ritem->next)
- ritem->next->prev = ritem;
- babinfo->rfree_list = ritem;
- babinfo->rfree_count++;
- }
- mutex_unlock(&(babinfo->res_lock));
- return found;
- }
- static void _bab_reset(__maybe_unused struct cgpu_info *babcgpu, struct bab_info *babinfo, int bank, int times)
- {
- const int banks[4] = { 18, 23, 24, 25 };
- int i;
- BAB_INP_GPIO(10);
- BAB_OUT_GPIO(10);
- BAB_INP_GPIO(11);
- BAB_OUT_GPIO(11);
- if (bank) {
- for (i = 0; i < 4; i++) {
- BAB_INP_GPIO(banks[i]);
- BAB_OUT_GPIO(banks[i]);
- if (bank == i+1)
- BAB_GPIO_SET = 1 << banks[i];
- else
- BAB_GPIO_CLR = 1 << banks[i];
- }
- cgsleep_us(4096);
- } else {
- for (i = 0; i < 4; i++)
- BAB_INP_GPIO(banks[i]);
- }
- BAB_GPIO_SET = 1 << 11;
- for (i = 0; i < times; i++) { // 1us = 1MHz
- BAB_GPIO_SET = 1 << 10;
- cgsleep_us(1);
- BAB_GPIO_CLR = 1 << 10;
- cgsleep_us(1);
- }
- BAB_GPIO_CLR = 1 << 11;
- BAB_INP_GPIO(11);
- BAB_INP_GPIO(10);
- BAB_INP_GPIO(9);
- BAB_OUT_GPIO_V(11, 0);
- BAB_OUT_GPIO_V(10, 0);
- BAB_OUT_GPIO_V(9, 0);
- }
- // TODO: handle a false return where this is called?
- static bool _bab_txrx(struct cgpu_info *babcgpu, struct bab_info *babinfo, int buf, uint32_t siz, bool detect_ignore, const char *file, const char *func, const int line)
- {
- int bank, i;
- uint32_t pos;
- struct spi_ioc_transfer tran;
- uintptr_t rbuf, wbuf;
- wbuf = (uintptr_t)(babinfo->buf_write[buf]);
- rbuf = (uintptr_t)(babinfo->buf_read[buf]);
- memset(&tran, 0, sizeof(tran));
- tran.delay_usecs = 0;
- tran.speed_hz = BAB_SPI_SPEED;
- i = 0;
- pos = 0;
- for (bank = 0; bank <= BAB_MAXBANKS; bank++) {
- if (babinfo->bank_off[buf][bank]) {
- bab_reset(bank, 64);
- break;
- }
- }
- if (unlikely(bank > BAB_MAXBANKS)) {
- applog(LOG_ERR, "%s%d: %s() failed to find a bank" BAB_FFL,
- babcgpu->drv->name, babcgpu->device_id,
- __func__, BAB_FFL_PASS);
- return false;
- }
- while (siz > 0) {
- tran.tx_buf = wbuf;
- tran.rx_buf = rbuf;
- tran.speed_hz = BAB_SPI_SPEED;
- if (pos == babinfo->bank_off[buf][bank]) {
- for (; ++bank <= BAB_MAXBANKS; ) {
- if (babinfo->bank_off[buf][bank] > pos) {
- bab_reset(bank, 64);
- break;
- }
- }
- }
- if (siz < BAB_SPI_BUFSIZ)
- tran.len = siz;
- else
- tran.len = BAB_SPI_BUFSIZ;
- if (pos < babinfo->bank_off[buf][bank] &&
- babinfo->bank_off[buf][bank] < (pos + tran.len))
- tran.len = babinfo->bank_off[buf][bank] - pos;
- for (; i < babinfo->chips; i++) {
- if (!babinfo->chip_off[buf][i])
- continue;
- if (babinfo->chip_off[buf][i] >= pos + tran.len) {
- tran.speed_hz = babinfo->chip_spis[i];
- break;
- }
- }
- if (unlikely(i > babinfo->chips)) {
- applog(LOG_ERR, "%s%d: %s() failed to find chip" BAB_FFL,
- babcgpu->drv->name, babcgpu->device_id,
- __func__, BAB_FFL_PASS);
- return false;
- }
- if (unlikely(babinfo->chip_spis[i] == BAB_SPI_SPEED)) {
- applog(LOG_DEBUG, "%s%d: %s() chip[%d] speed %d shouldn't be %d" BAB_FFL,
- babcgpu->drv->name, babcgpu->device_id,
- __func__, i, (int)babinfo->chip_spis[i],
- BAB_SPI_SPEED, BAB_FFL_PASS);
- }
- if (unlikely(tran.speed_hz == BAB_SPI_SPEED)) {
- applog(LOG_DEBUG, "%s%d: %s() transfer speed %d shouldn't be %d" BAB_FFL,
- babcgpu->drv->name, babcgpu->device_id,
- __func__, (int)tran.speed_hz,
- BAB_SPI_SPEED, BAB_FFL_PASS);
- }
- if (ioctl(babinfo->spifd, SPI_IOC_MESSAGE(1), (void *)&tran) < 0) {
- if (!detect_ignore || errno != 110) {
- applog(LOG_ERR, "%s%d: ioctl failed err=%d" BAB_FFL,
- babcgpu->drv->name, babcgpu->device_id,
- errno, BAB_FFL_PASS);
- }
- return false;
- }
- siz -= tran.len;
- wbuf += tran.len;
- rbuf += tran.len;
- pos += tran.len;
- }
- mutex_lock(&(babinfo->did_lock));
- cgtime(&(babinfo->last_did));
- mutex_unlock(&(babinfo->did_lock));
- return true;
- }
- static void _bab_add_buf_rev(__maybe_unused struct cgpu_info *babcgpu, struct bab_info *babinfo, const uint8_t *data, uint32_t siz, const char *file, const char *func, const int line)
- {
- uint8_t tmp;
- uint32_t now_used, i;
- int buf;
- buf = babinfo->buffer;
- now_used = babinfo->buf_used[buf];
- if (now_used + siz >= BAB_MAXBUF) {
- quitfrom(1, file, func, line,
- "%s() buffer %d limit of %d exceeded=%d siz=%d",
- __func__, buf, BAB_MAXBUF, now_used + siz, siz);
- }
- for (i = 0; i < siz; i++) {
- tmp = data[i];
- tmp = ((tmp & 0xaa)>>1) | ((tmp & 0x55) << 1);
- tmp = ((tmp & 0xcc)>>2) | ((tmp & 0x33) << 2);
- tmp = ((tmp & 0xf0)>>4) | ((tmp & 0x0f) << 4);
- babinfo->buf_write[buf][now_used + i] = tmp;
- }
- babinfo->buf_used[buf] += siz;
- }
- static void _bab_add_buf(__maybe_unused struct cgpu_info *babcgpu, struct bab_info *babinfo, const uint8_t *data, size_t siz, const char *file, const char *func, const int line)
- {
- uint32_t now_used;
- int buf;
- buf = babinfo->buffer;
- now_used = babinfo->buf_used[buf];
- if (now_used + siz >= BAB_MAXBUF) {
- quitfrom(1, file, func, line,
- "%s() buffer %d limit of %d exceeded=%d siz=%d",
- __func__, buf, BAB_MAXBUF, (int)(now_used + siz), (int)siz);
- }
- memcpy(&(babinfo->buf_write[buf][now_used]), data, siz);
- babinfo->buf_used[buf] += siz;
- }
- static void _bab_add_data(struct cgpu_info *babcgpu, struct bab_info *babinfo, uint32_t addr, const uint8_t *data, size_t siz, const char *file, const char *func, const int line)
- {
- uint8_t tmp[3];
- int trf_siz;
- if (siz < BAB_ADD_MIN || siz > BAB_ADD_MAX) {
- quitfrom(1, file, func, line,
- "%s() called with invalid siz=%d (min=%d max=%d)",
- __func__, (int)siz, BAB_ADD_MIN, BAB_ADD_MAX);
- }
- trf_siz = siz / 4;
- tmp[0] = (trf_siz - 1) | 0xE0;
- tmp[1] = (addr >> 8) & 0xff;
- tmp[2] = addr & 0xff;
- _bab_add_buf(babcgpu, babinfo, tmp, sizeof(tmp), BAB_FFL_PASS);
- _bab_add_buf_rev(babcgpu, babinfo, data, siz, BAB_FFL_PASS);
- }
- static void _bab_config_reg(struct cgpu_info *babcgpu, struct bab_info *babinfo, uint32_t reg, bool enable, const char *file, const char *func, const int line)
- {
- if (enable) {
- _bab_add_data(babcgpu, babinfo, BAB_REG_ADDR + reg*32,
- bab_reg_ena, sizeof(bab_reg_ena), BAB_FFL_PASS);
- } else {
- _bab_add_data(babcgpu, babinfo, BAB_REG_ADDR + reg*32,
- bab_reg_dis, sizeof(bab_reg_dis), BAB_FFL_PASS);
- }
- }
- static void bab_set_osc(struct bab_info *babinfo, int chip)
- {
- int fast, i;
- fast = babinfo->chip_fast[chip];
- for (i = 0; i < BAB_OSC && fast > BAB_OSC; i++, fast -= BAB_OSC) {
- babinfo->osc[i] = 0xff;
- }
- if (i < BAB_OSC && fast > 0 && fast <= BAB_OSC)
- babinfo->osc[i++] = bab_osc_bits[fast - 1];
- for (; i < BAB_OSC; i++)
- babinfo->osc[i] = 0x00;
- applog(LOG_DEBUG, "@osc(chip=%d) fast=%d 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", chip, fast, babinfo->osc[0], babinfo->osc[1], babinfo->osc[2], babinfo->osc[3], babinfo->osc[4], babinfo->osc[5], babinfo->osc[6], babinfo->osc[7]);
- }
- static bool bab_put(struct cgpu_info *babcgpu, struct bab_info *babinfo)
- {
- int buf, i, reg, bank = 0;
- babinfo->buffer = -1;
- mutex_lock(&(babinfo->spi_lock));
- if (babinfo->buf_status[0] == BAB_STATE_DONE) {
- babinfo->buffer = 0;
- } else if (babinfo->buf_status[1] == BAB_STATE_DONE) {
- babinfo->buffer = 1;
- } else if (babinfo->buf_status[0] == BAB_STATE_READY) {
- babinfo->buf_status[0] = BAB_STATE_DONE;
- babinfo->buffer = 0;
- } else if (babinfo->buf_status[1] == BAB_STATE_READY) {
- babinfo->buf_status[1] = BAB_STATE_DONE;
- babinfo->buffer = 1;
- }
- mutex_unlock(&(babinfo->spi_lock));
- if (babinfo->buffer == -1)
- return false;
- buf = babinfo->buffer;
- babinfo->buf_used[buf] = 0;
- memset(babinfo->bank_off[buf], 0, sizeof(babinfo->bank_off) / BAB_SPI_BUFFERS);
- BAB_ADD_BREAK();
- for (i = 0; i < babinfo->chips; i++) {
- if (babinfo->chip_bank[i] != bank) {
- babinfo->bank_off[buf][bank] = babinfo->buf_used[buf];
- bank = babinfo->chip_bank[i];
- BAB_ADD_BREAK();
- }
- if (i == babinfo->fixchip &&
- (BAB_CFGD_SET(babinfo->chip_conf[i]) ||
- !babinfo->chip_conf[i])) {
- bab_set_osc(babinfo, i);
- bab_add_data(BAB_OSC_ADDR, babinfo->osc, sizeof(babinfo->osc));
- bab_config_reg(BAB_ICLK_REG, BAB_ICLK_BIT(babinfo->chip_conf[i]));
- bab_config_reg(BAB_FAST_REG, BAB_FAST_BIT(babinfo->chip_conf[i]));
- bab_config_reg(BAB_DIV2_REG, BAB_DIV2_BIT(babinfo->chip_conf[i]));
- bab_config_reg(BAB_SLOW_REG, BAB_SLOW_BIT(babinfo->chip_conf[i]));
- bab_config_reg(BAB_OCLK_REG, BAB_OCLK_BIT(babinfo->chip_conf[i]));
- for (reg = BAB_REG_CLR_FROM; reg <= BAB_REG_CLR_TO; reg++)
- bab_config_reg(reg, false);
- if (babinfo->chip_conf[i]) {
- bab_add_data(BAB_COUNT_ADDR, bab_counters, sizeof(bab_counters));
- bab_add_data(BAB_W1A_ADDR, bab_w1, sizeof(bab_w1));
- bab_add_data(BAB_W1B_ADDR, bab_w1, sizeof(bab_w1)/2);
- bab_add_data(BAB_W2_ADDR, bab_w2, sizeof(bab_w2));
- babinfo->chip_conf[i] ^= BAB_CFGD_VAL;
- }
- babinfo->old_fast[i] = babinfo->chip_fast[i];
- babinfo->old_conf[i] = babinfo->chip_conf[i];
- } else {
- if (babinfo->old_fast[i] != babinfo->chip_fast[i]) {
- bab_set_osc(babinfo, i);
- bab_add_data(BAB_OSC_ADDR, babinfo->osc, sizeof(babinfo->osc));
- babinfo->old_fast[i] = babinfo->chip_fast[i];
- }
- if (babinfo->old_conf[i] != babinfo->chip_conf[i]) {
- if (BAB_ICLK_SET(babinfo->old_conf[i]) !=
- BAB_ICLK_SET(babinfo->chip_conf[i]))
- bab_config_reg(BAB_ICLK_REG,
- BAB_ICLK_BIT(babinfo->chip_conf[i]));
- if (BAB_FAST_SET(babinfo->old_conf[i]) !=
- BAB_FAST_SET(babinfo->chip_conf[i]))
- bab_config_reg(BAB_FAST_REG,
- BAB_FAST_BIT(babinfo->chip_conf[i]));
- if (BAB_DIV2_SET(babinfo->old_conf[i]) !=
- BAB_DIV2_SET(babinfo->chip_conf[i]))
- bab_config_reg(BAB_DIV2_REG,
- BAB_DIV2_BIT(babinfo->chip_conf[i]));
- if (BAB_SLOW_SET(babinfo->old_conf[i]) !=
- BAB_SLOW_SET(babinfo->chip_conf[i]))
- bab_config_reg(BAB_SLOW_REG,
- BAB_SLOW_BIT(babinfo->chip_conf[i]));
- if (BAB_OCLK_SET(babinfo->old_conf[i]) !=
- BAB_OCLK_SET(babinfo->chip_conf[i]))
- bab_config_reg(BAB_OCLK_REG,
- BAB_OCLK_BIT(babinfo->chip_conf[i]));
- babinfo->old_conf[i] = babinfo->chip_conf[i];
- }
- }
- babinfo->chip_off[buf][i] = babinfo->buf_used[buf] + 3;
- if (babinfo->chip_conf[i])
- bab_add_data(BAB_INP_ADDR, (uint8_t *)(&(babinfo->chip_input[i])),
- sizeof(babinfo->chip_input[i]));
- BAB_ADD_ASYNC();
- }
- babinfo->chip_off[buf][i] = babinfo->buf_used[buf];
- babinfo->bank_off[buf][bank] = babinfo->buf_used[buf];
- mutex_lock(&(babinfo->spi_lock));
- babinfo->buf_status[buf] = BAB_STATE_READY;
- mutex_unlock(&(babinfo->spi_lock));
- babinfo->fixchip = (babinfo->fixchip + 1) % babinfo->chips;
- return true;
- }
- static bool bab_get(__maybe_unused struct cgpu_info *babcgpu, struct bab_info *babinfo)
- {
- int buf, i;
- babinfo->buffer = -1;
- mutex_lock(&(babinfo->spi_lock));
- if (babinfo->buf_status[0] == BAB_STATE_SENT) {
- babinfo->buf_status[0] = BAB_STATE_READING;
- babinfo->buffer = 0;
- } else if (babinfo->buf_status[1] == BAB_STATE_SENT) {
- babinfo->buf_status[1] = BAB_STATE_READING;
- babinfo->buffer = 1;
- }
- mutex_unlock(&(babinfo->spi_lock));
- if (babinfo->buffer == -1)
- return false;
- buf = babinfo->buffer;
- for (i = 0; i < babinfo->chips; i++) {
- if (babinfo->chip_conf[i] & 0x7f) {
- memcpy((void *)&(babinfo->chip_results[i]),
- (void *)(babinfo->buf_read[buf] + babinfo->chip_off[buf][i]),
- sizeof(babinfo->chip_results[0]));
- }
- }
- mutex_lock(&(babinfo->spi_lock));
- babinfo->buf_status[buf] = BAB_STATE_DONE;
- mutex_unlock(&(babinfo->spi_lock));
- return true;
- }
- void bab_detect_chips(struct cgpu_info *babcgpu, struct bab_info *babinfo, int bank, int first, int last)
- {
- int buf, i, reg, j;
- if (sizeof(struct bab_work_send) != sizeof(bab_test_data)) {
- quithere(1, "struct bab_work_send (%d) and bab_test_data (%d)"
- " must be the same size",
- (int)sizeof(struct bab_work_send),
- (int)sizeof(bab_test_data));
- }
- memset(babinfo->bank_off, 0, sizeof(babinfo->bank_off));
- buf = babinfo->buffer = 0;
- babinfo->buf_used[buf] = 0;
- BAB_ADD_BREAK();
- for (i = first; i < last && i < BAB_MAXCHIPS; i++) {
- bab_set_osc(babinfo, i);
- bab_add_data(BAB_OSC_ADDR, babinfo->osc, sizeof(babinfo->osc));
- bab_config_reg(BAB_ICLK_REG, BAB_ICLK_BIT(babinfo->chip_conf[i]));
- bab_config_reg(BAB_FAST_REG, BAB_FAST_BIT(babinfo->chip_conf[i]));
- bab_config_reg(BAB_DIV2_REG, BAB_DIV2_BIT(babinfo->chip_conf[i]));
- bab_config_reg(BAB_SLOW_REG, BAB_SLOW_BIT(babinfo->chip_conf[i]));
- bab_config_reg(BAB_OCLK_REG, BAB_OCLK_BIT(babinfo->chip_conf[i]));
- for (reg = BAB_REG_CLR_FROM; reg <= BAB_REG_CLR_TO; reg++)
- bab_config_reg(reg, false);
- bab_add_data(BAB_COUNT_ADDR, bab_counters, sizeof(bab_counters));
- bab_add_data(BAB_W1A_ADDR, bab_w1, sizeof(bab_w1));
- bab_add_data(BAB_W1B_ADDR, bab_w1, sizeof(bab_w1)/2);
- bab_add_data(BAB_W2_ADDR, bab_w2, sizeof(bab_w2));
- babinfo->chip_off[buf][i] = babinfo->buf_used[buf] + 3;
- bab_add_data(BAB_INP_ADDR, bab_test_data, sizeof(bab_test_data));
- babinfo->chip_off[buf][i+1] = babinfo->buf_used[buf];
- babinfo->bank_off[buf][bank] = babinfo->buf_used[buf];
- babinfo->chips = i + 1;
- bab_txrx(buf, babinfo->buf_used[buf], false);
- babinfo->buf_used[buf] = 0;
- BAB_ADD_BREAK();
- for (j = first; j <= i; j++) {
- babinfo->chip_off[buf][j] = babinfo->buf_used[buf] + 3;
- BAB_ADD_ASYNC();
- }
- }
- buf = babinfo->buffer = 1;
- babinfo->buf_used[buf] = 0;
- BAB_ADD_BREAK();
- for (i = first; i < last && i < BAB_MAXCHIPS; i++) {
- babinfo->chip_off[buf][i] = babinfo->buf_used[buf] + 3;
- bab_add_data(BAB_INP_ADDR, bab_test_data, sizeof(bab_test_data));
- BAB_ADD_ASYNC();
- }
- babinfo->chip_off[buf][i] = babinfo->buf_used[buf];
- babinfo->bank_off[buf][bank] = babinfo->buf_used[buf];
- babinfo->chips = i;
- bab_txrx(buf, babinfo->buf_used[buf], true);
- babinfo->buf_used[buf] = 0;
- babinfo->chips = first;
- for (i = first; i < last && i < BAB_MAXCHIPS; i++) {
- uint32_t tmp[DATA_UINTS-1];
- memcpy(tmp, babinfo->buf_read[buf]+babinfo->chip_off[buf][i], sizeof(tmp));
- for (j = 0; j < BAB_SPI_BUFFERS; j++)
- babinfo->chip_off[j][i] = 0;
- for (j = 0; j < BAB_REPLY_NONCES; j++) {
- if (tmp[j] != 0xffffffff && tmp[j] != 0x00000000) {
- babinfo->chip_bank[i] = bank;
- babinfo->chips = i + 1;
- break;
- }
- }
- }
- for (i = first ; i < babinfo->chips; i++)
- babinfo->chip_bank[i] = bank;
- }
- static const char *bab_modules[] = {
- "i2c-dev",
- "i2c-bcm2708",
- "spidev",
- "spi-bcm2708",
- NULL
- };
- static const char *bab_memory = "/dev/mem";
- static int bab_memory_addr = 0x20200000;
- static struct {
- int request;
- int value;
- } bab_ioc[] = {
- { SPI_IOC_RD_MODE, 0 },
- { SPI_IOC_WR_MODE, 0 },
- { SPI_IOC_RD_BITS_PER_WORD, 8 },
- { SPI_IOC_WR_BITS_PER_WORD, 8 },
- { SPI_IOC_RD_MAX_SPEED_HZ, 1000000 },
- { SPI_IOC_WR_MAX_SPEED_HZ, 1000000 },
- { -1, -1 }
- };
- static bool bab_init_gpio(struct cgpu_info *babcgpu, struct bab_info *babinfo, int bus, int chip)
- {
- int i, err, memfd, data;
- char buf[64];
- for (i = 0; bab_modules[i]; i++) {
- snprintf(buf, sizeof(buf), "modprobe %s", bab_modules[i]);
- err = system(buf);
- if (err) {
- applog(LOG_ERR, "%s failed to modprobe %s (%d) - you need to be root?",
- babcgpu->drv->dname,
- bab_modules[i], err);
- goto bad_out;
- }
- }
- memfd = open(bab_memory, O_RDWR | O_SYNC);
- if (memfd < 0) {
- applog(LOG_ERR, "%s failed open %s (%d)",
- babcgpu->drv->dname,
- bab_memory, errno);
- goto bad_out;
- }
- babinfo->gpio = (volatile unsigned *)mmap(NULL, BAB_SPI_BUFSIZ,
- PROT_READ | PROT_WRITE,
- MAP_SHARED, memfd,
- bab_memory_addr);
- if (babinfo->gpio == MAP_FAILED) {
- close(memfd);
- applog(LOG_ERR, "%s failed mmap gpio (%d)",
- babcgpu->drv->dname,
- errno);
- goto bad_out;
- }
- close(memfd);
- snprintf(buf, sizeof(buf), "/dev/spidev%d.%d", bus, chip);
- babinfo->spifd = open(buf, O_RDWR);
- if (babinfo->spifd < 0) {
- applog(LOG_ERR, "%s failed to open spidev (%d)",
- babcgpu->drv->dname,
- errno);
- goto map_out;
- }
- babcgpu->device_path = strdup(buf);
- for (i = 0; bab_ioc[i].value != -1; i++) {
- data = bab_ioc[i].value;
- err = ioctl(babinfo->spifd, bab_ioc[i].request, (void *)&data);
- if (err < 0) {
- applog(LOG_ERR, "%s failed ioctl (%d) (%d)",
- babcgpu->drv->dname,
- i, errno);
- goto close_out;
- }
- }
- for (i = 0; i < BAB_MAXCHIPS; i++)
- babinfo->chip_spis[i] = (int)((1000000.0 / (100.0 + 31.0 * (i + 1))) * 1000);
- return true;
- close_out:
- close(babinfo->spifd);
- babinfo->spifd = 0;
- free(babcgpu->device_path);
- babcgpu->device_path = NULL;
- map_out:
- munmap((void *)(babinfo->gpio), BAB_SPI_BUFSIZ);
- babinfo->gpio = NULL;
- bad_out:
- return false;
- }
- static void bab_init_chips(struct cgpu_info *babcgpu, struct bab_info *babinfo)
- {
- bab_detect_chips(babcgpu, babinfo, 0, 0, BAB_MAXCHIPS);
- memcpy(babinfo->old_conf, babinfo->chip_conf, sizeof(babinfo->old_conf));
- memcpy(babinfo->old_fast, babinfo->chip_fast, sizeof(babinfo->old_fast));
- }
- static void bab_detect(bool hotplug)
- {
- struct cgpu_info *babcgpu = NULL;
- struct bab_info *babinfo = NULL;
- int i;
- if (hotplug)
- return;
- babcgpu = calloc(1, sizeof(*babcgpu));
- if (unlikely(!babcgpu))
- quithere(1, "Failed to calloc babcgpu");
- babcgpu->drv = &bab_drv;
- babcgpu->deven = DEV_ENABLED;
- babcgpu->threads = 1;
- babinfo = calloc(1, sizeof(*babinfo));
- if (unlikely(!babinfo))
- quithere(1, "Failed to calloc babinfo");
- babcgpu->device_data = (void *)babinfo;
- for (i = 0; i < BAB_MAXCHIPS; i++) {
- babinfo->chip_conf[i] = BAB_DEFCONF;
- babinfo->chip_fast[i] = BAB_DEFSPEED;
- }
- mutex_init(&babinfo->spi_lock);
- if (!bab_init_gpio(babcgpu, babinfo, BAB_SPI_BUS, BAB_SPI_CHIP))
- goto unalloc;
- applog(LOG_WARNING, "%s V1 testing for %d chips ...", babcgpu->drv->dname, BAB_MAXCHIPS);
- bab_init_chips(babcgpu, babinfo);
- applog(LOG_WARNING, "%s found %d chips", babcgpu->drv->dname, babinfo->chips);
- if (babinfo->chips == 0)
- goto cleanup;
- if (!add_cgpu(babcgpu))
- goto cleanup;
- mutex_init(&babinfo->res_lock);
- mutex_init(&babinfo->did_lock);
- cglock_init(&babinfo->blist_lock);
- babinfo->initialised = true;
- return;
- cleanup:
- close(babinfo->spifd);
- munmap((void *)(babinfo->gpio), BAB_SPI_BUFSIZ);
- unalloc:
- mutex_destroy(&babinfo->spi_lock);
- free(babinfo);
- free(babcgpu);
- }
- static void bab_identify(__maybe_unused struct cgpu_info *babcgpu)
- {
- }
- #define BAB_LONG_WAIT_uS 1200000
- #define BAB_WAIT_MSG_EVERY 10
- #define BAB_LONG_WAIT_SLEEP_uS 100000
- #define BAB_STD_WAIT_uS 3000
- // thread to do spi txrx
- static void *bab_spi(void *userdata)
- {
- struct cgpu_info *babcgpu = (struct cgpu_info *)userdata;
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- struct timeval start, stop;
- double wait;
- int i, buf, msgs;
- applog(LOG_DEBUG, "%s%i: SPIing...",
- babcgpu->drv->name, babcgpu->device_id);
- // Wait until we're ready
- while (babcgpu->shutdown == false) {
- if (babinfo->initialised) {
- break;
- }
- cgsleep_ms(3);
- }
- msgs = 0;
- cgtime(&start);
- while (babcgpu->shutdown == false) {
- buf = -1;
- mutex_lock(&(babinfo->spi_lock));
- for (i = 0; i < BAB_SPI_BUFFERS; i++) {
- if (babinfo->buf_status[i] == BAB_STATE_READY) {
- babinfo->buf_status[i] = BAB_STATE_SENDING;
- buf = i;
- cgtime(&start);
- break;
- }
- }
- mutex_unlock(&(babinfo->spi_lock));
- if (buf == -1) {
- cgtime(&stop);
- wait = us_tdiff(&stop, &start);
- if (wait > BAB_LONG_WAIT_uS) {
- if ((msgs++ % BAB_WAIT_MSG_EVERY) == 0) {
- applog(LOG_WARNING, "%s%i: SPI waiting %.0fus ...",
- babcgpu->drv->name,
- babcgpu->device_id,
- (float)wait);
- }
- }
- cgsleep_us(BAB_LONG_WAIT_SLEEP_uS);
- continue;
- }
- bab_txrx(buf, babinfo->buf_used[buf], false);
- cgtime(&stop);
- wait = us_tdiff(&stop, &start);
- if (wait < BAB_STD_WAIT_uS)
- cgsleep_us((uint64_t)(BAB_STD_WAIT_uS - wait));
- else if (wait > BAB_LONG_WAIT_uS) {
- applog(LOG_DEBUG, "%s%i: SPI waited %.0fus",
- babcgpu->drv->name, babcgpu->device_id,
- (float)wait);
- }
- mutex_lock(&(babinfo->spi_lock));
- babinfo->buf_status[i] = BAB_STATE_SENT;
- mutex_unlock(&(babinfo->spi_lock));
- msgs = 0;
- }
- return NULL;
- }
- static void bab_flush_work(struct cgpu_info *babcgpu)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- applog(LOG_DEBUG, "%s%i: flushing work",
- babcgpu->drv->name, babcgpu->device_id);
- mutex_lock(&(babinfo->did_lock));
- memset(&(babinfo->last_did), 0, sizeof(babinfo->last_did));
- mutex_unlock(&(babinfo->did_lock));
- }
- static void ms3steps(uint32_t *p)
- {
- uint32_t a, b, c, d, e, f, g, h, new_e, new_a;
- int i;
- a = p[0];
- b = p[1];
- c = p[2];
- d = p[3];
- e = p[4];
- f = p[5];
- g = p[6];
- h = p[7];
- for (i = 0; i < 3; i++) {
- new_e = p[i+16] + sha256_k[i] + h + CH(e,f,g) + SHA256_F2(e) + d;
- new_a = p[i+16] + sha256_k[i] + h + CH(e,f,g) + SHA256_F2(e) +
- SHA256_F1(a) + MAJ(a,b,c);
- d = c;
- c = b;
- b = a;
- a = new_a;
- h = g;
- g = f;
- f = e;
- e = new_e;
- }
- p[15] = a;
- p[14] = b;
- p[13] = c;
- p[12] = d;
- p[11] = e;
- p[10] = f;
- p[9] = g;
- p[8] = h;
- }
- #define DATA_MERKLE7 16
- #define DATA_NTIME 17
- #define DATA_BITS 18
- #define DATA_NONCE 19
- #define WORK_MERKLE7 (16*4)
- #define WORK_NTIME (17*4)
- #define WORK_BITS (18*4)
- #define WORK_NONCE (19*4)
- static uint32_t decnonce(uint32_t in)
- {
- uint32_t out;
- /* First part load */
- out = (in & 0xFF) << 24;
- in >>= 8;
- /* Byte reversal */
- in = (((in & 0xaaaaaaaa) >> 1) | ((in & 0x55555555) << 1));
- in = (((in & 0xcccccccc) >> 2) | ((in & 0x33333333) << 2));
- in = (((in & 0xf0f0f0f0) >> 4) | ((in & 0x0f0f0f0f) << 4));
- out |= (in >> 2) & 0x3FFFFF;
- /* Extraction */
- if (in & 1)
- out |= (1 << 23);
- if (in & 2)
- out |= (1 << 22);
- out -= 0x800004;
- return out;
- }
- /*
- * Find the matching work item by checking the nonce against each work
- * item for the chip
- * Discard any work items older than a match
- */
- static bool oknonce(struct thr_info *thr, struct cgpu_info *babcgpu, int chip, uint32_t nonce)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- BLIST *bitem;
- unsigned int links, tests;
- int i;
- babinfo->chip_nonces[chip]++;
- nonce = decnonce(nonce);
- /*
- * We can grab the head of the chip work queue and then
- * release the lock and follow it to the end
- * since the other thread will only add items above the
- * head - it wont touch the list->next pointers from the
- * head to the end - only the head->prev pointer may get
- * changed
- */
- cg_rlock(&babinfo->blist_lock);
- bitem = babinfo->chip_list[chip];
- cg_runlock(&babinfo->blist_lock);
- if (!bitem) {
- applog(LOG_ERR, "%s%i: chip %d has no work!",
- babcgpu->drv->name, babcgpu->device_id, chip);
- babinfo->untested_nonces++;
- return false;
- }
- babinfo->tested_nonces++;
- tests = 0;
- links = 0;
- while (bitem) {
- if (!bitem->work) {
- applog(LOG_ERR, "%s%i: chip %d bitem links %d has no work!",
- babcgpu->drv->name,
- babcgpu->device_id,
- chip, links);
- } else {
- for (i = 0; i < BAB_NONCE_OFFSETS; i++) {
- tests++;
- if (test_nonce(bitem->work, nonce + bab_nonce_offsets[i])) {
- submit_tested_work(thr, bitem->work);
- babinfo->nonce_offset_count[i]++;
- babinfo->chip_good[chip]++;
- bitem->nonces++;
- babinfo->new_nonces++;
- babinfo->ok_nonces++;
- free_blist(babcgpu, bitem->next, chip);
- babinfo->total_tests += tests;
- if (babinfo->max_tests_per_nonce < tests)
- babinfo->max_tests_per_nonce = tests;
- babinfo->total_links += links;
- if (babinfo->max_links < links)
- babinfo->max_links = links;
- return true;
- }
- }
- }
- bitem = bitem->next;
- links++;
- }
- if (babinfo->not_first_reply[chip]) {
- babinfo->chip_bad[chip]++;
- inc_hw_errors(thr);
- } else
- babinfo->initial_ignored++;
- return false;
- }
- // Results checking thread
- static void *bab_res(void *userdata)
- {
- struct cgpu_info *babcgpu = (struct cgpu_info *)userdata;
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- struct thr_info *thr = babcgpu->thr[0];
- bool first_second;
- uint32_t nonce;
- int chip;
- applog(LOG_DEBUG, "%s%i: Results...",
- babcgpu->drv->name, babcgpu->device_id);
- // Wait until we're ready
- while (babcgpu->shutdown == false) {
- if (babinfo->initialised) {
- break;
- }
- cgsleep_ms(3);
- }
- while (babcgpu->shutdown == false) {
- if (!oldest_nonce(babcgpu, &chip, &nonce, &first_second)) {
- cgsleep_ms(3);
- continue;
- }
- if (first_second)
- babinfo->not_first_reply[chip] = true;
- oknonce(thr, babcgpu, chip, nonce);
- }
- return NULL;
- }
- static bool bab_do_work(struct cgpu_info *babcgpu)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- int busy, newbusy, match, work_items = 0;
- int spi, mis, miso;
- int i, j;
- BLIST *bitem;
- bool res, got_a_nonce;
- for (i = 0; i < babinfo->chips; i++) {
- bitem = next_work(babcgpu, i);
- if (!bitem) {
- applog(LOG_ERR, "%s%i: short work list (%i) expected %d - discarded",
- babcgpu->drv->name, babcgpu->device_id,
- i, babinfo->chips);
- for (j = 0; j < i; i++)
- discard_last(babcgpu, j);
- return false;
- }
- memcpy((void *)&(babinfo->chip_input[i].midstate[0]),
- bitem->work->midstate, sizeof(bitem->work->midstate));
- memcpy((void *)&(babinfo->chip_input[i].merkle7),
- (void *)&(bitem->work->data[WORK_MERKLE7]), 12);
- ms3steps((void *)&(babinfo->chip_input[i]));
- work_items++;
- }
- // Send
- res = bab_put(babcgpu, babinfo);
- if (!res) {
- applog(LOG_DEBUG, "%s%i: couldn't put work ...",
- babcgpu->drv->name, babcgpu->device_id);
- }
- // Receive
- res = bab_get(babcgpu, babinfo);
- if (!res) {
- applog(LOG_DEBUG, "%s%i: didn't get work reply ...",
- babcgpu->drv->name, babcgpu->device_id);
- return false;
- }
- applog(LOG_DEBUG, "%s%i: Did get work reply ...",
- babcgpu->drv->name, babcgpu->device_id);
- spi = mis = miso = 0;
- for (i = 0; i < babinfo->chips; i++) {
- match = 0;
- newbusy = busy = babinfo->chip_busy[i];
- if (!babinfo->chip_conf[i])
- continue;
- for (j = 1; j < BAB_REPLY_NONCES; j++) {
- if (babinfo->chip_results[i].nonce[(busy+j) % BAB_REPLY_NONCES] !=
- babinfo->chip_prev[i].nonce[(busy+j) % BAB_REPLY_NONCES])
- newbusy = (busy+j) % BAB_REPLY_NONCES;
- else
- match++;
- }
- if (!match) {
- if (!miso) {
- mis++;
- // ignore for now ... babinfo->chip_miso[i]++;
- }
- miso = 1;
- continue;
- }
- miso = 0;
- if (babinfo->chip_results[i].jobsel != 0xffffffff &&
- babinfo->chip_results[i].jobsel != 0x00000000) {
- spi++;
- babinfo->chip_spie[i]++;
- applog(LOG_DEBUG, "%s%i: SPI ERROR on chip %d (0x%08x)",
- babcgpu->drv->name, babcgpu->device_id,
- i, babinfo->chip_results[i].jobsel);
- }
- // Not used yet
- // if (babinfo->chip_results[i].jobsel != babinfo->chip_prev[i].jobsel) {
- got_a_nonce = false;
- for (; newbusy != busy; busy = (busy + 1) % BAB_REPLY_NONCES) {
- if (babinfo->chip_results[i].nonce[busy] == 0xffffffff ||
- babinfo->chip_results[i].nonce[busy] == 0x00000000) {
- babinfo->chip_results[i].nonce[busy] = babinfo->chip_prev[i].nonce[busy];
- spi = 1;
- continue;
- }
- store_nonce(babcgpu, i,
- babinfo->chip_results[i].nonce[busy],
- babinfo->nonce_before[i]);
- got_a_nonce = true;
- }
- /*
- * We only care about this after the first reply we find a nonce
- * After that, the value has no more effect
- */
- if (got_a_nonce)
- babinfo->nonce_before[i] = true;
- mis += miso;
- babinfo->chip_miso[i] += miso;
- babinfo->chip_busy[i] = busy;
- }
- memcpy((void *)(&(babinfo->chip_prev[0])),
- (void *)(&(babinfo->chip_results[0])),
- sizeof(babinfo->chip_prev));
- applog(LOG_DEBUG, "Work: items:%d spi:%d miso:%d",
- work_items, spi, mis);
- return true;
- }
- static bool bab_thread_prepare(struct thr_info *thr)
- {
- struct cgpu_info *babcgpu = thr->cgpu;
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- if (thr_info_create(&(babinfo->spi_thr), NULL, bab_spi, (void *)babcgpu)) {
- applog(LOG_ERR, "%s%i: SPI thread create failed",
- babcgpu->drv->name, babcgpu->device_id);
- return false;
- }
- pthread_detach(babinfo->spi_thr.pth);
- /*
- * We require a seperate results checking thread since there is a lot
- * of work done checking the results multiple times - thus we don't
- * want that delay affecting sending/receiving work to/from the device
- */
- if (thr_info_create(&(babinfo->res_thr), NULL, bab_res, (void *)babcgpu)) {
- applog(LOG_ERR, "%s%i: Results thread create failed",
- babcgpu->drv->name, babcgpu->device_id);
- return false;
- }
- pthread_detach(babinfo->res_thr.pth);
- return true;
- }
- static void bab_shutdown(struct thr_info *thr)
- {
- struct cgpu_info *babcgpu = thr->cgpu;
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- int i;
- applog(LOG_DEBUG, "%s%i: shutting down",
- babcgpu->drv->name, babcgpu->device_id);
- for (i = 0; i < babinfo->chips; i++)
- // bab_shutdown(babcgpu, babinfo, i);
- ;
- babcgpu->shutdown = true;
- }
- static bool bab_queue_full(struct cgpu_info *babcgpu)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- struct work *work;
- bool ret;
- if (babinfo->work_count >= babinfo->chips)
- ret = true;
- else {
- work = get_queued(babcgpu);
- if (work)
- store_work(babcgpu, work);
- else
- // Avoid a hard loop when we can't get work fast enough
- cgsleep_ms(10);
- ret = false;
- }
- return ret;
- }
- /*
- * 1.0s per nonce = 4.2GH/s
- * So anything around 4GH/s or less per chip should be fine
- */
- #define BAB_STD_WORK_uS 1000000
- #define BAB_STD_DELAY_uS 30000
- /*
- * TODO: allow this to run through more than once - the second+
- * time not sending any new work unless a flush occurs since:
- * at the moment we have BAB_STD_WORK_uS latency added to earliest replies
- */
- static int64_t bab_scanwork(__maybe_unused struct thr_info *thr)
- {
- struct cgpu_info *babcgpu = thr->cgpu;
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- int64_t hashcount = 0;
- struct timeval now;
- double delay;
- bab_do_work(babcgpu);
- // Sleep now so we get the work "bab_queue_full()" just before we use it
- while (80085) {
- cgtime(&now);
- mutex_lock(&(babinfo->did_lock));
- delay = us_tdiff(&now, &(babinfo->last_did));
- mutex_unlock(&(babinfo->did_lock));
- if (delay < (BAB_STD_WORK_uS - BAB_STD_DELAY_uS))
- cgsleep_us(BAB_STD_DELAY_uS);
- else
- break;
- }
- if (babinfo->new_nonces) {
- hashcount += 0xffffffffull * babinfo->new_nonces;
- babinfo->new_nonces = 0;
- }
- return hashcount;
- }
- #define CHIPS_PER_STAT 16
- static struct api_data *bab_api_stats(struct cgpu_info *babcgpu)
- {
- struct bab_info *babinfo = (struct bab_info *)(babcgpu->device_data);
- struct api_data *root = NULL;
- char data[2048];
- char buf[32];
- int i, to, j;
- if (babinfo->initialised == false)
- return NULL;
- root = api_add_int(root, "Chips", &(babinfo->chips), true);
- for (i = 0; i < babinfo->chips; i += CHIPS_PER_STAT) {
- to = i + CHIPS_PER_STAT - 1;
- if (to >= babinfo->chips)
- to = babinfo->chips - 1;
- data[0] = '\0';
- for (j = i; j <= to; j++) {
- snprintf(buf, sizeof(buf),
- "%s%"PRIu64,
- j == i ? "" : " ",
- babinfo->chip_nonces[j]);
- strcat(data, buf);
- }
- snprintf(buf, sizeof(buf), "Nonces %d - %d", i, to);
- root = api_add_string(root, buf, data, true);
- data[0] = '\0';
- for (j = i; j <= to; j++) {
- snprintf(buf, sizeof(buf),
- "%s%"PRIu64,
- j == i ? "" : " ",
- babinfo->chip_good[j]);
- strcat(data, buf);
- }
- snprintf(buf, sizeof(buf), "Good %d - %d", i, to);
- root = api_add_string(root, buf, data, true);
- data[0] = '\0';
- for (j = i; j <= to; j++) {
- snprintf(buf, sizeof(buf),
- "%s%"PRIu64,
- j == i ? "" : " ",
- babinfo->chip_bad[j]);
- strcat(data, buf);
- }
- snprintf(buf, sizeof(buf), "Bad %d - %d", i, to);
- root = api_add_string(root, buf, data, true);
- data[0] = '\0';
- for (j = i; j <= to; j++) {
- snprintf(buf, sizeof(buf),
- "%s0x%02x",
- j == i ? "" : " ",
- (int)(babinfo->chip_conf[j]));
- strcat(data, buf);
- }
- snprintf(buf, sizeof(buf), "Conf %d - %d", i, to);
- root = api_add_string(root, buf, data, true);
- data[0] = '\0';
- for (j = i; j <= to; j++) {
- snprintf(buf, sizeof(buf),
- "%s0x%02x",
- j == i ? "" : " ",
- (int)(babinfo->chip_fast[j]));
- strcat(data, buf);
- }
- snprintf(buf, sizeof(buf), "Fast %d - %d", i, to);
- root = api_add_string(root, buf, data, true);
- }
- for (i = 0; i < BAB_NONCE_OFFSETS; i++) {
- snprintf(buf, sizeof(buf), "Nonce Offset 0x%08x", bab_nonce_offsets[i]);
- root = api_add_uint64(root, buf, &(babinfo->nonce_offset_count[i]), true);
- }
- root = api_add_uint64(root, "Tested", &(babinfo->tested_nonces), true);
- root = api_add_uint64(root, "Total Tests", &(babinfo->total_tests), true);
- root = api_add_uint64(root, "Max Tests", &(babinfo->max_tests_per_nonce), true);
- float avg = babinfo->tested_nonces ? (float)(babinfo->total_tests) /
- (float)(babinfo->tested_nonces) : 0;
- // TODO: add a API_AVG which is 3 places - double/float?
- root = api_add_volts(root, "Avg Tests", &avg, true);
- root = api_add_uint64(root, "Untested", &(babinfo->untested_nonces), true);
- root = api_add_uint64(root, "Work Links", &(babinfo->total_links), true);
- root = api_add_uint64(root, "Max Links", &(babinfo->max_links), true);
- avg = babinfo->tested_nonces ? (float)(babinfo->total_links) /
- (float)(babinfo->tested_nonces) : 0;
- root = api_add_volts(root, "Avg Links", &avg, true);
- root = api_add_uint32(root, "Initial Ignored", &(babinfo->initial_ignored), true);
- root = api_add_int(root, "BList Count", &(babinfo->blist_count), true);
- root = api_add_int(root, "BFree Count", &(babinfo->bfree_count), true);
- root = api_add_int(root, "Work Count", &(babinfo->work_count), true);
- root = api_add_int(root, "Chip Count", &(babinfo->chip_count), true);
- root = api_add_int(root, "RList Count", &(babinfo->rlist_count), true);
- root = api_add_int(root, "RFree Count", &(babinfo->rfree_count), true);
- root = api_add_int(root, "Result Count", &(babinfo->res_count), true);
- return root;
- }
- #endif
- struct device_drv bab_drv = {
- .drv_id = DRIVER_bab,
- .dname = "BlackArrowBitFuryGPIO",
- .name = "BaB",
- .drv_detect = bab_detect,
- #ifdef LINUX
- .get_api_stats = bab_api_stats,
- //TODO: .get_statline_before = get_bab_statline_before,
- .identify_device = bab_identify,
- .thread_prepare = bab_thread_prepare,
- .hash_work = hash_queued_work,
- .scanwork = bab_scanwork,
- .queue_full = bab_queue_full,
- .flush_work = bab_flush_work,
- .thread_shutdown = bab_shutdown
- #endif
- };
|