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

VxWorks

开发平台:

C/C++

  1. /*
  2.     Copyright 2001, Broadcom Corporation
  3.     All Rights Reserved.
  4.     This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
  5.     the contents of this file may not be disclosed to third parties, copied or
  6.     duplicated in any form, in whole or in part, without the prior written
  7.     permission of Broadcom Corporation.
  8. */
  9. /*
  10.  * vxWorks 5.x END device driver for
  11.  * Broadcom BCM44XX/BCM47XX family 10/100 Mbps Ethernet Controller
  12.  *
  13.  * Copyright(c) 2000 Broadcom Corp.
  14.  * All Rights Reserved.
  15.  * $Id: et_vx.c,v 1.1 Broadcom SDK $
  16.  */
  17. #ifndef lint
  18. static const char cvsid[] = "$Id: et_vx.c,v 1.1 2004/02/24 07:47:01 csm Exp $";
  19. #endif
  20. #define __INCunixLibh /* XXX temp defeat unixLib.h MALLOC() definition */
  21. #include <vx_osl.h>
  22. #include <endLib.h>
  23. #include <intLib.h>
  24. #include <ioctl.h>
  25. #include <netLib.h>
  26. #include <wdLib.h>
  27. #ifndef MSI
  28. #include <drv/pci/pciConfigLib.h>
  29. #endif
  30. #undef ETHER_MAP_IP_MULTICAST
  31. #include <etherMultiLib.h>
  32. #include <config.h>
  33. #include <epivers.h>
  34. #include <bcmendian.h>
  35. #include <bcmutils.h>
  36. #include <ethernet.h>
  37. #include <bcmenetmib.h>
  38. #include <bcmenetrxh.h>
  39. #include <etsockio.h>
  40. #include <et_dbg.h>
  41. #include <etc.h>
  42. /* mblk queue */
  43. struct mblkq {
  44. M_BLK_ID head;
  45. M_BLK_ID tail;
  46. uint len;
  47. };
  48. /*
  49.  * Principle vx-specific, per-device software state.
  50.  *
  51.  * The END_OBJ must be the first field in this structure since
  52.  * we overload entry point END_OBJ* with et_info_t* .
  53.  */
  54. typedef struct et_info {
  55. END_OBJ endobj; /* end object */
  56. etc_info_t *etc; /* pointer to common os-independent data */
  57. SEM_ID mutex; /* private lock */
  58. bool netjobpend; /* netjob(et_intr) is pending */
  59. WDOG_ID watchdogid; /* 1 sec et_watchdog timer id */
  60. bool dogtimerset; /* if true: watchdog is running */
  61. void *descmem; /* uncached dma descriptor memory */
  62.     pciinfo_t   pciinfo;
  63. int     ivec; /* interrupt vector */
  64. int     irq; /* interrupt vector */
  65. struct mblkq txq; /* private transmit software queue */
  66. long flags; /* our local flags. */
  67. M_CL_CONFIG mclconfig; /* packet pool */
  68. CL_DESC cldesc[1]; /* cluster buffer pool descriptors */
  69. struct et_info *next; /* point to next et_info_t in chain */
  70. } et_info_t;
  71. #define MAXUNITS 8
  72. static et_info_t *et_global[MAXUNITS];
  73. static et_info_t *et_list = NULL;
  74. #define ONE_SECOND sysClkRateGet()
  75. #ifdef __i386__
  76. /* perf logging */
  77. #define rdtscl(low) 
  78. __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
  79. #define rdmsr(msr,val1,val2) 
  80. __asm__ __volatile__("rdmsr" 
  81. : "=a" (val1), "=d" (val2) 
  82. : "c" (msr))
  83. #define wrmsr(msr,val1,val2) 
  84. __asm__ __volatile__("wrmsr" 
  85. : /* no outputs */ 
  86. : "c" (msr), "a" (val1), "d" (val2))
  87. #define INT_NUM(_a) (_a)
  88. #define INT_NUM_IRQ0 0x20
  89. #define INT_ENABLE(_a) sysIntEnablePIC(_a)
  90. #elif __mips__
  91. #include <vxbsp.h>
  92. #define INT_NUM(_a) (((_a) >= IV_RTIME_VEC)? INT_LVL_IORQ0: 
  93. (INT_LVL_IORQ0 << ((_a) - IV_IORQ0_VEC)))
  94. #undef INT_NUM_IRQ0
  95. #define INT_NUM_IRQ0 0
  96. #define INT_ENABLE(_a) intEnable(_a)
  97. #endif /* __mips__ */
  98. #define CLASS_NET_ETH 0x000200    /* 24 bit class value */
  99. #define DATAHIWAT     50
  100. /* functions called by etc.c */
  101. void et_init(et_info_t *et);
  102. void et_reset(et_info_t *et);
  103. void et_link_up(et_info_t *et);
  104. void et_link_down(et_info_t *et);
  105. void et_up(et_info_t *et);
  106. void et_down(et_info_t *et, int reset);
  107. int et_dump(et_info_t *et, uchar *buf, uint len);
  108. /* local functions */
  109. END_OBJ *et_load(char *initString, void *unused);
  110. static int et_find_device(int unit, int *bus, int *dev, int *func,
  111. uint16 *vendorid, uint16 *deviceid);
  112. static STATUS et_unload(et_info_t *et);
  113. static STATUS et_netpool_alloc(et_info_t *et);
  114. static void et_netpool_free(et_info_t *et);
  115. static void et_free(et_info_t *et);
  116. static void et_vxwatchdog(et_info_t *et);
  117. static void et_vxintr(et_info_t *et);
  118. static void et_sendnext(et_info_t *et);
  119. static void et_watchdog(et_info_t *et);
  120. static void et_sendup(et_info_t *et, struct mbuf *m);
  121. static void et_loginit(void);
  122. static STATUS et_end_start(et_info_t *et);
  123. static STATUS et_end_stop(et_info_t *et);
  124. static int et_ioctl(et_info_t *et, int cmd, caddr_t data);
  125. static STATUS et_send(et_info_t *et, M_BLK_ID pBuf);
  126. static STATUS et_mcastAdd(et_info_t *et, char* pAddress);
  127. static STATUS et_mcastDel(et_info_t *et, char* pAddress);
  128. static STATUS et_mcastGet(et_info_t *et, MULTI_TABLE* pTable);
  129. static void et_config(et_info_t *et);
  130. static void et_enq(struct mblkq *q, M_BLK_ID m);
  131. static M_BLK_ID et_deq(struct mblkq *q);
  132. #ifdef BCMDBG
  133. static void et_dumpet(et_info_t *et, uchar *buf, uint len);
  134. #endif
  135. #ifdef ROBO 
  136. static M_BLK_ID
  137. et_endEtherAddressForm(M_BLK_ID p, M_BLK_ID s, M_BLK_ID d, BOOL bcastFlag);
  138. #else
  139. #define et_endEtherAddressForm endEtherAddressForm
  140. #endif
  141. static NET_FUNCS etFuncTable = {
  142. (FUNCPTR) et_end_start, /* function to start the device. */
  143. (FUNCPTR) et_end_stop, /* function to stop the device. */
  144. (FUNCPTR) et_unload, /* unloading function for the driver. */
  145. (FUNCPTR) et_ioctl, /* ioctl function for the driver. */
  146. (FUNCPTR) et_send, /* send function for the driver. */
  147. (FUNCPTR) et_mcastAdd, /* multicast add function for the driver. */
  148. (FUNCPTR) et_mcastDel, /* multicast delete function for the driver. */
  149. (FUNCPTR) et_mcastGet, /* multicast retrieve function for the driver. */
  150. (FUNCPTR) NULL, /* polling send function -  not supported*/
  151. (FUNCPTR) NULL, /* polling receive function  -  not supported */
  152. et_endEtherAddressForm, /* put address info into a NET_BUFFER */
  153. endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
  154. endEtherPacketAddrGet /* get packet addresses. */
  155. };
  156. #define ET_LOCK(et)     semTake((et)->mutex, WAIT_FOREVER)
  157. #define ET_UNLOCK(et) semGive((et)->mutex)
  158. /*
  159.  * vxWorks 5.x does not directly support shared interrupts.  Unbelievable.
  160.  * Redefine intConnect().
  161.  */
  162. #ifndef __mips__
  163. #if defined(INCLUDE_IL_END) || defined(INCLUDE_IL)
  164. extern STATUS cmn_int_connect(VOIDFUNCPTR *ivec, VOIDFUNCPTR dev_vxintr, int param);
  165. #define intConnect  cmn_int_connect
  166. #endif
  167. #endif
  168. END_OBJ*
  169. et_load(char *initString, void *unused)
  170. {
  171. et_info_t *et;
  172. char *tok;
  173. int unit;
  174. uint16 vendorid, deviceid;
  175. uint32 regaddr;
  176. char irq;
  177. int bus, dev, func;
  178. et = NULL;
  179. bus = dev = func = 0;
  180. regaddr = 0;
  181. irq = 0;
  182. if (initString == NULL)
  183. return (NULL);
  184. /* end driver first pass init */
  185. if (initString[0] == '') {
  186. bcopy("et", initString, 3);
  187. return (NULL);
  188. }
  189. /* get our unit number from the init string */
  190. if ((tok = strtok(initString, ":")) == NULL) {
  191. ET_ERROR(("et_load: garbled initString (%s) - unit number not foundn",
  192. initString));
  193. goto fail;
  194. }
  195. unit = bcm_atoi(tok);
  196. ET_TRACE(("et%d: et_loadn", unit));
  197. #ifndef MSI
  198. if (et_find_device(unit, &bus, &dev, &func, &vendorid, &deviceid) == ERROR) {
  199. ET_ERROR(("et%d: et_load: et_find_device() failed n", unit));
  200. goto fail;
  201. }
  202. pciConfigInLong(bus, dev, func, PCI_CFG_BASE_ADDRESS_0, &regaddr);
  203. pciConfigInByte(bus, dev, func, PCI_CFG_DEV_INT_LINE, &irq);
  204. /* map chip registers */
  205. regaddr = REG_MAP(regaddr, 0);
  206. #endif
  207. /* allocate our private device structure */
  208. if ((et = (et_info_t*) MALLOC(sizeof (et_info_t))) == NULL) {
  209. ET_ERROR(("et%d: et_load: malloc et_info_t failed!n", unit));
  210. goto fail;
  211. }
  212. bzero((char*) et, sizeof (et_info_t));
  213. et->irq = INT_NUM(irq);
  214. et->ivec = (int) INUM_TO_IVEC(irq + INT_NUM_IRQ0);
  215. et->pciinfo.bus = bus;
  216. et->pciinfo.dev = dev;
  217. et->pciinfo.func = func;
  218. ET_TRACE(("et%d: et_load: regaddr %x ivec %d irq %dn",
  219. unit, regaddr, et->ivec, et->irq));
  220. /* initialize private semaphore */
  221. if ((et->mutex = semBCreate(SEM_Q_FIFO, SEM_FULL)) == NULL) {
  222. ET_ERROR(("et%d: et_load: semBCreate failn", unit));
  223. goto fail;
  224. }
  225. /* common load-time initialization */
  226. if ((et->etc = etc_attach((void*)et, vendorid, deviceid, unit, &et->pciinfo,
  227. (void*)regaddr)) == NULL) {
  228. ET_ERROR(("et%d: etc_attach failedn", unit));
  229. goto fail;
  230. }
  231. /* create a watchdog timer */
  232. if ((et->watchdogid = wdCreate()) == NULL ) {
  233. ET_ERROR(("et%d: error creating watchdog timern", unit));
  234. goto fail;
  235. }
  236. et->dogtimerset = FALSE;
  237. /* initialize the END and MIB2 parts of the structure */
  238. if (END_OBJ_INIT(&et->endobj, (DEV_OBJ*)et, "et", unit, &etFuncTable, "END et Driver")
  239. == ERROR)
  240. goto fail;
  241. if (END_MIB_INIT(&et->endobj, M2_ifType_ethernet_csmacd, (char *)&et->etc->cur_etheraddr,
  242. ETHER_ADDR_LEN, ETHERMTU, 100000000) == ERROR)
  243. goto fail;
  244. /* allocate and initialize our private mblk/clblk netpool */
  245. if (et_netpool_alloc(et) == ERROR)
  246. goto fail;
  247. /* set the flags to indicate readiness */
  248. END_OBJ_READY(&et->endobj, (IFF_NOTRAILERS|IFF_BROADCAST|IFF_MULTICAST));
  249. /* register our interrupt handler */
  250. if (intConnect((VOIDFUNCPTR*)et->ivec, (VOIDFUNCPTR)et_vxintr, (int)et) == ERROR) {
  251. ET_ERROR(("et%d: et_load: interrupt connect errorn", unit));
  252. goto fail;
  253. }
  254. et_global[unit] = et;
  255. /* add us to the global linked list */
  256. et->next = et_list;
  257. et_list = et;
  258. return (&et->endobj);
  259. fail:
  260. et_free(et);
  261. return (NULL);
  262. }
  263. /*
  264.  * et_unload - unload a driver from the system
  265.  */
  266. static STATUS
  267. et_unload(et_info_t *et)
  268. {
  269. ET_TRACE(("et%d: et_unloadn", et->etc->unit));
  270. ASSERT(!et->etc->up);
  271. END_OBJECT_UNLOAD(&et->endobj);
  272. et_global[et->etc->unit] = NULL;
  273. et_free(et);
  274. return (OK);
  275. }
  276. static int
  277. et_find_device(int unit, int *bus, int *dev, int *func, uint16 *vendorid, uint16 *deviceid)
  278. {
  279. int found;
  280. int i;
  281. found = 0;
  282. /* find the unit'th instance of a recognized et device */
  283. for (i = 0; i < 32; i++) {
  284. if (pciFindClass(CLASS_NET_ETH, i, bus, dev, func) != OK)
  285. continue;
  286. if (pciConfigInWord(*bus, *dev, *func, 0, vendorid) != OK)
  287. continue;
  288. if (pciConfigInWord(*bus, *dev, *func, 2, deviceid) != OK)
  289. continue;
  290. if (!etc_chipmatch(*vendorid, *deviceid))
  291. continue;
  292. if (found == unit)
  293. return (OK);
  294. found++;
  295. }
  296. ET_ERROR(("et%d: et_find_device:  error finding devicen", unit));
  297. return (ERROR);
  298. }
  299. static void
  300. et_free(et_info_t *et)
  301. {
  302. et_info_t **prev;
  303. if (et == NULL)
  304. return;
  305. ET_TRACE(("et: et_freen"));
  306. /* delete the watchdog timer */
  307. if (et->watchdogid) {
  308. wdDelete(et->watchdogid);
  309. et->watchdogid = NULL;
  310. }
  311. /* free common resources */
  312. if (et->etc) {
  313. etc_detach(et->etc);
  314. et->etc = NULL;
  315. }
  316. /* free private netpool */
  317. et_netpool_free(et);
  318. /* remove us from the global linked list */
  319. for (prev = &et_list; *prev; prev = &(*prev)->next)
  320. if (*prev == et) {
  321. *prev = et->next;
  322. break;
  323. }
  324. free((char*)et);
  325. }
  326. /* alloc and init a private mblk/clblk netpool */
  327. STATUS
  328. et_netpool_alloc(et_info_t *et)
  329. {
  330. ET_TRACE(("et%d: et_netpool_allocn", et->etc->unit));
  331. /* alloc the netpool structure itself */
  332. if ((et->endobj.pNetPool = (NET_POOL_ID) MALLOC(sizeof (NET_POOL))) == NULL)
  333. goto error;
  334. et->mclconfig.mBlkNum = MIN_PKTS;
  335. et->mclconfig.clBlkNum = MIN_PKTS;
  336. /* sanity check */
  337. ASSERT(BUFSZ == VXCLSIZE);
  338. /* create a single 2Kbyte cluster buffer pool */
  339. et->cldesc[0].clNum = MIN_CLUSTERS;
  340. et->cldesc[0].clSize = VXCLSIZE;
  341. /* calculate the total memory for all the M_BLKs and CL_BLKs */
  342. et->mclconfig.memSize = (et->mclconfig.mBlkNum * (MSIZE + sizeof (long))) +
  343. (et->mclconfig.clBlkNum * (CL_BLK_SZ + sizeof(long)));
  344. /* allocate the M_BLK&CL_BLK pool */
  345. if ((et->mclconfig.memArea = MALLOC(et->mclconfig.memSize)) == NULL)
  346. goto error;
  347. /* calculate the memory size of all the clusters. */
  348. et->cldesc[0].memSize = (et->cldesc[0].clNum * (VXCLSIZE + 8)) + sizeof (int);
  349. /* allocate the cluster buffer pool */
  350. if ((et->cldesc[0].memArea = memalign(2048, et->cldesc[0].memSize)) == NULL)
  351. goto error;
  352. ASSERT(ISALIGNED(et->cldesc[0].memArea, 2048));
  353. /* now init the netpool */
  354. if (netPoolInit(et->endobj.pNetPool, &et->mclconfig, &et->cldesc[0], 1, NULL) == ERROR)
  355. goto error;
  356. return (OK);
  357. error:
  358. ET_ERROR(("et%d: et_netpool_alloc: malloc failed!n", et->etc->unit));
  359. et_netpool_free(et);
  360. return (ERROR);
  361. }
  362. static void
  363. et_netpool_free(et_info_t *et)
  364. {
  365. ET_TRACE(("et%d: et_netpool_freen", et->etc->unit));
  366. if (et->cldesc[0].memArea) {
  367. MFREE(et->cldesc[0].memArea, et->cldesc[0].memSize);
  368. et->cldesc[0].memSize = 0;
  369. et->cldesc[0].memArea = NULL;
  370. }
  371. if (et->mclconfig.memArea) {
  372. MFREE(et->mclconfig.memArea, et->mclconfig.memSize);
  373. et->mclconfig.memSize = 0;
  374. et->mclconfig.memArea = NULL;
  375. }
  376. if (et->endobj.pNetPool) {
  377. netPoolDelete(et->endobj.pNetPool);
  378. et->endobj.pNetPool = NULL;
  379. }
  380. }
  381. void
  382. et_init(et_info_t *et)
  383. {
  384. ET_TRACE(("et%d: et_initn", et->etc->unit));
  385. ET_LOG("et_init", 0);
  386. et_loginit();
  387. /* reset the interface */
  388. et_reset(et);
  389. /* initialize the driver and chip */
  390. etc_init(et->etc);
  391. et->endobj.flags |= (IFF_RUNNING | IFF_UP);
  392. }
  393. void
  394. et_reset(et_info_t *et)
  395. {
  396. ET_TRACE(("et%d: et_resetn", et->etc->unit));
  397. /* common reset code */
  398. etc_reset(et->etc);
  399. et->endobj.flags &= ~IFF_RUNNING;
  400. }
  401. void
  402. et_link_up(et_info_t *et)
  403. {
  404. et->endobj.mib2Tbl.ifOperStatus = 1;
  405. ET_ERROR(("et%d: link upn", et->etc->unit));
  406. }
  407. void
  408. et_link_down(et_info_t *et)
  409. {
  410. et->endobj.mib2Tbl.ifOperStatus = 0;
  411. ET_ERROR(("et%d: link downn", et->etc->unit));
  412. }
  413. void
  414. et_up(et_info_t *et)
  415. {
  416. ET_TRACE(("et%d: et_upn", et->etc->unit));
  417. etc_up(et->etc);
  418. END_FLAGS_SET (&et->endobj, IFF_UP | IFF_RUNNING);
  419. /* start a one second the watchdog timer */
  420. if (et->dogtimerset == FALSE) {
  421. if (wdStart(et->watchdogid, ONE_SECOND, (FUNCPTR)et_vxwatchdog, (int)et) != OK) {
  422. ET_ERROR(("et%d: et_up: Error starting the watchdogn", et->etc->unit));
  423. }
  424. et->dogtimerset = TRUE;
  425. }
  426. }
  427. void
  428. et_down(et_info_t *et, int reset)
  429. {
  430. etc_info_t *etc;
  431. M_BLK_ID m;
  432. etc = et->etc;
  433. ET_TRACE(("et%d: et_downn", etc->unit));
  434. /* cancel the watchdog timer */
  435. if (et->dogtimerset) {
  436. wdCancel(et->watchdogid);
  437. et->dogtimerset = FALSE;
  438. }
  439. etc_down(etc, reset);
  440.     /* mark the driver as down */
  441.     END_FLAGS_CLR (&et->endobj, IFF_UP | IFF_RUNNING);
  442. /* flush the txq */
  443. while ((m = (M_BLK_ID) et_deq(&et->txq)))
  444. netMblkClChainFree(m);
  445. }
  446. int
  447. et_dump(et_info_t *et, uchar *buf, uint len)
  448. {
  449. /* big enough? */
  450. if (len < 4096)
  451. return (4096);
  452. sprintf(buf, "et%d: %s %s version %sn", et->etc->unit,
  453. __DATE__, __TIME__, EPI_VERSION_STR);
  454. #ifdef BCMDBG
  455. et_dumpet(et, &buf[strlen(buf)], len - strlen(buf));
  456. etc_dump(et->etc, &buf[strlen(buf)], len - strlen(buf));
  457. #endif
  458. return (strlen(buf));
  459. }
  460. static void
  461. et_vxwatchdog(et_info_t *et)
  462. {
  463. netJobAdd((FUNCPTR)et_watchdog, (int)et, 0, 0, 0, 0);
  464. }
  465. static void
  466. et_watchdog(et_info_t *et)
  467. {
  468. #if 0
  469. ET_TRACE(("et%d: watchdogn", et->etc->unit));
  470. ET_LOG("et_watchdog", 0);
  471. #endif
  472. ET_LOCK(et);
  473. etc_watchdog(et->etc);
  474. /* restart timer */
  475. wdStart(et->watchdogid, ONE_SECOND, (FUNCPTR)et_vxwatchdog, (int)et);
  476. ET_UNLOCK(et);
  477. ET_LOG("et_watchdog retn", 0);
  478. }
  479. static void
  480. et_sendnext(et_info_t *et)
  481. {
  482. M_BLK_ID m;
  483. etc_info_t *etc;
  484. etc = et->etc;
  485. ET_TRACE(("et%d: et_sendnextn", etc->unit));
  486. ET_LOG("et_sendnext", 0);
  487. /* dequeue and send each packet */
  488. while ((*etc->txavail > 8)
  489. && (etc->pioactive == NULL)
  490. && (m = et_deq(&et->txq))) {
  491. ET_PRHDR("tx", (struct ether_header*) m->mBlkHdr.mData, etc_totlen(etc, (void*)m));
  492. ET_PRPKT("txpkt", m->mBlkHdr.mData, m->mBlkHdr.mLen);
  493. /* transmit the frame */
  494. (*etc->chops->tx)(etc->ch, (void*)m);
  495. etc->txframe++;
  496. etc->txbyte += m->mBlkHdr.mLen;
  497. }
  498. ET_LOG("et_sendnext retn", 0);
  499. }
  500. static void
  501. et_intr(et_info_t *et, uint events)
  502. {
  503. etc_info_t *etc;
  504. struct chops *chops;
  505. void *ch;
  506. M_BLK_ID m;
  507. etc = et->etc;
  508. chops = etc->chops;
  509. ch = etc->ch;
  510. ASSERT(events);
  511. ET_TRACE(("et%d: et_intr: events 0x%xn", etc->unit, events));
  512. ET_LOG("et_intr: events 0x%x", events);
  513. ET_LOCK(et);
  514. if (events & INTR_RX) {
  515. while ((m = (M_BLK_ID) (*chops->rx)(ch)))
  516. et_sendup(et, m);
  517. /* post more rx bufs */
  518. (*chops->rxfill)(ch);
  519. }
  520. if (events & INTR_TX)
  521. (*chops->txreclaim)(ch, FALSE);
  522. if (events & INTR_ERROR)
  523. if ((*chops->errors)(ch))
  524. et_init(et);
  525. /* run the tx queue */
  526. if (et->txq.len)
  527. et_sendnext(et);
  528. et->netjobpend = FALSE;
  529. /* re-enable interrupts */
  530. (*chops->intrson)(ch);
  531. ET_UNLOCK(et);
  532. ET_LOG("et_intr retn", 0);
  533. }
  534. /* just a wrapper for et_intr() */
  535. static void
  536. et_vxintr(et_info_t *et)
  537. {
  538. uint events;
  539. /* guard against shared interrupts */
  540. if (!et->etc->up)
  541. goto done;
  542. events = (*et->etc->chops->getintrevents)(et->etc->ch);
  543. ET_LOG("et_vxintr: events 0x%x", events);
  544. if (!(events & INTR_NEW) || et->netjobpend)
  545. goto done;
  546. /* disable device interrupts */
  547. (*et->etc->chops->intrsoff)(et->etc->ch);
  548. et->netjobpend = TRUE;
  549. netJobAdd((FUNCPTR)et_intr, (int)et, events, 0, 0 ,0);
  550. done:
  551. ET_LOG("et_vxintr retn", 0);
  552. }
  553. static void
  554. et_sendup(et_info_t *et, M_BLK_ID m)
  555. {
  556. bcmenetrxh_t *rxh;
  557. uint16 flags;
  558. uchar eabuf[32];
  559. #if 0
  560. sysSerialPrintString("et_sendupn");
  561. ET_PRPKT("rxpktraw", (uchar*)m->mBlkHdr.mData, m->mBlkHdr.mLen);
  562. #endif
  563. /* packet buffer starts with rxh */
  564. rxh = (bcmenetrxh_t*) m->mBlkHdr.mData;
  565. /* strip off rxh */
  566. m->mBlkHdr.mData += HWRXOFF;
  567. m->mBlkHdr.mLen -= HWRXOFF;
  568. ET_TRACE(("et%d: et_sendup: %d bytesn", et->etc->unit, m->mBlkHdr.mLen));
  569. ET_LOG("et_sendup: len %d", m->mBlkHdr.mLen);
  570. et->etc->rxframe++;
  571. et->etc->rxbyte += m->m_len;
  572. /* eh should now be aligned 2-mod-4 */
  573. ASSERT(((uint)m->mBlkHdr.mData & 3) == 2);
  574. /* strip off crc32 */
  575. m->mBlkHdr.mLen -= ETHER_CRC_LEN;
  576. ET_PRHDR("rx", (struct ether_header*)m->mBlkHdr.mData, m->mBlkHdr.mLen);
  577. ET_PRPKT("rxpkt", (uchar*)m->mBlkHdr.mData, m->mBlkHdr.mLen);
  578. /* check for reported frame errors */
  579. flags = ltoh16(rxh->flags);
  580. if (flags & (RXF_NO | RXF_RXER | RXF_CRC | RXF_OV))
  581. goto err;
  582. m->mBlkHdr.mFlags |= M_PKTHDR;
  583. m->mBlkPktHdr.len = m->mBlkHdr.mLen;
  584. /* The vx router 1.0 stack is reentrant so we 
  585. need to drop the perimeter lock here */
  586. ET_UNLOCK(et);
  587. END_RCV_RTN_CALL(&et->endobj, m);
  588. ET_LOCK(et);
  589. ET_LOG("et_sendup ret", 0);
  590. return;
  591. err:
  592. bcm_ether_ntoa(((struct ether_header*)m->mBlkHdr.mData)->ether_shost, eabuf);
  593. if (flags & RXF_NO) {
  594. ET_ERROR(("et%d: rx: crc error (odd nibbles) from %sn", et->etc->unit, eabuf));
  595. }
  596. if (flags & RXF_RXER) {
  597. ET_ERROR(("et%d: rx: symbol error from %sn", et->etc->unit, eabuf));
  598. }
  599. if ((flags & RXF_CRC) == RXF_CRC) {
  600. ET_ERROR(("et%d: rx: crc error from %sn", et->etc->unit, eabuf));
  601. }
  602. if (flags & RXF_OV) {
  603. ET_ERROR(("et%d: rx: fifo overflown", et->etc->unit));
  604. }
  605. netMblkClFree(m);
  606. return;
  607. }
  608. /*
  609.  * Debugging/Performance Logging Functions
  610.  */
  611. static void
  612. et_loginit(void)
  613. {
  614. #if defined(BCMDBG) && defined(__i386__)
  615. if (et_msg_level & 2048)
  616. wrmsr(0x186, 0x4700c0, 0); /* enable P6 instr counting */
  617. #ifdef notdef
  618. wrmsr(0x11, 0xd6, 0); /* enable Pentium instr counting */
  619. #endif
  620. #endif /* BCMDBG && __i386__ */
  621. }
  622. #ifdef BCMDBG
  623. static void
  624. et_dumpet(et_info_t *et, uchar *buf, uint len)
  625. {
  626. sprintf(&buf[strlen(buf)], "et %p flags 0x%x txq.len %dn",
  627. et, (uint)et->flags, et->txq.len);
  628. sprintf(&buf[strlen(buf)], "n");
  629. }
  630. /* obtaining cycle and instruction counts is processor specific */
  631. void
  632. et_log(char *fmt, ulong a1)
  633. {
  634. static uint32 lasttsc = 0;
  635. static uint32 lastinstr = 0;
  636. uint32 tsc, instr;
  637. #ifdef __i386__
  638. uint32 dummy;
  639. /* read cycle counter */
  640. rdtscl(tsc);
  641. /* read ctr1 value */
  642. rdmsr(0xc1, instr, dummy); /* read P6 CTR0 register */
  643. #ifdef notdef
  644. rdmsr(0x12, instr, dummy); /* read Pentium CTR0 register */
  645. #endif
  646. #endif /* __i386__ */
  647. #if defined(__mips__)
  648. /* readCount() and readInstr() must be provided by the bsp */
  649. tsc = readCount();
  650. instr = readInstr();
  651. #endif
  652. /* call common log handler */
  653. etc_log(tsc - lasttsc, instr - lastinstr, fmt, a1);
  654. /* update last values */
  655. lasttsc = tsc;
  656. lastinstr = instr;
  657. }
  658. #endif /* BCMDBG */
  659. /*
  660.  * et_end_start - start the device
  661.  */
  662. static STATUS
  663. et_end_start(et_info_t *et)
  664. {
  665. ET_TRACE(("et%d: et_end_startn", et->etc->unit));
  666. ET_LOCK(et);
  667. et_up(et);
  668. #ifndef MSI
  669. INT_ENABLE(et->irq);
  670. #endif
  671. ET_UNLOCK(et);
  672. return (OK);
  673. }
  674. /*
  675.  * et_end_stop - stop the device
  676.  */
  677. static STATUS
  678. et_end_stop(et_info_t *et)
  679. {
  680. ET_TRACE(("et%d: et_end_stopn", et->etc->unit));
  681. ET_LOCK(et);
  682. et_down(et, 1);
  683. ET_UNLOCK(et);
  684. return (OK);
  685. }
  686. /*
  687.  * et_send - the driver send routine
  688.  */
  689. static STATUS
  690. et_send(et_info_t *et, M_BLK_ID m)
  691. {
  692. ET_TRACE(("et%d: et_send: len %d n", et->etc->unit, m->mBlkPktHdr.len));
  693. END_TX_SEM_TAKE(&et->endobj, WAIT_FOREVER);
  694. ET_LOCK(et);
  695. /* discard if transmit queue is too full */
  696. if (et->txq.len > DATAHIWAT)
  697. goto qfull;
  698. et_enq(&et->txq, m);
  699. et_sendnext(et);
  700. ET_UNLOCK(et);
  701. END_TX_SEM_GIVE(&et->endobj);
  702. /* bump the statistic counter. */
  703. END_ERR_ADD(&et->endobj, MIB2_OUT_UCAST, +1);
  704. return (OK);
  705. qfull:
  706. ET_ERROR(("et%d: et_send: txq fulln", et->etc->unit));
  707. et->etc->txnobuf++;
  708. et->etc->txerror++;
  709. ET_UNLOCK(et);
  710. END_TX_SEM_GIVE(&et->endobj);
  711. return (END_ERR_BLOCK);
  712. }
  713. static int
  714. et_ioctl(et_info_t *et, int cmd, caddr_t data)
  715. {
  716. int error;
  717. long value;
  718. etc_info_t  *etc;
  719. etc = et->etc;
  720. error = 0;
  721. ET_TRACE(("et%d: et_ioctln", et->etc->unit));
  722. switch (cmd) {
  723. case EIOCSADDR:
  724. if (data == NULL)
  725. return (EINVAL);
  726. bcopy((char*)data, (char*)et->endobj.mib2Tbl.ifPhysAddress.phyAddress, ETHER_ADDR_LEN);
  727. bcopy((char*)data, (char*)&etc->cur_etheraddr, ETHER_ADDR_LEN);
  728. et_config(et);
  729. break;
  730. case EIOCGADDR:
  731. if (data == NULL)
  732. return (EINVAL);
  733. bcopy((char*)&etc->cur_etheraddr, (char *)data, ETHER_ADDR_LEN);
  734. break;
  735. case EIOCSFLAGS:
  736. value = (long)data;
  737. if (value < 0) {
  738. value = ~value;
  739. END_FLAGS_CLR(&et->endobj, value);
  740. }
  741. else {
  742. END_FLAGS_SET(&et->endobj, value);
  743. }
  744. et_config(et);
  745. break;
  746. case EIOCGFLAGS:
  747. *(int*)data = END_FLAGS_GET(&et->endobj);
  748. break;
  749. case EIOCPOLLSTART:
  750. ASSERT(0); /* not supported */
  751. break;
  752. case EIOCPOLLSTOP:
  753. ASSERT(0); /* not supported */
  754. break;
  755. case EIOCGMIB2: /* return MIB information */
  756. if (data == NULL)
  757. return (EINVAL);
  758. /* update some of the mib counters */
  759. et->endobj.mib2Tbl.ifInErrors = etc->rxerror;
  760. et->endobj.mib2Tbl.ifOutErrors = etc->txerror;
  761. et->endobj.mib2Tbl.ifInOctets = etc->rxbyte;
  762. et->endobj.mib2Tbl.ifOutOctets = etc->txbyte;
  763. et->endobj.mib2Tbl.ifInUcastPkts = etc->rxframe;
  764. et->endobj.mib2Tbl.ifOutUcastPkts = etc->txframe;
  765. bcopy((char *)&et->endobj.mib2Tbl, (char *)data,
  766. sizeof(et->endobj.mib2Tbl));
  767. break;
  768. case EIOCGFBUF: /* return minimum First Buffer for chaining */
  769. if (data == NULL)
  770. return (EINVAL);
  771. *(int *)data = ETHER_MAX_LEN;
  772. break;
  773. #ifdef ROBO
  774. case EIOCGNPT:
  775.         if (et->etc->unit == 1) {
  776.             return(OK);
  777.         } else {
  778.             return(EINVAL);
  779.         }
  780. #endif
  781. default:
  782. error = EINVAL;
  783. }
  784. return (error);
  785. }
  786. /*
  787.  * et_config - Reconfigure the interface to match the current flag/multicast settings
  788.  */
  789. static void
  790. et_config(et_info_t *et)
  791. {
  792. int i;
  793. ETHER_MULTI *pCurr;
  794. uchar *src, *dst;
  795. ET_TRACE(("et%d: et_confign", et->etc->unit));
  796. ET_LOCK(et);
  797. /* set promiscuous mode if it's asked for. */
  798. et->etc->promisc = (et->endobj.flags & IFF_PROMISC)? TRUE: FALSE;
  799. et->etc->allmulti = (et->endobj.flags & IFF_ALLMULTI)? TRUE: FALSE;
  800. /* set up address filter for multicasting */
  801. pCurr = END_MULTI_LST_FIRST(&et->endobj);
  802. i = 0;
  803. while (pCurr != NULL) {
  804. src = (unsigned char *)&pCurr->addr;
  805. dst = (unsigned char *)&et->etc->multicast[i];
  806. bcopy(src, dst, ETHER_ADDR_LEN);
  807. pCurr = END_MULTI_LST_NEXT(pCurr);
  808. i++;
  809. }
  810. et->etc->nmulticast = i;
  811. if (i) {
  812. if (et->etc->nmulticast == et->endobj.nMulti) {
  813. ET_ERROR(("et%d: et_config: etc.nmulticast %d, endobj.nMulti %dn",
  814. et->etc->unit, et->etc->nmulticast, et->endobj.nMulti));
  815. }
  816. }
  817. if (et->endobj.flags & IFF_UP)
  818. et_up(et);
  819. else if (et->endobj.flags & IFF_RUNNING)
  820. et_down(et, 1);
  821. ET_UNLOCK(et);
  822. }
  823. /*
  824.  * et_mcastAdd - add a multicast address for the device
  825.  */
  826. static STATUS
  827. et_mcastAdd(et_info_t *et, char* pAddress)
  828. {
  829. int error;
  830. ET_TRACE(("et%d: et_mcastAddn", et->etc->unit));
  831. if ((error = etherMultiAdd(&et->endobj.multiList, pAddress)) == ENETRESET)
  832. et_config(et);
  833. return(OK);
  834. }
  835. /*
  836.  * et_mcastDel - delete a multicast address for the device
  837.  */
  838. static STATUS
  839. et_mcastDel(et_info_t *et,char* pAddress)
  840. {
  841. int error;
  842. ET_TRACE(("et%d: et_mcastDeln", et->etc->unit));
  843. if ((error = etherMultiDel(&et->endobj.multiList, (char *)pAddress)) == ENETRESET)
  844. et_config(et);
  845. return (OK);
  846. }
  847. /*
  848.  * et_mcastGet - get the multicast address list for the device
  849.  */
  850. static STATUS
  851. et_mcastGet(et_info_t *et, MULTI_TABLE* pTable)
  852. {
  853. ET_TRACE(("et%d: et_mcastGetn", et->etc->unit));
  854. return (etherMultiGet(&et->endobj.multiList, pTable));
  855. }
  856. #ifdef ROBO 
  857. /*
  858.  * et_endEtherAddressForm - src/dst mac updation routine
  859.  */
  860. M_BLK_ID
  861. et_endEtherAddressForm(M_BLK_ID p, M_BLK_ID s, M_BLK_ID d, BOOL bcastFlag)
  862. {
  863.     char zd[] = {0,0,0,0,0,0};
  864.     if (memcmp(d->mBlkHdr.mData,zd,6) == 0) {
  865.         return(p);
  866.     }
  867.     return (endEtherAddressForm(p,s,d,bcastFlag));
  868. }
  869. #endif
  870. /* enqueue mblk on queue */
  871. static void
  872. et_enq(struct mblkq *q, M_BLK_ID m)
  873. {
  874. ASSERT(m->mBlkHdr.mNextPkt == NULL);
  875. if (q->tail == NULL) {
  876. ASSERT(q->head == NULL);
  877. q->head = q->tail = m;
  878. }
  879. else {
  880. ASSERT(q->head);
  881. ASSERT(q->tail->mBlkHdr.mNextPkt == NULL);
  882. q->tail->mBlkHdr.mNextPkt = m;
  883. q->tail = m;
  884. }
  885. q->len++;
  886. }
  887. /* dequeue mblk from queue */
  888. static M_BLK_ID
  889. et_deq(struct mblkq *q)
  890. {
  891. M_BLK_ID m;
  892. if ((m = q->head)) {
  893. ASSERT(q->tail);
  894. q->head = m->mBlkHdr.mNextPkt;
  895. m->mBlkHdr.mNextPkt = NULL;
  896. q->len--;
  897. if (q->head == NULL)
  898. q->tail = NULL;
  899. }
  900. else {
  901. ASSERT(q->tail == NULL);
  902. }
  903. return (m);
  904. }
  905. #ifdef BCM47XX_CHOPS
  906. /*
  907.  * 47XX-specific shared mdc/mdio contortion:
  908.  * Find the et associated with the same chip as <et>
  909.  * and coreunit matching <coreunit>.
  910.  */
  911. void*
  912. et_phyfind(et_info_t *et, uint coreunit)
  913. {
  914. et_info_t *tmp;
  915. /* walk the list et's */
  916. for (tmp = et_list; tmp; tmp = tmp->next) {
  917. if (et->etc == NULL)
  918. continue;
  919. if (tmp->pciinfo.bus != et->pciinfo.bus)
  920. continue;  
  921. if (tmp->etc->coreunit != coreunit)
  922. continue;
  923. break;
  924. }
  925. return (tmp);
  926. }
  927. /* shared phy read entry point */
  928. uint16
  929. et_phyrd(et_info_t *et, uint phyaddr, uint reg)
  930. {
  931. uint16 val;
  932. ET_LOCK(et);
  933. val = et->etc->chops->phyrd(et->etc->ch, phyaddr, reg);
  934. ET_UNLOCK(et);
  935. return (val);
  936. }
  937. /* shared phy write entry point */
  938. void
  939. et_phywr(et_info_t *et, uint phyaddr, uint reg, uint16 val)
  940. {
  941. ET_LOCK(et);
  942. et->etc->chops->phywr(et->etc->ch, phyaddr, reg, val);
  943. ET_UNLOCK(et);
  944. }
  945. #endif /* BCM47XX_CHOPS */
  946. #ifdef BCMINTERNAL
  947. #ifdef BCMDBG
  948. /* debugging routines callable from the shell */
  949. static uchar buf1[64 * 1024];
  950. void
  951. set_et_msg_level(int level) {
  952. et_msg_level = level;
  953. }
  954. void
  955. dump_etstats(int unit) {
  956. et_dump(et_global[unit], buf1, 4096);
  957. printf("%s", buf1);
  958. }
  959. void dump_etlog(int unit) {
  960. etc_dumplog(buf1);
  961. printf("%s", buf1);
  962. }
  963. void up_et(int unit) {
  964. et_up(et_global[unit]);
  965. }
  966. #endif
  967. #endif