bcmutils.c 114 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351
  1. /*
  2. * Driver O/S-independent utility routines
  3. *
  4. * Portions of this code are copyright (c) 2020 Cypress Semiconductor Corporation
  5. *
  6. * Copyright (C) 1999-2020, Broadcom Corporation
  7. *
  8. * Unless you and Broadcom execute a separate written software license
  9. * agreement governing use of this software, this software is licensed to you
  10. * under the terms of the GNU General Public License version 2 (the "GPL"),
  11. * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  12. * following added to such license:
  13. *
  14. * As a special exception, the copyright holders of this software give you
  15. * permission to link this software with independent modules, and to copy and
  16. * distribute the resulting executable under terms of your choice, provided that
  17. * you also meet, for each linked independent module, the terms and conditions of
  18. * the license of that module. An independent module is a module which is not
  19. * derived from this software. The special exception does not apply to any
  20. * modifications of the software.
  21. *
  22. * Notwithstanding the above, under no circumstances may you combine this
  23. * software in any way with any other Broadcom software provided under a license
  24. * other than the GPL, without Broadcom's express prior written consent.
  25. *
  26. *
  27. * <<Broadcom-WL-IPTag/Open:>>
  28. *
  29. * $Id: bcmutils.c 702105 2017-05-30 19:10:39Z $
  30. */
  31. #include <bcm_cfg.h>
  32. #include <typedefs.h>
  33. #include <bcmdefs.h>
  34. #include <stdarg.h>
  35. #ifdef BCMDRIVER
  36. #include <osl.h>
  37. #include <bcmutils.h>
  38. #else /* !BCMDRIVER */
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <bcm_math.h>
  42. #include <bcmutils.h>
  43. #if defined(BCMEXTSUP)
  44. #include <bcm_osl.h>
  45. #endif // endif
  46. #ifndef ASSERT
  47. #define ASSERT(exp)
  48. #endif // endif
  49. #endif /* !BCMDRIVER */
  50. #ifdef WL_UNITTEST
  51. #ifdef ASSERT
  52. #undef ASSERT
  53. #endif /* ASSERT */
  54. #define ASSERT(exp)
  55. #endif /* WL_UNITTEST */
  56. #include <bcmstdlib_s.h>
  57. #include <bcmendian.h>
  58. #include <bcmdevs.h>
  59. #include <ethernet.h>
  60. #include <vlan.h>
  61. #include <bcmip.h>
  62. #include <802.1d.h>
  63. #include <802.11.h>
  64. #include <bcmip.h>
  65. #include <bcmipv6.h>
  66. #include <bcmtcp.h>
  67. #ifdef BCMDRIVER
  68. /* return total length of buffer chain */
  69. uint BCMFASTPATH
  70. pkttotlen(osl_t *osh, void *p)
  71. {
  72. uint total;
  73. int len;
  74. total = 0;
  75. for (; p; p = PKTNEXT(osh, p)) {
  76. len = PKTLEN(osh, p);
  77. total += (uint)len;
  78. #ifdef BCMLFRAG
  79. if (BCMLFRAG_ENAB()) {
  80. if (PKTISFRAG(osh, p)) {
  81. total += PKTFRAGTOTLEN(osh, p);
  82. }
  83. }
  84. #endif // endif
  85. }
  86. return (total);
  87. }
  88. /* return the last buffer of chained pkt */
  89. void *
  90. pktlast(osl_t *osh, void *p)
  91. {
  92. for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p))
  93. ;
  94. return (p);
  95. }
  96. /* count segments of a chained packet */
  97. uint BCMFASTPATH
  98. pktsegcnt(osl_t *osh, void *p)
  99. {
  100. uint cnt;
  101. for (cnt = 0; p; p = PKTNEXT(osh, p)) {
  102. cnt++;
  103. #ifdef BCMLFRAG
  104. if (BCMLFRAG_ENAB()) {
  105. if (PKTISFRAG(osh, p)) {
  106. cnt += PKTFRAGTOTNUM(osh, p);
  107. }
  108. }
  109. #endif // endif
  110. }
  111. return cnt;
  112. }
  113. /* copy a pkt buffer chain into a buffer */
  114. uint
  115. pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf)
  116. {
  117. uint n, ret = 0;
  118. if (len < 0)
  119. len = 4096; /* "infinite" */
  120. /* skip 'offset' bytes */
  121. for (; p && offset; p = PKTNEXT(osh, p)) {
  122. if (offset < (uint)PKTLEN(osh, p))
  123. break;
  124. offset -= (uint)PKTLEN(osh, p);
  125. }
  126. if (!p)
  127. return 0;
  128. /* copy the data */
  129. for (; p && len; p = PKTNEXT(osh, p)) {
  130. n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
  131. bcopy(PKTDATA(osh, p) + offset, buf, n);
  132. buf += n;
  133. len -= n;
  134. ret += n;
  135. offset = 0;
  136. }
  137. return ret;
  138. }
  139. /* copy a buffer into a pkt buffer chain */
  140. uint
  141. pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf)
  142. {
  143. uint n, ret = 0;
  144. /* skip 'offset' bytes */
  145. for (; p && offset; p = PKTNEXT(osh, p)) {
  146. if (offset < (uint)PKTLEN(osh, p))
  147. break;
  148. offset -= (uint)PKTLEN(osh, p);
  149. }
  150. if (!p)
  151. return 0;
  152. /* copy the data */
  153. for (; p && len; p = PKTNEXT(osh, p)) {
  154. n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
  155. bcopy(buf, PKTDATA(osh, p) + offset, n);
  156. buf += n;
  157. len -= n;
  158. ret += n;
  159. offset = 0;
  160. }
  161. return ret;
  162. }
  163. uint8 * BCMFASTPATH
  164. pktdataoffset(osl_t *osh, void *p, uint offset)
  165. {
  166. uint total = pkttotlen(osh, p);
  167. uint pkt_off = 0, len = 0;
  168. uint8 *pdata = (uint8 *) PKTDATA(osh, p);
  169. if (offset > total)
  170. return NULL;
  171. for (; p; p = PKTNEXT(osh, p)) {
  172. pdata = (uint8 *) PKTDATA(osh, p);
  173. pkt_off = offset - len;
  174. len += (uint)PKTLEN(osh, p);
  175. if (len > offset)
  176. break;
  177. }
  178. return (uint8*) (pdata+pkt_off);
  179. }
  180. /* given a offset in pdata, find the pkt seg hdr */
  181. void *
  182. pktoffset(osl_t *osh, void *p, uint offset)
  183. {
  184. uint total = pkttotlen(osh, p);
  185. uint len = 0;
  186. if (offset > total)
  187. return NULL;
  188. for (; p; p = PKTNEXT(osh, p)) {
  189. len += (uint)PKTLEN(osh, p);
  190. if (len > offset)
  191. break;
  192. }
  193. return p;
  194. }
  195. void
  196. bcm_mdelay(uint ms)
  197. {
  198. uint i;
  199. for (i = 0; i < ms; i++) {
  200. OSL_DELAY(1000);
  201. }
  202. }
  203. #if defined(DHD_DEBUG)
  204. /* pretty hex print a pkt buffer chain */
  205. void
  206. prpkt(const char *msg, osl_t *osh, void *p0)
  207. {
  208. void *p;
  209. if (msg && (msg[0] != '\0'))
  210. printf("%s:\n", msg);
  211. for (p = p0; p; p = PKTNEXT(osh, p))
  212. prhex(NULL, PKTDATA(osh, p), (uint)PKTLEN(osh, p));
  213. }
  214. #endif // endif
  215. /* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
  216. * Also updates the inplace vlan tag if requested.
  217. * For debugging, it returns an indication of what it did.
  218. */
  219. uint BCMFASTPATH
  220. pktsetprio(void *pkt, bool update_vtag)
  221. {
  222. struct ether_header *eh;
  223. struct ethervlan_header *evh;
  224. uint8 *pktdata;
  225. uint priority = 0;
  226. uint rc = 0;
  227. pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
  228. ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
  229. eh = (struct ether_header *) pktdata;
  230. if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) {
  231. uint16 vlan_tag;
  232. uint vlan_prio, dscp_prio = 0;
  233. evh = (struct ethervlan_header *)eh;
  234. vlan_tag = ntoh16(evh->vlan_tag);
  235. vlan_prio = (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
  236. if ((evh->ether_type == hton16(ETHER_TYPE_IP)) ||
  237. (evh->ether_type == hton16(ETHER_TYPE_IPV6))) {
  238. uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
  239. uint8 tos_tc = (uint8)IP_TOS46(ip_body);
  240. dscp_prio = tos_tc >> IPV4_TOS_PREC_SHIFT;
  241. }
  242. /* DSCP priority gets precedence over 802.1P (vlan tag) */
  243. if (dscp_prio != 0) {
  244. priority = dscp_prio;
  245. rc |= PKTPRIO_VDSCP;
  246. } else {
  247. priority = vlan_prio;
  248. rc |= PKTPRIO_VLAN;
  249. }
  250. /*
  251. * If the DSCP priority is not the same as the VLAN priority,
  252. * then overwrite the priority field in the vlan tag, with the
  253. * DSCP priority value. This is required for Linux APs because
  254. * the VLAN driver on Linux, overwrites the skb->priority field
  255. * with the priority value in the vlan tag
  256. */
  257. if (update_vtag && (priority != vlan_prio)) {
  258. vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
  259. vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
  260. evh->vlan_tag = hton16(vlan_tag);
  261. rc |= PKTPRIO_UPD;
  262. }
  263. #if defined(EAPOL_PKT_PRIO) || defined(DHD_LOSSLESS_ROAMING)
  264. } else if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
  265. priority = PRIO_8021D_NC;
  266. rc = PKTPRIO_DSCP;
  267. #endif /* EAPOL_PKT_PRIO || DHD_LOSSLESS_ROAMING */
  268. } else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) ||
  269. (eh->ether_type == hton16(ETHER_TYPE_IPV6))) {
  270. uint8 *ip_body = pktdata + sizeof(struct ether_header);
  271. uint8 tos_tc = (uint8)IP_TOS46(ip_body);
  272. uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT;
  273. switch (dscp) {
  274. case DSCP_EF:
  275. case DSCP_VA:
  276. priority = PRIO_8021D_VO;
  277. break;
  278. case DSCP_AF31:
  279. case DSCP_AF32:
  280. case DSCP_AF33:
  281. case DSCP_CS3:
  282. priority = PRIO_8021D_CL;
  283. break;
  284. case DSCP_AF21:
  285. case DSCP_AF22:
  286. case DSCP_AF23:
  287. priority = PRIO_8021D_EE;
  288. break;
  289. case DSCP_AF11:
  290. case DSCP_AF12:
  291. case DSCP_AF13:
  292. case DSCP_CS2:
  293. priority = PRIO_8021D_BE;
  294. break;
  295. case DSCP_CS6:
  296. case DSCP_CS7:
  297. priority = PRIO_8021D_NC;
  298. break;
  299. default:
  300. priority = tos_tc >> IPV4_TOS_PREC_SHIFT;
  301. break;
  302. }
  303. rc |= PKTPRIO_DSCP;
  304. }
  305. ASSERT(priority <= MAXPRIO);
  306. PKTSETPRIO(pkt, (int)priority);
  307. return (rc | priority);
  308. }
  309. /* lookup user priority for specified DSCP */
  310. static uint8
  311. dscp2up(uint8 *up_table, uint8 dscp)
  312. {
  313. uint8 user_priority = 255;
  314. /* lookup up from table if parameters valid */
  315. if (up_table != NULL && dscp < UP_TABLE_MAX) {
  316. user_priority = up_table[dscp];
  317. }
  318. /* 255 is unused value so return up from dscp */
  319. if (user_priority == 255) {
  320. user_priority = dscp >> (IPV4_TOS_PREC_SHIFT - IPV4_TOS_DSCP_SHIFT);
  321. }
  322. return user_priority;
  323. }
  324. /* set user priority by QoS Map Set table (UP table), table size is UP_TABLE_MAX */
  325. uint BCMFASTPATH
  326. pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag)
  327. {
  328. if (up_table) {
  329. uint8 *pktdata;
  330. uint pktlen;
  331. uint8 dscp;
  332. uint user_priority = 0;
  333. uint rc = 0;
  334. pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
  335. pktlen = (uint)PKTLEN(OSH_NULL, pkt);
  336. if (pktgetdscp(pktdata, pktlen, &dscp)) {
  337. rc = PKTPRIO_DSCP;
  338. user_priority = dscp2up(up_table, dscp);
  339. PKTSETPRIO(pkt, (int)user_priority);
  340. }
  341. return (rc | user_priority);
  342. } else {
  343. return pktsetprio(pkt, update_vtag);
  344. }
  345. }
  346. /* Returns TRUE and DSCP if IP header found, FALSE otherwise.
  347. */
  348. bool BCMFASTPATH
  349. pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp)
  350. {
  351. struct ether_header *eh;
  352. struct ethervlan_header *evh;
  353. uint8 *ip_body;
  354. bool rc = FALSE;
  355. /* minimum length is ether header and IP header */
  356. if (pktlen < sizeof(struct ether_header) + IPV4_MIN_HEADER_LEN)
  357. return FALSE;
  358. eh = (struct ether_header *) pktdata;
  359. if (eh->ether_type == HTON16(ETHER_TYPE_IP)) {
  360. ip_body = pktdata + sizeof(struct ether_header);
  361. *dscp = (uint8)IP_DSCP46(ip_body);
  362. rc = TRUE;
  363. }
  364. else if (eh->ether_type == HTON16(ETHER_TYPE_8021Q)) {
  365. evh = (struct ethervlan_header *)eh;
  366. /* minimum length is ethervlan header and IP header */
  367. if (pktlen >= sizeof(struct ethervlan_header) + IPV4_MIN_HEADER_LEN &&
  368. evh->ether_type == HTON16(ETHER_TYPE_IP)) {
  369. ip_body = pktdata + sizeof(struct ethervlan_header);
  370. *dscp = (uint8)IP_DSCP46(ip_body);
  371. rc = TRUE;
  372. }
  373. }
  374. return rc;
  375. }
  376. /* usr_prio range from low to high with usr_prio value */
  377. static bool
  378. up_table_set(uint8 *up_table, uint8 usr_prio, uint8 low, uint8 high)
  379. {
  380. int i;
  381. if (usr_prio > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) {
  382. return FALSE;
  383. }
  384. for (i = low; i <= high; i++) {
  385. up_table[i] = usr_prio;
  386. }
  387. return TRUE;
  388. }
  389. /* set user priority table */
  390. int BCMFASTPATH
  391. wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie)
  392. {
  393. uint8 len;
  394. if (up_table == NULL || qos_map_ie == NULL) {
  395. return BCME_ERROR;
  396. }
  397. /* clear table to check table was set or not */
  398. memset(up_table, 0xff, UP_TABLE_MAX);
  399. /* length of QoS Map IE must be 16+n*2, n is number of exceptions */
  400. if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID &&
  401. (len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH &&
  402. (len % 2) == 0) {
  403. uint8 *except_ptr = (uint8 *)qos_map_ie->data;
  404. uint8 except_len = len - QOS_MAP_FIXED_LENGTH;
  405. uint8 *range_ptr = except_ptr + except_len;
  406. uint8 i;
  407. /* fill in ranges */
  408. for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) {
  409. uint8 low = range_ptr[i];
  410. uint8 high = range_ptr[i + 1];
  411. if (low == 255 && high == 255) {
  412. continue;
  413. }
  414. if (!up_table_set(up_table, i / 2, low, high)) {
  415. /* clear the table on failure */
  416. memset(up_table, 0xff, UP_TABLE_MAX);
  417. return BCME_ERROR;
  418. }
  419. }
  420. /* update exceptions */
  421. for (i = 0; i < except_len; i += 2) {
  422. uint8 dscp = except_ptr[i];
  423. uint8 usr_prio = except_ptr[i+1];
  424. /* exceptions with invalid dscp/usr_prio are ignored */
  425. up_table_set(up_table, usr_prio, dscp, dscp);
  426. }
  427. }
  428. return BCME_OK;
  429. }
  430. /* The 0.5KB string table is not removed by compiler even though it's unused */
  431. static char bcm_undeferrstr[32];
  432. static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
  433. /* Convert the error codes into related error strings */
  434. const char *
  435. BCMRAMFN(bcmerrorstr)(int bcmerror)
  436. {
  437. /* check if someone added a bcmerror code but forgot to add errorstring */
  438. ASSERT((uint)ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1));
  439. if (bcmerror > 0 || bcmerror < BCME_LAST) {
  440. snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror);
  441. return bcm_undeferrstr;
  442. }
  443. ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN);
  444. return bcmerrorstrtable[-bcmerror];
  445. }
  446. /* iovar table lookup */
  447. /* could mandate sorted tables and do a binary search */
  448. const bcm_iovar_t*
  449. bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
  450. {
  451. const bcm_iovar_t *vi;
  452. const char *lookup_name;
  453. /* skip any ':' delimited option prefixes */
  454. lookup_name = strrchr(name, ':');
  455. if (lookup_name != NULL)
  456. lookup_name++;
  457. else
  458. lookup_name = name;
  459. ASSERT(table != NULL);
  460. for (vi = table; vi->name; vi++) {
  461. if (!strcmp(vi->name, lookup_name))
  462. return vi;
  463. }
  464. /* ran to end of table */
  465. return NULL; /* var name not found */
  466. }
  467. int
  468. bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
  469. {
  470. int bcmerror = 0;
  471. BCM_REFERENCE(arg);
  472. /* length check on io buf */
  473. switch (vi->type) {
  474. case IOVT_BOOL:
  475. case IOVT_INT8:
  476. case IOVT_INT16:
  477. case IOVT_INT32:
  478. case IOVT_UINT8:
  479. case IOVT_UINT16:
  480. case IOVT_UINT32:
  481. /* all integers are int32 sized args at the ioctl interface */
  482. if (len < (int)sizeof(int)) {
  483. bcmerror = BCME_BUFTOOSHORT;
  484. }
  485. break;
  486. case IOVT_BUFFER:
  487. /* buffer must meet minimum length requirement */
  488. if (len < vi->minlen) {
  489. bcmerror = BCME_BUFTOOSHORT;
  490. }
  491. break;
  492. case IOVT_VOID:
  493. if (!set) {
  494. /* Cannot return nil... */
  495. bcmerror = BCME_UNSUPPORTED;
  496. }
  497. break;
  498. default:
  499. /* unknown type for length check in iovar info */
  500. ASSERT(0);
  501. bcmerror = BCME_UNSUPPORTED;
  502. }
  503. return bcmerror;
  504. }
  505. #if !defined(_CFEZ_)
  506. /*
  507. * Hierarchical Multiword bitmap based small id allocator.
  508. *
  509. * Multilevel hierarchy bitmap. (maximum 2 levels)
  510. * First hierarchy uses a multiword bitmap to identify 32bit words in the
  511. * second hierarchy that have at least a single bit set. Each bit in a word of
  512. * the second hierarchy represents a unique ID that may be allocated.
  513. *
  514. * BCM_MWBMAP_ITEMS_MAX: Maximum number of IDs managed.
  515. * BCM_MWBMAP_BITS_WORD: Number of bits in a bitmap word word
  516. * BCM_MWBMAP_WORDS_MAX: Maximum number of bitmap words needed for free IDs.
  517. * BCM_MWBMAP_WDMAP_MAX: Maximum number of bitmap wordss identifying first non
  518. * non-zero bitmap word carrying at least one free ID.
  519. * BCM_MWBMAP_SHIFT_OP: Used in MOD, DIV and MUL operations.
  520. * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID
  521. *
  522. * Design Notes:
  523. * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many
  524. * bits are computed each time on allocation and deallocation, requiring 4
  525. * array indexed access and 3 arithmetic operations. When not defined, a runtime
  526. * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed.
  527. * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation.
  528. * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may
  529. * be used by defining BCM_MWBMAP_USE_CNTSETBITS.
  530. *
  531. * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array
  532. * size is fixed. No intention to support larger than 4K indice allocation. ID
  533. * allocators for ranges smaller than 4K will have a wastage of only 12Bytes
  534. * with savings in not having to use an indirect access, had it been dynamically
  535. * allocated.
  536. */
  537. #define BCM_MWBMAP_ITEMS_MAX (64 * 1024) /* May increase to 64K */
  538. #define BCM_MWBMAP_BITS_WORD (NBITS(uint32))
  539. #define BCM_MWBMAP_WORDS_MAX (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD)
  540. #define BCM_MWBMAP_WDMAP_MAX (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD)
  541. #define BCM_MWBMAP_SHIFT_OP (5)
  542. #define BCM_MWBMAP_MODOP(ix) ((ix) & (BCM_MWBMAP_BITS_WORD - 1))
  543. #define BCM_MWBMAP_DIVOP(ix) ((ix) >> BCM_MWBMAP_SHIFT_OP)
  544. #define BCM_MWBMAP_MULOP(ix) ((ix) << BCM_MWBMAP_SHIFT_OP)
  545. /* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */
  546. #define BCM_MWBMAP_PTR(hdl) ((struct bcm_mwbmap *)(hdl))
  547. #define BCM_MWBMAP_HDL(ptr) ((void *)(ptr))
  548. #if defined(BCM_MWBMAP_DEBUG)
  549. #define BCM_MWBMAP_AUDIT(mwb) \
  550. do { \
  551. ASSERT((mwb != NULL) && \
  552. (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \
  553. bcm_mwbmap_audit(mwb); \
  554. } while (0)
  555. #define MWBMAP_ASSERT(exp) ASSERT(exp)
  556. #define MWBMAP_DBG(x) printf x
  557. #else /* !BCM_MWBMAP_DEBUG */
  558. #define BCM_MWBMAP_AUDIT(mwb) do {} while (0)
  559. #define MWBMAP_ASSERT(exp) do {} while (0)
  560. #define MWBMAP_DBG(x)
  561. #endif /* !BCM_MWBMAP_DEBUG */
  562. typedef struct bcm_mwbmap { /* Hierarchical multiword bitmap allocator */
  563. uint16 wmaps; /* Total number of words in free wd bitmap */
  564. uint16 imaps; /* Total number of words in free id bitmap */
  565. int32 ifree; /* Count of free indices. Used only in audits */
  566. uint16 total; /* Total indices managed by multiword bitmap */
  567. void * magic; /* Audit handle parameter from user */
  568. uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of */
  569. #if !defined(BCM_MWBMAP_USE_CNTSETBITS)
  570. int8 wd_count[BCM_MWBMAP_WORDS_MAX]; /* free id running count, 1st lvl */
  571. #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
  572. uint32 id_bitmap[0]; /* Second level bitmap */
  573. } bcm_mwbmap_t;
  574. /* Incarnate a hierarchical multiword bitmap based small index allocator. */
  575. struct bcm_mwbmap *
  576. bcm_mwbmap_init(osl_t *osh, uint32 items_max)
  577. {
  578. struct bcm_mwbmap * mwbmap_p;
  579. uint32 wordix, size, words, extra;
  580. /* Implementation Constraint: Uses 32bit word bitmap */
  581. MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U);
  582. MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U);
  583. MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX));
  584. MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U);
  585. ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX);
  586. /* Determine the number of words needed in the multiword bitmap */
  587. extra = BCM_MWBMAP_MODOP(items_max);
  588. words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U);
  589. /* Allocate runtime state of multiword bitmap */
  590. /* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */
  591. size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words);
  592. mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size);
  593. if (mwbmap_p == (bcm_mwbmap_t *)NULL) {
  594. ASSERT(0);
  595. goto error1;
  596. }
  597. memset(mwbmap_p, 0, size);
  598. /* Initialize runtime multiword bitmap state */
  599. mwbmap_p->imaps = (uint16)words;
  600. mwbmap_p->ifree = (int32)items_max;
  601. mwbmap_p->total = (uint16)items_max;
  602. /* Setup magic, for use in audit of handle */
  603. mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p);
  604. /* Setup the second level bitmap of free indices */
  605. /* Mark all indices as available */
  606. for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) {
  607. mwbmap_p->id_bitmap[wordix] = (uint32)(~0U);
  608. #if !defined(BCM_MWBMAP_USE_CNTSETBITS)
  609. mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD;
  610. #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
  611. }
  612. /* Ensure that extra indices are tagged as un-available */
  613. if (extra) { /* fixup the free ids in last bitmap and wd_count */
  614. uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1];
  615. *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
  616. #if !defined(BCM_MWBMAP_USE_CNTSETBITS)
  617. mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */
  618. #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
  619. }
  620. /* Setup the first level bitmap hierarchy */
  621. extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps);
  622. words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U);
  623. mwbmap_p->wmaps = (uint16)words;
  624. for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++)
  625. mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U);
  626. if (extra) {
  627. uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1];
  628. *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
  629. }
  630. return mwbmap_p;
  631. error1:
  632. return BCM_MWBMAP_INVALID_HDL;
  633. }
  634. /* Release resources used by multiword bitmap based small index allocator. */
  635. void
  636. bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl)
  637. {
  638. bcm_mwbmap_t * mwbmap_p;
  639. BCM_MWBMAP_AUDIT(mwbmap_hdl);
  640. mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
  641. MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap)
  642. + (sizeof(uint32) * mwbmap_p->imaps));
  643. return;
  644. }
  645. /* Allocate a unique small index using a multiword bitmap index allocator. */
  646. uint32 BCMFASTPATH
  647. bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl)
  648. {
  649. bcm_mwbmap_t * mwbmap_p;
  650. uint32 wordix, bitmap;
  651. BCM_MWBMAP_AUDIT(mwbmap_hdl);
  652. mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
  653. /* Start with the first hierarchy */
  654. for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) {
  655. bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */
  656. if (bitmap != 0U) {
  657. uint32 count, bitix, *bitmap_p;
  658. bitmap_p = &mwbmap_p->wd_bitmap[wordix];
  659. /* clear all except trailing 1 */
  660. bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
  661. MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
  662. bcm_count_leading_zeros(bitmap));
  663. bitix = (BCM_MWBMAP_BITS_WORD - 1)
  664. - (uint32)bcm_count_leading_zeros(bitmap); /* use asm clz */
  665. wordix = BCM_MWBMAP_MULOP(wordix) + bitix;
  666. /* Clear bit if wd count is 0, without conditional branch */
  667. #if defined(BCM_MWBMAP_USE_CNTSETBITS)
  668. count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1;
  669. #else /* ! BCM_MWBMAP_USE_CNTSETBITS */
  670. mwbmap_p->wd_count[wordix]--;
  671. count = (uint32)mwbmap_p->wd_count[wordix];
  672. MWBMAP_ASSERT(count ==
  673. (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1));
  674. #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
  675. MWBMAP_ASSERT(count >= 0);
  676. /* clear wd_bitmap bit if id_map count is 0 */
  677. bitmap = ((uint32)(count == 0)) << BCM_MWBMAP_MODOP(bitix);
  678. MWBMAP_DBG((
  679. "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
  680. bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count));
  681. *bitmap_p ^= bitmap;
  682. /* Use bitix in the second hierarchy */
  683. bitmap_p = &mwbmap_p->id_bitmap[wordix];
  684. bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */
  685. MWBMAP_ASSERT(bitmap != 0U);
  686. /* clear all except trailing 1 */
  687. bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
  688. MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
  689. bcm_count_leading_zeros(bitmap));
  690. bitix = BCM_MWBMAP_MULOP(wordix)
  691. + (BCM_MWBMAP_BITS_WORD - 1)
  692. - (uint32)bcm_count_leading_zeros(bitmap); /* use asm clz */
  693. mwbmap_p->ifree--; /* decrement system wide free count */
  694. MWBMAP_ASSERT(mwbmap_p->ifree >= 0);
  695. MWBMAP_DBG((
  696. "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d",
  697. bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
  698. mwbmap_p->ifree));
  699. *bitmap_p ^= bitmap; /* mark as allocated = 1b0 */
  700. return bitix;
  701. }
  702. }
  703. ASSERT(mwbmap_p->ifree == 0);
  704. return BCM_MWBMAP_INVALID_IDX;
  705. }
  706. /* Force an index at a specified position to be in use */
  707. void
  708. bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
  709. {
  710. bcm_mwbmap_t * mwbmap_p;
  711. uint32 count, wordix, bitmap, *bitmap_p;
  712. BCM_MWBMAP_AUDIT(mwbmap_hdl);
  713. mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
  714. ASSERT(bitix < mwbmap_p->total);
  715. /* Start with second hierarchy */
  716. wordix = BCM_MWBMAP_DIVOP(bitix);
  717. bitmap = (uint32)(1U << BCM_MWBMAP_MODOP(bitix));
  718. bitmap_p = &mwbmap_p->id_bitmap[wordix];
  719. ASSERT((*bitmap_p & bitmap) == bitmap);
  720. mwbmap_p->ifree--; /* update free count */
  721. ASSERT(mwbmap_p->ifree >= 0);
  722. MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d",
  723. bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
  724. mwbmap_p->ifree));
  725. *bitmap_p ^= bitmap; /* mark as in use */
  726. /* Update first hierarchy */
  727. bitix = wordix;
  728. wordix = BCM_MWBMAP_DIVOP(bitix);
  729. bitmap_p = &mwbmap_p->wd_bitmap[wordix];
  730. #if defined(BCM_MWBMAP_USE_CNTSETBITS)
  731. count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
  732. #else /* ! BCM_MWBMAP_USE_CNTSETBITS */
  733. mwbmap_p->wd_count[bitix]--;
  734. count = (uint32)mwbmap_p->wd_count[bitix];
  735. MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
  736. #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
  737. MWBMAP_ASSERT(count >= 0);
  738. bitmap = (uint32)(count == 0) << BCM_MWBMAP_MODOP(bitix);
  739. MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
  740. BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap,
  741. (*bitmap_p) ^ bitmap, count));
  742. *bitmap_p ^= bitmap; /* mark as in use */
  743. return;
  744. }
  745. /* Free a previously allocated index back into the multiword bitmap allocator */
  746. void BCMFASTPATH
  747. bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
  748. {
  749. bcm_mwbmap_t * mwbmap_p;
  750. uint32 wordix, bitmap, *bitmap_p;
  751. BCM_MWBMAP_AUDIT(mwbmap_hdl);
  752. mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
  753. ASSERT(bitix < mwbmap_p->total);
  754. /* Start with second level hierarchy */
  755. wordix = BCM_MWBMAP_DIVOP(bitix);
  756. bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
  757. bitmap_p = &mwbmap_p->id_bitmap[wordix];
  758. ASSERT((*bitmap_p & bitmap) == 0U); /* ASSERT not a double free */
  759. mwbmap_p->ifree++; /* update free count */
  760. ASSERT(mwbmap_p->ifree <= mwbmap_p->total);
  761. MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d",
  762. bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap,
  763. mwbmap_p->ifree));
  764. *bitmap_p |= bitmap; /* mark as available */
  765. /* Now update first level hierarchy */
  766. bitix = wordix;
  767. wordix = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */
  768. bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
  769. bitmap_p = &mwbmap_p->wd_bitmap[wordix];
  770. #if !defined(BCM_MWBMAP_USE_CNTSETBITS)
  771. mwbmap_p->wd_count[bitix]++;
  772. #endif // endif
  773. #if defined(BCM_MWBMAP_DEBUG)
  774. {
  775. uint32 count;
  776. #if defined(BCM_MWBMAP_USE_CNTSETBITS)
  777. count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
  778. #else /* ! BCM_MWBMAP_USE_CNTSETBITS */
  779. count = mwbmap_p->wd_count[bitix];
  780. MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
  781. #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
  782. MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD);
  783. MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d",
  784. bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count));
  785. }
  786. #endif /* BCM_MWBMAP_DEBUG */
  787. *bitmap_p |= bitmap;
  788. return;
  789. }
  790. /* Fetch the toal number of free indices in the multiword bitmap allocator */
  791. uint32
  792. bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl)
  793. {
  794. bcm_mwbmap_t * mwbmap_p;
  795. BCM_MWBMAP_AUDIT(mwbmap_hdl);
  796. mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
  797. ASSERT(mwbmap_p->ifree >= 0);
  798. return (uint32)mwbmap_p->ifree;
  799. }
  800. /* Determine whether an index is inuse or free */
  801. bool
  802. bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
  803. {
  804. bcm_mwbmap_t * mwbmap_p;
  805. uint32 wordix, bitmap;
  806. BCM_MWBMAP_AUDIT(mwbmap_hdl);
  807. mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
  808. ASSERT(bitix < mwbmap_p->total);
  809. wordix = BCM_MWBMAP_DIVOP(bitix);
  810. bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
  811. return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U);
  812. }
  813. /* Debug dump a multiword bitmap allocator */
  814. void
  815. bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl)
  816. {
  817. uint32 ix, count;
  818. bcm_mwbmap_t * mwbmap_p;
  819. BCM_MWBMAP_AUDIT(mwbmap_hdl);
  820. mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
  821. printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n",
  822. OSL_OBFUSCATE_BUF((void *)mwbmap_p),
  823. mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total);
  824. for (ix = 0U; ix < mwbmap_p->wmaps; ix++) {
  825. printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]);
  826. bcm_bitprint32(mwbmap_p->wd_bitmap[ix]);
  827. printf("\n");
  828. }
  829. for (ix = 0U; ix < mwbmap_p->imaps; ix++) {
  830. #if defined(BCM_MWBMAP_USE_CNTSETBITS)
  831. count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]);
  832. #else /* ! BCM_MWBMAP_USE_CNTSETBITS */
  833. count = (uint32)mwbmap_p->wd_count[ix];
  834. MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix]));
  835. #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
  836. printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count);
  837. bcm_bitprint32(mwbmap_p->id_bitmap[ix]);
  838. printf("\n");
  839. }
  840. return;
  841. }
  842. /* Audit a hierarchical multiword bitmap */
  843. void
  844. bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl)
  845. {
  846. bcm_mwbmap_t * mwbmap_p;
  847. uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p;
  848. mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
  849. for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) {
  850. bitmap_p = &mwbmap_p->wd_bitmap[wordix];
  851. for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) {
  852. if ((*bitmap_p) & (1 << bitix)) {
  853. idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix;
  854. #if defined(BCM_MWBMAP_USE_CNTSETBITS)
  855. count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]);
  856. #else /* ! BCM_MWBMAP_USE_CNTSETBITS */
  857. count = (uint32)mwbmap_p->wd_count[idmap_ix];
  858. ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]));
  859. #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
  860. ASSERT(count != 0U);
  861. free_cnt += count;
  862. }
  863. }
  864. }
  865. ASSERT((int)free_cnt == mwbmap_p->ifree);
  866. }
  867. /* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */
  868. /* Simple 16bit Id allocator using a stack implementation. */
  869. typedef struct id16_map {
  870. uint32 failures; /* count of failures */
  871. void *dbg; /* debug placeholder */
  872. uint16 total; /* total number of ids managed by allocator */
  873. uint16 start; /* start value of 16bit ids to be managed */
  874. int stack_idx; /* index into stack of available ids */
  875. uint16 stack[0]; /* stack of 16 bit ids */
  876. } id16_map_t;
  877. #define ID16_MAP_SZ(items) (sizeof(id16_map_t) + \
  878. (sizeof(uint16) * (items)))
  879. #if defined(BCM_DBG)
  880. /* Uncomment BCM_DBG_ID16 to debug double free */
  881. /* #define BCM_DBG_ID16 */
  882. typedef struct id16_map_dbg {
  883. uint16 total;
  884. bool avail[0];
  885. } id16_map_dbg_t;
  886. #define ID16_MAP_DBG_SZ(items) (sizeof(id16_map_dbg_t) + \
  887. (sizeof(bool) * (items)))
  888. #define ID16_MAP_MSG(x) print x
  889. #else
  890. #define ID16_MAP_MSG(x)
  891. #endif /* BCM_DBG */
  892. void * /* Construct an id16 allocator: [start_val16 .. start_val16+total_ids) */
  893. id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16)
  894. {
  895. uint16 idx, val16;
  896. id16_map_t * id16_map;
  897. ASSERT(total_ids > 0);
  898. /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
  899. * with random values.
  900. */
  901. ASSERT((start_val16 == ID16_UNDEFINED) ||
  902. (start_val16 + total_ids) < ID16_INVALID);
  903. id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids));
  904. if (id16_map == NULL) {
  905. return NULL;
  906. }
  907. id16_map->total = total_ids;
  908. id16_map->start = start_val16;
  909. id16_map->failures = 0;
  910. id16_map->dbg = NULL;
  911. /*
  912. * Populate stack with 16bit id values, commencing with start_val16.
  913. * if start_val16 is ID16_UNDEFINED, then do not populate the id16 map.
  914. */
  915. id16_map->stack_idx = -1;
  916. if (id16_map->start != ID16_UNDEFINED) {
  917. val16 = start_val16;
  918. for (idx = 0; idx < total_ids; idx++, val16++) {
  919. id16_map->stack_idx = idx;
  920. id16_map->stack[id16_map->stack_idx] = val16;
  921. }
  922. }
  923. #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
  924. if (id16_map->start != ID16_UNDEFINED) {
  925. id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids));
  926. if (id16_map->dbg) {
  927. id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
  928. id16_map_dbg->total = total_ids;
  929. for (idx = 0; idx < total_ids; idx++) {
  930. id16_map_dbg->avail[idx] = TRUE;
  931. }
  932. }
  933. }
  934. #endif /* BCM_DBG && BCM_DBG_ID16 */
  935. return (void *)id16_map;
  936. }
  937. void * /* Destruct an id16 allocator instance */
  938. id16_map_fini(osl_t *osh, void * id16_map_hndl)
  939. {
  940. uint16 total_ids;
  941. id16_map_t * id16_map;
  942. if (id16_map_hndl == NULL)
  943. return NULL;
  944. id16_map = (id16_map_t *)id16_map_hndl;
  945. total_ids = id16_map->total;
  946. ASSERT(total_ids > 0);
  947. #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
  948. if (id16_map->dbg) {
  949. MFREE(osh, id16_map->dbg, ID16_MAP_DBG_SZ(total_ids));
  950. id16_map->dbg = NULL;
  951. }
  952. #endif /* BCM_DBG && BCM_DBG_ID16 */
  953. id16_map->total = 0;
  954. MFREE(osh, id16_map, ID16_MAP_SZ(total_ids));
  955. return NULL;
  956. }
  957. void
  958. id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16)
  959. {
  960. uint16 idx, val16;
  961. id16_map_t * id16_map;
  962. ASSERT(total_ids > 0);
  963. /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
  964. * with random values.
  965. */
  966. ASSERT((start_val16 == ID16_UNDEFINED) ||
  967. (start_val16 + total_ids) < ID16_INVALID);
  968. id16_map = (id16_map_t *)id16_map_hndl;
  969. if (id16_map == NULL) {
  970. return;
  971. }
  972. id16_map->total = total_ids;
  973. id16_map->start = start_val16;
  974. id16_map->failures = 0;
  975. /* Populate stack with 16bit id values, commencing with start_val16 */
  976. id16_map->stack_idx = -1;
  977. if (id16_map->start != ID16_UNDEFINED) {
  978. val16 = start_val16;
  979. for (idx = 0; idx < total_ids; idx++, val16++) {
  980. id16_map->stack_idx = idx;
  981. id16_map->stack[id16_map->stack_idx] = val16;
  982. }
  983. }
  984. #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
  985. if (id16_map->start != ID16_UNDEFINED) {
  986. if (id16_map->dbg) {
  987. id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
  988. id16_map_dbg->total = total_ids;
  989. for (idx = 0; idx < total_ids; idx++) {
  990. id16_map_dbg->avail[idx] = TRUE;
  991. }
  992. }
  993. }
  994. #endif /* BCM_DBG && BCM_DBG_ID16 */
  995. }
  996. uint16 BCMFASTPATH /* Allocate a unique 16bit id */
  997. id16_map_alloc(void * id16_map_hndl)
  998. {
  999. uint16 val16;
  1000. id16_map_t * id16_map;
  1001. ASSERT(id16_map_hndl != NULL);
  1002. if (!id16_map_hndl) {
  1003. return ID16_INVALID;
  1004. }
  1005. id16_map = (id16_map_t *)id16_map_hndl;
  1006. ASSERT(id16_map->total > 0);
  1007. if (id16_map->stack_idx < 0) {
  1008. id16_map->failures++;
  1009. return ID16_INVALID;
  1010. }
  1011. val16 = id16_map->stack[id16_map->stack_idx];
  1012. id16_map->stack_idx--;
  1013. #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
  1014. ASSERT((id16_map->start == ID16_UNDEFINED) ||
  1015. (val16 < (id16_map->start + id16_map->total)));
  1016. if (id16_map->dbg) { /* Validate val16 */
  1017. id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
  1018. ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == TRUE);
  1019. id16_map_dbg->avail[val16 - id16_map->start] = FALSE;
  1020. }
  1021. #endif /* BCM_DBG && BCM_DBG_ID16 */
  1022. return val16;
  1023. }
  1024. void BCMFASTPATH /* Free a 16bit id value into the id16 allocator */
  1025. id16_map_free(void * id16_map_hndl, uint16 val16)
  1026. {
  1027. id16_map_t * id16_map;
  1028. ASSERT(id16_map_hndl != NULL);
  1029. id16_map = (id16_map_t *)id16_map_hndl;
  1030. #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
  1031. ASSERT((id16_map->start == ID16_UNDEFINED) ||
  1032. (val16 < (id16_map->start + id16_map->total)));
  1033. if (id16_map->dbg) { /* Validate val16 */
  1034. id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
  1035. ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == FALSE);
  1036. id16_map_dbg->avail[val16 - id16_map->start] = TRUE;
  1037. }
  1038. #endif /* BCM_DBG && BCM_DBG_ID16 */
  1039. id16_map->stack_idx++;
  1040. id16_map->stack[id16_map->stack_idx] = val16;
  1041. }
  1042. uint32 /* Returns number of failures to allocate an unique id16 */
  1043. id16_map_failures(void * id16_map_hndl)
  1044. {
  1045. ASSERT(id16_map_hndl != NULL);
  1046. return ((id16_map_t *)id16_map_hndl)->failures;
  1047. }
  1048. bool
  1049. id16_map_audit(void * id16_map_hndl)
  1050. {
  1051. int idx;
  1052. int insane = 0;
  1053. id16_map_t * id16_map;
  1054. ASSERT(id16_map_hndl != NULL);
  1055. if (!id16_map_hndl) {
  1056. goto done;
  1057. }
  1058. id16_map = (id16_map_t *)id16_map_hndl;
  1059. ASSERT(id16_map->stack_idx >= -1);
  1060. ASSERT(id16_map->stack_idx < (int)id16_map->total);
  1061. if (id16_map->start == ID16_UNDEFINED)
  1062. goto done;
  1063. for (idx = 0; idx <= id16_map->stack_idx; idx++) {
  1064. ASSERT(id16_map->stack[idx] >= id16_map->start);
  1065. ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total));
  1066. #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
  1067. if (id16_map->dbg) {
  1068. uint16 val16 = id16_map->stack[idx];
  1069. if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) {
  1070. insane |= 1;
  1071. ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n",
  1072. OSL_OBFUSATE_BUF(id16_map_hndl), idx, val16));
  1073. }
  1074. }
  1075. #endif /* BCM_DBG && BCM_DBG_ID16 */
  1076. }
  1077. #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
  1078. if (id16_map->dbg) {
  1079. uint16 avail = 0; /* Audit available ids counts */
  1080. for (idx = 0; idx < id16_map_dbg->total; idx++) {
  1081. if (((id16_map_dbg_t *)(id16_map->dbg))->avail[idx16] == TRUE)
  1082. avail++;
  1083. }
  1084. if (avail && (avail != (id16_map->stack_idx + 1))) {
  1085. insane |= 1;
  1086. ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n",
  1087. OSL_OBFUSCATE_BUF(id16_map_hndl),
  1088. avail, id16_map->stack_idx));
  1089. }
  1090. }
  1091. #endif /* BCM_DBG && BCM_DBG_ID16 */
  1092. done:
  1093. /* invoke any other system audits */
  1094. return (!!insane);
  1095. }
  1096. /* END: Simple id16 allocator */
  1097. void
  1098. dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size)
  1099. {
  1100. uint32 memsize;
  1101. memsize = sizeof(dll_pool_t) + (elems_max * elem_size);
  1102. if (pool)
  1103. MFREE(osh, pool, memsize);
  1104. }
  1105. dll_pool_t *
  1106. dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size)
  1107. {
  1108. uint32 memsize, i;
  1109. dll_pool_t * dll_pool_p;
  1110. dll_t * elem_p;
  1111. ASSERT(elem_size > sizeof(dll_t));
  1112. memsize = sizeof(dll_pool_t) + (elems_max * elem_size);
  1113. if ((dll_pool_p = (dll_pool_t *)MALLOCZ(osh, memsize)) == NULL) {
  1114. printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n",
  1115. elems_max, elem_size);
  1116. ASSERT(0);
  1117. return dll_pool_p;
  1118. }
  1119. dll_init(&dll_pool_p->free_list);
  1120. dll_pool_p->elems_max = elems_max;
  1121. dll_pool_p->elem_size = elem_size;
  1122. elem_p = dll_pool_p->elements;
  1123. for (i = 0; i < elems_max; i++) {
  1124. dll_append(&dll_pool_p->free_list, elem_p);
  1125. elem_p = (dll_t *)((uintptr)elem_p + elem_size);
  1126. }
  1127. dll_pool_p->free_count = elems_max;
  1128. return dll_pool_p;
  1129. }
  1130. void *
  1131. dll_pool_alloc(dll_pool_t * dll_pool_p)
  1132. {
  1133. dll_t * elem_p;
  1134. if (dll_pool_p->free_count == 0) {
  1135. ASSERT(dll_empty(&dll_pool_p->free_list));
  1136. return NULL;
  1137. }
  1138. elem_p = dll_head_p(&dll_pool_p->free_list);
  1139. dll_delete(elem_p);
  1140. dll_pool_p->free_count -= 1;
  1141. return (void *)elem_p;
  1142. }
  1143. void
  1144. dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p)
  1145. {
  1146. dll_t * node_p = (dll_t *)elem_p;
  1147. dll_prepend(&dll_pool_p->free_list, node_p);
  1148. dll_pool_p->free_count += 1;
  1149. }
  1150. void
  1151. dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p)
  1152. {
  1153. dll_t * node_p = (dll_t *)elem_p;
  1154. dll_append(&dll_pool_p->free_list, node_p);
  1155. dll_pool_p->free_count += 1;
  1156. }
  1157. #endif // endif
  1158. #endif /* BCMDRIVER */
  1159. #if defined(BCMDRIVER) || defined(WL_UNITTEST)
  1160. /* triggers bcm_bprintf to print to kernel log */
  1161. bool bcm_bprintf_bypass = FALSE;
  1162. /* Initialization of bcmstrbuf structure */
  1163. void
  1164. bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
  1165. {
  1166. b->origsize = b->size = size;
  1167. b->origbuf = b->buf = buf;
  1168. if (size > 0) {
  1169. buf[0] = '\0';
  1170. }
  1171. }
  1172. /* Buffer sprintf wrapper to guard against buffer overflow */
  1173. int
  1174. bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
  1175. {
  1176. va_list ap;
  1177. int r;
  1178. va_start(ap, fmt);
  1179. r = vsnprintf(b->buf, b->size, fmt, ap);
  1180. if (bcm_bprintf_bypass == TRUE) {
  1181. printf("%s", b->buf);
  1182. goto exit;
  1183. }
  1184. /* Non Ansi C99 compliant returns -1,
  1185. * Ansi compliant return r >= b->size,
  1186. * bcmstdlib returns 0, handle all
  1187. */
  1188. /* r == 0 is also the case when strlen(fmt) is zero.
  1189. * typically the case when "" is passed as argument.
  1190. */
  1191. if ((r == -1) || (r >= (int)b->size)) {
  1192. b->size = 0;
  1193. } else {
  1194. b->size -= (uint)r;
  1195. b->buf += r;
  1196. }
  1197. exit:
  1198. va_end(ap);
  1199. return r;
  1200. }
  1201. void
  1202. bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, const uint8 *buf, int len)
  1203. {
  1204. int i;
  1205. if (msg != NULL && msg[0] != '\0')
  1206. bcm_bprintf(b, "%s", msg);
  1207. for (i = 0; i < len; i ++)
  1208. bcm_bprintf(b, "%02X", buf[i]);
  1209. if (newline)
  1210. bcm_bprintf(b, "\n");
  1211. }
  1212. void
  1213. bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount)
  1214. {
  1215. int i;
  1216. for (i = 0; i < num_bytes; i++) {
  1217. num[i] += amount;
  1218. if (num[i] >= amount)
  1219. break;
  1220. amount = 1;
  1221. }
  1222. }
  1223. int
  1224. bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes)
  1225. {
  1226. int i;
  1227. for (i = nbytes - 1; i >= 0; i--) {
  1228. if (arg1[i] != arg2[i])
  1229. return (arg1[i] - arg2[i]);
  1230. }
  1231. return 0;
  1232. }
  1233. void
  1234. bcm_print_bytes(const char *name, const uchar *data, int len)
  1235. {
  1236. int i;
  1237. int per_line = 0;
  1238. printf("%s: %d \n", name ? name : "", len);
  1239. for (i = 0; i < len; i++) {
  1240. printf("%02x ", *data++);
  1241. per_line++;
  1242. if (per_line == 16) {
  1243. per_line = 0;
  1244. printf("\n");
  1245. }
  1246. }
  1247. printf("\n");
  1248. }
  1249. /* Look for vendor-specific IE with specified OUI and optional type */
  1250. bcm_tlv_t *
  1251. bcm_find_vendor_ie(const void *tlvs, uint tlvs_len, const char *voui, uint8 *type, uint type_len)
  1252. {
  1253. const bcm_tlv_t *ie;
  1254. uint8 ie_len;
  1255. ie = (const bcm_tlv_t*)tlvs;
  1256. /* make sure we are looking at a valid IE */
  1257. if (ie == NULL || !bcm_valid_tlv(ie, tlvs_len)) {
  1258. return NULL;
  1259. }
  1260. /* Walk through the IEs looking for an OUI match */
  1261. do {
  1262. ie_len = ie->len;
  1263. if ((ie->id == DOT11_MNG_VS_ID) &&
  1264. (ie_len >= (DOT11_OUI_LEN + type_len)) &&
  1265. !bcmp(ie->data, voui, DOT11_OUI_LEN))
  1266. {
  1267. /* compare optional type */
  1268. if (type_len == 0 ||
  1269. !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) {
  1270. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  1271. return (bcm_tlv_t *)(ie); /* a match */
  1272. GCC_DIAGNOSTIC_POP();
  1273. }
  1274. }
  1275. } while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL);
  1276. return NULL;
  1277. }
  1278. #if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
  1279. defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
  1280. #define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1)
  1281. int
  1282. bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len)
  1283. {
  1284. uint i, c;
  1285. char *p = buf;
  1286. char *endp = buf + SSID_FMT_BUF_LEN;
  1287. if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN;
  1288. for (i = 0; i < ssid_len; i++) {
  1289. c = (uint)ssid[i];
  1290. if (c == '\\') {
  1291. *p++ = '\\';
  1292. *p++ = '\\';
  1293. } else if (bcm_isprint((uchar)c)) {
  1294. *p++ = (char)c;
  1295. } else {
  1296. p += snprintf(p, (size_t)(endp - p), "\\x%02X", c);
  1297. }
  1298. }
  1299. *p = '\0';
  1300. ASSERT(p < endp);
  1301. return (int)(p - buf);
  1302. }
  1303. #endif // endif
  1304. #endif /* BCMDRIVER || WL_UNITTEST */
  1305. char *
  1306. bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
  1307. {
  1308. static const char hex[] =
  1309. {
  1310. '0', '1', '2', '3', '4', '5', '6', '7',
  1311. '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
  1312. };
  1313. const uint8 *octet = ea->octet;
  1314. char *p = buf;
  1315. int i;
  1316. for (i = 0; i < 6; i++, octet++) {
  1317. *p++ = hex[(*octet >> 4) & 0xf];
  1318. *p++ = hex[*octet & 0xf];
  1319. *p++ = ':';
  1320. }
  1321. *(p-1) = '\0';
  1322. return (buf);
  1323. }
  1324. /* Find the position of first bit set
  1325. * in the given number.
  1326. */
  1327. int
  1328. bcm_find_fsb(uint32 num)
  1329. {
  1330. uint8 pos = 0;
  1331. if (!num)
  1332. return pos;
  1333. while (!(num & 1)) {
  1334. num >>= 1;
  1335. pos++;
  1336. }
  1337. return (pos+1);
  1338. }
  1339. char *
  1340. bcm_ip_ntoa(struct ipv4_addr *ia, char *buf)
  1341. {
  1342. snprintf(buf, 16, "%d.%d.%d.%d",
  1343. ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]);
  1344. return (buf);
  1345. }
  1346. char *
  1347. bcm_ipv6_ntoa(void *ipv6, char *buf)
  1348. {
  1349. /* Implementing RFC 5952 Sections 4 + 5 */
  1350. /* Not thoroughly tested */
  1351. uint16 tmp[8];
  1352. uint16 *a = &tmp[0];
  1353. char *p = buf;
  1354. int i, i_max = -1, cnt = 0, cnt_max = 1;
  1355. uint8 *a4 = NULL;
  1356. memcpy((uint8 *)&tmp[0], (uint8 *)ipv6, IPV6_ADDR_LEN);
  1357. for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
  1358. if (a[i]) {
  1359. if (cnt > cnt_max) {
  1360. cnt_max = cnt;
  1361. i_max = i - cnt;
  1362. }
  1363. cnt = 0;
  1364. } else
  1365. cnt++;
  1366. }
  1367. if (cnt > cnt_max) {
  1368. cnt_max = cnt;
  1369. i_max = i - cnt;
  1370. }
  1371. if (i_max == 0 &&
  1372. /* IPv4-translated: ::ffff:0:a.b.c.d */
  1373. ((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) ||
  1374. /* IPv4-mapped: ::ffff:a.b.c.d */
  1375. (cnt_max == 5 && a[5] == 0xffff)))
  1376. a4 = (uint8*) (a + 6);
  1377. for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
  1378. if ((uint8*) (a + i) == a4) {
  1379. snprintf(p, 16, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]);
  1380. break;
  1381. } else if (i == i_max) {
  1382. *p++ = ':';
  1383. i += cnt_max - 1;
  1384. p[0] = ':';
  1385. p[1] = '\0';
  1386. } else {
  1387. if (i)
  1388. *p++ = ':';
  1389. p += snprintf(p, 8, "%x", ntoh16(a[i]));
  1390. }
  1391. }
  1392. return buf;
  1393. }
  1394. #if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
  1395. const unsigned char bcm_ctype[] = {
  1396. _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */
  1397. _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C,
  1398. _BCM_C, /* 8-15 */
  1399. _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */
  1400. _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */
  1401. _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */
  1402. _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */
  1403. _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */
  1404. _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */
  1405. _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X,
  1406. _BCM_U|_BCM_X, _BCM_U, /* 64-71 */
  1407. _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */
  1408. _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */
  1409. _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */
  1410. _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X,
  1411. _BCM_L|_BCM_X, _BCM_L, /* 96-103 */
  1412. _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
  1413. _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
  1414. _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
  1415. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */
  1416. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */
  1417. _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
  1418. _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */
  1419. _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
  1420. _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */
  1421. _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
  1422. _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */
  1423. _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U,
  1424. _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */
  1425. _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
  1426. _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */
  1427. _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L,
  1428. _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */
  1429. };
  1430. uint64
  1431. bcm_strtoull(const char *cp, char **endp, uint base)
  1432. {
  1433. uint64 result, last_result = 0, value;
  1434. bool minus;
  1435. minus = FALSE;
  1436. while (bcm_isspace(*cp))
  1437. cp++;
  1438. if (cp[0] == '+')
  1439. cp++;
  1440. else if (cp[0] == '-') {
  1441. minus = TRUE;
  1442. cp++;
  1443. }
  1444. if (base == 0) {
  1445. if (cp[0] == '0') {
  1446. if ((cp[1] == 'x') || (cp[1] == 'X')) {
  1447. base = 16;
  1448. cp = &cp[2];
  1449. } else {
  1450. base = 8;
  1451. cp = &cp[1];
  1452. }
  1453. } else
  1454. base = 10;
  1455. } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
  1456. cp = &cp[2];
  1457. }
  1458. result = 0;
  1459. while (bcm_isxdigit(*cp) &&
  1460. (value = (uint64)(bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10)) < base) {
  1461. result = result*base + value;
  1462. /* Detected overflow */
  1463. if (result < last_result && !minus) {
  1464. if (endp) {
  1465. /* Go to the end of current number */
  1466. while (bcm_isxdigit(*cp)) {
  1467. cp++;
  1468. }
  1469. *endp = DISCARD_QUAL(cp, char);
  1470. }
  1471. return (ulong)-1;
  1472. }
  1473. last_result = result;
  1474. cp++;
  1475. }
  1476. if (minus)
  1477. result = (ulong)(-(long)result);
  1478. if (endp)
  1479. *endp = DISCARD_QUAL(cp, char);
  1480. return (result);
  1481. }
  1482. ulong
  1483. bcm_strtoul(const char *cp, char **endp, uint base)
  1484. {
  1485. return (ulong) bcm_strtoull(cp, endp, base);
  1486. }
  1487. int
  1488. bcm_atoi(const char *s)
  1489. {
  1490. return (int)bcm_strtoul(s, NULL, 10);
  1491. }
  1492. /* return pointer to location of substring 'needle' in 'haystack' */
  1493. char *
  1494. bcmstrstr(const char *haystack, const char *needle)
  1495. {
  1496. int len, nlen;
  1497. int i;
  1498. if ((haystack == NULL) || (needle == NULL))
  1499. return DISCARD_QUAL(haystack, char);
  1500. nlen = (int)strlen(needle);
  1501. len = (int)strlen(haystack) - nlen + 1;
  1502. for (i = 0; i < len; i++)
  1503. if (memcmp(needle, &haystack[i], (size_t)nlen) == 0)
  1504. return DISCARD_QUAL(&haystack[i], char);
  1505. return (NULL);
  1506. }
  1507. char *
  1508. bcmstrnstr(const char *s, uint s_len, const char *substr, uint substr_len)
  1509. {
  1510. for (; s_len >= substr_len; s++, s_len--)
  1511. if (strncmp(s, substr, substr_len) == 0)
  1512. return DISCARD_QUAL(s, char);
  1513. return NULL;
  1514. }
  1515. char *
  1516. bcmstrcat(char *dest, const char *src)
  1517. {
  1518. char *p;
  1519. p = dest + strlen(dest);
  1520. while ((*p++ = *src++) != '\0')
  1521. ;
  1522. return (dest);
  1523. }
  1524. char *
  1525. bcmstrncat(char *dest, const char *src, uint size)
  1526. {
  1527. char *endp;
  1528. char *p;
  1529. p = dest + strlen(dest);
  1530. endp = p + size;
  1531. while (p != endp && (*p++ = *src++) != '\0')
  1532. ;
  1533. return (dest);
  1534. }
  1535. /****************************************************************************
  1536. * Function: bcmstrtok
  1537. *
  1538. * Purpose:
  1539. * Tokenizes a string. This function is conceptually similiar to ANSI C strtok(),
  1540. * but allows strToken() to be used by different strings or callers at the same
  1541. * time. Each call modifies '*string' by substituting a NULL character for the
  1542. * first delimiter that is encountered, and updates 'string' to point to the char
  1543. * after the delimiter. Leading delimiters are skipped.
  1544. *
  1545. * Parameters:
  1546. * string (mod) Ptr to string ptr, updated by token.
  1547. * delimiters (in) Set of delimiter characters.
  1548. * tokdelim (out) Character that delimits the returned token. (May
  1549. * be set to NULL if token delimiter is not required).
  1550. *
  1551. * Returns: Pointer to the next token found. NULL when no more tokens are found.
  1552. *****************************************************************************
  1553. */
  1554. char *
  1555. bcmstrtok(char **string, const char *delimiters, char *tokdelim)
  1556. {
  1557. unsigned char *str;
  1558. unsigned long map[8];
  1559. int count;
  1560. char *nextoken;
  1561. if (tokdelim != NULL) {
  1562. /* Prime the token delimiter */
  1563. *tokdelim = '\0';
  1564. }
  1565. /* Clear control map */
  1566. for (count = 0; count < 8; count++) {
  1567. map[count] = 0;
  1568. }
  1569. /* Set bits in delimiter table */
  1570. do {
  1571. map[*delimiters >> 5] |= (1 << (*delimiters & 31));
  1572. }
  1573. while (*delimiters++);
  1574. str = (unsigned char*)*string;
  1575. /* Find beginning of token (skip over leading delimiters). Note that
  1576. * there is no token iff this loop sets str to point to the terminal
  1577. * null (*str == '\0')
  1578. */
  1579. while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) {
  1580. str++;
  1581. }
  1582. nextoken = (char*)str;
  1583. /* Find the end of the token. If it is not the end of the string,
  1584. * put a null there.
  1585. */
  1586. for (; *str; str++) {
  1587. if (map[*str >> 5] & (1 << (*str & 31))) {
  1588. if (tokdelim != NULL) {
  1589. *tokdelim = (char)*str;
  1590. }
  1591. *str++ = '\0';
  1592. break;
  1593. }
  1594. }
  1595. *string = (char*)str;
  1596. /* Determine if a token has been found. */
  1597. if (nextoken == (char *) str) {
  1598. return NULL;
  1599. }
  1600. else {
  1601. return nextoken;
  1602. }
  1603. }
  1604. #define xToLower(C) \
  1605. ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C)
  1606. /****************************************************************************
  1607. * Function: bcmstricmp
  1608. *
  1609. * Purpose: Compare to strings case insensitively.
  1610. *
  1611. * Parameters: s1 (in) First string to compare.
  1612. * s2 (in) Second string to compare.
  1613. *
  1614. * Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
  1615. * t1 > t2, when ignoring case sensitivity.
  1616. *****************************************************************************
  1617. */
  1618. int
  1619. bcmstricmp(const char *s1, const char *s2)
  1620. {
  1621. char dc, sc;
  1622. while (*s2 && *s1) {
  1623. dc = xToLower(*s1);
  1624. sc = xToLower(*s2);
  1625. if (dc < sc) return -1;
  1626. if (dc > sc) return 1;
  1627. s1++;
  1628. s2++;
  1629. }
  1630. if (*s1 && !*s2) return 1;
  1631. if (!*s1 && *s2) return -1;
  1632. return 0;
  1633. }
  1634. /****************************************************************************
  1635. * Function: bcmstrnicmp
  1636. *
  1637. * Purpose: Compare to strings case insensitively, upto a max of 'cnt'
  1638. * characters.
  1639. *
  1640. * Parameters: s1 (in) First string to compare.
  1641. * s2 (in) Second string to compare.
  1642. * cnt (in) Max characters to compare.
  1643. *
  1644. * Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
  1645. * t1 > t2, when ignoring case sensitivity.
  1646. *****************************************************************************
  1647. */
  1648. int
  1649. bcmstrnicmp(const char* s1, const char* s2, int cnt)
  1650. {
  1651. char dc, sc;
  1652. while (*s2 && *s1 && cnt) {
  1653. dc = xToLower(*s1);
  1654. sc = xToLower(*s2);
  1655. if (dc < sc) return -1;
  1656. if (dc > sc) return 1;
  1657. s1++;
  1658. s2++;
  1659. cnt--;
  1660. }
  1661. if (!cnt) return 0;
  1662. if (*s1 && !*s2) return 1;
  1663. if (!*s1 && *s2) return -1;
  1664. return 0;
  1665. }
  1666. /* parse a xx:xx:xx:xx:xx:xx format ethernet address */
  1667. int
  1668. bcm_ether_atoe(const char *p, struct ether_addr *ea)
  1669. {
  1670. int i = 0;
  1671. char *ep;
  1672. for (;;) {
  1673. ea->octet[i++] = (uint8) bcm_strtoul(p, &ep, 16);
  1674. p = ep;
  1675. if (!*p++ || i == 6)
  1676. break;
  1677. }
  1678. return (i == 6);
  1679. }
  1680. int
  1681. bcm_atoipv4(const char *p, struct ipv4_addr *ip)
  1682. {
  1683. int i = 0;
  1684. char *c;
  1685. for (;;) {
  1686. ip->addr[i++] = (uint8)bcm_strtoul(p, &c, 0);
  1687. if (*c++ != '.' || i == IPV4_ADDR_LEN)
  1688. break;
  1689. p = c;
  1690. }
  1691. return (i == IPV4_ADDR_LEN);
  1692. }
  1693. #endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
  1694. #if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER)
  1695. /* registry routine buffer preparation utility functions:
  1696. * parameter order is like strncpy, but returns count
  1697. * of bytes copied. Minimum bytes copied is null char(1)/wchar(2)
  1698. */
  1699. ulong
  1700. wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen)
  1701. {
  1702. ulong copyct = 1;
  1703. ushort i;
  1704. if (abuflen == 0)
  1705. return 0;
  1706. /* wbuflen is in bytes */
  1707. wbuflen /= sizeof(ushort);
  1708. for (i = 0; i < wbuflen; ++i) {
  1709. if (--abuflen == 0)
  1710. break;
  1711. *abuf++ = (char) *wbuf++;
  1712. ++copyct;
  1713. }
  1714. *abuf = '\0';
  1715. return copyct;
  1716. }
  1717. #endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */
  1718. #ifdef BCM_OBJECT_TRACE
  1719. #define BCM_OBJECT_MERGE_SAME_OBJ 0
  1720. /* some place may add / remove the object to trace list for Linux: */
  1721. /* add: osl_alloc_skb dev_alloc_skb skb_realloc_headroom dhd_start_xmit */
  1722. /* remove: osl_pktfree dev_kfree_skb netif_rx */
  1723. #define BCM_OBJDBG_COUNT (1024 * 100)
  1724. static spinlock_t dbgobj_lock;
  1725. #define BCM_OBJDBG_LOCK_INIT() spin_lock_init(&dbgobj_lock)
  1726. #define BCM_OBJDBG_LOCK_DESTROY()
  1727. #define BCM_OBJDBG_LOCK spin_lock_irqsave
  1728. #define BCM_OBJDBG_UNLOCK spin_unlock_irqrestore
  1729. #define BCM_OBJDBG_ADDTOHEAD 0
  1730. #define BCM_OBJDBG_ADDTOTAIL 1
  1731. #define BCM_OBJDBG_CALLER_LEN 32
  1732. struct bcm_dbgobj {
  1733. struct bcm_dbgobj *prior;
  1734. struct bcm_dbgobj *next;
  1735. uint32 flag;
  1736. void *obj;
  1737. uint32 obj_sn;
  1738. uint32 obj_state;
  1739. uint32 line;
  1740. char caller[BCM_OBJDBG_CALLER_LEN];
  1741. };
  1742. static struct bcm_dbgobj *dbgobj_freehead = NULL;
  1743. static struct bcm_dbgobj *dbgobj_freetail = NULL;
  1744. static struct bcm_dbgobj *dbgobj_objhead = NULL;
  1745. static struct bcm_dbgobj *dbgobj_objtail = NULL;
  1746. static uint32 dbgobj_sn = 0;
  1747. static int dbgobj_count = 0;
  1748. static struct bcm_dbgobj bcm_dbg_objs[BCM_OBJDBG_COUNT];
  1749. void
  1750. bcm_object_trace_init(void)
  1751. {
  1752. int i = 0;
  1753. BCM_OBJDBG_LOCK_INIT();
  1754. memset(&bcm_dbg_objs, 0x00, sizeof(struct bcm_dbgobj) * BCM_OBJDBG_COUNT);
  1755. dbgobj_freehead = &bcm_dbg_objs[0];
  1756. dbgobj_freetail = &bcm_dbg_objs[BCM_OBJDBG_COUNT - 1];
  1757. for (i = 0; i < BCM_OBJDBG_COUNT; ++i) {
  1758. bcm_dbg_objs[i].next = (i == (BCM_OBJDBG_COUNT - 1)) ?
  1759. dbgobj_freehead : &bcm_dbg_objs[i + 1];
  1760. bcm_dbg_objs[i].prior = (i == 0) ?
  1761. dbgobj_freetail : &bcm_dbg_objs[i - 1];
  1762. }
  1763. }
  1764. void
  1765. bcm_object_trace_deinit(void)
  1766. {
  1767. if (dbgobj_objhead || dbgobj_objtail) {
  1768. printf("%s: not all objects are released\n", __FUNCTION__);
  1769. ASSERT(0);
  1770. }
  1771. BCM_OBJDBG_LOCK_DESTROY();
  1772. }
  1773. static void
  1774. bcm_object_rm_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
  1775. struct bcm_dbgobj *dbgobj)
  1776. {
  1777. if ((dbgobj == *head) && (dbgobj == *tail)) {
  1778. *head = NULL;
  1779. *tail = NULL;
  1780. } else if (dbgobj == *head) {
  1781. *head = (*head)->next;
  1782. } else if (dbgobj == *tail) {
  1783. *tail = (*tail)->prior;
  1784. }
  1785. dbgobj->next->prior = dbgobj->prior;
  1786. dbgobj->prior->next = dbgobj->next;
  1787. }
  1788. static void
  1789. bcm_object_add_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
  1790. struct bcm_dbgobj *dbgobj, int addtotail)
  1791. {
  1792. if (!(*head) && !(*tail)) {
  1793. *head = dbgobj;
  1794. *tail = dbgobj;
  1795. dbgobj->next = dbgobj;
  1796. dbgobj->prior = dbgobj;
  1797. } else if ((*head) && (*tail)) {
  1798. (*tail)->next = dbgobj;
  1799. (*head)->prior = dbgobj;
  1800. dbgobj->next = *head;
  1801. dbgobj->prior = *tail;
  1802. if (addtotail == BCM_OBJDBG_ADDTOTAIL)
  1803. *tail = dbgobj;
  1804. else
  1805. *head = dbgobj;
  1806. } else {
  1807. ASSERT(0); /* can't be this case */
  1808. }
  1809. }
  1810. static INLINE void
  1811. bcm_object_movetoend(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
  1812. struct bcm_dbgobj *dbgobj, int movetotail)
  1813. {
  1814. if ((*head) && (*tail)) {
  1815. if (movetotail == BCM_OBJDBG_ADDTOTAIL) {
  1816. if (dbgobj != (*tail)) {
  1817. bcm_object_rm_list(head, tail, dbgobj);
  1818. bcm_object_add_list(head, tail, dbgobj, movetotail);
  1819. }
  1820. } else {
  1821. if (dbgobj != (*head)) {
  1822. bcm_object_rm_list(head, tail, dbgobj);
  1823. bcm_object_add_list(head, tail, dbgobj, movetotail);
  1824. }
  1825. }
  1826. } else {
  1827. ASSERT(0); /* can't be this case */
  1828. }
  1829. }
  1830. void
  1831. bcm_object_trace_opr(void *obj, uint32 opt, const char *caller, int line)
  1832. {
  1833. struct bcm_dbgobj *dbgobj;
  1834. unsigned long flags;
  1835. BCM_REFERENCE(flags);
  1836. BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
  1837. if (opt == BCM_OBJDBG_ADD_PKT ||
  1838. opt == BCM_OBJDBG_ADD) {
  1839. dbgobj = dbgobj_objtail;
  1840. while (dbgobj) {
  1841. if (dbgobj->obj == obj) {
  1842. printf("%s: obj %p allocated from %s(%d),"
  1843. " allocate again from %s(%d)\n",
  1844. __FUNCTION__, dbgobj->obj,
  1845. dbgobj->caller, dbgobj->line,
  1846. caller, line);
  1847. ASSERT(0);
  1848. goto EXIT;
  1849. }
  1850. dbgobj = dbgobj->prior;
  1851. if (dbgobj == dbgobj_objtail)
  1852. break;
  1853. }
  1854. #if BCM_OBJECT_MERGE_SAME_OBJ
  1855. dbgobj = dbgobj_freetail;
  1856. while (dbgobj) {
  1857. if (dbgobj->obj == obj) {
  1858. goto FREED_ENTRY_FOUND;
  1859. }
  1860. dbgobj = dbgobj->prior;
  1861. if (dbgobj == dbgobj_freetail)
  1862. break;
  1863. }
  1864. #endif /* BCM_OBJECT_MERGE_SAME_OBJ */
  1865. dbgobj = dbgobj_freehead;
  1866. #if BCM_OBJECT_MERGE_SAME_OBJ
  1867. FREED_ENTRY_FOUND:
  1868. #endif /* BCM_OBJECT_MERGE_SAME_OBJ */
  1869. if (!dbgobj) {
  1870. printf("%s: already got %d objects ?????????????????????\n",
  1871. __FUNCTION__, BCM_OBJDBG_COUNT);
  1872. ASSERT(0);
  1873. goto EXIT;
  1874. }
  1875. bcm_object_rm_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj);
  1876. dbgobj->obj = obj;
  1877. strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN);
  1878. dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0';
  1879. dbgobj->line = line;
  1880. dbgobj->flag = 0;
  1881. if (opt == BCM_OBJDBG_ADD_PKT) {
  1882. dbgobj->obj_sn = dbgobj_sn++;
  1883. dbgobj->obj_state = 0;
  1884. /* first 4 bytes is pkt sn */
  1885. if (((unsigned long)PKTTAG(obj)) & 0x3)
  1886. printf("pkt tag address not aligned by 4: %p\n", PKTTAG(obj));
  1887. *(uint32*)PKTTAG(obj) = dbgobj->obj_sn;
  1888. }
  1889. bcm_object_add_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj,
  1890. BCM_OBJDBG_ADDTOTAIL);
  1891. dbgobj_count++;
  1892. } else if (opt == BCM_OBJDBG_REMOVE) {
  1893. dbgobj = dbgobj_objtail;
  1894. while (dbgobj) {
  1895. if (dbgobj->obj == obj) {
  1896. if (dbgobj->flag) {
  1897. printf("%s: rm flagged obj %p flag 0x%08x from %s(%d)\n",
  1898. __FUNCTION__, obj, dbgobj->flag, caller, line);
  1899. }
  1900. bcm_object_rm_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj);
  1901. memset(dbgobj->caller, 0x00, BCM_OBJDBG_CALLER_LEN);
  1902. strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN);
  1903. dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0';
  1904. dbgobj->line = line;
  1905. bcm_object_add_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj,
  1906. BCM_OBJDBG_ADDTOTAIL);
  1907. dbgobj_count--;
  1908. goto EXIT;
  1909. }
  1910. dbgobj = dbgobj->prior;
  1911. if (dbgobj == dbgobj_objtail)
  1912. break;
  1913. }
  1914. dbgobj = dbgobj_freetail;
  1915. while (dbgobj && dbgobj->obj) {
  1916. if (dbgobj->obj == obj) {
  1917. printf("%s: obj %p already freed from from %s(%d),"
  1918. " try free again from %s(%d)\n",
  1919. __FUNCTION__, obj,
  1920. dbgobj->caller, dbgobj->line,
  1921. caller, line);
  1922. //ASSERT(0); /* release same obj more than one time? */
  1923. goto EXIT;
  1924. }
  1925. dbgobj = dbgobj->prior;
  1926. if (dbgobj == dbgobj_freetail)
  1927. break;
  1928. }
  1929. printf("%s: ################### release none-existing obj %p from %s(%d)\n",
  1930. __FUNCTION__, obj, caller, line);
  1931. //ASSERT(0); /* release same obj more than one time? */
  1932. }
  1933. EXIT:
  1934. BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
  1935. return;
  1936. }
  1937. void
  1938. bcm_object_trace_upd(void *obj, void *obj_new)
  1939. {
  1940. struct bcm_dbgobj *dbgobj;
  1941. unsigned long flags;
  1942. BCM_REFERENCE(flags);
  1943. BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
  1944. dbgobj = dbgobj_objtail;
  1945. while (dbgobj) {
  1946. if (dbgobj->obj == obj) {
  1947. dbgobj->obj = obj_new;
  1948. if (dbgobj != dbgobj_objtail) {
  1949. bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
  1950. dbgobj, BCM_OBJDBG_ADDTOTAIL);
  1951. }
  1952. goto EXIT;
  1953. }
  1954. dbgobj = dbgobj->prior;
  1955. if (dbgobj == dbgobj_objtail)
  1956. break;
  1957. }
  1958. EXIT:
  1959. BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
  1960. return;
  1961. }
  1962. void
  1963. bcm_object_trace_chk(void *obj, uint32 chksn, uint32 sn,
  1964. const char *caller, int line)
  1965. {
  1966. struct bcm_dbgobj *dbgobj;
  1967. unsigned long flags;
  1968. BCM_REFERENCE(flags);
  1969. BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
  1970. dbgobj = dbgobj_objtail;
  1971. while (dbgobj) {
  1972. if ((dbgobj->obj == obj) &&
  1973. ((!chksn) || (dbgobj->obj_sn == sn))) {
  1974. if (dbgobj != dbgobj_objtail) {
  1975. bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
  1976. dbgobj, BCM_OBJDBG_ADDTOTAIL);
  1977. }
  1978. goto EXIT;
  1979. }
  1980. dbgobj = dbgobj->prior;
  1981. if (dbgobj == dbgobj_objtail)
  1982. break;
  1983. }
  1984. dbgobj = dbgobj_freetail;
  1985. while (dbgobj) {
  1986. if ((dbgobj->obj == obj) &&
  1987. ((!chksn) || (dbgobj->obj_sn == sn))) {
  1988. printf("%s: (%s:%d) obj %p (sn %d state %d) was freed from %s(%d)\n",
  1989. __FUNCTION__, caller, line,
  1990. dbgobj->obj, dbgobj->obj_sn, dbgobj->obj_state,
  1991. dbgobj->caller, dbgobj->line);
  1992. goto EXIT;
  1993. }
  1994. else if (dbgobj->obj == NULL) {
  1995. break;
  1996. }
  1997. dbgobj = dbgobj->prior;
  1998. if (dbgobj == dbgobj_freetail)
  1999. break;
  2000. }
  2001. printf("%s: obj %p not found, check from %s(%d), chksn %s, sn %d\n",
  2002. __FUNCTION__, obj, caller, line, chksn ? "yes" : "no", sn);
  2003. dbgobj = dbgobj_objtail;
  2004. while (dbgobj) {
  2005. printf("%s: (%s:%d) obj %p sn %d was allocated from %s(%d)\n",
  2006. __FUNCTION__, caller, line,
  2007. dbgobj->obj, dbgobj->obj_sn, dbgobj->caller, dbgobj->line);
  2008. dbgobj = dbgobj->prior;
  2009. if (dbgobj == dbgobj_objtail)
  2010. break;
  2011. }
  2012. EXIT:
  2013. BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
  2014. return;
  2015. }
  2016. void
  2017. bcm_object_feature_set(void *obj, uint32 type, uint32 value)
  2018. {
  2019. struct bcm_dbgobj *dbgobj;
  2020. unsigned long flags;
  2021. BCM_REFERENCE(flags);
  2022. BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
  2023. dbgobj = dbgobj_objtail;
  2024. while (dbgobj) {
  2025. if (dbgobj->obj == obj) {
  2026. if (type == BCM_OBJECT_FEATURE_FLAG) {
  2027. if (value & BCM_OBJECT_FEATURE_CLEAR)
  2028. dbgobj->flag &= ~(value);
  2029. else
  2030. dbgobj->flag |= (value);
  2031. } else if (type == BCM_OBJECT_FEATURE_PKT_STATE) {
  2032. dbgobj->obj_state = value;
  2033. }
  2034. if (dbgobj != dbgobj_objtail) {
  2035. bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
  2036. dbgobj, BCM_OBJDBG_ADDTOTAIL);
  2037. }
  2038. goto EXIT;
  2039. }
  2040. dbgobj = dbgobj->prior;
  2041. if (dbgobj == dbgobj_objtail)
  2042. break;
  2043. }
  2044. printf("%s: obj %p not found in active list\n", __FUNCTION__, obj);
  2045. ASSERT(0);
  2046. EXIT:
  2047. BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
  2048. return;
  2049. }
  2050. int
  2051. bcm_object_feature_get(void *obj, uint32 type, uint32 value)
  2052. {
  2053. int rtn = 0;
  2054. struct bcm_dbgobj *dbgobj;
  2055. unsigned long flags;
  2056. BCM_REFERENCE(flags);
  2057. BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
  2058. dbgobj = dbgobj_objtail;
  2059. while (dbgobj) {
  2060. if (dbgobj->obj == obj) {
  2061. if (type == BCM_OBJECT_FEATURE_FLAG) {
  2062. rtn = (dbgobj->flag & value) & (~BCM_OBJECT_FEATURE_CLEAR);
  2063. }
  2064. if (dbgobj != dbgobj_objtail) {
  2065. bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
  2066. dbgobj, BCM_OBJDBG_ADDTOTAIL);
  2067. }
  2068. goto EXIT;
  2069. }
  2070. dbgobj = dbgobj->prior;
  2071. if (dbgobj == dbgobj_objtail)
  2072. break;
  2073. }
  2074. printf("%s: obj %p not found in active list\n", __FUNCTION__, obj);
  2075. ASSERT(0);
  2076. EXIT:
  2077. BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
  2078. return rtn;
  2079. }
  2080. #endif /* BCM_OBJECT_TRACE */
  2081. uint8 *
  2082. bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst)
  2083. {
  2084. uint8 *new_dst = dst;
  2085. bcm_tlv_t *dst_tlv = (bcm_tlv_t *)dst;
  2086. /* dst buffer should always be valid */
  2087. ASSERT(dst);
  2088. /* data len must be within valid range */
  2089. ASSERT((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE));
  2090. /* source data buffer pointer should be valid, unless datalen is 0
  2091. * meaning no data with this TLV
  2092. */
  2093. ASSERT((data != NULL) || (datalen == 0));
  2094. /* only do work if the inputs are valid
  2095. * - must have a dst to write to AND
  2096. * - datalen must be within range AND
  2097. * - the source data pointer must be non-NULL if datalen is non-zero
  2098. * (this last condition detects datalen > 0 with a NULL data pointer)
  2099. */
  2100. if ((dst != NULL) &&
  2101. ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) &&
  2102. ((data != NULL) || (datalen == 0))) {
  2103. /* write type, len fields */
  2104. dst_tlv->id = (uint8)type;
  2105. dst_tlv->len = (uint8)datalen;
  2106. /* if data is present, copy to the output buffer and update
  2107. * pointer to output buffer
  2108. */
  2109. if (datalen > 0) {
  2110. memcpy(dst_tlv->data, data, (size_t)datalen);
  2111. }
  2112. /* update the output destination poitner to point past
  2113. * the TLV written
  2114. */
  2115. new_dst = dst + BCM_TLV_HDR_SIZE + datalen;
  2116. }
  2117. return (new_dst);
  2118. }
  2119. uint8 *
  2120. bcm_write_tlv_ext(uint8 type, uint8 ext, const void *data, uint8 datalen, uint8 *dst)
  2121. {
  2122. uint8 *new_dst = dst;
  2123. bcm_tlv_ext_t *dst_tlv = (bcm_tlv_ext_t *)dst;
  2124. /* dst buffer should always be valid */
  2125. ASSERT(dst);
  2126. /* data len must be within valid range */
  2127. ASSERT(datalen <= BCM_TLV_EXT_MAX_DATA_SIZE);
  2128. /* source data buffer pointer should be valid, unless datalen is 0
  2129. * meaning no data with this TLV
  2130. */
  2131. ASSERT((data != NULL) || (datalen == 0));
  2132. /* only do work if the inputs are valid
  2133. * - must have a dst to write to AND
  2134. * - datalen must be within range AND
  2135. * - the source data pointer must be non-NULL if datalen is non-zero
  2136. * (this last condition detects datalen > 0 with a NULL data pointer)
  2137. */
  2138. if ((dst != NULL) &&
  2139. (datalen <= BCM_TLV_EXT_MAX_DATA_SIZE) &&
  2140. ((data != NULL) || (datalen == 0))) {
  2141. /* write type, len fields */
  2142. dst_tlv->id = (uint8)type;
  2143. dst_tlv->ext = ext;
  2144. dst_tlv->len = 1 + (uint8)datalen;
  2145. /* if data is present, copy to the output buffer and update
  2146. * pointer to output buffer
  2147. */
  2148. if (datalen > 0) {
  2149. memcpy(dst_tlv->data, data, datalen);
  2150. }
  2151. /* update the output destination poitner to point past
  2152. * the TLV written
  2153. */
  2154. new_dst = dst + BCM_TLV_EXT_HDR_SIZE + datalen;
  2155. }
  2156. return (new_dst);
  2157. }
  2158. uint8 *
  2159. bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst, int dst_maxlen)
  2160. {
  2161. uint8 *new_dst = dst;
  2162. if ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) {
  2163. /* if len + tlv hdr len is more than destlen, don't do anything
  2164. * just return the buffer untouched
  2165. */
  2166. if ((int)(datalen + (int)BCM_TLV_HDR_SIZE) <= dst_maxlen) {
  2167. new_dst = bcm_write_tlv(type, data, datalen, dst);
  2168. }
  2169. }
  2170. return (new_dst);
  2171. }
  2172. uint8 *
  2173. bcm_copy_tlv(const void *src, uint8 *dst)
  2174. {
  2175. uint8 *new_dst = dst;
  2176. const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
  2177. uint totlen;
  2178. ASSERT(dst && src);
  2179. if (dst && src) {
  2180. totlen = BCM_TLV_HDR_SIZE + src_tlv->len;
  2181. memcpy(dst, src_tlv, totlen);
  2182. new_dst = dst + totlen;
  2183. }
  2184. return (new_dst);
  2185. }
  2186. uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen)
  2187. {
  2188. uint8 *new_dst = dst;
  2189. const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
  2190. ASSERT(src);
  2191. if (src) {
  2192. if (bcm_valid_tlv(src_tlv, dst_maxlen)) {
  2193. new_dst = bcm_copy_tlv(src, dst);
  2194. }
  2195. }
  2196. return (new_dst);
  2197. }
  2198. #if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
  2199. /*******************************************************************************
  2200. * crc8
  2201. *
  2202. * Computes a crc8 over the input data using the polynomial:
  2203. *
  2204. * x^8 + x^7 +x^6 + x^4 + x^2 + 1
  2205. *
  2206. * The caller provides the initial value (either CRC8_INIT_VALUE
  2207. * or the previous returned value) to allow for processing of
  2208. * discontiguous blocks of data. When generating the CRC the
  2209. * caller is responsible for complementing the final return value
  2210. * and inserting it into the byte stream. When checking, a final
  2211. * return value of CRC8_GOOD_VALUE indicates a valid CRC.
  2212. *
  2213. * Reference: Dallas Semiconductor Application Note 27
  2214. * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
  2215. * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
  2216. * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
  2217. *
  2218. * ****************************************************************************
  2219. */
  2220. static const uint8 crc8_table[256] = {
  2221. 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
  2222. 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
  2223. 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
  2224. 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
  2225. 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
  2226. 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
  2227. 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
  2228. 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
  2229. 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
  2230. 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
  2231. 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
  2232. 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
  2233. 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
  2234. 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
  2235. 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
  2236. 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
  2237. 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
  2238. 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
  2239. 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
  2240. 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
  2241. 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
  2242. 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
  2243. 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
  2244. 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
  2245. 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
  2246. 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
  2247. 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
  2248. 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
  2249. 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
  2250. 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
  2251. 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
  2252. 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
  2253. };
  2254. #define CRC_INNER_LOOP(n, c, x) \
  2255. (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
  2256. uint8
  2257. hndcrc8(
  2258. const uint8 *pdata, /* pointer to array of data to process */
  2259. uint nbytes, /* number of input data bytes to process */
  2260. uint8 crc /* either CRC8_INIT_VALUE or previous return value */
  2261. )
  2262. {
  2263. /* hard code the crc loop instead of using CRC_INNER_LOOP macro
  2264. * to avoid the undefined and unnecessary (uint8 >> 8) operation.
  2265. */
  2266. while (nbytes-- > 0)
  2267. crc = crc8_table[(crc ^ *pdata++) & 0xff];
  2268. return crc;
  2269. }
  2270. /*******************************************************************************
  2271. * crc16
  2272. *
  2273. * Computes a crc16 over the input data using the polynomial:
  2274. *
  2275. * x^16 + x^12 +x^5 + 1
  2276. *
  2277. * The caller provides the initial value (either CRC16_INIT_VALUE
  2278. * or the previous returned value) to allow for processing of
  2279. * discontiguous blocks of data. When generating the CRC the
  2280. * caller is responsible for complementing the final return value
  2281. * and inserting it into the byte stream. When checking, a final
  2282. * return value of CRC16_GOOD_VALUE indicates a valid CRC.
  2283. *
  2284. * Reference: Dallas Semiconductor Application Note 27
  2285. * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
  2286. * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
  2287. * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
  2288. *
  2289. * ****************************************************************************
  2290. */
  2291. static const uint16 crc16_table[256] = {
  2292. 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
  2293. 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
  2294. 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
  2295. 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
  2296. 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
  2297. 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
  2298. 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
  2299. 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
  2300. 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
  2301. 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
  2302. 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
  2303. 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
  2304. 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
  2305. 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
  2306. 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
  2307. 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
  2308. 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
  2309. 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
  2310. 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
  2311. 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
  2312. 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
  2313. 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
  2314. 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
  2315. 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
  2316. 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
  2317. 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
  2318. 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
  2319. 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
  2320. 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
  2321. 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
  2322. 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
  2323. 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
  2324. };
  2325. uint16
  2326. hndcrc16(
  2327. const uint8 *pdata, /* pointer to array of data to process */
  2328. uint nbytes, /* number of input data bytes to process */
  2329. uint16 crc /* either CRC16_INIT_VALUE or previous return value */
  2330. )
  2331. {
  2332. while (nbytes-- > 0)
  2333. CRC_INNER_LOOP(16, crc, *pdata++);
  2334. return crc;
  2335. }
  2336. static const uint32 crc32_table[256] = {
  2337. 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
  2338. 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
  2339. 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
  2340. 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
  2341. 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
  2342. 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
  2343. 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
  2344. 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
  2345. 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
  2346. 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
  2347. 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
  2348. 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
  2349. 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
  2350. 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
  2351. 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
  2352. 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
  2353. 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
  2354. 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
  2355. 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
  2356. 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
  2357. 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
  2358. 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
  2359. 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
  2360. 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
  2361. 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
  2362. 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
  2363. 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
  2364. 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
  2365. 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
  2366. 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
  2367. 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
  2368. 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
  2369. 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
  2370. 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
  2371. 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
  2372. 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
  2373. 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
  2374. 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
  2375. 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
  2376. 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
  2377. 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
  2378. 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
  2379. 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
  2380. 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
  2381. 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
  2382. 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
  2383. 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
  2384. 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
  2385. 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
  2386. 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
  2387. 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
  2388. 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
  2389. 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
  2390. 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
  2391. 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
  2392. 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
  2393. 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
  2394. 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
  2395. 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
  2396. 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
  2397. 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
  2398. 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
  2399. 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
  2400. 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
  2401. };
  2402. /*
  2403. * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if
  2404. * accumulating over multiple pieces.
  2405. */
  2406. uint32
  2407. hndcrc32(const uint8 *pdata, uint nbytes, uint32 crc)
  2408. {
  2409. const uint8 *pend;
  2410. pend = pdata + nbytes;
  2411. while (pdata < pend)
  2412. CRC_INNER_LOOP(32, crc, *pdata++);
  2413. return crc;
  2414. }
  2415. #ifdef notdef
  2416. #define CLEN 1499 /* CRC Length */
  2417. #define CBUFSIZ (CLEN+4)
  2418. #define CNBUFS 5 /* # of bufs */
  2419. void
  2420. testcrc32(void)
  2421. {
  2422. uint j, k, l;
  2423. uint8 *buf;
  2424. uint len[CNBUFS];
  2425. uint32 crcr;
  2426. uint32 crc32tv[CNBUFS] =
  2427. {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110};
  2428. ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL);
  2429. /* step through all possible alignments */
  2430. for (l = 0; l <= 4; l++) {
  2431. for (j = 0; j < CNBUFS; j++) {
  2432. len[j] = CLEN;
  2433. for (k = 0; k < len[j]; k++)
  2434. *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff;
  2435. }
  2436. for (j = 0; j < CNBUFS; j++) {
  2437. crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE);
  2438. ASSERT(crcr == crc32tv[j]);
  2439. }
  2440. }
  2441. MFREE(buf, CBUFSIZ*CNBUFS);
  2442. return;
  2443. }
  2444. #endif /* notdef */
  2445. /*
  2446. * Advance from the current 1-byte tag/1-byte length/variable-length value
  2447. * triple, to the next, returning a pointer to the next.
  2448. * If the current or next TLV is invalid (does not fit in given buffer length),
  2449. * NULL is returned.
  2450. * *buflen is not modified if the TLV elt parameter is invalid, or is decremented
  2451. * by the TLV parameter's length if it is valid.
  2452. */
  2453. bcm_tlv_t *
  2454. bcm_next_tlv(const bcm_tlv_t *elt, uint *buflen)
  2455. {
  2456. uint len;
  2457. /* validate current elt */
  2458. if (!bcm_valid_tlv(elt, *buflen)) {
  2459. return NULL;
  2460. }
  2461. /* advance to next elt */
  2462. len = elt->len;
  2463. elt = (const bcm_tlv_t*)(elt->data + len);
  2464. *buflen -= (TLV_HDR_LEN + len);
  2465. /* validate next elt */
  2466. if (!bcm_valid_tlv(elt, *buflen)) {
  2467. return NULL;
  2468. }
  2469. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  2470. return (bcm_tlv_t *)(elt);
  2471. GCC_DIAGNOSTIC_POP();
  2472. }
  2473. /**
  2474. * Advance a const tlv buffer pointer and length up to the given tlv element pointer
  2475. * 'elt'. The function checks that elt is a valid tlv; the elt pointer and data
  2476. * are all in the range of the buffer/length.
  2477. *
  2478. * @param elt pointer to a valid bcm_tlv_t in the buffer
  2479. * @param buffer pointer to a tlv buffer
  2480. * @param buflen length of the buffer in bytes
  2481. *
  2482. * On return, if elt is not a tlv in the buffer bounds, the *buffer parameter
  2483. * will be set to NULL and *buflen parameter will be set to zero. Otherwise,
  2484. * *buffer will point to elt, and *buflen will have been adjusted by the the
  2485. * difference between *buffer and elt.
  2486. */
  2487. void
  2488. bcm_tlv_buffer_advance_to(const bcm_tlv_t *elt, const uint8 **buffer, uint *buflen)
  2489. {
  2490. uint new_buflen;
  2491. const uint8 *new_buffer;
  2492. new_buffer = (const uint8*)elt;
  2493. /* make sure the input buffer pointer is non-null, that (buffer + buflen) does not wrap,
  2494. * and that the elt pointer is in the range of [buffer, buffer + buflen]
  2495. */
  2496. if ((*buffer != NULL) &&
  2497. ((uintptr)*buffer < ((uintptr)*buffer + *buflen)) &&
  2498. (new_buffer >= *buffer) &&
  2499. (new_buffer < (*buffer + *buflen))) {
  2500. /* delta between buffer and new_buffer is <= *buflen, so truncating cast to uint
  2501. * from ptrdiff is ok
  2502. */
  2503. uint delta = (uint)(new_buffer - *buffer);
  2504. /* New buffer length is old len minus the delta from the buffer start to elt.
  2505. * The check just above guarantees that the subtractions does not underflow.
  2506. */
  2507. new_buflen = *buflen - delta;
  2508. /* validate current elt */
  2509. if (bcm_valid_tlv(elt, new_buflen)) {
  2510. /* All good, so update the input/output parameters */
  2511. *buffer = new_buffer;
  2512. *buflen = new_buflen;
  2513. return;
  2514. }
  2515. }
  2516. /* something did not check out, clear out the buffer info */
  2517. *buffer = NULL;
  2518. *buflen = 0;
  2519. return;
  2520. }
  2521. /**
  2522. * Advance a const tlv buffer pointer and length past the given tlv element pointer
  2523. * 'elt'. The function checks that elt is a valid tlv; the elt pointer and data
  2524. * are all in the range of the buffer/length. The function also checks that the
  2525. * remaining buffer starts with a valid tlv.
  2526. *
  2527. * @param elt pointer to a valid bcm_tlv_t in the buffer
  2528. * @param buffer pointer to a tlv buffer
  2529. * @param buflen length of the buffer in bytes
  2530. *
  2531. * On return, if elt is not a tlv in the buffer bounds, or the remaining buffer
  2532. * following the elt does not begin with a tlv in the buffer bounds, the *buffer
  2533. * parameter will be set to NULL and *buflen parameter will be set to zero.
  2534. * Otherwise, *buffer will point to the first byte past elt, and *buflen will
  2535. * have the remaining buffer length.
  2536. */
  2537. void
  2538. bcm_tlv_buffer_advance_past(const bcm_tlv_t *elt, const uint8 **buffer, uint *buflen)
  2539. {
  2540. /* Start by advancing the buffer up to the given elt */
  2541. bcm_tlv_buffer_advance_to(elt, buffer, buflen);
  2542. /* if that did not work, bail out */
  2543. if (*buflen == 0) {
  2544. return;
  2545. }
  2546. #if defined(__COVERITY__)
  2547. /* The elt has been verified by bcm_tlv_buffer_advance_to() to be a valid element,
  2548. * so its elt->len is in the bounds of the buffer. The following check prevents
  2549. * Coverity from flagging the (elt->data + elt->len) statement below as using a
  2550. * tainted elt->len to index into array 'elt->data'.
  2551. */
  2552. if (elt->len > *buflen) {
  2553. return;
  2554. }
  2555. #endif /* __COVERITY__ */
  2556. /* We know we are advanced up to a good tlv.
  2557. * Now just advance to the following tlv.
  2558. */
  2559. elt = (const bcm_tlv_t*)(elt->data + elt->len);
  2560. bcm_tlv_buffer_advance_to(elt, buffer, buflen);
  2561. return;
  2562. }
  2563. /*
  2564. * Traverse a string of 1-byte tag/1-byte length/variable-length value
  2565. * triples, returning a pointer to the substring whose first element
  2566. * matches tag
  2567. */
  2568. bcm_tlv_t *
  2569. bcm_parse_tlvs(const void *buf, uint buflen, uint key)
  2570. {
  2571. const bcm_tlv_t *elt;
  2572. int totlen;
  2573. if ((elt = (const bcm_tlv_t*)buf) == NULL) {
  2574. return NULL;
  2575. }
  2576. totlen = (int)buflen;
  2577. /* find tagged parameter */
  2578. while (totlen >= TLV_HDR_LEN) {
  2579. uint len = elt->len;
  2580. /* validate remaining totlen */
  2581. if ((elt->id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
  2582. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  2583. return (bcm_tlv_t *)(elt);
  2584. GCC_DIAGNOSTIC_POP();
  2585. }
  2586. elt = (const bcm_tlv_t*)((const uint8*)elt + (len + TLV_HDR_LEN));
  2587. totlen -= (len + TLV_HDR_LEN);
  2588. }
  2589. return NULL;
  2590. }
  2591. bcm_tlv_t *
  2592. bcm_parse_tlvs_dot11(const void *buf, int buflen, uint key, bool id_ext)
  2593. {
  2594. bcm_tlv_t *elt;
  2595. int totlen;
  2596. /*
  2597. ideally, we don't want to do that, but returning a const pointer
  2598. from these parse function spreads casting everywhere in the code
  2599. */
  2600. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  2601. elt = (bcm_tlv_t*)buf;
  2602. GCC_DIAGNOSTIC_POP();
  2603. totlen = buflen;
  2604. /* find tagged parameter */
  2605. while (totlen >= TLV_HDR_LEN) {
  2606. int len = elt->len;
  2607. do {
  2608. /* validate remaining totlen */
  2609. if (totlen < (int)(len + TLV_HDR_LEN))
  2610. break;
  2611. if (id_ext) {
  2612. if (!DOT11_MNG_IE_ID_EXT_MATCH(elt, key))
  2613. break;
  2614. } else if (elt->id != key) {
  2615. break;
  2616. }
  2617. return (bcm_tlv_t *)(elt); /* a match */
  2618. } while (0);
  2619. elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
  2620. totlen -= (len + TLV_HDR_LEN);
  2621. }
  2622. return NULL;
  2623. }
  2624. /*
  2625. * Traverse a string of 1-byte tag/1-byte length/variable-length value
  2626. * triples, returning a pointer to the substring whose first element
  2627. * matches tag
  2628. * return NULL if not found or length field < min_varlen
  2629. */
  2630. bcm_tlv_t *
  2631. bcm_parse_tlvs_min_bodylen(const void *buf, int buflen, uint key, int min_bodylen)
  2632. {
  2633. bcm_tlv_t * ret;
  2634. ret = bcm_parse_tlvs(buf, (uint)buflen, key);
  2635. if (ret == NULL || ret->len < min_bodylen) {
  2636. return NULL;
  2637. }
  2638. return ret;
  2639. }
  2640. /*
  2641. * Traverse a string of 1-byte tag/1-byte length/variable-length value
  2642. * triples, returning a pointer to the substring whose first element
  2643. * matches tag. Stop parsing when we see an element whose ID is greater
  2644. * than the target key.
  2645. */
  2646. const bcm_tlv_t *
  2647. bcm_parse_ordered_tlvs(const void *buf, int buflen, uint key)
  2648. {
  2649. const bcm_tlv_t *elt;
  2650. int totlen;
  2651. elt = (const bcm_tlv_t*)buf;
  2652. totlen = buflen;
  2653. /* find tagged parameter */
  2654. while (totlen >= TLV_HDR_LEN) {
  2655. uint id = elt->id;
  2656. int len = elt->len;
  2657. /* Punt if we start seeing IDs > than target key */
  2658. if (id > key) {
  2659. return (NULL);
  2660. }
  2661. /* validate remaining totlen */
  2662. if ((id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
  2663. return (elt);
  2664. }
  2665. elt = (const bcm_tlv_t*)((const uint8*)elt + (len + TLV_HDR_LEN));
  2666. totlen -= (len + TLV_HDR_LEN);
  2667. }
  2668. return NULL;
  2669. }
  2670. #endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
  2671. #if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \
  2672. defined(DHD_DEBUG)
  2673. int
  2674. bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len)
  2675. {
  2676. int i, slen = 0;
  2677. uint32 bit, mask;
  2678. const char *name;
  2679. mask = bd->mask;
  2680. if (len < 2 || !buf)
  2681. return 0;
  2682. buf[0] = '\0';
  2683. for (i = 0; (name = bd->bitfield[i].name) != NULL; i++) {
  2684. bit = bd->bitfield[i].bit;
  2685. if ((flags & mask) == bit) {
  2686. if (len > (int)strlen(name)) {
  2687. slen = (int)strlen(name);
  2688. strncpy(buf, name, (size_t)slen+1);
  2689. }
  2690. break;
  2691. }
  2692. }
  2693. return slen;
  2694. }
  2695. int
  2696. bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len)
  2697. {
  2698. int i;
  2699. char* p = buf;
  2700. char hexstr[16];
  2701. int slen = 0, nlen = 0;
  2702. uint32 bit;
  2703. const char* name;
  2704. if (len < 2 || !buf)
  2705. return 0;
  2706. buf[0] = '\0';
  2707. for (i = 0; flags != 0; i++) {
  2708. bit = bd[i].bit;
  2709. name = bd[i].name;
  2710. if (bit == 0 && flags != 0) {
  2711. /* print any unnamed bits */
  2712. snprintf(hexstr, 16, "0x%X", flags);
  2713. name = hexstr;
  2714. flags = 0; /* exit loop */
  2715. } else if ((flags & bit) == 0)
  2716. continue;
  2717. flags &= ~bit;
  2718. nlen = (int)strlen(name);
  2719. slen += nlen;
  2720. /* count btwn flag space */
  2721. if (flags != 0)
  2722. slen += 1;
  2723. /* need NULL char as well */
  2724. if (len <= slen)
  2725. break;
  2726. /* copy NULL char but don't count it */
  2727. strncpy(p, name, (size_t)nlen + 1);
  2728. p += nlen;
  2729. /* copy btwn flag space and NULL char */
  2730. if (flags != 0)
  2731. p += snprintf(p, 2, " ");
  2732. }
  2733. /* indicate the str was too short */
  2734. if (flags != 0) {
  2735. p += snprintf(p, 2, ">");
  2736. }
  2737. return (int)(p - buf);
  2738. }
  2739. /* print out whcih bits in octet array 'addr' are set. bcm_bit_desc_t:bit is a bit offset. */
  2740. int
  2741. bcm_format_octets(const bcm_bit_desc_t *bd, uint bdsz,
  2742. const uint8 *addr, uint size, char *buf, int len)
  2743. {
  2744. uint i;
  2745. char *p = buf;
  2746. int slen = 0, nlen = 0;
  2747. uint32 bit;
  2748. const char* name;
  2749. bool more = FALSE;
  2750. BCM_REFERENCE(size);
  2751. if (len < 2 || !buf)
  2752. return 0;
  2753. buf[0] = '\0';
  2754. for (i = 0; i < bdsz; i++) {
  2755. bit = bd[i].bit;
  2756. name = bd[i].name;
  2757. CLANG_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  2758. if (isset(addr, bit)) {
  2759. CLANG_DIAGNOSTIC_POP();
  2760. nlen = (int)strlen(name);
  2761. slen += nlen;
  2762. /* need SPACE - for simplicity */
  2763. slen += 1;
  2764. /* need NULL as well */
  2765. if (len < slen + 1) {
  2766. more = TRUE;
  2767. break;
  2768. }
  2769. memcpy(p, name, (size_t)nlen);
  2770. p += nlen;
  2771. p[0] = ' ';
  2772. p += 1;
  2773. p[0] = '\0';
  2774. }
  2775. }
  2776. if (more) {
  2777. p[0] = '>';
  2778. p += 1;
  2779. p[0] = '\0';
  2780. }
  2781. return (int)(p - buf);
  2782. }
  2783. #endif // endif
  2784. /* print bytes formatted as hex to a string. return the resulting string length */
  2785. int
  2786. bcm_format_hex(char *str, const void *bytes, int len)
  2787. {
  2788. int i;
  2789. char *p = str;
  2790. const uint8 *src = (const uint8*)bytes;
  2791. for (i = 0; i < len; i++) {
  2792. p += snprintf(p, 3, "%02X", *src);
  2793. src++;
  2794. }
  2795. return (int)(p - str);
  2796. }
  2797. /* pretty hex print a contiguous buffer */
  2798. void
  2799. prhex(const char *msg, const uchar *buf, uint nbytes)
  2800. {
  2801. char line[128], *p;
  2802. int len = sizeof(line);
  2803. int nchar;
  2804. uint i;
  2805. if (msg && (msg[0] != '\0'))
  2806. printf("%s:\n", msg);
  2807. p = line;
  2808. for (i = 0; i < nbytes; i++) {
  2809. if (i % 16 == 0) {
  2810. nchar = snprintf(p, (size_t)len, " %04x: ", i); /* line prefix */
  2811. p += nchar;
  2812. len -= nchar;
  2813. }
  2814. if (len > 0) {
  2815. nchar = snprintf(p, (size_t)len, "%02x ", buf[i]);
  2816. p += nchar;
  2817. len -= nchar;
  2818. }
  2819. if (i % 16 == 15) {
  2820. printf("%s\n", line); /* flush line */
  2821. p = line;
  2822. len = sizeof(line);
  2823. }
  2824. }
  2825. /* flush last partial line */
  2826. if (p != line)
  2827. printf("%s\n", line);
  2828. }
  2829. static const char *crypto_algo_names[] = {
  2830. "NONE",
  2831. "WEP1",
  2832. "TKIP",
  2833. "WEP128",
  2834. "AES_CCM",
  2835. "AES_OCB_MSDU",
  2836. "AES_OCB_MPDU",
  2837. #ifdef BCMCCX
  2838. "CKIP",
  2839. "CKIP_MMH",
  2840. "WEP_MMH",
  2841. "NALG",
  2842. #else
  2843. "NALG",
  2844. "UNDEF",
  2845. "UNDEF",
  2846. "UNDEF",
  2847. #endif /* BCMCCX */
  2848. #ifdef BCMWAPI_WAI
  2849. "WAPI",
  2850. #else
  2851. "UNDEF",
  2852. #endif // endif
  2853. "PMK",
  2854. "BIP",
  2855. "AES_GCM",
  2856. "AES_CCM256",
  2857. "AES_GCM256",
  2858. "BIP_CMAC256",
  2859. "BIP_GMAC",
  2860. "BIP_GMAC256",
  2861. "UNDEF"
  2862. };
  2863. const char *
  2864. bcm_crypto_algo_name(uint algo)
  2865. {
  2866. return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR";
  2867. }
  2868. char *
  2869. bcm_chipname(uint chipid, char *buf, uint len)
  2870. {
  2871. const char *fmt;
  2872. fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
  2873. /*
  2874. * The following call to snprintf generates a compiler warning
  2875. * due to -Wformat-nonliteral. However, the format string is coming
  2876. * from internal callers rather than external data input, and is a
  2877. * useful debugging tool serving a variety of diagnostics. Rather
  2878. * than expand code size by replicating multiple functions with different
  2879. * argument lists, or disabling the warning globally, let's consider
  2880. * if we can just disable the warning for this one instance.
  2881. */
  2882. CLANG_DIAGNOSTIC_PUSH_SUPPRESS_FORMAT()
  2883. snprintf(buf, len, fmt, chipid);
  2884. CLANG_DIAGNOSTIC_POP()
  2885. return buf;
  2886. }
  2887. /* Produce a human-readable string for boardrev */
  2888. char *
  2889. bcm_brev_str(uint32 brev, char *buf)
  2890. {
  2891. if (brev < 0x100)
  2892. snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf);
  2893. else
  2894. snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff);
  2895. return (buf);
  2896. }
  2897. #define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */
  2898. /* dump large strings to console */
  2899. void
  2900. printbig(char *buf)
  2901. {
  2902. uint len, max_len;
  2903. char c;
  2904. len = (uint)strlen(buf);
  2905. max_len = BUFSIZE_TODUMP_ATONCE;
  2906. while (len > max_len) {
  2907. c = buf[max_len];
  2908. buf[max_len] = '\0';
  2909. printf("%s", buf);
  2910. buf[max_len] = c;
  2911. buf += max_len;
  2912. len -= max_len;
  2913. }
  2914. /* print the remaining string */
  2915. printf("%s\n", buf);
  2916. return;
  2917. }
  2918. /* routine to dump fields in a fileddesc structure */
  2919. uint
  2920. bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array,
  2921. char *buf, uint32 bufsize)
  2922. {
  2923. uint filled_len;
  2924. int len;
  2925. struct fielddesc *cur_ptr;
  2926. filled_len = 0;
  2927. cur_ptr = fielddesc_array;
  2928. while (bufsize > 1) {
  2929. if (cur_ptr->nameandfmt == NULL)
  2930. break;
  2931. /*
  2932. * The following call to snprintf generates a compiler warning
  2933. * due to -Wformat-nonliteral. However, the format string is coming
  2934. * from internal callers rather than external data input, and is a
  2935. * useful debugging tool serving a variety of diagnostics. Rather
  2936. * than expand code size by replicating multiple functions with different
  2937. * argument lists, or disabling the warning globally, let's consider
  2938. * if we can just disable the warning for this one instance.
  2939. */
  2940. CLANG_DIAGNOSTIC_PUSH_SUPPRESS_FORMAT()
  2941. len = snprintf(buf, bufsize, cur_ptr->nameandfmt,
  2942. read_rtn(arg0, arg1, cur_ptr->offset));
  2943. CLANG_DIAGNOSTIC_POP()
  2944. /* check for snprintf overflow or error */
  2945. if (len < 0 || (uint32)len >= bufsize)
  2946. len = (int)(bufsize - 1);
  2947. buf += len;
  2948. bufsize -= (uint32)len;
  2949. filled_len += (uint32)len;
  2950. cur_ptr++;
  2951. }
  2952. return filled_len;
  2953. }
  2954. uint
  2955. bcm_mkiovar(const char *name, const char *data, uint datalen, char *buf, uint buflen)
  2956. {
  2957. uint len;
  2958. len = (uint)strlen(name) + 1;
  2959. if ((len + datalen) > buflen)
  2960. return 0;
  2961. strncpy(buf, name, buflen);
  2962. /* append data onto the end of the name string */
  2963. if (data && datalen != 0) {
  2964. memcpy(&buf[len], data, datalen);
  2965. len += datalen;
  2966. }
  2967. return len;
  2968. }
  2969. /* Quarter dBm units to mW
  2970. * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
  2971. * Table is offset so the last entry is largest mW value that fits in
  2972. * a uint16.
  2973. */
  2974. #define QDBM_OFFSET 153 /* Offset for first entry */
  2975. #define QDBM_TABLE_LEN 40 /* Table size */
  2976. /* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
  2977. * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
  2978. */
  2979. #define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
  2980. /* Largest mW value that will round down to the last table entry,
  2981. * QDBM_OFFSET + QDBM_TABLE_LEN-1.
  2982. * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
  2983. */
  2984. #define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
  2985. static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
  2986. /* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
  2987. /* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
  2988. /* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
  2989. /* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
  2990. /* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
  2991. /* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
  2992. };
  2993. uint16
  2994. bcm_qdbm_to_mw(uint8 qdbm)
  2995. {
  2996. uint factor = 1;
  2997. int idx = qdbm - QDBM_OFFSET;
  2998. if (idx >= QDBM_TABLE_LEN) {
  2999. /* clamp to max uint16 mW value */
  3000. return 0xFFFF;
  3001. }
  3002. /* scale the qdBm index up to the range of the table 0-40
  3003. * where an offset of 40 qdBm equals a factor of 10 mW.
  3004. */
  3005. while (idx < 0) {
  3006. idx += 40;
  3007. factor *= 10;
  3008. }
  3009. /* return the mW value scaled down to the correct factor of 10,
  3010. * adding in factor/2 to get proper rounding.
  3011. */
  3012. return (uint16)((nqdBm_to_mW_map[idx] + factor/2) / factor);
  3013. }
  3014. uint8
  3015. bcm_mw_to_qdbm(uint16 mw)
  3016. {
  3017. uint8 qdbm;
  3018. int offset;
  3019. uint mw_uint = mw;
  3020. uint boundary;
  3021. /* handle boundary case */
  3022. if (mw_uint <= 1)
  3023. return 0;
  3024. offset = QDBM_OFFSET;
  3025. /* move mw into the range of the table */
  3026. while (mw_uint < QDBM_TABLE_LOW_BOUND) {
  3027. mw_uint *= 10;
  3028. offset -= 40;
  3029. }
  3030. for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) {
  3031. boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] -
  3032. nqdBm_to_mW_map[qdbm])/2;
  3033. if (mw_uint < boundary) break;
  3034. }
  3035. qdbm += (uint8)offset;
  3036. return (qdbm);
  3037. }
  3038. uint
  3039. bcm_bitcount(uint8 *bitmap, uint length)
  3040. {
  3041. uint bitcount = 0, i;
  3042. uint8 tmp;
  3043. for (i = 0; i < length; i++) {
  3044. tmp = bitmap[i];
  3045. while (tmp) {
  3046. bitcount++;
  3047. tmp &= (tmp - 1);
  3048. }
  3049. }
  3050. return bitcount;
  3051. }
  3052. /*
  3053. * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL.
  3054. * also accepts nvram files which are already in the format of <var1>=<value>\0\<var2>=<value2>\0
  3055. * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs.
  3056. * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs.
  3057. */
  3058. unsigned int
  3059. process_nvram_vars(char *varbuf, unsigned int len)
  3060. {
  3061. char *dp;
  3062. bool findNewline;
  3063. int column;
  3064. unsigned int buf_len, n;
  3065. unsigned int pad = 0;
  3066. dp = varbuf;
  3067. findNewline = FALSE;
  3068. column = 0;
  3069. for (n = 0; n < len; n++) {
  3070. if (varbuf[n] == '\r')
  3071. continue;
  3072. if (findNewline && varbuf[n] != '\n')
  3073. continue;
  3074. findNewline = FALSE;
  3075. if (varbuf[n] == '#') {
  3076. findNewline = TRUE;
  3077. continue;
  3078. }
  3079. if (varbuf[n] == '\n') {
  3080. if (column == 0)
  3081. continue;
  3082. *dp++ = 0;
  3083. column = 0;
  3084. continue;
  3085. }
  3086. *dp++ = varbuf[n];
  3087. column++;
  3088. }
  3089. buf_len = (unsigned int)(dp - varbuf);
  3090. if (buf_len % 4) {
  3091. pad = 4 - buf_len % 4;
  3092. if (pad && (buf_len + pad <= len)) {
  3093. buf_len += pad;
  3094. }
  3095. }
  3096. while (dp < varbuf + n)
  3097. *dp++ = 0;
  3098. return buf_len;
  3099. }
  3100. #ifndef setbit /* As in the header file */
  3101. #ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
  3102. /* Set bit in byte array. */
  3103. void
  3104. setbit(void *array, uint bit)
  3105. {
  3106. ((uint8 *)array)[bit / NBBY] |= 1 << (bit % NBBY);
  3107. }
  3108. /* Clear bit in byte array. */
  3109. void
  3110. clrbit(void *array, uint bit)
  3111. {
  3112. ((uint8 *)array)[bit / NBBY] &= ~(1 << (bit % NBBY));
  3113. }
  3114. /* Test if bit is set in byte array. */
  3115. bool
  3116. isset(const void *array, uint bit)
  3117. {
  3118. return (((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY)));
  3119. }
  3120. /* Test if bit is clear in byte array. */
  3121. bool
  3122. isclr(const void *array, uint bit)
  3123. {
  3124. return ((((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))) == 0);
  3125. }
  3126. #endif /* BCMUTILS_BIT_MACROS_USE_FUNCS */
  3127. #endif /* setbit */
  3128. void
  3129. set_bitrange(void *array, uint start, uint end, uint maxbit)
  3130. {
  3131. uint startbyte = start/NBBY;
  3132. uint endbyte = end/NBBY;
  3133. uint i, startbytelastbit, endbytestartbit;
  3134. if (end >= start) {
  3135. if (endbyte - startbyte > 1)
  3136. {
  3137. startbytelastbit = (startbyte+1)*NBBY - 1;
  3138. endbytestartbit = endbyte*NBBY;
  3139. for (i = startbyte+1; i < endbyte; i++)
  3140. ((uint8 *)array)[i] = 0xFF;
  3141. for (i = start; i <= startbytelastbit; i++)
  3142. setbit(array, i);
  3143. for (i = endbytestartbit; i <= end; i++)
  3144. setbit(array, i);
  3145. } else {
  3146. for (i = start; i <= end; i++)
  3147. setbit(array, i);
  3148. }
  3149. }
  3150. else {
  3151. set_bitrange(array, start, maxbit, maxbit);
  3152. set_bitrange(array, 0, end, maxbit);
  3153. }
  3154. }
  3155. void
  3156. bcm_bitprint32(const uint32 u32arg)
  3157. {
  3158. int i;
  3159. for (i = NBITS(uint32) - 1; i >= 0; i--) {
  3160. if (isbitset(u32arg, i)) {
  3161. printf("1");
  3162. } else {
  3163. printf("0");
  3164. }
  3165. if ((i % NBBY) == 0) printf(" ");
  3166. }
  3167. printf("\n");
  3168. }
  3169. /* calculate checksum for ip header, tcp / udp header / data */
  3170. uint16
  3171. bcm_ip_cksum(uint8 *buf, uint32 len, uint32 sum)
  3172. {
  3173. while (len > 1) {
  3174. sum += (uint32)((buf[0] << 8) | buf[1]);
  3175. buf += 2;
  3176. len -= 2;
  3177. }
  3178. if (len > 0) {
  3179. sum += (uint32)((*buf) << 8);
  3180. }
  3181. while (sum >> 16) {
  3182. sum = (sum & 0xffff) + (sum >> 16);
  3183. }
  3184. return ((uint16)~sum);
  3185. }
  3186. int
  3187. BCMRAMFN(valid_bcmerror)(int e)
  3188. {
  3189. return ((e <= 0) && (e >= BCME_LAST));
  3190. }
  3191. #ifdef DEBUG_COUNTER
  3192. #if (OSL_SYSUPTIME_SUPPORT == TRUE)
  3193. void counter_printlog(counter_tbl_t *ctr_tbl)
  3194. {
  3195. uint32 now;
  3196. if (!ctr_tbl->enabled)
  3197. return;
  3198. now = OSL_SYSUPTIME();
  3199. if (now - ctr_tbl->prev_log_print > ctr_tbl->log_print_interval) {
  3200. uint8 i = 0;
  3201. printf("counter_print(%s %d):", ctr_tbl->name, now - ctr_tbl->prev_log_print);
  3202. for (i = 0; i < ctr_tbl->needed_cnt; i++) {
  3203. printf(" %u", ctr_tbl->cnt[i]);
  3204. }
  3205. printf("\n");
  3206. ctr_tbl->prev_log_print = now;
  3207. bzero(ctr_tbl->cnt, CNTR_TBL_MAX * sizeof(uint));
  3208. }
  3209. }
  3210. #else
  3211. /* OSL_SYSUPTIME is not supported so no way to get time */
  3212. #define counter_printlog(a) do {} while (0)
  3213. #endif /* OSL_SYSUPTIME_SUPPORT == TRUE */
  3214. #endif /* DEBUG_COUNTER */
  3215. /* calculate partial checksum */
  3216. static uint32
  3217. ip_cksum_partial(uint32 sum, uint8 *val8, uint32 count)
  3218. {
  3219. uint32 i;
  3220. uint16 *val16 = (uint16 *)val8;
  3221. ASSERT(val8 != NULL);
  3222. /* partial chksum calculated on 16-bit values */
  3223. ASSERT((count % 2) == 0);
  3224. count /= 2;
  3225. for (i = 0; i < count; i++) {
  3226. sum += *val16++;
  3227. }
  3228. return sum;
  3229. }
  3230. /* calculate IP checksum */
  3231. static uint16
  3232. ip_cksum(uint32 sum, uint8 *val8, uint32 count)
  3233. {
  3234. uint16 *val16 = (uint16 *)val8;
  3235. ASSERT(val8 != NULL);
  3236. while (count > 1) {
  3237. sum += *val16++;
  3238. count -= 2;
  3239. }
  3240. /* add left-over byte, if any */
  3241. if (count > 0) {
  3242. sum += (*(uint8 *)val16);
  3243. }
  3244. /* fold 32-bit sum to 16 bits */
  3245. sum = (sum >> 16) + (sum & 0xffff);
  3246. sum += (sum >> 16);
  3247. return ((uint16)~sum);
  3248. }
  3249. /* calculate IPv4 header checksum
  3250. * - input ip points to IP header in network order
  3251. * - output cksum is in network order
  3252. */
  3253. uint16
  3254. ipv4_hdr_cksum(uint8 *ip, int ip_len)
  3255. {
  3256. uint32 sum = 0;
  3257. uint8 *ptr = ip;
  3258. ASSERT(ip != NULL);
  3259. ASSERT(ip_len >= IPV4_MIN_HEADER_LEN);
  3260. /* partial cksum skipping the hdr_chksum field */
  3261. sum = ip_cksum_partial(sum, ptr, OFFSETOF(struct ipv4_hdr, hdr_chksum));
  3262. ptr += OFFSETOF(struct ipv4_hdr, hdr_chksum) + 2;
  3263. /* return calculated chksum */
  3264. return ip_cksum(sum, ptr, (uint32)((uint)ip_len - OFFSETOF(struct ipv4_hdr, src_ip)));
  3265. }
  3266. /* calculate TCP header checksum using partial sum */
  3267. static uint16
  3268. tcp_hdr_chksum(uint32 sum, uint8 *tcp_hdr, uint16 tcp_len)
  3269. {
  3270. uint8 *ptr = tcp_hdr;
  3271. ASSERT(tcp_hdr != NULL);
  3272. ASSERT(tcp_len >= TCP_MIN_HEADER_LEN);
  3273. /* partial TCP cksum skipping the chksum field */
  3274. sum = ip_cksum_partial(sum, ptr, OFFSETOF(struct bcmtcp_hdr, chksum));
  3275. ptr += OFFSETOF(struct bcmtcp_hdr, chksum) + 2;
  3276. /* return calculated chksum */
  3277. return ip_cksum(sum, ptr, tcp_len - OFFSETOF(struct bcmtcp_hdr, urg_ptr));
  3278. }
  3279. struct tcp_pseudo_hdr {
  3280. uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */
  3281. uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */
  3282. uint8 zero;
  3283. uint8 prot;
  3284. uint16 tcp_size;
  3285. };
  3286. /* calculate IPv4 TCP header checksum
  3287. * - input ip and tcp points to IP and TCP header in network order
  3288. * - output cksum is in network order
  3289. */
  3290. uint16
  3291. ipv4_tcp_hdr_cksum(uint8 *ip, uint8 *tcp, uint16 tcp_len)
  3292. {
  3293. struct ipv4_hdr *ip_hdr = (struct ipv4_hdr *)ip;
  3294. struct tcp_pseudo_hdr tcp_ps;
  3295. uint32 sum = 0;
  3296. ASSERT(ip != NULL);
  3297. ASSERT(tcp != NULL);
  3298. ASSERT(tcp_len >= TCP_MIN_HEADER_LEN);
  3299. if (!ip || !tcp || !(tcp_len >= TCP_MIN_HEADER_LEN))
  3300. return 0;
  3301. /* pseudo header cksum */
  3302. memset(&tcp_ps, 0, sizeof(tcp_ps));
  3303. memcpy(&tcp_ps.dst_ip, ip_hdr->dst_ip, IPV4_ADDR_LEN);
  3304. memcpy(&tcp_ps.src_ip, ip_hdr->src_ip, IPV4_ADDR_LEN);
  3305. tcp_ps.zero = 0;
  3306. tcp_ps.prot = ip_hdr->prot;
  3307. tcp_ps.tcp_size = hton16(tcp_len);
  3308. sum = ip_cksum_partial(sum, (uint8 *)&tcp_ps, sizeof(tcp_ps));
  3309. /* return calculated TCP header chksum */
  3310. return tcp_hdr_chksum(sum, tcp, tcp_len);
  3311. }
  3312. struct ipv6_pseudo_hdr {
  3313. uint8 saddr[IPV6_ADDR_LEN];
  3314. uint8 daddr[IPV6_ADDR_LEN];
  3315. uint16 payload_len;
  3316. uint8 zero;
  3317. uint8 next_hdr;
  3318. };
  3319. /* calculate IPv6 TCP header checksum
  3320. * - input ipv6 and tcp points to IPv6 and TCP header in network order
  3321. * - output cksum is in network order
  3322. */
  3323. uint16
  3324. ipv6_tcp_hdr_cksum(uint8 *ipv6, uint8 *tcp, uint16 tcp_len)
  3325. {
  3326. struct ipv6_hdr *ipv6_hdr = (struct ipv6_hdr *)ipv6;
  3327. struct ipv6_pseudo_hdr ipv6_pseudo;
  3328. uint32 sum = 0;
  3329. ASSERT(ipv6 != NULL);
  3330. ASSERT(tcp != NULL);
  3331. ASSERT(tcp_len >= TCP_MIN_HEADER_LEN);
  3332. if (!ipv6 || !tcp || !(tcp_len >= TCP_MIN_HEADER_LEN))
  3333. return 0;
  3334. /* pseudo header cksum */
  3335. memset((char *)&ipv6_pseudo, 0, sizeof(ipv6_pseudo));
  3336. memcpy((char *)ipv6_pseudo.saddr, (char *)ipv6_hdr->saddr.addr,
  3337. sizeof(ipv6_pseudo.saddr));
  3338. memcpy((char *)ipv6_pseudo.daddr, (char *)ipv6_hdr->daddr.addr,
  3339. sizeof(ipv6_pseudo.daddr));
  3340. ipv6_pseudo.payload_len = ipv6_hdr->payload_len;
  3341. ipv6_pseudo.next_hdr = ipv6_hdr->nexthdr;
  3342. sum = ip_cksum_partial(sum, (uint8 *)&ipv6_pseudo, sizeof(ipv6_pseudo));
  3343. /* return calculated TCP header chksum */
  3344. return tcp_hdr_chksum(sum, tcp, tcp_len);
  3345. }
  3346. void *_bcmutils_dummy_fn = NULL;
  3347. /* GROUP 1 --- start
  3348. * These function under GROUP 1 are general purpose functions to do complex number
  3349. * calculations and square root calculation.
  3350. */
  3351. uint32 sqrt_int(uint32 value)
  3352. {
  3353. uint32 root = 0, shift = 0;
  3354. /* Compute integer nearest to square root of input integer value */
  3355. for (shift = 0; shift < 32; shift += 2) {
  3356. if (((0x40000000 >> shift) + root) <= value) {
  3357. value -= ((0x40000000 >> shift) + root);
  3358. root = (root >> 1) | (0x40000000 >> shift);
  3359. }
  3360. else {
  3361. root = root >> 1;
  3362. }
  3363. }
  3364. /* round to the nearest integer */
  3365. if (root < value) ++root;
  3366. return root;
  3367. }
  3368. /* GROUP 1 --- end */
  3369. /* read/write field in a consecutive bits in an octet array.
  3370. * 'addr' is the octet array's start byte address
  3371. * 'size' is the octet array's byte size
  3372. * 'stbit' is the value's start bit offset
  3373. * 'nbits' is the value's bit size
  3374. * This set of utilities are for convenience. Don't use them
  3375. * in time critical/data path as there's a great overhead in them.
  3376. */
  3377. void
  3378. setbits(uint8 *addr, uint size, uint stbit, uint nbits, uint32 val)
  3379. {
  3380. uint fbyte = stbit >> 3; /* first byte */
  3381. uint lbyte = (stbit + nbits - 1) >> 3; /* last byte */
  3382. uint fbit = stbit & 7; /* first bit in the first byte */
  3383. uint rbits = (nbits > 8 - fbit ?
  3384. nbits - (8 - fbit) :
  3385. 0) & 7; /* remaining bits of the last byte when not 0 */
  3386. uint8 mask;
  3387. uint byte;
  3388. BCM_REFERENCE(size);
  3389. ASSERT(fbyte < size);
  3390. ASSERT(lbyte < size);
  3391. ASSERT(nbits <= (sizeof(val) << 3));
  3392. /* all bits are in the same byte */
  3393. if (fbyte == lbyte) {
  3394. mask = (uint8)(((1 << nbits) - 1) << fbit);
  3395. addr[fbyte] &= ~mask;
  3396. addr[fbyte] |= (uint8)(val << fbit);
  3397. return;
  3398. }
  3399. /* first partial byte */
  3400. if (fbit > 0) {
  3401. mask = (uint8)(0xff << fbit);
  3402. addr[fbyte] &= ~mask;
  3403. addr[fbyte] |= (uint8)(val << fbit);
  3404. val >>= (8 - fbit);
  3405. nbits -= (8 - fbit);
  3406. fbyte ++; /* first full byte */
  3407. }
  3408. /* last partial byte */
  3409. if (rbits > 0) {
  3410. mask = (uint8)((1 << rbits) - 1);
  3411. addr[lbyte] &= ~mask;
  3412. addr[lbyte] |= (uint8)(val >> (nbits - rbits));
  3413. lbyte --; /* last full byte */
  3414. }
  3415. /* remaining full byte(s) */
  3416. for (byte = fbyte; byte <= lbyte; byte ++) {
  3417. addr[byte] = (uint8)val;
  3418. val >>= 8;
  3419. }
  3420. }
  3421. uint32
  3422. getbits(const uint8 *addr, uint size, uint stbit, uint nbits)
  3423. {
  3424. uint fbyte = stbit >> 3; /* first byte */
  3425. uint lbyte = (stbit + nbits - 1) >> 3; /* last byte */
  3426. uint fbit = stbit & 7; /* first bit in the first byte */
  3427. uint rbits = (nbits > 8 - fbit ?
  3428. nbits - (8 - fbit) :
  3429. 0) & 7; /* remaining bits of the last byte when not 0 */
  3430. uint32 val = 0;
  3431. uint bits = 0; /* bits in first partial byte */
  3432. uint8 mask;
  3433. uint byte;
  3434. BCM_REFERENCE(size);
  3435. ASSERT(fbyte < size);
  3436. ASSERT(lbyte < size);
  3437. ASSERT(nbits <= (sizeof(val) << 3));
  3438. /* all bits are in the same byte */
  3439. if (fbyte == lbyte) {
  3440. mask = (uint8)(((1 << nbits) - 1) << fbit);
  3441. val = (addr[fbyte] & mask) >> fbit;
  3442. return val;
  3443. }
  3444. /* first partial byte */
  3445. if (fbit > 0) {
  3446. bits = 8 - fbit;
  3447. mask = (uint8)(0xFFu << fbit);
  3448. val |= (addr[fbyte] & mask) >> fbit;
  3449. fbyte ++; /* first full byte */
  3450. }
  3451. /* last partial byte */
  3452. if (rbits > 0) {
  3453. mask = (uint8)((1 << rbits) - 1);
  3454. val |= (uint32)((addr[lbyte] & mask) << (nbits - rbits));
  3455. lbyte --; /* last full byte */
  3456. }
  3457. /* remaining full byte(s) */
  3458. for (byte = fbyte; byte <= lbyte; byte ++) {
  3459. val |= (uint32)((addr[byte] << (((byte - fbyte) << 3) + bits)));
  3460. }
  3461. return val;
  3462. }
  3463. #ifdef BCMDRIVER
  3464. /** allocate variable sized data with 'size' bytes. note: vld should NOT be null.
  3465. */
  3466. int
  3467. bcm_vdata_alloc(osl_t *osh, var_len_data_t *vld, uint32 size)
  3468. {
  3469. int ret = BCME_ERROR;
  3470. uint8 *dat = NULL;
  3471. if (vld == NULL) {
  3472. ASSERT(0);
  3473. goto done;
  3474. }
  3475. /* trying to allocate twice? */
  3476. if (vld->vdata != NULL) {
  3477. ASSERT(0);
  3478. goto done;
  3479. }
  3480. /* trying to allocate 0 size? */
  3481. if (size == 0) {
  3482. ASSERT(0);
  3483. ret = BCME_BADARG;
  3484. goto done;
  3485. }
  3486. dat = MALLOCZ(osh, size);
  3487. if (dat == NULL) {
  3488. ret = BCME_NOMEM;
  3489. goto done;
  3490. }
  3491. vld->vlen = size;
  3492. vld->vdata = dat;
  3493. ret = BCME_OK;
  3494. done:
  3495. return ret;
  3496. }
  3497. /** free memory associated with variable sized data. note: vld should NOT be null.
  3498. */
  3499. int
  3500. bcm_vdata_free(osl_t *osh, var_len_data_t *vld)
  3501. {
  3502. int ret = BCME_ERROR;
  3503. if (vld == NULL) {
  3504. ASSERT(0);
  3505. goto done;
  3506. }
  3507. if (vld->vdata) {
  3508. MFREE(osh, vld->vdata, vld->vlen);
  3509. vld->vdata = NULL;
  3510. vld->vlen = 0;
  3511. ret = BCME_OK;
  3512. }
  3513. done:
  3514. return ret;
  3515. }
  3516. #endif /* BCMDRIVER */
  3517. /* Count the number of elements not matching a given value in a null terminated array */
  3518. int
  3519. array_value_mismatch_count(uint8 value, uint8 *array, int array_size)
  3520. {
  3521. int i;
  3522. int count = 0;
  3523. for (i = 0; i < array_size; i++) {
  3524. /* exit if a null terminator is found */
  3525. if (array[i] == 0) {
  3526. break;
  3527. }
  3528. if (array[i] != value) {
  3529. count++;
  3530. }
  3531. }
  3532. return count;
  3533. }
  3534. /* Count the number of non-zero elements in an uint8 array */
  3535. int
  3536. array_nonzero_count(uint8 *array, int array_size)
  3537. {
  3538. return array_value_mismatch_count(0, array, array_size);
  3539. }
  3540. /* Count the number of non-zero elements in an int16 array */
  3541. int
  3542. array_nonzero_count_int16(int16 *array, int array_size)
  3543. {
  3544. int i;
  3545. int count = 0;
  3546. for (i = 0; i < array_size; i++) {
  3547. if (array[i] != 0) {
  3548. count++;
  3549. }
  3550. }
  3551. return count;
  3552. }
  3553. /* Count the number of zero elements in an uint8 array */
  3554. int
  3555. array_zero_count(uint8 *array, int array_size)
  3556. {
  3557. int i;
  3558. int count = 0;
  3559. for (i = 0; i < array_size; i++) {
  3560. if (array[i] == 0) {
  3561. count++;
  3562. }
  3563. }
  3564. return count;
  3565. }
  3566. /* Validate an array that can be 1 of 2 data types.
  3567. * One of array1 or array2 should be non-NULL. The other should be NULL.
  3568. */
  3569. static int
  3570. verify_ordered_array(uint8 *array1, int16 *array2, int array_size,
  3571. int range_lo, int range_hi, bool err_if_no_zero_term, bool is_ordered)
  3572. {
  3573. int ret;
  3574. int i;
  3575. int val = 0;
  3576. int prev_val = 0;
  3577. ret = err_if_no_zero_term ? BCME_NOTFOUND : BCME_OK;
  3578. /* Check that:
  3579. * - values are in strict descending order.
  3580. * - values are within the valid range.
  3581. */
  3582. for (i = 0; i < array_size; i++) {
  3583. if (array1) {
  3584. val = (int)array1[i];
  3585. } else if (array2) {
  3586. val = (int)array2[i];
  3587. } else {
  3588. /* both array parameters are NULL */
  3589. return BCME_NOTFOUND;
  3590. }
  3591. if (val == 0) {
  3592. /* array is zero-terminated */
  3593. ret = BCME_OK;
  3594. break;
  3595. }
  3596. if (is_ordered && i > 0 && val >= prev_val) {
  3597. /* array is not in descending order */
  3598. ret = BCME_BADOPTION;
  3599. break;
  3600. }
  3601. prev_val = val;
  3602. if (val < range_lo || val > range_hi) {
  3603. /* array value out of range */
  3604. ret = BCME_RANGE;
  3605. break;
  3606. }
  3607. }
  3608. return ret;
  3609. }
  3610. /* Validate an ordered uint8 configuration array */
  3611. int
  3612. verify_ordered_array_uint8(uint8 *array, int array_size,
  3613. uint8 range_lo, uint8 range_hi)
  3614. {
  3615. return verify_ordered_array(array, NULL, array_size, (int)range_lo, (int)range_hi,
  3616. TRUE, TRUE);
  3617. }
  3618. /* Validate an ordered int16 non-zero-terminated configuration array */
  3619. int
  3620. verify_ordered_array_int16(int16 *array, int array_size,
  3621. int16 range_lo, int16 range_hi)
  3622. {
  3623. return verify_ordered_array(NULL, array, array_size, (int)range_lo, (int)range_hi,
  3624. FALSE, TRUE);
  3625. }
  3626. /* Validate all values in an array are in range */
  3627. int
  3628. verify_array_values(uint8 *array, int array_size,
  3629. int range_lo, int range_hi, bool zero_terminated)
  3630. {
  3631. int ret = BCME_OK;
  3632. int i;
  3633. int val = 0;
  3634. /* Check that:
  3635. * - values are in strict descending order.
  3636. * - values are within the valid range.
  3637. */
  3638. for (i = 0; i < array_size; i++) {
  3639. val = (int)array[i];
  3640. if (val == 0 && zero_terminated) {
  3641. ret = BCME_OK;
  3642. break;
  3643. }
  3644. if (val < range_lo || val > range_hi) {
  3645. /* array value out of range */
  3646. ret = BCME_RANGE;
  3647. break;
  3648. }
  3649. }
  3650. return ret;
  3651. }
  3652. /* Adds/replaces NVRAM variable with given value
  3653. * varbuf[in,out] - Buffer with NVRAM variables (sequence of zero-terminated 'name=value' records,
  3654. * terminated with additional zero)
  3655. * buflen[in] - Length of buffer (may, even should, have some unused space)
  3656. * variable[in] - Variable to add/replace in 'name=value' form
  3657. * datalen[out,opt] - Optional output parameter - resulting length of data in buffer
  3658. * Returns TRUE on success, FALSE if buffer too short or variable specified incorrectly
  3659. */
  3660. bool
  3661. replace_nvram_variable(char *varbuf, unsigned int buflen, const char *variable,
  3662. unsigned int *datalen)
  3663. {
  3664. char *p;
  3665. int variable_heading_len, record_len, variable_record_len = (int)strlen(variable) + 1;
  3666. char *buf_end = varbuf + buflen;
  3667. p = strchr(variable, '=');
  3668. if (!p) {
  3669. return FALSE;
  3670. }
  3671. /* Length of given variable name, followed by '=' */
  3672. variable_heading_len = (int)((const char *)(p + 1) - variable);
  3673. /* Scanning NVRAM, record by record up to trailing 0 */
  3674. for (p = varbuf; *p; p += strlen(p) + 1) {
  3675. /* If given variable found - remove it */
  3676. if (!strncmp(p, variable, (size_t)variable_heading_len)) {
  3677. record_len = (int)strlen(p) + 1;
  3678. memmove_s(p, buf_end - p, p + record_len,
  3679. (size_t)(buf_end - (p + record_len)));
  3680. }
  3681. }
  3682. /* If buffer does not have space for given variable - return FALSE */
  3683. if ((p + variable_record_len + 1) > buf_end) {
  3684. return FALSE;
  3685. }
  3686. /* Copy given variable to end of buffer */
  3687. memmove_s(p, buf_end - p, variable, (size_t)variable_record_len);
  3688. /* Adding trailing 0 */
  3689. p[variable_record_len] = 0;
  3690. /* Setting optional output parameter - length of data in buffer */
  3691. if (datalen) {
  3692. *datalen = (unsigned int)(p + variable_record_len + 1 - varbuf);
  3693. }
  3694. return TRUE;
  3695. }