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

VxWorks

开发平台:

C/C++

  1. /* if_ultra.c - SMC Elite Ultra Ethernet network interface driver */
  2. /* Copyright 1984-1999 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01u,11jan99,aeg  fixed multiple semaphore inits in ultraattach ().
  8. 01t,29jun98,dat  SPR 21211. fixes to Interrupt loop. 
  9. 01s,11jun98,hdn  fixed typo in ultraIntr().
  10. 01r,22apr98,hdn  set FINE16 bit in ultraInit(). 
  11.  added a loop to ack pending interrupts in untraIntr().
  12. 01q,15jul97,spm  removed driver initialization from ioctl support (SPR #8831)
  13. 01p,15may97,spm  reverted to bcopy routines for mbufs in BSD 4.4
  14. 01o,07apr97,spm  code cleanup and corrected counter for incoming packets
  15. 01n,17mar97,spm  upgraded to BSD 4.4 and corrected statistics counters.
  16. 01m,14jun95,hdn  removed function declarations defined in sysLib.h.
  17. 01l,01feb95,jdi  doc cleanup.
  18. 01k,29nov94,hdn  added a semaphore in ultraPut().
  19. 01j,12nov94,tmk  removed some IMPORTed function decs and included unixLib.h
  20. 01i,30sep94,hdn  implemented two transmit buffers.
  21.  enabled getting GPOUT and ZWSEN bit of GCR in EEROM.
  22.  deleted while loop in ultraPut().
  23. 01h,29nov93,hdn  disabled the interrupt in ultraPut().
  24.  removed netJobAdd (ultraPut, ..) in ultraIntr().
  25. 01g,28nov93,hdn  changed NULTRA to 1.
  26. 01f,23nov93,hdn  removed cacheInvalidate(). 
  27.  added checking TXP bit before the transmission. 
  28. 01e,22nov93,hdn  added elcdetach () for the warm start.
  29. 01d,15nov93,hdn  added support for Thin Ethernet(10Base2, BNC)
  30. 01c,05nov93,hdn  added cacheFlush() and cacheInvalidate().
  31. 01b,04nov93,hdn  cleaned up.
  32. 01a,30oct93,hdn  written.
  33. */
  34. /*
  35. DESCRIPTION
  36. This module implements the SMC Elite Ultra Ethernet network interface driver.
  37. This driver supports single transmission and multiple reception.  The
  38. Current register is a write pointer to the ring.  The Bound register is a
  39. read pointer from the ring.  This driver gets the Current register at the
  40. interrupt level and sets the Bound register at the task level.  The
  41. interrupt is never masked at the task level.
  42. CONFIGURATION
  43. The W1 jumper should be set in the position of "Software Configuration".
  44. The defined I/O address in config.h must match the one stored in EEROM. 
  45. The RAM address, the RAM size, and the IRQ level are defined in config.h. 
  46. IRQ levels 2,3,5,7,10,11,15 are supported.
  47. EXTERNAL INTERFACE
  48. The only user-callable routines are ultraattach() and ultraShow():
  49. .iP ultraattach() 14
  50. publishes the `ultra' interface and initializes the driver and device.
  51. .iP ultraShow()
  52. displays statistics that are collected in the interrupt handler.
  53. .LP
  54. */
  55. #include "vxWorks.h"
  56. #include "net/mbuf.h"
  57. #include "net/protosw.h"
  58. #include "net/unixLib.h"
  59. #include "ioctl.h"
  60. #include "socket.h"
  61. #include "errnoLib.h"
  62. #include "net/uio.h"
  63. #include "net/if.h"
  64. #include "net/route.h"
  65. #include "netinet/in.h"
  66. #include "netinet/in_systm.h"
  67. #include "netinet/ip.h"
  68. #include "netinet/ip_var.h"
  69. #include "netinet/in_var.h"
  70. #include "netinet/if_ether.h"
  71. #include "etherLib.h"
  72. #include "vme.h"
  73. #include "iv.h"
  74. #include "iosLib.h"
  75. #include "ioLib.h"
  76. #include "memLib.h"
  77. #include "net/systm.h"
  78. #include "net/if_subr.h"
  79. #include "sysLib.h"
  80. #include "vxLib.h"
  81. #include "stdio.h"
  82. #include "intLib.h"
  83. #include "logLib.h"
  84. #include "string.h"
  85. #include "netLib.h"
  86. #include "stdlib.h"
  87. #include "semLib.h"
  88. #include "cacheLib.h"
  89. #include "drv/netif/if_ultra.h"
  90. /* defines */
  91. #define NULTRA 1 /* max number of ULTRA controllers */
  92. /* typedefs */
  93. typedef struct ifnet IFNET;                 /* real Interface Data Record */
  94. /* globals */
  95. /* locals */
  96. LOCAL ULTRA_SOFTC ultra_softc [NULTRA];
  97. LOCAL IRQ_TABLE irqTable [] = 
  98.     {
  99.     { 2, 0x15},    { 2, 0x15},    { 2, 0x15},    { 3, 0x19},
  100.     { 3, 0x19},    { 5, 0x1d},    { 5, 0x1d},    { 7, 0x51},
  101.     { 7, 0x51},    { 7, 0x51},    {10, 0x55},    {11, 0x59},
  102.     {11, 0x59},    {11, 0x59},    {11, 0x59},    {15, 0x5d}
  103.     };
  104. LOCAL BOOL ultraAttached = FALSE;
  105. LOCAL SEMAPHORE  ultraSyncSem;           /* syncronization semaphore */
  106. /* forward static functions */
  107.        void ultraShow (int unit, BOOL zap);
  108.        void ultradetach (int unit);
  109. LOCAL  int  ultrainit (int unit);
  110. LOCAL  void ultrareset (int unit);
  111. LOCAL  int  ultraioctl (struct ifnet *ifp, int cmd, caddr_t data);
  112. #ifdef BSD43_DRIVER
  113. LOCAL  int  ultraoutput (struct ifnet *ifp, struct mbuf *m0, struct sockaddr
  114.  *dst);
  115. #endif
  116. LOCAL  void ultraInit (int unit);
  117. LOCAL  void ultraIntr (int unit);
  118. LOCAL  void ultraGet (int unit);
  119. #ifdef BSD43_DRIVER
  120. LOCAL  void ultraPut (int unit);
  121. #else
  122. LOCAL  void ultraPut  (ULTRA_SOFTC *sc);
  123. #endif
  124. /*******************************************************************************
  125. *
  126. * ultraattach - publish `ultra' interface and initialize device
  127. *
  128. * This routine attaches an `ultra' Ethernet interface to the network if the
  129. * device exists.  It makes the interface available by filling in the network
  130. * interface record.  The system will initialize the interface when it is ready
  131. * to accept packets.
  132. *
  133. * RETURNS: OK or ERROR.
  134. *
  135. * SEE ALSO: ifLib, netShow
  136. */
  137. STATUS ultraattach 
  138.     (
  139.     int unit,           /* unit number */
  140.     int ioAddr,         /* address of ultra's shared memory */
  141.     int ivec,           /* interrupt vector to connect to */
  142.     int ilevel,         /* interrupt level */
  143.     int memAddr,        /* address of ultra's shared memory */
  144.     int memSize,        /* size of ultra's shared memory */
  145.     int config /* 0: RJ45 + AUI(Thick)  1: RJ45 + BNC(Thin) */
  146.     )
  147.     {
  148.     FAST ULTRA_SOFTC *sc = &ultra_softc[unit];
  149.     if ((UINT)unit >= NULTRA)
  150. {
  151.         errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);
  152. return (ERROR);
  153. }
  154.     sc->ioAddr = ioAddr;
  155.     sc->memAddr = memAddr;
  156.     sc->memSize = memSize;
  157.     sc->intLevel = irqTable[ilevel].irq;
  158.     sc->intVec = ivec;
  159.     sc->config = config;
  160.     sc->transmitPage[0] = ULTRA_TSTART0;
  161.     sc->transmitPage[1] = ULTRA_TSTART1;
  162.     sc->transmitCnt = 0;
  163.     /* synchronization semaphore must be initialized only once */
  164.     if (!ultraAttached)
  165. semBInit (&ultraSyncSem, SEM_Q_FIFO, SEM_FULL);
  166.     (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (ivec), 
  167.        (VOIDFUNCPTR)ultraIntr, unit);
  168. #ifdef BSD43_DRIVER
  169.     ether_attach (&sc->es_if, unit, "ultra", (FUNCPTR)ultrainit, 
  170.   (FUNCPTR)ultraioctl, (FUNCPTR)ultraoutput, (FUNCPTR)ultrareset);
  171. #else
  172.     ether_attach (
  173.                  (IFNET *) & sc->es_ac,
  174.                  unit,
  175.                  "ultra",
  176.                  (FUNCPTR) ultrainit,
  177.                  (FUNCPTR) ultraioctl,
  178.                  (FUNCPTR) ether_output,    /* generic ether_output */ 
  179.                  (FUNCPTR) ultrareset
  180.                  );
  181.     sc->es_if.if_start = (FUNCPTR) ultraPut;
  182. #endif 
  183.     ultrainit (unit);
  184.     ultraAttached = TRUE;
  185.     return (OK);
  186.     }
  187. /*******************************************************************************
  188. *
  189. * ultrareset - reset the interface
  190. *
  191. * RETURNS: N/A
  192. */
  193. LOCAL void ultrareset 
  194.     (
  195.     int unit  /* device unit number */
  196.     )
  197.     {
  198.     FAST ULTRA_SOFTC *sc   = &ultra_softc [unit];
  199.     int s = splnet ();
  200.     sc->stat.reset++;
  201.     sysIntDisablePIC (sc->intLevel);
  202.     sc->es_if.if_flags = 0;
  203.     splx (s);
  204.     }
  205. /*******************************************************************************
  206. *
  207. * ultrainit - initialize ultra
  208. *
  209. * Restart the link level software on the board and mark the interface up.
  210. *
  211. * RETURNS: 0
  212. */
  213. LOCAL int ultrainit 
  214.     (
  215.     int unit  /* device unit number */
  216.     )
  217.     {
  218.     FAST ULTRA_SOFTC *sc = &ultra_softc[unit];
  219.     int s = splnet ();
  220.     ultraInit (unit);
  221.     sysIntEnablePIC (sc->intLevel);
  222.     sc->es_if.if_flags |= IFF_UP|IFF_RUNNING; /* open for business*/
  223.     splx (s);
  224.     return (0);
  225.     }
  226. #ifdef BSD43_DRIVER
  227. /*******************************************************************************
  228. *
  229. * ultraoutput - ethernet output routine
  230. *
  231. * Encapsulate a packet of type family for the local net.
  232. * Use trailer local net encapsulation if enough data in first
  233. * packet leaves a multiple of 512 bytes of data in remainder.
  234. * If destination is this address or broadcast, send packet to
  235. * loop device to kludge around the fact that 3com interfaces can't
  236. * talk to themselves.
  237. *
  238. * RETURNS:  OK if successful, otherwise errno.
  239. */
  240. LOCAL int ultraoutput 
  241.     (
  242.     struct ifnet *ifp, /* device structure */
  243.     struct mbuf *m0, /* mbuf containing packet */
  244.     struct sockaddr *dst  /* destination address */
  245.     )
  246.     {
  247.     return (ether_output (ifp, m0, dst, (FUNCPTR)ultraPut,
  248.   &ultra_softc [ifp->if_unit].es_ac));
  249.     }
  250. #endif
  251. /*******************************************************************************
  252. *
  253. * ultraioctl - ioctl for interface
  254. *
  255. * RETURNS: OK if successful, otherwise errno.
  256. */
  257. LOCAL int ultraioctl 
  258.     (
  259.     FAST struct ifnet *ifp, /* device structure */
  260.     int cmd, /* ioctl cmd code */
  261.     caddr_t data  /* ioctl argument */
  262.     )
  263.     {
  264.     int status = OK;
  265.     int s = splimp();
  266.     short flags;
  267.     switch (cmd)
  268. {
  269. case SIOCSIFADDR:
  270.             ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN (data)->sin_addr;
  271.             arpwhohas ((struct arpcom *)ifp, &IA_SIN (data)->sin_addr);
  272.     break;
  273. case SIOCSIFFLAGS:
  274.             flags = ifp->if_flags;
  275.     if (ifp->if_flags & IFF_UP)
  276.                 ifp->if_flags = flags | (IFF_UP | IFF_RUNNING);
  277.             else
  278.                 ifp->if_flags = flags & ~(IFF_UP|IFF_RUNNING);
  279.     break;
  280. default:
  281.     status = EINVAL;
  282. }
  283.     splx (s);
  284.     return (status);
  285.     }
  286. /*******************************************************************************
  287. *
  288. * ultraIntr - Ethernet interface interrupt
  289. *
  290. * Hand off reading of packets from the interface to task level.
  291. *
  292. * RETURNS: N/A
  293. */
  294. LOCAL void ultraIntr 
  295.     (
  296.     int unit  /* device unit number */
  297.     )
  298.     {
  299.     FAST ULTRA_SOFTC *sc = &ultra_softc[unit];
  300.     UCHAR istat;
  301.     int   nCnt = 0;
  302.     /* Acknowledge interrupt, get Transmit/Receive status */
  303.     sc->istat = 0;
  304.     do  {
  305.         istat = sysInByte (LAN_INTSTAT (sc->ioAddr));
  306.         sysOutByte (LAN_INTSTAT (sc->ioAddr), istat);
  307.         sc->istat |= istat;
  308.         nCnt ++;
  309.         }
  310.     while (istat != 0);
  311.     sc->tstat = sysInByte (LAN_TSTAT (sc->ioAddr));
  312.     sc->rstat = sysInByte (LAN_RSTAT (sc->ioAddr));
  313.     /* get xxxCount Reg that is cleared after read access */
  314.     sc->stat.interrupts++;
  315.     sc->stat.collisions += sysInByte (LAN_COLCNT (sc->ioAddr));
  316.     sc->stat.aligns += sysInByte (LAN_ALICNT (sc->ioAddr));
  317.     sc->stat.crcs += sysInByte (LAN_CRCCNT (sc->ioAddr));
  318.     sc->stat.missed += sysInByte (LAN_MPCNT (sc->ioAddr));
  319.     if (sc->istat & ISTAT_RXE) /* Receive-error */
  320. {
  321.         sc->es_if.if_ierrors++;
  322. sc->stat.rerror++;
  323. if (sc->rstat & RSTAT_OVER)
  324.     sc->stat.overruns++;
  325. if (sc->rstat & RSTAT_DIS)
  326.     sc->stat.disabled++;
  327. if (sc->rstat & RSTAT_DFR)
  328.     sc->stat.deferring++;
  329. }
  330.     if (sc->istat & (ISTAT_PRX | ISTAT_OVW)) /* Receive, Overwrite */
  331. {
  332.         if (sc->istat & ISTAT_OVW)
  333.             {
  334.     sc->stat.overwrite++;
  335.             sc->es_if.if_ierrors++;
  336.             }
  337.         sysOutByte (LAN_CMD (sc->ioAddr), CMD_PS0);
  338.         sc->current = sysInByte (LAN_CURR (sc->ioAddr));
  339.         sysOutByte (LAN_CMD (sc->ioAddr), 0);
  340. if ((sc->flags & RXING) == 0)
  341.     {
  342.             sc->flags |= RXING;
  343.     (void) netJobAdd ((FUNCPTR)ultraGet, unit, 0,0,0,0);
  344.     }
  345. if (sc->rstat & RSTAT_PRX)
  346.     sc->stat.rnoerror++;
  347. }
  348.     if (sc->istat & (ISTAT_TXE | ISTAT_PTX)) /* Transmit-error, Transmit */
  349. {
  350. semGive (&ultraSyncSem);
  351. #if FALSE  /* BEGIN TEST CODE */
  352. if (sc->es_if.if_snd.ifq_head != NULL)
  353.     {
  354. #ifdef BSD43_DRIVER
  355.     netJobAdd ((FUNCPTR) ultraPut, unit, 0,0,0,0);
  356. #else
  357.     netJobAdd ((FUNCPTR) ultraPut, (int)sc, 0,0,0,0);
  358. #endif
  359.     }
  360. #endif /* END TEST CODE */
  361.         if (sc->istat & ISTAT_TXE)
  362.             {
  363.     sc->stat.terror++;
  364.             sc->es_if.if_oerrors++;
  365.             sc->es_if.if_opackets--;
  366.             }
  367. if (sc->tstat & TSTAT_ABORT)
  368.     {
  369.     sc->stat.aborts++;
  370.     sc->stat.collisions += 16;
  371.     }
  372. if (sc->tstat & TSTAT_UNDER)
  373.     sc->stat.underruns++;
  374. if (sc->tstat & TSTAT_CDH)
  375.     sc->stat.heartbeats++;
  376. if (sc->tstat & TSTAT_OWC)
  377.     sc->stat.outofwindow++;
  378. if (sc->tstat & TSTAT_PTX)
  379.     sc->stat.tnoerror++;
  380. }
  381.     }
  382. /*******************************************************************************
  383. *
  384. * ultraGet - read a packet off the interface
  385. *
  386. * Copy packets from a RING into an mbuf and hand it to the next higher layer.
  387. *
  388. * RETURNS: N/A
  389. */
  390. LOCAL void ultraGet 
  391.     (
  392.     int unit /* device unit number */
  393.     )
  394.     {
  395.     FAST ULTRA_SOFTC *sc = &ultra_softc[unit];
  396.     FAST ULTRA_HEADER *pH;
  397.     FAST struct ether_header *eh;
  398.     FAST struct mbuf *m;
  399.     int len;
  400. #ifdef BSD43_DRIVER
  401.     int off;
  402. #endif
  403.     int ix;
  404.     USHORT wrapSize;
  405.     USHORT packetSize;
  406.     char *pSrc;
  407.     char *pDst;
  408.     UCHAR *pData;
  409. unlucky:
  410.     ix = 0;
  411.     while ((sc->next != sc->current) && (ix++ < ULTRA_PSTOP))
  412. {
  413. /* Invalidate cache */
  414.         cacheDrvInvalidate (&cacheDmaFuncs, 
  415.             (UCHAR *)(sc->memAddr + (ULTRA_PSTART << 8)),
  416.             (sc->memSize - (ULTRA_PSTART << 8)));
  417. pH = (ULTRA_HEADER *)(sc->memAddr + (sc->next << 8));
  418. /* sanity check */
  419. if ((pH->next < ULTRA_PSTART) || (pH->next >= ULTRA_PSTOP))
  420.     {
  421.     sc->stat.badPacket++;
  422.     pH->next = sc->next + sc->uppByteCnt + 1;
  423.     if (pH->next >= ULTRA_PSTOP)
  424. pH->next = ULTRA_PSTART + (pH->next - ULTRA_PSTOP);
  425.     }
  426. packetSize = *(USHORT *)(&pH->lowByteCnt);
  427. if (packetSize < (ULTRA_MIN_SIZE))
  428.     {
  429.     sc->stat.shortPacket++;
  430.     goto doneGet;
  431.     }
  432. if (packetSize > (ULTRA_MAX_SIZE))
  433.     {
  434.     sc->stat.longPacket++;
  435.     goto doneGet;
  436.     }
  437.         sc->es_if.if_ipackets++;        /* bump statistic */
  438. if (pH->next > sc->next)
  439.     wrapSize = 0;
  440. else
  441.     wrapSize = min (packetSize, ((ULTRA_PSTOP - sc->next) << 8));
  442. /* copy separated frame to a temporary buffer */
  443. if (wrapSize)
  444.     {
  445.     sc->stat.wrapped++;
  446.     pSrc = (char *)pH;
  447.     pDst = (char *)sc->receiveBuf;
  448.     bcopy (pSrc, pDst, wrapSize);
  449.     pSrc = (char *)(sc->memAddr + (ULTRA_PSTART << 8));
  450.     pDst += wrapSize;
  451.     len = packetSize - wrapSize;
  452.     if (len)
  453. bcopy (pSrc, pDst, len);
  454.     }
  455.         len = packetSize - 4; /* remove CRCs 4 bytes */
  456.         if (wrapSize)
  457.     eh = (struct ether_header *)((UINT)sc->receiveBuf + 
  458. sizeof (ULTRA_HEADER));
  459.         else
  460.     eh = (struct ether_header *)((UINT)pH + sizeof (ULTRA_HEADER));
  461.         /* call input hook if any */
  462.         if ((etherInputHookRtn != NULL) &&
  463.     (* etherInputHookRtn) (&sc->es_if, (char *) eh, len))
  464.     {
  465.     goto doneGet;
  466.     }
  467.         if (len >= SIZEOF_ETHERHEADER)
  468.             len -= SIZEOF_ETHERHEADER;
  469.         else
  470.     goto doneGet;
  471.         pData = ((unsigned char *) eh) + SIZEOF_ETHERHEADER;
  472. #ifdef BSD43_DRIVER
  473.         check_trailer (eh, pData, &len, &off, &sc->es_if);
  474.         /* copy data from the ring buffer to mbuf a long-word at a time */
  475.         m = bcopy_to_mbufs (pData, len, off, (struct ifnet *) &sc->es_if, 2);
  476.         if (m == NULL)
  477.             {
  478.             sc->es_if.if_ierrors++;         /* bump error statistic */
  479.     goto doneGet;
  480.             }
  481.         do_protocol_with_type (eh->ether_type, m, &sc->es_ac, len);
  482. #else
  483.         /* copy data from the ring buffer to mbuf a long-word at a time */
  484.         m = bcopy_to_mbufs (pData, len, 0, (struct ifnet *) &sc->es_if, 2);
  485.         if (m == NULL)
  486.             {
  487.             sc->es_if.if_ierrors++;         /* bump error statistic */
  488.     goto doneGet;
  489.             }
  490.         do_protocol (eh, m, &sc->es_ac, len);
  491. #endif
  492. doneGet:
  493. sc->next = pH->next;
  494. sc->uppByteCnt = pH->uppByteCnt;
  495. }
  496.     /* update BOUND Register */
  497.     if ((sc->next < ULTRA_PSTART) || (sc->next >= ULTRA_PSTOP))
  498. sysOutByte (LAN_BOUND (sc->ioAddr), ULTRA_PSTART);
  499.     else
  500. sysOutByte (LAN_BOUND (sc->ioAddr), sc->next);
  501.     sc->flags &= ~RXING;
  502.     /* go back if we received an interrupt and a new packet */
  503.     if (sc->next != sc->current)
  504. goto unlucky;
  505.     }
  506. /*******************************************************************************
  507. *
  508. * ultraPut - copy a packet to the interface.
  509. *
  510. * Copy from mbuf chain to transmitter buffer in shared memory.
  511. *
  512. * RETURNS: N/A
  513. */
  514. #ifdef BSD43_DRIVER
  515. LOCAL void ultraPut 
  516.     (
  517.     int unit /* device unit number */
  518.     )
  519.     {
  520.     FAST ULTRA_SOFTC *sc   = &ultra_softc [unit];
  521. #else
  522. LOCAL void ultraPut
  523.     (
  524.     ULTRA_SOFTC *sc /* device context */
  525.     )
  526.     {
  527. #endif
  528.     FAST struct mbuf *m;
  529.     FAST int len;
  530.     UINT transmitPage = sc->transmitPage[sc->transmitCnt & 1];
  531.     UCHAR *pBuf = (UCHAR *)(sc->memAddr + (transmitPage << 8));
  532. #ifdef BSD43_DRIVER
  533.     int s = splnet ();
  534. #endif
  535.     while (sc->es_if.if_snd.ifq_head != NULL)
  536. {
  537. semTake (&ultraSyncSem, sysClkRateGet ());
  538. IF_DEQUEUE (&sc->es_if.if_snd, m);
  539. if (m != NULL)
  540.     {
  541.     copy_from_mbufs (pBuf, m, len);
  542.     len = max (ETHERSMALL, len);
  543.     cacheDrvFlush (&cacheDmaFuncs, pBuf, len);
  544.     /* call output hook if any */
  545.     if ((etherOutputHookRtn != NULL) &&
  546. (* etherOutputHookRtn) (&sc->es_if, pBuf, len))
  547. continue;
  548.     /* kick Transmitter */
  549.     sysOutByte (LAN_INTMASK (sc->ioAddr), 0x00);
  550.     sysOutByte (LAN_TSTART (sc->ioAddr), transmitPage);
  551.     sysOutByte (LAN_TCNTH (sc->ioAddr), len >> 8);
  552.     sysOutByte (LAN_TCNTL (sc->ioAddr), len & 0xff);
  553.     sysOutByte (LAN_CMD (sc->ioAddr), CMD_TXP);
  554.     sc->transmitCnt++;
  555.     sysOutByte (LAN_INTMASK (sc->ioAddr), 
  556. IM_OVWE | IM_TXEE | IM_PTXE | IM_PRXE);
  557. #ifndef BSD43_DRIVER
  558.     sc->es_if.if_opackets++;
  559. #endif
  560.     }
  561. }
  562. #ifdef BSD43_DRIVER
  563.     splx (s);
  564. #endif
  565.     }
  566. /*******************************************************************************
  567. *
  568. * ultraInit - initialize Elite Ultra (Ethernet LAN Controller)
  569. *
  570. * RETURNS: N/A
  571. */
  572. LOCAL void ultraInit 
  573.     (
  574.     int unit /* device unit number */
  575.     )
  576.     {
  577.     FAST ULTRA_SOFTC *sc = &ultra_softc[unit];
  578.     UCHAR *pAddr  = (UCHAR *)sc->es_enaddr;
  579.     UCHAR memAddr;
  580.     UCHAR intLevel;
  581.     UCHAR ioAddr;
  582.     UCHAR eeromGcon;
  583.     /* mask interrupt */
  584.     sysOutByte (LAN_INTMASK (sc->ioAddr), 0x00);
  585.     /* reset */
  586.     sysOutByte (CTRL_CON (sc->ioAddr), CON_RESET);
  587.     sysOutByte (CTRL_CON (sc->ioAddr), 0x00);
  588.     sysOutByte (CTRL_HARD (sc->ioAddr), 0x08);
  589.     taskDelay (sysClkRateGet () >> 2);
  590.     sysOutByte (CTRL_CON (sc->ioAddr), CON_MENABLE);
  591.     /* get values set by EEROM */
  592.     sysOutByte (CTRL_HARD (sc->ioAddr), 0x80);
  593.     eeromGcon = sysInByte (CTRL_GCON(sc->ioAddr));
  594.     /* IO address, Memory address, Interrupt request */
  595.     memAddr = ((sc->memAddr & 0x1e000) >> 13) | ((sc->memAddr & 0x20000) >> 10);
  596.     intLevel = ((sc->intLevel & 0x03) << 2) | ((sc->intLevel & 0x04) << 6);
  597.     ioAddr = ((sc->ioAddr & 0xe000) >> 8) | ((sc->ioAddr & 0x01e0) >> 4);
  598.     sysOutByte (CTRL_HARD (sc->ioAddr), 0x80);
  599.     sysOutByte (CTRL_IOADDR (sc->ioAddr), ioAddr);
  600.     sysOutByte (CTRL_MEMADDR (sc->ioAddr), memAddr | 0x10);
  601.     if (sc->config == 1)
  602.         sysOutByte (CTRL_GCON (sc->ioAddr), irqTable[sc->intLevel].reg |
  603.     (eeromGcon & 0x20));
  604.     else if (sc->config == 2)
  605.         sysOutByte (CTRL_GCON (sc->ioAddr), irqTable[sc->intLevel].reg | 0x02 |
  606.     (eeromGcon & 0x20));
  607.     else
  608.         sysOutByte (CTRL_GCON (sc->ioAddr), irqTable[sc->intLevel].reg | 
  609.     (eeromGcon & 0x22));
  610.     /* set FINE16 bit in BIO register to get finer resolution for M16CS decode */
  611.     sysOutByte (CTRL_BIO (sc->ioAddr), sysInByte (CTRL_BIO (sc->ioAddr) | 0x80)); 
  612.     sysOutByte (CTRL_HARD (sc->ioAddr), 0x00);
  613.     /* 16 bit enable */
  614.     sysOutByte (CTRL_BIOS (sc->ioAddr), BIOS_M16EN);
  615.     /* program Command Register for page 0 */
  616.     sysOutByte (LAN_CMD (sc->ioAddr), CMD_STP);
  617.     while ((sysInByte (LAN_INTSTAT (sc->ioAddr)) & ISTAT_RST) != ISTAT_RST)
  618. ;
  619.     /* initialize Data Configuration Register */
  620.     sysOutByte (LAN_DCON (sc->ioAddr), DCON_BSIZE1 | DCON_BUS16);
  621.     /* initialize Receive Configuration Register */
  622.     sysOutByte (LAN_RCON (sc->ioAddr), 0x04);
  623.     /* place the Ultra in LOOPBACK mode 1 or 2 */
  624.     sysOutByte (LAN_TCON (sc->ioAddr), TCON_LB1);
  625.     /* initialize Receive Buffer Ring */
  626.     sysOutByte (LAN_RSTART (sc->ioAddr), ULTRA_PSTART);
  627.     sysOutByte (LAN_RSTOP (sc->ioAddr), ULTRA_PSTOP);
  628.     sysOutByte (LAN_BOUND (sc->ioAddr), ULTRA_PSTART);
  629.     /* clear Interrupt Status Register */
  630.     sysOutByte (LAN_INTSTAT (sc->ioAddr), 0xff);
  631.     /* initialize Interrupt Mask Register */
  632.     sysOutByte (LAN_INTMASK (sc->ioAddr), 0x00);
  633.     /* program Command Register for page 1 */
  634.     sysOutByte (LAN_CMD (sc->ioAddr), CMD_PS0 | CMD_STP);
  635.     sysOutByte (LAN_STA0 (sc->ioAddr), sysInByte (CTRL_LAN0 (sc->ioAddr)));
  636.     sysOutByte (LAN_STA1 (sc->ioAddr), sysInByte (CTRL_LAN1 (sc->ioAddr)));
  637.     sysOutByte (LAN_STA2 (sc->ioAddr), sysInByte (CTRL_LAN2 (sc->ioAddr)));
  638.     sysOutByte (LAN_STA3 (sc->ioAddr), sysInByte (CTRL_LAN3 (sc->ioAddr)));
  639.     sysOutByte (LAN_STA4 (sc->ioAddr), sysInByte (CTRL_LAN4 (sc->ioAddr)));
  640.     sysOutByte (LAN_STA5 (sc->ioAddr), sysInByte (CTRL_LAN5 (sc->ioAddr)));
  641.     *pAddr++ = sysInByte (CTRL_LAN0 (sc->ioAddr));
  642.     *pAddr++ = sysInByte (CTRL_LAN1 (sc->ioAddr));
  643.     *pAddr++ = sysInByte (CTRL_LAN2 (sc->ioAddr));
  644.     *pAddr++ = sysInByte (CTRL_LAN3 (sc->ioAddr));
  645.     *pAddr++ = sysInByte (CTRL_LAN4 (sc->ioAddr));
  646.     *pAddr   = sysInByte (CTRL_LAN5 (sc->ioAddr));
  647.     sysOutByte (LAN_MAR0 (sc->ioAddr), 0);
  648.     sysOutByte (LAN_MAR1 (sc->ioAddr), 0);
  649.     sysOutByte (LAN_MAR2 (sc->ioAddr), 0);
  650.     sysOutByte (LAN_MAR3 (sc->ioAddr), 0);
  651.     sysOutByte (LAN_MAR4 (sc->ioAddr), 0);
  652.     sysOutByte (LAN_MAR5 (sc->ioAddr), 0);
  653.     sysOutByte (LAN_MAR6 (sc->ioAddr), 0);
  654.     sysOutByte (LAN_MAR7 (sc->ioAddr), 0);
  655.     sc->next = ULTRA_PSTART + 1;
  656.     sysOutByte (LAN_CURR (sc->ioAddr), sc->next);
  657.     sysOutByte (LAN_CMD (sc->ioAddr), CMD_PS1 | CMD_STP);
  658.     sysOutByte (LAN_ENH (sc->ioAddr), 0x00); /* 0 wait states */
  659.     /* put the Ultra in START mode */
  660.     sysOutByte (LAN_CMD (sc->ioAddr), CMD_STA);
  661.     /* initialize Transmit Configuration Register */
  662.     sysOutByte (LAN_TCON (sc->ioAddr), 0x00);
  663.     /* enable interrupt */
  664.     sysOutByte (CTRL_INT (sc->ioAddr), INT_ENABLE);
  665.     sysOutByte (LAN_INTMASK (sc->ioAddr),
  666. IM_OVWE | IM_TXEE | IM_PTXE | IM_PRXE);
  667.     }
  668. /*******************************************************************************
  669. *
  670. * ultraShow - display statistics for the `ultra' network interface
  671. *
  672. * This routine displays statistics about the `elc' Ethernet network interface.
  673. * It has two parameters:
  674. * .iP <unit>
  675. * interface unit; should be 0.
  676. * .iP <zap>
  677. * if 1, all collected statistics are cleared to zero.
  678. * .LP
  679. *
  680. * RETURNS: N/A
  681. */
  682. void ultraShow 
  683.     (
  684.     int unit,   /* interface unit */
  685.     BOOL zap    /* zero totals */
  686.     )
  687.     {
  688.     FAST ULTRA_SOFTC *sc          = &ultra_softc[unit];
  689.     FAST int ix;
  690.     static char *e_message [] = {
  691. "collisions",
  692. "crcs",
  693. "aligns",
  694. "missed",
  695. "over-runs",
  696. "disabled",
  697. "deferring",
  698. "under-run",
  699. "aborts",
  700. "out-of-window",
  701. "heart-beats",
  702. "bad-packet",
  703. "short-packet",
  704. "long-packet",
  705. "t-no-error",
  706. "r-no-error",
  707. "t-error",
  708. "r-error",
  709. "over-write",
  710. "wrapped",
  711. "interrupts",
  712. "reset",
  713. "stray-int"};
  714.     printf ("ioAddr=0x%x memAddr=0x%x memSize=0x%x vector=0x%x level=0x%xn",
  715. sc->ioAddr, sc->memAddr, sc->memSize, sc->intVec, sc->intLevel);
  716.     for (ix = 0; ix < NELEMENTS(e_message); ix++)
  717. {
  718. printf ("    %-30.30s  %4dn", e_message [ix], sc->stat.stat [ix]);
  719. if (zap)
  720.     sc->stat.stat [ix] = 0;
  721. }
  722.     printf ("    %-30.30s  0x%2xn", "flags", sc->flags);
  723.     }
  724. /*******************************************************************************
  725. *
  726. * ultradetach - detach the card from the bus.
  727. *
  728. * Dettach the card from the bus for reset.
  729. *
  730. * RETURNS: N/A
  731. *
  732. * NOMANUAL
  733. */
  734. void ultradetach 
  735.     (
  736.     int unit /* device unit number */
  737.     )
  738.     {
  739.     FAST ULTRA_SOFTC *sc = &ultra_softc[unit];
  740.     if (ultraAttached)
  741. {
  742.         sysOutByte (LAN_INTMASK (sc->ioAddr), 0x00);
  743.         sysOutByte (LAN_CMD (sc->ioAddr), CMD_STP);
  744.         while ((sysInByte (LAN_INTSTAT (sc->ioAddr)) & ISTAT_RST) != ISTAT_RST)
  745.     ;
  746.         sysOutByte (LAN_RCON (sc->ioAddr), 0x00);
  747.         sysOutByte (LAN_TCON (sc->ioAddr), TCON_LB1);
  748.         sysIntDisablePIC (sc->intLevel);
  749.         sysOutByte (CTRL_CON (sc->ioAddr), CON_RESET);
  750.         taskDelay (sysClkRateGet () >> 1);
  751.         sysOutByte (CTRL_CON (sc->ioAddr), 0x00);
  752.         taskDelay (sysClkRateGet () >> 1);
  753. }
  754.     }