skaddr.c 49 KB

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