etc47xx.c
上传用户:yuanda199
上传日期:2022-06-26
资源大小:412k
文件大小:36k
源码类别:

VxWorks

开发平台:

C/C++

  1. /*
  2.     EXTERNAL SOURCE RELEASE on 12/03/2001 3.0 - Subject to change without notice.
  3. */
  4. /*
  5.     Copyright 2001, Broadcom Corporation
  6.     All Rights Reserved.
  7.     
  8.     This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
  9.     the contents of this file may not be disclosed to third parties, copied or
  10.     duplicated in any form, in whole or in part, without the prior written
  11.     permission of Broadcom Corporation.
  12. */
  13. /*
  14.  * Broadcom Home Networking Division 10/100 Mbit/s Ethernet core.
  15.  *
  16.  * This file implements the chip-specific routines
  17.  * for Broadcom HNBU Sonics SiliconBackplane enet cores.
  18.  *
  19.  * Copyright(c) 2001 Broadcom, Inc.
  20.  * $Id: etc47xx.c,v 1.1 Broadcom SDK $
  21.  */
  22. #include <osl.h>
  23. #include <bcmendian.h>
  24. #include <ethernet.h>
  25. #include <hnddma.h>
  26. #include <et_dbg.h>
  27. #include <sbconfig.h>
  28. #include <sbutils.h>
  29. #include <bcmenet47xx.h>
  30. #include <bcmutils.h>
  31. #ifndef BROADCOM_BSP
  32. #include <bcmnvram.h>
  33. #endif
  34. #include <et_export.h> /* for et_phyxx() routines */
  35. struct bcm4xxx; /* forward declaration */
  36. #define ch_t struct bcm4xxx
  37. #include <etc.h>
  38. #ifdef BROADCOM_BSP
  39. STATUS (* _func_etEnetAddrGet)
  40.     (char *dev,int unit,unsigned char *pMac) = NULL;
  41. #else
  42. #define NVRAM_GET(name, vars) nvram_get(name)
  43. #endif
  44. /* private chip state */
  45. struct bcm4xxx {
  46. void  *et; /* pointer to et private state */
  47. etc_info_t *etc; /* pointer to etc public state */
  48. bcmenetregs_t *regs; /* pointer to chip registers */
  49. void  *dev; /* device handle */
  50. void  *etphy; /* pointer to et for shared mdc/mdio contortion */
  51. uint32 intstatus; /* saved interrupt condition bits */
  52. uint32 intmask; /* current software interrupt mask */
  53. void  *di; /* dma engine software state */
  54. bool mibgood; /* true once mib registers have been cleared */
  55.         void            *sbh;           /* sb utils handle */
  56.         char            *vars;          /* sprom name=value */
  57.         int             vars_size;
  58.         void            *robo;          /* robo utils handle */
  59. };
  60. static struct bcm4xxx *mpCh[2];
  61. /* local prototypes */
  62. static bool chipid(uint vendor, uint device);
  63. static void *chipattach(etc_info_t *etc, void *dev, void *regsva);
  64. static void chipdetach(ch_t *ch);
  65. static void chipreset(ch_t *ch);
  66. static void chipinit(ch_t *ch, bool full);
  67. static void chiptx(ch_t *ch, void *p);
  68. static void *chiprx(ch_t *ch);
  69. static void chiprxfill(ch_t *ch);
  70. static int chipgetintrevents(ch_t *ch);
  71. static bool chiperrors(ch_t *ch);
  72. static void chipintrson(ch_t *ch);
  73. static void chipintrsoff(ch_t *ch);
  74. static void chiptxreclaim(ch_t *ch, bool all);
  75. static void chiprxreclaim(ch_t *ch);
  76. static void chipstatsupd(ch_t *ch);
  77. static void chipenablepme(ch_t *ch);
  78. static void chipdisablepme(ch_t *ch);
  79. static void chipphyreset(ch_t *ch, uint phyaddr);
  80. static void chipphyinit(ch_t *ch, uint phyaddr);
  81. static uint16 chipphyrd(ch_t *ch, uint phyaddr, uint reg);
  82. static void chipdump(ch_t *ch, char *buf);
  83. static void chiplongname(ch_t *ch, char *buf, uint bufsize);
  84. static void chipduplexupd(ch_t *ch);
  85. static void chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex);
  86. static void chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
  87. static void chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
  88. static void chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
  89. static void chipphyforce(struct bcm4xxx *ch, uint phyaddr);
  90. static void chipphyadvertise(struct bcm4xxx *ch, uint phyaddr);
  91. static char *chipdumpregs(struct bcm4xxx *ch, bcmenetregs_t *regs, char *buf);
  92. /* chip interrupt bit error summary */
  93. #define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)
  94. #define DEF_INTMASK (I_XI | I_RI | I_ERRORS)
  95. struct chops bcm47xx_et_chops = {
  96. chipid,
  97. chipattach,
  98. chipdetach,
  99. chipreset,
  100. chipinit,
  101. chiptx,
  102. chiprx,
  103. chiprxfill,
  104. chipgetintrevents,
  105. chiperrors,
  106. chipintrson,
  107. chipintrsoff,
  108. chiptxreclaim,
  109. chiprxreclaim,
  110. chipstatsupd,
  111.         chipenablepme,
  112.         chipdisablepme,
  113. chipphyreset,
  114. chipphyrd,
  115. chipphywr,
  116. chipdump,
  117. chiplongname,
  118. chipduplexupd
  119. };
  120. static uint devices[] = {
  121. BCM47XX_ENET_ID,
  122. 0x0000 };
  123. static bool
  124. chipid(uint vendor, uint device)
  125. {
  126. int i;
  127. if (vendor != VENDOR_BROADCOM)
  128. return (FALSE);
  129. for (i = 0; devices[i]; i++) {
  130. if (device == devices[i])
  131. return (TRUE);
  132. }
  133. return (FALSE);
  134. }
  135. static void*
  136. chipattach(etc_info_t *etc, void *dev, void *regsva)
  137. {
  138. struct bcm4xxx *ch;
  139. bcmenetregs_t *regs;
  140. char ourname[8];
  141. uint ddoffset, dataoffset;
  142. #ifndef BROADCOM_BSP
  143. char name[16];
  144. char *var;
  145. #endif
  146. ET_TRACE(("et%d: chipattach: regsva 0x%xn", etc->unit, (uint)regsva));
  147. if ((ch = (struct bcm4xxx*) MALLOC(sizeof (struct bcm4xxx))) == NULL) {
  148. ET_ERROR(("et%d: chipattach: malloc failed!n", etc->unit));
  149. return (NULL);
  150. }
  151. bzero((char*)ch, sizeof (struct bcm4xxx));
  152.         ch->etc = etc;
  153.         ch->et = etc->et;
  154.         regs = (bcmenetregs_t*) regsva;
  155.         ch->regs = regs;
  156.         ch->dev = dev;
  157.         /* get sb handle */
  158.         if ((ch->sbh = sb_attach(etc->deviceid, ch->dev, regsva, &ch->vars, &ch->vars_size)) == NULL) {
  159.                 ET_ERROR(("et%d: chipattach: sb_attach errorn", etc->unit));
  160.                 goto fail;
  161.         }
  162.         ASSERT(sb_coreid(ch->sbh) == SB_ENET);
  163.         etc->chip = sb_chip(ch->sbh);
  164.         etc->chiprev = sb_chiprev(ch->sbh);
  165.         etc->nicmode = !(sb_bus(ch->sbh) == SB_BUS);
  166.         etc->coreunit = sb_coreunit(ch->sbh);
  167.         /* configure pci core */
  168.         sb_pci_setup(ch->sbh, &ddoffset, (1 << sb_coreidx(ch->sbh)));
  169.         dataoffset = ddoffset;
  170. #if defined(__mips__) && defined(IL_BIGENDIAN)
  171.         /* use sdram swapped region for data buffers but not dma descriptors */
  172.         /* XXX this assumes that we are running on a 47xx mips with a swap window at 0x1 000000 */
  173.         dataoffset |= SB_SDRAM_SWAPPED;
  174. #endif
  175. /* dma attach */
  176. if ((ch->di = dma_attach(etc->et, dev, ourname, &regs->dmaregs,
  177.             NTXD, NRXD, RXBUFSZ, NRXBUFPOST, HWRXOFF, ddoffset, dataoffset,
  178.             &et_msg_level)) == NULL) {
  179. ET_ERROR(("et%d: chipattach: dma_attach failedn", etc->unit));
  180. goto fail;
  181. }
  182. etc->txavail = (uint*) dma_getvar(ch->di, "&txavail");
  183. /* get our local ether addr */
  184. #ifdef BROADCOM_BSP
  185.         if (_func_etEnetAddrGet == NULL || _func_etEnetAddrGet ("et", etc->unit, 
  186.             (unsigned char *) &etc->perm_etheraddr) != OK)
  187.             {
  188.     ET_ERROR(("et%d: chipattach: MAC address not foundn", etc->unit));
  189.             goto fail;
  190.             }
  191. #else
  192. sprintf(name, "et%dmacaddr", etc->coreunit);
  193. if ((var = NVRAM_GET(name, ch->vars)) == NULL) {
  194. ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not foundn", etc->unit, name));
  195. goto fail;
  196. }
  197. bcm_ether_atoe(var, (uchar*) &etc->perm_etheraddr);
  198. #endif  /* BROADCOM_BSP */
  199. if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) {
  200. #ifndef BROADCOM_BSP
  201. ET_ERROR(("et%d: chipattach: invalid format: %s=%sn", etc->unit, name, var));
  202. #endif
  203. goto fail;
  204. }
  205. bcopy((char*)&etc->perm_etheraddr, (char*)&etc->cur_etheraddr, ETHER_ADDR_LEN);
  206. /*
  207.  * Rather than scan the mdio space looking for phys that
  208.  * respond and then guessing which one is ours and which
  209.  * might be used in the dualphy case by another emac,
  210.  * we instead explicitly require the environment var
  211.  * "et<coreunit>phyaddr=<val>".
  212.  */
  213. /* get our phyaddr value */
  214. #ifdef BROADCOM_BSP
  215.         if (_func_etEnetAddrGet == NULL || _func_etEnetAddrGet ("phy", etc->unit, 
  216.             (unsigned char *) &etc->phyaddr) != OK)
  217.             {
  218.     ET_ERROR(("et%d: chipattach: PHY address not foundn", etc->unit));
  219.             goto fail;
  220.             }
  221. #else
  222. sprintf(name, "et%dphyaddr", etc->coreunit);
  223. if ((var = NVRAM_GET(name, ch->vars)) == NULL) {
  224. ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not foundn", etc->unit, name));
  225. goto fail;
  226. }
  227. etc->phyaddr = bcm_atoi(var);
  228. #endif
  229. /* special 5bit phyaddr value indicating no phy present */
  230. if (etc->phyaddr == PHY_NONE) {
  231. ET_ERROR(("et%d: chipattach: phy not presentn", etc->unit));
  232. goto fail;
  233. }
  234. /* get our mdc/mdio port number */
  235. #ifdef BROADCOM_BSP
  236.         if (_func_etEnetAddrGet == NULL || _func_etEnetAddrGet ("mdc", etc->unit, 
  237.             (unsigned char *) &etc->mdcport) != OK)
  238.             {
  239.     ET_ERROR(("et%d: chipattach: MDC port not foundn", etc->unit));
  240.             goto fail;
  241.             }
  242. #else
  243. sprintf(name, "et%dmdcport", etc->coreunit);
  244. if ((var = NVRAM_GET(name, ch->vars)) == NULL) {
  245. ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not foundn", etc->unit, name));
  246. goto fail;
  247. }
  248. etc->mdcport = bcm_atoi(var);
  249. #endif
  250. /* reset the enet core */
  251. chipreset(ch);
  252. /* set default sofware intmask */
  253. ch->intmask = DEF_INTMASK;
  254. /*
  255.  * For the 5222 dual phy shared mdio contortion, our phy is
  256.  * on someone elses mdio pins.  This other enet enet
  257.  * may not yet be attached so we must defer the et_phyfind().
  258.  */
  259. /* if local phy: reset it once now */
  260. if (etc->mdcport == etc->coreunit)
  261. chipphyreset(ch, etc->phyaddr);
  262. mpCh[etc->unit] = ch;
  263. return ((void*) ch);
  264. fail:
  265. chipdetach(ch);
  266. return (NULL);
  267. }
  268. static void
  269. chipdetach(struct bcm4xxx *ch)
  270. {
  271. if (ch == NULL)
  272. return;
  273. ET_TRACE(("et%d: chipdetachn", ch->etc->unit));
  274. /* put the core back into reset */
  275.         sb_core_disable(ch->sbh, 0);
  276.         /* free dma state */
  277.         dma_detach(ch->di);
  278.         ch->di = NULL;
  279.         /* free sb handle */
  280.         sb_detach(ch->sbh);
  281.         ch->sbh = NULL;
  282.         /* free vars */
  283.         if (ch->vars)
  284.                 MFREE(ch->vars, ch->vars_size);
  285.         /* free chip private state */
  286.         MFREE(ch, sizeof (struct bcm4xxx));
  287. }
  288. static void
  289. chiplongname(struct bcm4xxx *ch, char *buf, uint bufsize)
  290. {
  291. char *s = "Broadcom BCM47xx 10/100 Mbps Ethernet Controller";
  292. strncpy(buf, s, bufsize);
  293. buf[bufsize - 1] = '';
  294. }
  295. static void
  296. chipdump(struct bcm4xxx *ch, char *buf)
  297. {
  298. buf += sprintf(buf, "regs 0x%x etphy 0x%x ch->intstatus 0x%x intmask 0x%x n",
  299. (uint)ch->regs, (uint)ch->etphy, ch->intstatus, ch->intmask);
  300. buf += sprintf(buf, "n");
  301. /* dma engine state */
  302. buf = dma_dump(ch->di, buf);
  303. buf += sprintf(buf, "n");
  304. /* registers */
  305. buf = chipdumpregs(ch, ch->regs, buf);
  306. }
  307. #define PRREG(name) buf += sprintf(buf, #name " 0x%x ", R_REG(&regs->name))
  308. #define PRMIBREG(name) buf += sprintf(buf, #name " 0x%x ", R_REG(&regs->mib.name))
  309. static char*
  310. chipdumpregs(struct bcm4xxx *ch, bcmenetregs_t *regs, char *buf)
  311. {
  312. uint phyaddr;
  313. phyaddr = ch->etc->phyaddr;
  314. PRREG(devcontrol); PRREG(biststatus); PRREG(wakeuplength);
  315. buf += sprintf(buf, "n");
  316. PRREG(intstatus); PRREG(intmask); PRREG(gptimer);
  317. buf += sprintf(buf, "n");
  318. PRREG(emactxmaxburstlen); PRREG(emacrxmaxburstlen);
  319. PRREG(emaccontrol); PRREG(emacflowcontrol);
  320. buf += sprintf(buf, "n");
  321. PRREG(intrecvlazy);
  322. buf += sprintf(buf, "n");
  323. /* emac registers */
  324. PRREG(rxconfig); PRREG(rxmaxlength); PRREG(txmaxlength);
  325. buf += sprintf(buf, "n");
  326. PRREG(mdiocontrol); PRREG(camcontrol); PRREG(enetcontrol);
  327. buf += sprintf(buf, "n");
  328. PRREG(txcontrol); PRREG(txwatermark); PRREG(mibcontrol);
  329. buf += sprintf(buf, "n");
  330. /* mib registers */
  331. PRMIBREG(tx_good_octets); PRMIBREG(tx_good_pkts); PRMIBREG(tx_octets); PRMIBREG(tx_pkts);
  332. buf += sprintf(buf, "n");
  333. PRMIBREG(tx_broadcast_pkts); PRMIBREG(tx_multicast_pkts);
  334. buf += sprintf(buf, "n");
  335. PRMIBREG(tx_jabber_pkts); PRMIBREG(tx_oversize_pkts); PRMIBREG(tx_fragment_pkts);
  336. buf += sprintf(buf, "n");
  337. PRMIBREG(tx_underruns); PRMIBREG(tx_total_cols); PRMIBREG(tx_single_cols);
  338. buf += sprintf(buf, "n");
  339. PRMIBREG(tx_multiple_cols); PRMIBREG(tx_excessive_cols); PRMIBREG(tx_late_cols);
  340. buf += sprintf(buf, "n");
  341. PRMIBREG(tx_defered); PRMIBREG(tx_carrier_lost); PRMIBREG(tx_pause_pkts);
  342. buf += sprintf(buf, "n");
  343. PRMIBREG(rx_good_octets); PRMIBREG(rx_good_pkts); PRMIBREG(rx_octets); PRMIBREG(rx_pkts);
  344. buf += sprintf(buf, "n");
  345. PRMIBREG(rx_broadcast_pkts); PRMIBREG(rx_multicast_pkts);
  346. buf += sprintf(buf, "n");
  347. PRMIBREG(rx_jabber_pkts); PRMIBREG(rx_oversize_pkts); PRMIBREG(rx_fragment_pkts);
  348. buf += sprintf(buf, "n");
  349. PRMIBREG(rx_missed_pkts); PRMIBREG(rx_crc_align_errs); PRMIBREG(rx_undersize);
  350. buf += sprintf(buf, "n");
  351. PRMIBREG(rx_crc_errs); PRMIBREG(rx_align_errs); PRMIBREG(rx_symbol_errs);
  352. buf += sprintf(buf, "n");
  353. PRMIBREG(rx_pause_pkts); PRMIBREG(rx_nonpause_pkts);
  354. buf += sprintf(buf, "n");
  355. buf += sprintf(buf, "n");
  356. if (phyaddr != PHY_NOMDC) {
  357. /* print a few interesting phy registers */
  358. buf += sprintf(buf, "phy0 0x%x phy1 0x%x phy2 0x%x phy3 0x%xn",
  359.        chipphyrd(ch, phyaddr, 0),
  360.        chipphyrd(ch, phyaddr, 1),
  361.        chipphyrd(ch, phyaddr, 2),
  362.        chipphyrd(ch, phyaddr, 3));
  363. buf += sprintf(buf, "phy4 0x%x phy5 0x%x phy24 0x%x phy25 0x%xn",
  364.        chipphyrd(ch, phyaddr, 4),
  365.        chipphyrd(ch, phyaddr, 5),
  366.        chipphyrd(ch, phyaddr, 24),
  367.        chipphyrd(ch, phyaddr, 25));
  368. }
  369. return (buf);
  370. }
  371. static void
  372. chipreset(struct bcm4xxx *ch)
  373. {
  374. bcmenetregs_t *regs;
  375.         uint32 offset;
  376. ET_TRACE(("et%d: chipresetn", ch->etc->unit));
  377. regs = ch->regs;
  378.         if (!sb_iscoreup(ch->sbh)) {
  379.                 if (!ch->etc->nicmode)
  380.                         sb_pci_setup(ch->sbh, &offset, (1 << sb_coreidx(ch->sbh)));
  381.                 /* power on reset: reset the enet core */
  382.                 sb_core_reset(ch->sbh, 0);
  383.                 goto chipinreset;
  384.         }
  385. /* read counters before resetting the chip */
  386. if (ch->mibgood)
  387. chipstatsupd(ch);
  388. /* reset the dma engines */
  389. dma_txreset(ch->di);
  390. dma_rxreset(ch->di);
  391.         /* reset core */
  392.         /* 4402A0 requires PR3714 workaround */
  393.         if ((ch->etc->deviceid == BCM4402_ENET_ID) && (ch->etc->chiprev == 0)) {
  394.                 W_REG(&regs->enetcontrol, EC_ES);
  395.                 SPINWAIT((R_REG(&regs->enetcontrol) & EC_ES), 100);
  396.                 ASSERT((R_REG(&regs->enetcontrol) & EC_ES) == 0);
  397.                 W_REG(&regs->intmask, 0);
  398.                 W_REG(&regs->intstatus, R_REG(&regs->intstatus));
  399.                 ASSERT(R_REG(&regs->intstatus) == 0);
  400.                 W_REG(&regs->biststatus, 0);
  401.                 W_REG(&regs->wakeuplength, 0);
  402.                 W_REG(&regs->gptimer, 0);
  403.                 W_REG(&regs->emaccontrol, 0);
  404.                 W_REG(&regs->emacflowcontrol, 0);
  405.                 W_REG(&regs->intrecvlazy, 0);
  406.         } else
  407.                 sb_core_reset(ch->sbh, 0);
  408. chipinreset:
  409. /* must clear mib registers by hand */
  410. W_REG(&regs->mibcontrol, EMC_RZ);
  411. (void) R_REG(&regs->mib.tx_broadcast_pkts);
  412. (void) R_REG(&regs->mib.tx_multicast_pkts);
  413. (void) R_REG(&regs->mib.tx_len_64);
  414. (void) R_REG(&regs->mib.tx_len_65_to_127);
  415. (void) R_REG(&regs->mib.tx_len_128_to_255);
  416. (void) R_REG(&regs->mib.tx_len_256_to_511);
  417. (void) R_REG(&regs->mib.tx_len_512_to_1023);
  418. (void) R_REG(&regs->mib.tx_len_1024_to_max);
  419. (void) R_REG(&regs->mib.tx_jabber_pkts);
  420. (void) R_REG(&regs->mib.tx_oversize_pkts);
  421. (void) R_REG(&regs->mib.tx_fragment_pkts);
  422. (void) R_REG(&regs->mib.tx_underruns);
  423. (void) R_REG(&regs->mib.tx_total_cols);
  424. (void) R_REG(&regs->mib.tx_single_cols);
  425. (void) R_REG(&regs->mib.tx_multiple_cols);
  426. (void) R_REG(&regs->mib.tx_excessive_cols);
  427. (void) R_REG(&regs->mib.tx_late_cols);
  428. (void) R_REG(&regs->mib.tx_defered);
  429. (void) R_REG(&regs->mib.tx_carrier_lost);
  430. (void) R_REG(&regs->mib.tx_pause_pkts);
  431. (void) R_REG(&regs->mib.rx_broadcast_pkts);
  432. (void) R_REG(&regs->mib.rx_multicast_pkts);
  433. (void) R_REG(&regs->mib.rx_len_64);
  434. (void) R_REG(&regs->mib.rx_len_65_to_127);
  435. (void) R_REG(&regs->mib.rx_len_128_to_255);
  436. (void) R_REG(&regs->mib.rx_len_256_to_511);
  437. (void) R_REG(&regs->mib.rx_len_512_to_1023);
  438. (void) R_REG(&regs->mib.rx_len_1024_to_max);
  439. (void) R_REG(&regs->mib.rx_jabber_pkts);
  440. (void) R_REG(&regs->mib.rx_oversize_pkts);
  441. (void) R_REG(&regs->mib.rx_fragment_pkts);
  442. (void) R_REG(&regs->mib.rx_missed_pkts);
  443. (void) R_REG(&regs->mib.rx_crc_align_errs);
  444. (void) R_REG(&regs->mib.rx_undersize);
  445. (void) R_REG(&regs->mib.rx_crc_errs);
  446. (void) R_REG(&regs->mib.rx_align_errs);
  447. (void) R_REG(&regs->mib.rx_symbol_errs);
  448. (void) R_REG(&regs->mib.rx_pause_pkts);
  449. (void) R_REG(&regs->mib.rx_nonpause_pkts);
  450. ch->mibgood = TRUE;
  451. /*
  452.  * We want the phy registers to be accessible even when
  453.  * the driver is "downed" so initialize MDC preamble, frequency,
  454.  * and whether internal or external phy here.
  455.  */
  456.         if (ch->etc->deviceid == BCM47XX_ENET_ID) {
  457.                 /* 4710A0 has a 100Mhz SB clock and external phy */
  458.                 W_REG(&regs->mdiocontrol, 0x94);
  459.         } else if (ch->etc->deviceid == BCM4402_ENET_ID) {
  460.                 /* 4402 has 62.5Mhz SB clock and internal phy */
  461.                 W_REG(&regs->mdiocontrol, 0x8d);
  462. #ifdef BCMINTERNAL
  463.         } else if ((ch->etc->deviceid == BCM4307_ENET_ID) ||
  464.                    (ch->etc->deviceid == BCM4309_ENET_ID)) {
  465.                 /* 4307/4309 have 88Mhz SB clock and external phy */
  466.                 W_REG(&regs->mdiocontrol, 0x92);
  467.         } else if (ch->etc->deviceid == BCM4310_ENET_ID) {
  468.                 /* 4310 has a 124.8Mhz SB clock and external phy */
  469.                 W_REG(&regs->mdiocontrol, 0x99);
  470. #else
  471.         } else if (ch->etc->deviceid == BCM4307_ENET_ID) {
  472.                 /* 4307 has 88 MHz SB clock and external phy */
  473.                 W_REG(&regs->mdiocontrol, 0x92);
  474. #endif
  475.         } else
  476.                 ASSERT(0);
  477. /* some chips have internal phy, some don't */
  478. if (!(R_REG(&regs->devcontrol) & DC_IP)) {
  479. W_REG(&regs->enetcontrol, EC_EP);
  480. } else if (R_REG(&regs->devcontrol) & DC_ER) {
  481. AND_REG(&regs->devcontrol, ~DC_ER);
  482. OSL_DELAY(100);
  483. chipphyinit(ch, ch->etc->phyaddr);
  484. }
  485. /* clear persistent sw intstatus */
  486. ch->intstatus = 0;
  487. }
  488. /*
  489.  * Initialize all the chip registers.  If dma mode, init tx and rx dma engines
  490.  * but leave the devcontrol tx and rx (fifos) disabled.
  491.  */
  492. static void
  493. chipinit(struct bcm4xxx *ch, bool full)
  494. {
  495. etc_info_t *etc;
  496. bcmenetregs_t *regs;
  497. uint idx;
  498. uint i;
  499. regs = ch->regs;
  500. etc = ch->etc;
  501. idx = 0;
  502. ET_TRACE(("et%d: chipinitn", etc->unit));
  503. /* enable crc32 generation */
  504. OR_REG(&regs->emaccontrol, EMC_CG);
  505. /* enable one rx interrupt per received frame */
  506. W_REG(&regs->intrecvlazy, (1 << IRL_FC_SHIFT));
  507. /* enable 802.3x tx flow control (honor received PAUSE frames) */
  508. W_REG(&regs->rxconfig, ERC_FE | ERC_UF);
  509. /* initialize CAM */
  510. if (etc->promisc)
  511. OR_REG(&regs->rxconfig, ERC_PE);
  512. else {
  513. /* our local address */
  514. chipwrcam(ch, &etc->cur_etheraddr, idx++);
  515. /* allmulti or a list of discrete multicast addresses */
  516. if (etc->allmulti)
  517. OR_REG(&regs->rxconfig, ERC_AM);
  518. else if (etc->nmulticast) {
  519. for (i = 0; i < etc->nmulticast; i++)
  520. chipwrcam(ch, &etc->multicast[i], idx++);
  521. }
  522. /* enable cam */
  523. OR_REG(&regs->camcontrol, CC_CE);
  524. }
  525. /* optionally enable mac-level loopback */
  526. if (etc->loopbk)
  527. OR_REG(&regs->rxconfig, ERC_LE);
  528. /* set max frame lengths - account for possible vlan tag */
  529. W_REG(&regs->rxmaxlength, ETHER_MAX_LEN + 32);
  530. W_REG(&regs->txmaxlength, ETHER_MAX_LEN + 32);
  531. /* set tx watermark */
  532. W_REG(&regs->txwatermark, 56);
  533. /*
  534.  * Optionally, disable phy autonegotiation and force our speed/duplex
  535.  * or constrain our advertised capabilities.
  536.  */
  537. if (etc->forcespeed != ET_AUTO)
  538. chipphyforce(ch, etc->phyaddr);
  539. else if (etc->advertise && etc->needautoneg)
  540. chipphyadvertise(ch, etc->phyaddr);
  541. if (full) {
  542. /* initialize the tx and rx dma channels */
  543. dma_txinit(ch->di);
  544. dma_rxinit(ch->di);
  545. /* post dma receive buffers */
  546. dma_rxfill(ch->di);
  547. /* lastly, enable interrupts */
  548. W_REG(&regs->intmask, ch->intmask);
  549. }
  550. else
  551. dma_rxenable(ch->di);
  552. /* turn on the emac */
  553. OR_REG(&regs->enetcontrol, EC_EE);
  554. }
  555. /* dma transmit */
  556. static void
  557. chiptx(struct bcm4xxx *ch, void *p0)
  558. {
  559. int error;
  560. ET_TRACE(("et%d: chiptxn", ch->etc->unit));
  561. ET_LOG("chiptx", 0);
  562. error = dma_txfast(ch->di, p0, 0);
  563. if (error) {
  564. ET_ERROR(("et%d: chiptx: out of txdsn", ch->etc->unit));
  565. ch->etc->txnobuf++;
  566. }
  567. }
  568. /* reclaim complete transmit descriptors and packets */
  569. static void
  570. chiptxreclaim(struct bcm4xxx *ch, bool forceall)
  571. {
  572. ET_TRACE(("et%d: chiptxreclaimn", ch->etc->unit));
  573. dma_txreclaim(ch->di, forceall);
  574. ch->intstatus &= ~I_XI;
  575. }
  576. /* dma receive: returns a pointer to the next frame received, or NULL if there are no more */
  577. static void*
  578. chiprx(struct bcm4xxx *ch)
  579. {
  580. void *p;
  581. ET_TRACE(("et%d: chiprxn", ch->etc->unit));
  582. ET_LOG("chiprx", 0);
  583. if ((p = dma_rx(ch->di)) == NULL)
  584. ch->intstatus &= ~I_RI;
  585. return (p);
  586. }
  587. /* reclaim completes dma transmit descriptors and packets */
  588. static void
  589. chiprxreclaim(struct bcm4xxx *ch)
  590. {
  591. ET_TRACE(("et%d: chiprxreclaimn", ch->etc->unit));
  592. dma_rxreclaim(ch->di);
  593. ch->intstatus &= ~I_RI;
  594. }
  595. /* allocate and post dma receive buffers */
  596. static void
  597. chiprxfill(struct bcm4xxx *ch)
  598. {
  599. ET_TRACE(("et%d: chiprxfilln", ch->etc->unit));
  600. ET_LOG("chiprx", 0);
  601. dma_rxfill(ch->di);
  602. }
  603. /* get current and pending interrupt events */
  604. static int
  605. chipgetintrevents(struct bcm4xxx *ch)
  606. {
  607. bcmenetregs_t *regs;
  608. uint32 intstatus;
  609. int events;
  610. regs = ch->regs;
  611. events = 0;
  612. /* read the interrupt status register */
  613. intstatus = R_REG(&regs->intstatus);
  614. /* if there are new events */
  615. if (intstatus & ch->intmask)
  616. events |= INTR_NEW;
  617. /* or new bits into persistent intstatus */
  618. intstatus = (ch->intstatus |= intstatus);
  619. /* return if no events */
  620. if (intstatus == 0)
  621. return (0);
  622. /* clear non-error interrupt conditions */
  623. W_REG(&regs->intstatus, intstatus);
  624. /* convert chip-specific intstatus bits into generic intr event bits */
  625. if (intstatus & I_RI)
  626. events |= INTR_RX;
  627. if (intstatus & I_XI)
  628. events |= INTR_TX;
  629. if (intstatus & I_ERRORS)
  630. events |= INTR_ERROR;
  631. if (intstatus & I_TO)
  632. events |= INTR_TO;
  633. return (events);
  634. }
  635. /* enable chip interrupts */
  636. static void
  637. chipintrson(struct bcm4xxx *ch)
  638. {
  639. ch->intmask = DEF_INTMASK;
  640. W_REG(&ch->regs->intmask, ch->intmask);
  641. }
  642. /* disable chip interrupts */
  643. static void
  644. chipintrsoff(struct bcm4xxx *ch)
  645. {
  646. ch->intmask = 0;
  647. W_REG(&ch->regs->intmask, ch->intmask);
  648. (void) R_REG(&ch->regs->intmask); /* sync readback */
  649. }
  650. /* return true of caller should re-initialize, otherwise false */
  651. static bool
  652. chiperrors(struct bcm4xxx *ch)
  653. {
  654. uint32 intstatus;
  655. etc_info_t *etc;
  656. etc = ch->etc;
  657. intstatus = ch->intstatus;
  658. ch->intstatus &= ~(I_ERRORS);
  659. ET_TRACE(("et%d: chiperrors: intstatus 0x%xn", etc->unit, intstatus));
  660. if (intstatus & I_PC) {
  661. ET_ERROR(("et%d: descriptor errorn", etc->unit));
  662. etc->dmade++;
  663. }
  664. if (intstatus & I_PD) {
  665. ET_ERROR(("et%d: data errorn", etc->unit));
  666. etc->dmada++;
  667. }
  668. if (intstatus & I_DE) {
  669. ET_ERROR(("et%d: descriptor protocol errorn", etc->unit));
  670. etc->dmape++;
  671. }
  672. if (intstatus & I_RU) {
  673. ET_ERROR(("et%d: receive descriptor underflown", etc->unit));
  674. etc->rxdmauflo++;
  675. }
  676. if (intstatus & I_RO) {
  677. ET_ERROR(("et%d: receive fifo overflown", etc->unit));
  678. etc->rxoflo++;
  679. }
  680. if (intstatus & I_XU) {
  681. ET_ERROR(("et%d: transmit fifo underflown", etc->unit));
  682. etc->txuflo++;
  683. }
  684. return (TRUE);
  685. }
  686. static void
  687. chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex)
  688. {
  689. uint32 w;
  690. ASSERT((R_REG(&ch->regs->camcontrol) & (CC_CB | CC_CE)) == 0);
  691. w = (ea->octet[2] << 24) | (ea->octet[3] << 16) | (ea->octet[4] << 8)
  692. | ea->octet[5];
  693. W_REG(&ch->regs->camdatalo, w);
  694. w = CD_V | (ea->octet[0] << 8) | ea->octet[1];
  695. W_REG(&ch->regs->camdatahi, w);
  696. W_REG(&ch->regs->camcontrol, ((camindex << CC_INDEX_SHIFT) | CC_WR));
  697. /* spin until done */
  698. SPINWAIT((R_REG(&ch->regs->camcontrol) & CC_CB), 100);
  699. ASSERT((R_REG(&ch->regs->camcontrol) & CC_CB) == 0);
  700. }
  701. static void
  702. chipstatsupd(struct bcm4xxx *ch)
  703. {
  704. etc_info_t *etc;
  705. bcmenetregs_t *regs;
  706. etc = ch->etc;
  707. regs = ch->regs;
  708. /*
  709.  * mib counters are clear-on-read.
  710.  * Don't bother using the pkt and octet counters since they are only
  711.  * 16bits and wrap too quickly to be useful.
  712.  */
  713. etc->mib.tx_broadcast_pkts += R_REG(&regs->mib.tx_broadcast_pkts);
  714. etc->mib.tx_multicast_pkts += R_REG(&regs->mib.tx_multicast_pkts);
  715. etc->mib.tx_len_64 += R_REG(&regs->mib.tx_len_64);
  716. etc->mib.tx_len_65_to_127 += R_REG(&regs->mib.tx_len_65_to_127);
  717. etc->mib.tx_len_128_to_255 += R_REG(&regs->mib.tx_len_128_to_255);
  718. etc->mib.tx_len_256_to_511 += R_REG(&regs->mib.tx_len_256_to_511);
  719. etc->mib.tx_len_512_to_1023 += R_REG(&regs->mib.tx_len_512_to_1023);
  720. etc->mib.tx_len_1024_to_max += R_REG(&regs->mib.tx_len_1024_to_max);
  721. etc->mib.tx_jabber_pkts += R_REG(&regs->mib.tx_jabber_pkts);
  722. etc->mib.tx_oversize_pkts += R_REG(&regs->mib.tx_oversize_pkts);
  723. etc->mib.tx_fragment_pkts += R_REG(&regs->mib.tx_fragment_pkts);
  724. etc->mib.tx_underruns += R_REG(&regs->mib.tx_underruns);
  725. etc->mib.tx_total_cols += R_REG(&regs->mib.tx_total_cols);
  726. etc->mib.tx_single_cols += R_REG(&regs->mib.tx_single_cols);
  727. etc->mib.tx_multiple_cols += R_REG(&regs->mib.tx_multiple_cols);
  728. etc->mib.tx_excessive_cols += R_REG(&regs->mib.tx_excessive_cols);
  729. etc->mib.tx_late_cols += R_REG(&regs->mib.tx_late_cols);
  730. etc->mib.tx_defered += R_REG(&regs->mib.tx_defered);
  731. etc->mib.tx_carrier_lost += R_REG(&regs->mib.tx_carrier_lost);
  732. etc->mib.tx_pause_pkts += R_REG(&regs->mib.tx_pause_pkts);
  733. etc->mib.rx_broadcast_pkts += R_REG(&regs->mib.rx_broadcast_pkts);
  734. etc->mib.rx_multicast_pkts += R_REG(&regs->mib.rx_multicast_pkts);
  735. etc->mib.rx_len_64 += R_REG(&regs->mib.rx_len_64);
  736. etc->mib.rx_len_65_to_127 += R_REG(&regs->mib.rx_len_65_to_127);
  737. etc->mib.rx_len_128_to_255 += R_REG(&regs->mib.rx_len_128_to_255);
  738. etc->mib.rx_len_256_to_511 += R_REG(&regs->mib.rx_len_256_to_511);
  739. etc->mib.rx_len_512_to_1023 += R_REG(&regs->mib.rx_len_512_to_1023);
  740. etc->mib.rx_len_1024_to_max += R_REG(&regs->mib.rx_len_1024_to_max);
  741. etc->mib.rx_jabber_pkts += R_REG(&regs->mib.rx_jabber_pkts);
  742. etc->mib.rx_oversize_pkts += R_REG(&regs->mib.rx_oversize_pkts);
  743. etc->mib.rx_fragment_pkts += R_REG(&regs->mib.rx_fragment_pkts);
  744. etc->mib.rx_missed_pkts += R_REG(&regs->mib.rx_missed_pkts);
  745. etc->mib.rx_crc_align_errs += R_REG(&regs->mib.rx_crc_align_errs);
  746. etc->mib.rx_undersize += R_REG(&regs->mib.rx_undersize);
  747. etc->mib.rx_crc_errs += R_REG(&regs->mib.rx_crc_errs);
  748. etc->mib.rx_align_errs += R_REG(&regs->mib.rx_align_errs);
  749. etc->mib.rx_symbol_errs += R_REG(&regs->mib.rx_symbol_errs);
  750. etc->mib.rx_pause_pkts += R_REG(&regs->mib.rx_pause_pkts);
  751. etc->mib.rx_nonpause_pkts += R_REG(&regs->mib.rx_nonpause_pkts);
  752. /*
  753.  * Aggregate transmit and receive errors that probably resulted
  754.  * in the loss of a frame are computed on the fly.
  755.  *
  756.  * We seem to get lots of tx_carrier_lost errors when flipping
  757.  * speed modes so don't count these as tx errors.
  758.  *
  759.  * Arbitrarily lump the non-specific dma errors as tx errors.
  760.  */
  761. etc->txerror = etc->mib.tx_jabber_pkts + etc->mib.tx_oversize_pkts
  762. + etc->mib.tx_underruns + etc->mib.tx_excessive_cols
  763. + etc->mib.tx_late_cols + etc->txnobuf + etc->dmade
  764. + etc->dmada + etc->dmape + etc->txuflo + etc->txnobuf;
  765. etc->rxerror = etc->mib.rx_jabber_pkts + etc->mib.rx_oversize_pkts
  766. + etc->mib.rx_missed_pkts + etc->mib.rx_crc_align_errs
  767. + etc->mib.rx_undersize + etc->mib.rx_crc_errs
  768. + etc->mib.rx_align_errs + etc->mib.rx_symbol_errs
  769. + etc->rxnobuf + etc->rxdmauflo + etc->rxoflo + etc->rxbadlen;
  770. }
  771. static void
  772. chipenablepme(struct bcm4xxx *ch)
  773. {
  774.         bcmenetregs_t *regs;
  775.         regs = ch->regs;
  776.         /* enable chip wakeup pattern matching */
  777.         OR_REG(&regs->devcontrol, DC_PM);
  778.         /* enable sonics bus PME */
  779.         sb_coreflags(ch->sbh, SBTML_PE, SBTML_PE);
  780. }
  781. static void
  782. chipdisablepme(struct bcm4xxx *ch)
  783. {
  784.         bcmenetregs_t *regs;
  785.         regs = ch->regs;
  786.         AND_REG(&regs->devcontrol, ~DC_PM);
  787.         sb_coreflags(ch->sbh, SBTML_PE, 0);
  788. }
  789. static void
  790. chipduplexupd(struct bcm4xxx *ch)
  791. {
  792. uint32 txcontrol;
  793. txcontrol = R_REG(&ch->regs->txcontrol);
  794. if (ch->etc->duplex && !(txcontrol & EXC_FD))
  795. OR_REG(&ch->regs->txcontrol, EXC_FD);
  796. else if (!ch->etc->duplex && (txcontrol & EXC_FD))
  797. AND_REG(&ch->regs->txcontrol, ~EXC_FD);
  798. }
  799. char  mDbg_mdio = FALSE;
  800. static uint16
  801. chipphyrd(struct bcm4xxx *ch, uint phyaddr, uint reg)
  802. {
  803. bcmenetregs_t *regs;
  804. uint16 ret;
  805. ASSERT(phyaddr < PHY_NOMDC);
  806. ASSERT(reg < 32);
  807. /*
  808.  * BCM5222 dualphy shared mdio contortion.
  809.  * remote phy: another emac controls our phy.
  810.  */
  811. if (ch->etc->mdcport != ch->etc->coreunit) {
  812. if (ch->etphy == NULL) {
  813. ch->etphy = et_phyfind(ch->et, ch->etc->mdcport);
  814. /* first time reset */
  815. if (ch->etphy)
  816. chipphyreset(ch, ch->etc->phyaddr);
  817. }
  818. if (ch->etphy)
  819. return (et_phyrd(ch->etphy, phyaddr, reg));
  820. else
  821. return (0xffff);
  822. }
  823. /* local phy: our emac controls our phy */
  824. regs = ch->regs;
  825. /* clear mii_int */
  826. W_REG(&regs->emacintstatus, EI_MII);
  827. /* issue the read */
  828. W_REG(&regs->mdiodata,  (MD_SB_START | MD_OP_READ | (phyaddr << MD_PMD_SHIFT)
  829. | (reg << MD_RA_SHIFT) | MD_TA_VALID));
  830. /* wait for it to complete */
  831. SPINWAIT(((R_REG(&regs->emacintstatus) & EI_MII) == 0), 100);
  832. if ((R_REG(&regs->emacintstatus) & EI_MII) == 0) {
  833. ET_ERROR(("et%d: chipphyrd: did not completen", ch->etc->unit));
  834. }
  835. ret =  R_REG(&regs->mdiodata) & MD_DATA_MASK;
  836. if (mDbg_mdio) {
  837.     printf("%s(0x%x, 0x%x) -->0x%xn",__FUNCTION__, phyaddr, reg, ret);
  838. }
  839. return ret;
  840. }
  841. static void
  842. chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
  843. {
  844. bcmenetregs_t *regs;
  845. ASSERT(phyaddr < PHY_NOMDC);
  846. ASSERT(reg < 32);
  847. /*
  848.  * BCM5222 dualphy shared mdio contortion.
  849.  * remote phy: another emac controls our phy.
  850.  */
  851. if (ch->etc->mdcport != ch->etc->coreunit) {
  852. if (ch->etphy == NULL)
  853. ch->etphy = et_phyfind(ch->et, ch->etc->mdcport);
  854. if (ch->etphy)
  855. et_phywr(ch->etphy, phyaddr, reg, v);
  856. return;
  857. }
  858. if (mDbg_mdio) {
  859.    printf("%s(0x%x, 0x%x, 0x%x)n",__FUNCTION__, phyaddr, reg, v);
  860. }
  861. /* local phy: our emac controls our phy */
  862. regs = ch->regs;
  863. /* clear mii_int */
  864. W_REG(&regs->emacintstatus, EI_MII);
  865. ASSERT((R_REG(&regs->emacintstatus) & EI_MII) == 0);;
  866. /* issue the write */
  867. W_REG(&regs->mdiodata,  (MD_SB_START | MD_OP_WRITE | (phyaddr << MD_PMD_SHIFT)
  868. | (reg << MD_RA_SHIFT) | MD_TA_VALID | v));
  869. /* wait for it to complete */
  870. SPINWAIT(((R_REG(&regs->emacintstatus) & EI_MII) == 0), 100);
  871. if ((R_REG(&regs->emacintstatus) & EI_MII) == 0) {
  872. ET_ERROR(("et%d: chipphywr: did not completen", ch->etc->unit));
  873. }
  874. }
  875. static void
  876. chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
  877. {
  878. uint16 tmp;
  879. tmp = chipphyrd(ch, phyaddr, reg);
  880. tmp |= v;
  881. chipphywr(ch, phyaddr, reg, tmp);
  882. }
  883. static void
  884. chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
  885. {
  886. uint16 tmp;
  887. tmp = chipphyrd(ch, phyaddr, reg);
  888. tmp &= v;
  889. chipphywr(ch, phyaddr, reg, tmp);
  890. }
  891. static void
  892. chipphyreset(struct bcm4xxx *ch, uint phyaddr)
  893. {
  894. if (phyaddr == PHY_NOMDC) return;
  895. chipphywr(ch, phyaddr, 0, CTL_RESET);
  896. OSL_DELAY(100);
  897. if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) {
  898. ET_ERROR(("et%d: chipphyreset: reset not completen", ch->etc->unit));
  899. }
  900. chipphyinit(ch, phyaddr);
  901. }
  902. static void
  903. chipphyinit(struct bcm4xxx *ch, uint phyaddr)
  904. {
  905.         uint    phyid = 0;
  906.         /* enable activity led */
  907.         chipphyand(ch, phyaddr, 26, 0x7fff);
  908.         /* enable traffic meter led mode */
  909.         chipphyor(ch, phyaddr, 27, (1 << 6));
  910.         /* PR 10115 detecting MELCO specific link pulse. */
  911.         phyid = chipphyrd( ch, phyaddr, 0x2);
  912.         phyid |=  chipphyrd( ch, phyaddr, 0x3) << 16;
  913.         if( phyid == 0x55210022) {
  914.                 chipphywr( ch, phyaddr, 30, chipphyrd( ch, phyaddr, 30 ) | 0x3000);
  915.                 chipphywr( ch, phyaddr, 19, chipphyrd( ch, phyaddr, 19 ) | 0x0010);
  916.         }
  917. }
  918. static void
  919. chipphyforce(struct bcm4xxx *ch, uint phyaddr)
  920. {
  921. etc_info_t *etc;
  922. uint16 ctl;
  923. if (phyaddr == PHY_NOMDC) return;
  924. etc = ch->etc;
  925. if (etc->forcespeed == ET_AUTO)
  926. return;
  927. ctl = chipphyrd(ch, phyaddr, 0);
  928. ctl &= ~(CTL_SPEED | CTL_ANENAB | CTL_DUPLEX);
  929. switch (etc->forcespeed) {
  930. case ET_10HALF:
  931. break;
  932. case ET_10FULL:
  933. ctl |= CTL_DUPLEX;
  934. break;
  935. case ET_100HALF:
  936. ctl |= CTL_SPEED;
  937. break;
  938. case ET_100FULL:
  939. ctl |= (CTL_SPEED | CTL_DUPLEX);
  940. break;
  941. }
  942. chipphywr(ch, phyaddr, 0, ctl);
  943. }
  944. /* set selected capability bits in autonegotiation advertisement */
  945. static void
  946. chipphyadvertise(struct bcm4xxx *ch, uint phyaddr)
  947. {
  948. etc_info_t *etc;
  949. uint16 adv;
  950. if (phyaddr == PHY_NOMDC) return;
  951. etc = ch->etc;
  952. if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg)
  953. return;
  954. ASSERT(etc->advertise);
  955. /* reset our advertised capabilitity bits */
  956. adv = chipphyrd(ch, phyaddr, 4);
  957. adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF);
  958. adv |= etc->advertise;
  959. chipphywr(ch, phyaddr, 4, adv);
  960. /* restart autonegotiation */
  961. chipphyor(ch, phyaddr, 0, CTL_RESTART);
  962. etc->needautoneg = FALSE;
  963. }
  964. static struct mdioCtrlReg1{
  965.     uint8     page;
  966.     uint8     writeAll:1;
  967.     uint8     reserved:4;
  968.     uint8     chipId:2;
  969.     uint8     mdioEnable:1;
  970. }  mdioCtrl1;
  971. static struct mdioCtrlReg2 {
  972.     uint8    regOffset;
  973.     uint8    reserved:6;
  974.     uint8    op:2;   
  975. } mdioCtrl2;
  976. int     gSPIEnable = TRUE;
  977. int  mdioDelay=100;
  978. static uint16  *pMdioCtrl1 = (uint16 *) &mdioCtrl1;
  979. static uint16  *pMdioCtrl2 = (uint16 *) &mdioCtrl2;
  980. static uint16  mMdioBuf[4];
  981. static  char mMdioUsed = FALSE;
  982. #define    MII_PAGE_PORTmin 0x10
  983. #define    MII_PAGE_PORTmax 0x18
  984. #define    PSEUDO_PHY 0x1e
  985. #define    MDIO_CTRL1_ADDR 16
  986. #define    MDIO_CTRL2_ADDR 17
  987. #define    MDIO_DATAREG_BASE    24
  988. #define    MDIO_OP_RD 2
  989. #define    MDIO_OP_WR    1
  990. /*-------------------------------------------------------------
  991. check if this access is at the same page as the previous access
  992. if it is in different page, then need to set the mdio_ctrl1 
  993. ---------------------------------------------------------------*/
  994. #define    CHKSET_CHIP_PAGE(cid, page) 
  995.         if ( !mMdioUsed ||mdioCtrl1.page != page || mdioCtrl1.chipId !=cid ) {
  996.     mMdioUsed = TRUE;     
  997.             mdioCtrl1.page = page; 
  998.          mdioCtrl1.chipId = cid; 
  999.     chipphywr(mpCh[1], PSEUDO_PHY, MDIO_CTRL1_ADDR, *pMdioCtrl1); 
  1000. }
  1001. void robo_mdio_reset() 
  1002. {
  1003. mMdioUsed = FALSE;
  1004. chipphywr(mpCh[1], PSEUDO_PHY, MDIO_CTRL1_ADDR, 0);
  1005. }
  1006. void setSPI(int fEnable)
  1007. {
  1008. gSPIEnable = fEnable;
  1009. mdioCtrl1.mdioEnable = 1-fEnable;
  1010. mMdioUsed = FALSE;
  1011. chipphywr(mpCh[1], PSEUDO_PHY, MDIO_CTRL1_ADDR, 1-fEnable);
  1012. }
  1013. void robo_mdio_rreg(uint8 cid, uint8 page, uint8 addr, uint8 *buf, uint len)
  1014. {
  1015. int i, nWord=(len+1)>>1;
  1016. uint16 ret;
  1017. uint8  *p = buf;
  1018. if (len>8) {
  1019.     ET_ERROR(("length should be no greater than 8 bytesn"));
  1020.     return;
  1021. }
  1022. if (page>= MII_PAGE_PORTmin && page <= MII_PAGE_PORTmax) {
  1023.     /* direct access */
  1024.     if (len!=2) {
  1025. ET_ERROR(("All MII registers are 2 bytes longn"));
  1026. return;
  1027.     }
  1028.     cid = cid<<3 |(page - MII_PAGE_PORTmin); 
  1029.     ret = chipphyrd(mpCh[1], cid, addr>>1);
  1030.     buf[0] = ret & 0x00ff;
  1031.     buf[1] = ret >>8;    
  1032.     return;
  1033. }
  1034. /* if the access is to pages/chips other than the previous one
  1035.    set the mdio_ctrl1 register again  */
  1036. CHKSET_CHIP_PAGE(cid, page); 
  1037. mdioCtrl2.op = MDIO_OP_RD;
  1038. mdioCtrl2.regOffset = addr;
  1039. chipphywr(mpCh[1], PSEUDO_PHY, MDIO_CTRL2_ADDR, *pMdioCtrl2);
  1040. do {
  1041.     *pMdioCtrl2 = chipphyrd(mpCh[1], PSEUDO_PHY, MDIO_CTRL2_ADDR);
  1042. } while (mdioCtrl2.op != 0);
  1043. for (i=0; i<nWord; i++ ) {
  1044.     ret = chipphyrd(mpCh[1], PSEUDO_PHY, MDIO_DATAREG_BASE+ i);
  1045.     *p++ = ret & 0x00ff;
  1046.     *p++ = ret >>8;
  1047. }
  1048. void robo_mdio_wreg(uint8 cid, uint8 page, uint8 addr, uint8 *buf, uint len)
  1049. {
  1050. int i, nWord=(len+1)>>1;
  1051. if (len>8) {
  1052.     ET_ERROR(("length should be no greater than 8 bytesn"));
  1053.     return;
  1054. }
  1055. memcpy((uint8 *)mMdioBuf, buf, len);
  1056. /*odd number of bytes, move data from hibyte to lobyte for the last 
  1057.   byte */
  1058. if (len &0x01) 
  1059.     mMdioBuf[nWord] >>=8;
  1060. if (page>= MII_PAGE_PORTmin && page <= MII_PAGE_PORTmax) {
  1061.     /*direct access */
  1062.     if (len!=2) {
  1063. ET_ERROR(("All MII registers are 2 bytes longn"));
  1064. return;
  1065.     }
  1066.     cid = cid<<3 |(page - MII_PAGE_PORTmin);
  1067.     chipphywr(mpCh[1], cid, addr>>1, mMdioBuf[0]);
  1068.     return;
  1069. }
  1070. for (i=0; i<nWord; i++ )  {
  1071.     chipphywr(mpCh[1], PSEUDO_PHY, MDIO_DATAREG_BASE+ i, mMdioBuf[i]);
  1072. }
  1073. CHKSET_CHIP_PAGE(cid, page);
  1074. mdioCtrl2.op = MDIO_OP_WR;
  1075. mdioCtrl2.regOffset = addr;
  1076. chipphywr(mpCh[1], PSEUDO_PHY, MDIO_CTRL2_ADDR, *pMdioCtrl2);
  1077. do {
  1078.     *pMdioCtrl2 = chipphyrd(mpCh[1], PSEUDO_PHY, MDIO_CTRL2_ADDR);
  1079. } while (mdioCtrl2.op != 0);
  1080. }