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

VxWorks

开发平台:

C/C++

  1. /* if_ln.c - AMD Am7990 LANCE Ethernet network interface driver */
  2. /* Copyright 1984-1997 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02x,15jul97,spm  added ARP request to SIOCSIFADDR ioctl handler
  8. 02w,10jun97,spm  removed frame check sequence from length of incoming packets
  9. 02v,04jun97,spm  corrected errors introduced during merge from Sirocco tree
  10. 02u,19may97,spm  eliminated all compiler warnings
  11. 02t,15may97,spm  included changes from versions 02r and 02s of Sirocco tree
  12. 02s,23jan97,vin  upgraded to BSD44
  13. 02s,06feb96,dat  added check for inactive interrupt, at end of lnInt.
  14.                  Added a real lnRestart function.
  15. 02r,11nov94,vin  incorporated the etherOutputHook routine.
  16. 02r,15jun94,dzb  [re]implemented buffer loaning, multiple unit support.
  17. 02q,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h
  18. 02p,19feb93,jdi  documentation cleanup.
  19. 02o,13oct92,rfs  Added documentation.
  20. 02n,02oct92,rfs  ANSI warnings go away.
  21. 02m,02oct92,rfs  Made multiple attach calls per unit return OK.
  22. 02l,09sep92,gae  documentation tweaks.
  23. 02k,02aug92,rfs  Merged with cache changes from previous version, added
  24.                  virtual address conversion and write pipe flushing.
  25.                  Removed code that appeared to handle chained incoming packets,
  26.                  but in fact could not do so.  Receive buffers must always be
  27.                  large enough to hold a complete packet.  Removed promiscuous
  28.                  support.  Moved all startup code to the attach routine.
  29.                  Eliminated the init() routine and provided stub for a restart
  30.                  routine that will handle the fatal errors.  Removed support
  31.                  for buffer loaning, as it was wrong as well.  Revised the
  32.                  ioctl() routine, which was also wrong.  Moved driver control
  33.                  structure(s) to bss and changed name used for pointer.
  34.                  Overhauled the transmit routines to discontinue the obsolete
  35.                  usage of the output queue.  Added the transmit semaphore.
  36.                  Many other misc.
  37. 02j,31jul92,dave Changed to new cacheLib.
  38. 02i,30jul92,rfs  Changed the way collisions are counted.
  39. 02h,29jul92,rfs  Typedef'd and renamed the driver control structure and,
  40.                  changed all references to it.
  41. 02g,29jul92,rfs  Moved driver specific items here from the header file.
  42. 02f,17jul92,jwt  added missing cache funtion pointers for "default" case.
  43. 02e,13jul92,rdc  now uses cacheMalloc.
  44. 02d,12jul92,jcf  cacheMalloc() call uses malloc() for 68k 'til cacheMc68kLib.
  45. 02c,06jul92,jwt  removed SPARC sysCacheSet() function calls due to 02c;
  46.                  forced conversion of &cacheFuncs to pointer for macros;
  47.                  cleaned up some typos and compiler warning messages.
  48.     02jul92,rfs  Added cache coherency support.  Added blank lines between
  49.                  functions.
  50. 02b,26may92,rrr  the tree shuffle
  51.                  -changed includes to have absolute path from h/
  52. 02a,27apr92,jwt  converted CPU==SPARC to CPU_FAMILY==SPARC.
  53. 01z,09oct91,jpb  rewrote to fix error handling for transmitter errors,
  54.                  should no longer hang.
  55.                  channel all chip accesses through new functions
  56.                  lnCsrRead and lnCsrWrite, and minimize chip accesses
  57.                  including eliminating transmitter kick-start in
  58.                  lnStartOutput if selected with lnKickStartTx == FALSE.
  59.                  modified to adapt to the LANCE chip alignment which
  60.                  eliminated the need for the RAP padding flags.
  61.                  fixed infinite loop on initialization failure to timeout.
  62.                  cleaned up some ansification remnants.
  63. 01y,04oct91,rrr  passed through the ansification filter
  64.                  -changed functions to ansi style
  65.                  -changed includes to have absolute path from h/
  66.                  -changed VOID to void
  67.                  -changed copyright notice
  68. 01x,02oct91,jwt  restored lnCSR_3B global variable for Radstone Apex driver.
  69. 01w,25jul91,jwt  removed bit fields (added masks) for portability, correctness.
  70. 01v,06mar91,hvh  aligned buffers for SPARC optimizations.
  71. 01u,20feb91,jwt  added sysCacheSet() call for DMA and caching support.
  72. 01t,10apr91,jdi  documentation cleanup; doc review by elh.
  73. 01s,20sep90,dab  made lnInit() return int.
  74. 01r,10aug90,dnw  added forward declarations of void routines.
  75.                  added include of if_subr.h.
  76. 01q,11jul90,hjb  removed references to ipintr().
  77. 01p,26jun90,hjb  copy_from_mbufs() & m_freem() fix; changed params to
  78.                  bulid_cluster().
  79. 01o,11may90,yao  added missing modification history (01n) for the last checkin.
  80. 01n,09may90,yao  typecasted malloc to (char *).
  81. 01m,07may90,hjb  new RMD loans implementation to avoid hangups.
  82. 01l,19apr90,hjb  deleted param.h, added LN_RMD_GIVE_TO_LANCE, deleted
  83.                  lnHandleXmitInt and ln_bcopy, added lnRmdFree to support
  84.                  cluster-callback optimization, speed-ups in lnInt(),
  85.                  use of LS_ flags, de-linted, modifications to receive
  86.                  routines, added lnLoansPrint() debug routine.
  87. 01k,18mar90,hjb  reduction of redundant code and addition of cluster support.
  88.                  added input error checking in RINT handling code to reduce
  89.                  unnecessary netJobAdd's.  recoded the Tadpole padding check.
  90.                  added crude LANCE data chaining support.
  91. 01j,08nov89,dab  added check for Tadpole cpu to enable padding of CSR structure.
  92. 01i,07aug89,gae  changed iv68k.h to iv.h.
  93. 01h,28jun89,hjb  fixed a bug in lnIoctl() -- SIOCSIFFLAGS handling was buggy.
  94. 01g,13jun89,hjb  changed mtu to ETHERMTU (from 1000).  check lnLogCount before
  95.                  doing modulo operation to make sure it's not zero.
  96. 01f,12jun89,hjb  added a missing splx (s) in lnRecv ().
  97. 01e,24may89,jcf  reduced netJobAdd () calls by handling more receive packets
  98.                  +dnw   at task level, and calling ipintr directly from lnRecv.
  99. 01d,14feb89,jcf  changed copy from/to interface to use appropriate data width.
  100.                  changed lnattach to optionally take address of memory pool.
  101.                  added macros ItoK(), KtoI(), etc.
  102.                  removed superfluous lnConfig() call from lnattach().
  103.                  +dnw  improved error reporting and recovery.
  104. 01c,07sep88,gae  added global variable lnLogCount so that dropped
  105.                  interrupts are not normally reported.
  106. 01b,09aug88,gae  made lnattach have usual number of parameters.  Lint.
  107. 01a,28apr88,dfm  written based on other drivers (if_xx) & LANCE documentation.
  108. */
  109. /*
  110. This module implements the Advanced Micro Devices Am7990 LANCE Ethernet network
  111. interface driver.
  112. This driver is designed to be moderately generic, operating unmodified
  113. across the range of architectures and targets supported by VxWorks.  To
  114. achieve this, the driver must be given several target-specific parameters,
  115. and some external support routines must be provided.  These parameters,
  116. and the mechanisms used to communicate them to the driver, are detailed
  117. below.  If any of the assumptions stated below are not true for your
  118. particular hardware, this driver will probably not function correctly with
  119. it.
  120. This driver supports only one LANCE unit per CPU.  The driver can be
  121. configured to support big-endian or little-endian architectures.  It
  122. contains error recovery code to handle known device errata related to DMA
  123. activity.
  124. BOARD LAYOUT
  125. This device is on-board.  No jumpering diagram is necessary.
  126. EXTERNAL INTERFACE
  127. This driver provides the standard external interface with the following
  128. exceptions.  All initialization is performed within the attach routine;
  129. there is no separate initialization routine.  Therefore, in the global interface
  130. structure, the function pointer to the initialization routine is NULL.
  131. The only user-callable routine is lnattach(), which publishes the `ln'
  132. interface and initializes the driver and device.
  133. TARGET-SPECIFIC PARAMETERS
  134. .iP "bus mode"
  135. This parameter is a global variable that can be modified at run-time.
  136. The LANCE control register #3 determines the bus mode of the device,
  137. allowing the support of big-endian and little-endian architectures.
  138. This parameter, defined as "u_short lnCSR_3B", is the value that will
  139. be placed into LANCE control register #3.  The default value supports
  140. Motorola-type buses.  For information about changing this parameter, see 
  141. the manual
  142. .I "Advanced Micro Devices Local Area Network Controller Am7990 (LANCE)."
  143. .iP "base address of device registers"
  144. This parameter is passed to the driver by lnattach().  It 
  145. indicates to the driver where to find the RDP register.
  146. The LANCE presents two registers to the external interface, the RDP (register
  147. data port) and RAP (register address port) registers.  This driver assumes 
  148. that these two registers occupy two unique addresses in a memory space
  149. that is directly accessible by the CPU executing this driver.  The driver
  150. assumes that the RDP register is mapped at a lower address than the RAP
  151. register; the RDP register is therefore considered the "base address."
  152. .iP "interrupt vector"
  153. This parameter is passed to the driver by lnattach().
  154. This driver configures the LANCE device to generate hardware interrupts
  155. for various events within the device; thus it contains
  156. an interrupt handler routine.  The driver calls intConnect() to connect 
  157. its interrupt handler to the interrupt vector generated as a result of 
  158. the LANCE interrupt.
  159. .iP "interrupt level"
  160. This parameter is passed to the driver by lnattach().
  161. Some targets use additional interrupt controller devices to help organize
  162. and service the various interrupt sources.  This driver avoids all
  163. board-specific knowledge of such devices.  During the driver's
  164. initialization, the external routine sysLanIntEnable() is called to
  165. perform any board-specific operations required to allow the servicing of a
  166. LANCE interrupt.  For a description of sysLanIntEnable(), see "External
  167. Support Requirements" below.
  168. This parameter is passed to the external routine.
  169. .iP "shared memory address"
  170. This parameter is passed to the driver by lnattach().
  171. The LANCE device is a DMA type of device and typically shares access to
  172. some region of memory with the CPU.  This driver is designed for systems
  173. that directly share memory between the CPU and the LANCE.  It
  174. assumes that this shared memory is directly available to it
  175. without any arbitration or timing concerns.
  176. This parameter can be used to specify an explicit memory region for use
  177. by the LANCE.  This should be done on hardware that restricts the LANCE
  178. to a particular memory region.  The constant NONE can be used to indicate
  179. that there are no memory limitations, in which case, the driver 
  180. attempts to allocate the shared memory from the system space.
  181. .iP "shared memory size"
  182. This parameter is passed to the driver by lnattach().
  183. This parameter can be used to explicitly limit the amount of shared
  184. memory (bytes) this driver will use.  The constant NONE can be used to
  185. indicate no specific size limitation.  This parameter is used only if
  186. a specific memory region is provided to the driver.
  187. .iP "shared memory width"
  188. This parameter is passed to the driver by lnattach().
  189. Some target hardware that restricts the shared memory region to a
  190. specific location also restricts the access width to this region by
  191. the CPU.  On these targets, performing an access of an invalid width
  192. will cause a bus error.
  193. This parameter can be used to specify the number of bytes of access
  194. width to be used by the driver during access to the shared memory.
  195. The constant NONE can be used to indicate no restrictions.
  196. Current internal support for this mechanism is not robust; implementation 
  197. may not work on all targets requiring these restrictions.
  198. .iP "Ethernet address"
  199. This parameter is obtained directly from a global memory location.
  200. During initialization, the driver needs to know the Ethernet address for
  201. the LANCE device.  The driver assumes that this address is available in
  202. a global, six-byte character array, lnEnetAddr[].  This array is
  203. typically created and stuffed by the BSP code.
  204. .LP
  205. EXTERNAL SUPPORT REQUIREMENTS
  206. This driver requires one external support function:
  207. .iP "void sysLanIntEnable (int level)" "" 9 -1
  208. This routine provides a target-specific enable of the interrupt for
  209. the LANCE device.  Typically, this involves interrupt controller hardware,
  210. either internal or external to the CPU.
  211. This routine is called once, from the lnattach() routine.
  212. .LP
  213. SYSTEM RESOURCE USAGE
  214. When implemented, this driver requires the following system resources:
  215.     - one mutual exclusion semaphore
  216.     - one interrupt vector
  217.     - 24 bytes in the initialized data section (data)
  218.     - 208 bytes in the uninitialized data section (BSS)
  219. The above data and BSS requirements are for the MC68020 architecture 
  220. and may vary for other architectures.  Code size (text) varies greatly between
  221. architectures and is therefore not quoted here.
  222. If the driver is not given a specific region of memory via the lnattach()
  223. routine, then it calls cacheDmaMalloc() to allocate the memory to be shared 
  224. with the LANCE.  The size requested is 80,542 bytes.  If a memory region
  225. is provided to the driver, the size of this region is adjustable to suit
  226. user needs.
  227. The LANCE can only be operated if the shared memory region is write-coherent
  228. with the data cache.  The driver cannot maintain cache coherency
  229. for the device for data that is written by the driver because fields
  230. within the shared structures are asynchronously modified by both the driver
  231. and the device, and these fields may share the same cache line.
  232. SEE ALSO: ifLib, 
  233. .I "Advanced Micro Devices Local Area Network Controller Am7990 (LANCE)"
  234. */
  235. /* includes */
  236. #include "vxWorks.h"
  237. #include "stdlib.h"
  238. #include "taskLib.h"
  239. #include "logLib.h"
  240. #include "intLib.h"
  241. #include "netLib.h"
  242. #include "stdio.h"
  243. #include "stdlib.h"
  244. #include "sysLib.h"
  245. #include "iv.h"
  246. #include "memLib.h"
  247. #include "cacheLib.h"
  248. #include "sys/ioctl.h"
  249. #include "etherLib.h"
  250. #include "net/mbuf.h"
  251. #include "net/protosw.h"
  252. #include "net/unixLib.h"
  253. #include "sys/socket.h"
  254. #include "errno.h"
  255. #include "net/if.h"
  256. #include "net/route.h"
  257. #include "netinet/in.h"
  258. #include "netinet/in_systm.h"
  259. #include "netinet/in_var.h"
  260. #include "netinet/ip.h"
  261. #include "netinet/if_ether.h"
  262. #include "net/if_subr.h"
  263. #include "semLib.h"
  264. #include "drv/netif/if_ln.h"            /* device description header */
  265. /* defines */
  266. #define LN_BUFSIZ (ETHERMTU + SIZEOF_ETHERHEADER + 6)
  267. #define LN_RMD_RLEN 5 /* default Rx ring size as a power of 2 (32) */
  268. #define LN_TMD_TLEN 5 /* default Tx ring size as a power of 2 (32) */
  269. #define LN_L_POOL 0x10 /* number of Rx loaner buffers in pool */
  270. #define MAX_UNITS 4 /* maximum units supported */
  271. /*
  272.  * If LN_KICKSTART_TX is TRUE, the transmitter is kick-started to force a
  273.  * read of the transmit descriptors, otherwise the internal polling (1.6msec)
  274.  * will initiate a read of the descriptors.  This should be FALSE if there
  275.  * is any chance of memory latency or chip accesses detaining the LANCE DMA,
  276.  * which results in a transmitter UFLO error.  This can be changed with the
  277.  * global lnKickStartTx below.
  278.  */
  279. #define LN_KICKSTART_TX TRUE
  280. /* Cache macros */
  281. #define LN_CACHE_INVALIDATE(address, len) 
  282.         CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))
  283. #define LN_CACHE_PHYS_TO_VIRT(address) 
  284.         CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))
  285. #define LN_CACHE_VIRT_TO_PHYS(address) 
  286.         CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
  287. /* typedefs for external structures that are not typedef'd in their .h files */
  288. typedef struct mbuf MBUF;
  289. typedef struct arpcom IDR; /* Interface Data Record wrapper */
  290. typedef struct ifnet IFNET; /* real Interface Data Record */
  291. typedef struct sockaddr SOCK;
  292. #ifndef BSD43_DRIVER
  293. typedef struct ether_header ETH_HDR; 
  294. #endif /* BSD43_DRIVER */
  295. /* the definition of the driver control structure */
  296. typedef struct drv_ctrl
  297.     {
  298.     IDR idr; /* Interface Data Record */
  299.     char *  pMemPool;               /* start of LANCE memory pool */
  300.     BOOL attached; /* indicates unit is attached */
  301.     int rmdIndex; /* current RMD index */
  302.     int rringSize; /* RMD ring size */
  303.     int         rringLen;               /* RMD ring length (bytes) */
  304.     ln_rmd *  rring; /* RMD ring start */
  305.     char *  rBufBase;               /* Rx buffer base address */
  306.     int tmdIndex; /* current TMD index */
  307.     int tmdIndexC; /* current TMD index */
  308.     int tringSize; /* TMD ring size */
  309.     int         tringLen;               /* TMD ring length (bytes) */
  310.     ln_tmd *  tring; /* TMD ring start */
  311.     char *  tBufBase; /* Tx buffer base address */
  312.     SEM_ID TxSem; /* transmitter semaphore */
  313.     u_char flags; /* misc control flags */
  314.     int ivec; /* interrupt vector */
  315.     int ilevel; /* interrupt level */
  316.     LN_DEVICE * devAdrs; /* device structure address */
  317.     int memWidth; /* width of data port */
  318.     CACHE_FUNCS cacheFuncs; /* cache function pointers */
  319.     int nLoanRx; /* number of Rx buffers left to loan */
  320.     char *  lPool[LN_L_POOL]; /* receive loaner pool ptrs */
  321.     UINT8 *  pRefCnt[LN_L_POOL]; /* stack of reference count pointers */
  322.     UINT8 refCnt[LN_L_POOL]; /* actual reference count values */
  323.     } DRV_CTRL;
  324. #define DRV_CTRL_SIZ sizeof(DRV_CTRL)
  325. #define DC_SIZ sizeof(LN_DC_BUF)
  326. #ifdef BSD43_DRIVER
  327. #define ENET_HDR_SIZ sizeof(ETH_HDR)
  328. #endif  /* BSD43_DRIVER */
  329. #define RMD_SIZ sizeof(ln_rmd)
  330. #define TMD_SIZ sizeof(ln_tmd)
  331. #define IB_SIZ sizeof(ln_ib)
  332. /* definitions for the flags field */
  333. #define LN_PROMISCUOUS_FLAG 0x1
  334. #define LN_RX_HANDLING_FLAG 0x2
  335. /* globals */
  336. IMPORT void sysLanIntEnable ();
  337. #ifdef BSD43_DRIVER
  338. IMPORT BOOL arpresolve ();
  339. #endif  /* BSD43_DRIVER */
  340. IMPORT unsigned char lnEnetAddr []; /* Ethernet addr to load into lance */
  341. u_short lnCSR_3B = lncsr3_BSWP ; /* allows ext setting of bus modes */
  342. BOOL lnKickStartTx = LN_KICKSTART_TX;
  343. /* locals */
  344. LOCAL DRV_CTRL drvCtrl [MAX_UNITS]; /* array of driver control structures */
  345. LOCAL int lnTsize = LN_TMD_TLEN; /* deflt xmit ring size as power of 2 */
  346. LOCAL int lnRsize = LN_RMD_RLEN; /* deflt recv ring size as power of 2 */
  347. LOCAL int lnLPool = LN_L_POOL;
  348. /* initial word offsets from LANCE base address to access these registers */
  349. LOCAL u_int CSROffset = 0;
  350. LOCAL u_int RAPOffset = 1;
  351. /* forward declarations */
  352. #ifdef __STDC__
  353. LOCAL void lnReset (int unit);
  354. LOCAL void lnInt (DRV_CTRL *pDrvCtrl);
  355. LOCAL void lnHandleRecvInt (DRV_CTRL *pDrvCtrl);
  356. LOCAL STATUS lnRecv (DRV_CTRL *pDrvCtrl);
  357. #ifdef BSD43_DRIVER
  358. LOCAL int lnOutput (IDR *ifp, MBUF *m0, SOCK *dst);
  359. #else
  360. LOCAL void lnStartOutput (DRV_CTRL * pDrvCtrl);
  361. #endif /* BSD43_DRIVER */
  362. LOCAL int lnIoctl (IDR *ifp, int cmd, caddr_t data);
  363. LOCAL void lnChipReset (DRV_CTRL *pDrvCtrl);
  364. LOCAL BOOL lnGetFullRMD (DRV_CTRL *pDrvCtrl);
  365. LOCAL u_short lnCsr0Read (DRV_CTRL * pDrvCtrl);
  366. LOCAL void lnCsr0Write (DRV_CTRL * pDrvCtrl, u_short value);
  367. LOCAL void lnCsrWrite (DRV_CTRL * pDrvCtrl, int reg, u_short value);
  368. LOCAL void lnRestart (int unit);
  369. LOCAL void lnRestartSetup (DRV_CTRL * pDrvCtrl);
  370. #ifdef BSD43_DRIVER
  371. LOCAL BOOL convertDestAddr (IDR *pIDR, SOCK *pDestSktAddr, char *pDestEnetAddr,
  372.      u_short *pPacketType, MBUF *pMbuf);
  373. #endif /* BSD43_DRIVER */
  374. LOCAL void lnLoanFree (DRV_CTRL *pDrvCtrl, char *pRxBuf, UINT8 *pRef);
  375. #else /* __STDC__ */
  376. LOCAL void lnReset ();
  377. LOCAL void lnInt ();
  378. LOCAL void lnHandleRecvInt ();
  379. LOCAL STATUS lnRecv ();
  380. #ifdef BSD43_DRIVER
  381. LOCAL int lnOutput ();
  382. #else
  383. LOCAL void lnStartOutput ();
  384. #endif /* BSD43_DRIVER */
  385. LOCAL int lnIoctl ();
  386. LOCAL void lnChipReset ();
  387. LOCAL BOOL lnGetFullRMD ();
  388. LOCAL u_short lnCsr0Read ();
  389. LOCAL void lnCsr0Write ();
  390. LOCAL void lnCsrWrite ();
  391. LOCAL void lnRestart ();
  392. LOCAL BOOL convertDestAddr ();
  393. LOCAL void lnLoanFree ();
  394. #endif /*  __STDC__ */
  395. /*******************************************************************************
  396. *
  397. * lnattach - publish the `ln' network interface and initialize driver structures
  398. *
  399. * This routine publishes the `ln' interface by filling in a network interface
  400. * record and adding this record to the system list.  This routine also
  401. * initializes the driver and the device to the operational state.
  402. *
  403. * The <memAdrs> parameter can be used to specify the location of the
  404. * memory that will be shared between the driver and the device.  The value
  405. * NONE is used to indicate that the driver should obtain the memory.
  406. *
  407. * The <memSize> parameter is valid only if the <memAdrs> parameter is not
  408. * set to NONE, in which case <memSize> indicates the size of the
  409. * provided memory region.
  410. *
  411. * The <memWidth> parameter sets the memory pool's data port width (in bytes);
  412. * if it is NONE, any data width is used.
  413. *
  414. * BUGS
  415. * To zero out LANCE data structures, this routine uses bzero(), which
  416. * ignores the <memWidth> specification and uses any size data access to
  417. * write to memory.
  418. *
  419. * RETURNS: OK or ERROR.
  420. */
  421. STATUS lnattach
  422.     (
  423.     int       unit, /* unit number */
  424.     char     *devAdrs, /* LANCE I/O address */
  425.     int       ivec, /* interrupt vector */
  426.     int       ilevel, /* interrupt level */
  427.     char     *memAdrs, /* address of memory pool (-1 = malloc it) */
  428.     ULONG     memSize, /* only used if memory pool is NOT malloc()'d */
  429.     int       memWidth, /* byte-width of data (-1 = any width)     */
  430.     int       spare, /* not used */
  431.     int       spare2 /* not used */
  432.     )
  433.     {
  434.     DRV_CTRL     *pDrvCtrl;
  435.     char         *pShMem; /* start of the LANCE memory pool */
  436.     char         *buf;
  437.     ln_rmd       *rmd;
  438.     unsigned int sz;
  439.     int          ix;
  440.     /* sanity check the unit number */
  441.     if (unit < 0 || unit >= MAX_UNITS)
  442.         return (ERROR);
  443.     /* ensure single invocation per system life */
  444.     pDrvCtrl = & drvCtrl [unit];
  445.     if (pDrvCtrl->attached)
  446.         return (OK);
  447.     /* publish the interface data record */
  448. #ifdef BSD43_DRIVER
  449.     ether_attach (& pDrvCtrl->idr.ac_if, unit, "ln", (FUNCPTR) NULL,
  450.                   (FUNCPTR) lnIoctl, (FUNCPTR) lnOutput, (FUNCPTR) lnReset);
  451. #else
  452.     /* Publish the interface record */
  453.     ether_attach    (
  454.                     (IFNET *) & pDrvCtrl->idr,
  455.                     unit,
  456.                     "ln",
  457.                     (FUNCPTR) NULL,
  458.                     (FUNCPTR) lnIoctl,
  459.                     (FUNCPTR) ether_output, /* generic ether_output */
  460.                     (FUNCPTR) lnReset
  461.                     );
  462.     pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)lnStartOutput;
  463. #endif
  464.     /* create the transmit semaphore. */
  465.     if ((pDrvCtrl->TxSem = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE |
  466. SEM_INVERSION_SAFE)) == NULL)
  467.         {
  468.         printf ("ln: error creating transmitter semaphoren");
  469.         return (ERROR);
  470.         }
  471.     /* establish size of shared memory region we require */
  472.     if ((int) memAdrs != NONE)  /* specified memory pool */
  473.         {
  474.         /* we want to maximize lnRsize and lnTsize */
  475.         sz = (memSize - (RMD_SIZ + TMD_SIZ + (lnLPool * LN_BUFSIZ) +
  476.      IB_SIZ)) / ((2 * LN_BUFSIZ) + RMD_SIZ + TMD_SIZ);
  477.         sz >>= 1; /* adjust for roundoff */
  478.         for (lnRsize = 0; sz != 0; lnRsize++, sz >>= 1)
  479.             ;
  480.         lnTsize = lnRsize; /* lnTsize = lnRsize for convenience */
  481.         }
  482.     /* limit ring sizes to reasonable values */
  483.     lnRsize = max (lnRsize, 2); /* 4 Rx buffers is reasonable min */
  484.     lnRsize = min (lnRsize, 7); /* 128 Rx buffers is max for chip */
  485.     lnTsize = max (lnTsize, 2); /* 4 Tx buffers is reasonable min */
  486.     lnTsize = min (lnTsize, 7); /* 128 Tx buffers is max for chip */
  487.     lnLPool = min (lnLPool, LN_L_POOL); /* L_POOL is max for Rx loaner pool */
  488.     /* add it all up - allow extra bytes for alignment adjustments */
  489.     sz = (((1 << lnRsize) + 1) * RMD_SIZ ) + (LN_BUFSIZ << lnRsize) +
  490.  (((1 << lnTsize) + 1) * TMD_SIZ ) + (LN_BUFSIZ << lnTsize) +
  491.  (LN_BUFSIZ * lnLPool) + IB_SIZ + 24;
  492.     /* establish a region of shared memory */
  493.     /*
  494.      * OK. We now know how much shared memory we need.  If the caller
  495.      * provides a specific memory region, we check to see if the provided
  496.      * region is large enough for our needs.  If the caller did not
  497.      * provide a specific region, then we attempt to allocate the memory
  498.      * from the system, using the cache aware allocation system call.
  499.      */
  500.     switch ( (int) memAdrs )
  501.         {
  502.         default : /* caller provided memory */
  503.             if ( memSize < sz ) /* not enough space */
  504.                 {
  505.                 printf ( "ln: not enough memory providedn" );
  506.                 return ( ERROR );
  507.                 }
  508.             pShMem = memAdrs; /* set the beginning of pool */
  509.             /* assume pool is cache coherent, copy null structure */
  510.             pDrvCtrl->cacheFuncs = cacheNullFuncs;
  511.             break;
  512.         case NONE :     /* get our own memory */
  513.             /*
  514.      * Because the structures that are shared between the device
  515.              * and the driver may share cache lines, the possibility exists
  516.              * that the driver could flush a cache line for a structure and
  517.              * wipe out an asynchronous change by the device to a neighboring
  518.              * structure. Therefore, this driver cannot operate with memory
  519.              * that is not write coherent.  We check for the availability of
  520.              * such memory here, and abort if the system did not give us what
  521.              * we need.
  522.              */
  523.             if (!CACHE_DMA_IS_WRITE_COHERENT ())
  524.                 {
  525.                 printf ( "ln: device requires cache coherent memoryn" );
  526.                 return (ERROR);
  527.                 }
  528.             pShMem = (char *) cacheDmaMalloc (sz);
  529.             if ((int) pShMem == NULL)
  530.                 {
  531.                 printf ( "ln: system memory unavailablen" );
  532.                 return (ERROR);
  533.                 }
  534.             /* copy the DMA structure */
  535.             pDrvCtrl->cacheFuncs = cacheDmaFuncs;
  536.             break;
  537.         }
  538.     /* Align pool on 4 byte boundary - uses up to 8 bytes of excess memory. */
  539.     pShMem = (char *) ( ( (int)pShMem + 3) & ~3);
  540.     /* save some things */
  541.     pDrvCtrl->flags    = 0; /* initialize the LANCE flags */
  542.     pDrvCtrl->memWidth = memWidth;
  543.     pDrvCtrl->ivec     = ivec;                  /* interrupt vector */
  544.     pDrvCtrl->ilevel   = ilevel;                /* interrupt level */
  545.     pDrvCtrl->devAdrs  = (LN_DEVICE *) devAdrs; /* LANCE I/O address */
  546.     pDrvCtrl->pMemPool = pShMem;                /* start of memory pool */
  547.     /* obtain our Ethernet address and save it */
  548.     bcopy ((char *) lnEnetAddr, (char *) pDrvCtrl->idr.ac_enaddr, 6);
  549.     /*
  550.      *                        MEMORY MAPPING
  551.      *
  552.      *                          low memory
  553.      *
  554.      *             |-------------------------------------|
  555.      *             |       The initialization block      |
  556.      *             |              (IB_SIZ)               |
  557.      *             |-------------------------------------|
  558.      *             |         The Rx descriptors          |
  559.      *             |   ((1 << lnRsize) + 1) * RMD_SIZ    |
  560.      *             |-------------------------------------|
  561.      *             |          The receive buffers        |
  562.      *             |       (LN_BUFSIZ << lnRsize)        |
  563.      *             |-------------------------------------|
  564.      *             |         The Rx loaner pool          |
  565.      *             |        (LN_BUFSIZ * lnLPool)        |
  566.      *             |-------------------------------------|
  567.      *             |         The Tx descriptors          |
  568.      *             |    ((1 << lnTsize) + 1)* TMD_SIZ    |
  569.      *             |-------------------------------------|
  570.      *             |        The transmit buffers         |
  571.      *             |       (LN_BUFSIZ << lnTsize)        |
  572.      *             |-------------------------------------|
  573.      */
  574.     /* first let's clear memory */
  575.     bzero ((char *) pShMem, (int) sz); /* XXX deal with memWidth */
  576.     /* carve Rx memory structure */
  577.     pDrvCtrl->rring     = (ln_rmd *) ((int)pShMem + IB_SIZ);
  578.     pDrvCtrl->rringLen  = lnRsize;
  579.     pDrvCtrl->rringSize = 1 << lnRsize;
  580.     pDrvCtrl->rmdIndex = 0;
  581.     /* setup Rx buffer descriptors */
  582.     rmd = pDrvCtrl->rring;
  583.     /* 
  584.      * Set the Rx buffer misaligned so that the ether header will align the
  585.      * IP header on a 4 byte boundary. 
  586.      */
  587.     buf = ( (char *) (rmd + (pDrvCtrl->rringSize +1))) + 2;
  588.     /* Skip over the receive buffer pool to the Rx loaner pool. */
  589.     buf += LN_BUFSIZ << lnRsize;
  590.     /* setup Rx loaner pool */
  591.     pDrvCtrl->nLoanRx = lnLPool;
  592.     for (ix = 0; ix < lnLPool; ix++)
  593. {
  594.         pDrvCtrl->lPool[ix] = buf + (ix * LN_BUFSIZ);
  595.         pDrvCtrl->refCnt[ix] = 0;
  596.         pDrvCtrl->pRefCnt[ix] = & pDrvCtrl->refCnt[ix];
  597. }
  598.     /* carve Tx memory structure */
  599.     /* Note: +2 offset aligns IP header on 4 byte boundary. */
  600.      
  601.     pDrvCtrl->tring     = (ln_tmd *)(buf + (ix * LN_BUFSIZ) + 2);
  602.     pDrvCtrl->tringLen  = lnTsize;
  603.     pDrvCtrl->tringSize = 1 << lnTsize;
  604.     pDrvCtrl->tmdIndex = 0;
  605.     pDrvCtrl->tmdIndexC = 0;
  606.     lnChipReset (pDrvCtrl);                           /* reset LANCE */
  607.  
  608.     if (intConnect ((VOIDFUNCPTR *) INUM_TO_IVEC (ivec), lnInt, (int) pDrvCtrl)
  609.         == ERROR)
  610.         return (ERROR);
  611.     lnRestartSetup (pDrvCtrl);
  612.     pDrvCtrl->attached = TRUE; /* Set our flag */
  613.     return (OK);
  614.     }
  615. /*******************************************************************************
  616. *
  617. * lnReset - reset the interface
  618. *
  619. * Mark interface as inactive & reset the chip
  620. */
  621. LOCAL void lnReset
  622.     (
  623.     int unit
  624.     )
  625.     {
  626.     DRV_CTRL *pDrvCtrl = & drvCtrl [unit];
  627.     pDrvCtrl->idr.ac_if.if_flags = 0;
  628.     lnChipReset (pDrvCtrl); /* reset LANCE */
  629.     }
  630. /*******************************************************************************
  631. *
  632. * lnInt - handle controller interrupt
  633. *
  634. * This routine is called at interrupt level in response to an interrupt from
  635. * the controller.
  636. */
  637. LOCAL void lnInt
  638.     (
  639.     DRV_CTRL  *pDrvCtrl
  640.     )
  641.     {
  642.     ln_tmd *tmd;
  643.     u_short stat;
  644.     int  i;
  645.     stat = lnCsr0Read (pDrvCtrl); /* Read the device status register */
  646.     if (!(stat & lncsr_INTR)) /* If false interrupt, return. */
  647.         return;
  648.     /*
  649.      * Enable interrupts, clear receive and/or transmit interrupts, and clear
  650.      * any errors that may be set.
  651.      */
  652.     lnCsr0Write (pDrvCtrl, ((stat & (lncsr_BABL | lncsr_CERR | lncsr_MISS |
  653. lncsr_MERR | lncsr_RINT | lncsr_TINT | lncsr_IDON)) | lncsr_INEA));
  654.     /* Check for errors */
  655.     if (stat & (lncsr_BABL | lncsr_MISS | lncsr_MERR))
  656.         {
  657.         ++pDrvCtrl->idr.ac_if.if_ierrors;
  658.         if (stat & lncsr_MERR) /* restart chip on memory error */
  659.             {
  660.             logMsg ("lnInt: memory error detectedn",0, 0, 0, 0, 0, 0);
  661.             pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);
  662.             (void) netJobAdd ((FUNCPTR) lnRestart, pDrvCtrl->idr.ac_if.if_unit,
  663.                               0,0,0,0);
  664.             }
  665.         }
  666.     /* schedule netTask to handle any Rx packets */
  667.     if ((stat & lncsr_RINT) && (stat & lncsr_RXON) &&
  668. !(pDrvCtrl->flags & LN_RX_HANDLING_FLAG))
  669. {
  670.         pDrvCtrl->flags |= LN_RX_HANDLING_FLAG;
  671.         (void) netJobAdd ((FUNCPTR)lnHandleRecvInt, (int)pDrvCtrl, 0,0,0,0);
  672.         }
  673.  
  674.     /*
  675.      * Did LANCE update any of the TMD's?
  676.      * If not then don't bother continuing with transmitter stuff
  677.      */  
  678.     if (!(stat & lncsr_TINT))
  679.         {
  680.         /* Flush the write pipe */
  681.         CACHE_PIPE_FLUSH ();
  682.         /* allow interrupt line to go inactive */
  683.         i = 3;
  684.         while (i-- && (lnCsr0Read (pDrvCtrl) & lncsr_INTR))
  685.            ;
  686.         return;
  687.         }
  688.     while (pDrvCtrl->tmdIndexC != pDrvCtrl->tmdIndex)
  689.         {
  690.         /* disposal has not caught up */
  691.  
  692.         tmd = pDrvCtrl->tring + pDrvCtrl->tmdIndexC;
  693.  
  694.         /* if the buffer is still owned by LANCE, don't touch it */
  695.  
  696.         LN_CACHE_INVALIDATE (tmd, TMD_SIZ);
  697.         if (tmd->tbuf_stat & TMD_OWN)
  698.             break;
  699.         /*
  700.          * lntmd1_ERR is an "OR" of LCOL, LCAR, UFLO or RTRY.
  701.          * Note that BUFF is not indicated in lntmd1_ERR.
  702.          * We should therefore check both lntmd1_ERR and lntmd3_BUFF
  703.          * here for error conditions.
  704.          */
  705.         if ((tmd->tbuf_stat & lntmd1_ERR) || (tmd->tbuf_err & lntmd3_BUFF))
  706.             {
  707.             pDrvCtrl->idr.ac_if.if_oerrors++;     /* output error */
  708.             pDrvCtrl->idr.ac_if.if_opackets--;
  709.             /* 
  710.              * If error was due to excess collisions, bump the collision
  711.              * counter.  The LANCE does not keep an individual counter of
  712.              * collisions, so in this driver, the collision statistic is not
  713.              * an accurate count of total collisions.
  714.              */
  715.             if (tmd->tbuf_err & lntmd3_RTRY) /* assume DRTY bit not set */
  716.                 pDrvCtrl->idr.ac_if.if_collisions += 16;
  717.             /* check for no carrier */
  718.             if (tmd->tbuf_err & TMD_LCAR)
  719.                 logMsg ("ln%d: no carriern", pDrvCtrl->idr.ac_if.if_unit,
  720.                          0, 0, 0, 0, 0);
  721.             /* Restart chip on fatal errors.
  722.              * The following code handles the situation where the transmitter
  723.              * shuts down due to an underflow error.  This is a situation that
  724.              * will occur if the DMA cannot keep up with the transmitter.
  725.              * It will occur if the LANCE is being held off from DMA access
  726.              * for too long or due to significant memory latency.  DRAM
  727.              * refresh or slow memory could influence this.  Many
  728.              * implementations use a dedicated LANCE buffer.  This can be
  729.              * static RAM to eliminate refresh conflicts; or dual-port RAM
  730.              * so that the LANCE can have free run of this memory during its
  731.              * DMA transfers.
  732.              */
  733.     
  734.             if ((tmd->tbuf_err & lntmd3_BUFF) || (tmd->tbuf_err & TMD_UFLO))
  735.                 {
  736.                 pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);
  737.                 logMsg ("lnInt: transmitter underflown", 0, 0, 0, 0, 0, 0);
  738.                 (void) netJobAdd ((FUNCPTR) lnRestart,
  739.             pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0);
  740.                 /* Flush the write pipe */
  741.                 CACHE_PIPE_FLUSH ();
  742.                 /* allow interrupt line to go inactive */
  743.                 i = 3;
  744.                 while (i-- && (lnCsr0Read (pDrvCtrl) & lncsr_INTR))
  745.                     ;
  746.                 return;
  747.                 }
  748.             }
  749.         tmd->tbuf_stat &= 0x00ff;  /* reset status bits */
  750.         tmd->tbuf_err = 0;  /* clear error bits */
  751.        /* now bump the tmd disposal index pointer around the ring */
  752.         pDrvCtrl->tmdIndexC = (pDrvCtrl->tmdIndexC + 1) &
  753.                               (pDrvCtrl->tringSize - 1);
  754.         }
  755.     CACHE_PIPE_FLUSH (); /* flush the write pipe */
  756.     /* allow interrupt line to go inactive */
  757.     i = 3;
  758.     while (i-- && (lnCsr0Read (pDrvCtrl) & lncsr_INTR))
  759.         ;
  760.     }
  761. /*******************************************************************************
  762. *
  763. * lnHandleRecvInt - task level interrupt service for input packets
  764. *
  765. * This routine is called at task level indirectly by the interrupt
  766. * service routine to do any message received processing.
  767. */
  768. LOCAL void lnHandleRecvInt
  769.     (
  770.     DRV_CTRL *pDrvCtrl
  771.     )
  772.     {
  773.     do {
  774.         pDrvCtrl->flags |= LN_RX_HANDLING_FLAG;
  775.         while (lnGetFullRMD (pDrvCtrl))
  776.             lnRecv (pDrvCtrl);
  777.         /*
  778.          * There is a RACE right here.  The ISR could add a receive packet
  779.          * and check the boolean below, and decide to exit.  Thus the
  780.          * packet could be dropped if we don't double check before we
  781.          * return.
  782.          */
  783.         pDrvCtrl->flags &= ~LN_RX_HANDLING_FLAG;
  784.         }
  785.     while (lnGetFullRMD (pDrvCtrl)); /* double check for RACE */
  786.     }
  787. /*******************************************************************************
  788. *
  789. * lnGetFullRMD - check next RMD for ownership
  790. *
  791. */
  792. LOCAL BOOL lnGetFullRMD
  793.     (
  794.     DRV_CTRL *pDrvCtrl
  795.     )
  796.     {
  797.     int status = FALSE;
  798.     ln_rmd *rmd;
  799.     if  ((pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) ==
  800.         (IFF_UP | IFF_RUNNING))
  801. {
  802.         rmd = pDrvCtrl->rring + pDrvCtrl->rmdIndex;
  803.         LN_CACHE_INVALIDATE (rmd, RMD_SIZ);
  804.         if ((rmd->rbuf_stat & lnrmd1_OWN) == 0)
  805.             status = TRUE;
  806. }
  807.     return (status);
  808.     }
  809. /*******************************************************************************
  810. *
  811. * lnRecv - process the next incoming packet
  812. *
  813. */
  814. LOCAL STATUS lnRecv
  815.     (
  816.     DRV_CTRL *pDrvCtrl
  817.     )
  818.     {
  819.     ETH_HDR *pEnetHdr;
  820.     MBUF *pMbuf = NULL;
  821.     ln_rmd *rmd = pDrvCtrl->rring + pDrvCtrl->rmdIndex;
  822.     u_char *pData;
  823.     u_long pPhys;
  824.     int len;
  825.     u_short type;
  826.     /* packet must be checked for errors or possible data chaining */
  827.     if ((rmd->rbuf_stat & lnrmd1_ERR) || ((rmd->rbuf_stat &
  828. (lnrmd1_STP | lnrmd1_ENP)) != (lnrmd1_STP | lnrmd1_ENP)))
  829.         {
  830.         ++pDrvCtrl->idr.ac_if.if_ierrors; /* bump error stat */
  831.         goto cleanRXD; /* skip to clean up */
  832.         }
  833.     len = rmd->rbuf_mcnt; /* get packet length */
  834.     len = len - 4;  /* omit frame check sequence */
  835.     /* get pointer to the receive buffer */
  836.     pPhys = ((ULONG)pDrvCtrl->pMemPool & 0xff000000) |
  837.             ((rmd->rbuf_ladr | (rmd->rbuf_hadr << 16)) & 0x00ffffff);
  838.     pEnetHdr = (ETH_HDR *) LN_CACHE_PHYS_TO_VIRT (pPhys);
  839.     LN_CACHE_INVALIDATE (pEnetHdr, len); /* make the pkt data coherent */
  840.     /* call input hook if any */
  841.     if ((etherInputHookRtn == NULL) || ((*etherInputHookRtn)
  842.        (& pDrvCtrl->idr.ac_if, (char *) pEnetHdr, len)) == 0)
  843.         {
  844.         len -= SIZEOF_ETHERHEADER; /* adjust length to size of data only */
  845.         type = ntohs (pEnetHdr->ether_type); /* save type field */
  846.         pData = ((u_char *) pEnetHdr) + SIZEOF_ETHERHEADER;
  847.         /* OK to loan out buffer ? -> build an mbuf cluster */
  848. #ifdef BSD43_DRIVER    
  849. if ((pDrvCtrl->nLoanRx > 0) && (USE_CLUSTER (len)))
  850.     pMbuf = build_cluster (pData, len, & pDrvCtrl->idr, MC_LANCE,
  851.         pDrvCtrl->pRefCnt[(pDrvCtrl->nLoanRx - 1)], lnLoanFree,
  852. (int) pDrvCtrl, (int) pEnetHdr,
  853. (int) pDrvCtrl->pRefCnt[(pDrvCtrl->nLoanRx - 1)]);
  854.         /* if buffer was successfully turned into mbuf cluster */
  855.         if (pMbuf != NULL)
  856.     {
  857.             pPhys = (u_long) LN_CACHE_VIRT_TO_PHYS
  858.     (pDrvCtrl->lPool[--pDrvCtrl->nLoanRx]);
  859.             rmd->rbuf_ladr = pPhys;
  860.             rmd->rbuf_hadr = (pPhys >> 16) & lnrmd1_HADR;
  861.     }
  862.         else
  863.             {
  864.             if ((pMbuf = bcopy_to_mbufs (pData, len, 0, & pDrvCtrl->idr.ac_if,
  865.                 pDrvCtrl->memWidth)) == NULL)
  866. {
  867.                 ++pDrvCtrl->idr.ac_if.if_ierrors; /* bump error stat */
  868.                 goto cleanRXD;
  869. }
  870.             }
  871.         /* send on up... */
  872.         do_protocol_with_type (type, pMbuf, & pDrvCtrl->idr, len);
  873. #else  /* BSD43_DRIVER */
  874. if ((pDrvCtrl->nLoanRx > 0) && (USE_CLUSTER (len)) &&
  875.     ((pMbuf = build_cluster (pData, len, &pDrvCtrl->idr.ac_if, MC_LANCE,
  876.                                     pDrvCtrl->pRefCnt[(pDrvCtrl->nLoanRx - 1)],
  877.                                     (FUNCPTR)lnLoanFree, (int)pDrvCtrl, 
  878.                                     (int)pEnetHdr, 
  879.                     (int)pDrvCtrl->pRefCnt[(pDrvCtrl->nLoanRx - 1)])) != NULL))
  880.     {
  881.             pPhys = (u_long) LN_CACHE_VIRT_TO_PHYS
  882.     (pDrvCtrl->lPool[--pDrvCtrl->nLoanRx]);
  883.             rmd->rbuf_ladr = pPhys;
  884.             rmd->rbuf_hadr = (pPhys >> 16) & lnrmd1_HADR;
  885.     }
  886. else 
  887.     pMbuf = bcopy_to_mbufs (pData, len, 0, &pDrvCtrl->idr.ac_if, 
  888.                                     pDrvCtrl->memWidth);
  889. if (pMbuf != NULL)
  890.     do_protocol (pEnetHdr, pMbuf, &pDrvCtrl->idr, len);
  891. #endif /* BSD43_DRIVER */ 
  892.         ++pDrvCtrl->idr.ac_if.if_ipackets; /* bump statistic */
  893.         }
  894.     /* Done with descriptor, clean up and give it to the device. */
  895. cleanRXD:
  896.     rmd->rbuf_mcnt = 0; /* reset count */
  897.     rmd->rbuf_stat &= 0xff;  /* reset status bits */
  898.     rmd->rbuf_stat |= lnrmd1_OWN; /* give device ownership */
  899.     CACHE_PIPE_FLUSH (); /* flush the write pipe */
  900.     /* advance our management index */
  901.     pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
  902.     return (OK);
  903.     }
  904. #ifdef BSD43_DRIVER
  905. /*******************************************************************************
  906. *
  907. * lnOutput - the driver output routine
  908. *
  909. */
  910. LOCAL int lnOutput
  911.     (
  912.     IDR  *pIDR,
  913.     MBUF *pMbuf,
  914.     SOCK *pDest
  915.     )
  916.     {
  917.     DRV_CTRL *pDrvCtrl;
  918.     char destEnetAddr [6]; /* space for enet addr */
  919.     u_short packetType; /* type field for the packet */
  920.     ln_tmd *tmd;
  921.     char *buf;
  922.     int len;
  923.     /* check ifnet flags - return error if incorrect. */
  924.     if ((pIDR->ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=
  925. (IFF_UP | IFF_RUNNING))
  926.         return (ENETDOWN);
  927.     /*
  928.      * Attempt to convert socket addr into enet addr and packet type.
  929.      * Note that if ARP resolution of the address is required, the ARP
  930.      * module will call our routine again to transmit the ARP request
  931.      * packet.  This means we may actually call ourselves recursively!
  932.      */
  933.     if (convertDestAddr (pIDR,pDest, destEnetAddr, &packetType, pMbuf) == FALSE)
  934.         return (OK);    /* I KNOW returning OK is stupid, but it is correct */
  935.     /* get driver control pointer */
  936.     pDrvCtrl = & drvCtrl [pIDR->ac_if.if_unit];
  937.     /*
  938.      * Obtain exclusive access to transmitter.  This is necessary because
  939.      * certain events can cause netTask to run a job that attempts to transmit
  940.      * a packet.  We can only allow one task here at a time.
  941.      */
  942.     semTake (pDrvCtrl->TxSem, WAIT_FOREVER);
  943.     tmd = pDrvCtrl->tring + pDrvCtrl->tmdIndex;
  944.     LN_CACHE_INVALIDATE (tmd, TMD_SIZ);
  945.     if ((tmd->tbuf_stat & lntmd1_OWN) || (((pDrvCtrl->tmdIndex + 1) &
  946.         (pDrvCtrl->tringSize - 1)) == pDrvCtrl->tmdIndexC))
  947.         {
  948.         m_freem (pMbuf); /* discard data */
  949.         pDrvCtrl->idr.ac_if.if_oerrors++; /* output error */
  950.         goto outputDone;
  951.         }
  952.     buf = pDrvCtrl->tBufBase + (pDrvCtrl->tmdIndex * LN_BUFSIZ);
  953.     bcopy_from_mbufs ((buf + SIZEOF_ETHERHEADER), pMbuf, len,
  954.       pDrvCtrl->memWidth);
  955.     bcopy (destEnetAddr, buf, 6);
  956.     bcopy ((char *) pIDR->ac_enaddr, (buf + 6), 6);
  957.     ((ETH_HDR *) buf)->ether_type = packetType;
  958.     len += SIZEOF_ETHERHEADER;
  959.     len = max (ETHERSMALL, len);
  960.     if ((etherOutputHookRtn != NULL) &&
  961.         (* etherOutputHookRtn) (&pDrvCtrl->idr.ac_if,buf,len))
  962.         {
  963.         CACHE_PIPE_FLUSH ();    /* done as a safety */
  964.         goto outputDone;        /* goto the end */
  965.         }
  966.     tmd->tbuf_bcnt = -len;
  967.     tmd->tbuf_err = 0;
  968.     /* advance our management index */
  969.     pDrvCtrl->tmdIndex = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);
  970.     tmd->tbuf_stat |= lntmd1_OWN | lntmd1_STP | lntmd1_ENP;
  971.     tmd->tbuf_stat &= ~lntmd1_DEF & ~lntmd1_MORE & ~lntmd1_ERR;
  972.     CACHE_PIPE_FLUSH (); /* flush the write pipe */
  973.     /* kick start the transmitter, if selected */
  974.     if (lnKickStartTx)
  975.         lnCsr0Write (pDrvCtrl, (lncsr_INEA | lncsr_TDMD));
  976.     pIDR->ac_if.if_opackets++; /* bump the statistic counter. */
  977. outputDone:
  978.     semGive (pDrvCtrl->TxSem); /* release exclusive access. */
  979.     return (OK);
  980.     }
  981. #else /* BSD43_DRIVER */
  982. /*******************************************************************************
  983. *
  984. * lnStartOutput - the driver output routine
  985. *
  986. */
  987. LOCAL void lnStartOutput
  988.     (
  989.     DRV_CTRL * pDrvCtrl /* pointer to driver control structure */
  990.     )
  991.     {
  992.     struct mbuf *  pMbuf = NULL;
  993.     ln_tmd * tmd;
  994.     char * buf;
  995.     int len;
  996.     while (pDrvCtrl->idr.ac_if.if_snd.ifq_head)
  997.         {
  998. /* dequeue a packet from the transmit queue */
  999.         IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf);  
  1000. tmd = pDrvCtrl->tring + pDrvCtrl->tmdIndex;
  1001. LN_CACHE_INVALIDATE (tmd, TMD_SIZ);
  1002. if ((tmd->tbuf_stat & lntmd1_OWN) || (((pDrvCtrl->tmdIndex + 1) &
  1003.        (pDrvCtrl->tringSize - 1)) == 
  1004.       pDrvCtrl->tmdIndexC))
  1005.     {
  1006.     pDrvCtrl->idr.ac_if.if_oerrors++; /* output error */
  1007.     if (pMbuf != NULL)
  1008. m_freem (pMbuf);  /* drop the packet */
  1009.     break;
  1010.     }
  1011. buf = pDrvCtrl->tBufBase + (pDrvCtrl->tmdIndex * LN_BUFSIZ);
  1012. bcopy_from_mbufs (buf, pMbuf, len, pDrvCtrl->memWidth);
  1013.         len = max (ETHERSMALL, len);
  1014.         if ((etherOutputHookRtn != NULL) &&
  1015.             (* etherOutputHookRtn) (&pDrvCtrl->idr.ac_if,buf,len))
  1016.             {
  1017.             CACHE_PIPE_FLUSH ();    /* done as a safety */
  1018.             break; 
  1019.             }
  1020. tmd->tbuf_bcnt = -len;
  1021. tmd->tbuf_err = 0;
  1022. /* advance our management index */
  1023. pDrvCtrl->tmdIndex = ((pDrvCtrl->tmdIndex + 1) & 
  1024.       (pDrvCtrl->tringSize - 1));
  1025. tmd->tbuf_stat |= lntmd1_OWN | lntmd1_STP | lntmd1_ENP;
  1026.         tmd->tbuf_stat &= ~lntmd1_DEF & ~lntmd1_MORE & ~lntmd1_ERR;
  1027. CACHE_PIPE_FLUSH (); /* flush the write pipe */
  1028. /* kick start the transmitter, if selected */
  1029. if (lnKickStartTx)
  1030.     lnCsr0Write (pDrvCtrl, (lncsr_INEA | lncsr_TDMD));
  1031.         pDrvCtrl->idr.ac_if.if_opackets++; /* bump the statistic counter. */
  1032.         }
  1033.     }
  1034. #endif  /* BSD43_DRIVER */
  1035. /*******************************************************************************
  1036. *
  1037. * lnIoctl - the driver I/O control routine
  1038. *
  1039. * Process an ioctl request.
  1040. */
  1041. LOCAL int lnIoctl
  1042.     (
  1043.     IDR *ifp,
  1044.     int cmd,
  1045.     caddr_t data
  1046.     )
  1047.     {
  1048.     int error = 0;
  1049.     switch (cmd)
  1050.         {
  1051.         case SIOCSIFADDR:
  1052.            ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN (data)->sin_addr;
  1053.             arpwhohas (ifp, &IA_SIN (data)->sin_addr);
  1054.             break;
  1055.         case SIOCSIFFLAGS:
  1056.             /* No further work to be done */
  1057.             break;
  1058.         default:
  1059.             error = EINVAL;
  1060.         }
  1061.     return (error);
  1062.     }
  1063. /*******************************************************************************
  1064. *
  1065. * lnChipReset - hardware reset of chip (stop it)
  1066. */
  1067. LOCAL void lnChipReset
  1068.     (
  1069.     DRV_CTRL  *pDrvCtrl
  1070.     )
  1071.     {
  1072.     u_short *dv = (u_short *)pDrvCtrl->devAdrs;
  1073.     u_int RAPIndx;
  1074.     u_int CSRIndx;
  1075.     /*@RICK The following loops attempt to magically determine the exact
  1076.      * location of the two LANCE registers.  Not only is this algorithm
  1077.      * poorly documented, it is poor practice to poke at unknown memory
  1078.      * locations.  This will be revised.
  1079.      */
  1080.     /* find control registers and stop LANCE */
  1081.     for (CSRIndx=CSROffset; CSRIndx < 3; CSRIndx++)
  1082.         {
  1083.         for (RAPIndx=CSRIndx+1; RAPIndx <= 4; RAPIndx++)
  1084.             {
  1085.             /* setup CSR0 */
  1086.             *(dv+RAPIndx) = (u_short)0;
  1087.             if (!(u_short)*(dv+RAPIndx))
  1088.                 {
  1089.                 /* write stop */
  1090.                 *(dv+CSRIndx) = (u_short)lncsr_STOP;
  1091.                 /* might want to delay here */
  1092.                 }
  1093.             /* check stop condition */
  1094.             if ((!(u_short)*(dv+RAPIndx)) &&
  1095.                 ((u_short)*(dv+CSRIndx) == (u_short)lncsr_STOP)) break;
  1096.             }
  1097.         /* check stop condition */
  1098.         if ((!(u_short)*(dv+RAPIndx)) &&
  1099.             ((u_short)*(dv+CSRIndx) == (u_short)lncsr_STOP)) break;
  1100.         }
  1101.     CSROffset = CSRIndx;
  1102.     RAPOffset = RAPIndx;
  1103.     }
  1104. /*******************************************************************************
  1105. *
  1106. * lnCsr0Read - read CSR 0 register
  1107. *
  1108. * Assumes normal operation, where the RAP register has been left selecting
  1109. * CSR0.
  1110. */
  1111. LOCAL u_short lnCsr0Read
  1112.     (
  1113.     DRV_CTRL * pDrvCtrl /* driver control */
  1114.     )
  1115.     {
  1116.     u_short *dv = (u_short *) pDrvCtrl->devAdrs;
  1117.     return (*(dv + CSROffset)); /* get contents of CSR */
  1118.     }
  1119. /*******************************************************************************
  1120. *
  1121. * lnCsr0Write - write CSR 0 register
  1122. *
  1123. * Assumes normal operation, where the RAP register has been left selecting
  1124. * CSR0.
  1125. */
  1126. LOCAL void lnCsr0Write
  1127.     (
  1128.     DRV_CTRL * pDrvCtrl, /* driver control */
  1129.     u_short value /* value to write */
  1130.     )
  1131.     {
  1132.     u_short *dv = (u_short *) pDrvCtrl->devAdrs;
  1133.     *(dv + CSROffset) = (u_short) value; /* write value to CSR */
  1134.     }
  1135. /*******************************************************************************
  1136. *
  1137. * lnCsrWrite - select and write a CSR register
  1138. *
  1139. */
  1140. LOCAL void lnCsrWrite
  1141.     (
  1142.     DRV_CTRL * pDrvCtrl, /* driver control */
  1143.     int reg, /* register to select */
  1144.     u_short value /* value to write */
  1145.     )
  1146.     {
  1147.     u_short *dv = (u_short *) pDrvCtrl->devAdrs;
  1148.     *(dv + RAPOffset) = (u_short) reg; /* select CSR */
  1149.     *(dv + CSROffset) = (u_short) value; /* write value to CSR */
  1150.     }
  1151. /*******************************************************************************
  1152. *
  1153. * lnRestartSetup - setup memory descriptors and turn on chip
  1154. *
  1155. * Initializes all the shared memory structures and turns on the chip.
  1156. */
  1157. LOCAL void lnRestartSetup
  1158.     (
  1159.     DRV_CTRL *  pDrvCtrl
  1160.     )
  1161.     {
  1162.     char *  buf;
  1163.     void *  pTemp;
  1164.     ln_rmd *  rmd;
  1165.     ln_tmd *  tmd;
  1166.     ln_ib *  ib;
  1167.     int  ix;
  1168.     int  rsize;
  1169.     int  tsize;
  1170.     u_short  stat;
  1171.     int  timeoutCount = 0;
  1172.     /* setup Rx buffer descriptors */
  1173.     
  1174.     rsize = pDrvCtrl->rringLen;
  1175.     rmd = pDrvCtrl->rring;
  1176.     buf = ( (char *) (rmd + (pDrvCtrl->rringSize + 1))) + 2;
  1177.     rmd = (ln_rmd *) ( ( (int)rmd + 7) & ~7);   /* align on 000 boundary */
  1178.     pDrvCtrl->rring = rmd;
  1179.     pDrvCtrl->rBufBase = buf;
  1180.     for (ix = 0; ix < pDrvCtrl->rringSize; ix++, rmd++, buf += LN_BUFSIZ)
  1181.         {
  1182.         pTemp = LN_CACHE_VIRT_TO_PHYS (buf);    /* convert to physical addr */
  1183.         rmd->rbuf_ladr = (u_long) pTemp;        /* bits 15:00 of buffer addr */
  1184.         rmd->rbuf_hadr = (((u_long) pTemp >> 16) & 0xff) | lnrmd1_OWN;
  1185.                                                 /* bits 23:16 of buffer addr */
  1186.         rmd->rbuf_bcnt = -(LN_BUFSIZ);          /* neg of buffer byte count */
  1187.         rmd->rbuf_mcnt = 0;                     /* no message byte count yet */
  1188.         }
  1189.     /* setup Tx buffer descriptors */
  1190.     tsize = pDrvCtrl->tringLen;
  1191.     tmd = pDrvCtrl->tring;
  1192.     buf = ( (char *) (tmd + (pDrvCtrl->tringSize + 1))) + 2;
  1193.     tmd = (ln_tmd *) ( ( (int)tmd + 7) & ~7);   /* align on 000 boundary */
  1194.     pDrvCtrl->tring = tmd;
  1195.  
  1196.     pDrvCtrl->tBufBase = buf;
  1197.     for (ix = 0; ix < pDrvCtrl->tringSize; ix++, tmd++, buf += LN_BUFSIZ)
  1198.         {
  1199.         pTemp = LN_CACHE_VIRT_TO_PHYS (buf);    /* convert to phys addr */
  1200.         tmd->tbuf_ladr = (u_long)pTemp;        /* bits 15:00 of buf addr */
  1201.         tmd->tbuf_hadr = (((u_long)pTemp >> 16) & 0xff) | lntmd1_ENP; 
  1202.                                                /* bits 23:16 of buf addr */
  1203.         tmd->tbuf_bcnt = 0;                     /* no message byte count yet */
  1204.         tmd->tbuf_err = 0;                      /* no error status yet */
  1205.         }
  1206.     /* setup the initialization block */
  1207.     ib = (ln_ib *)pDrvCtrl->pMemPool;
  1208.     ib->lnIBMode = 0;           /* chip will be in normal receive mode */
  1209.     swab ((char *) pDrvCtrl->idr.ac_enaddr, ib->lnIBPadr, 6);
  1210.     pTemp = LN_CACHE_VIRT_TO_PHYS (pDrvCtrl->rring);    /* point to Rx ring */
  1211.     ib->lnIBRdraLow = (u_long) pTemp;
  1212.     ib->lnIBRdraHigh = (((u_long) pTemp >> 16) & 0xff) | (rsize << 13);
  1213.     pTemp = LN_CACHE_VIRT_TO_PHYS (pDrvCtrl->tring);    /* point to Tx ring */
  1214.     ib->lnIBTdraLow = (u_long) pTemp;
  1215.     ib->lnIBTdraHigh = (((u_long) pTemp >> 16) & 0xff) | (tsize << 13);
  1216.     CACHE_PIPE_FLUSH ();                        /* Flush the write pipe */
  1217.     lnCsrWrite (pDrvCtrl, 0, lncsr_STOP);       /* set the stop bit */
  1218.     /* set the bus modes */
  1219. #if (CPU_FAMILY == SPARC)
  1220.     lnCsrWrite (pDrvCtrl, 3, lncsr3_BSWP | lncsr3_ACON | lncsr3_BCON);
  1221. #else
  1222.     /* lnCSR_3B is either set above, or overridden externally */
  1223.     lnCsrWrite (pDrvCtrl, 3, lnCSR_3B);
  1224. #endif
  1225.     /* point the device to the initialization block */
  1226.     pTemp = LN_CACHE_VIRT_TO_PHYS (ib);
  1227.     lnCsrWrite (pDrvCtrl, 2, (u_short)(((u_long)pTemp >> 16) & 0xff));
  1228.     lnCsrWrite (pDrvCtrl, 1, (u_long) pTemp);
  1229.     lnCsrWrite (pDrvCtrl, 0, lncsr_INIT);       /* init chip (read IB) */
  1230.     /* hang until Initialization DONe, ERRor, or timeout */
  1231.     while (((stat = lnCsr0Read (pDrvCtrl)) & (lncsr_IDON | lncsr_ERR)) == 0)
  1232.         {
  1233.         if (timeoutCount++ > 0x10000) 
  1234.             break;
  1235.         taskDelay (100);
  1236.         }
  1237.     /* log chip initialization failure */
  1238.     if ((stat & lncsr_ERR) || (timeoutCount >= 0x10000) )
  1239.         {
  1240.         logMsg ("ln%d: Device initialization failedn",
  1241.                     pDrvCtrl->idr.ac_if.if_unit, 0, 0, 0, 0, 0);
  1242.         return;
  1243.         }
  1244.     /*
  1245.      * Device is initialized.  Start transmitter and receiver.  The device
  1246.      * RAP register is left selecting CSR 0.
  1247.      */
  1248.     lnCsrWrite (pDrvCtrl, 0, lncsr_IDON | lncsr_INEA | lncsr_STRT);
  1249.     sysLanIntEnable (pDrvCtrl->ilevel);         /* enable LANCE interrupts */
  1250.     pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);
  1251.     }
  1252. /*******************************************************************************
  1253. *
  1254. * lnRestart - restart the device after a fatal error
  1255. *
  1256. * This routine takes care of all the messy details of a restart.  The device
  1257. * is reset and re-initialized.  The driver state is re-synchronized.
  1258. */
  1259. LOCAL void lnRestart
  1260.     (
  1261.     int unit
  1262.     )
  1263.     {
  1264.     DRV_CTRL * pDrvCtrl = &drvCtrl [unit];
  1265.     printf("ln: RESTART calledn");
  1266.     lnChipReset (pDrvCtrl);
  1267.     lnRestartSetup (pDrvCtrl);
  1268.     /* Set our flag. */
  1269.     pDrvCtrl->attached = TRUE;
  1270.     return;
  1271.     }
  1272. #ifdef BSD43_DRIVER
  1273. /*******************************************************************************
  1274. *
  1275. * convertDestAddr - converts socket addr into enet addr and packet type
  1276. *
  1277. */
  1278. LOCAL BOOL convertDestAddr
  1279.     (
  1280.     IDR *pIDR,                          /* ptr to i/f data record */
  1281.     SOCK *pDestSktAddr,                 /* ptr to a generic sock addr */
  1282.     char *pDestEnetAddr,                /* where to write enet addr */
  1283.     u_short *pPacketType,               /* where to write packet type */
  1284.     MBUF *pMbuf                         /* ptr to mbuf data */
  1285.     )
  1286.     {
  1287.     /***** Internet family *****/
  1288.     {
  1289.     struct in_addr destIPAddr;              /* not used */
  1290.     int trailers;                           /* not supported */
  1291.      if (pDestSktAddr->sa_family == AF_INET)
  1292.         {
  1293.         *pPacketType = ETHERTYPE_IP;            /* stuff packet type */
  1294.         destIPAddr = ((struct sockaddr_in *) pDestSktAddr)->sin_addr;
  1295.         if (!arpresolve (pIDR, pMbuf, &destIPAddr, pDestEnetAddr, &trailers))
  1296.             return (FALSE);     /* if not yet resolved */
  1297.         return (TRUE);
  1298.         }
  1299.     }
  1300.     /***** Generic family *****/
  1301.     {
  1302.     ETH_HDR *pEnetHdr;
  1303.     if (pDestSktAddr->sa_family == AF_UNSPEC)
  1304.         {
  1305.         pEnetHdr = (ETH_HDR *) pDestSktAddr->sa_data;      /* ptr to hdr */
  1306.         bcopy ((char *) pEnetHdr->ether_dhost, pDestEnetAddr, 6);
  1307.         *pPacketType = pEnetHdr->ether_type;               /* copy type */
  1308.         return (TRUE);
  1309.         }
  1310.     }
  1311.     /* Unsupported family */
  1312.     return (FALSE);
  1313.     } /* End of convertDestAddr() */
  1314. #endif /* BSD43_DRIVER */
  1315. /*******************************************************************************
  1316. *
  1317. * lnLoanFree - return the given buffer to loaner pool
  1318. *
  1319. * This routine returns <pRxBuf> to the pool of available loaner buffers.
  1320. * It also returns <pRef> to the pool of available loaner reference counters,
  1321. * then zeroes the reference count.
  1322. *
  1323. * RETURNS: N/A
  1324. */
  1325.  
  1326. LOCAL void lnLoanFree
  1327.     (
  1328.     DRV_CTRL *pDrvCtrl,
  1329.     char *pRxBuf,
  1330.     UINT8 *pRef
  1331.     )
  1332.     {
  1333.     /* return loaned buffer to pool */
  1334.  
  1335.     pDrvCtrl->lPool[pDrvCtrl->nLoanRx] = pRxBuf;
  1336.  
  1337.     /* return loaned reference count to pool */
  1338.  
  1339.     pDrvCtrl->pRefCnt[pDrvCtrl->nLoanRx++] = pRef;
  1340.  
  1341.     /* reset reference count - should have been done from above, but... */
  1342.  
  1343.     *pRef = 0;
  1344.     }