12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670 |
- /*
- * Copyright 2017-2021 vh
- * Copyright 2021-2022 sidehack
- * Copyright 2021-2023 kano
- *
- * 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 "driver-gekko.h"
- #include "crc.h"
- #include "compat.h"
- #include <unistd.h>
- #ifdef __GNUC__
- #if __GNUC__ >= 7
- #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
- #endif
- #endif
- // usleep reliability
- #if defined(__APPLE__)
- #define USLEEPMIN 2000
- #define USLEEPPLUS 200
- #elif defined (WIN32)
- #define USLEEPMIN 250
- #define USLEEPPLUS 100
- #else
- #define USLEEPMIN 200
- #define USLEEPPLUS 50
- #endif
- static bool compac_prepare(struct thr_info *thr);
- static pthread_mutex_t static_lock = PTHREAD_MUTEX_INITIALIZER;
- static bool last_widescreen;
- static uint8_t dev_init_count[0xffff] = {0};
- static uint8_t *init_count;
- static uint32_t stat_len;
- static uint32_t chip_max;
- #define MS2US(_n) ((_n) * 1000)
- // report averages and how far they overrun the requested time
- // linux would appear to be unable to handle less than 55us
- // on the RPi4 it would regularly sleep 3 times as long
- // thus code in general ignores sleeping anything less than 200us
- #define TUNE_CODE 1
- static void gekko_usleep(struct COMPAC_INFO *info, int usec)
- {
- #if TUNE_CODE
- struct timeval stt, fin;
- double td, fac;
- #endif
- // error for usleep()
- if (usec >= 1000000)
- {
- cgsleep_ms(usec / 1000);
- #if TUNE_CODE
- mutex_lock(&info->slock);
- info->inv++;
- mutex_unlock(&info->slock);
- #endif
- return;
- }
- #if TUNE_CODE
- cgtime(&stt);
- #endif
- usleep(usec);
- #if TUNE_CODE
- cgtime(&fin);
- td = us_tdiff(&fin, &stt);
- fac = (td / (double)usec);
- mutex_lock(&info->slock);
- if (td < usec)
- info->num0++;
- if (fac >= 1.5)
- {
- info->req1_5 += usec;
- info->fac1_5 += fac;
- info->num1_5++;
- }
- else
- {
- if (fac >= 1.1)
- {
- info->req1_1 += usec;
- info->fac1_1 += fac;
- info->num1_1++;
- }
- else
- {
- info->req += usec;
- info->fac += fac;
- info->num++;
- }
- }
- mutex_unlock(&info->slock);
- #endif
- }
- static float fbound(float value, float lower_bound, float upper_bound)
- {
- if (value < lower_bound)
- return lower_bound;
- if (value > upper_bound)
- return upper_bound;
- return value;
- }
- uint32_t bmcrc(unsigned char *ptr, uint32_t len)
- {
- unsigned char c[5] = {1, 1, 1, 1, 1};
- uint32_t i, c1, ptr_idx = 0;
- for (i = 0; i < len; i++) {
- c1 = c[1];
- c[1] = c[0];
- c[0] = c[4] ^ ((ptr[ptr_idx] & (0x80 >> (i % 8))) ? 1 : 0);
- c[4] = c[3];
- c[3] = c[2];
- c[2] = c1 ^ c[0];
- if (((i + 1) % 8) == 0)
- ptr_idx++;
- }
- return (c[4] * 0x10) | (c[3] * 0x08) | (c[2] * 0x04) | (c[1] * 0x02) | (c[0] * 0x01);
- }
- void dumpbuffer(struct cgpu_info *compac, int LOG_LEVEL, char *note, unsigned char *ptr, uint32_t len)
- {
- if (opt_log_output || LOG_LEVEL <= opt_log_level) {
- char str[2048];
- const char * hex = "0123456789ABCDEF";
- char * pout = str;
- unsigned int i = 0;
- for(; i < 768 && i < len - 1; ++i) {
- *pout++ = hex[(*ptr>>4)&0xF];
- *pout++ = hex[(*ptr++)&0xF];
- if (i % 42 == 41) {
- *pout = 0;
- pout = str;
- applog(LOG_LEVEL, "%i: %s %s: %s", compac->cgminer_id, compac->drv->name, note, str);
- } else {
- *pout++ = ':';
- }
- }
- *pout++ = hex[(*ptr>>4)&0xF];
- *pout++ = hex[(*ptr)&0xF];
- *pout = 0;
- applog(LOG_LEVEL, "%d: %s %d - %s: %s", compac->cgminer_id, compac->drv->name, compac->device_id, note, str);
- }
- }
- static int compac_micro_send(struct cgpu_info *compac, uint8_t cmd, uint8_t channel, uint8_t value)
- {
- struct COMPAC_INFO *info = compac->device_data;
- int bytes = 1;
- int read_bytes = 1;
- int micro_temp;
- uint8_t temp;
- unsigned short usb_val;
- __maybe_unused char null[255];
- // synchronous : safe to run in the listen thread.
- if (!info->micro_found) {
- return 0;
- }
- // Baud Rate : 500,000
- usb_val = (FTDI_BITMODE_CBUS << 8) | 0xF3; // low byte: bitmask - 1111 0011 - CB1(HI), CB0(HI)
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_BITMODE, usb_val, info->interface, C_SETMODEM);
- gekko_usleep(info, MS2US(2));
- //usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, 0x06, (FTDI_INDEX_BAUD_BTS & 0xff00) | info->interface, C_SETBAUD);
- info->cmd[0] = cmd | channel;
- info->cmd[1] = value;
- if (value != 0x00 || cmd == M2_SET_VCORE) {
- bytes = 2;
- }
- usb_read_timeout(compac, (char *)info->rx, 255, &read_bytes, 1, C_GETRESULTS);
- dumpbuffer(compac, LOG_INFO, "(micro) TX", info->cmd, bytes);
- usb_write(compac, (char *)info->cmd, bytes, &read_bytes, C_REQUESTRESULTS);
- memset(info->rx, 0, info->rx_len);
- usb_read_timeout(compac, (char *)info->rx, 1, &read_bytes, 5, C_GETRESULTS);
- if (read_bytes > 0) {
- dumpbuffer(compac, LOG_INFO, "(micro) RX", info->rx, read_bytes);
- switch (cmd) {
- case 0x20:
- temp = info->rx[0];
- micro_temp = 32 + 1.8 * temp;
- if (micro_temp != info->micro_temp) {
- info->micro_temp = micro_temp;
- applog(LOG_WARNING, "%d: %s %d - micro temp changed to %d°C / %.1f°F",
- compac->cgminer_id, compac->drv->name, compac->device_id, temp, info->micro_temp);
- }
- break;
- default:
- break;
- }
- }
- // Restore Baud Rate
- //usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, (info->bauddiv + 1), (FTDI_INDEX_BAUD_BTS & 0xff00) | info->interface, C_SETBAUD);
- usb_val = (FTDI_BITMODE_CBUS << 8) | 0xF2; // low byte: bitmask - 1111 0010 - CB1(HI), CB0(LO)
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_BITMODE, usb_val, info->interface, C_SETMODEM);
- gekko_usleep(info, MS2US(2));
- return read_bytes;
- }
- #define compac_send(_c, _r, _b, _crc) compac_send2(_c, _r, _b, _crc, NULL)
- static void compac_send2(struct cgpu_info *compac, unsigned char *req_tx, uint32_t bytes, uint32_t crc_bits, __maybe_unused char *msg)
- {
- struct COMPAC_INFO *info = compac->device_data;
- int read_bytes = 1;
- unsigned int i, off = 0;
- // leave original buffer intact
- if (info->asic_type == BM1397)
- {
- info->cmd[0] = 0x55;
- info->cmd[1] = 0xAA;
- off = 2;
- }
- for (i = 0; i < bytes; i++)
- info->cmd[i+off] = req_tx[i];
- bytes += off;
- info->cmd[bytes-1] |= bmcrc(req_tx, crc_bits);
- #if 0
- if (msg == NULL)
- msg = "null";
- applog(LOG_ERR, "%s() %d: %s %d - Send len %3u (%s)", __func__,
- compac->cgminer_id, compac->drv->name, compac->device_id, bytes, msg);
- applog(LOG_ERR, "%s() [%02x %02x %02x %02x %02x %02x %02x %02x]", __func__,
- info->cmd[0], info->cmd[1], info->cmd[2], info->cmd[3], info->cmd[4], info->cmd[5], info->cmd[6], info->cmd[7]);
- applog(LOG_ERR, "%s() [%02x %02x %02x %02x %02x %02x %02x %02x]", __func__,
- info->cmd[8], info->cmd[9], info->cmd[10], info->cmd[11], info->cmd[12], info->cmd[13], info->cmd[14], info->cmd[15]);
- #endif
- int log_level = (bytes < info->task_len) ? LOG_INFO : LOG_INFO;
- dumpbuffer(compac, log_level, "TX", info->cmd, bytes);
- usb_write(compac, (char *)(info->cmd), bytes, &read_bytes, C_REQUESTRESULTS);
- //let the usb frame propagate
- if (info->asic_type == BM1397)
- gekko_usleep(info, info->usb_prop);
- else
- gekko_usleep(info, MS2US(1));
- }
- static float limit_freq(struct COMPAC_INFO *info, float freq, bool zero)
- {
- switch(info->ident)
- {
- case IDENT_BSC:
- case IDENT_GSC:
- case IDENT_BSD:
- case IDENT_GSD:
- case IDENT_BSE:
- case IDENT_GSE:
- freq = fbound(freq, info->freq_base, 500);
- break;
- case IDENT_GSH:
- case IDENT_GSI:
- freq = fbound(freq, 50, 900);
- break;
- case IDENT_GSF:
- case IDENT_GSFM:
- // allow 0 also if zero is true - coded obviously
- if (zero && freq == 0)
- freq = 0;
- else
- freq = fbound(freq, 100, 800);
- break;
- default:
- // 'should' never happen ...
- freq = fbound(freq, 100, 300);
- break;
- }
- return freq;
- }
- static void ping_freq(struct cgpu_info *compac, int asic)
- {
- struct COMPAC_INFO *info = compac->device_data;
- bool ping = false;
- if (info->asic_type == BM1397)
- {
- unsigned char pingall[] = {0x52, 0x05, 0x00, BM1397FREQ, 0x00};
- compac_send2(compac, pingall, sizeof(pingall), 8 * sizeof(pingall) - 8, "pingfreq");
- ping = true;
- }
- else if (info->asic_type == BM1387)
- {
- unsigned char buffer[] = {0x44, 0x05, 0x00, 0x0C, 0x00}; // PLL_PARAMETER
- buffer[2] = (0x100 / info->chips) * asic;
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 8);
- ping = true;
- }
- else if (info->asic_type == BM1384)
- {
- unsigned char buffer[] = {0x04, 0x00, 0x04, 0x00};
- buffer[1] = (0x100 / info->chips) * asic;
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 5);
- ping = true;
- }
- if (ping)
- {
- cgtime(&info->last_frequency_ping);
- cgtime(&(info->asics[asic].last_frequency_ping));
- }
- }
- static void gsf_calc_nb2c(struct cgpu_info *compac)
- {
- struct COMPAC_INFO *info = compac->device_data;
- int c, i, j;
- double fac;
- if (info->chips == 1)
- {
- // default all 0 is correct
- info->nb2c_setup = true;
- }
- else if (info->chips == 6)
- {
- // groups of 4
- fac = CHIPPY1397(info, 1) / 4.0;
- for (i = 0; i < 256; i += 64)
- {
- for (j = 0; j < 64; j++)
- {
- c = (int)((double)j / fac);
- if (c >= (int)(info->chips))
- c = info->chips - 1;
- info->nb2chip[i + j] = c;
- }
- }
- info->nb2c_setup = true;
- }
- }
- static void gc_wipe(struct GEKKOCHIP *gc, struct timeval *now)
- {
- // clear out everything
- gc->zerosec = now->tv_sec;
- gc->offset = 0;
- memset(gc->noncenum, 0, sizeof(gc->noncenum));
- gc->noncesum = 0;
- gc->last = 0;
- }
- static void gc_wipe_all(struct COMPAC_INFO *info, struct timeval *now, bool locked)
- {
- int i;
- if (!locked)
- mutex_lock(&info->ghlock);
- for (i = 0; i < (int)(info->chips); i++)
- gc_wipe(&(info->asics[i].gc), now);
- if (!locked)
- mutex_unlock(&info->ghlock);
- }
- // update asic->gc offset as at 'now' and correct values
- // info must be locked, wipe creates a new data set
- static void gc_offset(struct COMPAC_INFO *info, struct ASIC_INFO *asic, struct timeval *now, bool wipe, bool locked)
- {
- struct GEKKOCHIP *gc = &(asic->gc);
- time_t delta;
- if (!locked)
- mutex_lock(&info->ghlock);
- // wipe or delta != 0
- if (wipe || !CHCMP(gc->zerosec, now->tv_sec))
- {
- // clear some/all delta data
- delta = CHBASE(now->tv_sec) - CHBASE(gc->zerosec);
- // if time goes back, also reset everything
- // a forward jump of CHNUM will reset the whole buffer
- if (wipe || delta < 0 || delta >= CHNUM)
- gc_wipe(gc, now);
- else
- {
- // delta is > 0, but usually always 1 unless,
- // due to asic failure, a 10 minutes had no nonces
- // however the loop will total 1 iteration each
- // 10 minutes elapsed real time e.g. if not called
- // for 30 minutes, it will loop 3 times
- // there is also a CHNUM-1 limit on that
- gc->zerosec = now->tv_sec;
- // clear out the old values
- do
- {
- gc->offset = CHOFF(gc->offset+1);
- gc->noncesum -= gc->noncenum[CHOFF(gc->offset)];
- gc->noncenum[CHOFF(gc->offset)] = 0;
- if (gc->last < (CHNUM-1))
- gc->last++;
- }
- while (--delta > 0);
- }
- }
- // if there's been no nonces up to now, history must already be all zero
- // so just remove history
- if (gc->noncesum == 0 && gc->last > 0)
- gc->last = 0;
- if (!locked)
- mutex_unlock(&info->ghlock);
- }
- // update info->gh offset as at 'now' and correct values
- // info must be locked, wipe creates a new data set and also wipes all asic->gc
- static void gh_offset(struct COMPAC_INFO *info, struct timeval *now, bool wipe, bool locked)
- {
- struct GEKKOHASH *gh = &(info->gh);
- time_t delta;
- int i;
- if (!locked)
- mutex_lock(&info->ghlock);
- // first time in, wipe is ignored (it's already all zero)
- if (gh->zerosec == 0)
- {
- gh->zerosec = now->tv_sec;
- for (i = 0; i < (int)(info->chips); i++)
- info->asics[i].gc.zerosec = now->tv_sec;
- }
- else
- {
- if (wipe)
- gc_wipe_all(info, now, true);
- // wipe or delta != 0
- if (wipe || gh->zerosec != now->tv_sec)
- {
- // clear some/all delta data
- delta = now->tv_sec - gh->zerosec;
- // if time goes back, also reset everything
- // N.B. a forward time jump between 2 and GHLIMsec
- // seconds will reduce the hash rate value
- // but GHLIMsec or more will reset the whole buffer
- if (wipe || delta < 0 || delta >= GHLIMsec)
- {
- // clear out everything
- gh->zerosec = now->tv_sec;
- gh->offset = 0;
- memset(gh->diff, 0, sizeof(gh->diff));
- memset(gh->firstt, 0, sizeof(gh->firstt));
- memset(gh->firstd, 0, sizeof(gh->firstd));
- memset(gh->lastt, 0, sizeof(gh->lastt));
- memset(gh->noncenum, 0, sizeof(gh->noncenum));
- gh->diffsum = 0;
- gh->noncesum = 0;
- gh->last = 0;
- }
- else
- {
- // delta is > 0, but usually always 1 unless,
- // due to asic failure, a second had no nonces
- // however the loop will total 1 iteration each
- // second elapsed real time e.g. if not called
- // for 3 seconds, it will loop 3 times
- // there is also a GHLIMsec-1 limit on that
- gh->zerosec = now->tv_sec;
- // clear out the old values
- do
- {
- gh->offset = GHOFF(gh->offset+1);
- gh->diffsum -= gh->diff[GHOFF(gh->offset)];
- gh->diff[GHOFF(gh->offset)] = 0;
- gh->noncesum -= gh->noncenum[GHOFF(gh->offset)];
- gh->noncenum[GHOFF(gh->offset)] = 0;
- gh->firstt[GHOFF(gh->offset)].tv_sec = 0;
- gh->firstt[GHOFF(gh->offset)].tv_usec = 0;
- gh->firstd[GHOFF(gh->offset)] = 0;
- gh->lastt[GHOFF(gh->offset)].tv_sec = 0;
- gh->lastt[GHOFF(gh->offset)].tv_usec = 0;
- if (gh->last < (GHNUM-1))
- gh->last++;
- }
- while (--delta > 0);
- }
- }
- }
- // if there's been no nonces up to now, history must already be all zero
- // so just remove history
- if (gh->noncesum == 0 && gh->last > 0)
- gh->last = 0;
- // this also handles the issue of a nonce-less wipe with a high
- // now->tv_usec and if the first nonce comes in during the next second.
- // without setting 'last=0' the previous empty full second(s) will
- // always be included in the elapsed time used to calc the hash rate
- if (!locked)
- mutex_unlock(&info->ghlock);
- }
- // update info->gh with a new nonce as at 'now' (diff=info->difficulty)
- // info must be locked, wipe creates a new data set with the single nonce
- static void add_gekko_nonce(struct COMPAC_INFO *info, struct ASIC_INFO *asic, struct timeval *now)
- {
- struct GEKKOHASH *gh = &(info->gh);
- mutex_lock(&info->ghlock);
- gh_offset(info, now, false, true);
- if (gh->diff[gh->offset] == 0)
- {
- gh->firstt[gh->offset].tv_sec = now->tv_sec;
- gh->firstt[gh->offset].tv_usec = now->tv_usec;
- gh->firstd[gh->offset] = info->difficulty;
- }
- gh->lastt[gh->offset].tv_sec = now->tv_sec;
- gh->lastt[gh->offset].tv_usec = now->tv_usec;
- gh->diff[gh->offset] += info->difficulty;
- gh->diffsum += info->difficulty;
- (gh->noncenum[gh->offset])++;
- (gh->noncesum)++;
- if (asic != NULL)
- {
- struct GEKKOCHIP *gc = &(asic->gc);
- gc_offset(info, asic, now, false, true);
- (gc->noncenum[gc->offset])++;
- (gc->noncesum)++;
- }
- mutex_unlock(&info->ghlock);
- }
- // calculate MH/s hashrate, info must be locked
- // value is 0.0 if there's no useful data
- // caller check info->gh.last for history size used and info->gh.noncesum-1
- // for the amount of data used (i.e. accuracy of the hash rate)
- static double gekko_gh_hashrate(struct COMPAC_INFO *info, struct timeval *now, bool locked)
- {
- struct GEKKOHASH *gh = &(info->gh);
- struct timeval age, end;
- int zero, last;
- uint64_t delta;
- double ghr, old;
- ghr = 0.0;
- if (!locked)
- mutex_lock(&info->ghlock);
- // can't be calculated with only one nonce
- if (gh->diffsum > 0 && gh->noncesum > 1)
- {
- gh_offset(info, now, false, true);
- if (gh->diffsum > 0 && gh->noncesum > 1)
- {
- // offset of 'now'
- zero = gh->offset;
- // offset of oldest nonce
- last = GHOFF(zero - gh->last);
- if (gh->diff[last] != 0)
- {
- // from the oldest nonce, excluding it's diff
- delta = gh->firstd[last];
- age.tv_sec = gh->firstt[last].tv_sec;
- age.tv_usec = gh->firstt[last].tv_usec;
- }
- else
- {
- // if last is empty, use the start time of last
- delta = 0;
- age.tv_sec = gh->zerosec - (GHNUM - 1);
- age.tv_usec = 0;
- }
- // up to the time of the newest nonce as long as it
- // was curr or prev second, otherwise use now
- if (gh->diff[zero] != 0)
- {
- // time of the newest nonce found this second
- end.tv_sec = gh->lastt[zero].tv_sec;
- end.tv_usec = gh->lastt[zero].tv_usec;
- }
- else
- {
- // unexpected ... no recent nonces ...
- if (gh->diff[GHOFF(zero-1)] == 0)
- {
- end.tv_sec = now->tv_sec;
- end.tv_usec = now->tv_usec;
- }
- else
- {
- // time of the newest nonce found this second-1
- end.tv_sec = gh->lastt[GHOFF(zero-1)].tv_sec;
- end.tv_usec = gh->lastt[GHOFF(zero-1)].tv_usec;
- }
- }
- old = tdiff(&end, &age);
- if (old > 0.0)
- {
- ghr = (double)(gh->diffsum - delta)
- * (pow(2.0, 32.0) / old) / 1.0e6;
- }
- }
- }
- if (!locked)
- mutex_unlock(&info->ghlock);
- return ghr;
- }
- static void job_offset(struct COMPAC_INFO *info, struct timeval *now, bool wipe, bool locked)
- {
- struct GEKKOJOB *job = &(info->job);
- time_t delta;
- int jobnow;
- jobnow = JOBTIME(now->tv_sec);
- if (!locked)
- mutex_lock(&info->joblock);
- // first time in, wipe is ignored (it's already all zero)
- if (job->zeromin == 0)
- job->zeromin = jobnow;
- else
- {
- // wipe or delta != 0
- if (wipe || job->zeromin != jobnow)
- {
- // clear some/all delta data
- delta = jobnow - job->zeromin;
- // if time goes back, also reset everything
- // N.B. a forward time jump between 2 and JOBLIMn
- // seconds will reduce the job rate value
- // but JOBLIMn or more will reset the whole buffer
- if (wipe || delta < 0 || delta >= JOBLIMn)
- {
- // clear out everything
- job->zeromin = jobnow;
- job->lastjob.tv_sec = 0;
- job->lastjob.tv_usec = 0;
- job->offset = 0;
- memset(job->firstj, 0, sizeof(job->firstj));
- memset(job->lastj, 0, sizeof(job->lastj));
- memset(job->jobnum, 0, sizeof(job->jobnum));
- memset(job->avgms, 0, sizeof(job->avgms));
- memset(job->minms, 0, sizeof(job->minms));
- memset(job->maxms, 0, sizeof(job->maxms));
- job->jobsnum = 0;
- job->last = 0;
- }
- else
- {
- // delta is > 0, but usually always 1 unless,
- // due to asic or pool failure, a minute had no jobs
- // however the loop will total 1 iteration each
- // minute elapsed real time e.g. if not called
- // for 2 minutes, it will loop 2 times
- // there is also a JOBLIMn-1 limit on that
- job->zeromin = jobnow;
- // clear out the old values
- do
- {
- job->offset = JOBOFF(job->offset+1);
- job->firstj[JOBOFF(job->offset)].tv_sec = 0;
- job->firstj[JOBOFF(job->offset)].tv_usec = 0;
- job->lastj[JOBOFF(job->offset)].tv_sec = 0;
- job->lastj[JOBOFF(job->offset)].tv_usec = 0;
- job->jobsnum -= job->jobnum[JOBOFF(job->offset)];
- job->jobnum[JOBOFF(job->offset)] = 0;
- job->avgms[JOBOFF(job->offset)] = 0;
- job->minms[JOBOFF(job->offset)] = 0;
- job->maxms[JOBOFF(job->offset)] = 0;
- if (job->last < (JOBMIN-1))
- job->last++;
- }
- while (--delta > 0);
- }
- }
- }
- // if there's been no jobs up to now, history must already be all zero
- // so just remove history
- if (job->jobsnum == 0 && job->last > 0)
- job->last = 0;
- // this also handles the issue of a job-less wipe with a high
- // now->tv_usec and if the first job comes in during the next minute.
- // without setting 'last=0' the previous empty full minute will
- // always be included in the elapsed time used to calc the job rate
- if (!locked)
- mutex_unlock(&info->joblock);
- }
- // update info->job with a job as at 'now'
- // info must be locked, wipe creates a new empty data set
- static void add_gekko_job(struct COMPAC_INFO *info, struct timeval *now, bool wipe)
- {
- struct GEKKOJOB *job = &(info->job);
- bool firstjob;
- double avg;
- double ms;
- mutex_lock(&info->joblock);
- job_offset(info, now, wipe, true);
- if (!wipe)
- {
- if (job->jobnum[job->offset] == 0)
- {
- job->firstj[job->offset].tv_sec = now->tv_sec;
- job->firstj[job->offset].tv_usec = now->tv_usec;
- firstjob = true;
- }
- else
- firstjob = false;
- job->lastj[job->offset].tv_sec = now->tv_sec;
- job->lastj[job->offset].tv_usec = now->tv_usec;
- // first job time in each offset gets ignored
- // this is only necessary for the very first job,
- // but easier to do it for every offset group
- if (firstjob)
- {
- // already true
- // job->avgms[job->offset] = 0.0;
- // job->minms[job->offset] = 0.0;
- // job->maxms[job->offset] = 0.0;
- }
- else
- {
- avg = job->avgms[job->offset] * (double)(job->jobnum[job->offset] - 1);
- ms = (double)(now->tv_sec - job->lastjob.tv_sec) * 1000.0;
- ms += (double)(now->tv_usec - job->lastjob.tv_usec) / 1000.0;
- // jobnum[] must be > 0
- job->avgms[job->offset] = (avg + ms) / (double)(job->jobnum[job->offset]);
- if (job->minms[job->offset] == 0.0)
- {
- job->minms[job->offset] = ms;
- job->maxms[job->offset] = ms;
- }
- else
- {
- if (ms < job->minms[job->offset])
- job->minms[job->offset] = ms;
- if (job->maxms[job->offset] < ms)
- job->maxms[job->offset] = ms;
- }
- }
- (job->jobnum[job->offset])++;
- (job->jobsnum)++;
- job->lastjob.tv_sec = now->tv_sec;
- job->lastjob.tv_usec = now->tv_usec;
- }
- mutex_unlock(&info->joblock);
- }
- // ignore nonces for this many work items after the ticket change
- #define TICKET_DELAY 8
- // allow this many nonces below the ticket value in case of work swap delays
- // N.B. if the chip mask is half the wanted value,
- // roughly 85% of shares will be low since CDF 190% = 0.850
- // with the lowest nonce_count of 150 below for diff 2,
- // TICKET_BLOW_LIM 4 will always be exceeded if incorrectly set to diff 1
- #define TICKET_BELOW_LIM 4
- struct TICKET_INFO {
- uint32_t diff; // work diff value
- uint32_t ticket_mask; // ticket mask to ensure work diff
- int nonce_count; // CDF[Erl] nonces must have 1 below low_limit
- double low_limit; // must be a diff below this or ticket is too hi
- double hi_limit; // a diff below this means ticket is too low
- // set to .1 below diff to avoid any rounding
- uint32_t cclimit; // chips x cores limit i.e. required to go above 16
- };
- // ticket restart checks allowed before forced to diff=1
- #define MAX_TICKET_CHECK 3
- // ticket values, diff descending. List values rather than calc them
- // end comments are how long at given task/sec (15 ~= 60 1diff nonce/sec = ~260GH/s)
- // testing should take and chance of failure
- // though it will retry MAX_TICKET_CHECK times so shouldn't give up in the
- // exceedingly rare occasion where it fails once due to bad luck
- // limit to max diff of 16 unless the chips x cores is a bit better than a GSF/GSFM
- // to ensure enough nonces are coming back to identify status changes/issues
- // the luck calculation is the chance all nonce diff values will be above low_limit
- // after nonce_count nonces i.e. after nonce_count nonces there should be a nonce
- // below low_limit, or the ticket mask is actually higher than it was set to
- // the gsl function is cdf_gamma_Q(nonces, nonces, low_limit/diff)
- static struct TICKET_INFO ticket_1397[] =
- {
- { 64, 0xfc, 20000, 65.9, 63.9, 2600 }, // 90 59.3m Erlang=1.6x10-5 <- 64+ nonces
- { 32, 0xf8, 10000, 33.3, 31.9, 1300 }, // 45 29.6m Erlang=3.0x10-5 <- 32+ nonces
- { 16, 0xf0, 5000, 16.9, 15.9, 0 }, // 15 22.2m Erlang=4.6x10-5 <- 16+ nonces
- { 8, 0xe0, 1250, 8.9, 7.9, 0 }, // 15 166s Erlang=6.0x10-5
- { 4, 0xc0, 450, 4.9, 3.9, 0 }, // 15 30s Erlang=3.9x10-6
- { 2, 0x80, 150, 2.9, 1.9, 0 }, // 15 5s Erlang=5.4x10-7
- { 1, 0x00, 50, 1.9, 0.0, 0 }, // 15 0.8s Erlang=1.5x10-7 <- all nonces
- { 0 }
- };
- // force=true to allow setting it if it may not have taken before
- // force also delays longer after sending the ticket mask
- // diff=0.0 mean set the highest valid
- static void set_ticket(struct cgpu_info *compac, float diff, bool force, bool locked)
- {
- struct COMPAC_INFO *info = compac->device_data;
- struct timeval now;
- bool got = false;
- uint32_t udiff, new_diff = 0, new_mask = 0, cc;
- int i;
- if (diff == 0.0)
- {
- // above max will get the highest valid for cc
- diff = 128;
- }
- // if (!force && info->last_work_diff == diff)
- // return;
- // closest uint diff equal or below
- udiff = (uint32_t)floor(diff);
- cc = info->chips * info->cores;
- for (i = 0; ticket_1397[i].diff > 0; i++)
- {
- if (udiff >= ticket_1397[i].diff && cc > ticket_1397[i].cclimit)
- {
- // if ticket is already the same
- if (!force && info->difficulty == ticket_1397[i].diff)
- return;
- if (!locked)
- mutex_lock(&info->lock);
- new_diff = info->difficulty = ticket_1397[i].diff;
- new_mask = info->ticket_mask = ticket_1397[i].ticket_mask;
- info->last_work_diff = diff;
- cgtime(&info->last_ticket_attempt);
- info->ticket_number = i;
- info->ticket_work = 0;
- info->ticket_nonces = 0;
- info->below_nonces = 0;
- info->ticket_ok = false;
- info->ticket_got_low = false;
- if (!locked)
- mutex_unlock(&info->lock);
- got = true;
- break;
- }
- }
- // code failure
- if (!got)
- return;
- // set them all the same 0x51 .... 0x00
- unsigned char ticket[] = {0x51, 0x09, 0x00, BM1397TICKET, 0x00, 0x00, 0x00, 0xC0, 0x00};
- ticket[7] = info->ticket_mask;
- compac_send2(compac, ticket, sizeof(ticket), 8 * sizeof(ticket) - 8, "ticket");
- if (!force)
- gekko_usleep(info, MS2US(10));
- else
- gekko_usleep(info, MS2US(20));
- applog(LOG_ERR, "%d: %s %d - set ticket to 0x%02x/%u work %u/%.1f",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- new_mask, new_diff, udiff, diff);
- // wipe info->gh/asic->gc
- cgtime(&now);
- gh_offset(info, &now, true, false);
- job_offset(info, &now, true, false);
- // reset P:
- info->frequency_computed = 0;
- }
- // expected nonces for GEKKOCHIP - MUST already be locked AND gc_offset()
- // full 50 mins + current offset in 10 mins - N.B. uses CLOCK_MONOTONIC
- // it will grow from 0% to ~100% between 50 & 60 mins if the chip
- // is performing at 100% - random variance of course also applies
- static double noncepercent(struct COMPAC_INFO *info, int chip, struct timeval *now)
- {
- double sec, hashpersec, noncepersec, nonceexpect;
- if (info->asic_type != BM1397)
- return 0.0;
- sec = CHTIME * (CHNUM-1) + (now->tv_sec % CHTIME) + ((double)now->tv_usec / 1000000.0);
- hashpersec = info->asics[chip].frequency * info->cores * info->hr_scale * 1000000.0;
- noncepersec = (hashpersec / (double)0xffffffffull)
- / (double)(ticket_1397[info->ticket_number].diff);
- nonceexpect = noncepersec * sec;
- return 100.0 * (double)(info->asics[chip].gc.noncesum) / nonceexpect;
- }
- // GSF/GSFM any chip count
- static void calc_gsf_freq(struct cgpu_info *compac, float frequency, int chip)
- {
- struct COMPAC_INFO *info = compac->device_data;
- char chipn[8];
- bool doall;
- if (info->asic_type != BM1397)
- return;
- if (chip == -1)
- doall = true;
- else
- {
- if (chip < 0 || chip >= (int)(info->chips))
- {
- applog(LOG_ERR, "%d: %s %d - invalid set chip [%d] -> freq %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id, chip, frequency);
- return;
- }
- doall = false;
- }
- // if attempting the same frequency that previously failed ...
- if (frequency != 0 && frequency == info->freq_fail)
- return;
- unsigned char prefreqall[] = {0x51, 0x09, 0x00, 0x70, 0x0F, 0x0F, 0x0F, 0x00, 0x00};
- unsigned char prefreqch[] = {0x41, 0x09, 0x00, 0x70, 0x0F, 0x0F, 0x0F, 0x00, 0x00};
- // default 200Mhz if it fails
- unsigned char freqbufall[] = {0x51, 0x09, 0x00, BM1397FREQ, 0x40, 0xF0, 0x02, 0x35, 0x00};
- unsigned char freqbufch[] = {0x41, 0x09, 0x00, BM1397FREQ, 0x40, 0xF0, 0x02, 0x35, 0x00};
- float deffreq = 200.0;
- float fa, fb, fc1, fc2, newf;
- float f1, basef, famax = 0xf0, famin = 0x10;
- uint16_t c;
- int i;
- // allow a frequency 'power down'
- if (frequency == 0)
- {
- doall = true;
- basef = fa = 0;
- fb = fc1 = fc2 = 1;
- }
- else
- {
- f1 = limit_freq(info, frequency, false);
- fb = 2; fc1 = 1; fc2 = 5; // initial multiplier of 10
- if (f1 >= 500)
- {
- // halv down to '250-400'
- fb = 1;
- }
- else if (f1 <= 150)
- {
- // tiple up to '300-450'
- fc1 = 3;
- }
- else if (f1 <= 250)
- {
- // double up to '300-500'
- fc1 = 2;
- }
- // else f1 is 250-500
- // f1 * fb * fc1 * fc2 is between 2500 and 5000
- // - so round up to the next 25 (freq_mult)
- basef = info->freq_mult * ceil(f1 * fb * fc1 * fc2 / info->freq_mult);
- // fa should be between 100 (0x64) and 200 (0xC8)
- fa = basef / info->freq_mult;
- }
- // code failure ... basef isn't 400 to 6000
- if (frequency != 0 && (fa < famin || fa > famax))
- {
- info->freq_fail = frequency;
- newf = deffreq;
- }
- else
- {
- if (doall)
- {
- freqbufall[5] = (int)fa;
- freqbufall[6] = (int)fb;
- // fc1, fc2 'should' already be 1..15
- freqbufall[7] = (((int)fc1 & 0xf) << 4) + ((int)fc2 & 0xf);
- }
- else
- {
- freqbufch[5] = (int)fa;
- freqbufch[6] = (int)fb;
- // fc1, fc2 'should' already be 1..15
- freqbufch[7] = (((int)fc1 & 0xf) << 4) + ((int)fc2 & 0xf);
- }
- newf = basef / ((float)fb * (float)fc1 * (float)fc2);
- }
- if (doall)
- {
- // i.e. -1 means no reply since last set
- for (c = 0; c < info->chips; c++)
- info->asics[c].frequency_reply = -1;
- for (i = 0; i < 2; i++)
- {
- gekko_usleep(info, MS2US(10));
- compac_send2(compac, prefreqall, sizeof(prefreqall), 8 * sizeof(prefreqall) - 8, "prefreq");
- }
- for (i = 0; i < 2; i++)
- {
- gekko_usleep(info, MS2US(10));
- compac_send2(compac, freqbufall, sizeof(freqbufall), 8 * sizeof(freqbufall) - 8, "freq");
- }
- // the freq wanted, which 'should' be the same
- for (c = 0; c < info->chips; c++)
- info->asics[c].frequency = frequency;
- }
- else
- {
- // just setting 1 chip
- prefreqch[2] = freqbufch[2] = CHIPPY1397(info, chip);
- // i.e. -1 means no reply since last set
- info->asics[chip].frequency_reply = -1;
- for (i = 0; i < 2; i++)
- {
- gekko_usleep(info, MS2US(10));
- compac_send2(compac, prefreqch, sizeof(prefreqch), 8 * sizeof(prefreqch) - 8, "prefreq");
- }
- for (i = 0; i < 2; i++)
- {
- gekko_usleep(info, MS2US(10));
- compac_send2(compac, freqbufch, sizeof(freqbufch), 8 * sizeof(freqbufch) - 8, "freq");
- }
- // the freq wanted, which 'should' be the same
- info->asics[chip].frequency = frequency;
- }
- if (doall)
- info->frequency = frequency;
- gekko_usleep(info, MS2US(10));
- if (doall)
- snprintf(chipn, sizeof(chipn), "all");
- else
- snprintf(chipn, sizeof(chipn), "%d", chip);
- // applog(LOG_INFO, "%d: %s %d - setting frequency to %.2fMHz (%.2f)" " (%.0f/%.0f/%.0f/%.0f)",
- applog(LOG_ERR, "%d: %s %d - setting [%s] frequency to %.2fMHz (%.2f)" " (%.0f/%.0f/%.0f/%.0f)",
- compac->cgminer_id, compac->drv->name, compac->device_id, chipn, frequency, newf, fa, fb, fc1, fc2);
- ping_freq(compac, 0);
- }
- static void compac_send_chain_inactive(struct cgpu_info *compac)
- {
- struct COMPAC_INFO *info = compac->device_data;
- unsigned int i, j;
- applog(LOG_INFO,"%d: %s %d - sending chain inactive for %d chip(s)",
- compac->cgminer_id, compac->drv->name, compac->device_id, info->chips);
- if (info->asic_type == BM1397)
- {
- // chain inactive
- unsigned char chainin[5] = {0x53, 0x05, 0x00, 0x00, 0x00};
- for (i = 0; i < 3; i++)
- {
- compac_send2(compac, chainin, sizeof(chainin), 8 * sizeof(chainin) - 8, "chin");
- gekko_usleep(info, MS2US(100));
- }
- unsigned char chippy[] = {0x40, 0x05, 0x00, 0x00, 0x00};
- for (i = 0; i < info->chips; i++)
- {
- chippy[2] = CHIPPY1397(info, i);
- compac_send2(compac, chippy, sizeof(chippy), 8 * sizeof(chippy) - 8, "chippy");
- gekko_usleep(info, MS2US(10));
- }
- unsigned char init1[] = {0x51, 0x09, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00};
- unsigned char init2[] = {0x51, 0x09, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
- unsigned char init3[] = {0x51, 0x09, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00};
- unsigned char init4[] = {0x51, 0x09, 0x00, 0x3C, 0x80, 0x00, 0x80, 0x74, 0x00};
- compac_send2(compac, init1, sizeof(init1), 8 * sizeof(init1) - 8, "init1");
- gekko_usleep(info, MS2US(10));
- compac_send2(compac, init2, sizeof(init2), 8 * sizeof(init2) - 8, "init2");
- gekko_usleep(info, MS2US(100));
- compac_send2(compac, init3, sizeof(init3), 8 * sizeof(init3) - 8, "init3");
- gekko_usleep(info, MS2US(50));
- compac_send2(compac, init4, sizeof(init4), 8 * sizeof(init4) - 8, "init4");
- gekko_usleep(info, MS2US(100));
- // set ticket based on chips, pool will be above this anyway
- set_ticket(compac, 0.0, true, false);
- unsigned char init5[] = {0x51, 0x09, 0x00, 0x68, 0xC0, 0x70, 0x01, 0x11, 0x00};
- unsigned char init6[] = {0x51, 0x09, 0x00, 0x28, 0x06, 0x00, 0x00, 0x0F, 0x00};
- for (j = 0; j < 2; j++)
- {
- compac_send2(compac, init5, sizeof(init5), 8 * sizeof(init5) - 8, "init5");
- gekko_usleep(info, MS2US(50));
- }
- compac_send2(compac, init6, sizeof(init6), 8 * sizeof(init6) - 8, "init6");
- gekko_usleep(info, MS2US(100));
- unsigned char baudrate[] = { 0x51, 0x09, 0x00, 0x18, 0x00, 0x00, 0x61, 0x31, 0x00 }; // lo 1.51M
- info->bauddiv = 1; // 1.5M
- #ifdef WIN32___fixme_zzz
- if (info->midstates == 4)
- {
- // 4 mid = slow it down on windows 116K
- baudrate[5] = 0x00;
- baudrate[6] = 0x7A;
- // 3.125M/27
- info->bauddiv = 26;
- }
- #endif
- applog(LOG_ERR, "%d: %s %d - setting bauddiv : %02x %02x (ftdi/%d)",
- compac->cgminer_id, compac->drv->name, compac->device_id, baudrate[5], baudrate[6], info->bauddiv + 1);
- compac_send2(compac, baudrate, sizeof(baudrate), 8 * sizeof(baudrate) - 8, "baud");
- gekko_usleep(info, MS2US(10));
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, info->bauddiv + 1,
- (FTDI_INDEX_BAUD_BTS & 0xff00) | info->interface, C_SETBAUD);
- gekko_usleep(info, MS2US(10));
- calc_gsf_freq(compac, info->frequency, -1);
- gekko_usleep(info, MS2US(20));
- } else if (info->asic_type == BM1387) {
- unsigned char buffer[5] = {0x55, 0x05, 0x00, 0x00, 0x00};
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 8); // chain inactive
- gekko_usleep(info, MS2US(5));
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 8); // chain inactive
- gekko_usleep(info, MS2US(5));
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 8); // chain inactive
- for (i = 0; i < info->chips; i++) {
- buffer[0] = 0x41;
- buffer[1] = 0x05;
- buffer[2] = (0x100 / info->chips) * i;
- gekko_usleep(info, MS2US(5));
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 8);
- }
- gekko_usleep(info, MS2US(10));
- unsigned char baudrate[] = { 0x58, 0x09, 0x00, 0x1C, 0x00, 0x20, 0x07, 0x00, 0x19 };
- if (opt_gekko_bauddiv) {
- info->bauddiv = opt_gekko_bauddiv;
- } else {
- info->bauddiv = 0x01; // 1.5Mbps baud.
- #ifdef WIN32
- if (info->midstates == 4)
- info->bauddiv = 0x0D; // 214Kbps baud.
- #endif
- }
- applog(LOG_INFO, "%d: %s %d - setting bauddiv : %02x",
- compac->cgminer_id, compac->drv->name, compac->device_id, info->bauddiv);
- baudrate[6] = info->bauddiv;
- compac_send(compac, baudrate, sizeof(baudrate), 8 * sizeof(baudrate) - 8);
- gekko_usleep(info, MS2US(10));
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, (info->bauddiv + 1),
- (FTDI_INDEX_BAUD_BTS & 0xff00) | info->interface, C_SETBAUD);
- gekko_usleep(info, MS2US(10));
- unsigned char gateblk[9] = {0x58, 0x09, 0x00, 0x1C, 0x40, 0x20, 0x99, 0x80, 0x01};
- gateblk[6] = 0x80 | info->bauddiv;
- compac_send(compac, gateblk, sizeof(gateblk), 8 * sizeof(gateblk) - 8); // chain inactive
- } else if (info->asic_type == BM1384) {
- unsigned char buffer[] = {0x85, 0x00, 0x00, 0x00};
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 5); // chain inactive
- for (i = 0; i < info->chips; i++) {
- buffer[0] = 0x01;
- buffer[1] = (0x100 / info->chips) * i;
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 5);
- }
- buffer[0] = 0x86; // GATEBLK
- buffer[1] = 0x00;
- buffer[2] = 0x9a; // 0x80 | 0x1a;
- //compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 5);
- }
- if (info->mining_state == MINER_CHIP_COUNT_OK) {
- applog(LOG_INFO, "%d: %s %d - open cores",
- compac->cgminer_id, compac->drv->name, compac->device_id);
- info->zero_check = 0;
- info->task_hcn = 0;
- info->mining_state = MINER_OPEN_CORE;
- }
- }
- static void compac_update_rates(struct cgpu_info *compac)
- {
- struct COMPAC_INFO *info = compac->device_data;
- struct ASIC_INFO *asic;
- float average_frequency = 0, est;
- unsigned int i;
- cgtime(&(info->last_update_rates));
- if (info->chips == 0 || info->frequency == 0)
- return;
- for (i = 0; i < info->chips; i++)
- {
- if (info->asics[i].frequency == 0)
- return;
- }
- info->frequency_asic = 0;
- for (i = 0; i < info->chips; i++) {
- asic = &info->asics[i];
- asic->hashrate = asic->frequency * info->cores * 1000000 * info->hr_scale;
- asic->fullscan_ms = 1000.0 * info->hr_scale * 0xffffffffull / asic->hashrate;
- asic->fullscan_us = 1000.0 * info->hr_scale * 1000.0 * 0xffffffffull / asic->hashrate;
- average_frequency += asic->frequency;
- info->frequency_asic = (asic->frequency > info->frequency_asic ) ? asic->frequency : info->frequency_asic;
- }
- average_frequency = average_frequency / info->chips;
- if (average_frequency != info->frequency) {
- applog(LOG_INFO,"%d: %s %d - frequency updated %.2fMHz -> %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id, info->frequency, average_frequency);
- info->frequency = average_frequency;
- info->wu_max = 0;
- }
- info->wu = (info->chips * info->frequency * info->cores / 71.6) * info->hr_scale;
- info->hashrate = info->chips * info->frequency * info->cores * 1000000 * info->hr_scale;
- info->fullscan_ms = 1000.0 * info->hr_scale * 0xffffffffull / info->hashrate;
- info->fullscan_us = 1000.0 * info->hr_scale * 1000.0 * 0xffffffffull / info->hashrate;
- if (info->asic_type != BM1397)
- {
- info->ticket_mask = bound(pow(2, ceil(log(info->hashrate / (2.0 * 0xffffffffull)) / log(2))) - 1, 0, 4000);
- info->ticket_mask = (info->asic_type == BM1387) ? 0 : info->ticket_mask;
- info->difficulty = info->ticket_mask + 1;
- }
- info->wait_factor = info->wait_factor0;
- if (!opt_gekko_noboost && info->vmask && (info->asic_type == BM1387 || info->asic_type == BM1397))
- info->wait_factor *= info->midstates;
- est = info->wait_factor * (float)(info->fullscan_us);
- info->max_task_wait = bound((uint64_t)est, 1, 3 * info->fullscan_us);
- if (info->asic_type == BM1387)
- {
- if (opt_gekko_tune_up > 95)
- info->tune_up = 100.0 * ((info->frequency - info->freq_base * (600 / info->frequency)) / info->frequency);
- else
- info->tune_up = opt_gekko_tune_up;
- }
- else if (info->asic_type == BM1397)
- {
- // 90% will always allow at least 2 freq steps
- if (opt_gekko_tune_up > 90)
- opt_gekko_tune_up = 90;
- else
- info->tune_up = opt_gekko_tune_up;
- }
- else
- info->tune_up = 99;
- // shouldn't happen, but next call should fix it
- if (info->difficulty == 0)
- info->nonce_expect = 0;
- else
- {
- // expected ms per nonce for PT_NONONCE
- info->nonce_expect = info->fullscan_ms * info->difficulty;
- // BM1397 check is per miner, not per chip, fullscan_ms is sum of chips
- if (info->asic_type != BM1397 && info->chips > 1)
- info->nonce_expect *= (float)info->chips;
- // CDF >2000% is avg once in 485165205.1 nonces
- info->nonce_limit = info->nonce_expect * 20.0;
- // N.B. this ignores info->ghrequire since
- // that should be an independent test
- }
- applog(LOG_INFO, "%d: %s %d - Rates: ms %.2f tu %.2f td %.2f",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- info->fullscan_ms, info->tune_up, info->tune_down);
- }
- static void compac_set_frequency_single(struct cgpu_info *compac, float frequency, int asic_id)
- {
- struct COMPAC_INFO *info = compac->device_data;
- struct ASIC_INFO *asic = &info->asics[asic_id];
- struct timeval now;
- if (info->asic_type == BM1387) {
- unsigned char buffer[] = {0x48, 0x09, 0x00, 0x0C, 0x00, 0x50, 0x02, 0x41, 0x00}; //250MHz -- osc of 25MHz
- frequency = bound(frequency, 50, 1200);
- frequency = FREQ_BASE(frequency);
- if (frequency < 400) {
- buffer[7] = 0x41;
- buffer[5] = (frequency * 8) / info->freq_mult;
- } else {
- buffer[7] = 0x21;
- buffer[5] = (frequency * 4) / info->freq_mult;
- }
- buffer[2] = (0x100 / info->chips) * asic_id;
- //asic->frequency = frequency;
- asic->frequency_set = frequency;
- asic->frequency_attempt++;
- applog(LOG_INFO, "%d: %s %d - setting chip[%d] frequency (%d) %.2fMHz -> %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- asic_id, asic->frequency_attempt, asic->frequency, frequency);
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 8);
- //unsigned char gateblk[9] = {0x48, 0x09, 0x00, 0x1C, 0x40, 0x20, 0x99, 0x80, 0x01};
- //gateblk[6] = 0x80 | info->bauddiv;
- //gateblk[2] = (0x100 / info->chips) * id;
- //compac_send(compac, gateblk, sizeof(gateblk), 8 * sizeof(gateblk) - 8); // chain inactive
- // wipe info->gh/asic->gc
- cgtime(&now);
- gh_offset(info, &now, true, false);
- // reset P:
- info->frequency_computed = 0;
- }
- }
- static void compac_set_frequency(struct cgpu_info *compac, float frequency)
- {
- struct COMPAC_INFO *info = compac->device_data;
- uint32_t i, r, r1, r2, r3, p1, p2, pll;
- struct timeval now;
- if (info->asic_type == BM1397) {
- calc_gsf_freq(compac, frequency, -1);
- } else if (info->asic_type == BM1387) {
- unsigned char buffer[] = {0x58, 0x09, 0x00, 0x0C, 0x00, 0x50, 0x02, 0x41, 0x00}; //250MHz -- osc of 25MHz
- frequency = bound(frequency, 50, 1200);
- frequency = FREQ_BASE(frequency);
- if (frequency < 400) {
- buffer[7] = 0x41;
- buffer[5] = (frequency * 8) / info->freq_mult;
- } else {
- buffer[7] = 0x21;
- buffer[5] = (frequency * 4) / info->freq_mult;
- }
- /*
- } else {
- buffer[7] = 0x11;
- buffer[5] = (frequency * 2) / info->freq_mult;
- }
- */
- applog(LOG_INFO, "%d: %s %d - setting frequency to %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id, frequency);
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 8);
- info->frequency = frequency;
- for (i = 0; i < info->chips; i++)
- info->asics[i].frequency = frequency;
- } else if (info->asic_type == BM1384) {
- unsigned char buffer[] = {0x82, 0x0b, 0x83, 0x00};
- frequency = bound(frequency, 6, 500);
- frequency = FREQ_BASE(frequency);
- info->frequency = frequency;
- r = floor(log(info->frequency/info->freq_mult) / log(2));
- r1 = 0x0785 - r;
- r2 = 0x200 / pow(2, r);
- r3 = info->freq_mult * pow(2, r);
- p1 = r1 + r2 * (info->frequency - r3) / info->freq_base;
- p2 = p1 * 2 + (0x7f + r);
- pll = (((uint32_t)(info->frequency) % (uint32_t)(info->freq_mult)) == 0 ? p1 : p2);
- if (info->frequency < 100) {
- pll = 0x0783 - 0x80 * (100 - info->frequency) / info->freq_base;
- }
- buffer[1] = (pll >> 8) & 0xff;
- buffer[2] = (pll) & 0xff;
- applog(LOG_INFO, "%d: %s %d - setting frequency to %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id, frequency);
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 5);
- buffer[0] = 0x84;
- buffer[1] = 0x00;
- buffer[2] = 0x00;
- // compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 5);
- buffer[2] = 0x04;
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 5);
- for (i = 0; i < info->chips; i++)
- info->asics[i].frequency = frequency;
- }
- compac_update_rates(compac);
- // wipe info->gh/asic->gc
- cgtime(&now);
- gh_offset(info, &now, true, false);
- // reset P:
- info->frequency_computed = 0;
- }
- static void compac_update_work(struct cgpu_info *compac)
- {
- struct COMPAC_INFO *info = compac->device_data;
- int i;
- for (i = 0; i < JOB_MAX; i++) {
- info->active_work[i] = false;
- }
- info->update_work = 1;
- }
- static void compac_flush_buffer(struct cgpu_info *compac)
- {
- int read_bytes = 1;
- unsigned char resp[32];
- while (read_bytes) {
- usb_read_timeout(compac, (char *)resp, 32, &read_bytes, 1, C_REQUESTRESULTS);
- }
- }
- static void compac_flush_work(struct cgpu_info *compac)
- {
- compac_flush_buffer(compac);
- compac_update_work(compac);
- }
- static void compac_toggle_reset(struct cgpu_info *compac)
- {
- struct COMPAC_INFO *info = compac->device_data;
- unsigned short usb_val;
- applog(info->log_wide,"%d: %s %d - Toggling ASIC nRST to reset",
- compac->cgminer_id, compac->drv->name, compac->device_id);
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_RESET, info->interface, C_RESET);
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, FTDI_VALUE_DATA_BTS, info->interface, C_SETDATA);
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD_BTS, (FTDI_INDEX_BAUD_BTS & 0xff00) | info->interface, C_SETBAUD);
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW, FTDI_VALUE_FLOW, info->interface, C_SETFLOW);
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_PURGE_TX, info->interface, C_PURGETX);
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_PURGE_RX, info->interface, C_PURGERX);
- usb_val = (FTDI_BITMODE_CBUS << 8) | 0xF2; // low byte: bitmask - 1111 0010 - CB1(HI)
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_BITMODE, usb_val, info->interface, C_SETMODEM);
- gekko_usleep(info, MS2US(30));
- usb_val = (FTDI_BITMODE_CBUS << 8) | 0xF0; // low byte: bitmask - 1111 0000 - CB1(LO)
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_BITMODE, usb_val, info->interface, C_SETMODEM);
- if (info->asic_type == BM1397)
- gekko_usleep(info, MS2US(1000));
- else
- gekko_usleep(info, MS2US(30));
- usb_val = (FTDI_BITMODE_CBUS << 8) | 0xF2; // low byte: bitmask - 1111 0010 - CB1(HI)
- usb_transfer(compac, FTDI_TYPE_OUT, FTDI_REQUEST_BITMODE, usb_val, info->interface, C_SETMODEM);
- gekko_usleep(info, MS2US(200));
- cgtime(&info->last_reset);
- }
- static void compac_gsf_nonce(struct cgpu_info *compac, K_ITEM *item)
- {
- struct COMPAC_INFO *info = compac->device_data;
- unsigned char *rx = DATA_NONCE(item)->rx;
- int hwe = compac->hw_errors;
- struct work *work = NULL;
- bool active_work = false;
- uint32_t job_id = 0;
- uint32_t nonce = 0;
- int domid, midnum = 0;
- double diff = 0.0;
- bool boost, ok;
- int asic_id, i;
- if (info->asic_type != BM1397)
- return;
- job_id = rx[7] & 0xff;
- nonce = (rx[5] << 0) | (rx[4] << 8) | (rx[3] << 16) | (rx[2] << 24);
- // N.B. busy work (0xff) never returns a nonce
- mutex_lock(&info->lock);
- info->nonces++;
- info->nonceless = 0;
- info->noncebyte[rx[3]]++;
- mutex_unlock(&info->lock);
- if (info->nb2c_setup)
- asic_id = info->nb2chip[rx[3]];
- else
- asic_id = floor((double)(rx[4]) / ((double)0x100 / (double)(info->chips)));
- if (asic_id >= (int)(info->chips))
- {
- applog(LOG_ERR, "%d: %s %d - nonce %08x @ %02x rx[4] %02x invalid asic_id (0..%d)",
- compac->cgminer_id, compac->drv->name, compac->device_id, nonce, job_id,
- rx[4], (int)(info->chips)-1);
- asic_id = (info->chips - 1);
- }
- #if 0
- else
- {
- applog(LOG_ERR, "%d: %s %d - gotnonce %08x @ %02x rx[2] %02x id %d(%u)",
- compac->cgminer_id, compac->drv->name, compac->device_id, nonce, job_id,
- rx[2], asic_id, info->chips);
- applog(LOG_ERR, " N:[%02x %02x %02x %02x %02x %02x %02x]",
- rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6]);
- }
- #endif
- struct ASIC_INFO *asic = &info->asics[asic_id];
- if (nonce == asic->prev_nonce)
- {
- applog(LOG_INFO, "%d: %s %d - Duplicate Nonce : %08x @ %02x [%02x %02x %02x %02x %02x %02x %02x]",
- compac->cgminer_id, compac->drv->name, compac->device_id, nonce, job_id,
- rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6]);
- mutex_lock(&info->lock);
- info->dups++;
- info->dupsall++;
- info->dupsreset++;
- asic->dups++;
- asic->dupsall++;
- cgtime(&info->last_dup_time);
- if (info->dups == 1)
- info->mining_state = MINER_MINING_DUPS;
- mutex_unlock(&info->lock);
- return;
- }
- mutex_lock(&info->lock);
- info->prev_nonce = nonce;
- asic->prev_nonce = nonce;
- applog(LOG_INFO, "%d: %s %d - Device reported nonce: %08x @ %02x (%d)",
- compac->cgminer_id, compac->drv->name, compac->device_id, nonce, job_id, info->tracker);
- if (!opt_gekko_noboost && info->vmask)
- {
- domid = info->midstates;
- boost = true;
- }
- else
- {
- domid = 1;
- boost = false;
- }
- ok = false;
- // test the exact jobid/midnum
- uint32_t w_job_id = job_id & 0xfc;
- if (w_job_id <= info->max_job_id)
- {
- work = info->work[w_job_id];
- active_work = info->active_work[w_job_id];
- if (work && active_work)
- {
- if (boost)
- {
- midnum = job_id & 0x03;
- work->micro_job_id = pow(2, midnum);
- memcpy(work->data, &(work->pool->vmask_001[work->micro_job_id]), 4);
- }
- if ((diff = test_nonce_value(work, nonce)) != 0.0)
- {
- ok = true;
- if (midnum > 0)
- info->boosted = true;
- }
- }
- }
- if (!ok)
- {
- // not found, try each cur_attempt
- for (i = 0; !ok && i < (int)CUR_ATTEMPT; i++)
- {
- w_job_id = JOB_ID_ROLL(info->job_id, cur_attempt[i], info) & 0xfc;
- work = info->work[w_job_id];
- active_work = info->active_work[w_job_id];
- if (work && active_work)
- {
- for (midnum = 0; !ok && midnum < domid; midnum++)
- {
- // failed original job_id already tested
- if ((w_job_id | midnum) == job_id)
- continue;
- if (boost)
- {
- work->micro_job_id = pow(2, midnum);
- memcpy(work->data, &(work->pool->vmask_001[work->micro_job_id]), 4);
- }
- if ((diff = test_nonce_value(work, nonce)) != 0)
- {
- if (midnum > 0)
- info->boosted = true;
- info->cur_off[i]++;
- ok = true;
- applog(LOG_INFO, "%d: %s %d - Nonce Recovered : %08x @ job[%02x]->fix[%02x] len %u prelen %u",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- nonce, job_id, w_job_id, (uint32_t)(DATA_NONCE(item)->len),
- (uint32_t)(DATA_NONCE(item)->prelen));
- }
- }
- }
- }
- if (!ok)
- {
- applog(LOG_INFO, "%d: %s %d - Nonce Dumped : %08x @ job[%02x] cur[%02x] diff %u",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- nonce, job_id, info->job_id, info->difficulty);
- inc_hw_errors_n(info->thr, info->difficulty);
- cgtime(&info->last_hwerror);
- mutex_unlock(&info->lock);
- return;
- }
- }
- // verify the ticket mask is correct
- if (!info->ticket_ok && diff > 0)
- {
- do // so we can break out
- {
- if (++(info->ticket_work) > TICKET_DELAY)
- {
- int i = info->ticket_number;
- info->ticket_nonces++;
- // nonce below ticket setting - redo ticket - chip must be too low
- // check this for all nonces until ticket_ok
- if (diff < ticket_1397[i].hi_limit)
- {
- if (++(info->below_nonces) < TICKET_BELOW_LIM)
- break;
- // redo ticket to return fewer nonces
- if (info->ticket_failures > MAX_TICKET_CHECK)
- {
- // give up - just set it to max
- applog(LOG_ERR, "%d: %s %d - ticket %u failed too many times setting to max",
- compac->cgminer_id, compac->drv->name, compac->device_id, ticket_1397[i].diff);
- //set_ticket(compac, 1.0, true, true);
- set_ticket(compac, 0.0, true, true);
- info->ticket_ok = true;
- break;
- }
- applog(LOG_ERR, "%d: %s %d - ticket %u failure (%"PRId64") diff %.1f below lim %.1f - retry %d",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- ticket_1397[i].diff, info->below_nonces, diff, ticket_1397[i].hi_limit, info->ticket_failures+1);
- // try again ...
- //set_ticket(compac, ticket_1397[i].diff, true, true);
- set_ticket(compac, 0.0, true, true);
- info->ticket_failures++;
- break;
- }
- // after nonce_count, CDF[Erlang] chance of NOT being below
- if (diff < ticket_1397[i].low_limit)
- info->ticket_got_low = true;
- if (info->ticket_work >= (ticket_1397[i].nonce_count + TICKET_DELAY))
- {
- // we should have got a 'low' by now
- if (info->ticket_got_low)
- {
- info->ticket_ok = true;
- info->ticket_failures = 0;
- applog(LOG_ERR, "%d: %s %d - ticket value confirmed 0x%02x/%u after %"PRId64" nonces",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- info->ticket_mask, info->difficulty, info->ticket_nonces);
- break;
- }
- // chip ticket must be too high means lost shares
- if (info->ticket_failures > MAX_TICKET_CHECK)
- {
- // give up - just set it to 1.0
- applog(LOG_ERR, "%d: %s %d - ticket %u failed too many times setting to max",
- compac->cgminer_id, compac->drv->name, compac->device_id, ticket_1397[i].diff);
- //set_ticket(compac, 1.0, true, true);
- set_ticket(compac, 0.0, true, true);
- info->ticket_ok = true;
- break;
- }
- applog(LOG_ERR, "%d: %s %d - ticket %u failure no low < %.1f after %d - retry %d",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- ticket_1397[i].diff, ticket_1397[i].low_limit, info->ticket_work, info->ticket_failures+1);
- // try again ...
- //set_ticket(compac, ticket_1397[i].diff, true, true);
- set_ticket(compac, 0.0, true, true);
- info->ticket_failures++;
- break;
- }
- }
- }
- while (0);
- }
- if (active_work && work)
- work->device_diff = info->difficulty;
- mutex_unlock(&info->lock);
- if (active_work && work && submit_nonce(info->thr, work, nonce))
- {
- mutex_lock(&info->lock);
- cgtime(&info->last_nonce);
- cgtime(&asic->last_nonce);
- // count of valid nonces
- asic->nonces++; // info only
- if (midnum > 0)
- {
- applog(LOG_INFO, "%d: %s %d - AsicBoost nonce found : midstate %d",
- compac->cgminer_id, compac->drv->name, compac->device_id, midnum);
- }
- // if work diff < info->dificulty, 'accept' hash rate will be low
- info->hashes += info->difficulty * 0xffffffffull;
- info->xhashes += info->difficulty;
- info->accepted++;
- info->failing = false;
- info->dups = 0;
- asic->dups = 0;
- mutex_unlock(&info->lock);
- if (info->nb2c_setup)
- add_gekko_nonce(info, asic, &(DATA_NONCE(item)->when));
- else
- add_gekko_nonce(info, NULL, &(DATA_NONCE(item)->when));
- }
- else
- {
- // shouldn't be possible since diff has already been checked
- if (hwe != compac->hw_errors)
- {
- mutex_lock(&info->lock);
- cgtime(&info->last_hwerror);
- mutex_unlock(&info->lock);
- }
- }
- }
- static uint64_t compac_check_nonce(struct cgpu_info *compac)
- {
- struct COMPAC_INFO *info = compac->device_data;
- uint32_t nonce = 0;
- int hwe = compac->hw_errors;
- uint32_t job_id = 0;
- uint64_t hashes = 0;
- struct timeval now;
- int i;
- if (info->asic_type == BM1387) {
- job_id = info->rx[5] & 0xff;
- nonce = (info->rx[3] << 0) | (info->rx[2] << 8) | (info->rx[1] << 16) | (info->rx[0] << 24);
- } else if (info->asic_type == BM1384) {
- job_id = info->rx[4] ^ 0x80;
- nonce = (info->rx[3] << 0) | (info->rx[2] << 8) | (info->rx[1] << 16) | (info->rx[0] << 24);
- } else if (info->asic_type == BM1397) {
- // should never call here
- return hashes;
- }
- if ((info->rx[0] == 0x72 && info->rx[1] == 0x03 && info->rx[2] == 0xEA && info->rx[3] == 0x83)
- || (info->rx[0] == 0xE1 && info->rx[1] == 0x6B && info->rx[2] == 0xF8 && info->rx[3] == 0x09))
- {
- //busy work nonces
- return hashes;
- }
- if (job_id > info->max_job_id
- || (abs((int)(info->job_id) - (int)job_id) > 3 && abs((int)(info->max_job_id) - (int)job_id + (int)(info->job_id)) > 3))
- {
- return hashes;
- }
- if (!info->active_work[job_id]
- && !(job_id > 0 && info->active_work[job_id - 1])
- && !(job_id > 1 && info->active_work[job_id - 2])
- && !(job_id > 2 && info->active_work[job_id - 3]))
- {
- return hashes;
- }
- cgtime(&now);
- info->nonces++;
- info->nonceless = 0;
- int asic_id = (int)floor((double)(info->rx[0]) / ((double)0x100 / (double)(info->chips)));
- struct ASIC_INFO *asic = &info->asics[asic_id];
- if (nonce == asic->prev_nonce) {
- applog(LOG_INFO, "%d: %s %d - Duplicate Nonce : %08x @ %02x [%02x %02x %02x %02x %02x %02x]",
- compac->cgminer_id, compac->drv->name, compac->device_id, nonce, job_id,
- info->rx[0], info->rx[1], info->rx[2], info->rx[3], info->rx[4], info->rx[5]);
- info->dups++;
- info->dupsall++;
- info->dupsreset++;
- asic->dups++;
- asic->dupsall++;
- cgtime(&info->last_dup_time);
- if (info->dups == 1) {
- info->mining_state = MINER_MINING_DUPS;
- }
- return hashes;
- }
- info->prev_nonce = nonce;
- asic->prev_nonce = nonce;
- applog(LOG_INFO, "%d: %s %d - Device reported nonce: %08x @ %02x (%d)",
- compac->cgminer_id, compac->drv->name, compac->device_id, nonce, job_id, info->tracker);
- struct work *work = info->work[job_id];
- bool active_work = info->active_work[job_id];
- int midnum = 0;
- if (!opt_gekko_noboost && info->vmask)
- {
- // force check last few nonces by [job_id - 1]
- // doesn't handle job_id roll over
- if (info->asic_type == BM1387)
- {
- for (i = 0; i < info->midstates; i++)
- {
- if ((int)job_id >= i)
- {
- if (info->active_work[job_id - i])
- {
- work = info->work[job_id - i];
- active_work = info->active_work[job_id - i];
- if (active_work && work)
- {
- work->micro_job_id = pow(2, i);
- memcpy(work->data, &(work->pool->vmask_001[work->micro_job_id]), 4);
- if (test_nonce(work, nonce))
- {
- midnum = i;
- if (i > 0)
- info->boosted = true;
- break;
- }
- }
- }
- }
- }
- }
- }
- if (!active_work || !work) {
- return hashes;
- }
- work->device_diff = info->difficulty;
- if (submit_nonce(info->thr, work, nonce)) {
- cgtime(&info->last_nonce);
- cgtime(&asic->last_nonce);
- // count of valid nonces
- asic->nonces++; // info only
- if (midnum > 0) {
- applog(LOG_INFO, "%d: %s %d - AsicBoost nonce found : midstate%d",
- compac->cgminer_id, compac->drv->name, compac->device_id, midnum);
- }
- hashes = info->difficulty * 0xffffffffull;
- info->xhashes += info->difficulty;
- info->accepted++;
- info->failing = false;
- info->dups = 0;
- asic->dups = 0;
- add_gekko_nonce(info, asic, &now);
- } else {
- if (hwe != compac->hw_errors) {
- cgtime(&info->last_hwerror);
- }
- }
- return hashes;
- }
- static void busy_work(struct COMPAC_INFO *info)
- {
- memset(info->task, 0, info->task_len);
- if (info->asic_type == BM1387 || info->asic_type == BM1397) {
- info->task[0] = 0x21;
- info->task[1] = info->task_len;
- info->task[2] = info->job_id & 0xff;
- info->task[3] = ((!opt_gekko_noboost && info->vmask) ? 0x04 : 0x01);
- memset(info->task + 8, 0xff, 12);
- unsigned short crc = crc16_false(info->task, info->task_len - 2);
- info->task[info->task_len - 2] = (crc >> 8) & 0xff;
- info->task[info->task_len - 1] = crc & 0xff;
- } else if (info->asic_type == BM1384) {
- if (info->mining_state == MINER_MINING) {
- info->task[39] = info->ticket_mask & 0xff;
- stuff_msb(info->task + 40, info->task_hcn);
- }
- info->task[51] = info->job_id & 0xff;
- }
- }
- static void init_task(struct COMPAC_INFO *info)
- {
- struct work *work = info->work[info->job_id];
- memset(info->task, 0, info->task_len);
- if (info->asic_type == BM1387 || info->asic_type == BM1397) {
- info->task[0] = 0x21;
- info->task[1] = info->task_len;
- info->task[2] = info->job_id & 0xff;
- info->task[3] = ((!opt_gekko_noboost && info->vmask) ? info->midstates : 0x01);
- if (info->mining_state == MINER_MINING) {
- stuff_reverse(info->task + 8, work->data + 64, 12);
- stuff_reverse(info->task + 20, work->midstate, 32);
- if (!opt_gekko_noboost && info->vmask) {
- if (info->midstates > 1)
- stuff_reverse(info->task + 20 + 32, work->midstate1, 32);
- if (info->midstates > 2)
- stuff_reverse(info->task + 20 + 32 + 32, work->midstate2, 32);
- if (info->midstates > 3)
- stuff_reverse(info->task + 20 + 32 + 32 + 32, work->midstate3, 32);
- }
- } else {
- memset(info->task + 8, 0xff, 12);
- }
- unsigned short crc = crc16_false(info->task, info->task_len - 2);
- info->task[info->task_len - 2] = (crc >> 8) & 0xff;
- info->task[info->task_len - 1] = crc & 0xff;
- } else if (info->asic_type == BM1384) {
- if (info->mining_state == MINER_MINING) {
- stuff_reverse(info->task, work->midstate, 32);
- stuff_reverse(info->task + 52, work->data + 64, 12);
- info->task[39] = info->ticket_mask & 0xff;
- stuff_msb(info->task + 40, info->task_hcn);
- }
- info->task[51] = info->job_id & 0xff;
- }
- }
- static void change_freq_any(struct cgpu_info *compac, float new_freq)
- {
- struct COMPAC_INFO *info = compac->device_data;
- unsigned int i;
- float old_freq;
- old_freq = info->frequency;
- for (i = 0; i < info->chips; i++)
- {
- struct ASIC_INFO *asic = &info->asics[i];
- cgtime(&info->last_frequency_adjust);
- cgtime(&asic->last_frequency_adjust);
- cgtime(&info->monitor_time);
- asic->frequency_updated = 1;
- if (info->asic_type == BM1397)
- {
- if (i == 0)
- compac_set_frequency(compac, new_freq);
- }
- else if (info->asic_type == BM1387)
- {
- compac_set_frequency_single(compac, new_freq, i);
- info->frequency = new_freq;
- }
- else if (info->asic_type == BM1384)
- {
- if (i == 0)
- {
- compac_set_frequency(compac, new_freq);
- compac_send_chain_inactive(compac);
- info->frequency = new_freq;
- }
- }
- }
- applog(LOG_WARNING,"%d: %s %d - new frequency %.2fMHz -> %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- old_freq, new_freq);
- }
- // compac_mine() with long term adjustments
- static void *compac_mine2(void *object)
- {
- struct cgpu_info *compac = (struct cgpu_info *)object;
- struct COMPAC_INFO *info = compac->device_data;
- struct work *work = NULL;
- struct work *old_work = NULL;
- struct timeval now;
- struct timeval last_rolling = (struct timeval){0};
- struct timeval last_movement = (struct timeval){0};
- struct timeval last_plateau_check = (struct timeval){0};
- struct timeval last_frequency_check = (struct timeval){0};
- struct sched_param param;
- int sent_bytes, sleep_us, use_us, policy, ret_nice;
- double diff_us, left_us;
- unsigned int i, j;
- uint32_t err = 0;
- uint64_t hashrate_gs;
- double dev_runtime, wu;
- float frequency_computed;
- bool frequency_updated;
- bool has_freq;
- bool job_added;
- bool last_was_busy = false;
- int plateau_type = 0;
- #ifndef WIN32
- ret_nice = nice(-15);
- #else /* WIN32 */
- pthread_getschedparam(pthread_self(), &policy, ¶m);
- param.sched_priority = sched_get_priority_max(policy);
- pthread_setschedparam(pthread_self(), policy, ¶m);
- ret_nice = param.sched_priority;
- #endif /* WIN32 */
- applog(LOG_INFO, "%d: %s %d - work thread niceness (%d)",
- compac->cgminer_id, compac->drv->name, compac->device_id, ret_nice);
- sleep_us = 100;
- cgtime(&last_plateau_check);
- while (info->mining_state != MINER_SHUTDOWN)
- {
- if (old_work)
- {
- mutex_lock(&info->lock);
- work_completed(compac, old_work);
- mutex_unlock(&info->lock);
- old_work = NULL;
- }
- if (info->chips == 0
- || compac->deven == DEV_DISABLED
- || compac->usbinfo.nodev
- || (info->mining_state != MINER_MINING && info->mining_state != MINER_MINING_DUPS))
- {
- gekko_usleep(info, MS2US(10));
- continue;
- }
- cgtime(&now);
- if (!info->update_work)
- {
- diff_us = us_tdiff(&now, &info->last_task);
- left_us = info->max_task_wait - diff_us;
- if (left_us > 0)
- {
- // allow 300us from here to next sleep
- left_us -= 300;
- use_us = sleep_us;
- if (use_us > left_us)
- use_us = left_us;
- // 1ms is more than enough
- if (use_us > 1000)
- use_us = 1000;
- if (use_us >= USLEEPMIN)
- {
- gekko_usleep(info, use_us);
- continue;
- }
- }
- }
- frequency_updated = 0;
- info->update_work = 0;
- sleep_us = bound(ceil(info->max_task_wait / 20), 1, 100 * 1000); // 1us .. 100ms
- dev_runtime = cgpu_runtime(compac);
- wu = compac->diff1 / dev_runtime * 60;
- if (wu > info->wu_max)
- {
- info->wu_max = wu;
- cgtime(&info->last_wu_increase);
- }
- // don't change anything until we have 10s of data since a reset
- if (ms_tdiff(&now, &info->last_reset) > MS_SECOND_10)
- {
- if (ms_tdiff(&now, &last_rolling) >= MS_SECOND_1)
- {
- mutex_lock(&info->ghlock);
- if (info->gh.noncesum > (GHNONCENEEDED+1))
- {
- cgtime(&last_rolling);
- info->rolling = gekko_gh_hashrate(info, &last_rolling, true);
- }
- mutex_unlock(&info->ghlock);
- }
- hashrate_gs = (double)info->rolling * 1000000ull;
- info->eff_gs = 100.0 * (1.0 * hashrate_gs / info->hashrate);
- info->eff_wu = 100.0 * (1.0 * wu / info->wu);
- if (info->eff_gs > 100)
- info->eff_gs = 100;
- if (info->eff_wu > 100)
- info->eff_wu = 100;
- frequency_computed = ((hashrate_gs / 1.0e6) / info->cores) / info->chips;
- frequency_computed = limit_freq(info, frequency_computed, true);
- if (frequency_computed > info->frequency_computed
- && frequency_computed <= info->frequency)
- {
- info->frequency_computed = frequency_computed;
- cgtime(&info->last_computed_increase);
- applog(LOG_INFO, "%d: %s %d - new comp=%.2f (gs=%.2f)",
- compac->cgminer_id, compac->drv->name, compac->device_id, frequency_computed,
- ((double)hashrate_gs)/1.0e6);
- }
- plateau_type = 0;
- // search for plateau
- if (ms_tdiff(&now, &last_plateau_check) > MS_SECOND_5)
- {
- has_freq = false;
- for (i = 0; i < info->chips; i++)
- {
- if (info->asics[i].frequency != 0)
- {
- has_freq = true;
- break;
- }
- }
- cgtime(&last_plateau_check);
- for (i = 0; i < info->chips; i++)
- {
- struct ASIC_INFO *asic = &info->asics[i];
- // missing nonces
- if (info->asic_type == BM1397)
- {
- if (has_freq && i == 0 && info->nonce_limit > 0.0
- && ms_tdiff(&now, &info->last_nonce) > info->nonce_limit)
- {
- plateau_type = PT_NONONCE;
- applog(LOG_ERR, "%d: %s %d - plateau_type PT_NONONCE [%u] %d > %.2f (lock=%d)",
- compac->cgminer_id, compac->drv->name, compac->device_id, i,
- ms_tdiff(&now, &info->last_nonce), info->nonce_limit, info->lock_freq);
- if (info->lock_freq)
- info->lock_freq = false;
- }
- }
- else
- {
- if (has_freq && info->nonce_limit > 0.0
- && ms_tdiff(&now, &asic->last_nonce) > info->nonce_limit)
- {
- plateau_type = PT_NONONCE;
- applog(LOG_ERR, "%d: %s %d - plateau_type PT_NONONCE [%u] %d > %.2f (lock=%d)",
- compac->cgminer_id, compac->drv->name, compac->device_id, i,
- ms_tdiff(&now, &asic->last_nonce), info->nonce_limit, info->lock_freq);
- if (info->lock_freq)
- info->lock_freq = false;
- }
- }
- // asic check-in failed
- if (!info->lock_freq
- && info->asic_type != BM1397)
- {
- if (ms_tdiff(&asic->last_frequency_ping, &asic->last_frequency_reply) > MS_SECOND_30
- && ms_tdiff(&now, &asic->last_frequency_reply) > MS_SECOND_30)
- {
- plateau_type = PT_FREQNR;
- applog(LOG_INFO, "%d: %s %d - plateau_type PT_FREQNR [%u] %d > %d",
- compac->cgminer_id, compac->drv->name, compac->device_id, i,
- ms_tdiff(&now, &asic->last_frequency_reply), MS_SECOND_30);
- }
- }
- // set frequency requests not honored
- if (!info->lock_freq
- && asic->frequency_attempt > 3)
- {
- plateau_type = PT_FREQSET;
- applog(LOG_INFO, "%d: %s %d - plateau_type PT_FREQSET [%u] %u > 3",
- compac->cgminer_id, compac->drv->name, compac->device_id, i, asic->frequency_attempt);
- }
- if (plateau_type)
- {
- float old_frequency, new_frequency;
- new_frequency = info->frequency_requested;
- bool didmsg, doreset;
- char *reason;
- char freq_buf[512];
- char freq_chip_buf[15];
- memset(freq_buf, 0, sizeof(freq_buf));
- memset(freq_chip_buf, 0, sizeof(freq_chip_buf));
- for (j = 0; j < info->chips; j++)
- {
- struct ASIC_INFO *asjc = &info->asics[j];
- sprintf(freq_chip_buf, "[%d:%.2f]", j, asjc->frequency);
- strcat(freq_buf, freq_chip_buf);
- }
- applog(LOG_INFO,"%d: %s %d - %s",
- compac->cgminer_id, compac->drv->name, compac->device_id, freq_buf);
- if (info->plateau_reset < 3)
- {
- // Capture failure high frequency using first three resets
- if ((info->frequency - info->freq_base) > info->frequency_fail_high)
- info->frequency_fail_high = (info->frequency - info->freq_base);
- applog(LOG_WARNING,"%d: %s %d - asic plateau: [%u] (%d/3) %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- i, info->plateau_reset + 1, info->frequency_fail_high);
- }
- if (info->plateau_reset >= 2) {
- if (ms_tdiff(&now, &info->last_frequency_adjust) > MS_MINUTE_30) {
- // Been running for 30 minutes, possible plateau
- // Overlook the incident
- } else {
- // Step back frequency
- info->frequency_fail_high -= info->freq_base;
- }
- new_frequency = limit_freq(info, FREQ_BASE(info->frequency_fail_high), true);
- }
- info->plateau_reset++;
- asic->last_state = asic->state;
- asic->state = ASIC_HALFDEAD;
- cgtime(&asic->state_change_time);
- cgtime(&info->monitor_time);
- switch (plateau_type)
- {
- case PT_FREQNR:
- applog(info->log_wide,"%d: %s %d - no frequency reply from chip[%u] - %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id, i, info->frequency);
- asic->frequency_attempt = 0;
- reason = " FREQNR";
- break;
- case PT_FREQSET:
- applog(info->log_wide,"%d: %s %d - frequency set fail to chip[%u] - %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id, i, info->frequency);
- asic->frequency_attempt = 0;
- reason = " FREQSET";
- break;
- case PT_NONONCE:
- applog(info->log_wide,"%d: %s %d - missing nonces from chip[%u] - %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id, i, info->frequency);
- reason = " NONONCE";
- break;
- default:
- reason = NULL;
- break;
- }
- if (plateau_type == PT_NONONCE || info->asic_type == BM1387 || info->asic_type == BM1397)
- {
- // BM1384 is less tolerant to sudden drops in frequency.
- // Ignore other indicators except no nonce.
- doreset = true;
- }
- else
- doreset = false;
- didmsg = false;
- old_frequency = info->frequency_requested;
- if (new_frequency != old_frequency)
- {
- info->frequency_requested = new_frequency;
- applog(LOG_WARNING,"%d: %s %d - plateau%s [%u] adjust:%s target frequency %.2fMHz -> %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- reason ? : "", i, doreset ? " RESET" : "", old_frequency, new_frequency);
- didmsg = true;
- }
- if (doreset)
- {
- if (didmsg == false)
- {
- applog(LOG_WARNING,"%d: %s %d - plateau%s [%u] RESET at %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- reason ? : "", i, old_frequency);
- }
- info->mining_state = MINER_RESET;
- }
- // any plateau on 1 chip means no need to check the rest
- break;
- }
- }
- }
- if (!info->lock_freq
- && ms_tdiff(&now, &info->last_reset) < info->ramp_time)
- {
- // move running frequency towards target every second
- // initially or for up to ramp_time after a reset
- if ((plateau_type == 0)
- && (ms_tdiff(&now, &last_movement) > MS_SECOND_1)
- && (info->frequency < info->frequency_requested)
- && (info->gh.noncesum > GHNONCENEEDED))
- {
- float new_frequency = info->frequency + info->step_freq;
- if (new_frequency > info->frequency_requested)
- new_frequency = info->frequency_requested;
- frequency_updated = 1;
- change_freq_any(compac, new_frequency);
- cgtime(&last_movement);
- }
- }
- else
- {
- // after ramp_time regularly check the frequency vs hashrate
- // when we have enough nonces or gh is full
- if (!info->lock_freq
- && (info->gh.last == (GHNUM-1) || info->gh.noncesum > GHNONCES)
- && (ms_tdiff(&now, &info->tune_limit) >= MS_MINUTE_2))
- {
- float new_freq, prev_freq;
- double hash_for_freq, curr_hr;
- int nonces, last;
- prev_freq = info->frequency;
- mutex_lock(&info->ghlock);
- curr_hr = gekko_gh_hashrate(info, &now, true);
- nonces = info->gh.noncesum;
- last = info->gh.last;
- mutex_unlock(&info->ghlock);
- // verify with locked values
- if ((last == (GHNUM-1)) || (nonces > GHNONCES))
- {
- hash_for_freq = info->frequency * (double)(info->cores * info->chips);
- // a low hash rate means frequency may be too high
- if (curr_hr < (hash_for_freq * info->ghrequire))
- {
- new_freq = FREQ_BASE(info->frequency - (info->freq_base * 2));
- if (new_freq < info->min_freq)
- new_freq = FREQ_BASE(info->min_freq);
- if (info->frequency_requested > new_freq)
- info->frequency_requested = new_freq;
- if (info->frequency_start > new_freq)
- info->frequency_start = new_freq;
- applog(LOG_WARNING,"%d: %s %d - %.2fGH/s low [%.2f/%.2f/%d] reset limit %.2fMHz -> %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- curr_hr/1.0e3, hash_for_freq/1.0e3, hash_for_freq*info->ghrequire/1.0e3,
- nonces, prev_freq, new_freq);
- mutex_lock(&info->lock);
- frequency_updated = 1;
- change_freq_any(compac, info->frequency_start);
- // reset from start
- info->mining_state = MINER_RESET;
- mutex_unlock(&info->lock);
- continue;
- }
- cgtime(&info->tune_limit);
- // step the freq up one - environment may have changed to allow it
- if (opt_gekko_tune2 != 0
- && (info->frequency_requested < info->frequency_selected)
- && (tdiff(&now, &info->last_reset) >= ((double)opt_gekko_tune2 * 60.0))
- && (tdiff(&now, &info->last_tune_up) >= ((double)opt_gekko_tune2 * 60.0)))
- {
- new_freq = FREQ_BASE(info->frequency + info->freq_base);
- if (new_freq <= info->frequency_selected)
- {
- if (info->frequency_requested < new_freq)
- info->frequency_requested = new_freq;
- applog(LOG_WARNING,"%d: %s %d - tune up attempt (%.1fGH/s) %.2fMHz -> %.2fMHz",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- curr_hr/1.0e3, prev_freq, new_freq);
- // will reset if it doesn't improve,
- // as soon as it has enough nonces
- frequency_updated = 1;
- change_freq_any(compac, new_freq);
- }
- cgtime(&info->last_tune_up);
- }
- }
- }
- }
- if (!info->lock_freq
- && !frequency_updated
- && ms_tdiff(&now, &last_frequency_check) > 20)
- {
- cgtime(&last_frequency_check);
- for (i = 0; i < info->chips; i++)
- {
- struct ASIC_INFO *asic = &info->asics[i];
- if (asic->frequency_updated)
- {
- asic->frequency_updated = 0;
- info->frequency_of = i;
- if (info->asic_type != BM1397)
- ping_freq(compac, i);
- break;
- }
- }
- }
- }
- has_freq = false;
- for (i = 0; i < info->chips; i++)
- {
- if (info->asics[i].frequency != 0)
- {
- has_freq = true;
- break;
- }
- }
- // don't bother with work if it's not mining
- if (!has_freq)
- {
- gekko_usleep(info, MS2US(10));
- continue;
- }
- struct timeval stt, fin;
- double wd;
- // don't delay work updates when doing busy work
- if (info->work_usec_num > 1 && !last_was_busy)
- {
- // check if we got here early
- // and sleep almost the entire delay required
- cgtime(&now);
- diff_us = us_tdiff(&now, &info->last_task);
- left_us = info->max_task_wait - diff_us;
- if (left_us > 0)
- {
- // allow time for get_queued() + a bit
- left_us -= (info->work_usec_avg + USLEEPPLUS);
- if (left_us >= USLEEPMIN)
- gekko_usleep(info, left_us);
- }
- else
- {
- #if TUNE_CODE
- // ran over by 10us or more
- if (left_us <= -10)
- {
- info->over1num++;
- info->over1amt -= left_us;
- }
- #endif
- }
- }
- cgtime(&stt);
- work = get_queued(compac);
- if (work)
- {
- cgtime(&fin);
- wd = us_tdiff(&fin, &stt);
- if (info->work_usec_num == 0)
- info->work_usec_avg = wd;
- else
- {
- // fast work times should have a higher effect
- if (wd < (info->work_usec_avg / 2.0))
- info->work_usec_avg = (info->work_usec_avg + wd) / 2.0;
- else
- {
- // ignore extra long work times after we get a few
- if (info->work_usec_num > 5
- && (wd / 3.0) < info->work_usec_avg)
- {
- info->work_usec_avg =
- (info->work_usec_avg * 9.0 + wd) / 10.0;
- }
- }
- }
- info->work_usec_num++;
- if (last_was_busy)
- last_was_busy = false;
- #if TUNE_CODE
- diff_us = us_tdiff(&fin, &info->last_task);
- // stats if we got here too fast ...
- left_us = info->max_task_wait - diff_us;
- if (left_us < 0)
- {
- // ran over by 10us or more
- if (left_us <= -10)
- {
- info->over2num++;
- info->over2amt -= left_us;
- }
- }
- #endif
- if (opt_gekko_noboost)
- work->pool->vmask = 0;
- info->job_id += info->add_job_id;
- if (info->job_id > info->max_job_id)
- info->job_id = info->min_job_id;
- old_work = info->work[info->job_id];
- info->work[info->job_id] = work;
- info->active_work[info->job_id] = 1;
- info->vmask = work->pool->vmask;
- if (info->asic_type == BM1387 || info->asic_type == BM1397)
- {
- if (!opt_gekko_noboost && info->vmask)
- info->task_len = 54 + 32 * (info->midstates - 1);
- else
- info->task_len = 54;
- }
- init_task(info);
- }
- else
- {
- struct pool *cp;
- cp = current_pool();
- if (!cp->stratum_active)
- cgtime(&info->last_pool_lost);
- if (cp->stratum_active
- && (info->asic_type == BM1387 || info->asic_type == BM1397))
- {
- // get Dups instead of sending busy work
- // sleep 1ms then fast loop back
- gekko_usleep(info, MS2US(1));
- last_was_busy = true;
- continue;
- }
- busy_work(info);
- info->busy_work++;
- last_was_busy = true;
- cgtime(&info->monitor_time);
- applog(LOG_INFO, "%d: %s %d - Busy",
- compac->cgminer_id, compac->drv->name, compac->device_id);
- }
- int task_len = info->task_len;
- #if 0
- unsigned char jid = info->task[2];
- #endif
- if (info->asic_type == BM1397)
- {
- int k;
- for (k = (info->task_len - 1); k >= 0; k--)
- {
- info->task[k+2] = info->task[k];
- }
- info->task[0] = 0x55;
- info->task[1] = 0xaa;
- task_len += 2;
- }
- #if 0
- applog(LOG_ERR, "%s() %d: %s %d - Task [%02x] len %3u", __func__,
- compac->cgminer_id, compac->drv->name, compac->device_id, jid, task_len);
- applog(LOG_ERR, " [%02x %02x %02x %02x %02x %02x %02x %02x]",
- info->task[0], info->task[1], info->task[2], info->task[3], info->task[4], info->task[5], info->task[6], info->task[7]);
- applog(LOG_ERR, " [%02x %02x %02x %02x %02x %02x %02x %02x]",
- info->task[8], info->task[9], info->task[10], info->task[11], info->task[12], info->task[13], info->task[14], info->task[15]);
- applog(LOG_ERR, " [%02x %02x %02x %02x %02x %02x %02x %02x]",
- info->task[16], info->task[17], info->task[18], info->task[19], info->task[20], info->task[21], info->task[22], info->task[23]);
- applog(LOG_ERR, " [%02x %02x %02x %02x %02x %02x %02x %02x]",
- info->task[24], info->task[25], info->task[26], info->task[27], info->task[28], info->task[29], info->task[30], info->task[31]);
- #endif
- cgtime(&now); // set the time we actually sent it
- err = usb_write(compac, (char *)info->task, task_len, &sent_bytes, C_SENDWORK);
- //dumpbuffer(compac, LOG_WARNING, "TASK.TX", info->task, task_len);
- if (err != LIBUSB_SUCCESS)
- {
- applog(LOG_WARNING,"%d: %s %d - usb failure (%d)", compac->cgminer_id, compac->drv->name, compac->device_id, err);
- info->mining_state = MINER_RESET;
- continue;
- }
- if (sent_bytes != task_len)
- {
- if (ms_tdiff(&now, &info->last_write_error) > (5 * 1000)) {
- applog(LOG_WARNING,"%d: %s %d - usb write error [%d:%d]",
- compac->cgminer_id, compac->drv->name, compac->device_id, sent_bytes, task_len);
- cgtime(&info->last_write_error);
- }
- job_added = false;
- }
- else
- {
- // successfully sent work
- add_gekko_job(info, &now, false);
- job_added = true;
- }
- //let the usb frame propagate
- if (info->asic_type == BM1397 && info->usb_prop != 1000)
- gekko_usleep(info, info->usb_prop);
- else
- gekko_usleep(info, MS2US(1));
- info->task_ms = (info->task_ms * 9 + ms_tdiff(&now, &info->last_task)) / 10;
- info->last_task.tv_sec = now.tv_sec;
- info->last_task.tv_usec = now.tv_usec;
- if (info->first_task.tv_sec == 0L)
- {
- info->first_task.tv_sec = now.tv_sec;
- info->first_task.tv_usec = now.tv_usec;
- }
- info->tasks++;
- // work source changes can affect this e.g. 1 vs 4 midstates
- if (work && job_added
- && ms_tdiff(&now, &info->last_update_rates) > MS_SECOND_5)
- {
- compac_update_rates(compac);
- }
- }
- return NULL;
- }
- // not called by BM1397
- static void *compac_handle_rx(void *object, int read_bytes, int path)
- {
- struct cgpu_info *compac = (struct cgpu_info *)object;
- struct COMPAC_INFO *info = compac->device_data;
- struct ASIC_INFO *asic;
- int cmd_resp;
- unsigned int i;
- struct timeval now;
- cgtime(&now);
- cmd_resp = 0;
- if (info->rx[read_bytes-1] <= 0x1f)
- {
- if (bmcrc(info->rx, 8 * read_bytes - 5) == info->rx[read_bytes-1])
- cmd_resp = 1;
- }
- int log_level = (cmd_resp) ? LOG_INFO : LOG_INFO;
- if (path) {
- dumpbuffer(compac, log_level, "RX1", info->rx, read_bytes);
- } else {
- dumpbuffer(compac, log_level, "RX0", info->rx, read_bytes);
- }
- if (cmd_resp && info->rx[0] == 0x80 && info->frequency_of != (int)(info->chips)) {
- float frequency = 0.0;
- int frequency_of = info->frequency_of;
- info->frequency_of = info->chips;
- cgtime(&info->last_frequency_report);
- if (info->asic_type == BM1387 && (info->rx[2] == 0 || (info->rx[3] >> 4) == 0 || (info->rx[3] & 0x0f) != 1 || (info->rx[4]) != 0 || (info->rx[5]) != 0)) {
- cgtime(&info->last_frequency_invalid);
- applog(LOG_INFO,"%d: %s %d - invalid frequency report", compac->cgminer_id, compac->drv->name, compac->device_id);
- } else {
- if (info->asic_type == BM1387) {
- frequency = info->freq_mult * info->rx[1] / (info->rx[2] * (info->rx[3] >> 4) * (info->rx[3] & 0x0f));
- } else if (info->asic_type == BM1384) {
- frequency = (info->rx[1] + 1) * info->freq_base / ((1 + info->rx[2]) & 0x0f) * pow(2, (3 - info->rx[3])) + ((info->rx[2] >> 4) * info->freq_base);
- }
- if (frequency_of != (int)(info->chips)) {
- asic = &info->asics[frequency_of];
- cgtime(&asic->last_frequency_reply);
- if (frequency != asic->frequency) {
- bool syncd = 1;
- if (frequency < asic->frequency && frequency != info->frequency_requested) {
- applog(LOG_INFO,"%d: %s %d - chip[%d] reported frequency at %.2fMHz", compac->cgminer_id, compac->drv->name, compac->device_id, info->frequency_of, frequency);
- } else {
- applog(LOG_INFO,"%d: %s %d - chip[%d] reported new frequency of %.2fMHz", compac->cgminer_id, compac->drv->name, compac->device_id, info->frequency_of, frequency);
- }
- asic->frequency = frequency;
- if (asic->frequency == asic->frequency_set) {
- asic->frequency_attempt = 0;
- }
- for (i = 1; i < info->chips; i++) {
- if (info->asics[i].frequency != info->asics[i - 1].frequency) {
- syncd = 0;
- }
- }
- if (info->frequency_syncd != syncd) {
- info->frequency_syncd = syncd;
- applog(LOG_INFO,"%d: %s %d - syncd [%d]", compac->cgminer_id, compac->drv->name, compac->device_id, syncd);
- }
- } else {
- applog(LOG_INFO,"%d: %s %d - chip[%d] reported frequency of %.2fMHz", compac->cgminer_id, compac->drv->name, compac->device_id, info->frequency_of, frequency);
- }
- } else {
- //applog(LOG_INFO,"%d: %s %d - [-1] reported frequency of %.2fMHz", compac->cgminer_id, compac->drv->name, compac->device_id, frequency);
- //if (frequency != info->frequency) {
- // info->frequency = frequency;
- //}
- }
- compac_update_rates(compac);
- }
- }
- switch (info->mining_state) {
- case MINER_CHIP_COUNT:
- case MINER_CHIP_COUNT_XX:
- if (cmd_resp && (info->rx[0] == 0x13 ||
- (info->rx[0] == 0xaa && info->rx[1] == 0x55 && info->rx[2] == 0x13))) { // BM1397
- struct ASIC_INFO *asic = &info->asics[info->chips];
- memset(asic, 0, sizeof(struct ASIC_INFO));
- asic->frequency = info->frequency_default;
- asic->frequency_attempt = 0;
- asic->last_frequency_ping = (struct timeval){0};
- asic->last_frequency_reply = (struct timeval){0};
- cgtime(&asic->last_nonce);
- info->chips++;
- info->mining_state = MINER_CHIP_COUNT_XX;
- compac_update_rates(compac);
- }
- break;
- case MINER_OPEN_CORE:
- if ((info->rx[0] == 0x72 && info->rx[1] == 0x03 && info->rx[2] == 0xEA && info->rx[3] == 0x83) ||
- (info->rx[0] == 0xE1 && info->rx[1] == 0x6B && info->rx[2] == 0xF8 && info->rx[3] == 0x09)) {
- //open core nonces = healthy chips.
- info->zero_check++;
- }
- break;
- case MINER_MINING:
- if (!cmd_resp) {
- #ifdef __APPLE__
- if (opt_mac_yield)
- sched_yield();
- #else
- selective_yield();
- #endif
- mutex_lock(&info->lock);
- info->hashes += compac_check_nonce(compac);
- mutex_unlock(&info->lock);
- }
- break;
- default:
- break;
- }
- return NULL;
- }
- static void *compac_gsf_nonce_que(void *object)
- {
- struct cgpu_info *compac = (struct cgpu_info *)object;
- struct COMPAC_INFO *info = compac->device_data;
- struct timespec abstime, addtime;
- K_ITEM *item;
- int rc;
- if (info->asic_type != BM1397)
- return NULL;
- // wait at most 42ms for a nonce
- ms_to_timespec(&addtime, 42);
- while (info->mining_state != MINER_SHUTDOWN)
- {
- K_WLOCK(info->nlist);
- item = k_unlink_head(info->nstore);
- K_WUNLOCK(info->nlist);
- if (item)
- {
- compac_gsf_nonce(compac, item);
- K_WLOCK(info->nlist);
- k_add_head(info->nlist, item);
- K_WUNLOCK(info->nlist);
- }
- else
- {
- cgcond_time(&abstime);
- timeraddspec(&abstime, &addtime);
- mutex_lock(&info->nlock);
- rc = pthread_cond_timedwait(&info->ncond, &info->nlock, &abstime);
- mutex_unlock(&info->nlock);
- if (rc == ETIMEDOUT)
- info->ntimeout++;
- else
- info->ntrigger++;
- }
- }
- return NULL;
- }
- static bool gsf_reply(struct COMPAC_INFO *info, unsigned char *rx, int len, struct timeval *now)
- {
- unsigned char fa, fb, fc1, fc2;
- bool used = false;
- if (len == (int)(info->rx_len) && rx[7] == BM1397FREQ)
- {
- int chip = TOCHIPPY1397(info, rx[6]);
- if (chip >= 0 && chip < (int)(info->chips))
- {
- struct ASIC_INFO *asic = &info->asics[chip];
- fa = rx[3];
- fb = rx[4];
- fc1 = (rx[5] & 0xf0) >> 4;
- fc2 = rx[5] & 0x0f;
- // only allow a valid reply
- if (fa >= 0 && fb > 0 && fc1 > 0 && fc2 > 0)
- {
- asic->frequency_reply = info->freq_mult * fa / fb / fc1 / fc2;
- asic->last_frequency_reply.tv_sec = now->tv_sec;
- asic->last_frequency_reply.tv_usec = now->tv_usec;
- used = true;
- }
- }
- }
- return used;
- }
- static void *compac_listen2(struct cgpu_info *compac, struct COMPAC_INFO *info)
- {
- unsigned char rx[BUFFER_MAX];
- struct timeval now;
- int read_bytes, tmo, pos = 0, len, i, prelen;
- bool okcrc, used, chipped;
- K_ITEM *item;
- memset(rx, 0, sizeof(rx));
- while (info->mining_state != MINER_SHUTDOWN)
- {
- tmo = 20;
- if (info->mining_state == MINER_CHIP_COUNT)
- {
- unsigned char chippy[] = {0x52, 0x05, 0x00, 0x00, 0x0A};
- compac_send2(compac, chippy, sizeof(chippy), 8 * sizeof(chippy) - 8, "CHIPPY");
- info->mining_state = MINER_CHIP_COUNT_XX;
- // initial config reply allow much longer
- tmo = 1000;
- }
- usb_read_timeout(compac, ((char *)rx)+pos, BUFFER_MAX-pos, &read_bytes, tmo, C_GETRESULTS);
- pos += read_bytes;
- cgtime(&now);
- // all replies should be info->rx_len
- while (read_bytes > 0 && pos >= (int)(info->rx_len))
- {
- #if 0
- applog(LOG_ERR, "%d: %s %d - READ %3d pos %3d state %2d first 16: [%02x %02x %02x %02x %02x %02x %02x %02x]",
- compac->cgminer_id, compac->drv->name, compac->device_id, read_bytes, pos, info->mining_state,
- rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
- applog(LOG_ERR, " [%02x %02x %02x %02x %02x %02x %02x %02x]",
- rx[8], rx[9], rx[10], rx[11], rx[12], rx[13], rx[14], rx[15]);
- #endif
- // rubbish - skip over it to next 0xaa
- if (rx[0] != 0xaa || rx[1] != 0x55)
- {
- for (i = 1; i < pos; i++)
- {
- if (rx[i] == 0xaa)
- {
- // next read could be 0x55 or i+1=0x55
- if (i == (pos - 1) || rx[i+1] == 0x55)
- break;
- }
- }
- // no 0xaa dump it and wait for more data
- if (i >= pos)
- {
- #if 0
- applog(LOG_ERR, " %s %d no 0xaa = dump all (%d) [%02x %02x %02x %02x ...]",
- compac->drv->name, compac->device_id, pos, rx[0], rx[1], rx[2], rx[3]);
- #endif
- pos = 0;
- continue;
- }
- #if 0
- applog(LOG_ERR, " %s %d dump before %d=0xaa [%02x %02x %02x %02x ...]",
- compac->drv->name, compac->device_id, i, rx[0], rx[1], rx[2], rx[3]);
- #endif
- // i=0xaa dump up to i-1
- memmove(rx, rx+i, pos-i);
- pos -= i;
- if (pos < (int)(info->rx_len))
- continue;
- }
- // find next 0xaa 0x55
- for (len = info->rx_len; len < pos; len++)
- {
- if (rx[len] == 0xaa
- && (len == (pos-1) || rx[len+1] == 0x55))
- break;
- }
- prelen = len;
- // a reply followed by only 0xaa but no 0x55 yet
- if (len == pos && (len == 8 || len == 10) && rx[pos-1] == 0xaa)
- len--;
- // try it as a nonce
- if (len != (int)(info->rx_len))
- len = info->rx_len;
- #if 0
- if (info->asic_type == BM1397 &&
- bmcrc(&rx[i+2], 8 * (info->rx_len-2) - 5) == (rx[i + info->rx_len - 1] & 0x1f)) {
- // crc checksum is good
- crc_match = true;
- rx_okay = true;
- }
- if (info->asic_type == BM1397 && rx[0] >= 0xaa && rx[1] <= 0x55) {
- // bm1397 response
- rx_okay = true;
- }
- #endif
- if (rx[len-1] <= 0x1f
- && bmcrc(rx+2, 8 * (len-2) - 5) == rx[len-1])
- okcrc = true;
- else
- okcrc = false;
- switch (info->mining_state)
- {
- case MINER_CHIP_COUNT:
- case MINER_CHIP_COUNT_XX:
- // BM1397
- chipped = false;
- if (rx[2] == 0x13 && rx[3] == 0x97)
- {
- struct ASIC_INFO *asic = &info->asics[info->chips];
- memset(asic, 0, sizeof(struct ASIC_INFO));
- asic->frequency = info->frequency_default;
- asic->frequency_attempt = 0;
- asic->last_frequency_ping = (struct timeval){0};
- asic->frequency_reply = -1;
- asic->last_frequency_reply = (struct timeval){0};
- cgtime(&asic->last_nonce);
- info->chips++;
- info->mining_state = MINER_CHIP_COUNT_XX;
- compac_update_rates(compac);
- chipped = true;
- }
- // ignore all data until we get at least 1 chip reply
- if (!chipped && info->mining_state == MINER_CHIP_COUNT_XX)
- {
- // we found some chips then it replied with other data ...
- if (info->chips > 0)
- {
- info->mining_state = MINER_CHIP_COUNT_OK;
- mutex_lock(&static_lock);
- (*init_count) = 0;
- info->init_count = 0;
- mutex_unlock(&static_lock);
- // don't discard the data
- if (len == (int)(info->rx_len) && okcrc)
- gsf_reply(info, rx, info->rx_len, &now);
- }
- else
- info->mining_state = MINER_RESET;
- }
- break;
- case MINER_MINING:
- used = false;
- if (len == (int)(info->rx_len) && okcrc)
- {
- used = gsf_reply(info, rx, info->rx_len, &now);
- #if 0
- if (!used)
- {
- applog(LOG_ERR, "%d: %s %d - ? len %3d state %2d first 12:",
- compac->cgminer_id, compac->drv->name, compac->device_id, len, info->mining_state);
- applog(LOG_ERR, " [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
- rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7], rx[8], rx[9], rx[10], rx[11]);
- }
- #endif
- }
- // also try unidentifed crc's as a nonce
- if (!used)
- {
- K_WLOCK(info->nlist);
- item = k_unlink_head(info->nlist);
- K_WUNLOCK(info->nlist);
- DATA_NONCE(item)->asic = 0;
- // should never be true ...
- if (len > (int)sizeof(DATA_NONCE(item)->rx))
- len = (int)sizeof(DATA_NONCE(item)->rx);
- memcpy(DATA_NONCE(item)->rx, rx, len);
- DATA_NONCE(item)->len = len;
- DATA_NONCE(item)->prelen = prelen;
- DATA_NONCE(item)->when.tv_sec = now.tv_sec;
- DATA_NONCE(item)->when.tv_usec = now.tv_usec;
- K_WLOCK(info->nlist);
- k_add_tail(info->nstore, item);
- K_WUNLOCK(info->nlist);
- mutex_lock(&info->nlock);
- pthread_cond_signal(&info->ncond);
- mutex_unlock(&info->nlock);
- }
- break;
- default:
- used = false;
- if (len == (int)(info->rx_len) && okcrc)
- used = gsf_reply(info, rx, info->rx_len, &now);
- #if 0
- if (!used)
- {
- applog(LOG_ERR, "%d: %s %d - unhandled, len %3d state %2d first 12:",
- compac->cgminer_id, compac->drv->name, compac->device_id, len, info->mining_state);
- applog(LOG_ERR, " [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
- rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7], rx[8], rx[9], rx[10], rx[11]);
- }
- #endif
- break;
- }
- // we've used up 0..len-1
- if (pos > len)
- memmove(rx, rx+len, pos-len);
- pos -= len;
- }
- if (read_bytes == 0 || pos < 6)
- {
- if (info->mining_state == MINER_CHIP_COUNT_XX)
- {
- if (info->chips < info->expected_chips)
- info->mining_state = MINER_RESET;
- else
- {
- if (info->chips > 0)
- {
- info->mining_state = MINER_CHIP_COUNT_OK;
- mutex_lock(&static_lock);
- (*init_count) = 0;
- info->init_count = 0;
- mutex_unlock(&static_lock);
- }
- else
- info->mining_state = MINER_RESET;
- }
- }
- }
- }
- return NULL;
- }
- static void *compac_listen(void *object)
- {
- struct cgpu_info *compac = (struct cgpu_info *)object;
- struct COMPAC_INFO *info = compac->device_data;
- if (info->asic_type == BM1397)
- return compac_listen2(compac, info);
- struct timeval now;
- unsigned char rx[BUFFER_MAX];
- unsigned char *prx = rx;
- int read_bytes, cmd_resp, pos;
- unsigned int i, rx_bytes;
- memset(rx, 0, sizeof(rx));
- memset(info->rx, 0, sizeof(info->rx));
- pos = 0;
- rx_bytes = 0;
- while (info->mining_state != MINER_SHUTDOWN) {
- cgtime(&now);
- if (info->mining_state == MINER_CHIP_COUNT) {
- if (info->asic_type == BM1387) {
- unsigned char buffer[] = {0x54, 0x05, 0x00, 0x00, 0x00};
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 8);
- } else if (info->asic_type == BM1384) {
- unsigned char buffer[] = {0x84, 0x00, 0x00, 0x00};
- compac_send(compac, buffer, sizeof(buffer), 8 * sizeof(buffer) - 5);
- }
- usb_read_timeout(compac, (char *)rx, BUFFER_MAX, &read_bytes, 1000, C_GETRESULTS);
- dumpbuffer(compac, LOG_INFO, "CMD.RX", rx, read_bytes);
- rx_bytes = (unsigned int)read_bytes;
- info->mining_state = MINER_CHIP_COUNT_XX;
- } else {
- if (rx_bytes >= (BUFFER_MAX - info->rx_len)) {
- applog(LOG_INFO, "%d: %s %d - Buffer not useful, dumping (b) %d bytes", compac->cgminer_id, compac->drv->name, compac->device_id, rx_bytes);
- dumpbuffer(compac, LOG_INFO, "NO-CRC-RX", rx, rx_bytes);
- pos = 0;
- rx_bytes = 0;
- }
- usb_read_timeout(compac, (char *)(&rx[pos]), info->rx_len, &read_bytes, 20, C_GETRESULTS);
- rx_bytes += read_bytes;
- pos = rx_bytes;
- }
- if (read_bytes > 0) {
- if (rx_bytes < info->rx_len) {
- applog(LOG_INFO, "%d: %s %d - Buffered %d bytes", compac->cgminer_id, compac->drv->name, compac->device_id, rx_bytes);
- dumpbuffer(compac, LOG_INFO, "Partial-RX", rx, rx_bytes);
- continue;
- }
- if (rx_bytes >= info->rx_len)
- cmd_resp = (rx[read_bytes - 1] <= 0x1f && bmcrc(prx, 8 * read_bytes - 5) == rx[read_bytes - 1]) ? 1 : 0;
- if (info->mining_state == MINER_CHIP_COUNT_XX || cmd_resp) {
- if (rx_bytes % info->rx_len == 2) {
- // fix up trial 1
- int shift = 0;
- int extra = 0;
- for (i = 0; i < (rx_bytes - shift); i++) {
- if (rx[i] == 0x01) {
- shift = 2;
- extra = rx[i + 1];
- }
- rx[i] = rx[i + shift];
- }
- rx_bytes -= shift;
- pos = rx_bytes;
- applog(LOG_INFO, "%d: %s %d - Extra Data - 0x01 0x%02x", compac->cgminer_id, compac->drv->name, compac->device_id, extra & 0xff);
- }
- }
- if (rx_bytes >= info->rx_len) {
- bool crc_match = false;
- unsigned int new_pos = 0;
- for (i = 0; i <= (rx_bytes - info->rx_len); i++) {
- bool rx_okay = false;
- if (bmcrc(&rx[i], 8 * info->rx_len - 5) == (rx[i + info->rx_len - 1] & 0x1f)) {
- // crc checksum is good
- crc_match = true;
- rx_okay = true;
- }
- if (info->asic_type == BM1384 && rx[i + info->rx_len - 1] >= 0x80 && rx[i + info->rx_len - 1] <= 0x9f) {
- // bm1384 nonce
- rx_okay = true;
- }
- if (rx_okay) {
- memcpy(info->rx, &rx[i], info->rx_len);
- compac_handle_rx(compac, info->rx_len, 0);
- new_pos = i + info->rx_len;
- }
- }
- if (new_pos > rx_bytes) {
- rx_bytes = 0;
- pos = 0;
- } else if (new_pos > 0) {
- for (i = new_pos; i < rx_bytes; i++) {
- rx[i - new_pos] = rx[i];
- }
- rx_bytes -= new_pos;
- pos = rx_bytes;
- }
- }
- /*
- if (bmcrc(&rx[rx_bytes - info->rx_len], 8 * info->rx_len - 5) != info->rx[rx_bytes - 1]) {
- int n_read_bytes;
- pos = rx_bytes;
- usb_read_timeout(compac, &rx[pos], BUFFER_MAX - pos, &n_read_bytes, 5, C_GETRESULTS);
- rx_bytes += n_read_bytes;
- if (rx_bytes % info->rx_len != 0 && rx_bytes >= info->rx_len) {
- int extra_bytes = rx_bytes % info->rx_len;
- for (i = extra_bytes; i < rx_bytes; i++) {
- rx[i - extra_bytes] = rx[i];
- }
- rx_bytes -= extra_bytes;
- applog(LOG_INFO, "%d: %s %d - Fixing buffer alignment, dumping initial %d bytes", compac->cgminer_id, compac->drv->name, compac->device_id, extra_bytes);
- }
- }
- if (rx_bytes % info->rx_len == 0) {
- for (i = 0; i < rx_bytes; i += info->rx_len) {
- memcpy(info->rx, &rx[i], info->rx_len);
- compac_handle_rx(compac, info->rx_len, 1);
- }
- pos = 0;
- rx_bytes = 0;
- }
- */
- } else {
- if (rx_bytes > 0) {
- applog(LOG_INFO, "%d: %s %d - Second read, no data dumping (c) %d bytes", compac->cgminer_id, compac->drv->name, compac->device_id, rx_bytes);
- dumpbuffer(compac, LOG_INFO, "EXTRA-RX", rx, rx_bytes);
- }
- pos = 0;
- rx_bytes = 0;
- // RX line is idle, let's squeeze in a command to the micro if needed.
- if (info->asic_type == BM1387) {
- if (ms_tdiff(&now, &info->last_micro_ping) > MS_SECOND_5 && ms_tdiff(&now, &info->last_task) > 1 && ms_tdiff(&now, &info->last_task) < 3) {
- compac_micro_send(compac, M1_GET_TEMP, 0x00, 0x00);
- cgtime(&info->last_micro_ping);
- }
- }
- switch (info->mining_state) {
- case MINER_CHIP_COUNT_XX:
- if (info->chips < info->expected_chips) {
- applog(LOG_INFO, "%d: %s %d - found %d/%d chip(s)", compac->cgminer_id, compac->drv->name, compac->device_id, info->chips, info->expected_chips);
- info->mining_state = MINER_RESET;
- } else {
- applog(LOG_INFO, "%d: %s %d - found %d chip(s)", compac->cgminer_id, compac->drv->name, compac->device_id, info->chips);
- if (info->chips > 0) {
- info->mining_state = MINER_CHIP_COUNT_OK;
- mutex_lock(&static_lock);
- (*init_count) = 0;
- info->init_count = 0;
- mutex_unlock(&static_lock);
- } else {
- info->mining_state = MINER_RESET;
- }
- }
- break;
- default:
- break;
- }
- }
- }
- return NULL;
- }
- static bool compac_init(struct thr_info *thr)
- {
- int i;
- struct cgpu_info *compac = thr->cgpu;
- struct COMPAC_INFO *info = compac->device_data;
- float step_freq;
- // all are currently this value
- info->freq_mult = 25.0;
- // most are this value (6.25)
- info->freq_base = info->freq_mult / 4.0;
- // correct some options
- if (opt_gekko_tune_down > 100)
- opt_gekko_tune_down = 100;
- if (opt_gekko_tune_up > 99)
- opt_gekko_tune_up = 99;
- opt_gekko_wait_factor = fbound(opt_gekko_wait_factor, 0.01, 2.0);
- info->wait_factor0 = opt_gekko_wait_factor;
- if (opt_gekko_start_freq < 25)
- opt_gekko_start_freq = 25;
- if (opt_gekko_step_freq < 1)
- opt_gekko_step_freq = 1;
- if (opt_gekko_step_delay < 1)
- opt_gekko_step_delay = 1;
- // must limit it to allow tune downs before trying again
- if (opt_gekko_tune2 < 30 && opt_gekko_tune2 != 0)
- opt_gekko_tune2 = 30;
- info->boosted = false;
- info->prev_nonce = 0;
- info->fail_count = 0;
- info->busy_work = 0;
- info->log_wide = (opt_widescreen) ? LOG_WARNING : LOG_INFO;
- info->plateau_reset = 0;
- info->low_eff_resets = 0;
- info->frequency_fail_high = 0;
- info->frequency_fail_low = 999;
- info->frequency_fo = info->chips;
- info->first_task.tv_sec = 0L;
- info->first_task.tv_usec = 0L;
- info->tasks = 0;
- info->tune_limit.tv_sec = 0L;
- info->tune_limit.tv_usec = 0L;
- info->last_tune_up.tv_sec = 0L;
- info->last_tune_up.tv_usec = 0L;
- memset(info->rx, 0, sizeof(info->rx));
- memset(info->tx, 0, sizeof(info->tx));
- memset(info->cmd, 0, sizeof(info->cmd));
- memset(info->end, 0, sizeof(info->end));
- memset(info->task, 0, sizeof(info->task));
- for (i = 0; i < JOB_MAX; i++) {
- info->active_work[i] = false;
- info->work[i] = NULL;
- }
- memset(&(info->gh), 0, sizeof(info->gh));
- cgtime(&info->last_write_error);
- cgtime(&info->last_frequency_adjust);
- cgtime(&info->last_computed_increase);
- cgtime(&info->last_low_eff_reset);
- info->last_frequency_invalid = (struct timeval){0};
- cgtime(&info->last_micro_ping);
- cgtime(&info->last_scanhash);
- cgtime(&info->last_reset);
- cgtime(&info->last_task);
- cgtime(&info->start_time);
- cgtime(&info->monitor_time);
- info->step_freq = FREQ_BASE(opt_gekko_step_freq);
- // if it can't mine at this freq the hardware has failed
- info->min_freq = info->freq_mult;
- // most should only take this long
- info->ramp_time = MS_MINUTE_3;
- info->ghrequire = GHREQUIRE;
- info->freq_fail = 0.0;
- info->hr_scale = 1.0;
- info->usb_prop = 1000;
- switch (info->ident)
- {
- case IDENT_BSC:
- case IDENT_GSC:
- info->frequency_requested = limit_freq(info, opt_gekko_gsc_freq, false);
- info->frequency_start = limit_freq(info, opt_gekko_start_freq, false);
- break;
- case IDENT_BSD:
- case IDENT_GSD:
- info->frequency_requested = limit_freq(info, opt_gekko_gsd_freq, false);
- info->frequency_start = limit_freq(info, opt_gekko_start_freq, false);
- break;
- case IDENT_BSE:
- case IDENT_GSE:
- info->frequency_requested = limit_freq(info, opt_gekko_gse_freq, false);
- info->frequency_start = limit_freq(info, opt_gekko_start_freq, false);
- break;
- case IDENT_GSH:
- info->frequency_requested = limit_freq(info, opt_gekko_gsh_freq, false);
- info->frequency_start = limit_freq(info, opt_gekko_start_freq, false);
- break;
- case IDENT_GSI:
- info->frequency_requested = limit_freq(info, opt_gekko_gsi_freq, false);
- info->frequency_start = limit_freq(info, opt_gekko_start_freq, false);
- // default to 550
- if (info->frequency_start == 100)
- info->frequency_start = 550;
- if (info->frequency_start < 100)
- info->frequency_start = 100;
- // due to higher freq allow longer
- info->ramp_time = MS_MINUTE_4;
- break;
- case IDENT_GSF:
- case IDENT_GSFM:
- if (info->ident == IDENT_GSF)
- info->frequency_requested = limit_freq(info, opt_gekko_gsf_freq, false);
- else
- info->frequency_requested = limit_freq(info, opt_gekko_r909_freq, false);
- info->frequency_start = limit_freq(info, opt_gekko_start_freq, false);
- if (info->frequency_start < 100)
- info->frequency_start = 100;
- if (info->frequency_start == 100)
- {
- if (info->ident == IDENT_GSF)
- {
- // default to 200
- info->frequency_start = 200;
- }
- else // (info->ident == IDENT_GSFM)
- {
- // default to 400
- info->frequency_start = 400;
- }
- }
- // ensure request is >= start
- if (info->frequency_requested < info->frequency_start)
- info->frequency_requested = info->frequency_start;
- // correct the defaults:
- info->freq_base = info->freq_mult / 5.0;
- step_freq = opt_gekko_step_freq;
- if (step_freq == 6.25)
- step_freq = 5.0;
- info->step_freq = FREQ_BASE(step_freq);
- // IDENT_GSFM runs at the more reliable higher frequencies
- if (info->ident == IDENT_GSF)
- {
- // chips can get lower than the calculated 67.2 at lower freq
- info->hr_scale = 52.5 / 67.2;
- }
- // due to ticket mask allow longer
- info->ramp_time = MS_MINUTE_5;
- break;
- default:
- info->frequency_requested = 200;
- info->frequency_start = info->frequency_requested;
- break;
- }
- if (info->frequency_start > info->frequency_requested) {
- info->frequency_start = info->frequency_requested;
- }
- info->frequency_requested = FREQ_BASE(info->frequency_requested);
- info->frequency_selected = info->frequency_requested;
- info->frequency_start = FREQ_BASE(info->frequency_start);
- info->frequency = info->frequency_start;
- info->frequency_default = info->frequency_start;
- if (!info->rthr.pth) {
- pthread_mutex_init(&info->lock, NULL);
- pthread_mutex_init(&info->wlock, NULL);
- pthread_mutex_init(&info->rlock, NULL);
- pthread_mutex_init(&info->ghlock, NULL);
- pthread_mutex_init(&info->joblock, NULL);
- if (info->ident == IDENT_GSF || info->ident == IDENT_GSFM)
- {
- info->nlist = k_new_list("GekkoNonces", sizeof(struct COMPAC_NONCE),
- ALLOC_NLIST_ITEMS, LIMIT_NLIST_ITEMS, true);
- info->nstore = k_new_store(info->nlist);
- }
- if (thr_info_create(&(info->rthr), NULL, compac_listen, (void *)compac)) {
- applog(LOG_ERR, "%d: %s %d - read thread create failed", compac->cgminer_id, compac->drv->name, compac->device_id);
- return false;
- } else {
- applog(LOG_INFO, "%d: %s %d - read thread created", compac->cgminer_id, compac->drv->name, compac->device_id);
- }
- pthread_detach(info->rthr.pth);
- gekko_usleep(info, MS2US(100));
- if (thr_info_create(&(info->wthr), NULL, compac_mine2, (void *)compac)) {
- applog(LOG_ERR, "%d: %s %d - write thread create failed", compac->cgminer_id, compac->drv->name, compac->device_id);
- return false;
- } else {
- applog(LOG_INFO, "%d: %s %d - write thread created", compac->cgminer_id, compac->drv->name, compac->device_id);
- }
- pthread_detach(info->wthr.pth);
- if (info->ident == IDENT_GSF || info->ident == IDENT_GSFM)
- {
- gekko_usleep(info, MS2US(10));
- if (pthread_mutex_init(&info->nlock, NULL))
- {
- applog(LOG_ERR, "%d: %s %d - nonce mutex create failed",
- compac->cgminer_id, compac->drv->name, compac->device_id);
- return false;
- }
- if (pthread_cond_init(&info->ncond, NULL))
- {
- applog(LOG_ERR, "%d: %s %d - nonce cond create failed",
- compac->cgminer_id, compac->drv->name, compac->device_id);
- return false;
- }
- if (thr_info_create(&(info->nthr), NULL, compac_gsf_nonce_que, (void *)compac))
- {
- applog(LOG_ERR, "%d: %s %d - nonce thread create failed",
- compac->cgminer_id, compac->drv->name, compac->device_id);
- return false;
- }
- else
- {
- applog(LOG_INFO, "%d: %s %d - nonce thread created",
- compac->cgminer_id, compac->drv->name, compac->device_id);
- }
- pthread_detach(info->nthr.pth);
- }
- }
- return true;
- }
- static int64_t compac_scanwork(struct thr_info *thr)
- {
- struct cgpu_info *compac = thr->cgpu;
- struct COMPAC_INFO *info = compac->device_data;
- struct timeval now;
- int read_bytes;
- // uint64_t hashes = 0;
- uint64_t xhashes = 0;
- if (info->chips == 0)
- gekko_usleep(info, MS2US(10));
- if (compac->usbinfo.nodev)
- return -1;
- #ifdef __APPLE__
- if (opt_mac_yield)
- sched_yield();
- #else
- selective_yield();
- #endif
- cgtime(&now);
- switch (info->mining_state) {
- case MINER_INIT:
- gekko_usleep(info, MS2US(50));
- compac_flush_buffer(compac);
- info->chips = 0;
- info->ramping = 0;
- info->frequency_syncd = 1;
- if (info->frequency_start > info->frequency_requested) {
- info->frequency_start = info->frequency_requested;
- }
- info->mining_state = MINER_CHIP_COUNT;
- return 0;
- break;
- case MINER_CHIP_COUNT:
- if (ms_tdiff(&now, &info->last_reset) > MS_SECOND_5) {
- applog(LOG_INFO, "%d: %s %d - found 0 chip(s)", compac->cgminer_id, compac->drv->name, compac->device_id);
- info->mining_state = MINER_RESET;
- return 0;
- }
- gekko_usleep(info, MS2US(10));
- break;
- case MINER_CHIP_COUNT_OK:
- gekko_usleep(info, MS2US(50));
- //compac_set_frequency(compac, info->frequency_start);
- compac_send_chain_inactive(compac);
- if (info->asic_type == BM1397)
- info->mining_state = MINER_OPEN_CORE_OK;
- return 0;
- break;
- case MINER_OPEN_CORE:
- info->job_id = info->ramping % (info->max_job_id + 1);
- //info->task_hcn = (0xffffffff / info->chips) * (1 + info->ramping) / info->cores;
- init_task(info);
- dumpbuffer(compac, LOG_DEBUG, "RAMP", info->task, info->task_len);
- usb_write(compac, (char *)info->task, info->task_len, &read_bytes, C_SENDWORK);
- if (info->ramping > (info->cores * info->add_job_id)) {
- //info->job_id = 0;
- info->mining_state = MINER_OPEN_CORE_OK;
- info->task_hcn = (0xffffffff / info->chips);
- return 0;
- }
- info->ramping += info->add_job_id;
- info->task_ms = (info->task_ms * 9 + ms_tdiff(&now, &info->last_task)) / 10;
- cgtime(&info->last_task);
- gekko_usleep(info, MS2US(10));
- return 0;
- break;
- case MINER_OPEN_CORE_OK:
- applog(LOG_INFO, "%d: %s %d - start work", compac->cgminer_id, compac->drv->name, compac->device_id);
- if (info->asic_type == BM1397)
- gsf_calc_nb2c(compac);
- cgtime(&info->start_time);
- cgtime(&info->monitor_time);
- cgtime(&info->last_frequency_adjust);
- info->last_dup_time = (struct timeval){0};
- cgtime(&info->last_frequency_report);
- cgtime(&info->last_micro_ping);
- cgtime(&info->last_nonce);
- compac_flush_buffer(compac);
- compac_update_rates(compac);
- info->update_work = 1;
- info->mining_state = MINER_MINING;
- return 0;
- break;
- case MINER_MINING:
- break;
- case MINER_RESET:
- compac_flush_work(compac);
- if (info->asic_type == BM1387 || info->asic_type == BM1397) {
- compac_toggle_reset(compac);
- } else if (info->asic_type == BM1384) {
- compac_set_frequency(compac, info->frequency_default);
- //compac_send_chain_inactive(compac);
- }
- compac_prepare(thr);
- info->fail_count++;
- info->dupsreset = 0;
- info->mining_state = MINER_INIT;
- cgtime(&info->last_reset);
- // in case clock jumps back ...
- cgtime(&info->tune_limit);
- // wipe info->gh/asic->gc
- gh_offset(info, &now, true, false);
- // wipe info->job
- job_offset(info, &now, true, false);
- // reset P:
- info->frequency_computed = 0;
- return 0;
- break;
- case MINER_MINING_DUPS:
- info->mining_state = MINER_MINING;
- break;
- default:
- break;
- }
- mutex_lock(&info->lock);
- // hashes = info->hashes;
- xhashes = info->xhashes;
- info->hashes = 0;
- info->xhashes = 0;
- mutex_unlock(&info->lock);
- gekko_usleep(info, MS2US(1));
- return xhashes * 0xffffffffull;
- //return hashes;
- }
- static struct cgpu_info *compac_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
- {
- struct cgpu_info *compac;
- struct COMPAC_INFO *info;
- int i;
- bool exclude_me = 0;
- uint32_t baudrate = CP210X_DATA_BAUD;
- unsigned int bits = CP210X_BITS_DATA_8 | CP210X_BITS_PARITY_MARK;
- compac = usb_alloc_cgpu(&gekko_drv, 1);
- if (!usb_init(compac, dev, found))
- {
- applog(LOG_INFO, "failed usb_init");
- compac = usb_free_cgpu(compac);
- return NULL;
- }
- // all zero
- info = cgcalloc(1, sizeof(struct COMPAC_INFO));
- #if TUNE_CODE
- pthread_mutex_init(&info->slock, NULL);
- #endif
- compac->device_data = (void *)info;
- info->ident = usb_ident(compac);
- if (opt_gekko_gsc_detect || opt_gekko_gsd_detect || opt_gekko_gse_detect
- || opt_gekko_gsh_detect || opt_gekko_gsi_detect || opt_gekko_gsf_detect
- || opt_gekko_r909_detect)
- {
- exclude_me = (info->ident == IDENT_BSC && !opt_gekko_gsc_detect);
- exclude_me |= (info->ident == IDENT_GSC && !opt_gekko_gsc_detect);
- exclude_me |= (info->ident == IDENT_BSD && !opt_gekko_gsd_detect);
- exclude_me |= (info->ident == IDENT_GSD && !opt_gekko_gsd_detect);
- exclude_me |= (info->ident == IDENT_BSE && !opt_gekko_gse_detect);
- exclude_me |= (info->ident == IDENT_GSE && !opt_gekko_gse_detect);
- exclude_me |= (info->ident == IDENT_GSH && !opt_gekko_gsh_detect);
- exclude_me |= (info->ident == IDENT_GSI && !opt_gekko_gsi_detect);
- exclude_me |= (info->ident == IDENT_GSF && !opt_gekko_gsf_detect);
- exclude_me |= (info->ident == IDENT_GSFM && !opt_gekko_r909_detect);
- }
- if (opt_gekko_serial != NULL
- && (strstr(opt_gekko_serial, compac->usbdev->serial_string) == NULL))
- {
- exclude_me = true;
- }
- if (exclude_me)
- {
- usb_uninit(compac);
- free(info);
- compac->device_data = NULL;
- return NULL;
- }
- switch (info->ident)
- {
- case IDENT_BSC:
- case IDENT_GSC:
- case IDENT_BSD:
- case IDENT_GSD:
- case IDENT_BSE:
- case IDENT_GSE:
- info->asic_type = BM1384;
- usb_transfer_data(compac, CP210X_TYPE_OUT, CP210X_REQUEST_IFC_ENABLE,
- CP210X_VALUE_UART_ENABLE, info->interface, NULL, 0, C_ENABLE_UART);
- usb_transfer_data(compac, CP210X_TYPE_OUT, CP210X_REQUEST_DATA,
- CP210X_VALUE_DATA, info->interface, NULL, 0, C_SETDATA);
- usb_transfer_data(compac, CP210X_TYPE_OUT, CP210X_REQUEST_BAUD,
- 0, info->interface, &baudrate, sizeof (baudrate), C_SETBAUD);
- usb_transfer_data(compac, CP210X_TYPE_OUT, CP210X_SET_LINE_CTL,
- bits, info->interface, NULL, 0, C_SETPARITY);
- break;
- case IDENT_GSH:
- info->asic_type = BM1387;
- info->expected_chips = 2;
- break;
- case IDENT_GSI:
- info->asic_type = BM1387;
- info->expected_chips = 12;
- break;
- case IDENT_GSF:
- case IDENT_GSFM:
- info->asic_type = BM1397;
- // at least 1
- info->expected_chips = 1;
- break;
- default:
- quit(1, "%d: %s compac_detect_one() invalid %s ident=%d",
- compac->cgminer_id, compac->drv->dname, compac->drv->dname, info->ident);
- }
- info->min_job_id = 0x10;
- switch (info->asic_type)
- {
- case BM1384:
- info->rx_len = 5;
- info->task_len = 64;
- info->cores = 55;
- info->add_job_id = 1;
- info->max_job_id = 0x1f;
- info->midstates = 1;
- info->can_boost = false;
- break;
- case BM1387:
- info->rx_len = 7;
- info->task_len = 54;
- info->cores = 114;
- info->add_job_id = 1;
- info->max_job_id = 0x7f;
- info->midstates = (opt_gekko_lowboost) ? 2 : 4;
- info->can_boost = true;
- compac_toggle_reset(compac);
- break;
- case BM1397:
- info->rx_len = 9;
- info->task_len = 54;
- info->cores = 672;
- info->add_job_id = 4;
- info->max_job_id = 0x7f;
- // ignore lowboost
- info->midstates = 4;
- info->can_boost = true;
- compac_toggle_reset(compac);
- break;
- default:
- break;
- }
- info->interface = usb_interface(compac);
- info->mining_state = MINER_INIT;
- applog(LOG_DEBUG, "Using interface %d", info->interface);
- if (!add_cgpu(compac))
- quit(1, "Failed to add_cgpu in compac_detect_one");
- update_usb_stats(compac);
- for (i = 0; i < 8; i++)
- compac->unique_id[i] = compac->unique_id[i+3];
- compac->unique_id[8] = 0;
- info->wait_factor = info->wait_factor0;
- if (!opt_gekko_noboost && info->vmask && (info->asic_type == BM1387 || info->asic_type == BM1397))
- info->wait_factor *= info->midstates;
- return compac;
- }
- static void compac_detect(bool __maybe_unused hotplug)
- {
- usb_detect(&gekko_drv, compac_detect_one);
- }
- static bool compac_prepare(struct thr_info *thr)
- {
- struct cgpu_info *compac = thr->cgpu;
- struct COMPAC_INFO *info = compac->device_data;
- int device = (compac->usbinfo.bus_number * 0xff + compac->usbinfo.device_address) % 0xffff;
- mutex_lock(&static_lock);
- init_count = &dev_init_count[device];
- (*init_count)++;
- info->init_count = (*init_count);
- mutex_unlock(&static_lock);
- if (info->init_count == 1) {
- applog(LOG_WARNING, "%d: %s %d - %s (%s)",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- compac->usbdev->prod_string, compac->unique_id);
- } else {
- applog(LOG_INFO, "%d: %s %d - init_count %d",
- compac->cgminer_id, compac->drv->name, compac->device_id,
- info->init_count);
- }
- info->thr = thr;
- info->bauddiv = 0x19; // 115200
- //info->bauddiv = 0x0D; // 214286
- //info->bauddiv = 0x07; // 375000
- //Sanity check and abort to prevent miner thread from being created.
- if (info->asic_type == BM1387) {
- // Ping Micro
- info->micro_found = 0;
- /*
- if (info->asic_type == BM1387) {
- info->vcore = bound(opt_gekko_gsh_vcore, 300, 810);
- info->micro_found = 1;
- if (!compac_micro_send(compac, M1_GET_TEMP, 0x00, 0x00)) {
- info->micro_found = 0;
- applog(LOG_INFO, "%d: %s %d - micro not found : dummy mode", compac->cgminer_id, compac->drv->name, compac->device_id);
- } else {
- uint8_t vcc = (info->vcore / 1000.0 - 0.3) / 0.002;
- applog(LOG_INFO, "%d: %s %d - requesting vcore of %dmV (%x)", compac->cgminer_id, compac->drv->name, compac->device_id, info->vcore, vcc);
- compac_micro_send(compac, M2_SET_VCORE, 0x00, vcc); // Default 400mV
- }
- }
- */
- }
- if (info->init_count != 0 && info->init_count % 5 == 0) {
- applog(LOG_INFO, "%d: %s %d - forcing usb_nodev()", compac->cgminer_id, compac->drv->name, compac->device_id);
- usb_nodev(compac);
- } else if (info->init_count > 1) {
- if (info->init_count > 10) {
- compac->deven = DEV_DISABLED;
- } else {
- cgsleep_ms(MS_SECOND_5);
- }
- }
- return true;
- }
- static void compac_statline(char *buf, size_t bufsiz, struct cgpu_info *compac)
- {
- struct COMPAC_INFO *info = compac->device_data;
- struct timeval now;
- unsigned int i;
- char ab[2];
- char asic_stat[64];
- char asic_statline[512];
- char ms_stat[64];
- char eff_stat[64];
- uint32_t len = 0;
- memset(asic_statline, 0, sizeof(asic_statline));
- memset(asic_stat, 0, sizeof(asic_stat));
- memset(ms_stat, 0, sizeof(ms_stat));
- memset(eff_stat, 0, sizeof(eff_stat));
- if (info->chips == 0) {
- if (info->init_count > 1) {
- sprintf(asic_statline, "found 0 chip(s)");
- }
- for (i = strlen(asic_statline); i < stat_len + 15; i++)
- asic_statline[i] = ' ';
- tailsprintf(buf, bufsiz, "%s", asic_statline);
- return;
- }
- ab[0] = (info->boosted) ? '+' : 0;
- ab[1] = 0;
- if (info->chips > chip_max)
- chip_max = info->chips;
- cgtime(&now);
- if (opt_widescreen) {
- asic_stat[0] = '[';
- for (i = 1; i <= info->chips; i++) {
- struct ASIC_INFO *asic = &info->asics[i - 1];
- switch (asic->state) {
- case ASIC_HEALTHY:
- asic_stat[i] = 'o';
- break;
- case ASIC_HALFDEAD:
- asic_stat[i] = '-';
- break;
- case ASIC_ALMOST_DEAD:
- asic_stat[i] = '!';
- break;
- case ASIC_DEAD:
- asic_stat[i] = 'x';
- break;
- }
- }
- asic_stat[info->chips + 1] = ']';
- for (i = 1; i <= (chip_max - info->chips) + 1; i++)
- asic_stat[info->chips + 1 + i] = ' ';
- }
- sprintf(ms_stat, "(%.0f:%.0f)", info->task_ms, info->fullscan_ms);
- uint8_t wuc = (ms_tdiff(&now, &info->last_wu_increase) > MS_MINUTE_1) ? 32 : 94;
- if (info->eff_gs >= 99.9 && info->eff_wu >= 98.9) {
- sprintf(eff_stat, "| 100%% WU:100%%");
- } else if (info->eff_gs >= 99.9) {
- sprintf(eff_stat, "| 100%% WU:%c%2.0f%%", wuc, info->eff_wu);
- } else if (info->eff_wu >= 98.9) {
- sprintf(eff_stat, "| %4.1f%% WU:100%%", info->eff_gs);
- } else {
- sprintf(eff_stat, "| %4.1f%% WU:%c%2.0f%%", info->eff_gs, wuc, info->eff_wu);
- }
- if (info->asic_type == BM1387 || info->asic_type == BM1397) {
- char *chipnam = ((info->asic_type == BM1387) ? "BM1387" : "BM1397");
- if (info->micro_found) {
- sprintf(asic_statline, "%s:%02d%-1s %.2fMHz T:%.0f P:%.0f %s %.0fF",
- chipnam, info->chips, ab, info->frequency, info->frequency_requested,
- info->frequency_computed, ms_stat, info->micro_temp);
- } else {
- if (opt_widescreen) {
- sprintf(asic_statline, "%s:%02d%-1s %.0f/%.0f/%3.0f %s %s",
- chipnam, info->chips, ab, info->frequency, info->frequency_requested,
- info->frequency_computed, ms_stat, asic_stat);
- } else {
- sprintf(asic_statline, "%s:%02d%-1s %.2fMHz T:%-3.0f P:%-3.0f %s %s",
- chipnam, info->chips, ab, info->frequency, info->frequency_requested,
- info->frequency_computed, ms_stat, asic_stat);
- }
- }
- } else {
- if (opt_widescreen) {
- sprintf(asic_statline, "BM1384:%02d %.0f/%.0f/%.0f %s %s",
- info->chips, info->frequency, info->frequency_requested,
- info->frequency_computed, ms_stat, asic_stat);
- } else {
- sprintf(asic_statline, "BM1384:%02d %.2fMHz T:%-3.0f P:%-3.0f %s %s",
- info->chips, info->frequency, info->frequency_requested,
- info->frequency_computed, ms_stat, asic_stat);
- }
- }
- len = strlen(asic_statline);
- if (len > stat_len || opt_widescreen != last_widescreen) {
- mutex_lock(&static_lock);
- stat_len = len;
- last_widescreen = opt_widescreen;
- mutex_unlock(&static_lock);
- }
- for (i = len; i < stat_len; i++)
- asic_statline[i] = ' ';
- strcat(asic_statline, eff_stat);
- asic_statline[63] = 0;
- tailsprintf(buf, bufsiz, "%s", asic_statline);
- }
- static struct api_data *compac_api_stats(struct cgpu_info *compac)
- {
- struct COMPAC_INFO *info = compac->device_data;
- struct api_data *root = NULL;
- struct timeval now;
- char nambuf[64], buf256[256];
- double taskdiff, tps, ghs, off;
- time_t secs;
- size_t len;
- int i, j, k;
- cgtime(&now);
- taskdiff = tdiff(&now, &(info->first_task));
- if (taskdiff == 0 || info->tasks < 2)
- tps = 0;
- else
- tps = (double)(info->tasks - 1) / taskdiff;
- root = api_add_string(root, "Serial", compac->usbdev->serial_string, false);
- root = api_add_int(root, "Nonces", &info->nonces, false);
- root = api_add_int(root, "Accepted", &info->accepted, false);
- root = api_add_double(root, "TasksPerSec", &tps, true);
- root = api_add_uint64(root, "Tasks", &info->tasks, false);
- root = api_add_uint64(root, "BusyWork", &info->busy_work, false);
- root = api_add_int(root, "Midstates", &info->midstates, false);
- root = api_add_uint64(root, "MaxTaskWait", &info->max_task_wait, false);
- root = api_add_float(root, "WaitFactor0", &info->wait_factor0, false);
- root = api_add_float(root, "WaitFactor", &info->wait_factor, false);
- root = api_add_float(root, "FreqBase", &info->freq_base, false);
- root = api_add_float(root, "FreqFail", &info->freq_fail, false);
- root = api_add_uint32(root, "TicketDiff", &info->difficulty, false);
- root = api_add_hex32(root, "TicketMask", &info->ticket_mask, false);
- root = api_add_int64(root, "TicketNonces", &info->ticket_nonces, false);
- root = api_add_int64(root, "TicketBelow", &info->below_nonces, false);
- root = api_add_bool(root, "TicketOK", &info->ticket_ok, false);
- root = api_add_float(root, "NonceExpect", &info->nonce_expect, false);
- root = api_add_float(root, "NonceLimit", &info->nonce_limit, false);
- // info->gh access must be under lock
- mutex_lock(&info->ghlock);
- ghs = gekko_gh_hashrate(info, &now, true) / 1.0e3;
- secs = now.tv_sec - info->gh.zerosec;
- root = api_add_time(root, "GHZeroDelta", &secs, true);
- root = api_add_int(root, "GHLast", &info->gh.last, true);
- root = api_add_int(root, "GHNonces", &info->gh.noncesum, true);
- root = api_add_int64(root, "GHDiff", &info->gh.diffsum, true);
- root = api_add_double(root, "GHGHs", &ghs, true);
- mutex_unlock(&info->ghlock);
- root = api_add_float(root, "Require", &info->ghrequire, true);
- ghs = info->frequency * (double)(info->cores * info->chips) * info->ghrequire / 1.0e3;
- root = api_add_double(root, "RequireGH", &ghs, true);
- // info->job access must be under lock
- // N.B. this is as at the last job sent, not 'now'
- mutex_lock(&info->joblock);
- off = tdiff(&now, &(info->job.lastjob));
- root = api_add_double(root, "JobDataAge", &off, true);
- buf256[0] = '\0';
- for (i = 0; i < JOBMIN; i++)
- {
- j = JOBOFF(info->job.offset - i);
- len = strlen(buf256);
- // /, digit, null = 3
- if ((len - sizeof(buf256)) < 3)
- break;
- snprintf(buf256+len, sizeof(buf256)-len, "/%d", info->job.jobnum[j]);
- }
- root = api_add_string(root, "Jobs", buf256+1, true);
- buf256[0] = '\0';
- for (i = 0; i < JOBMIN; i++)
- {
- double elap;
- j = JOBOFF(info->job.offset - i);
- elap = tdiff(&(info->job.lastj[j]), &(info->job.firstj[j]));
- len = strlen(buf256);
- // /, digit, null = 3
- if ((len - sizeof(buf256)) < 3)
- break;
- snprintf(buf256+len, sizeof(buf256)-len, "/%.2f", elap);
- }
- root = api_add_string(root, "JobElapsed", buf256+1, true);
- buf256[0] = '\0';
- for (i = 0; i < JOBMIN; i++)
- {
- double jps, elap;
- j = JOBOFF(info->job.offset - i);
- elap = tdiff(&(info->job.lastj[j]), &(info->job.firstj[j]));
- if (elap == 0)
- jps = 0;
- else
- jps = (double)(info->job.jobnum[j] - 1) / elap;
- len = strlen(buf256);
- // /, digit, null = 3
- if ((len - sizeof(buf256)) < 3)
- break;
- snprintf(buf256+len, sizeof(buf256)-len, "/%.2f", jps);
- }
- root = api_add_string(root, "JobsPerSec", buf256+1, true);
- buf256[0] = '\0';
- for (i = 0; i < JOBMIN; i++)
- {
- j = JOBOFF(info->job.offset - i);
- len = strlen(buf256);
- // /, digit, null = 3
- if ((len - sizeof(buf256)) < 3)
- break;
- snprintf(buf256+len, sizeof(buf256)-len, "/%.2f", info->job.avgms[j]);
- }
- root = api_add_string(root, "JobsAvgms", buf256+1, true);
- buf256[0] = '\0';
- for (i = 0; i < JOBMIN; i++)
- {
- j = JOBOFF(info->job.offset - i);
- len = strlen(buf256);
- // /, digit, null = 3
- if ((len - sizeof(buf256)) < 3)
- break;
- snprintf(buf256+len, sizeof(buf256)-len, "/%.2f:%.2f",
- info->job.minms[j], info->job.maxms[j]);
- }
- root = api_add_string(root, "JobsMinMaxms", buf256+1, true);
- mutex_unlock(&info->joblock);
- for (i = 0; i < (int)CUR_ATTEMPT; i++)
- {
- snprintf(nambuf, sizeof(nambuf), "cur_off_%d_%d", i, cur_attempt[i]);
- root = api_add_uint64(root, nambuf, &info->cur_off[i], true);
- }
- root = api_add_double(root, "Rolling", &info->rolling, false);
- root = api_add_int(root, "Resets", &info->fail_count, false);
- root = api_add_float(root, "Frequency", &info->frequency, false);
- root = api_add_float(root, "FreqComp", &info->frequency_computed, false);
- root = api_add_float(root, "FreqReq", &info->frequency_requested, false);
- root = api_add_float(root, "FreqStart", &info->frequency_start, false);
- root = api_add_float(root, "FreqSel", &info->frequency_selected, false);
- //root = api_add_temp(root, "Temp", &info->micro_temp, false);
- root = api_add_int(root, "Dups", &info->dupsall, true);
- root = api_add_int(root, "DupsReset", &info->dupsreset, true);
- root = api_add_uint(root, "Chips", &info->chips, false);
- root = api_add_bool(root, "FreqLocked", &info->lock_freq, false);
- if (info->asic_type == BM1397)
- root = api_add_int(root, "USBProp", &info->usb_prop, false);
- mutex_lock(&info->ghlock);
- for (i = 0; i < (int)info->chips; i++)
- {
- struct ASIC_INFO *asic = &info->asics[i];
- snprintf(nambuf, sizeof(nambuf), "Chip%dNonces", i);
- root = api_add_int(root, nambuf, &asic->nonces, true);
- snprintf(nambuf, sizeof(nambuf), "Chip%dDups", i);
- root = api_add_uint(root, nambuf, &asic->dupsall, true);
- gc_offset(info, asic, &now, false, true);
- snprintf(nambuf, sizeof(nambuf), "Chip%dRanges", i);
- buf256[0] = '\0';
- for (j = 0; j < CHNUM; j++)
- {
- len = strlen(buf256);
- // slash, digit, null = 3
- if ((len - sizeof(buf256)) < 3)
- break;
- k = CHOFF(asic->gc.offset - j);
- snprintf(buf256+len, sizeof(buf256)-len, "/%d", asic->gc.noncenum[k]);
- }
- len = strlen(buf256);
- if ((len - sizeof(buf256)) >= 3)
- snprintf(buf256+len, sizeof(buf256)-len, "/%d", asic->gc.noncesum);
- len = strlen(buf256);
- if ((len - sizeof(buf256)) >= 3)
- snprintf(buf256+len, sizeof(buf256)-len, "/%.2f%%", noncepercent(info, i, &now));
- root = api_add_string(root, nambuf, buf256+1, true);
- snprintf(nambuf, sizeof(nambuf), "Chip%dFreqSend", i);
- root = api_add_float(root, nambuf, &asic->frequency, true);
- snprintf(nambuf, sizeof(nambuf), "Chip%dFreqReply", i);
- root = api_add_float(root, nambuf, &asic->frequency_reply, true);
- }
- mutex_unlock(&info->ghlock);
- for (i = 0; i < 16; i++)
- {
- snprintf(nambuf, sizeof(nambuf), "NonceByte-%1X0", i);
- buf256[0] = '\0';
- for (j = 0; j < 16; j++)
- {
- len = strlen(buf256);
- // dot, digit, null = 3
- if ((len - sizeof(buf256)) < 3)
- break;
- snprintf(buf256+len, sizeof(buf256)-len, ".%"PRId64, info->noncebyte[i*16+j]);
- }
- root = api_add_string(root, nambuf, buf256+1, true);
- }
- for (i = 0; i < 16; i++)
- {
- snprintf(nambuf, sizeof(nambuf), "nb2c-%1X0", i);
- buf256[0] = '\0';
- for (j = 0; j < 16; j++)
- {
- len = strlen(buf256);
- // dot, digit, null = 3
- if ((len - sizeof(buf256)) < 3)
- break;
- snprintf(buf256+len, sizeof(buf256)-len, ".%u", info->nb2chip[i*16+j]);
- }
- root = api_add_string(root, nambuf, buf256+1, true);
- }
- root = api_add_uint64(root, "NTimeout", &info->ntimeout, false);
- root = api_add_uint64(root, "NTrigger", &info->ntrigger, false);
- #if TUNE_CODE
- mutex_lock(&info->slock);
- uint64_t num = info->num;
- double req = info->req;
- double fac = info->fac;
- uint64_t num1_1 = info->num1_1;
- double req1_1 = info->req1_1;
- double fac1_1 = info->fac1_1;
- uint64_t num1_5 = info->num1_5;
- double req1_5 = info->req1_5;
- double fac1_5 = info->fac1_5;
- uint64_t inv = info->inv;
- mutex_unlock(&info->slock);
- double avg, res, avg1_1, res1_1, avg1_5, res1_5;
- if (num == 0)
- avg = res = 0.0;
- else
- {
- avg = req / (double)num;
- res = fac / (double)num;
- }
- if (num1_1 == 0)
- avg1_1 = res1_1 = 0.0;
- else
- {
- avg1_1 = req1_1 / (double)num1_1;
- res1_1 = fac1_1 / (double)num1_1;
- }
- if (num1_5 == 0)
- avg1_5 = res1_5 = 0.0;
- else
- {
- avg1_5 = req1_5 / (double)num1_5;
- res1_5 = fac1_5 / (double)num1_5;
- }
- root = api_add_uint64(root, "SleepN", &num, true);
- root = api_add_double(root, "SleepAvgReq", &avg, true);
- root = api_add_double(root, "SleepAvgRes", &res, true);
- root = api_add_uint64(root, "SleepN1_1", &num1_1, true);
- root = api_add_double(root, "SleepAvgReq1_1", &avg1_1, true);
- root = api_add_double(root, "SleepAvgRes1_1", &res1_1, true);
- root = api_add_uint64(root, "SleepN1_5", &num1_5, true);
- root = api_add_double(root, "SleepAvgReq1_5", &avg1_5, true);
- root = api_add_double(root, "SleepAvgRes1_5", &res1_5, true);
- root = api_add_uint64(root, "SleepInv", &inv, true);
- root = api_add_uint64(root, "WorkGenNum", &info->work_usec_num, true);
- root = api_add_double(root, "WorkGenAvg", &info->work_usec_avg, true);
- if (info->over1num == 0)
- avg = 0.0;
- else
- avg = info->over1amt / (double)(info->over1num);
- root = api_add_int64(root, "Over1N", &info->over1num, true);
- root = api_add_double(root, "Over1Avg", &avg, true);
- if (info->over2num == 0)
- avg = 0.0;
- else
- avg = info->over2amt / (double)(info->over2num);
- root = api_add_int64(root, "Over2N", &info->over2num, true);
- root = api_add_double(root, "Over2Avg", &avg, true);
- #endif
- #if STRATUM_WORK_TIMING
- cg_rlock(&swt_lock);
- uint64_t swc = stratum_work_count;
- uint64_t swt = stratum_work_time;
- uint64_t swmin = stratum_work_min;
- uint64_t swmax = stratum_work_max;
- uint64_t swt0 = stratum_work_time0;
- uint64_t swt10 = stratum_work_time10;
- uint64_t swt100 = stratum_work_time100;
- cg_runlock(&swt_lock);
- double sw_avg;
- if (swc == 0)
- sw_avg = 0.0;
- else
- sw_avg = (double)swt / (double)swc;
- root = api_add_uint64(root, "SWCount", &swc, true);
- root = api_add_double(root, "SWAvg", &sw_avg, true);
- root = api_add_uint64(root, "SWMin", &swmin, true);
- root = api_add_uint64(root, "SWMax", &swmax, true);
- root = api_add_uint64(root, "SW0Count", &swt0, true);
- root = api_add_uint64(root, "SW10Count", &swt10, true);
- root = api_add_uint64(root, "SW100Count", &swt100, true);
- #endif
- return root;
- }
- static void compac_shutdown(struct thr_info *thr)
- {
- struct cgpu_info *compac = thr->cgpu;
- struct COMPAC_INFO *info = compac->device_data;
- applog(LOG_INFO, "%d: %s %d - shutting down", compac->cgminer_id, compac->drv->name, compac->device_id);
- if (!compac->usbinfo.nodev) {
- if (info->asic_type == BM1387) {
- compac_micro_send(compac, M2_SET_VCORE, 0x00, 0x00); // 300mV
- compac_toggle_reset(compac);
- } else if (info->asic_type == BM1397) {
- calc_gsf_freq(compac, 0, -1);
- compac_toggle_reset(compac);
- } else if (info->asic_type == BM1384 && info->frequency != info->frequency_default) {
- float frequency = info->frequency - info->freq_mult;
- while (frequency > info->frequency_default) {
- compac_set_frequency(compac, frequency);
- frequency -= info->freq_mult;
- cgsleep_ms(100);
- }
- compac_set_frequency(compac, info->frequency_default);
- compac_send_chain_inactive(compac);
- }
- }
- info->mining_state = MINER_SHUTDOWN;
- pthread_join(info->rthr.pth, NULL); // Let thread close.
- pthread_join(info->wthr.pth, NULL); // Let thread close.
- if (info->asic_type == BM1397)
- pthread_join(info->nthr.pth, NULL); // Let thread close.
- PTH(thr) = 0L;
- }
- uint64_t bound(uint64_t value, uint64_t lower_bound, uint64_t upper_bound)
- {
- if (value < lower_bound)
- return lower_bound;
- if (value > upper_bound)
- return upper_bound;
- return value;
- }
- void stuff_reverse(unsigned char *dst, unsigned char *src, uint32_t len)
- {
- uint32_t i;
- for (i = 0; i < len; i++) {
- dst[i] = src[len - i - 1];
- }
- }
- void stuff_lsb(unsigned char *dst, uint32_t x)
- {
- dst[0] = (x >> 0) & 0xff;
- dst[1] = (x >> 8) & 0xff;
- dst[2] = (x >> 16) & 0xff;
- dst[3] = (x >> 24) & 0xff;
- }
- void stuff_msb(unsigned char *dst, uint32_t x)
- {
- dst[0] = (x >> 24) & 0xff;
- dst[1] = (x >> 16) & 0xff;
- dst[2] = (x >> 8) & 0xff;
- dst[3] = (x >> 0) & 0xff;
- }
- static char *compac_api_set(struct cgpu_info *compac, char *option, char *setting, char *replybuf, size_t siz)
- {
- struct COMPAC_INFO *info = compac->device_data;
- float freq;
- if (strcasecmp(option, "help") == 0)
- {
- // freq: all of the drivers automatically fix the value
- // BM1397 0 is a special case, since it 'works'
- if (info->asic_type == BM1397)
- {
- snprintf(replybuf, siz, "reset freq: 0-1200 chip: N:0-800 target: 0-1200"
- " lockfreq unlockfreq waitfactor: 0.01-2.0"
- " usbprop: %d-1000 require: 0.0-0.8", USLEEPMIN);
- }
- else
- {
- snprintf(replybuf, siz, "reset freq: 0-1200 chip: N:0-800 target: 0-1200"
- " lockfreq unlockfreq waitfactor: 0.01-2.0"
- " require: 0.0-0.8");
- }
- return replybuf;
- }
- if (strcasecmp(option, "reset") == 0)
- {
- // will cause various problems ...
- info->mining_state = MINER_RESET;
- return NULL;
- }
- // set all chips to freq
- if (strcasecmp(option, "freq") == 0)
- {
- if (!setting || !*setting)
- {
- snprintf(replybuf, siz, "missing freq");
- return replybuf;
- }
- freq = limit_freq(info, atof(setting), true);
- freq = FREQ_BASE(freq);
- change_freq_any(compac, freq);
- return NULL;
- }
- // set chip:freq
- if (strcasecmp(option, "chip") == 0)
- {
- char *fpos;
- int chip;
- if (!setting || !*setting)
- {
- snprintf(replybuf, siz, "missing chip:freq");
- return replybuf;
- }
- if (info->asic_type != BM1397)
- {
- snprintf(replybuf, siz, "chip:freq only valid for BM1397");
- return replybuf;
- }
- fpos = strchr(setting, ':');
- if (!fpos || fpos == setting || *(fpos+1) == '\0')
- {
- snprintf(replybuf, siz, "not chip:freq");
- return replybuf;
- }
- // atoi will stop at the ':'
- chip = atoi(setting);
- if (chip < 0 || chip >= (int)(info->chips))
- {
- snprintf(replybuf, siz, "invalid chip %d", chip);
- return replybuf;
- }
- freq = limit_freq(info, atof(fpos+1), true);
- freq = FREQ_BASE(freq);
- calc_gsf_freq(compac, freq, chip);
- return NULL;
- }
- if (strcasecmp(option, "target") == 0)
- {
- if (!setting || !*setting)
- {
- snprintf(replybuf, siz, "missing freq");
- return replybuf;
- }
- freq = limit_freq(info, atof(setting), true);
- freq = FREQ_BASE(freq);
- info->frequency_requested = freq;
- return NULL;
- }
- if (strcasecmp(option, "lockfreq") == 0)
- {
- info->lock_freq = true;
- return NULL;
- }
- if (strcasecmp(option, "unlockfreq") == 0)
- {
- info->lock_freq = false;
- return NULL;
- }
- // set wait-factor
- if (strcasecmp(option, "waitfactor") == 0)
- {
- if (!setting || !*setting)
- {
- snprintf(replybuf, siz, "missing value");
- return replybuf;
- }
- info->wait_factor0 = fbound(atof(setting), 0.01, 2.0);
- compac_update_rates(compac);
- return NULL;
- }
- // set work propagation time
- if (strcasecmp(option, "usbprop") == 0)
- {
- if (info->asic_type != BM1397)
- {
- snprintf(replybuf, siz, "usbprop only for BM1397");
- return replybuf;
- }
- if (!setting || !*setting)
- {
- snprintf(replybuf, siz, "missing usec");
- return replybuf;
- }
- info->usb_prop = (int)bound(atoi(setting), USLEEPMIN, 1000);
- return NULL;
- }
- // set ghrequire
- if (strcasecmp(option, "require") == 0)
- {
- if (!setting || !*setting)
- {
- snprintf(replybuf, siz, "missing value");
- return replybuf;
- }
- info->ghrequire = fbound(atof(setting), 0.0, 0.8);
- compac_update_rates(compac);
- return NULL;
- }
- snprintf(replybuf, siz, "Unknown option: %s", option);
- return replybuf;
- }
- struct device_drv gekko_drv = {
- .drv_id = DRIVER_gekko,
- .dname = "GekkoScience",
- .name = "GSX",
- .hash_work = hash_queued_work,
- .get_api_stats = compac_api_stats,
- .get_statline_before = compac_statline,
- .set_device = compac_api_set,
- .drv_detect = compac_detect,
- .scanwork = compac_scanwork,
- .flush_work = compac_flush_work,
- .update_work = compac_update_work,
- .thread_prepare = compac_prepare,
- .thread_init = compac_init,
- .thread_shutdown = compac_shutdown,
- };
|