if_elc.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:26k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* if_elc.c - SMC 8013WC Ethernet network interface driver */
  2. /* Copyright 1984-1999 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02b,11jan99,aeg  fixed multiple semaphore inits in elcattach ().
  8. 02a,15jul97,spm  removed driver initialization from ioctl support (SPR #8831)
  9. 01z,15may97,spm  reverted to bcopy routines for mbufs in BSD 4.4
  10. 01y,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.4
  11. 01x,14jun95,hdn  removed function declarations defined in sysLib.h.
  12. 01w,01feb95,jdi  doc cleanup; made elcShow() NOMANUAL.
  13. 01v,29nov94,hdn  added a semaphore in ultraPut().
  14. 01u,12nov94,tmk  removed some IMPORTed function decs and included unixLib.h
  15. 01t,03oct94,hdn  implemented two transmit buffers.
  16.  enabled getting OUT2 bit of IRR in EEROM.
  17.  deleted while loop in ultraPut().
  18. 01s,03dec93,hdn  added documentation.
  19. 01r,29nov93,hdn  removed netJobAdd (elcPut, ..) in elcIntr().
  20. 01q,28nov93,hdn  changed NELC to 1.
  21. 01p,24nov93,hdn  removed TXING and txreq flags.
  22.  added checking TXP bit before the transmission. 
  23. 01o,23nov93,hdn  removed cacheInvalidate(). 
  24. 01n,22nov93,hdn  added elcdetach () for the warm start.
  25. 01m,15nov93,hdn  added support for Thin Ethernet(10Base2, BNC)
  26. 01l,05nov93,hdn  added cacheFlush() and cacheInvalidate().
  27. 01k,04nov93,hdn  cleaned up.
  28. 01j,03nov93,hdn  made RAM size 16Kbytes. cleaned up.
  29. 01i,05sep93,hdn  added sysIntEnablePIC ().
  30. 01h,02sep93,hdn  added macros about PIC.
  31. 01g,11aug93,hdn  changed a way of setting a handler for stray interrupt IRQ7.
  32. 01f,23jun93,hdn  made address, irq software configuarable.
  33. 01e,17jun93,hdn  updated to 5.1.
  34. 01d,28may93,hdn  deleted a zero wait bit. fixed a race condition.
  35. 01c,23apr93,hdn  fixed a bug which appears when a packet is wrapped.
  36.  fixed a stray interrupt 15.
  37.  moved a interrupt masking to the top of elcGet.
  38. 01b,03jan93,hdn  fixed bugs and cleaned up.
  39. 01a,09jun92,hdn  written.
  40. */
  41. /*
  42. DESCRIPTION
  43. This module implements the SMC 8013WC network interface driver.
  44. BOARD LAYOUT
  45. The W1 jumper should be set in position SOFT.
  46. The W2 jumper should be set in position NONE/SOFT.
  47. CONFIGURATION
  48. The I/O address, RAM address, RAM size, and IRQ levels are defined in config.h.
  49. The I/O address must match the one stored in EEROM.  The configuration 
  50. software supplied by the manufacturer should be used to set the I/O address. 
  51. IRQ levels 2,3,4,5,7,9,10,11,15 are supported.  Thick Ethernet (AUI) and
  52. Thin Ethernet (BNC) are configurable by changing the macro CONFIG_ELC
  53. in config.h.
  54. EXTERNAL INTERFACE
  55. The only user-callable routines are elcattach() and elcShow():
  56. .iP elcattach() 14
  57. publishes the `elc' interface and initializes the driver and device.
  58. .iP elcShow()
  59. displays statistics that are collected in the interrupt handler.
  60. .LP
  61. */
  62. #include "vxWorks.h"
  63. #include "net/mbuf.h"
  64. #include "net/protosw.h"
  65. #include "net/unixLib.h"
  66. #include "ioctl.h"
  67. #include "socket.h"
  68. #include "errnoLib.h"
  69. #include "net/uio.h"
  70. #include "net/if.h"
  71. #include "net/route.h"
  72. #include "netinet/in.h"
  73. #include "netinet/in_systm.h"
  74. #include "netinet/ip.h"
  75. #include "netinet/ip_var.h"
  76. #include "netinet/in_var.h"
  77. #include "netinet/if_ether.h"
  78. #include "etherLib.h"
  79. #include "vme.h"
  80. #include "iv.h"
  81. #include "iosLib.h"
  82. #include "ioLib.h"
  83. #include "memLib.h"
  84. #include "net/systm.h"
  85. #include "net/if_subr.h"
  86. #include "sysLib.h"
  87. #include "vxLib.h"
  88. #include "stdio.h"
  89. #include "intLib.h"
  90. #include "logLib.h"
  91. #include "string.h"
  92. #include "netLib.h"
  93. #include "stdlib.h"
  94. #include "semLib.h"
  95. #include "cacheLib.h"
  96. #include "drv/intrCtl/i8259a.h"
  97. #include "drv/netif/if_elc.h"
  98. /*
  99.  * Ethernet software status per interface.
  100.  *
  101.  * Each interface is referenced by a network interface structure,
  102.  * es_if, which the routing code uses to locate the interface.
  103.  * This structure contains the output queue for the interface, its address, ...
  104.  */
  105. #define NELC 1 /* max number of ELC controllers */
  106. LOCAL ELC_SOFTC elc_softc [NELC];
  107. LOCAL IRQ_TABLE irqTable [] =
  108.     {
  109.     {0xff,  0xff}, /* IRQ0  not supported  */
  110.     {0xff,  0xff}, /* IRQ1  not supported  */
  111.     {0x0,   0x0}, /* IRQ2   */
  112.     {0x0,   0x1}, /* IRQ3   */
  113.     {0x1,   0x3}, /* IRQ4   */
  114.     {0x0,   0x2}, /* IRQ5   */
  115.     {0xff,  0xff}, /* IRQ6  not supported  */
  116.     {0x0,   0x3}, /* IRQ7   */
  117.     {0xff,  0xff}, /* IRQ8  not supported  */
  118.     {0x0,   0x0}, /* IRQ9   */
  119.     {0x1,   0x0}, /* IRQ10  */
  120.     {0x1,   0x1}, /* IRQ11  */
  121.     {0xff,  0xff}, /* IRQ12 not supported  */
  122.     {0xff,  0xff}, /* IRQ13 not supported  */
  123.     {0xff,  0xff}, /* IRQ14 not supported  */
  124.     {0x1,   0x2}, /* IRQ15  */
  125.     {0, 0},
  126.     };
  127. LOCAL BOOL elcAttached = FALSE;
  128. LOCAL SEMAPHORE elcSyncSem; /* syncronization semaphore */
  129. /* forward static functions */
  130. static void elcreset (int unit);
  131. static int elcinit (int unit);
  132. static void elcintr (int unit);
  133. static int elcioctl (struct ifnet *ifp, int cmd, caddr_t data);
  134. #ifdef BSD43_DRIVER
  135. static int elcoutput (struct ifnet *ifp, struct mbuf *m0, struct sockaddr
  136. *dst);
  137. #endif
  138. static void elcGet (int unit);
  139. #ifdef BSD43_DRIVER
  140. static void elcPut (int unit);
  141. #else
  142. static void elcPut (ELC_SOFTC *sc);
  143. #endif
  144. static void elcReset (int unit);
  145. static void elcGetAddr (int unit);
  146. static void bicInit (int unit);
  147. static void elcInit (int unit);
  148. static UCHAR elcGetCurr (int unit);
  149.        void elcShow (int unit, BOOL zap);
  150.        void elcdetach (int unit);
  151. /*******************************************************************************
  152. *
  153. * elcattach - publish the `elc' network interface and initialize the driver and device
  154. *
  155. * This routine attaches an `elc' Ethernet interface to the network if the
  156. * device exists.  It makes the interface available by filling in the network
  157. * interface record.  The system will initialize the interface when it is
  158. * ready to accept packets.
  159. *
  160. * RETURNS: OK or ERROR.
  161. *
  162. * SEE ALSO: ifLib, netShow
  163. */
  164. STATUS elcattach 
  165.     (
  166.     int unit,           /* unit number */
  167.     int ioAddr,         /* address of elc's shared memory */
  168.     int ivec,           /* interrupt vector to connect to */
  169.     int ilevel,         /* interrupt level */
  170.     int memAddr,        /* address of elc's shared memory */
  171.     int memSize,        /* size of elc's shared memory */
  172.     int config /* 0: RJ45 + AUI(Thick)  1: RJ45 + BNC(Thin) */
  173.     )
  174.     {
  175.     FAST ELC_SOFTC *sc = &elc_softc[unit];
  176.     if ((UINT)unit >= NELC)
  177. {
  178. errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);
  179. return (ERROR);
  180. }
  181.     sc->bicAddr = ioAddr;
  182.     sc->elcAddr = ioAddr + 0x10;
  183.     sc->memAddr = memAddr;
  184.     sc->memSize = memSize;
  185.     if (ilevel == 0  || ilevel == 1  || ilevel == 6 || ilevel == 8 ||
  186. ilevel == 12 || ilevel == 13 || ilevel == 14)
  187. ilevel = 3;                     /* default is IRQ3 */
  188.     sc->intLevel = ilevel;
  189.     sc->intVec = ivec;
  190.     sc->config = config;
  191.     sc->transmitPage[0] = SMC8013WC_TSTART0;
  192.     sc->transmitPage[1] = SMC8013WC_TSTART1;
  193.     sc->transmitCnt = 0;
  194.     /* synchronization semaphore must be initialized only once */
  195.     if (!elcAttached)
  196. semBInit (&elcSyncSem, SEM_Q_FIFO, SEM_FULL);
  197.     bicInit (unit); /* initialize BIC */
  198.     elcInit (unit); /* initialize ELC */
  199.     elcGetAddr (unit); /* get ethernet address */
  200.     (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (ivec), (VOIDFUNCPTR)elcintr, unit);
  201.     /* enable interrupt */
  202.     sysOutByte (ELC_INTMASK (sc->elcAddr), 
  203. IM_OVWE | IM_TXEE | IM_PTXE | IM_PRXE);
  204.     sysIntEnablePIC (ilevel);
  205. #ifdef BSD43_DRIVER
  206.     ether_attach (&sc->es_if, unit, "elc", (FUNCPTR)elcinit, (FUNCPTR)elcioctl,
  207.   (FUNCPTR)elcoutput, (FUNCPTR)elcreset);
  208. #else
  209.     ether_attach (
  210.                  &sc->es_if, 
  211.                  unit, 
  212.                  "elc", 
  213.                  (FUNCPTR)elcinit, 
  214.                  (FUNCPTR)elcioctl,
  215.  (FUNCPTR)ether_output, 
  216.                  (FUNCPTR)elcreset
  217.                  );
  218.     sc->es_if.if_start = (FUNCPTR)elcPut;
  219. #endif
  220.     elcinit (unit);
  221.     elcAttached = TRUE;
  222.     return (OK);
  223.     }
  224. /*******************************************************************************
  225. *
  226. * elcreset - reset the interface
  227. */
  228. LOCAL void elcreset 
  229.     (
  230.     int unit 
  231.     )
  232.     {
  233.     elcReset (unit);
  234.     }
  235. /*******************************************************************************
  236. *
  237. * elcinit - initialize elc
  238. *
  239. * Restart the link level software on the board and mark the interface up.
  240. *
  241. * RETURNS: 0
  242. */
  243. LOCAL int elcinit 
  244.     (
  245.     int unit 
  246.     )
  247.     {
  248.     FAST ELC_SOFTC *sc = &elc_softc[unit];
  249.     sc->es_if.if_flags |= IFF_UP|IFF_RUNNING; /* open for business*/
  250.     return (0);
  251.     }
  252. /*******************************************************************************
  253. *
  254. * elcintr - Ethernet interface interrupt
  255. *
  256. * Hand off reading of packets from the interface to task level.
  257. */
  258. LOCAL void elcintr 
  259.     (
  260.     int unit 
  261.     )
  262.     {
  263.     FAST ELC_SOFTC *sc = &elc_softc[unit];
  264.     sc->elcStat.interrupts++;
  265.     sysBusIntAck (sc->intLevel); /* acknowledge int */
  266.     /* acknowledge interrupt, get Transmit/Receive status */
  267.     sc->istat = sysInByte (ELC_INTSTAT (sc->elcAddr));
  268.     sysOutByte (ELC_INTSTAT (sc->elcAddr), sc->istat);
  269.     sc->tstat = sysInByte (ELC_TSTAT (sc->elcAddr));
  270.     sc->rstat = sysInByte (ELC_RSTAT (sc->elcAddr));
  271.     /* get xxxCount Reg that is cleared after read access */
  272.     sc->elcStat.collisions += sysInByte (ELC_COLCNT (sc->elcAddr));
  273.     sc->elcStat.aligns += sysInByte (ELC_ALICNT (sc->elcAddr));
  274.     sc->elcStat.crcs += sysInByte (ELC_CRCCNT (sc->elcAddr));
  275.     sc->elcStat.missed += sysInByte (ELC_MPCNT (sc->elcAddr));
  276.     if (sc->istat & ISTAT_OVW) /* Receive buffer ring overwrite */
  277. {
  278.         sysOutByte (ELC_BOUND(sc->elcAddr), sysInByte (ELC_BOUND(sc->elcAddr)));
  279. sc->elcStat.overwrite++;
  280.         sc->es_if.if_ierrors++;
  281. }
  282.     if (sc->istat & ISTAT_RXE) /* Receive-error */
  283. {
  284.         sc->es_if.if_ierrors++;
  285. sc->elcStat.rerror++;
  286. if (sc->rstat & RSTAT_OVER)
  287.     sc->elcStat.overruns++;
  288. if (sc->rstat & RSTAT_DIS)
  289.     sc->elcStat.disabled++;
  290. if (sc->rstat & RSTAT_DFR)
  291.     sc->elcStat.deferring++;
  292. }
  293.     if (sc->istat & ISTAT_PRX) /* Receive */
  294. {
  295.         sc->current = elcGetCurr (unit);
  296. if ((sc->flags & RXING) == 0)
  297.     {
  298.             sc->flags |= RXING;
  299.     (void) netJobAdd ((FUNCPTR)elcGet, unit, 0,0,0,0);
  300.     }
  301. if (sc->rstat & RSTAT_PRX)
  302.     sc->elcStat.rnoerror++;
  303. }
  304.     if (sc->istat & (ISTAT_TXE | ISTAT_PTX)) /* Transmit-error, Transmit */
  305. {
  306. semGive (&elcSyncSem);
  307.         if (sc->istat & ISTAT_TXE)
  308.             {
  309.             sc->es_if.if_oerrors++;
  310.             sc->es_if.if_opackets--;
  311.     sc->elcStat.terror++;
  312.             }
  313. if (sc->tstat & TSTAT_ABORT)
  314.     {
  315.     sc->elcStat.aborts++;
  316.     sc->elcStat.collisions += 16;
  317.     }
  318. if (sc->tstat & TSTAT_UNDER)
  319.     sc->elcStat.underruns++;
  320. if (sc->tstat & TSTAT_CDH)
  321.     sc->elcStat.heartbeats++;
  322. if (sc->tstat & TSTAT_OWC)
  323.     sc->elcStat.outofwindow++;
  324. if (sc->tstat & TSTAT_PTX)
  325.     sc->elcStat.tnoerror++;
  326. }
  327.     }
  328. /*******************************************************************************
  329. *
  330. * elcGet - read a packet off the interface
  331. *
  332. * Copy packets from a RING into an mbuf and hand it to the next higher layer.
  333. */
  334. LOCAL void elcGet 
  335.     (
  336.     int unit
  337.     )
  338.     {
  339.     FAST ELC_SOFTC *sc = &elc_softc[unit];
  340.     FAST ELC_HEADER *pH;
  341.     FAST struct ether_header *eh;
  342.     FAST struct mbuf *m;
  343.     int len;
  344. #ifdef BSD43_DRIVER
  345.     int off;
  346. #endif
  347.     int ix = 0;
  348.     USHORT wrapSize;
  349.     USHORT packetSize;
  350.     char *pSrc;
  351.     char *pDst;
  352.     UCHAR *pData;
  353.     UCHAR uppByteCnt;
  354. unlucky:
  355.     ix = 0;
  356.     while ((sc->next != sc->current) && (ix++ < SMC8013WC_PSTOP))
  357. {
  358. /* Invalidate cache */
  359.         cacheDrvInvalidate (&cacheDmaFuncs, 
  360.             (UCHAR *)(sc->memAddr + (SMC8013WC_PSTART << 8)),
  361.             (sc->memSize - (SMC8013WC_PSTART << 8)));
  362. pH = (ELC_HEADER *)(sc->memAddr + 
  363.    (((UINT)sc->next << 8) & 0x0000ffff));
  364. /* sanity check */
  365. if ((pH->next < SMC8013WC_PSTART) || (pH->next >= SMC8013WC_PSTOP))
  366.     {
  367.     sc->elcStat.badPacket++;
  368.     pH->next = sc->next + sc->uppByteCnt + 1;
  369.     if (pH->next >= SMC8013WC_PSTOP)
  370. pH->next = SMC8013WC_PSTART + (pH->next - SMC8013WC_PSTOP);
  371.     }
  372. if (*(USHORT *)(&pH->lowByteCnt) < 64)
  373.     {
  374.     sc->elcStat.shortPacket++;
  375.     goto doneGet;
  376.     }
  377.         sc->es_if.if_ipackets++;        /* bump statistic */
  378. /* get uppByteCnt from pH->next because of the bug of a chip */
  379. if (pH->next > sc->next)
  380.     {
  381.     wrapSize = 0;
  382.     uppByteCnt = pH->next - sc->next;
  383.     }
  384. else
  385.     {
  386.     wrapSize = (SMC8013WC_PSTOP - sc->next) << 8;
  387.     uppByteCnt = (SMC8013WC_PSTOP - sc->next) + 
  388.  (pH->next - SMC8013WC_PSTART);
  389.     }
  390. if (pH->lowByteCnt > 0xfc)
  391.     uppByteCnt -= 2;
  392. else
  393.     uppByteCnt -= 1;
  394. packetSize = (uppByteCnt << 8) | pH->lowByteCnt;
  395. pH->uppByteCnt = uppByteCnt;
  396. if (wrapSize > packetSize)
  397.     wrapSize = 0;
  398. /* copy separated frame to a temporary buffer */
  399. if (wrapSize)
  400.     {
  401.     sc->elcStat.wrapped++;
  402.     pSrc = (char *)pH;
  403.     pDst = (char *)sc->receiveBuf;
  404.     bcopy (pSrc, pDst, wrapSize);
  405.     pSrc = (char *)(sc->memAddr + (SMC8013WC_PSTART << 8));
  406.     pDst += wrapSize;
  407.     len = packetSize - wrapSize;
  408.     if (len)
  409. bcopy (pSrc, pDst, len);
  410.     }
  411.         len = packetSize - 4; /* remove CRCs 4 bytes */
  412.         if (wrapSize)
  413.     eh = (struct ether_header *)((UINT)sc->receiveBuf + 
  414. sizeof (ELC_HEADER));
  415.         else
  416.     eh = (struct ether_header *)((UINT)pH + sizeof (ELC_HEADER));
  417.         /* call input hook if any */
  418.         if ((etherInputHookRtn != NULL) &&
  419.     (* etherInputHookRtn) (&sc->es_if, (char *) eh, len))
  420.     {
  421.     goto doneGet;
  422.     }
  423.         if (len >= SIZEOF_ETHERHEADER)
  424.             len -= SIZEOF_ETHERHEADER;
  425.         else
  426.             {
  427.             sc->es_if.if_ierrors++;         /* bump error statistic */
  428.     goto doneGet;
  429.             }
  430.         pData = ((unsigned char *) eh) + SIZEOF_ETHERHEADER;
  431. #ifdef BSD43_DRIVER
  432.         check_trailer (eh, pData, &len, &off, &sc->es_if);
  433.         /* copy data from the ring buffer to mbuf a long-word at a time */
  434.         
  435.         m = bcopy_to_mbufs (pData, len, off, (struct ifnet *) &sc->es_if, 2);
  436.         if (m == NULL)
  437.             {
  438.             sc->es_if.if_ierrors++;         /* bump error statistic */
  439.     goto doneGet;
  440.             }
  441.         do_protocol_with_type (eh->ether_type, m, &sc->es_ac, len);
  442. #else
  443.         /* copy data from the ring buffer to mbuf a long-word at a time */
  444.         m = bcopy_to_mbufs (pData, len, 0, (struct ifnet *) &sc->es_if, 2);
  445.         if (m == NULL)
  446.             {
  447.             sc->es_if.if_ierrors++;         /* bump error statistic */
  448.             goto doneGet;
  449.             }
  450.         do_protocol (eh, m, &sc->es_ac, len);
  451. #endif
  452. doneGet:
  453. sc->next = pH->next;
  454. sc->uppByteCnt = pH->uppByteCnt;
  455. }
  456.     /* update BOUND Register */
  457.     if (sc->next <= SMC8013WC_PSTART)
  458. sysOutByte (ELC_BOUND (sc->elcAddr), SMC8013WC_PSTOP - 1);
  459.     else
  460. sysOutByte (ELC_BOUND (sc->elcAddr), sc->next - 1);
  461.     sc->flags &= ~RXING;
  462.     /* go back if we received an interrupt and a new packet */
  463.     if (sc->next != sc->current)
  464. goto unlucky;
  465.     }
  466. #ifdef BSD43_DRIVER
  467. /*******************************************************************************
  468. *
  469. * elcoutput - ethernet output routine
  470. *
  471. * Encapsulate a packet of type family for the local net.
  472. * Use trailer local net encapsulation if enough data in first
  473. * packet leaves a multiple of 512 bytes of data in remainder.
  474. * If destination is this address or broadcast, send packet to
  475. * loop device to kludge around the fact that 3com interfaces can't
  476. * talk to themselves.
  477. *
  478. * RETURNS: ?
  479. */
  480. LOCAL int elcoutput 
  481.     (
  482.     struct ifnet *ifp,
  483.     struct mbuf *m0,
  484.     struct sockaddr *dst 
  485.     )
  486.     {
  487.     return (ether_output (ifp, m0, dst, (FUNCPTR)elcPut,
  488.   &elc_softc [ifp->if_unit].es_ac));
  489.     }
  490. #endif
  491. /*******************************************************************************
  492. *
  493. * elcPut - copy a packet to the interface.
  494. *
  495. * Copy from mbuf chain to transmitter buffer in shared memory.
  496. *
  497. */
  498. #ifdef BSD43_DRIVER
  499. LOCAL void elcPut 
  500.     (
  501.     int unit
  502.     )
  503.     {
  504.     FAST ELC_SOFTC *sc   = &elc_softc [unit];
  505. #else
  506. LOCAL void elcPut 
  507.     (
  508.     ELC_SOFTC *sc
  509.     )
  510.     {
  511. #endif
  512.     FAST struct mbuf *m;
  513.     FAST int len;
  514.     UINT transmitPage = sc->transmitPage[sc->transmitCnt & 1];
  515.     UCHAR *pBuf = (UCHAR *)(sc->memAddr + (transmitPage << 8));
  516. #ifdef BSD43_DRIVER
  517.     int s = splnet ();
  518.     if (sc->es_if.if_snd.ifq_head != NULL)
  519. #else
  520.     while (sc->es_if.if_snd.ifq_head != NULL)
  521. #endif
  522. {
  523. semTake (&elcSyncSem, sysClkRateGet());
  524. IF_DEQUEUE (&sc->es_if.if_snd, m);
  525. copy_from_mbufs (pBuf, m, len);
  526. len = max (ETHERSMALL, len);
  527. cacheDrvFlush (&cacheDmaFuncs, pBuf, len);
  528. /* call output hook if any */
  529. if ((etherOutputHookRtn != NULL) &&
  530.     (* etherOutputHookRtn) (&sc->es_if, pBuf, len))
  531. #ifdef BSD43_DRIVER
  532.     goto donePut;
  533. #else
  534.             continue;
  535. #endif
  536. /* kick Transmitter */
  537.         sysOutByte (ELC_INTMASK (sc->elcAddr), 0x00);
  538. sysOutByte (ELC_TSTART (sc->elcAddr), transmitPage);
  539. sysOutByte (ELC_TCNTH (sc->elcAddr), len >> 8);
  540. sysOutByte (ELC_TCNTL (sc->elcAddr), len & 0xff);
  541. sysOutByte (ELC_CMD (sc->elcAddr), CMD_TXP);
  542. sc->transmitCnt++;
  543.         sysOutByte (ELC_INTMASK (sc->elcAddr), 
  544.     IM_OVWE | IM_TXEE | IM_PTXE | IM_PRXE);
  545. #ifndef BSD43_DRIVER
  546.         sc->es_if.if_opackets++;
  547. #endif
  548. }
  549. #ifdef BSD43_DRIVER
  550. donePut:
  551.     splx (s);
  552. #endif
  553.     }
  554. /*******************************************************************************
  555. *
  556. * elcReset - reset the chip
  557. *
  558. * Reset the chip.
  559. *
  560. */
  561. LOCAL void elcReset 
  562.     (
  563.     int unit
  564.     )
  565.     {
  566.     FAST ELC_SOFTC *sc   = &elc_softc [unit];
  567.     int s = splnet ();
  568.     /* mask interrupt */
  569.     sysOutByte (ELC_INTMASK (sc->elcAddr), 0x00);
  570.     bicInit (unit);
  571.     elcInit (unit);
  572.     /* unmask interrupt */
  573.     sysOutByte (ELC_INTMASK (sc->elcAddr), 
  574. IM_OVWE | IM_TXEE | IM_PTXE | IM_PRXE);
  575.     sc->elcStat.reset++;
  576.     splx (s);
  577.     }
  578. /*******************************************************************************
  579. *
  580. * elcioctl - ioctl for interface
  581. *
  582. * RETURNS: ?
  583. */
  584. LOCAL int elcioctl 
  585.     (
  586.     FAST struct ifnet *ifp,
  587.     int cmd,
  588.     caddr_t data 
  589.     )
  590.     {
  591.     int error = 0;
  592.     int s;
  593.     s = splimp();
  594.     switch (cmd)
  595. {
  596. case SIOCSIFADDR:
  597.             ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN (data)->sin_addr;
  598.             arpwhohas (ifp, &IA_SIN (data)->sin_addr);
  599.     break;
  600. case SIOCSIFFLAGS:
  601.             /* Handled outside module - nothing more to do. */
  602.     break;
  603. default:
  604.     error = EINVAL;
  605. }
  606.     splx (s);
  607.     return (error);
  608.     }
  609. /*******************************************************************************
  610. *
  611. * bicInit - initialize SMC83c584 BIC (Bus Interface Controller)
  612. *
  613. * RETURNS: N/A
  614. *
  615. * NOMANUAL
  616. */
  617. LOCAL void bicInit 
  618.     (
  619.     int unit
  620.     )
  621.     {
  622.     FAST ELC_SOFTC *sc = &elc_softc[unit];
  623.     IRQ_TABLE *p = &irqTable[sc->intLevel];
  624.     char laar = (sc->memAddr & 0xf80000) >> 19;
  625.     char msr  = (sc->memAddr & 0x07e000) >> 13;
  626.     char iar  = (sc->bicAddr & 0xe000) >> 8 | (sc->bicAddr & 0x03e0) >> 5;
  627.     char irr;
  628.     char icr;
  629.     char eeromIrr;
  630.     /* get IRQ level bits */
  631.     if (p->ir2 == 0xff)
  632.         p = &irqTable[3]; /* default is IRQ3 */
  633.     irr  = p->ir01 << 5;
  634.     icr  = p->ir2 << 2;
  635.     /* Reset and Recall */
  636.     sysOutByte (BIC_MSR (sc->bicAddr), MSR_RST);
  637.     sysOutByte (BIC_MSR (sc->bicAddr), 0);
  638.     taskDelay (sysClkRateGet () >> 2);
  639.     sysOutByte (BIC_ICR (sc->bicAddr), ICR_RLA | ICR_RX7);
  640.     while (sysInByte (BIC_ICR (sc->bicAddr)) & (ICR_RLA | ICR_RX7))
  641. ;
  642.     /* get values set by EEROM */
  643.     eeromIrr = sysInByte (BIC_IRR (sc->bicAddr));
  644.     /* Memory Select Reg: Enable, 0x??000. */
  645.     sysOutByte (BIC_MSR (sc->bicAddr), MSR_MEN | msr);
  646.     /* Interface Config Reg: 16Kbytes, 16Bit. */
  647.     sysOutByte (BIC_ICR (sc->bicAddr), ICR_BIT16 | icr);
  648.     /* IO Address Reg: 0x??0 */
  649.     sysOutByte (BIC_IAR (sc->bicAddr), iar);
  650.     /* BIOS ROM Address Reg: Disable */
  651.     sysOutByte (BIC_BIO (sc->bicAddr), 0x00);
  652.     /* Interrupt Request Reg: Enable, IRQ? */
  653.     if (sc->config == 1)
  654.         sysOutByte (BIC_IRR (sc->bicAddr), IRR_IEN | irr | IRR_OUT1);
  655.     else if (sc->config == 2)
  656.         sysOutByte (BIC_IRR (sc->bicAddr), IRR_IEN | irr | IRR_OUT1 | IRR_OUT2);
  657.     else
  658.         sysOutByte (BIC_IRR (sc->bicAddr), IRR_IEN | irr | IRR_OUT1 |
  659.     (eeromIrr & 0x0e));
  660.     /* LA Address Reg: 16Bit-memory, 16Bit-lan, 0x??000 */
  661.     sysOutByte (BIC_LAAR (sc->bicAddr), LAAR_M16EN | LAAR_L16EN | laar);
  662.     }
  663. /*******************************************************************************
  664. *
  665. * elcInit - initialize SMC83c690 ELC (Ethernet LAN Controller)
  666. *
  667. * RETURNS: N/A
  668. *
  669. * NOMANUAL
  670. */
  671. LOCAL void elcInit 
  672.     (
  673.     int unit
  674.     )
  675.     {
  676.     FAST ELC_SOFTC *sc          = &elc_softc[unit];
  677.     /* 1. program Command Register for page 0 */
  678.     sysOutByte (ELC_CMD (sc->elcAddr), CMD_CMD5 | CMD_STP);
  679.     while ((sysInByte (ELC_INTSTAT (sc->elcAddr)) & ISTAT_RST) != ISTAT_RST)
  680. ;
  681.     /* 2. initialize Data Configuration Register */
  682.     sysOutByte (ELC_DCON (sc->elcAddr), DCON_BSIZE1 | DCON_BUS16 | 0x08);
  683.     /* 3. clear Remote Byte Count Register */
  684.     sysOutByte (ELC_RBCR0 (sc->elcAddr), 0x00);
  685.     sysOutByte (ELC_RBCR1 (sc->elcAddr), 0x00);
  686.     /* 4. initialize Receive Configuration Register */
  687.     sysOutByte (ELC_RCON (sc->elcAddr), 0x04);
  688.     /* 5. place the ELC in LOOPBACK mode 1 or 2 */
  689.     sysOutByte (ELC_TCON (sc->elcAddr), TCON_LB1);
  690.     /* 6. initialize Receive Buffer Ring */
  691.     sysOutByte (ELC_RSTART (sc->elcAddr), SMC8013WC_PSTART);
  692.     sysOutByte (ELC_RSTOP (sc->elcAddr), SMC8013WC_PSTOP);
  693.     sysOutByte (ELC_BOUND (sc->elcAddr), SMC8013WC_PSTART);
  694.     /* 7. clear Interrupt Status Register */
  695.     sysOutByte (ELC_INTSTAT (sc->elcAddr), 0xff);
  696.     /* 8. initialize Interrupt Mask Register */
  697.     sysOutByte (ELC_INTMASK (sc->elcAddr), 0x00);
  698.     /* 9. program Command Register for page 1 */
  699.     sysOutByte (ELC_CMD (sc->elcAddr), CMD_PS0 | CMD_STP);
  700.     sysOutByte (ELC_STA0 (sc->elcAddr), sysInByte (BIC_LAR0 (sc->bicAddr)));
  701.     sysOutByte (ELC_STA1 (sc->elcAddr), sysInByte (BIC_LAR1 (sc->bicAddr)));
  702.     sysOutByte (ELC_STA2 (sc->elcAddr), sysInByte (BIC_LAR2 (sc->bicAddr)));
  703.     sysOutByte (ELC_STA3 (sc->elcAddr), sysInByte (BIC_LAR3 (sc->bicAddr)));
  704.     sysOutByte (ELC_STA4 (sc->elcAddr), sysInByte (BIC_LAR4 (sc->bicAddr)));
  705.     sysOutByte (ELC_STA5 (sc->elcAddr), sysInByte (BIC_LAR5 (sc->bicAddr)));
  706.     sysOutByte (ELC_MAR0 (sc->elcAddr), 0);
  707.     sysOutByte (ELC_MAR1 (sc->elcAddr), 0);
  708.     sysOutByte (ELC_MAR2 (sc->elcAddr), 0);
  709.     sysOutByte (ELC_MAR3 (sc->elcAddr), 0);
  710.     sysOutByte (ELC_MAR4 (sc->elcAddr), 0);
  711.     sysOutByte (ELC_MAR5 (sc->elcAddr), 0);
  712.     sysOutByte (ELC_MAR6 (sc->elcAddr), 0);
  713.     sysOutByte (ELC_MAR7 (sc->elcAddr), 0);
  714.     sc->next = SMC8013WC_PSTART + 1;
  715.     sysOutByte (ELC_CURR (sc->elcAddr), sc->next);
  716.     sysOutByte (ELC_CMD (sc->elcAddr), CMD_PS1 | CMD_STP);
  717.     sysOutByte (ELC_ENH (sc->elcAddr), 0x00); /* 0 wait states */
  718.     sysOutByte (ELC_BLOCK (sc->elcAddr), 0x00); /* 0x00xxxx */
  719.     /* 10. put the ELC in START mode */
  720.     sysOutByte (ELC_CMD (sc->elcAddr), CMD_STA);
  721.     /* 11. initialize Transmit Configuration Register */
  722.     sysOutByte (ELC_TCON (sc->elcAddr), 0x00);
  723.     }
  724. /*******************************************************************************
  725. *
  726. * elcGetAddr - get hardwired ethernet address.
  727. *
  728. * Read the ethernet address off the board, one byte at a time.
  729. *
  730. */
  731. LOCAL void elcGetAddr 
  732.     (
  733.     int unit 
  734.     )
  735.     {
  736.     FAST ELC_SOFTC *sc          = &elc_softc[unit];
  737.     UCHAR *pAddr = (UCHAR *)sc->es_enaddr;
  738.     *pAddr++ = sysInByte (BIC_LAR0 (sc->bicAddr));
  739.     *pAddr++ = sysInByte (BIC_LAR1 (sc->bicAddr));
  740.     *pAddr++ = sysInByte (BIC_LAR2 (sc->bicAddr));
  741.     *pAddr++ = sysInByte (BIC_LAR3 (sc->bicAddr));
  742.     *pAddr++ = sysInByte (BIC_LAR4 (sc->bicAddr));
  743.     *pAddr   = sysInByte (BIC_LAR5 (sc->bicAddr));
  744.     }
  745. /*******************************************************************************
  746. *
  747. * elcGetCurr - get current page
  748. *
  749. * RETURNS: current page that ELC is working on
  750. *
  751. * NOMANUAL
  752. */
  753. LOCAL UCHAR elcGetCurr 
  754.     (
  755.     int unit
  756.     )
  757.     {
  758.     FAST ELC_SOFTC *sc          = &elc_softc[unit];
  759.     UCHAR curr;
  760.     /* get CURR register */
  761.     sysOutByte (ELC_CMD (sc->elcAddr), CMD_PS0);
  762.     curr = sysInByte (ELC_CURR (sc->elcAddr));
  763.     sysOutByte (ELC_CMD (sc->elcAddr), 0);
  764.     return (curr);
  765.     }
  766. /*******************************************************************************
  767. *
  768. * elcShow - display statistics for the SMC 8013WC `elc' network interface
  769. *
  770. * This routine displays statistics about the `elc' Ethernet network interface.
  771. * It has two parameters: 
  772. * .iP <unit>
  773. * interface unit; should be 0.
  774. * .iP <zap>
  775. * if 1, all collected statistics are cleared to zero.
  776. * .LP
  777. *
  778. * RETURNS: N/A
  779. */
  780. void elcShow 
  781.     (
  782.     int unit,   /* interface unit */
  783.     BOOL zap    /* 1 = zero totals */
  784.     )
  785.     {
  786.     FAST ELC_SOFTC *sc          = &elc_softc[unit];
  787.     FAST int ix;
  788.     static char *e_message [] = {
  789. "collisions",
  790. "crcs",
  791. "aligns",
  792. "missed",
  793. "over-runs",
  794. "disabled",
  795. "deferring",
  796. "under-run",
  797. "aborts",
  798. "out-of-window",
  799. "heart-beats",
  800. "bad-packet",
  801. "short-packet",
  802. "t-no-error",
  803. "r-no-error",
  804. "t-error",
  805. "r-error",
  806. "over-write",
  807. "wrapped",
  808. "interrupts",
  809. "reset",
  810. "stray-int"};
  811.     for (ix = 0; ix < NELEMENTS(e_message); ix++)
  812. {
  813. printf ("    %-30.30s  %4dn", e_message [ix], sc->elcStat.stat [ix]);
  814. if (zap)
  815.     sc->elcStat.stat [ix] = 0;
  816. }
  817.     printf ("    %-30.30s  0x%2xn", "flags", sc->flags);
  818.     }
  819. /*******************************************************************************
  820. *
  821. * elcdetach - detach the card from the bus.
  822. *
  823. * Dettach the card from the bus for reset.
  824. *
  825. * RETURNS: N/A
  826. *
  827. * NOMANUAL
  828. */
  829. void elcdetach 
  830.     (
  831.     int unit
  832.     )
  833.     {
  834.     FAST ELC_SOFTC *sc = &elc_softc[unit];
  835.     if (elcAttached)
  836. {
  837.         sysOutByte (ELC_INTMASK (sc->elcAddr), 0x00);
  838.         sysOutByte (ELC_CMD (sc->elcAddr), CMD_CMD5 | CMD_STP);
  839.         while ((sysInByte (ELC_INTSTAT (sc->elcAddr)) & ISTAT_RST) != ISTAT_RST)
  840.     ;
  841.         sysOutByte (ELC_RCON (sc->elcAddr), 0x00);
  842.         sysOutByte (ELC_TCON (sc->elcAddr), TCON_LB1);
  843.         sysIntDisablePIC (sc->intLevel);
  844.         sysOutByte (BIC_MSR (sc->bicAddr), MSR_RST);
  845.         taskDelay (sysClkRateGet () >> 1);
  846.         sysOutByte (BIC_MSR (sc->bicAddr), 0x00);
  847.         taskDelay (sysClkRateGet () >> 1);
  848. }
  849.     }