skaddr.c 48 KB

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