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

VxWorks

开发平台:

C/C++

  1. /* if_lnIsa.c - AMD Am79C961 PCnet-ISA+ Ethernet network interface driver */
  2. /* Copyright 1984-1996 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01a,1sep96,joes  written from 01a of if_lnPci.c.
  8. */
  9. /*
  10. This module implements the Advanced Micro Devices Am79C961 PCnet-ISA+
  11. Ethernet  network interface driver.
  12. This driver is designed to be moderately generic, operating unmodified
  13. on any i386 or above PC architecture which supports the ISA bus.  To
  14. achieve this, the driver must be given several target-specific parameters,
  15. and some external support routines must be provided.  These parameters,
  16. and the mechanisms used to communicate them to the driver, are detailed
  17. below.  If any of the assumptions stated below are not true for your
  18. particular hardware, this driver will probably not function correctly with
  19. it.
  20. Plug And Play
  21. This device is compatible with the Microsoft Plug N' Play resource allocation
  22. specification (http://www.microsoft.com, the P n' P spec is available for 
  23. download from the microsoft site.). This device driver does not implement 
  24. the Plug N' Play protocol, but expects the device to power up on the ISA bus
  25. based on Data in the Plug N' Play EEPROM. Included are utilities for 
  26. programming the EEPROM if it is detected as invalid or if you wish to change
  27. the IEEE Ethernet address (Warning: This is not a bright thing to do if you 
  28. do not know what you are doing. It is included as a development/manufacturing
  29. tool only).
  30. If the EEPROM is invalid, the device is enabled onto the ISA Bus using the 
  31. device specific software relocatable key (A backdoor mechanism). This allows
  32. the EEPROM to be accessible and programmed with valid data. To enable the
  33. LANCE after programming the EEPROM, the pack must be rebooted.
  34. Little Endian
  35. It is assumed that the device is on a Intel X86 based platform, which supports
  36. sysInWord, sysOutWord, etc and is Little Endian.
  37. BOARD LAYOUT
  38. This device is jumperless.  No jumpering diagram is necessary.
  39. EXTERNAL INTERFACE
  40. This driver provides the standard external interface with the following
  41. exceptions.  All initialization is performed within the attach routine;
  42. there is no separate initialization routine.  Therefore, in the global 
  43. interface structure, the function pointer to the initialization routine is 
  44. NULL.
  45. The only user-callable routine is lnIsaattach(), which publishes the `lnIsa'
  46. interface and initializes the driver and device.
  47. TARGET-SPECIFIC PARAMETERS
  48. .iP "base address of device registers"
  49. This parameter is passed to the driver by lnIsaattach().  It 
  50. indicates to the driver where to find the device's register block. It is 
  51. assumed that 
  52. the Plug N' Play registers are already setup with data from the EEPROM
  53. and the device is enabled on the Bus. If the EEPROM is invalid, it may be 
  54. reprogrammed using lnIsa_eeprog() which takes the IEEE ethernet address and 
  55. (optionally) the IP address of the pack as parameters. It loads the Plug N' 
  56. Play EEPROM data area with values defined in config.h (See diagram in 
  57. lnIsa_eeprom.c). The pack can then be rebooted and the device will be enabled
  58. correctly. By defining IP_ADDR_STORED_IN_EEPROM 
  59. The enabled LANCE presents two registers to the external interface, the RDP 
  60. (register data port) and RAP (register address port) registers.  This driver 
  61. assumes that these two registers occupy two unique addresses in IO space
  62. that is directly accessible by the CPU executing this driver through the PC IO
  63. Read/Write functions sysInByte(), sysOutByte(), sysOutWord(), sysInWord().
  64. The register map is as follows:
  65.    Offset     #Bytes      Register
  66.    0x0 16 IEEE Address
  67.    0x10 2 RDP
  68.    0x12 2 RAP
  69.    0x14 2 Reset
  70.    0x16 2 IDP
  71. .iP "interrupt vector"
  72. This parameter is passed to the driver by lnIsaattach().
  73. This driver configures the LANCE device to generate hardware interrupts
  74. for various events within the device; thus it contains
  75. an interrupt handler routine.  The driver calls intConnect() to connect 
  76. its interrupt handler to the interrupt vector generated as a result of 
  77. the LANCE interrupt.
  78. .iP "interrupt level"
  79. This parameter is passed to the driver by lnIsaattach().
  80. Since this is an ISA device (i.e. PC based, an 8259 PIC is the expected 
  81. interrupt controller. Therefore sysIntEnablePIC() is explicitly referenced
  82. to enable the interrupts. This parameter is used to set up Edge or Level 
  83. triggered interrupts in the ISA brige chip.
  84. .iP "shared memory address"
  85. This parameter is passed to the driver by lnIsaattach().
  86. The LANCE device is a DMA type of device and typically shares access to
  87. some region of memory with the CPU.  This driver is designed for systems
  88. that directly share memory between the CPU and the LANCE.  It
  89. assumes that this shared memory is directly available to it
  90. without any arbitration or timing concerns.
  91. This parameter can be used to specify an explicit memory region for use
  92. by the LANCE.  This should be done on hardware that restricts the LANCE
  93. to a particular memory region.  The constant NONE can be used to indicate
  94. that there are no memory limitations, in which case, the driver 
  95. attempts to allocate the shared memory from the system space.
  96. .iP "shared memory size"
  97. This parameter is passed to the driver by lnIsaattach().
  98. This parameter can be used to explicitly limit the amount of shared
  99. memory (bytes) this driver will use.  The constant NONE can be used to
  100. indicate no specific size limitation.  This parameter is used only if
  101. a specific memory region is provided to the driver.
  102. .iP "shared memory width"
  103. This parameter is passed to the driver by lnIsaattach().
  104. Some target hardware that restricts the shared memory region to a
  105. specific location also restricts the access width to this region by
  106. the CPU.  On these targets, performing an access of an invalid width
  107. will cause a bus error.
  108. This parameter can be used to specify the number of bytes of access
  109. width to be used by the driver during access to the shared memory.
  110. The constant NONE can be used to indicate no restrictions.
  111. Current internal support for this mechanism is not robust; implementation 
  112. may not work on all targets requiring these restrictions.
  113. .iP "shared memory buffer size"
  114. This parameter is passed to the driver by lnIsaattach().
  115. The driver and LANCE device exchange network data in buffers.  This
  116. parameter permits the size of these individual buffers to be limited.
  117. A value of zero indicates that the default buffer size should be used.
  118. The default buffer size is large enough to hold a maximum-size Ethernet
  119. packet.
  120. Use of this parameter should be rare.  Network performance
  121. will be affected, since the target will no longer be able to receive
  122. all valid packet sizes.
  123. .iP "Ethernet address"
  124. This parameter is obtained directly from the EEPROM connected to the device.
  125. During initialization, the driver needs to know the Ethernet address for
  126. the LANCE device.  The driver assumes that this address is available in
  127. a global, six-byte character array, lnEnetAddr[].  This array is
  128. stuffed from EEPROM by lnIsaattach().
  129. .iP "DMA Channel"
  130. This parameter is defined in config.h by the MACRO DMA_CHAN_LNISA.
  131. The DMA channel selected must be a 16 bit channel. lnIsaattach() places this 
  132. channel in Cascade mode, which allows DMA requests to be passed though the
  133. DMA controller to the CPU.
  134. .LP
  135. EXTERNAL SUPPORT REQUIREMENTS
  136. This driver requires one external support function:
  137. .iP "void sysIntEnablePIC (int level)" "" 9 -1
  138. This routine provides a PC specific enable of the interrupt for
  139. the LANCE device.  
  140. This routine is called once, from the lnIsaattach() routine.
  141. .LP
  142. SYSTEM RESOURCE USAGE
  143. When implemented, this driver requires the following system resources:
  144.     - one mutual exclusion semaphore
  145.     - one interrupt vector
  146.     - 24 bytes in the initialized data section (data)
  147.     - 208 bytes in the uninitialized data section (BSS)
  148. The above data and BSS requirements are for the I80386 architecture 
  149. and may vary for other architectures.  Code size (text) varies greatly between
  150. architectures and is therefore not quoted here.
  151. If the driver is not given a specific region of memory via the lnIsaattach()
  152. routine, then it calls cacheDmaMalloc() to allocate the memory to be shared 
  153. with the LANCE.  The size requested is 80,542 bytes.  If a memory region
  154. is provided to the driver, the size of this region is adjustable to suit
  155. user needs.
  156. The LANCE can only be operated if the shared memory region is write-coherent
  157. with the data cache.  The driver cannot maintain cache coherency
  158. for the device for data that is written by the driver because fields
  159. within the shared structures are asynchronously modified by both the driver
  160. and the device, and these fields may share the same cache line.
  161. SEE ALSO: ifLib, 
  162. .I "Advanced Micro Devices PCnet-ISA+ Ethernet Controller for ISA."
  163. */
  164. #include "vxWorks.h"
  165. #include "sysLib.h"
  166. #include "stdlib.h"
  167. #include "taskLib.h"
  168. #include "logLib.h"
  169. #include "intLib.h"
  170. #include "netLib.h"
  171. #include "stdio.h"
  172. #include "stdlib.h"
  173. #include "sysLib.h"
  174. #include "iv.h"
  175. #include "memLib.h"
  176. #include "cacheLib.h"
  177. #include "sys/ioctl.h"
  178. #include "etherLib.h"
  179. #ifndef DOC             /* don't include when building documentation */
  180. #include "net/mbuf.h"
  181. #endif  /* DOC */
  182. #include "net/protosw.h"
  183. #include "sys/socket.h"
  184. #include "errno.h"
  185. #include "net/route.h"
  186. #include "netinet/in.h"
  187. #include "netinet/in_systm.h"
  188. #include "netinet/in_var.h"
  189. #include "netinet/ip.h"
  190. #include "netinet/if_ether.h"
  191. #include "net/if_subr.h"
  192. #include "semLib.h"
  193. #include "bootLib.h"
  194. #include "drv/netif/if_lnIsa.h" /* device description header */
  195. /***** LOCAL DEFINITIONS *****/
  196. /* descriptor size */
  197. #define RMD_SIZ  sizeof(ln_rmd)
  198. #define TMD_SIZ  sizeof(ln_tmd)
  199. /* Configuration items */
  200. #define LN_MIN_FIRST_DATA_CHAIN 96      /* min size of 1st buf in data-chain */
  201. #define LN_MAX_MDS              128     /* max number of [r|t]md's for LANCE */
  202. #define LN_BUFSIZ      (ETHERMTU + ENET_HDR_REAL_SIZ + 6)
  203. #define LN_RMD_RLEN     5       /* ring size as a power of 2 -- 32 RMD's */
  204. #define LN_TMD_TLEN     5       /* same for transmit ring    -- 32 TMD's */
  205. #define MAX_UNITS       1       /* maximum units supported */
  206. /*
  207.  * If LN_KICKSTART_TX is TRUE the transmitter is kick-started to force a
  208.  * read of the transmit descriptors, otherwise the internal polling (1.6msec)
  209.  * will initiate a read of the descriptors.  This should be FALSE is there
  210.  * is any chance of memory latency or chip accesses detaining the LANCE DMA,
  211.  * which results in a transmitter UFLO error.  This can be changed with the
  212.  * global lnKickStartTx below.
  213.  */
  214. #define LN_KICKSTART_TX TRUE
  215. /* Cache macros */
  216. #define LN_CACHE_INVALIDATE(address, len) 
  217.         CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))
  218. #define LN_CACHE_VIRT_TO_PHYS(address) 
  219.         CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
  220. #define LN_CACHE_PHYS_TO_VIRT(address) 
  221.         CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))
  222. /* Typedefs for external structures that are not typedef'd in their .h files */
  223. typedef struct mbuf MBUF;
  224. typedef struct arpcom IDR;                  /* Interface Data Record wrapper */
  225. typedef struct ifnet IFNET;                 /* real Interface Data Record */
  226. typedef struct sockaddr SOCK;
  227. /* The Ethernet header */
  228. typedef struct enet_hdr
  229.     {
  230.     char dst [6];
  231.     char src [6];
  232.     u_short type;
  233.     } ENET_HDR;
  234. #define ENET_HDR_SIZ        sizeof(ENET_HDR)
  235. #define ENET_HDR_REAL_SIZ   14
  236. /* The definition of the driver control structure */
  237. typedef struct drv_ctrl
  238.     {
  239.     IDR         idr;                /* Interface Data Record */
  240.     ln_ib       *ib;                 /* ptr to Initialization Block */
  241.     struct
  242.         {
  243.         int     r_po2;                  /* RMD ring size as a power of 2! */
  244.         int     r_size;                 /* RMD ring size (power of 2!) */
  245.         int     r_index;                /* index into RMD ring */
  246.         ln_rmd  *r_ring;                /* RMD ring */
  247.         char    *r_bufs;                /* receive buffers base */
  248.         } rmd_ring;
  249.     struct
  250.         {
  251.         int     t_po2;                  /* TMD ring size as a power of 2! */
  252.         int     t_size;                 /* TMD ring size (power of 2!) */
  253.         int     t_index;                /* index into TMD ring */
  254.         int     d_index;                /* index into TMD ring */
  255.         ln_tmd  *t_ring;                /* TMD ring */
  256.         char    *t_bufs;                /* transmit buffers base */
  257.         } tmd_ring;
  258.     BOOL        attached;               /* indicates unit is attached */
  259.     SEM_ID      TxSem;                  /* transmitter semaphore */
  260.     u_char      flags;                  /* misc control flags */
  261.     int         ivec;                   /* interrupt vector */
  262.     int         ilevel;                 /* interrupt level */
  263.     LN_DEVICE   *devAdrs;               /* device structure address */
  264.     char        *memBase;               /* LANCE memory pool base */
  265.     int         memWidth;               /* width of data port */
  266.     int         bufSize;                /* size of buffer in the LANCE ring */
  267.     CACHE_FUNCS cacheFuncs;             /* cache function pointers */
  268.     } DRV_CTRL;
  269. #define DRV_CTRL_SIZ    sizeof(DRV_CTRL)
  270. /* Definitions for the flags field */
  271. #define LS_PROMISCUOUS_FLAG     0x1
  272. #define LS_MEM_ALLOC_FLAG       0x2
  273. #define LS_PAD_USED_FLAG        0x4
  274. #define LS_RCV_HANDLING_FLAG    0x8
  275. #define LS_START_OUTPUT_FLAG    0x10
  276. /* Shorthand structure references */
  277. #define rpo2         rmd_ring.r_po2
  278. #define rsize        rmd_ring.r_size
  279. #define rindex       rmd_ring.r_index
  280. #define rring        rmd_ring.r_ring
  281. #define tpo2         tmd_ring.t_po2
  282. #define tsize        tmd_ring.t_size
  283. #define tindex       tmd_ring.t_index
  284. #define dindex       tmd_ring.d_index
  285. #define tring        tmd_ring.t_ring
  286. /***** GLOBALS *****/
  287. IMPORT STATUS sysIntDisablePIC  (int intLevel);
  288. IMPORT STATUS sysIntEnablePIC(int intLevel);
  289. IMPORT USHORT sysInWord (int address);
  290. IMPORT void sysOutWord (int address, USHORT data);
  291. IMPORT void sysOutByte (int address, UINT8 data);
  292. void panic ();
  293. void ether_attach ();
  294. BOOL arpresolve ();
  295. /***** LOCALS *****/
  296. static int lnTsize = LN_TMD_TLEN;    /* deflt xmit ring size as power of 2 */
  297. static int lnRsize = LN_RMD_RLEN;    /* deflt recv ring size as power of 2 */
  298. static BOOL lnKickStartTx = LN_KICKSTART_TX;
  299. #define LNISA_DEBUG
  300. /* The array of driver control structures */
  301. static DRV_CTRL  drvCtrl [MAX_UNITS];
  302. /* initial word offsets from LANCE base address to access these registers */
  303. static u_int CSROffset =  0x10;
  304. static u_int RAPOffset =  0x12;
  305. static u_int IDPOffset =  0x16;
  306. /* forward static functions */
  307. static void  lnReset (int unit);
  308. static void  lnInt (DRV_CTRL *pDrvCtrl);
  309. static void  lnHandleRecvInt (DRV_CTRL *pDrvCtrl);
  310. static STATUS  lnRecv (DRV_CTRL *pDrvCtrl, ln_rmd *rmd);
  311. static int  lnOutput (IDR *ifp, MBUF *m0, SOCK *dst);
  312. static int  lnIoctl (IDR *ifp, int cmd, caddr_t data);
  313. static int  lnChipReset (DRV_CTRL *pDrvCtrl);
  314. static ln_rmd * lnGetFullRMD (DRV_CTRL *pDrvCtrl);
  315. void  lnCsrWrite (DRV_CTRL * pDrvCtrl, int reg, USHORT value);
  316. USHORT  lnCsrRead (DRV_CTRL * pDrvCtrl, int reg);
  317. void  lnIdpWrite (DRV_CTRL * pDrvCtrl, int reg, USHORT value);
  318. USHORT  lnIdpRead (DRV_CTRL * pDrvCtrl, int reg);
  319. static void  lnRestart (int unit,int loc,int stat);
  320. static BOOL  convertDestAddr
  321.                 (
  322. IDR *pIDR,
  323. SOCK *pDestSktAddr,
  324. char *pDestEnetAddr,
  325. u_short *pPacketType,
  326. MBUF *pMbuf
  327. );
  328. UINT8 lnEnetAddr [6];
  329. #include "lnIsa_eeprom.c" /* EEPROM and PnP control functions for AMD961 */
  330. /*******************************************************************************
  331. *
  332. * lnIsaattach - publish the `lnIsa' network interface and initialize the driver and device
  333. *
  334. * This routine publishes the `lnIsa' interface by filling in a network 
  335. * interface record and adding this record to the system list.  This routine 
  336. * also initializes the driver and the device to the operational state.
  337. *
  338. * The <memAdrs> parameter can be used to specify the location of the
  339. * memory that will be shared between the driver and the device.  The value
  340. * NONE is used to indicate that the driver should obtain the memory.
  341. *
  342. * The <memSize> parameter is valid only if the <memAdrs> parameter is not
  343. * set to NONE, in which case <memSize> indicates the size of the
  344. * provided memory region.
  345. *
  346. * The <memWidth> parameter sets the memory pool's data port width (in bytes);
  347. * if it is NONE, any data width is used.
  348. *
  349. * BUGS
  350. * To zero out LANCE data structures, this routine uses bzero(), which
  351. * ignores the <memWidth> specification and uses any size data access to
  352. * write to memory.
  353. *
  354. * RETURNS: OK or ERROR.
  355. */
  356. STATUS lnIsaattach
  357. (
  358.     int unit, /* unit number */
  359.     char * devAdrs, /* LANCE I/O address */
  360.     int ivec, /* interrupt vector */
  361.     int ilevel, /* interrupt level */
  362.     char * memAdrs, /* address of memory pool (-1 = malloc it) */
  363.     ULONG memSize, /* used if memory pool is NOT malloc()'d */
  364.     int memWidth, /* byte-width of data (-1 = any width)     */
  365.     int mode, /* See CONFIG_LNISA in config.h */
  366.     int dmaChan /* DMA channel to use */
  367.     )
  368.     {
  369.     DRV_CTRL     *pDrvCtrl;
  370.     unsigned int sz;           /* temporary size holder */
  371.     char         *pTurkey;     /* start of the LANCE memory pool */
  372.     int i;
  373. #ifdef IP_ADDR_STORED_IN_EEPROM
  374.     char ipStr[BOOT_ADDR_LEN];
  375.     char *subNetMaskStr;
  376.     char scratchStr[BOOT_ADDR_LEN];
  377.     UINT32 ipAddr = 0;
  378.     BOOT_PARAMS bootParams;
  379. #endif /* IP_ADDR_STORED_IN_EEPROM */
  380.     /* Sanity check the unit number */
  381.     if (unit < 0 || unit >= MAX_UNITS)
  382.         return (ERROR);
  383.     /*
  384.      * The DMA channel must be one of 5,6 or 7 as it has 
  385.      * to be a 16 bit channel.
  386.      */
  387.     if((dmaChan < 5) || (dmaChan > 7))
  388.       return ERROR;
  389.     /* Ensure single invocation per system life */
  390.     pDrvCtrl = & drvCtrl [unit];
  391.     if (pDrvCtrl->attached)
  392.         return (OK);
  393.     /* 
  394.      * Fill pDrvCtrl->devAdrs out now as it is used by lnCsrXXXX and 
  395.      * lnIdpXXXX functions for register access.
  396.      */
  397.     pDrvCtrl->devAdrs    = (LN_DEVICE *)devAdrs; /* LANCE I/O address */
  398.     /* set DMA channel to cascade mode to enable device as ISA bus master */
  399.     sysOutByte (0xd6,(0xc0 | (dmaChan - 4))); 
  400.     sysOutByte (0xd4,(dmaChan - 4)); /* enable DMA channel */
  401.     /* 
  402.      * Examine ISACSR3 for a valid EEPROM. If the EEPROM is invalid bring the
  403.      * device out of PnP mode using the Software Relocatable key code. This 
  404.      * will allow the user to program the EEPROM with valid information using 
  405.      * the function lnIsa_eeprog().
  406.      */
  407.      if(lnIdpRead(pDrvCtrl,ISACSR3) != EE_VALID)
  408.      {
  409.        printf("nn!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!nn");
  410.        printf("Ethernet Device EEPROM invalidn");
  411.        printf("Use lnIsa_eeprog(pDrvCtrl,ENET_HI,ENET_MID,ENET_LO");
  412. #ifdef IP_ADDR_STORED_IN_EEPROM
  413.        printf(","IP ADDRESS (Dot Notation)")n");
  414. #else
  415.        printf("n");
  416. #endif
  417.        printf("to initialize EEPROM: pDrvCtrl = %pn",pDrvCtrl);
  418.        printf("nn!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!nn");
  419.        lnIsaPnPInitiation(); /* send AMD961 SW relocation key */
  420.        lnIsaPnPSetup(devAdrs,(UINT8)ilevel,(UINT8)INT_TYPE_LNISA,
  421.      (UINT8)dmaChan);
  422.        for(i = 0; i < 6; i++)
  423.  lnEnetAddr[i] = 0; /* invalidate enet addr */
  424.        return ERROR;
  425.      }
  426.      else
  427.      {
  428.        /* EEPROM is Valid, so read out the Ethernet Address */
  429.        lnCsrWrite(pDrvCtrl,0,4); /* make sure device is stopped */
  430.        WR_EE_REG(EE_EN); /* enable EEPROM access */
  431.        EE_TIMEOUT;
  432.        *(UINT16 *)(&lnEnetAddr[4]) = ntohs(lnIsa_eeread16(pDrvCtrl,2));
  433.        *(UINT16 *)(&lnEnetAddr[2]) = ntohs(lnIsa_eeread16(pDrvCtrl,1));
  434.        *(UINT16 *)(&lnEnetAddr[0]) = ntohs(lnIsa_eeread16(pDrvCtrl,0));
  435. #ifdef IP_ADDR_STORED_IN_EEPROM
  436.        ipAddr = lnIsa_eeread16(pDrvCtrl,EE_WORD_LEN_MIN+1);
  437.        ipAddr = ipAddr << 16;
  438.        ipAddr |= lnIsa_eeread16(pDrvCtrl,EE_WORD_LEN_MIN);
  439.        sprintf(ipStr,"%d.%d.%d.%d",(ipAddr&0x000000ff),
  440.        ((ipAddr&0x0000ff00)>>8),((ipAddr&0x00ff0000)>> 16),
  441.        ((ipAddr&0xff000000)>> 24));
  442.        if((ipAddr == 0x0) || (ipAddr == 0xffffffff))
  443.        {
  444.  printf("nnInvalid IP Address: %snn",ipStr);
  445.  return ERROR;
  446.        }
  447.        if((ipAddr != 0) && (ipAddr != 0xffffffff))
  448.        {
  449.  bootStringToStruct(BOOT_LINE_ADRS, &bootParams);
  450.  /* get current subnet mask*/
  451.  subNetMaskStr = strstr(&bootParams.ead[0],":"); 
  452.  if(subNetMaskStr != NULL)
  453.    sprintf(scratchStr,"%s%s",ipStr,subNetMaskStr);
  454.  else
  455.    sprintf(scratchStr,"%s",ipStr);
  456.  sprintf(&bootParams.ead[0],"%s",scratchStr);
  457.  bootStructToString(BOOT_LINE_ADRS, &bootParams); /* update bootline */
  458.        }
  459. #endif /* IP_ADDR_STORED_IN_EEPROM */
  460.        WR_EE_REG(0); /* Disable EEPROM access */
  461.      }
  462.      
  463. #ifdef LNISA_DEBUG
  464.     printf("ndevAdrs = %p, ivec = %d, ilevel = %dn",devAdrs,ivec,ilevel);
  465.     printf("memAdrs = %p, memSize = %x, memWidth = %dn",memAdrs, memSize,
  466.    memWidth);
  467.     printf("Ethernet Address: %02x:%02x:%02x:%02x:%02x:%02xn",lnEnetAddr[0],
  468.    lnEnetAddr[1],lnEnetAddr[2],lnEnetAddr[3],lnEnetAddr[4],
  469.    lnEnetAddr[5]);
  470.     printf("IP Address = %08x = %sn",ipAddr,ipStr);
  471. #endif
  472.     /* Publish the interface data record */
  473.     ether_attach    (
  474.                     & pDrvCtrl->idr.ac_if,
  475.                     unit,
  476.                     "lnIsa",
  477.                     (FUNCPTR) NULL,
  478.                     (FUNCPTR) lnIoctl,
  479.                     (FUNCPTR) lnOutput,
  480.                     (FUNCPTR) lnReset
  481.                     );
  482.     /* Create the transmit semaphore. */
  483.     pDrvCtrl->TxSem = semMCreate    (
  484.                                     SEM_Q_PRIORITY |
  485.                                     SEM_DELETE_SAFE |
  486.                                     SEM_INVERSION_SAFE
  487.                                     );
  488.     if (pDrvCtrl->TxSem == NULL)
  489.         {
  490.         printf ("lnIsa: error creating transmitter semaphoren");
  491.         return (ERROR);
  492.         }
  493.     { /***** Establish size of shared memory region we require *****/
  494.     if ((int) memAdrs != NONE)  /* specified memory pool */
  495.         {
  496.         /*
  497.          * With a specified memory pool we want to maximize
  498.          * lnRsize and lnTsize
  499.          */
  500.         sz = (memSize - (RMD_SIZ + TMD_SIZ + sizeof (ln_ib)))
  501.                / ((2 * LN_BUFSIZ) + RMD_SIZ + TMD_SIZ);
  502.         sz >>= 1;               /* adjust for roundoff */
  503.         for (lnRsize = 0; sz != 0; lnRsize++, sz >>= 1)
  504.             ;
  505.         lnTsize = lnRsize;      /* lnTsize = lnRsize for convenience */
  506.         }
  507.     /* limit ring sizes to reasonable values */
  508.     if (lnRsize < 2)
  509.         lnRsize = 2;            /* 4 buffers is reasonable min */
  510.     if (lnRsize > 7)
  511.         lnRsize = 7;            /* 128 buffers is max for chip */
  512.     /* limit ring sizes to reasonable values */
  513.     if (lnTsize < 2)
  514.         lnTsize = 2;            /* 4 buffers is reasonable min */
  515.     if (lnTsize > 7)
  516.         lnTsize = 7;            /* 128 buffers is max for chip */
  517.     /* Add it all up */
  518.     sz = (sizeof (ln_ib)) +
  519.          ( ((1 << lnRsize) + 1) * RMD_SIZ ) +
  520.          (LN_BUFSIZ << lnRsize) +
  521.          ( ((1 << lnTsize) + 1) * TMD_SIZ ) +
  522.          (LN_BUFSIZ << lnTsize) +
  523.          6;                        /* allow for alignment adjustment */
  524.     }
  525.     { /***** Establish a region of shared memory *****/
  526.     /* OK. We now know how much shared memory we need.  If the caller
  527.      * provides a specific memory region, we check to see if the provided
  528.      * region is large enough for our needs.  If the caller did not
  529.      * provide a specific region, then we attempt to allocate the memory
  530.      * from the system, using the cache aware allocation system call.
  531.      */
  532.     switch ( (int) memAdrs )
  533.         {
  534.         default :       /* caller provided memory */
  535.             if ( memSize < sz )     /* not enough space */
  536.                 {
  537.                 printf ( "lnIsa: not enough memory providedn" );
  538.                 return ( ERROR );
  539.                 }
  540.             pTurkey = memAdrs;             /* set the beginning of pool */
  541.             /* assume pool is cache coherent, copy null structure */
  542.             pDrvCtrl->cacheFuncs = cacheNullFuncs;
  543.             break;
  544.         case NONE :     /* get our own memory */
  545.             /* Because the structures that are shared between the device
  546.              * and the driver may share cache lines, the possibility exists
  547.              * that the driver could flush a cache line for a structure and
  548.              * wipe out an asynchronous change by the device to a neighboring
  549.              * structure. Therefore, this driver cannot operate with memory
  550.              * that is not write coherent.  We check for the availability of
  551.              * such memory here, and abort if the system did not give us what
  552.              * we need.
  553.              */
  554.             if (!CACHE_DMA_IS_WRITE_COHERENT ())
  555.                 {
  556.                 printf ( "lnIsa: device requires cache coherent memoryn" );
  557.                 return (ERROR);
  558.                 }
  559.             pTurkey = (char *) cacheDmaMalloc ( sz );
  560.             if ((int)pTurkey == NULL)
  561.                 {
  562.                 printf ( "lnIsa: system memory unavailablen" );
  563.                 return (ERROR);
  564.                 }
  565.             /* copy the DMA structure */
  566.             pDrvCtrl->cacheFuncs = cacheDmaFuncs;
  567.             break;
  568.         }
  569.     }
  570.     /*                        Turkey Carving
  571.      *                        --------------
  572.      *
  573.      *                          LOW MEMORY
  574.      *
  575.      *             |-------------------------------------|
  576.      *             |       The initialization block      |
  577.      *             |         (sizeof (ln_ib))            |
  578.      *             |-------------------------------------|
  579.      *             |         The Rx descriptors          |
  580.      *             | (1 << lnRsize) * sizeof (ln_rmd)|
  581.      *             |-------------------------------------|
  582.      *             |          The receive buffers        |
  583.      *             |       (LN_BUFSIZ << lnRsize)        |
  584.      *             |-------------------------------------|
  585.      *             |         The Tx descriptors          |
  586.      *             | (1 << lnTsize) * sizeof (ln_tmd)|
  587.      *             |-------------------------------------|
  588.      *             |           The transmit buffers      |
  589.      *             |       (LN_BUFSIZ << lnTsize)        |
  590.      *             |-------------------------------------|
  591.      */
  592.     /* Save some things */
  593.     pDrvCtrl->memBase  = (char *)((ULONG)pTurkey & 0xffff0000);
  594.     pDrvCtrl->memWidth = memWidth;
  595.     pDrvCtrl->bufSize = LN_BUFSIZ;
  596.     if ((int) memAdrs == NONE)
  597.         pDrvCtrl->flags |= LS_MEM_ALLOC_FLAG;
  598.     { /***** Carve up the turkey *****/
  599.     /* First let's clean the whole turkey */
  600.     bzero ( (char *) pTurkey, (int) sz );
  601.     /* carve out initialization block */
  602.     pDrvCtrl->ib = (ln_ib *)pTurkey;
  603.     sz = sizeof (ln_ib);                /* size of initialization block */
  604.     /* carve out receive message descriptor (RMD) ring structure */
  605.     pDrvCtrl->rpo2 = lnRsize;              /* remember for lnConfig */
  606.     pDrvCtrl->rsize = (1 << lnRsize);      /* receive ring size */
  607.     /* make it 16 byte aligned */
  608.     pDrvCtrl->rring = (ln_rmd *) (((int)pDrvCtrl->ib + sz + 0x0f) & ~0x0f);
  609.     sz = (1 << lnRsize) * RMD_SIZ;
  610.     pDrvCtrl->rmd_ring.r_bufs = (char *)((int)pDrvCtrl->rring + sz);
  611.     sz = (LN_BUFSIZ << lnRsize);   /* room for all the receive buffers */
  612.     /* carve out transmit message descriptor (TMD) ring structure */
  613.     pDrvCtrl->tpo2 = lnTsize;              /* remember for lnConfig */
  614.     pDrvCtrl->tsize = (1 << lnTsize);      /* transmit ring size */
  615.     pDrvCtrl->tring = (ln_tmd *) (((int)pDrvCtrl->rmd_ring.r_bufs + sz + 0x0f)
  616.   & ~0x0f);
  617.     sz = (1 << lnTsize) * TMD_SIZ;
  618.     /* carve out transmit buffer space */
  619.     pDrvCtrl->tmd_ring.t_bufs = (char *)((int)pDrvCtrl->tring + sz);
  620.     }
  621.     /* Save some values */
  622.     pDrvCtrl->ivec       = ivec;                 /* interrupt vector */
  623.     pDrvCtrl->ilevel     = ilevel;               /* interrupt level */
  624.     pDrvCtrl->devAdrs    = (LN_DEVICE *)devAdrs; /* LANCE I/O address */
  625.     /* Obtain our Ethernet address and save it */
  626.     bcopy ((char *) lnEnetAddr, (char *)pDrvCtrl->idr.ac_enaddr, 6);
  627.     { /***** Device Initialization *****/
  628.     if (lnChipReset (pDrvCtrl) == ERROR) /* reset lance device */
  629.      {
  630. logMsg ("lnIsa: cannot Reset device:n",0,0,0,0,0,0);
  631. return (ERROR);
  632. }
  633.     if (intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC(ivec),lnInt,(int)pDrvCtrl)
  634.         == ERROR)
  635.         return (ERROR);
  636.     { /* Initialize all shared memory structures */
  637.     ln_rmd  *rmd;
  638.     ln_tmd  *tmd;
  639.     char    *buf;
  640.     ln_ib   *ib;
  641.     ULONG    pTemp;
  642.     int     loopy;
  643.     /* Set up the Rx descriptors */
  644.     rmd = pDrvCtrl->rring;                      /* receive ring */
  645.     buf = pDrvCtrl->rmd_ring.r_bufs;
  646.     for (loopy = 0; loopy < pDrvCtrl->rsize; loopy++)
  647.     {
  648.       pTemp = (ULONG)LN_CACHE_VIRT_TO_PHYS(buf);/* convert to physical addr */
  649.       rmd->rbuf_adr = (USHORT)(pTemp & 0x0000ffff); /* bits 15:00 buf addr */
  650.       rmd->rbuf_rmd1 = (USHORT)((pTemp & 0x00ff0000) >> 16); /* bits 7:0 */
  651.       /* neg of buffer byte count */
  652.       rmd->rbuf_bcnt = ((RMD2_BCNT_MSK & -(pDrvCtrl->bufSize)) | RMD2_MBO);
  653.       rmd->rbuf_mcnt = 0; /* no message byte count yet */
  654.       rmd->rbuf_rmd1 |= RMD1_OWN; /* buffer now owned by LANCE */
  655.       rmd++; /* step to next descriptor */
  656.       buf += (pDrvCtrl->bufSize); /* step to the next buffer */
  657.     }
  658.     pDrvCtrl->rindex = 0;
  659.     /* Setup the Tx descriptors */
  660.     tmd = pDrvCtrl->tring;                 /* transmit ring */
  661.     buf = pDrvCtrl->tmd_ring.t_bufs;
  662.     for (loopy = 0; loopy < pDrvCtrl->tsize; loopy++)
  663.     {
  664.       pTemp = (ULONG)LN_CACHE_VIRT_TO_PHYS(buf); /* convert to physical addr */
  665.       tmd->tbuf_adr = (USHORT) (pTemp & 0x0000ffff); /* bits 15:00 of addr */
  666.       tmd->tbuf_tmd1 = (USHORT)((pTemp & 0x00ff0000) >> 16); /* bits 7:0 */
  667.       tmd->tbuf_tmd2 = 0; /* no length of Tx Buf yet */
  668.       tmd->tbuf_tmd3 = 0; /* clear status bits */
  669.       tmd->tbuf_tmd1 |= TMD1_ENP; /* buffer is end of packet */
  670.       tmd->tbuf_tmd1 |= TMD1_STP; /* buffer is start of packet */
  671.       tmd++; /* step to next descriptor */
  672.       buf += (pDrvCtrl->bufSize); /* step to next buffer */
  673.     }
  674.     pDrvCtrl->tindex = pDrvCtrl->dindex = 0;
  675.     /* Setup the initialization block */
  676.     lnIdpWrite(pDrvCtrl,2, (0x100 | (mode & 0x3))); /* set up mode */
  677.     ib = pDrvCtrl->ib;
  678.     ib->lnIBMode = 0;        /* chip will be in normal receive mode */
  679.     bcopy ((char *)&pDrvCtrl->idr.ac_enaddr[0],&ib->lnIBPadr[0], 6);
  680.     pTemp =(ULONG)LN_CACHE_VIRT_TO_PHYS(pDrvCtrl->rring);/* point to Rx ring */
  681.     ib->lnIBRdraLow = (USHORT)(pTemp & 0x0000ffff);
  682.     ib->lnIBRdraHigh = (UCHAR)((pTemp & 0x00ff0000) >> 16);
  683.     ib->lnRLEN =  pDrvCtrl->rpo2<<5;
  684.     pTemp =(ULONG)LN_CACHE_VIRT_TO_PHYS(pDrvCtrl->tring);/* point to Tx ring */
  685.     ib->lnIBTdraLow = (USHORT)(pTemp & 0x0000ffff);
  686.     ib->lnIBTdraHigh = (UCHAR)((pTemp & 0x00ff0000) >> 16);
  687.     ib->lnTLEN = pDrvCtrl->tpo2<<5;
  688.     /* Flush the write pipe */
  689.     CACHE_PIPE_FLUSH ();
  690.     }
  691.     { /* Start the device */
  692.     USHORT stat = 0;
  693.     ULONG pTemp;
  694.     int timeoutCount = 0;
  695.     lnCsrWrite (pDrvCtrl, 0, CSR0_STOP); /* set the stop bit */
  696.     /* Point the device to the initialization block */
  697.     pTemp = (ULONG)LN_CACHE_VIRT_TO_PHYS ( pDrvCtrl->ib );
  698.     lnCsrWrite (pDrvCtrl, 2, (USHORT)((pTemp >> 16) & 0x000000ff));
  699.     lnCsrWrite (pDrvCtrl, 1, (USHORT)(pTemp & 0x0000ffff));
  700.     lnCsrWrite (pDrvCtrl, 0, CSR0_INIT);            /* init chip (read IB) */
  701.     while (((stat = lnCsrRead (pDrvCtrl, 0)) & (CSR0_IDON | CSR0_ERR)) == 0)
  702.         {
  703.         if (timeoutCount++ > 5) 
  704.   break;
  705.         taskDelay(sysClkRateGet());
  706.         }
  707.     if ((stat & CSR0_ERR) == CSR0_ERR)
  708. {
  709. if ((stat & CSR0_MERR)  == CSR0_MERR)
  710.     {
  711.     printf ("Lance Memory error during initialization:t0x%xn",
  712.     stat);
  713.     }
  714. else
  715.     {
  716.     printf ("Lance Error during initialization:t0x%xn",
  717.     stat);
  718.     }
  719. }
  720.     /* log chip initialization failure */
  721.     if ( (stat & CSR0_ERR) || (timeoutCount >= 0x10000) )
  722.         {
  723.         printf ("lnIsa%d: Device initialization failedn",
  724.                     pDrvCtrl->idr.ac_if.if_unit);
  725.         return (ERROR);
  726.         }
  727.     /* Device is initialized.  Start transmitter and receiver.  The device
  728.      * RAP register is left selecting CSR 0.
  729.      */
  730.     lnCsrWrite(pDrvCtrl, 0, CSR0_IDON | CSR0_IENA | CSR0_STRT);
  731.     }
  732.     sysIntEnablePIC (ilevel);                   /* enable LANCE interrupts */
  733.     pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);
  734.     } /* Block end; device initialization */
  735.     /* Set our flag */
  736.     pDrvCtrl->attached = TRUE;
  737.     return (OK);
  738. }
  739. /*******************************************************************************
  740. *
  741. * lnReset - reset the interface
  742. *
  743. * Mark interface as inactive & reset the chip
  744. */
  745. static void lnReset
  746.     (
  747.     int unit
  748.     )
  749.     {
  750.     DRV_CTRL *pDrvCtrl = & drvCtrl [unit];
  751.     pDrvCtrl->idr.ac_if.if_flags = 0;
  752.     lnChipReset (pDrvCtrl);                           /* reset LANCE */
  753.     }
  754. /*******************************************************************************
  755. *
  756. * lnInt - handle controller interrupt
  757. *
  758. * This routine is called at interrupt level in response to an interrupt from
  759. * the controller.
  760. */
  761. static void lnInt
  762.     (
  763.     DRV_CTRL  *pDrvCtrl
  764.     )
  765.     {
  766.     ln_tmd         *tmd;
  767.     int            *pDindex;
  768.     int            *pTindex;
  769.     int            *pTsize;
  770.     ln_tmd         *pTring;
  771.     USHORT    stat;
  772.     /* Read the device status register */
  773.     
  774.     stat = lnCsrRead (pDrvCtrl, 0);
  775.     /* If false interrupt, return. */
  776.     if ( ! (stat & CSR0_INTR) )
  777.         return;
  778.     /*
  779.      * enable interrupts, clear receive and/or transmit interrupts, and clear
  780.      * any errors that may be set.
  781.      */
  782.     lnCsrWrite (pDrvCtrl, 0, ((stat &
  783.             (CSR0_BABL|CSR0_CERR|CSR0_MISS|CSR0_MERR|
  784.              CSR0_RINT|CSR0_TINT|CSR0_IDON)) | CSR0_IENA));
  785.     /* Check for errors */
  786.     if (stat & (CSR0_BABL | CSR0_MISS | CSR0_MERR))
  787.         {
  788.         ++pDrvCtrl->idr.ac_if.if_ierrors;
  789.         /* restart chip on fatal error */
  790.         if (stat & CSR0_MERR)        /* memory error */
  791.             {
  792.             pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);
  793.             (void) netJobAdd (
  794.                              (FUNCPTR)lnRestart,
  795.                              pDrvCtrl->idr.ac_if.if_unit,
  796.                              1,(int)stat,0,0
  797.                              );
  798.             }
  799.         }
  800.     /* Have netTask handle any input packets */
  801.     if ((stat & CSR0_RINT) && (stat & CSR0_RXON))
  802.         {
  803.         if ( ! (pDrvCtrl->flags & LS_RCV_HANDLING_FLAG) )
  804.             {
  805.             pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;
  806.             (void) netJobAdd (
  807.                              (FUNCPTR)lnHandleRecvInt,
  808.                              (int)pDrvCtrl,
  809.                              0,0,0,0
  810.                              );
  811.             }
  812.         }
  813.     /*
  814.      * Did LANCE update any of the TMD's?
  815.      * If not then don't bother continuing with transmitter stuff
  816.      */
  817.     if (!(stat & CSR0_TINT))
  818.         return;
  819.     pDindex = &pDrvCtrl->dindex;
  820.     pTindex = &pDrvCtrl->tindex;
  821.     pTsize  = &pDrvCtrl->tsize;
  822.     pTring  = pDrvCtrl->tring;
  823.     while (*pDindex != *pTindex)
  824.         {
  825.         /* disposal has not caught up */
  826.         tmd = pTring + *pDindex;
  827.         /* if the buffer is still owned by LANCE, don't touch it */
  828.         LN_CACHE_INVALIDATE (tmd, TMD_SIZ);
  829.         if (tmd->tbuf_tmd1 & TMD1_OWN)
  830.             break;
  831.         /*
  832.          * tbuf_err (TMD1.ERR) is an "OR" of LCOL, LCAR, UFLO or RTRY.
  833.          * Note that BUFF is not indicated in TMD1.ERR.
  834.          * We should therefore check both tbuf_err and tbuf_buff
  835.          * here for error conditions.
  836.          */
  837.         if ((tmd->tbuf_tmd1 & TMD1_ERR) || 
  838.     (tmd->tbuf_tmd3 & TMD3_BUFF))
  839.             {
  840.             pDrvCtrl->idr.ac_if.if_oerrors++;     /* output error */
  841.             pDrvCtrl->idr.ac_if.if_opackets--;
  842.             /* If error was due to excess collisions, bump the collision
  843.              * counter.  The LANCE does not keep an individual counter of
  844.              * collisions, so in this driver, the collision statistic is not
  845.              * an accurate count of total collisions.
  846.              */
  847.             if (tmd->tbuf_tmd3 & TMD3_RTRY)
  848.                 pDrvCtrl->idr.ac_if.if_collisions++;
  849.             /* check for no carrier */
  850.             if (tmd->tbuf_tmd3 & TMD3_LCAR)
  851.                 logMsg ("ln%d: no carriern",
  852.                     pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0,0);
  853.             /* Restart chip on fatal errors.
  854.              * The following code handles the situation where the transmitter
  855.              * shuts down due to an underflow error.  This is a situation that
  856.              * will occur if the DMA cannot keep up with the transmitter.
  857.              * It will occur if the LANCE is being held off from DMA access
  858.              * for too long or due to significant memory latency.  DRAM
  859.              * refresh or slow memory could influence this.  Many
  860.              * implementation use a dedicated LANCE buffer.  This can be
  861.              * static RAM to eliminate refresh conflicts; or dual-port RAM
  862.              * so that the LANCE can have free run of this memory during its
  863.              * DMA transfers.
  864.              */
  865.             if ((tmd->tbuf_tmd3 & TMD3_BUFF) || 
  866. (tmd->tbuf_tmd3 & TMD3_UFLO))
  867.                 {
  868.                 pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);
  869.                 (void) netJobAdd (
  870.                                  (FUNCPTR)lnRestart,
  871.                                  pDrvCtrl->idr.ac_if.if_unit,
  872.                                  2,(int)(tmd->tbuf_tmd3),0,0
  873.                                  );
  874.                 return;
  875.                 }
  876.             }
  877.         tmd->tbuf_tmd1 &= 0x00ff;   /* clear status/err bits, keep hadr bits */
  878.         tmd->tbuf_tmd3 = 0; /* clear all error & stat stuff */
  879.         /* now bump the tmd disposal index pointer around the ring */
  880.         *pDindex = (*pDindex + 1) & (*pTsize - 1);
  881.         }
  882.     /* Flush the write pipe */
  883.     CACHE_PIPE_FLUSH ();
  884.     }
  885. /*******************************************************************************
  886. *
  887. * lnHandleRecvInt - task level interrupt service for input packets
  888. *
  889. * This routine is called at task level indirectly by the interrupt
  890. * service routine to do any message received processing.
  891. */
  892. static void lnHandleRecvInt
  893.     (
  894.     DRV_CTRL *pDrvCtrl
  895.     )
  896.     {
  897.     ln_rmd *rmd;
  898.     do
  899.         {
  900.         pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;
  901.         while ((rmd = lnGetFullRMD (pDrvCtrl)) != NULL)
  902.             lnRecv (pDrvCtrl, rmd);
  903.         /*
  904.          * There is a RACE right here.  The ISR could add a receive packet
  905.          * and check the boolean below, and decide to exit.  Thus the
  906.          * packet could be dropped if we don't double check before we
  907.          * return.
  908.          */
  909.         pDrvCtrl->flags &= ~LS_RCV_HANDLING_FLAG;
  910.         }
  911.     while (lnGetFullRMD (pDrvCtrl) != NULL);
  912.     /* this double check solves the RACE */
  913.     }
  914. /*******************************************************************************
  915. *
  916. * lnGetFullRMD - get next received message RMD
  917. *
  918. * Returns ptr to next Rx desc to process, or NULL if none ready.
  919. */
  920. static ln_rmd *lnGetFullRMD
  921.     (
  922.     DRV_CTRL  *pDrvCtrl
  923.     )
  924.     {
  925.     ln_rmd   *rmd;
  926.     /* Refuse to do anything if flags are down */
  927.     if  (
  928.         (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING) ) !=
  929.         (IFF_UP | IFF_RUNNING)
  930.         )
  931.         return ((ln_rmd *) NULL);
  932.     rmd = pDrvCtrl->rring + pDrvCtrl->rindex;       /* form ptr to Rx desc */
  933.     LN_CACHE_INVALIDATE (rmd, RMD_SIZ);
  934.     if ((rmd->rbuf_rmd1 & RMD1_OWN) == 0)
  935.         return (rmd);
  936.     else
  937.         return ((ln_rmd *) NULL);
  938.     }
  939. /*******************************************************************************
  940. *
  941. * lnRecv - process the next incoming packet
  942. *
  943. */
  944. static STATUS lnRecv
  945.     (
  946.     DRV_CTRL *pDrvCtrl,
  947.     ln_rmd   *rmd
  948.     )
  949.     {
  950.     ENET_HDR    *pEnetHdr;
  951.     MBUF        *pMbuf;
  952.     u_char      *pData;
  953.     int         len;
  954.     u_short     ether_type;
  955.     BOOL        hookAte;
  956.     /* Packet must be checked for errors. */
  957.     if  (
  958.         /* If error flag */
  959.         (rmd->rbuf_rmd1 & (RMD1_ERR | RMD1_FRAM)) ||
  960.         /* OR if packet is not completely in one buffer */
  961.         (
  962.         (rmd->rbuf_rmd1 & (RMD1_STP | RMD1_ENP) ) !=
  963.         (RMD1_STP | RMD1_ENP)
  964.         )
  965.         )
  966.         {
  967.         ++pDrvCtrl->idr.ac_if.if_ierrors;       /* bump error stat */
  968.         goto cleanRXD;                          /* skip to clean up */
  969.         }
  970.     ++pDrvCtrl->idr.ac_if.if_ipackets; /* bump statistic */
  971.     len = rmd->rbuf_mcnt & RMD3_MCNT_MSK; /* get packet length */
  972.     /* Get pointer to packet */
  973.     pEnetHdr = (ENET_HDR *)
  974.                 (pDrvCtrl->rmd_ring.r_bufs + (pDrvCtrl->rindex * LN_BUFSIZ));
  975.     LN_CACHE_INVALIDATE (pEnetHdr, len);   /* make the packet data coherent */
  976.     /* call input hook if any */
  977.     hookAte = FALSE;
  978.     if  (etherInputHookRtn != NULL)
  979.         {
  980.         if  (
  981.             (* etherInputHookRtn) (&pDrvCtrl->idr.ac_if, (char *)pEnetHdr, len)
  982.             )
  983.             hookAte = TRUE;
  984.         }
  985.     /* Normal path; send packet upstairs */
  986.     if (hookAte == FALSE)
  987.         {
  988.         /* Adjust length to size of data only */
  989.         len -= ENET_HDR_REAL_SIZ;
  990.         /* Get pointer to packet data */
  991.         pData = ((u_char *) pEnetHdr) + ENET_HDR_REAL_SIZ;
  992.         ether_type = ntohs ( pEnetHdr->type );
  993.         /* Copy packet data into MBUFs, using the specified width */
  994.         pMbuf = bcopy_to_mbufs (pData, len, 0, (IFNET *) & pDrvCtrl->idr.ac_if,
  995.                             pDrvCtrl->memWidth);
  996.         if (pMbuf != NULL)
  997.             do_protocol_with_type (ether_type, pMbuf, & pDrvCtrl->idr, len);
  998.   
  999.         }
  1000.     /* Done with descriptor, clean up and give it to the device. */
  1001.     cleanRXD:
  1002.     /* clear status bits */
  1003.     rmd->rbuf_rmd1 &= 0x00ff; /* clear status/err bits, keep address */
  1004.     rmd->rbuf_mcnt = 0; /* reset count */
  1005.     rmd->rbuf_rmd1 |= RMD1_OWN; /* give device ownership */
  1006.     /* Flush the write pipe */
  1007.     CACHE_PIPE_FLUSH ();
  1008.     /* Advance our management index */
  1009.     pDrvCtrl->rindex = (pDrvCtrl->rindex + 1) & (pDrvCtrl->rsize - 1);
  1010.     return (OK);
  1011.     }
  1012. /*******************************************************************************
  1013. *
  1014. * lnOutput - the driver output routine
  1015. *
  1016. */
  1017. static int lnOutput
  1018.     (
  1019.     IDR  *pIDR,
  1020.     MBUF *pMbuf,
  1021.     SOCK *pDest
  1022.     )
  1023.     {
  1024.     char destEnetAddr [6];                  /* space for enet addr */
  1025.     u_short packetType;                     /* type field for the packet */
  1026.     DRV_CTRL    *pDrvCtrl;
  1027.     ln_tmd      *tmd;
  1028.     char        *buf;
  1029.     int         len;
  1030.     int         oldLevel;
  1031.     BOOL        hookAte;
  1032.     /* Check ifnet flags. Return error if incorrect. */
  1033.     if  (
  1034.         (pIDR->ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=
  1035.         (IFF_UP | IFF_RUNNING)
  1036.         )
  1037.         return (ENETDOWN);
  1038.     /* Attempt to convert socket addr into enet addr and packet type.
  1039.      * Note that if ARP resolution of the address is required, the ARP
  1040.      * module will call our routine again to transmit the ARP request
  1041.      * packet.  This means we may actually call ourselves recursively!
  1042.      */
  1043.     if (convertDestAddr (pIDR,pDest, destEnetAddr, &packetType, pMbuf) == 
  1044. FALSE)
  1045.       return (OK);    /* I KNOW returning OK is stupid, but it is correct */
  1046.     /* Get driver control pointer */
  1047.     pDrvCtrl = & drvCtrl [pIDR->ac_if.if_unit];
  1048.     /* Obtain exclusive access to transmitter.  This is necessary because
  1049.      * certain events can cause netTask to run a job that attempts to transmit
  1050.      * a packet.  We can only allow one task here at a time.
  1051.      */
  1052.     semTake (pDrvCtrl->TxSem, WAIT_FOREVER);
  1053.     pDrvCtrl->flags |= LS_START_OUTPUT_FLAG;
  1054.     /* See if next TXD is available */
  1055.     tmd = pDrvCtrl->tring + pDrvCtrl->tindex;
  1056.     LN_CACHE_INVALIDATE (tmd, TMD_SIZ);
  1057.     if  (((tmd->tbuf_tmd1 & TMD1_OWN) != 0) ||
  1058.         (((pDrvCtrl->tindex + 1) & (pDrvCtrl->tsize - 1)) == pDrvCtrl->dindex))
  1059.         {
  1060.         m_freem (pMbuf);            /* Discard data */
  1061.         goto outputDone;
  1062.         }
  1063.     /* Get pointer to transmit buffer */
  1064.     buf = (char *)
  1065.         (pDrvCtrl->tmd_ring.t_bufs + (pDrvCtrl->tindex * LN_BUFSIZ));
  1066.     /* Fill in the Ethernet header */
  1067.     bcopy (destEnetAddr, buf, 6);
  1068.     bcopy ( (char *) pIDR->ac_enaddr, (buf + 6), 6);
  1069.     /* added htons translation joes 12/9/96 */
  1070.     ((ENET_HDR *)buf)->type = htons(packetType);
  1071.     /* Copy packet from MBUFs to our transmit buffer.  MBUFs are
  1072.      * transparently freed.
  1073.      */
  1074.     bcopy_from_mbufs    (
  1075.                         (buf + ENET_HDR_REAL_SIZ),
  1076.                         pMbuf,
  1077.                         len,                            /* stuffed by macro */
  1078.                         pDrvCtrl->memWidth
  1079.                         );
  1080.     /* Ensure we send a legal size frame. */
  1081.     len += ENET_HDR_REAL_SIZ;
  1082.     len = max (ETHERSMALL, len);
  1083.     /* call output hook if any */
  1084.     hookAte = FALSE;
  1085.     if  (etherOutputHookRtn != NULL)
  1086.       {
  1087.         if  (
  1088.             (* etherOutputHookRtn)(&pDrvCtrl->idr.ac_if, buf, len)
  1089.             )
  1090.             hookAte = TRUE;
  1091.       }
  1092.     /* place a transmit request */
  1093.     if (hookAte == FALSE)
  1094.       {
  1095. oldLevel = intLock ();          /* disable ints during update */
  1096. tmd->tbuf_tmd3 = 0;                     /* clear buffer error status */
  1097. /* negative message byte count */
  1098. tmd->tbuf_tmd2 = (TMD2_BCNT_MSK & -len);
  1099. tmd->tbuf_tmd2 |= TMD2_MBO;
  1100. tmd->tbuf_tmd1 |= (TMD1_ENP|TMD1_STP); /* start and end of packet */
  1101. /*tmd->tbuf_tmd1 |= TMD1_STP;  buffer is start of packet */
  1102. tmd->tbuf_tmd1 &= ~(TMD1_DEF|TMD1_MORE|TMD1_ERR);/* clear status bit */
  1103. /* tmd->tbuf_tmd1 &= ~TMD1_MORE;
  1104. tmd->tbuf_tmd1 &= ~TMD1_ERR;*/
  1105. tmd->tbuf_tmd1 |= TMD1_OWN;
  1106. /* Flush the write pipe */
  1107. CACHE_PIPE_FLUSH ();
  1108. intUnlock (oldLevel);   /* now lnInt won't get confused */
  1109. /* Advance our management index */
  1110. pDrvCtrl->tindex = (pDrvCtrl->tindex + 1) & (pDrvCtrl->tsize - 1);
  1111. /* kick start the transmitter, if selected */
  1112. if (lnKickStartTx)
  1113.   lnCsrWrite (pDrvCtrl, 0, (CSR0_IENA | CSR0_TDMD));
  1114. pDrvCtrl->flags &= ~LS_START_OUTPUT_FLAG;
  1115. /* Bump the statistic counter. */
  1116. pIDR->ac_if.if_opackets++;
  1117.       }
  1118.     outputDone:
  1119.     /* Release exclusive access. */
  1120.     semGive (pDrvCtrl->TxSem);
  1121.     return (OK);
  1122.     }
  1123. /*******************************************************************************
  1124. *
  1125. * lnIoctl - the driver I/O control routine
  1126. *
  1127. * Process an ioctl request.
  1128. */
  1129. static int lnIoctl
  1130.     (
  1131.     IDR  *ifp,
  1132.     int            cmd,
  1133.     caddr_t        data
  1134.     )
  1135.     {
  1136.     int error = 0;
  1137.     switch (cmd)
  1138.         {
  1139.         case SIOCSIFADDR:
  1140.             ifp->ac_ipaddr = IA_SIN (data)->sin_addr;
  1141.             break;
  1142.         case SIOCSIFFLAGS:
  1143.             /* No further work to be done */
  1144.             break;
  1145.         default:
  1146.             error = EINVAL;
  1147.         }
  1148.     return (error);
  1149.     }
  1150. /*******************************************************************************
  1151. *
  1152. * lnChipReset - hardware reset of chip (stop it)
  1153. */
  1154. static int lnChipReset
  1155.     (
  1156.     DRV_CTRL  *pDrvCtrl
  1157.     )
  1158.     {
  1159.     lnCsrWrite (pDrvCtrl, CSR(0), CSR0_STOP);
  1160.     return (OK);
  1161.     }
  1162. /*******************************************************************************
  1163. *
  1164. * lnCsrWrite - select and write a CSR register
  1165. *
  1166. */
  1167. void lnCsrWrite
  1168.     (
  1169.     DRV_CTRL *  pDrvCtrl, /* driver control */
  1170.     int  reg, /* register to select */
  1171.     USHORT  value /* value to write */
  1172.     )
  1173.     {
  1174.     int dv = (int)pDrvCtrl->devAdrs;
  1175.     /* select CSR */
  1176.     sysOutWord(dv+RAPOffset,reg);;
  1177.     /* write val to CSR */
  1178.     sysOutWord(dv+CSROffset,value);;
  1179.     }
  1180. /*******************************************************************************
  1181. *
  1182. * lnCsrRead - select and read a CSR register
  1183. *
  1184. */
  1185. USHORT lnCsrRead
  1186.     (
  1187.     DRV_CTRL * pDrvCtrl, /* driver control */
  1188.     int reg /* register to select */
  1189.     )
  1190.     {
  1191.     int dv = (int)pDrvCtrl->devAdrs;
  1192.     /* select CSR */
  1193.     sysOutWord(dv+RAPOffset,reg);;
  1194.     /* get contents of CSR */
  1195.     return (sysInWord(dv+CSROffset));
  1196.     }
  1197. /*******************************************************************************
  1198. *
  1199. * lnIdpWrite - select and write a IDP register
  1200. *
  1201. */
  1202. void lnIdpWrite
  1203.     (
  1204.     DRV_CTRL *  pDrvCtrl, /* driver control */
  1205.     int  reg, /* register to select */
  1206.     USHORT  value /* value to write */
  1207.     )
  1208.     {
  1209.     int dv = (int)pDrvCtrl->devAdrs;
  1210.     /* select IDP */
  1211.     sysOutWord(dv+RAPOffset,reg);;
  1212.     /* write val to IDP */
  1213.     sysOutWord(dv+IDPOffset,value);;
  1214.     }
  1215. /*******************************************************************************
  1216. *
  1217. * lnIdpRead - select and read a Idp register
  1218. *
  1219. */
  1220. USHORT lnIdpRead
  1221.     (
  1222.     DRV_CTRL * pDrvCtrl, /* driver control */
  1223.     int reg /* register to select */
  1224.     )
  1225.     {
  1226.     int dv = (int)pDrvCtrl->devAdrs;
  1227.     /* select IDP register */
  1228.     sysOutWord(dv+RAPOffset,reg);;
  1229.     /* get contents of IDP register */
  1230.     return (sysInWord(dv+IDPOffset));
  1231.     }
  1232. /*******************************************************************************
  1233. *
  1234. * lnRestart - restart the device after a fatal error
  1235. *
  1236. * This routine takes care of all the messy details of a restart.  The device
  1237. * is reset and re-initialized.  The driver state is re-synchronized.
  1238. */
  1239. static void lnRestart
  1240.     (
  1241.     int unit,
  1242.     int loc,
  1243.     int stat
  1244.     )
  1245.     {
  1246.     printf("ln: RESTART called, loc = %d, stat = %xn",loc,stat);
  1247.     taskSuspend (0);
  1248.     }
  1249. #include "sys/socket.h"
  1250. /*******************************************************************************
  1251. *
  1252. * convertDestAddr - converts socket addr into enet addr and packet type
  1253. *
  1254. */
  1255. static BOOL convertDestAddr
  1256.     (
  1257.     IDR *pIDR,                          /* ptr to i/f data record */
  1258.     SOCK *pDestSktAddr,                 /* ptr to a generic sock addr */
  1259.     char *pDestEnetAddr,                /* where to write enet addr */
  1260.     u_short *pPacketType,               /* where to write packet type */
  1261.     MBUF *pMbuf                         /* ptr to mbuf data */
  1262.     )
  1263.     {
  1264.     /***** Internet family *****/
  1265.     {
  1266.     struct in_addr destIPAddr;              /* not used */
  1267.     int trailers;                           /* not supported */
  1268.      if (pDestSktAddr->sa_family == AF_INET)
  1269.         {
  1270.         *pPacketType = ETHERTYPE_IP;            /* stuff packet type */
  1271.         destIPAddr = ((struct sockaddr_in *) pDestSktAddr)->sin_addr;
  1272.         if (!arpresolve (pIDR, pMbuf, &destIPAddr, pDestEnetAddr, &trailers))
  1273.             return (FALSE);     /* if not yet resolved */
  1274.         return (TRUE);
  1275.         }
  1276.     }
  1277.     /***** Generic family *****/
  1278.     {
  1279.     ENET_HDR *pEnetHdr;
  1280.     if (pDestSktAddr->sa_family == AF_UNSPEC)
  1281.         {
  1282.         pEnetHdr = (ENET_HDR *) pDestSktAddr->sa_data;      /* ptr to hdr */
  1283.         bcopy (pEnetHdr->dst, pDestEnetAddr, 6);            /* copy dst addr */
  1284.         *pPacketType = pEnetHdr->type;                      /* copy type */
  1285.         return (TRUE);
  1286.         }
  1287.     }
  1288.     /* Unsupported family */
  1289.     return (FALSE);
  1290.     } /* End of convertDestAddr() */
  1291. #ifdef LNISA_DEBUG
  1292. STATUS lnIsa_restart(DRV_CTRL     *pDrvCtrl)
  1293. {
  1294.     sysIntDisablePIC (pDrvCtrl->ilevel);        /* disable LANCE interrupts */
  1295.     pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);
  1296.     if (lnChipReset (pDrvCtrl) == ERROR) /* reset lance device */
  1297.      {
  1298. printf ("Unable to Reset lnIsa%dn",pDrvCtrl->idr.ac_if.if_unit);
  1299. return (ERROR);
  1300. }
  1301.     { /* Initialize all shared memory structures */
  1302.     ln_rmd  *rmd;
  1303.     ln_tmd  *tmd;
  1304.     char    *buf;
  1305.     ULONG    pTemp;
  1306.     int     loopy;
  1307.     /* Set up the Rx descriptors */
  1308.     rmd = pDrvCtrl->rring;                      /* receive ring */
  1309.     buf = pDrvCtrl->rmd_ring.r_bufs;
  1310.     for (loopy = 0; loopy < pDrvCtrl->rsize; loopy++)
  1311.     {
  1312.         pTemp = (ULONG)LN_CACHE_VIRT_TO_PHYS(buf);/* convert to physical addr */
  1313.       rmd->rbuf_adr = (USHORT)(pTemp & 0x0000ffff); /* bits 15:00 buf addr */
  1314.       rmd->rbuf_rmd1 = (USHORT)((pTemp & 0x00ff0000) >> 16); /* bits 7:0 */
  1315.       /* neg of buffer byte count */
  1316.       rmd->rbuf_bcnt = ((RMD2_BCNT_MSK & -(pDrvCtrl->bufSize)) | RMD2_MBO);
  1317.       rmd->rbuf_mcnt = 0; /* no message byte count yet */
  1318.       rmd->rbuf_rmd1 |= RMD1_OWN; /* buffer now owned by LANCE */
  1319.       rmd++; /* step to next descriptor */
  1320.       buf += (pDrvCtrl->bufSize); /* step to the next buffer */
  1321.     }
  1322.     pDrvCtrl->rindex = 0;
  1323.      /* Setup the Tx descriptors */
  1324.     tmd = pDrvCtrl->tring;                 /* transmit ring */
  1325.     buf = pDrvCtrl->tmd_ring.t_bufs;
  1326.     for (loopy = 0; loopy < pDrvCtrl->tsize; loopy++)
  1327.     {
  1328.       pTemp = (ULONG)LN_CACHE_VIRT_TO_PHYS(buf); /* convert to physical addr */
  1329.       tmd->tbuf_adr = (USHORT) (pTemp & 0x0000ffff); /* bits 15:00 of addr */
  1330.       tmd->tbuf_tmd1 = (USHORT)((pTemp & 0x00ff0000) >> 16); /* bits 7:0 */
  1331.       tmd->tbuf_tmd2 = 0; /* no length of Tx Buf yet */
  1332.       tmd->tbuf_tmd3 = 0; /* clear status bits */
  1333.       tmd->tbuf_tmd1 |= TMD1_ENP; /* buffer is end of packet */
  1334.       tmd->tbuf_tmd1 |= TMD1_STP; /* buffer is start of packet */
  1335.       tmd++; /* step to next descriptor */
  1336.       buf += (pDrvCtrl->bufSize); /* step to next buffer */
  1337.     }
  1338.     pDrvCtrl->tindex = pDrvCtrl->dindex = 0;
  1339.     /* Flush the write pipe */
  1340.     CACHE_PIPE_FLUSH ();
  1341.     }
  1342.     { /* Start the device */
  1343.     USHORT stat = 0;
  1344.     ULONG pTemp;
  1345.     int timeoutCount = 0;
  1346.     lnCsrWrite (pDrvCtrl, 0, CSR0_STOP); /* set the stop bit */
  1347.     /* Point the device to the initialization block */
  1348.     pTemp = (ULONG)LN_CACHE_VIRT_TO_PHYS ( pDrvCtrl->ib );
  1349.     lnCsrWrite (pDrvCtrl, 2, (USHORT)((pTemp >> 16) & 0x000000ff));
  1350.     lnCsrWrite (pDrvCtrl, 1, (USHORT)(pTemp & 0x0000ffff));
  1351.     lnCsrWrite (pDrvCtrl, 0, CSR0_INIT);            /* init chip (read IB) */
  1352.     while (((stat = lnCsrRead (pDrvCtrl, 0)) & (CSR0_IDON | CSR0_ERR)) == 0)
  1353.         {
  1354.         if (timeoutCount++ > 5) 
  1355.   break;
  1356.         taskDelay(sysClkRateGet());
  1357.         }
  1358.     if ((stat & CSR0_ERR) == CSR0_ERR)
  1359. {
  1360. if ((stat & CSR0_MERR)  == CSR0_MERR)
  1361.     {
  1362.     printf ("Lance Memory error during initialization:t0x%xn",
  1363.     stat);
  1364.     }
  1365. else
  1366.     {
  1367.     printf ("Lance Error during initialization:t0x%xn",
  1368.     stat);
  1369.     }
  1370. }
  1371.     /* log chip initialization failure */
  1372.     if ( (stat & CSR0_ERR) || (timeoutCount >= 0x10000) )
  1373.         {
  1374.         printf ("lnIsa%d: Device initialization failedn",
  1375.                     pDrvCtrl->idr.ac_if.if_unit);
  1376.         return (ERROR);
  1377.         }
  1378.     /* Device is initialized.  Start transmitter and receiver.  The device
  1379.      * RAP register is left selecting CSR 0.
  1380.      */
  1381.     lnCsrWrite(pDrvCtrl, 0, CSR0_IDON | CSR0_IENA | CSR0_STRT);
  1382.     sysIntEnablePIC (pDrvCtrl->ilevel);         /* enable LANCE interrupts */
  1383.     pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);
  1384.     } /* Block end; device initialization */
  1385.     return (OK);
  1386. }
  1387. #endif /* LNISA_DEBUG */
  1388. BOOL outHook (struct ifnet *pIf,char *buf,int len)
  1389. {
  1390.   UINT8 *myHdr = (UINT8 *)buf;
  1391.   printf("nSending Packet:n");
  1392.   printf("Dest: %02x:%02x:%02x:%02x:%02x:%02xn",myHdr[0],myHdr[1],
  1393.  myHdr[2],myHdr[3],myHdr[4],myHdr[5]);
  1394.   printf("Src : %02x:%02x:%02x:%02x:%02x:%02xn",myHdr[6],myHdr[7],
  1395.  myHdr[8],myHdr[9],myHdr[10],myHdr[11]);
  1396.   printf("len = %dn",len);
  1397.   printf("Data at %pn",buf);
  1398.   return FALSE;
  1399. }
  1400. BOOL inHook (struct ifnet *pIf,char *buf,int len)
  1401. {
  1402.   UINT8 *myHdr = (UINT8 *)buf;
  1403.   printf("nGot Packet:n");
  1404.   printf("Dest: %02x:%02x:%02x:%02x:%02x:%02xn",myHdr[0],myHdr[1],
  1405.  myHdr[2],myHdr[3],myHdr[4],myHdr[5]);
  1406.   printf("Src : %02x:%02x:%02x:%02x:%02x:%02xn",myHdr[6],myHdr[7],
  1407.  myHdr[8],myHdr[9],myHdr[10],myHdr[11]);
  1408.   printf("len = %dn",len);
  1409.   printf("Data at %pn",buf);
  1410.   return FALSE;
  1411. }
  1412. /* END OF FILE */