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

VxWorks

开发平台:

C/C++

  1. /* if_sm.c - shared memory backplane network interface driver */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01o,07jun02,mas  total packet length compared to SM packet size (SPR 78405)
  7. 01n,03may02,mas  now receives its own broadcasts (SPR 9676); packets in excess
  8.  of MTU size are just deleted and an optional error message is
  9.  printed (SPR 29305); cache flushing and volatile ptr fixes
  10.  (SPR 68334); bridge flushing fix (SPR 68844); now uses
  11.  netMblkToBufCopy() rather than copyFromMbufs().
  12. 01m,24oct01,mas  fixed diab warnings (SPR 71120); doc update (SPR 71149)
  13. 01l,02oct01,mas  no user callable routines, all are NOMANUAL (SPR 4547)
  14. 01k,24jul96,vin  upgraded to bsd4.4.
  15. 01k,14dec96,dat  fixed SPR 2258. chg'd inet_ntoa to inet_ntoa_b
  16. 01j,11jan95,rhp  remove reference to unpublished lib from man page.
  17. 01i,19feb93,jdi  documentation cleanup.
  18. 01h,09sep92,gae  documentation tweaks.
  19. 01g,11jun92,elh  added documentation, more cleanup, added parameter
  20.  to smIfAttach.
  21. 01f,02jun92,elh  the tree shuffle
  22. 01e,27may92,elh  Incorperated the changes caused from restructuring the
  23.  shared memory libraries.
  24. 01d,17may92,elh  renamed routines from sm to smIf
  25. 01c,03may92,elh  changed to use subnet in shared memory when
  26.  calculating host address (smIfHwAddrSet).
  27. 01b,12apr92,elh  added in support for sequential addressing.
  28. 01a,17nov90,elh  written.
  29. */
  30. /*
  31. DESCRIPTION
  32. This module implements the VxWorks shared memory backplane network
  33. interface driver.  
  34. This driver is designed to be moderately generic, operating unmodified
  35. across the range of hosts and targets supported by VxWorks.  To achieve 
  36. this, the driver must be given several target-specific parameters, and 
  37. some external support routines must be provided.  These parameters are 
  38. detailed below.
  39. There are no user-callable routines.
  40. This driver is layered between the shared memory packet library and the network 
  41. modules.  The backplane driver gives CPUs residing on a common backplane 
  42. the ability to communicate using IP (via shared memory).
  43. BOARD LAYOUT
  44. This device is "software only."  There is no jumpering diagram required.
  45. INTERNAL
  46. This file no longer runs under SunOs.
  47. File Layout:
  48. This network interface driver has been physically split up into the 
  49. the operating system specific code (smNetLib) and the common network
  50. interface code (if_sm).  Dividing the driver up this way layers 
  51. the driver and reduces the number of conditional compilations and 
  52. thereby makes the code cleaner and more readable.
  53.      ____________________
  54. vxWorks interface    |smNetLib (vxWorks) |     |
  55. to backplane driver  ____________________     |backplane
  56. |                           |driver
  57.                  |                           |
  58.                      |                           |
  59. v          |
  60. shared  memory       _______________     |
  61. backplane driver     |   if_sm      |     |
  62.      _______________
  63.      |
  64. ---------------------------------------
  65.      |     | shared memory
  66.              v     | libraries
  67.     ____________     |
  68.   | smPktLib | 
  69. ____________ 
  70. smNetLib 
  71. smNetLib implements the interface between the OS and the driver.
  72. There exists an smNetLib for both UNIX and VxWorks.
  73. Each smNetLib must implement how the OS initializes and attaches 
  74. the driver, interrupt handling, etc as well as the OS dependent 
  75. system calls.  
  76. if_sm 
  77. if_sm contains the network interface code that is common to most 
  78. BSD based systems.  It is the interface to the network modules and does 
  79. the packet processing.
  80. OS Interface:
  81. The interfaces into this module from the OS specific modules follow.  
  82. smIfAttach -  attaches the shared memory network interface driver 
  83. to the network modules.  smIfAttach typically gets called once per 
  84. backplane interface.  The shared memory region must have been 
  85. setup and initialized (via smPktSetup) prior to calling smIfAttach. 
  86. smIfInput -  gets called from the OS specific interrupt service handler 
  87. to process input shared memory packets and to pass them up to the 
  88. network modules.  
  89. smIfLoanReturn - return a previously loaned shared memory buffer.
  90. OS Dependent Routines:
  91. The following routines/macros must be provided by the OS specific 
  92. modules for this module: 
  93.     UNIT_TO_SOFTC convert unit to softc pointer
  94.     outputHook output hook for packet
  95.     inputHook input hook for packet
  96.     etherAddrPtr return pointer to ethernet address
  97.     netMblkToBufCopy copy from mbuf chain to passed buffer
  98.     copyToMbufs copy from buffer to mbuf chain
  99.     deviceValid if device is a valid device
  100.     USE_CLUSTER use a cluster mbuf
  101.     loanBuild build a loan mbuf buffer
  102. There should be better documentation discussing the interfaces, 
  103. functionality and expectations of the OS spcecific library.
  104. Optional function pointer hook for use by netMblkToBufCopy() routine:
  105. FUNCPTR  smBufCpyFuncHook
  106. By default this is set to NULL which denotes use of bcopy().  Any other
  107. routine specified here must adhere to the same input argument specification
  108. as bcopy().
  109. TARGET-SPECIFIC PARAMETERS
  110. A set of target-specific parameters is used to configure shared memory and
  111. backplane networking.
  112. is
  113. i `local address of anchor'
  114. This parameter is the local address by which the local CPU accesses the shared
  115. memory anchor.
  116. i `maximum number of input packets'
  117. This parameter specifies the maximum number of incoming shared memory packets
  118. that can be queued to this CPU at one time.
  119. i `method of notification'
  120. These four parameters are used to enable a CPU to announce the method by which
  121. it is to be notified of input packets that have been queued to it.
  122. i `heartbeat frequency'
  123. This parameter specifies the frequency of the shared memory backplane
  124. network's heartbeat, which is expressed in terms of the number of CPU ticks on
  125. the local CPU corresponding to one heartbeat period.
  126. i `number of buffers to loan'
  127. This parameter, when non-zero, specifies the number of shared memory packets
  128. available to be loaned out.
  129. i `master CPU number'
  130. This parameter specifies the master CPU number as set during system
  131. configuration.
  132. ie
  133. For detailed information refer to 
  134. tb VxWorks Network Programmer's Guide: Data Link Layer Network Compnents.
  135. INCLUDE FILES: smNetLib.h
  136. SEE ALSO: ifLib, smNetLib, 
  137. tb VxWorks Network Programmer's Guide
  138. NOROUTINES
  139. */
  140. /* includes */
  141. #ifdef UNIX
  142. #include "smNetLib.h"
  143. #else
  144. #include "drv/netif/smNetLib.h"
  145. #endif
  146. #include "cacheLib.h"
  147. #include "netBufLib.h"
  148. #include "smLib.h"
  149. #include "smPktLib.h"
  150. #include "smUtilLib.h"
  151. /* globals */
  152. BOOL smIfVerbose = FALSE; /* verbose mode */
  153. /* packet copy routine ptr (NULL = bcopy) */
  154. FUNCPTR smBufCpyFuncHook = NULL;
  155. /* forward declarations  */
  156. /* network hooks */
  157. LOCAL void  smIfReset (int unit);
  158. LOCAL int  smIfInit (int unit);
  159. LOCAL int  smIfIoctl (struct ifnet * pIf, UINT cmd, caddr_t data);
  160. LOCAL void  smIfRecv (SM_SOFTC * sm, SM_PKT volatile * pPkt,
  161.                           BOOL * retBuffer);
  162. LOCAL void  smIfHwAddrSet (int unit);
  163. LOCAL void  smIfStartOutput (SM_SOFTC * xs);
  164. IMPORT void if_down (struct ifnet *);
  165. /******************************************************************************
  166. *
  167. * smIfAttach - publish the `sm' interface and initialize the driver and device
  168. *
  169. * This routine attaches an `sm' Ethernet interface to the network, if the
  170. * interface exists.  This routine makes the interface available by filling in
  171. * the network interface record.  The system will initialize the interface
  172. * when it is ready to accept packets.
  173. *
  174. * The shared memory region must have been initialized, via smPktSetup(), prior
  175. * to calling this routine (typically by an OS-specific initialization routine).
  176. * The smIfAttach() routine can be called only once per unit number.
  177. *
  178. * The <pAnchor> parameter is the local address by which the local CPU may
  179. * access the shared memory anchor.
  180. *
  181. * The <maxInputPkts> parameter specifies the maximum number of incoming
  182. * shared memory packets which may be queued to this CPU at one time.
  183. *
  184. * The <intType>, <intArg1>, <intArg2>, and <intArg3> parameters allow a
  185. * CPU to announce the method by which it is to be notified of input packets
  186. * which have been queued to it.
  187. *
  188. * The <ticksPerBeat> parameter specifies the frequency of the shared memory
  189. * anchor's heartbeat.  The frequency is expressed in terms of the number of CPU
  190. * ticks on the local CPU corresponding to one heartbeat period.
  191. *
  192. * If <numLoan> is non-zero, it specifies the number of shared memory 
  193. * packets available to be loaned out.
  194. *
  195. * RETURNS: OK or ERROR.
  196. *
  197. * NOMANUAL
  198. */
  199. STATUS smIfAttach
  200.     (
  201.     int unit, /* interface unit number */
  202.     SM_ANCHOR * pAnchor, /* local addr of anchor */
  203.     int maxInputPkts, /* max no. of input pkts */
  204.     int intType, /* method of notif. */
  205.     int intArg1, /* interrupt argument #1 */
  206.     int intArg2, /* interrupt argument #2 */
  207.     int intArg3, /* interrupt argument #3 */
  208.     int ticksPerBeat, /* heartbeat freq. */
  209.     int numLoan /* no. of buffers to loan */ 
  210.     )
  211.     {
  212.     SM_SOFTC * xs; /* softc pointer */
  213.     if ((xs = UNIT_TO_SOFTC (unit)) == NULL)
  214.         {
  215. return (ERROR);
  216.         }
  217.     bzero ((caddr_t) xs, sizeof (SM_SOFTC));
  218.     /* Initialize the shared memory descriptor.  */
  219.     smPktInit (&xs->smPktDesc, pAnchor, maxInputPkts, ticksPerBeat,
  220.        intType, intArg1, intArg2, intArg3);
  221.     if (numLoan)
  222. {
  223. xs->bufFree = numLoan;
  224. if (smIfVerbose)
  225.     printf ("smIfAttach:%d loan buffersn", xs->bufFree);
  226.         }
  227.     ether_attach (
  228.       &xs->xs_if, 
  229.  unit, 
  230.  "sm", 
  231.  smIfInit, 
  232.  smIfIoctl, 
  233.  (FUNCPTR) ether_output, /* generic ether_output */
  234.  (FUNCPTR) smIfReset
  235.       );
  236.     xs->xs_if.if_start = (FUNCPTR) smIfStartOutput; 
  237.     return (OK);
  238.     }
  239. /******************************************************************************
  240. *
  241. * smIfInit - initialize the backplane interface
  242. *
  243. * smIfInit initializes the backplane interface by attaching to shared memory
  244. * and by marking the interface as up and running.  This routine gets called
  245. * (indirectly) through smIfIoctl which has the spl semaphore.
  246. *
  247. * INTERNAL
  248. * We must attach to shared memory here (instead of smIfAttach) because we
  249. * can not wait around at boot time (in UNIX the case) waiting for shared
  250. * memory to become alive.
  251. *
  252. * RETURNS:  OK if successful, errno otherwise.
  253. *
  254. * NOMANUAL
  255. */
  256. LOCAL int smIfInit
  257.     (
  258.     int  unit /* unit number */
  259.     )
  260.     {
  261.     SM_SOFTC *  xs; /* softc pointer */
  262.     SM_PKT_INFO smPktInfo; /* info structure */
  263.     xs = UNIT_TO_SOFTC (unit);
  264.     /* attach to shared memory */
  265.     if (smPktAttach (&xs->smPktDesc) == ERROR)
  266. {
  267. if (smIfVerbose)
  268.     printf ("smIfInit:couldn't attach [%x]n", errno);
  269.      return (errno);
  270. }
  271.     smIfHwAddrSet (unit); /* set hardware address */
  272.     (void) smPktInfoGet (&xs->smPktDesc, &smPktInfo);
  273.     xs->xs_if.if_mtu = smPktInfo.maxPktBytes - SIZEOF_ETHERHEADER;
  274.     /*
  275.      * Set current interface status and characteristics.
  276.      * Interface must be marked simplex so that it can receive its
  277.      * own broadcasts.  [SPR 9676]
  278.      */
  279.     xs->xs_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_MULTICAST | IFF_SIMPLEX;
  280.     return (OK);
  281.     }
  282. /******************************************************************************
  283. *
  284. * smIfStartOutput - put packet in shared memory
  285. *
  286. * This routine removes an mbuf chain from the interface send queue, copies
  287. * the data into a shared memory packet and calls smPktSend to send it off.
  288. * This routine gets called from ether_output, after it has taken the 
  289. * spl semaphore.
  290. *
  291. * RETURNS: N/A
  292. *
  293. * NOMANUAL
  294. */
  295. LOCAL void smIfStartOutput
  296.     (
  297.     SM_SOFTC * xs /* ptr to ctrl structure */
  298.     )
  299.     {
  300.     struct mbuf *   pMbuf; /* mbuf pointer */
  301.     int   len; /* data length */
  302.     int                   tmp; /* temp storage */
  303.     UINT   destCPU; /* destination cpu */
  304.     struct ether_header * pEh; /* enet header */
  305.     SM_PKT volatile *   pPkt = NULL; /* packet pointer */
  306.     BOOL    retBuffer; /* return buffer */
  307.     u_char *    pEaddr;
  308.     while (xs->xs_if.if_snd.ifq_head != NULL)
  309.      {
  310. /* dequeue mbuf chain, get a free shared memory packet */
  311.      IF_DEQUEUE (&xs->xs_if.if_snd, pMbuf);
  312.         /* drop packet if it exceeds MTU size  (SPR 29305, 78405) */
  313.         if (pMbuf->m_pkthdr.len > xs->smPktDesc.maxPktBytes)
  314.             {
  315.             m_freem (pMbuf);
  316.             if (smIfVerbose)
  317.                 {
  318.                 printf ("smIfStartOutput: pkt len [%#x] > MTU [%#x]n",
  319.                         pMbuf->m_pkthdr.len, xs->smPktDesc.maxPktBytes);
  320.                 }
  321.             xs->xs_if.if_oerrors++;
  322.             continue;
  323.          }
  324.      if ((smPktFreeGet (&xs->smPktDesc, (SM_PKT **)&pPkt) == ERROR) ||
  325.          (pPkt == NULL))
  326.          {
  327.     m_freem (pMbuf);
  328.     if (smIfVerbose)
  329.      printf ("smIfStartOutput:smPktFreeGet [%x]n", errno);
  330.          xs->xs_if.if_oerrors++;
  331.     continue;
  332.          }
  333.      pEh = (struct ether_header *) pPkt->data; /* copy data to pkt */
  334.         len = netMblkToBufCopy ((M_BLK_ID)pMbuf, (char*)pEh, smBufCpyFuncHook);
  335.      pPkt->header.nBytes = len;
  336.         CACHE_PIPE_FLUSH (); /* CACHE FLUSH   [SPR 68334] */
  337.         tmp = pPkt->header.nBytes; /* BRIDGE FLUSH  [SPR 68334] */
  338.         m_freem (pMbuf);
  339.     if (outputHook (&xs->xs_if, (char *)pEh, pPkt->header.nBytes) != 0)
  340.     {
  341.     (void) smPktFreePut (&xs->smPktDesc, (SM_PKT *)pPkt);
  342.          continue;
  343.     }
  344.      if (bcmp ((caddr_t) etherAddrPtr (pEh->ether_dhost),
  345.   (caddr_t) etherAddrPtr (etherbroadcastaddr) ,
  346.   sizeof (pEh->ether_dhost)) == 0)
  347.             {
  348.          destCPU = SM_BROADCAST;  /* specify broadcast */
  349.             }
  350.      else
  351.          {
  352.     pEaddr = etherAddrPtr (pEh->ether_dhost);
  353.             if (xs->masterAddr != 0) /* sequential addressing */
  354. {
  355. destCPU = ((pEaddr [3] << 16)|(pEaddr [4] << 8)| pEaddr [5]) -
  356.           xs->masterAddr;
  357. }
  358.     else
  359. destCPU = pEaddr [5];
  360.             /* receive packets sent to self */
  361.          if (destCPU == xs->smPktDesc.smDesc.cpuNum)
  362.      {
  363.      smIfRecv (xs, pPkt, &retBuffer);
  364.                 if (retBuffer)
  365.                     (void) smPktFreePut (&xs->smPktDesc, (SM_PKT *)pPkt);
  366.                 continue;                 /* don't use SM to send to self */
  367.      }
  368.          }
  369.    if (smIfVerbose)
  370.     {
  371.     printf ("smIfStartOutput: [0x%x] len:%d src:%s ", pEh->ether_type,
  372.     len, ether_sprintf (etherAddrPtr (pEh->ether_shost)));
  373.     printf ("dst:%s cpu [%d]n",
  374.     ether_sprintf (etherAddrPtr (pEh->ether_dhost)), destCPU);
  375.     }
  376. xs->xs_if.if_opackets++;
  377.     
  378.      if (smPktSend (&xs->smPktDesc, (SM_PKT *)pPkt, destCPU) == ERROR)
  379.          {
  380.     if (smIfVerbose)
  381.      printf ("smIfStartOutput:smPktSend failed 0x%xn", errno);
  382.          xs->xs_if.if_oerrors++;
  383.     xs->xs_if.if_opackets--;
  384.     /*
  385.      * need to return shared memory packet on error,
  386.      * unless it's a incomplete broadcast error.
  387.      */
  388.          if (errno != S_smPktLib_INCOMPLETE_BROADCAST)
  389.      (void) smPktFreePut (&xs->smPktDesc, (SM_PKT *)pPkt);
  390.          }
  391.      }
  392.     }
  393. /******************************************************************************
  394. *
  395. * smIfReset - reset the backplane interface
  396. *
  397. * smIfReset resets the interface.  This gets called when the system
  398. * receives a reset.  Basically this routine cleans up the state and marks
  399. * the interface as inactive before it goes away.
  400. *
  401. * RETURNS: N/A
  402. *
  403. * NOMANUAL
  404. */
  405. LOCAL void smIfReset
  406.     (
  407.     int  unit /* unit number */
  408.     )
  409.     {
  410.     SM_SOFTC * xs = UNIT_TO_SOFTC (unit); /* softc pointer */
  411.     int        spl; /* spl level   */
  412.     if (!deviceValid (unit))
  413.      return;
  414.     /* detach from network */
  415.     spl = splimp ();
  416.     xs->xs_if.if_flags &= ~IFF_RUNNING;
  417.     if_down (&xs->xs_if);
  418.     splx (spl);
  419.     /* detach from shared mem */
  420.     (void) smPktDetach (&xs->smPktDesc, SM_FLUSH);
  421.     }
  422. /******************************************************************************
  423. *
  424. * smIfIoctl - process an ioctl request
  425. *
  426. * smIfIoctl gets called to perform a control operation on the backplane network
  427. * interface.  The implemented commands include: SIOCSIFADDR (set interface
  428. * address) SIOCSIFFLAGS (set interface flags), SIOCGIFADDR get (link-level)
  429. * interface address.
  430. *
  431. * RETURNS: OK if successful, otherwise errno.
  432. *
  433. * NOMANUAL
  434. */
  435. LOCAL int smIfIoctl
  436.     (
  437.     struct ifnet * pIf, /* interface pointer */
  438.     UINT    cmd, /* ioctl command */
  439.     caddr_t     data /* command data */
  440.     )
  441.     {
  442.     struct ifreq * pIfr; /* if request */
  443.     int    retVal = OK; /* error value */
  444.     int    spl    = splimp (); /* spl level */
  445.     SM_SOFTC *    xs     = UNIT_TO_SOFTC (pIf->if_unit);
  446.     struct in_addr ipAddr; /* address passed */
  447.     struct in_addr expAddr; /* expected address */
  448.     char    netString[32];
  449.     pIfr = (struct ifreq *) data;
  450.     switch (cmd)
  451.         {
  452.         case SIOCSIFADDR: /* set interface address */
  453.          retVal = set_if_addr (pIf, data, etherAddrPtr (xs->xs_enaddr));
  454.     if ((retVal == OK) && (xs->masterAddr != 0))
  455. {
  456.      /*
  457.       * We validate address after set_if_addr because
  458.          * shared memory must be up (smPktAttach) before master
  459.        * address can be determined.
  460.        */
  461. ipAddr = ((struct in_ifaddr *) data)->ia_addr.sin_addr;
  462.      expAddr.s_addr = htonl (
  463.  ntohl (xs->smPktDesc.hdrLocalAdrs->reserved1)+
  464.     xs->smPktDesc.smDesc.cpuNum);
  465.      if (expAddr.s_addr != ipAddr.s_addr)
  466.     {
  467.     inet_ntoa_b (expAddr, netString);
  468.             printf ("Seqential addressing enabled - expected address:"
  469.     "%sn", netString);
  470.     smIfReset (pIf->if_unit);
  471.          retVal = ERROR;
  472.             }
  473.         }
  474.          break;
  475. case SIOCSIFFLAGS: /* set interface flags */
  476.          if (pIf->if_flags & IFF_UP)
  477. smIfInit (pIf->if_unit);
  478.     break;
  479.         case SIOCGIFADDR: /* get link level address */
  480.     bcopy ((caddr_t) etherAddrPtr (xs->xs_enaddr),
  481.    (caddr_t)(pIfr->ifr_addr.sa_data), sizeof (xs->xs_enaddr));
  482.             break;
  483. case SIOCADDMULTI:
  484. case SIOCDELMULTI:
  485.     if (pIfr == 0)
  486. {
  487. retVal = EINVAL;  /* invalid argument passed */
  488. break;
  489. }
  490.     switch (pIfr->ifr_addr.sa_family)
  491. {
  492. #ifdef INET
  493. case AF_INET: /* do nothing */
  494.     break;
  495. #endif
  496. default:
  497.     retVal = EAFNOSUPPORT;
  498.     break;
  499. }
  500.     break;
  501.      default:
  502.     if (smIfVerbose)
  503. printf ("smIfIoctl: [0x%x] command not implementedn", cmd);
  504.          retVal = EINVAL;
  505. }
  506.     (void) splx (spl);
  507.     return (retVal);
  508.     }
  509. /******************************************************************************
  510. *
  511. * smIfInput - handle an input packet
  512. *
  513. * smIfInput gets called from the OS specific interrupt handling routine
  514. * to process a shared memory input packet.  It calls smPktRecv to obtain
  515. * the packets from shared memory and then calls smIfRecv to process the
  516. * packet and pass it up to the network modules.
  517. *
  518. * RETURNS: N/A
  519. *
  520. * NOMANUAL
  521. */
  522. void smIfInput
  523.     (
  524.     SM_SOFTC * xs /* softc pointer */
  525.     )
  526.     {
  527.     SM_PKT *   pPkt; /* shared memory packet */
  528.     int        status; /* status */
  529.     BOOL       retBuffer; /* return packet */
  530.     int        cpuNum; /* my cpu number */
  531.     cpuNum = xs->smPktDesc.smDesc.cpuNum;
  532.     do
  533. {
  534. xs->taskRecvActive = TRUE;
  535.      while (((status = smPktRecv (&xs->smPktDesc, &pPkt)) == OK) &&
  536.             (pPkt != NULL))
  537.     {
  538.          smIfRecv (xs, pPkt, &retBuffer);
  539.     if (retBuffer)
  540. (void) smPktFreePut (&xs->smPktDesc, pPkt);
  541.     }
  542. if (status == ERROR)
  543.     {
  544.     xs->xs_if.if_ierrors++;
  545.     if (smIfVerbose)
  546.         printf ("smIfInput:error receiving packet 0x%xn", errno);
  547.     }
  548. xs->taskRecvActive = FALSE;
  549. } while ((xs->smPktDesc.status == SM_CPU_ATTACHED) &&
  550.          (smIfInputCount (xs, cpuNum) > 0));
  551.     }
  552. /******************************************************************************
  553. *
  554. * smIfRecv - process shared memory input packet
  555. *
  556. * smIfRecv is called once per packet that arrives.  It calls check_trailer
  557. * to process trailers.  Copies that packet into an mbuf chain (if buffer
  558. * loaning is not set).  Then passes the packet to the network layer by calling
  559. * do_protocol.
  560. *
  561. * RETURNS: N/A
  562. *
  563. * NOMANUAL
  564. */
  565. LOCAL void smIfRecv
  566.     (
  567.     SM_SOFTC *        xs, /* softc pointer */
  568.     SM_PKT volatile * pPkt, /* packet */
  569.     BOOL *            retBuffer /* kept buffer */
  570.     )
  571.     {
  572.     struct ether_header * pEh; /* ethernet header */
  573.     int   len; /* length */
  574.     u_char *   pData; /* pointer to data */
  575.     struct mbuf *   pMbuf = NULL; /* mbuf pointer */
  576.     *retBuffer = TRUE;     /* return buffer by default */
  577.     CACHE_PIPE_FLUSH (); /* CACHE FLUSH   [SPR 68334] */
  578.     len = pPkt->header.nBytes; /* PCI bug       [SPR 68844] */
  579.     len = pPkt->header.nBytes;
  580.     pEh = (struct ether_header *) pPkt->data;
  581.     if (inputHook (&xs->xs_if, (char *) pEh, len))
  582. return;
  583.     if (len < SIZEOF_ETHERHEADER)
  584. {
  585. if (smIfVerbose)
  586.     printf ("smIfRecv:invalid packet len %dn", len);
  587. xs->xs_if.if_ierrors++;
  588. return; /* invalid packet size */
  589. }
  590.     if (smIfVerbose) /* debugging aide */
  591. {
  592.         printf ("smIfRecv [0x%x] len: %d src:%s ", ntohs (pEh->ether_type), len,
  593.         ether_sprintf (etherAddrPtr (pEh->ether_shost)));
  594. printf ("dst:%sn", ether_sprintf (etherAddrPtr (pEh->ether_dhost)));
  595. }
  596.     len -= SIZEOF_ETHERHEADER; /* adj. for enet header */
  597.     pData = ((unsigned char *) pEh) + SIZEOF_ETHERHEADER;
  598.     if (len == 0)
  599. return; /* packet with no data */
  600.     /*
  601.      * try to build a loaned mbuf cluster (if buffering loaning is enabled,
  602.      * there are loan buffers available, the packet doesn't use
  603.      * trailers, and the packet is big enough).  Otherwise copy it
  604.      * to an mbuf.
  605.      */
  606.     if ((xs->bufFree > 0) && (USE_CLUSTER (len)))
  607.    {
  608. if ((pMbuf = loanBuild (xs, pPkt, pData, len)) != NULL)
  609.        {
  610.     xs->bufFree--;
  611.     *retBuffer = FALSE;
  612.     }
  613. }
  614.     if (pMbuf == NULL)
  615. {
  616.      if ((pMbuf = (struct mbuf *)
  617.      copyToMbufs (pData, len, 0, &xs->xs_if)) == NULL)
  618.     return;
  619.      }
  620.     do_protocol (pEh, pMbuf, &xs->xs_ac, len);
  621.     xs->xs_if.if_ipackets++;
  622.     }
  623. /******************************************************************************
  624. *
  625. * smIfLoanReturn - return shared memory packet to shared memory pool
  626. *
  627. * smPktReturn gets called from the network modules to return the loaned
  628. * shared memory buffer once the network code has finished with it.  It gets
  629. * called with the spl semaphore taken.
  630. *
  631. * RETURNS: N/A
  632. *
  633. * NOMANUAL
  634. */
  635. void smIfLoanReturn
  636.     (
  637.     SM_SOFTC * xs,            /* softc pointer */
  638.     SM_PKT *   pPkt           /* shared memory packet */
  639.     )
  640.     {
  641.     if (smPktFreePut (&xs->smPktDesc, pPkt) == ERROR)
  642. return;
  643.     xs->bufFree++;
  644.     }
  645. /******************************************************************************
  646. *
  647. * smIfHwAddrSet - set hardware address
  648. *
  649. * This routine sets the hardware address associated with the backplane 
  650. * interface specified by <unit>.
  651. *
  652. * RETURNS: N/A
  653. *
  654. * NOMANUAL
  655. */
  656. LOCAL void smIfHwAddrSet
  657.     (
  658.     int  unit  /* unit number */
  659.     )
  660.     {
  661.     u_char *       pEaddr; /* ethernet address */
  662.     u_long      addr; /* address */
  663.     int              tmp; /* temp storage */
  664.     SM_PKT_MEM_HDR volatile * pSmPktHdr; /* packet header */
  665.     SM_SOFTC *       xs = UNIT_TO_SOFTC (unit); /* softc pointer */
  666.     pEaddr = etherAddrPtr(xs->xs_enaddr);
  667.     bzero ((caddr_t)pEaddr, 6); /* fill in ethernet address */
  668.     pEaddr [0] = 0x00;
  669.     pEaddr [1] = 0x02;
  670.     pEaddr [2] = 0xE2;
  671.     pSmPktHdr = (SM_PKT_MEM_HDR volatile *)xs->smPktDesc.hdrLocalAdrs;
  672.     CACHE_PIPE_FLUSH (); /* CACHE FLUSH   [SPR 68334] */
  673.     tmp = pSmPktHdr->reserved1; /* PCI bug       [SPR 68844] */
  674.     if (pSmPktHdr->reserved1 != 0) /* sequential addressing */
  675. {
  676. /*
  677.  * The backplane hw address consists of
  678.  * { 0x00, 0x02, 0xE2, ip[1], ip[2], ip[3] }.
  679.  * where ip is the lower three bytes of
  680.  * the IP interface address.
  681.  */
  682. xs->masterAddr = ntohl (pSmPktHdr->reserved1) & 0x00ffffff;
  683. addr = xs->masterAddr + xs->smPktDesc.smDesc.cpuNum;
  684. pEaddr [3] = (u_char)((addr >> 16) & 0xff);
  685. pEaddr [4] = (u_char)((addr >> 8)  & 0xff);
  686. pEaddr [5] = (u_char)(addr & 0xff);
  687. }
  688.     else
  689. {
  690.      /*
  691.       * Backplane hw address consists of
  692.        * { 0x00, 0x02, 0xE2, 0x00, unit, cpu }.
  693.        */
  694. pEaddr [4] =  (u_char)unit;
  695. pEaddr [5] =  (u_char)xs->smPktDesc.smDesc.cpuNum;
  696. }
  697.     if (smIfVerbose)
  698. printf ("hw address:%sn", ether_sprintf (pEaddr));
  699.     }