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

VxWorks

开发平台:

C/C++

  1. /*
  2.     Copyright 2001, Broadcom Corporation
  3.     All Rights Reserved.
  4.     
  5.     This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
  6.     the contents of this file may not be disclosed to third parties, copied or
  7.     duplicated in any form, in whole or in part, without the prior written
  8.     permission of Broadcom Corporation.
  9. */
  10. /*
  11.  * Common [OS-independent] portion of
  12.  * Broadcom Home Networking Division 10/100 Mbit/s Ethernet
  13.  * Device Driver.
  14.  *
  15.  * Copyright(c) 2000 Broadcom, Inc.
  16.  * $Id: etc.c,v 1.1 Broadcom SDK $
  17.  */
  18. #include <osl.h>
  19. #include <bcmendian.h>
  20. #include <ethernet.h>
  21. #include <bcmenetmib.h>
  22. #include <bcmenetrxh.h>
  23. #include <et_dbg.h>
  24. #include <etc.h>
  25. #include <et_export.h>
  26. #include <bcmutils.h>
  27. int et_msg_level =
  28. #ifdef BCMDBG
  29. 0xffffffff;   /* This is normally "1" */
  30. #else
  31. 0;
  32. #endif
  33. /* local prototypes */
  34. static void etc_loopback(etc_info_t *etc, int on);
  35. static void etc_dumpetc(etc_info_t *etc, uchar *buf);
  36. /* find the chip opsvec for this chip */
  37. struct chops*
  38. etc_chipmatch(uint vendor, uint device)
  39. {
  40. #ifdef BCM4413_CHOPS
  41. {
  42. extern struct chops bcm4413_chops;
  43. if (bcm4413_chops.id(vendor, device))
  44. return (&bcm4413_chops);
  45. }
  46. #endif
  47. #ifdef BCM47XX_CHOPS
  48. {
  49. extern struct chops bcm47xx_et_chops;
  50. if (bcm47xx_et_chops.id(vendor, device))
  51. return (&bcm47xx_et_chops);
  52. }
  53. #endif
  54. return (NULL);
  55. }
  56. void*
  57. etc_attach(void *et, uint vendor, uint device, uint unit, void *pdev, void *regsva)
  58. {
  59.     extern int sysIsLM();
  60. etc_info_t *etc;
  61. ET_TRACE(("et%d: etc_attach: vendor 0x%x device 0x%xn", unit, vendor, device));
  62. /* some code depends on packed structures */
  63. ASSERT(sizeof (struct ether_addr) == ETHER_ADDR_LEN);
  64. ASSERT(sizeof (struct ether_header) == ETHER_HDR_LEN);
  65. /* allocate etc_info_t state structure */
  66. if ((etc = (etc_info_t*) MALLOC(sizeof (etc_info_t))) == NULL) {
  67. ET_ERROR(("et%d: etc_attach malloc failedn", unit));
  68. return (NULL);
  69. }
  70. bzero((char*)etc, sizeof (etc_info_t));
  71. etc->et = et;
  72. etc->unit = unit;
  73. etc->vendorid = (uint16) vendor;
  74. etc->deviceid = (uint16) device;
  75.     
  76. etc->forcespeed = (sysIsLM()) ? ET_100HALF : ET_AUTO;
  77. etc->linkstate = FALSE;
  78. /* set chip opsvec */
  79. etc->chops = etc_chipmatch(vendor, device);
  80. ASSERT(etc->chops);
  81. /* chip attach */
  82. if ((etc->ch = (*etc->chops->attach)(etc, pdev, regsva)) == NULL) {
  83. ET_ERROR(("et%d: chipattach errorn", unit));
  84. goto fail;
  85. }
  86. return ((void*)etc);
  87. fail:
  88. etc_detach(etc);
  89. return (NULL);
  90. }
  91. void
  92. etc_detach(etc_info_t *etc)
  93. {
  94. if (etc == NULL)
  95. return;
  96. /* free chip private state */
  97. if (etc->ch) {
  98. (*etc->chops->detach)(etc->ch);
  99. etc->chops = etc->ch = NULL;
  100. }
  101. MFREE(etc, sizeof (etc_info_t));
  102. }
  103. void
  104. etc_reset(etc_info_t *etc)
  105. {
  106. ET_TRACE(("et%d: etc_resetn", etc->unit));
  107. etc->reset++;
  108. /* reset the chip */
  109. (*etc->chops->reset)(etc->ch);
  110. /* free any posted tx packets */
  111. (*etc->chops->txreclaim)(etc->ch, TRUE);
  112. #ifdef DMA
  113. /* free any posted rx packets */
  114. (*etc->chops->rxreclaim)(etc->ch);
  115. #endif
  116. }
  117. void
  118. etc_init(etc_info_t *etc)
  119. {
  120. ET_TRACE(("et%d: etc_initn", etc->unit));
  121. ASSERT(etc->pioactive == NULL);
  122. ASSERT(!ETHER_ISNULLADDR(&etc->cur_etheraddr));
  123. ASSERT(!ETHER_ISMULTI(&etc->cur_etheraddr));
  124. /* init the chip */
  125. (*etc->chops->init)(etc->ch, TRUE);
  126. }
  127. /* mark interface up */
  128. void
  129. etc_up(etc_info_t *etc)
  130. {
  131. /* calibration */
  132. ET_LOG("etc_up1", 0);
  133. ET_LOG("etc_up2", 0);
  134. ET_LOG("etc_up3", 0);
  135. etc->up = TRUE;
  136. et_init(etc->et);
  137. }
  138. /* mark interface down */
  139. uint
  140. etc_down(etc_info_t *etc, int reset)
  141. {
  142. uint callback;
  143. callback = 0;
  144. etc->up = FALSE;
  145. if (reset)
  146. et_reset(etc->et);
  147. /* suppress link state changes during power management mode changes */
  148. if (etc->linkstate) { 
  149. etc->linkstate = FALSE;
  150. if (!etc->pm_modechange)
  151. et_link_down(etc->et);
  152. }
  153. return (callback);
  154. }
  155. /* common ioctl handler.  return: 0=ok, -1=error */
  156. int
  157. etc_ioctl(etc_info_t *etc, int cmd, void *arg)
  158. {
  159. int error;
  160. int val;
  161. int *vec = (int*)arg;
  162. error = 0;
  163. val = arg? *(int*)arg: 0;
  164. ET_TRACE(("et%d: etc_ioctl: cmd 0x%xn", etc->unit, cmd));
  165. switch (cmd) {
  166. case ETCUP:
  167. et_up(etc->et);
  168. break;
  169. case ETCDOWN:
  170. et_down(etc->et, TRUE);
  171. break;
  172. case ETCLOOP:
  173. etc_loopback(etc, val);
  174. break;
  175. case ETCDUMP:
  176. #ifdef BCMDBG
  177. /* if trace logging is on, hijack et_dump() */
  178. if (et_msg_level & 2048)
  179. etc_dumplog((uchar*) arg);
  180. else
  181. #endif
  182. et_dump(etc->et, (uchar*) arg, 4096);
  183. break;
  184. case ETCSETMSGLEVEL:
  185. et_msg_level = val;
  186. break;
  187. case ETCPROMISC:
  188. etc_promisc(etc, val);
  189. break;
  190. case ETCSPEED:
  191. if ((val != ET_AUTO) && (val != ET_10HALF) && (val != ET_10FULL)
  192. && (val != ET_100HALF) && (val != ET_100FULL))
  193. goto err;
  194. etc->forcespeed = val;
  195. /* explicitly reset the phy */
  196. (*etc->chops->phyreset)(etc->ch, etc->phyaddr);
  197. /* request restart autonegotiation if we're reverting to adv mode */
  198. if ((etc->forcespeed == ET_AUTO) & etc->advertise)
  199. etc->needautoneg = TRUE;
  200. et_init(etc->et);
  201. break;
  202. case ETCPHYRD:
  203. if (vec)
  204. vec[1] = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, vec[0]);
  205. break;
  206. case ETCPHYWR:
  207. if (vec)
  208. (*etc->chops->phywr)(etc->ch, etc->phyaddr, vec[0], vec[1]);
  209. break;
  210. default:
  211. err:
  212. error = -1;
  213. }
  214. return (error);
  215. }
  216. /* called once per second */
  217. void
  218. etc_watchdog(etc_info_t *etc)
  219. {
  220. uint16 status;
  221. uint16 adv;
  222. uint16 lpa;
  223. etc->now++;
  224. if (etc->phyaddr == PHY_NOMDC) {
  225. etc->linkstate = TRUE;
  226. etc->speed = 100;
  227. etc->duplex = 1;
  228. return;
  229. }
  230. status = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, 1);
  231. adv = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, 4);
  232. lpa = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, 5);
  233. /* check for bad mdio read */
  234. if (status == 0xffff) {
  235. ET_ERROR(("et%d: etc_watchdog: bad mdio read: phyaddr %d mdcport %dn",
  236. etc->unit, etc->phyaddr, etc->mdcport));
  237. return;
  238. }
  239. /* monitor link state */
  240. if (!etc->linkstate && (status & STAT_LINK)) {
  241. etc->linkstate = TRUE;
  242. if (etc->pm_modechange)
  243. etc->pm_modechange = FALSE;
  244. else
  245. et_link_up(etc->et);
  246. }
  247. else if (etc->linkstate && !(status & STAT_LINK)) {
  248. etc->linkstate = FALSE;
  249. if (!etc->pm_modechange)
  250. et_link_down(etc->et);
  251. }
  252. /* update current speed and duplex */
  253. if ( (adv & ADV_100FULL) && (lpa & LPA_100FULL) ) {
  254. etc->speed = 100;
  255. etc->duplex = 1;
  256. } else if ( (adv & ADV_100HALF) && (lpa & LPA_100HALF) ) {
  257. etc->speed = 100;
  258. etc->duplex = 0;
  259. } else if ( (adv & ADV_10FULL) && (lpa & LPA_10FULL) ) {
  260. etc->speed = 10;
  261. etc->duplex = 1;
  262. } else {
  263. etc->speed = 10;
  264. etc->duplex = 0;
  265. }
  266. /* keep emac txcontrol duplex bit consistent with current phy duplex */
  267. (*etc->chops->duplexupd)(etc->ch);
  268. /* check for remote fault error */
  269. if (status & STAT_REMFAULT) {
  270. ET_ERROR(("et%d: remote faultn", etc->unit));
  271. }
  272. /* check for jabber error */
  273. if (status & STAT_JAB) {
  274. ET_ERROR(("et%d: jabbern", etc->unit));
  275. }
  276. /*
  277.  * Read chip mib counters occationally before the 16bit ones can wrap.
  278.  * We don't use the high-rate mib counters.
  279.  */
  280. if ((etc->now % 30) == 0)
  281. (*etc->chops->statsupd)(etc->ch);
  282. }
  283. static void
  284. etc_loopback(etc_info_t *etc, int on)
  285. {
  286. ET_TRACE(("et%d: etc_loopback: %dn", etc->unit, on));
  287. etc->loopbk = (bool) on;
  288. et_init(etc->et);
  289. }
  290. void
  291. etc_promisc(etc_info_t *etc, uint on)
  292. {
  293. ET_TRACE(("et%d: etc_promisc: %dn", etc->unit, on));
  294. etc->promisc = (bool) on;
  295. et_init(etc->et);
  296. }
  297. void
  298. etc_dump(etc_info_t *etc, uchar *buf, int size)
  299. {
  300. /* big enough */
  301. if (size < 3700)
  302. return;
  303. etc_dumpetc(etc, buf);
  304. (*etc->chops->dump)(etc->ch, buf + strlen(buf));
  305. }
  306. static void
  307. etc_dumpetc(etc_info_t *etc, uchar *buf)
  308. {
  309. char perm[32], cur[32];
  310. uint i;
  311. buf += sprintf(buf, "etc 0x%x et 0x%x unit %d msglevel %d speed/duplex %d%sn",
  312. (uint)etc, (uint)etc->et, etc->unit, et_msg_level,
  313. etc->speed, (etc->duplex? "full": "half"));
  314. buf += sprintf(buf, "up %d promisc %d loopbk %d forcespeed %d advertise 0x%x needautoneg %dn",
  315. etc->up, etc->promisc, etc->loopbk, etc->forcespeed, etc->advertise, etc->needautoneg);
  316. buf += sprintf(buf, "piomode %d pioactive 0x%x nmulticast %d allmulti %dn",
  317. etc->piomode, (uint)etc->pioactive, etc->nmulticast, etc->allmulti);
  318. buf += sprintf(buf, "vendor 0x%x device 0x%x rev %d coreunit %d phyaddr %d mdcport %dn",
  319. etc->vendorid, etc->deviceid, etc->chiprev,
  320. etc->coreunit, etc->phyaddr, etc->mdcport);
  321. buf += sprintf(buf, "perm_etheraddr %s cur_etheraddr %sn",
  322. bcm_ether_ntoa((char*)&etc->perm_etheraddr, perm),
  323. bcm_ether_ntoa((char*)&etc->cur_etheraddr, cur));
  324. if (etc->nmulticast) {
  325. buf += sprintf(buf, "multicast: ");
  326. for (i = 0; i < etc->nmulticast; i++)
  327. buf += sprintf(buf, "%s ", bcm_ether_ntoa((char*)&etc->multicast[i], cur));
  328. buf += sprintf(buf, "n");
  329. }
  330. buf += sprintf(buf, "linkstate %dn", etc->linkstate);
  331. buf += sprintf(buf, "n");
  332. /* refresh stat counters */
  333. (*etc->chops->statsupd)(etc->ch);
  334. /* summary stat counter line */
  335. /* use sw frame and byte counters -- hw mib counters wrap too quickly to be useful */
  336. buf += sprintf(buf, "txframe %d txbyte %d txerror %d rxframe %d rxbyte %d rxerror %dn",
  337. etc->txframe, etc->txbyte, etc->txerror,
  338. etc->rxframe, etc->rxbyte, etc->rxerror);
  339. /* transmit stat counters */
  340. /* hardware mib pkt and octet counters wrap too quickly to be useful */
  341. buf += sprintf(buf, "tx_broadcast_pkts %d tx_multicast_pkts %d tx_jabber_pkts %d tx_oversize_pkts %dn",
  342. etc->mib.tx_broadcast_pkts, etc->mib.tx_multicast_pkts, etc->mib.tx_jabber_pkts,
  343. etc->mib.tx_oversize_pkts);
  344. buf += sprintf(buf, "tx_fragment_pkts %d tx_underruns %dn",
  345. etc->mib.tx_fragment_pkts, etc->mib.tx_underruns);
  346. buf += sprintf(buf, "tx_total_cols %d tx_single_cols %d tx_multiple_cols %d tx_excessive_cols %dn",
  347. etc->mib.tx_total_cols, etc->mib.tx_single_cols, etc->mib.tx_multiple_cols, etc->mib.tx_excessive_cols);
  348. buf += sprintf(buf, "tx_late_cols %d tx_defered %d tx_carrier_lost %d tx_pause_pkts %dn",
  349. etc->mib.tx_late_cols, etc->mib.tx_defered, etc->mib.tx_carrier_lost, etc->mib.tx_pause_pkts);
  350. buf += sprintf(buf, "txnobuf %d reset %d dmade %d dmada %d dmape %dn",
  351. etc->txnobuf, etc->reset, etc->dmade, etc->dmada, etc->dmape);
  352. /* receive stat counters */
  353. /* hardware mib pkt and octet counters wrap too quickly to be useful */
  354. buf += sprintf(buf, "rx_broadcast_pkts %d rx_multicast_pkts %d rx_jabber_pkts %d rx_oversize_pkts %dn",
  355. etc->mib.rx_broadcast_pkts, etc->mib.rx_multicast_pkts, etc->mib.rx_jabber_pkts, etc->mib.rx_oversize_pkts);
  356. buf += sprintf(buf, "rx_fragment_pkts %d rx_missed_pkts %d rx_crc_align_errs %d rx_undersize %dn",
  357. etc->mib.rx_fragment_pkts, etc->mib.rx_missed_pkts, etc->mib.rx_crc_align_errs, etc->mib.rx_undersize);
  358. buf += sprintf(buf, "rx_crc_errs %d rx_align_errs %d rx_symbol_errs %d rx_pause_pkts %dn",
  359. etc->mib.rx_crc_errs, etc->mib.rx_align_errs, etc->mib.rx_symbol_errs, etc->mib.rx_pause_pkts);
  360. buf += sprintf(buf, "rx_nonpause_pkts %d rxnobuf %d rxdmauflo %d rxoflo %d rxbadlen %dn",
  361. etc->mib.rx_nonpause_pkts, etc->rxnobuf, etc->rxdmauflo, etc->rxoflo, etc->rxbadlen);
  362. buf += sprintf(buf, "n");
  363. }
  364. #define LOGSIZE 256
  365. static struct {
  366. uint32 cycles;
  367. uint32 instr;
  368. char *fmt;
  369. ulong a1;
  370. } etc_logtab[LOGSIZE];
  371. static uint etc_logi = 0;
  372. void
  373. etc_log(uint cycles, uint instr, char *fmt, ulong a1)
  374. {
  375. uint i;
  376. i = etc_logi;
  377. /* save values */
  378. etc_logtab[i].cycles = cycles;
  379. etc_logtab[i].instr = instr;
  380. etc_logtab[i].fmt = fmt;
  381. etc_logtab[i].a1 = a1;
  382. etc_logi = ++i % LOGSIZE;
  383. }
  384. void
  385. etc_dumplog(uchar *buf)
  386. {
  387. uint i;
  388. *buf = '';
  389. /* format the log into the buffer in chronological order */
  390. for (i = (etc_logi + 1) % LOGSIZE; i != etc_logi; i = (++i % LOGSIZE)) {
  391. if (etc_logtab[i].fmt == NULL)
  392. continue;
  393. buf += sprintf(buf, "%dt%dt",
  394. etc_logtab[i].cycles, etc_logtab[i].instr);
  395. buf += sprintf(buf, etc_logtab[i].fmt, etc_logtab[i].a1);
  396. buf += sprintf(buf, "n");
  397. }
  398. }
  399. uint
  400. etc_totlen(etc_info_t *etc, void *p)
  401. {
  402. uint total;
  403. total = 0;
  404. for (; p; p = PKTNEXT(etc->et, p))
  405. total += PKTLEN(etc->et, p);
  406. return (total);
  407. }
  408. #ifdef BCMDBG
  409. void
  410. etc_prhdr(char *msg, struct ether_header *eh, uint len)
  411. {
  412. char da[32], sa[32];
  413. printf("%s: dst %s src %s type 0x%x len %dn",
  414. msg,
  415. bcm_ether_ntoa(eh->ether_dhost, da),
  416. bcm_ether_ntoa(eh->ether_shost, sa),
  417. ntoh16(eh->ether_type),
  418. len);
  419. }
  420. #endif /* BCMDBG */