skaddr.c 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875
  1. /******************************************************************************
  2. *
  3. * Name: skaddr.c
  4. * Project: GEnesis, PCI Gigabit Ethernet Adapter
  5. * Version: $Revision: 1.48 $
  6. * Date: $Date: 2003/02/12 17:09:37 $
  7. * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
  8. *
  9. ******************************************************************************/
  10. /******************************************************************************
  11. *
  12. * (C)Copyright 1998-2002 SysKonnect GmbH.
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation; either version 2 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * The information in this file is provided "AS IS" without warranty.
  20. *
  21. ******************************************************************************/
  22. /******************************************************************************
  23. *
  24. * History:
  25. *
  26. * $Log: skaddr.c,v $
  27. * Revision 1.48 2003/02/12 17:09:37 tschilli
  28. * Fix in SkAddrOverride() to set both (physical and logical) MAC addresses
  29. * in case that both addresses are identical.
  30. *
  31. * Revision 1.47 2002/09/17 06:31:10 tschilli
  32. * Handling of SK_PROM_MODE_ALL_MC flag in SkAddrGmacMcUpdate()
  33. * and SkAddrGmacPromiscuousChange() fixed.
  34. * Editorial changes.
  35. *
  36. * Revision 1.46 2002/08/22 07:55:41 tschilli
  37. * New function SkGmacMcHash() for GMAC multicast hashing algorithm added.
  38. * Editorial changes.
  39. *
  40. * Revision 1.45 2002/08/15 12:29:35 tschilli
  41. * SkAddrGmacMcUpdate() and SkAddrGmacPromiscuousChange() changed.
  42. *
  43. * Revision 1.44 2002/08/14 12:18:03 rschmidt
  44. * Replaced direct handling of MAC Hashing (XMAC and GMAC)
  45. * with routine SkMacHashing().
  46. * Replaced wrong 3rd para 'i' with 'PortNumber' in SkMacPromiscMode().
  47. *
  48. * Revision 1.43 2002/08/13 09:37:43 rschmidt
  49. * Corrected some SK_DBG_MSG outputs.
  50. * Replaced wrong 2nd para pAC with IoC in SkMacPromiscMode().
  51. * Editorial changes.
  52. *
  53. * Revision 1.42 2002/08/12 11:24:36 rschmidt
  54. * Remove setting of logical MAC address GM_SRC_ADDR_2 in SkAddrInit().
  55. * Replaced direct handling of MAC Promiscuous Mode (XMAC and GMAC)
  56. * with routine SkMacPromiscMode().
  57. * Editorial changes.
  58. *
  59. * Revision 1.41 2002/06/10 13:52:18 tschilli
  60. * Changes for handling YUKON.
  61. * All changes are internally and not visible to the programmer
  62. * using this module.
  63. *
  64. * Revision 1.40 2001/02/14 14:04:59 rassmann
  65. * Editorial changes.
  66. *
  67. * Revision 1.39 2001/01/30 10:30:04 rassmann
  68. * Editorial changes.
  69. *
  70. * Revision 1.38 2001/01/25 16:26:52 rassmann
  71. * Ensured that logical address overrides are done on net's active port.
  72. *
  73. * Revision 1.37 2001/01/22 13:41:34 rassmann
  74. * Supporting two nets on dual-port adapters.
  75. *
  76. * Revision 1.36 2000/08/07 11:10:39 rassmann
  77. * Editorial changes.
  78. *
  79. * Revision 1.35 2000/05/04 09:38:41 rassmann
  80. * Editorial changes.
  81. * Corrected multicast address hashing.
  82. *
  83. * Revision 1.34 1999/11/22 13:23:44 cgoos
  84. * Changed license header to GPL.
  85. *
  86. * Revision 1.33 1999/05/28 10:56:06 rassmann
  87. * Editorial changes.
  88. *
  89. * Revision 1.32 1999/03/31 10:59:20 rassmann
  90. * Returning Success instead of DupAddr if address shall be overridden
  91. * with same value.
  92. *
  93. * Revision 1.31 1999/01/14 16:18:17 rassmann
  94. * Corrected multicast initialization.
  95. *
  96. * Revision 1.30 1999/01/04 10:30:35 rassmann
  97. * SkAddrOverride only possible after SK_INIT_IO phase.
  98. *
  99. * Revision 1.29 1998/12/29 13:13:10 rassmann
  100. * An address override is now preserved in the SK_INIT_IO phase.
  101. * All functions return an int now.
  102. * Extended parameter checking.
  103. *
  104. * Revision 1.28 1998/12/01 11:45:53 rassmann
  105. * Code cleanup.
  106. *
  107. * Revision 1.27 1998/12/01 09:22:49 rassmann
  108. * SkAddrMcAdd and SkAddrMcUpdate returned SK_MC_FILTERING_INEXACT
  109. * too often.
  110. *
  111. * Revision 1.26 1998/11/24 12:39:44 rassmann
  112. * Reserved multicast entry for BPDU address.
  113. * 13 multicast entries left for protocol.
  114. *
  115. * Revision 1.25 1998/11/17 16:54:23 rassmann
  116. * Using exact match for up to 14 multicast addresses.
  117. * Still receiving all multicasts if more addresses are added.
  118. *
  119. * Revision 1.24 1998/11/13 17:24:31 rassmann
  120. * Changed return value of SkAddrOverride to int.
  121. *
  122. * Revision 1.23 1998/11/13 16:56:18 rassmann
  123. * Added macro SK_ADDR_COMPARE.
  124. * Changed return type of SkAddrOverride to SK_BOOL.
  125. *
  126. * Revision 1.22 1998/11/04 17:06:17 rassmann
  127. * Corrected McUpdate and PromiscuousChange functions.
  128. *
  129. * Revision 1.21 1998/10/29 14:34:04 rassmann
  130. * Clearing SK_ADDR struct at startup.
  131. *
  132. * Revision 1.20 1998/10/28 18:16:34 rassmann
  133. * Avoiding I/Os before SK_INIT_RUN level.
  134. * Aligning InexactFilter.
  135. *
  136. * Revision 1.19 1998/10/28 11:29:28 rassmann
  137. * Programming physical address in SkAddrMcUpdate.
  138. * Corrected programming of exact match entries.
  139. *
  140. * Revision 1.18 1998/10/28 10:34:48 rassmann
  141. * Corrected reading of physical addresses.
  142. *
  143. * Revision 1.17 1998/10/28 10:26:13 rassmann
  144. * Getting ports' current MAC addresses from EPROM now.
  145. * Added debug output.
  146. *
  147. * Revision 1.16 1998/10/27 16:20:12 rassmann
  148. * Reading MAC address byte by byte.
  149. *
  150. * Revision 1.15 1998/10/22 11:39:09 rassmann
  151. * Corrected signed/unsigned mismatches.
  152. *
  153. * Revision 1.14 1998/10/19 17:12:35 rassmann
  154. * Syntax corrections.
  155. *
  156. * Revision 1.13 1998/10/19 17:02:19 rassmann
  157. * Now reading permanent MAC addresses from CRF.
  158. *
  159. * Revision 1.12 1998/10/15 15:15:48 rassmann
  160. * Changed Flags Parameters from SK_U8 to int.
  161. * Checked with lint.
  162. *
  163. * Revision 1.11 1998/09/24 19:15:12 rassmann
  164. * Code cleanup.
  165. *
  166. * Revision 1.10 1998/09/18 20:18:54 rassmann
  167. * Added HW access.
  168. * Implemented swapping.
  169. *
  170. * Revision 1.9 1998/09/16 11:32:00 rassmann
  171. * Including skdrv1st.h again. :(
  172. *
  173. * Revision 1.8 1998/09/16 11:09:34 rassmann
  174. * Syntax corrections.
  175. *
  176. * Revision 1.7 1998/09/14 17:06:34 rassmann
  177. * Minor changes.
  178. *
  179. * Revision 1.6 1998/09/07 08:45:41 rassmann
  180. * Syntax corrections.
  181. *
  182. * Revision 1.5 1998/09/04 19:40:19 rassmann
  183. * Interface enhancements.
  184. *
  185. * Revision 1.4 1998/09/04 12:14:12 rassmann
  186. * Interface cleanup.
  187. *
  188. * Revision 1.3 1998/09/02 16:56:40 rassmann
  189. * Updated interface.
  190. *
  191. * Revision 1.2 1998/08/27 14:26:09 rassmann
  192. * Updated interface.
  193. *
  194. * Revision 1.1 1998/08/21 08:30:22 rassmann
  195. * First public version.
  196. *
  197. ******************************************************************************/
  198. /******************************************************************************
  199. *
  200. * Description:
  201. *
  202. * This module is intended to manage multicast addresses, address override,
  203. * and promiscuous mode on GEnesis and Yukon adapters.
  204. *
  205. * Address Layout:
  206. * port address: physical MAC address
  207. * 1st exact match: logical MAC address (GEnesis only)
  208. * 2nd exact match: RLMT multicast (GEnesis only)
  209. * exact match 3-13: OS-specific multicasts (GEnesis only)
  210. *
  211. * Include File Hierarchy:
  212. *
  213. * "skdrv1st.h"
  214. * "skdrv2nd.h"
  215. *
  216. ******************************************************************************/
  217. #include <config.h>
  218. #ifndef lint
  219. static const char SysKonnectFileId[] =
  220. "@(#) $Id: skaddr.c,v 1.48 2003/02/12 17:09:37 tschilli Exp $ (C) SysKonnect.";
  221. #endif /* !defined(lint) */
  222. #define __SKADDR_C
  223. #ifdef __cplusplus
  224. #error C++ is not yet supported.
  225. extern "C" {
  226. #endif /* cplusplus */
  227. #include "h/skdrv1st.h"
  228. #include "h/skdrv2nd.h"
  229. /* defines ********************************************************************/
  230. #define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
  231. #define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
  232. #define HASH_BITS 6 /* #bits in hash */
  233. #define SK_MC_BIT 0x01
  234. /* Error numbers and messages. */
  235. #define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
  236. #define SKERR_ADDR_E001MSG "Bad Flags."
  237. #define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
  238. #define SKERR_ADDR_E002MSG "New Error."
  239. /* typedefs *******************************************************************/
  240. /* None. */
  241. /* global variables ***********************************************************/
  242. /* 64-bit hash values with all bits set. */
  243. SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
  244. /* local variables ************************************************************/
  245. #ifdef DEBUG
  246. static int Next0[SK_MAX_MACS] = {0, 0};
  247. #endif /* DEBUG */
  248. /* functions ******************************************************************/
  249. /******************************************************************************
  250. *
  251. * SkAddrInit - initialize data, set state to init
  252. *
  253. * Description:
  254. *
  255. * SK_INIT_DATA
  256. * ============
  257. *
  258. * This routine clears the multicast tables and resets promiscuous mode.
  259. * Some entries are reserved for the "logical MAC address", the
  260. * SK-RLMT multicast address, and the BPDU multicast address.
  261. *
  262. *
  263. * SK_INIT_IO
  264. * ==========
  265. *
  266. * All permanent MAC addresses are read from EPROM.
  267. * If the current MAC addresses are not already set in software,
  268. * they are set to the values of the permanent addresses.
  269. * The current addresses are written to the corresponding MAC.
  270. *
  271. *
  272. * SK_INIT_RUN
  273. * ===========
  274. *
  275. * Nothing.
  276. *
  277. * Context:
  278. * init, pageable
  279. *
  280. * Returns:
  281. * SK_ADDR_SUCCESS
  282. */
  283. int SkAddrInit(
  284. SK_AC *pAC, /* the adapter context */
  285. SK_IOC IoC, /* I/O context */
  286. int Level) /* initialization level */
  287. {
  288. int j;
  289. SK_U32 i;
  290. SK_U8 *InAddr;
  291. SK_U16 *OutAddr;
  292. SK_ADDR_PORT *pAPort;
  293. switch (Level) {
  294. case SK_INIT_DATA:
  295. SK_MEMSET((char *) &pAC->Addr, 0, sizeof(SK_ADDR));
  296. for (i = 0; i < SK_MAX_MACS; i++) {
  297. pAPort = &pAC->Addr.Port[i];
  298. pAPort->PromMode = SK_PROM_MODE_NONE;
  299. pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
  300. pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
  301. pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
  302. pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
  303. }
  304. #ifdef xDEBUG
  305. for (i = 0; i < SK_MAX_MACS; i++) {
  306. if (pAC->Addr.Port[i].NextExactMatchRlmt <
  307. SK_ADDR_FIRST_MATCH_RLMT) {
  308. Next0[i] |= 4;
  309. }
  310. }
  311. #endif /* DEBUG */
  312. /* pAC->Addr.InitDone = SK_INIT_DATA; */
  313. break;
  314. case SK_INIT_IO:
  315. for (i = 0; i < SK_MAX_NETS; i++) {
  316. pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
  317. }
  318. #ifdef xDEBUG
  319. for (i = 0; i < SK_MAX_MACS; i++) {
  320. if (pAC->Addr.Port[i].NextExactMatchRlmt <
  321. SK_ADDR_FIRST_MATCH_RLMT) {
  322. Next0[i] |= 8;
  323. }
  324. }
  325. #endif /* DEBUG */
  326. /* Read permanent logical MAC address from Control Register File. */
  327. for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
  328. InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
  329. SK_IN8(IoC, B2_MAC_1 + j, InAddr);
  330. }
  331. if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
  332. /* Set the current logical MAC address to the permanent one. */
  333. pAC->Addr.Net[0].CurrentMacAddress =
  334. pAC->Addr.Net[0].PermanentMacAddress;
  335. pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
  336. }
  337. /* Set the current logical MAC address. */
  338. pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
  339. pAC->Addr.Net[0].CurrentMacAddress;
  340. #if SK_MAX_NETS > 1
  341. /* Set logical MAC address for net 2 to (log | 3). */
  342. if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
  343. pAC->Addr.Net[1].PermanentMacAddress =
  344. pAC->Addr.Net[0].PermanentMacAddress;
  345. pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
  346. /* Set the current logical MAC address to the permanent one. */
  347. pAC->Addr.Net[1].CurrentMacAddress =
  348. pAC->Addr.Net[1].PermanentMacAddress;
  349. pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
  350. }
  351. #endif /* SK_MAX_NETS > 1 */
  352. #ifdef DEBUG
  353. for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
  354. SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
  355. ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
  356. i,
  357. pAC->Addr.Net[i].PermanentMacAddress.a[0],
  358. pAC->Addr.Net[i].PermanentMacAddress.a[1],
  359. pAC->Addr.Net[i].PermanentMacAddress.a[2],
  360. pAC->Addr.Net[i].PermanentMacAddress.a[3],
  361. pAC->Addr.Net[i].PermanentMacAddress.a[4],
  362. pAC->Addr.Net[i].PermanentMacAddress.a[5]))
  363. SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
  364. ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
  365. i,
  366. pAC->Addr.Net[i].CurrentMacAddress.a[0],
  367. pAC->Addr.Net[i].CurrentMacAddress.a[1],
  368. pAC->Addr.Net[i].CurrentMacAddress.a[2],
  369. pAC->Addr.Net[i].CurrentMacAddress.a[3],
  370. pAC->Addr.Net[i].CurrentMacAddress.a[4],
  371. pAC->Addr.Net[i].CurrentMacAddress.a[5]))
  372. }
  373. #endif /* DEBUG */
  374. for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
  375. pAPort = &pAC->Addr.Port[i];
  376. /* Read permanent port addresses from Control Register File. */
  377. for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
  378. InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
  379. SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
  380. }
  381. if (!pAPort->CurrentMacAddressSet) {
  382. /*
  383. * Set the current and previous physical MAC address
  384. * of this port to its permanent MAC address.
  385. */
  386. pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
  387. pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
  388. pAPort->CurrentMacAddressSet = SK_TRUE;
  389. }
  390. /* Set port's current physical MAC address. */
  391. OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
  392. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
  393. XM_OUTADDR(IoC, i, XM_SA, OutAddr);
  394. }
  395. else {
  396. GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
  397. }
  398. #ifdef DEBUG
  399. SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
  400. ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
  401. pAPort->PermanentMacAddress.a[0],
  402. pAPort->PermanentMacAddress.a[1],
  403. pAPort->PermanentMacAddress.a[2],
  404. pAPort->PermanentMacAddress.a[3],
  405. pAPort->PermanentMacAddress.a[4],
  406. pAPort->PermanentMacAddress.a[5]))
  407. SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
  408. ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
  409. pAPort->CurrentMacAddress.a[0],
  410. pAPort->CurrentMacAddress.a[1],
  411. pAPort->CurrentMacAddress.a[2],
  412. pAPort->CurrentMacAddress.a[3],
  413. pAPort->CurrentMacAddress.a[4],
  414. pAPort->CurrentMacAddress.a[5]))
  415. #endif /* DEBUG */
  416. }
  417. /* pAC->Addr.InitDone = SK_INIT_IO; */
  418. break;
  419. case SK_INIT_RUN:
  420. #ifdef xDEBUG
  421. for (i = 0; i < SK_MAX_MACS; i++) {
  422. if (pAC->Addr.Port[i].NextExactMatchRlmt <
  423. SK_ADDR_FIRST_MATCH_RLMT) {
  424. Next0[i] |= 16;
  425. }
  426. }
  427. #endif /* DEBUG */
  428. /* pAC->Addr.InitDone = SK_INIT_RUN; */
  429. break;
  430. default: /* error */
  431. break;
  432. }
  433. return (SK_ADDR_SUCCESS);
  434. } /* SkAddrInit */
  435. /******************************************************************************
  436. *
  437. * SkAddrMcClear - clear the multicast table
  438. *
  439. * Description:
  440. * This routine clears the multicast table.
  441. *
  442. * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
  443. * immediately.
  444. *
  445. * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
  446. * to the adapter in use. The real work is done there.
  447. *
  448. * Context:
  449. * runtime, pageable
  450. * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
  451. * may be called after SK_INIT_IO without limitation
  452. *
  453. * Returns:
  454. * SK_ADDR_SUCCESS
  455. * SK_ADDR_ILLEGAL_PORT
  456. */
  457. int SkAddrMcClear(
  458. SK_AC *pAC, /* adapter context */
  459. SK_IOC IoC, /* I/O context */
  460. SK_U32 PortNumber, /* Index of affected port */
  461. int Flags) /* permanent/non-perm, sw-only */
  462. {
  463. int ReturnCode;
  464. if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
  465. return (SK_ADDR_ILLEGAL_PORT);
  466. }
  467. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
  468. ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
  469. }
  470. else {
  471. ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
  472. }
  473. return (ReturnCode);
  474. } /* SkAddrMcClear */
  475. /******************************************************************************
  476. *
  477. * SkAddrXmacMcClear - clear the multicast table
  478. *
  479. * Description:
  480. * This routine clears the multicast table
  481. * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
  482. * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
  483. * immediately.
  484. *
  485. * Context:
  486. * runtime, pageable
  487. * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
  488. * may be called after SK_INIT_IO without limitation
  489. *
  490. * Returns:
  491. * SK_ADDR_SUCCESS
  492. * SK_ADDR_ILLEGAL_PORT
  493. */
  494. int SkAddrXmacMcClear(
  495. SK_AC *pAC, /* adapter context */
  496. SK_IOC IoC, /* I/O context */
  497. SK_U32 PortNumber, /* Index of affected port */
  498. int Flags) /* permanent/non-perm, sw-only */
  499. {
  500. int i;
  501. if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
  502. /* Clear RLMT multicast addresses. */
  503. pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
  504. }
  505. else { /* not permanent => DRV */
  506. /* Clear InexactFilter */
  507. for (i = 0; i < 8; i++) {
  508. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
  509. }
  510. /* Clear DRV multicast addresses. */
  511. pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
  512. }
  513. if (!(Flags & SK_MC_SW_ONLY)) {
  514. (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
  515. }
  516. return (SK_ADDR_SUCCESS);
  517. } /* SkAddrXmacMcClear */
  518. /******************************************************************************
  519. *
  520. * SkAddrGmacMcClear - clear the multicast table
  521. *
  522. * Description:
  523. * This routine clears the multicast hashing table (InexactFilter)
  524. * (either the RLMT or the driver bits) of the given port.
  525. *
  526. * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
  527. * immediately.
  528. *
  529. * Context:
  530. * runtime, pageable
  531. * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
  532. * may be called after SK_INIT_IO without limitation
  533. *
  534. * Returns:
  535. * SK_ADDR_SUCCESS
  536. * SK_ADDR_ILLEGAL_PORT
  537. */
  538. int SkAddrGmacMcClear(
  539. SK_AC *pAC, /* adapter context */
  540. SK_IOC IoC, /* I/O context */
  541. SK_U32 PortNumber, /* Index of affected port */
  542. int Flags) /* permanent/non-perm, sw-only */
  543. {
  544. int i;
  545. #ifdef DEBUG
  546. SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  547. ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
  548. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
  549. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
  550. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
  551. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
  552. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
  553. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
  554. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
  555. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
  556. #endif /* DEBUG */
  557. /* Clear InexactFilter */
  558. for (i = 0; i < 8; i++) {
  559. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
  560. }
  561. if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
  562. /* Copy DRV bits to InexactFilter. */
  563. for (i = 0; i < 8; i++) {
  564. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
  565. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
  566. /* Clear InexactRlmtFilter. */
  567. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
  568. }
  569. }
  570. else { /* not permanent => DRV */
  571. /* Copy RLMT bits to InexactFilter. */
  572. for (i = 0; i < 8; i++) {
  573. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
  574. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
  575. /* Clear InexactDrvFilter. */
  576. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
  577. }
  578. }
  579. #ifdef DEBUG
  580. SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  581. ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
  582. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
  583. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
  584. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
  585. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
  586. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
  587. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
  588. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
  589. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
  590. #endif /* DEBUG */
  591. if (!(Flags & SK_MC_SW_ONLY)) {
  592. (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
  593. }
  594. return (SK_ADDR_SUCCESS);
  595. } /* SkAddrGmacMcClear */
  596. #ifndef SK_ADDR_CHEAT
  597. /******************************************************************************
  598. *
  599. * SkXmacMcHash - hash multicast address
  600. *
  601. * Description:
  602. * This routine computes the hash value for a multicast address.
  603. * A CRC32 algorithm is used.
  604. *
  605. * Notes:
  606. * The code was adapted from the XaQti data sheet.
  607. *
  608. * Context:
  609. * runtime, pageable
  610. *
  611. * Returns:
  612. * Hash value of multicast address.
  613. */
  614. SK_U32 SkXmacMcHash(
  615. unsigned char *pMc) /* Multicast address */
  616. {
  617. SK_U32 Idx;
  618. SK_U32 Bit;
  619. SK_U32 Data;
  620. SK_U32 Crc;
  621. Crc = 0xFFFFFFFFUL;
  622. for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
  623. Data = *pMc++;
  624. for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
  625. Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
  626. }
  627. }
  628. return (Crc & ((1 << HASH_BITS) - 1));
  629. } /* SkXmacMcHash */
  630. /******************************************************************************
  631. *
  632. * SkGmacMcHash - hash multicast address
  633. *
  634. * Description:
  635. * This routine computes the hash value for a multicast address.
  636. * A CRC16 algorithm is used.
  637. *
  638. * Notes:
  639. *
  640. *
  641. * Context:
  642. * runtime, pageable
  643. *
  644. * Returns:
  645. * Hash value of multicast address.
  646. */
  647. SK_U32 SkGmacMcHash(
  648. unsigned char *pMc) /* Multicast address */
  649. {
  650. SK_U32 Data;
  651. SK_U32 TmpData;
  652. SK_U32 Crc;
  653. int Byte;
  654. int Bit;
  655. Crc = 0xFFFFFFFFUL;
  656. for (Byte = 0; Byte < 6; Byte++) {
  657. /* Get next byte. */
  658. Data = (SK_U32) pMc[Byte];
  659. /* Change bit order in byte. */
  660. TmpData = Data;
  661. for (Bit = 0; Bit < 8; Bit++) {
  662. if (TmpData & 1L) {
  663. Data |= 1L << (7 - Bit);
  664. }
  665. else {
  666. Data &= ~(1L << (7 - Bit));
  667. }
  668. TmpData >>= 1;
  669. }
  670. Crc ^= (Data << 24);
  671. for (Bit = 0; Bit < 8; Bit++) {
  672. if (Crc & 0x80000000) {
  673. Crc = (Crc << 1) ^ GMAC_POLY;
  674. }
  675. else {
  676. Crc <<= 1;
  677. }
  678. }
  679. }
  680. return (Crc & ((1 << HASH_BITS) - 1));
  681. } /* SkGmacMcHash */
  682. #endif /* not SK_ADDR_CHEAT */
  683. /******************************************************************************
  684. *
  685. * SkAddrMcAdd - add a multicast address to a port
  686. *
  687. * Description:
  688. * This routine enables reception for a given address on the given port.
  689. *
  690. * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
  691. * adapter in use. The real work is done there.
  692. *
  693. * Notes:
  694. * The return code is only valid for SK_PROM_MODE_NONE.
  695. *
  696. * Context:
  697. * runtime, pageable
  698. * may be called after SK_INIT_DATA
  699. *
  700. * Returns:
  701. * SK_MC_FILTERING_EXACT
  702. * SK_MC_FILTERING_INEXACT
  703. * SK_MC_ILLEGAL_ADDRESS
  704. * SK_MC_ILLEGAL_PORT
  705. * SK_MC_RLMT_OVERFLOW
  706. */
  707. int SkAddrMcAdd(
  708. SK_AC *pAC, /* adapter context */
  709. SK_IOC IoC, /* I/O context */
  710. SK_U32 PortNumber, /* Port Number */
  711. SK_MAC_ADDR *pMc, /* multicast address to be added */
  712. int Flags) /* permanent/non-permanent */
  713. {
  714. int ReturnCode;
  715. if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
  716. return (SK_ADDR_ILLEGAL_PORT);
  717. }
  718. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
  719. ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
  720. }
  721. else {
  722. ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
  723. }
  724. return (ReturnCode);
  725. } /* SkAddrMcAdd */
  726. /******************************************************************************
  727. *
  728. * SkAddrXmacMcAdd - add a multicast address to a port
  729. *
  730. * Description:
  731. * This routine enables reception for a given address on the given port.
  732. *
  733. * Notes:
  734. * The return code is only valid for SK_PROM_MODE_NONE.
  735. *
  736. * The multicast bit is only checked if there are no free exact match
  737. * entries.
  738. *
  739. * Context:
  740. * runtime, pageable
  741. * may be called after SK_INIT_DATA
  742. *
  743. * Returns:
  744. * SK_MC_FILTERING_EXACT
  745. * SK_MC_FILTERING_INEXACT
  746. * SK_MC_ILLEGAL_ADDRESS
  747. * SK_MC_RLMT_OVERFLOW
  748. */
  749. int SkAddrXmacMcAdd(
  750. SK_AC *pAC, /* adapter context */
  751. SK_IOC IoC, /* I/O context */
  752. SK_U32 PortNumber, /* Port Number */
  753. SK_MAC_ADDR *pMc, /* multicast address to be added */
  754. int Flags) /* permanent/non-permanent */
  755. {
  756. int i;
  757. SK_U8 Inexact;
  758. #ifndef SK_ADDR_CHEAT
  759. SK_U32 HashBit;
  760. #endif /* !defined(SK_ADDR_CHEAT) */
  761. if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
  762. #ifdef xDEBUG
  763. if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
  764. SK_ADDR_FIRST_MATCH_RLMT) {
  765. Next0[PortNumber] |= 1;
  766. return (SK_MC_RLMT_OVERFLOW);
  767. }
  768. #endif /* DEBUG */
  769. if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
  770. SK_ADDR_LAST_MATCH_RLMT) {
  771. return (SK_MC_RLMT_OVERFLOW);
  772. }
  773. /* Set a RLMT multicast address. */
  774. pAC->Addr.Port[PortNumber].Exact[
  775. pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
  776. return (SK_MC_FILTERING_EXACT);
  777. }
  778. #ifdef xDEBUG
  779. if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
  780. SK_ADDR_FIRST_MATCH_DRV) {
  781. Next0[PortNumber] |= 2;
  782. return (SK_MC_RLMT_OVERFLOW);
  783. }
  784. #endif /* DEBUG */
  785. if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
  786. /* Set exact match entry. */
  787. pAC->Addr.Port[PortNumber].Exact[
  788. pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
  789. /* Clear InexactFilter */
  790. for (i = 0; i < 8; i++) {
  791. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
  792. }
  793. }
  794. else {
  795. if (!(pMc->a[0] & SK_MC_BIT)) {
  796. /* Hashing only possible with multicast addresses. */
  797. return (SK_MC_ILLEGAL_ADDRESS);
  798. }
  799. #ifndef SK_ADDR_CHEAT
  800. /* Compute hash value of address. */
  801. HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
  802. /* Add bit to InexactFilter. */
  803. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
  804. 1 << (HashBit % 8);
  805. #else /* SK_ADDR_CHEAT */
  806. /* Set all bits in InexactFilter. */
  807. for (i = 0; i < 8; i++) {
  808. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
  809. }
  810. #endif /* SK_ADDR_CHEAT */
  811. }
  812. for (Inexact = 0, i = 0; i < 8; i++) {
  813. Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
  814. }
  815. if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
  816. return (SK_MC_FILTERING_EXACT);
  817. }
  818. else {
  819. return (SK_MC_FILTERING_INEXACT);
  820. }
  821. } /* SkAddrXmacMcAdd */
  822. /******************************************************************************
  823. *
  824. * SkAddrGmacMcAdd - add a multicast address to a port
  825. *
  826. * Description:
  827. * This routine enables reception for a given address on the given port.
  828. *
  829. * Notes:
  830. * The return code is only valid for SK_PROM_MODE_NONE.
  831. *
  832. * Context:
  833. * runtime, pageable
  834. * may be called after SK_INIT_DATA
  835. *
  836. * Returns:
  837. * SK_MC_FILTERING_INEXACT
  838. * SK_MC_ILLEGAL_ADDRESS
  839. */
  840. int SkAddrGmacMcAdd(
  841. SK_AC *pAC, /* adapter context */
  842. SK_IOC IoC, /* I/O context */
  843. SK_U32 PortNumber, /* Port Number */
  844. SK_MAC_ADDR *pMc, /* multicast address to be added */
  845. int Flags) /* permanent/non-permanent */
  846. {
  847. int i;
  848. #ifndef SK_ADDR_CHEAT
  849. SK_U32 HashBit;
  850. #endif /* !defined(SK_ADDR_CHEAT) */
  851. if (!(pMc->a[0] & SK_MC_BIT)) {
  852. /* Hashing only possible with multicast addresses. */
  853. return (SK_MC_ILLEGAL_ADDRESS);
  854. }
  855. #ifndef SK_ADDR_CHEAT
  856. /* Compute hash value of address. */
  857. HashBit = SkGmacMcHash(&pMc->a[0]);
  858. if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
  859. /* Add bit to InexactRlmtFilter. */
  860. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
  861. 1 << (HashBit % 8);
  862. /* Copy bit to InexactFilter. */
  863. for (i = 0; i < 8; i++) {
  864. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
  865. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
  866. }
  867. #ifdef DEBUG
  868. SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  869. ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
  870. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
  871. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
  872. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
  873. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
  874. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
  875. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
  876. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
  877. pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
  878. #endif /* DEBUG */
  879. }
  880. else { /* not permanent => DRV */
  881. /* Add bit to InexactDrvFilter. */
  882. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
  883. 1 << (HashBit % 8);
  884. /* Copy bit to InexactFilter. */
  885. for (i = 0; i < 8; i++) {
  886. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
  887. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
  888. }
  889. #ifdef DEBUG
  890. SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  891. ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
  892. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
  893. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
  894. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
  895. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
  896. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
  897. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
  898. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
  899. pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
  900. #endif /* DEBUG */
  901. }
  902. #else /* SK_ADDR_CHEAT */
  903. /* Set all bits in InexactFilter. */
  904. for (i = 0; i < 8; i++) {
  905. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
  906. }
  907. #endif /* SK_ADDR_CHEAT */
  908. return (SK_MC_FILTERING_INEXACT);
  909. } /* SkAddrGmacMcAdd */
  910. /******************************************************************************
  911. *
  912. * SkAddrMcUpdate - update the HW MC address table and set the MAC address
  913. *
  914. * Description:
  915. * This routine enables reception of the addresses contained in a local
  916. * table for a given port.
  917. * It also programs the port's current physical MAC address.
  918. *
  919. * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
  920. * to the adapter in use. The real work is done there.
  921. *
  922. * Notes:
  923. * The return code is only valid for SK_PROM_MODE_NONE.
  924. *
  925. * Context:
  926. * runtime, pageable
  927. * may be called after SK_INIT_IO
  928. *
  929. * Returns:
  930. * SK_MC_FILTERING_EXACT
  931. * SK_MC_FILTERING_INEXACT
  932. * SK_ADDR_ILLEGAL_PORT
  933. */
  934. int SkAddrMcUpdate(
  935. SK_AC *pAC, /* adapter context */
  936. SK_IOC IoC, /* I/O context */
  937. SK_U32 PortNumber) /* Port Number */
  938. {
  939. int ReturnCode;
  940. if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
  941. return (SK_ADDR_ILLEGAL_PORT);
  942. }
  943. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
  944. ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
  945. }
  946. else {
  947. ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
  948. }
  949. return (ReturnCode);
  950. } /* SkAddrMcUpdate */
  951. /******************************************************************************
  952. *
  953. * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
  954. *
  955. * Description:
  956. * This routine enables reception of the addresses contained in a local
  957. * table for a given port.
  958. * It also programs the port's current physical MAC address.
  959. *
  960. * Notes:
  961. * The return code is only valid for SK_PROM_MODE_NONE.
  962. *
  963. * Context:
  964. * runtime, pageable
  965. * may be called after SK_INIT_IO
  966. *
  967. * Returns:
  968. * SK_MC_FILTERING_EXACT
  969. * SK_MC_FILTERING_INEXACT
  970. * SK_ADDR_ILLEGAL_PORT
  971. */
  972. int SkAddrXmacMcUpdate(
  973. SK_AC *pAC, /* adapter context */
  974. SK_IOC IoC, /* I/O context */
  975. SK_U32 PortNumber) /* Port Number */
  976. {
  977. SK_U32 i;
  978. SK_U8 Inexact;
  979. SK_U16 *OutAddr;
  980. SK_ADDR_PORT *pAPort;
  981. SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  982. ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
  983. pAPort = &pAC->Addr.Port[PortNumber];
  984. #ifdef DEBUG
  985. SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  986. ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
  987. #endif /* DEBUG */
  988. /* Start with 0 to also program the logical MAC address. */
  989. for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
  990. /* Set exact match address i on XMAC */
  991. OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
  992. XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
  993. }
  994. /* Clear other permanent exact match addresses on XMAC */
  995. if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
  996. SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
  997. SK_ADDR_LAST_MATCH_RLMT);
  998. }
  999. for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
  1000. OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
  1001. XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
  1002. }
  1003. /* Clear other non-permanent exact match addresses on XMAC */
  1004. if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
  1005. SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
  1006. SK_ADDR_LAST_MATCH_DRV);
  1007. }
  1008. for (Inexact = 0, i = 0; i < 8; i++) {
  1009. Inexact |= pAPort->InexactFilter.Bytes[i];
  1010. }
  1011. if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
  1012. /* Set all bits in 64-bit hash register. */
  1013. XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
  1014. /* Enable Hashing */
  1015. SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
  1016. }
  1017. else if (Inexact != 0) {
  1018. /* Set 64-bit hash register to InexactFilter. */
  1019. XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
  1020. /* Enable Hashing */
  1021. SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
  1022. }
  1023. else {
  1024. /* Disable Hashing */
  1025. SkMacHashing(pAC, IoC, PortNumber, SK_FALSE);
  1026. }
  1027. if (pAPort->PromMode != SK_PROM_MODE_NONE) {
  1028. (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
  1029. }
  1030. /* Set port's current physical MAC address. */
  1031. OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
  1032. XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
  1033. #ifdef xDEBUG
  1034. for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
  1035. SK_U8 InAddr8[6];
  1036. SK_U16 *InAddr;
  1037. /* Get exact match address i from port PortNumber. */
  1038. InAddr = (SK_U16 *) &InAddr8[0];
  1039. XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
  1040. SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  1041. ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
  1042. "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
  1043. i,
  1044. PortNumber,
  1045. InAddr8[0],
  1046. InAddr8[1],
  1047. InAddr8[2],
  1048. InAddr8[3],
  1049. InAddr8[4],
  1050. InAddr8[5],
  1051. pAPort->Exact[i].a[0],
  1052. pAPort->Exact[i].a[1],
  1053. pAPort->Exact[i].a[2],
  1054. pAPort->Exact[i].a[3],
  1055. pAPort->Exact[i].a[4],
  1056. pAPort->Exact[i].a[5]))
  1057. }
  1058. #endif /* DEBUG */
  1059. /* Determine return value. */
  1060. if (Inexact == 0 && pAPort->PromMode == 0) {
  1061. return (SK_MC_FILTERING_EXACT);
  1062. }
  1063. else {
  1064. return (SK_MC_FILTERING_INEXACT);
  1065. }
  1066. } /* SkAddrXmacMcUpdate */
  1067. /******************************************************************************
  1068. *
  1069. * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
  1070. *
  1071. * Description:
  1072. * This routine enables reception of the addresses contained in a local
  1073. * table for a given port.
  1074. * It also programs the port's current physical MAC address.
  1075. *
  1076. * Notes:
  1077. * The return code is only valid for SK_PROM_MODE_NONE.
  1078. *
  1079. * Context:
  1080. * runtime, pageable
  1081. * may be called after SK_INIT_IO
  1082. *
  1083. * Returns:
  1084. * SK_MC_FILTERING_EXACT
  1085. * SK_MC_FILTERING_INEXACT
  1086. * SK_ADDR_ILLEGAL_PORT
  1087. */
  1088. int SkAddrGmacMcUpdate(
  1089. SK_AC *pAC, /* adapter context */
  1090. SK_IOC IoC, /* I/O context */
  1091. SK_U32 PortNumber) /* Port Number */
  1092. {
  1093. SK_U32 i;
  1094. SK_U8 Inexact;
  1095. SK_U16 *OutAddr;
  1096. SK_ADDR_PORT *pAPort;
  1097. SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  1098. ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
  1099. pAPort = &pAC->Addr.Port[PortNumber];
  1100. #ifdef DEBUG
  1101. SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  1102. ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
  1103. #endif /* DEBUG */
  1104. for (Inexact = 0, i = 0; i < 8; i++) {
  1105. Inexact |= pAPort->InexactFilter.Bytes[i];
  1106. }
  1107. /* Set 64-bit hash register to InexactFilter. */
  1108. GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
  1109. &pAPort->InexactFilter.Bytes[0]);
  1110. if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
  1111. /* Set all bits in 64-bit hash register. */
  1112. GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
  1113. /* Enable Hashing */
  1114. SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
  1115. }
  1116. else {
  1117. /* Enable Hashing. */
  1118. SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
  1119. }
  1120. if (pAPort->PromMode != SK_PROM_MODE_NONE) {
  1121. (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
  1122. }
  1123. /* Set port's current physical MAC address. */
  1124. OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
  1125. GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
  1126. /* Set port's current logical MAC address. */
  1127. OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
  1128. GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
  1129. #ifdef DEBUG
  1130. SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  1131. ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
  1132. pAPort->Exact[0].a[0],
  1133. pAPort->Exact[0].a[1],
  1134. pAPort->Exact[0].a[2],
  1135. pAPort->Exact[0].a[3],
  1136. pAPort->Exact[0].a[4],
  1137. pAPort->Exact[0].a[5]))
  1138. SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  1139. ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
  1140. pAPort->CurrentMacAddress.a[0],
  1141. pAPort->CurrentMacAddress.a[1],
  1142. pAPort->CurrentMacAddress.a[2],
  1143. pAPort->CurrentMacAddress.a[3],
  1144. pAPort->CurrentMacAddress.a[4],
  1145. pAPort->CurrentMacAddress.a[5]))
  1146. #endif /* DEBUG */
  1147. /* Determine return value. */
  1148. if (Inexact == 0 && pAPort->PromMode == 0) {
  1149. return (SK_MC_FILTERING_EXACT);
  1150. }
  1151. else {
  1152. return (SK_MC_FILTERING_INEXACT);
  1153. }
  1154. } /* SkAddrGmacMcUpdate */
  1155. /******************************************************************************
  1156. *
  1157. * SkAddrOverride - override a port's MAC address
  1158. *
  1159. * Description:
  1160. * This routine overrides the MAC address of one port.
  1161. *
  1162. * Context:
  1163. * runtime, pageable
  1164. * may be called after SK_INIT_IO
  1165. *
  1166. * Returns:
  1167. * SK_ADDR_SUCCESS if successful.
  1168. * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
  1169. * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
  1170. * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
  1171. */
  1172. int SkAddrOverride(
  1173. SK_AC *pAC, /* adapter context */
  1174. SK_IOC IoC, /* I/O context */
  1175. SK_U32 PortNumber, /* Port Number */
  1176. SK_MAC_ADDR *pNewAddr, /* new MAC address */
  1177. int Flags) /* logical/physical MAC address */
  1178. {
  1179. SK_EVPARA Para;
  1180. SK_U32 NetNumber;
  1181. SK_U32 i;
  1182. SK_U16 *OutAddr;
  1183. NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
  1184. if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
  1185. return (SK_ADDR_ILLEGAL_PORT);
  1186. }
  1187. if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
  1188. return (SK_ADDR_MULTICAST_ADDRESS);
  1189. }
  1190. if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
  1191. return (SK_ADDR_TOO_EARLY);
  1192. }
  1193. if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
  1194. /* Parameter *pNewAddr is ignored. */
  1195. for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
  1196. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  1197. return (SK_ADDR_TOO_EARLY);
  1198. }
  1199. }
  1200. /* Set PortNumber to number of net's active port. */
  1201. PortNumber = pAC->Rlmt.Net[NetNumber].
  1202. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
  1203. pAC->Addr.Port[PortNumber].Exact[0] =
  1204. pAC->Addr.Net[NetNumber].CurrentMacAddress;
  1205. /* Write address to first exact match entry of active port. */
  1206. (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
  1207. }
  1208. else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
  1209. /* Deactivate logical MAC address. */
  1210. /* Parameter *pNewAddr is ignored. */
  1211. for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
  1212. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  1213. return (SK_ADDR_TOO_EARLY);
  1214. }
  1215. }
  1216. /* Set PortNumber to number of net's active port. */
  1217. PortNumber = pAC->Rlmt.Net[NetNumber].
  1218. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
  1219. for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
  1220. pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
  1221. }
  1222. /* Write address to first exact match entry of active port. */
  1223. (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
  1224. }
  1225. else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
  1226. if (SK_ADDR_EQUAL(pNewAddr->a,
  1227. pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
  1228. return (SK_ADDR_DUPLICATE_ADDRESS);
  1229. }
  1230. for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
  1231. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  1232. return (SK_ADDR_TOO_EARLY);
  1233. }
  1234. if (SK_ADDR_EQUAL(pNewAddr->a,
  1235. pAC->Addr.Port[i].CurrentMacAddress.a)) {
  1236. if (i == PortNumber) {
  1237. return (SK_ADDR_SUCCESS);
  1238. }
  1239. else {
  1240. return (SK_ADDR_DUPLICATE_ADDRESS);
  1241. }
  1242. }
  1243. }
  1244. pAC->Addr.Port[PortNumber].PreviousMacAddress =
  1245. pAC->Addr.Port[PortNumber].CurrentMacAddress;
  1246. pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
  1247. /* Change port's physical MAC address. */
  1248. OutAddr = (SK_U16 *) pNewAddr;
  1249. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
  1250. XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
  1251. }
  1252. else {
  1253. GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
  1254. }
  1255. /* Report address change to RLMT. */
  1256. Para.Para32[0] = PortNumber;
  1257. Para.Para32[0] = -1;
  1258. SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
  1259. }
  1260. else { /* Logical MAC address. */
  1261. if (SK_ADDR_EQUAL(pNewAddr->a,
  1262. pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
  1263. return (SK_ADDR_SUCCESS);
  1264. }
  1265. for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
  1266. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  1267. return (SK_ADDR_TOO_EARLY);
  1268. }
  1269. if (SK_ADDR_EQUAL(pNewAddr->a,
  1270. pAC->Addr.Port[i].CurrentMacAddress.a)) {
  1271. return (SK_ADDR_DUPLICATE_ADDRESS);
  1272. }
  1273. }
  1274. /*
  1275. * In case that the physical and the logical MAC addresses are equal
  1276. * we must also change the physical MAC address here.
  1277. * In this case we have an adapter which initially was programmed with
  1278. * two identical MAC addresses.
  1279. */
  1280. if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
  1281. pAC->Addr.Port[PortNumber].Exact[0].a)) {
  1282. pAC->Addr.Port[PortNumber].PreviousMacAddress =
  1283. pAC->Addr.Port[PortNumber].CurrentMacAddress;
  1284. pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
  1285. /* Report address change to RLMT. */
  1286. Para.Para32[0] = PortNumber;
  1287. Para.Para32[0] = -1;
  1288. SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
  1289. }
  1290. /* Set PortNumber to number of net's active port. */
  1291. PortNumber = pAC->Rlmt.Net[NetNumber].
  1292. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
  1293. pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
  1294. pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
  1295. #ifdef DEBUG
  1296. SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  1297. ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
  1298. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
  1299. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
  1300. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
  1301. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
  1302. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
  1303. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
  1304. SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
  1305. ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
  1306. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
  1307. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
  1308. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
  1309. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
  1310. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
  1311. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
  1312. #endif /* DEBUG */
  1313. /* Write address to first exact match entry of active port. */
  1314. (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
  1315. }
  1316. return (SK_ADDR_SUCCESS);
  1317. } /* SkAddrOverride */
  1318. /******************************************************************************
  1319. *
  1320. * SkAddrPromiscuousChange - set promiscuous mode for given port
  1321. *
  1322. * Description:
  1323. * This routine manages promiscuous mode:
  1324. * - none
  1325. * - all LLC frames
  1326. * - all MC frames
  1327. *
  1328. * It calls either SkAddrXmacPromiscuousChange or
  1329. * SkAddrGmacPromiscuousChange, according to the adapter in use.
  1330. * The real work is done there.
  1331. *
  1332. * Context:
  1333. * runtime, pageable
  1334. * may be called after SK_INIT_IO
  1335. *
  1336. * Returns:
  1337. * SK_ADDR_SUCCESS
  1338. * SK_ADDR_ILLEGAL_PORT
  1339. */
  1340. int SkAddrPromiscuousChange(
  1341. SK_AC *pAC, /* adapter context */
  1342. SK_IOC IoC, /* I/O context */
  1343. SK_U32 PortNumber, /* port whose promiscuous mode changes */
  1344. int NewPromMode) /* new promiscuous mode */
  1345. {
  1346. int ReturnCode;
  1347. if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
  1348. return (SK_ADDR_ILLEGAL_PORT);
  1349. }
  1350. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
  1351. ReturnCode = SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
  1352. }
  1353. else {
  1354. ReturnCode = SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
  1355. }
  1356. return (ReturnCode);
  1357. } /* SkAddrPromiscuousChange */
  1358. /******************************************************************************
  1359. *
  1360. * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
  1361. *
  1362. * Description:
  1363. * This routine manages promiscuous mode:
  1364. * - none
  1365. * - all LLC frames
  1366. * - all MC frames
  1367. *
  1368. * Context:
  1369. * runtime, pageable
  1370. * may be called after SK_INIT_IO
  1371. *
  1372. * Returns:
  1373. * SK_ADDR_SUCCESS
  1374. * SK_ADDR_ILLEGAL_PORT
  1375. */
  1376. int SkAddrXmacPromiscuousChange(
  1377. SK_AC *pAC, /* adapter context */
  1378. SK_IOC IoC, /* I/O context */
  1379. SK_U32 PortNumber, /* port whose promiscuous mode changes */
  1380. int NewPromMode) /* new promiscuous mode */
  1381. {
  1382. int i;
  1383. SK_BOOL InexactModeBit;
  1384. SK_U8 Inexact;
  1385. SK_U8 HwInexact;
  1386. SK_FILTER64 HwInexactFilter;
  1387. SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
  1388. int CurPromMode = SK_PROM_MODE_NONE;
  1389. /* Read CurPromMode from Hardware. */
  1390. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  1391. if ((LoMode & XM_MD_ENA_PROM) != 0) {
  1392. /* Promiscuous mode! */
  1393. CurPromMode |= SK_PROM_MODE_LLC;
  1394. }
  1395. for (Inexact = 0xFF, i = 0; i < 8; i++) {
  1396. Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
  1397. }
  1398. if (Inexact == 0xFF) {
  1399. CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
  1400. }
  1401. else {
  1402. /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
  1403. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  1404. InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
  1405. /* Read 64-bit hash register from XMAC */
  1406. XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
  1407. for (HwInexact = 0xFF, i = 0; i < 8; i++) {
  1408. HwInexact &= HwInexactFilter.Bytes[i];
  1409. }
  1410. if (InexactModeBit && (HwInexact == 0xFF)) {
  1411. CurPromMode |= SK_PROM_MODE_ALL_MC;
  1412. }
  1413. }
  1414. pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
  1415. if (NewPromMode == CurPromMode) {
  1416. return (SK_ADDR_SUCCESS);
  1417. }
  1418. if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
  1419. !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
  1420. /* Set all bits in 64-bit hash register. */
  1421. XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
  1422. /* Enable Hashing */
  1423. SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
  1424. }
  1425. else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
  1426. !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
  1427. for (Inexact = 0, i = 0; i < 8; i++) {
  1428. Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
  1429. }
  1430. if (Inexact == 0) {
  1431. /* Disable Hashing */
  1432. SkMacHashing(pAC, IoC, PortNumber, SK_FALSE);
  1433. }
  1434. else {
  1435. /* Set 64-bit hash register to InexactFilter. */
  1436. XM_OUTHASH(IoC, PortNumber, XM_HSM,
  1437. &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
  1438. /* Enable Hashing */
  1439. SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
  1440. }
  1441. }
  1442. if ((NewPromMode & SK_PROM_MODE_LLC) &&
  1443. !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
  1444. /* Set the MAC in Promiscuous Mode */
  1445. SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE);
  1446. }
  1447. else if ((CurPromMode & SK_PROM_MODE_LLC) &&
  1448. !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
  1449. /* Clear Promiscuous Mode */
  1450. SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE);
  1451. }
  1452. return (SK_ADDR_SUCCESS);
  1453. } /* SkAddrXmacPromiscuousChange */
  1454. /******************************************************************************
  1455. *
  1456. * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
  1457. *
  1458. * Description:
  1459. * This routine manages promiscuous mode:
  1460. * - none
  1461. * - all LLC frames
  1462. * - all MC frames
  1463. *
  1464. * Context:
  1465. * runtime, pageable
  1466. * may be called after SK_INIT_IO
  1467. *
  1468. * Returns:
  1469. * SK_ADDR_SUCCESS
  1470. * SK_ADDR_ILLEGAL_PORT
  1471. */
  1472. int SkAddrGmacPromiscuousChange(
  1473. SK_AC *pAC, /* adapter context */
  1474. SK_IOC IoC, /* I/O context */
  1475. SK_U32 PortNumber, /* port whose promiscuous mode changes */
  1476. int NewPromMode) /* new promiscuous mode */
  1477. {
  1478. SK_U16 ReceiveControl; /* GMAC Receive Control Register */
  1479. int CurPromMode = SK_PROM_MODE_NONE;
  1480. /* Read CurPromMode from Hardware. */
  1481. GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
  1482. if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
  1483. /* Promiscuous mode! */
  1484. CurPromMode |= SK_PROM_MODE_LLC;
  1485. }
  1486. if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
  1487. /* All Multicast mode! */
  1488. CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
  1489. }
  1490. pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
  1491. if (NewPromMode == CurPromMode) {
  1492. return (SK_ADDR_SUCCESS);
  1493. }
  1494. if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
  1495. !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */
  1496. /* Set all bits in 64-bit hash register. */
  1497. GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
  1498. /* Enable Hashing */
  1499. SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
  1500. }
  1501. if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
  1502. !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */
  1503. /* Set 64-bit hash register to InexactFilter. */
  1504. GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
  1505. &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
  1506. /* Enable Hashing. */
  1507. SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
  1508. }
  1509. if ((NewPromMode & SK_PROM_MODE_LLC) &&
  1510. !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
  1511. /* Set the MAC to Promiscuous Mode. */
  1512. SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE);
  1513. }
  1514. else if ((CurPromMode & SK_PROM_MODE_LLC) &&
  1515. !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */
  1516. /* Clear Promiscuous Mode. */
  1517. SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE);
  1518. }
  1519. return (SK_ADDR_SUCCESS);
  1520. } /* SkAddrGmacPromiscuousChange */
  1521. /******************************************************************************
  1522. *
  1523. * SkAddrSwap - swap address info
  1524. *
  1525. * Description:
  1526. * This routine swaps address info of two ports.
  1527. *
  1528. * Context:
  1529. * runtime, pageable
  1530. * may be called after SK_INIT_IO
  1531. *
  1532. * Returns:
  1533. * SK_ADDR_SUCCESS
  1534. * SK_ADDR_ILLEGAL_PORT
  1535. */
  1536. int SkAddrSwap(
  1537. SK_AC *pAC, /* adapter context */
  1538. SK_IOC IoC, /* I/O context */
  1539. SK_U32 FromPortNumber, /* Port1 Index */
  1540. SK_U32 ToPortNumber) /* Port2 Index */
  1541. {
  1542. int i;
  1543. SK_U8 Byte;
  1544. SK_MAC_ADDR MacAddr;
  1545. SK_U32 DWord;
  1546. if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
  1547. return (SK_ADDR_ILLEGAL_PORT);
  1548. }
  1549. if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
  1550. return (SK_ADDR_ILLEGAL_PORT);
  1551. }
  1552. if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
  1553. return (SK_ADDR_ILLEGAL_PORT);
  1554. }
  1555. /*
  1556. * Swap:
  1557. * - Exact Match Entries (GEnesis and Yukon)
  1558. * Yukon uses first entry for the logical MAC
  1559. * address (stored in the second GMAC register).
  1560. * - FirstExactMatchRlmt (GEnesis only)
  1561. * - NextExactMatchRlmt (GEnesis only)
  1562. * - FirstExactMatchDrv (GEnesis only)
  1563. * - NextExactMatchDrv (GEnesis only)
  1564. * - 64-bit filter (InexactFilter)
  1565. * - Promiscuous Mode
  1566. * of ports.
  1567. */
  1568. for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
  1569. MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
  1570. pAC->Addr.Port[FromPortNumber].Exact[i] =
  1571. pAC->Addr.Port[ToPortNumber].Exact[i];
  1572. pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
  1573. }
  1574. for (i = 0; i < 8; i++) {
  1575. Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
  1576. pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
  1577. pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
  1578. pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
  1579. }
  1580. i = pAC->Addr.Port[FromPortNumber].PromMode;
  1581. pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
  1582. pAC->Addr.Port[ToPortNumber].PromMode = i;
  1583. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
  1584. DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
  1585. pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
  1586. pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
  1587. pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
  1588. DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
  1589. pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
  1590. pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
  1591. pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
  1592. DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
  1593. pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
  1594. pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
  1595. pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
  1596. DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
  1597. pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
  1598. pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
  1599. pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
  1600. }
  1601. /* CAUTION: Solution works if only ports of one adapter are in use. */
  1602. for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
  1603. Net->NetNumber].NumPorts; i++) {
  1604. if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
  1605. Port[i]->PortNumber == ToPortNumber) {
  1606. pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
  1607. ActivePort = i;
  1608. /* 20001207 RA: Was "ToPortNumber;". */
  1609. }
  1610. }
  1611. (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
  1612. (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
  1613. return (SK_ADDR_SUCCESS);
  1614. } /* SkAddrSwap */
  1615. #ifdef __cplusplus
  1616. }
  1617. #endif /* __cplusplus */